1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /*
3 * Libbrasero-media
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 <unistd.h>
36 #include <string.h>
37
38 #ifdef HAVE_CAM_LIB_H
39 #include <errno.h>
40 #include <stdio.h>
41 #include <fcntl.h>
42 #include <camlib.h>
43 #endif
44
45 #include <glib.h>
46 #include <glib-object.h>
47 #include <glib/gi18n-lib.h>
48
49 #include <gio/gio.h>
50
51 #include "brasero-media-private.h"
52 #include "brasero-gio-operation.h"
53
54 #include "brasero-medium.h"
55 #include "brasero-volume.h"
56 #include "brasero-drive.h"
57
58 #include "brasero-drive-priv.h"
59 #include "scsi-device.h"
60 #include "scsi-utils.h"
61 #include "scsi-spc1.h"
62 #include "scsi-mmc1.h"
63 #include "scsi-mmc2.h"
64 #include "scsi-status-page.h"
65 #include "scsi-mode-pages.h"
66 #include "scsi-sbc.h"
67
68 typedef struct _BraseroDrivePrivate BraseroDrivePrivate;
69 struct _BraseroDrivePrivate
70 {
71 GDrive *gdrive;
72
73 GThread *probe;
74 GMutex *mutex;
75 GCond *cond;
76 GCond *cond_probe;
77 gint probe_id;
78
79 BraseroMedium *medium;
80 BraseroDriveCaps caps;
81
82 gchar *udi;
83
84 gchar *name;
85
86 gchar *device;
87 gchar *block_device;
88
89 GCancellable *cancel;
90
91 guint initial_probe:1;
92 guint initial_probe_cancelled:1;
93
94 guint has_medium:1;
95 guint probe_cancelled:1;
96
97 guint locked:1;
98 guint ejecting:1;
99 guint probe_waiting:1;
100 };
101
102 #define BRASERO_DRIVE_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), BRASERO_TYPE_DRIVE, BraseroDrivePrivate))
103
104 enum {
105 MEDIUM_REMOVED,
106 MEDIUM_INSERTED,
107 LAST_SIGNAL
108 };
109 static gulong drive_signals [LAST_SIGNAL] = {0, };
110
111 enum {
112 PROP_NONE = 0,
113 PROP_DEVICE,
114 PROP_GDRIVE,
115 PROP_UDI
116 };
117
118 G_DEFINE_TYPE (BraseroDrive, brasero_drive, G_TYPE_OBJECT);
119
120 #define BRASERO_DRIVE_OPEN_ATTEMPTS 5
121
122 static void
123 brasero_drive_probe_inside (BraseroDrive *drive);
124
125 /**
126 * brasero_drive_get_gdrive:
127 * @drive: a #BraseroDrive
128 *
129 * Returns the #GDrive corresponding to this #BraseroDrive
130 *
131 * Return value: a #GDrive or NULL. Unref after use.
132 **/
133 GDrive *
brasero_drive_get_gdrive(BraseroDrive * drive)134 brasero_drive_get_gdrive (BraseroDrive *drive)
135 {
136 BraseroDrivePrivate *priv;
137
138 g_return_val_if_fail (drive != NULL, NULL);
139 g_return_val_if_fail (BRASERO_IS_DRIVE (drive), NULL);
140
141 if (brasero_drive_is_fake (drive))
142 return NULL;
143
144 priv = BRASERO_DRIVE_PRIVATE (drive);
145
146 if (!priv->gdrive)
147 return NULL;
148
149 return g_object_ref (priv->gdrive);
150 }
151
152 /**
153 * brasero_drive_can_eject:
154 * @drive: #BraseroDrive
155 *
156 * Returns whether the drive can eject media.
157 *
158 * Return value: a #gboolean. TRUE if the media can be ejected, FALSE otherwise.
159 *
160 **/
161 gboolean
brasero_drive_can_eject(BraseroDrive * drive)162 brasero_drive_can_eject (BraseroDrive *drive)
163 {
164 GVolume *volume;
165 gboolean result;
166 BraseroDrivePrivate *priv;
167
168 g_return_val_if_fail (drive != NULL, FALSE);
169 g_return_val_if_fail (BRASERO_IS_DRIVE (drive), FALSE);
170
171 priv = BRASERO_DRIVE_PRIVATE (drive);
172
173 if (!priv->gdrive) {
174 BRASERO_MEDIA_LOG ("No GDrive");
175 goto last_resort;
176 }
177
178 if (!g_drive_can_eject (priv->gdrive)) {
179 BRASERO_MEDIA_LOG ("GDrive can't eject");
180 goto last_resort;
181 }
182
183 return TRUE;
184
185 last_resort:
186
187 if (!priv->medium)
188 return FALSE;
189
190 /* last resort */
191 volume = brasero_volume_get_gvolume (BRASERO_VOLUME (priv->medium));
192 if (!volume)
193 return FALSE;
194
195 result = g_volume_can_eject (volume);
196 g_object_unref (volume);
197
198 return result;
199 }
200
201 static void
brasero_drive_cancel_probing(BraseroDrive * drive)202 brasero_drive_cancel_probing (BraseroDrive *drive)
203 {
204 BraseroDrivePrivate *priv;
205
206 priv = BRASERO_DRIVE_PRIVATE (drive);
207
208 priv->probe_waiting = FALSE;
209
210 g_mutex_lock (priv->mutex);
211 if (priv->probe) {
212 /* This to signal that we are cancelling */
213 priv->probe_cancelled = TRUE;
214 priv->initial_probe_cancelled = TRUE;
215
216 /* This is to wake up the thread if it
217 * was asleep waiting to retry to get
218 * hold of a handle to probe the drive */
219 g_cond_signal (priv->cond_probe);
220
221 g_cond_wait (priv->cond, priv->mutex);
222 }
223 g_mutex_unlock (priv->mutex);
224
225 if (priv->probe_id) {
226 g_source_remove (priv->probe_id);
227 priv->probe_id = 0;
228 }
229 }
230
231 static void
brasero_drive_wait_probing_thread(BraseroDrive * drive)232 brasero_drive_wait_probing_thread (BraseroDrive *drive)
233 {
234 BraseroDrivePrivate *priv;
235
236 priv = BRASERO_DRIVE_PRIVATE (drive);
237
238 g_mutex_lock (priv->mutex);
239 if (priv->probe) {
240 /* This is to wake up the thread if it
241 * was asleep waiting to retry to get
242 * hold of a handle to probe the drive */
243 g_cond_signal (priv->cond_probe);
244 g_cond_wait (priv->cond, priv->mutex);
245 }
246 g_mutex_unlock (priv->mutex);
247 }
248
249 /**
250 * brasero_drive_eject:
251 * @drive: #BraseroDrive
252 * @wait: #gboolean whether to wait for the completion of the operation (with a GMainLoop)
253 * @error: #GError
254 *
255 * Open the drive tray or ejects the media if there is any inside.
256 *
257 * Return value: a #gboolean. TRUE on success, FALSE otherwise.
258 *
259 **/
260 gboolean
brasero_drive_eject(BraseroDrive * drive,gboolean wait,GError ** error)261 brasero_drive_eject (BraseroDrive *drive,
262 gboolean wait,
263 GError **error)
264 {
265 BraseroDrivePrivate *priv;
266 GVolume *gvolume;
267 gboolean res;
268
269 g_return_val_if_fail (drive != NULL, FALSE);
270 g_return_val_if_fail (BRASERO_IS_DRIVE (drive), FALSE);
271
272 priv = BRASERO_DRIVE_PRIVATE (drive);
273
274 /* reset if needed */
275 if (g_cancellable_is_cancelled (priv->cancel)) {
276 BRASERO_MEDIA_LOG ("Resetting GCancellable object");
277 g_cancellable_reset (priv->cancel);
278 }
279
280 BRASERO_MEDIA_LOG ("Trying to eject drive");
281 if (priv->gdrive) {
282 /* Wait for any ongoing probing as it
283 * would prevent the door from being
284 * opened. */
285 brasero_drive_wait_probing_thread (drive);
286
287 priv->ejecting = TRUE;
288 res = brasero_gio_operation_eject_drive (priv->gdrive,
289 priv->cancel,
290 wait,
291 error);
292 priv->ejecting = FALSE;
293 if (priv->probe_waiting)
294 brasero_drive_probe_inside (drive);
295
296 if (res)
297 return TRUE;
298
299 if (g_cancellable_is_cancelled (priv->cancel))
300 return FALSE;
301 }
302 else
303 BRASERO_MEDIA_LOG ("No GDrive");
304
305 if (!priv->medium)
306 return FALSE;
307
308 /* reset if needed */
309 if (g_cancellable_is_cancelled (priv->cancel)) {
310 BRASERO_MEDIA_LOG ("Resetting GCancellable object");
311 g_cancellable_reset (priv->cancel);
312 }
313
314 gvolume = brasero_volume_get_gvolume (BRASERO_VOLUME (priv->medium));
315 if (gvolume) {
316 BRASERO_MEDIA_LOG ("Trying to eject volume");
317
318 /* Cancel any ongoing probing as it
319 * would prevent the door from being
320 * opened. */
321 brasero_drive_wait_probing_thread (drive);
322
323 priv->ejecting = TRUE;
324 res = brasero_gio_operation_eject_volume (gvolume,
325 priv->cancel,
326 wait,
327 error);
328
329 priv->ejecting = FALSE;
330 if (priv->probe_waiting)
331 brasero_drive_probe_inside (drive);
332
333 g_object_unref (gvolume);
334 }
335
336 return res;
337 }
338
339 /**
340 * brasero_drive_cancel_current_operation:
341 * @drive: #BraseroDrive *
342 *
343 * Cancels all operations currently running for @drive
344 *
345 **/
346 void
brasero_drive_cancel_current_operation(BraseroDrive * drive)347 brasero_drive_cancel_current_operation (BraseroDrive *drive)
348 {
349 BraseroDrivePrivate *priv;
350
351 g_return_if_fail (drive != NULL);
352 g_return_if_fail (BRASERO_IS_DRIVE (drive));
353
354 priv = BRASERO_DRIVE_PRIVATE (drive);
355
356 BRASERO_MEDIA_LOG ("Cancelling GIO operation");
357 g_cancellable_cancel (priv->cancel);
358 }
359
360 /**
361 * brasero_drive_get_bus_target_lun_string:
362 * @drive: a #BraseroDrive
363 *
364 * Returns the bus, target, lun ("{bus},{target},{lun}") as a string which is
365 * sometimes needed by some backends like cdrecord.
366 *
367 * NOTE: that function returns either bus/target/lun or the device path
368 * according to OSes. Basically it returns bus/target/lun only for FreeBSD
369 * which is the only OS in need for that. For all others it returns the device
370 * path.
371 *
372 * Return value: a string or NULL. The string must be freed when not needed
373 *
374 **/
375 gchar *
brasero_drive_get_bus_target_lun_string(BraseroDrive * drive)376 brasero_drive_get_bus_target_lun_string (BraseroDrive *drive)
377 {
378 g_return_val_if_fail (drive != NULL, NULL);
379 g_return_val_if_fail (BRASERO_IS_DRIVE (drive), NULL);
380
381 return brasero_device_get_bus_target_lun (brasero_drive_get_device (drive));
382 }
383
384 /**
385 * brasero_drive_is_fake:
386 * @drive: a #BraseroDrive
387 *
388 * Returns whether or not the drive is a fake one. There is only one and
389 * corresponds to a file which is used when the user wants to burn to a file.
390 *
391 * Return value: %TRUE or %FALSE.
392 **/
393 gboolean
brasero_drive_is_fake(BraseroDrive * drive)394 brasero_drive_is_fake (BraseroDrive *drive)
395 {
396 BraseroDrivePrivate *priv;
397
398 g_return_val_if_fail (drive != NULL, FALSE);
399 g_return_val_if_fail (BRASERO_IS_DRIVE (drive), FALSE);
400
401 priv = BRASERO_DRIVE_PRIVATE (drive);
402 return (priv->device == NULL);
403 }
404
405 /**
406 * brasero_drive_is_door_open:
407 * @drive: a #BraseroDrive
408 *
409 * Returns whether or not the drive door is open.
410 *
411 * Return value: %TRUE or %FALSE.
412 **/
413 gboolean
brasero_drive_is_door_open(BraseroDrive * drive)414 brasero_drive_is_door_open (BraseroDrive *drive)
415 {
416 const gchar *device;
417 BraseroDrivePrivate *priv;
418 BraseroDeviceHandle *handle;
419 BraseroScsiMechStatusHdr hdr;
420
421 g_return_val_if_fail (drive != NULL, FALSE);
422 g_return_val_if_fail (BRASERO_IS_DRIVE (drive), FALSE);
423
424 priv = BRASERO_DRIVE_PRIVATE (drive);
425 if (!priv->device)
426 return FALSE;
427
428 device = brasero_drive_get_device (drive);
429 handle = brasero_device_handle_open (device, FALSE, NULL);
430 if (!handle)
431 return FALSE;
432
433 brasero_mmc1_mech_status (handle,
434 &hdr,
435 NULL);
436
437 brasero_device_handle_close (handle);
438
439 return hdr.door_open;
440 }
441
442 /**
443 * brasero_drive_can_use_exclusively:
444 * @drive: a #BraseroDrive
445 *
446 * Returns whether or not the drive can be used exclusively, that is whether or
447 * not it is currently used by another application.
448 *
449 * Return value: %TRUE or %FALSE.
450 **/
451 gboolean
brasero_drive_can_use_exclusively(BraseroDrive * drive)452 brasero_drive_can_use_exclusively (BraseroDrive *drive)
453 {
454 BraseroDeviceHandle *handle;
455 const gchar *device;
456
457 g_return_val_if_fail (drive != NULL, FALSE);
458 g_return_val_if_fail (BRASERO_IS_DRIVE (drive), FALSE);
459
460 device = brasero_drive_get_device (drive);
461 handle = brasero_device_handle_open (device, TRUE, NULL);
462 if (!handle)
463 return FALSE;
464
465 brasero_device_handle_close (handle);
466 return TRUE;
467 }
468
469 /**
470 * brasero_drive_is_locked:
471 * @drive: a #BraseroDrive
472 * @reason: a #gchar or NULL. A string to indicate what the drive was locked for if return value is %TRUE
473 *
474 * Checks whether a #BraseroDrive is currently locked. Manual ejection shouldn't be possible any more.
475 *
476 * Since 2.29.0
477 *
478 * Return value: %TRUE if the drive is locked or %FALSE.
479 **/
480 gboolean
brasero_drive_is_locked(BraseroDrive * drive,gchar ** reason)481 brasero_drive_is_locked (BraseroDrive *drive,
482 gchar **reason)
483 {
484 BraseroDrivePrivate *priv;
485
486 g_return_val_if_fail (drive != NULL, FALSE);
487 g_return_val_if_fail (BRASERO_IS_DRIVE (drive), FALSE);
488
489 priv = BRASERO_DRIVE_PRIVATE (drive);
490 return priv->locked;
491 }
492
493 /**
494 * brasero_drive_lock:
495 * @drive: a #BraseroDrive
496 * @reason: a string to indicate what the drive was locked for
497 * @reason_for_failure: a string (or NULL) to hold the reason why the locking failed
498 *
499 * Locks a #BraseroDrive. Manual ejection shouldn't be possible any more.
500 *
501 * Return value: %TRUE if the drive was successfully locked or %FALSE.
502 **/
503 gboolean
brasero_drive_lock(BraseroDrive * drive,const gchar * reason,gchar ** reason_for_failure)504 brasero_drive_lock (BraseroDrive *drive,
505 const gchar *reason,
506 gchar **reason_for_failure)
507 {
508 BraseroDeviceHandle *handle;
509 BraseroDrivePrivate *priv;
510 const gchar *device;
511 gboolean result;
512
513 g_return_val_if_fail (drive != NULL, FALSE);
514 g_return_val_if_fail (BRASERO_IS_DRIVE (drive), FALSE);
515
516 priv = BRASERO_DRIVE_PRIVATE (drive);
517 if (!priv->device)
518 return FALSE;
519
520 device = brasero_drive_get_device (drive);
521 handle = brasero_device_handle_open (device, FALSE, NULL);
522 if (!handle)
523 return FALSE;
524
525 result = (brasero_sbc_medium_removal (handle, 1, NULL) == BRASERO_SCSI_OK);
526 if (result) {
527 BRASERO_MEDIA_LOG ("Device locked");
528 priv->locked = TRUE;
529 }
530 else
531 BRASERO_MEDIA_LOG ("Device failed to lock");
532
533 brasero_device_handle_close (handle);
534 return result;
535 }
536
537 /**
538 * brasero_drive_unlock:
539 * @drive: a #BraseroDrive
540 *
541 * Unlocks a #BraseroDrive.
542 *
543 * Return value: %TRUE if the drive was successfully unlocked or %FALSE.
544 **/
545 gboolean
brasero_drive_unlock(BraseroDrive * drive)546 brasero_drive_unlock (BraseroDrive *drive)
547 {
548 BraseroDeviceHandle *handle;
549 BraseroDrivePrivate *priv;
550 const gchar *device;
551 gboolean result;
552
553 g_return_val_if_fail (drive != NULL, FALSE);
554 g_return_val_if_fail (BRASERO_IS_DRIVE (drive), FALSE);
555
556 priv = BRASERO_DRIVE_PRIVATE (drive);
557 if (!priv->device)
558 return FALSE;
559
560 device = brasero_drive_get_device (drive);
561 handle = brasero_device_handle_open (device, FALSE, NULL);
562 if (!handle)
563 return FALSE;
564
565 result = (brasero_sbc_medium_removal (handle, 0, NULL) == BRASERO_SCSI_OK);
566 if (result) {
567 BRASERO_MEDIA_LOG ("Device unlocked");
568 priv->locked = FALSE;
569
570 if (priv->probe_waiting) {
571 BRASERO_MEDIA_LOG ("Probe on hold");
572
573 /* A probe was waiting */
574 brasero_drive_probe_inside (drive);
575 }
576 }
577 else
578 BRASERO_MEDIA_LOG ("Device failed to unlock");
579
580 brasero_device_handle_close (handle);
581
582 return result;
583 }
584
585 /**
586 * brasero_drive_get_display_name:
587 * @drive: a #BraseroDrive
588 *
589 * Gets a string holding the name for the drive. That string can be then
590 * displayed in a user interface.
591 *
592 * Return value: a string holding the name
593 **/
594 gchar *
brasero_drive_get_display_name(BraseroDrive * drive)595 brasero_drive_get_display_name (BraseroDrive *drive)
596 {
597 BraseroDrivePrivate *priv;
598
599 g_return_val_if_fail (drive != NULL, NULL);
600 g_return_val_if_fail (BRASERO_IS_DRIVE (drive), NULL);
601
602 priv = BRASERO_DRIVE_PRIVATE (drive);
603 if (!priv->device) {
604 /* Translators: This is a fake drive, a file, and means that
605 * when we're writing, we're writing to a file and create an
606 * image on the hard drive. */
607 return g_strdup (_("Image File"));
608 }
609
610 return g_strdup (priv->name);
611 }
612
613 /**
614 * brasero_drive_get_device:
615 * @drive: a #BraseroDrive
616 *
617 * Gets a string holding the device path for the drive.
618 *
619 * Return value: a string holding the device path.
620 * On Solaris returns raw device.
621 **/
622 const gchar *
brasero_drive_get_device(BraseroDrive * drive)623 brasero_drive_get_device (BraseroDrive *drive)
624 {
625 BraseroDrivePrivate *priv;
626
627 g_return_val_if_fail (drive != NULL, NULL);
628 g_return_val_if_fail (BRASERO_IS_DRIVE (drive), NULL);
629
630 priv = BRASERO_DRIVE_PRIVATE (drive);
631 return priv->device;
632 }
633
634 /**
635 * brasero_drive_get_block_device:
636 * @drive: a #BraseroDrive
637 *
638 * Gets a string holding the block device path for the drive. This can be used on
639 * some other OSes, like Solaris, for GIO operations instead of the device
640 * path.
641 *
642 * Solaris uses block device for GIO operations and
643 * uses raw device for system calls and backends
644 * like cdrtool.
645 *
646 * If such a path is not available, it returns the device path.
647 *
648 * Return value: a string holding the block device path
649 **/
650 const gchar *
brasero_drive_get_block_device(BraseroDrive * drive)651 brasero_drive_get_block_device (BraseroDrive *drive)
652 {
653 BraseroDrivePrivate *priv;
654
655 g_return_val_if_fail (drive != NULL, NULL);
656 g_return_val_if_fail (BRASERO_IS_DRIVE (drive), NULL);
657
658 priv = BRASERO_DRIVE_PRIVATE (drive);
659 return priv->block_device? priv->block_device:priv->device;
660 }
661
662 /**
663 * brasero_drive_get_udi:
664 * @drive: a #BraseroDrive
665 *
666 * Gets a string holding the HAL udi corresponding to this device. It can be used
667 * to uniquely identify the drive.
668 *
669 * Return value: a string holding the HAL udi or NULL. Not to be freed
670 **/
671 const gchar *
brasero_drive_get_udi(BraseroDrive * drive)672 brasero_drive_get_udi (BraseroDrive *drive)
673 {
674 BraseroDrivePrivate *priv;
675
676 if (!drive)
677 return NULL;
678
679 g_return_val_if_fail (BRASERO_IS_DRIVE (drive), NULL);
680
681 priv = BRASERO_DRIVE_PRIVATE (drive);
682 if (!priv->device || !priv->gdrive)
683 return NULL;
684
685 if (priv->udi)
686 return priv->udi;
687
688 priv->udi = g_drive_get_identifier (priv->gdrive, G_VOLUME_IDENTIFIER_KIND_HAL_UDI);
689 return priv->udi;
690 }
691
692 /**
693 * brasero_drive_get_medium:
694 * @drive: a #BraseroDrive
695 *
696 * Gets the medium currently inserted in the drive. If there is no medium or if
697 * the medium is not probed yet then it returns NULL.
698 *
699 * Return value: (transfer none): a #BraseroMedium object or NULL. No need to unref after use.
700 **/
701 BraseroMedium *
brasero_drive_get_medium(BraseroDrive * drive)702 brasero_drive_get_medium (BraseroDrive *drive)
703 {
704 BraseroDrivePrivate *priv;
705
706 if (!drive)
707 return NULL;
708
709 g_return_val_if_fail (BRASERO_IS_DRIVE (drive), NULL);
710
711 priv = BRASERO_DRIVE_PRIVATE (drive);
712 if (brasero_drive_probing (drive))
713 return NULL;
714
715 return priv->medium;
716 }
717
718 /**
719 * brasero_drive_get_caps:
720 * @drive: a #BraseroDrive
721 *
722 * Returns what type(s) of disc the drive can write to.
723 *
724 * Return value: a #BraseroDriveCaps.
725 **/
726 BraseroDriveCaps
brasero_drive_get_caps(BraseroDrive * drive)727 brasero_drive_get_caps (BraseroDrive *drive)
728 {
729 BraseroDrivePrivate *priv;
730
731 g_return_val_if_fail (drive != NULL, BRASERO_DRIVE_CAPS_NONE);
732 g_return_val_if_fail (BRASERO_IS_DRIVE (drive), BRASERO_DRIVE_CAPS_NONE);
733
734 priv = BRASERO_DRIVE_PRIVATE (drive);
735 return priv->caps;
736 }
737
738 /**
739 * brasero_drive_can_write_media:
740 * @drive: a #BraseroDrive
741 * @media: a #BraseroMedia
742 *
743 * Returns whether the disc can burn a specific media type.
744 *
745 * Since 2.29.0
746 *
747 * Return value: a #gboolean. TRUE if the drive can write this type of media and FALSE otherwise
748 **/
749 gboolean
brasero_drive_can_write_media(BraseroDrive * drive,BraseroMedia media)750 brasero_drive_can_write_media (BraseroDrive *drive,
751 BraseroMedia media)
752 {
753 BraseroDrivePrivate *priv;
754
755 g_return_val_if_fail (drive != NULL, FALSE);
756 g_return_val_if_fail (BRASERO_IS_DRIVE (drive), FALSE);
757
758 priv = BRASERO_DRIVE_PRIVATE (drive);
759
760 if (!(media & BRASERO_MEDIUM_REWRITABLE)
761 && (media & BRASERO_MEDIUM_CLOSED))
762 return FALSE;
763
764 if (media & BRASERO_MEDIUM_FILE)
765 return FALSE;
766
767 if (BRASERO_MEDIUM_IS (media, BRASERO_MEDIUM_CDR))
768 return (priv->caps & BRASERO_DRIVE_CAPS_CDR) != 0;
769
770 if (BRASERO_MEDIUM_IS (media, BRASERO_MEDIUM_DVDR))
771 return (priv->caps & BRASERO_DRIVE_CAPS_DVDR) != 0;
772
773 if (BRASERO_MEDIUM_IS (media, BRASERO_MEDIUM_DVDR_PLUS))
774 return (priv->caps & BRASERO_DRIVE_CAPS_DVDR_PLUS) != 0;
775
776 if (BRASERO_MEDIUM_IS (media, BRASERO_MEDIUM_CDRW))
777 return (priv->caps & BRASERO_DRIVE_CAPS_CDRW) != 0;
778
779 if (BRASERO_MEDIUM_IS (media, BRASERO_MEDIUM_DVDRW))
780 return (priv->caps & BRASERO_DRIVE_CAPS_DVDRW) != 0;
781
782 if (BRASERO_MEDIUM_IS (media, BRASERO_MEDIUM_DVDRW_RESTRICTED))
783 return (priv->caps & BRASERO_DRIVE_CAPS_DVDRW) != 0;
784
785 if (BRASERO_MEDIUM_IS (media, BRASERO_MEDIUM_DVDRW_PLUS))
786 return (priv->caps & BRASERO_DRIVE_CAPS_DVDRW_PLUS) != 0;
787
788 if (BRASERO_MEDIUM_IS (media, BRASERO_MEDIUM_DVDR_PLUS_DL))
789 return (priv->caps & BRASERO_DRIVE_CAPS_DVDR_PLUS_DL) != 0;
790
791 if (BRASERO_MEDIUM_IS (media, BRASERO_MEDIUM_DVDRW_PLUS_DL))
792 return (priv->caps & BRASERO_DRIVE_CAPS_DVDRW_PLUS_DL) != 0;
793
794 if (BRASERO_MEDIUM_IS (media, BRASERO_MEDIUM_DVD_RAM))
795 return (priv->caps & BRASERO_DRIVE_CAPS_DVDRAM) != 0;
796
797 /* All types of BD-R */
798 if (BRASERO_MEDIUM_IS (media, BRASERO_MEDIUM_BD|BRASERO_MEDIUM_WRITABLE))
799 return (priv->caps & BRASERO_DRIVE_CAPS_BDR) != 0;
800
801 if (BRASERO_MEDIUM_IS (media, BRASERO_MEDIUM_BDRE))
802 return (priv->caps & BRASERO_DRIVE_CAPS_BDRW) != 0;
803
804 return FALSE;
805 }
806
807 /**
808 * brasero_drive_can_write:
809 * @drive: a #BraseroDrive
810 *
811 * Returns whether the disc can burn any disc at all.
812 *
813 * Return value: a #gboolean. TRUE if the drive can write a disc and FALSE otherwise
814 **/
815 gboolean
brasero_drive_can_write(BraseroDrive * drive)816 brasero_drive_can_write (BraseroDrive *drive)
817 {
818 BraseroDrivePrivate *priv;
819
820 g_return_val_if_fail (drive != NULL, FALSE);
821 g_return_val_if_fail (BRASERO_IS_DRIVE (drive), FALSE);
822
823 priv = BRASERO_DRIVE_PRIVATE (drive);
824 return (priv->caps & (BRASERO_DRIVE_CAPS_CDR|
825 BRASERO_DRIVE_CAPS_DVDR|
826 BRASERO_DRIVE_CAPS_DVDR_PLUS|
827 BRASERO_DRIVE_CAPS_CDRW|
828 BRASERO_DRIVE_CAPS_DVDRW|
829 BRASERO_DRIVE_CAPS_DVDRW_PLUS|
830 BRASERO_DRIVE_CAPS_DVDR_PLUS_DL|
831 BRASERO_DRIVE_CAPS_DVDRW_PLUS_DL));
832 }
833
834 static void
brasero_drive_medium_probed(BraseroMedium * medium,BraseroDrive * self)835 brasero_drive_medium_probed (BraseroMedium *medium,
836 BraseroDrive *self)
837 {
838 BraseroDrivePrivate *priv;
839
840 priv = BRASERO_DRIVE_PRIVATE (self);
841
842 /* only when it is probed */
843 /* NOTE: BraseroMedium calls GDK_THREADS_ENTER/LEAVE() around g_signal_emit () */
844 if (brasero_medium_get_status (priv->medium) == BRASERO_MEDIUM_NONE) {
845 g_object_unref (priv->medium);
846 priv->medium = NULL;
847 return;
848 }
849
850 g_signal_emit (self,
851 drive_signals [MEDIUM_INSERTED],
852 0,
853 priv->medium);
854 }
855
856 /**
857 * This is not public API. Defined in brasero-drive-priv.h.
858 */
859 gboolean
brasero_drive_probing(BraseroDrive * drive)860 brasero_drive_probing (BraseroDrive *drive)
861 {
862 BraseroDrivePrivate *priv;
863
864 g_return_val_if_fail (drive != NULL, FALSE);
865 g_return_val_if_fail (BRASERO_IS_DRIVE (drive), FALSE);
866
867 priv = BRASERO_DRIVE_PRIVATE (drive);
868 if (priv->probe != NULL)
869 return TRUE;
870
871 if (priv->medium)
872 return brasero_medium_probing (priv->medium);
873
874 return FALSE;
875 }
876
877 static void
brasero_drive_update_medium(BraseroDrive * drive)878 brasero_drive_update_medium (BraseroDrive *drive)
879 {
880 BraseroDrivePrivate *priv;
881
882 priv = BRASERO_DRIVE_PRIVATE (drive);
883
884 if (priv->has_medium) {
885 if (priv->medium) {
886 BRASERO_MEDIA_LOG ("Already a medium. Skipping");
887 return;
888 }
889
890 BRASERO_MEDIA_LOG ("Probing new medium");
891 priv->medium = g_object_new (BRASERO_TYPE_VOLUME,
892 "drive", drive,
893 NULL);
894
895 g_signal_connect (priv->medium,
896 "probed",
897 G_CALLBACK (brasero_drive_medium_probed),
898 drive);
899 }
900 else if (priv->medium) {
901 BraseroMedium *medium;
902
903 BRASERO_MEDIA_LOG ("Medium removed");
904
905 medium = priv->medium;
906 priv->medium = NULL;
907
908 g_signal_emit (drive,
909 drive_signals [MEDIUM_REMOVED],
910 0,
911 medium);
912
913 g_object_unref (medium);
914 }
915 }
916
917 static gboolean
brasero_drive_probed_inside(gpointer data)918 brasero_drive_probed_inside (gpointer data)
919 {
920 BraseroDrive *self;
921 BraseroDrivePrivate *priv;
922
923 self = BRASERO_DRIVE (data);
924 priv = BRASERO_DRIVE_PRIVATE (self);
925
926 if (!g_mutex_trylock (priv->mutex))
927 return TRUE;
928
929 priv->probe_id = 0;
930 g_mutex_unlock (priv->mutex);
931
932 brasero_drive_update_medium (self);
933 return FALSE;
934 }
935
936 static gpointer
brasero_drive_probe_inside_thread(gpointer data)937 brasero_drive_probe_inside_thread (gpointer data)
938 {
939 gint counter = 0;
940 GTimeVal wait_time;
941 const gchar *device;
942 BraseroScsiErrCode code;
943 BraseroDrivePrivate *priv;
944 BraseroDeviceHandle *handle = NULL;
945 BraseroDrive *drive = BRASERO_DRIVE (data);
946
947 priv = BRASERO_DRIVE_PRIVATE (drive);
948
949 /* the drive might be busy (a burning is going on) so we don't block
950 * but we re-try to open it every second */
951 device = brasero_drive_get_device (drive);
952 BRASERO_MEDIA_LOG ("Trying to open device %s", device);
953
954 priv->has_medium = FALSE;
955
956 handle = brasero_device_handle_open (device, FALSE, &code);
957 while (!handle && counter <= BRASERO_DRIVE_OPEN_ATTEMPTS) {
958 sleep (1);
959
960 if (priv->probe_cancelled) {
961 BRASERO_MEDIA_LOG ("Open () cancelled");
962 goto end;
963 }
964
965 counter ++;
966 handle = brasero_device_handle_open (device, FALSE, &code);
967 }
968
969 if (!handle) {
970 BRASERO_MEDIA_LOG ("Open () failed: medium busy");
971 goto end;
972 }
973
974 if (priv->probe_cancelled) {
975 BRASERO_MEDIA_LOG ("Open () cancelled");
976
977 brasero_device_handle_close (handle);
978 goto end;
979 }
980
981 while (brasero_spc1_test_unit_ready (handle, &code) != BRASERO_SCSI_OK) {
982 if (code == BRASERO_SCSI_NO_MEDIUM) {
983 BRASERO_MEDIA_LOG ("No medium inserted");
984
985 brasero_device_handle_close (handle);
986 goto end;
987 }
988
989 if (code != BRASERO_SCSI_NOT_READY) {
990 BRASERO_MEDIA_LOG ("Device does not respond");
991
992 brasero_device_handle_close (handle);
993 goto end;
994 }
995
996 g_get_current_time (&wait_time);
997 g_time_val_add (&wait_time, 2000000);
998
999 g_mutex_lock (priv->mutex);
1000 g_cond_timed_wait (priv->cond_probe,
1001 priv->mutex,
1002 &wait_time);
1003 g_mutex_unlock (priv->mutex);
1004
1005 if (priv->probe_cancelled) {
1006 BRASERO_MEDIA_LOG ("Device probing cancelled");
1007
1008 brasero_device_handle_close (handle);
1009 goto end;
1010 }
1011 }
1012
1013 BRASERO_MEDIA_LOG ("Medium inserted");
1014 brasero_device_handle_close (handle);
1015
1016 priv->has_medium = TRUE;
1017
1018 end:
1019
1020 g_mutex_lock (priv->mutex);
1021
1022 if (!priv->probe_cancelled)
1023 priv->probe_id = g_idle_add (brasero_drive_probed_inside, drive);
1024
1025 priv->probe = NULL;
1026 g_cond_broadcast (priv->cond);
1027 g_mutex_unlock (priv->mutex);
1028
1029 g_thread_exit (0);
1030
1031 return NULL;
1032 }
1033
1034 static void
brasero_drive_probe_inside(BraseroDrive * drive)1035 brasero_drive_probe_inside (BraseroDrive *drive)
1036 {
1037 BraseroDrivePrivate *priv;
1038
1039 priv = BRASERO_DRIVE_PRIVATE (drive);
1040
1041 if (priv->initial_probe) {
1042 BRASERO_MEDIA_LOG ("Still initializing the drive properties");
1043 return;
1044 }
1045
1046 /* Check that a probe is not already being performed */
1047 if (priv->probe) {
1048 BRASERO_MEDIA_LOG ("Ongoing probe");
1049 brasero_drive_cancel_probing (drive);
1050 }
1051
1052 BRASERO_MEDIA_LOG ("Setting new probe");
1053
1054 g_mutex_lock (priv->mutex);
1055
1056 priv->probe_waiting = FALSE;
1057 priv->probe_cancelled = FALSE;
1058
1059 priv->probe = g_thread_create (brasero_drive_probe_inside_thread,
1060 drive,
1061 FALSE,
1062 NULL);
1063
1064 g_mutex_unlock (priv->mutex);
1065 }
1066
1067 static void
brasero_drive_medium_gdrive_changed_cb(BraseroDrive * gdrive,BraseroDrive * drive)1068 brasero_drive_medium_gdrive_changed_cb (BraseroDrive *gdrive,
1069 BraseroDrive *drive)
1070 {
1071 BraseroDrivePrivate *priv;
1072
1073 priv = BRASERO_DRIVE_PRIVATE (drive);
1074 if (priv->locked || priv->ejecting) {
1075 BRASERO_MEDIA_LOG ("Waiting for next unlocking of the drive to probe");
1076
1077 /* Since the drive was locked, it should
1078 * not be possible that the medium
1079 * actually changed.
1080 * This allows to avoid probing while
1081 * we are burning something.
1082 * Delay the probe until brasero_drive_unlock ()
1083 * is called. */
1084 priv->probe_waiting = TRUE;
1085 return;
1086 }
1087
1088 BRASERO_MEDIA_LOG ("GDrive changed");
1089 brasero_drive_probe_inside (drive);
1090 }
1091
1092 static void
brasero_drive_update_gdrive(BraseroDrive * drive,GDrive * gdrive)1093 brasero_drive_update_gdrive (BraseroDrive *drive,
1094 GDrive *gdrive)
1095 {
1096 BraseroDrivePrivate *priv;
1097
1098 priv = BRASERO_DRIVE_PRIVATE (drive);
1099 if (priv->gdrive) {
1100 g_signal_handlers_disconnect_by_func (priv->gdrive,
1101 brasero_drive_medium_gdrive_changed_cb,
1102 drive);
1103
1104 /* Stop any ongoing GIO operation */
1105 g_cancellable_cancel (priv->cancel);
1106
1107 g_object_unref (priv->gdrive);
1108 priv->gdrive = NULL;
1109 }
1110
1111 BRASERO_MEDIA_LOG ("Setting GDrive %p", gdrive);
1112
1113 if (gdrive) {
1114 priv->gdrive = g_object_ref (gdrive);
1115
1116 /* If it's not a fake drive then connect to signal for any
1117 * change and check medium inside */
1118 g_signal_connect (priv->gdrive,
1119 "changed",
1120 G_CALLBACK (brasero_drive_medium_gdrive_changed_cb),
1121 drive);
1122 }
1123
1124 if (priv->locked || priv->ejecting) {
1125 BRASERO_MEDIA_LOG ("Waiting for next unlocking of the drive to probe");
1126
1127 /* Since the drive was locked, it should
1128 * not be possible that the medium
1129 * actually changed.
1130 * This allows to avoid probing while
1131 * we are burning something.
1132 * Delay the probe until brasero_drive_unlock ()
1133 * is called. */
1134 priv->probe_waiting = TRUE;
1135 return;
1136 }
1137
1138 brasero_drive_probe_inside (drive);
1139 }
1140
1141 /**
1142 * brasero_drive_reprobe:
1143 * @drive: a #BraseroDrive
1144 *
1145 * Reprobes the drive contents. Useful when an operation has just been performed
1146 * (blanking, burning, ...) and medium status should be updated.
1147 *
1148 * NOTE: This operation does not block.
1149 *
1150 **/
1151
1152 void
brasero_drive_reprobe(BraseroDrive * drive)1153 brasero_drive_reprobe (BraseroDrive *drive)
1154 {
1155 BraseroDrivePrivate *priv;
1156 BraseroMedium *medium;
1157
1158 g_return_if_fail (drive != NULL);
1159 g_return_if_fail (BRASERO_IS_DRIVE (drive));
1160
1161 priv = BRASERO_DRIVE_PRIVATE (drive);
1162
1163 if (priv->gdrive) {
1164 /* reprobe the contents of the drive system wide */
1165 g_drive_poll_for_media (priv->gdrive, NULL, NULL, NULL);
1166 }
1167
1168 priv->probe_waiting = FALSE;
1169
1170 BRASERO_MEDIA_LOG ("Reprobing inserted medium");
1171 if (priv->medium) {
1172 /* remove current medium */
1173 medium = priv->medium;
1174 priv->medium = NULL;
1175
1176 g_signal_emit (drive,
1177 drive_signals [MEDIUM_REMOVED],
1178 0,
1179 medium);
1180 g_object_unref (medium);
1181 }
1182
1183 brasero_drive_probe_inside (drive);
1184 }
1185
1186 static gboolean
brasero_drive_get_caps_profiles(BraseroDrive * self,BraseroDeviceHandle * handle,BraseroScsiErrCode * code)1187 brasero_drive_get_caps_profiles (BraseroDrive *self,
1188 BraseroDeviceHandle *handle,
1189 BraseroScsiErrCode *code)
1190 {
1191 BraseroScsiGetConfigHdr *hdr = NULL;
1192 BraseroScsiProfileDesc *profiles;
1193 BraseroScsiFeatureDesc *desc;
1194 BraseroDrivePrivate *priv;
1195 BraseroScsiResult result;
1196 int profiles_num;
1197 int size;
1198
1199 priv = BRASERO_DRIVE_PRIVATE (self);
1200
1201 BRASERO_MEDIA_LOG ("Checking supported profiles");
1202 result = brasero_mmc2_get_configuration_feature (handle,
1203 BRASERO_SCSI_FEAT_PROFILES,
1204 &hdr,
1205 &size,
1206 code);
1207 if (result != BRASERO_SCSI_OK) {
1208 BRASERO_MEDIA_LOG ("GET CONFIGURATION failed");
1209 return FALSE;
1210 }
1211
1212 BRASERO_MEDIA_LOG ("Dectected medium is 0x%x", BRASERO_GET_16 (hdr->current_profile));
1213
1214 /* Go through all features available */
1215 desc = hdr->desc;
1216 profiles = (BraseroScsiProfileDesc *) desc->data;
1217 profiles_num = desc->add_len / sizeof (BraseroScsiProfileDesc);
1218
1219 while (profiles_num) {
1220 switch (BRASERO_GET_16 (profiles->number)) {
1221 case BRASERO_SCSI_PROF_CDR:
1222 priv->caps |= BRASERO_DRIVE_CAPS_CDR;
1223 break;
1224 case BRASERO_SCSI_PROF_CDRW:
1225 priv->caps |= BRASERO_DRIVE_CAPS_CDRW;
1226 break;
1227 case BRASERO_SCSI_PROF_DVD_R:
1228 priv->caps |= BRASERO_DRIVE_CAPS_DVDR;
1229 break;
1230 case BRASERO_SCSI_PROF_DVD_RW_SEQUENTIAL:
1231 case BRASERO_SCSI_PROF_DVD_RW_RESTRICTED:
1232 priv->caps |= BRASERO_DRIVE_CAPS_DVDRW;
1233 break;
1234 case BRASERO_SCSI_PROF_DVD_RAM:
1235 priv->caps |= BRASERO_DRIVE_CAPS_DVDRAM;
1236 break;
1237 case BRASERO_SCSI_PROF_DVD_R_PLUS_DL:
1238 priv->caps |= BRASERO_DRIVE_CAPS_DVDR_PLUS_DL;
1239 break;
1240 case BRASERO_SCSI_PROF_DVD_RW_PLUS_DL:
1241 priv->caps |= BRASERO_DRIVE_CAPS_DVDRW_PLUS_DL;
1242 break;
1243 case BRASERO_SCSI_PROF_DVD_R_PLUS:
1244 priv->caps |= BRASERO_DRIVE_CAPS_DVDR_PLUS;
1245 break;
1246 case BRASERO_SCSI_PROF_DVD_RW_PLUS:
1247 priv->caps |= BRASERO_DRIVE_CAPS_DVDRW_PLUS;
1248 break;
1249 case BRASERO_SCSI_PROF_BR_R_SEQUENTIAL:
1250 case BRASERO_SCSI_PROF_BR_R_RANDOM:
1251 priv->caps |= BRASERO_DRIVE_CAPS_BDR;
1252 break;
1253 case BRASERO_SCSI_PROF_BD_RW:
1254 priv->caps |= BRASERO_DRIVE_CAPS_BDRW;
1255 break;
1256 default:
1257 break;
1258 }
1259
1260 if (priv->initial_probe_cancelled)
1261 break;
1262
1263 /* Move the pointer to the next features */
1264 profiles ++;
1265 profiles_num --;
1266 }
1267
1268 g_free (hdr);
1269 return TRUE;
1270 }
1271
1272 static void
brasero_drive_get_caps_2A(BraseroDrive * self,BraseroDeviceHandle * handle,BraseroScsiErrCode * code)1273 brasero_drive_get_caps_2A (BraseroDrive *self,
1274 BraseroDeviceHandle *handle,
1275 BraseroScsiErrCode *code)
1276 {
1277 BraseroScsiStatusPage *page_2A = NULL;
1278 BraseroScsiModeData *data = NULL;
1279 BraseroDrivePrivate *priv;
1280 BraseroScsiResult result;
1281 int size = 0;
1282
1283 priv = BRASERO_DRIVE_PRIVATE (self);
1284
1285 result = brasero_spc1_mode_sense_get_page (handle,
1286 BRASERO_SPC_PAGE_STATUS,
1287 &data,
1288 &size,
1289 code);
1290 if (result != BRASERO_SCSI_OK) {
1291 BRASERO_MEDIA_LOG ("MODE SENSE failed");
1292 return;
1293 }
1294
1295 page_2A = (BraseroScsiStatusPage *) &data->page;
1296
1297 if (page_2A->wr_CDR != 0)
1298 priv->caps |= BRASERO_DRIVE_CAPS_CDR;
1299 if (page_2A->wr_CDRW != 0)
1300 priv->caps |= BRASERO_DRIVE_CAPS_CDRW;
1301 if (page_2A->wr_DVDR != 0)
1302 priv->caps |= BRASERO_DRIVE_CAPS_DVDR;
1303 if (page_2A->wr_DVDRAM != 0)
1304 priv->caps |= BRASERO_DRIVE_CAPS_DVDRAM;
1305
1306 g_free (data);
1307 }
1308
1309 static gpointer
brasero_drive_probe_thread(gpointer data)1310 brasero_drive_probe_thread (gpointer data)
1311 {
1312 gint counter = 0;
1313 GTimeVal wait_time;
1314 const gchar *device;
1315 BraseroScsiResult res;
1316 BraseroScsiInquiry hdr;
1317 BraseroScsiErrCode code;
1318 BraseroDrivePrivate *priv;
1319 BraseroDeviceHandle *handle;
1320 BraseroDrive *drive = BRASERO_DRIVE (data);
1321
1322 priv = BRASERO_DRIVE_PRIVATE (drive);
1323
1324 /* the drive might be busy (a burning is going on) so we don't block
1325 * but we re-try to open it every second */
1326 device = brasero_drive_get_device (drive);
1327 BRASERO_MEDIA_LOG ("Trying to open device %s", device);
1328
1329 handle = brasero_device_handle_open (device, FALSE, &code);
1330 while (!handle && counter <= BRASERO_DRIVE_OPEN_ATTEMPTS) {
1331 sleep (1);
1332
1333 if (priv->initial_probe_cancelled) {
1334 BRASERO_MEDIA_LOG ("Open () cancelled");
1335 goto end;
1336 }
1337
1338 counter ++;
1339 handle = brasero_device_handle_open (device, FALSE, &code);
1340 }
1341
1342 if (priv->initial_probe_cancelled) {
1343 BRASERO_MEDIA_LOG ("Open () cancelled");
1344 goto end;
1345 }
1346
1347 if (!handle) {
1348 BRASERO_MEDIA_LOG ("Open () failed: medium busy");
1349 goto end;
1350 }
1351
1352 while (brasero_spc1_test_unit_ready (handle, &code) != BRASERO_SCSI_OK) {
1353 if (code == BRASERO_SCSI_NO_MEDIUM) {
1354 BRASERO_MEDIA_LOG ("No medium inserted");
1355 goto capabilities;
1356 }
1357
1358 if (code != BRASERO_SCSI_NOT_READY) {
1359 brasero_device_handle_close (handle);
1360 BRASERO_MEDIA_LOG ("Device does not respond");
1361 goto end;
1362 }
1363
1364 g_get_current_time (&wait_time);
1365 g_time_val_add (&wait_time, 2000000);
1366
1367 g_mutex_lock (priv->mutex);
1368 g_cond_timed_wait (priv->cond_probe,
1369 priv->mutex,
1370 &wait_time);
1371 g_mutex_unlock (priv->mutex);
1372
1373 if (priv->initial_probe_cancelled) {
1374 brasero_device_handle_close (handle);
1375 BRASERO_MEDIA_LOG ("Device probing cancelled");
1376 goto end;
1377 }
1378 }
1379
1380 BRASERO_MEDIA_LOG ("Device ready");
1381 priv->has_medium = TRUE;
1382
1383 capabilities:
1384
1385 /* get additional information like the name */
1386 res = brasero_spc1_inquiry (handle, &hdr, NULL);
1387 if (res == BRASERO_SCSI_OK) {
1388 gchar *name_utf8;
1389 gchar *vendor;
1390 gchar *model;
1391 gchar *name;
1392
1393 vendor = g_strndup ((gchar *) hdr.vendor, sizeof (hdr.vendor));
1394 model = g_strndup ((gchar *) hdr.name, sizeof (hdr.name));
1395 name = g_strdup_printf ("%s %s", g_strstrip (vendor), g_strstrip (model));
1396 g_free (vendor);
1397 g_free (model);
1398
1399 /* make sure that's proper UTF-8 */
1400 name_utf8 = g_convert_with_fallback (name,
1401 -1,
1402 "ASCII",
1403 "UTF-8",
1404 "_",
1405 NULL,
1406 NULL,
1407 NULL);
1408 g_free (name);
1409
1410 priv->name = name_utf8;
1411 }
1412
1413 /* Get supported medium types */
1414 if (!brasero_drive_get_caps_profiles (drive, handle, &code))
1415 brasero_drive_get_caps_2A (drive, handle, &code);
1416
1417 brasero_device_handle_close (handle);
1418
1419 BRASERO_MEDIA_LOG ("Drive caps are %d", priv->caps);
1420
1421 end:
1422
1423 g_mutex_lock (priv->mutex);
1424
1425 brasero_drive_update_medium (drive);
1426
1427 priv->probe = NULL;
1428 priv->initial_probe = FALSE;
1429
1430 g_cond_broadcast (priv->cond);
1431 g_mutex_unlock (priv->mutex);
1432
1433 g_thread_exit (0);
1434
1435 return NULL;
1436 }
1437
1438 static void
brasero_drive_init_real_device(BraseroDrive * drive,const gchar * device)1439 brasero_drive_init_real_device (BraseroDrive *drive,
1440 const gchar *device)
1441 {
1442 BraseroDrivePrivate *priv;
1443
1444 priv = BRASERO_DRIVE_PRIVATE (drive);
1445
1446 #if defined(HAVE_STRUCT_USCSI_CMD)
1447 /* On Solaris path points to raw device, block_path points to the block device. */
1448 g_assert(g_str_has_prefix(device, "/dev/dsk/"));
1449 priv->device = g_strdup_printf ("/dev/rdsk/%s", device + 9);
1450 priv->block_device = g_strdup (device);
1451 BRASERO_MEDIA_LOG ("Initializing block drive %s", priv->block_device);
1452 #else
1453 priv->device = g_strdup (device);
1454 #endif
1455
1456 BRASERO_MEDIA_LOG ("Initializing drive %s from device", priv->device);
1457
1458 /* NOTE: why a thread? Because in case of a damaged medium, brasero can
1459 * block on some functions until timeout and if we do this in the main
1460 * thread then our whole UI blocks. This medium won't be exported by the
1461 * BraseroDrive that exported until it returns PROBED signal.
1462 * One (good) side effect is that it also improves start time. */
1463 g_mutex_lock (priv->mutex);
1464
1465 priv->initial_probe = TRUE;
1466 priv->probe = g_thread_create (brasero_drive_probe_thread,
1467 drive,
1468 FALSE,
1469 NULL);
1470
1471 g_mutex_unlock (priv->mutex);
1472 }
1473
1474 static void
brasero_drive_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)1475 brasero_drive_set_property (GObject *object,
1476 guint prop_id,
1477 const GValue *value,
1478 GParamSpec *pspec)
1479 {
1480 BraseroDrivePrivate *priv;
1481 GDrive *gdrive = NULL;
1482
1483 g_return_if_fail (BRASERO_IS_DRIVE (object));
1484
1485 priv = BRASERO_DRIVE_PRIVATE (object);
1486
1487 switch (prop_id)
1488 {
1489 case PROP_UDI:
1490 break;
1491 case PROP_GDRIVE:
1492 if (!priv->device)
1493 break;
1494
1495 gdrive = g_value_get_object (value);
1496 brasero_drive_update_gdrive (BRASERO_DRIVE (object), gdrive);
1497 break;
1498 case PROP_DEVICE:
1499 /* The first case is only a fake drive/medium */
1500 if (!g_value_get_string (value))
1501 priv->medium = g_object_new (BRASERO_TYPE_VOLUME,
1502 "drive", object,
1503 NULL);
1504 else
1505 brasero_drive_init_real_device (BRASERO_DRIVE (object), g_value_get_string (value));
1506 break;
1507 default:
1508 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1509 break;
1510 }
1511 }
1512
1513 static void
brasero_drive_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)1514 brasero_drive_get_property (GObject *object,
1515 guint prop_id,
1516 GValue *value,
1517 GParamSpec *pspec)
1518 {
1519 BraseroDrivePrivate *priv;
1520
1521 g_return_if_fail (BRASERO_IS_DRIVE (object));
1522
1523 priv = BRASERO_DRIVE_PRIVATE (object);
1524
1525 switch (prop_id)
1526 {
1527 case PROP_UDI:
1528 break;
1529 case PROP_GDRIVE:
1530 g_value_set_object (value, priv->gdrive);
1531 break;
1532 case PROP_DEVICE:
1533 g_value_set_string (value, priv->device);
1534 break;
1535 default:
1536 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1537 break;
1538 }
1539 }
1540
1541 static void
brasero_drive_init(BraseroDrive * object)1542 brasero_drive_init (BraseroDrive *object)
1543 {
1544 BraseroDrivePrivate *priv;
1545
1546 priv = BRASERO_DRIVE_PRIVATE (object);
1547 priv->cancel = g_cancellable_new ();
1548
1549 priv->mutex = g_mutex_new ();
1550 priv->cond = g_cond_new ();
1551 priv->cond_probe = g_cond_new ();
1552 }
1553
1554 static void
brasero_drive_finalize(GObject * object)1555 brasero_drive_finalize (GObject *object)
1556 {
1557 BraseroDrivePrivate *priv;
1558
1559 priv = BRASERO_DRIVE_PRIVATE (object);
1560
1561 BRASERO_MEDIA_LOG ("Finalizing BraseroDrive");
1562
1563 brasero_drive_cancel_probing (BRASERO_DRIVE (object));
1564
1565 if (priv->mutex) {
1566 g_mutex_free (priv->mutex);
1567 priv->mutex = NULL;
1568 }
1569
1570 if (priv->cond) {
1571 g_cond_free (priv->cond);
1572 priv->cond = NULL;
1573 }
1574
1575 if (priv->cond_probe) {
1576 g_cond_free (priv->cond_probe);
1577 priv->cond_probe = NULL;
1578 }
1579
1580 if (priv->medium) {
1581 g_signal_emit (object,
1582 drive_signals [MEDIUM_REMOVED],
1583 0,
1584 priv->medium);
1585 g_object_unref (priv->medium);
1586 priv->medium = NULL;
1587 }
1588
1589 if (priv->name) {
1590 g_free (priv->name);
1591 priv->name = NULL;
1592 }
1593
1594 if (priv->device) {
1595 g_free (priv->device);
1596 priv->device = NULL;
1597 }
1598
1599 if (priv->block_device) {
1600 g_free (priv->block_device);
1601 priv->block_device = NULL;
1602 }
1603
1604 if (priv->udi) {
1605 g_free (priv->udi);
1606 priv->udi = NULL;
1607 }
1608
1609 if (priv->gdrive) {
1610 g_signal_handlers_disconnect_by_func (priv->gdrive,
1611 brasero_drive_medium_gdrive_changed_cb,
1612 object);
1613 g_object_unref (priv->gdrive);
1614 priv->gdrive = NULL;
1615 }
1616
1617 if (priv->cancel) {
1618 g_cancellable_cancel (priv->cancel);
1619 g_object_unref (priv->cancel);
1620 priv->cancel = NULL;
1621 }
1622
1623 G_OBJECT_CLASS (brasero_drive_parent_class)->finalize (object);
1624 }
1625
1626 static void
brasero_drive_class_init(BraseroDriveClass * klass)1627 brasero_drive_class_init (BraseroDriveClass *klass)
1628 {
1629 GObjectClass* object_class = G_OBJECT_CLASS (klass);
1630
1631 g_type_class_add_private (klass, sizeof (BraseroDrivePrivate));
1632
1633 object_class->finalize = brasero_drive_finalize;
1634 object_class->set_property = brasero_drive_set_property;
1635 object_class->get_property = brasero_drive_get_property;
1636
1637 /**
1638 * BraseroDrive::medium-added:
1639 * @drive: the object which received the signal
1640 * @medium: the new medium which was added
1641 *
1642 * This signal gets emitted when a new medium was detected
1643 *
1644 */
1645 drive_signals[MEDIUM_INSERTED] =
1646 g_signal_new ("medium_added",
1647 G_OBJECT_CLASS_TYPE (klass),
1648 G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE,
1649 G_STRUCT_OFFSET (BraseroDriveClass, medium_added),
1650 NULL, NULL,
1651 g_cclosure_marshal_VOID__OBJECT,
1652 G_TYPE_NONE, 1,
1653 BRASERO_TYPE_MEDIUM);
1654
1655 /**
1656 * BraseroDrive::medium-removed:
1657 * @drive: the object which received the signal
1658 * @medium: the medium which was removed
1659 *
1660 * This signal gets emitted when a medium is not longer available
1661 *
1662 */
1663 drive_signals[MEDIUM_REMOVED] =
1664 g_signal_new ("medium_removed",
1665 G_OBJECT_CLASS_TYPE (klass),
1666 G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE,
1667 G_STRUCT_OFFSET (BraseroDriveClass, medium_removed),
1668 NULL, NULL,
1669 g_cclosure_marshal_VOID__OBJECT,
1670 G_TYPE_NONE, 1,
1671 BRASERO_TYPE_MEDIUM);
1672
1673 g_object_class_install_property (object_class,
1674 PROP_UDI,
1675 g_param_spec_string("udi",
1676 "udi",
1677 "HAL udi as a string (Deprecated)",
1678 NULL,
1679 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
1680 g_object_class_install_property (object_class,
1681 PROP_GDRIVE,
1682 g_param_spec_object ("gdrive",
1683 "GDrive",
1684 "A GDrive object for the drive",
1685 G_TYPE_DRIVE,
1686 G_PARAM_READWRITE));
1687 g_object_class_install_property (object_class,
1688 PROP_DEVICE,
1689 g_param_spec_string ("device",
1690 "Device",
1691 "Device path for the drive",
1692 NULL,
1693 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
1694 }
1695
1696