pnmixer
Volume mixer for the system tray
prefs.c
Go to the documentation of this file.
1 /* prefs.c
2  * PNmixer is written by Nick Lanham, a fork of OBmixer
3  * which was programmed by Lee Ferrett, derived
4  * from the program "AbsVolume" by Paul Sherman
5  * This program is free software; you can redistribute
6  * it and/or modify it under the terms of the GNU General
7  * Public License v3. source code is available at
8  * <http://github.com/nicklan/pnmixer>
9  */
10 
18 #ifdef HAVE_CONFIG_H
19 #include "config.h"
20 #endif
21 
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <unistd.h>
25 #include <stdlib.h>
26 #include <strings.h>
27 #include <string.h>
28 #include <stdio.h>
29 #include <errno.h>
30 
31 #include <glib.h>
32 #include <glib/gstdio.h>
33 
34 #include "prefs.h"
35 #include "support-log.h"
36 #include "support-intl.h"
37 
38 #include "main.h"
39 
40 #define DEFAULT_PREFS "[PNMixer]\n\
41 SliderOrientation=vertical\n\
42 DisplayTextVolume=true\n\
43 TextVolumePosition=0\n\
44 ScrollStep=5\n\
45 FineScrollStep=1\n\
46 MiddleClickAction=0\n\
47 CustomCommand=\n\
48 VolMuteKey=-1\n\
49 VolUpKey=-1\n\
50 VolDownKey=-1\n\
51 AlsaCard=(default)\n\
52 NormalizeVolume=true\n\
53 SystemTheme=false"
54 
55 static GKeyFile *keyFile;
56 
57 /*
58  * Default volume commands.
59  */
60 static const gchar *vol_control_commands[] = {
61  "pavucontrol",
62  "mate-volume-control"
63  "xfce4-mixer",
64  "alsamixergui",
65  NULL
66 };
67 
68 /*
69  * Look for an installed volume command.
70  */
71 static const gchar *
73 {
74  const char **cmd;
75 
76  DEBUG("Looking for a volume control command...");
77 
79  while (*cmd) {
80  gchar *absolute_path;
81 
82  absolute_path = g_find_program_in_path(*cmd);
83  if (absolute_path) {
84  g_free(absolute_path);
85  return *cmd;
86  }
87  cmd++;
88  }
89 
90  return NULL;
91 }
92 
101 gboolean
102 prefs_get_boolean(const gchar *key, gboolean def)
103 {
104  gboolean ret;
105  GError *error = NULL;
106 
107  ret = g_key_file_get_boolean(keyFile, "PNMixer", key, &error);
108  if (error) {
109  g_error_free(error);
110  return def;
111  }
112 
113  return ret;
114 }
115 
124 gint
125 prefs_get_integer(const gchar *key, gint def)
126 {
127  gint ret;
128  GError *error = NULL;
129 
130  ret = g_key_file_get_integer(keyFile, "PNMixer", key, &error);
131  if (error) {
132  g_error_free(error);
133  return def;
134  }
135 
136  return ret;
137 }
138 
147 gdouble
148 prefs_get_double(const gchar *key, gdouble def)
149 {
150  gdouble ret;
151  GError *error = NULL;
152 
153  ret = g_key_file_get_double(keyFile, "PNMixer", key, &error);
154  if (error) {
155  g_error_free(error);
156  return def;
157  }
158 
159  return ret;
160 }
161 
170 gchar *
171 prefs_get_string(const gchar *key, const gchar *def)
172 {
173  gchar *ret;
174  GError *error = NULL;
175 
176  ret = g_key_file_get_string(keyFile, "PNMixer", key, &error);
177 
178  /* Return value if found */
179  if (error == NULL)
180  return ret;
181  else
182  g_error_free(error);
183 
184  /* If the volume control command is not defined,
185  * be clever and try to find a command installed.
186  */
187  if (!g_strcmp0(key, "VolumeControlCommand")) {
188  const gchar *cmd = find_vol_control_command();
189  if (cmd)
190  return g_strdup(cmd);
191  }
192 
193  /* At last, return default value */
194  return g_strdup(def);
195 }
196 
205 gdouble *
206 prefs_get_double_list(const gchar *key, gsize *n)
207 {
208  gsize numcols = 0;
209  gdouble *ret = NULL;
210  GError *error = NULL;
211 
212  ret = g_key_file_get_double_list(keyFile, "PNMixer", key, &numcols, &error);
213  if (error) {
214  g_error_free(error);
215  ret = NULL;
216  }
217 
218  /* For the volume meter color, we need a little bit of care.
219  * Ensure the list is valid, and provide default values if needed.
220  */
221  if (!g_strcmp0(key, "VolMeterColor")) {
222  gsize i;
223 
224  if (ret && numcols != 3) {
225  g_free(ret);
226  ret = NULL;
227  }
228 
229  if (!ret) {
230  ret = g_malloc(3 * sizeof(gdouble));
231  ret[0] = 0.909803921569;
232  ret[1] = 0.43137254902;
233  ret[2] = 0.43137254902;
234  }
235 
236  for (i = 0; i < 3; i++) {
237  if (ret[i] < 0)
238  ret[i] = 0;
239  if (ret[i] > 1)
240  ret[i] = 1;
241  }
242  }
243 
244  if (n)
245  *n = numcols;
246 
247  return ret;
248 }
249 
258 gchar *
259 prefs_get_channel(const gchar *card)
260 {
261  if (!card)
262  return NULL;
263  return g_key_file_get_string(keyFile, card, "Channel", NULL);
264 }
265 
272 void
273 prefs_set_boolean(const gchar *key, gboolean value)
274 {
275  g_key_file_set_boolean(keyFile, "PNMixer", key, value);
276 }
277 
284 void
285 prefs_set_integer(const gchar *key, gint value)
286 {
287  g_key_file_set_integer(keyFile, "PNMixer", key, value);
288 }
289 
296 void
297 prefs_set_double(const gchar *key, gdouble value)
298 {
299  g_key_file_set_double(keyFile, "PNMixer", key, value);
300 }
301 
308 void
309 prefs_set_string(const gchar *key, const gchar *value)
310 {
311  g_key_file_set_string(keyFile, "PNMixer", key, value);
312 }
313 
321 void
322 prefs_set_double_list(const gchar *key, gdouble *list, gsize n)
323 {
324  g_key_file_set_double_list(keyFile, "PNMixer", key, list, n);
325 }
326 
333 void
334 prefs_set_channel(const gchar *card, const gchar *channel)
335 {
336  g_key_file_set_string(keyFile, card, "Channel", channel);
337 }
338 
343 void
345 {
346  GError *err = NULL;
347  gchar *filename = g_build_filename(g_get_user_config_dir(),
348  "pnmixer", "config", NULL);
349 
350  if (keyFile != NULL)
351  g_key_file_free(keyFile);
352 
353  keyFile = g_key_file_new();
354 
355  if (g_file_test(filename, G_FILE_TEST_EXISTS)) {
356  if (!g_key_file_load_from_file(keyFile, filename, 0, &err)) {
357  run_error_dialog(_("Couldn't load preferences file: %s"),
358  err->message);
359  g_error_free(err);
360  g_key_file_free(keyFile);
361  keyFile = NULL;
362  }
363  } else {
364  if (!g_key_file_load_from_data
365  (keyFile, DEFAULT_PREFS, strlen(DEFAULT_PREFS), 0, &err)) {
366  run_error_dialog(_("Couldn't load default preferences: %s"),
367  err->message);
368  g_error_free(err);
369  g_key_file_free(keyFile);
370  keyFile = NULL;
371  }
372  }
373 
374  g_free(filename);
375 }
376 
380 void
382 {
383  gsize len;
384  GError *err = NULL;
385  gchar *filename = g_build_filename(g_get_user_config_dir(),
386  "pnmixer", "config", NULL);
387  gchar *filedata = g_key_file_to_data(keyFile, &len, NULL);
388 
389  g_file_set_contents(filename, filedata, len, &err);
390 
391  if (err != NULL) {
392  run_error_dialog(_("Couldn't write preferences file: %s"), err->message);
393  g_error_free(err);
394  }
395 
396  g_free(filename);
397  g_free(filedata);
398 }
399 
404 void
406 {
407  gchar *prefs_dir = g_build_filename(g_get_user_config_dir(),
408  "pnmixer", NULL);
409 
410  if (!g_file_test(prefs_dir, G_FILE_TEST_IS_DIR)) {
411  if (g_file_test(prefs_dir, G_FILE_TEST_EXISTS))
412  run_error_dialog(_("'%s' exists but is not a directory, "
413  "won't be able to save preferences."),
414  prefs_dir);
415  else if (g_mkdir(prefs_dir, S_IRWXU))
416  run_error_dialog(_("Couldn't make preferences directory: %s"),
417  strerror(errno));
418  }
419 
420  g_free(prefs_dir);
421 }
#define _(String)
Definition: support-intl.h:44
Internationalization support.
Logging support.
static const gchar * find_vol_control_command(void)
Definition: prefs.c:72
void prefs_set_double(const gchar *key, gdouble value)
Definition: prefs.c:297
static GKeyFile * keyFile
Definition: prefs.c:55
#define DEFAULT_PREFS
Definition: prefs.c:40
static const gchar * vol_control_commands[]
Definition: prefs.c:60
Header for prefs.c.
gdouble * prefs_get_double_list(const gchar *key, gsize *n)
Definition: prefs.c:206
void prefs_set_channel(const gchar *card, const gchar *channel)
Definition: prefs.c:334
gboolean prefs_get_boolean(const gchar *key, gboolean def)
Definition: prefs.c:102
#define DEBUG(...)
Definition: support-log.h:38
Header for main.c.
void prefs_set_integer(const gchar *key, gint value)
Definition: prefs.c:285
gchar * prefs_get_channel(const gchar *card)
Definition: prefs.c:259
void prefs_save(void)
Definition: prefs.c:381
gchar * prefs_get_string(const gchar *key, const gchar *def)
Definition: prefs.c:171
void prefs_load(void)
Definition: prefs.c:344
void prefs_ensure_save_dir(void)
Definition: prefs.c:405
void prefs_set_double_list(const gchar *key, gdouble *list, gsize n)
Definition: prefs.c:322
void run_error_dialog(const char *fmt,...)
Definition: main.c:188
void prefs_set_string(const gchar *key, const gchar *value)
Definition: prefs.c:309
gint prefs_get_integer(const gchar *key, gint def)
Definition: prefs.c:125
void prefs_set_boolean(const gchar *key, gboolean value)
Definition: prefs.c:273
gdouble prefs_get_double(const gchar *key, gdouble def)
Definition: prefs.c:148