1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2
3 /*
4 * Goo
5 *
6 * Copyright (C) 2001-2009 Free Software Foundation, Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include <config.h>
23 #include <brasero3/brasero-drive-selection.h>
24 #include <gtk/gtk.h>
25 #include <gst/gst.h>
26 #include "dlg-preferences.h"
27 #include "goo-window.h"
28 #include "glib-utils.h"
29 #include "gtk-utils.h"
30 #include "preferences.h"
31 #include "typedefs.h"
32
33
34 #define N_VALUES 10
35 #define GET_WIDGET(x) _gtk_builder_get_widget (data->builder, (x))
36
37
38 enum {
39 TEXT_COLUMN,
40 DATA_COLUMN,
41 PRESENT_COLUMN,
42 N_COLUMNS
43 };
44
45
46 static int flac_compression[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
47 static int mp3_quality[] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
48
49
50 typedef struct {
51 GooWindow *window;
52 GtkBuilder *builder;
53 GSettings *settings_general;
54 GSettings *settings_ripper;
55 GtkWidget *dialog;
56 GtkWidget *drive_selector;
57 GtkWidget *filetype_combobox;
58 GtkTreeModel *filetype_model;
59 int ogg_value;
60 int flac_value;
61 } DialogData;
62
63
64 static void
apply_button_clicked(DialogData * data)65 apply_button_clicked (DialogData *data)
66 {
67 const char *destination;
68 BraseroDrive *drive;
69
70 destination = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (GET_WIDGET ("destination_filechooserbutton")));
71 g_settings_set_string (data->settings_ripper, PREF_RIPPER_DESTINATION, destination);
72
73 g_settings_set_enum (data->settings_ripper, PREF_RIPPER_FILETYPE, gtk_combo_box_get_active (GTK_COMBO_BOX (data->filetype_combobox)));
74 g_settings_set_boolean (data->settings_ripper, PREF_RIPPER_SAVE_PLAYLIST, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("save_playlist_checkbutton"))));
75 g_settings_set_boolean (data->settings_general, PREF_GENERAL_AUTOPLAY, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("autoplay_checkbutton"))));
76
77 /**/
78
79 drive = brasero_drive_selection_get_active (BRASERO_DRIVE_SELECTION (data->drive_selector));
80 if (drive == NULL)
81 return;
82
83 g_settings_set_string (data->settings_general, PREF_GENERAL_DEVICE, brasero_drive_get_device (drive));
84 goo_window_set_drive (data->window, drive);
85
86 g_object_unref (drive);
87 }
88
89
90 static void
dialog_destroy_cb(GtkWidget * widget,DialogData * data)91 dialog_destroy_cb (GtkWidget *widget,
92 DialogData *data)
93 {
94 apply_button_clicked (data);
95 data->window->preferences_dialog = NULL;
96
97 _g_object_unref (data->settings_general);
98 _g_object_unref (data->settings_ripper);
99 g_object_unref (data->builder);
100 g_free (data);
101 }
102
103
104 void dlg_format (DialogData *dialog_data, GooFileFormat format);
105
106
107 static void
filetype_properties_clicked_cb(GtkWidget * widget,DialogData * data)108 filetype_properties_clicked_cb (GtkWidget *widget,
109 DialogData *data)
110 {
111 dlg_format (data, gtk_combo_box_get_active (GTK_COMBO_BOX (data->filetype_combobox)));
112 }
113
114
115 static gboolean
drive_selector_device_changed_cb(GtkWidget * drive_selector,const char * device_path,DialogData * data)116 drive_selector_device_changed_cb (GtkWidget *drive_selector,
117 const char *device_path,
118 DialogData *data)
119 {
120 apply_button_clicked (data);
121 return FALSE;
122 }
123
124
125 static void
filetype_combobox_changed_cb(GtkComboBox * widget,DialogData * data)126 filetype_combobox_changed_cb (GtkComboBox *widget,
127 DialogData *data)
128 {
129 int format;
130
131 format = gtk_combo_box_get_active (GTK_COMBO_BOX (data->filetype_combobox));
132 gtk_notebook_set_current_page (GTK_NOTEBOOK (GET_WIDGET ("encoding_notebook")), format);
133 gtk_widget_set_sensitive (GET_WIDGET ("filetype_properties_button"), format != GOO_FILE_FORMAT_WAVE);
134 }
135
136
137 static void
set_description_label(DialogData * data,const char * widget_name,const char * label_text)138 set_description_label (DialogData *data,
139 const char *widget_name,
140 const char *label_text)
141 {
142 char *text;
143
144 text = g_markup_printf_escaped ("<small><i>%s</i></small>", label_text);
145 gtk_label_set_markup (GTK_LABEL (GET_WIDGET (widget_name)), text);
146
147 g_free (text);
148 }
149
150
151 static void
dialog_response_cb(GtkWidget * dialog,int response_id,DialogData * data)152 dialog_response_cb (GtkWidget *dialog,
153 int response_id,
154 DialogData *data)
155 {
156 apply_button_clicked (data);
157 gtk_widget_destroy (dialog);
158 }
159
160
161 void
dlg_preferences(GooWindow * window)162 dlg_preferences (GooWindow *window)
163 {
164 DialogData *data;
165 char *destination = NULL;
166 GooFileFormat file_format;
167 GstElement *encoder;
168 gboolean ogg_encoder, flac_encoder, mp3_encoder, wave_encoder;
169 gboolean find_first_available;
170 GtkTreeIter iter;
171 GtkCellRenderer *renderer;
172 BraseroDrive *drive;
173
174 if (window->preferences_dialog != NULL) {
175 gtk_window_present (GTK_WINDOW (window->preferences_dialog));
176 return;
177 }
178
179 data = g_new0 (DialogData, 1);
180 data->window = window;
181 data->builder = _gtk_builder_new_from_resource ("preferences.ui");
182 data->settings_general = g_settings_new (GOOBOX_SCHEMA_GENERAL);
183 data->settings_ripper = g_settings_new (GOOBOX_SCHEMA_RIPPER);
184
185 /* Get the widgets. */
186
187 data->dialog = g_object_new (GTK_TYPE_DIALOG,
188 "title", _("CD Player Preferences"),
189 "transient-for", GTK_WINDOW (window),
190 "modal", FALSE,
191 "use-header-bar", _gtk_settings_get_dialogs_use_header (),
192 "resizable", FALSE,
193 NULL);
194 window->preferences_dialog = data->dialog;
195
196 gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG (data->dialog))),
197 GET_WIDGET ("preferences_dialog"));
198
199 /* Set widgets data. */
200
201 if (g_settings_get_boolean (data->settings_general, PREF_GENERAL_USE_SJ)) {
202 GtkWidget *notebook;
203 GtkWidget *encoder_page;
204
205 notebook = GET_WIDGET ("notebook");
206 gtk_notebook_set_show_border (GTK_NOTEBOOK (notebook), FALSE);
207 gtk_notebook_set_show_tabs (GTK_NOTEBOOK (notebook), FALSE);
208
209 encoder_page = gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), 1);
210 gtk_widget_hide (encoder_page);
211
212 gtk_container_set_border_width (GTK_CONTAINER (GET_WIDGET ("general_vbox")), 0);
213 }
214
215 /* Extraction */
216
217 data->filetype_model = GTK_TREE_MODEL (gtk_list_store_new (N_COLUMNS,
218 G_TYPE_STRING,
219 G_TYPE_INT,
220 G_TYPE_BOOLEAN));
221 data->filetype_combobox = gtk_combo_box_new_with_model (data->filetype_model);
222
223 renderer = gtk_cell_renderer_text_new ();
224 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (data->filetype_combobox),
225 renderer,
226 FALSE);
227 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (data->filetype_combobox),
228 renderer,
229 "text", TEXT_COLUMN,
230 "sensitive", PRESENT_COLUMN,
231 NULL);
232 gtk_widget_show (data->filetype_combobox);
233 gtk_box_pack_start (GTK_BOX (GET_WIDGET ("filetype_combobox_box")), data->filetype_combobox, TRUE, TRUE, 0);
234
235 /**/
236
237 destination = g_settings_get_string (data->settings_ripper, PREF_RIPPER_DESTINATION);
238 if ((destination == NULL) || (strcmp (destination, "") == 0))
239 destination = g_filename_to_uri (g_get_user_special_dir (G_USER_DIRECTORY_MUSIC), NULL, NULL);
240 if (destination == NULL)
241 destination = g_filename_to_uri (g_get_home_dir (), NULL, NULL);
242 gtk_file_chooser_set_uri (GTK_FILE_CHOOSER (GET_WIDGET ("destination_filechooserbutton")), destination);
243 g_free (destination);
244
245 /* ogg */
246
247 encoder = gst_element_factory_make (OGG_ENCODER, "encoder");
248 ogg_encoder = encoder != NULL;
249 gtk_list_store_append (GTK_LIST_STORE (data->filetype_model), &iter);
250 gtk_list_store_set (GTK_LIST_STORE (data->filetype_model),
251 &iter,
252 TEXT_COLUMN, _("Ogg Vorbis"),
253 DATA_COLUMN, GOO_FILE_FORMAT_OGG,
254 PRESENT_COLUMN, ogg_encoder,
255 -1);
256 if (encoder != NULL)
257 gst_object_unref (GST_OBJECT (encoder));
258
259 /* flac */
260
261 encoder = gst_element_factory_make (FLAC_ENCODER, "encoder");
262 flac_encoder = encoder != NULL;
263 gtk_list_store_append (GTK_LIST_STORE (data->filetype_model), &iter);
264 gtk_list_store_set (GTK_LIST_STORE (data->filetype_model),
265 &iter,
266 TEXT_COLUMN, _("FLAC"),
267 DATA_COLUMN, GOO_FILE_FORMAT_FLAC,
268 PRESENT_COLUMN, flac_encoder,
269 -1);
270 if (encoder != NULL)
271 gst_object_unref (GST_OBJECT (encoder));
272
273 /* mp3 */
274
275 encoder = gst_element_factory_make (MP3_ENCODER, "encoder");
276 mp3_encoder = encoder != NULL;
277 gtk_list_store_append (GTK_LIST_STORE (data->filetype_model), &iter);
278 gtk_list_store_set (GTK_LIST_STORE (data->filetype_model),
279 &iter,
280 TEXT_COLUMN, _("MP3"),
281 DATA_COLUMN, GOO_FILE_FORMAT_MP3,
282 PRESENT_COLUMN, mp3_encoder,
283 -1);
284 if (encoder != NULL)
285 gst_object_unref (GST_OBJECT (encoder));
286
287 /* wav */
288
289 encoder = gst_element_factory_make (WAVE_ENCODER, "encoder");
290 wave_encoder = encoder != NULL;
291 gtk_list_store_append (GTK_LIST_STORE (data->filetype_model), &iter);
292 gtk_list_store_set (GTK_LIST_STORE (data->filetype_model),
293 &iter,
294 TEXT_COLUMN, _("Waveform PCM"),
295 DATA_COLUMN, GOO_FILE_FORMAT_WAVE,
296 PRESENT_COLUMN, wave_encoder,
297 -1);
298 if (encoder != NULL)
299 gst_object_unref (GST_OBJECT (encoder));
300
301 file_format = g_settings_get_enum (data->settings_ripper, PREF_RIPPER_FILETYPE);
302 find_first_available = (((file_format == GOO_FILE_FORMAT_OGG) && ! ogg_encoder)
303 || ((file_format == GOO_FILE_FORMAT_FLAC) && ! flac_encoder)
304 || ((file_format == GOO_FILE_FORMAT_MP3) && ! mp3_encoder)
305 || ((file_format == GOO_FILE_FORMAT_WAVE) && ! wave_encoder));
306
307 if (find_first_available) {
308 if (ogg_encoder)
309 file_format = GOO_FILE_FORMAT_OGG;
310 else if (flac_encoder)
311 file_format = GOO_FILE_FORMAT_FLAC;
312 else if (mp3_encoder)
313 file_format = GOO_FILE_FORMAT_MP3;
314 else if (wave_encoder)
315 file_format = GOO_FILE_FORMAT_WAVE;
316 }
317
318 gtk_combo_box_set_active (GTK_COMBO_BOX (data->filetype_combobox), file_format);
319 filetype_combobox_changed_cb (NULL, data);
320
321 /**/
322
323 set_description_label (data, "ogg_description_label", _(OGG_DESCRIPTION));
324 set_description_label (data, "flac_description_label", _(FLAC_DESCRIPTION));
325 set_description_label (data, "mp3_description_label", _(MP3_DESCRIPTION));
326 set_description_label (data, "wave_description_label", _(WAVE_DESCRIPTION));
327
328 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("save_playlist_checkbutton")), g_settings_get_boolean (data->settings_ripper, PREF_RIPPER_SAVE_PLAYLIST));
329 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("autoplay_checkbutton")), g_settings_get_boolean (data->settings_general, PREF_GENERAL_AUTOPLAY));
330
331 /**/
332
333 data->drive_selector = brasero_drive_selection_new ();
334 drive = goo_player_get_drive (goo_window_get_player (data->window));
335 if (drive != NULL)
336 brasero_drive_selection_set_active (BRASERO_DRIVE_SELECTION (data->drive_selector), drive);
337 gtk_widget_show (data->drive_selector);
338 gtk_box_pack_start (GTK_BOX (GET_WIDGET ("drive_selector_box")), data->drive_selector, TRUE, TRUE, 0);
339
340 /* Set the signals handlers. */
341
342 g_signal_connect (data->dialog,
343 "destroy",
344 G_CALLBACK (dialog_destroy_cb),
345 data);
346 g_signal_connect (G_OBJECT (data->dialog),
347 "response",
348 G_CALLBACK (dialog_response_cb),
349 data);
350 g_signal_connect (GET_WIDGET ("filetype_properties_button"),
351 "clicked",
352 G_CALLBACK (filetype_properties_clicked_cb),
353 data);
354 g_signal_connect_after (G_OBJECT (data->drive_selector),
355 "changed",
356 G_CALLBACK (drive_selector_device_changed_cb),
357 data);
358 g_signal_connect (data->filetype_combobox,
359 "changed",
360 G_CALLBACK (filetype_combobox_changed_cb),
361 data);
362
363 /* run dialog. */
364
365 gtk_window_set_transient_for (GTK_WINDOW (data->dialog), GTK_WINDOW (window));
366 gtk_window_set_modal (GTK_WINDOW (data->dialog), FALSE);
367 gtk_widget_show (data->dialog);
368 }
369
370
371 /* -- format dialog -- */
372
373
374 typedef struct {
375 GooFileFormat format;
376 int value;
377 GSettings *settings_encoder;
378 GtkBuilder *builder;
379 GtkWidget *dialog;
380 GtkWidget *f_quality_label;
381 GtkWidget *f_quality_scale;
382 } FormatDialogData;
383
384
385 static void
format_dialog_destroy_cb(GtkWidget * widget,FormatDialogData * data)386 format_dialog_destroy_cb (GtkWidget *widget,
387 FormatDialogData *data)
388 {
389 g_object_unref (data->settings_encoder);
390 g_object_unref (data->builder);
391 g_free (data);
392 }
393
394
395 static void
format_dialog_ok_button_clicked(FormatDialogData * data)396 format_dialog_ok_button_clicked (FormatDialogData *data)
397 {
398 switch (data->format) {
399 case GOO_FILE_FORMAT_OGG:
400 g_settings_set_double (data->settings_encoder, PREF_ENCODER_OGG_QUALITY, (float) data->value / 10.0);
401 break;
402 case GOO_FILE_FORMAT_FLAC:
403 g_settings_set_int (data->settings_encoder, PREF_ENCODER_FLAC_COMPRESSION, flac_compression[data->value]);
404 break;
405 case GOO_FILE_FORMAT_MP3:
406 g_settings_set_int (data->settings_encoder, PREF_ENCODER_MP3_QUALITY, mp3_quality[data->value]);
407 break;
408 default:
409 break;
410 }
411
412 gtk_widget_destroy (data->dialog);
413 }
414
415
416 static void
format_dialog_scale_value_changed_cb(GtkRange * range,FormatDialogData * data)417 format_dialog_scale_value_changed_cb (GtkRange *range,
418 FormatDialogData *data)
419 {
420 data->value = (int) gtk_range_get_value (range);
421 }
422
423
424 static int
find_index(int a[],int v)425 find_index (int a[], int v)
426 {
427 int i;
428 for (i = 0; i < N_VALUES; i++)
429 if (a[i] == v)
430 return i;
431 return 5;
432 }
433
434
435 static int
get_current_value(FormatDialogData * data,GooFileFormat format)436 get_current_value (FormatDialogData *data,
437 GooFileFormat format)
438 {
439 int index = 0;
440 int value;
441
442 switch (format) {
443 case GOO_FILE_FORMAT_OGG:
444 index = (int) (g_settings_get_double (data->settings_encoder, PREF_ENCODER_OGG_QUALITY) * 10.0 + 0.05);
445 break;
446 case GOO_FILE_FORMAT_FLAC:
447 value = g_settings_get_int (data->settings_encoder, PREF_ENCODER_FLAC_COMPRESSION);
448 index = find_index (flac_compression, value);
449 break;
450 case GOO_FILE_FORMAT_MP3:
451 value = g_settings_get_int (data->settings_encoder, PREF_ENCODER_MP3_QUALITY);
452 index = find_index (mp3_quality, value);
453 break;
454 default:
455 break;
456 }
457
458 return index;
459 }
460
461
462 static double
scale_value(double v)463 scale_value (double v)
464 {
465 return v * 1.0 + 0.0;
466 }
467
468 static void
format_dialog_response_cb(GtkWidget * dialog,int response_id,FormatDialogData * data)469 format_dialog_response_cb (GtkWidget *dialog,
470 int response_id,
471 FormatDialogData *data)
472 {
473 format_dialog_ok_button_clicked (data);
474 }
475
476
477 void
dlg_format(DialogData * preferences_data,GooFileFormat format)478 dlg_format (DialogData *preferences_data,
479 GooFileFormat format)
480 {
481 FormatDialogData *data;
482 char *text;
483
484 data = g_new0 (FormatDialogData, 1);
485 data->format = format;
486 data->settings_encoder = g_settings_new (GOOBOX_SCHEMA_ENCODER);
487 data->builder = _gtk_builder_new_from_resource ("format-options.ui");
488
489 data->dialog = g_object_new (GTK_TYPE_DIALOG,
490 "title", _("Format Properties"),
491 "transient-for", GTK_WINDOW (preferences_data->dialog),
492 "modal", FALSE,
493 "use-header-bar", _gtk_settings_get_dialogs_use_header (),
494 "resizable", FALSE,
495 NULL);
496 gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG (data->dialog))),
497 GET_WIDGET ("format_dialog"));
498
499 /* Set widgets data. */
500
501 if (format == GOO_FILE_FORMAT_FLAC) {
502 gtk_adjustment_set_upper (GTK_ADJUSTMENT (GET_WIDGET ("quality_adjustment")), 9.0);
503
504 text = g_strdup_printf ("<small><i>%s</i></small>", _("Faster compression"));
505 gtk_label_set_markup (GTK_LABEL (GET_WIDGET ("smaller_value_label")), text);
506 g_free (text);
507
508 text = g_strdup_printf ("<small><i>%s</i></small>", _("Higher compression"));
509 gtk_label_set_markup (GTK_LABEL (GET_WIDGET ("bigger_value_label")), text);
510 g_free (text);
511 }
512 else if ((format == GOO_FILE_FORMAT_OGG) || (format == GOO_FILE_FORMAT_MP3)) {
513 gtk_adjustment_set_upper (GTK_ADJUSTMENT (GET_WIDGET ("quality_adjustment")), 10.0);
514
515 text = g_strdup_printf ("<small><i>%s</i></small>", _("Smaller size"));
516 gtk_label_set_markup (GTK_LABEL (GET_WIDGET ("smaller_value_label")), text);
517 g_free (text);
518
519 text = g_strdup_printf ("<small><i>%s</i></small>", _("Higher quality"));
520 gtk_label_set_markup (GTK_LABEL (GET_WIDGET ("bigger_value_label")), text);
521 g_free (text);
522 }
523
524 data->value = get_current_value (data, format);
525 gtk_range_set_value (GTK_RANGE (GET_WIDGET ("quality_scale")), scale_value (data->value));
526
527 switch (format) {
528 case GOO_FILE_FORMAT_OGG:
529 text = g_strdup_printf ("<big><b>%s</b></big>", _("Ogg Vorbis"));
530 break;
531 case GOO_FILE_FORMAT_FLAC:
532 text = g_strdup_printf ("<big><b>%s</b></big>", _("FLAC"));
533 break;
534 case GOO_FILE_FORMAT_MP3:
535 text = g_strdup_printf ("<big><b>%s</b></big>", _("MP3"));
536 break;
537 default:
538 text = g_strdup ("");
539 break;
540 }
541 gtk_label_set_markup (GTK_LABEL (GET_WIDGET ("title_label")), text);
542 g_free (text);
543
544 switch (data->format) {
545 case GOO_FILE_FORMAT_OGG:
546 case GOO_FILE_FORMAT_MP3:
547 text = _("Quality:");
548 break;
549 case GOO_FILE_FORMAT_FLAC:
550 text = _("Compression level:");
551 break;
552 default:
553 text = "";
554 break;
555 }
556 gtk_label_set_text (GTK_LABEL (GET_WIDGET ("quality_label")), text);
557
558 switch (data->format) {
559 case GOO_FILE_FORMAT_OGG:
560 text = _(OGG_DESCRIPTION);
561 break;
562 case GOO_FILE_FORMAT_FLAC:
563 text = _(FLAC_DESCRIPTION);
564 break;
565 case GOO_FILE_FORMAT_MP3:
566 text = _(MP3_DESCRIPTION);
567 break;
568 case GOO_FILE_FORMAT_WAVE:
569 text = _(WAVE_DESCRIPTION);
570 break;
571 default:
572 text = "";
573 break;
574 }
575 gtk_label_set_text (GTK_LABEL (GET_WIDGET ("description_label")), text);
576
577 /* Set the signals handlers. */
578
579 g_signal_connect (data->dialog,
580 "destroy",
581 G_CALLBACK (format_dialog_destroy_cb),
582 data);
583 g_signal_connect (G_OBJECT (data->dialog),
584 "response",
585 G_CALLBACK (format_dialog_response_cb),
586 data);
587 g_signal_connect (GET_WIDGET ("quality_scale"),
588 "value_changed",
589 G_CALLBACK (format_dialog_scale_value_changed_cb),
590 data);
591
592 /* run dialog. */
593
594 gtk_window_set_transient_for (GTK_WINDOW (data->dialog), GTK_WINDOW (preferences_data->dialog));
595 gtk_window_set_modal (GTK_WINDOW (data->dialog), TRUE);
596 gtk_widget_show (data->dialog);
597 }
598