mp3splt-gtk
mp3splt-gtk.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 main file,
00035  *
00036  * this file contains the main() function as well as some 
00037  * globally used functions.
00038  *********************************************************/
00039 
00040 #include <signal.h>
00041 #include <locale.h>
00042 #include <string.h>
00043 #include <ctype.h>
00044 #include <unistd.h>
00045 
00046 #include <sys/stat.h>
00047 #include <sys/types.h>
00048 
00049 #include <glib/gi18n.h>
00050 #include <glib.h>
00051 
00052 #include <gtk/gtk.h>
00053 #include <libmp3splt/mp3splt.h>
00054 
00055 #ifdef __WIN32__
00056 #include <windows.h>
00057 #include <shlwapi.h>
00058 #endif
00059 
00060 #include "util.h"
00061 #include "special_split.h"
00062 #include "player.h"
00063 #include "utilities.h"
00064 #include "tree_tab.h"
00065 #include "main_win.h"
00066 #include "snackamp_control.h"
00067 #include "split_files.h"
00068 #include "preferences_tab.h"
00069 #include "multiple_files.h"
00070 #include "preferences_manager.h"
00071 #include "player_tab.h"
00072 #include "import.h"
00073 #include "mp3splt-gtk.h"
00074 
00075 #include "ui_manager.h"
00076 
00077 //the state
00078 splt_state *the_state = NULL;
00079 
00080 //the progress bar
00081 GtkWidget *progress_bar;
00082 
00083 extern GArray *splitpoints;
00084 extern gint splitnumber;
00085 extern GtkWidget *queue_files_button;
00086 extern gchar *filename_to_split;
00087 extern gchar *filename_path_of_split;
00088 
00089 //EXTERNAL OPTIONS
00090 //frame mode option
00091 extern GtkWidget *frame_mode;
00092 //auto-adjust option
00093 extern GtkWidget *adjust_mode;
00094 //gap parameter
00095 extern GtkWidget *spinner_adjust_gap;
00096 //offset parameter
00097 extern GtkWidget *spinner_adjust_offset;
00098 //threshold parameter
00099 extern GtkWidget *spinner_adjust_threshold;
00100 
00101 extern GtkWidget *create_dirs_from_output_files;
00102 
00103 //silence mode parameters
00104 //number of tracks parameter
00105 extern GtkWidget *spinner_silence_number_tracks;
00106 //number of tracks parameter
00107 extern GtkWidget *spinner_silence_minimum;
00108 //offset parameter
00109 extern GtkWidget *spinner_silence_offset;
00110 //threshold parameter
00111 extern GtkWidget *spinner_silence_threshold;
00112 //remove silence check button (silence mode parameter
00113 extern GtkWidget *silence_remove_silence;
00114 
00115 //spinner time
00116 extern GtkWidget *spinner_time;
00117 
00118 //player
00119 extern gint selected_player;
00120 
00121 //if we are currently splitting
00122 extern gint we_are_splitting;
00123 //if we quit the main program while splitting
00124 extern gint we_quit_main_program;
00125 //the percent progress bar
00126 extern GtkWidget *percent_progress_bar;
00127 
00128 //stop button to cancel the split
00129 extern GtkWidget *cancel_button;
00130 
00131 //the output entry
00132 extern GtkWidget *output_entry;
00133 
00134 extern GtkWidget *remove_all_files_button;
00135 
00136 extern gint split_file_mode;
00137 extern GtkWidget *multiple_files_tree;
00138 extern gint multiple_files_tree_number;
00139 
00140 //how many split files
00141 gint split_files = 0;
00142 
00144 ui_state *ui = NULL;
00145 
00147 void put_split_filename(const char *filename,int progress_data)
00148 {
00149   enter_threads();
00150 
00151   if (!gtk_widget_get_sensitive(queue_files_button))
00152   {
00153     gtk_widget_set_sensitive(queue_files_button, TRUE);
00154   }
00155   if (!gtk_widget_get_sensitive(remove_all_files_button))
00156   {
00157     gtk_widget_set_sensitive(remove_all_files_button,TRUE);
00158   }
00159 
00160   add_split_row(filename);
00161   split_files++;
00162 
00163   gint fname_status_size = (strlen(filename) + 255);
00164   gchar *fname_status = g_malloc(sizeof(char) * fname_status_size);
00165   g_snprintf(fname_status, fname_status_size,
00166       _(" File '%s' created"), filename);
00167   put_status_message(fname_status);
00168   if (fname_status)
00169   {
00170     free(fname_status);
00171     fname_status = NULL;
00172   }
00173 
00174 #ifdef __WIN32__
00175   while (gtk_events_pending())
00176   {
00177           gtk_main_iteration();
00178   }
00179   gdk_flush();
00180 #endif
00181 
00182   exit_threads();
00183 }
00184 
00186 void change_window_progress_bar(splt_progress *p_bar)
00187 {
00188   gchar progress_text[1024] = " ";
00189 
00190   switch (p_bar->progress_type)
00191   {
00192     case SPLT_PROGRESS_PREPARE:
00193       g_snprintf(progress_text,1023, _(" preparing \"%s\" (%d of %d)"),
00194           p_bar->filename_shorted,
00195           p_bar->current_split,
00196           p_bar->max_splits);
00197       break;
00198     case SPLT_PROGRESS_CREATE:
00199       g_snprintf(progress_text,1023, _(" creating \"%s\" (%d of %d)"),
00200           p_bar->filename_shorted,
00201           p_bar->current_split,
00202           p_bar->max_splits);
00203       break;
00204     case SPLT_PROGRESS_SEARCH_SYNC:
00205       g_snprintf(progress_text,1023, _(" searching for sync errors..."));
00206       break;
00207     case SPLT_PROGRESS_SCAN_SILENCE:
00208       g_snprintf(progress_text,1023,
00209                       _("S: %02d, Level: %.2f dB; scanning for silence..."),
00210                       p_bar->silence_found_tracks, p_bar->silence_db_level);
00211       break;
00212     default:
00213       g_snprintf(progress_text,1023, " ");
00214       break;
00215   }
00216 
00217   gchar printed_value[1024] = { '\0' };
00218 
00219   enter_threads();
00220 
00221   gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(percent_progress_bar),
00222       p_bar->percent_progress);
00223   g_snprintf(printed_value,1023,"%6.2f %% %s", p_bar->percent_progress * 100,
00224       progress_text);
00225 
00226   gtk_progress_bar_set_text(GTK_PROGRESS_BAR(percent_progress_bar),
00227       printed_value);
00228 
00229 #ifdef __WIN32__
00230   while (gtk_events_pending())
00231   {
00232           gtk_main_iteration();
00233   }
00234   gdk_flush();
00235 #endif
00236 
00237   exit_threads();
00238 }
00239 
00241 gpointer split_it(gpointer data)
00242 {
00243   gint confirmation = SPLT_OK;
00244   
00245   enter_threads();
00246 
00247   remove_all_split_rows();
00248 
00249   exit_threads();
00250  
00251   gint err = SPLT_OK;
00252 
00253   mp3splt_erase_all_splitpoints(the_state,&err);
00254 
00255   //we erase previous tags if we don't have the option
00256   //splt_current_tags
00257   if ((mp3splt_get_int_option(the_state, SPLT_OPT_TAGS, &err) !=
00258         (SPLT_CURRENT_TAGS) || split_file_mode == FILE_MODE_MULTIPLE))
00259   {
00260     mp3splt_erase_all_tags(the_state,&err);
00261   }
00262 
00263   gint split_mode =
00264     mp3splt_get_int_option(the_state, SPLT_OPT_SPLIT_MODE, &err);
00265 
00266   enter_threads();
00267   print_status_bar_confirmation(err);
00268   
00269   gchar *format = strdup(gtk_entry_get_text(GTK_ENTRY(output_entry)));
00270   exit_threads();
00271 
00272   mp3splt_set_oformat(the_state, format, &err);
00273   if (format)
00274   {
00275     free(format);
00276     format = NULL;
00277   }
00278  
00279   //if we have the normal split mode, enable default output
00280   gint output_filenames = 
00281     mp3splt_get_int_option(the_state, SPLT_OPT_OUTPUT_FILENAMES,&err);
00282   if (mp3splt_get_int_option(the_state, SPLT_OPT_SPLIT_MODE,&err)
00283       == SPLT_OPTION_NORMAL_MODE)
00284   {
00285     mp3splt_set_int_option(the_state, SPLT_OPT_OUTPUT_FILENAMES,
00286         SPLT_OUTPUT_CUSTOM);
00287   }
00288 
00289   mp3splt_set_path_of_split(the_state,filename_path_of_split);
00290 
00291   gint multiple_files_error = SPLT_FALSE;
00292   if (split_file_mode == FILE_MODE_SINGLE)
00293   {
00294     enter_threads();
00295 
00296     if (split_mode == SPLT_OPTION_NORMAL_MODE)
00297     {
00298       put_splitpoints_in_the_state(the_state);
00299     }
00300 
00301     print_processing_file(filename_to_split);
00302     exit_threads();
00303 
00304     mp3splt_set_filename_to_split(the_state, filename_to_split);
00305     confirmation = mp3splt_split(the_state);
00306   }
00307   else
00308   {
00309     if (multiple_files_tree_number > 0)
00310     {
00311       enter_threads();
00312 
00313       gchar *filename = NULL;
00314       GtkTreeIter iter;
00315       GtkTreePath *path;
00316       GtkTreeModel *model =
00317         gtk_tree_view_get_model(GTK_TREE_VIEW(multiple_files_tree));
00318 
00319       exit_threads();
00320 
00321       gint row_number = 0;
00322       while (row_number < multiple_files_tree_number)
00323       {
00324         enter_threads();
00325 
00326         if (split_mode == SPLT_OPTION_NORMAL_MODE)
00327         {
00328           put_splitpoints_in_the_state(the_state);
00329         }
00330 
00331         path = gtk_tree_path_new_from_indices(row_number ,-1);
00332         gtk_tree_model_get_iter(model, &iter, path);
00333         gtk_tree_model_get(model, &iter, MULTIPLE_COL_FILENAME,
00334             &filename, -1);
00335 
00336         print_processing_file(filename);
00337 
00338         exit_threads();
00339 
00340         mp3splt_set_filename_to_split(the_state, filename);
00341         confirmation = mp3splt_split(the_state);
00342 
00343         if (filename)
00344         {
00345           g_free(filename);
00346           filename = NULL;
00347         }
00348 
00349         if (confirmation < 0)
00350         {
00351           break;
00352         }
00353 
00354         row_number++;
00355 
00356         enter_threads();
00357 
00358         mp3splt_erase_all_tags(the_state, &err);
00359         print_status_bar_confirmation(err);
00360         err = SPLT_OK;
00361         mp3splt_erase_all_splitpoints(the_state, &err);
00362         print_status_bar_confirmation(err);
00363 
00364         exit_threads();
00365       }
00366     }
00367     else
00368     {
00369       multiple_files_error = SPLT_TRUE;
00370 
00371       enter_threads();
00372       put_status_message(_(" error: no files found in multiple files mode"));
00373       exit_threads();
00374     }
00375   }
00376 
00379   mp3splt_set_int_option(the_state, SPLT_OPT_OUTPUT_FILENAMES, output_filenames);
00380   
00381   enter_threads();
00382 
00383   //we show infos about the split action
00384   print_status_bar_confirmation(confirmation);
00385   
00386   //see the cancel button
00387   gtk_widget_set_sensitive(GTK_WIDGET(cancel_button), FALSE);
00388   
00389   //we look if we have pushed the exit button
00390   if (we_quit_main_program)
00391   {
00392     quit(NULL,NULL);
00393   }
00394   
00395   if (confirmation >= 0 && !multiple_files_error)
00396   {
00397     gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(percent_progress_bar), 1.0);
00398     gtk_progress_bar_set_text(GTK_PROGRESS_BAR(percent_progress_bar),
00399         _(" finished"));
00400   }
00401 
00402   we_are_splitting = FALSE;
00403 
00404   exit_threads();
00405  
00406   return NULL;
00407 }
00408 
00413 void sigpipe_handler(gint sig)
00414 {
00415   if (player_is_running() && selected_player == PLAYER_SNACKAMP)
00416   {
00417     disconnect_snackamp();
00418   }
00419 }
00420 
00421 gboolean sigint_called = FALSE;
00423 void sigint_handler(gint sig)
00424 {
00425   if (!sigint_called)
00426   {
00427     sigint_called = TRUE;
00428     we_quit_main_program = TRUE;
00429     quit(NULL,NULL);
00430   }
00431 }
00432 
00434 void put_message_from_library(const char *message, splt_message_type mess_type)
00435 {
00436   gchar *mess = g_strdup(message);
00437   if (mess)
00438   {
00439     gint i = 0;
00440     //replace '\n' with ' '
00441     for (i = 0;i < strlen(mess);i++)
00442     {
00443       if (mess[i] == '\n')
00444       {
00445         mess[i] = ' ';
00446       }
00447     }
00448     enter_threads();
00449 
00450     put_status_message_with_type(mess, mess_type);
00451 
00452 #ifdef __WIN32__
00453   while (gtk_events_pending())
00454   {
00455           gtk_main_iteration();
00456   }
00457   gdk_flush();
00458 #endif
00459 
00460     exit_threads();
00461     g_free(mess);
00462     mess = NULL;
00463   }
00464 }
00465 
00466 GThread *create_thread(GThreadFunc func, gpointer data,
00467                 gboolean joinable, GError **error)
00468 {
00469 /*#ifdef __WIN32__
00470         func(data);
00471         return NULL;
00472         return g_thread_create(func, data, joinable, error);
00473 #else*/
00474         return g_thread_create(func, data, joinable, error);
00475 //#endif
00476 }
00477 
00478 void enter_threads()
00479 {
00480         gdk_threads_enter();
00481 }
00482 
00483 void exit_threads()
00484 {
00485         gdk_threads_leave();
00486 }
00487 
00511 gint main(gint argc, gchar *argv[], gchar **envp)
00512 {
00513   ui = ui_state_new();
00514 
00515   int OptionChar;
00516 
00517   //init threads
00518   g_thread_init(NULL);
00519   gdk_threads_init();
00520 
00521   gint error = 0;
00522   
00523   //close nicely
00524   signal (SIGINT, sigint_handler);
00525   
00526 #ifndef __WIN32__
00527   signal (SIGPIPE, sigpipe_handler);
00528 #endif
00529    
00530   //create new state
00531   the_state = mp3splt_new_state(&error);
00532 
00533   //used for gettext
00534   setlocale (LC_ALL, "");
00535   textdomain ("mp3splt-gtk");
00536 
00537 #ifdef __WIN32__
00538   char mp3splt_uninstall_file[2048] = { '\0' };
00539   DWORD dwType, dwSize = sizeof(mp3splt_uninstall_file) - 1;
00540   SHGetValue(HKEY_LOCAL_MACHINE,
00541         TEXT("SOFTWARE\\mp3splt-gtk"),
00542         TEXT("UninstallString"),
00543         &dwType,
00544         mp3splt_uninstall_file,
00545         &dwSize);
00546 
00547   gchar *end = strrchr(mp3splt_uninstall_file, SPLT_DIRCHAR);
00548   if (end) { *end = '\0'; }
00549 
00550   gchar *executable_dir = NULL;
00551   gchar *executable = strdup(argv[0]);
00552 
00553   end = strrchr(executable, SPLT_DIRCHAR);
00554   if (end)
00555   {
00556     *end = '\0';
00557     executable_dir = executable;
00558   }
00559   else
00560   {
00561     if (mp3splt_uninstall_file[0] != '\0')
00562     {
00563       executable_dir = mp3splt_uninstall_file;
00564     }
00565   }
00566 
00567   bindtextdomain(MP3SPLT_LIB_GETTEXT_DOMAIN, "translations");
00568   bindtextdomain("mp3splt-gtk", "translations");
00569 
00570 #else
00571   bindtextdomain("mp3splt-gtk", LOCALEDIR);
00572 #endif
00573 
00574   bind_textdomain_codeset("mp3splt-gtk", "UTF-8");
00575  
00576   // Allow the gtk to parse all gtk arguments from the command 
00577   // line first
00578   gtk_init(&argc, &argv);
00579   
00580   // Now pass all remaining arguments to getopt.
00581   opterr = 0;
00582   
00583   while ((OptionChar = getopt (argc, argv, "d:")) != -1)
00584     switch (OptionChar)
00585       {
00586       case 'd':
00587         fprintf (stderr, _("Trying to set the output directory to %s.\n"), optarg);
00588         outputdirectory_set((gchar *)optarg);
00589 #ifdef __WIN32__
00590         mkdir(optarg);
00591 #else
00592         mkdir(optarg, 0777);
00593 #endif
00594         if(!check_if_dir((guchar *)optarg))
00595           {
00596             fprintf(stderr,_("Error: The specified output directory is inaccessible!\n"));
00597             exit(-1);
00598           }
00599         break;
00600       case '?':
00601         if (optopt == 'd')
00602           fprintf (stderr, _("Option -%c requires an argument.\n"), optopt);
00603         else if (isprint (optopt))
00604           fprintf (stderr, _("Unknown option `-%c'.\n"), optopt);
00605         else
00606           fprintf (stderr,
00607                    _("Unknown option character `\\x%x'.\n"),
00608                    optopt);
00609         return 1;
00610       default:
00611         abort ();
00612       }
00613   
00614   // If we have a filename at the command line is checked after the
00615   // GUI is up.
00616 
00617   //We initialise the splitpoints array
00618   splitpoints = g_array_new(FALSE, FALSE, sizeof (Split_point));
00619  
00620   //check if preferences file exists
00621   //and if it does not create it
00622   check_pref_file();
00623  
00624   mp3splt_set_progress_function(the_state,change_window_progress_bar);
00625   mp3splt_set_split_filename_function(the_state,put_split_filename);
00626   mp3splt_set_message_function(the_state, put_message_from_library);
00627 
00628   mp3splt_set_int_option(the_state, SPLT_OPT_DEBUG_MODE, SPLT_FALSE);
00629   mp3splt_set_int_option(the_state,
00630       SPLT_OPT_SET_FILE_FROM_CUE_IF_FILE_TAG_FOUND, SPLT_TRUE);
00631 
00632   //add special directory search for plugins on Windows
00633 #ifdef __WIN32__
00634   if (executable != NULL)
00635   {
00636     if (executable[0] != '\0')
00637     {
00638       g_setenv("GST_PLUGIN_PATH", ".\\", TRUE);
00639       mp3splt_append_plugins_scan_dir(the_state, executable);
00640       _chdir(executable);
00641     }
00642   }
00643 #endif
00644 
00645   //main program
00646   create_all();
00647   error = mp3splt_find_plugins(the_state);
00648   if (error < 0)
00649   {
00650     print_status_bar_confirmation(error);
00651   }
00652 
00653   // Now let's see if we found a filename at the command line.
00654   if (optind != argc) 
00655     {
00656       if(!check_if_file((guchar *)argv[optind]))
00657         {
00658           fprintf (stderr,
00659                    _("Cannot open input file %s\n"),
00660                    argv[optind]);
00661         return 1;
00662         }
00663 
00664 #ifndef __WIN32__
00665       // If we start the player it will find a file with a relative
00666       // pathname. But if the player is already running it might
00667       // need an absolute path.
00668       char *inputfilename=realpath(argv[optind],NULL);
00669       handle_import(inputfilename);
00670       free(inputfilename);
00671 #else
00672       handle_import(argv[optind]);
00673 #endif
00674     }
00675 
00676   gdk_threads_enter();
00677   gtk_main();
00678   exit_threads();
00679 
00680   mp3splt_free_state(the_state, &error);
00681 
00682   ui_state_free(ui);
00683   
00684   return 0;
00685 }
00686