diff options
author | Tofu Linden <tofu.linden@lindenlab.com> | 2010-02-22 13:12:44 +0000 |
---|---|---|
committer | Tofu Linden <tofu.linden@lindenlab.com> | 2010-02-22 13:12:44 +0000 |
commit | 9c66a9b6eb18276823a91e344a82787149ad7c15 (patch) | |
tree | 0db8924cb6967a2d23dfa0af22a10cb41e9146ec /indra/media_plugins/webkit/linux_volume_catcher.cpp | |
parent | 1b6a57564c166e9b54eba8e6a1eccc4399d387ec (diff) |
Really start to fill the implementation in.
Diffstat (limited to 'indra/media_plugins/webkit/linux_volume_catcher.cpp')
-rw-r--r-- | indra/media_plugins/webkit/linux_volume_catcher.cpp | 141 |
1 files changed, 140 insertions, 1 deletions
diff --git a/indra/media_plugins/webkit/linux_volume_catcher.cpp b/indra/media_plugins/webkit/linux_volume_catcher.cpp index 8d8600c344..43731fe8d0 100644 --- a/indra/media_plugins/webkit/linux_volume_catcher.cpp +++ b/indra/media_plugins/webkit/linux_volume_catcher.cpp @@ -40,19 +40,158 @@ #include <pulse/subscribe.h> #include <pulse/glib-mainloop.h> // There's no special reason why we want the *glib* PA mainloop, but the generic polling implementation seems broken. +#include "linux_volume_catcher.h" + +//////////////////////////////////////////////////// + +LinuxVolumeCatcher::LinuxVolumeCatcher() +{ + pimpl = new LinuxVolumeCatcherImpl(); +} + +LinuxVolumeCatcher::LinuxVolumeCatcher~() +{ + delete pimpl; + pimpl = NULL; +} + +void LinuxVolumeCatcher::setVol(F32 volume) +{ + llassert(pimpl); + pimpl->setVol(volume); +} + +void LinuxVolumeCatcher::pump() +{ + llassert(pimpl); + pimpl->pump(); +} + +///////////////////////////////////////////////////// + +// 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); + void callback_subscription_alert(pa_context *context, pa_subscription_event_type_t t, uint32_t index, void *userdata); + void callback_context_state(pa_context *context, void *userdata); +} + + class LinuxVolumeCatcherImpl { public: + LinuxVolumeCatcherImpl(); + ~LinuxVolumeCatcherImpl(); + void setVol(F32 volume); void pump(void); private: + void init(); + void cleanup(); + + void connected_okay(); + void update_index_volume(F32 volume); + void update_all_volumes(F32 volume); + F32 mDesiredVolume; pa_glib_mainloop *mMainloop; - pa_context *mLastContext; + pa_context *mPAContext; bool connected; std::set<U32> mSinkInputIndices; std::map<U32,U32> mSinkInputNumChannels; +}; + +LinuxVolumeCatcherImpl::LinuxVolumeCatcherImpl() + : mDesiredVolume(0.0f), + mMainloop(NULL), + mPAContext(NULL), + mConnected(false) +{ + init(); } +LinuxVolumeCatcherImpl::~LinuxVolumeCatcherImpl() +{ + cleanup(); +} + +LinuxVolumeCatcherImpl::init() +{ + // try to be as robust as possible because PA's interface is a + // bit fragile and (for our purposes) we'd rather simply not function + // than crash + mMainloop = pa_glib_mainloop_new(g_main_context_default()); + if (mMainloop) + { + pa_mainloop_api *api = pa_glib_mainloop_get_api(mMainloop); + if (api) + { + pa_proplist *proplist = pa_proplist_new(); + if (proplist) + { + pa_proplist_sets(proplist, PA_PROP_APPLICATION_ICON_NAME, "multimedia-player"); + pa_proplist_sets(proplist, PA_PROP_APPLICATION_ID, "com.secondlife.viewer.mediaplugvoladjust"); + pa_proplist_sets(proplist, PA_PROP_APPLICATION_NAME, "SL Plugin Volume Adjuster"); + pa_proplist_sets(proplist, PA_PROP_APPLICATION_VERSION, "1"); + + // plain old pa_context_new() is broken! + mPAContext = pa_context_new_with_proplist(api, NULL, proplist); + pa_proplist_free(proplist); + } + } + } + + // Now we've set up a PA context and mainloop, try connecting the + // PA context to a PA daemon. + if (mPAContext) + { + pa_context_set_state_callback(mPAContext, callback_context_state, NULL); + pa_context_flags_t cflags = 0; // maybe add PA_CONTEXT_NOAUTOSPAWN? + if (pa_context_connect(mPAContext, NULL, cflags, NULL) >= 0) + { + // Okay! We haven't definitely connected, but we + // haven't definitely failed yet. + } + else + { + // Failed to connect to PA manager... we'll leave + // things like that. Perhaps we should try again later. + } + } +} + +LinuxVolumeCatcherImpl::cleanup() +{ + // there's some cleanup we could do, but do nothing... for now. +} + +LinuxVolumeCatcherImpl::setVol(F32 volume) +{ + mDesiredVolume = volume; + + if (mConnected && mPAContext) + { + update_all_volumes(mDesiredVolume); + } + + pump(); +} + +LinuxVolumeCatcherImpl::pump() +{ + g_main_context_iteration(g_main_context_default()); +} + +void callback_discovered_sinkinput(pa_context *context, const pa_sink_input_info *i, int eol, void *userdata) +{ +} + +void callback_subscription_alert(pa_context *context, pa_subscription_event_type_t t, uint32_t index, void *userdata) +{ +} + +void callback_context_state(pa_context *context, void *userdata) +{ +} |