Bug 805333 part 2 - MediaElement connected to AudioChannelService, r=kinetik, a=blocking-basecamp

This commit is contained in:
Andrea Marchesini 2012-12-05 00:56:17 -08:00
Родитель 109dd4019c
Коммит 661c89ec0c
6 изменённых файлов: 118 добавлений и 14 удалений

Просмотреть файл

@ -7705,7 +7705,7 @@ nsDocument::CloneDocHelper(nsDocument* clone) const
if (mCreatingStaticClone) {
nsCOMPtr<nsILoadGroup> loadGroup;
// |mDocumentContainer| is the container of the document that is being
// created and not the original container. See CreateStaticClone function().
nsCOMPtr<nsIDocumentLoader> docLoader = do_QueryReferent(mDocumentContainer);
@ -9911,6 +9911,8 @@ nsDocument::UpdateVisibilityState()
NS_LITERAL_STRING("mozvisibilitychange"),
/* bubbles = */ true,
/* cancelable = */ false);
EnumerateFreezableElements(NotifyActivityChanged, nullptr);
}
}

Просмотреть файл

@ -113,7 +113,7 @@ public:
/**
* Call this to reevaluate whether we should start/stop due to our owner
* document being active or inactive.
* document being active, inactive, visible or hidden.
*/
void NotifyOwnerDocumentActivityChanged();
@ -405,6 +405,9 @@ public:
return mSrcStream->GetStream();
}
// Notification from the AudioChannelService.
nsresult NotifyAudioChannelStateChanged();
protected:
class MediaLoadListener;
class StreamListener;
@ -648,9 +651,20 @@ protected:
*/
void ProcessMediaFragmentURI();
/**
* Mute or unmute the audio, without changing the value that |muted| reports.
*/
void SetMutedInternal(bool aMuted);
// Check the permissions for audiochannel.
bool CheckAudioChannelPermissions(const nsAString& aType);
// This method does the check for muting/unmuting the audio channel.
nsresult UpdateChannelMuteState();
// Update the audio channel playing state
void UpdateAudioChannelPlayingState();
// The current decoder. Load() has been called on this decoder.
// At most one of mDecoder and mSrcStream can be non-null.
nsRefPtr<nsMediaDecoder> mDecoder;
@ -911,6 +925,12 @@ protected:
// Audio Channel Type.
mozilla::dom::AudioChannelType mAudioChannelType;
// The audiochannel has been muted
bool mChannelMuted;
// Is this media element playing?
bool mPlayingThroughTheAudioChannel;
};
#endif

Просмотреть файл

