/* -*- 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 http://mozilla.org/MPL/2.0/. */ #ifndef mozilla_dom_audiochannelservice_h__ #define mozilla_dom_audiochannelservice_h__ #include "nsIAudioChannelService.h" #include "nsAutoPtr.h" #include "nsIObserver.h" #include "nsTArray.h" #include "AudioChannelAgent.h" #include "nsAttrValue.h" #include "nsClassHashtable.h" #include "mozilla/dom/AudioChannelBinding.h" class nsIRunnable; class nsPIDOMWindow; namespace mozilla { namespace dom { #ifdef MOZ_WIDGET_GONK class SpeakerManagerService; #endif #define NUMBER_OF_AUDIO_CHANNELS (uint32_t)AudioChannel::Publicnotification + 1 class AudioChannelService final : public nsIAudioChannelService , public nsIObserver { public: NS_DECL_ISUPPORTS NS_DECL_NSIOBSERVER NS_DECL_NSIAUDIOCHANNELSERVICE /** * Returns the AudioChannelServce singleton. * If AudioChannelServce is not exist, create and return new one. * Only to be called from main thread. */ static already_AddRefed GetOrCreate(); /** * Shutdown the singleton. */ static void Shutdown(); /** * Any audio channel agent that starts playing should register itself to * this service, sharing the AudioChannel. */ void RegisterAudioChannelAgent(AudioChannelAgent* aAgent, AudioChannel aChannel); /** * Any audio channel agent that stops playing should unregister itself to * this service. */ void UnregisterAudioChannelAgent(AudioChannelAgent* aAgent); /** * 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); /* 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); #ifdef MOZ_WIDGET_GONK void RegisterSpeakerManager(SpeakerManagerService* aSpeakerManager) { if (!mSpeakerManager.Contains(aSpeakerManager)) { mSpeakerManager.AppendElement(aSpeakerManager); } } void UnregisterSpeakerManager(SpeakerManagerService* aSpeakerManager) { mSpeakerManager.RemoveElement(aSpeakerManager); } #endif 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); private: AudioChannelService(); ~AudioChannelService(); void MaybeSendStatusUpdate(); bool ContentOrNormalChannelIsActive(); /* Send the default-volume-channel-changed notification */ void SetDefaultVolumeControlChannelInternal(int32_t aChannel, bool aVisible, uint64_t aChildID); struct AudioChannelConfig final { AudioChannelConfig() : mVolume(1.0) , mMuted(false) , mNumberOfAgents(0) {} float mVolume; bool mMuted; uint32_t mNumberOfAgents; }; struct AudioChannelWindow final { AudioChannelConfig mChannels[NUMBER_OF_AUDIO_CHANNELS]; nsClassHashtable, AudioChannel> mAgents; }; AudioChannelWindow& GetOrCreateWindowData(nsPIDOMWindow* aWindow); static PLDHashOperator TelephonyChannelIsActiveEnumerator(const uint64_t& aWindowID, nsAutoPtr& aWinData, void *aPtr); static PLDHashOperator ContentOrNormalChannelIsActiveEnumerator( const uint64_t& aWindowID, nsAutoPtr& aWinData, void *aPtr); static PLDHashOperator AnyAudioChannelIsActiveEnumerator(const uint64_t& aWindowID, nsAutoPtr& aWinData, void *aPtr); static PLDHashOperator RefreshAgentsVolumeEnumerator(AudioChannelAgent* aAgent, AudioChannel* aUnused, void *aPtr); static PLDHashOperator NotifyEnumerator(AudioChannelAgent* aAgent, AudioChannel* aAudioChannel, void* aUnused); nsClassHashtable mWindows; struct AudioChannelChildStatus final { AudioChannelChildStatus() : mActiveTelephonyChannel(false) , mActiveContentOrNormalChannel(false) {} bool mActiveTelephonyChannel; bool mActiveContentOrNormalChannel; }; static PLDHashOperator TelephonyChannelIsActiveInChildrenEnumerator( const uint64_t& aChildID, nsAutoPtr& aData, void *aPtr); nsClassHashtable mPlayingChildren; #ifdef MOZ_WIDGET_GONK nsTArray mSpeakerManager; #endif bool mDisabled; nsCOMPtr 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 #endif