[totem-pl-parser] Remove GTK+ dependency.



commit 01ded1197b0553ecb0685ef180e35c053a504b8e
Author: Carlos Garnacho <carlos lanedo com>
Date:   Fri Dec 18 14:25:57 2009 +0100

    Remove GTK+ dependency.
    
    TotemPlPlaylist has been added to replace GtkTreeModel usage in the
    write API, internal playlist implementations now use this to get
    songs/titles in order to write the playlist. Older write API has been
    replaced by totem_pl_parser_save().

 configure.in                                |    2 +-
 docs/reference/totem-pl-parser-docs.xml     |    1 +
 docs/reference/totem-pl-parser-sections.txt |   32 ++-
 docs/reference/totem-pl-parser.types        |    1 +
 plparse/Makefile.am                         |    7 +-
 plparse/plparser.symbols                    |   18 +-
 plparse/totem-pl-parser-lines.c             |   41 ++-
 plparse/totem-pl-parser-lines.h             |   13 +-
 plparse/totem-pl-parser-media.c             |    3 +-
 plparse/totem-pl-parser-misc.c              |    2 +-
 plparse/totem-pl-parser-pla.c               |   50 ++-
 plparse/totem-pl-parser-pla.h               |    8 +-
 plparse/totem-pl-parser-pls.c               |  107 +++---
 plparse/totem-pl-parser-pls.h               |    6 +-
 plparse/totem-pl-parser-podcast.c           |    2 +-
 plparse/totem-pl-parser-private.h           |    8 +-
 plparse/totem-pl-parser-qt.c                |    2 +-
 plparse/totem-pl-parser-smil.c              |    2 +-
 plparse/totem-pl-parser-wm.c                |    2 +-
 plparse/totem-pl-parser-xspf.c              |   58 ++--
 plparse/totem-pl-parser-xspf.h              |   15 +-
 plparse/totem-pl-parser.c                   |  197 ++++------
 plparse/totem-pl-parser.h                   |   43 +--
 plparse/totem-pl-playlist.c                 |  533 +++++++++++++++++++++++++++
 plparse/totem-pl-playlist.h                 |  100 +++++
 totem-plparser-uninstalled.pc.in            |    1 -
 totem-plparser.pc.in                        |    1 -
 27 files changed, 955 insertions(+), 300 deletions(-)
---
diff --git a/configure.in b/configure.in
index fbbb1e2..440e60a 100644
--- a/configure.in
+++ b/configure.in
@@ -57,7 +57,7 @@ AC_SUBST(TOTEM_PL_PARSER_VERSION_MAJOR)
 AC_SUBST(TOTEM_PL_PARSER_VERSION_MINOR)
 AC_SUBST(TOTEM_PL_PARSER_VERSION_MICRO)
 
-pkg_modules="glib-2.0 >= $GLIB_REQS gtk+-2.0 libxml-2.0 gthread-2.0 gio-2.0 >= $GIO_REQS"
+pkg_modules="glib-2.0 >= $GLIB_REQS libxml-2.0 gthread-2.0 gio-2.0 >= $GIO_REQS"
 
 ##################################
 # Checking libgmime dependency
diff --git a/docs/reference/totem-pl-parser-docs.xml b/docs/reference/totem-pl-parser-docs.xml
index b314ffd..8fd5519 100644
--- a/docs/reference/totem-pl-parser-docs.xml
+++ b/docs/reference/totem-pl-parser-docs.xml
@@ -16,6 +16,7 @@
 	<chapter id="api-reference">
 		<title>API Reference</title>
 		<xi:include href="xml/totem-pl-parser.xml"/>
+		<xi:include href="xml/totem-pl-playlist.xml"/>
 		<xi:include href="xml/totem-disc.xml"/>
 	</chapter>
 
diff --git a/docs/reference/totem-pl-parser-sections.txt b/docs/reference/totem-pl-parser-sections.txt
index 07828e0..e2c3308 100644
--- a/docs/reference/totem-pl-parser-sections.txt
+++ b/docs/reference/totem-pl-parser-sections.txt
@@ -6,15 +6,13 @@ TotemPlParserClass
 TotemPlParserResult
 TotemPlParserType
 TotemPlParserError
-TotemPlParserIterFunc
 totem_pl_parser_new
 totem_pl_parser_parse
 totem_pl_parser_parse_async
 totem_pl_parser_parse_finish
 totem_pl_parser_parse_with_base
 totem_pl_parser_parse_with_base_async
-totem_pl_parser_write
-totem_pl_parser_write_with_title
+totem_pl_parser_save
 totem_pl_parser_parse_duration
 totem_pl_parser_parse_date
 totem_pl_parser_add_ignored_scheme
@@ -66,6 +64,34 @@ playlist_started
 </SECTION>
 
 <SECTION>
+<FILE>totem-pl-playlist</FILE>
+<TITLE>TotemPlPlaylist</TITLE>
+TotemPlPlaylist
+TotemPlPlaylistClass
+totem_pl_playlist_new
+totem_pl_playlist_size
+totem_pl_playlist_prepend
+totem_pl_playlist_append
+totem_pl_playlist_insert
+totem_pl_playlist_iter_first
+totem_pl_playlist_iter_next
+totem_pl_playlist_iter_prev
+totem_pl_playlist_get_value
+totem_pl_playlist_get_valist
+totem_pl_playlist_get
+totem_pl_playlist_set_value
+totem_pl_playlist_set_valist
+totem_pl_playlist_set
+<SUBSECTION Standard>
+TOTEM_PL_PLAYLIST
+TOTEM_IS_PL_PLAYLIST
+TOTEM_TYPE_PL_PLAYLIST
+totem_pl_playlist_get_type
+TOTEM_PL_PLAYLIST_CLASS
+TOTEM_IS_PL_PLAYLIST_CLASS
+</SECTION>
+
+<SECTION>
 <FILE>totem-disc</FILE>
 TotemDiscMediaType
 totem_cd_detect_type
diff --git a/docs/reference/totem-pl-parser.types b/docs/reference/totem-pl-parser.types
index 9028680..4324176 100644
--- a/docs/reference/totem-pl-parser.types
+++ b/docs/reference/totem-pl-parser.types
@@ -1 +1,2 @@
 totem_pl_parser_get_type
+totem_pl_playlist_get_type
diff --git a/plparse/Makefile.am b/plparse/Makefile.am
index 4d6a7f8..9addf0e 100644
--- a/plparse/Makefile.am
+++ b/plparse/Makefile.am
@@ -16,6 +16,7 @@ plparserinclude_HEADERS =			\
 	totem-pl-parser-builtins.h		\
 	totem-pl-parser-features.h		\
 	totem-pl-parser.h			\
+	totem-pl-playlist.h			\
 	totem-disc.h				\
 	totem-pl-parser-mini.h
 
@@ -53,6 +54,8 @@ libtotem_plparser_la_SOURCES =			\
 	totem-pl-parser-smil.h			\
 	totem-pl-parser-wm.h			\
 	totem-pl-parser-xspf.h			\
+	totem-pl-playlist.c			\
+	totem-pl-playlist.h			\
 	xmlparser.h xmlparser.c			\
 	xmllexer.h xmllexer.c			\
 	bswap.h
@@ -106,7 +109,9 @@ libtotem_plparser_mini_la_SOURCES =		\
 	totem-pl-parser-wm.c			\
 	totem-pl-parser-wm.h			\
 	totem-pl-parser-xspf.c			\
-	totem-pl-parser-xspf.h
+	totem-pl-parser-xspf.h			\
+	totem-pl-playlist.c			\
+	totem-pl-playlist.h
 
 libtotem_plparser_mini_la_CPPFLAGS = \
 	-I$(top_srcdir)			\
diff --git a/plparse/plparser.symbols b/plparse/plparser.symbols
index 25572d0..5552e19 100644
--- a/plparse/plparser.symbols
+++ b/plparse/plparser.symbols
@@ -24,6 +24,20 @@ totem_pl_parser_relative
 totem_pl_parser_resolve_uri
 totem_pl_parser_result_get_type
 totem_pl_parser_type_get_type
-totem_pl_parser_write
-totem_pl_parser_write_with_title
+totem_pl_parser_save
 totem_pl_parser_metadata_get_type
+totem_pl_playlist_get_type
+totem_pl_playlist_new
+totem_pl_playlist_size
+totem_pl_playlist_prepend
+totem_pl_playlist_append
+totem_pl_playlist_insert
+totem_pl_playlist_iter_first
+totem_pl_playlist_iter_next
+totem_pl_playlist_iter_prev
+totem_pl_playlist_get_value
+totem_pl_playlist_get_valist
+totem_pl_playlist_get
+totem_pl_playlist_set_value
+totem_pl_playlist_set_valist
+totem_pl_playlist_set
diff --git a/plparse/totem-pl-parser-lines.c b/plparse/totem-pl-parser-lines.c
index b114028..0ff94ff 100644
--- a/plparse/totem-pl-parser-lines.c
+++ b/plparse/totem-pl-parser-lines.c
@@ -27,7 +27,7 @@
 
 #ifndef TOTEM_PL_PARSER_MINI
 #include <glib/gi18n-lib.h>
