Bug 1132257 - Update cubeb from upstream. r=padenot

This commit is contained in:
Matthew Gregan 2015-02-17 11:52:59 +13:00
Родитель a533827683
Коммит 8b8ae2538d
4 изменённых файлов: 150 добавлений и 116 удалений

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

@ -5,4 +5,4 @@ Makefile.in build files for the Mozilla build system.
The cubeb git repository is: git://github.com/kinetiknz/cubeb.git
The git commit ID used was 14d97931da6435d10aa4dcb444896af0314372f4.
The git commit ID used was 66aa55bb3b883381a73ad12d20688b932858be28.

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

@ -477,7 +477,6 @@ audiounit_stream_init(cubeb * context, cubeb_stream ** stream, char const * stre
unsigned int buffer_size, default_buffer_size;
OSStatus r;
UInt32 size;
AudioDeviceID output_device_id;
AudioValueRange latency_range;
assert(context);
@ -783,7 +782,6 @@ audiounit_stream_get_latency(cubeb_stream * stm, uint32_t * latency)
int audiounit_stream_set_volume(cubeb_stream * stm, float volume)
{
AudioDeviceID id;
OSStatus r;
r = AudioUnitSetParameter(stm->unit,

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

@ -34,15 +34,14 @@
// #define LOGGING_ENABLED
#ifdef LOGGING_ENABLED
# define LOG(...) do { \
fprintf(stdout, __VA_ARGS__); \
fprintf(stdout, "\n"); \
} while(0);
#define LOG(...) do { \
fprintf(stderr, __VA_ARGS__); \
} while(0)
#else
# define LOG(...)
#define LOG(...)
#endif
#define ARRAY_LENGTH(array_) \
#define ARRAY_LENGTH(array_) \
(sizeof(array_) / sizeof(array_[0]))
namespace {
@ -85,7 +84,6 @@ void SafeRelease(T * ptr)
class owned_critical_section
{
public:
owned_critical_section()
#ifdef DEBUG
: owner(0)
@ -136,7 +134,7 @@ private:
struct auto_lock {
auto_lock(owned_critical_section * lock)
:lock(lock)
: lock(lock)
{
lock->enter();
}
@ -150,7 +148,7 @@ private:
struct auto_unlock {
auto_unlock(owned_critical_section * lock)
:lock(lock)
: lock(lock)
{
lock->leave();
}
@ -163,33 +161,29 @@ private:
};
struct auto_com {
auto_com()
: need_uninit(false) {
HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
// This is for information purposes only, in anycase, COM is initialized
// at the end of the constructor.
if (hr == RPC_E_CHANGED_MODE) {
// This is an error, COM was not initialized by this function, so it is
auto_com() {
result = CoInitializeEx(NULL, COINIT_MULTITHREADED);
}
~auto_com() {
if (result == RPC_E_CHANGED_MODE) {
// This is not an error, COM was not initialized by this function, so it is
// not necessary to uninit it.
LOG("COM already initialized in STA.");
} else if (hr == S_FALSE) {
LOG("COM already initialized in STA.\n");
} else if (result == S_FALSE) {
// This is not an error. We are allowed to call CoInitializeEx more than
// once, as long as it is matches by an CoUninitialize call.
// We do that in the dtor which is guaranteed to be called.
LOG("COM already initialized in MTA");
need_uninit = true;
} else if (hr == S_OK) {
LOG("COM initialized.");
need_uninit = true;
LOG("COM already initialized in MTA\n");
}
}
~auto_com() {
if (need_uninit) {
if (SUCCEEDED(result)) {
CoUninitialize();
}
}
bool ok() {
return result == RPC_E_CHANGED_MODE || SUCCEEDED(result);
}
private:
bool need_uninit;
HRESULT result;
};
typedef HANDLE (WINAPI *set_mm_thread_characteristics_function)(
@ -205,7 +199,6 @@ int setup_wasapi_stream(cubeb_stream * stm);
}
struct cubeb
{
cubeb_ops const * ops;
@ -258,7 +251,7 @@ struct cubeb_stream
HANDLE refill_event;
/* Each cubeb_stream has its own thread. */
HANDLE thread;
/* We synthetize our clock from the callbacks. */
/* We synthesize our clock from the callbacks. */
LONG64 clock;
owned_critical_section * stream_reset_lock;
/* Maximum number of frames we can be requested in a callback. */
@ -296,7 +289,7 @@ public:
HRESULT STDMETHODCALLTYPE
QueryInterface(REFIID riid, VOID **ppvInterface)
{
if (IID_IUnknown == riid) {
if (__uuidof(IUnknown) == riid) {
AddRef();
*ppvInterface = (IUnknown*)this;
} else if (__uuidof(IMMNotificationClient) == riid) {
@ -326,7 +319,10 @@ public:
return S_OK;
}
auto_com autocom;
auto_com com;
if (!com.ok()) {
return E_FAIL;
}
/* Close the stream */
wasapi_stream_stop(stm);
@ -346,27 +342,27 @@ public:
* log is enabled), for debugging. */
HRESULT STDMETHODCALLTYPE OnDeviceAdded(LPCWSTR device_id)
{
LOG("Audio device added.");
LOG("Audio device added.\n");
return S_OK;
};
HRESULT STDMETHODCALLTYPE OnDeviceRemoved(LPCWSTR device_id)
{
LOG("Audio device removed.");
LOG("Audio device removed.\n");
return S_OK;
}
HRESULT STDMETHODCALLTYPE
OnDeviceStateChanged(LPCWSTR device_id, DWORD new_state)
{
LOG("Audio device state changed.");
LOG("Audio device state changed.\n");
return S_OK;
}
HRESULT STDMETHODCALLTYPE
OnPropertyValueChanged(LPCWSTR device_id, const PROPERTYKEY key)
{
LOG("Audio device property value changed.");
LOG("Audio device property value changed.\n");
return S_OK;
}
private:
@ -488,7 +484,7 @@ refill(cubeb_stream * stm, float * data, long frames_needed)
/* Go in draining mode if we got fewer frames than requested. */
if (out_frames < frames_needed) {
LOG("draining.");
LOG("draining.\n");
stm->draining = true;
}
@ -513,10 +509,14 @@ wasapi_stream_render_loop(LPVOID stream)
bool is_playing = true;
HANDLE wait_array[2] = {stm->shutdown_event, stm->refill_event};
HANDLE mmcss_handle = NULL;
HRESULT hr;
HRESULT hr = 0;
bool first = true;
DWORD mmcss_task_index = 0;
auto_com com;
if (!com.ok()) {
LOG("COM initialization failed on render_loop thread.\n");
return 0;
}
/* We could consider using "Pro Audio" here for WebAudio and
* maybe WebRTC. */
@ -524,7 +524,7 @@ wasapi_stream_render_loop(LPVOID stream)
stm->context->set_mm_thread_characteristics("Audio", &mmcss_task_index);
if (!mmcss_handle) {
/* This is not fatal, but we might glitch under heavy load. */
LOG("Unable to use mmcss to bump the render thread priority: %x", GetLastError());
LOG("Unable to use mmcss to bump the render thread priority: %x\n", GetLastError());
}
@ -549,7 +549,7 @@ wasapi_stream_render_loop(LPVOID stream)
hr = stm->client->GetCurrentPadding(&padding);
if (FAILED(hr)) {
LOG("Failed to get padding");
LOG("Failed to get padding\n");
is_playing = false;
continue;
}
@ -576,11 +576,11 @@ wasapi_stream_render_loop(LPVOID stream)
hr = stm->render_client->ReleaseBuffer(available, 0);
if (FAILED(hr)) {
LOG("failed to release buffer.");
LOG("failed to release buffer.\n");
is_playing = false;
}
} else {
LOG("failed to get buffer.");
LOG("failed to get buffer.\n");
is_playing = false;
}
}
@ -619,7 +619,7 @@ HRESULT register_notification_client(cubeb_stream * stm)
IID_PPV_ARGS(&stm->device_enumerator));
if (FAILED(hr)) {
LOG("Could not get device enumerator: %x", hr);
LOG("Could not get device enumerator: %x\n", hr);
return hr;
}
@ -628,7 +628,7 @@ HRESULT register_notification_client(cubeb_stream * stm)
hr = stm->device_enumerator->RegisterEndpointNotificationCallback(stm->notification_client);
if (FAILED(hr)) {
LOG("Could not register endpoint notification callback: %x", hr);
LOG("Could not register endpoint notification callback: %x\n", hr);
return hr;
}
@ -657,9 +657,8 @@ HRESULT get_default_endpoint(IMMDevice ** device)
HRESULT hr = CoCreateInstance(__uuidof(MMDeviceEnumerator),
NULL, CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&enumerator));
if (FAILED(hr)) {
LOG("Could not get device enumerator.");
LOG("Could not get device enumerator.\n");
return hr;
}
/* eMultimedia is okay for now ("Music, movies, narration, [...]").
@ -668,7 +667,7 @@ HRESULT get_default_endpoint(IMMDevice ** device)
* and eCommunication ("Voice communication"). */
hr = enumerator->GetDefaultAudioEndpoint(eRender, eMultimedia, device);
if (FAILED(hr)) {
LOG("Could not get default audio endpoint. %d", __LINE__);
LOG("Could not get default audio endpoint. %d\n", __LINE__);
SafeRelease(enumerator);
return hr;
}
@ -684,6 +683,9 @@ int wasapi_init(cubeb ** context, char const * context_name)
{
HRESULT hr;
auto_com com;
if (!com.ok()) {
return CUBEB_ERROR;
}
/* We don't use the device yet, but need to make sure we can initialize one
so that this backend is not incorrectly enabled on platforms that don't
@ -691,7 +693,7 @@ int wasapi_init(cubeb ** context, char const * context_name)
IMMDevice * device;
hr = get_default_endpoint(&device);
if (FAILED(hr)) {
LOG("Could not get device.");
LOG("Could not get device.\n");
return CUBEB_ERROR;
}
SafeRelease(device);
@ -710,13 +712,13 @@ int wasapi_init(cubeb ** context, char const * context_name)
(revert_mm_thread_characteristics_function) GetProcAddress(
ctx->mmcss_module, "AvRevertMmThreadCharacteristics");
if (!(ctx->set_mm_thread_characteristics && ctx->revert_mm_thread_characteristics)) {
LOG("Could not load AvSetMmThreadCharacteristics or AvRevertMmThreadCharacteristics: %x", GetLastError());
LOG("Could not load AvSetMmThreadCharacteristics or AvRevertMmThreadCharacteristics: %x\n", GetLastError());
FreeLibrary(ctx->mmcss_module);
}
} else {
// This is not a fatal error, but we might end up glitching when
// the system is under high load.
LOG("Could not load Avrt.dll");
LOG("Could not load Avrt.dll\n");
ctx->set_mm_thread_characteristics = &set_mm_thread_characteristics_noop;
ctx->revert_mm_thread_characteristics = &revert_mm_thread_characteristics_noop;
}
@ -749,6 +751,9 @@ wasapi_get_max_channel_count(cubeb * ctx, uint32_t * max_channels)
IAudioClient * client;
WAVEFORMATEX * mix_format;
auto_com com;
if (!com.ok()) {
return CUBEB_ERROR;
}
assert(ctx && max_channels);
@ -787,11 +792,14 @@ wasapi_get_min_latency(cubeb * ctx, cubeb_stream_params params, uint32_t * laten
IAudioClient * client;
REFERENCE_TIME default_period;
auto_com com;
if (!com.ok()) {
return CUBEB_ERROR;
}
IMMDevice * device;
hr = get_default_endpoint(&device);
if (FAILED(hr)) {
LOG("Could not get default endpoint:%x.", hr)
LOG("Could not get default endpoint:%x.\n", hr);
return CUBEB_ERROR;
}
@ -800,7 +808,7 @@ wasapi_get_min_latency(cubeb * ctx, cubeb_stream_params params, uint32_t * laten
NULL, (void **)&client);
SafeRelease(device);
if (FAILED(hr)) {
LOG("Could not activate device for latency: %x.", hr)
LOG("Could not activate device for latency: %x.\n", hr);
return CUBEB_ERROR;
}
@ -808,11 +816,11 @@ wasapi_get_min_latency(cubeb * ctx, cubeb_stream_params params, uint32_t * laten
hr = client->GetDevicePeriod(&default_period, NULL);
if (FAILED(hr)) {
SafeRelease(client);
LOG("Could not get device period: %x.", hr)
LOG("Could not get device period: %x.\n", hr);
return CUBEB_ERROR;
}
LOG("default device period: %ld", default_period)
LOG("default device period: %ld\n", default_period);
/* According to the docs, the best latency we can achieve is by synchronizing
* the stream and the engine.
@ -831,6 +839,9 @@ wasapi_get_preferred_sample_rate(cubeb * ctx, uint32_t * rate)
IAudioClient * client;
WAVEFORMATEX * mix_format;
auto_com com;
if (!com.ok()) {
return CUBEB_ERROR;
}
IMMDevice * device;
hr = get_default_endpoint(&device);
@ -915,7 +926,7 @@ handle_channel_layout(cubeb_stream * stm, WAVEFORMATEX ** mix_format, const cub
if (hr == S_FALSE) {
/* Not supported, but WASAPI gives us a suggestion. Use it, and handle the
* eventual upmix/downmix ourselves */
LOG("Using WASAPI suggested format: channels: %d", closest->nChannels);
LOG("Using WASAPI suggested format: channels: %d\n", closest->nChannels);
WAVEFORMATEXTENSIBLE * closest_pcm = reinterpret_cast<WAVEFORMATEXTENSIBLE *>(closest);
assert(closest_pcm->SubFormat == format_pcm->SubFormat);
CoTaskMemFree(*mix_format);
@ -926,7 +937,7 @@ handle_channel_layout(cubeb_stream * stm, WAVEFORMATEX ** mix_format, const cub
* of the code figure out the right conversion path. */
**mix_format = hw_mixformat;
} else if (hr == S_OK) {
LOG("Requested format accepted by WASAPI.");
LOG("Requested format accepted by WASAPI.\n");
}
}
@ -936,15 +947,20 @@ int setup_wasapi_stream(cubeb_stream * stm)
IMMDevice * device;
WAVEFORMATEX * mix_format;
#ifdef DEBUG
stm->stream_reset_lock->assert_current_thread_owns();
#endif
auto_com com;
if (!com.ok()) {
return CUBEB_ERROR;
}
assert(!stm->client && "WASAPI stream already setup, close it first.");
hr = get_default_endpoint(&device);
if (FAILED(hr)) {
LOG("Could not get default endpoint, error: %x", hr);
LOG("Could not get default endpoint, error: %x\n", hr);
auto_unlock unlock(stm->stream_reset_lock);
wasapi_stream_destroy(stm);
return CUBEB_ERROR;
@ -953,11 +969,11 @@ int setup_wasapi_stream(cubeb_stream * stm)
/* Get a client. We will get all other interfaces we need from
* this pointer. */
hr = device->Activate(__uuidof(IAudioClient),
CLSCTX_INPROC_SERVER,
NULL, (void **)&stm->client);
CLSCTX_INPROC_SERVER,
NULL, (void **)&stm->client);
SafeRelease(device);
if (FAILED(hr)) {
LOG("Could not activate the device to get an audio client: error: %x", hr);
LOG("Could not activate the device to get an audio client: error: %x\n", hr);
auto_unlock unlock(stm->stream_reset_lock);
wasapi_stream_destroy(stm);
return CUBEB_ERROR;
@ -967,7 +983,7 @@ int setup_wasapi_stream(cubeb_stream * stm)
* and the format the stream we want to play uses. */
hr = stm->client->GetMixFormat(&mix_format);
if (FAILED(hr)) {
LOG("Could not fetch current mix format from the audio client: error: %x", hr);
LOG("Could not fetch current mix format from the audio client: error: %x\n", hr);
auto_unlock unlock(stm->stream_reset_lock);
wasapi_stream_destroy(stm);
return CUBEB_ERROR;
@ -982,17 +998,17 @@ int setup_wasapi_stream(cubeb_stream * stm)
stm->mix_params.channels = mix_format->nChannels;
hr = stm->client->Initialize(AUDCLNT_SHAREMODE_SHARED,
AUDCLNT_STREAMFLAGS_EVENTCALLBACK |
AUDCLNT_STREAMFLAGS_NOPERSIST,
ms_to_hns(stm->latency),
0,
mix_format,
NULL);
AUDCLNT_STREAMFLAGS_EVENTCALLBACK |
AUDCLNT_STREAMFLAGS_NOPERSIST,
ms_to_hns(stm->latency),
0,
mix_format,
NULL);
CoTaskMemFree(mix_format);
if (FAILED(hr)) {
LOG("Unable to initialize audio client: %x.", hr);
LOG("Unable to initialize audio client: %x.\n", hr);
auto_unlock unlock(stm->stream_reset_lock);
wasapi_stream_destroy(stm);
return CUBEB_ERROR;
@ -1000,37 +1016,37 @@ int setup_wasapi_stream(cubeb_stream * stm)
hr = stm->client->GetBufferSize(&stm->buffer_frame_count);
if (FAILED(hr)) {
LOG("Could not get the buffer size from the client %x.", hr);
LOG("Could not get the buffer size from the client %x.\n", hr);
auto_unlock unlock(stm->stream_reset_lock);
wasapi_stream_destroy(stm);
return CUBEB_ERROR;
}
if (should_upmix(stm) || should_downmix(stm)) {
stm->mix_buffer = (float *)malloc(frames_to_bytes_before_mix(stm, stm->buffer_frame_count));
stm->mix_buffer = (float *) malloc(frames_to_bytes_before_mix(stm, stm->buffer_frame_count));
}
hr = stm->client->SetEventHandle(stm->refill_event);
if (FAILED(hr)) {
LOG("Could set the event handle for the client %x.", hr);
LOG("Could set the event handle for the client %x.\n", hr);
auto_unlock unlock(stm->stream_reset_lock);
wasapi_stream_destroy(stm);
return CUBEB_ERROR;
}
hr = stm->client->GetService(__uuidof(IAudioRenderClient),
(void **)&stm->render_client);
(void **)&stm->render_client);
if (FAILED(hr)) {
LOG("Could not get the render client %x.", hr);
LOG("Could not get the render client %x.\n", hr);
auto_unlock unlock(stm->stream_reset_lock);
wasapi_stream_destroy(stm);
return CUBEB_ERROR;
}
hr = stm->client->GetService(__uuidof(IAudioStreamVolume),
(void **)&stm->audio_stream_volume);
(void **)&stm->audio_stream_volume);
if (FAILED(hr)) {
LOG("Could not get the IAudioStreamVolume %x.", hr);
LOG("Could not get the IAudioStreamVolume %x.\n", hr);
auto_unlock unlock(stm->stream_reset_lock);
wasapi_stream_destroy(stm);
return CUBEB_ERROR;
@ -1041,14 +1057,14 @@ int setup_wasapi_stream(cubeb_stream * stm)
* of channels of the stream, not the number of channels
* that WASAPI wants. */
stm->resampler = cubeb_resampler_create(stm, stm->stream_params,
stm->mix_params.rate,
stm->data_callback,
stm->buffer_frame_count,
stm->user_ptr,
CUBEB_RESAMPLER_QUALITY_DESKTOP);
stm->mix_params.rate,
stm->data_callback,
stm->buffer_frame_count,
stm->user_ptr,
CUBEB_RESAMPLER_QUALITY_DESKTOP);
if (!stm->resampler) {
LOG("Could not get a resampler\n");
auto_unlock unlock(stm->stream_reset_lock);
LOG("Could not get a resampler");
wasapi_stream_destroy(stm);
return CUBEB_ERROR;
}
@ -1065,6 +1081,9 @@ wasapi_stream_init(cubeb * context, cubeb_stream ** stream,
HRESULT hr;
int rv;
auto_com com;
if (!com.ok()) {
return CUBEB_ERROR;
}
assert(context && stream);
@ -1082,12 +1101,12 @@ wasapi_stream_init(cubeb * context, cubeb_stream ** stream,
stm->clock = 0;
/* Null out WASAPI-specific state */
stm->resampler = nullptr;
stm->client = nullptr;
stm->render_client = nullptr;
stm->audio_stream_volume = nullptr;
stm->device_enumerator = nullptr;
stm->notification_client = nullptr;
stm->resampler = NULL;
stm->client = NULL;
stm->render_client = NULL;
stm->audio_stream_volume = NULL;
stm->device_enumerator = NULL;
stm->notification_client = NULL;
stm->stream_reset_lock = new owned_critical_section();
@ -1095,14 +1114,14 @@ wasapi_stream_init(cubeb * context, cubeb_stream ** stream,
stm->refill_event = CreateEvent(NULL, 0, 0, NULL);
if (!stm->shutdown_event) {
LOG("Can't create the shutdown event, error: %x.", GetLastError());
LOG("Can't create the shutdown event, error: %x\n", GetLastError());
wasapi_stream_destroy(stm);
return CUBEB_ERROR;
}
if (!stm->refill_event) {
SafeRelease(stm->shutdown_event);
LOG("Can't create the refill event, error: %x.", GetLastError());
LOG("Can't create the refill event, error: %x\n", GetLastError());
wasapi_stream_destroy(stm);
return CUBEB_ERROR;
}
@ -1122,7 +1141,7 @@ wasapi_stream_init(cubeb * context, cubeb_stream ** stream,
if (FAILED(hr)) {
/* this is not fatal, we can still play audio, but we won't be able
* to keep using the default audio endpoint if it changes. */
LOG("failed to register notification client, %x", hr);
LOG("failed to register notification client, %x\n", hr);
}
*stream = stm;
@ -1134,21 +1153,23 @@ void close_wasapi_stream(cubeb_stream * stm)
{
assert(stm);
#ifdef DEBUG
stm->stream_reset_lock->assert_current_thread_owns();
#endif
SafeRelease(stm->client);
stm->client = nullptr;
stm->client = NULL;
SafeRelease(stm->render_client);
stm->client = nullptr;
stm->render_client = NULL;
if (stm->resampler) {
cubeb_resampler_destroy(stm->resampler);
stm->resampler = nullptr;
stm->resampler = NULL;
}
free(stm->mix_buffer);
stm->mix_buffer = nullptr;
stm->mix_buffer = NULL;
}
void wasapi_stream_destroy(cubeb_stream * stm)
@ -1158,8 +1179,14 @@ void wasapi_stream_destroy(cubeb_stream * stm)
unregister_notification_client(stm);
if (stm->thread) {
SetEvent(stm->shutdown_event);
WaitForSingleObject(stm->thread, INFINITE);
BOOL ok = SetEvent(stm->shutdown_event);
if (!ok) {
LOG("Destroy SetEvent failed: %d\n", GetLastError());
}
DWORD r = WaitForSingleObject(stm->thread, INFINITE);
if (r == WAIT_FAILED) {
LOG("Destroy WaitForSingleObject on thread failed: %d\n", GetLastError());
}
CloseHandle(stm->thread);
stm->thread = 0;
}
@ -1179,27 +1206,25 @@ void wasapi_stream_destroy(cubeb_stream * stm)
int wasapi_stream_start(cubeb_stream * stm)
{
HRESULT hr;
auto_lock lock(stm->stream_reset_lock);
assert(stm);
assert(stm && !stm->thread);
stm->thread = (HANDLE) _beginthreadex(NULL, 256 * 1024, wasapi_stream_render_loop, stm, STACK_SIZE_PARAM_IS_A_RESERVATION, NULL);
if (stm->thread == NULL) {
LOG("could not create WASAPI render thread.");
LOG("could not create WASAPI render thread.\n");
return CUBEB_ERROR;
}
hr = stm->client->Start();
HRESULT hr = stm->client->Start();
if (FAILED(hr)) {
LOG("could not start the stream.");
LOG("could not start the stream.\n");
return CUBEB_ERROR;
} else {
stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_STARTED);
}
stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_STARTED);
return CUBEB_OK;
return FAILED(hr) ? CUBEB_ERROR : CUBEB_OK;
}
int wasapi_stream_stop(cubeb_stream * stm)
@ -1208,23 +1233,31 @@ int wasapi_stream_stop(cubeb_stream * stm)
auto_lock lock(stm->stream_reset_lock);
SetEvent(stm->shutdown_event);
BOOL ok = SetEvent(stm->shutdown_event);
if (!ok) {
LOG("Stop SetEvent failed: %d\n", GetLastError());
}
HRESULT hr = stm->client->Stop();
if (FAILED(hr)) {
LOG("could not stop AudioClient");
LOG("could not stop AudioClient\n");
}
if (stm->thread) {
auto_unlock lock(stm->stream_reset_lock);
WaitForSingleObject(stm->thread, INFINITE);
DWORD r = WaitForSingleObject(stm->thread, INFINITE);
if (r == WAIT_FAILED) {
LOG("Stop WaitForSingleObject on thread failed: %d\n", GetLastError());
}
CloseHandle(stm->thread);
stm->thread = NULL;
}
stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_STOPPED);
if (SUCCEEDED(hr)) {
stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_STOPPED);
}
return CUBEB_OK;
return FAILED(hr) ? CUBEB_ERROR : CUBEB_OK;
}
int wasapi_stream_get_position(cubeb_stream * stm, uint64_t * position)
@ -1267,7 +1300,7 @@ int wasapi_stream_set_volume(cubeb_stream * stm, float volume)
hr = stm->audio_stream_volume->GetChannelCount(&channels);
if (hr != S_OK) {
LOG("could not get the channel count: %x", hr);
LOG("could not get the channel count: %x\n", hr);
return CUBEB_ERROR;
}
@ -1279,7 +1312,7 @@ int wasapi_stream_set_volume(cubeb_stream * stm, float volume)
hr = stm->audio_stream_volume->SetAllVolumes(channels, volumes);
if (hr != S_OK) {
LOG("coult not set the channels volume: %x", hr);
LOG("could not set the channels volume: %x\n", hr);
return CUBEB_ERROR;
}
return CUBEB_OK;
@ -1303,6 +1336,5 @@ cubeb_ops const wasapi_ops = {
/*.stream_get_current_device =*/ NULL,
/*.stream_device_destroy =*/ NULL,
/*.stream_register_device_changed_callback =*/ NULL
};
};
} // namespace anonymous

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

@ -654,6 +654,10 @@ winmm_stream_get_latency(cubeb_stream * stm, uint32_t * latency)
written = stm->written;
LeaveCriticalSection(&stm->lock);
if (r != MMSYSERR_NOERROR || time.wType != TIME_SAMPLES) {
return CUBEB_ERROR;
}
*latency = written - time.u.sample;
return CUBEB_OK;