static ALCboolean pulse_load(void) //{{{ { ALCboolean ret = ALC_FALSE; if(!pa_handle) { pa_threaded_mainloop *loop; #ifdef HAVE_DYNLOAD #ifdef _WIN32 #define PALIB "libpulse-0.dll" #elif defined(__APPLE__) && defined(__MACH__) #define PALIB "libpulse.0.dylib" #else #define PALIB "libpulse.so.0" #endif pa_handle = LoadLib(PALIB); if(!pa_handle) return ALC_FALSE; #define LOAD_FUNC(x) do { \ p##x = GetSymbol(pa_handle, #x); \ if(!(p##x)) { \ CloseLib(pa_handle); \ pa_handle = NULL; \ return ALC_FALSE; \ } \ } while(0) LOAD_FUNC(pa_context_unref); LOAD_FUNC(pa_sample_spec_valid); LOAD_FUNC(pa_stream_drop); LOAD_FUNC(pa_strerror); LOAD_FUNC(pa_context_get_state); LOAD_FUNC(pa_stream_get_state); LOAD_FUNC(pa_threaded_mainloop_signal); LOAD_FUNC(pa_stream_peek); LOAD_FUNC(pa_threaded_mainloop_wait); LOAD_FUNC(pa_threaded_mainloop_unlock); LOAD_FUNC(pa_threaded_mainloop_in_thread); LOAD_FUNC(pa_context_new); LOAD_FUNC(pa_threaded_mainloop_stop); LOAD_FUNC(pa_context_disconnect); LOAD_FUNC(pa_threaded_mainloop_start); LOAD_FUNC(pa_threaded_mainloop_get_api); LOAD_FUNC(pa_context_set_state_callback); LOAD_FUNC(pa_stream_write); LOAD_FUNC(pa_xfree); LOAD_FUNC(pa_stream_connect_record); LOAD_FUNC(pa_stream_connect_playback); LOAD_FUNC(pa_stream_readable_size); LOAD_FUNC(pa_stream_writable_size); LOAD_FUNC(pa_stream_cork); LOAD_FUNC(pa_stream_is_suspended); LOAD_FUNC(pa_stream_get_device_name); LOAD_FUNC(pa_path_get_filename); LOAD_FUNC(pa_get_binary_name); LOAD_FUNC(pa_threaded_mainloop_free); LOAD_FUNC(pa_context_errno); LOAD_FUNC(pa_xmalloc); LOAD_FUNC(pa_stream_unref); LOAD_FUNC(pa_threaded_mainloop_accept); LOAD_FUNC(pa_stream_set_write_callback); LOAD_FUNC(pa_threaded_mainloop_new); LOAD_FUNC(pa_context_connect); LOAD_FUNC(pa_stream_set_buffer_attr); LOAD_FUNC(pa_stream_get_buffer_attr); LOAD_FUNC(pa_stream_get_sample_spec); LOAD_FUNC(pa_stream_get_time); LOAD_FUNC(pa_stream_set_read_callback); LOAD_FUNC(pa_stream_set_state_callback); LOAD_FUNC(pa_stream_set_moved_callback); LOAD_FUNC(pa_stream_set_underflow_callback); LOAD_FUNC(pa_stream_new); LOAD_FUNC(pa_stream_disconnect); LOAD_FUNC(pa_threaded_mainloop_lock); LOAD_FUNC(pa_channel_map_init_auto); LOAD_FUNC(pa_channel_map_parse); LOAD_FUNC(pa_channel_map_snprint); LOAD_FUNC(pa_channel_map_equal); LOAD_FUNC(pa_context_get_server_info); LOAD_FUNC(pa_context_get_sink_info_by_name); LOAD_FUNC(pa_context_get_sink_info_list); LOAD_FUNC(pa_context_get_source_info_list); LOAD_FUNC(pa_operation_get_state); LOAD_FUNC(pa_operation_unref); #undef LOAD_FUNC #define LOAD_OPTIONAL_FUNC(x) do { \ p##x = GetSymbol(pa_handle, #x); \ } while(0) #if PA_CHECK_VERSION(0,9,15) LOAD_OPTIONAL_FUNC(pa_channel_map_superset); LOAD_OPTIONAL_FUNC(pa_stream_set_buffer_attr_callback); #endif #if PA_CHECK_VERSION(0,9,16) LOAD_OPTIONAL_FUNC(pa_stream_begin_write); #endif #undef LOAD_OPTIONAL_FUNC #else /* HAVE_DYNLOAD */ pa_handle = (void*)0xDEADBEEF; #endif if((loop=pa_threaded_mainloop_new()) && pa_threaded_mainloop_start(loop) >= 0) { pa_context *context; pa_threaded_mainloop_lock(loop); context = connect_context(loop, AL_TRUE); if(context) { ret = ALC_TRUE; pa_context_disconnect(context); pa_context_unref(context); } pa_threaded_mainloop_unlock(loop); pa_threaded_mainloop_stop(loop); } if(loop) pa_threaded_mainloop_free(loop); if(!ret) { #ifdef HAVE_DYNLOAD CloseLib(pa_handle); #endif pa_handle = NULL; } } return ret; } //}}}
void* pulse_load( void ) //{{{ { if ( !pa_handle ) { #ifdef _WIN32 pa_handle = LoadLibrary( "libpulse-0.dll" ); #define LOAD_FUNC(x) do { \ p##x = (typeof(p##x))GetProcAddress(pa_handle, #x); \ if(!(p##x)) { \ AL_PRINT("Could not load %s from libpulse-0.dll\n", #x); \ FreeLibrary(pa_handle); \ pa_handle = NULL; \ return NULL; \ } \ } while(0) #define LOAD_OPTIONAL_FUNC(x) do { \ p##x = (typeof(p##x))GetProcAddress(pa_handle, #x); \ } while(0) #elif defined (HAVE_DLFCN_H) const char* err; #if defined(__APPLE__) && defined(__MACH__) pa_handle = dlopen( "libpulse.0.dylib", RTLD_NOW ); #else pa_handle = dlopen( "libpulse.so.0", RTLD_NOW ); #endif dlerror(); #define LOAD_FUNC(x) do { \ p##x = dlsym(pa_handle, #x); \ if((err=dlerror()) != NULL) { \ AL_PRINT("Could not load %s from libpulse: %s\n", #x, err); \ dlclose(pa_handle); \ pa_handle = NULL; \ return NULL; \ } \ } while(0) #define LOAD_OPTIONAL_FUNC(x) do { \ p##x = dlsym(pa_handle, #x); \ if((err=dlerror()) != NULL) { \ p##x = NULL; \ } \ } while(0) #else pa_handle = ( void* )0xDEADBEEF; #define LOAD_FUNC(x) p##x = (x) #define LOAD_OPTIONAL_FUNC(x) p##x = (x) #endif if ( !pa_handle ) { return NULL; } LOAD_FUNC( pa_context_unref ); LOAD_FUNC( pa_sample_spec_valid ); LOAD_FUNC( pa_stream_drop ); LOAD_FUNC( pa_strerror ); LOAD_FUNC( pa_context_get_state ); LOAD_FUNC( pa_stream_get_state ); LOAD_FUNC( pa_threaded_mainloop_signal ); LOAD_FUNC( pa_stream_peek ); LOAD_FUNC( pa_threaded_mainloop_wait ); LOAD_FUNC( pa_threaded_mainloop_unlock ); LOAD_FUNC( pa_threaded_mainloop_in_thread ); LOAD_FUNC( pa_context_new ); LOAD_FUNC( pa_threaded_mainloop_stop ); LOAD_FUNC( pa_context_disconnect ); LOAD_FUNC( pa_threaded_mainloop_start ); LOAD_FUNC( pa_threaded_mainloop_get_api ); LOAD_FUNC( pa_context_set_state_callback ); LOAD_FUNC( pa_stream_write ); LOAD_FUNC( pa_xfree ); LOAD_FUNC( pa_stream_connect_record ); LOAD_FUNC( pa_stream_connect_playback ); LOAD_FUNC( pa_stream_readable_size ); LOAD_FUNC( pa_stream_cork ); LOAD_FUNC( pa_stream_is_suspended ); LOAD_FUNC( pa_stream_get_device_name ); LOAD_FUNC( pa_path_get_filename ); LOAD_FUNC( pa_get_binary_name ); LOAD_FUNC( pa_threaded_mainloop_free ); LOAD_FUNC( pa_context_errno ); LOAD_FUNC( pa_xmalloc ); LOAD_FUNC( pa_stream_unref ); LOAD_FUNC( pa_threaded_mainloop_accept ); LOAD_FUNC( pa_stream_set_write_callback ); LOAD_FUNC( pa_threaded_mainloop_new ); LOAD_FUNC( pa_context_connect ); LOAD_FUNC( pa_stream_set_buffer_attr ); LOAD_FUNC( pa_stream_get_buffer_attr ); LOAD_FUNC( pa_stream_get_sample_spec ); LOAD_FUNC( pa_stream_set_read_callback ); LOAD_FUNC( pa_stream_set_state_callback ); LOAD_FUNC( pa_stream_set_moved_callback ); LOAD_FUNC( pa_stream_new ); LOAD_FUNC( pa_stream_disconnect ); LOAD_FUNC( pa_threaded_mainloop_lock ); LOAD_FUNC( pa_channel_map_init_auto ); LOAD_FUNC( pa_channel_map_parse ); LOAD_FUNC( pa_channel_map_snprint ); LOAD_FUNC( pa_channel_map_equal ); LOAD_FUNC( pa_context_get_server_info ); LOAD_FUNC( pa_context_get_sink_info_by_name ); LOAD_FUNC( pa_context_get_sink_info_list ); LOAD_FUNC( pa_context_get_source_info_list ); LOAD_FUNC( pa_operation_get_state ); LOAD_FUNC( pa_operation_unref ); #if PA_CHECK_VERSION(0,9,15) LOAD_OPTIONAL_FUNC( pa_channel_map_superset ); LOAD_OPTIONAL_FUNC( pa_stream_set_buffer_attr_callback ); #endif #if PA_CHECK_VERSION(0,9,16) LOAD_OPTIONAL_FUNC( pa_stream_begin_write ); #endif #undef LOAD_OPTIONAL_FUNC #undef LOAD_FUNC } return pa_handle; } //}}}