diff --git a/content/media/nsAudioStream.cpp b/content/media/nsAudioStream.cpp index 551d3520ba47..943566b10edb 100644 --- a/content/media/nsAudioStream.cpp +++ b/content/media/nsAudioStream.cpp @@ -93,7 +93,7 @@ class nsAudioStreamLocal : public nsAudioStream nsresult Write(const void* aBuf, PRUint32 aCount, PRBool aBlocking); PRUint32 Available(); void SetVolume(double aVolume); - void Drain(); + nsresult Drain(); void Pause(); void Resume(); PRInt64 GetPosition(); @@ -137,7 +137,7 @@ class nsAudioStreamRemote : public nsAudioStream nsresult Write(const void* aBuf, PRUint32 aCount, PRBool aBlocking); PRUint32 Available(); void SetVolume(double aVolume); - void Drain(); + nsresult Drain(); void Pause(); void Resume(); PRInt64 GetPosition(); @@ -560,12 +560,12 @@ void nsAudioStreamLocal::SetVolume(double aVolume) #endif } -void nsAudioStreamLocal::Drain() +nsresult nsAudioStreamLocal::Drain() { NS_ASSERTION(!mPaused, "Don't drain audio when paused, it won't finish!"); if (mInError) - return; + return NS_ERROR_FAILURE; // Write any remaining unwritten sound data in the overflow buffer if (!mBufferOverflow.IsEmpty()) { @@ -574,14 +574,16 @@ void nsAudioStreamLocal::Drain() mBufferOverflow.Length() * sizeof(short)) != SA_SUCCESS) PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsAudioStreamLocal: sa_stream_write error")); mInError = PR_TRUE; - return; + return NS_ERROR_FAILURE; } int r = sa_stream_drain(static_cast(mAudioHandle)); if (r != SA_SUCCESS && r != SA_ERROR_INVALID) { PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsAudioStreamLocal: sa_stream_drain error")); mInError = PR_TRUE; + return NS_ERROR_FAILURE; } + return NS_OK; } void nsAudioStreamLocal::Pause() @@ -739,16 +741,16 @@ nsAudioStreamRemote::SetVolume(double aVolume) NS_DispatchToMainThread(event); } -void +nsresult nsAudioStreamRemote::Drain() { if (!mAudioChild) - return; + return NS_ERROR_FAILURE; nsCOMPtr event = new AudioDrainEvent(mAudioChild); NS_DispatchToMainThread(event); - mAudioChild->WaitForDrain(); + return mAudioChild->WaitForDrain(); } - + void nsAudioStreamRemote::Pause() { diff --git a/content/media/nsAudioStream.h b/content/media/nsAudioStream.h index 192dcc0f06eb..2c0ba6f9bbf0 100644 --- a/content/media/nsAudioStream.h +++ b/content/media/nsAudioStream.h @@ -98,7 +98,7 @@ public: virtual void SetVolume(double aVolume) = 0; // Block until buffered audio data has been consumed. - virtual void Drain() = 0; + virtual nsresult Drain() = 0; // Pause audio playback virtual void Pause() = 0; diff --git a/dom/ipc/AudioChild.cpp b/dom/ipc/AudioChild.cpp index d8a6dadbfa90..a08a0b551608 100644 --- a/dom/ipc/AudioChild.cpp +++ b/dom/ipc/AudioChild.cpp @@ -76,10 +76,13 @@ AudioChild::RecvSampleOffsetUpdate(const PRInt64& offset, } bool -AudioChild::RecvDrainDone() +AudioChild::RecvDrainDone(const nsresult& status) { ReentrantMonitorAutoEnter mon(mAudioReentrantMonitor); - mDrained = PR_TRUE; + + if (status == NS_OK) + mDrained = PR_TRUE; + mAudioReentrantMonitor.NotifyAll(); return true; } @@ -103,13 +106,17 @@ AudioChild::RecvMinWriteSampleDone(const PRInt32& minSamples) return true; } -void +nsresult AudioChild::WaitForDrain() { ReentrantMonitorAutoEnter mon(mAudioReentrantMonitor); while (!mDrained && mIPCOpen) { mAudioReentrantMonitor.Wait(); } + if (mDrained) + return NS_OK; + + return NS_ERROR_FAILURE; } PRInt64 diff --git a/dom/ipc/AudioChild.h b/dom/ipc/AudioChild.h index 5467f035f1c3..6f652bf154dd 100644 --- a/dom/ipc/AudioChild.h +++ b/dom/ipc/AudioChild.h @@ -55,10 +55,10 @@ class AudioChild : public PAudioChild AudioChild(); virtual ~AudioChild(); virtual bool RecvSampleOffsetUpdate(const PRInt64&, const PRInt64&); - virtual bool RecvDrainDone(); + virtual bool RecvDrainDone(const nsresult& status); virtual PRInt32 WaitForMinWriteSample(); virtual bool RecvMinWriteSampleDone(const PRInt32& sampleCount); - virtual void WaitForDrain(); + virtual nsresult WaitForDrain(); virtual void ActorDestroy(ActorDestroyReason); PRInt64 GetLastKnownSampleOffset(); diff --git a/dom/ipc/AudioParent.cpp b/dom/ipc/AudioParent.cpp index 6e5864a2e1a7..705b053beeeb 100644 --- a/dom/ipc/AudioParent.cpp +++ b/dom/ipc/AudioParent.cpp @@ -154,19 +154,21 @@ class AudioMinWriteSampleEvent : public nsRunnable class AudioDrainDoneEvent : public nsRunnable { public: - AudioDrainDoneEvent(AudioParent* owner) + AudioDrainDoneEvent(AudioParent* owner, nsresult status) { mOwner = owner; + mStatus = status; } NS_IMETHOD Run() { - mOwner->SendDrainDone(); + mOwner->SendDrainDone(mStatus); return NS_OK; } private: nsRefPtr mOwner; + nsresult mStatus; }; class AudioDrainEvent : public nsRunnable @@ -180,8 +182,8 @@ class AudioDrainEvent : public nsRunnable NS_IMETHOD Run() { - mOwner->Drain(); - nsCOMPtr event = new AudioDrainDoneEvent(mParent); + nsresult rv = mOwner->Drain(); + nsCOMPtr event = new AudioDrainDoneEvent(mParent, rv); NS_DispatchToMainThread(event); return NS_OK; } @@ -290,10 +292,10 @@ AudioParent::SendMinWriteSampleDone(PRInt32 minSamples) } bool -AudioParent::SendDrainDone() +AudioParent::SendDrainDone(nsresult status) { if (mIPCOpen) - return PAudioParent::SendDrainDone(); + return PAudioParent::SendDrainDone(status); return true; } diff --git a/dom/ipc/AudioParent.h b/dom/ipc/AudioParent.h index 22fe704eb9eb..bb3fbca54626 100644 --- a/dom/ipc/AudioParent.h +++ b/dom/ipc/AudioParent.h @@ -80,7 +80,7 @@ class AudioParent : public PAudioParent, public nsITimerCallback SendMinWriteSampleDone(PRInt32 minSamples); virtual bool - SendDrainDone(); + SendDrainDone(nsresult status); AudioParent(PRInt32 aNumChannels, PRInt32 aRate, PRInt32 aFormat); virtual ~AudioParent(); diff --git a/dom/ipc/PAudio.ipdl b/dom/ipc/PAudio.ipdl index 954229ec5d9e..a6df6828f99f 100644 --- a/dom/ipc/PAudio.ipdl +++ b/dom/ipc/PAudio.ipdl @@ -65,7 +65,7 @@ parent: SampleOffsetUpdate(PRInt64 offset, PRInt64 time); MinWriteSampleDone(PRInt32 sampleCount); - DrainDone(); + DrainDone(nsresult status); };