OSDN Git Service

8f032d819e970167022f8956aa02a5af3648166d
[handbrake-jp/handbrake-jp-git.git] / gtk / src / presets.c
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3  * presets.c
4  * Copyright (C) John Stebbins 2008 <stebbins@stebbins>
5  * 
6  * presets.c is free software.
7  * 
8  * You may redistribute it and/or modify it under the terms of the
9  * GNU General Public License, as published by the Free Software
10  * Foundation; either version 2 of the License, or (at your option)
11  * any later version.
12  * 
13  */
14 #include <glib.h>
15 #include <glib-object.h>
16 #include <glib/gstdio.h>
17 #include <string.h>
18 #include <gtk/gtk.h>
19 #include "settings.h"
20 #include "plist.h"
21 #include "presets.h"
22 #include "values.h"
23
24 //
25 // Internal defaults stored in character arrays and parsed
26 // the same as external settings files.
27 const gchar defaultSettings[] =
28 #include "internal_defaults.h"
29 ;
30 const gchar standardPresets[] =
31 #include "standard_presets.h"
32 ;
33
34 static GValue *presetsPlist = NULL;
35 static GValue *internalPlist = NULL;
36 static GValue *prefsPlist = NULL;
37
38 static GValue*
39 plist_get_dict(GValue *presets, const gchar *name)
40 {
41         if (presets == NULL || name == NULL) return NULL;
42         return ghb_dict_lookup(presets, name);
43 }
44
45 void
46 ghb_set_preset_default(GValue *settings)
47 {
48         gchar *preset;
49         
50         preset = ghb_settings_get_string (settings, "preset");
51         ghb_settings_set_string(settings, "default_preset", preset);
52         ghb_prefs_save(settings);
53         g_free(preset);
54 }
55
56 // Used for sorting dictionaries.
57 gint
58 key_cmp(gconstpointer a, gconstpointer b)
59 {
60         gchar *stra = (gchar*)a;
61         gchar *strb = (gchar*)b;
62
63         return strcmp(stra, strb);
64 }
65
66 gchar*
67 ghb_presets_get_description(const gchar *name)
68 {
69         GValue *pdict;
70         pdict = plist_get_dict(presetsPlist, name);
71         if (pdict == NULL) return g_strdup("");
72         return ghb_value_string(ghb_dict_lookup(pdict, "preset_description"));
73 }
74
75 static const GValue*
76 preset_dict_get_value(
77         GValue *dict,
78         const gchar *key)
79 {
80         const GValue *gval = NULL;
81
82         if (dict)
83         {
84                 gval = ghb_dict_lookup(dict, key);
85         }
86         if (internalPlist == NULL) return NULL;
87         if (gval == NULL)
88         {
89                 dict = plist_get_dict(internalPlist, "Presets");
90                 if (dict == NULL) return NULL;
91                 gval = ghb_dict_lookup(dict, key);
92         }
93         return gval;
94 }
95
96 static const GValue*
97 preset_get_value(
98         const gchar *name,
99         const gchar *key)
100 {
101         GValue *dict;
102
103         dict = plist_get_dict(presetsPlist, name);
104         return preset_dict_get_value(dict, key);
105 }
106
107 GList*
108 ghb_presets_get_names()
109 {
110         GHashTable *dict;
111         GList *names, *link;
112         GList *standard = NULL;
113         GList *custom = NULL;
114
115         if (presetsPlist == NULL) return NULL;
116         dict = g_value_get_boxed(presetsPlist);
117         link = names = g_hash_table_get_keys(dict);
118         while (link)
119         {
120                 gchar *name;
121                 gint ptype;
122
123                 name = (gchar*)link->data;
124                 ptype = ghb_value_int(preset_get_value(name, "preset_type"));
125                 if (ptype)
126                         custom = g_list_append(custom, name);
127                 else
128                         standard = g_list_append(standard, name);
129                 link = link->next;
130         }
131         custom = g_list_sort(custom, key_cmp);
132         standard = g_list_sort(standard, key_cmp);
133         g_list_free(names);
134         names = g_list_concat(standard, custom);
135         return names;
136 }
137
138 gint
139 ghb_preset_flags(const gchar *name)
140 {
141         GValue *dict;
142         const GValue *gval;
143         gint ptype;
144         gint ret = 0;
145
146         dict = plist_get_dict(presetsPlist, name);
147         gval = preset_dict_get_value(dict, "preset_type");
148         if (gval)
149         {
150                 ptype = ghb_value_int(gval);
151                 ret = (ptype != 0 ? PRESET_CUSTOM : 0);
152         }
153         return ret;
154 }
155
156 static void init_settings_from_dict(
157         GValue *dest, GValue *internal, GValue *dict);
158
159 static void
160 init_settings_from_array(
161         GValue *dest, 
162         GValue *internal,
163         GValue *array)
164 {
165         GValue *gval, *val;
166         gint count, ii;
167         
168         count = ghb_array_len(array);
169         // The first element of the internal version is always the 
170         // template for the allowed values
171         gval = ghb_array_get_nth(internal, 0);
172         for (ii = 0; ii < count; ii++)
173         {
174                 val = NULL;
175                 val = ghb_array_get_nth(array, ii);
176                 if (val == NULL)
177                         val = gval;
178                 if (G_VALUE_TYPE(gval) == ghb_dict_get_type())
179                 {
180                         GValue *new_dict;
181                         new_dict = ghb_dict_value_new();
182                         ghb_array_append(dest, new_dict);
183                         if (G_VALUE_TYPE(val) == ghb_dict_get_type())
184                                 init_settings_from_dict(new_dict, gval, val);
185                         else
186                                 init_settings_from_dict(new_dict, gval, gval);
187                 }
188                 else if (G_VALUE_TYPE(gval) == ghb_array_get_type())
189                 {
190                         GValue *new_array;
191                         new_array = ghb_array_value_new(8);
192                         ghb_array_append(dest, new_array);
193                         if (G_VALUE_TYPE(val) == ghb_array_get_type())
194                                 init_settings_from_array(new_array, gval, val);
195                         else
196                                 init_settings_from_array(new_array, gval, gval);
197                 }
198                 else
199                 {
200                         ghb_array_append(dest, val);
201                 }
202         }
203 }
204
205 static void
206 init_settings_from_dict(
207         GValue *dest, 
208         GValue *internal,
209         GValue *dict)
210 {
211         GHashTableIter iter;
212         gchar *key;
213         GValue *gval, *val;
214         
215         ghb_dict_iter_init(&iter, internal);
216         while (g_hash_table_iter_next(&iter, (gpointer*)&key, (gpointer*)&gval))
217         {
218                 val = NULL;
219                 if (dict)
220                         val = ghb_dict_lookup(dict, key);
221                 if (val == NULL)
222                         val = gval;
223                 if (G_VALUE_TYPE(gval) == ghb_dict_get_type())
224                 {
225                         GValue *new_dict;
226                         new_dict = ghb_dict_value_new();
227                         ghb_settings_take_value(dest, key, new_dict);
228                         if (G_VALUE_TYPE(val) == ghb_dict_get_type())
229                                 init_settings_from_dict(new_dict, gval, val);
230                         else
231                                 init_settings_from_dict(new_dict, gval, gval);
232                 }
233                 else if (G_VALUE_TYPE(gval) == ghb_array_get_type())
234                 {
235                         GValue *new_array;
236                         new_array = ghb_array_value_new(8);
237                         ghb_settings_take_value(dest, key, new_array);
238                         if (G_VALUE_TYPE(val) == ghb_array_get_type())
239                                 init_settings_from_array(new_array, gval, val);
240                         else
241                                 init_settings_from_array(new_array, gval, gval);
242         
243                 }
244                 else
245                 {
246                         ghb_settings_set_value(dest, key, val);
247                 }
248         }
249 }
250
251 void
252 init_ui_from_dict(
253         signal_user_data_t *ud, 
254         GValue *internal,
255         GValue *dict)
256 {
257         GHashTableIter iter;
258         gchar *key;
259         GValue *gval, *val;
260         
261         ghb_dict_iter_init(&iter, internal);
262         while (g_hash_table_iter_next(&iter, (gpointer*)&key, (gpointer*)&gval))
263         {
264                 val = NULL;
265                 if (dict)
266                         val = ghb_dict_lookup(dict, key);
267                 if (val == NULL)
268                         val = gval;
269                 ghb_ui_update(ud, key, val);
270         }
271 }
272
273 static void
274 preset_to_ui(signal_user_data_t *ud, GValue *dict)
275 {
276         g_debug("preset_to_ui()\n");
277         // Initialize the ui from presets file.
278         GValue *internal;
279
280         // Get key list from internal default presets.  This way we do not
281         // load any unknown keys.
282         if (internalPlist == NULL) return;
283         internal = plist_get_dict(internalPlist, "Presets");
284         // Setting a ui widget will cause the corresponding setting
285         // to be set, but it also triggers a callback that can 
286         // have the side effect of using other settings values
287         // that have not yet been set.  So set *all* settings first
288         // then update the ui.
289         init_settings_from_dict(ud->settings, internal, dict);
290         init_ui_from_dict(ud, internal, dict);
291
292         if (ghb_settings_get_boolean(ud->settings, "allow_tweaks"))
293         {
294                 const GValue *gval;
295                 gval = preset_dict_get_value(dict, "deinterlace");
296                 if (gval)
297                 {
298                         ghb_ui_update(ud, "tweak_deinterlace", gval);
299                 }
300                 gval = preset_dict_get_value(dict, "denoise");
301                 if (gval)
302                 {
303                         ghb_ui_update(ud, "tweak_denoise", gval);
304                 }
305         }
306 }
307
308 void
309 ghb_set_preset(signal_user_data_t *ud, const gchar *name)
310 {
311         GValue *dict;
312         
313         g_debug("ghb_set_preset() %s\n", name);
314         if (name == NULL)
315         {
316                 GList *presets;
317                 // Try to get the first preset
318                 presets = ghb_presets_get_names();
319                 if (presets)
320                 {
321                         name = (const gchar*)presets->data;
322                         g_list_free(presets);
323                 }
324         }
325         dict = plist_get_dict(presetsPlist, name);
326         if (dict == NULL || name == NULL)
327         {
328                 preset_to_ui(ud, NULL);
329         }
330         else
331         {
332                 preset_to_ui(ud, dict);
333                 ghb_settings_set_string(ud->settings, "preset", name);
334         }
335 }
336
337 void
338 ghb_update_from_preset(
339         signal_user_data_t *ud, 
340         const gchar *name, 
341         const gchar *key)
342 {
343         const GValue *gval;
344         
345         g_debug("ghb_update_from_preset() %s %s", name, key);
346         if (name == NULL) return;
347         gval = preset_get_value(name, key);
348         if (gval != NULL)
349         {
350                 ghb_ui_update(ud, key, gval);
351         }
352 }
353
354 static void
355 store_plist(GValue *plist, const gchar *name)
356 {
357         const gchar *dir;
358         gchar *config;
359         FILE *file;
360
361         dir = g_get_user_config_dir();
362         config = g_strdup_printf ("%s/ghb", dir);
363         if (!g_file_test(config, G_FILE_TEST_IS_DIR))
364         {
365                 g_mkdir (config, 0755);
366         }
367         g_free(config);
368         config = g_strdup_printf ("%s/ghb/%s", dir, name);
369         file = g_fopen(config, "w");
370         g_free(config);
371         ghb_plist_write(file, plist);
372         fclose(file);
373 }
374
375 static GValue*
376 load_plist(const gchar *name)
377 {
378         const gchar *dir;
379         gchar *config;
380         FILE *file;
381         GValue *plist = NULL;
382
383         dir = g_get_user_config_dir();
384         config = g_strdup_printf ("%s/ghb/%s", dir, name);
385         if (g_file_test(config, G_FILE_TEST_IS_REGULAR))
386         {
387                 file = g_fopen(config, "r");
388                 plist = ghb_plist_parse_file(file);
389         }
390         g_free(config);
391         return plist;
392 }
393
394 static void
395 remove_plist(const gchar *name)
396 {
397         const gchar *dir;
398         gchar *config;
399
400         dir = g_get_user_config_dir();
401         config = g_strdup_printf ("%s/ghb/%s", dir, name);
402         if (g_file_test(config, G_FILE_TEST_IS_REGULAR))
403         {
404                 g_unlink(config);
405         }
406         g_free(config);
407 }
408
409 static gboolean prefs_initializing = FALSE;
410
411 void
412 ghb_prefs_to_ui(signal_user_data_t *ud)
413 {
414         const GValue *gval;
415         gchar *key;
416         gchar *str;
417         GValue *internal, *dict;
418         GHashTableIter iter;
419         
420
421         prefs_initializing = TRUE;
422
423         // Setting a ui widget will cause the corresponding setting
424         // to be set, but it also triggers a callback that can 
425         // have the side effect of using other settings values
426         // that have not yet been set.  So set *all* settings first
427         // then update the ui.
428         internal = plist_get_dict(internalPlist, "Initialization");
429         ghb_dict_iter_init(&iter, internal);
430         while (g_hash_table_iter_next(&iter, (gpointer*)&key, (gpointer*)&gval))
431         {
432                 ghb_ui_update(ud, key, gval);
433         }
434
435         dict = plist_get_dict(prefsPlist, "Preferences");
436         internal = plist_get_dict(internalPlist, "Preferences");
437         ghb_dict_iter_init(&iter, internal);
438         while (g_hash_table_iter_next(&iter, (gpointer*)&key, (gpointer*)&gval))
439     {
440                 const GValue *value = NULL;
441                 if (dict)
442                         value = ghb_dict_lookup(dict, key);
443                 if (value == NULL)
444                         value = gval;
445                 ghb_settings_set_value(ud->settings, key, value);
446     }
447         internal = plist_get_dict(internalPlist, "Preferences");
448         ghb_dict_iter_init(&iter, internal);
449         while (g_hash_table_iter_next(&iter, (gpointer*)&key, (gpointer*)&gval))
450         {
451                 const GValue *value = NULL;
452                 if (dict)
453                         value = ghb_dict_lookup(dict, key);
454                 if (value == NULL)
455                         value = gval;
456                 ghb_ui_update(ud, key, value);
457         }
458         const GValue *val;
459         val = ghb_settings_get_value(ud->settings, "show_presets");
460         ghb_ui_update(ud, "show_presets", val);
461         if (ghb_settings_get_boolean(ud->settings, "hbfd_feature"))
462         {
463                 GtkAction *action;
464                 val = ghb_settings_get_value(ud->settings, "hbfd");
465                 ghb_ui_update(ud, "hbfd", val);
466                 action = GHB_ACTION (ud->builder, "hbfd");
467                 gtk_action_set_visible(action, TRUE);
468         }
469         else
470         {
471                 ghb_ui_update(ud, "hbfd", ghb_int64_value(0));
472         }
473         gval = ghb_settings_get_value(ud->settings, "default_source");
474         ghb_settings_set_value (ud->settings, "source", gval);
475         str = ghb_settings_get_string(ud->settings, "destination_dir");
476
477         gchar *path = g_strdup_printf ("%s/new_video.mp4", str);
478         ghb_ui_update(ud, "destination", ghb_string_value(path));
479         g_free(str);
480         g_free(path);
481
482         prefs_initializing = FALSE;
483 }
484
485 void
486 ghb_prefs_save(GValue *settings)
487 {
488         GValue *dict;
489         GValue *pref_dict;
490         GHashTableIter iter;
491         gchar *key;
492         const GValue *value;
493         
494         if (prefs_initializing) return;
495         dict = plist_get_dict(internalPlist, "Preferences");
496         if (dict == NULL) return;
497         pref_dict = plist_get_dict(prefsPlist, "Preferences");
498         if (pref_dict == NULL) return;
499         ghb_dict_iter_init(&iter, dict);
500     while (g_hash_table_iter_next(&iter, (gpointer*)&key, (gpointer*)&value))
501     {
502             value = ghb_settings_get_value(settings, key);
503             if (value != NULL)
504             {
505                         ghb_dict_insert(pref_dict, g_strdup(key), ghb_value_dup(value));
506             }
507         }
508     store_plist(prefsPlist, "preferences");
509 }
510
511 void
512 ghb_pref_save(GValue *settings, const gchar *key)
513 {
514         const GValue *value;
515         
516         if (prefs_initializing) return;
517         value = ghb_settings_get_value(settings, key);
518         if (value != NULL)
519         {
520                 GValue *dict;
521                 dict = plist_get_dict(prefsPlist, "Preferences");
522                 if (dict == NULL) return;
523                 ghb_dict_insert(dict, g_strdup(key), ghb_value_dup(value));
524                 store_plist(prefsPlist, "preferences");
525         }
526 }
527
528 void
529 ghb_settings_init(signal_user_data_t *ud)
530 {
531         GValue *internal;
532         GHashTableIter iter;
533         gchar *key;
534         GValue *gval;
535
536
537         g_debug("ghb_settings_init");
538         prefs_initializing = TRUE;
539
540         internalPlist = ghb_plist_parse(defaultSettings, sizeof(defaultSettings)-1);
541         // Setting a ui widget will cause the corresponding setting
542         // to be set, but it also triggers a callback that can 
543         // have the side effect of using other settings values
544         // that have not yet been set.  So set *all* settings first
545         // then update the ui.
546         internal = plist_get_dict(internalPlist, "Initialization");
547         ghb_dict_iter_init(&iter, internal);
548         while (g_hash_table_iter_next(&iter, (gpointer*)&key, (gpointer*)&gval))
549         {
550                 ghb_settings_set_value(ud->settings, key, gval);
551         }
552
553         internal = plist_get_dict(internalPlist, "Presets");
554         ghb_dict_iter_init(&iter, internal);
555         while (g_hash_table_iter_next(&iter, (gpointer*)&key, (gpointer*)&gval))
556         {
557                 ghb_settings_set_value(ud->settings, key, gval);
558         }
559
560         internal = plist_get_dict(internalPlist, "Preferences");
561         ghb_dict_iter_init(&iter, internal);
562         while (g_hash_table_iter_next(&iter, (gpointer*)&key, (gpointer*)&gval))
563         {
564                 ghb_settings_set_value(ud->settings, key, gval);
565         }
566         prefs_initializing = FALSE;
567 }
568
569 void
570 ghb_prefs_load(signal_user_data_t *ud)
571 {
572         GValue *dict, *internal;
573         GHashTableIter iter;
574         gchar *key;
575         GValue *gval;
576         
577         g_debug("ghb_prefs_load");
578         prefsPlist = load_plist("preferences");
579         if (prefsPlist == NULL)
580                 prefsPlist = ghb_dict_value_new();
581         dict = plist_get_dict(prefsPlist, "Preferences");
582         internal = plist_get_dict(internalPlist, "Preferences");
583     if (dict == NULL && internal)
584     {
585                 dict = ghb_dict_value_new();
586                 ghb_dict_insert(prefsPlist, g_strdup("Preferences"), dict);
587
588         // Get defaults from internal defaults 
589                 ghb_dict_iter_init(&iter, internal);
590                 while (g_hash_table_iter_next(&iter, (gpointer*)&key, (gpointer*)&gval))
591         {
592                         ghb_dict_insert(dict, g_strdup(key), ghb_value_dup(gval));
593         }
594                 const gchar *dir = g_get_user_special_dir (G_USER_DIRECTORY_VIDEOS);
595                 ghb_dict_insert(dict, 
596                         g_strdup("destination_dir"), ghb_value_dup(ghb_string_value(dir)));
597                 store_plist(prefsPlist, "preferences");
598     }
599 }
600
601 void
602 ghb_presets_reload(signal_user_data_t *ud)
603 {
604         GValue *std_dict, *dict;
605         GHashTableIter std_iter;
606
607         g_debug("ghb_presets_reload()\n");
608         std_dict = ghb_plist_parse(standardPresets, sizeof(standardPresets)-1);
609         if (std_dict == NULL) return;
610
611         // Merge the keyfile contents into our presets
612         gchar *name;
613         GValue *orig_dict;
614
615         ghb_dict_iter_init(&std_iter, std_dict);
616         while (g_hash_table_iter_next(&std_iter, (gpointer*)&name, (gpointer*)&orig_dict))
617         {
618                 GHashTableIter iter;
619                 gchar *key;
620                 GValue *value;
621
622                 dict = ghb_dict_value_new();
623                 ghb_dict_insert(presetsPlist, g_strdup(name), dict);
624                 ghb_dict_iter_init(&iter, orig_dict);
625                 while (g_hash_table_iter_next(&iter, (gpointer*)&key, (gpointer*)&value))
626                 {
627                         ghb_dict_insert(dict, g_strdup(key), ghb_value_dup(value));
628                 }
629         }
630         ghb_value_free(std_dict);
631         store_plist(presetsPlist, "presets");
632 }
633
634 static void
635 presets_store()
636 {
637         g_debug("presets_store ()\n");
638         store_plist(presetsPlist, "presets");
639 }
640
641 void
642 ghb_save_queue(GValue *queue)
643 {
644         store_plist(queue, "queue");
645 }
646
647 GValue*
648 ghb_load_queue()
649 {
650         return load_plist("queue");
651 }
652
653 void
654 ghb_remove_queue_file()
655 {
656         remove_plist("queue");
657 }
658
659 void
660 ghb_presets_load()
661 {
662         presetsPlist = load_plist("presets");
663         if (presetsPlist == NULL)
664         {
665                 presetsPlist = ghb_plist_parse(
666                         standardPresets, sizeof(standardPresets)-1);
667                 presets_store();
668         }
669 }
670
671 void
672 ghb_settings_save(signal_user_data_t *ud, const gchar *name)
673 {
674         GValue *dict, *internal;
675         GHashTableIter iter;
676         gchar *key;
677         GValue *value;
678         gboolean autoscale;
679
680         if (internalPlist == NULL) return;
681         if (ghb_settings_get_boolean(ud->settings, "allow_tweaks"))
682         {
683                 gchar *str;
684                 str = ghb_settings_get_string(ud->settings, "tweak_deinterlace");
685                 if (str)
686                 {
687                         ghb_settings_set_string(ud->settings, "deinterlace", str);
688                         g_free(str);
689                 }
690                 str = ghb_settings_get_string(ud->settings, "tweak_denoise");
691                 if (str)
692                 {
693                         ghb_settings_set_string(ud->settings, "denoise", str);
694                         g_free(str);
695                 }
696         }
697         autoscale = ghb_settings_get_boolean(ud->settings, "autoscale");
698         ghb_settings_set_int64(ud->settings, "preset_type", 1);
699
700         dict = ghb_dict_value_new();
701         ghb_dict_insert(presetsPlist, g_strdup(name), dict);
702         internal = plist_get_dict(internalPlist, "Presets");
703
704         ghb_dict_iter_init(&iter, internal);
705         while (g_hash_table_iter_next(&iter, (gpointer*)&key, (gpointer*)&value))
706         {
707                 if (!autoscale)
708                 {
709                         if (strcmp(key, "scale_width"))
710                         {
711                                 key = "max_width";
712                         }
713                         if (strcmp(key, "scale_height"))
714                         {
715                                 key = "max_height";
716                         }
717                 }
718                 const GValue *gval;
719                 gval = ghb_settings_get_value(ud->settings, key);
720                 if (gval == NULL)
721                 {
722                         g_debug("Setting (%s) is not in defaults\n", (gchar*)key);
723                         continue;
724                 }
725                 if (ghb_value_cmp(gval, value) != 0)
726                 {
727                         // Differs from default value.  Store it.
728                         ghb_dict_insert(dict, g_strdup(key), ghb_value_dup(gval));
729                 }
730         }
731         presets_store();
732         ud->dont_clear_presets = TRUE;
733         ghb_set_preset (ud, name);
734         ud->dont_clear_presets = FALSE;
735 }
736
737 void
738 ghb_presets_remove(const gchar *name)
739 {
740         if (ghb_dict_lookup(presetsPlist, name))
741         {
742                 ghb_dict_remove(presetsPlist, name);
743                 presets_store();
744         }
745 }
746