Bug 1242874 - part4 : wrap the volume/mute/suspend for notifyStartedPlaying. draft
authorAlastor Wu <alwu@mozilla.com>
Tue, 03 May 2016 09:52:44 +0800
changeset 362708 b112e0da333bc115b69eef924c6a510df2108458
parent 362707 938674ab93ca0b502cde39c2e4a5bd4947a5c074
child 362709 d512589cc8e2ecfd7d1ca1ddafca8d45f2e02d86
push id17024
push useralwu@mozilla.com
push dateTue, 03 May 2016 01:54:01 +0000
bugs1242874
milestone49.0a1
Bug 1242874 - part4 : wrap the volume/mute/suspend for notifyStartedPlaying. MozReview-Commit-ID: 2FMfEVuODmu
dom/audiochannel/AudioChannelAgent.cpp
dom/audiochannel/nsIAudioChannelAgent.idl
dom/fmradio/FMRadio.cpp
dom/html/HTMLMediaElement.cpp
dom/media/webaudio/AudioDestinationNode.cpp
dom/media/webspeech/synth/nsSpeechTask.cpp
dom/plugins/base/nsNPAPIPlugin.cpp
dom/telephony/Telephony.cpp
--- a/dom/audiochannel/AudioChannelAgent.cpp
+++ b/dom/audiochannel/AudioChannelAgent.cpp
@@ -196,27 +196,21 @@ AudioChannelAgent::InitInternal(nsPIDOMW
   MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
          ("AudioChannelAgent, InitInternal, this = %p, type = %d, "
           "owner = %p, hasCallback = %d\n", this, mAudioChannelType,
           mWindow.get(), (!!mCallback || !!mWeakCallback)));
 
   return NS_OK;
 }
 
-NS_IMETHODIMP AudioChannelAgent::NotifyStartedPlaying(float *aVolume,
-                                                      bool* aMuted)
+NS_IMETHODIMP
+AudioChannelAgent::NotifyStartedPlaying(AudioPlaybackConfig* aConfig)
 {
-  MOZ_ASSERT(aVolume);
-  MOZ_ASSERT(aMuted);
-
-  // Window-less AudioChannelAgents are muted by default.
-  if (!mWindow) {
-    *aVolume = 0;
-    *aMuted = true;
-    return NS_OK;
+  if (NS_WARN_IF(!aConfig)) {
+    return NS_ERROR_FAILURE;
   }
 
   RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
   if (mAudioChannelType == AUDIO_AGENT_CHANNEL_ERROR ||
       service == nullptr || mIsRegToService) {
     return NS_ERROR_FAILURE;
   }
 
@@ -226,24 +220,23 @@ NS_IMETHODIMP AudioChannelAgent::NotifyS
   AudioPlaybackConfig config = service->GetMediaConfig(mWindow,
                                                        mAudioChannelType);
 
   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;
-
+  aConfig->SetConfig(config.mVolume, config.mMuted, config.mSuspend);
   mIsRegToService = true;
   return NS_OK;
 }
 
-NS_IMETHODIMP AudioChannelAgent::NotifyStoppedPlaying()
+NS_IMETHODIMP
+AudioChannelAgent::NotifyStoppedPlaying()
 {
   if (mAudioChannelType == AUDIO_AGENT_CHANNEL_ERROR ||
       !mIsRegToService) {
     return NS_ERROR_FAILURE;
   }
 
   MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
          ("AudioChannelAgent, NotifyStoppedPlaying, this = %p\n", this));
--- a/dom/audiochannel/nsIAudioChannelAgent.idl
+++ b/dom/audiochannel/nsIAudioChannelAgent.idl
@@ -50,16 +50,26 @@ interface nsISuspendedTypes : nsISupport
 
   const uint32_t NONE_SUSPENDED             = 0;
   const uint32_t SUSPENDED_PAUSE            = 1;
   const uint32_t SUSPENDED_BLOCK            = 2;
   const uint32_t SUSPENDED_PAUSE_DISPOSABLE = 3;
   const uint32_t SUSPENDED_STOP_DISPOSABLE  = 4;
 };
 
