* looking for rhythmbox-devel@gnome.org--2004/rhythmbox--main--0.9--patch-146 to compare with
* comparing to rhythmbox-devel@gnome.org--2004/rhythmbox--main--0.9--patch-146
A  sources/rb-iriver-source.c
A  sources/rb-iriver-source.h
M  sources/Makefile.am
M  lib/rb-stock-icons.h
M  lib/rb-stock-icons.c
M  shell/rb-shell.c
M  configure.ac

* modified files

--- orig/configure.ac
+++ mod/configure.ac
@@ -110,6 +110,14 @@
 fi
 AM_CONDITIONAL(WITH_DASHBOARD, test x"$enable_dashboard" = xyes)
 
+dnl iRiver support
+AC_ARG_ENABLE(iriver,
+	      [  --enable-iriver	  Enable iRiver support (default disabled)],enable_iriver=yes,enable_iriver=no)
+if test "x$enable_iriver" = "xyes" ; then
+   AC_DEFINE([WITH_IRIVER_SUPPORT], 1, [Define to enable support for iRiver])
+fi
+AM_CONDITIONAL(WITH_IRIVER_SUPPORT, test x"$enable_iriver" = xyes)
+
 dnl Sound system
 AC_ARG_WITH(player,
             AC_HELP_STRING([--with-player=gstreamer|xine],[Select the player to use]),,
@@ -529,6 +537,11 @@
 else
 	AC_MSG_NOTICE([   iPod integration disabled])
 fi
+if test x"$enable_iriver" = xyes; then
+	AC_MSG_NOTICE([** iRiver integration enabled])
+else
+	AC_MSG_NOTICE([   iRiver integration disabled])
+fi
 if test x"$enable_bonobo" = xyes; then
 	AC_MSG_NOTICE([** Bonobo control/activation enabled])
 else


--- orig/lib/rb-stock-icons.c
+++ mod/lib/rb-stock-icons.c
@@ -65,7 +65,8 @@
 		RB_STOCK_NO_STAR,
 		RB_STOCK_DND_ICON,
                 RB_STOCK_AUDIOCD,
-		RB_STOCK_IPOD
+		RB_STOCK_IPOD,
+		RB_STOCK_IRIVER
 	};
 
 	g_return_if_fail (factory == NULL);


--- orig/lib/rb-stock-icons.h
+++ mod/lib/rb-stock-icons.h
@@ -55,6 +55,7 @@
 #define RB_STOCK_AUDIOCD       "rhythmbox-audiocd"
 #define RB_STOCK_DND_ICON      "rhythmbox-dnd"
 #define RB_STOCK_IPOD          "rhythmbox-ipod"
+#define RB_STOCK_IRIVER        "rhythmbox-iriver"
 
 void	rb_stock_icons_init	(void);
 


--- orig/shell/rb-shell.c
+++ mod/shell/rb-shell.c
@@ -67,6 +67,9 @@
 #ifdef WITH_IPOD_SUPPORT
 #include "rb-ipod-source.h"
 #endif /* WITH_IPOD_SUPPORT */
+#ifdef WITH_IRIVER_SUPPORT
+#include "rb-iriver-source.h"
+#endif /* WITH_IRIVER_SUPPORT */
 #include "rb-load-failure-dialog.h"
 #include "rb-new-station-dialog.h"
 #include "rb-iradio-source.h"
@@ -228,6 +231,9 @@
 #ifdef WITH_IPOD_SUPPORT
 	rb_ipod_source_new,	
 #endif /* WITH_IPOD_SUPPORT */
+#ifdef WITH_IRIVER_SUPPORT
+	rb_iriver_source_new,	
+#endif /* WITH_IRIVER_SUPPORT */
 	NULL,
 };
 


--- orig/sources/Makefile.am
+++ mod/sources/Makefile.am
@@ -52,3 +52,11 @@
 	itunesdb.c		     \
 	itunesdb.h
 endif
+
+if WITH_IRIVER_SUPPORT
+libsourcesimpl_la_SOURCES +=         \
+	rb-iriver-source.c           \
+	rb-iriver-source.h	     \
+	iriverdb.c		     \
+	iriverdb.h
+endif



* added files

