1
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8; tab-width: 8 -*-
3
* Copyright (C) 2003 Novell, Inc.
4
* Copyright (C) 2003-2004 Red Hat, Inc.
5
* Copyright (C) 2005 William Jon McCann <mccann@jhu.edu>
6
* Copyright (C) 2008 Philippe Rouquier <bonfire-app@wanadoo.fr> (modified to work with brasero)
8
* This program is free software; you can redistribute it and/or
9
* modify it under the terms of the GNU General Public License as
10
* published by the Free Software Foundation; either version 2 of the
11
* License, or (at your option) any later version.
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
* General Public License for more details.
18
* You should have received a copy of the GNU General Public
19
* License along with this program; if not, write to the
20
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21
* Boston, MA 02111-1307, USA.
29
#include <glib/gi18n-lib.h>
32
#include <libnautilus-extension/nautilus-menu-provider.h>
33
#include <libnautilus-extension/nautilus-location-widget-provider.h>
35
#include "brasero-media.h"
36
#include "brasero-medium-monitor.h"
37
#include "brasero-drive.h"
38
#include "brasero-medium.h"
39
#include "nautilus-burn-bar.h"
41
#define BURN_URI "burn:///"
43
#define NAUTILUS_TYPE_DISC_BURN (nautilus_disc_burn_get_type ())
44
#define NAUTILUS_DISC_BURN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), NAUTILUS_TYPE_DISC_BURN, NautilusDiscBurn))
45
#define NAUTILUS_IS_DISC_BURN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), NAUTILUS_TYPE_DISC_BURN))
47
typedef struct _NautilusDiscBurnPrivate NautilusDiscBurnPrivate;
52
NautilusDiscBurnPrivate *priv;
57
GObjectClass parent_slot;
58
} NautilusDiscBurnClass;
60
#define NAUTILUS_DISC_BURN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NAUTILUS_TYPE_DISC_BURN, NautilusDiscBurnPrivate))
62
struct _NautilusDiscBurnPrivate
64
GFileMonitor *burn_monitor;
67
guint start_monitor_id;
68
guint empty_update_id;
73
static GType nautilus_disc_burn_get_type (void);
74
static void nautilus_disc_burn_register_type (GTypeModule *module);
76
static GObjectClass *parent_class;
78
//#define DEBUG_PRINT(format_MACRO,...) g_print (format_MACRO, ##__VA_ARGS__);
79
#define DEBUG_PRINT(format_MACRO,...)
82
launch_process (GPtrArray *argv, GtkWindow *parent)
88
if (parent && GTK_WIDGET (parent)->window) {
91
xid = gdk_x11_drawable_get_xid (GDK_DRAWABLE (GTK_WIDGET (parent)->window));
93
g_ptr_array_add (argv, g_strdup ("-x"));
94
g_ptr_array_add (argv, g_strdup_printf ("%d", xid));
99
g_ptr_array_add (argv, NULL);
100
args = (gchar **) g_ptr_array_free (argv, FALSE);
101
if (!g_spawn_async (NULL,
108
dialog = gtk_message_dialog_new (parent,
112
_("Unable to launch the cd burner application"));
114
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
118
gtk_dialog_run (GTK_DIALOG (dialog));
119
gtk_widget_destroy (dialog);
122
g_error_free (error);
129
launch_brasero_on_window (GtkWindow *window)
132
GPtrArray *argv = NULL;
134
argv = g_ptr_array_new ();
135
g_ptr_array_add (argv, g_build_filename (BINDIR, "brasero", NULL));
136
g_ptr_array_add (argv, g_strdup ("-n"));
138
launch_process (argv, window);
142
write_activate_cb (NautilusMenuItem *item,
145
launch_brasero_on_window (GTK_WINDOW (user_data));
149
write_iso_activate_cb (NautilusMenuItem *item,
152
NautilusFileInfo *file_info;
153
GPtrArray *argv = NULL;
158
file_info = g_object_get_data (G_OBJECT (item), "file_info");
160
uri = nautilus_file_info_get_uri (file_info);
161
image_path = g_filename_from_uri (uri, NULL, NULL);
163
if (image_path == NULL) {
164
g_warning ("Can not get local path for URI %s", uri);
171
argv = g_ptr_array_new ();
172
g_ptr_array_add (argv, g_build_filename (BINDIR, "brasero", NULL));
173
g_ptr_array_add (argv, g_strdup ("-i"));
174
g_ptr_array_add (argv, image_path);
176
launch_process (argv, GTK_WINDOW (user_data));
180
copy_disc_activate_cb (NautilusMenuItem *item,
184
GPtrArray *argv = NULL;
187
device_path = g_object_get_data (G_OBJECT (item), "drive_device_path");
190
g_warning ("Drive device path not specified");
194
argv = g_ptr_array_new ();
195
g_ptr_array_add (argv, g_build_filename (BINDIR, "brasero", NULL));
196
g_ptr_array_add (argv, g_strdup ("-c"));
197
g_ptr_array_add (argv, g_strdup (device_path));
199
launch_process (argv, GTK_WINDOW (user_data));
203
blank_disc_activate_cb (NautilusMenuItem *item,
207
GPtrArray *argv = NULL;
210
device_path = g_object_get_data (G_OBJECT (item), "drive_device_path");
213
g_warning ("Drive device path not specified");
217
argv = g_ptr_array_new ();
218
g_ptr_array_add (argv, g_build_filename (BINDIR, "brasero", NULL));
219
g_ptr_array_add (argv, g_strdup ("-b"));
220
g_ptr_array_add (argv, g_strdup (device_path));
222
launch_process (argv, GTK_WINDOW (user_data));
226
check_disc_activate_cb (NautilusMenuItem *item,
230
GPtrArray *argv = NULL;
233
device_path = g_object_get_data (G_OBJECT (item), "drive_device_path");
236
g_warning ("Drive device path not specified");
240
argv = g_ptr_array_new ();
241
g_ptr_array_add (argv, g_build_filename (BINDIR, "brasero", NULL));
242
g_ptr_array_add (argv, g_strdup ("-k"));
243
g_ptr_array_add (argv, g_strdup (device_path));
245
launch_process (argv, GTK_WINDOW (user_data));
249
volume_is_blank (GVolume *volume)
251
BraseroMediumMonitor *monitor;
252
BraseroMedium *medium;
259
device = g_volume_get_identifier (volume, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE);
263
DEBUG_PRINT ("Got device: %s\n", device);
265
monitor = brasero_medium_monitor_get_default ();
266
drive = brasero_medium_monitor_get_drive (monitor, device);
267
g_object_unref (monitor);
273
medium = brasero_drive_get_medium (drive);
274
is_blank = (brasero_medium_get_status (medium) & BRASERO_MEDIUM_BLANK);
275
g_object_unref (drive);
281
drive_get_first_volume (GDrive *drive)
286
volumes = g_drive_get_volumes (drive);
288
volume = g_list_nth_data (volumes, 0);
290
if (volume != NULL) {
291
g_object_ref (volume);
294
g_list_foreach (volumes, (GFunc) g_object_unref, NULL);
295
g_list_free (volumes);
301
drive_is_cd_device (GDrive *gdrive)
303
BraseroMediumMonitor *monitor;
307
device = g_drive_get_identifier (gdrive, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE);
311
DEBUG_PRINT ("Got device: %s\n", device);
313
monitor = brasero_medium_monitor_get_default ();
314
drive = brasero_medium_monitor_get_drive (monitor, device);
315
g_object_unref (monitor);
321
g_object_unref (drive);
326
nautilus_disc_burn_get_file_items (NautilusMenuProvider *provider,
331
NautilusMenuItem *item;
332
NautilusFileInfo *file_info;
340
DEBUG_PRINT ("Getting file items\n");
342
if (!selection || selection->next != NULL) {
346
file_info = NAUTILUS_FILE_INFO (selection->data);
348
if (nautilus_file_info_is_gone (file_info)) {
352
file = nautilus_file_info_get_location (file_info);
355
DEBUG_PRINT ("No file found\n");
359
mime_type = nautilus_file_info_get_mime_type (file_info);
360
DEBUG_PRINT ("Mime type: %s\n", mime_type);
362
g_object_unref (file);
366
is_iso = (strcmp (mime_type, "application/x-iso-image") == 0)
367
|| (strcmp (mime_type, "application/x-cd-image") == 0)
368
|| (strcmp (mime_type, "application/x-cue") == 0)
369
|| (strcmp (mime_type, "application/x-toc") == 0)
370
|| (strcmp (mime_type, "application/x-cdrdao-toc") == 0);
373
/* Whether or not this file is local is not a problem */
374
item = nautilus_menu_item_new ("NautilusDiscBurn::write_iso",
375
_("_Write to Disc..."),
376
_("Write disc image to a CD or DVD disc"),
377
"media-optical-data-new");
378
g_object_set_data (G_OBJECT (item), "file_info", file_info);
379
g_object_set_data (G_OBJECT (item), "window", window);
380
g_signal_connect (item, "activate",
381
G_CALLBACK (write_iso_activate_cb), window);
382
items = g_list_append (items, item);
386
* We handle two cases here. The selection is:
390
* This is because there is very little distinction between
391
* the two for CD/DVD media
397
mount = nautilus_file_info_get_mount (file_info);
399
drive = g_mount_get_drive (mount);
400
volume = g_mount_get_volume (mount);
402
char *uri = g_file_get_uri (file);
403
DEBUG_PRINT ("Mount not found: %s\n", uri);
407
if (drive == NULL && volume != NULL) {
409
drive = g_volume_get_drive (volume);
410
} else if (volume == NULL && drive != NULL) {
412
volume = drive_get_first_volume (drive);
413
if (volume == NULL) {
414
DEBUG_PRINT ("Volume not found\n");
420
&& drive_is_cd_device (drive)
421
&& ! volume_is_blank (volume)) {
424
device_path = g_volume_get_identifier (volume, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE);
426
/* user may want to copy it ... */
427
item = nautilus_menu_item_new ("NautilusDiscBurn::copy_disc",
429
_("Create a copy of this CD or DVD disc"),
430
"media-optical-copy");
431
g_object_set_data (G_OBJECT (item), "file_info", file_info);
432
g_object_set_data (G_OBJECT (item), "window", window);
433
g_object_set_data_full (G_OBJECT (item), "drive_device_path", g_strdup (device_path), g_free);
434
g_signal_connect (item, "activate",
435
G_CALLBACK (copy_disc_activate_cb), window);
436
items = g_list_append (items, item);
438
/* ... or if it's a rewritable medium to blank it ... */
439
item = nautilus_menu_item_new ("NautilusDiscBurn::blank_disc",
441
_("Blank this CD or DVD disc"),
442
"media-optical-blank");
443
g_object_set_data (G_OBJECT (item), "file_info", file_info);
444
g_object_set_data (G_OBJECT (item), "window", window);
445
g_object_set_data_full (G_OBJECT (item), "drive_device_path", g_strdup (device_path), g_free);
446
g_signal_connect (item, "activate",
447
G_CALLBACK (blank_disc_activate_cb), window);
448
items = g_list_append (items, item);
450
/* ... or verify medium. */
451
item = nautilus_menu_item_new ("NautilusDiscBurn::check_disc",
453
_("Check the data integrity on this CD or DVD disc"),
455
g_object_set_data (G_OBJECT (item), "file_info", file_info);
456
g_object_set_data (G_OBJECT (item), "window", window);
457
g_object_set_data_full (G_OBJECT (item), "drive_device_path", g_strdup (device_path), g_free);
458
g_signal_connect (item, "activate",
459
G_CALLBACK (check_disc_activate_cb), window);
460
items = g_list_append (items, item);
462
g_free (device_path);
465
g_object_unref (file);
468
g_object_unref (drive);
470
if (volume != NULL) {
471
g_object_unref (volume);
476
DEBUG_PRINT ("Items returned\n");
481
nautilus_disc_burn_get_background_items (NautilusMenuProvider *provider,
483
NautilusFileInfo *current_folder)
490
scheme = nautilus_file_info_get_uri_scheme (current_folder);
492
if (strcmp (scheme, "burn") == 0) {
493
NautilusMenuItem *item;
495
item = nautilus_menu_item_new ("NautilusDiscBurn::write_menu",
496
_("_Write to Disc..."),
497
_("Write contents to a CD or DVD disc"),
499
g_signal_connect (item, "activate",
500
G_CALLBACK (write_activate_cb),
502
items = g_list_append (items, item);
504
g_object_set (item, "sensitive", ! NAUTILUS_DISC_BURN (provider)->priv->empty, NULL);
513
nautilus_disc_burn_get_toolbar_items (NautilusMenuProvider *provider,
515
NautilusFileInfo *current_folder)
525
nautilus_disc_burn_menu_provider_iface_init (NautilusMenuProviderIface *iface)
527
iface->get_file_items = nautilus_disc_burn_get_file_items;
528
iface->get_background_items = nautilus_disc_burn_get_background_items;
529
iface->get_toolbar_items = nautilus_disc_burn_get_toolbar_items;
533
bar_activated_cb (NautilusDiscBurnBar *bar,
536
launch_brasero_on_window (GTK_WINDOW (data));
540
dir_is_empty (const char *uri)
543
GFileEnumerator *enumerator;
547
file = g_file_new_for_uri (uri);
550
enumerator = g_file_enumerate_children (file,
551
G_FILE_ATTRIBUTE_STANDARD_NAME ","
552
G_FILE_ATTRIBUTE_STANDARD_TYPE ","
553
G_FILE_ATTRIBUTE_ACCESS_CAN_READ,
557
if (enumerator == NULL) {
558
DEBUG_PRINT ("Could not open burn uri %s: %s\n",
561
g_error_free (error);
570
info = g_file_enumerator_next_file (enumerator, NULL, NULL);
575
g_object_unref (info);
581
g_object_unref (enumerator);
582
g_object_unref (file);
588
destroyed_callback (GtkWidget *widget,
589
NautilusDiscBurn *burn)
591
burn->priv->widget_list = g_slist_remove (burn->priv->widget_list, widget);
595
sense_widget (NautilusDiscBurn *burn,
598
gtk_widget_set_sensitive (widget, !burn->priv->empty);
600
burn->priv->widget_list = g_slist_prepend (burn->priv->widget_list, widget);
602
g_signal_connect (widget, "destroy",
603
G_CALLBACK (destroyed_callback),
608
nautilus_disc_burn_get_location_widget (NautilusLocationWidgetProvider *iface,
612
if (g_str_has_prefix (uri, "burn:")) {
614
NautilusDiscBurn *burn;
616
DEBUG_PRINT ("Get location widget for burn\n");
618
burn = NAUTILUS_DISC_BURN (iface);
620
bar = nautilus_disc_burn_bar_new ();
622
sense_widget (burn, nautilus_disc_burn_bar_get_button (NAUTILUS_DISC_BURN_BAR (bar)));
624
g_signal_connect (bar, "activate",
625
G_CALLBACK (bar_activated_cb),
628
gtk_widget_show (bar);
637
nautilus_disc_burn_location_widget_provider_iface_init (NautilusLocationWidgetProviderIface *iface)
639
iface->get_widget = nautilus_disc_burn_get_location_widget;
643
update_widget_sensitivity (GtkWidget *widget,
644
NautilusDiscBurn *burn)
646
gtk_widget_set_sensitive (widget, !burn->priv->empty);
650
update_empty_idle (NautilusDiscBurn *burn)
654
burn->priv->empty_update_id = 0;
656
is_empty = dir_is_empty (BURN_URI);
658
DEBUG_PRINT ("Dir is %s\n", is_empty ? "empty" : "not empty");
660
if (burn->priv->empty != is_empty) {
661
burn->priv->empty = is_empty;
663
g_slist_foreach (burn->priv->widget_list, (GFunc)update_widget_sensitivity, burn);
665
/* Trigger update for menu items */
666
nautilus_menu_provider_emit_items_updated_signal (NAUTILUS_MENU_PROVIDER (burn));
673
queue_update_empty (NautilusDiscBurn *burn)
675
if (burn->priv->empty_update_id != 0) {
676
g_source_remove (burn->priv->empty_update_id);
679
burn->priv->empty_update_id = g_idle_add ((GSourceFunc)update_empty_idle, burn);
683
burn_monitor_cb (GFileMonitor *monitor,
686
GFileMonitorEvent event_type,
687
NautilusDiscBurn *burn)
689
DEBUG_PRINT ("Monitor callback type %d\n", event_type);
691
/* only queue the action if it has a chance of changing the state */
692
if (event_type == G_FILE_MONITOR_EVENT_CREATED) {
693
if (burn->priv->empty) {
694
queue_update_empty (burn);
696
} else if (event_type == G_FILE_MONITOR_EVENT_DELETED) {
697
if (! burn->priv->empty) {
698
queue_update_empty (burn);
704
start_monitor (NautilusDiscBurn *burn)
709
file = g_file_new_for_uri (BURN_URI);
712
burn->priv->burn_monitor = g_file_monitor_directory (file,
716
if (burn->priv->burn_monitor == NULL) {
717
g_warning ("Unable to add monitor: %s", error->message);
718
g_error_free (error);
722
DEBUG_PRINT ("Starting monitor for %s\n", BURN_URI);
723
g_signal_connect (burn->priv->burn_monitor,
725
G_CALLBACK (burn_monitor_cb),
728
burn->priv->empty = dir_is_empty (BURN_URI);
730
DEBUG_PRINT ("Init burn extension, empty: %d\n", burn->priv->empty);
733
g_object_unref (file);
735
burn->priv->start_monitor_id = 0;
741
nautilus_disc_burn_instance_init (NautilusDiscBurn *burn)
743
burn->priv = NAUTILUS_DISC_BURN_GET_PRIVATE (burn);
744
burn->priv->start_monitor_id = g_timeout_add_seconds (1,
745
(GSourceFunc)start_monitor,
750
nautilus_disc_burn_finalize (GObject *object)
752
NautilusDiscBurn *burn;
754
g_return_if_fail (object != NULL);
755
g_return_if_fail (NAUTILUS_IS_DISC_BURN (object));
757
DEBUG_PRINT ("Finalizing burn extension\n");
759
burn = NAUTILUS_DISC_BURN (object);
761
g_return_if_fail (burn->priv != NULL);
763
if (burn->priv->empty_update_id > 0) {
764
g_source_remove (burn->priv->empty_update_id);
767
if (burn->priv->start_monitor_id > 0) {
768
g_source_remove (burn->priv->start_monitor_id);
771
if (burn->priv->burn_monitor != NULL) {
772
g_file_monitor_cancel (burn->priv->burn_monitor);
775
if (burn->priv->widget_list != NULL) {
776
g_slist_free (burn->priv->widget_list);
779
G_OBJECT_CLASS (parent_class)->finalize (object);
783
nautilus_disc_burn_class_init (NautilusDiscBurnClass *klass)
785
GObjectClass *object_class = G_OBJECT_CLASS (klass);
787
parent_class = g_type_class_peek_parent (klass);
789
object_class->finalize = nautilus_disc_burn_finalize;
791
g_type_class_add_private (klass, sizeof (NautilusDiscBurnPrivate));
794
static GType burn_type = 0;
797
nautilus_disc_burn_get_type (void)
803
nautilus_disc_burn_register_type (GTypeModule *module)
805
static const GTypeInfo info = {
806
sizeof (NautilusDiscBurnClass),
807
(GBaseInitFunc) NULL,
808
(GBaseFinalizeFunc) NULL,
809
(GClassInitFunc) nautilus_disc_burn_class_init,
812
sizeof (NautilusDiscBurn),
814
(GInstanceInitFunc) nautilus_disc_burn_instance_init,
817
static const GInterfaceInfo menu_provider_iface_info = {
818
(GInterfaceInitFunc) nautilus_disc_burn_menu_provider_iface_init,
822
static const GInterfaceInfo location_widget_provider_iface_info = {
823
(GInterfaceInitFunc) nautilus_disc_burn_location_widget_provider_iface_init,
828
burn_type = g_type_module_register_type (module,
833
g_type_module_add_interface (module,
835
NAUTILUS_TYPE_MENU_PROVIDER,
836
&menu_provider_iface_info);
837
g_type_module_add_interface (module,
839
NAUTILUS_TYPE_LOCATION_WIDGET_PROVIDER,
840
&location_widget_provider_iface_info);
844
nautilus_module_initialize (GTypeModule *module)
846
DEBUG_PRINT ("Initializing nautilus disc recorder\n");
848
brasero_media_library_start ();
849
DEBUG_PRINT ("Libbrasero-media started\n");
851
nautilus_disc_burn_register_type (module);
855
nautilus_module_shutdown (void)
857
DEBUG_PRINT ("Shutting down nautilus disc recorder\n");
859
/* Don't do that in case another module would need the library */
860
//brasero_media_library_stop ();
864
nautilus_module_list_types (const GType **types,
867
static GType type_list [1];
869
type_list [0] = NAUTILUS_TYPE_DISC_BURN;