/* * 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 * @title: MateMixer * @include: libmatemixer/matemixer.h */ 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_deinit: * * Deinitializes the library. You should call this function when you are done * using the library. */ void mate_mixer_deinit (void) { GList *list; if (initialized == FALSE) return; list = modules; while (list != NULL) { g_type_module_unuse (G_TYPE_MODULE (list->data)); list = list->next; } initialized = FALSE; } /* Internal function: return a list of loaded backend modules */ const GList * mate_mixer_get_modules (void) { return (const GList *) modules; } 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 */ 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; }