@ -65,6 +65,8 @@
#include "nsDOMMediaStream.h"
#include "nsIScriptError.h"
#include "AudioChannelService.h"
#include "nsCSSParser.h"
#include "nsIMediaList.h"
@ -1515,14 +1517,9 @@ NS_IMETHODIMP nsHTMLMediaElement::GetMuted(bool *aMuted)
return NS_OK;
}
NS_IMETHODIMP nsHTMLMediaElement::SetMuted(bool aMuted)
void nsHTMLMediaElement::SetMutedInternal(bool aMuted)
{
if (aMuted == mMuted)
return NS_OK;
mMuted = aMuted;
float effectiveVolume = mMuted ? 0.0f : float(mVolume);
float effectiveVolume = aMuted || mChannelMuted ? 0.0f : float(mVolume);
if (mDecoder) {
mDecoder->SetVolume(effectiveVolume);
} else if (mAudioStream) {
@ -1530,6 +1527,15 @@ NS_IMETHODIMP nsHTMLMediaElement::SetMuted(bool aMuted)
} else if (mSrcStream) {
GetSrcMediaStream()->SetAudioOutputVolume(this, effectiveVolume);
}
}
NS_IMETHODIMP nsHTMLMediaElement::SetMuted(bool aMuted)
{
if (aMuted == mMuted)
return NS_OK;
mMuted = aMuted;
SetMutedInternal(aMuted);
DispatchAsyncEvent(NS_LITERAL_STRING("volumechange"));
@ -1723,7 +1729,9 @@ nsHTMLMediaElement::nsHTMLMediaElement(already_AddRefed<nsINodeInfo> aNodeInfo)
mCORSMode(CORS_NONE),
mHasAudio(false),
mDownloadSuspendedByCache(false),
mAudioChannelType(AUDIO_CHANNEL_NORMAL)
mAudioChannelType(AUDIO_CHANNEL_NORMAL),
mChannelMuted(false),
mPlayingThroughTheAudioChannel(false)
{
#ifdef PR_LOGGING
if (!gMediaElementLog) {
@ -3193,6 +3201,8 @@ void nsHTMLMediaElement::ChangeReadyState(nsMediaReadyState aState)
nsMediaReadyState oldState = mReadyState;
mReadyState = aState;
UpdateAudioChannelPlayingState();
if (mNetworkState == nsIDOMHTMLMediaElement::NETWORK_EMPTY ||
oldState == mReadyState) {
return;
@ -3437,6 +3447,10 @@ void nsHTMLMediaElement::NotifyOwnerDocumentActivityChanged()
}
}
if (mPlayingThroughTheAudioChannel) {
UpdateChannelMuteState();
}
AddRemoveSelfReference();
}
@ -3475,6 +3489,8 @@ void nsHTMLMediaElement::AddRemoveSelfReference()
NS_DispatchToMainThread(event);
}
}
UpdateAudioChannelPlayingState();
}
void nsHTMLMediaElement::DoRemoveSelfReference()
@ -3752,6 +3768,64 @@ void nsHTMLMediaElement::GetMimeType(nsCString& aMimeType)
aMimeType = mMimeType;
}
nsresult nsHTMLMediaElement::UpdateChannelMuteState()
{
bool hidden = false;
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(OwnerDoc());
if (!domDoc) {
return NS_ERROR_FAILURE;
}
nsresult rv = domDoc->GetHidden(&hidden);
NS_ENSURE_SUCCESS(rv, rv);
bool mute = false;
nsRefPtr<AudioChannelService> audioChannelService = AudioChannelService::GetAudioChannelService();
if (audioChannelService) {
mute = audioChannelService->GetMuted(mAudioChannelType, hidden);
}
// We have to mute this channel:
if (mute && !mChannelMuted) {
mChannelMuted = true;
SetMutedInternal(mMuted);
DispatchAsyncEvent(NS_LITERAL_STRING("mozinterruptbegin"));
} else if (!mute && mChannelMuted) {
mChannelMuted = false;
SetMutedInternal(mMuted);
DispatchAsyncEvent(NS_LITERAL_STRING("mozinterruptend"));
}
return NS_OK;
}
void nsHTMLMediaElement::UpdateAudioChannelPlayingState()
{
bool playingThroughTheAudioChannel =
(mReadyState >= nsIDOMHTMLMediaElement::HAVE_FUTURE_DATA &&
IsPotentiallyPlaying());
if (playingThroughTheAudioChannel != mPlayingThroughTheAudioChannel) {
mPlayingThroughTheAudioChannel = playingThroughTheAudioChannel;
nsRefPtr<AudioChannelService> audioChannelService = AudioChannelService::GetAudioChannelService();
if (!audioChannelService) {
return;
}
if (mPlayingThroughTheAudioChannel) {
audioChannelService->RegisterMediaElement(this, mAudioChannelType);
} else {
audioChannelService->UnregisterMediaElement(this);
}
}
}
nsresult nsHTMLMediaElement::NotifyAudioChannelStateChanged()
{
return UpdateChannelMuteState();
}
void nsHTMLMediaElement::NotifyAudioAvailableListener()
{
if (mDecoder) {

Просмотреть файл

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

Просмотреть файл

@ -138,6 +138,10 @@ interface nsIDOMHTMLMediaElement : nsIDOMHTMLElement
// Use case: dialer, voip
// * publicnotification
// Always plays in speaker, even when headphones are plugged in.
attribute DOMString mozAudioChannelType;
// In addition the media element has these new events:
// * onmozinterruptbegin - called when the media element is interrupted
// because of the audiochannel manager.
// * onmozinterruptend - called when the interruption is concluded
};

Просмотреть файл

@ -345,7 +345,8 @@
"loadstart", "timeupdate", "progress",
"playing", "waiting", "canplay", "canplaythrough",
"seeking", "seeked", "emptied", "loadedmetadata",
"error", "suspend", "stalled"],
"error", "suspend", "stalled",
"mozinterruptbegin", "mozinterruptend" ],
firstFrameShown : false,
timeUpdateCount : 0,
@ -641,6 +642,10 @@
this.controlsSpacer.removeAttribute("hideCursor");
}
break;
case "mozinterruptbegin":
case "mozinterruptend":
// Nothing to do...
break;
default:
this.log("!!! event " + aEvent.type + " not handled!");
}