Skip to content

Instantly share code, notes, and snippets.

@notmasteryet
Created May 1, 2010 21:21
Show Gist options
  • Save notmasteryet/386668 to your computer and use it in GitHub Desktop.
Save notmasteryet/386668 to your computer and use it in GitHub Desktop.
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