+%{C++
+namespace mozilla {
+namespace dom {
+// It's defined in dom/audiochannel/AudioChannelService.h.
+class AudioPlaybackConfig;
+}
+}
+%}
+[ptr] native AudioPlaybackConfig(mozilla::dom::AudioPlaybackConfig);
+
 [uuid(15c05894-408e-4798-b527-a8c32d9c5f8c)]
 interface nsIAudioChannelAgentCallback : nsISupports
 {
   /**
    * Notified when the window volume/mute is changed
    */
   void windowVolumeChanged(in float aVolume, in bool aMuted);
 
@@ -147,25 +157,20 @@ interface nsIAudioChannelAgent : nsISupp
   void initWithWeakCallback(in mozIDOMWindow window, in long channelType,
                             in nsIAudioChannelAgentCallback callback);
 
   /**
    * Notify the agent that we want to start playing.
    * Note: Gecko component SHOULD call this function first then start to
    *          play audio stream only when return value is true.
    *
-   * @return
-   *    normal state: the agent has registered with audio channel service and
-   *          the component should start playback.
-   *    muted state: the agent has registered with audio channel service but
-   *          the component should not start playback.
-   *    faded state: the agent has registered with audio channel service the
-   *          component should start playback as well as reducing the volume.
+   * @param config
+   *    It contains the playback related states (volume/mute/suspend)
    */
-  void notifyStartedPlaying(out float volume, out bool muted);
+  void notifyStartedPlaying(in AudioPlaybackConfig config);
 
   /**
    * Notify the agent we no longer want to play.
    *
    * 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.
--- a/dom/fmradio/FMRadio.cpp
+++ b/dom/fmradio/FMRadio.cpp
@@ -447,20 +447,24 @@ FMRadio::DisableRDS()
   return r.forget();
 }
 
 void
 FMRadio::EnableAudioChannelAgent()
 {
   NS_ENSURE_TRUE_VOID(mAudioChannelAgent);
 
-  float volume = 0.0;
-  bool muted = true;
-  mAudioChannelAgent->NotifyStartedPlaying(&volume, &muted);
-  WindowVolumeChanged(volume, muted);
+  AudioPlaybackConfig config;
+  nsresult rv = mAudioChannelAgent->NotifyStartedPlaying(&config);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return;
+  }
+
+  WindowVolumeChanged(config.mVolume, config.mMuted);
+  WindowSuspendChanged(config.mSuspend);
 
   mAudioChannelAgentEnabled = true;
 }
 
 NS_IMETHODIMP
 FMRadio::WindowVolumeChanged(float aVolume, bool aMuted)
 {
   // TODO : Not support to change volume now, so we just close it.
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -5056,20 +5056,24 @@ 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;
 
   if (aPlaying) {
-    float volume = 0.0;
-    bool muted = true;
-    mAudioChannelAgent->NotifyStartedPlaying(&volume, &muted);
-    WindowVolumeChanged(volume, muted);
+    AudioPlaybackConfig config;
+    nsresult rv = mAudioChannelAgent->NotifyStartedPlaying(&config);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return;
+    }
+
+    WindowVolumeChanged(config.mVolume, config.mMuted);
+    WindowSuspendChanged(config.mSuspend);
   } else {
     mAudioChannelAgent->NotifyStoppedPlaying();
     mAudioChannelAgent = nullptr;
   }
 }
 
 NS_IMETHODIMP
 HTMLMediaElement::WindowVolumeChanged(float aVolume, bool aMuted)
--- a/dom/media/webaudio/AudioDestinationNode.cpp
+++ b/dom/media/webaudio/AudioDestinationNode.cpp
@@ -659,20 +659,20 @@ AudioDestinationNode::InputMuted(bool aM
     CreateAudioChannelAgent();
   }
 
   if (aMuted) {
     mAudioChannelAgent->NotifyStoppedPlaying();
     return;
   }
 
-  float volume = 0.0;
-  bool muted = true;
-  nsresult rv = mAudioChannelAgent->NotifyStartedPlaying(&volume, &muted);
+  AudioPlaybackConfig config;
+  nsresult rv = mAudioChannelAgent->NotifyStartedPlaying(&config);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return;
   }
 
-  WindowVolumeChanged(volume, muted);
+  WindowVolumeChanged(config.mVolume, config.mMuted);
+  WindowSuspendChanged(config.mSuspend);
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/media/webspeech/synth/nsSpeechTask.cpp
+++ b/dom/media/webspeech/synth/nsSpeechTask.cpp
@@ -707,19 +707,25 @@ nsSpeechTask::CreateAudioChannelAgent()
   if (mAudioChannelAgent) {
     mAudioChannelAgent->NotifyStoppedPlaying();
   }
 
   mAudioChannelAgent = new AudioChannelAgent();
   mAudioChannelAgent->InitWithWeakCallback(mUtterance->GetOwner(),
                                            static_cast<int32_t>(AudioChannelService::GetDefaultAudioChannel()),
                                            this);
-  float volume = 0.0f;
-  bool muted = true;
-  mAudioChannelAgent->NotifyStartedPlaying(&volume, &muted);
+
+  AudioPlaybackConfig config;
+  nsresult rv = mAudioChannelAgent->NotifyStartedPlaying(&config);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return;
+  }
+
+  WindowVolumeChanged(config.mVolume, config.mMuted);
+  WindowSuspendChanged(config.mSuspend);
 }
 
 void
 nsSpeechTask::DestroyAudioChannelAgent()
 {
   if (mAudioChannelAgent) {
     mAudioChannelAgent->NotifyStoppedPlaying();
     mAudioChannelAgent = nullptr;
@@ -731,19 +737,21 @@ nsSpeechTask::WindowVolumeChanged(float 
 {
   SetAudioOutputVolume(aMuted ? 0.0 : mVolume * aVolume);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsSpeechTask::WindowSuspendChanged(nsSuspendedTypes aSuspend)
 {
-  if (aSuspend == nsISuspendedTypes::NONE_SUSPENDED) {
+  if (aSuspend == nsISuspendedTypes::NONE_SUSPENDED &&
+      mUtterance->mPaused) {
     Resume();
-  } else {
+  } else if (aSuspend != nsISuspendedTypes::NONE_SUSPENDED &&
+             !mUtterance->mPaused) {
     Pause();
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsSpeechTask::WindowAudioCaptureChanged(bool aCapture)
 {
--- a/dom/plugins/base/nsNPAPIPlugin.cpp
+++ b/dom/plugins/base/nsNPAPIPlugin.cpp
@@ -102,16 +102,17 @@ using mozilla::plugins::PluginModuleCont
 #include "android_npapi.h"
 #include "ANPBase.h"
 #include "AndroidBridge.h"
 #undef LOG
 #define LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args)
 #endif
 
 #include "nsIAudioChannelAgent.h"
+#include "AudioChannelService.h"
 
 using namespace mozilla;
 using namespace mozilla::plugins::parent;
 
 // We should make this const...
 static NPNetscapeFuncs sBrowserFuncs = {
   sizeof(sBrowserFuncs),
   (NP_VERSION_MAJOR << 8) + NP_VERSION_MINOR,
@@ -2284,24 +2285,29 @@ NPError
       MOZ_ASSERT(agent);
 
       if (isMuted) {
         rv = agent->NotifyStoppedPlaying();
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return NPERR_NO_ERROR;
         }
       } else {
-        float volume = 0.0;
-        bool muted = true;
-        rv = agent->NotifyStartedPlaying(&volume, &muted);
+
+        dom::AudioPlaybackConfig config;
+        rv = agent->NotifyStartedPlaying(&config);
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return NPERR_NO_ERROR;
         }
 
-        rv = inst->WindowVolumeChanged(volume, muted);
+        rv = inst->WindowVolumeChanged(config.mVolume, config.mMuted);
+        if (NS_WARN_IF(NS_FAILED(rv))) {
+          return NPERR_NO_ERROR;
+        }
+
+        rv = inst->WindowSuspendChanged(config.mSuspend);
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return NPERR_NO_ERROR;
         }
       }
 
       return NPERR_NO_ERROR;
     }
 
--- a/dom/telephony/Telephony.cpp
+++ b/dom/telephony/Telephony.cpp
@@ -556,35 +556,37 @@ Telephony::HandleAudioAgentState()
     mIsAudioStartPlaying = false;
     rv = mAudioAgent->NotifyStoppedPlaying();
     mAudioAgent = nullptr;
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   } else if (!activeCall.IsNull() && !mIsAudioStartPlaying) {
     mIsAudioStartPlaying = true;
-    float volume;
-    bool muted;
-    rv = mAudioAgent->NotifyStartedPlaying(&volume, &muted);
+    AudioPlaybackConfig config;
+    rv = mAudioAgent->NotifyStartedPlaying(&config);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
     // In B2G, the system app manages audio playback policy. If there is a new
     // sound want to be playback, it must wait for the permission from the
     // system app. It means that the sound would be muted first, and then be
     // unmuted. For telephony, the behaviors are hold() first, then resume().
     // However, the telephony service can't handle all these requests within a
     // short period. The telephony service would reject our resume request,
     // because the modem have not changed the call state yet. It causes that
     // the telephony can't be resumed. Therefore, we don't mute the telephony
     // at the beginning.
-    volume = 1.0;
-    muted = false;
-    rv = WindowVolumeChanged(volume, muted);
+    rv = WindowVolumeChanged(1.0, false);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+
+    rv = WindowSuspendChanged(config.mSuspend);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
   return NS_OK;
 }
 
 bool