mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-22 00:06:59 +02:00
Setup callbacks for the PulseAudio backend.
This commit is contained in:
@@ -11391,202 +11391,6 @@ done:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
mal_result mal_context_init__pulse(mal_context* pContext)
|
|
||||||
{
|
|
||||||
mal_assert(pContext != NULL);
|
|
||||||
|
|
||||||
#ifndef MAL_NO_RUNTIME_LINKING
|
|
||||||
// libpulse.so
|
|
||||||
const char* libpulseNames[] = {
|
|
||||||
"libpulse.so",
|
|
||||||
"libpulse.so.0"
|
|
||||||
};
|
|
||||||
|
|
||||||
for (size_t i = 0; i < mal_countof(libpulseNames); ++i) {
|
|
||||||
pContext->pulse.pulseSO = mal_dlopen(libpulseNames[i]);
|
|
||||||
if (pContext->pulse.pulseSO != NULL) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pContext->pulse.pulseSO == NULL) {
|
|
||||||
return MAL_NO_BACKEND;
|
|
||||||
}
|
|
||||||
|
|
||||||
pContext->pulse.pa_mainloop_new = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_mainloop_new");
|
|
||||||
pContext->pulse.pa_mainloop_free = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_mainloop_free");
|
|
||||||
pContext->pulse.pa_mainloop_get_api = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_mainloop_get_api");
|
|
||||||
pContext->pulse.pa_mainloop_iterate = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_mainloop_iterate");
|
|
||||||
pContext->pulse.pa_mainloop_wakeup = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_mainloop_wakeup");
|
|
||||||
pContext->pulse.pa_context_new = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_context_new");
|
|
||||||
pContext->pulse.pa_context_unref = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_context_unref");
|
|
||||||
pContext->pulse.pa_context_connect = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_context_connect");
|
|
||||||
pContext->pulse.pa_context_disconnect = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_context_disconnect");
|
|
||||||
pContext->pulse.pa_context_set_state_callback = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_context_set_state_callback");
|
|
||||||
pContext->pulse.pa_context_get_state = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_context_get_state");
|
|
||||||
pContext->pulse.pa_context_get_sink_info_list = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_context_get_sink_info_list");
|
|
||||||
pContext->pulse.pa_context_get_source_info_list = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_context_get_source_info_list");
|
|
||||||
pContext->pulse.pa_context_get_sink_info_by_name = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_context_get_sink_info_by_name");
|
|
||||||
pContext->pulse.pa_context_get_source_info_by_name = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_context_get_source_info_by_name");
|
|
||||||
pContext->pulse.pa_operation_unref = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_operation_unref");
|
|
||||||
pContext->pulse.pa_operation_get_state = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_operation_get_state");
|
|
||||||
pContext->pulse.pa_channel_map_init_extend = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_channel_map_init_extend");
|
|
||||||
pContext->pulse.pa_channel_map_valid = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_channel_map_valid");
|
|
||||||
pContext->pulse.pa_channel_map_compatible = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_channel_map_compatible");
|
|
||||||
pContext->pulse.pa_stream_new = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_stream_new");
|
|
||||||
pContext->pulse.pa_stream_unref = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_stream_unref");
|
|
||||||
pContext->pulse.pa_stream_connect_playback = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_stream_connect_playback");
|
|
||||||
pContext->pulse.pa_stream_connect_record = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_stream_connect_record");
|
|
||||||
pContext->pulse.pa_stream_disconnect = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_stream_disconnect");
|
|
||||||
pContext->pulse.pa_stream_get_state = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_stream_get_state");
|
|
||||||
pContext->pulse.pa_stream_get_sample_spec = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_stream_get_sample_spec");
|
|
||||||
pContext->pulse.pa_stream_get_channel_map = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_stream_get_channel_map");
|
|
||||||
pContext->pulse.pa_stream_get_buffer_attr = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_stream_get_buffer_attr");
|
|
||||||
pContext->pulse.pa_stream_get_device_name = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_stream_get_device_name");
|
|
||||||
pContext->pulse.pa_stream_set_write_callback = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_stream_set_write_callback");
|
|
||||||
pContext->pulse.pa_stream_set_read_callback = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_stream_set_read_callback");
|
|
||||||
pContext->pulse.pa_stream_flush = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_stream_flush");
|
|
||||||
pContext->pulse.pa_stream_drain = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_stream_drain");
|
|
||||||
pContext->pulse.pa_stream_cork = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_stream_cork");
|
|
||||||
pContext->pulse.pa_stream_trigger = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_stream_trigger");
|
|
||||||
pContext->pulse.pa_stream_begin_write = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_stream_begin_write");
|
|
||||||
pContext->pulse.pa_stream_write = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_stream_write");
|
|
||||||
pContext->pulse.pa_stream_peek = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_stream_peek");
|
|
||||||
pContext->pulse.pa_stream_drop = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_stream_drop");
|
|
||||||
#else
|
|
||||||
// This strange assignment system is just for type safety.
|
|
||||||
mal_pa_mainloop_new_proc _pa_mainloop_new = pa_mainloop_new;
|
|
||||||
mal_pa_mainloop_free_proc _pa_mainloop_free = pa_mainloop_free;
|
|
||||||
mal_pa_mainloop_get_api_proc _pa_mainloop_get_api = pa_mainloop_get_api;
|
|
||||||
mal_pa_mainloop_iterate_proc _pa_mainloop_iterate = pa_mainloop_iterate;
|
|
||||||
mal_pa_mainloop_wakeup_proc _pa_mainloop_wakeup = pa_mainloop_wakeup;
|
|
||||||
mal_pa_context_new_proc _pa_context_new = pa_context_new;
|
|
||||||
mal_pa_context_unref_proc _pa_context_unref = pa_context_unref;
|
|
||||||
mal_pa_context_connect_proc _pa_context_connect = pa_context_connect;
|
|
||||||
mal_pa_context_disconnect_proc _pa_context_disconnect = pa_context_disconnect;
|
|
||||||
mal_pa_context_set_state_callback_proc _pa_context_set_state_callback = pa_context_set_state_callback;
|
|
||||||
mal_pa_context_get_state_proc _pa_context_get_state = pa_context_get_state;
|
|
||||||
mal_pa_context_get_sink_info_list_proc _pa_context_get_sink_info_list = pa_context_get_sink_info_list;
|
|
||||||
mal_pa_context_get_source_info_list_proc _pa_context_get_source_info_list = pa_context_get_source_info_list;
|
|
||||||
mal_pa_context_get_sink_info_by_name_proc _pa_context_get_sink_info_by_name = pa_context_get_sink_info_by_name;
|
|
||||||
mal_pa_context_get_source_info_by_name_proc _pa_context_get_source_info_by_name= pa_context_get_source_info_by_name;
|
|
||||||
mal_pa_operation_unref_proc _pa_operation_unref = pa_operation_unref;
|
|
||||||
mal_pa_operation_get_state_proc _pa_operation_get_state = pa_operation_get_state;
|
|
||||||
mal_pa_channel_map_init_extend_proc _pa_channel_map_init_extend = pa_channel_map_init_extend;
|
|
||||||
mal_pa_channel_map_valid_proc _pa_channel_map_valid = pa_channel_map_valid;
|
|
||||||
mal_pa_channel_map_compatible_proc _pa_channel_map_compatible = pa_channel_map_compatible;
|
|
||||||
mal_pa_stream_new_proc _pa_stream_new = pa_stream_new;
|
|
||||||
mal_pa_stream_unref_proc _pa_stream_unref = pa_stream_unref;
|
|
||||||
mal_pa_stream_connect_playback_proc _pa_stream_connect_playback = pa_stream_connect_playback;
|
|
||||||
mal_pa_stream_connect_record_proc _pa_stream_connect_record = pa_stream_connect_record;
|
|
||||||
mal_pa_stream_disconnect_proc _pa_stream_disconnect = pa_stream_disconnect;
|
|
||||||
mal_pa_stream_get_state_proc _pa_stream_get_state = pa_stream_get_state;
|
|
||||||
mal_pa_stream_get_sample_spec_proc _pa_stream_get_sample_spec = pa_stream_get_sample_spec;
|
|
||||||
mal_pa_stream_get_channel_map_proc _pa_stream_get_channel_map = pa_stream_get_channel_map;
|
|
||||||
mal_pa_stream_get_buffer_attr_proc _pa_stream_get_buffer_attr = pa_stream_get_buffer_attr;
|
|
||||||
mal_pa_stream_get_device_name_proc _pa_stream_get_device_name = pa_stream_get_device_name;
|
|
||||||
mal_pa_stream_set_write_callback_proc _pa_stream_set_write_callback = pa_stream_set_write_callback;
|
|
||||||
mal_pa_stream_set_read_callback_proc _pa_stream_set_read_callback = pa_stream_set_read_callback;
|
|
||||||
mal_pa_stream_flush_proc _pa_stream_flush = pa_stream_flush;
|
|
||||||
mal_pa_stream_drain_proc _pa_stream_drain = pa_stream_drain;
|
|
||||||
mal_pa_stream_cork_proc _pa_stream_cork = pa_stream_cork;
|
|
||||||
mal_pa_stream_trigger_proc _pa_stream_trigger = pa_stream_trigger;
|
|
||||||
mal_pa_stream_begin_write_proc _pa_stream_begin_write = pa_stream_begin_write;
|
|
||||||
mal_pa_stream_write_proc _pa_stream_write = pa_stream_write;
|
|
||||||
mal_pa_stream_peek_proc _pa_stream_peek = pa_stream_peek;
|
|
||||||
mal_pa_stream_drop_proc _pa_stream_drop = pa_stream_drop;
|
|
||||||
|
|
||||||
pContext->pulse.pa_mainloop_new = (mal_proc)_pa_mainloop_new;
|
|
||||||
pContext->pulse.pa_mainloop_free = (mal_proc)_pa_mainloop_free;
|
|
||||||
pContext->pulse.pa_mainloop_get_api = (mal_proc)_pa_mainloop_get_api;
|
|
||||||
pContext->pulse.pa_mainloop_iterate = (mal_proc)_pa_mainloop_iterate;
|
|
||||||
pContext->pulse.pa_mainloop_wakeup = (mal_proc)_pa_mainloop_wakeup;
|
|
||||||
pContext->pulse.pa_context_new = (mal_proc)_pa_context_new;
|
|
||||||
pContext->pulse.pa_context_unref = (mal_proc)_pa_context_unref;
|
|
||||||
pContext->pulse.pa_context_connect = (mal_proc)_pa_context_connect;
|
|
||||||
pContext->pulse.pa_context_disconnect = (mal_proc)_pa_context_disconnect;
|
|
||||||
pContext->pulse.pa_context_set_state_callback = (mal_proc)_pa_context_set_state_callback;
|
|
||||||
pContext->pulse.pa_context_get_state = (mal_proc)_pa_context_get_state;
|
|
||||||
pContext->pulse.pa_context_get_sink_info_list = (mal_proc)_pa_context_get_sink_info_list;
|
|
||||||
pContext->pulse.pa_context_get_source_info_list = (mal_proc)_pa_context_get_source_info_list;
|
|
||||||
pContext->pulse.pa_context_get_sink_info_by_name = (mal_proc)_pa_context_get_sink_info_by_name;
|
|
||||||
pContext->pulse.pa_context_get_source_info_by_name = (mal_proc)_pa_context_get_source_info_by_name;
|
|
||||||
pContext->pulse.pa_operation_unref = (mal_proc)_pa_operation_unref;
|
|
||||||
pContext->pulse.pa_operation_get_state = (mal_proc)_pa_operation_get_state;
|
|
||||||
pContext->pulse.pa_channel_map_init_extend = (mal_proc)_pa_channel_map_init_extend;
|
|
||||||
pContext->pulse.pa_channel_map_valid = (mal_proc)_pa_channel_map_valid;
|
|
||||||
pContext->pulse.pa_channel_map_compatible = (mal_proc)_pa_channel_map_compatible;
|
|
||||||
pContext->pulse.pa_stream_new = (mal_proc)_pa_stream_new;
|
|
||||||
pContext->pulse.pa_stream_unref = (mal_proc)_pa_stream_unref;
|
|
||||||
pContext->pulse.pa_stream_connect_playback = (mal_proc)_pa_stream_connect_playback;
|
|
||||||
pContext->pulse.pa_stream_connect_record = (mal_proc)_pa_stream_connect_record;
|
|
||||||
pContext->pulse.pa_stream_disconnect = (mal_proc)_pa_stream_disconnect;
|
|
||||||
pContext->pulse.pa_stream_get_state = (mal_proc)_pa_stream_get_state;
|
|
||||||
pContext->pulse.pa_stream_get_sample_spec = (mal_proc)_pa_stream_get_sample_spec;
|
|
||||||
pContext->pulse.pa_stream_get_channel_map = (mal_proc)_pa_stream_get_channel_map;
|
|
||||||
pContext->pulse.pa_stream_get_buffer_attr = (mal_proc)_pa_stream_get_buffer_attr;
|
|
||||||
pContext->pulse.pa_stream_get_device_name = (mal_proc)_pa_stream_get_device_name;
|
|
||||||
pContext->pulse.pa_stream_set_write_callback = (mal_proc)_pa_stream_set_write_callback;
|
|
||||||
pContext->pulse.pa_stream_set_read_callback = (mal_proc)_pa_stream_set_read_callback;
|
|
||||||
pContext->pulse.pa_stream_flush = (mal_proc)_pa_stream_flush;
|
|
||||||
pContext->pulse.pa_stream_drain = (mal_proc)_pa_stream_drain;
|
|
||||||
pContext->pulse.pa_stream_cork = (mal_proc)_pa_stream_cork;
|
|
||||||
pContext->pulse.pa_stream_trigger = (mal_proc)_pa_stream_trigger;
|
|
||||||
pContext->pulse.pa_stream_begin_write = (mal_proc)_pa_stream_begin_write;
|
|
||||||
pContext->pulse.pa_stream_write = (mal_proc)_pa_stream_write;
|
|
||||||
pContext->pulse.pa_stream_peek = (mal_proc)_pa_stream_peek;
|
|
||||||
pContext->pulse.pa_stream_drop = (mal_proc)_pa_stream_drop;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
pContext->onDeviceIDEqual = mal_context_is_device_id_equal__pulse;
|
|
||||||
pContext->onEnumDevices = mal_context_enumerate_devices__pulse;
|
|
||||||
pContext->onGetDeviceInfo = mal_context_get_device_info__pulse;
|
|
||||||
|
|
||||||
|
|
||||||
// Although we have found the libpulse library, it doesn't necessarily mean PulseAudio is useable. We need to initialize
|
|
||||||
// and connect a dummy PulseAudio context to test PulseAudio's usability.
|
|
||||||
mal_pa_mainloop* pMainLoop = ((mal_pa_mainloop_new_proc)pContext->pulse.pa_mainloop_new)();
|
|
||||||
if (pMainLoop == NULL) {
|
|
||||||
return MAL_NO_BACKEND;
|
|
||||||
}
|
|
||||||
|
|
||||||
mal_pa_mainloop_api* pAPI = ((mal_pa_mainloop_get_api_proc)pContext->pulse.pa_mainloop_get_api)(pMainLoop);
|
|
||||||
if (pAPI == NULL) {
|
|
||||||
((mal_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)(pMainLoop);
|
|
||||||
return MAL_NO_BACKEND;
|
|
||||||
}
|
|
||||||
|
|
||||||
mal_pa_context* pPulseContext = ((mal_pa_context_new_proc)pContext->pulse.pa_context_new)(pAPI, pContext->config.pulse.pApplicationName);
|
|
||||||
if (pPulseContext == NULL) {
|
|
||||||
((mal_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)(pMainLoop);
|
|
||||||
return MAL_NO_BACKEND;
|
|
||||||
}
|
|
||||||
|
|
||||||
int error = ((mal_pa_context_connect_proc)pContext->pulse.pa_context_connect)(pPulseContext, pContext->config.pulse.pServerName, 0, NULL);
|
|
||||||
if (error != MAL_PA_OK) {
|
|
||||||
((mal_pa_context_unref_proc)pContext->pulse.pa_context_unref)(pPulseContext);
|
|
||||||
((mal_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)(pMainLoop);
|
|
||||||
return MAL_NO_BACKEND;
|
|
||||||
}
|
|
||||||
|
|
||||||
((mal_pa_context_disconnect_proc)pContext->pulse.pa_context_disconnect)(pPulseContext);
|
|
||||||
((mal_pa_context_unref_proc)pContext->pulse.pa_context_unref)(pPulseContext);
|
|
||||||
((mal_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)(pMainLoop);
|
|
||||||
return MAL_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
mal_result mal_context_uninit__pulse(mal_context* pContext)
|
|
||||||
{
|
|
||||||
mal_assert(pContext != NULL);
|
|
||||||
mal_assert(pContext->backend == mal_backend_pulseaudio);
|
|
||||||
|
|
||||||
#ifndef MAL_NO_RUNTIME_LINKING
|
|
||||||
mal_dlclose(pContext->pulse.pulseSO);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return MAL_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void mal_pulse_device_state_callback(mal_pa_context* pPulseContext, void* pUserData)
|
void mal_pulse_device_state_callback(mal_pa_context* pPulseContext, void* pUserData)
|
||||||
{
|
{
|
||||||
@@ -12170,6 +11974,210 @@ mal_result mal_device__main_loop__pulse(mal_device* pDevice)
|
|||||||
|
|
||||||
return MAL_SUCCESS;
|
return MAL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
mal_result mal_context_uninit__pulse(mal_context* pContext)
|
||||||
|
{
|
||||||
|
mal_assert(pContext != NULL);
|
||||||
|
mal_assert(pContext->backend == mal_backend_pulseaudio);
|
||||||
|
|
||||||
|
#ifndef MAL_NO_RUNTIME_LINKING
|
||||||
|
mal_dlclose(pContext->pulse.pulseSO);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return MAL_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
mal_result mal_context_init__pulse(mal_context* pContext)
|
||||||
|
{
|
||||||
|
mal_assert(pContext != NULL);
|
||||||
|
|
||||||
|
#ifndef MAL_NO_RUNTIME_LINKING
|
||||||
|
// libpulse.so
|
||||||
|
const char* libpulseNames[] = {
|
||||||
|
"libpulse.so",
|
||||||
|
"libpulse.so.0"
|
||||||
|
};
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mal_countof(libpulseNames); ++i) {
|
||||||
|
pContext->pulse.pulseSO = mal_dlopen(libpulseNames[i]);
|
||||||
|
if (pContext->pulse.pulseSO != NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pContext->pulse.pulseSO == NULL) {
|
||||||
|
return MAL_NO_BACKEND;
|
||||||
|
}
|
||||||
|
|
||||||
|
pContext->pulse.pa_mainloop_new = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_mainloop_new");
|
||||||
|
pContext->pulse.pa_mainloop_free = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_mainloop_free");
|
||||||
|
pContext->pulse.pa_mainloop_get_api = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_mainloop_get_api");
|
||||||
|
pContext->pulse.pa_mainloop_iterate = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_mainloop_iterate");
|
||||||
|
pContext->pulse.pa_mainloop_wakeup = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_mainloop_wakeup");
|
||||||
|
pContext->pulse.pa_context_new = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_context_new");
|
||||||
|
pContext->pulse.pa_context_unref = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_context_unref");
|
||||||
|
pContext->pulse.pa_context_connect = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_context_connect");
|
||||||
|
pContext->pulse.pa_context_disconnect = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_context_disconnect");
|
||||||
|
pContext->pulse.pa_context_set_state_callback = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_context_set_state_callback");
|
||||||
|
pContext->pulse.pa_context_get_state = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_context_get_state");
|
||||||
|
pContext->pulse.pa_context_get_sink_info_list = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_context_get_sink_info_list");
|
||||||
|
pContext->pulse.pa_context_get_source_info_list = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_context_get_source_info_list");
|
||||||
|
pContext->pulse.pa_context_get_sink_info_by_name = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_context_get_sink_info_by_name");
|
||||||
|
pContext->pulse.pa_context_get_source_info_by_name = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_context_get_source_info_by_name");
|
||||||
|
pContext->pulse.pa_operation_unref = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_operation_unref");
|
||||||
|
pContext->pulse.pa_operation_get_state = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_operation_get_state");
|
||||||
|
pContext->pulse.pa_channel_map_init_extend = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_channel_map_init_extend");
|
||||||
|
pContext->pulse.pa_channel_map_valid = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_channel_map_valid");
|
||||||
|
pContext->pulse.pa_channel_map_compatible = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_channel_map_compatible");
|
||||||
|
pContext->pulse.pa_stream_new = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_stream_new");
|
||||||
|
pContext->pulse.pa_stream_unref = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_stream_unref");
|
||||||
|
pContext->pulse.pa_stream_connect_playback = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_stream_connect_playback");
|
||||||
|
pContext->pulse.pa_stream_connect_record = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_stream_connect_record");
|
||||||
|
pContext->pulse.pa_stream_disconnect = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_stream_disconnect");
|
||||||
|
pContext->pulse.pa_stream_get_state = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_stream_get_state");
|
||||||
|
pContext->pulse.pa_stream_get_sample_spec = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_stream_get_sample_spec");
|
||||||
|
pContext->pulse.pa_stream_get_channel_map = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_stream_get_channel_map");
|
||||||
|
pContext->pulse.pa_stream_get_buffer_attr = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_stream_get_buffer_attr");
|
||||||
|
pContext->pulse.pa_stream_get_device_name = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_stream_get_device_name");
|
||||||
|
pContext->pulse.pa_stream_set_write_callback = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_stream_set_write_callback");
|
||||||
|
pContext->pulse.pa_stream_set_read_callback = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_stream_set_read_callback");
|
||||||
|
pContext->pulse.pa_stream_flush = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_stream_flush");
|
||||||
|
pContext->pulse.pa_stream_drain = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_stream_drain");
|
||||||
|
pContext->pulse.pa_stream_cork = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_stream_cork");
|
||||||
|
pContext->pulse.pa_stream_trigger = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_stream_trigger");
|
||||||
|
pContext->pulse.pa_stream_begin_write = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_stream_begin_write");
|
||||||
|
pContext->pulse.pa_stream_write = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_stream_write");
|
||||||
|
pContext->pulse.pa_stream_peek = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_stream_peek");
|
||||||
|
pContext->pulse.pa_stream_drop = (mal_proc)mal_dlsym(pContext->pulse.pulseSO, "pa_stream_drop");
|
||||||
|
#else
|
||||||
|
// This strange assignment system is just for type safety.
|
||||||
|
mal_pa_mainloop_new_proc _pa_mainloop_new = pa_mainloop_new;
|
||||||
|
mal_pa_mainloop_free_proc _pa_mainloop_free = pa_mainloop_free;
|
||||||
|
mal_pa_mainloop_get_api_proc _pa_mainloop_get_api = pa_mainloop_get_api;
|
||||||
|
mal_pa_mainloop_iterate_proc _pa_mainloop_iterate = pa_mainloop_iterate;
|
||||||
|
mal_pa_mainloop_wakeup_proc _pa_mainloop_wakeup = pa_mainloop_wakeup;
|
||||||
|
mal_pa_context_new_proc _pa_context_new = pa_context_new;
|
||||||
|
mal_pa_context_unref_proc _pa_context_unref = pa_context_unref;
|
||||||
|
mal_pa_context_connect_proc _pa_context_connect = pa_context_connect;
|
||||||
|
mal_pa_context_disconnect_proc _pa_context_disconnect = pa_context_disconnect;
|
||||||
|
mal_pa_context_set_state_callback_proc _pa_context_set_state_callback = pa_context_set_state_callback;
|
||||||
|
mal_pa_context_get_state_proc _pa_context_get_state = pa_context_get_state;
|
||||||
|
mal_pa_context_get_sink_info_list_proc _pa_context_get_sink_info_list = pa_context_get_sink_info_list;
|
||||||
|
mal_pa_context_get_source_info_list_proc _pa_context_get_source_info_list = pa_context_get_source_info_list;
|
||||||
|
mal_pa_context_get_sink_info_by_name_proc _pa_context_get_sink_info_by_name = pa_context_get_sink_info_by_name;
|
||||||
|
mal_pa_context_get_source_info_by_name_proc _pa_context_get_source_info_by_name= pa_context_get_source_info_by_name;
|
||||||
|
mal_pa_operation_unref_proc _pa_operation_unref = pa_operation_unref;
|
||||||
|
mal_pa_operation_get_state_proc _pa_operation_get_state = pa_operation_get_state;
|
||||||
|
mal_pa_channel_map_init_extend_proc _pa_channel_map_init_extend = pa_channel_map_init_extend;
|
||||||
|
mal_pa_channel_map_valid_proc _pa_channel_map_valid = pa_channel_map_valid;
|
||||||
|
mal_pa_channel_map_compatible_proc _pa_channel_map_compatible = pa_channel_map_compatible;
|
||||||
|
mal_pa_stream_new_proc _pa_stream_new = pa_stream_new;
|
||||||
|
mal_pa_stream_unref_proc _pa_stream_unref = pa_stream_unref;
|
||||||
|
mal_pa_stream_connect_playback_proc _pa_stream_connect_playback = pa_stream_connect_playback;
|
||||||
|
mal_pa_stream_connect_record_proc _pa_stream_connect_record = pa_stream_connect_record;
|
||||||
|
mal_pa_stream_disconnect_proc _pa_stream_disconnect = pa_stream_disconnect;
|
||||||
|
mal_pa_stream_get_state_proc _pa_stream_get_state = pa_stream_get_state;
|
||||||
|
mal_pa_stream_get_sample_spec_proc _pa_stream_get_sample_spec = pa_stream_get_sample_spec;
|
||||||
|
mal_pa_stream_get_channel_map_proc _pa_stream_get_channel_map = pa_stream_get_channel_map;
|
||||||
|
mal_pa_stream_get_buffer_attr_proc _pa_stream_get_buffer_attr = pa_stream_get_buffer_attr;
|
||||||
|
mal_pa_stream_get_device_name_proc _pa_stream_get_device_name = pa_stream_get_device_name;
|
||||||
|
mal_pa_stream_set_write_callback_proc _pa_stream_set_write_callback = pa_stream_set_write_callback;
|
||||||
|
mal_pa_stream_set_read_callback_proc _pa_stream_set_read_callback = pa_stream_set_read_callback;
|
||||||
|
mal_pa_stream_flush_proc _pa_stream_flush = pa_stream_flush;
|
||||||
|
mal_pa_stream_drain_proc _pa_stream_drain = pa_stream_drain;
|
||||||
|
mal_pa_stream_cork_proc _pa_stream_cork = pa_stream_cork;
|
||||||
|
mal_pa_stream_trigger_proc _pa_stream_trigger = pa_stream_trigger;
|
||||||
|
mal_pa_stream_begin_write_proc _pa_stream_begin_write = pa_stream_begin_write;
|
||||||
|
mal_pa_stream_write_proc _pa_stream_write = pa_stream_write;
|
||||||
|
mal_pa_stream_peek_proc _pa_stream_peek = pa_stream_peek;
|
||||||
|
mal_pa_stream_drop_proc _pa_stream_drop = pa_stream_drop;
|
||||||
|
|
||||||
|
pContext->pulse.pa_mainloop_new = (mal_proc)_pa_mainloop_new;
|
||||||
|
pContext->pulse.pa_mainloop_free = (mal_proc)_pa_mainloop_free;
|
||||||
|
pContext->pulse.pa_mainloop_get_api = (mal_proc)_pa_mainloop_get_api;
|
||||||
|
pContext->pulse.pa_mainloop_iterate = (mal_proc)_pa_mainloop_iterate;
|
||||||
|
pContext->pulse.pa_mainloop_wakeup = (mal_proc)_pa_mainloop_wakeup;
|
||||||
|
pContext->pulse.pa_context_new = (mal_proc)_pa_context_new;
|
||||||
|
pContext->pulse.pa_context_unref = (mal_proc)_pa_context_unref;
|
||||||
|
pContext->pulse.pa_context_connect = (mal_proc)_pa_context_connect;
|
||||||
|
pContext->pulse.pa_context_disconnect = (mal_proc)_pa_context_disconnect;
|
||||||
|
pContext->pulse.pa_context_set_state_callback = (mal_proc)_pa_context_set_state_callback;
|
||||||
|
pContext->pulse.pa_context_get_state = (mal_proc)_pa_context_get_state;
|
||||||
|
pContext->pulse.pa_context_get_sink_info_list = (mal_proc)_pa_context_get_sink_info_list;
|
||||||
|
pContext->pulse.pa_context_get_source_info_list = (mal_proc)_pa_context_get_source_info_list;
|
||||||
|
pContext->pulse.pa_context_get_sink_info_by_name = (mal_proc)_pa_context_get_sink_info_by_name;
|
||||||
|
pContext->pulse.pa_context_get_source_info_by_name = (mal_proc)_pa_context_get_source_info_by_name;
|
||||||
|
pContext->pulse.pa_operation_unref = (mal_proc)_pa_operation_unref;
|
||||||
|
pContext->pulse.pa_operation_get_state = (mal_proc)_pa_operation_get_state;
|
||||||
|
pContext->pulse.pa_channel_map_init_extend = (mal_proc)_pa_channel_map_init_extend;
|
||||||
|
pContext->pulse.pa_channel_map_valid = (mal_proc)_pa_channel_map_valid;
|
||||||
|
pContext->pulse.pa_channel_map_compatible = (mal_proc)_pa_channel_map_compatible;
|
||||||
|
pContext->pulse.pa_stream_new = (mal_proc)_pa_stream_new;
|
||||||
|
pContext->pulse.pa_stream_unref = (mal_proc)_pa_stream_unref;
|
||||||
|
pContext->pulse.pa_stream_connect_playback = (mal_proc)_pa_stream_connect_playback;
|
||||||
|
pContext->pulse.pa_stream_connect_record = (mal_proc)_pa_stream_connect_record;
|
||||||
|
pContext->pulse.pa_stream_disconnect = (mal_proc)_pa_stream_disconnect;
|
||||||
|
pContext->pulse.pa_stream_get_state = (mal_proc)_pa_stream_get_state;
|
||||||
|
pContext->pulse.pa_stream_get_sample_spec = (mal_proc)_pa_stream_get_sample_spec;
|
||||||
|
pContext->pulse.pa_stream_get_channel_map = (mal_proc)_pa_stream_get_channel_map;
|
||||||
|
pContext->pulse.pa_stream_get_buffer_attr = (mal_proc)_pa_stream_get_buffer_attr;
|
||||||
|
pContext->pulse.pa_stream_get_device_name = (mal_proc)_pa_stream_get_device_name;
|
||||||
|
pContext->pulse.pa_stream_set_write_callback = (mal_proc)_pa_stream_set_write_callback;
|
||||||
|
pContext->pulse.pa_stream_set_read_callback = (mal_proc)_pa_stream_set_read_callback;
|
||||||
|
pContext->pulse.pa_stream_flush = (mal_proc)_pa_stream_flush;
|
||||||
|
pContext->pulse.pa_stream_drain = (mal_proc)_pa_stream_drain;
|
||||||
|
pContext->pulse.pa_stream_cork = (mal_proc)_pa_stream_cork;
|
||||||
|
pContext->pulse.pa_stream_trigger = (mal_proc)_pa_stream_trigger;
|
||||||
|
pContext->pulse.pa_stream_begin_write = (mal_proc)_pa_stream_begin_write;
|
||||||
|
pContext->pulse.pa_stream_write = (mal_proc)_pa_stream_write;
|
||||||
|
pContext->pulse.pa_stream_peek = (mal_proc)_pa_stream_peek;
|
||||||
|
pContext->pulse.pa_stream_drop = (mal_proc)_pa_stream_drop;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
pContext->onUninit = mal_context_uninit__pulse;
|
||||||
|
pContext->onDeviceIDEqual = mal_context_is_device_id_equal__pulse;
|
||||||
|
pContext->onEnumDevices = mal_context_enumerate_devices__pulse;
|
||||||
|
pContext->onGetDeviceInfo = mal_context_get_device_info__pulse;
|
||||||
|
pContext->onDeviceInit = mal_device_init__pulse;
|
||||||
|
pContext->onDeviceUninit = mal_device_uninit__pulse;
|
||||||
|
pContext->onDeviceStart = mal_device__start_backend__pulse;
|
||||||
|
pContext->onDeviceStop = mal_device__stop_backend__pulse;
|
||||||
|
pContext->onDeviceBreakMainLoop = mal_device__break_main_loop__pulse;
|
||||||
|
pContext->onDeviceMainLoop = mal_device__main_loop__pulse;
|
||||||
|
|
||||||
|
|
||||||
|
// Although we have found the libpulse library, it doesn't necessarily mean PulseAudio is useable. We need to initialize
|
||||||
|
// and connect a dummy PulseAudio context to test PulseAudio's usability.
|
||||||
|
mal_pa_mainloop* pMainLoop = ((mal_pa_mainloop_new_proc)pContext->pulse.pa_mainloop_new)();
|
||||||
|
if (pMainLoop == NULL) {
|
||||||
|
return MAL_NO_BACKEND;
|
||||||
|
}
|
||||||
|
|
||||||
|
mal_pa_mainloop_api* pAPI = ((mal_pa_mainloop_get_api_proc)pContext->pulse.pa_mainloop_get_api)(pMainLoop);
|
||||||
|
if (pAPI == NULL) {
|
||||||
|
((mal_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)(pMainLoop);
|
||||||
|
return MAL_NO_BACKEND;
|
||||||
|
}
|
||||||
|
|
||||||
|
mal_pa_context* pPulseContext = ((mal_pa_context_new_proc)pContext->pulse.pa_context_new)(pAPI, pContext->config.pulse.pApplicationName);
|
||||||
|
if (pPulseContext == NULL) {
|
||||||
|
((mal_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)(pMainLoop);
|
||||||
|
return MAL_NO_BACKEND;
|
||||||
|
}
|
||||||
|
|
||||||
|
int error = ((mal_pa_context_connect_proc)pContext->pulse.pa_context_connect)(pPulseContext, pContext->config.pulse.pServerName, 0, NULL);
|
||||||
|
if (error != MAL_PA_OK) {
|
||||||
|
((mal_pa_context_unref_proc)pContext->pulse.pa_context_unref)(pPulseContext);
|
||||||
|
((mal_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)(pMainLoop);
|
||||||
|
return MAL_NO_BACKEND;
|
||||||
|
}
|
||||||
|
|
||||||
|
((mal_pa_context_disconnect_proc)pContext->pulse.pa_context_disconnect)(pPulseContext);
|
||||||
|
((mal_pa_context_unref_proc)pContext->pulse.pa_context_unref)(pPulseContext);
|
||||||
|
((mal_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)(pMainLoop);
|
||||||
|
return MAL_SUCCESS;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user