diff options
Diffstat (limited to 'backends/pulse/pulse-ext-stream.c')
-rw-r--r-- | backends/pulse/pulse-ext-stream.c | 374 |
1 files changed, 224 insertions, 150 deletions
diff --git a/backends/pulse/pulse-ext-stream.c b/backends/pulse/pulse-ext-stream.c index b00e967..3e7490a 100644 --- a/backends/pulse/pulse-ext-stream.c +++ b/backends/pulse/pulse-ext-stream.c @@ -19,252 +19,326 @@ #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/ext-stream-restore.h> #include "pulse-connection.h" -#include "pulse-client-stream.h" #include "pulse-ext-stream.h" #include "pulse-helpers.h" #include "pulse-stream.h" +#include "pulse-stream-control.h" -static void pulse_ext_stream_class_init (PulseExtStreamClass *klass); -static void pulse_ext_stream_init (PulseExtStream *ext); +struct _PulseExtStreamPrivate +{ + MateMixerAppInfo *app_info; + MateMixerDirection direction; +}; -G_DEFINE_TYPE (PulseExtStream, pulse_ext_stream, PULSE_TYPE_CLIENT_STREAM); +enum { + PROP_0, + PROP_DIRECTION +}; -static void pulse_ext_stream_reload (PulseStream *pstream); +static void mate_mixer_stored_control_interface_init (MateMixerStoredControlInterface *iface); -static gboolean pulse_ext_stream_set_mute (PulseStream *pstream, - gboolean mute); -static gboolean pulse_ext_stream_set_volume (PulseStream *pstream, - pa_cvolume *cvolume); -static gboolean pulse_ext_stream_set_parent (PulseClientStream *pclient, - PulseStream *parent); -static gboolean pulse_ext_stream_remove (PulseClientStream *pclient); +static void pulse_ext_stream_class_init (PulseExtStreamClass *klass); -static void -pulse_ext_stream_class_init (PulseExtStreamClass *klass) -{ - PulseStreamClass *stream_class; - PulseClientStreamClass *client_class; +static void pulse_ext_stream_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec); +static void pulse_ext_stream_set_property (GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec); - stream_class = PULSE_STREAM_CLASS (klass); +static void pulse_ext_stream_init (PulseExtStream *ext); - stream_class->reload = pulse_ext_stream_reload; - stream_class->set_mute = pulse_ext_stream_set_mute; - stream_class->set_volume = pulse_ext_stream_set_volume; +G_DEFINE_TYPE_WITH_CODE (PulseExtStream, pulse_ext_stream, PULSE_TYPE_STREAM_CONTROL, + G_IMPLEMENT_INTERFACE (MATE_MIXER_TYPE_STORED_CONTROL, + mate_mixer_stored_control_interface_init)) - client_class = PULSE_CLIENT_STREAM_CLASS (klass); +static MateMixerDirection pulse_ext_stream_get_direction (MateMixerStoredControl *mmsc); - client_class->set_parent = pulse_ext_stream_set_parent; - client_class->remove = pulse_ext_stream_remove; -} +static MateMixerAppInfo * pulse_ext_stream_get_app_info (MateMixerStreamControl *mmsc); + +static gboolean pulse_ext_stream_set_stream (MateMixerStreamControl *mmsc, + MateMixerStream *mms); + +static gboolean pulse_ext_stream_set_mute (PulseStreamControl *control, + gboolean mute); +static gboolean pulse_ext_stream_set_volume (PulseStreamControl *control, + pa_cvolume *cvolume); + +static void fill_ext_stream_restore_info (PulseStreamControl *control, + pa_ext_stream_restore_info *info); static void -pulse_ext_stream_init (PulseExtStream *ext) +mate_mixer_stored_control_interface_init (MateMixerStoredControlInterface *iface) { + iface->get_direction = pulse_ext_stream_get_direction; } -PulseStream * -pulse_ext_stream_new (PulseConnection *connection, - const pa_ext_stream_restore_info *info, - PulseStream *parent) +static void +pulse_ext_stream_class_init (PulseExtStreamClass *klass) { - PulseStream *ext; + GObjectClass *object_class; + MateMixerStreamControlClass *control_class; + PulseStreamControlClass *pulse_class; - g_return_val_if_fail (PULSE_IS_CONNECTION (connection), NULL); - g_return_val_if_fail (info != NULL, NULL); + object_class = G_OBJECT_CLASS (klass); + object_class->get_property = pulse_ext_stream_get_property; + object_class->set_property = pulse_ext_stream_set_property; - ext = g_object_new (PULSE_TYPE_EXT_STREAM, - "connection", connection, - NULL); + control_class = MATE_MIXER_STREAM_CONTROL_CLASS (klass); + control_class->get_app_info = pulse_ext_stream_get_app_info; + control_class->set_stream = pulse_ext_stream_set_stream; - /* Consider the stream name as unchanging parameter */ - pulse_stream_update_name (ext, info->name); + pulse_class = PULSE_STREAM_CONTROL_CLASS (klass); + pulse_class->set_mute = pulse_ext_stream_set_mute; + pulse_class->set_volume = pulse_ext_stream_set_volume; - /* Other data may change at any time, so let's make a use of our update function */ - pulse_ext_stream_update (ext, info, parent); + g_object_class_override_property (object_class, PROP_DIRECTION, "direction"); - return ext; + g_type_class_add_private (object_class, sizeof (PulseExtStreamPrivate)); } -gboolean -pulse_ext_stream_update (PulseStream *pstream, - const pa_ext_stream_restore_info *info, - PulseStream *parent) +static void +pulse_ext_stream_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec) { - MateMixerClientStreamRole role = MATE_MIXER_CLIENT_STREAM_ROLE_NONE; - MateMixerStreamFlags flags = MATE_MIXER_STREAM_CLIENT | - MATE_MIXER_STREAM_HAS_VOLUME | - MATE_MIXER_STREAM_HAS_MUTE | - MATE_MIXER_STREAM_CAN_SET_VOLUME; - MateMixerClientStreamFlags client_flags = - MATE_MIXER_CLIENT_STREAM_CACHED; + PulseExtStream *ext; - PulseClientStream *pclient; - gchar *suffix; + ext = PULSE_EXT_STREAM (object); - g_return_val_if_fail (PULSE_IS_EXT_STREAM (pstream), FALSE); - g_return_val_if_fail (info != NULL, FALSE); + switch (param_id) { + case PROP_DIRECTION: + g_value_set_enum (value, ext->priv->direction); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} - pclient = PULSE_CLIENT_STREAM (pstream); +static void +pulse_ext_stream_set_property (GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec) +{ + PulseExtStream *ext; - suffix = strchr (info->name, ':'); - if (suffix != NULL) - suffix++; + ext = PULSE_EXT_STREAM (object); - /* Let all the information update before emitting notify signals */ - g_object_freeze_notify (G_OBJECT (pstream)); + switch (param_id) { + case PROP_DIRECTION: + ext->priv->direction = g_value_get_enum (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} + +static void +pulse_ext_stream_init (PulseExtStream *ext) +{ + ext->priv = G_TYPE_INSTANCE_GET_PRIVATE (ext, + PULSE_TYPE_EXT_STREAM, + PulseExtStreamPrivate); +} + +PulseExtStream * +pulse_ext_stream_new (PulseConnection *connection, + const pa_ext_stream_restore_info *info, + PulseStream *parent) +{ + PulseExtStream *ext; + gchar *suffix; + MateMixerDirection direction; + MateMixerStreamControlFlags flags = MATE_MIXER_STREAM_CONTROL_VOLUME_READABLE | + MATE_MIXER_STREAM_CONTROL_VOLUME_WRITABLE | + MATE_MIXER_STREAM_CONTROL_MUTE_READABLE | + MATE_MIXER_STREAM_CONTROL_MUTE_WRITABLE; + MateMixerStreamControlRole role = MATE_MIXER_STREAM_CONTROL_ROLE_UNKNOWN; + MateMixerAppInfo *app_info; + + MateMixerStreamControlMediaRole media_role = MATE_MIXER_STREAM_CONTROL_MEDIA_ROLE_UNKNOWN; + + g_return_val_if_fail (PULSE_IS_CONNECTION (connection), NULL); + g_return_val_if_fail (info != NULL, NULL); if (g_str_has_prefix (info->name, "sink-input")) - flags |= MATE_MIXER_STREAM_OUTPUT; + direction = MATE_MIXER_DIRECTION_OUTPUT; else if (g_str_has_prefix (info->name, "source-output")) - flags |= MATE_MIXER_STREAM_INPUT; + direction = MATE_MIXER_DIRECTION_INPUT; else - g_debug ("Unknown ext-stream %s", info->name); + direction = MATE_MIXER_DIRECTION_UNKNOWN; + + app_info = _mate_mixer_app_info_new (); + + suffix = strchr (info->name, ':'); + if (suffix != NULL) + suffix++; if (strstr (info->name, "-by-media-role:")) { if (G_LIKELY (suffix != NULL)) - role = pulse_convert_media_role_name (suffix); + media_role = pulse_convert_media_role_name (suffix); } else if (strstr (info->name, "-by-application-name:")) { - client_flags |= MATE_MIXER_CLIENT_STREAM_APPLICATION; + role = MATE_MIXER_STREAM_CONTROL_ROLE_APPLICATION; if (G_LIKELY (suffix != NULL)) - pulse_client_stream_update_app_name (pclient, suffix); + _mate_mixer_app_info_set_name (app_info, suffix); } else if (strstr (info->name, "-by-application-id:")) { - client_flags |= MATE_MIXER_CLIENT_STREAM_APPLICATION; + role = MATE_MIXER_STREAM_CONTROL_ROLE_APPLICATION; if (G_LIKELY (suffix != NULL)) - pulse_client_stream_update_app_id (pclient, suffix); + _mate_mixer_app_info_set_id (app_info, suffix); } - /* Flags needed before volume */ - pulse_stream_update_flags (pstream, flags); + ext = g_object_new (PULSE_TYPE_EXT_STREAM, + "flags", flags, + "role", role, + "media-role", media_role, + "name", info->name, + "connection", connection, + "direction", direction, + "stream", parent, + NULL); - pulse_stream_update_channel_map (pstream, &info->channel_map); - pulse_stream_update_volume (pstream, &info->volume, 0); + if (role == MATE_MIXER_STREAM_CONTROL_ROLE_APPLICATION) + ext->priv->app_info = app_info; + else + _mate_mixer_app_info_free (app_info); - pulse_stream_update_mute (pstream, info->mute ? TRUE : FALSE); + pulse_ext_stream_update (ext, info, parent); + return ext; +} - pulse_client_stream_update_flags (pclient, client_flags); - pulse_client_stream_update_role (pclient, role); +void +pulse_ext_stream_update (PulseExtStream *ext, + const pa_ext_stream_restore_info *info, + PulseStream *parent) +{ + g_return_if_fail (PULSE_IS_EXT_STREAM (ext)); + g_return_if_fail (info != NULL); - if (parent != NULL) - pulse_client_stream_update_parent (pclient, MATE_MIXER_STREAM (parent)); - else - pulse_client_stream_update_parent (pclient, NULL); + /* Let all the information update before emitting notify signals */ + g_object_freeze_notify (G_OBJECT (ext)); + + _mate_mixer_stream_control_set_mute (MATE_MIXER_STREAM_CONTROL (ext), + info->mute ? TRUE : FALSE); - g_object_thaw_notify (G_OBJECT (pstream)); - return TRUE; + pulse_stream_control_set_channel_map (PULSE_STREAM_CONTROL (ext), + &info->channel_map); + + pulse_stream_control_set_cvolume (PULSE_STREAM_CONTROL (ext), + &info->volume, + 0); + + _mate_mixer_stream_control_set_stream (MATE_MIXER_STREAM_CONTROL (ext), + MATE_MIXER_STREAM (parent)); + + g_object_thaw_notify (G_OBJECT (ext)); } -static void -pulse_ext_stream_reload (PulseStream *pstream) +static MateMixerDirection +pulse_ext_stream_get_direction (MateMixerStoredControl *mmsc) { - g_return_if_fail (PULSE_IS_EXT_STREAM (pstream)); + g_return_val_if_fail (PULSE_IS_EXT_STREAM (mmsc), MATE_MIXER_DIRECTION_UNKNOWN); - pulse_connection_load_ext_stream_info (pulse_stream_get_connection (pstream)); + return PULSE_EXT_STREAM (mmsc)->priv->direction; } -static gboolean -pulse_ext_stream_set_mute (PulseStream *pstream, gboolean mute) +static MateMixerAppInfo * +pulse_ext_stream_get_app_info (MateMixerStreamControl *mmsc) { - MateMixerStream *parent; - const pa_channel_map *map; - const pa_cvolume *cvolume; - pa_ext_stream_restore_info info; + g_return_val_if_fail (PULSE_IS_EXT_STREAM (mmsc), NULL); - g_return_val_if_fail (PULSE_IS_EXT_STREAM (pstream), FALSE); + return PULSE_EXT_STREAM (mmsc)->priv->app_info; +} - info.name = mate_mixer_stream_get_name (MATE_MIXER_STREAM (pstream)); - info.mute = mute; +static gboolean +pulse_ext_stream_set_stream (MateMixerStreamControl *mmsc, MateMixerStream *mms) +{ + pa_ext_stream_restore_info info; - map = pulse_stream_get_channel_map (pstream); - info.channel_map = *map; + g_return_val_if_fail (PULSE_IS_EXT_STREAM (mmsc), FALSE); + g_return_val_if_fail (mms == NULL || PULSE_IS_STREAM (mms), FALSE); - cvolume = pulse_stream_get_cvolume (pstream); - info.volume = *cvolume; + fill_ext_stream_restore_info (PULSE_STREAM_CONTROL (mms), &info); - parent = mate_mixer_client_stream_get_parent (MATE_MIXER_CLIENT_STREAM (pstream)); - if (parent != NULL) - info.device = mate_mixer_stream_get_name (parent); + if (mms != NULL) + info.device = mate_mixer_stream_get_name (mms); else info.device = NULL; - return pulse_connection_write_ext_stream (pulse_stream_get_connection (pstream), &info); + return pulse_connection_write_ext_stream (pulse_stream_control_get_connection (PULSE_STREAM_CONTROL (mmsc)), + &info); } static gboolean -pulse_ext_stream_set_volume (PulseStream *pstream, pa_cvolume *cvolume) +pulse_ext_stream_set_mute (PulseStreamControl *control, gboolean mute) { - MateMixerStream *parent; - const pa_channel_map *map; pa_ext_stream_restore_info info; - g_return_val_if_fail (PULSE_IS_EXT_STREAM (pstream), FALSE); - g_return_val_if_fail (cvolume != NULL, FALSE); - - info.name = mate_mixer_stream_get_name (MATE_MIXER_STREAM (pstream)); - info.mute = mate_mixer_stream_get_mute (MATE_MIXER_STREAM (pstream)); + g_return_val_if_fail (PULSE_IS_EXT_STREAM (control), FALSE); - map = pulse_stream_get_channel_map (pstream); - info.channel_map = *map; - - parent = mate_mixer_client_stream_get_parent (MATE_MIXER_CLIENT_STREAM (pstream)); - if (parent != NULL) - info.device = mate_mixer_stream_get_name (parent); - else - info.device = NULL; + fill_ext_stream_restore_info (control, &info); - info.volume = *cvolume; + info.mute = mute; - return pulse_connection_write_ext_stream (pulse_stream_get_connection (pstream), &info); + return pulse_connection_write_ext_stream (pulse_stream_control_get_connection (control), + &info); } static gboolean -pulse_ext_stream_set_parent (PulseClientStream *pclient, PulseStream *parent) +pulse_ext_stream_set_volume (PulseStreamControl *control, pa_cvolume *cvolume) { - PulseStream *pstream; - const pa_channel_map *map; - const pa_cvolume *cvolume; pa_ext_stream_restore_info info; - g_return_val_if_fail (PULSE_IS_EXT_STREAM (pclient), FALSE); - g_return_val_if_fail (PULSE_IS_STREAM (parent), FALSE); - - pstream = PULSE_STREAM (pclient); - - info.name = mate_mixer_stream_get_name (MATE_MIXER_STREAM (pstream)); - info.mute = mate_mixer_stream_get_mute (MATE_MIXER_STREAM (pstream)); + g_return_val_if_fail (PULSE_IS_EXT_STREAM (control), FALSE); + g_return_val_if_fail (cvolume != NULL, FALSE); - map = pulse_stream_get_channel_map (pstream); - info.channel_map = *map; + fill_ext_stream_restore_info (control, &info); - cvolume = pulse_stream_get_cvolume (pstream); info.volume = *cvolume; - info.device = mate_mixer_stream_get_name (MATE_MIXER_STREAM (parent)); - - return pulse_connection_write_ext_stream (pulse_stream_get_connection (pstream), &info); + return pulse_connection_write_ext_stream (pulse_stream_control_get_connection (control), + &info); } -static gboolean -pulse_ext_stream_remove (PulseClientStream *pclient) +static void +fill_ext_stream_restore_info (PulseStreamControl *control, + pa_ext_stream_restore_info *info) { - PulseStream *pstream; - const gchar *name; + MateMixerStream *stream; + MateMixerStreamControl *mmsc; + const pa_channel_map *map; + const pa_cvolume *cvolume; + + mmsc = MATE_MIXER_STREAM_CONTROL (control); - g_return_val_if_fail (PULSE_IS_EXT_STREAM (pclient), FALSE); + info->name = mate_mixer_stream_control_get_name (mmsc); + info->mute = mate_mixer_stream_control_get_mute (mmsc); - pstream = PULSE_STREAM (pclient); - name = mate_mixer_stream_get_name (MATE_MIXER_STREAM (pstream)); + map = pulse_stream_control_get_channel_map (control); + info->channel_map = *map; - return pulse_connection_delete_ext_stream (pulse_stream_get_connection (pstream), name); + cvolume = pulse_stream_control_get_cvolume (control); + info->volume = *cvolume; + + stream = mate_mixer_stream_control_get_stream (mmsc); + if (stream != NULL) + info->device = mate_mixer_stream_get_name (stream); + else + info->device = NULL; } |