--- a/dom/media/CubebUtils.cpp
+++ b/dom/media/CubebUtils.cpp
@@ -15,16 +15,17 @@
#include "mozilla/Telemetry.h"
#include "mozilla/Logging.h"
#include "nsThreadUtils.h"
#include "CubebUtils.h"
#include "nsAutoRef.h"
#include "prdtoa.h"
#define PREF_VOLUME_SCALE "media.volume_scale"
+#define PREF_CUBEB_BACKEND "media.cubeb.backend"
#define PREF_CUBEB_LATENCY_PLAYBACK "media.cubeb_latency_playback_ms"
#define PREF_CUBEB_LATENCY_MSG "media.cubeb_latency_msg_frames"
#define PREF_CUBEB_LOG_LEVEL "media.cubeb.log_level"
#define MASK_MONO (1 << AudioConfig::CHANNEL_MONO)
#define MASK_MONO_LFE (MASK_MONO | (1 << AudioConfig::CHANNEL_LFE))
#define MASK_STEREO ((1 << AudioConfig::CHANNEL_LEFT) | (1 << AudioConfig::CHANNEL_RIGHT))
#define MASK_STEREO_LFE (MASK_STEREO | (1 << AudioConfig::CHANNEL_LFE))
@@ -68,16 +69,17 @@ enum class CubebState {
cubeb* sCubebContext;
double sVolumeScale;
uint32_t sCubebPlaybackLatencyInMilliseconds;
uint32_t sCubebMSGLatencyInFrames;
bool sCubebPlaybackLatencyPrefSet;
bool sCubebMSGLatencyPrefSet;
bool sAudioStreamInitEverSucceeded = false;
StaticAutoPtr<char> sBrandName;
+StaticAutoPtr<char> sCubebBackendName;
const char kBrandBundleURL[] = "chrome://branding/locale/brand.properties";
const char* AUDIOSTREAM_BACKEND_ID_STR[] = {
"jack",
"pulse",
"alsa",
"audiounit",
@@ -163,16 +165,27 @@ void PrefChanged(const char* aPref, void
cubebLog->SetLevel(LogLevel::Verbose);
} else if (strcmp(utf8.get(), "normal") == 0) {
cubeb_set_log_callback(CUBEB_LOG_NORMAL, CubebLogCallback);
cubebLog->SetLevel(LogLevel::Error);
} else if (utf8.IsEmpty()) {
cubeb_set_log_callback(CUBEB_LOG_DISABLED, nullptr);
cubebLog->SetLevel(LogLevel::Disabled);
}
+ } else if (strcmp(aPref, PREF_CUBEB_BACKEND) == 0) {
+ nsAdoptingString value = Preferences::GetString(aPref);
+ if (value.IsEmpty()) {
+ sCubebBackendName = nullptr;
+ } else {
+ /* cubeb expects a c-string. */
+ const char* ascii = NS_LossyConvertUTF16toASCII(value).get();
+ sCubebBackendName = new char[value.Length() + 1];
+ PodCopy(sCubebBackendName.get(), ascii, value.Length());
+ sCubebBackendName[value.Length()] = 0;
+ }
}
}
bool GetFirstStream()
{
static bool sFirstStream = true;
StaticMutexAutoLock lock(sMutex);
@@ -323,17 +336,17 @@ cubeb* GetCubebContextUnlocked()
if (!sBrandName && NS_IsMainThread()) {
InitBrandName();
} else {
NS_WARNING_ASSERTION(
sBrandName, "Did not initialize sbrandName, and not on the main thread?");
}
- int rv = cubeb_init(&sCubebContext, sBrandName);
+ int rv = cubeb_init(&sCubebContext, sBrandName, sCubebBackendName.get());
NS_WARNING_ASSERTION(rv == CUBEB_OK, "Could not get a cubeb context.");
sCubebState = (rv == CUBEB_OK) ? CubebState::Initialized : CubebState::Uninitialized;
if (MOZ_LOG_TEST(gCubebLog, LogLevel::Verbose)) {
cubeb_set_log_callback(CUBEB_LOG_VERBOSE, CubebLogCallback);
} else if (MOZ_LOG_TEST(gCubebLog, LogLevel::Error)) {
cubeb_set_log_callback(CUBEB_LOG_NORMAL, CubebLogCallback);
}
@@ -403,37 +416,41 @@ Maybe<uint32_t> GetCubebMSGLatencyInFram
}
void InitLibrary()
{
PrefChanged(PREF_VOLUME_SCALE, nullptr);
Preferences::RegisterCallback(PrefChanged, PREF_VOLUME_SCALE);
PrefChanged(PREF_CUBEB_LATENCY_PLAYBACK, nullptr);
PrefChanged(PREF_CUBEB_LATENCY_MSG, nullptr);
+ PrefChanged(PREF_CUBEB_BACKEND, nullptr);
+ Preferences::RegisterCallback(PrefChanged, PREF_CUBEB_BACKEND);
Preferences::RegisterCallback(PrefChanged, PREF_CUBEB_LATENCY_PLAYBACK);
Preferences::RegisterCallback(PrefChanged, PREF_CUBEB_LATENCY_MSG);
Preferences::RegisterCallback(PrefChanged, PREF_CUBEB_LOG_LEVEL);
#ifndef MOZ_WIDGET_ANDROID
NS_DispatchToMainThread(NS_NewRunnableFunction(&InitBrandName));
#endif
}
void ShutdownLibrary()
{
Preferences::UnregisterCallback(PrefChanged, PREF_VOLUME_SCALE);
+ Preferences::UnregisterCallback(PrefChanged, PREF_CUBEB_BACKEND);
Preferences::UnregisterCallback(PrefChanged, PREF_CUBEB_LATENCY_PLAYBACK);
Preferences::UnregisterCallback(PrefChanged, PREF_CUBEB_LATENCY_MSG);
Preferences::UnregisterCallback(PrefChanged, PREF_CUBEB_LOG_LEVEL);
StaticMutexAutoLock lock(sMutex);
if (sCubebContext) {
cubeb_destroy(sCubebContext);
sCubebContext = nullptr;
}
sBrandName = nullptr;
+ sCubebBackendName = nullptr;
// This will ensure we don't try to re-create a context.
sCubebState = CubebState::Shutdown;
}
uint32_t MaxNumberOfChannels()
{
cubeb* cubebContext = GetCubebContext();
uint32_t maxNumberOfChannels;