mp3splt-gtk
preferences_window.c
Go to the documentation of this file.
1 /**********************************************************
2  *
3  * mp3splt-gtk -- utility based on mp3splt,
4  * for mp3/ogg splitting without decoding
5  *
6  * Copyright: (C) 2005-2013 Alexandru Munteanu
7  * Contact: m@ioalex.net
8  *
9  * http://mp3splt.sourceforge.net/
10  *
11  *********************************************************/
12 
13 /**********************************************************
14  *
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * as published by the Free Software Foundation; either version 2
18  * of the License, or (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23  * GNU General Public License for more details.
24  *
25  * along with this program; if not, write to the Free Software
26  * You should have received a copy of the GNU General Public License
27  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
28  * USA.
29  *
30  *********************************************************/
31 
32 /*!********************************************************
33  * \file
34  * The preferences tab
35  *
36  * this file contains the code for the preferences tab where
37  * the preferences can be chosen.
38  ********************************************************/
39 
40 #include "preferences_window.h"
41 
42 static GtkWidget *create_extract_tags_from_filename_options_box(ui_state *ui);
43 static GtkWidget *create_test_regex_table(ui_state *ui);
44 static void update_wave_preview_label_markup(gint index, gint interpolation_level, ui_state *ui);
45 
51 {
52  GSList *radio_button_list = gtk_radio_button_get_group(GTK_RADIO_BUTTON(ui->gui->radio_button));
53 
54  //0 = german, 1 = french, 2 = english
55  GtkWidget *our_button = GTK_WIDGET(g_slist_nth_data(radio_button_list, 0));
56  if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(our_button)))
57  {
58  return g_string_new("de_DE");
59  }
60 
61  our_button = GTK_WIDGET(g_slist_nth_data(radio_button_list, 1));
62  if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(our_button)))
63  {
64  return g_string_new("fr_FR");
65  }
66 
67  return g_string_new("en");
68 }
69 
72 {
73  GSList *radio_button_list = gtk_radio_button_get_group(GTK_RADIO_BUTTON(ui->gui->radio_output));
74  //O = default output mode
75  //1 = custom output mode
76  gint i;
77  for(i = 0; i<2;i++)
78  {
79  GtkToggleButton *test = (GtkToggleButton *)g_slist_nth_data(radio_button_list,i);
80  if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(test)))
81  {
82  return i;
83  }
84  }
85 
86  return 0;
87 }
88 
91 {
92  GSList *radio_button_list = gtk_radio_button_get_group(GTK_RADIO_BUTTON(gui->tags_version_radio));
93 
94  //O = The same version as the original file
95  //1 = ID3v1
96  //2 = ID3v2
97  //3 = ID3v1 & ID3v2
98  gint i = 0;
99  for(i = 0; i < 4;i++)
100  {
101  GtkToggleButton *button = GTK_TOGGLE_BUTTON(g_slist_nth_data(radio_button_list,i));
102  if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)))
103  {
104  return i;
105  }
106  }
107 
108  return 0;
109 }
110 
111 static void set_output_directory(gchar *dirname, ui_state *ui)
112 {
113  if (dirname == NULL)
114  {
115  return;
116  }
117 
118  lock_mutex(&ui->variables_mutex);
119  if (ui->infos->outputdirname != NULL)
120  {
121  g_string_free(ui->infos->outputdirname, TRUE);
122  }
123  ui->infos->outputdirname = g_string_new(dirname);
124  unlock_mutex(&ui->variables_mutex);
125 }
126 
127 static void change_output_dir_options(GtkToggleButton *button, gpointer data)
128 {
129  ui_state *ui = (ui_state *)data;
130 
131  GtkWidget *dir_file_chooser_button = ui->gui->custom_dir_file_chooser_button;
132  if (!dir_file_chooser_button || !ui->gui->example_output_dir_box)
133  {
134  return;
135  }
136 
137  if (rh_get_active_value(ui->gui->output_dir_radio) == CUSTOM_DIRECTORY)
138  {
139  gchar *directory = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(dir_file_chooser_button));
140  set_output_directory(directory, ui);
141  gtk_widget_set_sensitive(dir_file_chooser_button, SPLT_TRUE);
142  gtk_widget_set_sensitive(ui->gui->example_output_dir_box, SPLT_FALSE);
143  }
144  else
145  {
146  set_output_directory("", ui);
147  gtk_widget_set_sensitive(dir_file_chooser_button, SPLT_FALSE);
148  gtk_widget_set_sensitive(ui->gui->example_output_dir_box, SPLT_TRUE);
149  }
150 
151  ui_save_preferences(NULL, ui);
152 }
153 
154 static void update_output_directory_in_gui(ui_state *ui, char *output_dir)
155 {
156  GtkWidget *custom_dir_file_chooser_button = ui->gui->custom_dir_file_chooser_button;
157 
158  if (output_dir == NULL || output_dir[0] == '\0')
159  {
160  rh_set_radio_value(ui->gui->output_dir_radio, FILE_DIRECTORY, TRUE);
161  }
162  else
163  {
164  rh_set_radio_value(ui->gui->output_dir_radio, CUSTOM_DIRECTORY, TRUE);
165  gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(custom_dir_file_chooser_button), output_dir);
166  }
167 
168  change_output_dir_options(GTK_TOGGLE_BUTTON(ui->gui->output_dir_radio), ui);
169 }
170 
171 void set_output_directory_and_update_ui(gchar *dirname, ui_state *ui)
172 {
173  if (dirname == NULL)
174  {
175  return;
176  }
177 
178  set_output_directory(dirname, ui);
179 
180  update_output_directory_in_gui(ui, dirname);
181 }
182 
190 {
191  if (ui->infos->outputdirname != NULL)
192  {
193  return ui->infos->outputdirname->str;
194  }
195 
196  return NULL;
197 }
198 
200 static void output_radio_box_event(GtkToggleButton *radio_b, ui_state *ui)
201 {
202  gint selected = get_checked_output_radio_box(ui);
203  if (selected == 0)
204  {
205  gtk_widget_set_sensitive(ui->gui->output_entry, TRUE);
206  gtk_widget_set_sensitive(ui->gui->output_label, TRUE);
207  mp3splt_set_int_option(ui->mp3splt_state, SPLT_OPT_OUTPUT_FILENAMES, SPLT_OUTPUT_FORMAT);
208  gtk_widget_set_sensitive(ui->gui->output_default_label, FALSE);
209  }
210  else
211  {
212  gtk_widget_set_sensitive(ui->gui->output_entry, FALSE);
213  gtk_widget_set_sensitive(ui->gui->output_label, FALSE);
214  mp3splt_set_int_option(ui->mp3splt_state, SPLT_OPT_OUTPUT_FILENAMES, SPLT_OUTPUT_DEFAULT);
215  gtk_widget_set_sensitive(ui->gui->output_default_label, TRUE);
216  }
217 
218  ui_save_preferences(NULL, ui);
219 }
220 
221 #ifdef __WIN32__
222 
224 static GtkWidget *create_language_box(ui_state *ui)
225 {
226  GtkWidget *radio_vbox = wh_vbox_new();
227 
228  GtkWidget *radio_button = gtk_radio_button_new_with_label(NULL, "English");
229  ui->gui->radio_button = radio_button;
230  g_signal_connect(GTK_TOGGLE_BUTTON(radio_button), "toggled",
231  G_CALLBACK(ui_save_preferences), ui);
232  gtk_box_pack_start(GTK_BOX(radio_vbox), radio_button, TRUE, TRUE, 0);
233 
234  radio_button = gtk_radio_button_new_with_label_from_widget
235  (GTK_RADIO_BUTTON(radio_button), "Français");
236  ui->gui->radio_button = radio_button;
237  g_signal_connect(GTK_TOGGLE_BUTTON(radio_button), "toggled",
238  G_CALLBACK(ui_save_preferences), ui);
239  gtk_box_pack_start(GTK_BOX(radio_vbox), radio_button, TRUE, TRUE, 0);
240 
241  radio_button = gtk_radio_button_new_with_label_from_widget
242  (GTK_RADIO_BUTTON(radio_button), "Deutsch");
243  ui->gui->radio_button = radio_button;
244  g_signal_connect(GTK_TOGGLE_BUTTON (radio_button), "toggled",
245  G_CALLBACK(ui_save_preferences), ui);
246  gtk_box_pack_start(GTK_BOX(radio_vbox), radio_button, TRUE, TRUE, 0);
247 
248  return wh_set_title_and_get_vbox(radio_vbox,
249  _("<b>Choose language (requires restart)</b>"));
250 }
251 
253 static GtkWidget *create_pref_language_page(ui_state *ui)
254 {
255  GtkWidget *language_hbox = wh_hbox_new();;
256  GtkWidget *language_inside_hbox = wh_hbox_new();;
257 
258  GtkWidget *scrolled_window = wh_create_scrolled_window();
259  gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window),
260  GTK_WIDGET(language_inside_hbox));
261  gtk_box_pack_start(GTK_BOX(language_hbox), scrolled_window, TRUE, TRUE, 0);
262 
263  GtkWidget *vbox = wh_vbox_new();;
264  gtk_box_pack_start(GTK_BOX(language_inside_hbox), vbox, TRUE, TRUE, 10);
265 
266  GtkWidget *lang_box = create_language_box(ui);
267  gtk_box_pack_start(GTK_BOX(vbox), lang_box, FALSE, FALSE, 10);
268 
269  return language_hbox;
270 }
271 #endif
272 
274 static void disable_adjust_parameters(gui_state *gui)
275 {
276  gtk_widget_set_sensitive(gui->adjust_param_vbox, FALSE);
277 }
278 
280 static void enable_adjust_parameters(gui_state *gui)
281 {
282  gtk_widget_set_sensitive(gui->adjust_param_vbox, TRUE);
283 }
284 
286 static void adjust_event(GtkToggleButton *adjust_mode, ui_state *ui)
287 {
288  if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(adjust_mode)))
289  {
290  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ui->gui->frame_mode),TRUE);
291  enable_adjust_parameters(ui->gui);
292  }
293  else
294  {
295  disable_adjust_parameters(ui->gui);
296  }
297 
298  ui_save_preferences(NULL, ui);
299 }
300 
302 static void frame_event(GtkToggleButton *frame_mode, ui_state *ui)
303 {
304  if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(frame_mode)))
305  {
306  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ui->gui->adjust_mode),FALSE);
307  }
308 
309  ui_save_preferences(NULL, ui);
310 }
311 
312 static void splitpoints_from_filename_event(GtkToggleButton *frame_mode, ui_state *ui)
313 {
314  gint splitpoints_from_filename = gtk_toggle_button_get_active(ui->gui->names_from_filename);
315  if (splitpoints_from_filename == TRUE && ui->status->file_browsed == TRUE)
316  {
317  copy_filename_to_current_description(get_input_filename(ui->gui), ui);
318  }
319  else
320  {
321  clear_current_description(ui);
322  }
323 
324  ui_save_preferences(NULL, ui);
325 }
326 
328 static void set_default_prefs_event(GtkWidget *widget, ui_state *ui)
329 {
330  gui_state *gui = ui->gui;
331 
332  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gui->frame_mode), FALSE);
333  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gui->adjust_mode), FALSE);
334  gtk_spin_button_set_value(GTK_SPIN_BUTTON(gui->spinner_adjust_threshold),
335  SPLT_DEFAULT_PARAM_THRESHOLD);
336  gtk_spin_button_set_value(GTK_SPIN_BUTTON(gui->spinner_adjust_offset),
337  SPLT_DEFAULT_PARAM_OFFSET);
338  gtk_spin_button_set_value(GTK_SPIN_BUTTON(gui->spinner_adjust_gap),
339  SPLT_DEFAULT_PARAM_GAP);
340  gtk_spin_button_set_value(GTK_SPIN_BUTTON(gui->spinner_adjust_min),
341  SPLT_DEFAULT_PARAM_MINIMUM_LENGTH);
342  gtk_toggle_button_set_active(gui->names_from_filename, FALSE);
343  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gui->create_dirs_from_output_files), TRUE);
344 
345  ui_save_preferences(NULL, ui);
346 }
347 
348 static void custom_directory_changed(GtkFileChooser *custom_dir_file_chooser, ui_state *ui)
349 {
350  gchar *filename = gtk_file_chooser_get_filename(custom_dir_file_chooser);
351  set_output_directory(filename, ui);
352  ui_save_preferences(NULL, ui);
353 }
354 
355 static GtkWidget *create_custom_directory_box(ui_state *ui)
356 {
357  GtkWidget *custom_dir_file_chooser_button =
358  gtk_file_chooser_button_new(_("Browse directory ..."), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
359  wh_set_browser_directory_handler(ui, custom_dir_file_chooser_button);
360 
361  g_signal_connect(G_OBJECT(custom_dir_file_chooser_button), "selection-changed",
362  G_CALLBACK(custom_directory_changed), ui);
363 
364  ui->gui->custom_dir_file_chooser_button = custom_dir_file_chooser_button;
365 
366  GtkWidget *hbox = wh_hbox_new();
367  gtk_box_pack_start(GTK_BOX(hbox), custom_dir_file_chooser_button, TRUE, TRUE, 20);
368 
369  return hbox;
370 }
371 
372 static GtkWidget *create_input_file_directory_example_box(ui_state *ui)
373 {
374  GtkWidget *vbox = wh_vbox_new();
375 
376  GtkWidget *example_output_dir_label = gtk_label_new(_("Example for the single file split:"));
377  GtkWidget *fake_hbox = wh_hbox_new();
378  gtk_box_pack_start(GTK_BOX(fake_hbox), example_output_dir_label, FALSE, FALSE, 0);
379 
380  gtk_box_pack_start(GTK_BOX(vbox), fake_hbox, FALSE, FALSE, 0);
381 
382  GtkWidget *example_output_dir_entry = gtk_entry_new();
383  gtk_editable_set_editable(GTK_EDITABLE(example_output_dir_entry), FALSE);
384  gtk_box_pack_start(GTK_BOX(vbox), example_output_dir_entry, TRUE, TRUE, 5);
385  ui->gui->example_output_dir_entry = example_output_dir_entry;
386 
387  GtkWidget *hbox_for_margin = wh_hbox_new();
388  gtk_box_pack_start(GTK_BOX(hbox_for_margin), vbox, TRUE, TRUE, 20);
389 
390  ui->gui->example_output_dir_box = hbox_for_margin;
391 
392  return hbox_for_margin;
393 }
394 
395 void update_example_output_dir_for_single_file_split(ui_state *ui)
396 {
397  if (!ui->gui->example_output_dir_entry)
398  {
399  return;
400  }
401 
402  gchar *dirname = g_path_get_dirname(get_input_filename(ui->gui));
403  gtk_entry_set_text(GTK_ENTRY(ui->gui->example_output_dir_entry), dirname);
404  g_free(dirname);
405 }
406 
408 static GtkWidget *create_directory_box(ui_state *ui)
409 {
410  gui_state *gui = ui->gui;
411 
412  GtkWidget *vbox = wh_vbox_new();
413 
414  GtkWidget *output_dir_radio = NULL;
415  output_dir_radio = rh_append_radio_to_vbox(output_dir_radio, _("Custom directory"),
416  CUSTOM_DIRECTORY, change_output_dir_options, ui, vbox);
417  gtk_widget_set_tooltip_text(output_dir_radio, _("Create split files in a custom directory"));
418 
419  GtkWidget *custom_dir_box = create_custom_directory_box(ui);
420  gtk_box_pack_start(GTK_BOX(vbox), custom_dir_box, FALSE, FALSE, 0);
421 
422  output_dir_radio = rh_append_radio_to_vbox(output_dir_radio, _("Input file directory"),
423  FILE_DIRECTORY, change_output_dir_options, ui, vbox);
424  gtk_widget_set_tooltip_text(output_dir_radio,
425  _("Create split files in the same directory as the file being split"));
426  gui->output_dir_radio = output_dir_radio;
427 
428  GtkWidget *input_file_directory_example_box = create_input_file_directory_example_box(ui);
429  gtk_box_pack_start(GTK_BOX(vbox), input_file_directory_example_box, FALSE, FALSE, 0);
430 
431  return wh_set_title_and_get_vbox(vbox, _("<b>Directory for split files</b>"));
432 }
433 
435 static GtkWidget *create_split_options_box(ui_state *ui)
436 {
437  gui_state *gui = ui->gui;
438 
439  GtkWidget *vbox = wh_vbox_new();
440 
441  //names from filename
442  GtkToggleButton *names_from_filename =
443  GTK_TOGGLE_BUTTON(gtk_check_button_new_with_mnemonic(
444  _("_Splitpoint name from filename (manual single file split only)")));
445  gtk_widget_set_tooltip_text(GTK_WIDGET(names_from_filename),
446  _("Name newly added splitpoints as the input file"));
447  gui->names_from_filename = names_from_filename;
448 
449  gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(names_from_filename), FALSE, FALSE, 0);
450  g_signal_connect(G_OBJECT(names_from_filename), "toggled",
451  G_CALLBACK(splitpoints_from_filename_event), ui);
452 
453  GtkWidget *create_dirs_from_output_files =
454  gtk_check_button_new_with_mnemonic(_("Create directories from _filenames "));
455 
456  gtk_widget_set_tooltip_text(create_dirs_from_output_files,
457  _("If the splitpoint name is 'a/b/output', the directory chain 'a/b' is created in the"
458  " output\ndirectory and the file 'output.<extension>' is written in the"
459  " '<output_directory>/a/b' directory"));
460  gui->create_dirs_from_output_files = create_dirs_from_output_files;
461  gtk_box_pack_start(GTK_BOX(vbox), create_dirs_from_output_files, FALSE, FALSE, 0);
462  g_signal_connect(G_OBJECT(create_dirs_from_output_files), "toggled",
463  G_CALLBACK(ui_save_preferences), ui);
464 
465  //frame mode option
466  GtkWidget *frame_mode =
467  gtk_check_button_new_with_mnemonic(_("F_rame mode (useful for mp3 VBR) (mp3 only)"));
468  gtk_widget_set_tooltip_text(frame_mode,
469  _("The split is slower with this option, but some mp3 files having\n"
470  "Variable Bit Rate need this mode to be enabled"));
471  gui->frame_mode = frame_mode;
472  gtk_box_pack_start(GTK_BOX(vbox), frame_mode, FALSE, FALSE, 0);
473  g_signal_connect(G_OBJECT(frame_mode), "toggled", G_CALLBACK(frame_event), ui);
474 
475  //auto adjust option
476  GtkWidget *adjust_mode = gtk_check_button_new_with_mnemonic(_("_Auto-adjust mode (use"
477  " silence detection to auto-adjust splitpoints)"));
478  gtk_widget_set_tooltip_text(adjust_mode,
479  _("Splitpoints will be adjusted to match silences (if found)\n"
480  "This mode requires the frame mode"));
481  gui->adjust_mode = adjust_mode;
482  gtk_box_pack_start(GTK_BOX(vbox), adjust_mode, FALSE, FALSE, 0);
483  g_signal_connect(G_OBJECT(adjust_mode), "toggled", G_CALLBACK(adjust_event), ui);
484 
485  //parameters for the adjust option
486  GtkWidget *horiz_fake = wh_hbox_new();
487  gtk_box_pack_start(GTK_BOX(vbox), horiz_fake, FALSE, FALSE, 0);
488 
489  GtkWidget *param_vbox = wh_vbox_new();
490  gui->adjust_param_vbox = param_vbox;
491  gtk_box_pack_start(GTK_BOX(horiz_fake), param_vbox, FALSE, FALSE, 25);
492 
493  //threshold level
494  horiz_fake = wh_hbox_new();
495  gtk_box_pack_start(GTK_BOX(param_vbox), horiz_fake, FALSE, FALSE, 0);
496 
497  GtkWidget *threshold_label = gtk_label_new(_("Threshold level (dB):"));
498  gtk_box_pack_start(GTK_BOX(horiz_fake), threshold_label, FALSE, FALSE, 0);
499 
500  GtkAdjustment *adj =
501  (GtkAdjustment *) gtk_adjustment_new(0.0, -96.0, 0.0, 0.5, 10.0, 0.0);
502  GtkWidget *spinner_adjust_threshold = gtk_spin_button_new (adj, 0.5, 2);
503  gui->spinner_adjust_threshold = spinner_adjust_threshold;
504  g_signal_connect(G_OBJECT(spinner_adjust_threshold), "value_changed",
505  G_CALLBACK(ui_save_preferences), ui);
506  gtk_box_pack_start(GTK_BOX(horiz_fake), spinner_adjust_threshold,
507  FALSE, FALSE, 6);
508 
509  //min level
510  horiz_fake = wh_hbox_new();
511  gtk_box_pack_start(GTK_BOX(param_vbox), horiz_fake, FALSE, FALSE, 0);
512 
513  GtkWidget *min_label = gtk_label_new(_("Minimum silence length (seconds):"));
514  gtk_box_pack_start(GTK_BOX(horiz_fake), min_label, FALSE, FALSE, 0);
515 
516  adj = (GtkAdjustment *)gtk_adjustment_new(0.0, 0, 2000, 0.5, 10.0, 0.0);
517  GtkWidget *spinner_adjust_min = gtk_spin_button_new(adj, 1, 2);
518  gui->spinner_adjust_min = spinner_adjust_min;
519  g_signal_connect(G_OBJECT(spinner_adjust_min), "value_changed",
520  G_CALLBACK(ui_save_preferences), ui);
521  gtk_box_pack_start(GTK_BOX(horiz_fake), spinner_adjust_min,
522  FALSE, FALSE, 6);
523 
524  //offset level
525  horiz_fake = wh_hbox_new();
526  gtk_box_pack_start(GTK_BOX(param_vbox), horiz_fake, FALSE, FALSE, 0);
527 
528  GtkWidget *offset_label = gtk_label_new(_("Cutpoint offset (0 is the begin of silence "
529  "and 1 the end):"));
530  gtk_box_pack_start(GTK_BOX(horiz_fake), offset_label, FALSE, FALSE, 0);
531 
532  //adjustement for the offset spinner
533  adj = (GtkAdjustment *)gtk_adjustment_new(0.0, -2, 2, 0.05, 10.0, 0.0);
534  GtkWidget *spinner_adjust_offset = gtk_spin_button_new (adj, 0.05, 2);
535  gui->spinner_adjust_offset = spinner_adjust_offset;
536  g_signal_connect(G_OBJECT(spinner_adjust_offset), "value_changed",
537  G_CALLBACK(ui_save_preferences), ui);
538  gtk_box_pack_start(GTK_BOX(horiz_fake), spinner_adjust_offset, FALSE, FALSE, 6);
539 
540  //gap level (seconds)
541  horiz_fake = wh_hbox_new();
542  gtk_box_pack_start(GTK_BOX(param_vbox), horiz_fake, FALSE, FALSE, 0);
543 
544  GtkWidget *gap_label =
545  gtk_label_new(_("Gap level (seconds around splitpoint to search for silence):"));
546  gtk_box_pack_start(GTK_BOX(horiz_fake), gap_label, FALSE, FALSE, 0);
547 
548  adj = (GtkAdjustment *) gtk_adjustment_new(0.0, 0, 2000, 1.0, 10.0, 0.0);
549  GtkWidget *spinner_adjust_gap = gtk_spin_button_new (adj, 1, 0);
550  gui->spinner_adjust_gap = spinner_adjust_gap;
551  g_signal_connect(G_OBJECT(spinner_adjust_gap), "value_changed",
552  G_CALLBACK(ui_save_preferences), ui);
553  gtk_box_pack_start(GTK_BOX(horiz_fake), spinner_adjust_gap, FALSE, FALSE, 6);
554 
555  disable_adjust_parameters(ui->gui);
556 
557  //set default preferences button
558  horiz_fake = wh_hbox_new();
559  gtk_box_pack_start(GTK_BOX(vbox), horiz_fake, FALSE, FALSE, 0);
560 
561  GtkWidget *set_default_prefs_button =
562  wh_create_cool_button(GTK_STOCK_PROPERTIES, _("Set _default split options"),FALSE);
563  g_signal_connect(G_OBJECT(set_default_prefs_button), "clicked",
564  G_CALLBACK(set_default_prefs_event), ui);
565  gtk_box_pack_start (GTK_BOX (horiz_fake), set_default_prefs_button, FALSE, FALSE, 5);
566 
567  return wh_set_title_and_get_vbox(vbox, _("<b>Split options</b>"));
568 }
569 
571 static GtkWidget *create_pref_splitpoints_page(ui_state *ui)
572 {
573  GtkWidget *general_hbox = wh_hbox_new();
574  GtkWidget *inside_hbox = wh_hbox_new();
575 
576  GtkWidget *scrolled_window = wh_create_scrolled_window();
577  gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window),
578  GTK_WIDGET(inside_hbox));
579  gtk_box_pack_start(GTK_BOX(general_hbox), scrolled_window, TRUE, TRUE, 0);
580 
581  GtkWidget *inside_vbox = wh_vbox_new();
582  gtk_box_pack_start(GTK_BOX(inside_hbox), inside_vbox, TRUE, TRUE, 5);
583 
584  GtkWidget *dir_box = create_directory_box(ui);
585  gtk_box_pack_start(GTK_BOX(inside_vbox), dir_box, FALSE, FALSE, 2);
586 
587  GtkWidget *split_options_box = create_split_options_box(ui);
588  gtk_box_pack_start(GTK_BOX(inside_vbox), split_options_box, FALSE, FALSE, 1);
589 
590  return general_hbox;
591 }
592 
594 static void player_combo_box_event(GtkComboBox *widget, ui_state *ui)
595 {
596  disconnect_button_event(ui->gui->disconnect_button, ui);
597 
598  ui->infos->selected_player = ch_get_active_value(widget);
599  if (ui->infos->selected_player == PLAYER_GSTREAMER)
600  {
601  hide_connect_button(ui->gui);
602  gtk_widget_show(ui->gui->playlist_box);
603  }
604  else
605  {
606  show_connect_button(ui->gui);
607  gtk_widget_hide(ui->gui->playlist_box);
608  }
609 
610  gtk_widget_show(ui->gui->player_box);
611  gtk_widget_show(ui->gui->queue_files_button);
612 
613  ui_save_preferences(NULL, ui);
614 }
615 
616 static void update_timeout_value(GtkWidget *spinner, ui_state *ui)
617 {
618  ui->infos->timeout_value = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spinner));
619 
620  restart_player_timer(ui);
621  ui_save_preferences(NULL, ui);
622 }
623 
625 static GtkWidget *create_player_options_box(ui_state *ui)
626 {
627  GtkWidget *vbox = wh_vbox_new();
628  GtkWidget *horiz_fake = wh_hbox_new();
629 
630  GtkWidget *label = gtk_label_new(_("Player:"));
631  gtk_box_pack_start(GTK_BOX(horiz_fake), label, FALSE, FALSE, 0);
632 
633  GtkWidget *player_combo_box = GTK_WIDGET(ch_new_combo());
634  ui->gui->player_combo_box = player_combo_box;
635 
636 #ifndef NO_AUDACIOUS
637  ch_append_to_combo(GTK_COMBO_BOX(player_combo_box), "Audacious", PLAYER_AUDACIOUS);
638 #endif
639  ch_append_to_combo(GTK_COMBO_BOX(player_combo_box), "SnackAmp", PLAYER_SNACKAMP);
640 #ifndef NO_GSTREAMER
641  ch_append_to_combo(GTK_COMBO_BOX(player_combo_box), "GStreamer", PLAYER_GSTREAMER);
642 #endif
643 
644  g_signal_connect(G_OBJECT(player_combo_box), "changed", G_CALLBACK(player_combo_box_event), ui);
645 
646  gtk_box_pack_start(GTK_BOX(horiz_fake), player_combo_box, FALSE, FALSE, 5);
647  gtk_box_pack_start(GTK_BOX(vbox), horiz_fake, FALSE, FALSE, 0);
648 
649  GtkWidget *spinner = wh_create_int_spinner_in_box(_("Refresh player every "),
650  _("milliseconds."),
651  (gdouble)DEFAULT_TIMEOUT_VALUE, 20.0, 1000.0, 10.0, 100.0,
652  _("\t(higher refresh rate decreases CPU usage - default is 200)"),
653  update_timeout_value, ui, vbox);
654  ui_register_spinner_int_preference("player", "refresh_rate", DEFAULT_TIMEOUT_VALUE,
655  spinner, (void (*)(GtkWidget *, gpointer)) update_timeout_value,
656  ui, ui);
657 
658  return wh_set_title_and_get_vbox(vbox, _("<b>Player options</b>"));
659 }
660 
661 static void wave_quality_changed_event(GtkAdjustment *wave_quality_adjustment, ui_state *ui)
662 {
663  gint quality_level = (gint)gtk_adjustment_get_value(GTK_ADJUSTMENT(wave_quality_adjustment));
664 
665  gint level = 0;
666  for (level = 0; level <= 5; level++)
667  {
668  gdouble default_value = ui->infos->douglas_peucker_thresholds_defaults[level];
669  gdouble final_value = default_value - quality_level;
670  if (final_value <= 0)
671  {
672  final_value = 0.1;
673  }
674 
675  ui->infos->douglas_peucker_thresholds[level] = final_value;
676  }
677 
678  gint default_number_of_points_th = DEFAULT_SILENCE_WAVE_NUMBER_OF_POINTS_THRESHOLD;
679  gint number_of_points_th = default_number_of_points_th + (quality_level * 1000);
680  if (number_of_points_th <= 0)
681  {
682  number_of_points_th = 0;
683  }
684 
685  ui->infos->silence_wave_number_of_points_threshold = number_of_points_th;
686 
687  compute_douglas_peucker_filters(ui);
688  refresh_preview_drawing_areas(ui->gui);
689 
690  ui_save_preferences(NULL, ui);
691 }
692 
693 void refresh_preview_drawing_areas(gui_state *gui)
694 {
695  gint i = 0;
696  for (i = 0; i < gui->wave_quality_das->len; i++)
697  {
698  gtk_widget_queue_draw(g_ptr_array_index(gui->wave_quality_das, i));
699  }
700 
701  gtk_widget_queue_draw(gui->player_scrolled_window);
702 }
703 
704 static gint get_wave_preview_width_drawing_area(ui_state *ui)
705 {
706  if (ui->infos->width_drawing_area < 50)
707  {
708  return 500;
709  }
710 
711  return ui->infos->width_drawing_area;
712 }
713 
714 #if GTK_MAJOR_VERSION <= 2
715 static gboolean wave_quality_draw_event(GtkWidget *drawing_area, GdkEventExpose *event,
717 {
718  cairo_t *cairo_surface = gdk_cairo_create(drawing_area->window);
719 #else
720 static gboolean wave_quality_draw_event(GtkWidget *drawing_area, cairo_t *cairo_surface,
722 {
723 #endif
724 
725  ui_state *ui = data->data;
726  gint index = data->index;
727 
728  gint width = get_wave_preview_width_drawing_area(ui);
729  gtk_widget_set_size_request(drawing_area, width, 70);
730 
731  gint expected_drawing_time_int = g_array_index(ui->infos->preview_time_windows, gint, index);
732  gfloat expected_drawing_time = (gfloat)(expected_drawing_time_int);
733 
734  dh_set_white_color(cairo_surface);
735 
736  dh_draw_rectangle(cairo_surface, TRUE, 0, 0, width, 70);
737  gfloat current_time = ui->infos->total_time / 2.0;
738 
739  gfloat drawing_time = 0;
740  gfloat zoom_coeff = 0.2;
741 
742  gfloat left_time = 0;
743  gfloat right_time = 0;
744  while ((((gint)drawing_time) == 0) || (drawing_time > expected_drawing_time))
745  {
746  left_time = get_left_drawing_time(current_time, ui->infos->total_time, zoom_coeff);
747  right_time = get_right_drawing_time(current_time, ui->infos->total_time, zoom_coeff);
748  drawing_time = right_time - left_time;
749  zoom_coeff += 0.01;
750 
751  if (zoom_coeff > 100) { break; }
752  }
753 
754  gint interpolation_level = draw_silence_wave((gint)left_time, (gint)right_time, width / 2, 50,
755  drawing_time, width, 0,
756  current_time, ui->infos->total_time, zoom_coeff,
757  drawing_area, cairo_surface, ui);
758 
759  update_wave_preview_label_markup(index, interpolation_level, ui);
760 
761 #if GTK_MAJOR_VERSION <= 2
762  cairo_destroy(cairo_surface);
763 #endif
764 
765  return TRUE;
766 }
767 
768 static GtkWidget *create_wave_quality_preview_box(ui_state *ui)
769 {
770  GtkWidget *vbox = wh_vbox_new();
771 
772  GtkWidget *label_hbox = wh_hbox_new();
773  GtkWidget *wave_preview_label = gtk_label_new(NULL);
774 
775  gchar wave_availability[256] = { '\0' };
776  g_snprintf(wave_availability, 256, "<span style='italic' color='#0000AA'>%s</span>",
777  _("Wave preview is only available if the amplitude wave is shown in the player"));
778  gtk_label_set_markup(GTK_LABEL(wave_preview_label), wave_availability);
779  gtk_box_pack_start(GTK_BOX(label_hbox), wave_preview_label, FALSE, FALSE, 0);
780  gtk_box_pack_start(GTK_BOX(vbox), label_hbox, FALSE, FALSE, 4);
781 
782  ui->gui->wave_quality_das = g_ptr_array_new();
783  ui->gui->wave_preview_labels = g_ptr_array_new();
784 
785  gint i = 0;
786  for (i = 0; i < ui->infos->preview_time_windows->len; i++)
787  {
788  GtkWidget *wave_quality_da = gtk_drawing_area_new();
789  g_ptr_array_add(ui->gui->wave_quality_das, (gpointer)wave_quality_da);
790  ui->infos->preview_indexes[i].index = i;
791  ui->infos->preview_indexes[i].data = ui;
792 
793 #if GTK_MAJOR_VERSION <= 2
794  g_signal_connect(wave_quality_da, "expose_event", G_CALLBACK(wave_quality_draw_event),
795  &ui->infos->preview_indexes[i]);
796 #else
797  g_signal_connect(wave_quality_da, "draw", G_CALLBACK(wave_quality_draw_event),
798  &ui->infos->preview_indexes[i]);
799 #endif
800  wh_put_in_hbox_and_attach_to_vbox(wave_quality_da, vbox, 0);
801 
802  GtkWidget *minutes_label = gtk_label_new(NULL);
803  g_ptr_array_add(ui->gui->wave_preview_labels, minutes_label);
804  update_wave_preview_label_markup(i, -1, ui);
805 
806  wh_put_in_hbox_and_attach_to_vbox_with_bottom_margin(minutes_label, vbox, 0, 4);
807  }
808 
809  return vbox;
810 }
811 
812 static void update_wave_preview_label_markup(gint index, gint interpolation_level, ui_state *ui)
813 {
814  gint time_window = g_array_index(ui->infos->preview_time_windows, gint, index);
815 
816  gchar minutes_text[128] = { '\0' };
817  g_snprintf(minutes_text, 128, _("%d minute(s) window"), time_window / 100 / 60);
818 
819  gchar interpolation_text[256] = { '\0' };
820  if (interpolation_level >= 0)
821  {
822  g_snprintf(interpolation_text, 256, _("Wave interpolation level %d with threshold of %.1lf"),
823  interpolation_level + 1, ui->infos->douglas_peucker_thresholds[interpolation_level]);
824  }
825  else {
826  g_snprintf(interpolation_text, 256, _("No wave interpolation"));
827  }
828 
829  gchar final_text_with_color[512] = { '\0' };
830  g_snprintf(final_text_with_color, 512,
831  "<span color='#DD0000'>%s</span> - <span>%s</span>",
832  minutes_text, interpolation_text);
833 
834  GtkWidget *text_label = g_ptr_array_index(ui->gui->wave_preview_labels, index);
835  gtk_label_set_markup(GTK_LABEL(text_label), final_text_with_color);
836 }
837 
838 static GtkWidget *create_wave_options_box(ui_state *ui)
839 {
840  GtkWidget *vbox = wh_vbox_new();
841  GtkWidget *range_hbox = wh_hbox_new();
842 
843  GtkWidget *wave_quality_label =
844  gtk_label_new(_("Wave quality (higher is better but consumes more CPU):"));
845  gtk_box_pack_start(GTK_BOX(range_hbox), wave_quality_label, FALSE, FALSE, 0);
846 
847  GtkWidget *wave_quality_hscale = wh_hscale_new_with_range(-6.0, 6.0, 1.0);
848  gtk_scale_set_draw_value(GTK_SCALE(wave_quality_hscale), TRUE);
849  gtk_box_pack_start(GTK_BOX(range_hbox), wave_quality_hscale, FALSE, FALSE, 4);
850  gtk_widget_set_size_request(wave_quality_hscale, 160, 0);
851 
852  gtk_range_set_increments(GTK_RANGE(wave_quality_hscale), 1.0, 1.0);
853 
854  ui_register_range_preference("player", "wave_quality", 0.0,
855  wave_quality_hscale, (void (*)(GtkAdjustment *,gpointer))wave_quality_changed_event, ui, ui);
856 
857  GtkAdjustment *wave_quality_adjustment = gtk_range_get_adjustment(GTK_RANGE(wave_quality_hscale));
858  g_signal_connect(G_OBJECT(wave_quality_adjustment), "value-changed",
859  G_CALLBACK(wave_quality_changed_event), ui);
860 
861  gtk_box_pack_start(GTK_BOX(vbox), range_hbox, FALSE, FALSE, 0);
862 
863  return wh_set_title_and_get_vbox(vbox, _("<b>Amplitude wave options</b>"));
864 }
865 
867 static GtkWidget *create_pref_player_page(ui_state *ui)
868 {
869  GtkWidget *player_hbox = wh_hbox_new();;
870  GtkWidget *inside_hbox = wh_hbox_new();;
871 
872  GtkWidget *inside_vbox = wh_vbox_new();;
873  gtk_box_pack_start(GTK_BOX(inside_hbox), inside_vbox, TRUE, TRUE, 5);
874 
875  GtkWidget *player_scrolled_window = wh_create_scrolled_window();
876  ui->gui->player_scrolled_window = player_scrolled_window;
877  gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(player_scrolled_window),
878  GTK_WIDGET(inside_hbox));
879  gtk_box_pack_start(GTK_BOX(player_hbox), player_scrolled_window, TRUE, TRUE, 0);
880 
881  GtkWidget *vbox = wh_vbox_new();;
882  gtk_box_pack_start(GTK_BOX(inside_vbox), vbox, TRUE, TRUE, 0);
883 
884  GtkWidget *player_options_box = create_player_options_box(ui);
885  gtk_box_pack_start(GTK_BOX(vbox), player_options_box, FALSE, FALSE, 3);
886 
887  GtkWidget *wave_options_box = create_wave_options_box(ui);
888  gtk_box_pack_start(GTK_BOX(vbox), wave_options_box, FALSE, FALSE, 3);
889 
890  GtkWidget *wave_quality_box = create_wave_quality_preview_box(ui);
891  gtk_box_pack_start(GTK_BOX(inside_vbox), wave_quality_box, FALSE, FALSE, 0);
892 
893  return player_hbox;
894 }
895 
897 static gboolean output_entry_event(GtkWidget *widget, GdkEventKey *event, ui_state *ui)
898 {
899  const char *data = gtk_entry_get_text(GTK_ENTRY(ui->gui->output_entry));
900  gint error = mp3splt_set_oformat(ui->mp3splt_state, data);
901  remove_status_message(ui->gui);
903 
904  ui_save_preferences(NULL, ui);
905 
906  return FALSE;
907 }
908 
910 static GtkWidget *create_output_filename_box(ui_state *ui)
911 {
912  gui_state *gui = ui->gui;
913 
914  GtkWidget *vbox = wh_vbox_new();
915 
916  GtkWidget *horiz_fake = wh_hbox_new();
917  gtk_box_pack_start(GTK_BOX(vbox), horiz_fake, FALSE, FALSE, 5);
918 
919  //default/custom radio buttons
920  GtkWidget *radio_output = gtk_radio_button_new_with_label(NULL, _("Default format"));
921  gui->radio_output = radio_output;
922  gtk_box_pack_start(GTK_BOX(vbox), radio_output, FALSE, FALSE, 0);
923 
924  horiz_fake = wh_hbox_new();
925  gtk_box_pack_start(GTK_BOX(vbox), horiz_fake, FALSE, FALSE, 5);
926 
927  GString *outputs_str = g_string_new(_(" Default output: "));
928  g_string_append(outputs_str, "<span color='#222288'>");
929  g_string_append(outputs_str, SPLT_DEFAULT_OUTPUT);
930  g_string_append(outputs_str, "</span>");
931 
932  g_string_append(outputs_str, "\n");
933  g_string_append(outputs_str, _(" CDDB, CUE and tracktype.org default: "));
934  g_string_append(outputs_str, "<span color='#222288'>");
935  g_string_append(outputs_str, SPLT_DEFAULT_CDDB_CUE_OUTPUT);
936  g_string_append(outputs_str, "</span>");
937 
938  g_string_append(outputs_str, "\n");
939  g_string_append(outputs_str, _(" Split with silence detection default: "));
940  g_string_append(outputs_str, "<span color='#222288'>");
941  g_string_append(outputs_str, SPLT_DEFAULT_SILENCE_OUTPUT);
942  g_string_append(outputs_str, "</span>");
943 
944  g_string_append(outputs_str, "\n");
945  g_string_append(outputs_str, _(" Trim using silence detection default: "));
946  g_string_append(outputs_str, "<span color='#222288'>");
947  g_string_append(outputs_str, SPLT_DEFAULT_TRIM_SILENCE_OUTPUT);
948  g_string_append(outputs_str, "</span>");
949 
950  g_string_append(outputs_str, "\n");
951  g_string_append(outputs_str, _(" Error mode default: "));
952  g_string_append(outputs_str, "<span color='#222288'>");
953  g_string_append(outputs_str, SPLT_DEFAULT_SYNCERROR_OUTPUT);
954  g_string_append(outputs_str, "</span>");
955 
956  GtkWidget *default_label = gtk_label_new(NULL);
957  gui->output_default_label = default_label;
958  gtk_label_set_markup(GTK_LABEL(default_label), outputs_str->str);
959  gtk_label_set_selectable(GTK_LABEL(default_label), TRUE);
960  gtk_box_pack_start(GTK_BOX(horiz_fake), default_label, FALSE, FALSE, 0);
961 
962  g_string_free(outputs_str, TRUE);
963 
964  //second radio button
965  radio_output = gtk_radio_button_new_with_label_from_widget
966  (GTK_RADIO_BUTTON(radio_output), _("Custom format"));
967  gui->radio_output = radio_output;
968  gtk_box_pack_start(GTK_BOX(vbox), radio_output, FALSE, FALSE, 0);
969 
970  //output entry
971  horiz_fake = wh_hbox_new();
972  gtk_box_pack_start(GTK_BOX(vbox), horiz_fake, FALSE, FALSE, 5);
973 
974  GtkWidget *output_entry = gtk_entry_new();
975  gui->output_entry = output_entry;
976  gtk_editable_set_editable(GTK_EDITABLE(output_entry), TRUE);
977  g_signal_connect(G_OBJECT(output_entry), "key_release_event", G_CALLBACK(output_entry_event), ui);
978  gtk_entry_set_max_length(GTK_ENTRY(output_entry),244);
979  gtk_box_pack_start(GTK_BOX(horiz_fake), output_entry, TRUE, TRUE, 0);
980 
981  //output label
982  horiz_fake = wh_hbox_new();
983  gtk_box_pack_start(GTK_BOX(vbox), horiz_fake, FALSE, FALSE, 5);
984  GtkWidget *output_label = gtk_label_new(_(
985  " @A: performer if found, otherwise artist\n"
986  " @a: artist name\n"
987  " @p: performer of each song (only with .cue)\n"
988  " @b: album title\n"
989  " @g: genre\n"
990  " @t: song title\n"
991  " @n: track number identifier (not the real ID3 track number) **\n"
992  " @N: track tag number **\n"
993  " @l: track number identifier as lowercase letter (not the real ID3 track number) **\n"
994  " @L: track tag number as lowercase letter **\n"
995  " @u: track number identifier as uppercase letter (not the real ID3 track number) **\n"
996  " @U: track tag number as uppercase letter **\n"
997  " @f: input filename (without extension)\n"
998  " @m, @s or @h: the number of minutes, seconds or hundreths of seconds of the start splitpoint **\n"
999  " @M, @S or @H: the number of minutes, seconds or hundreths of seconds of the end splitpoint **\n"
1000  "\n"
1001  " (**) a digit may follow for the number of digits to output\n"));
1002  gtk_label_set_selectable(GTK_LABEL(output_label), TRUE);
1003  gui->output_label = output_label;
1004  gtk_box_pack_start(GTK_BOX(horiz_fake), output_label, FALSE, FALSE, 0);
1005 
1006  g_signal_connect(GTK_TOGGLE_BUTTON(gui->radio_output),
1007  "toggled", G_CALLBACK(output_radio_box_event), ui);
1008 
1009  return wh_set_title_and_get_vbox(vbox,
1010  _("<b>Output format for batch split and when importing splitpoints</b>"));
1011 }
1012 
1014 static GtkWidget *create_pref_output_page(ui_state *ui)
1015 {
1016  GtkWidget *output_hbox = wh_hbox_new();;
1017  GtkWidget *output_inside_hbox = wh_hbox_new();;
1018 
1019  GtkWidget *scrolled_window = wh_create_scrolled_window();
1020  gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window),
1021  GTK_WIDGET(output_inside_hbox));
1022  gtk_box_pack_start(GTK_BOX(output_hbox), scrolled_window, TRUE, TRUE, 0);
1023 
1024  GtkWidget *vbox = wh_vbox_new();;
1025  gtk_box_pack_start(GTK_BOX(output_inside_hbox), vbox, TRUE, TRUE, 5);
1026 
1027  GtkWidget *output_fname_box = create_output_filename_box(ui);
1028  gtk_box_pack_start(GTK_BOX(vbox), output_fname_box, FALSE, FALSE, 2);
1029 
1030  return output_hbox;
1031 }
1032 
1033 static void change_tags_options(GtkToggleButton *button, gpointer data)
1034 {
1035  ui_state *ui = (ui_state *)data;
1036 
1037  if (ui->gui->extract_tags_box != NULL)
1038  {
1039  if (rh_get_active_value(ui->gui->tags_radio) == TAGS_FROM_FILENAME)
1040  {
1041  gtk_widget_set_sensitive(ui->gui->extract_tags_box, SPLT_TRUE);
1042  }
1043  else
1044  {
1045  gtk_widget_set_sensitive(ui->gui->extract_tags_box, SPLT_FALSE);
1046  }
1047  }
1048 
1049  ui_save_preferences(NULL, ui);
1050 }
1051 
1053 static GtkWidget *create_tags_options_box(ui_state *ui)
1054 {
1055  gui_state *gui = ui->gui;
1056 
1057  GtkWidget *vbox = wh_vbox_new();
1058 
1059  GtkWidget *tags_radio = NULL;
1060  tags_radio = rh_append_radio_to_vbox(tags_radio, _("Original file tags"),
1061  ORIGINAL_FILE_TAGS, change_tags_options, ui, vbox);
1062  gui->tags_radio = tags_radio;
1063  tags_radio = rh_append_radio_to_vbox(tags_radio, _("Custom tags (from the splitpoints table)"),
1064  DEFAULT_TAGS, change_tags_options, ui, vbox);
1065  gui->tags_radio = tags_radio;
1066  tags_radio = rh_append_radio_to_vbox(tags_radio, _("No tags"),
1067  NO_TAGS, change_tags_options, ui, vbox);
1068  gui->tags_radio = tags_radio;
1069  tags_radio = rh_append_radio_to_vbox(tags_radio, _("Extract tags from filename"),
1070  TAGS_FROM_FILENAME, change_tags_options, ui, vbox);
1071  gui->tags_radio = tags_radio;
1072 
1073  GtkWidget *extract_tags_box = create_extract_tags_from_filename_options_box(ui);
1074  gui->extract_tags_box = extract_tags_box;
1075  gtk_widget_set_sensitive(extract_tags_box, SPLT_FALSE);
1076  gtk_box_pack_start(GTK_BOX(vbox), extract_tags_box, FALSE, FALSE, 2);
1077 
1078  return wh_set_title_and_get_vbox(vbox, _("<b>Split files tags</b>"));
1079 }
1080 
1081 static GtkComboBox *create_genre_combo(ui_state *ui)
1082 {
1083  GtkComboBox *combo = ch_new_combo();
1084 
1085  int i = 0;
1086  for (i = 0;i < SPLT_ID3V1_NUMBER_OF_GENRES;i++)
1087  {
1088  ch_append_to_combo(combo, splt_id3v1_genres[i], 0);
1089  }
1090 
1091  g_signal_connect(G_OBJECT(combo), "changed", G_CALLBACK(ui_save_preferences), ui);
1092 
1093  return combo;
1094 }
1095 
1096 static GtkComboBox *create_text_preferences_combo(ui_state *ui)
1097 {
1098  GtkComboBox *combo = ch_new_combo();
1099 
1100  ch_append_to_combo(combo, _("No change"), SPLT_NO_CONVERSION);
1101  ch_append_to_combo(combo, _("lowercase"), SPLT_TO_LOWERCASE);
1102  ch_append_to_combo(combo, _("UPPERCASE"), SPLT_TO_UPPERCASE);
1103  ch_append_to_combo(combo, _("First uppercase"), SPLT_TO_FIRST_UPPERCASE);
1104  ch_append_to_combo(combo, _("Word Uppercase"), SPLT_TO_WORD_FIRST_UPPERCASE);
1105 
1106  g_signal_connect(G_OBJECT(combo), "changed", G_CALLBACK(ui_save_preferences), ui);
1107 
1108  return combo;
1109 }
1110 
1111 static void test_regex_event(GtkWidget *widget, ui_state *ui)
1112 {
1113  put_tags_from_filename_regex_options(ui);
1114 
1115  const gchar *test_regex_filename = gtk_entry_get_text(GTK_ENTRY(ui->gui->test_regex_fname_entry));
1116  mp3splt_set_filename_to_split(ui->mp3splt_state, test_regex_filename);
1117 
1118  gint error = SPLT_OK;
1119  splt_tags *tags = mp3splt_parse_filename_regex(ui->mp3splt_state, &error);
1120  print_status_bar_confirmation(error, ui);
1121 
1122  if (error >= 0)
1123  {
1124  GString *regex_result = g_string_new(NULL);
1125 
1126  g_string_append(regex_result, _("<artist>: "));
1127  char *artist = mp3splt_tags_get(tags, SPLT_TAGS_ARTIST);
1128  if (artist)
1129  {
1130  g_string_append(regex_result, artist);
1131  free(artist);
1132  }
1133  g_string_append(regex_result, "\n");
1134 
1135  g_string_append(regex_result, _("<album>: "));
1136  char *album = mp3splt_tags_get(tags, SPLT_TAGS_ALBUM);
1137  if (album)
1138  {
1139  g_string_append(regex_result, album);
1140  free(album);
1141  }
1142  g_string_append(regex_result, "\n");
1143 
1144 
1145  g_string_append(regex_result, _("<title>: "));
1146  char *title = mp3splt_tags_get(tags, SPLT_TAGS_TITLE);
1147  if (title)
1148  {
1149  g_string_append(regex_result, title);
1150  free(title);
1151  }
1152  g_string_append(regex_result, "\n");
1153 
1154  g_string_append(regex_result, _("<genre>: "));
1155  char *genre = mp3splt_tags_get(tags, SPLT_TAGS_GENRE);
1156  if (genre)
1157  {
1158  g_string_append(regex_result, genre);
1159  free(genre);
1160  }
1161  g_string_append(regex_result, "\n");
1162 
1163  g_string_append(regex_result, _("<comment>: "));
1164  char *comment = mp3splt_tags_get(tags, SPLT_TAGS_COMMENT);
1165  if (comment)
1166  {
1167  g_string_append(regex_result, comment);
1168  free(comment);
1169  }
1170  g_string_append(regex_result, "\n");
1171 
1172  g_string_append(regex_result, _("<year>: "));
1173  char *year = mp3splt_tags_get(tags, SPLT_TAGS_YEAR);
1174  if (year)
1175  {
1176  g_string_append(regex_result, year);
1177  free(year);
1178  }
1179  g_string_append(regex_result, "\n");
1180 
1181  g_string_append(regex_result, _("<track>: "));
1182  gchar *track = mp3splt_tags_get(tags, SPLT_TAGS_TRACK);
1183  if (track)
1184  {
1185  g_string_append(regex_result, track);
1186  free(track);
1187  }
1188 
1189  gchar *regex_result_text = g_string_free(regex_result, FALSE);
1190  if (regex_result_text)
1191  {
1192  gtk_label_set_text(GTK_LABEL(ui->gui->sample_result_label), regex_result_text);
1193  g_free(regex_result_text);
1194  }
1195  }
1196  else
1197  {
1198  gtk_label_set_text(GTK_LABEL(ui->gui->sample_result_label), "");
1199  }
1200 
1201  mp3splt_free_one_tag(tags);
1202 }
1203 
1204 static GtkWidget *create_extract_tags_from_filename_options_box(ui_state *ui)
1205 {
1206  GtkWidget *table = wh_new_table();
1207 
1208  GtkWidget *regex_entry = wh_new_entry(ui_save_preferences, ui);
1209  ui->gui->regex_entry = regex_entry;
1210  wh_add_in_table_with_label_expand(table, _("Regular expression:"), regex_entry);
1211 
1212  GtkWidget *regex_label = gtk_label_new(_(
1213  "Above enter PERL-like regular expression using named subgroups.\nFollowing names are recognized:\n"
1214  " (?<artist>) - artist name\n"
1215  " (?<album>) - album title\n"
1216  " (?<title>) - track title\n"
1217  " (?<tracknum>) - current track number\n"
1218  //" (?<tracks>) - total number of tracks\n"
1219  " (?<year>) - year of emission\n"
1220  " (?<genre>) - genre\n"
1221  " (?<comment>) - comment"));
1222  gtk_label_set_selectable(GTK_LABEL(regex_label), TRUE);
1223  gtk_misc_set_alignment(GTK_MISC(regex_label), 0.0, 0.5);
1224  wh_add_in_table(table, wh_put_in_new_hbox_with_margin_level(regex_label, 2));
1225 
1226  ui_infos *infos = ui->infos;
1227 
1228  infos->text_options_list =
1229  g_list_append(infos->text_options_list, GINT_TO_POINTER(SPLT_NO_CONVERSION));
1230  infos->text_options_list =
1231  g_list_append(infos->text_options_list, GINT_TO_POINTER(SPLT_TO_LOWERCASE));
1232  infos->text_options_list =
1233  g_list_append(infos->text_options_list, GINT_TO_POINTER(SPLT_TO_UPPERCASE));
1234  infos->text_options_list =
1235  g_list_append(infos->text_options_list, GINT_TO_POINTER(SPLT_TO_FIRST_UPPERCASE));
1236  infos->text_options_list =
1237  g_list_append(infos->text_options_list, GINT_TO_POINTER(SPLT_TO_WORD_FIRST_UPPERCASE));
1238 
1239  GtkWidget *replace_underscore_by_space_check_box =
1240  gtk_check_button_new_with_mnemonic(_("_Replace underscores by spaces"));
1241  ui->gui->replace_underscore_by_space_check_box = replace_underscore_by_space_check_box;
1242  g_signal_connect(G_OBJECT(replace_underscore_by_space_check_box), "toggled",
1243  G_CALLBACK(ui_save_preferences), ui);
1244 
1245  wh_add_in_table(table, replace_underscore_by_space_check_box);
1246 
1247  GtkComboBox *artist_text_properties_combo = create_text_preferences_combo(ui);
1248  ui->gui->artist_text_properties_combo = artist_text_properties_combo;
1249  wh_add_in_table_with_label(table,
1250  _("Artist text properties:"), GTK_WIDGET(artist_text_properties_combo));
1251 
1252  GtkComboBox *album_text_properties_combo = create_text_preferences_combo(ui);
1253  ui->gui->album_text_properties_combo = album_text_properties_combo;
1254  wh_add_in_table_with_label(table,
1255  _("Album text properties:"), GTK_WIDGET(album_text_properties_combo));
1256 
1257  GtkComboBox *title_text_properties_combo = create_text_preferences_combo(ui);
1258  ui->gui->title_text_properties_combo = title_text_properties_combo;
1259  wh_add_in_table_with_label(table,
1260  _("Title text properties:"), GTK_WIDGET(title_text_properties_combo));
1261 
1262  GtkComboBox *comment_text_properties_combo = create_text_preferences_combo(ui);
1263  ui->gui->comment_text_properties_combo = comment_text_properties_combo;
1264  wh_add_in_table_with_label(table,
1265  _("Comment text properties:"), GTK_WIDGET(comment_text_properties_combo));
1266 
1267  GtkComboBox *genre_combo = create_genre_combo(ui);
1268  ui->gui->genre_combo = genre_combo;
1269  wh_add_in_table_with_label(table, _("Genre tag:"), GTK_WIDGET(genre_combo));
1270 
1271  GtkWidget *comment_tag_entry = wh_new_entry(ui_save_preferences, ui);
1272  ui->gui->comment_tag_entry = comment_tag_entry;
1273  wh_add_in_table_with_label_expand(table, _("Comment tag:"), comment_tag_entry);
1274 
1275  GtkWidget *test_regex_expander = gtk_expander_new(_("Regular expression test"));
1276  gtk_container_add(GTK_CONTAINER(test_regex_expander), create_test_regex_table(ui));
1277  wh_add_in_table(table, test_regex_expander);
1278 
1279  return wh_put_in_new_hbox_with_margin_level(GTK_WIDGET(table), 3);
1280 }
1281 
1282 static GtkWidget *create_test_regex_table(ui_state *ui)
1283 {
1284  GtkWidget *table = wh_new_table();
1285 
1286  GtkWidget *sample_test_hbox = wh_hbox_new();
1287  GtkWidget *test_regex_fname_entry = wh_new_entry(ui_save_preferences, ui);
1288  ui->gui->test_regex_fname_entry = test_regex_fname_entry;
1289  gtk_box_pack_start(GTK_BOX(sample_test_hbox), test_regex_fname_entry, TRUE, TRUE, 0);
1290 
1291  GtkWidget *test_regex_button = wh_new_button(_("_Test"));
1292  gtk_box_pack_start(GTK_BOX(sample_test_hbox), test_regex_button, FALSE, FALSE, 5);
1293  g_signal_connect(G_OBJECT(test_regex_button), "clicked", G_CALLBACK(test_regex_event), ui);
1294 
1295  wh_add_in_table_with_label_expand(table, _("Sample filename:"), sample_test_hbox);
1296 
1297  GtkWidget *sample_result_label = gtk_label_new("");
1298  ui->gui->sample_result_label = sample_result_label;
1299  gtk_misc_set_alignment(GTK_MISC(ui->gui->sample_result_label), 0.0, 0.5);
1300  wh_add_in_table_with_label_expand(table, _("Sample result:"), ui->gui->sample_result_label);
1301 
1302  return wh_put_in_new_hbox_with_margin_level(GTK_WIDGET(table), 3);
1303 }
1304 
1306 static GtkWidget *create_tags_version_box(ui_state *ui)
1307 {
1308  gui_state *gui = ui->gui;
1309 
1310  GtkWidget *vbox = wh_vbox_new();
1311 
1312  GtkWidget *tags_version_radio = gtk_radio_button_new_with_label(NULL, _("ID3v1 & ID3v2 tags"));
1313  gui->tags_version_radio = tags_version_radio;
1314  gtk_box_pack_start(GTK_BOX(vbox), tags_version_radio, FALSE, FALSE, 0);
1315  g_signal_connect(GTK_TOGGLE_BUTTON(tags_version_radio), "toggled",
1316  G_CALLBACK(ui_save_preferences), ui);
1317 
1318  tags_version_radio = gtk_radio_button_new_with_label_from_widget
1319  (GTK_RADIO_BUTTON(tags_version_radio), _("ID3v2 tags"));
1320  gui->tags_version_radio = tags_version_radio;
1321  gtk_box_pack_start(GTK_BOX(vbox), tags_version_radio, FALSE, FALSE, 0);
1322  g_signal_connect(GTK_TOGGLE_BUTTON(tags_version_radio), "toggled",
1323  G_CALLBACK(ui_save_preferences), ui);
1324 
1325  tags_version_radio = gtk_radio_button_new_with_label_from_widget
1326  (GTK_RADIO_BUTTON(tags_version_radio), _("ID3v1 tags"));
1327  gui->tags_version_radio = tags_version_radio;
1328  g_signal_connect(GTK_TOGGLE_BUTTON(tags_version_radio), "toggled",
1329  G_CALLBACK(ui_save_preferences), ui);
1330  gtk_box_pack_start(GTK_BOX(vbox), tags_version_radio, FALSE, FALSE, 0);
1331 
1332  tags_version_radio = gtk_radio_button_new_with_label_from_widget
1333  (GTK_RADIO_BUTTON (tags_version_radio),_("Same tags version as the input file"));
1334  gui->tags_version_radio = tags_version_radio;
1335  g_signal_connect(GTK_TOGGLE_BUTTON(tags_version_radio), "toggled",
1336  G_CALLBACK(ui_save_preferences), ui);
1337  gtk_box_pack_start(GTK_BOX(vbox), tags_version_radio, FALSE, FALSE, 0);
1338 
1339  return wh_set_title_and_get_vbox(vbox, _("<b>Tags version (mp3 only)</b>"));
1340 }
1341 
1343 static GtkWidget *create_pref_tags_page(ui_state *ui)
1344 {
1345  GtkWidget *outside_vbox = wh_vbox_new();;
1346  GtkWidget *inside_hbox = wh_hbox_new();
1347 
1348  GtkWidget *scrolled_window = wh_create_scrolled_window();
1349  gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window),
1350  GTK_WIDGET(inside_hbox));
1351  gtk_box_pack_start(GTK_BOX(outside_vbox), scrolled_window, TRUE, TRUE, 0);
1352 
1353  GtkWidget *vbox = wh_vbox_new();;
1354  gtk_box_pack_start(GTK_BOX(inside_hbox), vbox, TRUE, TRUE, 5);
1355 
1356  GtkWidget *tags_version_box = create_tags_version_box(ui);
1357  gtk_box_pack_start(GTK_BOX(vbox), tags_version_box, FALSE, FALSE, 2);
1358 
1359  GtkWidget *tags_opts_box = create_tags_options_box(ui);
1360  gtk_box_pack_start(GTK_BOX(vbox), tags_opts_box, FALSE, FALSE, 1);
1361 
1362  return outside_vbox;
1363 }
1364 
1367 {
1368  GtkWidget *pref_vbox = wh_vbox_new();
1369 
1370  GtkWidget *notebook = gtk_notebook_new();
1371  gtk_box_pack_start(GTK_BOX(pref_vbox), notebook, TRUE, TRUE, 0);
1372 
1373  gtk_notebook_popup_enable(GTK_NOTEBOOK(notebook));
1374  gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook), TRUE);
1375  gtk_notebook_set_show_border(GTK_NOTEBOOK(notebook), FALSE);
1376  gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
1377 
1378  /* split preferences */
1379  GtkWidget *splitpoints_prefs = create_pref_splitpoints_page(ui);
1380  GtkWidget *notebook_label = gtk_label_new(_("Split"));
1381  gtk_notebook_append_page(GTK_NOTEBOOK(notebook), splitpoints_prefs, notebook_label);
1382 
1383  /* tags preferences */
1384  GtkWidget *tags_prefs = create_pref_tags_page(ui);
1385  notebook_label = gtk_label_new(_("Tags"));
1386  gtk_notebook_append_page(GTK_NOTEBOOK(notebook), tags_prefs, notebook_label);
1387 
1388  /* player preferences */
1389  GtkWidget *player_prefs = create_pref_player_page(ui);
1390  notebook_label = gtk_label_new(_("Player"));
1391  gtk_notebook_append_page(GTK_NOTEBOOK(notebook), player_prefs, notebook_label);
1392 
1393  /* output preferences */
1394  GtkWidget *output_prefs = create_pref_output_page(ui);
1395  notebook_label = gtk_label_new(_("Output format"));
1396  gtk_notebook_append_page(GTK_NOTEBOOK(notebook), output_prefs, notebook_label);
1397 
1398  /* language preferences page */
1399 #ifdef __WIN32__
1400  GtkWidget *language_prefs = create_pref_language_page(ui);
1401  notebook_label = gtk_label_new(_("Language"));
1402  gtk_notebook_append_page(GTK_NOTEBOOK(notebook), language_prefs, notebook_label);
1403 #endif
1404 
1405  return pref_vbox;
1406 }
1407 
gfloat get_left_drawing_time(gfloat current_time, gfloat total_time, gfloat zoom_coeff)
returns the value of the left drawing area
GtkWidget * wh_create_scrolled_window()
creates a scrolled window
gfloat get_right_drawing_time(gfloat current_time, gfloat total_time, gfloat zoom_coeff)
returns the value of the right drawing area
gchar * get_input_filename(gui_state *gui)
Get the name of the input file.
Definition: main_window.c:76
void print_status_bar_confirmation(gint error, ui_state *ui)
Output an error message from libmp3splt to the status bar.
Definition: main_window.c:1115
void disconnect_button_event(GtkWidget *widget, ui_state *ui)
disconnect button event
gchar * get_output_directory(ui_state *ui)
Get the name of the output directory.
GString * get_checked_language(ui_state *ui)
Returns the selected language.
gint get_checked_tags_version_radio_box(gui_state *gui)
returns the checked tags radio box
gboolean get_checked_output_radio_box(ui_state *ui)
returns the checked output radio box
gint draw_silence_wave(gint left_mark, gint right_mark, gint interpolation_text_x, gint interpolation_text_y, gfloat draw_time, gint width_drawing_area, gint y_margin, gfloat current_time, gfloat total_time, gfloat zoom_coeff, GtkWidget *da, cairo_t *gc, ui_state *ui)
Draws the silence wave.
GtkWidget * wh_set_title_and_get_vbox(GtkWidget *widget, const gchar *title)
Generates a window portion containing a caption and a vbox.
GtkWidget * wh_create_cool_button(gchar *stock_id, gchar *label_text, gint toggle_or_not)
creates a cool button with image from stock
void show_connect_button(gui_state *gui)
Show the connect button.
void hide_connect_button(gui_state *gui)
Hide the connect button.
void remove_status_message(gui_state *gui)
Removes status bar message.
Definition: main_window.c:252
GtkWidget * create_choose_preferences(ui_state *ui)
creates the preferences tab