mp3splt-gtk
mp3splt-gtk.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 main file,
35  *
36  * this file contains the main() function as well as some
37  * globally used functions.
38  *********************************************************/
39 
40 #include <signal.h>
41 #include <locale.h>
42 #include <string.h>
43 #include <ctype.h>
44 #include <unistd.h>
45 
46 #include <sys/stat.h>
47 #include <sys/types.h>
48 
49 #include <glib/gi18n.h>
50 #include <glib.h>
51 
52 #include <gtk/gtk.h>
53 #include <libmp3splt/mp3splt.h>
54 
55 #ifdef __WIN32__
56 #include <windows.h>
57 #include <shlwapi.h>
58 #endif
59 
60 #include "util.h"
61 #include "special_split.h"
62 #include "player.h"
63 #include "utilities.h"
64 #include "tree_tab.h"
65 #include "main_win.h"
66 #include "snackamp_control.h"
67 #include "split_files.h"
68 #include "preferences_tab.h"
69 #include "multiple_files.h"
70 #include "preferences_manager.h"
71 #include "player_tab.h"
72 #include "import.h"
73 #include "mp3splt-gtk.h"
74 
75 #include "ui_manager.h"
76 
77 //the state
78 splt_state *the_state = NULL;
79 
80 //the progress bar
81 GtkWidget *progress_bar;
82 
83 extern GArray *splitpoints;
84 extern gint splitnumber;
85 extern GtkWidget *queue_files_button;
86 extern gchar *filename_to_split;
87 extern gchar *filename_path_of_split;
88 
89 //EXTERNAL OPTIONS
90 //frame mode option
91 extern GtkWidget *frame_mode;
92 //auto-adjust option
93 extern GtkWidget *adjust_mode;
94 //gap parameter
95 extern GtkWidget *spinner_adjust_gap;
96 //offset parameter
97 extern GtkWidget *spinner_adjust_offset;
98 //threshold parameter
99 extern GtkWidget *spinner_adjust_threshold;
100 
101 extern GtkWidget *create_dirs_from_output_files;
102 
103 //silence mode parameters
104 //number of tracks parameter
105 extern GtkWidget *spinner_silence_number_tracks;
106 //number of tracks parameter
107 extern GtkWidget *spinner_silence_minimum;
108 //offset parameter
109 extern GtkWidget *spinner_silence_offset;
110 //threshold parameter
111 extern GtkWidget *spinner_silence_threshold;
112 //remove silence check button (silence mode parameter
113 extern GtkWidget *silence_remove_silence;
114 
115 //spinner time
116 extern GtkWidget *spinner_time;
117 
118 //player
119 extern gint selected_player;
120 
121 //if we are currently splitting
122 extern gint we_are_splitting;
123 //if we quit the main program while splitting
124 extern gint we_quit_main_program;
125 //the percent progress bar
126 extern GtkWidget *percent_progress_bar;
127 
128 //stop button to cancel the split
129 extern GtkWidget *cancel_button;
130 
131 //the output entry
132 extern GtkWidget *output_entry;
133 
134 extern GtkWidget *remove_all_files_button;
135 
136 extern gint split_file_mode;
137 extern GtkWidget *multiple_files_tree;
138 extern gint multiple_files_tree_number;
139 
140 //how many split files
141 gint split_files = 0;
142 
144 ui_state *ui = NULL;
145 
147 void put_split_filename(const char *filename,int progress_data)
148 {
149  enter_threads();
150 
151  if (!gtk_widget_get_sensitive(queue_files_button))
152  {
153  gtk_widget_set_sensitive(queue_files_button, TRUE);
154  }
155  if (!gtk_widget_get_sensitive(remove_all_files_button))
156  {
157  gtk_widget_set_sensitive(remove_all_files_button,TRUE);
158  }
159 
160  add_split_row(filename);
161  split_files++;
162 
163  gint fname_status_size = (strlen(filename) + 255);
164  gchar *fname_status = g_malloc(sizeof(char) * fname_status_size);
165  g_snprintf(fname_status, fname_status_size,
166  _(" File '%s' created"), filename);
167  put_status_message(fname_status);
168  if (fname_status)
169  {
170  free(fname_status);
171  fname_status = NULL;
172  }
173 
174 #ifdef __WIN32__
175  while (gtk_events_pending())
176  {
177  gtk_main_iteration();
178  }
179  gdk_flush();
180 #endif
181 
182  exit_threads();
183 }
184 
187 {
188  gchar progress_text[1024] = " ";
189 
190  switch (p_bar->progress_type)
191  {
193  g_snprintf(progress_text,1023, _(" preparing \"%s\" (%d of %d)"),
194  p_bar->filename_shorted,
195  p_bar->current_split,
196  p_bar->max_splits);
197  break;
199  g_snprintf(progress_text,1023, _(" creating \"%s\" (%d of %d)"),
200  p_bar->filename_shorted,
201  p_bar->current_split,
202  p_bar->max_splits);
203  break;
205  g_snprintf(progress_text,1023, _(" searching for sync errors..."));
206  break;
208  g_snprintf(progress_text,1023,
209  _("S: %02d, Level: %.2f dB; scanning for silence..."),
210  p_bar->silence_found_tracks, p_bar->silence_db_level);
211  break;
212  default:
213  g_snprintf(progress_text,1023, " ");
214  break;
215  }
216 
217  gchar printed_value[1024] = { '\0' };
218 
219  enter_threads();
220 
221  gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(percent_progress_bar),
222  p_bar->percent_progress);
223  g_snprintf(printed_value,1023,"%6.2f %% %s", p_bar->percent_progress * 100,
224  progress_text);
225 
226  gtk_progress_bar_set_text(GTK_PROGRESS_BAR(percent_progress_bar),
227  printed_value);
228 
229 #ifdef __WIN32__
230  while (gtk_events_pending())
231  {
232  gtk_main_iteration();
233  }
234  gdk_flush();
235 #endif
236 
237  exit_threads();
238 }
239 
241 gpointer split_it(gpointer data)
242 {
243  gint confirmation = SPLT_OK;
244 
245  enter_threads();
246 
248 
249  exit_threads();
250 
251  gint err = SPLT_OK;
252 
253  mp3splt_erase_all_splitpoints(the_state,&err);
254 
255  //we erase previous tags if we don't have the option
256  //splt_current_tags
257  if ((mp3splt_get_int_option(the_state, SPLT_OPT_TAGS, &err) !=
258  (SPLT_CURRENT_TAGS) || split_file_mode == FILE_MODE_MULTIPLE))
259  {
260  mp3splt_erase_all_tags(the_state,&err);
261  }
262 
263  gint split_mode =
264  mp3splt_get_int_option(the_state, SPLT_OPT_SPLIT_MODE, &err);
265 
266  enter_threads();
268 
269  gchar *format = strdup(gtk_entry_get_text(GTK_ENTRY(output_entry)));
270  exit_threads();
271 
272  mp3splt_set_oformat(the_state, format, &err);
273  if (format)
274  {
275  free(format);
276  format = NULL;
277  }
278 
279  //if we have the normal split mode, enable default output
280  gint output_filenames =
281  mp3splt_get_int_option(the_state, SPLT_OPT_OUTPUT_FILENAMES,&err);
282  if (mp3splt_get_int_option(the_state, SPLT_OPT_SPLIT_MODE,&err)
284  {
285  mp3splt_set_int_option(the_state, SPLT_OPT_OUTPUT_FILENAMES,
287  }
288 
289  mp3splt_set_path_of_split(the_state,filename_path_of_split);
290 
291  gint multiple_files_error = SPLT_FALSE;
292  if (split_file_mode == FILE_MODE_SINGLE)
293  {
294  enter_threads();
295 
296  if (split_mode == SPLT_OPTION_NORMAL_MODE)
297  {
298  put_splitpoints_in_the_state(the_state);
299  }
300 
301  print_processing_file(filename_to_split);
302  exit_threads();
303 
304  mp3splt_set_filename_to_split(the_state, filename_to_split);
305  confirmation = mp3splt_split(the_state);
306  }
307  else
308  {
309  if (multiple_files_tree_number > 0)
310  {
311  enter_threads();
312 
313  gchar *filename = NULL;
314  GtkTreeIter iter;
315  GtkTreePath *path;
316  GtkTreeModel *model =
317  gtk_tree_view_get_model(GTK_TREE_VIEW(multiple_files_tree));
318 
319  exit_threads();
320 
321  gint row_number = 0;
322  while (row_number < multiple_files_tree_number)
323  {
324  enter_threads();
325 
326  if (split_mode == SPLT_OPTION_NORMAL_MODE)
327  {
328  put_splitpoints_in_the_state(the_state);
329  }
330 
331  path = gtk_tree_path_new_from_indices(row_number ,-1);
332  gtk_tree_model_get_iter(model, &iter, path);
333  gtk_tree_model_get(model, &iter, MULTIPLE_COL_FILENAME,
334  &filename, -1);
335 
336  print_processing_file(filename);
337 
338  exit_threads();
339 
340  mp3splt_set_filename_to_split(the_state, filename);
341  confirmation = mp3splt_split(the_state);
342 
343  if (filename)
344  {
345  g_free(filename);
346  filename = NULL;
347  }
348 
349  if (confirmation < 0)
350  {
351  break;
352  }
353 
354  row_number++;
355 
356  enter_threads();
357 
358  mp3splt_erase_all_tags(the_state, &err);
360  err = SPLT_OK;
361  mp3splt_erase_all_splitpoints(the_state, &err);
363 
364  exit_threads();
365  }
366  }
367  else
368  {
369  multiple_files_error = SPLT_TRUE;
370 
371  enter_threads();
372  put_status_message(_(" error: no files found in multiple files mode"));
373  exit_threads();
374  }
375  }
376 
379  mp3splt_set_int_option(the_state, SPLT_OPT_OUTPUT_FILENAMES, output_filenames);
380 
381  enter_threads();
382 
383  //we show infos about the split action
384  print_status_bar_confirmation(confirmation);
385 
386  //see the cancel button
387  gtk_widget_set_sensitive(GTK_WIDGET(cancel_button), FALSE);
388 
389  //we look if we have pushed the exit button
390  if (we_quit_main_program)
391  {
392  quit(NULL,NULL);
393  }
394 
395  if (confirmation >= 0 && !multiple_files_error)
396  {
397  gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(percent_progress_bar), 1.0);
398  gtk_progress_bar_set_text(GTK_PROGRESS_BAR(percent_progress_bar),
399  _(" finished"));
400  }
401 
402  we_are_splitting = FALSE;
403 
404  exit_threads();
405 
406  return NULL;
407 }
408 
413 void sigpipe_handler(gint sig)
414 {
415  if (player_is_running() && selected_player == PLAYER_SNACKAMP)
416  {
418  }
419 }
420 
421 gboolean sigint_called = FALSE;
423 void sigint_handler(gint sig)
424 {
425  if (!sigint_called)
426  {
427  sigint_called = TRUE;
428  we_quit_main_program = TRUE;
429  quit(NULL,NULL);
430  }
431 }
432 
434 void put_message_from_library(const char *message, splt_message_type mess_type)
435 {
436  gchar *mess = g_strdup(message);
437  if (mess)
438  {
439  gint i = 0;
440  //replace '\n' with ' '
441  for (i = 0;i < strlen(mess);i++)
442  {
443  if (mess[i] == '\n')
444  {
445  mess[i] = ' ';
446  }
447  }
448  enter_threads();
449 
450  put_status_message_with_type(mess, mess_type);
451 
452 #ifdef __WIN32__
453  while (gtk_events_pending())
454  {
455  gtk_main_iteration();
456  }
457  gdk_flush();
458 #endif
459 
460  exit_threads();
461  g_free(mess);
462  mess = NULL;
463  }
464 }
465 
466 GThread *create_thread(GThreadFunc func, gpointer data,
467  gboolean joinable, GError **error)
468 {
469 /*#ifdef __WIN32__
470  func(data);
471  return NULL;
472  return g_thread_create(func, data, joinable, error);
473 #else*/
474  return g_thread_create(func, data, joinable, error);
475 //#endif
476 }
477 
478 void enter_threads()
479 {
480  gdk_threads_enter();
481 }
482 
483 void exit_threads()
484 {
485  gdk_threads_leave();
486 }
487 
511 gint main(gint argc, gchar *argv[], gchar **envp)
512 {
513  ui = ui_state_new();
514 
515  int OptionChar;
516 
517  //init threads
518  g_thread_init(NULL);
519  gdk_threads_init();
520 
521  gint error = 0;
522 
523  //close nicely
524  signal (SIGINT, sigint_handler);
525 
526 #ifndef __WIN32__
527  signal (SIGPIPE, sigpipe_handler);
528 #endif
529 
530  //create new state
531  the_state = mp3splt_new_state(&error);
532 
533  //used for gettext
534  setlocale (LC_ALL, "");
535  textdomain ("mp3splt-gtk");
536 
537 #ifdef __WIN32__
538  char mp3splt_uninstall_file[2048] = { '\0' };
539  DWORD dwType, dwSize = sizeof(mp3splt_uninstall_file) - 1;
540  SHGetValue(HKEY_LOCAL_MACHINE,
541  TEXT("SOFTWARE\\mp3splt-gtk"),
542  TEXT("UninstallString"),
543  &dwType,
544  mp3splt_uninstall_file,
545  &dwSize);
546 
547  gchar *end = strrchr(mp3splt_uninstall_file, SPLT_DIRCHAR);
548  if (end) { *end = '\0'; }
549 
550  gchar *executable_dir = NULL;
551  gchar *executable = strdup(argv[0]);
552 
553  end = strrchr(executable, SPLT_DIRCHAR);
554  if (end)
555  {
556  *end = '\0';
557  executable_dir = executable;
558  }
559  else
560  {
561  if (mp3splt_uninstall_file[0] != '\0')
562  {
563  executable_dir = mp3splt_uninstall_file;
564  }
565  }
566 
567  bindtextdomain(MP3SPLT_LIB_GETTEXT_DOMAIN, "translations");
568  bindtextdomain("mp3splt-gtk", "translations");
569 
570 #else
571  bindtextdomain("mp3splt-gtk", LOCALEDIR);
572 #endif
573 
574  bind_textdomain_codeset("mp3splt-gtk", "UTF-8");
575 
576  // Allow the gtk to parse all gtk arguments from the command
577  // line first
578  gtk_init(&argc, &argv);
579 
580  // Now pass all remaining arguments to getopt.
581  opterr = 0;
582 
583  while ((OptionChar = getopt (argc, argv, "d:")) != -1)
584  switch (OptionChar)
585  {
586  case 'd':
587  fprintf (stderr, _("Trying to set the output directory to %s.\n"), optarg);
588  outputdirectory_set((gchar *)optarg);
589 #ifdef __WIN32__
590  mkdir(optarg);
591 #else
592  mkdir(optarg, 0777);
593 #endif
594  if(!check_if_dir((guchar *)optarg))
595  {
596  fprintf(stderr,_("Error: The specified output directory is inaccessible!\n"));
597  exit(-1);
598  }
599  break;
600  case '?':
601  if (optopt == 'd')
602  fprintf (stderr, _("Option -%c requires an argument.\n"), optopt);
603  else if (isprint (optopt))
604  fprintf (stderr, _("Unknown option `-%c'.\n"), optopt);
605  else
606  fprintf (stderr,
607  _("Unknown option character `\\x%x'.\n"),
608  optopt);
609  return 1;
610  default:
611  abort ();
612  }
613 
614  // If we have a filename at the command line is checked after the
615  // GUI is up.
616 
617  //We initialise the splitpoints array
618  splitpoints = g_array_new(FALSE, FALSE, sizeof (Split_point));
619 
620  //check if preferences file exists
621  //and if it does not create it
622  check_pref_file();
623 
627 
628  mp3splt_set_int_option(the_state, SPLT_OPT_DEBUG_MODE, SPLT_FALSE);
629  mp3splt_set_int_option(the_state,
631 
632  //add special directory search for plugins on Windows
633 #ifdef __WIN32__
634  if (executable != NULL)
635  {
636  if (executable[0] != '\0')
637  {
638  g_setenv("GST_PLUGIN_PATH", ".\\", TRUE);
639  mp3splt_append_plugins_scan_dir(the_state, executable);
640  _chdir(executable);
641  }
642  }
643 #endif
644 
645  //main program
646  create_all();
647  error = mp3splt_find_plugins(the_state);
648  if (error < 0)
649  {
651  }
652 
653  // Now let's see if we found a filename at the command line.
654  if (optind != argc)
655  {
656  if(!check_if_file((guchar *)argv[optind]))
657  {
658  fprintf (stderr,
659  _("Cannot open input file %s\n"),
660  argv[optind]);
661  return 1;
662  }
663 
664 #ifndef __WIN32__
665  // If we start the player it will find a file with a relative
666  // pathname. But if the player is already running it might
667  // need an absolute path.
668  char *inputfilename=realpath(argv[optind],NULL);
669  handle_import(inputfilename);
670  free(inputfilename);
671 #else
672  handle_import(argv[optind]);
673 #endif
674  }
675 
676  gdk_threads_enter();
677  gtk_main();
678  exit_threads();
679 
680  mp3splt_free_state(the_state, &error);
681 
682  ui_state_free(ui);
683 
684  return 0;
685 }
686