mp3splt-gtk 0.9.3.1519
Loading...
Searching...
No Matches
splitpoints_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 *
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 * 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 splitpoints tab
35 *
36 * this file is used for the Splitpoints tab
37 * (which in turn contains the splitpoints table)
38 **********************************************************/
39
40#include "splitpoints_window.h"
41#include "ui_types.h"
42
44static gboolean check_if_splitpoint_does_not_exists(gint minutes, gint seconds, gint hundr_secs,
45 gint current_split, ui_state *ui)
46{
47 GtkTreeModel *model = gtk_tree_view_get_model(ui->gui->tree_view);
48
49 GtkTreeIter iter;
50 if (!gtk_tree_model_get_iter_first(model, &iter))
51 {
52 return TRUE;
53 }
54
55 gint tree_minutes;
56 gint tree_seconds;
57 gint tree_hundr_secs;
58
59 while (TRUE)
60 {
61 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter,
62 COL_MINUTES, &tree_minutes,
63 COL_SECONDS, &tree_seconds,
64 COL_HUNDR_SECS, &tree_hundr_secs,
65 -1);
66
67 GtkTreePath *path = gtk_tree_model_get_path(model, &iter);
68 gint i = gtk_tree_path_get_indices (path)[0];
69
70 if ((minutes == tree_minutes) &&
71 (seconds == tree_seconds) &&
72 (hundr_secs == tree_hundr_secs) &&
73 (i != current_split))
74 {
75 gtk_tree_path_free(path);
76 return FALSE;
77 }
78
79 gtk_tree_path_free(path);
80
81 if (!gtk_tree_model_iter_next(model, &iter))
82 {
83 break;
84 }
85 }
86
87 return TRUE;
88}
89
95static void update_add_button(ui_state *ui)
96{
97 gui_status *status = ui->status;
98 if (check_if_splitpoint_does_not_exists(status->spin_mins, status->spin_secs, status->spin_hundr_secs,-1, ui))
99 {
100 gtk_widget_set_sensitive(GTK_WIDGET(ui->gui->add_button), TRUE);
101 }
102 else
103 {
104 gtk_widget_set_sensitive(GTK_WIDGET(ui->gui->add_button), FALSE);
105 }
106}
107
109void update_minutes_from_spinner(GtkWidget *widget, ui_state *ui)
110{
111 ui->status->spin_mins = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(ui->gui->spinner_minutes));
112 update_add_button(ui);
113}
114
116void update_seconds_from_spinner(GtkWidget *widget, ui_state *ui)
117{
118 ui->status->spin_secs = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(ui->gui->spinner_seconds));
119 update_add_button(ui);
120}
121
123void update_hundr_secs_from_spinner(GtkWidget *widget, ui_state *ui)
124{
125 ui->status->spin_hundr_secs = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(ui->gui->spinner_hundr_secs));
126 update_add_button(ui);
127}
128
130static GtkTreeModel *create_model()
131{
132 GtkListStore * model = gtk_list_store_new(NUM_COLUMNS,
133 G_TYPE_BOOLEAN,
134 G_TYPE_STRING,
135 G_TYPE_INT,
136 G_TYPE_INT,
137 G_TYPE_INT,
138 G_TYPE_STRING,
139 G_TYPE_STRING,
140 G_TYPE_STRING,
141 //tags
142 G_TYPE_STRING,
143 G_TYPE_STRING,
144 G_TYPE_STRING,
145 G_TYPE_STRING,
146 G_TYPE_INT,
147 G_TYPE_INT,
148 G_TYPE_STRING);
149
150 return GTK_TREE_MODEL(model);
151}
152
154static void recompute_length_column(ui_state *ui)
155{
156 gint line_mins, line_secs, line_hundr;
157 gint line1_mins, line1_secs, line1_hundr;
158
159 gchar new_length_string[30];
160
161 GtkTreeModel *model = gtk_tree_view_get_model(ui->gui->tree_view);
162
163 gint number = 0;
164 for (number = 0;number < ui->infos->splitnumber; number++)
165 {
166 GtkTreePath *path = gtk_tree_path_new_from_indices(number ,-1);
167 GtkTreeIter iter;
168 gtk_tree_model_get_iter(model, &iter, path);
169
170 if (number != ui->infos->splitnumber-1)
171 {
172 GtkTreePath *path2 = gtk_tree_path_new_from_indices (number+1 ,-1);
173 GtkTreeIter iter2;
174 gtk_tree_model_get_iter(model, &iter2, path2);
175
176 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter,
177 COL_MINUTES, &line_mins,
178 COL_SECONDS, &line_secs,
179 COL_HUNDR_SECS, &line_hundr,
180 -1);
181 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter2,
182 COL_MINUTES, &line1_mins,
183 COL_SECONDS, &line1_secs,
184 COL_HUNDR_SECS, &line1_hundr,
185 -1);
186
187 gint result_secs = 0,result_hundr = 0;
188 gint result_mins = line1_mins - line_mins;
189 if ((result_secs = line1_secs - line_secs) < 0)
190 {
191 result_secs = 60 - line_secs + line1_secs;
192 result_mins--;
193 }
194
195 if ((result_hundr = line1_hundr - line_hundr) < 0)
196 {
197 result_hundr = 100 - line_hundr + line1_hundr;
198 result_secs--;
199 if (result_secs < 0)
200 {
201 result_mins--;
202 result_secs = 0;
203 }
204 }
205
206 g_snprintf(new_length_string, 30, "%d:%02d:%02d", result_mins, result_secs, result_hundr);
207
208 gtk_tree_path_free(path2);
209 }
210 else
211 {
212 g_snprintf(new_length_string, 30, "%s","-");
213 }
214
215 gtk_tree_path_free(path);
216
217 gtk_list_store_set(GTK_LIST_STORE(model), &iter, COL_NUMBER, new_length_string, -1);
218 }
219}
220
228static gboolean check_if_description_exists(gchar *descr, gint number, ui_state *ui)
229{
230 GtkTreeModel *model = gtk_tree_view_get_model(ui->gui->tree_view);
231
232 GtkTreeIter iter;
233 if (!gtk_tree_model_get_iter_first(model, &iter))
234 {
235 return TRUE;
236 }
237
238 gint count = 0;
239 while (TRUE)
240 {
241 gchar *description = NULL;
242 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter,
243 COL_DESCRIPTION, &description,
244 -1);
245
246 if (description != NULL && strcmp(descr, description) == 0 && count != number)
247 {
248 g_free(description);
249 return FALSE;
250 }
251
252 g_free(description);
253
254 if (!gtk_tree_model_iter_next(model, &iter))
255 break;
256
257 count++;
258 }
259
260 return TRUE;
261}
262
265{
266 gint splitpoint_selected = -1;
267
268 GtkTreeModel *model = gtk_tree_view_get_model(gui->tree_view);
269 GtkTreeSelection *selection = gtk_tree_view_get_selection(gui->tree_view);
270
271 GList *selected_list =
272 gtk_tree_selection_get_selected_rows(GTK_TREE_SELECTION(selection), &model);
273
274 if (g_list_length(selected_list) > 0)
275 {
276 GList *current_element = g_list_first(selected_list);
277 GtkTreePath *path = current_element->data;
278 splitpoint_selected = gtk_tree_path_get_indices (path)[0];
279
280 g_list_foreach(selected_list, (GFunc)gtk_tree_path_free, NULL);
281 g_list_free(selected_list);
282 }
283
284 return splitpoint_selected;
285}
286
288static void row_selection_event(GtkTreeSelection *selection, ui_state *ui)
289{
290 gtk_widget_set_sensitive(ui->gui->remove_row_button, TRUE);
291}
292
303static void update_current_description(gchar *descr, gint number, ui_state *ui)
304{
305 gint ll = 0;
306
307 gchar *current_description = ui->status->current_description;
308
309 g_snprintf(current_description, 255, "%s", descr);
310
311 while (ll < ui->infos->splitnumber)
312 {
313 if (check_if_description_exists(current_description, number, ui))
314 {
315 ll++;
316 continue;
317 }
318
319 //we cut the part _* from the string and put it back
320 gchar *tmp = NULL;
321 gchar *t = current_description;
322 while ((t = strstr(t, _("_part"))) != NULL)
323 {
324 tmp = t++;
325 }
326
327 if (tmp != NULL)
328 {
329 *tmp = '\0';
330 }
331
332 gchar *temp = g_strdup(current_description);
333 g_snprintf(current_description, 255, _("%s_part%d"), temp, ll + 2);
334 g_free(temp);
335
336 ll++;
337 }
338}
339
344void get_hundr_secs_mins_time(gint time_pos, gint *time_hundr,
345 gint *time_secs,gint *time_mins)
346{
347 *time_hundr = time_pos % 100;
348 time_pos = time_pos / 100;
349 *time_secs = time_pos % 60;
350 time_pos = time_pos / 60;
351 *time_mins = time_pos;
352}
353
355void select_splitpoint(gint index, gui_state *gui)
356{
357 GtkTreeSelection *selection = gtk_tree_view_get_selection(gui->tree_view);
358 GtkTreeModel *model = gtk_tree_view_get_model(gui->tree_view);
359 GtkTreePath *path = gtk_tree_path_new_from_indices(index ,-1);
360
361 GtkTreeIter iter;
362 gtk_tree_model_get_iter(model, &iter, path);
363 gtk_tree_selection_unselect_all(selection);
364 gtk_tree_selection_select_iter(selection, &iter);
365
366 gtk_tree_path_free(path);
367
369}
370
371static void order_all_splitpoints_from_table(const char *current_description_base,
372 GtkTreeModel *model, ui_state *ui)
373{
374 GtkTreeIter iter;
375 if (!gtk_tree_model_get_iter_first(model, &iter))
376 {
377 return;
378 }
379
380 size_t description_base_length = strlen(current_description_base);
381
382 gint i = 0;
383 gint description_counter = 0;
384 while (i < ui->infos->splitnumber)
385 {
386 gchar *description = NULL;
387 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter,
388 COL_DESCRIPTION, &description,
389 -1);
390
391 size_t length = strlen(description);
392 if (length >= description_base_length)
393 {
394 if (strncmp(description, current_description_base, description_base_length) == 0)
395 {
396 GString *new_description = g_string_new("");
397 g_string_append_printf(new_description, "%s_part%d", current_description_base,
398 i + 1);
399 gchar *new_desc = g_string_free(new_description, FALSE);
400
401 gtk_list_store_set(GTK_LIST_STORE(model),
402 &iter,
403 COL_DESCRIPTION, new_desc,
404 -1);
405
406 g_free(new_desc);
407 description_counter++;
408 }
409 }
410
411 g_free(description);
412
413 gtk_tree_model_iter_next(model, &iter);
414 i++;
415 }
416}
417
422void remove_splitpoint(gint index, gint stop_preview, ui_state *ui)
423{
424 g_array_remove_index(ui->splitpoints, (guint) index);
425
426 GtkTreeModel *model = gtk_tree_view_get_model(ui->gui->tree_view);
427 GtkTreePath *path = gtk_tree_path_new_from_indices (index ,-1);
428
429 GtkTreeIter iter;
430 gtk_tree_model_get_iter(model, &iter, path);
431
432 //cancel preview if necessary
433 if (((index == ui->status->preview_start_splitpoint) && stop_preview) ||
434 ((index == get_quick_preview_end_splitpoint_safe(ui)) &&
435 (get_quick_preview_end_splitpoint_safe(ui) == (ui->infos->splitnumber-1)) && stop_preview))
436 {
438 }
439
440 //if we remove a point at the left of the play preview, move the indexes
441 if (index < ui->status->preview_start_splitpoint)
442 {
443 ui->status->preview_start_splitpoint--;
444 set_quick_preview_end_splitpoint_safe(ui->status->preview_start_splitpoint + 1, ui);
445 }
446
447 gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
448 gtk_tree_path_free(path);
449
450 ui->infos->splitnumber--;
451
452 if (get_first_splitpoint_selected(ui->gui) == -1)
453 {
454 gtk_widget_set_sensitive(ui->gui->remove_row_button, FALSE);
455 }
456
457 if (ui->infos->splitnumber == 0)
458 {
459 gtk_widget_set_sensitive(ui->gui->remove_all_button, FALSE);
460 }
461
462 if (stop_preview)
463 {
464 order_all_splitpoints_from_table(ui->status->current_description, model, ui);
465 }
466
467 recompute_length_column(ui);
468 remove_status_message(ui->gui);
469 update_add_button(ui);
471 refresh_drawing_area(ui->gui, ui->infos);
472
473 export_cue_file_in_configuration_directory(ui);
474}
475
482static void add_splitpoint(Split_point my_split_point, gint old_index, ui_state *ui,
483 gint reorder_names, gchar *old_description)
484{
485 gchar *current_description_base = g_strdup(ui->status->current_description);
486
487 GtkTreeModel *model = gtk_tree_view_get_model(ui->gui->tree_view);
488
489 if (check_if_splitpoint_does_not_exists(my_split_point.mins,
490 my_split_point.secs, my_split_point.hundr_secs,-1, ui))
491 {
492 gint k = 0;
493
494 update_current_description(current_description_base, -1, ui);
495
496 GtkTreeIter iter;
497 if (gtk_tree_model_get_iter_first(model, &iter))
498 {
499 while (k < ui->infos->splitnumber)
500 {
501 gint tree_minutes;
502 gint tree_seconds;
503 gint tree_hundr_secs;
504 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter,
505 COL_MINUTES, &tree_minutes,
506 COL_SECONDS, &tree_seconds,
507 COL_HUNDR_SECS, &tree_hundr_secs,
508 -1);
509
510 if (my_split_point.mins < tree_minutes)
511 {
512 break;
513 }
514 else if (my_split_point.mins == tree_minutes)
515 {
516 if (my_split_point.secs < tree_seconds)
517 {
518 break;
519 }
520 else if (my_split_point.secs == tree_seconds)
521 {
522 if (my_split_point.hundr_secs < tree_hundr_secs)
523 {
524 break;
525 }
526 }
527 }
528
529 gtk_tree_model_iter_next(model, &iter);
530 k++;
531 }
532
533 gtk_list_store_insert(GTK_LIST_STORE(model), &iter,k--);
534 g_array_insert_val(ui->splitpoints, (guint) k + 1, my_split_point);
535 }
536 else
537 {
538 gtk_list_store_append(GTK_LIST_STORE(model), &iter);
539 g_array_append_val(ui->splitpoints, my_split_point);
540 }
541
542 ui->infos->splitnumber++;
543
544 //we keep the selection on the previous splipoint
545 if ((ui->status->first_splitpoint_selected == old_index) &&
546 (old_index != -1))
547 {
548 GtkTreePath *path = gtk_tree_model_get_path(model, &iter);
549 gtk_tree_view_set_cursor(ui->gui->tree_view, path, NULL, FALSE);
550 gtk_tree_path_free(path);
551 }
552
553 if (ui->status->quick_preview)
554 {
555 //if we move the current start preview splitpoint
556 //at the right of the current time, we cancel preview
557 if (old_index == ui->status->preview_start_splitpoint)
558 {
559 if (ui->infos->current_time < get_splitpoint_time(ui->status->preview_start_splitpoint, ui))
560 {
561 cancel_quick_preview(ui->status);
562 }
563 }
564 }
565
566 //we manage the play preview here
567 if (old_index != -1)
568 {
569 //if we have a split preview on going
570 //if we move the point from the left to the right of the
571 //the start preview splitpoint
572 if ((old_index < ui->status->preview_start_splitpoint))
573 {
574 if ((k+1) >= ui->status->preview_start_splitpoint)
575 {
576 ui->status->preview_start_splitpoint--;
577 set_quick_preview_end_splitpoint_safe(ui->status->preview_start_splitpoint + 1, ui);
578 }
579 }
580 else
581 {
582 //if we move from the right of the split preview to his left
583 if ((old_index > ui->status->preview_start_splitpoint))
584 {
585 if ((k+1) <= ui->status->preview_start_splitpoint)
586 {
587 ui->status->preview_start_splitpoint++;
588 set_quick_preview_end_splitpoint_safe(ui->status->preview_start_splitpoint + 1, ui);
589 }
590 }
591 else
592 {
593 //if we move the start splitpoint on the right of the end splitpoint
594 if (old_index == ui->status->preview_start_splitpoint)
595 {
596 if ((k+1) > ui->status->preview_start_splitpoint)
597 {
598 ui->status->preview_start_splitpoint += (k+1) - ui->status->preview_start_splitpoint;
599 set_quick_preview_end_splitpoint_safe(ui->status->preview_start_splitpoint + 1, ui);
600 }
601 else
602 {
603 //if we move the start splitpoint at the left
604 if ((k+1) < ui->status->preview_start_splitpoint)
605 {
606 ui->status->preview_start_splitpoint -= ui->status->preview_start_splitpoint - (k + 1);
607 set_quick_preview_end_splitpoint_safe(ui->status->preview_start_splitpoint + 1, ui);
608 }
609 }
610 }
611 }
612 }
613
614 if (ui->status->preview_start_splitpoint == (ui->infos->splitnumber-1))
615 {
617 }
618 }
619 else
620 {
621 //if we add a splitpoint at the left of the quick
622 //preview start, add 1
623 if ((k+1) <= ui->status->preview_start_splitpoint)
624 {
625 ui->status->preview_start_splitpoint++;
626 set_quick_preview_end_splitpoint_safe(ui->status->preview_start_splitpoint + 1, ui);
627 }
628 }
629
630 //put values in the line
631 //sets text in the minute, second and milisecond column
632 gtk_list_store_set(GTK_LIST_STORE(model),
633 &iter,
634 COL_CHECK, my_split_point.checked,
635 COL_DESCRIPTION, ui->status->current_description,
636 COL_MINUTES, my_split_point.mins,
637 COL_SECONDS, my_split_point.secs,
638 COL_HUNDR_SECS, my_split_point.hundr_secs,
639 -1);
640
641 gtk_widget_set_sensitive(ui->gui->remove_all_button, TRUE);
642
643 recompute_length_column(ui);
644 remove_status_message(ui->gui);
645 }
646 else
647 {
648 put_status_message(_(" error: you already have the splitpoint in table"), ui);
649 }
650
651 if (reorder_names)
652 {
653 if (old_description)
654 {
655 order_all_splitpoints_from_table(old_description, model, ui);
656 }
657 else
658 {
659 order_all_splitpoints_from_table(current_description_base, model, ui);
660 }
661 }
662
663 if (old_description) { g_free(old_description); }
664 if (current_description_base) { g_free(current_description_base); }
665
666 if (gtk_toggle_button_get_active(ui->gui->names_from_filename))
667 {
668 copy_filename_to_current_description(get_input_filename(ui->gui), ui);
669 }
670 else
671 {
672 g_snprintf(ui->status->current_description, 255, "%s", _("description here"));
673 }
674
675 update_add_button(ui);
676 refresh_drawing_area(ui->gui, ui->infos);
678
679 export_cue_file_in_configuration_directory(ui);
680}
681
691void update_splitpoint(gint index, Split_point new_point, ui_state *ui)
692{
693 int splitpoint_does_not_exists =
694 check_if_splitpoint_does_not_exists(new_point.mins, new_point.secs, new_point.hundr_secs,-1, ui);
695
696 Split_point old_point = g_array_index(ui->splitpoints, Split_point, index);
697
698 if (splitpoint_does_not_exists ||
699 (old_point.checked != new_point.checked))
700 {
701 ui->status->lock_cue_export = SPLT_TRUE;
702
703 ui->status->first_splitpoint_selected = get_first_splitpoint_selected(ui->gui);
704
705 gchar *old_description = g_strdup(ui->status->current_description);
706
707 gchar *description = get_splitpoint_name(index, ui);
708 g_snprintf(ui->status->current_description, 255, "%s", description);
709 g_free(description);
710
711 //backup tags
712 GtkTreeModel *model = gtk_tree_view_get_model(ui->gui->tree_view);
713 GtkTreePath *path = gtk_tree_path_new_from_indices(index ,-1);
714 GtkTreeIter iter;
715 gtk_tree_model_get_iter(model, &iter, path);
716
717 gint year = 0, track = 0;
718 gchar *title = NULL, *artist = NULL, *album = NULL, *genre = NULL, *comment = NULL;
719 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter,
720 COL_TITLE, &title,
721 COL_ARTIST, &artist,
722 COL_ALBUM, &album,
723 COL_GENRE, &genre,
724 COL_COMMENT, &comment,
725 COL_YEAR, &year,
726 COL_TRACK, &track,
727 -1);
728
729 remove_splitpoint(index, FALSE, ui);
730 add_splitpoint(new_point, index, ui, TRUE, old_description);
731
732 //restore tags
733 gtk_tree_model_get_iter(model, &iter, path);
734 gtk_tree_path_free(path);
735
736 gtk_list_store_set(GTK_LIST_STORE(model), &iter, COL_TITLE, title, -1);
737 gtk_list_store_set(GTK_LIST_STORE(model), &iter, COL_ARTIST, artist, -1);
738 gtk_list_store_set(GTK_LIST_STORE(model), &iter, COL_ALBUM, album, -1);
739 gtk_list_store_set(GTK_LIST_STORE(model), &iter, COL_GENRE, genre, -1);
740 gtk_list_store_set(GTK_LIST_STORE(model), &iter, COL_COMMENT, comment, -1);
741 gtk_list_store_set(GTK_LIST_STORE(model), &iter, COL_YEAR, year, -1);
742 gtk_list_store_set(GTK_LIST_STORE(model), &iter, COL_TRACK, track, -1);
743 free(title); free(artist); free(album); free(genre); free(comment);
744
745 ui->status->lock_cue_export = SPLT_FALSE;
746
747 export_cue_file_in_configuration_directory(ui);
748 }
749 else
750 {
751 //don't put error if we move the same splitpoint
752 //on the same place
753 if ((new_point.mins == old_point.mins) &&
754 (new_point.secs == old_point.secs) &&
755 (new_point.hundr_secs == old_point.hundr_secs))
756 {
757 }
758 else
759 {
760 put_status_message(_(" error: you already have the splitpoint in table"), ui);
761 }
762 }
763}
764
769void update_splitpoint_from_time(gint index, gdouble time, ui_state *ui)
770{
771 Split_point new_point;
772 get_hundr_secs_mins_time((gint)time, &new_point.hundr_secs, &new_point.secs, &new_point.mins);
773 Split_point old_point = g_array_index(ui->splitpoints, Split_point, index);
774 new_point.checked = old_point.checked;
775
776 update_splitpoint(index, new_point, ui);
777}
778
785{
786 Split_point old_point = g_array_index(ui->splitpoints, Split_point, index);
787 old_point.checked ^= 1;
788 update_splitpoint(index, old_point, ui);
789}
790
791void clear_current_description(ui_state *ui)
792{
793 update_current_description(_("description here"), -1, ui);
794}
795
796void copy_filename_to_current_description(const gchar *fname, ui_state *ui)
797{
798 if (strcmp(fname, "") == 0)
799 {
800 clear_current_description(ui);
801 }
802
803 gchar *temp = g_strdup(g_path_get_basename(fname));
804 gchar *tmp = strrchr(temp,'.');
805 if (tmp != NULL) { *tmp = '\0'; }
806
807 g_snprintf(ui->status->current_description, 255, "%s", temp);
808 g_free(temp);
809}
810
812static void cell_edited_event(GtkCellRendererText *cell, gchar *path_string, gchar *new_text, ui_state *ui)
813{
814 GtkTreePath *path = gtk_tree_path_new_from_string (path_string);
815 GtkTreeModel *model = gtk_tree_view_get_model(ui->gui->tree_view);
816
817 gint col = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(cell), "col"));
818
819 GtkTreeIter iter;
820 gtk_tree_model_get_iter(model, &iter, path);
821 gint i = gtk_tree_path_get_indices (path)[0];
822 Split_point old_point = g_array_index(ui->splitpoints, Split_point, i);
823
824 Split_point new_point;
825 new_point.checked = old_point.checked;
826
827 switch (col)
828 {
829 case COL_DESCRIPTION:
830 update_current_description(new_text, i, ui);
831
832 //put the new content in the list
833 gtk_list_store_set(GTK_LIST_STORE(model), &iter,
834 col, ui->status->current_description,
835 -1);
836
837 if (gtk_toggle_button_get_active(ui->gui->names_from_filename))
838 {
839 copy_filename_to_current_description(get_input_filename(ui->gui), ui);
840 }
841 else
842 {
843 g_snprintf(ui->status->current_description, 255, "%s", _("description here"));
844 }
845 break;
846 //seconds column
847 case COL_SECONDS:
848 new_point.mins = old_point.mins;
849 new_point.secs = atoi(new_text);
850 new_point.hundr_secs = old_point.hundr_secs;
851
852 if (new_point.secs < 0)
853 {
854 new_point.secs = 0;
855 }
856 if (new_point.secs > 59)
857 {
858 new_point.secs = 59;
859 }
860
861 update_splitpoint(i, new_point, ui);
862 break;
863 //minutes column
864 case COL_MINUTES:
865 new_point.mins = atoi(new_text);
866 new_point.secs = old_point.secs;
867 new_point.hundr_secs = old_point.hundr_secs;
868
869 if (new_point.mins < 0)
870 {
871 new_point.mins = 0;
872 }
873 if (new_point.mins > INT_MAX/6000)
874 {
875 new_point.mins = INT_MAX/6000;
876 }
877
878 update_splitpoint(i, new_point, ui);
879 break;
880 //hundreth column
881 case COL_HUNDR_SECS:
882 new_point.mins = old_point.mins;
883 new_point.secs = old_point.secs;
884 new_point.hundr_secs = atoi(new_text);
885
886 if (new_point.hundr_secs < 0)
887 {
888 new_point.hundr_secs = 0;
889 }
890 if (new_point.hundr_secs > 99)
891 {
892 new_point.hundr_secs = 99;
893 }
894
895 update_splitpoint(i, new_point, ui);
896 break;
897 case COL_YEAR:
898 case COL_TRACK:
899 ;
900 gint value = (gint) atoi(new_text);
901 if (value < 0) { value = 0; }
902 gtk_list_store_set(GTK_LIST_STORE(model), &iter, col, value, -1);
903 break;
904 default:
905 gtk_list_store_set(GTK_LIST_STORE(model), &iter, col, new_text, -1);
906 break;
907 }
908
909 gtk_tree_path_free(path);
910
911 export_cue_file_in_configuration_directory(ui);
912}
913
914void add_splitpoint_from_player(GtkWidget *widget, ui_state *ui)
915{
916 if (!ui->status->timer_active)
917 {
918 return;
919 }
920
921 Split_point my_split_point;
922 my_split_point.mins = ui->infos->player_minutes;
923 my_split_point.secs = ui->infos->player_seconds;
924 my_split_point.hundr_secs = ui->infos->player_hundr_secs;
925 my_split_point.checked = TRUE;
926
927 add_splitpoint(my_split_point, -1, ui, TRUE, NULL);
928}
929
931void add_row(gboolean checked, ui_state *ui)
932{
933 gui_status *status = ui->status;
934
935 Split_point my_split_point;
936 my_split_point.mins = status->spin_mins;
937 my_split_point.secs = status->spin_secs;
938 my_split_point.hundr_secs = status->spin_hundr_secs;
939 my_split_point.checked = checked;
940
941 add_splitpoint(my_split_point, -1, ui, FALSE, NULL);
942}
943
944static void add_row_clicked(GtkWidget *button, ui_state *ui)
945{
946 gui_status *status = ui->status;
947
948 Split_point my_split_point;
949 my_split_point.mins = status->spin_mins;
950 my_split_point.secs = status->spin_secs;
951 my_split_point.hundr_secs = status->spin_hundr_secs;
952 my_split_point.checked = TRUE;
953
954 add_splitpoint(my_split_point, -1, ui, TRUE, NULL);
955}
956
957static gboolean detect_silence_and_set_splitpoints_end(ui_with_err *ui_err)
958{
959 gint err = ui_err->err;
960 ui_state *ui = ui_err->ui;
961
962 mp3splt_set_int_option(ui->mp3splt_state, SPLT_OPT_PRETEND_TO_SPLIT, SPLT_FALSE);
963 mp3splt_set_split_filename_function(ui->mp3splt_state, lmanager_put_split_filename, ui);
964
965 if (err >= 0)
966 {
968 }
969
971
972 gtk_widget_set_sensitive(ui->gui->cancel_button, FALSE);
973 gtk_widget_set_sensitive(ui->gui->scan_silence_button, TRUE);
974 gtk_widget_set_sensitive(ui->gui->scan_silence_button_player, TRUE);
975 gtk_widget_set_sensitive(ui->gui->scan_trim_silence_button, TRUE);
976 gtk_widget_set_sensitive(ui->gui->scan_trim_silence_button_player, TRUE);
977
978 set_is_splitting_safe(FALSE, ui);
979
980 set_process_in_progress_and_wait_safe(FALSE, ui);
981
982 g_free(ui_err);
983
984 export_cue_file_in_configuration_directory(ui);
985
986 return FALSE;
987}
988
989
991static gpointer detect_silence_and_set_splitpoints(ui_for_split *ui_fs)
992{
993 ui_state *ui = ui_fs->ui;
994
995 set_process_in_progress_and_wait_safe(TRUE, ui);
996
997 set_is_splitting_safe(TRUE, ui);
998
999 mp3splt_set_float_option(ui->mp3splt_state, SPLT_OPT_PARAM_THRESHOLD, ui_fs->single_silence_threshold);
1000 mp3splt_set_int_option(ui->mp3splt_state, SPLT_OPT_PARAM_SHOTS, ui_fs->single_silence_shots);
1001 mp3splt_set_float_option(ui->mp3splt_state, SPLT_OPT_PARAM_OFFSET, ui_fs->single_silence_offset);
1002 mp3splt_set_int_option(ui->mp3splt_state, SPLT_OPT_PARAM_NUMBER_TRACKS, ui_fs->single_silence_number);
1003 mp3splt_set_float_option(ui->mp3splt_state, SPLT_OPT_PARAM_MIN_LENGTH,
1004 ui_fs->single_silence_minimum_length);
1005 mp3splt_set_float_option(ui->mp3splt_state, SPLT_OPT_PARAM_MIN_TRACK_LENGTH,
1006 ui_fs->single_silence_minimum_track_length);
1007 mp3splt_set_int_option(ui->mp3splt_state, SPLT_OPT_PARAM_REMOVE_SILENCE,
1008 ui_fs->single_silence_remove);
1009
1010 splt_code err = SPLT_OK;
1011 if (ui_fs->is_checked_output_radio_box == 0)
1012 {
1013 err = mp3splt_set_oformat(ui->mp3splt_state, ui_fs->output_format);
1014 }
1015 print_status_bar_confirmation_in_idle(err, ui);
1016
1017 err = mp3splt_erase_all_splitpoints(ui->mp3splt_state);
1018 print_status_bar_confirmation_in_idle(err, ui);
1019
1020 mp3splt_set_int_option(ui->mp3splt_state, SPLT_OPT_PRETEND_TO_SPLIT, SPLT_TRUE);
1021 mp3splt_set_split_filename_function(ui->mp3splt_state, NULL, ui);
1022 mp3splt_set_int_option(ui->mp3splt_state, SPLT_OPT_TAGS, SPLT_TAGS_ORIGINAL_FILE);
1023
1024 err = SPLT_OK;
1025 int old_split_mode = mp3splt_get_int_option(ui->mp3splt_state, SPLT_OPT_SPLIT_MODE, &err);
1026 int old_tags_option = mp3splt_get_int_option(ui->mp3splt_state, SPLT_OPT_TAGS, &err);
1027
1028 if (ui_fs->should_trim)
1029 {
1030 err = mp3splt_set_trim_silence_points(ui->mp3splt_state);
1031 }
1032 else
1033 {
1034 mp3splt_set_silence_points(ui->mp3splt_state, &err);
1035 }
1036 print_status_bar_confirmation_in_idle(err, ui);
1037
1038 mp3splt_set_int_option(ui->mp3splt_state, SPLT_OPT_TAGS, old_tags_option);
1039 mp3splt_set_int_option(ui->mp3splt_state, SPLT_OPT_SPLIT_MODE, old_split_mode);
1040
1041 free_ui_for_split(ui_fs);
1042
1043 ui_with_err *ui_err = g_malloc0(sizeof(ui_with_err));
1044 ui_err->err = err;
1045 ui_err->ui = ui;
1046
1047 add_idle(G_PRIORITY_HIGH_IDLE,
1048 (GSourceFunc)detect_silence_and_set_splitpoints_end, ui_err, NULL);
1049
1050 return NULL;
1051}
1052
1053static void detect_silence_and_set_splitpoints_action(ui_state *ui, gboolean should_trim)
1054{
1055 gtk_widget_set_sensitive(ui->gui->scan_silence_button, FALSE);
1056 gtk_widget_set_sensitive(ui->gui->scan_silence_button_player, FALSE);
1057 gtk_widget_set_sensitive(ui->gui->scan_trim_silence_button, FALSE);
1058 gtk_widget_set_sensitive(ui->gui->scan_trim_silence_button_player, FALSE);
1059 gtk_widget_set_sensitive(ui->gui->cancel_button, TRUE);
1060
1061 ui_for_split *ui_fs = build_ui_for_split(ui);
1062 ui_fs->should_trim = should_trim;
1063
1064 create_thread_and_unref((GThreadFunc)detect_silence_and_set_splitpoints,
1065 (gpointer) ui_fs, ui, "detect_silence");
1066}
1067
1069static void detect_silence_and_add_splitpoints_start_thread(ui_state *ui)
1070{
1071 detect_silence_and_set_splitpoints_action(ui, FALSE);
1072}
1073
1074static void detect_silence_and_add_trim_splitpoints_start_thread(ui_state *ui)
1075{
1076 detect_silence_and_set_splitpoints_action(ui, TRUE);
1077}
1078
1080static void update_silence_parameters(GtkWidget *widget, ui_state *ui)
1081{
1082 ui_infos *infos = ui->infos;
1083 gui_state *gui = ui->gui;
1084
1085 infos->silence_threshold_value = (gfloat)
1086 gtk_spin_button_get_value(GTK_SPIN_BUTTON(gui->spinner_silence_threshold));
1087 if (gui->spinner_silence_shots != NULL)
1088 {
1089 infos->silence_shots_value =
1090 gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(gui->spinner_silence_shots));
1091 }
1092 if (gui->spinner_silence_offset != NULL)
1093 {
1094 infos->silence_offset_value = (gfloat)
1095 gtk_spin_button_get_value(GTK_SPIN_BUTTON(gui->spinner_silence_offset));
1096 }
1097 if (gui->spinner_silence_number_tracks != NULL)
1098 {
1099 infos->silence_number_of_tracks =
1100 gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(gui->spinner_silence_number_tracks));
1101 }
1102 if (gui->spinner_silence_minimum != NULL)
1103 {
1104 infos->silence_minimum_length = (gfloat)
1105 gtk_spin_button_get_value(GTK_SPIN_BUTTON(gui->spinner_silence_minimum));
1106 }
1107 if (gui->spinner_silence_minimum_track != NULL)
1108 {
1109 infos->silence_minimum_track_length = (gfloat)
1110 gtk_spin_button_get_value(GTK_SPIN_BUTTON(gui->spinner_silence_minimum_track));
1111 }
1112 if (gui->silence_remove_silence != NULL)
1113 {
1114 infos->silence_remove_silence_between_tracks =
1115 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gui->silence_remove_silence));
1116 }
1117}
1118
1120static void silence_remove_silence_checked(GtkToggleButton *button, ui_state *ui)
1121{
1122 update_silence_parameters(GTK_WIDGET(button), ui);
1123}
1124
1125void create_trim_silence_window(GtkWidget *button, ui_state *ui)
1126{
1127 GtkWidget *silence_detection_window =
1128 gtk_dialog_new_with_buttons(_("Set trim splitpoints using silence detection"),
1129 GTK_WINDOW(ui->gui->window),
1130 GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
1131 _("_OK"),
1132 GTK_RESPONSE_YES,
1133 _("_Cancel"),
1134 GTK_RESPONSE_CANCEL,
1135 NULL);
1136
1137 gtk_widget_set_size_request(silence_detection_window, 300, 90);
1138
1139 GtkWidget *general_inside_vbox = wh_vbox_new();
1140
1141 GtkWidget *horiz_fake = wh_hbox_new();
1142 gtk_box_pack_start(GTK_BOX(general_inside_vbox), horiz_fake, FALSE, FALSE, 10);
1143
1144 //vertical parameter box
1145 GtkWidget *param_vbox = wh_vbox_new();
1146 gtk_box_pack_start(GTK_BOX(horiz_fake), param_vbox, FALSE, FALSE, 25);
1147
1148 //horizontal box fake for threshold level
1149 horiz_fake = wh_hbox_new();
1150 gtk_box_pack_start(GTK_BOX(param_vbox), horiz_fake, FALSE, FALSE, 0);
1151
1152 //threshold level
1153 GtkWidget *label = gtk_label_new(_("Threshold level (dB):"));
1154 gtk_box_pack_start(GTK_BOX(horiz_fake), label, FALSE, FALSE, 0);
1155
1156 //adjustement for the threshold spinner
1157 GtkAdjustment *adj = gtk_adjustment_new(0.0, -96.0, 0.0, 0.5, 10.0, 0.0);
1158 GtkWidget *spinner_silence_threshold = gtk_spin_button_new(adj, 0.5, 2);
1159 ui->gui->spinner_silence_threshold = spinner_silence_threshold;
1160 gtk_box_pack_start(GTK_BOX(horiz_fake), spinner_silence_threshold, FALSE, FALSE, 6);
1161 gtk_spin_button_set_value(GTK_SPIN_BUTTON(spinner_silence_threshold), ui->infos->silence_threshold_value);
1162 g_signal_connect(G_OBJECT(spinner_silence_threshold), "value_changed",
1163 G_CALLBACK(update_silence_parameters), ui);
1164
1165 gtk_widget_show_all(general_inside_vbox);
1166 gtk_container_add(GTK_CONTAINER(
1167 gtk_dialog_get_content_area(GTK_DIALOG(silence_detection_window))), general_inside_vbox);
1168
1169 gint result = gtk_dialog_run(GTK_DIALOG(silence_detection_window));
1170
1171 gtk_widget_destroy(silence_detection_window);
1172
1173 if (result != GTK_RESPONSE_YES) { return; }
1174
1175 detect_silence_and_add_trim_splitpoints_start_thread(ui);
1176}
1177
1180{
1181 ui_infos *infos = ui->infos;
1182 gui_state *gui = ui->gui;
1183
1184 GtkWidget *silence_detection_window =
1185 gtk_dialog_new_with_buttons(_("Set splitpoints from silence detection"),
1186 GTK_WINDOW(gui->window),
1187 GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
1188 _("_OK"),
1189 GTK_RESPONSE_YES,
1190 _("_Cancel"),
1191 GTK_RESPONSE_CANCEL,
1192 NULL);
1193
1194 GtkWidget *general_inside_vbox = wh_vbox_new();
1195 GtkWidget *horiz_fake = wh_hbox_new();
1196 gtk_box_pack_start(GTK_BOX(general_inside_vbox), horiz_fake, FALSE, FALSE, 10);
1197
1198 //vertical parameter box
1199 GtkWidget *param_vbox = wh_vbox_new();
1200 gtk_box_pack_start(GTK_BOX(horiz_fake), param_vbox, FALSE, FALSE, 25);
1201
1202 //horizontal box fake for threshold level
1203 horiz_fake = wh_hbox_new();
1204 gtk_box_pack_start(GTK_BOX(param_vbox), horiz_fake, FALSE, FALSE, 0);
1205
1206 //threshold level
1207 GtkWidget *label = gtk_label_new(_("Threshold level (dB):"));
1208 gtk_box_pack_start(GTK_BOX(horiz_fake), label, FALSE, FALSE, 0);
1209
1210 //adjustement for the threshold spinner
1211 GtkAdjustment *adj = gtk_adjustment_new(0.0, -96.0, 0.0, 0.5, 10.0, 0.0);
1212 GtkWidget *spinner_silence_threshold = gtk_spin_button_new(adj, 0.5, 2);
1213 gui->spinner_silence_threshold = spinner_silence_threshold;
1214 gtk_box_pack_start(GTK_BOX(horiz_fake), spinner_silence_threshold, FALSE, FALSE, 6);
1215
1216 //horizontal box fake for the shots
1217 horiz_fake = wh_hbox_new();
1218 gtk_box_pack_start(GTK_BOX(param_vbox), horiz_fake, FALSE, FALSE, 0);
1219 //shots
1220 label = gtk_label_new(_("Shots as non silence after silence:"));
1221 gtk_box_pack_start(GTK_BOX(horiz_fake), label, FALSE, FALSE, 0);
1222 //adjustement for the threshold spinner
1223 adj = gtk_adjustment_new(25.0, 0.0, 500.0, 1.0, 10.0, 0.0);
1224 GtkWidget *spinner_silence_shots = gtk_spin_button_new(adj, 1.0, 0);
1225 gui->spinner_silence_shots = spinner_silence_shots;
1226 gtk_box_pack_start(GTK_BOX(horiz_fake), spinner_silence_shots, FALSE, FALSE, 6);
1227
1228 //horizontal box fake for the offset level
1229 horiz_fake = wh_hbox_new();
1230 gtk_box_pack_start(GTK_BOX(param_vbox), horiz_fake, FALSE, FALSE, 0);
1231 //offset level
1232 label = gtk_label_new(_("Cutpoint offset (0 is the begin of silence,"
1233 "and 1 the end):"));
1234 gtk_box_pack_start(GTK_BOX(horiz_fake), label, FALSE, FALSE, 0);
1235 //adjustement for the offset spinner
1236 adj = gtk_adjustment_new(0.0, -2, 2, 0.05, 10.0, 0.0);
1237 GtkWidget *spinner_silence_offset = gtk_spin_button_new(adj, 0.05, 2);
1238 gui->spinner_silence_offset = spinner_silence_offset;
1239 gtk_box_pack_start(GTK_BOX(horiz_fake), spinner_silence_offset, FALSE, FALSE, 6);
1240
1241 //number of tracks
1242 horiz_fake = wh_hbox_new();
1243 gtk_box_pack_start(GTK_BOX(param_vbox), horiz_fake, FALSE, FALSE, 0);
1244
1245 label = gtk_label_new(_("Number of tracks (0 means all tracks):"));
1246 gtk_box_pack_start(GTK_BOX(horiz_fake), label, FALSE, FALSE, 0);
1247
1248 adj = gtk_adjustment_new(0.0, 0, INT_MAX/6000, 1, 10.0, 0.0);
1249 GtkWidget *spinner_silence_number_tracks = gtk_spin_button_new(adj, 1, 0);
1250 gui->spinner_silence_number_tracks = spinner_silence_number_tracks;
1251 gtk_box_pack_start(GTK_BOX(horiz_fake), spinner_silence_number_tracks, FALSE, FALSE, 6);
1252
1253 //minimum length
1254 horiz_fake = wh_hbox_new();
1255 gtk_box_pack_start(GTK_BOX(param_vbox), horiz_fake, FALSE, FALSE, 0);
1256
1257 label = gtk_label_new(_("Minimum silence length (seconds):"));
1258 gtk_box_pack_start(GTK_BOX(horiz_fake), label, FALSE, FALSE, 0);
1259
1260 adj = gtk_adjustment_new(0.0, 0, INT_MAX/6000, 0.5, 10.0, 0.0);
1261 GtkWidget *spinner_silence_minimum = gtk_spin_button_new(adj, 1, 2);
1262 gui->spinner_silence_minimum = spinner_silence_minimum;
1263 gtk_box_pack_start(GTK_BOX(horiz_fake), spinner_silence_minimum, FALSE, FALSE, 6);
1264
1265 //the minimum track length parameter
1266 horiz_fake = wh_hbox_new();
1267 gtk_box_pack_start(GTK_BOX(param_vbox), horiz_fake, FALSE, FALSE, 0);
1268
1269 label = gtk_label_new(_("Minimum track length (seconds):"));
1270 gtk_box_pack_start(GTK_BOX(horiz_fake), label, FALSE, FALSE, 0);
1271
1272 adj = gtk_adjustment_new(0.0, 0, INT_MAX/6000, 0.5, 10.0, 0.0);
1273 GtkWidget *spinner_silence_minimum_track = gtk_spin_button_new(adj, 1, 2);
1274 gui->spinner_silence_minimum_track = spinner_silence_minimum_track;
1275 gtk_box_pack_start(GTK_BOX(horiz_fake), spinner_silence_minimum_track, FALSE, FALSE, 6);
1276
1277 //remove silence (rm): allows you to remove the silence between
1278 //tracks
1279 GtkWidget *silence_remove_silence = gtk_check_button_new_with_mnemonic(_("_Remove silence between tracks"));
1280 gui->silence_remove_silence = silence_remove_silence;
1281 gtk_box_pack_start(GTK_BOX(param_vbox), silence_remove_silence, FALSE, FALSE, 0);
1282
1283 //we set the default parameters for the silence split
1284 gtk_spin_button_set_value(GTK_SPIN_BUTTON(spinner_silence_threshold),
1285 infos->silence_threshold_value);
1286 gtk_spin_button_set_value(GTK_SPIN_BUTTON(spinner_silence_shots),
1287 infos->silence_shots_value);
1288 gtk_spin_button_set_value(GTK_SPIN_BUTTON(spinner_silence_offset),
1289 infos->silence_offset_value);
1290 gtk_spin_button_set_value(GTK_SPIN_BUTTON(spinner_silence_number_tracks),
1291 infos->silence_number_of_tracks);
1292 gtk_spin_button_set_value(GTK_SPIN_BUTTON(spinner_silence_minimum),
1293 infos->silence_minimum_length);
1294 gtk_spin_button_set_value(GTK_SPIN_BUTTON(spinner_silence_minimum_track),
1295 infos->silence_minimum_track_length);
1296 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(silence_remove_silence),
1297 infos->silence_remove_silence_between_tracks);
1298
1299 //add actions when changing the values
1300 g_signal_connect(G_OBJECT(spinner_silence_threshold), "value_changed",
1301 G_CALLBACK(update_silence_parameters), ui);
1302 g_signal_connect(G_OBJECT(spinner_silence_shots), "value_changed",
1303 G_CALLBACK(update_silence_parameters), ui);
1304 g_signal_connect(G_OBJECT(spinner_silence_offset), "value_changed",
1305 G_CALLBACK(update_silence_parameters), ui);
1306 g_signal_connect(G_OBJECT(spinner_silence_number_tracks), "value_changed",
1307 G_CALLBACK(update_silence_parameters), ui);
1308 g_signal_connect(G_OBJECT(spinner_silence_minimum), "value_changed",
1309 G_CALLBACK(update_silence_parameters), ui);
1310 g_signal_connect(G_OBJECT(spinner_silence_minimum_track), "value_changed",
1311 G_CALLBACK(update_silence_parameters), ui);
1312 g_signal_connect(G_OBJECT(silence_remove_silence), "toggled",
1313 G_CALLBACK(silence_remove_silence_checked), ui);
1314
1315 gtk_widget_show_all(general_inside_vbox);
1316 gtk_container_add(GTK_CONTAINER(
1317 gtk_dialog_get_content_area(GTK_DIALOG(silence_detection_window))),
1318 general_inside_vbox);
1319
1320 gint result = gtk_dialog_run(GTK_DIALOG(silence_detection_window));
1321
1322 gtk_widget_destroy(silence_detection_window);
1323
1324 if (result != GTK_RESPONSE_YES) { return; }
1325
1326 detect_silence_and_add_splitpoints_start_thread(ui);
1327}
1328
1330static void remove_row(GtkWidget *widget, ui_state *ui)
1331{
1332 GtkTreeModel *model = gtk_tree_view_get_model(ui->gui->tree_view);
1333 GtkTreeSelection *selection = gtk_tree_view_get_selection(ui->gui->tree_view);
1334
1335 GList *selected_list = gtk_tree_selection_get_selected_rows(selection, &model);
1336
1337 while ((g_list_length(selected_list) > 0) && (ui->infos->splitnumber > 0))
1338 {
1339 GList *current_element = g_list_last(selected_list);
1340 GtkTreePath *path = current_element->data;
1341 gint i = gtk_tree_path_get_indices (path)[0];
1342
1343 remove_splitpoint(i, TRUE, ui);
1344
1345 selected_list = g_list_remove(selected_list, path);
1346
1347 gtk_tree_path_free(path);
1348 }
1349
1350 g_list_foreach(selected_list, (GFunc)gtk_tree_path_free, NULL);
1351 g_list_free(selected_list);
1352}
1353
1355void remove_all_rows(GtkWidget *widget, ui_state *ui)
1356{
1357 GtkTreeModel *model = gtk_tree_view_get_model(ui->gui->tree_view);
1358
1359 while (ui->infos->splitnumber > 0)
1360 {
1361 GtkTreeIter iter;
1362 gtk_tree_model_get_iter_first(model, &iter);
1363 gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
1364 g_array_remove_index(ui->splitpoints, ((guint) ui->infos->splitnumber - 1));
1365 ui->infos->splitnumber--;
1366 }
1367
1368 gtk_widget_set_sensitive(ui->gui->remove_all_button, FALSE);
1369 gtk_widget_set_sensitive(ui->gui->remove_row_button, FALSE);
1370
1371 remove_status_message(ui->gui);
1373 update_add_button(ui);
1374 refresh_drawing_area(ui->gui, ui->infos);
1376
1377 export_cue_file_in_configuration_directory(ui);
1378}
1379
1381static GtkWidget *create_init_spinner(GtkWidget *bottomhbox1, gint min, gint max,
1382 gchar *label_text, gint type, ui_state *ui)
1383{
1384 GtkWidget *spinner_box = wh_vbox_new();
1385 GtkWidget *label = gtk_label_new(label_text);
1386 gtk_box_pack_start(GTK_BOX(spinner_box), label, TRUE, FALSE, 0);
1387
1388 GtkAdjustment *adj = gtk_adjustment_new(0.0, min, max, 1.0, 10.0, 0.0);
1389 GtkWidget *spinner = gtk_spin_button_new(adj, 0, 0);
1390 gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(spinner), TRUE);
1391
1392 if (type == 0)
1393 {
1394 g_signal_connect(G_OBJECT(spinner), "value_changed",
1395 G_CALLBACK(update_minutes_from_spinner), ui);
1396 }
1397 else if (type == 1)
1398 {
1399 g_signal_connect(G_OBJECT(spinner), "value_changed",
1400 G_CALLBACK(update_seconds_from_spinner), ui);
1401 }
1402 else
1403 {
1404 g_signal_connect(G_OBJECT(spinner), "value_changed",
1405 G_CALLBACK(update_hundr_secs_from_spinner), ui);
1406 }
1407
1408 gtk_box_pack_start(GTK_BOX(spinner_box), spinner, TRUE, FALSE, 0);
1409 gtk_box_pack_start(GTK_BOX(bottomhbox1), spinner_box, FALSE, FALSE, 5);
1410
1411 return spinner;
1412}
1413
1415static GtkWidget *create_init_spinners_buttons(ui_state *ui)
1416{
1417 GtkWidget *hbox = wh_hbox_new();
1418 gtk_container_set_border_width(GTK_CONTAINER(hbox), 0);
1419
1420 //0 means spinner minutes
1421 ui->gui->spinner_minutes = create_init_spinner(hbox, 0, INT_MAX/6000, _("Minutes:"), 0, ui);
1422 //1 means spinner seconds
1423 ui->gui->spinner_seconds = create_init_spinner(hbox, 0, 59, _("Seconds:"), 1, ui);
1424 //2 means spinner hundredth
1425 ui->gui->spinner_hundr_secs = create_init_spinner(hbox, 0, 99, _("Hundredths:"), 2, ui);
1426
1427 /* add button */
1428 GtkWidget *add_button = wh_create_cool_button("list-add", _("_Add"), FALSE);
1429 ui->gui->add_button = add_button;
1430
1431 gtk_button_set_relief(GTK_BUTTON(add_button), GTK_RELIEF_NONE);
1432 gtk_widget_set_sensitive(add_button, TRUE);
1433 g_signal_connect(G_OBJECT(add_button), "clicked", G_CALLBACK(add_row_clicked), ui);
1434 gtk_box_pack_start(GTK_BOX(hbox), add_button, FALSE, FALSE, 5);
1435 gtk_widget_set_tooltip_text(add_button,_("Add splitpoint"));
1436
1437 /* remove row button */
1438 GtkWidget *remove_row_button = wh_create_cool_button("list-remove", _("_Remove"), FALSE);
1439 ui->gui->remove_row_button = remove_row_button;
1440
1441 gtk_button_set_relief(GTK_BUTTON(remove_row_button), GTK_RELIEF_NONE);
1442 gtk_widget_set_sensitive(remove_row_button, FALSE);
1443 g_signal_connect(G_OBJECT(remove_row_button), "clicked", G_CALLBACK(remove_row), ui);
1444 gtk_box_pack_start(GTK_BOX(hbox), remove_row_button, FALSE, FALSE, 5);
1445 gtk_widget_set_tooltip_text(remove_row_button, _("Remove selected splitpoints"));
1446
1447 /* remove all rows button */
1448 GtkWidget *remove_all_button = wh_create_cool_button("edit-clear", _("R_emove all"), FALSE);
1449 ui->gui->remove_all_button = remove_all_button;
1450
1451 gtk_button_set_relief(GTK_BUTTON(remove_all_button), GTK_RELIEF_NONE);
1452 gtk_widget_set_sensitive(remove_all_button, FALSE);
1453 g_signal_connect(G_OBJECT(remove_all_button), "clicked", G_CALLBACK(remove_all_rows), ui);
1454 gtk_box_pack_start(GTK_BOX(hbox), remove_all_button, FALSE, FALSE, 5);
1455 gtk_widget_set_tooltip_text(remove_all_button, _("Remove all splitpoints"));
1456
1457 return hbox;
1458}
1459
1461static void create_init_special_buttons(ui_state *ui)
1462{
1463 /* set splitpoints from trim silence detection */
1464 GtkWidget *scan_trim_silence_button =
1465 wh_create_cool_button("edit-find", _("_Trim splitpoints"), FALSE);
1466 ui->gui->scan_trim_silence_button = scan_trim_silence_button;
1467 gtk_widget_set_sensitive(scan_trim_silence_button, TRUE);
1468 g_signal_connect(G_OBJECT(scan_trim_silence_button), "clicked",
1469 G_CALLBACK(create_trim_silence_window), ui);
1470 gtk_widget_set_tooltip_text(scan_trim_silence_button,
1471 _("Set trim splitpoints using silence detection"));
1472
1473 /* set splitpoints from silence detection */
1474 GtkWidget *scan_silence_button =
1475 wh_create_cool_button("edit-find-replace", _("_Silence detection"), FALSE);
1476 ui->gui->scan_silence_button = scan_silence_button;
1477 gtk_widget_set_sensitive(scan_silence_button, TRUE);
1478 g_signal_connect(G_OBJECT(scan_silence_button), "clicked",
1480 gtk_widget_set_tooltip_text(scan_silence_button,
1481 _("Set splitpoints from silence detection"));
1482}
1483
1488gchar *get_splitpoint_name(gint index, ui_state *ui)
1489{
1490 GtkTreeModel *model = gtk_tree_view_get_model(ui->gui->tree_view);
1491
1492 gchar *description = NULL;
1493
1494 GtkTreeIter iter;
1495 if (!gtk_tree_model_get_iter_first(model, &iter))
1496 {
1497 return NULL;
1498 }
1499
1500 if (index == -1)
1501 {
1502 index = 0;
1503 }
1504
1505 if (index >= 0)
1506 {
1507 GtkTreePath *path = gtk_tree_path_new_from_indices(index ,-1);
1508 gtk_tree_model_get_iter(model, &iter, path);
1509 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter,
1510 COL_DESCRIPTION, &description,
1511 -1);
1512 gtk_tree_path_free(path);
1513 }
1514
1515 return description;
1516}
1517
1519gint get_splitpoint_time(gint splitpoint_index, ui_state *ui)
1520{
1521 if (splitpoint_index < 0 ||
1522 splitpoint_index >= ui->splitpoints->len)
1523 {
1524 return -1;
1525 }
1526
1527 Split_point point = g_array_index(ui->splitpoints, Split_point, splitpoint_index);
1528 return point.mins * 6000 + point.secs * 100 + point.hundr_secs;
1529}
1530
1531static gboolean split_preview_end(ui_with_err *ui_err)
1532{
1533 set_process_in_progress_and_wait_safe(FALSE, ui_err->ui);
1534
1535 gint err = ui_err->err;
1536 ui_state *ui = ui_err->ui;
1537
1539
1540 gchar *split_file = get_filename_from_split_files(1, ui->gui);
1541 if (split_file != NULL && err > 0)
1542 {
1543 connect_button_event(ui->gui->connect_button, ui);
1544
1545 change_current_filename(split_file, ui);
1546 g_free(split_file);
1547
1548 //0 means start playing
1550 }
1551
1552 if (err > 0)
1553 {
1554 gtk_progress_bar_set_fraction(ui->gui->percent_progress_bar, 1.0);
1555 gtk_progress_bar_set_text(ui->gui->percent_progress_bar, _(" finished"));
1556 }
1557
1558 g_free(ui_err);
1559
1560 return FALSE;
1561}
1562
1563static gpointer split_preview(ui_for_split *ui_fs)
1564{
1565 ui_state *ui = ui_fs->ui;
1566
1567 set_process_in_progress_and_wait_safe(TRUE, ui);
1568
1569 int err = mp3splt_erase_all_splitpoints(ui->mp3splt_state);
1570 print_status_bar_confirmation_in_idle(err, ui);
1571
1572 err = mp3splt_erase_all_tags(ui->mp3splt_state);
1573 print_status_bar_confirmation_in_idle(err, ui);
1574
1575 splt_point *splitpoint = mp3splt_point_new(get_preview_start_position_safe(ui), NULL);
1576 mp3splt_point_set_name(splitpoint, "preview");
1577 mp3splt_point_set_type(splitpoint, SPLT_SPLITPOINT);
1578 mp3splt_append_splitpoint(ui->mp3splt_state, splitpoint);
1579
1580 splitpoint = mp3splt_point_new(
1581 get_splitpoint_time(get_quick_preview_end_splitpoint_safe(ui), ui), NULL);
1582 mp3splt_point_set_type(splitpoint, SPLT_SKIPPOINT);
1583 mp3splt_append_splitpoint(ui->mp3splt_state, splitpoint);
1584
1585 mp3splt_set_int_option(ui->mp3splt_state, SPLT_OPT_OUTPUT_FILENAMES, SPLT_OUTPUT_CUSTOM);
1586 mp3splt_set_int_option(ui->mp3splt_state, SPLT_OPT_SPLIT_MODE, SPLT_OPTION_NORMAL_MODE);
1587
1589
1590 gchar *fname_path = get_preferences_filename();
1591 fname_path[strlen(fname_path) - 18] = '\0';
1592 mp3splt_set_path_of_split(ui->mp3splt_state, fname_path);
1593 if (fname_path) { g_free(fname_path); }
1594
1595 err = mp3splt_split(ui->mp3splt_state);
1596
1597 free_ui_for_split(ui_fs);
1598
1599 ui_with_err *ui_err = g_malloc0(sizeof(ui_with_err));
1600 ui_err->err = err;
1601 ui_err->ui = ui;
1602
1603 add_idle(G_PRIORITY_HIGH_IDLE, (GSourceFunc)split_preview_end, ui_err, NULL);
1604
1605 return NULL;
1606}
1607
1608static void split_preview_action(ui_state *ui)
1609{
1610 ui_for_split *ui_fs = build_ui_for_split(ui);
1611
1613
1614 create_thread_and_unref((GThreadFunc)split_preview, (gpointer) ui_fs, ui, "split_preview");
1615}
1616
1618static void preview_song(GtkTreeView *tree_view, GtkTreePath *path,
1619 GtkTreeViewColumn *col, ui_state *ui)
1620{
1621 gint number = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(col), "col"));
1622 if (number != COL_PREVIEW && number != COL_SPLIT_PREVIEW)
1623 {
1624 return;
1625 }
1626
1627 if (!ui->status->timer_active)
1628 {
1629 put_status_message(_(" cannot preview, not connected to player"), ui);
1630 return;
1631 }
1632
1633 //get the split begin position to find the end position
1634 gint preview_row = gtk_tree_path_get_indices(path)[0];
1635 ui->status->preview_row = preview_row;
1636 if (number == COL_PREVIEW)
1637 {
1638 player_quick_preview(preview_row, ui);
1639 }
1640 else if (number == COL_SPLIT_PREVIEW)
1641 {
1642 set_preview_start_position_safe(get_splitpoint_time(preview_row, ui), ui);
1643 set_quick_preview_end_splitpoint_safe(preview_row + 1, ui);
1644
1645 if (ui->status->preview_row + 1 == ui->infos->splitnumber)
1646 {
1647 put_status_message(_(" cannot split preview last splitpoint"), ui);
1648 return;
1649 }
1650
1651 split_preview_action(ui);
1652 }
1653}
1654
1656static void toggled_splitpoint_event(GtkCellRendererToggle *cell,
1657 gchar *path_str, ui_state *ui)
1658{
1659 GtkTreeModel *model = gtk_tree_view_get_model(ui->gui->tree_view);
1660 GtkTreePath *path = gtk_tree_path_new_from_string(path_str);
1661 gboolean checked = FALSE;
1662
1663 GtkTreeIter iter;
1664 gtk_tree_model_get_iter(model, &iter, path);
1665 gtk_tree_model_get(model, &iter, COL_CHECK, &checked, -1);
1666
1667 //toggle the value
1668 checked ^= 1;
1669
1670 //get the indice
1671 gint index = gtk_tree_path_get_indices (path)[0];
1672 Split_point new_point;
1673 Split_point old_point;
1674
1675 //put new 'checked' value to splitpoint
1676 old_point = g_array_index(ui->splitpoints, Split_point, index);
1677 new_point.mins = old_point.mins;
1678 new_point.secs = old_point.secs;
1679 new_point.hundr_secs = old_point.hundr_secs;
1680 new_point.checked = checked;
1681
1682 update_splitpoint(index, new_point, ui);
1683
1684 gtk_tree_path_free(path);
1685}
1686
1687static void clone_tag(ui_state *ui, gint column)
1688{
1689 gui_state *gui = ui->gui;
1690
1691 GtkTreeModel *model = gtk_tree_view_get_model(gui->tree_view);
1692 GtkTreeSelection *selection = gtk_tree_view_get_selection(gui->tree_view);
1693
1694 GList *selected_list =
1695 gtk_tree_selection_get_selected_rows(GTK_TREE_SELECTION(selection), &model);
1696
1697 if (g_list_length(selected_list) <= 0)
1698 {
1699 return;
1700 }
1701
1702 GList *current_element = g_list_first(selected_list);
1703 GtkTreePath *path = current_element->data;
1704 GtkTreeIter iter;
1705 gtk_tree_model_get_iter(model, &iter, path);
1706
1707 gchar *value = NULL;
1708 gint int_value = 0;
1709 if (column == COL_YEAR || column == COL_TRACK)
1710 {
1711 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, column, &int_value, -1);
1712 }
1713 else
1714 {
1715 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, column, &value, -1);
1716 }
1717
1718 gint number = 0;
1719 for (number = 0;number < ui->infos->splitnumber; number++)
1720 {
1721 GtkTreePath *path2 = gtk_tree_path_new_from_indices(number ,-1);
1722 GtkTreeIter iter2;
1723 gtk_tree_model_get_iter(model, &iter2, path2);
1724 gtk_tree_path_free(path2);
1725
1726 if (column == COL_YEAR || column == COL_TRACK)
1727 {
1728 gtk_list_store_set(GTK_LIST_STORE(model), &iter2, column, int_value, -1);
1729 }
1730 else
1731 {
1732 gtk_list_store_set(GTK_LIST_STORE(model), &iter2, column, value, -1);
1733 }
1734 }
1735
1736 if (value) { g_free(value); }
1737
1738 g_list_foreach(selected_list, (GFunc)gtk_tree_path_free, NULL);
1739 g_list_free(selected_list);
1740}
1741
1742static void clone_all_event(GtkMenuItem *menuitem, ui_state *ui)
1743{
1744 clone_tag(ui, COL_TITLE);
1745 clone_tag(ui, COL_ARTIST);
1746 clone_tag(ui, COL_ALBUM);
1747 clone_tag(ui, COL_GENRE);
1748 clone_tag(ui, COL_YEAR);
1749 clone_tag(ui, COL_TRACK);
1750 clone_tag(ui, COL_COMMENT);
1751
1752 export_cue_file_in_configuration_directory(ui);
1753}
1754
1755static void clone_title_event(GtkMenuItem *menuitem, ui_state *ui)
1756{
1757 clone_tag(ui, COL_TITLE);
1758 export_cue_file_in_configuration_directory(ui);
1759}
1760
1761static void clone_artist_event(GtkMenuItem *menuitem, ui_state *ui)
1762{
1763 clone_tag(ui, COL_ARTIST);
1764 export_cue_file_in_configuration_directory(ui);
1765}
1766
1767static void clone_album_event(GtkMenuItem *menuitem, ui_state *ui)
1768{
1769 clone_tag(ui, COL_ALBUM);
1770 export_cue_file_in_configuration_directory(ui);
1771}
1772
1773static void clone_genre_event(GtkMenuItem *menuitem, ui_state *ui)
1774{
1775 clone_tag(ui, COL_GENRE);
1776 export_cue_file_in_configuration_directory(ui);
1777}
1778
1779static void clone_year_event(GtkMenuItem *menuitem, ui_state *ui)
1780{
1781 clone_tag(ui, COL_YEAR);
1782 export_cue_file_in_configuration_directory(ui);
1783}
1784
1785static void clone_track_event(GtkMenuItem *menuitem, ui_state *ui)
1786{
1787 clone_tag(ui, COL_TRACK);
1788 export_cue_file_in_configuration_directory(ui);
1789}
1790
1791static void clone_comment_event(GtkMenuItem *menuitem, ui_state *ui)
1792{
1793 clone_tag(ui, COL_COMMENT);
1794 export_cue_file_in_configuration_directory(ui);
1795}
1796
1797static void auto_increment_track_event(GtkMenuItem *menuitem, ui_state *ui)
1798{
1799 GtkTreeModel *model = gtk_tree_view_get_model(ui->gui->tree_view);
1800
1801 gint number = 0;
1802 for (number = 0;number < ui->infos->splitnumber; number++)
1803 {
1804 GtkTreePath *path2 = gtk_tree_path_new_from_indices(number ,-1);
1805 GtkTreeIter iter2;
1806 gtk_tree_model_get_iter(model, &iter2, path2);
1807 gtk_tree_path_free(path2);
1808 gtk_list_store_set(GTK_LIST_STORE(model), &iter2, COL_TRACK, GINT_TO_POINTER(number + 1), -1);
1809 }
1810
1811 export_cue_file_in_configuration_directory(ui);
1812}
1813
1814static void build_and_show_popup_menu(GtkWidget *treeview, GdkEventButton *event, ui_state *ui)
1815{
1816 GtkWidget *menu = gtk_menu_new();
1817
1818 GtkWidget *item = gtk_menu_item_new_with_label(_("Clone all tags"));
1819 g_signal_connect(item, "activate", G_CALLBACK(clone_all_event), ui);
1820 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
1821
1822 gtk_menu_shell_append(GTK_MENU_SHELL(menu), gtk_separator_menu_item_new());
1823
1824 item = gtk_menu_item_new_with_label(_("Clone title"));
1825 g_signal_connect(item, "activate", G_CALLBACK(clone_title_event), ui);
1826 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
1827
1828 item = gtk_menu_item_new_with_label(_("Clone artist"));
1829 g_signal_connect(item, "activate", G_CALLBACK(clone_artist_event), ui);
1830 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
1831
1832 item = gtk_menu_item_new_with_label(_("Clone album"));
1833 g_signal_connect(item, "activate", G_CALLBACK(clone_album_event), ui);
1834 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
1835
1836 item = gtk_menu_item_new_with_label(_("Clone genre"));
1837 g_signal_connect(item, "activate", G_CALLBACK(clone_genre_event), ui);
1838 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
1839
1840 item = gtk_menu_item_new_with_label(_("Clone year"));
1841 g_signal_connect(item, "activate", G_CALLBACK(clone_year_event), ui);
1842 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
1843
1844 item = gtk_menu_item_new_with_label(_("Clone track"));
1845 g_signal_connect(item, "activate", G_CALLBACK(clone_track_event), ui);
1846 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
1847
1848 item = gtk_menu_item_new_with_label(_("Clone comment"));
1849 g_signal_connect(item, "activate", G_CALLBACK(clone_comment_event), ui);
1850 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
1851
1852 gtk_menu_shell_append(GTK_MENU_SHELL(menu), gtk_separator_menu_item_new());
1853
1854 item = gtk_menu_item_new_with_label(_("Auto-increment track"));
1855 g_signal_connect(item, "activate", G_CALLBACK(auto_increment_track_event), ui);
1856 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
1857
1858 gtk_widget_show_all(menu);
1859
1860 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
1861 (event != NULL) ? event->button : 0, gdk_event_get_time((GdkEvent*)event));
1862}
1863
1864static gboolean show_popup(GtkWidget *treeview, ui_state *ui)
1865{
1866 build_and_show_popup_menu(treeview, NULL, ui);
1867 return TRUE;
1868}
1869
1870static gboolean select_and_show_popup(GtkWidget *treeview, GdkEventButton *event, ui_state *ui)
1871{
1872 if (event->type != GDK_BUTTON_PRESS || event->button != 3)
1873 {
1874 return FALSE;
1875 }
1876
1877 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
1878 if (gtk_tree_selection_count_selected_rows(selection) <= 1)
1879 {
1880 GtkTreePath *path;
1881 if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(treeview),
1882 (gint) event->x, (gint) event->y, &path, NULL, NULL, NULL))
1883 {
1884 gtk_tree_selection_unselect_all(selection);
1885 gtk_tree_selection_select_path(selection, path);
1886 gtk_tree_path_free(path);
1887 }
1888 else
1889 {
1890 return FALSE;
1891 }
1892 }
1893
1894 build_and_show_popup_menu(treeview, event, ui);
1895
1896 return TRUE;
1897}
1898
1900static void create_columns(ui_state *ui)
1901{
1902 gui_state *gui = ui->gui;
1903
1904 GtkTreeView *tree_view = gui->tree_view;
1905
1906 GtkCellRendererText *renderer;
1907 GtkCellRendererPixbuf *renderer_pix;
1908 GtkCellRendererToggle *renderer_toggle;
1909
1910 GtkTreeViewColumn *column_number;
1911 GtkTreeViewColumn *column_check = NULL;
1912 GtkTreeViewColumn *column_description;
1913 GtkTreeViewColumn *column_hundr_secs;
1914 GtkTreeViewColumn *column_minutes;
1915 GtkTreeViewColumn *column_seconds;
1916 GtkTreeViewColumn *column_preview;
1917 GtkTreeViewColumn *column_split_preview;
1918
1919 /* Check point / skip point */
1920 renderer_toggle = GTK_CELL_RENDERER_TOGGLE(gtk_cell_renderer_toggle_new());
1921 g_signal_connect(renderer_toggle, "toggled", G_CALLBACK(toggled_splitpoint_event), ui);
1922 g_object_set_data(G_OBJECT(renderer_toggle), "col", GINT_TO_POINTER(COL_CHECK));
1923 column_check = gtk_tree_view_column_new_with_attributes
1924 (_("Keep"), GTK_CELL_RENDERER(renderer_toggle), "active", COL_CHECK, NULL);
1925
1926 /* description */
1927 renderer = GTK_CELL_RENDERER_TEXT(gtk_cell_renderer_text_new());
1928 g_signal_connect(renderer, "edited", G_CALLBACK(cell_edited_event), ui);
1929 g_object_set(renderer, "editable", TRUE, NULL);
1930 g_object_set_data(G_OBJECT(renderer), "col", GINT_TO_POINTER(COL_DESCRIPTION));
1931 column_description = gtk_tree_view_column_new_with_attributes
1932 (_("Filename"), GTK_CELL_RENDERER(renderer), "text", COL_DESCRIPTION, NULL);
1933
1934 /* seconds */
1935 renderer = GTK_CELL_RENDERER_TEXT(gtk_cell_renderer_text_new());
1936 g_signal_connect(renderer, "edited", G_CALLBACK(cell_edited_event), ui);
1937 g_object_set(renderer, "editable", TRUE, NULL);
1938 g_object_set_data(G_OBJECT(renderer), "col", GINT_TO_POINTER(COL_SECONDS));
1939 column_seconds = gtk_tree_view_column_new_with_attributes
1940 (_("Secs"), GTK_CELL_RENDERER(renderer), "text", COL_SECONDS, NULL);
1941
1942 /* minutes */
1943 renderer = GTK_CELL_RENDERER_TEXT(gtk_cell_renderer_text_new());
1944 g_signal_connect(renderer, "edited", G_CALLBACK(cell_edited_event), ui);
1945 g_object_set(renderer, "editable", TRUE, NULL);
1946 g_object_set_data(G_OBJECT(renderer), "col", GINT_TO_POINTER(COL_MINUTES));
1947 column_minutes = gtk_tree_view_column_new_with_attributes
1948 (_("Mins"), GTK_CELL_RENDERER(renderer), "text", COL_MINUTES, NULL);
1949
1950 /* hundr secs */
1951 renderer = GTK_CELL_RENDERER_TEXT(gtk_cell_renderer_text_new());
1952 g_signal_connect(renderer, "edited", G_CALLBACK(cell_edited_event), ui);
1953 g_object_set(renderer, "editable", TRUE, NULL);
1954 g_object_set_data(G_OBJECT(renderer), "col", GINT_TO_POINTER(COL_HUNDR_SECS));
1955 column_hundr_secs = gtk_tree_view_column_new_with_attributes
1956 (_("Hundr"), GTK_CELL_RENDERER(renderer), "text", COL_HUNDR_SECS, NULL);
1957
1958 /* Length column */
1959 //renderer creation
1960 renderer = GTK_CELL_RENDERER_TEXT(gtk_cell_renderer_text_new());
1961 g_object_set(G_OBJECT (renderer), "xalign", 1.0, NULL);
1962 g_object_set_data(G_OBJECT(renderer), "col", GINT_TO_POINTER(COL_NUMBER));
1963 column_number = gtk_tree_view_column_new_with_attributes
1964 (_("Length"), GTK_CELL_RENDERER(renderer), "text", COL_NUMBER, NULL);
1965
1966 /* column preview */
1967 renderer_pix = GTK_CELL_RENDERER_PIXBUF(gtk_cell_renderer_pixbuf_new());
1968 g_object_set(renderer_pix, "icon-name", "media-playback-start",
1969 "stock-size", GTK_ICON_SIZE_MENU, NULL);
1970 column_preview = gtk_tree_view_column_new_with_attributes
1971 (_("LiveP"), GTK_CELL_RENDERER(renderer_pix), NULL);
1972 g_object_set_data(G_OBJECT(column_preview), "col", GINT_TO_POINTER(COL_PREVIEW));
1973
1974 /* split preview */
1975 renderer_pix = GTK_CELL_RENDERER_PIXBUF(gtk_cell_renderer_pixbuf_new());
1976 g_object_set(renderer_pix, "icon-name", "media-playback-start",
1977 "stock-size", GTK_ICON_SIZE_MENU, NULL);
1978 column_split_preview = gtk_tree_view_column_new_with_attributes
1979 (_("SplitP"), GTK_CELL_RENDERER(renderer_pix), NULL);
1980 g_object_set_data(G_OBJECT(column_split_preview), "col", GINT_TO_POINTER(COL_SPLIT_PREVIEW));
1981
1982 gtk_tree_view_insert_column(GTK_TREE_VIEW(tree_view), column_check, COL_CHECK);
1983 gtk_tree_view_insert_column(GTK_TREE_VIEW(tree_view), column_description, COL_DESCRIPTION);
1984 gtk_tree_view_insert_column(GTK_TREE_VIEW(tree_view), column_minutes, COL_MINUTES);
1985 gtk_tree_view_insert_column(GTK_TREE_VIEW(tree_view), column_seconds, COL_SECONDS);
1986 gtk_tree_view_insert_column(GTK_TREE_VIEW(tree_view), column_hundr_secs, COL_HUNDR_SECS);
1987 gtk_tree_view_insert_column(GTK_TREE_VIEW(tree_view), column_number, COL_NUMBER);
1988 gtk_tree_view_insert_column(GTK_TREE_VIEW(tree_view), column_preview, COL_PREVIEW);
1989 gtk_tree_view_insert_column(GTK_TREE_VIEW(tree_view), column_split_preview, COL_SPLIT_PREVIEW);
1990
1991 gtk_tree_view_column_set_alignment(column_check, 0.5);
1992 gtk_tree_view_column_set_alignment(column_description, 0.5);
1993 gtk_tree_view_column_set_alignment(column_minutes, 0.5);
1994 gtk_tree_view_column_set_alignment(column_seconds, 0.5);
1995 gtk_tree_view_column_set_alignment(column_hundr_secs, 0.5);
1996 gtk_tree_view_column_set_alignment(column_number, 0.5);
1997 gtk_tree_view_column_set_alignment(column_preview, 0.5);
1998 gtk_tree_view_column_set_alignment(column_split_preview, 0.5);
1999
2000 gtk_tree_view_column_set_sizing(column_check, GTK_TREE_VIEW_COLUMN_FIXED);
2001 gtk_tree_view_column_set_fixed_width(column_check, 70);
2002
2003 gtk_tree_view_column_set_resizable(column_description, TRUE);
2004
2005 gtk_tree_view_column_set_reorderable(column_check, TRUE);
2006 gtk_tree_view_column_set_reorderable(column_description, TRUE);
2007 gtk_tree_view_column_set_reorderable(column_minutes, TRUE);
2008 gtk_tree_view_column_set_reorderable(column_seconds, TRUE);
2009 gtk_tree_view_column_set_reorderable(column_hundr_secs, TRUE);
2010 gtk_tree_view_column_set_reorderable(column_number, TRUE);
2011 gtk_tree_view_column_set_reorderable(column_preview, TRUE);
2012 gtk_tree_view_column_set_reorderable(column_split_preview, TRUE);
2013
2014 gtk_tree_view_column_set_expand(column_description, TRUE);
2015
2016 gint i = 0;
2017 for (i = COL_TITLE;i < NUM_COLUMNS;i++)
2018 {
2019 renderer = GTK_CELL_RENDERER_TEXT(gtk_cell_renderer_text_new());
2020 g_signal_connect(renderer, "edited", G_CALLBACK(cell_edited_event), ui);
2021 g_object_set(renderer, "editable", TRUE, NULL);
2022 g_object_set_data(G_OBJECT(renderer), "col", GINT_TO_POINTER(i));
2023
2024 gchar column_name[255] = { '\0' };
2025 gint minimum_width = 100;
2026 switch (i)
2027 {
2028 case COL_TITLE:
2029 g_snprintf(column_name, 255, _("Title"));
2030 break;
2031 case COL_ARTIST:
2032 g_snprintf(column_name, 255, _("Artist"));
2033 break;
2034 case COL_ALBUM:
2035 g_snprintf(column_name, 255, _("Album"));
2036 break;
2037 case COL_GENRE:
2038 g_snprintf(column_name, 255, _("Genre"));
2039 minimum_width = 70;
2040 break;
2041 case COL_COMMENT:
2042 g_snprintf(column_name, 255, _("Comment"));
2043 break;
2044 case COL_YEAR:
2045 g_snprintf(column_name, 255, _("Year"));
2046 minimum_width = 40;
2047 break;
2048 case COL_TRACK:
2049 g_snprintf(column_name, 255, _("Track"));
2050 minimum_width = 20;
2051 break;
2052 default:
2053 break;
2054 }
2055
2056 GtkTreeViewColumn *tag_column = gtk_tree_view_column_new_with_attributes
2057 (column_name, GTK_CELL_RENDERER(renderer), "text", i, NULL);
2058
2059 gtk_tree_view_insert_column(GTK_TREE_VIEW(tree_view), tag_column, i);
2060 gtk_tree_view_column_set_alignment(tag_column, 0.5);
2061 gtk_tree_view_column_set_resizable(tag_column, TRUE);
2062 gtk_tree_view_column_set_reorderable(tag_column, TRUE);
2063 gtk_tree_view_column_set_min_width(tag_column, minimum_width);
2064 }
2065}
2066
2068static void create_tree_view(ui_state *ui)
2069{
2070 GtkTreeView *tree_view = GTK_TREE_VIEW(gtk_tree_view_new_with_model(create_model()));
2071 dnd_add_drag_data_received_to_widget(GTK_WIDGET(tree_view), DND_DATA_FILES, ui);
2072
2073 ui->gui->tree_view = tree_view;
2074
2075 g_signal_connect(tree_view, "row-activated", G_CALLBACK(preview_song), ui);
2076
2077 GtkTreeSelection *selection = gtk_tree_view_get_selection(tree_view);
2078 g_signal_connect(selection, "changed", G_CALLBACK(row_selection_event), ui);
2079}
2080
2087{
2088 gui_state *gui = ui->gui;
2089
2090 create_tree_view(ui);
2091
2092 /* choose splitpoins vbox */
2093 GtkWidget *choose_splitpoints_vbox = wh_vbox_new();
2094 gtk_container_set_border_width(GTK_CONTAINER(choose_splitpoints_vbox), 0);
2095
2096 /* spinner buttons hbox */
2097 GtkWidget *spinners_buttons_hbox = create_init_spinners_buttons(ui);
2098 gtk_box_pack_start(GTK_BOX(choose_splitpoints_vbox), spinners_buttons_hbox, FALSE, FALSE, 3);
2099
2100 /* horizontal box for the tree */
2101 GtkWidget *tree_hbox = wh_hbox_new();
2102 gtk_box_pack_start(GTK_BOX(choose_splitpoints_vbox), tree_hbox, TRUE, TRUE, 0);
2103
2104 /* scrolled window for the tree */
2105 GtkWidget *scrolled_window = gtk_scrolled_window_new(NULL, NULL);
2106 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW(scrolled_window), GTK_SHADOW_NONE);
2107 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
2108 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2109 gtk_box_pack_start(GTK_BOX(tree_hbox), scrolled_window, TRUE, TRUE, 0);
2110
2111 GtkTreeSelection *selection = gtk_tree_view_get_selection(gui->tree_view);
2112 gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE);
2113 create_columns(ui);
2114 gtk_container_add(GTK_CONTAINER(scrolled_window), GTK_WIDGET(gui->tree_view));
2115
2116 g_signal_connect(gui->tree_view, "popup-menu", G_CALLBACK(show_popup), ui);
2117 g_signal_connect(gui->tree_view, "button-press-event", G_CALLBACK(select_and_show_popup), ui);
2118
2119 /* special buttons like 'set silence from silence detection' */
2120 create_init_special_buttons(ui);
2121
2122 return choose_splitpoints_vbox;
2123}
2124
2125static void garray_to_array(GArray *spltpoints, glong *hundredth, ui_state *ui)
2126{
2127 gint i = 0;
2128 for(i = 0; i < ui->infos->splitnumber; i++ )
2129 {
2130 Split_point point = g_array_index(ui->splitpoints, Split_point, i);
2131 if (point.mins >= (INT_MAX-1)/6000)
2132 {
2133 hundredth[i] = LONG_MAX;
2134 }
2135 else
2136 {
2137 hundredth[i] = point.mins * 6000 +
2138 point.secs * 100 + point.hundr_secs;
2139 }
2140 }
2141}
2142
2143points_and_tags *get_splitpoints_and_tags_for_mp3splt_state(ui_state *ui)
2144{
2145 points_and_tags *pat = new_points_and_tags();
2146
2147 glong hundr[ui->infos->splitnumber];
2148 garray_to_array(ui->splitpoints, hundr, ui);
2149
2150 GtkTreeModel *model = gtk_tree_view_get_model(ui->gui->tree_view);
2151
2152 gint i;
2153 for (i = 0; i < ui->infos->splitnumber; i++)
2154 {
2155 GtkTreePath *path = gtk_tree_path_new_from_indices(i ,-1);
2156 GtkTreeIter iter;
2157 gtk_tree_model_get_iter(model, &iter, path);
2158 gtk_tree_path_free(path);
2159
2160 gchar *description = NULL;
2161 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, COL_DESCRIPTION, &description, -1);
2162
2163 //get the 'checked' value from the current splitpoint
2164 Split_point point = g_array_index(ui->splitpoints, Split_point, i);
2165 splt_type_of_splitpoint splitpoint_type = SPLT_SPLITPOINT;
2166
2167 if (point.checked == FALSE)
2168 {
2169 splitpoint_type = SPLT_SKIPPOINT;
2170 }
2171
2172 splt_point *splitpoint = mp3splt_point_new(hundr[i], NULL);
2173 mp3splt_point_set_name(splitpoint, description);
2174 g_free(description);
2175 mp3splt_point_set_type(splitpoint, splitpoint_type);
2176 append_point_to_pat(splitpoint, pat);
2177
2178 gint year = 0, track = 0;
2179 gchar *title = NULL, *artist = NULL, *album = NULL, *genre = NULL, *comment = NULL;
2180
2181 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter,
2182 COL_TITLE, &title,
2183 COL_ARTIST, &artist,
2184 COL_ALBUM, &album,
2185 COL_GENRE, &genre,
2186 COL_COMMENT, &comment,
2187 COL_YEAR, &year,
2188 COL_TRACK, &track,
2189 -1);
2190
2191 splt_tags *tags = mp3splt_tags_new(NULL);
2192
2193 if (year > 0)
2194 {
2195 gchar year_str[10] = { '\0' };
2196 g_snprintf(year_str, 10, "%d", year);
2197 mp3splt_tags_set(tags, SPLT_TAGS_YEAR, year_str, 0);
2198 }
2199
2200 if (track <= 0) { track = -2; }
2201 gchar track_str[10] = { '\0' };
2202 g_snprintf(track_str, 10, "%d", track);
2203 mp3splt_tags_set(tags, SPLT_TAGS_TRACK, track_str, 0);
2204
2205 mp3splt_tags_set(tags,
2206 SPLT_TAGS_TITLE, title,
2207 SPLT_TAGS_ARTIST, artist,
2208 SPLT_TAGS_ALBUM, album,
2209 SPLT_TAGS_GENRE, genre,
2210 SPLT_TAGS_COMMENT, comment,
2211 0);
2212 append_tags_to_pat(tags, pat);
2213
2214 free(title); free(artist); free(album); free(genre); free(comment);
2215 }
2216
2217 return pat;
2218}
2219
void update_splitpoints_from_mp3splt_state(ui_state *ui)
updates the current splitpoints in ui->mp3splt_state
void print_status_bar_confirmation(gint error, ui_state *ui)
Output an error message from libmp3splt to the status bar.
void remove_status_message(gui_state *gui)
Removes status bar message.
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 put_options_from_preferences(ui_for_split *ui_fs)
Update the ui->mp3splt_state structure.
void change_current_filename(const gchar *fname, ui_state *ui)
Change the name of the song that is to be cut and played.
void player_quick_preview(gint splitpoint_to_preview, ui_state *ui)
makes a preview of the song
void check_update_down_progress_bar(ui_state *ui)
updates bottom progress bar
void connect_button_event(GtkWidget *widget, ui_state *ui)
play button event
void cancel_quick_preview(gui_status *status)
cancels preview
void cancel_quick_preview_all(ui_state *ui)
full cancel of the preview
void connect_to_player_with_song(gint i, ui_state *ui)
connects to player with the song from the filename entry
gchar * get_preferences_filename()
Get the name of the preferences file.
gchar * get_filename_from_split_files(gint number, gui_state *gui)
return the n_th filename from the split files
void remove_all_split_rows(ui_state *ui)
removes all rows from the split files table
void update_minutes_from_spinner(GtkWidget *widget, ui_state *ui)
updates the minutes from the spinner
void update_seconds_from_spinner(GtkWidget *widget, ui_state *ui)
updates the seconds from the spinner
void select_splitpoint(gint index, gui_state *gui)
selects a splitpoint
void create_detect_silence_and_add_splitpoints_window(GtkWidget *button, ui_state *ui)
event for clicking the 'detect silence and add splitpoints' button
void update_splitpoint_from_time(gint index, gdouble time, ui_state *ui)
Set a splitpoint's time value.
void update_splitpoint_check(gint index, ui_state *ui)
Toggles a splitpoint's "Keep" flag.
void get_hundr_secs_mins_time(gint time_pos, gint *time_hundr, gint *time_secs, gint *time_mins)
returns secs, mins, hundr of secs from a time
void remove_all_rows(GtkWidget *widget, ui_state *ui)
removes all rows from the table
void update_hundr_secs_from_spinner(GtkWidget *widget, ui_state *ui)
updates the hundredth of seconds for the spinner
GtkWidget * create_splitpoints_frame(ui_state *ui)
creates the choose splitpoints frame
gint get_first_splitpoint_selected(gui_state *gui)
Gets the number of the first splitpoint with selected "Keep" checkbox.
void add_row(gboolean checked, ui_state *ui)
adds a row to the table
gint get_splitpoint_time(gint splitpoint_index, ui_state *ui)
returns a splitpoint from the table
void update_splitpoint(gint index, Split_point new_point, ui_state *ui)
Set all values of a split point.
gchar * get_splitpoint_name(gint index, ui_state *ui)
returns the name of the splitpoint
void remove_splitpoint(gint index, gint stop_preview, ui_state *ui)
removes a splitpoint