1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * arch-tag: Implementation of Rhythmbox removable media manager
5 * Copyright (C) 2005 James Livingston <jrl@ids.org.au>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include <glib/gi18n.h>
28 #include <libgnomevfs/gnome-vfs.h>
30 #include "rb-removable-media-manager.h"
31 #include "rb-library-source.h"
32 #include "rb-sourcelist.h"
33 #include "rb-removable-media-source.h"
36 #include "rb-shell-player.h"
38 #include "rb-dialog.h"
39 #include "rb-stock-icons.h"
41 #include "rb-marshal.h"
44 #ifdef ENABLE_TRACK_TRANSFER
45 #include "rb-encoder.h"
48 static void rb_removable_media_manager_class_init (RBRemovableMediaManagerClass
*klass
);
49 static void rb_removable_media_manager_init (RBRemovableMediaManager
*mgr
);
50 static void rb_removable_media_manager_dispose (GObject
*object
);
51 static void rb_removable_media_manager_finalize (GObject
*object
);
52 static void rb_removable_media_manager_set_property (GObject
*object
,
56 static void rb_removable_media_manager_get_property (GObject
*object
,
61 static void rb_removable_media_manager_cmd_scan_media (GtkAction
*action
,
62 RBRemovableMediaManager
*manager
);
63 static void rb_removable_media_manager_cmd_eject_medium (GtkAction
*action
,
64 RBRemovableMediaManager
*mgr
);
65 static void rb_removable_media_manager_set_uimanager (RBRemovableMediaManager
*mgr
,
66 GtkUIManager
*uimanager
);
68 static void rb_removable_media_manager_append_media_source (RBRemovableMediaManager
*mgr
, RBRemovableMediaSource
*source
);
70 static void rb_removable_media_manager_mount_volume (RBRemovableMediaManager
*mgr
,
71 GnomeVFSVolume
*volume
);
72 static void rb_removable_media_manager_unmount_volume (RBRemovableMediaManager
*mgr
,
73 GnomeVFSVolume
*volume
);
75 static void rb_removable_media_manager_volume_mounted_cb (GnomeVFSVolumeMonitor
*monitor
,
76 GnomeVFSVolume
*volume
,
78 static void rb_removable_media_manager_volume_unmounted_cb (GnomeVFSVolumeMonitor
*monitor
,
79 GnomeVFSVolume
*volume
,
81 static gboolean
rb_removable_media_manager_load_media (RBRemovableMediaManager
*manager
);
83 #ifdef ENABLE_TRACK_TRANSFER
84 static void do_transfer (RBRemovableMediaManager
*manager
);
86 static void rb_removable_media_manager_cmd_copy_tracks (GtkAction
*action
,
87 RBRemovableMediaManager
*mgr
);
94 RBSourceList
*sourcelist
;
95 RBSource
*selected_source
;
97 GtkActionGroup
*actiongroup
;
98 GtkUIManager
*uimanager
;
101 GHashTable
*volume_mapping
;
102 GList
*cur_volume_list
;
105 GAsyncQueue
*transfer_queue
;
106 gboolean transfer_running
;
109 double transfer_fraction
;
110 } RBRemovableMediaManagerPrivate
;
112 G_DEFINE_TYPE (RBRemovableMediaManager
, rb_removable_media_manager
, G_TYPE_OBJECT
)
113 #define REMOVABLE_MEDIA_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), RB_TYPE_REMOVABLE_MEDIA_MANAGER, RBRemovableMediaManagerPrivate))
132 static guint rb_removable_media_manager_signals
[LAST_SIGNAL
] = { 0 };
134 static GtkActionEntry rb_removable_media_manager_actions
[] =
136 { "RemovableSourceEject", GNOME_MEDIA_EJECT
, N_("_Eject"), NULL
,
137 N_("Eject this medium"),
138 G_CALLBACK (rb_removable_media_manager_cmd_eject_medium
) },
139 { "RemovableSourceCopyAllTracks", GTK_STOCK_CDROM
, N_("_Copy to library"), NULL
,
140 N_("Copy all tracks to the library"),
141 G_CALLBACK (rb_removable_media_manager_cmd_copy_tracks
) },
142 { "MusicScanMedia", NULL
, N_("_Scan Removable Media"), NULL
,
143 N_("Scan for new Removable Media"),
144 G_CALLBACK (rb_removable_media_manager_cmd_scan_media
) },
146 static guint rb_removable_media_manager_n_actions
= G_N_ELEMENTS (rb_removable_media_manager_actions
);
149 rb_removable_media_manager_class_init (RBRemovableMediaManagerClass
*klass
)
151 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
153 object_class
->dispose
= rb_removable_media_manager_dispose
;
154 object_class
->finalize
= rb_removable_media_manager_finalize
;
155 object_class
->set_property
= rb_removable_media_manager_set_property
;
156 object_class
->get_property
= rb_removable_media_manager_get_property
;
158 g_object_class_install_property (object_class
,
160 g_param_spec_object ("source",
165 g_object_class_install_property (object_class
,
167 g_param_spec_object ("shell",
173 g_object_class_install_property (object_class
,
175 g_param_spec_object ("sourcelist",
179 G_PARAM_READWRITE
| G_PARAM_CONSTRUCT_ONLY
));
180 g_object_class_install_property (object_class
,
182 g_param_spec_boolean ("scanned",
184 "Whether a scan has been performed",
188 rb_removable_media_manager_signals
[MEDIUM_ADDED
] =
189 g_signal_new ("medium_added",
190 RB_TYPE_REMOVABLE_MEDIA_MANAGER
,
192 G_STRUCT_OFFSET (RBRemovableMediaManagerClass
, medium_added
),
194 g_cclosure_marshal_VOID__OBJECT
,
198 rb_removable_media_manager_signals
[TRANSFER_PROGRESS
] =
199 g_signal_new ("transfer-progress",
200 RB_TYPE_REMOVABLE_MEDIA_MANAGER
,
202 G_STRUCT_OFFSET (RBRemovableMediaManagerClass
, transfer_progress
),
204 rb_marshal_VOID__INT_INT_DOUBLE
,
206 3, G_TYPE_INT
, G_TYPE_INT
, G_TYPE_DOUBLE
);
208 rb_removable_media_manager_signals
[CREATE_SOURCE
] =
209 g_signal_new ("create-source",
210 RB_TYPE_REMOVABLE_MEDIA_MANAGER
,
212 G_STRUCT_OFFSET (RBRemovableMediaManagerClass
, create_source
),
213 rb_signal_accumulator_object_handled
, NULL
,
214 rb_marshal_OBJECT__OBJECT
,
216 1, GNOME_VFS_TYPE_VOLUME
);
218 g_type_class_add_private (klass
, sizeof (RBRemovableMediaManagerPrivate
));
222 rb_removable_media_manager_init (RBRemovableMediaManager
*mgr
)
224 RBRemovableMediaManagerPrivate
*priv
= REMOVABLE_MEDIA_MANAGER_GET_PRIVATE (mgr
);
226 priv
->volume_mapping
= g_hash_table_new (NULL
, NULL
);
227 priv
->transfer_queue
= g_async_queue_new ();
229 g_idle_add ((GSourceFunc
)rb_removable_media_manager_load_media
, mgr
);
233 rb_removable_media_manager_dispose (GObject
*object
)
235 RBRemovableMediaManager
*mgr
= RB_REMOVABLE_MEDIA_MANAGER (object
);
236 RBRemovableMediaManagerPrivate
*priv
= REMOVABLE_MEDIA_MANAGER_GET_PRIVATE (mgr
);
240 GnomeVFSVolumeMonitor
*monitor
= gnome_vfs_get_volume_monitor ();
242 g_signal_handlers_disconnect_by_func (G_OBJECT (monitor
),
243 G_CALLBACK (rb_removable_media_manager_volume_mounted_cb
),
245 g_signal_handlers_disconnect_by_func (G_OBJECT (monitor
),
246 G_CALLBACK (rb_removable_media_manager_volume_unmounted_cb
),
251 g_list_free (priv
->sources
);
252 priv
->sources
= NULL
;
255 priv
->disposed
= TRUE
;
257 G_OBJECT_CLASS (rb_removable_media_manager_parent_class
)->dispose (object
);
261 rb_removable_media_manager_finalize (GObject
*object
)
263 RBRemovableMediaManagerPrivate
*priv
= REMOVABLE_MEDIA_MANAGER_GET_PRIVATE (object
);
265 g_hash_table_destroy (priv
->volume_mapping
);
266 g_async_queue_unref (priv
->transfer_queue
);
268 G_OBJECT_CLASS (rb_removable_media_manager_parent_class
)->finalize (object
);
272 rb_removable_media_manager_set_property (GObject
*object
,
277 RBRemovableMediaManagerPrivate
*priv
= REMOVABLE_MEDIA_MANAGER_GET_PRIVATE (object
);
283 priv
->selected_source
= g_value_get_object (value
);
288 GtkUIManager
*uimanager
;
290 priv
->shell
= g_value_get_object (value
);
291 g_object_get (priv
->shell
,
292 "ui-manager", &uimanager
,
294 rb_removable_media_manager_set_uimanager (RB_REMOVABLE_MEDIA_MANAGER (object
), uimanager
);
295 g_object_unref (uimanager
);
298 case PROP_SOURCELIST
:
299 priv
->sourcelist
= g_value_get_object (value
);
302 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
308 rb_removable_media_manager_get_property (GObject
*object
,
313 RBRemovableMediaManagerPrivate
*priv
= REMOVABLE_MEDIA_MANAGER_GET_PRIVATE (object
);
318 g_value_set_object (value
, priv
->selected_source
);
321 g_value_set_object (value
, priv
->shell
);
323 case PROP_SOURCELIST
:
324 g_value_set_object (value
, priv
->sourcelist
);
327 g_value_set_boolean (value
, priv
->scanned
);
330 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
335 RBRemovableMediaManager
*
336 rb_removable_media_manager_new (RBShell
*shell
,
337 RBSourceList
*sourcelist
)
339 return g_object_new (RB_TYPE_REMOVABLE_MEDIA_MANAGER
,
341 "sourcelist", sourcelist
,
346 rb_removable_media_manager_load_media (RBRemovableMediaManager
*manager
)
348 GnomeVFSVolumeMonitor
*monitor
= gnome_vfs_get_volume_monitor ();
350 GDK_THREADS_ENTER ();
353 * Monitor new (un)mounted file systems to look for new media
355 * both pre-unmount and unmounted callbacks are registered because it is
356 * better to do it before the unmount, but sometimes we don't get those
357 * (e.g. someone pressing the eject button on a cd drive). If we get the
358 * pre-unmount signal, the corrosponding unmounted signal is ignored
360 g_signal_connect (G_OBJECT (monitor
), "volume-mounted",
361 G_CALLBACK (rb_removable_media_manager_volume_mounted_cb
),
363 g_signal_connect (G_OBJECT (monitor
), "volume-pre-unmount",
364 G_CALLBACK (rb_removable_media_manager_volume_unmounted_cb
),
366 g_signal_connect (G_OBJECT (monitor
), "volume-unmounted",
367 G_CALLBACK (rb_removable_media_manager_volume_unmounted_cb
),
370 GDK_THREADS_LEAVE ();
375 rb_removable_media_manager_volume_mounted_cb (GnomeVFSVolumeMonitor
*monitor
,
376 GnomeVFSVolume
*volume
,
379 RBRemovableMediaManager
*mgr
= RB_REMOVABLE_MEDIA_MANAGER (data
);
381 rb_removable_media_manager_mount_volume (mgr
, volume
);
385 remove_volume_by_source (GnomeVFSVolume
*volume
, RBSource
*source
,
386 RBSource
*ref_source
)
388 return (ref_source
== source
);
392 rb_removable_media_manager_source_deleted_cb (RBSource
*source
, RBRemovableMediaManager
*mgr
)
394 RBRemovableMediaManagerPrivate
*priv
= REMOVABLE_MEDIA_MANAGER_GET_PRIVATE (mgr
);
396 rb_debug ("removing source %p", source
);
397 g_hash_table_foreach_remove (priv
->volume_mapping
,
398 (GHRFunc
)remove_volume_by_source
,
400 priv
->sources
= g_list_remove (priv
->sources
, source
);
404 rb_removable_media_manager_volume_unmounted_cb (GnomeVFSVolumeMonitor
*monitor
,
405 GnomeVFSVolume
*volume
,
408 RBRemovableMediaManager
*mgr
= RB_REMOVABLE_MEDIA_MANAGER (data
);
410 g_assert (volume
!= NULL
);
411 rb_removable_media_manager_unmount_volume (mgr
, volume
);
415 rb_removable_media_manager_mount_volume (RBRemovableMediaManager
*mgr
, GnomeVFSVolume
*volume
)
417 RBRemovableMediaManagerPrivate
*priv
= REMOVABLE_MEDIA_MANAGER_GET_PRIVATE (mgr
);
418 RBRemovableMediaSource
*source
= NULL
;
419 char *fs_type
, *device_path
, *display_name
, *hal_udi
, *icon_name
;
420 GnomeVFSDeviceType device_type
;
422 g_assert (volume
!= NULL
);
424 if (g_hash_table_lookup (priv
->volume_mapping
, volume
) != NULL
)
427 if (!gnome_vfs_volume_is_mounted (volume
))
430 /* ignore network volumes */
431 device_type
= gnome_vfs_volume_get_device_type (volume
);
432 if (device_type
== GNOME_VFS_DEVICE_TYPE_NFS
||
433 device_type
== GNOME_VFS_DEVICE_TYPE_AUTOFS
||
434 device_type
== GNOME_VFS_DEVICE_TYPE_SMB
||
435 device_type
== GNOME_VFS_DEVICE_TYPE_NETWORK
)
438 fs_type
= gnome_vfs_volume_get_filesystem_type (volume
);
439 device_path
= gnome_vfs_volume_get_device_path (volume
);
440 display_name
= gnome_vfs_volume_get_display_name (volume
);
441 hal_udi
= gnome_vfs_volume_get_hal_udi (volume
);
442 icon_name
= gnome_vfs_volume_get_icon (volume
);
443 rb_debug ("detecting new media - device type=%d", device_type
);
444 rb_debug ("detecting new media - volume type=%d", gnome_vfs_volume_get_volume_type (volume
));
445 rb_debug ("detecting new media - fs type=%s", fs_type
);
446 rb_debug ("detecting new media - device path=%s", device_path
);
447 rb_debug ("detecting new media - display name=%s", display_name
);
448 rb_debug ("detecting new media - hal udi=%s", hal_udi
);
449 rb_debug ("detecting new media - icon=%s", icon_name
);
451 /* rb_xxx_source_new first checks if the 'volume' parameter corresponds
452 * to a medium of type 'xxx', and returns NULL if it doesn't.
453 * When volume is of the appropriate type, it creates a new source
454 * to handle this volume
457 g_signal_emit (G_OBJECT (mgr
), rb_removable_media_manager_signals
[CREATE_SOURCE
], 0,
461 g_hash_table_insert (priv
->volume_mapping
, volume
, source
);
462 rb_removable_media_manager_append_media_source (mgr
, source
);
464 rb_debug ("Unhandled media");
468 g_free (device_path
);
469 g_free (display_name
);
475 rb_removable_media_manager_unmount_volume (RBRemovableMediaManager
*mgr
, GnomeVFSVolume
*volume
)
477 RBRemovableMediaManagerPrivate
*priv
= REMOVABLE_MEDIA_MANAGER_GET_PRIVATE (mgr
);
478 RBRemovableMediaSource
*source
;
480 g_assert (volume
!= NULL
);
482 rb_debug ("media removed");
483 source
= g_hash_table_lookup (priv
->volume_mapping
, volume
);
485 rb_source_delete_thyself (RB_SOURCE (source
));
490 rb_removable_media_manager_append_media_source (RBRemovableMediaManager
*mgr
, RBRemovableMediaSource
*source
)
492 RBRemovableMediaManagerPrivate
*priv
= REMOVABLE_MEDIA_MANAGER_GET_PRIVATE (mgr
);
494 priv
->sources
= g_list_prepend (priv
->sources
, source
);
495 g_signal_connect_object (G_OBJECT (source
), "deleted",
496 G_CALLBACK (rb_removable_media_manager_source_deleted_cb
), mgr
, 0);
498 g_signal_emit (G_OBJECT (mgr
), rb_removable_media_manager_signals
[MEDIUM_ADDED
], 0,
503 rb_removable_media_manager_set_uimanager (RBRemovableMediaManager
*mgr
,
504 GtkUIManager
*uimanager
)
506 RBRemovableMediaManagerPrivate
*priv
= REMOVABLE_MEDIA_MANAGER_GET_PRIVATE (mgr
);
508 if (priv
->uimanager
!= NULL
) {
509 if (priv
->actiongroup
!= NULL
) {
510 gtk_ui_manager_remove_action_group (priv
->uimanager
,
513 g_object_unref (G_OBJECT (priv
->uimanager
));
514 priv
->uimanager
= NULL
;
517 priv
->uimanager
= uimanager
;
519 if (priv
->uimanager
!= NULL
) {
520 g_object_ref (priv
->uimanager
);
523 if (priv
->actiongroup
== NULL
) {
524 priv
->actiongroup
= gtk_action_group_new ("RemovableMediaActions");
525 gtk_action_group_set_translation_domain (priv
->actiongroup
,
527 gtk_action_group_add_actions (priv
->actiongroup
,
528 rb_removable_media_manager_actions
,
529 rb_removable_media_manager_n_actions
,
533 #ifndef ENABLE_TRACK_TRANSFER
537 action
= gtk_action_group_get_action (priv
->actiongroup
, "RemovableSourceCopyAllTracks");
538 gtk_action_set_visible (action
, FALSE
);
542 gtk_ui_manager_insert_action_group (priv
->uimanager
,
548 rb_removable_media_manager_eject_medium_cb (gboolean succeeded
,
550 const char *detailed_error
,
556 rb_error_dialog (NULL
, error
, "%s", detailed_error
);
560 rb_removable_media_manager_cmd_eject_medium (GtkAction
*action
, RBRemovableMediaManager
*mgr
)
562 RBRemovableMediaManagerPrivate
*priv
= REMOVABLE_MEDIA_MANAGER_GET_PRIVATE (mgr
);
563 RBRemovableMediaSource
*source
= RB_REMOVABLE_MEDIA_SOURCE (priv
->selected_source
);
564 GnomeVFSVolume
*volume
;
566 g_object_get (source
, "volume", &volume
, NULL
);
567 rb_removable_media_manager_unmount_volume (mgr
, volume
);
568 gnome_vfs_volume_eject (volume
, (GnomeVFSVolumeOpCallback
)rb_removable_media_manager_eject_medium_cb
, mgr
);
569 gnome_vfs_volume_unref (volume
);
573 rb_removable_media_manager_cmd_scan_media (GtkAction
*action
, RBRemovableMediaManager
*manager
)
575 rb_removable_media_manager_scan (manager
);
578 struct VolumeCheckData
580 RBRemovableMediaManager
*manager
;
582 GList
*volumes_to_remove
;
586 rb_removable_media_manager_check_volume (GnomeVFSVolume
*volume
,
587 RBRemovableMediaSource
*source
,
588 struct VolumeCheckData
*check_data
)
590 /* if the volume is no longer present, queue it for removal */
591 if (g_list_find (check_data
->volume_list
, volume
) == NULL
)
592 check_data
->volumes_to_remove
= g_list_prepend (check_data
->volumes_to_remove
, volume
);
596 rb_removable_media_manager_unmount_volume_swap (GnomeVFSVolume
*volume
, RBRemovableMediaManager
*manager
)
598 rb_removable_media_manager_unmount_volume (manager
, volume
);
602 rb_removable_media_manager_scan (RBRemovableMediaManager
*manager
)
604 RBRemovableMediaManagerPrivate
*priv
= REMOVABLE_MEDIA_MANAGER_GET_PRIVATE (manager
);
605 GnomeVFSVolumeMonitor
*monitor
= gnome_vfs_get_volume_monitor ();
607 GnomeVFSVolume
*volume
;
608 struct VolumeCheckData check_data
;
610 priv
->scanned
= TRUE
;
612 list
= gnome_vfs_volume_monitor_get_mounted_volumes (monitor
);
614 /* see if any removable media has gone */
615 check_data
.volume_list
= list
;
616 check_data
.manager
= manager
;
617 check_data
.volumes_to_remove
= NULL
;
618 g_hash_table_foreach (priv
->volume_mapping
,
619 (GHFunc
) rb_removable_media_manager_check_volume
,
621 g_list_foreach (check_data
.volumes_to_remove
,
622 (GFunc
) rb_removable_media_manager_unmount_volume_swap
,
624 g_list_free (check_data
.volumes_to_remove
);
626 /* look for new volume media */
627 for (it
= list
; it
!= NULL
; it
= g_list_next (it
)) {
628 volume
= GNOME_VFS_VOLUME (it
->data
);
629 rb_removable_media_manager_mount_volume (manager
, volume
);
630 gnome_vfs_volume_unref (volume
);
635 #ifdef ENABLE_TRACK_TRANSFER
639 RBRemovableMediaManager
*manager
;
640 RhythmDBEntry
*entry
;
644 RBTranferCompleteCallback callback
;
649 emit_progress (RBRemovableMediaManager
*mgr
)
651 RBRemovableMediaManagerPrivate
*priv
= REMOVABLE_MEDIA_MANAGER_GET_PRIVATE (mgr
);
653 g_signal_emit (G_OBJECT (mgr
), rb_removable_media_manager_signals
[TRANSFER_PROGRESS
], 0,
655 priv
->transfer_total
,
656 priv
->transfer_fraction
);
660 error_cb (RBEncoder
*encoder
, GError
*error
, TransferData
*data
)
662 rb_debug ("Error transferring track to %s: %s", data
->dest
, error
->message
);
663 rb_error_dialog (NULL
, _("Error transferring track"), "%s", error
->message
);
666 rb_encoder_cancel (encoder
);
670 progress_cb (RBEncoder
*encoder
, double fraction
, TransferData
*data
)
672 RBRemovableMediaManagerPrivate
*priv
= REMOVABLE_MEDIA_MANAGER_GET_PRIVATE (data
->manager
);
674 rb_debug ("transfer progress %f", (float)fraction
);
675 priv
->transfer_fraction
= fraction
;
676 emit_progress (data
->manager
);
680 completed_cb (RBEncoder
*encoder
, TransferData
*data
)
682 RBRemovableMediaManagerPrivate
*priv
= REMOVABLE_MEDIA_MANAGER_GET_PRIVATE (data
->manager
);
684 rb_debug ("completed transferring track to %s", data
->dest
);
686 (data
->callback
) (data
->entry
, data
->dest
, data
->userdata
);
688 priv
->transfer_running
= FALSE
;
689 priv
->transfer_done
++;
690 priv
->transfer_fraction
= 0.0;
691 do_transfer (data
->manager
);
693 g_object_unref (G_OBJECT (encoder
));
695 g_free (data
->mime_type
);
700 do_transfer (RBRemovableMediaManager
*manager
)
702 RBRemovableMediaManagerPrivate
*priv
= REMOVABLE_MEDIA_MANAGER_GET_PRIVATE (manager
);
706 g_assert (rb_is_main_thread ());
708 emit_progress (manager
);
710 if (priv
->transfer_running
)
713 data
= g_async_queue_try_pop (priv
->transfer_queue
);
715 priv
->transfer_total
= 0;
716 priv
->transfer_done
= 0;
717 emit_progress (manager
);
721 priv
->transfer_running
= TRUE
;
722 priv
->transfer_fraction
= 0.0;
724 encoder
= rb_encoder_new ();
725 g_signal_connect (G_OBJECT (encoder
),
726 "error", G_CALLBACK (error_cb
),
728 g_signal_connect (G_OBJECT (encoder
),
729 "progress", G_CALLBACK (progress_cb
),
731 g_signal_connect (G_OBJECT (encoder
),
732 "completed", G_CALLBACK (completed_cb
),
734 rb_encoder_encode (encoder
, data
->entry
, data
->dest
, NULL
);
738 rb_removable_media_manager_queue_transfer (RBRemovableMediaManager
*manager
,
739 RhythmDBEntry
*entry
,
741 const char *mime_type
,
742 RBTranferCompleteCallback callback
,
745 RBRemovableMediaManagerPrivate
*priv
= REMOVABLE_MEDIA_MANAGER_GET_PRIVATE (manager
);
748 g_assert (rb_is_main_thread ());
750 data
= g_new0 (TransferData
, 1);
751 data
->manager
= manager
;
753 data
->dest
= g_strdup (dest
);
754 data
->mime_type
= g_strdup (mime_type
);
755 data
->callback
= callback
;
756 data
->userdata
= userdata
;
758 g_async_queue_push (priv
->transfer_queue
, data
);
759 priv
->transfer_total
++;
760 do_transfer (manager
);
764 copy_entry (RhythmDBQueryModel
*model
,
770 l
= g_list_append (*list
, rhythmdb_query_model_iter_to_entry (model
, iter
));
777 rb_removable_media_manager_cmd_copy_tracks (GtkAction
*action
, RBRemovableMediaManager
*mgr
)
779 #ifdef ENABLE_TRACK_TRANSFER
780 RBRemovableMediaManagerPrivate
*priv
= REMOVABLE_MEDIA_MANAGER_GET_PRIVATE (mgr
);
781 RBRemovableMediaSource
*source
;
782 RBLibrarySource
*library
;
783 RhythmDBQueryModel
*model
;
786 source
= RB_REMOVABLE_MEDIA_SOURCE (priv
->selected_source
);
787 g_object_get (source
, "query-model", &model
, NULL
);
788 g_object_get (priv
->shell
, "library-source", &library
, NULL
);
790 gtk_tree_model_foreach (GTK_TREE_MODEL (model
), (GtkTreeModelForeachFunc
)copy_entry
, &list
);
791 rb_source_paste (RB_SOURCE (library
), list
);
794 g_object_unref (model
);
795 g_object_unref (library
);