mp3splt-gtk
freedb_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-2012 Alexandru Munteanu
7  * Contact: io_fx@yahoo.fr
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
28  * USA.
29  *
30  *********************************************************/
31 
32 /*!********************************************************
33  * \file
34  * The freedb tab
35  *
36  * this file is used for the cddb tab
37  * (for searching on freedb)
38  *********************************************************/
39 
40 #include "freedb_window.h"
41 
42 enum {
43  ALBUM_NAME,
44  NUMBER,
45  FREEDB_TABLE
46 };
47 
49 static void add_freedb_row(gchar *album_name, gint album_id,
50  gint *revisions, gint revisions_number, ui_state *ui)
51 {
52  GtkTreeModel *model = gtk_tree_view_get_model(ui->gui->freedb_tree);
53 
54  GtkTreeIter iter;
55  gtk_tree_store_append (GTK_TREE_STORE(model), &iter,NULL);
56  gtk_tree_store_set(GTK_TREE_STORE(model), &iter,
57  ALBUM_NAME, album_name, NUMBER, album_id, -1);
58 
59  gint malloc_number = strlen(album_name) + 20;
60  gchar *number = malloc(malloc_number * sizeof(gchar *));
61  gint i;
62  for(i = 0; i < revisions_number; i++)
63  {
64  g_snprintf(number,malloc_number, _("%s Revision %d"),album_name, revisions[i]);
65 
66  GtkTreeIter child_iter;
67  gtk_tree_store_append(GTK_TREE_STORE(model), &child_iter, &iter);
68  gtk_tree_store_set(GTK_TREE_STORE(model), &child_iter,
69  ALBUM_NAME, number, NUMBER, album_id + i + 1, -1);
70  }
71 
72  ui->infos->freedb_table_number++;
73  g_free(number);
74 }
75 
77 static GtkTreeModel *create_freedb_model()
78 {
79  GtkTreeStore *model = gtk_tree_store_new(FREEDB_TABLE, G_TYPE_STRING, G_TYPE_INT);
80  return GTK_TREE_MODEL(model);
81 }
82 
84 static GtkTreeView *create_freedb_tree()
85 {
86  GtkTreeModel *model = create_freedb_model();
87  return GTK_TREE_VIEW(gtk_tree_view_new_with_model(model));
88 }
89 
91 static void create_freedb_columns(GtkTreeView *freedb_tree)
92 {
93  GtkCellRendererText *renderer = GTK_CELL_RENDERER_TEXT(gtk_cell_renderer_text_new());
94  g_object_set_data(G_OBJECT(renderer), "col", GINT_TO_POINTER(ALBUM_NAME));
95  GtkTreeViewColumn *name_column = gtk_tree_view_column_new_with_attributes
96  (_("Album title"), GTK_CELL_RENDERER(renderer), "text", ALBUM_NAME, NULL);
97 
98  gtk_tree_view_insert_column(freedb_tree, GTK_TREE_VIEW_COLUMN(name_column), ALBUM_NAME);
99 
100  gtk_tree_view_column_set_alignment(GTK_TREE_VIEW_COLUMN(name_column), 0.5);
101  gtk_tree_view_column_set_sizing(GTK_TREE_VIEW_COLUMN(name_column), GTK_TREE_VIEW_COLUMN_AUTOSIZE);
102  gtk_tree_view_column_set_expand(GTK_TREE_VIEW_COLUMN(name_column), TRUE);
103 
104  gtk_tree_view_column_set_resizable(GTK_TREE_VIEW_COLUMN(name_column), TRUE);
105 }
106 
107 static void set_freedb_selected_id_safe(gint selected_id, ui_state *ui)
108 {
109  lock_mutex(&ui->variables_mutex);
110  ui->infos->freedb_selected_id = selected_id;
111  unlock_mutex(&ui->variables_mutex);
112 }
113 
114 static gint get_freedb_selected_id_safe(ui_state *ui)
115 {
116  lock_mutex(&ui->variables_mutex);
117  gint selected_id = ui->infos->freedb_selected_id;
118  unlock_mutex(&ui->variables_mutex);
119  return selected_id;
120 }
121 
123 static void freedb_selection_changed(GtkTreeSelection *selection, ui_state *ui)
124 {
125  GtkTreeModel *model = gtk_tree_view_get_model(ui->gui->freedb_tree);
126 
127  GtkTreeIter iter;
128  if (gtk_tree_selection_get_selected(selection, &model, &iter))
129  {
130  gchar *info;
131  gint selected_id;
132  gtk_tree_model_get(model, &iter, ALBUM_NAME, &info, NUMBER, &selected_id, -1);
133  g_free(info);
134 
135  set_freedb_selected_id_safe(selected_id, ui);
136 
137  gtk_widget_set_sensitive(ui->gui->freedb_add_button, TRUE);
138  }
139  else
140  {
141  gtk_widget_set_sensitive(ui->gui->freedb_add_button, FALSE);
142  }
143 }
144 
146 static void remove_all_freedb_rows(ui_state *ui)
147 {
148  GtkTreeModel *model = gtk_tree_view_get_model(ui->gui->freedb_tree);
149  while (ui->infos->freedb_table_number > 0)
150  {
151  GtkTreeIter iter;
152  gtk_tree_model_get_iter_first(model, &iter);
153  gtk_tree_store_remove(GTK_TREE_STORE(model), &iter);
154  ui->infos->freedb_table_number--;
155  }
156 }
157 
158 static gboolean freedb_search_start(ui_state *ui)
159 {
160  gui_state *gui = ui->gui;
161 
162  gtk_widget_hide(gui->freedb_search_button);
163  gtk_widget_show(gui->freedb_spinner);
164  gtk_spinner_start(GTK_SPINNER(gui->freedb_spinner));
165 
166  gtk_widget_set_sensitive(gui->freedb_add_button, FALSE);
167  gtk_widget_set_sensitive(gui->freedb_entry, FALSE);
168  gtk_widget_set_sensitive(GTK_WIDGET(gui->freedb_tree), FALSE);
169 
170  put_status_message(_("please wait... contacting tracktype.org"), ui);
171 
172  return FALSE;
173 }
174 
175 static gboolean freedb_search_end(ui_with_err *ui_err)
176 {
177  gui_state *gui = ui_err->ui->gui;
178  ui_infos *infos = ui_err->ui->infos;
179 
180  remove_all_freedb_rows(ui_err->ui);
181 
182  if (ui_err->err >= 0 && infos->freedb_search_results)
183  {
184  gint i = 0;
185  for (i = 0; i < infos->freedb_search_results->number;i++)
186  {
187  gint must_be_free = SPLT_FALSE;
188  infos->freedb_search_results->results[i].name =
189  transform_to_utf8(infos->freedb_search_results->results[i].name, TRUE, &must_be_free);
190  add_freedb_row(infos->freedb_search_results->results[i].name,
191  infos->freedb_search_results->results[i].id,
192  infos->freedb_search_results->results[i].revisions,
193  infos->freedb_search_results->results[i].revision_number, ui_err->ui);
194  }
195 
196  if (infos->freedb_search_results->number > 0)
197  {
198  GtkTreeSelection *selection = gtk_tree_view_get_selection(gui->freedb_tree);
199  GtkTreeModel *model = gtk_tree_view_get_model(gui->freedb_tree);
200  GtkTreePath *path = gtk_tree_path_new_from_indices (0 ,-1);
201 
202  GtkTreeIter iter;
203  gtk_tree_model_get_iter(model, &iter, path);
204  gtk_tree_selection_select_iter(selection, &iter);
205  gtk_tree_path_free(path);
206  }
207  }
208 
209  gtk_widget_show(gui->freedb_search_button);
210  gtk_spinner_stop(GTK_SPINNER(gui->freedb_spinner));
211  gtk_widget_hide(gui->freedb_spinner);
212 
213  gtk_widget_set_sensitive(gui->freedb_entry, TRUE);
214  gtk_widget_set_sensitive(GTK_WIDGET(gui->freedb_tree), TRUE);
215 
216  set_process_in_progress_and_wait_safe(FALSE, ui_err->ui);
217 
218  g_free(ui_err);
219 
220  return FALSE;
221 }
222 
224 static gpointer freedb_search(ui_state *ui)
225 {
226  set_process_in_progress_and_wait_safe(TRUE, ui);
227 
228  gdk_threads_add_idle_full(G_PRIORITY_HIGH_IDLE, (GSourceFunc)freedb_search_start, ui, NULL);
229 
230  gint err = SPLT_OK;
231 
232  enter_threads();
233  const gchar *freedb_search_value = gtk_entry_get_text(GTK_ENTRY(ui->gui->freedb_entry));
234  exit_threads();
235 
236  //freedb_search_results is only used in the idle of the end of the thread, so no mutex needed
237  ui->infos->freedb_search_results =
238  mp3splt_get_freedb_search(ui->mp3splt_state, freedb_search_value, &err,
240 
241  print_status_bar_confirmation_in_idle(err, ui);
242 
243  ui_with_err *ui_err = g_malloc0(sizeof(ui_with_err));
244  ui_err->err = err;
245  ui_err->ui = ui;
246  gdk_threads_add_idle_full(G_PRIORITY_HIGH_IDLE, (GSourceFunc)freedb_search_end, ui_err, NULL);
247 
248  return NULL;
249 }
250 
252 static void freedb_search_start_thread(ui_state *ui)
253 {
254  create_thread((GThreadFunc)freedb_search, ui);
255 }
256 
258 static void freedb_search_button_event(GtkWidget *widget, ui_state *ui)
259 {
260  freedb_search_start_thread(ui);
261 }
262 
267 static void freedb_entry_activate_event(GtkEntry *entry, ui_state *ui)
268 {
269  freedb_search_start_thread(ui);
270 }
271 
273 static void get_secs_mins_hundr(gfloat time, gint *mins,gint *secs, gint *hundr)
274 {
275  *mins = (gint)(time / 6000);
276  *secs = (gint)(time - (*mins * 6000)) / 100;
277  *hundr = (gint)(time - (*mins * 6000) - (*secs * 100));
278 }
279 
287 {
288  gint max_splits = 0;
289 
290  gint err = SPLT_OK;
291  const splt_point *points = mp3splt_get_splitpoints(ui->mp3splt_state, &max_splits, &err);
293 
294  if (max_splits <= 0)
295  {
296  return;
297  }
298 
299  remove_all_rows(ui->gui->remove_all_button, ui);
300  gint i;
301  for (i = 0; i < max_splits;i++)
302  {
303  //ugly hack because we use maximum ints in the GUI
304  //-GUI must be changed to accept long values
305  long old_point_value = points[i].value;
306  int point_value = (int) old_point_value;
307  if (old_point_value > INT_MAX)
308  {
309  point_value = INT_MAX;
310  }
311 
312  get_secs_mins_hundr(point_value,
313  &ui->status->spin_mins, &ui->status->spin_secs, &ui->status->spin_hundr_secs);
314 
315  gint must_be_free = FALSE;
316  gchar *result_utf8 = points[i].name;
317  if (result_utf8 != NULL)
318  {
319  result_utf8 = transform_to_utf8(result_utf8, FALSE, &must_be_free);
320  g_snprintf(ui->status->current_description, 255, "%s", result_utf8);
321  }
322  else
323  {
324  g_snprintf(ui->status->current_description, 255, "%s", _("description here"));
325  }
326 
327  if (must_be_free)
328  {
329  g_free(result_utf8);
330  result_utf8 = NULL;
331  }
332 
333  if (points[i].type == SPLT_SPLITPOINT)
334  {
335  add_row(TRUE, ui);
336  }
337  else if (points[i].type == SPLT_SKIPPOINT)
338  {
339  add_row(FALSE, ui);
340  }
341  }
342 
343  g_snprintf(ui->status->current_description, 255, "%s", _("description here"));
344 
345  update_minutes_from_spinner(ui->gui->spinner_minutes, ui);
346  update_seconds_from_spinner(ui->gui->spinner_seconds, ui);
347  update_hundr_secs_from_spinner(ui->gui->spinner_hundr_secs, ui);
348 }
349 
350 static gboolean put_freedb_splitpoints_start(ui_state *ui)
351 {
352  gtk_widget_set_sensitive(ui->gui->freedb_add_button, FALSE);
353  gtk_widget_set_sensitive(GTK_WIDGET(ui->gui->freedb_tree), FALSE);
354 
355  put_status_message(_("please wait... contacting tracktype.org"), ui);
356 
357  return FALSE;
358 }
359 
360 static gboolean put_freedb_splitpoints_end(ui_state *ui)
361 {
363 
364  gtk_widget_set_sensitive(ui->gui->freedb_add_button, TRUE);
365  gtk_widget_set_sensitive(GTK_WIDGET(ui->gui->freedb_tree), TRUE);
366 
367  set_process_in_progress_and_wait_safe(FALSE, ui);
368 
369  return FALSE;
370 }
371 
372 static gpointer put_freedb_splitpoints(ui_state *ui)
373 {
374  set_process_in_progress_and_wait_safe(TRUE, ui);
375 
376  gint selected_id = get_freedb_selected_id_safe(ui);
377 
378  gdk_threads_add_idle_full(G_PRIORITY_HIGH_IDLE,
379  (GSourceFunc)put_freedb_splitpoints_start, ui, NULL);
380 
381  gchar mp3splt_dir[14] = ".mp3splt-gtk";
382  const gchar *home_dir = g_get_home_dir();
383  gint malloc_number = strlen(mp3splt_dir) + strlen(home_dir) + 20;
384  gchar *filename = malloc(malloc_number * sizeof(gchar));
385  g_snprintf(filename, malloc_number, "%s%s%s%s%s", home_dir,
386  G_DIR_SEPARATOR_S, mp3splt_dir,
387  G_DIR_SEPARATOR_S, "query.cddb");
388 
389  gint err = SPLT_OK;
390 
391  mp3splt_write_freedb_file_result(ui->mp3splt_state, selected_id,
392  filename, &err, SPLT_FREEDB_GET_FILE_TYPE_CDDB_CGI, "\0",-1);
393  print_status_bar_confirmation_in_idle(err, ui);
394 
395  enter_threads();
397  {
398  exit_threads();
399  mp3splt_set_int_option(ui->mp3splt_state, SPLT_OPT_OUTPUT_FILENAMES, SPLT_OUTPUT_DEFAULT);
400  }
401  else
402  {
403  const char *data = gtk_entry_get_text(GTK_ENTRY(ui->gui->output_entry));
404  exit_threads();
405 
406  mp3splt_set_int_option(ui->mp3splt_state, SPLT_OPT_OUTPUT_FILENAMES, SPLT_OUTPUT_FORMAT);
407 
408  gint error = SPLT_OUTPUT_FORMAT_OK;
409  mp3splt_set_oformat(ui->mp3splt_state, data, &error);
410  print_status_bar_confirmation_in_idle(error, ui);
411  }
412 
413  err = SPLT_OK;
414  mp3splt_put_cddb_splitpoints_from_file(ui->mp3splt_state, filename, &err);
415  print_status_bar_confirmation_in_idle(err, ui);
416 
417  if (filename)
418  {
419  g_free(filename);
420  filename = NULL;
421  }
422 
423  gdk_threads_add_idle_full(G_PRIORITY_HIGH_IDLE,
424  (GSourceFunc)put_freedb_splitpoints_end, ui, NULL);
425 
426  return NULL;
427 }
428 
430 static void freedb_add_button_clicked_event(GtkButton *button, ui_state *ui)
431 {
432  create_thread((GThreadFunc)put_freedb_splitpoints, ui);
433 }
434 
437 {
438  GtkWidget *freedb_hbox = wh_hbox_new();
439  gtk_container_set_border_width(GTK_CONTAINER(freedb_hbox), 0);
440 
441  GtkWidget *freedb_vbox = wh_vbox_new();
442  gtk_box_pack_start(GTK_BOX(freedb_hbox), freedb_vbox, TRUE, TRUE, 4);
443 
444  /* search box */
445  GtkWidget *search_hbox = wh_hbox_new();
446  gtk_box_pack_start(GTK_BOX(freedb_vbox), search_hbox, FALSE, FALSE, 2);
447 
448  GtkWidget *label = gtk_label_new(_("Search tracktype.org:"));
449  gtk_box_pack_start(GTK_BOX(search_hbox), label, FALSE, FALSE, 0);
450 
451  GtkWidget *freedb_entry = gtk_entry_new();
452  ui->gui->freedb_entry = freedb_entry;
453  gtk_editable_set_editable(GTK_EDITABLE(freedb_entry), TRUE);
454  gtk_box_pack_start(GTK_BOX(search_hbox), freedb_entry, TRUE, TRUE, 6);
455  g_signal_connect(G_OBJECT(freedb_entry), "activate",
456  G_CALLBACK(freedb_entry_activate_event), ui);
457 
458  GtkWidget *freedb_search_button = wh_create_cool_button(GTK_STOCK_FIND, _("_Search"),FALSE);
459  ui->gui->freedb_search_button = freedb_search_button;
460  g_signal_connect(G_OBJECT(freedb_search_button), "clicked",
461  G_CALLBACK(freedb_search_button_event), ui);
462  gtk_box_pack_start(GTK_BOX(search_hbox), freedb_search_button, FALSE, FALSE, 0);
463 
464  GtkWidget *freedb_spinner = gtk_spinner_new();
465  ui->gui->freedb_spinner = freedb_spinner;
466  gtk_box_pack_start(GTK_BOX(search_hbox), freedb_spinner, FALSE, FALSE, 4);
467 
468  /* freedb scrolled window and the tree */
469  GtkTreeView *freedb_tree = create_freedb_tree();
470  ui->gui->freedb_tree = freedb_tree;
471 
472  GtkWidget *scrolled_window = gtk_scrolled_window_new(NULL, NULL);
473  gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_window), GTK_SHADOW_NONE);
474  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
475  GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
476  gtk_box_pack_start(GTK_BOX(freedb_vbox), scrolled_window, TRUE, TRUE, 1);
477 
478  create_freedb_columns(freedb_tree);
479 
480  gtk_container_add(GTK_CONTAINER(scrolled_window), GTK_WIDGET(freedb_tree));
481 
482  GtkTreeSelection *freedb_tree_selection = gtk_tree_view_get_selection(freedb_tree);
483  g_signal_connect(G_OBJECT(freedb_tree_selection), "changed",
484  G_CALLBACK(freedb_selection_changed), ui);
485 
486  /* add button */
487  GtkWidget *freedb_add_button = wh_create_cool_button(GTK_STOCK_ADD,_("_Add splitpoints"), FALSE);
488  ui->gui->freedb_add_button = freedb_add_button;
489 
490  gtk_widget_set_sensitive(freedb_add_button, FALSE);
491  g_signal_connect(G_OBJECT(freedb_add_button), "clicked",
492  G_CALLBACK(freedb_add_button_clicked_event), ui);
493  gtk_widget_set_tooltip_text(freedb_add_button, _("Set splitpoints to the splitpoints table"));
494 
495  return freedb_hbox;
496 }
497 
498 void hide_freedb_spinner(gui_state *gui)
499 {
500  gtk_widget_hide(gui->freedb_spinner);
501 }
502 
503