/* * 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 "config.h" #include #include #include #include "matemixer.h" #include "matemixer-private.h" #include "matemixer-backend-module.h" /** * SECTION:matemixer * @short_description: Library initialization and support functions * @include: libmatemixer/matemixer.h * @see_also: #MateMixerContext * * The libmatemixer library must be initialized before it is used by an * application. The initialization function loads dynamic modules which provide * access to sound systems (also called backends) and it only succeeds if there * is at least one usable module present on the target system. * * To connect to a sound system and access the mixer functionality after the * library is initialized, create a #MateMixerContext using the * mate_mixer_context_new() function. */ static void load_modules (void); static gint compare_modules (gconstpointer a, gconstpointer b); static GList *modules = NULL; static gboolean 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 does not * provide support for any sound system backends. */ gboolean mate_mixer_init (void) { if (initialized == TRUE) return TRUE; load_modules (); if (modules != NULL) { GList *list = modules; while (list != NULL) { GTypeModule *module = G_TYPE_MODULE (list->data); GList *next = list->next; /* Load the plugin and remove it from the list if it fails */ if (g_type_module_use (module) == FALSE) { g_object_unref (module); modules = g_list_delete_link (modules, list); } list = next; } if (modules != NULL) { /* Sort the usable modules by priority */ modules = g_list_sort (modules, compare_modules); initialized = TRUE; } else g_critical ("No usable backend modules have been found"); } else g_critical ("No backend modules have been found"); return initialized; } /** * mate_mixer_is_initialized: * * Returns %TRUE if the library has been initialized. * * Returns: %TRUE or %FALSE. */ gboolean mate_mixer_is_initialized (void) { return initialized; } /** * _mate_mixer_list_modules: * * Gets a list of loaded backend modules. * * Returns: a #GList. */ const GList * _mate_mixer_list_modules (void) { return (const GList *) modules; } /** * _mate_mixer_create_channel_mask: * @positions: an array of channel positions * @n: number of channel positions in the array * * Creates a channel mask using the given list of channel positions. * * Returns: a channel mask. */ guint32 _mate_mixer_create_channel_mask (MateMixerChannelPosition *positions, guint n) { guint32 mask = 0; guint i = 0; for (i = 0; i < n; i++) { if (positions[i] > MATE_MIXER_CHANNEL_UNKNOWN && positions[i] < MATE_MIXER_CHANNEL_MAX) mask |= 1 << positions[i]; } return mask; } static void load_modules (void) { static gboolean loaded = FALSE; if (loaded == TRUE) return; if G_LIKELY (g_module_supported () == TRUE) { GDir *dir; GError *error = NULL; /* 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; while ((name = g_dir_read_name (dir)) != NULL) { gchar *file; if (g_str_has_suffix (name, "." G_MODULE_SUFFIX) == FALSE) continue; file = g_build_filename (LIBMATEMIXER_BACKEND_DIR, name, NULL); modules = g_list_prepend (modules, mate_mixer_backend_module_new (file)); g_free (file); } g_dir_close (dir); } else { g_critical ("%s", error->message); g_error_free (error); } } else { g_critical ("Unable to load backend modules: Not supported"); } loaded = TRUE; } /* Backend modules sorting function, higher priority number means higher priority * of the backend module */ static gint compare_modules (gconstpointer a, gconstpointer b) { const MateMixerBackendInfo *info1, *info2; info1 = mate_mixer_backend_module_get_info (MATE_MIXER_BACKEND_MODULE (a)); info2 = mate_mixer_backend_module_get_info (MATE_MIXER_BACKEND_MODULE (b)); return info2->priority - info1->priority; }