Index: bindings/python/rb.defs
===================================================================
RCS file: /cvs/gnome/rhythmbox/bindings/python/rb.defs,v
retrieving revision 1.31
diff -p -u -r1.31 rb.defs
--- bindings/python/rb.defs	12 Jul 2006 09:56:55 -0000	1.31
+++ bindings/python/rb.defs	26 Jul 2006 16:14:29 -0000
@@ -512,7 +512,7 @@
   (c-name "rb_shell_player_get_playing_path")
   (return-type "gboolean")
   (parameters
-    '("const-gchar**" "path")
+    '("gchar**" "path")
     '("GError**" "error")
   )
 )
Index: rhythmdb/rb-refstring.c
===================================================================
RCS file: /cvs/gnome/rhythmbox/rhythmdb/rb-refstring.c,v
retrieving revision 1.16
diff -p -u -r1.16 rb-refstring.c
--- rhythmdb/rb-refstring.c	24 Jul 2006 01:34:08 -0000	1.16
+++ rhythmdb/rb-refstring.c	26 Jul 2006 16:14:30 -0000
@@ -1,4 +1,5 @@
-/*
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
  *  arch-tag: Implementation of reference-counted string
  *
  *  Copyright (C) 2004 Colin Walters <walters@redhat.com>
@@ -28,24 +29,100 @@
 #include "rb-refstring.h"
 
 GHashTable *rb_refstrings;
+GHashTable *rb_refwords;
 GMutex *rb_refstrings_mutex;
+GMutex *rb_refwords_mutex;
 
-struct RBRefString
+struct RBRefWord
 {
 	gint refcount;
-	gpointer folded;
-	gpointer sortkey;
 	char value[1];
 };
+typedef struct RBRefWord RBRefWord;
+
+struct RBRefString
+{
+	guint index;
+	guint length;
+	char delimiter[3];
+	gint refcount;
+	GPtrArray *words;
+};
+
+static void
+rb_refword_free (RBRefWord *refword)
+{
+	refword->refcount = 0xdeadbeef;
+	g_free (refword);
+}
+
+static void
+rb_refword_unref (RBRefWord *val)
+{
+	if (val == NULL) {
+		return;
+	}
+
+	g_return_if_fail (val->refcount > 0);
+
+	if (g_atomic_int_dec_and_test (&val->refcount)) {
+		g_mutex_lock (rb_refwords_mutex);
+		g_hash_table_remove (rb_refwords, val->value);
+		g_mutex_unlock (rb_refwords_mutex);
+	}
+}
+
+static RBRefWord *
+rb_refword_ref (RBRefWord *val)
+{
+	if (val == NULL)
+		return NULL;
+
+	g_return_val_if_fail (val->refcount > 0, NULL);
+
+	g_atomic_int_inc (&val->refcount);
+	return val;
+}
+
+static RBRefWord *
+rb_refword_new (const char *init)
+{
+	RBRefWord *ret;
+
+	g_mutex_lock (rb_refwords_mutex);
+
+	ret = g_hash_table_lookup (rb_refwords, init);
+
+	if (ret != NULL) {
+		rb_refword_ref (ret);
+		g_mutex_unlock (rb_refwords_mutex);
+		return ret;
+	}
+
+	ret = g_malloc (sizeof (RBRefWord) + strlen (init));
+
+	strcpy (ret->value, init);
+	ret->refcount = 1;
+
+	g_hash_table_insert (rb_refwords, ret->value, ret);
+
+	g_mutex_unlock (rb_refwords_mutex);
+
+	return ret;
+}
+
+static const char *
+rb_refword_get (const RBRefWord *val)
+{
+	return val ? val->value : NULL;
+}
 
 static void
 rb_refstring_free (RBRefString *refstr)
 {
 	refstr->refcount = 0xdeadbeef;
-	g_free (refstr->folded);
-	refstr->folded = NULL;
-	g_free (refstr->sortkey);
-	refstr->sortkey = NULL;
+	g_ptr_array_foreach (refstr->words, (GFunc)rb_refword_unref, NULL);
+	g_ptr_array_free (refstr->words, TRUE);
 	g_free (refstr);
 }
 
@@ -53,33 +130,111 @@ void
 rb_refstring_system_init ()
 {
 	rb_refstrings_mutex = g_mutex_new ();
+	rb_refwords_mutex = g_mutex_new ();
 
-	rb_refstrings = g_hash_table_new_full (g_str_hash, g_str_equal,
+	rb_refstrings = g_hash_table_new_full (g_direct_hash, g_direct_equal,
 					       NULL, (GDestroyNotify) rb_refstring_free);
+	rb_refwords = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                             NULL, (GDestroyNotify) rb_refword_free);
+}
+
+static inline guint
+create_index (const char *str)
+{
+	guint index;
+
+	index = g_str_hash (str);
+
+	return index;
 }
 
 RBRefString *
-rb_refstring_new (const char *init)
+rb_refstring_new (const char *init,
+                  const char *delimiter)
 {
 	RBRefString *ret;
+	guint index;
 
 	g_mutex_lock (rb_refstrings_mutex);
-	ret = g_hash_table_lookup (rb_refstrings, init);
 
-	if (ret) {
+	index = create_index (init);
+
+	ret = g_hash_table_lookup (rb_refstrings, GUINT_TO_POINTER (index));
+
+	if (ret != NULL) {
 		rb_refstring_ref (ret);
 		g_mutex_unlock (rb_refstrings_mutex);
 		return ret;
 	}
 
-	ret = g_malloc (sizeof (RBRefString) + strlen (init));
-
-	strcpy (ret->value, init);
+	ret = g_new0 (RBRefString, 1);
 	ret->refcount = 1;
-	ret->folded = NULL;
-	ret->sortkey = NULL;
+	ret->length = strlen (init);
+	ret->index = index;
+
+	if (delimiter != NULL) {
+		char **str_array;
+		int    size;
+		int    offset;
+		int    i;
+		const char *ptr;
+		const char *prefix;
+
+		strncpy (ret->delimiter, delimiter, 2);
+		ret->delimiter[2] = '\0';
+
+		prefix = NULL;
+		ptr = init;
+		offset = 1;
+		if (strcmp (delimiter, "/") == 0) {
+			if (g_str_has_prefix (init, "file:///")) {
+				ptr += 8;
+				offset++;
+				prefix = "file://";
+			} else if (g_str_has_prefix (init, "http://")) {
+				ptr += 7;
+				offset++;
+				prefix = "http:/";
+			}
+		}
+
+		str_array = g_strsplit (ptr, delimiter, -1);
+		size = g_strv_length (str_array);
+		ret->words = g_ptr_array_sized_new (size + offset);
+		if (prefix != NULL) {
+			g_ptr_array_add (ret->words, rb_refword_new (prefix));
+		}
+		for (i = 0; i < size; i++) {
+			g_ptr_array_add (ret->words, rb_refword_new (str_array[i]));
+		}
+		g_strfreev (str_array);
+	} else {
+		ret->words = g_ptr_array_sized_new (2);
+		g_ptr_array_add (ret->words, rb_refword_new (init));
+	}
+	g_ptr_array_add (ret->words, NULL);
+
+	g_hash_table_insert (rb_refstrings, GUINT_TO_POINTER (index), ret);
+	g_mutex_unlock (rb_refstrings_mutex);
+
+	return ret;
+}
+
+RBRefString *
+rb_refstring_find (const char *init)
+{
+	RBRefString *ret;
+	guint index;
+
+	g_mutex_lock (rb_refstrings_mutex);
+
+	index = create_index (init);
+	ret = g_hash_table_lookup (rb_refstrings, GUINT_TO_POINTER (index));
+
+	if (ret != NULL) {
+		rb_refstring_ref (ret);
+	}
 
-	g_hash_table_insert (rb_refstrings, ret->value, ret);
 	g_mutex_unlock (rb_refstrings_mutex);
 	return ret;
 }
@@ -91,10 +246,11 @@ rb_refstring_unref (RBRefString *val)
 		return;
 
 	g_return_if_fail (val->refcount > 0);
+	g_return_if_fail (val->refcount < 10000);
 
 	if (g_atomic_int_dec_and_test (&val->refcount)) {
 		g_mutex_lock (rb_refstrings_mutex);
-		g_hash_table_remove (rb_refstrings, val->value);
+		g_hash_table_remove (rb_refstrings, GUINT_TO_POINTER (val->index));
 		g_mutex_unlock (rb_refstrings_mutex);
 	}
 }
@@ -103,7 +259,9 @@ void
 rb_refstring_system_shutdown (void)
 {
 	g_hash_table_destroy (rb_refstrings);
+	g_hash_table_destroy (rb_refwords);
 	g_mutex_free (rb_refstrings_mutex);
+	g_mutex_free (rb_refwords_mutex);
 }
 
 RBRefString *
@@ -118,10 +276,46 @@ rb_refstring_ref (RBRefString *val)
 	return val;
 }
 
-const char *
+static char *
+join_words (const char *separator,
+	    guint       length,
+	    GPtrArray  *words)
+{
+	char *string;
+	char *ptr;
+	int i;
+
+	if (separator == NULL)
+		separator = "";
+
+	if (length < 1) {
+		return g_strdup ("");
+	}
+
+	string = g_new (char, length + 1);
+	ptr = g_stpcpy (string, rb_refword_get (*words->pdata));
+
+	for (i = 1; words->pdata[i] != NULL; i++) {
+		ptr = g_stpcpy (ptr, separator);
+		ptr = g_stpcpy (ptr, rb_refword_get (words->pdata[i]));
+	}
+
+	return string;
+}
+
+char *
 rb_refstring_get (const RBRefString *val)
 {
-	return val ? val->value : NULL;
+	char *str;
+
+	if (val == NULL)
+		return NULL;
+
+	g_mutex_lock (rb_refstrings_mutex);
+	str = join_words (val->delimiter, val->length, val->words);
+	g_mutex_unlock (rb_refstrings_mutex);
+
+	return str;
 }
 
 /*
@@ -131,59 +325,34 @@ rb_refstring_get (const RBRefString *val
  * get called often.
  */
 
-const char *
+char *
 rb_refstring_get_folded (RBRefString *val)
 {
-	gpointer *ptr;
-	const char *string;
+	char *string;
+	char *str;
 
 	if (val == NULL)
 		return NULL;
 
-	ptr = &val->folded;
-	string = (const char*)g_atomic_pointer_get (ptr);
-	if (string == NULL) {
-		char *newstring;
-
-		newstring = rb_search_fold (rb_refstring_get (val));
-		if (g_atomic_pointer_compare_and_exchange (ptr, NULL, newstring)) {
-			string = newstring;
-		} else {
-			g_free (newstring);
-			string = (const char *)g_atomic_pointer_get (ptr);
-			g_assert (string);
-		}
-	}
+	str = rb_refstring_get (val);
+	string = rb_search_fold (str);
+	g_free (str);
 
 	return string;
 }
 
-const char *
+char *
 rb_refstring_get_sort_key (RBRefString *val)
 {
-	gpointer *ptr;
-	const char *string;
+	char *folded;
+	char *string;
 
 	if (val == NULL)
 		return NULL;
 
-	ptr = &val->sortkey;
-	string = (const char *)g_atomic_pointer_get (ptr);
-	if (string == NULL) {
-		char *newstring;
-		const char *s;
-
-		s = rb_refstring_get_folded (val);
-		newstring = rb_utf8_collate_key_for_filename (s, -1);
-
-		if (g_atomic_pointer_compare_and_exchange (ptr, NULL, newstring)) {
-			string = newstring;
-		} else {
-			g_free (newstring);
-			string = (const char*)g_atomic_pointer_get (ptr);
-			g_assert (string);
-		}
-	}
+	folded = rb_refstring_get_folded (val);
+	string = rb_utf8_collate_key_for_filename (folded, -1);
+	g_free (folded);
 
 	return string;
 }
@@ -192,7 +361,7 @@ guint
 rb_refstring_hash (gconstpointer p)
 {
 	const RBRefString *ref = p;
-	return g_str_hash (rb_refstring_get (ref));
+	return ref->index;
 }
 
 gboolean
Index: rhythmdb/rb-refstring.h
===================================================================
RCS file: /cvs/gnome/rhythmbox/rhythmdb/rb-refstring.h,v
retrieving revision 1.8
diff -p -u -r1.8 rb-refstring.h
--- rhythmdb/rb-refstring.h	14 Jul 2006 12:29:27 -0000	1.8
+++ rhythmdb/rb-refstring.h	26 Jul 2006 16:14:30 -0000
@@ -29,14 +29,16 @@ typedef struct RBRefString RBRefString;
 void		rb_refstring_system_init (void);
 void		rb_refstring_system_shutdown (void);
 
-RBRefString *	rb_refstring_new (const char *init);
+RBRefString *	rb_refstring_new (const char *init,
+                                  const char *delimiter);
+RBRefString *	rb_refstring_find (const char *init);
 
 RBRefString *	rb_refstring_ref (RBRefString *val);
 void		rb_refstring_unref (RBRefString *val);
 
-const char *	rb_refstring_get (const RBRefString *val);
-const char *	rb_refstring_get_folded (RBRefString *val);
-const char *	rb_refstring_get_sort_key (RBRefString *val);
+char *	        rb_refstring_get (const RBRefString *val);
+char *	        rb_refstring_get_folded (RBRefString *val);
+char *     	rb_refstring_get_sort_key (RBRefString *val);
 
 guint rb_refstring_hash (gconstpointer p);
 gboolean rb_refstring_equal (gconstpointer ap, gconstpointer bp);
Index: rhythmdb/rhythmdb-monitor.c
===================================================================
RCS file: /cvs/gnome/rhythmbox/rhythmdb/rhythmdb-monitor.c,v
retrieving revision 1.5
diff -p -u -r1.5 rhythmdb-monitor.c
--- rhythmdb/rhythmdb-monitor.c	14 Jul 2006 12:29:27 -0000	1.5
+++ rhythmdb/rhythmdb-monitor.c	26 Jul 2006 16:14:30 -0000
@@ -51,8 +51,8 @@ rhythmdb_init_monitoring (RhythmDB *db)
 								 (GDestroyNotify) g_free,
 								 NULL);
 
