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-2013 Alexandru Munteanu
7  * Contact: m@ioalex.net
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
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 = mp3splt_erase_all_splitpoints(ui->mp3splt_state);
169  err = mp3splt_erase_all_tags(ui->mp3splt_state);
170 
171  gint split_mode = mp3splt_get_int_option(ui->mp3splt_state, SPLT_OPT_SPLIT_MODE, &err);
172  print_status_bar_confirmation_in_idle(err, ui);
173 
174  enter_threads();
175  gchar *format = strdup(gtk_entry_get_text(GTK_ENTRY(ui->gui->output_entry)));
176  exit_threads();
177 
178  err = mp3splt_set_oformat(ui->mp3splt_state, format);
179 
180  if (format)
181  {
182  free(format);
183  format = NULL;
184  }
185 
186  if (mp3splt_get_int_option(ui->mp3splt_state, SPLT_OPT_SPLIT_MODE, &err) == SPLT_OPTION_NORMAL_MODE &&
187  split_file_mode == FILE_MODE_SINGLE)
188  {
189  mp3splt_set_int_option(ui->mp3splt_state, SPLT_OPT_OUTPUT_FILENAMES, SPLT_OUTPUT_CUSTOM);
190  }
191 
192  if (split_mode == SPLT_OPTION_NORMAL_MODE)
193  {
194  enter_threads();
195  put_splitpoints_and_tags_in_mp3splt_state(ui->mp3splt_state, ui);
196 
197  err = mp3splt_remove_tags_of_skippoints(ui->mp3splt_state);
198  print_status_bar_confirmation_in_idle(err, ui);
199  exit_threads();
200  }
201 
202  err = SPLT_OK;
203  gint output_filenames = mp3splt_get_int_option(ui->mp3splt_state, SPLT_OPT_OUTPUT_FILENAMES, &err);
204 
205  //files_to_split will not have a read/write issue because the 'splitting' boolean, which does not
206  //allow us to modify it while we read it here - no mutex needed
207  GPtrArray *files_to_split = ui->files_to_split;
208  gint length = files_to_split->len;
209  gint i = 0;
210  for (i = 0;i < length;i++)
211  {
212  gchar *filename = g_ptr_array_index(files_to_split, i);
213 
214  enter_threads();
215  print_processing_file(filename, ui);
216  exit_threads();
217 
218  mp3splt_set_filename_to_split(ui->mp3splt_state, filename);
219 
220  gint err = mp3splt_split(ui->mp3splt_state);
221  print_status_bar_confirmation_in_idle(err, ui);
222 
223  err = mp3splt_erase_all_tags(ui->mp3splt_state);
224  print_status_bar_confirmation_in_idle(err, ui);
225 
226  err = mp3splt_erase_all_splitpoints(ui->mp3splt_state);
227  print_status_bar_confirmation_in_idle(err, ui);
228 
229  if (get_stop_split_safe(ui))
230  {
231  set_stop_split_safe(FALSE, ui);
232  break;
233  }
234  }
235 
236  mp3splt_set_int_option(ui->mp3splt_state, SPLT_OPT_OUTPUT_FILENAMES, output_filenames);
237 
238  ui_with_err *ui_err = g_malloc0(sizeof(ui_with_err));
239  ui_err->err = err;
240  ui_err->ui = ui;
241 
242  gdk_threads_add_idle_full(G_PRIORITY_HIGH_IDLE, (GSourceFunc)split_collected_files_end, ui_err, NULL);
243 
244  return NULL;
245 }
246 
247 GThread *create_thread(GThreadFunc func, ui_state *ui)
248 {
249  mp3splt_set_int_option(ui->mp3splt_state, SPLT_OPT_DEBUG_MODE, ui->infos->debug_is_active);
250  return g_thread_create(func, ui, TRUE, NULL);
251 }
252 
253 GThread *create_thread_with_fname(GThreadFunc func, ui_with_fname *ui_fname)
254 {
255  mp3splt_set_int_option(ui_fname->ui->mp3splt_state, SPLT_OPT_DEBUG_MODE, ui_fname->ui->infos->debug_is_active);
256  return g_thread_create(func, ui_fname, TRUE, NULL);
257 }
258 
259 void enter_threads()
260 {
261  gdk_threads_enter();
262 }
263 
264 void exit_threads()
265 {
266  gdk_threads_leave();
267 }
268 
269 gboolean exit_application(GtkWidget *widget, GdkEvent *event, gpointer data)
270 {
271  ui_state *ui = (ui_state *)data;
272 
273  ui_save_preferences(NULL, ui);
274 
275  if (get_is_splitting_safe(ui))
276  {
277  lmanager_stop_split(ui);
278  put_status_message(_(" info: stopping the split process before exiting"), ui);
279  }
280 
281  if (player_is_running(ui))
282  {
283  player_quit(ui);
284  }
285 
286  gtk_main_quit();
287 
288  return FALSE;
289 }
290 
291 void exit_application_bis(GtkWidget *widget, gpointer data)
292 {
293  exit_application(widget, NULL, data);
294 }
295 
296 static gboolean sigint_called = FALSE;
297 static void sigint_handler(gint sig)
298 {
299  if (!sigint_called)
300  {
301  sigint_called = TRUE;
302  exit_application(NULL, NULL, ui);
303  }
304 }
305 
306 #ifndef __WIN32__
307 static void sigpipe_handler(gint sig)
308 {
309  if (player_is_running(ui) &&
310  ui->infos->selected_player == PLAYER_SNACKAMP)
311  {
313  }
314 }
315 #endif
316 
317 static void register_application_signals()
318 {
319  signal(SIGINT, sigint_handler);
320 #ifndef __WIN32__
321  signal(SIGPIPE, sigpipe_handler);
322 #endif
323 }
324 
325 static void init_i18n_and_plugin_paths(gchar *argv[], ui_state *ui)
326 {
327  setlocale(LC_ALL, "");
328  textdomain("mp3splt-gtk");
329 
330 #ifdef __WIN32__
331  char mp3splt_uninstall_file[2048] = { '\0' };
332  DWORD dwType, dwSize = sizeof(mp3splt_uninstall_file) - 1;
333  SHGetValue(HKEY_LOCAL_MACHINE,
334  TEXT("SOFTWARE\\mp3splt-gtk"),
335  TEXT("UninstallString"),
336  &dwType,
337  mp3splt_uninstall_file,
338  &dwSize);
339 
340  gchar *end = strrchr(mp3splt_uninstall_file, SPLT_DIRCHAR);
341  if (end) { *end = '\0'; }
342 
343  gchar *executable_dir = NULL;
344  gchar *executable = strdup(argv[0]);
345 
346  end = strrchr(executable, SPLT_DIRCHAR);
347  if (end)
348  {
349  *end = '\0';
350  executable_dir = executable;
351  }
352  else
353  {
354  if (mp3splt_uninstall_file[0] != '\0')
355  {
356  executable_dir = mp3splt_uninstall_file;
357  }
358  }
359 
360  bindtextdomain(LIBMP3SPLT_WITH_SONAME, "translations");
361  bindtextdomain("mp3splt-gtk", "translations");
362 #else
363  bindtextdomain("mp3splt-gtk", LOCALEDIR);
364 #endif
365  bind_textdomain_codeset("mp3splt-gtk", "UTF-8");
366 
367 #ifdef __WIN32__
368  if (executable != NULL)
369  {
370  if (executable[0] != '\0')
371  {
372  g_setenv("GST_PLUGIN_PATH", ".\\", TRUE);
373  mp3splt_append_plugins_scan_dir(ui->mp3splt_state, executable);
374  _chdir(executable);
375  }
376  }
377 #endif
378 }
379 
380 static void parse_command_line_options(gint argc, gchar * argv[], ui_state *ui)
381 {
382  opterr = 0;
383  int option;
384  while ((option = getopt(argc, argv, "d:")) != -1)
385  {
386  switch (option)
387  {
388  case 'd':
389  fprintf(stdout, _("Setting the output directory to %s.\n"), optarg);
390  set_output_directory_and_update_ui((gchar *)optarg, ui);
391 #ifdef __WIN32__
392  mkdir(optarg);
393 #else
394  mkdir(optarg, 0777);
395 #endif
396  if (!directory_exists(optarg))
397  {
398  ui_fail(ui, "Error: The specified output directory is inaccessible!\n");
399  }
400  break;
401  case '?':
402  if (optopt == 'd')
403  ui_fail(ui, _("Option -%c requires an argument.\n"), optopt);
404  else if (isprint(optopt))
405  ui_fail(ui, _("Unknown option `-%c'.\n"), optopt, NULL);
406  else
407  ui_fail(ui, _("Unknown option character `\\x%x'.\n"), optopt);
408  break;
409  default:
410  ui_fail(ui, NULL);
411  }
412  }
413 
414  if (optind == argc)
415  {
416  return;
417  }
418 
419  if (!file_exists(argv[optind]))
420  {
421  ui_fail(ui, _("Cannot open input file %s\n"), argv[optind]);
422  }
423 
424 #ifndef __WIN32__
425  char *input_filename = realpath(argv[optind], NULL);
426  import_file(input_filename, ui);
427  free(input_filename);
428 #else
429  import_file(argv[optind], ui);
430 #endif
431 }
432 
433 #ifdef __WIN32__
434 static void set_language_env_variable_from_preferences()
436 {
437  GKeyFile *key_file = g_key_file_new();
438  gchar *filename = get_preferences_filename();
439 
440  g_key_file_load_from_file(key_file, filename, G_KEY_FILE_KEEP_COMMENTS, NULL);
441 
442  if (filename)
443  {
444  g_free(filename);
445  filename = NULL;
446  }
447 
448  gchar *lang = g_key_file_get_string(key_file, "general", "language", NULL);
449 
450  gchar lang_env[32] = { '\0' };
451  g_snprintf(lang_env, 32, "LANG=%s", lang);
452  putenv(lang_env);
453 
454  g_free(lang);
455  g_key_file_free(key_file);
456 }
457 #endif
458 
482 gint main(gint argc, gchar *argv[], gchar **envp)
483 {
484  ui = ui_state_new();
485 
486  g_thread_init(NULL);
487  gdk_threads_init();
488 
489  register_application_signals();
490  init_i18n_and_plugin_paths(argv, ui);
491 
492  gtk_init(&argc, &argv);
493 
494  lmanager_init_and_find_plugins(ui);
495 
496 #ifdef __WIN32__
497  set_language_env_variable_from_preferences();
498 #endif
499 
500  create_application(ui);
501 
502  import_cue_file_from_the_configuration_directory(ui);
503 
504  parse_command_line_options(argc, argv, ui);
505 
506  enter_threads();
507  gtk_main();
508  exit_threads();
509 
510  gint return_code = ui->return_code;
511  ui_state_free(ui);
512 
513  return return_code;
514 }
515 
gchar * get_preferences_filename()
Get the name of the preferences file.
void put_splitpoints_and_tags_in_mp3splt_state(splt_state *state, ui_state *ui)
puts the splitpoints into the state
gchar * get_input_filename(gui_state *gui)
Get the name of the input file.
Definition: main_window.c:76
gint player_quit(ui_state *ui)
quits the player
gint player_is_running(ui_state *ui)
returns FALSE if the player is not running, else TRUE
gint file_exists(const gchar *fname)
check if specified file exists
Definition: utilities.c:62
void print_processing_file(gchar *filename, ui_state *ui)
Issues the message &quot;Processing file &lt;filename&gt;&quot; into the message bar.
Definition: utilities.c:82
gchar * get_output_directory(ui_state *ui)
Get the name of the output directory.
void put_status_message(const gchar *text, ui_state *ui)
Output a info message to the status message bar.
Definition: main_window.c:264
gint disconnect_snackamp(ui_state *ui)
disconnecting with the player possibly returns an error
void remove_all_split_rows(ui_state *ui)
removes all rows from the split files table
gboolean get_checked_output_radio_box(ui_state *ui)
returns the checked output radio box
void put_options_from_preferences(ui_state *ui)
Update the ui-&gt;mp3splt_state structure.
void import_file(gchar *filename, ui_state *ui)
Handles the import of an input file (audio or splitpoint)
Definition: import.c:86
gint main(gint argc, gchar *argv[], gchar **envp)
The traditional C main function.
Definition: mp3splt-gtk.c:482
gint directory_exists(const gchar *directory)
check if specified directory exists
Definition: utilities.c:44