Bug 1235612 - part3 : send audio-playback event from ME.
--- a/dom/audiochannel/AudioChannelService.cpp
+++ b/dom/audiochannel/AudioChannelService.cpp
@@ -117,44 +117,16 @@ GetTopWindow(nsPIDOMWindow* aWindow)
}
bool
IsParentProcess()
{
return XRE_GetProcessType() == GeckoProcessType_Default;
}
-class MediaPlaybackRunnable : public nsRunnable
-{
-public:
- MediaPlaybackRunnable(nsIDOMWindow* aWindow, bool aActive)
- : mWindow(aWindow)
- , mActive(aActive)
- {}
-
- NS_IMETHOD Run()
- {
- nsCOMPtr<nsIObserverService> observerService =
- services::GetObserverService();
- if (observerService) {
- observerService->NotifyObservers(
- ToSupports(mWindow),
- "audio-playback",
- mActive ? MOZ_UTF16("active")
- : MOZ_UTF16("inactive"));
- }
-
- return NS_OK;
- }
-
-private:
- nsCOMPtr<nsIDOMWindow> mWindow;
- bool mActive;
-};
-
} // anonymous namespace
StaticRefPtr<AudioChannelService> gAudioChannelService;
// Mappings from 'mozaudiochannel' attribute strings to an enumeration.
static const nsAttrValue::EnumTable kMozAudioChannelAttributeTable[] = {
{ "normal", (int16_t)AudioChannel::Normal },
{ "content", (int16_t)AudioChannel::Content },
@@ -282,23 +254,16 @@ AudioChannelService::RegisterAudioChanne
++winData->mChannels[(uint32_t)aChannel].mNumberOfAgents;
// The first one, we must inform the BrowserElementAudioChannel.
if (winData->mChannels[(uint32_t)aChannel].mNumberOfAgents == 1) {
NotifyChannelActive(aAgent->WindowID(), aChannel, true);
}
- // If this is the first agent for this window, we must notify the observers.
- if (winData->mAgents.Length() == 1) {
- RefPtr<MediaPlaybackRunnable> runnable =
- new MediaPlaybackRunnable(aAgent->Window(), true /* active */);
- NS_DispatchToCurrentThread(runnable);
- }
-
// If the window has already been captured, the agent of that window should
// also be captured.
if (winData->mIsAudioCaptured) {
aAgent->WindowAudioCaptureChanged(aAgent->InnerWindowID(),
winData->mIsAudioCaptured);
}
MaybeSendStatusUpdate();
@@ -331,23 +296,16 @@ AudioChannelService::UnregisterAudioChan
#ifdef MOZ_WIDGET_GONK
bool active = AnyAudioChannelIsActive();
for (uint32_t i = 0; i < mSpeakerManager.Length(); i++) {
mSpeakerManager[i]->SetAudioChannelActive(active);
}
#endif
- // If this is the last agent for this window, we must notify the observers.
- if (winData->mAgents.IsEmpty()) {
- RefPtr<MediaPlaybackRunnable> runnable =
- new MediaPlaybackRunnable(aAgent->Window(), false /* active */);
- NS_DispatchToCurrentThread(runnable);
- }
-
// No need to capture non-audible object.
if (winData->mIsAudioCaptured) {
aAgent->WindowAudioCaptureChanged(aAgent->InnerWindowID(), false);
}
MaybeSendStatusUpdate();
}
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -27,16 +27,17 @@
#include "nsSize.h"
#include "nsIFrame.h"
#include "nsIDocument.h"
#include "nsIDOMDocument.h"
#include "nsIDocShell.h"
#include "nsError.h"
#include "nsNodeInfoManager.h"
#include "nsNetUtil.h"
+#include "nsIObserverService.h"
#include "nsXPCOMStrings.h"
#include "xpcpublic.h"
#include "nsThreadUtils.h"
#include "nsIThreadInternal.h"
#include "nsContentUtils.h"
#include "nsIRequest.h"
#include "nsQueryObject.h"
@@ -80,16 +81,17 @@
#include "mozilla/dom/AudioTrack.h"
#include "mozilla/dom/AudioTrackList.h"
#include "mozilla/dom/VideoTrack.h"
#include "mozilla/dom/VideoTrackList.h"
#include "mozilla/dom/TextTrack.h"
#include "nsIContentPolicy.h"
#include "mozilla/Telemetry.h"
+#include "mozilla/Services.h"
#include "ImageContainer.h"
#include "nsRange.h"
#include <algorithm>
#include <cmath>
static mozilla::LazyLogModule gMediaElementLog("nsMediaElement");
static mozilla::LazyLogModule gMediaElementEventsLog("nsMediaElementEvents");
@@ -124,16 +126,94 @@ public:
}
~AutoNotifyAudioChannelAgent()
{
mElement->UpdateAudioChannelPlayingState();
}
};
+class MOZ_STACK_CLASS AutoNotifyAudibleState
+{
+public:
+ explicit AutoNotifyAudibleState(mozilla::dom::HTMLMediaElement* aElement,
+ bool aPlaying
+ MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+ : mElement(aElement)
+ , mIsPlaying(aPlaying)
+ {
+ MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+ }
+
+ ~AutoNotifyAudibleState()
+ {
+ if ((mIsPlaying && mElement->IsAudible()) || !mIsPlaying) {
+ RefPtr<MediaPlaybackRunnable> runnable =
+ new MediaPlaybackRunnable(mElement->OwnerDoc()->GetInnerWindow(),
+ mIsPlaying);
+ NS_DispatchToMainThread(runnable);
+ }
+ }
+
+private:
+ RefPtr<mozilla::dom::HTMLMediaElement> mElement;
+ bool mIsPlaying;
+ MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER;
+
+ class MediaPlaybackRunnable : public nsRunnable
+ {
+ public:
+ MediaPlaybackRunnable(nsIDOMWindow* aWindow, bool aActive)
+ : mInnerWindow(aWindow)
+ , mActive(aActive)
+ {}
+
+ NS_IMETHOD Run()
+ {
+ nsCOMPtr<nsIObserverService> observerService =
+ mozilla::services::GetObserverService();
+ if (observerService) {
+ nsPIDOMWindow* window = GetWindow();
+ if (NS_WARN_IF(!window)) {
+ return NS_OK;
+ }
+
+ observerService->NotifyObservers(
+ ToSupports(window),
+ "audio-playback",
+ mActive ? MOZ_UTF16("active")
+ : MOZ_UTF16("inactive"));
+ }
+ return NS_OK;
+ }
+
+ private:
+ nsPIDOMWindow* GetWindow()
+ {
+ nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(mInnerWindow);
+ MOZ_ASSERT(window->IsInnerWindow());
+
+ window = window->GetScriptableTop();
+ if (NS_WARN_IF(!window)) {
+ return nullptr;
+ }
+
+ window = window->GetOuterWindow();
+ if (NS_WARN_IF(!window)) {
+ return nullptr;
+ }
+
+ return window;
+ }
+
+ nsCOMPtr<nsIDOMWindow> mInnerWindow;
+ bool mActive;
+ };
+};
+
namespace mozilla {
namespace dom {
// Number of milliseconds between progress events as defined by spec
static const uint32_t PROGRESS_MS = 350;
// Number of milliseconds of no data before a stall event is fired as defined by spec
static const uint32_t STALL_MS = 3000;
@@ -2108,17 +2188,18 @@ HTMLMediaElement::HTMLMediaElement(alrea
mAudioChannelVolume(1.0),
mPlayingThroughTheAudioChannel(false),
mDisableVideo(false),
mPlayBlockedBecauseHidden(false),
mMediaStreamTrackListener(nullptr),
mElementInTreeState(ELEMENT_NOT_INTREE),
mHasUserInteraction(false),
mFirstFrameLoaded(false),
- mDefaultPlaybackStartPosition(0.0)
+ mDefaultPlaybackStartPosition(0.0),
+ mIsAudioTrackAudible(false)
{
mAudioChannel = AudioChannelService::GetDefaultAudioChannel();
mPaused.SetOuter(this);
RegisterActivityObserver();
NotifyOwnerDocumentActivityChangedInternal();
@@ -4779,16 +4860,17 @@ HTMLMediaElement::UpdateAudioChannelPlay
void
HTMLMediaElement::NotifyAudioChannelAgent(bool aPlaying)
{
// This is needed to pass nsContentUtils::IsCallerChrome().
// AudioChannel API should not called from content but it can happen that
// this method has some content JS in its stack.
AutoNoJSAPI nojsapi;
+ AutoNotifyAudibleState autoNotify(this, aPlaying);
if (aPlaying) {
float volume = 0.0;
bool muted = true;
mAudioChannelAgent->NotifyStartedPlaying(&volume, &muted);
WindowVolumeChanged(volume, muted);
} else {
mAudioChannelAgent->NotifyStoppedPlaying();
@@ -5167,14 +5249,15 @@ HTMLMediaElement::IsCurrentlyPlaying() c
return true;
}
return false;
}
void
HTMLMediaElement::NotifyAudibleStateChanged(bool aAudible)
{
- // TO DO ...
- printf_stderr("DD | #### NotifyAudibleStateChanged, aAudible = %d\n", aAudible);
+ if (mIsAudioTrackAudible != aAudible) {
+ mIsAudioTrackAudible = aAudible;
+ }
}
} // namespace dom
} // namespace mozilla
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -661,16 +661,20 @@ public:
IMPL_EVENT_HANDLER(mozinterruptbegin)
IMPL_EVENT_HANDLER(mozinterruptend)
// This is for testing only
float ComputedVolume() const;
bool ComputedMuted() const;
+ bool IsAudible() const {
+ return mIsAudioTrackAudible;
+ };
+
protected:
virtual ~HTMLMediaElement();
class MediaLoadListener;
class MediaStreamTracksAvailableCallback;
class MediaStreamTrackListener;
class StreamListener;
class StreamSizeListener;
@@ -1519,14 +1523,17 @@ private:
// True if the first frame has been successfully loaded.
bool mFirstFrameLoaded;
// Media elements also have a default playback start position, which must
// initially be set to zero seconds. This time is used to allow the element to
// be seeked even before the media is loaded.
double mDefaultPlaybackStartPosition;
+
+ // Sometime the audio track may have only silent data.
+ bool mIsAudioTrackAudible;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_HTMLMediaElement_h