Bug 1190040 - Part 2: Teach the audio channel service how to not notify audio-playback, and do that when a media element has no audio track; r=padenot

This commit is contained in:
Ehsan Akhgari 2015-08-05 09:06:57 -04:00
parent 82215ebaac
commit ec9e9b5db2
9 changed files with 51 additions and 30 deletions

View File

@ -49,7 +49,7 @@ void
AudioChannelAgent::Shutdown()
{
if (mIsRegToService) {
NotifyStoppedPlaying();
NotifyStoppedPlaying(nsIAudioChannelAgent::AUDIO_AGENT_NOTIFY);
}
}
@ -127,7 +127,8 @@ AudioChannelAgent::InitInternal(nsIDOMWindow* aWindow, int32_t aChannelType,
return NS_OK;
}
NS_IMETHODIMP AudioChannelAgent::NotifyStartedPlaying(float *aVolume,
NS_IMETHODIMP AudioChannelAgent::NotifyStartedPlaying(uint32_t aNotifyPlayback,
float *aVolume,
bool* aMuted)
{
MOZ_ASSERT(aVolume);
@ -139,7 +140,7 @@ NS_IMETHODIMP AudioChannelAgent::NotifyStartedPlaying(float *aVolume,
return NS_ERROR_FAILURE;
}
service->RegisterAudioChannelAgent(this,
service->RegisterAudioChannelAgent(this, aNotifyPlayback,
static_cast<AudioChannel>(mAudioChannelType));
service->GetState(mWindow, mAudioChannelType, aVolume, aMuted);
@ -148,7 +149,7 @@ NS_IMETHODIMP AudioChannelAgent::NotifyStartedPlaying(float *aVolume,
return NS_OK;
}
NS_IMETHODIMP AudioChannelAgent::NotifyStoppedPlaying(void)
NS_IMETHODIMP AudioChannelAgent::NotifyStoppedPlaying(uint32_t aNotifyPlayback)
{
if (mAudioChannelType == AUDIO_AGENT_CHANNEL_ERROR ||
!mIsRegToService) {
@ -156,7 +157,7 @@ NS_IMETHODIMP AudioChannelAgent::NotifyStoppedPlaying(void)
}
nsRefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
service->UnregisterAudioChannelAgent(this);
service->UnregisterAudioChannelAgent(this, aNotifyPlayback);
mIsRegToService = false;
return NS_OK;
}

View File

@ -233,6 +233,7 @@ AudioChannelService::~AudioChannelService()
void
AudioChannelService::RegisterAudioChannelAgent(AudioChannelAgent* aAgent,
uint32_t aNotifyPlayback,
AudioChannel aChannel)
{
uint64_t windowID = aAgent->WindowID();
@ -253,7 +254,8 @@ AudioChannelService::RegisterAudioChannelAgent(AudioChannelAgent* aAgent,
}
// If this is the first agent for this window, we must notify the observers.
if (winData->mAgents.Length() == 1) {
if (aNotifyPlayback == nsIAudioChannelAgent::AUDIO_AGENT_NOTIFY &&
winData->mAgents.Length() == 1) {
nsRefPtr<MediaPlaybackRunnable> runnable =
new MediaPlaybackRunnable(aAgent->Window(), true /* active */);
NS_DispatchToCurrentThread(runnable);
@ -263,7 +265,8 @@ AudioChannelService::RegisterAudioChannelAgent(AudioChannelAgent* aAgent,
}
void
AudioChannelService::UnregisterAudioChannelAgent(AudioChannelAgent* aAgent)
AudioChannelService::UnregisterAudioChannelAgent(AudioChannelAgent* aAgent,
uint32_t aNotifyPlayback)
{
AudioChannelWindow* winData = GetWindowData(aAgent->WindowID());
if (!winData) {
@ -295,7 +298,8 @@ AudioChannelService::UnregisterAudioChannelAgent(AudioChannelAgent* aAgent)
#endif
// If this is the last agent for this window, we must notify the observers.
if (winData->mAgents.IsEmpty()) {
if (aNotifyPlayback == nsIAudioChannelAgent::AUDIO_AGENT_NOTIFY &&
winData->mAgents.IsEmpty()) {
nsRefPtr<MediaPlaybackRunnable> runnable =
new MediaPlaybackRunnable(aAgent->Window(), false /* active */);
NS_DispatchToCurrentThread(runnable);

View File

@ -49,13 +49,16 @@ public:
* Any audio channel agent that starts playing should register itself to
* this service, sharing the AudioChannel.
*/
void RegisterAudioChannelAgent(AudioChannelAgent* aAgent, AudioChannel aChannel);
void RegisterAudioChannelAgent(AudioChannelAgent* aAgent,
uint32_t aNotifyPlayback,
AudioChannel aChannel);
/**
* Any audio channel agent that stops playing should unregister itself to
* this service.
*/
void UnregisterAudioChannelAgent(AudioChannelAgent* aAgent);
void UnregisterAudioChannelAgent(AudioChannelAgent* aAgent,
uint32_t aNotifyPlayback);
/**
* Return the state to indicate this audioChannel for his window should keep

View File

@ -34,7 +34,7 @@ interface nsIAudioChannelAgentCallback : nsISupports
* 1. Changes to the playable status of this channel.
*/
[uuid(ee39a34b-a5c7-4b30-b1ac-cd64ceedef67)]
[uuid(62e0037c-9786-4b79-b986-27111f6e553b)]
interface nsIAudioChannelAgent : nsISupports
{
const long AUDIO_AGENT_CHANNEL_NORMAL = 0;
@ -52,6 +52,9 @@ interface nsIAudioChannelAgent : nsISupports
const long AUDIO_AGENT_STATE_MUTED = 1;
const long AUDIO_AGENT_STATE_FADED = 2;
const long AUDIO_AGENT_DONT_NOTIFY = 0;
const long AUDIO_AGENT_NOTIFY = 1;
/**
* Before init() is called, this returns AUDIO_AGENT_CHANNEL_ERROR.
*/
@ -98,6 +101,9 @@ interface nsIAudioChannelAgent : nsISupports
* Note: Gecko component SHOULD call this function first then start to
* play audio stream only when return value is true.
*
* @param notifyPlaying
* Whether to send audio-playback notifications, one of AUDIO_CHANNEL_NOTIFY
* or AUDIO_CHANNEL_DONT_NOTIFY.
*
* @return
* normal state: the agent has registered with audio channel service and
@ -107,15 +113,19 @@ interface nsIAudioChannelAgent : nsISupports
* faded state: the agent has registered with audio channel service the
* component should start playback as well as reducing the volume.
*/
void notifyStartedPlaying(out float volume, out bool muted);
void notifyStartedPlaying(in unsigned long notifyPlayback, out float volume, out bool muted);
/**
* Notify the agent we no longer want to play.
*
* @param notifyPlaying
* Whether to send audio-playback notifications, one of AUDIO_CHANNEL_NOTIFY
* or AUDIO_CHANNEL_DONT_NOTIFY.
*
* Note : even if notifyStartedPlaying() returned false, the agent would
* still be registered with the audio channel service and receive callbacks
* for status changes. So notifyStoppedPlaying must still eventually be
* called to unregister the agent with the channel service.
*/
void notifyStoppedPlaying();
void notifyStoppedPlaying(in unsigned long notifyPlayback);
};

View File

@ -1101,7 +1101,7 @@ nsDOMCameraControl::ReleaseAudioChannelAgent()
{
#ifdef MOZ_B2G
if (mAudioChannelAgent) {
mAudioChannelAgent->NotifyStoppedPlaying();
mAudioChannelAgent->NotifyStoppedPlaying(nsIAudioChannelAgent::AUDIO_AGENT_DONT_NOTIFY);
mAudioChannelAgent = nullptr;
}
#endif
@ -1137,7 +1137,8 @@ nsDOMCameraControl::NotifyRecordingStatusChange(const nsString& aMsg)
// Video recording doesn't output any sound, so it's not necessary to check canPlay.
float volume = 0.0;
bool muted = true;
rv = mAudioChannelAgent->NotifyStartedPlaying(&volume, &muted);
rv = mAudioChannelAgent->NotifyStartedPlaying(nsIAudioChannelAgent::AUDIO_AGENT_DONT_NOTIFY,
&volume, &muted);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}

View File

@ -195,7 +195,7 @@ FMRadio::Notify(const FMRadioEventType& aType)
DispatchTrustedEvent(NS_LITERAL_STRING("enabled"));
} else {
if (mAudioChannelAgentEnabled) {
mAudioChannelAgent->NotifyStoppedPlaying();
mAudioChannelAgent->NotifyStoppedPlaying(nsIAudioChannelAgent::AUDIO_AGENT_NOTIFY);
mAudioChannelAgentEnabled = false;
}
@ -457,7 +457,8 @@ FMRadio::EnableAudioChannelAgent()
float volume = 0.0;
bool muted = true;
mAudioChannelAgent->NotifyStartedPlaying(&volume, &muted);
mAudioChannelAgent->NotifyStartedPlaying(nsIAudioChannelAgent::AUDIO_AGENT_NOTIFY,
&volume, &muted);
WindowVolumeChanged(volume, muted);
mAudioChannelAgentEnabled = true;

View File

@ -4509,11 +4509,6 @@ void HTMLMediaElement::UpdateAudioChannelPlayingState()
void
HTMLMediaElement::NotifyAudioChannelAgent(bool aPlaying)
{
// Don't do anything if this element doesn't have any audio tracks.
if (!HasAudio()) {
return;
}
// Immediately check if this should go to the MSG instead of the normal
// media playback route.
WindowAudioCaptureChanged();
@ -4523,13 +4518,17 @@ HTMLMediaElement::NotifyAudioChannelAgent(bool aPlaying)
// this method has some content JS in its stack.
AutoNoJSAPI nojsapi;
// Don't notify playback if this element doesn't have any audio tracks.
uint32_t notify = HasAudio() ? nsIAudioChannelAgent::AUDIO_AGENT_NOTIFY :
nsIAudioChannelAgent::AUDIO_AGENT_DONT_NOTIFY;
if (aPlaying) {
float volume = 0.0;
bool muted = true;
mAudioChannelAgent->NotifyStartedPlaying(&volume, &muted);
mAudioChannelAgent->NotifyStartedPlaying(notify, &volume, &muted);
WindowVolumeChanged(volume, muted);
} else {
mAudioChannelAgent->NotifyStoppedPlaying();
mAudioChannelAgent->NotifyStoppedPlaying(notify);
mAudioChannelAgent = nullptr;
}
}

View File

@ -371,7 +371,7 @@ void
AudioDestinationNode::DestroyAudioChannelAgent()
{
if (mAudioChannelAgent && !Context()->IsOffline()) {
mAudioChannelAgent->NotifyStoppedPlaying();
mAudioChannelAgent->NotifyStoppedPlaying(nsIAudioChannelAgent::AUDIO_AGENT_NOTIFY);
mAudioChannelAgent = nullptr;
}
}
@ -605,7 +605,7 @@ AudioDestinationNode::CreateAudioChannelAgent()
}
if (mAudioChannelAgent) {
mAudioChannelAgent->NotifyStoppedPlaying();
mAudioChannelAgent->NotifyStoppedPlaying(nsIAudioChannelAgent::AUDIO_AGENT_NOTIFY);
}
mAudioChannelAgent = new AudioChannelAgent();
@ -698,13 +698,14 @@ AudioDestinationNode::InputMuted(bool aMuted)
}
if (aMuted) {
mAudioChannelAgent->NotifyStoppedPlaying();
mAudioChannelAgent->NotifyStoppedPlaying(nsIAudioChannelAgent::AUDIO_AGENT_NOTIFY);
return;
}
float volume = 0.0;
bool muted = true;
nsresult rv = mAudioChannelAgent->NotifyStartedPlaying(&volume, &muted);
nsresult rv = mAudioChannelAgent->NotifyStartedPlaying(nsIAudioChannelAgent::AUDIO_AGENT_NOTIFY,
&volume, &muted);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}

View File

@ -2423,14 +2423,15 @@ _setvalue(NPP npp, NPPVariable variable, void *result)
MOZ_ASSERT(agent);
if (isMuted) {
rv = agent->NotifyStoppedPlaying();
rv = agent->NotifyStoppedPlaying(nsIAudioChannelAgent::AUDIO_AGENT_NOTIFY);
if (NS_WARN_IF(NS_FAILED(rv))) {
return NPERR_NO_ERROR;
}
} else {
float volume = 0.0;
bool muted = true;
rv = agent->NotifyStartedPlaying(&volume, &muted);
rv = agent->NotifyStartedPlaying(nsIAudioChannelAgent::AUDIO_AGENT_NOTIFY,
&volume, &muted);
if (NS_WARN_IF(NS_FAILED(rv))) {
return NPERR_NO_ERROR;
}