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