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  "show_interface", "TRUE",
41 
42  /* equalizer */
43  "eqpreset_default_file", "",
44  "eqpreset_extension", "",
45  "equalizer_active", "FALSE",
46  "equalizer_autoload", "FALSE",
47  "equalizer_bands", "0,0,0,0,0,0,0,0,0,0",
48  "equalizer_preamp", "0",
49 
50  /* info popup / info window */
51  "cover_name_exclude", "back",
52  "cover_name_include", "album,cover,front,folder",
53  "filepopup_delay", "5",
54  "filepopup_showprogressbar", "TRUE",
55  "recurse_for_cover", "FALSE",
56  "recurse_for_cover_depth", "0",
57  "show_filepopup_for_tuple", "TRUE",
58  "use_file_cover", "FALSE",
59 
60  /* network */
61  "use_proxy", "FALSE",
62  "use_proxy_auth", "FALSE",
63 
64  /* output */
65  "default_gain", "0",
66  "enable_replay_gain", "TRUE",
67  "enable_clipping_prevention", "TRUE",
68  "output_bit_depth", "16",
69  "output_buffer_size", "500",
70  "replay_gain_album", "FALSE",
71  "replay_gain_preamp", "0",
72  "soft_clipping", "FALSE",
73  "software_volume_control", "FALSE",
74  "sw_volume_left", "100",
75  "sw_volume_right", "100",
76 
77  /* playback */
78  "no_playlist_advance", "FALSE",
79  "repeat", "FALSE",
80  "shuffle", "FALSE",
81  "stop_after_current_song", "FALSE",
82 
83  /* playlist */
84 #ifdef _WIN32
85  "convert_backslash", "TRUE",
86 #else
87  "convert_backslash", "FALSE",
88 #endif
89  "generic_title_format", "${?artist:${artist} - }${?album:${album} - }${title}",
90  "leading_zero", "FALSE",
91  "metadata_on_play", "FALSE",
92  "show_numbers_in_pl", "FALSE",
93 
94  NULL};
95 
96 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
97 static GHashTable * defaults;
98 static GKeyFile * keyfile;
100 
101 /* str_unref() may be a macro */
102 static void str_unref_cb (void * str)
103 {
104  str_unref (str);
105 }
106 
107 void config_load (void)
108 {
109  g_return_if_fail (! defaults && ! keyfile);
110  pthread_mutex_lock (& mutex);
111 
112  defaults = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
113  (GDestroyNotify) g_hash_table_destroy);
114  keyfile = g_key_file_new ();
115 
116  char * path = g_strdup_printf ("%s/config", get_path (AUD_PATH_USER_DIR));
117  if (g_file_test (path, G_FILE_TEST_EXISTS))
118  {
119  GError * error = NULL;
120  if (! g_key_file_load_from_file (keyfile, path, 0, & error))
121  {
122  fprintf (stderr, "Error loading config: %s\n", error->message);
123  g_error_free (error);
124  }
125  }
126  g_free (path);
127 
128  modified = FALSE;
129  pthread_mutex_unlock (& mutex);
130 
132 }
133 
134 void config_save (void)
135 {
136  g_return_if_fail (defaults && keyfile);
137  pthread_mutex_lock (& mutex);
138 
139  if (! modified)
140  {
141  pthread_mutex_unlock (& mutex);
142  return;
143  }
144 
145  char * path = g_strdup_printf ("%s/config", get_path (AUD_PATH_USER_DIR));
146  char * data = g_key_file_to_data (keyfile, NULL, NULL);
147 
148  GError * error = NULL;
149  if (! g_file_set_contents (path, data, -1, & error))
150  {
151  fprintf (stderr, "Error saving config: %s\n", error->message);
152  g_error_free (error);
153  }
154 
155  g_free (data);
156  g_free (path);
157 
158  modified = FALSE;
159  pthread_mutex_unlock (& mutex);
160 }
161 
162 void config_cleanup (void)
163 {
164  g_return_if_fail (defaults && keyfile);
165  pthread_mutex_lock (& mutex);
166 
167  g_key_file_free (keyfile);
168  keyfile = NULL;
169  g_hash_table_destroy (defaults);
170  defaults = NULL;
171 
172  pthread_mutex_unlock (& mutex);
173 }
174 
175 void config_clear_section (const char * section)
176 {
177  g_return_if_fail (defaults && keyfile);
178  pthread_mutex_lock (& mutex);
179 
180  if (! section)
181  section = DEFAULT_SECTION;
182 
183  if (g_key_file_has_group (keyfile, section))
184  {
185  g_key_file_remove_group (keyfile, section, NULL);
186  modified = TRUE;
187  }
188 
189  pthread_mutex_unlock (& mutex);
190 }
191 
192 void config_set_defaults (const char * section, const char * const * entries)
193 {
194  g_return_if_fail (defaults && keyfile);
195  pthread_mutex_lock (& mutex);
196 
197  if (! section)
198  section = DEFAULT_SECTION;
199 
200  GHashTable * table = g_hash_table_lookup (defaults, section);
201  if (! table)
202  {
203  table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, str_unref_cb);
204  g_hash_table_replace (defaults, g_strdup (section), table);
205  }
206 
207  while (1)
208  {
209  const char * name = * entries ++;
210  const char * value = * entries ++;
211  if (! name || ! value)
212  break;
213 
214  g_hash_table_replace (table, g_strdup (name), str_get (value));
215  }
216 
217  pthread_mutex_unlock (& mutex);
218 }
219 
220 static const char * get_default (const char * section, const char * name)
221 {
222  GHashTable * table = g_hash_table_lookup (defaults, section);
223  const char * def = table ? g_hash_table_lookup (table, name) : NULL;
224  return def ? def : "";
225 }
226 
227 void set_string (const char * section, const char * name, const char * value)
228 {
229  g_return_if_fail (defaults && keyfile);
230  g_return_if_fail (name && value);
231  pthread_mutex_lock (& mutex);
232 
233  if (! section)
234  section = DEFAULT_SECTION;
235 
236  const char * def = get_default (section, name);
237  bool_t changed = FALSE;
238 
239  if (! strcmp (value, def))
240  {
241  if (g_key_file_has_key (keyfile, section, name, NULL))
242  {
243  g_key_file_remove_key (keyfile, section, name, NULL);
244  changed = TRUE;
245  }
246  }
247  else
248  {
249  char * old = g_key_file_has_key (keyfile, section, name, NULL) ?
250  g_key_file_get_value (keyfile, section, name, NULL) : NULL;
251 
252  if (! old || strcmp (value, old))
253  {
254  g_key_file_set_value (keyfile, section, name, value);
255  changed = TRUE;
256  }
257 
258  g_free (old);
259  }
260 
261  if (changed)
262  {
263  modified = TRUE;
264 
265  if (! strcmp (section, DEFAULT_SECTION))
266  {
267  char * event = g_strdup_printf ("set %s", name);
268  event_queue (event, NULL);
269  g_free (event);
270  }
271  }
272 
273  pthread_mutex_unlock (& mutex);
274 }
275 
276 char * get_string (const char * section, const char * name)
277 {
278  g_return_val_if_fail (defaults && keyfile, g_strdup (""));
279  g_return_val_if_fail (name, g_strdup (""));
280  pthread_mutex_lock (& mutex);
281 
282  if (! section)
283  section = DEFAULT_SECTION;
284 
285  char * value = g_key_file_has_key (keyfile, section, name, NULL) ?
286  g_key_file_get_value (keyfile, section, name, NULL) : NULL;
287 
288  if (! value)
289  value = g_strdup (get_default (section, name));
290 
291  pthread_mutex_unlock (& mutex);
292  return value;
293 }
294 
295 void set_bool (const char * section, const char * name, bool_t value)
296 {
297  set_string (section, name, value ? "TRUE" : "FALSE");
298 }
299 
300 bool_t get_bool (const char * section, const char * name)
301 {
302  char * string = get_string (section, name);
303  bool_t value = ! strcmp (string, "TRUE");
304  g_free (string);
305  return value;
306 }
307 
308 void set_int (const char * section, const char * name, int value)
309 {
310  char * string = int_to_string (value);
311  g_return_if_fail (string);
312  set_string (section, name, string);
313  g_free (string);
314 }
315 
316 int get_int (const char * section, const char * name)
317 {
318  int value = 0;
319  char * string = get_string (section, name);
320  string_to_int (string, & value);
321  g_free (string);
322  return value;
323 }
324 
325 void set_double (const char * section, const char * name, double value)
326 {
327  char * string = double_to_string (value);
328  g_return_if_fail (string);
329  set_string (section, name, string);
330  g_free (string);
331 }
332 
333 double get_double (const char * section, const char * name)
334 {
335  double value = 0;
336  char * string = get_string (section, name);
337  string_to_double (string, & value);
338  g_free (string);
339  return value;
340 }