/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * 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/. */
/* * To take advantage of what Vista+ have to offer with respect to audio, * we need to maintain an audio session. This class wraps IAudioSessionControl * and implements IAudioSessionEvents (for callbacks from Windows)
*/ class AudioSession final : public IAudioSessionEvents { public:
AudioSession();
static AudioSession* GetSingleton();
// COM IUnknown
STDMETHODIMP_(ULONG) AddRef();
STDMETHODIMP QueryInterface(REFIID, void**);
STDMETHODIMP_(ULONG) Release();
void StartAudioSession() {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!sService);
sService = new AudioSession();
// Destroy AudioSession only after any background task threads have been // stopped or abandoned.
ClearOnShutdown(&sService, ShutdownPhase::XPCOMShutdownFinal);
AudioSession::AudioSession() : mMutex("AudioSessionControl") { // This func must be run on the main thread as // nsStringBundle is not thread safe otherwise
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(XRE_IsParentProcess(), "Should only get here in a chrome process!");
// Once we are started Windows will hold a reference to us through our // IAudioSessionEvents interface that will keep us alive until the appshell // calls Stop. void AudioSession::Start() {
MOZ_ASSERT(mscom::IsCurrentThreadMTA());
// Decrement refcount of 'this'
mAudioSessionControl->UnregisterAudioSessionNotification(this);
// Deleting the IAudioSessionControl COM object requires the STA/main thread. // Audio code may concurrently be running on the main thread and it may // block waiting for this to complete, creating deadlock. So we destroy the // IAudioSessionControl on the main thread instead. In order to do that, we // need to marshall the object to the main thread's apartment with an // AgileReference.
mscom::AgileReference agileAsc(mAudioSessionControl);
mAudioSessionControl = nullptr;
NS_DispatchToMainThread(NS_NewRunnableFunction( "FreeAudioSession",
[agileAsc = std::move(agileAsc), shouldRestart]() mutable { // Now release the AgileReference which holds our only reference to the // IAudioSessionControl, then maybe restart.
agileAsc = nullptr; if (shouldRestart) {
NS_DispatchBackgroundTask(
NS_NewCancelableRunnableFunction("RestartAudioSession", [] {
AudioSession* as = AudioSession::GetSingleton();
MOZ_ASSERT(as);
as->Start();
}));
}
}));
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.