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

#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;
}