build,core,plugins: Port to GDBus and GVariant
[profile/ivi/rygel.git] / src / rygel / rygel-user-config.vala
1 /*
2  * Copyright (C) 2008,2009 Nokia Corporation.
3  * Copyright (C) 2008,2009 Zeeshan Ali (Khattak) <zeeshanak@gnome.org>.
4  *
5  * Author: Zeeshan Ali (Khattak) <zeeshanak@gnome.org>
6  *                               <zeeshan.ali@nokia.com>
7  *
8  * This file is part of Rygel.
9  *
10  * Rygel is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU Lesser General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * Rygel is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public License
21  * along with this program; if not, write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23  */
24
25 /**
26  * Manages the user configuration for Rygel.
27  */
28 public class Rygel.UserConfig : GLib.Object, Configuration {
29     protected static const string CONFIG_FILE = "rygel.conf";
30     protected static const string IFACE_KEY = "interface";
31     protected static const string PORT_KEY = "port";
32     protected static const string ENABLED_KEY = "enabled";
33     protected static const string TITLE_KEY = "title";
34     protected static const string TRANSCODING_KEY = "enable-transcoding";
35     protected static const string MP3_TRANSCODER_KEY = "enable-mp3-transcoder";
36     protected static const string MP2TS_TRANSCODER_KEY =
37                                                     "enable-mp2ts-transcoder";
38     protected static const string LPCM_TRANSCODER_KEY =
39                                                     "enable-lpcm-transcoder";
40     protected static const string WMV_TRANSCODER_KEY = "enable-wmv-transcoder";
41     protected static const string LOG_LEVEL_KEY = "log-level";
42     protected static const string PLUGIN_PATH_KEY = "plugin-path";
43
44     private const string RYGEL_SERVICE = "org.gnome.Rygel1";
45     private const string RYGEL_PATH = "/org/gnome/Rygel1";
46     private const string RYGEL_INTERFACE = "org.gnome.Rygel1";
47
48     // Our singleton
49     private static UserConfig config;
50
51     protected KeyFile key_file;
52     private bool read_only;
53
54     public bool get_upnp_enabled () throws GLib.Error {
55         return this.get_bool ("general", ENABLED_KEY);
56     }
57
58     public void set_upnp_enabled (bool value) {
59         bool enabled = false;
60
61         try {
62             enabled = this.get_upnp_enabled ();
63         } catch (GLib.Error err) {}
64
65         if (value != enabled) {
66             this.enable_upnp (value);
67         }
68     }
69
70     public string get_interface () throws GLib.Error {
71         return this.get_string ("general", IFACE_KEY);
72     }
73
74     public void set_interface (string value) {
75         this.set_string ("general", IFACE_KEY, value);
76     }
77
78     public int get_port () throws GLib.Error {
79         return this.get_int ("general", PORT_KEY, uint16.MIN, uint16.MAX);
80     }
81
82     public void set_port (int value) {
83         this.set_int ("general", PORT_KEY, value);
84     }
85
86     public bool get_transcoding () throws GLib.Error {
87         return this.get_bool ("general", TRANSCODING_KEY);
88     }
89
90     public void set_transcoding (bool value) {
91         this.set_bool ("general", TRANSCODING_KEY, value);
92     }
93
94     public bool get_mp3_transcoder () throws GLib.Error {
95         return this.get_bool ("general", MP3_TRANSCODER_KEY);
96     }
97
98     public void set_mp3_transcoder (bool value) {
99         this.set_bool ("general", MP3_TRANSCODER_KEY, value);
100     }
101
102     public bool get_mp2ts_transcoder () throws GLib.Error {
103         return this.get_bool ("general", MP2TS_TRANSCODER_KEY);
104     }
105
106     public void set_mp2ts_transcoder (bool value) {
107         this.set_bool ("general", MP2TS_TRANSCODER_KEY, value);
108     }
109
110     public bool get_lpcm_transcoder () throws GLib.Error {
111         return this.get_bool ("general", LPCM_TRANSCODER_KEY);
112     }
113
114     public void set_lpcm_transcoder (bool value) {
115         this.set_bool ("general", LPCM_TRANSCODER_KEY, value);
116     }
117
118     public bool get_wmv_transcoder () throws GLib.Error {
119         return this.get_bool ("general", WMV_TRANSCODER_KEY);
120     }
121
122     public void set_wmv_transcoder (bool value) {
123         this.set_bool ("general", WMV_TRANSCODER_KEY, value);
124     }
125
126     public LogLevel get_log_level () throws GLib.Error {
127         return (LogLevel) this.get_int ("general",
128                                         LOG_LEVEL_KEY,
129                                         LogLevel.INVALID,
130                                         LogLevel.DEBUG);
131     }
132
133     public string get_plugin_path () throws GLib.Error {
134         return this.get_string ("general", PLUGIN_PATH_KEY);
135     }
136
137     public static UserConfig get_default () throws Error {
138         if (config == null) {
139             config = new UserConfig ();
140         }
141
142         return config;
143     }
144
145     public UserConfig (bool read_only=true) throws Error {
146         this.read_only = read_only;
147         this.key_file = new KeyFile ();
148
149         var dirs = new string[2];
150         dirs[0] = Environment.get_user_config_dir ();
151         dirs[1] = BuildConfig.SYS_CONFIG_DIR;
152
153         string path;
154         this.key_file.load_from_dirs (CONFIG_FILE,
155                                       dirs,
156                                       out path,
157                                       KeyFileFlags.KEEP_COMMENTS |
158                                       KeyFileFlags.KEEP_TRANSLATIONS);
159         debug ("Loaded user configuration from file '%s'", path);
160     }
161
162     public void save () {
163         return_if_fail (!this.read_only);
164
165         // Always write to user's config
166         string path = Path.build_filename (Environment.get_user_config_dir (),
167                                            CONFIG_FILE);
168
169         size_t length;
170         var data = this.key_file.to_data (out length);
171
172         try {
173             FileUtils.set_contents (path, data, (long) length);
174         } catch (FileError err) {
175             critical (_("Failed to save configuration data to file '%s': %s"),
176                       path,
177                       err.message);
178         }
179     }
180
181     public bool get_enabled (string section) throws GLib.Error {
182         return this.get_bool (section, ENABLED_KEY);
183     }
184
185     public string get_title (string section) throws GLib.Error {
186         return this.get_string (section, TITLE_KEY);
187     }
188
189     public string get_string (string section,
190                               string key) throws GLib.Error {
191         var val = this.key_file.get_string (section, key);
192
193         if (val == null || val == "") {
194             throw new ConfigurationError.NO_VALUE_SET (
195                                         _("No value available for '%s'"),
196                                         key);
197         }
198
199         return val;
200     }
201
202     public Gee.ArrayList<string> get_string_list (string section,
203                                                   string key)
204                                                   throws GLib.Error {
205         var str_list = new Gee.ArrayList<string> ();
206         var strings = this.key_file.get_string_list (section, key);
207
208         foreach (var str in strings) {
209             str_list.add (str);
210         }
211
212         return str_list;
213     }
214
215     public int get_int (string section,
216                         string key,
217                         int    min,
218                         int    max)
219                         throws GLib.Error {
220         int val = this.key_file.get_integer (section, key);
221
222         if (val == 0 || val < min || val > max) {
223             throw new ConfigurationError.VALUE_OUT_OF_RANGE (
224                                         _("Value of '%s' out of range"),
225                                         key);
226         }
227
228         return val;
229     }
230
231     public Gee.ArrayList<int> get_int_list (string section,
232                                             string key)
233                                             throws GLib.Error {
234         var int_list = new Gee.ArrayList<int> ();
235         var ints = this.key_file.get_integer_list (section, key);
236
237         foreach (var num in ints) {
238             int_list.add (num);
239         }
240
241         return int_list;
242     }
243
244     public bool get_bool (string section,
245                           string key)
246                           throws GLib.Error {
247         return this.key_file.get_boolean (section, key);
248     }
249
250     public void set_string (string section,
251                             string key,
252                             string value) {
253         this.key_file.set_string (section, key, value);
254     }
255
256     public void set_string_list (string                section,
257                                  string                key,
258                                  Gee.ArrayList<string> str_list) {
259         // GConf requires us to provide it GLib.SList
260         var strings = new string[str_list.size];
261         int i = 0;
262
263         foreach (var str in str_list) {
264             if (str != "") {
265                 strings[i++] = str;
266             }
267         }
268
269         this.key_file.set_string_list (section, key, strings);
270     }
271
272     public void set_int (string section,
273                          string key,
274                          int    value) {
275         this.key_file.set_integer (section, key, value);
276     }
277
278     public void set_bool (string section,
279                           string key,
280                           bool   value) {
281         this.key_file.set_boolean (section, key, value);
282     }
283
284     private void enable_upnp (bool enable) {
285         var dest_dir = Path.build_filename (Environment.get_user_config_dir (),
286                                              "autostart");
287         try {
288             this.ensure_dir_exists (dest_dir);
289
290             var dest_path = Path.build_filename (dest_dir, "rygel.desktop");
291             var dest = File.new_for_path (dest_path);
292
293             if (enable) {
294                 // Creating the proxy starts the service
295                 DBusInterface rygel_proxy = Bus.get_proxy_sync
296                                         (BusType.SESSION,
297                                          DBusInterface.SERVICE_NAME,
298                                          DBusInterface.OBJECT_PATH);
299                 // Just to satisfy valac
300                 rygel_proxy.get_object_path ();
301
302                 // Then symlink the desktop file to user's autostart dir
303                 var source_path = Path.build_filename (BuildConfig.DESKTOP_DIR,
304                                                        "rygel.desktop");
305                 try {
306                     dest.make_symbolic_link (source_path, null);
307                 } catch (IOError.EXISTS err) {}
308
309                 this.set_bool ("general", ENABLED_KEY, true);
310             } else {
311                 // Stop service only if already running
312                 if (this.get_enabled ("general")) {
313                     // Create proxy to Rygel
314                     DBusInterface rygel_proxy = Bus.get_proxy_sync
315                                         (BusType.SESSION,
316                                          DBusInterface.SERVICE_NAME,
317                                          DBusInterface.OBJECT_PATH);
318
319                     rygel_proxy.shutdown ();
320                 }
321
322                 // Then delete the symlink from user's autostart dir
323                 try {
324                     dest.delete (null);
325                 } catch (IOError.NOT_FOUND err) {}
326
327                 this.set_bool ("general", ENABLED_KEY, false);
328             }
329         } catch (GLib.Error err) {
330             string message;
331
332             if (enable) {
333                 message = _("Failed to start Rygel service: %s");
334             } else {
335                 message = _("Failed to stop Rygel service: %s");
336             }
337
338             warning (message, err.message);
339         }
340     }
341
342     private void ensure_dir_exists (string dir_path) throws GLib.Error {
343         var dir = File.new_for_path (dir_path);
344
345         try {
346             dir.make_directory (null);
347         } catch (IOError.EXISTS err) { /* Thats OK */ }
348     }
349 }
350