Audacious
$Id:Doxyfile42802007-03-2104:39:00Znenolod$
|
00001 /* 00002 * config.c 00003 * Copyright 2011 John Lindgren 00004 * 00005 * This file is part of Audacious. 00006 * 00007 * Audacious is free software: you can redistribute it and/or modify it under 00008 * the terms of the GNU General Public License as published by the Free Software 00009 * Foundation, version 2 or version 3 of the License. 00010 * 00011 * Audacious is distributed in the hope that it will be useful, but WITHOUT ANY 00012 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 00013 * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License along with 00016 * Audacious. If not, see <http://www.gnu.org/licenses/>. 00017 * 00018 * The Audacious team does not consider modular code linking to Audacious or 00019 * using our public API to be a derived work. 00020 */ 00021 00022 #include <glib.h> 00023 #include <pthread.h> 00024 #include <stdio.h> 00025 #include <string.h> 00026 00027 #include <libaudcore/audstrings.h> 00028 #include <libaudcore/hook.h> 00029 00030 #include "main.h" 00031 #include "misc.h" 00032 00033 #define DEFAULT_SECTION "audacious" 00034 00035 static const char * const core_defaults[] = { 00036 00037 /* general */ 00038 "advance_on_delete", "FALSE", 00039 "clear_playlist", "TRUE", 00040 "open_to_temporary", "TRUE", 00041 "resume_playback_on_startup", "FALSE", 00042 00043 /* equalizer */ 00044 "eqpreset_default_file", "", 00045 "eqpreset_extension", "", 00046 "equalizer_active", "FALSE", 00047 "equalizer_autoload", "FALSE", 00048 "equalizer_bands", "0,0,0,0,0,0,0,0,0,0", 00049 "equalizer_preamp", "0", 00050 00051 /* info popup / info window */ 00052 "cover_name_exclude", "back", 00053 "cover_name_include", "album,cover,front,folder", 00054 "filepopup_delay", "5", 00055 "filepopup_showprogressbar", "TRUE", 00056 "recurse_for_cover", "FALSE", 00057 "recurse_for_cover_depth", "0", 00058 "show_filepopup_for_tuple", "TRUE", 00059 "use_file_cover", "FALSE", 00060 00061 /* network */ 00062 "use_proxy", "FALSE", 00063 "use_proxy_auth", "FALSE", 00064 00065 /* output */ 00066 "default_gain", "0", 00067 "enable_replay_gain", "TRUE", 00068 "enable_clipping_prevention", "TRUE", 00069 "output_bit_depth", "16", 00070 "output_buffer_size", "500", 00071 "replay_gain_album", "FALSE", 00072 "replay_gain_preamp", "0", 00073 "software_volume_control", "FALSE", 00074 "sw_volume_left", "100", 00075 "sw_volume_right", "100", 00076 00077 /* playback */ 00078 "no_playlist_advance", "FALSE", 00079 "repeat", "FALSE", 00080 "shuffle", "FALSE", 00081 "stop_after_current_song", "FALSE", 00082 00083 /* playlist */ 00084 "generic_title_format", "${?artist:${artist} - }${?album:${album} - }${title}", 00085 "leading_zero", "FALSE", 00086 "metadata_on_play", "FALSE", 00087 "show_numbers_in_pl", "FALSE", 00088 00089 NULL}; 00090 00091 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 00092 static GHashTable * defaults; 00093 static GKeyFile * keyfile; 00094 static bool_t modified; 00095 00096 /* str_unref() may be a macro */ 00097 static void str_unref_cb (void * str) 00098 { 00099 str_unref (str); 00100 } 00101 00102 void config_load (void) 00103 { 00104 g_return_if_fail (! defaults && ! keyfile); 00105 pthread_mutex_lock (& mutex); 00106 00107 defaults = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, 00108 (GDestroyNotify) g_hash_table_destroy); 00109 keyfile = g_key_file_new (); 00110 00111 char * path = g_strdup_printf ("%s/config", get_path (AUD_PATH_USER_DIR)); 00112 if (g_file_test (path, G_FILE_TEST_EXISTS)) 00113 { 00114 GError * error = NULL; 00115 if (! g_key_file_load_from_file (keyfile, path, 0, & error)) 00116 { 00117 fprintf (stderr, "Error loading config: %s\n", error->message); 00118 g_error_free (error); 00119 } 00120 } 00121 g_free (path); 00122 00123 modified = FALSE; 00124 pthread_mutex_unlock (& mutex); 00125 00126 config_set_defaults (NULL, core_defaults); 00127 } 00128 00129 void config_save (void) 00130 { 00131 g_return_if_fail (defaults && keyfile); 00132 pthread_mutex_lock (& mutex); 00133 00134 if (! modified) 00135 { 00136 pthread_mutex_unlock (& mutex); 00137 return; 00138 } 00139 00140 char * path = g_strdup_printf ("%s/config", get_path (AUD_PATH_USER_DIR)); 00141 char * data = g_key_file_to_data (keyfile, NULL, NULL); 00142 00143 GError * error = NULL; 00144 if (! g_file_set_contents (path, data, -1, & error)) 00145 { 00146 fprintf (stderr, "Error saving config: %s\n", error->message); 00147 g_error_free (error); 00148 } 00149 00150 g_free (data); 00151 g_free (path); 00152 00153 modified = FALSE; 00154 pthread_mutex_unlock (& mutex); 00155 } 00156 00157 void config_cleanup (void) 00158 { 00159 g_return_if_fail (defaults && keyfile); 00160 pthread_mutex_lock (& mutex); 00161 00162 g_key_file_free (keyfile); 00163 keyfile = NULL; 00164 g_hash_table_destroy (defaults); 00165 defaults = NULL; 00166 00167 pthread_mutex_unlock (& mutex); 00168 } 00169 00170 void config_clear_section (const char * section) 00171 { 00172 g_return_if_fail (defaults && keyfile); 00173 pthread_mutex_lock (& mutex); 00174 00175 if (! section) 00176 section = DEFAULT_SECTION; 00177 00178 if (g_key_file_has_group (keyfile, section)) 00179 { 00180 g_key_file_remove_group (keyfile, section, NULL); 00181 modified = TRUE; 00182 } 00183 00184 pthread_mutex_unlock (& mutex); 00185 } 00186 00187 void config_set_defaults (const char * section, const char * const * entries) 00188 { 00189 g_return_if_fail (defaults && keyfile); 00190 pthread_mutex_lock (& mutex); 00191 00192 if (! section) 00193 section = DEFAULT_SECTION; 00194 00195 GHashTable * table = g_hash_table_lookup (defaults, section); 00196 if (! table) 00197 { 00198 table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, str_unref_cb); 00199 g_hash_table_replace (defaults, g_strdup (section), table); 00200 } 00201 00202 while (1) 00203 { 00204 const char * name = * entries ++; 00205 const char * value = * entries ++; 00206 if (! name || ! value) 00207 break; 00208 00209 g_hash_table_replace (table, g_strdup (name), str_get (value)); 00210 } 00211 00212 pthread_mutex_unlock (& mutex); 00213 } 00214 00215 static const char * get_default (const char * section, const char * name) 00216 { 00217 GHashTable * table = g_hash_table_lookup (defaults, section); 00218 const char * def = table ? g_hash_table_lookup (table, name) : NULL; 00219 return def ? def : ""; 00220 } 00221 00222 void set_string (const char * section, const char * name, const char * value) 00223 { 00224 g_return_if_fail (defaults && keyfile); 00225 g_return_if_fail (name && value); 00226 pthread_mutex_lock (& mutex); 00227 00228 if (! section) 00229 section = DEFAULT_SECTION; 00230 00231 const char * def = get_default (section, name); 00232 bool_t changed = FALSE; 00233 00234 if (! strcmp (value, def)) 00235 { 00236 if (g_key_file_has_key (keyfile, section, name, NULL)) 00237 { 00238 g_key_file_remove_key (keyfile, section, name, NULL); 00239 changed = TRUE; 00240 } 00241 } 00242 else 00243 { 00244 char * old = g_key_file_has_key (keyfile, section, name, NULL) ? 00245 g_key_file_get_value (keyfile, section, name, NULL) : NULL; 00246 00247 if (! old || strcmp (value, old)) 00248 { 00249 g_key_file_set_value (keyfile, section, name, value); 00250 changed = TRUE; 00251 } 00252 00253 g_free (old); 00254 } 00255 00256 if (changed) 00257 { 00258 modified = TRUE; 00259 00260 if (! strcmp (section, DEFAULT_SECTION)) 00261 { 00262 char * event = g_strdup_printf ("set %s", name); 00263 event_queue (event, NULL); 00264 g_free (event); 00265 } 00266 } 00267 00268 pthread_mutex_unlock (& mutex); 00269 } 00270 00271 char * get_string (const char * section, const char * name) 00272 { 00273 g_return_val_if_fail (defaults && keyfile, g_strdup ("")); 00274 g_return_val_if_fail (name, g_strdup ("")); 00275 pthread_mutex_lock (& mutex); 00276 00277 if (! section) 00278 section = DEFAULT_SECTION; 00279 00280 char * value = g_key_file_has_key (keyfile, section, name, NULL) ? 00281 g_key_file_get_value (keyfile, section, name, NULL) : NULL; 00282 00283 if (! value) 00284 value = g_strdup (get_default (section, name)); 00285 00286 pthread_mutex_unlock (& mutex); 00287 return value; 00288 } 00289 00290 void set_bool (const char * section, const char * name, bool_t value) 00291 { 00292 set_string (section, name, value ? "TRUE" : "FALSE"); 00293 } 00294 00295 bool_t get_bool (const char * section, const char * name) 00296 { 00297 char * string = get_string (section, name); 00298 bool_t value = ! strcmp (string, "TRUE"); 00299 g_free (string); 00300 return value; 00301 } 00302 00303 void set_int (const char * section, const char * name, int value) 00304 { 00305 char * string = int_to_string (value); 00306 g_return_if_fail (string); 00307 set_string (section, name, string); 00308 g_free (string); 00309 } 00310 00311 int get_int (const char * section, const char * name) 00312 { 00313 int value = 0; 00314 char * string = get_string (section, name); 00315 string_to_int (string, & value); 00316 g_free (string); 00317 return value; 00318 } 00319 00320 void set_double (const char * section, const char * name, double value) 00321 { 00322 char * string = double_to_string (value); 00323 g_return_if_fail (string); 00324 set_string (section, name, string); 00325 g_free (string); 00326 } 00327 00328 double get_double (const char * section, const char * name) 00329 { 00330 double value = 0; 00331 char * string = get_string (section, name); 00332 string_to_double (string, & value); 00333 g_free (string); 00334 return value; 00335 }