summaryrefslogtreecommitdiff
path: root/indra/media_plugins
diff options
context:
space:
mode:
Diffstat (limited to 'indra/media_plugins')
-rw-r--r--indra/media_plugins/webkit/CMakeLists.txt11
-rw-r--r--indra/media_plugins/webkit/linux_volume_catcher.cpp202
2 files changed, 170 insertions, 43 deletions
diff --git a/indra/media_plugins/webkit/CMakeLists.txt b/indra/media_plugins/webkit/CMakeLists.txt
index a9e202da99..a43680bb16 100644
--- a/indra/media_plugins/webkit/CMakeLists.txt
+++ b/indra/media_plugins/webkit/CMakeLists.txt
@@ -34,11 +34,6 @@ set(media_plugin_webkit_SOURCE_FILES
media_plugin_webkit.cpp
)
-add_library(media_plugin_webkit
- SHARED
- ${media_plugin_webkit_SOURCE_FILES}
-)
-
set(media_plugin_webkit_LINK_LIBRARIES
${LLPLUGIN_LIBRARIES}
${MEDIA_PLUGIN_BASE_LIBRARIES}
@@ -48,6 +43,7 @@ set(media_plugin_webkit_LINK_LIBRARIES
)
if (LINUX)
+ list(APPEND media_plugin_webkit_SOURCE_FILES linux_volume_catcher.cpp)
list(APPEND media_plugin_webkit_LINK_LIBRARIES
${UI_LIBRARIES} # for glib/GTK
pulse
@@ -55,6 +51,11 @@ if (LINUX)
)
endif (LINUX)
+add_library(media_plugin_webkit
+ SHARED
+ ${media_plugin_webkit_SOURCE_FILES}
+)
+
target_link_libraries(media_plugin_webkit ${media_plugin_webkit_LINK_LIBRARIES})
add_dependencies(media_plugin_webkit
diff --git a/indra/media_plugins/webkit/linux_volume_catcher.cpp b/indra/media_plugins/webkit/linux_volume_catcher.cpp
index 43731fe8d0..6eb5a9a30c 100644
--- a/indra/media_plugins/webkit/linux_volume_catcher.cpp
+++ b/indra/media_plugins/webkit/linux_volume_catcher.cpp
@@ -44,31 +44,6 @@
////////////////////////////////////////////////////
-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);
@@ -86,20 +61,21 @@ public:
void setVol(F32 volume);
void pump(void);
-private:
+ // for internal use - can't be private because used from our C callbacks
+
void init();
void cleanup();
- void connected_okay();
- void update_index_volume(F32 volume);
void update_all_volumes(F32 volume);
+ void update_index_volume(U32 index, F32 volume);
+ void connected_okay();
+ std::set<U32> mSinkInputIndices;
+ std::map<U32,U32> mSinkInputNumChannels;
F32 mDesiredVolume;
pa_glib_mainloop *mMainloop;
pa_context *mPAContext;
- bool connected;
- std::set<U32> mSinkInputIndices;
- std::map<U32,U32> mSinkInputNumChannels;
+ bool mConnected;
};
LinuxVolumeCatcherImpl::LinuxVolumeCatcherImpl()
@@ -116,7 +92,7 @@ LinuxVolumeCatcherImpl::~LinuxVolumeCatcherImpl()
cleanup();
}
-LinuxVolumeCatcherImpl::init()
+void 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
@@ -146,8 +122,8 @@ LinuxVolumeCatcherImpl::init()
// 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?
+ pa_context_set_state_callback(mPAContext, callback_context_state, this);
+ pa_context_flags_t cflags = (pa_context_flags)0; // maybe add PA_CONTEXT_NOAUTOSPAWN?
if (pa_context_connect(mPAContext, NULL, cflags, NULL) >= 0)
{
// Okay! We haven't definitely connected, but we
@@ -161,12 +137,14 @@ LinuxVolumeCatcherImpl::init()
}
}
-LinuxVolumeCatcherImpl::cleanup()
+void LinuxVolumeCatcherImpl::cleanup()
{
// there's some cleanup we could do, but do nothing... for now.
+
+ mConnected = false;
}
-LinuxVolumeCatcherImpl::setVol(F32 volume)
+void LinuxVolumeCatcherImpl::setVol(F32 volume)
{
mDesiredVolume = volume;
@@ -178,20 +156,168 @@ LinuxVolumeCatcherImpl::setVol(F32 volume)
pump();
}
-LinuxVolumeCatcherImpl::pump()
+void 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 LinuxVolumeCatcherImpl::connected_okay()
{
+ pa_operation *op;
+
+ // fetch global list of existing sinkinputs
+ if (op = pa_context_get_sink_input_info_list(mPAContext,
+ callback_discovered_sinkinput,
+ this))
+ {
+ pa_operation_unref(op);
+ }
+
+ // subscribe to future global sinkinput changes
+ pa_context_set_subscribe_callback(mPAContext,
+ callback_subscription_alert,
+ this);
+ if (op = pa_context_subscribe(mPAContext, (pa_subscription_mask_t)
+ (PA_SUBSCRIPTION_MASK_SINK_INPUT),
+ NULL, NULL))
+ {
+ pa_operation_unref(op);
+ }
+}
+
+void LinuxVolumeCatcherImpl::update_all_volumes(F32 volume)
+{
+ for (std::set<U32>::iterator it = mSinkInputIndices.begin();
+ it != mSinkInputIndices.end(); ++it)
+ {
+ update_index_volume(*it, volume);
+ }
+}
+
+void LinuxVolumeCatcherImpl::update_index_volume(U32 index, F32 volume)
+{
+ static pa_cvolume cvol;
+ pa_cvolume_set(&cvol, mSinkInputNumChannels[index],
+ pa_sw_volume_from_linear(volume));
+
+ pa_context *c = mPAContext;
+ uint32_t idx = index;
+ const pa_cvolume *volume = &cvol;
+ pa_context_success_cb_t cb = NULL; // okay as null
+ void *userdata = NULL; // okay as null
+
+ if (op = pa_context_set_sink_input_volume(c, idx, volume, cb, userdata))
+ {
+ pa_operation_unref(op);
+ }
+}
+
+
+void callback_discovered_sinkinput(pa_context *context, const pa_sink_input_info *sii, int eol, void *userdata)
+{
+ LinuxVolumeCatcherImpl *impl = dynamic_cast<LinuxVolumeCatcherImpl*>(userdata);
+ llassert(impl);
+
+ if (0 == eol)
+ {
+ pa_proplist *proplist = sii->proplist;
+ pid_t sinkpid = atoll(pa_proplist_gets(proplist, PA_PROP_APPLICATION_PROCESS_ID));
+ fprintf(stderr, "Found sinkinput #%d, name=%s, pid=%d\t", sii->index, sii->name, int(sinkpid));
+
+ if (sinkpid == getpid()) // does the discovered sinkinput belong to this process?
+ {
+ bool is_new = (impl->mSinkInputIndices.find(sii->index) ==
+ impl->mSinkInputIndices.end());
+
+ impl->mSinkInputIndices.insert(sii->index);
+ impl->mSinkInputNumChannels[sii->index] = sii->channel_map.channels;
+
+ if (is_new)
+ {
+ // new!
+ fprintf(stderr, "\nJACKPOT!\n");
+ impl->update_index_volume(sii->index, impl->mDesiredVolume);
+ }
+ else
+ {
+ // seen it already, do nothing.
+ }
+ }
+ }
}
void callback_subscription_alert(pa_context *context, pa_subscription_event_type_t t, uint32_t index, void *userdata)
{
+ LinuxVolumeCatcherImpl *impl = dynamic_cast<LinuxVolumeCatcherImpl*>(userdata);
+ llassert(impl);
+
+ switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) {
+ case PA_SUBSCRIPTION_EVENT_SINK_INPUT:
+ if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) ==
+ PA_SUBSCRIPTION_EVENT_REMOVE)
+ {
+ // forget this sinkinput, if we were caring about it
+ impl->mSinkInputIndices.erase(index);
+ impl->mSinkInputNumChannels.erase(index);
+ }
+ else
+ {
+ // ask for more info about this new sinkinput
+ pa_operation *op;
+ if (op = pa_context_get_sink_input_info(impl->mPAContext, index, callback_discovered_sinkinput, impl))
+ {
+ pa_operation_unref(o);
+ }
+ }
+ break;
+
+ default:;
+ }
}
void callback_context_state(pa_context *context, void *userdata)
{
+ LinuxVolumeCatcherImpl *impl = dynamic_cast<LinuxVolumeCatcherImpl*>(userdata);
+ llassert(impl);
+
+ switch (pa_context_get_state(c))
+ {
+ case PA_CONTEXT_READY:
+ impl->mConnected = true;
+ impl->connected_okay(c);
+ break;
+ case PA_CONTEXT_TERMINATED:
+ impl->mConnected = false;
+ break;
+ case PA_CONTEXT_FAILED:
+ impl->mConnected = false;
+ break;
+ default:;
+ }
+}
+
+/////////////////////////////////////////////////////
+
+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();
}