diff options
Diffstat (limited to 'backends/pulse/pulse-sink-input.c')
-rw-r--r-- | backends/pulse/pulse-sink-input.c | 321 |
1 files changed, 123 insertions, 198 deletions
diff --git a/backends/pulse/pulse-sink-input.c b/backends/pulse/pulse-sink-input.c index 1d5f9c2..eab85b8 100644 --- a/backends/pulse/pulse-sink-input.c +++ b/backends/pulse/pulse-sink-input.c @@ -15,57 +15,41 @@ * License along with this library; if not, see <http://www.gnu.org/licenses/>. */ -#include <string.h> #include <glib.h> #include <glib-object.h> - -#include <libmatemixer/matemixer-client-stream.h> -#include <libmatemixer/matemixer-enums.h> -#include <libmatemixer/matemixer-stream.h> +#include <libmatemixer/matemixer.h> +#include <libmatemixer/matemixer-private.h> #include <pulse/pulseaudio.h> #include "pulse-connection.h" -#include "pulse-client-stream.h" #include "pulse-helpers.h" #include "pulse-monitor.h" #include "pulse-sink.h" #include "pulse-sink-input.h" #include "pulse-stream.h" +#include "pulse-stream-control.h" static void pulse_sink_input_class_init (PulseSinkInputClass *klass); static void pulse_sink_input_init (PulseSinkInput *input); -G_DEFINE_TYPE (PulseSinkInput, pulse_sink_input, PULSE_TYPE_CLIENT_STREAM); - -static void pulse_sink_input_reload (PulseStream *pstream); +G_DEFINE_TYPE (PulseSinkInput, pulse_sink_input, PULSE_TYPE_STREAM_CONTROL); -static gboolean pulse_sink_input_set_mute (PulseStream *pstream, - gboolean mute); -static gboolean pulse_sink_input_set_volume (PulseStream *pstream, - pa_cvolume *cvolume); -static gboolean pulse_sink_input_set_parent (PulseClientStream *pclient, - PulseStream *parent); -static gboolean pulse_sink_input_remove (PulseClientStream *pclient); -static PulseMonitor *pulse_sink_input_create_monitor (PulseStream *pstream); +static gboolean pulse_sink_input_set_mute (PulseStreamControl *psc, + gboolean mute); +static gboolean pulse_sink_input_set_volume (PulseStreamControl *psc, + pa_cvolume *cvolume); +static PulseMonitor *pulse_sink_input_create_monitor (PulseStreamControl *psc); static void pulse_sink_input_class_init (PulseSinkInputClass *klass) { - PulseStreamClass *stream_class; - PulseClientStreamClass *client_class; - - stream_class = PULSE_STREAM_CLASS (klass); + PulseStreamControlClass *control_class; - stream_class->reload = pulse_sink_input_reload; - stream_class->set_mute = pulse_sink_input_set_mute; - stream_class->set_volume = pulse_sink_input_set_volume; - stream_class->create_monitor = pulse_sink_input_create_monitor; - - client_class = PULSE_CLIENT_STREAM_CLASS (klass); - - client_class->set_parent = pulse_sink_input_set_parent; - client_class->remove = pulse_sink_input_remove; + control_class = PULSE_STREAM_CONTROL_CLASS (klass); + control_class->set_mute = pulse_sink_input_set_mute; + control_class->set_volume = pulse_sink_input_set_volume; + control_class->create_monitor = pulse_sink_input_create_monitor; } static void @@ -73,230 +57,171 @@ pulse_sink_input_init (PulseSinkInput *input) { } -PulseStream * -pulse_sink_input_new (PulseConnection *connection, - const pa_sink_input_info *info, - PulseStream *parent) +PulseSinkInput * +pulse_sink_input_new (PulseSink *sink, const pa_sink_input_info *info) { - PulseSinkInput *input; + PulseSinkInput *input; + gchar *name; + const gchar *prop; + const gchar *label = NULL; + MateMixerAppInfo *app_info = NULL; - g_return_val_if_fail (PULSE_IS_CONNECTION (connection), NULL); - g_return_val_if_fail (info != NULL, NULL); + MateMixerStreamControlFlags flags = MATE_MIXER_STREAM_CONTROL_MUTE_READABLE | + MATE_MIXER_STREAM_CONTROL_MUTE_WRITABLE | + MATE_MIXER_STREAM_CONTROL_HAS_MONITOR; + MateMixerStreamControlRole role = MATE_MIXER_STREAM_CONTROL_ROLE_UNKNOWN; - /* Consider the sink input index as unchanging parameter */ - input = g_object_new (PULSE_TYPE_SINK_INPUT, - "connection", connection, - "index", info->index, - NULL); + MateMixerStreamControlMediaRole media_role = MATE_MIXER_STREAM_CONTROL_MEDIA_ROLE_UNKNOWN; - /* Other data may change at any time, so let's make a use of our update function */ - pulse_sink_input_update (PULSE_STREAM (input), info, parent); - - return PULSE_STREAM (input); -} - -gboolean -pulse_sink_input_update (PulseStream *pstream, - const pa_sink_input_info *info, - PulseStream *parent) -{ - MateMixerStreamFlags flags = MATE_MIXER_STREAM_OUTPUT | - MATE_MIXER_STREAM_CLIENT | - MATE_MIXER_STREAM_HAS_MUTE | - MATE_MIXER_STREAM_HAS_MONITOR; - PulseClientStream *pclient; - const gchar *prop; - const gchar *description = NULL; - gchar *name; - - g_return_val_if_fail (PULSE_IS_SINK_INPUT (pstream), FALSE); - g_return_val_if_fail (info != NULL, FALSE); - - pclient = PULSE_CLIENT_STREAM (pstream); - - /* Let all the information update before emitting notify signals */ - g_object_freeze_notify (G_OBJECT (pstream)); + g_return_val_if_fail (PULSE_IS_SINK (sink), NULL); + g_return_val_if_fail (info != NULL, NULL); /* Many 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 PulseAudio index. */ - name = g_strdup_printf ("pulse-stream-client-output-%lu", (gulong) info->index); - - pulse_stream_update_name (pstream, name); - g_free (name); - - prop = pa_proplist_gets (info->proplist, PA_PROP_MEDIA_ROLE); - if (prop != NULL) { - MateMixerClientStreamRole role = pulse_convert_media_role_name (prop); - - if (role == MATE_MIXER_CLIENT_STREAM_ROLE_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; - } - pulse_client_stream_update_role (pclient, role); - } else - pulse_client_stream_update_role (pclient, MATE_MIXER_CLIENT_STREAM_ROLE_NONE); - - if (description == NULL) - description = info->name; - - pulse_stream_update_description (pstream, description); - pulse_stream_update_mute (pstream, info->mute ? TRUE : FALSE); - - if (info->client != PA_INVALID_INDEX) - pulse_client_stream_update_flags (pclient, MATE_MIXER_CLIENT_STREAM_APPLICATION); - else - pulse_client_stream_update_flags (pclient, MATE_MIXER_CLIENT_STREAM_NO_FLAGS); - - if (G_LIKELY (parent != NULL)) { - if (pulse_sink_get_monitor_index (parent) != PA_INVALID_INDEX) - flags |= MATE_MIXER_STREAM_HAS_MONITOR; - - pulse_client_stream_update_parent (pclient, MATE_MIXER_STREAM (parent)); - } else - pulse_client_stream_update_parent (pclient, NULL); + name = g_strdup_printf ("pulse-output-control-%lu", (gulong) info->index); #if PA_CHECK_VERSION(1, 0, 0) if (info->has_volume) { flags |= - MATE_MIXER_STREAM_HAS_VOLUME | - MATE_MIXER_STREAM_HAS_DECIBEL_VOLUME; + MATE_MIXER_STREAM_CONTROL_VOLUME_READABLE | + MATE_MIXER_STREAM_CONTROL_HAS_DECIBEL; if (info->volume_writable) - flags |= MATE_MIXER_STREAM_CAN_SET_VOLUME; + flags |= MATE_MIXER_STREAM_CONTROL_VOLUME_WRITABLE; } - - /* Flags needed before volume */ - pulse_stream_update_flags (pstream, flags); - pulse_stream_update_channel_map (pstream, &info->channel_map); - - if (info->has_volume) - pulse_stream_update_volume (pstream, &info->volume, 0); - else - pulse_stream_update_volume (pstream, NULL, 0); #else /* Pre-1.0 PulseAudio does not include the has_volume and volume_writable * fields, but does include the volume info, so let's give it a try */ flags |= - MATE_MIXER_STREAM_HAS_VOLUME | - MATE_MIXER_STREAM_HAS_DECIBEL_VOLUME | - MATE_MIXER_STREAM_CAN_SET_VOLUME; + MATE_MIXER_STREAM_CONTROL_VOLUME_READABLE | + MATE_MIXER_STREAM_CONTROL_VOLUME_WRITABLE | + MATE_MIXER_STREAM_CONTROL_HAS_DECIBEL; +#endif - /* Flags needed before volume */ - pulse_stream_update_flags (pstream, flags); - pulse_stream_update_channel_map (pstream, &info->channel_map); + if (info->client != PA_INVALID_INDEX) { + app_info = _mate_mixer_app_info_new (); - pulse_stream_update_volume (pstream, &info->volume, 0); -#endif + role = MATE_MIXER_STREAM_CONTROL_ROLE_APPLICATION; - prop = pa_proplist_gets (info->proplist, PA_PROP_APPLICATION_NAME); - if (prop != NULL) - pulse_client_stream_update_app_name (pclient, prop); + prop = pa_proplist_gets (info->proplist, PA_PROP_APPLICATION_NAME); + if (prop != NULL) + _mate_mixer_app_info_set_name (app_info, prop); - prop = pa_proplist_gets (info->proplist, PA_PROP_APPLICATION_ID); - if (prop != NULL) - pulse_client_stream_update_app_id (pclient, prop); + prop = pa_proplist_gets (info->proplist, PA_PROP_APPLICATION_ID); + if (prop != NULL) + _mate_mixer_app_info_set_id (app_info, prop); - prop = pa_proplist_gets (info->proplist, PA_PROP_APPLICATION_VERSION); - if (prop != NULL) - pulse_client_stream_update_app_version (pclient, prop); + prop = pa_proplist_gets (info->proplist, PA_PROP_APPLICATION_VERSION); + if (prop != NULL) + _mate_mixer_app_info_set_version (app_info, prop); - prop = pa_proplist_gets (info->proplist, PA_PROP_APPLICATION_ICON_NAME); - if (prop != NULL) - pulse_client_stream_update_app_icon (pclient, prop); + prop = pa_proplist_gets (info->proplist, PA_PROP_APPLICATION_ICON_NAME); + if (prop != NULL) + _mate_mixer_app_info_set_icon (app_info, prop); + } - // XXX needs to fix monitor if parent changes + prop = pa_proplist_gets (info->proplist, PA_PROP_MEDIA_ROLE); + if (prop != NULL) { + media_role = pulse_convert_media_role_name (prop); - g_object_thaw_notify (G_OBJECT (pstream)); - return TRUE; -} + if (media_role == MATE_MIXER_STREAM_CONTROL_MEDIA_ROLE_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 (prop != NULL) + label = prop; + } + } -static void -pulse_sink_input_reload (PulseStream *pstream) -{ - g_return_if_fail (PULSE_IS_SINK_INPUT (pstream)); + if (label == NULL) + label = info->name; - pulse_connection_load_sink_input_info (pulse_stream_get_connection (pstream), - pulse_stream_get_index (pstream)); -} + input = g_object_new (PULSE_TYPE_SINK_INPUT, + "name", name, + "label", label, + "flags", flags, + "role", role, + "media-role", media_role, + "index", info->index, + "stream", sink, + NULL); + g_free (name); -static gboolean -pulse_sink_input_set_mute (PulseStream *pstream, gboolean mute) -{ - g_return_val_if_fail (PULSE_IS_SINK_INPUT (pstream), FALSE); + if (app_info != NULL) + pulse_stream_control_set_app_info (PULSE_STREAM_CONTROL (input), app_info); - return pulse_connection_set_sink_input_mute (pulse_stream_get_connection (pstream), - pulse_stream_get_index (pstream), - mute); + pulse_sink_input_update (input, info); + return input; } -static gboolean -pulse_sink_input_set_volume (PulseStream *pstream, pa_cvolume *cvolume) +void +pulse_sink_input_update (PulseSinkInput *input, const pa_sink_input_info *info) { - g_return_val_if_fail (PULSE_IS_SINK_INPUT (pstream), FALSE); - g_return_val_if_fail (cvolume != NULL, FALSE); + g_return_if_fail (PULSE_IS_SINK_INPUT (input)); + g_return_if_fail (info != NULL); - return pulse_connection_set_sink_input_volume (pulse_stream_get_connection (pstream), - pulse_stream_get_index (pstream), - cvolume); -} + /* Let all the information update before emitting notify signals */ + g_object_freeze_notify (G_OBJECT (input)); -static gboolean -pulse_sink_input_set_parent (PulseClientStream *pclient, PulseStream *parent) -{ - PulseStream *pstream; + _mate_mixer_stream_control_set_mute (MATE_MIXER_STREAM_CONTROL (input), + info->mute ? TRUE : FALSE); - g_return_val_if_fail (PULSE_IS_SINK_INPUT (pclient), FALSE); +#if PA_CHECK_VERSION(1, 0, 0) + pulse_stream_control_set_channel_map (PULSE_STREAM_CONTROL (input), &info->channel_map); - pstream = PULSE_STREAM (pclient); + if (info->has_volume) + pulse_stream_control_set_cvolume (PULSE_STREAM_CONTROL (input), &info->volume, 0); + else + pulse_stream_control_set_cvolume (PULSE_STREAM_CONTROL (input), NULL, 0); +#else + pulse_stream_control_set_channel_map (PULSE_STREAM_CONTROL (input), &info->channel_map); + pulse_stream_control_set_volume (PULSE_STREAM_CONTROL (input), &info->volume, 0); +#endif - return pulse_connection_move_sink_input (pulse_stream_get_connection (pstream), - pulse_stream_get_index (pstream), - pulse_stream_get_index (parent)); + g_object_thaw_notify (G_OBJECT (input)); } static gboolean -pulse_sink_input_remove (PulseClientStream *pclient) +pulse_sink_input_set_mute (PulseStreamControl *psc, gboolean mute) { - PulseStream *pstream; + g_return_val_if_fail (PULSE_IS_SINK_INPUT (psc), FALSE); - g_return_val_if_fail (PULSE_IS_SINK_INPUT (pclient), FALSE); + return pulse_connection_set_sink_input_mute (PULSE_STREAM_CONTROL_GET_CONNECTION (psc), + pulse_stream_control_get_index (psc), + mute); +} - pstream = PULSE_STREAM (pclient); +static gboolean +pulse_sink_input_set_volume (PulseStreamControl *psc, pa_cvolume *cvolume) +{ + g_return_val_if_fail (PULSE_IS_SINK_INPUT (psc), FALSE); + g_return_val_if_fail (cvolume != NULL, FALSE); - return pulse_connection_kill_sink_input (pulse_stream_get_connection (pstream), - pulse_stream_get_index (pstream)); + return pulse_connection_set_sink_input_volume (PULSE_STREAM_CONTROL_GET_CONNECTION (psc), + pulse_stream_control_get_index (psc), + cvolume); } static PulseMonitor * -pulse_sink_input_create_monitor (PulseStream *pstream) +pulse_sink_input_create_monitor (PulseStreamControl *psc) { - MateMixerStream *parent; - guint32 index; - - g_return_val_if_fail (PULSE_IS_SINK_INPUT (pstream), NULL); + PulseSink *sink; + guint32 index; - parent = mate_mixer_client_stream_get_parent (MATE_MIXER_CLIENT_STREAM (pstream)); - if (G_UNLIKELY (parent == NULL)) { - g_debug ("Not creating monitor for client stream %s as it is not available", - mate_mixer_stream_get_name (MATE_MIXER_STREAM (pstream))); - return NULL; - } + g_return_val_if_fail (PULSE_IS_SINK_INPUT (psc), NULL); - index = pulse_sink_get_monitor_index (PULSE_STREAM (parent)); + sink = PULSE_SINK (mate_mixer_stream_control_get_stream (MATE_MIXER_STREAM_CONTROL (psc))); - if (G_UNLIKELY (index == PA_INVALID_INDEX)) { - g_debug ("Not creating monitor for client stream %s as it is not available", - mate_mixer_stream_get_name (MATE_MIXER_STREAM (pstream))); + index = pulse_sink_get_index_monitor (sink); + if G_UNLIKELY (index == PA_INVALID_INDEX) { + g_debug ("Monitor of stream control %s is not available", + mate_mixer_stream_control_get_name (MATE_MIXER_STREAM_CONTROL (psc))); return NULL; } - return pulse_connection_create_monitor (pulse_stream_get_connection (pstream), + return pulse_connection_create_monitor (PULSE_STREAM_CONTROL_GET_CONNECTION (psc), index, - pulse_stream_get_index (pstream)); + pulse_stream_control_get_index (psc)); } |