AudioChannelService.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  4. * You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #ifndef mozilla_dom_audiochannelservice_h__
  6. #define mozilla_dom_audiochannelservice_h__
  7. #include "nsIAudioChannelService.h"
  8. #include "nsAutoPtr.h"
  9. #include "nsIObserver.h"
  10. #include "nsTObserverArray.h"
  11. #include "nsTArray.h"
  12. #include "AudioChannelAgent.h"
  13. #include "nsAttrValue.h"
  14. #include "mozilla/dom/AudioChannelBinding.h"
  15. #include "mozilla/Function.h"
  16. class nsIRunnable;
  17. class nsPIDOMWindowOuter;
  18. struct PRLogModuleInfo;
  19. namespace mozilla {
  20. namespace dom {
  21. class TabParent;
  22. #define NUMBER_OF_AUDIO_CHANNELS (uint32_t)AudioChannel::EndGuard_
  23. class AudioPlaybackConfig
  24. {
  25. public:
  26. AudioPlaybackConfig()
  27. : mVolume(1.0)
  28. , mMuted(false)
  29. , mSuspend(nsISuspendedTypes::NONE_SUSPENDED)
  30. {}
  31. AudioPlaybackConfig(float aVolume, bool aMuted, uint32_t aSuspended)
  32. : mVolume(aVolume)
  33. , mMuted(aMuted)
  34. , mSuspend(aSuspended)
  35. {}
  36. void SetConfig(float aVolume, bool aMuted, uint32_t aSuspended)
  37. {
  38. mVolume = aVolume;
  39. mMuted = aMuted;
  40. mSuspend = aSuspended;
  41. }
  42. float mVolume;
  43. bool mMuted;
  44. uint32_t mSuspend;
  45. };
  46. class AudioChannelService final : public nsIAudioChannelService
  47. , public nsIObserver
  48. {
  49. public:
  50. NS_DECL_ISUPPORTS
  51. NS_DECL_NSIOBSERVER
  52. NS_DECL_NSIAUDIOCHANNELSERVICE
  53. /**
  54. * eNotAudible : agent is not audible
  55. * eMaybeAudible : agent is not audible now, but it might be audible later
  56. * eAudible : agent is audible now
  57. */
  58. enum AudibleState : uint8_t {
  59. eNotAudible = 0,
  60. eMaybeAudible = 1,
  61. eAudible = 2
  62. };
  63. enum AudioCaptureState : bool {
  64. eCapturing = true,
  65. eNotCapturing = false
  66. };
  67. enum AudibleChangedReasons : uint32_t {
  68. eVolumeChanged = 0,
  69. eDataAudibleChanged = 1,
  70. ePauseStateChanged = 2
  71. };
  72. /**
  73. * Returns the AudioChannelServce singleton.
  74. * If AudioChannelServce is not exist, create and return new one.
  75. * Only to be called from main thread.
  76. */
  77. static already_AddRefed<AudioChannelService> GetOrCreate();
  78. static bool IsAudioChannelMutedByDefault();
  79. static PRLogModuleInfo* GetAudioChannelLog();
  80. static bool IsEnableAudioCompeting();
  81. /**
  82. * Any audio channel agent that starts playing should register itself to
  83. * this service, sharing the AudioChannel.
  84. */
  85. void RegisterAudioChannelAgent(AudioChannelAgent* aAgent,
  86. AudibleState aAudible);
  87. /**
  88. * Any audio channel agent that stops playing should unregister itself to
  89. * this service.
  90. */
  91. void UnregisterAudioChannelAgent(AudioChannelAgent* aAgent);
  92. /**
  93. * For nested iframes.
  94. */
  95. void RegisterTabParent(TabParent* aTabParent);
  96. void UnregisterTabParent(TabParent* aTabParent);
  97. /**
  98. * Return the state to indicate this audioChannel for his window should keep
  99. * playing/muted/suspended.
  100. */
  101. AudioPlaybackConfig GetMediaConfig(nsPIDOMWindowOuter* aWindow,
  102. uint32_t aAudioChannel) const;
  103. /**
  104. * Called this method when the audible state of the audio playback changed,
  105. * it would dispatch the playback event to observers which want to know the
  106. * actual audible state of the window.
  107. */
  108. void AudioAudibleChanged(AudioChannelAgent* aAgent,
  109. AudibleState aAudible,
  110. AudibleChangedReasons aReason);
  111. /* Methods for the BrowserElementAudioChannel */
  112. float GetAudioChannelVolume(nsPIDOMWindowOuter* aWindow, AudioChannel aChannel);
  113. void SetAudioChannelVolume(nsPIDOMWindowOuter* aWindow, AudioChannel aChannel,
  114. float aVolume);
  115. bool GetAudioChannelMuted(nsPIDOMWindowOuter* aWindow, AudioChannel aChannel);
  116. void SetAudioChannelMuted(nsPIDOMWindowOuter* aWindow, AudioChannel aChannel,
  117. bool aMuted);
  118. bool IsAudioChannelActive(nsPIDOMWindowOuter* aWindow, AudioChannel aChannel);
  119. /**
  120. * Return true if there is a telephony channel active in this process
  121. * or one of its subprocesses.
  122. */
  123. bool TelephonyChannelIsActive();
  124. /**
  125. * Return true if a normal or content channel is active for the given
  126. * process ID.
  127. */
  128. bool ProcessContentOrNormalChannelIsActive(uint64_t aChildID);
  129. /***
  130. * AudioChannelManager calls this function to notify the default channel used
  131. * to adjust volume when there is no any active channel. if aChannel is -1,
  132. * the default audio channel will be used. Otherwise aChannel is casted to
  133. * AudioChannel enum.
  134. */
  135. virtual void SetDefaultVolumeControlChannel(int32_t aChannel,
  136. bool aVisible);
  137. bool AnyAudioChannelIsActive();
  138. void RefreshAgentsVolume(nsPIDOMWindowOuter* aWindow);
  139. void RefreshAgentsSuspend(nsPIDOMWindowOuter* aWindow,
  140. nsSuspendedTypes aSuspend);
  141. void RefreshAgentsVolumeAndPropagate(AudioChannel aAudioChannel,
  142. nsPIDOMWindowOuter* aWindow);
  143. // This method needs to know the inner window that wants to capture audio. We
  144. // group agents per top outer window, but we can have multiple innerWindow per
  145. // top outerWindow (subiframes, etc.) and we have to identify all the agents
  146. // just for a particular innerWindow.
  147. void SetWindowAudioCaptured(nsPIDOMWindowOuter* aWindow,
  148. uint64_t aInnerWindowID,
  149. bool aCapture);
  150. static const nsAttrValue::EnumTable* GetAudioChannelTable();
  151. static AudioChannel GetAudioChannel(const nsAString& aString);
  152. static AudioChannel GetDefaultAudioChannel();
  153. static void GetAudioChannelString(AudioChannel aChannel, nsAString& aString);
  154. static void GetDefaultAudioChannelString(nsAString& aString);
  155. void Notify(uint64_t aWindowID);
  156. void ChildStatusReceived(uint64_t aChildID, bool aTelephonyChannel,
  157. bool aContentOrNormalChannel, bool aAnyChannel);
  158. private:
  159. AudioChannelService();
  160. ~AudioChannelService();
  161. void RefreshAgents(nsPIDOMWindowOuter* aWindow,
  162. mozilla::function<void(AudioChannelAgent*)> aFunc);
  163. static void CreateServiceIfNeeded();
  164. /**
  165. * Shutdown the singleton.
  166. */
  167. static void Shutdown();
  168. void MaybeSendStatusUpdate();
  169. bool ContentOrNormalChannelIsActive();
  170. /* Send the default-volume-channel-changed notification */
  171. void SetDefaultVolumeControlChannelInternal(int32_t aChannel,
  172. bool aVisible, uint64_t aChildID);
  173. void RefreshAgentsAudioFocusChanged(AudioChannelAgent* aAgent);
  174. class AudioChannelConfig final : public AudioPlaybackConfig
  175. {
  176. public:
  177. AudioChannelConfig()
  178. : AudioPlaybackConfig(1.0, IsAudioChannelMutedByDefault(),
  179. nsISuspendedTypes::NONE_SUSPENDED)
  180. , mNumberOfAgents(0)
  181. {}
  182. uint32_t mNumberOfAgents;
  183. };
  184. class AudioChannelWindow final
  185. {
  186. public:
  187. explicit AudioChannelWindow(uint64_t aWindowID)
  188. : mWindowID(aWindowID)
  189. , mIsAudioCaptured(false)
  190. , mOwningAudioFocus(!AudioChannelService::IsEnableAudioCompeting())
  191. {
  192. // Workaround for bug1183033, system channel type can always playback.
  193. mChannels[(int16_t)AudioChannel::System].mMuted = false;
  194. }
  195. void AudioFocusChanged(AudioChannelAgent* aNewPlayingAgent);
  196. void AudioAudibleChanged(AudioChannelAgent* aAgent,
  197. AudibleState aAudible,
  198. AudibleChangedReasons aReason);
  199. void AppendAgent(AudioChannelAgent* aAgent, AudibleState aAudible);
  200. void RemoveAgent(AudioChannelAgent* aAgent);
  201. uint64_t mWindowID;
  202. bool mIsAudioCaptured;
  203. AudioChannelConfig mChannels[NUMBER_OF_AUDIO_CHANNELS];
  204. // Raw pointer because the AudioChannelAgent must unregister itself.
  205. nsTObserverArray<AudioChannelAgent*> mAgents;
  206. nsTObserverArray<AudioChannelAgent*> mAudibleAgents;
  207. // Owning audio focus when the window starts playing audible sound, and
  208. // lose audio focus when other windows starts playing.
  209. bool mOwningAudioFocus;
  210. private:
  211. void AudioCapturedChanged(AudioChannelAgent* aAgent,
  212. AudioCaptureState aCapture);
  213. void AppendAudibleAgentIfNotContained(AudioChannelAgent* aAgent,
  214. AudibleChangedReasons aReason);
  215. void RemoveAudibleAgentIfContained(AudioChannelAgent* aAgent,
  216. AudibleChangedReasons aReason);
  217. void AppendAgentAndIncreaseAgentsNum(AudioChannelAgent* aAgent);
  218. void RemoveAgentAndReduceAgentsNum(AudioChannelAgent* aAgent);
  219. bool IsFirstAudibleAgent() const;
  220. bool IsLastAudibleAgent() const;
  221. void NotifyAudioAudibleChanged(nsPIDOMWindowOuter* aWindow,
  222. AudibleState aAudible,
  223. AudibleChangedReasons aReason);
  224. void NotifyChannelActive(uint64_t aWindowID, AudioChannel aChannel,
  225. bool aActive);
  226. void MaybeNotifyMediaBlocked(AudioChannelAgent* aAgent);
  227. void RequestAudioFocus(AudioChannelAgent* aAgent);
  228. // We need to do audio competing only when the new incoming agent started.
  229. void NotifyAudioCompetingChanged(AudioChannelAgent* aAgent);
  230. uint32_t GetCompetingBehavior(AudioChannelAgent* aAgent,
  231. int32_t aIncomingChannelType) const;
  232. bool IsAgentInvolvingInAudioCompeting(AudioChannelAgent* aAgent) const;
  233. bool IsAudioCompetingInSameTab() const;
  234. bool IsContainingPlayingAgent(AudioChannelAgent* aAgent) const;
  235. bool IsInactiveWindow() const;
  236. };
  237. AudioChannelWindow*
  238. GetOrCreateWindowData(nsPIDOMWindowOuter* aWindow);
  239. AudioChannelWindow*
  240. GetWindowData(uint64_t aWindowID) const;
  241. struct AudioChannelChildStatus final
  242. {
  243. explicit AudioChannelChildStatus(uint64_t aChildID)
  244. : mChildID(aChildID)
  245. , mActiveTelephonyChannel(false)
  246. , mActiveContentOrNormalChannel(false)
  247. {}
  248. uint64_t mChildID;
  249. bool mActiveTelephonyChannel;
  250. bool mActiveContentOrNormalChannel;
  251. };
  252. AudioChannelChildStatus*
  253. GetChildStatus(uint64_t aChildID) const;
  254. void
  255. RemoveChildStatus(uint64_t aChildID);
  256. nsTObserverArray<nsAutoPtr<AudioChannelWindow>> mWindows;
  257. nsTObserverArray<nsAutoPtr<AudioChannelChildStatus>> mPlayingChildren;
  258. // Raw pointers because TabParents must unregister themselves.
  259. nsTArray<TabParent*> mTabParents;
  260. nsCOMPtr<nsIRunnable> mRunnable;
  261. uint64_t mDefChannelChildID;
  262. // These boolean are used to know if we have to send an status update to the
  263. // service running in the main process.
  264. bool mTelephonyChannel;
  265. bool mContentOrNormalChannel;
  266. bool mAnyChannel;
  267. // This is needed for IPC comunication between
  268. // AudioChannelServiceChild and this class.
  269. friend class ContentParent;
  270. friend class ContentChild;
  271. };
  272. } // namespace dom
  273. } // namespace mozilla
  274. #endif