mp3splt-gtk
freedb_tab.c
Go to the documentation of this file.
00001 /**********************************************************
00002  *
00003  * mp3splt-gtk -- utility based on mp3splt,
00004  *                for mp3/ogg splitting without decoding
00005  *
00006  * Copyright: (C) 2005-2012 Alexandru Munteanu
00007  * Contact: io_fx@yahoo.fr
00008  *
00009  * http://mp3splt.sourceforge.net/
00010  *
00011  *********************************************************/
00012 
00013 /**********************************************************
00014  *
00015  * This program is free software; you can redistribute it and/or
00016  * modify it under the terms of the GNU General Public License
00017  * as published by the Free Software Foundation; either version 2
00018  * of the License, or (at your option) any later version.
00019  *
00020  * This program is distributed in the hope that it will be useful,
00021  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00022  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023  * GNU General Public License for more details.
00024  *
00025  * You should have received a copy of the GNU General Public License
00026  * along with this program; if not, write to the Free Software
00027  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
00028  * USA.
00029  *
00030  *********************************************************/
00031 
00032 /*!********************************************************
00033  * \file 
00034  * The freedb tab
00035  *
00036  * this file is used for the cddb tab 
00037  *   (for searching on freedb)
00038  *********************************************************/
00039 
00040 #include <stdlib.h>
00041 #include <string.h>
00042 
00043 #include <gtk/gtk.h>
00044 #include <glib/gi18n.h>
00045 #include <glib/gstdio.h>
00046 
00047 #include <libmp3splt/mp3splt.h>
00048 
00049 #include "util.h"
00050 #include "main_win.h"
00051 #include "tree_tab.h"
00052 #include "preferences_tab.h"
00053 #include "utilities.h"
00054 #include "mp3splt-gtk.h"
00055 
00056 //handle box for detaching window
00057 GtkWidget *freedb_handle_box;
00058 
00059 //filename entry
00060 GtkWidget *freedb_entry;
00061 
00062 //our freedb tree
00063 GtkWidget *freedb_tree;
00064 //we count the number of rows in the table
00065 gint freedb_table_number = 0;
00066 //freedb table enumeration
00067 enum
00068   {
00069     ALBUM_NAME,
00070     NUMBER,
00071     FREEDB_TABLE
00072   };
00073 
00074 //results of the freedb search
00075 const splt_freedb_results *search_results;
00076 //the selected entry id
00077 gint selected_id = -1;
00078 
00079 //the add splitpoint button
00080 GtkWidget *freedb_add_button;
00081 GtkWidget *freedb_search_button;
00082 GtkWidget *spinner;
00083 
00084 gboolean executed_lock = FALSE;
00085 
00086 //the state main mp3splt state
00087 extern splt_state *the_state;
00088 //the spin values
00089 extern gint spin_mins,spin_secs,
00090   spin_hundr_secs;
00091 extern gchar current_description[255];
00092 //output for the cddb,cue and freedb file output
00093 extern GtkWidget *output_entry;
00094 extern gint debug_is_active;
00095 
00097 void add_freedb_row(gchar *album_name, 
00098                     gint album_id,
00099                     gint *revisions,
00100                     gint revisions_number)
00101 {
00102   //father iter
00103   GtkTreeIter iter;
00104   //children iter
00105   GtkTreeIter child_iter;
00106   //our tree and the model
00107   GtkTreeView *tree_view = (GtkTreeView *)freedb_tree;
00108   GtkTreeModel *model;
00109 
00110   model = gtk_tree_view_get_model(tree_view);
00111   
00112   gtk_tree_store_append (GTK_TREE_STORE(model), &iter,NULL);
00113   //sets the father
00114   gtk_tree_store_set (GTK_TREE_STORE(model), &iter,
00115                       ALBUM_NAME, album_name,
00116                       NUMBER, album_id,
00117                       -1);
00118   
00119   gchar *number;
00120   gint malloc_number = strlen(album_name) + 20;
00121   //allocate memory
00122   number = malloc(malloc_number * sizeof(gchar *));
00123   gint i;
00124   for(i = 0; i < revisions_number; i++)
00125     {
00126       g_snprintf(number,malloc_number,
00127           _("%s Revision %d"),album_name, revisions[i]);
00128 
00129       //sets the children..
00130       gtk_tree_store_append (GTK_TREE_STORE(model),
00131                              &child_iter, &iter);
00132       gtk_tree_store_set (GTK_TREE_STORE(model),
00133                           &child_iter,
00134                           ALBUM_NAME, number,
00135                           NUMBER, album_id+i+1,
00136                           -1);
00137     }
00138   freedb_table_number++;
00139   //free memory
00140   g_free(number);
00141 }
00142 
00144 GtkTreeModel *create_freedb_model()
00145 {
00146   GtkTreeStore *model = gtk_tree_store_new(FREEDB_TABLE, G_TYPE_STRING, G_TYPE_INT);
00147   return GTK_TREE_MODEL(model);
00148 }
00149 
00151 GtkTreeView *create_freedb_tree()
00152 {
00153   GtkTreeModel *model = (GtkTreeModel *)create_freedb_model();
00154   GtkTreeView *tree_view = (GtkTreeView *)gtk_tree_view_new_with_model(model);
00155   return tree_view;
00156 }
00157 
00159 void create_freedb_columns(GtkTreeView *tree_view)
00160 {
00161   GtkCellRendererText *renderer = GTK_CELL_RENDERER_TEXT(gtk_cell_renderer_text_new ());
00162   g_object_set_data(G_OBJECT(renderer), "col", GINT_TO_POINTER(ALBUM_NAME));
00163   GtkTreeViewColumn *name_column = gtk_tree_view_column_new_with_attributes 
00164     (_("Album title"), GTK_CELL_RENDERER(renderer),
00165      "text", ALBUM_NAME, NULL);
00166 
00167   //appends columns to the list of columns of tree_view
00168   gtk_tree_view_insert_column(GTK_TREE_VIEW(tree_view),
00169       GTK_TREE_VIEW_COLUMN(name_column), ALBUM_NAME);
00170 
00171   //middle alignment of the column name
00172   gtk_tree_view_column_set_alignment(GTK_TREE_VIEW_COLUMN(name_column), 0.5);
00173   gtk_tree_view_column_set_sizing(GTK_TREE_VIEW_COLUMN(name_column),
00174                                    GTK_TREE_VIEW_COLUMN_AUTOSIZE);
00175   gtk_tree_view_column_set_expand(GTK_TREE_VIEW_COLUMN(name_column), TRUE);
00176 
00177   gtk_tree_view_column_set_resizable(GTK_TREE_VIEW_COLUMN(name_column), TRUE);
00178 }
00179 
00181 void close_freedb_popup_window_event(GtkWidget *window, gpointer data)
00182 {
00183   GtkWidget *window_child = gtk_bin_get_child(GTK_BIN(window));
00184   gtk_widget_reparent(GTK_WIDGET(window_child), GTK_WIDGET(freedb_handle_box));
00185   gtk_widget_destroy(window);
00186 }
00187 
00189 void handle_freedb_detached_event(GtkHandleBox *handlebox, GtkWidget *widget,
00190     gpointer data)
00191 {
00192   GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
00193   gtk_widget_reparent(GTK_WIDGET(widget), GTK_WIDGET(window));
00194   g_signal_connect(G_OBJECT(window), "delete_event",
00195       G_CALLBACK(close_freedb_popup_window_event), NULL);
00196   gtk_widget_show(GTK_WIDGET(window));
00197 }
00198 
00200 void freedb_selection_changed(GtkTreeSelection *selection, gpointer data)
00201 {
00202   GtkTreeIter iter;
00203   GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(freedb_tree));
00204 
00205   if (gtk_tree_selection_get_selected(selection, &model, &iter))
00206   {
00207     gchar *info;
00208     gtk_tree_model_get (model, &iter,
00209         ALBUM_NAME, &info,
00210         NUMBER, &selected_id,
00211         -1);
00212 
00213     g_free(info);
00214     gtk_widget_set_sensitive(GTK_WIDGET(freedb_add_button), TRUE);
00215   }
00216   else {
00217     gtk_widget_set_sensitive(GTK_WIDGET(freedb_add_button), FALSE);
00218   }
00219 }
00220 
00222 void remove_all_freedb_rows()
00223 {
00224   GtkTreeView *tree_view = (GtkTreeView *)freedb_tree;
00225   GtkTreeModel *model = gtk_tree_view_get_model(tree_view);
00226 
00227   while (freedb_table_number > 0)
00228   {
00229     GtkTreeIter iter;
00230     gtk_tree_model_get_iter_first(model, &iter);
00231     gtk_tree_store_remove(GTK_TREE_STORE(model), &iter);
00232     freedb_table_number--;
00233   }
00234 }
00235 
00237 gpointer freedb_search(gpointer data)
00238 {
00239   enter_threads();
00240 
00241   executed_lock = TRUE;
00242  
00243   gtk_widget_hide(freedb_search_button);
00244   gtk_widget_show(spinner);
00245   gtk_spinner_start(GTK_SPINNER(spinner));
00246 
00247   gtk_widget_set_sensitive(GTK_WIDGET(freedb_add_button), FALSE);
00248   gtk_editable_set_editable(GTK_EDITABLE(freedb_entry), FALSE);
00249  
00250   put_status_message(_("please wait... contacting tracktype.org"));
00251  
00252   const gchar *freedb_search = gtk_entry_get_text(GTK_ENTRY(freedb_entry));
00253   
00254   exit_threads();
00255   
00256   gint err = SPLT_OK;
00257   search_results = mp3splt_get_freedb_search(the_state, freedb_search, &err,
00258       SPLT_FREEDB_SEARCH_TYPE_CDDB_CGI, "\0",-1);
00259  
00260   enter_threads();
00261 
00262   print_status_bar_confirmation(err);
00263  
00264   remove_all_freedb_rows();
00265  
00266   if (err >= 0)
00267   {
00268     gint i = 0;
00269     for (i = 0; i< search_results->number;i++)
00270     {
00271       gint must_be_free = SPLT_FALSE;
00272       search_results->results[i].name =
00273         transform_to_utf8(search_results->results[i].name,
00274             TRUE, &must_be_free);
00275       add_freedb_row(search_results->results[i].name,
00276           search_results->results[i].id,
00277           search_results->results[i].revisions,
00278           search_results->results[i].revision_number);
00279     }
00280 
00281     if (search_results->number > 0)
00282     {
00283       //select the first result
00284       GtkTreeModel *model;
00285       GtkTreePath *path;
00286       GtkTreeIter iter;
00287       GtkTreeSelection *selection;
00288       selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(freedb_tree));
00289 
00290       model = gtk_tree_view_get_model(GTK_TREE_VIEW(freedb_tree));
00291       path = gtk_tree_path_new_from_indices (0 ,-1);
00292       gtk_tree_model_get_iter(model, &iter, path);
00293       gtk_tree_selection_select_iter(selection, &iter);
00294       gtk_tree_path_free(path);
00295     }
00296   }
00297  
00298   gtk_widget_show(freedb_search_button);
00299   gtk_spinner_stop(GTK_SPINNER(spinner));
00300   gtk_widget_hide(spinner);
00301 
00302   gtk_editable_set_editable(GTK_EDITABLE(freedb_entry), TRUE);
00303  
00304   executed_lock = FALSE;
00305 
00306   exit_threads();
00307 
00308   return NULL;
00309 }
00310 
00312 void freedb_search_start_thread()
00313 {
00314   if (executed_lock) { return; }
00315 
00316   mp3splt_set_int_option(the_state, SPLT_OPT_DEBUG_MODE, debug_is_active);
00317   create_thread(freedb_search, NULL, TRUE, NULL);
00318 }
00319 
00321 void freedb_search_button_event(GtkWidget *widget, gpointer   data)
00322 {
00323   freedb_search_start_thread();
00324 }
00325 
00330 void freedb_entry_activate_event(GtkEntry *entry, gpointer data)
00331 {
00332   freedb_search_start_thread();
00333 }
00334 
00339 void write_freedbfile(int *err)
00340 {
00341   gchar *filename = NULL;
00342  
00343   enter_threads();
00344    
00345   put_status_message(_("please wait... contacting tracktype.org"));
00346   
00347   //we suppose directory exists
00348   //it should be created when mp3splt-gtk starts
00349   gchar mp3splt_dir[14] = ".mp3splt-gtk";
00350 
00351   const gchar *home_dir = g_get_home_dir();
00352   gint malloc_number = strlen(mp3splt_dir) + strlen(home_dir) + 20;
00353   filename = malloc(malloc_number * sizeof(gchar *));
00354   
00355   g_snprintf(filename,malloc_number,
00356              "%s%s%s%s%s", home_dir,
00357              G_DIR_SEPARATOR_S, mp3splt_dir,
00358              G_DIR_SEPARATOR_S, "query.cddb");
00359  
00360   exit_threads();
00361 
00362   //we write the freedb file ...
00363   mp3splt_write_freedb_file_result(the_state, selected_id,
00364                                    filename, err,
00365                                    //for now cddb.cgi get file type
00366                                    SPLT_FREEDB_GET_FILE_TYPE_CDDB_CGI,
00367                                    "\0",-1);
00368 
00369   enter_threads();
00370   print_status_bar_confirmation(*err);
00371   exit_threads();
00372 
00373   if(get_checked_output_radio_box())
00374   {
00375     mp3splt_set_int_option(the_state, SPLT_OPT_OUTPUT_FILENAMES,
00376         SPLT_OUTPUT_DEFAULT);
00377   }
00378   else
00379   {
00380     mp3splt_set_int_option(the_state, SPLT_OPT_OUTPUT_FILENAMES,
00381         SPLT_OUTPUT_FORMAT);
00382 
00383     const char *data = gtk_entry_get_text(GTK_ENTRY(output_entry));
00384     gint error = SPLT_OUTPUT_FORMAT_OK;
00385     mp3splt_set_oformat(the_state, data, &error);
00386     enter_threads();
00387     print_status_bar_confirmation(error);
00388     exit_threads();
00389   }
00390 
00391   mp3splt_put_cddb_splitpoints_from_file(the_state,filename, err);
00392  
00393   if (filename)
00394   {
00395     g_free(filename);
00396     filename = NULL;
00397   }
00398 }
00399 
00401 void get_secs_mins_hundr(gfloat time,
00402                          gint *mins,gint *secs, 
00403                          gint *hundr)
00404 {
00405   *mins = (gint)(time / 6000);
00406   *secs = (gint)(time - (*mins * 6000))
00407     / 100;
00408   *hundr = (gint)(time - (*mins * 6000)
00409                   - (*secs * 100));
00410 }
00411 
00418 void update_splitpoints_from_the_state()
00419 {
00420   gint max_splits = 0;
00421   gint err = SPLT_OK;
00422 
00423   exit_threads();
00424   const splt_point *points = mp3splt_get_splitpoints(the_state, &max_splits,&err);
00425   enter_threads();
00426 
00427   print_status_bar_confirmation(err);
00428   
00429   //only if we have splitpoints
00430   if (max_splits > 0)
00431   {
00432     //erase rows from the splitpoints table
00433     remove_all_rows(NULL,NULL);
00434     gint i;
00435 
00436     //for each splitpoint, we put it in the table
00437     for(i = 0; i < max_splits;i++)
00438     {
00439       //ugly hack because we use maximum ints in the GUI
00440       //-GUI must be changed to accept long values
00441       long old_point_value = points[i].value;
00442       int point_value = (int) old_point_value;
00443       if (old_point_value > INT_MAX)
00444       {
00445         point_value = INT_MAX;
00446       }
00447 
00448       //we get the minutes, seconds and hundreths
00449       get_secs_mins_hundr(point_value,
00450           &spin_mins, &spin_secs,
00451           &spin_hundr_secs);
00452 
00453       gint must_be_free = FALSE;
00454       gchar *result_utf8 = points[i].name;
00455 
00456       if (result_utf8 != NULL)
00457       {
00458         result_utf8 = transform_to_utf8(result_utf8, 
00459             FALSE, &must_be_free);
00460 
00461         g_snprintf(current_description,255,
00462             "%s", result_utf8);
00463       }
00464       else
00465       {
00466         g_snprintf(current_description, 255, "%s", _("description here"));
00467       }
00468 
00469       if (must_be_free)
00470       {
00471         g_free(result_utf8);
00472         result_utf8 = NULL;
00473       }
00474 
00475       //we add the row
00476       if (points[i].type == SPLT_SPLITPOINT)
00477       {
00478         add_row(TRUE);
00479       }
00480       else if (points[i].type == SPLT_SKIPPOINT)
00481       {
00482         add_row(FALSE);
00483       }
00484     }
00485 
00486     //we reput the "description here" name
00487     g_snprintf(current_description, 255, "%s",
00488         _("description here"));
00489 
00490     update_minutes_from_spinner(NULL,NULL);
00491     update_seconds_from_spinner(NULL,NULL);
00492     update_hundr_secs_from_spinner(NULL,NULL);
00493     update_add_button();
00494   }
00495 }
00496 
00497 gpointer put_freedb_splitpoints(gpointer data)
00498 {
00499   gint err = SPLT_OK;
00500 
00501   enter_threads();
00502   gtk_widget_set_sensitive(GTK_WIDGET(freedb_add_button), FALSE);  
00503   exit_threads();
00504  
00505   write_freedbfile(&err);
00506  
00507   enter_threads();
00508  
00509   update_splitpoints_from_the_state();
00510   print_status_bar_confirmation(err);
00511   gtk_widget_set_sensitive(GTK_WIDGET(freedb_add_button), TRUE);
00512 
00513   exit_threads();
00514   
00515   return NULL;
00516 }
00517 
00519 void freedb_add_button_clicked_event(GtkButton *button, gpointer data)
00520 {
00521   mp3splt_set_int_option(the_state, SPLT_OPT_DEBUG_MODE, debug_is_active);
00522   create_thread(put_freedb_splitpoints, NULL, TRUE, NULL);
00523 }
00524 
00526 GtkWidget *create_freedb_frame()
00527 {
00528   GtkWidget *freedb_hbox = gtk_hbox_new(FALSE, 0);
00529   gtk_container_set_border_width(GTK_CONTAINER(freedb_hbox), 0);
00530   
00531   /* handle box for detaching */
00532   freedb_handle_box = gtk_handle_box_new();
00533   gtk_container_add(GTK_CONTAINER(freedb_handle_box), GTK_WIDGET(freedb_hbox));
00534   g_signal_connect(freedb_handle_box, "child-detached",
00535                    G_CALLBACK(handle_freedb_detached_event),
00536                    NULL);
00537   
00538   GtkWidget *freedb_vbox = gtk_vbox_new(FALSE, 0);
00539   gtk_box_pack_start(GTK_BOX(freedb_hbox), freedb_vbox, TRUE, TRUE, 4);
00540   
00541   /* search box */
00542   GtkWidget *search_hbox = gtk_hbox_new(FALSE, 0);
00543   gtk_box_pack_start(GTK_BOX(freedb_vbox), search_hbox , FALSE, FALSE, 2);
00544 
00545   GtkWidget *label = gtk_label_new(_("Search tracktype.org:"));
00546   gtk_box_pack_start(GTK_BOX(search_hbox), label, FALSE, FALSE, 0);
00547 
00548   freedb_entry = gtk_entry_new();
00549   gtk_editable_set_editable(GTK_EDITABLE(freedb_entry), TRUE);
00550   gtk_box_pack_start(GTK_BOX(search_hbox), freedb_entry, TRUE, TRUE, 6);
00551 
00552   g_signal_connect(G_OBJECT(freedb_entry), "activate",
00553       G_CALLBACK(freedb_entry_activate_event), NULL);
00554 
00555   freedb_search_button = (GtkWidget *)
00556     create_cool_button(GTK_STOCK_FIND, _("_Search"),FALSE);
00557   g_signal_connect(G_OBJECT(freedb_search_button), "clicked",
00558       G_CALLBACK(freedb_search_button_event), NULL);
00559   gtk_box_pack_start(GTK_BOX(search_hbox), freedb_search_button, FALSE, FALSE, 0);
00560  
00561   spinner = gtk_spinner_new();
00562   gtk_box_pack_start(GTK_BOX(search_hbox), spinner, FALSE, FALSE, 4);
00563 
00564   /* freedb scrolled window and the tree */
00565   freedb_tree = (GtkWidget *) create_freedb_tree();
00566 
00567   GtkWidget *scrolled_window;
00568   scrolled_window = gtk_scrolled_window_new(NULL, NULL);
00569   gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_window), GTK_SHADOW_NONE);
00570   gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
00571                                   GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
00572   gtk_box_pack_start(GTK_BOX(freedb_vbox), scrolled_window, TRUE, TRUE, 1);
00573 
00574   create_freedb_columns(GTK_TREE_VIEW(freedb_tree));
00575 
00576   gtk_container_add(GTK_CONTAINER(scrolled_window), GTK_WIDGET(freedb_tree));
00577   
00578   GtkWidget *freedb_tree_selection;
00579   freedb_tree_selection = (GtkWidget *)
00580     gtk_tree_view_get_selection(GTK_TREE_VIEW(freedb_tree));
00581   g_signal_connect(G_OBJECT(freedb_tree_selection), "changed",
00582                     G_CALLBACK(freedb_selection_changed), NULL);
00583 
00584   /* add button */
00585   GtkWidget *selected_hbox = gtk_hbox_new(FALSE, 0);
00586   gtk_box_pack_start(GTK_BOX(freedb_vbox), selected_hbox , FALSE, FALSE, 2);
00587 
00588   freedb_add_button = (GtkWidget *)
00589     create_cool_button(GTK_STOCK_ADD,_("_Add splitpoints"), FALSE);
00590 
00591   gtk_widget_set_sensitive(GTK_WIDGET(freedb_add_button), FALSE);
00592   g_signal_connect(G_OBJECT(freedb_add_button), "clicked",
00593       G_CALLBACK(freedb_add_button_clicked_event), NULL);
00594   gtk_box_pack_start(GTK_BOX(selected_hbox), freedb_add_button, FALSE, FALSE, 0);
00595   gtk_widget_set_tooltip_text(freedb_add_button, 
00596       _("Set splitpoints to the splitpoints table"));
00597   
00598   return freedb_handle_box;
00599 }
00600 
00601 void hide_freedb_spinner()
00602 {
00603   gtk_widget_hide(spinner);
00604 }
00605