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 <string.h>
36 
37 #include <glib.h>
38 #include <glib-object.h>
39 #include <glib/gi18n-lib.h>
40 
41 #include <gio/gio.h>
42 
43 #include <gtk/gtk.h>
44 
45 #include "brasero-medium.h"
46 #include "brasero-drive.h"
47 
48 #include "brasero-misc.h"
49 
50 #include "burn-basics.h"
51 #include "burn-debug.h"
52 #include "brasero-drive-properties.h"
53 
54 typedef struct _BraseroDrivePropertiesPrivate BraseroDrivePropertiesPrivate;
55 struct _BraseroDrivePropertiesPrivate
56 {
57 	BraseroSessionCfg *session;
58 	gulong valid_sig;
59 	gulong output_sig;
60 
61 	GtkWidget *speed;
62 	GtkWidget *dummy;
63 	GtkWidget *multi;
64 	GtkWidget *burnproof;
65 	GtkWidget *notmp;
66 
67 	GtkWidget *tmpdir;
68 };
69 
70 #define BRASERO_DRIVE_PROPERTIES_PRIVATE(o)  (G_TYPE_INSTANCE_GET_PRIVATE ((o), BRASERO_TYPE_DRIVE_PROPERTIES, BraseroDrivePropertiesPrivate))
71 
72 enum {
73 	TEXT_COL,
74 	RATE_COL,
75 	COL_NUM
76 };
77 
78 enum {
79 	PROP_0,
80 	PROP_SESSION
81 };
82 
83 G_DEFINE_TYPE (BraseroDriveProperties, brasero_drive_properties, GTK_TYPE_ALIGNMENT);
84 
85 static void
brasero_drive_properties_no_tmp_toggled(GtkToggleButton * button,BraseroDriveProperties * self)86 brasero_drive_properties_no_tmp_toggled (GtkToggleButton *button,
87 					 BraseroDriveProperties *self)
88 {
89 	BraseroDrivePropertiesPrivate *priv;
90 
91 	priv = BRASERO_DRIVE_PROPERTIES_PRIVATE (self);
92 
93 	/* retrieve the flags */
94 	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->notmp)))
95 		brasero_session_cfg_add_flags (priv->session,
96 					       BRASERO_BURN_FLAG_NO_TMP_FILES);
97 	else
98 		brasero_session_cfg_remove_flags (priv->session,
99 						  BRASERO_BURN_FLAG_NO_TMP_FILES);
100 }
101 
102 static void
brasero_drive_properties_dummy_toggled(GtkToggleButton * button,BraseroDriveProperties * self)103 brasero_drive_properties_dummy_toggled (GtkToggleButton *button,
104 					BraseroDriveProperties *self)
105 {
106 	BraseroDrivePropertiesPrivate *priv;
107 
108 	priv = BRASERO_DRIVE_PROPERTIES_PRIVATE (self);
109 
110 	/* retrieve the flags */
111 	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->dummy)))
112 		brasero_session_cfg_add_flags (priv->session,
113 					       BRASERO_BURN_FLAG_DUMMY);
114 	else
115 		brasero_session_cfg_remove_flags (priv->session,
116 						  BRASERO_BURN_FLAG_DUMMY);
117 }
118 
119 static void
brasero_drive_properties_burnproof_toggled(GtkToggleButton * button,BraseroDriveProperties * self)120 brasero_drive_properties_burnproof_toggled (GtkToggleButton *button,
121 					    BraseroDriveProperties *self)
122 {
123 	BraseroDrivePropertiesPrivate *priv;
124 
125 	priv = BRASERO_DRIVE_PROPERTIES_PRIVATE (self);
126 
127 	/* retrieve the flags */
128 	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->burnproof)))
129 		brasero_session_cfg_add_flags (priv->session,
130 					       BRASERO_BURN_FLAG_BURNPROOF);
131 	else
132 		brasero_session_cfg_remove_flags (priv->session,
133 						  BRASERO_BURN_FLAG_BURNPROOF);
134 }
135 
136 static void
brasero_drive_properties_multi_toggled(GtkToggleButton * button,BraseroDriveProperties * self)137 brasero_drive_properties_multi_toggled (GtkToggleButton *button,
138 					BraseroDriveProperties *self)
139 {
140 	BraseroDrivePropertiesPrivate *priv;
141 
142 	priv = BRASERO_DRIVE_PROPERTIES_PRIVATE (self);
143 
144 	/* retrieve the flags */
145 	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->multi)))
146 		brasero_session_cfg_add_flags (priv->session,
147 					       BRASERO_BURN_FLAG_MULTI);
148 	else
149 		brasero_session_cfg_remove_flags (priv->session,
150 						  BRASERO_BURN_FLAG_MULTI);
151 }
152 
153 static void
brasero_drive_properties_set_tmpdir_info(BraseroDriveProperties * self,const gchar * path)154 brasero_drive_properties_set_tmpdir_info (BraseroDriveProperties *self,
155 					  const gchar *path)
156 {
157 	GFile *file;
158 	gchar *string;
159 	GFileInfo *info;
160 	gchar *string_size;
161 	guint64 vol_size = 0;
162 	BraseroDrivePropertiesPrivate *priv;
163 
164 	priv = BRASERO_DRIVE_PROPERTIES_PRIVATE (self);
165 
166 	/* get the volume free space */
167 	file = g_file_new_for_commandline_arg (path);
168 	if (!file) {
169 		BRASERO_BURN_LOG ("Impossible to retrieve size for %s", path);
170 		gtk_label_set_text (GTK_LABEL (priv->tmpdir), path);
171 		return;
172 	}
173 
174 	info = g_file_query_filesystem_info (file,
175 					     G_FILE_ATTRIBUTE_FILESYSTEM_FREE,
176 					     NULL,
177 					     NULL);
178 	g_object_unref (file);
179 
180 	if (!info) {
181 		BRASERO_BURN_LOG ("Impossible to retrieve size for %s", path);
182 		gtk_label_set_text (GTK_LABEL (priv->tmpdir), path);
183 		return;
184 	}
185 
186 	vol_size = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE);
187 	g_object_unref (info);
188 
189 	string_size = g_format_size (vol_size);
190 	/* Translators: the first %s is the path of the directory where brasero
191 	 * will store its temporary files; the second one is the size available */
192 	string = g_strdup_printf (_("%s: %s free"), path, string_size);
193 	g_free (string_size);
194 
195 	gtk_label_set_text (GTK_LABEL (priv->tmpdir), string);
196 	g_free (string);
197 }
198 
199 static gboolean
brasero_drive_properties_check_tmpdir(BraseroDriveProperties * self,const gchar * path)200 brasero_drive_properties_check_tmpdir (BraseroDriveProperties *self,
201 				       const gchar *path)
202 {
203 	GFile *file;
204 	GFileInfo *info;
205 	GError *error = NULL;
206 	const gchar *filesystem;
207 
208 	file = g_file_new_for_commandline_arg (path);
209 	if (!file)
210 		return TRUE;
211 
212 	info = g_file_query_info (file,
213 				  G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE,
214 				  G_FILE_QUERY_INFO_NONE,
215 				  NULL,
216 				  &error);
217 	if (error) {
218 		gint answer;
219 		gchar *string;
220 		GtkWidget *dialog;
221 		GtkWidget *toplevel;
222 
223 		if (error)
224 			return TRUE;
225 
226 		/* Tell the user what went wrong */
227 		toplevel = gtk_widget_get_toplevel (GTK_WIDGET (self));
228 		dialog = gtk_message_dialog_new (GTK_WINDOW (toplevel),
229 						 GTK_DIALOG_DESTROY_WITH_PARENT |
230 						 GTK_DIALOG_MODAL,
231 						 GTK_MESSAGE_WARNING,
232 						 GTK_BUTTONS_NONE,
233 						 _("Do you really want to choose this location?"));
234 
235 		gtk_window_set_icon_name (GTK_WINDOW (dialog),
236 					  gtk_window_get_icon_name (GTK_WINDOW (toplevel)));
237 
238 		string = g_strdup_printf ("%s.", error->message);
239 		gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", string);
240 		g_error_free (error);
241 		g_free (string);
242 
243 		gtk_dialog_add_buttons (GTK_DIALOG (dialog),
244 					_("_Keep Current Location"), GTK_RESPONSE_CANCEL,
245 					_("_Change Location"), GTK_RESPONSE_OK,
246 					NULL);
247 
248 		gtk_widget_show_all (dialog);
249 		answer = gtk_dialog_run (GTK_DIALOG (dialog));
250 		gtk_widget_destroy (dialog);
251 
252 		g_object_unref (info);
253 		g_object_unref (file);
254 		if (answer != GTK_RESPONSE_OK)
255 			return TRUE;
256 
257 		return FALSE;
258 	}
259 
260 	if (!g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE)) {
261 		gint answer;
262 		gchar *string;
263 		GtkWidget *dialog;
264 		GtkWidget *toplevel;
265 
266 		toplevel = gtk_widget_get_toplevel (GTK_WIDGET (self));
267 		dialog = gtk_message_dialog_new (GTK_WINDOW (toplevel),
268 						 GTK_DIALOG_DESTROY_WITH_PARENT |
269 						 GTK_DIALOG_MODAL,
270 						 GTK_MESSAGE_WARNING,
271 						 GTK_BUTTONS_NONE,
272 						 _("Do you really want to choose this location?"));
273 
274 		gtk_window_set_icon_name (GTK_WINDOW (dialog),
275 					  gtk_window_get_icon_name (GTK_WINDOW (toplevel)));
276 
277 		string = g_strdup_printf ("%s.", _("You do not have the required permission to write at this location"));
278 		gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", string);
279 		g_free (string);
280 
281 		gtk_dialog_add_buttons (GTK_DIALOG (dialog),
282 					_("_Keep Current Location"), GTK_RESPONSE_CANCEL,
283 					_("_Change Location"), GTK_RESPONSE_OK,
284 					NULL);
285 
286 		gtk_widget_show_all (dialog);
287 		answer = gtk_dialog_run (GTK_DIALOG (dialog));
288 		gtk_widget_destroy (dialog);
289 
290 		g_object_unref (info);
291 		g_object_unref (file);
292 		if (answer != GTK_RESPONSE_OK)
293 			return TRUE;
294 
295 		return FALSE;
296 	}
297 
298 	g_object_unref (info);
299 	info = g_file_query_filesystem_info (file,
300 					     G_FILE_ATTRIBUTE_FILESYSTEM_TYPE,
301 					     NULL,
302 					     &error);
303 	g_object_unref (file);
304 
305 	/* NOTE/FIXME: also check, probably best at start or in a special dialog
306 	 * whether quotas or any other limitation enforced on the system may not
307 	 * get in out way. Think getrlimit (). */
308 
309 	/* check the filesystem type: the problem here is that some
310 	 * filesystems have a maximum file size limit of 4 GiB and more than
311 	 * often we need a temporary file size of 4 GiB or more. */
312 	filesystem = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_FILESYSTEM_TYPE);
313 	if (!g_strcmp0 (filesystem, "msdos")) {
314 		gint answer;
315 		GtkWidget *dialog;
316 		GtkWidget *toplevel;
317 
318 		toplevel = gtk_widget_get_toplevel (GTK_WIDGET (self));
319 		dialog = gtk_message_dialog_new (GTK_WINDOW (toplevel),
320 						 GTK_DIALOG_DESTROY_WITH_PARENT |
321 						 GTK_DIALOG_MODAL,
322 						 GTK_MESSAGE_WARNING,
323 						 GTK_BUTTONS_NONE,
324 						 _("Do you really want to choose this location?"));
325 
326 		gtk_window_set_icon_name (GTK_WINDOW (dialog),
327 					  gtk_window_get_icon_name (GTK_WINDOW (toplevel)));
328 
329 		gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
330 							  _("The filesystem on this volume does not support large files (size over 2 GiB)."
331 							    "\nThis can be a problem when writing DVDs or large images."));
332 
333 		gtk_dialog_add_buttons (GTK_DIALOG (dialog),
334 					_("_Keep Current Location"), GTK_RESPONSE_CANCEL,
335 					_("_Change Location"), GTK_RESPONSE_OK,
336 					NULL);
337 
338 		gtk_widget_show_all (dialog);
339 		answer = gtk_dialog_run (GTK_DIALOG (dialog));
340 		gtk_widget_destroy (dialog);
341 
342 		g_object_unref (info);
343 		if (answer != GTK_RESPONSE_OK)
344 			return TRUE;
345 	}
346 	else if (info)
347 		g_object_unref (info);
348 
349 	return FALSE;
350 }
351 
352 static void
brasero_drive_properties_tmpdir_clicked(GtkButton * button,BraseroDriveProperties * self)353 brasero_drive_properties_tmpdir_clicked (GtkButton *button,
354 					 BraseroDriveProperties *self)
355 {
356 	GtkWidget *parent;
357 	const gchar *path;
358 	GtkWidget *chooser;
359 	GtkResponseType res;
360 	const gchar *new_path;
361 	BraseroDrivePropertiesPrivate *priv;
362 
363 	priv = BRASERO_DRIVE_PROPERTIES_PRIVATE (self);
364 
365 	parent = gtk_widget_get_toplevel (GTK_WIDGET (button));
366 	chooser = gtk_file_chooser_dialog_new (_("Location for Temporary Files"),
367 					       GTK_WINDOW (parent),
368 					       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
369 					       GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
370 					       GTK_STOCK_OK, GTK_RESPONSE_OK,
371 					       NULL);
372 
373 	path = brasero_burn_session_get_tmpdir (BRASERO_BURN_SESSION (priv->session));
374 	gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (chooser), path);
375 	res = gtk_dialog_run (GTK_DIALOG (chooser));
376 	if (res != GTK_RESPONSE_OK) {
377 		gtk_widget_destroy (chooser);
378 		return;
379 	}
380 
381 	new_path = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (chooser));
382 	if (!new_path || !strcmp (new_path, path)) {
383 		gtk_widget_destroy (chooser);
384 		return;
385 	}
386 
387 	if (!brasero_drive_properties_check_tmpdir (self, new_path)) {
388 		brasero_burn_session_set_tmpdir (BRASERO_BURN_SESSION (priv->session), new_path);
389 		brasero_drive_properties_set_tmpdir_info (self, new_path);
390 	}
391 
392 	gtk_widget_destroy (chooser);
393 }
394 
395 static void
brasero_drive_properties_set_tmpdir(BraseroDriveProperties * self,const gchar * path)396 brasero_drive_properties_set_tmpdir (BraseroDriveProperties *self,
397 				     const gchar *path)
398 {
399 	if (!path)
400 		path = g_get_tmp_dir ();
401 
402 	brasero_drive_properties_set_tmpdir_info (self, path);
403 }
404 
405 static void
406 brasero_drive_properties_set_flags (BraseroDriveProperties *self,
407 				    BraseroBurnFlag flags,
408 				    BraseroBurnFlag supported,
409 				    BraseroBurnFlag compulsory);
410 
411 static void
brasero_drive_properties_set_toggle_state(BraseroDriveProperties * self,GtkWidget * toggle,BraseroBurnFlag flag,BraseroBurnFlag flags,BraseroBurnFlag supported,BraseroBurnFlag compulsory)412 brasero_drive_properties_set_toggle_state (BraseroDriveProperties *self,
413 					   GtkWidget *toggle,
414 					   BraseroBurnFlag flag,
415 					   BraseroBurnFlag flags,
416 					   BraseroBurnFlag supported,
417 					   BraseroBurnFlag compulsory)
418 {
419 	if (!(supported & flag)) {
420 		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), FALSE);
421 		gtk_widget_set_sensitive (toggle, FALSE);
422 		gtk_widget_hide (toggle);
423 		return;
424 	}
425 
426 	gtk_widget_show (toggle);
427 	g_signal_handlers_block_by_func (toggle,
428 					 brasero_drive_properties_set_flags,
429 					 self);
430 	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), (flags & flag));
431 	g_signal_handlers_unblock_by_func (toggle,
432 					   brasero_drive_properties_set_flags,
433 					   self);
434 
435 	gtk_widget_set_sensitive (toggle, (compulsory & flag) == 0);
436 }
437 
438 static void
brasero_drive_properties_set_flags(BraseroDriveProperties * self,BraseroBurnFlag flags,BraseroBurnFlag supported,BraseroBurnFlag compulsory)439 brasero_drive_properties_set_flags (BraseroDriveProperties *self,
440 				    BraseroBurnFlag flags,
441 				    BraseroBurnFlag supported,
442 				    BraseroBurnFlag compulsory)
443 {
444 	BraseroDrivePropertiesPrivate *priv;
445 
446 	priv = BRASERO_DRIVE_PROPERTIES_PRIVATE (self);
447 
448 	flags &= BRASERO_DRIVE_PROPERTIES_FLAGS;
449 	supported &= BRASERO_DRIVE_PROPERTIES_FLAGS;
450 	compulsory &= BRASERO_DRIVE_PROPERTIES_FLAGS;
451 
452 	/* flag properties */
453 	brasero_drive_properties_set_toggle_state (self,
454 						   priv->dummy,
455 						   BRASERO_BURN_FLAG_DUMMY,
456 						   flags,
457 						   supported,
458 						   compulsory);
459 	brasero_drive_properties_set_toggle_state (self,
460 						   priv->burnproof,
461 						   BRASERO_BURN_FLAG_BURNPROOF,
462 						   flags,
463 						   supported,
464 						   compulsory);
465 	brasero_drive_properties_set_toggle_state (self,
466 						   priv->notmp,
467 						   BRASERO_BURN_FLAG_NO_TMP_FILES,
468 						   flags,
469 						   supported,
470 						   compulsory);
471 	brasero_drive_properties_set_toggle_state (self,
472 						   priv->multi,
473 						   BRASERO_BURN_FLAG_MULTI,
474 						   flags,
475 						   supported,
476 						   compulsory);
477 }
478 
479 static gint64
brasero_drive_properties_get_rate(BraseroDriveProperties * self)480 brasero_drive_properties_get_rate (BraseroDriveProperties *self)
481 {
482 	BraseroDrivePropertiesPrivate *priv;
483 	GtkTreeModel *model;
484 	GtkTreeIter iter;
485 	gint64 rate;
486 
487 	priv = BRASERO_DRIVE_PROPERTIES_PRIVATE (self);
488 
489 	model = gtk_combo_box_get_model (GTK_COMBO_BOX (priv->speed));
490 	if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (priv->speed), &iter)
491 	&&  !gtk_tree_model_get_iter_first (model, &iter))
492 		return 0;
493 
494 	gtk_tree_model_get (model, &iter,
495 			    RATE_COL, &rate,
496 			    -1);
497 	return rate;
498 }
499 
500 static void
brasero_drive_properties_rate_changed_cb(GtkComboBox * combo,BraseroDriveProperties * self)501 brasero_drive_properties_rate_changed_cb (GtkComboBox *combo,
502 					  BraseroDriveProperties *self)
503 {
504 	BraseroDrivePropertiesPrivate *priv;
505 	guint64 rate;
506 
507 	priv = BRASERO_DRIVE_PROPERTIES_PRIVATE (self);
508 
509 	rate = brasero_drive_properties_get_rate (self);
510 	if (!rate)
511 		return;
512 
513 	brasero_burn_session_set_rate (BRASERO_BURN_SESSION (priv->session), rate);
514 }
515 
516 static gchar *
brasero_drive_properties_format_disc_speed(BraseroMedia media,gint64 rate)517 brasero_drive_properties_format_disc_speed (BraseroMedia media,
518 					    gint64 rate)
519 {
520 	gchar *text;
521 
522 	if (media & BRASERO_MEDIUM_DVD)
523 		/* Translators %s.1f is the speed used to burn */
524 		text = g_strdup_printf (_("%.1f\303\227 (DVD)"),
525 					BRASERO_RATE_TO_SPEED_DVD (rate));
526 	else if (media & BRASERO_MEDIUM_CD)
527 		/* Translators %s.1f is the speed used to burn */
528 		text = g_strdup_printf (_("%.1f\303\227 (CD)"),
529 					BRASERO_RATE_TO_SPEED_CD (rate));
530 	else if (media & BRASERO_MEDIUM_BD)
531 		/* Translators %s.1f is the speed used to burn. BD = Blu Ray*/
532 		text = g_strdup_printf (_("%.1f\303\227 (BD)"),
533 					BRASERO_RATE_TO_SPEED_BD (rate));
534 	else
535 		/* Translators %s.1f is the speed used to burn for every medium
536 		 * type. BD = Blu Ray*/
537 		text = g_strdup_printf (_("%.1f\303\227 (BD) %.1f\303\227 (DVD) %.1f\303\227 (CD)"),
538 					BRASERO_RATE_TO_SPEED_BD (rate),
539 					BRASERO_RATE_TO_SPEED_DVD (rate),
540 					BRASERO_RATE_TO_SPEED_CD (rate));
541 
542 	return text;
543 }
544 
545 static void
brasero_drive_properties_set_drive(BraseroDriveProperties * self,BraseroDrive * drive,gint64 default_rate)546 brasero_drive_properties_set_drive (BraseroDriveProperties *self,
547 				    BraseroDrive *drive,
548 				    gint64 default_rate)
549 {
550 	BraseroDrivePropertiesPrivate *priv;
551 	BraseroMedium *medium;
552 	BraseroMedia media;
553 	GtkTreeModel *model;
554 	GtkTreeIter iter;
555 	guint64 *rates;
556 	gchar *text;
557 	guint i;
558 
559 	priv = BRASERO_DRIVE_PROPERTIES_PRIVATE (self);
560 
561 	/* Speed combo */
562 	medium = brasero_drive_get_medium (drive);
563 	media = brasero_medium_get_status (medium);
564 	if (media & BRASERO_MEDIUM_FILE)
565 		return;
566 
567 	rates = brasero_medium_get_write_speeds (medium);
568 	model = gtk_combo_box_get_model (GTK_COMBO_BOX (priv->speed));
569 	gtk_list_store_clear (GTK_LIST_STORE (model));
570 
571 	if (!rates) {
572 		gtk_widget_set_sensitive (priv->speed, FALSE);
573 		gtk_list_store_append (GTK_LIST_STORE (model), &iter);
574 		gtk_list_store_set (GTK_LIST_STORE (model), &iter,
575 				    TEXT_COL, _("Impossible to retrieve speeds"),
576 				    RATE_COL, 1764, /* Speed 1 */
577 				    -1);
578 		gtk_combo_box_set_active_iter (GTK_COMBO_BOX (priv->speed), &iter);
579 		return;
580 	}
581 
582 	gtk_list_store_append (GTK_LIST_STORE (model), &iter);
583 	gtk_list_store_set (GTK_LIST_STORE (model), &iter,
584 			    TEXT_COL, _("Maximum speed"),
585 			    RATE_COL, rates [0],
586 			    -1);
587 
588 	/* fill model */
589 	for (i = 0; rates [i] != 0; i ++) {
590 		text = brasero_drive_properties_format_disc_speed (media, rates [i]);
591 		gtk_list_store_append (GTK_LIST_STORE (model), &iter);
592 		gtk_list_store_set (GTK_LIST_STORE (model), &iter,
593 				    TEXT_COL, text,
594 				    RATE_COL, rates [i],
595 				    -1);
596 		g_free (text);
597 	}
598 	g_free (rates);
599 
600 	/* Set active one preferably max speed */
601 	gtk_tree_model_get_iter_first (model, &iter);
602 	do {
603 		gint64 rate;
604 
605 		gtk_tree_model_get (model, &iter,
606 				    RATE_COL, &rate,
607 				    -1);
608 
609 		/* we do this to round things and get the closest possible speed */
610 		if ((rate / 1024) == (default_rate / 1024)) {
611 			gtk_combo_box_set_active_iter (GTK_COMBO_BOX (priv->speed), &iter);
612 			break;
613 		}
614 
615 	} while (gtk_tree_model_iter_next (model, &iter));
616 
617 	/* make sure at least one is active */
618 	if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (priv->speed), &iter)) {
619 		gtk_tree_model_get_iter_first (model, &iter);
620 		gtk_combo_box_set_active_iter (GTK_COMBO_BOX (priv->speed), &iter);
621 	}
622 }
623 
624 static void
brasero_drive_properties_update(BraseroDriveProperties * self)625 brasero_drive_properties_update (BraseroDriveProperties *self)
626 {
627 	BraseroBurnFlag compulsory = BRASERO_BURN_FLAG_NONE;
628 	BraseroBurnFlag supported = BRASERO_BURN_FLAG_NONE;
629 	BraseroDrivePropertiesPrivate *priv;
630 	BraseroBurnFlag flags;
631 
632 	priv = BRASERO_DRIVE_PROPERTIES_PRIVATE (self);
633 	brasero_drive_properties_set_drive (self,
634 					    brasero_burn_session_get_burner (BRASERO_BURN_SESSION (priv->session)),
635 					    brasero_burn_session_get_rate (BRASERO_BURN_SESSION (priv->session)));
636 
637 	flags = brasero_burn_session_get_flags (BRASERO_BURN_SESSION (priv->session));
638 	brasero_burn_session_get_burn_flags (BRASERO_BURN_SESSION (priv->session),
639 					     &supported,
640 					     &compulsory);
641 	brasero_drive_properties_set_flags (self,
642 					    flags,
643 					    supported,
644 					    compulsory);
645 	brasero_drive_properties_set_tmpdir (self, brasero_burn_session_get_tmpdir (BRASERO_BURN_SESSION (priv->session)));
646 }
647 
648 static void
brasero_drive_properties_is_valid_cb(BraseroSessionCfg * session,BraseroDriveProperties * self)649 brasero_drive_properties_is_valid_cb (BraseroSessionCfg *session,
650 				      BraseroDriveProperties *self)
651 {
652 	BraseroDrivePropertiesPrivate *priv;
653 	BraseroBurnFlag compulsory;
654 	BraseroBurnFlag supported;
655 	BraseroBurnFlag flags;
656 
657 	priv = BRASERO_DRIVE_PROPERTIES_PRIVATE (self);
658 
659 	flags = brasero_burn_session_get_flags (BRASERO_BURN_SESSION (priv->session));
660 	brasero_burn_session_get_burn_flags (BRASERO_BURN_SESSION (priv->session),
661 					     &supported,
662 					     &compulsory);
663 	brasero_drive_properties_set_flags (self,
664 					    flags,
665 					    supported,
666 					    compulsory);
667 }
668 
669 static void
brasero_drive_properties_output_changed_cb(BraseroSessionCfg * session,BraseroMedium * former,BraseroDriveProperties * self)670 brasero_drive_properties_output_changed_cb (BraseroSessionCfg *session,
671 					    BraseroMedium *former,
672 					    BraseroDriveProperties *self)
673 {
674 	BraseroDrivePropertiesPrivate *priv;
675 
676 	priv = BRASERO_DRIVE_PROPERTIES_PRIVATE (self);
677 
678 	/* if the drive changed update rate but only if the drive changed that's
679 	 * why we don't do it when the is-valid signal is emitted. */
680 	brasero_drive_properties_set_drive (self,
681 					    brasero_burn_session_get_burner (BRASERO_BURN_SESSION (priv->session)),
682 					    brasero_burn_session_get_rate (BRASERO_BURN_SESSION (priv->session)));
683 }
684 
685 static void
brasero_drive_properties_init(BraseroDriveProperties * object)686 brasero_drive_properties_init (BraseroDriveProperties *object)
687 {
688 	BraseroDrivePropertiesPrivate *priv;
689 	GtkCellRenderer *renderer;
690 	GtkTreeModel *model;
691 	GtkWidget *button;
692 	GtkWidget *image;
693 	GtkWidget *label;
694 	GtkWidget *vbox;
695 	GtkWidget *box;
696 	gchar *string;
697 
698 	priv = BRASERO_DRIVE_PROPERTIES_PRIVATE (object);
699 
700 	vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
701 	gtk_widget_show (vbox);
702 	gtk_container_add (GTK_CONTAINER (object), vbox);
703 
704 	model = GTK_TREE_MODEL (gtk_list_store_new (COL_NUM,
705 						    G_TYPE_STRING,
706 						    G_TYPE_INT64));
707 
708 	priv->speed = gtk_combo_box_new_with_model (model);
709 	gtk_widget_show (priv->speed);
710 	string = g_strdup_printf ("<b>%s</b>", _("Burning speed"));
711 	gtk_box_pack_start (GTK_BOX (vbox),
712 			    brasero_utils_pack_properties (string,
713 							   priv->speed, NULL),
714 			    FALSE, FALSE, 0);
715 	g_free (string);
716 
717 	renderer = gtk_cell_renderer_text_new ();
718 	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (priv->speed), renderer, TRUE);
719 	gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (priv->speed), renderer,
720 					"text", TEXT_COL,
721 					NULL);
722 
723 	priv->dummy = gtk_check_button_new_with_mnemonic (_("_Simulate before burning"));
724 	gtk_widget_set_tooltip_text (priv->dummy, _("Brasero will simulate the burning and, if it is successful, go on with actual burning after 10 seconds"));
725 	gtk_widget_show (priv->dummy);
726 	priv->burnproof = gtk_check_button_new_with_mnemonic (_("Use burn_proof (decrease the risk of failures)"));
727 	gtk_widget_show (priv->burnproof);
728 	priv->notmp = gtk_check_button_new_with_mnemonic (_("Burn the image directly _without saving it to disc"));
729 	gtk_widget_show (priv->notmp);
730 	priv->multi = gtk_check_button_new_with_mnemonic (_("Leave the disc _open to add other files later"));
731 	gtk_widget_set_tooltip_text (priv->multi, _("Allow to add more data to the disc later"));
732 	gtk_widget_show (priv->multi);
733 
734 	g_signal_connect (priv->dummy,
735 			  "toggled",
736 			  G_CALLBACK (brasero_drive_properties_dummy_toggled),
737 			  object);
738 	g_signal_connect (priv->burnproof,
739 			  "toggled",
740 			  G_CALLBACK (brasero_drive_properties_burnproof_toggled),
741 			  object);
742 	g_signal_connect (priv->multi,
743 			  "toggled",
744 			  G_CALLBACK (brasero_drive_properties_multi_toggled),
745 			  object);
746 	g_signal_connect (priv->notmp,
747 			  "toggled",
748 			  G_CALLBACK (brasero_drive_properties_no_tmp_toggled),
749 			  object);
750 
751 	string = g_strdup_printf ("<b>%s</b>", _("Options"));
752 	gtk_box_pack_start (GTK_BOX (vbox),
753 			    brasero_utils_pack_properties (string,
754 							   priv->dummy,
755 							   priv->burnproof,
756 							   priv->multi,
757 							   priv->notmp,
758 							   NULL),
759 			    FALSE,
760 			    FALSE, 0);
761 	g_free (string);
762 
763 	label = gtk_label_new_with_mnemonic (_("Location for _Temporary Files"));
764 	gtk_widget_show (label);
765 	gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
766 	gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
767 	gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_START);
768 	gtk_widget_show (label);
769 
770 	priv->tmpdir = label;
771 
772 	image = gtk_image_new_from_icon_name ("folder", GTK_ICON_SIZE_BUTTON);
773 	gtk_widget_show (image);
774 
775 	box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
776 	gtk_widget_show (box);
777 	gtk_box_pack_start (GTK_BOX (box), image, FALSE, FALSE, 0);
778 	gtk_box_pack_start (GTK_BOX (box), label, TRUE, TRUE, 0);
779 
780 	button = gtk_button_new ();
781 	gtk_widget_show (button);
782 	gtk_container_add (GTK_CONTAINER (button), box);
783 	gtk_widget_set_tooltip_text (button, _("Set the directory where to store temporary files"));
784 
785 	box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
786 	gtk_widget_show (box);
787 
788 	string = g_strdup_printf ("<b>%s</b>", _("Temporary files"));
789 	gtk_box_pack_start (GTK_BOX (vbox),
790 			    brasero_utils_pack_properties (string,
791 							   box,
792 							   button,
793 							   NULL),
794 			    FALSE,
795 			    FALSE, 0);
796 	g_free (string);
797 	gtk_widget_show (vbox);
798 
799 	g_signal_connect (button,
800 			  "clicked",
801 			  G_CALLBACK (brasero_drive_properties_tmpdir_clicked),
802 			  object);
803 	g_signal_connect (priv->speed,
804 			  "changed",
805 			  G_CALLBACK (brasero_drive_properties_rate_changed_cb),
806 			  object);
807 }
808 
809 static void
brasero_drive_properties_finalize(GObject * object)810 brasero_drive_properties_finalize (GObject *object)
811 {
812 	BraseroDrivePropertiesPrivate *priv;
813 
814 	priv = BRASERO_DRIVE_PROPERTIES_PRIVATE (object);
815 	if (priv->valid_sig) {
816 		g_signal_handler_disconnect (priv->session, priv->valid_sig);
817 		priv->valid_sig = 0;
818 	}
819 	if (priv->output_sig) {
820 		g_signal_handler_disconnect (priv->session, priv->output_sig);
821 		priv->output_sig = 0;
822 	}
823 	if (priv->session) {
824 		g_object_unref (priv->session);
825 		priv->session = NULL;
826 	}
827 
828 	G_OBJECT_CLASS (brasero_drive_properties_parent_class)->finalize (object);
829 }
830 
831 static void
brasero_drive_properties_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)832 brasero_drive_properties_set_property (GObject *object,
833 				       guint property_id,
834 				       const GValue *value,
835 				       GParamSpec *pspec)
836 {
837 	BraseroDrivePropertiesPrivate *priv;
838 	BraseroBurnSession *session;
839 
840 	priv = BRASERO_DRIVE_PROPERTIES_PRIVATE (object);
841 
842 	switch (property_id) {
843 	case PROP_SESSION: /* Readable and only writable at creation time */
844 		/* NOTE: no need to unref a potential previous session since
845 		 * it's only set at construct time */
846 		session = g_value_get_object (value);
847 		priv->session = g_object_ref (session);
848 
849 		brasero_drive_properties_update (BRASERO_DRIVE_PROPERTIES (object));
850 		priv->valid_sig = g_signal_connect (session,
851 						    "is-valid",
852 						    G_CALLBACK (brasero_drive_properties_is_valid_cb),
853 						    object);
854 		priv->output_sig = g_signal_connect (session,
855 						     "output-changed",
856 						     G_CALLBACK (brasero_drive_properties_output_changed_cb),
857 						     object);
858 		break;
859 
860 	default:
861 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
862 	}
863 }
864 
865 static void
brasero_drive_properties_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)866 brasero_drive_properties_get_property (GObject *object,
867 				       guint property_id,
868 				       GValue *value,
869 				       GParamSpec *pspec)
870 {
871 	BraseroDrivePropertiesPrivate *priv;
872 
873 	priv = BRASERO_DRIVE_PROPERTIES_PRIVATE (object);
874 
875 	switch (property_id) {
876 	case PROP_SESSION:
877 		g_object_ref (priv->session);
878 		g_value_set_object (value, priv->session);
879 		break;
880 
881 	default:
882 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
883 	}
884 }
885 
886 static void
brasero_drive_properties_class_init(BraseroDrivePropertiesClass * klass)887 brasero_drive_properties_class_init (BraseroDrivePropertiesClass *klass)
888 {
889 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
890 
891 	g_type_class_add_private (klass, sizeof (BraseroDrivePropertiesPrivate));
892 
893 	object_class->finalize = brasero_drive_properties_finalize;
894 	object_class->set_property = brasero_drive_properties_set_property;
895 	object_class->get_property = brasero_drive_properties_get_property;
896 
897 	g_object_class_install_property (object_class,
898 					 PROP_SESSION,
899 					 g_param_spec_object ("session",
900 							      "The session",
901 							      "The session to work with",
902 							      BRASERO_TYPE_BURN_SESSION,
903 							      G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
904 }
905 
906 GtkWidget *
brasero_drive_properties_new(BraseroSessionCfg * session)907 brasero_drive_properties_new (BraseroSessionCfg *session)
908 {
909 	return g_object_new (BRASERO_TYPE_DRIVE_PROPERTIES,
910 			     "session", session,
911 			     NULL);
912 }
913