Created
May 1, 2010 21:21
-
-
Save notmasteryet/386668 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff -r 0efb08f1b29a content/base/src/nsContentUtils.cpp | |
--- a/content/base/src/nsContentUtils.cpp Sat May 01 14:02:03 2010 +0200 | |
+++ b/content/base/src/nsContentUtils.cpp Sat May 01 16:19:35 2010 -0500 | |
@@ -563,6 +563,7 @@ | |
{ &nsGkAtoms::onratechange, { NS_RATECHANGE, EventNameType_HTML }}, | |
{ &nsGkAtoms::ondurationchange, { NS_DURATIONCHANGE, EventNameType_HTML }}, | |
{ &nsGkAtoms::onvolumechange, { NS_VOLUMECHANGE, EventNameType_HTML }}, | |
+ { &nsGkAtoms::onaudiowritten, { NS_AUDIOWRITTEN, EventNameType_HTML }}, | |
#endif //MOZ_MEDIA | |
{ &nsGkAtoms::onMozAfterPaint, { NS_AFTERPAINT, EventNameType_None }}, | |
{ &nsGkAtoms::onMozScrolledAreaChanged, { NS_SCROLLEDAREACHANGED, EventNameType_None }}, | |
diff -r 0efb08f1b29a content/base/src/nsGkAtomList.h | |
--- a/content/base/src/nsGkAtomList.h Sat May 01 14:02:03 2010 +0200 | |
+++ b/content/base/src/nsGkAtomList.h Sat May 01 16:19:35 2010 -0500 | |
@@ -1652,6 +1652,8 @@ | |
GK_ATOM(ratechange, "ratechange") | |
GK_ATOM(durationchange, "durationchange") | |
GK_ATOM(volumechange, "volumechange") | |
+GK_ATOM(onaudiowritten, "onaudiowritten") | |
+GK_ATOM(audiowritten, "audiowritten") | |
#endif | |
// Content property names | |
diff -r 0efb08f1b29a content/events/public/nsIPrivateDOMEvent.h | |
--- a/content/events/public/nsIPrivateDOMEvent.h Sat May 01 14:02:03 2010 +0200 | |
+++ b/content/events/public/nsIPrivateDOMEvent.h Sat May 01 16:19:35 2010 -0500 | |
@@ -50,6 +50,7 @@ | |
class nsCommandEvent; | |
class nsPresContext; | |
class nsInvalidateRequestList; | |
+class nsIDOMAudioData; | |
class nsIPrivateDOMEvent : public nsISupports | |
{ | |
@@ -111,6 +112,14 @@ | |
nsEvent* aEvent, | |
PRUint32 aEventType = 0, | |
nsInvalidateRequestList* aInvalidateRequests = nsnull); | |
+ | |
+nsresult | |
+NS_NewDOMAudioWrittenEvent(nsIDOMEvent** aResult, nsPresContext* aPresContext, | |
+ nsEvent* aEvent, | |
+ PRUint32 aEventType = 0, | |
+ nsIDOMAudioData* aFrameBuffer = nsnull, | |
+ nsIDOMAudioData* aSpectrum = nsnull); | |
+ | |
nsresult | |
NS_NewDOMSimpleGestureEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, class nsSimpleGestureEvent* aEvent); | |
nsresult | |
diff -r 0efb08f1b29a content/events/src/Makefile.in | |
--- a/content/events/src/Makefile.in Sat May 01 14:02:03 2010 +0200 | |
+++ b/content/events/src/Makefile.in Sat May 01 16:19:35 2010 -0500 | |
@@ -78,6 +78,8 @@ | |
nsDOMProgressEvent.cpp \ | |
nsDOMDataTransfer.cpp \ | |
nsDOMNotifyPaintEvent.cpp \ | |
+ nsDOMNotifyAudioWrittenEvent.cpp \ | |
+ nsDOMAudioData.cpp \ | |
nsDOMSimpleGestureEvent.cpp \ | |
nsDOMEventTargetHelper.cpp \ | |
nsDOMScrollAreaEvent.cpp \ | |
diff -r 0efb08f1b29a content/events/src/nsDOMAudioData.cpp | |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 | |
+++ b/content/events/src/nsDOMAudioData.cpp Sat May 01 16:19:35 2010 -0500 | |
@@ -0,0 +1,36 @@ | |
+#include "nsDOMAudioData.h" | |
+#include "nsCOMPtr.h" | |
+#include "nsContentUtils.h" | |
+ | |
+DOMCI_DATA(AudioData, nsDOMAudioData) | |
+ | |
+NS_INTERFACE_TABLE_HEAD(nsDOMAudioData) | |
+ NS_INTERFACE_TABLE1(nsDOMAudioData, nsIDOMAudioData) | |
+ NS_INTERFACE_TABLE_TO_MAP_SEGUE | |
+ NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(AudioData) | |
+NS_INTERFACE_MAP_END | |
+ | |
+NS_IMPL_ADDREF(nsDOMAudioData) | |
+NS_IMPL_RELEASE(nsDOMAudioData) | |
+ | |
+ | |
+nsDOMAudioData::nsDOMAudioData(nsTArray<float>& aData) | |
+{ | |
+ mData.SwapElements(aData); | |
+} | |
+ | |
+nsDOMAudioData::~nsDOMAudioData() | |
+{ | |
+} | |
+ | |
+NS_IMETHODIMP nsDOMAudioData::GetLength(PRUint32 *aLength) | |
+{ | |
+ *aLength = mData.Length(); | |
+ return NS_OK; | |
+} | |
+ | |
+NS_IMETHODIMP nsDOMAudioData::Item(PRUint32 aIndex, float *retval NS_OUTPARAM) | |
+{ | |
+ *retval = GetItemAt(aIndex); | |
+ return NS_OK; | |
+} | |
diff -r 0efb08f1b29a content/events/src/nsDOMAudioData.h | |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 | |
+++ b/content/events/src/nsDOMAudioData.h Sat May 01 16:19:35 2010 -0500 | |
@@ -0,0 +1,24 @@ | |
+#include "nsIDOMNotifyAudioWrittenEvent.h" | |
+#include "nsTArray.h" | |
+ | |
+class nsDOMAudioData : public nsIDOMAudioData | |
+{ | |
+public: | |
+ NS_DECL_ISUPPORTS | |
+ NS_DECL_NSIDOMAUDIODATA | |
+ | |
+ nsDOMAudioData(nsTArray<float>& aData); | |
+ | |
+ void Append(float aElement) { mData.AppendElement(aElement); } | |
+ | |
+ float GetItemAt(PRUint32 aIndex) | |
+ { | |
+ return mData[aIndex]; | |
+ } | |
+ | |
+private: | |
+ ~nsDOMAudioData(); | |
+ | |
+protected: | |
+ nsTArray<float> mData; | |
+}; | |
diff -r 0efb08f1b29a content/events/src/nsDOMEvent.cpp | |
--- a/content/events/src/nsDOMEvent.cpp Sat May 01 14:02:03 2010 +0200 | |
+++ b/content/events/src/nsDOMEvent.cpp Sat May 01 16:19:35 2010 -0500 | |
@@ -80,7 +80,7 @@ | |
"loadstart", "progress", "suspend", "emptied", "stalled", "play", "pause", | |
"loadedmetadata", "loadeddata", "waiting", "playing", "canplay", | |
"canplaythrough", "seeking", "seeked", "timeupdate", "ended", "ratechange", | |
- "durationchange", "volumechange", | |
+ "durationchange", "volumechange", "audiowritten", | |
#endif // MOZ_MEDIA | |
"MozAfterPaint", | |
"MozSwipeGesture", | |
@@ -683,6 +683,8 @@ | |
mEvent->message = NS_MEDIA_ABORT; | |
else if (atom == nsGkAtoms::onerror) | |
mEvent->message = NS_MEDIA_ERROR; | |
+ else if (atom == nsGkAtoms::onaudiowritten) | |
+ mEvent->message = NS_AUDIOWRITTEN; | |
} | |
#endif // MOZ_MEDIA | |
else if (mEvent->eventStructType == NS_SIMPLE_GESTURE_EVENT) { | |
@@ -1493,6 +1495,8 @@ | |
return sEventNames[eDOMEvents_durationchange]; | |
case NS_VOLUMECHANGE: | |
return sEventNames[eDOMEvents_volumechange]; | |
+ case NS_AUDIOWRITTEN: | |
+ return sEventNames[eDOMEvents_audiowritten]; | |
#endif | |
case NS_AFTERPAINT: | |
return sEventNames[eDOMEvents_afterpaint]; | |
diff -r 0efb08f1b29a content/events/src/nsDOMEvent.h | |
--- a/content/events/src/nsDOMEvent.h Sat May 01 14:02:03 2010 +0200 | |
+++ b/content/events/src/nsDOMEvent.h Sat May 01 16:19:35 2010 -0500 | |
@@ -161,6 +161,7 @@ | |
eDOMEvents_ratechange, | |
eDOMEvents_durationchange, | |
eDOMEvents_volumechange, | |
+ eDOMEvents_audiowritten, | |
#endif | |
eDOMEvents_afterpaint, | |
eDOMEvents_MozSwipeGesture, | |
diff -r 0efb08f1b29a content/events/src/nsDOMNotifyAudioWrittenEvent.cpp | |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 | |
+++ b/content/events/src/nsDOMNotifyAudioWrittenEvent.cpp Sat May 01 16:19:35 2010 -0500 | |
@@ -0,0 +1,70 @@ | |
+#include "nsDOMNotifyAudioWrittenEvent.h" | |
+#include "nsDOMAudioData.h" | |
+ | |
+nsDOMNotifyAudioWrittenEvent::nsDOMNotifyAudioWrittenEvent(nsPresContext* aPresContext, nsEvent* aEvent, | |
+ PRUint32 aEventType, nsIDOMAudioData* aFrameBuffer, | |
+ nsIDOMAudioData* aSpectrum) | |
+ : nsDOMEvent(aPresContext, aEvent) | |
+{ | |
+ if (mEvent) { | |
+ mEvent->message = aEventType; | |
+ } | |
+ mFrameBuffer = aFrameBuffer; | |
+ mSpectrum = aSpectrum; | |
+} | |
+ | |
+DOMCI_DATA(NotifyAudioWrittenEvent, nsDOMNotifyAudioWrittenEvent) | |
+ | |
+NS_INTERFACE_MAP_BEGIN(nsDOMNotifyAudioWrittenEvent) | |
+ NS_INTERFACE_MAP_ENTRY(nsIDOMNotifyAudioWrittenEvent) | |
+ NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(NotifyAudioWrittenEvent) | |
+NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent) | |
+ | |
+NS_IMPL_ADDREF_INHERITED(nsDOMNotifyAudioWrittenEvent, nsDOMEvent) | |
+NS_IMPL_RELEASE_INHERITED(nsDOMNotifyAudioWrittenEvent, nsDOMEvent) | |
+ | |
+nsDOMNotifyAudioWrittenEvent::~nsDOMNotifyAudioWrittenEvent() | |
+{ | |
+} | |
+ | |
+NS_IMETHODIMP nsDOMNotifyAudioWrittenEvent::GetMozFrameBuffer(nsIDOMAudioData * *aResult) | |
+{ | |
+ NS_IF_ADDREF(*aResult = mFrameBuffer); | |
+ return NS_OK; | |
+} | |
+ | |
+NS_IMETHODIMP nsDOMNotifyAudioWrittenEvent::GetMozSpectrum(nsIDOMAudioData * *aResult) | |
+{ | |
+ NS_IF_ADDREF(*aResult = mSpectrum); | |
+ return NS_OK; | |
+} | |
+ | |
+NS_IMETHODIMP | |
+nsDOMNotifyAudioWrittenEvent::InitAudioWrittenEvent(const nsAString& aType, | |
+ PRBool aCanBubble, | |
+ PRBool aCancelable, | |
+ nsIDOMAudioData* aFrameBuffer, | |
+ nsIDOMAudioData* aSpectrum) | |
+{ | |
+ nsresult rv = nsDOMEvent::InitEvent(aType, aCanBubble, aCancelable); | |
+ NS_ENSURE_SUCCESS(rv, rv); | |
+ | |
+ mFrameBuffer = aFrameBuffer; | |
+ mSpectrum = aSpectrum; | |
+ return NS_OK; | |
+} | |
+ | |
+nsresult NS_NewDOMAudioWrittenEvent(nsIDOMEvent** aInstancePtrResult, | |
+ nsPresContext* aPresContext, | |
+ nsEvent *aEvent, | |
+ PRUint32 aEventType, | |
+ nsIDOMAudioData* aFrameBuffer, | |
+ nsIDOMAudioData* aSpectrum) | |
+{ | |
+ nsDOMNotifyAudioWrittenEvent* it = new nsDOMNotifyAudioWrittenEvent(aPresContext, aEvent, aEventType, aFrameBuffer, aSpectrum); | |
+ if (nsnull == it) { | |
+ return NS_ERROR_OUT_OF_MEMORY; | |
+ } | |
+ | |
+ return CallQueryInterface(it, aInstancePtrResult); | |
+} | |
diff -r 0efb08f1b29a content/events/src/nsDOMNotifyAudioWrittenEvent.h | |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 | |
+++ b/content/events/src/nsDOMNotifyAudioWrittenEvent.h Sat May 01 16:19:35 2010 -0500 | |
@@ -0,0 +1,35 @@ | |
+#ifndef nsDOMNotifyAudioWrittenEvent_h_ | |
+#define nsDOMNotifyAudioWrittenEvent_h_ | |
+ | |
+#include "nsIDOMNotifyAudioWrittenEvent.h" | |
+#include "nsDOMEvent.h" | |
+#include "nsPresContext.h" | |
+ | |
+class nsDOMNotifyAudioWrittenEvent : public nsDOMEvent, | |
+ public nsIDOMNotifyAudioWrittenEvent | |
+{ | |
+public: | |
+ nsDOMNotifyAudioWrittenEvent(nsPresContext* aPresContext, nsEvent* aEvent, | |
+ PRUint32 aEventType, nsIDOMAudioData* aFrameBuffer, | |
+ nsIDOMAudioData* aSpectrum); | |
+ | |
+ NS_DECL_ISUPPORTS_INHERITED | |
+ NS_DECL_NSIDOMNOTIFYAUDIOWRITTENEVENT | |
+ | |
+ // Forward to base class | |
+ NS_FORWARD_TO_NSDOMEVENT | |
+ | |
+nsresult NS_NewDOMAudioWrittenEvent(nsIDOMEvent** aInstancePtrResult, | |
+ nsPresContext* aPresContext, | |
+ nsEvent *aEvent, | |
+ PRUint32 aEventType, | |
+ nsIDOMAudioData* aFrameBuffer, | |
+ nsIDOMAudioData* aSpectrum); | |
+ | |
+private: | |
+ ~nsDOMNotifyAudioWrittenEvent(); | |
+ nsCOMPtr<nsIDOMAudioData> mFrameBuffer; | |
+ nsCOMPtr<nsIDOMAudioData> mSpectrum; | |
+}; | |
+ | |
+#endif // nsDOMNotifyAudioWrittenEvent_h_ | |
diff -r 0efb08f1b29a content/events/src/nsEventDispatcher.cpp | |
--- a/content/events/src/nsEventDispatcher.cpp Sat May 01 14:02:03 2010 +0200 | |
+++ b/content/events/src/nsEventDispatcher.cpp Sat May 01 16:19:35 2010 -0500 | |
@@ -820,12 +820,12 @@ | |
return NS_NewDOMPageTransitionEvent(aDOMEvent, aPresContext, nsnull); | |
if (aEventType.LowerCaseEqualsLiteral("scrollareaevent")) | |
return NS_NewDOMScrollAreaEvent(aDOMEvent, aPresContext, nsnull); | |
- // FIXME: Should get spec to say what the right string is here! This | |
- // is probably wrong! | |
if (aEventType.LowerCaseEqualsLiteral("transitionevent")) | |
return NS_NewDOMTransitionEvent(aDOMEvent, aPresContext, nsnull); | |
if (aEventType.LowerCaseEqualsLiteral("popstateevent")) | |
return NS_NewDOMPopStateEvent(aDOMEvent, aPresContext, nsnull); | |
+ if (aEventType.LowerCaseEqualsLiteral("audiowrittenevent")) | |
+ return NS_NewDOMAudioWrittenEvent(aDOMEvent, aPresContext, nsnull); | |
return NS_ERROR_DOM_NOT_SUPPORTED_ERR; | |
} | |
diff -r 0efb08f1b29a content/html/content/public/nsHTMLMediaElement.h | |
--- a/content/html/content/public/nsHTMLMediaElement.h Sat May 01 14:02:03 2010 +0200 | |
+++ b/content/html/content/public/nsHTMLMediaElement.h Sat May 01 16:19:35 2010 -0500 | |
@@ -49,6 +49,8 @@ | |
#include "nsIObserver.h" | |
#include "ImageLayers.h" | |
+#include "nsAudioStream.h" | |
+ | |
// Define to output information on decoding and painting framerate | |
/* #define DEBUG_FRAME_RATE 1 */ | |
@@ -178,6 +180,7 @@ | |
nsresult DispatchProgressEvent(const nsAString& aName); | |
nsresult DispatchAsyncSimpleEvent(const nsAString& aName); | |
nsresult DispatchAsyncProgressEvent(const nsAString& aName); | |
+ nsresult DispatchAudioWrittenEvent(nsTArray<float>& aFrameBuffer, nsTArray<float>& aSpectrum); | |
// Called by the decoder when some data has been downloaded or | |
// buffering/seeking has ended. aNextFrameAvailable is true when | |
@@ -260,6 +263,11 @@ | |
*/ | |
void NotifyLoadError(); | |
+ /** | |
+ * Called when data has been written to the underlying audio stream. | |
+ */ | |
+ void NotifyAudioWritten(nsTArray<float>& aFrameBuffer, nsTArray<float>& aSpectrum); | |
+ | |
virtual PRBool IsNodeOfType(PRUint32 aFlags) const; | |
/** | |
@@ -401,10 +409,17 @@ | |
nsRefPtr<nsMediaDecoder> mDecoder; | |
+ // XXX: just a hack to get an audio stream we can write to without an ogg/wave source. | |
+ nsAutoPtr<nsAudioStream> mAudioStream; | |
+ | |
// A reference to the ImageContainer which contains the current frame | |
// of video to display. | |
nsRefPtr<ImageContainer> mImageContainer; | |
+ // XXX: just a hack to keep track of channels and rate info | |
+ PRUint32 mChannels; | |
+ PRUint32 mRate; | |
+ | |
// Holds a reference to the first channel we open to the media resource. | |
// Once the decoder is created, control over the channel passes to the | |
// decoder, and we null out this reference. We must store this in case | |
diff -r 0efb08f1b29a content/html/content/src/nsHTMLMediaElement.cpp | |
--- a/content/html/content/src/nsHTMLMediaElement.cpp Sat May 01 14:02:03 2010 +0200 | |
+++ b/content/html/content/src/nsHTMLMediaElement.cpp Sat May 01 16:19:35 2010 -0500 | |
@@ -87,6 +87,11 @@ | |
#include <limits> | |
#include "nsIDocShellTreeItem.h" | |
+#include "nsEventDispatcher.h" | |
+#include "nsIPrivateDOMEvent.h" | |
+#include "nsIDOMNotifyAudioWrittenEvent.h" | |
+#include "nsDOMAudioData.h" | |
+ | |
#ifdef MOZ_OGG | |
#include "nsOggDecoder.h" | |
#endif | |
@@ -159,9 +164,17 @@ | |
nsMediaEvent(nsHTMLMediaElement* aElement) : | |
mElement(aElement), | |
mLoadID(mElement->GetCurrentLoadID()) {} | |
+ nsMediaEvent(nsHTMLMediaElement* aElement, nsTArray<float>& aFrameBuffer, nsTArray<float>& aSpectrum) : | |
+ mElement(aElement), | |
+ mLoadID(mElement->GetCurrentLoadID()) { | |
+ mFrameBuffer.SwapElements(aFrameBuffer); | |
+ mSpectrum.SwapElements(aSpectrum); | |
+ } | |
~nsMediaEvent() {} | |
NS_IMETHOD Run() = 0; | |
+ nsTArray<float> mFrameBuffer; | |
+ nsTArray<float> mSpectrum; | |
protected: | |
PRBool IsCancelled() { | |
@@ -183,14 +196,22 @@ | |
nsMediaEvent(aElement), mName(aName), mProgress(aProgress) | |
{ | |
} | |
+ nsAsyncEventRunner(const nsAString& aName, nsHTMLMediaElement* aElement, PRBool aProgress, nsTArray<float>& aFrameBuffer, nsTArray<float>& aSpectrum) : | |
+ nsMediaEvent(aElement, aFrameBuffer, aSpectrum), mName(aName), mProgress(aProgress) | |
+ { | |
+ } | |
NS_IMETHOD Run() { | |
// Silently cancel if our load has been cancelled. | |
if (IsCancelled()) | |
return NS_OK; | |
- return mProgress ? | |
- mElement->DispatchProgressEvent(mName) : | |
- mElement->DispatchSimpleEvent(mName); | |
+ | |
+ if (mFrameBuffer.Length() > 0) | |
+ return mElement->DispatchAudioWrittenEvent(mFrameBuffer, mSpectrum); | |
+ else | |
+ return mProgress ? | |
+ mElement->DispatchProgressEvent(mName) : | |
+ mElement->DispatchSimpleEvent(mName); | |
} | |
}; | |
@@ -609,6 +630,17 @@ | |
} | |
} | |
+void nsHTMLMediaElement::NotifyAudioWritten(nsTArray<float>& aFrameBuffer, nsTArray<float>& aSpectrum) | |
+{ | |
+// DispatchAsyncSimpleEvent(NS_LITERAL_STRING("audiowritten")); | |
+// LOG_EVENT(PR_LOG_DEBUG, ("%p Queuing simple event %s", this, NS_LITERAL_STRING("audiowritten").get())); | |
+ | |
+ // XXX: do I need to dispatch to main thread agian? | |
+ nsCOMPtr<nsIRunnable> event = | |
+ new nsAsyncEventRunner(NS_LITERAL_STRING("audiowritten"), this, PR_FALSE, aFrameBuffer, aSpectrum); | |
+ NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); | |
+} | |
+ | |
void nsHTMLMediaElement::LoadFromSourceChildren() | |
{ | |
NS_ASSERTION(mDelayingLoadEvent, | |
@@ -791,6 +823,55 @@ | |
return NS_OK; | |
} | |
+NS_IMETHODIMP nsHTMLMediaElement::MozSetup(PRUint32 aChannels, PRUint32 aRate, float aVolume) | |
+{ | |
+ mAudioStream = new nsAudioStream(); | |
+ mAudioStream->Init(aChannels, aRate, nsAudioStream::FORMAT_FLOAT32); | |
+ // So we don't crash, in case Init doesn't work (params were wrong)... | |
+ if (mAudioStream) { | |
+ mChannels = aChannels; | |
+ mRate = aRate; | |
+ mAudioStream->SetVolume(aVolume); | |
+ return NS_OK; | |
+ } else | |
+ return NS_ERROR_FAILURE; | |
+} | |
+ | |
+NS_IMETHODIMP nsHTMLMediaElement::MozWriteAudio(PRUint32 count, float *valueArray, PRUint32 *_retval NS_OUTPARAM) | |
+{ | |
+ *_retval = 0; | |
+ if (mAudioStream) { | |
+ // Make sure that we are going to write the correct amount of data based on number of channels | |
+ if (count % mChannels != 0) | |
+ return NS_ERROR_FAILURE; | |
+ else { | |
+ *_retval = mAudioStream->Write(valueArray, count, PR_FALSE); | |
+ return NS_OK; | |
+ } | |
+ } else | |
+ return NS_ERROR_FAILURE; | |
+} | |
+ | |
+NS_IMETHODIMP nsHTMLMediaElement::MozAvailable(PRUint32 *_retval NS_OUTPARAM) | |
+{ | |
+ if (mAudioStream) | |
+ *_retval = mAudioStream->Available(); | |
+ else | |
+ *_retval = 0; | |
+ | |
+ return NS_OK; | |
+} | |
+ | |
+NS_IMETHODIMP nsHTMLMediaElement::MozCurrentSample(PRUint32 *_retval NS_OUTPARAM) | |
+{ | |
+ if (mAudioStream) | |
+ *_retval = (PRUint32)mAudioStream->GetSamplePosition(); | |
+ else | |
+ *_retval = 0.0; | |
+ | |
+ return NS_OK; | |
+} | |
+ | |
/* readonly attribute unsigned short readyState; */ | |
NS_IMETHODIMP nsHTMLMediaElement::GetReadyState(PRUint16 *aReadyState) | |
{ | |
@@ -969,7 +1050,9 @@ | |
mAllowSuspendAfterFirstFrame(PR_TRUE), | |
mHasPlayedOrSeeked(PR_FALSE), | |
mHasSelfReference(PR_FALSE), | |
- mShuttingDown(PR_FALSE) | |
+ mShuttingDown(PR_FALSE), | |
+ mChannels(0), | |
+ mRate(0) | |
{ | |
#ifdef PR_LOGGING | |
if (!gMediaElementLog) { | |
@@ -1854,11 +1937,33 @@ | |
return mImageContainer; | |
} | |
+nsresult nsHTMLMediaElement::DispatchAudioWrittenEvent(nsTArray<float>& aFrameBuffer, nsTArray<float>& aSpectrum) | |
+{ | |
+ nsCOMPtr<nsIDOMDocumentEvent> docEvent(do_QueryInterface(GetOwnerDoc())); | |
+ nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(static_cast<nsIContent*>(this))); | |
+ nsCOMPtr<nsIDOMEvent> event; | |
+ | |
+ docEvent->CreateEvent(NS_LITERAL_STRING("AudioWrittenEvent"), getter_AddRefs(event)); | |
+ nsCOMPtr<nsIDOMNotifyAudioWrittenEvent> audioWrittenEvent(do_QueryInterface(event)); | |
+ | |
+ nsRefPtr<nsDOMAudioData> frameBufferData = new nsDOMAudioData(aFrameBuffer); | |
+ if (!frameBufferData) | |
+ return NS_ERROR_OUT_OF_MEMORY; | |
+ | |
+ nsRefPtr<nsDOMAudioData> spectrumData = new nsDOMAudioData(aSpectrum); | |
+ if (!spectrumData) | |
+ return NS_ERROR_OUT_OF_MEMORY; | |
+ | |
+ audioWrittenEvent->InitAudioWrittenEvent(NS_LITERAL_STRING("audiowritten"), PR_TRUE, PR_TRUE, frameBufferData, spectrumData); | |
+ | |
+ PRBool dummy; | |
+ return target->DispatchEvent(event, &dummy); | |
+} | |
+ | |
nsresult nsHTMLMediaElement::DispatchSimpleEvent(const nsAString& aName) | |
{ | |
LOG_EVENT(PR_LOG_DEBUG, ("%p Dispatching simple event %s", this, | |
NS_ConvertUTF16toUTF8(aName).get())); | |
- | |
return nsContentUtils::DispatchTrustedEvent(GetOwnerDoc(), | |
static_cast<nsIContent*>(this), | |
aName, | |
diff -r 0efb08f1b29a content/media/nsAudioStream.cpp | |
--- a/content/media/nsAudioStream.cpp Sat May 01 14:02:03 2010 +0200 | |
+++ b/content/media/nsAudioStream.cpp Sat May 01 16:19:35 2010 -0500 | |
@@ -45,9 +45,10 @@ | |
extern "C" { | |
#include "sydneyaudio/sydney_audio.h" | |
} | |
-#include "mozilla/TimeStamp.h" | |
-using mozilla::TimeStamp; | |
+//#include "mozilla/TimeStamp.h" | |
+// | |
+//using mozilla::TimeStamp; | |
#ifdef PR_LOGGING | |
PRLogModuleInfo* gAudioStreamLog = nsnull; | |
@@ -114,7 +115,13 @@ | |
mAudioHandle = nsnull; | |
} | |
-void nsAudioStream::Write(const void* aBuf, PRUint32 aCount, PRBool aBlocking) | |
+void nsAudioStream::Write(const void* aBuf, PRUint32 aCount) | |
+{ | |
+ // ignore return value for existing callers. | |
+ Write(aBuf, aCount, PR_TRUE); | |
+} | |
+ | |
+PRUint32 nsAudioStream::Write(const void* aBuf, PRUint32 aCount, PRBool aBlocking) | |
{ | |
NS_ABORT_IF_FALSE(aCount % mChannels == 0, | |
"Buffer size must be divisible by channel count"); | |
@@ -124,10 +131,12 @@ | |
PRUint32 count = aCount + offset; | |
if (!mAudioHandle) | |
- return; | |
+ return 0; | |
nsAutoArrayPtr<short> s_data(new short[count]); | |
+ PRUint32 buffered = 0; | |
+ | |
if (s_data) { | |
for (PRUint32 i=0; i < offset; ++i) { | |
s_data[i] = mBufferOverflow.ElementAt(i); | |
@@ -180,6 +189,7 @@ | |
PRUint32 available = Available(); | |
if (available < count) { | |
mBufferOverflow.AppendElements(s_data.get() + available, (count - available)); | |
+ buffered = mBufferOverflow.Length(); | |
count = available; | |
} | |
} | |
@@ -192,6 +202,7 @@ | |
Shutdown(); | |
} | |
} | |
+ return buffered; | |
} | |
PRUint32 nsAudioStream::Available() | |
@@ -268,3 +279,20 @@ | |
return -1; | |
} | |
+PRInt64 nsAudioStream::GetSamplePosition() | |
+{ | |
+ if (!mAudioHandle) | |
+ return -1; | |
+ | |
+ sa_position_t positionType = SA_POSITION_WRITE_SOFTWARE; | |
+#if defined(XP_WIN) | |
+ positionType = SA_POSITION_WRITE_HARDWARE; | |
+#endif | |
+ PRInt64 position = 0; | |
+ if (sa_stream_get_position(static_cast<sa_stream_t*>(mAudioHandle), | |
+ positionType, &position) == SA_SUCCESS) { | |
+ return (position / mChannels / sizeof(short)); | |
+ } | |
+ | |
+ return 0; | |
+} | |
diff -r 0efb08f1b29a content/media/nsAudioStream.h | |
--- a/content/media/nsAudioStream.h Sat May 01 14:02:03 2010 +0200 | |
+++ b/content/media/nsAudioStream.h Sat May 01 16:19:35 2010 -0500 | |
@@ -79,7 +79,9 @@ | |
// When aBlocking is PR_TRUE, we'll block until the write has completed, | |
// otherwise we'll buffer any data we can't write immediately, and write | |
// it in a later call. | |
- void Write(const void* aBuf, PRUint32 aCount, PRBool aBlocking); | |
+ | |
+ PRUint32 Write(const void* aBuf, PRUint32 aCount, PRBool aBlocking); | |
+ void Write(const void* aBuf, PRUint32 aCount); // just to support callers in this old rev... | |
// Return the number of sound samples that can be written to the audio device | |
// without blocking. | |
@@ -102,6 +104,8 @@ | |
// audio hardware. | |
PRInt64 GetPosition(); | |
+ PRInt64 GetSamplePosition(); | |
+ | |
// Returns PR_TRUE when the audio stream is paused. | |
PRBool IsPaused() { return mPaused; } | |
diff -r 0efb08f1b29a content/media/nsBuiltinDecoder.cpp | |
--- a/content/media/nsBuiltinDecoder.cpp Sat May 01 14:02:03 2010 +0200 | |
+++ b/content/media/nsBuiltinDecoder.cpp Sat May 01 16:19:35 2010 -0500 | |
@@ -51,6 +51,9 @@ | |
using mozilla::MonitorAutoEnter; | |
using mozilla::MonitorAutoExit; | |
+using mozilla::TimeDuration; | |
+using mozilla::TimeStamp; | |
+ | |
#ifdef PR_LOGGING | |
PRLogModuleInfo* gBuiltinDecoderLog; | |
#define LOG(type, msg) PR_LOG(gBuiltinDecoderLog, type, msg) | |
@@ -72,6 +75,12 @@ | |
ChangeState(PLAY_STATE_PAUSED); | |
} | |
+void nsBuiltinDecoder::Write(PRUint32 count, float *valueArray) | |
+{ | |
+ if (mDecoderStateMachine) | |
+ mDecoderStateMachine->Write(count, valueArray); | |
+} | |
+ | |
void nsBuiltinDecoder::SetVolume(float volume) | |
{ | |
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); | |
@@ -293,6 +302,14 @@ | |
return mStream ? mStream->GetCurrentPrincipal() : nsnull; | |
} | |
+void nsBuiltinDecoder::AudioWritten(nsTArray<float>& aFrameBuffer, nsTArray<float>& aSpectrum) | |
+{ | |
+ if (mShuttingDown) | |
+ return; | |
+ | |
+ mElement->NotifyAudioWritten(aFrameBuffer, aSpectrum); | |
+} | |
+ | |
void nsBuiltinDecoder::MetadataLoaded() | |
{ | |
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); | |
diff -r 0efb08f1b29a content/media/nsBuiltinDecoder.h | |
--- a/content/media/nsBuiltinDecoder.h Sat May 01 14:02:03 2010 +0200 | |
+++ b/content/media/nsBuiltinDecoder.h Sat May 01 16:19:35 2010 -0500 | |
@@ -204,6 +204,9 @@ | |
// Called from the main thread to set whether the media resource can | |
// be seeked. The decoder monitor must be obtained before calling this. | |
virtual void SetSeekable(PRBool aSeekable) = 0; | |
+ | |
+ // Writes some data | |
+ virtual void Write(PRUint32 count, float *valueArray) = 0; | |
}; | |
class nsBuiltinDecoder : public nsMediaDecoder | |
@@ -255,6 +258,8 @@ | |
virtual void SetVolume(float volume); | |
virtual float GetDuration(); | |
+ virtual void Write(PRUint32 count, float *valueArray); | |
+ | |
virtual nsMediaStream* GetCurrentStream(); | |
virtual already_AddRefed<nsIPrincipal> GetCurrentPrincipal(); | |
@@ -311,6 +316,8 @@ | |
// state machine. | |
void Stop(); | |
+ void AudioWritten(nsTArray<float>& aFrameBuffer, nsTArray<float>& aSpectrum); | |
+ | |
// Called by the state machine to notify the decoder that the duration | |
// has changed. | |
void DurationChanged(); | |
diff -r 0efb08f1b29a content/media/nsMediaDecoder.h | |
--- a/content/media/nsMediaDecoder.h Sat May 01 14:02:03 2010 +0200 | |
+++ b/content/media/nsMediaDecoder.h Sat May 01 16:19:35 2010 -0500 | |
@@ -223,6 +223,9 @@ | |
// their nsMediaStream. | |
virtual void MoveLoadsToBackground()=0; | |
+ // XXX: just a hack to test writing to audio stream | |
+ virtual void Write(PRUint32 count, float *valueArray)=0; | |
+ | |
// Gets the image container for the media element. Will return null if | |
// the element is not a video element. This can be called from any | |
// thread; ImageContainers can be used from any thread. | |
diff -r 0efb08f1b29a content/media/ogg/nsOggDecoder.cpp | |
--- a/content/media/ogg/nsOggDecoder.cpp Sat May 01 14:02:03 2010 +0200 | |
+++ b/content/media/ogg/nsOggDecoder.cpp Sat May 01 16:19:35 2010 -0500 | |
@@ -44,3 +44,4 @@ | |
{ | |
return new nsOggPlayStateMachine(this); | |
} | |
+ | |
diff -r 0efb08f1b29a content/media/ogg/nsOggPlayStateMachine.cpp | |
--- a/content/media/ogg/nsOggPlayStateMachine.cpp Sat May 01 14:02:03 2010 +0200 | |
+++ b/content/media/ogg/nsOggPlayStateMachine.cpp Sat May 01 16:19:35 2010 -0500 | |
@@ -46,6 +46,11 @@ | |
#include "mozilla/mozalloc.h" | |
#include "VideoUtils.h" | |
+#include <math.h> | |
+#ifndef M_PI | |
+#define M_PI 3.14159265358979323846 | |
+#endif | |
+ | |
using namespace mozilla::layers; | |
using mozilla::MonitorAutoExit; | |
@@ -96,6 +101,26 @@ | |
// less than LOW_VIDEO_FRAMES frames. | |
static const PRUint32 LOW_VIDEO_FRAMES = 1; | |
+class nsAudioWrittenEventRunner : public nsRunnable | |
+{ | |
+private: | |
+ nsCOMPtr<nsBuiltinDecoder> mDecoder; | |
+ nsTArray<float> mFrameBuffer; | |
+ nsTArray<float> mSpectrum; | |
+ | |
+public: | |
+ nsAudioWrittenEventRunner(nsBuiltinDecoder* aDecoder, nsTArray<float>& aFrameBuffer, nsTArray<float>& aSpectrum) : | |
+ mDecoder(aDecoder) | |
+ { | |
+ mFrameBuffer.SwapElements(aFrameBuffer); | |
+ mSpectrum.SwapElements(aSpectrum); | |
+ } | |
+ NS_IMETHOD Run() { | |
+ mDecoder->AudioWritten(mFrameBuffer, mSpectrum); | |
+ return NS_OK; | |
+ } | |
+}; | |
+ | |
nsOggPlayStateMachine::nsOggPlayStateMachine(nsBuiltinDecoder* aDecoder) : | |
mDecoder(aDecoder), | |
mState(DECODER_STATE_DECODING_METADATA), | |
@@ -119,6 +144,7 @@ | |
mStopDecodeThreads(PR_TRUE) | |
{ | |
MOZ_COUNT_CTOR(nsOggPlayStateMachine); | |
+ PreloadTables(); | |
} | |
nsOggPlayStateMachine::~nsOggPlayStateMachine() | |
@@ -316,6 +342,8 @@ | |
mAudioCompleted = PR_FALSE; | |
} | |
PRInt64 audioStartTime = -1; | |
+ nsTArray<float> signalBuffer; | |
+ | |
while (1) { | |
// Wait while we're not playing, and we're not shutting down, or we're | |
@@ -374,6 +402,26 @@ | |
// able to acquire the audio monitor in order to resume or destroy the | |
// audio stream. | |
if (!mAudioStream->IsPaused()) { | |
+ // Re-split by packets for FFT processing | |
+ // and CalculateFFT will assume signal is stereo | |
+ const PRUint32 maxBufferForFFT = 2 * FFT_TABLE_SIZE; | |
+ signalBuffer.AppendElements(sound->mAudioData.get(), sound->AudioDataLength()); | |
+ | |
+ while (signalBuffer.Length() >= maxBufferForFFT) { | |
+ // Inform the element that we've written sound data. | |
+ nsTArray<float> spectrum; | |
+ nsTArray<float> frameBuffer; | |
+ | |
+ frameBuffer.AppendElements(signalBuffer.Elements(), maxBufferForFFT); | |
+ signalBuffer.RemoveElementsAt(0, maxBufferForFFT); | |
+ | |
+ CalculateFFT(frameBuffer, spectrum); | |
+ | |
+ nsCOMPtr<nsIRunnable> event = | |
+ new nsAudioWrittenEventRunner(mDecoder, frameBuffer, spectrum); | |
+ NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); | |
+ } | |
+ | |
mAudioStream->Write(sound->mAudioData, | |
sound->AudioDataLength(), | |
PR_TRUE); | |
@@ -1324,6 +1372,103 @@ | |
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); | |
} | |
+// TODO: figure out where this should be done... | |
+void nsOggPlayStateMachine::PreloadTables() | |
+{ | |
+ for (PRUint32 i = 0; i < FFT_TABLE_SIZE; i++) | |
+ mReverseTable.AppendElement(0); | |
+ | |
+ PRUint32 limit = 1; | |
+ PRUint32 bit = FFT_TABLE_SIZE >> 1; | |
+ | |
+ while (limit < FFT_TABLE_SIZE) { | |
+ for (PRUint32 i = 0; i < limit; i++) | |
+ mReverseTable[i + limit] = mReverseTable[i] + bit; | |
+ | |
+ limit = limit << 1; | |
+ bit = bit >> 1; | |
+ } | |
+ | |
+ for (PRUint32 i = 0; i < FFT_TABLE_SIZE; i++) { | |
+ mSinTable.AppendElement(sin(-M_PI/i)); | |
+ mCosTable.AppendElement(cos(-M_PI/i)); | |
+ } | |
+} | |
+ | |
+void nsOggPlayStateMachine::CalculateFFT(nsTArray<float>& aData, nsTArray<float>& aSpectrum) | |
+{ | |
+ nsTArray<float> signal; | |
+ nsTArray<float> real; | |
+ nsTArray<float> imag; | |
+ | |
+ // Assuming interlaced stereo channels, need to split and merge into a stero-mix mono signal | |
+ for (PRUint32 i = 0; i < FFT_TABLE_SIZE; i++) | |
+ signal.AppendElement((aData[2*i] + aData[2*i+1]) / 2); | |
+ | |
+ for (PRUint32 i = 0; i < FFT_TABLE_SIZE; i++) { | |
+ real.AppendElement(signal[mReverseTable[i]]); | |
+ imag.AppendElement(0); | |
+ } | |
+ | |
+ PRUint32 halfSize = 1; | |
+ float phaseShiftStepReal; | |
+ float phaseShiftStepImag; | |
+ float currentPhaseShiftReal; | |
+ float currentPhaseShiftImag; | |
+ PRUint32 i; | |
+ PRUint32 off; | |
+ float tr; | |
+ float ti; | |
+ float tmpReal; | |
+ | |
+ while (halfSize < FFT_TABLE_SIZE) { | |
+ phaseShiftStepReal = mCosTable[halfSize]; | |
+ phaseShiftStepImag = mSinTable[halfSize]; | |
+ currentPhaseShiftReal = 1.0; | |
+ currentPhaseShiftImag = 0.0; | |
+ | |
+ for (PRUint32 fftStep = 0; fftStep < halfSize; fftStep++) { | |
+ i = fftStep; | |
+ | |
+ while (i < FFT_TABLE_SIZE) { | |
+ off = i + halfSize; | |
+ tr = (currentPhaseShiftReal * real[off]) - (currentPhaseShiftImag * imag[off]); | |
+ ti = (currentPhaseShiftReal * imag[off]) + (currentPhaseShiftImag * real[off]); | |
+ | |
+ real[off] = real[i] - tr; | |
+ imag[off] = imag[i] - ti; | |
+ real[i] += tr; | |
+ imag[i] += ti; | |
+ | |
+ i += halfSize << 1; | |
+ } | |
+ | |
+ tmpReal = currentPhaseShiftReal; | |
+ currentPhaseShiftReal = (tmpReal * phaseShiftStepReal) - (currentPhaseShiftImag * phaseShiftStepImag); | |
+ currentPhaseShiftImag = (tmpReal * phaseShiftStepImag) + (currentPhaseShiftImag * phaseShiftStepReal); | |
+ } | |
+ | |
+ halfSize = halfSize << 1; | |
+ } | |
+ | |
+ // Calculate hypotenuse of the complex number with pythagorean theorem | |
+ for (PRUint32 i = 0; i < FFT_TABLE_SIZE / 2; i++) { | |
+ aSpectrum.AppendElement(sqrt(real[i] * real[i] + imag[i] * imag[i]) / FFT_TABLE_SIZE); | |
+ } | |
+} | |
+ | |
+void nsOggPlayStateMachine::Write(PRUint32 count, float *valueArray) | |
+{ | |
+ if (!mAudioStream) { | |
+ mAudioStream = new nsAudioStream(); | |
+// mAudioStream->Init(mAudioChannels, mAudioRate, nsAudioStream::FORMAT_FLOAT32); | |
+ mAudioStream->Init(1, 44100, nsAudioStream::FORMAT_FLOAT32); | |
+// mAudioStream->SetVolume(mVolume); | |
+ mAudioStream->SetVolume(1); | |
+ } | |
+ mAudioStream->Write(valueArray, count); | |
+} | |
+ | |
static PRBool AddOverflow(PRUint32 a, PRUint32 b, PRUint32& aResult) { | |
PRUint64 rl = static_cast<PRUint64>(a) + static_cast<PRUint64>(b); | |
diff -r 0efb08f1b29a content/media/ogg/nsOggPlayStateMachine.h | |
--- a/content/media/ogg/nsOggPlayStateMachine.h Sat May 01 14:02:03 2010 +0200 | |
+++ b/content/media/ogg/nsOggPlayStateMachine.h Sat May 01 16:19:35 2010 -0500 | |
@@ -189,6 +189,11 @@ | |
using mozilla::TimeDuration; | |
using mozilla::TimeStamp; | |
+// The size to use for the FFT lookup tables | |
+#define FFT_TABLE_SIZE 2048 | |
+ | |
+class nsOggDecoder; | |
+ | |
/* | |
The playback state machine class. This manages the decoding in the | |
nsOggReader on the decode thread, seeking and in-sync-playback on the | |
@@ -239,6 +244,15 @@ | |
virtual void ClearPositionChangeFlag(); | |
virtual void SetSeekable(PRBool aSeekable); | |
+ // Writes some data | |
+ virtual void Write(PRUint32 count, float *valueArray); | |
+ | |
+ // Calculate FFT for frame data | |
+ void CalculateFFT(nsTArray<float>& aData, nsTArray<float>& aSpectrum); | |
+ | |
+ // Preload all FFT lookup tables | |
+ void PreloadTables(); | |
+ | |
// State machine thread run function. Polls the state, sends frames to be | |
// displayed at appropriate times, and generally manages the decode. | |
NS_IMETHOD Run(); | |
@@ -516,6 +530,11 @@ | |
// PR_FALSE while decode threads should be running. Accessed on audio, | |
// state machine and decode threads. Syncrhonised by decoder monitor. | |
PRPackedBool mStopDecodeThreads; | |
+ | |
+ // FFT look-up tables | |
+ nsAutoTArray<PRUint32, FFT_TABLE_SIZE> mReverseTable; | |
+ nsAutoTArray<float, FFT_TABLE_SIZE> mCosTable; | |
+ nsAutoTArray<float, FFT_TABLE_SIZE> mSinTable; | |
}; | |
diff -r 0efb08f1b29a content/media/wave/nsWaveDecoder.cpp | |
--- a/content/media/wave/nsWaveDecoder.cpp Sat May 01 14:02:03 2010 +0200 | |
+++ b/content/media/wave/nsWaveDecoder.cpp Sat May 01 16:19:35 2010 -0500 | |
@@ -1272,6 +1272,12 @@ | |
} | |
void | |
+nsWaveDecoder::Write(PRUint32 count, float *valueArray) | |
+{ | |
+ return; | |
+} | |
+ | |
+void | |
nsWaveDecoder::SetVolume(float aVolume) | |
{ | |
mInitialVolume = aVolume; | |
diff -r 0efb08f1b29a content/media/wave/nsWaveDecoder.h | |
--- a/content/media/wave/nsWaveDecoder.h Sat May 01 14:02:03 2010 +0200 | |
+++ b/content/media/wave/nsWaveDecoder.h Sat May 01 16:19:35 2010 -0500 | |
@@ -165,6 +165,8 @@ | |
virtual nsresult Play(); | |
virtual void Pause(); | |
+ virtual void Write(PRUint32 count, float *valueArray); | |
+ | |
// Set the current time of the media to aTime. This may cause mStream to | |
// create a new channel to fetch data from the appropriate position in the | |
// stream. | |
diff -r 0efb08f1b29a dom/base/nsDOMClassInfo.cpp | |
--- a/dom/base/nsDOMClassInfo.cpp Sat May 01 14:02:03 2010 +0200 | |
+++ b/dom/base/nsDOMClassInfo.cpp Sat May 01 16:19:35 2010 -0500 | |
@@ -234,6 +234,7 @@ | |
#include "nsIDOMMessageEvent.h" | |
#include "nsPaintRequest.h" | |
#include "nsIDOMNotifyPaintEvent.h" | |
+#include "nsIDOMNotifyAudioWrittenEvent.h" | |
#include "nsIDOMScrollAreaEvent.h" | |
#include "nsIDOMTransitionEvent.h" | |
#include "nsIDOMNSDocumentStyle.h" | |
@@ -1342,6 +1343,12 @@ | |
NS_DEFINE_CLASSINFO_DATA(NotifyPaintEvent, nsDOMGenericSH, | |
DOM_DEFAULT_SCRIPTABLE_FLAGS) | |
+ NS_DEFINE_CLASSINFO_DATA(NotifyAudioWrittenEvent, nsDOMGenericSH, | |
+ DOM_DEFAULT_SCRIPTABLE_FLAGS) | |
+ | |
+ NS_DEFINE_CLASSINFO_DATA(AudioData, nsDOMGenericSH, | |
+ DOM_DEFAULT_SCRIPTABLE_FLAGS) | |
+ | |
NS_DEFINE_CLASSINFO_DATA(SimpleGestureEvent, nsDOMGenericSH, | |
DOM_DEFAULT_SCRIPTABLE_FLAGS) | |
@@ -3751,6 +3758,15 @@ | |
DOM_CLASSINFO_EVENT_MAP_ENTRIES | |
DOM_CLASSINFO_MAP_END | |
+ DOM_CLASSINFO_MAP_BEGIN(NotifyAudioWrittenEvent, nsIDOMNotifyAudioWrittenEvent) | |
+ DOM_CLASSINFO_MAP_ENTRY(nsIDOMNotifyAudioWrittenEvent) | |
+ DOM_CLASSINFO_EVENT_MAP_ENTRIES | |
+ DOM_CLASSINFO_MAP_END | |
+ | |
+ DOM_CLASSINFO_MAP_BEGIN(AudioData, nsIDOMAudioData) | |
+ DOM_CLASSINFO_MAP_ENTRY(nsIDOMAudioData) | |
+ DOM_CLASSINFO_MAP_END | |
+ | |
DOM_CLASSINFO_MAP_BEGIN(SimpleGestureEvent, nsIDOMSimpleGestureEvent) | |
DOM_CLASSINFO_MAP_ENTRY(nsIDOMSimpleGestureEvent) | |
DOM_CLASSINFO_MAP_ENTRY(nsIDOMMouseEvent) | |
diff -r 0efb08f1b29a dom/base/nsDOMClassInfoClasses.h | |
--- a/dom/base/nsDOMClassInfoClasses.h Sat May 01 14:02:03 2010 +0200 | |
+++ b/dom/base/nsDOMClassInfoClasses.h Sat May 01 16:19:35 2010 -0500 | |
@@ -440,6 +440,10 @@ | |
DOMCI_CLASS(NotifyPaintEvent) | |
+DOMCI_CLASS(NotifyAudioWrittenEvent) | |
+ | |
+DOMCI_CLASS(AudioData) | |
+ | |
DOMCI_CLASS(SimpleGestureEvent) | |
#ifdef MOZ_MATHML | |
diff -r 0efb08f1b29a dom/interfaces/events/Makefile.in | |
--- a/dom/interfaces/events/Makefile.in Sat May 01 14:02:03 2010 +0200 | |
+++ b/dom/interfaces/events/Makefile.in Sat May 01 16:19:35 2010 -0500 | |
@@ -76,6 +76,7 @@ | |
nsIDOMCommandEvent.idl \ | |
nsIDOMMessageEvent.idl \ | |
nsIDOMNotifyPaintEvent.idl \ | |
+ nsIDOMNotifyAudioWrittenEvent.idl \ | |
nsIDOMPaintRequest.idl \ | |
nsIDOMPaintRequestList.idl \ | |
nsIDOMSimpleGestureEvent.idl \ | |
diff -r 0efb08f1b29a dom/interfaces/events/nsIDOMNotifyAudioWrittenEvent.idl | |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 | |
+++ b/dom/interfaces/events/nsIDOMNotifyAudioWrittenEvent.idl Sat May 01 16:19:35 2010 -0500 | |
@@ -0,0 +1,23 @@ | |
+#include "nsIDOMEvent.idl" | |
+#include "domstubs.idl" | |
+ | |
+[scriptable, uuid(9d4872bc-1aba-46c6-ad52-00ea927e08fb)] | |
+interface nsIDOMAudioData : nsISupports | |
+{ | |
+ readonly attribute unsigned long length; | |
+ float item(in unsigned long index); | |
+}; | |
+ | |
+ | |
+[scriptable, uuid(6250652d-7a6a-49a4-a2ee-9114e1e83427)] | |
+interface nsIDOMNotifyAudioWrittenEvent : nsIDOMEvent | |
+{ | |
+ readonly attribute nsIDOMAudioData mozFrameBuffer; | |
+ readonly attribute nsIDOMAudioData mozSpectrum; | |
+ | |
+ void initAudioWrittenEvent(in DOMString typeArg, | |
+ in boolean canBubbleArg, | |
+ in boolean cancelableArg, | |
+ in nsIDOMAudioData frameBuffer, | |
+ in nsIDOMAudioData spectrum); | |
+}; | |
diff -r 0efb08f1b29a dom/interfaces/html/nsIDOMHTMLMediaElement.idl | |
--- a/dom/interfaces/html/nsIDOMHTMLMediaElement.idl Sat May 01 14:02:03 2010 +0200 | |
+++ b/dom/interfaces/html/nsIDOMHTMLMediaElement.idl Sat May 01 16:19:35 2010 -0500 | |
@@ -106,4 +106,14 @@ | |
// buffered data. In fact any future data downloaded by this element or | |
// other will be sharable by both elements. | |
void mozLoadFrom(in nsIDOMHTMLMediaElement other); | |
+ | |
+ // Allow content to push audio data to the stream directly. Must call mozSetup first. | |
+ PRUint32 mozWriteAudio(in PRUint32 count, [array, size_is(count)] in float valueArray); | |
+ | |
+ // Setup the audio stream for writing | |
+ void mozSetup(in PRUint32 channels, in PRUint32 rate, in float volume); | |
+ | |
+ PRUint32 mozAvailable(); | |
+ | |
+ PRUint32 mozCurrentSample(); | |
}; | |
diff -r 0efb08f1b29a widget/public/nsGUIEvent.h | |
--- a/widget/public/nsGUIEvent.h Sat May 01 14:02:03 2010 +0200 | |
+++ b/widget/public/nsGUIEvent.h Sat May 01 16:19:35 2010 -0500 | |
@@ -409,8 +409,9 @@ | |
#define NS_RATECHANGE (NS_MEDIA_EVENT_START+17) | |
#define NS_DURATIONCHANGE (NS_MEDIA_EVENT_START+18) | |
#define NS_VOLUMECHANGE (NS_MEDIA_EVENT_START+19) | |
-#define NS_MEDIA_ABORT (NS_MEDIA_EVENT_START+20) | |
-#define NS_MEDIA_ERROR (NS_MEDIA_EVENT_START+21) | |
+#define NS_AUDIOWRITTEN (NS_MEDIA_EVENT_START+20) | |
+#define NS_MEDIA_ABORT (NS_MEDIA_EVENT_START+21) | |
+#define NS_MEDIA_ERROR (NS_MEDIA_EVENT_START+22) | |
#endif // MOZ_MEDIA | |
// paint notification events |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment