summaryrefslogtreecommitdiff
path: root/libmatemixer/matemixer-backend.c
diff options
context:
space:
mode:
Diffstat (limited to 'libmatemixer/matemixer-backend.c')
-rw-r--r--libmatemixer/matemixer-backend.c359
1 files changed, 202 insertions, 157 deletions
diff --git a/libmatemixer/matemixer-backend.c b/libmatemixer/matemixer-backend.c
index fab0883..b8177e3 100644
--- a/libmatemixer/matemixer-backend.c
+++ b/libmatemixer/matemixer-backend.c
@@ -20,16 +20,16 @@
#include <glib-object.h>
#include "matemixer-backend.h"
-#include "matemixer-backend-private.h"
+#include "matemixer-device.h"
#include "matemixer-enums.h"
#include "matemixer-enum-types.h"
#include "matemixer-stream.h"
+#include "matemixer-stream-control.h"
+#include "matemixer-stored-control.h"
struct _MateMixerBackendPrivate
{
- GList *devices;
- GList *streams;
- GList *stored_streams;
+ GHashTable *devices;
MateMixerStream *default_input;
MateMixerStream *default_output;
MateMixerState state;
@@ -51,8 +51,8 @@ enum {
DEVICE_REMOVED,
STREAM_ADDED,
STREAM_REMOVED,
- STORED_STREAM_ADDED,
- STORED_STREAM_REMOVED,
+ STORED_CONTROL_ADDED,
+ STORED_CONTROL_REMOVED,
N_SIGNALS
};
@@ -72,22 +72,19 @@ static void mate_mixer_backend_set_property (GObject *object,
GParamSpec *pspec);
static void mate_mixer_backend_dispose (GObject *object);
+static void mate_mixer_backend_finalize (GObject *object);
G_DEFINE_ABSTRACT_TYPE (MateMixerBackend, mate_mixer_backend, G_TYPE_OBJECT)
-static void device_added (MateMixerBackend *backend, const gchar *name);
-static void device_removed (MateMixerBackend *backend, const gchar *name);
+static void device_added (MateMixerBackend *backend,
+ const gchar *name);
+static void device_removed (MateMixerBackend *backend,
+ const gchar *name);
-static void device_stream_added (MateMixerDevice *device,
- const gchar *name);
-static void device_stream_removed (MateMixerDevice *device,
- const gchar *name);
-
-static void free_devices (MateMixerBackend *backend);
-static void free_streams (MateMixerBackend *backend);
-static void free_stored_streams (MateMixerBackend *backend);
-static void stream_removed (MateMixerBackend *backend,
- const gchar *name);
+static void device_stream_added (MateMixerBackend *backend,
+ const gchar *name);
+static void device_stream_removed (MateMixerBackend *backend,
+ const gchar *name);
static void
mate_mixer_backend_class_init (MateMixerBackendClass *klass)
@@ -96,6 +93,7 @@ mate_mixer_backend_class_init (MateMixerBackendClass *klass)
object_class = G_OBJECT_CLASS (klass);
object_class->dispose = mate_mixer_backend_dispose;
+ object_class->finalize = mate_mixer_backend_finalize;
object_class->get_property = mate_mixer_backend_get_property;
object_class->set_property = mate_mixer_backend_set_property;
@@ -129,7 +127,7 @@ mate_mixer_backend_class_init (MateMixerBackendClass *klass)
signals[DEVICE_ADDED] =
g_signal_new ("device-added",
G_TYPE_FROM_CLASS (object_class),
- G_SIGNAL_RUN_LAST,
+ G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (MateMixerBackendClass, device_added),
NULL,
NULL,
@@ -141,7 +139,7 @@ mate_mixer_backend_class_init (MateMixerBackendClass *klass)
signals[DEVICE_REMOVED] =
g_signal_new ("device-removed",
G_TYPE_FROM_CLASS (object_class),
- G_SIGNAL_RUN_LAST,
+ G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (MateMixerBackendClass, device_removed),
NULL,
NULL,
@@ -153,7 +151,7 @@ mate_mixer_backend_class_init (MateMixerBackendClass *klass)
signals[STREAM_ADDED] =
g_signal_new ("stream-added",
G_TYPE_FROM_CLASS (object_class),
- G_SIGNAL_RUN_LAST,
+ G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (MateMixerBackendClass, stream_added),
NULL,
NULL,
@@ -165,7 +163,7 @@ mate_mixer_backend_class_init (MateMixerBackendClass *klass)
signals[STREAM_REMOVED] =
g_signal_new ("stream-removed",
G_TYPE_FROM_CLASS (object_class),
- G_SIGNAL_RUN_LAST,
+ G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (MateMixerBackendClass, stream_removed),
NULL,
NULL,
@@ -174,11 +172,11 @@ mate_mixer_backend_class_init (MateMixerBackendClass *klass)
1,
G_TYPE_STRING);
- signals[STORED_STREAM_ADDED] =
- g_signal_new ("stored-stream-added",
+ signals[STORED_CONTROL_ADDED] =
+ g_signal_new ("stored-control-added",
G_TYPE_FROM_CLASS (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (MateMixerBackendClass, stored_stream_added),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (MateMixerBackendClass, stored_control_added),
NULL,
NULL,
g_cclosure_marshal_VOID__STRING,
@@ -186,11 +184,11 @@ mate_mixer_backend_class_init (MateMixerBackendClass *klass)
1,
G_TYPE_STRING);
- signals[STORED_STREAM_REMOVED] =
- g_signal_new ("stored-stream-removed",
+ signals[STORED_CONTROL_REMOVED] =
+ g_signal_new ("stored-control-removed",
G_TYPE_FROM_CLASS (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (MateMixerBackendClass, stored_stream_removed),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (MateMixerBackendClass, stored_control_removed),
NULL,
NULL,
g_cclosure_marshal_VOID__STRING,
@@ -215,11 +213,9 @@ mate_mixer_backend_get_property (GObject *object,
case PROP_STATE:
g_value_set_enum (value, backend->priv->state);
break;
-
case PROP_DEFAULT_INPUT_STREAM:
g_value_set_object (value, backend->priv->default_input);
break;
-
case PROP_DEFAULT_OUTPUT_STREAM:
g_value_set_object (value, backend->priv->default_output);
break;
@@ -244,7 +240,6 @@ mate_mixer_backend_set_property (GObject *object,
case PROP_DEFAULT_INPUT_STREAM:
mate_mixer_backend_set_default_input_stream (backend, g_value_get_object (value));
break;
-
case PROP_DEFAULT_OUTPUT_STREAM:
mate_mixer_backend_set_default_output_stream (backend, g_value_get_object (value));
break;
@@ -262,10 +257,11 @@ mate_mixer_backend_init (MateMixerBackend *backend)
MATE_MIXER_TYPE_BACKEND,
MateMixerBackendPrivate);
- g_signal_connect (G_OBJECT (backend),
- "device-added",
- G_CALLBACK (free_devices),
- NULL);
+ backend->priv->devices = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ g_object_unref);
+
g_signal_connect (G_OBJECT (backend),
"device-added",
G_CALLBACK (device_added),
@@ -273,32 +269,8 @@ mate_mixer_backend_init (MateMixerBackend *backend)
g_signal_connect (G_OBJECT (backend),
"device-removed",
- G_CALLBACK (free_devices),
- NULL);
- g_signal_connect (G_OBJECT (backend),
- "device-removed",
G_CALLBACK (device_removed),
NULL);
-
- g_signal_connect (G_OBJECT (backend),
- "stream-added",
- G_CALLBACK (free_streams),
- NULL);
- g_signal_connect (G_OBJECT (backend),
- "stream-removed",
- G_CALLBACK (free_streams),
- NULL);
-
- g_signal_connect (G_OBJECT (backend),
- "stored-stream-added",
- G_CALLBACK (free_stored_streams),
- NULL);
- g_signal_connect (G_OBJECT (backend),
- "stored-stream-removed",
- G_CALLBACK (free_stored_streams),
- NULL);
-
- // XXX also free when changing state
}
static void
@@ -308,18 +280,28 @@ mate_mixer_backend_dispose (GObject *object)
backend = MATE_MIXER_BACKEND (object);
- free_devices (backend);
- free_streams (backend);
- free_stored_streams (backend);
-
g_clear_object (&backend->priv->default_input);
g_clear_object (&backend->priv->default_output);
+ g_hash_table_remove_all (backend->priv->devices);
+
G_OBJECT_CLASS (mate_mixer_backend_parent_class)->dispose (object);
}
+static void
+mate_mixer_backend_finalize (GObject *object)
+{
+ MateMixerBackend *backend;
+
+ backend = MATE_MIXER_BACKEND (object);
+
+ g_hash_table_unref (backend->priv->devices);
+
+ G_OBJECT_CLASS (mate_mixer_backend_parent_class)->finalize (object);
+}
+
void
-mate_mixer_backend_set_data (MateMixerBackend *backend, MateMixerBackendData *data)
+mate_mixer_backend_set_app_info (MateMixerBackend *backend, MateMixerAppInfo *info)
{
MateMixerBackendClass *klass;
@@ -327,8 +309,21 @@ mate_mixer_backend_set_data (MateMixerBackend *backend, MateMixerBackendData *da
klass = MATE_MIXER_BACKEND_GET_CLASS (backend);
- if (klass->set_data != NULL)
- klass->set_data (backend, data);
+ if (klass->set_app_info != NULL)
+ klass->set_app_info (backend, info);
+}
+
+void
+mate_mixer_backend_set_server_address (MateMixerBackend *backend, const gchar *address)
+{
+ MateMixerBackendClass *klass;
+
+ g_return_if_fail (MATE_MIXER_IS_BACKEND (backend));
+
+ klass = MATE_MIXER_BACKEND_GET_CLASS (backend);
+
+ if (klass->set_server_address != NULL)
+ klass->set_server_address (backend, address);
}
gboolean
@@ -369,72 +364,117 @@ mate_mixer_backend_get_flags (MateMixerBackend *backend)
return backend->priv->flags;
}
-const GList *
-mate_mixer_backend_list_devices (MateMixerBackend *backend)
+MateMixerDevice *
+mate_mixer_backend_get_device (MateMixerBackend *backend, const gchar *name)
{
+ const GList *list;
+
g_return_val_if_fail (MATE_MIXER_IS_BACKEND (backend), NULL);
+ g_return_val_if_fail (name != NULL, NULL);
- if (backend->priv->devices == NULL) {
- MateMixerBackendClass *klass;
+ list = mate_mixer_backend_list_devices (backend);
+ while (list != NULL) {
+ MateMixerDevice *device = MATE_MIXER_DEVICE (list->data);
- klass = MATE_MIXER_BACKEND_GET_CLASS (backend);
+ if (strcmp (name, mate_mixer_device_get_name (device)) == 0)
+ return device;
- if (klass->list_devices != NULL)
- backend->priv->devices = klass->list_devices (backend);
+ list = list->next;
}
-
- return backend->priv->devices;
+ return NULL;
}
-const GList *
-mate_mixer_backend_list_streams (MateMixerBackend *backend)
+MateMixerStream *
+mate_mixer_backend_get_stream (MateMixerBackend *backend, const gchar *name)
{
+ const GList *list;
+
g_return_val_if_fail (MATE_MIXER_IS_BACKEND (backend), NULL);
+ g_return_val_if_fail (name != NULL, NULL);
- if (backend->priv->streams == NULL) {
- MateMixerBackendClass *klass;
+ list = mate_mixer_backend_list_streams (backend);
+ while (list != NULL) {
+ MateMixerStream *stream = MATE_MIXER_STREAM (list->data);
- klass = MATE_MIXER_BACKEND_GET_CLASS (backend);
+ if (strcmp (name, mate_mixer_stream_get_name (stream)) == 0)
+ return stream;
- if (klass->list_streams != NULL)
- backend->priv->streams = klass->list_streams (backend);
+ list = list->next;
}
+ return NULL;
+}
+
+MateMixerStoredControl *
+mate_mixer_backend_get_stored_control (MateMixerBackend *backend, const gchar *name)
+{
+ const GList *list;
+
+ g_return_val_if_fail (MATE_MIXER_IS_BACKEND (backend), NULL);
+ g_return_val_if_fail (name != NULL, NULL);
+
+ list = mate_mixer_backend_list_stored_controls (backend);
+ while (list != NULL) {
+ MateMixerStreamControl *control = MATE_MIXER_STREAM_CONTROL (list->data);
- return backend->priv->streams;
+ if (strcmp (name, mate_mixer_stream_control_get_name (control)) == 0)
+ return MATE_MIXER_STORED_CONTROL (control);
+
+ list = list->next;
+ }
+ return NULL;
}
const GList *
-mate_mixer_backend_list_stored_streams (MateMixerBackend *backend)
+mate_mixer_backend_list_devices (MateMixerBackend *backend)
{
+ MateMixerBackendClass *klass;
+
g_return_val_if_fail (MATE_MIXER_IS_BACKEND (backend), NULL);
- if (backend->priv->stored_streams == NULL) {
- MateMixerBackendClass *klass;
+ klass = MATE_MIXER_BACKEND_GET_CLASS (backend);
- klass = MATE_MIXER_BACKEND_GET_CLASS (backend);
+ if G_LIKELY (klass->list_devices != NULL)
+ return klass->list_devices (backend);
- if (klass->list_stored_streams != NULL)
- backend->priv->stored_streams = klass->list_stored_streams (backend);
- }
+ return NULL;
+}
+
+const GList *
+mate_mixer_backend_list_streams (MateMixerBackend *backend)
+{
+ MateMixerBackendClass *klass;
+
+ g_return_val_if_fail (MATE_MIXER_IS_BACKEND (backend), NULL);
- return backend->priv->stored_streams;
+ klass = MATE_MIXER_BACKEND_GET_CLASS (backend);
+
+ if G_LIKELY (klass->list_streams != NULL)
+ return klass->list_streams (backend);
+
+ return NULL;
}
-MateMixerStream *
-mate_mixer_backend_get_default_input_stream (MateMixerBackend *backend)
+const GList *
+mate_mixer_backend_list_stored_controls (MateMixerBackend *backend)
{
- MateMixerStream *stream = NULL;
+ MateMixerBackendClass *klass;
g_return_val_if_fail (MATE_MIXER_IS_BACKEND (backend), NULL);
- g_object_get (G_OBJECT (backend),
- "default-input-stream", &stream,
- NULL);
+ klass = MATE_MIXER_BACKEND_GET_CLASS (backend);
- if (stream != NULL)
- g_object_unref (stream);
+ if (klass->list_stored_controls != NULL)
+ return klass->list_stored_controls (backend);
- return stream;
+ return NULL;
+}
+
+MateMixerStream *
+mate_mixer_backend_get_default_input_stream (MateMixerBackend *backend)
+{
+ g_return_val_if_fail (MATE_MIXER_IS_BACKEND (backend), NULL);
+
+ return backend->priv->default_input;
}
gboolean
@@ -462,18 +502,9 @@ mate_mixer_backend_set_default_input_stream (MateMixerBackend *backend,
MateMixerStream *
mate_mixer_backend_get_default_output_stream (MateMixerBackend *backend)
{
- MateMixerStream *stream = NULL;
-
g_return_val_if_fail (MATE_MIXER_IS_BACKEND (backend), NULL);
- g_object_get (G_OBJECT (backend),
- "default-output-stream", &stream,
- NULL);
-
- if (stream != NULL)
- g_object_unref (stream);
-
- return stream;
+ return backend->priv->default_output;
}
gboolean
@@ -503,87 +534,97 @@ device_added (MateMixerBackend *backend, const gchar *name)
{
MateMixerDevice *device;
- // device = mate_mixer_backend_get_device (backend, name);
+ device = mate_mixer_backend_get_device (backend, name);
+ if G_UNLIKELY (device == NULL) {
+ g_warn_if_reached ();
+ return;
+ }
-/*
- g_signal_connect (G_OBJECT (device),
- "stream-added",
- G_CALLBACK (device_stream_added));
- */
+ /* Keep the device in a hash table as it won't be possible to retrieve
+ * it when the remove signal is received */
+ g_hash_table_insert (backend->priv->devices,
+ g_strdup (name),
+ g_object_ref (device));
+
+ /* Connect to the stream signals from devices so we can forward them on
+ * the backend */
+ g_signal_connect_swapped (G_OBJECT (device),
+ "stream-added",
+ G_CALLBACK (device_stream_added),
+ backend);
+ g_signal_connect_swapped (G_OBJECT (device),
+ "stream-removed",
+ G_CALLBACK (device_stream_removed),
+ backend);
}
static void
device_removed (MateMixerBackend *backend, const gchar *name)
{
+ MateMixerDevice *device;
+
+ device = g_hash_table_lookup (backend->priv->devices, name);
+ if G_UNLIKELY (device == NULL) {
+ g_warn_if_reached ();
+ return;
+ }
+
+ g_signal_handlers_disconnect_by_func (G_OBJECT (device),
+ G_CALLBACK (device_stream_added),
+ backend);
+ g_signal_handlers_disconnect_by_func (G_OBJECT (device),
+ G_CALLBACK (device_stream_removed),
+ backend);
+
+ g_hash_table_remove (backend->priv->devices, name);
}
static void
-device_stream_added (MateMixerDevice *device, const gchar *name)
+device_stream_added (MateMixerBackend *backend, const gchar *name)
{
- g_signal_emit (G_OBJECT (device),
+ g_signal_emit (G_OBJECT (backend),
signals[STREAM_ADDED],
0,
name);
}
static void
-device_stream_removed (MateMixerDevice *device, const gchar *name)
+device_stream_removed (MateMixerBackend *backend, const gchar *name)
{
- g_signal_emit (G_OBJECT (device),
+ g_signal_emit (G_OBJECT (backend),
signals[STREAM_REMOVED],
0,
name);
}
-static void
-free_devices (MateMixerBackend *backend)
-{
- if (backend->priv->devices == NULL)
- return;
-
- g_list_free_full (backend->priv->devices, g_object_unref);
-
- backend->priv->devices = NULL;
-}
-
-static void
-free_streams (MateMixerBackend *backend)
+/* Protected functions */
+void
+_mate_mixer_backend_set_state (MateMixerBackend *backend, MateMixerState state)
{
- if (backend->priv->streams == NULL)
- return;
-
- g_list_free_full (backend->priv->streams, g_object_unref);
-
- backend->priv->streams = NULL;
-}
+ g_return_if_fail (MATE_MIXER_IS_BACKEND (backend));
-static void
-free_stored_streams (MateMixerBackend *backend)
-{
- if (backend->priv->stored_streams == NULL)
+ if (backend->priv->state == state)
return;
- g_list_free_full (backend->priv->stored_streams, g_object_unref);
+ backend->priv->state = state;
- backend->priv->stored_streams = NULL;
+ g_object_notify_by_pspec (G_OBJECT (backend), properties[PROP_STATE]);
}
-/* Protected */
void
-_mate_mixer_backend_set_state (MateMixerBackend *backend, MateMixerState state)
+_mate_mixer_backend_set_flags (MateMixerBackend *backend, MateMixerBackendFlags flags)
{
- if (backend->priv->state == state)
- return;
-
- backend->priv->state = state;
+ g_return_if_fail (MATE_MIXER_IS_BACKEND (backend));
- g_object_notify_by_pspec (G_OBJECT (backend), properties[PROP_STATE]);
+ backend->priv->flags = flags;
}
void
_mate_mixer_backend_set_default_input_stream (MateMixerBackend *backend,
MateMixerStream *stream)
{
+ g_return_if_fail (MATE_MIXER_IS_BACKEND (backend));
+
if (backend->priv->default_input == stream)
return;
@@ -598,13 +639,16 @@ _mate_mixer_backend_set_default_input_stream (MateMixerBackend *backend,
g_debug ("Default input stream changed to %s",
(stream != NULL) ? mate_mixer_stream_get_name (stream) : "none");
- g_object_notify_by_pspec (G_OBJECT (backend), properties[PROP_DEFAULT_INPUT_STREAM]);
+ g_object_notify_by_pspec (G_OBJECT (backend),
+ properties[PROP_DEFAULT_INPUT_STREAM]);
}
void
_mate_mixer_backend_set_default_output_stream (MateMixerBackend *backend,
MateMixerStream *stream)
{
+ g_return_if_fail (MATE_MIXER_IS_BACKEND (backend));
+
if (backend->priv->default_output == stream)
return;
@@ -619,5 +663,6 @@ _mate_mixer_backend_set_default_output_stream (MateMixerBackend *backend,
g_debug ("Default output stream changed to %s",
(stream != NULL) ? mate_mixer_stream_get_name (stream) : "none");
- g_object_notify_by_pspec (G_OBJECT (backend), properties[PROP_DEFAULT_OUTPUT_STREAM]);
+ g_object_notify_by_pspec (G_OBJECT (backend),
+ properties[PROP_DEFAULT_OUTPUT_STREAM]);
}