/* GSequencer - Advanced GTK Sequencer * Copyright (C) 2005-2020 Joël Krähemann * * This file is part of GSequencer. * * GSequencer is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GSequencer 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GSequencer. If not, see . */ #include #include #include #include #include #include #include #ifndef AGS_W32API #include #endif #include #include void ags_priority_class_init(AgsPriorityClass *priority_class); void ags_priority_init(AgsPriority *priority); void ags_priority_set_property(GObject *gobject, guint prop_id, const GValue *value, GParamSpec *param_spec); void ags_priority_get_property(GObject *gobject, guint prop_id, GValue *value, GParamSpec *param_spec); void ags_priority_dispose(GObject *gobject); void ags_priority_finalize(GObject *gobject); gchar* ags_priority_get_version(AgsPriority *priority); void ags_priority_set_version(AgsPriority *priority, gchar *version); gchar* ags_priority_get_build_id(AgsPriority *priority); void ags_priority_set_build_id(AgsPriority *priority, gchar *build_id); void ags_priority_real_load_defaults(AgsPriority *priority); void ags_priority_real_set_value(AgsPriority *priority, gchar *group, gchar *key, gchar *value); gchar* ags_priority_real_get_value(AgsPriority *priority, gchar *group, gchar *key); /** * SECTION:ags_priority * @short_description: Priority Advanced Gtk+ Sequencer * @title: AgsPriority * @section_id: * @include: ags/object/ags_priority.h * * #AgsPriority provides priorities to Advanced Gtk+ Sequencer. */ enum{ LOAD_DEFAULTS, SET_VALUE, GET_VALUE, LAST_SIGNAL, }; enum{ PROP_0, }; static gpointer ags_priority_parent_class = NULL; static guint priority_signals[LAST_SIGNAL]; AgsPriority *ags_priority = NULL; GType ags_priority_get_type (void) { static volatile gsize g_define_type_id__volatile = 0; if(g_once_init_enter (&g_define_type_id__volatile)){ GType ags_type_priority = 0; static const GTypeInfo ags_priority_info = { sizeof (AgsPriorityClass), NULL, /* base_init */ NULL, /* base_finalize */ (GClassInitFunc) ags_priority_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof (AgsPriority), 0, /* n_preallocs */ (GInstanceInitFunc) ags_priority_init, }; ags_type_priority = g_type_register_static(G_TYPE_OBJECT, "AgsPriority", &ags_priority_info, 0); g_once_init_leave(&g_define_type_id__volatile, ags_type_priority); } return g_define_type_id__volatile; } GType ags_priority_flags_get_type() { static volatile gsize g_flags_type_id__volatile; if(g_once_init_enter (&g_flags_type_id__volatile)){ static const GFlagsValue values[] = { { AGS_PRIORITY_CONNECTED, "AGS_PRIORITY_CONNECTED", "priority-connected" }, { 0, NULL, NULL } }; GType g_flags_type_id = g_flags_register_static(g_intern_static_string("AgsPriorityFlags"), values); g_once_init_leave (&g_flags_type_id__volatile, g_flags_type_id); } return g_flags_type_id__volatile; } void ags_priority_class_init(AgsPriorityClass *priority) { GObjectClass *gobject; GParamSpec *param_spec; ags_priority_parent_class = g_type_class_peek_parent(priority); /* GObjectClass */ gobject = (GObjectClass *) priority; gobject->set_property = ags_priority_set_property; gobject->get_property = ags_priority_get_property; gobject->dispose = ags_priority_dispose; gobject->finalize = ags_priority_finalize; /* properties */ /* AgsPriorityClass */ priority->load_defaults = ags_priority_real_load_defaults; priority->set_value = ags_priority_real_set_value; priority->get_value = ags_priority_real_get_value; /* signals */ /** * AgsPriority::load-defaults: * @priority: the object to resolve * * The ::load-defaults signal notifies about loading defaults * * Since: 3.0.0 */ priority_signals[LOAD_DEFAULTS] = g_signal_new("load-defaults", G_TYPE_FROM_CLASS (priority), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (AgsPriorityClass, load_defaults), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); /** * AgsPriority::set-value: * @priority: the object to resolve * @group: the group to apply to * @key: the key to set * @value: the value to apply * * The ::set-value signal notifies about value been setting. * * Since: 3.0.0 */ priority_signals[SET_VALUE] = g_signal_new("set-value", G_TYPE_FROM_CLASS (priority), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (AgsPriorityClass, set_value), NULL, NULL, ags_cclosure_marshal_VOID__STRING_STRING_STRING, G_TYPE_NONE, 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); /** * AgsPriority::get-value: * @priority: the object to resolve * @group: the group to retrieve from * @key: the key to get * * The ::get-value signal notifies about value been getting. * * Returns: the value * * Since: 3.0.0 */ priority_signals[GET_VALUE] = g_signal_new("get-value", G_TYPE_FROM_CLASS (priority), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (AgsPriorityClass, get_value), NULL, NULL, ags_cclosure_marshal_STRING__STRING_STRING, G_TYPE_STRING, 2, G_TYPE_STRING, G_TYPE_STRING); } void ags_priority_init(AgsPriority *priority) { priority->flags = 0; g_rec_mutex_init(&(priority->obj_mutex)); /* version and build id */ priority->version = g_strdup(AGS_PRIORITY_DEFAULT_VERSION); priority->build_id = g_strdup(AGS_PRIORITY_DEFAULT_BUILD_ID); priority->key_file = g_key_file_new(); g_key_file_ref(priority->key_file); } void ags_priority_set_property(GObject *gobject, guint prop_id, const GValue *value, GParamSpec *param_spec) { AgsPriority *priority; GRecMutex *priority_mutex; priority = AGS_PRIORITY(gobject); /* get priority mutex */ priority_mutex = AGS_PRIORITY_GET_OBJ_MUTEX(priority); switch(prop_id){ default: G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec); break; } } void ags_priority_get_property(GObject *gobject, guint prop_id, GValue *value, GParamSpec *param_spec) { AgsPriority *priority; GRecMutex *priority_mutex; priority = AGS_PRIORITY(gobject); /* get priority mutex */ priority_mutex = AGS_PRIORITY_GET_OBJ_MUTEX(priority); switch(prop_id){ default: G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec); break; } } void ags_priority_dispose(GObject *gobject) { AgsPriority *priority; priority = (AgsPriority *) gobject; /* call parent */ G_OBJECT_CLASS(ags_priority_parent_class)->dispose(gobject); } void ags_priority_finalize(GObject *gobject) { AgsPriority *priority; priority = (AgsPriority *) gobject; /* key file */ if(priority->key_file != NULL){ g_key_file_unref(priority->key_file); } /* global variable */ if(ags_priority == priority){ ags_priority = NULL; } /* call parent */ G_OBJECT_CLASS(ags_priority_parent_class)->finalize(gobject); } gchar* ags_priority_get_version(AgsPriority *priority) { gchar *version; GRecMutex *priority_mutex; if(!AGS_IS_PRIORITY(priority)){ return(NULL); } priority_mutex = AGS_PRIORITY_GET_OBJ_MUTEX(priority); /* get version */ g_rec_mutex_lock(priority_mutex); version = priority->version; g_rec_mutex_unlock(priority_mutex); return(version); } void ags_priority_set_version(AgsPriority *priority, gchar *version) { GRecMutex *priority_mutex; if(!AGS_IS_PRIORITY(priority)){ return; } priority_mutex = AGS_PRIORITY_GET_OBJ_MUTEX(priority); /* set version */ g_rec_mutex_lock(priority_mutex); priority->version = g_strdup(version); g_rec_mutex_unlock(priority_mutex); } gchar* ags_priority_get_build_id(AgsPriority *priority) { gchar *build_id; GRecMutex *priority_mutex; if(!AGS_IS_PRIORITY(priority)){ return(NULL); } priority_mutex = AGS_PRIORITY_GET_OBJ_MUTEX(priority); /* get build id */ g_rec_mutex_lock(priority_mutex); build_id = priority->build_id; g_rec_mutex_unlock(priority_mutex); return(build_id); } void ags_priority_set_build_id(AgsPriority *priority, gchar *build_id) { GRecMutex *priority_mutex; if(!AGS_IS_PRIORITY(priority)){ return; } priority_mutex = AGS_PRIORITY_GET_OBJ_MUTEX(priority); /* set version */ g_rec_mutex_lock(priority_mutex); priority->build_id = g_strdup(build_id); g_rec_mutex_unlock(priority_mutex); } void ags_priority_real_load_defaults(AgsPriority *priority) { GRecMutex *priority_mutex; priority_mutex = AGS_PRIORITY_GET_OBJ_MUTEX(priority); /* load defaults */ g_rec_mutex_lock(priority_mutex); ags_priority_set_value(priority, AGS_PRIORITY_RT_THREAD, AGS_PRIORITY_KEY_LIBAGS, "0"); // 45 ags_priority_set_value(priority, AGS_PRIORITY_RT_THREAD, AGS_PRIORITY_KEY_SERVER_MAIN_LOOP, "0"); // 15 ags_priority_set_value(priority, AGS_PRIORITY_RT_THREAD, AGS_PRIORITY_KEY_AUDIO_MAIN_LOOP, "0"); // 15 ags_priority_set_value(priority, AGS_PRIORITY_RT_THREAD, AGS_PRIORITY_KEY_AUDIO, "0"); // 45 ags_priority_set_value(priority, AGS_PRIORITY_RT_THREAD, AGS_PRIORITY_KEY_OSC_SERVER_MAIN_LOOP, "0"); // 15 ags_priority_set_value(priority, AGS_PRIORITY_RT_THREAD, AGS_PRIORITY_KEY_GUI_MAIN_LOOP, "0"); // 15 g_rec_mutex_unlock(priority_mutex); } /** * ags_priority_load_defaults: * @priority: the #AgsPriority * * Load priorities from default values. * * Since: 3.0.0 */ void ags_priority_load_defaults(AgsPriority *priority) { g_return_if_fail(AGS_IS_PRIORITY(priority)); g_object_ref(G_OBJECT(priority)); g_signal_emit(G_OBJECT(priority), priority_signals[LOAD_DEFAULTS], 0); g_object_unref(G_OBJECT(priority)); } /** * ags_priority_load_from_file: * @priority: the #AgsPriority * @filename: the priorityuration file * * Load priorities from @filename. * * Since: 3.0.0 */ void ags_priority_load_from_file(AgsPriority *priority, gchar *filename) { GFile *file; GRecMutex *priority_mutex; if(!AGS_IS_PRIORITY(priority)){ return; } priority_mutex = AGS_PRIORITY_GET_OBJ_MUTEX(priority); file = g_file_new_for_path(filename); g_message("loading priorities for: %s", filename); if(!g_file_query_exists(file, NULL)){ ags_priority_load_defaults(priority); }else{ GKeyFile *key_file; gchar **groups, **groups_start; gchar **keys, **keys_start; gchar *value; GError *error; g_rec_mutex_lock(priority_mutex); error = NULL; key_file = g_key_file_new(); g_key_file_load_from_file(key_file, filename, G_KEY_FILE_NONE, &error); if(error != NULL){ g_warning("%s", error->message); g_error_free(error); } groups = groups_start = g_key_file_get_groups(key_file, NULL); while(*groups != NULL){ keys = keys_start = g_key_file_get_keys(key_file, *groups, NULL, NULL); while(*keys != NULL){ value = g_key_file_get_value(key_file, *groups, *keys, NULL); ags_priority_set_value(priority, *groups, *keys, value); keys++; } g_strfreev(keys_start); groups++; } g_strfreev(groups_start); g_key_file_unref(key_file); g_rec_mutex_unlock(priority_mutex); } g_object_unref(file); } void ags_priority_real_set_value(AgsPriority *priority, gchar *group, gchar *key, gchar *value) { GRecMutex *priority_mutex; priority_mutex = AGS_PRIORITY_GET_OBJ_MUTEX(priority); /* set value */ g_rec_mutex_lock(priority_mutex); g_key_file_set_value(priority->key_file, group, key, value); g_rec_mutex_unlock(priority_mutex); } /** * ags_priority_set_value: * @priority: the #AgsPriority * @group: the priority group identifier * @key: the key of the property * @value: the value to set * * Set priority by @group and @key, applying @value. * * Since: 3.0.0 */ void ags_priority_set_value(AgsPriority *priority, gchar *group, gchar *key, gchar *value) { g_return_if_fail(AGS_IS_PRIORITY(priority)); g_object_ref(G_OBJECT(priority)); g_signal_emit(G_OBJECT(priority), priority_signals[SET_VALUE], 0, group, key, value); g_object_unref(G_OBJECT(priority)); } gchar* ags_priority_real_get_value(AgsPriority *priority, gchar *group, gchar *key) { gchar *str; GError *error; GRecMutex *priority_mutex; priority_mutex = AGS_PRIORITY_GET_OBJ_MUTEX(priority); /* get value */ g_rec_mutex_lock(priority_mutex); error = NULL; str = g_key_file_get_value(priority->key_file, group, key, &error); if(error != NULL){ // g_warning("%s", error->message); g_error_free(error); } g_rec_mutex_unlock(priority_mutex); return(str); } /** * ags_priority_get_value: * @priority: the #AgsPriority * @group: the priority group identifier * @key: the key of the property * * Retrieve priority by @group and @key. * * Returns: (transfer full): the property's value * * Since: 3.0.0 */ gchar* ags_priority_get_value(AgsPriority *priority, gchar *group, gchar *key) { gchar *value; g_return_val_if_fail(AGS_IS_PRIORITY(priority), NULL); g_object_ref(G_OBJECT(priority)); g_signal_emit(G_OBJECT(priority), priority_signals[GET_VALUE], 0, group, key, &value); g_object_unref(G_OBJECT(priority)); return(value); } /** * ags_priority_get_instance: * * Get priority instance. * * Returns: (transfer none): the priority instance * * Since: 3.0.0 */ AgsPriority* ags_priority_get_instance() { static GMutex mutex; g_mutex_lock(&mutex); if(ags_priority == NULL){ ags_priority = ags_priority_new(NULL); } g_mutex_unlock(&mutex); return(ags_priority); } /** * ags_priority_new: * * Create a new instance of #AgsPriority. * * Returns: the new #AgsPriority. * * Since: 3.0.0 */ AgsPriority* ags_priority_new() { AgsPriority *priority; priority = (AgsPriority *) g_object_new(AGS_TYPE_PRIORITY, NULL); return(priority); }