mp3splt-gtk 0.9.3.1519
Loading...
Searching...
No Matches
main_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-2014 Alexandru Munteanu
7 * Contact: m@ioalex.net
8 *
9 * http://mp3splt.sourceforge.net/
10 *
11 *********************************************************/
12/**********************************************************
13 *
14 * This program is free software; you can redistribute it and/or
15
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 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
28 * USA.
29 *
30 *********************************************************/
31
32/*!********************************************************
33 * \file
34 * The main window
35 *
36 * main file that initialises the menubar, the toolbar,
37 * the tabs, about window, status error messages
38 *
39 *********************************************************/
40
41#include "main_window.h"
42
44void set_input_filename(const gchar *filename, ui_state *ui)
45{
46 if (filename == NULL)
47 {
48 return;
49 }
50
51 if (ui->gui->input_filename != NULL)
52 {
53 g_string_free(ui->gui->input_filename,TRUE);
54 }
55 ui->gui->input_filename = g_string_new(filename);
56
57 if (ui->gui->open_file_chooser_button != NULL && !ui->status->file_selection_changed)
58 {
59 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(ui->gui->open_file_chooser_button), filename);
60 }
61
62 update_example_output_dir_for_single_file_split(ui);
63
64 export_cue_file_in_configuration_directory(ui);
65}
66
74{
75 if (gui->input_filename != NULL)
76 {
77 return gui->input_filename->str;
78 }
79
80 return "";
81}
82
83static gboolean configure_window_callback(GtkWindow *window, GdkEvent *event, ui_state *ui)
84{
85 ui_set_main_win_position(ui, event->configure.x, event->configure.y);
86 ui_set_main_win_size(ui, event->configure.width, event->configure.height);
87
88 refresh_drawing_area(ui->gui, ui->infos);
89 refresh_preview_drawing_areas(ui->gui);
90
91 clear_previous_distances(ui);
92
93 return FALSE;
94}
95
96static void initialize_window(GApplication *app, ui_state *ui)
97{
98 GtkWidget *window = gtk_application_window_new(GTK_APPLICATION(app));
99 ui->gui->window = window;
100
101 g_signal_connect(G_OBJECT(window), "configure-event", G_CALLBACK(configure_window_callback), ui);
102
103 gtk_window_set_title(GTK_WINDOW(window), PACKAGE_NAME" "VERSION);
104 gtk_container_set_border_width(GTK_CONTAINER(window), 0);
105
106 g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(exit_application), ui);
107
108 GString *imagefile = g_string_new("");
109 build_path(imagefile, PIXMAP_PATH, "mp3splt-gtk_ico"ICON_EXT);
110 GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(imagefile->str, NULL);
111 gtk_window_set_default_icon(pixbuf);
112 g_string_free(imagefile, TRUE);
113}
114
115static void activate_url(GtkAboutDialog *about, const gchar *link, ui_state *ui)
116{
117#ifdef __WIN32__
118 char default_browser[512] = { '\0' };
119 DWORD dwType, dwSize = sizeof(default_browser) - 1;
120
121 SHGetValue(HKEY_CURRENT_USER,
122 TEXT("Software\\Clients\\StartMenuInternet"),
123 TEXT(""),
124 &dwType,
125 default_browser,
126 &dwSize);
127
128 if (default_browser[0] != '\0')
129 {
130 SHGetValue(HKEY_LOCAL_MACHINE,
131 TEXT("SOFTWARE\\Clients\\StartMenuInternet"),
132 TEXT(""),
133 &dwType,
134 default_browser,
135 &dwSize);
136 }
137
138 if (default_browser[0] != '\0')
139 {
140 char browser_exe[2048] = { '\0' };
141 dwSize = sizeof(browser_exe) - 1;
142
143 char browser_exe_registry[1024] = { '\0' };
144 snprintf(browser_exe_registry, 1024,
145 "SOFTWARE\\Clients\\StartMenuInternet\\%s\\shell\\open\\command\\",
146 default_browser);
147
148 SHGetValue(HKEY_LOCAL_MACHINE,
149 TEXT(browser_exe_registry), TEXT(""),
150 &dwType, browser_exe, &dwSize);
151
152 if (browser_exe[0] != '\0')
153 {
154 gint browser_command_size = strlen(browser_exe) + strlen(link) + 2;
155 char *browser_command = g_malloc(sizeof(char) * browser_command_size);
156 if (browser_command)
157 {
158 snprintf(browser_command, browser_command_size, "%s %s",
159 browser_exe, link);
160
161 STARTUPINFO si;
162 PROCESS_INFORMATION pinf;
163 ZeroMemory(&si, sizeof(si));
164 si.cb = sizeof(si);
165 ZeroMemory(&pinf, sizeof(pinf));
166
167 if (! CreateProcess(NULL, browser_command,
168 NULL, NULL, FALSE, 0, NULL, NULL, &si, &pinf))
169 {
170 put_status_message(_("Error launching external command"), ui);
171 }
172
173 CloseHandle(pinf.hProcess);
174 CloseHandle(pinf.hThread);
175
176 g_free(browser_command);
177 browser_command = NULL;
178 }
179 }
180 }
181#endif
182}
183
184static void about_window(GSimpleAction *action, GVariant *parameter, gpointer data)
185{
186 ui_state *ui = (ui_state *) data;
187
188 GtkWidget *dialog = gtk_about_dialog_new();
189
190 GString *imagefile = g_string_new("");
191 build_path(imagefile, PIXMAP_PATH, "mp3splt-gtk.png");
192 GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(imagefile->str, NULL);
193 gtk_about_dialog_set_logo(GTK_ABOUT_DIALOG(dialog), pixbuf);
194 g_string_free(imagefile, TRUE);
195
196 gtk_about_dialog_set_program_name(GTK_ABOUT_DIALOG(dialog), (gchar *)PACKAGE_NAME);
197 gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(dialog), VERSION);
198 gtk_about_dialog_set_copyright(GTK_ABOUT_DIALOG(dialog),
199 PACKAGE_NAME" : Copyright © 2005-2014 Alexandru"
200 " Munteanu \n mp3splt : Copyright © 2002-2005 Matteo Trotta");
201
202 gchar b3[100] = { '\0' };
203 gchar *b1 = _("using");
204
205 char *library_version = mp3splt_get_version();
206 g_snprintf(b3, 100, "-%s-\n%s libmp3splt %s",
207 _("release of "MP3SPLT_GTK_DATE), b1, library_version);
208 free(library_version);
209
210 gtk_about_dialog_set_comments(GTK_ABOUT_DIALOG(dialog), b3);
211
212 gtk_about_dialog_set_license(GTK_ABOUT_DIALOG(dialog),
213 "\n"
214 "This program is free software; you can "
215 "redistribute it and/or \n"
216 "modify it under the terms of the GNU General Public License\n"
217 "as published by the Free Software "
218 "Foundation; either version 2\n"
219 "of the License, or (at your option) "
220 "any later version.\n\n"
221 "This program is distributed in the "
222 "hope that it will be useful,\n"
223 "but WITHOUT ANY WARRANTY; without even "
224 "the implied warranty of\n"
225 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
226 "GNU General Public License for more details.\n\n"
227 "You should have received a copy of the GNU General Public License\n"
228 "along with this program; if not, write "
229 "to the Free Software\n"
230 "Foundation, Inc., "
231 "51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.");
232
233 g_signal_connect(G_OBJECT(dialog), "activate-link", G_CALLBACK(activate_url), ui);
234
235 gtk_about_dialog_set_website_label(GTK_ABOUT_DIALOG(dialog),
236 "http://mp3splt.sourceforge.net");
237 gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(dialog),
238 "http://mp3splt.sourceforge.net");
239
240 gtk_about_dialog_set_translator_credits(GTK_ABOUT_DIALOG(dialog),
241 "Mario Blättermann <mariobl@gnome.org>");
242
243 gtk_dialog_run(GTK_DIALOG(dialog));
244 gtk_widget_destroy(dialog);
245}
246
252{
253 guint status_id = gtk_statusbar_get_context_id(gui->status_bar, "mess");
254 gtk_statusbar_pop(gui->status_bar, status_id);
255}
256
263void put_status_message(const gchar *text, ui_state *ui)
264{
265 put_status_message_with_type(text, SPLT_MESSAGE_INFO, ui);
266}
267
277void put_status_message_with_type(const gchar *text, splt_message_type mess_type, ui_state *ui)
278{
279 gui_state *gui = ui->gui;
280
281 if (mess_type == SPLT_MESSAGE_INFO || mess_type == SPLT_MESSAGE_WARNING)
282 {
283 guint status_id = gtk_statusbar_get_context_id(gui->status_bar, "mess");
284 gtk_statusbar_pop(gui->status_bar, status_id);
285 gtk_statusbar_push(gui->status_bar, status_id, text);
286 }
287
288 put_message_in_history(text, mess_type, ui);
289}
290
291void set_stop_split_safe(gboolean value, ui_state *ui)
292{
293 lock_mutex(&ui->variables_mutex);
294 ui->status->stop_split = value;
295 unlock_mutex(&ui->variables_mutex);
296}
297
299void cancel_button_event(GtkWidget *widget, ui_state *ui)
300{
301 lmanager_stop_split(ui);
302
303 set_stop_split_safe(TRUE, ui);
304
305 if (widget != NULL)
306 {
307 gtk_widget_set_sensitive(widget, FALSE);
308 }
309
310 put_status_message(_(" info: stopping the split process.. please wait"), ui);
311}
312
313void set_is_splitting_safe(gboolean value, ui_state *ui)
314{
315 lock_mutex(&ui->variables_mutex);
316 ui->status->splitting = value;
317 unlock_mutex(&ui->variables_mutex);
318}
319
320gint get_is_splitting_safe(ui_state *ui)
321{
322 lock_mutex(&ui->variables_mutex);
323 gint is_splitting = ui->status->splitting;
324 unlock_mutex(&ui->variables_mutex);
325 return is_splitting;
326}
327
328static void _set_process_in_progress_safe(gboolean value, ui_state *ui)
329{
330 lock_mutex(&ui->variables_mutex);
331 if (value)
332 {
333 ui->status->process_in_progress++;
334 }
335 else
336 {
337 ui->status->process_in_progress--;
338 }
339 unlock_mutex(&ui->variables_mutex);
340}
341
342void set_process_in_progress_and_wait_safe(gboolean value, ui_state *ui)
343{
344 if (value == TRUE)
345 {
346 while (get_process_in_progress_safe(ui))
347 {
348 g_usleep(G_USEC_PER_SEC / 4);
349 }
350 }
351
352 _set_process_in_progress_safe(value, ui);
353}
354
355void set_process_in_progress_safe(gboolean value, ui_state *ui)
356{
357#ifdef __WIN32__
358 _set_process_in_progress_safe(value, ui);
359#endif
360}
361
362gint get_process_in_progress_safe(ui_state *ui)
363{
364 lock_mutex(&ui->variables_mutex);
365 gint process_in_progress = ui->status->process_in_progress;
366 unlock_mutex(&ui->variables_mutex);
367 return process_in_progress > 0;
368}
369
371void split_button_event(GtkWidget *widget, ui_state *ui)
372{
373 if (get_is_splitting_safe(ui))
374 {
375 put_status_message(_(" error: split in progress..."), ui);
376 return;
377 }
378
379 if (get_output_directory(ui) != NULL)
380 {
381 split_action(ui);
382 }
383 else
384 {
385 put_status_message(_(" error: no path of split selected"), ui);
386 }
387}
388
389void set_split_file_mode(gint file_mode, ui_state *ui)
390{
391 ui->infos->split_file_mode = file_mode;
392}
393
394gint get_split_file_mode(ui_state *ui)
395{
396 return ui->infos->split_file_mode;
397}
398
399static void single_file_mode_split_button_event(GtkWidget *widget, ui_state *ui)
400{
401 set_split_file_mode(FILE_MODE_SINGLE, ui);
402 split_button_event(widget, ui);
403}
404
405static void show_messages_history_window(GSimpleAction *action, GVariant *parameter, gpointer data)
406{
407 ui_state *ui = (ui_state *) data;
408 wh_show_window(ui->gui->mess_history_window);
409}
410
411#ifndef NO_GNOME
412static void ShowHelp(GSimpleAction *action, GVariant *parameter, gpointer data)
413{
414 GError* gerror = NULL;
415 gtk_show_uri(gdk_screen_get_default(), "ghelp:mp3splt-gtk", gtk_get_current_event_time(), &gerror);
416}
417#endif
418
419static void player_pause_action(GSimpleAction *action, GVariant *parameter, gpointer data)
420{
421 ui_state *ui = (ui_state *) data;
422 pause_event(ui->gui->pause_button, ui);
423}
424
425static void player_seek_forward_action(GSimpleAction *action, GVariant *parameter, gpointer data)
426{
427 ui_state *ui = (ui_state *) data;
428
429 gfloat total_time = ui->infos->total_time;
430 gfloat new_time = ui->infos->current_time * 10 +
431 (ui->infos->seek_jump_value != 0 ? ui->infos->seek_jump_value :
432 2./100. * total_time * 10);
433 if (new_time > total_time * 10) { new_time = total_time * 10; }
434 player_seek(new_time, ui);
435}
436
437static void player_seek_backward_action(GSimpleAction *action, GVariant *parameter, gpointer data)
438{
439 ui_state *ui = (ui_state *) data;
440
441 gfloat total_time = ui->infos->total_time;
442 gfloat new_time = ui->infos->current_time * 10 -
443 (ui->infos->seek_jump_value != 0 ? ui->infos->seek_jump_value :
444 2./100. * total_time * 10);
445 if (new_time <= 0) { new_time = 0; }
446 player_seek(new_time, ui);
447}
448
449static void player_big_seek_forward_action(GSimpleAction *action, GVariant *parameter, gpointer data)
450{
451 ui_state *ui = (ui_state *) data;
452
453 gfloat total_time = ui->infos->total_time;
454 gfloat new_time = ui->infos->current_time * 10 +
455 (ui->infos->big_seek_jump_value != 0 ? ui->infos->big_seek_jump_value :
456 15./100. * total_time * 10);
457 if (new_time > total_time * 10) { new_time = total_time * 10; }
458 player_seek(new_time, ui);
459}
460
461static void player_big_seek_backward_action(GSimpleAction *action, GVariant *parameter, gpointer data)
462{
463 ui_state *ui = (ui_state *) data;
464
465 gfloat total_time = ui->infos->total_time;
466 gfloat new_time = ui->infos->current_time * 10 -
467 (ui->infos->big_seek_jump_value != 0 ? ui->infos->big_seek_jump_value :
468 15./100. * total_time * 10);
469 if (new_time <= 0) { new_time = 0; }
470 player_seek(new_time, ui);
471}
472
473static void player_small_seek_forward_action(GSimpleAction *action, GVariant *parameter, gpointer data)
474{
475 ui_state *ui = (ui_state *) data;
476
477 gfloat total_time = ui->infos->total_time;
478 gfloat new_time = ui->infos->current_time * 10 + ui->infos->small_seek_jump_value;
479 if (new_time > total_time * 10) { new_time = total_time * 10; }
480 player_seek(new_time, ui);
481}
482
483static void player_small_seek_backward_action(GSimpleAction *action, GVariant *parameter, gpointer data)
484{
485 ui_state *ui = (ui_state *) data;
486
487 gfloat new_time = ui->infos->current_time * 10 - ui->infos->small_seek_jump_value;
488 if (new_time <= 0) { new_time = 0; }
489 player_seek(new_time, ui);
490}
491
492static void player_seek_to_next_splitpoint_action(GSimpleAction *action, GVariant *parameter, gpointer data)
493{
494 ui_state *ui = (ui_state *) data;
495
496 gint time_left = -1;
497 gint time_right = -1;
498 get_current_splitpoints_time_left_right(&time_left, &time_right, NULL, ui);
499
500 if (time_right != -1)
501 {
502 player_seek(time_right * 10, ui);
503 }
504}
505
506static void player_seek_to_previous_splitpoint_action(GSimpleAction *action, GVariant *parameter, gpointer data)
507{
508 ui_state *ui = (ui_state *) data;
509
510 gint time_left = -1;
511 gint time_right = -1;
512 get_current_splitpoints_time_left_right(&time_left, &time_right, NULL, ui);
513
514 if (time_left != -1)
515 {
516 player_seek(time_left * 10, ui);
517 }
518}
519
520static int find_closest_splitpoint(ui_state *ui)
521{
522 gint left_index_point = -1;
523 gint right_index_point = -1;
524
525 gint i = 0;
526 for (i = 0; i < ui->infos->splitnumber; i++ )
527 {
528 gint current_point_hundr_secs = get_splitpoint_time(i, ui);
529 if (current_point_hundr_secs <= ui->infos->current_time)
530 {
531 left_index_point = i;
532 continue;
533 }
534
535 if (current_point_hundr_secs >= ui->infos->current_time)
536 {
537 right_index_point = i;
538 break;
539 }
540 }
541
542 if (left_index_point == -1 && right_index_point == -1)
543 {
544 return -1;
545 }
546
547 gint time_to_left = INT_MAX;
548 if (left_index_point != -1)
549 {
550 time_to_left = ui->infos->current_time - get_splitpoint_time(left_index_point, ui);
551 }
552
553 gint time_to_right = INT_MAX;
554 if (right_index_point != -1)
555 {
556 time_to_right = get_splitpoint_time(right_index_point, ui) - ui->infos->current_time;
557 }
558
559 if (time_to_right > time_to_left)
560 {
561 return left_index_point;
562 }
563
564 return right_index_point;
565}
566
567static void delete_closest_splitpoint(GSimpleAction *action, GVariant *parameter, gpointer data)
568{
569 ui_state *ui = (ui_state *) data;
570
571 int closest_splitpoint_index = find_closest_splitpoint(ui);
572 if (closest_splitpoint_index == -1)
573 {
574 return;
575 }
576
577 remove_splitpoint(closest_splitpoint_index, TRUE, ui);
578}
579
580static void player_seek_before_closest_splitpoint(GSimpleAction *action, GVariant *parameter, gpointer data)
581{
582 ui_state *ui = (ui_state *) data;
583
584 int closest_splitpoint_index = find_closest_splitpoint(ui);
585 if (closest_splitpoint_index == -1) { return; }
586
587 gint current_point_hundr_secs = get_splitpoint_time(closest_splitpoint_index, ui);
588 player_seek((current_point_hundr_secs * 10) - 100 * 3 * 10, ui);
589
590 if (closest_splitpoint_index == 0) { return; }
591
592 set_preview_start_position_safe(get_splitpoint_time(closest_splitpoint_index - 1, ui), ui);
593 ui->status->preview_start_splitpoint = closest_splitpoint_index - 1;
594 if (closest_splitpoint_index < ui->infos->splitnumber)
595 {
596 set_quick_preview_end_splitpoint_safe(closest_splitpoint_index, ui);
597 }
598 else
599 {
600 set_quick_preview_end_splitpoint_safe(-1, ui);
601 }
602
603 if (player_is_paused(ui))
604 {
605 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ui->gui->pause_button), FALSE);
606 }
607
608 ui->status->quick_preview = TRUE;
609}
610
611static void player_seek_closest_splitpoint_no_pause(GSimpleAction *action, GVariant *parameter, gpointer data)
612{
613 ui_state *ui = (ui_state *) data;
614
615 int closest_splitpoint_index = find_closest_splitpoint(ui);
616 if (closest_splitpoint_index == -1) { return; }
617
618 gint current_point_hundr_secs = get_splitpoint_time(closest_splitpoint_index, ui);
619 player_seek(current_point_hundr_secs * 10, ui);
620
621 set_preview_start_position_safe(current_point_hundr_secs, ui);
622 ui->status->preview_start_splitpoint = closest_splitpoint_index;
623
624 if (closest_splitpoint_index < (ui->infos->splitnumber - 1))
625 {
626 set_quick_preview_end_splitpoint_safe(closest_splitpoint_index + 1, ui);
627 }
628 else
629 {
630 set_quick_preview_end_splitpoint_safe(-1, ui);
631 }
632
633 if (player_is_paused(ui))
634 {
635 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ui->gui->pause_button), FALSE);
636 }
637
638 ui->status->quick_preview = TRUE;
639}
640
641static void player_seek_closest_splitpoint(GSimpleAction *action, GVariant *parameter, gpointer data)
642{
643 ui_state *ui = (ui_state *) data;
644 player_seek_closest_splitpoint_no_pause(NULL, NULL, ui);
645 ui->status->stop_preview_right_after_start = TRUE;
646}
647
648static void zoom_in(GSimpleAction *action, GVariant *parameter, gpointer data)
649{
650 ui_state *ui = (ui_state *) data;
651
652 gdouble fraction = 40./100. * ui->infos->zoom_coeff;
653 ui->infos->zoom_coeff += fraction;
654 adjust_zoom_coeff(ui->infos);
655 refresh_drawing_area(ui->gui, ui->infos);
656}
657
658static void zoom_out(GSimpleAction *action, GVariant *parameter, gpointer data)
659{
660 ui_state *ui = (ui_state *) data;
661
662 gdouble fraction = 40./100. * ui->infos->zoom_coeff;
663 ui->infos->zoom_coeff -= fraction;
664 adjust_zoom_coeff(ui->infos);
665 refresh_drawing_area(ui->gui, ui->infos);
666}
667
668void add_filters_to_file_chooser(GtkWidget *file_chooser)
669{
670 GtkFileFilter *our_filter = gtk_file_filter_new();
671 gtk_file_filter_set_name(our_filter, _("mp3, ogg vorbis and flac files (*.mp3 *.ogg *.flac)"));
672 gtk_file_filter_add_pattern(our_filter, "*.mp3");
673 gtk_file_filter_add_pattern(our_filter, "*.ogg");
674 gtk_file_filter_add_pattern(our_filter, "*.flac");
675 gtk_file_filter_add_pattern(our_filter, "*.MP3");
676 gtk_file_filter_add_pattern(our_filter, "*.OGG");
677 gtk_file_filter_add_pattern(our_filter, "*.FLAC");
678 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(file_chooser), our_filter);
679
680 our_filter = gtk_file_filter_new();
681 gtk_file_filter_set_name (our_filter, _("mp3 files (*.mp3)"));
682 gtk_file_filter_add_pattern(our_filter, "*.mp3");
683 gtk_file_filter_add_pattern(our_filter, "*.MP3");
684 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(file_chooser), our_filter);
685
686 our_filter = gtk_file_filter_new();
687 gtk_file_filter_set_name (our_filter, _("ogg vorbis files (*.ogg)"));
688 gtk_file_filter_add_pattern(our_filter, "*.ogg");
689 gtk_file_filter_add_pattern(our_filter, "*.OGG");
690 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(file_chooser), our_filter);
691
692 our_filter = gtk_file_filter_new();
693 gtk_file_filter_set_name (our_filter, _("flac files (*.flac)"));
694 gtk_file_filter_add_pattern(our_filter, "*.flac");
695 gtk_file_filter_add_pattern(our_filter, "*.FLAC");
696 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(file_chooser), our_filter);
697}
698
699static void file_selection_changed(GtkFileChooser *open_file_chooser, ui_state *ui)
700{
701 gchar *filename = gtk_file_chooser_get_filename(open_file_chooser);
702 gchar *previous_fname = get_input_filename(ui->gui);
703
704 if (previous_fname != NULL && filename != NULL &&
705 strcmp(filename, previous_fname) == 0)
706 {
707 return;
708 }
709
710 if (filename != NULL)
711 {
712 ui->status->file_selection_changed = TRUE;
713 file_chooser_ok_event(filename, ui);
714 ui->status->file_selection_changed = FALSE;
715
716 g_free(filename);
717 filename = NULL;
718 return;
719 }
720}
721
722static void file_set_event(GtkFileChooserButton *open_file_chooser_button, ui_state *ui)
723{
724 file_selection_changed(GTK_FILE_CHOOSER(open_file_chooser_button), ui);
725}
726
727static GtkWidget *create_choose_file_frame(ui_state *ui)
728{
729 GtkWidget *open_file_chooser_button = gtk_file_chooser_button_new(_("Open file ..."), GTK_FILE_CHOOSER_ACTION_OPEN);
730 dnd_add_drag_data_received_to_widget(open_file_chooser_button, DND_SINGLE_MODE_AUDIO_FILE, ui);
731
732 ui->gui->open_file_chooser_button = open_file_chooser_button;
733 add_filters_to_file_chooser(open_file_chooser_button);
734 wh_set_browser_directory_handler(ui, open_file_chooser_button);
735
736 g_signal_connect(G_OBJECT(open_file_chooser_button), "file-set", G_CALLBACK(file_set_event), ui);
737 g_signal_connect(G_OBJECT(open_file_chooser_button), "selection-changed",
738 G_CALLBACK(file_selection_changed), ui);
739
740 gchar *fname = get_input_filename(ui->gui);
741 if (fname != NULL && strlen(fname) != 0)
742 {
743 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(open_file_chooser_button), get_input_filename(ui->gui));
744 }
745
746 return open_file_chooser_button;
747}
748
750static GtkWidget *create_main_vbox(ui_state *ui)
751{
752 GtkWidget *main_vbox = wh_vbox_new();
753 gtk_container_set_border_width(GTK_CONTAINER(main_vbox), 0);
754
755 /* tabbed notebook */
756 GtkWidget *notebook = gtk_notebook_new();
757
758 gtk_box_pack_start(GTK_BOX(main_vbox), notebook, TRUE, TRUE, 0);
759 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook), TRUE);
760 gtk_notebook_set_show_border(GTK_NOTEBOOK(notebook), FALSE);
761 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
762
763 /* player page */
764 GtkWidget *player_vbox = wh_vbox_new();
765
766 //file & split button hbox
767 GtkWidget *top_hbox = wh_hbox_new();
768 gtk_box_pack_start(GTK_BOX(player_vbox), top_hbox, FALSE, FALSE, 0);
769
770 //choose file
771 gtk_box_pack_start(GTK_BOX(top_hbox), create_choose_file_frame(ui), TRUE, TRUE, 0);
772
773 //single mode split button
774 GtkWidget *split_button = wh_create_cool_button("system-run",_("Split"), FALSE);
775 g_signal_connect(G_OBJECT(split_button), "clicked",
776 G_CALLBACK(single_file_mode_split_button_event), ui);
777 gtk_widget_set_tooltip_text(split_button, _("Split the current file"));
778 gtk_box_pack_start(GTK_BOX(top_hbox), split_button, FALSE, FALSE, 4);
779
780 ui->gui->player_box = create_player_control_frame(ui);
781 gtk_box_pack_start(GTK_BOX(player_vbox), ui->gui->player_box, FALSE, FALSE, 0);
782
783 ui->gui->playlist_box = create_player_playlist_frame(ui);
784 gtk_box_pack_start(GTK_BOX(player_vbox), ui->gui->playlist_box, TRUE, TRUE, 0);
785
786 GtkWidget *notebook_label = wh_create_cool_label(NULL, _("Manual single file split"));
787 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), player_vbox, notebook_label);
788
789 /* splitpoints page */
790 ui->gui->splitpoints_widget = create_splitpoints_frame(ui);
791
792 /* split files page */
793 ui->gui->split_files_widget = create_split_files_frame(ui);
794
795 /* freedb page */
796 ui->gui->freedb_widget = create_freedb_frame(ui);
797
798 /* special split page */
799 GtkWidget *special_split_vbox = wh_vbox_new();
800 gtk_container_set_border_width(GTK_CONTAINER(special_split_vbox), 0);
801 GtkWidget *frame = create_special_split_page(ui);
802 gtk_box_pack_start(GTK_BOX(special_split_vbox), frame, TRUE, TRUE, 0);
803
804 notebook_label = wh_create_cool_label(NULL, _("Batch & automatic split"));
805 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), special_split_vbox, notebook_label);
806
807 /* preferences widget */
808 ui->gui->preferences_widget = create_choose_preferences(ui);
809
810 /* progress bar */
811 GtkProgressBar *percent_progress_bar = GTK_PROGRESS_BAR(gtk_progress_bar_new());
812 ui->gui->percent_progress_bar = percent_progress_bar;
813 gtk_progress_bar_set_fraction(percent_progress_bar, 0.0);
814 gtk_progress_bar_set_text(percent_progress_bar, "");
815
816 gtk_progress_bar_set_show_text(percent_progress_bar, TRUE);
817
818 GtkWidget *hbox = wh_hbox_new();
819 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(percent_progress_bar), TRUE, TRUE, 0);
820
821 //stop button
822 GtkWidget *cancel_button = wh_create_cool_button("process-stop", _("S_top"), FALSE);
823 ui->gui->cancel_button = cancel_button;
824 g_signal_connect(G_OBJECT(cancel_button), "clicked", G_CALLBACK(cancel_button_event), ui);
825 gtk_box_pack_start(GTK_BOX(hbox), cancel_button, FALSE, TRUE, 3);
826 gtk_widget_set_sensitive(cancel_button, FALSE);
827
828 gtk_box_pack_start(GTK_BOX(main_vbox), hbox, FALSE, FALSE, 2);
829
830 /* show messages history dialog */
832
833 /* statusbar */
834 GtkStatusbar *status_bar = GTK_STATUSBAR(gtk_statusbar_new());
835 ui->gui->status_bar = status_bar;
836
837 gtk_box_pack_start(GTK_BOX(main_vbox), GTK_WIDGET(status_bar), FALSE, FALSE, 0);
838
839 return main_vbox;
840}
841
842static void move_and_resize_main_window(ui_state *ui)
843{
844 const ui_main_window *main_win = ui_get_main_window_infos(ui);
845
846 gint x = main_win->root_x_pos;
847 gint y = main_win->root_y_pos;
848
849 if (x != 0 && y != 0)
850 {
851 gtk_window_move(GTK_WINDOW(ui->gui->window), x, y);
852 }
853 else
854 {
855 gtk_window_set_position(GTK_WINDOW(ui->gui->window), GTK_WIN_POS_CENTER);
856 }
857
858 gtk_window_resize(GTK_WINDOW(ui->gui->window), main_win->width, main_win->height);
859}
860
861static void application_startup(GApplication *app, ui_state *ui)
862{
863 GtkBuilder *builder = gtk_builder_new();
864
865 gtk_builder_add_from_string(builder,
866 "<?xml version=\"1.0\" ?>"
867 "<interface>"
868
869 " <menu id=\"appmenu\">"
870 " <section>"
871 " <item>"
872 " <attribute name=\"label\" translatable=\"yes\">_Preferences</attribute>"
873 " <attribute name=\"action\">app.preferences</attribute>"
874 " <attribute name=\"accel\">&lt;Primary&gt;p</attribute>"
875 " </item>"
876 " <item>"
877 " <attribute name=\"label\" translatable=\"yes\">_Quit</attribute>"
878 " <attribute name=\"action\">app.quit</attribute>"
879 " <attribute name=\"accel\">&lt;Primary&gt;q</attribute>"
880 " </item>"
881 " </section>"
882 " </menu>"
883
884 " <menu id=\"menubar\">"
885
886 " <submenu>"
887 " <attribute name=\"label\" translatable=\"yes\">_File</attribute>"
888 " <section>"
889 " <item>"
890 " <attribute name=\"label\" translatable=\"yes\">_Open single file...</attribute>"
891 " <attribute name=\"action\">app.open_single_file</attribute>"
892 " <attribute name=\"accel\">&lt;Primary&gt;o</attribute>"
893 " </item>"
894 " <item>"
895 " <attribute name=\"label\" translatable=\"yes\">_Add files or directories to batch...</attribute>"
896 " <attribute name=\"action\">app.add_files_to_batch</attribute>"
897 " <attribute name=\"accel\">&lt;Primary&gt;d</attribute>"
898 " </item>"
899 " </section>"
900 " <section>"
901 " <item>"
902 " <attribute name=\"label\" translatable=\"yes\">_Import splitpoints from file...</attribute>"
903 " <attribute name=\"action\">app.import_splitpoints_from_file</attribute>"
904 " <attribute name=\"accel\">&lt;Primary&gt;i</attribute>"
905 " </item>"
906 " <item>"
907 " <attribute name=\"label\" translatable=\"yes\">_Import splitpoints from _TrackType.org...</attribute>"
908 " <attribute name=\"action\">app.import_splitpoints_from_tracktype</attribute>"
909 " <attribute name=\"accel\">&lt;Primary&gt;t</attribute>"
910 " </item>"
911 " <item>"
912 " <attribute name=\"label\" translatable=\"yes\">_Export splitpoints...</attribute>"
913 " <attribute name=\"action\">app.export_splitpoints</attribute>"
914 " <attribute name=\"accel\">&lt;Primary&gt;e</attribute>"
915 " </item>"
916 " </section>"
917 " <section>"
918 " <item>"
919 " <attribute name=\"label\" translatable=\"yes\">_Split</attribute>"
920 " <attribute name=\"action\">app.split</attribute>"
921 " <attribute name=\"accel\">&lt;Primary&gt;s</attribute>"
922 " </item>"
923 " <item>"
924 " <attribute name=\"label\" translatable=\"yes\">_Batch split</attribute>"
925 " <attribute name=\"action\">app.batch_split</attribute>"
926 " <attribute name=\"accel\">&lt;Primary&gt;b</attribute>"
927 " </item>"
928 " </section>"
929 " </submenu>"
930
931 " <submenu>"
932 " <attribute name=\"label\" translatable=\"yes\">_View</attribute>"
933 " <section>"
934 " <item>"
935 " <attribute name=\"label\" translatable=\"yes\">_Splitpoints</attribute>"
936 " <attribute name=\"action\">app.view_splitpoints</attribute>"
937 " <attribute name=\"accel\">&lt;Primary&gt;l</attribute>"
938 " </item>"
939 " <item>"
940 " <attribute name=\"label\" translatable=\"yes\">Split _files</attribute>"
941 " <attribute name=\"action\">app.view_split_files</attribute>"
942 " <attribute name=\"accel\">&lt;Primary&gt;f</attribute>"
943 " </item>"
944 " </section>"
945 " </submenu>"
946
947 " <submenu>"
948 " <attribute name=\"label\" translatable=\"yes\">_Player</attribute>"
949 " <section>"
950 " <item>"
951 " <attribute name=\"label\" translatable=\"yes\">P_ause / Play</attribute>"
952 " <attribute name=\"action\">app.pause_play</attribute>"
953 " <attribute name=\"accel\">space</attribute>"
954 " </item>"
955 " </section>"
956
957 " <section>"
958 " <item>"
959 " <attribute name=\"label\" translatable=\"yes\">Seek _forward</attribute>"
960 " <attribute name=\"action\">app.seek_forward</attribute>"
961 " <attribute name=\"accel\">Right</attribute>"
962 " </item>"
963 " <item>"
964 " <attribute name=\"label\" translatable=\"yes\">Seek _backward</attribute>"
965 " <attribute name=\"action\">app.seek_backward</attribute>"
966 " <attribute name=\"accel\">Left</attribute>"
967 " </item>"
968 " <item>"
969 " <attribute name=\"label\" translatable=\"yes\">Small seek f_orward</attribute>"
970 " <attribute name=\"action\">app.small_seek_forward</attribute>"
971 " <attribute name=\"accel\">&lt;Alt&gt;Right</attribute>"
972 " </item>"
973 " <item>"
974 " <attribute name=\"label\" translatable=\"yes\">Small seek back_ward</attribute>"
975 " <attribute name=\"action\">app.small_seek_backward</attribute>"
976 " <attribute name=\"accel\">&lt;Alt&gt;Left</attribute>"
977 " </item>"
978 " <item>"
979 " <attribute name=\"label\" translatable=\"yes\">Big seek fo_rward</attribute>"
980 " <attribute name=\"action\">app.big_seek_forward</attribute>"
981 " <attribute name=\"accel\">&lt;Shift&gt;Right</attribute>"
982 " </item>"
983 " <item>"
984 " <attribute name=\"label\" translatable=\"yes\">Big seek bac_kward</attribute>"
985 " <attribute name=\"action\">app.big_seek_backward</attribute>"
986 " <attribute name=\"accel\">&lt;Shift&gt;Left</attribute>"
987 " </item>"
988 " <item>"
989 " <attribute name=\"label\" translatable=\"yes\">Seek to _next splitpoint</attribute>"
990 " <attribute name=\"action\">app.seek_next_splitpoint</attribute>"
991 " <attribute name=\"accel\">&lt;Primary&gt;Right</attribute>"
992 " </item>"
993 " <item>"
994 " <attribute name=\"label\" translatable=\"yes\">Seek to _previous splitpoint</attribute>"
995 " <attribute name=\"action\">app.seek_previous_splitpoint</attribute>"
996 " <attribute name=\"accel\">&lt;Primary&gt;Left</attribute>"
997 " </item>"
998 " </section>"
999
1000 " <section>"
1001 " <item>"
1002 " <attribute name=\"label\" translatable=\"yes\">Preview clos_est splitpoint</attribute>"
1003 " <attribute name=\"action\">app.preview_closest</attribute>"
1004 " <attribute name=\"accel\">&lt;Shift&gt;Up</attribute>"
1005 " </item>"
1006 " <item>"
1007 " <attribute name=\"label\" translatable=\"yes\">Preview _closest splitpoint &amp; pause</attribute>"
1008 " <attribute name=\"action\">app.preview_closest_and_pause</attribute>"
1009 " <attribute name=\"accel\">&lt;Primary&gt;Up</attribute>"
1010 " </item>"
1011 " <item>"
1012 " <attribute name=\"label\" translatable=\"yes\">Preview before c_losest splitpoint</attribute>"
1013 " <attribute name=\"action\">app.preview_before_closest</attribute>"
1014 " <attribute name=\"accel\">&lt;Primary&gt;Down</attribute>"
1015 " </item>"
1016 " </section>"
1017
1018 " <section>"
1019 " <item>"
1020 " <attribute name=\"label\" translatable=\"yes\">Add _splitpoint</attribute>"
1021 " <attribute name=\"action\">app.add_splitpoint</attribute>"
1022 " <attribute name=\"accel\">s</attribute>"
1023 " </item>"
1024 " <item>"
1025 " <attribute name=\"label\" translatable=\"yes\">_Delete closest splitpoint</attribute>"
1026 " <attribute name=\"action\">app.delete_closest_splitpoint</attribute>"
1027 " <attribute name=\"accel\">d</attribute>"
1028 " </item>"
1029 " </section>"
1030
1031 " <section>"
1032 " <item>"
1033 " <attribute name=\"label\" translatable=\"yes\">Zoom _in</attribute>"
1034 " <attribute name=\"action\">app.zoom_in</attribute>"
1035 " <attribute name=\"accel\">&lt;Primary&gt;plus</attribute>"
1036 " </item>"
1037 " <item>"
1038 " <attribute name=\"label\" translatable=\"yes\">Zoom _out</attribute>"
1039 " <attribute name=\"action\">app.zoom_out</attribute>"
1040 " <attribute name=\"accel\">&lt;Primary&gt;minus</attribute>"
1041 " </item>"
1042 " </section>"
1043 " </submenu>"
1044
1045 " <submenu>"
1046 " <attribute name=\"label\" translatable=\"yes\">_Help</attribute>"
1047 " <section>"
1048 " <item>"
1049 " <attribute name=\"label\" translatable=\"yes\">Messages _history</attribute>"
1050 " <attribute name=\"action\">app.messages_history</attribute>"
1051 " <attribute name=\"accel\">&lt;Primary&gt;h</attribute>"
1052 " </item>"
1053#ifndef NO_GNOME
1054 " <item>"
1055 " <attribute name=\"label\" translatable=\"yes\">_Contents</attribute>"
1056 " <attribute name=\"action\">app.contents</attribute>"
1057 " <attribute name=\"accel\">F1</attribute>"
1058 " </item>"
1059#endif
1060 " <item>"
1061 " <attribute name=\"label\" translatable=\"yes\">_About</attribute>"
1062 " <attribute name=\"action\">app.about</attribute>"
1063 " <attribute name=\"accel\">&lt;Primary&gt;a</attribute>"
1064 " </item>"
1065 " </section>"
1066 " </submenu>"
1067
1068 " </menu>"
1069 "</interface>", -1, NULL);
1070
1071 GMenuModel *appmenu = (GMenuModel *) gtk_builder_get_object(builder, "appmenu");
1072 gtk_application_set_app_menu(GTK_APPLICATION(app), appmenu);
1073
1074 GMenuModel *menubar = (GMenuModel *) gtk_builder_get_object (builder, "menubar");
1075 gtk_application_set_menubar(GTK_APPLICATION(app), menubar);
1076
1077 g_object_unref(builder);
1078}
1079
1080static void parse_command_line_options(gint argc, gchar * argv[], ui_state *ui)
1081{
1082 opterr = 0;
1083 int option;
1084 while ((option = getopt(argc, argv, "d:")) != -1)
1085 {
1086 switch (option)
1087 {
1088 case 'd':
1089 fprintf(stdout, _("Setting the output directory to %s.\n"), optarg);
1090 set_output_directory_and_update_ui((gchar *)optarg, ui);
1091#ifdef __WIN32__
1092 mkdir(optarg);
1093#else
1094 mkdir(optarg, 0777);
1095#endif
1096 if (!directory_exists(optarg))
1097 {
1098 ui_fail(ui, "Error: The specified output directory is inaccessible!\n");
1099 }
1100 break;
1101 case '?':
1102 if (optopt == 'd')
1103 ui_fail(ui, _("Option -%c requires an argument.\n"), optopt);
1104 else if (isprint(optopt))
1105 ui_fail(ui, _("Unknown option `-%c'.\n"), optopt, NULL);
1106 else
1107 ui_fail(ui, _("Unknown option character `\\x%x'.\n"), optopt);
1108 break;
1109 default:
1110 ui_fail(ui, NULL);
1111 }
1112 }
1113
1114 if (optind == argc)
1115 {
1116 return;
1117 }
1118
1119 if (!file_exists(argv[optind]))
1120 {
1121 ui_fail(ui, _("Cannot open input file %s\n"), argv[optind]);
1122 }
1123
1124#ifndef __WIN32__
1125 char *input_filename = realpath(argv[optind], NULL);
1126 import_file(input_filename, ui, FALSE, TRUE);
1127 free(input_filename);
1128#else
1129 import_file(argv[optind], ui, FALSE, TRUE);
1130#endif
1131}
1132
1133static void application_activate(GApplication *app, ui_state *ui)
1134{
1135 initialize_window(app, ui);
1136
1137 GtkWidget *window_vbox = wh_vbox_new();
1138 gtk_container_add(GTK_CONTAINER(ui->gui->window), window_vbox);
1139
1140 gtk_box_pack_start(GTK_BOX(window_vbox), create_main_vbox(ui), TRUE, TRUE, 0);
1141
1142 ui_load_preferences(ui);
1143
1144 move_and_resize_main_window(ui);
1145
1146 gtk_widget_show_all(ui->gui->window);
1147
1148 if (ui->infos->selected_player != PLAYER_GSTREAMER)
1149 {
1150 gtk_widget_hide(ui->gui->playlist_box);
1151 }
1152
1153 hide_freedb_spinner(ui->gui);
1154
1155 import_cue_file_from_the_configuration_directory(ui);
1156
1157 parse_command_line_options(ui->argc, ui->argv, ui);
1158}
1159
1160static void open_file_menu_action(GSimpleAction *action, GVariant *parameter, gpointer data)
1161{
1162 ui_state *ui = (ui_state *) data;
1163
1164 GtkWidget *file_chooser = gtk_file_chooser_dialog_new(_("Choose File"), NULL,
1165 GTK_FILE_CHOOSER_ACTION_OPEN,
1166 _("_Cancel"),
1167 GTK_RESPONSE_CANCEL,
1168 _("_Open"),
1169 GTK_RESPONSE_ACCEPT, NULL);
1170
1171 add_filters_to_file_chooser(file_chooser);
1172 wh_set_browser_directory_handler(ui, file_chooser);
1173
1174 if (gtk_dialog_run(GTK_DIALOG(file_chooser)) == GTK_RESPONSE_ACCEPT)
1175 {
1176 gchar *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(file_chooser));
1177 file_chooser_ok_event(filename, ui);
1178 if (filename)
1179 {
1180 g_free(filename);
1181 filename = NULL;
1182 }
1183 }
1184
1185 gtk_widget_destroy(file_chooser);
1186 remove_status_message(ui->gui);
1187}
1188
1189static void multiple_files_add_menu_action(GSimpleAction *action, GVariant *parameter, gpointer data)
1190{
1191 ui_state *ui = (ui_state *) data;
1192 multiple_files_add_button_event(NULL, ui);
1193}
1194
1195static void import_event_menu_action(GSimpleAction *action, GVariant *parameter, gpointer data)
1196{
1197 ui_state *ui = (ui_state *) data;
1198 import_event(NULL, ui);
1199}
1200
1201static void show_tracktype_window_menu_action(GSimpleAction *action, GVariant *parameter, gpointer data)
1202{
1203 ui_state *ui = (ui_state *) data;
1204
1205 if (ui->gui->freedb_window == NULL)
1206 {
1207 ui->gui->freedb_window =
1208 wh_create_window_with_close_button(_("TrackType"), 500, 300, GTK_WIN_POS_CENTER,
1209 GTK_WINDOW(ui->gui->window),
1210 ui->gui->freedb_widget,
1211 ui->gui->freedb_add_button, NULL);
1212 }
1213
1214 wh_show_window(ui->gui->freedb_window);
1215 hide_freedb_spinner(ui->gui);
1216}
1217
1218static void show_preferences_window_menu_action(GSimpleAction *action, GVariant *parameter, gpointer data)
1219{
1220 ui_state *ui = (ui_state *) data;
1221
1222 if (ui->gui->preferences_window == NULL)
1223 {
1224 ui->gui->preferences_window =
1225 wh_create_window_with_close_button(_("Preferences"), 750, 450, GTK_WIN_POS_CENTER,
1226 GTK_WINDOW(ui->gui->window), ui->gui->preferences_widget, NULL);
1227 }
1228
1229 wh_show_window(ui->gui->preferences_window);
1230}
1231
1232static void split_menu_action(GSimpleAction *action, GVariant *parameter, gpointer data)
1233{
1234 ui_state *ui = (ui_state *) data;
1235 single_file_mode_split_button_event(NULL, ui);
1236}
1237
1238static void batch_split_menu_action(GSimpleAction *action, GVariant *parameter, gpointer data)
1239{
1240 ui_state *ui = (ui_state *) data;
1241 batch_file_mode_split_button_event(NULL, ui);
1242}
1243
1244static void exit_application_menu_action(GSimpleAction *action, GVariant *parameter, gpointer data)
1245{
1246 ui_state *ui = (ui_state *) data;
1247 exit_application(NULL, NULL, ui);
1248}
1249
1250static void show_splitpoints_window_menu_action(GSimpleAction *action, GVariant *parameter, gpointer data)
1251{
1252 ui_state *ui = (ui_state *) data;
1253
1254 if (ui->gui->splitpoints_window == NULL)
1255 {
1256 ui->gui->splitpoints_window =
1257 wh_create_window_with_close_button(_("Splitpoints"), 500, 300, GTK_WIN_POS_CENTER,
1258 GTK_WINDOW(ui->gui->window),
1259 ui->gui->splitpoints_widget,
1260 ui->gui->scan_trim_silence_button, ui->gui->scan_silence_button, NULL);
1261 }
1262
1263 wh_show_window(ui->gui->splitpoints_window);
1264}
1265
1266static void show_split_files_window_menu_action(GSimpleAction *action, GVariant *parameter, gpointer data)
1267{
1268 ui_state *ui = (ui_state *) data;
1269
1270 if (ui->gui->split_files_window == NULL)
1271 {
1272 ui->gui->split_files_window =
1273 wh_create_window_with_close_button(_("Split files"), 500, 300, GTK_WIN_POS_CENTER,
1274 GTK_WINDOW(ui->gui->window),
1275 ui->gui->split_files_widget,
1276 ui->gui->queue_files_button, ui->gui->remove_file_button,
1277 ui->gui->remove_all_files_button, NULL);
1278 }
1279
1280 wh_show_window(ui->gui->split_files_window);
1281}
1282
1283static void add_splitpoint_from_player_menu_action(GSimpleAction *action, GVariant *parameter, gpointer data)
1284{
1285 ui_state *ui = (ui_state *) data;
1286 add_splitpoint_from_player(NULL, ui);
1287}
1288
1289const static GActionEntry app_entries[] = {
1290 {"open_single_file", open_file_menu_action},
1291 {"add_files_to_batch", multiple_files_add_menu_action},
1292 {"import_splitpoints_from_file", import_event_menu_action},
1293 {"import_splitpoints_from_tracktype", show_tracktype_window_menu_action},
1294 {"export_splitpoints", export_menu_action},
1295 {"preferences", show_preferences_window_menu_action},
1296 {"split", split_menu_action},
1297 {"batch_split", batch_split_menu_action},
1298 {"quit", exit_application_menu_action},
1299
1300 {"view_splitpoints", show_splitpoints_window_menu_action},
1301 {"view_split_files", show_split_files_window_menu_action},
1302
1303 {"pause_play", player_pause_action},
1304 {"seek_forward", player_seek_forward_action},
1305 {"seek_backward", player_seek_backward_action},
1306 {"small_seek_forward", player_small_seek_forward_action},
1307 {"small_seek_backward", player_small_seek_backward_action},
1308 {"big_seek_forward", player_big_seek_forward_action},
1309 {"big_seek_backward", player_big_seek_backward_action},
1310 {"seek_next_splitpoint", player_seek_to_next_splitpoint_action},
1311 {"seek_previous_splitpoint", player_seek_to_previous_splitpoint_action},
1312 {"preview_closest", player_seek_closest_splitpoint_no_pause},
1313 {"preview_closest_and_pause", player_seek_closest_splitpoint},
1314 {"preview_before_closest", player_seek_before_closest_splitpoint},
1315 {"add_splitpoint", add_splitpoint_from_player_menu_action},
1316 {"delete_closest_splitpoint", delete_closest_splitpoint},
1317 {"zoom_in", zoom_in},
1318 {"zoom_out", zoom_out},
1319
1320 {"messages_history", show_messages_history_window},
1321#ifndef NO_GNOME
1322 {"contents", ShowHelp},
1323#endif
1324 {"about", about_window}
1325};
1326
1327void create_application(ui_state *ui)
1328{
1329 GtkApplication *app = gtk_application_new("net.sf.mp3splt", G_APPLICATION_FLAGS_NONE);
1330 ui->gui->application = app;
1331
1332 g_action_map_add_action_entries(G_ACTION_MAP(app), app_entries, G_N_ELEMENTS(app_entries), ui);
1333
1334 player_key_actions_set_sensitivity(FALSE, ui->gui);
1335
1336 g_signal_connect(app, "startup", G_CALLBACK(application_startup), ui);
1337 g_signal_connect(app, "activate", G_CALLBACK(application_activate), ui);
1338}
1339
1345{
1346 char *error_from_library = mp3splt_get_strerror(ui->mp3splt_state, error);
1347 if (error_from_library == NULL) { return; }
1348
1349 put_status_message(error_from_library, ui);
1350 free(error_from_library);
1351}
1352
1353static gboolean put_status_message_idle(ui_with_fname *ui_fname)
1354{
1355 put_status_message(ui_fname->fname, ui_fname->ui);
1356
1357 g_free(ui_fname->fname);
1358 g_free(ui_fname);
1359
1360 return FALSE;
1361}
1362
1363void put_status_message_in_idle(const gchar *text, ui_state *ui)
1364{
1365 if (text == NULL) { return; }
1366
1367 ui_with_fname *ui_fname = g_malloc0(sizeof(ui_with_fname));
1368 ui_fname->ui = ui;
1369 ui_fname->fname = strdup(text);
1370 if (ui_fname->fname == NULL)
1371 {
1372 g_free(ui_fname);
1373 return;
1374 }
1375
1376 add_idle(G_PRIORITY_HIGH_IDLE,
1377 (GSourceFunc)put_status_message_idle, ui_fname, NULL);
1378}
1379
1380void print_status_bar_confirmation_in_idle(gint error, ui_state *ui)
1381{
1382 char *error_from_library = mp3splt_get_strerror(ui->mp3splt_state, error);
1383 put_status_message_in_idle(error_from_library, ui);
1384}
1385
GtkWidget * create_freedb_frame(ui_state *ui)
creates the freedb box
void import_file(gchar *filename, ui_state *ui, gboolean force_import_cue, gboolean show_errors)
Handles the import of an input file (audio or splitpoint)
Definition import.c:105
void import_event(GtkWidget *widget, ui_state *ui)
What happens if the "Import" button is pressed.
Definition import.c:54
void print_status_bar_confirmation(gint error, ui_state *ui)
Output an error message from libmp3splt to the status bar.
void set_input_filename(const gchar *filename, ui_state *ui)
Set the name of the input file.
Definition main_window.c:44
void put_status_message_with_type(const gchar *text, splt_message_type mess_type, ui_state *ui)
Output a message to the status message bar.
void cancel_button_event(GtkWidget *widget, ui_state *ui)
event for the cancel button
void remove_status_message(gui_state *gui)
Removes status bar message.
void split_button_event(GtkWidget *widget, ui_state *ui)
event for the split button
gchar * get_input_filename(gui_state *gui)
Get the name of the input file.
Definition main_window.c:73
void put_status_message(const gchar *text, ui_state *ui)
Output a info message to the status message bar.
void create_mess_history_window(ui_state *ui)
Create the message history dialog.
void put_message_in_history(const gchar *message, splt_message_type mess_type, ui_state *ui)
Record this message in the message history.
gint player_is_paused(ui_state *ui)
Check if the player is paused.
void player_seek(gint position, ui_state *ui)
jumps to a position in the song
GtkWidget * create_player_playlist_frame(ui_state *ui)
creates the playlist of the player
GtkWidget * create_player_control_frame(ui_state *ui)
creates the control player frame, stop button, play button, etc.
void pause_event(GtkWidget *widget, ui_state *ui)
pause button event
gchar * get_output_directory(ui_state *ui)
Get the name of the output directory.
GtkWidget * create_choose_preferences(ui_state *ui)
creates the preferences tab
GtkWidget * create_split_files_frame(ui_state *ui)
creates the split files tab
GtkWidget * create_special_split_page(ui_state *ui)
creates the special split page
GtkWidget * create_splitpoints_frame(ui_state *ui)
creates the choose splitpoints frame
gint get_splitpoint_time(gint splitpoint_index, ui_state *ui)
returns a splitpoint from the table
void remove_splitpoint(gint index, gint stop_preview, ui_state *ui)
removes a splitpoint
gint file_exists(const gchar *fname)
check if specified file exists
Definition utilities.c:62
gint directory_exists(const gchar *directory)
check if specified directory exists
Definition utilities.c:44