--- /dev/null
+++ /home/mark/Projects/rhythmbox--main--0.9--patch-146/,,what-changed.rhythmbox--main--0.9--patch-146--rhythmbox-devel@gnome.org--2004/new-files-archive/./sources/rb-iriver-source.c
@@ -0,0 +1,479 @@
+/*
+ *  arch-tag: Implementation of iRiver source object
+ *
+ *  Copyright (C) 2004 Mark Humphreys <marquee@users.sourceforge.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <config.h>
+
+#include <gtk/gtktreeview.h>
+#include <gtk/gtkicontheme.h>
+#include <string.h>
+#include <libgnome/gnome-i18n.h>
+#include <libgnomevfs/gnome-vfs-volume.h>
+#include <libgnomevfs/gnome-vfs-volume-monitor.h>
+#include "eel-gconf-extensions.h"
+#include "rb-iriver-source.h"
+#include "rb-stock-icons.h"
+#include "rb-debug.h"
+#include "iriverdb.h"
+#include "rhythmdb.h"
+
+static void rb_iriver_source_init (RBiRiverSource *source);
+static void rb_iriver_source_finalize (GObject *object);
+static void rb_iriver_source_class_init (RBiRiverSourceClass *klass);
+static GObject *rb_iriver_source_constructor (GType type, 
+					    guint n_construct_properties,
+					    GObjectConstructParam *construct_properties);
+
+static gboolean rb_iriver_is_volume_iriver (GnomeVFSVolume *volume);
+static void rb_iriver_volume_mounted_cb (GnomeVFSVolumeMonitor *monitor, 
+				       GnomeVFSVolume *volume, gpointer data);
+static void rb_iriver_volume_unmounted_cb (GnomeVFSVolumeMonitor *monitor,
+					 GnomeVFSVolume *volume, 
+					 gpointer data);
+static void rb_iriver_plugged   (RBiRiverSource *source, 
+			       const gchar *mount_path,
+			       GnomeVFSVolume *volume);
+static void rb_iriver_unplugged (RBiRiverSource *source);
+static gchar *rb_iriver_get_mount_path (GnomeVFSVolume *volume);
+
+static void rb_iriver_monitor (RBiRiverSource *source, gboolean enable);
+
+struct RBiRiverSourcePrivate
+{
+	GnomeVFSVolume *iriver_volume;
+	iRiverParser *parser;
+	gchar *iriver_mount_path;
+};
+
+GType
+rb_iriver_source_get_type (void)
+{
+	static GType rb_iriver_source_type = 0;
+
+	if (rb_iriver_source_type == 0)
+	{
+		static const GTypeInfo our_info =
+		{
+			sizeof (RBiRiverSourceClass),
+			NULL,
+			NULL,
+			(GClassInitFunc) rb_iriver_source_class_init,
+			NULL,
+			NULL,
+			sizeof (RBiRiverSource),
+			0,
+			(GInstanceInitFunc) rb_iriver_source_init
+		};
+
+		rb_iriver_source_type = g_type_register_static (RB_TYPE_LIBRARY_SOURCE,
+							      "RBiRiverSource",
+							      &our_info, 0);
+
+	}
+
+	return rb_iriver_source_type;
+}
+
+static void
+rb_iriver_source_class_init (RBiRiverSourceClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->finalize = rb_iriver_source_finalize;
+	object_class->constructor = rb_iriver_source_constructor;
+}
+
+
+static GObject *
+rb_iriver_source_constructor (GType type, guint n_construct_properties,
+			    GObjectConstructParam *construct_properties)
+{
+	GObject *object;
+	RBiRiverSourceClass *klass;
+	GObjectClass *parent_class;  
+
+	/* Invoke parent constructor. */
+	klass = RB_IRIVER_SOURCE_CLASS (g_type_class_peek (RB_TYPE_IRIVER_SOURCE));
+	parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
+	object = parent_class->constructor (type,
+					    n_construct_properties,
+					    construct_properties);
+  
+	/* This needs to be done once the GObject properties are set
+	 * since rb_iriver_monitor expect the properties on the
+	 * RBiRiverSource to be set (especially the "db" property)
+	 */
+	rb_iriver_monitor (RB_IRIVER_SOURCE (object), TRUE);
+
+	return object;
+}
+
+static void
+rb_iriver_monitor (RBiRiverSource *source, gboolean enable)
+{
+	GnomeVFSVolumeMonitor *monitor;
+	
+	monitor = gnome_vfs_get_volume_monitor ();
+
+	if (enable) 
+	{
+		GList *volumes;
+		GList *it;
+
+		/* Look for already plugged iRiver */
+		volumes = gnome_vfs_volume_monitor_get_mounted_volumes (monitor);
+		for (it = volumes; it != NULL; it = it->next) 
+		{
+			if (rb_iriver_is_volume_iriver (GNOME_VFS_VOLUME (it->data))) 
+			{
+				rb_iriver_plugged (source, NULL,
+						 GNOME_VFS_VOLUME (it->data));
+			}
+		}
+		
+		/* Monitor new (un)mounted file systems to look for an iRiver */
+		g_signal_connect (G_OBJECT (monitor), "volume-mounted", 
+				  G_CALLBACK (rb_iriver_volume_mounted_cb), 
+				  source);
+		g_signal_connect (G_OBJECT (monitor), "volume-unmounted", 
+				  G_CALLBACK (rb_iriver_volume_unmounted_cb), 
+				  source);
+	} 
+	else 
+	{
+		g_signal_handlers_disconnect_by_func (G_OBJECT (monitor), 
+						      G_CALLBACK (rb_iriver_volume_mounted_cb), 
+						      source);
+		g_signal_handlers_disconnect_by_func (G_OBJECT (monitor), 
+						      G_CALLBACK (rb_iriver_volume_unmounted_cb), 
+						      source);
+	}
+}
+
+static void
+rb_iriver_source_init (RBiRiverSource *source)
+{
+	source->priv = g_new0 (RBiRiverSourcePrivate, 1);
+}
+
+static void 
+rb_iriver_source_finalize (GObject *object)
+{
+	RBiRiverSource *source = RB_IRIVER_SOURCE (object);
+
+	rb_iriver_monitor (source, FALSE);
+
+	if (source->priv->parser != NULL) 
+	{
+		iriver_parser_destroy (source->priv->parser);
+		source->priv->parser = NULL;
+	}
+
+	if (source->priv->iriver_volume != NULL) {
+		gnome_vfs_volume_unref (source->priv->iriver_volume);
+		source->priv->iriver_volume = NULL;
+	}
+	g_free (source->priv->iriver_mount_path);
+	g_free (source->priv);
+}
+
+static GdkPixbuf *
+rb_iriver_get_icon (void)
+{
+	GdkPixbuf *icon;
+	GtkIconTheme *theme;
+
+	theme = gtk_icon_theme_get_default ();
+	icon = gtk_icon_theme_load_icon (theme, "gnome-dev-iriver", 24, 0, NULL);
+
+	if (icon == NULL) {
+		/* gnome-dev-iriver is only available in gnome 2.8, so fallback
+		 * to an icon provided by rhythmbox for older gnome 
+		 */
+		GtkWidget *dummy;
+
+		dummy = gtk_tree_view_new ();
+		icon = gtk_widget_render_icon (dummy, RB_STOCK_IRIVER,
+					       GTK_ICON_SIZE_LARGE_TOOLBAR,
+					       NULL);
+		gtk_widget_destroy (dummy);
+	}
+
+	return icon;
+}
+
+RBSource *
+rb_iriver_source_new (RBShell *shell)
+{
+	RBSource *source;
+
+	rb_debug ("Creating iriver source");
+
+	source = RB_SOURCE (g_object_new (RB_TYPE_IRIVER_SOURCE,
+					  "name", _("iRiver"),
+					  "entry-type", RHYTHMDB_ENTRY_TYPE_IRIVER,
+					  "internal-name", "<iriver>",
+					  "icon", rb_iriver_get_icon (),
+					  "shell", shell,
+					  "visibility", FALSE,
+					  NULL));
+
+	rb_shell_register_entry_type_for_source (shell, source, 
+						 RHYTHMDB_ENTRY_TYPE_IRIVER);
+
+	return source;
+}
+
+static void 
+entry_set_string_prop (RhythmDB *db, RhythmDBEntry *entry,
+		       RhythmDBPropType propid, const char *str)
+{
+	GValue value = {0,};
+	gchar *tmp;
+
+	if (str == NULL) 
+	{
+		tmp = g_strdup (_("Unknown"));
+	} 
+	else 
+	{
+		tmp = g_strdup (str);
+	}
+
+	g_value_init (&value, G_TYPE_STRING);
+	g_value_set_string_take_ownership (&value, tmp);
+	rhythmdb_entry_set (RHYTHMDB (db), entry, propid, &value);
+	g_value_unset (&value);
+}
+
+#define MAX_SONGS_LOADED_AT_ONCE 250
+
+static gboolean
+load_iriver_db_idle_cb (RBiRiverSource *source)
+{
+	RhythmDBEntry *entry;
+	RBShell *shell;
+	RhythmDB *db;
+	int count;
+
+	g_object_get (G_OBJECT (source), "shell", &shell, NULL);
+	g_object_get (G_OBJECT (shell), "db", &db, NULL);
+	g_object_unref (G_OBJECT (shell));
+
+	g_assert (db != NULL);
+	g_assert (source->priv->parser != NULL);
+
+	for (count = 0; count < MAX_SONGS_LOADED_AT_ONCE; count++) 
+	{
+		gchar *pc_path;
+		gchar *mount_path;
+		iRiverItem *item;
+		iRiverTrack *song;
+		
+		item = iriver_get_next_item (source->priv->parser);
+		if ((item == NULL) || (item->type != IRIVER_ITEM_SONG)) 
+		{
+			iriver_item_destroy (item);
+			iriver_parser_destroy (source->priv->parser);
+			source->priv->parser = NULL;
+			g_object_unref (G_OBJECT (db));
+			return FALSE;
+		}
+		song = (iRiverTrack *)item->data;
+				
+		mount_path = source->priv->iriver_mount_path;
+		pc_path = iriverdb_get_track_name_on_iriver (mount_path, song);
+
+		entry = rhythmdb_entry_new (RHYTHMDB (db), 
+					    RHYTHMDB_ENTRY_TYPE_IRIVER,
+					    pc_path);
+		g_free (pc_path);
+
+		entry_set_string_prop (RHYTHMDB (db), entry, 
+				       RHYTHMDB_PROP_TITLE, song->title);
+		
+		entry_set_string_prop (RHYTHMDB (db), entry, 
+				       RHYTHMDB_PROP_ARTIST, song->artist);
+		
+		entry_set_string_prop (RHYTHMDB (db), entry, 
+				       RHYTHMDB_PROP_ALBUM, song->album);
+		
+		entry_set_string_prop (RHYTHMDB (db), entry, 
+				       RHYTHMDB_PROP_GENRE, song->genre);
+		
+		rhythmdb_commit (RHYTHMDB (db));
+
+		iriver_item_destroy (item);
+	}
+
+	g_object_unref (G_OBJECT (db));
+	return TRUE;
+}
+
+static void
+rb_iriver_load_songs (RBiRiverSource *source)
+{
+	source->priv->parser = iriver_parser_new (source->priv->iriver_mount_path);
+
+	g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, 
+			 (GSourceFunc)load_iriver_db_idle_cb,
+			 source, NULL);
+}
+
+static void
+rb_iriver_unload_songs (RBiRiverSource *source)
+{
+	RhythmDB *db;
+
+	g_object_get (G_OBJECT (source), "db", &db, NULL);
+	rhythmdb_entry_delete_by_type (db, RHYTHMDB_ENTRY_TYPE_IRIVER);
+	rhythmdb_commit (db);
+	g_object_unref (db);
+}
+
+
+static void
+rb_iriver_plugged (RBiRiverSource *source, 
+		 const gchar *mount_path,
+		 GnomeVFSVolume *volume)
+{
+	if (source->priv->iriver_mount_path != NULL) 
+	{
+		/* Only one iRiver can be recognized at once */
+		return;
+	}
+
+	source->priv->iriver_volume = volume;
+	source->priv->iriver_mount_path = rb_iriver_get_mount_path (volume);
+	gnome_vfs_volume_ref (volume);
+	g_object_set (G_OBJECT (source), "visibility", TRUE, NULL);	
+	rb_iriver_load_songs (source);
+
+	/* FIXME: should we suspend this monitor until the iRiver 
+	 * database has been read and fed to rhythmbox?
+	 */
+}
+
+static void
+rb_iriver_unplugged (RBiRiverSource *source)
+{
+	g_assert (source->priv->iriver_mount_path != NULL);
+
+	source->priv->iriver_volume = NULL;
+	gnome_vfs_volume_unref (source->priv->iriver_volume);
+	g_free (source->priv->iriver_mount_path);
+	source->priv->iriver_mount_path = NULL;
+	g_object_set (G_OBJECT (source), "visibility", FALSE, NULL);
+	rb_iriver_unload_songs (source);
+}
+
+RhythmDBEntryType rhythmdb_entry_iriver_get_type (void) 
+{
+	static RhythmDBEntryType iriver_type = -1;
+       
+	if (iriver_type == -1) {
+		iriver_type = rhythmdb_entry_register_type ();
+	}
+
+	return iriver_type;
+}
+
+static gchar *
+rb_iriver_get_mount_path (GnomeVFSVolume *volume)
+{
+	gchar *path;
+	gchar *uri;
+
+	uri = gnome_vfs_volume_get_activation_uri (volume);
+	path = g_filename_from_uri (uri, NULL, NULL);
+	g_assert (path != NULL);
+	g_free (uri);
+
+	return path;
+}
+
+static gchar *
+rb_iriver_get_db_path (GnomeVFSVolume *volume)
+{
+	gchar *mount_point_uri;
+	gchar *mount_point;
+	gchar *result;
+
+	mount_point_uri = gnome_vfs_volume_get_activation_uri (volume);
+	mount_point = g_filename_from_uri (mount_point_uri, NULL, NULL);
+	g_free (mount_point_uri);
+	g_assert (mount_point != NULL);
+	result = g_build_filename (mount_point, 
+				   "iRivNavi.iDB",
+				   NULL);
+	g_free (mount_point);
+	return result;
+}
+
+static gboolean
+rb_iriver_is_volume_iriver (GnomeVFSVolume *volume)
+{
+	gchar *iriverdb_path;
+	gboolean result = FALSE;
+
+	if (gnome_vfs_volume_get_volume_type (volume) != GNOME_VFS_VOLUME_TYPE_MOUNTPOINT) 
+	{
+		return FALSE;
+	}
+
+	iriverdb_path = rb_iriver_get_db_path (volume);
+	
+	result = g_file_test (iriverdb_path, G_FILE_TEST_EXISTS);
+	g_free (iriverdb_path);
+
+	return result;
+}
+
+static void 
+rb_iriver_volume_mounted_cb (GnomeVFSVolumeMonitor *monitor,
+			   GnomeVFSVolume *volume, 
+			   gpointer data)
+{
+	RBiRiverSource *source = RB_IRIVER_SOURCE (data);
+
+	if (source->priv->iriver_volume != NULL) {
+		rb_debug ("iRiver plugged while another one is already present, ignoring the new one");
+		return;
+	}
+
+	if (rb_iriver_is_volume_iriver (volume)) 
+	{
+		rb_iriver_plugged (source, NULL, volume);
+	}
+}
+
+static void 
+rb_iriver_volume_unmounted_cb (GnomeVFSVolumeMonitor *monitor,
+			     GnomeVFSVolume *volume, 
+			     gpointer data)
+{
+	RBiRiverSource *source = RB_IRIVER_SOURCE (data);
+
+	g_assert (volume != NULL);
+
+	if (source->priv->iriver_volume == volume) {
+		rb_iriver_unplugged (source);
+	}
+}
--- /dev/null
+++ /home/mark/Projects/rhythmbox--main--0.9--patch-146/,,what-changed.rhythmbox--main--0.9--patch-146--rhythmbox-devel@gnome.org--2004/new-files-archive/./sources/rb-iriver-source.h
@@ -0,0 +1,62 @@
+/*
+ *  arch-tag: Header for iRiver source object
+ *
+ *  Copyright (C) 2004 Mark Humphreys <marquee@users.sourceforge.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __RB_IRIVER_SOURCE_H
+#define __RB_IRIVER_SOURCE_H
+
+#include "rb-shell.h"
+#include "rb-library-source.h"
+#include "rhythmdb.h"
+
+G_BEGIN_DECLS
+
+#define RB_TYPE_IRIVER_SOURCE         (rb_iriver_source_get_type ())
+#define RB_IRIVER_SOURCE(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), RB_TYPE_IRIVER_SOURCE, RBiRiverSource))
+#define RB_IRIVER_SOURCE_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), RB_TYPE_IRIVER_SOURCE, RBiRiverSourceClass))
+#define RB_IS_IRIVER_SOURCE(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), RB_TYPE_IRIVER_SOURCE))
+#define RB_IS_IRIVER_SOURCE_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), RB_TYPE_IRIVER_SOURCE))
+#define RB_IRIVER_SOURCE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), RB_TYPE_IRIVER_SOURCE, RBiRiverSourceClass))
+
+#define RHYTHMDB_ENTRY_TYPE_IRIVER (rhythmdb_entry_iriver_get_type ())
+
+typedef struct RBiRiverSourcePrivate RBiRiverSourcePrivate;
+
+typedef struct
+{
+	RBLibrarySource parent;
+
+	RBiRiverSourcePrivate *priv;
+} RBiRiverSource;
+
+typedef struct
+{
+	RBLibrarySourceClass parent;
+} RBiRiverSourceClass;
+
+RBSource *	rb_iriver_source_new		(RBShell *shell);
+
+GType		rb_iriver_source_get_type	        (void);
+
+RhythmDBEntryType rhythmdb_entry_iriver_get_type  (void);
+
+G_END_DECLS
+
+#endif /* __RB_IRIVER_SOURCE_H */
