[rhythmbox/media-player-sync: 3/3] ipod: implement sync methods
- From: Jonathan Matthew <jmatthew src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [rhythmbox/media-player-sync: 3/3] ipod: implement sync methods
- Date: Sun, 27 Dec 2009 11:06:21 +0000 (UTC)
commit 8cc15c26af34f1fbe77e4a2113b037f45112bb6f
Author: Jonathan Matthew <jonathan d14n org>
Date: Sun Dec 27 20:54:48 2009 +1000
ipod: implement sync methods
Since the ipod plugin supports playlists, it implements the add_playlist
and remove_playlists methods as well as get_entries and delete_entries.
plugins/ipod/ipod-ui.xml | 2 +
plugins/ipod/rb-ipod-db.c | 11 ++-
plugins/ipod/rb-ipod-db.h | 1 +
plugins/ipod/rb-ipod-source.c | 210 ++++++++++++++++++++++---
plugins/ipod/rb-ipod-source.h | 13 +-
plugins/ipod/rb-ipod-static-playlist-source.c | 7 +-
6 files changed, 208 insertions(+), 36 deletions(-)
---
diff --git a/plugins/ipod/ipod-ui.xml b/plugins/ipod/ipod-ui.xml
index cdadb93..b9273de 100644
--- a/plugins/ipod/ipod-ui.xml
+++ b/plugins/ipod/ipod-ui.xml
@@ -1,6 +1,8 @@
<ui>
<popup name="iPodSourcePopup">
<placeholder name="iPodSrcPopupRename" action="iPodSourceRename"/>
+ <menuitem name="iPodSrcPopupSync" action="MediaPlayerSourceSync"/>
+ <separator />
<menuitem name="iPodSrcPopupPlaylistNew" action="iPodSourcePlaylistNew"/>
<separator />
<menuitem name="iPodSrcPopupEject" action="RemovableSourceEject"/>
diff --git a/plugins/ipod/rb-ipod-db.c b/plugins/ipod/rb-ipod-db.c
index 2eea1cb..6775dbf 100644
--- a/plugins/ipod/rb-ipod-db.c
+++ b/plugins/ipod/rb-ipod-db.c
@@ -873,7 +873,16 @@ rb_ipod_db_get_playlists (RbIpodDb *ipod_db)
{
RbIpodDbPrivate *priv = IPOD_DB_GET_PRIVATE (ipod_db);
- return priv->itdb->playlists;
+ return g_list_copy (priv->itdb->playlists);
+}
+
+Itdb_Playlist *
+rb_ipod_db_get_playlist_by_name (RbIpodDb *ipod_db,
+ gchar *name)
+{
+ RbIpodDbPrivate *priv = IPOD_DB_GET_PRIVATE (ipod_db);
+
+ return itdb_playlist_by_name (priv->itdb, name);
}
GList *
diff --git a/plugins/ipod/rb-ipod-db.h b/plugins/ipod/rb-ipod-db.h
index 729056f..27d30a7 100644
--- a/plugins/ipod/rb-ipod-db.h
+++ b/plugins/ipod/rb-ipod-db.h
@@ -72,6 +72,7 @@ void rb_ipod_db_set_ipod_name (RbIpodDb *db, const char *name);
const char *rb_ipod_db_get_ipod_name (RbIpodDb *db);
GList *rb_ipod_db_get_playlists (RbIpodDb *ipod_db);
+Itdb_Playlist *rb_ipod_db_get_playlist_by_name (RbIpodDb *ipod_db, gchar *name);
GList *rb_ipod_db_get_tracks (RbIpodDb *ipod_db);
const char *rb_ipod_db_get_mount_path (RbIpodDb *ipod_db);
Itdb_Device *rb_ipod_db_get_device (RbIpodDb *ipod_db);
diff --git a/plugins/ipod/rb-ipod-source.c b/plugins/ipod/rb-ipod-source.c
index ebd4cb0..617df71 100644
--- a/plugins/ipod/rb-ipod-source.c
+++ b/plugins/ipod/rb-ipod-source.c
@@ -49,6 +49,7 @@
#include "rhythmdb.h"
#include "rb-cut-and-paste-code.h"
#include "rb-media-player-source.h"
+#include "rb-media-player-sync-settings.h"
#include "rb-playlist-source.h"
#include "rb-playlist-manager.h"
#include "rb-podcast-manager.h"
@@ -93,6 +94,10 @@ static gboolean rb_ipod_song_artwork_add_cb (RhythmDB *db,
static guint64 impl_get_capacity (RBMediaPlayerSource *source);
static guint64 impl_get_free_space (RBMediaPlayerSource *source);
+static void impl_get_entries (RBMediaPlayerSource *source, const char *category, GHashTable *map);
+static void impl_delete_entries (RBMediaPlayerSource *source, GList *entries, RBMediaPlayerSourceDeleteCallback callback, gpointer callback_data, GDestroyNotify destroy_data);
+static void impl_add_playlist (RBMediaPlayerSource *source, gchar *name, GList *entries);
+static void impl_remove_playlists (RBMediaPlayerSource *source);
static void impl_show_properties (RBMediaPlayerSource *source, GtkWidget *info_box, GtkWidget *notebook);
static void rb_ipod_source_set_property (GObject *object,
@@ -104,6 +109,7 @@ static void rb_ipod_source_get_property (GObject *object,
GValue *value,
GParamSpec *pspec);
+
static RhythmDB *get_db_for_source (RBiPodSource *source);
struct _PlayedEntry {
@@ -174,8 +180,12 @@ rb_ipod_source_class_init (RBiPodSourceClass *klass)
source_class->impl_get_ui_actions = impl_get_ui_actions;
source_class->impl_can_paste = (RBSourceFeatureFunc) rb_true_function;
+ mps_class->impl_get_entries = impl_get_entries;
mps_class->impl_get_capacity = impl_get_capacity;
mps_class->impl_get_free_space = impl_get_free_space;
+ mps_class->impl_delete_entries = impl_delete_entries;
+ mps_class->impl_add_playlist = impl_add_playlist;
+ mps_class->impl_remove_playlists = impl_remove_playlists;
mps_class->impl_show_properties = impl_show_properties;
rms_class->impl_should_paste = rb_removable_media_source_should_paste_no_duplicate;
@@ -286,12 +296,15 @@ rb_ipod_source_constructed (GObject *object)
rb_ipod_load_songs (source);
- db = get_db_for_source (source);
- g_signal_connect_object (db,
+ db = get_db_for_source (source);
+ g_signal_connect_object (db,
"entry-extra-metadata-notify::rb:coverArt",
G_CALLBACK (rb_ipod_song_artwork_add_cb),
- RB_IPOD_SOURCE(source), 0);
+ source, 0);
+
g_object_unref (db);
+
+ rb_media_player_source_load (RB_MEDIA_PLAYER_SOURCE (source));
}
static void
@@ -450,7 +463,7 @@ playlist_track_added (GtkTreeModel *model, GtkTreePath *path,
rb_ipod_db_add_to_playlist (priv->ipod_db, ipod_pl, track);
}
-static void
+static RBIpodStaticPlaylistSource *
add_rb_playlist (RBiPodSource *source, Itdb_Playlist *playlist)
{
RBShell *shell;
@@ -506,6 +519,8 @@ add_rb_playlist (RBiPodSource *source, Itdb_Playlist *playlist)
priv->podcast_pl = playlist_source;
rb_shell_append_source (shell, RB_SOURCE (playlist_source), RB_SOURCE (source));
g_object_unref (shell);
+
+ return playlist_source;
}
static void
@@ -1039,6 +1054,7 @@ impl_get_ui_actions (RBSource *source)
GList *actions = NULL;
actions = g_list_prepend (actions, g_strdup ("RemovableSourceEject"));
+ actions = g_list_prepend (actions, g_strdup ("MediaPlayerSourceSync"));
return actions;
}
@@ -1062,21 +1078,57 @@ impl_show_popup (RBSource *source)
return TRUE;
}
-void
-rb_ipod_source_trash_entries (RBiPodSource *source, GList *entries)
+typedef struct {
+ RBMediaPlayerSource *source;
+ RBMediaPlayerSourceDeleteCallback callback;
+ gpointer callback_data;
+ GDestroyNotify destroy_data;
+ GList *files;
+} DeleteFileData;
+
+static gboolean
+delete_done_cb (DeleteFileData *data)
+{
+ if (data->callback) {
+ data->callback (data->source, data->callback_data);
+ }
+ if (data->destroy_data) {
+ data->destroy_data (data->callback_data);
+ }
+ g_object_unref (data->source);
+ rb_list_deep_free (data->files);
+ return FALSE;
+}
+
+static gpointer
+delete_thread (DeleteFileData *data)
+{
+ GList *i;
+ rb_debug ("deleting %d files", g_list_length (data->files));
+ for (i = data->files; i != NULL; i = i->next) {
+ g_unlink ((const char *)i->data);
+ }
+ rb_debug ("done deleting %d files", g_list_length (data->files));
+ g_idle_add ((GSourceFunc) delete_done_cb, data);
+ return NULL;
+}
+
+static void
+impl_delete_entries (RBMediaPlayerSource *source, GList *entries, RBMediaPlayerSourceDeleteCallback callback, gpointer cb_data, GDestroyNotify destroy_data)
{
RBiPodSourcePrivate *priv = IPOD_SOURCE_GET_PRIVATE (source);
- RhythmDB *db;
- GList *tem;
+ RhythmDB *db = get_db_for_source ((RBiPodSource *)source);
+ GList *i;
+ GList *filenames = NULL;
+ DeleteFileData *data = g_new0 (DeleteFileData, 1);
- db = get_db_for_source (source);
- for (tem = entries; tem != NULL; tem = tem->next) {
- RhythmDBEntry *entry;
- const gchar *uri;
- gchar *file;
+ for (i = entries; i != NULL; i = i->next) {
+ const char *uri;
+ char *filename;
Itdb_Track *track;
+ RhythmDBEntry *entry;
- entry = (RhythmDBEntry *)tem->data;
+ entry = i->data;
uri = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION);
track = g_hash_table_lookup (priv->entry_map, entry);
if (track == NULL) {
@@ -1086,15 +1138,24 @@ rb_ipod_source_trash_entries (RBiPodSource *source, GList *entries)
rb_ipod_db_remove_track (priv->ipod_db, track);
g_hash_table_remove (priv->entry_map, entry);
- file = g_filename_from_uri (uri, NULL, NULL);
- if (file != NULL)
- g_unlink (file);
- g_free (file);
+ filename = g_filename_from_uri (uri, NULL, NULL);
+
+ if (filename != NULL) {
+ filenames = g_list_prepend (filenames, filename);
+ }
rhythmdb_entry_delete (db, entry);
}
rhythmdb_commit (db);
g_object_unref (db);
+
+ data->source = g_object_ref (source);
+ data->callback = callback;
+ data->callback_data = cb_data;
+ data->destroy_data = destroy_data;
+ data->files = filenames;
+
+ g_thread_create ((GThreadFunc) delete_thread, data, FALSE, NULL);
}
static void
@@ -1105,10 +1166,53 @@ impl_move_to_trash (RBSource *source)
songs = rb_source_get_entry_view (source);
sel = rb_entry_view_get_selected_entries (songs);
- rb_ipod_source_trash_entries (RB_IPOD_SOURCE (source), sel);
+ impl_delete_entries (RB_MEDIA_PLAYER_SOURCE (source), sel, NULL, NULL, NULL);
+ rb_list_destroy_free (sel, (GDestroyNotify) rhythmdb_entry_unref);
+}
- g_list_foreach (sel, (GFunc) rhythmdb_entry_unref, NULL);
- g_list_free (sel);
+static void
+impl_add_playlist (RBMediaPlayerSource *source,
+ char *name,
+ GList *entries) /* GList of RhythmDBEntry * on the device to go into the playlist */
+{
+ RBiPodSourcePrivate *priv = IPOD_SOURCE_GET_PRIVATE (source);
+ RBIpodStaticPlaylistSource *playlist_source;
+ Itdb_Playlist *ipod_playlist;
+ GList *iter;
+
+ ipod_playlist = itdb_playlist_new (name, FALSE);
+ rb_ipod_db_add_playlist (priv->ipod_db, ipod_playlist);
+ playlist_source = add_rb_playlist (RB_IPOD_SOURCE (source), ipod_playlist);
+
+ for (iter = entries; iter != NULL; iter = iter->next) {
+ rb_static_playlist_source_add_entry (RB_STATIC_PLAYLIST_SOURCE (playlist_source), iter->data, -1);
+ }
+}
+
+static void
+impl_remove_playlists (RBMediaPlayerSource *source)
+{
+ RBiPodSourcePrivate *priv = IPOD_SOURCE_GET_PRIVATE (source);
+ GList *playlists;
+ GList *p;
+
+ playlists = rb_ipod_db_get_playlists (priv->ipod_db);
+
+ for (p = playlists; p != NULL; p = p->next) {
+ Itdb_Playlist *playlist = (Itdb_Playlist *)p->data;
+ /* XXX might need to exclude more playlists here.. */
+ if (!itdb_playlist_is_mpl (playlist) && !playlist->is_spl) {
+
+ /* destroy the playlist source */
+ RBSource *rb_playlist = RB_SOURCE (playlist->userdata);
+ rb_source_delete_thyself (rb_playlist);
+
+ /* remove playlist from ipod */
+ rb_ipod_db_remove_playlist (priv->ipod_db, playlist);
+ }
+ }
+
+ g_list_free (playlists);
}
static char *
@@ -1275,6 +1379,25 @@ request_artwork (RBiPodSource *isource,
}
}
+Itdb_Playlist *
+rb_ipod_source_get_playlist (RBiPodSource *source,
+ gchar *name)
+{
+ RBiPodSourcePrivate *priv = IPOD_SOURCE_GET_PRIVATE (source);
+ Itdb_Playlist *ipod_playlist;
+
+ ipod_playlist = rb_ipod_db_get_playlist_by_name (priv->ipod_db, name);
+
+ /* Playlist doesn't exist on the iPod, create it */
+ if (ipod_playlist == NULL) {
+ ipod_playlist = itdb_playlist_new (name, FALSE);
+ rb_ipod_db_add_playlist (priv->ipod_db, ipod_playlist);
+ add_rb_playlist (source, ipod_playlist);
+ }
+
+ return ipod_playlist;
+}
+
static void
add_to_podcasts (RBiPodSource *source, Itdb_Track *song)
{
@@ -1341,6 +1464,10 @@ impl_track_added (RBRemovableMediaSource *source,
}
g_object_unref (db);
+
+ /* chain up to parent class for sync */
+ RB_REMOVABLE_MEDIA_SOURCE_CLASS (rb_ipod_source_parent_class)->impl_track_added (source, entry, dest, filesize, mimetype);
+
return FALSE;
}
@@ -1603,6 +1730,7 @@ static void
impl_delete_thyself (RBSource *source)
{
RBiPodSourcePrivate *priv = IPOD_SOURCE_GET_PRIVATE (source);
+ RhythmDB *db;
GList *p;
if (priv->ipod_db == NULL) {
@@ -1610,6 +1738,12 @@ impl_delete_thyself (RBSource *source)
return;
}
+ db = get_db_for_source (RB_IPOD_SOURCE (source));
+ g_signal_handlers_disconnect_by_func (db,
+ G_CALLBACK (rb_ipod_song_artwork_add_cb),
+ RB_IPOD_SOURCE (source));
+ g_object_unref (db);
+
for (p = rb_ipod_db_get_playlists (priv->ipod_db);
p != NULL;
p = p->next) {
@@ -1650,8 +1784,7 @@ impl_get_mime_types (RBRemovableMediaSource *source)
return ret;
}
-
-void
+Itdb_Playlist *
rb_ipod_source_new_playlist (RBiPodSource *source)
{
RBiPodSourcePrivate *priv = IPOD_SOURCE_GET_PRIVATE (source);
@@ -1659,12 +1792,13 @@ rb_ipod_source_new_playlist (RBiPodSource *source)
if (priv->ipod_db == NULL) {
rb_debug ("can't create new ipod playlist with no ipod db");
- return;
+ return NULL;
}
ipod_playlist = itdb_playlist_new (_("New playlist"), FALSE);
rb_ipod_db_add_playlist (priv->ipod_db, ipod_playlist);
add_rb_playlist (source, ipod_playlist);
+ return ipod_playlist;
}
void
@@ -1817,3 +1951,31 @@ impl_get_free_space (RBMediaPlayerSource *source)
return rb_ipod_helpers_get_free_space (get_mount_point (RB_IPOD_SOURCE (source)));
}
+static void
+impl_get_entries (RBMediaPlayerSource *source, const char *category, GHashTable *map)
+{
+ RBiPodSourcePrivate *priv = IPOD_SOURCE_GET_PRIVATE (source);
+ GHashTableIter iter;
+ gpointer key, value;
+ Itdb_Mediatype media_type;
+
+ /* map the sync category to an itdb media type */
+ if (g_str_equal (category, SYNC_CATEGORY_MUSIC)) {
+ media_type = ITDB_MEDIATYPE_AUDIO;
+ } else if (g_str_equal (category, SYNC_CATEGORY_PODCAST)) {
+ media_type = ITDB_MEDIATYPE_PODCAST;
+ } else {
+ g_warning ("unsupported ipod sync category %s", category);
+ return;
+ }
+
+ /* extract all entries matching the media type for the sync category */
+ g_hash_table_iter_init (&iter, priv->entry_map);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ Itdb_Track *track = value;
+ if (track->mediatype == media_type) {
+ RhythmDBEntry *entry = key;
+ _rb_media_player_source_add_to_map (map, entry);
+ }
+ }
+}
diff --git a/plugins/ipod/rb-ipod-source.h b/plugins/ipod/rb-ipod-source.h
index f93ac4b..7d8bff4 100644
--- a/plugins/ipod/rb-ipod-source.h
+++ b/plugins/ipod/rb-ipod-source.h
@@ -33,6 +33,7 @@
#include "rhythmdb.h"
#include "rb-plugin.h"
#include "mediaplayerid.h"
+#include "rb-ipod-db.h"
G_BEGIN_DECLS
@@ -53,21 +54,19 @@ typedef struct
RBMediaPlayerSourceClass parent;
} RBiPodSourceClass;
-RBMediaPlayerSource *rb_ipod_source_new (RBPlugin *plugin,
+RBMediaPlayerSource *rb_ipod_source_new (RBPlugin *plugin,
RBShell *shell,
- GMount *mount,
+ GMount *mount,
MPIDDevice *device_info);
GType rb_ipod_source_get_type (void);
GType rb_ipod_source_register_type (GTypeModule *module);
-void rb_ipod_source_new_playlist (RBiPodSource *source);
+Itdb_Playlist * rb_ipod_source_new_playlist (RBiPodSource *source);
void rb_ipod_source_remove_playlist (RBiPodSource *ipod_source,
RBSource *source);
-void rb_ipod_source_show_properties (RBiPodSource *source);
-
-void rb_ipod_source_trash_entries (RBiPodSource *source,
- GList *entries);
+Itdb_Playlist * rb_ipod_source_get_playlist (RBiPodSource *source,
+ gchar *name);
G_END_DECLS
diff --git a/plugins/ipod/rb-ipod-static-playlist-source.c b/plugins/ipod/rb-ipod-static-playlist-source.c
index c5cb7c1..7e265d8 100644
--- a/plugins/ipod/rb-ipod-static-playlist-source.c
+++ b/plugins/ipod/rb-ipod-static-playlist-source.c
@@ -31,6 +31,7 @@
#include "rhythmdb.h"
#include "rb-ipod-static-playlist-source.h"
+#include "rb-media-player-source.h"
#include "rb-ipod-source.h"
static void rb_ipod_static_playlist_source_constructed (GObject *object);
@@ -274,9 +275,7 @@ impl_move_to_trash (RBSource *source)
songs = rb_source_get_entry_view (source);
sel = rb_entry_view_get_selected_entries (songs);
- rb_ipod_source_trash_entries (priv->ipod_source, sel);
-
- g_list_foreach (sel, (GFunc) rhythmdb_entry_unref, NULL);
- g_list_free (sel);
+ rb_media_player_source_delete_entries (RB_MEDIA_PLAYER_SOURCE (priv->ipod_source), sel, NULL, NULL, NULL);
+ rb_list_destroy_free (sel, (GDestroyNotify)rhythmdb_entry_unref);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]