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-2012 Alexandru Munteanu
7  * Contact: io_fx@yahoo.fr
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
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 
112 void set_output_directory(gchar *dirname, ui_state *ui)
113 {
114  if (dirname == NULL)
115  {
116  return;
117  }
118 
119  lock_mutex(&ui->variables_mutex);
120  if (ui->infos->outputdirname != NULL)
121  {
122  g_string_free(ui->infos->outputdirname, TRUE);
123  }
124  ui->infos->outputdirname = g_string_new(dirname);
125  unlock_mutex(&ui->variables_mutex);
126 
127  gtk_entry_set_text(GTK_ENTRY(ui->gui->directory_entry), dirname);
128 }
129 
137 {
138  if (ui->infos->outputdirname != NULL)
139  {
140  return ui->infos->outputdirname->str;
141  }
142 
143  return NULL;
144 }
145 
147 static void output_radio_box_event(GtkToggleButton *radio_b, ui_state *ui)
148 {
149  gint selected = get_checked_output_radio_box(ui);
150  if (selected == 0)
151  {
152  gtk_widget_set_sensitive(ui->gui->output_entry, TRUE);
153  gtk_widget_set_sensitive(ui->gui->output_label, TRUE);
154  mp3splt_set_int_option(ui->mp3splt_state, SPLT_OPT_OUTPUT_FILENAMES, SPLT_OUTPUT_FORMAT);
155  gtk_widget_set_sensitive(ui->gui->output_default_label, FALSE);
156  }
157  else
158  {
159  gtk_widget_set_sensitive(ui->gui->output_entry, FALSE);
160  gtk_widget_set_sensitive(ui->gui->output_label, FALSE);
161  mp3splt_set_int_option(ui->mp3splt_state, SPLT_OPT_OUTPUT_FILENAMES, SPLT_OUTPUT_DEFAULT);
162  gtk_widget_set_sensitive(ui->gui->output_default_label, TRUE);
163  }
164 
165  ui_save_preferences(NULL, ui);
166 }
167 
168 #ifdef __WIN32__
169 
171 static GtkWidget *create_language_box(ui_state *ui)
172 {
173  GtkWidget *radio_vbox = wh_vbox_new();
174 
175  GtkWidget *radio_button = gtk_radio_button_new_with_label(NULL, "English");
176  ui->gui->radio_button = radio_button;
177  g_signal_connect(GTK_TOGGLE_BUTTON(radio_button), "toggled",
178  G_CALLBACK(ui_save_preferences), ui);
179  gtk_box_pack_start(GTK_BOX(radio_vbox), radio_button, TRUE, TRUE, 0);
180 
181  radio_button = gtk_radio_button_new_with_label_from_widget
182  (GTK_RADIO_BUTTON(radio_button), "Français");
183  ui->gui->radio_button = radio_button;
184  g_signal_connect(GTK_TOGGLE_BUTTON(radio_button), "toggled",
185  G_CALLBACK(ui_save_preferences), ui);
186  gtk_box_pack_start(GTK_BOX(radio_vbox), radio_button, TRUE, TRUE, 0);
187 
188  radio_button = gtk_radio_button_new_with_label_from_widget
189  (GTK_RADIO_BUTTON(radio_button), "Deutsch");
190  ui->gui->radio_button = radio_button;
191  g_signal_connect(GTK_TOGGLE_BUTTON (radio_button), "toggled",
192  G_CALLBACK(ui_save_preferences), ui);
193  gtk_box_pack_start(GTK_BOX(radio_vbox), radio_button, TRUE, TRUE, 0);
194 
195  return wh_set_title_and_get_vbox(radio_vbox,
196  _("<b>Choose language (requires restart)</b>"));
197 }
198 
200 static GtkWidget *create_pref_language_page(ui_state *ui)
201 {
202  GtkWidget *language_hbox = wh_hbox_new();;
203  GtkWidget *language_inside_hbox = wh_hbox_new();;
204 
205  GtkWidget *scrolled_window = wh_create_scrolled_window();
206  gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window),
207  GTK_WIDGET(language_inside_hbox));
208  gtk_box_pack_start(GTK_BOX(language_hbox), scrolled_window, TRUE, TRUE, 0);
209 
210  GtkWidget *vbox = wh_vbox_new();;
211  gtk_box_pack_start(GTK_BOX(language_inside_hbox), vbox, TRUE, TRUE, 10);
212 
213  GtkWidget *lang_box = create_language_box(ui);
214  gtk_box_pack_start(GTK_BOX(vbox), lang_box, FALSE, FALSE, 10);
215 
216  return language_hbox;
217 }
218 #endif
219 
221 static void browse_dir_button_event(GtkWidget *widget, ui_state *ui)
222 {
223  GtkWidget *dir_chooser = gtk_file_chooser_dialog_new(_("Choose split directory"),
224  NULL,
225  GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
226  GTK_STOCK_CANCEL,
227  GTK_RESPONSE_CANCEL,
228  GTK_STOCK_OPEN,
229  GTK_RESPONSE_ACCEPT,
230  NULL);
231 
232  wh_set_browser_directory_handler(ui, dir_chooser);
233 
234  if (gtk_dialog_run(GTK_DIALOG(dir_chooser)) == GTK_RESPONSE_ACCEPT)
235  {
236  gchar *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dir_chooser));
237  set_output_directory(filename, ui);
238 
239  g_free(filename);
240  filename = NULL;
241 
242  ui_save_preferences(NULL, ui);
243  }
244 
245  gtk_widget_destroy(dir_chooser);
246 }
247 
249 static void disable_adjust_spinners(gui_state *gui)
250 {
251  gtk_widget_set_sensitive(gui->spinner_adjust_threshold, FALSE);
252  gtk_widget_set_sensitive(gui->spinner_adjust_offset, FALSE);
253  gtk_widget_set_sensitive(gui->spinner_adjust_gap, FALSE);
254  gtk_widget_set_sensitive(gui->threshold_label, FALSE);
255  gtk_widget_set_sensitive(gui->offset_label, FALSE);
256  gtk_widget_set_sensitive(gui->gap_label, FALSE);
257 }
258 
260 static void enable_adjust_spinners(gui_state *gui)
261 {
262  gtk_widget_set_sensitive(gui->spinner_adjust_threshold, TRUE);
263  gtk_widget_set_sensitive(gui->spinner_adjust_offset, TRUE);
264  gtk_widget_set_sensitive(gui->spinner_adjust_gap, TRUE);
265  gtk_widget_set_sensitive(gui->threshold_label, TRUE);
266  gtk_widget_set_sensitive(gui->offset_label, TRUE);
267  gtk_widget_set_sensitive(gui->gap_label, TRUE);
268 }
269 
271 static void adjust_event(GtkToggleButton *adjust_mode, ui_state *ui)
272 {
273  if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(adjust_mode)))
274  {
275  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ui->gui->frame_mode),TRUE);
276  enable_adjust_spinners(ui->gui);
277  }
278  else
279  {
280  disable_adjust_spinners(ui->gui);
281  }
282 
283  ui_save_preferences(NULL, ui);
284 }
285 
287 static void frame_event(GtkToggleButton *frame_mode, ui_state *ui)
288 {
289  if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(frame_mode)))
290  {
291  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ui->gui->adjust_mode),FALSE);
292  }
293 
294  ui_save_preferences(NULL, ui);
295 }
296 
297 static void splitpoints_from_filename_event(GtkToggleButton *frame_mode, ui_state *ui)
298 {
299  gint splitpoints_from_filename = gtk_toggle_button_get_active(ui->gui->names_from_filename);
300  if (splitpoints_from_filename == TRUE && ui->status->file_browsed == TRUE)
301  {
302  copy_filename_to_current_description(get_input_filename(ui->gui), ui);
303  }
304  else
305  {
306  clear_current_description(ui);
307  }
308 
309  ui_save_preferences(NULL, ui);
310 }
311 
313 static void set_default_prefs_event(GtkWidget *widget, ui_state *ui)
314 {
315  gui_state *gui = ui->gui;
316 
317  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gui->frame_mode), FALSE);
318  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gui->adjust_mode), FALSE);
319  gtk_spin_button_set_value(GTK_SPIN_BUTTON(gui->spinner_adjust_threshold),
321  gtk_spin_button_set_value(GTK_SPIN_BUTTON(gui->spinner_adjust_offset),
323  gtk_spin_button_set_value(GTK_SPIN_BUTTON(gui->spinner_adjust_gap),
325  gtk_toggle_button_set_active(gui->names_from_filename, FALSE);
326  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gui->create_dirs_from_output_files), TRUE);
327 
328  ui_save_preferences(NULL, ui);
329 }
330 
332 static void song_dir_button_event(GtkWidget *widget, ui_state *ui)
333 {
334  set_output_directory("", ui);
335  ui_save_preferences(NULL, ui);
336 }
337 
339 static GtkWidget *create_directory_box(ui_state *ui)
340 {
341  gui_state *gui = ui->gui;
342 
343  GtkWidget *dir_hbox = wh_hbox_new();
344 
345  GtkWidget *directory_entry = gtk_entry_new();
346  gui->directory_entry = directory_entry;
347  gtk_editable_set_editable(GTK_EDITABLE(directory_entry), FALSE);
348  gtk_box_pack_start(GTK_BOX(dir_hbox), directory_entry, TRUE, TRUE, 0);
349 
350  // Put the right text into the text box containing the output directory
351  // name if this name was provided on command line
352  if (get_output_directory(ui) != NULL)
353  {
354  gtk_entry_set_text(GTK_ENTRY(directory_entry), get_output_directory(ui));
355  }
356 
357  //browse dir button
358  GtkWidget *browse_dir_button =
359  wh_create_cool_button(GTK_STOCK_DIRECTORY,_("Br_owse dir"), FALSE);
360  g_signal_connect(G_OBJECT(browse_dir_button), "clicked",
361  G_CALLBACK(browse_dir_button_event), ui);
362  gtk_box_pack_start(GTK_BOX(dir_hbox), browse_dir_button, FALSE, FALSE, 8);
363 
364  //to set the directory for split files to the current song directory
365  GtkWidget *song_dir_button =
366  wh_create_cool_button(GTK_STOCK_CLEAR, _("So_ng dir"), FALSE);
367  g_signal_connect(G_OBJECT(song_dir_button), "clicked",
368  G_CALLBACK(song_dir_button_event), ui);
369  gtk_box_pack_start(GTK_BOX(dir_hbox), song_dir_button, FALSE, FALSE, 0);
370 
371  return wh_set_title_and_get_vbox(dir_hbox, _("<b>Directory for split files</b>"));
372 }
373 
375 static GtkWidget *create_split_options_box(ui_state *ui)
376 {
377  gui_state *gui = ui->gui;
378 
379  GtkWidget *vbox = wh_vbox_new();
380 
381  //names from filename
382  GtkToggleButton *names_from_filename =
383  GTK_TOGGLE_BUTTON(gtk_check_button_new_with_mnemonic(
384  _("_Splitpoint name from filename (manual single file split only)")));
385  gui->names_from_filename = names_from_filename;
386 
387  gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(names_from_filename), FALSE, FALSE, 0);
388  g_signal_connect(G_OBJECT(names_from_filename), "toggled",
389  G_CALLBACK(splitpoints_from_filename_event), ui);
390 
391  GtkWidget *create_dirs_from_output_files =
392  gtk_check_button_new_with_mnemonic(_("Create directories from _filenames "));
393  gui->create_dirs_from_output_files = create_dirs_from_output_files;
394  gtk_box_pack_start(GTK_BOX(vbox), create_dirs_from_output_files, FALSE, FALSE, 0);
395  g_signal_connect(G_OBJECT(create_dirs_from_output_files), "toggled",
396  G_CALLBACK(ui_save_preferences), ui);
397 
398  //frame mode option
399  GtkWidget *frame_mode =
400  gtk_check_button_new_with_mnemonic(_("F_rame mode (useful for mp3 VBR) (mp3 only)"));
401  gui->frame_mode = frame_mode;
402  gtk_box_pack_start(GTK_BOX(vbox), frame_mode, FALSE, FALSE, 0);
403  g_signal_connect(G_OBJECT(frame_mode), "toggled", G_CALLBACK(frame_event), ui);
404 
405  //auto adjust option
406  GtkWidget *adjust_mode = gtk_check_button_new_with_mnemonic(_("_Auto-adjust mode (uses"
407  " silence detection to auto-adjust splitpoints)"));
408  gui->adjust_mode = adjust_mode;
409  gtk_box_pack_start(GTK_BOX(vbox), adjust_mode, FALSE, FALSE, 0);
410  g_signal_connect(G_OBJECT(adjust_mode), "toggled", G_CALLBACK(adjust_event), ui);
411 
412  //parameters for the adjust option
413  GtkWidget *horiz_fake = wh_hbox_new();
414  gtk_box_pack_start(GTK_BOX(vbox), horiz_fake, FALSE, FALSE, 0);
415 
416  GtkWidget *param_vbox = wh_vbox_new();
417  gtk_box_pack_start(GTK_BOX(horiz_fake), param_vbox, FALSE, FALSE, 25);
418 
419  //threshold level
420  horiz_fake = wh_hbox_new();
421  gtk_box_pack_start(GTK_BOX(param_vbox), horiz_fake, FALSE, FALSE, 0);
422 
423  GtkWidget *threshold_label = gtk_label_new(_("Threshold level (dB):"));
424  gui->threshold_label = threshold_label;
425  gtk_box_pack_start(GTK_BOX(horiz_fake), threshold_label, FALSE, FALSE, 0);
426 
427  GtkAdjustment *adj = (GtkAdjustment *) gtk_adjustment_new(0.0, -96.0, 0.0,
428  0.5, 10.0, 0.0);
429  GtkWidget *spinner_adjust_threshold = gtk_spin_button_new (adj, 0.5, 2);
430  gui->spinner_adjust_threshold = spinner_adjust_threshold;
431  g_signal_connect(G_OBJECT(spinner_adjust_threshold), "value_changed",
432  G_CALLBACK(ui_save_preferences), ui);
433  gtk_box_pack_start(GTK_BOX(horiz_fake), spinner_adjust_threshold,
434  FALSE, FALSE, 6);
435 
436  //offset level
437  horiz_fake = wh_hbox_new();
438  gtk_box_pack_start(GTK_BOX(param_vbox), horiz_fake, FALSE, FALSE, 0);
439 
440  GtkWidget *offset_label = gtk_label_new(_("Cutpoint offset (0 is the begin of silence "
441  "and 1 the end):"));
442  gui->offset_label = offset_label;
443  gtk_box_pack_start(GTK_BOX(horiz_fake), offset_label, FALSE, FALSE, 0);
444 
445  //adjustement for the offset spinner
446  adj = (GtkAdjustment *)gtk_adjustment_new(0.0, -2, 2, 0.05, 10.0, 0.0);
447  GtkWidget *spinner_adjust_offset = gtk_spin_button_new (adj, 0.05, 2);
448  gui->spinner_adjust_offset = spinner_adjust_offset;
449  g_signal_connect(G_OBJECT(spinner_adjust_offset), "value_changed",
450  G_CALLBACK(ui_save_preferences), ui);
451  gtk_box_pack_start(GTK_BOX(horiz_fake), spinner_adjust_offset, FALSE, FALSE, 6);
452 
453  //gap level (seconds)
454  horiz_fake = wh_hbox_new();
455  gtk_box_pack_start(GTK_BOX(param_vbox), horiz_fake, FALSE, FALSE, 0);
456 
457  GtkWidget *gap_label =
458  gtk_label_new(_("Gap level (seconds around splitpoint to search for silence):"));
459  gui->gap_label = gap_label;
460  gtk_box_pack_start(GTK_BOX(horiz_fake), gap_label, FALSE, FALSE, 0);
461 
462  adj = (GtkAdjustment *) gtk_adjustment_new(0.0, 0, 2000, 1.0, 10.0, 0.0);
463  GtkWidget *spinner_adjust_gap = gtk_spin_button_new (adj, 1, 0);
464  gui->spinner_adjust_gap = spinner_adjust_gap;
465  g_signal_connect(G_OBJECT(spinner_adjust_gap), "value_changed",
466  G_CALLBACK(ui_save_preferences), ui);
467  gtk_box_pack_start(GTK_BOX(horiz_fake), spinner_adjust_gap, FALSE, FALSE, 6);
468 
469  disable_adjust_spinners(ui->gui);
470 
471  //set default preferences button
472  horiz_fake = wh_hbox_new();
473  gtk_box_pack_start(GTK_BOX(vbox), horiz_fake, FALSE, FALSE, 0);
474 
475  GtkWidget *set_default_prefs_button =
476  wh_create_cool_button(GTK_STOCK_PROPERTIES, _("Set _default split options"),FALSE);
477  g_signal_connect(G_OBJECT(set_default_prefs_button), "clicked",
478  G_CALLBACK(set_default_prefs_event), ui);
479  gtk_box_pack_start (GTK_BOX (horiz_fake), set_default_prefs_button, FALSE, FALSE, 5);
480 
481  return wh_set_title_and_get_vbox(vbox, _("<b>Split options</b>"));
482 }
483 
485 static GtkWidget *create_pref_splitpoints_page(ui_state *ui)
486 {
487  GtkWidget *general_hbox = wh_hbox_new();
488  GtkWidget *inside_hbox = wh_hbox_new();
489 
490  GtkWidget *scrolled_window = wh_create_scrolled_window();
491  gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window),
492  GTK_WIDGET(inside_hbox));
493  gtk_box_pack_start(GTK_BOX(general_hbox), scrolled_window, TRUE, TRUE, 0);
494 
495  GtkWidget *inside_vbox = wh_vbox_new();
496  gtk_box_pack_start(GTK_BOX(inside_hbox), inside_vbox, TRUE, TRUE, 5);
497 
498  GtkWidget *dir_box = create_directory_box(ui);
499  gtk_box_pack_start(GTK_BOX(inside_vbox), dir_box, FALSE, FALSE, 2);
500 
501  GtkWidget *split_options_box = create_split_options_box(ui);
502  gtk_box_pack_start(GTK_BOX(inside_vbox), split_options_box, FALSE, FALSE, 1);
503 
504  return general_hbox;
505 }
506 
508 static void player_combo_box_event(GtkComboBox *widget, ui_state *ui)
509 {
510  disconnect_button_event(ui->gui->disconnect_button, ui);
511 
512  ui->infos->selected_player = ch_get_active_value(widget);
513  if (ui->infos->selected_player == PLAYER_GSTREAMER)
514  {
515  hide_connect_button(ui->gui);
516  gtk_widget_show(ui->gui->playlist_box);
517  }
518  else
519  {
520  show_connect_button(ui->gui);
521  gtk_widget_hide(ui->gui->playlist_box);
522  }
523 
524  gtk_widget_show(ui->gui->player_box);
525  gtk_widget_show(ui->gui->queue_files_button);
526 
527  ui_save_preferences(NULL, ui);
528 }
529 
530 static void update_timeout_value(GtkWidget *spinner, ui_state *ui)
531 {
532  ui->infos->timeout_value = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spinner));
533 
534  restart_player_timer(ui);
535  ui_save_preferences(NULL, ui);
536 }
537 
539 static GtkWidget *create_player_options_box(ui_state *ui)
540 {
541  GtkWidget *vbox = wh_vbox_new();
542  GtkWidget *horiz_fake = wh_hbox_new();
543 
544  GtkWidget *label = gtk_label_new(_("Player:"));
545  gtk_box_pack_start(GTK_BOX(horiz_fake), label, FALSE, FALSE, 0);
546 
547  GtkWidget *player_combo_box = GTK_WIDGET(ch_new_combo());
548  ui->gui->player_combo_box = player_combo_box;
549 
550 #ifndef NO_AUDACIOUS
551  ch_append_to_combo(GTK_COMBO_BOX(player_combo_box), "Audacious", PLAYER_AUDACIOUS);
552 #endif
553  ch_append_to_combo(GTK_COMBO_BOX(player_combo_box), "SnackAmp", PLAYER_SNACKAMP);
554 #ifndef NO_GSTREAMER
555  ch_append_to_combo(GTK_COMBO_BOX(player_combo_box), "GStreamer", PLAYER_GSTREAMER);
556 #endif
557 
558  g_signal_connect(G_OBJECT(player_combo_box), "changed", G_CALLBACK(player_combo_box_event), ui);
559 
560  gtk_box_pack_start(GTK_BOX(horiz_fake), player_combo_box, FALSE, FALSE, 5);
561  gtk_box_pack_start(GTK_BOX(vbox), horiz_fake, FALSE, FALSE, 0);
562 
563  GtkWidget *spinner = wh_create_int_spinner_in_box(_("Refresh player every "),
564  _("milliseconds."),
565  (gdouble)DEFAULT_TIMEOUT_VALUE, 20.0, 1000.0, 10.0, 100.0,
566  _("\t(higher refresh rate decreases CPU usage - default is 200)"),
567  update_timeout_value, ui, vbox);
568  ui_register_spinner_int_preference("player", "refresh_rate", DEFAULT_TIMEOUT_VALUE,
569  spinner, (void (*)(GtkWidget *, gpointer)) update_timeout_value,
570  ui, ui);
571 
572  return wh_set_title_and_get_vbox(vbox, _("<b>Player options</b>"));
573 }
574 
575 static void wave_quality_changed_event(GtkAdjustment *wave_quality_adjustment, ui_state *ui)
576 {
577  gint quality_level = (gint)gtk_adjustment_get_value(GTK_ADJUSTMENT(wave_quality_adjustment));
578 
579  gint level = 0;
580  for (level = 0; level <= 4; level++)
581  {
582  gdouble default_value = ui->infos->douglas_peucker_thresholds_defaults[level];
583  gdouble final_value = default_value - quality_level;
584  if (final_value <= 0)
585  {
586  final_value = 0.1;
587  }
588 
589  ui->infos->douglas_peucker_thresholds[level] = final_value;
590  }
591 
592  gint default_number_of_points_th = DEFAULT_SILENCE_WAVE_NUMBER_OF_POINTS_THRESHOLD;
593  gint number_of_points_th = default_number_of_points_th + (quality_level * 1000);
594  if (number_of_points_th <= 0)
595  {
596  number_of_points_th = 0;
597  }
598 
599  ui->infos->silence_wave_number_of_points_threshold = number_of_points_th;
600 
601  compute_douglas_peucker_filters(ui);
602  refresh_preview_drawing_areas(ui->gui);
603 
604  ui_save_preferences(NULL, ui);
605 }
606 
607 void refresh_preview_drawing_areas(gui_state *gui)
608 {
609  gint i = 0;
610  for (i = 0; i < gui->wave_quality_das->len; i++)
611  {
612  gtk_widget_queue_draw(g_ptr_array_index(gui->wave_quality_das, i));
613  }
614 
615  gtk_widget_queue_draw(gui->player_scrolled_window);
616 }
617 
618 static gint get_wave_preview_width_drawing_area(ui_state *ui)
619 {
620  if (ui->infos->width_drawing_area < 50)
621  {
622  return 500;
623  }
624 
625  return ui->infos->width_drawing_area;
626 }
627 
628 #if GTK_MAJOR_VERSION <= 2
629 static gboolean wave_quality_draw_event(GtkWidget *drawing_area, GdkEventExpose *event,
631 {
632  cairo_t *cairo_surface = gdk_cairo_create(drawing_area->window);
633 #else
634 static gboolean wave_quality_draw_event(GtkWidget *drawing_area, cairo_t *cairo_surface,
636 {
637 #endif
638 
639  ui_state *ui = data->data;
640  gint index = data->index;
641 
642  gint width = get_wave_preview_width_drawing_area(ui);
643  gtk_widget_set_size_request(drawing_area, width, 70);
644 
645  gint expected_drawing_time_int = g_array_index(ui->infos->preview_time_windows, gint, index);
646  gfloat expected_drawing_time = (gfloat)(expected_drawing_time_int);
647 
648  dh_set_white_color(cairo_surface);
649 
650  dh_draw_rectangle(cairo_surface, TRUE, 0, 0, width, 70);
651  gfloat current_time = ui->infos->total_time / 2.0;
652 
653  gfloat drawing_time = 0;
654  gfloat zoom_coeff = 0.2;
655 
656  gfloat left_time = 0;
657  gfloat right_time = 0;
658  while ((((gint)drawing_time) == 0) || (drawing_time > expected_drawing_time))
659  {
660  left_time = get_left_drawing_time(current_time, ui->infos->total_time, zoom_coeff);
661  right_time = get_right_drawing_time(current_time, ui->infos->total_time, zoom_coeff);
662  drawing_time = right_time - left_time;
663  zoom_coeff += 0.2;
664 
665  if (zoom_coeff > 100) { break; }
666  }
667 
668  gint interpolation_level = draw_silence_wave((gint)left_time, (gint)right_time, width / 2, 50,
669  drawing_time, width, 0,
670  current_time, ui->infos->total_time, zoom_coeff,
671  drawing_area, cairo_surface, ui);
672 
673  update_wave_preview_label_markup(index, interpolation_level, ui);
674 
675 #if GTK_MAJOR_VERSION <= 2
676  cairo_destroy(cairo_surface);
677 #endif
678 
679  return TRUE;
680 }
681 
682 static GtkWidget *create_wave_quality_preview_box(ui_state *ui)
683 {
684  GtkWidget *vbox = wh_vbox_new();
685 
686  GtkWidget *label_hbox = wh_hbox_new();
687  GtkWidget *wave_preview_label = gtk_label_new(NULL);
688 
689  gchar wave_availability[256] = { '\0' };
690  g_snprintf(wave_availability, 256, "<span style='italic' color='#0000AA'>%s</span>",
691  _("Wave preview is only available if the amplitude wave was ticked in the player"));
692  gtk_label_set_markup(GTK_LABEL(wave_preview_label), wave_availability);
693  gtk_box_pack_start(GTK_BOX(label_hbox), wave_preview_label, FALSE, FALSE, 0);
694  gtk_box_pack_start(GTK_BOX(vbox), label_hbox, FALSE, FALSE, 4);
695 
696  ui->gui->wave_quality_das = g_ptr_array_new();
697  ui->gui->wave_preview_labels = g_ptr_array_new();
698 
699  gint i = 0;
700  for (i = 0; i < ui->infos->preview_time_windows->len; i++)
701  {
702  GtkWidget *wave_quality_da = gtk_drawing_area_new();
703  g_ptr_array_add(ui->gui->wave_quality_das, (gpointer)wave_quality_da);
704  ui->infos->preview_indexes[i].index = i;
705  ui->infos->preview_indexes[i].data = ui;
706 
707 #if GTK_MAJOR_VERSION <= 2
708  g_signal_connect(wave_quality_da, "expose_event", G_CALLBACK(wave_quality_draw_event),
709  &ui->infos->preview_indexes[i]);
710 #else
711  g_signal_connect(wave_quality_da, "draw", G_CALLBACK(wave_quality_draw_event),
712  &ui->infos->preview_indexes[i]);
713 #endif
714  wh_put_in_hbox_and_attach_to_vbox(wave_quality_da, vbox, 0);
715 
716  GtkWidget *minutes_label = gtk_label_new(NULL);
717  g_ptr_array_add(ui->gui->wave_preview_labels, minutes_label);
718  update_wave_preview_label_markup(i, -1, ui);
719 
720  wh_put_in_hbox_and_attach_to_vbox_with_bottom_margin(minutes_label, vbox, 0, 4);
721  }
722 
723  return vbox;
724 }
725 
726 static void update_wave_preview_label_markup(gint index, gint interpolation_level, ui_state *ui)
727 {
728  gint time_window = g_array_index(ui->infos->preview_time_windows, gint, index);
729 
730  gchar minutes_text[128] = { '\0' };
731  g_snprintf(minutes_text, 128, _("%d minute(s) window"), time_window / 100 / 60);
732 
733  gchar interpolation_text[256] = { '\0' };
734  if (interpolation_level >= 0)
735  {
736  g_snprintf(interpolation_text, 256, _("Wave interpolation level %d with threshold of %.1lf"),
737  interpolation_level + 1, ui->infos->douglas_peucker_thresholds[interpolation_level]);
738  }
739  else {
740  g_snprintf(interpolation_text, 256, _("No wave interpolation"));
741  }
742 
743  gchar final_text_with_color[512] = { '\0' };
744  g_snprintf(final_text_with_color, 512,
745  "<span color='#DD0000'>%s</span> - <span>%s</span>",
746  minutes_text, interpolation_text);
747 
748  GtkWidget *text_label = g_ptr_array_index(ui->gui->wave_preview_labels, index);
749  gtk_label_set_markup(GTK_LABEL(text_label), final_text_with_color);
750 }
751 
752 static GtkWidget *create_wave_options_box(ui_state *ui)
753 {
754  GtkWidget *vbox = wh_vbox_new();
755  GtkWidget *range_hbox = wh_hbox_new();
756 
757  GtkWidget *wave_quality_label =
758  gtk_label_new(_("Wave quality (higher is better but consumes more CPU):"));
759  gtk_box_pack_start(GTK_BOX(range_hbox), wave_quality_label, FALSE, FALSE, 0);
760 
761  GtkWidget *wave_quality_hscale = wh_hscale_new_with_range(-6.0, 6.0, 1.0);
762  gtk_scale_set_draw_value(GTK_SCALE(wave_quality_hscale), TRUE);
763  gtk_box_pack_start(GTK_BOX(range_hbox), wave_quality_hscale, FALSE, FALSE, 4);
764  gtk_widget_set_size_request(wave_quality_hscale, 160, 0);
765 
766  gtk_range_set_increments(GTK_RANGE(wave_quality_hscale), 1.0, 1.0);
767 
768  ui_register_range_preference("player", "wave_quality", 0.0,
769  wave_quality_hscale, (void (*)(GtkAdjustment *,gpointer))wave_quality_changed_event, ui, ui);
770 
771  GtkAdjustment *wave_quality_adjustment = gtk_range_get_adjustment(GTK_RANGE(wave_quality_hscale));
772  g_signal_connect(G_OBJECT(wave_quality_adjustment), "value-changed",
773  G_CALLBACK(wave_quality_changed_event), ui);
774 
775  gtk_box_pack_start(GTK_BOX(vbox), range_hbox, FALSE, FALSE, 0);
776 
777  return wh_set_title_and_get_vbox(vbox, _("<b>Amplitude wave options</b>"));
778 }
779 
781 static GtkWidget *create_pref_player_page(ui_state *ui)
782 {
783  GtkWidget *player_hbox = wh_hbox_new();;
784  GtkWidget *inside_hbox = wh_hbox_new();;
785 
786  GtkWidget *inside_vbox = wh_vbox_new();;
787  gtk_box_pack_start(GTK_BOX(inside_hbox), inside_vbox, TRUE, TRUE, 5);
788 
789  GtkWidget *player_scrolled_window = wh_create_scrolled_window();
790  ui->gui->player_scrolled_window = player_scrolled_window;
791  gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(player_scrolled_window),
792  GTK_WIDGET(inside_hbox));
793  gtk_box_pack_start(GTK_BOX(player_hbox), player_scrolled_window, TRUE, TRUE, 0);
794 
795  GtkWidget *vbox = wh_vbox_new();;
796  gtk_box_pack_start(GTK_BOX(inside_vbox), vbox, TRUE, TRUE, 0);
797 
798  GtkWidget *player_options_box = create_player_options_box(ui);
799  gtk_box_pack_start(GTK_BOX(vbox), player_options_box, FALSE, FALSE, 3);
800 
801  GtkWidget *wave_options_box = create_wave_options_box(ui);
802  gtk_box_pack_start(GTK_BOX(vbox), wave_options_box, FALSE, FALSE, 3);
803 
804  GtkWidget *wave_quality_box = create_wave_quality_preview_box(ui);
805  gtk_box_pack_start(GTK_BOX(inside_vbox), wave_quality_box, FALSE, FALSE, 0);
806 
807  return player_hbox;
808 }
809 
811 static gboolean output_entry_event(GtkWidget *widget, GdkEventKey *event, ui_state *ui)
812 {
813  const char *data = gtk_entry_get_text(GTK_ENTRY(ui->gui->output_entry));
814  gint error = SPLT_OUTPUT_FORMAT_OK;
815  mp3splt_set_oformat(ui->mp3splt_state, data, &error);
816  remove_status_message(ui->gui);
818 
819  ui_save_preferences(NULL, ui);
820 
821  return FALSE;
822 }
823 
825 static GtkWidget *create_output_filename_box(ui_state *ui)
826 {
827  gui_state *gui = ui->gui;
828 
829  GtkWidget *vbox = wh_vbox_new();
830 
831  //default/custom radio buttons
832  GtkWidget *radio_output = gtk_radio_button_new_with_label(NULL, _("Default format"));
833  gui->radio_output = radio_output;
834  gtk_box_pack_start(GTK_BOX(vbox), radio_output, FALSE, FALSE, 0);
835 
836  GtkWidget *horiz_fake = wh_hbox_new();
837  gtk_box_pack_start(GTK_BOX(vbox), horiz_fake, FALSE, FALSE, 5);
838 
839  GString *outputs_str = g_string_new(_(" Default output: "));
840  g_string_append(outputs_str, "<span color='#222288'>");
841  g_string_append(outputs_str, SPLT_DEFAULT_OUTPUT);
842  g_string_append(outputs_str, "</span>");
843 
844  g_string_append(outputs_str, "\n");
845  g_string_append(outputs_str, _(" CDDB, CUE and tracktype.org default: "));
846  g_string_append(outputs_str, "<span color='#222288'>");
847  g_string_append(outputs_str, SPLT_DEFAULT_CDDB_CUE_OUTPUT);
848  g_string_append(outputs_str, "</span>");
849 
850  g_string_append(outputs_str, "\n");
851  g_string_append(outputs_str, _(" Split with silence detection default: "));
852  g_string_append(outputs_str, "<span color='#222288'>");
853  g_string_append(outputs_str, SPLT_DEFAULT_SILENCE_OUTPUT);
854  g_string_append(outputs_str, "</span>");
855 
856  g_string_append(outputs_str, "\n");
857  g_string_append(outputs_str, _(" Trim using silence detection default: "));
858  g_string_append(outputs_str, "<span color='#222288'>");
859  g_string_append(outputs_str, SPLT_DEFAULT_TRIM_SILENCE_OUTPUT);
860  g_string_append(outputs_str, "</span>");
861 
862  g_string_append(outputs_str, "\n");
863  g_string_append(outputs_str, _(" Error mode default: "));
864  g_string_append(outputs_str, "<span color='#222288'>");
865  g_string_append(outputs_str, SPLT_DEFAULT_SYNCERROR_OUTPUT);
866  g_string_append(outputs_str, "</span>");
867 
868  GtkWidget *default_label = gtk_label_new(NULL);
869  gui->output_default_label = default_label;
870  gtk_label_set_markup(GTK_LABEL(default_label), outputs_str->str);
871  gtk_label_set_selectable(GTK_LABEL(default_label), TRUE);
872  gtk_box_pack_start(GTK_BOX(horiz_fake), default_label, FALSE, FALSE, 0);
873 
874  g_string_free(outputs_str, TRUE);
875 
876  //second radio button
877  radio_output = gtk_radio_button_new_with_label_from_widget
878  (GTK_RADIO_BUTTON(radio_output), _("Custom format"));
879  gui->radio_output = radio_output;
880  gtk_box_pack_start(GTK_BOX(vbox), radio_output, FALSE, FALSE, 0);
881 
882  //output entry
883  horiz_fake = wh_hbox_new();
884  gtk_box_pack_start(GTK_BOX(vbox), horiz_fake, FALSE, FALSE, 5);
885 
886  GtkWidget *output_entry = gtk_entry_new();
887  gui->output_entry = output_entry;
888  gtk_editable_set_editable(GTK_EDITABLE(output_entry), TRUE);
889  g_signal_connect(G_OBJECT(output_entry), "key_release_event", G_CALLBACK(output_entry_event), ui);
890  gtk_entry_set_max_length(GTK_ENTRY(output_entry),244);
891  gtk_box_pack_start(GTK_BOX(horiz_fake), output_entry, TRUE, TRUE, 0);
892 
893  //output label
894  horiz_fake = wh_hbox_new();
895  gtk_box_pack_start(GTK_BOX(vbox), horiz_fake, FALSE, FALSE, 5);
896  GtkWidget *output_label = gtk_label_new(_(
897  " @A: performer if found, otherwise artist\n"
898  " @a: artist name\n"
899  " @p: performer of each song (only with .cue)\n"
900  " @b: album title\n"
901  " @g: genre\n"
902  " @t: song title\n"
903  " @n: track number identifier (not the real ID3 track number) **\n"
904  " @N: track tag number **\n"
905  " @l: track number identifier as lowercase letter (not the real ID3 track number) **\n"
906  " @L: track tag number as lowercase letter **\n"
907  " @u: track number identifier as uppercase letter (not the real ID3 track number) **\n"
908  " @U: track tag number as uppercase letter **\n"
909  " @f: input filename (without extension)\n"
910  " @m, @s or @h: the number of minutes, seconds or hundreths of seconds of the start splitpoint **\n"
911  " @M, @S or @H: the number of minutes, seconds or hundreths of seconds of the end splitpoint **\n"
912  "\n"
913  " (**) a digit may follow for the number of digits to output\n"));
914  gtk_label_set_selectable(GTK_LABEL(output_label), TRUE);
915  gui->output_label = output_label;
916  gtk_box_pack_start(GTK_BOX(horiz_fake), output_label, FALSE, FALSE, 0);
917 
918  g_signal_connect(GTK_TOGGLE_BUTTON(gui->radio_output),
919  "toggled", G_CALLBACK(output_radio_box_event), ui);
920 
921  return wh_set_title_and_get_vbox(vbox, _("<b>Output filename format for batch split, CUE, CDDB and tracktype.org</b>"));
922 }
923 
925 static GtkWidget *create_pref_output_page(ui_state *ui)
926 {
927  GtkWidget *output_hbox = wh_hbox_new();;
928  GtkWidget *output_inside_hbox = wh_hbox_new();;
929 
930  GtkWidget *scrolled_window = wh_create_scrolled_window();
931  gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window),
932  GTK_WIDGET(output_inside_hbox));
933  gtk_box_pack_start(GTK_BOX(output_hbox), scrolled_window, TRUE, TRUE, 0);
934 
935  GtkWidget *vbox = wh_vbox_new();;
936  gtk_box_pack_start(GTK_BOX(output_inside_hbox), vbox, TRUE, TRUE, 5);
937 
938  GtkWidget *output_fname_box = create_output_filename_box(ui);
939  gtk_box_pack_start(GTK_BOX(vbox), output_fname_box, FALSE, FALSE, 2);
940 
941  return output_hbox;
942 }
943 
944 static void change_tags_options(GtkToggleButton *button, gpointer data)
945 {
946  ui_state *ui = (ui_state *)data;
947 
948  if (ui->gui->extract_tags_box != NULL)
949  {
950  if (rh_get_active_value(ui->gui->tags_radio) == TAGS_FROM_FILENAME)
951  {
952  gtk_widget_set_sensitive(ui->gui->extract_tags_box, SPLT_TRUE);
953  }
954  else
955  {
956  gtk_widget_set_sensitive(ui->gui->extract_tags_box, SPLT_FALSE);
957  }
958  }
959 
960  ui_save_preferences(NULL, ui);
961 }
962 
964 static GtkWidget *create_tags_options_box(ui_state *ui)
965 {
966  gui_state *gui = ui->gui;
967 
968  GtkWidget *vbox = wh_vbox_new();
969 
970  GtkWidget *tags_radio = NULL;
971  tags_radio = rh_append_radio_to_vbox(tags_radio, _("Original file tags"),
972  ORIGINAL_FILE_TAGS, change_tags_options, ui, vbox);
973  gui->tags_radio = tags_radio;
974  tags_radio = rh_append_radio_to_vbox(tags_radio, _("Default tags (cddb or cue tags)"),
975  DEFAULT_TAGS, change_tags_options, ui, vbox);
976  gui->tags_radio = tags_radio;
977  tags_radio = rh_append_radio_to_vbox(tags_radio, _("No tags"),
978  NO_TAGS, change_tags_options, ui, vbox);
979  gui->tags_radio = tags_radio;
980  tags_radio = rh_append_radio_to_vbox(tags_radio, _("Extract tags from filename"),
981  TAGS_FROM_FILENAME, change_tags_options, ui, vbox);
982  gui->tags_radio = tags_radio;
983 
984  GtkWidget *extract_tags_box = create_extract_tags_from_filename_options_box(ui);
985  gui->extract_tags_box = extract_tags_box;
986  gtk_widget_set_sensitive(extract_tags_box, SPLT_FALSE);
987  gtk_box_pack_start(GTK_BOX(vbox), extract_tags_box, FALSE, FALSE, 2);
988 
989  return wh_set_title_and_get_vbox(vbox, _("<b>Split files tags</b>"));
990 }
991 
992 static GtkComboBox *create_genre_combo(ui_state *ui)
993 {
994  GtkComboBox *combo = ch_new_combo();
995 
996  int i = 0;
997  for (i = 0;i < SPLT_ID3V1_NUMBER_OF_GENRES;i++)
998  {
999  ch_append_to_combo(combo, splt_id3v1_genres[i], 0);
1000  }
1001 
1002  g_signal_connect(G_OBJECT(combo), "changed", G_CALLBACK(ui_save_preferences), ui);
1003 
1004  return combo;
1005 }
1006 
1007 static GtkComboBox *create_text_preferences_combo(ui_state *ui)
1008 {
1009  GtkComboBox *combo = ch_new_combo();
1010 
1011  ch_append_to_combo(combo, _("No change"), SPLT_NO_CONVERSION);
1012  ch_append_to_combo(combo, _("lowercase"), SPLT_TO_LOWERCASE);
1013  ch_append_to_combo(combo, _("UPPERCASE"), SPLT_TO_UPPERCASE);
1014  ch_append_to_combo(combo, _("First uppercase"), SPLT_TO_FIRST_UPPERCASE);
1015  ch_append_to_combo(combo, _("Word Uppercase"), SPLT_TO_WORD_FIRST_UPPERCASE);
1016 
1017  g_signal_connect(G_OBJECT(combo), "changed", G_CALLBACK(ui_save_preferences), ui);
1018 
1019  return combo;
1020 }
1021 
1022 static void test_regex_event(GtkWidget *widget, ui_state *ui)
1023 {
1024  put_tags_from_filename_regex_options(ui);
1025 
1026  const gchar *test_regex_filename = gtk_entry_get_text(GTK_ENTRY(ui->gui->test_regex_fname_entry));
1027  mp3splt_set_filename_to_split(ui->mp3splt_state, test_regex_filename);
1028 
1029  gint error = SPLT_OK;
1030  splt_tags *tags = mp3splt_parse_filename_regex(ui->mp3splt_state, &error);
1031  print_status_bar_confirmation(error, ui);
1032 
1033  if (error >= 0)
1034  {
1035  GString *regex_result = g_string_new(NULL);
1036 
1037  g_string_append(regex_result, _("<artist>: "));
1038  if (tags->artist)
1039  {
1040  g_string_append(regex_result, tags->artist);
1041  }
1042  g_string_append(regex_result, "\n");
1043 
1044  g_string_append(regex_result, _("<album>: "));
1045  if (tags->album)
1046  {
1047  g_string_append(regex_result, tags->album);
1048  }
1049  g_string_append(regex_result, "\n");
1050 
1051 
1052  g_string_append(regex_result, _("<title>: "));
1053  if (tags->title)
1054  {
1055  g_string_append(regex_result, tags->title);
1056  }
1057  g_string_append(regex_result, "\n");
1058 
1059  g_string_append(regex_result, _("<genre>: "));
1060  if (tags->genre)
1061  {
1062  g_string_append(regex_result, tags->genre);
1063  }
1064  g_string_append(regex_result, "\n");
1065 
1066  g_string_append(regex_result, _("<comment>: "));
1067  if (tags->comment)
1068  {
1069  g_string_append(regex_result, tags->comment);
1070  }
1071  g_string_append(regex_result, "\n");
1072 
1073  g_string_append(regex_result, _("<year>: "));
1074  if (tags->year)
1075  {
1076  g_string_append(regex_result, tags->year);
1077  }
1078  g_string_append(regex_result, "\n");
1079 
1080  g_string_append(regex_result, _("<track>: "));
1081  if (tags->track >= 0)
1082  {
1083  g_string_append_printf(regex_result, "%d", tags->track);
1084  }
1085 
1086  gchar *regex_result_text = g_string_free(regex_result, FALSE);
1087  if (regex_result_text)
1088  {
1089  gtk_label_set_text(GTK_LABEL(ui->gui->sample_result_label), regex_result_text);
1090  g_free(regex_result_text);
1091  }
1092  }
1093  else
1094  {
1095  gtk_label_set_text(GTK_LABEL(ui->gui->sample_result_label), "");
1096  }
1097 
1098  mp3splt_free_one_tag(tags);
1099 }
1100 
1101 static GtkWidget *create_extract_tags_from_filename_options_box(ui_state *ui)
1102 {
1103  GtkWidget *table = wh_new_table();
1104 
1105  GtkWidget *regex_entry = wh_new_entry(ui_save_preferences, ui);
1106  ui->gui->regex_entry = regex_entry;
1107  wh_add_in_table_with_label_expand(table, _("Regular expression:"), regex_entry);
1108 
1109  GtkWidget *regex_label = gtk_label_new(_(
1110  "Above enter PERL-like regular expression using named subgroups.\nFollowing names are recognized:\n"
1111  " (?<artist>) - artist name\n"
1112  " (?<album>) - album title\n"
1113  " (?<title>) - track title\n"
1114  " (?<tracknum>) - current track number\n"
1115  //" (?<tracks>) - total number of tracks\n"
1116  " (?<year>) - year of emission\n"
1117  " (?<genre>) - genre\n"
1118  " (?<comment>) - comment"));
1119  gtk_label_set_selectable(GTK_LABEL(regex_label), TRUE);
1120  gtk_misc_set_alignment(GTK_MISC(regex_label), 0.0, 0.5);
1121  wh_add_in_table(table, wh_put_in_new_hbox_with_margin_level(regex_label, 2));
1122 
1123  ui_infos *infos = ui->infos;
1124 
1125  infos->text_options_list =
1126  g_list_append(infos->text_options_list, GINT_TO_POINTER(SPLT_NO_CONVERSION));
1127  infos->text_options_list =
1128  g_list_append(infos->text_options_list, GINT_TO_POINTER(SPLT_TO_LOWERCASE));
1129  infos->text_options_list =
1130  g_list_append(infos->text_options_list, GINT_TO_POINTER(SPLT_TO_UPPERCASE));
1131  infos->text_options_list =
1132  g_list_append(infos->text_options_list, GINT_TO_POINTER(SPLT_TO_FIRST_UPPERCASE));
1133  infos->text_options_list =
1134  g_list_append(infos->text_options_list, GINT_TO_POINTER(SPLT_TO_WORD_FIRST_UPPERCASE));
1135 
1136  GtkWidget *replace_underscore_by_space_check_box =
1137  gtk_check_button_new_with_mnemonic(_("_Replace underscores by spaces"));
1138  ui->gui->replace_underscore_by_space_check_box = replace_underscore_by_space_check_box;
1139  g_signal_connect(G_OBJECT(replace_underscore_by_space_check_box), "toggled",
1140  G_CALLBACK(ui_save_preferences), ui);
1141 
1142  wh_add_in_table(table, replace_underscore_by_space_check_box);
1143 
1144  GtkComboBox *artist_text_properties_combo = create_text_preferences_combo(ui);
1145  ui->gui->artist_text_properties_combo = artist_text_properties_combo;
1146  wh_add_in_table_with_label(table,
1147  _("Artist text properties:"), GTK_WIDGET(artist_text_properties_combo));
1148 
1149  GtkComboBox *album_text_properties_combo = create_text_preferences_combo(ui);
1150  ui->gui->album_text_properties_combo = album_text_properties_combo;
1151  wh_add_in_table_with_label(table,
1152  _("Album text properties:"), GTK_WIDGET(album_text_properties_combo));
1153 
1154  GtkComboBox *title_text_properties_combo = create_text_preferences_combo(ui);
1155  ui->gui->title_text_properties_combo = title_text_properties_combo;
1156  wh_add_in_table_with_label(table,
1157  _("Title text properties:"), GTK_WIDGET(title_text_properties_combo));
1158 
1159  GtkComboBox *comment_text_properties_combo = create_text_preferences_combo(ui);
1160  ui->gui->comment_text_properties_combo = comment_text_properties_combo;
1161  wh_add_in_table_with_label(table,
1162  _("Comment text properties:"), GTK_WIDGET(comment_text_properties_combo));
1163 
1164  GtkComboBox *genre_combo = create_genre_combo(ui);
1165  ui->gui->genre_combo = genre_combo;
1166  wh_add_in_table_with_label(table, _("Genre tag:"), GTK_WIDGET(genre_combo));
1167 
1168  GtkWidget *comment_tag_entry = wh_new_entry(ui_save_preferences, ui);
1169  ui->gui->comment_tag_entry = comment_tag_entry;
1170  wh_add_in_table_with_label_expand(table, _("Comment tag:"), comment_tag_entry);
1171 
1172  GtkWidget *test_regex_expander = gtk_expander_new(_("Regular expression test"));
1173  gtk_container_add(GTK_CONTAINER(test_regex_expander), create_test_regex_table(ui));
1174  wh_add_in_table(table, test_regex_expander);
1175 
1176  return wh_put_in_new_hbox_with_margin_level(GTK_WIDGET(table), 3);
1177 }
1178 
1179 static GtkWidget *create_test_regex_table(ui_state *ui)
1180 {
1181  GtkWidget *table = wh_new_table();
1182 
1183  GtkWidget *sample_test_hbox = wh_hbox_new();
1184  GtkWidget *test_regex_fname_entry = wh_new_entry(ui_save_preferences, ui);
1185  ui->gui->test_regex_fname_entry = test_regex_fname_entry;
1186  gtk_box_pack_start(GTK_BOX(sample_test_hbox), test_regex_fname_entry, TRUE, TRUE, 0);
1187 
1188  GtkWidget *test_regex_button = wh_new_button(_("_Test"));
1189  gtk_box_pack_start(GTK_BOX(sample_test_hbox), test_regex_button, FALSE, FALSE, 5);
1190  g_signal_connect(G_OBJECT(test_regex_button), "clicked", G_CALLBACK(test_regex_event), ui);
1191 
1192  wh_add_in_table_with_label_expand(table, _("Sample filename:"), sample_test_hbox);
1193 
1194  GtkWidget *sample_result_label = gtk_label_new("");
1195  ui->gui->sample_result_label = sample_result_label;
1196  gtk_misc_set_alignment(GTK_MISC(ui->gui->sample_result_label), 0.0, 0.5);
1197  wh_add_in_table_with_label_expand(table, _("Sample result:"), ui->gui->sample_result_label);
1198 
1199  return wh_put_in_new_hbox_with_margin_level(GTK_WIDGET(table), 3);
1200 }
1201 
1203 static GtkWidget *create_tags_version_box(ui_state *ui)
1204 {
1205  gui_state *gui = ui->gui;
1206 
1207  GtkWidget *vbox = wh_vbox_new();
1208 
1209  GtkWidget *tags_version_radio = gtk_radio_button_new_with_label(NULL, _("ID3v1 & ID3v2 tags"));
1210  gui->tags_version_radio = tags_version_radio;
1211  gtk_box_pack_start(GTK_BOX(vbox), tags_version_radio, FALSE, FALSE, 0);
1212  g_signal_connect(GTK_TOGGLE_BUTTON(tags_version_radio), "toggled",
1213  G_CALLBACK(ui_save_preferences), ui);
1214 
1215  tags_version_radio = gtk_radio_button_new_with_label_from_widget
1216  (GTK_RADIO_BUTTON(tags_version_radio), _("ID3v2 tags"));
1217  gui->tags_version_radio = tags_version_radio;
1218  gtk_box_pack_start(GTK_BOX(vbox), tags_version_radio, FALSE, FALSE, 0);
1219  g_signal_connect(GTK_TOGGLE_BUTTON(tags_version_radio), "toggled",
1220  G_CALLBACK(ui_save_preferences), ui);
1221 
1222  tags_version_radio = gtk_radio_button_new_with_label_from_widget
1223  (GTK_RADIO_BUTTON(tags_version_radio), _("ID3v1 tags"));
1224  gui->tags_version_radio = tags_version_radio;
1225  g_signal_connect(GTK_TOGGLE_BUTTON(tags_version_radio), "toggled",
1226  G_CALLBACK(ui_save_preferences), ui);
1227  gtk_box_pack_start(GTK_BOX(vbox), tags_version_radio, FALSE, FALSE, 0);
1228 
1229  tags_version_radio = gtk_radio_button_new_with_label_from_widget
1230  (GTK_RADIO_BUTTON (tags_version_radio),_("Same tags version as the input file"));
1231  gui->tags_version_radio = tags_version_radio;
1232  g_signal_connect(GTK_TOGGLE_BUTTON(tags_version_radio), "toggled",
1233  G_CALLBACK(ui_save_preferences), ui);
1234  gtk_box_pack_start(GTK_BOX(vbox), tags_version_radio, FALSE, FALSE, 0);
1235 
1236  return wh_set_title_and_get_vbox(vbox, _("<b>Tags version (mp3 only)</b>"));
1237 }
1238 
1240 static GtkWidget *create_pref_tags_page(ui_state *ui)
1241 {
1242  GtkWidget *outside_vbox = wh_vbox_new();;
1243  GtkWidget *inside_hbox = wh_hbox_new();
1244 
1245  GtkWidget *scrolled_window = wh_create_scrolled_window();
1246  gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window),
1247  GTK_WIDGET(inside_hbox));
1248  gtk_box_pack_start(GTK_BOX(outside_vbox), scrolled_window, TRUE, TRUE, 0);
1249 
1250  GtkWidget *vbox = wh_vbox_new();;
1251  gtk_box_pack_start(GTK_BOX(inside_hbox), vbox, TRUE, TRUE, 5);
1252 
1253  GtkWidget *tags_version_box = create_tags_version_box(ui);
1254  gtk_box_pack_start(GTK_BOX(vbox), tags_version_box, FALSE, FALSE, 2);
1255 
1256  GtkWidget *tags_opts_box = create_tags_options_box(ui);
1257  gtk_box_pack_start(GTK_BOX(vbox), tags_opts_box, FALSE, FALSE, 1);
1258 
1259  return outside_vbox;
1260 }
1261 
1264 {
1265  GtkWidget *pref_vbox = wh_vbox_new();
1266 
1267  GtkWidget *notebook = gtk_notebook_new();
1268  gtk_box_pack_start(GTK_BOX(pref_vbox), notebook, TRUE, TRUE, 0);
1269 
1270  gtk_notebook_popup_enable(GTK_NOTEBOOK(notebook));
1271  gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook), TRUE);
1272  gtk_notebook_set_show_border(GTK_NOTEBOOK(notebook), FALSE);
1273  gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
1274 
1275  /* split preferences */
1276  GtkWidget *splitpoints_prefs = create_pref_splitpoints_page(ui);
1277  GtkWidget *notebook_label = gtk_label_new(_("Split"));
1278  gtk_notebook_append_page(GTK_NOTEBOOK(notebook), splitpoints_prefs, notebook_label);
1279 
1280  /* tags preferences */
1281  GtkWidget *tags_prefs = create_pref_tags_page(ui);
1282  notebook_label = gtk_label_new(_("Tags"));
1283  gtk_notebook_append_page(GTK_NOTEBOOK(notebook), tags_prefs, notebook_label);
1284 
1285  /* player preferences */
1286  GtkWidget *player_prefs = create_pref_player_page(ui);
1287  notebook_label = gtk_label_new(_("Player"));
1288  gtk_notebook_append_page(GTK_NOTEBOOK(notebook), player_prefs, notebook_label);
1289 
1290  /* output preferences */
1291  GtkWidget *output_prefs = create_pref_output_page(ui);
1292  notebook_label = gtk_label_new(_("Output filename format"));
1293  gtk_notebook_append_page(GTK_NOTEBOOK(notebook), output_prefs, notebook_label);
1294 
1295  /* language preferences page */
1296 #ifdef __WIN32__
1297  GtkWidget *language_prefs = create_pref_language_page(ui);
1298  notebook_label = gtk_label_new(_("Language"));
1299  gtk_notebook_append_page(GTK_NOTEBOOK(notebook), language_prefs, notebook_label);
1300 #endif
1301 
1302  return pref_vbox;
1303 }
1304