Skip to content

Commit

Permalink
Bug 805333 part 1 - AudioChannelService, r=kinetik, a=blocking-basecamp
Browse files Browse the repository at this point in the history
  • Loading branch information
bakulf committed Dec 4, 2012
1 parent bc88272 commit e867518
Show file tree
Hide file tree
Showing 6 changed files with 282 additions and 4 deletions.
187 changes: 187 additions & 0 deletions dom/audiochannel/AudioChannelService.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=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/. */

#include "AudioChannelService.h"

#include "base/basictypes.h"

#include "mozilla/Services.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/unused.h"
#include "mozilla/Util.h"

#include "mozilla/dom/ContentParent.h"

#include "base/basictypes.h"

#include "nsThreadUtils.h"

using namespace mozilla;
using namespace mozilla::dom;

StaticRefPtr<AudioChannelService> gAudioChannelService;

// static
AudioChannelService*
AudioChannelService::GetAudioChannelService()
{
MOZ_ASSERT(NS_IsMainThread());

// If we already exist, exit early
if (gAudioChannelService) {
return gAudioChannelService;
}

// Create new instance, register, return
nsRefPtr<AudioChannelService> service = new AudioChannelService();
NS_ENSURE_TRUE(service, nullptr);

gAudioChannelService = service;
return gAudioChannelService;
}

void
AudioChannelService::Shutdown()
{
if (gAudioChannelService) {
delete gAudioChannelService;
gAudioChannelService = nullptr;
}
}

NS_IMPL_ISUPPORTS0(AudioChannelService)

AudioChannelService::AudioChannelService()
{
mChannelCounters = new int32_t[AUDIO_CHANNEL_PUBLICNOTIFICATION+1];

for (int i = AUDIO_CHANNEL_NORMAL;
i <= AUDIO_CHANNEL_PUBLICNOTIFICATION;
++i) {
mChannelCounters[i] = 0;
}

// Creation of the hash table.
mMediaElements.Init();
}

AudioChannelService::~AudioChannelService()
{
delete [] mChannelCounters;
}

void
AudioChannelService::RegisterMediaElement(nsHTMLMediaElement* aMediaElement,
AudioChannelType aType)
{
mMediaElements.Put(aMediaElement, aType);
mChannelCounters[aType]++;

// In order to avoid race conditions, it's safer to notify any existing
// media element any time a new one is registered.
Notify();
}

void
AudioChannelService::UnregisterMediaElement(nsHTMLMediaElement* aMediaElement)
{
AudioChannelType type;
if (!mMediaElements.Get(aMediaElement, &type)) {
return;
}

mMediaElements.Remove(aMediaElement);

mChannelCounters[type]--;
MOZ_ASSERT(mChannelCounters[type] >= 0);

// In order to avoid race conditions, it's safer to notify any existing
// media element any time a new one is registered.
Notify();
}

bool
AudioChannelService::GetMuted(AudioChannelType aType, bool aElementHidden)
{
// We are not visible, maybe we have to mute:
if (aElementHidden) {
switch (aType) {
case AUDIO_CHANNEL_NORMAL:
return true;

case AUDIO_CHANNEL_CONTENT:
// TODO: this should work per apps
if (mChannelCounters[AUDIO_CHANNEL_CONTENT] > 1)
return true;
break;

case AUDIO_CHANNEL_NOTIFICATION:
case AUDIO_CHANNEL_ALARM:
case AUDIO_CHANNEL_TELEPHONY:
case AUDIO_CHANNEL_PUBLICNOTIFICATION:
// Nothing to do
break;
}
}

// Priorities:
switch (aType) {
case AUDIO_CHANNEL_NORMAL:
case AUDIO_CHANNEL_CONTENT:
return !!mChannelCounters[AUDIO_CHANNEL_NOTIFICATION] ||
!!mChannelCounters[AUDIO_CHANNEL_ALARM] ||
!!mChannelCounters[AUDIO_CHANNEL_TELEPHONY] ||
!!mChannelCounters[AUDIO_CHANNEL_PUBLICNOTIFICATION];

case AUDIO_CHANNEL_NOTIFICATION:
case AUDIO_CHANNEL_ALARM:
case AUDIO_CHANNEL_TELEPHONY:
return ChannelsActiveWithHigherPriorityThan(aType);

case AUDIO_CHANNEL_PUBLICNOTIFICATION:
return false;
}

return false;
}


static PLDHashOperator
NotifyEnumerator(nsHTMLMediaElement* aElement,
AudioChannelType aType, void* aData)
{
if (aElement) {
// TODO: this part will be cover by a different patch.
// aElement->NotifyAudioChannelStateChanged();
}
return PL_DHASH_NEXT;
}

void
AudioChannelService::Notify()
{
MOZ_ASSERT(NS_IsMainThread());

// Notify any media element for the main process.
mMediaElements.EnumerateRead(NotifyEnumerator, nullptr);
}

