mp3splt-gtk

- Main Page
- Related Pages
- Data Structures
- Files

- File List
- Globals

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