diff options
Diffstat (limited to 'backends/pulse/pulse-source-output.c')
-rw-r--r-- | backends/pulse/pulse-source-output.c | 198 |
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); +} |