1 /* -*- linux-c -*-
2 Copyright (C) 2004 Tom Szilagyi
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 $Id: cddb_lookup.c 1287 2014-04-27 20:51:08Z tszilagyi $
19 */
20
21 #include <config.h>
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <glib.h>
27 #include <glib-object.h>
28 #include <gdk/gdk.h>
29 #include <gtk/gtk.h>
30 #include <cddb/cddb.h>
31
32 #ifdef HAVE_CDDA
33 #include "cdda.h"
34 #include "store_cdda.h"
35 #endif /* HAVE_CDDA */
36
37 #include "athread.h"
38 #include "common.h"
39 #include "utils.h"
40 #include "utils_gui.h"
41 #include "i18n.h"
42 #include "options.h"
43 #include "music_browser.h"
44 #include "store_file.h"
45 #include "cddb_lookup.h"
46
47
48 extern options_t options;
49
50 extern GtkWidget * browser_window;
51 extern GtkTreeStore * music_store;
52
53
54 enum {
55 CASE_UP,
56 CASE_DOWN
57 };
58
59 enum {
60 CDDB_INIT,
61 CDDB_BUSY,
62 CDDB_SUCCESS,
63 CDDB_ERROR,
64 CDDB_NO_MATCH,
65 CDDB_ABORTED
66 };
67
68 enum {
69 CDDB_TYPE_QUERY,
70 CDDB_TYPE_SUBMIT,
71 CDDB_TYPE_SUBMIT_NEW
72 };
73
74 typedef struct {
75
76 AQUALUNG_THREAD_DECLARE(thread_id);
77 AQUALUNG_MUTEX_DECLARE(mutex);
78
79 int state;
80 int type;
81
82 int ntracks;
83 int * frames;
84 int record_length;
85
86 cddb_disc_t ** records;
87 int nrecords;
88
89 int counter;
90 int aborted;
91
92 GtkTreeIter iter_record;
93
94 GtkWidget * progress_win;
95 GtkWidget * progress_label;
96 GtkWidget * progbar;
97
98 GtkWidget * combo;
99
100 GtkWidget * artist_entry;
101 GtkWidget * title_entry;
102 GtkWidget * year_spinner;
103 GtkWidget * category_entry;
104 GtkWidget * category_combo;
105 GtkWidget * genre_entry;
106 GtkWidget * ext_entry;
107 GtkWidget * track_list;
108 GtkListStore * track_store;
109
110 GtkWidget * year_import_button;
111 GtkWidget * title_import_button;
112
113 int year_imported;
114 int title_imported;
115
116 } cddb_lookup_t;
117
118
119 void cddb_dialog(cddb_lookup_t * data);
120 void cddb_dialog_load_disc(cddb_lookup_t * data, cddb_disc_t * disc);
121
122
123 const char *
notnull(const char * str)124 notnull(const char * str) {
125
126 return str ? str : "";
127 }
128
129 cddb_lookup_t *
cddb_lookup_new()130 cddb_lookup_new () {
131
132 cddb_lookup_t * data;
133
134 if ((data = calloc(1, sizeof(cddb_lookup_t))) == NULL) {
135 fprintf(stderr, "cddb_lookup_new: calloc error\n");
136 return NULL;
137 }
138
139 #ifndef HAVE_LIBPTHREAD
140 data->mutex = g_mutex_new();
141 #endif /* !HAVE_LIBPTHREAD */
142
143 data->state = CDDB_INIT;
144
145 return data;
146 }
147
148 void
cddb_lookup_set_state(cddb_lookup_t * data,int state)149 cddb_lookup_set_state(cddb_lookup_t * data, int state) {
150
151 AQUALUNG_MUTEX_LOCK(data->mutex);
152 data->state = state;
153 AQUALUNG_MUTEX_UNLOCK(data->mutex);
154 }
155
156 int
cddb_lookup_get_state(cddb_lookup_t * data)157 cddb_lookup_get_state(cddb_lookup_t * data) {
158
159 int state;
160
161 AQUALUNG_MUTEX_LOCK(data->mutex);
162 state = data->state;
163 AQUALUNG_MUTEX_UNLOCK(data->mutex);
164
165 return state;
166 }
167
168 void
cddb_lookup_free(cddb_lookup_t * data)169 cddb_lookup_free(cddb_lookup_t * data) {
170
171 if (data->records != NULL) {
172 int i;
173 for (i = 0; i < data->nrecords; i++) {
174 if (data->records[i] != NULL) {
175 cddb_disc_destroy(data->records[i]);
176 }
177 }
178 free(data->records);
179 }
180
181 if (data->frames != NULL) {
182 free(data->frames);
183 }
184
185 #ifndef HAVE_LIBPTHREAD
186 g_mutex_free(data->mutex);
187 #endif /* !HAVE_LIBPTHREAD */
188
189 free(data);
190 }
191
192
193 int
cddb_connection_setup(cddb_conn_t ** conn)194 cddb_connection_setup(cddb_conn_t ** conn) {
195
196 if ((*conn = cddb_new()) == NULL) {
197 fprintf(stderr, "cddb_lookup.c: cddb_connection_setup(): cddb_new error\n");
198 return 1;
199 }
200
201 cddb_set_server_name(*conn, options.cddb_server);
202 cddb_set_timeout(*conn, options.cddb_timeout);
203 cddb_set_charset(*conn, "UTF-8");
204
205 if (options.cddb_local[0] != '\0') {
206 cddb_cache_set_dir(*conn, options.cddb_local);
207 }
208
209 if (options.cddb_cache_only) {
210 cddb_cache_only(*conn);
211 }
212
213 if (options.inet_use_proxy) {
214 cddb_http_enable(*conn);
215 cddb_set_server_port(*conn, 80);
216 cddb_http_proxy_enable(*conn);
217 cddb_set_http_proxy_server_name(*conn, options.inet_proxy);
218 cddb_set_http_proxy_server_port(*conn, options.inet_proxy_port);
219 } else {
220 cddb_http_proxy_disable(*conn);
221 if (options.cddb_use_http) {
222 cddb_http_enable(*conn);
223 cddb_set_server_port(*conn, 80);
224 } else {
225 cddb_http_disable(*conn);
226 cddb_set_server_port(*conn, 888);
227 }
228 }
229
230 return 0;
231 }
232
233 void
cddb_lookup(cddb_lookup_t * data)234 cddb_lookup(cddb_lookup_t * data) {
235
236 cddb_conn_t * conn = NULL;
237 cddb_disc_t * disc = NULL;
238 cddb_track_t * track = NULL;
239
240 int i;
241
242 if (cddb_connection_setup(&conn) == 1) {
243 cddb_lookup_set_state(data, CDDB_ERROR);
244 return;
245 }
246
247 if ((disc = cddb_disc_new()) == NULL) {
248 fprintf(stderr, "cddb_lookup(): cddb_disc_new error\n");
249 cddb_lookup_set_state(data, CDDB_ERROR);
250 return;
251 }
252
253 cddb_disc_set_length(disc, data->record_length);
254
255 for (i = 0; i < data->ntracks; i++) {
256 track = cddb_track_new();
257 cddb_track_set_frame_offset(track, data->frames[i]);
258 cddb_disc_add_track(disc, track);
259 }
260
261 data->nrecords = cddb_query(conn, disc);
262
263 if (data->nrecords <= 0) {
264 cddb_destroy(conn);
265 cddb_disc_destroy(disc);
266 cddb_lookup_set_state(data, (data->nrecords == 0) ? CDDB_NO_MATCH : CDDB_ERROR);
267 return;
268 }
269
270 cddb_lookup_set_state(data, CDDB_BUSY);
271
272 if ((data->records = (cddb_disc_t **)calloc(data->nrecords, sizeof(cddb_disc_t *))) == NULL) {
273 fprintf(stderr, "cddb_lookup(): malloc error\n");
274 cddb_lookup_set_state(data, CDDB_ERROR);
275 return;
276 }
277
278 for (i = 0; i < data->nrecords; i++) {
279
280 if (cddb_lookup_get_state(data) == CDDB_ABORTED) {
281 break;
282 }
283
284 if (i > 0 && !cddb_query_next(conn, disc)) {
285 break;
286 }
287 cddb_read(conn, disc);
288 data->records[i] = cddb_disc_clone(disc);
289
290 AQUALUNG_MUTEX_LOCK(data->mutex);
291 data->counter++;
292 AQUALUNG_MUTEX_UNLOCK(data->mutex);
293 }
294
295 cddb_destroy(conn);
296 cddb_disc_destroy(disc);
297
298 if (cddb_lookup_get_state(data) == CDDB_ABORTED) {
299 cddb_lookup_free(data);
300 return;
301 }
302
303 cddb_lookup_set_state(data, CDDB_SUCCESS);
304 }
305
306
307 static void
abort_cb(GtkWidget * widget,gpointer user_data)308 abort_cb(GtkWidget * widget, gpointer user_data) {
309
310 cddb_lookup_set_state((cddb_lookup_t *)user_data, CDDB_ABORTED);
311 }
312
313
314 void
create_query_progress_window(cddb_lookup_t * data)315 create_query_progress_window(cddb_lookup_t * data) {
316
317 GtkWidget * vbox;
318 GtkWidget * hbuttonbox;
319 GtkWidget * hseparator;
320 GtkWidget * abort_button;
321
322
323 data->progress_win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
324 gtk_window_set_title(GTK_WINDOW(data->progress_win), _("CDDB query"));
325 gtk_window_set_position(GTK_WINDOW(data->progress_win), GTK_WIN_POS_CENTER);
326 gtk_window_resize(GTK_WINDOW(data->progress_win), 330, 120);
327 g_signal_connect(G_OBJECT(data->progress_win), "delete_event",
328 G_CALLBACK(abort_cb), data);
329 gtk_container_set_border_width(GTK_CONTAINER(data->progress_win), 10);
330
331 vbox = gtk_vbox_new(FALSE, 0);
332 gtk_container_add(GTK_CONTAINER(data->progress_win), vbox);
333
334 data->progress_label = gtk_label_new(_("Retrieving matches from server..."));
335 gtk_box_pack_start(GTK_BOX(vbox), data->progress_label, FALSE, FALSE, 0);
336
337 data->progbar = gtk_progress_bar_new();
338 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(data->progbar), _("Connecting to CDDB server..."));
339 gtk_box_pack_start(GTK_BOX(vbox), data->progbar, FALSE, FALSE, 6);
340
341 hseparator = gtk_hseparator_new ();
342 gtk_widget_show (hseparator);
343 gtk_box_pack_start (GTK_BOX (vbox), hseparator, FALSE, TRUE, 5);
344
345 hbuttonbox = gtk_hbutton_box_new();
346 gtk_box_pack_end(GTK_BOX(vbox), hbuttonbox, FALSE, TRUE, 0);
347 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbuttonbox), GTK_BUTTONBOX_END);
348
349 abort_button = gui_stock_label_button(_("Abort"), GTK_STOCK_CANCEL);
350 g_signal_connect(G_OBJECT(abort_button), "clicked",
351 G_CALLBACK(abort_cb), data);
352 gtk_container_add(GTK_CONTAINER(hbuttonbox), abort_button);
353
354 gtk_widget_grab_focus(abort_button);
355
356 gtk_widget_show_all(data->progress_win);
357 }
358
359
360 #ifdef HAVE_CDDA
361 void
store_cdda_export_merged(cddb_lookup_t * data,char * artist,char * record,char * genre,int year,char ** tracks)362 store_cdda_export_merged(cddb_lookup_t * data, char * artist, char * record, char * genre, int year, char ** tracks) {
363
364 int i;
365 GtkTreeIter iter;
366
367 char name[MAXLEN];
368 cdda_drive_t * drive;
369
370 for (i = 0; gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(music_store),
371 &iter, &data->iter_record, i); i++) {
372
373 gtk_tree_store_set(music_store, &iter, MS_COL_NAME, tracks[i], -1);
374 }
375
376 gtk_tree_model_get(GTK_TREE_MODEL(music_store), &data->iter_record, MS_COL_DATA, &drive, -1);
377
378 strncpy(drive->disc.artist_name, artist, MAXLEN-1);
379 strncpy(drive->disc.record_name, record, MAXLEN-1);
380 strncpy(drive->disc.genre, genre, MAXLEN-1);
381 drive->disc.year = year;
382
383 snprintf(name, MAXLEN-1, "%s: %s",
384 drive->disc.artist_name,
385 drive->disc.record_name);
386
387 gtk_tree_store_set(music_store, &data->iter_record, MS_COL_NAME, name, -1);
388
389 music_store_selection_changed(STORE_TYPE_CDDA);
390 }
391 #endif /* HAVE_CDDA */
392
393
394 void
cddb_lookup_merge(cddb_lookup_t * data,char * artist,char * record,char * genre,int * year,char ** tracks)395 cddb_lookup_merge(cddb_lookup_t * data, char * artist, char * record, char * genre, int * year, char ** tracks) {
396
397 int i, j, y;
398
399 map_t * map_artist = NULL;
400 map_t * map_record = NULL;
401 map_t * map_genre = NULL;
402 map_t * map_year = NULL;
403 map_t ** map_tracks = NULL;
404
405 char tmp[MAXLEN];
406
407
408 if ((map_tracks = (map_t **)calloc(data->ntracks, sizeof(map_t *))) == NULL) {
409 fprintf(stderr, "cddb_lookup_merge: calloc error\n");
410 return;
411 }
412
413 for (i = 0; i < data->nrecords; i++) {
414
415 strncpy(tmp, notnull(cddb_disc_get_artist(data->records[i])), MAXLEN-1);
416 if (!is_all_wspace(tmp)) {
417 map_put(&map_artist, tmp);
418 }
419
420 strncpy(tmp, notnull(cddb_disc_get_title(data->records[i])), MAXLEN-1);
421 if (!is_all_wspace(tmp)) {
422 map_put(&map_record, tmp);
423 }
424
425 if (genre != NULL) {
426 strncpy(tmp, notnull(cddb_disc_get_genre(data->records[i])), MAXLEN-1);
427 if (!is_all_wspace(tmp)) {
428 map_put(&map_genre, tmp);
429 }
430 }
431
432 y = cddb_disc_get_year(data->records[i]);
433 if (is_valid_year(y)) {
434 snprintf(tmp, MAXLEN-1, "%d", y);
435 map_put(&map_year, tmp);
436 }
437
438 for (j = 0; j < data->ntracks; j++) {
439 strncpy(tmp,
440 notnull(cddb_track_get_title(cddb_disc_get_track(data->records[i], j))),
441 MAXLEN-1);
442 if (!is_all_wspace(tmp)) {
443 map_put(map_tracks + j, tmp);
444 }
445 }
446 }
447
448 if (map_artist) {
449 strncpy(artist, map_get_max(map_artist), MAXLEN-1);
450 }
451
452 if (map_record) {
453 strncpy(record, map_get_max(map_record), MAXLEN-1);
454 }
455
456 if (map_genre) {
457 strncpy(genre, map_get_max(map_genre), MAXLEN-1);
458 }
459
460 if (map_year) {
461 *year = atoi(map_get_max(map_year));
462 }
463
464 for (j = 0; j < data->ntracks; j++) {
465
466 if (map_tracks[j]) {
467 strncpy(tracks[j], map_get_max(map_tracks[j]), MAXLEN-1);
468 map_free(map_tracks[j]);
469 }
470 }
471
472 map_free(map_artist);
473 map_free(map_record);
474 map_free(map_genre);
475 map_free(map_year);
476 free(map_tracks);
477 }
478
479 gboolean
query_timeout_cb(gpointer user_data)480 query_timeout_cb(gpointer user_data) {
481
482 cddb_lookup_t * data = (cddb_lookup_t *)user_data;
483 int state = cddb_lookup_get_state(data);
484 char text[MAXLEN];
485
486 switch (state) {
487 case CDDB_INIT:
488 return TRUE;
489 case CDDB_BUSY:
490 snprintf(text, MAXLEN, "%d / %d", data->counter, data->nrecords);
491 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(data->progbar),
492 (double)data->counter / data->nrecords);
493 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(data->progbar), text);
494 return TRUE;
495 case CDDB_SUCCESS:
496 gtk_widget_destroy(data->progress_win);
497 cddb_dialog(data);
498 break;
499 case CDDB_ERROR:
500 gtk_widget_destroy(data->progress_win);
501 message_dialog(_("Error"),
502 browser_window,
503 GTK_MESSAGE_ERROR,
504 GTK_BUTTONS_OK,
505 NULL,
506 _("An error occurred while attempting "
507 "to connect to the CDDB server."));
508 break;
509 case CDDB_NO_MATCH:
510 gtk_widget_destroy(data->progress_win);
511 if (data->type == CDDB_TYPE_QUERY) {
512 message_dialog(_("Warning"),
513 browser_window,
514 GTK_MESSAGE_WARNING,
515 GTK_BUTTONS_OK,
516 NULL,
517 _("No matching record found."));
518 } else {
519 data->type = CDDB_TYPE_SUBMIT_NEW;
520 cddb_dialog(data);
521 }
522 break;
523 case CDDB_ABORTED:
524 gtk_widget_destroy(data->progress_win);
525 return FALSE;
526 }
527
528 cddb_lookup_free(data);
529
530 return FALSE;
531 }
532
533
534 #ifdef HAVE_CDDA
535 gboolean
cdda_auto_query_timeout_cb(gpointer user_data)536 cdda_auto_query_timeout_cb(gpointer user_data) {
537
538 cddb_lookup_t * data = (cddb_lookup_t *)user_data;
539 int state = cddb_lookup_get_state(data);
540
541 if (state == CDDB_INIT || state == CDDB_BUSY) {
542 return TRUE;
543 }
544
545 if (state == CDDB_SUCCESS) {
546 char artist[MAXLEN];
547 char record[MAXLEN];
548 char genre[MAXLEN];
549 int year = 0;
550 char ** tracks;
551 int i;
552
553 artist[0] = '\0';
554 record[0] = '\0';
555 genre[0] = '\0';
556
557 if ((tracks = calloc(data->ntracks, sizeof(char *))) == NULL) {
558 fprintf(stderr, "cdda_auto_query_timeout_cb(): calloc error\n");
559 return FALSE;
560 }
561
562 for (i = 0; i < data->ntracks; i++) {
563 if ((tracks[i] = calloc(1, MAXLEN * sizeof(char))) == NULL) {
564 fprintf(stderr, "cdda_auto_query_timeout_cb(): calloc error\n");
565 return FALSE;
566 }
567 }
568
569 cddb_lookup_merge(data, artist, record, genre, &year, tracks);
570 store_cdda_export_merged(data, artist, record, genre, year, tracks);
571
572 for (i = 0; i < data->ntracks; i++) {
573 free(tracks[i]);
574 }
575 free(tracks);
576 }
577
578 if (options.cdda_add_to_playlist) {
579 cdda_drive_t * drive;
580 gtk_tree_model_get(GTK_TREE_MODEL(music_store), &data->iter_record,
581 MS_COL_DATA, &drive, -1);
582 cdda_add_to_playlist(&data->iter_record, drive->disc.hash);
583 }
584
585 cddb_lookup_free(data);
586
587 return FALSE;
588 }
589 #endif /* HAVE_CDDA */
590
591
592 static void
add_to_comments(cddb_lookup_t * data,GtkWidget * entry)593 add_to_comments(cddb_lookup_t * data, GtkWidget * entry) {
594
595 record_data_t * record_data;
596
597 gtk_tree_model_get(GTK_TREE_MODEL(music_store), &data->iter_record, MS_COL_DATA, &record_data, -1);
598
599 if (record_data->comment != NULL && record_data->comment[0] != '\0') {
600 char comment[MAXLEN];
601 snprintf(comment, MAXLEN-1, "%s\n%s",
602 record_data->comment,
603 gtk_entry_get_text(GTK_ENTRY(entry)));
604 free_strdup(&record_data->comment, comment);
605 } else {
606 free_strdup(&record_data->comment, gtk_entry_get_text(GTK_ENTRY(entry)));
607 }
608
609 music_store_mark_changed(&data->iter_record);
610 }
611
612 static void
add_category_to_comments(GtkWidget * widget,gpointer user_data)613 add_category_to_comments(GtkWidget * widget, gpointer user_data) {
614
615 cddb_lookup_t * data = (cddb_lookup_t *)user_data;
616 add_to_comments(data, data->category_entry);
617 }
618
619 static void
add_genre_to_comments(GtkWidget * widget,gpointer user_data)620 add_genre_to_comments(GtkWidget * widget, gpointer user_data) {
621
622 cddb_lookup_t * data = (cddb_lookup_t *)user_data;
623 add_to_comments(data, data->genre_entry);
624 }
625
626 static void
add_ext_to_comments(GtkWidget * widget,gpointer user_data)627 add_ext_to_comments(GtkWidget * widget, gpointer user_data) {
628
629 cddb_lookup_t * data = (cddb_lookup_t *)user_data;
630 add_to_comments(data, data->ext_entry);
631 }
632
633 static void
import_as_artist(GtkWidget * widget,gpointer user_data)634 import_as_artist(GtkWidget * widget, gpointer user_data) {
635
636 GtkTreeIter parent;
637 GtkTreePath * path;
638 cddb_lookup_t * data = (cddb_lookup_t *)user_data;
639
640 path = gtk_tree_model_get_path(GTK_TREE_MODEL(music_store), &data->iter_record);
641 gtk_tree_path_up(path);
642 gtk_tree_model_get_iter(GTK_TREE_MODEL(music_store), &parent, path);
643 gtk_tree_path_free(path);
644 gtk_tree_store_set(music_store, &parent,
645 MS_COL_NAME, gtk_entry_get_text(GTK_ENTRY(data->artist_entry)), -1);
646
647 music_store_mark_changed(&parent);
648 }
649
650
651 static void
import_as_title(GtkWidget * widget,gpointer user_data)652 import_as_title(GtkWidget * widget, gpointer user_data) {
653
654 cddb_lookup_t * data = (cddb_lookup_t *)user_data;
655
656 if (data->title_imported) {
657 gtk_tree_store_set(music_store, &data->iter_record,
658 MS_COL_SORT, gtk_entry_get_text(GTK_ENTRY(data->title_entry)), -1);
659 } else {
660 gtk_tree_store_set(music_store, &data->iter_record,
661 MS_COL_NAME, gtk_entry_get_text(GTK_ENTRY(data->title_entry)), -1);
662
663 data->title_imported = 1;
664 gtk_button_set_label(GTK_BUTTON(data->title_import_button), _("Import as Sort Key"));
665 }
666
667 music_store_mark_changed(&data->iter_record);
668 }
669
670 static void
import_as_year(GtkWidget * widget,gpointer user_data)671 import_as_year(GtkWidget * widget, gpointer user_data) {
672
673 cddb_lookup_t * data = (cddb_lookup_t *)user_data;
674 int year = gtk_spin_button_get_value(GTK_SPIN_BUTTON(data->year_spinner));
675
676 if (data->year_imported) {
677 char buf[16];
678 snprintf(buf, 15, "%d", year);
679 gtk_tree_store_set(music_store, &data->iter_record, MS_COL_SORT, buf, -1);
680 } else {
681 record_data_t * record_data;
682 gtk_tree_model_get(GTK_TREE_MODEL(music_store), &data->iter_record,
683 MS_COL_DATA, &record_data, -1);
684 record_data->year = year;
685
686 data->year_imported = 1;
687 gtk_button_set_label(GTK_BUTTON(data->year_import_button), _("Import as Sort Key"));
688 }
689
690
691 music_store_mark_changed(&data->iter_record);
692 }
693
694 gboolean
title_entry_focused(GtkWidget * widget,GdkEventFocus * event,gpointer user_data)695 title_entry_focused(GtkWidget * widget, GdkEventFocus * event, gpointer user_data) {
696
697 cddb_lookup_t * data = (cddb_lookup_t *)user_data;
698
699 data->title_imported = 0;
700 gtk_button_set_label(GTK_BUTTON(data->title_import_button), _("Import as Title"));
701
702 return FALSE;
703 }
704
705 gboolean
year_spinner_focused(GtkWidget * widget,GdkEventFocus * event,gpointer user_data)706 year_spinner_focused(GtkWidget * widget, GdkEventFocus * event, gpointer user_data) {
707
708 cddb_lookup_t * data = (cddb_lookup_t *)user_data;
709
710 data->year_imported = 0;
711 gtk_button_set_label(GTK_BUTTON(data->year_import_button), _("Import as Year"));
712
713 return FALSE;
714 }
715
716
717 static void
changed_combo(GtkWidget * widget,gpointer * user_data)718 changed_combo(GtkWidget * widget, gpointer * user_data) {
719
720 cddb_lookup_t * data = (cddb_lookup_t *)user_data;
721 int i = gtk_combo_box_get_active(GTK_COMBO_BOX(data->combo));
722
723 if (i >= 0 && i < data->nrecords) {
724 cddb_dialog_load_disc(data, data->records[i]);
725 }
726
727 if (data->type == CDDB_TYPE_QUERY && iter_get_store_type(&data->iter_record) == STORE_TYPE_FILE) {
728 title_entry_focused(data->title_entry, NULL, user_data);
729 year_spinner_focused(data->year_spinner, NULL, user_data);
730 }
731 }
732
733
734 static void
cell_edited_callback(GtkCellRendererText * cell,gchar * path,gchar * text,gpointer user_data)735 cell_edited_callback(GtkCellRendererText * cell, gchar * path, gchar * text, gpointer user_data) {
736
737 cddb_lookup_t * data = (cddb_lookup_t *)user_data;
738 GtkTreeIter iter;
739
740 if (gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(data->track_store), &iter, path)) {
741 gtk_list_store_set(data->track_store, &iter, 0, text, -1);
742 }
743 }
744
745
746 gboolean
create_cddb_write_error_dialog(gpointer data)747 create_cddb_write_error_dialog(gpointer data) {
748
749 message_dialog(_("Error"),
750 browser_window,
751 GTK_MESSAGE_ERROR,
752 GTK_BUTTONS_OK,
753 NULL,
754 (char *)data);
755
756 return FALSE;
757 }
758
759 int
create_cddb_write_warn_dialog(char * text)760 create_cddb_write_warn_dialog(char * text) {
761
762 int ret = message_dialog(_("Warning"),
763 browser_window,
764 GTK_MESSAGE_WARNING,
765 GTK_BUTTONS_YES_NO,
766 NULL,
767 text);
768
769 return (ret != GTK_RESPONSE_YES);
770 }
771
772 static int
check_case(char * text,int _case)773 check_case(char * text, int _case) {
774
775 char * str;
776 char * p;
777 int has = 0;
778 int ret = 0;
779
780 for (p = text; *p; p = g_utf8_next_char(p)) {
781
782 gunichar ch = g_utf8_get_char(p);
783
784 if (g_unichar_islower(ch) || g_unichar_isupper(ch)) {
785 has = 1;
786 break;
787 }
788 }
789
790 if (!has) {
791 return 1;
792 }
793
794 switch (_case) {
795 case CASE_UP:
796 str = g_utf8_strup(text, -1);
797 ret = strcmp(str, text);
798 g_free(str);
799 break;
800 case CASE_DOWN:
801 str = g_utf8_strdown(text, -1);
802 ret = strcmp(str, text);
803 g_free(str);
804 break;
805 }
806
807 return ret;
808 }
809
810
811 int
cddb_submit_check(cddb_lookup_t * data)812 cddb_submit_check(cddb_lookup_t * data) {
813
814 GtkTreeIter iter_trlist;
815 char * artist;
816 char * title;
817 char * genre;
818 char * ext;
819 int category;
820 int year;
821 int i;
822
823
824 artist = (char *)gtk_entry_get_text(GTK_ENTRY(data->artist_entry));
825 if (is_all_wspace(artist)) {
826 gtk_widget_grab_focus(data->artist_entry);
827 return 1;
828 }
829
830 if (!check_case(artist, CASE_DOWN)) {
831 if (create_cddb_write_warn_dialog(_("Artist appears to be in all lowercase.\n"
832 "Do you want to proceed?"))) {
833 gtk_widget_grab_focus(data->artist_entry);
834 return 1;
835 }
836 }
837
838 if (!check_case(artist, CASE_UP)) {
839 if (create_cddb_write_warn_dialog(_("Artist appears to be in all uppercase.\n"
840 "Do you want to proceed?"))) {
841 gtk_widget_grab_focus(data->artist_entry);
842 return 1;
843 }
844 }
845
846 title = (char *)gtk_entry_get_text(GTK_ENTRY(data->title_entry));
847 if (is_all_wspace(title)) {
848 gtk_widget_grab_focus(data->title_entry);
849 return 1;
850 }
851
852 if (!check_case(title, CASE_DOWN)) {
853 if (create_cddb_write_warn_dialog(_("Title appears to be in all lowercase.\n"
854 "Do you want to proceed?"))) {
855 gtk_widget_grab_focus(data->title_entry);
856 return 1;
857 }
858 }
859
860 if (!check_case(title, CASE_UP)) {
861 if (create_cddb_write_warn_dialog(_("Title appears to be in all uppercase.\n"
862 "Do you want to proceed?"))) {
863 gtk_widget_grab_focus(data->title_entry);
864 return 1;
865 }
866 }
867
868 year = gtk_spin_button_get_value(GTK_SPIN_BUTTON(data->year_spinner));
869
870 if (year == YEAR_MIN) {
871 if (create_cddb_write_warn_dialog(_("It is very likely that the year is wrong.\n"
872 "Do you want to proceed?"))) {
873 gtk_widget_grab_focus(data->year_spinner);
874 return 1;
875 }
876 }
877
878 if (data->type == CDDB_TYPE_SUBMIT_NEW) {
879 category = gtk_combo_box_get_active(GTK_COMBO_BOX(data->category_combo));
880 if (category == 0) {
881 gtk_widget_grab_focus(data->category_combo);
882 return 1;
883 }
884 }
885
886 genre = (char *)gtk_entry_get_text(GTK_ENTRY(data->genre_entry));
887 if (genre[0] != '\0' && is_all_wspace(genre)) {
888 gtk_widget_grab_focus(data->genre_entry);
889 return 1;
890 }
891
892 ext = (char *)gtk_entry_get_text(GTK_ENTRY(data->ext_entry));
893 if (ext[0] != '\0' && is_all_wspace(ext)) {
894 gtk_widget_grab_focus(data->ext_entry);
895 return 1;
896 }
897
898 for (i = 0; gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(data->track_store),
899 &iter_trlist, NULL, i); i++) {
900 char * name;
901 gtk_tree_model_get(GTK_TREE_MODEL(data->track_store),
902 &iter_trlist, 0, &name, -1);
903
904 if (is_all_wspace(name)) {
905 gtk_tree_selection_select_iter(gtk_tree_view_get_selection(GTK_TREE_VIEW(data->track_list)),
906 &iter_trlist);
907 return 1;
908 }
909
910 g_free(name);
911 }
912
913 return 0;
914 }
915
916 void
cddb_submit(cddb_lookup_t * data,int n)917 cddb_submit(cddb_lookup_t * data, int n) {
918
919 GtkTreeIter iter_trlist;
920 cddb_conn_t * conn = NULL;
921 cddb_disc_t * disc = NULL;
922 int i;
923
924
925 if (cddb_connection_setup(&conn) == 1) {
926 return;
927 }
928
929 if (!cddb_set_email_address(conn, options.cddb_email)) {
930 create_cddb_write_error_dialog(_("The email address provided for submission is invalid."));
931 cddb_destroy(conn);
932 return;
933 }
934
935 cddb_http_enable(conn);
936 cddb_set_server_port(conn, 80);
937
938 if (n < 0) {
939 cddb_track_t * track = NULL;
940
941 if ((disc = cddb_disc_new()) == NULL) {
942 fprintf(stderr, "cddb_submit: cddb_disc_new error\n");
943 cddb_destroy(conn);
944 return;
945 }
946
947 for (i = 0; i < data->ntracks; i++) {
948 track = cddb_track_new();
949 cddb_track_set_frame_offset(track, data->frames[i]);
950 cddb_disc_add_track(disc, track);
951 }
952
953 cddb_disc_set_length(disc, data->record_length);
954 cddb_disc_set_category(disc, gtk_combo_box_get_active(GTK_COMBO_BOX(data->category_combo)) - 1);
955
956 if (cddb_disc_calc_discid(disc) == 0) {
957 fprintf(stderr, "cddb_submit: cddb_disc_calc_discid error\n");
958 cddb_disc_destroy(disc);
959 cddb_destroy(conn);
960 return;
961 }
962 } else {
963 disc = data->records[n];
964 #ifdef LIBCDDB_REVISION
965 cddb_disc_set_revision(disc, cddb_disc_get_revision(disc) + 1);
966 #endif /* LIBCDDB_REVISION */
967 }
968
969 for (i = 0; gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(data->track_store),
970 &iter_trlist, NULL, i); i++) {
971 char * name;
972 gtk_tree_model_get(GTK_TREE_MODEL(data->track_store),
973 &iter_trlist, 0, &name, -1);
974
975 cddb_track_set_title(cddb_disc_get_track(disc, i), name);
976 g_free(name);
977 }
978
979 cddb_disc_set_artist(disc, gtk_entry_get_text(GTK_ENTRY(data->artist_entry)));
980 cddb_disc_set_title(disc, gtk_entry_get_text(GTK_ENTRY(data->title_entry)));
981 cddb_disc_set_year(disc, gtk_spin_button_get_value(GTK_SPIN_BUTTON(data->year_spinner)));
982 cddb_disc_set_genre(disc, gtk_entry_get_text(GTK_ENTRY(data->genre_entry)));
983 cddb_disc_set_ext_data(disc, gtk_entry_get_text(GTK_ENTRY(data->ext_entry)));
984
985 if (!cddb_write(conn, disc)) {
986 create_cddb_write_error_dialog(_("An error occurred while submitting the record to the CDDB server."));
987 }
988
989 cddb_destroy(conn);
990
991 if (n < 0) {
992 cddb_disc_destroy(disc);
993 }
994 }
995
996
997 void
cddb_dialog_load_disc(cddb_lookup_t * data,cddb_disc_t * disc)998 cddb_dialog_load_disc(cddb_lookup_t * data, cddb_disc_t * disc) {
999
1000 GtkTreeIter iter;
1001 int i;
1002
1003 gtk_entry_set_text(GTK_ENTRY(data->artist_entry), notnull(cddb_disc_get_artist(disc)));
1004 gtk_entry_set_text(GTK_ENTRY(data->title_entry), notnull(cddb_disc_get_title(disc)));
1005 gtk_entry_set_text(GTK_ENTRY(data->category_entry), notnull(cddb_disc_get_category_str(disc)));
1006 gtk_entry_set_text(GTK_ENTRY(data->genre_entry), notnull(cddb_disc_get_genre(disc)));
1007 gtk_entry_set_text(GTK_ENTRY(data->ext_entry), notnull(cddb_disc_get_ext_data(disc)));
1008
1009 gtk_spin_button_set_value(GTK_SPIN_BUTTON(data->year_spinner), cddb_disc_get_year(disc));
1010
1011 gtk_list_store_clear(GTK_LIST_STORE(data->track_store));
1012
1013 for (i = 0; i < data->ntracks; i++) {
1014 gtk_list_store_append(data->track_store, &iter);
1015 gtk_list_store_set(data->track_store, &iter, 0,
1016 notnull(cddb_track_get_title(cddb_disc_get_track(disc, i))), -1);
1017 }
1018 }
1019
1020
1021 void
store_load_tracklist(cddb_lookup_t * data)1022 store_load_tracklist(cddb_lookup_t * data) {
1023
1024 GtkTreeIter iter;
1025 GtkTreeIter iter_trlist;
1026 int i = 0;
1027
1028 while (gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(music_store),
1029 &iter, &data->iter_record, i++)) {
1030 char * name;
1031
1032 gtk_tree_model_get(GTK_TREE_MODEL(music_store), &iter, MS_COL_NAME, &name, -1);
1033 gtk_list_store_append(data->track_store, &iter_trlist);
1034 gtk_list_store_set(data->track_store, &iter_trlist, 0, name, -1);
1035 g_free(name);
1036 }
1037 }
1038
1039 void
cddb_dialog_load_store_file(cddb_lookup_t * data)1040 cddb_dialog_load_store_file(cddb_lookup_t * data) {
1041
1042 GtkTreeIter iter_artist;
1043 record_data_t * record_data;
1044 char * str;
1045
1046 store_load_tracklist(data);
1047
1048 gtk_tree_model_iter_parent(GTK_TREE_MODEL(music_store), &iter_artist, &data->iter_record);
1049 gtk_tree_model_get(GTK_TREE_MODEL(music_store), &iter_artist, MS_COL_NAME, &str, -1);
1050 gtk_entry_set_text(GTK_ENTRY(data->artist_entry), str);
1051 g_free(str);
1052
1053 gtk_tree_model_get(GTK_TREE_MODEL(music_store), &data->iter_record, MS_COL_NAME, &str, -1);
1054 gtk_entry_set_text(GTK_ENTRY(data->title_entry), str);
1055 g_free(str);
1056
1057 gtk_tree_model_get(GTK_TREE_MODEL(music_store), &data->iter_record, MS_COL_DATA, &record_data, -1);
1058 gtk_spin_button_set_value(GTK_SPIN_BUTTON(data->year_spinner), record_data->year);
1059 }
1060
1061
1062 #ifdef HAVE_CDDA
1063 void
cddb_dialog_load_store_cdda(cddb_lookup_t * data)1064 cddb_dialog_load_store_cdda(cddb_lookup_t * data) {
1065
1066 store_load_tracklist(data);
1067
1068 cdda_drive_t * drive;
1069
1070 gtk_tree_model_get(GTK_TREE_MODEL(music_store), &data->iter_record,
1071 MS_COL_DATA, &drive, -1);
1072
1073 gtk_entry_set_text(GTK_ENTRY(data->artist_entry), drive->disc.artist_name);
1074 gtk_entry_set_text(GTK_ENTRY(data->title_entry), drive->disc.record_name);
1075 gtk_entry_set_text(GTK_ENTRY(data->genre_entry), drive->disc.genre);
1076 gtk_spin_button_set_value(GTK_SPIN_BUTTON(data->year_spinner), drive->disc.year);
1077 }
1078 #endif /* HAVE_CDDA */
1079
1080
1081 void
export_tracklist(cddb_lookup_t * data)1082 export_tracklist(cddb_lookup_t * data) {
1083
1084 int i;
1085 GtkTreeIter iter;
1086 GtkTreeIter iter_trlist;
1087
1088 for (i = 0; gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(music_store),
1089 &iter, &data->iter_record, i); i++) {
1090
1091 if (gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(data->track_store),
1092 &iter_trlist, NULL, i)) {
1093 char * name;
1094 gtk_tree_model_get(GTK_TREE_MODEL(data->track_store), &iter_trlist, 0, &name, -1);
1095 gtk_tree_store_set(music_store, &iter, MS_COL_NAME, name, -1);
1096 g_free(name);
1097 }
1098 }
1099 }
1100
1101 void
store_file_export(cddb_lookup_t * data)1102 store_file_export(cddb_lookup_t * data) {
1103
1104 export_tracklist(data);
1105 music_store_mark_changed(&data->iter_record);
1106 }
1107
1108
1109 #ifdef HAVE_CDDA
1110 void
store_cdda_export(cddb_lookup_t * data)1111 store_cdda_export(cddb_lookup_t * data) {
1112
1113 char name[MAXLEN];
1114 cdda_drive_t * drive;
1115
1116 export_tracklist(data);
1117
1118 gtk_tree_model_get(GTK_TREE_MODEL(music_store), &data->iter_record, MS_COL_DATA, &drive, -1);
1119
1120 strncpy(drive->disc.artist_name, gtk_entry_get_text(GTK_ENTRY(data->artist_entry)), MAXLEN-1);
1121 strncpy(drive->disc.record_name, gtk_entry_get_text(GTK_ENTRY(data->title_entry)), MAXLEN-1);
1122 strncpy(drive->disc.genre, gtk_entry_get_text(GTK_ENTRY(data->genre_entry)), MAXLEN-1);
1123 drive->disc.year = gtk_spin_button_get_value(GTK_SPIN_BUTTON(data->year_spinner));
1124
1125 snprintf(name, MAXLEN-1, "%s: %s",
1126 drive->disc.artist_name,
1127 drive->disc.record_name);
1128
1129 gtk_tree_store_set(music_store, &data->iter_record, MS_COL_NAME, name, -1);
1130 }
1131 #endif /* HAVE_CDDA */
1132
1133
1134 void
cddb_dialog(cddb_lookup_t * data)1135 cddb_dialog(cddb_lookup_t * data) {
1136
1137 GtkWidget * dialog;
1138 GtkWidget * table;
1139
1140 GtkWidget * hbox;
1141 GtkWidget * label;
1142 GtkWidget * button;
1143
1144 GtkWidget * viewport;
1145 GtkWidget * scrollwin;
1146 GtkCellRenderer * renderer;
1147 GtkTreeViewColumn * column;
1148
1149 int i;
1150 char text[MAXLEN];
1151
1152
1153 dialog = gtk_dialog_new_with_buttons(NULL,
1154 GTK_WINDOW(browser_window),
1155 GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
1156 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
1157 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
1158 NULL);
1159
1160 gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER);
1161 gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
1162
1163 switch (data->type) {
1164 case CDDB_TYPE_QUERY:
1165 gtk_window_set_title(GTK_WINDOW(dialog), _("CDDB query"));
1166 break;
1167 case CDDB_TYPE_SUBMIT:
1168 gtk_window_set_title(GTK_WINDOW(dialog), _("Correct existing record"));
1169 break;
1170 case CDDB_TYPE_SUBMIT_NEW:
1171 gtk_window_set_title(GTK_WINDOW(dialog), _("Submit new record"));
1172 break;
1173 }
1174
1175 table = gtk_table_new(8, 3, FALSE);
1176 gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))),
1177 table, FALSE, FALSE, 2);
1178
1179 if (data->type != CDDB_TYPE_SUBMIT_NEW) {
1180 hbox = gtk_hbox_new(FALSE, 0);
1181 gtk_table_attach(GTK_TABLE(table), hbox, 0, 1, 0, 1, GTK_FILL, GTK_FILL, 5, 3);
1182 label = gtk_label_new(_("Matches:"));
1183 gtk_box_pack_end(GTK_BOX(hbox), label, FALSE, FALSE, 2);
1184
1185 data->combo = gtk_combo_box_new_text();
1186 for (i = 0; i < data->nrecords; i++) {
1187 snprintf(text, MAXLEN, "%d. %s: %s [%x] ",
1188 i + 1,
1189 notnull(cddb_disc_get_artist(data->records[i])),
1190 notnull(cddb_disc_get_title(data->records[i])),
1191 cddb_disc_get_discid(data->records[i]));
1192 gtk_combo_box_append_text(GTK_COMBO_BOX(data->combo), text);
1193 }
1194
1195 gtk_combo_box_set_active(GTK_COMBO_BOX(data->combo), 0);
1196 g_signal_connect(data->combo, "changed", G_CALLBACK(changed_combo), data);
1197
1198 gtk_table_attach(GTK_TABLE(table), data->combo, 1, 3, 0, 1, GTK_FILL, GTK_FILL, 5, 3);
1199 }
1200
1201 hbox = gtk_hbox_new(FALSE, 0);
1202 gtk_table_attach(GTK_TABLE(table), hbox, 0, 1, 1, 2, GTK_FILL, GTK_FILL, 5, 3);
1203 label = gtk_label_new(_("Artist:"));
1204 gtk_box_pack_end(GTK_BOX(hbox), label, FALSE, FALSE, 2);
1205
1206 data->artist_entry = gtk_entry_new();
1207 gtk_table_attach(GTK_TABLE(table), data->artist_entry, 1, 2, 1, 2,
1208 GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 5, 3);
1209
1210 hbox = gtk_hbox_new(FALSE, 0);
1211 gtk_table_attach(GTK_TABLE(table), hbox, 0, 1, 2, 3, GTK_FILL, GTK_FILL, 5, 3);
1212 label = gtk_label_new(_("Title:"));
1213 gtk_box_pack_end(GTK_BOX(hbox), label, FALSE, FALSE, 2);
1214
1215 data->title_entry = gtk_entry_new();
1216 gtk_table_attach(GTK_TABLE(table), data->title_entry, 1, 2, 2, 3,
1217 GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 5, 3);
1218
1219 hbox = gtk_hbox_new(FALSE, 0);
1220 gtk_table_attach(GTK_TABLE(table), hbox, 0, 1, 3, 4, GTK_FILL, GTK_FILL, 5, 3);
1221 label = gtk_label_new(_("Year:"));
1222 gtk_box_pack_end(GTK_BOX(hbox), label, FALSE, FALSE, 2);
1223
1224 data->year_spinner = gtk_spin_button_new_with_range(YEAR_MIN, YEAR_MAX, 1);
1225 gtk_table_attach(GTK_TABLE(table), data->year_spinner, 1, 2, 3, 4,
1226 GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 5, 3);
1227
1228 hbox = gtk_hbox_new(FALSE, 0);
1229 gtk_table_attach(GTK_TABLE(table), hbox, 0, 1, 4, 5, GTK_FILL, GTK_FILL, 5, 3);
1230 label = gtk_label_new(_("Category:"));
1231 gtk_box_pack_end(GTK_BOX(hbox), label, FALSE, FALSE, 2);
1232
1233 if (data->type != CDDB_TYPE_SUBMIT_NEW) {
1234 data->category_entry = gtk_entry_new();
1235 gtk_editable_set_editable(GTK_EDITABLE(data->category_entry), FALSE);
1236 gtk_table_attach(GTK_TABLE(table), data->category_entry, 1, 2, 4, 5,
1237 GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 5, 3);
1238 } else {
1239 data->category_combo = gtk_combo_box_new_text();
1240 gtk_combo_box_append_text(GTK_COMBO_BOX(data->category_combo), _("(choose a category)"));
1241 gtk_combo_box_append_text(GTK_COMBO_BOX(data->category_combo), "data");
1242 gtk_combo_box_append_text(GTK_COMBO_BOX(data->category_combo), "folk");
1243 gtk_combo_box_append_text(GTK_COMBO_BOX(data->category_combo), "jazz");
1244 gtk_combo_box_append_text(GTK_COMBO_BOX(data->category_combo), "misc");
1245 gtk_combo_box_append_text(GTK_COMBO_BOX(data->category_combo), "rock");
1246 gtk_combo_box_append_text(GTK_COMBO_BOX(data->category_combo), "country");
1247 gtk_combo_box_append_text(GTK_COMBO_BOX(data->category_combo), "blues");
1248 gtk_combo_box_append_text(GTK_COMBO_BOX(data->category_combo), "newage");
1249 gtk_combo_box_append_text(GTK_COMBO_BOX(data->category_combo), "reagge");
1250 gtk_combo_box_append_text(GTK_COMBO_BOX(data->category_combo), "classical");
1251 gtk_combo_box_append_text(GTK_COMBO_BOX(data->category_combo), "soundtrack");
1252 gtk_combo_box_set_active(GTK_COMBO_BOX(data->category_combo), 0);
1253 gtk_table_attach(GTK_TABLE(table), data->category_combo, 1, 2, 4, 5,
1254 GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 5, 3);
1255 }
1256
1257 hbox = gtk_hbox_new(FALSE, 0);
1258 gtk_table_attach(GTK_TABLE(table), hbox, 0, 1, 5, 6, GTK_FILL, GTK_FILL, 5, 3);
1259 label = gtk_label_new(_("Genre:"));
1260 gtk_box_pack_end(GTK_BOX(hbox), label, FALSE, FALSE, 2);
1261
1262 data->genre_entry = gtk_entry_new();
1263 gtk_table_attach(GTK_TABLE(table), data->genre_entry, 1, 2, 5, 6,
1264 GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 5, 3);
1265
1266 hbox = gtk_hbox_new(FALSE, 0);
1267 gtk_table_attach(GTK_TABLE(table), hbox, 0, 1, 6, 7, GTK_FILL, GTK_FILL, 5, 3);
1268 label = gtk_label_new(_("Extended data:"));
1269 gtk_box_pack_end(GTK_BOX(hbox), label, FALSE, FALSE, 2);
1270
1271 data->ext_entry = gtk_entry_new();
1272 gtk_table_attach(GTK_TABLE(table), data->ext_entry, 1, 2, 6, 7,
1273 GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 5, 3);
1274
1275 if (data->type == CDDB_TYPE_QUERY && iter_get_store_type(&data->iter_record) == STORE_TYPE_FILE) {
1276
1277 g_signal_connect(G_OBJECT(data->title_entry), "focus-in-event",
1278 G_CALLBACK(title_entry_focused), data);
1279 g_signal_connect(G_OBJECT(data->year_spinner), "focus-in-event",
1280 G_CALLBACK(year_spinner_focused), data);
1281
1282 button = gtk_button_new_with_label(_("Import as Artist"));
1283 g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(import_as_artist), data);
1284 gtk_table_attach(GTK_TABLE(table), button, 2, 3, 1, 2, GTK_FILL, GTK_FILL, 5, 3);
1285
1286 data->title_import_button = gtk_button_new_with_label(_("Import as Title"));
1287 g_signal_connect(G_OBJECT(data->title_import_button), "clicked",
1288 G_CALLBACK(import_as_title), data);
1289 gtk_table_attach(GTK_TABLE(table), data->title_import_button,
1290 2, 3, 2, 3, GTK_FILL, GTK_FILL, 5, 3);
1291
1292 data->year_import_button = gtk_button_new_with_label(_("Import as Year"));
1293 g_signal_connect(G_OBJECT(data->year_import_button), "clicked",
1294 G_CALLBACK(import_as_year), data);
1295 gtk_table_attach(GTK_TABLE(table), data->year_import_button,
1296 2, 3, 3, 4, GTK_FILL, GTK_FILL, 5, 3);
1297
1298 button = gtk_button_new_with_label(_("Add to Comments"));
1299 g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(add_category_to_comments), data);
1300 gtk_table_attach(GTK_TABLE(table), button, 2, 3, 4, 5, GTK_FILL, GTK_FILL, 5, 3);
1301
1302 button = gtk_button_new_with_label(_("Add to Comments"));
1303 g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(add_genre_to_comments), data);
1304 gtk_table_attach(GTK_TABLE(table), button, 2, 3, 5, 6, GTK_FILL, GTK_FILL, 5, 3);
1305
1306 button = gtk_button_new_with_label(_("Add to Comments"));
1307 g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(add_ext_to_comments), data);
1308 gtk_table_attach(GTK_TABLE(table), button, 2, 3, 6, 7, GTK_FILL, GTK_FILL, 5, 3);
1309 }
1310
1311 data->track_store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_BOOLEAN);
1312 data->track_list = gtk_tree_view_new_with_model(GTK_TREE_MODEL(data->track_store));
1313
1314 renderer = gtk_cell_renderer_text_new();
1315 g_object_set(renderer, "editable", TRUE, NULL);
1316 g_signal_connect(renderer, "edited", (GCallback)cell_edited_callback, data);
1317 column = gtk_tree_view_column_new_with_attributes(_("Tracks"),
1318 renderer,
1319 "text", 0,
1320 NULL);
1321 gtk_tree_view_append_column(GTK_TREE_VIEW(data->track_list), column);
1322 gtk_tree_view_set_reorderable(GTK_TREE_VIEW(data->track_list), FALSE);
1323
1324 viewport = gtk_viewport_new(NULL, NULL);
1325 scrollwin = gtk_scrolled_window_new(NULL, NULL);
1326 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin),
1327 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1328 gtk_widget_set_size_request(scrollwin, -1, 200);
1329 gtk_table_attach(GTK_TABLE(table), viewport, 0, 3, 7, 8,
1330 GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 5, 3);
1331 gtk_container_add(GTK_CONTAINER(viewport), scrollwin);
1332 gtk_container_add(GTK_CONTAINER(scrollwin), data->track_list);
1333
1334 gtk_widget_show_all(dialog);
1335
1336 if (data->type != CDDB_TYPE_SUBMIT_NEW) {
1337 cddb_dialog_load_disc(data, data->records[0]);
1338 } else {
1339 if (iter_get_store_type(&data->iter_record) == STORE_TYPE_FILE) {
1340 cddb_dialog_load_store_file(data);
1341 } else {
1342 #ifdef HAVE_CDDA
1343 cddb_dialog_load_store_cdda(data);
1344 #endif /* HAVE_CDDA */
1345 }
1346 }
1347
1348 display:
1349
1350 if (aqualung_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1351
1352 if (data->type == CDDB_TYPE_SUBMIT || data->type == CDDB_TYPE_SUBMIT_NEW) {
1353 if (cddb_submit_check(data)) {
1354 goto display;
1355 }
1356 }
1357
1358 if (data->type == CDDB_TYPE_SUBMIT) {
1359 cddb_submit(data, gtk_combo_box_get_active(GTK_COMBO_BOX(data->combo)));
1360 }
1361
1362 if (data->type == CDDB_TYPE_SUBMIT_NEW) {
1363 cddb_submit(data, -1);
1364 }
1365
1366 if (data->type == CDDB_TYPE_QUERY) {
1367 if (iter_get_store_type(&data->iter_record) == STORE_TYPE_FILE) {
1368 store_file_export(data);
1369 } else {
1370 #ifdef HAVE_CDDA
1371 store_cdda_export(data);
1372 #endif /* HAVE_CDDA */
1373 }
1374 }
1375 }
1376
1377 gtk_widget_destroy(dialog);
1378 }
1379
1380
1381 void *
cddb_lookup_thread(void * arg)1382 cddb_lookup_thread(void * arg) {
1383
1384 AQUALUNG_THREAD_DETACH();
1385
1386 cddb_lookup((cddb_lookup_t *)arg);
1387
1388 return NULL;
1389 }
1390
1391 void
cddb_start_lookup_thread(GtkTreeIter * iter_record,int type,int progress,int ntracks,int * frames,int length,gboolean (* timeout_cb)(gpointer))1392 cddb_start_lookup_thread(GtkTreeIter * iter_record,
1393 int type,
1394 int progress,
1395 int ntracks, int * frames, int length,
1396 gboolean (*timeout_cb)(gpointer)) {
1397
1398 cddb_lookup_t * data;
1399
1400 if ((data = cddb_lookup_new()) == NULL) {
1401 return;
1402 }
1403
1404 data->iter_record = *iter_record;
1405 data->type = type;
1406 data->ntracks = ntracks;
1407 data->frames = frames;
1408 data->record_length = length;
1409
1410 AQUALUNG_THREAD_CREATE(data->thread_id, NULL, cddb_lookup_thread, data);
1411 if (progress) {
1412 create_query_progress_window(data);
1413 }
1414 aqualung_timeout_add(100, timeout_cb, data);
1415 }
1416
1417 void
cddb_start_query(GtkTreeIter * iter_record,int ntracks,int * frames,int length)1418 cddb_start_query(GtkTreeIter * iter_record, int ntracks, int * frames, int length) {
1419
1420 cddb_start_lookup_thread(iter_record,
1421 CDDB_TYPE_QUERY,
1422 1,
1423 ntracks, frames, length,
1424 query_timeout_cb);
1425 }
1426
1427 void
cddb_start_submit(GtkTreeIter * iter_record,int ntracks,int * frames,int length)1428 cddb_start_submit(GtkTreeIter * iter_record, int ntracks, int * frames, int length) {
1429
1430 if (options.cddb_email[0] == '\0') {
1431 create_cddb_write_error_dialog(_("You have to provide an email address for CDDB submission."));
1432 return;
1433 }
1434
1435 cddb_start_lookup_thread(iter_record,
1436 CDDB_TYPE_SUBMIT,
1437 1,
1438 ntracks, frames, length,
1439 query_timeout_cb);
1440 }
1441
1442 #ifdef HAVE_CDDA
1443 void
cddb_auto_query_cdda(GtkTreeIter * drive_iter,int ntracks,int * frames,int length)1444 cddb_auto_query_cdda(GtkTreeIter * drive_iter, int ntracks, int * frames, int length) {
1445
1446 cddb_start_lookup_thread(drive_iter,
1447 CDDB_TYPE_QUERY,
1448 0,
1449 ntracks, frames, length,
1450 cdda_auto_query_timeout_cb);
1451 }
1452 #endif /* HAVE_CDDA */
1453
1454 void
cddb_query_batch(int ntracks,int * frames,int length,char * artist,char * record,int * year,char ** tracks)1455 cddb_query_batch(int ntracks, int * frames, int length,
1456 char * artist, char * record, int * year, char ** tracks) {
1457
1458 cddb_lookup_t * data;
1459
1460 if ((data = cddb_lookup_new()) == NULL) {
1461 return;
1462 }
1463
1464 data->type = CDDB_TYPE_QUERY;
1465 data->ntracks = ntracks;
1466 data->frames = frames;
1467 data->record_length = length;
1468
1469 cddb_lookup(data);
1470 cddb_lookup_merge(data, artist, record, NULL/*genre*/, year, tracks);
1471 cddb_lookup_free(data);
1472 }
1473
1474
1475 // vim: shiftwidth=8:tabstop=8:softtabstop=8 :
1476
1477