From a2290d5e13ccee88fd9ae66a3895eb4da646f81f Mon Sep 17 00:00:00 2001 From: Michal Ratajsky Date: Fri, 13 Jun 2014 17:36:14 +0200 Subject: Weekly update --- libmatemixer/Makefile.am | 8 +- libmatemixer/matemixer-backend-module.c | 22 +- libmatemixer/matemixer-backend-module.h | 6 +- libmatemixer/matemixer-backend.c | 163 ++++- libmatemixer/matemixer-backend.h | 70 ++- libmatemixer/matemixer-client-stream.c | 83 +++ libmatemixer/matemixer-client-stream.h | 59 ++ libmatemixer/matemixer-control.c | 1043 +++++++++++++++++++++++++++++-- libmatemixer/matemixer-control.h | 67 +- libmatemixer/matemixer-device.c | 7 +- libmatemixer/matemixer-device.h | 8 +- libmatemixer/matemixer-enum-types.c | 30 +- libmatemixer/matemixer-enum-types.h | 13 +- libmatemixer/matemixer-enums.h | 61 +- libmatemixer/matemixer-port.c | 102 ++- libmatemixer/matemixer-port.h | 32 +- libmatemixer/matemixer-profile.c | 65 +- libmatemixer/matemixer-profile.h | 16 +- libmatemixer/matemixer-stream.c | 131 +++- libmatemixer/matemixer-stream.h | 69 +- libmatemixer/matemixer-version.h.in | 64 ++ libmatemixer/matemixer.c | 27 +- libmatemixer/matemixer.h | 4 +- 23 files changed, 1848 insertions(+), 302 deletions(-) create mode 100644 libmatemixer/matemixer-client-stream.c create mode 100644 libmatemixer/matemixer-client-stream.h create mode 100644 libmatemixer/matemixer-version.h.in (limited to 'libmatemixer') diff --git a/libmatemixer/Makefile.am b/libmatemixer/Makefile.am index 0280b27..a45b29c 100644 --- a/libmatemixer/Makefile.am +++ b/libmatemixer/Makefile.am @@ -10,12 +10,14 @@ libmatemixer_includedir = $(includedir)/libmatemixer libmatemixer_include_HEADERS = \ matemixer.h \ + matemixer-client-stream.h \ matemixer-control.h \ matemixer-device.h \ matemixer-enums.h \ matemixer-port.h \ matemixer-profile.h \ - matemixer-stream.h + matemixer-stream.h \ + matemixer-version.h libmatemixer_la_CFLAGS = $(GLIB_CFLAGS) @@ -26,6 +28,7 @@ libmatemixer_la_SOURCES = \ matemixer-backend.h \ matemixer-backend-module.c \ matemixer-backend-module.h \ + matemixer-client-stream.c \ matemixer-control.c \ matemixer-device.c \ matemixer-enum-types.c \ @@ -38,6 +41,9 @@ libmatemixer_la_LIBADD = $(GLIB_LIBS) libmatemixer_la_LDFLAGS = \ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ + -no-undefined \ -export-dynamic +EXTRA_DIST = matemixer-version.h.in + -include $(top_srcdir)/git.mk diff --git a/libmatemixer/matemixer-backend-module.c b/libmatemixer/matemixer-backend-module.c index 5ad2836..b04ad6f 100644 --- a/libmatemixer/matemixer-backend-module.c +++ b/libmatemixer/matemixer-backend-module.c @@ -22,8 +22,6 @@ #include "matemixer-backend.h" #include "matemixer-backend-module.h" -G_DEFINE_TYPE (MateMixerBackendModule, mate_mixer_backend_module, G_TYPE_TYPE_MODULE); - struct _MateMixerBackendModulePrivate { GModule *gmodule; @@ -44,6 +42,8 @@ static void mate_mixer_backend_module_finalize (GObject static gboolean mate_mixer_backend_module_load (GTypeModule *gmodule); static void mate_mixer_backend_module_unload (GTypeModule *gmodule); +G_DEFINE_TYPE (MateMixerBackendModule, mate_mixer_backend_module, G_TYPE_TYPE_MODULE); + static void mate_mixer_backend_module_class_init (MateMixerBackendModuleClass *klass) { @@ -58,7 +58,7 @@ mate_mixer_backend_module_class_init (MateMixerBackendModuleClass *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)); + g_type_class_add_private (klass, sizeof (MateMixerBackendModulePrivate)); } static void @@ -88,11 +88,7 @@ mate_mixer_backend_module_dispose (GObject *object) static void mate_mixer_backend_module_finalize (GObject *object) { - MateMixerBackendModule *module; - - module = MATE_MIXER_BACKEND_MODULE (object); - - g_free (module->priv->path); + g_free (MATE_MIXER_BACKEND_MODULE (object)->priv->path); G_OBJECT_CLASS (mate_mixer_backend_module_parent_class)->finalize (object); } @@ -139,8 +135,8 @@ mate_mixer_backend_module_load (GTypeModule *type_module) module->priv->init (type_module); module->priv->loaded = TRUE; - /* Make sure get_info () returns something so we can avoid checking - * it in other parts of the library */ + /* Make sure get_info() returns something so we can avoid checking 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); @@ -158,7 +154,7 @@ mate_mixer_backend_module_load (GTypeModule *type_module) g_debug ("Loaded backend module %s", module->priv->path); } else { - /* This function was called before so initialize only */ + /* This function was called before, so initialize only */ module->priv->init (type_module); } return TRUE; @@ -171,8 +167,8 @@ mate_mixer_backend_module_unload (GTypeModule *type_module) module = MATE_MIXER_BACKEND_MODULE (type_module); - /* Only deinitialize the backend module, do not modify the loaded - * flag as the module remains loaded */ + /* Only deinitialize the backend module, do not modify the loaded flag + * as the module remains loaded */ if (module->priv->deinit) module->priv->deinit (); } diff --git a/libmatemixer/matemixer-backend-module.h b/libmatemixer/matemixer-backend-module.h index b629bfc..61a426d 100644 --- a/libmatemixer/matemixer-backend-module.h +++ b/libmatemixer/matemixer-backend-module.h @@ -61,11 +61,11 @@ struct _MateMixerBackendModuleClass GTypeModuleClass parent; }; -GType mate_mixer_backend_module_get_type (void) G_GNUC_CONST; +GType mate_mixer_backend_module_get_type (void) G_GNUC_CONST; -MateMixerBackendModule *mate_mixer_backend_module_new (const gchar *path); +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); +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 890c34b..474edd4 100644 --- a/libmatemixer/matemixer-backend.c +++ b/libmatemixer/matemixer-backend.c @@ -19,15 +19,121 @@ #include #include "matemixer-backend.h" +#include "matemixer-enums.h" +#include "matemixer-enum-types.h" #include "matemixer-stream.h" +enum { + DEVICE_ADDED, + DEVICE_CHANGED, + DEVICE_REMOVED, + STREAM_ADDED, + STREAM_CHANGED, + STREAM_REMOVED, + N_SIGNALS +}; + +static guint signals[N_SIGNALS] = { 0, }; + G_DEFINE_INTERFACE (MateMixerBackend, mate_mixer_backend, G_TYPE_OBJECT) static void mate_mixer_backend_default_init (MateMixerBackendInterface *iface) { + g_object_interface_install_property (iface, + g_param_spec_enum ("state", + "State", + "Backend connection state", + MATE_MIXER_TYPE_STATE, + MATE_MIXER_STATE_IDLE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + signals[DEVICE_ADDED] = g_signal_new ("device-added", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (MateMixerBackendInterface, device_added), + NULL, + NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, + 1, + G_TYPE_STRING); + + signals[DEVICE_CHANGED] = g_signal_new ("device-changed", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (MateMixerBackendInterface, device_changed), + NULL, + NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, + 1, + G_TYPE_STRING); + + signals[DEVICE_REMOVED] = g_signal_new ("device-removed", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (MateMixerBackendInterface, device_removed), + NULL, + NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, + 1, + G_TYPE_STRING); + + signals[STREAM_ADDED] = g_signal_new ("stream-added", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (MateMixerBackendInterface, stream_added), + NULL, + NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, + 1, + G_TYPE_STRING); + + signals[STREAM_CHANGED] = g_signal_new ("stream-changed", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (MateMixerBackendInterface, stream_changed), + NULL, + NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, + 1, + G_TYPE_STRING); + + signals[STREAM_REMOVED] = g_signal_new ("stream-removed", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (MateMixerBackendInterface, stream_removed), + NULL, + NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, + 1, + G_TYPE_STRING); +} + +void +mate_mixer_backend_set_data (MateMixerBackend *backend, const MateMixerBackendData *data) +{ + MateMixerBackendInterface *iface; + + g_return_if_fail (MATE_MIXER_IS_BACKEND (backend)); + + iface = MATE_MIXER_BACKEND_GET_INTERFACE (backend); + + if (iface->set_data) + iface->set_data (backend, data); } +/* + * Required behaviour: + * if the function returns TRUE, the state must be either MATE_MIXER_STATE_READY or + * MATE_MIXER_STATE_CONNECTING. + */ gboolean mate_mixer_backend_open (MateMixerBackend *backend) { @@ -37,10 +143,11 @@ mate_mixer_backend_open (MateMixerBackend *backend) iface = MATE_MIXER_BACKEND_GET_INTERFACE (backend); - if (iface->open) - return iface->open (backend); - - return FALSE; + if (!iface->open) { + g_critical ("Backend module does not implement the open() method"); + return FALSE; + } + return iface->open (backend); } void @@ -56,6 +163,22 @@ mate_mixer_backend_close (MateMixerBackend *backend) iface->close (backend); } +MateMixerState +mate_mixer_backend_get_state (MateMixerBackend *backend) +{ + MateMixerBackendInterface *iface; + + g_return_val_if_fail (MATE_MIXER_IS_BACKEND (backend), MATE_MIXER_STATE_UNKNOWN); + + iface = MATE_MIXER_BACKEND_GET_INTERFACE (backend); + + if (!iface->get_state) { + g_critical ("Backend module does not implement the get_state() method"); + return MATE_MIXER_STATE_UNKNOWN; + } + return iface->get_state (backend); +} + GList * mate_mixer_backend_list_devices (MateMixerBackend *backend) { @@ -101,6 +224,22 @@ mate_mixer_backend_get_default_input_stream (MateMixerBackend *backend) return NULL; } +gboolean +mate_mixer_backend_set_default_input_stream (MateMixerBackend *backend, + MateMixerStream *stream) +{ + MateMixerBackendInterface *iface; + + g_return_val_if_fail (MATE_MIXER_IS_BACKEND (backend), FALSE); + + iface = MATE_MIXER_BACKEND_GET_INTERFACE (backend); + + if (iface->set_default_input_stream) + return iface->set_default_input_stream (backend, stream); + + return FALSE; +} + MateMixerStream * mate_mixer_backend_get_default_output_stream (MateMixerBackend *backend) { @@ -115,3 +254,19 @@ mate_mixer_backend_get_default_output_stream (MateMixerBackend *backend) return NULL; } + +gboolean +mate_mixer_backend_set_default_output_stream (MateMixerBackend *backend, + MateMixerStream *stream) +{ + MateMixerBackendInterface *iface; + + g_return_val_if_fail (MATE_MIXER_IS_BACKEND (backend), FALSE); + + iface = MATE_MIXER_BACKEND_GET_INTERFACE (backend); + + if (iface->set_default_output_stream) + return iface->set_default_output_stream (backend, stream); + + return FALSE; +} diff --git a/libmatemixer/matemixer-backend.h b/libmatemixer/matemixer-backend.h index 897641f..1a5418f 100644 --- a/libmatemixer/matemixer-backend.h +++ b/libmatemixer/matemixer-backend.h @@ -25,6 +25,15 @@ G_BEGIN_DECLS +typedef struct +{ + gchar *app_name; + gchar *app_id; + gchar *app_version; + gchar *app_icon; + gchar *server_address; +} MateMixerBackendData; + #define MATE_MIXER_TYPE_BACKEND \ (mate_mixer_backend_get_type ()) #define MATE_MIXER_BACKEND(o) \ @@ -42,23 +51,58 @@ struct _MateMixerBackendInterface GTypeInterface parent; /* Required */ - gboolean (*open) (MateMixerBackend *backend); + gboolean (*open) (MateMixerBackend *backend); + MateMixerState (*get_state) (MateMixerBackend *backend); + + /* Optional */ + void (*set_data) (MateMixerBackend *backend, + const MateMixerBackendData *data); - 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); + void (*close) (MateMixerBackend *backend); + GList *(*list_devices) (MateMixerBackend *backend); + GList *(*list_streams) (MateMixerBackend *backend); + MateMixerStream *(*get_default_input_stream) (MateMixerBackend *backend); + gboolean (*set_default_input_stream) (MateMixerBackend *backend, + MateMixerStream *stream); + MateMixerStream *(*get_default_output_stream) (MateMixerBackend *backend); + gboolean (*set_default_output_stream) (MateMixerBackend *backend, + MateMixerStream *stream); + + /* Signals */ + void (*device_added) (MateMixerBackend *backend, + const gchar *name); + void (*device_changed) (MateMixerBackend *backend, + const gchar *name); + void (*device_removed) (MateMixerBackend *backend, + const gchar *name); + void (*stream_added) (MateMixerBackend *backend, + const gchar *name); + void (*stream_changed) (MateMixerBackend *backend, + const gchar *name); + void (*stream_removed) (MateMixerBackend *backend, + const gchar *name); }; -GType mate_mixer_backend_get_type (void) G_GNUC_CONST; +GType mate_mixer_backend_get_type (void) G_GNUC_CONST; + +void mate_mixer_backend_set_data (MateMixerBackend *backend, + const MateMixerBackendData *data); + +gboolean mate_mixer_backend_open (MateMixerBackend *backend); +void mate_mixer_backend_close (MateMixerBackend *backend); + +MateMixerState mate_mixer_backend_get_state (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); +gboolean mate_mixer_backend_set_default_input_stream (MateMixerBackend *backend, + MateMixerStream *stream); -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); +MateMixerStream *mate_mixer_backend_get_default_output_stream (MateMixerBackend *backend); +gboolean mate_mixer_backend_set_default_output_stream (MateMixerBackend *backend, + MateMixerStream *stream); G_END_DECLS diff --git a/libmatemixer/matemixer-client-stream.c b/libmatemixer/matemixer-client-stream.c new file mode 100644 index 0000000..80f48a9 --- /dev/null +++ b/libmatemixer/matemixer-client-stream.c @@ -0,0 +1,83 @@ +/* + * 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-client-stream.h" +#include "matemixer-stream.h" + +G_DEFINE_INTERFACE (MateMixerClientStream, mate_mixer_client_stream, G_TYPE_OBJECT) + +static void +mate_mixer_client_stream_default_init (MateMixerClientStreamInterface *iface) +{ + g_object_interface_install_property (iface, + g_param_spec_object ("parent", + "Parent", + "Parent stream of the client stream", + MATE_MIXER_TYPE_STREAM, + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); +} + +MateMixerStream * +mate_mixer_client_stream_get_parent (MateMixerClientStream *client) +{ + MateMixerClientStreamInterface *iface; + + g_return_val_if_fail (MATE_MIXER_IS_CLIENT_STREAM (client), NULL); + + iface = MATE_MIXER_CLIENT_STREAM_GET_INTERFACE (client); + + if (iface->get_parent) + return iface->get_parent (client); + + return NULL; +} + +gboolean +mate_mixer_client_stream_set_parent (MateMixerClientStream *client, MateMixerStream *parent) +{ + MateMixerClientStreamInterface *iface; + + g_return_val_if_fail (MATE_MIXER_IS_CLIENT_STREAM (client), FALSE); + g_return_val_if_fail (MATE_MIXER_IS_STREAM (parent), FALSE); + + iface = MATE_MIXER_CLIENT_STREAM_GET_INTERFACE (client); + + if (iface->set_parent) + return iface->set_parent (client, parent); + + return FALSE; +} + +gboolean +mate_mixer_client_stream_remove (MateMixerClientStream *client) +{ + MateMixerClientStreamInterface *iface; + + g_return_val_if_fail (MATE_MIXER_IS_CLIENT_STREAM (client), FALSE); + + iface = MATE_MIXER_CLIENT_STREAM_GET_INTERFACE (client); + + if (iface->remove) + return iface->remove (client); + + return FALSE; +} diff --git a/libmatemixer/matemixer-client-stream.h b/libmatemixer/matemixer-client-stream.h new file mode 100644 index 0000000..2c690c5 --- /dev/null +++ b/libmatemixer/matemixer-client-stream.h @@ -0,0 +1,59 @@ +/* + * 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_CLIENT_STREAM_H +#define MATEMIXER_CLIENT_STREAM_H + +#include +#include + +#include + +G_BEGIN_DECLS + +#define MATE_MIXER_TYPE_CLIENT_STREAM \ + (mate_mixer_client_stream_get_type ()) +#define MATE_MIXER_CLIENT_STREAM(o) \ + (G_TYPE_CHECK_INSTANCE_CAST ((o), MATE_MIXER_TYPE_CLIENT_STREAM, MateMixerClientStream)) +#define MATE_MIXER_IS_CLIENT_STREAM(o) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((o), MATE_MIXER_TYPE_CLIENT_STREAM)) +#define MATE_MIXER_CLIENT_STREAM_GET_INTERFACE(o) \ + (G_TYPE_INSTANCE_GET_INTERFACE ((o), MATE_MIXER_TYPE_CLIENT_STREAM, MateMixerClientStreamInterface)) + +typedef struct _MateMixerClientStream MateMixerClientStream; /* dummy object */ +typedef struct _MateMixerClientStreamInterface MateMixerClientStreamInterface; + +struct _MateMixerClientStreamInterface +{ + /*< private >*/ + GTypeInterface parent; + + MateMixerStream *(*get_parent) (MateMixerClientStream *client); + gboolean (*set_parent) (MateMixerClientStream *client, + MateMixerStream *stream); + gboolean (*remove) (MateMixerClientStream *client); +}; + +GType mate_mixer_client_stream_get_type (void) G_GNUC_CONST; +MateMixerStream *mate_mixer_client_stream_get_parent (MateMixerClientStream *client); +gboolean mate_mixer_client_stream_set_parent (MateMixerClientStream *client, + MateMixerStream *parent); +gboolean mate_mixer_client_stream_remove (MateMixerClientStream *client); + +G_END_DECLS + +#endif /* MATEMIXER_CLIENT_STREAM_H */ diff --git a/libmatemixer/matemixer-control.c b/libmatemixer/matemixer-control.c index c122a7e..3e3045e 100644 --- a/libmatemixer/matemixer-control.c +++ b/libmatemixer/matemixer-control.c @@ -15,6 +15,7 @@ * License along with this library; if not, see . */ +#include #include #include @@ -22,6 +23,7 @@ #include "matemixer-backend-module.h" #include "matemixer-control.h" #include "matemixer-enums.h" +#include "matemixer-enum-types.h" #include "matemixer-private.h" #include "matemixer-stream.h" @@ -29,17 +31,146 @@ struct _MateMixerControlPrivate { GList *devices; GList *streams; + MateMixerState state; MateMixerBackend *backend; + MateMixerBackendData backend_data; + MateMixerBackendType backend_type; MateMixerBackendModule *module; }; +enum { + PROP_0, + PROP_APP_NAME, + PROP_APP_ID, + PROP_APP_VERSION, + PROP_APP_ICON, + PROP_SERVER_ADDRESS, + PROP_STATE, + PROP_DEFAULT_INPUT, + PROP_DEFAULT_OUTPUT, + N_PROPERTIES +}; + +enum { + DEVICE_ADDED, + DEVICE_CHANGED, + DEVICE_REMOVED, + STREAM_ADDED, + STREAM_CHANGED, + STREAM_REMOVED, + N_SIGNALS +}; + +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 void mate_mixer_control_finalize (GObject *object); + +static gboolean control_try_next_backend (MateMixerControl *control); +static void control_change_state (MateMixerControl *control, + MateMixerState state); +static void control_state_changed_cb (MateMixerBackend *backend, + GParamSpec *pspec, + MateMixerControl *control); + +static void control_device_added_cb (MateMixerBackend *backend, + const gchar *name, + MateMixerControl *control); +static void control_device_changed_cb (MateMixerBackend *backend, + const gchar *name, + MateMixerControl *control); +static void control_device_removed_cb (MateMixerBackend *backend, + const gchar *name, + MateMixerControl *control); + +static void control_stream_added_cb (MateMixerBackend *backend, + const gchar *name, + MateMixerControl *control); +static void control_stream_changed_cb (MateMixerBackend *backend, + const gchar *name, + MateMixerControl *control); +static void control_stream_removed_cb (MateMixerBackend *backend, + const gchar *name, + MateMixerControl *control); + G_DEFINE_TYPE (MateMixerControl, mate_mixer_control, G_TYPE_OBJECT); -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 GParamSpec *properties[N_PROPERTIES] = { NULL, }; + +static guint signals[N_SIGNALS] = { 0, }; + +static void +mate_mixer_control_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec) +{ + MateMixerControl *control; + + control = MATE_MIXER_CONTROL (object); + + switch (param_id) { + case PROP_APP_NAME: + g_value_set_string (value, control->priv->backend_data.app_name); + break; + case PROP_APP_ID: + g_value_set_string (value, control->priv->backend_data.app_id); + break; + case PROP_APP_VERSION: + g_value_set_string (value, control->priv->backend_data.app_version); + break; + case PROP_APP_ICON: + g_value_set_string (value, control->priv->backend_data.app_icon); + break; + case PROP_SERVER_ADDRESS: + g_value_set_string (value, control->priv->backend_data.server_address); + break; + case PROP_STATE: + g_value_set_enum (value, control->priv->state); + break; + case PROP_DEFAULT_INPUT: + g_value_set_object (value, mate_mixer_control_get_default_input_stream (control)); + break; + case PROP_DEFAULT_OUTPUT: + g_value_set_object (value, mate_mixer_control_get_default_output_stream (control)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} + +static void +mate_mixer_control_set_property (GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec) +{ + MateMixerControl *control; + + control = MATE_MIXER_CONTROL (object); -static MateMixerBackend *mixer_control_init_module (MateMixerBackendModule *module); + switch (param_id) { + case PROP_APP_NAME: + mate_mixer_control_set_app_name (control, g_value_get_string (value)); + break; + case PROP_APP_ID: + mate_mixer_control_set_app_id (control, g_value_get_string (value)); + break; + case PROP_APP_VERSION: + mate_mixer_control_set_app_version (control, g_value_get_string (value)); + break; + case PROP_APP_ICON: + mate_mixer_control_set_app_icon (control, g_value_get_string (value)); + break; + case PROP_SERVER_ADDRESS: + mate_mixer_control_set_server_address (control, g_value_get_string (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} static void mate_mixer_control_class_init (MateMixerControlClass *klass) @@ -47,7 +178,160 @@ mate_mixer_control_class_init (MateMixerControlClass *klass) GObjectClass *object_class; object_class = G_OBJECT_CLASS (klass); - object_class->dispose = mate_mixer_control_dispose; + object_class->dispose = mate_mixer_control_dispose; + object_class->finalize = mate_mixer_control_finalize; + object_class->get_property = mate_mixer_control_get_property; + object_class->set_property = mate_mixer_control_set_property; + + /** + * MateMixerControl:app-name: + * + * Localized human readable name of the application. + */ + properties[PROP_APP_NAME] = g_param_spec_string ("app-name", + "App name", + "Application name", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + /** + * MateMixerControl:app-id: + * + * Identifier of the application (e.g. org.example.app). + */ + properties[PROP_APP_ID] = g_param_spec_string ("app-id", + "App ID", + "Application identifier", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + /** + * MateMixerControl:app-version: + * + * Version of the application. + */ + properties[PROP_APP_VERSION] = g_param_spec_string ("app-version", + "App version", + "Application version", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + /** + * MateMixerControl:app-icon: + * + * An XDG icon name for the application. + */ + properties[PROP_APP_ICON] = g_param_spec_string ("app-icon", + "App icon", + "Application icon", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + + /** + * MateMixerControl:server-address: + * + * Address of the sound server to connect to. + * + * This feature is only supported in the PulseAudio backend. There is + * no need to specify an address in order to connect to the local daemon. + */ + properties[PROP_SERVER_ADDRESS] = g_param_spec_string ("server-address", + "Server address", + "Sound server address", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + + properties[PROP_STATE] = g_param_spec_enum ("state", + "State", + "Current backend connection state", + MATE_MIXER_TYPE_STATE, + MATE_MIXER_STATE_IDLE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + properties[PROP_DEFAULT_INPUT] = g_param_spec_object ("default-input", + "Default input", + "Default input stream", + MATE_MIXER_TYPE_STREAM, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + properties[PROP_DEFAULT_OUTPUT] = g_param_spec_object ("default-output", + "Default output", + "Default output stream", + MATE_MIXER_TYPE_STREAM, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + signals[DEVICE_ADDED] = g_signal_new ("device-added", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (MateMixerControlClass, device_added), + NULL, + NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, + 1, + G_TYPE_STRING); + + signals[DEVICE_CHANGED] = g_signal_new ("device-changed", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (MateMixerControlClass, device_changed), + NULL, + NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, + 1, + G_TYPE_STRING); + + signals[DEVICE_REMOVED] = g_signal_new ("device-removed", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (MateMixerControlClass, device_removed), + NULL, + NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, + 1, + G_TYPE_STRING); + + signals[STREAM_ADDED] = g_signal_new ("stream-added", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (MateMixerControlClass, stream_added), + NULL, + NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, + 1, + G_TYPE_STRING); + + signals[STREAM_CHANGED] = g_signal_new ("stream-changed", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (MateMixerControlClass, stream_changed), + NULL, + NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, + 1, + G_TYPE_STRING); + + signals[STREAM_REMOVED] = g_signal_new ("stream-removed", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (MateMixerControlClass, stream_removed), + NULL, + NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, + 1, + G_TYPE_STRING); + + g_object_class_install_properties (object_class, N_PROPERTIES, properties); g_type_class_add_private (object_class, sizeof (MateMixerControlPrivate)); } @@ -86,86 +370,443 @@ mate_mixer_control_dispose (GObject *object) G_OBJECT_CLASS (mate_mixer_control_parent_class)->dispose (object); } -MateMixerControl * -mate_mixer_control_new (void) +static void +mate_mixer_control_finalize (GObject *object) { - const GList *modules; - MateMixerControl *control; - MateMixerBackend *backend = NULL; - MateMixerBackendModule *module = NULL; + MateMixerControl *control; + + control = MATE_MIXER_CONTROL (object); + + g_free (control->priv->backend_data.app_name); + g_free (control->priv->backend_data.app_id); + g_free (control->priv->backend_data.app_version); + g_free (control->priv->backend_data.app_icon); + g_free (control->priv->backend_data.server_address); + G_OBJECT_CLASS (mate_mixer_control_parent_class)->finalize (object); +} + +/** + * mate_mixer_control_new: + * + * Creates a new #MateMixerControl instance. + * + * Returns: a new #MateMixerControl instance or %NULL if the library has not + * been initialized using mate_mixer_init(). + */ +MateMixerControl *mate_mixer_control_new (void) +{ if (!mate_mixer_is_initialized ()) { g_critical ("The library has not been initialized"); return NULL; } + return g_object_new (MATE_MIXER_TYPE_CONTROL, NULL); +} + +/** + * mate_mixer_control_set_backend_type: + * @control: a #MateMixerControl + * @backend_type: the sound system backend to use + * + * Makes the #MateMixerControl use the given #MateMixerBackendType. + * + * By default the backend type is determined automatically. This function can + * be used before mate_mixer_control_open() to alter this behavior and make the + * @control use the given backend. + * + * This function will fail if support for the backend is not installed in + * the system. + * + * Returns: %TRUE on success or %FALSE on failure. + */ +gboolean +mate_mixer_control_set_backend_type (MateMixerControl *control, + MateMixerBackendType backend_type) +{ + MateMixerBackendModule *module; + const GList *modules; + const MateMixerBackendInfo *info; + + g_return_val_if_fail (MATE_MIXER_IS_CONTROL (control), FALSE); modules = mate_mixer_get_modules (); while (modules) { - module = MATE_MIXER_BACKEND_MODULE (modules->data); - backend = mixer_control_init_module (module); - if (backend != NULL) - break; + module = MATE_MIXER_BACKEND_MODULE (modules->data); + info = mate_mixer_backend_module_get_info (module); + if (info->backend_type == backend_type) { + control->priv->backend_type = backend_type; + return TRUE; + } modules = modules->next; } + return FALSE; +} - /* The last module in the priority list is the "null" module which - * should always be initialized correctly, but in case "null" is absent, - * all the other modules might fail their initializations */ - if (backend == NULL) - return NULL; +/** + * mate_mixer_control_set_app_name: + * @control: a #MateMixerControl + * @app_name: the name of your application, or %NULL to unset + * + * Sets the name of the application. This feature is only supported in the + * PulseAudio backend. + * + * This function will fail if the current state is either + * %MATE_MIXER_STATE_CONNECTING or %MATE_MIXER_STATE_READY, therefore you should + * use it before opening a connection to the sound system. + * + * Returns: %TRUE on success or %FALSE on failure. + */ +gboolean +mate_mixer_control_set_app_name (MateMixerControl *control, const gchar *app_name) +{ + g_return_val_if_fail (MATE_MIXER_IS_CONTROL (control), FALSE); - control = g_object_new (MATE_MIXER_TYPE_CONTROL, NULL); + if (control->priv->state == MATE_MIXER_STATE_CONNECTING || + control->priv->state == MATE_MIXER_STATE_READY) + return FALSE; - control->priv->module = g_object_ref (module); - control->priv->backend = backend; + g_free (control->priv->backend_data.app_name); + + control->priv->backend_data.app_name = g_strdup (app_name); - return control; + g_object_notify_by_pspec (G_OBJECT (control), properties[PROP_APP_NAME]); + return TRUE; } -MateMixerControl * -mate_mixer_control_new_backend (MateMixerBackendType backend_type) +/** + * mate_mixer_control_set_app_id: + * @control: a #MateMixerControl + * @app_id: the identifier of your application, or %NULL to unset + * + * Sets the identifier of the application (e.g. org.example.app). This feature + * is only supported in the PulseAudio backend. + * + * This function will fail if the current state is either + * %MATE_MIXER_STATE_CONNECTING or %MATE_MIXER_STATE_READY, therefore you should + * use it before opening a connection to the sound system. + * + * Returns: %TRUE on success or %FALSE on failure. + */ +gboolean +mate_mixer_control_set_app_id (MateMixerControl *control, const gchar *app_id) { - const GList *modules; - MateMixerControl *control; - MateMixerBackend *backend = NULL; - MateMixerBackendModule *module = NULL; + g_return_val_if_fail (MATE_MIXER_IS_CONTROL (control), FALSE); - if (!mate_mixer_is_initialized ()) { - g_critical ("The library has not been initialized"); - return NULL; - } + if (control->priv->state == MATE_MIXER_STATE_CONNECTING || + control->priv->state == MATE_MIXER_STATE_READY) + return FALSE; + + g_free (control->priv->backend_data.app_id); + + control->priv->backend_data.app_id = g_strdup (app_id); + + g_object_notify_by_pspec (G_OBJECT (control), properties[PROP_APP_ID]); + return TRUE; +} + +/** + * mate_mixer_control_set_app_version: + * @control: a #MateMixerControl + * @app_version: the version of your application, or %NULL to unset + * + * Sets the version of the application. This feature is only supported in the + * PulseAudio backend. + * + * This function will fail if the current state is either + * %MATE_MIXER_STATE_CONNECTING or %MATE_MIXER_STATE_READY, therefore you should + * use it before opening a connection to the sound system. + * + * Returns: %TRUE on success or %FALSE on failure. + */ +gboolean +mate_mixer_control_set_app_version (MateMixerControl *control, const gchar *app_version) +{ + g_return_val_if_fail (MATE_MIXER_IS_CONTROL (control), FALSE); + + if (control->priv->state == MATE_MIXER_STATE_CONNECTING || + control->priv->state == MATE_MIXER_STATE_READY) + return FALSE; + + g_free (control->priv->backend_data.app_version); + + control->priv->backend_data.app_version = g_strdup (app_version); + + g_object_notify_by_pspec (G_OBJECT (control), properties[PROP_APP_VERSION]); + return TRUE; +} + +/** + * mate_mixer_control_set_app_icon: + * @control: a #MateMixerControl + * @app_icon: the XDG icon name of your application, or %NULL to unset + * + * Sets the XDG icon name of the application. This feature is only supported in + * the PulseAudio backend. + * + * This function will fail if the current state is either + * %MATE_MIXER_STATE_CONNECTING or %MATE_MIXER_STATE_READY, therefore you should + * use it before opening a connection to the sound system. + * + * Returns: %TRUE on success or %FALSE on failure. + */ +gboolean +mate_mixer_control_set_app_icon (MateMixerControl *control, const gchar *app_icon) +{ + g_return_val_if_fail (MATE_MIXER_IS_CONTROL (control), FALSE); + + if (control->priv->state == MATE_MIXER_STATE_CONNECTING || + control->priv->state == MATE_MIXER_STATE_READY) + return FALSE; + + g_free (control->priv->backend_data.app_icon); + + control->priv->backend_data.app_icon = g_strdup (app_icon); + + g_object_notify_by_pspec (G_OBJECT (control), properties[PROP_APP_ICON]); + return TRUE; +} + +/** + * mate_mixer_control_set_server_address: + * @control: a #MateMixerControl + * @address: the address of the sound server to connect to or %NULL + * + * Sets the address of the sound server. This feature is only supported in the + * PulseAudio backend. If the address is not set, the default PulseAudio sound + * server will be used, which is normally the local daemon. + * + * This function will fail if the current state is either + * %MATE_MIXER_STATE_CONNECTING or %MATE_MIXER_STATE_READY, therefore you should + * use it before opening a connection to the sound system. + * + * Returns: %TRUE on success or %FALSE on failure. + */ +gboolean +mate_mixer_control_set_server_address (MateMixerControl *control, const gchar *address) +{ + g_return_val_if_fail (MATE_MIXER_IS_CONTROL (control), FALSE); + + if (control->priv->state == MATE_MIXER_STATE_CONNECTING || + control->priv->state == MATE_MIXER_STATE_READY) + return FALSE; + + g_free (control->priv->backend_data.server_address); + + control->priv->backend_data.server_address = g_strdup (address); + + g_object_notify_by_pspec (G_OBJECT (control), properties[PROP_SERVER_ADDRESS]); + return TRUE; +} + +/** + * mate_mixer_control_open: + * @control: a #MateMixerControl + * + * Opens connection to a sound system. Unless the backend type was given + * beforehand, the library will find a working sound system automatically. + * If the automatic discovery fails to find a working sound system, it will + * use the "Null" backend, which provides no functionality. + * + * This function can complete the operation either synchronously or + * asynchronously. + * + * In case this function returns %TRUE, you should check the current state of + * the connection using mate_mixer_control_get_state(). If the current state + * is %MATE_MIXER_STATE_READY, the connection has been established successfully. + * Otherwise the state will be set to %MATE_MIXER_STATE_CONNECTING and the + * result of the operation will be determined asynchronously. You should wait + * for the state transition by connecting to the notification signal of the + * #MateMixerControl:state property. + * + * In case this function returns %FALSE, it is not possible to use the selected + * backend and the state will be set to %MATE_MIXER_STATE_FAILED. + * + * Returns: %TRUE on success or if the result will be determined asynchronously, + * or %FALSE on failure. + */ +gboolean +mate_mixer_control_open (MateMixerControl *control) +{ + MateMixerBackendModule *module = NULL; + MateMixerState state; + const GList *modules; + const MateMixerBackendInfo *info = NULL; + + g_return_val_if_fail (MATE_MIXER_IS_CONTROL (control), FALSE); + g_return_val_if_fail (control->priv->state != MATE_MIXER_STATE_CONNECTING && + control->priv->state != MATE_MIXER_STATE_READY, FALSE); + /* We are going to choose the first backend to try. It will be either the one + * specified by the user or the one with the highest priority */ modules = mate_mixer_get_modules (); - while (modules) { - const MateMixerBackendInfo *info; - module = MATE_MIXER_BACKEND_MODULE (modules->data); - info = mate_mixer_backend_module_get_info (module); + if (control->priv->backend_type != MATE_MIXER_BACKEND_UNKNOWN) { + while (modules) { + const MateMixerBackendInfo *info; - if (info->backend_type == backend_type) { - backend = mixer_control_init_module (module); - break; + module = MATE_MIXER_BACKEND_MODULE (modules->data); + info = mate_mixer_backend_module_get_info (module); + + if (info->backend_type == control->priv->backend_type) + break; + + module = NULL; + modules = modules->next; } - modules = modules->next; + } else { + /* The highest priority module is on the top of the list */ + module = MATE_MIXER_BACKEND_MODULE (modules->data); } - /* The initialization might fail or the selected module might be absent */ - if (backend == NULL) - return NULL; + if (module == NULL) { + /* Most likely the selected backend is not installed */ + control_change_state (control, MATE_MIXER_STATE_FAILED); + return FALSE; + } - control = g_object_new (MATE_MIXER_TYPE_CONTROL, NULL); + if (info == NULL) + info = mate_mixer_backend_module_get_info (module); control->priv->module = g_object_ref (module); - control->priv->backend = backend; + control->priv->backend = g_object_newv (info->g_type, 0, NULL); + + mate_mixer_backend_set_data (control->priv->backend, &control->priv->backend_data); + + /* This transitional state is always present, it will change to MATE_MIXER_STATE_READY + * or MATE_MIXER_STATE_FAILED either instantly or asynchronously */ + control_change_state (control, MATE_MIXER_STATE_CONNECTING); + + /* The backend initialization might fail in case it is known right now that + * it is unusable */ + if (!mate_mixer_backend_open (control->priv->backend)) { + if (control->priv->backend_type == MATE_MIXER_BACKEND_UNKNOWN) { + /* User didn't request a specific backend, so try another one */ + return control_try_next_backend (control); + } + + /* User requested a specific backend and it failed */ + g_clear_object (&control->priv->module); + g_clear_object (&control->priv->backend); + + control_change_state (control, MATE_MIXER_STATE_FAILED); + return FALSE; + } - return control; + state = mate_mixer_backend_get_state (control->priv->backend); + + if (G_UNLIKELY (state != MATE_MIXER_STATE_READY && + state != MATE_MIXER_STATE_CONNECTING)) { + /* The backend should not be in this state */ + g_warn_if_reached (); + + g_clear_object (&control->priv->module); + g_clear_object (&control->priv->backend); + control_change_state (control, MATE_MIXER_STATE_FAILED); + return FALSE; + } + + g_signal_connect (control->priv->backend, + "notify::state", + G_CALLBACK (control_state_changed_cb), + control); + + control_change_state (control, state); + return TRUE; +} + +/** + * mate_mixer_control_get_state: + * @control: a #MateMixerControl + * + * Gets the current backend connection state of the #MateMixerControl. + * + * Returns: The current connection state. + */ +MateMixerState +mate_mixer_control_get_state (MateMixerControl *control) +{ + g_return_val_if_fail (MATE_MIXER_IS_CONTROL (control), MATE_MIXER_STATE_UNKNOWN); + + return control->priv->state; } +/** + * mate_mixer_control_get_device: + * @control: a #MateMixerControl + * @name: a device name + * + * Gets the devices with the given name. + * + * Returns: a #MateMixerDevice or %NULL if there is no such device. + */ +MateMixerDevice * +mate_mixer_control_get_device (MateMixerControl *control, const gchar *name) +{ + GList *list; + + g_return_val_if_fail (MATE_MIXER_IS_CONTROL (control), NULL); + g_return_val_if_fail (name != NULL, NULL); + + list = control->priv->devices; + while (list) { + MateMixerDevice *device = MATE_MIXER_DEVICE (list->data); + + if (!strcmp (name, mate_mixer_device_get_name (device))) + return device; + + list = list->next; + } + return NULL; +} + +/** + * mate_mixer_control_get_stream: + * @control: a #MateMixerControl + * @name: a stream name + * + * Gets the stream with the given name. + * + * Returns: a #MateMixerStream or %NULL if there is no such stream. + */ +MateMixerStream * +mate_mixer_control_get_stream (MateMixerControl *control, const gchar *name) +{ + GList *list; + + g_return_val_if_fail (MATE_MIXER_IS_CONTROL (control), NULL); + g_return_val_if_fail (name != NULL, NULL); + + list = control->priv->streams; + while (list) { + MateMixerStream *stream = MATE_MIXER_STREAM (list->data); + + if (!strcmp (name, mate_mixer_stream_get_name (stream))) + return stream; + + list = list->next; + } + return NULL; +} + +/** + * mate_mixer_control_list_devices: + * @control: a #MateMixerControl + * + * Gets a list of devices. Each list item is a #MateMixerDevice representing a + * hardware or software sound device in the system. + * + * The returned #GList is owned by the #MateMixerControl and may be invalidated + * at any time. + * + * Returns: a #GList of all devices in the system or %NULL if there are none or + * you are not connected to a sound system. + */ const GList * mate_mixer_control_list_devices (MateMixerControl *control) { g_return_val_if_fail (MATE_MIXER_IS_CONTROL (control), NULL); + g_return_val_if_fail (control->priv->state == MATE_MIXER_STATE_READY, NULL); /* This list is cached here and invalidated when the backend notifies us * about a change */ @@ -176,10 +817,24 @@ mate_mixer_control_list_devices (MateMixerControl *control) return (const GList *) control->priv->devices; } +/** + * mate_mixer_control_list_streams: + * @control: a #MateMixerControl + * + * Gets a list of streams. Each list item is a #MateMixerStream representing an + * input or output of a sound device. + * + * The returned #GList is owned by the #MateMixerControl and may be invalidated + * at any time. + * + * Returns: a #GList of all streams in the system or %NULL if there are none or + * you are not connected to a sound system. + */ const GList * mate_mixer_control_list_streams (MateMixerControl *control) { g_return_val_if_fail (MATE_MIXER_IS_CONTROL (control), NULL); + g_return_val_if_fail (control->priv->state == MATE_MIXER_STATE_READY, NULL); /* This list is cached here and invalidated when the backend notifies us * about a change */ @@ -190,58 +845,330 @@ mate_mixer_control_list_streams (MateMixerControl *control) return (const GList *) control->priv->streams; } +/** + * mate_mixer_control_get_default_input_stream: + * @control: a #MateMixerControl + * + * Gets the default input stream. The returned stream is where sound input is + * directed to by default. + * + * Returns: a #MateMixerStream or %NULL if there are no input streams in + * the system. + */ MateMixerStream * mate_mixer_control_get_default_input_stream (MateMixerControl *control) { g_return_val_if_fail (MATE_MIXER_IS_CONTROL (control), NULL); + g_return_val_if_fail (control->priv->state == MATE_MIXER_STATE_READY, NULL); return mate_mixer_backend_get_default_input_stream (control->priv->backend); } +/** + * mate_mixer_control_set_default_input_stream: + * @control: a #MateMixerControl + * @stream: a #MateMixerStream to set as the default input stream + * + * Changes the default input stream in the system. + * + * Returns: %TRUE on success or %FALSE on failure. + */ +gboolean +mate_mixer_control_set_default_input_stream (MateMixerControl *control, + MateMixerStream *stream) +{ + g_return_val_if_fail (MATE_MIXER_IS_CONTROL (control), NULL); + g_return_val_if_fail (control->priv->state == MATE_MIXER_STATE_READY, NULL); + + return mate_mixer_backend_set_default_input_stream (control->priv->backend, stream); +} + +/** + * mate_mixer_control_get_default_output_stream: + * @control: a #MateMixerControl + * + * Gets the default output stream. The returned stream is where sound output is + * directed to by default. + * + * Returns: a #MateMixerStream or %NULL if there are no output streams in + * the system. + */ MateMixerStream * mate_mixer_control_get_default_output_stream (MateMixerControl *control) { g_return_val_if_fail (MATE_MIXER_IS_CONTROL (control), NULL); + g_return_val_if_fail (control->priv->state == MATE_MIXER_STATE_READY, NULL); return mate_mixer_backend_get_default_output_stream (control->priv->backend); } +/** + * mate_mixer_control_set_default_output_stream: + * @control: a #MateMixerControl + * @stream: a #MateMixerStream to set as the default output stream + * + * Changes the default output stream in the system. + * + * Returns: %TRUE on success or %FALSE on failure. + */ +gboolean +mate_mixer_control_set_default_output_stream (MateMixerControl *control, + MateMixerStream *stream) +{ + g_return_val_if_fail (MATE_MIXER_IS_CONTROL (control), NULL); + g_return_val_if_fail (control->priv->state == MATE_MIXER_STATE_READY, NULL); + + return mate_mixer_backend_set_default_input_stream (control->priv->backend, stream); +} + +/** + * mate_mixer_control_get_backend_name: + * @control: a #MateMixerControl + * + * Gets the name of the currently used backend. The @control must be in the + * %MATE_MIXER_STATE_READY state. + * + * Returns: the name or %NULL on error. + */ const gchar * mate_mixer_control_get_backend_name (MateMixerControl *control) { const MateMixerBackendInfo *info; g_return_val_if_fail (MATE_MIXER_IS_CONTROL (control), NULL); + g_return_val_if_fail (control->priv->state == MATE_MIXER_STATE_READY, NULL); info = mate_mixer_backend_module_get_info (control->priv->module); return info->name; } +/** + * mate_mixer_control_get_backend_type: + * @control: a #MateMixerControl + * + * Gets the type of the currently used backend. The @control must be in the + * %MATE_MIXER_STATE_READY state. + * + * Returns: the backend type or %MATE_MIXER_BACKEND_UNKNOWN on error. + */ MateMixerBackendType mate_mixer_control_get_backend_type (MateMixerControl *control) { const MateMixerBackendInfo *info; g_return_val_if_fail (MATE_MIXER_IS_CONTROL (control), FALSE); + g_return_val_if_fail (control->priv->state == MATE_MIXER_STATE_READY, FALSE); info = mate_mixer_backend_module_get_info (control->priv->module); return info->backend_type; } -static MateMixerBackend * -mixer_control_init_module (MateMixerBackendModule *module) +static gboolean +control_try_next_backend (MateMixerControl *control) { - MateMixerBackend *backend; - const MateMixerBackendInfo *info; + const GList *modules; + MateMixerBackendModule *module = NULL; + + modules = mate_mixer_get_modules (); + while (modules) { + if (control->priv->module == modules->data) { + /* Found the last tested backend, try to use the next one with a lower + * priority unless we have reached the end of the list */ + if (modules->next) + module = MATE_MIXER_BACKEND_MODULE (modules->next->data); + break; + } + modules = modules->next; + } + g_clear_object (&control->priv->module); + g_clear_object (&control->priv->backend); - info = mate_mixer_backend_module_get_info (module); - backend = g_object_newv (info->g_type, 0, NULL); + if (module == NULL) { + /* This shouldn't happen under normal circumstances as the lowest + * priority module is the "Null" module which never fails to initialize, + * but in a broken installation this module could be missing */ + control_change_state (control, MATE_MIXER_STATE_FAILED); + return FALSE; + } - if (!mate_mixer_backend_open (backend)) { - g_object_unref (backend); - return NULL; + control->priv->module = g_object_ref (module); + control->priv->backend = + g_object_newv (mate_mixer_backend_module_get_info (module)->g_type, + 0, + NULL); + + if (!mate_mixer_backend_open (control->priv->backend)) + return control_try_next_backend (control); + + g_signal_connect (control->priv->backend, + "notify::state", + G_CALLBACK (control_state_changed_cb), + control); + return TRUE; +} + +static void +control_change_state (MateMixerControl *control, MateMixerState state) +{ + if (control->priv->state == state) + return; + + control->priv->state = state; + + if (state == MATE_MIXER_STATE_READY) { + /* It is safe to connect to the backend signals after reaching the READY + * state, because the app is not allowed to query any data before that state */ + g_signal_connect (control->priv->backend, + "device-added", + G_CALLBACK (control_device_added_cb), + control); + g_signal_connect (control->priv->backend, + "device-changed", + G_CALLBACK (control_device_changed_cb), + control); + g_signal_connect (control->priv->backend, + "device-removed", + G_CALLBACK (control_device_removed_cb), + control); + g_signal_connect (control->priv->backend, + "stream-added", + G_CALLBACK (control_stream_added_cb), + control); + g_signal_connect (control->priv->backend, + "stream-changed", + G_CALLBACK (control_stream_changed_cb), + control); + g_signal_connect (control->priv->backend, + "stream-removed", + G_CALLBACK (control_stream_removed_cb), + control); + } + g_object_notify_by_pspec (G_OBJECT (control), properties[PROP_STATE]); +} + +static void +control_state_changed_cb (MateMixerBackend *backend, + GParamSpec *pspec, + MateMixerControl *control) +{ + MateMixerState state = mate_mixer_backend_get_state (backend); + + switch (state) { + case MATE_MIXER_STATE_READY: + control_change_state (control, state); + break; + + case MATE_MIXER_STATE_FAILED: + control_try_next_backend (control); + break; + + default: + break; + } +} + +static void +control_device_added_cb (MateMixerBackend *backend, + const gchar *name, + MateMixerControl *control) +{ + if (control->priv->devices) { + g_list_free_full (control->priv->devices, g_object_unref); + control->priv->devices = NULL; + } + + g_debug ("Device added: %s", name); + + g_signal_emit (G_OBJECT (control), + signals[DEVICE_ADDED], + 0, + name); +} + +static void +control_device_changed_cb (MateMixerBackend *backend, + const gchar *name, + MateMixerControl *control) +{ + /* Do not invalidate the list of devices here as the list has not changed, + * only some properties of a device */ + + g_debug ("Device changed: %s", name); + + g_signal_emit (G_OBJECT (control), + signals[DEVICE_CHANGED], + 0, + name); +} + +static void +control_device_removed_cb (MateMixerBackend *backend, + const gchar *name, + MateMixerControl *control) +{ + if (control->priv->devices) { + g_list_free_full (control->priv->devices, g_object_unref); + control->priv->devices = NULL; } - return backend; + + g_debug ("Device removed: %s", name); + + g_signal_emit (G_OBJECT (control), + signals[DEVICE_REMOVED], + 0, + name); +} + +static void +control_stream_added_cb (MateMixerBackend *backend, + const gchar *name, + MateMixerControl *control) +{ + if (control->priv->streams) { + g_list_free_full (control->priv->streams, g_object_unref); + control->priv->streams = NULL; + } + + g_debug ("Stream added: %s", name); + + g_signal_emit (G_OBJECT (control), + signals[STREAM_ADDED], + 0, + name); +} + +static void +control_stream_changed_cb (MateMixerBackend *backend, + const gchar *name, + MateMixerControl *control) +{ + /* Do not invalidate the list of streams here as the list has not changed, + * only some properties of a stream */ + + g_debug ("Stream changed: %s", name); + + g_signal_emit (G_OBJECT (control), + signals[STREAM_CHANGED], + 0, + name); +} + +static void +control_stream_removed_cb (MateMixerBackend *backend, + const gchar *name, + MateMixerControl *control) +{ + if (control->priv->streams) { + g_list_free_full (control->priv->streams, g_object_unref); + control->priv->streams = NULL; + } + + g_debug ("Stream removed: %s", name); + + g_signal_emit (G_OBJECT (control), + signals[STREAM_REMOVED], + 0, + name); } diff --git a/libmatemixer/matemixer-control.h b/libmatemixer/matemixer-control.h index 3482fbb..ad48768 100644 --- a/libmatemixer/matemixer-control.h +++ b/libmatemixer/matemixer-control.h @@ -43,26 +43,79 @@ typedef struct _MateMixerControl MateMixerControl; typedef struct _MateMixerControlClass MateMixerControlClass; typedef struct _MateMixerControlPrivate MateMixerControlPrivate; +/** + * MateMixerControl: + * + * The #MateMixerControl structure contains only private data and should only + * be accessed using the provided API. + */ struct _MateMixerControl { - GObject parent; - - MateMixerControlPrivate *priv; + /*< private >*/ + GObject parent; + MateMixerControlPrivate *priv; }; +/** + * MateMixerControlClass: + * + * The class structure of #MateMixerControl. + */ struct _MateMixerControlClass { - GObjectClass parent; -}; + /*< private >*/ + GObjectClass parent; -GType mate_mixer_control_get_type (void) G_GNUC_CONST; + /* Signals */ + void (*device_added) (MateMixerControl *control, + const gchar *name); + void (*device_changed) (MateMixerControl *control, + const gchar *name); + void (*device_removed) (MateMixerControl *control, + const gchar *name); + void (*stream_added) (MateMixerControl *control, + const gchar *name); + void (*stream_changed) (MateMixerControl *control, + const gchar *name); + void (*stream_removed) (MateMixerControl *control, + const gchar *name); +}; +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); + +gboolean mate_mixer_control_set_backend_type (MateMixerControl *control, + MateMixerBackendType backend_type); +gboolean mate_mixer_control_set_app_name (MateMixerControl *control, + const gchar *app_name); +gboolean mate_mixer_control_set_app_id (MateMixerControl *control, + const gchar *app_id); +gboolean mate_mixer_control_set_app_version (MateMixerControl *control, + const gchar *app_version); +gboolean mate_mixer_control_set_app_icon (MateMixerControl *control, + const gchar *app_icon); +gboolean mate_mixer_control_set_server_address (MateMixerControl *control, + const gchar *address); +gboolean mate_mixer_control_open (MateMixerControl *control); + +MateMixerState mate_mixer_control_get_state (MateMixerControl *control); + +MateMixerDevice * mate_mixer_control_get_device (MateMixerControl *control, + const gchar *name); +MateMixerStream * mate_mixer_control_get_stream (MateMixerControl *control, + const gchar *name); + 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); +gboolean mate_mixer_control_set_default_input_stream (MateMixerControl *control, + MateMixerStream *stream); + MateMixerStream * mate_mixer_control_get_default_output_stream (MateMixerControl *control); +gboolean mate_mixer_control_set_default_output_stream (MateMixerControl *control, + MateMixerStream *stream); + const gchar * mate_mixer_control_get_backend_name (MateMixerControl *control); MateMixerBackendType mate_mixer_control_get_backend_type (MateMixerControl *control); diff --git a/libmatemixer/matemixer-device.c b/libmatemixer/matemixer-device.c index cd5a47c..a022877 100644 --- a/libmatemixer/matemixer-device.c +++ b/libmatemixer/matemixer-device.c @@ -19,7 +19,6 @@ #include #include "matemixer-device.h" -#include "matemixer-enum-types.h" #include "matemixer-profile.h" G_DEFINE_INTERFACE (MateMixerDevice, mate_mixer_device, G_TYPE_OBJECT) @@ -169,17 +168,17 @@ mate_mixer_device_get_active_profile (MateMixerDevice *device) } gboolean -mate_mixer_device_set_active_profile (MateMixerDevice *device, const gchar *profile_name) +mate_mixer_device_set_active_profile (MateMixerDevice *device, const gchar *profile) { MateMixerDeviceInterface *iface; g_return_val_if_fail (MATE_MIXER_IS_DEVICE (device), FALSE); - g_return_val_if_fail (profile_name != NULL, FALSE); + g_return_val_if_fail (profile != NULL, FALSE); iface = MATE_MIXER_DEVICE_GET_INTERFACE (device); if (iface->set_active_profile) - return iface->set_active_profile (device, profile_name); + return iface->set_active_profile (device, profile); return FALSE; } diff --git a/libmatemixer/matemixer-device.h b/libmatemixer/matemixer-device.h index 3b25313..d814847 100644 --- a/libmatemixer/matemixer-device.h +++ b/libmatemixer/matemixer-device.h @@ -39,6 +39,7 @@ typedef struct _MateMixerDeviceInterface MateMixerDeviceInterface; struct _MateMixerDeviceInterface { + /*< private >*/ GTypeInterface parent; const gchar *(*get_name) (MateMixerDevice *device); @@ -49,11 +50,10 @@ struct _MateMixerDeviceInterface const GList *(*list_profiles) (MateMixerDevice *device); MateMixerProfile *(*get_active_profile) (MateMixerDevice *device); gboolean (*set_active_profile) (MateMixerDevice *device, - const gchar *profile_name); + const gchar *profile); }; -GType mate_mixer_device_get_type (void) G_GNUC_CONST; - +GType mate_mixer_device_get_type (void) G_GNUC_CONST; 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); @@ -62,7 +62,7 @@ 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 *profile_name); + const gchar *profile); G_END_DECLS diff --git a/libmatemixer/matemixer-enum-types.c b/libmatemixer/matemixer-enum-types.c index 0d1c57d..43249a3 100644 --- a/libmatemixer/matemixer-enum-types.c +++ b/libmatemixer/matemixer-enum-types.c @@ -23,6 +23,27 @@ * https://bugzilla.gnome.org/show_bug.cgi?id=621942 */ +GType +mate_mixer_state_get_type (void) +{ + static GType etype = 0; + + if (etype == 0) { + static const GEnumValue values[] = { + { MATE_MIXER_STATE_IDLE, "MATE_MIXER_STATE_IDLE", "idle" }, + { MATE_MIXER_STATE_CONNECTING, "MATE_MIXER_STATE_CONNECTING", "connecting" }, + { MATE_MIXER_STATE_READY, "MATE_MIXER_STATE_READY", "ready" }, + { MATE_MIXER_STATE_FAILED, "MATE_MIXER_STATE_FAILED", "failed" }, + { MATE_MIXER_STATE_UNKNOWN, "MATE_MIXER_STATE_UNKNOWN", "unknown" }, + { 0, NULL, NULL } + }; + etype = g_enum_register_static ( + g_intern_static_string ("MateMixerState"), + values); + } + return etype; +} + GType mate_mixer_backend_type_get_type (void) { @@ -68,14 +89,19 @@ mate_mixer_stream_flags_get_type (void) if (etype == 0) { static const GFlagsValue values[] = { + { MATE_MIXER_STREAM_NO_FLAGS, "MATE_MIXER_STREAM_NO_FLAGS", "no-flags" }, { 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_APPLICATION, "MATE_MIXER_STREAM_APPLICATION", "application" }, { MATE_MIXER_STREAM_OUTPUT_MONITOR, "MATE_MIXER_STREAM_OUTPUT_MONITOR", "output-monitor" }, + { MATE_MIXER_STREAM_HAS_MUTE, "MATE_MIXER_STREAM_HAS_MUTE", "has-mute" }, + { MATE_MIXER_STREAM_HAS_VOLUME, "MATE_MIXER_STREAM_HAS_VOLUME", "has-volume" }, + { MATE_MIXER_STREAM_HAS_DECIBEL_VOLUME, "MATE_MIXER_STREAM_HAS_DECIBEL_VOLUME", "has-decibel-volume" }, + { MATE_MIXER_STREAM_HAS_FLAT_VOLUME, "MATE_MIXER_STREAM_HAS_FLAT_VOLUME", "has-flat-volume" }, { 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" }, + { MATE_MIXER_STREAM_CAN_SET_VOLUME, "MATE_MIXER_STREAM_CAN_SET_VOLUME", "can-set-volume" }, { 0, NULL, NULL } }; etype = g_flags_register_static ( diff --git a/libmatemixer/matemixer-enum-types.h b/libmatemixer/matemixer-enum-types.h index ccb87a6..0275c27 100644 --- a/libmatemixer/matemixer-enum-types.h +++ b/libmatemixer/matemixer-enum-types.h @@ -28,19 +28,22 @@ G_BEGIN_DECLS * https://bugzilla.gnome.org/show_bug.cgi?id=621942 */ -#define MATE_MIXER_TYPE_BACKEND_TYPE (mate_mixer_backend_type_get_type ()) +#define MATE_MIXER_TYPE_STATE (mate_mixer_state_get_type ()) +GType mate_mixer_state_get_type (void) G_GNUC_CONST; + +#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_PORT_STATUS (mate_mixer_port_status_get_type ()) +#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_STREAM_FLAGS (mate_mixer_stream_flags_get_type ()) +#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 ()) +#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 ()) +#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 cccb70d..5fc348d 100644 --- a/libmatemixer/matemixer-enums.h +++ b/libmatemixer/matemixer-enums.h @@ -24,7 +24,15 @@ */ typedef enum { - MATE_MIXER_BACKEND_UNKNOWN, + MATE_MIXER_STATE_IDLE = 0, + MATE_MIXER_STATE_CONNECTING, + MATE_MIXER_STATE_READY, + MATE_MIXER_STATE_FAILED, + MATE_MIXER_STATE_UNKNOWN +} MateMixerState; + +typedef enum { + MATE_MIXER_BACKEND_UNKNOWN = 0, MATE_MIXER_BACKEND_PULSE, MATE_MIXER_BACKEND_NULL } MateMixerBackendType; @@ -36,29 +44,34 @@ typedef enum { } MateMixerPortStatus; typedef enum { /*< flags >*/ - 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 + MATE_MIXER_STREAM_NO_FLAGS = 0, + MATE_MIXER_STREAM_INPUT = 1 << 0, + MATE_MIXER_STREAM_OUTPUT = 1 << 1, + MATE_MIXER_STREAM_CLIENT = 1 << 2, + MATE_MIXER_STREAM_APPLICATION = 1 << 3, + MATE_MIXER_STREAM_OUTPUT_MONITOR = 1 << 4, + MATE_MIXER_STREAM_HAS_MUTE = 1 << 5, + MATE_MIXER_STREAM_HAS_VOLUME = 1 << 6, + MATE_MIXER_STREAM_HAS_DECIBEL_VOLUME = 1 << 7, + MATE_MIXER_STREAM_HAS_FLAT_VOLUME = 1 << 8, + MATE_MIXER_STREAM_CAN_BALANCE = 1 << 9, + MATE_MIXER_STREAM_CAN_FADE = 1 << 10, + MATE_MIXER_STREAM_CAN_SET_VOLUME = 1 << 11 } MateMixerStreamFlags; typedef enum { - MATE_MIXER_STREAM_UNKNOWN_STATUS, - MATE_MIXER_STREAM_RUNNING, - MATE_MIXER_STREAM_IDLE, - MATE_MIXER_STREAM_SUSPENDED + 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_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, @@ -67,13 +80,13 @@ typedef enum { 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_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 + 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 index c4b2de3..7ac21f7 100644 --- a/libmatemixer/matemixer-port.c +++ b/libmatemixer/matemixer-port.c @@ -27,12 +27,11 @@ struct _MateMixerPortPrivate gchar *name; gchar *description; gchar *icon; - guint32 priority; + gulong priority; MateMixerPortStatus status; }; -enum -{ +enum { PROP_0, PROP_NAME, PROP_DESCRIPTION, @@ -71,7 +70,7 @@ mate_mixer_port_get_property (GObject *object, g_value_set_string (value, port->priv->icon); break; case PROP_PRIORITY: - g_value_set_uint (value, port->priv->priority); + g_value_set_ulong (value, port->priv->priority); break; case PROP_STATUS: g_value_set_enum (value, port->priv->status); @@ -103,7 +102,7 @@ mate_mixer_port_set_property (GObject *object, port->priv->icon = g_strdup (g_value_get_string (value)); break; case PROP_PRIORITY: - port->priv->priority = g_value_get_uint (value); + port->priv->priority = g_value_get_ulong (value); break; case PROP_STATUS: port->priv->status = g_value_get_enum (value); @@ -124,53 +123,48 @@ mate_mixer_port_class_init (MateMixerPortClass *klass) 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); + 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_ulong ("priority", + "Priority", + "Priority of the port", + 0, + G_MAXULONG, + 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); @@ -203,7 +197,7 @@ MateMixerPort * mate_mixer_port_new (const gchar *name, const gchar *description, const gchar *icon, - guint32 priority, + gulong priority, MateMixerPortStatus status) { return g_object_new (MATE_MIXER_TYPE_PORT, @@ -239,7 +233,7 @@ mate_mixer_port_get_icon (MateMixerPort *port) return port->priv->icon; } -guint32 +gulong mate_mixer_port_get_priority (MateMixerPort *port) { g_return_val_if_fail (MATE_MIXER_IS_PORT (port), 0); diff --git a/libmatemixer/matemixer-port.h b/libmatemixer/matemixer-port.h index 581f4ec..e0a9f79 100644 --- a/libmatemixer/matemixer-port.h +++ b/libmatemixer/matemixer-port.h @@ -44,29 +44,29 @@ typedef struct _MateMixerPortPrivate MateMixerPortPrivate; struct _MateMixerPort { - GObject parent; - - MateMixerPortPrivate *priv; + /*< private >*/ + GObject parent; + MateMixerPortPrivate *priv; }; struct _MateMixerPortClass { - GObjectClass parent; + /*< private >*/ + 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); +GType mate_mixer_port_get_type (void) G_GNUC_CONST; +MateMixerPort * mate_mixer_port_new (const gchar *name, + const gchar *description, + const gchar *icon, + gulong 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); +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); +gulong mate_mixer_port_get_priority (MateMixerPort *port); +MateMixerPortStatus mate_mixer_port_get_status (MateMixerPort *port); G_END_DECLS diff --git a/libmatemixer/matemixer-profile.c b/libmatemixer/matemixer-profile.c index c32489f..38f17c7 100644 --- a/libmatemixer/matemixer-profile.c +++ b/libmatemixer/matemixer-profile.c @@ -24,7 +24,7 @@ struct _MateMixerProfilePrivate { gchar *name; gchar *description; - guint32 priority; + gulong priority; }; enum @@ -62,7 +62,7 @@ mate_mixer_profile_get_property (GObject *object, g_value_set_string (value, profile->priv->description); break; case PROP_PRIORITY: - g_value_set_uint (value, profile->priv->priority); + g_value_set_ulong (value, profile->priv->priority); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); @@ -88,7 +88,7 @@ mate_mixer_profile_set_property (GObject *object, profile->priv->description = g_strdup (g_value_get_string (value)); break; case PROP_PRIORITY: - profile->priv->priority = g_value_get_uint (value); + profile->priv->priority = g_value_get_ulong (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); @@ -106,34 +106,31 @@ mate_mixer_profile_class_init (MateMixerProfileClass *klass) 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); + 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_ulong ("priority", + "Priority", + "Priority of the profile", + 0, + G_MAXULONG, + 0, + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, N_PROPERTIES, properties); @@ -162,7 +159,7 @@ mate_mixer_profile_finalize (GObject *object) } MateMixerProfile * -mate_mixer_profile_new (const gchar *name, const gchar *description, guint32 priority) +mate_mixer_profile_new (const gchar *name, const gchar *description, gulong priority) { return g_object_new (MATE_MIXER_TYPE_PROFILE, "name", name, @@ -187,10 +184,10 @@ mate_mixer_profile_get_description (MateMixerProfile *profile) return profile->priv->description; } -guint32 +gulong mate_mixer_profile_get_priority (MateMixerProfile *profile) { - g_return_val_if_fail (MATE_MIXER_IS_PROFILE (profile), G_MAXUINT32); + g_return_val_if_fail (MATE_MIXER_IS_PROFILE (profile), 0); return profile->priv->priority; } diff --git a/libmatemixer/matemixer-profile.h b/libmatemixer/matemixer-profile.h index 7be140b..4ce0d1a 100644 --- a/libmatemixer/matemixer-profile.h +++ b/libmatemixer/matemixer-profile.h @@ -42,25 +42,25 @@ typedef struct _MateMixerProfilePrivate MateMixerProfilePrivate; struct _MateMixerProfile { - GObject parent; - - MateMixerProfilePrivate *priv; + /*< private >*/ + GObject parent; + MateMixerProfilePrivate *priv; }; struct _MateMixerProfileClass { - GObjectClass parent; + /*< private >*/ + GObjectClass parent; }; -GType mate_mixer_profile_get_type (void) G_GNUC_CONST; - +GType mate_mixer_profile_get_type (void) G_GNUC_CONST; MateMixerProfile *mate_mixer_profile_new (const gchar *name, const gchar *description, - guint32 priority); + gulong 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); +gulong mate_mixer_profile_get_priority (MateMixerProfile *profile); G_END_DECLS diff --git a/libmatemixer/matemixer-stream.c b/libmatemixer/matemixer-stream.c index 8fd309d..e2c9820 100644 --- a/libmatemixer/matemixer-stream.c +++ b/libmatemixer/matemixer-stream.c @@ -65,6 +65,16 @@ mate_mixer_stream_default_init (MateMixerStreamInterface *iface) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_interface_install_property (iface, + g_param_spec_flags ("flags", + "Flags", + "Capability flags of the stream", + MATE_MIXER_TYPE_STREAM_FLAGS, + MATE_MIXER_STREAM_NO_FLAGS, + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + g_object_interface_install_property (iface, g_param_spec_enum ("status", "Status", @@ -80,19 +90,30 @@ mate_mixer_stream_default_init (MateMixerStreamInterface *iface) "Mute", "Mute state of the stream", FALSE, - G_PARAM_READABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_interface_install_property (iface, - g_param_spec_uint ("volume", - "Volume", - "Volume of the stream", + g_param_spec_uint ("num-channels", + "Number of channels", + "Number of volume channels in the stream", 0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_interface_install_property (iface, + g_param_spec_int64 ("volume", + "Volume", + "Volume of the stream", + G_MININT64, + G_MAXINT64, + 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + g_object_interface_install_property (iface, g_param_spec_double ("volume-db", "Volume dB", @@ -128,7 +149,8 @@ mate_mixer_stream_default_init (MateMixerStreamInterface *iface) "Active port", "The currently active port of the stream", MATE_MIXER_TYPE_PORT, - G_PARAM_READABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); } @@ -237,7 +259,7 @@ mate_mixer_stream_set_mute (MateMixerStream *stream, gboolean mute) return FALSE; } -guint32 +gint64 mate_mixer_stream_get_volume (MateMixerStream *stream) { MateMixerStreamInterface *iface; @@ -253,7 +275,7 @@ mate_mixer_stream_get_volume (MateMixerStream *stream) } gboolean -mate_mixer_stream_set_volume (MateMixerStream *stream, guint32 volume) +mate_mixer_stream_set_volume (MateMixerStream *stream, gint64 volume) { MateMixerStreamInterface *iface; @@ -297,7 +319,7 @@ mate_mixer_stream_set_volume_db (MateMixerStream *stream, gdouble volume_db) return FALSE; } -guint8 +guint mate_mixer_stream_get_num_channels (MateMixerStream *stream) { MateMixerStreamInterface *iface; @@ -313,7 +335,7 @@ mate_mixer_stream_get_num_channels (MateMixerStream *stream) } MateMixerChannelPosition -mate_mixer_stream_get_channel_position (MateMixerStream *stream, guint8 channel) +mate_mixer_stream_get_channel_position (MateMixerStream *stream, guint channel) { MateMixerStreamInterface *iface; @@ -327,8 +349,8 @@ mate_mixer_stream_get_channel_position (MateMixerStream *stream, guint8 channel) return MATE_MIXER_CHANNEL_UNKNOWN_POSITION; } -guint32 -mate_mixer_stream_get_channel_volume (MateMixerStream *stream, guint8 channel) +gint64 +mate_mixer_stream_get_channel_volume (MateMixerStream *stream, guint channel) { MateMixerStreamInterface *iface; @@ -344,8 +366,8 @@ mate_mixer_stream_get_channel_volume (MateMixerStream *stream, guint8 channel) gboolean mate_mixer_stream_set_channel_volume (MateMixerStream *stream, - guint8 channel, - guint32 volume) + guint channel, + gint64 volume) { MateMixerStreamInterface *iface; @@ -360,7 +382,7 @@ mate_mixer_stream_set_channel_volume (MateMixerStream *stream, } gdouble -mate_mixer_stream_get_channel_volume_db (MateMixerStream *stream, guint8 channel) +mate_mixer_stream_get_channel_volume_db (MateMixerStream *stream, guint channel) { MateMixerStreamInterface *iface; @@ -376,7 +398,7 @@ mate_mixer_stream_get_channel_volume_db (MateMixerStream *stream, guint8 channel gboolean mate_mixer_stream_set_channel_volume_db (MateMixerStream *stream, - guint8 channel, + guint channel, gdouble volume_db) { MateMixerStreamInterface *iface; @@ -407,7 +429,7 @@ mate_mixer_stream_has_position (MateMixerStream *stream, return FALSE; } -guint32 +gint64 mate_mixer_stream_get_position_volume (MateMixerStream *stream, MateMixerChannelPosition position) { @@ -426,7 +448,7 @@ mate_mixer_stream_get_position_volume (MateMixerStream *stream, gboolean mate_mixer_stream_set_position_volume (MateMixerStream *stream, MateMixerChannelPosition position, - guint32 volume) + gint64 volume) { MateMixerStreamInterface *iface; @@ -533,6 +555,36 @@ mate_mixer_stream_set_fade (MateMixerStream *stream, gdouble fade) return FALSE; } +gboolean +mate_mixer_stream_suspend (MateMixerStream *stream) +{ + MateMixerStreamInterface *iface; + + g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), FALSE); + + iface = MATE_MIXER_STREAM_GET_INTERFACE (stream); + + if (iface->suspend) + return iface->suspend (stream); + + return FALSE; +} + +gboolean +mate_mixer_stream_resume (MateMixerStream *stream) +{ + MateMixerStreamInterface *iface; + + g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), FALSE); + + iface = MATE_MIXER_STREAM_GET_INTERFACE (stream); + + if (iface->resume) + return iface->resume (stream); + + return FALSE; +} + const GList * mate_mixer_stream_list_ports (MateMixerStream *stream) { @@ -578,3 +630,48 @@ mate_mixer_stream_set_active_port (MateMixerStream *stream, const gchar *port_na return FALSE; } + +gint64 +mate_mixer_stream_get_min_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_min_volume) + return iface->get_min_volume (stream); + + return 0; +} + +gint64 +mate_mixer_stream_get_max_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_max_volume) + return iface->get_max_volume (stream); + + return 0; +} + +gint64 +mate_mixer_stream_get_normal_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_normal_volume) + return iface->get_normal_volume (stream); + + return 0; +} diff --git a/libmatemixer/matemixer-stream.h b/libmatemixer/matemixer-stream.h index a6e8dde..d773398 100644 --- a/libmatemixer/matemixer-stream.h +++ b/libmatemixer/matemixer-stream.h @@ -41,42 +41,44 @@ typedef struct _MateMixerStreamInterface MateMixerStreamInterface; struct _MateMixerStreamInterface { + /*< private >*/ 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); + MateMixerStreamFlags (*get_flags) (MateMixerStream *stream); MateMixerStreamStatus (*get_status) (MateMixerStream *stream); gboolean (*get_mute) (MateMixerStream *stream); gboolean (*set_mute) (MateMixerStream *stream, gboolean mute); - guint32 (*get_volume) (MateMixerStream *stream); + guint (*get_num_channels) (MateMixerStream *stream); + gint64 (*get_volume) (MateMixerStream *stream); gboolean (*set_volume) (MateMixerStream *stream, - guint32 volume); + gint64 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); + guint channel); + gint64 (*get_channel_volume) (MateMixerStream *stream, + guint channel); gboolean (*set_channel_volume) (MateMixerStream *stream, - guint8 channel, - guint32 volume); + guint channel, + gint64 volume); gdouble (*get_channel_volume_db) (MateMixerStream *stream, - guint8 channel); + guint channel); gboolean (*set_channel_volume_db) (MateMixerStream *stream, - guint8 channel, + guint channel, gdouble volume_db); gboolean (*has_position) (MateMixerStream *stream, MateMixerChannelPosition position); - guint32 (*get_position_volume) (MateMixerStream *stream, + gint64 (*get_position_volume) (MateMixerStream *stream, MateMixerChannelPosition position); gboolean (*set_position_volume) (MateMixerStream *stream, MateMixerChannelPosition position, - guint32 volume); + gint64 volume); gdouble (*get_position_volume_db) (MateMixerStream *stream, MateMixerChannelPosition position); gboolean (*set_position_volume_db) (MateMixerStream *stream, @@ -88,57 +90,63 @@ struct _MateMixerStreamInterface gdouble (*get_fade) (MateMixerStream *stream); gboolean (*set_fade) (MateMixerStream *stream, gdouble fade); + gboolean (*suspend) (MateMixerStream *stream); + gboolean (*resume) (MateMixerStream *stream); + const GList * (*list_ports) (MateMixerStream *stream); MateMixerPort * (*get_active_port) (MateMixerStream *stream); gboolean (*set_active_port) (MateMixerStream *stream, const gchar *port_name); - const GList * (*list_ports) (MateMixerStream *stream); + gint64 (*get_min_volume) (MateMixerStream *stream); + gint64 (*get_max_volume) (MateMixerStream *stream); + gint64 (*get_normal_volume) (MateMixerStream *stream); }; -GType mate_mixer_stream_get_type (void) G_GNUC_CONST; +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); +MateMixerStreamFlags mate_mixer_stream_get_flags (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); +guint mate_mixer_stream_get_num_channels (MateMixerStream *stream); + +gint64 mate_mixer_stream_get_volume (MateMixerStream *stream); gboolean mate_mixer_stream_set_volume (MateMixerStream *stream, - guint32 volume); + gint64 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); + guint channel); -guint32 mate_mixer_stream_get_channel_volume (MateMixerStream *stream, - guint8 channel); +gint64 mate_mixer_stream_get_channel_volume (MateMixerStream *stream, + guint channel); gboolean mate_mixer_stream_set_channel_volume (MateMixerStream *stream, - guint8 channel, - guint32 volume); + guint channel, + gint64 volume); gdouble mate_mixer_stream_get_channel_volume_db (MateMixerStream *stream, - guint8 channel); + guint channel); gboolean mate_mixer_stream_set_channel_volume_db (MateMixerStream *stream, - guint8 channel, + guint channel, gdouble volume_db); gboolean mate_mixer_stream_has_position (MateMixerStream *stream, MateMixerChannelPosition position); -guint32 mate_mixer_stream_get_position_volume (MateMixerStream *stream, +gint64 mate_mixer_stream_get_position_volume (MateMixerStream *stream, MateMixerChannelPosition position); gboolean mate_mixer_stream_set_position_volume (MateMixerStream *stream, MateMixerChannelPosition position, - guint32 volume); + gint64 volume); gdouble mate_mixer_stream_get_position_volume_db (MateMixerStream *stream, MateMixerChannelPosition position); @@ -154,12 +162,19 @@ gdouble mate_mixer_stream_get_fade (MateMixerStre gboolean mate_mixer_stream_set_fade (MateMixerStream *stream, gdouble fade); +gboolean mate_mixer_stream_suspend (MateMixerStream *stream); +gboolean mate_mixer_stream_resume (MateMixerStream *stream); + 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, const gchar *port); +gint64 mate_mixer_stream_get_min_volume (MateMixerStream *stream); +gint64 mate_mixer_stream_get_max_volume (MateMixerStream *stream); +gint64 mate_mixer_stream_get_normal_volume (MateMixerStream *stream); + G_END_DECLS #endif /* MATEMIXER_STREAM_H */ diff --git a/libmatemixer/matemixer-version.h.in b/libmatemixer/matemixer-version.h.in new file mode 100644 index 0000000..17ea7b4 --- /dev/null +++ b/libmatemixer/matemixer-version.h.in @@ -0,0 +1,64 @@ +/* + * 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_VERSION_H +#define MATEMIXER_VERSION_H + +/** + * LIBMATEMIXER_MAJOR_VERSION: + * + * Libmatemixer major version component (e.g. 1 if %LIBMATEMIXER_VERSION is 1.2.3). + */ +#define LIBMATEMIXER_MAJOR_VERSION (@LIBMATEMIXER_MAJOR_VERSION@) + +/** + * LIBMATEMIXER_MINOR_VERSION: + * + * Libmatemixer minor version component (e.g. 2 if %LIBMATEMIXER_VERSION is 1.2.3). + */ +#define LIBMATEMIXER_MINOR_VERSION (@LIBMATEMIXER_MINOR_VERSION@) + +/** + * LIBMATEMIXER_MICRO_VERSION: + * + * Libmatemixer micro version component (e.g. 3 if %LIBMATEMIXER_VERSION is 1.2.3). + */ +#define LIBMATEMIXER_MICRO_VERSION (@LIBMATEMIXER_MICRO_VERSION@) + +/** + * LIBMATEMIXER_VERSION: + * + * Libmatemixer version. + */ +#define LIBMATEMIXER_VERSION (@LIBMATEMIXER_VERSION@) + +/** + * LIBMATEMIXER_CHECK_VERSION: + * @major: major version number + * @minor: minor version number + * @micro: micro version number + * + * Compile-time version checking. Evaluates to %TRUE if the version of the + * library is greater than the required one. + */ +#define LIBMATEMIXER_CHECK_VERSION(major, minor, micro) \ + (LIBMATEMIXER_MAJOR_VERSION > (major) || \ + (LIBMATEMIXER_MAJOR_VERSION == (major) && LIBMATEMIXER_MINOR_VERSION > (minor)) || \ + (LIBMATEMIXER_MAJOR_VERSION == (major) && LIBMATEMIXER_MINOR_VERSION == (minor) && \ + LIBMATEMIXER_MICRO_VERSION >= (micro))) + +#endif /* LIBMATEMIXER_VERSION_H */ diff --git a/libmatemixer/matemixer.c b/libmatemixer/matemixer.c index 3c8f643..1e5d4e0 100644 --- a/libmatemixer/matemixer.c +++ b/libmatemixer/matemixer.c @@ -25,12 +25,21 @@ #include "matemixer-private.h" #include "matemixer-backend-module.h" -static void mixer_load_modules (void); -static gint mixer_compare_modules (gconstpointer a, gconstpointer b); +static void mixer_load_modules (void); +static gint mixer_compare_modules (gconstpointer a, gconstpointer b); static GList *mixer_modules = NULL; static gboolean mixer_initialized = FALSE; +/** + * mate_mixer_init: + * + * Initializes the library. You must call this function before using any other + * function from the library. + * + * Returns: %TRUE on success, or %FALSE if the library installation is broken and + * does not provide support for any sound systems. + */ gboolean mate_mixer_init (void) { @@ -66,6 +75,12 @@ mate_mixer_init (void) return mixer_initialized; } +/** + * mate_mixer_deinit: + * + * Deinitializes the library. You should call this function when you do not need + * to use the library any longer or before exitting the application. + */ void mate_mixer_deinit (void) { @@ -135,14 +150,14 @@ mixer_load_modules (void) g_error_free (error); } } else { - g_critical ("Unable to load backend modules: GModule not supported"); + g_critical ("Unable to load backend modules: GModule is not supported in your system"); } loaded = TRUE; } -/* GCompareFunc function to sort backend modules by the priority, lower - * number means higher priority */ +/* GCompareFunc function to sort backend modules by the priority, higher number means + * higher priority */ static gint mixer_compare_modules (gconstpointer a, gconstpointer b) { @@ -151,5 +166,5 @@ mixer_compare_modules (gconstpointer a, gconstpointer b) info1 = mate_mixer_backend_module_get_info (MATE_MIXER_BACKEND_MODULE (a)); info2 = mate_mixer_backend_module_get_info (MATE_MIXER_BACKEND_MODULE (b)); - return info1->priority - info2->priority; + return info2->priority - info1->priority; } diff --git a/libmatemixer/matemixer.h b/libmatemixer/matemixer.h index b43de79..99df233 100644 --- a/libmatemixer/matemixer.h +++ b/libmatemixer/matemixer.h @@ -26,8 +26,8 @@ G_BEGIN_DECLS -gboolean mate_mixer_init (void); -void mate_mixer_deinit (void); +gboolean mate_mixer_init (void); +void mate_mixer_deinit (void); G_END_DECLS -- cgit v1.2.1