Bug 923247 - patch 2 - mute and volume per window, r=ehsan, r=roc

This commit is contained in:
Andrea Marchesini 2014-03-10 16:36:15 +00:00
parent 9202ffb069
commit 5c90d4d8c7
19 changed files with 417 additions and 12 deletions

View File

@ -245,6 +245,12 @@ HTMLAudioElement::CanPlayChanged(int32_t canPlay)
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
HTMLAudioElement::WindowVolumeChanged()
{
return HTMLMediaElement::WindowVolumeChanged();
}
NS_IMETHODIMP NS_IMETHODIMP
HTMLAudioElement::Notify(nsITimer* aTimer) HTMLAudioElement::Notify(nsITimer* aTimer)
{ {

View File

@ -1729,6 +1729,14 @@ void HTMLMediaElement::SetVolumeInternal()
float effectiveVolume = mMuted ? 0.0f : float effectiveVolume = mMuted ? 0.0f :
mAudioChannelFaded ? float(mVolume) * FADED_VOLUME_RATIO : float(mVolume); mAudioChannelFaded ? float(mVolume) * FADED_VOLUME_RATIO : float(mVolume);
if (mAudioChannelAgent) {
float volume;
nsresult rv = mAudioChannelAgent->GetWindowVolume(&volume);
if (NS_SUCCEEDED(rv)) {
effectiveVolume *= volume;
}
}
if (mDecoder) { if (mDecoder) {
mDecoder->SetVolume(effectiveVolume); mDecoder->SetVolume(effectiveVolume);
} else if (mAudioStream) { } else if (mAudioStream) {
@ -3921,6 +3929,12 @@ NS_IMETHODIMP HTMLMediaElement::CanPlayChanged(int32_t canPlay)
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP HTMLMediaElement::WindowVolumeChanged()
{
SetVolumeInternal();
return NS_OK;
}
/* readonly attribute TextTrackList textTracks; */ /* readonly attribute TextTrackList textTracks; */
TextTrackList* TextTrackList*
HTMLMediaElement::TextTracks() const HTMLMediaElement::TextTracks() const

View File

@ -64,8 +64,6 @@ NS_IMPL_RELEASE_INHERITED(AudioContext, nsDOMEventTargetHelper)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(AudioContext) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(AudioContext)
NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper) NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
static uint8_t gWebAudioOutputKey;
static float GetSampleRateForAudioContext(bool aIsOffline, float aSampleRate) static float GetSampleRateForAudioContext(bool aIsOffline, float aSampleRate)
{ {
if (aIsOffline) { if (aIsOffline) {
@ -95,7 +93,6 @@ AudioContext::AudioContext(nsPIDOMWindow* aWindow,
// bound to the window. // bound to the window.
mDestination = new AudioDestinationNode(this, aIsOffline, aNumberOfChannels, mDestination = new AudioDestinationNode(this, aIsOffline, aNumberOfChannels,
aLength, aSampleRate); aLength, aSampleRate);
mDestination->Stream()->AddAudioOutput(&gWebAudioOutputKey);
// We skip calling SetIsOnlyNodeForContext during mDestination's constructor, // We skip calling SetIsOnlyNodeForContext during mDestination's constructor,
// because we can only call SetIsOnlyNodeForContext after mDestination has // because we can only call SetIsOnlyNodeForContext after mDestination has
// been set up. // been set up.

View File

@ -23,6 +23,8 @@
namespace mozilla { namespace mozilla {
namespace dom { namespace dom {
static uint8_t gWebAudioOutputKey;
class OfflineDestinationNodeEngine : public AudioNodeEngine class OfflineDestinationNodeEngine : public AudioNodeEngine
{ {
public: public:
@ -233,6 +235,7 @@ AudioDestinationNode::AudioDestinationNode(AudioContext* aContext,
mStream = graph->CreateAudioNodeStream(engine, MediaStreamGraph::EXTERNAL_STREAM); mStream = graph->CreateAudioNodeStream(engine, MediaStreamGraph::EXTERNAL_STREAM);
mStream->AddMainThreadListener(this); mStream->AddMainThreadListener(this);
mStream->AddAudioOutput(&gWebAudioOutputKey);
if (!aIsOffline && UseAudioChannelService()) { if (!aIsOffline && UseAudioChannelService()) {
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(GetOwner()); nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(GetOwner());
@ -380,6 +383,23 @@ AudioDestinationNode::CanPlayChanged(int32_t aCanPlay)
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
AudioDestinationNode::WindowVolumeChanged()
{
MOZ_ASSERT(mAudioChannelAgent);
if (!mStream) {
return NS_OK;
}
float volume;
nsresult rv = mAudioChannelAgent->GetWindowVolume(&volume);
NS_ENSURE_SUCCESS(rv, rv);
mStream->SetAudioOutputVolume(&gWebAudioOutputKey, volume);
return NS_OK;
}
AudioChannel AudioChannel
AudioDestinationNode::MozAudioChannelType() const AudioDestinationNode::MozAudioChannelType() const
{ {

View File

@ -38,6 +38,7 @@ public:
NS_DECL_ISUPPORTS_INHERITED NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(AudioDestinationNode, AudioNode) NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(AudioDestinationNode, AudioNode)
NS_DECL_NSIAUDIOCHANNELAGENTCALLBACK
virtual JSObject* WrapObject(JSContext* aCx, virtual JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aScope) MOZ_OVERRIDE; JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
@ -61,9 +62,6 @@ public:
// nsIDOMEventListener // nsIDOMEventListener
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent); NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
// nsIAudioChannelAgentCallback
NS_IMETHOD CanPlayChanged(int32_t aCanPlay);
AudioChannel MozAudioChannelType() const; AudioChannel MozAudioChannelType() const;
void SetMozAudioChannelType(AudioChannel aValue, ErrorResult& aRv); void SetMozAudioChannelType(AudioChannel aValue, ErrorResult& aRv);

View File

@ -6,6 +6,7 @@
#include "AudioChannelCommon.h" #include "AudioChannelCommon.h"
#include "AudioChannelService.h" #include "AudioChannelService.h"
#include "nsIDOMWindow.h" #include "nsIDOMWindow.h"
#include "nsPIDOMWindow.h"
#include "nsXULAppAPI.h" #include "nsXULAppAPI.h"
using namespace mozilla::dom; using namespace mozilla::dom;
@ -183,3 +184,29 @@ AudioChannelAgent::GetCallback()
} }
return callback.forget(); return callback.forget();
} }
void
AudioChannelAgent::WindowVolumeChanged()
{
nsCOMPtr<nsIAudioChannelAgentCallback> callback = GetCallback();
if (!callback) {
return;
}
callback->WindowVolumeChanged();
}
NS_IMETHODIMP
AudioChannelAgent::GetWindowVolume(float* aVolume)
{
NS_ENSURE_ARG_POINTER(aVolume);
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(mWindow);
if (!win) {
*aVolume = 1.0f;
return NS_OK;
}
*aVolume = win->GetAudioGlobalVolume();
return NS_OK;
}

View File

@ -34,6 +34,13 @@ public:
AudioChannelAgent(); AudioChannelAgent();
virtual void NotifyAudioChannelStateChanged(); virtual void NotifyAudioChannelStateChanged();
void WindowVolumeChanged();
nsIDOMWindow* Window() const
{
return mWindow;
}
private: private:
virtual ~AudioChannelAgent(); virtual ~AudioChannelAgent();

View File

@ -780,3 +780,44 @@ AudioChannelService::GetInternalType(AudioChannelType aType,
MOZ_CRASH("unexpected audio channel type"); MOZ_CRASH("unexpected audio channel type");
} }
struct RefreshAgentsVolumeData
{
RefreshAgentsVolumeData(nsPIDOMWindow* aWindow)
: mWindow(aWindow)
{}
nsPIDOMWindow* mWindow;
nsTArray<nsRefPtr<AudioChannelAgent>> mAgents;
};
PLDHashOperator
AudioChannelService::RefreshAgentsVolumeEnumerator(AudioChannelAgent* aAgent,
AudioChannelAgentData* aUnused,
void* aPtr)
{
MOZ_ASSERT(aAgent);
RefreshAgentsVolumeData* data = static_cast<RefreshAgentsVolumeData*>(aPtr);
MOZ_ASSERT(data);
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aAgent->Window());
if (window && !window->IsInnerWindow()) {
window = window->GetCurrentInnerWindow();
}
if (window == data->mWindow) {
data->mAgents.AppendElement(aAgent);
}
return PL_DHASH_NEXT;
}
void
AudioChannelService::RefreshAgentsVolume(nsPIDOMWindow* aWindow)
{
RefreshAgentsVolumeData data(aWindow);
mAgents.EnumerateRead(RefreshAgentsVolumeEnumerator, &data);
for (uint32_t i = 0; i < data.mAgents.Length(); ++i) {
data.mAgents[i]->WindowVolumeChanged();
}
}

View File

@ -16,6 +16,8 @@
#include "AudioChannelAgent.h" #include "AudioChannelAgent.h"
#include "nsClassHashtable.h" #include "nsClassHashtable.h"
class nsPIDOMWindow;
namespace mozilla { namespace mozilla {
namespace dom { namespace dom {
#ifdef MOZ_WIDGET_GONK #ifdef MOZ_WIDGET_GONK
@ -85,6 +87,8 @@ public:
bool AnyAudioChannelIsActive(); bool AnyAudioChannelIsActive();
void RefreshAgentsVolume(nsPIDOMWindow* aWindow);
#ifdef MOZ_WIDGET_GONK #ifdef MOZ_WIDGET_GONK
void RegisterSpeakerManager(SpeakerManagerService* aSpeakerManager) void RegisterSpeakerManager(SpeakerManagerService* aSpeakerManager)
{ {
@ -179,6 +183,11 @@ protected:
NotifyEnumerator(AudioChannelAgent* aAgent, NotifyEnumerator(AudioChannelAgent* aAgent,
AudioChannelAgentData* aData, void *aUnused); AudioChannelAgentData* aData, void *aUnused);
static PLDHashOperator
RefreshAgentsVolumeEnumerator(AudioChannelAgent* aAgent,
AudioChannelAgentData* aUnused,
void *aPtr);
nsClassHashtable< nsPtrHashKey<AudioChannelAgent>, AudioChannelAgentData > mAgents; nsClassHashtable< nsPtrHashKey<AudioChannelAgent>, AudioChannelAgentData > mAgents;
#ifdef MOZ_WIDGET_GONK #ifdef MOZ_WIDGET_GONK
nsTArray<SpeakerManagerService*> mSpeakerManager; nsTArray<SpeakerManagerService*> mSpeakerManager;

View File

@ -6,7 +6,7 @@
interface nsIDOMWindow; interface nsIDOMWindow;
[function, scriptable, uuid(86975108-cd78-4796-8fc8-6cd777cd6eba)] [scriptable, uuid(194b55d9-39c0-45c6-b8ef-b8049f978ea5)]
interface nsIAudioChannelAgentCallback : nsISupports interface nsIAudioChannelAgentCallback : nsISupports
{ {
/** /**
@ -19,6 +19,11 @@ interface nsIAudioChannelAgentCallback : nsISupports
* it is faded state then the volume of media should be reduced. * it is faded state then the volume of media should be reduced.
*/ */
void canPlayChanged(in long canPlay); void canPlayChanged(in long canPlay);
/**
* Notified when the window volume/mute is changed
*/
void windowVolumeChanged();
}; };
/** /**
@ -35,7 +40,7 @@ interface nsIAudioChannelAgentCallback : nsISupports
* 1. Changes to the playable status of this channel. * 1. Changes to the playable status of this channel.
*/ */
[scriptable, uuid(86ef883d-9cec-4c04-994f-5de198286e7c)] [scriptable, uuid(2b0222a5-8f7b-49d2-9ab8-cd01b744b23e)]
interface nsIAudioChannelAgent : nsISupports interface nsIAudioChannelAgent : nsISupports
{ {
const long AUDIO_AGENT_CHANNEL_NORMAL = 0; const long AUDIO_AGENT_CHANNEL_NORMAL = 0;
@ -128,5 +133,10 @@ interface nsIAudioChannelAgent : nsISupports
* True if the window associated with the agent is visible. * True if the window associated with the agent is visible.
*/ */
void setVisibilityState(in boolean visible); void setVisibilityState(in boolean visible);
/**
* Retrieve the volume from the window.
*/
readonly attribute float windowVolume;
}; };

View File

@ -104,6 +104,11 @@ public:
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP WindowVolumeChanged()
{
return NS_OK;
}
nsresult GetCanPlay(AudioChannelState *_ret) nsresult GetCanPlay(AudioChannelState *_ret)
{ {
int loop = 0; int loop = 0;

View File

@ -3732,3 +3732,53 @@ nsDOMWindowUtils::GetOMTAOrComputedStyle(nsIDOMElement* aElement,
return style->GetPropertyValue(aProperty, aResult); return style->GetPropertyValue(aProperty, aResult);
} }
NS_IMETHODIMP
nsDOMWindowUtils::GetAudioMuted(bool* aMuted)
{
if (!nsContentUtils::IsCallerChrome()) {
return NS_ERROR_DOM_SECURITY_ERR;
}
nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
NS_ENSURE_STATE(window);
*aMuted = window->GetAudioMuted();
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::SetAudioMuted(bool aMuted)
{
if (!nsContentUtils::IsCallerChrome()) {
return NS_ERROR_DOM_SECURITY_ERR;
}
nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
NS_ENSURE_STATE(window);
window->SetAudioMuted(aMuted);
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetAudioVolume(float* aVolume)
{
if (!nsContentUtils::IsCallerChrome()) {
return NS_ERROR_DOM_SECURITY_ERR;
}
nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
NS_ENSURE_STATE(window);
*aVolume = window->GetAudioVolume();
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::SetAudioVolume(float aVolume)
{
if (!nsContentUtils::IsCallerChrome()) {
return NS_ERROR_DOM_SECURITY_ERR;
}
nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
NS_ENSURE_STATE(window);
return window->SetAudioVolume(aVolume);
}

View File

@ -60,6 +60,7 @@
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include "mozilla/Debug.h" #include "mozilla/Debug.h"
#include "mozilla/MouseEvents.h" #include "mozilla/MouseEvents.h"
#include "AudioChannelService.h"
// Interfaces Needed // Interfaces Needed
#include "nsIFrame.h" #include "nsIFrame.h"
@ -564,6 +565,7 @@ nsPIDOMWindow::nsPIDOMWindow(nsPIDOMWindow *aOuterWindow)
mMayHavePointerEnterLeaveEventListener(false), mMayHavePointerEnterLeaveEventListener(false),
mIsModalContentWindow(false), mIsModalContentWindow(false),
mIsActive(false), mIsBackground(false), mIsActive(false), mIsBackground(false),
mAudioMuted(false), mAudioVolume(1.0),
mInnerWindow(nullptr), mOuterWindow(aOuterWindow), mInnerWindow(nullptr), mOuterWindow(aOuterWindow),
// Make sure no actual window ends up with mWindowID == 0 // Make sure no actual window ends up with mWindowID == 0
mWindowID(++gNextWindowID), mHasNotifiedGlobalCreated(false), mWindowID(++gNextWindowID), mHasNotifiedGlobalCreated(false),
@ -3582,6 +3584,100 @@ nsPIDOMWindow::CreatePerformanceObjectIfNeeded()
} }
} }
bool
nsPIDOMWindow::GetAudioMuted() const
{
if (!IsInnerWindow()) {
return mInnerWindow->GetAudioMuted();
}
return mAudioMuted;
}
void
nsPIDOMWindow::SetAudioMuted(bool aMuted)
{
if (!IsInnerWindow()) {
mInnerWindow->SetAudioMuted(aMuted);
return;
}
if (mAudioMuted == aMuted) {
return;
}
mAudioMuted = aMuted;
RefreshMediaElements();
}
float
nsPIDOMWindow::GetAudioVolume() const
{
if (!IsInnerWindow()) {
return mInnerWindow->GetAudioVolume();
}
return mAudioVolume;
}
nsresult
nsPIDOMWindow::SetAudioVolume(float aVolume)
{
if (!IsInnerWindow()) {
return mInnerWindow->SetAudioVolume(aVolume);
}
if (aVolume < 0.0) {
return NS_ERROR_DOM_INDEX_SIZE_ERR;
}
if (mAudioVolume == aVolume) {
return NS_OK;
}
mAudioVolume = aVolume;
RefreshMediaElements();
return NS_OK;
}
float
nsPIDOMWindow::GetAudioGlobalVolume()
{
float globalVolume = 1.0;
nsCOMPtr<nsPIDOMWindow> window = this;
do {
if (window->GetAudioMuted()) {
return 0;
}
globalVolume *= window->GetAudioVolume();
nsCOMPtr<nsIDOMWindow> win;
window->GetParent(getter_AddRefs(win));
if (window == win) {
break;
}
window = do_QueryInterface(win);
// If there is not parent, or we are the toplevel or the volume is
// already 0.0, we don't continue.
} while (window && window != this && globalVolume);
return globalVolume;
}
void
nsPIDOMWindow::RefreshMediaElements()
{
nsRefPtr<AudioChannelService> service =
AudioChannelService::GetAudioChannelService();
if (service) {
service->RefreshAgentsVolume(this);
}
}
// nsISpeechSynthesisGetter // nsISpeechSynthesisGetter
#ifdef MOZ_WEBSPEECH #ifdef MOZ_WEBSPEECH

View File

@ -190,11 +190,23 @@ public:
virtual NS_HIDDEN_(bool) IsRunningTimeout() = 0; virtual NS_HIDDEN_(bool) IsRunningTimeout() = 0;
// Audio API
bool GetAudioMuted() const;
void SetAudioMuted(bool aMuted);
float GetAudioVolume() const;
nsresult SetAudioVolume(float aVolume);
float GetAudioGlobalVolume();
protected: protected:
// Lazily instantiate an about:blank document if necessary, and if // Lazily instantiate an about:blank document if necessary, and if
// we have what it takes to do so. // we have what it takes to do so.
void MaybeCreateDoc(); void MaybeCreateDoc();
float GetAudioGlobalVolumeInternal(float aVolume);
void RefreshMediaElements();
public: public:
// Internal getter/setter for the frame element, this version of the // Internal getter/setter for the frame element, this version of the
// getter crosses chrome boundaries whereas the public scriptable // getter crosses chrome boundaries whereas the public scriptable
@ -768,6 +780,9 @@ protected:
// "active". Only used on outer windows. // "active". Only used on outer windows.
bool mIsBackground; bool mIsBackground;
bool mAudioMuted;
float mAudioVolume;
// And these are the references between inner and outer windows. // And these are the references between inner and outer windows.
nsPIDOMWindow *mInnerWindow; nsPIDOMWindow *mInnerWindow;
nsCOMPtr<nsPIDOMWindow> mOuterWindow; nsCOMPtr<nsPIDOMWindow> mOuterWindow;

View File

@ -8,6 +8,7 @@ support-files =
[test_Image_constructor.html] [test_Image_constructor.html]
[test_appname_override.html] [test_appname_override.html]
[test_audioWindowUtils.html]
[test_bug913761.html] [test_bug913761.html]
[test_bug978522.html] [test_bug978522.html]
[test_bug979109.html] [test_bug979109.html]

View File

@ -0,0 +1,92 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for audio controller in windows</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<iframe src="about:blank" id="iframe"></iframe>
<script type="application/javascript">
function runTest() {
var utils = SpecialPowers.wrap(window).
QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor).
getInterface(SpecialPowers.Ci.nsIDOMWindowUtils);
ok(utils, "nsIDOMWindowUtils");
is(utils.audioMuted, false, "By default utils.audioMuted is false");
utils.audioMuted = true;
is(utils.audioMuted, true, "utils.audioMuted is true");
utils.audioMuted = false;
is(utils.audioMuted, false, "utils.audioMuted is true");
is(utils.audioVolume, 1.0, "By default utils.audioVolume is 1.0");
utils.audioVolume = 0.4;
is(utils.audioVolume.toFixed(2), 0.4, "utils.audioVolume is ok");
utils.audioMuted = true;
is(utils.audioMuted, true, "utils.audioMuted is true");
is(utils.audioVolume.toFixed(2), 0.4, "utils.audioVolume is ok");
utils.audioMuted = false;
utils.audioVolume = 2.0;
is(utils.audioVolume, 2.0, "utils.audioVolume is ok");
try {
utils.audioVolume = -42;
ok(false, "This should throw");
} catch(e) {
ok(true, "This should throw");
}
utils.audioVolume = 0;
is(utils.audioVolume, 0.0, "utils.audioVolume is ok");
utils.audioVolume = 1.0;
is(utils.audioVolume, 1.0, "utils.audioVolume is ok");
var iframe = document.getElementById("iframe");
ok(iframe, "IFrame exists");
utils = SpecialPowers.wrap(iframe.contentWindow).
QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor).
getInterface(SpecialPowers.Ci.nsIDOMWindowUtils);
ok(utils, "nsIDOMWindowUtils");
is(utils.audioMuted, false, "By default utils.audioMuted is false");
utils.audioMuted = true;
is(utils.audioMuted, true, "utils.audioMuted is true");
utils.audioMuted = false;
is(utils.audioMuted, false, "utils.audioMuted is true");
is(utils.audioVolume, 1.0, "By default utils.audioVolume is 1.0");
utils.audioVolume = 0.4;
is(utils.audioVolume.toFixed(2), 0.4, "utils.audioVolume is ok");
utils.audioMuted = true;
is(utils.audioMuted, true, "utils.audioMuted is true");
is(utils.audioVolume.toFixed(2), 0.4, "utils.audioVolume is ok");
utils.audioMuted = false;
utils.audioVolume = 2.0;
is(utils.audioVolume, 2.0, "utils.audioVolume is ok");
try {
utils.audioVolume = -42;
ok(false, "This should throw");
} catch(e) {
ok(true, "This should throw");
}
utils.audioVolume = 0;
is(utils.audioVolume, 0.0, "utils.audioVolume is ok");
utils.audioVolume = 1.0;
is(utils.audioVolume, 1.0, "utils.audioVolume is ok");
SimpleTest.finish();
}
SpecialPowers.pushPrefEnv({ "set": [["media.useAudioChannelService", true]]}, runTest);
SimpleTest.waitForExplicitFinish();
</script>
</body>
</html>

View File

@ -389,6 +389,12 @@ FMRadio::CanPlayChanged(int32_t aCanPlay)
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
FMRadio::WindowVolumeChanged(float aVolume)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
void void
FMRadio::SetCanPlay(bool aCanPlay) FMRadio::SetCanPlay(bool aCanPlay)
{ {

View File

@ -34,6 +34,7 @@ public:
FMRadio(); FMRadio();
NS_DECL_ISUPPORTS_INHERITED NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIAUDIOCHANNELAGENTCALLBACK
NS_REALLY_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper) NS_REALLY_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper)
@ -82,9 +83,6 @@ public:
IMPL_EVENT_HANDLER(antennaavailablechange); IMPL_EVENT_HANDLER(antennaavailablechange);
IMPL_EVENT_HANDLER(frequencychange); IMPL_EVENT_HANDLER(frequencychange);
// nsIAudioChannelAgentCallback
NS_IMETHOD CanPlayChanged(int32_t aCanPlay);
// nsIDOMEventListener // nsIDOMEventListener
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent); NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);

View File

@ -43,7 +43,7 @@ interface nsIDOMEventTarget;
interface nsIRunnable; interface nsIRunnable;
interface nsICompositionStringSynthesizer; interface nsICompositionStringSynthesizer;
[scriptable, uuid(27efada9-b8ea-4d70-a2e6-f46b9ba905f4)] [scriptable, uuid(ef70a299-033c-4adc-b214-6649aed9d828)]
interface nsIDOMWindowUtils : nsISupports { interface nsIDOMWindowUtils : nsISupports {
/** /**
@ -1582,4 +1582,17 @@ interface nsIDOMWindowUtils : nsISupports {
*/ */
AString getOMTAOrComputedStyle(in nsIDOMElement aElement, AString getOMTAOrComputedStyle(in nsIDOMElement aElement,
in AString aProperty); in AString aProperty);
/**
* With this it's possible to mute all the MediaElements in this window.
* We have audioMuted and audioVolume to preserve the volume across
* mute/umute.
*/
attribute boolean audioMuted;
/**
* range: greater or equal to 0. The real volume level is affected by the
* volume of all ancestor windows.
*/
attribute float audioVolume;
}; };