[rhythmbox] ipod: update track order in the ipod db playlist before saving (bug #604170)
- From: Jonathan Matthew <jmatthew src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [rhythmbox] ipod: update track order in the ipod db playlist before saving (bug #604170)
- Date: Fri, 29 Oct 2010 07:44:00 +0000 (UTC)
commit fcb6157e0988188cc99d0a238cfe1bf6f21f3494
Author: Ben Walsh <b wumpster com>
Date: Thu Oct 28 13:25:37 2010 +0100
ipod: update track order in the ipod db playlist before saving (bug #604170)
When tracks in an ipod playlist have been reordered, update the ipod
db playlist to match the new order before saving.
To do this, add a new signal to RbIpodDb to allow other parts of the
plugin to update bits of the database immediately before it becomes
read-only.
plugins/ipod/rb-ipod-db.c | 29 ++++++
plugins/ipod/rb-ipod-source.c | 121 ++++++++++++++++++++++---
plugins/ipod/rb-ipod-static-playlist-source.c | 33 +++++++-
plugins/ipod/rb-ipod-static-playlist-source.h | 2 +
4 files changed, 170 insertions(+), 15 deletions(-)
---
diff --git a/plugins/ipod/rb-ipod-db.c b/plugins/ipod/rb-ipod-db.c
index 9121d44..0c59d58 100644
--- a/plugins/ipod/rb-ipod-db.c
+++ b/plugins/ipod/rb-ipod-db.c
@@ -118,6 +118,13 @@ G_DEFINE_TYPE (RbIpodDb, rb_ipod_db, G_TYPE_OBJECT)
#define IPOD_DB_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), RB_TYPE_IPOD_DB, RbIpodDbPrivate))
+enum {
+ BEFORE_SAVE,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+
static void
rb_itdb_save (RbIpodDb *ipod_db, GError **error)
{
@@ -209,6 +216,22 @@ rb_ipod_db_class_init (RbIpodDbClass *klass)
object_class->dispose = rb_ipod_db_dispose;
+ /**
+ * RbIpodDb::before-save
+ * @db: the #RbIpodDb
+ *
+ * Emitted before iPod database write to disk.
+ */
+ signals[BEFORE_SAVE] =
+ g_signal_new ("before-save",
+ RB_TYPE_IPOD_DB,
+ G_SIGNAL_RUN_FIRST,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
g_type_class_add_private (klass, sizeof (RbIpodDbPrivate));
}
@@ -846,6 +869,12 @@ save_timeout_cb (RbIpodDb *ipod_db)
g_warning ("Database is read-only, not saving");
return TRUE;
}
+
+ /* Tell everyone about the save */
+ g_signal_emit (G_OBJECT (ipod_db),
+ signals[BEFORE_SAVE],
+ 0);
+
rb_debug ("Starting iPod database save");
rb_debug ("Switching iPod database to read-only");
priv->read_only = TRUE;
diff --git a/plugins/ipod/rb-ipod-source.c b/plugins/ipod/rb-ipod-source.c
index 847551e..6e70494 100644
--- a/plugins/ipod/rb-ipod-source.c
+++ b/plugins/ipod/rb-ipod-source.c
@@ -471,7 +471,99 @@ playlist_track_added (GtkTreeModel *model, GtkTreePath *path,
rb_ipod_db_add_to_playlist (priv->ipod_db, ipod_pl, track);
}
-static void playlist_source_model_connect_signals (RBIpodStaticPlaylistSource *playlist_source)
+static void
+playlist_before_save (RbIpodDb *ipod_db, gpointer data)
+{
+ RBIpodStaticPlaylistSource *playlist = RB_IPOD_STATIC_PLAYLIST_SOURCE (data);
+ GtkTreeModel *model = GTK_TREE_MODEL (rb_playlist_source_get_query_model (RB_PLAYLIST_SOURCE (playlist)));
+ Itdb_Playlist *ipod_pl = rb_ipod_static_playlist_source_get_itdb_playlist (playlist);
+ RBiPodSource *ipod = rb_ipod_static_playlist_source_get_ipod_source (playlist);
+ RBiPodSourcePrivate *priv = IPOD_SOURCE_GET_PRIVATE (ipod);
+ GtkTreeIter iter;
+
+ if (!rb_ipod_static_playlist_source_get_was_reordered (playlist)) {
+ return;
+ }
+
+ rb_ipod_static_playlist_source_set_was_reordered (playlist, FALSE);
+
+ /* Sanity check that all tracks are in entry_map */
+
+ if (gtk_tree_model_get_iter_first (model, &iter)) {
+ do {
+ RhythmDBEntry *entry;
+ Itdb_Track *track;
+
+ gtk_tree_model_get (model, &iter, 0, &entry, -1);
+ track = g_hash_table_lookup (priv->entry_map, entry);
+
+ g_return_if_fail (track != NULL);
+ } while (gtk_tree_model_iter_next (model, &iter));
+ }
+
+ /* Remove all tracks then re-add in correct order */
+
+ while (ipod_pl->members != NULL) {
+ Itdb_Track *track;
+
+ track = (Itdb_Track *)ipod_pl->members->data;
+
+ rb_debug ("removing \"%s\" from \"%s\"", track->title, ipod_pl->name);
+
+ /* Call directly to itdb to avoid scheduling another save */
+ itdb_playlist_remove_track (ipod_pl, track);
+ }
+
+ if (gtk_tree_model_get_iter_first (model, &iter)) {
+ do {
+ RhythmDBEntry *entry;
+ Itdb_Track *track;
+
+ gtk_tree_model_get (model, &iter, 0, &entry, -1);
+ track = g_hash_table_lookup (priv->entry_map, entry);
+
+ rb_debug ("adding \"%s\" to \"%s\"", track->title, ipod_pl->name);
+
+ /* Call directly to itdb to avoid scheduling another save */
+ itdb_playlist_add_track (ipod_pl, track, -1);
+ } while (gtk_tree_model_iter_next (model, &iter));
+ }
+}
+
+static void
+playlist_rows_reordered (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gint *order, gpointer data)
+{
+ RBIpodStaticPlaylistSource *playlist = RB_IPOD_STATIC_PLAYLIST_SOURCE (data);
+ RBiPodSource *ipod = rb_ipod_static_playlist_source_get_ipod_source (playlist);
+ RBiPodSourcePrivate *priv = IPOD_SOURCE_GET_PRIVATE (ipod);
+
+ /* Mark as reordered; will check before save */
+ rb_ipod_static_playlist_source_set_was_reordered (playlist, TRUE);
+
+ rb_ipod_db_save_async (priv->ipod_db);
+}
+
+static void
+playlist_source_model_disconnect_signals (GObject *model, RBIpodStaticPlaylistSource *playlist_source)
+{
+ g_return_if_fail (RB_IS_IPOD_STATIC_PLAYLIST_SOURCE (playlist_source));
+
+ g_signal_handlers_disconnect_by_func (model,
+ G_CALLBACK (playlist_track_added),
+ playlist_source);
+ g_signal_handlers_disconnect_by_func (model,
+ G_CALLBACK (playlist_track_removed),
+ playlist_source);
+ g_signal_handlers_disconnect_by_func (model,
+ G_CALLBACK (playlist_rows_reordered),
+ playlist_source);
+}
+
+static void
+playlist_source_model_connect_signals (RBIpodStaticPlaylistSource *playlist_source)
{
RhythmDBQueryModel *model;
@@ -485,24 +577,26 @@ static void playlist_source_model_connect_signals (RBIpodStaticPlaylistSource *p
g_signal_connect (model, "entry-removed",
G_CALLBACK (playlist_track_removed),
playlist_source);
+ g_signal_connect (model, "rows-reordered",
+ G_CALLBACK (playlist_rows_reordered),
+ playlist_source);
g_object_unref (model);
}
-static void playlist_source_model_changed (GObject *obj, GParamSpec *pspec, gpointer old_model)
+static void
+playlist_source_model_changed (GObject *obj, GParamSpec *pspec, gpointer old_model)
{
RBIpodStaticPlaylistSource *playlist_source;
rb_debug ("base model changed for iPod playlist");
playlist_source = RB_IPOD_STATIC_PLAYLIST_SOURCE (obj);
- g_signal_handlers_disconnect_by_func (G_OBJECT (old_model),
- G_CALLBACK (playlist_track_added),
- playlist_source);
- g_signal_handlers_disconnect_by_func (G_OBJECT (old_model),
- G_CALLBACK (playlist_track_removed),
- playlist_source);
+
+ playlist_source_model_disconnect_signals (G_OBJECT (old_model), playlist_source);
+
playlist_source_model_connect_signals (playlist_source);
}
+
static void
set_podcast_icon (RBIpodStaticPlaylistSource *source)
{
@@ -570,6 +664,9 @@ add_rb_playlist (RBiPodSource *source, Itdb_Playlist *playlist)
g_signal_connect (playlist_source, "notify::base-query-model",
G_CALLBACK (playlist_source_model_changed),
playlist_source);
+ g_signal_connect (priv->ipod_db, "before-save",
+ G_CALLBACK (playlist_before_save),
+ playlist_source);
g_object_unref (model);
playlist_source_model_connect_signals (playlist_source);
@@ -1831,12 +1928,8 @@ impl_delete_thyself (RBSource *source)
"base-query-model", &model, NULL);
/* remove these to ensure they aren't called during source deletion */
- g_signal_handlers_disconnect_by_func (model,
- G_CALLBACK (playlist_track_added),
- rb_playlist);
- g_signal_handlers_disconnect_by_func (model,
- G_CALLBACK (playlist_track_removed),
- rb_playlist);
+ playlist_source_model_disconnect_signals (G_OBJECT (model),
+ RB_IPOD_STATIC_PLAYLIST_SOURCE (rb_playlist));
g_object_unref (model);
rb_source_delete_thyself (rb_playlist);
diff --git a/plugins/ipod/rb-ipod-static-playlist-source.c b/plugins/ipod/rb-ipod-static-playlist-source.c
index d6b8171..b3bfed7 100644
--- a/plugins/ipod/rb-ipod-static-playlist-source.c
+++ b/plugins/ipod/rb-ipod-static-playlist-source.c
@@ -57,6 +57,7 @@ typedef struct
RbIpodDb *ipod_db;
Itdb_Playlist *itdb_playlist;
RBiPodSource *ipod_source;
+ gboolean was_reordered;
} RBIpodStaticPlaylistSourcePrivate;
RB_PLUGIN_DEFINE_TYPE(RBIpodStaticPlaylistSource,
@@ -69,7 +70,8 @@ enum {
PROP_0,
PROP_IPOD_SOURCE,
PROP_IPOD_DB,
- PROP_ITDB_PLAYLIST
+ PROP_ITDB_PLAYLIST,
+ PROP_WAS_REORDERED
};
@@ -114,6 +116,13 @@ rb_ipod_static_playlist_source_class_init (RBIpodStaticPlaylistSourceClass *klas
"itdb-playlist",
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (object_class,
+ PROP_WAS_REORDERED,
+ g_param_spec_pointer ("was-reordered",
+ "was-reordered",
+ "was-reordered",
+ G_PARAM_READWRITE));
+
g_type_class_add_private (klass, sizeof (RBIpodStaticPlaylistSourcePrivate));
}
@@ -196,6 +205,9 @@ rb_ipod_static_playlist_source_set_property (GObject *object,
case PROP_ITDB_PLAYLIST:
priv->itdb_playlist = g_value_get_pointer (value);
break;
+ case PROP_WAS_REORDERED:
+ priv->was_reordered = g_value_get_boolean (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -220,6 +232,9 @@ rb_ipod_static_playlist_source_get_property (GObject *object,
case PROP_ITDB_PLAYLIST:
g_value_set_pointer (value, priv->itdb_playlist);
break;
+ case PROP_WAS_REORDERED:
+ g_value_set_boolean (value, priv->was_reordered);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -243,6 +258,22 @@ rb_ipod_static_playlist_source_get_ipod_source (RBIpodStaticPlaylistSource *play
return priv->ipod_source;
}
+gboolean
+rb_ipod_static_playlist_source_get_was_reordered (RBIpodStaticPlaylistSource *playlist)
+{
+ RBIpodStaticPlaylistSourcePrivate *priv = IPOD_STATIC_PLAYLIST_SOURCE_GET_PRIVATE (playlist);
+
+ return priv->was_reordered;
+}
+
+void
+rb_ipod_static_playlist_source_set_was_reordered (RBIpodStaticPlaylistSource *playlist, gboolean was_reordered)
+{
+ RBIpodStaticPlaylistSourcePrivate *priv = IPOD_STATIC_PLAYLIST_SOURCE_GET_PRIVATE (playlist);
+
+ priv->was_reordered = was_reordered;
+}
+
static gboolean
impl_show_popup (RBSource *source)
{
diff --git a/plugins/ipod/rb-ipod-static-playlist-source.h b/plugins/ipod/rb-ipod-static-playlist-source.h
index 16f2ff3..b793806 100644
--- a/plugins/ipod/rb-ipod-static-playlist-source.h
+++ b/plugins/ipod/rb-ipod-static-playlist-source.h
@@ -56,6 +56,8 @@ RBIpodStaticPlaylistSource * rb_ipod_static_playlist_source_new (RBShell *shell,
Itdb_Playlist* rb_ipod_static_playlist_source_get_itdb_playlist (RBIpodStaticPlaylistSource *playlist);
RBiPodSource* rb_ipod_static_playlist_source_get_ipod_source (RBIpodStaticPlaylistSource *playlist);
+gboolean rb_ipod_static_playlist_source_get_was_reordered (RBIpodStaticPlaylistSource *playlist);
+void rb_ipod_static_playlist_source_set_was_reordered (RBIpodStaticPlaylistSource *playlist, gboolean was_reordered);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]