diff --git a/content/media/nsAudioStream.cpp b/content/media/nsAudioStream.cpp index 4edf86d0546..f02b34acd46 100644 --- a/content/media/nsAudioStream.cpp +++ b/content/media/nsAudioStream.cpp @@ -138,7 +138,7 @@ class nsAudioStreamRemote : public nsAudioStream PRInt64 GetSampleOffset(); PRBool IsPaused(); - AudioChild* mAudioChild; + nsRefPtr mAudioChild; SampleFormat mFormat; int mRate; @@ -149,12 +149,6 @@ class nsAudioStreamRemote : public nsAudioStream PRInt32 mBytesPerSample; friend class AudioInitEvent; - friend class AudioShutdownEvent; - friend class AudioWriteEvent; - friend class AudioSetVolumeEvent; - friend class AudioPauseEvent; - friend class AudioDrainEvent; - friend class AudioGetSampleEvent; }; class AudioInitEvent : public nsRunnable @@ -181,27 +175,27 @@ class AudioInitEvent : public nsRunnable class AudioWriteEvent : public nsRunnable { public: - AudioWriteEvent(nsAudioStreamRemote* owner, + AudioWriteEvent(AudioChild* aChild, const void* aBuf, PRUint32 aNumberOfSamples, PRUint32 aBytesPerSample) { - mOwner = owner; + mAudioChild = aChild; mBytesPerSample = aBytesPerSample; mBuffer.Assign((const char*)aBuf, aNumberOfSamples*aBytesPerSample); } NS_IMETHOD Run() { - if (!mOwner->mAudioChild) + if (!mAudioChild->IsIPCOpen()) return NS_OK; - mOwner->mAudioChild->SendWrite(mBuffer, - mBuffer.Length() / mBytesPerSample); + mAudioChild->SendWrite(mBuffer, + mBuffer.Length() / mBytesPerSample); return NS_OK; } - nsRefPtr mOwner; + nsRefPtr mAudioChild; nsCString mBuffer; PRUint32 mBytesPerSample; }; @@ -209,73 +203,90 @@ class AudioWriteEvent : public nsRunnable class AudioSetVolumeEvent : public nsRunnable { public: - AudioSetVolumeEvent(nsAudioStreamRemote* owner, float volume) + AudioSetVolumeEvent(AudioChild* aChild, float volume) { - mOwner = owner; + mAudioChild = aChild; mVolume = volume; } NS_IMETHOD Run() { - if (!mOwner->mAudioChild) + if (!mAudioChild->IsIPCOpen()) return NS_OK; - mOwner->mAudioChild->SendSetVolume(mVolume); + mAudioChild->SendSetVolume(mVolume); return NS_OK; } - nsRefPtr mOwner; + nsRefPtr mAudioChild; float mVolume; }; class AudioDrainEvent : public nsRunnable { public: - AudioDrainEvent(nsAudioStreamRemote* owner) + AudioDrainEvent(AudioChild* aChild) { - mOwner = owner; + mAudioChild = aChild; } NS_IMETHOD Run() { - if (!mOwner->mAudioChild) + if (!mAudioChild->IsIPCOpen()) return NS_OK; - mOwner->mAudioChild->SendDrain(); + mAudioChild->SendDrain(); return NS_OK; } - nsRefPtr mOwner; + nsRefPtr mAudioChild; }; class AudioPauseEvent : public nsRunnable { public: - AudioPauseEvent(nsAudioStreamRemote* owner, PRBool pause) + AudioPauseEvent(AudioChild* aChild, PRBool pause) { - mOwner = owner; + mAudioChild = aChild; mPause = pause; } NS_IMETHOD Run() { - if (!mOwner->mAudioChild) + if (!mAudioChild->IsIPCOpen()) return NS_OK; if (mPause) - mOwner->mAudioChild->SendPause(); + mAudioChild->SendPause(); else - mOwner->mAudioChild->SendResume(); + mAudioChild->SendResume(); return NS_OK; } - nsRefPtr mOwner; + nsRefPtr mAudioChild; PRBool mPause; }; +class AudioShutdownEvent : public nsRunnable +{ + public: + AudioShutdownEvent(AudioChild* aChild) + { + mAudioChild = aChild; + } + + NS_IMETHOD Run() + { + if (mAudioChild->IsIPCOpen()) + PAudioChild::Send__delete__(mAudioChild); + return NS_OK; + } + + nsRefPtr mAudioChild; +}; #endif // MOZ_IPC @@ -602,14 +613,17 @@ nsAudioStreamRemote::Init(PRInt32 aNumChannels, } nsCOMPtr event = new AudioInitEvent(this); - NS_DispatchToMainThread(event); + NS_DispatchToMainThread(event, NS_DISPATCH_SYNC); return NS_OK; } void nsAudioStreamRemote::Shutdown() { - PAudioChild::Send__delete__(mAudioChild); + if (!mAudioChild) + return; + nsCOMPtr event = new AudioShutdownEvent(mAudioChild); + NS_DispatchToMainThread(event); mAudioChild = nsnull; } @@ -618,7 +632,9 @@ nsAudioStreamRemote::Write(const void* aBuf, PRUint32 aCount, PRBool aBlocking) { - nsCOMPtr event = new AudioWriteEvent(this, + if (!mAudioChild) + return NS_ERROR_FAILURE; + nsCOMPtr event = new AudioWriteEvent(mAudioChild, aBuf, aCount, mBytesPerSample); @@ -635,14 +651,18 @@ nsAudioStreamRemote::Available() void nsAudioStreamRemote::SetVolume(float aVolume) { - nsCOMPtr event = new AudioSetVolumeEvent(this, aVolume); + if (!mAudioChild) + return; + nsCOMPtr event = new AudioSetVolumeEvent(mAudioChild, aVolume); NS_DispatchToMainThread(event); } void nsAudioStreamRemote::Drain() { - nsCOMPtr event = new AudioDrainEvent(this); + if (!mAudioChild) + return; + nsCOMPtr event = new AudioDrainEvent(mAudioChild); NS_DispatchToMainThread(event, NS_DISPATCH_SYNC); } @@ -650,7 +670,9 @@ void nsAudioStreamRemote::Pause() { mPaused = PR_TRUE; - nsCOMPtr event = new AudioPauseEvent(this, PR_TRUE); + if (!mAudioChild) + return; + nsCOMPtr event = new AudioPauseEvent(mAudioChild, PR_TRUE); NS_DispatchToMainThread(event); } @@ -658,7 +680,9 @@ void nsAudioStreamRemote::Resume() { mPaused = PR_FALSE; - nsCOMPtr event = new AudioPauseEvent(this, PR_FALSE); + if (!mAudioChild) + return; + nsCOMPtr event = new AudioPauseEvent(mAudioChild, PR_FALSE); NS_DispatchToMainThread(event); } diff --git a/dom/ipc/AudioChild.cpp b/dom/ipc/AudioChild.cpp index 243bcec0b65..d2b6502ef85 100644 --- a/dom/ipc/AudioChild.cpp +++ b/dom/ipc/AudioChild.cpp @@ -42,9 +42,13 @@ namespace mozilla { namespace dom { +NS_IMPL_THREADSAFE_ADDREF(AudioChild); +NS_IMPL_THREADSAFE_RELEASE(AudioChild); + AudioChild::AudioChild() : mLastSampleOffset(-1), - mLastSampleOffsetTime(0) + mLastSampleOffsetTime(0), + mIPCOpen(PR_TRUE) { MOZ_COUNT_CTOR(AudioChild); } @@ -54,6 +58,12 @@ AudioChild::~AudioChild() MOZ_COUNT_DTOR(AudioChild); } +void +AudioChild::ActorDestroy(ActorDestroyReason aWhy) +{ + mIPCOpen = PR_FALSE; +} + bool AudioChild::RecvSampleOffsetUpdate(const PRInt64& offset, const PRInt64& time) diff --git a/dom/ipc/AudioChild.h b/dom/ipc/AudioChild.h index 1360ae03d3c..93d4572c6e7 100644 --- a/dom/ipc/AudioChild.h +++ b/dom/ipc/AudioChild.h @@ -48,14 +48,23 @@ namespace dom { class AudioChild : public PAudioChild { public: + NS_IMETHOD_(nsrefcnt) AddRef(); + NS_IMETHOD_(nsrefcnt) Release(); + AudioChild(); virtual ~AudioChild(); virtual bool RecvSampleOffsetUpdate(const PRInt64&, const PRInt64&); + virtual void ActorDestroy(ActorDestroyReason); PRInt64 GetLastKnownSampleOffset(); PRInt64 GetLastKnownSampleOffsetTime(); + + PRBool IsIPCOpen() { return mIPCOpen; }; private: + nsAutoRefCnt mRefCnt; + NS_DECL_OWNINGTHREAD PRInt64 mLastSampleOffset, mLastSampleOffsetTime; + PRPackedBool mIPCOpen; }; } // namespace dom diff --git a/dom/ipc/AudioParent.cpp b/dom/ipc/AudioParent.cpp index 9fa6a690144..5770a95d0b6 100644 --- a/dom/ipc/AudioParent.cpp +++ b/dom/ipc/AudioParent.cpp @@ -66,12 +66,35 @@ class AudioWriteEvent : public nsRunnable PRUint32 mCount; }; +class AudioPauseEvent : public nsRunnable +{ + public: + AudioPauseEvent(nsAudioStream* owner, PRBool aPause) + { + mOwner = owner; + mPause = aPause; + } + + NS_IMETHOD Run() + { + if (mPause) + mOwner->Pause(); + else + mOwner->Resume(); + return NS_OK; + } + + private: + nsRefPtr mOwner; + PRBool mPause; +}; + NS_IMPL_THREADSAFE_ISUPPORTS1(AudioParent, nsITimerCallback) nsresult AudioParent::Notify(nsITimer* timer) { - if (!mStream) { + if (!mIPCOpen || !mStream) { timer->Cancel(); return NS_ERROR_FAILURE; } @@ -110,16 +133,18 @@ AudioParent::RecvDrain() bool AudioParent::RecvPause() { - if (mStream) - mStream->Pause(); + nsCOMPtr event = new AudioPauseEvent(mStream, PR_TRUE); + nsCOMPtr thread = nsAudioStream::GetGlobalThread(); + thread->Dispatch(event, nsIEventTarget::DISPATCH_NORMAL); return true; } bool AudioParent::RecvResume() { - if (mStream) - mStream->Resume(); + nsCOMPtr event = new AudioPauseEvent(mStream, PR_FALSE); + nsCOMPtr thread = nsAudioStream::GetGlobalThread(); + thread->Dispatch(event, nsIEventTarget::DISPATCH_NORMAL); return true; } @@ -139,6 +164,7 @@ AudioParent::Recv__delete__() } AudioParent::AudioParent(PRInt32 aNumChannels, PRInt32 aRate, PRInt32 aFormat) + : mIPCOpen(PR_TRUE) { mStream = nsAudioStream::AllocateStream(); if (mStream) @@ -156,5 +182,11 @@ AudioParent::~AudioParent() { } +void +AudioParent::ActorDestroy(ActorDestroyReason aWhy) +{ + mIPCOpen = PR_FALSE; +} + } // namespace dom } // namespace mozilla diff --git a/dom/ipc/AudioParent.h b/dom/ipc/AudioParent.h index 260f693352b..2d555164d2f 100644 --- a/dom/ipc/AudioParent.h +++ b/dom/ipc/AudioParent.h @@ -75,10 +75,13 @@ class AudioParent : public PAudioParent, public nsITimerCallback AudioParent(PRInt32 aNumChannels, PRInt32 aRate, PRInt32 aFormat); virtual ~AudioParent(); + virtual void ActorDestroy(ActorDestroyReason); nsRefPtr mStream; nsCOMPtr mTimer; +private: + PRPackedBool mIPCOpen; }; } // namespace dom } // namespace mozilla diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index 36602f15d8f..99a2729e694 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -333,14 +333,16 @@ ContentChild::AllocPAudio(const PRInt32& numChannels, const PRInt32& rate, const PRInt32& format) { - PAudioChild *child = new AudioChild(); + AudioChild *child = new AudioChild(); + NS_ADDREF(child); return child; } bool ContentChild::DeallocPAudio(PAudioChild* doomed) { - delete doomed; + AudioChild *child = static_cast(doomed); + NS_RELEASE(child); return true; } diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index 7089c419c7f..4b8ce5ed2a5 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -427,7 +427,7 @@ ContentParent::AllocPAudio(const PRInt32& numChannels, const PRInt32& format) { AudioParent *parent = new AudioParent(numChannels, rate, format); - parent->AddRef(); + NS_ADDREF(parent); return parent; }