mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 923247 - patch 2 - mute and volume per window, r=ehsan, r=roc
This commit is contained in:
parent
9202ffb069
commit
5c90d4d8c7
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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]
|
||||||
|
92
dom/base/test/test_audioWindowUtils.html
Normal file
92
dom/base/test/test_audioWindowUtils.html
Normal 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>
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user