-	db->priv->changed_files = g_hash_table_new_full (g_str_hash, g_str_equal,
-							 (GDestroyNotify) g_free,
+	db->priv->changed_files = g_hash_table_new_full (rb_refstring_hash, rb_refstring_equal,
+							 (GDestroyNotify) rb_refstring_unref,
 							 NULL);
 
 	g_signal_connect (G_OBJECT (gnome_vfs_get_volume_monitor ()),
@@ -102,7 +102,10 @@ monitor_entry_file (RhythmDBEntry *entry
 	GError *error = NULL;
 
 	if (entry->type == RHYTHMDB_ENTRY_TYPE_SONG) {
-		rhythmdb_monitor_uri_path (db, entry->location, &error);
+		const char *loc;
+
+		loc = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION);
+		rhythmdb_monitor_uri_path (db, loc, &error);
 	}
 
 	if (error) {
@@ -152,10 +155,13 @@ monitor_library_directory (const char *u
 }
 
 static gboolean
-rhythmdb_check_changed_file (const char *uri, gpointer data, RhythmDB *db)
+rhythmdb_check_changed_file (RBRefString *uri, gpointer data, RhythmDB *db)
 {
 	GTimeVal time;
 	glong time_sec = GPOINTER_TO_INT (data);
+	char *str;
+
+	str = rb_refstring_get (uri);
 
 	g_get_current_time (&time);
 	if (time.tv_sec >= time_sec + RHYTHMDB_FILE_MODIFY_PROCESS_TIME) {
@@ -163,14 +169,16 @@ rhythmdb_check_changed_file (const char 
 		RhythmDBEvent *event = g_new0 (RhythmDBEvent, 1);
 		event->db = db;
 		event->type = RHYTHMDB_EVENT_FILE_CREATED_OR_MODIFIED;
-		event->uri = g_strdup (uri);
+		event->uri = rb_refstring_ref (uri);
 
 		g_async_queue_push (db->priv->event_queue, event);
-		rb_debug ("adding newly located file %s", uri);
+		rb_debug ("adding newly located file %s", str);
+		g_free (str);
 		return TRUE;
 	}
 
-	rb_debug ("waiting to add newly located file %s", uri);
+	rb_debug ("waiting to add newly located file %s", str);
+	g_free (str);
 
 	return FALSE;
 }
@@ -242,7 +250,7 @@ rhythmdb_directory_change_cb (GnomeVFSMo
 
 			g_get_current_time (&time);
 			g_hash_table_replace (db->priv->changed_files,
-					      g_strdup (info_uri),
+					      rb_refstring_new (info_uri, URI_DELIMITER),
 					      GINT_TO_POINTER (time.tv_sec));
 		}
 		break;
@@ -251,7 +259,7 @@ rhythmdb_directory_change_cb (GnomeVFSMo
 			RhythmDBEvent *event = g_new0 (RhythmDBEvent, 1);
 			event->db = db;
 			event->type = RHYTHMDB_EVENT_FILE_DELETED;
-			event->uri = g_strdup (info_uri);
+			event->uri = rb_refstring_new (info_uri, URI_DELIMITER);
 			g_async_queue_push (db->priv->event_queue, event);
 		}
 		break;
Index: rhythmdb/rhythmdb-private.h
===================================================================
RCS file: /cvs/gnome/rhythmbox/rhythmdb/rhythmdb-private.h,v
retrieving revision 1.19
diff -p -u -r1.19 rhythmdb-private.h
--- rhythmdb/rhythmdb-private.h	23 Jul 2006 16:02:56 -0000	1.19
+++ rhythmdb/rhythmdb-private.h	26 Jul 2006 16:14:30 -0000
@@ -89,7 +89,7 @@ struct RhythmDBEntry_ {
 	GDate date;
 
 	/* filesystem */
-	char *location;
+	RBRefString *location;
 	RBRefString *mountpoint;
 	guint64 file_size;
 	RBRefString *mimetype;
@@ -108,7 +108,7 @@ struct RhythmDBEntry_ {
 	gpointer last_seen_str;
 
 	/* playback error string */
-	char *playback_error;
+	RBRefString *playback_error;
 };
 
 struct RhythmDBPrivate
@@ -188,8 +188,8 @@ typedef struct
 		RHYTHMDB_EVENT_FILE_DELETED,
 		RHYTHMDB_EVENT_ENTRY_SET
 	} type;
-	char *uri;
-	char *real_uri; /* Target of a symlink, if any */
+	RBRefString *uri;
+	RBRefString *real_uri; /* Target of a symlink, if any */
 	RhythmDBEntryType entry_type;
 
 	GError *error;
@@ -209,6 +209,11 @@ typedef struct
 	RhythmDBEntryChange change;
 } RhythmDBEvent;
 
+#define NO_DELIMITER NULL
+#define STRING_DELIMITER " "
+#define URI_DELIMITER "/"
+#define MIME_DELIMITER "/"
+
 /* from rhythmdb.c */
 void queue_stat_uri (const char *uri, RhythmDB *db, RhythmDBEntryType type);
 void rhythmdb_entry_set_visibility (RhythmDB *db, RhythmDBEntry *entry,
@@ -217,6 +222,7 @@ void rhythmdb_entry_set_internal (Rhythm
 				  gboolean notify_if_inserted, guint propid,
 				  const GValue *value);
 void rhythmdb_entry_type_foreach (RhythmDB *db, GHFunc func, gpointer data);
+RhythmDBEntry *	rhythmdb_entry_lookup_by_location_refstring (RhythmDB *db, RBRefString *uri);
 
 /* from rhythmdb-monitor.c */
 void rhythmdb_init_monitoring (RhythmDB *db);
Index: rhythmdb/rhythmdb-property-model.c
===================================================================
RCS file: /cvs/gnome/rhythmbox/rhythmdb/rhythmdb-property-model.c,v
retrieving revision 1.51
diff -p -u -r1.51 rhythmdb-property-model.c
--- rhythmdb/rhythmdb-property-model.c	25 Jul 2006 12:05:46 -0000	1.51
+++ rhythmdb/rhythmdb-property-model.c	26 Jul 2006 16:14:31 -0000
@@ -410,11 +410,11 @@ rhythmdb_property_model_init (RhythmDBPr
 	model->priv->stamp = g_random_int ();
 
 	model->priv->properties = g_sequence_new (NULL);
-	model->priv->reverse_map = g_hash_table_new (g_str_hash, g_str_equal);
+	model->priv->reverse_map = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify)g_free, NULL);
 	model->priv->entries = g_hash_table_new (g_direct_hash, g_direct_equal);
 
 	model->priv->all = g_new0 (RhythmDBPropertyModelEntry, 1);
-	model->priv->all->string = rb_refstring_new (_("All"));
+	model->priv->all->string = rb_refstring_new (_("All"), NULL);
 }
 
 static void
@@ -550,12 +550,15 @@ rhythmdb_property_model_compare (RhythmD
 				 RhythmDBPropertyModelEntry *b,
 				 RhythmDBPropertyModel *model)
 {
-	const char *a_str, *b_str;
+	char *a_str, *b_str;
+	gint ret;
 
 	a_str = rb_refstring_get_sort_key (a->sort_string);
 	b_str = rb_refstring_get_sort_key (b->sort_string);
-
-	return strcmp (a_str, b_str);
+	ret = strcmp (a_str, b_str);
+	g_free (a_str);
+	g_free (b_str);
+	return ret;
 }
 
 static RhythmDBPropertyModelEntry *
@@ -566,7 +569,8 @@ rhythmdb_property_model_insert (RhythmDB
 	GtkTreeIter iter;
 	GtkTreePath *path;
 	GSequencePtr ptr;
-	const char *propstr;
+	char *propstr;
+	char *str;
 
 	propstr = rhythmdb_entry_get_string (entry, model->priv->propid);
 
@@ -576,21 +580,25 @@ rhythmdb_property_model_insert (RhythmDB
 		prop = g_sequence_ptr_get_data (ptr);
 		prop->refcount++;
 		rb_debug ("adding \"%s\": refcount %d", propstr, prop->refcount);
+		g_free (propstr);
 		return prop;
 	}
 	rb_debug ("adding new property \"%s\"", propstr);
+	g_free (propstr);
 
 	prop = g_new0 (RhythmDBPropertyModelEntry, 1);
-	prop->string = rb_refstring_new (propstr);
-	prop->sort_string = rb_refstring_new (rhythmdb_entry_get_string (entry, model->priv->sort_propid));
+	prop->string = rhythmdb_entry_get_refstring (entry, model->priv->propid);
+	prop->sort_string = rhythmdb_entry_get_refstring (entry, model->priv->sort_propid);
 	prop->refcount = 1;
 
 	iter.stamp = model->priv->stamp;
 	ptr = g_sequence_insert_sorted (model->priv->properties, prop,
 					(GCompareDataFunc) rhythmdb_property_model_compare,
 					model);
+
+	str = rb_refstring_get (prop->string);
 	g_hash_table_insert (model->priv->reverse_map,
-			     (gpointer)rb_refstring_get (prop->string),
+			     str,
 			     ptr);
 
 	iter.user_data = ptr;
@@ -606,11 +614,12 @@ rhythmdb_property_model_delete (RhythmDB
 				RhythmDBEntry *entry)
 {
 	RhythmDBPropertyModelEntry *prop;
-	const char *propstr;
+	char *propstr;
 
 	prop = g_hash_table_lookup (model->priv->entries, entry);
 	propstr = rb_refstring_get (prop->string);
 	rhythmdb_property_model_delete_prop (model, propstr);
+	g_free (propstr);
 }
 
 static void
@@ -766,8 +775,14 @@ rhythmdb_property_model_get_value (GtkTr
 	if (iter->user_data == model->priv->all) {
 		switch (column) {
 		case RHYTHMDB_PROPERTY_MODEL_COLUMN_TITLE:
-			g_value_init (value, G_TYPE_STRING);
-			g_value_set_string (value, rb_refstring_get (model->priv->all->string));
+			{
+				char *str;
+
+				g_value_init (value, G_TYPE_STRING);
+				str = rb_refstring_get (model->priv->all->string);
+				g_value_set_string (value, str);
+				g_free (str);
+			}
 			break;
 		case RHYTHMDB_PROPERTY_MODEL_COLUMN_PRIORITY:
 			g_value_init (value, G_TYPE_BOOLEAN);
@@ -785,8 +800,14 @@ rhythmdb_property_model_get_value (GtkTr
 
 		switch (column) {
 		case RHYTHMDB_PROPERTY_MODEL_COLUMN_TITLE:
-			g_value_init (value, G_TYPE_STRING);
-			g_value_set_string (value, rb_refstring_get (prop->string));
+			{
+				char *str;
+
+				g_value_init (value, G_TYPE_STRING);
+				str = rb_refstring_get (prop->string);
+				g_value_set_string (value, str);
+				g_free (str);
+			}
 			break;
 		case RHYTHMDB_PROPERTY_MODEL_COLUMN_PRIORITY:
 			g_value_init (value, G_TYPE_BOOLEAN);
@@ -918,12 +939,13 @@ query_model_cb (GtkTreeModel *query_mode
 		GtkTreeIter *iter,
  		struct QueryModelCbStruct *data)
 {
- 	const char *uri;
+ 	char *uri;
  	RhythmDBEntry *entry;
 
  	gtk_tree_model_get (query_model, iter, 0, &entry, -1);
  	uri = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION);
  	g_string_append (data->reply, uri);
+	g_free (uri);
  	g_string_append (data->reply, "\r\n");
 
  	rhythmdb_entry_unref (entry);
Index: rhythmdb/rhythmdb-query-model.c
===================================================================
RCS file: /cvs/gnome/rhythmbox/rhythmdb/rhythmdb-query-model.c,v
retrieving revision 1.143
diff -p -u -r1.143 rhythmdb-query-model.c
--- rhythmdb/rhythmdb-query-model.c	26 Jul 2006 11:40:03 -0000	1.143
+++ rhythmdb/rhythmdb-query-model.c	26 Jul 2006 16:14:33 -0000
@@ -850,14 +850,17 @@ rhythmdb_query_model_entry_changed_cb (R
 		 * this is needed to update propery models correctly */
 		GValue true_val = { 0, };
 		GValue false_val = { 0, };
+		char *uri;
 
 		g_value_init (&true_val, G_TYPE_BOOLEAN);
 		g_value_set_boolean (&true_val, TRUE);
 		g_value_init (&false_val, G_TYPE_BOOLEAN);
 		g_value_set_boolean (&false_val, FALSE);
 
-		rb_debug ("emitting hidden-removal notification for %s",
-			  rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION));
+		uri = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION);
+		rb_debug ("emitting hidden-removal notification for %s", uri);
+		g_free (uri);
+
 		g_signal_emit (G_OBJECT (model),
 			       rhythmdb_query_model_signals[ENTRY_PROP_CHANGED], 0,
 			       entry, RHYTHMDB_PROP_HIDDEN, &false_val, &true_val);
@@ -1589,7 +1592,7 @@ rhythmdb_query_model_drag_data_get (RbTr
 		for (tem = paths; tem; tem = tem->next) {
 			GtkTreeIter iter;
 			GtkTreePath *path;
-			const char *location;
+			char *location;
 
 			path = gtk_tree_row_reference_get_path (tem->data);
 
@@ -1606,6 +1609,8 @@ rhythmdb_query_model_drag_data_get (RbTr
 
 			g_string_append (data, location);
 			need_newline = TRUE;
+
+			g_free (location);
 		}
 
 		gtk_selection_data_set (selection_data,
@@ -2374,21 +2379,26 @@ rhythmdb_query_model_location_sort_func 
 					 RhythmDBEntry *b,
 					 gpointer data)
 {
-	const char *a_val;
-	const char *b_val;
+	char *a_val;
+	char *b_val;
+	int ret;
 
 	a_val = rhythmdb_entry_get_string (a, RHYTHMDB_PROP_LOCATION);
 	b_val = rhythmdb_entry_get_string (b, RHYTHMDB_PROP_LOCATION);
 
 	if (a_val == NULL) {
 		if (b_val == NULL)
-			return 0;
+			ret = 0;
 		else
-			return -1;
+			ret = -1;
 	} else if (b_val == NULL)
-		return 1;
+		ret = 1;
 	else
-		return strcmp (a_val, b_val);
+		ret = strcmp (a_val, b_val);
+
+	g_free (a_val);
+	g_free (b_val);
+	return ret;
 }
 
 gint
@@ -2396,8 +2406,8 @@ rhythmdb_query_model_title_sort_func (Rh
 				      RhythmDBEntry *b,
 				      gpointer data)
 {
-	const char *a_val;
-	const char *b_val;
+	char *a_val;
+	char *b_val;
 	gint ret;
 
 	/* Sort by album name */
@@ -2414,10 +2424,13 @@ rhythmdb_query_model_title_sort_func (Rh
 	else
 		ret = strcmp (a_val, b_val);
 
-	if (ret != 0)
-		return ret;
-	else
-		return rhythmdb_query_model_location_sort_func (a, b, data);
+	if (ret == 0)
+		ret = rhythmdb_query_model_location_sort_func (a, b, data);
+
+	g_free (a_val);
+	g_free (b_val);
+
+	return ret;
 }
 
 gint
@@ -2425,8 +2438,8 @@ rhythmdb_query_model_album_sort_func (Rh
 				      RhythmDBEntry *b,
 				      gpointer data)
 {
-	const char *a_val;
-	const char *b_val;
+	char *a_val;
+	char *b_val;
 	gulong a_num;
 	gulong b_num;
 	gint ret;
@@ -2445,34 +2458,46 @@ rhythmdb_query_model_album_sort_func (Rh
 	else
 		ret = strcmp (a_val, b_val);
 
-	if (ret != 0)
-		return ret;
+	if (ret != 0) {
+		goto out;
+	}
 
 	/* Then by disc number, */
 	a_num = rhythmdb_entry_get_ulong (a, RHYTHMDB_PROP_DISC_NUMBER);
 	b_num = rhythmdb_entry_get_ulong (b, RHYTHMDB_PROP_DISC_NUMBER);
-	if (a_num != b_num)
-		return (a_num < b_num ? -1 : 1);
+	if (a_num != b_num) {
+		ret = (a_num < b_num ? -1 : 1);
+		goto out;
+	}
 
 	/* by track number */
 	a_num = rhythmdb_entry_get_ulong (a, RHYTHMDB_PROP_TRACK_NUMBER);
 	b_num = rhythmdb_entry_get_ulong (b, RHYTHMDB_PROP_TRACK_NUMBER);
-	if (a_num != b_num)
-		return (a_num < b_num ? -1 : 1);
+	if (a_num != b_num) {
+		ret = (a_num < b_num ? -1 : 1);
+		goto out;
+	}
 
 	/*  by title */
+	g_free (a_val);
+	g_free (b_val);
 	a_val = rhythmdb_entry_get_string (a, RHYTHMDB_PROP_TITLE_SORT_KEY);
 	b_val = rhythmdb_entry_get_string (b, RHYTHMDB_PROP_TITLE_SORT_KEY);
 
 	if (a_val == NULL) {
 		if (b_val == NULL)
-			return 0;
+			ret = 0;
 		else
-			return -1;
-	} else if (b_val == NULL)
-		return 1;
-	else
-		return rhythmdb_query_model_location_sort_func (a, b, data);
+			ret = -1;
+	} else if (b_val == NULL) {
+		ret = 1;
+	} else {
+		ret = rhythmdb_query_model_location_sort_func (a, b, data);
+	}
+ out:
+	g_free (a_val);
+	g_free (b_val);
+	return ret;
 }
 
 gint
@@ -2480,8 +2505,8 @@ rhythmdb_query_model_artist_sort_func (R
 				       RhythmDBEntry *b,
 				       gpointer data)
 {
-	const char *a_val;
-	const char *b_val;
+	char *a_val;
+	char *b_val;
 	gint ret;
 
 	a_val = rhythmdb_entry_get_string (a, RHYTHMDB_PROP_ARTIST_SORT_KEY);
@@ -2497,18 +2522,20 @@ rhythmdb_query_model_artist_sort_func (R
 	else
 		ret = strcmp (a_val, b_val);
 
-	if (ret != 0)
-		return ret;
-	else
-		return rhythmdb_query_model_album_sort_func (a, b, data);
+	if (ret == 0)
+		ret = rhythmdb_query_model_album_sort_func (a, b, data);
+
+	g_free (a_val);
+	g_free (b_val);
+	return ret;
 }
 
 gint
 rhythmdb_query_model_genre_sort_func (RhythmDBEntry *a, RhythmDBEntry *b,
 				      gpointer data)
 {
-	const char *a_val;
-	const char *b_val;
+	char *a_val;
+	char *b_val;
 	gint ret;
 
 	a_val = rhythmdb_entry_get_string (a, RHYTHMDB_PROP_GENRE_SORT_KEY);
@@ -2524,10 +2551,12 @@ rhythmdb_query_model_genre_sort_func (Rh
 	else
 		ret = strcmp (a_val, b_val);
 
-	if (ret != 0)
-		return ret;
-	else
-		return rhythmdb_query_model_artist_sort_func (a, b, data);
+	if (ret == 0)
+		ret = rhythmdb_query_model_artist_sort_func (a, b, data);
+
+	g_free (a_val);
+	g_free (b_val);
+	return ret;
 }
 
 gint
@@ -2601,8 +2630,8 @@ rhythmdb_query_model_string_sort_func (R
 				       RhythmDBEntry *b,
 				       gpointer data)
 {
-	const char *a_val;
-	const char *b_val;
+	char *a_val;
+	char *b_val;
 	gint ret;
 	RhythmDBPropType prop_id;
 
@@ -2620,10 +2649,12 @@ rhythmdb_query_model_string_sort_func (R
 	else
 		ret = strcmp (a_val, b_val);
 
-	if (ret != 0)
-		return ret;
-	else
-		return rhythmdb_query_model_location_sort_func (a, b, data);
+	if (ret == 0)
+		ret = rhythmdb_query_model_location_sort_func (a, b, data);
+
+	g_free (a_val);
+	g_free (b_val);
+	return ret;
 }
 
 static gboolean
Index: rhythmdb/rhythmdb-tree.c
===================================================================
RCS file: /cvs/gnome/rhythmbox/rhythmdb/rhythmdb-tree.c,v
retrieving revision 1.115
diff -p -u -r1.115 rhythmdb-tree.c
--- rhythmdb/rhythmdb-tree.c	23 Jul 2006 16:02:56 -0000	1.115
+++ rhythmdb/rhythmdb-tree.c	26 Jul 2006 16:14:34 -0000
@@ -72,7 +72,7 @@ static gboolean rhythmdb_tree_entry_set 
 static void rhythmdb_tree_entry_delete (RhythmDB *db, RhythmDBEntry *entry);
 static void rhythmdb_tree_entry_delete_by_type (RhythmDB *adb, RhythmDBEntryType type);
 
-static RhythmDBEntry * rhythmdb_tree_entry_lookup_by_location (RhythmDB *db, const char *uri);
+static RhythmDBEntry * rhythmdb_tree_entry_lookup_by_location (RhythmDB *db, RBRefString *uri);
 static void rhythmdb_tree_entry_foreach (RhythmDB *adb, GFunc func, gpointer user_data);
 static void rhythmdb_tree_do_full_query (RhythmDB *db, GPtrArray *query,
 					 RhythmDBQueryResults *results,
@@ -127,13 +127,13 @@ struct RhythmDBTreePrivate
 
 typedef struct
 {
-	char *name;
-	char *value;
+	RBRefString *name;
+	RBRefString *value;
 } RhythmDBUnknownEntryProperty;
 
 typedef struct
 {
-	char *typename;
+	RBRefString *typename;
 	GList *properties;
 } RhythmDBUnknownEntry;
 
@@ -174,15 +174,15 @@ rhythmdb_tree_init (RhythmDBTree *db)
 {
 	db->priv = RHYTHMDB_TREE_GET_PRIVATE (db);
 
-	db->priv->entries = g_hash_table_new (g_str_hash, g_str_equal);
+	db->priv->entries = g_hash_table_new (rb_refstring_hash, rb_refstring_equal);
 
 	db->priv->genres = g_hash_table_new_full (g_direct_hash, g_direct_equal,
 						  NULL, (GDestroyNotify)g_hash_table_destroy);
-	db->priv->unknown_entry_types = g_hash_table_new (g_str_hash, g_str_equal);
+	db->priv->unknown_entry_types = g_hash_table_new (rb_refstring_hash, rb_refstring_equal);
 }
 
 static void
-unparent_entries (const char *uri,
+unparent_entries (gpointer key,
 		  RhythmDBEntry *entry,
 		  RhythmDBTree *db)
 {
@@ -190,7 +190,7 @@ unparent_entries (const char *uri,
 }
 
 static void
-free_unknown_entries (const char *name,
+free_unknown_entries (RBRefString *name,
 		      GList *entries,
 		      gpointer nah)
 {
@@ -200,13 +200,13 @@ free_unknown_entries (const char *name,
 		GList *p;
 
 		entry = (RhythmDBUnknownEntry *)e->data;
-		g_free (entry->typename);
+		rb_refstring_unref (entry->typename);
 		for (p = entry->properties; p != NULL; p = p->next) {
 			RhythmDBUnknownEntryProperty *prop;
 
 			prop = (RhythmDBUnknownEntryProperty *)p->data;
-			g_free (prop->name);
-			g_free (prop->value);
+			rb_refstring_unref (prop->name);
+			rb_refstring_unref (prop->value);
 			g_free (prop);
 		}
 
@@ -342,7 +342,7 @@ rhythmdb_tree_parser_start_element (stru
 				rb_debug ("reading unknown entry");
 				ctx->state = RHYTHMDB_TREE_PARSER_STATE_UNKNOWN_ENTRY;
 				ctx->unknown_entry = g_new0 (RhythmDBUnknownEntry, 1);
-				ctx->unknown_entry->typename = g_strdup (typename);
+				ctx->unknown_entry->typename = rb_refstring_new (typename, NO_DELIMITER);
 			}
 		} else {
 			ctx->in_unknown_elt++;
@@ -367,7 +367,7 @@ rhythmdb_tree_parser_start_element (stru
 		RhythmDBUnknownEntryProperty *prop;
 
 		prop = g_new0 (RhythmDBUnknownEntryProperty, 1);
-		prop->name = g_strdup (name);
+		prop->name = rb_refstring_new (name, NO_DELIMITER);
 
 		ctx->unknown_entry->properties = g_list_prepend (ctx->unknown_entry->properties, prop);
 		ctx->state = RHYTHMDB_TREE_PARSER_STATE_UNKNOWN_ENTRY_PROPERTY;
@@ -433,7 +433,11 @@ rhythmdb_tree_parser_end_element (struct
 					ctx->batch_count = 0;
 				}
 			} else {
-				rb_debug ("found entry with duplicate location %s. merging metadata", ctx->entry->location);
+				char *uri;
+				uri = rb_refstring_get (ctx->entry->location);
+				rb_debug ("found entry with duplicate location %s. merging metadata", uri);
+				g_free (uri);
+
 				entry->play_count += ctx->entry->play_count;
 
 				if (entry->rating < 0.01)
@@ -519,12 +523,18 @@ rhythmdb_tree_parser_end_element (struct
 	case RHYTHMDB_TREE_PARSER_STATE_UNKNOWN_ENTRY_PROPERTY:
 	{
 		RhythmDBUnknownEntryProperty *prop;
+		char *name;
+		char *value;
 
 		g_assert (ctx->unknown_entry->properties);
 		prop = ctx->unknown_entry->properties->data;
 		g_assert (prop->value == NULL);
-		prop->value = g_strdup (ctx->buf->str);
-		rb_debug ("unknown entry property: %s = %s", prop->name, prop->value);
+		prop->value = rb_refstring_new (ctx->buf->str, NO_DELIMITER);
+		name = rb_refstring_get (prop->name);
+		value = rb_refstring_get (prop->value);
+		rb_debug ("unknown entry property: %s = %s", name, value);
+		g_free (value);
+		g_free (name);
 
 		ctx->state = RHYTHMDB_TREE_PARSER_STATE_UNKNOWN_ENTRY;
 		break;
@@ -741,6 +751,8 @@ save_entry_double (struct RhythmDBTreeSa
 	write_elt_name_close (ctx, elt_name);
 }
 
+#define SAVE_ENTRY_STR(_str_) { char *s; s = rb_refstring_get (_str_); if (s) save_entry_string(ctx, elt_name, s); g_free (s); }
+
 /* This code is intended to be highly optimized.  This came at a small
  * readability cost.  Sorry about that.
  */
@@ -780,19 +792,19 @@ save_entry (RhythmDBTree *db,
 		case RHYTHMDB_PROP_TYPE:
 			break;
 		case RHYTHMDB_PROP_TITLE:
-			save_entry_string(ctx, elt_name, rb_refstring_get (entry->title));
+			SAVE_ENTRY_STR (entry->title);
 			break;
 		case RHYTHMDB_PROP_ALBUM:
-			save_entry_string(ctx, elt_name, rb_refstring_get (entry->album));
+			SAVE_ENTRY_STR (entry->album);
 			break;
 		case RHYTHMDB_PROP_ARTIST:
-			save_entry_string(ctx, elt_name, rb_refstring_get (entry->artist));
+			SAVE_ENTRY_STR (entry->artist);
 			break;
 		case RHYTHMDB_PROP_GENRE:
-			save_entry_string(ctx, elt_name, rb_refstring_get (entry->genre));
+			SAVE_ENTRY_STR (entry->genre);
 			break;
 		case RHYTHMDB_PROP_MUSICBRAINZ_TRACKID:
-			save_entry_string(ctx, elt_name, rb_refstring_get (entry->musicbrainz_trackid));
+			SAVE_ENTRY_STR (entry->musicbrainz_trackid);
 			break;
 		case RHYTHMDB_PROP_TRACK_NUMBER:
 			save_entry_ulong (ctx, elt_name, entry->tracknum, FALSE);
@@ -825,20 +837,19 @@ save_entry (RhythmDBTree *db,
 			save_entry_double(ctx, elt_name, entry->album_peak);
 			break;
 		case RHYTHMDB_PROP_LOCATION:
-			save_entry_string(ctx, elt_name, entry->location);
+			SAVE_ENTRY_STR (entry->location);
 			break;
 		case RHYTHMDB_PROP_MOUNTPOINT:
 			/* Avoid crashes on exit when upgrading from 0.8
 			 * and no mountpoint is available from some entries */
-			if (entry->mountpoint) {
-				save_entry_string(ctx, elt_name, rb_refstring_get (entry->mountpoint));
-			}
+			if (entry->mountpoint)
+				SAVE_ENTRY_STR (entry->mountpoint);
 			break;
 		case RHYTHMDB_PROP_FILE_SIZE:
 			save_entry_uint64(ctx, elt_name, entry->file_size);
 			break;
 		case RHYTHMDB_PROP_MIMETYPE:
-			save_entry_string(ctx, elt_name, rb_refstring_get (entry->mimetype));
+			SAVE_ENTRY_STR (entry->mimetype);
 			break;
 		case RHYTHMDB_PROP_MTIME:
 			save_entry_ulong (ctx, elt_name, entry->mtime, FALSE);
@@ -870,27 +881,27 @@ save_entry (RhythmDBTree *db,
 			break;
 		case RHYTHMDB_PROP_DESCRIPTION:
 			if (podcast && podcast->description)
-				save_entry_string(ctx, elt_name, rb_refstring_get (podcast->description));
+				SAVE_ENTRY_STR (podcast->description);
 			break;
 		case RHYTHMDB_PROP_SUBTITLE:
 			if (podcast && podcast->subtitle)
-				save_entry_string(ctx, elt_name, rb_refstring_get (podcast->subtitle));
+				SAVE_ENTRY_STR (podcast->subtitle);
 			break;
 		case RHYTHMDB_PROP_SUMMARY:
 			if (podcast && podcast->summary)
-				save_entry_string(ctx, elt_name, rb_refstring_get (podcast->summary));
+				SAVE_ENTRY_STR (podcast->summary);
 			break;
 		case RHYTHMDB_PROP_LANG:
 			if (podcast && podcast->lang)
-				save_entry_string(ctx, elt_name, rb_refstring_get (podcast->lang));
+				SAVE_ENTRY_STR (podcast->lang);
 			break;
 		case RHYTHMDB_PROP_COPYRIGHT:
 			if (podcast && podcast->copyright)
-				save_entry_string(ctx, elt_name, rb_refstring_get (podcast->copyright));
+				SAVE_ENTRY_STR (podcast->copyright);
 			break;
 		case RHYTHMDB_PROP_IMAGE:
 			if (podcast && podcast->image)
-				save_entry_string(ctx, elt_name, rb_refstring_get (podcast->image));
+				SAVE_ENTRY_STR (podcast->image);
 			break;
 		case RHYTHMDB_PROP_POST_TIME:
 			if (podcast)
@@ -933,7 +944,7 @@ save_entry_type (const char *name,
 }
 
 static void
-save_unknown_entry_type (const char *typename,
+save_unknown_entry_type (RBRefString *typename,
 			 GList *entries,
 			 struct RhythmDBTreeSaveContext *ctx)
 {
@@ -943,6 +954,7 @@ save_unknown_entry_type (const char *typ
 		RhythmDBUnknownEntry *entry;
 		xmlChar *encoded;
 		GList *p;
+		char *str;
 
 		if (ctx->error)
 			return;
@@ -950,7 +962,9 @@ save_unknown_entry_type (const char *typ
 		entry = (RhythmDBUnknownEntry *)t->data;
 
 		RHYTHMDB_FWRITE_STATICSTR ("  <entry type=\"", ctx->handle, ctx->error);
-		encoded	= xmlEncodeEntitiesReentrant (NULL, BAD_CAST entry->typename);
+		str = rb_refstring_get (entry->typename);
+		encoded	= xmlEncodeEntitiesReentrant (NULL, BAD_CAST str);
+		g_free (str);
 		RHYTHMDB_FWRITE (encoded, 1, xmlStrlen (encoded), ctx->handle, ctx->error);
 		g_free (encoded);
 
@@ -959,7 +973,9 @@ save_unknown_entry_type (const char *typ
 		for (p = entry->properties; p != NULL; p = p->next) {
 			RhythmDBUnknownEntryProperty *prop;
 			prop = (RhythmDBUnknownEntryProperty *) p->data;
-			save_entry_string(ctx, (const xmlChar *)prop->name, prop->value);
+			str = rb_refstring_get (prop->name);
+			save_entry_string(ctx, (const xmlChar *)str, rb_refstring_get (prop->value));
+			g_free (str);
 		}
 
 		RHYTHMDB_FWRITE_STATICSTR ("  </entry>\n", ctx->handle, ctx->error);
@@ -1062,31 +1078,34 @@ rhythmdb_tree_entry_new (RhythmDB *rdb,
 	RhythmDBTree *db = RHYTHMDB_TREE (rdb);
 	RhythmDBTreeProperty *artist;
 	RhythmDBTreeProperty *genre;
+	char *uri;
 
 	g_assert (entry != NULL);
 
 	g_return_if_fail (entry->location != NULL);
 
+	uri = rb_refstring_get (entry->location);
 	if (entry->title == NULL) {
-		g_warning ("Entry %s has missing title",entry->location);
-		entry->title = rb_refstring_new (_("Unknown"));
+		g_warning ("Entry %s has missing title", uri);
+		entry->title = rb_refstring_new (_("Unknown"), STRING_DELIMITER);
 	}
 	if (entry->artist == NULL) {
-		g_warning ("Entry %s has missing artist",entry->location);
-		entry->artist = rb_refstring_new (_("Unknown"));
+		g_warning ("Entry %s has missing artist", uri);
+		entry->artist = rb_refstring_new (_("Unknown"), STRING_DELIMITER);
 	}
 	if (entry->album == NULL) {
-		g_warning ("Entry %s has missing album",entry->location);
-		entry->album = rb_refstring_new (_("Unknown"));
+		g_warning ("Entry %s has missing album", uri);
+		entry->album = rb_refstring_new (_("Unknown"), STRING_DELIMITER);
 	}
 	if (entry->genre == NULL) {
-		g_warning ("Entry %s has missing genre",entry->location);
-		entry->genre = rb_refstring_new (_("Unknown"));
+		g_warning ("Entry %s has missing genre", uri);
+		entry->genre = rb_refstring_new (_("Unknown"), STRING_DELIMITER);
 	}
 	if (entry->mimetype == NULL) {
-		g_warning ("Entry %s has missing mimetype",entry->location);
-		entry->mimetype = rb_refstring_new ("unknown/unknown");
+		g_warning ("Entry %s has missing mimetype", uri);
+		entry->mimetype = rb_refstring_new ("unknown/unknown", MIME_DELIMITER);
 	}
+	g_free (uri);
 
 	/* Initialize the tree structure. */
 	genre = get_or_create_genre (db, entry->type, entry->genre);
@@ -1290,17 +1309,17 @@ rhythmdb_tree_entry_set (RhythmDB *adb,
 	{
 	case RHYTHMDB_PROP_LOCATION:
 	{
+		RBRefString *s;
 		/* We have to use the string in the entry itself as the hash key,
 		 * otherwise either we leak it, or the string vanishes when the
 		 * GValue is freed; this means we have to do the entry modification
 		 * here, rather than letting rhythmdb_entry_set_internal do it.
 		 */
-		g_assert (g_hash_table_lookup (db->priv->entries, entry->location) != NULL);
+		g_assert (g_hash_table_remove (db->priv->entries, entry->location));
 
-		g_hash_table_remove (db->priv->entries, entry->location);
-
-		g_free (entry->location);
-		entry->location = g_strdup (g_value_get_string (value));
+		s = rb_refstring_new (g_value_get_string (value), URI_DELIMITER);
+		rb_refstring_unref (entry->location);
+		entry->location = s;
 		g_hash_table_insert (db->priv->entries, entry->location, entry);
 
 		return TRUE;
@@ -1308,8 +1327,10 @@ rhythmdb_tree_entry_set (RhythmDB *adb,
 	case RHYTHMDB_PROP_ALBUM:
 	{
 		const char *albumname = g_value_get_string (value);
+		char *str;
 
-		if (strcmp (rb_refstring_get (entry->album), albumname)) {
+		str = rb_refstring_get (entry->album);
+		if (strcmp (str, albumname)) {
 			RhythmDBTreeProperty *artist;
 			RhythmDBTreeProperty *genre;
 
@@ -1321,19 +1342,24 @@ rhythmdb_tree_entry_set (RhythmDB *adb,
 
 			genre = get_or_create_genre (db, type, entry->genre);
 			artist = get_or_create_artist (db, genre, entry->artist);
-			set_entry_album (db, entry, artist, rb_refstring_new (albumname));
+			set_entry_album (db, entry, artist, rb_refstring_new (albumname, STRING_DELIMITER));
 
 			rb_refstring_unref (entry->genre);
 			rb_refstring_unref (entry->artist);
 			rb_refstring_unref (entry->album);
 		}
+
+		g_free (str);
+
 		break;
 	}
 	case RHYTHMDB_PROP_ARTIST:
 	{
 		const char *artistname = g_value_get_string (value);
+		char *str;
 
-		if (strcmp (rb_refstring_get (entry->artist), artistname)) {
+		str = rb_refstring_get (entry->artist);
+		if (strcmp (str, artistname)) {
 			RhythmDBTreeProperty *new_artist;
 			RhythmDBTreeProperty *genre;
 
@@ -1345,20 +1371,23 @@ rhythmdb_tree_entry_set (RhythmDB *adb,
 
 			genre = get_or_create_genre (db, type, entry->genre);
 			new_artist = get_or_create_artist (db, genre,
-							   rb_refstring_new (artistname));
+							   rb_refstring_new (artistname, STRING_DELIMITER));
 			set_entry_album (db, entry, new_artist, entry->album);
 
 			rb_refstring_unref (entry->genre);
 			rb_refstring_unref (entry->artist);
 			rb_refstring_unref (entry->album);
 		}
+		g_free (str);
 		break;
 	}
 	case RHYTHMDB_PROP_GENRE:
 	{
 		const char *genrename = g_value_get_string (value);
+		char *str;
 
-		if (strcmp (rb_refstring_get (entry->genre), genrename)) {
+		str = rb_refstring_get (entry->genre);
+		if (strcmp (str, genrename)) {
 			RhythmDBTreeProperty *new_genre;
 			RhythmDBTreeProperty *new_artist;
 
@@ -1369,7 +1398,7 @@ rhythmdb_tree_entry_set (RhythmDB *adb,
 			remove_entry_from_album (db, entry);
 
 			new_genre = get_or_create_genre (db, type,
-							 rb_refstring_new (genrename));
+							 rb_refstring_new (genrename, STRING_DELIMITER));
 			new_artist = get_or_create_artist (db, new_genre, entry->artist);
 			set_entry_album (db, entry, new_artist, entry->album);
 
@@ -1377,6 +1406,7 @@ rhythmdb_tree_entry_set (RhythmDB *adb,
 			rb_refstring_unref (entry->artist);
 			rb_refstring_unref (entry->album);
 		}
+		g_free (str);
 		break;
 	}
 	default:
@@ -1394,9 +1424,7 @@ rhythmdb_tree_entry_delete (RhythmDB *ad
 
 	remove_entry_from_album (db, entry);
 
-	g_assert (g_hash_table_lookup (db->priv->entries, entry->location) != NULL);
-
-	g_hash_table_remove (db->priv->entries, entry->location);
+	g_assert (g_hash_table_remove (db->priv->entries, entry->location));
 	rhythmdb_entry_unref (entry);
 }
 
@@ -1406,7 +1434,7 @@ typedef struct {
 } RbEntryRemovalCtxt;
 
 static gboolean
-remove_one_song (gchar *uri,
+remove_one_song (gpointer key,
 		 RhythmDBEntry *entry,
 		 RbEntryRemovalCtxt *ctxt)
 {
@@ -1483,9 +1511,13 @@ rhythmdb_tree_evaluate_query (RhythmDB *
 #define RHYTHMDB_PROPERTY_COMPARE(OP) \
 			switch (rhythmdb_get_property_type (db, data->propid)) { \
 			case G_TYPE_STRING: \
-				if (strcmp (rhythmdb_entry_get_string (entry, data->propid), \
-					    g_value_get_string (data->val)) OP 0) \
-					return FALSE; \
+				{ \
+					char *str; \
+					str = rhythmdb_entry_get_string (entry, data->propid); \
+					if (strcmp (str, g_value_get_string (data->val)) OP 0) \
+						return FALSE;		\
+					g_free (str); \
+				} \
 				break; \
 			case G_TYPE_ULONG: \
 				if (rhythmdb_entry_get_ulong (entry, data->propid) OP \
@@ -1536,12 +1568,14 @@ search_match_properties (RhythmDB *db,
 		gboolean word_found = FALSE;
 
 		for (i = 0; i < G_N_ELEMENTS (props); i++) {
-			const char *entry_string = rhythmdb_entry_get_string (entry, props[i]);
+			char *entry_string = rhythmdb_entry_get_string (entry, props[i]);
 			if (entry_string && (strstr (entry_string, *current) != NULL)) {
 				/* the word was found, go to the next one */
 				word_found = TRUE;
+				g_free (entry_string);
 				break;
 			}
+			g_free (entry_string);
 		}
 		if (!word_found) {
 			/* the word wasn't in any of the properties*/
@@ -1618,18 +1652,22 @@ evaluate_conjunctive_subquery (RhythmDBT
 		case RHYTHMDB_QUERY_PROP_SUFFIX:
 		{
 			const char *value_s;
-			const char *entry_s;
+			char *entry_s;
 
 			g_assert (rhythmdb_get_property_type (db, data->propid) == G_TYPE_STRING);
 
 			value_s = g_value_get_string (data->val);
 			entry_s = rhythmdb_entry_get_string (entry, data->propid);
 
-			if (data->type == RHYTHMDB_QUERY_PROP_PREFIX && !g_str_has_prefix (entry_s, value_s))
+			if (data->type == RHYTHMDB_QUERY_PROP_PREFIX && !g_str_has_prefix (entry_s, value_s)) {
+				g_free (entry_s);
 				return FALSE;
-			if (data->type == RHYTHMDB_QUERY_PROP_SUFFIX && !g_str_has_suffix (entry_s, value_s))
+			}
+			if (data->type == RHYTHMDB_QUERY_PROP_SUFFIX && !g_str_has_suffix (entry_s, value_s)) {
+				g_free (entry_s);
 				return FALSE;
-
+			}
+			g_free (entry_s);
 			break;
 		}
 		case RHYTHMDB_QUERY_PROP_LIKE:
@@ -1644,13 +1682,14 @@ evaluate_conjunctive_subquery (RhythmDBT
 
 				} else {
 					const gchar *value_string = g_value_get_string (data->val);
-					const char *entry_string = rhythmdb_entry_get_string (entry, data->propid);
+					char *entry_string = rhythmdb_entry_get_string (entry, data->propid);
 
 					/* check in case the property is NULL, the value should never be NULL */
 					if (entry_string == NULL)
 						return FALSE;
 
 					islike = (strstr (entry_string, value_string) != NULL);
+					g_free (entry_string);
 				}
 
 				if ((data->type == RHYTHMDB_QUERY_PROP_LIKE) ^ islike)
@@ -1744,7 +1783,7 @@ conjunctive_query_albums (const char *na
 	if (album_query_idx >= 0) {
 		RhythmDBTreeProperty *album;
 		RhythmDBQueryData *qdata = g_ptr_array_index (data->query, album_query_idx);
-		RBRefString *albumname = rb_refstring_new (g_value_get_string (qdata->val));
+		RBRefString *albumname = rb_refstring_new (g_value_get_string (qdata->val), STRING_DELIMITER);
 		GPtrArray *oldquery = data->query;
 
 		data->query = clone_remove_ptr_array_index (data->query, album_query_idx);
@@ -1752,7 +1791,10 @@ conjunctive_query_albums (const char *na
 		album = g_hash_table_lookup (artist->children, albumname);
 
 		if (album != NULL) {
-			conjunctive_query_songs (rb_refstring_get (albumname), album, data);
+			char *str;
+			str = rb_refstring_get (albumname);
+			conjunctive_query_songs (str, album, data);
+			g_free (str);
 		}
 		g_ptr_array_free (data->query, TRUE);
 		data->query = oldquery;
@@ -1787,14 +1829,17 @@ conjunctive_query_artists (const char *n
 	if (artist_query_idx >= 0) {
 		RhythmDBTreeProperty *artist;
 		RhythmDBQueryData *qdata = g_ptr_array_index (data->query, artist_query_idx);
-		RBRefString *artistname = rb_refstring_new (g_value_get_string (qdata->val));
+		RBRefString *artistname = rb_refstring_new (g_value_get_string (qdata->val), STRING_DELIMITER);
 		GPtrArray *oldquery = data->query;
 
 		data->query = clone_remove_ptr_array_index (data->query, artist_query_idx);
 
 		artist = g_hash_table_lookup (genre->children, artistname);
 		if (artist != NULL) {
-			conjunctive_query_albums (rb_refstring_get (artistname), artist, data);
+			char *str;
+			str = rb_refstring_get (artistname);
+			conjunctive_query_albums (str, artist, data);
+			g_free (str);
 		}
 		g_ptr_array_free (data->query, TRUE);
 		data->query = oldquery;
@@ -1832,14 +1877,17 @@ conjunctive_query_genre (RhythmDBTree *d
 	if (genre_query_idx >= 0) {
 		RhythmDBTreeProperty *genre;
 		RhythmDBQueryData *qdata = g_ptr_array_index (data->query, genre_query_idx);
-		RBRefString *genrename = rb_refstring_new (g_value_get_string (qdata->val));
+		RBRefString *genrename = rb_refstring_new (g_value_get_string (qdata->val), STRING_DELIMITER);
 		GPtrArray *oldquery = data->query;
 
 		data->query = clone_remove_ptr_array_index (data->query, genre_query_idx);
 
 		genre = g_hash_table_lookup (genres, genrename);
 		if (genre != NULL) {
-			conjunctive_query_artists (rb_refstring_get (genrename), genre, data);
+			char *str;
+			str = rb_refstring_get (genrename);
+			conjunctive_query_artists (str, genre, data);
+			g_free (str);
 		}
 		g_ptr_array_free (data->query, TRUE);
 		data->query = oldquery;
@@ -2023,7 +2071,7 @@ rhythmdb_tree_do_full_query (RhythmDB *a
 
 static RhythmDBEntry *
 rhythmdb_tree_entry_lookup_by_location (RhythmDB *adb,
-					const char *uri)
+					RBRefString *uri)
 {
 	RhythmDBTree *db = RHYTHMDB_TREE (adb);
 	return g_hash_table_lookup (db->priv->entries, uri);
@@ -2175,15 +2223,19 @@ rhythmdb_tree_entry_type_registered (Rhy
 				     const char *name,
 				     RhythmDBEntryType entry_type)
 {
-	GList *entries;
+	GList *entries = NULL;
 	GList *e;
 	gint count = 0;
 	RhythmDBTree *rdb;
+	RBRefString *rs_name;
+
 	if (name == NULL)
 		return;
 
 	rdb = RHYTHMDB_TREE (db);
-	entries = g_hash_table_lookup (rdb->priv->unknown_entry_types, name);
+	rs_name = rb_refstring_find (name);
+	if (rs_name)
+		entries = g_hash_table_lookup (rdb->priv->unknown_entry_types, rs_name);
 	if (entries == NULL) {
 		rb_debug ("no entries of newly registered type %s loaded from db", name);
 		return;
@@ -2201,11 +2253,15 @@ rhythmdb_tree_entry_type_registered (Rhy
 			RhythmDBUnknownEntryProperty *prop;
 			RhythmDBPropType propid;
 			GValue value = {0,};
+			char *str;
 
 			prop = (RhythmDBUnknownEntryProperty *) p->data;
-			propid = rhythmdb_propid_from_nice_elt_name (db, (const xmlChar *) prop->name);
-
-			rhythmdb_read_encoded_property (db, prop->value, propid, &value);
+ 			str = rb_refstring_get (prop->name);
+			propid = rhythmdb_propid_from_nice_elt_name (db, (const xmlChar *) str);
+			g_free (str);
+			str = rb_refstring_get (prop->value);
+			rhythmdb_read_encoded_property (db, str, propid, &value);
+			g_free (str);
 			rhythmdb_entry_set_internal (db, entry, FALSE, propid, &value);
 			g_value_unset (&value);
 		}
@@ -2216,6 +2272,6 @@ rhythmdb_tree_entry_type_registered (Rhy
 	rb_debug ("handled %d entries of newly registered type %s", count, name);
 	rhythmdb_commit (db);
 
-	g_hash_table_remove (rdb->priv->unknown_entry_types, name);
-	free_unknown_entries (name, entries, NULL);
+	g_hash_table_remove (rdb->priv->unknown_entry_types, rs_name);
+	free_unknown_entries (rs_name, entries, NULL);
 }
Index: rhythmdb/rhythmdb.c
===================================================================
RCS file: /cvs/gnome/rhythmbox/rhythmdb/rhythmdb.c,v
retrieving revision 1.242
diff -p -u -r1.242 rhythmdb.c
--- rhythmdb/rhythmdb.c	25 Jul 2006 11:36:53 -0000	1.242
+++ rhythmdb/rhythmdb.c	26 Jul 2006 16:14:37 -0000
@@ -77,7 +77,7 @@ typedef struct
 		RHYTHMDB_ACTION_LOAD,
 		RHYTHMDB_ACTION_SYNC
 	} type;
-	char *uri;
+	RBRefString *uri;
  	RhythmDBEntryType entry_type;
 } RhythmDBAction;
 
@@ -419,8 +419,8 @@ rhythmdb_init (RhythmDB *db)
 	db->priv->saving = FALSE;
 	db->priv->dirty = FALSE;
 
-	db->priv->empty_string = rb_refstring_new ("");
-	db->priv->octet_stream_str = rb_refstring_new ("application/octet-stream");
+	db->priv->empty_string = rb_refstring_new ("", NO_DELIMITER);
+	db->priv->octet_stream_str = rb_refstring_new ("application/octet-stream", MIME_DELIMITER);
 
 	rhythmdb_init_monitoring (db);
 }
@@ -451,7 +451,12 @@ rhythmdb_execute_multi_stat_info_cb (Gno
 		if (info_result->result == GNOME_VFS_OK) {
 			event->vfsinfo = gnome_vfs_file_info_dup (info_result->file_info);
 		} else {
-			char *unescaped = gnome_vfs_unescape_string_for_display (event->real_uri);
+			char *unescaped;
+			char *str;
+
+			str = rb_refstring_get (event->real_uri);
+			unescaped = gnome_vfs_unescape_string_for_display (str);
+			g_free (str);
 			event->error = g_error_new (RHYTHMDB_ERROR,
 						    RHYTHMDB_ERROR_ACCESS_FAILED,
 						    _("Couldn't access %s: %s"),
@@ -522,8 +527,8 @@ rhythmdb_event_free (RhythmDB *db,
 	}
 	if (result->error)
 		g_error_free (result->error);
-	g_free (result->uri);
-	g_free (result->real_uri);
+	rb_refstring_unref (result->uri);
+	rb_refstring_unref (result->real_uri);
 	if (result->vfsinfo)
 		gnome_vfs_file_info_unref (result->vfsinfo);
 	if (result->metadata)
@@ -789,7 +794,7 @@ sync_entry_changed (RhythmDBEntry *entry
 
 			action = g_new0 (RhythmDBAction, 1);
 			action->type = RHYTHMDB_ACTION_SYNC;
-			action->uri = g_strdup (entry->location);
+			action->uri = rb_refstring_ref (entry->location);
 			g_async_queue_push (db->priv->action_queue, action);
 			break;
 		}
@@ -844,10 +849,9 @@ process_added_entries_cb (RhythmDBEntry 
 		return FALSE;
 
 	if (entry->type == RHYTHMDB_ENTRY_TYPE_SONG) {
-		const gchar *uri;
+		char *uri;
 
-		uri = rhythmdb_entry_get_string (entry,
-						 RHYTHMDB_PROP_LOCATION);
+		uri = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION);
 
 		/* always start remote files hidden*/
 		if (!g_str_has_prefix (uri, "file://")) {
@@ -855,6 +859,8 @@ process_added_entries_cb (RhythmDBEntry 
 		}
 
 		queue_stat_uri (uri, db, RHYTHMDB_ENTRY_TYPE_INVALID);
+
+		g_free (uri);
 	}
 
 	g_assert ((entry->flags & RHYTHMDB_ENTRY_INSERTED) == 0);
@@ -1090,7 +1096,7 @@ rhythmdb_entry_new (RhythmDB *db,
 	}
 
 	ret = rhythmdb_entry_allocate (db, type);
-	ret->location = g_strdup (uri);
+	ret->location = rb_refstring_new (uri, URI_DELIMITER);
 	klass->impl_entry_new (db, ret);
 	rb_debug ("emitting entry added");
 	rhythmdb_entry_insert (db, ret);
@@ -1119,15 +1125,15 @@ rhythmdb_entry_example_new (RhythmDB *db
 	RhythmDBEntry *ret;
 
 	ret = rhythmdb_entry_allocate (db, type);
-	ret->location = g_strdup (uri);
+	ret->location = rb_refstring_new (uri, URI_DELIMITER);
 
 	if (type == RHYTHMDB_ENTRY_TYPE_SONG) {
 		rb_refstring_unref (ret->artist);
-		ret->artist = rb_refstring_new ("The Beatles");
+		ret->artist = rb_refstring_new ("The Beatles", NO_DELIMITER);
 		rb_refstring_unref (ret->album);
-		ret->album = rb_refstring_new ("Help!");
+		ret->album = rb_refstring_new ("Help!", NO_DELIMITER);
 		rb_refstring_unref (ret->title);
-		ret->title = rb_refstring_new ("Ticket To Ride");
+		ret->title = rb_refstring_new ("Ticket To Ride", NO_DELIMITER);
 		ret->tracknum = 7;
 	} else {
 	}
@@ -1163,8 +1169,8 @@ rhythmdb_entry_finalize (RhythmDBEntry *
 	if (type->pre_entry_destroy)
 		(type->pre_entry_destroy)(entry, type->pre_entry_destroy_data);
 
-	g_free (entry->location);
-	g_free (entry->playback_error);
+	rb_refstring_unref (entry->location);
+	rb_refstring_unref (entry->playback_error);
 	rb_refstring_unref (entry->title);
 	rb_refstring_unref (entry->genre);
 	rb_refstring_unref (entry->artist);
@@ -1442,7 +1448,7 @@ rhythmdb_process_stat_event (RhythmDB *d
 	RhythmDBEntry *entry;
 	RhythmDBAction *action;
 
-	entry = rhythmdb_entry_lookup_by_location (db, event->real_uri);
+	entry = rhythmdb_entry_lookup_by_location_refstring (db, event->real_uri);
 	if (entry) {
 		time_t mtime = (time_t) entry->mtime;
 
@@ -1456,14 +1462,14 @@ rhythmdb_process_stat_event (RhythmDB *d
 			if (!is_ghost_entry (entry)) {
 				rhythmdb_entry_set_visibility (db, entry, FALSE);
 			} else {
-				rb_debug ("error accessing %s: %s", event->real_uri,
+				rb_debug ("error accessing %s: %s", rb_refstring_get (event->real_uri),
 					  event->error->message);
 				rhythmdb_entry_delete (db, entry);
 			}
 		} else {
 			GValue val = {0, };
 			GTimeVal time;
-			const char *mount_point;
+			char *mount_point;
 
 			rhythmdb_entry_set_visibility (db, entry, TRUE);
 
@@ -1473,9 +1479,12 @@ rhythmdb_process_stat_event (RhythmDB *d
 			 */
 			mount_point = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_MOUNTPOINT);
 			if (mount_point == NULL) {
-				rhythmdb_entry_set_mount_point (db, entry,
-								event->real_uri);
+				char *str;
+				str = rb_refstring_get (event->real_uri);
+				rhythmdb_entry_set_mount_point (db, entry, str);
+				g_free (str);
 			}
+			g_free (mount_point);
 
 			/* Update last seen time. It will also be updated
 			 * upon saving and when a volume is unmounted
@@ -1497,17 +1506,29 @@ rhythmdb_process_stat_event (RhythmDB *d
 			g_value_unset (&val);
 
 			if (mtime == event->vfsinfo->mtime) {
-				rb_debug ("not modified: %s", event->real_uri);
+				char *uri;
+				uri = rb_refstring_get (event->real_uri);
+				rb_debug ("not modified: %s", uri);
+				g_free (uri);
+
 				/* monitor the file for changes */
-				if (eel_gconf_get_boolean (CONF_MONITOR_LIBRARY))
-					rhythmdb_monitor_uri_path (db, entry->location, NULL /* FIXME */);
+				if (eel_gconf_get_boolean (CONF_MONITOR_LIBRARY)) {
+					char *str;
+					str = rb_refstring_get (entry->location);
+					rhythmdb_monitor_uri_path (db, str, NULL /* FIXME */);
+					g_free (str);
+				}
 			} else {
 				RhythmDBEvent *new_event;
+				char *uri;
+				uri = rb_refstring_get (event->real_uri);
+
+				rb_debug ("changed: %s", uri);
+				g_free (uri);
 
-				rb_debug ("changed: %s", event->real_uri);
 				new_event = g_new0 (RhythmDBEvent, 1);
 				new_event->db = db;
-				new_event->uri = g_strdup (event->real_uri);
+				new_event->uri = rb_refstring_ref (event->real_uri);
 				new_event->type = RHYTHMDB_EVENT_FILE_CREATED_OR_MODIFIED;
 				g_async_queue_push (db->priv->event_queue,
 						    new_event);
@@ -1516,11 +1537,14 @@ rhythmdb_process_stat_event (RhythmDB *d
 
 		rhythmdb_commit (db);
 	} else {
+		char *uri;
 		action = g_new0 (RhythmDBAction, 1);
 		action->type = RHYTHMDB_ACTION_LOAD;
-		action->uri = g_strdup (event->real_uri);
+		action->uri = rb_refstring_ref (event->real_uri);
 		action->entry_type = event->entry_type;
-		rb_debug ("queuing a RHYTHMDB_ACTION_LOAD: %s", action->uri);
+		uri = rb_refstring_get (action->uri);
+		rb_debug ("queuing a RHYTHMDB_ACTION_LOAD: %s", uri);
+		g_free (uri);
 		g_async_queue_push (db->priv->action_queue, action);
 	}
 }
@@ -1549,13 +1573,16 @@ rhythmdb_add_import_error_entry (RhythmD
 		error_entry_type = RHYTHMDB_ENTRY_TYPE_IGNORE;
 	}
 
-	entry = rhythmdb_entry_lookup_by_location (db, event->real_uri);
+	entry = rhythmdb_entry_lookup_by_location_refstring (db, event->real_uri);
 	if (entry) {
 		RhythmDBEntryType entry_type = rhythmdb_entry_get_entry_type (entry);
 		if (entry_type != RHYTHMDB_ENTRY_TYPE_IMPORT_ERROR &&
 		    entry_type != RHYTHMDB_ENTRY_TYPE_IGNORE) {
+			char *uri;
 			/* FIXME we've successfully read this file before.. so what should we do? */
-			rb_debug ("%s already exists in the library.. ignoring import error?", event->real_uri);
+			uri = rb_refstring_get (event->real_uri);
+			rb_debug ("%s already exists in the library.. ignoring import error?", uri);
+			g_free (uri);
 			return;
 		}
 
@@ -1585,8 +1612,12 @@ rhythmdb_add_import_error_entry (RhythmD
 	}
 
 	if (entry == NULL) {
+		char *str;
 		/* create a new import error or ignore entry */
-		entry = rhythmdb_entry_new (db, error_entry_type, event->real_uri);
+		str = rb_refstring_get (event->real_uri);
+		entry = rhythmdb_entry_new (db, error_entry_type, str);
+		g_free (str);
+
 		if (entry == NULL)
 			return;
 
@@ -1609,7 +1640,12 @@ rhythmdb_add_import_error_entry (RhythmD
 		}
 
 		/* record the mount point so we can delete entries for unmounted volumes */
-		rhythmdb_entry_set_mount_point (db, entry, event->real_uri);
+		{
+			char *str;
+			str = rb_refstring_get (event->real_uri);
+			rhythmdb_entry_set_mount_point (db, entry, str);
+			g_free (str);
+		}
 
 		rhythmdb_entry_set_visibility (db, entry, TRUE);
 
@@ -1646,7 +1682,7 @@ rhythmdb_process_metadata_load (RhythmDB
 
 	g_get_current_time (&time);
 
-	entry = rhythmdb_entry_lookup_by_location (db, event->real_uri);
+	entry = rhythmdb_entry_lookup_by_location_refstring (db, event->real_uri);
 
 	if (entry != NULL) {
 		if ((event->entry_type != RHYTHMDB_ENTRY_TYPE_INVALID) &&
@@ -1659,10 +1695,15 @@ rhythmdb_process_metadata_load (RhythmDB
 	}
 
 	if (entry == NULL) {
+		char *str;
+
 		if (event->entry_type == RHYTHMDB_ENTRY_TYPE_INVALID)
 			event->entry_type = RHYTHMDB_ENTRY_TYPE_SONG;
 
-		entry = rhythmdb_entry_new (db, event->entry_type, event->real_uri);
+		str = rb_refstring_get (event->real_uri);
+		entry = rhythmdb_entry_new (db, event->entry_type, str);
+		g_free (str);
+
 		if (entry == NULL) {
 			rb_debug ("entry already exists");
 			return TRUE;
@@ -1713,12 +1754,21 @@ rhythmdb_process_metadata_load (RhythmDB
 	g_value_unset (&value);
 
 	/* Remember the mount point of the volume the song is on */
-	rhythmdb_entry_set_mount_point (db, entry, event->real_uri);
+	{
+		char *str;
+		str = rb_refstring_get (event->real_uri);
+		rhythmdb_entry_set_mount_point (db, entry, str);
+		g_free (str);
+	}
 
 	/* monitor the file for changes */
 	/* FIXME: watch for errors */
-	if (eel_gconf_get_boolean (CONF_MONITOR_LIBRARY) && event->entry_type == RHYTHMDB_ENTRY_TYPE_SONG)
-		rhythmdb_monitor_uri_path (db, entry->location, NULL);
+	if (eel_gconf_get_boolean (CONF_MONITOR_LIBRARY) && event->entry_type == RHYTHMDB_ENTRY_TYPE_SONG) {
+		char *str;
+		str = rb_refstring_get (entry->location);
+		rhythmdb_monitor_uri_path (db, str, NULL);
+		g_free (str);
+	}
 
 	rhythmdb_add_timeout_commit (db, FALSE);
 
@@ -1748,7 +1798,7 @@ rhythmdb_process_file_created_or_modifie
 
 	action = g_new0 (RhythmDBAction, 1);
 	action->type = RHYTHMDB_ACTION_LOAD;
-	action->uri = g_strdup (event->uri);
+	action->uri = rb_refstring_ref (event->uri);
 	action->entry_type = RHYTHMDB_ENTRY_TYPE_INVALID;
 	g_async_queue_push (db->priv->action_queue, action);
 }
@@ -1757,15 +1807,21 @@ static void
 rhythmdb_process_file_deleted (RhythmDB *db,
 			       RhythmDBEvent *event)
 {
-	RhythmDBEntry *entry = rhythmdb_entry_lookup_by_location (db, event->uri);
+	RhythmDBEntry *entry;
+	char *str;
 
-	g_hash_table_remove (db->priv->changed_files, event->uri);
+	entry = rhythmdb_entry_lookup_by_location_refstring (db, event->uri);
+
+	str = rb_refstring_get (event->uri);
+	g_hash_table_remove (db->priv->changed_files, str);
 
 	if (entry) {
-		rb_debug ("deleting entry for %s", event->uri);
+		rb_debug ("deleting entry for %s", str);
 		rhythmdb_entry_set_visibility (db, entry, FALSE);
 		rhythmdb_commit (db);
 	}
+
+	g_free (str);
 }
 
 static gboolean
@@ -1930,7 +1986,12 @@ rhythmdb_execute_stat_info_cb (GnomeVFSA
 	if (info_result->result == GNOME_VFS_OK) {
 		event->vfsinfo = gnome_vfs_file_info_dup (info_result->file_info);
 	} else {
-		char *unescaped = gnome_vfs_unescape_string_for_display (event->real_uri);
+		char *unescaped;
+		char *str;
+
+		str = rb_refstring_get (event->real_uri);
+		unescaped = gnome_vfs_unescape_string_for_display (str);
+		g_free (str);
 		event->error = g_error_new (RHYTHMDB_ERROR,
 					    RHYTHMDB_ERROR_ACCESS_FAILED,
 					    _("Couldn't access %s: %s"),
@@ -1951,7 +2012,7 @@ rhythmdb_execute_stat (RhythmDB *db,
 	GnomeVFSURI *vfs_uri = gnome_vfs_uri_new (uri);
 
 	GList *uri_list = g_list_append (NULL, vfs_uri);
-	event->real_uri = g_strdup (uri);
+	event->real_uri = rb_refstring_new (uri, URI_DELIMITER);
 
 	gnome_vfs_async_get_file_info (&event->handle, uri_list,
 			       GNOME_VFS_FILE_INFO_FOLLOW_LINKS,
@@ -2006,7 +2067,7 @@ queue_stat_uri (const char *uri,
 			g_free (result);
 			gnome_vfs_uri_unref (vfs_uri);
 		} else {
-			result->real_uri = g_strdup (uri);
+			result->real_uri = rb_refstring_new (uri, URI_DELIMITER);
 			g_hash_table_insert (db->priv->stat_events, vfs_uri, result);
 			db->priv->stat_list = g_list_prepend (db->priv->stat_list, vfs_uri);
 		}
@@ -2048,7 +2109,7 @@ rhythmdb_execute_load (RhythmDB *db,
 	GnomeVFSURI *vfs_uri = gnome_vfs_uri_new (uri);
 	GnomeVFSResult vfsresult;
 
-	event->real_uri = rb_uri_resolve_symlink (uri);
+	event->real_uri = rb_refstring_new (rb_uri_resolve_symlink (uri), URI_DELIMITER);
 	event->vfsinfo = gnome_vfs_file_info_new ();
 
 	vfsresult = gnome_vfs_get_file_info (uri,
@@ -2068,9 +2129,11 @@ rhythmdb_execute_load (RhythmDB *db,
 		event->vfsinfo = NULL;
 	} else {
 		if (event->type == RHYTHMDB_EVENT_METADATA_LOAD) {
+			char *str;
 			event->metadata = rb_metadata_new ();
-			rb_metadata_load (event->metadata, event->real_uri,
-					  &event->error);
+			str = rb_refstring_get (event->real_uri);
+			rb_metadata_load (event->metadata, str, &event->error);
+			g_free (str);
 		}
 	}
 
@@ -2101,7 +2164,12 @@ rhythmdb_entry_get (RhythmDB *db,
 	g_assert (G_VALUE_TYPE (val) == rhythmdb_get_property_type (db, propid));
 	switch (rhythmdb_property_type_map[propid]) {
 	case G_TYPE_STRING:
-		g_value_set_string (val, rhythmdb_entry_get_string (entry, propid));
+		{
+			char *str;
+			str = rhythmdb_entry_get_string (entry, propid);
+			g_value_set_string (val, str);
+			g_free (str);
+		}
 		break;
 	case G_TYPE_BOOLEAN:
 		g_value_set_boolean (val, rhythmdb_entry_get_boolean (entry, propid));
@@ -2182,26 +2250,34 @@ action_thread_main (RhythmDB *db)
 		switch (action->type) {
 		case RHYTHMDB_ACTION_STAT:
 		{
+			char *str;
+
 			result = g_new0 (RhythmDBEvent, 1);
 			result->db = db;
 			result->type = RHYTHMDB_EVENT_STAT;
 			result->entry_type = action->entry_type;
 
-			rb_debug ("executing RHYTHMDB_ACTION_STAT for \"%s\"", action->uri);
+			str = rb_refstring_get (action->uri);
+			rb_debug ("executing RHYTHMDB_ACTION_STAT for \"%s\"", str);
 
-			rhythmdb_execute_stat (db, action->uri, result);
+			rhythmdb_execute_stat (db, str, result);
+			g_free (str);
 		}
 		break;
 		case RHYTHMDB_ACTION_LOAD:
 		{
+			char *str;
+
 			result = g_new0 (RhythmDBEvent, 1);
 			result->db = db;
 			result->type = RHYTHMDB_EVENT_METADATA_LOAD;
 			result->entry_type = action->entry_type;
 
-			rb_debug ("executing RHYTHMDB_ACTION_LOAD for \"%s\"", action->uri);
+			str = rb_refstring_get (action->uri);
+			rb_debug ("executing RHYTHMDB_ACTION_LOAD for \"%s\"", str);
 
-			rhythmdb_execute_load (db, action->uri, result);
+			rhythmdb_execute_load (db, str, result);
+			g_free (str);
 		}
 		break;
 		case RHYTHMDB_ACTION_SYNC:
@@ -2215,7 +2291,7 @@ action_thread_main (RhythmDB *db)
 				break;
 			}
 
-			entry = rhythmdb_entry_lookup_by_location (db, action->uri);
+			entry = rhythmdb_entry_lookup_by_location_refstring (db, action->uri);
 			if (!entry)
 				break;
 
@@ -2224,11 +2300,13 @@ action_thread_main (RhythmDB *db)
 
 			if (error != NULL) {
 				RhythmDBSaveErrorData *data;
+				char *str;
 
 				data = g_new0 (RhythmDBSaveErrorData, 1);
 				g_object_ref (db);
 				data->db = db;
-				data->uri = g_strdup (action->uri);
+				str = rb_refstring_get (action->uri);
+				data->uri = str;
 				data->error = error;
 				g_idle_add ((GSourceFunc)emit_save_error_idle, data);
 				break;
@@ -2562,25 +2640,25 @@ rhythmdb_entry_set_internal (RhythmDB *d
 			if (entry->title != NULL) {
 				rb_refstring_unref (entry->title);
 			}
-			entry->title = rb_refstring_new (g_value_get_string (value));
+			entry->title = rb_refstring_new (g_value_get_string (value), STRING_DELIMITER);
 			break;
 		case RHYTHMDB_PROP_ALBUM:
 			if (entry->album != NULL) {
 				rb_refstring_unref (entry->album);
 			}
-			entry->album = rb_refstring_new (g_value_get_string (value));
+			entry->album = rb_refstring_new (g_value_get_string (value), STRING_DELIMITER);
 			break;
 		case RHYTHMDB_PROP_ARTIST:
 			if (entry->artist != NULL) {
 				rb_refstring_unref (entry->artist);
 			}
-			entry->artist = rb_refstring_new (g_value_get_string (value));
+			entry->artist = rb_refstring_new (g_value_get_string (value), STRING_DELIMITER);
 			break;
 		case RHYTHMDB_PROP_GENRE:
 			if (entry->genre != NULL) {
 				rb_refstring_unref (entry->genre);
 			}
-			entry->genre = rb_refstring_new (g_value_get_string (value));
+			entry->genre = rb_refstring_new (g_value_get_string (value), STRING_DELIMITER);
 			break;
 		case RHYTHMDB_PROP_TRACK_NUMBER:
 			entry->tracknum = g_value_get_ulong (value);
@@ -2617,13 +2695,13 @@ rhythmdb_entry_set_internal (RhythmDB *d
 			entry->album_peak = g_value_get_double (value);
 			break;
 		case RHYTHMDB_PROP_LOCATION:
-			g_free (entry->location);
-			entry->location = g_value_dup_string (value);
+			rb_refstring_unref (entry->location);
+			entry->location = rb_refstring_new (g_value_get_string (value), URI_DELIMITER);
 			break;
 		case RHYTHMDB_PROP_PLAYBACK_ERROR:
-			g_free (entry->playback_error);
+			rb_refstring_unref (entry->playback_error);
 			if (g_value_get_string (value))
-				entry->playback_error = g_value_dup_string (value);
+				entry->playback_error = rb_refstring_new (g_value_get_string (value), STRING_DELIMITER);
 			else
 				entry->playback_error = NULL;
 			break;
@@ -2631,7 +2709,7 @@ rhythmdb_entry_set_internal (RhythmDB *d
 			if (entry->mountpoint != NULL) {
 				rb_refstring_unref (entry->mountpoint);
 			}
-			entry->mountpoint = rb_refstring_new (g_value_get_string (value));
+			entry->mountpoint = rb_refstring_new (g_value_get_string (value), URI_DELIMITER);
 			break;
 		case RHYTHMDB_PROP_FILE_SIZE:
 			entry->file_size = g_value_get_uint64 (value);
@@ -2640,7 +2718,7 @@ rhythmdb_entry_set_internal (RhythmDB *d
 			if (entry->mimetype != NULL) {
 				rb_refstring_unref (entry->mimetype);
 			}
-			entry->mimetype = rb_refstring_new (g_value_get_string (value));
+			entry->mimetype = rb_refstring_new (g_value_get_string (value), MIME_DELIMITER);
 			break;
 		case RHYTHMDB_PROP_MTIME:
 			entry->mtime = g_value_get_ulong (value);
@@ -2664,8 +2742,10 @@ rhythmdb_entry_set_internal (RhythmDB *d
 			entry->flags |= RHYTHMDB_ENTRY_LAST_PLAYED_DIRTY;
 			break;
 		case RHYTHMDB_PROP_MUSICBRAINZ_TRACKID:
-			rb_refstring_unref (entry->musicbrainz_trackid);
-			entry->musicbrainz_trackid = rb_refstring_new (g_value_get_string (value));
+			if (entry->musicbrainz_trackid != NULL) {
+				rb_refstring_unref (entry->musicbrainz_trackid);
+			}
+			entry->musicbrainz_trackid = rb_refstring_new (g_value_get_string (value), NO_DELIMITER);
 			break;
 		case RHYTHMDB_PROP_HIDDEN:
 			if (g_value_get_boolean (value)) {
@@ -2682,38 +2762,38 @@ rhythmdb_entry_set_internal (RhythmDB *d
 		case RHYTHMDB_PROP_DESCRIPTION:
 			g_assert (podcast);
 			rb_refstring_unref (podcast->description);
-			podcast->description = rb_refstring_new (g_value_get_string (value));
+			podcast->description = rb_refstring_new (g_value_get_string (value), STRING_DELIMITER);
 			break;
 		case RHYTHMDB_PROP_SUBTITLE:
 			g_assert (podcast);
 			rb_refstring_unref (podcast->subtitle);
-			podcast->subtitle = rb_refstring_new (g_value_get_string (value));
+			podcast->subtitle = rb_refstring_new (g_value_get_string (value), STRING_DELIMITER);
 			break;
 		case RHYTHMDB_PROP_SUMMARY:
 			g_assert (podcast);
 			rb_refstring_unref (podcast->summary);
-			podcast->summary = rb_refstring_new (g_value_get_string (value));
+			podcast->summary = rb_refstring_new (g_value_get_string (value), STRING_DELIMITER);
 			break;
 		case RHYTHMDB_PROP_LANG:
 			g_assert (podcast);
 			if (podcast->lang != NULL) {
 				rb_refstring_unref (podcast->lang);
 			}
-			podcast->lang = rb_refstring_new (g_value_get_string (value));
+			podcast->lang = rb_refstring_new (g_value_get_string (value), STRING_DELIMITER);
 			break;
 		case RHYTHMDB_PROP_COPYRIGHT:
 			g_assert (podcast);
 			if (podcast->copyright != NULL) {
 				rb_refstring_unref (podcast->copyright);
 			}
-			podcast->copyright = rb_refstring_new (g_value_get_string (value));
+			podcast->copyright = rb_refstring_new (g_value_get_string (value), STRING_DELIMITER);
 			break;
 		case RHYTHMDB_PROP_IMAGE:
 			g_assert (podcast);
 			if (podcast->image != NULL) {
 				rb_refstring_unref (podcast->image);
 			}
-			podcast->image = rb_refstring_new (g_value_get_string (value));
+			podcast->image = rb_refstring_new (g_value_get_string (value), URI_DELIMITER);
 			break;
 		case RHYTHMDB_PROP_POST_TIME:
 			g_assert (podcast);
@@ -2766,10 +2846,10 @@ rhythmdb_entry_sync_mirrored (RhythmDBEn
 
 		old = g_atomic_pointer_get (&entry->last_played_str);
 		if (entry->last_played == 0) {
-			new = rb_refstring_new (never);
+			new = rb_refstring_new (never, NO_DELIMITER);
 		} else {
 			val = eel_strdup_strftime (format, localtime ((glong*)&entry->last_played));
-			new = rb_refstring_new (val);
+			new = rb_refstring_new (val, NO_DELIMITER);
 			g_free (val);
 		}
 
@@ -2792,7 +2872,7 @@ rhythmdb_entry_sync_mirrored (RhythmDBEn
 
 		old = g_atomic_pointer_get (&entry->first_seen_str);
 		val = eel_strdup_strftime (format, localtime ((glong*)&entry->first_seen));
-		new = rb_refstring_new (val);
+		new = rb_refstring_new (val, NO_DELIMITER);
 		g_free (val);
 
 		if (g_atomic_pointer_compare_and_exchange (&entry->first_seen_str, old, new)) {
@@ -2816,7 +2896,7 @@ rhythmdb_entry_sync_mirrored (RhythmDBEn
 		/* only store last seen time as a string for hidden entries */
 		if (entry->flags & RHYTHMDB_ENTRY_HIDDEN) {
 			val = eel_strdup_strftime (format, localtime ((glong*)&entry->last_seen));
-			new = rb_refstring_new (val);
+			new = rb_refstring_new (val, NO_DELIMITER);
 			g_free (val);
 		} else {
 			new = NULL;
@@ -2895,8 +2975,8 @@ rhythmdb_entry_move_to_trash_set_error (
 	rhythmdb_entry_set (db, entry, RHYTHMDB_PROP_PLAYBACK_ERROR, &value);
 	g_value_unset (&value);
 
-	rb_debug ("Deleting %s failed: %s", entry->location,
-			gnome_vfs_result_to_string (res));
+	rb_debug ("Deleting %s failed: %s", rb_refstring_get (entry->location),
+		  gnome_vfs_result_to_string (res));
 }
 
 void
@@ -2906,18 +2986,21 @@ rhythmdb_entry_move_to_trash (RhythmDB *
 	GnomeVFSResult res;
 	GnomeVFSURI *uri, *trash, *dest;
 	char *shortname;
+	char *str;
 
-	uri = gnome_vfs_uri_new (entry->location);
+	str = rb_refstring_get (entry->location);
+	uri = gnome_vfs_uri_new (str);
+	g_free (str);
 	if (uri == NULL) {
 		rhythmdb_entry_move_to_trash_set_error (db, entry, -1);
 		return;
 	}
 
 	res = gnome_vfs_find_directory (uri,
-			GNOME_VFS_DIRECTORY_KIND_TRASH,
-			&trash,
-			TRUE, TRUE,
-			0);
+					GNOME_VFS_DIRECTORY_KIND_TRASH,
+					&trash,
+					TRUE, TRUE,
+					0);
 	if (res != GNOME_VFS_OK || trash == NULL) {
 		/* If the file doesn't exist, or trash isn't support,
 		 * remove it from the db */
@@ -2967,11 +3050,11 @@ rhythmdb_entry_move_to_trash (RhythmDB *
 
 	/* RB can't tell that a file's moved, so no unique names */
 	res = gnome_vfs_xfer_uri (uri, dest,
-			GNOME_VFS_XFER_REMOVESOURCE,
-			GNOME_VFS_XFER_ERROR_MODE_ABORT,
-			GNOME_VFS_XFER_OVERWRITE_MODE_SKIP,
-			rhythmdb_entry_move_to_trash_cb,
-			entry);
+				  GNOME_VFS_XFER_REMOVESOURCE,
+				  GNOME_VFS_XFER_ERROR_MODE_ABORT,
+				  GNOME_VFS_XFER_OVERWRITE_MODE_SKIP,
+				  rhythmdb_entry_move_to_trash_cb,
+				  entry);
 
 	if (res == GNOME_VFS_OK) {
 		rhythmdb_entry_set_visibility (db, entry, FALSE);
@@ -3038,6 +3121,20 @@ RhythmDBEntry *
 rhythmdb_entry_lookup_by_location (RhythmDB *db,
 				   const char *uri)
 {
+	RBRefString *rs;
+
+	rs = rb_refstring_find (uri);
+	if (rs != NULL) {
+		return rhythmdb_entry_lookup_by_location_refstring (db, rs);
+	} else {
+		return NULL;
+	}
+}
+
+RhythmDBEntry *
+rhythmdb_entry_lookup_by_location_refstring (RhythmDB *db,
+					     RBRefString *uri)
+{
 	RhythmDBClass *klass = RHYTHMDB_GET_CLASS (db);
 
 	return klass->impl_lookup_by_location (db, uri);
@@ -3462,12 +3559,13 @@ default_sync_metadata (RhythmDB *db,
 		       GError **error,
 		       gpointer data)
 {
-	const char *uri;
+	char *uri;
 	GError *local_error = NULL;
 
 	uri = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION);
 	rb_metadata_load (db->priv->metadata,
 			  uri, &local_error);
+	g_free (uri);
 	if (local_error != NULL) {
 		g_propagate_error (error, local_error);
 		return;
@@ -3482,7 +3580,7 @@ default_sync_metadata (RhythmDB *db,
 		/* reload the metadata, to revert the db changes */
 		load_action = g_new0 (RhythmDBAction, 1);
 		load_action->type = RHYTHMDB_ACTION_LOAD;
-		load_action->uri = g_strdup (uri);
+		load_action->uri = rb_refstring_ref (entry->location);
 		load_action->entry_type = RHYTHMDB_ENTRY_TYPE_INVALID;
 		g_async_queue_push (db->priv->action_queue, load_action);
 
@@ -3611,10 +3709,13 @@ song_can_sync_metadata (RhythmDB *db,
 			RhythmDBEntry *entry,
 			gpointer data)
 {
-	const char *mimetype;
+	char *mimetype;
+	gboolean ret;
 
 	mimetype = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_MIMETYPE);
-	return rb_metadata_can_save (db->priv->metadata, mimetype);
+	ret = rb_metadata_can_save (db->priv->metadata, mimetype);
+	g_free (mimetype);
+	return ret;
 }
 
 static char *
@@ -3819,19 +3920,12 @@ char *
 rhythmdb_entry_dup_string (RhythmDBEntry *entry,
 			   RhythmDBPropType propid)
 {
-	const char *s;
-
 	g_return_val_if_fail (entry != NULL, NULL);
 
-	s = rhythmdb_entry_get_string (entry, propid);
-	if (s != NULL) {
-		return g_strdup (s);
-	} else {
-		return NULL;
-	}
+	return rhythmdb_entry_get_string (entry, propid);
 }
 
-const char *
+char *
 rhythmdb_entry_get_string (RhythmDBEntry *entry,
 			   RhythmDBPropType propid)
 {
@@ -3876,13 +3970,13 @@ rhythmdb_entry_get_string (RhythmDBEntry
 	case RHYTHMDB_PROP_GENRE_FOLDED:
 		return rb_refstring_get_folded (entry->genre);
 	case RHYTHMDB_PROP_LOCATION:
-		return entry->location;
+		return rb_refstring_get (entry->location);
 	case RHYTHMDB_PROP_MOUNTPOINT:
 		return rb_refstring_get (entry->mountpoint);
 	case RHYTHMDB_PROP_LAST_PLAYED_STR:
 		return rb_refstring_get (entry->last_played_str);
 	case RHYTHMDB_PROP_PLAYBACK_ERROR:
-		return entry->playback_error;
+		return rb_refstring_get (entry->playback_error);
 	case RHYTHMDB_PROP_FIRST_SEEN_STR:
 		return rb_refstring_get (entry->first_seen_str);
 	case RHYTHMDB_PROP_LAST_SEEN_STR:
@@ -3921,6 +4015,46 @@ rhythmdb_entry_get_string (RhythmDBEntry
 		else
 			return NULL;
 
+	default:
+		g_assert_not_reached ();
+		return NULL;
+	}
+}
+
+RBRefString *
+rhythmdb_entry_get_refstring (RhythmDBEntry *entry,
+			      RhythmDBPropType propid)
+{
+	g_return_val_if_fail (entry != NULL, NULL);
+	g_return_val_if_fail (entry->refcount > 0, NULL);
+
+	rhythmdb_entry_sync_mirrored (entry, propid);
+
+	switch (propid) {
+	case RHYTHMDB_PROP_TITLE:
+		return rb_refstring_ref (entry->title);
+	case RHYTHMDB_PROP_ALBUM:
+		return rb_refstring_ref (entry->album);
+	case RHYTHMDB_PROP_ARTIST:
+		return rb_refstring_ref (entry->artist);
+	case RHYTHMDB_PROP_GENRE:
+		return rb_refstring_ref (entry->genre);
+	case RHYTHMDB_PROP_MUSICBRAINZ_TRACKID:
+		return rb_refstring_ref (entry->musicbrainz_trackid);
+	case RHYTHMDB_PROP_MIMETYPE:
+		return rb_refstring_ref (entry->mimetype);
+	case RHYTHMDB_PROP_MOUNTPOINT:
+		return rb_refstring_ref (entry->mountpoint);
+	case RHYTHMDB_PROP_LAST_PLAYED_STR:
+		return rb_refstring_ref (entry->last_played_str);
+	case RHYTHMDB_PROP_FIRST_SEEN_STR:
+		return rb_refstring_ref (entry->first_seen_str);
+	case RHYTHMDB_PROP_LAST_SEEN_STR:
+		return rb_refstring_ref (entry->last_seen_str);
+	case RHYTHMDB_PROP_LOCATION:
+		return rb_refstring_ref (entry->location);
+	case RHYTHMDB_PROP_PLAYBACK_ERROR:
+		return rb_refstring_ref (entry->playback_error);
 	default:
 		g_assert_not_reached ();
 		return NULL;
Index: rhythmdb/rhythmdb.h
===================================================================
RCS file: /cvs/gnome/rhythmbox/rhythmdb/rhythmdb.h,v
retrieving revision 1.94
diff -p -u -r1.94 rhythmdb.h
--- rhythmdb/rhythmdb.h	23 Jul 2006 16:03:00 -0000	1.94
+++ rhythmdb/rhythmdb.h	26 Jul 2006 16:14:37 -0000
@@ -28,6 +28,7 @@
 #include <libxml/tree.h>
 
 #include "config.h"
+#include "rb-refstring.h"
 #include "rhythmdb-query-results.h"
 
 G_BEGIN_DECLS
@@ -215,7 +216,8 @@ typedef struct {
 	GValue new;
 } RhythmDBEntryChange;
 
-const char *rhythmdb_entry_get_string	(RhythmDBEntry *entry, RhythmDBPropType propid);
+char *rhythmdb_entry_get_string	(RhythmDBEntry *entry, RhythmDBPropType propid);
+RBRefString *rhythmdb_entry_get_refstring (RhythmDBEntry *entry, RhythmDBPropType propid);
 char *rhythmdb_entry_dup_string	(RhythmDBEntry *entry, RhythmDBPropType propid);
 gboolean rhythmdb_entry_get_boolean	(RhythmDBEntry *entry, RhythmDBPropType propid);
 guint64 rhythmdb_entry_get_uint64	(RhythmDBEntry *entry, RhythmDBPropType propid);
@@ -274,7 +276,7 @@ typedef struct
 
 	void            (*impl_entry_delete_by_type) (RhythmDB *db, RhythmDBEntryType type);
 
-	RhythmDBEntry *	(*impl_lookup_by_location)(RhythmDB *db, const char *uri);
+	RhythmDBEntry *	(*impl_lookup_by_location)(RhythmDB *db, RBRefString *uri);
 
 	gboolean 	(*impl_evaluate_query)	(RhythmDB *db, GPtrArray *query, RhythmDBEntry *entry);
 
Index: shell/rb-playlist-manager.c
===================================================================
RCS file: /cvs/gnome/rhythmbox/shell/rb-playlist-manager.c,v
retrieving revision 1.113
diff -p -u -r1.113 rb-playlist-manager.c
--- shell/rb-playlist-manager.c	23 Jul 2006 16:04:11 -0000	1.113
+++ shell/rb-playlist-manager.c	26 Jul 2006 16:14:38 -0000
@@ -891,8 +891,8 @@ create_name_from_selection_data (RBPlayl
 			for (l = list; l != NULL; l = g_list_next (l)) {
 				RhythmDBEntry *entry;
 				char          *location;
-				const char    *e_artist;
-				const char    *e_album;
+				char          *e_artist;
+				char          *e_album;
 
 				location = gnome_vfs_uri_to_string ((const GnomeVFSURI *) l->data, 0);
 				if (location == NULL) {
@@ -928,7 +928,8 @@ create_name_from_selection_data (RBPlayl
 				    && strcmp (album, e_album) != 0) {
 					mixed_albums = TRUE;
 				}
-
+				g_free (e_album);
+				g_free (e_artist);
 				/* if there is a mix of both then stop */
 				if (mixed_artists && mixed_albums) {
 					break;
Index: shell/rb-shell-player.c
===================================================================
RCS file: /cvs/gnome/rhythmbox/shell/rb-shell-player.c,v
retrieving revision 1.254
diff -p -u -r1.254 rb-shell-player.c
--- shell/rb-shell-player.c	23 Jul 2006 16:04:11 -0000	1.254
+++ shell/rb-shell-player.c	26 Jul 2006 16:14:41 -0000
@@ -527,7 +527,7 @@ volume_pre_unmount_cb (GnomeVFSVolumeMon
 	gchar *uri_mount_point;
 	gchar *volume_mount_point;
 	RhythmDBEntry *entry;
-	const char *uri;
+	char *uri;
 	gboolean playing;
 
 	rb_shell_player_get_playing (player, &playing, NULL);
@@ -543,6 +543,8 @@ volume_pre_unmount_cb (GnomeVFSVolumeMon
 
 	uri = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION);
 	uri_mount_point = rb_uri_get_mount_point (uri);
+	g_free (uri);
+
 	volume_mount_point = gnome_vfs_volume_get_activation_uri (volume);
 
 	if (uri_mount_point && volume_mount_point &&
@@ -600,6 +602,7 @@ rb_shell_player_handle_eos_unlocked (RBS
 {
 	RhythmDBEntry *entry;
 	RBSource *source;
+	char *str;
 
 	source = player->priv->current_playing_source;
 
@@ -660,12 +663,14 @@ rb_shell_player_handle_eos_unlocked (RBS
 		break;
 	}
 
-	if (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_PLAYBACK_ERROR) == NULL) {
+	str = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_PLAYBACK_ERROR);
+	if (str == NULL) {
 		rb_debug ("updating play statistics");
 		rb_source_update_play_statistics (source,
 						  player->priv->db,
 						  entry);
 	}
+	g_free (str);
 
 	if (entry != NULL) {
 		rhythmdb_entry_unref (entry);
@@ -1288,7 +1293,7 @@ rb_shell_player_set_playing_entry (RBShe
 				   GError **error)
 {
 	GError *tmp_error = NULL;
-	const char *location;
+	char *location;
 	GValue val = {0,};
 
 	g_return_val_if_fail (player->priv->current_playing_source != NULL, TRUE);
@@ -1321,6 +1326,7 @@ rb_shell_player_set_playing_entry (RBShe
 	g_signal_emit (G_OBJECT (player),
 		       rb_shell_player_signals[PLAYING_URI_CHANGED], 0,
 		       location);
+	g_free (location);
 
 	rb_shell_player_sync_with_source (player);
 	rb_shell_player_sync_buttons (player);
@@ -2252,7 +2258,7 @@ rb_shell_player_entry_changed_cb (Rhythm
 {
 	GSList *t;
 	gboolean synced = FALSE;
-	const char *location;
+	char *location;
 	RhythmDBEntry *playing_entry;
 
 	playing_entry = rb_shell_player_get_playing_entry (player);
@@ -2302,6 +2308,8 @@ rb_shell_player_entry_changed_cb (Rhythm
 		}
 	}
 
+	g_free (location);
+
 	if (playing_entry != NULL) {
 		rhythmdb_entry_unref (playing_entry);
 	}
@@ -2310,8 +2318,8 @@ rb_shell_player_entry_changed_cb (Rhythm
 static void
 rb_shell_player_sync_with_source (RBShellPlayer *player)
 {
-	const char *entry_title = NULL;
-	const char *artist = NULL;
+	char *entry_title = NULL;
+	char *artist = NULL;
 	char *title;
 	RhythmDBEntry *entry;
 
@@ -2345,6 +2353,8 @@ rb_shell_player_sync_with_source (RBShel
 		rb_header_set_title (player->priv->header_widget, title);
 	else
 		rb_header_set_title (player->priv->header_widget, entry_title);
+	g_free (artist);
+	g_free (entry_title);
 	g_free (title);
 
 	rb_header_set_playing_entry (player->priv->header_widget, entry);
@@ -2806,7 +2816,7 @@ info_available_cb (RBPlayer *mmplayer,
 	case RB_METADATA_FIELD_GENRE:
 	{
 		const char *genre = g_value_get_string (value);
-		const char *existing;
+		char *existing;
 		if (!g_utf8_validate (genre, -1, NULL)) {
 			g_warning ("Invalid UTF-8 from internet radio: %s", genre);
 			goto out_unlock;
@@ -2823,13 +2833,14 @@ info_available_cb (RBPlayer *mmplayer,
 		} else {
 			rb_debug ("iradio station already has genre: %s; ignoring %s", existing, genre);
 		}
+		g_free (existing);
 		break;
 	}
 	case RB_METADATA_FIELD_COMMENT:
 	{
 		const char *name = g_value_get_string (value);
-		const char *existing;
-		const char *location;
+		char *existing;
+		char *location;
 
 		if (!g_utf8_validate (name, -1, NULL)) {
 			g_warning ("Invalid UTF-8 from internet radio: %s", name);
@@ -2853,6 +2864,8 @@ info_available_cb (RBPlayer *mmplayer,
 		} else {
 			rb_debug ("iradio station already has title: %s; ignoring %s", existing, name);
 		}
+		g_free (location);
+		g_free (existing);
 		break;
 	}
 	case RB_METADATA_FIELD_BITRATE:
@@ -2903,7 +2916,7 @@ buffering_cb (RBPlayer *mmplayer,
 
 gboolean
 rb_shell_player_get_playing_path (RBShellPlayer *shell_player,
-				  const gchar **path,
+				  char **path,
 				  GError **error)
 {
 	RhythmDBEntry *entry;
Index: shell/rb-shell-player.h
===================================================================
RCS file: /cvs/gnome/rhythmbox/shell/rb-shell-player.h,v
retrieving revision 1.46
diff -p -u -r1.46 rb-shell-player.h
--- shell/rb-shell-player.h	14 Jul 2006 12:30:52 -0000	1.46
+++ shell/rb-shell-player.h	26 Jul 2006 16:14:41 -0000
@@ -121,7 +121,7 @@ gboolean		rb_shell_player_get_playing	(R
 							 GError **error);
 
 gboolean		rb_shell_player_get_playing_path(RBShellPlayer *shell_player,
-							 const gchar **path,
+							 char **path,
 							 GError **error);
 
 void			rb_shell_player_set_playback_state(RBShellPlayer *player,
Index: shell/rb-shell.c
===================================================================
RCS file: /cvs/gnome/rhythmbox/shell/rb-shell.c,v
retrieving revision 1.467
diff -p -u -r1.467 rb-shell.c
--- shell/rb-shell.c	23 Jul 2006 16:04:14 -0000	1.467
+++ shell/rb-shell.c	26 Jul 2006 16:14:42 -0000
@@ -1705,16 +1705,21 @@ rb_shell_db_entry_added_cb (RhythmDB *db
 			    RhythmDBEntry *entry,
 			    RBShell *shell)
 {
+	char *loc;
+
 	if (shell->priv->pending_entry == NULL)
 		return;
 
-	rb_debug ("got entry added for %s", entry->location);
-	if (strcmp (entry->location, shell->priv->pending_entry) == 0) {
+	loc = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION);
+	rb_debug ("got entry added for %s", loc);
+	if (strcmp (loc, shell->priv->pending_entry) == 0) {
 		rb_shell_play_entry (shell, entry);
 
 		g_free (shell->priv->pending_entry);
 		shell->priv->pending_entry = NULL;
 	}
+
+	g_free (loc);
 }
 
 RBSource *
@@ -1889,39 +1894,26 @@ rb_shell_playing_entry_changed_cb (RBShe
 				   RhythmDBEntry *entry,
 				   RBShell *shell)
 {
-/*	RBRemoteSong song; */
 	char *notifytitle;
+	char *artist;
+	char *album;
+	char *title;
+
+	artist = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ARTIST);
+	album = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ALBUM);
+	title = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_TITLE);
 
-	/* emit remote song_changed notification */
-	/*
-	song.title = g_strdup (rb_refstring_get (entry->title));
-	song.artist = g_strdup (rb_refstring_get (entry->artist));
-	song.genre = g_strdup (rb_refstring_get (entry->genre));
-	song.album = g_strdup (rb_refstring_get (entry->album));
-	song.uri = g_strdup (entry->location);
-
-	song.track_number = entry->tracknum;
-	song.disc_number = entry->discnum;
-	song.duration = entry->duration;
-	song.bitrate = entry->bitrate;
-	song.filesize = entry->file_size;
-	song.rating = entry->rating;
-	song.play_count = entry->play_count;
-	song.last_played = entry->last_played;
-
-	g_signal_emit_by_name (RB_REMOTE_PROXY (shell), "song_changed", &song);
-	*/
-
-	/* Translators: by Artist from Album*/
-	notifytitle = g_strdup_printf (_("by %s from %s"),
-				       rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ARTIST),
-				       rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ALBUM));
+	/* Translators: by Artist from Album */
+	notifytitle = g_strdup_printf (_("by %s from %s"), artist, album);
 	rb_shell_hidden_notify (shell,
 				4000,
-				rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_TITLE),
+				title,
 				NULL,
 				notifytitle);
 	g_free (notifytitle);
+	g_free (title);
+	g_free (album);
+	g_free (artist);
 }
 
 static void
Index: sources/rb-library-source.c
===================================================================
RCS file: /cvs/gnome/rhythmbox/sources/rb-library-source.c,v
retrieving revision 1.180
diff -p -u -r1.180 rb-library-source.c
--- sources/rb-library-source.c	23 Jul 2006 16:04:45 -0000	1.180
+++ sources/rb-library-source.c	26 Jul 2006 16:14:44 -0000
@@ -795,6 +795,8 @@ sanitize_path (const char *str)
 	return res ? res : g_strdup(str);
 }
 
+#define SANITIZE_PROP(_str_, _prop_) { char *s; s = rhythmdb_entry_get_string (entry, _prop_); _str_ = sanitize_path (s); g_free (s); }
+
 /**
  * Parse a filename pattern and replace markers with values from a TrackDetails
  * structure.
@@ -852,16 +854,16 @@ filepath_parse_pattern (const char *patt
 			 */
 			switch (*++p) {
 			case 't':
-				string = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ALBUM));
+				SANITIZE_PROP (string, RHYTHMDB_PROP_ALBUM);
 				break;
 			case 'T':
-				temp = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ALBUM_FOLDED));
+				SANITIZE_PROP (string, RHYTHMDB_PROP_ALBUM_FOLDED);
 				break;
 			case 'a':
-				string = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ARTIST));
+				SANITIZE_PROP (string, RHYTHMDB_PROP_ARTIST);
 				break;
 			case 'A':
-				string = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ARTIST_FOLDED));
+				SANITIZE_PROP (string, RHYTHMDB_PROP_ARTIST_FOLDED);
 				break;
 			/*case 's':
 				string = sanitize_path (album sort name);
@@ -883,16 +885,16 @@ filepath_parse_pattern (const char *patt
 			 */
 			switch (*++p) {
 			case 't':
-				string = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_TITLE));
+				SANITIZE_PROP (string, RHYTHMDB_PROP_TITLE);
 				break;
 			case 'T':
-				string = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_TITLE_FOLDED));
+				SANITIZE_PROP (string, RHYTHMDB_PROP_TITLE_FOLDED);
 				break;
 			case 'a':
-				string = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ARTIST));
+				SANITIZE_PROP (string, RHYTHMDB_PROP_ARTIST);
 				break;
 			case 'A':
-				string = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ARTIST_FOLDED));
+				SANITIZE_PROP (string, RHYTHMDB_PROP_ARTIST_FOLDED);
 				break;
 			/*case 's':
 				string = sanitize_path (artist sort name);
@@ -1059,6 +1061,7 @@ build_filename (RBLibrarySource *source,
 	char *filename;
 	char *string;
 	char *extension = NULL;
+	char *str;
 	GSList *list;
 	const char *layout_path;
 	const char *layout_filename;
@@ -1085,18 +1088,22 @@ build_filename (RBLibrarySource *source,
 	uri = new;
 	g_free (realpath);
 
-	if (g_str_has_prefix (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_MIMETYPE), "audio/x-raw")) {
+	str = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_MIMETYPE);
+	if (g_str_has_prefix (str, "audio/x-raw")) {
 		GMAudioProfile *profile;
 		profile = gm_audio_profile_lookup (preferred_format);
 		if (profile)
 			extension = g_strdup (gm_audio_profile_get_extension (profile));
 	}
+	g_free (str);
 
 	if (extension == NULL) {
 		char *tmp;
 
 		/* use the old extension. strip anything after a '?' for http/daap/etc */
-		extension = g_strdup (g_utf8_strrchr (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION), -1, '.') + 1);
+		str = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION);
+		extension = g_strdup (g_utf8_strrchr (str, -1, '.') + 1);
+		g_free (str);
 
 		tmp = g_utf8_strchr (extension, -1, '?');
 		if (tmp)
@@ -1177,8 +1184,11 @@ impl_paste (RBSource *asource, GList *en
 		RhythmDBEntry *entry = (RhythmDBEntry *)l->data;
 		RhythmDBEntryType entry_type;
 		char *dest;
+		char *str;
 
-		rb_debug ("pasting entry %s", rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION));
+		str = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION);
+		rb_debug ("pasting entry %s", str);
+		g_free (str);
 
 		entry_type = rhythmdb_entry_get_entry_type (entry);
 		if (entry_type == RHYTHMDB_ENTRY_TYPE_SONG)
Index: sources/rb-playlist-source.c
===================================================================
RCS file: /cvs/gnome/rhythmbox/sources/rb-playlist-source.c,v
retrieving revision 1.128
diff -p -u -r1.128 rb-playlist-source.c
--- sources/rb-playlist-source.c	25 Jul 2006 12:06:10 -0000	1.128
+++ sources/rb-playlist-source.c	26 Jul 2006 16:14:45 -0000
@@ -247,7 +247,8 @@ rb_playlist_source_constructor (GType ty
 	g_object_unref (db);
 	g_object_unref (shell);
 
-	source->priv->entries = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+	source->priv->entries = g_hash_table_new_full (rb_refstring_hash, rb_refstring_equal,
+						       (GDestroyNotify)rb_refstring_unref, NULL);
 
 	source->priv->songs = rb_entry_view_new (source->priv->db,
 						 shell_player,
@@ -711,15 +712,16 @@ rb_playlist_source_row_deleted (GtkTreeM
 				RBPlaylistSource *source)
 {
 	RhythmDBEntry *entry;
-	const char *location;
+	RBRefString *location;
 
 	entry = rhythmdb_query_model_tree_path_to_entry (RHYTHMDB_QUERY_MODEL (model),
 							 path);
 
-	location = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION);
+	location = rhythmdb_entry_get_refstring (entry, RHYTHMDB_PROP_LOCATION);
 	if (g_hash_table_remove (source->priv->entries, location))
 		source->priv->dirty = TRUE;
 
+	rb_refstring_unref (location);
 	rhythmdb_entry_unref (entry);
 }
 
@@ -728,14 +730,16 @@ rb_playlist_source_entry_added_cb (Rhyth
 				   RhythmDBEntry *entry,
 				   RBPlaylistSource *source)
 {
-	const char *location;
+	RBRefString *location;
 
-	location = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION);
+	location = rhythmdb_entry_get_refstring (entry, RHYTHMDB_PROP_LOCATION);
 
 	if (g_hash_table_lookup (source->priv->entries, location)) {
 		rhythmdb_query_model_add_entry (source->priv->model, entry, -1);
 		source->priv->dirty = TRUE;
 	}
+
+	rb_refstring_unref (location);
 }
 
 static void
@@ -834,22 +838,38 @@ gboolean
 rb_playlist_source_location_in_map (RBPlaylistSource *source,
 				    const char *location)
 {
+	RBRefString *refstr;
+	gboolean found;
+
 	g_return_val_if_fail (RB_IS_PLAYLIST_SOURCE (source), FALSE);
 
-	return (g_hash_table_lookup (source->priv->entries, location) != NULL);
+	refstr = rb_refstring_find (location);
+	if (refstr == NULL) {
+		return FALSE;
+	}
+
+	found = (g_hash_table_lookup (source->priv->entries, refstr) != NULL);
+	rb_refstring_unref (refstr);
+
+	return found;
 }
 
 gboolean
 rb_playlist_source_add_to_map (RBPlaylistSource *source,
 			       const char *location)
 {
+	RBRefString *refstr;
+
 	g_return_val_if_fail (RB_IS_PLAYLIST_SOURCE (source), FALSE);
 
-	if (g_hash_table_lookup (source->priv->entries, location)) {
+	refstr = rb_refstring_new (location, "/");
+	if (g_hash_table_lookup (source->priv->entries, refstr)) {
+		rb_refstring_unref (refstr);
 		return FALSE;
 	}
 
 	g_hash_table_insert (source->priv->entries,
-			     g_strdup (location), GINT_TO_POINTER (1));
+			     refstr, GINT_TO_POINTER (1));
+
 	return TRUE;
 }
Index: sources/rb-podcast-source.c
===================================================================
RCS file: /cvs/gnome/rhythmbox/sources/rb-podcast-source.c,v
retrieving revision 1.75
diff -p -u -r1.75 rb-podcast-source.c
--- sources/rb-podcast-source.c	25 Jul 2006 12:06:10 -0000	1.75
+++ sources/rb-podcast-source.c	26 Jul 2006 16:14:45 -0000
@@ -1527,13 +1527,15 @@ rb_podcast_source_post_feed_cell_data_fu
 
 {
 	RhythmDBEntry *entry;
-	const gchar *album;
+	char *album;
 
 	gtk_tree_model_get (tree_model, iter, 0, &entry, -1);
 	album = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ALBUM);
 
 	g_object_set (renderer, "text", album, NULL);
 
+	g_free (album);
+
 	rhythmdb_entry_unref (entry);
 }
 
@@ -1590,7 +1592,7 @@ rb_podcast_source_feed_title_cell_data_f
 	entry = rhythmdb_entry_lookup_by_location (source->priv->db, title);
 	if (entry != NULL) {
 		g_free (title);
-		title = g_strdup (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_TITLE));
+		title = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_TITLE);
 	}
 
 	if (is_all) {
@@ -1740,11 +1742,12 @@ rb_podcast_source_start_download_cb (RBP
 				     RBPodcastSource *source)
 {
 	RBShell *shell = rb_podcast_source_get_shell (source);
-	const gchar *podcast_name = rhythmdb_entry_get_string(entry, RHYTHMDB_PROP_TITLE);
+	char *podcast_name = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_TITLE);
 
 	rb_debug ("Start download");
 	rb_shell_hidden_notify (shell, 4000, _("Downloading podcast"), NULL, podcast_name);
 	g_object_unref (shell);
+	g_free (podcast_name);
 }
 
 static void
@@ -1753,11 +1756,12 @@ rb_podcast_source_finish_download_cb (RB
 				      RBPodcastSource *source)
 {
 	RBShell *shell = rb_podcast_source_get_shell (source);
-	const gchar *podcast_name = rhythmdb_entry_get_string(entry, RHYTHMDB_PROP_TITLE);
+	char *podcast_name = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_TITLE);
 
 	rb_debug ("Finish download");
 	rb_shell_hidden_notify (shell, 4000, _("Finished downloading podcast"), NULL, podcast_name);
 	g_object_unref (shell);
+	g_free (podcast_name);
 }
 
 static void
@@ -1766,11 +1770,12 @@ rb_podcast_source_feed_updates_avaliable
 					     RBPodcastSource *source)
 {
 	RBShell *shell = rb_podcast_source_get_shell (source);
-	const gchar *podcast_name = rhythmdb_entry_get_string(entry, RHYTHMDB_PROP_TITLE);
+	char *podcast_name = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_TITLE);
 
 	rb_debug ("Updates avaliable");
 	rb_shell_hidden_notify (shell, 4000, _("New updates avaliable from"), NULL, podcast_name);
 	g_object_unref (shell);
+	g_free (podcast_name);
 
 }
 
@@ -1834,7 +1839,7 @@ rb_podcast_source_post_feed_cell_sort_fu
 					    RhythmDBEntry *b,
 					    RhythmDBQueryModel *model)
 {
-	const char *a_str, *b_str;
+	char *a_str, *b_str;
 	gint ret;
 
 	/* feeds */
@@ -1843,21 +1848,29 @@ rb_podcast_source_post_feed_cell_sort_fu
 
 	ret = strcmp (a_str, b_str);
 	if (ret != 0)
-		return ret;
+		goto out;
 
 	/* titles */
+	g_free (a_str);
+	g_free (b_str);
 	a_str = rhythmdb_entry_get_string (a, RHYTHMDB_PROP_TITLE);
 	b_str = rhythmdb_entry_get_string (b, RHYTHMDB_PROP_TITLE);
 
 	ret = strcmp (a_str, b_str);
 	if (ret != 0)
-		return ret;
+		goto out;
 
 	/* location */
+	g_free (a_str);
+	g_free (b_str);
 	a_str = rhythmdb_entry_get_string (a, RHYTHMDB_PROP_LOCATION);
 	b_str = rhythmdb_entry_get_string (b, RHYTHMDB_PROP_LOCATION);
 
 	ret = strcmp (a_str, b_str);
+
+ out:
+	g_free (a_str);
+	g_free (b_str);
 	return ret;
 }
 
Index: sources/rb-source.c
===================================================================
RCS file: /cvs/gnome/rhythmbox/sources/rb-source.c,v
retrieving revision 1.77
diff -p -u -r1.77 rb-source.c
--- sources/rb-source.c	25 Jul 2006 12:06:11 -0000	1.77
+++ sources/rb-source.c	26 Jul 2006 16:14:46 -0000
@@ -1073,7 +1073,7 @@ rb_source_gather_selected_properties (RB
 
 	for (tem = selected; tem; tem = tem->next) {
 		RhythmDBEntry *entry = tem->data;
-		char *val = g_strdup (rhythmdb_entry_get_string (entry, prop));
+		char *val = rhythmdb_entry_get_string (entry, prop);
 		g_hash_table_insert (selected_set, val, NULL);
 	}
 
Index: sources/rb-sourcelist-model.c
===================================================================
RCS file: /cvs/gnome/rhythmbox/sources/rb-sourcelist-model.c,v
retrieving revision 1.30
diff -p -u -r1.30 rb-sourcelist-model.c
--- sources/rb-sourcelist-model.c	23 Jul 2006 16:04:49 -0000	1.30
+++ sources/rb-sourcelist-model.c	26 Jul 2006 16:14:46 -0000
@@ -709,6 +709,7 @@ rb_sourcelist_model_drag_data_get (RbTre
 
 		do {
 			RhythmDBEntry *entry;
+			char *str;
 
 			if (first) {
 				g_string_append(data, "\r\n");
@@ -716,7 +717,9 @@ rb_sourcelist_model_drag_data_get (RbTre
 			}
 
 			entry = rhythmdb_query_model_iter_to_entry (query_model, &iter);
-			g_string_append (data, rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION));
+			str = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION);
+			g_string_append (data, str);
+			g_free (str);
 
 			rhythmdb_entry_unref (entry);
 
Index: sources/rb-static-playlist-source.c
===================================================================
RCS file: /cvs/gnome/rhythmbox/sources/rb-static-playlist-source.c,v
retrieving revision 1.29
diff -p -u -r1.29 rb-static-playlist-source.c
--- sources/rb-static-playlist-source.c	25 Jul 2006 12:06:11 -0000	1.29
+++ sources/rb-static-playlist-source.c	26 Jul 2006 16:14:47 -0000
@@ -527,12 +527,13 @@ impl_save_contents_to_xml (RBPlaylistSou
 		xmlNodePtr child_node = xmlNewChild (node, NULL, RB_PLAYLIST_LOCATION, NULL);
 		RhythmDBEntry *entry;
 		xmlChar *encoded;
-		const char *location;
+		char *location;
 
 		gtk_tree_model_get (GTK_TREE_MODEL (priv->base_model), &iter, 0, &entry, -1);
 
 		location = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION);
 		encoded = xmlEncodeEntitiesReentrant (NULL, BAD_CAST location);
+		g_free (location);
 
 		xmlNodeSetContent (child_node, encoded);
 
@@ -682,20 +683,22 @@ rb_static_playlist_source_add_entry (RBS
 				     RhythmDBEntry *entry,
 				     gint index)
 {
-	const char *location;
+	char *location;
 
 	location = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION);
 	rb_static_playlist_source_add_location_internal (source, location, index);
+	g_free (location);
 }
 
 void
 rb_static_playlist_source_remove_entry (RBStaticPlaylistSource *source,
 					RhythmDBEntry *entry)
 {
-	const char *location;
+	char *location;
 
 	location = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION);
 	rb_static_playlist_source_remove_location (source, location);
+	g_free (location);
 }
 
 void
Index: widgets/rb-entry-view.c
===================================================================
RCS file: /cvs/gnome/rhythmbox/widgets/rb-entry-view.c,v
retrieving revision 1.155
diff -p -u -r1.155 rb-entry-view.c
--- widgets/rb-entry-view.c	25 Jul 2006 12:06:59 -0000	1.155
+++ widgets/rb-entry-view.c	26 Jul 2006 16:14:48 -0000
@@ -197,8 +197,8 @@ type_ahead_search_func (GtkTreeModel *mo
 			gpointer search_data)
 {
 	RhythmDBEntry *entry;
-	gchar *folded;
-	const gchar *entry_folded;
+	char *folded;
+	char *entry_folded;
 	gboolean res;
 
 	gtk_tree_model_get (model, iter, 0, &entry, -1);
@@ -206,10 +206,15 @@ type_ahead_search_func (GtkTreeModel *mo
 	entry_folded = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_TITLE_FOLDED);
 	rhythmdb_entry_unref (entry);
 
-	if (entry_folded == NULL || folded == NULL)
-		return 1;
+	if (entry_folded == NULL || folded == NULL) {
+		res = TRUE;
+		goto out;
+	}
 
 	res = (strstr (entry_folded, folded) == NULL);
+
+ out:
+	g_free (entry_folded);
 	g_free (folded);
 
 	return res;
@@ -633,6 +638,7 @@ rb_entry_view_playing_cell_data_func (Gt
 {
 	RhythmDBEntry *entry;
 	GdkPixbuf *pixbuf = NULL;
+	char *str;
 
 	entry = rhythmdb_query_model_iter_to_entry (view->priv->model, iter);
 
@@ -654,9 +660,11 @@ rb_entry_view_playing_cell_data_func (Gt
 		}
 	}
 
-	if (pixbuf == NULL && rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_PLAYBACK_ERROR)) {
+	str = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_PLAYBACK_ERROR);
+	if (pixbuf == NULL && str != NULL) {
 		pixbuf = view->priv->error_pixbuf;
 	}
+	g_free (str);
 
 	g_object_set (renderer, "pixbuf", pixbuf, NULL);
 
@@ -812,13 +820,14 @@ rb_entry_view_location_cell_data_func (G
 				       struct RBEntryViewCellDataFuncData *data)
 {
 	RhythmDBEntry *entry;
-	const char *location;
+	char *location;
 	char *str;
 
 	entry = rhythmdb_query_model_iter_to_entry (data->view->priv->model, iter);
 
 	location = rhythmdb_entry_get_string (entry, data->propid);
 	str = gnome_vfs_unescape_string_for_display (location);
+	g_free (location);
 
 	g_object_set (renderer, "text", str, NULL);
 	g_free (str);
@@ -834,7 +843,7 @@ rb_entry_view_string_cell_data_func (Gtk
 				     struct RBEntryViewCellDataFuncData *data)
 {
 	RhythmDBEntry *entry;
-	const char *str;
+	char *str;
 
 	entry = rhythmdb_query_model_iter_to_entry (data->view->priv->model, iter);
 
@@ -842,6 +851,7 @@ rb_entry_view_string_cell_data_func (Gtk
 	if (str != NULL) {
 		g_object_set (renderer, "text", str, NULL);
 	}
+	g_free (str);
 
 	rhythmdb_entry_unref (entry);
 }
@@ -1464,7 +1474,7 @@ rb_entry_view_pixbuf_clicked_cb (RBEntry
 {
 	GtkTreePath *path;
 	RhythmDBEntry *entry;
-	const gchar *error;
+	char *error;
 
 	g_return_if_fail (path_string != NULL);
 
@@ -1477,6 +1487,7 @@ rb_entry_view_pixbuf_clicked_cb (RBEntry
 	if (error) {
 		rb_error_dialog (NULL, _("Playback Error"), "%s", error);
 	}
+	g_free (error);
 
 	rhythmdb_entry_unref (entry);
 }
Index: widgets/rb-header.c
===================================================================
RCS file: /cvs/gnome/rhythmbox/widgets/rb-header.c,v
retrieving revision 1.34
diff -p -u -r1.34 rb-header.c
--- widgets/rb-header.c	23 Jul 2006 16:05:02 -0000	1.34
+++ widgets/rb-header.c	26 Jul 2006 16:14:49 -0000
@@ -333,9 +333,8 @@ rb_header_sync (RBHeader *header)
 
 	if (header->priv->entry != NULL) {
 		const char *song = header->priv->title;
-		const char *album;
-		const char *artist;
-
+		char *album;
+		char *artist;
 		gboolean have_duration = (header->priv->duration > 0);
 
 		album = rhythmdb_entry_get_string (header->priv->entry, RHYTHMDB_PROP_ALBUM);
@@ -348,6 +347,9 @@ rb_header_sync (RBHeader *header)
 		} else {
 			label_text = SONG_MARKUP (song);
 		}
+
+		g_free (artist);
+		g_free (album);
 
 		gtk_label_set_markup (GTK_LABEL (header->priv->song), label_text);
 		g_free (label_text);
