1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /*
3  * Libbrasero-burn
4  * Copyright (C) Philippe Rouquier 2005-2009 <bonfire-app@wanadoo.fr>
5  *
6  * Libbrasero-burn 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  * The Libbrasero-burn authors hereby grant permission for non-GPL compatible
12  * GStreamer plugins to be used and distributed together with GStreamer
13  * and Libbrasero-burn. This permission is above and beyond the permissions granted
14  * by the GPL license by which Libbrasero-burn is covered. If you modify this code
15  * you may extend this exception to your version of the code, but you are not
16  * obligated to do so. If you do not wish to do so, delete this exception
17  * statement from your version.
18  *
19  * Libbrasero-burn is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU Library General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to:
26  * 	The Free Software Foundation, Inc.,
27  * 	51 Franklin Street, Fifth Floor
28  * 	Boston, MA  02110-1301, USA.
29  */
30 
31 #ifdef HAVE_CONFIG_H
32 #  include <config.h>
33 #endif
34 
35 #include <glib.h>
36 #include <glib-object.h>
37 #include <glib/gi18n-lib.h>
38 
39 #include <gdk/gdkx.h>
40 #include <gtk/gtk.h>
41 
42 #include "burn-basics.h"
43 
44 #include "brasero-medium.h"
45 #include "brasero-medium-selection-priv.h"
46 
47 #include "burn-debug.h"
48 #include "brasero-session.h"
49 #include "brasero-session-helper.h"
50 #include "brasero-burn-options.h"
51 #include "brasero-video-options.h"
52 #include "brasero-src-image.h"
53 #include "brasero-src-selection.h"
54 #include "brasero-session-cfg.h"
55 #include "brasero-dest-selection.h"
56 #include "brasero-medium-properties.h"
57 #include "brasero-status-dialog.h"
58 #include "brasero-track-stream.h"
59 #include "brasero-track-data-cfg.h"
60 #include "brasero-track-image-cfg.h"
61 
62 #include "brasero-notify.h"
63 #include "brasero-misc.h"
64 #include "brasero-pk.h"
65 
66 typedef struct _BraseroBurnOptionsPrivate BraseroBurnOptionsPrivate;
67 struct _BraseroBurnOptionsPrivate
68 {
69 	BraseroSessionCfg *session;
70 
71 	GtkSizeGroup *size_group;
72 
73 	GtkWidget *source;
74 	GtkWidget *source_placeholder;
75 	GtkWidget *message_input;
76 	GtkWidget *selection;
77 	GtkWidget *properties;
78 	GtkWidget *message_output;
79 	GtkWidget *options;
80 	GtkWidget *options_placeholder;
81 	GtkWidget *button;
82 
83 	GtkWidget *burn;
84 	GtkWidget *burn_multi;
85 
86 	guint not_ready_id;
87 	GtkWidget *status_dialog;
88 
89 	GCancellable *cancel;
90 
91 	guint is_valid:1;
92 
93 	guint has_image:1;
94 	guint has_audio:1;
95 	guint has_video:1;
96 	guint has_data:1;
97 	guint has_disc:1;
98 };
99 
100 #define BRASERO_BURN_OPTIONS_PRIVATE(o)  (G_TYPE_INSTANCE_GET_PRIVATE ((o), BRASERO_TYPE_BURN_OPTIONS, BraseroBurnOptionsPrivate))
101 
102 enum {
103 	PROP_0,
104 	PROP_SESSION
105 };
106 
107 G_DEFINE_TYPE (BraseroBurnOptions, brasero_burn_options, GTK_TYPE_DIALOG);
108 
109 static void
brasero_burn_options_add_source(BraseroBurnOptions * self,const gchar * title,...)110 brasero_burn_options_add_source (BraseroBurnOptions *self,
111 				 const gchar *title,
112 				 ...)
113 {
114 	va_list vlist;
115 	GtkWidget *child;
116 	GSList *list = NULL;
117 	BraseroBurnOptionsPrivate *priv;
118 
119 	priv = BRASERO_BURN_OPTIONS_PRIVATE (self);
120 
121 	/* create message queue for input */
122 	priv->message_input = brasero_notify_new ();
123 	list = g_slist_prepend (list, priv->message_input);
124 
125 	va_start (vlist, title);
126 	while ((child = va_arg (vlist, GtkWidget *))) {
127 		GtkWidget *hbox;
128 		GtkWidget *alignment;
129 
130 		hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
131 		gtk_widget_show (hbox);
132 
133 		gtk_box_pack_start (GTK_BOX (hbox), child, TRUE, TRUE, 0);
134 
135 		alignment = gtk_alignment_new (0.0, 0.5, 0., 0.);
136 		gtk_widget_show (alignment);
137 		gtk_size_group_add_widget (priv->size_group, alignment);
138 		gtk_box_pack_start (GTK_BOX (hbox), alignment, FALSE, FALSE, 0);
139 
140 		list = g_slist_prepend (list, hbox);
141 	}
142 	va_end (vlist);
143 
144 	priv->source = brasero_utils_pack_properties_list (title, list);
145 	g_slist_free (list);
146 
147 	gtk_container_add (GTK_CONTAINER (priv->source_placeholder), priv->source);
148 	gtk_widget_show (priv->source_placeholder);
149 }
150 
151 /**
152  * brasero_burn_options_add_options:
153  * @dialog: a #BraseroBurnOptions
154  * @options: a #GtkWidget
155  *
156  * Adds some new options to be displayed in the dialog.
157  **/
158 
159 void
brasero_burn_options_add_options(BraseroBurnOptions * self,GtkWidget * options)160 brasero_burn_options_add_options (BraseroBurnOptions *self,
161 				  GtkWidget *options)
162 {
163 	BraseroBurnOptionsPrivate *priv;
164 
165 	priv = BRASERO_BURN_OPTIONS_PRIVATE (self);
166 	gtk_box_pack_start (GTK_BOX (priv->options), options, FALSE, TRUE, 0);
167 	gtk_widget_show (priv->options);
168 }
169 
170 static void
brasero_burn_options_set_type_shown(BraseroBurnOptions * self,BraseroMediaType type)171 brasero_burn_options_set_type_shown (BraseroBurnOptions *self,
172 				     BraseroMediaType type)
173 {
174 	BraseroBurnOptionsPrivate *priv;
175 
176 	priv = BRASERO_BURN_OPTIONS_PRIVATE (self);
177 	brasero_medium_selection_show_media_type (BRASERO_MEDIUM_SELECTION (priv->selection), type);
178 }
179 
180 static void
brasero_burn_options_message_response_cb(BraseroDiscMessage * message,GtkResponseType response,BraseroBurnOptions * self)181 brasero_burn_options_message_response_cb (BraseroDiscMessage *message,
182 					  GtkResponseType response,
183 					  BraseroBurnOptions *self)
184 {
185 	if (response == GTK_RESPONSE_OK) {
186 		BraseroBurnOptionsPrivate *priv;
187 
188 		priv = BRASERO_BURN_OPTIONS_PRIVATE (self);
189 		brasero_session_cfg_add_flags (priv->session, BRASERO_BURN_FLAG_OVERBURN);
190 	}
191 }
192 
193 static void
brasero_burn_options_message_response_span_cb(BraseroDiscMessage * message,GtkResponseType response,BraseroBurnOptions * self)194 brasero_burn_options_message_response_span_cb (BraseroDiscMessage *message,
195 					       GtkResponseType response,
196 					       BraseroBurnOptions *self)
197 {
198 	if (response == GTK_RESPONSE_OK) {
199 		BraseroBurnOptionsPrivate *priv;
200 
201 		priv = BRASERO_BURN_OPTIONS_PRIVATE (self);
202 		brasero_session_span_start (BRASERO_SESSION_SPAN (priv->session));
203 		if (brasero_session_span_next (BRASERO_SESSION_SPAN (priv->session)) == BRASERO_BURN_ERR)
204 			BRASERO_BURN_LOG ("Spanning failed\n");
205 	}
206 }
207 
208 #define BRASERO_BURN_OPTIONS_NO_MEDIUM_WARNING	1000
209 
210 static void
brasero_burn_options_update_no_medium_warning(BraseroBurnOptions * self)211 brasero_burn_options_update_no_medium_warning (BraseroBurnOptions *self)
212 {
213 	BraseroBurnOptionsPrivate *priv;
214 
215 	priv = BRASERO_BURN_OPTIONS_PRIVATE (self);
216 
217 	if (!priv->is_valid
218 	||  !brasero_burn_session_is_dest_file (BRASERO_BURN_SESSION (priv->session))
219 	||   brasero_medium_selection_get_media_num (BRASERO_MEDIUM_SELECTION (priv->selection)) != 1) {
220 		brasero_notify_message_remove (priv->message_output,
221 					       BRASERO_BURN_OPTIONS_NO_MEDIUM_WARNING);
222 		return;
223 	}
224 
225 	/* The user may have forgotten to insert a disc so remind him of that if
226 	 * there aren't any other possibility in the selection */
227 	brasero_notify_message_add (priv->message_output,
228 				    _("Please insert a writable CD or DVD if you don't want to write to an image file."),
229 				    NULL,
230 				    -1,
231 				    BRASERO_BURN_OPTIONS_NO_MEDIUM_WARNING);
232 }
233 
234 static void
brasero_burn_options_not_ready_dialog_cancel_cb(GtkDialog * dialog,guint response,gpointer data)235 brasero_burn_options_not_ready_dialog_cancel_cb (GtkDialog *dialog,
236 						 guint response,
237 						 gpointer data)
238 {
239 	BraseroBurnOptionsPrivate *priv;
240 
241 	priv = BRASERO_BURN_OPTIONS_PRIVATE (data);
242 
243 	if (priv->not_ready_id) {
244 		g_source_remove (priv->not_ready_id);
245 		priv->not_ready_id = 0;
246 	}
247 	gtk_widget_set_sensitive (GTK_WIDGET (data), TRUE);
248 
249 	if (response != GTK_RESPONSE_OK)
250 		gtk_dialog_response (GTK_DIALOG (data),
251 				     GTK_RESPONSE_CANCEL);
252 	else {
253 		priv->status_dialog = NULL;
254 		gtk_widget_destroy (GTK_WIDGET (dialog));
255 	}
256 }
257 
258 static gboolean
brasero_burn_options_not_ready_dialog_show_cb(gpointer data)259 brasero_burn_options_not_ready_dialog_show_cb (gpointer data)
260 {
261 	BraseroBurnOptionsPrivate *priv;
262 
263 	priv = BRASERO_BURN_OPTIONS_PRIVATE (data);
264 
265 	/* icon should be set by now */
266 	gtk_window_set_icon_name (GTK_WINDOW (priv->status_dialog),
267 	                          gtk_window_get_icon_name (GTK_WINDOW (data)));
268 
269 	gtk_widget_show (priv->status_dialog);
270 	priv->not_ready_id = 0;
271 	return FALSE;
272 }
273 
274 static void
brasero_burn_options_not_ready_dialog_shown_cb(GtkWidget * widget,gpointer data)275 brasero_burn_options_not_ready_dialog_shown_cb (GtkWidget *widget,
276                                                 gpointer data)
277 {
278 	BraseroBurnOptionsPrivate *priv;
279 
280 	priv = BRASERO_BURN_OPTIONS_PRIVATE (data);
281 	if (priv->not_ready_id) {
282 		g_source_remove (priv->not_ready_id);
283 		priv->not_ready_id = 0;
284 	}
285 }
286 
287 static void
brasero_burn_options_setup_buttons(BraseroBurnOptions * self)288 brasero_burn_options_setup_buttons (BraseroBurnOptions *self)
289 {
290 	BraseroBurnOptionsPrivate *priv;
291 	BraseroTrackType *type;
292 	gchar *label_m = "";
293 	gchar *label;
294 	gchar *icon;
295 
296 	priv = BRASERO_BURN_OPTIONS_PRIVATE (self);
297 
298 	/* add the new widgets */
299 	type = brasero_track_type_new ();
300 	brasero_burn_session_get_input_type (BRASERO_BURN_SESSION (priv->session), type);
301 	if (brasero_burn_session_is_dest_file (BRASERO_BURN_SESSION (priv->session))) {
302 		label = _("Create _Image");
303 		icon = "iso-image-new";
304 	}
305 	else if (brasero_track_type_get_has_medium (type)) {
306 		/* Translators: This is a verb, an action */
307 		label = _("_Copy");
308 		icon = "media-optical-copy";
309 
310 		label_m = _("Make _Several Copies");
311 	}
312 	else {
313 		/* Translators: This is a verb, an action */
314 		label = _("_Burn");
315 		icon = "media-optical-burn";
316 
317 		label_m = _("Burn _Several Copies");
318 	}
319 
320 	if (priv->burn_multi)
321 		gtk_button_set_label (GTK_BUTTON (priv->burn_multi), label_m);
322 	else
323 		priv->burn_multi = gtk_dialog_add_button (GTK_DIALOG (self),
324 							  label_m,
325 							  GTK_RESPONSE_ACCEPT);
326 
327 	if (brasero_burn_session_is_dest_file (BRASERO_BURN_SESSION (priv->session)))
328 		gtk_widget_hide (priv->burn_multi);
329 	else
330 		gtk_widget_show (priv->burn_multi);
331 
332 	if (priv->burn)
333 		gtk_button_set_label (GTK_BUTTON (priv->burn), label);
334 	else
335 		priv->burn = gtk_dialog_add_button (GTK_DIALOG (self),
336 						    label,
337 						    GTK_RESPONSE_OK);
338 
339 	gtk_button_set_image (GTK_BUTTON (priv->burn), gtk_image_new_from_icon_name (icon, GTK_ICON_SIZE_BUTTON));
340 
341 	gtk_widget_set_sensitive (priv->burn, priv->is_valid);
342 	gtk_widget_set_sensitive (priv->burn_multi, priv->is_valid);
343 
344 	brasero_track_type_free (type);
345 }
346 
347 static void
brasero_burn_options_update_valid(BraseroBurnOptions * self)348 brasero_burn_options_update_valid (BraseroBurnOptions *self)
349 {
350 	BraseroBurnOptionsPrivate *priv;
351 	BraseroSessionError valid;
352 	BraseroDrive *drive;
353 
354 	priv = BRASERO_BURN_OPTIONS_PRIVATE (self);
355 
356 	valid = brasero_session_cfg_get_error (priv->session);
357 	priv->is_valid = BRASERO_SESSION_IS_VALID (valid);
358 
359 	brasero_burn_options_setup_buttons (self);
360 
361 	gtk_widget_set_sensitive (priv->options, priv->is_valid);
362 	/* Ensure the user can always change the properties (i.e. file location)
363 	 * the target is a fake drive */
364 	drive = brasero_burn_session_get_burner (BRASERO_BURN_SESSION (priv->session));
365 	if (drive && brasero_drive_is_fake (drive))
366 		gtk_widget_set_sensitive (priv->properties, TRUE);
367 	else
368 		gtk_widget_set_sensitive (priv->properties, priv->is_valid);
369 
370 	if (priv->message_input) {
371 		gtk_widget_hide (priv->message_input);
372 		brasero_notify_message_remove (priv->message_input,
373 					       BRASERO_NOTIFY_CONTEXT_SIZE);
374 	}
375 
376 	brasero_notify_message_remove (priv->message_output,
377 				       BRASERO_NOTIFY_CONTEXT_SIZE);
378 
379 	if (valid == BRASERO_SESSION_NOT_READY) {
380 		if (!priv->not_ready_id && !priv->status_dialog) {
381 			gtk_widget_set_sensitive (GTK_WIDGET (self), FALSE);
382 			priv->status_dialog = brasero_status_dialog_new (BRASERO_BURN_SESSION (priv->session),  GTK_WIDGET (self));
383 			g_signal_connect (priv->status_dialog,
384 					  "response",
385 					  G_CALLBACK (brasero_burn_options_not_ready_dialog_cancel_cb),
386 					  self);
387 
388 			g_signal_connect (priv->status_dialog,
389 					  "show",
390 					  G_CALLBACK (brasero_burn_options_not_ready_dialog_shown_cb),
391 					  self);
392 			g_signal_connect (priv->status_dialog,
393 					  "user-interaction",
394 					  G_CALLBACK (brasero_burn_options_not_ready_dialog_shown_cb),
395 					  self);
396 
397 			priv->not_ready_id = g_timeout_add_seconds (1,
398 								    brasero_burn_options_not_ready_dialog_show_cb,
399 								    self);
400 		}
401 	}
402 	else {
403 		gtk_widget_set_sensitive (GTK_WIDGET (self), TRUE);
404 		if (priv->status_dialog) {
405 			gtk_widget_destroy (priv->status_dialog);
406 			priv->status_dialog = NULL;
407 		}
408 
409 		if (priv->not_ready_id) {
410 			g_source_remove (priv->not_ready_id);
411 			priv->not_ready_id = 0;
412 		}
413 	}
414 
415 	if (valid == BRASERO_SESSION_INSUFFICIENT_SPACE) {
416 		goffset min_disc_size;
417 		goffset available_space;
418 
419 		min_disc_size = brasero_session_span_get_max_space (BRASERO_SESSION_SPAN (priv->session));
420 
421 		/* One rule should be that the maximum batch size should not exceed the disc size
422 		 * FIXME: we could change it into a dialog telling the user what is the maximum
423 		 * size required. */
424 		available_space = brasero_burn_session_get_available_medium_space (BRASERO_BURN_SESSION (priv->session));
425 
426 		/* Here there is an alternative: we may be able to span the data
427 		 * across multiple media. So try that. */
428 		if (available_space > min_disc_size
429 		&&  brasero_session_span_possible (BRASERO_SESSION_SPAN (priv->session)) == BRASERO_BURN_RETRY) {
430 			GtkWidget *message;
431 
432 			message = brasero_notify_message_add (priv->message_output,
433 							      _("Would you like to burn the selection of files across several media?"),
434 							      _("The data size is too large for the disc even with the overburn option."),
435 							      -1,
436 							      BRASERO_NOTIFY_CONTEXT_SIZE);
437 
438 			gtk_widget_set_tooltip_text (gtk_info_bar_add_button (GTK_INFO_BAR (message),
439 									      _("_Burn Several Discs"),
440 									      GTK_RESPONSE_OK),
441 						    _("Burn the selection of files across several media"));
442 
443 			g_signal_connect (message,
444 					  "response",
445 					  G_CALLBACK (brasero_burn_options_message_response_span_cb),
446 					  self);
447 		}
448 		else
449 			brasero_notify_message_add (priv->message_output,
450 						    _("Please choose another CD or DVD or insert a new one."),
451 						    _("The data size is too large for the disc even with the overburn option."),
452 						    -1,
453 						    BRASERO_NOTIFY_CONTEXT_SIZE);
454 	}
455 	else if (valid == BRASERO_SESSION_NO_OUTPUT) {
456 		brasero_notify_message_add (priv->message_output,
457 					    _("Please insert a writable CD or DVD."),
458 					    NULL,
459 					    -1,
460 					    BRASERO_NOTIFY_CONTEXT_SIZE);
461 	}
462 	else if (valid == BRASERO_SESSION_NO_CD_TEXT) {
463 		brasero_notify_message_add (priv->message_output,
464 					    _("No track information (artist, title, ...) will be written to the disc."),
465 					    _("This is not supported by the current active burning backend."),
466 					    -1,
467 					    BRASERO_NOTIFY_CONTEXT_SIZE);
468 	}
469 	else if (valid == BRASERO_SESSION_EMPTY) {
470 		BraseroTrackType *type;
471 
472 		type = brasero_track_type_new ();
473 		brasero_burn_session_get_input_type (BRASERO_BURN_SESSION (priv->session), type);
474 
475 		if (brasero_track_type_get_has_data (type))
476 			brasero_notify_message_add (priv->message_output,
477 						    _("Please add files."),
478 						    _("There are no files to write to disc"),
479 						    -1,
480 						    BRASERO_NOTIFY_CONTEXT_SIZE);
481 		else if (!BRASERO_STREAM_FORMAT_HAS_VIDEO (brasero_track_type_get_stream_format (type)))
482 			brasero_notify_message_add (priv->message_output,
483 						    _("Please add songs."),
484 						    _("There are no songs to write to disc"),
485 						    -1,
486 						    BRASERO_NOTIFY_CONTEXT_SIZE);
487 		else
488 			brasero_notify_message_add (priv->message_output,
489 						     _("Please add videos."),
490 						    _("There are no videos to write to disc"),
491 						    -1,
492 						    BRASERO_NOTIFY_CONTEXT_SIZE);
493 		brasero_track_type_free (type);
494 		gtk_window_resize (GTK_WINDOW (self), 10, 10);
495 		return;
496 	}
497 	else if (valid == BRASERO_SESSION_NO_INPUT_MEDIUM) {
498 		if (priv->message_input) {
499 			gtk_widget_show (priv->message_input);
500 			brasero_notify_message_add (priv->message_input,
501 			                            _("Please insert a disc holding data."),
502 			                            _("There is no inserted disc to copy."),
503 			                            -1,
504 			                            BRASERO_NOTIFY_CONTEXT_SIZE);
505 		}
506 	}
507 	else if (valid == BRASERO_SESSION_NO_INPUT_IMAGE) {
508 		if (priv->message_input) {
509 			gtk_widget_show (priv->message_input);
510 			brasero_notify_message_add (priv->message_input,
511 			                            _("Please select a disc image."),
512 			                            _("There is no selected disc image."),
513 			                            -1,
514 			                            BRASERO_NOTIFY_CONTEXT_SIZE);
515 		}
516 	}
517 	else if (valid == BRASERO_SESSION_UNKNOWN_IMAGE) {
518 		if (priv->message_input) {
519 			gtk_widget_show (priv->message_input);
520 			brasero_notify_message_add (priv->message_input,
521 			                            /* Translators: this is a disc image not a picture */
522 			                            C_("disc", "Please select another image."),
523 			                            _("It doesn't appear to be a valid disc image or a valid cue file."),
524 			                            -1,
525 			                            BRASERO_NOTIFY_CONTEXT_SIZE);
526 		}
527 	}
528 	else if (valid == BRASERO_SESSION_DISC_PROTECTED) {
529 		if (priv->message_input) {
530 			gtk_widget_show (priv->message_input);
531 			brasero_notify_message_add (priv->message_input,
532 			                            _("Please insert a disc that is not copy protected."),
533 			                            _("All required applications and libraries are not installed."),
534 			                            -1,
535 			                            BRASERO_NOTIFY_CONTEXT_SIZE);
536 		}
537 	}
538 	else if (valid == BRASERO_SESSION_NOT_SUPPORTED) {
539 		brasero_notify_message_add (priv->message_output,
540 		                            _("Please replace the disc with a supported CD or DVD."),
541 		                            NULL,
542 		                            -1,
543 		                            BRASERO_NOTIFY_CONTEXT_SIZE);
544 	}
545 	else if (valid == BRASERO_SESSION_OVERBURN_NECESSARY) {
546 		GtkWidget *message;
547 
548 		message = brasero_notify_message_add (priv->message_output,
549 						      _("Would you like to burn beyond the disc's reported capacity?"),
550 						      _("The data size is too large for the disc and you must remove files from the selection otherwise."
551 							"\nYou may want to use this option if you're using 90 or 100 min CD-R(W) which cannot be properly recognised and therefore need overburn option."
552 							"\nNOTE: This option might cause failure."),
553 						      -1,
554 						      BRASERO_NOTIFY_CONTEXT_SIZE);
555 
556 		gtk_widget_set_tooltip_text (gtk_info_bar_add_button (GTK_INFO_BAR (message),
557 								      _("_Overburn"),
558 								      GTK_RESPONSE_OK),
559 					     _("Burn beyond the disc's reported capacity"));
560 
561 		g_signal_connect (message,
562 				  "response",
563 				  G_CALLBACK (brasero_burn_options_message_response_cb),
564 				  self);
565 	}
566 	else if (brasero_burn_session_same_src_dest_drive (BRASERO_BURN_SESSION (priv->session))) {
567 		/* The medium is valid but it's a special case */
568 		brasero_notify_message_add (priv->message_output,
569 					    _("The drive that holds the source disc will also be the one used to record."),
570 					    _("A new writable disc will be required once the currently loaded one has been copied."),
571 					    -1,
572 					    BRASERO_NOTIFY_CONTEXT_SIZE);
573 		gtk_widget_show_all (priv->message_output);
574 	}
575 
576 	brasero_burn_options_update_no_medium_warning (self);
577 	gtk_window_resize (GTK_WINDOW (self), 10, 10);
578 }
579 
580 static void
brasero_burn_options_valid_cb(BraseroSessionCfg * session,BraseroBurnOptions * self)581 brasero_burn_options_valid_cb (BraseroSessionCfg *session,
582 			       BraseroBurnOptions *self)
583 {
584 	brasero_burn_options_update_valid (self);
585 }
586 
587 static void
brasero_burn_options_init(BraseroBurnOptions * object)588 brasero_burn_options_init (BraseroBurnOptions *object)
589 {
590 }
591 
592 /**
593  * To build anything we need to have the session set first
594  */
595 
596 static void
brasero_burn_options_build_contents(BraseroBurnOptions * object)597 brasero_burn_options_build_contents (BraseroBurnOptions *object)
598 {
599 	BraseroBurnOptionsPrivate *priv;
600 	GtkWidget *content_area;
601 	GtkWidget *selection;
602 	GtkWidget *alignment;
603 	gchar *string;
604 
605 	priv = BRASERO_BURN_OPTIONS_PRIVATE (object);
606 
607 	priv->size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
608 
609 	/* Sets default flags for the session */
610 	brasero_burn_session_add_flag (BRASERO_BURN_SESSION (priv->session),
611 				       BRASERO_BURN_FLAG_NOGRACE|
612 				       BRASERO_BURN_FLAG_CHECK_SIZE);
613 
614 	/* Create a cancel button */
615 	gtk_dialog_add_button (GTK_DIALOG (object),
616 			       GTK_STOCK_CANCEL,
617 			       GTK_RESPONSE_CANCEL);
618 
619 	/* Create an upper box for sources */
620 	priv->source_placeholder = gtk_alignment_new (0.0, 0.5, 1.0, 1.0);
621 	content_area = gtk_dialog_get_content_area (GTK_DIALOG (object));
622 	gtk_box_pack_start (GTK_BOX (content_area),
623 			    priv->source_placeholder,
624 			    FALSE,
625 			    TRUE,
626 			    0);
627 
628 	/* Medium selection box */
629 	selection = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
630 	gtk_widget_show (selection);
631 
632 	alignment = gtk_alignment_new (0.0, 0.5, 1.0, 1.0);
633 	gtk_widget_show (alignment);
634 	gtk_box_pack_start (GTK_BOX (selection),
635 			    alignment,
636 			    TRUE,
637 			    TRUE,
638 			    0);
639 
640 	priv->selection = brasero_dest_selection_new (BRASERO_BURN_SESSION (priv->session));
641 	gtk_widget_show (priv->selection);
642 	gtk_container_add (GTK_CONTAINER (alignment), priv->selection);
643 
644 	priv->properties = brasero_medium_properties_new (priv->session);
645 	gtk_size_group_add_widget (priv->size_group, priv->properties);
646 	gtk_widget_show (priv->properties);
647 	gtk_box_pack_start (GTK_BOX (selection),
648 			    priv->properties,
649 			    FALSE,
650 			    FALSE,
651 			    0);
652 
653 	/* Box to display warning messages */
654 	priv->message_output = brasero_notify_new ();
655 	gtk_widget_show (priv->message_output);
656 
657 	string = g_strdup_printf ("<b>%s</b>", _("Select a disc to write to"));
658 	selection = brasero_utils_pack_properties (string,
659 						   priv->message_output,
660 						   selection,
661 						   NULL);
662 	g_free (string);
663 	gtk_widget_show (selection);
664 
665 	gtk_box_pack_start (GTK_BOX (content_area),
666 			    selection,
667 			    FALSE,
668 			    TRUE,
669 			    0);
670 
671 	/* Create a lower box for options */
672 	alignment = gtk_alignment_new (0.0, 0.5, 1.0, 1.0);
673 	gtk_widget_show (alignment);
674 	gtk_box_pack_start (GTK_BOX (content_area),
675 			    alignment,
676 			    FALSE,
677 			    TRUE,
678 			    0);
679 	priv->options_placeholder = alignment;
680 
681 	priv->options = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
682 	gtk_container_add (GTK_CONTAINER (alignment), priv->options);
683 
684 	g_signal_connect (priv->session,
685 			  "is-valid",
686 			  G_CALLBACK (brasero_burn_options_valid_cb),
687 			  object);
688 
689 	brasero_burn_options_update_valid (object);
690 }
691 
692 static void
brasero_burn_options_reset(BraseroBurnOptions * self)693 brasero_burn_options_reset (BraseroBurnOptions *self)
694 {
695 	BraseroBurnOptionsPrivate *priv;
696 
697 	priv = BRASERO_BURN_OPTIONS_PRIVATE (self);
698 
699 	priv->has_image = FALSE;
700 	priv->has_audio = FALSE;
701 	priv->has_video = FALSE;
702 	priv->has_data = FALSE;
703 	priv->has_disc = FALSE;
704 
705 	/* reset all the dialog */
706 	if (priv->message_input) {
707 		gtk_widget_destroy (priv->message_input);
708 		priv->message_input = NULL;
709 	}
710 
711 	if (priv->options) {
712 		gtk_widget_destroy (priv->options);
713 		priv->options = NULL;
714 	}
715 
716 	priv->options = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
717 	gtk_container_add (GTK_CONTAINER (priv->options_placeholder), priv->options);
718 
719 	if (priv->source) {
720 		gtk_widget_destroy (priv->source);
721 		priv->source = NULL;
722 	}
723 
724 	gtk_widget_hide (priv->source_placeholder);
725 }
726 
727 static void
brasero_burn_options_setup_audio(BraseroBurnOptions * self)728 brasero_burn_options_setup_audio (BraseroBurnOptions *self)
729 {
730 	BraseroBurnOptionsPrivate *priv;
731 
732 	priv = BRASERO_BURN_OPTIONS_PRIVATE (self);
733 
734 	brasero_burn_options_reset (self);
735 
736 	priv->has_audio = TRUE;
737 	gtk_window_set_title (GTK_WINDOW (self), _("Disc Burning Setup"));
738 	brasero_burn_options_set_type_shown (BRASERO_BURN_OPTIONS (self),
739 					     BRASERO_MEDIA_TYPE_WRITABLE|
740 					     BRASERO_MEDIA_TYPE_FILE);
741 }
742 
743 static void
brasero_burn_options_setup_video(BraseroBurnOptions * self)744 brasero_burn_options_setup_video (BraseroBurnOptions *self)
745 {
746 	gchar *title;
747 	GtkWidget *options;
748 	BraseroBurnOptionsPrivate *priv;
749 
750 	priv = BRASERO_BURN_OPTIONS_PRIVATE (self);
751 
752 	brasero_burn_options_reset (self);
753 
754 	priv->has_video = TRUE;
755 	gtk_window_set_title (GTK_WINDOW (self), _("Disc Burning Setup"));
756 	brasero_burn_options_set_type_shown (BRASERO_BURN_OPTIONS (self),
757 					     BRASERO_MEDIA_TYPE_WRITABLE|
758 					     BRASERO_MEDIA_TYPE_FILE);
759 
760 	/* create the options box */
761 	options = brasero_video_options_new (BRASERO_BURN_SESSION (priv->session));
762 	gtk_widget_show (options);
763 
764 	title = g_strdup_printf ("<b>%s</b>", _("Video Options"));
765 	options = brasero_utils_pack_properties (title,
766 	                                           options,
767 	                                           NULL);
768 	g_free (title);
769 
770 	gtk_widget_show (options);
771 	brasero_burn_options_add_options (self, options);
772 }
773 
774 static BraseroBurnResult
brasero_status_dialog_uri_has_image(BraseroTrackDataCfg * track,const gchar * uri,BraseroBurnOptions * self)775 brasero_status_dialog_uri_has_image (BraseroTrackDataCfg *track,
776 				     const gchar *uri,
777 				     BraseroBurnOptions *self)
778 {
779 	gint answer;
780 	gchar *name;
781 	GtkWidget *button;
782 	GtkWidget *dialog;
783 	gboolean was_visible = FALSE;
784 	gboolean was_not_ready = FALSE;
785 	BraseroTrackImageCfg *track_img;
786 	BraseroBurnOptionsPrivate *priv;
787 
788 	priv = BRASERO_BURN_OPTIONS_PRIVATE (self);
789 	dialog = gtk_message_dialog_new (GTK_WINDOW (self),
790 					 GTK_DIALOG_MODAL |
791 					 GTK_DIALOG_DESTROY_WITH_PARENT,
792 					 GTK_MESSAGE_QUESTION,
793 					 GTK_BUTTONS_NONE,
794 					 "%s",
795 					 _("Do you want to create a disc from the contents of the image or with the image file inside?"));
796 
797 	gtk_window_set_title (GTK_WINDOW (dialog), "");
798 	gtk_window_set_icon_name (GTK_WINDOW (dialog),
799 	                          gtk_window_get_icon_name (GTK_WINDOW (self)));
800 
801 	name = brasero_utils_get_uri_name (uri);
802 	gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
803 			/* Translators: %s is the name of the image */
804 			_("There is only one selected file (\"%s\"). "
805 			  "It is the image of a disc and its contents can be burned."),
806 			name);
807 	g_free (name);
808 
809 	gtk_dialog_add_button (GTK_DIALOG (dialog), _("Burn as _File"), GTK_RESPONSE_NO);
810 
811 	button = brasero_utils_make_button (_("Burn _Contents…"),
812 	                                    NULL,
813 	                                    "media-optical-burn",
814 	                                    GTK_ICON_SIZE_BUTTON);
815 	gtk_widget_show (button);
816 	gtk_dialog_add_action_widget (GTK_DIALOG (dialog),
817 				      button,
818 				      GTK_RESPONSE_YES);
819 
820 	if (!priv->not_ready_id && priv->status_dialog) {
821 		was_visible = TRUE;
822 		gtk_widget_hide (GTK_WIDGET (priv->status_dialog));
823 	}
824 	else if (priv->not_ready_id) {
825 		g_source_remove (priv->not_ready_id);
826 		priv->not_ready_id = 0;
827 		was_not_ready = TRUE;
828 	}
829 
830 	gtk_widget_show_all (dialog);
831 	answer = gtk_dialog_run (GTK_DIALOG (dialog));
832 	gtk_widget_destroy (dialog);
833 
834 	if (answer != GTK_RESPONSE_YES) {
835 		if (was_not_ready)
836 			priv->not_ready_id = g_timeout_add_seconds (1,
837 								    brasero_burn_options_not_ready_dialog_show_cb,
838 								    self);
839 		if (was_visible)
840 			gtk_widget_show (GTK_WIDGET (priv->status_dialog));
841 
842 		return BRASERO_BURN_OK;
843 	}
844 
845 	/* Setup a new track and add it to session */
846 	track_img = brasero_track_image_cfg_new ();
847 	brasero_track_image_cfg_set_source (track_img, uri);
848 	brasero_burn_session_add_track (BRASERO_BURN_SESSION (priv->session),
849 					BRASERO_TRACK (track_img),
850 					NULL);
851 
852 	return BRASERO_BURN_CANCEL;
853 }
854 
855 static void
brasero_burn_options_setup_data(BraseroBurnOptions * self)856 brasero_burn_options_setup_data (BraseroBurnOptions *self)
857 {
858 	GSList *tracks;
859 	BraseroBurnOptionsPrivate *priv;
860 
861 	priv = BRASERO_BURN_OPTIONS_PRIVATE (self);
862 
863 	brasero_burn_options_reset (self);
864 
865 	/* NOTE: we don't need to keep a record of the signal as the track will
866 	 * be destroyed if the user agrees to burn the image directly */
867 	tracks = brasero_burn_session_get_tracks (BRASERO_BURN_SESSION (priv->session));
868 	if (BRASERO_IS_TRACK_DATA_CFG (tracks->data))
869 		g_signal_connect (tracks->data,
870 				  "image-uri",
871 				  G_CALLBACK (brasero_status_dialog_uri_has_image),
872 				  self);
873 
874 	priv->has_data = TRUE;
875 	gtk_window_set_title (GTK_WINDOW (self), _("Disc Burning Setup"));
876 	brasero_burn_options_set_type_shown (BRASERO_BURN_OPTIONS (self),
877 					     BRASERO_MEDIA_TYPE_WRITABLE|
878 					     BRASERO_MEDIA_TYPE_FILE);
879 }
880 
881 static void
brasero_burn_options_setup_image(BraseroBurnOptions * self)882 brasero_burn_options_setup_image (BraseroBurnOptions *self)
883 {
884 	gchar *string;
885 	GtkWidget *file;
886 	BraseroBurnOptionsPrivate *priv;
887 
888 	priv = BRASERO_BURN_OPTIONS_PRIVATE (self);
889 
890 	brasero_burn_options_reset (self);
891 
892 	priv->has_image = TRUE;
893 	gtk_window_set_title (GTK_WINDOW (self), _("Image Burning Setup"));
894 	brasero_burn_options_set_type_shown (self, BRASERO_MEDIA_TYPE_WRITABLE);
895 
896 	/* Image properties */
897 	file = brasero_src_image_new (BRASERO_BURN_SESSION (priv->session));
898 	gtk_widget_show (file);
899 
900 	/* pack everything */
901 	string = g_strdup_printf ("<b>%s</b>", _("Select a disc image to write"));
902 	brasero_burn_options_add_source (self,
903 					 string,
904 					 file,
905 					 NULL);
906 	g_free (string);
907 }
908 
909 static void
brasero_burn_options_setup_disc(BraseroBurnOptions * self)910 brasero_burn_options_setup_disc (BraseroBurnOptions *self)
911 {
912 	gchar *title_str;
913 	GtkWidget *source;
914 	BraseroBurnOptionsPrivate *priv;
915 
916 	priv = BRASERO_BURN_OPTIONS_PRIVATE (self);
917 
918 	brasero_burn_options_reset (self);
919 
920 	priv->has_disc = TRUE;
921 	gtk_window_set_title (GTK_WINDOW (self), _("Copy CD/DVD"));
922 
923 	/* take care of source media */
924 	source = brasero_src_selection_new (BRASERO_BURN_SESSION (priv->session));
925 	gtk_widget_show (source);
926 
927 	title_str = g_strdup_printf ("<b>%s</b>", _("Select disc to copy"));
928 	brasero_burn_options_add_source (self,
929 					 title_str,
930 					 source,
931 					 NULL);
932 	g_free (title_str);
933 
934 	/* only show media with something to be read on them */
935 	brasero_medium_selection_show_media_type (BRASERO_MEDIUM_SELECTION (source),
936 						  BRASERO_MEDIA_TYPE_AUDIO|
937 						  BRASERO_MEDIA_TYPE_DATA);
938 
939 	/* This is a special case. When we're copying, someone may want to read
940 	 * and burn to the same drive so provided that the drive is a burner
941 	 * then show its contents. */
942 	brasero_burn_options_set_type_shown (self,
943 					     BRASERO_MEDIA_TYPE_ANY_IN_BURNER|
944 					     BRASERO_MEDIA_TYPE_FILE);
945 }
946 
947 static void
brasero_burn_options_setup(BraseroBurnOptions * self)948 brasero_burn_options_setup (BraseroBurnOptions *self)
949 {
950 	BraseroBurnOptionsPrivate *priv;
951 	BraseroTrackType *type;
952 
953 	priv = BRASERO_BURN_OPTIONS_PRIVATE (self);
954 
955 	/* add the new widgets */
956 	type = brasero_track_type_new ();
957 	brasero_burn_session_get_input_type (BRASERO_BURN_SESSION (priv->session), type);
958 	if (brasero_track_type_get_has_medium (type)) {
959 		if (!priv->has_disc)
960 			brasero_burn_options_setup_disc (self);
961 	}
962 	else if (brasero_track_type_get_has_image (type)) {
963 		if (!priv->has_image)
964 			brasero_burn_options_setup_image (self);
965 	}
966 	else if (brasero_track_type_get_has_data (type)) {
967 		if (!priv->has_data)
968 			brasero_burn_options_setup_data (self);
969 	}
970 	else if (brasero_track_type_get_has_stream (type)) {
971 		if (BRASERO_STREAM_FORMAT_HAS_VIDEO (brasero_track_type_get_stream_format (type))) {
972 			if (!priv->has_video)
973 				brasero_burn_options_setup_video (self);
974 		}
975 		else if (!priv->has_audio)
976 			brasero_burn_options_setup_audio (self);
977 	}
978 	brasero_track_type_free (type);
979 
980 	brasero_burn_options_setup_buttons (self);
981 }
982 
983 static void
brasero_burn_options_track_added(BraseroBurnSession * session,BraseroTrack * track,BraseroBurnOptions * dialog)984 brasero_burn_options_track_added (BraseroBurnSession *session,
985 				  BraseroTrack *track,
986 				  BraseroBurnOptions *dialog)
987 {
988 	brasero_burn_options_setup (dialog);
989 }
990 
991 static void
brasero_burn_options_track_removed(BraseroBurnSession * session,BraseroTrack * track,guint former_position,BraseroBurnOptions * dialog)992 brasero_burn_options_track_removed (BraseroBurnSession *session,
993 				    BraseroTrack *track,
994 				    guint former_position,
995 				    BraseroBurnOptions *dialog)
996 {
997 	brasero_burn_options_setup (dialog);
998 }
999 
1000 static void
brasero_burn_options_track_changed(BraseroBurnSession * session,BraseroTrack * track,BraseroBurnOptions * dialog)1001 brasero_burn_options_track_changed (BraseroBurnSession *session,
1002                                     BraseroTrack *track,
1003                                     BraseroBurnOptions *dialog)
1004 {
1005 	brasero_burn_options_setup (dialog);
1006 }
1007 
1008 static void
brasero_burn_options_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)1009 brasero_burn_options_set_property (GObject *object,
1010 				   guint prop_id,
1011 				   const GValue *value,
1012 				   GParamSpec *pspec)
1013 {
1014 	BraseroBurnOptionsPrivate *priv;
1015 
1016 	g_return_if_fail (BRASERO_IS_BURN_OPTIONS (object));
1017 
1018 	priv = BRASERO_BURN_OPTIONS_PRIVATE (object);
1019 
1020 	switch (prop_id)
1021 	{
1022 	case PROP_SESSION: /* Readable and only writable at creation time */
1023 		priv->session = g_object_ref (g_value_get_object (value));
1024 
1025 		g_object_notify (object, "session");
1026 
1027 		g_signal_connect (priv->session,
1028 				  "track-added",
1029 				  G_CALLBACK (brasero_burn_options_track_added),
1030 				  object);
1031 		g_signal_connect (priv->session,
1032 				  "track-removed",
1033 				  G_CALLBACK (brasero_burn_options_track_removed),
1034 				  object);
1035 		g_signal_connect (priv->session,
1036 				  "track-changed",
1037 				  G_CALLBACK (brasero_burn_options_track_changed),
1038 				  object);
1039 		brasero_burn_options_build_contents (BRASERO_BURN_OPTIONS (object));
1040 		brasero_burn_options_setup (BRASERO_BURN_OPTIONS (object));
1041 
1042 		break;
1043 	default:
1044 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1045 		break;
1046 	}
1047 }
1048 
1049 static void
brasero_burn_options_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)1050 brasero_burn_options_get_property (GObject *object,
1051 				   guint prop_id,
1052 				   GValue *value,
1053 				   GParamSpec *pspec)
1054 {
1055 	BraseroBurnOptionsPrivate *priv;
1056 
1057 	g_return_if_fail (BRASERO_IS_BURN_OPTIONS (object));
1058 
1059 	priv = BRASERO_BURN_OPTIONS_PRIVATE (object);
1060 
1061 	switch (prop_id)
1062 	{
1063 	case PROP_SESSION:
1064 		g_value_set_object (value, priv->session);
1065 		g_object_ref (priv->session);
1066 		break;
1067 	default:
1068 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1069 		break;
1070 	}
1071 }
1072 
1073 static void
brasero_burn_options_finalize(GObject * object)1074 brasero_burn_options_finalize (GObject *object)
1075 {
1076 	BraseroBurnOptionsPrivate *priv;
1077 
1078 	priv = BRASERO_BURN_OPTIONS_PRIVATE (object);
1079 
1080 	if (priv->cancel) {
1081 		g_cancellable_cancel (priv->cancel);
1082 		priv->cancel = NULL;
1083 	}
1084 
1085 	if (priv->not_ready_id) {
1086 		g_source_remove (priv->not_ready_id);
1087 		priv->not_ready_id = 0;
1088 	}
1089 
1090 	if (priv->status_dialog) {
1091 		gtk_widget_destroy (priv->status_dialog);
1092 		priv->status_dialog = NULL;
1093 	}
1094 
1095 	if (priv->session) {
1096 		g_signal_handlers_disconnect_by_func (priv->session,
1097 						      brasero_burn_options_track_added,
1098 						      object);
1099 		g_signal_handlers_disconnect_by_func (priv->session,
1100 						      brasero_burn_options_track_removed,
1101 						      object);
1102 		g_signal_handlers_disconnect_by_func (priv->session,
1103 						      brasero_burn_options_track_changed,
1104 						      object);
1105 		g_signal_handlers_disconnect_by_func (priv->session,
1106 						      brasero_burn_options_valid_cb,
1107 						      object);
1108 
1109 		g_object_unref (priv->session);
1110 		priv->session = NULL;
1111 	}
1112 
1113 	if (priv->size_group) {
1114 		g_object_unref (priv->size_group);
1115 		priv->size_group = NULL;
1116 	}
1117 
1118 	G_OBJECT_CLASS (brasero_burn_options_parent_class)->finalize (object);
1119 }
1120 
1121 static BraseroBurnResult
brasero_burn_options_install_missing(BraseroPluginErrorType type,const gchar * detail,gpointer user_data)1122 brasero_burn_options_install_missing (BraseroPluginErrorType type,
1123                                       const gchar *detail,
1124                                       gpointer user_data)
1125 {
1126 	BraseroBurnOptionsPrivate *priv = BRASERO_BURN_OPTIONS_PRIVATE (user_data);
1127 	GCancellable *cancel;
1128 	BraseroPK *package;
1129 	gboolean res;
1130 	int xid = 0;
1131 
1132 	/* Get the xid */
1133 	xid = gdk_x11_window_get_xid (gtk_widget_get_window (GTK_WIDGET (user_data)));
1134 
1135 	package = brasero_pk_new ();
1136 	cancel = g_cancellable_new ();
1137 	priv->cancel = cancel;
1138 	switch (type) {
1139 		case BRASERO_PLUGIN_ERROR_MISSING_APP:
1140 			res = brasero_pk_install_missing_app (package, detail, xid, cancel);
1141 			break;
1142 
1143 		case BRASERO_PLUGIN_ERROR_MISSING_LIBRARY:
1144 			res = brasero_pk_install_missing_library (package, detail, xid, cancel);
1145 			break;
1146 
1147 		case BRASERO_PLUGIN_ERROR_MISSING_GSTREAMER_PLUGIN:
1148 			res = brasero_pk_install_gstreamer_plugin (package, detail, xid, cancel);
1149 			break;
1150 
1151 		default:
1152 			res = FALSE;
1153 			break;
1154 	}
1155 
1156 	if (package) {
1157 		g_object_unref (package);
1158 		package = NULL;
1159 	}
1160 
1161 	if (g_cancellable_is_cancelled (cancel)) {
1162 		g_object_unref (cancel);
1163 		return BRASERO_BURN_CANCEL;
1164 	}
1165 
1166 	priv->cancel = NULL;
1167 	g_object_unref (cancel);
1168 
1169 	if (!res)
1170 		return BRASERO_BURN_ERR;
1171 
1172 	return BRASERO_BURN_RETRY;
1173 }
1174 
1175 static BraseroBurnResult
brasero_burn_options_list_missing(BraseroPluginErrorType type,const gchar * detail,gpointer user_data)1176 brasero_burn_options_list_missing (BraseroPluginErrorType type,
1177                                    const gchar *detail,
1178                                    gpointer user_data)
1179 {
1180 	GString *string = user_data;
1181 
1182 	if (type == BRASERO_PLUGIN_ERROR_MISSING_APP ||
1183 	    type == BRASERO_PLUGIN_ERROR_SYMBOLIC_LINK_APP ||
1184 	    type == BRASERO_PLUGIN_ERROR_WRONG_APP_VERSION) {
1185 		g_string_append_c (string, '\n');
1186 		/* Translators: %s is the name of a missing application */
1187 		g_string_append_printf (string, _("%s (application)"), detail);
1188 	}
1189 	else if (type == BRASERO_PLUGIN_ERROR_MISSING_LIBRARY ||
1190 	         type == BRASERO_PLUGIN_ERROR_LIBRARY_VERSION) {
1191 		g_string_append_c (string, '\n');
1192 		/* Translators: %s is the name of a missing library */
1193 		g_string_append_printf (string, _("%s (library)"), detail);
1194 	}
1195 	else if (type == BRASERO_PLUGIN_ERROR_MISSING_GSTREAMER_PLUGIN) {
1196 		g_string_append_c (string, '\n');
1197 		/* Translators: %s is the name of a missing GStreamer plugin */
1198 		g_string_append_printf (string, _("%s (GStreamer plugin)"), detail);
1199 	}
1200 
1201 	return BRASERO_BURN_OK;
1202 }
1203 
1204 static void
brasero_burn_options_response(GtkDialog * dialog,GtkResponseType response)1205 brasero_burn_options_response (GtkDialog *dialog,
1206                                GtkResponseType response)
1207 {
1208 	BraseroBurnOptionsPrivate *priv;
1209 	BraseroBurnResult result;
1210 	GString *string;
1211 
1212 	if (response != GTK_RESPONSE_OK)
1213 		return;
1214 
1215 	priv = BRASERO_BURN_OPTIONS_PRIVATE (dialog);
1216 	gtk_widget_set_sensitive (GTK_WIDGET (dialog), FALSE);
1217 
1218 	result = brasero_session_foreach_plugin_error (BRASERO_BURN_SESSION (priv->session),
1219 	                                               brasero_burn_options_install_missing,
1220 	                                               dialog);
1221 	if (result == BRASERO_BURN_CANCEL)
1222 		return;
1223 
1224 	gtk_widget_set_sensitive (GTK_WIDGET (dialog), TRUE);
1225 
1226 	if (result == BRASERO_BURN_OK)
1227 		return;
1228 
1229 	string = g_string_new (_("Please install the following manually and try again:"));
1230 	brasero_session_foreach_plugin_error (BRASERO_BURN_SESSION (priv->session),
1231 	                                      brasero_burn_options_list_missing,
1232 	                                      string);
1233 
1234 	brasero_utils_message_dialog (GTK_WIDGET (dialog),
1235 	                              _("All required applications and libraries are not installed."),
1236 	                              string->str,
1237 	                              GTK_MESSAGE_ERROR);
1238 	g_string_free (string, TRUE);
1239 
1240 	/* Cancel the rest */
1241 	gtk_dialog_response (dialog, GTK_RESPONSE_CANCEL);
1242 }
1243 
1244 static void
brasero_burn_options_class_init(BraseroBurnOptionsClass * klass)1245 brasero_burn_options_class_init (BraseroBurnOptionsClass *klass)
1246 {
1247 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
1248 	GtkDialogClass *gtk_dialog_class = GTK_DIALOG_CLASS (klass);
1249 
1250 	g_type_class_add_private (klass, sizeof (BraseroBurnOptionsPrivate));
1251 
1252 	object_class->finalize = brasero_burn_options_finalize;
1253 	object_class->set_property = brasero_burn_options_set_property;
1254 	object_class->get_property = brasero_burn_options_get_property;
1255 
1256 	gtk_dialog_class->response = brasero_burn_options_response;
1257 
1258 	g_object_class_install_property (object_class,
1259 					 PROP_SESSION,
1260 					 g_param_spec_object ("session",
1261 							      "The session",
1262 							      "The session to work with",
1263 							      BRASERO_TYPE_BURN_SESSION,
1264 							      G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
1265 }
1266 
1267 /**
1268  * brasero_burn_options_new:
1269  * @session: a #BraseroSessionCfg object
1270  *
1271  *  Creates a new #BraseroBurnOptions object.
1272  *
1273  * Return value: a #GtkWidget object.
1274  **/
1275 
1276 GtkWidget *
brasero_burn_options_new(BraseroSessionCfg * session)1277 brasero_burn_options_new (BraseroSessionCfg *session)
1278 {
1279 	return g_object_new (BRASERO_TYPE_BURN_OPTIONS, "session", session, NULL);
1280 }
1281