cubeb* GetCubebContextUnlocked() { sMutex.AssertCurrentThreadOwns(); if (sCubebState != CubebState::Uninitialized) { // If we have already passed the initialization point (below), just return // the current context, which may be null (e.g., after error or shutdown.) return sCubebContext; } 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); 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); } return sCubebContext; }
void PrefChanged(const char* aPref, void* aClosure) { if (strcmp(aPref, PREF_VOLUME_SCALE) == 0) { nsAdoptingString value = Preferences::GetString(aPref); StaticMutexAutoLock lock(sMutex); if (value.IsEmpty()) { sVolumeScale = 1.0; } else { NS_ConvertUTF16toUTF8 utf8(value); sVolumeScale = std::max<double>(0, PR_strtod(utf8.get(), nullptr)); } } else if (strcmp(aPref, PREF_CUBEB_LATENCY_PLAYBACK) == 0) { // Arbitrary default stream latency of 100ms. The higher this // value, the longer stream volume changes will take to become // audible. sCubebPlaybackLatencyPrefSet = Preferences::HasUserValue(aPref); uint32_t value = Preferences::GetUint(aPref, CUBEB_NORMAL_LATENCY_MS); StaticMutexAutoLock lock(sMutex); sCubebPlaybackLatencyInMilliseconds = std::min<uint32_t>(std::max<uint32_t>(value, 1), 1000); } else if (strcmp(aPref, PREF_CUBEB_LATENCY_MSG) == 0) { sCubebMSGLatencyPrefSet = Preferences::HasUserValue(aPref); uint32_t value = Preferences::GetUint(aPref, CUBEB_NORMAL_LATENCY_FRAMES); StaticMutexAutoLock lock(sMutex); // 128 is the block size for the Web Audio API, which limits how low the // latency can be here. // We don't want to limit the upper limit too much, so that people can // experiment. sCubebMSGLatencyInFrames = std::min<uint32_t>(std::max<uint32_t>(value, 128), 1e6); } else if (strcmp(aPref, PREF_CUBEB_LOG_LEVEL) == 0) { nsAdoptingString value = Preferences::GetString(aPref); NS_ConvertUTF16toUTF8 utf8(value); LogModule* cubebLog = LogModule::Get("cubeb"); if (strcmp(utf8.get(), "verbose") == 0) { cubeb_set_log_callback(CUBEB_LOG_VERBOSE, CubebLogCallback); 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); } } }
TEST(cubeb, record) { if (cubeb_set_log_callback(CUBEB_LOG_DISABLED, nullptr /*print_log*/) != CUBEB_OK) { printf("Set log callback failed\n"); } cubeb *ctx; cubeb_stream *stream; cubeb_stream_params params; int r; user_state_record stream_state = { false }; r = cubeb_init(&ctx, "Cubeb record example"); if (r != CUBEB_OK) { fprintf(stderr, "Error initializing cubeb library\n"); ASSERT_EQ(r, CUBEB_OK); } /* This test needs an available input device, skip it if this host does not * have one. */ if (!has_available_input_device(ctx)) { return; } params.format = STREAM_FORMAT; params.rate = SAMPLE_FREQUENCY; params.channels = 1; params.layout = CUBEB_LAYOUT_MONO; r = cubeb_stream_init(ctx, &stream, "Cubeb record (mono)", NULL, ¶ms, NULL, nullptr, 4096, data_cb_record, state_cb_record, &stream_state); if (r != CUBEB_OK) { fprintf(stderr, "Error initializing cubeb stream\n"); ASSERT_EQ(r, CUBEB_OK); } cubeb_stream_start(stream); delay(500); cubeb_stream_stop(stream); cubeb_stream_destroy(stream); cubeb_destroy(ctx); #ifdef __linux__ // user callback does not arrive in Linux, silence the error printf("Check is disabled in Linux\n"); #else ASSERT_TRUE(stream_state.seen_audio); #endif }