diff options
3 files changed, 126 insertions, 1 deletions
| diff --git a/indra/media_plugins/webkit/linux_volume_catcher.cpp b/indra/media_plugins/webkit/linux_volume_catcher.cpp index d61b00cf67..4f4f3c1740 100644 --- a/indra/media_plugins/webkit/linux_volume_catcher.cpp +++ b/indra/media_plugins/webkit/linux_volume_catcher.cpp @@ -53,6 +53,95 @@  //////////////////////////////////////////////////// +#define DEBUGMSG(...) do {} while(0) +#define INFOMSG(...) do {} while(0) +#define WARNMSG(...) do {} while(0) + +#define LL_PA_SYM(REQUIRED, PASYM, RTN, ...) RTN (*ll##PASYM)(__VA_ARGS__) = NULL +#include "linux_volume_catcher_pa_syms.inc" +#undef LL_PA_SYM + +static bool sSymsGrabbed = false; +static apr_pool_t *sSymPADSOMemoryPool = NULL; +static apr_dso_handle_t *sSymPADSOHandleG = NULL; + +bool grab_pa_syms(std::string pa_dso_name) +{ +	if (sSymsGrabbed) +	{ +		// already have grabbed good syms +		return true; +	} + +	bool sym_error = false; +	bool rtn = false; +	apr_status_t rv; +	apr_dso_handle_t *sSymPADSOHandle = NULL; + +#define LL_PA_SYM(REQUIRED, PASYM, RTN, ...) do{rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll##PASYM, sSymPADSOHandle, #PASYM); if (rv != APR_SUCCESS) {INFOMSG("Failed to grab symbol: %s", #PASYM); if (REQUIRED) sym_error = true;} else DEBUGMSG("grabbed symbol: %s from %p", #PASYM, (void*)ll##PASYM);}while(0) + +	//attempt to load the shared library +	apr_pool_create(&sSymPADSOMemoryPool, NULL); +   +	if ( APR_SUCCESS == (rv = apr_dso_load(&sSymPADSOHandle, +					       pa_dso_name.c_str(), +					       sSymPADSOMemoryPool) )) +	{ +		INFOMSG("Found DSO: %s", pa_dso_name.c_str()); + +#include "linux_volume_catcher_pa_syms.inc" +       +		if ( sSymPADSOHandle ) +		{ +			sSymPADSOHandleG = sSymPADSOHandle; +			sSymPADSOHandle = NULL; +		} +       +		rtn = !sym_error; +	} +	else +	{ +		INFOMSG("Couldn't load DSO: %s", pa_dso_name.c_str()); +		rtn = false; // failure +	} + +	if (sym_error) +	{ +		WARNMSG("Failed to find necessary symbols in PulseAudio libraries."); +	} +#undef LL_PA_SYM + +	sSymsGrabbed = rtn; +	return rtn; +} + + +void ungrab_pa_syms() +{  +	// should be safe to call regardless of whether we've +	// actually grabbed syms. + +	if ( sSymPADSOHandleG ) +	{ +		apr_dso_unload(sSymPADSOHandleG); +		sSymPADSOHandleG = NULL; +	} +	 +	if ( sSymPADSOMemoryPool ) +	{ +		apr_pool_destroy(sSymPADSOMemoryPool); +		sSymPADSOMemoryPool = NULL; +	} +	 +	// NULL-out all of the symbols we'd grabbed +#define LL_PA_SYM(REQUIRED, PASYM, RTN, ...) do{ll##PASYM = NULL;}while(0) +#include "linux_volume_catcher_pa_syms.inc" +#undef LL_PA_SYM + +	sSymsGrabbed = false; +} +//////////////////////////////////////////////////// +  // PulseAudio requires a chain of callbacks with C linkage  extern "C" {  	void callback_discovered_sinkinput(pa_context *context, const pa_sink_input_info *i, int eol, void *userdata); @@ -72,7 +161,7 @@ public:  	// for internal use - can't be private because used from our C callbacks -	bool loadsyms(); +	bool loadsyms(std::string pulse_dso_name, std::string pulse_glib_dso_name);  	void init();  	void cleanup(); @@ -104,11 +193,20 @@ LinuxVolumeCatcherImpl::~LinuxVolumeCatcherImpl()  	cleanup();  } +bool LinuxVolumeCatcherImpl::loadsyms(std::string pulse_dso_name, +				      std::string pulse_glib_dso_name) +{ +	return grab_pa_syms(pulse_dso_name, pulse_glib_dso_name); +} +  void LinuxVolumeCatcherImpl::init()  {  	// try to be as defensive as possible because PA's interface is a  	// bit fragile and (for our purposes) we'd rather simply not function  	// than crash + +	mGotSyms = loadsyms("libpulse.so.0", "libpulse-mainloop-glib.so.0"); +  	mMainloop = llpa_glib_mainloop_new(g_main_context_default());  	if (mMainloop)  	{ diff --git a/indra/media_plugins/webkit/linux_volume_catcher_pa_syms.inc b/indra/media_plugins/webkit/linux_volume_catcher_pa_syms.inc new file mode 100644 index 0000000000..d806b48428 --- /dev/null +++ b/indra/media_plugins/webkit/linux_volume_catcher_pa_syms.inc @@ -0,0 +1,21 @@ +// required symbols to grab +LL_PA_SYM(true, pa_context_connect, int, pa_context *c, const char *server, pa_context_flags_t flags, const pa_spawn_api *api); +LL_PA_SYM(true, pa_context_disconnect, void, pa_context *c); +LL_PA_SYM(true, pa_context_get_sink_input_info, pa_operation*, pa_context *c, uint32_t idx, pa_sink_input_info_cb_t cb, void *userdata); +LL_PA_SYM(true, pa_context_get_sink_input_info_list, pa_operation*, pa_context *c, pa_sink_input_info_cb_t cb, void *userdata); +LL_PA_SYM(true, pa_context_get_state, pa_context_state_t, pa_context *c); +LL_PA_SYM(true, pa_context_new_with_proplist, pa_context*, pa_mainloop_api *mainloop, const char *name, pa_proplist *proplist); +LL_PA_SYM(true, pa_context_set_sink_input_volume, pa_operation*, pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata); +LL_PA_SYM(true, pa_context_set_state_callback, void, pa_context *c, pa_context_notify_cb_t cb, void *userdata); +LL_PA_SYM(true, pa_context_set_subscribe_callback, void, pa_context *c, pa_context_subscribe_cb_t cb, void *userdata); +LL_PA_SYM(true, pa_context_subscribe, pa_operation*, pa_context *c, pa_subscription_mask_t m, pa_context_success_cb_t cb, void *userdata); +LL_PA_SYM(true, pa_context_unref, void, pa_context *c); +LL_PA_SYM(true, pa_cvolume_set, pa_cvolume*, pa_cvolume *a, unsigned channels, pa_volume_t v); +LL_PA_SYM(true, pa_operation_unref, void, pa_operation *o); +LL_PA_SYM(true, pa_proplist_free, void, pa_proplist* p); +LL_PA_SYM(true, pa_proplist_gets, const char*, pa_proplist *p, const char *key); +LL_PA_SYM(true, pa_proplist_new, pa_proplist*, void); +LL_PA_SYM(true, pa_proplist_sets, int, pa_proplist *p, const char *key, const char *value); +LL_PA_SYM(true, pa_sw_volume_from_linear, pa_volume_t, double v); + +// optional symbols to grab diff --git a/indra/media_plugins/webkit/linux_volume_catcher_paglib_syms.inc b/indra/media_plugins/webkit/linux_volume_catcher_paglib_syms.inc new file mode 100644 index 0000000000..abf628c96c --- /dev/null +++ b/indra/media_plugins/webkit/linux_volume_catcher_paglib_syms.inc @@ -0,0 +1,6 @@ +// required symbols to grab +LL_PA_SYM(true, pa_glib_mainloop_free, void, pa_glib_mainloop* g); +LL_PA_SYM(true, pa_glib_mainloop_get_api, pa_mainloop_api*, pa_glib_mainloop* g); +LL_PA_SYM(true, pa_glib_mainloop_new, pa_glib_mainloop *, GMainContext *c); + +// optional symbols to grab | 
