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  * This file is part of Audacious.
6  *
7  * Audacious is free software: you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License as published by the Free Software
9  * Foundation, version 2 or version 3 of the License.
10  *
11  * Audacious is distributed in the hope that it will be useful, but WITHOUT ANY
12  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13  * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along with
16  * Audacious. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * The Audacious team does not consider modular code linking to Audacious or
19  * using our public API to be a derived work.
20  */
21 
22 #include <glib.h>
23 #include <pthread.h>
24 #include <stdio.h>
25 #include <string.h>
26 
27 #include <libaudcore/audstrings.h>
28 #include <libaudcore/hook.h>
29 
30 #include "main.h"
31 #include "misc.h"
32 
33 #define DEFAULT_SECTION "audacious"
34 
35 static const char * const core_defaults[] = {
36 
37  /* general */
38  "advance_on_delete", "FALSE",
39  "clear_playlist", "TRUE",
40  "open_to_temporary", "TRUE",
41  "resume_playback_on_startup", "FALSE",
42 
43  /* equalizer */
44  "eqpreset_default_file", "",
45  "eqpreset_extension", "",
46  "equalizer_active", "FALSE",
47  "equalizer_autoload", "FALSE",
48  "equalizer_bands", "0,0,0,0,0,0,0,0,0,0",
49  "equalizer_preamp", "0",
50 
51  /* info popup / info window */
52  "cover_name_exclude", "back",
53  "cover_name_include", "album,cover,front,folder",
54  "filepopup_delay", "5",
55  "filepopup_showprogressbar", "TRUE",
56  "recurse_for_cover", "FALSE",
57  "recurse_for_cover_depth", "0",
58  "show_filepopup_for_tuple", "TRUE",
59  "use_file_cover", "FALSE",
60 
61  /* network */
62  "use_proxy", "FALSE",
63  "use_proxy_auth", "FALSE",
64 
65  /* output */
66  "default_gain", "0",
67  "enable_replay_gain", "TRUE",
68  "enable_clipping_prevention", "TRUE",
69  "output_bit_depth", "16",
70  "output_buffer_size", "500",
71  "replay_gain_album", "FALSE",
72  "replay_gain_preamp", "0",
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  "generic_title_format", "${?artist:${artist} - }${?album:${album} - }${title}",
85  "leading_zero", "FALSE",
86  "metadata_on_play", "FALSE",
87  "show_numbers_in_pl", "FALSE",
88 
89  NULL};
90 
91 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
92 static GHashTable * defaults;
93 static GKeyFile * keyfile;
95 
96 /* str_unref() may be a macro */
97 static void str_unref_cb (void * str)
98 {
99  str_unref (str);
100 }
101 
102 void config_load (void)
103 {
104  g_return_if_fail (! defaults && ! keyfile);
105  pthread_mutex_lock (& mutex);
106 
107  defaults = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
108  (GDestroyNotify) g_hash_table_destroy);
109  keyfile = g_key_file_new ();
110 
111  char * path = g_strdup_printf ("%s/config", get_path (AUD_PATH_USER_DIR));
112  if (g_file_test (path, G_FILE_TEST_EXISTS))
113  {
114  GError * error = NULL;
115  if (! g_key_file_load_from_file (keyfile, path, 0, & error))
116  {
117  fprintf (stderr, "Error loading config: %s\n", error->message);
118  g_error_free (error);
119  }
120  }
121  g_free (path);
122 
123  modified = FALSE;
124  pthread_mutex_unlock (& mutex);
125 
127 }
128 
129 void config_save (void)
130 {
131  g_return_if_fail (defaults && keyfile);
132  pthread_mutex_lock (& mutex);
133 
134  if (! modified)
135  {
136  pthread_mutex_unlock (& mutex);
137  return;
138  }
139 
140  char * path = g_strdup_printf ("%s/config", get_path (AUD_PATH_USER_DIR));
141  char * data = g_key_file_to_data (keyfile, NULL, NULL);
142 
143  GError * error = NULL;
144  if (! g_file_set_contents (path, data, -1, & error))
145  {
146  fprintf (stderr, "Error saving config: %s\n", error->message);
147  g_error_free (error);
148  }
149 
150  g_free (data);
151  g_free (path);
152 
153  modified = FALSE;
154  pthread_mutex_unlock (& mutex);
155 }
156 
157 void config_cleanup (void)
158 {
159  g_return_if_fail (defaults && keyfile);
160  pthread_mutex_lock (& mutex);
161 
162  g_key_file_free (keyfile);
163  keyfile = NULL;
164  g_hash_table_destroy (defaults);
165  defaults = NULL;
166 
167  pthread_mutex_unlock (& mutex);
168 }
169 
170 void config_clear_section (const char * section)
171 {
172  g_return_if_fail (defaults && keyfile);
173  pthread_mutex_lock (& mutex);
174 
175  if (! section)
176  section = DEFAULT_SECTION;
177 
178  if (g_key_file_has_group (keyfile, section))
179  {
180  g_key_file_remove_group (keyfile, section, NULL);
181  modified = TRUE;
182  }
183 
184  pthread_mutex_unlock (& mutex);
185 }
186 
187 void config_set_defaults (const char * section, const char * const * entries)
188 {
189  g_return_if_fail (defaults && keyfile);
190  pthread_mutex_lock (& mutex);
191 
192  if (! section)
193  section = DEFAULT_SECTION;
194 
195  GHashTable * table = g_hash_table_lookup (defaults, section);
196  if (! table)
197  {
198  table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, str_unref_cb);
199  g_hash_table_replace (defaults, g_strdup (section), table);
200  }
201 
202  while (1)
203  {
204  const char * name = * entries ++;
205  const char * value = * entries ++;
206  if (! name || ! value)
207  break;
208 
209  g_hash_table_replace (table, g_strdup (name), str_get (value));
210  }
211 
212  pthread_mutex_unlock (& mutex);
213 }
214 
215 static const char * get_default (const char * section, const char * name)
216 {
217  GHashTable * table = g_hash_table_lookup (defaults, section);
218  const char * def = table ? g_hash_table_lookup (table, name) : NULL;
219  return def ? def : "";
220 }
221 
222 void set_string (const char * section, const char * name, const char * value)
223 {
224  g_return_if_fail (defaults && keyfile);
225  g_return_if_fail (name && value);
226  pthread_mutex_lock (& mutex);
227 
228  if (! section)
229  section = DEFAULT_SECTION;
230 
231  const char * def = get_default (section, name);
232  bool_t changed = FALSE;
233 
234  if (! strcmp (value, def))
235  {
236  if (g_key_file_has_key (keyfile, section, name, NULL))
237  {
238  g_key_file_remove_key (keyfile, section, name, NULL);
239  changed = TRUE;
240  }
241  }
242  else
243  {
244  char * old = g_key_file_has_key (keyfile, section, name, NULL) ?
245  g_key_file_get_value (keyfile, section, name, NULL) : NULL;
246 
247  if (! old || strcmp (value, old))
248  {
249  g_key_file_set_value (keyfile, section, name, value);
250  changed = TRUE;
251  }
252 
253  g_free (old);
254  }
255 
256  if (changed)
257  {
258  modified = TRUE;
259 
260  if (! strcmp (section, DEFAULT_SECTION))
261  {
262  char * event = g_strdup_printf ("set %s", name);
263  event_queue (event, NULL);
264  g_free (event);
265  }
266  }
267 
268  pthread_mutex_unlock (& mutex);
269 }
270 
271 char * get_string (const char * section, const char * name)
272 {
273  g_return_val_if_fail (defaults && keyfile, g_strdup (""));
274  g_return_val_if_fail (name, g_strdup (""));
275  pthread_mutex_lock (& mutex);
276 
277  if (! section)
278  section = DEFAULT_SECTION;
279 
280  char * value = g_key_file_has_key (keyfile, section, name, NULL) ?
281  g_key_file_get_value (keyfile, section, name, NULL) : NULL;
282 
283  if (! value)
284  value = g_strdup (get_default (section, name));
285 
286  pthread_mutex_unlock (& mutex);
287  return value;
288 }
289 
290 void set_bool (const char * section, const char * name, bool_t value)
291 {
292  set_string (section, name, value ? "TRUE" : "FALSE");
293 }
294 
295 bool_t get_bool (const char * section, const char * name)
296 {
297  char * string = get_string (section, name);
298  bool_t value = ! strcmp (string, "TRUE");
299  g_free (string);
300  return value;
301 }
302 
303 void set_int (const char * section, const char * name, int value)
304 {
305  char * string = int_to_string (value);
306  g_return_if_fail (string);
307  set_string (section, name, string);
308  g_free (string);
309 }
310 
311 int get_int (const char * section, const char * name)
312 {
313  int value = 0;
314  char * string = get_string (section, name);
315  string_to_int (string, & value);
316  g_free (string);
317  return value;
318 }
319 
320 void set_double (const char * section, const char * name, double value)
321 {
322  char * string = double_to_string (value);
323  g_return_if_fail (string);
324  set_string (section, name, string);
325  g_free (string);
326 }
327 
328 double get_double (const char * section, const char * name)
329 {
330  double value = 0;
331  char * string = get_string (section, name);
332  string_to_double (string, & value);
333  g_free (string);
334  return value;
335 }