Adding first code drop
[demorecorder] / src / ApplicationSettings.vala
1 /*  Demo Recorder for MAEMO 5
2 *   Copyright (C) 2010 Dru Moore <usr@dru-id.co.uk>
3 *   This program is free software; you can redistribute it and/or modify
4 *   it under the terms of the GNU General Public License version 2,
5 *   or (at your option) any later version, as published by the Free
6 *   Software Foundation
7 *
8 *   This program is distributed in the hope that it will be useful,
9 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
10 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 *   GNU General Public License for more details
12 *
13 *   You should have received a copy of the GNU General Public
14 *   License along with this program; if not, write to the
15 *   Free Software Foundation, Inc.,
16 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17 */
18 namespace IdWorks {
19
20 public class ApplicationSettings {
21
22   public enum OpenAction {
23     LAST_PROJECT,
24     NEW_PROJECT,
25     RECENT_PROJECTS,
26     NAMED_PROJECT;
27     
28     public static OpenAction from_label(string val) {
29       switch (val) {
30         case "Last open project":
31           return LAST_PROJECT;
32         case "New project":
33           return NEW_PROJECT;
34         case "Recent projects list":
35           return RECENT_PROJECTS;
36         case "Specified project":
37           return NAMED_PROJECT;
38         default:
39           return LAST_PROJECT;
40       }
41     }
42     public static OpenAction from_name(string val) {
43       switch (val) {
44         case "LAST_PROJECT":
45           return LAST_PROJECT;
46         case "NEW_PROJECT":
47           return NEW_PROJECT;
48         case "RECENT_PROJECTS":
49           return RECENT_PROJECTS;
50         case "NAMED_PROJECT":
51           return NAMED_PROJECT;
52         default:
53           return LAST_PROJECT;
54       }
55     }
56     public static string to_label(OpenAction val) {
57       switch (val) {
58         case LAST_PROJECT:
59           return "Last open project";
60         case NEW_PROJECT:
61           return "New project";
62         case RECENT_PROJECTS:
63           return "Recent projects list";
64         case NAMED_PROJECT:
65           return "Specified project";
66         default:
67           return "Last open project";
68       }
69     }
70     public static string to_name(OpenAction val) {
71       switch(val) {
72         case LAST_PROJECT:
73           return "LAST_PROJECT";
74         case NEW_PROJECT:
75           return "NEW_PROJECT";
76         case RECENT_PROJECTS:
77           return "RECENT_PROJECTS";
78         case NAMED_PROJECT:
79           return "NAMED_PROJECT";
80         default:
81           return "LAST_PROJECT";
82       }
83     }
84   }
85   public enum CloseAction {
86     AUTO_SAVE_PROJECT,
87     PROMPT_SAVE_PROJECT,
88     DO_NOTHING;
89     
90     public static CloseAction from_label(string val) {
91       switch (val) {
92         case "Auto-save the project":
93           return AUTO_SAVE_PROJECT; 
94         case "Prompt to save the project":
95           return PROMPT_SAVE_PROJECT;
96         case "Do nothing":
97           return DO_NOTHING;
98         default:
99           return AUTO_SAVE_PROJECT;
100       }
101     }
102     public static CloseAction from_name(string val) {
103       switch (val) {
104         case "AUTO_SAVE_PROJECT":
105           return AUTO_SAVE_PROJECT;
106         case "PROMPT_SAVE_PROJECT":
107           return PROMPT_SAVE_PROJECT;
108         case "DO_NOTHING":
109           return DO_NOTHING;
110         default:
111           return PROMPT_SAVE_PROJECT;
112       }
113     }
114     public static string to_label(CloseAction val) {
115       switch (val) {
116         case AUTO_SAVE_PROJECT:
117           return "Auto-save the project";
118         case PROMPT_SAVE_PROJECT:
119           return "Prompt to save the project";
120         case DO_NOTHING:
121           return "Do nothing";
122         default:
123           return "Auto-save the project";
124       }
125     } 
126     public static string to_name(CloseAction val) {
127       switch(val) {
128         case AUTO_SAVE_PROJECT:
129           return "AUTO_SAVE_PROJECT";
130         case PROMPT_SAVE_PROJECT:
131           return "PROMPT_SAVE_PROJECT";
132         case DO_NOTHING:
133           return "DO_NOTHING";
134         default:
135           return "PROMPT_SAVE_PROJECT";
136       }
137     }
138   }
139   public enum AddTrackAction {
140     SET_ACTIVE,
141     SET_SOLO,
142     SET_INACTIVE,
143     SET_MUTE;
144     
145     public static AddTrackAction from_label(string val) {
146       switch (val) {
147         case "Enable track":
148           return SET_ACTIVE;
149         case "Solo track":
150           return SET_SOLO;
151         case "Disable track":
152           return SET_INACTIVE;
153         case "Mute track":
154           return SET_MUTE;
155         default:
156           return SET_ACTIVE;
157       }
158     }
159     public static AddTrackAction from_name(string val) {
160       switch (val) {
161         case "SET_ACTIVE":
162           return SET_ACTIVE;
163         case "SET_SOLO":
164           return SET_SOLO;
165         case "SET_INACTIVE":
166           return SET_INACTIVE;
167         case "SET_MUTE":
168           return SET_MUTE;
169         default:
170           return SET_ACTIVE;
171       }
172     }
173     public static string to_label(AddTrackAction val) {
174       switch (val) {
175         case SET_ACTIVE:
176           return "Enable track";
177         case SET_SOLO:
178           return "Solo track";
179         case SET_INACTIVE:
180           return "Disable track";
181         case SET_MUTE:
182           return "Mute track";
183         default:
184           return "Enable track";
185       }
186     }
187     public static string to_name(AddTrackAction val) {
188       switch(val) {
189         case SET_ACTIVE:
190           return "SET_ACTIVE";
191         case SET_SOLO:
192           return "SET_SOLO";
193         case SET_INACTIVE:
194           return "SET_INACTIVE";
195         case SET_MUTE:
196           return "SET_MUTE";
197         default:
198           return "SET_ACTIVE";
199       }
200     }
201   }
202   public enum BounceTracksAction {
203     SET_SOURCE_INACTIVE,
204     SET_SOURCE_MUTE,
205     SET_TARGET_SOLO,
206     SET_TARGET_INACTIVE,
207     SET_TARGET_MUTE;
208     
209     public static BounceTracksAction from_label(string val) {
210       switch (val) {
211         case "Disable source tracks":
212           return SET_SOURCE_INACTIVE;
213         case "Mute source tracks":
214           return SET_SOURCE_MUTE;
215         case "Solo new track":
216           return SET_TARGET_SOLO;
217         case "Disable new track":
218           return SET_TARGET_INACTIVE;
219         case "Mute new track":
220           return SET_TARGET_MUTE;
221         default:
222           return SET_SOURCE_INACTIVE;
223       }
224     }
225     public static BounceTracksAction from_name(string val) {
226       switch (val) {
227         case "SET_SOURCE_INACTIVE":
228           return SET_SOURCE_INACTIVE;
229         case "SET_SOURCE_MUTE":
230           return SET_SOURCE_MUTE;
231         case "SET_TARGET_SOLO":
232           return SET_TARGET_SOLO;
233         case "SET_TARGET_INACTIVE":
234           return SET_TARGET_INACTIVE;
235         case "SET_TARGET_MUTE":
236           return SET_TARGET_MUTE;
237         default:
238           return SET_SOURCE_INACTIVE;
239       }
240     }
241     public static string to_label(BounceTracksAction val) {
242       switch (val) {
243         case SET_SOURCE_INACTIVE:
244           return "Disable source tracks";
245         case SET_SOURCE_MUTE:
246           return "Mute source tracks";
247         case SET_TARGET_SOLO:
248           return "Solo new track";
249         case SET_TARGET_INACTIVE:
250           return "Disable new track";
251         case SET_TARGET_MUTE:
252           return "Mute new track";
253         default:
254           return "Disable source tracks";
255       }
256     }
257     public static string to_name(BounceTracksAction val) {
258       switch (val) {
259         case SET_SOURCE_INACTIVE:
260           return "SET_SOURCE_INACTIVE";
261         case SET_SOURCE_MUTE:
262           return "SET_SOURCE_MUTE";
263         case SET_TARGET_SOLO:
264           return "SET_TARGET_SOLO";
265         case SET_TARGET_INACTIVE:
266           return "SET_TARGET_INACTIVE";
267         case SET_TARGET_MUTE:
268           return "SET_TARGET_MUTE";
269         default:
270           return "SET_SOURCE_INACTIVE";
271       }
272     }
273   }
274   public enum RemoveTrackAction {
275     PROMPT,
276     DELETE_FILE,
277     PRESERVE_FILE;
278     
279     public static RemoveTrackAction from_label(string val) {
280       switch (val) {
281         case "Prompt with choices":
282           return PROMPT;
283         case "Delete the file":
284           return DELETE_FILE;
285         case "Preserve the file":
286           return PRESERVE_FILE;
287         default:
288           return PROMPT;
289       }
290     }
291     public static RemoveTrackAction from_name(string val) {
292       switch (val) {
293         case "PROMPT":
294           return PROMPT;
295         case "DELETE_FILE":
296           return DELETE_FILE;
297         case "PRESERVE_FILE":
298           return PRESERVE_FILE;
299         default:
300           return PROMPT;
301       }
302     }
303     public static string to_label(RemoveTrackAction val) {
304       switch (val) {
305         case PROMPT:
306           return "Prompt with choices";
307         case DELETE_FILE:
308           return "Delete the file";
309         case PRESERVE_FILE:
310           return "Preserve the file";
311         default:
312           return "Prompt with choices";
313       }
314     }
315     public static string to_name(RemoveTrackAction val) {
316       switch(val) {
317         case PROMPT:
318           return "PROMPT";
319         case DELETE_FILE:
320           return "DELETE_FILE";
321         case PRESERVE_FILE:
322           return "PRESERVE_FILE";
323         default:
324           return "PROMPT";
325       }
326     }
327   }
328   public enum MixdownAction {
329     NONE,
330     PLAY_TARGET;
331     
332     public static MixdownAction from_label(string val) {
333       switch (val) {
334         case "Do nothing":
335           return NONE;
336         case "Play mix":
337           return PLAY_TARGET;
338         default:
339           return NONE;
340       }
341     }
342     public static MixdownAction from_name(string val) {
343       switch (val) {
344         case "NONE":
345           return NONE;
346         case "PLAY_TARGET":
347           return PLAY_TARGET;
348         default:
349           return NONE;
350       }
351     }
352     public static string to_label(MixdownAction val) {
353       switch (val) {
354         case NONE:
355           return "Do nothing";
356         case PLAY_TARGET:
357           return "Play mix";
358         default:
359           return "Do nothing";
360       }
361     }
362     public static string to_name(MixdownAction val) {
363       switch(val) {
364         case NONE:
365           return "NONE";
366         case PLAY_TARGET:
367           return "PLAY_TARGET";
368         default:
369           return "NONE";
370       }
371     }
372   }
373   
374   public string working_directory {public get; public set;}
375   public string last_project_name {public get; public set;}
376   public string last_project_location {public get; public set;}
377   public string named_project_name {public get; public set;}
378   public string named_project_location {public get; public set;}
379   public string[] recent_project_names {public get; public set;}
380   public string[] recent_project_locations {public get; public set;}
381   public uint64 delay_max_delay {public get; public set;}
382   public bool mixdown_enable_lamenc {public get; public set;}
383   public bool mixdown_enable_mpegaudio {public get; public set;}
384   public OpenAction open_action {public get; public set;}
385   public CloseAction close_action {public get; public set;}
386   public AddTrackAction add_track_action {public get; public set;}
387   public BounceTracksAction bounce_tracks_action {public get; public set;}
388   public RemoveTrackAction remove_track_action {public get; public set;}
389   public MixdownAction mixdown_action {public get; public set;}
390   
391   public ApplicationSettings() {
392     working_directory = Environment.get_home_dir() + "/DemoRecordings";
393     last_project_name = "";
394     last_project_location = "";
395     named_project_name = "";
396     named_project_location = "";
397     recent_project_names = new string[]{"","","","","","","","","",""};
398     recent_project_locations = new string[]{"","","","","","","","","",""};
399     delay_max_delay = Time.Nanoseconds.SECOND / 2;
400     mixdown_enable_lamenc = false;
401     mixdown_enable_mpegaudio = false;
402     open_action = OpenAction.LAST_PROJECT;
403     close_action = CloseAction.PROMPT_SAVE_PROJECT;
404     add_track_action = AddTrackAction.SET_ACTIVE;
405     bounce_tracks_action = BounceTracksAction.SET_SOURCE_INACTIVE;
406     remove_track_action = RemoveTrackAction.PROMPT;
407   }
408   
409   public static ApplicationSettings load_settings(string filename, string version, out string errors) {
410     errors = "";
411     ApplicationSettings settings = new ApplicationSettings();
412     bool success = false;
413     // prepare the Xml Parser
414     Xml.Parser.init();
415     // load the document
416     Xml.Doc* doc = Xml.Parser.parse_file(filename);
417     if (null != doc) {
418       // load the root node
419       Xml.Node* root = doc->get_root_element();
420       if (null != root) {
421         // check element is ProjectSettings
422         if ("ApplicationSettings" == root->name) {
423           // check version
424           string? doc_version = XmlHelpers.get_node_attribute(root, "version");
425           if (null != doc_version && version == doc_version) {
426             // looking good let's get parsing.
427             try {
428               settings.from_xml_node(root);
429               success = true;
430             }
431             catch (GLib.Error ex) {
432               errors = "ApplicationSettings parser threw an error.";
433             }
434             finally {
435               // no op
436             }
437           }
438           else {
439             errors = "Incorrect version or unversioned document.";
440           }
441         }
442         else {
443           errors = "Not a valid settings file.";
444         }
445       }
446       else {
447         errors = "No root node found.";
448       }
449       // clean up
450       delete doc;
451     }
452     else {
453       errors = "Couldn't parse file as valid XML.";
454     }
455     // clean up the parser
456     Xml.Parser.cleanup();
457     return (success) ? settings : null;
458   }
459   
460   public static bool save_settings(string filename, ApplicationSettings settings, ref string errors) {
461     //stdout.printf("save settings called\n");
462     //stdout.flush();
463     string contents = settings.to_xml_string();
464     errors = "";
465     if (0 < contents.length) {
466       contents = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + contents;
467       //stdout.printf(contents);
468       //stdout.printf("\n" + filename + "\n");
469       //stdout.flush();
470       try {
471         if (FileUtils.set_contents(filename, contents, contents.length)) {
472           //stdout.printf("save settings worked\n");
473           //stdout.flush();
474           return true;
475         }
476         else {
477           errors = "Couldn't save the settings file!\n%s".printf("FILE ERROR");
478         }
479       }
480       catch (FileError ex) {
481         errors = "Couldn't save the settings file!\n%s".printf("FILE ERROR");
482       }
483     }
484     else {
485       errors = "Couldn't serialize the settings!.";
486     }
487     //stdout.printf("save settings failed\n");
488     //stdout.flush();
489     return false;
490   }
491   
492   private string to_xml_string() {
493     return ("<ApplicationSettings version=\"1.0\">\n" +
494             "<working_directory type=\"string\"><![CDATA[%s]]></working_directory>\n" +
495             "<last_project_name type=\"string\"><![CDATA[%s]]></last_project_name>\n" +
496             "<last_project_location type=\"string\"><![CDATA[%s]]></last_project_location>\n" +
497             "<named_project_name type=\"string\"><![CDATA[%s]]></named_project_name>\n" +
498             "<named_project_location type=\"string\"><![CDATA[%s]]></named_project_location>\n" +
499             "<recent_project_names type=\"CDL\"><![CDATA[%s]]></recent_project_names>\n" +
500             "<recent_project_locations type=\"CDL\"><![CDATA[%s]]></recent_project_locations>\n" +
501             "<delay_max_delay type=\"uint64\">%llu</delay_max_delay>\n" +
502             "<mixdown_enable_lamenc type=\"bool\">%s</mixdown_enable_lamenc>\n" +
503             "<mixdown_enable_mpegaudio type=\"bool\">%s</mixdown_enable_mpegaudio>\n" +
504             "<open_action type=\"OpenAction\">%s</open_action>\n" +
505             "<close_action type=\"CloseAction\">%s</close_action>\n" +
506             "<add_track_action type=\"AddTrackAction\">%s</add_track_action>\n" +
507             "<bounce_tracks_action type=\"BounceTracksAction\">%s</bounce_tracks_action>\n" +
508             "<remove_track_action type=\"RemoveTrackAction\">%s</remove_track_action>\n" +
509             "</ApplicationSettings>\n").printf(
510             working_directory,
511             last_project_name,
512             last_project_location,
513             "",
514             "",
515             "",
516             "",
517             delay_max_delay,
518             mixdown_enable_lamenc.to_string(),
519             mixdown_enable_mpegaudio.to_string(),
520             OpenAction.to_name(open_action),
521             CloseAction.to_name(close_action),
522             AddTrackAction.to_name(add_track_action),
523             BounceTracksAction.to_name(bounce_tracks_action),
524             RemoveTrackAction.to_name(remove_track_action)
525             );
526   }
527   
528   private void from_xml_node(Xml.Node* node) {
529     // Loop over the passed node's children
530     for (Xml.Node* iter = node->children; iter != null; iter = iter->next) {
531       // Spaces between tags are also nodes, discard them
532       if (iter->type != Xml.ElementType.ELEMENT_NODE) {
533         continue;
534       }
535       // Get the node's name
536       string node_name = iter->name;
537       // Get the nodes type
538       string? type = XmlHelpers.get_node_attribute(iter, "type");
539       // Get the node's content with <tags> stripped
540       if (null != type) {
541         // check the type
542         switch(type) {
543           case "string":
544             switch(node_name) {
545               case "working_directory":
546                 this.working_directory = iter->get_content();
547                 break;
548               case "last_project_name":
549                 this.last_project_name = iter->get_content();
550                 break;
551               case "last_project_location":
552                 this.last_project_location = iter->get_content();
553                 break;
554               case "named_project_name":
555                 this.named_project_name = iter->get_content();
556                 break;
557               case "named_project_location":
558                 this.named_project_location = iter->get_content();
559                 break;
560               default:
561                 break;
562             }
563             break;
564           case "bool":
565             switch(node_name) {
566               case "mixdown_enable_lamenc":
567                 this.mixdown_enable_lamenc = iter->get_content().to_bool();
568                 break;
569               case "mixdown_enable_mpegaudio":
570                 this.mixdown_enable_mpegaudio = iter->get_content().to_bool();
571                 break;
572               default:
573                 break;
574             }
575             break;
576           case "uint64":
577             switch(node_name) {
578               case "delay_max_delay":
579                 this.delay_max_delay = iter->get_content().to_uint64();
580                 break;
581               default:
582                 break;
583             }
584             break;
585           case "CDL":
586             switch(node_name) {
587               case "recent_project_names":
588                 /// TODO this.recent_project_names = iter->get_content().to_uint64();
589                 break;
590               case "recent_project_locations":
591                 /// TODO this.recent_project_locations = iter->get_content().to_uint64();
592                 break;
593               default:
594                 break;
595             }
596             break;
597           case "OpenAction":
598             switch(node_name) {
599               case "open_action":
600                 this.open_action = OpenAction.from_name(iter->get_content());
601                 break;
602               default:
603                 break;
604             }
605             break;
606           case "CloseAction":
607             switch(node_name) {
608               case "close_action":
609                 this.close_action = CloseAction.from_name(iter->get_content());
610                 break;
611               default:
612                 break;
613             }
614             break;
615           case "AddTrackAction":
616             switch(node_name) {
617               case "add_track_action":
618                 this.add_track_action = AddTrackAction.from_name(iter->get_content());
619                 break;
620               default:
621                 break;
622             }
623             break;
624           case "BounceTracksAction":
625             switch(node_name) {
626               case "bounce_tracks_action":
627                 this.bounce_tracks_action = BounceTracksAction.from_name(iter->get_content());
628                 break;
629               default:
630                 break;
631             }
632             break;
633           case "RemoveTrackAction":
634             switch(node_name) {
635               case "remove_track_action":
636                 this.remove_track_action = RemoveTrackAction.from_name(iter->get_content());
637                 break;
638               default:
639                 break;
640             }
641             break;
642           default:
643             continue;
644         }
645       }
646       
647     }
648   }
649
650 }
651
652 }