michael@0: /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ michael@0: /* vim: set ts=2 et sw=2 tw=80: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef mozilla_dom_audiochannelservice_h__ michael@0: #define mozilla_dom_audiochannelservice_h__ michael@0: michael@0: #include "nsAutoPtr.h" michael@0: #include "nsIObserver.h" michael@0: #include "nsTArray.h" michael@0: #include "nsITimer.h" michael@0: michael@0: #include "AudioChannelCommon.h" michael@0: #include "AudioChannelAgent.h" michael@0: #include "nsAttrValue.h" michael@0: #include "nsClassHashtable.h" michael@0: #include "mozilla/dom/AudioChannelBinding.h" michael@0: michael@0: class nsPIDOMWindow; michael@0: michael@0: namespace mozilla { michael@0: namespace dom { michael@0: #ifdef MOZ_WIDGET_GONK michael@0: class SpeakerManagerService; michael@0: #endif michael@0: class AudioChannelService michael@0: : public nsIObserver michael@0: , public nsITimerCallback michael@0: { michael@0: public: michael@0: NS_DECL_ISUPPORTS michael@0: NS_DECL_NSIOBSERVER michael@0: NS_DECL_NSITIMERCALLBACK michael@0: michael@0: /** michael@0: * Returns the AudioChannelServce singleton. Only to be called from main michael@0: * thread. michael@0: * michael@0: * @return NS_OK on proper assignment, NS_ERROR_FAILURE otherwise. michael@0: */ michael@0: static AudioChannelService* GetAudioChannelService(); michael@0: michael@0: /** michael@0: * Shutdown the singleton. michael@0: */ michael@0: static void Shutdown(); michael@0: michael@0: /** michael@0: * Any audio channel agent that starts playing should register itself to michael@0: * this service, sharing the AudioChannel. michael@0: */ michael@0: virtual void RegisterAudioChannelAgent(AudioChannelAgent* aAgent, michael@0: AudioChannel aChannel, michael@0: bool aWithVideo); michael@0: michael@0: /** michael@0: * Any audio channel agent that stops playing should unregister itself to michael@0: * this service. michael@0: */ michael@0: virtual void UnregisterAudioChannelAgent(AudioChannelAgent* aAgent); michael@0: michael@0: /** michael@0: * Return the state to indicate this agent should keep playing/ michael@0: * fading volume/muted. michael@0: */ michael@0: virtual AudioChannelState GetState(AudioChannelAgent* aAgent, michael@0: bool aElementHidden); michael@0: michael@0: /** michael@0: * Return true if there is a content channel active in this process michael@0: * or one of its subprocesses. michael@0: */ michael@0: virtual bool ContentOrNormalChannelIsActive(); michael@0: michael@0: /** michael@0: * Return true if a normal or content channel is active for the given michael@0: * process ID. michael@0: */ michael@0: virtual bool ProcessContentOrNormalChannelIsActive(uint64_t aChildID); michael@0: michael@0: /*** michael@0: * AudioChannelManager calls this function to notify the default channel used michael@0: * to adjust volume when there is no any active channel. if aChannel is -1, michael@0: * the default audio channel will be used. Otherwise aChannel is casted to michael@0: * AudioChannel enum. michael@0: */ michael@0: virtual void SetDefaultVolumeControlChannel(int32_t aChannel, michael@0: bool aHidden); michael@0: michael@0: bool AnyAudioChannelIsActive(); michael@0: michael@0: void RefreshAgentsVolume(nsPIDOMWindow* aWindow); michael@0: michael@0: #ifdef MOZ_WIDGET_GONK michael@0: void RegisterSpeakerManager(SpeakerManagerService* aSpeakerManager) michael@0: { michael@0: if (!mSpeakerManager.Contains(aSpeakerManager)) { michael@0: mSpeakerManager.AppendElement(aSpeakerManager); michael@0: } michael@0: } michael@0: michael@0: void UnregisterSpeakerManager(SpeakerManagerService* aSpeakerManager) michael@0: { michael@0: mSpeakerManager.RemoveElement(aSpeakerManager); michael@0: } michael@0: #endif michael@0: michael@0: static const nsAttrValue::EnumTable* GetAudioChannelTable(); michael@0: static AudioChannel GetAudioChannel(const nsAString& aString); michael@0: static AudioChannel GetDefaultAudioChannel(); michael@0: static void GetAudioChannelString(AudioChannel aChannel, nsAString& aString); michael@0: static void GetDefaultAudioChannelString(nsAString& aString); michael@0: michael@0: protected: michael@0: void Notify(); michael@0: michael@0: /** michael@0: * Send the audio-channel-changed notification for the given process ID if michael@0: * needed. michael@0: */ michael@0: void SendAudioChannelChangedNotification(uint64_t aChildID); michael@0: michael@0: /* Register/Unregister IPC types: */ michael@0: void RegisterType(AudioChannel aChannel, uint64_t aChildID, bool aWithVideo); michael@0: void UnregisterType(AudioChannel aChannel, bool aElementHidden, michael@0: uint64_t aChildID, bool aWithVideo); michael@0: void UnregisterTypeInternal(AudioChannel aChannel, bool aElementHidden, michael@0: uint64_t aChildID, bool aWithVideo); michael@0: michael@0: AudioChannelState GetStateInternal(AudioChannel aChannel, uint64_t aChildID, michael@0: bool aElementHidden, michael@0: bool aElementWasHidden); michael@0: michael@0: /* Update the internal type value following the visibility changes */ michael@0: void UpdateChannelType(AudioChannel aChannel, uint64_t aChildID, michael@0: bool aElementHidden, bool aElementWasHidden); michael@0: michael@0: /* Send the default-volume-channel-changed notification */ michael@0: void SetDefaultVolumeControlChannelInternal(int32_t aChannel, michael@0: bool aHidden, uint64_t aChildID); michael@0: michael@0: AudioChannelService(); michael@0: virtual ~AudioChannelService(); michael@0: michael@0: enum AudioChannelInternalType { michael@0: AUDIO_CHANNEL_INT_NORMAL = 0, michael@0: AUDIO_CHANNEL_INT_NORMAL_HIDDEN, michael@0: AUDIO_CHANNEL_INT_CONTENT, michael@0: AUDIO_CHANNEL_INT_CONTENT_HIDDEN, michael@0: AUDIO_CHANNEL_INT_NOTIFICATION, michael@0: AUDIO_CHANNEL_INT_NOTIFICATION_HIDDEN, michael@0: AUDIO_CHANNEL_INT_ALARM, michael@0: AUDIO_CHANNEL_INT_ALARM_HIDDEN, michael@0: AUDIO_CHANNEL_INT_TELEPHONY, michael@0: AUDIO_CHANNEL_INT_TELEPHONY_HIDDEN, michael@0: AUDIO_CHANNEL_INT_RINGER, michael@0: AUDIO_CHANNEL_INT_RINGER_HIDDEN, michael@0: AUDIO_CHANNEL_INT_PUBLICNOTIFICATION, michael@0: AUDIO_CHANNEL_INT_PUBLICNOTIFICATION_HIDDEN, michael@0: AUDIO_CHANNEL_INT_LAST michael@0: }; michael@0: michael@0: bool ChannelsActiveWithHigherPriorityThan(AudioChannelInternalType aType); michael@0: michael@0: bool CheckVolumeFadedCondition(AudioChannelInternalType aType, michael@0: bool aElementHidden); michael@0: michael@0: AudioChannelInternalType GetInternalType(AudioChannel aChannel, michael@0: bool aElementHidden); michael@0: michael@0: class AudioChannelAgentData { michael@0: public: michael@0: AudioChannelAgentData(AudioChannel aChannel, michael@0: bool aElementHidden, michael@0: AudioChannelState aState, michael@0: bool aWithVideo) michael@0: : mChannel(aChannel) michael@0: , mElementHidden(aElementHidden) michael@0: , mState(aState) michael@0: , mWithVideo(aWithVideo) michael@0: {} michael@0: michael@0: AudioChannel mChannel; michael@0: bool mElementHidden; michael@0: AudioChannelState mState; michael@0: const bool mWithVideo; michael@0: }; michael@0: michael@0: static PLDHashOperator michael@0: NotifyEnumerator(AudioChannelAgent* aAgent, michael@0: AudioChannelAgentData* aData, void *aUnused); michael@0: michael@0: static PLDHashOperator michael@0: RefreshAgentsVolumeEnumerator(AudioChannelAgent* aAgent, michael@0: AudioChannelAgentData* aUnused, michael@0: void *aPtr); michael@0: michael@0: static PLDHashOperator michael@0: CountWindowEnumerator(AudioChannelAgent* aAgent, michael@0: AudioChannelAgentData* aUnused, michael@0: void *aPtr); michael@0: michael@0: // This returns the number of agents from this aWindow. michael@0: uint32_t CountWindow(nsIDOMWindow* aWindow); michael@0: michael@0: nsClassHashtable< nsPtrHashKey, AudioChannelAgentData > mAgents; michael@0: #ifdef MOZ_WIDGET_GONK michael@0: nsTArray mSpeakerManager; michael@0: #endif michael@0: nsTArray mChannelCounters[AUDIO_CHANNEL_INT_LAST]; michael@0: michael@0: int32_t mCurrentHigherChannel; michael@0: int32_t mCurrentVisibleHigherChannel; michael@0: michael@0: nsTArray mWithVideoChildIDs; michael@0: michael@0: // mPlayableHiddenContentChildID stores the ChildID of the process which can michael@0: // play content channel(s) in the background. michael@0: // A background process contained content channel(s) will become playable: michael@0: // 1. When this background process registers its content channel(s) in michael@0: // AudioChannelService and there is no foreground process with registered michael@0: // content channel(s). michael@0: // 2. When this process goes from foreground into background and there is michael@0: // no foreground process with registered content channel(s). michael@0: // A background process contained content channel(s) will become non-playable: michael@0: // 1. When there is a foreground process registering its content channel(s) michael@0: // in AudioChannelService. michael@0: // ps. Currently this condition is never satisfied because the default value michael@0: // of visibility status of each channel during registering is hidden = true. michael@0: // 2. When there is a process with registered content channel(s) goes from michael@0: // background into foreground. michael@0: // 3. When this process unregisters all hidden content channels. michael@0: // 4. When this process shuts down. michael@0: uint64_t mPlayableHiddenContentChildID; michael@0: michael@0: bool mDisabled; michael@0: michael@0: nsCOMPtr mDeferTelChannelTimer; michael@0: bool mTimerElementHidden; michael@0: uint64_t mTimerChildID; michael@0: michael@0: uint64_t mDefChannelChildID; michael@0: michael@0: // This is needed for IPC comunication between michael@0: // AudioChannelServiceChild and this class. michael@0: friend class ContentParent; michael@0: friend class ContentChild; michael@0: }; michael@0: michael@0: } // namespace dom michael@0: } // namespace mozilla michael@0: michael@0: #endif