void ShutdownLibrary() { Preferences::UnregisterCallback(PrefChanged, PREF_VOLUME_SCALE); Preferences::UnregisterCallback(PrefChanged, PREF_CUBEB_LATENCY); StaticMutexAutoLock lock(sMutex); if (sCubebContext) { cubeb_destroy(sCubebContext); sCubebContext = nullptr; } }
static void test_init_destroy_multiple_contexts(void) { int i; int r; cubeb * ctx[4]; BEGIN_TEST for (i = 0; i < 4; ++i) { r = cubeb_init(&ctx[i], NULL); assert(r == 0 && ctx[i]); } /* destroy in a different order */ cubeb_destroy(ctx[2]); cubeb_destroy(ctx[0]); cubeb_destroy(ctx[3]); cubeb_destroy(ctx[1]); END_TEST }
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 }
int cubeb_init(cubeb ** context, char const * context_name) { cubeb * ctx; assert(context); *context = NULL; ctx = calloc(1, sizeof(*ctx)); assert(ctx); ctx->work = _aligned_malloc(sizeof(*ctx->work), MEMORY_ALLOCATION_ALIGNMENT); assert(ctx->work); InitializeSListHead(ctx->work); ctx->event = CreateEvent(NULL, FALSE, FALSE, NULL); if (!ctx->event) { cubeb_destroy(ctx); return CUBEB_ERROR; } ctx->thread = (HANDLE) _beginthreadex(NULL, 64 * 1024, cubeb_buffer_thread, ctx, 0, NULL); if (!ctx->thread) { cubeb_destroy(ctx); return CUBEB_ERROR; } SetThreadPriority(ctx->thread, THREAD_PRIORITY_TIME_CRITICAL); InitializeCriticalSection(&ctx->lock); ctx->active_streams = 0; *context = ctx; return CUBEB_OK; }
static void test_init_destroy_context(void) { int r; cubeb * ctx; BEGIN_TEST r = cubeb_init(&ctx, "test_sanity"); assert(r == 0 && ctx); cubeb_destroy(ctx); END_TEST }
void AudioStream::ShutdownLibrary() { Preferences::UnregisterCallback(PrefChanged, PREF_VOLUME_SCALE); #if defined(MOZ_CUBEB) Preferences::UnregisterCallback(PrefChanged, PREF_CUBEB_LATENCY); #endif delete gAudioPrefsLock; gAudioPrefsLock = nullptr; #if defined(MOZ_CUBEB) if (gCubebContext) { cubeb_destroy(gCubebContext); gCubebContext = nullptr; } #endif }
void ShutdownLibrary() { Preferences::UnregisterCallback(PrefChanged, PREF_VOLUME_SCALE); 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; // This will ensure we don't try to re-create a context. sCubebState = CubebState::Shutdown; }
int main(int argc, char * argv[]) { #ifdef CUBEB_GECKO_BUILD ScopedXPCOM xpcom("test_latency"); #endif cubeb * ctx = NULL; int r; uint32_t max_channels; uint32_t preferred_rate; uint32_t latency_ms; LOG("latency_test start"); r = cubeb_init(&ctx, "Cubeb audio test"); assert(r == CUBEB_OK && "Cubeb init failed."); LOG("cubeb_init ok"); r = cubeb_get_max_channel_count(ctx, &max_channels); assert(r == CUBEB_OK || r == CUBEB_ERROR_NOT_SUPPORTED); if (r == CUBEB_OK) { assert(max_channels > 0 && "Invalid max channel count."); LOG("cubeb_get_max_channel_count ok"); } r = cubeb_get_preferred_sample_rate(ctx, &preferred_rate); assert(r == CUBEB_OK || r == CUBEB_ERROR_NOT_SUPPORTED); if (r == CUBEB_OK) { assert(preferred_rate > 0 && "Invalid preferred sample rate."); LOG("cubeb_get_preferred_sample_rate ok"); } cubeb_stream_params params = { CUBEB_SAMPLE_FLOAT32NE, preferred_rate, max_channels }; r = cubeb_get_min_latency(ctx, params, &latency_ms); assert(r == CUBEB_OK || r == CUBEB_ERROR_NOT_SUPPORTED); if (r == CUBEB_OK) { assert(latency_ms > 0 && "Invalid minimal latency."); LOG("cubeb_get_min_latency ok"); } cubeb_destroy(ctx); LOG("cubeb_destroy ok"); return EXIT_SUCCESS; }
int main(int argc, char *argv[]) { #ifdef CUBEB_GECKO_BUILD ScopedXPCOM xpcom("test_record"); #endif cubeb *ctx; cubeb_stream *stream; cubeb_stream_params params; int r; user_state stream_state = { false }; r = cubeb_init(&ctx, "Cubeb record example"); if (r != CUBEB_OK) { fprintf(stderr, "Error initializing cubeb library\n"); return r; } /* This test needs an available input device, skip it if this host does not * have one. */ if (!has_available_input_device(ctx)) { return 0; } params.format = STREAM_FORMAT; params.rate = SAMPLE_FREQUENCY; params.channels = 1; r = cubeb_stream_init(ctx, &stream, "Cubeb record (mono)", NULL, ¶ms, NULL, nullptr, 250, data_cb, state_cb, &stream_state); if (r != CUBEB_OK) { fprintf(stderr, "Error initializing cubeb stream\n"); return r; } cubeb_stream_start(stream); delay(500); cubeb_stream_stop(stream); cubeb_stream_destroy(stream); cubeb_destroy(ctx); assert(stream_state.seen_noise); return CUBEB_OK; }
TEST(cubeb, init_destroy_context) { int r; cubeb * ctx; char const* backend_id; r = common_init(&ctx, "test_sanity"); ASSERT_EQ(r, CUBEB_OK); ASSERT_NE(ctx, nullptr); backend_id = cubeb_get_backend_id(ctx); ASSERT_TRUE(backend_id); fprintf(stderr, "Backend: %s\n", backend_id); cubeb_destroy(ctx); }
static void test_basic_stream_operations(void) { int r; cubeb * ctx; cubeb_stream * stream; cubeb_stream_params params; uint64_t position; BEGIN_TEST r = cubeb_init(&ctx, "test_sanity"); assert(r == 0 && ctx); params.format = STREAM_FORMAT; params.rate = STREAM_RATE; params.channels = STREAM_CHANNELS; r = cubeb_stream_init(ctx, &stream, "test", params, STREAM_LATENCY, test_data_callback, test_state_callback, &dummy); assert(r == 0 && stream); /* position and volume before stream has started */ r = cubeb_stream_get_position(stream, &position); assert(r == 0 && position == 0); r = cubeb_stream_start(stream); assert(r == 0); /* position and volume after while stream running */ r = cubeb_stream_get_position(stream, &position); assert(r == 0); r = cubeb_stream_stop(stream); assert(r == 0); /* position and volume after stream has stopped */ r = cubeb_stream_get_position(stream, &position); assert(r == 0); cubeb_stream_destroy(stream); cubeb_destroy(ctx); END_TEST }
TEST(cubeb, basic_stream_operations) { int r; cubeb * ctx; cubeb_stream * stream; cubeb_stream_params params; uint64_t position; r = common_init(&ctx, "test_sanity"); ASSERT_EQ(r, CUBEB_OK); ASSERT_NE(ctx, nullptr); params.format = STREAM_FORMAT; params.rate = STREAM_RATE; params.channels = STREAM_CHANNELS; params.layout = STREAM_LAYOUT; r = cubeb_stream_init(ctx, &stream, "test", NULL, NULL, NULL, ¶ms, STREAM_LATENCY, test_data_callback, test_state_callback, &dummy); ASSERT_EQ(r, CUBEB_OK); ASSERT_NE(stream, nullptr); /* position and volume before stream has started */ r = cubeb_stream_get_position(stream, &position); ASSERT_EQ(r, CUBEB_OK); ASSERT_EQ(position, 0u); r = cubeb_stream_start(stream); ASSERT_EQ(r, CUBEB_OK); /* position and volume after while stream running */ r = cubeb_stream_get_position(stream, &position); ASSERT_EQ(r, CUBEB_OK); r = cubeb_stream_stop(stream); ASSERT_EQ(r, CUBEB_OK); /* position and volume after stream has stopped */ r = cubeb_stream_get_position(stream, &position); ASSERT_EQ(r, CUBEB_OK); cubeb_stream_destroy(stream); cubeb_destroy(ctx); }
TEST(cubeb, init_destroy_multiple_contexts) { size_t i; int r; cubeb * ctx[4]; int order[4] = {2, 0, 3, 1}; ASSERT_EQ(ARRAY_LENGTH(ctx), ARRAY_LENGTH(order)); for (i = 0; i < ARRAY_LENGTH(ctx); ++i) { r = common_init(&ctx[i], NULL); ASSERT_EQ(r, CUBEB_OK); ASSERT_NE(ctx[i], nullptr); } /* destroy in a different order */ for (i = 0; i < ARRAY_LENGTH(ctx); ++i) { cubeb_destroy(ctx[order[i]]); } }
TEST(cubeb, init_destroy_multiple_contexts_and_streams) { size_t i, j; int r; cubeb * ctx[2]; cubeb_stream * stream[8]; cubeb_stream_params params; size_t streams_per_ctx = ARRAY_LENGTH(stream) / ARRAY_LENGTH(ctx); ASSERT_EQ(ARRAY_LENGTH(ctx) * streams_per_ctx, ARRAY_LENGTH(stream)); /* Sometimes, when using WASAPI on windows 7 (vista and 8 are okay), and * calling Activate a lot on an AudioClient, 0x800700b7 is returned. This is * the HRESULT value for "Cannot create a file when that file already exists", * and is not documented as a possible return value for this call. Hence, we * try to limit the number of streams we create in this test. */ if (is_windows_7()) return; params.format = STREAM_FORMAT; params.rate = STREAM_RATE; params.channels = STREAM_CHANNELS; params.layout = STREAM_LAYOUT; for (i = 0; i < ARRAY_LENGTH(ctx); ++i) { r = common_init(&ctx[i], "test_sanity"); ASSERT_EQ(r, CUBEB_OK); ASSERT_NE(ctx[i], nullptr); for (j = 0; j < streams_per_ctx; ++j) { r = cubeb_stream_init(ctx[i], &stream[i * streams_per_ctx + j], "test", NULL, NULL, NULL, ¶ms, STREAM_LATENCY, test_data_callback, test_state_callback, &dummy); ASSERT_EQ(r, CUBEB_OK); ASSERT_NE(stream[i * streams_per_ctx + j], nullptr); } } for (i = 0; i < ARRAY_LENGTH(ctx); ++i) { for (j = 0; j < streams_per_ctx; ++j) { cubeb_stream_destroy(stream[i * streams_per_ctx + j]); } cubeb_destroy(ctx[i]); } }
TEST(cubeb, record) { 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; 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); ASSERT_TRUE(stream_state.seen_noise); }
static void test_init_destroy_context(void) { int r; cubeb * ctx; char const* backend_id; BEGIN_TEST; r = cubeb_init(&ctx, "test_sanity"); assert(r == 0 && ctx); backend_id = cubeb_get_backend_id(ctx); assert(backend_id); fprintf(stderr, "Backend: %s\n", backend_id); cubeb_destroy(ctx); END_TEST; }
static void test_init_destroy_multiple_contexts_and_streams(void) { size_t i, j; int r; cubeb * ctx[2]; cubeb_stream * stream[8]; cubeb_stream_params params; size_t streams_per_ctx = ARRAY_LENGTH(stream) / ARRAY_LENGTH(ctx); assert(ARRAY_LENGTH(ctx) * streams_per_ctx == ARRAY_LENGTH(stream)); BEGIN_TEST; params.format = STREAM_FORMAT; params.rate = STREAM_RATE; params.channels = STREAM_CHANNELS; for (i = 0; i < ARRAY_LENGTH(ctx); ++i) { r = cubeb_init(&ctx[i], "test_sanity"); assert(r == 0 && ctx[i]); for (j = 0; j < streams_per_ctx; ++j) { r = cubeb_stream_init(ctx[i], &stream[i * streams_per_ctx + j], "test", params, STREAM_LATENCY, test_data_callback, test_state_callback, &dummy); assert(r == 0); assert(stream[i * streams_per_ctx + j]); } } for (i = 0; i < ARRAY_LENGTH(ctx); ++i) { for (j = 0; j < streams_per_ctx; ++j) { cubeb_stream_destroy(stream[i * streams_per_ctx + j]); } cubeb_destroy(ctx[i]); } END_TEST; }
TEST(cubeb, stable_devid) { /* Test that the devid field of cubeb_device_info is stable * (ie. compares equal) over two invocations of * cubeb_enumerate_devices(). */ int r; cubeb * ctx; cubeb_device_collection first; cubeb_device_collection second; cubeb_device_type all_devices = (cubeb_device_type) (CUBEB_DEVICE_TYPE_INPUT | CUBEB_DEVICE_TYPE_OUTPUT); size_t n; r = common_init(&ctx, "test_sanity"); ASSERT_EQ(r, CUBEB_OK); ASSERT_NE(ctx, nullptr); r = cubeb_enumerate_devices(ctx, all_devices, &first); if (r == CUBEB_ERROR_NOT_SUPPORTED) return; ASSERT_EQ(r, CUBEB_OK); r = cubeb_enumerate_devices(ctx, all_devices, &second); ASSERT_EQ(r, CUBEB_OK); ASSERT_EQ(first.count, second.count); for (n = 0; n < first.count; n++) { ASSERT_EQ(first.device[n].devid, second.device[n].devid); } r = cubeb_device_collection_destroy(ctx, &first); ASSERT_EQ(r, CUBEB_OK); r = cubeb_device_collection_destroy(ctx, &second); ASSERT_EQ(r, CUBEB_OK); cubeb_destroy(ctx); }
int main(int argc, char * argv[]) { cubeb * ctx = NULL; int rv; uint32_t max_channels; uint32_t preferred_rate; uint32_t latency_ms; LOG("latency_test start"); rv = cubeb_init(&ctx, "Cubeb audio test"); assert(rv == CUBEB_OK && "Cubeb init failed."); LOG("cubeb_init ok"); rv = cubeb_get_max_channel_count(ctx, &max_channels); assert(rv == CUBEB_OK && "Could not query the max channe count."); assert(max_channels > 0 && "Invalid max channel count."); LOG("cubeb_get_max_channel_count ok"); rv = cubeb_get_preferred_sample_rate(ctx, &preferred_rate); assert(rv == CUBEB_OK && "Could not query the preferred sample rate."); assert(preferred_rate && "Invalid preferred sample rate."); LOG("cubeb_get_preferred_sample_rate ok"); cubeb_stream_params params = { CUBEB_SAMPLE_FLOAT32NE, preferred_rate, max_channels }; rv = cubeb_get_min_latency(ctx, params, &latency_ms); assert(rv == CUBEB_OK && "Could not query the minimal latency."); assert(latency_ms && "Invalid minimal latency."); LOG("cubeb_get_min_latency ok"); cubeb_destroy(ctx); LOG("cubeb_destroy ok"); return EXIT_SUCCESS; }
static void test_init_destroy_multiple_contexts(void) { size_t i; int r; cubeb * ctx[4]; int order[4] = {2, 0, 3, 1}; assert(ARRAY_LENGTH(ctx) == ARRAY_LENGTH(order)); BEGIN_TEST; for (i = 0; i < ARRAY_LENGTH(ctx); ++i) { r = cubeb_init(&ctx[i], NULL); assert(r == 0 && ctx[i]); } /* destroy in a different order */ for (i = 0; i < ARRAY_LENGTH(ctx); ++i) { cubeb_destroy(ctx[order[i]]); } END_TEST; }
TEST(cubeb, init_destroy_stream) { int r; cubeb * ctx; cubeb_stream * stream; cubeb_stream_params params; r = common_init(&ctx, "test_sanity"); ASSERT_EQ(r, CUBEB_OK); ASSERT_NE(ctx, nullptr); params.format = STREAM_FORMAT; params.rate = STREAM_RATE; params.channels = STREAM_CHANNELS; params.layout = STREAM_LAYOUT; r = cubeb_stream_init(ctx, &stream, "test", NULL, NULL, NULL, ¶ms, STREAM_LATENCY, test_data_callback, test_state_callback, &dummy); ASSERT_EQ(r, CUBEB_OK); ASSERT_NE(stream, nullptr); cubeb_stream_destroy(stream); cubeb_destroy(ctx); }
static void test_init_destroy_multiple_contexts_and_streams(void) { int i, j; int r; cubeb * ctx[2]; cubeb_stream * stream[8]; cubeb_stream_params params; BEGIN_TEST params.format = STREAM_FORMAT; params.rate = STREAM_RATE; params.channels = STREAM_CHANNELS; for (i = 0; i < 2; ++i) { r = cubeb_init(&ctx[i], "test_sanity"); assert(r == 0 && ctx[i]); for (j = 0; j < 4; ++j) { r = cubeb_stream_init(ctx[i], &stream[i * 4 + j], "test", params, STREAM_LATENCY, test_data_callback, test_state_callback, &dummy); assert(r == 0); assert(stream[i * 4 + j]); } } for (i = 0; i < 2; ++i) { for (j = 0; j < 4; ++j) { cubeb_stream_destroy(stream[i * 4 + j]); } cubeb_destroy(ctx[i]); } END_TEST }
int run_panning_volume_test(int is_float) { int r = CUBEB_OK; cubeb *ctx = NULL; synth_state* synth = NULL; cubeb_stream *stream = NULL; const char * backend_id = NULL; r = cubeb_init(&ctx, "Cubeb audio test"); if (r != CUBEB_OK) { fprintf(stderr, "Error initializing cubeb library\n"); goto cleanup; } backend_id = cubeb_get_backend_id(ctx); if ((is_float && !supports_float32(backend_id)) || (!is_float && !supports_int16(backend_id))) { /* don't treat this as a test failure. */ goto cleanup; } cubeb_stream_params params; params.format = is_float ? CUBEB_SAMPLE_FLOAT32NE : CUBEB_SAMPLE_S16NE; params.rate = 44100; params.channels = 2; synth = synth_create(params.channels, params.rate); if (synth == NULL) { fprintf(stderr, "Out of memory\n"); goto cleanup; } r = cubeb_stream_init(ctx, &stream, "test tone", NULL, NULL, NULL, ¶ms, 4096, is_float ? data_cb_float : data_cb_short, state_cb_audio, synth); if (r != CUBEB_OK) { fprintf(stderr, "Error initializing cubeb stream: %d\n", r); goto cleanup; } fprintf(stderr, "Testing: volume\n"); for(int i=0;i <= 4; ++i) { fprintf(stderr, "Volume: %d%%\n", i*25); cubeb_stream_set_volume(stream, i/4.0f); cubeb_stream_start(stream); delay(400); cubeb_stream_stop(stream); delay(100); } fprintf(stderr, "Testing: panning\n"); for(int i=-4;i <= 4; ++i) { fprintf(stderr, "Panning: %.2f%%\n", i/4.0f); cubeb_stream_set_panning(stream, i/4.0f); cubeb_stream_start(stream); delay(400); cubeb_stream_stop(stream); delay(100); } cleanup: cubeb_stream_destroy(stream); cubeb_destroy(ctx); synth_destroy(synth); return r; }
TEST(cubeb, stream_position) { size_t i; int r; cubeb * ctx; cubeb_stream * stream; cubeb_stream_params params; uint64_t position, last_position; total_frames_written = 0; r = common_init(&ctx, "test_sanity"); ASSERT_EQ(r, CUBEB_OK); ASSERT_NE(ctx, nullptr); params.format = STREAM_FORMAT; params.rate = STREAM_RATE; params.channels = STREAM_CHANNELS; params.layout = STREAM_LAYOUT; r = cubeb_stream_init(ctx, &stream, "test", NULL, NULL, NULL, ¶ms, STREAM_LATENCY, test_data_callback, test_state_callback, &dummy); ASSERT_EQ(r, CUBEB_OK); ASSERT_NE(stream, nullptr); /* stream position should not advance before starting playback */ r = cubeb_stream_get_position(stream, &position); ASSERT_EQ(r, CUBEB_OK); ASSERT_EQ(position, 0u); delay(500); r = cubeb_stream_get_position(stream, &position); ASSERT_EQ(r, CUBEB_OK); ASSERT_EQ(position, 0u); /* stream position should advance during playback */ r = cubeb_stream_start(stream); ASSERT_EQ(r, CUBEB_OK); /* XXX let start happen */ delay(500); /* stream should have prefilled */ ASSERT_TRUE(total_frames_written.load() > 0); r = cubeb_stream_get_position(stream, &position); ASSERT_EQ(r, CUBEB_OK); last_position = position; delay(500); r = cubeb_stream_get_position(stream, &position); ASSERT_EQ(r, CUBEB_OK); ASSERT_GE(position, last_position); last_position = position; /* stream position should not exceed total frames written */ for (i = 0; i < 5; ++i) { r = cubeb_stream_get_position(stream, &position); ASSERT_EQ(r, CUBEB_OK); ASSERT_GE(position, last_position); ASSERT_LE(position, total_frames_written.load()); last_position = position; delay(500); } /* test that the position is valid even when starting and * stopping the stream. */ for (i = 0; i < 5; ++i) { r = cubeb_stream_stop(stream); ASSERT_EQ(r, CUBEB_OK); r = cubeb_stream_get_position(stream, &position); ASSERT_EQ(r, CUBEB_OK); ASSERT_TRUE(last_position < position); last_position = position; delay(500); r = cubeb_stream_start(stream); ASSERT_EQ(r, CUBEB_OK); delay(500); } ASSERT_NE(last_position, 0u); /* stream position should not advance after stopping playback */ r = cubeb_stream_stop(stream); ASSERT_EQ(r, CUBEB_OK); /* XXX allow stream to settle */ delay(500); r = cubeb_stream_get_position(stream, &position); ASSERT_EQ(r, CUBEB_OK); last_position = position; delay(500); r = cubeb_stream_get_position(stream, &position); ASSERT_EQ(r, CUBEB_OK); ASSERT_EQ(position, last_position); cubeb_stream_destroy(stream); cubeb_destroy(ctx); }
int cubeb_init(cubeb ** context, char const * context_name) { cubeb * ctx; *context = NULL; ctx = calloc(1, sizeof(*ctx)); assert(ctx); ctx->lib = dlopen("libOpenSLES.so", RTLD_LAZY); if (!ctx->lib) { free(ctx); return CUBEB_ERROR; } typedef SLresult (*slCreateEngine_t)(SLObjectItf *, SLuint32, const SLEngineOption *, SLuint32, const SLInterfaceID *, const SLboolean *); slCreateEngine_t f_slCreateEngine = (slCreateEngine_t)dlsym(ctx->lib, "slCreateEngine"); SLInterfaceID SL_IID_ENGINE = *(SLInterfaceID *)dlsym(ctx->lib, "SL_IID_ENGINE"); SLInterfaceID SL_IID_OUTPUTMIX = *(SLInterfaceID *)dlsym(ctx->lib, "SL_IID_OUTPUTMIX"); ctx->SL_IID_BUFFERQUEUE = *(SLInterfaceID *)dlsym(ctx->lib, "SL_IID_BUFFERQUEUE"); ctx->SL_IID_PLAY = *(SLInterfaceID *)dlsym(ctx->lib, "SL_IID_PLAY"); if (!f_slCreateEngine || !SL_IID_ENGINE || !SL_IID_OUTPUTMIX || !ctx->SL_IID_BUFFERQUEUE || !ctx->SL_IID_PLAY) { cubeb_destroy(ctx); return CUBEB_ERROR; } const SLEngineOption opt[] = {{SL_ENGINEOPTION_THREADSAFE, SL_BOOLEAN_TRUE}}; SLresult res; res = f_slCreateEngine(&ctx->engObj, 1, opt, 0, NULL, NULL); if (res != SL_RESULT_SUCCESS) { cubeb_destroy(ctx); return CUBEB_ERROR; } res = (*ctx->engObj)->Realize(ctx->engObj, SL_BOOLEAN_FALSE); if (res != SL_RESULT_SUCCESS) { cubeb_destroy(ctx); return CUBEB_ERROR; } res = (*ctx->engObj)->GetInterface(ctx->engObj, SL_IID_ENGINE, &ctx->eng); if (res != SL_RESULT_SUCCESS) { cubeb_destroy(ctx); return CUBEB_ERROR; } const SLInterfaceID idsom[] = {SL_IID_OUTPUTMIX}; const SLboolean reqom[] = {SL_BOOLEAN_TRUE}; res = (*ctx->eng)->CreateOutputMix(ctx->eng, &ctx->outmixObj, 1, idsom, reqom); if (res != SL_RESULT_SUCCESS) { cubeb_destroy(ctx); return CUBEB_ERROR; } res = (*ctx->outmixObj)->Realize(ctx->outmixObj, SL_BOOLEAN_FALSE); if (res != SL_RESULT_SUCCESS) { cubeb_destroy(ctx); return CUBEB_ERROR; } *context = ctx; return CUBEB_OK; }
static void test_stream_position(void) { int i; int r; cubeb * ctx; cubeb_stream * stream; cubeb_stream_params params; uint64_t position, last_position; BEGIN_TEST total_frames_written = 0; r = cubeb_init(&ctx, "test_sanity"); assert(r == 0 && ctx); params.format = STREAM_FORMAT; params.rate = STREAM_RATE; params.channels = STREAM_CHANNELS; r = cubeb_stream_init(ctx, &stream, "test", params, STREAM_LATENCY, test_data_callback, test_state_callback, &dummy); assert(r == 0 && stream); /* stream position should not advance before starting playback */ r = cubeb_stream_get_position(stream, &position); assert(r == 0 && position == 0); delay(500); r = cubeb_stream_get_position(stream, &position); assert(r == 0 && position == 0); /* stream position should advance during playback */ r = cubeb_stream_start(stream); assert(r == 0); /* XXX let start happen */ delay(500); /* stream should have prefilled */ assert(total_frames_written > 0); r = cubeb_stream_get_position(stream, &position); assert(r == 0); last_position = position; delay(500); r = cubeb_stream_get_position(stream, &position); assert(r == 0); assert(position >= last_position); last_position = position; /* stream position should not exceed total frames written */ for (i = 0; i < 5; ++i) { r = cubeb_stream_get_position(stream, &position); assert(r == 0); assert(position >= last_position); assert(position <= total_frames_written); last_position = position; delay(500); } assert(last_position != 0); /* stream position should not advance after stopping playback */ r = cubeb_stream_stop(stream); assert(r == 0); /* XXX allow stream to settle */ delay(500); r = cubeb_stream_get_position(stream, &position); assert(r == 0); last_position = position; delay(500); r = cubeb_stream_get_position(stream, &position); assert(r == 0); assert(position == last_position); cubeb_stream_destroy(stream); cubeb_destroy(ctx); END_TEST }
static void test_drain(void) { int r; cubeb * ctx; cubeb_stream * stream; cubeb_stream_params params; uint64_t position; BEGIN_TEST total_frames_written = 0; r = cubeb_init(&ctx, "test_sanity"); assert(r == 0 && ctx); params.format = STREAM_FORMAT; params.rate = STREAM_RATE; params.channels = STREAM_CHANNELS; r = cubeb_stream_init(ctx, &stream, "test", params, STREAM_LATENCY, test_drain_data_callback, test_drain_state_callback, &dummy); assert(r == 0 && stream); r = cubeb_stream_start(stream); assert(r == 0); delay(500); do_drain = 1; for (;;) { r = cubeb_stream_get_position(stream, &position); assert(r == 0); if (got_drain) { break; } else { uint32_t i, skip = 0; /* Latency passed to cubeb_stream_init is not really honored on OSX, win32/winmm and android, skip this test. */ const char * backend_id = cubeb_get_backend_id(ctx); const char * latency_not_honored_bakends[] = { "audiounit", "winmm", "audiotrack", "opensl" }; for (i = 0; i < ARRAY_LENGTH(latency_not_honored_bakends); i++) { if (!strcmp(backend_id, latency_not_honored_bakends[i])) { skip = 1; } } if (!skip) { /* Position should roughly be equal to the number of written frames. We * need to take the latency into account. */ int latency = (STREAM_LATENCY * STREAM_RATE) / 1000; assert(position + latency <= total_frames_written); } } delay(500); } r = cubeb_stream_get_position(stream, &position); assert(r == 0); assert(got_drain); // Disabled due to failures in the ALSA backend. //assert(position == total_frames_written); cubeb_stream_destroy(stream); cubeb_destroy(ctx); END_TEST }