1
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
4
* Copyright (C) Philippe Rouquier 2005-2009 <bonfire-app@wanadoo.fr>
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.
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.
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.
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.
38
#include <glib/gi18n-lib.h>
42
#include <dbus/dbus.h>
43
#include <dbus/dbus-glib.h>
44
#include <dbus/dbus-glib-lowlevel.h>
48
#include "brasero-media-private.h"
50
#include "brasero-drive.h"
51
#include "brasero-medium.h"
52
#include "burn-hal-watch.h"
53
#include "brasero-medium-monitor.h"
55
typedef struct _BraseroMediumMonitorPrivate BraseroMediumMonitorPrivate;
56
struct _BraseroMediumMonitorPrivate
59
GVolumeMonitor *gmonitor;
64
#define BRASERO_MEDIUM_MONITOR_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), BRASERO_TYPE_MEDIUM_MONITOR, BraseroMediumMonitorPrivate))
77
static guint medium_monitor_signals[LAST_SIGNAL] = { 0 };
79
G_DEFINE_TYPE (BraseroMediumMonitor, brasero_medium_monitor, G_TYPE_OBJECT);
83
* These definitions go here as they shouldn't be public and they're used only
88
brasero_drive_new (const gchar *udi);
91
brasero_drive_probing (BraseroDrive *drive);
94
* brasero_medium_monitor_get_drive:
95
* @monitor: a #BraseroMediumMonitor
96
* @device: the path of the device
98
* Returns the #BraseroDrive object whose path is @path.
100
* Return value: a #BraseroDrive or NULL
103
brasero_medium_monitor_get_drive (BraseroMediumMonitor *monitor,
107
BraseroMediumMonitorPrivate *priv;
109
g_return_val_if_fail (monitor != NULL, NULL);
110
g_return_val_if_fail (BRASERO_IS_MEDIUM_MONITOR (monitor), NULL);
112
priv = BRASERO_MEDIUM_MONITOR_PRIVATE (monitor);
113
for (iter = priv->drives; iter; iter = iter->next) {
115
const gchar *drive_device;
118
drive_device = brasero_drive_get_device (drive);
119
if (drive_device && !strcmp (drive_device, device)) {
120
g_object_ref (drive);
129
* brasero_medium_monitor_is_probing:
130
* @monitor: a #BraseroMediumMonitor
132
* Returns if the library is still probing some other media.
134
* Return value: %TRUE if it is still probing some media
137
brasero_medium_monitor_is_probing (BraseroMediumMonitor *monitor)
140
BraseroMediumMonitorPrivate *priv;
142
g_return_val_if_fail (monitor != NULL, FALSE);
143
g_return_val_if_fail (BRASERO_IS_MEDIUM_MONITOR (monitor), FALSE);
145
priv = BRASERO_MEDIUM_MONITOR_PRIVATE (monitor);
147
for (iter = priv->drives; iter; iter = iter->next) {
151
if (brasero_drive_is_fake (drive))
154
if (brasero_drive_probing (drive))
162
* brasero_medium_monitor_get_drives:
163
* @monitor: a #BraseroMediumMonitor
164
* @type: a #BraseroDriveType to tell what type of drives to include in the list
166
* Gets the list of available drives that are of the given type.
168
* Return value: a #GSList or NULL
171
brasero_medium_monitor_get_drives (BraseroMediumMonitor *monitor,
172
BraseroDriveType type)
174
BraseroMediumMonitorPrivate *priv;
175
GSList *drives = NULL;
178
g_return_val_if_fail (monitor != NULL, NULL);
179
g_return_val_if_fail (BRASERO_IS_MEDIUM_MONITOR (monitor), NULL);
181
priv = BRASERO_MEDIUM_MONITOR_PRIVATE (monitor);
183
for (iter = priv->drives; iter; iter = iter->next) {
187
if (brasero_drive_is_fake (drive)) {
188
if (type & BRASERO_DRIVE_TYPE_FILE)
189
drives = g_slist_prepend (drives, drive);
194
if (brasero_drive_can_write (drive)
195
&& (type & BRASERO_DRIVE_TYPE_WRITER)) {
196
drives = g_slist_prepend (drives, drive);
200
if (type & BRASERO_DRIVE_TYPE_READER) {
201
drives = g_slist_prepend (drives, drive);
205
g_slist_foreach (drives, (GFunc) g_object_ref, NULL);
211
* brasero_medium_monitor_get_media:
212
* @monitor: a #BraseroMediumMonitor
213
* @type: the type of #BraseroMedium that should be in the list
215
* Obtains the list of available media that are of the given type.
217
* Return value: a #GSList or NULL
220
brasero_medium_monitor_get_media (BraseroMediumMonitor *monitor,
221
BraseroMediaType type)
225
BraseroMediumMonitorPrivate *priv;
227
g_return_val_if_fail (monitor != NULL, NULL);
228
g_return_val_if_fail (BRASERO_IS_MEDIUM_MONITOR (monitor), NULL);
230
priv = BRASERO_MEDIUM_MONITOR_PRIVATE (monitor);
232
for (iter = priv->drives; iter; iter = iter->next) {
233
BraseroMedium *medium;
238
medium = brasero_drive_get_medium (drive);
242
if ((type & BRASERO_MEDIA_TYPE_ANY_IN_BURNER)
243
&& (brasero_drive_can_write (drive))) {
244
list = g_slist_prepend (list, medium);
245
g_object_ref (medium);
249
if ((type & BRASERO_MEDIA_TYPE_AUDIO)
250
&& !(brasero_medium_get_status (medium) & BRASERO_MEDIUM_FILE)
251
&& (brasero_medium_get_status (medium) & BRASERO_MEDIUM_HAS_AUDIO)) {
252
list = g_slist_prepend (list, medium);
253
g_object_ref (medium);
257
if ((type & BRASERO_MEDIA_TYPE_DATA)
258
&& !(brasero_medium_get_status (medium) & BRASERO_MEDIUM_FILE)
259
&& (brasero_medium_get_status (medium) & BRASERO_MEDIUM_HAS_DATA)) {
260
list = g_slist_prepend (list, medium);
261
g_object_ref (medium);
265
if (type & BRASERO_MEDIA_TYPE_WRITABLE) {
266
if (brasero_medium_can_be_written (medium)) {
267
list = g_slist_prepend (list, medium);
268
g_object_ref (medium);
273
if (type & BRASERO_MEDIA_TYPE_REWRITABLE) {
274
if (brasero_medium_can_be_rewritten (medium)) {
275
list = g_slist_prepend (list, medium);
276
g_object_ref (medium);
281
if (type & BRASERO_MEDIA_TYPE_FILE) {
282
if (brasero_medium_get_status (medium) & BRASERO_MEDIUM_FILE) {
283
list = g_slist_prepend (list, medium);
284
g_object_ref (medium);
293
brasero_medium_monitor_medium_added_cb (BraseroDrive *drive,
294
BraseroMedium *medium,
295
BraseroMediumMonitor *self)
298
medium_monitor_signals [MEDIUM_INSERTED],
304
brasero_medium_monitor_medium_removed_cb (BraseroDrive *drive,
305
BraseroMedium *medium,
306
BraseroMediumMonitor *self)
309
medium_monitor_signals [MEDIUM_REMOVED],
315
brasero_medium_monitor_inserted_cb (BraseroHALWatch *watch,
317
BraseroMediumMonitor *self)
319
BraseroMediumMonitorPrivate *priv;
320
BraseroDrive *drive = NULL;
323
ctx = brasero_hal_watch_get_ctx (watch);
324
if (!libhal_device_query_capability (ctx, udi, "storage.cdrom", NULL))
327
BRASERO_MEDIA_LOG ("New drive added");
329
priv = BRASERO_MEDIUM_MONITOR_PRIVATE (self);
331
drive = brasero_drive_new (udi);
332
priv->drives = g_slist_prepend (priv->drives, drive);
334
/* connect to signals. This must come before the g_signal_emit () so we
335
* are the first to get an update on the medium inside. */
336
g_signal_connect (drive,
338
G_CALLBACK (brasero_medium_monitor_medium_added_cb),
340
g_signal_connect (drive,
342
G_CALLBACK (brasero_medium_monitor_medium_removed_cb),
346
medium_monitor_signals [DRIVE_ADDED],
350
/* check if a medium is inserted */
351
if (brasero_drive_get_medium (drive))
353
medium_monitor_signals [MEDIUM_INSERTED],
355
brasero_drive_get_medium (drive));
359
brasero_medium_monitor_removed_cb (BraseroHALWatch *watch,
361
BraseroMediumMonitor *self)
363
BraseroMediumMonitorPrivate *priv;
368
ctx = brasero_hal_watch_get_ctx (watch);
369
priv = BRASERO_MEDIUM_MONITOR_PRIVATE (self);
371
BRASERO_MEDIA_LOG ("Drive removed");
373
for (iter = priv->drives; iter; iter = next) {
374
const gchar *device_udi;
380
device_udi = brasero_drive_get_udi (drive);
384
if (!strcmp (device_udi, udi)) {
385
BraseroMedium *medium;
387
medium = brasero_drive_get_medium (drive);
390
medium_monitor_signals [MEDIUM_REMOVED],
394
priv->drives = g_slist_remove (priv->drives, drive);
396
medium_monitor_signals [DRIVE_REMOVED],
399
g_object_unref (drive);
405
brasero_medium_monitor_init (BraseroMediumMonitor *object)
411
char **devices = NULL;
412
BraseroHALWatch *watch;
413
BraseroMediumMonitorPrivate *priv;
415
priv = BRASERO_MEDIUM_MONITOR_PRIVATE (object);
417
/* This must done early on. GVolumeMonitor when it relies on HAL (like
418
* us) must be able to update its list of volumes before us so it must
419
* connect to HAL before us. */
420
priv->gmonitor = g_volume_monitor_get ();
422
watch = brasero_hal_watch_get_default ();
423
ctx = brasero_hal_watch_get_ctx (watch);
425
g_signal_connect (watch,
427
G_CALLBACK (brasero_medium_monitor_inserted_cb),
429
g_signal_connect (watch,
431
G_CALLBACK (brasero_medium_monitor_removed_cb),
434
/* Now we get the list and cache it */
435
dbus_error_init (&error);
436
BRASERO_MEDIA_LOG ("Polling for drives");
437
devices = libhal_find_device_by_capability (ctx,
438
"storage.cdrom", &nb_devices,
440
if (dbus_error_is_set (&error)) {
441
BRASERO_MEDIA_LOG ("Hal is not running : %s\n", error.message);
442
dbus_error_free (&error);
446
BRASERO_MEDIA_LOG ("Found %d drives", nb_devices);
447
for (i = 0; i < nb_devices; i++) {
448
/* create the drive */
449
BRASERO_MEDIA_LOG ("Probing %s", devices [i]);
450
drive = brasero_drive_new (devices [i]);
451
priv->drives = g_slist_prepend (priv->drives, drive);
453
g_signal_connect (drive,
455
G_CALLBACK (brasero_medium_monitor_medium_added_cb),
457
g_signal_connect (drive,
459
G_CALLBACK (brasero_medium_monitor_medium_removed_cb),
462
libhal_free_string_array (devices);
464
/* add fake/file drive */
465
drive = brasero_drive_new (NULL);
466
priv->drives = g_slist_prepend (priv->drives, drive);
472
brasero_medium_monitor_finalize (GObject *object)
474
BraseroMediumMonitorPrivate *priv;
476
priv = BRASERO_MEDIUM_MONITOR_PRIVATE (object);
479
g_slist_foreach (priv->drives, (GFunc) g_object_unref, NULL);
480
g_slist_free (priv->drives);
484
if (priv->gmonitor) {
485
g_object_unref (priv->gmonitor);
486
priv->gmonitor = NULL;
489
G_OBJECT_CLASS (brasero_medium_monitor_parent_class)->finalize (object);
493
brasero_medium_monitor_class_init (BraseroMediumMonitorClass *klass)
495
GObjectClass* object_class = G_OBJECT_CLASS (klass);
497
g_type_class_add_private (klass, sizeof (BraseroMediumMonitorPrivate));
499
object_class->finalize = brasero_medium_monitor_finalize;
502
* BraseroMediumMonitor::medium-added:
503
* @monitor: the object which received the signal
504
* @medium: the new medium which was added
506
* This signal gets emitted when a new medium was detected
508
medium_monitor_signals[MEDIUM_INSERTED] =
509
g_signal_new ("medium_added",
510
G_OBJECT_CLASS_TYPE (klass),
511
G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE,
512
G_STRUCT_OFFSET (BraseroMediumMonitorClass, medium_added),
514
g_cclosure_marshal_VOID__OBJECT,
516
BRASERO_TYPE_MEDIUM);
519
* BraseroMediumMonitor::medium-removed:
520
* @monitor: the object which received the signal
521
* @medium: the medium which was removed
523
* This signal gets emitted when a medium is not longer available
525
medium_monitor_signals[MEDIUM_REMOVED] =
526
g_signal_new ("medium_removed",
527
G_OBJECT_CLASS_TYPE (klass),
528
G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE,
529
G_STRUCT_OFFSET (BraseroMediumMonitorClass, medium_removed),
531
g_cclosure_marshal_VOID__OBJECT,
533
BRASERO_TYPE_MEDIUM);
536
* BraseroMediumMonitor::drive-added:
537
* @monitor: the object which received the signal
538
* @medium: the new medium which was added
540
* This signal gets emitted when a new drive was detected
542
medium_monitor_signals[DRIVE_ADDED] =
543
g_signal_new ("drive_added",
544
G_OBJECT_CLASS_TYPE (klass),
545
G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE,
546
G_STRUCT_OFFSET (BraseroMediumMonitorClass, drive_added),
548
g_cclosure_marshal_VOID__OBJECT,
553
* BraseroMediumMonitor::drive-removed:
554
* @monitor: the object which received the signal
555
* @medium: the medium which was removed
557
* This signal gets emitted when a drive is not longer available
559
medium_monitor_signals[DRIVE_REMOVED] =
560
g_signal_new ("drive_removed",
561
G_OBJECT_CLASS_TYPE (klass),
562
G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE,
563
G_STRUCT_OFFSET (BraseroMediumMonitorClass, drive_removed),
565
g_cclosure_marshal_VOID__OBJECT,
570
static BraseroMediumMonitor *singleton = NULL;
573
* brasero_medium_monitor_get_default:
575
* Gets the currently active monitor.
577
* Return value: a #BraseroMediumMonitor. Unref when it is not needed anymore.
579
BraseroMediumMonitor *
580
brasero_medium_monitor_get_default (void)
583
g_object_ref (singleton);
587
singleton = g_object_new (BRASERO_TYPE_MEDIUM_MONITOR, NULL);
589
/* keep a reference */
590
g_object_ref (singleton);