summaryrefslogtreecommitdiff
path: root/backends/pulse/pulse-sink.c
diff options
context:
space:
mode:
Diffstat (limited to 'backends/pulse/pulse-sink.c')
-rw-r--r--backends/pulse/pulse-sink.c288
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);
+}