Backed out changeset d09b20eeb382 (bug 1242874)
This commit is contained in:
@@ -223,16 +223,11 @@ NS_IMETHODIMP AudioChannelAgent::NotifyStartedPlaying(float *aVolume,
|
||||
service->RegisterAudioChannelAgent(this,
|
||||
static_cast<AudioChannel>(mAudioChannelType));
|
||||
|
||||
AudioPlaybackConfig config = service->GetMediaConfig(mWindow,
|
||||
mAudioChannelType);
|
||||
service->GetState(mWindow, mAudioChannelType, aVolume, aMuted);
|
||||
|
||||
MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
|
||||
("AudioChannelAgent, NotifyStartedPlaying, this = %p, "
|
||||
"mute = %d, volume = %f, suspend = %d\n", this,
|
||||
config.mMuted, config.mVolume, config.mSuspend));
|
||||
|
||||
*aVolume = config.mVolume;
|
||||
*aMuted = config.mMuted;
|
||||
("AudioChannelAgent, NotifyStartedPlaying, this = %p, mute = %d, "
|
||||
"volume = %f\n", this, *aMuted, *aVolume));
|
||||
|
||||
mIsRegToService = true;
|
||||
return NS_OK;
|
||||
@@ -275,49 +270,19 @@ AudioChannelAgent::WindowVolumeChanged()
|
||||
return;
|
||||
}
|
||||
|
||||
AudioPlaybackConfig config = GetMediaConfig();
|
||||
float volume = 1.0;
|
||||
bool muted = false;
|
||||
|
||||
RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
|
||||
if (service) {
|
||||
service->GetState(mWindow, mAudioChannelType, &volume, &muted);
|
||||
}
|
||||
|
||||
MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
|
||||
("AudioChannelAgent, WindowVolumeChanged, this = %p, mute = %d, "
|
||||
"volume = %f\n", this, config.mMuted, config.mVolume));
|
||||
"volume = %f\n", this, muted, volume));
|
||||
|
||||
callback->WindowVolumeChanged(config.mVolume, config.mMuted);
|
||||
}
|
||||
|
||||
void
|
||||
AudioChannelAgent::WindowSuspendChanged(nsSuspendedTypes aSuspend)
|
||||
{
|
||||
nsCOMPtr<nsIAudioChannelAgentCallback> callback = GetCallback();
|
||||
if (!callback) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsDisposableSuspend(aSuspend)) {
|
||||
aSuspend = GetMediaConfig().mSuspend;
|
||||
}
|
||||
|
||||
MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
|
||||
("AudioChannelAgent, WindowSuspendChanged, this = %p, "
|
||||
"suspended = %d\n", this, aSuspend));
|
||||
|
||||
callback->WindowSuspendChanged(aSuspend);
|
||||
}
|
||||
|
||||
AudioPlaybackConfig
|
||||
AudioChannelAgent::GetMediaConfig()
|
||||
{
|
||||
RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
|
||||
AudioPlaybackConfig config(1.0, false, nsISuspendedTypes::NONE_SUSPENDED);
|
||||
if (service) {
|
||||
config = service->GetMediaConfig(mWindow, mAudioChannelType);
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
bool
|
||||
AudioChannelAgent::IsDisposableSuspend(nsSuspendedTypes aSuspend) const
|
||||
{
|
||||
return (aSuspend == nsISuspendedTypes::SUSPENDED_PAUSE_DISPOSABLE ||
|
||||
aSuspend == nsISuspendedTypes::SUSPENDED_STOP_DISPOSABLE);
|
||||
callback->WindowVolumeChanged(volume, muted);
|
||||
}
|
||||
|
||||
uint64_t
|
||||
|
||||
@@ -23,8 +23,6 @@ class nsPIDOMWindowOuter;
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class AudioPlaybackConfig;
|
||||
|
||||
/* Header file */
|
||||
class AudioChannelAgent : public nsIAudioChannelAgent
|
||||
{
|
||||
@@ -37,7 +35,6 @@ public:
|
||||
AudioChannelAgent();
|
||||
|
||||
void WindowVolumeChanged();
|
||||
void WindowSuspendChanged(nsSuspendedTypes aSuspend);
|
||||
void WindowAudioCaptureChanged(uint64_t aInnerWindowID, bool aCapture);
|
||||
|
||||
nsPIDOMWindowOuter* Window() const
|
||||
@@ -51,9 +48,6 @@ public:
|
||||
private:
|
||||
virtual ~AudioChannelAgent();
|
||||
|
||||
AudioPlaybackConfig GetMediaConfig();
|
||||
bool IsDisposableSuspend(nsSuspendedTypes aSuspend) const;
|
||||
|
||||
// Returns mCallback if that's non-null, or otherwise tries to get an
|
||||
// nsIAudioChannelAgentCallback out of mWeakCallback.
|
||||
already_AddRefed<nsIAudioChannelAgentCallback> GetCallback();
|
||||
|
||||
@@ -353,22 +353,24 @@ AudioChannelService::UnregisterTabParent(TabParent* aTabParent)
|
||||
mTabParents.RemoveElement(aTabParent);
|
||||
}
|
||||
|
||||
AudioPlaybackConfig
|
||||
AudioChannelService::GetMediaConfig(nsPIDOMWindowOuter* aWindow,
|
||||
uint32_t aAudioChannel) const
|
||||
void
|
||||
AudioChannelService::GetState(nsPIDOMWindowOuter* aWindow, uint32_t aAudioChannel,
|
||||
float* aVolume, bool* aMuted)
|
||||
{
|
||||
MOZ_ASSERT(!aWindow || aWindow->IsOuterWindow());
|
||||
MOZ_ASSERT(aVolume && aMuted);
|
||||
MOZ_ASSERT(aAudioChannel < NUMBER_OF_AUDIO_CHANNELS);
|
||||
|
||||
AudioPlaybackConfig config(1.0, false,
|
||||
nsISuspendedTypes::NONE_SUSPENDED);
|
||||
|
||||
if (!aWindow || !aWindow->IsOuterWindow()) {
|
||||
config.SetConfig(0.0, true,
|
||||
nsISuspendedTypes::SUSPENDED_BLOCK);
|
||||
return config;
|
||||
*aVolume = 0.0;
|
||||
*aMuted = true;
|
||||
return;
|
||||
}
|
||||
|
||||
*aVolume = 1.0;
|
||||
*aMuted = false;
|
||||
|
||||
AudioChannelWindow* winData = nullptr;
|
||||
nsCOMPtr<nsPIDOMWindowOuter> window = aWindow;
|
||||
|
||||
@@ -377,16 +379,13 @@ AudioChannelService::GetMediaConfig(nsPIDOMWindowOuter* aWindow,
|
||||
do {
|
||||
winData = GetWindowData(window->WindowID());
|
||||
if (winData) {
|
||||
config.mVolume *= winData->mChannels[aAudioChannel].mVolume;
|
||||
config.mMuted = config.mMuted || winData->mChannels[aAudioChannel].mMuted;
|
||||
*aVolume *= winData->mChannels[aAudioChannel].mVolume;
|
||||
*aMuted = *aMuted || winData->mChannels[aAudioChannel].mMuted;
|
||||
}
|
||||
|
||||
config.mVolume *= window->GetAudioVolume();
|
||||
config.mMuted = config.mMuted || window->GetAudioMuted();
|
||||
|
||||
// If the mSuspend is already suspended, we don't need to set it again.
|
||||
config.mSuspend = (config.mSuspend == nsISuspendedTypes::NONE_SUSPENDED) ?
|
||||
window->GetMediaSuspend() : config.mSuspend;
|
||||
*aVolume *= window->GetAudioVolume();
|
||||
// TODO : distiguish between suspend and mute, it would be done in bug1242874.
|
||||
*aMuted = *aMuted || window->GetMediaSuspended() || window->GetAudioMuted();
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowOuter> win = window->GetScriptableParentOrNull();
|
||||
if (!win) {
|
||||
@@ -397,8 +396,6 @@ AudioChannelService::GetMediaConfig(nsPIDOMWindowOuter* aWindow,
|
||||
|
||||
// If there is no parent, or we are the toplevel we don't continue.
|
||||
} while (window && window != aWindow);
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -603,8 +600,7 @@ AudioChannelService::RefreshAgentsVolumeAndPropagate(AudioChannel aAudioChannel,
|
||||
}
|
||||
|
||||
void
|
||||
AudioChannelService::RefreshAgents(nsPIDOMWindowOuter* aWindow,
|
||||
mozilla::function<void(AudioChannelAgent*)> aFunc)
|
||||
AudioChannelService::RefreshAgentsVolume(nsPIDOMWindowOuter* aWindow)
|
||||
{
|
||||
MOZ_ASSERT(aWindow);
|
||||
MOZ_ASSERT(aWindow->IsOuterWindow());
|
||||
@@ -622,27 +618,10 @@ AudioChannelService::RefreshAgents(nsPIDOMWindowOuter* aWindow,
|
||||
nsTObserverArray<AudioChannelAgent*>::ForwardIterator
|
||||
iter(winData->mAgents);
|
||||
while (iter.HasMore()) {
|
||||
aFunc(iter.GetNext());
|
||||
iter.GetNext()->WindowVolumeChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AudioChannelService::RefreshAgentsVolume(nsPIDOMWindowOuter* aWindow)
|
||||
{
|
||||
RefreshAgents(aWindow, [] (AudioChannelAgent* agent) {
|
||||
agent->WindowVolumeChanged();
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
AudioChannelService::RefreshAgentsSuspend(nsPIDOMWindowOuter* aWindow,
|
||||
nsSuspendedTypes aSuspend)
|
||||
{
|
||||
RefreshAgents(aWindow, [aSuspend] (AudioChannelAgent* agent) {
|
||||
agent->WindowSuspendChanged(aSuspend);
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
AudioChannelService::SetWindowAudioCaptured(nsPIDOMWindowOuter* aWindow,
|
||||
uint64_t aInnerWindowID,
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#include "AudioChannelAgent.h"
|
||||
#include "nsAttrValue.h"
|
||||
#include "mozilla/dom/AudioChannelBinding.h"
|
||||
#include "mozilla/Function.h"
|
||||
|
||||
class nsIRunnable;
|
||||
class nsPIDOMWindowOuter;
|
||||
@@ -33,33 +32,6 @@ class TabParent;
|
||||
|
||||
#define NUMBER_OF_AUDIO_CHANNELS (uint32_t)AudioChannel::EndGuard_
|
||||
|
||||
class AudioPlaybackConfig
|
||||
{
|
||||
public:
|
||||
AudioPlaybackConfig()
|
||||
: mVolume(1.0)
|
||||
, mMuted(false)
|
||||
, mSuspend(nsISuspendedTypes::NONE_SUSPENDED)
|
||||
{}
|
||||
|
||||
AudioPlaybackConfig(float aVolume, bool aMuted, uint32_t aSuspended)
|
||||
: mVolume(aVolume)
|
||||
, mMuted(aMuted)
|
||||
, mSuspend(aSuspended)
|
||||
{}
|
||||
|
||||
void SetConfig(float aVolume, bool aMuted, uint32_t aSuspended)
|
||||
{
|
||||
mVolume = aVolume;
|
||||
mMuted = aMuted;
|
||||
mSuspend = aSuspended;
|
||||
}
|
||||
|
||||
float mVolume;
|
||||
bool mMuted;
|
||||
uint32_t mSuspend;
|
||||
};
|
||||
|
||||
class AudioChannelService final : public nsIAudioChannelService
|
||||
, public nsIObserver
|
||||
{
|
||||
@@ -100,10 +72,10 @@ public:
|
||||
|
||||
/**
|
||||
* Return the state to indicate this audioChannel for his window should keep
|
||||
* playing/muted/suspended.
|
||||
* playing/muted.
|
||||
*/
|
||||
AudioPlaybackConfig GetMediaConfig(nsPIDOMWindowOuter* aWindow,
|
||||
uint32_t aAudioChannel) const;
|
||||
void GetState(nsPIDOMWindowOuter* aWindow, uint32_t aChannel,
|
||||
float* aVolume, bool* aMuted);
|
||||
|
||||
/* Methods for the BrowserElementAudioChannel */
|
||||
float GetAudioChannelVolume(nsPIDOMWindowOuter* aWindow, AudioChannel aChannel);
|
||||
@@ -142,8 +114,6 @@ public:
|
||||
bool AnyAudioChannelIsActive();
|
||||
|
||||
void RefreshAgentsVolume(nsPIDOMWindowOuter* aWindow);
|
||||
void RefreshAgentsSuspend(nsPIDOMWindowOuter* aWindow,
|
||||
nsSuspendedTypes aSuspend);
|
||||
|
||||
void RefreshAgentsVolumeAndPropagate(AudioChannel aAudioChannel,
|
||||
nsPIDOMWindowOuter* aWindow);
|
||||
@@ -185,9 +155,6 @@ private:
|
||||
AudioChannelService();
|
||||
~AudioChannelService();
|
||||
|
||||
void RefreshAgents(nsPIDOMWindowOuter* aWindow,
|
||||
mozilla::function<void(AudioChannelAgent*)> aFunc);
|
||||
|
||||
static void CreateServiceIfNeeded();
|
||||
|
||||
/**
|
||||
@@ -203,15 +170,17 @@ private:
|
||||
void SetDefaultVolumeControlChannelInternal(int32_t aChannel,
|
||||
bool aVisible, uint64_t aChildID);
|
||||
|
||||
class AudioChannelConfig final : public AudioPlaybackConfig
|
||||
struct AudioChannelConfig final
|
||||
{
|
||||
public:
|
||||
AudioChannelConfig()
|
||||
: AudioPlaybackConfig(1.0, IsAudioChannelMutedByDefault(),
|
||||
nsISuspendedTypes::NONE_SUSPENDED)
|
||||
: mVolume(1.0)
|
||||
, mMuted(IsAudioChannelMutedByDefault())
|
||||
, mNumberOfAgents(0)
|
||||
{}
|
||||
|
||||
float mVolume;
|
||||
bool mMuted;
|
||||
|
||||
uint32_t mNumberOfAgents;
|
||||
};
|
||||
|
||||
|
||||
@@ -3796,7 +3796,7 @@ nsPIDOMWindowOuter::RefreshMediaElementsSuspend(SuspendTypes aSuspend)
|
||||
{
|
||||
RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
|
||||
if (service) {
|
||||
service->RefreshAgentsSuspend(GetOuterWindow(), aSuspend);
|
||||
// TODO : Impelement in next patch.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -463,16 +463,15 @@ FMRadio::EnableAudioChannelAgent()
|
||||
NS_IMETHODIMP
|
||||
FMRadio::WindowVolumeChanged(float aVolume, bool aMuted)
|
||||
{
|
||||
// TODO : Not support to change volume now, so we just close it.
|
||||
IFMRadioService::Singleton()->EnableAudio(!aMuted);
|
||||
// TODO: what about the volume?
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FMRadio::WindowSuspendChanged(nsSuspendedTypes aSuspend)
|
||||
{
|
||||
bool enable = (aSuspend == nsISuspendedTypes::NONE_SUSPENDED);
|
||||
IFMRadioService::Singleton()->EnableAudio(enable);
|
||||
// TODO : implementation.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -1162,6 +1162,11 @@ static bool IsAutoplayEnabled()
|
||||
return Preferences::GetBool("media.autoplay.enabled");
|
||||
}
|
||||
|
||||
static bool UseAudioChannelAPI()
|
||||
{
|
||||
return Preferences::GetBool("media.useAudioChannelAPI");
|
||||
}
|
||||
|
||||
void HTMLMediaElement::UpdatePreloadAction()
|
||||
{
|
||||
PreloadAction nextAction = PRELOAD_UNDEFINED;
|
||||
@@ -2239,7 +2244,6 @@ HTMLMediaElement::HTMLMediaElement(already_AddRefed<mozilla::dom::NodeInfo>& aNo
|
||||
mAutoplayEnabled(true),
|
||||
mPaused(true),
|
||||
mMuted(0),
|
||||
mAudioChannelSuspended(nsISuspendedTypes::NONE_SUSPENDED),
|
||||
mStatsShowing(false),
|
||||
mAllowCasting(false),
|
||||
mIsCasting(false),
|
||||
@@ -2391,7 +2395,20 @@ HTMLMediaElement::Play(ErrorResult& aRv)
|
||||
nsresult
|
||||
HTMLMediaElement::PlayInternal(bool aCallerIsChrome)
|
||||
{
|
||||
if (!IsAllowedToPlay()) {
|
||||
// Prevent media element from being auto-started by a script when
|
||||
// media.autoplay.enabled=false
|
||||
if (!mHasUserInteraction
|
||||
&& !IsAutoplayEnabled()
|
||||
&& !EventStateManager::IsHandlingUserInput()
|
||||
&& !aCallerIsChrome) {
|
||||
LOG(LogLevel::Debug, ("%p Blocked attempt to autoplay media.", this));
|
||||
#if defined(MOZ_WIDGET_ANDROID)
|
||||
nsContentUtils::DispatchTrustedEvent(OwnerDoc(),
|
||||
static_cast<nsIContent*>(this),
|
||||
NS_LITERAL_STRING("MozAutoplayMediaBlocked"),
|
||||
false,
|
||||
false);
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@@ -2456,8 +2473,6 @@ HTMLMediaElement::PlayInternal(bool aCallerIsChrome)
|
||||
|
||||
mPaused = false;
|
||||
mAutoplaying = false;
|
||||
SetAudioChannelSuspended(nsISuspendedTypes::NONE_SUSPENDED);
|
||||
|
||||
// We changed mPaused and mAutoplaying which can affect AddRemoveSelfReference
|
||||
// and our preload status.
|
||||
AddRemoveSelfReference();
|
||||
@@ -4523,7 +4538,12 @@ bool HTMLMediaElement::IsBeingDestroyed()
|
||||
void HTMLMediaElement::NotifyOwnerDocumentActivityChanged()
|
||||
{
|
||||
bool pauseElement = NotifyOwnerDocumentActivityChangedInternal();
|
||||
if (pauseElement && mAudioChannelAgent) {
|
||||
if (pauseElement && mAudioChannelAgent &&
|
||||
// On B2G, NotifyOwnerDocumentActivityChangedInternal may return true for
|
||||
// two reasons: the document no longer being active, or the element being
|
||||
// paused by the audio channel. However we are only interested in the
|
||||
// first case here, so we need to filter out the second case.
|
||||
(!UseAudioChannelAPI() || !ComputedMuted())) {
|
||||
// If the element is being paused since we are navigating away from the
|
||||
// document, notify the audio channel agent.
|
||||
// Be careful to ignore this event during a docshell frame swap.
|
||||
@@ -4547,6 +4567,14 @@ HTMLMediaElement::NotifyOwnerDocumentActivityChangedInternal()
|
||||
}
|
||||
|
||||
bool pauseElement = !IsActive();
|
||||
// Only pause the element when we start playing. If we pause without playing
|
||||
// audio, the resource loading would be affected unexpectedly. For example,
|
||||
// the media element is muted by default, but we don't want this behavior
|
||||
// interrupting the loading process.
|
||||
if (UseAudioChannelAPI() && mAudioChannelAgent) {
|
||||
pauseElement |= ComputedMuted();
|
||||
}
|
||||
|
||||
SuspendOrResumeElement(pauseElement, !IsActive());
|
||||
|
||||
if (!mPausedForInactiveDocumentOrChannel &&
|
||||
@@ -4960,6 +4988,33 @@ ImageContainer* HTMLMediaElement::GetImageContainer()
|
||||
return container ? container->GetImageContainer() : nullptr;
|
||||
}
|
||||
|
||||
nsresult HTMLMediaElement::UpdateChannelMuteState(float aVolume, bool aMuted)
|
||||
{
|
||||
if (mAudioChannelVolume != aVolume) {
|
||||
mAudioChannelVolume = aVolume;
|
||||
SetVolumeInternal();
|
||||
}
|
||||
|
||||
// We have to mute this channel.
|
||||
if (aMuted && !ComputedMuted()) {
|
||||
SetMutedInternal(mMuted | MUTED_BY_AUDIO_CHANNEL);
|
||||
if (UseAudioChannelAPI()) {
|
||||
DispatchAsyncEvent(NS_LITERAL_STRING("mozinterruptbegin"));
|
||||
}
|
||||
} else if (!aMuted && ComputedMuted()) {
|
||||
SetMutedInternal(mMuted & ~MUTED_BY_AUDIO_CHANNEL);
|
||||
if (UseAudioChannelAPI()) {
|
||||
DispatchAsyncEvent(NS_LITERAL_STRING("mozinterruptend"));
|
||||
}
|
||||
}
|
||||
|
||||
if (UseAudioChannelAPI()) {
|
||||
SuspendOrResumeElement(ComputedMuted(), false);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
HTMLMediaElement::MaybeCreateAudioChannelAgent()
|
||||
{
|
||||
@@ -4980,11 +5035,6 @@ HTMLMediaElement::MaybeCreateAudioChannelAgent()
|
||||
bool
|
||||
HTMLMediaElement::IsPlayingThroughTheAudioChannel() const
|
||||
{
|
||||
// It might be resumed from remote, we should keep the audio channel agent.
|
||||
if (IsSuspendedByAudioChannel()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Are we paused or muted
|
||||
if (mPaused || Muted()) {
|
||||
return false;
|
||||
@@ -5071,176 +5121,26 @@ HTMLMediaElement::NotifyAudioChannelAgent(bool aPlaying)
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLMediaElement::WindowVolumeChanged(float aVolume, bool aMuted)
|
||||
NS_IMETHODIMP HTMLMediaElement::WindowVolumeChanged(float aVolume, bool aMuted)
|
||||
{
|
||||
MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
|
||||
("HTMLMediaElement, WindowVolumeChanged, this = %p, "
|
||||
"aVolume = %f, aMuted = %d\n", this, aVolume, aMuted));
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (mAudioChannelVolume != aVolume) {
|
||||
mAudioChannelVolume = aVolume;
|
||||
SetVolumeInternal();
|
||||
}
|
||||
UpdateChannelMuteState(aVolume, aMuted);
|
||||
|
||||
if (aMuted && !ComputedMuted()) {
|
||||
SetMutedInternal(mMuted | MUTED_BY_AUDIO_CHANNEL);
|
||||
} else if (!aMuted && ComputedMuted()) {
|
||||
SetMutedInternal(mMuted & ~MUTED_BY_AUDIO_CHANNEL);
|
||||
if (UseAudioChannelAPI()) {
|
||||
mPaused.SetCanPlay(!aMuted);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLMediaElement::WindowSuspendChanged(SuspendTypes aSuspend)
|
||||
HTMLMediaElement::WindowSuspendChanged(nsSuspendedTypes aSuspend)
|
||||
{
|
||||
MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
|
||||
("HTMLMediaElement, WindowSuspendChanged, this = %p, "
|
||||
"aSuspend = %d\n", this, aSuspend));
|
||||
|
||||
switch (aSuspend) {
|
||||
case nsISuspendedTypes::NONE_SUSPENDED:
|
||||
ResumeFromAudioChannel();
|
||||
break;
|
||||
case nsISuspendedTypes::SUSPENDED_PAUSE:
|
||||
case nsISuspendedTypes::SUSPENDED_PAUSE_DISPOSABLE:
|
||||
PauseByAudioChannel(aSuspend);
|
||||
break;
|
||||
case nsISuspendedTypes::SUSPENDED_BLOCK:
|
||||
BlockByAudioChannel();
|
||||
break;
|
||||
case nsISuspendedTypes::SUSPENDED_STOP_DISPOSABLE:
|
||||
Pause();
|
||||
break;
|
||||
default:
|
||||
MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
|
||||
("HTMLMediaElement, WindowSuspendChanged, this = %p, "
|
||||
"Error : unknown suspended type!\n", this));
|
||||
}
|
||||
|
||||
// TODO : implementation.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
HTMLMediaElement::ResumeFromAudioChannel()
|
||||
{
|
||||
if (!IsSuspendedByAudioChannel()) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (mAudioChannelSuspended) {
|
||||
case nsISuspendedTypes::SUSPENDED_PAUSE:
|
||||
case nsISuspendedTypes::SUSPENDED_PAUSE_DISPOSABLE:
|
||||
ResumeFromAudioChannelPaused(mAudioChannelSuspended);
|
||||
break;
|
||||
case nsISuspendedTypes::SUSPENDED_BLOCK:
|
||||
ResumeFromAudioChannelBlocked();
|
||||
break;
|
||||
default:
|
||||
MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
|
||||
("HTMLMediaElement, ResumeFromAudioChannel, this = %p, "
|
||||
"Error : resume without suspended!\n", this));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
HTMLMediaElement::ResumeFromAudioChannelPaused(SuspendTypes aSuspend)
|
||||
{
|
||||
MOZ_ASSERT(mAudioChannelSuspended == nsISuspendedTypes::SUSPENDED_PAUSE ||
|
||||
mAudioChannelSuspended == nsISuspendedTypes::SUSPENDED_PAUSE_DISPOSABLE);
|
||||
|
||||
SetAudioChannelSuspended(nsISuspendedTypes::NONE_SUSPENDED);
|
||||
nsresult rv = PlayInternal(nsContentUtils::IsCallerChrome());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
}
|
||||
DispatchAsyncEvent(NS_LITERAL_STRING("mozinterruptend"));
|
||||
}
|
||||
|
||||
void
|
||||
HTMLMediaElement::ResumeFromAudioChannelBlocked()
|
||||
{
|
||||
MOZ_ASSERT(mAudioChannelSuspended == nsISuspendedTypes::SUSPENDED_BLOCK);
|
||||
|
||||
SetAudioChannelSuspended(nsISuspendedTypes::NONE_SUSPENDED);
|
||||
mPaused.SetCanPlay(true);
|
||||
SuspendOrResumeElement(false /* resume */, false);
|
||||
}
|
||||
|
||||
void
|
||||
HTMLMediaElement::PauseByAudioChannel(SuspendTypes aSuspend)
|
||||
{
|
||||
if (IsSuspendedByAudioChannel()) {
|
||||
return;
|
||||
}
|
||||
|
||||
SetAudioChannelSuspended(aSuspend);
|
||||
Pause();
|
||||
DispatchAsyncEvent(NS_LITERAL_STRING("mozinterruptbegin"));
|
||||
}
|
||||
|
||||
void
|
||||
HTMLMediaElement::BlockByAudioChannel()
|
||||
{
|
||||
if (IsSuspendedByAudioChannel()) {
|
||||
return;
|
||||
}
|
||||
|
||||
SetAudioChannelSuspended(nsISuspendedTypes::SUSPENDED_BLOCK);
|
||||
SuspendOrResumeElement(true /* suspend */, false);
|
||||
mPaused.SetCanPlay(false);
|
||||
}
|
||||
|
||||
void
|
||||
HTMLMediaElement::SetAudioChannelSuspended(SuspendTypes aSuspend)
|
||||
{
|
||||
if (mAudioChannelSuspended == aSuspend) {
|
||||
return;
|
||||
}
|
||||
|
||||
mAudioChannelSuspended = aSuspend;
|
||||
MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
|
||||
("HTMLMediaElement, SetAudioChannelSuspended, this = %p, "
|
||||
"aSuspend = %d\n", this, aSuspend));
|
||||
}
|
||||
|
||||
bool
|
||||
HTMLMediaElement::IsSuspendedByAudioChannel() const
|
||||
{
|
||||
return (mAudioChannelSuspended == nsISuspendedTypes::SUSPENDED_PAUSE ||
|
||||
mAudioChannelSuspended == nsISuspendedTypes::SUSPENDED_PAUSE_DISPOSABLE ||
|
||||
mAudioChannelSuspended == nsISuspendedTypes::SUSPENDED_BLOCK);
|
||||
}
|
||||
|
||||
bool
|
||||
HTMLMediaElement::IsAllowedToPlay()
|
||||
{
|
||||
// Prevent media element from being auto-started by a script when
|
||||
// media.autoplay.enabled=false
|
||||
if (!mHasUserInteraction &&
|
||||
!IsAutoplayEnabled() &&
|
||||
!EventStateManager::IsHandlingUserInput() &&
|
||||
!nsContentUtils::IsCallerChrome()) {
|
||||
#if defined(MOZ_WIDGET_ANDROID)
|
||||
nsContentUtils::DispatchTrustedEvent(OwnerDoc(),
|
||||
static_cast<nsIContent*>(this),
|
||||
NS_LITERAL_STRING("MozAutoplayMediaBlocked"),
|
||||
false,
|
||||
false);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
// The MediaElement can't start playback until it's resumed by audio channel.
|
||||
if (mAudioChannelSuspended == nsISuspendedTypes::SUSPENDED_PAUSE ||
|
||||
mAudioChannelSuspended == nsISuspendedTypes::SUSPENDED_BLOCK) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef MOZ_EME
|
||||
MediaKeys*
|
||||
HTMLMediaElement::GetMediaKeys() const
|
||||
|
||||
@@ -37,7 +37,6 @@
|
||||
|
||||
typedef uint16_t nsMediaNetworkState;
|
||||
typedef uint16_t nsMediaReadyState;
|
||||
typedef uint32_t SuspendTypes;
|
||||
|
||||
namespace mozilla {
|
||||
class DecoderDoctorDiagnostics;
|
||||
@@ -1115,6 +1114,9 @@ protected:
|
||||
// Check the permissions for audiochannel.
|
||||
bool CheckAudioChannelPermissions(const nsAString& aType);
|
||||
|
||||
// This method does the check for muting/nmuting the audio channel.
|
||||
nsresult UpdateChannelMuteState(float aVolume, bool aMuted);
|
||||
|
||||
// Seeks to aTime seconds. aSeekType can be Exact to seek to exactly the
|
||||
// seek target, or PrevSyncPoint if a quicker but less precise seek is
|
||||
// desired, and we'll seek to the sync point (keyframe and/or start of the
|
||||
@@ -1149,38 +1151,6 @@ protected:
|
||||
// channel agent is ready to be used.
|
||||
bool MaybeCreateAudioChannelAgent();
|
||||
|
||||
/**
|
||||
* We have different kinds of suspended cases,
|
||||
* - SUSPENDED_PAUSE
|
||||
* It's used when we temporary lost platform audio focus. MediaElement can
|
||||
* only be resumed when we gain the audio focus again.
|
||||
*
|
||||
* - SUSPENDED_PAUSE_DISPOSABLE
|
||||
* It's used when user press the pause botton on the remote media-control.
|
||||
* MediaElement can be resumed by reomte media-control or via play().
|
||||
*
|
||||
* - SUSPENDED_BLOCK
|
||||
* It's used to reduce the power comsuption, we won't play the auto-play
|
||||
* audio/video in the page we have never visited before. MediaElement would
|
||||
* be resumed when the page is active. See bug647429 for more details.
|
||||
*
|
||||
* - SUSPENDED_STOP_DISPOSABLE
|
||||
* When we permanently lost platform audio focus, we shuold stop playing
|
||||
* and stop the audio channel agent. MediaElement can only be restarted by
|
||||
* play().
|
||||
*/
|
||||
void PauseByAudioChannel(SuspendTypes aSuspend);
|
||||
void BlockByAudioChannel();
|
||||
|
||||
void ResumeFromAudioChannel();
|
||||
void ResumeFromAudioChannelPaused(SuspendTypes aSuspend);
|
||||
void ResumeFromAudioChannelBlocked();
|
||||
|
||||
bool IsSuspendedByAudioChannel() const;
|
||||
void SetAudioChannelSuspended(SuspendTypes aSuspend);
|
||||
|
||||
bool IsAllowedToPlay();
|
||||
|
||||
class nsAsyncEventRunner;
|
||||
using nsGenericHTMLElement::DispatchEvent;
|
||||
// For nsAsyncEventRunner.
|
||||
@@ -1400,7 +1370,6 @@ protected:
|
||||
};
|
||||
|
||||
uint32_t mMuted;
|
||||
SuspendTypes mAudioChannelSuspended;
|
||||
|
||||
// True if the media statistics are currently being shown by the builtin
|
||||
// video controls
|
||||
|
||||
@@ -305,6 +305,11 @@ private:
|
||||
bool mSuspended;
|
||||
};
|
||||
|
||||
static bool UseAudioChannelAPI()
|
||||
{
|
||||
return Preferences::GetBool("media.useAudioChannelAPI");
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(AudioDestinationNode, AudioNode,
|
||||
mAudioChannelAgent,
|
||||
mOfflineRenderingPromise)
|
||||
@@ -326,7 +331,7 @@ AudioDestinationNode::AudioDestinationNode(AudioContext* aContext,
|
||||
, mFramesToProduce(aLength)
|
||||
, mAudioChannel(AudioChannel::Normal)
|
||||
, mIsOffline(aIsOffline)
|
||||
, mAudioChannelSuspended(false)
|
||||
, mAudioChannelAgentPlaying(false)
|
||||
, mExtraCurrentTimeSinceLastStartedBlocking(0)
|
||||
, mExtraCurrentTimeUpdatedSinceLastStableState(false)
|
||||
, mCaptured(false)
|
||||
@@ -498,36 +503,38 @@ AudioDestinationNode::StartRendering(Promise* aPromise)
|
||||
mStream->Graph()->StartNonRealtimeProcessing(mFramesToProduce);
|
||||
}
|
||||
|
||||
void
|
||||
AudioDestinationNode::SetCanPlay(float aVolume, bool aMuted)
|
||||
{
|
||||
if (!mStream) {
|
||||
return;
|
||||
}
|
||||
|
||||
mStream->SetTrackEnabled(AudioNodeStream::AUDIO_TRACK, !aMuted);
|
||||
mStream->SetAudioOutputVolume(&gWebAudioOutputKey, aVolume);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
AudioDestinationNode::WindowVolumeChanged(float aVolume, bool aMuted)
|
||||
{
|
||||
if (!mStream) {
|
||||
return NS_OK;
|
||||
if (aMuted != mAudioChannelAgentPlaying) {
|
||||
mAudioChannelAgentPlaying = aMuted;
|
||||
|
||||
if (UseAudioChannelAPI()) {
|
||||
Context()->DispatchTrustedEvent(
|
||||
!aMuted ? NS_LITERAL_STRING("mozinterruptend")
|
||||
: NS_LITERAL_STRING("mozinterruptbegin"));
|
||||
}
|
||||
}
|
||||
|
||||
float volume = aMuted ? 0.0 : aVolume;
|
||||
mStream->SetAudioOutputVolume(&gWebAudioOutputKey, volume);
|
||||
SetCanPlay(aVolume, aMuted);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
AudioDestinationNode::WindowSuspendChanged(nsSuspendedTypes aSuspend)
|
||||
{
|
||||
if (!mStream) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool suspended = (aSuspend != nsISuspendedTypes::NONE_SUSPENDED);
|
||||
if (mAudioChannelSuspended == suspended) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mAudioChannelSuspended = suspended;
|
||||
Context()->DispatchTrustedEvent(!suspended ?
|
||||
NS_LITERAL_STRING("mozinterruptend") :
|
||||
NS_LITERAL_STRING("mozinterruptbegin"));
|
||||
|
||||
mStream->SetTrackEnabled(AudioNodeStream::AUDIO_TRACK, !suspended);
|
||||
// TODO : implementation.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -99,6 +99,8 @@ private:
|
||||
void SetMozAudioChannelType(AudioChannel aValue, ErrorResult& aRv);
|
||||
bool CheckAudioChannelPermissions(AudioChannel aValue);
|
||||
|
||||
void SetCanPlay(float aVolume, bool aMuted);
|
||||
|
||||
void NotifyStableState();
|
||||
void ScheduleStableStateNotification();
|
||||
|
||||
@@ -113,7 +115,7 @@ private:
|
||||
// Audio Channel Type.
|
||||
AudioChannel mAudioChannel;
|
||||
bool mIsOffline;
|
||||
bool mAudioChannelSuspended;
|
||||
bool mAudioChannelAgentPlaying;
|
||||
|
||||
TimeStamp mStartedBlockingDueToBeingOnlyNode;
|
||||
StreamTime mExtraCurrentTimeSinceLastStartedBlocking;
|
||||
|
||||
@@ -736,11 +736,7 @@ nsSpeechTask::WindowVolumeChanged(float aVolume, bool aMuted)
|
||||
NS_IMETHODIMP
|
||||
nsSpeechTask::WindowSuspendChanged(nsSuspendedTypes aSuspend)
|
||||
{
|
||||
if (aSuspend == nsISuspendedTypes::NONE_SUSPENDED) {
|
||||
Resume();
|
||||
} else {
|
||||
Pause();
|
||||
}
|
||||
// TODO : implementation.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -663,11 +663,12 @@ nsSynthVoiceRegistry::SpeakUtterance(SpeechSynthesisUtterance& aUtterance,
|
||||
RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
|
||||
if (service) {
|
||||
if (nsCOMPtr<nsPIDOMWindowInner> topWindow = aUtterance.GetOwner()) {
|
||||
// TODO : use audio channel agent, open new bug to fix it.
|
||||
uint32_t channel = static_cast<uint32_t>(AudioChannelService::GetDefaultAudioChannel());
|
||||
AudioPlaybackConfig config = service->GetMediaConfig(topWindow->GetOuterWindow(),
|
||||
channel);
|
||||
volume = config.mMuted ? 0.0f : config.mVolume * volume;
|
||||
float audioVolume = 1.0f;
|
||||
bool muted = false;
|
||||
service->GetState(topWindow->GetOuterWindow(),
|
||||
static_cast<uint32_t>(AudioChannelService::GetDefaultAudioChannel()),
|
||||
&audioVolume, &muted);
|
||||
volume = muted ? 0.0f : audioVolume * volume;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1851,9 +1851,7 @@ nsNPAPIPluginInstance::WindowVolumeChanged(float aVolume, bool aMuted)
|
||||
NS_IMETHODIMP
|
||||
nsNPAPIPluginInstance::WindowSuspendChanged(nsSuspendedTypes aSuspend)
|
||||
{
|
||||
// It doesn't support suspended, so we just do something like mute/unmute.
|
||||
WindowVolumeChanged(1.0, /* useless */
|
||||
aSuspend != nsISuspendedTypes::NONE_SUSPENDED);
|
||||
// TODO : implementation.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user