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 "mp3splt-gtk.h"
41 
42 ui_state *ui;
43 
44 static gpointer split_collected_files(ui_state *ui);
45 static gboolean collect_files_to_split(ui_state *ui);
46 
47 void split_action(ui_state *ui)
48 {
49  set_is_splitting_safe(TRUE, ui);
50  if (!collect_files_to_split(ui))
51  {
52  set_is_splitting_safe(FALSE, ui);
53  return;
54  }
55  set_is_splitting_safe(FALSE, ui);
56 
57  create_thread((GThreadFunc)split_collected_files, ui);
58 }
59 
60 static gboolean collect_files_to_split(ui_state *ui)
61 {
62  //clean
63  GPtrArray *files_to_split = ui->files_to_split;
64  if (files_to_split && files_to_split->len > 0)
65  {
66  gint length = files_to_split->len;
67  gint i = 0;
68  for (i = 0;i < length;i++)
69  {
70  g_free(g_ptr_array_index(files_to_split, i));
71  }
72  g_ptr_array_free(ui->files_to_split, TRUE);
73  }
74  ui->files_to_split = g_ptr_array_new();
75 
76  //collect
77  if (get_split_file_mode_safe(ui) == FILE_MODE_SINGLE)
78  {
79  g_ptr_array_add(ui->files_to_split, g_strdup(get_input_filename(ui->gui)));
80  }
81  else if (ui->infos->multiple_files_tree_number > 0)
82  {
83  GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(ui->gui->multiple_files_tree));
84  gint row_number = 0;
85  while (row_number < ui->infos->multiple_files_tree_number)
86  {
87  GtkTreePath *path = gtk_tree_path_new_from_indices(row_number ,-1);
88 
89  GtkTreeIter iter;
90  gtk_tree_model_get_iter(model, &iter, path);
91 
92  gchar *filename = NULL;
93  gtk_tree_model_get(model, &iter, MULTIPLE_COL_FILENAME, &filename, -1);
94 
95  g_ptr_array_add(ui->files_to_split, filename);
96 
97  row_number++;
98  }
99  }
100  else
101  {
102  put_status_message(_(" error: no files found in batch mode"), ui);
103  return FALSE;
104  }
105 
106  return TRUE;
107 }
108 
109 static gboolean split_collected_files_end(ui_with_err *ui_err)
110 {
111  gint err = ui_err->err;
112  ui_state *ui = ui_err->ui;
113 
114  gtk_widget_set_sensitive(ui->gui->cancel_button, FALSE);
115 
116  if (err >= 0)
117  {
118  gtk_progress_bar_set_fraction(ui->gui->percent_progress_bar, 1.0);
119  gtk_progress_bar_set_text(ui->gui->percent_progress_bar, _(" finished"));
120  }
121 
122  set_is_splitting_safe(FALSE, ui);
123 
124  set_process_in_progress_and_wait_safe(FALSE, ui_err->ui);
125 
126  g_free(ui_err);
127 
128  return FALSE;
129 }
130 
131 static gint get_stop_split_safe(ui_state *ui)
132 {
133  lock_mutex(&ui->variables_mutex);
134  gint stop_split = ui->status->stop_split;
135  unlock_mutex(&ui->variables_mutex);
136  return stop_split;
137 }
138 
140 static gpointer split_collected_files(ui_state *ui)
141 {
142  set_process_in_progress_and_wait_safe(TRUE, ui);
143 
144  enter_threads();
145 
146  gtk_widget_set_sensitive(ui->gui->cancel_button, TRUE);
147 
149 
150  mp3splt_set_int_option(ui->mp3splt_state, SPLT_OPT_OUTPUT_FILENAMES, SPLT_OUTPUT_DEFAULT);
152  {
153  mp3splt_set_int_option(ui->mp3splt_state, SPLT_OPT_OUTPUT_FILENAMES, SPLT_OUTPUT_FORMAT);
154  }
155 
156  exit_threads();
157 
158  gint split_file_mode = get_split_file_mode_safe(ui);
159 
160  lock_mutex(&ui->variables_mutex);
161  mp3splt_set_path_of_split(ui->mp3splt_state, get_output_directory(ui));
162  unlock_mutex(&ui->variables_mutex);
163 
164  enter_threads();
166  exit_threads();
167 
168  gint err = SPLT_OK;
169  mp3splt_erase_all_splitpoints(ui->mp3splt_state, &err);
170 
171  //we erase previous tags if we don't have the option splt_current_tags
172  if ((mp3splt_get_int_option(ui->mp3splt_state, SPLT_OPT_TAGS, &err) != SPLT_CURRENT_TAGS ||
173  split_file_mode == FILE_MODE_MULTIPLE))
174  {
175  mp3splt_erase_all_tags(ui->mp3splt_state, &err);
176  }
177 
178  gint split_mode = mp3splt_get_int_option(ui->mp3splt_state, SPLT_OPT_SPLIT_MODE, &err);
179  print_status_bar_confirmation_in_idle(err, ui);
180 
181  enter_threads();
182  gchar *format = strdup(gtk_entry_get_text(GTK_ENTRY(ui->gui->output_entry)));
183  exit_threads();
184 
185  mp3splt_set_oformat(ui->mp3splt_state, format, &err);
186 
187  if (format)
188  {
189  free(format);
190  format = NULL;
191  }
192 
193  if (mp3splt_get_int_option(ui->mp3splt_state, SPLT_OPT_SPLIT_MODE, &err) == SPLT_OPTION_NORMAL_MODE &&
194  split_file_mode == FILE_MODE_SINGLE)
195  {
196  mp3splt_set_int_option(ui->mp3splt_state, SPLT_OPT_OUTPUT_FILENAMES, SPLT_OUTPUT_CUSTOM);
197  }
198 
199  if (split_mode == SPLT_OPTION_NORMAL_MODE)
200  {
201  enter_threads();
202  put_splitpoints_in_mp3splt_state(ui->mp3splt_state, ui);
203  exit_threads();
204  }
205 
206  err = SPLT_OK;
207  gint output_filenames = mp3splt_get_int_option(ui->mp3splt_state, SPLT_OPT_OUTPUT_FILENAMES, &err);
208 
209  //files_to_split will not have a read/write issue because the 'splitting' boolean, which does not
210  //allow us to modify it while we read it here - no mutex needed
211  GPtrArray *files_to_split = ui->files_to_split;
212  gint length = files_to_split->len;
213  gint i = 0;
214  for (i = 0;i < length;i++)
215  {
216  gchar *filename = g_ptr_array_index(files_to_split, i);
217 
218  enter_threads();
219  print_processing_file(filename, ui);
220  exit_threads();
221 
222  mp3splt_set_filename_to_split(ui->mp3splt_state, filename);
223 
224  gint err = mp3splt_split(ui->mp3splt_state);
225  print_status_bar_confirmation_in_idle(err, ui);
226 
227  err = SPLT_OK;
228  mp3splt_erase_all_tags(ui->mp3splt_state, &err);
229  print_status_bar_confirmation_in_idle(err, ui);
230 
231  err = SPLT_OK;
232  mp3splt_erase_all_splitpoints(ui->mp3splt_state, &err);
233  print_status_bar_confirmation_in_idle(err, ui);
234 
235  if (get_stop_split_safe(ui))
236  {
237  set_stop_split_safe(FALSE, ui);
238  break;
239  }
240  }
241 
242  mp3splt_set_int_option(ui->mp3splt_state, SPLT_OPT_OUTPUT_FILENAMES, output_filenames);
243 
244  ui_with_err *ui_err = g_malloc0(sizeof(ui_with_err));
245  ui_err->err = err;
246  ui_err->ui = ui;
247 
248  gdk_threads_add_idle_full(G_PRIORITY_HIGH_IDLE, (GSourceFunc)split_collected_files_end, ui_err, NULL);
249 
250  return NULL;
251 }
252 
253 GThread *create_thread(GThreadFunc func, ui_state *ui)
254 {
255  mp3splt_set_int_option(ui->mp3splt_state, SPLT_OPT_DEBUG_MODE, ui->infos->debug_is_active);
256  return g_thread_create(func, ui, TRUE, NULL);
257 }
258 
259 GThread *create_thread_with_fname(GThreadFunc func, ui_with_fname *ui_fname)
260 {
261  mp3splt_set_int_option(ui_fname->ui->mp3splt_state, SPLT_OPT_DEBUG_MODE, ui_fname->ui->infos->debug_is_active);
262  return g_thread_create(func, ui_fname, TRUE, NULL);
263 }
264 
265 void enter_threads()
266 {
267  gdk_threads_enter();
268 }
269 
270 void exit_threads()
271 {
272  gdk_threads_leave();
273 }
274 
275 gboolean exit_application(GtkWidget *widget, GdkEvent *event, gpointer data)
276 {
277  ui_state *ui = (ui_state *)data;
278 
279  ui_save_preferences(NULL, ui);
280 
281  if (get_is_splitting_safe(ui))
282  {
283  lmanager_stop_split(ui);
284  put_status_message(_(" info: stopping the split process before exiting"), ui);
285  }
286 
287  if (player_is_running(ui))
288  {
289  player_quit(ui);
290  }
291 
292  gtk_main_quit();
293 }
294 
295 void exit_application_bis(GtkWidget *widget, gpointer data)
296 {
297  exit_application(widget, NULL, data);
298 }
299 
300 
301 static gboolean sigint_called = FALSE;
302 static void sigint_handler(gint sig)
303 {
304  if (!sigint_called)
305  {
306  sigint_called = TRUE;
307  exit_application(NULL, NULL, ui);
308  }
309 }
310 
311 #ifndef __WIN32__
312 static void sigpipe_handler(gint sig)
313 {
314  if (player_is_running(ui) &&
315  ui->infos->selected_player == PLAYER_SNACKAMP)
316  {
318  }
319 }
320 #endif
321 
322 static void register_application_signals()
323 {
324  signal(SIGINT, sigint_handler);
325 #ifndef __WIN32__
326  signal(SIGPIPE, sigpipe_handler);
327 #endif
328 }
329 
330 static void init_i18n_and_plugin_paths(gchar *argv[], ui_state *ui)
331 {
332  setlocale(LC_ALL, "");
333  textdomain("mp3splt-gtk");
334 
335 #ifdef __WIN32__
336  char mp3splt_uninstall_file[2048] = { '\0' };
337  DWORD dwType, dwSize = sizeof(mp3splt_uninstall_file) - 1;
338  SHGetValue(HKEY_LOCAL_MACHINE,
339  TEXT("SOFTWARE\\mp3splt-gtk"),
340  TEXT("UninstallString"),
341  &dwType,
342  mp3splt_uninstall_file,
343  &dwSize);
344 
345  gchar *end = strrchr(mp3splt_uninstall_file, SPLT_DIRCHAR);
346  if (end) { *end = '\0'; }
347 
348  gchar *executable_dir = NULL;
349  gchar *executable = strdup(argv[0]);
350 
351  end = strrchr(executable, SPLT_DIRCHAR);
352  if (end)
353  {
354  *end = '\0';
355  executable_dir = executable;
356  }
357  else
358  {
359  if (mp3splt_uninstall_file[0] != '\0')
360  {
361  executable_dir = mp3splt_uninstall_file;
362  }
363  }
364 
365  bindtextdomain(MP3SPLT_LIB_GETTEXT_DOMAIN, "translations");
366  bindtextdomain("mp3splt-gtk", "translations");
367 #else
368  bindtextdomain("mp3splt-gtk", LOCALEDIR);
369 #endif
370  bind_textdomain_codeset("mp3splt-gtk", "UTF-8");
371 
372 #ifdef __WIN32__
373  if (executable != NULL)
374  {
375  if (executable[0] != '\0')
376  {
377  g_setenv("GST_PLUGIN_PATH", ".\\", TRUE);
378  mp3splt_append_plugins_scan_dir(ui->mp3splt_state, executable);
379  _chdir(executable);
380  }
381  }
382 #endif
383 }
384 
385 static void parse_command_line_options(gint argc, gchar * argv[], ui_state *ui)
386 {
387  opterr = 0;
388  int option;
389  while ((option = getopt(argc, argv, "d:")) != -1)
390  {
391  switch (option)
392  {
393  case 'd':
394  fprintf(stdout, _("Setting the output directory to %s.\n"), optarg);
395  set_output_directory((gchar *)optarg, ui);
396 #ifdef __WIN32__
397  mkdir(optarg);
398 #else
399  mkdir(optarg, 0777);
400 #endif
401  if (!directory_exists(optarg))
402  {
403  ui_fail(ui, "Error: The specified output directory is inaccessible!\n");
404  }
405  break;
406  case '?':
407  if (optopt == 'd')
408  ui_fail(ui, _("Option -%c requires an argument.\n"), optopt);
409  else if (isprint(optopt))
410  ui_fail(ui, _("Unknown option `-%c'.\n"), optopt, NULL);
411  else
412  ui_fail(ui, _("Unknown option character `\\x%x'.\n"), optopt);
413  break;
414  default:
415  ui_fail(ui, NULL);
416  }
417  }
418 
419  if (optind == argc)
420  {
421  return;
422  }
423 
424  if (!file_exists(argv[optind]))
425  {
426  ui_fail(ui, _("Cannot open input file %s\n"), argv[optind]);
427  }
428 
429 #ifndef __WIN32__
430  char *input_filename = realpath(argv[optind], NULL);
431  import_file(input_filename, ui);
432  free(input_filename);
433 #else
434  import_file(argv[optind], ui);
435 #endif
436 }
437 
438 #ifdef __WIN32__
439 
440 static void set_language_env_variable_from_preferences()
441 {
442  GKeyFile *key_file = g_key_file_new();
443  gchar *filename = get_preferences_filename();
444 
445  g_key_file_load_from_file(key_file, filename, G_KEY_FILE_KEEP_COMMENTS, NULL);
446 
447  if (filename)
448  {
449  g_free(filename);
450  filename = NULL;
451  }
452 
453  gchar *lang = g_key_file_get_string(key_file, "general", "language", NULL);
454 
455  gchar lang_env[32] = { '\0' };
456  g_snprintf(lang_env, 32, "LANG=%s", lang);
457  putenv(lang_env);
458 
459  g_free(lang);
460  g_key_file_free(key_file);
461 }
462 #endif
463 
487 gint main(gint argc, gchar *argv[], gchar **envp)
488 {
489  ui = ui_state_new();
490 
491  g_thread_init(NULL);
492  gdk_threads_init();
493 
494  register_application_signals();
495  init_i18n_and_plugin_paths(argv, ui);
496 
497  gtk_init(&argc, &argv);
498 
499  lmanager_init_and_find_plugins(ui);
500 
501 #ifdef __WIN32__
502  set_language_env_variable_from_preferences();
503 #endif
504 
505  create_application(ui);
506 
507  parse_command_line_options(argc, argv, ui);
508 
509  enter_threads();
510  gtk_main();
511  exit_threads();
512 
513  gint return_code = ui->return_code;
514  ui_state_free(ui);
515 
516  return return_code;
517 }
518