diff --git a/dom/base/test/mochitest.ini b/dom/base/test/mochitest.ini index 9a102c6b6f97..e8023134bc8c 100644 --- a/dom/base/test/mochitest.ini +++ b/dom/base/test/mochitest.ini @@ -267,6 +267,8 @@ support-files = skip-if = buildapp == 'mulet' [test_audioNotificationStopOnNavigation.html] skip-if = buildapp == 'mulet' +[test_audioNotificationWithEarlyPlay.html] +skip-if = buildapp == 'mulet' [test_bug1091883.html] [test_bug116083.html] [test_bug793311.html] diff --git a/dom/base/test/test_audioNotificationWithEarlyPlay.html b/dom/base/test/test_audioNotificationWithEarlyPlay.html new file mode 100644 index 000000000000..66184ae03ab3 --- /dev/null +++ b/dom/base/test/test_audioNotificationWithEarlyPlay.html @@ -0,0 +1,73 @@ + + + + Test for audio controller in windows + + + + +
+
+ + + + + diff --git a/dom/html/HTMLMediaElement.cpp b/dom/html/HTMLMediaElement.cpp index 2e47c0946486..f76e600f4b69 100644 --- a/dom/html/HTMLMediaElement.cpp +++ b/dom/html/HTMLMediaElement.cpp @@ -3184,11 +3184,47 @@ void HTMLMediaElement::ProcessMediaFragmentURI() } } +class MOZ_STACK_CLASS AutoNotifyAudioChannelAgent +{ + nsRefPtr mElement; + bool mShouldNotify; + MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER; +public: + AutoNotifyAudioChannelAgent(HTMLMediaElement* aElement, + bool aNotify + MOZ_GUARD_OBJECT_NOTIFIER_PARAM) + : mElement(aElement) + , mShouldNotify(aNotify) + { + MOZ_GUARD_OBJECT_NOTIFIER_INIT; + if (mShouldNotify) { + mElement->NotifyAudioChannelAgent(false); + } + } + ~AutoNotifyAudioChannelAgent() + { + if (mShouldNotify) { + // The audio channel agent is destroyed at this point. + if (mElement->MaybeCreateAudioChannelAgent()) { + mElement->NotifyAudioChannelAgent(true); + } + } + } +}; + void HTMLMediaElement::MetadataLoaded(const MediaInfo* aInfo, nsAutoPtr aTags) { MOZ_ASSERT(NS_IsMainThread()); + // If the element is gaining or losing an audio track, we need to notify + // the audio channel agent so that the correct audio-playback events will + // get dispatched. + bool audioTrackChanging = mMediaInfo.HasAudio() != aInfo->HasAudio(); + AutoNotifyAudioChannelAgent autoNotify(this, + audioTrackChanging && + mPlayingThroughTheAudioChannel); + mMediaInfo = *aInfo; mIsEncrypted = aInfo->IsEncrypted() #ifdef MOZ_EME @@ -4488,7 +4524,25 @@ nsresult HTMLMediaElement::UpdateChannelMuteState(float aVolume, bool aMuted) return NS_OK; } -void HTMLMediaElement::UpdateAudioChannelPlayingState() +bool +HTMLMediaElement::MaybeCreateAudioChannelAgent() +{ + if (!mAudioChannelAgent) { + nsresult rv; + mAudioChannelAgent = do_CreateInstance("@mozilla.org/audiochannelagent;1", &rv); + if (NS_WARN_IF(NS_FAILED(rv))) { + return false; + } + MOZ_ASSERT(mAudioChannelAgent); + mAudioChannelAgent->InitWithWeakCallback(OwnerDoc()->GetInnerWindow(), + static_cast(mAudioChannel), + this); + } + return true; +} + +void +HTMLMediaElement::UpdateAudioChannelPlayingState() { bool playingThroughTheAudioChannel = (!mPaused && @@ -4506,18 +4560,9 @@ void HTMLMediaElement::UpdateAudioChannelPlayingState() return; } - if (!mAudioChannelAgent) { - nsresult rv; - mAudioChannelAgent = do_CreateInstance("@mozilla.org/audiochannelagent;1", &rv); - if (!mAudioChannelAgent) { - return; - } - mAudioChannelAgent->InitWithWeakCallback(OwnerDoc()->GetInnerWindow(), - static_cast(mAudioChannel), - this); + if (MaybeCreateAudioChannelAgent()) { + NotifyAudioChannelAgent(mPlayingThroughTheAudioChannel); } - - NotifyAudioChannelAgent(mPlayingThroughTheAudioChannel); } } diff --git a/dom/html/HTMLMediaElement.h b/dom/html/HTMLMediaElement.h index 664b508dc4bc..410168beaed1 100644 --- a/dom/html/HTMLMediaElement.h +++ b/dom/html/HTMLMediaElement.h @@ -35,10 +35,6 @@ // Define to output information on decoding and painting framerate /* #define DEBUG_FRAME_RATE 1 */ -class nsIChannel; -class nsIHttpChannel; -class nsILoadGroup; - typedef uint16_t nsMediaNetworkState; typedef uint16_t nsMediaReadyState; @@ -56,9 +52,13 @@ class MediaTrack; } // namespace dom } // namespace mozilla +class AutoNotifyAudioChannelAgent; +class nsIChannel; +class nsIHttpChannel; +class nsILoadGroup; +class nsIRunnable; class nsITimer; class nsRange; -class nsIRunnable; namespace mozilla { namespace dom { @@ -78,6 +78,8 @@ class HTMLMediaElement : public nsGenericHTMLElement, public MediaDecoderOwner, public nsIAudioChannelAgentCallback { + friend class AutoNotifyAudioChannelAgent; + public: typedef mozilla::TimeStamp TimeStamp; typedef mozilla::layers::ImageContainer ImageContainer; @@ -1050,6 +1052,10 @@ protected: // Notifies the audio channel agent when the element starts or stops playing. void NotifyAudioChannelAgent(bool aPlaying); + // Creates the audio channel agent if needed. Returns true if the audio + // channel agent is ready to be used. + bool MaybeCreateAudioChannelAgent(); + class nsAsyncEventRunner; using nsGenericHTMLElement::DispatchEvent; // For nsAsyncEventRunner.