You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
71 lines
3.6 KiB
71 lines
3.6 KiB
#include "audio_diagnostics.h" |
|
#ifdef __linux__ |
|
#include <dlfcn.h> |
|
static void audio_diag_pulse_init(void* device); |
|
#define MA_DIAGNOSTIC_EVENT(device, kind, stage, value, detail) audio_diag_event(device, kind, stage, value, detail) |
|
#define MA_DIAGNOSTIC_LOG(log, level, message) audio_diag_log(log, level, message) |
|
#define MA_DIAGNOSTIC_DEVICE_INIT(device) audio_diag_pulse_init(device) |
|
#endif |
|
#define MINIAUDIO_IMPLEMENTATION |
|
#include "../../../lib/miniaudio.h" |
|
|
|
#ifdef __linux__ |
|
#ifdef MA_SUPPORT_PULSEAUDIO |
|
static void audio_diag_pulse_underflow(ma_pa_stream* stream, void* userdata) { |
|
(void)stream; |
|
audio_diag_event(userdata, AUDIO_DIAG_BACKEND_UNDERRUN, AUDIO_DIAG_WRITE, 1, 0); |
|
} |
|
static void audio_diag_pulse_overflow(ma_pa_stream* stream, void* userdata) { |
|
(void)stream; |
|
audio_diag_event(userdata, AUDIO_DIAG_BACKEND_OVERFLOW, AUDIO_DIAG_WRITE, 1, 0); |
|
} |
|
static void audio_diag_pulse_started(ma_pa_stream* stream, void* userdata) { |
|
(void)stream; |
|
audio_diag_event(userdata, AUDIO_DIAG_BACKEND_STARTED, AUDIO_DIAG_WRITE, 1, 0); |
|
} |
|
#endif |
|
|
|
/* Только init-поток: backend-callbacks остаются короткими наблюдателями. */ |
|
static void audio_diag_pulse_init(void* device) { |
|
#ifdef MA_SUPPORT_PULSEAUDIO |
|
ma_device* dev = (ma_device*)device; |
|
ma_pa_stream_set_suspended_callback_proc underflow, overflow, started; |
|
if (dev->pContext->backend != ma_backend_pulseaudio || !dev->pulse.pStreamPlayback) return; |
|
#ifndef MA_NO_RUNTIME_LINKING |
|
underflow = (ma_pa_stream_set_suspended_callback_proc)dlsym(dev->pContext->pulse.pulseSO, "pa_stream_set_underflow_callback"); |
|
overflow = (ma_pa_stream_set_suspended_callback_proc)dlsym(dev->pContext->pulse.pulseSO, "pa_stream_set_overflow_callback"); |
|
started = (ma_pa_stream_set_suspended_callback_proc)dlsym(dev->pContext->pulse.pulseSO, "pa_stream_set_started_callback"); |
|
#else |
|
underflow = pa_stream_set_underflow_callback; |
|
overflow = pa_stream_set_overflow_callback; |
|
started = pa_stream_set_started_callback; |
|
#endif |
|
if (!underflow || !overflow || !started) { |
|
audio_diag_log(ma_device_get_log(dev), MA_LOG_LEVEL_WARNING, "PulseAudio xrun/started callbacks unavailable"); |
|
return; |
|
} |
|
underflow((ma_pa_stream*)dev->pulse.pStreamPlayback, audio_diag_pulse_underflow, dev); |
|
overflow((ma_pa_stream*)dev->pulse.pStreamPlayback, audio_diag_pulse_overflow, dev); |
|
started((ma_pa_stream*)dev->pulse.pStreamPlayback, audio_diag_pulse_started, dev); |
|
audio_diag_log(ma_device_get_log(dev), MA_LOG_LEVEL_INFO, "PulseAudio xrun/started observers registered"); |
|
#else |
|
(void)device; |
|
#endif |
|
} |
|
#endif |
|
|
|
/* Вызывается только владельцем общего контекста (GUI), вне device callbacks. */ |
|
int audio_context_failed(ma_context* context) { |
|
#ifdef MA_SUPPORT_PULSEAUDIO |
|
if (context && context->backend == ma_backend_pulseaudio) { |
|
int result = ((ma_pa_mainloop_iterate_proc)context->pulse.pa_mainloop_iterate)((ma_pa_mainloop*)context->pulse.pMainLoop, 0, NULL); |
|
ma_pa_context_state_t state = ((ma_pa_context_get_state_proc)context->pulse.pa_context_get_state)((ma_pa_context*)context->pulse.pPulseContext); |
|
if (result < 0 || state == MA_PA_CONTEXT_FAILED || state == MA_PA_CONTEXT_TERMINATED) { |
|
ma_log_postf(ma_context_get_log(context), MA_LOG_LEVEL_ERROR, "[PulseAudio] Shared context failed iterate=%d state=%d errno=%d.\n", |
|
result, state, ((ma_pa_context_errno_proc)context->pulse.pa_context_errno)((ma_pa_context*)context->pulse.pPulseContext)); |
|
return 1; |
|
} |
|
} |
|
#endif |
|
return 0; |
|
}
|
|
|