/* * Copyright (c) 2011- Osmo Antero. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 3 of the License (GPL3), or 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 Library General Public License 3 for more details. * * You should have received a copy of the GNU Library General Public * License 3 along with this program; if not, see /usr/share/common-licenses/GPL file * or . */ #include #include #include "dconf.h" #include "support.h" #include "utility.h" #include "log.h" #include // This module writes and reads values from/to GNOME's configuration registry (GSettings). // DConf is most likely the backend. // You can check these values in dconf-editor. // Start dconf-editor and browse to /apps/audio-recorder/. // Notice: // All valid configuration keys must be defined in the schema file "org.gnome.audio-recorder.gschema.xml". // It's in the data/ folder. // You must also compile and install this file to /usr/share/glib-2.0/schemas/ directory. // // 0) Test the schema file first. I assume here that the schema is in the current (.) directory. // $ glib-compile-schemas --dry-run . // // 1) Copy the schema file to /usr/share/glib-2.0/schemas/. // $ sudo cp org.gnome.audio-recorder.gschema.xml /usr/share/glib-2.0/schemas/ // // 2) Then re-compile all schemas. // $ sudo glib-compile-schemas /usr/share/glib-2.0/schemas/ // // The Makefile.am in the data/ folder should do this installation automatically. // // You can also study various schema values with gsettings tool. // $ gsettings // // This command will list all keys and values for org.gnome.audio-recorder // $ gsettings list-recursively org.gnome.audio-recorder // ----------------------------------------------------------------- // // The main schema name is "org.gnome.audio-recorder", and its path is /apps/audio-recorder/. // Notice that there are also child schemas (sub paths) for // track/ (/apps/audio-recorder/track/). // skype/ (/apps/audio-recorder/skype/). // players/ (/apps/audio-recorder/players/). // The main configuration schema for this application #define APPLICATION_SETTINGS_SCHEMA "org.gnome.audio-recorder" static GSettings *conf_get_base_settings(); void conf_flush_settings() { // Flush and write settings cache to disk g_settings_sync(); GSettings *settings = conf_get_base_settings(); if (!settings) { return; } guint i = 0; while (i++ < 4 && g_settings_get_has_unapplied(settings)) { g_settings_sync(); g_usleep(G_USEC_PER_SEC * 0.1); } } static gboolean conf_is_valid_key(GSettings *settings, gchar *key) { // Check if the key is valid key within settings if (!G_IS_SETTINGS(settings)) { return FALSE; } // Get list of keys gchar **keys = NULL; // Check: // $ pkg-config --modversion glib-2.0 // #if GLIB_CHECK_VERSION(2, 45, 6) GSettingsSchema *schema = NULL; g_object_get(settings, "settings-schema", &schema, NULL); keys = g_settings_schema_list_keys(schema); #else keys = g_settings_list_keys(settings); #endif gint i = 0; gboolean found = FALSE; while (keys && keys[i]) { //Debug: //GVariant *value = NULL; //gchar *str = NULL; //value = g_settings_get_value (settings, keys[i]); //str = g_variant_print(value, TRUE); //g_print ("%s %s %s\n", g_settings_schema_get_id (schema), keys[i], str); //g_variant_unref(value); //g_free (str); if (!g_strcmp0(key, keys[i])) { found = TRUE; break; } i++; } g_strfreev(keys); #if GLIB_CHECK_VERSION(2, 45, 6) g_settings_schema_unref(schema); #endif return found; } #if 0 void conf_list_keys(GSettings *settings) { // List keys for the given settings (and schema) gchar *str = NULL; g_object_get(settings, "schema", &str, NULL); if (!str) { g_print("Bad schema:%s\n", str); } gchar **keys = NULL; gint i = 0; keys = g_settings_list_keys(settings); while (keys && keys[i]) { g_print("List key for schema:%s key:%s\n", str, keys[i]); i++; } g_strfreev(keys); g_free(str); } void conf_list_children(GSettings *settings) { // List children of the given settings (and schema) gchar *str = NULL; g_object_get(settings, "schema", &str, NULL); if (!str) { g_print("Bad schema:%s\n", str); } gchar **children = NULL; gint i = 0; children = g_settings_list_children(settings); while (children && children[i]) { g_print("List child for schema:%s child:%s\n", str, children[i]); i++; } g_strfreev(children); g_free(str); } #endif static void conf_get_child_path(gchar *key, gchar **child_path, gchar **child_key) { // Split the key to child_path and child_key. // Eg. "track/track-title" has child_path "track/" and child_key "track-title". *child_path = NULL; *child_key = NULL; static gchar buf[MAX_PATH_LEN]; // Find "/" in key gchar *p = g_strrstr(key, "/"); if (p) { memset(buf, '\0', MAX_PATH_LEN); g_utf8_strncpy(buf, key, p - key); *child_path = g_strdup(buf); *child_key = g_strdup(p+1); } } static GSettings *conf_get_base_settings() { // Return GSettings (base) object. This points to /apps/audio-recorder/. #if 0 // This code failed on some Linux-distributions. Reverting to g_settings_new(). // Ref: https://developer.gnome.org/gio/2.32/gio-GSettingsSchema-GSettingsSchemaSource.html GSettingsSchemaSource *source = g_settings_schema_source_get_default(); GSettingsSchema *schema = g_settings_schema_source_lookup(source, APPLICATION_SETTINGS_SCHEMA, TRUE); // Check if schema has been installed if (!schema) { g_printerr("Error: Cannot find settings for %s in GNOME's registry. " "Please run \"make install\" as sudo or root user.\n", "/apps/audio-recorder/"); } GSettings *settings = g_settings_new_full(schema, NULL, NULL); g_settings_schema_unref(schema); #endif GSettings *settings = g_settings_new(APPLICATION_SETTINGS_SCHEMA); if (!G_IS_SETTINGS(settings)) { g_printerr("Error: Cannot find settings for %s in GNOME's registry. " "Please run \"make install\" as sudo or root user.\n", "/apps/audio-recorder/"); } return settings; } static GSettings *conf_get_settings_for_key(gchar *key, gchar **child_path, gchar **child_key) { // Return GSettings object for the given key *child_path = NULL; *child_key = NULL; // The key may contain a child path (it has a "/" in it). // For example the key "track/track-title" contains child_path ("track/") and child_key "track-title". // Take possible child_path and child_key. conf_get_child_path(key, child_path, child_key); // The main GSettings object GSettings *settings = conf_get_base_settings(); // Points to /apps/audio-recorder/. if (*child_path) { // Get GSettings object for child_path GSettings *child_settings = g_settings_get_child(settings, *child_path); if (G_IS_SETTINGS(child_settings)) { g_object_unref(settings); settings = child_settings; // Points to /apps/audio-recorder/some child_path/. } } return settings; } void conf_get_boolean_value(gchar *key, gboolean *value) { gchar *child_path = NULL; gchar *child_key = NULL; // Get GSettings object. Handle also child_path and child_key (like "track/track-title") GSettings *settings = conf_get_settings_for_key(key, &child_path, &child_key); gchar *k = NULL; if (child_key) k = child_key; // settings object points to child_path (/apps/audio-recorder/some child_path/). else k = key; // settings object points to main path (/apps/audio-recorder/). // Check if the key is valid. Avoid crash. if (!conf_is_valid_key(settings, k)) { LOG_ERROR("Cannot find configuration key \"%s\". Run \"make install\" as sudo or root user.\n", key); goto LBL_1; } // Read value *value = g_settings_get_boolean(settings, k); LBL_1: // Free values g_free(child_path); g_free(child_key); g_object_unref(settings); } void conf_get_int_value(gchar *key, gint *value) { gchar *child_path = NULL; gchar *child_key = NULL; // Get GSettings object. Handle also child_path and child_key (like "track/track-title") GSettings *settings = conf_get_settings_for_key(key, &child_path, &child_key); gchar *k = NULL; if (child_key) k = child_key; // settings object points to child_path (/apps/audio-recorder/some child_path/). else k = key; // settings object points to main path (/apps/audio-recorder/). // Check if the key is valid. Avoid crash. if (!conf_is_valid_key(settings, k)) { LOG_ERROR("Cannot find configuration key \"%s\". Run \"make install\" as sudo or root user.\n", key); goto LBL_1; } // Read value *value = g_settings_get_int(settings, k); LBL_1: // Free values g_free(child_path); g_free(child_key); g_object_unref(settings); } void conf_get_string_value(gchar *key, gchar **value) { gchar *child_path = NULL; gchar *child_key = NULL; // Get GSettings object. Handle also child_path and child_key (like "track/track-title") GSettings *settings = conf_get_settings_for_key(key, &child_path, &child_key); gchar *k = NULL; if (child_key) k = child_key; // settings object points to child_path (/apps/audio-recorder/some child_path/). else k = key; // settings object points to main path (/apps/audio-recorder/). // Check if the key is valid. Avoid crash. if (!conf_is_valid_key(settings, k)) { LOG_ERROR("Cannot find configuration key \"%s\". Run \"make install\" as sudo or root user.\n", key); goto LBL_1; } // Read value *value = g_settings_get_string(settings, k); LBL_1: // Free values g_free(child_path); g_free(child_key); g_object_unref(settings); // The caller should g_free() the value } void conf_get_string_list(gchar *key, GList **list) { gchar *child_path = NULL; gchar *child_key = NULL; // Get GSettings object. Handle also child_path and child_key (like "track/track-title") GSettings *settings = conf_get_settings_for_key(key, &child_path, &child_key); gchar *k = NULL; if (child_key) k = child_key; // settings object points to child_path (/apps/audio-recorder/some child_path/). else k = key; // settings object points to main path (/apps/audio-recorder/). // Check if the key is valid. Avoid crash. if (!conf_is_valid_key(settings, k)) { LOG_ERROR("Cannot find configuration key \"%s\". Run \"make install\" as sudo or root user.\n", key); goto LBL_1; } // Read string list gchar **argv = g_settings_get_strv(settings, k); // From gchar *argv[] to GList *list = NULL; guint i = 0; while (argv && argv[i]) { *list = g_list_append(*list, g_strdup(argv[i])); i++; } // Free argv[] g_strfreev(argv); LBL_1: // Free values g_free(child_path); g_free(child_key); g_object_unref(settings); // The caller should free the list } void conf_get_variant_value(gchar *key, GVariant **var) { gchar *child_path = NULL; gchar *child_key = NULL; *var = NULL; // Get GSettings object. Handle also child_path and child_key (like "track/track-title") GSettings *settings = conf_get_settings_for_key(key, &child_path, &child_key); gchar *k = NULL; if (child_key) k = child_key; // settings object points to child_path (/apps/audio-recorder/some child_path/). else k = key; // settings object points to main path (/apps/audio-recorder/). // Check if the key is valid. Avoid crash. if (!conf_is_valid_key(settings, k)) { LOG_ERROR("Cannot find configuration key \"%s\". Run \"make install\" as sudo or root user.\n", key); goto LBL_1; } *var = g_settings_get_value(settings, k); LBL_1: // Free values g_free(child_path); g_free(child_key); g_object_unref(settings); // The caller should free the value } void conf_save_boolean_value(gchar *key, gboolean value) { gchar *child_path = NULL; gchar *child_key = NULL; // Get GSettings object. Handle also child_path and child_key (like "track/track-title") GSettings *settings = conf_get_settings_for_key(key, &child_path, &child_key); gchar *k = NULL; if (child_key) k = child_key; // settings object points to child_path (/apps/audio-recorder/some child_path/). else k = key; // settings object points to main path (/apps/audio-recorder/). // Check if the key is valid. Avoid crash. if (!conf_is_valid_key(settings, k)) { LOG_ERROR("Cannot find configuration key \"%s\". Run \"make install\" as sudo or root user.\n", key); goto LBL_1; } // Save value if (!g_settings_set_boolean(settings, k, value)) { LOG_ERROR("Cannot save configuration key \"%s\" (%s).\n", key, (value ? "true" : "false")); } LBL_1: // Free values g_free(child_path); g_free(child_key); g_object_unref(settings); } void conf_save_int_value(gchar *key, gint value) { gchar *child_path = NULL; gchar *child_key = NULL; // Get GSettings object. Handle also child_path and child_key (like "track/track-title") GSettings *settings = conf_get_settings_for_key(key, &child_path, &child_key); gchar *k = NULL; if (child_key) k = child_key; // settings object points to child_path (/apps/audio-recorder/some child_path/). else k = key; // settings object points to main path (/apps/audio-recorder/). // Check if the key is valid. Avoid crash. if (!conf_is_valid_key(settings, k)) { LOG_ERROR("Cannot find configuration key \"%s\". Run \"make install\" as sudo or root user.\n", key); goto LBL_1; } // Save value if (!g_settings_set_int(settings, k, value)) { LOG_ERROR("Cannot save configuration key \"%s\" (%d).\n", key, value); } LBL_1: // Free values g_free(child_path); g_free(child_key); g_object_unref(settings); } void conf_save_string_value(gchar *key, gchar *value) { gchar *child_path = NULL; gchar *child_key = NULL; // Get GSettings object. Handle also child_path and child_key (like "track/track-title") GSettings *settings = conf_get_settings_for_key(key, &child_path, &child_key); gchar *k = NULL; if (child_key) k = child_key; // settings object points to child_path (/apps/audio-recorder/some child_path/). else k = key; // settings object points to main path (/apps/audio-recorder/). // Check if the key is valid. Avoid crash. if (!conf_is_valid_key(settings, k)) { LOG_ERROR("Cannot find configuration key \"%s\". Run \"make install\" as sudo or root user.\n", key); goto LBL_1; } // Save value if (!g_settings_set_string(settings, k, value)) { LOG_ERROR("Cannot save configuration key \"%s\" (%s).\n", key, value); } g_settings_apply(settings); LBL_1: // Free values g_free(child_path); g_free(child_key); g_object_unref(settings); } void conf_save_string_list(gchar *key, GList *list) { gchar *child_path = NULL; gchar *child_key = NULL; // Get GSettings object. Handle also child_path and child_key (like "track/track-title") GSettings *settings = conf_get_settings_for_key(key, &child_path, &child_key); gchar *k = NULL; if (child_key) k = child_key; // settings object points to child_path (/apps/audio-recorder/some child_path/). else k = key; // settings object points to main path (/apps/audio-recorder/). // Check if the key is valid. Avoid crash. if (!conf_is_valid_key(settings, k)) { LOG_ERROR("Cannot find configuration key \"%s\". Run \"make install\" as sudo or root user.\n", key); goto LBL_1; } // From GList to gchar *argv[]. guint len = g_list_length(list); // Allocate argv[] gchar **argv = g_new(gchar*, len + 1 /*+1 for NULL*/); guint i = 0; GList *n = g_list_first(list); while (n) { argv[i++] = g_strdup(n->data); n = g_list_next(n); } argv[len] = NULL; // Save string list if (!g_settings_set_strv(settings, k, (const gchar* const*)argv)) { LOG_ERROR("Cannot save configuration key \"%s\" (value is a string list).\n", key); } // Free argv[] g_strfreev((gchar **)argv); LBL_1: // Free values g_free(child_path); g_free(child_key); g_object_unref(settings); } void conf_save_variant(gchar *key, GVariant *var) { gchar *child_path = NULL; gchar *child_key = NULL; // Get GSettings object. Handle also child_path and child_key (like "track/track-title") GSettings *settings = conf_get_settings_for_key(key, &child_path, &child_key); gchar *k = NULL; if (child_key) k = child_key; // settings object points to child_path (/apps/audio-recorder/some child_path/). else k = key; // settings object points to main path (/apps/audio-recorder/). // Check if the key is valid. Avoid crash. if (!conf_is_valid_key(settings, k)) { LOG_ERROR("Cannot find configuration key \"%s\". Run \"make install\" as sudo or root user.\n", key); goto LBL_1; } g_settings_set_value(settings, k, var); LBL_1: // Free values g_free(child_path); g_free(child_key); g_object_unref(settings); }