author Chris Pearce <>
Mon, 14 Sep 2015 16:24:36 +1200
changeset 583904 0dfe11de72dc284c4261571950600883073842a0
parent 539281 6010b4d8d5e01425cedccfdcb832792f5e127324
permissions -rw-r--r--
[mq]: channel-service-activated.patch

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at */

#ifndef mozilla_dom_audiochannelservice_h__
#define mozilla_dom_audiochannelservice_h__

#include "nsIAudioChannelService.h"
#include "nsAutoPtr.h"
#include "nsIObserver.h"
#include "nsTObserverArray.h"
#include "nsTArray.h"

#include "AudioChannelAgent.h"
#include "nsAttrValue.h"
#include "mozilla/dom/AudioChannelBinding.h"

class nsIRunnable;
class nsPIDOMWindow;

namespace mozilla {
namespace dom {
class SpeakerManagerService;

#define NUMBER_OF_AUDIO_CHANNELS (uint32_t)AudioChannel::EndGuard_

class AudioChannelService final : public nsIAudioChannelService
                                , public nsIObserver

   * Returns the AudioChannelServce singleton.
   * If AudioChannelServce is not exist, create and return new one.
   * Only to be called from main thread.
  static already_AddRefed<AudioChannelService> GetOrCreate();

  static bool IsAudioChannelMutedByDefault();

  void RegisterAudioChannelAgent(AudioChannelAgent* aAgent);
  void UnregisterAudioChannelAgent(AudioChannelAgent* aAgent);

   * Any audio channel agent that starts playing should register itself to
   * this service, sharing the AudioChannel.
  void NotifyPlaybackStarted(AudioChannelAgent* aAgent,
                             uint32_t aNotifyPlayback,
                             AudioChannel aChannel);

   * Any audio channel agent that stops playing should unregister itself to
   * this service.
  void NotifyPlaybackStopped(AudioChannelAgent* aAgent,
                             uint32_t aNotifyPlayback);

   * Return the state to indicate this audioChannel for his window should keep
   * playing/muted.
  void GetState(nsPIDOMWindow* aWindow, uint32_t aChannel,
                float* aVolume, bool* aMuted, bool* aBlocked);

  /* Methods for the BrowserElementAudioChannel */
  float GetAudioChannelVolume(nsPIDOMWindow* aWindow, AudioChannel aChannel);

  void SetAudioChannelVolume(nsPIDOMWindow* aWindow, AudioChannel aChannel,
                             float aVolume);

  bool GetAudioChannelMuted(nsPIDOMWindow* aWindow, AudioChannel aChannel);

  void SetAudioChannelMuted(nsPIDOMWindow* aWindow, AudioChannel aChannel,
                            bool aMuted);

  bool IsAudioChannelActive(nsPIDOMWindow* aWindow, AudioChannel aChannel);

   * Return true if there is a telephony channel active in this process
   * or one of its subprocesses.
  bool TelephonyChannelIsActive();

   * Return true if a normal or content channel is active for the given
   * process ID.
  bool ProcessContentOrNormalChannelIsActive(uint64_t aChildID);

   * AudioChannelManager calls this function to notify the default channel used
   * to adjust volume when there is no any active channel. if aChannel is -1,
   * the default audio channel will be used. Otherwise aChannel is casted to
   * AudioChannel enum.
  virtual void SetDefaultVolumeControlChannel(int32_t aChannel,
                                              bool aVisible);

  bool AnyAudioChannelIsActive();

  void RefreshAgentsVolume(nsPIDOMWindow* aWindow);

  // This method needs to know the inner window that wants to capture audio. We
  // group agents per top outer window, but we can have multiple innerWindow per
  // top outerWindow (subiframes, etc.) and we have to identify all the agents
  // just for a particular innerWindow.
  void RefreshAgentsCapture(nsPIDOMWindow* aWindow,
                            uint64_t aInnerWindowID);

  void RefreshAgentsPlaybackBlocked(nsPIDOMWindow* aWindow);

  void RegisterSpeakerManager(SpeakerManagerService* aSpeakerManager)
    if (!mSpeakerManager.Contains(aSpeakerManager)) {

  void UnregisterSpeakerManager(SpeakerManagerService* aSpeakerManager)

  static const nsAttrValue::EnumTable* GetAudioChannelTable();
  static AudioChannel GetAudioChannel(const nsAString& aString);
  static AudioChannel GetDefaultAudioChannel();
  static void GetAudioChannelString(AudioChannel aChannel, nsAString& aString);
  static void GetDefaultAudioChannelString(nsAString& aString);

  void Notify(uint64_t aWindowID);

  void ChildStatusReceived(uint64_t aChildID, bool aTelephonyChannel,
                           bool aContentOrNormalChannel, bool aAnyChannel);


  static void CreateServiceIfNeeded();

   * Shutdown the singleton.
  static void Shutdown();

  void MaybeSendStatusUpdate();

  bool ContentOrNormalChannelIsActive();

  /* Send the default-volume-channel-changed notification */
  void SetDefaultVolumeControlChannelInternal(int32_t aChannel,
                                              bool aVisible, uint64_t aChildID);

  struct AudioChannelConfig final
      : mVolume(1.0)
      , mMuted(IsAudioChannelMutedByDefault())
      , mNumberOfAgents(0)

    float mVolume;
    bool mMuted;

    uint32_t mNumberOfAgents;

  struct AudioChannelWindow final
    explicit AudioChannelWindow(uint64_t aWindowID)
      : mWindowID(aWindowID)
      , mNotifyCount(0)

    uint64_t mWindowID;
    AudioChannelConfig mChannels[NUMBER_OF_AUDIO_CHANNELS];

    // Raw pointer because the AudioChannelAgent must unregister itself.
    nsTObserverArray<AudioChannelAgent*> mAgents;

    int32_t mNotifyCount;

  GetOrCreateWindowData(nsPIDOMWindow* aWindow);

  GetWindowData(uint64_t aWindowID) const;

  struct AudioChannelChildStatus final
    explicit AudioChannelChildStatus(uint64_t aChildID)
      : mChildID(aChildID)
      , mActiveTelephonyChannel(false)
      , mActiveContentOrNormalChannel(false)

    uint64_t mChildID;
    bool mActiveTelephonyChannel;
    bool mActiveContentOrNormalChannel;

  GetChildStatus(uint64_t aChildID) const;

  RemoveChildStatus(uint64_t aChildID);

  nsTObserverArray<nsAutoPtr<AudioChannelWindow>> mWindows;

  nsTObserverArray<nsAutoPtr<AudioChannelChildStatus>> mPlayingChildren;

  nsTArray<SpeakerManagerService*>  mSpeakerManager;

  nsCOMPtr<nsIRunnable> mRunnable;

  uint64_t mDefChannelChildID;

  // These boolean are used to know if we have to send an status update to the
  // service running in the main process.
  bool mTelephonyChannel;
  bool mContentOrNormalChannel;
  bool mAnyChannel;

  // This is needed for IPC comunication between
  // AudioChannelServiceChild and this class.
  friend class ContentParent;
  friend class ContentChild;

} // namespace dom
} // namespace mozilla