bool
AudioChannelService::ChannelsActiveWithHigherPriorityThan(AudioChannelType aType)
{
for (int i = AUDIO_CHANNEL_PUBLICNOTIFICATION;
i != AUDIO_CHANNEL_CONTENT; --i) {
if (i == aType) {
return false;
}

if (mChannelCounters[i]) {
return true;
}
}

return false;
}
70 changes: 70 additions & 0 deletions dom/audiochannel/AudioChannelService.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=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 "nsAutoPtr.h"
#include "nsISupports.h"

#include "AudioChannelCommon.h"
#include "nsHTMLMediaElement.h"

namespace mozilla {
namespace dom {

class AudioChannelService : public nsISupports
{
public:
NS_DECL_ISUPPORTS

/**
* Returns the AudioChannelServce singleton. Only to be called from main thread.
* @return NS_OK on proper assignment, NS_ERROR_FAILURE otherwise.
*/
static AudioChannelService*
GetAudioChannelService();

/**
* Shutdown the singleton.
*/
static void Shutdown();

/**
* Any MediaElement that starts playing should register itself to
* this service, sharing the AudioChannelType.
*/
void RegisterMediaElement(nsHTMLMediaElement* aMediaElement,
AudioChannelType aType);

/**
* Any MediaElement that stops playing should unregister itself to
* this service.
*/
void UnregisterMediaElement(nsHTMLMediaElement* aMediaElement);

/**
* Return true if this type should be muted.
*/
virtual bool GetMuted(AudioChannelType aType, bool aElementHidden);

void Notify();

protected:
AudioChannelService();
virtual ~AudioChannelService();

bool ChannelsActiveWithHigherPriorityThan(AudioChannelType aType);

nsDataHashtable< nsPtrHashKey<nsHTMLMediaElement>, AudioChannelType > mMediaElements;

int32_t* mChannelCounters;
};

} // namespace dom
} // namespace mozilla

#endif
7 changes: 6 additions & 1 deletion dom/audiochannel/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,12 @@ EXPORTS_NAMESPACES = \
mozilla/dom \
$(NULL)

EXPORTS = AudioChannelCommon.h
EXPORTS = AudioChannelService.h \
AudioChannelCommon.h

CPPSRCS += \
AudioChannelService.cpp \
$(NULL)

include $(topsrcdir)/config/config.mk
include $(topsrcdir)/ipc/chromium/chromium-config.mk
Expand Down
2 changes: 2 additions & 0 deletions layout/build/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ SHARED_LIBRARY_LIBS = \
$(DEPTH)/dom/src/storage/$(LIB_PREFIX)jsdomstorage_s.$(LIB_SUFFIX) \
$(DEPTH)/dom/src/offline/$(LIB_PREFIX)jsdomoffline_s.$(LIB_SUFFIX) \
$(DEPTH)/dom/src/geolocation/$(LIB_PREFIX)jsdomgeolocation_s.$(LIB_SUFFIX) \
$(DEPTH)/dom/audiochannel/$(LIB_PREFIX)domaudiochannel_s.$(LIB_SUFFIX) \
$(DEPTH)/dom/src/notification/$(LIB_PREFIX)jsdomnotification_s.$(LIB_SUFFIX) \
$(DEPTH)/dom/system/$(LIB_PREFIX)domsystem_s.$(LIB_SUFFIX) \
$(DEPTH)/dom/workers/$(LIB_PREFIX)domworkers_s.$(LIB_SUFFIX) \
Expand Down Expand Up @@ -289,6 +290,7 @@ LOCAL_INCLUDES += -I$(srcdir)/../base \
-I$(topsrcdir)/dom/src/storage \
-I$(topsrcdir)/dom/src/offline \
-I$(topsrcdir)/dom/src/geolocation \
-I$(topsrcdir)/dom/audiochannel \
-I$(topsrcdir)/dom/contacts \
-I$(topsrcdir)/dom/settings \
-I$(topsrcdir)/dom/permission \
Expand Down
16 changes: 13 additions & 3 deletions layout/build/nsLayoutModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,8 @@ static void Shutdown();
#include "nsIAlarmHalService.h"
#include "nsMixedContentBlocker.h"

#include "AudioChannelService.h"

#include "mozilla/dom/power/PowerManagerService.h"
#include "mozilla/dom/alarm/AlarmHalService.h"
#include "mozilla/dom/time/TimeService.h"
Expand Down Expand Up @@ -648,8 +650,13 @@ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsGeolocation, Init)
#define NS_GEOLOCATION_SERVICE_CID \
{ 0x404d02a, 0x1CA, 0xAAAB, { 0x47, 0x62, 0x94, 0x4b, 0x1b, 0xf2, 0xf7, 0xb5 } }

