1 /*
2 Asunder
3
4 Copyright(C) 2005 Eric Lathrop <eric@ericlathrop.com>
5 Copyright(C) 2007 Andrew Smith <http://littlesvr.ca/contact.php>
6
7 Any code in this file may be redistributed or modified under the terms of
8 the GNU General Public Licence as published by the Free Software
9 Foundation; version 2 of the licence.
10
11 */
12
13 #ifdef HAVE_CONFIG_H
14 # include <config.h>
15 #endif
16
17 #include <gtk/gtk.h>
18 #include <unistd.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <ctype.h>
22
23 #include "callbacks.h"
24 #include "interface.h"
25 #include "support.h"
26 #include "main.h"
27 #include "prefs.h"
28 #include "threads.h"
29 #include "util.h"
30
31 gboolean
for_each_row_deselect(GtkTreeModel * model,GtkTreePath * path,GtkTreeIter * iter,gpointer data)32 for_each_row_deselect (GtkTreeModel *model,
33 GtkTreePath *path,
34 GtkTreeIter *iter,
35 gpointer data)
36 {
37 gtk_list_store_set(GTK_LIST_STORE(model), iter, COL_RIPTRACK, 0, -1);
38
39 return FALSE;
40 }
41
42 gboolean
for_each_row_select(GtkTreeModel * model,GtkTreePath * path,GtkTreeIter * iter,gpointer data)43 for_each_row_select (GtkTreeModel *model,
44 GtkTreePath *path,
45 GtkTreeIter *iter,
46 gpointer data)
47 {
48 gtk_list_store_set(GTK_LIST_STORE(model), iter, COL_RIPTRACK, 1, -1);
49
50 return FALSE;
51 }
52
53 gchar*
format_wavpack_bitrate(GtkScale * scale,gdouble arg1,gpointer user_data)54 format_wavpack_bitrate (GtkScale *scale,
55 gdouble arg1,
56 gpointer user_data)
57 {
58 return g_strdup_printf (_("%dKbps"), int_to_wavpack_bitrate((int)arg1));
59 }
60
61 void
on_about_clicked(GtkToolButton * toolbutton,gpointer user_data)62 on_about_clicked (GtkToolButton *toolbutton,
63 gpointer user_data)
64 {
65 show_aboutbox();
66 }
67
68 void
on_aboutbox_response(GtkDialog * dialog,gint response_id,gpointer user_data)69 on_aboutbox_response (GtkDialog *dialog,
70 gint response_id,
71 gpointer user_data)
72 {
73 gtk_widget_hide(GTK_WIDGET(dialog));
74 gtk_widget_destroy(GTK_WIDGET(dialog));
75 }
76
77 void
update_track_offsets(void)78 update_track_offsets (void)
79 {
80 GtkTreeIter iter;
81 GtkListStore * store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(lookup_widget(win_main, "tracklist"))));
82 if (store == NULL)
83 return;
84 gboolean rowsleft = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter);
85 int tracknum;
86
87 while (rowsleft)
88 {
89 gtk_tree_model_get(GTK_TREE_MODEL(store), &iter,
90 COL_TRACKNUM, &tracknum,
91 -1);
92 gtk_list_store_set(store, &iter,
93 COL_TRACKNUM_VIS, tracknum + global_prefs->first_track_num_offset,
94 -1);
95 rowsleft = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter);
96 }
97 }
98
99 gboolean
on_album_artist_focus_out_event(GtkWidget * widget,GdkEventFocus * event,gpointer user_data)100 on_album_artist_focus_out_event (GtkWidget *widget,
101 GdkEventFocus *event,
102 gpointer user_data)
103 {
104 const gchar * ctext = gtk_entry_get_text(GTK_ENTRY(widget));
105 gchar * text = malloc(sizeof(gchar) * (strlen(ctext) + 1));
106 if (text == NULL)
107 fatalError("malloc(sizeof(gchar) * (strlen(ctext) + 1)) failed. Out of memory.");
108 strncpy(text, ctext, strlen(ctext)+1);
109
110 //trim_chars(text, BADCHARS); // lnr //Commented out by mrpl
111 trim_whitespace(text);
112
113 if(text[0] == '\0')
114 gtk_entry_set_text(GTK_ENTRY(widget), "unknown");
115 else
116 gtk_entry_set_text(GTK_ENTRY(widget), text);
117
118 free(text);
119 return FALSE;
120 }
121
122 gboolean
on_year_focus_out_event(GtkWidget * widget,GdkEventFocus * event,gpointer user_data)123 on_year_focus_out_event (GtkWidget *widget,
124 GdkEventFocus *event,
125 gpointer user_data)
126 {
127 const gchar * ctext = gtk_entry_get_text(GTK_ENTRY(widget));
128 gchar * text = malloc(5);
129 if (text == NULL)
130 fatalError("malloc(5) failed. Out of memory.");
131 strncpy(text, ctext, 5);
132 text[4] = '\0';
133
134 if((text[0] != '1' && text[0] != '2') || text[1] < '0' || text[1] > '9' ||
135 text[2] < '0' || text[2] > '9' || text[3] < '0' || text[3] > '9')
136 {
137 sprintf(text, "1900");
138 }
139
140 gtk_entry_set_text(GTK_ENTRY(widget), text);
141
142 free(text);
143 return FALSE;
144 }
145
146 gboolean
on_album_title_focus_out_event(GtkWidget * widget,GdkEventFocus * event,gpointer user_data)147 on_album_title_focus_out_event (GtkWidget *widget,
148 GdkEventFocus *event,
149 gpointer user_data)
150 {
151 const gchar * ctext = gtk_entry_get_text(GTK_ENTRY(widget));
152 gchar * text = malloc(sizeof(gchar) * (strlen(ctext) + 1));
153 if (text == NULL)
154 fatalError("malloc(sizeof(gchar) * (strlen(ctext) + 1)) failed. Out of memory.");
155 strncpy(text, ctext, strlen(ctext)+1);
156
157 //trim_chars(text, BADCHARS); // lnr //Commented out by mrpl
158 trim_whitespace(text);
159
160 if(text[0] == '\0')
161 gtk_entry_set_text(GTK_ENTRY(widget), "unknown");
162 else
163 gtk_entry_set_text(GTK_ENTRY(widget), text);
164
165 free(text);
166 return FALSE;
167 }
168
169 // lnr
170 gboolean
on_album_genre_focus_out_event(GtkWidget * widget,GdkEventFocus * event,gpointer user_data)171 on_album_genre_focus_out_event (GtkWidget *widget,
172 GdkEventFocus *event,
173 gpointer user_data)
174 {
175 const gchar * ctext = gtk_entry_get_text(GTK_ENTRY(widget));
176
177 gchar * text = malloc(sizeof(gchar) * (strlen(ctext) + 1));
178
179 if (text == NULL)
180 fatalError("malloc(sizeof(gchar) * (strlen(ctext) + 1)) failed. Out of memory.");
181
182 strncpy(text, ctext, strlen(ctext)+1);
183
184 //trim_chars(text, BADCHARS); // lnr //Commented out by mrpl
185 trim_whitespace(text);
186
187 if(text[0] == '\0')
188 gtk_entry_set_text(GTK_ENTRY(widget), "Unknown");
189 else
190 gtk_entry_set_text(GTK_ENTRY(widget), text);
191
192 free(text);
193
194 return FALSE;
195 }
196
197 // First track number arbitrarily limited to 1001
198 gboolean
on_tracknum_first_focus_out_event(GtkWidget * widget,GdkEventFocus * event,gpointer user_data)199 on_tracknum_first_focus_out_event (GtkWidget *widget,
200 GdkEventFocus *event,
201 gpointer user_data)
202 {
203 const gchar * ctext = gtk_entry_get_text(GTK_ENTRY(widget));
204 int first = atoi(ctext);
205
206 if (first >= 1 && first <= 1001)
207 {
208 global_prefs->first_track_num_offset = first - 1;
209 }
210 update_track_offsets();
211
212 char txt[16];
213 snprintf(txt, 16, "%d", global_prefs->first_track_num_offset + 1);
214 gtk_entry_set_text(GTK_ENTRY (widget), txt);
215
216 return FALSE;
217 }
218
219 void
on_tracknum_width_changed_event(GtkComboBox * combobox,gpointer user_data)220 on_tracknum_width_changed_event (GtkComboBox *combobox,
221 gpointer user_data)
222 {
223 gint selected = gtk_combo_box_get_active(combobox);
224 int width = selected + 1;
225
226 if (width >= 1 && width <= 4)
227 {
228 global_prefs->track_num_width = width;
229 }
230
231 gtk_combo_box_set_active(GTK_COMBO_BOX(combobox), global_prefs->track_num_width - 1);
232 }
233
234 void
on_artist_edited(GtkCellRendererText * cell,gchar * path_string,gchar * new_text,gpointer user_data)235 on_artist_edited (GtkCellRendererText *cell,
236 gchar *path_string,
237 gchar *new_text,
238 gpointer user_data)
239 {
240 GtkListStore * store = GTK_LIST_STORE(gtk_tree_view_get_model(
241 GTK_TREE_VIEW(lookup_widget(win_main, "tracklist"))));
242 GtkTreeIter iter;
243
244 //trim_chars(new_text, BADCHARS); // lnr //Commented out by mrpl
245 trim_whitespace(new_text);
246
247 gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(store), &iter, path_string);
248
249 if(new_text[0] == '\0')
250 gtk_list_store_set(store, &iter, COL_TRACKARTIST, "unknown", -1);
251 else
252 gtk_list_store_set(store, &iter, COL_TRACKARTIST, new_text, -1);
253 }
254
255 void
on_cancel_clicked(GtkButton * button,gpointer user_data)256 on_cancel_clicked (GtkButton *button,
257 gpointer user_data)
258 {
259 abort_threads();
260 }
261
262 gboolean
on_cddb_update_closed(GtkWidget * widget,GdkEvent * event,GtkWidget ** update_window)263 on_cddb_update_closed (GtkWidget *widget,
264 GdkEvent *event,
265 GtkWidget** update_window)
266 {
267 *update_window = NULL;
268
269 return FALSE;
270 }
271
272 void
on_deselect_all_click(GtkMenuItem * menuitem,gpointer data)273 on_deselect_all_click (GtkMenuItem *menuitem,
274 gpointer data)
275 {
276 GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(lookup_widget(win_main, "tracklist")));
277
278 gtk_tree_model_foreach(model, for_each_row_deselect, NULL);
279 }
280
281 void
on_vbr_toggled(GtkToggleButton * togglebutton,gpointer user_data)282 on_vbr_toggled (GtkToggleButton *togglebutton,
283 gpointer user_data)
284 {
285 char bitrate[8];
286 GtkRange* range;
287 bool vbr;
288
289 /* update the displayed vbr, as it's different for vbr and non-vbr */
290 vbr = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(togglebutton));
291 range = GTK_RANGE(lookup_widget(win_prefs, "mp3bitrate"));
292 snprintf(bitrate, 8, _("%dKbps"), int_to_bitrate((int)gtk_range_get_value(range), vbr));
293 gtk_label_set_text(GTK_LABEL(lookup_widget(win_prefs, "bitrate_lbl_2")), bitrate);
294 }
295
296 void
on_hybrid_toggled(GtkToggleButton * togglebutton,gpointer user_data)297 on_hybrid_toggled (GtkToggleButton *togglebutton,
298 gpointer user_data)
299 {
300 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(win_prefs, "wavpack_hybrid"))))
301 {
302 gtk_widget_set_sensitive(lookup_widget(win_prefs, "wavpack_bitrate_lbl"), TRUE);
303 gtk_widget_set_sensitive(lookup_widget(win_prefs, "wavpack_bitrate_slider"), TRUE);
304 }
305 else
306 {
307 gtk_widget_set_sensitive(lookup_widget(win_prefs, "wavpack_bitrate_lbl"), FALSE);
308 gtk_widget_set_sensitive(lookup_widget(win_prefs, "wavpack_bitrate_slider"), FALSE);
309 }
310 }
311
312 void
on_mp3bitrate_value_changed(GtkRange * range,gpointer user_data)313 on_mp3bitrate_value_changed (GtkRange *range,
314 gpointer user_data)
315 {
316 char bitrate[8];
317 bool vbr;
318
319 vbr = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(win_prefs, "mp3_vbr")));
320 snprintf(bitrate, 8, _("%dKbps"), int_to_bitrate((int)gtk_range_get_value(range), vbr));
321 gtk_label_set_text(GTK_LABEL(lookup_widget(win_prefs, "bitrate_lbl_2")), bitrate);
322 }
323
324 void
on_fdkaac_bitrate_value_changed(GtkRange * range,gpointer user_data)325 on_fdkaac_bitrate_value_changed (GtkRange *range,
326 gpointer user_data)
327 {
328 char bitrate[8];
329 snprintf(bitrate, 8, _("%dKbps"), int_to_bitrate((int)gtk_range_get_value(range), 0));
330 gtk_label_set_text(GTK_LABEL(lookup_widget(win_prefs, "fdkaac_bitrate_lbl_2")), bitrate);
331 }
332
333 void
on_opusrate_value_changed(GtkRange * range,gpointer user_data)334 on_opusrate_value_changed (GtkRange *range,
335 gpointer user_data)
336 {
337 char bitrate[8];
338 snprintf(bitrate, 8, _("%dKbps"), int_to_bitrate((int)gtk_range_get_value(range), FALSE));
339 gtk_label_set_text(GTK_LABEL(lookup_widget(win_prefs, "bitrate_lbl_4")), bitrate);
340 }
341
342 void
on_musepackbitrate_value_changed(GtkRange * range,gpointer user_data)343 on_musepackbitrate_value_changed (GtkRange *range,
344 gpointer user_data)
345 {
346 char bitrate[8];
347
348 snprintf(bitrate, 8, _("%dKbps"), int_to_musepack_bitrate((int)gtk_range_get_value(range)));
349 gtk_label_set_text(GTK_LABEL(lookup_widget(win_prefs, "bitrate_lbl_3")), bitrate);
350 }
351
352 void
on_pick_disc_changed(GtkComboBox * combobox,gpointer user_data)353 on_pick_disc_changed (GtkComboBox *combobox,
354 gpointer user_data)
355 {
356 gint selected = gtk_combo_box_get_active(combobox);
357 if (gbl_disc_matches == NULL ||
358 selected == -1 ||
359 (guint)selected >= g_list_length(gbl_disc_matches))
360 return;
361 cddb_disc_t * disc = g_list_nth_data(gbl_disc_matches, selected);
362 update_tracklist(disc);
363 }
364
365 void
on_preferences_clicked(GtkToolButton * toolbutton,gpointer user_data)366 on_preferences_clicked (GtkToolButton *toolbutton,
367 gpointer user_data)
368 {
369 win_prefs = create_prefs();
370 gtk_widget_show(win_prefs);
371 }
372
373 void
on_prefs_response(GtkDialog * dialog,gint response_id,gpointer user_data)374 on_prefs_response (GtkDialog *dialog,
375 gint response_id,
376 gpointer user_data)
377 {
378 //gtk_widget_hide(GTK_WIDGET(dialog));
379
380 if (response_id == GTK_RESPONSE_OK)
381 {
382 if (!prefs_are_valid())
383 return;
384
385 get_prefs_from_widgets(global_prefs);
386 save_prefs(global_prefs);
387 toggle_allow_tracknum();
388 }
389
390 gtk_widget_destroy(GTK_WIDGET(dialog));
391 }
392
393 void
on_prefs_show(GtkWidget * widget,gpointer user_data)394 on_prefs_show (GtkWidget *widget,
395 gpointer user_data)
396 {
397 set_widgets_from_prefs(global_prefs);
398 }
399
400
401 void
on_edit_capitalize_clicked(void)402 on_edit_capitalize_clicked (void)
403 {
404 // "Capitalize Artists & Titles"
405
406 GtkTreeIter iter;
407 GtkListStore * store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(lookup_widget(win_main, "tracklist"))));
408 if (store == NULL)
409 return;
410
411 gboolean rowsleft = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter);
412 while (rowsleft)
413 {
414 int riptrack;
415 char * trackartist = NULL;
416 char * tracktitle = NULL;
417
418 gtk_tree_model_get(GTK_TREE_MODEL(store), &iter,
419 COL_RIPTRACK, &riptrack,
420 COL_TRACKARTIST, &trackartist,
421 COL_TRACKTITLE, &tracktitle,
422 -1);
423
424 if (riptrack) // Only modify selected tracks
425 {
426 int start_of_word = 1;
427 for (char *cp = trackartist; *cp; ++cp)
428 {
429 if (isspace(*cp))
430 {
431 start_of_word = 1;
432 }
433 else
434 if (start_of_word)
435 {
436 if (islower(*cp))
437 *cp = toupper(*cp);
438 start_of_word = 0;
439 }
440 }
441
442 start_of_word = 1;
443 for (char *cp = tracktitle; *cp; ++cp)
444 {
445 if (isspace(*cp))
446 {
447 start_of_word = 1;
448 }
449 else
450 if (start_of_word)
451 {
452 if (islower(*cp))
453 *cp = toupper(*cp);
454 start_of_word = 0;
455 }
456 }
457
458 // Write modified values back into widgets
459 gtk_list_store_set(store, &iter,
460 COL_TRACKARTIST, trackartist,
461 COL_TRACKTITLE, tracktitle,
462 -1);
463 }
464
465 if (trackartist)
466 free (trackartist);
467 if (tracktitle)
468 free (tracktitle);
469
470 rowsleft = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter);
471 }
472 }
473
474 void
on_edit_split_clicked(void)475 on_edit_split_clicked (void)
476 {
477 // "Split 'Artist/Title' in Title field"
478
479 GtkTreeIter iter;
480 GtkListStore * store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(lookup_widget(win_main, "tracklist"))));
481 if (store == NULL)
482 return;
483
484 gboolean rowsleft = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter);
485 while (rowsleft)
486 {
487 int riptrack;
488 char * trackartist = NULL;
489 char * tracktitle = NULL;
490
491 gtk_tree_model_get(GTK_TREE_MODEL(store), &iter,
492 COL_RIPTRACK, &riptrack,
493 COL_TRACKTITLE, &tracktitle,
494 -1);
495
496 if (riptrack) // Only modify selected tracks
497 {
498 char *separator = strchr(tracktitle, global_prefs->concatenated_track_separator[0]);
499 if (separator != NULL)
500 {
501 // If separator is present, split Artist/Title
502 trackartist = strdup(tracktitle);
503 separator = strchr(trackartist, global_prefs->concatenated_track_separator[0]);
504 char* cp = separator + 1;
505 while (*cp != '\0' && isspace(*cp)) // Remove space after separator
506 cp++;
507 strcpy(tracktitle, cp);
508 *separator = '\0';
509 cp = separator - 1;
510 while (cp >= trackartist && *cp && isspace(*cp)) // Remove space before separator
511 {
512 *cp = '\0';
513 cp--;
514 }
515
516 // Write modified values back into widgets
517 gtk_list_store_set(store, &iter,
518 COL_TRACKARTIST, trackartist,
519 COL_TRACKTITLE, tracktitle,
520 -1);
521 }
522 }
523
524 if (trackartist)
525 free (trackartist);
526 if (tracktitle)
527 free (tracktitle);
528
529 rowsleft = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter);
530 }
531 }
532
533 static void
concatenate_artist_track(void)534 concatenate_artist_track(void)
535 {
536 GtkTreeIter iter;
537 GtkListStore* store = GTK_LIST_STORE(gtk_tree_view_get_model(
538 GTK_TREE_VIEW(lookup_widget(win_main, "tracklist"))));
539
540 gboolean valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter);
541
542 while(valid)
543 {
544 GValue gTitle = {0, };
545 gtk_tree_model_get_value(GTK_TREE_MODEL(store), &iter, COL_TRACKTITLE,
546 &gTitle);
547 const char* title = g_value_get_string(&gTitle);
548
549 GValue gArtist = {0, };
550 gtk_tree_model_get_value(GTK_TREE_MODEL(store), &iter, COL_TRACKARTIST,
551 &gArtist);
552 const char* artist = g_value_get_string(&gArtist);
553
554 char separator[] = {" "};
555 separator[1] = global_prefs->concatenated_track_separator[0];
556
557 char* artist_and_track = malloc(strlen(artist)
558 + strlen(title)
559 + strlen(separator) + 1);
560
561 if(!artist_and_track)
562 {
563 fatalError("malloc(strlen(artist)+strlen(title)+strlen(separator)+1)"
564 " failed. Out of memory");
565 }
566
567 artist_and_track[0] = '\0';
568 strcat(artist_and_track, artist);
569 strcat(artist_and_track, separator);
570 strcat(artist_and_track, title);
571
572 gtk_list_store_set(store, &iter, COL_TRACKARTISTTITLE, artist_and_track, -1);
573
574 free(artist_and_track);
575
576 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter);
577 }
578 }
579
580 static void
toggle_joined_title_artist(void)581 toggle_joined_title_artist (void)
582 {
583 if(join_artist_title <= JOIN_OFF)
584 {
585 concatenate_artist_track();
586 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(win_main,
587 "single_artist")), TRUE);
588 join_artist_title = JOIN_ON;
589 }
590 else
591 {
592 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(win_main,
593 "single_artist")), FALSE);
594 join_artist_title = JOIN_OFF;
595 }
596
597 GtkTreeViewColumn * concatenatedCol = gtk_tree_view_get_column(
598 GTK_TREE_VIEW(tracklist), COL_TRACKARTISTTITLE);
599 gtk_tree_view_column_set_visible(concatenatedCol, join_artist_title == JOIN_ON);
600
601 GtkTreeViewColumn * titleCol = gtk_tree_view_get_column(GTK_TREE_VIEW(tracklist),
602 COL_TRACKTITLE );
603 gtk_tree_view_column_set_visible(titleCol, join_artist_title == JOIN_OFF);
604 }
605
606 void
on_edit_swap_clicked(void)607 on_edit_swap_clicked (void)
608 {
609 // "Swap Artist <=> Title"
610
611 GtkTreeIter iter;
612 GtkListStore * store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(lookup_widget(win_main, "tracklist"))));
613 if (store == NULL)
614 return;
615
616 gboolean rowsleft = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter);
617 while (rowsleft)
618 {
619 int riptrack;
620 char * trackartist = NULL;
621 char * tracktitle = NULL;
622
623 gtk_tree_model_get(GTK_TREE_MODEL(store), &iter,
624 COL_RIPTRACK, &riptrack,
625 COL_TRACKARTIST, &trackartist,
626 COL_TRACKTITLE, &tracktitle,
627 -1);
628
629 if (riptrack) // Only modify selected tracks
630 {
631 // Write swapped values back into widgets
632 gtk_list_store_set(store, &iter,
633 COL_TRACKARTIST, tracktitle,
634 COL_TRACKTITLE, trackartist,
635 -1);
636 }
637
638 if (trackartist)
639 free (trackartist);
640 if (tracktitle)
641 free (tracktitle);
642
643 rowsleft = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter);
644 }
645 }
646
647 void
on_press_f2(void)648 on_press_f2 (void)
649 {
650 GtkWidget* treeView;
651 GtkTreePath* treePath;
652 GtkTreeViewColumn* focusColumn;
653
654 treeView = lookup_widget(win_main, "tracklist");
655
656 if (!GTK_WIDGET_HAS_FOCUS(treeView))
657 return;
658
659 gtk_tree_view_get_cursor(GTK_TREE_VIEW(treeView), &treePath, &focusColumn);
660
661 if (treePath == NULL || focusColumn == NULL)
662 return;
663
664 gtk_tree_view_set_cursor(GTK_TREE_VIEW(treeView), treePath, focusColumn, TRUE);
665 }
666
667 void
on_lookup_clicked(GtkToolButton * toolbutton,gpointer user_data)668 on_lookup_clicked (GtkToolButton *toolbutton,
669 gpointer user_data)
670 {
671 /* i need to lock myself in refresh()->lookup_disc() */
672 /* another possible solution for this problem:
673 static GThread *main_thread = NULL;
674
675 void thread_helpers_init (void) {
676 main_thread = g_thread_self ();
677 }
678 gboolean thread_helpers_in_main_thread (void) {
679 return (main_thread == g_thread_self ());
680 }
681 void thread_helpers_lock_gdk (void) {
682 if (!thread_helpers_in_main_thread ()) gdk_threads_enter ();
683 }
684 void thread_helpers_unlock_gdk (void) {
685 if (!thread_helpers_in_main_thread ()) gdk_threads_leave ();
686 }
687 */
688 refresh();
689 }
690
691 void
on_rip_button_clicked(GtkButton * button,gpointer user_data)692 on_rip_button_clicked (GtkButton *button,
693 gpointer user_data)
694 {
695 GtkListStore * store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(lookup_widget(win_main, "tracklist"))));
696 if (store == NULL)
697 {
698 GtkWidget * dialog;
699 dialog = gtk_message_dialog_new(GTK_WINDOW(win_main),
700 GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
701 _("No CD is inserted. Please insert a CD into the CD-ROM drive."));
702 gtk_dialog_run(GTK_DIALOG(dialog));
703 gtk_widget_destroy(dialog);
704 return;
705 }
706
707 dorip();
708 }
709
710 void
on_rip_mp3_toggled(GtkToggleButton * togglebutton,gpointer user_data)711 on_rip_mp3_toggled (GtkToggleButton *togglebutton,
712 gpointer user_data)
713 {
714 if (gtk_toggle_button_get_active(togglebutton) && !program_exists("lame"))
715 {
716 GtkWidget * dialog;
717
718 dialog = gtk_message_dialog_new(GTK_WINDOW(win_main),
719 GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
720 _("%s was not found in your path. Asunder requires it to create %s files. "
721 "All %s functionality is disabled."),
722 "'lame'", "MP3", "MP3");
723 gtk_dialog_run(GTK_DIALOG(dialog));
724 gtk_widget_destroy(dialog);
725
726 global_prefs->rip_mp3 = 0;
727 gtk_toggle_button_set_active(togglebutton, global_prefs->rip_mp3);
728 }
729
730 if (!gtk_toggle_button_get_active(togglebutton))
731 disable_mp3_widgets();
732 else
733 enable_mp3_widgets();
734 }
735
736 void
on_rip_fdkaac_toggled(GtkToggleButton * togglebutton,gpointer user_data)737 on_rip_fdkaac_toggled (GtkToggleButton *togglebutton,
738 gpointer user_data)
739 {
740 if (gtk_toggle_button_get_active(togglebutton) && !program_exists("fdkaac"))
741 {
742 GtkWidget * dialog;
743
744 dialog = gtk_message_dialog_new(GTK_WINDOW(win_main),
745 GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
746 _("%s was not found in your path. Asunder requires it to create %s files. "
747 "All %s functionality is disabled."),
748 "'fdkaac'", "AAC", "AAC");
749 gtk_dialog_run(GTK_DIALOG(dialog));
750 gtk_widget_destroy(dialog);
751
752 global_prefs->rip_fdkaac = 0;
753 gtk_toggle_button_set_active(togglebutton, global_prefs->rip_fdkaac);
754 }
755
756 if (!gtk_toggle_button_get_active(togglebutton))
757 disable_fdkaac_widgets();
758 else
759 enable_fdkaac_widgets();
760 }
761
762 void
on_rip_flac_toggled(GtkToggleButton * togglebutton,gpointer user_data)763 on_rip_flac_toggled (GtkToggleButton *togglebutton,
764 gpointer user_data)
765 {
766 if (gtk_toggle_button_get_active(togglebutton) && !program_exists("flac"))
767 {
768 GtkWidget * dialog;
769 dialog = gtk_message_dialog_new(GTK_WINDOW(win_main),
770 GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
771 _("%s was not found in your path. Asunder requires it to create %s files. "
772 "All %s functionality is disabled."),
773 "'flac'", "FLAC", "FLAC");
774 gtk_dialog_run(GTK_DIALOG(dialog));
775 gtk_widget_destroy(dialog);
776
777 global_prefs->rip_flac = 0;
778 gtk_toggle_button_set_active(togglebutton, global_prefs->rip_flac);
779 }
780
781 if (!gtk_toggle_button_get_active(togglebutton))
782 disable_flac_widgets();
783 else
784 enable_flac_widgets();
785 }
786
787 void
on_rip_ogg_toggled(GtkToggleButton * togglebutton,gpointer user_data)788 on_rip_ogg_toggled (GtkToggleButton *togglebutton,
789 gpointer user_data)
790 {
791 if (gtk_toggle_button_get_active(togglebutton) && !program_exists("oggenc"))
792 {
793 GtkWidget * dialog;
794 dialog = gtk_message_dialog_new(GTK_WINDOW(win_main),
795 GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
796 _("%s was not found in your path. Asunder requires it to create %s files. "
797 "All %s functionality is disabled."),
798 "'oggenc'", "OGG", "OGG");
799 gtk_dialog_run(GTK_DIALOG(dialog));
800 gtk_widget_destroy(dialog);
801
802 global_prefs->rip_ogg = 0;
803 gtk_toggle_button_set_active(togglebutton, global_prefs->rip_ogg);
804 }
805
806 if (!gtk_toggle_button_get_active(togglebutton))
807 disable_ogg_widgets();
808 else
809 enable_ogg_widgets();
810 }
811
812 void
on_rip_opus_toggled(GtkToggleButton * togglebutton,gpointer user_data)813 on_rip_opus_toggled (GtkToggleButton *togglebutton,
814 gpointer user_data)
815 {
816 if (gtk_toggle_button_get_active(togglebutton) && !program_exists("opusenc"))
817 {
818 GtkWidget *dialog;
819 dialog = gtk_message_dialog_new(GTK_WINDOW(win_main),
820 GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
821 _("%s was not found in your path. Asunder requires it to create %s files. "
822 "All %s functionality is disabled."),
823 "'opusenc'", "OPUS", "opus");
824 gtk_dialog_run (GTK_DIALOG(dialog));
825 gtk_widget_destroy(dialog);
826
827 global_prefs->rip_opus=0;
828 gtk_toggle_button_set_active(togglebutton, global_prefs->rip_opus);
829
830 }
831
832 if (!gtk_toggle_button_get_active(togglebutton))
833 disable_opus_widgets();
834 else
835 enable_opus_widgets();
836 }
837
838 void
on_rip_wavpack_toggled(GtkToggleButton * togglebutton,gpointer user_data)839 on_rip_wavpack_toggled (GtkToggleButton *togglebutton,
840 gpointer user_data)
841 {
842 if (gtk_toggle_button_get_active(togglebutton) && !program_exists("wavpack"))
843 {
844 GtkWidget * dialog;
845 dialog = gtk_message_dialog_new(GTK_WINDOW(win_main),
846 GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
847 _("%s was not found in your path. Asunder requires it to create %s files. "
848 "All %s functionality is disabled."),
849 "'wavpack'", "WV", "wavpack");
850 gtk_dialog_run(GTK_DIALOG(dialog));
851 gtk_widget_destroy(dialog);
852
853 global_prefs->rip_wavpack = 0;
854 gtk_toggle_button_set_active(togglebutton, global_prefs->rip_wavpack);
855 }
856
857 if (!gtk_toggle_button_get_active(togglebutton))
858 disable_wavpack_widgets();
859 else
860 enable_wavpack_widgets();
861 }
862
863 void
on_rip_monkey_toggled(GtkToggleButton * togglebutton,gpointer user_data)864 on_rip_monkey_toggled (GtkToggleButton *togglebutton,
865 gpointer user_data)
866 {
867 if (gtk_toggle_button_get_active(togglebutton) && !program_exists("mac"))
868 {
869 GtkWidget * dialog;
870 dialog = gtk_message_dialog_new(GTK_WINDOW(win_main),
871 GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
872 _("%s was not found in your path. Asunder requires it to create %s files. "
873 "All %s functionality is disabled."),
874 "'mac'", "APE", "Monkey's Audio");
875 gtk_dialog_run(GTK_DIALOG(dialog));
876 gtk_widget_destroy(dialog);
877
878 global_prefs->rip_monkey = 0;
879 gtk_toggle_button_set_active(togglebutton, global_prefs->rip_monkey);
880 }
881
882 if (!gtk_toggle_button_get_active(togglebutton))
883 disable_monkey_widgets();
884 else
885 enable_monkey_widgets();
886 }
887
888 void
on_rip_musepack_toggled(GtkToggleButton * togglebutton,gpointer user_data)889 on_rip_musepack_toggled (GtkToggleButton *togglebutton,
890 gpointer user_data)
891 {
892 if (gtk_toggle_button_get_active(togglebutton) && !program_exists("mpcenc"))
893 {
894 GtkWidget * dialog;
895 dialog = gtk_message_dialog_new(GTK_WINDOW(win_main),
896 GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
897 _("%s was not found in your path. Asunder requires it to create %s files. "
898 "All %s functionality is disabled."),
899 "'mpcenc'", "MPC", "Musepack");
900 gtk_dialog_run(GTK_DIALOG(dialog));
901 gtk_widget_destroy(dialog);
902
903 global_prefs->rip_musepack = 0;
904 gtk_toggle_button_set_active(togglebutton, global_prefs->rip_musepack);
905 }
906
907 if (!gtk_toggle_button_get_active(togglebutton))
908 disable_musepack_widgets();
909 else
910 enable_musepack_widgets();
911 }
912
913 void
on_rip_toggled(GtkCellRendererToggle * cell,gchar * path_string,gpointer user_data)914 on_rip_toggled (GtkCellRendererToggle *cell,
915 gchar *path_string,
916 gpointer user_data)
917 {
918 GtkListStore * store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(lookup_widget(win_main, "tracklist"))));
919 GtkTreeIter iter;
920 int toggled;
921
922 gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(store), &iter, path_string);
923 gtk_tree_model_get(GTK_TREE_MODEL(store), &iter,
924 COL_RIPTRACK, &toggled,
925 -1);
926 gtk_list_store_set(store, &iter,
927 COL_RIPTRACK, !toggled,
928 -1);
929 }
930
931 void
on_select_all_click(GtkMenuItem * menuitem,gpointer data)932 on_select_all_click (GtkMenuItem *menuitem,
933 gpointer data)
934 {
935 GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(lookup_widget(win_main, "tracklist")));
936
937 gtk_tree_model_foreach(model, for_each_row_select, NULL);
938 }
939
940 void
on_single_artist_toggled(GtkToggleButton * togglebutton,gpointer user_data)941 on_single_artist_toggled (GtkToggleButton *togglebutton,
942 gpointer user_data)
943 {
944 GtkTreeViewColumn * artistCol = gtk_tree_view_get_column(GTK_TREE_VIEW(tracklist),
945 COL_TRACKARTIST ); //lnr
946 gtk_tree_view_column_set_visible(artistCol,
947 !gtk_toggle_button_get_active(togglebutton));
948 }
949
950 // lnr
951 void
on_title_edited(GtkCellRendererText * cell,gchar * path_string,gchar * new_text,gpointer user_data)952 on_title_edited (GtkCellRendererText *cell,
953 gchar *path_string,
954 gchar *new_text,
955 gpointer user_data)
956 {
957 GtkListStore * store = GTK_LIST_STORE(gtk_tree_view_get_model(
958 GTK_TREE_VIEW(lookup_widget(win_main, "tracklist"))));
959 GtkTreeIter iter;
960
961 //trim_chars(new_text, BADCHARS); // lnr //Commented out by mrpl
962 trim_whitespace(new_text);
963
964 gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(store), &iter, path_string);
965
966 if(new_text[0] == '\0')
967 gtk_list_store_set(store, &iter, COL_TRACKTITLE, "unknown", -1);
968 else
969 gtk_list_store_set(store, &iter, COL_TRACKTITLE, new_text, -1);
970
971
972 }
973
974 gboolean
on_tracklist_mouse_click(GtkWidget * treeView,GdkEventButton * event,gpointer user_data)975 on_tracklist_mouse_click (GtkWidget* treeView,
976 GdkEventButton* event,
977 gpointer user_data)
978 {
979 if( event->type == GDK_BUTTON_PRESS && event->button == 3 &&
980 GTK_WIDGET_SENSITIVE(lookup_widget(win_main, "rip_button")) )
981 {
982 GtkWidget* menu;
983 GtkWidget* menuItem;
984
985 menu = gtk_menu_new();
986
987 menuItem = gtk_menu_item_new_with_label(_("Select all for ripping"));
988 g_signal_connect(menuItem, "activate",
989 G_CALLBACK(on_select_all_click), NULL);
990 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuItem);
991 gtk_widget_show_all(menu);
992
993 menuItem = gtk_menu_item_new_with_label(_("Deselect all for ripping"));
994 g_signal_connect(menuItem, "activate",
995 G_CALLBACK(on_deselect_all_click), NULL);
996 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuItem);
997 gtk_widget_show_all(menu);
998
999 menuItem = gtk_menu_item_new_with_label(_("Capitalize Artists & Titles"));
1000 g_signal_connect(menuItem, "activate",
1001 G_CALLBACK(on_edit_capitalize_clicked), NULL);
1002 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuItem);
1003 gtk_widget_show_all(menu);
1004
1005 const char splitTemplate[] = "Split 'Artist%cTitle' in Title field";
1006 char splitLabel[sizeof(splitTemplate)];
1007 sprintf(splitLabel, splitTemplate, global_prefs->concatenated_track_separator[0]);
1008
1009 if(join_artist_title == JOIN_UNSET)
1010 {
1011 menuItem = gtk_menu_item_new_with_label(_(splitLabel));
1012 g_signal_connect(menuItem, "activate",
1013 G_CALLBACK(on_edit_split_clicked), NULL);
1014 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuItem);
1015 gtk_widget_show_all(menu);
1016 }
1017
1018 const char joinTemplate[] = "Join 'Artist%cTitle' in Title field";
1019 char joinLabel[sizeof(joinTemplate)];
1020 sprintf(joinLabel, joinTemplate, global_prefs->concatenated_track_separator[0]);
1021
1022 menuItem = gtk_menu_item_new_with_label(_(
1023 join_artist_title == JOIN_ON ? splitLabel : joinLabel));
1024 g_signal_connect(menuItem, "activate",
1025 G_CALLBACK(toggle_joined_title_artist), NULL);
1026 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuItem);
1027 gtk_widget_show_all(menu);
1028
1029 menuItem = gtk_menu_item_new_with_label(_("Swap Artist <=> Title"));
1030 g_signal_connect(menuItem, "activate",
1031 G_CALLBACK(on_edit_swap_clicked), NULL);
1032 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuItem);
1033 gtk_widget_show_all(menu);
1034
1035 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
1036 event->button, gdk_event_get_time((GdkEvent*)event));
1037
1038 /* no need for signal to propagate */
1039 return TRUE;
1040 }
1041
1042 return FALSE;
1043 }
1044
1045 void
on_rip_header_click(GtkTreeViewColumn * treeviewcolumn,gpointer user_data)1046 on_rip_header_click (GtkTreeViewColumn *treeviewcolumn,
1047 gpointer user_data)
1048 {
1049 // Select/Deselect all tracks.
1050 // Get first checkbox and set all to opposite value.
1051 GtkTreeIter iter;
1052 int riptrack;
1053 GtkTreeModel * model = gtk_tree_view_get_model(
1054 GTK_TREE_VIEW(lookup_widget(win_main, "tracklist")));
1055
1056 if (!gtk_tree_model_get_iter_first(model, &iter))
1057 return;
1058 gtk_tree_model_get(model, &iter, COL_RIPTRACK, &riptrack, -1);
1059
1060 if (riptrack)
1061 gtk_tree_model_foreach(model, for_each_row_deselect, NULL);
1062 else
1063 gtk_tree_model_foreach(model, for_each_row_select, NULL);
1064 }
1065
1066 void
on_window_close(GtkWidget * widget,GdkEventFocus * event,gpointer user_data)1067 on_window_close (GtkWidget *widget,
1068 GdkEventFocus *event,
1069 gpointer user_data)
1070 {
1071 gtk_window_get_size(GTK_WINDOW(win_main),
1072 &global_prefs->main_window_width,
1073 &global_prefs->main_window_height);
1074
1075 save_prefs(global_prefs);
1076
1077 gtk_main_quit();
1078 }
1079