From d2c3a4be634018a2b63f4c80a26f9024a0d3de47 Mon Sep 17 00:00:00 2001 From: Michal Ratajsky Date: Sat, 7 Jun 2014 01:07:02 +0200 Subject: Weekly update --- Makefile.am | 4 +- backends/null/Makefile.am | 6 +- backends/null/null.c | 32 +- backends/null/null.h | 6 +- backends/pulse/Makefile.am | 14 +- backends/pulse/pulse-connection.c | 764 ++++++++++++++++++++++++++++++++ backends/pulse/pulse-connection.h | 102 +++++ backends/pulse/pulse-device.c | 251 +++++++---- backends/pulse/pulse-device.h | 27 +- backends/pulse/pulse-sink-input.c | 0 backends/pulse/pulse-sink-input.h | 0 backends/pulse/pulse-sink.c | 130 ++++++ backends/pulse/pulse-sink.h | 69 +++ backends/pulse/pulse-source-output.c | 0 backends/pulse/pulse-source-output.h | 0 backends/pulse/pulse-source.c | 0 backends/pulse/pulse-source.h | 0 backends/pulse/pulse-stream.c | 259 +++++++++++ backends/pulse/pulse-stream.h | 86 ++++ backends/pulse/pulse-track.c | 0 backends/pulse/pulse-track.h | 0 backends/pulse/pulse.c | 383 ++++++++-------- backends/pulse/pulse.h | 2 + configure.ac | 2 +- doc/Makefile.am | 2 - docs/Makefile.am | 2 + libmatemixer/Makefile.am | 16 +- libmatemixer/matemixer-backend-module.c | 85 ++-- libmatemixer/matemixer-backend-module.h | 23 +- libmatemixer/matemixer-backend.c | 45 +- libmatemixer/matemixer-backend.h | 22 +- libmatemixer/matemixer-control.c | 117 +++-- libmatemixer/matemixer-control.h | 20 +- libmatemixer/matemixer-device-port.c | 270 ----------- libmatemixer/matemixer-device-port.h | 80 ---- libmatemixer/matemixer-device-profile.c | 189 -------- libmatemixer/matemixer-device-profile.h | 67 --- libmatemixer/matemixer-device.c | 147 ++++-- libmatemixer/matemixer-device.h | 36 +- libmatemixer/matemixer-enum-types.c | 88 +++- libmatemixer/matemixer-enum-types.h | 15 +- libmatemixer/matemixer-enums.h | 56 ++- libmatemixer/matemixer-port.c | 256 +++++++++++ libmatemixer/matemixer-port.h | 73 +++ libmatemixer/matemixer-private.h | 4 +- libmatemixer/matemixer-profile.c | 196 ++++++++ libmatemixer/matemixer-profile.h | 67 +++ libmatemixer/matemixer-stream.c | 531 ++++++++++++++++++++++ libmatemixer/matemixer-stream.h | 165 +++++++ libmatemixer/matemixer-track.c | 29 -- libmatemixer/matemixer-track.h | 47 -- libmatemixer/matemixer.c | 21 +- libmatemixer/matemixer.h | 2 +- 53 files changed, 3572 insertions(+), 1236 deletions(-) create mode 100644 backends/pulse/pulse-connection.c create mode 100644 backends/pulse/pulse-connection.h create mode 100644 backends/pulse/pulse-sink-input.c create mode 100644 backends/pulse/pulse-sink-input.h create mode 100644 backends/pulse/pulse-sink.c create mode 100644 backends/pulse/pulse-sink.h create mode 100644 backends/pulse/pulse-source-output.c create mode 100644 backends/pulse/pulse-source-output.h create mode 100644 backends/pulse/pulse-source.c create mode 100644 backends/pulse/pulse-source.h create mode 100644 backends/pulse/pulse-stream.c create mode 100644 backends/pulse/pulse-stream.h delete mode 100644 backends/pulse/pulse-track.c delete mode 100644 backends/pulse/pulse-track.h delete mode 100644 doc/Makefile.am create mode 100644 docs/Makefile.am delete mode 100644 libmatemixer/matemixer-device-port.c delete mode 100644 libmatemixer/matemixer-device-port.h delete mode 100644 libmatemixer/matemixer-device-profile.c delete mode 100644 libmatemixer/matemixer-device-profile.h create mode 100644 libmatemixer/matemixer-port.c create mode 100644 libmatemixer/matemixer-port.h create mode 100644 libmatemixer/matemixer-profile.c create mode 100644 libmatemixer/matemixer-profile.h create mode 100644 libmatemixer/matemixer-stream.c create mode 100644 libmatemixer/matemixer-stream.h delete mode 100644 libmatemixer/matemixer-track.c delete mode 100644 libmatemixer/matemixer-track.h diff --git a/Makefile.am b/Makefile.am index 57aa03e..0eb7591 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4,9 +4,9 @@ SUBDIRS = \ libmatemixer \ backends \ data \ - doc + docs -EXTRA_DIR = autogen.sh +EXTRA_DIST = autogen.sh MAINTAINERCLEANFILES = \ $(srcdir)/aclocal.m4 \ diff --git a/backends/null/Makefile.am b/backends/null/Makefile.am index b6d92c7..f28bc06 100644 --- a/backends/null/Makefile.am +++ b/backends/null/Makefile.am @@ -6,15 +6,13 @@ AM_CPPFLAGS = \ -I$(top_srcdir) \ -DG_LOG_DOMAIN=\"libmatemixer-null\" -libmatemixer_null_la_CFLAGS = \ - $(GLIB_CFLAGS) +libmatemixer_null_la_CFLAGS = $(GLIB_CFLAGS) libmatemixer_null_la_SOURCES = \ null.c \ null.h -libmatemixer_null_la_LIBADD = \ - $(GLIB_LIBS) +libmatemixer_null_la_LIBADD = $(GLIB_LIBS) libmatemixer_null_la_LDFLAGS = \ -avoid-version \ diff --git a/backends/null/null.c b/backends/null/null.c index b96c9b0..1e8085d 100644 --- a/backends/null/null.c +++ b/backends/null/null.c @@ -26,19 +26,17 @@ #define BACKEND_NAME "Null" #define BACKEND_PRIORITY 999 -/* Support function for dynamic loading of the backend module */ -void backend_module_init (GTypeModule *module); - -const MateMixerBackendModuleInfo *backend_module_get_info (void); - static void mate_mixer_backend_interface_init (MateMixerBackendInterface *iface); +static void mate_mixer_null_class_init (MateMixerNullClass *klass); +static void mate_mixer_null_class_finalize (MateMixerNullClass *klass); +static void mate_mixer_null_init (MateMixerNull *null); G_DEFINE_DYNAMIC_TYPE_EXTENDED (MateMixerNull, mate_mixer_null, G_TYPE_OBJECT, 0, G_IMPLEMENT_INTERFACE_DYNAMIC (MATE_MIXER_TYPE_BACKEND, mate_mixer_backend_interface_init)) -static MateMixerBackendModuleInfo info; +static MateMixerBackendInfo info; void backend_module_init (GTypeModule *module) @@ -48,10 +46,10 @@ backend_module_init (GTypeModule *module) info.name = BACKEND_NAME; info.priority = BACKEND_PRIORITY; info.g_type = MATE_MIXER_TYPE_NULL; - info.backend_type = MATE_MIXER_BACKEND_TYPE_NULL; + info.backend_type = MATE_MIXER_BACKEND_NULL; } -const MateMixerBackendModuleInfo * +const MateMixerBackendInfo * backend_module_get_info (void) { return &info; @@ -64,28 +62,18 @@ mate_mixer_backend_interface_init (MateMixerBackendInterface *iface) } static void -mate_mixer_null_init (MateMixerNull *null) -{ -} - -static void -mate_mixer_null_finalize (GObject *object) +mate_mixer_null_class_init (MateMixerNullClass *klass) { - G_OBJECT_CLASS (mate_mixer_null_parent_class)->finalize (object); } +/* Called in the code generated by G_DEFINE_DYNAMIC_TYPE_EXTENDED() */ static void -mate_mixer_null_class_init (MateMixerNullClass *klass) +mate_mixer_null_class_finalize (MateMixerNullClass *klass) { - GObjectClass *object_class; - - object_class = G_OBJECT_CLASS (klass); - object_class->finalize = mate_mixer_null_finalize; } -/* Called in the code generated by G_DEFINE_DYNAMIC_TYPE_EXTENDED() */ static void -mate_mixer_null_class_finalize (MateMixerNullClass *klass) +mate_mixer_null_init (MateMixerNull *null) { } diff --git a/backends/null/null.h b/backends/null/null.h index d73794e..c9dd501 100644 --- a/backends/null/null.h +++ b/backends/null/null.h @@ -51,6 +51,10 @@ struct _MateMixerNullClass GType mate_mixer_null_get_type (void) G_GNUC_CONST; -gboolean mate_mixer_null_open (MateMixerBackend *backend); +/* Support function for dynamic loading of the backend module */ +void backend_module_init (GTypeModule *module); +const MateMixerBackendInfo *backend_module_get_info (void); + +gboolean mate_mixer_null_open (MateMixerBackend *backend); #endif /* MATEMIXER_NULL_H */ diff --git a/backends/pulse/Makefile.am b/backends/pulse/Makefile.am index 2f7cd6f..2cc7b5e 100644 --- a/backends/pulse/Makefile.am +++ b/backends/pulse/Makefile.am @@ -13,10 +13,20 @@ libmatemixer_pulse_la_CFLAGS = \ libmatemixer_pulse_la_SOURCES = \ pulse.c \ pulse.h \ + pulse-connection.c \ + pulse-connection.h \ pulse-device.c \ pulse-device.h \ - pulse-track.c \ - pulse-track.h + pulse-stream.c \ + pulse-stream.h \ + pulse-sink.c \ + pulse-sink.h \ + pulse-sink-input.c \ + pulse-sink-input.h \ + pulse-source.c \ + pulse-source.h \ + pulse-source-output.c \ + pulse-source-output.h libmatemixer_pulse_la_LIBADD = \ $(GLIB_LIBS) \ diff --git a/backends/pulse/pulse-connection.c b/backends/pulse/pulse-connection.c new file mode 100644 index 0000000..6c70490 --- /dev/null +++ b/backends/pulse/pulse-connection.c @@ -0,0 +1,764 @@ +/* + * Copyright (C) 2014 Michal Ratajsky + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the licence, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include +#include +#include +#include + +#include + +#include "pulse-connection.h" + +struct _MateMixerPulseConnectionPrivate +{ + gchar *server; + gboolean reconnect; + gboolean connected; + pa_context *context; + pa_threaded_mainloop *mainloop; +}; + +enum { + PROP_0, + PROP_SERVER, + PROP_RECONNECT, + PROP_CONNECTED, + N_PROPERTIES +}; + +enum { + LIST_ITEM_CARD, + LIST_ITEM_SINK, + LIST_ITEM_SOURCE, + LIST_ITEM_SINK_INPUT, + LIST_ITEM_SOURCE_OUTPUT, + CARD_ADDED, + CARD_REMOVED, + CARD_CHANGED, + SINK_ADDED, + SINK_REMOVED, + SINK_CHANGED, + SOURCE_ADDED, + SOURCE_REMOVED, + SOURCE_CHANGED, + N_SIGNALS +}; + +static GParamSpec *properties[N_PROPERTIES] = { NULL, }; + +static guint signals[N_SIGNALS] = { 0, }; + +G_DEFINE_TYPE (MateMixerPulseConnection, mate_mixer_pulse_connection, G_TYPE_OBJECT); + +static gchar *pulse_connection_get_name (void); + +static gboolean pulse_connection_process_operation (MateMixerPulseConnection *connection, + pa_operation *o); + +static void pulse_connection_state_cb (pa_context *c, void *userdata); + +static void pulse_connection_subscribe_cb (pa_context *c, + pa_subscription_event_type_t t, + uint32_t idx, + void *userdata); + +static void pulse_connection_card_info_cb (pa_context *c, + const pa_card_info *info, + int eol, + void *userdata); + +static void pulse_connection_sink_info_cb (pa_context *c, + const pa_sink_info *info, + int eol, + void *userdata); + +static void pulse_connection_source_info_cb (pa_context *c, + const pa_source_info *info, + int eol, + void *userdata); + +static void pulse_connection_sink_input_info_cb (pa_context *c, + const pa_sink_input_info *info, + int eol, + void *userdata); + +static void pulse_connection_source_output_info_cb (pa_context *c, + const pa_source_output_info *info, + int eol, + void *userdata); + +static void +mate_mixer_pulse_connection_init (MateMixerPulseConnection *connection) +{ + connection->priv = G_TYPE_INSTANCE_GET_PRIVATE ( + connection, + MATE_MIXER_TYPE_PULSE_CONNECTION, + MateMixerPulseConnectionPrivate); +} + +static void +mate_mixer_pulse_connection_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec) +{ + MateMixerPulseConnection *connection; + + connection = MATE_MIXER_PULSE_CONNECTION (object); + + switch (param_id) { + case PROP_SERVER: + g_value_set_string (value, connection->priv->server); + break; + case PROP_RECONNECT: + g_value_set_boolean (value, connection->priv->reconnect); + break; + case PROP_CONNECTED: + g_value_set_boolean (value, connection->priv->connected); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} + +static void +mate_mixer_pulse_connection_set_property (GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec) +{ + MateMixerPulseConnection *connection; + + connection = MATE_MIXER_PULSE_CONNECTION (object); + + switch (param_id) { + case PROP_SERVER: + connection->priv->server = g_strdup (g_value_get_string (value)); + break; + case PROP_RECONNECT: + connection->priv->reconnect = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} + +static void +mate_mixer_pulse_connection_finalize (GObject *object) +{ + MateMixerPulseConnection *connection; + + connection = MATE_MIXER_PULSE_CONNECTION (object); + + g_free (connection->priv->server); + + G_OBJECT_CLASS (mate_mixer_pulse_connection_parent_class)->finalize (object); +} + +static void +mate_mixer_pulse_connection_class_init (MateMixerPulseConnectionClass *klass) +{ + GObjectClass *object_class; + + object_class = G_OBJECT_CLASS (klass); + object_class->finalize = mate_mixer_pulse_connection_finalize; + object_class->get_property = mate_mixer_pulse_connection_get_property; + object_class->set_property = mate_mixer_pulse_connection_set_property; + + properties[PROP_SERVER] = g_param_spec_string ( + "server", + "Server", + "PulseAudio server to connect to", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + properties[PROP_RECONNECT] = g_param_spec_boolean ( + "reconnect", + "Reconnect", + "Try to reconnect when connection to PulseAudio server is lost", + TRUE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + properties[PROP_CONNECTED] = g_param_spec_boolean ( + "connected", + "Connected", + "Connected to a PulseAudio server or not", + FALSE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + signals[LIST_ITEM_CARD] = g_signal_new ( + "list-item-card", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (MateMixerPulseConnectionClass, list_item_card), + NULL, + NULL, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, + 1, + G_TYPE_POINTER); + + signals[LIST_ITEM_SINK] = g_signal_new ( + "list-item-sink", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (MateMixerPulseConnectionClass, list_item_sink), + NULL, + NULL, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, + 1, + G_TYPE_POINTER); + + signals[LIST_ITEM_SINK_INPUT] = g_signal_new ( + "list-item-sink-input", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (MateMixerPulseConnectionClass, list_item_sink_input), + NULL, + NULL, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, + 1, + G_TYPE_POINTER); + + signals[LIST_ITEM_SOURCE] = g_signal_new ( + "list-item-source", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (MateMixerPulseConnectionClass, list_item_source), + NULL, + NULL, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, + 1, + G_TYPE_POINTER); + + signals[LIST_ITEM_SOURCE_OUTPUT] = g_signal_new ( + "list-item-source-output", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (MateMixerPulseConnectionClass, list_item_source_output), + NULL, + NULL, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, + 1, + G_TYPE_POINTER); + + g_object_class_install_properties (object_class, N_PROPERTIES, properties); + + g_type_class_add_private (object_class, sizeof (MateMixerPulseConnectionPrivate)); +} + +// XXX: pass more info about application, provide API + +MateMixerPulseConnection * +mate_mixer_pulse_connection_new (const gchar *server, const gchar *app_name) +{ + pa_threaded_mainloop *mainloop; + pa_context *context; + MateMixerPulseConnection *connection; + + mainloop = pa_threaded_mainloop_new (); + if (G_UNLIKELY (mainloop == NULL)) { + g_warning ("Failed to create PulseAudio main loop"); + return NULL; + } + + if (app_name != NULL) { + context = pa_context_new ( + pa_threaded_mainloop_get_api (mainloop), + app_name); + } else { + gchar *name = pulse_connection_get_name (); + + context = pa_context_new ( + pa_threaded_mainloop_get_api (mainloop), + name); + + g_free (name); + } + + if (G_UNLIKELY (context == NULL)) { + g_warning ("Failed to create PulseAudio context"); + + pa_threaded_mainloop_free (mainloop); + return NULL; + } + + connection = g_object_new (MATE_MIXER_TYPE_PULSE_CONNECTION, + "server", server, + "reconnect", TRUE, + NULL); + + connection->priv->mainloop = mainloop; + connection->priv->context = context; + + return connection; +} + +gboolean +mate_mixer_pulse_connection_connect (MateMixerPulseConnection *connection) +{ + int ret; + pa_operation *o; + + g_return_val_if_fail (MATE_MIXER_IS_PULSE_CONNECTION (connection), FALSE); + + if (connection->priv->connected) + return TRUE; + + /* Initiate a connection, this call does not guarantee the connection + * to be established and usable */ + ret = pa_context_connect (connection->priv->context, NULL, PA_CONTEXT_NOFLAGS, NULL); + if (ret < 0) { + g_warning ("Failed to connect to PulseAudio server: %s", pa_strerror (ret)); + return FALSE; + } + + pa_threaded_mainloop_lock (connection->priv->mainloop); + + /* Set callback for connection status changes; the callback is not really + * used when connecting the first time, it is only needed to signal + * a status change */ + pa_context_set_state_callback (connection->priv->context, + pulse_connection_state_cb, + connection); + + ret = pa_threaded_mainloop_start (connection->priv->mainloop); + if (ret < 0) { + g_warning ("Failed to start PulseAudio main loop: %s", pa_strerror (ret)); + + pa_context_disconnect (connection->priv->context); + pa_threaded_mainloop_unlock (connection->priv->mainloop); + return FALSE; + } + + while (TRUE) { + /* Wait for a connection state which tells us whether the connection + * has been established or has failed */ + pa_context_state_t state = + pa_context_get_state (connection->priv->context); + + if (state == PA_CONTEXT_READY) + break; + + if (state == PA_CONTEXT_FAILED || + state == PA_CONTEXT_TERMINATED) { + g_warning ("Failed to connect to PulseAudio server: %s", + pa_strerror (pa_context_errno (connection->priv->context))); + + pa_context_disconnect (connection->priv->context); + pa_threaded_mainloop_unlock (connection->priv->mainloop); + return FALSE; + } + pa_threaded_mainloop_wait (connection->priv->mainloop); + } + + pa_context_set_subscribe_callback (connection->priv->context, + pulse_connection_subscribe_cb, + connection); + + // XXX don't want notifications before the initial lists are downloaded + + o = pa_context_subscribe (connection->priv->context, + PA_SUBSCRIPTION_MASK_CARD | + PA_SUBSCRIPTION_MASK_SINK | + PA_SUBSCRIPTION_MASK_SOURCE | + PA_SUBSCRIPTION_MASK_SINK_INPUT | + PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT, + NULL, NULL); + if (o == NULL) + g_warning ("Failed to subscribe to PulseAudio notifications: %s", + pa_strerror (pa_context_errno (connection->priv->context))); + else + pa_operation_unref (o); + + pa_threaded_mainloop_unlock (connection->priv->mainloop); + + connection->priv->connected = TRUE; + + g_object_notify_by_pspec (G_OBJECT (connection), properties[PROP_CONNECTED]); + return TRUE; +} + +void +mate_mixer_pulse_connection_disconnect (MateMixerPulseConnection *connection) +{ + g_return_val_if_fail (MATE_MIXER_IS_PULSE_CONNECTION (connection), FALSE); + + if (!connection->priv->connected) + return; + + pa_context_disconnect (connection->priv->context); + + connection->priv->connected = FALSE; + + g_object_notify_by_pspec (G_OBJECT (connection), properties[PROP_CONNECTED]); +} + +gboolean +mate_mixer_pulse_connection_get_server_info (MateMixerPulseConnection *connection) +{ + // TODO + return TRUE; +} + +gboolean +mate_mixer_pulse_connection_get_card_list (MateMixerPulseConnection *connection) +{ + pa_operation *o; + gboolean ret; + + g_return_val_if_fail (MATE_MIXER_IS_PULSE_CONNECTION (connection), FALSE); + + pa_threaded_mainloop_lock (connection->priv->mainloop); + + o = pa_context_get_card_info_list ( + connection->priv->context, + pulse_connection_card_info_cb, + connection); + + ret = pulse_connection_process_operation (connection, o); + + pa_threaded_mainloop_unlock (connection->priv->mainloop); + return ret; +} + +gboolean +mate_mixer_pulse_connection_get_sink_list (MateMixerPulseConnection *connection) +{ + pa_operation *o; + gboolean ret; + + g_return_val_if_fail (MATE_MIXER_IS_PULSE_CONNECTION (connection), FALSE); + + pa_threaded_mainloop_lock (connection->priv->mainloop); + + o = pa_context_get_sink_info_list ( + connection->priv->context, + pulse_connection_sink_info_cb, + connection); + + ret = pulse_connection_process_operation (connection, o); + + pa_threaded_mainloop_unlock (connection->priv->mainloop); + return ret; +} + +gboolean +mate_mixer_pulse_connection_get_sink_input_list (MateMixerPulseConnection *connection) +{ + pa_operation *o; + gboolean ret; + + g_return_val_if_fail (MATE_MIXER_IS_PULSE_CONNECTION (connection), FALSE); + + pa_threaded_mainloop_lock (connection->priv->mainloop); + + o = pa_context_get_sink_input_info_list ( + connection->priv->context, + pulse_connection_sink_input_info_cb, + connection); + + ret = pulse_connection_process_operation (connection, o); + + pa_threaded_mainloop_unlock (connection->priv->mainloop); + return ret; +} + +gboolean +mate_mixer_pulse_connection_get_source_list (MateMixerPulseConnection *connection) +{ + pa_operation *o; + gboolean ret; + + g_return_val_if_fail (MATE_MIXER_IS_PULSE_CONNECTION (connection), FALSE); + + pa_threaded_mainloop_lock (connection->priv->mainloop); + + o = pa_context_get_source_info_list ( + connection->priv->context, + pulse_connection_source_info_cb, + connection); + + ret = pulse_connection_process_operation (connection, o); + + pa_threaded_mainloop_unlock (connection->priv->mainloop); + return ret; +} + +gboolean +mate_mixer_pulse_connection_get_source_output_list (MateMixerPulseConnection *connection) +{ + pa_operation *o; + gboolean ret; + + g_return_val_if_fail (MATE_MIXER_IS_PULSE_CONNECTION (connection), FALSE); + + pa_threaded_mainloop_lock (connection->priv->mainloop); + + o = pa_context_get_source_output_info_list ( + connection->priv->context, + pulse_connection_source_output_info_cb, + connection); + + ret = pulse_connection_process_operation (connection, o); + + pa_threaded_mainloop_unlock (connection->priv->mainloop); + return ret; +} + +gboolean +mate_mixer_pulse_connection_set_card_profile (MateMixerPulseConnection *connection, + const gchar *card, + const gchar *profile) +{ + pa_operation *o; + gboolean ret; + + g_return_val_if_fail (MATE_MIXER_IS_PULSE_CONNECTION (connection), FALSE); + + pa_threaded_mainloop_lock (connection->priv->mainloop); + + o = pa_context_set_card_profile_by_name ( + connection->priv->context, + card, + profile, + NULL, NULL); + + // XXX maybe shouldn't wait for the completion + + ret = pulse_connection_process_operation (connection, o); + + pa_threaded_mainloop_unlock (connection->priv->mainloop); + return ret; +} + +gboolean +mate_mixer_pulse_connection_set_sink_mute (MateMixerPulseConnection *connection, + guint32 index, + gboolean mute) +{ + pa_operation *o; + gboolean ret; + + g_return_val_if_fail (MATE_MIXER_IS_PULSE_CONNECTION (connection), FALSE); + + pa_threaded_mainloop_lock (connection->priv->mainloop); + + o = pa_context_set_sink_mute_by_index ( + connection->priv->context, + index, + (int) mute, + NULL, NULL); + + // XXX maybe shouldn't wait for the completion + + ret = pulse_connection_process_operation (connection, o); + + pa_threaded_mainloop_unlock (connection->priv->mainloop); + return ret; +} + +static gboolean +pulse_connection_process_operation (MateMixerPulseConnection *connection, + pa_operation *o) +{ + if (o == NULL) { + g_warning ("Failed to process PulseAudio operation: %s", + pa_strerror (pa_context_errno (connection->priv->context))); + + return FALSE; + } + + while (pa_operation_get_state (o) == PA_OPERATION_RUNNING) + pa_threaded_mainloop_wait (connection->priv->mainloop); + + pa_operation_unref (o); + return TRUE; +} + +static gchar * +pulse_connection_get_name (void) +{ + const char *name_app; + char name_buf[256]; + + /* Inspired by GStreamer's pulse plugin */ + name_app = g_get_application_name (); + if (name_app != NULL) + return g_strdup (name_app); + + if (pa_get_binary_name (name_buf, sizeof (name_buf)) != NULL) + return g_strdup (name_buf); + + return g_strdup_printf ("libmatemixer-%lu", (gulong) getpid ()); +} + +static void +pulse_connection_state_cb (pa_context *c, void *userdata) +{ + MateMixerPulseConnection *connection; + pa_context_state_t state; + + connection = MATE_MIXER_PULSE_CONNECTION (userdata); + + state = pa_context_get_state (c); + switch (state) { + case PA_CONTEXT_READY: + /* The connection is established, the context is ready to + * execute operations. */ + if (!connection->priv->connected) { + connection->priv->connected = TRUE; + + g_object_notify_by_pspec ( + G_OBJECT (connection), + properties[PROP_CONNECTED]); + } + break; + + case PA_CONTEXT_TERMINATED: + /* The connection was terminated cleanly. */ + if (connection->priv->connected) { + connection->priv->connected = FALSE; + + g_object_notify_by_pspec ( + G_OBJECT (connection), + properties[PROP_CONNECTED]); + + pa_context_disconnect (connection->priv->context); + } + break; + + case PA_CONTEXT_FAILED: + break; + + default: + break; + } + + pa_threaded_mainloop_signal (connection->priv->mainloop, 0); +} + +static void +pulse_connection_subscribe_cb (pa_context *c, + pa_subscription_event_type_t t, + uint32_t idx, + void *userdata) +{ + // TODO +} + +static void +pulse_connection_card_info_cb (pa_context *c, + const pa_card_info *info, + int eol, + void *userdata) +{ + MateMixerPulseConnection *connection; + + connection = MATE_MIXER_PULSE_CONNECTION (userdata); + + if (!eol) + g_signal_emit (G_OBJECT (connection), + signals[LIST_ITEM_CARD], + 0, + info); + + pa_threaded_mainloop_signal (connection->priv->mainloop, 0); +} + +static void +pulse_connection_sink_info_cb (pa_context *c, + const pa_sink_info *info, + int eol, + void *userdata) +{ + MateMixerPulseConnection *connection; + + connection = MATE_MIXER_PULSE_CONNECTION (userdata); + + if (!eol) + g_signal_emit (G_OBJECT (connection), + signals[LIST_ITEM_SINK], + 0, + info); + + pa_threaded_mainloop_signal (connection->priv->mainloop, 0); +} + +static void +pulse_connection_sink_input_info_cb (pa_context *c, + const pa_sink_input_info *info, + int eol, + void *userdata) +{ + MateMixerPulseConnection *connection; + + connection = MATE_MIXER_PULSE_CONNECTION (userdata); + + if (!eol) + g_signal_emit (G_OBJECT (connection), + signals[LIST_ITEM_SINK_INPUT], + 0, + info); + + pa_threaded_mainloop_signal (connection->priv->mainloop, 0); +} + +static void +pulse_connection_source_info_cb (pa_context *c, + const pa_source_info *info, + int eol, + void *userdata) +{ + MateMixerPulseConnection *connection; + + connection = MATE_MIXER_PULSE_CONNECTION (userdata); + + if (!eol) + g_signal_emit (G_OBJECT (connection), + signals[LIST_ITEM_SOURCE], + 0, + info); + + pa_threaded_mainloop_signal (connection->priv->mainloop, 0); +} + +static void +pulse_connection_source_output_info_cb (pa_context *c, + const pa_source_output_info *info, + int eol, + void *userdata) +{ + MateMixerPulseConnection *connection; + + connection = MATE_MIXER_PULSE_CONNECTION (userdata); + + if (!eol) + g_signal_emit (G_OBJECT (connection), + signals[LIST_ITEM_SOURCE_OUTPUT], + 0, + info); + + pa_threaded_mainloop_signal (connection->priv->mainloop, 0); +} diff --git a/backends/pulse/pulse-connection.h b/backends/pulse/pulse-connection.h new file mode 100644 index 0000000..85fd0b7 --- /dev/null +++ b/backends/pulse/pulse-connection.h @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2014 Michal Ratajsky + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the licence, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef MATEMIXER_PULSE_CONNECTION_H +#define MATEMIXER_PULSE_CONNECTION_H + +#include +#include + +#include + +G_BEGIN_DECLS + +#define MATE_MIXER_TYPE_PULSE_CONNECTION \ + (mate_mixer_pulse_connection_get_type ()) +#define MATE_MIXER_PULSE_CONNECTION(o) \ + (G_TYPE_CHECK_INSTANCE_CAST ((o), MATE_MIXER_TYPE_PULSE_CONNECTION, MateMixerPulseConnection)) +#define MATE_MIXER_IS_PULSE_CONNECTION(o) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((o), MATE_MIXER_TYPE_PULSE_CONNECTION)) +#define MATE_MIXER_PULSE_CONNECTION_CLASS(k) \ + (G_TYPE_CHECK_CLASS_CAST ((k), MATE_MIXER_TYPE_PULSE_CONNECTION, MateMixerPulseConnectionClass)) +#define MATE_MIXER_IS_PULSE_CONNECTION_CLASS(k) \ + (G_TYPE_CLASS_CHECK_CLASS_TYPE ((k), MATE_MIXER_TYPE_PULSE_CONNECTION)) +#define MATE_MIXER_PULSE_CONNECTION_GET_CLASS(o) \ + (G_TYPE_INSTANCE_GET_CLASS ((o), MATE_MIXER_TYPE_PULSE_CONNECTION, MateMixerPulseConnectionClass)) + +typedef struct _MateMixerPulseConnection MateMixerPulseConnection; +typedef struct _MateMixerPulseConnectionClass MateMixerPulseConnectionClass; +typedef struct _MateMixerPulseConnectionPrivate MateMixerPulseConnectionPrivate; + +struct _MateMixerPulseConnection +{ + GObject parent; + + MateMixerPulseConnectionPrivate *priv; +}; + +struct _MateMixerPulseConnectionClass +{ + GObjectClass parent; + + void (*disconnected) (MateMixerPulseConnection *connection); + void (*reconnected) (MateMixerPulseConnection *connection); + + void (*list_item_card) (MateMixerPulseConnection *connection, + const pa_card_info *info); + void (*list_item_sink) (MateMixerPulseConnection *connection, + const pa_sink_info *info); + void (*list_item_sink_input) (MateMixerPulseConnection *connection, + const pa_sink_input_info *info); + void (*list_item_source) (MateMixerPulseConnection *connection, + const pa_source_info *info); + void (*list_item_source_output) (MateMixerPulseConnection *connection, + const pa_source_output_info *info); +}; + +GType mate_mixer_pulse_connection_get_type (void) G_GNUC_CONST; + +MateMixerPulseConnection *mate_mixer_pulse_connection_new (const gchar *server, + const gchar *app_name); + +gboolean mate_mixer_pulse_connection_connect (MateMixerPulseConnection *connection); + +void mate_mixer_pulse_connection_disconnect (MateMixerPulseConnection *connection); + +gboolean mate_mixer_pulse_connection_get_server_info (MateMixerPulseConnection *connection); + +gboolean mate_mixer_pulse_connection_get_card_list (MateMixerPulseConnection *connection); + +gboolean mate_mixer_pulse_connection_get_sink_list (MateMixerPulseConnection *connection); + +gboolean mate_mixer_pulse_connection_get_sink_input_list (MateMixerPulseConnection *connection); + +gboolean mate_mixer_pulse_connection_get_source_list (MateMixerPulseConnection *connection); + +gboolean mate_mixer_pulse_connection_get_source_output_list (MateMixerPulseConnection *connection); + +gboolean mate_mixer_pulse_connection_set_card_profile (MateMixerPulseConnection *connection, + const gchar *device, + const gchar *profile); + +gboolean mate_mixer_pulse_connection_set_sink_mute (MateMixerPulseConnection *connection, + guint32 index, + gboolean mute); + +G_END_DECLS + +#endif /* MATEMIXER_PULSE_CONNECTION_H */ diff --git a/backends/pulse/pulse-device.c b/backends/pulse/pulse-device.c index dbc287c..a411d7f 100644 --- a/backends/pulse/pulse-device.c +++ b/backends/pulse/pulse-device.c @@ -19,30 +19,31 @@ #include #include -#include -#include +#include +#include #include +#include "pulse-connection.h" #include "pulse-device.h" struct _MateMixerPulseDevicePrivate { - guint32 index; - GList *profiles; - GList *ports; - gchar *identifier; - gchar *name; - gchar *icon; - - MateMixerDeviceProfile *active_profile; + guint32 index; + gchar *name; + gchar *description; + GList *profiles; + GList *ports; + gchar *icon; + MateMixerProfile *profile; + MateMixerPulseConnection *connection; }; enum { PROP_0, - PROP_IDENTIFIER, PROP_NAME, + PROP_DESCRIPTION, PROP_ICON, PROP_ACTIVE_PROFILE, N_PROPERTIES @@ -57,9 +58,12 @@ G_DEFINE_TYPE_WITH_CODE (MateMixerPulseDevice, mate_mixer_pulse_device, G_TYPE_O static void mate_mixer_device_interface_init (MateMixerDeviceInterface *iface) { - iface->list_tracks = mate_mixer_pulse_device_list_tracks; - iface->get_ports = mate_mixer_pulse_device_get_ports; - iface->get_profiles = mate_mixer_pulse_device_get_profiles; + iface->get_name = mate_mixer_pulse_device_get_name; + iface->get_description = mate_mixer_pulse_device_get_description; + iface->get_icon = mate_mixer_pulse_device_get_icon; + iface->list_streams = mate_mixer_pulse_device_list_streams; + iface->list_ports = mate_mixer_pulse_device_list_ports; + iface->list_profiles = mate_mixer_pulse_device_list_profiles; iface->get_active_profile = mate_mixer_pulse_device_get_active_profile; iface->set_active_profile = mate_mixer_pulse_device_set_active_profile; } @@ -67,10 +71,9 @@ mate_mixer_device_interface_init (MateMixerDeviceInterface *iface) static void mate_mixer_pulse_device_init (MateMixerPulseDevice *device) { - device->priv = G_TYPE_INSTANCE_GET_PRIVATE ( - device, - MATE_MIXER_TYPE_PULSE_DEVICE, - MateMixerPulseDevicePrivate); + device->priv = G_TYPE_INSTANCE_GET_PRIVATE (device, + MATE_MIXER_TYPE_PULSE_DEVICE, + MateMixerPulseDevicePrivate); } static void @@ -84,17 +87,17 @@ mate_mixer_pulse_device_get_property (GObject *object, device = MATE_MIXER_PULSE_DEVICE (object); switch (param_id) { - case PROP_IDENTIFIER: - g_value_set_string (value, device->priv->identifier); - break; case PROP_NAME: g_value_set_string (value, device->priv->name); break; + case PROP_DESCRIPTION: + g_value_set_string (value, device->priv->description); + break; case PROP_ICON: g_value_set_string (value, device->priv->icon); break; case PROP_ACTIVE_PROFILE: - g_value_set_object (value, device->priv->active_profile); + g_value_set_object (value, device->priv->profile); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); @@ -113,20 +116,15 @@ mate_mixer_pulse_device_set_property (GObject *object, device = MATE_MIXER_PULSE_DEVICE (object); switch (param_id) { - case PROP_IDENTIFIER: - device->priv->identifier = g_strdup (g_value_get_string (value)); - break; case PROP_NAME: device->priv->name = g_strdup (g_value_get_string (value)); break; + case PROP_DESCRIPTION: + device->priv->description = g_strdup (g_value_get_string (value)); + break; case PROP_ICON: device->priv->icon = g_strdup (g_value_get_string (value)); break; - case PROP_ACTIVE_PROFILE: - mate_mixer_pulse_device_set_active_profile ( - MATE_MIXER_DEVICE (device), - g_value_get_object (value)); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); break; @@ -134,24 +132,38 @@ mate_mixer_pulse_device_set_property (GObject *object, } static void -mate_mixer_pulse_device_finalize (GObject *object) +mate_mixer_pulse_device_dispose (GObject *object) { MateMixerPulseDevice *device; device = MATE_MIXER_PULSE_DEVICE (object); - g_free (device->priv->identifier); - g_free (device->priv->name); - g_free (device->priv->icon); - - if (device->priv->profiles != NULL) + if (device->priv->profiles != NULL) { g_list_free_full (device->priv->profiles, g_object_unref); + device->priv->profiles = NULL; + } - if (device->priv->ports != NULL) + if (device->priv->ports != NULL) { g_list_free_full (device->priv->ports, g_object_unref); + device->priv->ports = NULL; + } + + g_clear_object (&device->priv->profile); + g_clear_object (&device->priv->connection); + + G_OBJECT_CLASS (mate_mixer_pulse_device_parent_class)->dispose (object); +} + +static void +mate_mixer_pulse_device_finalize (GObject *object) +{ + MateMixerPulseDevice *device; - if (device->priv->active_profile != NULL) - g_object_unref (device->priv->active_profile); + device = MATE_MIXER_PULSE_DEVICE (object); + + g_free (device->priv->name); + g_free (device->priv->description); + g_free (device->priv->icon); G_OBJECT_CLASS (mate_mixer_pulse_device_parent_class)->finalize (object); } @@ -162,12 +174,13 @@ mate_mixer_pulse_device_class_init (MateMixerPulseDeviceClass *klass) GObjectClass *object_class; object_class = G_OBJECT_CLASS (klass); + object_class->dispose = mate_mixer_pulse_device_dispose; object_class->finalize = mate_mixer_pulse_device_finalize; object_class->get_property = mate_mixer_pulse_device_get_property; object_class->set_property = mate_mixer_pulse_device_set_property; - g_object_class_override_property (object_class, PROP_IDENTIFIER, "identifier"); g_object_class_override_property (object_class, PROP_NAME, "name"); + g_object_class_override_property (object_class, PROP_DESCRIPTION, "description"); g_object_class_override_property (object_class, PROP_ICON, "icon"); g_object_class_override_property (object_class, PROP_ACTIVE_PROFILE, "active-profile"); @@ -175,19 +188,19 @@ mate_mixer_pulse_device_class_init (MateMixerPulseDeviceClass *klass) } MateMixerPulseDevice * -mate_mixer_pulse_device_new (const pa_card_info *info) +mate_mixer_pulse_device_new (MateMixerPulseConnection *connection, const pa_card_info *info) { - MateMixerPulseDevice *device; - MateMixerDeviceProfile *active_profile = NULL; - GList *profiles = NULL; - GList *ports = NULL; - guint32 i; + MateMixerPulseDevice *device; + MateMixerProfile *active_profile = NULL; + GList *profiles = NULL; + GList *ports = NULL; + guint32 i; g_return_val_if_fail (info != NULL, NULL); /* Create a list of card profiles */ for (i = 0; i < info->n_profiles; i++) { - MateMixerDeviceProfile *profile; + MateMixerProfile *profile; #if PA_CHECK_VERSION(5, 0, 0) pa_card_profile_info2 *p_info = info->profiles2[i]; @@ -199,9 +212,9 @@ mate_mixer_pulse_device_new (const pa_card_info *info) continue; #else /* The old profile list is an array of structs, not pointers */ - pa_card_profile_info *p_info = &info->profiles[i]; + pa_card_profile_info *p_info = &info->profiles[i]; #endif - profile = mate_mixer_device_profile_new ( + profile = mate_mixer_profile_new ( p_info->name, p_info->description, p_info->priority); @@ -222,28 +235,27 @@ mate_mixer_pulse_device_new (const pa_card_info *info) /* Create a list of card ports */ for (i = 0; i < info->n_ports; i++) { - MateMixerDevicePort *port; - MateMixerDevicePortDirection direction = 0; - MateMixerDevicePortStatus status = 0; - pa_card_port_info *p_info = info->ports[i]; - - if (p_info->direction & PA_DIRECTION_INPUT) - direction |= MATE_MIXER_DEVICE_PORT_DIRECTION_INPUT; - - if (p_info->direction & PA_DIRECTION_OUTPUT) - direction |= MATE_MIXER_DEVICE_PORT_DIRECTION_OUTPUT; + MateMixerPort *port; + MateMixerPortStatus status = MATE_MIXER_PORT_UNKNOWN_STATUS; + pa_card_port_info *p_info = info->ports[i]; #if PA_CHECK_VERSION(2, 0, 0) - if (p_info->available == PA_PORT_AVAILABLE_YES) - status |= MATE_MIXER_DEVICE_PORT_STATUS_AVAILABLE; + switch (p_info->available) { + case PA_PORT_AVAILABLE_YES: + status = MATE_MIXER_PORT_AVAILABLE; + break; + case PA_PORT_AVAILABLE_NO: + status = MATE_MIXER_PORT_UNAVAILABLE; + break; + default: + break; + } #endif - port = mate_mixer_device_port_new ( - p_info->name, - p_info->description, - pa_proplist_gets (p_info->proplist, "device.icon_name"), - p_info->priority, - direction, - status); + port = mate_mixer_port_new (p_info->name, + p_info->description, + pa_proplist_gets (p_info->proplist, "device.icon_name"), + p_info->priority, + status); ports = g_list_prepend (ports, port); } @@ -253,15 +265,21 @@ mate_mixer_pulse_device_new (const pa_card_info *info) ports = g_list_reverse (ports); device = g_object_new (MATE_MIXER_TYPE_PULSE_DEVICE, - "identifier", info->name, - "name", pa_proplist_gets (info->proplist, "device.description"), - "icon", pa_proplist_gets (info->proplist, "device.icon_name"), - "active-profile", active_profile, - NULL); + "name", info->name, + "description", pa_proplist_gets (info->proplist, "device.description"), + "icon", pa_proplist_gets (info->proplist, "device.icon_name"), + NULL); + + if (profiles) { + device->priv->profiles = profiles; + + if (G_LIKELY (active_profile)) + device->priv->profile = g_object_ref (active_profile); + } device->priv->index = info->index; - device->priv->profiles = profiles; device->priv->ports = ports; + device->priv->connection = g_object_ref (connection); return device; } @@ -276,45 +294,104 @@ mate_mixer_pulse_device_update (MateMixerPulseDevice *device, const pa_card_info return TRUE; } +MateMixerPulseConnection * +mate_mixer_pulse_device_get_connection (MateMixerPulseDevice *device) +{ + g_return_val_if_fail (MATE_MIXER_IS_PULSE_DEVICE (device), NULL); + + return device->priv->connection; +} + +guint32 +mate_mixer_pulse_device_get_index (MateMixerPulseDevice *device) +{ + g_return_val_if_fail (MATE_MIXER_IS_PULSE_DEVICE (device), 0); + + return device->priv->index; +} + +const gchar * +mate_mixer_pulse_device_get_name (MateMixerDevice *device) +{ + g_return_val_if_fail (MATE_MIXER_IS_PULSE_DEVICE (device), NULL); + + return MATE_MIXER_PULSE_DEVICE (device)->priv->name; +} + +const gchar * +mate_mixer_pulse_device_get_description (MateMixerDevice *device) +{ + g_return_val_if_fail (MATE_MIXER_IS_PULSE_DEVICE (device), NULL); + + return MATE_MIXER_PULSE_DEVICE (device)->priv->description; +} + +const gchar * +mate_mixer_pulse_device_get_icon (MateMixerDevice *device) +{ + g_return_val_if_fail (MATE_MIXER_IS_PULSE_DEVICE (device), NULL); + + return MATE_MIXER_PULSE_DEVICE (device)->priv->icon; +} + const GList * -mate_mixer_pulse_device_list_tracks (MateMixerDevice *device) +mate_mixer_pulse_device_list_streams (MateMixerDevice *device) { // TODO return NULL; } const GList * -mate_mixer_pulse_device_get_ports (MateMixerDevice *device) +mate_mixer_pulse_device_list_ports (MateMixerDevice *device) { g_return_val_if_fail (MATE_MIXER_IS_PULSE_DEVICE (device), NULL); - return MATE_MIXER_PULSE_DEVICE (device)->priv->ports; + return (const GList *) MATE_MIXER_PULSE_DEVICE (device)->priv->ports; } const GList * -mate_mixer_pulse_device_get_profiles (MateMixerDevice *device) +mate_mixer_pulse_device_list_profiles (MateMixerDevice *device) { g_return_val_if_fail (MATE_MIXER_IS_PULSE_DEVICE (device), NULL); - return MATE_MIXER_PULSE_DEVICE (device)->priv->profiles; + return (const GList *) MATE_MIXER_PULSE_DEVICE (device)->priv->profiles; } -MateMixerDeviceProfile * +MateMixerProfile * mate_mixer_pulse_device_get_active_profile (MateMixerDevice *device) { g_return_val_if_fail (MATE_MIXER_IS_PULSE_DEVICE (device), NULL); - return MATE_MIXER_PULSE_DEVICE (device)->priv->active_profile; + return MATE_MIXER_PULSE_DEVICE (device)->priv->profile; } gboolean -mate_mixer_pulse_device_set_active_profile (MateMixerDevice *device, - MateMixerDeviceProfile *profile) +mate_mixer_pulse_device_set_active_profile (MateMixerDevice *device, const gchar *name) { + gboolean ret; + MateMixerPulseDevicePrivate *priv; + g_return_val_if_fail (MATE_MIXER_IS_PULSE_DEVICE (device), FALSE); - g_return_val_if_fail (MATE_MIXER_IS_DEVICE_PROFILE (profile), FALSE); + g_return_val_if_fail (name != NULL, FALSE); - // TODO - // pa_context_set_card_profile_by_index () - return TRUE; + priv = MATE_MIXER_PULSE_DEVICE (device)->priv; + ret = mate_mixer_pulse_connection_set_card_profile (priv->connection, + priv->name, + name); + + // XXX decide to either confirm the change during the connection call or + // wait for a notification from Pulse +/* + if (ret) { + if (priv->profile) + g_object_unref (priv->profile); + + priv->profile = g_object_ref (profile); + + g_object_notify_by_pspec ( + G_OBJECT (device), + properties[PROP_ACTIVE_PROFILE]); + } +*/ + return ret; } diff --git a/backends/pulse/pulse-device.h b/backends/pulse/pulse-device.h index ab997fe..896b02b 100644 --- a/backends/pulse/pulse-device.h +++ b/backends/pulse/pulse-device.h @@ -22,10 +22,12 @@ #include #include -#include +#include #include +#include "pulse-connection.h" + G_BEGIN_DECLS #define MATE_MIXER_TYPE_PULSE_DEVICE \ @@ -54,26 +56,35 @@ struct _MateMixerPulseDevice struct _MateMixerPulseDeviceClass { - GObjectClass parent; + GObjectClass parent; }; GType mate_mixer_pulse_device_get_type (void) G_GNUC_CONST; -MateMixerPulseDevice *mate_mixer_pulse_device_new (const pa_card_info *info); +MateMixerPulseDevice *mate_mixer_pulse_device_new (MateMixerPulseConnection *connection, + const pa_card_info *info); gboolean mate_mixer_pulse_device_update (MateMixerPulseDevice *device, const pa_card_info *info); +MateMixerPulseConnection *mate_mixer_pulse_device_get_connection (MateMixerPulseDevice *device); + +guint32 mate_mixer_pulse_device_get_index (MateMixerPulseDevice *device); + /* Interface implementation */ -const GList *mate_mixer_pulse_device_list_tracks (MateMixerDevice *device); +const gchar *mate_mixer_pulse_device_get_name (MateMixerDevice *device); +const gchar *mate_mixer_pulse_device_get_description (MateMixerDevice *device); +const gchar *mate_mixer_pulse_device_get_icon (MateMixerDevice *device); + +const GList *mate_mixer_pulse_device_list_streams (MateMixerDevice *device); -const GList *mate_mixer_pulse_device_get_ports (MateMixerDevice *device); -const GList *mate_mixer_pulse_device_get_profiles (MateMixerDevice *device); +const GList *mate_mixer_pulse_device_list_ports (MateMixerDevice *device); +const GList *mate_mixer_pulse_device_list_profiles (MateMixerDevice *device); -MateMixerDeviceProfile *mate_mixer_pulse_device_get_active_profile (MateMixerDevice *device); +MateMixerProfile *mate_mixer_pulse_device_get_active_profile (MateMixerDevice *device); gboolean mate_mixer_pulse_device_set_active_profile (MateMixerDevice *device, - MateMixerDeviceProfile *profile); + const gchar *name); G_END_DECLS diff --git a/backends/pulse/pulse-sink-input.c b/backends/pulse/pulse-sink-input.c new file mode 100644 index 0000000..e69de29 diff --git a/backends/pulse/pulse-sink-input.h b/backends/pulse/pulse-sink-input.h new file mode 100644 index 0000000..e69de29 diff --git a/backends/pulse/pulse-sink.c b/backends/pulse/pulse-sink.c new file mode 100644 index 0000000..64eb4c1 --- /dev/null +++ b/backends/pulse/pulse-sink.c @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2014 Michal Ratajsky + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the licence, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include +#include + +#include +#include + +#include + +#include "pulse-connection.h" +#include "pulse-stream.h" +#include "pulse-sink.h" + +struct _MateMixerPulseSinkPrivate +{ + guint32 index_monitor; +}; + +G_DEFINE_TYPE (MateMixerPulseSink, mate_mixer_pulse_sink, MATE_MIXER_TYPE_PULSE_STREAM); + +static void +mate_mixer_pulse_sink_init (MateMixerPulseSink *sink) +{ + sink->priv = G_TYPE_INSTANCE_GET_PRIVATE (sink, + MATE_MIXER_TYPE_PULSE_SINK, + MateMixerPulseSinkPrivate); +} + +static void +mate_mixer_pulse_sink_class_init (MateMixerPulseSinkClass *klass) +{ + MateMixerPulseStreamClass *stream_class; + + stream_class = MATE_MIXER_PULSE_STREAM_CLASS (klass); + + stream_class->set_volume = mate_mixer_pulse_sink_set_volume; + stream_class->set_mute = mate_mixer_pulse_sink_set_mute; + + g_type_class_add_private (G_OBJECT (klass), sizeof (MateMixerPulseSinkPrivate)); +} + +MateMixerPulseStream * +mate_mixer_pulse_sink_new (MateMixerPulseConnection *connection, const pa_sink_info *info) +{ + MateMixerPulseStream *stream; + GList *ports = NULL; + int i; + + for (i = 0; i < info->n_ports; i++) { + MateMixerPort *port; + MateMixerPortStatus status = MATE_MIXER_PORT_UNKNOWN_STATUS; + pa_sink_port_info *p_info = info->ports[i]; + +#if PA_CHECK_VERSION(2, 0, 0) + switch (p_info->available) { + case PA_PORT_AVAILABLE_YES: + status = MATE_MIXER_PORT_AVAILABLE; + break; + case PA_PORT_AVAILABLE_NO: + status = MATE_MIXER_PORT_UNAVAILABLE; + break; + default: + break; + } +#endif + port = mate_mixer_port_new (p_info->name, + p_info->description, + NULL, + p_info->priority, + status); + + ports = g_list_prepend (ports, port); + } + + if (ports) + ports = g_list_reverse (ports); + + stream = g_object_new (MATE_MIXER_TYPE_PULSE_STREAM, + "connection", connection, + "index", info->index, + "name", info->name, + "description", info->description, + "channels", info->channel_map.channels, + "mute", info->mute ? TRUE : FALSE, + NULL); + + return stream; +} + +gboolean +mate_mixer_pulse_sink_set_volume (MateMixerStream *stream, guint32 volume) +{ + g_return_val_if_fail (MATE_MIXER_IS_PULSE_STREAM (stream), FALSE); + +/* + return mate_mixer_pulse_connection_set_sink_volume (mate_mixer_pulse_stream_get_connection (MATE_MIXER_PULSE_STREAM (stream)), + volume); +*/ + return TRUE; +} + +gboolean +mate_mixer_pulse_sink_set_mute (MateMixerStream *stream, gboolean mute) +{ + MateMixerPulseStream *pulse_stream; + + g_return_val_if_fail (MATE_MIXER_IS_PULSE_STREAM (stream), FALSE); + + pulse_stream = MATE_MIXER_PULSE_STREAM (stream); + + return mate_mixer_pulse_connection_set_sink_mute (mate_mixer_pulse_stream_get_connection (pulse_stream), + mate_mixer_pulse_stream_get_index (pulse_stream), + mute); +} diff --git a/backends/pulse/pulse-sink.h b/backends/pulse/pulse-sink.h new file mode 100644 index 0000000..ef2608f --- /dev/null +++ b/backends/pulse/pulse-sink.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2014 Michal Ratajsky + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the licence, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef MATEMIXER_PULSE_SINK_H +#define MATEMIXER_PULSE_SINK_H + +#include +#include + +#include + +#include + +G_BEGIN_DECLS + +#define MATE_MIXER_TYPE_PULSE_SINK \ + (mate_mixer_pulse_sink_get_type ()) +#define MATE_MIXER_PULSE_SINK(o) \ + (G_TYPE_CHECK_INSTANCE_CAST ((o), MATE_MIXER_TYPE_PULSE_SINK, MateMixerPulseSink)) +#define MATE_MIXER_IS_PULSE_SINK(o) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((o), MATE_MIXER_TYPE_PULSE_SINK)) +#define MATE_MIXER_PULSE_SINK_CLASS(k) \ + (G_TYPE_CHECK_CLASS_CAST ((k), MATE_MIXER_TYPE_PULSE_SINK, MateMixerPulseSinkClass)) +#define MATE_MIXER_IS_PULSE_SINK_CLASS(k) \ + (G_TYPE_CLASS_CHECK_CLASS_TYPE ((k), MATE_MIXER_TYPE_PULSE_SINK)) +#define MATE_MIXER_PULSE_SINK_GET_CLASS(o) \ + (G_TYPE_INSTANCE_GET_CLASS ((o), MATE_MIXER_TYPE_PULSE_SINK, MateMixerPulseSinkClass)) + +typedef struct _MateMixerPulseSink MateMixerPulseSink; +typedef struct _MateMixerPulseSinkClass MateMixerPulseSinkClass; +typedef struct _MateMixerPulseSinkPrivate MateMixerPulseSinkPrivate; + +struct _MateMixerPulseSink +{ + GObject parent; + + MateMixerPulseSinkPrivate *priv; +}; + +struct _MateMixerPulseSinkClass +{ + GObjectClass parent; +}; + +GType mate_mixer_pulse_sink_get_type (void) G_GNUC_CONST; + +MateMixerPulseStream *mate_mixer_pulse_sink_new (MateMixerPulseConnection *connection, + const pa_sink_info *info); + +gboolean mate_mixer_pulse_sink_set_volume (MateMixerStream *stream, guint32 volume); +gboolean mate_mixer_pulse_sink_set_mute (MateMixerStream *stream, gboolean mute); + +G_END_DECLS + +#endif /* MATEMIXER_PULSE_SINK_H */ diff --git a/backends/pulse/pulse-source-output.c b/backends/pulse/pulse-source-output.c new file mode 100644 index 0000000..e69de29 diff --git a/backends/pulse/pulse-source-output.h b/backends/pulse/pulse-source-output.h new file mode 100644 index 0000000..e69de29 diff --git a/backends/pulse/pulse-source.c b/backends/pulse/pulse-source.c new file mode 100644 index 0000000..e69de29 diff --git a/backends/pulse/pulse-source.h b/backends/pulse/pulse-source.h new file mode 100644 index 0000000..e69de29 diff --git a/backends/pulse/pulse-stream.c b/backends/pulse/pulse-stream.c new file mode 100644 index 0000000..a9e01d1 --- /dev/null +++ b/backends/pulse/pulse-stream.c @@ -0,0 +1,259 @@ +/* + * Copyright (C) 2014 Michal Ratajsky + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the licence, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include +#include + +#include +#include + +#include + +#include "pulse-connection.h" +#include "pulse-stream.h" + +struct _MateMixerPulseStreamPrivate +{ + guint32 index; + gchar *name; + gchar *description; + gchar *icon; + guint channels; + gboolean mute; + GList *ports; + MateMixerPort *port; + MateMixerPulseConnection *connection; +}; + +enum +{ + PROP_0, + PROP_INDEX, + PROP_NAME, + PROP_DESCRIPTION, + PROP_ICON, + PROP_CHANNELS, + PROP_VOLUME, + PROP_MUTE, + N_PROPERTIES +}; + +static void mate_mixer_stream_interface_init (MateMixerStreamInterface *iface); +static void mate_mixer_pulse_stream_class_init (MateMixerPulseStreamClass *klass); +static void mate_mixer_pulse_stream_init (MateMixerPulseStream *stream); +static void mate_mixer_pulse_stream_dispose (GObject *object); +static void mate_mixer_pulse_stream_finalize (GObject *object); + +G_DEFINE_ABSTRACT_TYPE_WITH_CODE (MateMixerPulseStream, mate_mixer_pulse_stream, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (MATE_MIXER_TYPE_STREAM, + mate_mixer_stream_interface_init)) + +static void +mate_mixer_stream_interface_init (MateMixerStreamInterface *iface) +{ + iface->get_name = mate_mixer_pulse_stream_get_name; + iface->get_description = mate_mixer_pulse_stream_get_description; + iface->get_icon = mate_mixer_pulse_stream_get_icon; + iface->list_ports = mate_mixer_pulse_stream_list_ports; +} + +static void +mate_mixer_pulse_stream_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec) +{ + MateMixerPulseStream *stream; + + stream = MATE_MIXER_PULSE_STREAM (object); + + switch (param_id) { + case PROP_NAME: + g_value_set_string (value, stream->priv->name); + break; + case PROP_DESCRIPTION: + g_value_set_string (value, stream->priv->description); + break; + case PROP_ICON: + g_value_set_string (value, stream->priv->icon); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} + +static void +mate_mixer_pulse_stream_set_property (GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec) +{ + MateMixerPulseStream *stream; + + stream = MATE_MIXER_PULSE_STREAM (object); + + switch (param_id) { + case PROP_NAME: + stream->priv->name = g_strdup (g_value_get_string (value)); + break; + case PROP_DESCRIPTION: + stream->priv->description = g_strdup (g_value_get_string (value)); + break; + case PROP_ICON: + stream->priv->icon = g_strdup (g_value_get_string (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} + +static void +mate_mixer_pulse_stream_class_init (MateMixerPulseStreamClass *klass) +{ + GObjectClass *object_class; + + object_class = G_OBJECT_CLASS (klass); + object_class->dispose = mate_mixer_pulse_stream_dispose; + object_class->finalize = mate_mixer_pulse_stream_finalize; + object_class->get_property = mate_mixer_pulse_stream_get_property; + object_class->set_property = mate_mixer_pulse_stream_set_property; + + g_object_class_override_property (object_class, PROP_NAME, "name"); + g_object_class_override_property (object_class, PROP_DESCRIPTION, "description"); + g_object_class_override_property (object_class, PROP_ICON, "icon"); + + g_type_class_add_private (object_class, sizeof (MateMixerPulseStreamPrivate)); +} + +static void +mate_mixer_pulse_stream_init (MateMixerPulseStream *stream) +{ + stream->priv = G_TYPE_INSTANCE_GET_PRIVATE ( + stream, + MATE_MIXER_TYPE_PULSE_STREAM, + MateMixerPulseStreamPrivate); +} + +static void +mate_mixer_pulse_stream_dispose (GObject *object) +{ + MateMixerPulseStream *stream; + + stream = MATE_MIXER_PULSE_STREAM (object); + + if (stream->priv->ports) { + g_list_free_full (stream->priv->ports, g_object_unref); + stream->priv->ports = NULL; + } + g_clear_object (&stream->priv->connection); + + G_OBJECT_CLASS (mate_mixer_pulse_stream_parent_class)->dispose (object); +} + +static void +mate_mixer_pulse_stream_finalize (GObject *object) +{ + MateMixerPulseStream *stream; + + stream = MATE_MIXER_PULSE_STREAM (object); + + g_free (stream->priv->name); + g_free (stream->priv->description); + g_free (stream->priv->icon); + + G_OBJECT_CLASS (mate_mixer_pulse_stream_parent_class)->finalize (object); +} + +MateMixerPulseConnection * +mate_mixer_pulse_stream_get_connection (MateMixerPulseStream *stream) +{ + g_return_val_if_fail (MATE_MIXER_IS_PULSE_STREAM (stream), NULL); + + return stream->priv->connection; +} + +guint32 +mate_mixer_pulse_stream_get_index (MateMixerPulseStream *stream) +{ + g_return_val_if_fail (MATE_MIXER_IS_PULSE_STREAM (stream), FALSE); + + return stream->priv->index; +} + +const gchar * +mate_mixer_pulse_stream_get_name (MateMixerStream *stream) +{ + g_return_val_if_fail (MATE_MIXER_IS_PULSE_STREAM (stream), FALSE); + + return MATE_MIXER_PULSE_STREAM (stream)->priv->name; +} + +const gchar * +mate_mixer_pulse_stream_get_description (MateMixerStream *stream) +{ + g_return_val_if_fail (MATE_MIXER_IS_PULSE_STREAM (stream), FALSE); + + return MATE_MIXER_PULSE_STREAM (stream)->priv->description; +} + +const gchar * +mate_mixer_pulse_stream_get_icon (MateMixerStream *stream) +{ + g_return_val_if_fail (MATE_MIXER_IS_PULSE_STREAM (stream), FALSE); + + return MATE_MIXER_PULSE_STREAM (stream)->priv->icon; +} + +MateMixerPort * +mate_mixer_pulse_stream_get_active_port (MateMixerStream *stream) +{ + g_return_val_if_fail (MATE_MIXER_IS_PULSE_STREAM (stream), FALSE); + + return MATE_MIXER_PULSE_STREAM (stream)->priv->port; +} + +const GList * +mate_mixer_pulse_stream_list_ports (MateMixerStream *stream) +{ + g_return_val_if_fail (MATE_MIXER_IS_PULSE_STREAM (stream), FALSE); + + return MATE_MIXER_PULSE_STREAM (stream)->priv->ports; +} + +gboolean +mate_mixer_pulse_stream_set_volume (MateMixerStream *stream, guint32 volume) +{ + g_return_val_if_fail (MATE_MIXER_IS_PULSE_STREAM (stream), FALSE); + + return MATE_MIXER_PULSE_STREAM_GET_CLASS (stream)->set_volume (stream, volume); +} + +gboolean +mate_mixer_pulse_stream_set_mute (MateMixerStream *stream, gboolean mute) +{ + g_return_val_if_fail (MATE_MIXER_IS_PULSE_STREAM (stream), FALSE); + + return MATE_MIXER_PULSE_STREAM_GET_CLASS (stream)->set_mute (stream, mute); +} + +gboolean +mate_mixer_pulse_stream_set_active_port (MateMixerStream *stream, MateMixerPort *port) +{ + return TRUE; +} diff --git a/backends/pulse/pulse-stream.h b/backends/pulse/pulse-stream.h new file mode 100644 index 0000000..3d3ee78 --- /dev/null +++ b/backends/pulse/pulse-stream.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2014 Michal Ratajsky + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the licence, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef MATEMIXER_PULSE_STREAM_H +#define MATEMIXER_PULSE_STREAM_H + +#include +#include + +#include +#include + +#include + +#include "pulse-connection.h" + +G_BEGIN_DECLS + +#define MATE_MIXER_TYPE_PULSE_STREAM \ + (mate_mixer_pulse_stream_get_type ()) +#define MATE_MIXER_PULSE_STREAM(o) \ + (G_TYPE_CHECK_INSTANCE_CAST ((o), MATE_MIXER_TYPE_PULSE_STREAM, MateMixerPulseStream)) +#define MATE_MIXER_IS_PULSE_STREAM(o) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((o), MATE_MIXER_TYPE_PULSE_STREAM)) +#define MATE_MIXER_PULSE_STREAM_CLASS(k) \ + (G_TYPE_CHECK_CLASS_CAST ((k), MATE_MIXER_TYPE_PULSE_STREAM, MateMixerPulseStreamClass)) +#define MATE_MIXER_IS_PULSE_STREAM_CLASS(k) \ + (G_TYPE_CLASS_CHECK_CLASS_TYPE ((k), MATE_MIXER_TYPE_PULSE_STREAM)) +#define MATE_MIXER_PULSE_STREAM_GET_CLASS(o) \ + (G_TYPE_INSTANCE_GET_CLASS ((o), MATE_MIXER_TYPE_PULSE_STREAM, MateMixerPulseStreamClass)) + +typedef struct _MateMixerPulseStream MateMixerPulseStream; +typedef struct _MateMixerPulseStreamClass MateMixerPulseStreamClass; +typedef struct _MateMixerPulseStreamPrivate MateMixerPulseStreamPrivate; + +struct _MateMixerPulseStream +{ + GObject parent; + + MateMixerPulseStreamPrivate *priv; +}; + +struct _MateMixerPulseStreamClass +{ + GObjectClass parent; + + gboolean (*set_volume) (MateMixerStream *stream, guint32 volume); + gboolean (*set_mute) (MateMixerStream *stream, gboolean mute); +}; + +GType mate_mixer_pulse_stream_get_type (void) G_GNUC_CONST; + +MateMixerPulseConnection * mate_mixer_pulse_stream_get_connection (MateMixerPulseStream *stream); +guint32 mate_mixer_pulse_stream_get_index (MateMixerPulseStream *stream); + +/* Interface implementation */ +const gchar * mate_mixer_pulse_stream_get_name (MateMixerStream *stream); +const gchar * mate_mixer_pulse_stream_get_description (MateMixerStream *stream); +const gchar * mate_mixer_pulse_stream_get_icon (MateMixerStream *stream); + +MateMixerPort * mate_mixer_pulse_stream_get_active_port (MateMixerStream *stream); +gboolean mate_mixer_pulse_stream_set_active_port (MateMixerStream *stream, + MateMixerPort *port); +const GList * mate_mixer_pulse_stream_list_ports (MateMixerStream *stream); +gboolean mate_mixer_pulse_stream_set_mute (MateMixerStream *stream, + gboolean mute); +gboolean mate_mixer_pulse_stream_set_volume (MateMixerStream *stream, + guint32 volume); + +G_END_DECLS + +#endif /* MATEMIXER_PULSE_STREAM_H */ diff --git a/backends/pulse/pulse-track.c b/backends/pulse/pulse-track.c deleted file mode 100644 index e69de29..0000000 diff --git a/backends/pulse/pulse-track.h b/backends/pulse/pulse-track.h deleted file mode 100644 index e69de29..0000000 diff --git a/backends/pulse/pulse.c b/backends/pulse/pulse.c index d306577..59c5935 100644 --- a/backends/pulse/pulse.c +++ b/backends/pulse/pulse.c @@ -17,8 +17,6 @@ #include #include -#include -#include #include #include @@ -27,47 +25,59 @@ #include #include "pulse.h" +#include "pulse-connection.h" #include "pulse-device.h" +#include "pulse-stream.h" +#include "pulse-sink.h" #define BACKEND_NAME "PulseAudio" #define BACKEND_PRIORITY 0 struct _MateMixerPulsePrivate { - pa_threaded_mainloop *mainloop; - pa_context *context; - GHashTable *devices; + GHashTable *devices; + gboolean lists_loaded; + GHashTable *cards; + GHashTable *sinks; + GHashTable *sink_inputs; + GHashTable *sources; + GHashTable *source_outputs; + MateMixerPulseConnection *connection; }; /* Support function for dynamic loading of the backend module */ void backend_module_init (GTypeModule *module); -const MateMixerBackendModuleInfo *backend_module_get_info (void); +const MateMixerBackendInfo *backend_module_get_info (void); -static void mate_mixer_backend_interface_init (MateMixerBackendInterface *iface); +static void mate_mixer_backend_interface_init (MateMixerBackendInterface *iface); -static void pulse_card_info_cb (pa_context *c, - const pa_card_info *info, - int eol, - void *userdata); +static void pulse_card_cb (MateMixerPulseConnection *connection, + const pa_card_info *info, + MateMixerPulse *pulse); -static void pulse_card_update (MateMixerPulse *pulse, const pa_card_info *i); +static void pulse_sink_cb (MateMixerPulseConnection *connection, + const pa_sink_info *info, + MateMixerPulse *pulse); -static void pulse_state_cb (pa_context *c, void *userdata); +static void pulse_sink_input_cb (MateMixerPulseConnection *connection, + const pa_sink_input_info *info, + MateMixerPulse *pulse); -static void pulse_subscribe_cb (pa_context *c, - pa_subscription_event_type_t t, - uint32_t idx, - void *userdata); +static void pulse_source_cb (MateMixerPulseConnection *connection, + const pa_source_info *info, + MateMixerPulse *pulse); -static gchar *pulse_get_app_name (void); +static void pulse_source_output_cb (MateMixerPulseConnection *connection, + const pa_source_output_info *info, + MateMixerPulse *pulse); G_DEFINE_DYNAMIC_TYPE_EXTENDED (MateMixerPulse, mate_mixer_pulse, G_TYPE_OBJECT, 0, G_IMPLEMENT_INTERFACE_DYNAMIC (MATE_MIXER_TYPE_BACKEND, mate_mixer_backend_interface_init)) -static MateMixerBackendModuleInfo info; +static MateMixerBackendInfo info; void backend_module_init (GTypeModule *module) @@ -77,10 +87,10 @@ backend_module_init (GTypeModule *module) info.name = BACKEND_NAME; info.priority = BACKEND_PRIORITY; info.g_type = MATE_MIXER_TYPE_PULSE; - info.backend_type = MATE_MIXER_BACKEND_TYPE_PULSE; + info.backend_type = MATE_MIXER_BACKEND_PULSE; } -const MateMixerBackendModuleInfo * +const MateMixerBackendInfo * backend_module_get_info (void) { return &info; @@ -107,18 +117,70 @@ mate_mixer_pulse_init (MateMixerPulse *pulse) g_direct_equal, NULL, g_object_unref); + + pulse->priv->cards = g_hash_table_new_full ( + g_direct_hash, + g_direct_equal, + NULL, + g_object_unref); + pulse->priv->sinks = g_hash_table_new_full ( + g_direct_hash, + g_direct_equal, + NULL, + g_object_unref); + pulse->priv->sink_inputs = g_hash_table_new_full ( + g_direct_hash, + g_direct_equal, + NULL, + g_object_unref); + pulse->priv->sources = g_hash_table_new_full ( + g_direct_hash, + g_direct_equal, + NULL, + g_object_unref); + pulse->priv->source_outputs = g_hash_table_new_full ( + g_direct_hash, + g_direct_equal, + NULL, + g_object_unref); } static void -mate_mixer_pulse_finalize (GObject *object) +mate_mixer_pulse_dispose (GObject *object) { MateMixerPulse *pulse; pulse = MATE_MIXER_PULSE (object); - g_hash_table_destroy (pulse->priv->devices); + if (pulse->priv->devices) { + g_hash_table_destroy (pulse->priv->devices); + pulse->priv->devices = NULL; + } + + if (pulse->priv->cards) { + g_hash_table_destroy (pulse->priv->cards); + pulse->priv->cards = NULL; + } + if (pulse->priv->sinks) { + g_hash_table_destroy (pulse->priv->sinks); + pulse->priv->devices = NULL; + } + if (pulse->priv->sink_inputs) { + g_hash_table_destroy (pulse->priv->sink_inputs); + pulse->priv->devices = NULL; + } + if (pulse->priv->sources) { + g_hash_table_destroy (pulse->priv->sources); + pulse->priv->devices = NULL; + } + if (pulse->priv->source_outputs) { + g_hash_table_destroy (pulse->priv->source_outputs); + pulse->priv->source_outputs = NULL; + } + + g_clear_object (&pulse->priv->connection); - G_OBJECT_CLASS (mate_mixer_pulse_parent_class)->finalize (object); + G_OBJECT_CLASS (mate_mixer_pulse_parent_class)->dispose (object); } static void @@ -127,7 +189,7 @@ mate_mixer_pulse_class_init (MateMixerPulseClass *klass) GObjectClass *object_class; object_class = G_OBJECT_CLASS (klass); - object_class->finalize = mate_mixer_pulse_finalize; + object_class->dispose = mate_mixer_pulse_dispose; g_type_class_add_private (object_class, sizeof (MateMixerPulsePrivate)); } @@ -141,83 +203,48 @@ mate_mixer_pulse_class_finalize (MateMixerPulseClass *klass) gboolean mate_mixer_pulse_open (MateMixerBackend *backend) { - int ret; - gchar *app_name; - MateMixerPulse *pulse; + MateMixerPulse *pulse; + MateMixerPulseConnection *connection; - g_return_val_if_fail (MATE_MIXER_IS_BACKEND (backend), FALSE); + g_return_val_if_fail (MATE_MIXER_IS_PULSE (backend), FALSE); pulse = MATE_MIXER_PULSE (backend); - g_return_val_if_fail (pulse->priv->mainloop == NULL, FALSE); + g_return_val_if_fail (pulse->priv->connection == NULL, FALSE); - pulse->priv->mainloop = pa_threaded_mainloop_new (); - if (G_UNLIKELY (pulse->priv->mainloop == NULL)) { - g_warning ("Failed to created PulseAudio main loop"); + connection = mate_mixer_pulse_connection_new (NULL, NULL); + if (G_UNLIKELY (connection == NULL)) { + g_object_unref (connection); return FALSE; } - app_name = pulse_get_app_name (); - - pulse->priv->context = pa_context_new ( - pa_threaded_mainloop_get_api (pulse->priv->mainloop), - app_name); - - g_free (app_name); - - if (G_UNLIKELY (pulse->priv->context == NULL)) { - g_warning ("Failed to created PulseAudio context"); - - pa_threaded_mainloop_free (pulse->priv->mainloop); - pulse->priv->mainloop = NULL; - return FALSE; - } - - // XXX: investigate PA_CONTEXT_NOFAIL - ret = pa_context_connect (pulse->priv->context, NULL, PA_CONTEXT_NOFLAGS, NULL); - if (ret < 0) { - g_warning ("Failed to connect to PulseAudio server: %s", pa_strerror (ret)); - - pa_context_unref (pulse->priv->context); - pa_threaded_mainloop_free (pulse->priv->mainloop); - - pulse->priv->context = NULL; - pulse->priv->mainloop = NULL; + if (!mate_mixer_pulse_connection_connect (connection)) { + g_object_unref (connection); return FALSE; } - g_debug ("Connected to PulseAudio server"); - - pa_threaded_mainloop_lock (pulse->priv->mainloop); - - pa_context_set_state_callback (pulse->priv->context, - pulse_state_cb, - backend); - pa_context_set_subscribe_callback (pulse->priv->context, - pulse_subscribe_cb, - backend); - - ret = pa_threaded_mainloop_start (pulse->priv->mainloop); - if (ret < 0) { - g_warning ("Failed to start PulseAudio main loop: %s", pa_strerror (ret)); - - pa_threaded_mainloop_unlock (pulse->priv->mainloop); - - pa_context_unref (pulse->priv->context); - pa_threaded_mainloop_free (pulse->priv->mainloop); - - pulse->priv->context = NULL; - pulse->priv->mainloop = NULL; - return FALSE; - } - - while (pa_context_get_state (pulse->priv->context) != PA_CONTEXT_READY) { - // XXX this will get stuck if connection fails - pa_threaded_mainloop_wait (pulse->priv->mainloop); - } - - pa_threaded_mainloop_unlock (pulse->priv->mainloop); - + g_signal_connect (connection, + "list-item-card", + G_CALLBACK (pulse_card_cb), + pulse); + g_signal_connect (connection, + "list-item-sink", + G_CALLBACK (pulse_sink_cb), + pulse); + g_signal_connect (connection, + "list-item-sink-input", + G_CALLBACK (pulse_sink_input_cb), + pulse); + g_signal_connect (connection, + "list-item-source", + G_CALLBACK (pulse_source_cb), + pulse); + g_signal_connect (connection, + "list-item-source-output", + G_CALLBACK (pulse_source_output_cb), + pulse); + + pulse->priv->connection = connection; return TRUE; } @@ -226,140 +253,118 @@ mate_mixer_pulse_close (MateMixerBackend *backend) { MateMixerPulse *pulse; - g_return_if_fail (MATE_MIXER_IS_BACKEND (backend)); + g_return_if_fail (MATE_MIXER_IS_PULSE (backend)); pulse = MATE_MIXER_PULSE (backend); - g_return_if_fail (pulse->priv->mainloop != NULL); - - pa_threaded_mainloop_stop (pulse->priv->mainloop); + g_clear_object (&pulse->priv->connection); +} - pa_context_unref (pulse->priv->context); - pa_threaded_mainloop_free (pulse->priv->mainloop); +static gboolean +pulse_load_lists (MateMixerPulse *pulse) +{ + /* The Pulse server is queried for initial lists, each of the functions + * waits until the list is available and then continues with the next. + * + * One possible improvement would be to load the lists asynchronously right + * after we connect to Pulse and when the application calls one of the + * list_* () functions, check if the initial list is already available and + * eventually wait until it's available. However, this would be + * tricky with the way the Pulse API is currently used and might not + * be beneficial at all. + */ + + // XXX figure out how to handle server reconnects, ideally everything + // we know should be ditched and read again asynchronously and + // the user should only be notified about actual differences + // from the state before we were disconnected + + // mate_mixer_pulse_connection_get_server_info (pulse->priv->connection); + mate_mixer_pulse_connection_get_card_list (pulse->priv->connection); + mate_mixer_pulse_connection_get_sink_list (pulse->priv->connection); + mate_mixer_pulse_connection_get_sink_input_list (pulse->priv->connection); + mate_mixer_pulse_connection_get_source_list (pulse->priv->connection); + mate_mixer_pulse_connection_get_source_output_list (pulse->priv->connection); - pulse->priv->context = NULL; - pulse->priv->mainloop = NULL; + return TRUE; } GList * mate_mixer_pulse_list_devices (MateMixerBackend *backend) { - MateMixerPulse *pulse; - pa_operation *o; + MateMixerPulse *pulse; + GList *list; - g_return_val_if_fail (MATE_MIXER_IS_BACKEND (backend), NULL); + g_return_val_if_fail (MATE_MIXER_IS_PULSE (backend), NULL); pulse = MATE_MIXER_PULSE (backend); - pa_threaded_mainloop_lock (pulse->priv->mainloop); + if (!pulse->priv->lists_loaded) + pulse_load_lists (pulse); - o = pa_context_get_card_info_list (pulse->priv->context, pulse_card_info_cb, pulse); - if (o == NULL) { - g_warning ("Failed to read card list: %s", - pa_strerror (pa_context_errno (pulse->priv->context))); - - pa_threaded_mainloop_unlock (pulse->priv->mainloop); - return NULL; - } + list = g_hash_table_get_values (pulse->priv->devices); - while (pa_operation_get_state (o) == PA_OPERATION_RUNNING) - pa_threaded_mainloop_wait (pulse->priv->mainloop); - - pa_operation_unref (o); - pa_threaded_mainloop_unlock (pulse->priv->mainloop); + g_list_foreach (list, (GFunc) g_object_ref, NULL); + return list; +} - return g_hash_table_get_values (pulse->priv->devices); +GList * +mate_mixer_pulse_list_streams (MateMixerBackend *backend) +{ + // TODO + return NULL; } static void -pulse_card_info_cb (pa_context *c, const pa_card_info *info, int eol, void *userdata) +pulse_card_cb (MateMixerPulseConnection *connection, + const pa_card_info *info, + MateMixerPulse *pulse) { - MateMixerPulse *pulse; - - pulse = MATE_MIXER_PULSE (userdata); - - if (!eol) - pulse_card_update (pulse, info); - - pa_threaded_mainloop_signal (pulse->priv->mainloop, 0); + MateMixerPulseDevice *device; + + device = mate_mixer_pulse_device_new (connection, info); + if (G_LIKELY (device)) + g_hash_table_insert ( + pulse->priv->devices, + GINT_TO_POINTER (mate_mixer_pulse_device_get_index (device)), + device); } static void -pulse_card_update (MateMixerPulse *pulse, const pa_card_info *info) +pulse_sink_cb (MateMixerPulseConnection *connection, + const pa_sink_info *info, + MateMixerPulse *pulse) { - gpointer item; - - item = g_hash_table_lookup (pulse->priv->devices, GINT_TO_POINTER (info->index)); - if (item) { - /* The card is already known, just update the fields that may - * have changed */ - mate_mixer_pulse_device_update (MATE_MIXER_PULSE_DEVICE (item), info); - } else { - MateMixerPulseDevice *device = mate_mixer_pulse_device_new (info); - - if (G_UNLIKELY (device == NULL)) - g_warning ("Failed to process PulseAudio sound device"); - else - g_hash_table_insert ( - pulse->priv->devices, - GINT_TO_POINTER (info->index), - device); - } + MateMixerPulseStream *stream; + + stream = mate_mixer_pulse_sink_new (connection, info); + if (G_LIKELY (stream)) + g_hash_table_insert ( + pulse->priv->sinks, + GINT_TO_POINTER (mate_mixer_pulse_stream_get_index (stream)), + stream); } static void -pulse_state_cb (pa_context *c, void *userdata) +pulse_sink_input_cb (MateMixerPulseConnection *connection, + const pa_sink_input_info *info, + MateMixerPulse *pulse) { - MateMixerPulse *pulse; - pulse = MATE_MIXER_PULSE (userdata); - - // TODO: handle errors - - switch (pa_context_get_state (c)) { - case PA_CONTEXT_UNCONNECTED: - break; - case PA_CONTEXT_CONNECTING: - break; - case PA_CONTEXT_AUTHORIZING: - break; - case PA_CONTEXT_SETTING_NAME: - break; - case PA_CONTEXT_READY: - break; - case PA_CONTEXT_FAILED: - break; - case PA_CONTEXT_TERMINATED: - break; - default: - break; - } - - pa_threaded_mainloop_signal (pulse->priv->mainloop, FALSE); } static void -pulse_subscribe_cb (pa_context *c, - pa_subscription_event_type_t t, - uint32_t idx, - void *userdata) +pulse_source_cb (MateMixerPulseConnection *connection, + const pa_source_info *info, + MateMixerPulse *pulse) { - // TODO + } -static gchar * -pulse_get_app_name (void) +static void +pulse_source_output_cb (MateMixerPulseConnection *connection, + const pa_source_output_info *info, + MateMixerPulse *pulse) { - const char *name_app; - char name_buf[256]; - - /* Inspired by GStreamer's pulse plugin */ - name_app = g_get_application_name (); - if (name_app != NULL) - return g_strdup (name_app); - - if (pa_get_binary_name (name_buf, sizeof (name_buf)) != NULL) - return g_strdup (name_buf); - return g_strdup_printf ("libmatemixer-%lu", (gulong) getpid ()); } diff --git a/backends/pulse/pulse.h b/backends/pulse/pulse.h index 2f8414f..d94a543 100644 --- a/backends/pulse/pulse.h +++ b/backends/pulse/pulse.h @@ -54,8 +54,10 @@ struct _MateMixerPulseClass GType mate_mixer_pulse_get_type (void) G_GNUC_CONST; +/* Interface implementation */ gboolean mate_mixer_pulse_open (MateMixerBackend *backend); void mate_mixer_pulse_close (MateMixerBackend *backend); GList *mate_mixer_pulse_list_devices (MateMixerBackend *backend); +GList *mate_mixer_pulse_list_streams (MateMixerBackend *backend); #endif /* MATEMIXER_PULSE_H */ diff --git a/configure.ac b/configure.ac index fdd632b..e004f47 100644 --- a/configure.ac +++ b/configure.ac @@ -138,7 +138,7 @@ backends/null/Makefile backends/pulse/Makefile data/Makefile data/libmatemixer.pc -doc/Makefile +docs/Makefile ]) AC_OUTPUT diff --git a/doc/Makefile.am b/doc/Makefile.am deleted file mode 100644 index 9b582ee..0000000 --- a/doc/Makefile.am +++ /dev/null @@ -1,2 +0,0 @@ - --include $(top_srcdir)/git.mk diff --git a/docs/Makefile.am b/docs/Makefile.am new file mode 100644 index 0000000..9b582ee --- /dev/null +++ b/docs/Makefile.am @@ -0,0 +1,2 @@ + +-include $(top_srcdir)/git.mk diff --git a/libmatemixer/Makefile.am b/libmatemixer/Makefile.am index a269397..0280b27 100644 --- a/libmatemixer/Makefile.am +++ b/libmatemixer/Makefile.am @@ -1,7 +1,6 @@ lib_LTLIBRARIES = libmatemixer.la AM_CPPFLAGS = \ - $(GLIB_CFLAGS) \ -I$(top_srcdir) \ -I$(top_srcdir)/libmatemixer \ -DG_LOG_DOMAIN=\"libmatemixer\" \ @@ -13,10 +12,12 @@ libmatemixer_include_HEADERS = \ matemixer.h \ matemixer-control.h \ matemixer-device.h \ - matemixer-device-port.h \ - matemixer-device-profile.h \ matemixer-enums.h \ - matemixer-track.h + matemixer-port.h \ + matemixer-profile.h \ + matemixer-stream.h + +libmatemixer_la_CFLAGS = $(GLIB_CFLAGS) libmatemixer_la_SOURCES = \ matemixer.c \ @@ -24,13 +25,14 @@ libmatemixer_la_SOURCES = \ matemixer-backend.c \ matemixer-backend.h \ matemixer-backend-module.c \ + matemixer-backend-module.h \ matemixer-control.c \ matemixer-device.c \ - matemixer-device-port.c \ - matemixer-device-profile.c \ matemixer-enum-types.c \ matemixer-enum-types.h \ - matemixer-track.c + matemixer-port.c \ + matemixer-profile.c \ + matemixer-stream.c libmatemixer_la_LIBADD = $(GLIB_LIBS) diff --git a/libmatemixer/matemixer-backend-module.c b/libmatemixer/matemixer-backend-module.c index 7846359..5ad2836 100644 --- a/libmatemixer/matemixer-backend-module.c +++ b/libmatemixer/matemixer-backend-module.c @@ -33,19 +33,40 @@ struct _MateMixerBackendModulePrivate void (*init) (GTypeModule *type_module); void (*deinit) (void); - const MateMixerBackendModuleInfo *(*get_info) (void); + const MateMixerBackendInfo *(*get_info) (void); }; -static gboolean mate_mixer_backend_module_load (GTypeModule *gmodule); -static void mate_mixer_backend_module_unload (GTypeModule *gmodule); +static void mate_mixer_backend_module_class_init (MateMixerBackendModuleClass *klass); +static void mate_mixer_backend_module_init (MateMixerBackendModule *module); +static void mate_mixer_backend_module_dispose (GObject *object); +static void mate_mixer_backend_module_finalize (GObject *object); + +static gboolean mate_mixer_backend_module_load (GTypeModule *gmodule); +static void mate_mixer_backend_module_unload (GTypeModule *gmodule); + +static void +mate_mixer_backend_module_class_init (MateMixerBackendModuleClass *klass) +{ + GObjectClass *object_class; + GTypeModuleClass *module_class; + + object_class = G_OBJECT_CLASS (klass); + object_class->dispose = mate_mixer_backend_module_dispose; + object_class->finalize = mate_mixer_backend_module_finalize; + + module_class = G_TYPE_MODULE_CLASS (klass); + module_class->load = mate_mixer_backend_module_load; + module_class->unload = mate_mixer_backend_module_unload; + + g_type_class_add_private (object_class, sizeof (MateMixerBackendModulePrivate)); +} static void mate_mixer_backend_module_init (MateMixerBackendModule *module) { - module->priv = G_TYPE_INSTANCE_GET_PRIVATE ( - module, - MATE_MIXER_TYPE_BACKEND_MODULE, - MateMixerBackendModulePrivate); + module->priv = G_TYPE_INSTANCE_GET_PRIVATE (module, + MATE_MIXER_TYPE_BACKEND_MODULE, + MateMixerBackendModulePrivate); } static void @@ -76,23 +97,6 @@ mate_mixer_backend_module_finalize (GObject *object) G_OBJECT_CLASS (mate_mixer_backend_module_parent_class)->finalize (object); } -static void -mate_mixer_backend_module_class_init (MateMixerBackendModuleClass *klass) -{ - GObjectClass *object_class; - GTypeModuleClass *gtype_class; - - object_class = G_OBJECT_CLASS (klass); - object_class->dispose = mate_mixer_backend_module_dispose; - object_class->finalize = mate_mixer_backend_module_finalize; - - gtype_class = G_TYPE_MODULE_CLASS (klass); - gtype_class->load = mate_mixer_backend_module_load; - gtype_class->unload = mate_mixer_backend_module_unload; - - g_type_class_add_private (object_class, sizeof (MateMixerBackendModulePrivate)); -} - static gboolean mate_mixer_backend_module_load (GTypeModule *type_module) { @@ -101,28 +105,27 @@ mate_mixer_backend_module_load (GTypeModule *type_module) module = MATE_MIXER_BACKEND_MODULE (type_module); if (!module->priv->loaded) { - module->priv->gmodule = g_module_open ( - module->priv->path, - G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL); - + module->priv->gmodule = g_module_open (module->priv->path, + G_MODULE_BIND_LAZY | + G_MODULE_BIND_LOCAL); if (module->priv->gmodule == NULL) { g_warning ("Failed to load backend module %s: %s", - module->priv->path, - g_module_error ()); + module->priv->path, + g_module_error ()); return FALSE; } /* Validate library symbols that each backend module must provide */ if (!g_module_symbol (module->priv->gmodule, - "backend_module_init", - (gpointer *) &module->priv->init) || + "backend_module_init", + (gpointer *) &module->priv->init) || !g_module_symbol (module->priv->gmodule, - "backend_module_get_info", - (gpointer *) &module->priv->get_info)) { + "backend_module_get_info", + (gpointer *) &module->priv->get_info)) { g_warning ("Failed to load backend module %s: %s", - module->priv->path, - g_module_error ()); + module->priv->path, + g_module_error ()); g_module_close (module->priv->gmodule); return FALSE; @@ -130,8 +133,8 @@ mate_mixer_backend_module_load (GTypeModule *type_module) /* Optional backend functions */ g_module_symbol (module->priv->gmodule, - "backend_module_deinit", - (gpointer *) &module->priv->deinit); + "backend_module_deinit", + (gpointer *) &module->priv->deinit); module->priv->init (type_module); module->priv->loaded = TRUE; @@ -140,7 +143,7 @@ mate_mixer_backend_module_load (GTypeModule *type_module) * it in other parts of the library */ if (G_UNLIKELY (module->priv->get_info () == NULL)) { g_warning ("Backend module %s does not provide module information", - module->priv->path); + module->priv->path); /* Close the module but keep the loaded flag to avoid unreffing * this instance as the GType has most likely been registered */ @@ -150,7 +153,7 @@ mate_mixer_backend_module_load (GTypeModule *type_module) /* It is not possible to unref this instance, so let's avoid unloading * the module and just let the backend module (de)initialize when - * (un)load are called repeatedly */ + * (de)init functions are called repeatedly */ g_module_make_resident (module->priv->gmodule); g_debug ("Loaded backend module %s", module->priv->path); @@ -189,7 +192,7 @@ mate_mixer_backend_module_new (const gchar *path) return module; } -const MateMixerBackendModuleInfo * +const MateMixerBackendInfo * mate_mixer_backend_module_get_info (MateMixerBackendModule *module) { g_return_val_if_fail (MATE_MIXER_IS_BACKEND_MODULE (module), NULL); diff --git a/libmatemixer/matemixer-backend-module.h b/libmatemixer/matemixer-backend-module.h index 4cba866..b629bfc 100644 --- a/libmatemixer/matemixer-backend-module.h +++ b/libmatemixer/matemixer-backend-module.h @@ -25,6 +25,13 @@ G_BEGIN_DECLS +typedef struct { + gchar *name; + guint priority; + GType g_type; + MateMixerBackendType backend_type; +} MateMixerBackendInfo; + #define MATE_MIXER_TYPE_BACKEND_MODULE \ (mate_mixer_backend_module_get_type ()) #define MATE_MIXER_BACKEND_MODULE(o) \ @@ -40,18 +47,8 @@ G_BEGIN_DECLS typedef struct _MateMixerBackendModule MateMixerBackendModule; typedef struct _MateMixerBackendModuleClass MateMixerBackendModuleClass; -typedef struct _MateMixerBackendModuleInfo MateMixerBackendModuleInfo; typedef struct _MateMixerBackendModulePrivate MateMixerBackendModulePrivate; -struct _MateMixerBackendModuleInfo -{ - gchar *name; - guint priority; - GType g_type; - - MateMixerBackendType backend_type; -}; - struct _MateMixerBackendModule { GTypeModule parent; @@ -66,9 +63,9 @@ struct _MateMixerBackendModuleClass GType mate_mixer_backend_module_get_type (void) G_GNUC_CONST; -MateMixerBackendModule *mate_mixer_backend_module_new (const gchar *path); -const MateMixerBackendModuleInfo *mate_mixer_backend_module_get_info (MateMixerBackendModule *module); -const gchar *mate_mixer_backend_module_get_path (MateMixerBackendModule *module); +MateMixerBackendModule *mate_mixer_backend_module_new (const gchar *path); +const MateMixerBackendInfo *mate_mixer_backend_module_get_info (MateMixerBackendModule *module); +const gchar *mate_mixer_backend_module_get_path (MateMixerBackendModule *module); G_END_DECLS diff --git a/libmatemixer/matemixer-backend.c b/libmatemixer/matemixer-backend.c index 18e622f..890c34b 100644 --- a/libmatemixer/matemixer-backend.c +++ b/libmatemixer/matemixer-backend.c @@ -19,6 +19,7 @@ #include #include "matemixer-backend.h" +#include "matemixer-stream.h" G_DEFINE_INTERFACE (MateMixerBackend, mate_mixer_backend, G_TYPE_OBJECT) @@ -32,9 +33,10 @@ mate_mixer_backend_open (MateMixerBackend *backend) { MateMixerBackendInterface *iface; - g_return_val_if_fail (MATE_MIXER_IS_BACKEND (backend), NULL); + g_return_val_if_fail (MATE_MIXER_IS_BACKEND (backend), FALSE); iface = MATE_MIXER_BACKEND_GET_INTERFACE (backend); + if (iface->open) return iface->open (backend); @@ -46,9 +48,10 @@ mate_mixer_backend_close (MateMixerBackend *backend) { MateMixerBackendInterface *iface; - g_return_val_if_fail (MATE_MIXER_IS_BACKEND (backend), NULL); + g_return_if_fail (MATE_MIXER_IS_BACKEND (backend)); iface = MATE_MIXER_BACKEND_GET_INTERFACE (backend); + if (iface->close) iface->close (backend); } @@ -61,6 +64,7 @@ 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 (iface->list_devices) return iface->list_devices (backend); @@ -68,15 +72,46 @@ mate_mixer_backend_list_devices (MateMixerBackend *backend) } GList * -mate_mixer_backend_list_tracks (MateMixerBackend *backend) +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 (iface->list_streams) + return iface->list_streams (backend); + + return NULL; +} + +MateMixerStream * +mate_mixer_backend_get_default_input_stream (MateMixerBackend *backend) +{ + MateMixerBackendInterface *iface; + + g_return_val_if_fail (MATE_MIXER_IS_BACKEND (backend), NULL); + + iface = MATE_MIXER_BACKEND_GET_INTERFACE (backend); + + if (iface->get_default_input_stream) + return iface->get_default_input_stream (backend); + + return NULL; +} + +MateMixerStream * +mate_mixer_backend_get_default_output_stream (MateMixerBackend *backend) { MateMixerBackendInterface *iface; g_return_val_if_fail (MATE_MIXER_IS_BACKEND (backend), NULL); iface = MATE_MIXER_BACKEND_GET_INTERFACE (backend); - if (iface->list_tracks) - return iface->list_tracks (backend); + + if (iface->get_default_output_stream) + return iface->get_default_output_stream (backend); return NULL; } diff --git a/libmatemixer/matemixer-backend.h b/libmatemixer/matemixer-backend.h index e5a8585..897641f 100644 --- a/libmatemixer/matemixer-backend.h +++ b/libmatemixer/matemixer-backend.h @@ -21,7 +21,7 @@ #include #include -#include +#include "matemixer-stream.h" G_BEGIN_DECLS @@ -42,19 +42,23 @@ struct _MateMixerBackendInterface GTypeInterface parent; /* Required */ - gboolean (*open) (MateMixerBackend *backend); + gboolean (*open) (MateMixerBackend *backend); - void (*close) (MateMixerBackend *backend); - GList *(*list_devices) (MateMixerBackend *backend); - GList *(*list_tracks) (MateMixerBackend *backend); + void (*close) (MateMixerBackend *backend); + GList *(*list_devices) (MateMixerBackend *backend); + GList *(*list_streams) (MateMixerBackend *backend); + MateMixerStream *(*get_default_input_stream) (MateMixerBackend *backend); + MateMixerStream *(*get_default_output_stream) (MateMixerBackend *backend); }; GType mate_mixer_backend_get_type (void) G_GNUC_CONST; -gboolean mate_mixer_backend_open (MateMixerBackend *backend); -void mate_mixer_backend_close (MateMixerBackend *backend); -GList *mate_mixer_backend_list_devices (MateMixerBackend *backend); -GList *mate_mixer_backend_list_tracks (MateMixerBackend *backend); +gboolean mate_mixer_backend_open (MateMixerBackend *backend); +void mate_mixer_backend_close (MateMixerBackend *backend); +GList *mate_mixer_backend_list_devices (MateMixerBackend *backend); +GList *mate_mixer_backend_list_streams (MateMixerBackend *backend); +MateMixerStream *mate_mixer_backend_get_default_input_stream (MateMixerBackend *backend); +MateMixerStream *mate_mixer_backend_get_default_output_stream (MateMixerBackend *backend); G_END_DECLS diff --git a/libmatemixer/matemixer-control.c b/libmatemixer/matemixer-control.c index cf59ad5..c122a7e 100644 --- a/libmatemixer/matemixer-control.c +++ b/libmatemixer/matemixer-control.c @@ -23,64 +23,73 @@ #include "matemixer-control.h" #include "matemixer-enums.h" #include "matemixer-private.h" -#include "matemixer-track.h" +#include "matemixer-stream.h" struct _MateMixerControlPrivate { GList *devices; - GList *tracks; + GList *streams; MateMixerBackend *backend; MateMixerBackendModule *module; }; G_DEFINE_TYPE (MateMixerControl, mate_mixer_control, G_TYPE_OBJECT); -static MateMixerBackend *mixer_control_init_module (MateMixerBackendModule *module); +static void mate_mixer_control_class_init (MateMixerControlClass *klass); +static void mate_mixer_control_init (MateMixerControl *control); +static void mate_mixer_control_dispose (GObject *object); + +static MateMixerBackend *mixer_control_init_module (MateMixerBackendModule *module); + +static void +mate_mixer_control_class_init (MateMixerControlClass *klass) +{ + GObjectClass *object_class; + + object_class = G_OBJECT_CLASS (klass); + object_class->dispose = mate_mixer_control_dispose; + + g_type_class_add_private (object_class, sizeof (MateMixerControlPrivate)); +} static void mate_mixer_control_init (MateMixerControl *control) { - control->priv = G_TYPE_INSTANCE_GET_PRIVATE ( - control, - MATE_MIXER_TYPE_CONTROL, - MateMixerControlPrivate); + control->priv = G_TYPE_INSTANCE_GET_PRIVATE (control, + MATE_MIXER_TYPE_CONTROL, + MateMixerControlPrivate); } static void -mate_mixer_control_finalize (GObject *object) +mate_mixer_control_dispose (GObject *object) { MateMixerControl *control; control = MATE_MIXER_CONTROL (object); - mate_mixer_backend_close (control->priv->backend); + if (control->priv->backend) { + mate_mixer_backend_close (control->priv->backend); + g_clear_object (&control->priv->backend); + } - g_object_unref (control->priv->backend); - g_object_unref (control->priv->module); + g_clear_object (&control->priv->module); - if (control->priv->devices) + if (control->priv->devices) { g_list_free_full (control->priv->devices, g_object_unref); - if (control->priv->tracks) - g_list_free_full (control->priv->tracks, g_object_unref); - - G_OBJECT_CLASS (mate_mixer_control_parent_class)->finalize (object); -} - -static void -mate_mixer_control_class_init (MateMixerControlClass *klass) -{ - GObjectClass *object_class; - - object_class = G_OBJECT_CLASS (klass); - object_class->finalize = mate_mixer_control_finalize; + control->priv->devices = NULL; + } + if (control->priv->streams) { + g_list_free_full (control->priv->streams, g_object_unref); + control->priv->streams = NULL; + } - g_type_class_add_private (object_class, sizeof (MateMixerControlPrivate)); + G_OBJECT_CLASS (mate_mixer_control_parent_class)->dispose (object); } MateMixerControl * mate_mixer_control_new (void) { - GList *modules; + const GList *modules; MateMixerControl *control; MateMixerBackend *backend = NULL; MateMixerBackendModule *module = NULL; @@ -101,7 +110,7 @@ mate_mixer_control_new (void) } /* The last module in the priority list is the "null" module which - * should always be initialized correctly, but in case "null" is absent + * should always be initialized correctly, but in case "null" is absent, * all the other modules might fail their initializations */ if (backend == NULL) return NULL; @@ -117,7 +126,7 @@ mate_mixer_control_new (void) MateMixerControl * mate_mixer_control_new_backend (MateMixerBackendType backend_type) { - GList *modules; + const GList *modules; MateMixerControl *control; MateMixerBackend *backend = NULL; MateMixerBackendModule *module = NULL; @@ -129,7 +138,7 @@ mate_mixer_control_new_backend (MateMixerBackendType backend_type) modules = mate_mixer_get_modules (); while (modules) { - const MateMixerBackendModuleInfo *info; + const MateMixerBackendInfo *info; module = MATE_MIXER_BACKEND_MODULE (modules->data); info = mate_mixer_backend_module_get_info (module); @@ -158,35 +167,49 @@ mate_mixer_control_list_devices (MateMixerControl *control) { g_return_val_if_fail (MATE_MIXER_IS_CONTROL (control), NULL); - /* This list is cached here and invalidated when the backend - * notifies us about a change */ + /* This list is cached here and invalidated when the backend notifies us + * about a change */ if (control->priv->devices == NULL) - control->priv->devices = mate_mixer_backend_list_devices ( - MATE_MIXER_BACKEND (control->priv->backend)); - - // TODO: notification signals from backend + control->priv->devices = + mate_mixer_backend_list_devices (MATE_MIXER_BACKEND (control->priv->backend)); return (const GList *) control->priv->devices; } const GList * -mate_mixer_control_list_tracks (MateMixerControl *control) +mate_mixer_control_list_streams (MateMixerControl *control) { g_return_val_if_fail (MATE_MIXER_IS_CONTROL (control), NULL); - /* This list is cached here and invalidated when the backend - * notifies us about a change */ - if (control->priv->tracks == NULL) - control->priv->tracks = mate_mixer_backend_list_tracks ( - MATE_MIXER_BACKEND (control->priv->backend)); + /* This list is cached here and invalidated when the backend notifies us + * about a change */ + if (control->priv->streams == NULL) + control->priv->streams = + mate_mixer_backend_list_streams (MATE_MIXER_BACKEND (control->priv->backend)); + + return (const GList *) control->priv->streams; +} + +MateMixerStream * +mate_mixer_control_get_default_input_stream (MateMixerControl *control) +{ + g_return_val_if_fail (MATE_MIXER_IS_CONTROL (control), NULL); + + return mate_mixer_backend_get_default_input_stream (control->priv->backend); +} + +MateMixerStream * +mate_mixer_control_get_default_output_stream (MateMixerControl *control) +{ + g_return_val_if_fail (MATE_MIXER_IS_CONTROL (control), NULL); - return (const GList *) control->priv->tracks; + return mate_mixer_backend_get_default_output_stream (control->priv->backend); } const gchar * mate_mixer_control_get_backend_name (MateMixerControl *control) { - const MateMixerBackendModuleInfo *info; + const MateMixerBackendInfo *info; g_return_val_if_fail (MATE_MIXER_IS_CONTROL (control), NULL); @@ -198,7 +221,7 @@ mate_mixer_control_get_backend_name (MateMixerControl *control) MateMixerBackendType mate_mixer_control_get_backend_type (MateMixerControl *control) { - const MateMixerBackendModuleInfo *info; + const MateMixerBackendInfo *info; g_return_val_if_fail (MATE_MIXER_IS_CONTROL (control), FALSE); @@ -210,8 +233,8 @@ mate_mixer_control_get_backend_type (MateMixerControl *control) static MateMixerBackend * mixer_control_init_module (MateMixerBackendModule *module) { - MateMixerBackend *backend; - const MateMixerBackendModuleInfo *info; + MateMixerBackend *backend; + const MateMixerBackendInfo *info; info = mate_mixer_backend_module_get_info (module); backend = g_object_newv (info->g_type, 0, NULL); diff --git a/libmatemixer/matemixer-control.h b/libmatemixer/matemixer-control.h index 739eabd..3482fbb 100644 --- a/libmatemixer/matemixer-control.h +++ b/libmatemixer/matemixer-control.h @@ -21,7 +21,8 @@ #include #include -#include "matemixer-enums.h" +#include +#include G_BEGIN_DECLS @@ -51,18 +52,19 @@ struct _MateMixerControl struct _MateMixerControlClass { - GObjectClass parent; + GObjectClass parent; }; GType mate_mixer_control_get_type (void) G_GNUC_CONST; -MateMixerControl *mate_mixer_control_new (void); -MateMixerControl *mate_mixer_control_new_backend (MateMixerBackendType backend_type); -const GList *mate_mixer_control_list_devices (MateMixerControl *control); -const GList *mate_mixer_control_list_tracks (MateMixerControl *control); - -const gchar *mate_mixer_control_get_backend_name (MateMixerControl *control); -MateMixerBackendType mate_mixer_control_get_backend_type (MateMixerControl *control); +MateMixerControl * mate_mixer_control_new (void); +MateMixerControl * mate_mixer_control_new_backend (MateMixerBackendType backend_type); +const GList * mate_mixer_control_list_devices (MateMixerControl *control); +const GList * mate_mixer_control_list_streams (MateMixerControl *control); +MateMixerStream * mate_mixer_control_get_default_input_stream (MateMixerControl *control); +MateMixerStream * mate_mixer_control_get_default_output_stream (MateMixerControl *control); +const gchar * mate_mixer_control_get_backend_name (MateMixerControl *control); +MateMixerBackendType mate_mixer_control_get_backend_type (MateMixerControl *control); G_END_DECLS diff --git a/libmatemixer/matemixer-device-port.c b/libmatemixer/matemixer-device-port.c deleted file mode 100644 index ca84ef6..0000000 --- a/libmatemixer/matemixer-device-port.c +++ /dev/null @@ -1,270 +0,0 @@ -/* - * Copyright (C) 2014 Michal Ratajsky - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the licence, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - */ - -#include -#include - -#include "matemixer-device-port.h" -#include "matemixer-enums.h" -#include "matemixer-enum-types.h" - -struct _MateMixerDevicePortPrivate -{ - gchar *identifier; - gchar *name; - gchar *icon; - guint32 priority; - - MateMixerDevicePortDirection direction; - MateMixerDevicePortStatus status; -}; - -enum -{ - PROP_0, - PROP_IDENTIFIER, - PROP_NAME, - PROP_ICON, - PROP_PRIORITY, - PROP_DIRECTION, - PROP_STATUS, - N_PROPERTIES -}; - -static GParamSpec *properties[N_PROPERTIES] = { NULL, }; - -G_DEFINE_TYPE (MateMixerDevicePort, mate_mixer_device_port, G_TYPE_OBJECT); - -static void -mate_mixer_device_port_init (MateMixerDevicePort *port) -{ - port->priv = G_TYPE_INSTANCE_GET_PRIVATE ( - port, - MATE_MIXER_TYPE_DEVICE_PORT, - MateMixerDevicePortPrivate); -} - -static void -mate_mixer_device_port_get_property (GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec) -{ - MateMixerDevicePort *port; - - port = MATE_MIXER_DEVICE_PORT (object); - - switch (param_id) { - case PROP_IDENTIFIER: - g_value_set_string (value, port->priv->identifier); - break; - case PROP_NAME: - g_value_set_string (value, port->priv->name); - break; - case PROP_ICON: - g_value_set_string (value, port->priv->icon); - break; - case PROP_PRIORITY: - g_value_set_uint (value, port->priv->priority); - break; - case PROP_DIRECTION: - g_value_set_flags (value, port->priv->direction); - break; - case PROP_STATUS: - g_value_set_flags (value, port->priv->status); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); - break; - } -} - -static void -mate_mixer_device_port_set_property (GObject *object, - guint param_id, - const GValue *value, - GParamSpec *pspec) -{ - MateMixerDevicePort *port; - - port = MATE_MIXER_DEVICE_PORT (object); - - switch (param_id) { - case PROP_IDENTIFIER: - port->priv->identifier = g_strdup (g_value_get_string (value)); - break; - case PROP_NAME: - port->priv->name = g_strdup (g_value_get_string (value)); - break; - case PROP_ICON: - port->priv->icon = g_strdup (g_value_get_string (value)); - break; - case PROP_PRIORITY: - port->priv->priority = g_value_get_uint (value); - break; - case PROP_DIRECTION: - port->priv->direction = g_value_get_flags (value); - break; - case PROP_STATUS: - port->priv->status = g_value_get_flags (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); - break; - } -} - -static void -mate_mixer_device_port_finalize (GObject *object) -{ - MateMixerDevicePort *port; - - port = MATE_MIXER_DEVICE_PORT (object); - - g_free (port->priv->identifier); - g_free (port->priv->name); - g_free (port->priv->icon); - - G_OBJECT_CLASS (mate_mixer_device_port_parent_class)->finalize (object); -} - -static void -mate_mixer_device_port_class_init (MateMixerDevicePortClass *klass) -{ - GObjectClass *object_class; - - object_class = G_OBJECT_CLASS (klass); - object_class->finalize = mate_mixer_device_port_finalize; - object_class->get_property = mate_mixer_device_port_get_property; - object_class->set_property = mate_mixer_device_port_set_property; - - properties[PROP_IDENTIFIER] = g_param_spec_string ( - "identifier", - "Identifier", - "Identifier of the device port", - NULL, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); - - properties[PROP_NAME] = g_param_spec_string ( - "name", - "Name", - "Name of the device port", - NULL, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); - - properties[PROP_ICON] = g_param_spec_string ( - "icon", - "Icon", - "Icon name for the device port", - NULL, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); - - properties[PROP_PRIORITY] = g_param_spec_uint ( - "priority", - "Priority", - "Priority of the device port", - 0, - G_MAXUINT32, - 0, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); - - properties[PROP_DIRECTION] = g_param_spec_flags ( - "direction", - "Direction", - "Direction(s) for the device port", - MATE_MIXER_TYPE_DEVICE_PORT_DIRECTION, - 0, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); - - properties[PROP_STATUS] = g_param_spec_flags ( - "status", - "Status", - "Status for the device port", - MATE_MIXER_TYPE_DEVICE_PORT_STATUS, - 0, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); - - g_object_class_install_properties (object_class, N_PROPERTIES, properties); - - g_type_class_add_private (object_class, sizeof (MateMixerDevicePortPrivate)); -} - -MateMixerDevicePort * -mate_mixer_device_port_new (const gchar *identifier, - const gchar *name, - const gchar *icon, - guint32 priority, - MateMixerDevicePortDirection direction, - MateMixerDevicePortStatus status) -{ - return g_object_new (MATE_MIXER_TYPE_DEVICE_PORT, - "identifier", identifier, - "name", name, - "icon", icon, - "priority", priority, - "direction", direction, - "status", status, - NULL); -} - -const gchar * -mate_mixer_device_port_get_identifier (MateMixerDevicePort *port) -{ - g_return_val_if_fail (MATE_MIXER_IS_DEVICE_PORT (port), NULL); - - return port->priv->identifier; -} - -const gchar * -mate_mixer_device_port_get_name (MateMixerDevicePort *port) -{ - g_return_val_if_fail (MATE_MIXER_IS_DEVICE_PORT (port), NULL); - - return port->priv->name; -} - -const gchar * -mate_mixer_device_port_get_icon (MateMixerDevicePort *port) -{ - g_return_val_if_fail (MATE_MIXER_IS_DEVICE_PORT (port), NULL); - - return port->priv->icon; -} - -guint32 -mate_mixer_device_port_get_priority (MateMixerDevicePort *port) -{ - g_return_val_if_fail (MATE_MIXER_IS_DEVICE_PORT (port), 0); - - return port->priv->priority; -} - -MateMixerDevicePortDirection -mate_mixer_device_port_get_direction (MateMixerDevicePort *port) -{ - g_return_val_if_fail (MATE_MIXER_IS_DEVICE_PORT (port), 0); - - return port->priv->direction; -} - -MateMixerDevicePortStatus -mate_mixer_device_port_get_status (MateMixerDevicePort *port) -{ - g_return_val_if_fail (MATE_MIXER_IS_DEVICE_PORT (port), 0); - - return port->priv->status; -} diff --git a/libmatemixer/matemixer-device-port.h b/libmatemixer/matemixer-device-port.h deleted file mode 100644 index f21caaf..0000000 --- a/libmatemixer/matemixer-device-port.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2014 Michal Ratajsky - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the licence, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - */ - -#ifndef MATEMIXER_DEVICE_PORT_H -#define MATEMIXER_DEVICE_PORT_H - -#include -#include - -#include - -G_BEGIN_DECLS - -#define MATE_MIXER_TYPE_DEVICE_PORT \ - (mate_mixer_device_port_get_type ()) -#define MATE_MIXER_DEVICE_PORT(o) \ - (G_TYPE_CHECK_INSTANCE_CAST ((o), MATE_MIXER_TYPE_DEVICE_PORT, MateMixerDevicePort)) -#define MATE_MIXER_IS_DEVICE_PORT(o) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((o), MATE_MIXER_TYPE_DEVICE_PORT)) -#define MATE_MIXER_DEVICE_PORT_CLASS(k) \ - (G_TYPE_CHECK_CLASS_CAST ((k), MATE_MIXER_TYPE_DEVICE_PORT, MateMixerDevicePortClass)) -#define MATE_MIXER_IS_DEVICE_PORT_CLASS(k) \ - (G_TYPE_CLASS_CHECK_CLASS_TYPE ((k), MATE_MIXER_TYPE_DEVICE_PORT)) -#define MATE_MIXER_DEVICE_PORT_GET_CLASS(o) \ - (G_TYPE_INSTANCE_GET_CLASS ((o), MATE_MIXER_TYPE_DEVICE_PORT, MateMixerDevicePortClass)) - -typedef struct _MateMixerDevicePort MateMixerDevicePort; -typedef struct _MateMixerDevicePortClass MateMixerDevicePortClass; -typedef struct _MateMixerDevicePortPrivate MateMixerDevicePortPrivate; - -struct _MateMixerDevicePort -{ - GObject parent; - - MateMixerDevicePortPrivate *priv; -}; - -struct _MateMixerDevicePortClass -{ - GObjectClass parent; -}; - -GType mate_mixer_device_port_get_type (void) G_GNUC_CONST; - -MateMixerDevicePort *mate_mixer_device_port_new (const gchar *identifier, - const gchar *name, - const gchar *icon, - guint32 priority, - MateMixerDevicePortDirection direction, - MateMixerDevicePortStatus status); - -const gchar *mate_mixer_device_port_get_identifier (MateMixerDevicePort *port); - -const gchar *mate_mixer_device_port_get_name (MateMixerDevicePort *port); - -const gchar *mate_mixer_device_port_get_icon (MateMixerDevicePort *port); - -guint32 mate_mixer_device_port_get_priority (MateMixerDevicePort *port); - -MateMixerDevicePortDirection mate_mixer_device_port_get_direction (MateMixerDevicePort *port); - -MateMixerDevicePortStatus mate_mixer_device_port_get_status (MateMixerDevicePort *port); - -G_END_DECLS - -#endif /* MATEMIXER_PORT_H */ diff --git a/libmatemixer/matemixer-device-profile.c b/libmatemixer/matemixer-device-profile.c deleted file mode 100644 index 975f5ff..0000000 --- a/libmatemixer/matemixer-device-profile.c +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (C) 2014 Michal Ratajsky - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the licence, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - */ - -#include -#include - -#include "matemixer-device-profile.h" - -struct _MateMixerDeviceProfilePrivate -{ - gchar *identifier; - gchar *name; - guint32 priority; -}; - -enum -{ - PROP_0, - PROP_IDENTIFIER, - PROP_NAME, - PROP_PRIORITY, - N_PROPERTIES -}; - -static GParamSpec *properties[N_PROPERTIES] = { NULL, }; - -G_DEFINE_TYPE (MateMixerDeviceProfile, mate_mixer_device_profile, G_TYPE_OBJECT); - -static void -mate_mixer_device_profile_init (MateMixerDeviceProfile *profile) -{ - profile->priv = G_TYPE_INSTANCE_GET_PRIVATE ( - profile, - MATE_MIXER_TYPE_DEVICE_PROFILE, - MateMixerDeviceProfilePrivate); -} - -static void -mate_mixer_device_profile_get_property (GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec) -{ - MateMixerDeviceProfile *profile; - - profile = MATE_MIXER_DEVICE_PROFILE (object); - - switch (param_id) { - case PROP_IDENTIFIER: - g_value_set_string (value, profile->priv->identifier); - break; - case PROP_NAME: - g_value_set_string (value, profile->priv->name); - break; - case PROP_PRIORITY: - g_value_set_uint (value, profile->priv->priority); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); - break; - } -} - -static void -mate_mixer_device_profile_set_property (GObject *object, - guint param_id, - const GValue *value, - GParamSpec *pspec) -{ - MateMixerDeviceProfile *profile; - - profile = MATE_MIXER_DEVICE_PROFILE (object); - - switch (param_id) { - case PROP_IDENTIFIER: - profile->priv->identifier = g_strdup (g_value_get_string (value)); - break; - case PROP_NAME: - profile->priv->name = g_strdup (g_value_get_string (value)); - break; - case PROP_PRIORITY: - profile->priv->priority = g_value_get_uint (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); - break; - } -} - -static void -mate_mixer_device_profile_finalize (GObject *object) -{ - MateMixerDeviceProfile *profile; - - profile = MATE_MIXER_DEVICE_PROFILE (object); - - g_free (profile->priv->identifier); - g_free (profile->priv->name); - - G_OBJECT_CLASS (mate_mixer_device_profile_parent_class)->finalize (object); -} - -static void -mate_mixer_device_profile_class_init (MateMixerDeviceProfileClass *klass) -{ - GObjectClass *object_class; - - object_class = G_OBJECT_CLASS (klass); - object_class->finalize = mate_mixer_device_profile_finalize; - object_class->get_property = mate_mixer_device_profile_get_property; - object_class->set_property = mate_mixer_device_profile_set_property; - - properties[PROP_IDENTIFIER] = g_param_spec_string ( - "identifier", - "Identifier", - "Identifier of the device profile", - NULL, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); - - properties[PROP_NAME] = g_param_spec_string ( - "name", - "Name", - "Name of the device profile", - NULL, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); - - properties[PROP_PRIORITY] = g_param_spec_uint ( - "priority", - "Priority", - "Priority of the device profile", - 0, - G_MAXUINT32, - 0, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); - - g_object_class_install_properties (object_class, N_PROPERTIES, properties); - - g_type_class_add_private (object_class, sizeof (MateMixerDeviceProfilePrivate)); -} - -MateMixerDeviceProfile * -mate_mixer_device_profile_new (const gchar *identifier, - const gchar *name, - guint32 priority) -{ - return g_object_new (MATE_MIXER_TYPE_DEVICE_PROFILE, - "identifier", identifier, - "name", name, - "priority", priority, - NULL); -} - -const gchar * -mate_mixer_device_profile_get_identifier (MateMixerDeviceProfile *profile) -{ - g_return_val_if_fail (MATE_MIXER_IS_DEVICE_PROFILE (profile), NULL); - - return profile->priv->identifier; -} - -const gchar * -mate_mixer_device_profile_get_name (MateMixerDeviceProfile *profile) -{ - g_return_val_if_fail (MATE_MIXER_IS_DEVICE_PROFILE (profile), NULL); - - return profile->priv->name; -} - -guint32 -mate_mixer_device_profile_get_priority (MateMixerDeviceProfile *profile) -{ - g_return_val_if_fail (MATE_MIXER_IS_DEVICE_PROFILE (profile), NULL); - - return profile->priv->priority; -} diff --git a/libmatemixer/matemixer-device-profile.h b/libmatemixer/matemixer-device-profile.h deleted file mode 100644 index 1ac9020..0000000 --- a/libmatemixer/matemixer-device-profile.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2014 Michal Ratajsky - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the licence, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - */ - -#ifndef MATEMIXER_DEVICE_PROFILE_H -#define MATEMIXER_DEVICE_PROFILE_H - -#include -#include - -G_BEGIN_DECLS - -#define MATE_MIXER_TYPE_DEVICE_PROFILE \ - (mate_mixer_device_profile_get_type ()) -#define MATE_MIXER_DEVICE_PROFILE(o) \ - (G_TYPE_CHECK_INSTANCE_CAST ((o), MATE_MIXER_TYPE_DEVICE_PROFILE, MateMixerDeviceProfile)) -#define MATE_MIXER_IS_DEVICE_PROFILE(o) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((o), MATE_MIXER_TYPE_DEVICE_PROFILE)) -#define MATE_MIXER_DEVICE_PROFILE_CLASS(k) \ - (G_TYPE_CHECK_CLASS_CAST ((k), MATE_MIXER_TYPE_DEVICE_PROFILE, MateMixerDeviceProfileClass)) -#define MATE_MIXER_IS_DEVICE_PROFILE_CLASS(k) \ - (G_TYPE_CLASS_CHECK_CLASS_TYPE ((k), MATE_MIXER_TYPE_DEVICE_PROFILE)) -#define MATE_MIXER_DEVICE_PROFILE_GET_CLASS(o) \ - (G_TYPE_INSTANCE_GET_CLASS ((o), MATE_MIXER_TYPE_DEVICE_PROFILE, MateMixerDeviceProfileClass)) - -typedef struct _MateMixerDeviceProfile MateMixerDeviceProfile; -typedef struct _MateMixerDeviceProfileClass MateMixerDeviceProfileClass; -typedef struct _MateMixerDeviceProfilePrivate MateMixerDeviceProfilePrivate; - -struct _MateMixerDeviceProfile -{ - GObject parent; - - MateMixerDeviceProfilePrivate *priv; -}; - -struct _MateMixerDeviceProfileClass -{ - GObjectClass parent; -}; - -GType mate_mixer_device_profile_get_type (void) G_GNUC_CONST; - -MateMixerDeviceProfile *mate_mixer_device_profile_new (const gchar *identifier, - const gchar *name, - guint32 priority); - -const gchar *mate_mixer_device_profile_get_identifier (MateMixerDeviceProfile *profile); -const gchar *mate_mixer_device_profile_get_name (MateMixerDeviceProfile *profile); -guint32 mate_mixer_device_profile_get_priority (MateMixerDeviceProfile *profile); - -G_END_DECLS - -#endif /* MATEMIXER_PROFILE_H */ diff --git a/libmatemixer/matemixer-device.c b/libmatemixer/matemixer-device.c index 8e6a465..d4a7c39 100644 --- a/libmatemixer/matemixer-device.c +++ b/libmatemixer/matemixer-device.c @@ -19,89 +19,141 @@ #include #include "matemixer-device.h" -#include "matemixer-device-profile.h" +#include "matemixer-enum-types.h" +#include "matemixer-profile.h" G_DEFINE_INTERFACE (MateMixerDevice, mate_mixer_device, G_TYPE_OBJECT) static void mate_mixer_device_default_init (MateMixerDeviceInterface *iface) { - g_object_interface_install_property ( - iface, - g_param_spec_string ("identifier", - "Identifier", - "Identifier of the sound device", - NULL, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE)); - - g_object_interface_install_property ( - iface, - g_param_spec_string ("name", - "Name", - "Name of the sound device", - NULL, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE)); - - g_object_interface_install_property ( - iface, - g_param_spec_string ("icon", - "Icon", - "Name of the sound device icon", - NULL, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE)); - - g_object_interface_install_property ( - iface, - g_param_spec_object ("active-profile", - "Active profile", - "Identifier of the currently active profile", - MATE_MIXER_TYPE_DEVICE_PROFILE, - G_PARAM_CONSTRUCT | G_PARAM_READWRITE)); + g_object_interface_install_property (iface, + g_param_spec_string ("name", + "Name", + "Name of the sound device", + NULL, + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + g_object_interface_install_property (iface, + g_param_spec_string ("description", + "Description", + "Description of the sound device", + NULL, + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + g_object_interface_install_property (iface, + g_param_spec_string ("icon", + "Icon", + "Name of the sound device icon", + NULL, + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + g_object_interface_install_property (iface, + g_param_spec_object ("active-profile", + "Active profile", + "Name of the active profile", + MATE_MIXER_TYPE_PROFILE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); +} + +const gchar * +mate_mixer_device_get_name (MateMixerDevice *device) +{ + MateMixerDeviceInterface *iface; + + g_return_val_if_fail (MATE_MIXER_IS_DEVICE (device), NULL); + + iface = MATE_MIXER_DEVICE_GET_INTERFACE (device); + + if (iface->get_name) + return iface->get_name (device); + + return NULL; +} + +const gchar * +mate_mixer_device_get_description (MateMixerDevice *device) +{ + MateMixerDeviceInterface *iface; + + g_return_val_if_fail (MATE_MIXER_IS_DEVICE (device), NULL); + + iface = MATE_MIXER_DEVICE_GET_INTERFACE (device); + + if (iface->get_description) + return iface->get_description (device); + + return NULL; +} + +const gchar * +mate_mixer_device_get_icon (MateMixerDevice *device) +{ + MateMixerDeviceInterface *iface; + + g_return_val_if_fail (MATE_MIXER_IS_DEVICE (device), NULL); + + iface = MATE_MIXER_DEVICE_GET_INTERFACE (device); + + if (iface->get_icon) + return iface->get_icon (device); + + return NULL; } const GList * -mate_mixer_device_list_tracks (MateMixerDevice *device) +mate_mixer_device_list_streams (MateMixerDevice *device) { MateMixerDeviceInterface *iface; g_return_val_if_fail (MATE_MIXER_IS_DEVICE (device), NULL); iface = MATE_MIXER_DEVICE_GET_INTERFACE (device); - if (iface->list_tracks) - return iface->list_tracks (device); + + if (iface->list_streams) + return iface->list_streams (device); return NULL; } const GList * -mate_mixer_device_get_ports (MateMixerDevice *device) +mate_mixer_device_list_ports (MateMixerDevice *device) { MateMixerDeviceInterface *iface; g_return_val_if_fail (MATE_MIXER_IS_DEVICE (device), NULL); iface = MATE_MIXER_DEVICE_GET_INTERFACE (device); - if (iface->get_ports) - return iface->get_ports (device); + + if (iface->list_ports) + return iface->list_ports (device); return NULL; } const GList * -mate_mixer_device_get_profiles (MateMixerDevice *device) +mate_mixer_device_list_profiles (MateMixerDevice *device) { MateMixerDeviceInterface *iface; g_return_val_if_fail (MATE_MIXER_IS_DEVICE (device), NULL); iface = MATE_MIXER_DEVICE_GET_INTERFACE (device); - if (iface->get_profiles) - return iface->get_profiles (device); + + if (iface->list_profiles) + return iface->list_profiles (device); return NULL; } -MateMixerDeviceProfile * +MateMixerProfile * mate_mixer_device_get_active_profile (MateMixerDevice *device) { MateMixerDeviceInterface *iface; @@ -109,6 +161,7 @@ mate_mixer_device_get_active_profile (MateMixerDevice *device) g_return_val_if_fail (MATE_MIXER_IS_DEVICE (device), NULL); iface = MATE_MIXER_DEVICE_GET_INTERFACE (device); + if (iface->get_active_profile) return iface->get_active_profile (device); @@ -116,17 +169,17 @@ mate_mixer_device_get_active_profile (MateMixerDevice *device) } gboolean -mate_mixer_device_set_active_profile (MateMixerDevice *device, - MateMixerDeviceProfile *profile) +mate_mixer_device_set_active_profile (MateMixerDevice *device, const gchar *name) { MateMixerDeviceInterface *iface; - g_return_val_if_fail (MATE_MIXER_IS_DEVICE (device), NULL); - g_return_val_if_fail (MATE_MIXER_IS_DEVICE_PROFILE (profile), NULL); + g_return_val_if_fail (MATE_MIXER_IS_DEVICE (device), FALSE); + g_return_val_if_fail (name != NULL, FALSE); iface = MATE_MIXER_DEVICE_GET_INTERFACE (device); + if (iface->set_active_profile) - return iface->set_active_profile (device, profile); + return iface->set_active_profile (device, name); return FALSE; } diff --git a/libmatemixer/matemixer-device.h b/libmatemixer/matemixer-device.h index b601f7d..89c0187 100644 --- a/libmatemixer/matemixer-device.h +++ b/libmatemixer/matemixer-device.h @@ -21,8 +21,7 @@ #include #include -#include -#include +#include G_BEGIN_DECLS @@ -42,25 +41,28 @@ struct _MateMixerDeviceInterface { GTypeInterface parent; - const GList *(*list_tracks) (MateMixerDevice *device); - const GList *(*get_ports) (MateMixerDevice *device); - const GList *(*get_profiles) (MateMixerDevice *device); - MateMixerDeviceProfile *(*get_active_profile) (MateMixerDevice *device); - gboolean (*set_active_profile) (MateMixerDevice *device, MateMixerDeviceProfile *profile); + const gchar *(*get_name) (MateMixerDevice *device); + const gchar *(*get_description) (MateMixerDevice *device); + const gchar *(*get_icon) (MateMixerDevice *device); + const GList *(*list_streams) (MateMixerDevice *device); + const GList *(*list_ports) (MateMixerDevice *device); + const GList *(*list_profiles) (MateMixerDevice *device); + MateMixerProfile *(*get_active_profile) (MateMixerDevice *device); + gboolean (*set_active_profile) (MateMixerDevice *device, + const gchar *name); }; GType mate_mixer_device_get_type (void) G_GNUC_CONST; -const GList *mate_mixer_device_list_tracks (MateMixerDevice *device); - -const GList *mate_mixer_device_get_ports (MateMixerDevice *device); - -const GList *mate_mixer_device_get_profiles (MateMixerDevice *device); - -MateMixerDeviceProfile *mate_mixer_device_get_active_profile (MateMixerDevice *device); - -gboolean mate_mixer_device_set_active_profile (MateMixerDevice *device, - MateMixerDeviceProfile *profile); +const gchar * mate_mixer_device_get_name (MateMixerDevice *device); +const gchar * mate_mixer_device_get_description (MateMixerDevice *device); +const gchar * mate_mixer_device_get_icon (MateMixerDevice *device); +const GList * mate_mixer_device_list_streams (MateMixerDevice *device); +const GList * mate_mixer_device_list_ports (MateMixerDevice *device); +const GList * mate_mixer_device_list_profiles (MateMixerDevice *device); +MateMixerProfile *mate_mixer_device_get_active_profile (MateMixerDevice *device); +gboolean mate_mixer_device_set_active_profile (MateMixerDevice *device, + const gchar *name); G_END_DECLS diff --git a/libmatemixer/matemixer-enum-types.c b/libmatemixer/matemixer-enum-types.c index 390e32d..0d1c57d 100644 --- a/libmatemixer/matemixer-enum-types.c +++ b/libmatemixer/matemixer-enum-types.c @@ -30,9 +30,9 @@ mate_mixer_backend_type_get_type (void) if (etype == 0) { static const GEnumValue values[] = { - { MATE_MIXER_BACKEND_TYPE_UNKNOWN, "MATE_MIXER_BACKEND_TYPE_UNKNOWN", "unknown" }, - { MATE_MIXER_BACKEND_TYPE_PULSE, "MATE_MIXER_BACKEND_TYPE_PULSE", "pulse" }, - { MATE_MIXER_BACKEND_TYPE_NULL, "MATE_MIXER_BACKEND_TYPE_NULL", "null" }, + { MATE_MIXER_BACKEND_UNKNOWN, "MATE_MIXER_BACKEND_UNKNOWN", "unknown" }, + { MATE_MIXER_BACKEND_PULSE, "MATE_MIXER_BACKEND_PULSE", "pulse" }, + { MATE_MIXER_BACKEND_NULL, "MATE_MIXER_BACKEND_NULL", "null" }, { 0, NULL, NULL } }; etype = g_enum_register_static ( @@ -43,35 +43,99 @@ mate_mixer_backend_type_get_type (void) } GType -mate_mixer_device_port_direction_get_type (void) +mate_mixer_port_status_get_type (void) { static GType etype = 0; if (etype == 0) { - static const GFlagsValue values[] = { - { MATE_MIXER_DEVICE_PORT_DIRECTION_INPUT, "MATE_MIXER_DEVICE_PORT_DIRECTION_INPUT", "input" }, - { MATE_MIXER_DEVICE_PORT_DIRECTION_OUTPUT, "MATE_MIXER_DEVICE_PORT_DIRECTION_OUTPUT", "output" }, + static const GEnumValue values[] = { + { MATE_MIXER_PORT_UNKNOWN_STATUS, "MATE_MIXER_PORT_UNKNOWN_STATUS", "unknown-status" }, + { MATE_MIXER_PORT_AVAILABLE, "MATE_MIXER_PORT_AVAILABLE", "available" }, + { MATE_MIXER_PORT_UNAVAILABLE, "MATE_MIXER_PORT_UNAVAILABLE", "unavailable" }, { 0, NULL, NULL } }; - etype = g_flags_register_static ( - g_intern_static_string ("MateMixerDevicePortDirection"), + etype = g_enum_register_static ( + g_intern_static_string ("MateMixerPortStatus"), values); } return etype; } GType -mate_mixer_device_port_status_get_type (void) +mate_mixer_stream_flags_get_type (void) { static GType etype = 0; if (etype == 0) { static const GFlagsValue values[] = { - { MATE_MIXER_DEVICE_PORT_STATUS_AVAILABLE, "MATE_MIXER_DEVICE_PORT_STATUS_AVAILABLE", "available" }, + { MATE_MIXER_STREAM_INPUT, "MATE_MIXER_STREAM_INPUT", "input" }, + { MATE_MIXER_STREAM_OUTPUT, "MATE_MIXER_STREAM_OUTPUT", "output" }, + { MATE_MIXER_STREAM_CLIENT, "MATE_MIXER_STREAM_CLIENT", "client" }, + { MATE_MIXER_STREAM_VIRTUAL, "MATE_MIXER_STREAM_VIRTUAL", "virtual" }, + { MATE_MIXER_STREAM_OUTPUT_MONITOR, "MATE_MIXER_STREAM_OUTPUT_MONITOR", "output-monitor" }, + { MATE_MIXER_STREAM_CAN_BALANCE, "MATE_MIXER_STREAM_CAN_BALANCE", "can-balance" }, + { MATE_MIXER_STREAM_CAN_FADE, "MATE_MIXER_STREAM_CAN_FADE", "can-fade" }, + { MATE_MIXER_STREAM_FLAT_VOLUME, "MATE_MIXER_STREAM_FLAT_VOLUME", "flat-volume" }, { 0, NULL, NULL } }; etype = g_flags_register_static ( - g_intern_static_string ("MateMixerDevicePortStatus"), + g_intern_static_string ("MateMixerStreamFlags"), + values); + } + return etype; +} + +GType +mate_mixer_stream_status_get_type (void) +{ + static GType etype = 0; + + if (etype == 0) { + static const GEnumValue values[] = { + { MATE_MIXER_STREAM_UNKNOWN_STATUS, "MATE_MIXER_STREAM_UNKNOWN_STATUS", "unknown-status" }, + { MATE_MIXER_STREAM_RUNNING, "MATE_MIXER_STREAM_RUNNING", "running" }, + { MATE_MIXER_STREAM_IDLE, "MATE_MIXER_STREAM_IDLE", "idle" }, + { MATE_MIXER_STREAM_SUSPENDED, "MATE_MIXER_STREAM_SUSPENDED", "suspended" }, + { 0, NULL, NULL } + }; + etype = g_enum_register_static ( + g_intern_static_string ("MateMixerStreamStatus"), + values); + } + return etype; +} + +GType +mate_mixer_channel_position_get_type (void) +{ + static GType etype = 0; + + if (etype == 0) { + static const GEnumValue values[] = { + { MATE_MIXER_CHANNEL_UNKNOWN_POSITION, "MATE_MIXER_CHANNEL_UNKNOWN_POSITION", "unknown-position" }, + { MATE_MIXER_CHANNEL_MONO, "MATE_MIXER_CHANNEL_MONO", "mono" }, + { MATE_MIXER_CHANNEL_FRONT_LEFT, "MATE_MIXER_CHANNEL_FRONT_LEFT", "front-left" }, + { MATE_MIXER_CHANNEL_FRONT_RIGHT, "MATE_MIXER_CHANNEL_FRONT_RIGHT", "front-right" }, + { MATE_MIXER_CHANNEL_FRONT_CENTER, "MATE_MIXER_CHANNEL_FRONT_CENTER", "front-center" }, + { MATE_MIXER_CHANNEL_LFE, "MATE_MIXER_CHANNEL_LFE", "lfe" }, + { MATE_MIXER_CHANNEL_BACK_LEFT, "MATE_MIXER_CHANNEL_BACK_LEFT", "back-left" }, + { MATE_MIXER_CHANNEL_BACK_RIGHT, "MATE_MIXER_CHANNEL_BACK_RIGHT", "back-right" }, + { MATE_MIXER_CHANNEL_FRONT_LEFT_CENTER, "MATE_MIXER_CHANNEL_FRONT_LEFT_CENTER", "front-left-center" }, + { MATE_MIXER_CHANNEL_FRONT_RIGHT_CENTER, "MATE_MIXER_CHANNEL_FRONT_RIGHT_CENTER", "front-right-center" }, + { MATE_MIXER_CHANNEL_BACK_CENTER, "MATE_MIXER_CHANNEL_BACK_CENTER", "back-center" }, + { MATE_MIXER_CHANNEL_SIDE_LEFT, "MATE_MIXER_CHANNEL_SIDE_LEFT", "side-left" }, + { MATE_MIXER_CHANNEL_SIDE_RIGHT, "MATE_MIXER_CHANNEL_SIDE_RIGHT", "side-right" }, + { MATE_MIXER_CHANNEL_TOP_FRONT_LEFT, "MATE_MIXER_CHANNEL_TOP_FRONT_LEFT", "top-front-left" }, + { MATE_MIXER_CHANNEL_TOP_FRONT_RIGHT, "MATE_MIXER_CHANNEL_TOP_FRONT_RIGHT", "top-front-right" }, + { MATE_MIXER_CHANNEL_TOP_FRONT_CENTER, "MATE_MIXER_CHANNEL_TOP_FRONT_CENTER", "top-front-center" }, + { MATE_MIXER_CHANNEL_TOP_CENTER, "MATE_MIXER_CHANNEL_TOP_CENTER", "top-center" }, + { MATE_MIXER_CHANNEL_TOP_BACK_LEFT, "MATE_MIXER_CHANNEL_TOP_BACK_LEFT", "top-back-left" }, + { MATE_MIXER_CHANNEL_TOP_BACK_RIGHT, "MATE_MIXER_CHANNEL_TOP_BACK_RIGHT", "top-back-right" }, + { MATE_MIXER_CHANNEL_TOP_BACK_CENTER, "MATE_MIXER_CHANNEL_TOP_BACK_CENTER", "top-back-center" }, + { 0, NULL, NULL } + }; + etype = g_enum_register_static ( + g_intern_static_string ("MateMixerChannelPosition"), values); } return etype; diff --git a/libmatemixer/matemixer-enum-types.h b/libmatemixer/matemixer-enum-types.h index fa1551a..ccb87a6 100644 --- a/libmatemixer/matemixer-enum-types.h +++ b/libmatemixer/matemixer-enum-types.h @@ -18,6 +18,7 @@ #ifndef MATEMIXER_ENUM_TYPES_H #define MATEMIXER_ENUM_TYPES_H +#include #include G_BEGIN_DECLS @@ -30,11 +31,17 @@ G_BEGIN_DECLS #define MATE_MIXER_TYPE_BACKEND_TYPE (mate_mixer_backend_type_get_type ()) GType mate_mixer_backend_type_get_type (void) G_GNUC_CONST; -#define MATE_MIXER_TYPE_DEVICE_PORT_DIRECTION (mate_mixer_device_port_direction_get_type ()) -GType mate_mixer_device_port_direction_get_type (void) G_GNUC_CONST; +#define MATE_MIXER_TYPE_PORT_STATUS (mate_mixer_port_status_get_type ()) +GType mate_mixer_port_status_get_type (void) G_GNUC_CONST; -#define MATE_MIXER_TYPE_DEVICE_PORT_STATUS (mate_mixer_device_port_status_get_type ()) -GType mate_mixer_device_port_status_get_type (void) G_GNUC_CONST; +#define MATE_MIXER_TYPE_STREAM_FLAGS (mate_mixer_stream_flags_get_type ()) +GType mate_mixer_stream_flags_get_type (void) G_GNUC_CONST; + +#define MATE_MIXER_TYPE_STREAM_STATUS (mate_mixer_stream_status_get_type ()) +GType mate_mixer_stream_status_get_type (void) G_GNUC_CONST; + +#define MATE_MIXER_TYPE_CHANNEL_POSITION (mate_mixer_channel_position_get_type ()) +GType mate_mixer_channel_position_get_type (void) G_GNUC_CONST; G_END_DECLS diff --git a/libmatemixer/matemixer-enums.h b/libmatemixer/matemixer-enums.h index d83f283..cccb70d 100644 --- a/libmatemixer/matemixer-enums.h +++ b/libmatemixer/matemixer-enums.h @@ -24,18 +24,56 @@ */ typedef enum { - MATE_MIXER_BACKEND_TYPE_UNKNOWN, - MATE_MIXER_BACKEND_TYPE_PULSE, - MATE_MIXER_BACKEND_TYPE_NULL + MATE_MIXER_BACKEND_UNKNOWN, + MATE_MIXER_BACKEND_PULSE, + MATE_MIXER_BACKEND_NULL } MateMixerBackendType; -typedef enum { /*< flags >*/ - MATE_MIXER_DEVICE_PORT_DIRECTION_INPUT = 1 << 0, - MATE_MIXER_DEVICE_PORT_DIRECTION_OUTPUT = 1 << 1 -} MateMixerDevicePortDirection; +typedef enum { + MATE_MIXER_PORT_UNKNOWN_STATUS, + MATE_MIXER_PORT_AVAILABLE, + MATE_MIXER_PORT_UNAVAILABLE +} MateMixerPortStatus; typedef enum { /*< flags >*/ - MATE_MIXER_DEVICE_PORT_STATUS_AVAILABLE = 1 << 0 -} MateMixerDevicePortStatus; + MATE_MIXER_STREAM_INPUT = 1 << 0, + MATE_MIXER_STREAM_OUTPUT = 1 << 1, + MATE_MIXER_STREAM_CLIENT = 1 << 2, + MATE_MIXER_STREAM_VIRTUAL = 1 << 3, + MATE_MIXER_STREAM_OUTPUT_MONITOR = 1 << 4, + MATE_MIXER_STREAM_CAN_BALANCE = 1 << 5, + MATE_MIXER_STREAM_CAN_FADE = 1 << 6, + MATE_MIXER_STREAM_FLAT_VOLUME = 1 << 7 +} MateMixerStreamFlags; + +typedef enum { + MATE_MIXER_STREAM_UNKNOWN_STATUS, + MATE_MIXER_STREAM_RUNNING, + MATE_MIXER_STREAM_IDLE, + MATE_MIXER_STREAM_SUSPENDED +} MateMixerStreamStatus; + +typedef enum { + MATE_MIXER_CHANNEL_UNKNOWN_POSITION, + MATE_MIXER_CHANNEL_MONO, + MATE_MIXER_CHANNEL_FRONT_LEFT, + MATE_MIXER_CHANNEL_FRONT_RIGHT, + MATE_MIXER_CHANNEL_FRONT_CENTER, + MATE_MIXER_CHANNEL_LFE, + MATE_MIXER_CHANNEL_BACK_LEFT, + MATE_MIXER_CHANNEL_BACK_RIGHT, + MATE_MIXER_CHANNEL_FRONT_LEFT_CENTER, + MATE_MIXER_CHANNEL_FRONT_RIGHT_CENTER, + MATE_MIXER_CHANNEL_BACK_CENTER, + MATE_MIXER_CHANNEL_SIDE_LEFT, + MATE_MIXER_CHANNEL_SIDE_RIGHT, + MATE_MIXER_CHANNEL_TOP_FRONT_LEFT, + MATE_MIXER_CHANNEL_TOP_FRONT_RIGHT, + MATE_MIXER_CHANNEL_TOP_FRONT_CENTER, + MATE_MIXER_CHANNEL_TOP_CENTER, + MATE_MIXER_CHANNEL_TOP_BACK_LEFT, + MATE_MIXER_CHANNEL_TOP_BACK_RIGHT, + MATE_MIXER_CHANNEL_TOP_BACK_CENTER +} MateMixerChannelPosition; #endif /* MATEMIXER_ENUMS_H */ diff --git a/libmatemixer/matemixer-port.c b/libmatemixer/matemixer-port.c new file mode 100644 index 0000000..c4b2de3 --- /dev/null +++ b/libmatemixer/matemixer-port.c @@ -0,0 +1,256 @@ +/* + * Copyright (C) 2014 Michal Ratajsky + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the licence, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include +#include + +#include "matemixer-enums.h" +#include "matemixer-enum-types.h" +#include "matemixer-port.h" + +struct _MateMixerPortPrivate +{ + gchar *name; + gchar *description; + gchar *icon; + guint32 priority; + MateMixerPortStatus status; +}; + +enum +{ + PROP_0, + PROP_NAME, + PROP_DESCRIPTION, + PROP_ICON, + PROP_PRIORITY, + PROP_STATUS, + N_PROPERTIES +}; + +static GParamSpec *properties[N_PROPERTIES] = { NULL, }; + +static void mate_mixer_port_class_init (MateMixerPortClass *klass); +static void mate_mixer_port_init (MateMixerPort *port); +static void mate_mixer_port_finalize (GObject *object); + +G_DEFINE_TYPE (MateMixerPort, mate_mixer_port, G_TYPE_OBJECT); + +static void +mate_mixer_port_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec) +{ + MateMixerPort *port; + + port = MATE_MIXER_PORT (object); + + switch (param_id) { + case PROP_NAME: + g_value_set_string (value, port->priv->name); + break; + case PROP_DESCRIPTION: + g_value_set_string (value, port->priv->description); + break; + case PROP_ICON: + g_value_set_string (value, port->priv->icon); + break; + case PROP_PRIORITY: + g_value_set_uint (value, port->priv->priority); + break; + case PROP_STATUS: + g_value_set_enum (value, port->priv->status); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} + +static void +mate_mixer_port_set_property (GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec) +{ + MateMixerPort *port; + + port = MATE_MIXER_PORT (object); + + switch (param_id) { + case PROP_NAME: + port->priv->name = g_strdup (g_value_get_string (value)); + break; + case PROP_DESCRIPTION: + port->priv->description = g_strdup (g_value_get_string (value)); + break; + case PROP_ICON: + port->priv->icon = g_strdup (g_value_get_string (value)); + break; + case PROP_PRIORITY: + port->priv->priority = g_value_get_uint (value); + break; + case PROP_STATUS: + port->priv->status = g_value_get_enum (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} + +static void +mate_mixer_port_class_init (MateMixerPortClass *klass) +{ + GObjectClass *object_class; + + object_class = G_OBJECT_CLASS (klass); + object_class->finalize = mate_mixer_port_finalize; + object_class->get_property = mate_mixer_port_get_property; + object_class->set_property = mate_mixer_port_set_property; + + properties[PROP_NAME] = + g_param_spec_string ("name", + "Name", + "Name of the port", + NULL, + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + + properties[PROP_DESCRIPTION] = + g_param_spec_string ("description", + "Description", + "Description of the port", + NULL, + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + + properties[PROP_ICON] = + g_param_spec_string ("icon", + "Icon", + "Name of the port icon", + NULL, + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + + properties[PROP_PRIORITY] = + g_param_spec_uint ("priority", + "Priority", + "Priority of the port", + 0, + G_MAXUINT32, + 0, + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + + properties[PROP_STATUS] = + g_param_spec_enum ("status", + "Status", + "Status for the port", + MATE_MIXER_TYPE_PORT_STATUS, + MATE_MIXER_PORT_UNKNOWN_STATUS, + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, N_PROPERTIES, properties); + + g_type_class_add_private (object_class, sizeof (MateMixerPortPrivate)); +} + +static void +mate_mixer_port_init (MateMixerPort *port) +{ + port->priv = G_TYPE_INSTANCE_GET_PRIVATE (port, + MATE_MIXER_TYPE_PORT, + MateMixerPortPrivate); +} + +static void +mate_mixer_port_finalize (GObject *object) +{ + MateMixerPort *port; + + port = MATE_MIXER_PORT (object); + + g_free (port->priv->name); + g_free (port->priv->description); + g_free (port->priv->icon); + + G_OBJECT_CLASS (mate_mixer_port_parent_class)->finalize (object); +} + +MateMixerPort * +mate_mixer_port_new (const gchar *name, + const gchar *description, + const gchar *icon, + guint32 priority, + MateMixerPortStatus status) +{ + return g_object_new (MATE_MIXER_TYPE_PORT, + "name", name, + "description", description, + "icon", icon, + "priority", priority, + "status", status, + NULL); +} + +const gchar * +mate_mixer_port_get_name (MateMixerPort *port) +{ + g_return_val_if_fail (MATE_MIXER_IS_PORT (port), NULL); + + return port->priv->name; +} + +const gchar * +mate_mixer_port_get_description (MateMixerPort *port) +{ + g_return_val_if_fail (MATE_MIXER_IS_PORT (port), NULL); + + return port->priv->description; +} + +const gchar * +mate_mixer_port_get_icon (MateMixerPort *port) +{ + g_return_val_if_fail (MATE_MIXER_IS_PORT (port), NULL); + + return port->priv->icon; +} + +guint32 +mate_mixer_port_get_priority (MateMixerPort *port) +{ + g_return_val_if_fail (MATE_MIXER_IS_PORT (port), 0); + + return port->priv->priority; +} + +MateMixerPortStatus +mate_mixer_port_get_status (MateMixerPort *port) +{ + g_return_val_if_fail (MATE_MIXER_IS_PORT (port), MATE_MIXER_PORT_UNKNOWN_STATUS); + + return port->priv->status; +} diff --git a/libmatemixer/matemixer-port.h b/libmatemixer/matemixer-port.h new file mode 100644 index 0000000..581f4ec --- /dev/null +++ b/libmatemixer/matemixer-port.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2014 Michal Ratajsky + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the licence, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef MATEMIXER_PORT_H +#define MATEMIXER_PORT_H + +#include +#include + +#include + +G_BEGIN_DECLS + +#define MATE_MIXER_TYPE_PORT \ + (mate_mixer_port_get_type ()) +#define MATE_MIXER_PORT(o) \ + (G_TYPE_CHECK_INSTANCE_CAST ((o), MATE_MIXER_TYPE_PORT, MateMixerPort)) +#define MATE_MIXER_IS_PORT(o) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((o), MATE_MIXER_TYPE_PORT)) +#define MATE_MIXER_PORT_CLASS(k) \ + (G_TYPE_CHECK_CLASS_CAST ((k), MATE_MIXER_TYPE_PORT, MateMixerPortClass)) +#define MATE_MIXER_IS_PORT_CLASS(k) \ + (G_TYPE_CLASS_CHECK_CLASS_TYPE ((k), MATE_MIXER_TYPE_PORT)) +#define MATE_MIXER_PORT_GET_CLASS(o) \ + (G_TYPE_INSTANCE_GET_CLASS ((o), MATE_MIXER_TYPE_PORT, MateMixerPortClass)) + +typedef struct _MateMixerPort MateMixerPort; +typedef struct _MateMixerPortClass MateMixerPortClass; +typedef struct _MateMixerPortPrivate MateMixerPortPrivate; + +struct _MateMixerPort +{ + GObject parent; + + MateMixerPortPrivate *priv; +}; + +struct _MateMixerPortClass +{ + GObjectClass parent; +}; + +GType mate_mixer_port_get_type (void) G_GNUC_CONST; + +MateMixerPort * mate_mixer_port_new (const gchar *name, + const gchar *description, + const gchar *icon, + guint32 priority, + MateMixerPortStatus status); + +const gchar * mate_mixer_port_get_name (MateMixerPort *port); +const gchar * mate_mixer_port_get_description (MateMixerPort *port); +const gchar * mate_mixer_port_get_icon (MateMixerPort *port); +guint32 mate_mixer_port_get_priority (MateMixerPort *port); +MateMixerPortStatus mate_mixer_port_get_status (MateMixerPort *port); + +G_END_DECLS + +#endif /* MATEMIXER_PORT_H */ diff --git a/libmatemixer/matemixer-private.h b/libmatemixer/matemixer-private.h index 8f95664..0eb012a 100644 --- a/libmatemixer/matemixer-private.h +++ b/libmatemixer/matemixer-private.h @@ -22,8 +22,8 @@ G_BEGIN_DECLS -GList *mate_mixer_get_modules (void); -gboolean mate_mixer_is_initialized (void); +const GList *mate_mixer_get_modules (void); +gboolean mate_mixer_is_initialized (void); G_END_DECLS diff --git a/libmatemixer/matemixer-profile.c b/libmatemixer/matemixer-profile.c new file mode 100644 index 0000000..c32489f --- /dev/null +++ b/libmatemixer/matemixer-profile.c @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2014 Michal Ratajsky + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the licence, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include +#include + +#include "matemixer-profile.h" + +struct _MateMixerProfilePrivate +{ + gchar *name; + gchar *description; + guint32 priority; +}; + +enum +{ + PROP_0, + PROP_NAME, + PROP_DESCRIPTION, + PROP_PRIORITY, + N_PROPERTIES +}; + +static GParamSpec *properties[N_PROPERTIES] = { NULL, }; + +static void mate_mixer_profile_class_init (MateMixerProfileClass *klass); +static void mate_mixer_profile_init (MateMixerProfile *profile); +static void mate_mixer_profile_finalize (GObject *object); + +G_DEFINE_TYPE (MateMixerProfile, mate_mixer_profile, G_TYPE_OBJECT); + +static void +mate_mixer_profile_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec) +{ + MateMixerProfile *profile; + + profile = MATE_MIXER_PROFILE (object); + + switch (param_id) { + case PROP_NAME: + g_value_set_string (value, profile->priv->name); + break; + case PROP_DESCRIPTION: + g_value_set_string (value, profile->priv->description); + break; + case PROP_PRIORITY: + g_value_set_uint (value, profile->priv->priority); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} + +static void +mate_mixer_profile_set_property (GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec) +{ + MateMixerProfile *profile; + + profile = MATE_MIXER_PROFILE (object); + + switch (param_id) { + case PROP_NAME: + profile->priv->name = g_strdup (g_value_get_string (value)); + break; + case PROP_DESCRIPTION: + profile->priv->description = g_strdup (g_value_get_string (value)); + break; + case PROP_PRIORITY: + profile->priv->priority = g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} + +static void +mate_mixer_profile_class_init (MateMixerProfileClass *klass) +{ + GObjectClass *object_class; + + object_class = G_OBJECT_CLASS (klass); + object_class->finalize = mate_mixer_profile_finalize; + object_class->get_property = mate_mixer_profile_get_property; + object_class->set_property = mate_mixer_profile_set_property; + + properties[PROP_NAME] = + g_param_spec_string ("name", + "Name", + "Name of the profile", + NULL, + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + + properties[PROP_DESCRIPTION] = + g_param_spec_string ("description", + "Description", + "Description of the profile", + NULL, + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + + properties[PROP_PRIORITY] = + g_param_spec_uint ("priority", + "Priority", + "Priority of the profile", + 0, + G_MAXUINT32, + 0, + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, N_PROPERTIES, properties); + + g_type_class_add_private (object_class, sizeof (MateMixerProfilePrivate)); +} + +static void +mate_mixer_profile_init (MateMixerProfile *profile) +{ + profile->priv = G_TYPE_INSTANCE_GET_PRIVATE (profile, + MATE_MIXER_TYPE_PROFILE, + MateMixerProfilePrivate); +} + +static void +mate_mixer_profile_finalize (GObject *object) +{ + MateMixerProfile *profile; + + profile = MATE_MIXER_PROFILE (object); + + g_free (profile->priv->name); + g_free (profile->priv->description); + + G_OBJECT_CLASS (mate_mixer_profile_parent_class)->finalize (object); +} + +MateMixerProfile * +mate_mixer_profile_new (const gchar *name, const gchar *description, guint32 priority) +{ + return g_object_new (MATE_MIXER_TYPE_PROFILE, + "name", name, + "description", description, + "priority", priority, + NULL); +} + +const gchar * +mate_mixer_profile_get_name (MateMixerProfile *profile) +{ + g_return_val_if_fail (MATE_MIXER_IS_PROFILE (profile), NULL); + + return profile->priv->name; +} + +const gchar * +mate_mixer_profile_get_description (MateMixerProfile *profile) +{ + g_return_val_if_fail (MATE_MIXER_IS_PROFILE (profile), NULL); + + return profile->priv->description; +} + +guint32 +mate_mixer_profile_get_priority (MateMixerProfile *profile) +{ + g_return_val_if_fail (MATE_MIXER_IS_PROFILE (profile), G_MAXUINT32); + + return profile->priv->priority; +} diff --git a/libmatemixer/matemixer-profile.h b/libmatemixer/matemixer-profile.h new file mode 100644 index 0000000..7be140b --- /dev/null +++ b/libmatemixer/matemixer-profile.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2014 Michal Ratajsky + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the licence, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef MATEMIXER_PROFILE_H +#define MATEMIXER_PROFILE_H + +#include +#include + +G_BEGIN_DECLS + +#define MATE_MIXER_TYPE_PROFILE \ + (mate_mixer_profile_get_type ()) +#define MATE_MIXER_PROFILE(o) \ + (G_TYPE_CHECK_INSTANCE_CAST ((o), MATE_MIXER_TYPE_PROFILE, MateMixerProfile)) +#define MATE_MIXER_IS_PROFILE(o) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((o), MATE_MIXER_TYPE_PROFILE)) +#define MATE_MIXER_PROFILE_CLASS(k) \ + (G_TYPE_CHECK_CLASS_CAST ((k), MATE_MIXER_TYPE_PROFILE, MateMixerProfileClass)) +#define MATE_MIXER_IS_PROFILE_CLASS(k) \ + (G_TYPE_CLASS_CHECK_CLASS_TYPE ((k), MATE_MIXER_TYPE_PROFILE)) +#define MATE_MIXER_PROFILE_GET_CLASS(o) \ + (G_TYPE_INSTANCE_GET_CLASS ((o), MATE_MIXER_TYPE_PROFILE, MateMixerProfileClass)) + +typedef struct _MateMixerProfile MateMixerProfile; +typedef struct _MateMixerProfileClass MateMixerProfileClass; +typedef struct _MateMixerProfilePrivate MateMixerProfilePrivate; + +struct _MateMixerProfile +{ + GObject parent; + + MateMixerProfilePrivate *priv; +}; + +struct _MateMixerProfileClass +{ + GObjectClass parent; +}; + +GType mate_mixer_profile_get_type (void) G_GNUC_CONST; + +MateMixerProfile *mate_mixer_profile_new (const gchar *name, + const gchar *description, + guint32 priority); + +const gchar * mate_mixer_profile_get_name (MateMixerProfile *profile); +const gchar * mate_mixer_profile_get_description (MateMixerProfile *profile); +guint32 mate_mixer_profile_get_priority (MateMixerProfile *profile); + +G_END_DECLS + +#endif /* MATEMIXER_PROFILE_H */ diff --git a/libmatemixer/matemixer-stream.c b/libmatemixer/matemixer-stream.c new file mode 100644 index 0000000..62e0d2e --- /dev/null +++ b/libmatemixer/matemixer-stream.c @@ -0,0 +1,531 @@ +/* + * Copyright (C) 2014 Michal Ratajsky + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the licence, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include +#include + +#include "matemixer-device.h" +#include "matemixer-enums.h" +#include "matemixer-enum-types.h" +#include "matemixer-port.h" +#include "matemixer-stream.h" + +G_DEFINE_INTERFACE (MateMixerStream, mate_mixer_stream, G_TYPE_OBJECT) + +static void +mate_mixer_stream_default_init (MateMixerStreamInterface *iface) +{ + g_object_interface_install_property (iface, + g_param_spec_string ("name", + "Name", + "Name of the stream", + NULL, + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + g_object_interface_install_property (iface, + g_param_spec_string ("description", + "Description", + "Description of the stream", + NULL, + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + g_object_interface_install_property (iface, + g_param_spec_string ("icon", + "Icon", + "Name of the stream icon", + NULL, + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + g_object_interface_install_property (iface, + g_param_spec_object ("device", + "Device", + "Device the stream belongs to", + MATE_MIXER_TYPE_DEVICE, + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + g_object_interface_install_property (iface, + g_param_spec_enum ("status", + "Status", + "Status of the stream", + MATE_MIXER_TYPE_STREAM_STATUS, + MATE_MIXER_STREAM_UNKNOWN_STATUS, + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + g_object_interface_install_property (iface, + g_param_spec_double ("volume", + "Volume", + "Volume of the stream", + -1, 0, 1, + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + g_object_interface_install_property (iface, + g_param_spec_string ("mute", + "Mute", + "Mute state of the stream", + FALSE, + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); +} + +const gchar * +mate_mixer_stream_get_name (MateMixerStream *stream) +{ + MateMixerStreamInterface *iface; + + g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), NULL); + + iface = MATE_MIXER_STREAM_GET_INTERFACE (stream); + + if (iface->get_name) + return iface->get_name (stream); + + return NULL; +} + +const gchar * +mate_mixer_stream_get_description (MateMixerStream *stream) +{ + MateMixerStreamInterface *iface; + + g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), NULL); + + iface = MATE_MIXER_STREAM_GET_INTERFACE (stream); + + if (iface->get_description) + return iface->get_description (stream); + + return NULL; +} + +const gchar * +mate_mixer_stream_get_icon (MateMixerStream *stream) +{ + MateMixerStreamInterface *iface; + + g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), NULL); + + iface = MATE_MIXER_STREAM_GET_INTERFACE (stream); + + if (iface->get_icon) + return iface->get_icon (stream); + + return NULL; +} + +MateMixerDevice * +mate_mixer_stream_get_device (MateMixerStream *stream) +{ + MateMixerStreamInterface *iface; + + g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), NULL); + + iface = MATE_MIXER_STREAM_GET_INTERFACE (stream); + + if (iface->get_device) + return iface->get_device (stream); + + return NULL; +} + +MateMixerStreamStatus +mate_mixer_stream_get_status (MateMixerStream *stream) +{ + MateMixerStreamInterface *iface; + + g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), MATE_MIXER_STREAM_UNKNOWN_STATUS); + + iface = MATE_MIXER_STREAM_GET_INTERFACE (stream); + + if (iface->get_status) + return iface->get_status (stream); + + return MATE_MIXER_STREAM_UNKNOWN_STATUS; +} + +gboolean +mate_mixer_stream_get_mute (MateMixerStream *stream) +{ + MateMixerStreamInterface *iface; + + g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), FALSE); + + iface = MATE_MIXER_STREAM_GET_INTERFACE (stream); + + if (iface->get_mute) + return iface->get_mute (stream); + + return FALSE; +} + +gboolean +mate_mixer_stream_set_mute (MateMixerStream *stream, gboolean mute) +{ + MateMixerStreamInterface *iface; + + g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), FALSE); + + iface = MATE_MIXER_STREAM_GET_INTERFACE (stream); + + if (iface->set_mute) + return iface->set_mute (stream, mute); + + return FALSE; +} + +guint32 +mate_mixer_stream_get_volume (MateMixerStream *stream) +{ + MateMixerStreamInterface *iface; + + g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), 0); + + iface = MATE_MIXER_STREAM_GET_INTERFACE (stream); + + if (iface->get_volume) + return iface->get_volume (stream); + + return 0; +} + +gboolean +mate_mixer_stream_set_volume (MateMixerStream *stream, guint32 volume) +{ + MateMixerStreamInterface *iface; + + g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), FALSE); + + iface = MATE_MIXER_STREAM_GET_INTERFACE (stream); + + if (iface->set_volume) + return iface->set_volume (stream, volume); + + return FALSE; +} + +gdouble +mate_mixer_stream_get_volume_db (MateMixerStream *stream) +{ + MateMixerStreamInterface *iface; + + g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), 0); + + iface = MATE_MIXER_STREAM_GET_INTERFACE (stream); + + if (iface->get_volume_db) + return iface->get_volume_db (stream); + + return 0; +} + +gboolean +mate_mixer_stream_set_volume_db (MateMixerStream *stream, gdouble volume_db) +{ + MateMixerStreamInterface *iface; + + g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), FALSE); + + iface = MATE_MIXER_STREAM_GET_INTERFACE (stream); + + if (iface->set_volume_db) + return iface->set_volume_db (stream, volume_db); + + return FALSE; +} + +guint8 +mate_mixer_stream_get_num_channels (MateMixerStream *stream) +{ + MateMixerStreamInterface *iface; + + g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), 0); + + iface = MATE_MIXER_STREAM_GET_INTERFACE (stream); + + if (iface->get_num_channels) + return iface->get_num_channels (stream); + + return 0; +} + +MateMixerChannelPosition +mate_mixer_stream_get_channel_position (MateMixerStream *stream, guint8 channel) +{ + MateMixerStreamInterface *iface; + + g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), MATE_MIXER_CHANNEL_UNKNOWN_POSITION); + + iface = MATE_MIXER_STREAM_GET_INTERFACE (stream); + + if (iface->get_channel_position) + return iface->get_channel_position (stream, channel); + + return MATE_MIXER_CHANNEL_UNKNOWN_POSITION; +} + +guint32 +mate_mixer_stream_get_channel_volume (MateMixerStream *stream, guint8 channel) +{ + MateMixerStreamInterface *iface; + + g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), 0); + + iface = MATE_MIXER_STREAM_GET_INTERFACE (stream); + + if (iface->get_channel_volume) + return iface->get_channel_volume (stream, channel); + + return 0; +} + +gboolean +mate_mixer_stream_set_channel_volume (MateMixerStream *stream, guint8 channel, guint32 volume) +{ + MateMixerStreamInterface *iface; + + g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), FALSE); + + iface = MATE_MIXER_STREAM_GET_INTERFACE (stream); + + if (iface->set_channel_volume) + return iface->set_channel_volume (stream, channel, volume); + + return FALSE; +} + +gdouble +mate_mixer_stream_get_channel_volume_db (MateMixerStream *stream, guint8 channel) +{ + MateMixerStreamInterface *iface; + + g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), 0); + + iface = MATE_MIXER_STREAM_GET_INTERFACE (stream); + + if (iface->get_channel_volume_db) + return iface->get_channel_volume_db (stream, channel); + + return 0; +} + +gboolean +mate_mixer_stream_set_channel_volume_db (MateMixerStream *stream, guint8 channel, gdouble volume_db) +{ + MateMixerStreamInterface *iface; + + g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), FALSE); + + iface = MATE_MIXER_STREAM_GET_INTERFACE (stream); + + if (iface->set_channel_volume_db) + return iface->set_channel_volume_db (stream, channel, volume_db); + + return FALSE; +} + +gboolean +mate_mixer_stream_has_position (MateMixerStream *stream, MateMixerChannelPosition position) +{ + MateMixerStreamInterface *iface; + + g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), FALSE); + + iface = MATE_MIXER_STREAM_GET_INTERFACE (stream); + + if (iface->has_position) + return iface->has_position (stream, position); + + return FALSE; +} + +guint32 +mate_mixer_stream_get_position_volume (MateMixerStream *stream, MateMixerChannelPosition position) +{ + MateMixerStreamInterface *iface; + + g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), 0); + + iface = MATE_MIXER_STREAM_GET_INTERFACE (stream); + + if (iface->get_position_volume) + return iface->get_position_volume (stream, position); + + return 0; +} + +gboolean +mate_mixer_stream_set_position_volume (MateMixerStream *stream, MateMixerChannelPosition position, guint32 volume) +{ + MateMixerStreamInterface *iface; + + g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), FALSE); + + iface = MATE_MIXER_STREAM_GET_INTERFACE (stream); + + if (iface->set_position_volume) + return iface->set_position_volume (stream, position, volume); + + return FALSE; +} + +gdouble +mate_mixer_stream_get_position_volume_db (MateMixerStream *stream, MateMixerChannelPosition position) +{ + MateMixerStreamInterface *iface; + + g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), 0); + + iface = MATE_MIXER_STREAM_GET_INTERFACE (stream); + + if (iface->get_position_volume_db) + return iface->get_position_volume_db (stream, position); + + return 0; +} + +gboolean +mate_mixer_stream_set_position_volume_db (MateMixerStream *stream, MateMixerChannelPosition position, gdouble volume_db) +{ + MateMixerStreamInterface *iface; + + g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), FALSE); + + iface = MATE_MIXER_STREAM_GET_INTERFACE (stream); + + if (iface->set_position_volume_db) + return iface->set_position_volume_db (stream, position, volume_db); + + return FALSE; +} + +gdouble +mate_mixer_stream_get_balance (MateMixerStream *stream) +{ + MateMixerStreamInterface *iface; + + g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), 0); + + iface = MATE_MIXER_STREAM_GET_INTERFACE (stream); + + if (iface->get_balance) + return iface->get_balance (stream); + + return 0; +} + +gboolean +mate_mixer_stream_set_balance (MateMixerStream *stream, gdouble balance) +{ + MateMixerStreamInterface *iface; + + g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), FALSE); + + iface = MATE_MIXER_STREAM_GET_INTERFACE (stream); + + if (iface->set_balance) + return iface->set_balance (stream, balance); + + return FALSE; +} + +gdouble +mate_mixer_stream_get_fade (MateMixerStream *stream) +{ + MateMixerStreamInterface *iface; + + g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), 0); + + iface = MATE_MIXER_STREAM_GET_INTERFACE (stream); + + if (iface->get_fade) + return iface->get_fade (stream); + + return 0; +} + +gboolean +mate_mixer_stream_set_fade (MateMixerStream *stream, gdouble fade) +{ + MateMixerStreamInterface *iface; + + g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), FALSE); + + iface = MATE_MIXER_STREAM_GET_INTERFACE (stream); + + if (iface->set_fade) + return iface->set_fade (stream, fade); + + return FALSE; +} + +const GList * +mate_mixer_stream_list_ports (MateMixerStream *stream) +{ + MateMixerStreamInterface *iface; + + g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), NULL); + + iface = MATE_MIXER_STREAM_GET_INTERFACE (stream); + + if (iface->list_ports) + return iface->list_ports (stream); + + return NULL; +} + +MateMixerPort * +mate_mixer_stream_get_active_port (MateMixerStream *stream) +{ + MateMixerStreamInterface *iface; + + g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), NULL); + + iface = MATE_MIXER_STREAM_GET_INTERFACE (stream); + + if (iface->get_active_port) + return iface->get_active_port (stream); + + return NULL; +} + +gboolean +mate_mixer_stream_set_active_port (MateMixerStream *stream, MateMixerPort *port) +{ + MateMixerStreamInterface *iface; + + g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), FALSE); + g_return_val_if_fail (MATE_MIXER_IS_PORT (port), FALSE); + + iface = MATE_MIXER_STREAM_GET_INTERFACE (stream); + + if (iface->set_active_port) + return iface->set_active_port (stream, port); + + return FALSE; +} diff --git a/libmatemixer/matemixer-stream.h b/libmatemixer/matemixer-stream.h new file mode 100644 index 0000000..f95f13f --- /dev/null +++ b/libmatemixer/matemixer-stream.h @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2014 Michal Ratajsky + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the licence, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef MATEMIXER_STREAM_H +#define MATEMIXER_STREAM_H + +#include +#include + +#include +#include +#include + +G_BEGIN_DECLS + +#define MATE_MIXER_TYPE_STREAM \ + (mate_mixer_stream_get_type ()) +#define MATE_MIXER_STREAM(o) \ + (G_TYPE_CHECK_INSTANCE_CAST ((o), MATE_MIXER_TYPE_STREAM, MateMixerStream)) +#define MATE_MIXER_IS_STREAM(o) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((o), MATE_MIXER_TYPE_STREAM)) +#define MATE_MIXER_STREAM_GET_INTERFACE(o) \ + (G_TYPE_INSTANCE_GET_INTERFACE ((o), MATE_MIXER_TYPE_STREAM, MateMixerStreamInterface)) + +typedef struct _MateMixerStream MateMixerStream; /* dummy object */ +typedef struct _MateMixerStreamInterface MateMixerStreamInterface; + +struct _MateMixerStreamInterface +{ + GTypeInterface parent; + + const gchar * (*get_name) (MateMixerStream *stream); + const gchar * (*get_description) (MateMixerStream *stream); + const gchar * (*get_icon) (MateMixerStream *stream); + MateMixerDevice * (*get_device) (MateMixerStream *stream); + MateMixerStreamStatus (*get_status) (MateMixerStream *stream); + gboolean (*get_mute) (MateMixerStream *stream); + gboolean (*set_mute) (MateMixerStream *stream, + gboolean mute); + guint32 (*get_volume) (MateMixerStream *stream); + gboolean (*set_volume) (MateMixerStream *stream, + guint32 volume); + gdouble (*get_volume_db) (MateMixerStream *stream); + gboolean (*set_volume_db) (MateMixerStream *stream, + gdouble volume_db); + guint8 (*get_num_channels) (MateMixerStream *stream); + MateMixerChannelPosition (*get_channel_position) (MateMixerStream *stream, + guint8 channel); + guint32 (*get_channel_volume) (MateMixerStream *stream, + guint8 channel); + gboolean (*set_channel_volume) (MateMixerStream *stream, + guint8 channel, + guint32 volume); + gdouble (*get_channel_volume_db) (MateMixerStream *stream, + guint8 channel); + gboolean (*set_channel_volume_db) (MateMixerStream *stream, + guint8 channel, + gdouble volume_db); + gboolean (*has_position) (MateMixerStream *stream, + MateMixerChannelPosition position); + guint32 (*get_position_volume) (MateMixerStream *stream, + MateMixerChannelPosition position); + gboolean (*set_position_volume) (MateMixerStream *stream, + MateMixerChannelPosition position, + guint32 volume); + gdouble (*get_position_volume_db) (MateMixerStream *stream, + MateMixerChannelPosition position); + gboolean (*set_position_volume_db) (MateMixerStream *stream, + MateMixerChannelPosition position, + gdouble volume); + gboolean (*get_balance) (MateMixerStream *stream); + gboolean (*set_balance) (MateMixerStream *stream, + gdouble balance); + gboolean (*get_fade) (MateMixerStream *stream); + gboolean (*set_fade) (MateMixerStream *stream, + gdouble fade); + MateMixerPort * (*get_active_port) (MateMixerStream *stream); + gboolean (*set_active_port) (MateMixerStream *stream, + MateMixerPort *port); + const GList * (*list_ports) (MateMixerStream *stream); +}; + +GType mate_mixer_stream_get_type (void) G_GNUC_CONST; + +const gchar * mate_mixer_stream_get_name (MateMixerStream *stream); +const gchar * mate_mixer_stream_get_description (MateMixerStream *stream); +const gchar * mate_mixer_stream_get_icon (MateMixerStream *stream); +MateMixerDevice * mate_mixer_stream_get_device (MateMixerStream *stream); +MateMixerStreamStatus mate_mixer_stream_get_status (MateMixerStream *stream); + +gboolean mate_mixer_stream_get_mute (MateMixerStream *stream); +gboolean mate_mixer_stream_set_mute (MateMixerStream *stream, + gboolean mute); + +guint32 mate_mixer_stream_get_volume (MateMixerStream *stream); +gboolean mate_mixer_stream_set_volume (MateMixerStream *stream, + guint32 volume); + +gdouble mate_mixer_stream_get_volume_db (MateMixerStream *stream); +gboolean mate_mixer_stream_set_volume_db (MateMixerStream *stream, + gdouble volume_db); + +guint8 mate_mixer_stream_get_num_channels (MateMixerStream *stream); + +MateMixerChannelPosition mate_mixer_stream_get_channel_position (MateMixerStream *stream, + guint8 channel); + +guint32 mate_mixer_stream_get_channel_volume (MateMixerStream *stream, + guint8 channel); +gboolean mate_mixer_stream_set_channel_volume (MateMixerStream *stream, + guint8 channel, + guint32 volume); + +gdouble mate_mixer_stream_get_channel_volume_db (MateMixerStream *stream, + guint8 channel); +gboolean mate_mixer_stream_set_channel_volume_db (MateMixerStream *stream, + guint8 channel, + gdouble volume_db); + +gboolean mate_mixer_stream_has_position (MateMixerStream *stream, + MateMixerChannelPosition position); + +guint32 mate_mixer_stream_get_position_volume (MateMixerStream *stream, + MateMixerChannelPosition position); +gboolean mate_mixer_stream_set_position_volume (MateMixerStream *stream, + MateMixerChannelPosition position, + guint32 volume); + +gdouble mate_mixer_stream_get_position_volume_db (MateMixerStream *stream, + MateMixerChannelPosition position); +gboolean mate_mixer_stream_set_position_volume_db (MateMixerStream *stream, + MateMixerChannelPosition position, + gdouble volume_db); + +gdouble mate_mixer_stream_get_balance (MateMixerStream *stream); +gboolean mate_mixer_stream_set_balance (MateMixerStream *stream, + gdouble balance); + +gdouble mate_mixer_stream_get_fade (MateMixerStream *stream); +gboolean mate_mixer_stream_set_fade (MateMixerStream *stream, + gdouble fade); + +const GList * mate_mixer_stream_list_ports (MateMixerStream *stream); + +MateMixerPort * mate_mixer_stream_get_active_port (MateMixerStream *stream); +gboolean mate_mixer_stream_set_active_port (MateMixerStream *stream, + MateMixerPort *port); + +G_END_DECLS + +#endif /* MATEMIXER_STREAM_H */ diff --git a/libmatemixer/matemixer-track.c b/libmatemixer/matemixer-track.c deleted file mode 100644 index f78c4f8..0000000 --- a/libmatemixer/matemixer-track.c +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2014 Michal Ratajsky - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the licence, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - */ - -#include -#include - -#include "matemixer-track.h" - -G_DEFINE_INTERFACE (MateMixerTrack, mate_mixer_track, G_TYPE_OBJECT) - -static void -mate_mixer_track_default_init (MateMixerTrackInterface *iface) -{ - // TODO: properties -} diff --git a/libmatemixer/matemixer-track.h b/libmatemixer/matemixer-track.h deleted file mode 100644 index a535b59..0000000 --- a/libmatemixer/matemixer-track.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2014 Michal Ratajsky - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the licence, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - */ - -#ifndef MATEMIXER_TRACK_H -#define MATEMIXER_TRACK_H - -#include -#include - -G_BEGIN_DECLS - -#define MATE_MIXER_TYPE_TRACK \ - (mate_mixer_track_get_type ()) -#define MATE_MIXER_TRACK(o) \ - (G_TYPE_CHECK_INSTANCE_CAST ((o), MATE_MIXER_TYPE_TRACK, MateMixerTrack)) -#define MATE_MIXER_IS_TRACK(o) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((o), MATE_MIXER_TYPE_TRACK)) -#define MATE_MIXER_TRACK_GET_INTERFACE(o) \ - (G_TYPE_INSTANCE_GET_INTERFACE ((o), MATE_MIXER_TYPE_TRACK, MateMixerTrackInterface)) - -typedef struct _MateMixerTrack MateMixerTrack; /* dummy object */ -typedef struct _MateMixerTrackInterface MateMixerTrackInterface; - -struct _MateMixerTrackInterface -{ - GTypeInterface parent; -}; - -GType mate_mixer_track_get_type (void) G_GNUC_CONST; - -G_END_DECLS - -#endif /* MATEMIXER_TRACK_H */ diff --git a/libmatemixer/matemixer.c b/libmatemixer/matemixer.c index cc4b5f1..3c8f643 100644 --- a/libmatemixer/matemixer.c +++ b/libmatemixer/matemixer.c @@ -55,11 +55,8 @@ mate_mixer_init (void) } if (mixer_modules) { - /* Sort the usable modules by the priority */ - mixer_modules = g_list_sort ( - mixer_modules, - mixer_compare_modules); - + /* Sort the usable modules by their priority */ + mixer_modules = g_list_sort (mixer_modules, mixer_compare_modules); mixer_initialized = TRUE; } else g_critical ("No usable backend modules have been found"); @@ -85,11 +82,11 @@ mate_mixer_deinit (void) mixer_initialized = FALSE; } -/* Internal function: return a shared list of loaded backend modules */ -GList * +/* Internal function: return a list of loaded backend modules */ +const GList * mate_mixer_get_modules (void) { - return mixer_modules; + return (const GList *) mixer_modules; } /* Internal function: return TRUE if the library has been initialized */ @@ -124,10 +121,8 @@ mixer_load_modules (void) continue; file = g_build_filename (LIBMATEMIXER_BACKEND_DIR, name, NULL); - mixer_modules = g_list_prepend ( - mixer_modules, - mate_mixer_backend_module_new (file)); - + mixer_modules = g_list_prepend (mixer_modules, + mate_mixer_backend_module_new (file)); g_free (file); } @@ -151,7 +146,7 @@ mixer_load_modules (void) static gint mixer_compare_modules (gconstpointer a, gconstpointer b) { - const MateMixerBackendModuleInfo *info1, *info2; + const MateMixerBackendInfo *info1, *info2; info1 = mate_mixer_backend_module_get_info (MATE_MIXER_BACKEND_MODULE (a)); info2 = mate_mixer_backend_module_get_info (MATE_MIXER_BACKEND_MODULE (b)); diff --git a/libmatemixer/matemixer.h b/libmatemixer/matemixer.h index 8a62320..b43de79 100644 --- a/libmatemixer/matemixer.h +++ b/libmatemixer/matemixer.h @@ -22,7 +22,7 @@ #include #include #include -#include +#include G_BEGIN_DECLS -- cgit v1.2.1