summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichal Ratajsky <[email protected]>2014-05-24 21:01:21 +0200
committerMichal Ratajsky <[email protected]>2014-05-24 21:01:21 +0200
commit4db8dc0cbb3959d6278a9e7650d5103a475ab897 (patch)
tree4bc508298ce65013a5819cf0cdde7444c23abdb2
parentcaf4d9b8b8b0d26856d2d64f00ab23756867a923 (diff)
downloadlibmatemixer-4db8dc0cbb3959d6278a9e7650d5103a475ab897.tar.bz2
libmatemixer-4db8dc0cbb3959d6278a9e7650d5103a475ab897.tar.xz
General additions and improvements
-rw-r--r--backends/null/null.c13
-rw-r--r--backends/null/null.h2
-rw-r--r--backends/pulse/pulse-device.c53
-rw-r--r--backends/pulse/pulse-device.h18
-rw-r--r--backends/pulse/pulse.c12
-rw-r--r--libmatemixer/matemixer-backend-module.c121
-rw-r--r--libmatemixer/matemixer-backend.c34
-rw-r--r--libmatemixer/matemixer-backend.h18
-rw-r--r--libmatemixer/matemixer-control.c114
-rw-r--r--libmatemixer/matemixer-control.h11
-rw-r--r--libmatemixer/matemixer-device-port.c66
-rw-r--r--libmatemixer/matemixer-device-port.h14
-rw-r--r--libmatemixer/matemixer-device-profile.c30
-rw-r--r--libmatemixer/matemixer-device-profile.h4
-rw-r--r--libmatemixer/matemixer-device.c66
-rw-r--r--libmatemixer/matemixer-device.h16
-rw-r--r--libmatemixer/matemixer-enums.h1
-rw-r--r--libmatemixer/matemixer.c134
18 files changed, 503 insertions, 224 deletions
diff --git a/backends/null/null.c b/backends/null/null.c
index c049dcb..b96c9b0 100644
--- a/backends/null/null.c
+++ b/backends/null/null.c
@@ -28,7 +28,6 @@
/* Support function for dynamic loading of the backend module */
void backend_module_init (GTypeModule *module);
-void backend_module_free (void);
const MateMixerBackendModuleInfo *backend_module_get_info (void);
@@ -52,11 +51,6 @@ backend_module_init (GTypeModule *module)
info.backend_type = MATE_MIXER_BACKEND_TYPE_NULL;
}
-void
-backend_module_free (void)
-{
-}
-
const MateMixerBackendModuleInfo *
backend_module_get_info (void)
{
@@ -66,6 +60,7 @@ backend_module_get_info (void)
static void
mate_mixer_backend_interface_init (MateMixerBackendInterface *iface)
{
+ iface->open = mate_mixer_null_open;
}
static void
@@ -93,3 +88,9 @@ static void
mate_mixer_null_class_finalize (MateMixerNullClass *klass)
{
}
+
+gboolean
+mate_mixer_null_open (MateMixerBackend *backend)
+{
+ return TRUE;
+}
diff --git a/backends/null/null.h b/backends/null/null.h
index ef5b779..d73794e 100644
--- a/backends/null/null.h
+++ b/backends/null/null.h
@@ -51,4 +51,6 @@ struct _MateMixerNullClass
GType mate_mixer_null_get_type (void) G_GNUC_CONST;
+gboolean mate_mixer_null_open (MateMixerBackend *backend);
+
#endif /* MATEMIXER_NULL_H */
diff --git a/backends/pulse/pulse-device.c b/backends/pulse/pulse-device.c
index 75c5a32..4421e97 100644
--- a/backends/pulse/pulse-device.c
+++ b/backends/pulse/pulse-device.c
@@ -57,7 +57,11 @@ G_DEFINE_TYPE_WITH_CODE (MateMixerPulseDevice, mate_mixer_pulse_device, G_TYPE_O
static void
mate_mixer_device_interface_init (MateMixerDeviceInterface *iface)
{
-
+ iface->list_tracks = mate_mixer_pulse_device_list_tracks;
+ iface->get_ports = mate_mixer_pulse_device_get_ports;
+ iface->get_profiles = mate_mixer_pulse_device_get_profiles;
+ iface->get_active_profile = mate_mixer_pulse_device_get_active_profile;
+ iface->set_active_profile = mate_mixer_pulse_device_set_active_profile;
}
static void
@@ -119,7 +123,9 @@ mate_mixer_pulse_device_set_property (GObject *object,
device->priv->icon = g_strdup (g_value_get_string (value));
break;
case PROP_ACTIVE_PROFILE:
- // TODO
+ mate_mixer_pulse_device_set_active_profile (
+ MATE_MIXER_DEVICE (device),
+ g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
@@ -261,33 +267,50 @@ mate_mixer_pulse_device_new (const pa_card_info *info)
return device;
}
+gboolean
+mate_mixer_pulse_device_update (MateMixerPulseDevice *device, const pa_card_info *info)
+{
+ g_return_val_if_fail (MATE_MIXER_IS_PULSE_DEVICE (device), FALSE);
+ g_return_val_if_fail (info != NULL, FALSE);
+
+ // TODO: update status, active_profile, maybe others?
+ return TRUE;
+}
+
+const GList *
+mate_mixer_pulse_device_list_tracks (MateMixerDevice *device)
+{
+ // TODO
+ return NULL;
+}
+
const GList *
-mate_mixer_pulse_device_get_ports (MateMixerPulseDevice *device)
+mate_mixer_pulse_device_get_ports (MateMixerDevice *device)
{
g_return_val_if_fail (MATE_MIXER_IS_PULSE_DEVICE (device), NULL);
- return device->priv->ports;
+ return MATE_MIXER_PULSE_DEVICE (device)->priv->ports;
}
const GList *
-mate_mixer_pulse_device_get_profiles (MateMixerPulseDevice *device)
+mate_mixer_pulse_device_get_profiles (MateMixerDevice *device)
{
g_return_val_if_fail (MATE_MIXER_IS_PULSE_DEVICE (device), NULL);
- return device->priv->profiles;
+ return MATE_MIXER_PULSE_DEVICE (device)->priv->profiles;
}
MateMixerDeviceProfile *
-mate_mixer_pulse_device_get_active_profile (MateMixerPulseDevice *device)
+mate_mixer_pulse_device_get_active_profile (MateMixerDevice *device)
{
g_return_val_if_fail (MATE_MIXER_IS_PULSE_DEVICE (device), NULL);
- return device->priv->active_profile;
+ return MATE_MIXER_PULSE_DEVICE (device)->priv->active_profile;
}
gboolean
-mate_mixer_pulse_device_set_active_profile (MateMixerPulseDevice *device,
- MateMixerDeviceProfile *profile)
+mate_mixer_pulse_device_set_active_profile (MateMixerDevice *device,
+ MateMixerDeviceProfile *profile)
{
g_return_val_if_fail (MATE_MIXER_IS_PULSE_DEVICE (device), FALSE);
g_return_val_if_fail (MATE_MIXER_IS_DEVICE_PROFILE (profile), FALSE);
@@ -296,13 +319,3 @@ mate_mixer_pulse_device_set_active_profile (MateMixerPulseDevice *device,
// pa_context_set_card_profile_by_index ()
return TRUE;
}
-
-gboolean
-mate_mixer_pulse_device_update (MateMixerPulseDevice *device, const pa_card_info *info)
-{
- g_return_val_if_fail (MATE_MIXER_IS_PULSE_DEVICE (device), FALSE);
- g_return_val_if_fail (info != NULL, FALSE);
-
- // TODO: update status, active_profile, maybe others?
- return TRUE;
-}
diff --git a/backends/pulse/pulse-device.h b/backends/pulse/pulse-device.h
index f8b5a07..ab997fe 100644
--- a/backends/pulse/pulse-device.h
+++ b/backends/pulse/pulse-device.h
@@ -60,18 +60,20 @@ struct _MateMixerPulseDeviceClass
GType mate_mixer_pulse_device_get_type (void) G_GNUC_CONST;
MateMixerPulseDevice *mate_mixer_pulse_device_new (const pa_card_info *info);
-GList *mate_mixer_pulse_device_list_tracks (MateMixerPulseDevice *device);
-const GList *mate_mixer_pulse_device_get_ports (MateMixerPulseDevice *device);
-const GList *mate_mixer_pulse_device_get_profiles (MateMixerPulseDevice *device);
+gboolean mate_mixer_pulse_device_update (MateMixerPulseDevice *device,
+ const pa_card_info *info);
-MateMixerDeviceProfile *mate_mixer_pulse_device_get_active_profile (MateMixerPulseDevice *device);
+/* Interface implementation */
+const GList *mate_mixer_pulse_device_list_tracks (MateMixerDevice *device);
-gboolean mate_mixer_pulse_device_set_active_profile (MateMixerPulseDevice *device,
- MateMixerDeviceProfile *profile);
+const GList *mate_mixer_pulse_device_get_ports (MateMixerDevice *device);
+const GList *mate_mixer_pulse_device_get_profiles (MateMixerDevice *device);
-gboolean mate_mixer_pulse_device_update (MateMixerPulseDevice *device,
- const pa_card_info *info);
+MateMixerDeviceProfile *mate_mixer_pulse_device_get_active_profile (MateMixerDevice *device);
+
+gboolean mate_mixer_pulse_device_set_active_profile (MateMixerDevice *device,
+ MateMixerDeviceProfile *profile);
G_END_DECLS
diff --git a/backends/pulse/pulse.c b/backends/pulse/pulse.c
index e969dcf..d306577 100644
--- a/backends/pulse/pulse.c
+++ b/backends/pulse/pulse.c
@@ -41,7 +41,6 @@ struct _MateMixerPulsePrivate
/* Support function for dynamic loading of the backend module */
void backend_module_init (GTypeModule *module);
-void backend_module_free (void);
const MateMixerBackendModuleInfo *backend_module_get_info (void);
@@ -81,11 +80,6 @@ backend_module_init (GTypeModule *module)
info.backend_type = MATE_MIXER_BACKEND_TYPE_PULSE;
}
-void
-backend_module_free (void)
-{
-}
-
const MateMixerBackendModuleInfo *
backend_module_get_info (void)
{
@@ -95,9 +89,9 @@ backend_module_get_info (void)
static void
mate_mixer_backend_interface_init (MateMixerBackendInterface *iface)
{
- iface->open = mate_mixer_pulse_open;
- iface->close = mate_mixer_pulse_close;
- iface->list_devices = mate_mixer_pulse_list_devices;
+ iface->open = mate_mixer_pulse_open;
+ iface->close = mate_mixer_pulse_close;
+ iface->list_devices = mate_mixer_pulse_list_devices;
}
static void
diff --git a/libmatemixer/matemixer-backend-module.c b/libmatemixer/matemixer-backend-module.c
index 0acd786..7846359 100644
--- a/libmatemixer/matemixer-backend-module.c
+++ b/libmatemixer/matemixer-backend-module.c
@@ -28,15 +28,16 @@ struct _MateMixerBackendModulePrivate
{
GModule *gmodule;
gchar *path;
+ gboolean loaded;
- void (*init) (GTypeModule *type_module);
- void (*free) (void);
+ void (*init) (GTypeModule *type_module);
+ void (*deinit) (void);
const MateMixerBackendModuleInfo *(*get_info) (void);
};
-static gboolean mate_mixer_backend_module_load (GTypeModule *gmodule);
-static void mate_mixer_backend_module_unload (GTypeModule *gmodule);
+static gboolean mate_mixer_backend_module_load (GTypeModule *gmodule);
+static void mate_mixer_backend_module_unload (GTypeModule *gmodule);
static void
mate_mixer_backend_module_init (MateMixerBackendModule *module)
@@ -48,6 +49,22 @@ mate_mixer_backend_module_init (MateMixerBackendModule *module)
}
static void
+mate_mixer_backend_module_dispose (GObject *object)
+{
+ MateMixerBackendModule *module;
+
+ module = MATE_MIXER_BACKEND_MODULE (object);
+
+ if (module->priv->loaded) {
+ /* Keep the module alive and avoid calling the parent dispose, which
+ * would do the same thing and also produce a warning */
+ g_object_ref (object);
+ return;
+ }
+ G_OBJECT_CLASS (mate_mixer_backend_module_parent_class)->dispose (object);
+}
+
+static void
mate_mixer_backend_module_finalize (GObject *object)
{
MateMixerBackendModule *module;
@@ -66,6 +83,7 @@ mate_mixer_backend_module_class_init (MateMixerBackendModuleClass *klass)
GTypeModuleClass *gtype_class;
object_class = G_OBJECT_CLASS (klass);
+ object_class->dispose = mate_mixer_backend_module_dispose;
object_class->finalize = mate_mixer_backend_module_finalize;
gtype_class = G_TYPE_MODULE_CLASS (klass);
@@ -82,39 +100,64 @@ mate_mixer_backend_module_load (GTypeModule *type_module)
module = MATE_MIXER_BACKEND_MODULE (type_module);
- module->priv->gmodule = g_module_open (
- module->priv->path,
- G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
-
- if (module->priv->gmodule == NULL) {
- g_warning ("Failed to load backend module %s: %s",
- module->priv->path,
- g_module_error ());
-
- return FALSE;
+ if (!module->priv->loaded) {
+ module->priv->gmodule = g_module_open (
+ module->priv->path,
+ G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
+
+ if (module->priv->gmodule == NULL) {
+ g_warning ("Failed to load backend module %s: %s",
+ module->priv->path,
+ g_module_error ());
+
+ return FALSE;
+ }
+
+ /* Validate library symbols that each backend module must provide */
+ if (!g_module_symbol (module->priv->gmodule,
+ "backend_module_init",
+ (gpointer *) &module->priv->init) ||
+ !g_module_symbol (module->priv->gmodule,
+ "backend_module_get_info",
+ (gpointer *) &module->priv->get_info)) {
+ g_warning ("Failed to load backend module %s: %s",
+ module->priv->path,
+ g_module_error ());
+
+ g_module_close (module->priv->gmodule);
+ return FALSE;
+ }
+
+ /* Optional backend functions */
+ g_module_symbol (module->priv->gmodule,
+ "backend_module_deinit",
+ (gpointer *) &module->priv->deinit);
+
+ 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 */
+ if (G_UNLIKELY (module->priv->get_info () == NULL)) {
+ g_warning ("Backend module %s does not provide module information",
+ module->priv->path);
+
+ /* Close the module but keep the loaded flag to avoid unreffing
+ * this instance as the GType has most likely been registered */
+ g_module_close (module->priv->gmodule);
+ return FALSE;
+ }
+
+ /* It is not possible to unref this instance, so let's avoid unloading
+ * the module and just let the backend module (de)initialize when
+ * (un)load are called repeatedly */
+ g_module_make_resident (module->priv->gmodule);
+
+ g_debug ("Loaded backend module %s", module->priv->path);
+ } else {
+ /* This function was called before so initialize only */
+ module->priv->init (type_module);
}
-
- /* Validate library symbols that each backend module must provide */
- if (!g_module_symbol (module->priv->gmodule,
- "backend_module_init",
- (gpointer *) &module->priv->init) ||
- !g_module_symbol (module->priv->gmodule,
- "backend_module_free",
- (gpointer *) &module->priv->free) ||
- !g_module_symbol (module->priv->gmodule,
- "backend_module_get_info",
- (gpointer *) &module->priv->get_info)) {
- g_warning ("Failed to load backend module %s: %s",
- module->priv->path,
- g_module_error ());
-
- g_module_close (module->priv->gmodule);
- return FALSE;
- }
-
- g_debug ("Loaded backend module %s", module->priv->path);
-
- module->priv->init (type_module);
return TRUE;
}
@@ -124,9 +167,11 @@ mate_mixer_backend_module_unload (GTypeModule *type_module)
MateMixerBackendModule *module;
module = MATE_MIXER_BACKEND_MODULE (type_module);
- module->priv->free ();
- g_module_close (module->priv->gmodule);
+ /* Only deinitialize the backend module, do not modify the loaded
+ * flag as the module remains loaded */
+ if (module->priv->deinit)
+ module->priv->deinit ();
}
MateMixerBackendModule *
diff --git a/libmatemixer/matemixer-backend.c b/libmatemixer/matemixer-backend.c
index 9533e0f..18e622f 100644
--- a/libmatemixer/matemixer-backend.c
+++ b/libmatemixer/matemixer-backend.c
@@ -30,31 +30,53 @@ mate_mixer_backend_default_init (MateMixerBackendInterface *iface)
gboolean
mate_mixer_backend_open (MateMixerBackend *backend)
{
+ MateMixerBackendInterface *iface;
+
g_return_val_if_fail (MATE_MIXER_IS_BACKEND (backend), NULL);
- return MATE_MIXER_BACKEND_GET_INTERFACE (backend)->open (backend);
+ iface = MATE_MIXER_BACKEND_GET_INTERFACE (backend);
+ if (iface->open)
+ return iface->open (backend);
+
+ return FALSE;
}
void
mate_mixer_backend_close (MateMixerBackend *backend)
{
+ MateMixerBackendInterface *iface;
+
g_return_val_if_fail (MATE_MIXER_IS_BACKEND (backend), NULL);
- MATE_MIXER_BACKEND_GET_INTERFACE (backend)->close (backend);
+ iface = MATE_MIXER_BACKEND_GET_INTERFACE (backend);
+ if (iface->close)
+ iface->close (backend);
}
-const GList *
+GList *
mate_mixer_backend_list_devices (MateMixerBackend *backend)
{
+ MateMixerBackendInterface *iface;
+
g_return_val_if_fail (MATE_MIXER_IS_BACKEND (backend), NULL);
- return MATE_MIXER_BACKEND_GET_INTERFACE (backend)->list_devices (backend);
+ iface = MATE_MIXER_BACKEND_GET_INTERFACE (backend);
+ if (iface->list_devices)
+ return iface->list_devices (backend);
+
+ return NULL;
}
-const GList *
+GList *
mate_mixer_backend_list_tracks (MateMixerBackend *backend)
{
+ MateMixerBackendInterface *iface;
+
g_return_val_if_fail (MATE_MIXER_IS_BACKEND (backend), NULL);
- return MATE_MIXER_BACKEND_GET_INTERFACE (backend)->list_tracks (backend);
+ iface = MATE_MIXER_BACKEND_GET_INTERFACE (backend);
+ if (iface->list_tracks)
+ return iface->list_tracks (backend);
+
+ return NULL;
}
diff --git a/libmatemixer/matemixer-backend.h b/libmatemixer/matemixer-backend.h
index 6b0c318..e5a8585 100644
--- a/libmatemixer/matemixer-backend.h
+++ b/libmatemixer/matemixer-backend.h
@@ -41,18 +41,20 @@ struct _MateMixerBackendInterface
{
GTypeInterface parent;
- gboolean (*open) (MateMixerBackend *backend);
- void (*close) (MateMixerBackend *backend);
- const GList *(*list_devices) (MateMixerBackend *backend);
- const GList *(*list_tracks) (MateMixerBackend *backend);
+ /* Required */
+ gboolean (*open) (MateMixerBackend *backend);
+
+ void (*close) (MateMixerBackend *backend);
+ GList *(*list_devices) (MateMixerBackend *backend);
+ GList *(*list_tracks) (MateMixerBackend *backend);
};
GType mate_mixer_backend_get_type (void) G_GNUC_CONST;
-gboolean mate_mixer_backend_open (MateMixerBackend *backend);
-void mate_mixer_backend_close (MateMixerBackend *backend);
-const GList *mate_mixer_backend_list_devices (MateMixerBackend *backend);
-const GList *mate_mixer_backend_list_tracks (MateMixerBackend *backend);
+gboolean mate_mixer_backend_open (MateMixerBackend *backend);
+void mate_mixer_backend_close (MateMixerBackend *backend);
+GList *mate_mixer_backend_list_devices (MateMixerBackend *backend);
+GList *mate_mixer_backend_list_tracks (MateMixerBackend *backend);
G_END_DECLS
diff --git a/libmatemixer/matemixer-control.c b/libmatemixer/matemixer-control.c
index c3489e6..cf59ad5 100644
--- a/libmatemixer/matemixer-control.c
+++ b/libmatemixer/matemixer-control.c
@@ -27,15 +27,14 @@
struct _MateMixerControlPrivate
{
- MateMixerBackend *backend;
- GHashTable *devices;
- GHashTable *tracks;
+ GList *devices;
+ GList *tracks;
+ MateMixerBackend *backend;
+ MateMixerBackendModule *module;
};
G_DEFINE_TYPE (MateMixerControl, mate_mixer_control, G_TYPE_OBJECT);
-G_LOCK_DEFINE_STATIC (mixer_control_get_modules_lock);
-
static MateMixerBackend *mixer_control_init_module (MateMixerBackendModule *module);
static void
@@ -45,18 +44,6 @@ mate_mixer_control_init (MateMixerControl *control)
control,
MATE_MIXER_TYPE_CONTROL,
MateMixerControlPrivate);
-
- control->priv->devices = g_hash_table_new_full (
- g_direct_hash,
- g_direct_equal,
- NULL,
- g_object_unref);
-
- control->priv->tracks = g_hash_table_new_full (
- g_direct_hash,
- g_direct_equal,
- NULL,
- g_object_unref);
}
static void
@@ -66,9 +53,15 @@ mate_mixer_control_finalize (GObject *object)
control = MATE_MIXER_CONTROL (object);
+ mate_mixer_backend_close (control->priv->backend);
+
g_object_unref (control->priv->backend);
- g_hash_table_destroy (control->priv->devices);
- g_hash_table_destroy (control->priv->tracks);
+ g_object_unref (control->priv->module);
+
+ if (control->priv->devices)
+ g_list_free_full (control->priv->devices, g_object_unref);
+ if (control->priv->tracks)
+ g_list_free_full (control->priv->tracks, g_object_unref);
G_OBJECT_CLASS (mate_mixer_control_parent_class)->finalize (object);
}
@@ -87,21 +80,18 @@ mate_mixer_control_class_init (MateMixerControlClass *klass)
MateMixerControl *
mate_mixer_control_new (void)
{
- GList *modules;
- MateMixerControl *control;
- MateMixerBackend *backend = NULL;
+ GList *modules;
+ MateMixerControl *control;
+ MateMixerBackend *backend = NULL;
+ MateMixerBackendModule *module = NULL;
if (!mate_mixer_is_initialized ()) {
g_critical ("The library has not been initialized");
return NULL;
}
- G_LOCK (mixer_control_get_modules_lock);
-
modules = mate_mixer_get_modules ();
while (modules) {
- MateMixerBackendModule *module;
-
module = MATE_MIXER_BACKEND_MODULE (modules->data);
backend = mixer_control_init_module (module);
if (backend != NULL)
@@ -110,8 +100,6 @@ mate_mixer_control_new (void)
modules = modules->next;
}
- G_UNLOCK (mixer_control_get_modules_lock);
-
/* 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 */
@@ -119,6 +107,8 @@ mate_mixer_control_new (void)
return NULL;
control = g_object_new (MATE_MIXER_TYPE_CONTROL, NULL);
+
+ control->priv->module = g_object_ref (module);
control->priv->backend = backend;
return control;
@@ -127,22 +117,19 @@ mate_mixer_control_new (void)
MateMixerControl *
mate_mixer_control_new_backend (MateMixerBackendType backend_type)
{
- GList *modules;
- MateMixerControl *control;
- MateMixerBackend *backend = NULL;
+ GList *modules;
+ MateMixerControl *control;
+ MateMixerBackend *backend = NULL;
+ MateMixerBackendModule *module = NULL;
if (!mate_mixer_is_initialized ()) {
g_critical ("The library has not been initialized");
return NULL;
}
- G_LOCK (mixer_control_get_modules_lock);
-
modules = mate_mixer_get_modules ();
-
while (modules) {
- MateMixerBackendModule *module;
- const MateMixerBackendModuleInfo *info;
+ const MateMixerBackendModuleInfo *info;
module = MATE_MIXER_BACKEND_MODULE (modules->data);
info = mate_mixer_backend_module_get_info (module);
@@ -154,13 +141,13 @@ mate_mixer_control_new_backend (MateMixerBackendType backend_type)
modules = modules->next;
}
- G_UNLOCK (mixer_control_get_modules_lock);
-
/* The initialization might fail or the selected module might be absent */
if (backend == NULL)
return NULL;
control = g_object_new (MATE_MIXER_TYPE_CONTROL, NULL);
+
+ control->priv->module = g_object_ref (module);
control->priv->backend = backend;
return control;
@@ -171,12 +158,15 @@ mate_mixer_control_list_devices (MateMixerControl *control)
{
g_return_val_if_fail (MATE_MIXER_IS_CONTROL (control), NULL);
- // XXX
- // this is the midpoint between MateMixerDevice implementation and
- // the application, probably the list could be cached here but the
- // implementation uses a hash table, figure out how to do this properly
+ /* This list is cached here and invalidated when the backend
+ * notifies us about a change */
+ if (control->priv->devices == NULL)
+ control->priv->devices = mate_mixer_backend_list_devices (
+ MATE_MIXER_BACKEND (control->priv->backend));
- return mate_mixer_backend_list_devices (MATE_MIXER_BACKEND (control->priv->backend));
+ // TODO: notification signals from backend
+
+ return (const GList *) control->priv->devices;
}
const GList *
@@ -184,7 +174,37 @@ mate_mixer_control_list_tracks (MateMixerControl *control)
{
g_return_val_if_fail (MATE_MIXER_IS_CONTROL (control), NULL);
- return mate_mixer_backend_list_tracks (MATE_MIXER_BACKEND (control->priv->backend));
+ /* This list is cached here and invalidated when the backend
+ * notifies us about a change */
+ if (control->priv->tracks == NULL)
+ control->priv->tracks = mate_mixer_backend_list_tracks (
+ MATE_MIXER_BACKEND (control->priv->backend));
+
+ return (const GList *) control->priv->tracks;
+}
+
+const gchar *
+mate_mixer_control_get_backend_name (MateMixerControl *control)
+{
+ const MateMixerBackendModuleInfo *info;
+
+ g_return_val_if_fail (MATE_MIXER_IS_CONTROL (control), NULL);
+
+ info = mate_mixer_backend_module_get_info (control->priv->module);
+
+ return info->name;
+}
+
+MateMixerBackendType
+mate_mixer_control_get_backend_type (MateMixerControl *control)
+{
+ const MateMixerBackendModuleInfo *info;
+
+ g_return_val_if_fail (MATE_MIXER_IS_CONTROL (control), FALSE);
+
+ info = mate_mixer_backend_module_get_info (control->priv->module);
+
+ return info->backend_type;
}
static MateMixerBackend *
@@ -194,12 +214,6 @@ mixer_control_init_module (MateMixerBackendModule *module)
const MateMixerBackendModuleInfo *info;
info = mate_mixer_backend_module_get_info (module);
- if (G_UNLIKELY (info == NULL)) {
- g_warning ("Backend module %s does not provide module information",
- mate_mixer_backend_module_get_path (module));
- return NULL;
- }
-
backend = g_object_newv (info->g_type, 0, NULL);
if (!mate_mixer_backend_open (backend)) {
diff --git a/libmatemixer/matemixer-control.h b/libmatemixer/matemixer-control.h
index 010cbfa..739eabd 100644
--- a/libmatemixer/matemixer-control.h
+++ b/libmatemixer/matemixer-control.h
@@ -56,10 +56,13 @@ struct _MateMixerControlClass
GType mate_mixer_control_get_type (void) G_GNUC_CONST;
-MateMixerControl *mate_mixer_control_new (void);
-MateMixerControl *mate_mixer_control_new_backend (MateMixerBackendType backend_type);
-const GList *mate_mixer_control_list_devices (MateMixerControl *control);
-const GList *mate_mixer_control_list_tracks (MateMixerControl *control);
+MateMixerControl *mate_mixer_control_new (void);
+MateMixerControl *mate_mixer_control_new_backend (MateMixerBackendType backend_type);
+const GList *mate_mixer_control_list_devices (MateMixerControl *control);
+const GList *mate_mixer_control_list_tracks (MateMixerControl *control);
+
+const gchar *mate_mixer_control_get_backend_name (MateMixerControl *control);
+MateMixerBackendType mate_mixer_control_get_backend_type (MateMixerControl *control);
G_END_DECLS
diff --git a/libmatemixer/matemixer-device-port.c b/libmatemixer/matemixer-device-port.c
index 9443879..04771fa 100644
--- a/libmatemixer/matemixer-device-port.c
+++ b/libmatemixer/matemixer-device-port.c
@@ -155,28 +155,28 @@ mate_mixer_device_port_class_init (MateMixerDevicePortClass *klass)
object_class->get_property = mate_mixer_device_port_get_property;
object_class->set_property = mate_mixer_device_port_set_property;
- properties[PROP_IDENTIFIER] = g_param_spec_string(
+ properties[PROP_IDENTIFIER] = g_param_spec_string (
"identifier",
"Identifier",
"Identifier of the device port",
NULL,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
- properties[PROP_NAME] = g_param_spec_string(
+ properties[PROP_NAME] = g_param_spec_string (
"name",
"Name",
"Name of the device port",
NULL,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
- properties[PROP_ICON] = g_param_spec_string(
+ properties[PROP_ICON] = g_param_spec_string (
"icon",
"Icon",
"Icon name for the device port",
NULL,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
- properties[PROP_PRIORITY] = g_param_spec_uint(
+ properties[PROP_PRIORITY] = g_param_spec_uint (
"priority",
"Priority",
"Priority of the device port",
@@ -185,7 +185,7 @@ mate_mixer_device_port_class_init (MateMixerDevicePortClass *klass)
0,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
- properties[PROP_LATENCY_OFFSET] = g_param_spec_int64(
+ properties[PROP_LATENCY_OFFSET] = g_param_spec_int64 (
"latency-offset",
"Latency offset",
"Latency offset of the device port",
@@ -218,3 +218,59 @@ mate_mixer_device_port_new (const gchar *identifier,
"latency-offset", latency_offset,
NULL);
}
+
+const gchar *
+mate_mixer_device_port_get_identifier (MateMixerDevicePort *port)
+{
+ g_return_val_if_fail (MATE_MIXER_IS_DEVICE_PORT (port), NULL);
+
+ return port->priv->identifier;
+}
+
+const gchar *
+mate_mixer_device_port_get_name (MateMixerDevicePort *port)
+{
+ g_return_val_if_fail (MATE_MIXER_IS_DEVICE_PORT (port), NULL);
+
+ return port->priv->name;
+}
+
+const gchar *
+mate_mixer_device_port_get_icon (MateMixerDevicePort *port)
+{
+ g_return_val_if_fail (MATE_MIXER_IS_DEVICE_PORT (port), NULL);
+
+ return port->priv->icon;
+}
+
+guint32
+mate_mixer_device_port_get_priority (MateMixerDevicePort *port)
+{
+ g_return_val_if_fail (MATE_MIXER_IS_DEVICE_PORT (port), 0);
+
+ return port->priv->priority;
+}
+
+MateMixerDevicePortDirection
+mate_mixer_device_port_get_direction (MateMixerDevicePort *port)
+{
+ g_return_val_if_fail (MATE_MIXER_IS_DEVICE_PORT (port), 0);
+
+ return port->priv->direction;
+}
+
+MateMixerDevicePortStatus
+mate_mixer_device_port_get_status (MateMixerDevicePort *port)
+{
+ g_return_val_if_fail (MATE_MIXER_IS_DEVICE_PORT (port), 0);
+
+ return port->priv->status;
+}
+
+gint64
+mate_mixer_device_port_get_latency_offset (MateMixerDevicePort *port)
+{
+ g_return_val_if_fail (MATE_MIXER_IS_DEVICE_PORT (port), 0);
+
+ return port->priv->latency_offset;
+}
diff --git a/libmatemixer/matemixer-device-port.h b/libmatemixer/matemixer-device-port.h
index d411c89..d9dfbfa 100644
--- a/libmatemixer/matemixer-device-port.h
+++ b/libmatemixer/matemixer-device-port.h
@@ -64,6 +64,20 @@ MateMixerDevicePort *mate_mixer_device_port_new (const gchar *i
MateMixerDevicePortStatus status,
gint64 latency_offset);
+const gchar *mate_mixer_device_port_get_identifier (MateMixerDevicePort *port);
+
+const gchar *mate_mixer_device_port_get_name (MateMixerDevicePort *port);
+
+const gchar *mate_mixer_device_port_get_icon (MateMixerDevicePort *port);
+
+guint32 mate_mixer_device_port_get_priority (MateMixerDevicePort *port);
+
+MateMixerDevicePortDirection mate_mixer_device_port_get_direction (MateMixerDevicePort *port);
+
+MateMixerDevicePortStatus mate_mixer_device_port_get_status (MateMixerDevicePort *port);
+
+gint64 mate_mixer_device_port_get_latency_offset (MateMixerDevicePort *port);
+
G_END_DECLS
#endif /* MATEMIXER_PORT_H */
diff --git a/libmatemixer/matemixer-device-profile.c b/libmatemixer/matemixer-device-profile.c
index bfcbe6a..975f5ff 100644
--- a/libmatemixer/matemixer-device-profile.c
+++ b/libmatemixer/matemixer-device-profile.c
@@ -124,21 +124,21 @@ mate_mixer_device_profile_class_init (MateMixerDeviceProfileClass *klass)
object_class->get_property = mate_mixer_device_profile_get_property;
object_class->set_property = mate_mixer_device_profile_set_property;
- properties[PROP_IDENTIFIER] = g_param_spec_string(
+ properties[PROP_IDENTIFIER] = g_param_spec_string (
"identifier",
"Identifier",
"Identifier of the device profile",
NULL,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
- properties[PROP_NAME] = g_param_spec_string(
+ properties[PROP_NAME] = g_param_spec_string (
"name",
"Name",
"Name of the device profile",
NULL,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
- properties[PROP_PRIORITY] = g_param_spec_uint(
+ properties[PROP_PRIORITY] = g_param_spec_uint (
"priority",
"Priority",
"Priority of the device profile",
@@ -163,3 +163,27 @@ mate_mixer_device_profile_new (const gchar *identifier,
"priority", priority,
NULL);
}
+
+const gchar *
+mate_mixer_device_profile_get_identifier (MateMixerDeviceProfile *profile)
+{
+ g_return_val_if_fail (MATE_MIXER_IS_DEVICE_PROFILE (profile), NULL);
+
+ return profile->priv->identifier;
+}
+
+const gchar *
+mate_mixer_device_profile_get_name (MateMixerDeviceProfile *profile)
+{
+ g_return_val_if_fail (MATE_MIXER_IS_DEVICE_PROFILE (profile), NULL);
+
+ return profile->priv->name;
+}
+
+guint32
+mate_mixer_device_profile_get_priority (MateMixerDeviceProfile *profile)
+{
+ g_return_val_if_fail (MATE_MIXER_IS_DEVICE_PROFILE (profile), NULL);
+
+ return profile->priv->priority;
+}
diff --git a/libmatemixer/matemixer-device-profile.h b/libmatemixer/matemixer-device-profile.h
index fa750b8..1ac9020 100644
--- a/libmatemixer/matemixer-device-profile.h
+++ b/libmatemixer/matemixer-device-profile.h
@@ -58,6 +58,10 @@ MateMixerDeviceProfile *mate_mixer_device_profile_new (const gchar *identifier,
const gchar *name,
guint32 priority);
+const gchar *mate_mixer_device_profile_get_identifier (MateMixerDeviceProfile *profile);
+const gchar *mate_mixer_device_profile_get_name (MateMixerDeviceProfile *profile);
+guint32 mate_mixer_device_profile_get_priority (MateMixerDeviceProfile *profile);
+
G_END_DECLS
#endif /* MATEMIXER_PROFILE_H */
diff --git a/libmatemixer/matemixer-device.c b/libmatemixer/matemixer-device.c
index 0c36b0b..8e6a465 100644
--- a/libmatemixer/matemixer-device.c
+++ b/libmatemixer/matemixer-device.c
@@ -62,7 +62,71 @@ mate_mixer_device_default_init (MateMixerDeviceInterface *iface)
const GList *
mate_mixer_device_list_tracks (MateMixerDevice *device)
{
+ MateMixerDeviceInterface *iface;
+
+ g_return_val_if_fail (MATE_MIXER_IS_DEVICE (device), NULL);
+
+ iface = MATE_MIXER_DEVICE_GET_INTERFACE (device);
+ if (iface->list_tracks)
+ return iface->list_tracks (device);
+
+ return NULL;
+}
+
+const GList *
+mate_mixer_device_get_ports (MateMixerDevice *device)
+{
+ MateMixerDeviceInterface *iface;
+
+ g_return_val_if_fail (MATE_MIXER_IS_DEVICE (device), NULL);
+
+ iface = MATE_MIXER_DEVICE_GET_INTERFACE (device);
+ if (iface->get_ports)
+ return iface->get_ports (device);
+
+ return NULL;
+}
+
+const GList *
+mate_mixer_device_get_profiles (MateMixerDevice *device)
+{
+ MateMixerDeviceInterface *iface;
+
+ g_return_val_if_fail (MATE_MIXER_IS_DEVICE (device), NULL);
+
+ iface = MATE_MIXER_DEVICE_GET_INTERFACE (device);
+ if (iface->get_profiles)
+ return iface->get_profiles (device);
+
+ return NULL;
+}
+
+MateMixerDeviceProfile *
+mate_mixer_device_get_active_profile (MateMixerDevice *device)
+{
+ MateMixerDeviceInterface *iface;
+
g_return_val_if_fail (MATE_MIXER_IS_DEVICE (device), NULL);
- return MATE_MIXER_DEVICE_GET_INTERFACE (device)->list_tracks (device);
+ iface = MATE_MIXER_DEVICE_GET_INTERFACE (device);
+ if (iface->get_active_profile)
+ return iface->get_active_profile (device);
+
+ return NULL;
+}
+
+gboolean
+mate_mixer_device_set_active_profile (MateMixerDevice *device,
+ MateMixerDeviceProfile *profile)
+{
+ MateMixerDeviceInterface *iface;
+
+ g_return_val_if_fail (MATE_MIXER_IS_DEVICE (device), NULL);
+ g_return_val_if_fail (MATE_MIXER_IS_DEVICE_PROFILE (profile), NULL);
+
+ iface = MATE_MIXER_DEVICE_GET_INTERFACE (device);
+ if (iface->set_active_profile)
+ return iface->set_active_profile (device, profile);
+
+ return FALSE;
}
diff --git a/libmatemixer/matemixer-device.h b/libmatemixer/matemixer-device.h
index af5a1ce..b601f7d 100644
--- a/libmatemixer/matemixer-device.h
+++ b/libmatemixer/matemixer-device.h
@@ -21,6 +21,9 @@
#include <glib.h>
#include <glib-object.h>
+#include <libmatemixer/matemixer-device-port.h>
+#include <libmatemixer/matemixer-device-profile.h>
+
G_BEGIN_DECLS
#define MATE_MIXER_TYPE_DEVICE \
@@ -40,12 +43,25 @@ struct _MateMixerDeviceInterface
GTypeInterface parent;
const GList *(*list_tracks) (MateMixerDevice *device);
+ const GList *(*get_ports) (MateMixerDevice *device);
+ const GList *(*get_profiles) (MateMixerDevice *device);
+ MateMixerDeviceProfile *(*get_active_profile) (MateMixerDevice *device);
+ gboolean (*set_active_profile) (MateMixerDevice *device, MateMixerDeviceProfile *profile);
};
GType mate_mixer_device_get_type (void) G_GNUC_CONST;
const GList *mate_mixer_device_list_tracks (MateMixerDevice *device);
+const GList *mate_mixer_device_get_ports (MateMixerDevice *device);
+
+const GList *mate_mixer_device_get_profiles (MateMixerDevice *device);
+
+MateMixerDeviceProfile *mate_mixer_device_get_active_profile (MateMixerDevice *device);
+
+gboolean mate_mixer_device_set_active_profile (MateMixerDevice *device,
+ MateMixerDeviceProfile *profile);
+
G_END_DECLS
#endif /* MATEMIXER_DEVICE_H */
diff --git a/libmatemixer/matemixer-enums.h b/libmatemixer/matemixer-enums.h
index 445af7d..50190ce 100644
--- a/libmatemixer/matemixer-enums.h
+++ b/libmatemixer/matemixer-enums.h
@@ -19,6 +19,7 @@
#define MATEMIXER_ENUMS_H
typedef enum {
+ MATE_MIXER_BACKEND_TYPE_UNKNOWN,
MATE_MIXER_BACKEND_TYPE_PULSE,
MATE_MIXER_BACKEND_TYPE_NULL
} MateMixerBackendType;
diff --git a/libmatemixer/matemixer.c b/libmatemixer/matemixer.c
index 6c25cc5..cc4b5f1 100644
--- a/libmatemixer/matemixer.c
+++ b/libmatemixer/matemixer.c
@@ -25,8 +25,8 @@
#include "matemixer-private.h"
#include "matemixer-backend-module.h"
-static gboolean mixer_load_backends (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;
@@ -34,8 +34,37 @@ static gboolean mixer_initialized = FALSE;
gboolean
mate_mixer_init (void)
{
- if (!mixer_initialized)
- mixer_initialized = mixer_load_backends ();
+ if (!mixer_initialized) {
+ mixer_load_modules ();
+
+ if (mixer_modules) {
+ GList *list;
+
+ list = mixer_modules;
+ while (list) {
+ GTypeModule *module = G_TYPE_MODULE (list->data);
+ GList *next = list->next;
+
+ /* Attempt to load the module and remove it from the list
+ * if it isn't usable */
+ if (!g_type_module_use (module)) {
+ g_object_unref (module);
+ mixer_modules = g_list_delete_link (mixer_modules, list);
+ }
+ list = next;
+ }
+
+ if (mixer_modules) {
+ /* Sort the usable modules by the priority */
+ mixer_modules = g_list_sort (
+ mixer_modules,
+ mixer_compare_modules);
+
+ mixer_initialized = TRUE;
+ } else
+ g_critical ("No usable backend modules have been found");
+ }
+ }
return mixer_initialized;
}
@@ -50,24 +79,13 @@ mate_mixer_deinit (void)
list = mixer_modules;
while (list) {
- MateMixerBackendModule *module;
-
- module = MATE_MIXER_BACKEND_MODULE (list->data);
-
- g_type_module_unuse (G_TYPE_MODULE (module));
-
- // XXX it is not possible to unref the module, figure out how
- // to handle repeated initialization
- // g_object_unref (module);
-
+ g_type_module_unuse (G_TYPE_MODULE (list->data));
list = list->next;
}
- g_list_free (mixer_modules);
-
mixer_initialized = FALSE;
}
-/* Internal function: return a *shared* list of loaded backend modules */
+/* Internal function: return a shared list of loaded backend modules */
GList *
mate_mixer_get_modules (void)
{
@@ -78,70 +96,54 @@ mate_mixer_get_modules (void)
gboolean
mate_mixer_is_initialized (void)
{
- gboolean initialized;
-
- G_LOCK_DEFINE_STATIC (mixer_initialized_lock);
-
- G_LOCK (mixer_initialized_lock);
- initialized = mixer_initialized;
- G_UNLOCK (mixer_initialized_lock);
-
- return initialized;
+ return mixer_initialized;
}
-static gboolean
-mixer_load_backends (void)
+static void
+mixer_load_modules (void)
{
- GDir *dir;
- GError *error = NULL;
+ static gboolean loaded = FALSE;
- if (!g_module_supported ()) {
- g_critical ("Unable to load backend modules: GModule not supported");
- return FALSE;
- }
+ if (loaded)
+ return;
- /* Read the directory which contains module libraries and load them */
- dir = g_dir_open (LIBMATEMIXER_BACKEND_DIR, 0, &error);
- if (dir != NULL) {
- const gchar *name;
+ if (g_module_supported ()) {
+ GDir *dir;
+ GError *error = NULL;
- while ((name = g_dir_read_name (dir)) != NULL) {
- gchar *file;
- MateMixerBackendModule *module;
+ /* Read the directory which contains module libraries and create a list
+ * of those that are likely to be usable backend modules */
+ dir = g_dir_open (LIBMATEMIXER_BACKEND_DIR, 0, &error);
+ if (dir != NULL) {
+ const gchar *name;
- if (!g_str_has_suffix (name, "." G_MODULE_SUFFIX))
- continue;
+ while ((name = g_dir_read_name (dir)) != NULL) {
+ gchar *file;
- file = g_build_filename (LIBMATEMIXER_BACKEND_DIR, name, NULL);
- module = mate_mixer_backend_module_new (file);
+ if (!g_str_has_suffix (name, "." G_MODULE_SUFFIX))
+ continue;
- /* Load the backend module and make sure it includes all the
- * required symbols */
- if (g_type_module_use (G_TYPE_MODULE (module)))
- mixer_modules = g_list_prepend (mixer_modules, module);
- else
- g_object_unref (module);
+ file = g_build_filename (LIBMATEMIXER_BACKEND_DIR, name, NULL);
+ mixer_modules = g_list_prepend (
+ mixer_modules,
+ mate_mixer_backend_module_new (file));
- g_free (file);
- }
+ g_free (file);
+ }
- if (mixer_modules == NULL)
- g_critical ("No usable backend modules have been found");
+ if (mixer_modules == NULL)
+ g_critical ("No backend modules have been found");
- g_dir_close (dir);
+ g_dir_close (dir);
+ } else {
+ g_critical ("%s", error->message);
+ g_error_free (error);
+ }
} else {
- g_critical ("%s", error->message);
- g_error_free (error);
- }
-
- if (mixer_modules) {
- mixer_modules = g_list_sort (mixer_modules, mixer_compare_modules);
- return TRUE;
+ g_critical ("Unable to load backend modules: GModule not supported");
}
- /* As we include a "null" backend module to provide no functionality,
- * we fail the initialization in case no module could be loaded */
- return FALSE;
+ loaded = TRUE;
}
/* GCompareFunc function to sort backend modules by the priority, lower