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.c533
1 files changed, 433 insertions, 100 deletions
diff --git a/libmatemixer/matemixer-backend.c b/libmatemixer/matemixer-backend.c
index be5c704..fab0883 100644
--- a/libmatemixer/matemixer-backend.c
+++ b/libmatemixer/matemixer-backend.c
@@ -15,61 +15,122 @@
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
+#include <string.h>
#include <glib.h>
#include <glib-object.h>
#include "matemixer-backend.h"
+#include "matemixer-backend-private.h"
#include "matemixer-enums.h"
#include "matemixer-enum-types.h"
#include "matemixer-stream.h"
+struct _MateMixerBackendPrivate
+{
+ GList *devices;
+ GList *streams;
+ GList *stored_streams;
+ MateMixerStream *default_input;
+ MateMixerStream *default_output;
+ MateMixerState state;
+ MateMixerBackendFlags flags;
+};
+
+enum {
+ PROP_0,
+ PROP_STATE,
+ PROP_DEFAULT_INPUT_STREAM,
+ PROP_DEFAULT_OUTPUT_STREAM,
+ N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
enum {
DEVICE_ADDED,
DEVICE_REMOVED,
STREAM_ADDED,
STREAM_REMOVED,
- CACHED_STREAM_ADDED,
- CACHED_STREAM_REMOVED,
+ STORED_STREAM_ADDED,
+ STORED_STREAM_REMOVED,
N_SIGNALS
};
static guint signals[N_SIGNALS] = { 0, };
-G_DEFINE_INTERFACE (MateMixerBackend, mate_mixer_backend, G_TYPE_OBJECT)
+static void mate_mixer_backend_class_init (MateMixerBackendClass *klass);
+
+static void mate_mixer_backend_init (MateMixerBackend *backend);
+
+static void mate_mixer_backend_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void mate_mixer_backend_set_property (GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec);
+
+static void mate_mixer_backend_dispose (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_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
-mate_mixer_backend_default_init (MateMixerBackendInterface *iface)
+mate_mixer_backend_class_init (MateMixerBackendClass *klass)
{
- g_object_interface_install_property (iface,
- g_param_spec_enum ("state",
- "State",
- "Current backend connection state",
- MATE_MIXER_TYPE_STATE,
- MATE_MIXER_STATE_IDLE,
- G_PARAM_READABLE |
- G_PARAM_STATIC_STRINGS));
-
- g_object_interface_install_property (iface,
- g_param_spec_object ("default-input",
- "Default input",
- "Default input stream",
- MATE_MIXER_TYPE_STREAM,
- G_PARAM_READABLE |
- G_PARAM_STATIC_STRINGS));
-
- g_object_interface_install_property (iface,
- g_param_spec_object ("default-output",
- "Default output",
- "Default output stream",
- MATE_MIXER_TYPE_STREAM,
- G_PARAM_READABLE |
- G_PARAM_STATIC_STRINGS));
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->dispose = mate_mixer_backend_dispose;
+ object_class->get_property = mate_mixer_backend_get_property;
+ object_class->set_property = mate_mixer_backend_set_property;
+
+ properties[PROP_STATE] =
+ g_param_spec_enum ("state",
+ "State",
+ "Current backend connection state",
+ MATE_MIXER_TYPE_STATE,
+ MATE_MIXER_STATE_IDLE,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS);
+
+ properties[PROP_DEFAULT_INPUT_STREAM] =
+ g_param_spec_object ("default-input-stream",
+ "Default input stream",
+ "Default input stream",
+ MATE_MIXER_TYPE_STREAM,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS);
+
+ properties[PROP_DEFAULT_OUTPUT_STREAM] =
+ g_param_spec_object ("default-output-stream",
+ "Default output stream",
+ "Default output stream",
+ MATE_MIXER_TYPE_STREAM,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class, N_PROPERTIES, properties);
signals[DEVICE_ADDED] =
g_signal_new ("device-added",
- G_TYPE_FROM_INTERFACE (iface),
+ G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (MateMixerBackendInterface, device_added),
+ G_STRUCT_OFFSET (MateMixerBackendClass, device_added),
NULL,
NULL,
g_cclosure_marshal_VOID__STRING,
@@ -79,9 +140,9 @@ mate_mixer_backend_default_init (MateMixerBackendInterface *iface)
signals[DEVICE_REMOVED] =
g_signal_new ("device-removed",
- G_TYPE_FROM_INTERFACE (iface),
+ G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (MateMixerBackendInterface, device_removed),
+ G_STRUCT_OFFSET (MateMixerBackendClass, device_removed),
NULL,
NULL,
g_cclosure_marshal_VOID__STRING,
@@ -91,9 +152,9 @@ mate_mixer_backend_default_init (MateMixerBackendInterface *iface)
signals[STREAM_ADDED] =
g_signal_new ("stream-added",
- G_TYPE_FROM_INTERFACE (iface),
+ G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (MateMixerBackendInterface, stream_added),
+ G_STRUCT_OFFSET (MateMixerBackendClass, stream_added),
NULL,
NULL,
g_cclosure_marshal_VOID__STRING,
@@ -103,9 +164,9 @@ mate_mixer_backend_default_init (MateMixerBackendInterface *iface)
signals[STREAM_REMOVED] =
g_signal_new ("stream-removed",
- G_TYPE_FROM_INTERFACE (iface),
+ G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (MateMixerBackendInterface, stream_removed),
+ G_STRUCT_OFFSET (MateMixerBackendClass, stream_removed),
NULL,
NULL,
g_cclosure_marshal_VOID__STRING,
@@ -113,11 +174,11 @@ mate_mixer_backend_default_init (MateMixerBackendInterface *iface)
1,
G_TYPE_STRING);
- signals[CACHED_STREAM_ADDED] =
- g_signal_new ("cached-stream-added",
- G_TYPE_FROM_INTERFACE (iface),
+ signals[STORED_STREAM_ADDED] =
+ g_signal_new ("stored-stream-added",
+ G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (MateMixerBackendInterface, cached_stream_added),
+ G_STRUCT_OFFSET (MateMixerBackendClass, stored_stream_added),
NULL,
NULL,
g_cclosure_marshal_VOID__STRING,
@@ -125,30 +186,149 @@ mate_mixer_backend_default_init (MateMixerBackendInterface *iface)
1,
G_TYPE_STRING);
- signals[CACHED_STREAM_REMOVED] =
- g_signal_new ("cached-stream-removed",
- G_TYPE_FROM_INTERFACE (iface),
+ signals[STORED_STREAM_REMOVED] =
+ g_signal_new ("stored-stream-removed",
+ G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (MateMixerBackendInterface, cached_stream_removed),
+ G_STRUCT_OFFSET (MateMixerBackendClass, stored_stream_removed),
NULL,
NULL,
g_cclosure_marshal_VOID__STRING,
G_TYPE_NONE,
1,
G_TYPE_STRING);
+
+ g_type_class_add_private (object_class, sizeof (MateMixerBackendPrivate));
+}
+
+static void
+mate_mixer_backend_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ MateMixerBackend *backend;
+
+ backend = MATE_MIXER_BACKEND (object);
+
+ switch (param_id) {
+ 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;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ }
+}
+
+static void
+mate_mixer_backend_set_property (GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ MateMixerBackend *backend;
+
+ backend = MATE_MIXER_BACKEND (object);
+
+ switch (param_id) {
+ 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;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ }
+}
+
+static void
+mate_mixer_backend_init (MateMixerBackend *backend)
+{
+ backend->priv = G_TYPE_INSTANCE_GET_PRIVATE (backend,
+ MATE_MIXER_TYPE_BACKEND,
+ MateMixerBackendPrivate);
+
+ g_signal_connect (G_OBJECT (backend),
+ "device-added",
+ G_CALLBACK (free_devices),
+ NULL);
+ g_signal_connect (G_OBJECT (backend),
+ "device-added",
+ G_CALLBACK (device_added),
+ NULL);
+
+ 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
+mate_mixer_backend_dispose (GObject *object)
+{
+ MateMixerBackend *backend;
+
+ 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_OBJECT_CLASS (mate_mixer_backend_parent_class)->dispose (object);
}
void
-mate_mixer_backend_set_data (MateMixerBackend *backend, const MateMixerBackendData *data)
+mate_mixer_backend_set_data (MateMixerBackend *backend, MateMixerBackendData *data)
{
- MateMixerBackendInterface *iface;
+ MateMixerBackendClass *klass;
g_return_if_fail (MATE_MIXER_IS_BACKEND (backend));
- iface = MATE_MIXER_BACKEND_GET_INTERFACE (backend);
+ klass = MATE_MIXER_BACKEND_GET_CLASS (backend);
- if (iface->set_data)
- iface->set_data (backend, data);
+ if (klass->set_data != NULL)
+ klass->set_data (backend, data);
}
gboolean
@@ -157,20 +337,20 @@ mate_mixer_backend_open (MateMixerBackend *backend)
g_return_val_if_fail (MATE_MIXER_IS_BACKEND (backend), FALSE);
/* Implementation required */
- return MATE_MIXER_BACKEND_GET_INTERFACE (backend)->open (backend);
+ return MATE_MIXER_BACKEND_GET_CLASS (backend)->open (backend);
}
void
mate_mixer_backend_close (MateMixerBackend *backend)
{
- MateMixerBackendInterface *iface;
+ MateMixerBackendClass *klass;
g_return_if_fail (MATE_MIXER_IS_BACKEND (backend));
- iface = MATE_MIXER_BACKEND_GET_INTERFACE (backend);
+ klass = MATE_MIXER_BACKEND_GET_CLASS (backend);
- if (iface->close)
- iface->close (backend);
+ if (klass->close != NULL)
+ klass->close (backend);
}
MateMixerState
@@ -178,113 +358,266 @@ mate_mixer_backend_get_state (MateMixerBackend *backend)
{
g_return_val_if_fail (MATE_MIXER_IS_BACKEND (backend), MATE_MIXER_STATE_UNKNOWN);
- /* Implementation required */
- return MATE_MIXER_BACKEND_GET_INTERFACE (backend)->get_state (backend);
+ return backend->priv->state;
}
-GList *
-mate_mixer_backend_list_devices (MateMixerBackend *backend)
+MateMixerBackendFlags
+mate_mixer_backend_get_flags (MateMixerBackend *backend)
{
- MateMixerBackendInterface *iface;
+ g_return_val_if_fail (MATE_MIXER_IS_BACKEND (backend), MATE_MIXER_BACKEND_NO_FLAGS);
+ return backend->priv->flags;
+}
+
+const GList *
+mate_mixer_backend_list_devices (MateMixerBackend *backend)
+{
g_return_val_if_fail (MATE_MIXER_IS_BACKEND (backend), NULL);
- iface = MATE_MIXER_BACKEND_GET_INTERFACE (backend);
+ if (backend->priv->devices == NULL) {
+ MateMixerBackendClass *klass;
- if (iface->list_devices)
- return iface->list_devices (backend);
+ klass = MATE_MIXER_BACKEND_GET_CLASS (backend);
- return NULL;
+ if (klass->list_devices != NULL)
+ backend->priv->devices = klass->list_devices (backend);
+ }
+
+ return backend->priv->devices;
}
-GList *
+const GList *
mate_mixer_backend_list_streams (MateMixerBackend *backend)
{
- MateMixerBackendInterface *iface;
-
g_return_val_if_fail (MATE_MIXER_IS_BACKEND (backend), NULL);
- iface = MATE_MIXER_BACKEND_GET_INTERFACE (backend);
+ if (backend->priv->streams == NULL) {
+ MateMixerBackendClass *klass;
- if (iface->list_streams)
- return iface->list_streams (backend);
+ klass = MATE_MIXER_BACKEND_GET_CLASS (backend);
- return NULL;
+ if (klass->list_streams != NULL)
+ backend->priv->streams = klass->list_streams (backend);
+ }
+
+ return backend->priv->streams;
}
-GList *
-mate_mixer_backend_list_cached_streams (MateMixerBackend *backend)
+const GList *
+mate_mixer_backend_list_stored_streams (MateMixerBackend *backend)
{
- MateMixerBackendInterface *iface;
-
g_return_val_if_fail (MATE_MIXER_IS_BACKEND (backend), NULL);
- iface = MATE_MIXER_BACKEND_GET_INTERFACE (backend);
+ if (backend->priv->stored_streams == NULL) {
+ MateMixerBackendClass *klass;
- if (iface->list_cached_streams)
- return iface->list_cached_streams (backend);
+ klass = MATE_MIXER_BACKEND_GET_CLASS (backend);
- return NULL;
+ if (klass->list_stored_streams != NULL)
+ backend->priv->stored_streams = klass->list_stored_streams (backend);
+ }
+
+ return backend->priv->stored_streams;
}
MateMixerStream *
mate_mixer_backend_get_default_input_stream (MateMixerBackend *backend)
{
- MateMixerBackendInterface *iface;
+ MateMixerStream *stream = NULL;
g_return_val_if_fail (MATE_MIXER_IS_BACKEND (backend), NULL);
- iface = MATE_MIXER_BACKEND_GET_INTERFACE (backend);
+ g_object_get (G_OBJECT (backend),
+ "default-input-stream", &stream,
+ NULL);
- if (iface->get_default_input_stream)
- return iface->get_default_input_stream (backend);
+ if (stream != NULL)
+ g_object_unref (stream);
- return NULL;
+ return stream;
}
gboolean
mate_mixer_backend_set_default_input_stream (MateMixerBackend *backend,
MateMixerStream *stream)
{
- MateMixerBackendInterface *iface;
-
g_return_val_if_fail (MATE_MIXER_IS_BACKEND (backend), FALSE);
+ g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), FALSE);
+
+ if (backend->priv->default_input != stream) {
+ MateMixerBackendClass *klass;
+
+ klass = MATE_MIXER_BACKEND_GET_CLASS (backend);
- iface = MATE_MIXER_BACKEND_GET_INTERFACE (backend);
+ if (klass->set_default_input_stream == NULL ||
+ klass->set_default_input_stream (backend, stream) == FALSE)
+ return FALSE;
- if (iface->set_default_input_stream)
- return iface->set_default_input_stream (backend, stream);
+ _mate_mixer_backend_set_default_input_stream (backend, stream);
+ }
- return FALSE;
+ return TRUE;
}
MateMixerStream *
mate_mixer_backend_get_default_output_stream (MateMixerBackend *backend)
{
- MateMixerBackendInterface *iface;
+ MateMixerStream *stream = NULL;
g_return_val_if_fail (MATE_MIXER_IS_BACKEND (backend), NULL);
- iface = MATE_MIXER_BACKEND_GET_INTERFACE (backend);
+ g_object_get (G_OBJECT (backend),
+ "default-output-stream", &stream,
+ NULL);
- if (iface->get_default_output_stream)
- return iface->get_default_output_stream (backend);
+ if (stream != NULL)
+ g_object_unref (stream);
- return NULL;
+ return stream;
}
gboolean
mate_mixer_backend_set_default_output_stream (MateMixerBackend *backend,
MateMixerStream *stream)
{
- MateMixerBackendInterface *iface;
-
g_return_val_if_fail (MATE_MIXER_IS_BACKEND (backend), FALSE);
+ g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), FALSE);
+
+ if (backend->priv->default_input != stream) {
+ MateMixerBackendClass *klass;
+
+ klass = MATE_MIXER_BACKEND_GET_CLASS (backend);
+
+ if (klass->set_default_output_stream == NULL ||
+ klass->set_default_output_stream (backend, stream) == FALSE)
+ return FALSE;
+
+ _mate_mixer_backend_set_default_output_stream (backend, stream);
+ }
+
+ return TRUE;
+}
+
+static void
+device_added (MateMixerBackend *backend, const gchar *name)
+{
+ MateMixerDevice *device;
+
+ // device = mate_mixer_backend_get_device (backend, name);
+
+/*
+ g_signal_connect (G_OBJECT (device),
+ "stream-added",
+ G_CALLBACK (device_stream_added));
+ */
+}
+
+static void
+device_removed (MateMixerBackend *backend, const gchar *name)
+{
+}
+
+static void
+device_stream_added (MateMixerDevice *device, const gchar *name)
+{
+ g_signal_emit (G_OBJECT (device),
+ signals[STREAM_ADDED],
+ 0,
+ name);
+}
+
+static void
+device_stream_removed (MateMixerDevice *device, const gchar *name)
+{
+ g_signal_emit (G_OBJECT (device),
+ 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)
+{
+ if (backend->priv->streams == NULL)
+ return;
+
+ g_list_free_full (backend->priv->streams, g_object_unref);
+
+ backend->priv->streams = NULL;
+}
+
+static void
+free_stored_streams (MateMixerBackend *backend)
+{
+ if (backend->priv->stored_streams == NULL)
+ return;
+
+ g_list_free_full (backend->priv->stored_streams, g_object_unref);
+
+ backend->priv->stored_streams = NULL;
+}
+
+/* Protected */
+void
+_mate_mixer_backend_set_state (MateMixerBackend *backend, MateMixerState state)
+{
+ if (backend->priv->state == state)
+ return;
+
+ backend->priv->state = state;
+
+ g_object_notify_by_pspec (G_OBJECT (backend), properties[PROP_STATE]);
+}
+
+void
+_mate_mixer_backend_set_default_input_stream (MateMixerBackend *backend,
+ MateMixerStream *stream)
+{
+ if (backend->priv->default_input == stream)
+ return;
+
+ if (backend->priv->default_input != NULL)
+ g_object_unref (backend->priv->default_input);
+
+ if (stream != NULL)
+ backend->priv->default_input = g_object_ref (stream);
+ else
+ backend->priv->default_input = NULL;
+
+ 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]);
+}
+
+void
+_mate_mixer_backend_set_default_output_stream (MateMixerBackend *backend,
+ MateMixerStream *stream)
+{
+ if (backend->priv->default_output == stream)
+ return;
+
+ if (backend->priv->default_output != NULL)
+ g_object_unref (backend->priv->default_output);
- iface = MATE_MIXER_BACKEND_GET_INTERFACE (backend);
+ if (stream != NULL)
+ backend->priv->default_output = g_object_ref (stream);
+ else
+ backend->priv->default_output = NULL;
- if (iface->set_default_output_stream)
- return iface->set_default_output_stream (backend, stream);
+ g_debug ("Default output stream changed to %s",
+ (stream != NULL) ? mate_mixer_stream_get_name (stream) : "none");
- return FALSE;
+ g_object_notify_by_pspec (G_OBJECT (backend), properties[PROP_DEFAULT_OUTPUT_STREAM]);
}