-#include <gtk/gtk.h>
+
 #include <gio/gio.h>
 
 #include "totem-pl-parser.h"
@@ -78,13 +78,15 @@ totem_pl_parser_uri_to_dos (const char *uri, GFile *output)
 }
 
 gboolean
-totem_pl_parser_write_m3u (TotemPlParser *parser, GtkTreeModel *model,
-			   TotemPlParserIterFunc func, GFile *output,
-			   gboolean dos_compatible, gpointer user_data, GError **error)
+totem_pl_parser_save_m3u (TotemPlParser    *parser,
+                          TotemPlPlaylist  *playlist,
+                          GFile            *output,
+                          gboolean          dos_compatible,
+                          GError          **error)
 {
+        TotemPlPlaylistIter iter;
 	GFileOutputStream *stream;
-	int num_entries_total, i;
-	gboolean success;
+	gboolean valid, success;
 	char *buf;
 	char *cr;
 
@@ -93,9 +95,6 @@ totem_pl_parser_write_m3u (TotemPlParser *parser, GtkTreeModel *model,
 		return FALSE;
 
 	cr = dos_compatible ? "\r\n" : "\n";
-	num_entries_total = gtk_tree_model_iter_n_children (model, NULL);
-	if (num_entries_total == 0)
-		return TRUE;
 
 	buf = g_strdup_printf ("#EXTM3U%s", cr);
 	success = totem_pl_parser_write_string (G_OUTPUT_STREAM (stream), buf, error);
@@ -103,18 +102,26 @@ totem_pl_parser_write_m3u (TotemPlParser *parser, GtkTreeModel *model,
 	if (success == FALSE)
 		return FALSE;
 
-	for (i = 1; i <= num_entries_total; i++) {
-		GtkTreeIter iter;
+        valid = totem_pl_playlist_iter_first (playlist, &iter);
+
+        while (valid) {
 		char *uri, *title, *path2;
-		gboolean custom_title;
 		GFile *file;
 
-		if (gtk_tree_model_iter_nth_child (model, &iter, NULL, i - 1) == FALSE)
-			continue;
+                totem_pl_playlist_get (playlist, &iter,
+                                       TOTEM_PL_PARSER_FIELD_URI, &uri,
+                                       TOTEM_PL_PARSER_FIELD_TITLE, &title,
+                                       NULL);
+
+                valid = totem_pl_playlist_iter_next (playlist, &iter);
+
+                if (!uri) {
+                        g_free (title);
+                        continue;
+                }
 
-		func (model, &iter, &uri, &title, &custom_title, user_data);
+                file = g_file_new_for_uri (uri);
 
-		file = g_file_new_for_uri (uri);
 		if (totem_pl_parser_scheme_is_ignored (parser, file) != FALSE) {
 			g_object_unref (file);
 			g_free (uri);
@@ -123,7 +130,7 @@ totem_pl_parser_write_m3u (TotemPlParser *parser, GtkTreeModel *model,
 		}
 		g_object_unref (file);
 
-		if (custom_title != FALSE) {
+		if (title) {
 			buf = g_strdup_printf (EXTINF",%s%s", title, cr);
 			success = totem_pl_parser_write_string (G_OUTPUT_STREAM (stream), buf, error);
 			g_free (buf);
diff --git a/plparse/totem-pl-parser-lines.h b/plparse/totem-pl-parser-lines.h
index 3d7728e..68c6371 100644
--- a/plparse/totem-pl-parser-lines.h
+++ b/plparse/totem-pl-parser-lines.h
@@ -36,13 +36,12 @@ G_BEGIN_DECLS
 const char * totem_pl_parser_is_uri_list (const char *data, gsize len);
 
 #ifndef TOTEM_PL_PARSER_MINI
-gboolean totem_pl_parser_write_m3u (TotemPlParser *parser,
-				    GtkTreeModel *model,
-				    TotemPlParserIterFunc func,
-				    GFile *output,
-				    gboolean dos_compatible,
-				    gpointer user_data,
-				    GError **error);
+gboolean totem_pl_parser_save_m3u (TotemPlParser *parser,
+                                   TotemPlPlaylist *playlist,
+                                   GFile *output,
+                                   gboolean dos_compatible,
+                                   GError **error);
+
 TotemPlParserResult totem_pl_parser_add_ram (TotemPlParser *parser,
 					     GFile *file,
 					     TotemPlParseData *parse_data,
diff --git a/plparse/totem-pl-parser-media.c b/plparse/totem-pl-parser-media.c
index c945316..27d5f6e 100644
--- a/plparse/totem-pl-parser-media.c
+++ b/plparse/totem-pl-parser-media.c
@@ -25,7 +25,8 @@
 #ifndef TOTEM_PL_PARSER_MINI
 #include <string.h>
 #include <glib.h>
-#include <gtk/gtk.h>
+#include <stdio.h>
+
 #include "totem-pl-parser.h"
 #include "totemplparser-marshal.h"
 #include "totem-disc.h"
diff --git a/plparse/totem-pl-parser-misc.c b/plparse/totem-pl-parser-misc.c
index a65f823..8ec54df 100644
--- a/plparse/totem-pl-parser-misc.c
+++ b/plparse/totem-pl-parser-misc.c
@@ -26,7 +26,7 @@
 #include <glib.h>
 
 #ifndef TOTEM_PL_PARSER_MINI
-#include <gtk/gtk.h>
+
 #include "totem-pl-parser.h"
 #include "totemplparser-marshal.h"
 #include "totem-disc.h"
diff --git a/plparse/totem-pl-parser-pla.c b/plparse/totem-pl-parser-pla.c
index 23087ac..d067d32 100644
--- a/plparse/totem-pl-parser-pla.c
+++ b/plparse/totem-pl-parser-pla.c
@@ -25,7 +25,7 @@
 #include <string.h>
 #include <glib.h>
 #include <glib/gi18n-lib.h>
-#include <gtk/gtk.h>
+
 #include "totem-pl-parser.h"
 #include "totemplparser-marshal.h"
 #endif /* !TOTEM_PL_PARSER_MINI */
@@ -45,22 +45,24 @@
 
 #ifndef TOTEM_PL_PARSER_MINI
 gboolean
-totem_pl_parser_write_pla (TotemPlParser *parser, GtkTreeModel *model,
-			   TotemPlParserIterFunc func, 
-			   GFile *output, const char *title,
-			   gpointer user_data, GError **error)
+totem_pl_parser_save_pla (TotemPlParser    *parser,
+                          TotemPlPlaylist  *playlist,
+                          GFile            *output,
+                          const char       *title,
+                          GError          **error)
 {
+        TotemPlPlaylistIter iter;
 	GFileOutputStream *stream;
-	int num_entries_total, i;
+        gint num_entries_total, i;
 	char *buffer;
-	gboolean ret;
-
-	num_entries_total = gtk_tree_model_iter_n_children (model, NULL);
+	gboolean valid, ret;
 
 	stream = g_file_replace (output, NULL, FALSE, G_FILE_CREATE_NONE, NULL, error);
 	if (stream == NULL)
 		return FALSE;
 
+        num_entries_total = totem_pl_playlist_size (playlist);
+
 	/* write the header */
 	buffer = g_malloc0 (RECORD_SIZE);
 	*((gint32 *)buffer) = GINT32_TO_BE (num_entries_total);
@@ -78,22 +80,28 @@ totem_pl_parser_write_pla (TotemPlParser *parser, GtkTreeModel *model,
 	}
 
 	ret = TRUE;
-	for (i = 1; i <= num_entries_total; i++) {
-		GtkTreeIter iter;
-		char *euri, *title, *path, *converted, *filename;
+        valid = totem_pl_playlist_iter_first (playlist, &iter);
+        i = 0;
+
+        while (valid)
+        {
+		char *euri, *path, *converted, *filename;
 		gsize written;
-		gboolean custom_title;
 
-		if (gtk_tree_model_iter_nth_child (model, &iter, NULL, i - 1) == FALSE)
-			continue;
+                totem_pl_playlist_get (playlist, &iter,
+                                       TOTEM_PL_PARSER_FIELD_URI, &euri,
+                                       NULL);
 
-		func (model, &iter, &euri, &title, &custom_title, user_data);
-		g_free (title);
+                valid = totem_pl_playlist_iter_next (playlist, &iter);
 
-		memset (buffer, 0, RECORD_SIZE);
+                if (!euri) {
+                        continue;
+                }
 
-		/* convert to filename */
+                memset (buffer, 0, RECORD_SIZE);
 		path = g_filename_from_uri (euri, NULL, error);
+                i++;
+
 		if (path == NULL)
 		{
 			DEBUG(NULL, g_print ("Couldn't convert URI '%s' to a filename: %s\n", euri, (*error)->message));
@@ -112,7 +120,9 @@ totem_pl_parser_write_pla (TotemPlParser *parser, GtkTreeModel *model,
 		{
 			/* should never happen, but this would be the right value */
 			buffer[1] = 0x01;
-		} else {
+		}
+                else
+                {
 			/* we want the char after the slash, and it's one-based */
 			guint name_offset = (filename - path) + 2;
 
diff --git a/plparse/totem-pl-parser-pla.h b/plparse/totem-pl-parser-pla.h
index 0f416a4..d5081a3 100644
--- a/plparse/totem-pl-parser-pla.h
+++ b/plparse/totem-pl-parser-pla.h
@@ -32,13 +32,13 @@ G_BEGIN_DECLS
 #endif /* !TOTEM_PL_PARSER_MINI */
 
 #ifndef TOTEM_PL_PARSER_MINI
-gboolean totem_pl_parser_write_pla				(TotemPlParser *parser,
-								 GtkTreeModel *model,
-								 TotemPlParserIterFunc func, 
+
+gboolean totem_pl_parser_save_pla				(TotemPlParser *parser,
+                                                                 TotemPlPlaylist *playlist,
 								 GFile *output,
 								 const char *title,
-								 gpointer user_data,
 								 GError **error);
+
 TotemPlParserResult totem_pl_parser_add_pla			(TotemPlParser *parser,
 								 GFile *file,
 								 GFile *base_file,
diff --git a/plparse/totem-pl-parser-pls.c b/plparse/totem-pl-parser-pls.c
index db57617..50b5e68 100644
--- a/plparse/totem-pl-parser-pls.c
+++ b/plparse/totem-pl-parser-pls.c
@@ -26,7 +26,7 @@
 #include <string.h>
 #include <glib.h>
 #include <glib/gi18n-lib.h>
-#include <gtk/gtk.h>
+
 #include "totem-pl-parser.h"
 #include "totemplparser-marshal.h"
 #endif /* !TOTEM_PL_PARSER_MINI */
@@ -37,18 +37,19 @@
 
 #ifndef TOTEM_PL_PARSER_MINI
 gboolean
-totem_pl_parser_write_pls (TotemPlParser *parser, GtkTreeModel *model,
-			   TotemPlParserIterFunc func,
-			   GFile *output, const char *title,
-			   gpointer user_data, GError **error)
+totem_pl_parser_save_pls (TotemPlParser    *parser,
+                          TotemPlPlaylist  *playlist,
+                          GFile            *output,
+                          const gchar      *title,
+                          GError          **error)
 {
+        TotemPlPlaylistIter iter;
 	GFileOutputStream *stream;
-	int num_entries_total, num_entries, i;
+	int num_entries, i;
+	gboolean valid, success;
 	char *buf;
-	gboolean success;
 
-	num_entries = totem_pl_parser_num_entries (parser, model, func, user_data);
-	num_entries_total = gtk_tree_model_iter_n_children (model, NULL);
+	num_entries = totem_pl_parser_num_entries (parser, playlist);
 
 	stream = g_file_replace (output, NULL, FALSE, G_FILE_CREATE_NONE, NULL, error);
 	if (stream == NULL)
@@ -74,49 +75,63 @@ totem_pl_parser_write_pls (TotemPlParser *parser, GtkTreeModel *model,
 	if (success == FALSE)
 		return FALSE;
 
-	for (i = 1; i <= num_entries_total; i++) {
-		GtkTreeIter iter;
-		char *uri, *title, *relative;
-		GFile *file;
-		gboolean custom_title;
+        valid = totem_pl_playlist_iter_first (playlist, &iter);
+        i = 0;
 
-		if (gtk_tree_model_iter_nth_child (model, &iter, NULL, i - 1) == FALSE)
-			continue;
+        while (valid) {
+                gchar *uri, *title, *relative;
+                GFile *file;
 
-		func (model, &iter, &uri, &title, &custom_title, user_data);
+                totem_pl_playlist_get (playlist, &iter,
+                                       TOTEM_PL_PARSER_FIELD_URI, &uri,
+                                       TOTEM_PL_PARSER_FIELD_TITLE, &title,
+                                       NULL);
 
-		file = g_file_new_for_uri (uri);
-		if (totem_pl_parser_scheme_is_ignored (parser, file) != FALSE) {
-			g_free (uri);
-			g_free (title);
-			g_object_unref (file);
-			continue;
-		}
-		g_object_unref (file);
+                valid = totem_pl_playlist_iter_next (playlist, &iter);
 
-		relative = totem_pl_parser_relative (output, uri);
-		buf = g_strdup_printf ("File%d=%s\n", i, relative ? relative : uri);
-		g_free (relative);
-		g_free (uri);
-		success = totem_pl_parser_write_string (G_OUTPUT_STREAM (stream), buf, error);
-		g_free (buf);
-		if (success == FALSE) {
-			g_free (title);
-			return FALSE;
-		}
+                if (!uri) {
+                        g_free (title);
+                        continue;
+                }
 
-		if (custom_title == FALSE) {
-			g_free (title);
-			continue;
-		}
+                file = g_file_new_for_uri (uri);
 
-		buf = g_strdup_printf ("Title%d=%s\n", i, title);
-		success = totem_pl_parser_write_string (G_OUTPUT_STREAM (stream), buf, error);
-		g_free (buf);
-		g_free (title);
-		if (success == FALSE)
-			return FALSE;
-	}
+                if (totem_pl_parser_scheme_is_ignored (parser, file)) {
+                        g_object_unref (file);
+                        g_free (uri);
+                        g_free (title);
+                        continue;
+                }
+
+                g_object_unref (file);
+                i++;
+
+                relative = totem_pl_parser_relative (output, uri);
+                buf = g_strdup_printf ("File%d=%s\n", i, relative ? relative : uri);
+                g_free (relative);
+                g_free (uri);
+
+                success = totem_pl_parser_write_string (G_OUTPUT_STREAM (stream), buf, error);
+                g_free (buf);
+
+                if (success == FALSE) {
+                        g_free (title);
+                        return FALSE;
+                }
+
+                if (!title) {
+                        continue;
+                }
+
+                buf = g_strdup_printf ("Title%d=%s\n", i, title);
+                success = totem_pl_parser_write_string (G_OUTPUT_STREAM (stream), buf, error);
+                g_free (buf);
+                g_free (title);
+
+                if (success == FALSE) {
+                        return FALSE;
+                }
+        }
 
 	g_object_unref (stream);
 	return TRUE;
diff --git a/plparse/totem-pl-parser-pls.h b/plparse/totem-pl-parser-pls.h
index e74b317..6de1b88 100644
--- a/plparse/totem-pl-parser-pls.h
+++ b/plparse/totem-pl-parser-pls.h
@@ -32,12 +32,10 @@ G_BEGIN_DECLS
 #endif /* !TOTEM_PL_PARSER_MINI */
 
 #ifndef TOTEM_PL_PARSER_MINI
-gboolean totem_pl_parser_write_pls				(TotemPlParser *parser,
-								 GtkTreeModel *model,
-								 TotemPlParserIterFunc func, 
+gboolean totem_pl_parser_save_pls				(TotemPlParser *parser,
+                                                                 TotemPlPlaylist *playlist,
 								 GFile *file,
 								 const char *title,
-								 gpointer user_data,
 								 GError **error);
 TotemPlParserResult totem_pl_parser_add_pls_with_contents	(TotemPlParser *parser,
 								 GFile *file,
diff --git a/plparse/totem-pl-parser-podcast.c b/plparse/totem-pl-parser-podcast.c
index 325fe53..4480b3d 100644
--- a/plparse/totem-pl-parser-podcast.c
+++ b/plparse/totem-pl-parser-podcast.c
@@ -26,7 +26,7 @@
 
 #ifndef TOTEM_PL_PARSER_MINI
 #include <zlib.h>
-#include <gtk/gtk.h>
+
 #include "xmlparser.h"
 #include "totem-pl-parser.h"
 #include "totemplparser-marshal.h"
diff --git a/plparse/totem-pl-parser-private.h b/plparse/totem-pl-parser-private.h
index deae8d7..626e372 100644
--- a/plparse/totem-pl-parser-private.h
+++ b/plparse/totem-pl-parser-private.h
@@ -116,10 +116,10 @@ gboolean totem_pl_parser_is_debugging_enabled	(TotemPlParser *parser);
 char *totem_pl_parser_base_uri			(GFile *file);
 void totem_pl_parser_playlist_end		(TotemPlParser *parser,
 						 const char *playlist_title);
-int totem_pl_parser_num_entries			(TotemPlParser *parser,
-						 GtkTreeModel *model,
-						 TotemPlParserIterFunc func,
-						 gpointer user_data);
+
+int totem_pl_parser_num_entries			(TotemPlParser   *parser,
+                                                 TotemPlPlaylist *playlist);
+
 gboolean totem_pl_parser_scheme_is_ignored	(TotemPlParser *parser,
 						 GFile *file);
 gboolean totem_pl_parser_line_is_empty		(const char *line);
diff --git a/plparse/totem-pl-parser-qt.c b/plparse/totem-pl-parser-qt.c
index 416cb12..db0d4ee 100644
--- a/plparse/totem-pl-parser-qt.c
+++ b/plparse/totem-pl-parser-qt.c
@@ -27,7 +27,7 @@
 
 #ifndef TOTEM_PL_PARSER_MINI
 #include "xmlparser.h"
-#include <gtk/gtk.h>
+
 #include "totem-pl-parser.h"
 #include "totemplparser-marshal.h"
 #endif /* !TOTEM_PL_PARSER_MINI */
diff --git a/plparse/totem-pl-parser-smil.c b/plparse/totem-pl-parser-smil.c
index 0e284ef..7818b5f 100644
--- a/plparse/totem-pl-parser-smil.c
+++ b/plparse/totem-pl-parser-smil.c
@@ -24,7 +24,7 @@
 
 #ifndef TOTEM_PL_PARSER_MINI
 #include <glib.h>
-#include <gtk/gtk.h>
+
 #include <gio/gio.h>
 #include "xmlparser.h"
 #include "totem-pl-parser.h"
diff --git a/plparse/totem-pl-parser-wm.c b/plparse/totem-pl-parser-wm.c
index bbce3bd..3a544c2 100644
--- a/plparse/totem-pl-parser-wm.c
+++ b/plparse/totem-pl-parser-wm.c
@@ -27,7 +27,7 @@
 
 #ifndef TOTEM_PL_PARSER_MINI
 #include "xmlparser.h"
-#include <gtk/gtk.h>
+
 #include "totem-pl-parser.h"
 #include "totemplparser-marshal.h"
 #include "totem-disc.h"
diff --git a/plparse/totem-pl-parser-xspf.c b/plparse/totem-pl-parser-xspf.c
index 563f2be..7de49ef 100644
--- a/plparse/totem-pl-parser-xspf.c
+++ b/plparse/totem-pl-parser-xspf.c
@@ -28,7 +28,7 @@
 #include <glib/gi18n-lib.h>
 #include <libxml/tree.h>
 #include <libxml/parser.h>
-#include <gtk/gtk.h>
+
 #include "totem-pl-parser.h"
 #include "totemplparser-marshal.h"
 #endif /* !TOTEM_PL_PARSER_MINI */
@@ -74,17 +74,16 @@ totem_pl_parser_parse_xml_file (GFile *file)
 }
 
 gboolean
-totem_pl_parser_write_xspf (TotemPlParser *parser, GtkTreeModel *model,
-			   TotemPlParserIterFunc func, 
-			   GFile *output, const char *title,
-			   gpointer user_data, GError **error)
+totem_pl_parser_save_xspf (TotemPlParser    *parser,
+                           TotemPlPlaylist  *playlist,
+                           GFile            *output,
+                           const char       *title,
+                           GError          **error)
 {
+        TotemPlPlaylistIter iter;
 	GFileOutputStream *stream;
-	int num_entries_total, i;
 	char *buf;
-	gboolean success;
-
-	num_entries_total = gtk_tree_model_iter_n_children (model, NULL);
+	gboolean valid, success;
 
 	stream = g_file_replace (output, NULL, FALSE, G_FILE_CREATE_NONE, NULL, error);
 	if (stream == NULL)
@@ -98,17 +97,25 @@ totem_pl_parser_write_xspf (TotemPlParser *parser, GtkTreeModel *model,
 	if (success == FALSE)
 		return FALSE;
 
-	for (i = 1; i <= num_entries_total; i++) {
-		GtkTreeIter iter;
+        valid = totem_pl_playlist_iter_first (playlist, &iter);
+
+        while (valid) {
 		char *uri, *uri_escaped, *relative, *title;
 		GFile *file;
-		gboolean custom_title;
 
-		if (gtk_tree_model_iter_nth_child (model, &iter, NULL, i - 1) == FALSE)
-			continue;
+                totem_pl_playlist_get (playlist, &iter,
+                                       TOTEM_PL_PARSER_FIELD_URI, &uri,
+                                       TOTEM_PL_PARSER_FIELD_TITLE, &title,
+                                       NULL);
+
+                valid = totem_pl_playlist_iter_next (playlist, &iter);
 
-		func (model, &iter, &uri, &title, &custom_title, user_data);
-		file = g_file_new_for_uri (uri);
+                if (!uri) {
+                        g_free (title);
+                        continue;
+                }
+
+                file = g_file_new_for_uri (uri);
 
 		if (totem_pl_parser_scheme_is_ignored (parser, file) != FALSE) {
 			g_object_unref (file);
@@ -121,32 +128,35 @@ totem_pl_parser_write_xspf (TotemPlParser *parser, GtkTreeModel *model,
 		relative = totem_pl_parser_relative (output, uri);
 		uri_escaped = g_markup_escape_text (relative ? relative : uri, -1);
 		buf = g_strdup_printf ("  <track>\n"
-					"   <location>%s</location>\n", uri_escaped);
+                                       "   <location>%s</location>\n", uri_escaped);
 		success = totem_pl_parser_write_string (G_OUTPUT_STREAM (stream), buf, error);
 		g_free (uri);
 		g_free (uri_escaped);
 		g_free (relative);
 		g_free (buf);
-		if (success == FALSE) {
+
+                if (success == FALSE) {
 			g_free (title);
 			return FALSE;
 		}
 
-		if (custom_title == TRUE)
+		if (title) {
 			buf = g_strdup_printf ("   <title>%s</title>\n"
-						"  </track>\n", title);
-		else
+                                               "  </track>\n", title);
+                } else {
 			buf = g_strdup_printf ("  </track>\n");
-		
+                }
+
 		success = totem_pl_parser_write_string (G_OUTPUT_STREAM (stream), buf, error);
 		g_free (buf);
 		g_free (title);
-		if (success == FALSE)
+
+                if (success == FALSE)
 			return FALSE;
 	}
 
 	buf = g_strdup_printf (" </trackList>\n"
-				"</playlist>");
+                               "</playlist>");
 	success = totem_pl_parser_write_string (G_OUTPUT_STREAM (stream), buf, error);
 	g_free (buf);
 
diff --git a/plparse/totem-pl-parser-xspf.h b/plparse/totem-pl-parser-xspf.h
index e1717f4..c8e3695 100644
--- a/plparse/totem-pl-parser-xspf.h
+++ b/plparse/totem-pl-parser-xspf.h
@@ -32,13 +32,14 @@ G_BEGIN_DECLS
 #endif /* !TOTEM_PL_PARSER_MINI */
 
 #ifndef TOTEM_PL_PARSER_MINI
-gboolean totem_pl_parser_write_xspf (TotemPlParser *parser,
-				     GtkTreeModel *model,
-				     TotemPlParserIterFunc func, 
-				     GFile *output,
-				     const char *title,
-				     gpointer user_data,
-				     GError **error);
+
+gboolean totem_pl_parser_save_xspf (TotemPlParser *parser,
+                                    TotemPlPlaylist *playlist,
+                                    GFile *output,
+                                    const char *title,
+                                    GError **error);
+
+
 TotemPlParserResult totem_pl_parser_add_xspf (TotemPlParser *parser,
 					      GFile *file,
 					      GFile *base_file,
diff --git a/plparse/totem-pl-parser.c b/plparse/totem-pl-parser.c
index 788e720..742db02 100644
--- a/plparse/totem-pl-parser.c
+++ b/plparse/totem-pl-parser.c
@@ -87,36 +87,35 @@
  * <example>
  *  <title>Writing a Playlist</title>
  *  <programlisting>
- * void
- * parser_func (GtkTreeModel *model, GtkTreeIter *iter,
- * 		gchar **uri, gchar **title, gboolean *custom_title,
- * 		gpointer user_data)
- * {
- * 	gtk_tree_model_get (model, iter,
- * 		0, uri,
- * 		1, title,
- * 		2, custom_title,
- * 		-1);
- * }
- *
  * {
  * 	TotemPlParser *pl;
- * 	GtkTreeModel *tree_model;
+ * 	TotemPlPlaylist *playlist;
+ * 	TotemPlPlaylistIter iter;
+ * 	GFile *file;
  *
  * 	pl = totem_pl_parser_new ();
- *
- * 	&slash;* Your tree model can be as simple or as complex as you like;
- * 	 * parser_func() will just have to return the entry title, URI and custom title flag from it. *&slash;
- * 	tree_model = gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN);
- * 	populate_model (tree_model);
- *
- * 	if (totem_pl_parser_write (pl, tree_model, parser_func, "/tmp/playlist.pls",
- * 				   TOTEM_PL_PARSER_PLS, NULL, NULL) != TRUE) {
+ * 	playlist = totem_pl_playlist_new ();
+ * 	file = g_file_new_for_path ("/tmp/playlist.pls");
+ *
+ * 	totem_pl_playlist_append (playlist, &iter);
+ * 	totem_pl_playlist_set (playlist, &iter,
+ * 			       TOTEM_PL_PARSER_FIELD_URI, "file:///1.ogg",
+ * 			       TOTEM_PL_PARSER_FIELD_TITLE, "1.ogg",
+ * 			       NULL);
+ *
+ * 	totem_pl_playlist_append (playlist, &iter);
+ * 	totem_pl_playlist_set (playlist, &iter,
+ * 			       TOTEM_PL_PARSER_FIELD_URI, "file:///2.ogg",
+ * 			       NULL);
+ *
+ * 	if (totem_pl_parser_save (pl, playlist, file, "Title",
+ * 				  TOTEM_PL_PARSER_PLS, NULL) != TRUE) {
  * 		g_error ("Playlist writing failed.");
  * 	}
  *
- * 	g_object_unref (tree_model);
+ * 	g_object_unref (playlist);
  * 	g_object_unref (pl);
+ * 	g_object_unref (file);
  * }
  *  </programlisting>
  * </example>
@@ -132,7 +131,6 @@
 
 #ifndef TOTEM_PL_PARSER_MINI
 #include <gobject/gvaluecollector.h>
-#include <gtk/gtk.h>
 
 #ifdef HAVE_GMIME
 #include <gmime/gmime-utils.h>
@@ -884,43 +882,48 @@ totem_pl_parser_write_buffer (GOutputStream *stream, const char *buf, guint len,
 /**
  * totem_pl_parser_num_entries:
  * @parser: a #TotemPlParser
- * @model: a #GtkTreeModel
- * @func: a pointer to a #TotemPlParserIterFunc callback function
- * @user_data: a pointer to be passed to each call of @func
+ * @playlist: a #TotemPlPlaylist
  *
- * Returns the number of entries in @parser's playlist, and calls
- * @func for each valid entry in the playlist.
+ * Returns the number of valid entries in @playlist.
  *
  * Return value: the number of entries in the playlist
  **/
 int
-totem_pl_parser_num_entries (TotemPlParser *parser, GtkTreeModel *model,
-			     TotemPlParserIterFunc func, gpointer user_data)
+totem_pl_parser_num_entries (TotemPlParser   *parser,
+                             TotemPlPlaylist *playlist)
 {
-	int num_entries, i, ignored;
+	int num_entries, ignored;
+        TotemPlPlaylistIter iter;
+        gboolean valid;
 
-	num_entries = gtk_tree_model_iter_n_children (model, NULL);
+	num_entries = totem_pl_playlist_size (playlist);
+        valid = totem_pl_playlist_iter_first (playlist, &iter);
 	ignored = 0;
 
-	for (i = 1; i <= num_entries; i++)
-	{
-		GtkTreeIter iter;
-		char *uri, *title;
-		GFile *file;
-		gboolean custom_title;
+        while (valid) {
+                gchar *uri;
+                GFile *file;
 
-		if (gtk_tree_model_iter_nth_child (model, &iter, NULL, i - 1) == FALSE)
-			return i - ignored;
+                totem_pl_playlist_get (playlist, &iter,
+                                       TOTEM_PL_PARSER_FIELD_URI, &uri,
+                                       NULL);
 
-		func (model, &iter, &uri, &title, &custom_title, user_data);
-		file = g_file_new_for_uri (uri);
-		if (totem_pl_parser_scheme_is_ignored (parser, file) != FALSE)
-			ignored++;
+                valid = totem_pl_playlist_iter_next (playlist, &iter);
 
-		g_object_unref (file);
-		g_free (uri);
-		g_free (title);
-	}
+                if (!uri) {
+                        ignored++;
+                        continue;
+                }
+
+                file = g_file_new_for_uri (uri);
+
+                if (totem_pl_parser_scheme_is_ignored (parser, file)) {
+                        ignored++;
+                }
+
+                g_object_unref (file);
+                g_free (uri);
+        }
 
 	return num_entries - ignored;
 }
@@ -1081,24 +1084,18 @@ totem_pl_parser_resolve_uri (GFile *base_gfile,
 
 #ifndef TOTEM_PL_PARSER_MINI
 /**
- * totem_pl_parser_write_with_title:
+ * totem_pl_parser_save:
  * @parser: a #TotemPlParser
- * @model: a #GtkTreeModel
- * @func: a pointer to a #TotemPlParserIterFunc callback function
- * @output: the output path and filename
+ * @playlist: a #TotemPlPlaylist
+ * @dest: output #GFile
  * @title: the playlist title
- * @type: a #TotemPlParserType for the ouputted playlist
- * @user_data: a pointer to be passed to each call of @func
- * @error: return location for a #GError, or %NULL
+ * @type: a #TotemPlParserType for the outputted playlist
+ * @error: return loction for a #GError, or %NULL
  *
- * Writes the playlist held by @parser and @model out to the file of
- * path @output. The playlist is written in the format @type and is
+ * Writes the playlist held by @parser and @playlist out to the path
+ * pointed by @dest. The playlist is written in the format @type and is
  * given the title @title.
  *
- * For each entry in the @model, the function @func is called (and passed
- * @user_data), which gets various metadata values about the entry for
- * the playlist writer.
- *
  * If the @output file is a directory the #G_IO_ERROR_IS_DIRECTORY error
  * will be returned, and if the file is some other form of non-regular file
  * then a #G_IO_ERROR_NOT_REGULAR_FILE error will be returned. Some file
@@ -1113,77 +1110,43 @@ totem_pl_parser_resolve_uri (GFile *base_gfile,
  * If writing a PLA playlist and there is an error converting a URI's encoding,
  * a code from #GConvertError will be returned.
  *
- * Return value: %TRUE on success
+ * Returns: %TRUE on success
  **/
 gboolean
-totem_pl_parser_write_with_title (TotemPlParser *parser, GtkTreeModel *model,
-				  TotemPlParserIterFunc func,
-				  const char *output, const char *title,
-				  TotemPlParserType type,
-				  gpointer user_data, GError **error)
+totem_pl_parser_save (TotemPlParser      *parser,
+                      TotemPlPlaylist    *playlist,
+                      GFile              *dest,
+                      const gchar        *title,
+                      TotemPlParserType   type,
+                      GError            **error)
 {
-	GFile *file;
+        g_return_val_if_fail (TOTEM_IS_PL_PARSER (parser), FALSE);
+        g_return_val_if_fail (TOTEM_IS_PL_PLAYLIST (playlist), FALSE);
+        g_return_val_if_fail (G_IS_FILE (dest), FALSE);
 
-	file = g_file_new_for_commandline_arg (output);
+        if (totem_pl_playlist_size (playlist) == 0) {
+                return FALSE;
+        }
 
-	switch (type)
-	{
+        switch (type)
+        {
 	case TOTEM_PL_PARSER_PLS:
-		return totem_pl_parser_write_pls (parser, model, func,
-				file, title, user_data, error);
+		return totem_pl_parser_save_pls (parser, playlist, dest, title, error);
 	case TOTEM_PL_PARSER_M3U:
 	case TOTEM_PL_PARSER_M3U_DOS:
-		return totem_pl_parser_write_m3u (parser, model, func,
-				file, (type == TOTEM_PL_PARSER_M3U_DOS),
-                                user_data, error);
+		return totem_pl_parser_save_m3u (parser, playlist, dest,
+                                                 (type == TOTEM_PL_PARSER_M3U_DOS),
+                                                 error);
 	case TOTEM_PL_PARSER_XSPF:
-		return totem_pl_parser_write_xspf (parser, model, func,
-				file, title, user_data, error);
+		return totem_pl_parser_save_xspf (parser, playlist, dest, title, error);
 	case TOTEM_PL_PARSER_IRIVER_PLA:
-		return totem_pl_parser_write_pla (parser, model, func,
-				file, title, user_data, error);
+		return totem_pl_parser_save_pla (parser, playlist, dest, title, error);
 	default:
 		g_assert_not_reached ();
 	}
 
-	g_object_unref (file);
-
 	return FALSE;
 }
-
-/**
- * totem_pl_parser_write:
- * @parser: a #TotemPlParser
- * @model: a #GtkTreeModel
- * @func: a pointer to a #TotemPlParserIterFunc callback function
- * @output: the output path and filename
- * @type: a #TotemPlParserType for the ouputted playlist
- * @user_data: a pointer to be passed to each call of @func
- * @error: return location for a #GError, or %NULL
- *
- * Writes the playlist held by @parser and @model out to the file of
- * path @output. The playlist is written in the format @type and is given
- * a %NULL title.
- *
- * For each entry in the @model, the function @func is called (and passed
- * @user_data), which gets various metadata values about the entry for
- * the playlist writer.
- *
- * Possible error codes are as per totem_pl_parser_write_with_title().
- *
- * Return value: %TRUE on success
- **/
-gboolean
-totem_pl_parser_write (TotemPlParser *parser, GtkTreeModel *model,
-		       TotemPlParserIterFunc func,
-		       const char *output, TotemPlParserType type,
-		       gpointer user_data,
-		       GError **error)
-{
-	return totem_pl_parser_write_with_title (parser, model, func, output,
-			NULL, type, user_data, error);
-}
-
 #endif /* TOTEM_PL_PARSER_MINI */
 
 /**
diff --git a/plparse/totem-pl-parser.h b/plparse/totem-pl-parser.h
index fe87df7..ffac31d 100644
--- a/plparse/totem-pl-parser.h
+++ b/plparse/totem-pl-parser.h
@@ -25,9 +25,10 @@
 
 #include <glib.h>
 #include <gio/gio.h>
-#include <gtk/gtk.h>
+
 #include "totem-pl-parser-features.h"
 #include "totem-pl-parser-builtins.h"
+#include "totem-pl-playlist.h"
 
 G_BEGIN_DECLS
 
@@ -314,45 +315,17 @@ typedef enum {
 
 GQuark totem_pl_parser_error_quark (void);
 
-/**
- * TotemPlParserIterFunc:
- * @model: a #GtkTreeModel containing the playlist entries
- * @iter: a #GtkTreeIter pointing to the current row
- * @uri: (out) (transfer full): return location for the entry's URI, or %NULL
- * @title: (out) (transfer full): return location for the entry's title, or %NULL
- * @custom_title: (out) (transfer full): return location for a boolean which, if %TRUE, indicates that the entry's @title is custom; or %NULL
- * @user_data: user data to pass to the function
- *
- * Functions such as totem_pl_parser_write() accept pointers to TotemPlParserIterFunc()s
- * as callbacks to call for each entry in the playlist. These functions
- * are specific to each use of the playlist API, and should set the entry's
- * @uri, @title and @custom_title return values, getting the data from @model
- * or otherwise.
- **/
-typedef void (*TotemPlParserIterFunc) (GtkTreeModel *model, GtkTreeIter *iter,
-				       char **uri, char **title,
-				       gboolean *custom_title,
-				       gpointer user_data);
-
 GType    totem_pl_parser_get_type (void);
 
 gint64  totem_pl_parser_parse_duration (const char *duration, gboolean debug);
 guint64 totem_pl_parser_parse_date     (const char *date_str, gboolean debug);
 
-gboolean totem_pl_parser_write (TotemPlParser *parser, GtkTreeModel *model,
-				TotemPlParserIterFunc func,
-				const char *output, TotemPlParserType type,
-				gpointer user_data,
-				GError **error);
-
-gboolean   totem_pl_parser_write_with_title (TotemPlParser *parser,
-					     GtkTreeModel *model,
-					     TotemPlParserIterFunc func,
-					     const char *output,
-					     const char *title,
-					     TotemPlParserType type,
-					     gpointer user_data,
-					     GError **error);
+gboolean totem_pl_parser_save (TotemPlParser      *parser,
+			       TotemPlPlaylist    *playlist,
+			       GFile              *dest,
+			       const gchar        *title,
+			       TotemPlParserType   type,
+			       GError            **error);
 
 void	   totem_pl_parser_add_ignored_scheme (TotemPlParser *parser,
 					       const char *scheme);
diff --git a/plparse/totem-pl-playlist.c b/plparse/totem-pl-playlist.c
new file mode 100644
index 0000000..c3dfded
--- /dev/null
+++ b/plparse/totem-pl-playlist.c
@@ -0,0 +1,533 @@
+/*
+   Copyright (C) 2009, Nokia
+
+   The Gnome Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The Gnome Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the Gnome Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301  USA.
+
+   Author: Carlos Garnacho <carlos lanedo com>
+ */
+
+/**
+ * SECTION:totem-pl-playlist
+ * @short_description: playlist object
+ * @stability: Stable
+ * @include: totem-pl-playlist.h
+ *
+ * #TotemPlPlaylist represents a playlist, provides API to either navigate through
+ * the playlist elements, or perform additions or modifications. See also
+ * totem_pl_parser_save().
+ **/
+
+#include "totem-pl-playlist.h"
+
+typedef struct TotemPlPlaylistPrivate TotemPlPlaylistPrivate;
+
+struct TotemPlPlaylistPrivate {
+        GList *items;
+};
+
+#define TOTEM_PL_PLAYLIST_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TOTEM_TYPE_PL_PLAYLIST, TotemPlPlaylistPrivate))
+
+static void totem_pl_playlist_finalize (GObject *object);
+
+
+G_DEFINE_TYPE (TotemPlPlaylist, totem_pl_playlist, G_TYPE_OBJECT)
+
+
+static void
+totem_pl_playlist_class_init (TotemPlPlaylistClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->finalize = totem_pl_playlist_finalize;
+
+        g_type_class_add_private (klass, sizeof (TotemPlPlaylistPrivate));
+}
+
+static void
+totem_pl_playlist_init (TotemPlPlaylist *playlist)
+{
+}
+
+static void
+totem_pl_playlist_finalize (GObject *object)
+{
+        TotemPlPlaylistPrivate *priv;
+
+        priv = TOTEM_PL_PLAYLIST_GET_PRIVATE (object);
+
+        g_list_foreach (priv->items, (GFunc) g_hash_table_destroy, NULL);
+        g_list_free (priv->items);
+
+        G_OBJECT_CLASS (totem_pl_playlist_parent_class)->finalize (object);
+}
+
+/**
+ * totem_pl_playlist_new:
+ *
+ * Creates a new #TotemPlPlaylist object.
+ *
+ * Returns: The newly created #TotemPlPlaylist
+ **/
+TotemPlPlaylist *
+totem_pl_playlist_new (void)
+{
+        return g_object_new (TOTEM_TYPE_PL_PLAYLIST, NULL);
+}
+
+/**
+ * totem_pl_playlist_size:
+ * @playlist: a #TotemPlPlaylist
+ *
+ * Returns the number of elements in @playlist.
+ *
+ * Returns: The number of elements
+ **/
+guint
+totem_pl_playlist_size (TotemPlPlaylist *playlist)
+{
+        TotemPlPlaylistPrivate *priv;
+
+        g_return_val_if_fail (TOTEM_IS_PL_PLAYLIST (playlist), 0);
+
+        priv = TOTEM_PL_PLAYLIST_GET_PRIVATE (playlist);
+
+        return g_list_length (priv->items);
+}
+
+static GHashTable *
+create_playlist_item (void)
+{
+        return g_hash_table_new_full (g_str_hash,
+                                      g_str_equal,
+                                      (GDestroyNotify) g_free,
+                                      (GDestroyNotify) g_free);
+}
+
+/**
+ * totem_pl_playlist_prepend:
+ * @playlist: a #TotemPlPlaylist
+ * @iter: an unset #TotemPlPlaylistIter for returning the location
+ *
+ * Prepends a new empty element to @playlist, and modifies @iter so
+ * it points to it. To fill in values, you need to call
+ * totem_pl_playlist_set() or totem_pl_playlist_set_value().
+ **/
+void
+totem_pl_playlist_prepend (TotemPlPlaylist     *playlist,
+                           TotemPlPlaylistIter *iter)
+{
+        TotemPlPlaylistPrivate *priv;
+        GHashTable *item;
+
+        g_return_if_fail (TOTEM_IS_PL_PLAYLIST (playlist));
+        g_return_if_fail (iter != NULL);
+
+        priv = TOTEM_PL_PLAYLIST_GET_PRIVATE (playlist);
+
+        item = create_playlist_item ();
+        priv->items = g_list_prepend (priv->items, item);
+
+        iter->data1 = playlist;
+        iter->data2 = priv->items;
+}
+
+/**
+ * totem_pl_playlist_append:
+ * @playlist: a #TotemPlPlaylist
+ * @iter: an unset #TotemPlPlaylistIter for returning the location
+ *
+ * Appends a new empty element to @playlist, and modifies @iter so
+ * it points to it. To fill in values, you need to call
+ * totem_pl_playlist_set() or totem_pl_playlist_set_value().
+ **/
+void
+totem_pl_playlist_append (TotemPlPlaylist     *playlist,
+                          TotemPlPlaylistIter *iter)
+{
+        TotemPlPlaylistPrivate *priv;
+        GHashTable *item;
+        GList *list_item;
+
+        g_return_if_fail (TOTEM_IS_PL_PLAYLIST (playlist));
+        g_return_if_fail (iter != NULL);
+
+        priv = TOTEM_PL_PLAYLIST_GET_PRIVATE (playlist);
+
+        item = create_playlist_item ();
+
+        list_item = g_list_alloc ();
+        list_item->data = item;
+
+        priv->items = g_list_concat (priv->items, list_item);
+
+        iter->data1 = playlist;
+        iter->data2 = list_item;
+}
+
+/**
+ * totem_pl_playlist_insert:
+ * @playlist: a #TotemPlPlaylist
+ * @position: position in the playlist
+ * @iter: an unset #TotemPlPlaylistIter for returning the location
+ *
+ * Inserts a new empty element to @playlist at @position, and modifies
+ * @iter so it points to it. To fill in values, you need to call
+ * totem_pl_playlist_set() or totem_pl_playlist_set_value().
+ *
+ * @position may be minor than 0 to prepend elements, or bigger than
+ * the current @playlist size to append elements.
+ **/
+void
+totem_pl_playlist_insert (TotemPlPlaylist     *playlist,
+                          gint                 position,
+                          TotemPlPlaylistIter *iter)
+{
+        TotemPlPlaylistPrivate *priv;
+        GHashTable *item;
+
+        g_return_if_fail (TOTEM_IS_PL_PLAYLIST (playlist));
+        g_return_if_fail (iter != NULL);
+
+        priv = TOTEM_PL_PLAYLIST_GET_PRIVATE (playlist);
+
+        item = create_playlist_item ();
+        priv->items = g_list_insert (priv->items, item, position);
+
+        iter->data1 = playlist;
+        iter->data2 = g_list_find (priv->items, item);
+}
+
+static gboolean
+check_iter (TotemPlPlaylist     *playlist,
+            TotemPlPlaylistIter *iter)
+{
+        TotemPlPlaylistPrivate *priv;
+
+        if (!iter) {
+                return FALSE;
+        }
+
+        if (iter->data1 != playlist) {
+                return FALSE;
+        }
+
+        priv = TOTEM_PL_PLAYLIST_GET_PRIVATE (playlist);
+
+        if (g_list_position (priv->items, iter->data2) == -1) {
+                return FALSE;
+        }
+
+        return TRUE;
+}
+
+/**
+ * totem_pl_playlist_iter_first:
+ * @playlist: a #TotemPlPlaylist
+ * @iter: an unset #TotemPlPlaylistIter for returning the location
+ *
+ * Modifies @iter so it points to the first element in @playlist.
+ *
+ * Returns: %TRUE if there is such first element.
+ **/
+gboolean
+totem_pl_playlist_iter_first (TotemPlPlaylist     *playlist,
+                              TotemPlPlaylistIter *iter)
+{
+        TotemPlPlaylistPrivate *priv;
+
+        g_return_val_if_fail (TOTEM_IS_PL_PLAYLIST (playlist), FALSE);
+        g_return_val_if_fail (iter != NULL, FALSE);
+
+        priv = TOTEM_PL_PLAYLIST_GET_PRIVATE (playlist);
+
+        if (!priv->items) {
+                /* Empty playlist */
+                return FALSE;
+        }
+
+        iter->data1 = playlist;
+        iter->data2 = priv->items;
+
+        return TRUE;
+}
+
+/**
+ * totem_pl_playlist_iter_next:
+ * @playlist: a #TotemPlPlaylist
+ * @iter: a #TotemPlPlaylistIter pointing to some item in @playlist
+ *
+ * Modifies @iter so it points to the next element it previously
+ * pointed to. This function will return %FALSE if there was no
+ * next element, or @iter didn't actually point to any element
+ * in @playlist.
+ *
+ * Returns: %TRUE if there was next element.
+ **/
+gboolean
+totem_pl_playlist_iter_next (TotemPlPlaylist     *playlist,
+                             TotemPlPlaylistIter *iter)
+{
+        g_return_val_if_fail (TOTEM_IS_PL_PLAYLIST (playlist), FALSE);
+        g_return_val_if_fail (check_iter (playlist, iter), FALSE);
+
+        iter->data2 = ((GList *) iter->data2)->next;
+
+        return (iter->data2 != NULL);
+}
+
+/**
+ * totem_pl_playlist_iter_prev:
+ * @playlist: a #TotemPlPlaylist
+ * @iter: a #TotemPlPlaylistIter pointing to some item in @playlist
+ *
+ * Modifies @iter so it points to the previous element it previously
+ * pointed to. This function will return %FALSE if there was no
+ * previous element, or @iter didn't actually point to any element
+ * in @playlist.
+ *
+ * Returns: %TRUE if there was previous element.
+ **/
+gboolean
+totem_pl_playlist_iter_prev (TotemPlPlaylist     *playlist,
+                             TotemPlPlaylistIter *iter)
+{
+        g_return_val_if_fail (TOTEM_IS_PL_PLAYLIST (playlist), FALSE);
+        g_return_val_if_fail (check_iter (playlist, iter), FALSE);
+
+        iter->data2 = ((GList *) iter->data2)->prev;
+
+        return (iter->data2 != NULL);
+}
+
+/**
+ * totem_pl_playlist_get_value:
+ * @playlist: a #TotemPlPlaylist
+ * @iter: a #TotemPlPlaylistIter pointing to some item in @playlist
+ * @key: data key
+ * @value: an empty #GValue to set
+ *
+ * Gets the value for @key (Such as %TOTEM_PL_PARSER_FIELD_URI) in
+ * the playlist item pointed by @iter.
+ *
+ * Returns: %TRUE if @iter contains data for @key.
+ **/
+gboolean
+totem_pl_playlist_get_value (TotemPlPlaylist     *playlist,
+                             TotemPlPlaylistIter *iter,
+                             const gchar         *key,
+                             GValue              *value)
+{
+        TotemPlPlaylistPrivate *priv;
+        GHashTable *item_data;
+        gchar *str;
+
+        g_return_val_if_fail (TOTEM_IS_PL_PLAYLIST (playlist), FALSE);
+        g_return_val_if_fail (check_iter (playlist, iter), FALSE);
+        g_return_val_if_fail (key != NULL, FALSE);
+        g_return_val_if_fail (value != NULL, FALSE);
+
+        priv = TOTEM_PL_PLAYLIST_GET_PRIVATE (playlist);
+        item_data = ((GList *) iter->data2)->data;
+
+        str = g_hash_table_lookup (item_data, key);
+
+        if (!str) {
+                return FALSE;
+        }
+
+        g_value_init (value, G_TYPE_STRING);
+        g_value_set_string (value, str);
+
+        return TRUE;
+}
+
+/**
+ * totem_pl_playlist_get_valist:
+ * @playlist: a #TotemPlPlaylist
+ * @iter: a #TotemPlPlaylistIter pointing to some item in @playlist
+ * @args: a va_list
+ *
+ * See totem_pl_playlist_get(), this function takes a va_list.
+ **/
+void
+totem_pl_playlist_get_valist (TotemPlPlaylist     *playlist,
+                              TotemPlPlaylistIter *iter,
+                              va_list              args)
+{
+        TotemPlPlaylistPrivate *priv;
+        GHashTable *item_data;
+        gchar *key, **value;
+
+        g_return_if_fail (TOTEM_IS_PL_PLAYLIST (playlist));
+        g_return_if_fail (check_iter (playlist, iter));
+
+        priv = TOTEM_PL_PLAYLIST_GET_PRIVATE (playlist);
+        item_data = ((GList *) iter->data2)->data;
+
+        key = va_arg (args, gchar *);
+
+        while (key) {
+                value = va_arg (args, gchar **);
+
+                if (value) {
+                        gchar *str;
+
+                        str = g_hash_table_lookup (item_data, key);
+                        *value = g_strdup (str);
+                }
+
+                key = va_arg (args, gchar *);
+        }
+}
+
+/**
+ * totem_pl_playlist_get:
+ * @playlist: a #TotemPlPlaylist
+ * @iter: a #TotemPlPlaylistIter pointing to some item in @playlist
+ * @...: pairs of key/return location for value, terminated by %NULL
+ *
+ * Gets the value for one or more keys from the element pointed
+ * by @iter.
+ **/
+void
+totem_pl_playlist_get (TotemPlPlaylist     *playlist,
+                       TotemPlPlaylistIter *iter,
+                       ...)
+{
+        va_list args;
+
+        g_return_if_fail (TOTEM_IS_PL_PLAYLIST (playlist));
+        g_return_if_fail (check_iter (playlist, iter));
+
+        va_start (args, iter);
+        totem_pl_playlist_get_valist (playlist, iter, args);
+        va_end (args);
+}
+
+/**
+ * totem_pl_playlist_set_value:
+ * @playlist: a #TotemPlPlaylist
+ * @iter: a #TotemPlPlaylistIter pointing to some item in @playlist
+ * @key: key to set the value for
+ * @value: #GValue containing the key value
+ *
+ * Sets the value for @key in the element pointed by @iter.
+ *
+ * Returns: %TRUE if the value could be stored in @playlist
+ **/
+gboolean
+totem_pl_playlist_set_value (TotemPlPlaylist     *playlist,
+                             TotemPlPlaylistIter *iter,
+                             const gchar         *key,
+                             GValue              *value)
+{
+        TotemPlPlaylistPrivate *priv;
+        GHashTable *item_data;
+        gchar *str;
+
+        g_return_val_if_fail (TOTEM_IS_PL_PLAYLIST (playlist), FALSE);
+        g_return_val_if_fail (check_iter (playlist, iter), FALSE);
+        g_return_val_if_fail (key != NULL, FALSE);
+        g_return_val_if_fail (value != NULL, FALSE);
+
+        priv = TOTEM_PL_PLAYLIST_GET_PRIVATE (playlist);
+        item_data = ((GList *) iter->data2)->data;
+
+        if (G_VALUE_TYPE (value) == G_TYPE_STRING) {
+                str = g_value_dup_string (value);
+        } else {
+                GValue str_value = { 0 };
+
+                g_value_init (&str_value, G_TYPE_STRING);
+
+                if (g_value_transform (value, &str_value)) {
+                        str = g_value_dup_string (&str_value);
+                } else {
+                        str = NULL;
+                }
+
+                g_value_unset (&str_value);
+        }
+
+        if (!str) {
+                g_critical ("Value could not be transformed to string");
+                return FALSE;
+        }
+
+        g_hash_table_replace (item_data, g_strdup (key), str);
+
+        return TRUE;
+}
+
+/**
+ * totem_pl_playlist_set_valist:
+ * @playlist: a #TotemPlPlaylist
+ * @iter: a #TotemPlPlaylistIter pointing to some item in @playlist
+ * @args: a va_list
+ *
+ * See totem_pl_playlist_set(), this function takes a va_list.
+ **/
+void
+totem_pl_playlist_set_valist (TotemPlPlaylist     *playlist,
+                              TotemPlPlaylistIter *iter,
+                              va_list              args)
+{
+        TotemPlPlaylistPrivate *priv;
+        GHashTable *item_data;
+        gchar *key, *value;
+
+        g_return_if_fail (TOTEM_IS_PL_PLAYLIST (playlist));
+        g_return_if_fail (check_iter (playlist, iter));
+
+        priv = TOTEM_PL_PLAYLIST_GET_PRIVATE (playlist);
+        item_data = ((GList *) iter->data2)->data;
+
+        key = va_arg (args, gchar *);
+
+        while (key) {
+                value = va_arg (args, gchar *);
+
+                g_hash_table_replace (item_data,
+                                      g_strdup (key),
+                                      g_strdup (value));
+
+                key = va_arg (args, gchar *);
+        }
+}
+
+/**
+ * totem_pl_playlist_set:
+ * @playlist: a #TotemPlPlaylist
+ * @iter: a #TotemPlPlaylistIter pointing to some item in @playlist
+ * @...: key/value string pairs, terminated with %NULL
+ *
+ * Sets the value for one or several keys in the element pointed
+ * by @iter.
+ **/
+void
+totem_pl_playlist_set (TotemPlPlaylist     *playlist,
+                       TotemPlPlaylistIter *iter,
+                       ...)
+{
+        va_list args;
+
+        g_return_if_fail (TOTEM_IS_PL_PLAYLIST (playlist));
+        g_return_if_fail (check_iter (playlist, iter));
+
+        va_start (args, iter);
+        totem_pl_playlist_set_valist (playlist, iter, args);
+        va_end (args);
+}
diff --git a/plparse/totem-pl-playlist.h b/plparse/totem-pl-playlist.h
new file mode 100644
index 0000000..ceddfdc
--- /dev/null
+++ b/plparse/totem-pl-playlist.h
@@ -0,0 +1,100 @@
+/*
+   Copyright (C) 2009, Nokia
+
+   The Gnome Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The Gnome Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the Gnome Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301  USA.
+
+   Author: Carlos Garnacho <carlos lanedo com>
+ */
+
+#ifndef __TOTEM_PL_PLAYLIST_H__
+#define __TOTEM_PL_PLAYLIST_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define TOTEM_TYPE_PL_PLAYLIST            (totem_pl_playlist_get_type ())
+#define TOTEM_PL_PLAYLIST(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), TOTEM_TYPE_PL_PLAYLIST, TotemPlPlaylist))
+#define TOTEM_PL_PLAYLIST_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), TOTEM_TYPE_PL_PLAYLIST, TotemPlPlaylistClass))
+#define TOTEM_IS_PL_PLAYLIST(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TOTEM_TYPE_PL_PLAYLIST))
+#define TOTEM_IS_PL_PLAYLIST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TOTEM_TYPE_PL_PLAYLIST))
+
+typedef struct TotemPlPlaylist TotemPlPlaylist;
+typedef struct TotemPlPlaylistClass TotemPlPlaylistClass;
+typedef struct TotemPlPlaylistIter TotemPlPlaylistIter;
+
+struct TotemPlPlaylist {
+        GObject parent_instance;
+};
+
+struct TotemPlPlaylistClass {
+        GObjectClass parent_class;
+};
+
+struct TotemPlPlaylistIter {
+        gpointer data1;
+        gpointer data2;
+};
+
+GType totem_pl_playlist_get_type (void) G_GNUC_CONST;
+
+TotemPlPlaylist * totem_pl_playlist_new (void);
+
+guint totem_pl_playlist_size   (TotemPlPlaylist     *playlist);
+
+/* Item insertion methods */
+void totem_pl_playlist_prepend (TotemPlPlaylist     *playlist,
+                                TotemPlPlaylistIter *iter);
+void totem_pl_playlist_append  (TotemPlPlaylist     *playlist,
+                                TotemPlPlaylistIter *iter);
+void totem_pl_playlist_insert  (TotemPlPlaylist     *playlist,
+                                gint                 position,
+                                TotemPlPlaylistIter *iter);
+
+/* Navigation methods */
+gboolean totem_pl_playlist_iter_first (TotemPlPlaylist     *playlist,
+                                       TotemPlPlaylistIter *iter);
+gboolean totem_pl_playlist_iter_next  (TotemPlPlaylist     *playlist,
+                                       TotemPlPlaylistIter *iter);
+gboolean totem_pl_playlist_iter_prev  (TotemPlPlaylist     *playlist,
+                                       TotemPlPlaylistIter *iter);
+
+/* Item edition methods */
+gboolean totem_pl_playlist_get_value (TotemPlPlaylist     *playlist,
+                                      TotemPlPlaylistIter *iter,
+                                      const gchar         *key,
+                                      GValue              *value);
+void totem_pl_playlist_get_valist    (TotemPlPlaylist     *playlist,
+                                      TotemPlPlaylistIter *iter,
+                                      va_list              args);
+void totem_pl_playlist_get           (TotemPlPlaylist     *playlist,
+                                      TotemPlPlaylistIter *iter,
+                                      ...) G_GNUC_NULL_TERMINATED;
+
+gboolean totem_pl_playlist_set_value (TotemPlPlaylist     *playlist,
+                                      TotemPlPlaylistIter *iter,
+                                      const gchar         *key,
+                                      GValue              *value);
+void totem_pl_playlist_set_valist    (TotemPlPlaylist     *playlist,
+                                      TotemPlPlaylistIter *iter,
+                                      va_list              args);
+void totem_pl_playlist_set           (TotemPlPlaylist     *playlist,
+                                      TotemPlPlaylistIter *iter,
+                                      ...) G_GNUC_NULL_TERMINATED;
+
+G_END_DECLS
+
+#endif /* __TOTEM_PL_PLAYLIST_H__ */
diff --git a/totem-plparser-uninstalled.pc.in b/totem-plparser-uninstalled.pc.in
index 47f0748..43a9a6e 100644
--- a/totem-plparser-uninstalled.pc.in
+++ b/totem-plparser-uninstalled.pc.in
@@ -8,7 +8,6 @@ gconf_serverdir= libexecdir@
 Name: totem-plparser
 Description: Totem Playlist Parser library
 Version: @VERSION@
-Requires: gtk+-2.0
 Requires.private: libxml-2.0 gmime-2.4
 Libs: ${pc_top_builddir}/${pcfiledir}/plparse/libtotem-plparser.la
 Cflags: -I${pc_top_builddir}/${pcfiledir}/plparse
diff --git a/totem-plparser.pc.in b/totem-plparser.pc.in
index 685a8db..66043dd 100644
--- a/totem-plparser.pc.in
+++ b/totem-plparser.pc.in
@@ -8,7 +8,6 @@ gconf_serverdir= libexecdir@
 Name: totem-plparser
 Description: Totem Playlist Parser library
 Version: @VERSION@
-Requires: gtk+-2.0
 Requires.private: libxml-2.0 @GMIME@
 Libs: -L${libdir} -ltotem-plparser
 Cflags: -I${includedir}/totem-pl-parser/1/plparser



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]