Audacious  $Id:Doxyfile42802007-03-2104:39:00Znenolod$
config.c
Go to the documentation of this file.
1 /*
2  * config.c
3  * Copyright 2011 John Lindgren
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions, and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions, and the following disclaimer in the documentation
13  * provided with the distribution.
14  *
15  * This software is provided "as is" and without any warranty, express or
16  * implied. In no event shall the authors be liable for any damages arising from
17  * the use of this software.
18  */
19 
20 #include <glib.h>
21 #include <pthread.h>
22 #include <stdio.h>
23 #include <string.h>
24 
25 #include <libaudcore/audstrings.h>
26 #include <libaudcore/hook.h>
27 
28 #include "main.h"
29 #include "misc.h"
30 
31 #define DEFAULT_SECTION "audacious"
32 
33 static const char * const core_defaults[] = {
34 
35  /* general */
36  "advance_on_delete", "FALSE",
37  "clear_playlist", "TRUE",
38  "open_to_temporary", "TRUE",
39  "resume_playback_on_startup", "FALSE",
40 
41  /* equalizer */
42  "eqpreset_default_file", "",
43  "eqpreset_extension", "",
44  "equalizer_active", "FALSE",
45  "equalizer_autoload", "FALSE",
46  "equalizer_bands", "0,0,0,0,0,0,0,0,0,0",
47  "equalizer_preamp", "0",
48 
49  /* info popup / info window */
50  "cover_name_exclude", "back",
51  "cover_name_include", "album,cover,front,folder",
52  "filepopup_delay", "5",
53  "filepopup_showprogressbar", "TRUE",
54  "recurse_for_cover", "FALSE",
55  "recurse_for_cover_depth", "0",
56  "show_filepopup_for_tuple", "TRUE",
57  "use_file_cover", "FALSE",
58 
59  /* network */
60  "use_proxy", "FALSE",
61  "use_proxy_auth", "FALSE",
62 
63  /* output */
64  "default_gain", "0",
65  "enable_replay_gain", "TRUE",
66  "enable_clipping_prevention", "TRUE",
67  "output_bit_depth", "16",
68  "output_buffer_size", "500",
69  "replay_gain_album", "FALSE",
70  "replay_gain_preamp", "0",
71  "soft_clipping", "FALSE",
72  "software_volume_control", "FALSE",
73  "sw_volume_left", "100",
74  "sw_volume_right", "100",
75 
76  /* playback */
77  "no_playlist_advance", "FALSE",
78  "repeat", "FALSE",
79  "shuffle", "FALSE",
80  "stop_after_current_song", "FALSE",
81 
82  /* playlist */
83 #ifdef _WIN32
84  "convert_backslash", "TRUE",
85 #else
86  "convert_backslash", "FALSE",
87 #endif
88  "generic_title_format", "${?artist:${artist} - }${?album:${album} - }${title}",
89  "leading_zero", "FALSE",
90  "metadata_on_play", "FALSE",
91  "show_numbers_in_pl", "FALSE",
92 
93  NULL};
94 
95 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
96 static GHashTable * defaults;
97 static GKeyFile * keyfile;
99 
100 /* str_unref() may be a macro */
101 static void str_unref_cb (void * str)
102 {
103  str_unref (str);
104 }
105 
106 void config_load (void)
107 {
108  g_return_if_fail (! defaults && ! keyfile);
109  pthread_mutex_lock (& mutex);
110 
111  defaults = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
112  (GDestroyNotify) g_hash_table_destroy);
113  keyfile = g_key_file_new ();
114 
115  char * path = g_strdup_printf ("%s/config", get_path (AUD_PATH_USER_DIR));
116  if (g_file_test (path, G_FILE_TEST_EXISTS))
117  {
118  GError * error = NULL;
119  if (! g_key_file_load_from_file (keyfile, path, 0, & error))
120  {
121  fprintf (stderr, "Error loading config: %s\n", error->message);
122  g_error_free (error);
123  }
124  }
125  g_free (path);
126 
127  modified = FALSE;
128  pthread_mutex_unlock (& mutex);
129 
131 }
132 
133 void config_save (void)
134 {
135  g_return_if_fail (defaults && keyfile);
136  pthread_mutex_lock (& mutex);
137 
138  if (! modified)
139  {
140  pthread_mutex_unlock (& mutex);
141  return;
142  }
143 
144  char * path = g_strdup_printf ("%s/config", get_path (AUD_PATH_USER_DIR));
145  char * data = g_key_file_to_data (keyfile, NULL, NULL);
146 
147  GError * error = NULL;
148  if (! g_file_set_contents (path, data, -1, & error))
149  {
150  fprintf (stderr, "Error saving config: %s\n", error->message);
151  g_error_free (error);
152  }
153 
154  g_free (data);
155  g_free (path);
156 
157  modified = FALSE;
158  pthread_mutex_unlock (& mutex);
159 }
160 
161 void config_cleanup (void)
162 {
163  g_return_if_fail (defaults && keyfile);
164  pthread_mutex_lock (& mutex);
165 
166  g_key_file_free (keyfile);
167  keyfile = NULL;
168  g_hash_table_destroy (defaults);
169  defaults = NULL;
170 
171  pthread_mutex_unlock (& mutex);
172 }
173 
174 void config_clear_section (const char * section)
175 {
176  g_return_if_fail (defaults && keyfile);
177  pthread_mutex_lock (& mutex);
178 
179  if (! section)
180  section = DEFAULT_SECTION;
181 
182  if (g_key_file_has_group (keyfile, section))
183  {
184  g_key_file_remove_group (keyfile, section, NULL);
185  modified = TRUE;
186  }
187 
188  pthread_mutex_unlock (& mutex);
189 }
190 
191 void config_set_defaults (const char * section, const char * const * entries)
192 {
193  g_return_if_fail (defaults && keyfile);
194  pthread_mutex_lock (& mutex);
195 
196  if (! section)
197  section = DEFAULT_SECTION;
198 
199  GHashTable * table = g_hash_table_lookup (defaults, section);
200  if (! table)
201  {
202  table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, str_unref_cb);
203  g_hash_table_replace (defaults, g_strdup (section), table);
204  }
205 
206  while (1)
207  {
208  const char * name = * entries ++;
209  const char * value = * entries ++;
210  if (! name || ! value)
211  break;
212 
213  g_hash_table_replace (table, g_strdup (name), str_get (value));
214  }
215 
216  pthread_mutex_unlock (& mutex);
217 }
218 
219 static const char * get_default (const char * section, const char * name)
220 {
221  GHashTable * table = g_hash_table_lookup (defaults, section);
222  const char * def = table ? g_hash_table_lookup (table, name) : NULL;
223  return def ? def : "";
224 }
225 
226 void set_string (const char * section, const char * name, const char * value)
227 {
228  g_return_if_fail (defaults && keyfile);
229  g_return_if_fail (name && value);
230  pthread_mutex_lock (& mutex);
231 
232  if (! section)
233  section = DEFAULT_SECTION;
234 
235  const char * def = get_default (section, name);
236  bool_t changed = FALSE;
237 
238  if (! strcmp (value, def))
239  {
240  if (g_key_file_has_key (keyfile, section, name, NULL))
241  {
242  g_key_file_remove_key (keyfile, section, name, NULL);
243  changed = TRUE;
244  }
245  }
246  else
247  {
248  char * old = g_key_file_has_key (keyfile, section, name, NULL) ?
249  g_key_file_get_value (keyfile, section, name, NULL) : NULL;
250 
251  if (! old || strcmp (value, old))
252  {
253  g_key_file_set_value (keyfile, section, name, value);
254  changed = TRUE;
255  }
256 
257  g_free (old);
258  }
259 
260  if (changed)
261  {
262  modified = TRUE;
263 
264  if (! strcmp (section, DEFAULT_SECTION))
265  {
266  char * event = g_strdup_printf ("set %s", name);
267  event_queue (event, NULL);
268  g_free (event);
269  }
270  }
271 
272  pthread_mutex_unlock (& mutex);
273 }
274 
275 char * get_string (const char * section, const char * name)
276 {
277  g_return_val_if_fail (defaults && keyfile, g_strdup (""));
278  g_return_val_if_fail (name, g_strdup (""));
279  pthread_mutex_lock (& mutex);
280 
281  if (! section)
282  section = DEFAULT_SECTION;
283 
284  char * value = g_key_file_has_key (keyfile, section, name, NULL) ?
285  g_key_file_get_value (keyfile, section, name, NULL) : NULL;
286 
287  if (! value)
288  value = g_strdup (get_default (section, name));
289 
290  pthread_mutex_unlock (& mutex);
291  return value;
292 }
293 
294 void set_bool (const char * section, const char * name, bool_t value)
295 {
296  set_string (section, name, value ? "TRUE" : "FALSE");
297 }
298 
299 bool_t get_bool (const char * section, const char * name)
300 {
301  char * string = get_string (section, name);
302  bool_t value = ! strcmp (string, "TRUE");
303  g_free (string);
304  return value;
305 }
306 
307 void set_int (const char * section, const char * name, int value)
308 {
309  char * string = int_to_string (value);
310  g_return_if_fail (string);
311  set_string (section, name, string);
312  g_free (string);
313 }
314 
315 int get_int (const char * section, const char * name)
316 {
317  int value = 0;
318  char * string = get_string (section, name);
319  string_to_int (string, & value);
320  g_free (string);
321  return value;
322 }
323 
324 void set_double (const char * section, const char * name, double value)
325 {
326  char * string = double_to_string (value);
327  g_return_if_fail (string);
328  set_string (section, name, string);
329  g_free (string);
330 }
331 
332 double get_double (const char * section, const char * name)
333 {
334  double value = 0;
335  char * string = get_string (section, name);
336  string_to_double (string, & value);
337  g_free (string);
338  return value;
339 }