#define NS_AUDIOCHANNEL_SERVICE_CID \
{ 0xf712e983, 0x048a, 0x443f, { 0x88, 0x02, 0xfc, 0xc3, 0xd9, 0x27, 0xce, 0xac }}

NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsGeolocationService, nsGeolocationService::GetGeolocationService)

NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(AudioChannelService, AudioChannelService::GetAudioChannelService)

NS_GENERIC_FACTORY_CONSTRUCTOR(CSPService)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMixedContentBlocker)

Expand All @@ -664,7 +671,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(OSFileConstantsService)
NS_GENERIC_FACTORY_CONSTRUCTOR(TCPSocketChild)

static nsresult
Construct_nsIScriptSecurityManager(nsISupports *aOuter, REFNSIID aIID,
Construct_nsIScriptSecurityManager(nsISupports *aOuter, REFNSIID aIID,
void **aResult)
{
if (!aResult)
Expand All @@ -673,7 +680,7 @@ Construct_nsIScriptSecurityManager(nsISupports *aOuter, REFNSIID aIID,
if (aOuter)
return NS_ERROR_NO_AGGREGATION;
nsScriptSecurityManager *obj = nsScriptSecurityManager::GetScriptSecurityManager();
if (!obj)
if (!obj)
return NS_ERROR_OUT_OF_MEMORY;
if (NS_FAILED(obj->QueryInterface(aIID, aResult)))
return NS_ERROR_FAILURE;
Expand Down Expand Up @@ -796,6 +803,7 @@ NS_DEFINE_NAMED_CID(NS_EDITINGCOMMANDTABLE_CID);
NS_DEFINE_NAMED_CID(NS_TEXTSERVICESDOCUMENT_CID);
NS_DEFINE_NAMED_CID(NS_GEOLOCATION_SERVICE_CID);
NS_DEFINE_NAMED_CID(NS_GEOLOCATION_CID);
NS_DEFINE_NAMED_CID(NS_AUDIOCHANNEL_SERVICE_CID);
NS_DEFINE_NAMED_CID(NS_FOCUSMANAGER_CID);
NS_DEFINE_NAMED_CID(CSPSERVICE_CID);
NS_DEFINE_NAMED_CID(NS_MIXEDCONTENTBLOCKER_CID);
Expand Down Expand Up @@ -1075,6 +1083,7 @@ static const mozilla::Module::CIDEntry kLayoutCIDs[] = {
{ &kNS_TEXTSERVICESDOCUMENT_CID, false, NULL, nsTextServicesDocumentConstructor },
{ &kNS_GEOLOCATION_SERVICE_CID, false, NULL, nsGeolocationServiceConstructor },
{ &kNS_GEOLOCATION_CID, false, NULL, nsGeolocationConstructor },
{ &kNS_AUDIOCHANNEL_SERVICE_CID, false, NULL, AudioChannelServiceConstructor },
{ &kNS_FOCUSMANAGER_CID, false, NULL, CreateFocusManager },
{ &kCSPSERVICE_CID, false, NULL, CSPServiceConstructor },
{ &kNS_MIXEDCONTENTBLOCKER_CID, false, NULL, nsMixedContentBlockerConstructor },
Expand Down Expand Up @@ -1216,6 +1225,7 @@ static const mozilla::Module::ContractIDEntry kLayoutContracts[] = {
{ "@mozilla.org/textservices/textservicesdocument;1", &kNS_TEXTSERVICESDOCUMENT_CID },
{ "@mozilla.org/geolocation/service;1", &kNS_GEOLOCATION_SERVICE_CID },
{ "@mozilla.org/geolocation;1", &kNS_GEOLOCATION_CID },
{ "@mozilla.org/audiochannel/service;1", &kNS_AUDIOCHANNEL_SERVICE_CID },
{ "@mozilla.org/focus-manager;1", &kNS_FOCUSMANAGER_CID },
{ CSPSERVICE_CONTRACTID, &kCSPSERVICE_CID },
{ NS_MIXEDCONTENTBLOCKER_CONTRACTID, &kNS_MIXEDCONTENTBLOCKER_CID },
Expand Down Expand Up @@ -1299,5 +1309,5 @@ static const mozilla::Module kLayoutModule = {
Initialize,
LayoutModuleDtor
};

NSMODULE_DEFN(nsLayoutModule) = &kLayoutModule;
4 changes: 4 additions & 0 deletions layout/build/nsLayoutStatics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@
#include "Navigator.h"
#include "nsDOMStorageBaseDB.h"

#include "AudioChannelService.h"

#ifdef MOZ_XUL
#include "nsXULPopupManager.h"
#include "nsXULContentUtils.h"
Expand Down Expand Up @@ -361,5 +363,7 @@ nsLayoutStatics::Shutdown()
nsEditorSpellCheck::ShutDown();
nsDOMMutationObserver::Shutdown();

AudioChannelService::Shutdown();

ContentParent::ShutDown();
}

0 comments on commit e867518

Please sign in to comment.