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 * Libbrasero-media 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-media authors hereby grant permission for non-GPL compatible
12 * GStreamer plugins to be used and distributed together with GStreamer
13 * and Libbrasero-media. This permission is above and beyond the permissions granted
14 * by the GPL license by which Libbrasero-media 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-media 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/gi18n-lib.h>
39
40 #include <gio/gio.h>
41
42 #include "brasero-media-private.h"
43 #include "brasero-volume.h"
44 #include "brasero-gio-operation.h"
45
46 typedef struct _BraseroVolumePrivate BraseroVolumePrivate;
47 struct _BraseroVolumePrivate
48 {
49 GCancellable *cancel;
50 };
51
52 #define BRASERO_VOLUME_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), BRASERO_TYPE_VOLUME, BraseroVolumePrivate))
53
54 G_DEFINE_TYPE (BraseroVolume, brasero_volume, BRASERO_TYPE_MEDIUM);
55
56 /**
57 * brasero_volume_get_gvolume:
58 * @volume: #BraseroVolume
59 *
60 * Gets the corresponding #GVolume for @volume.
61 *
62 * Return value: a #GVolume *.
63 *
64 **/
65 GVolume *
brasero_volume_get_gvolume(BraseroVolume * volume)66 brasero_volume_get_gvolume (BraseroVolume *volume)
67 {
68 const gchar *volume_path = NULL;
69 GVolumeMonitor *monitor;
70 GVolume *gvolume = NULL;
71 BraseroDrive *drive;
72 GList *volumes;
73 GList *iter;
74
75 g_return_val_if_fail (volume != NULL, NULL);
76 g_return_val_if_fail (BRASERO_IS_VOLUME (volume), NULL);
77
78 drive = brasero_medium_get_drive (BRASERO_MEDIUM (volume));
79
80 /* This returns the block device which is the
81 * same as the device for all OSes except
82 * Solaris where the device is the raw device. */
83 volume_path = brasero_drive_get_block_device (drive);
84
85 /* NOTE: medium-monitor already holds a reference for GVolumeMonitor */
86 monitor = g_volume_monitor_get ();
87 volumes = g_volume_monitor_get_volumes (monitor);
88 g_object_unref (monitor);
89
90 for (iter = volumes; iter; iter = iter->next) {
91 gchar *device_path;
92 GVolume *tmp;
93
94 tmp = iter->data;
95 device_path = g_volume_get_identifier (tmp, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE);
96 if (!device_path)
97 continue;
98
99 BRASERO_MEDIA_LOG ("Found volume %s", device_path);
100 if (!strcmp (device_path, volume_path)) {
101 gvolume = tmp;
102 g_free (device_path);
103 g_object_ref (gvolume);
104 break;
105 }
106
107 g_free (device_path);
108 }
109 g_list_foreach (volumes, (GFunc) g_object_unref, NULL);
110 g_list_free (volumes);
111
112 if (!gvolume)
113 BRASERO_MEDIA_LOG ("No volume found for medium");
114
115 return gvolume;
116 }
117
118 /**
119 * brasero_volume_is_mounted:
120 * @volume: #BraseroVolume
121 *
122 * Returns whether the volume is currently mounted.
123 *
124 * Return value: a #gboolean. TRUE if it is mounted.
125 *
126 **/
127 gboolean
brasero_volume_is_mounted(BraseroVolume * volume)128 brasero_volume_is_mounted (BraseroVolume *volume)
129 {
130 gchar *path;
131
132 g_return_val_if_fail (volume != NULL, FALSE);
133 g_return_val_if_fail (BRASERO_IS_VOLUME (volume), FALSE);
134
135 /* NOTE: that's the surest way to know if a drive is really mounted. For
136 * GIO a blank medium can be mounted to burn:/// which is not really
137 * what we're interested in. So the mount path must be also local. */
138 path = brasero_volume_get_mount_point (volume, NULL);
139 if (path) {
140 g_free (path);
141 return TRUE;
142 }
143
144 return FALSE;
145 }
146
147 /**
148 * brasero_volume_get_mount_point:
149 * @volume: #BraseroVolume
150 * @error: #GError **
151 *
152 * Returns the path for mount point for @volume.
153 *
154 * Return value: a #gchar *
155 *
156 **/
157 gchar *
brasero_volume_get_mount_point(BraseroVolume * volume,GError ** error)158 brasero_volume_get_mount_point (BraseroVolume *volume,
159 GError **error)
160 {
161 gchar *local_path = NULL;
162 GVolume *gvolume;
163 GMount *mount;
164 GFile *root;
165
166 g_return_val_if_fail (volume != NULL, NULL);
167 g_return_val_if_fail (BRASERO_IS_VOLUME (volume), NULL);
168
169 gvolume = brasero_volume_get_gvolume (volume);
170 if (!gvolume)
171 return NULL;
172
173 /* get the uri for the mount point */
174 mount = g_volume_get_mount (gvolume);
175 g_object_unref (gvolume);
176 if (!mount)
177 return NULL;
178
179 root = g_mount_get_root (mount);
180 g_object_unref (mount);
181
182 if (!root) {
183 g_set_error (error,
184 BRASERO_MEDIA_ERROR,
185 BRASERO_MEDIA_ERROR_GENERAL,
186 _("The disc mount point could not be retrieved"));
187 }
188 else {
189 local_path = g_file_get_path (root);
190 g_object_unref (root);
191 BRASERO_MEDIA_LOG ("Mount point is %s", local_path);
192 }
193
194 return local_path;
195 }
196
197 /**
198 * brasero_volume_umount:
199 * @volume: #BraseroVolume
200 * @wait: #gboolean
201 * @error: #GError **
202 *
203 * Unmount @volume. If wait is set to TRUE, then block (in a GMainLoop) until
204 * the operation finishes.
205 *
206 * Return value: a #gboolean. TRUE if the operation succeeded.
207 *
208 **/
209 gboolean
brasero_volume_umount(BraseroVolume * volume,gboolean wait,GError ** error)210 brasero_volume_umount (BraseroVolume *volume,
211 gboolean wait,
212 GError **error)
213 {
214 gboolean result;
215 GVolume *gvolume;
216 BraseroVolumePrivate *priv;
217
218 if (!volume)
219 return TRUE;
220
221 g_return_val_if_fail (BRASERO_IS_VOLUME (volume), FALSE);
222
223 priv = BRASERO_VOLUME_PRIVATE (volume);
224
225 gvolume = brasero_volume_get_gvolume (volume);
226 if (!gvolume)
227 return TRUE;
228
229 if (g_cancellable_is_cancelled (priv->cancel)) {
230 BRASERO_MEDIA_LOG ("Resetting GCancellable object");
231 g_cancellable_reset (priv->cancel);
232 }
233
234 result = brasero_gio_operation_umount (gvolume,
235 priv->cancel,
236 wait,
237 error);
238 g_object_unref (gvolume);
239
240 return result;
241 }
242
243 /**
244 * brasero_volume_mount:
245 * @volume: #BraseroVolume *
246 * @parent_window: #GtkWindow *
247 * @wait: #gboolean
248 * @error: #GError **
249 *
250 * Mount @volume. If wait is set to TRUE, then block (in a GMainLoop) until
251 * the operation finishes.
252 * @parent_window is used if an authentification is needed. Then the authentification
253 * dialog will be set modal.
254 *
255 * Return value: a #gboolean. TRUE if the operation succeeded.
256 *
257 **/
258 gboolean
brasero_volume_mount(BraseroVolume * volume,GtkWindow * parent_window,gboolean wait,GError ** error)259 brasero_volume_mount (BraseroVolume *volume,
260 GtkWindow *parent_window,
261 gboolean wait,
262 GError **error)
263 {
264 gboolean result;
265 GVolume *gvolume;
266 BraseroVolumePrivate *priv;
267
268 if (!volume)
269 return TRUE;
270
271 g_return_val_if_fail (BRASERO_IS_VOLUME (volume), FALSE);
272
273 priv = BRASERO_VOLUME_PRIVATE (volume);
274
275 gvolume = brasero_volume_get_gvolume (volume);
276 if (!gvolume)
277 return TRUE;
278
279 if (g_cancellable_is_cancelled (priv->cancel)) {
280 BRASERO_MEDIA_LOG ("Resetting GCancellable object");
281 g_cancellable_reset (priv->cancel);
282 }
283
284 result = brasero_gio_operation_mount (gvolume,
285 parent_window,
286 priv->cancel,
287 wait,
288 error);
289 g_object_unref (gvolume);
290
291 return result;
292 }
293
294 /**
295 * brasero_volume_cancel_current_operation:
296 * @volume: #BraseroVolume *
297 *
298 * Cancels all operations currently running for @volume
299 *
300 **/
301 void
brasero_volume_cancel_current_operation(BraseroVolume * volume)302 brasero_volume_cancel_current_operation (BraseroVolume *volume)
303 {
304 BraseroVolumePrivate *priv;
305
306 g_return_if_fail (volume != NULL);
307 g_return_if_fail (BRASERO_IS_VOLUME (volume));
308
309 priv = BRASERO_VOLUME_PRIVATE (volume);
310
311 BRASERO_MEDIA_LOG ("Cancelling volume operation");
312
313 g_cancellable_cancel (priv->cancel);
314 }
315
316 /**
317 * brasero_volume_get_icon:
318 * @volume: #BraseroVolume *
319 *
320 * Returns a GIcon pointer for the volume.
321 *
322 * Return value: a #GIcon*
323 *
324 **/
325 GIcon *
brasero_volume_get_icon(BraseroVolume * volume)326 brasero_volume_get_icon (BraseroVolume *volume)
327 {
328 GVolume *gvolume;
329 GMount *mount;
330 GIcon *icon;
331
332 if (!volume)
333 return g_themed_icon_new_with_default_fallbacks ("drive-optical");
334
335 g_return_val_if_fail (BRASERO_IS_VOLUME (volume), NULL);
336
337 if (brasero_medium_get_status (BRASERO_MEDIUM (volume)) == BRASERO_MEDIUM_FILE)
338 return g_themed_icon_new_with_default_fallbacks ("iso-image-new");
339
340 gvolume = brasero_volume_get_gvolume (volume);
341 if (!gvolume)
342 return g_themed_icon_new_with_default_fallbacks ("drive-optical");
343
344 mount = g_volume_get_mount (gvolume);
345 if (mount) {
346 icon = g_mount_get_icon (mount);
347 g_object_unref (mount);
348 }
349 else
350 icon = g_volume_get_icon (gvolume);
351
352 g_object_unref (gvolume);
353
354 return icon;
355 }
356
357 /**
358 * brasero_volume_get_name:
359 * @volume: #BraseroVolume *
360 *
361 * Returns a string that can be displayed to represent the volume²
362 *
363 * Return value: a #gchar *. Free when not needed anymore.
364 *
365 **/
366 gchar *
brasero_volume_get_name(BraseroVolume * volume)367 brasero_volume_get_name (BraseroVolume *volume)
368 {
369 BraseroMedia media;
370 const gchar *type;
371 GVolume *gvolume;
372 gchar *name;
373
374 g_return_val_if_fail (volume != NULL, NULL);
375 g_return_val_if_fail (BRASERO_IS_VOLUME (volume), NULL);
376
377 media = brasero_medium_get_status (BRASERO_MEDIUM (volume));
378 if (media & BRASERO_MEDIUM_FILE) {
379 /* Translators: This is a fake drive, a file, and means that
380 * when we're writing, we're writing to a file and create an
381 * image on the hard drive. */
382 return g_strdup (_("Image File"));
383 }
384
385 if (media & BRASERO_MEDIUM_HAS_AUDIO) {
386 const gchar *audio_name;
387
388 audio_name = brasero_medium_get_CD_TEXT_title (BRASERO_MEDIUM (volume));
389 if (audio_name)
390 return g_strdup (audio_name);
391 }
392
393 gvolume = brasero_volume_get_gvolume (volume);
394 if (!gvolume)
395 goto last_chance;
396
397 name = g_volume_get_name (gvolume);
398 g_object_unref (gvolume);
399
400 if (name)
401 return name;
402
403 last_chance:
404
405 type = brasero_medium_get_type_string (BRASERO_MEDIUM (volume));
406 name = NULL;
407 if (media & BRASERO_MEDIUM_BLANK) {
408 /* NOTE for translators: the first %s is the disc type and Blank is an adjective. */
409 name = g_strdup_printf (_("Blank disc (%s)"), type);
410 }
411 else if (BRASERO_MEDIUM_IS (media, BRASERO_MEDIUM_HAS_AUDIO|BRASERO_MEDIUM_HAS_DATA)) {
412 /* NOTE for translators: the first %s is the disc type. */
413 name = g_strdup_printf (_("Audio and data disc (%s)"), type);
414 }
415 else if (media & BRASERO_MEDIUM_HAS_AUDIO) {
416 /* NOTE for translators: the first %s is the disc type. */
417 name = g_strdup_printf (_("Audio disc (%s)"), type);
418 }
419 else if (media & BRASERO_MEDIUM_HAS_DATA) {
420 /* NOTE for translators: the first %s is the disc type. */
421 name = g_strdup_printf (_("Data disc (%s)"), type);
422 }
423 else {
424 name = g_strdup (type);
425 }
426
427 return name;
428 }
429
430 static void
brasero_volume_init(BraseroVolume * object)431 brasero_volume_init (BraseroVolume *object)
432 {
433 BraseroVolumePrivate *priv;
434
435 priv = BRASERO_VOLUME_PRIVATE (object);
436 priv->cancel = g_cancellable_new ();
437 }
438
439 static void
brasero_volume_finalize(GObject * object)440 brasero_volume_finalize (GObject *object)
441 {
442 BraseroVolumePrivate *priv;
443
444 priv = BRASERO_VOLUME_PRIVATE (object);
445
446 BRASERO_MEDIA_LOG ("Finalizing Volume object");
447 if (priv->cancel) {
448 g_cancellable_cancel (priv->cancel);
449 g_object_unref (priv->cancel);
450 priv->cancel = NULL;
451 }
452
453 G_OBJECT_CLASS (brasero_volume_parent_class)->finalize (object);
454 }
455
456 static void
brasero_volume_class_init(BraseroVolumeClass * klass)457 brasero_volume_class_init (BraseroVolumeClass *klass)
458 {
459 GObjectClass* object_class = G_OBJECT_CLASS (klass);
460
461 g_type_class_add_private (klass, sizeof (BraseroVolumePrivate));
462
463 object_class->finalize = brasero_volume_finalize;
464 }
465