summaryrefslogtreecommitdiff
path: root/indra/media_plugins/webkit/linux_volume_catcher.cpp
diff options
context:
space:
mode:
authorTofu Linden <tofu.linden@lindenlab.com>2010-02-22 13:12:44 +0000
committerTofu Linden <tofu.linden@lindenlab.com>2010-02-22 13:12:44 +0000
commit9c66a9b6eb18276823a91e344a82787149ad7c15 (patch)
tree0db8924cb6967a2d23dfa0af22a10cb41e9146ec /indra/media_plugins/webkit/linux_volume_catcher.cpp
parent1b6a57564c166e9b54eba8e6a1eccc4399d387ec (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.cpp141
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)
+{
+}