1 /*
2 * Copyright (c) 2005-2006 Jean-François Wauthy (pollux@xfce.org)
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22
23 #ifdef HAVE_STRING_H
24 #include <string.h>
25 #endif
26
27 #include <stdlib.h>
28
29 #include <gtk/gtk.h>
30
31 #include <libxfce4util/libxfce4util.h>
32 #include <libxfce4ui/libxfce4ui.h>
33
34 #ifdef HAVE_GST
35 #include <gst/gst.h>
36 #endif
37
38 #include "xfburn-main.h"
39 #include "xfburn-global.h"
40 #include "xfburn-device-list.h"
41 #include "xfburn-utils.h"
42 #include "xfburn-settings.h"
43 #include "xfburn-burn-image-dialog.h"
44 #include "xfburn-main-window.h"
45 #include "xfburn-blank-dialog.h"
46 #include "xfburn-udev-manager.h"
47 #include "xfburn-transcoder-basic.h"
48 #include "xfburn-transcoder-gst.h"
49
50
51 /* internal prototypes */
52 static gboolean parse_option (const gchar *option_name, const gchar *value,
53 gpointer data, GError **error);
54 static void xfburn_main_enter_main_window (void);
55 static void print_available_transcoders (void);
56
57 /* globals */
58 static int window_counter = 0;
59
60
61 /* command line parameters */
62 static gchar *image_filename = NULL;
63 static gboolean show_version = FALSE;
64 static gboolean other_action = FALSE;
65 static gboolean show_main = FALSE;
66 static gboolean add_data_composition = FALSE;
67 static gboolean add_audio_composition = FALSE;
68 static gboolean blank = FALSE;
69 static gchar *transcoder_selection = NULL;
70 static gchar *initial_dir = NULL;
71
72 static GOptionEntry optionentries[] = {
73 { "burn-image", 'i', G_OPTION_FLAG_OPTIONAL_ARG /* || G_OPTION_FLAG_FILENAME */, G_OPTION_ARG_CALLBACK, &parse_option,
74 N_("Open the burn image dialog, optionally followed by the image filename"), NULL },
75 { "blank", 'b', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, &parse_option,
76 N_("Open the blank disc dialog"), NULL },
77 { "data-composition", 'd', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, &parse_option,
78 N_("Start a data composition, optionally followed by files/directories to be added to the composition"), NULL },
79 { "audio-composition", 'a', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, &parse_option,
80 N_("Start an audio composition, optionally followed by files/directories to be added to the composition"), NULL },
81 { "transcoder", 't', 0, G_OPTION_ARG_STRING, &transcoder_selection,
82 N_("Select the transcoder, run with --transcoder=list to see the available ones"), NULL },
83 { "directory", 'D', G_OPTION_FLAG_OPTIONAL_ARG , G_OPTION_ARG_CALLBACK, &parse_option,
84 N_("Start the file browser in the specified directory, or the current directory if none is specified (the default is to start in your home directory)"), NULL },
85 { "version", 'V', 0 , G_OPTION_ARG_NONE, &show_version,
86 N_("Display program version and exit"), NULL },
87 { "main", 'm', 0, G_OPTION_ARG_NONE, &show_main,
88 N_("Show main program even when other action is specified on the command line."), NULL },
89 { NULL, ' ', 0, 0, NULL, NULL, NULL }
90 };
91
92
93 /* public functions */
94 void
xfburn_main_enter_window(void)95 xfburn_main_enter_window (void)
96 {
97 /* if a main window is present, then it is in control */
98 if (window_counter != -42)
99 window_counter++;
100 }
101
102 void
xfburn_main_leave_window(void)103 xfburn_main_leave_window (void)
104 {
105 /* if a main window is present, then it is in control */
106 if (window_counter == -42)
107 return;
108
109 window_counter--;
110 if (window_counter <= 0)
111 g_idle_add ((GSourceFunc) gtk_main_quit, NULL );
112 }
113
114 static void
xfburn_main_enter_main_window(void)115 xfburn_main_enter_main_window (void)
116 {
117 /* mark the window_counter as having a main window */
118 window_counter = -42;
119 }
120
121
122 const gchar *
xfburn_main_get_initial_dir()123 xfburn_main_get_initial_dir ()
124 {
125 if (initial_dir)
126 return initial_dir;
127 else
128 return xfce_get_homedir ();
129 }
130
131 gboolean
xfburn_main_has_initial_dir()132 xfburn_main_has_initial_dir ()
133 {
134 if (initial_dir)
135 return TRUE;
136 else
137 return FALSE;
138 }
139
140
141 /* private functions */
142
parse_option(const gchar * option_name,const gchar * value,gpointer data,GError ** error)143 static gboolean parse_option (const gchar *option_name, const gchar *value,
144 gpointer data, GError **error)
145 {
146 if (strcmp (option_name, "-i") == 0 || strcmp (option_name, "--burn-image") == 0) {
147 if (value == NULL)
148 image_filename = "";
149 else
150 image_filename = g_strdup(value);
151 } else if (strcmp (option_name, "-d") == 0 || strcmp (option_name, "--data-composition") == 0) {
152 add_data_composition = TRUE;
153 } else if (strcmp (option_name, "-a") == 0 || strcmp (option_name, "--audio-composition") == 0) {
154 add_audio_composition = TRUE;
155 } else if (strcmp (option_name, "-b") == 0 || strcmp (option_name, "--blank") == 0) {
156 blank = TRUE;
157 } else if (strcmp (option_name, "-D") == 0 || strcmp (option_name, "--directory") == 0) {
158 if (value == NULL)
159 initial_dir = g_get_current_dir ();
160 else
161 initial_dir = g_strdup(value);
162 } else {
163 g_set_error (error, 0, G_OPTION_ERROR_FAILED, "Invalid command line option. Please report, this is a bug.");
164 return FALSE;
165 }
166
167 return TRUE;
168 }
169
170
171 static void
print_available_transcoders(void)172 print_available_transcoders (void)
173 {
174 g_print ("Valid transcoders are:\n");
175 g_print ("\tbasic\tCan only burn uncompressed CD quality .wav files.\n");
176 #ifdef HAVE_GST
177 g_print ("\tgst\tUses gstreamer, and can burn all formats supported by it.\n");
178 #endif
179 }
180
181 /* entry point */
182 int
main(int argc,char ** argv)183 main (int argc, char **argv)
184 {
185 GtkWidget *mainwin;
186 gint n_burners;
187 GError *error = NULL;
188 #ifdef HAVE_GUDEV
189 gchar *error_msg;
190 #endif
191 XfburnTranscoder *transcoder;
192 XfburnDeviceList *devlist;
193
194 #if DEBUG > 0
195 /* I have to disable this until GtkTreeView gets fixed,
196 * and doesn't complain anymore when a DnD doesn't add any
197 * rows
198 g_log_set_always_fatal (G_LOG_LEVEL_CRITICAL);
199 */
200 #endif
201
202 g_set_application_name (_("Xfburn"));
203
204 gdk_threads_init ();
205 gdk_threads_enter ();
206
207 xfce_textdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR, "UTF-8");
208
209 if (!gtk_init_with_args (&argc, &argv, NULL, optionentries, GETTEXT_PACKAGE, &error)) {
210 if (error != NULL) {
211 g_print (_("%s: %s\nTry %s --help to see a full list of available command line options.\n"), PACKAGE, error->message, PACKAGE_NAME);
212 g_error_free (error);
213 gdk_threads_leave ();
214 return EXIT_FAILURE;
215 }
216 }
217
218 if (!burn_initialize ()) {
219 g_critical ("Unable to initialize libburn");
220 xfce_dialog_show_error (NULL, NULL, _("Unable to initialize the burning backend."));
221 gdk_threads_leave ();
222 return EXIT_FAILURE;
223 }
224
225 #ifdef HAVE_GST
226 if (!gst_init_check (&argc, &argv, &error)) {
227 g_critical ("Failed to initialize gstreamer!");
228 /* I'm assuming this pretty much never happens. If it does, we should make this a soft failure and fall back to basic */
229 gdk_threads_leave ();
230 burn_finish ();
231 return EXIT_FAILURE;
232 }
233 #endif
234
235 if (show_version) {
236 #ifdef HAVE_GST
237 const char *nano_str;
238 guint gst_major, gst_minor, gst_micro, gst_nano;
239 #endif
240
241 g_print ("%s version %s for Xfce %s\n", PACKAGE, VERSION, xfce_version_string ());
242 g_print ("\tbuilt with GTK+-%d.%d.%d, ", GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION);
243 g_print ("linked with GTK+-%d.%d.%d.\n", gtk_major_version, gtk_minor_version, gtk_micro_version);
244
245 #ifdef HAVE_GST
246 gst_version (&gst_major, &gst_minor, &gst_micro, &gst_nano);
247
248 if (gst_nano == 1)
249 nano_str = " (CVS)";
250 else if (gst_nano == 2)
251 nano_str = " (Prerelease)";
252 else
253 nano_str = "";
254
255 g_print ("\tGStreamer support (built with %d.%d.%d, linked against %d.%d.%d%s)\n",
256 GST_VERSION_MAJOR, GST_VERSION_MINOR, GST_VERSION_MICRO,
257 gst_major, gst_minor, gst_micro, nano_str);
258
259 #endif
260 exit (EXIT_SUCCESS);
261 }
262
263 if (transcoder_selection && strcmp (transcoder_selection, "list") == 0) {
264 print_available_transcoders();
265 gdk_threads_leave ();
266 burn_finish ();
267 return EXIT_SUCCESS;
268 }
269
270 DBG ("%s version %s for Xfce %s\n", PACKAGE, VERSION, xfce_version_string ());
271
272 xfburn_settings_init ();
273
274 #ifdef HAVE_GUDEV
275 error_msg = xfburn_udev_manager_create_global ();
276 if (error_msg) {
277 xfce_dialog_show_error (NULL, NULL, "%s", error_msg);
278 gdk_threads_leave ();
279 burn_finish ();
280 return EXIT_FAILURE;
281 } else {
282 g_message ("Using UDEV");
283 }
284 #endif
285
286 devlist = xfburn_device_list_new ();
287 g_object_get (devlist, "num-burners", &n_burners, NULL);
288
289 if (n_burners < 1) {
290 GtkMessageDialog *dialog = (GtkMessageDialog *) gtk_message_dialog_new (NULL,
291 GTK_DIALOG_DESTROY_WITH_PARENT,
292 GTK_MESSAGE_WARNING,
293 GTK_BUTTONS_CLOSE,
294 ((const gchar *) _("No burners are currently available")));
295 gtk_message_dialog_format_secondary_text (dialog,
296 _("Possibly the disc(s) are in use, and cannot get accessed.\n\n"
297 "Please unmount and restart the application.\n\n"
298 "If no disc is in the drive, check that you have read and write access to the drive with the current user."));
299 gtk_dialog_run (GTK_DIALOG (dialog));
300 gtk_widget_destroy (GTK_WIDGET (dialog));
301 }
302
303
304 /*----------Transcoder--------------------------------------------------*/
305
306 if (!transcoder_selection) {
307 /* select the best available */
308 #ifdef HAVE_GST
309 transcoder = XFBURN_TRANSCODER (xfburn_transcoder_gst_new ());
310 #else
311 transcoder = XFBURN_TRANSCODER (xfburn_transcoder_basic_new ());
312 #endif
313 #ifdef HAVE_GST
314 } else if (strcmp (transcoder_selection, "gst") == 0) {
315 transcoder = XFBURN_TRANSCODER (xfburn_transcoder_gst_new ());
316 #endif
317 } else if (strcmp (transcoder_selection, "basic") == 0) {
318 transcoder = XFBURN_TRANSCODER (xfburn_transcoder_basic_new ());
319 } else {
320 g_print ("'%s' is an invalid transcoder selection.\n",
321 transcoder_selection);
322 g_print ("\n");
323 print_available_transcoders();
324 gdk_threads_leave ();
325 burn_finish ();
326 return EXIT_FAILURE;
327 }
328
329 if (!xfburn_transcoder_is_initialized (transcoder, &error)) {
330 xfce_dialog_show_warning(NULL, NULL, _("Failed to initialize %s transcoder: %s\n\t(falling back to basic implementation)"), xfburn_transcoder_get_name (transcoder), error->message);
331 g_error_free (error);
332 g_object_unref (transcoder);
333 transcoder = XFBURN_TRANSCODER (xfburn_transcoder_basic_new ());
334 } else {
335 g_message ("Using %s transcoder.", xfburn_transcoder_get_name (transcoder));
336 }
337 xfburn_transcoder_set_global (transcoder);
338
339
340 /*----------evaluate parsed command line action options-------------------------*/
341
342 /* heuristic for file names on the commandline */
343 if (argc == 2 && !add_data_composition && !add_audio_composition) {
344 /* exactly one filename, assume it is an image */
345 image_filename = argv[1];
346 } else if (argc > 2 && !add_data_composition && !add_audio_composition) {
347 /* several file names, for now just open up a data composition */
348 /* TODO: auto-detect music files for audio compositions */
349 add_data_composition = TRUE;
350 }
351
352 if (show_main) {
353 xfburn_main_enter_main_window ();
354 }
355
356 if (image_filename != NULL) {
357 GtkWidget *dialog = xfburn_burn_image_dialog_new ();
358 other_action = TRUE;
359
360 DBG ("image_filename = '%s'\n", image_filename);
361
362 if (*image_filename != '\0') {
363 gchar *image_fullname;
364
365 if (!g_path_is_absolute (image_filename))
366 image_fullname = g_build_filename (g_get_current_dir (), image_filename, NULL);
367 else
368 image_fullname = image_filename;
369
370 if (g_file_test (image_fullname, G_FILE_TEST_EXISTS))
371 xfburn_burn_image_dialog_set_filechooser_name (dialog, image_fullname);
372 else
373 xfce_dialog_show_error (NULL, NULL, _("Image file '%s' does not exist."), image_fullname);
374 }
375
376 gtk_dialog_run (GTK_DIALOG (dialog));
377 gtk_widget_destroy (dialog);
378 } else if (blank) {
379 GtkWidget *dialog = xfburn_blank_dialog_new ();
380
381 other_action = TRUE;
382 gtk_dialog_run (GTK_DIALOG (dialog));
383 gtk_widget_destroy (dialog);
384 }
385
386
387 /*----------main window--------------------------------------------------*/
388
389 if (!other_action || show_main) {
390 xfburn_main_enter_main_window ();
391 mainwin = xfburn_main_window_new ();
392
393 gtk_widget_show (mainwin);
394
395 if (add_data_composition)
396 xfburn_main_window_add_data_composition_with_files (XFBURN_MAIN_WINDOW (mainwin), argc-1, argv+1);
397
398 if (add_audio_composition)
399 xfburn_main_window_add_audio_composition_with_files (XFBURN_MAIN_WINDOW (mainwin), argc-1, argv+1);
400 }
401
402
403 gtk_main ();
404
405
406 /*----------shutdown--------------------------------------------------*/
407
408 g_object_unref (devlist);
409 g_object_unref (transcoder);
410
411 #ifdef HAVE_GUDEV
412 xfburn_udev_manager_shutdown ();
413 #endif
414
415 xfburn_settings_flush ();
416 xfburn_settings_free ();
417
418 burn_finish ();
419
420 gdk_threads_leave ();
421
422 return EXIT_SUCCESS;
423 }
424