00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
00038 "advance_on_delete", "FALSE",
00039 "clear_playlist", "TRUE",
00040 "open_to_temporary", "TRUE",
00041 "resume_playback_on_startup", "FALSE",
00042
00043
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
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
00062 "use_proxy", "FALSE",
00063 "use_proxy_auth", "FALSE",
00064
00065
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
00078 "no_playlist_advance", "FALSE",
00079 "repeat", "FALSE",
00080 "shuffle", "FALSE",
00081 "stop_after_current_song", "FALSE",
00082
00083
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
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 }