summaryrefslogtreecommitdiff
path: root/backends/pulse/pulse-source-output.c
diff options
context:
space:
mode:
Diffstat (limited to 'backends/pulse/pulse-source-output.c')
-rw-r--r--backends/pulse/pulse-source-output.c198
1 files changed, 158 insertions, 40 deletions
diff --git a/backends/pulse/pulse-source-output.c b/backends/pulse/pulse-source-output.c
index 94a4963..50269ce 100644
--- a/backends/pulse/pulse-source-output.c
+++ b/backends/pulse/pulse-source-output.c
@@ -17,44 +17,55 @@
#include <glib.h>
#include <glib-object.h>
+#include <string.h>
+#include <libmatemixer/matemixer-client-stream.h>
#include <libmatemixer/matemixer-stream.h>
#include <pulse/pulseaudio.h>
#include "pulse-connection.h"
+#include "pulse-client-stream.h"
+#include "pulse-monitor.h"
#include "pulse-stream.h"
+#include "pulse-source.h"
#include "pulse-source-output.h"
-struct _PulseSourceOutputPrivate
-{
- guint32 index_monitor;
-};
-
-static gboolean source_output_set_mute (MateMixerStream *stream, gboolean mute);
-static gboolean source_output_set_volume (MateMixerStream *stream, pa_cvolume *volume);
+static void pulse_source_output_class_init (PulseSourceOutputClass *klass);
+static void pulse_source_output_init (PulseSourceOutput *output);
-G_DEFINE_TYPE (PulseSourceOutput, pulse_source_output, PULSE_TYPE_STREAM);
+G_DEFINE_TYPE (PulseSourceOutput, pulse_source_output, PULSE_TYPE_CLIENT_STREAM);
-static void
-pulse_source_output_init (PulseSourceOutput *output)
-{
- output->priv = G_TYPE_INSTANCE_GET_PRIVATE (output,
- PULSE_TYPE_SOURCE_OUTPUT,
- PulseSourceOutputPrivate);
-}
+static gboolean source_output_set_mute (MateMixerStream *stream,
+ gboolean mute);
+static gboolean source_output_set_volume (MateMixerStream *stream,
+ pa_cvolume *volume);
+static gboolean source_output_set_parent (MateMixerClientStream *stream,
+ MateMixerStream *parent);
+static gboolean source_output_remove (MateMixerClientStream *stream);
+static PulseMonitor *source_output_create_monitor (MateMixerStream *stream);
static void
pulse_source_output_class_init (PulseSourceOutputClass *klass)
{
- PulseStreamClass *stream_class;
+ PulseStreamClass *stream_class;
+ PulseClientStreamClass *client_class;
stream_class = PULSE_STREAM_CLASS (klass);
- stream_class->set_mute = source_output_set_mute;
- stream_class->set_volume = source_output_set_volume;
+ stream_class->set_mute = source_output_set_mute;
+ stream_class->set_volume = source_output_set_volume;
+ stream_class->create_monitor = source_output_create_monitor;
- g_type_class_add_private (klass, sizeof (PulseSourceOutputPrivate));
+ client_class = PULSE_CLIENT_STREAM_CLASS (klass);
+
+ client_class->set_parent = source_output_set_parent;
+ client_class->remove = source_output_remove;
+}
+
+static void
+pulse_source_output_init (PulseSourceOutput *output)
+{
}
PulseStream *
@@ -62,6 +73,9 @@ pulse_source_output_new (PulseConnection *connection, const pa_source_output_inf
{
PulseSourceOutput *output;
+ g_return_val_if_fail (PULSE_IS_CONNECTION (connection), NULL);
+ g_return_val_if_fail (info != NULL, NULL);
+
/* Consider the sink input index as unchanging parameter */
output = g_object_new (PULSE_TYPE_SOURCE_OUTPUT,
"connection", connection,
@@ -77,27 +91,59 @@ pulse_source_output_new (PulseConnection *connection, const pa_source_output_inf
gboolean
pulse_source_output_update (PulseStream *stream, const pa_source_output_info *info)
{
- MateMixerStreamFlags flags = MATE_MIXER_STREAM_INPUT |
- MATE_MIXER_STREAM_CLIENT |
- MATE_MIXER_STREAM_HAS_MUTE;
+ MateMixerStreamFlags flags = MATE_MIXER_STREAM_INPUT |
+ MATE_MIXER_STREAM_CLIENT;
+ gchar *name;
+
+ const gchar *prop;
+ const gchar *description = NULL;
g_return_val_if_fail (PULSE_IS_SOURCE_OUTPUT (stream), FALSE);
/* Let all the information update before emitting notify signals */
g_object_freeze_notify (G_OBJECT (stream));
- pulse_stream_update_name (stream, info->name);
- // pulse_stream_update_description (stream, info->description);
- pulse_stream_update_mute (stream, info->mute ? TRUE : FALSE);
- pulse_stream_update_channel_map (stream, &info->channel_map);
+ /* Many other mixer applications query the Pulse client list and use the
+ * client name here, but we use the name only as an identifier, so let's avoid
+ * this unnecessary overhead and use a custom name.
+ * Also make sure to make the name unique by including the Pulse index. */
+ name = g_strdup_printf ("pulse-stream-client-input-%lu", (gulong) info->index);
- /* Build the flag list */
- if (info->has_volume) {
- flags |= MATE_MIXER_STREAM_HAS_VOLUME;
- pulse_stream_update_volume (stream, &info->volume);
+ pulse_stream_update_name (stream, name);
+ g_free (name);
+
+ prop = pa_proplist_gets (info->proplist, PA_PROP_APPLICATION_NAME);
+ if (prop != NULL)
+ pulse_client_stream_update_app_name (MATE_MIXER_CLIENT_STREAM (stream), prop);
+
+ prop = pa_proplist_gets (info->proplist, PA_PROP_APPLICATION_ID);
+ if (prop != NULL)
+ pulse_client_stream_update_app_id (MATE_MIXER_CLIENT_STREAM (stream), prop);
+
+ prop = pa_proplist_gets (info->proplist, PA_PROP_APPLICATION_VERSION);
+ if (prop != NULL)
+ pulse_client_stream_update_app_version (MATE_MIXER_CLIENT_STREAM (stream), prop);
+
+ prop = pa_proplist_gets (info->proplist, PA_PROP_APPLICATION_ICON_NAME);
+ if (prop != NULL)
+ pulse_client_stream_update_app_icon (MATE_MIXER_CLIENT_STREAM (stream), prop);
+
+ prop = pa_proplist_gets (info->proplist, PA_PROP_MEDIA_ROLE);
+
+ if (prop != NULL && !strcmp (prop, "event")) {
+ /* The event description seems to provide much better readable
+ * description for event streams */
+ prop = pa_proplist_gets (info->proplist, PA_PROP_EVENT_DESCRIPTION);
+
+ if (G_LIKELY (prop != NULL))
+ description = prop;
+
+ flags |= MATE_MIXER_STREAM_EVENT;
}
- if (info->volume_writable)
- flags |= MATE_MIXER_STREAM_CAN_SET_VOLUME;
+ if (description == NULL)
+ description = info->name;
+
+ pulse_stream_update_description (stream, description);
if (info->client != PA_INVALID_INDEX)
flags |= MATE_MIXER_STREAM_APPLICATION;
@@ -107,7 +153,27 @@ pulse_source_output_update (PulseStream *stream, const pa_source_output_info *in
if (pa_channel_map_can_fade (&info->channel_map))
flags |= MATE_MIXER_STREAM_CAN_FADE;
+#if PA_CHECK_VERSION(1, 0, 0)
+ if (info->has_volume) {
+ flags |= MATE_MIXER_STREAM_HAS_VOLUME;
+ if (info->volume_writable)
+ flags |= MATE_MIXER_STREAM_CAN_SET_VOLUME;
+ }
+ flags |= MATE_MIXER_STREAM_HAS_MUTE;
+
pulse_stream_update_flags (stream, flags);
+ pulse_stream_update_mute (stream, info->mute ? TRUE : FALSE);
+
+ if (info->has_volume)
+ pulse_stream_update_volume (stream, &info->volume, &info->channel_map);
+ else
+ pulse_stream_update_volume (stream, NULL, &info->channel_map);
+#else
+ pulse_stream_update_flags (stream, flags);
+ pulse_stream_update_volume (stream, NULL, &info->channel_map);
+#endif
+
+ // XXX needs to fix monitor if parent changes
g_object_thaw_notify (G_OBJECT (stream));
return TRUE;
@@ -116,28 +182,80 @@ pulse_source_output_update (PulseStream *stream, const pa_source_output_info *in
static gboolean
source_output_set_mute (MateMixerStream *stream, gboolean mute)
{
- PulseStream *ps;
+ PulseStream *pulse;
g_return_val_if_fail (PULSE_IS_SOURCE_OUTPUT (stream), FALSE);
- ps = PULSE_STREAM (stream);
+ pulse = PULSE_STREAM (stream);
- return pulse_connection_set_source_output_mute (pulse_stream_get_connection (ps),
- pulse_stream_get_index (ps),
+ return pulse_connection_set_source_output_mute (pulse_stream_get_connection (pulse),
+ pulse_stream_get_index (pulse),
mute);
}
static gboolean
source_output_set_volume (MateMixerStream *stream, pa_cvolume *volume)
{
- PulseStream *ps;
+ PulseStream *pulse;
g_return_val_if_fail (PULSE_IS_SOURCE_OUTPUT (stream), FALSE);
g_return_val_if_fail (volume != NULL, FALSE);
- ps = PULSE_STREAM (stream);
+ pulse = PULSE_STREAM (stream);
- return pulse_connection_set_source_output_volume (pulse_stream_get_connection (ps),
- pulse_stream_get_index (ps),
+ return pulse_connection_set_source_output_volume (pulse_stream_get_connection (pulse),
+ pulse_stream_get_index (pulse),
volume);
}
+
+static gboolean
+source_output_set_parent (MateMixerClientStream *stream, MateMixerStream *parent)
+{
+ PulseStream *pulse;
+
+ g_return_val_if_fail (PULSE_IS_SOURCE_OUTPUT (stream), FALSE);
+
+ if (G_UNLIKELY (!PULSE_IS_SOURCE (parent))) {
+ g_warning ("Could not change stream parent to %s: not a parent input stream",
+ mate_mixer_stream_get_name (parent));
+ return FALSE;
+ }
+
+ pulse = PULSE_STREAM (stream);
+
+ return pulse_connection_move_sink_input (pulse_stream_get_connection (pulse),
+ pulse_stream_get_index (pulse),
+ pulse_stream_get_index (PULSE_STREAM (parent)));
+}
+
+static gboolean
+source_output_remove (MateMixerClientStream *stream)
+{
+ PulseStream *pulse;
+
+ g_return_val_if_fail (PULSE_IS_SOURCE_OUTPUT (stream), FALSE);
+
+ pulse = PULSE_STREAM (stream);
+
+ return pulse_connection_kill_source_output (pulse_stream_get_connection (pulse),
+ pulse_stream_get_index (pulse));
+}
+
+static PulseMonitor *
+source_output_create_monitor (MateMixerStream *stream)
+{
+ MateMixerStream *parent;
+
+ g_return_val_if_fail (PULSE_IS_SOURCE_OUTPUT (stream), NULL);
+
+ parent = mate_mixer_client_stream_get_parent (MATE_MIXER_CLIENT_STREAM (stream));
+ if (G_UNLIKELY (parent == NULL)) {
+ g_debug ("Not creating monitor for client stream %s as it is not available",
+ mate_mixer_stream_get_name (stream));
+ return NULL;
+ }
+
+ return pulse_connection_create_monitor (pulse_stream_get_connection (PULSE_STREAM (stream)),
+ pulse_stream_get_index (PULSE_STREAM (parent)),
+ PA_INVALID_INDEX);
+}