1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /*
3  * Brasero
4  * Copyright (C) Philippe Rouquier 2005-2009 <bonfire-app@wanadoo.fr>
5  *
6  *  Brasero is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  * brasero is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14  * See the GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with brasero.  If not, write to:
18  * 	The Free Software Foundation, Inc.,
19  * 	51 Franklin Street, Fifth Floor
20  * 	Boston, MA  02110-1301, USA.
21  */
22 
23 #ifdef HAVE_CONFIG_H
24 #  include <config.h>
25 #endif
26 
27 #include <glib.h>
28 #include <glib/gstdio.h>
29 #include <glib/gi18n.h>
30 
31 #include <gtk/gtk.h>
32 #include <gdk/gdkx.h>
33 
34 #include "brasero-misc.h"
35 #include "brasero-io.h"
36 
37 #include "brasero-app.h"
38 #include "brasero-setting.h"
39 #include "brasero-blank-dialog.h"
40 #include "brasero-sum-dialog.h"
41 #include "brasero-eject-dialog.h"
42 #include "brasero-project-manager.h"
43 #include "brasero-pref.h"
44 
45 #include "brasero-drive.h"
46 #include "brasero-medium.h"
47 #include "brasero-volume.h"
48 
49 #include "brasero-tags.h"
50 #include "brasero-burn.h"
51 #include "brasero-track-disc.h"
52 #include "brasero-track-image.h"
53 #include "brasero-track-data-cfg.h"
54 #include "brasero-track-stream-cfg.h"
55 #include "brasero-track-image-cfg.h"
56 #include "brasero-session.h"
57 #include "brasero-burn-lib.h"
58 
59 #include "brasero-status-dialog.h"
60 #include "brasero-burn-options.h"
61 #include "brasero-burn-dialog.h"
62 #include "brasero-jacket-edit.h"
63 
64 #include "burn-plugin-manager.h"
65 #include "brasero-drive-settings.h"
66 
67 typedef struct _BraseroAppPrivate BraseroAppPrivate;
68 struct _BraseroAppPrivate
69 {
70 	GApplication *gapp;
71 
72 	BraseroSetting *setting;
73 
74 	GdkWindow *parent;
75 
76 	GtkWidget *mainwin;
77 
78 	GtkWidget *burn_dialog;
79 	GtkWidget *tool_dialog;
80 
81 	/* This is the toplevel window currently displayed */
82 	GtkWidget *toplevel;
83 
84 	GtkWidget *projects;
85 	GtkWidget *contents;
86 	GtkWidget *statusbar1;
87 	GtkWidget *statusbar2;
88 	GtkUIManager *manager;
89 
90 	guint tooltip_ctx;
91 
92 	gchar *saved_contents;
93 
94 	guint is_maximized:1;
95 	guint mainwin_running:1;
96 };
97 
98 #define BRASERO_APP_PRIVATE(o)  (G_TYPE_INSTANCE_GET_PRIVATE ((o), BRASERO_TYPE_APP, BraseroAppPrivate))
99 
100 
101 G_DEFINE_TYPE (BraseroApp, brasero_app, G_TYPE_OBJECT);
102 
103 enum {
104 	PROP_NONE,
105 	PROP_GAPP
106 };
107 
108 /**
109  * Menus and toolbar
110  */
111 
112 static void on_prefs_cb (GtkAction *action, BraseroApp *app);
113 static void on_eject_cb (GtkAction *action, BraseroApp *app);
114 static void on_erase_cb (GtkAction *action, BraseroApp *app);
115 static void on_integrity_check_cb (GtkAction *action, BraseroApp *app);
116 
117 static void on_exit_cb (GtkAction *action, BraseroApp *app);
118 
119 static void on_about_cb (GtkAction *action, BraseroApp *app);
120 static void on_help_cb (GtkAction *action, BraseroApp *app);
121 
122 static GtkActionEntry entries[] = {
123 	{"ProjectMenu", NULL, N_("_Project")},
124 	{"ViewMenu", NULL, N_("_View")},
125 	{"EditMenu", NULL, N_("_Edit")},
126 	{"ToolMenu", NULL, N_("_Tools")},
127 
128 	{"HelpMenu", NULL, N_("_Help")},
129 
130 	{"Plugins", NULL, N_("P_lugins"), NULL,
131 	 N_("Choose plugins for Brasero"), G_CALLBACK (on_prefs_cb)},
132 
133 	{"Eject", "media-eject", N_("E_ject"), NULL,
134 	 N_("Eject a disc"), G_CALLBACK (on_eject_cb)},
135 
136 	{"Blank", "media-optical-blank", N_("_Blank…"), NULL,
137 	 N_("Blank a disc"), G_CALLBACK (on_erase_cb)},
138 
139 	{"Check", NULL, N_("_Check Integrity…"), NULL,
140 	 N_("Check data integrity of disc"), G_CALLBACK (on_integrity_check_cb)},
141 
142 	{"Quit", GTK_STOCK_QUIT, NULL, NULL,
143 	 N_("Quit Brasero"), G_CALLBACK (on_exit_cb)},
144 
145 	{"Contents", GTK_STOCK_HELP, N_("_Contents"), "F1", N_("Display help"),
146 	 G_CALLBACK (on_help_cb)},
147 
148 	{"About", GTK_STOCK_ABOUT, NULL, NULL, N_("About"),
149 	 G_CALLBACK (on_about_cb)},
150 };
151 
152 
153 static const gchar *description = {
154 	"<ui>"
155 	    "<menubar name='menubar' >"
156 	    "<menu action='ProjectMenu'>"
157 		"<placeholder name='ProjectPlaceholder'/>"
158 		"<separator/>"
159 		"<menuitem action='Quit'/>"
160 	    "</menu>"
161 	    "<menu action='EditMenu'>"
162 		"<placeholder name='EditPlaceholder'/>"
163 		"<separator/>"
164 		"<menuitem action='Plugins'/>"
165 	    "</menu>"
166 	    "<menu action='ViewMenu'>"
167 		"<placeholder name='ViewPlaceholder'/>"
168 	    "</menu>"
169 	    "<menu action='ToolMenu'>"
170 		"<placeholder name='DiscPlaceholder'/>"
171 		"<menuitem action='Eject'/>"
172 		"<menuitem action='Blank'/>"
173 		"<menuitem action='Check'/>"
174 	    "</menu>"
175 	    "<menu action='HelpMenu'>"
176 		"<menuitem action='Contents'/>"
177 		"<separator/>"
178 		"<menuitem action='About'/>"
179 	    "</menu>"
180 	    "</menubar>"
181 	"</ui>"
182 };
183 
184 static gchar *
brasero_app_get_path(const gchar * name)185 brasero_app_get_path (const gchar *name)
186 {
187 	gchar *directory;
188 	gchar *retval;
189 
190 	directory = g_build_filename (g_get_user_config_dir (),
191 				      "brasero",
192 				      NULL);
193 	if (!g_file_test (directory, G_FILE_TEST_EXISTS))
194 		g_mkdir_with_parents (directory, S_IRWXU);
195 
196 	retval = g_build_filename (directory, name, NULL);
197 	g_free (directory);
198 	return retval;
199 }
200 
201 static gboolean
brasero_app_load_window_state(BraseroApp * app)202 brasero_app_load_window_state (BraseroApp *app)
203 {
204 	gint width;
205 	gint height;
206 	gint state = 0;
207 	gpointer value;
208 
209 	GdkScreen *screen;
210 	GdkRectangle rect;
211 	gint monitor;
212 
213 	BraseroAppPrivate *priv;
214 
215 	priv = BRASERO_APP_PRIVATE (app);
216 
217 	/* Make sure that on first run the window has a default size of at least
218 	 * 85% of the screen (hardware not GTK+) */
219 	screen = gtk_window_get_screen (GTK_WINDOW (priv->mainwin));
220 	monitor = gdk_screen_get_monitor_at_window (screen, gtk_widget_get_window (GTK_WIDGET (priv->mainwin)));
221 	gdk_screen_get_monitor_geometry (screen, monitor, &rect);
222 
223 	brasero_setting_get_value (brasero_setting_get_default (),
224 	                           BRASERO_SETTING_WIN_WIDTH,
225 	                           &value);
226 	width = GPOINTER_TO_INT (value);
227 
228 	brasero_setting_get_value (brasero_setting_get_default (),
229 	                           BRASERO_SETTING_WIN_HEIGHT,
230 	                           &value);
231 	height = GPOINTER_TO_INT (value);
232 
233 	brasero_setting_get_value (brasero_setting_get_default (),
234 	                           BRASERO_SETTING_WIN_MAXIMIZED,
235 	                           &value);
236 	state = GPOINTER_TO_INT (value);
237 
238 	if (width > 0 && height > 0)
239 		gtk_window_resize (GTK_WINDOW (priv->mainwin),
240 				   width,
241 				   height);
242 	else
243 		gtk_window_resize (GTK_WINDOW (priv->mainwin),
244 		                   rect.width / 100 *85,
245 		                   rect.height / 100 * 85);
246 
247 	if (state)
248 		gtk_window_maximize (GTK_WINDOW (priv->mainwin));
249 
250 	return TRUE;
251 }
252 
253 /**
254  * returns FALSE when nothing prevents the shutdown
255  * returns TRUE when shutdown should be delayed
256  */
257 
258 gboolean
brasero_app_save_contents(BraseroApp * app,gboolean cancellable)259 brasero_app_save_contents (BraseroApp *app,
260 			   gboolean cancellable)
261 {
262 	gboolean cancel;
263 	gchar *project_path;
264 	BraseroAppPrivate *priv;
265 
266 	priv = BRASERO_APP_PRIVATE (app);
267 
268 	if (priv->burn_dialog) {
269 		if (cancellable)
270 			return (brasero_burn_dialog_cancel (BRASERO_BURN_DIALOG (priv->burn_dialog), FALSE) == FALSE);
271 
272 		gtk_widget_destroy (priv->burn_dialog);
273 		return FALSE;
274 	}
275 
276 	if (priv->tool_dialog) {
277 		if (cancellable) {
278 			if (BRASERO_IS_TOOL_DIALOG (priv->tool_dialog))
279 				return (brasero_tool_dialog_cancel (BRASERO_TOOL_DIALOG (priv->tool_dialog)) == FALSE);
280 			else if (BRASERO_IS_EJECT_DIALOG (priv->tool_dialog))
281 				return (brasero_eject_dialog_cancel (BRASERO_EJECT_DIALOG (priv->tool_dialog)) == FALSE);
282 		}
283 
284 		gtk_widget_destroy (priv->tool_dialog);
285 		return FALSE;
286 	}
287 
288 	/* If we are not having a main window there is no point in going further */
289 	if (!priv->mainwin)
290 		return FALSE;
291 
292 	if (priv->saved_contents) {
293 		g_free (priv->saved_contents);
294 		priv->saved_contents = NULL;
295 	}
296 
297 	project_path = brasero_app_get_path (BRASERO_SESSION_TMP_PROJECT_PATH);
298 	cancel = brasero_project_manager_save_session (BRASERO_PROJECT_MANAGER (priv->projects),
299 						       project_path,
300 						       &priv->saved_contents,
301 						       cancellable);
302 	g_free (project_path);
303 
304 	return cancel;
305 }
306 
307 const gchar *
brasero_app_get_saved_contents(BraseroApp * app)308 brasero_app_get_saved_contents (BraseroApp *app)
309 {
310 	BraseroAppPrivate *priv;
311 
312 	priv = BRASERO_APP_PRIVATE (app);
313 	return priv->saved_contents;
314 }
315 
316 /**
317  * These functions are only useful because they set the proper toplevel parent
318  * for the message dialog. The following one also sets some properties in case
319  * there isn't any toplevel parent (like show in taskbar, ...).
320  **/
321 
322 static void
brasero_app_toplevel_destroyed_cb(GtkWidget * object,BraseroApp * app)323 brasero_app_toplevel_destroyed_cb (GtkWidget *object,
324 				   BraseroApp *app)
325 {
326 	BraseroAppPrivate *priv;
327 
328 	priv = BRASERO_APP_PRIVATE (app);
329 	priv->toplevel = NULL;
330 }
331 
332 GtkWidget *
brasero_app_dialog(BraseroApp * app,const gchar * primary_message,GtkButtonsType button_type,GtkMessageType msg_type)333 brasero_app_dialog (BraseroApp *app,
334 		    const gchar *primary_message,
335 		    GtkButtonsType button_type,
336 		    GtkMessageType msg_type)
337 {
338 	gboolean is_on_top = FALSE;
339 	BraseroAppPrivate *priv;
340 	GtkWindow *toplevel;
341 	GtkWidget *dialog;
342 
343 	priv = BRASERO_APP_PRIVATE (app);
344 
345 	if (priv->mainwin) {
346 		toplevel = GTK_WINDOW (priv->mainwin);
347 		gtk_widget_show (priv->mainwin);
348 	}
349 	else if (!priv->toplevel) {
350 		is_on_top = TRUE;
351 		toplevel = NULL;
352 	}
353 	else
354 		toplevel = GTK_WINDOW (priv->toplevel);
355 
356 	dialog = gtk_message_dialog_new (toplevel,
357 					 GTK_DIALOG_DESTROY_WITH_PARENT|
358 					 GTK_DIALOG_MODAL,
359 					 msg_type,
360 					 button_type,
361 					 "%s",
362 					 primary_message);
363 
364 	if (!toplevel && priv->parent) {
365 		gtk_widget_realize (GTK_WIDGET (dialog));
366 		gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
367 		gdk_window_set_transient_for (gtk_widget_get_window (GTK_WIDGET (dialog)), priv->parent);
368 	}
369 
370 	if (is_on_top) {
371 		gtk_window_set_skip_pager_hint (GTK_WINDOW (dialog), FALSE);
372 		gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dialog), FALSE);
373 
374 		priv->toplevel = dialog;
375 		g_signal_connect (dialog,
376 				  "destroy",
377 				  G_CALLBACK (brasero_app_toplevel_destroyed_cb),
378 				  app);
379 	}
380 
381 	return dialog;
382 }
383 
384 void
brasero_app_alert(BraseroApp * app,const gchar * primary_message,const gchar * secondary_message,GtkMessageType type)385 brasero_app_alert (BraseroApp *app,
386 		   const gchar *primary_message,
387 		   const gchar *secondary_message,
388 		   GtkMessageType type)
389 {
390 	GtkWidget *parent = NULL;
391 	gboolean is_on_top= TRUE;
392 	BraseroAppPrivate *priv;
393 	GtkWidget *alert;
394 
395 	priv = BRASERO_APP_PRIVATE (app);
396 
397 	/* Whatever happens, they need a parent or must be in the taskbar */
398 	if (priv->mainwin) {
399 		parent = GTK_WIDGET (priv->mainwin);
400 		is_on_top = FALSE;
401 	}
402 	else if (priv->toplevel) {
403 		parent = priv->toplevel;
404 		is_on_top = FALSE;
405 	}
406 
407 	alert = brasero_utils_create_message_dialog (parent,
408 						     primary_message,
409 						     secondary_message,
410 						     type);
411 	if (!parent && priv->parent) {
412 		is_on_top = FALSE;
413 
414 		gtk_widget_realize (GTK_WIDGET (alert));
415 		gtk_window_set_modal (GTK_WINDOW (alert), TRUE);
416 		gdk_window_set_transient_for (gtk_widget_get_window (GTK_WIDGET (alert)), priv->parent);
417 	}
418 
419 	if (is_on_top) {
420 		gtk_window_set_title (GTK_WINDOW (alert), _("Disc Burner"));
421 		gtk_window_set_skip_pager_hint (GTK_WINDOW (alert), FALSE);
422 		gtk_window_set_skip_taskbar_hint (GTK_WINDOW (alert), FALSE);
423 	}
424 
425 	gtk_dialog_run (GTK_DIALOG (alert));
426 	gtk_widget_destroy (alert);
427 }
428 
429 GtkWidget *
brasero_app_get_statusbar1(BraseroApp * app)430 brasero_app_get_statusbar1 (BraseroApp *app)
431 {
432 	BraseroAppPrivate *priv;
433 
434 	priv = BRASERO_APP_PRIVATE (app);
435 
436 	/* FIXME: change with future changes */
437 	return priv->statusbar1;
438 }
439 
440 GtkWidget *
brasero_app_get_statusbar2(BraseroApp * app)441 brasero_app_get_statusbar2 (BraseroApp *app)
442 {
443 	BraseroAppPrivate *priv;
444 
445 	priv = BRASERO_APP_PRIVATE (app);
446 	return priv->statusbar2;
447 }
448 
449 GtkWidget *
brasero_app_get_project_manager(BraseroApp * app)450 brasero_app_get_project_manager (BraseroApp *app)
451 {
452 	BraseroAppPrivate *priv;
453 
454 	priv = BRASERO_APP_PRIVATE (app);
455 	return priv->projects;
456 }
457 
458 static gboolean
on_destroy_cb(GtkWidget * window,BraseroApp * app)459 on_destroy_cb (GtkWidget *window, BraseroApp *app)
460 {
461 	BraseroAppPrivate *priv;
462 
463 	priv = BRASERO_APP_PRIVATE (app);
464 	if (priv->mainwin)
465 		gtk_main_quit ();
466 
467 	return FALSE;
468 }
469 
470 static gboolean
on_delete_cb(GtkWidget * window,GdkEvent * event,BraseroApp * app)471 on_delete_cb (GtkWidget *window, GdkEvent *event, BraseroApp *app)
472 {
473 	BraseroAppPrivate *priv;
474 
475 	priv = BRASERO_APP_PRIVATE (app);
476 	if (!priv->mainwin)
477 		return FALSE;
478 
479 	if (brasero_app_save_contents (app, TRUE))
480 		return TRUE;
481 
482 	return FALSE;
483 }
484 
485 static void
on_exit_cb(GtkAction * action,BraseroApp * app)486 on_exit_cb (GtkAction *action, BraseroApp *app)
487 {
488 	BraseroAppPrivate *priv;
489 
490 	priv = BRASERO_APP_PRIVATE (app);
491 
492 	if (brasero_app_save_contents (app, TRUE))
493 		return;
494 
495 	if (priv->mainwin)
496 		gtk_widget_destroy (GTK_WIDGET (priv->mainwin));
497 }
498 
499 gboolean
brasero_app_is_running(BraseroApp * app)500 brasero_app_is_running (BraseroApp *app)
501 {
502 	BraseroAppPrivate *priv;
503 
504 	priv = BRASERO_APP_PRIVATE (app);
505 	return priv->mainwin_running;
506 }
507 
508 void
brasero_app_set_parent(BraseroApp * app,guint parent_xid)509 brasero_app_set_parent (BraseroApp *app,
510 			guint parent_xid)
511 {
512 	BraseroAppPrivate *priv;
513 
514 	priv = BRASERO_APP_PRIVATE (app);
515 #ifdef GDK_WINDOWING_X11
516 	if (GDK_IS_X11_DISPLAY (gdk_display_get_default ()))
517 		priv->parent = gdk_x11_window_foreign_new_for_display (gdk_display_get_default (), parent_xid);
518 #endif
519 }
520 
521 gboolean
brasero_app_burn(BraseroApp * app,BraseroBurnSession * session,gboolean multi)522 brasero_app_burn (BraseroApp *app,
523 		  BraseroBurnSession *session,
524 		  gboolean multi)
525 {
526 	gboolean success;
527 	GtkWidget *dialog;
528 	BraseroAppPrivate *priv;
529 
530 	priv = BRASERO_APP_PRIVATE (app);
531 
532 	/* now setup the burn dialog */
533 	dialog = brasero_burn_dialog_new ();
534 	gtk_window_set_icon_name (GTK_WINDOW (dialog), "brasero");
535 
536 	priv->burn_dialog = dialog;
537 
538 	brasero_app_set_toplevel (app, GTK_WINDOW (dialog));
539 	if (!multi)
540 		success = brasero_burn_dialog_run (BRASERO_BURN_DIALOG (dialog),
541 						   BRASERO_BURN_SESSION (session));
542 	else
543 		success = brasero_burn_dialog_run_multi (BRASERO_BURN_DIALOG (dialog),
544 							 BRASERO_BURN_SESSION (session));
545 	priv->burn_dialog = NULL;
546 
547 	/* The destruction of the dialog will bring the main window forward */
548 	gtk_widget_destroy (dialog);
549 	return success;
550 }
551 
552 static BraseroBurnResult
brasero_app_burn_options(BraseroApp * app,BraseroSessionCfg * session)553 brasero_app_burn_options (BraseroApp *app,
554 			  BraseroSessionCfg *session)
555 {
556 	GtkWidget *dialog;
557 	GtkResponseType answer;
558 
559 	dialog = brasero_burn_options_new (session);
560 	brasero_app_set_toplevel (app, GTK_WINDOW (dialog));
561 	gtk_window_set_icon_name (GTK_WINDOW (dialog), "brasero");
562 
563 	answer = gtk_dialog_run (GTK_DIALOG (dialog));
564 
565 	/* The destruction of the dialog will bring the main window forward */
566 	gtk_widget_destroy (dialog);
567 	if (answer == GTK_RESPONSE_OK)
568 		return BRASERO_BURN_OK;
569 
570 	if (answer == GTK_RESPONSE_ACCEPT)
571 		return BRASERO_BURN_RETRY;
572 
573 	return BRASERO_BURN_CANCEL;
574 
575 }
576 
577 static void
brasero_app_session_burn(BraseroApp * app,BraseroSessionCfg * session,gboolean burn)578 brasero_app_session_burn (BraseroApp *app,
579 			  BraseroSessionCfg *session,
580 			  gboolean burn)
581 {
582 	BraseroDriveSettings *settings;
583 
584 	/* Set saved temporary directory for the session.
585 	 * NOTE: BraseroBurnSession can cope with NULL path */
586 	settings = brasero_drive_settings_new ();
587 	brasero_drive_settings_set_session (settings, BRASERO_BURN_SESSION (session));
588 
589 	/* We need to have a drive to start burning immediately */
590 	if (burn && brasero_burn_session_get_burner (BRASERO_BURN_SESSION (session))) {
591 		BraseroStatus *status;
592 		BraseroBurnResult result;
593 
594 		status = brasero_status_new ();
595 		brasero_burn_session_get_status (BRASERO_BURN_SESSION (session), status);
596 
597 		result = brasero_status_get_result (status);
598 		if (result == BRASERO_BURN_NOT_READY || result == BRASERO_BURN_RUNNING) {
599 			GtkWidget *status_dialog;
600 
601 			status_dialog = brasero_status_dialog_new (BRASERO_BURN_SESSION (session), NULL);
602 			gtk_dialog_run (GTK_DIALOG (status_dialog));
603 			gtk_widget_destroy (status_dialog);
604 
605 			brasero_burn_session_get_status (BRASERO_BURN_SESSION (session), status);
606 			result = brasero_status_get_result (status);
607 		}
608 		g_object_unref (status);
609 
610 		if (result == BRASERO_BURN_CANCEL) {
611 			g_object_unref (settings);
612 			return;
613 		}
614 
615 		if (result != BRASERO_BURN_OK) {
616 			GError *error;
617 
618 			error = brasero_status_get_error (status);
619 			brasero_app_alert (app,
620 					   _("Error while burning."),
621 					   error? error->message:"",
622 					   GTK_MESSAGE_ERROR);
623 			if (error)
624 				g_error_free (error);
625 
626 			g_object_unref (settings);
627 			return;
628 		}
629 
630 		result = brasero_app_burn (app,
631 		                           BRASERO_BURN_SESSION (session),
632 		                           FALSE);
633 	}
634 	else {
635 		BraseroBurnResult result;
636 
637 		result = brasero_app_burn_options (app, session);
638 		if (result == BRASERO_BURN_OK || result == BRASERO_BURN_RETRY) {
639 			result = brasero_app_burn (app,
640 			                           BRASERO_BURN_SESSION (session),
641 			                           (result == BRASERO_BURN_RETRY));
642 		}
643 	}
644 
645 	g_object_unref (settings);
646 }
647 
648 void
brasero_app_copy_disc(BraseroApp * app,BraseroDrive * burner,const gchar * device,const gchar * cover,gboolean burn)649 brasero_app_copy_disc (BraseroApp *app,
650 		       BraseroDrive *burner,
651 		       const gchar *device,
652 		       const gchar *cover,
653 		       gboolean burn)
654 {
655 	BraseroTrackDisc *track = NULL;
656 	BraseroSessionCfg *session;
657 	BraseroDrive *drive = NULL;
658 
659 	session = brasero_session_cfg_new ();
660 	track = brasero_track_disc_new ();
661 	brasero_burn_session_add_track (BRASERO_BURN_SESSION (session),
662 					BRASERO_TRACK (track),
663 					NULL);
664 	g_object_unref (track);
665 
666 	/* if a device is specified then get the corresponding medium */
667 	if (device) {
668 		BraseroMediumMonitor *monitor;
669 
670 		monitor = brasero_medium_monitor_get_default ();
671 		drive = brasero_medium_monitor_get_drive (monitor, device);
672 		g_object_unref (monitor);
673 
674 		if (!drive)
675 			return;
676 
677 		brasero_track_disc_set_drive (BRASERO_TRACK_DISC (track), drive);
678 		g_object_unref (drive);
679 	}
680 
681 	/* Set a cover if any. */
682 	if (cover) {
683 		GValue *value;
684 
685 		value = g_new0 (GValue, 1);
686 		g_value_init (value, G_TYPE_STRING);
687 		g_value_set_string (value, cover);
688 		brasero_burn_session_tag_add (BRASERO_BURN_SESSION (session),
689 					      BRASERO_COVER_URI,
690 					      value);
691 	}
692 
693 	brasero_burn_session_set_burner (BRASERO_BURN_SESSION (session), burner);
694 	brasero_app_session_burn (app, session, burn);
695 	g_object_unref (session);
696 }
697 
698 void
brasero_app_image(BraseroApp * app,BraseroDrive * burner,const gchar * uri_arg,gboolean burn)699 brasero_app_image (BraseroApp *app,
700 		   BraseroDrive *burner,
701 		   const gchar *uri_arg,
702 		   gboolean burn)
703 {
704 	BraseroSessionCfg *session;
705 	BraseroTrackImageCfg *track = NULL;
706 
707 	/* setup, show, and run options dialog */
708 	session = brasero_session_cfg_new ();
709 	track = brasero_track_image_cfg_new ();
710 	brasero_burn_session_add_track (BRASERO_BURN_SESSION (session),
711 					BRASERO_TRACK (track),
712 					NULL);
713 	g_object_unref (track);
714 
715 	if (uri_arg) {
716 		GFile *file;
717 		gchar *uri;
718 
719 		file = g_file_new_for_commandline_arg (uri_arg);
720 		uri = g_file_get_uri (file);
721 		g_object_unref (file);
722 
723 		brasero_track_image_cfg_set_source (track, uri);
724 		g_free (uri);
725 	}
726 
727 	brasero_burn_session_set_burner (BRASERO_BURN_SESSION (session), burner);
728 	brasero_app_session_burn (app, session, burn);
729 	g_object_unref (session);
730 }
731 
732 static void
brasero_app_process_session(BraseroApp * app,BraseroSessionCfg * session,gboolean burn)733 brasero_app_process_session (BraseroApp *app,
734 			     BraseroSessionCfg *session,
735 			     gboolean burn)
736 {
737 	if (!burn) {
738 		GtkWidget *manager;
739 		BraseroAppPrivate *priv;
740 
741 		priv = BRASERO_APP_PRIVATE (app);
742 		if (!priv->mainwin)
743 			brasero_app_create_mainwin (app);
744 
745 		manager = brasero_app_get_project_manager (app);
746 		brasero_project_manager_open_session (BRASERO_PROJECT_MANAGER (manager), session);
747 	}
748 	else
749 		brasero_app_session_burn (app, session, TRUE);
750 }
751 
752 void
brasero_app_burn_uri(BraseroApp * app,BraseroDrive * burner,gboolean burn)753 brasero_app_burn_uri (BraseroApp *app,
754 		      BraseroDrive *burner,
755 		      gboolean burn)
756 {
757 	GFileEnumerator *enumerator;
758 	BraseroSessionCfg *session;
759 	BraseroTrackDataCfg *track;
760 	GFileInfo *info = NULL;
761 	GError *error = NULL;
762 	GFile *file;
763 
764 	/* Here we get the contents from the burn:// URI and add them
765 	 * individually to the data project. This is done in case it is
766 	 * empty no to start the "Getting Project Size" dialog and then
767 	 * show the "Project is empty" dialog. Do this synchronously as:
768 	 * - we only want the top nodes which reduces time needed
769 	 * - it's always local
770 	 * - windows haven't been shown yet
771 	 * NOTE: don't use any file specified on the command line. */
772 	file = g_file_new_for_uri ("burn://");
773 	enumerator = g_file_enumerate_children (file,
774 						G_FILE_ATTRIBUTE_STANDARD_NAME,
775 						G_FILE_QUERY_INFO_NONE,
776 						NULL,
777 						&error);
778 	if (!enumerator) {
779 		gchar *string;
780 
781 		if (error) {
782 			string = g_strdup (error->message);
783 			g_error_free (error);
784 		}
785 		else
786 			string = g_strdup (_("An internal error occurred"));
787 
788 		brasero_app_alert (app,
789 				   _("Error while loading the project"),
790 				   string,
791 				   GTK_MESSAGE_ERROR);
792 
793 		g_free (string);
794 		g_object_unref (file);
795 		return;
796 	}
797 
798 	session = brasero_session_cfg_new ();
799 
800 	track = brasero_track_data_cfg_new ();
801 	brasero_burn_session_add_track (BRASERO_BURN_SESSION (session), BRASERO_TRACK (track), NULL);
802 	g_object_unref (track);
803 
804 	while ((info = g_file_enumerator_next_file (enumerator, NULL, &error)) != NULL) {
805 		gchar *uri;
806 
807 		uri = g_strconcat ("burn:///", g_file_info_get_name (info), NULL);
808 		g_object_unref (info);
809 
810 		brasero_track_data_cfg_add (track, uri, NULL);
811 		g_free (uri);
812 	}
813 
814 	g_object_unref (enumerator);
815 	g_object_unref (file);
816 
817 	if (error) {
818 		g_object_unref (session);
819 
820 		/* NOTE: this check errors in g_file_enumerator_next_file () */
821 		brasero_app_alert (app,
822 				   _("Error while loading the project"),
823 				   error->message,
824 				   GTK_MESSAGE_ERROR);
825 		return;
826 	}
827 
828 	if (gtk_tree_model_iter_n_children (GTK_TREE_MODEL (track), NULL) == 0) {
829 	        g_object_unref (session);
830 		brasero_app_alert (app,
831 				   _("Please add files to the project."),
832 				   _("The project is empty"),
833 				   GTK_MESSAGE_ERROR);
834 		return;
835 	}
836 
837 	brasero_burn_session_set_burner (BRASERO_BURN_SESSION (session), burner);
838 	brasero_app_process_session (app, session, burn);
839 	g_object_unref (session);
840 }
841 
842 void
brasero_app_data(BraseroApp * app,BraseroDrive * burner,gchar * const * uris,gboolean burn)843 brasero_app_data (BraseroApp *app,
844 		  BraseroDrive *burner,
845 		  gchar * const *uris,
846 		  gboolean burn)
847 {
848 	BraseroTrackDataCfg *track;
849 	BraseroSessionCfg *session;
850 	BraseroAppPrivate *priv;
851 	int i, num;
852 
853 	priv = BRASERO_APP_PRIVATE (app);
854 
855 	if (!uris) {
856 		GtkWidget *manager;
857 
858 		if (burn) {
859 			brasero_app_alert (app,
860 					   _("Please add files to the project."),
861 					   _("The project is empty"),
862 					   GTK_MESSAGE_ERROR);
863 			return;
864 		}
865 
866 		if (!priv->mainwin)
867 			brasero_app_create_mainwin (app);
868 
869 		manager = brasero_app_get_project_manager (app);
870 		brasero_project_manager_switch (BRASERO_PROJECT_MANAGER (manager),
871 						BRASERO_PROJECT_TYPE_DATA,
872 						TRUE);
873 		return;
874 	}
875 
876 	session = brasero_session_cfg_new ();
877 	track = brasero_track_data_cfg_new ();
878 	brasero_burn_session_add_track (BRASERO_BURN_SESSION (session), BRASERO_TRACK (track), NULL);
879 	g_object_unref (track);
880 
881 	num = g_strv_length ((gchar **) uris);
882 	for (i = 0; i < num; i ++) {
883 		GFile *file;
884 		gchar *uri;
885 
886 		file = g_file_new_for_commandline_arg (uris [i]);
887 		uri = g_file_get_uri (file);
888 		g_object_unref (file);
889 
890 		/* Ignore the return value */
891 		brasero_track_data_cfg_add (track, uri, NULL);
892 		g_free (uri);
893 	}
894 
895 	brasero_burn_session_set_burner (BRASERO_BURN_SESSION (session), burner);
896 	brasero_app_process_session (app, session, burn);
897 	g_object_unref (session);
898 }
899 
900 void
brasero_app_stream(BraseroApp * app,BraseroDrive * burner,gchar * const * uris,gboolean is_video,gboolean burn)901 brasero_app_stream (BraseroApp *app,
902 		    BraseroDrive *burner,
903 		    gchar * const *uris,
904 		    gboolean is_video,
905 		    gboolean burn)
906 {
907 	BraseroSessionCfg *session;
908 	BraseroAppPrivate *priv;
909 	int i, num;
910 
911 	priv = BRASERO_APP_PRIVATE (app);
912 
913 	session = brasero_session_cfg_new ();
914 
915 	if (!uris) {
916 		GtkWidget *manager;
917 
918 		if (burn) {
919 			brasero_app_alert (app,
920 					   _("Please add files to the project."),
921 					   _("The project is empty"),
922 					   GTK_MESSAGE_ERROR);
923 			return;
924 		}
925 
926 		if (!priv->mainwin)
927 			brasero_app_create_mainwin (app);
928 
929 		manager = brasero_app_get_project_manager (app);
930 		brasero_project_manager_switch (BRASERO_PROJECT_MANAGER (manager),
931 						is_video? BRASERO_PROJECT_TYPE_VIDEO:BRASERO_PROJECT_TYPE_AUDIO,
932 						TRUE);
933 		return;
934 	}
935 
936 	num = g_strv_length ((gchar **) uris);
937 	for (i = 0; i < num; i ++) {
938 		BraseroTrackStreamCfg *track;
939 		GFile *file;
940 		gchar *uri;
941 
942 		file = g_file_new_for_commandline_arg (uris [i]);
943 		uri = g_file_get_uri (file);
944 		g_object_unref (file);
945 
946 		track = brasero_track_stream_cfg_new ();
947 		brasero_track_stream_set_source (BRASERO_TRACK_STREAM (track), uri);
948 		g_free (uri);
949 
950 		if (is_video)
951 			brasero_track_stream_set_format (BRASERO_TRACK_STREAM (track),
952 			                                 BRASERO_VIDEO_FORMAT_UNDEFINED);
953 
954 		brasero_burn_session_add_track (BRASERO_BURN_SESSION (session), BRASERO_TRACK (track), NULL);
955 		g_object_unref (track);
956 	}
957 
958 	brasero_burn_session_set_burner (BRASERO_BURN_SESSION (session), burner);
959 	brasero_app_process_session (app, session, burn);
960 	g_object_unref (session);
961 }
962 
963 void
brasero_app_blank(BraseroApp * app,BraseroDrive * burner,gboolean burn)964 brasero_app_blank (BraseroApp *app,
965 		   BraseroDrive *burner,
966 		   gboolean burn)
967 {
968 	BraseroBlankDialog *dialog;
969 	BraseroAppPrivate *priv;
970 
971 	priv = BRASERO_APP_PRIVATE (app);
972 	dialog = brasero_blank_dialog_new ();
973 	gtk_window_set_icon_name (GTK_WINDOW (dialog), "brasero");
974 
975 	if (burner) {
976 		BraseroMedium *medium;
977 
978 		medium = brasero_drive_get_medium (burner);
979 		brasero_tool_dialog_set_medium (BRASERO_TOOL_DIALOG (dialog), medium);
980 	}
981 
982 	priv->tool_dialog = GTK_WIDGET (dialog);
983 	if (!priv->mainwin) {
984 		gtk_widget_realize (GTK_WIDGET (dialog));
985 
986 		if (priv->parent) {
987 			gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
988 			gdk_window_set_transient_for (gtk_widget_get_window (GTK_WIDGET (dialog)), priv->parent);
989 		}
990 	}
991 	else {
992 		GtkWidget *toplevel;
993 
994 		/* FIXME! This is a bad idea and needs fixing */
995 		toplevel = gtk_widget_get_toplevel (GTK_WIDGET (priv->mainwin));
996 
997 		gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (toplevel));
998 		gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
999 		gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER_ON_PARENT);
1000 	}
1001 
1002 	gtk_dialog_run (GTK_DIALOG (dialog));
1003 	gtk_widget_destroy (GTK_WIDGET (dialog));
1004 	priv->tool_dialog = NULL;
1005 }
1006 
1007 static void
on_erase_cb(GtkAction * action,BraseroApp * app)1008 on_erase_cb (GtkAction *action, BraseroApp *app)
1009 {
1010 	brasero_app_blank (app, NULL, FALSE);
1011 }
1012 
1013 static void
on_eject_cb(GtkAction * action,BraseroApp * app)1014 on_eject_cb (GtkAction *action, BraseroApp *app)
1015 {
1016 	GtkWidget *dialog;
1017 	GtkWidget *toplevel;
1018 	BraseroAppPrivate *priv;
1019 
1020 	priv = BRASERO_APP_PRIVATE (app);
1021 
1022 	dialog = brasero_eject_dialog_new ();
1023 	gtk_window_set_icon_name (GTK_WINDOW (dialog), "brasero");
1024 
1025 	/* FIXME! This is a bad idea and needs fixing */
1026 	toplevel = gtk_widget_get_toplevel (GTK_WIDGET (priv->mainwin));
1027 
1028 	gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (toplevel));
1029 	gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
1030 	gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER_ON_PARENT);
1031 
1032 	priv->tool_dialog = dialog;
1033 	gtk_dialog_run (GTK_DIALOG (dialog));
1034 	priv->tool_dialog = NULL;
1035 
1036 	gtk_widget_destroy (dialog);
1037 }
1038 
1039 void
brasero_app_check(BraseroApp * app,BraseroDrive * burner,gboolean burn)1040 brasero_app_check (BraseroApp *app,
1041 		   BraseroDrive *burner,
1042 		   gboolean burn)
1043 {
1044 	BraseroSumDialog *dialog;
1045 	BraseroAppPrivate *priv;
1046 
1047 	priv = BRASERO_APP_PRIVATE (app);
1048 
1049 	dialog = brasero_sum_dialog_new ();
1050 	gtk_window_set_icon_name (GTK_WINDOW (dialog), "brasero");
1051 
1052 	priv->tool_dialog = GTK_WIDGET (dialog);
1053 
1054 	if (burner) {
1055 		BraseroMedium *medium;
1056 
1057 		medium = brasero_drive_get_medium (burner);
1058 		brasero_tool_dialog_set_medium (BRASERO_TOOL_DIALOG (dialog), medium);
1059 	}
1060 
1061 	if (!priv->mainwin) {
1062 		gtk_widget_realize (GTK_WIDGET (dialog));
1063 
1064 		if (priv->parent) {
1065 			gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
1066 			gdk_window_set_transient_for (gtk_widget_get_window (GTK_WIDGET (dialog)), priv->parent);
1067 		}
1068 	}
1069 	else {
1070 		GtkWidget *toplevel;
1071 
1072 		/* FIXME! This is a bad idea and needs fixing */
1073 		toplevel = gtk_widget_get_toplevel (GTK_WIDGET (priv->mainwin));
1074 
1075 		gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (toplevel));
1076 		gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
1077 		gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER_ON_PARENT);
1078 	}
1079 
1080 	gtk_dialog_run (GTK_DIALOG (dialog));
1081 	gtk_widget_destroy (GTK_WIDGET (dialog));
1082 	priv->tool_dialog = NULL;
1083 }
1084 
1085 static void
on_integrity_check_cb(GtkAction * action,BraseroApp * app)1086 on_integrity_check_cb (GtkAction *action, BraseroApp *app)
1087 {
1088 	brasero_app_check (app, NULL, FALSE);
1089 }
1090 
1091 static void
brasero_app_current_toplevel_destroyed(GtkWidget * widget,BraseroApp * app)1092 brasero_app_current_toplevel_destroyed (GtkWidget *widget,
1093 					BraseroApp *app)
1094 {
1095 	BraseroAppPrivate *priv;
1096 
1097 	priv = BRASERO_APP_PRIVATE (app);
1098 	if (priv->mainwin_running)
1099 		gtk_widget_show (GTK_WIDGET (priv->mainwin));
1100 }
1101 
1102 void
brasero_app_set_toplevel(BraseroApp * app,GtkWindow * window)1103 brasero_app_set_toplevel (BraseroApp *app, GtkWindow *window)
1104 {
1105 	BraseroAppPrivate *priv;
1106 
1107 	priv = BRASERO_APP_PRIVATE (app);
1108 
1109 	if (!priv->mainwin_running) {
1110 		if (priv->parent) {
1111 			gtk_widget_realize (GTK_WIDGET (window));
1112 			gdk_window_set_transient_for (gtk_widget_get_window (GTK_WIDGET (window)), priv->parent);
1113 		}
1114 		else {
1115 			gtk_window_set_skip_taskbar_hint (GTK_WINDOW (window), FALSE);
1116 			gtk_window_set_skip_pager_hint (GTK_WINDOW (window), FALSE);
1117 			gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER);
1118 		}
1119 	}
1120 	else {
1121 		/* hide main dialog if it is shown */
1122 		gtk_widget_hide (GTK_WIDGET (priv->mainwin));
1123 
1124 		gtk_window_set_skip_taskbar_hint (GTK_WINDOW (window), FALSE);
1125 		gtk_window_set_skip_pager_hint (GTK_WINDOW (window), FALSE);
1126 		gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER);
1127 	}
1128 
1129 	gtk_widget_show (GTK_WIDGET (window));
1130 	g_signal_connect (window,
1131 			  "destroy",
1132 			  G_CALLBACK (brasero_app_current_toplevel_destroyed),
1133 			  app);
1134 }
1135 
1136 static void
on_prefs_cb(GtkAction * action,BraseroApp * app)1137 on_prefs_cb (GtkAction *action, BraseroApp *app)
1138 {
1139 	GtkWidget *dialog;
1140 	GtkWidget *toplevel;
1141 	BraseroAppPrivate *priv;
1142 
1143 	priv = BRASERO_APP_PRIVATE (app);
1144 
1145 	dialog = brasero_pref_new ();
1146 
1147 	/* FIXME! This is a bad idea and needs fixing */
1148 	toplevel = gtk_widget_get_toplevel (GTK_WIDGET (priv->mainwin));
1149 
1150 	gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (toplevel));
1151 	gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
1152 	gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER_ON_PARENT);
1153 
1154 	gtk_widget_show_all (dialog);
1155 	gtk_dialog_run (GTK_DIALOG (dialog));
1156 	gtk_widget_destroy (dialog);
1157 }
1158 
1159 static void
on_about_cb(GtkAction * action,BraseroApp * app)1160 on_about_cb (GtkAction *action, BraseroApp *app)
1161 {
1162 	const gchar *authors[] = {
1163 		"Philippe Rouquier <bonfire-app@wanadoo.fr>",
1164 		"Luis Medinas <lmedinas@gmail.com>",
1165 		NULL
1166 	};
1167 
1168 	const gchar *documenters[] = {
1169 		"Phil Bull <philbull@gmail.com>",
1170 		"Milo Casagrande <milo_casagrande@yahoo.it>",
1171 		"Andrew Stabeno <stabeno@gmail.com>",
1172 		NULL
1173 	};
1174 
1175 	const gchar *license_part[] = {
1176 		N_("Brasero is free software; you can redistribute "
1177 		   "it and/or modify it under the terms of the GNU "
1178 		   "General Public License as published by the Free "
1179 		   "Software Foundation; either version 2 of the "
1180 		   "License, or (at your option) any later version."),
1181                 N_("Brasero is distributed in the hope that it will "
1182 		   "be useful, but WITHOUT ANY WARRANTY; without even "
1183 		   "the implied warranty of MERCHANTABILITY or FITNESS "
1184 		   "FOR A PARTICULAR PURPOSE.  See the GNU General "
1185 		   "Public License for more details."),
1186                 N_("You should have received a copy of the GNU General "
1187 		   "Public License along with Brasero; if not, write "
1188 		   "to the Free Software Foundation, Inc., "
1189                    "51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA"),
1190 		NULL
1191         };
1192 
1193 	gchar  *license, *comments;
1194 	BraseroAppPrivate *priv;
1195 
1196 	priv = BRASERO_APP_PRIVATE (app);
1197 
1198 	comments = g_strdup (_("A simple to use CD/DVD burning application for GNOME"));
1199 
1200 	license = g_strjoin ("\n\n",
1201                              _(license_part[0]),
1202                              _(license_part[1]),
1203                              _(license_part[2]),
1204 			     NULL);
1205 
1206 	/* This can only be shown from the main window so no need for toplevel */
1207 	gtk_show_about_dialog (GTK_WINDOW (GTK_WIDGET (priv->mainwin)),
1208 			       "program-name", "Brasero",
1209 			       "comments", comments,
1210 			       "version", VERSION,
1211 			       "copyright", "Copyright © 2005-2010 Philippe Rouquier",
1212 			       "authors", authors,
1213 			       "documenters", documenters,
1214 			       "website", "http://www.gnome.org/projects/brasero",
1215 			       "website-label", _("Brasero Homepage"),
1216 			       "license", license,
1217 			       "wrap-license", TRUE,
1218 			       "logo-icon-name", "brasero",
1219 			       /* Translators: This is a special message that shouldn't be translated
1220                                  * literally. It is used in the about box to give credits to
1221                                  * the translators.
1222                                  * Thus, you should translate it to your name and email address.
1223                                  * You should also include other translators who have contributed to
1224                                  * this translation; in that case, please write each of them on a separate
1225                                  * line seperated by newlines (\n).
1226                                  */
1227                                "translator-credits", _("translator-credits"),
1228 			       NULL);
1229 
1230 	g_free (comments);
1231 	g_free (license);
1232 }
1233 
1234 static void
on_help_cb(GtkAction * action,BraseroApp * app)1235 on_help_cb (GtkAction *action, BraseroApp *app)
1236 {
1237 	GError *error = NULL;
1238 	BraseroAppPrivate *priv;
1239 
1240 	priv = BRASERO_APP_PRIVATE (app);
1241 
1242 	gtk_show_uri (NULL, "help:brasero", gtk_get_current_event_time (), &error);
1243    	if (error) {
1244 		GtkWidget *d;
1245 
1246 		d = gtk_message_dialog_new (GTK_WINDOW (priv->mainwin),
1247 					    GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
1248 					    GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
1249 					    "%s", error->message);
1250 		gtk_dialog_run (GTK_DIALOG(d));
1251 		gtk_widget_destroy (d);
1252 		g_error_free (error);
1253 		error = NULL;
1254 	}
1255 }
1256 
1257 static gboolean
on_window_state_changed_cb(GtkWidget * widget,GdkEventWindowState * event,BraseroApp * app)1258 on_window_state_changed_cb (GtkWidget *widget,
1259 			    GdkEventWindowState *event,
1260 			    BraseroApp *app)
1261 {
1262 	BraseroAppPrivate *priv;
1263 
1264 	priv = BRASERO_APP_PRIVATE (app);
1265 
1266 	if (event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) {
1267 		priv->is_maximized = 1;
1268 		brasero_setting_set_value (brasero_setting_get_default (),
1269 		                           BRASERO_SETTING_WIN_MAXIMIZED,
1270 		                           GINT_TO_POINTER (1));
1271 	}
1272 	else {
1273 		priv->is_maximized = 0;
1274 		brasero_setting_set_value (brasero_setting_get_default (),
1275 		                           BRASERO_SETTING_WIN_MAXIMIZED,
1276 		                           GINT_TO_POINTER (0));
1277 	}
1278 
1279 	return FALSE;
1280 }
1281 
1282 static gboolean
on_configure_event_cb(GtkWidget * widget,GdkEventConfigure * event,BraseroApp * app)1283 on_configure_event_cb (GtkWidget *widget,
1284 		       GdkEventConfigure *event,
1285 		       BraseroApp *app)
1286 {
1287 	BraseroAppPrivate *priv;
1288 
1289 	priv = BRASERO_APP_PRIVATE (app);
1290 
1291 	if (!priv->is_maximized) {
1292 		brasero_setting_set_value (brasero_setting_get_default (),
1293 		                           BRASERO_SETTING_WIN_WIDTH,
1294 		                           GINT_TO_POINTER (event->width));
1295 		brasero_setting_set_value (brasero_setting_get_default (),
1296 		                           BRASERO_SETTING_WIN_HEIGHT,
1297 		                           GINT_TO_POINTER (event->height));
1298 	}
1299 
1300 	return FALSE;
1301 }
1302 
1303 gboolean
brasero_app_open_project(BraseroApp * app,BraseroDrive * burner,const gchar * uri,gboolean is_playlist,gboolean warn_user,gboolean burn)1304 brasero_app_open_project (BraseroApp *app,
1305 			  BraseroDrive *burner,
1306                           const gchar *uri,
1307                           gboolean is_playlist,
1308                           gboolean warn_user,
1309                           gboolean burn)
1310 {
1311 	BraseroSessionCfg *session;
1312 
1313 	session = brasero_session_cfg_new ();
1314 
1315 #ifdef BUILD_PLAYLIST
1316 
1317 	if (is_playlist) {
1318 		if (!brasero_project_open_audio_playlist_project (uri,
1319 								  BRASERO_BURN_SESSION (session),
1320 								  warn_user))
1321 			return FALSE;
1322 	}
1323 	else
1324 
1325 #endif
1326 
1327 	if (!brasero_project_open_project_xml (uri,
1328 					       BRASERO_BURN_SESSION (session),
1329 					       warn_user))
1330 		return FALSE;
1331 
1332 	brasero_app_process_session (app, session, burn);
1333 	g_object_unref (session);
1334 
1335 	return TRUE;
1336 }
1337 
1338 static gboolean
brasero_app_open_by_mime(BraseroApp * app,const gchar * uri,const gchar * mime,gboolean warn_user)1339 brasero_app_open_by_mime (BraseroApp *app,
1340                           const gchar *uri,
1341                           const gchar *mime,
1342                           gboolean warn_user)
1343 {
1344 	if (!mime) {
1345 		/* that can happen when the URI could not be identified */
1346 		return FALSE;
1347 	}
1348 
1349 	/* When our files/description of x-brasero mime type is not properly
1350 	 * installed, it's returned as application/xml, so check that too. */
1351 	if (!strcmp (mime, "application/x-brasero")
1352 	||  !strcmp (mime, "application/xml"))
1353 		return brasero_app_open_project (app,
1354 						 NULL,
1355 						 uri,
1356 						 FALSE,
1357 						 warn_user,
1358 						 FALSE);
1359 
1360 #ifdef BUILD_PLAYLIST
1361 
1362 	else if (!strcmp (mime, "audio/x-scpls")
1363 	     ||  !strcmp (mime, "audio/x-ms-asx")
1364 	     ||  !strcmp (mime, "audio/x-mp3-playlist")
1365 	     ||  !strcmp (mime, "audio/x-mpegurl"))
1366 		return brasero_app_open_project (app,
1367 						 NULL,
1368 						 uri,
1369 						 TRUE,
1370 						 warn_user,
1371 						 FALSE);
1372 
1373 #endif
1374 
1375 	else if (!strcmp (mime, "application/x-cd-image")
1376 	     ||  !strcmp (mime, "application/x-cdrdao-toc")
1377 	     ||  !strcmp (mime, "application/x-toc")
1378 	     ||  !strcmp (mime, "application/x-cue")) {
1379 		brasero_app_image (app, NULL, uri, FALSE);
1380 		return TRUE;
1381 	}
1382 
1383 	return FALSE;
1384 }
1385 
1386 static gboolean
brasero_app_open_uri_file(BraseroApp * app,GFile * file,GFileInfo * info,gboolean warn_user)1387 brasero_app_open_uri_file (BraseroApp *app,
1388                            GFile *file,
1389                            GFileInfo *info,
1390                            gboolean warn_user)
1391 {
1392 	BraseroProjectType type;
1393 	gchar *uri = NULL;
1394 
1395 	/* if that's a symlink, redo it on its target to get the real mime type
1396 	 * that usually also depends on the extension of the target:
1397 	 * ex: an iso file with the extension .iso will be seen as octet-stream
1398 	 * if the symlink hasn't got any extention at all */
1399 	while (g_file_info_get_is_symlink (info)) {
1400 		const gchar *target;
1401 		GFileInfo *tmp_info;
1402 		GFile *tmp_file;
1403 		GError *error = NULL;
1404 
1405 		target = g_file_info_get_symlink_target (info);
1406 		if (!g_path_is_absolute (target)) {
1407 			gchar *parent;
1408 			gchar *tmp;
1409 
1410 			tmp = g_file_get_path (file);
1411 			parent = g_path_get_dirname (tmp);
1412 			g_free (tmp);
1413 
1414 			target = g_build_filename (parent, target, NULL);
1415 			g_free (parent);
1416 		}
1417 
1418 		tmp_file = g_file_new_for_commandline_arg (target);
1419 		tmp_info = g_file_query_info (tmp_file,
1420 					      G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE ","
1421 					      G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK ","
1422 					      G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET,
1423 					      G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
1424 					      NULL,
1425 					      &error);
1426 		if (!tmp_info) {
1427 			g_object_unref (tmp_file);
1428 			break;
1429 		}
1430 
1431 		g_object_unref (info);
1432 		g_object_unref (file);
1433 
1434 		info = tmp_info;
1435 		file = tmp_file;
1436 	}
1437 
1438 	uri = g_file_get_uri (file);
1439 	if (g_file_query_exists (file, NULL)
1440 	&&  g_file_info_get_content_type (info)) {
1441 		const gchar *mime;
1442 
1443 		mime = g_file_info_get_content_type (info);
1444 	  	type = brasero_app_open_by_mime (app, uri, mime, warn_user);
1445         }
1446 	else if (warn_user) {
1447 		gchar *string;
1448 
1449 		string = g_strdup_printf (_("The project \"%s\" does not exist"), uri);
1450 		brasero_app_alert (app,
1451 				   _("Error while loading the project"),
1452 				   string,
1453 				   GTK_MESSAGE_ERROR);
1454 		g_free (string);
1455 
1456 		type = BRASERO_PROJECT_TYPE_INVALID;
1457 	}
1458 	else
1459 		type = BRASERO_PROJECT_TYPE_INVALID;
1460 
1461 	g_free (uri);
1462 	return (type != BRASERO_PROJECT_TYPE_INVALID);
1463 }
1464 
1465 gboolean
brasero_app_open_uri(BraseroApp * app,const gchar * uri_arg,gboolean warn_user)1466 brasero_app_open_uri (BraseroApp *app,
1467                       const gchar *uri_arg,
1468                       gboolean warn_user)
1469 {
1470 	GFile *file;
1471 	GFileInfo *info;
1472 	gboolean retval;
1473 
1474 	/* FIXME: make that asynchronous */
1475 	/* NOTE: don't follow symlink because we want to identify them */
1476 	file = g_file_new_for_commandline_arg (uri_arg);
1477 	if (!file)
1478 		return FALSE;
1479 
1480 	info = g_file_query_info (file,
1481 				  G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE ","
1482 				  G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK ","
1483 				  G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET,
1484 				  G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
1485 				  NULL,
1486 				  NULL);
1487 
1488 	if (!info) {
1489 		g_object_unref (file);
1490 		return FALSE;
1491 	}
1492 
1493 	retval = brasero_app_open_uri_file (app, file, info, warn_user);
1494 
1495 	g_object_unref (file);
1496 	g_object_unref (info);
1497 
1498 	return retval;
1499 }
1500 
1501 gboolean
brasero_app_open_uri_drive_detection(BraseroApp * app,BraseroDrive * burner,const gchar * uri_arg,const gchar * cover_project,gboolean burn_immediately)1502 brasero_app_open_uri_drive_detection (BraseroApp *app,
1503                                       BraseroDrive *burner,
1504                                       const gchar *uri_arg,
1505                                       const gchar *cover_project,
1506                                       gboolean burn_immediately)
1507 {
1508 	gchar *uri;
1509 	GFile *file;
1510 	GFileInfo *info;
1511 	gboolean retval = FALSE;
1512 
1513 	file = g_file_new_for_commandline_arg (uri_arg);
1514 	if (!file)
1515 		return FALSE;
1516 
1517 	/* Note: if the path is the path of a mounted volume the uri returned
1518 	 * will be entirely different like if /path/to/somewhere is where
1519 	 * an audio CD is mounted will return cdda://sr0/ */
1520 	uri = g_file_get_uri (file);
1521 	info = g_file_query_info (file,
1522 	                          G_FILE_ATTRIBUTE_STANDARD_TYPE ","
1523 	                          G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE ","
1524 				  G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK ","
1525 				  G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET,
1526 				  G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
1527 				  NULL,
1528 				  NULL);
1529 	if (!info) {
1530 		g_object_unref (file);
1531 		g_free (uri);
1532 		return FALSE;
1533 	}
1534 
1535 	if (g_file_info_get_file_type (info) == G_FILE_TYPE_SPECIAL) {
1536 		/* It could be a block device, try */
1537 		if (!g_strcmp0 (g_file_info_get_content_type (info), "inode/blockdevice")) {
1538 			gchar *device;
1539 			BraseroMedia media;
1540 			BraseroDrive *drive;
1541 			BraseroMedium *medium;
1542 			BraseroMediumMonitor *monitor;
1543 
1544 			g_object_unref (info);
1545 			g_free (uri);
1546 
1547 			monitor = brasero_medium_monitor_get_default ();
1548 			while (brasero_medium_monitor_is_probing (monitor))
1549 				sleep (1);
1550 
1551 			device = g_file_get_path (file);
1552 			drive = brasero_medium_monitor_get_drive (monitor, device);
1553 			g_object_unref (monitor);
1554 
1555 			if (!drive) {
1556 				/* This is not a known optical drive to us. */
1557 				g_object_unref (file);
1558 				return FALSE;
1559 			}
1560 
1561 			medium = brasero_drive_get_medium (drive);
1562 			if (!medium) {
1563 				g_object_unref (file);
1564 				g_object_unref (drive);
1565 				return FALSE;
1566 			}
1567 
1568 			media = brasero_medium_get_status (medium);
1569 			if (BRASERO_MEDIUM_IS (media, BRASERO_MEDIUM_BLANK)) {
1570 				/* This medium is blank so it rules out blanking
1571 				 * copying, checksuming. Open a data project. */
1572 				g_object_unref (file);
1573 				g_object_unref (drive);
1574 				return FALSE;
1575 			}
1576 			g_object_unref (drive);
1577 
1578 			/* It seems that we are expected to copy the disc */
1579 			device = g_strdup (g_file_get_path (file));
1580 			g_object_unref (file);
1581 			brasero_app_copy_disc (app,
1582 					       burner,
1583 					       device,
1584 					       cover_project,
1585 					       burn_immediately != 0);
1586 			g_free (device);
1587 			return TRUE;
1588 		}
1589 
1590 		/* The rest are unsupported */
1591 	}
1592 	else if (g_str_has_prefix (uri, "cdda:")) {
1593 		GFile *child;
1594 		gchar *device;
1595 		BraseroMediumMonitor *monitor;
1596 
1597 		/* Make sure we are talking of the root */
1598 		child = g_file_get_parent (file);
1599 		if (child) {
1600 			g_object_unref (child);
1601 			g_object_unref (info);
1602 			g_object_unref (file);
1603 			g_free (uri);
1604 			return FALSE;
1605 		}
1606 
1607 		/* We need to wait for the monitor to be ready */
1608 		monitor = brasero_medium_monitor_get_default ();
1609 		while (brasero_medium_monitor_is_probing (monitor))
1610 			sleep (1);
1611 		g_object_unref (monitor);
1612 
1613 		if (g_str_has_suffix (uri, "/"))
1614 			device = g_strdup_printf ("/dev/%.*s",
1615 				                  (int) (strrchr (uri, '/') - uri - 7),
1616 				                  uri + 7);
1617 		else
1618 			device = g_strdup_printf ("/dev/%s", uri + 7);
1619 		brasero_app_copy_disc (app,
1620 				       burner,
1621 				       device,
1622 				       cover_project,
1623 				       burn_immediately != 0);
1624 		g_free (device);
1625 
1626 		retval = TRUE;
1627 	}
1628 	else if (g_str_has_prefix (uri, "file:/")
1629 	     &&  g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) {
1630 		BraseroMediumMonitor *monitor;
1631 		gchar *directory_path;
1632 		GSList *drives;
1633 		GSList *iter;
1634 
1635 		/* Try to detect a mounted optical disc */
1636 		monitor = brasero_medium_monitor_get_default ();
1637 		while (brasero_medium_monitor_is_probing (monitor))
1638 			sleep (1);
1639 
1640 		/* Check if this is a mount point for an optical disc */
1641 		directory_path = g_file_get_path (file);
1642 		drives = brasero_medium_monitor_get_drives (monitor, BRASERO_DRIVE_TYPE_ALL_BUT_FILE);
1643 		for (iter = drives; iter; iter = iter->next) {
1644 			gchar *mountpoint;
1645 			BraseroDrive *drive;
1646 			BraseroMedium *medium;
1647 
1648 			drive = iter->data;
1649 			medium = brasero_drive_get_medium (drive);
1650 			mountpoint = brasero_volume_get_mount_point (BRASERO_VOLUME (medium), NULL);
1651 			if (!mountpoint)
1652 				continue;
1653 
1654 			if (!g_strcmp0 (mountpoint, directory_path)) {
1655 				g_free (mountpoint);
1656 				brasero_app_copy_disc (app,
1657 						       burner,
1658 						       brasero_drive_get_device (drive),
1659 						       cover_project,
1660 						       burn_immediately != 0);
1661 				retval = TRUE;
1662 				break;
1663 			}
1664 			g_free (mountpoint);
1665 		}
1666 		g_slist_foreach (drives, (GFunc) g_object_unref, NULL);
1667 		g_slist_free (drives);
1668 
1669 		g_free (directory_path);
1670 	}
1671 
1672 	g_object_unref (info);
1673 	g_object_unref (file);
1674 	g_free (uri);
1675 	return retval;
1676 }
1677 
1678 static void
brasero_app_recent_open(GtkRecentChooser * chooser,BraseroApp * app)1679 brasero_app_recent_open (GtkRecentChooser *chooser,
1680 			 BraseroApp *app)
1681 {
1682 	gchar *uri;
1683     	const gchar *mime;
1684     	GtkRecentInfo *item;
1685 	GtkRecentManager *manager;
1686 
1687 	/* This is a workaround since following code doesn't work */
1688 	/*
1689     	item = gtk_recent_chooser_get_current_item (GTK_RECENT_CHOOSER (chooser));
1690 	if (!item)
1691 		return;
1692 	*/
1693 
1694 	uri = gtk_recent_chooser_get_current_uri (GTK_RECENT_CHOOSER (chooser));
1695 	if (!uri)
1696 		return;
1697 
1698 	manager = gtk_recent_manager_get_default ();
1699 	item = gtk_recent_manager_lookup_item (manager, uri, NULL);
1700 
1701 	if (!item) {
1702 		g_free (uri);
1703 		return;
1704 	}
1705 
1706 	mime = gtk_recent_info_get_mime_type (item);
1707 
1708 	if (!mime) {
1709 		g_free (uri);
1710 		g_warning ("Unrecognized mime type");
1711 		return;
1712 	}
1713 
1714 	/* Make sure it is no longer one shot */
1715 	brasero_app_open_by_mime (app,
1716 	                          uri,
1717 	                          mime,
1718 	                          TRUE);
1719 	gtk_recent_info_unref (item);
1720 	g_free (uri);
1721 }
1722 
1723 static void
brasero_app_add_recent(BraseroApp * app,GtkActionGroup * group)1724 brasero_app_add_recent (BraseroApp *app,
1725 			GtkActionGroup *group)
1726 {
1727 	GtkRecentManager *recent;
1728 	GtkRecentFilter *filter;
1729 	GtkAction *action;
1730 
1731 	recent = gtk_recent_manager_get_default ();
1732 	action = gtk_recent_action_new_for_manager ("RecentProjects",
1733 						    _("_Recent Projects"),
1734 						    _("Display the projects recently opened"),
1735 						    NULL,
1736 						    recent);
1737 	filter = gtk_recent_filter_new ();
1738 
1739 	gtk_recent_filter_set_name (filter, _("_Recent Projects"));
1740 	gtk_recent_filter_add_mime_type (filter, "application/x-brasero");
1741 	gtk_recent_filter_add_mime_type (filter, "application/x-cd-image");
1742 	gtk_recent_filter_add_mime_type (filter, "application/x-cdrdao-toc");
1743 	gtk_recent_filter_add_mime_type (filter, "application/x-toc");
1744 	gtk_recent_filter_add_mime_type (filter, "application/x-cue");
1745 	gtk_recent_filter_add_mime_type (filter, "audio/x-scpls");
1746 	gtk_recent_filter_add_mime_type (filter, "audio/x-ms-asx");
1747 	gtk_recent_filter_add_mime_type (filter, "audio/x-mp3-playlist");
1748 	gtk_recent_filter_add_mime_type (filter, "audio/x-mpegurl");
1749 
1750 	gtk_recent_chooser_add_filter (GTK_RECENT_CHOOSER (action), filter);
1751 	gtk_recent_chooser_set_filter (GTK_RECENT_CHOOSER (action), filter);
1752 
1753 	gtk_recent_chooser_set_local_only (GTK_RECENT_CHOOSER (action), TRUE);
1754 
1755 	gtk_recent_chooser_set_limit (GTK_RECENT_CHOOSER (action), 5);
1756 
1757 	gtk_recent_chooser_set_show_tips (GTK_RECENT_CHOOSER (action), TRUE);
1758 
1759 	gtk_recent_chooser_set_show_icons (GTK_RECENT_CHOOSER (action), TRUE);
1760 
1761 	gtk_recent_chooser_set_sort_type (GTK_RECENT_CHOOSER (action), GTK_RECENT_SORT_MRU);
1762 
1763 	gtk_action_group_add_action (group, action);
1764 	g_object_unref (action);
1765 	g_signal_connect (action,
1766 			  "item-activated",
1767 			  G_CALLBACK (brasero_app_recent_open),
1768 			  app);
1769 }
1770 
1771 static void
brasero_menu_item_selected_cb(GtkMenuItem * proxy,BraseroApp * app)1772 brasero_menu_item_selected_cb (GtkMenuItem *proxy,
1773 			       BraseroApp *app)
1774 {
1775 	BraseroAppPrivate *priv;
1776 	GtkAction *action;
1777 	gchar *message;
1778 
1779 	priv = BRASERO_APP_PRIVATE (app);
1780 
1781 	action = gtk_activatable_get_related_action (GTK_ACTIVATABLE (proxy));
1782 	g_return_if_fail (action != NULL);
1783 
1784 	g_object_get (G_OBJECT (action), "tooltip", &message, NULL);
1785 	if (message) {
1786 		gtk_statusbar_push (GTK_STATUSBAR (priv->statusbar2),
1787 				    priv->tooltip_ctx,
1788 				    message);
1789 		g_free (message);
1790 
1791 		gtk_statusbar_push (GTK_STATUSBAR (priv->statusbar1),
1792 				    priv->tooltip_ctx,
1793 				    "");
1794 	}
1795 }
1796 
1797 static void
brasero_menu_item_deselected_cb(GtkMenuItem * proxy,BraseroApp * app)1798 brasero_menu_item_deselected_cb (GtkMenuItem *proxy,
1799 				 BraseroApp *app)
1800 {
1801 	BraseroAppPrivate *priv;
1802 
1803 	priv = BRASERO_APP_PRIVATE (app);
1804 
1805 	gtk_statusbar_pop (GTK_STATUSBAR (priv->statusbar2),
1806 			   priv->tooltip_ctx);
1807 	gtk_statusbar_pop (GTK_STATUSBAR (priv->statusbar1),
1808 			   priv->tooltip_ctx);
1809 }
1810 
1811 static void
brasero_connect_ui_manager_proxy_cb(GtkUIManager * manager,GtkAction * action,GtkWidget * proxy,BraseroApp * app)1812 brasero_connect_ui_manager_proxy_cb (GtkUIManager *manager,
1813 				     GtkAction *action,
1814 				     GtkWidget *proxy,
1815 				     BraseroApp *app)
1816 {
1817 	if (!GTK_IS_MENU_ITEM (proxy))
1818 		return;
1819 
1820 	g_signal_connect (proxy,
1821 			  "select",
1822 			  G_CALLBACK (brasero_menu_item_selected_cb),
1823 			  app);
1824 	g_signal_connect (proxy,
1825 			  "deselect",
1826 			  G_CALLBACK (brasero_menu_item_deselected_cb),
1827 			  app);
1828 }
1829 
1830 static void
brasero_disconnect_ui_manager_proxy_cb(GtkUIManager * manager,GtkAction * action,GtkWidget * proxy,BraseroApp * app)1831 brasero_disconnect_ui_manager_proxy_cb (GtkUIManager *manager,
1832 					GtkAction *action,
1833 					GtkWidget *proxy,
1834 					BraseroApp *app)
1835 {
1836 	if (!GTK_IS_MENU_ITEM (proxy))
1837 		return;
1838 
1839 	g_signal_handlers_disconnect_by_func (proxy,
1840 					      G_CALLBACK (brasero_menu_item_selected_cb),
1841 					      app);
1842 	g_signal_handlers_disconnect_by_func (proxy,
1843 					      G_CALLBACK (brasero_menu_item_deselected_cb),
1844 					      app);
1845 }
1846 
1847 static void
brasero_caps_changed_cb(BraseroPluginManager * manager,BraseroApp * app)1848 brasero_caps_changed_cb (BraseroPluginManager *manager,
1849 			 BraseroApp *app)
1850 {
1851 	BraseroAppPrivate *priv;
1852 	GtkWidget *widget;
1853 
1854 	priv = BRASERO_APP_PRIVATE (app);
1855 
1856 	widget = gtk_ui_manager_get_widget (priv->manager, "/menubar/ToolMenu/Check");
1857 
1858 	if (!brasero_burn_library_can_checksum ())
1859 		gtk_widget_set_sensitive (widget, FALSE);
1860 	else
1861 		gtk_widget_set_sensitive (widget, TRUE);
1862 }
1863 
1864 void
brasero_app_create_mainwin(BraseroApp * app)1865 brasero_app_create_mainwin (BraseroApp *app)
1866 {
1867 	GtkWidget *hbox;
1868 	GtkWidget *menubar;
1869 	GError *error = NULL;
1870 	BraseroAppPrivate *priv;
1871 	GtkAccelGroup *accel_group;
1872 	GtkActionGroup *action_group;
1873 	BraseroPluginManager *plugin_manager;
1874 
1875 	priv = BRASERO_APP_PRIVATE (app);
1876 
1877 	if (priv->mainwin)
1878 		return;
1879 
1880 	/* New window */
1881 	priv->mainwin = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1882 	gtk_window_set_icon_name (GTK_WINDOW (priv->mainwin), "brasero");
1883 
1884 	g_signal_connect (G_OBJECT (priv->mainwin),
1885 			  "delete-event",
1886 			  G_CALLBACK (on_delete_cb),
1887 			  app);
1888 	g_signal_connect (G_OBJECT (priv->mainwin),
1889 			  "destroy",
1890 			  G_CALLBACK (on_destroy_cb),
1891 			  app);
1892 
1893 	/* contents */
1894 	priv->contents = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
1895 	gtk_widget_show (priv->contents);
1896 
1897 	gtk_container_add (GTK_CONTAINER (priv->mainwin), priv->contents);
1898 
1899 	/* menu and toolbar */
1900 	priv->manager = gtk_ui_manager_new ();
1901 	g_signal_connect (priv->manager,
1902 			  "connect-proxy",
1903 			  G_CALLBACK (brasero_connect_ui_manager_proxy_cb),
1904 			  app);
1905 	g_signal_connect (priv->manager,
1906 			  "disconnect-proxy",
1907 			  G_CALLBACK (brasero_disconnect_ui_manager_proxy_cb),
1908 			  app);
1909 
1910 	action_group = gtk_action_group_new ("MenuActions");
1911 	gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1912 	gtk_action_group_add_actions (action_group,
1913 				      entries,
1914 				      G_N_ELEMENTS (entries),
1915 				      app);
1916 
1917 	gtk_ui_manager_insert_action_group (priv->manager, action_group, 0);
1918 
1919 	brasero_app_add_recent (app, action_group);
1920 
1921 	if (!gtk_ui_manager_add_ui_from_string (priv->manager, description, -1, &error)) {
1922 		g_message ("building menus failed: %s", error->message);
1923 		g_error_free (error);
1924 	}
1925 
1926 	menubar = gtk_ui_manager_get_widget (priv->manager, "/menubar");
1927 	gtk_box_pack_start (GTK_BOX (priv->contents), menubar, FALSE, FALSE, 0);
1928 
1929 	/* window contents */
1930 	priv->projects = brasero_project_manager_new ();
1931 	gtk_widget_show (priv->projects);
1932 
1933 	gtk_box_pack_start (GTK_BOX (priv->contents), priv->projects, TRUE, TRUE, 0);
1934 
1935 	/* status bar to display the size of selected files */
1936 	hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
1937 	gtk_widget_show (hbox);
1938 	gtk_box_pack_end (GTK_BOX (priv->contents), hbox, FALSE, TRUE, 0);
1939 
1940 	priv->statusbar2 = gtk_statusbar_new ();
1941 	gtk_widget_show (priv->statusbar2);
1942 	priv->tooltip_ctx = gtk_statusbar_get_context_id (GTK_STATUSBAR (priv->statusbar2), "tooltip_info");
1943 	gtk_box_pack_start (GTK_BOX (hbox), priv->statusbar2, FALSE, TRUE, 0);
1944 
1945 	priv->statusbar1 = gtk_statusbar_new ();
1946 	gtk_widget_show (priv->statusbar1);
1947 	gtk_box_pack_start (GTK_BOX (hbox), priv->statusbar1, FALSE, TRUE, 0);
1948 
1949 	/* Update everything */
1950 	brasero_project_manager_register_ui (BRASERO_PROJECT_MANAGER (priv->projects),
1951 					     priv->manager);
1952 
1953 	gtk_ui_manager_ensure_update (priv->manager);
1954 
1955 	/* check if we can use checksums (we need plugins enabled) */
1956 	if (!brasero_burn_library_can_checksum ()) {
1957 		GtkWidget *widget;
1958 
1959 		widget = gtk_ui_manager_get_widget (priv->manager, "/menubar/ToolMenu/Check");
1960 		gtk_widget_set_sensitive (widget, FALSE);
1961 	}
1962 
1963 	plugin_manager = brasero_plugin_manager_get_default ();
1964 	g_signal_connect (plugin_manager,
1965 			  "caps-changed",
1966 			  G_CALLBACK (brasero_caps_changed_cb),
1967 			  app);
1968 
1969 	/* add accelerators */
1970 	accel_group = gtk_ui_manager_get_accel_group (priv->manager);
1971 	gtk_window_add_accel_group (GTK_WINDOW (priv->mainwin), accel_group);
1972 
1973 	/* set up the window geometry */
1974 	gtk_window_set_position (GTK_WINDOW (priv->mainwin),
1975 				 GTK_WIN_POS_CENTER);
1976 
1977 	g_signal_connect (priv->mainwin,
1978 			  "window-state-event",
1979 			  G_CALLBACK (on_window_state_changed_cb),
1980 			  app);
1981 	g_signal_connect (priv->mainwin,
1982 			  "configure-event",
1983 			  G_CALLBACK (on_configure_event_cb),
1984 			  app);
1985 
1986 	gtk_widget_realize (GTK_WIDGET (priv->mainwin));
1987 
1988 	if (priv->parent) {
1989 		gtk_window_set_modal (GTK_WINDOW (priv->mainwin), TRUE);
1990 		gdk_window_set_transient_for (gtk_widget_get_window (GTK_WIDGET (priv->mainwin)), priv->parent);
1991 	}
1992 
1993 	brasero_app_load_window_state (app);
1994 }
1995 
1996 static void
brasero_app_activate(GApplication * gapp,BraseroApp * app)1997 brasero_app_activate (GApplication *gapp,
1998                       BraseroApp *app)
1999 {
2000 	BraseroAppPrivate *priv;
2001 
2002 	priv = BRASERO_APP_PRIVATE (app);
2003 
2004 	/* Except if we are supposed to quit, show the window */
2005 	if (priv->mainwin_running) {
2006 		gtk_widget_show (priv->mainwin);
2007 		gtk_window_present (GTK_WINDOW (priv->mainwin));
2008 	}
2009 }
2010 
2011 gboolean
brasero_app_run_mainwin(BraseroApp * app)2012 brasero_app_run_mainwin (BraseroApp *app)
2013 {
2014 	BraseroAppPrivate *priv;
2015 
2016 	priv = BRASERO_APP_PRIVATE (app);
2017 
2018 	if (!priv->mainwin)
2019 		return FALSE;
2020 
2021 	if (priv->mainwin_running)
2022 		return TRUE;
2023 
2024 	priv->mainwin_running = 1;
2025 	gtk_widget_show (GTK_WIDGET (priv->mainwin));
2026 
2027 	if (priv->gapp)
2028 		g_signal_connect (priv->gapp,
2029 				  "activate",
2030 				  G_CALLBACK (brasero_app_activate),
2031 				  app);
2032 	gtk_main ();
2033 	return TRUE;
2034 }
2035 
2036 static GtkWindow *
brasero_app_get_io_parent_window(gpointer user_data)2037 brasero_app_get_io_parent_window (gpointer user_data)
2038 {
2039 	BraseroAppPrivate *priv;
2040 
2041 	priv = BRASERO_APP_PRIVATE (user_data);
2042 	if (!priv->mainwin) {
2043 		if (priv->parent)
2044 			return GTK_WINDOW (priv->parent);
2045 	}
2046 	else {
2047 		GtkWidget *toplevel;
2048 
2049 		toplevel = gtk_widget_get_toplevel (GTK_WIDGET (priv->mainwin));
2050 		return GTK_WINDOW (toplevel);
2051 	}
2052 
2053 	return NULL;
2054 }
2055 
2056 static void
brasero_app_init(BraseroApp * object)2057 brasero_app_init (BraseroApp *object)
2058 {
2059 	BraseroAppPrivate *priv;
2060 
2061 	priv = BRASERO_APP_PRIVATE (object);
2062 
2063 	priv->mainwin = NULL;
2064 
2065 	/* Load settings */
2066 	priv->setting = brasero_setting_get_default ();
2067 	brasero_setting_load (priv->setting);
2068 
2069 	g_set_application_name (_("Disc Burner"));
2070 	gtk_window_set_default_icon_name ("brasero");
2071 
2072 	brasero_io_set_parent_window_callback (brasero_app_get_io_parent_window, object);
2073 }
2074 
2075 static void
brasero_app_finalize(GObject * object)2076 brasero_app_finalize (GObject *object)
2077 {
2078 	BraseroAppPrivate *priv;
2079 
2080 	priv = BRASERO_APP_PRIVATE (object);
2081 
2082 	brasero_setting_save (priv->setting);
2083 	g_object_unref (priv->setting);
2084 	priv->setting = NULL;
2085 
2086 	if (priv->saved_contents) {
2087 		g_free (priv->saved_contents);
2088 		priv->saved_contents = NULL;
2089 	}
2090 
2091 	G_OBJECT_CLASS (brasero_app_parent_class)->finalize (object);
2092 }
2093 static void
brasero_app_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)2094 brasero_app_set_property (GObject *object,
2095                           guint prop_id,
2096                           const GValue *value,
2097                           GParamSpec *pspec)
2098 {
2099 	BraseroAppPrivate *priv;
2100 
2101 	g_return_if_fail (BRASERO_IS_APP (object));
2102 
2103 	priv = BRASERO_APP_PRIVATE (object);
2104 
2105 	switch (prop_id)
2106 	{
2107 	case PROP_GAPP:
2108 		priv->gapp = g_value_dup_object (value);
2109 		break;
2110 	default:
2111 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2112 		break;
2113 	}
2114 }
2115 
2116 static void
brasero_app_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)2117 brasero_app_get_property (GObject *object,
2118 			  guint prop_id,
2119 			  GValue *value,
2120 			  GParamSpec *pspec)
2121 {
2122 	BraseroAppPrivate *priv;
2123 
2124 	g_return_if_fail (BRASERO_IS_APP (object));
2125 
2126 	priv = BRASERO_APP_PRIVATE (object);
2127 
2128 	switch (prop_id)
2129 	{
2130 	case PROP_GAPP:
2131 		g_value_set_object (value, priv->gapp);
2132 		break;
2133 	default:
2134 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2135 		break;
2136 	}
2137 }
2138 
2139 static void
brasero_app_class_init(BraseroAppClass * klass)2140 brasero_app_class_init (BraseroAppClass *klass)
2141 {
2142 	GObjectClass* object_class = G_OBJECT_CLASS (klass);
2143 
2144 	g_type_class_add_private (klass, sizeof (BraseroAppPrivate));
2145 
2146 	object_class->finalize = brasero_app_finalize;
2147 	object_class->set_property = brasero_app_set_property;
2148 	object_class->get_property = brasero_app_get_property;
2149 
2150 	g_object_class_install_property (object_class,
2151 	                                 PROP_GAPP,
2152 	                                 g_param_spec_object("gapp",
2153 	                                                     "GApplication",
2154 	                                                     "The GApplication object",
2155 	                                                     G_TYPE_APPLICATION,
2156 	                                                     G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
2157 }
2158 
2159 BraseroApp *
brasero_app_new(GApplication * gapp)2160 brasero_app_new (GApplication *gapp)
2161 {
2162 	return g_object_new (BRASERO_TYPE_APP,
2163 	                     "gapp", gapp,
2164 	                     NULL);
2165 }
2166