diff options
Diffstat (limited to 'backends/pulse/pulse-sink.c')
-rw-r--r-- | backends/pulse/pulse-sink.c | 288 |
1 files changed, 157 insertions, 131 deletions
diff --git a/backends/pulse/pulse-sink.c b/backends/pulse/pulse-sink.c index 27d1466..0f828b1 100644 --- a/backends/pulse/pulse-sink.c +++ b/backends/pulse/pulse-sink.c @@ -18,6 +18,8 @@ #include <glib.h> #include <glib-object.h> +#include <libmatemixer/matemixer-port.h> +#include <libmatemixer/matemixer-port-private.h> #include <libmatemixer/matemixer-stream.h> #include <pulse/pulseaudio.h> @@ -38,15 +40,23 @@ static void pulse_sink_init (PulseSink *sink); G_DEFINE_TYPE (PulseSink, pulse_sink, PULSE_TYPE_STREAM); -static gboolean sink_set_mute (MateMixerStream *stream, - gboolean mute); -static gboolean sink_set_volume (MateMixerStream *stream, - pa_cvolume *volume); -static gboolean sink_set_active_port (MateMixerStream *stream, - const gchar *port); -static gboolean sink_suspend (MateMixerStream *stream); -static gboolean sink_resume (MateMixerStream *stream); -static PulseMonitor *sink_create_monitor (MateMixerStream *stream); +static void pulse_sink_reload (PulseStream *pstream); + +static gboolean pulse_sink_set_mute (PulseStream *pstream, + gboolean mute); +static gboolean pulse_sink_set_volume (PulseStream *pstream, + pa_cvolume *cvolume); +static gboolean pulse_sink_set_active_port (PulseStream *pstream, + MateMixerPort *port); + +static gboolean pulse_sink_suspend (PulseStream *pstream); +static gboolean pulse_sink_resume (PulseStream *pstream); + +static PulseMonitor *pulse_sink_create_monitor (PulseStream *pstream); + +static void update_ports (PulseStream *pstream, + pa_sink_port_info **ports, + pa_sink_port_info *active); static void pulse_sink_class_init (PulseSinkClass *klass) @@ -55,12 +65,13 @@ pulse_sink_class_init (PulseSinkClass *klass) stream_class = PULSE_STREAM_CLASS (klass); - stream_class->set_mute = sink_set_mute; - stream_class->set_volume = sink_set_volume; - stream_class->set_active_port = sink_set_active_port; - stream_class->suspend = sink_suspend; - stream_class->resume = sink_resume; - stream_class->create_monitor = sink_create_monitor; + stream_class->reload = pulse_sink_reload; + stream_class->set_mute = pulse_sink_set_mute; + stream_class->set_volume = pulse_sink_set_volume; + stream_class->set_active_port = pulse_sink_set_active_port; + stream_class->suspend = pulse_sink_suspend; + stream_class->resume = pulse_sink_resume; + stream_class->create_monitor = pulse_sink_create_monitor; g_type_class_add_private (klass, sizeof (PulseSinkPrivate)); } @@ -98,71 +109,46 @@ pulse_sink_new (PulseConnection *connection, } guint32 -pulse_sink_get_monitor_index (PulseStream *stream) +pulse_sink_get_monitor_index (PulseStream *pstream) { - g_return_val_if_fail (PULSE_IS_SINK (stream), PA_INVALID_INDEX); + g_return_val_if_fail (PULSE_IS_SINK (pstream), PA_INVALID_INDEX); - return PULSE_SINK (stream)->priv->index_monitor; + return PULSE_SINK (pstream)->priv->index_monitor; } gboolean -pulse_sink_update (PulseStream *stream, const pa_sink_info *info, PulseDevice *device) +pulse_sink_update (PulseStream *pstream, const pa_sink_info *info, PulseDevice *device) { MateMixerStreamFlags flags = MATE_MIXER_STREAM_OUTPUT | MATE_MIXER_STREAM_HAS_MUTE | MATE_MIXER_STREAM_HAS_VOLUME | - MATE_MIXER_STREAM_HAS_MONITOR | MATE_MIXER_STREAM_CAN_SET_VOLUME | MATE_MIXER_STREAM_CAN_SUSPEND; PulseSink *sink; - GList *ports = NULL; - guint32 i; - g_return_val_if_fail (PULSE_IS_SINK (stream), FALSE); + g_return_val_if_fail (PULSE_IS_SINK (pstream), FALSE); + g_return_val_if_fail (info != NULL, FALSE); /* Let all the information update before emitting notify signals */ - g_object_freeze_notify (G_OBJECT (stream)); + g_object_freeze_notify (G_OBJECT (pstream)); - pulse_stream_update_name (stream, info->name); - pulse_stream_update_description (stream, info->description); - pulse_stream_update_mute (stream, info->mute ? TRUE : FALSE); - - /* List of ports */ - for (i = 0; i < info->n_ports; i++) { - MateMixerPortFlags flags = MATE_MIXER_PORT_NO_FLAGS; - -#if PA_CHECK_VERSION(2, 0, 0) - if (info->ports[i]->available == PA_PORT_AVAILABLE_YES) - flags |= MATE_MIXER_PORT_AVAILABLE; -#endif - ports = g_list_prepend (ports, - mate_mixer_port_new (info->ports[i]->name, - info->ports[i]->description, - NULL, - info->ports[i]->priority, - flags)); - } - pulse_stream_update_ports (stream, ports); - - /* Active port */ - if (info->active_port) - pulse_stream_update_active_port (stream, info->active_port->name); - else - pulse_stream_update_active_port (stream, NULL); + pulse_stream_update_name (pstream, info->name); + pulse_stream_update_description (pstream, info->description); + pulse_stream_update_mute (pstream, info->mute ? TRUE : FALSE); /* Stream state */ switch (info->state) { case PA_SINK_RUNNING: - pulse_stream_update_state (stream, MATE_MIXER_STREAM_RUNNING); + pulse_stream_update_state (pstream, MATE_MIXER_STREAM_STATE_RUNNING); break; case PA_SINK_IDLE: - pulse_stream_update_state (stream, MATE_MIXER_STREAM_IDLE); + pulse_stream_update_state (pstream, MATE_MIXER_STREAM_STATE_IDLE); break; case PA_SINK_SUSPENDED: - pulse_stream_update_state (stream, MATE_MIXER_STREAM_SUSPENDED); + pulse_stream_update_state (pstream, MATE_MIXER_STREAM_STATE_SUSPENDED); break; default: - pulse_stream_update_state (stream, MATE_MIXER_STREAM_UNKNOWN_STATE); + pulse_stream_update_state (pstream, MATE_MIXER_STREAM_STATE_UNKNOWN); break; } @@ -172,132 +158,172 @@ pulse_sink_update (PulseStream *stream, const pa_sink_info *info, PulseDevice *d if (info->flags & PA_SINK_FLAT_VOLUME) flags |= MATE_MIXER_STREAM_HAS_FLAT_VOLUME; - if (pa_channel_map_can_balance (&info->channel_map)) - flags |= MATE_MIXER_STREAM_CAN_BALANCE; - if (pa_channel_map_can_fade (&info->channel_map)) - flags |= MATE_MIXER_STREAM_CAN_FADE; + sink = PULSE_SINK (pstream); - /* Flags must be updated before volume */ - pulse_stream_update_flags (stream, flags); - - pulse_stream_update_volume (stream, - &info->volume, - &info->channel_map, - info->base_volume); - - pulse_stream_update_device (stream, MATE_MIXER_DEVICE (device)); + if (sink->priv->index_monitor == PA_INVALID_INDEX) + sink->priv->index_monitor = info->monitor_source; - sink = PULSE_SINK (stream); + if (sink->priv->index_monitor != PA_INVALID_INDEX) + flags |= MATE_MIXER_STREAM_HAS_MONITOR; - /* Handle change of monitoring source index */ - // XXX probably call this each time to validate - if (sink->priv->index_monitor != info->monitor_source) { - PulseMonitor *monitor; + /* Flags must be updated before volume */ + pulse_stream_update_flags (pstream, flags); - monitor = pulse_stream_get_monitor (PULSE_STREAM (stream)); + pulse_stream_update_channel_map (pstream, &info->channel_map); + pulse_stream_update_volume (pstream, &info->volume, info->base_volume); - if (monitor) - pulse_monitor_update_index (monitor, - info->monitor_source, - PA_INVALID_INDEX); + pulse_stream_update_device (pstream, MATE_MIXER_DEVICE (device)); - sink->priv->index_monitor = info->monitor_source; + /* Ports must be updated after device */ + if (info->ports != NULL) { + update_ports (pstream, info->ports, info->active_port); } - g_object_thaw_notify (G_OBJECT (stream)); + g_object_thaw_notify (G_OBJECT (pstream)); return TRUE; } -static gboolean -sink_set_mute (MateMixerStream *stream, gboolean mute) +static void +pulse_sink_reload (PulseStream *pstream) { - PulseStream *pulse; + g_return_if_fail (PULSE_IS_SINK (pstream)); - g_return_val_if_fail (PULSE_IS_SINK (stream), FALSE); + pulse_connection_load_sink_info (pulse_stream_get_connection (pstream), + pulse_stream_get_index (pstream)); +} - pulse = PULSE_STREAM (stream); +static gboolean +pulse_sink_set_mute (PulseStream *pstream, gboolean mute) +{ + g_return_val_if_fail (PULSE_IS_SINK (pstream), FALSE); - return pulse_connection_set_sink_mute (pulse_stream_get_connection (pulse), - pulse_stream_get_index (pulse), + return pulse_connection_set_sink_mute (pulse_stream_get_connection (pstream), + pulse_stream_get_index (pstream), mute); } static gboolean -sink_set_volume (MateMixerStream *stream, pa_cvolume *volume) +pulse_sink_set_volume (PulseStream *pstream, pa_cvolume *cvolume) { - PulseStream *pulse; - - g_return_val_if_fail (PULSE_IS_SINK (stream), FALSE); - g_return_val_if_fail (volume != NULL, FALSE); + g_return_val_if_fail (PULSE_IS_SINK (pstream), FALSE); + g_return_val_if_fail (cvolume != NULL, FALSE); - pulse = PULSE_STREAM (stream); - - return pulse_connection_set_sink_volume (pulse_stream_get_connection (pulse), - pulse_stream_get_index (pulse), - volume); + return pulse_connection_set_sink_volume (pulse_stream_get_connection (pstream), + pulse_stream_get_index (pstream), + cvolume); } static gboolean -sink_set_active_port (MateMixerStream *stream, const gchar *port) +pulse_sink_set_active_port (PulseStream *pstream, MateMixerPort *port) { - PulseStream *pulse; - - g_return_val_if_fail (PULSE_IS_SINK (stream), FALSE); - g_return_val_if_fail (port != NULL, FALSE); + g_return_val_if_fail (PULSE_IS_SINK (pstream), FALSE); + g_return_val_if_fail (MATE_MIXER_IS_PORT (port), FALSE); - pulse = PULSE_STREAM (stream); - - return pulse_connection_set_sink_port (pulse_stream_get_connection (pulse), - pulse_stream_get_index (pulse), - port); + return pulse_connection_set_sink_port (pulse_stream_get_connection (pstream), + pulse_stream_get_index (pstream), + mate_mixer_port_get_name (port)); } static gboolean -sink_suspend (MateMixerStream *stream) +pulse_sink_suspend (PulseStream *pstream) { - PulseStream *pulse; - - g_return_val_if_fail (PULSE_IS_SINK (stream), FALSE); + g_return_val_if_fail (PULSE_IS_SINK (pstream), FALSE); - pulse = PULSE_STREAM (stream); - - return pulse_connection_suspend_sink (pulse_stream_get_connection (pulse), - pulse_stream_get_index (pulse), + return pulse_connection_suspend_sink (pulse_stream_get_connection (pstream), + pulse_stream_get_index (pstream), TRUE); } static gboolean -sink_resume (MateMixerStream *stream) +pulse_sink_resume (PulseStream *pstream) { - PulseStream *pulse; - - g_return_val_if_fail (PULSE_IS_SINK (stream), FALSE); - - pulse = PULSE_STREAM (stream); + g_return_val_if_fail (PULSE_IS_SINK (pstream), FALSE); - return pulse_connection_suspend_sink (pulse_stream_get_connection (pulse), - pulse_stream_get_index (pulse), + return pulse_connection_suspend_sink (pulse_stream_get_connection (pstream), + pulse_stream_get_index (pstream), FALSE); } static PulseMonitor * -sink_create_monitor (MateMixerStream *stream) +pulse_sink_create_monitor (PulseStream *pstream) { - PulseStream *pulse; - guint32 index; + guint32 index; - g_return_val_if_fail (PULSE_IS_SINK (stream), NULL); + g_return_val_if_fail (PULSE_IS_SINK (pstream), NULL); - pulse = PULSE_STREAM (stream); - index = pulse_sink_get_monitor_index (pulse); + index = pulse_sink_get_monitor_index (pstream); if (G_UNLIKELY (index == PA_INVALID_INDEX)) { - g_debug ("Not creating monitor for stream %s as it is not available", - mate_mixer_stream_get_name (stream)); + g_debug ("Not creating monitor for stream %s: not available", + mate_mixer_stream_get_name (MATE_MIXER_STREAM (pstream))); return NULL; } - return pulse_connection_create_monitor (pulse_stream_get_connection (pulse), + return pulse_connection_create_monitor (pulse_stream_get_connection (pstream), index, PA_INVALID_INDEX); } + +static void +update_ports (PulseStream *pstream, + pa_sink_port_info **ports, + pa_sink_port_info *active) +{ + MateMixerPort *port; + MateMixerDevice *device; + GHashTable *hash; + + hash = pulse_stream_get_ports (pstream); + + while (*ports != NULL) { + MateMixerPortFlags flags = MATE_MIXER_PORT_NO_FLAGS; + pa_sink_port_info *info = *ports; + const gchar *icon = NULL; + + device = mate_mixer_stream_get_device (MATE_MIXER_STREAM (pstream)); + if (device != NULL) { + port = mate_mixer_device_get_port (device, info->name); + + if (port != NULL) { + flags = mate_mixer_port_get_flags (port); + icon = mate_mixer_port_get_icon (port); + } + } + +#if PA_CHECK_VERSION(2, 0, 0) + if (info->available == PA_PORT_AVAILABLE_YES) + flags |= MATE_MIXER_PORT_AVAILABLE; + else + flags &= ~MATE_MIXER_PORT_AVAILABLE; +#endif + + port = g_hash_table_lookup (hash, info->name); + + if (port != NULL) { + /* Update existing port */ + _mate_mixer_port_update_description (port, info->description); + _mate_mixer_port_update_icon (port, icon); + _mate_mixer_port_update_priority (port, info->priority); + _mate_mixer_port_update_flags (port, flags); + } else { + /* Add previously unknown port to the hash table */ + port = _mate_mixer_port_new (info->name, + info->description, + icon, + info->priority, + flags); + + g_hash_table_insert (hash, g_strdup (info->name), port); + } + + ports++; + } + + /* Active port */ + if (G_LIKELY (active != NULL)) + port = g_hash_table_lookup (hash, active->name); + else + port = NULL; + + pulse_stream_update_active_port (pstream, port); +} |