[libdmapsharing] Implement DAAPConnection and DPAPConnection, add test program written in Vala Signed-off-by: W. Mich



commit 0e7b8dffaebdab601732fb8ab9173d105f49560d
Author: W. Michael Petullo <mike flyn org>
Date:   Fri Dec 10 11:55:15 2010 -0600

    Implement DAAPConnection and DPAPConnection, add test program written in Vala
    Signed-off-by: W. Michael Petullo <mike flyn org>

 .gitignore                       |    2 +
 Makefile.am                      |    1 +
 configure.ac                     |   22 +++
 libdmapsharing-2.2.vapi          |  331 ++++++++++++++++++++++++++++++++++++++
 libdmapsharing/Makefile.am       |    4 +
 libdmapsharing/daap-connection.c |  195 ++++++++++++++++++++++
 libdmapsharing/daap-connection.h |   96 +++++++++++
 libdmapsharing/dmap-connection.c |  169 +++++--------------
 libdmapsharing/dmap-connection.h |   10 +-
 libdmapsharing/dmap-structure.c  |   16 --
 libdmapsharing/dpap-connection.c |  183 +++++++++++++++++++++
 libdmapsharing/dpap-connection.h |   96 +++++++++++
 tests/Makefile.am                |   39 +++++-
 tests/dpapview.ui                |   31 ++++
 tests/dpapview.vala              |  226 ++++++++++++++++++++++++++
 tests/test-daap-record.c         |    6 +-
 tests/test-dmap-client.c         |    4 +-
 17 files changed, 1282 insertions(+), 149 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 54f0292..7f3ee1e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -53,5 +53,7 @@ tests/.libs/
 tests/Makefile
 tests/Makefile.in
 tests/*.o
+tests/dpapview
 tests/test-dmap-client
 tests/test-dmap-server
+tests/vala.stamp
diff --git a/Makefile.am b/Makefile.am
index 3a1498e..2148dea 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -17,6 +17,7 @@ pkgconfig_DATA = $(pcfiles)
 
 EXTRA_DIST =				\
 	autogen.sh			\
+	libdmapsharing-2.2.vapi		\
 	libdmapsharing.pc.in		\
 	README-Memory
 
diff --git a/configure.ac b/configure.ac
index 3780215..58a941d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -326,6 +326,28 @@ else
   AC_WARN(GStreamer app element not present, transcoding will not be supported.)
 fi
 
+AM_MAINTAINER_MODE
+if test "x$USE_MAINTAINER_MODE" = "xyes" ; then
+        AM_PROG_VALAC([0.10.0])
+        if test "x$VALAC" = "x" ; then
+                AC_MSG_ERROR([Cannot find the "valac" compiler in your PATH])
+        fi
+fi
+
+PKG_CHECK_MODULES(GTK, gtk+-2.0, HAVE_GTK=yes, HAVE_GTK=no)
+if test "x$HAVE_GTK" = "xno"; then
+        AC_MSG_ERROR(you need gtk+-2.0 installed)
+fi
+AC_SUBST(GTK_CFLAGS)
+AC_SUBST(GTK_LIBS)
+
+PKG_CHECK_MODULES(GEE, gee-1.0, HAVE_GEE=yes, HAVE_GEE=no)
+if test "x$HAVE_GEE" = "xno"; then
+        AC_MSG_ERROR(you need gee-1.0 installed)
+fi
+AC_SUBST(GEE_CFLAGS)
+AC_SUBST(GEE_LIBS)
+
 AM_CONDITIONAL(USE_GSTREAMERAPP, test x"$HAVE_GSTREAMERAPP" = "xyes")
 
 AC_SUBST(GSTREAMERAPP_CFLAGS)
diff --git a/libdmapsharing-2.2.vapi b/libdmapsharing-2.2.vapi
new file mode 100644
index 0000000..d264112
--- /dev/null
+++ b/libdmapsharing-2.2.vapi
@@ -0,0 +1,331 @@
+/* libdmapsharing-2.2.vapi generated by vapigen, do not modify. */
+
+[CCode (cprefix = "DMAP", lower_case_cprefix = "dmap_")]
+namespace DMAP {
+	[CCode (cheader_filename = "libdmapsharing/dmap.h")]
+	public class Connection : GLib.Object {
+		[CCode (has_construct_function = false)]
+		public Connection (string name, string host, int port, bool password_protected, DMAP.Db db, DMAP.RecordFactory factory);
+		public virtual unowned Soup.Message build_message (string path, bool need_hash, double version, int req_id, bool send_close);
+		public void connect (DMAP.ConnectionCallback callback);
+		public void disconnect (DMAP.ConnectionCallback callback);
+		public bool @get (string path, bool need_hash, DMAP.ResponseHandler handler);
+		public unowned Soup.MessageHeaders get_headers (string uri);
+		public unowned GLib.SList get_playlists ();
+		public bool is_connected ();
+		public void setup ();
+		[NoAccessorMethod]
+		public void* base_uri { get; set; }
+		[NoAccessorMethod]
+		public int database_id { get; set; }
+		[NoAccessorMethod]
+		public void* db { get; construct; }
+		[NoAccessorMethod]
+		public double dmap_version { get; set; }
+		[NoAccessorMethod]
+		public void* factory { get; construct; }
+		[NoAccessorMethod]
+		public string host { owned get; construct; }
+		[NoAccessorMethod]
+		public string name { owned get; construct; }
+		[NoAccessorMethod]
+		public bool password_protected { get; construct; }
+		[NoAccessorMethod]
+		public uint port { get; construct; }
+		[NoAccessorMethod]
+		public int revision_number { get; set; }
+		[NoAccessorMethod]
+		public int session_id { get; set; }
+		public virtual signal unowned string authenticate (string name);
+		public virtual signal void connected ();
+		public virtual signal void connecting (ulong state, float progress);
+		public virtual signal void disconnected ();
+		public virtual signal void operation_done ();
+	}
+	[CCode (cheader_filename = "libdmapsharing/dmap.h")]
+	public class DACPShare : DAAP.Share {
+		[CCode (cname = "dacp_share_new", type = "DACPShare*", has_construct_function = false)]
+		public DACPShare (string library_name, DMAP.DACPPlayer player, DMAP.Db db, DMAP.ContainerDb container_db);
+		[CCode (cname = "dacp_share_pair")]
+		public static void pair (DMAP.DACPShare share, string service_name, char[] passcode);
+		[CCode (cname = "dacp_share_player_updated")]
+		public static void player_updated (DMAP.DACPShare share);
+		[CCode (cname = "dacp_share_start_lookup")]
+		public static void start_lookup (DMAP.DACPShare share);
+		[CCode (cname = "dacp_share_stop_lookup")]
+		public static void stop_lookup (DMAP.DACPShare share);
+		[NoAccessorMethod]
+		public string library_name { owned get; set; }
+		[NoAccessorMethod]
+		public GLib.Object player { owned get; construct; }
+		public virtual signal void add_guid (string guid);
+		public virtual signal bool lookup_guid (string guid);
+		public virtual signal void remote_found (string service_name, string remote_name);
+		public virtual signal void remote_lost (string service_name);
+		public virtual signal void remote_paired (string service_name, bool connected);
+	}
+	[CCode (cheader_filename = "libdmapsharing/dmap.h")]
+	public class DmapMdnsPublisher : GLib.Object {
+		[CCode (cname = "dmap_mdns_publisher_new", type = "DmapMdnsPublisher*", has_construct_function = false)]
+		public DmapMdnsPublisher ();
+		[CCode (cname = "dmap_mdns_publisher_error_quark")]
+		public static GLib.Quark error_quark ();
+		[CCode (cname = "dmap_mdns_publisher_publish")]
+		public static bool publish (DMAP.DmapMdnsPublisher publisher, string name, uint port, string type_of_service, bool password_required, string txt_records) throws GLib.Error;
+		[CCode (cname = "dmap_mdns_publisher_rename_at_port")]
+		public static bool rename_at_port (DMAP.DmapMdnsPublisher publisher, uint port, string name) throws GLib.Error;
+		[CCode (cname = "dmap_mdns_publisher_withdraw")]
+		public static bool withdraw (DMAP.DmapMdnsPublisher publisher, uint port) throws GLib.Error;
+		public virtual signal void name_collision (string name);
+		public virtual signal void published (string name);
+	}
+	[Compact]
+	[CCode (cheader_filename = "libdmapsharing/dmap.h")]
+	public class FilterDefinition {
+		public weak string key;
+		public bool negate;
+		public weak string value;
+	}
+	[CCode (cheader_filename = "libdmapsharing/dmap.h")]
+	public class MdnsBrowser : GLib.Object {
+		[CCode (has_construct_function = false)]
+		public MdnsBrowser (DMAP.MdnsBrowserServiceType type);
+		public static GLib.Quark error_quark ();
+		public DMAP.MdnsBrowserServiceType get_service_type ();
+		public unowned GLib.SList get_services ();
+		public bool start () throws GLib.Error;
+		public bool stop () throws GLib.Error;
+		public virtual signal void service_added (void* service);
+		public virtual signal void service_removed (string service);
+	}
+	[Compact]
+	[CCode (cheader_filename = "libdmapsharing/dmap.h")]
+	public class MdnsBrowserService {
+		public weak string host;
+		public weak string name;
+		public weak string pair;
+		public bool password_protected;
+		public uint port;
+		public weak string service_name;
+	}
+	[Compact]
+	[CCode (cheader_filename = "libdmapsharing/dmap.h")]
+	public class MetaDataMap {
+	}
+	[Compact]
+	[CCode (cheader_filename = "libdmapsharing/dmap.h")]
+	public class Playlist {
+		public int id;
+		public weak string name;
+		public weak GLib.List uris;
+	}
+	[CCode (cheader_filename = "libdmapsharing/dmap.h")]
+	public class Share : GLib.Object {
+		[CCode (has_construct_function = false)]
+		protected Share ();
+		[NoWrapper]
+		public virtual void add_entry_to_mlcl (void* id, DMAP.Record record, void* mb);
+		[NoWrapper]
+		public virtual void content_codes (Soup.Server server, Soup.Message message, string path, GLib.HashTable query, Soup.ClientContext ctx);
+		[NoWrapper]
+		public virtual void ctrl_int (Soup.Server server, Soup.Message message, string path, GLib.HashTable query, Soup.ClientContext ctx);
+		[NoWrapper]
+		public virtual void databases (Soup.Server server, Soup.Message message, string path, GLib.HashTable query, Soup.ClientContext context);
+		[NoWrapper]
+		public virtual void databases_browse_xxx (Soup.Server server, Soup.Message msg, string path, GLib.HashTable query, Soup.ClientContext context);
+		[NoWrapper]
+		public virtual void databases_items_xxx (Soup.Server server, Soup.Message msg, string path, GLib.HashTable query, Soup.ClientContext context);
+		public static void free_filter (GLib.SList filter);
+		[NoWrapper]
+		public virtual uint get_desired_port ();
+		[NoWrapper]
+		public virtual void* get_meta_data_map ();
+		[NoWrapper]
+		public virtual unowned string get_type_of_service ();
+		[NoWrapper]
+		public virtual void login (Soup.Server server, Soup.Message message, string path, GLib.HashTable query, Soup.ClientContext ctx);
+		[NoWrapper]
+		public virtual void logout (Soup.Server server, Soup.Message message, string path, GLib.HashTable query, Soup.ClientContext ctx);
+		[NoWrapper]
+		public virtual void message_add_standard_headers (Soup.Message msg);
+		[NoWrapper]
+		public virtual void name_collision (DMAP.DmapMdnsPublisher publisher, string name);
+		[NoWrapper]
+		public virtual void published (DMAP.DmapMdnsPublisher publisher, string name);
+		[NoWrapper]
+		public virtual void server_info (Soup.Server server, Soup.Message message, string path, GLib.HashTable query, Soup.ClientContext ctx);
+		[NoWrapper]
+		public virtual void update (Soup.Server server, Soup.Message message, string path, GLib.HashTable query, Soup.ClientContext ctx);
+		[NoAccessorMethod]
+		public uint auth_method { get; set; }
+		[NoAccessorMethod]
+		public void* container_db { get; construct; }
+		[NoAccessorMethod]
+		public void* db { get; construct; }
+		[NoAccessorMethod]
+		public string name { owned get; set; }
+		[NoAccessorMethod]
+		public string password { owned get; set; }
+		[NoAccessorMethod]
+		public uint revision_number { get; set; }
+		[NoAccessorMethod]
+		public Soup.Server server { owned get; }
+		[NoAccessorMethod]
+		public string transcode_mimetype { owned get; construct; }
+		[NoAccessorMethod]
+		[CCode (array_length = false, array_null_terminated = true)]
+		public string[] txt_records { owned get; set; }
+	}
+	[Compact]
+	[CCode (cheader_filename = "libdmapsharing/dmap.h")]
+	public class bitwise {
+	}
+	[CCode (cheader_filename = "libdmapsharing/dmap.h")]
+	public interface ContainerDb {
+		public abstract int64 count ();
+		public abstract void @foreach (GLib.HFunc func, void* data);
+		public abstract unowned DMAP.ContainerRecord lookup_by_id (uint id);
+	}
+	[CCode (cheader_filename = "libdmapsharing/dmap.h")]
+	public interface ContainerRecord {
+		public abstract void add_entry (DMAP.Record record, int id);
+		public abstract unowned DMAP.Db get_entries ();
+		public abstract uint64 get_entry_count ();
+		public abstract uint get_id ();
+	}
+	[CCode (cheader_filename = "libdmapsharing/dmap.h")]
+	public interface DACPPlayer {
+		[CCode (cname = "dacp_player_cue_clear")]
+		public abstract void cue_clear (DMAP.DACPPlayer player);
+		[CCode (cname = "dacp_player_cue_play")]
+		public abstract void cue_play (DMAP.DACPPlayer player, GLib.List records, uint index);
+		[CCode (cname = "dacp_player_next_item")]
+		public abstract void next_item (DMAP.DACPPlayer player);
+		[CCode (cname = "dacp_player_now_playing_artwork")]
+		public abstract unowned string now_playing_artwork (DMAP.DACPPlayer player, uint width, uint height);
+		[CCode (cname = "dacp_player_now_playing_record")]
+		public abstract unowned DAAP.Record now_playing_record (DMAP.DACPPlayer player);
+		[CCode (cname = "dacp_player_pause")]
+		public abstract void pause (DMAP.DACPPlayer player);
+		[CCode (cname = "dacp_player_play_pause")]
+		public abstract void play_pause (DMAP.DACPPlayer player);
+		[CCode (cname = "dacp_player_prev_item")]
+		public abstract void prev_item (DMAP.DACPPlayer player);
+	}
+	[CCode (cheader_filename = "libdmapsharing/dmap.h")]
+	public interface Db {
+		public abstract uint add (DMAP.Record record);
+		public abstract uint add_path (string path);
+		public abstract uint add_with_id (DMAP.Record record, uint id);
+		public unowned GLib.HashTable apply_filter (GLib.SList filter_def);
+		public abstract int64 count ();
+		public abstract void @foreach (GLib.HFunc func);
+		public abstract unowned DMAP.Record lookup_by_id (uint id);
+		public abstract uint lookup_id_by_location (string location);
+	}
+	[CCode (cheader_filename = "libdmapsharing/dmap.h")]
+	public interface Record {
+		public abstract unowned DMAP.Record set_from_blob (GLib.ByteArray blob);
+		public abstract unowned GLib.ByteArray to_blob ();
+	}
+	[CCode (cheader_filename = "libdmapsharing/dmap.h")]
+	public interface RecordFactory {
+		public abstract DMAP.Record create (void* user_data);
+	}
+	[CCode (cprefix = "DMAP_", has_type_id = false, cheader_filename = "libdmapsharing/dmap.h")]
+	public enum ConnectionState {
+		GET_INFO,
+		GET_PASSWORD,
+		LOGIN,
+		GET_REVISION_NUMBER,
+		GET_DB_INFO,
+		GET_SONGS,
+		GET_PLAYLISTS,
+		GET_PLAYLIST_ENTRIES,
+		LOGOUT,
+		DONE
+	}
+	[CCode (cprefix = "PLAY_", has_type_id = false, cheader_filename = "libdmapsharing/dmap.h")]
+	public enum DACPPlayState {
+		STOPPED,
+		PAUSED,
+		PLAYING
+	}
+	[CCode (cprefix = "REPEAT_", has_type_id = false, cheader_filename = "libdmapsharing/dmap.h")]
+	public enum DACPRepeatState {
+		NONE,
+		SINGLE,
+		ALL
+	}
+	[CCode (cprefix = "DMAP_MDNS_PUBLISHER_ERROR_", has_type_id = false, cheader_filename = "libdmapsharing/dmap.h")]
+	public enum DmapMdnsPublisherError {
+		NOT_RUNNING,
+		FAILED
+	}
+	[CCode (cprefix = "DMAP_MDNS_BROWSER_ERROR_", has_type_id = false, cheader_filename = "libdmapsharing/dmap.h")]
+	public enum MdnsBrowserError {
+		NOT_RUNNING,
+		FAILED
+	}
+	[CCode (cprefix = "DMAP_MDNS_BROWSER_SERVICE_TYPE_", has_type_id = false, cheader_filename = "libdmapsharing/dmap.h")]
+	public enum MdnsBrowserServiceType {
+		INVALID,
+		DAAP,
+		DPAP,
+		DACP,
+		LAST
+	}
+	[CCode (cprefix = "DMAP_MEDIA_KIND_", has_type_id = false, cheader_filename = "libdmapsharing/dmap.h")]
+	public enum MediaKind {
+		MUSIC,
+		MOVIE
+	}
+	[CCode (cheader_filename = "libdmapsharing/dmap.h")]
+	public delegate bool ConnectionCallback (DMAP.Connection connection, bool result, string reason);
+	[CCode (cheader_filename = "libdmapsharing/dmap.h", has_target = false)]
+	public delegate unowned string RecordGetValueFunc (DMAP.Record record);
+	[CCode (cheader_filename = "libdmapsharing/dmap.h")]
+	public delegate void ResponseHandler (DMAP.Connection connection, uint status, GLib.Node structure);
+	[CCode (cheader_filename = "libdmapsharing/dmap.h")]
+	public const int SHARE_CHUNK_SIZE;
+	[CCode (cheader_filename = "libdmapsharing/dmap.h")]
+	public const int STATUS_OK;
+	[CCode (cheader_filename = "libdmapsharing/dmap.h")]
+	public static void hash_generate (short version_major, uchar[] url, uchar hash_select, uchar[] @out, int request_id);
+}
+namespace DPAP {
+	[CCode (cheader_filename = "libdmapsharing/dmap.h")]
+	public class Share : DMAP.Share {
+		[CCode (cname = "dpap_share_new", type = "DPAPShare*", has_construct_function = false)]
+		public Share (string name, string password, void* db, void* container_db, string transcode_mimetype);
+	}
+	[CCode (cheader_filename = "libdmapsharing/dmap.h")]
+	public interface Record {
+		[CCode (cname = "dpap_record_read")]
+		public abstract unowned GLib.InputStream read (DPAP.Record record) throws GLib.Error;
+	}
+	public class Connection : DMAP.Connection {
+		[CCode (has_construct_function = false)]
+		public Connection (string name, string host, int port, bool password_protected, DMAP.Db db, DMAP.RecordFactory factory);
+	}
+}
+namespace DAAP {
+	[CCode (cheader_filename = "libdmapsharing/dmap.h")]
+	public class Share : DMAP.Share {
+		[CCode (cname = "dpap_share_new", type = "DAAP.Share*", has_construct_function = false)]
+		public Share (string name, string password, void* db, void* container_db, string transcode_mimetype);
+	}
+	[CCode (cheader_filename = "libdmapsharing/dmap.h")]
+	public interface Record {
+		[CCode (cname = "daap_record_cmp_by_album")]
+		public static int cmp_by_album (void* a, void* b, DMAP.Db db);
+		[CCode (cname = "daap_record_itunes_compat")]
+		public abstract bool itunes_compat (DAAP.Record record);
+		[CCode (cname = "daap_record_read")]
+		public abstract unowned GLib.InputStream read (DAAP.Record record) throws GLib.Error;
+	}
+	public class Connection : DMAP.Connection {
+		[CCode (has_construct_function = false)]
+		public Connection (string name, string host, int port, bool password_protected, DMAP.Db db, DMAP.RecordFactory factory);
+	}
+}
diff --git a/libdmapsharing/Makefile.am b/libdmapsharing/Makefile.am
index 6a589d4..cdb89a9 100644
--- a/libdmapsharing/Makefile.am
+++ b/libdmapsharing/Makefile.am
@@ -4,6 +4,7 @@ BUILT_SOURCES = dmap-marshal.c dmap-marshal.h dmap-enums.c dmap-enums.h
 
 libdmapsharing_la_SOURCES = \
 	$(BUILT_SOURCES) \
+	daap-connection.c \
 	daap-record.c \
 	daap-share.c \
 	dacp-share.c \
@@ -17,6 +18,7 @@ libdmapsharing_la_SOURCES = \
 	dmap-record-factory.c \
 	dmap-share.c \
 	dmap-structure.c \
+	dpap-connection.c \
 	dpap-record.c \
 	dpap-share.c
 
@@ -66,6 +68,7 @@ libdmapsharingincludedir = \
 	$(includedir)/libdmapsharing- API_VERSION@/libdmapsharing
 
 libdmapsharinginclude_HEADERS = \
+	daap-connection.h \
 	daap-record.h \
 	daap-share.h \
 	dacp-share.h \
@@ -81,6 +84,7 @@ libdmapsharinginclude_HEADERS = \
 	dmap-record.h \
 	dmap-record-factory.h \
 	dmap-share.h \
+	dpap-connection.h \
 	dpap-record.h \
 	dpap-share.h
 
diff --git a/libdmapsharing/daap-connection.c b/libdmapsharing/daap-connection.c
new file mode 100644
index 0000000..84d671a
--- /dev/null
+++ b/libdmapsharing/daap-connection.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2004,2005 Charles Schmidt <cschmidt2 emich edu>
+ * Copyright (C) 2006 INDT
+ *  Andre Moreira Magalhaes <andre magalhaes indt org br>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "config.h"
+
+#include <libdmapsharing/daap-connection.h>
+#include <libdmapsharing/dmap-structure.h>
+
+#define DAAP_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_DAAP_CONNECTION, DAAPConnectionPrivate))
+
+/* FIXME:
+struct DAAPConnectionPrivate {
+};
+*/
+
+static DMAPContentCode
+get_protocol_version_cc (DMAPConnection *connection)
+{
+	return DMAP_CC_APRO;
+}
+
+static gchar *
+get_query_metadata (void)
+{
+	return g_strdup ("dmap.itemid,dmap.itemname,daap.songalbum,"
+			 "daap.songartist,daap.songgenre,daap.songsize,"
+			 "daap.songtime,daap.songtrackcount,daap.songtracknumber,"
+			 "daap.songyear,daap.songformat,"
+			 "daap.songbitrate,daap.songdiscnumber,daap.songdataurl,"
+			 "daap.sortartist,daap.sortalbum");
+}
+
+static DMAPRecord *
+handle_mlcl (DMAPConnection *connection, DMAPRecordFactory *factory, GNode *n, int *item_id)
+{
+	GNode *n2;
+	DMAPRecord *record = NULL;
+	const gchar *title = NULL;
+	const gchar *album = NULL;
+	const gchar *artist = NULL;
+	const gchar *format = NULL;
+	const gchar *genre = NULL;
+	const gchar *streamURI = NULL;
+	const gchar *sort_artist = NULL;
+	const gchar *sort_album = NULL;
+	gint length = 0;
+	gint track_number = 0;
+	gint disc_number = 0;
+	gint year = 0;
+	gint size = 0;
+	gint bitrate = 0;
+
+	for (n2 = n->children; n2; n2 = n2->next) {
+		DMAPStructureItem *meta_item;
+
+		meta_item = n2->data;
+
+		switch (meta_item->content_code) {
+			case DMAP_CC_MIID:
+				*item_id = g_value_get_int (&(meta_item->content));
+				break;
+			case DMAP_CC_MINM:
+				title = g_value_get_string (&(meta_item->content));
+				break;
+			case DMAP_CC_ASAL:
+				album = g_value_get_string (&(meta_item->content));
+				break;
+			case DMAP_CC_ASAR:
+				artist = g_value_get_string (&(meta_item->content));
+				break;
+			case DMAP_CC_ASFM:
+				format = g_value_get_string (&(meta_item->content));
+				break;
+			case DMAP_CC_ASGN:
+				genre = g_value_get_string (&(meta_item->content));
+				break;
+			case DMAP_CC_ASTM:
+				length = g_value_get_int (&(meta_item->content));
+				break;
+			case DMAP_CC_ASTN:
+				track_number = g_value_get_int (&(meta_item->content));
+				break;
+			case DMAP_CC_ASDN:
+				disc_number = g_value_get_int (&(meta_item->content));
+				break;
+			case DMAP_CC_ASYR:
+				year = g_value_get_int (&(meta_item->content));
+				break;
+			case DMAP_CC_ASSZ:
+				size = g_value_get_int (&(meta_item->content));
+				break;
+			case DMAP_CC_ASBR:
+				bitrate = g_value_get_int (&(meta_item->content));
+				break;
+			case DMAP_CC_ASUL:
+				streamURI = g_value_get_string (&(meta_item->content));
+				break;
+			case DMAP_CC_ASSA:
+				sort_artist = g_value_get_string (&(meta_item->content));
+				break;
+			case DMAP_CC_ASSU:
+				sort_album = g_value_get_string (&(meta_item->content));
+				break;
+			default:
+				break;
+		}
+	}
+
+	record = dmap_record_factory_create (factory, NULL);
+	if (record == NULL) {
+		goto _return;
+	}
+	g_object_set (record,
+		     "year", year,
+		     "track", track_number,
+		     "disc", disc_number,
+		     "bitrate", bitrate,
+		     "duration", length / 1000,
+		     "filesize", (guint64) size,
+		     "format", format,
+		     "title", title,
+		     "songalbum", album,
+		     "songartist", artist,
+		     "songgenre", genre,
+		     "sort-artist", sort_artist,
+		     "sort-album", sort_album,
+		      NULL);
+
+_return:
+	return record;
+}
+
+static void
+daap_connection_class_init (DAAPConnectionClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	DMAPConnectionClass *parent_class = DMAP_CONNECTION_CLASS (object_class);
+
+	parent_class->get_protocol_version_cc = get_protocol_version_cc;
+	parent_class->get_query_metadata = get_query_metadata;
+	parent_class->handle_mlcl = handle_mlcl;
+
+	/* FIXME:
+	g_type_class_add_private (klass, sizeof (DAAPConnectionPrivate));
+	*/
+}
+
+DAAPConnection *
+daap_connection_new (const char        *name,
+		     const char        *host,
+		     int                port,
+		     gboolean           password_protected,
+		     DMAPDb            *db,
+		     DMAPRecordFactory *factory)
+{
+	DAAPConnection *connection;
+	
+	connection = g_object_new (TYPE_DAAP_CONNECTION,
+			          "name", name,
+			          "password-protected", password_protected,
+			          "db", db,
+			          "host", host,
+			          "port", port,
+				  "factory", factory,
+			           NULL);
+
+	return connection;
+}
+
+static void
+daap_connection_init (DAAPConnection *connection)
+{
+	/* FIXME: 
+	connection->priv = DAAP_CONNECTION_GET_PRIVATE (connection);
+	*/
+}
+
+G_DEFINE_TYPE (DAAPConnection, daap_connection, TYPE_DMAP_CONNECTION)
diff --git a/libdmapsharing/daap-connection.h b/libdmapsharing/daap-connection.h
new file mode 100644
index 0000000..a9825be
--- /dev/null
+++ b/libdmapsharing/daap-connection.h
@@ -0,0 +1,96 @@
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __DAAP_CONNECTION_H
+#define __DAAP_CONNECTION_H
+
+#include <glib-object.h>
+
+#include <libdmapsharing/dmap-connection.h>
+#include <libdmapsharing/dmap-db.h>
+
+G_BEGIN_DECLS
+
+/**
+ * TYPE_DAAP_CONNECTION:
+ *
+ * The type for #DAAPConnection.
+ */
+#define TYPE_DAAP_CONNECTION		(daap_connection_get_type ())
+/**
+ * DAAP_CONNECTION:
+ * @o: Object which is subject to casting.
+ *
+ * Casts a #DAAPConnection or derived pointer into a (DAAPConnection *) pointer.
+ * Depending on the current debugging level, this function may invoke
+ * certain runtime checks to identify invalid casts.
+ */
+#define DAAP_CONNECTION(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), TYPE_DAAP_CONNECTION, DAAPConnection))
+/**
+ * DAAP_CONNECTION_CLASS:
+ * @k: a valid #DAAPConnectionClass
+ *
+ * Casts a derived #DAAPConnectionClass structure into a #DAAPConnectionClass
+ * structure.
+ */
+#define DAAP_CONNECTION_CLASS(k)	(G_TYPE_CHECK_CLASS_CAST((k), TYPE_DAAP_CONNECTION, DAAPConnectionClass))
+/**
+ * IS_DAAP_CONNECTION:
+ * @o: Instance to check for being a %TYPE_DAAP_CONNECTION.
+ *
+ * Checks whether a valid #GTypeInstance pointer is of type %TYPE_DAAP_CONNECTION.
+ */
+#define IS_DAAP_CONNECTION(o)	(G_TYPE_CHECK_INSTANCE_TYPE ((o), TYPE_DAAP_CONNECTION))
+/**
+ * IS_DAAP_CONNECTION_CLASS:
+ * @k: a #DAAPConnectionClass
+ *
+ * Checks whether @k "is a" valid #DAAPConnectionClass structure of type
+ * %DAAP_CONNECTION or derived.
+ */
+#define IS_DAAP_CONNECTION_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), TYPE_DAAP_CONNECTION))
+/**
+ * DAAP_CONNECTION_GET_CLASS:
+ * @o: a #DAAPConnection instance.
+ *
+ * Get the class structure associated to a #DAAPConnection instance.
+ *
+ * Returns: pointer to object class structure.
+ */
+#define DAAP_CONNECTION_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), TYPE_DAAP_CONNECTION, DAAPConnectionClass))
+
+typedef struct DAAPConnectionPrivate DAAPConnectionPrivate;
+
+typedef struct {
+	DMAPConnectionClass dmap_connection_class;
+} DAAPConnectionClass;
+
+typedef struct {
+	DMAPConnection dmap_connection_instance;
+	DAAPConnectionPrivate *priv;
+} DAAPConnection;
+
+GType              daap_connection_get_type        (void);
+
+DAAPConnection * daap_connection_new             (const char              *name,
+						  const char              *host,
+						  int                      port,
+						  gboolean                 password_protected,
+						  DMAPDb		  *db,
+						  DMAPRecordFactory *factory);
+G_END_DECLS
+
+#endif /* __DAAP_CONNECTION_H */
diff --git a/libdmapsharing/dmap-connection.c b/libdmapsharing/dmap-connection.c
index c442305..038f509 100644
--- a/libdmapsharing/dmap-connection.c
+++ b/libdmapsharing/dmap-connection.c
@@ -149,6 +149,10 @@ dmap_connection_class_init (DMAPConnectionClass *klass)
 {
 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
+	klass->get_protocol_version_cc = NULL;
+	klass->get_query_metadata = NULL;
+	klass->handle_mlcl = NULL;
+
 	object_class->finalize	   = dmap_connection_finalize;
 	object_class->dispose       = dmap_connection_dispose;
 	object_class->set_property = dmap_connection_set_property;
@@ -725,7 +729,8 @@ handle_server_info (DMAPConnection *connection,
 	}
 
 	/* get the daap version number */
-	item = dmap_structure_find_item (structure, DMAP_CC_APRO);
+	item = dmap_structure_find_item (structure, 
+					 DMAP_CONNECTION_GET_CLASS(connection)->get_protocol_version_cc (connection));
 	if (item == NULL) {
 		dmap_connection_state_done (connection, FALSE);
 		return;
@@ -917,135 +922,52 @@ handle_song_listing (DMAPConnection *connection,
 	if (priv->emit_progress_id != 0) {
 		g_source_remove (priv->emit_progress_id);
 	}
-	connection->priv->emit_progress_id = g_idle_add ((GSourceFunc) emit_progress_idle, connection);
+	priv->emit_progress_id = g_idle_add ((GSourceFunc) emit_progress_idle, connection);
 
 	for (i = 0, n = listing_node->children; n; i++, n = n->next) {
-		GNode *n2;
-		DMAPRecord *record = NULL;
-		gchar *uri = NULL;
 		gint item_id = 0;
-		const gchar *title = NULL;
-		const gchar *album = NULL;
-		const gchar *artist = NULL;
-		const gchar *format = NULL;
-		const gchar *genre = NULL;
-		const gchar *streamURI = NULL;
-		const gchar *sort_artist = NULL;
-		const gchar *sort_album = NULL;
-		gint length = 0;
-		gint track_number = 0;
-		gint disc_number = 0;
-		gint year = 0;
-		gint size = 0;
-		gint bitrate = 0;
-
-		for (n2 = n->children; n2; n2 = n2->next) {
-			DMAPStructureItem *meta_item;
-
-			meta_item = n2->data;
-
-			switch (meta_item->content_code) {
-				case DMAP_CC_MIID:
-					item_id = g_value_get_int (&(meta_item->content));
-					break;
-				case DMAP_CC_MINM:
-					title = g_value_get_string (&(meta_item->content));
-					break;
-				case DMAP_CC_ASAL:
-					album = g_value_get_string (&(meta_item->content));
-					break;
-				case DMAP_CC_ASAR:
-					artist = g_value_get_string (&(meta_item->content));
-					break;
-				case DMAP_CC_ASFM:
-					format = g_value_get_string (&(meta_item->content));
-					break;
-				case DMAP_CC_ASGN:
-					genre = g_value_get_string (&(meta_item->content));
-					break;
-				case DMAP_CC_ASTM:
-					length = g_value_get_int (&(meta_item->content));
-					break;
-				case DMAP_CC_ASTN:
-					track_number = g_value_get_int (&(meta_item->content));
-					break;
-				case DMAP_CC_ASDN:
-					disc_number = g_value_get_int (&(meta_item->content));
-					break;
-				case DMAP_CC_ASYR:
-					year = g_value_get_int (&(meta_item->content));
-					break;
-				case DMAP_CC_ASSZ:
-					size = g_value_get_int (&(meta_item->content));
-					break;
-				case DMAP_CC_ASBR:
-					bitrate = g_value_get_int (&(meta_item->content));
-					break;
-				case DMAP_CC_ASUL:
-					streamURI = g_value_get_string (&(meta_item->content));
-					break;
-				case DMAP_CC_ASSA:
-					sort_artist = g_value_get_string (&(meta_item->content));
-					break;
-				case DMAP_CC_ASSU:
-					sort_album = g_value_get_string (&(meta_item->content));
-					break;
-				default:
-					break;
+		DMAPRecord *record = DMAP_CONNECTION_GET_CLASS(connection)->handle_mlcl (connection, priv->record_factory, n, &item_id);
+		if (record) {
+			gchar *uri = NULL;
+			gchar *format = NULL;
+			
+			g_object_get (record, "format", &format, NULL);
+			if (format == NULL) {
+				format = "Unknown";
 			}
-		}
 
-		/*if (connection->dmap_version == 3.0) {*/
+			/*if (connection->dmap_version == 3.0) {*/
 			uri = g_strdup_printf ("%s/databases/%d/items/%d.%s?session-id=%u",
-					       priv->daap_base_uri,
-					       priv->database_id,
+					       connection->priv->daap_base_uri,
+					       connection->priv->database_id,
 					       item_id, format,
-					       priv->session_id);
-		/*} else {*/
-		/* uri should be
-		 * "/databases/%d/items/%d.%s?session-id=%u&revision-id=%d";
-		 * but its not going to work cause the other parts of the code
-		 * depend on the uri to have the ip address so that the
-		 * DAAPSource can be found to ++request_id
-		 * maybe just /dont/ support older itunes.  doesn't seem
-		 * unreasonable to me, honestly
-		 */
-		/*}*/
-		record = dmap_record_factory_create (priv->record_factory, NULL);
-		if (record == NULL) {
-			g_debug ("cannot create record for daap track %s", uri);
-			continue;
+					       connection->priv->session_id);
+			/*} else {*/
+			/* uri should be
+			 * "/databases/%d/items/%d.%s?session-id=%u&revision-id=%d";
+			 * but its not going to work cause the other parts of the code
+			 * depend on the uri to have the ip address so that the
+			 * DAAPSource can be found to ++request_id
+			 * maybe just /dont/ support older itunes.  doesn't seem
+			 * unreasonable to me, honestly
+			 */
+			/*}*/
+
+			g_object_set (record, "location", uri, NULL);
+			dmap_db_add (connection->priv->db, record);
+			g_object_unref (record);
+			g_hash_table_insert (connection->priv->item_id_to_uri, GINT_TO_POINTER (item_id), g_strdup (uri));
+			g_free (uri);
+		} else {
+			g_debug ("cannot create record for daap track");
 		}
-		/* FIXME: This is DAAP-specific! */
-		g_object_set (record,
-			     "location", uri,
-			     "year", year,
-			     "track", track_number,
-			     "disc", disc_number,
-			     "bitrate", bitrate,
-			     "duration", length / 1000,
-			     "filesize", (guint64) size,
-			     "format", format,
-			     "title", title,
-			     "songalbum", album,
-			     "songartist", artist,
-			     "songgenre", genre,
-			     "sort-artist", sort_artist,
-			     "sort-album", sort_album,
-			      NULL);
-		g_hash_table_insert (priv->item_id_to_uri, GINT_TO_POINTER (item_id), g_strdup (uri));
-		g_free (uri);
-
-		dmap_db_add (priv->db, record);
-		g_debug ("Got song: %s", title);
-		g_object_unref (record);
 
 		if (i % commit_batch == 0) {
-			connection->priv->progress = ((float) i / (float) returned_count);
+			priv->progress = ((float) i / (float) returned_count);
 			if (priv->emit_progress_id != 0) {
 				g_source_remove (connection->priv->emit_progress_id);
 			}
-			connection->priv->emit_progress_id = g_idle_add ((GSourceFunc) emit_progress_idle, connection);
+			priv->emit_progress_id = g_idle_add ((GSourceFunc) emit_progress_idle, connection);
 		}
 	}
 
@@ -1473,6 +1395,7 @@ static gboolean
 dmap_connection_do_something (DMAPConnection *connection)
 {
 	DMAPConnectionPrivate *priv = connection->priv;
+	char *meta;
 	char *path;
 
 	g_debug ("Doing something for state: %d", priv->state);
@@ -1551,22 +1474,20 @@ dmap_connection_do_something (DMAPConnection *connection)
 
 	case DMAP_GET_SONGS:
 		g_debug ("Getting DAAP song listing");
+		meta = DMAP_CONNECTION_GET_CLASS(connection)->get_query_metadata (connection);
 		path = g_strdup_printf ("/databases/%i/items?session-id=%u&revision-number=%i"
-				        "&meta=dmap.itemid,dmap.itemname,daap.songalbum,"
-					"daap.songartist,daap.songgenre,daap.songsize,"
-					"daap.songtime,daap.songtrackcount,daap.songtracknumber,"
-					"daap.songyear,daap.songformat,"
-					"daap.songbitrate,daap.songdiscnumber,daap.songdataurl,"
-					"daap.sortartist,daap.sortalbum",
+				        "&meta=%s",
 					priv->database_id,
 					priv->session_id,
-					priv->revision_number);
+					priv->revision_number,
+					meta);
 		if (! http_get (connection, path, TRUE, priv->dmap_version, 0, FALSE,
 			       (DMAPResponseHandler) handle_song_listing, NULL, TRUE)) {
 			g_debug ("Could not get DAAP song listing");
 			dmap_connection_state_done (connection, FALSE);
 		}
 		g_free (path);
+		g_free (meta);
 		break;
 
 	case DMAP_GET_PLAYLISTS:
diff --git a/libdmapsharing/dmap-connection.h b/libdmapsharing/dmap-connection.h
index 0e824aa..3b9d253 100644
--- a/libdmapsharing/dmap-connection.h
+++ b/libdmapsharing/dmap-connection.h
@@ -25,8 +25,9 @@
 #include <glib-object.h>
 #include <libsoup/soup.h>
 
-#include "dmap-db.h"
-#include "dmap-record-factory.h"
+#include <libdmapsharing/dmap-structure.h>
+#include <libdmapsharing/dmap-db.h>
+#include <libdmapsharing/dmap-record-factory.h>
 
 G_BEGIN_DECLS
 
@@ -107,6 +108,11 @@ typedef struct {
 typedef struct {
 	GObjectClass parent;
 
+	/* Pure virtual methods: */
+	DMAPContentCode (*get_protocol_version_cc) (DMAPConnection *connection);
+	gchar *         (*get_query_metadata)      (DMAPConnection *connection);
+	DMAPRecord *(*handle_mlcl) (DMAPConnection *connection, DMAPRecordFactory *factory, GNode *mlcl, gint *item_id);
+
 	SoupMessage * (*build_message)
 				  (DMAPConnection     *connection,
 				   const gchar        *path,
diff --git a/libdmapsharing/dmap-structure.c b/libdmapsharing/dmap-structure.c
index 47e7f1c..2ea1670 100644
--- a/libdmapsharing/dmap-structure.c
+++ b/libdmapsharing/dmap-structure.c
@@ -379,8 +379,6 @@ dmap_structure_parse_container_buffer (GNode *parent,
         GNode *node = NULL;
         GType gtype;
         
-        g_debug ("l is %d and buf_length is %d\n", l, buf_length);
-
         /* we need at least 8 bytes, 4 of content_code and 4 of size */
         if (buf_length - l < 8) {
             g_debug ("Malformed response recieved\n");
@@ -406,8 +404,6 @@ dmap_structure_parse_container_buffer (GNode *parent,
         }
         l += 4;
 
-        g_debug ("content_code = %d, codesize is %d, l is %d\n", cc, codesize, l);
-        
         item = g_new0 (DMAPStructureItem, 1);
         item->content_code = cc;
         node = g_node_new (item);
@@ -431,8 +427,6 @@ dmap_structure_parse_container_buffer (GNode *parent,
                 
                 item->size = 1;
                 g_value_set_char (&(item->content), c);
-                g_debug ("Code: %s, content (%d): \"%c\"\n", dmap_content_code_string (item->content_code), codesize, (gchar)c);
-
                 break;
             }
             case DMAP_TYPE_SHORT: {
@@ -444,8 +438,6 @@ dmap_structure_parse_container_buffer (GNode *parent,
 
                 item->size = 2;
                 g_value_set_int (&(item->content),(gint32)s);
-                g_debug ("Code: %s, content (%d): %hi\n", dmap_content_code_string (item->content_code), codesize, s);
-
                 break;
             }
             case DMAP_TYPE_DATE:
@@ -458,7 +450,6 @@ dmap_structure_parse_container_buffer (GNode *parent,
                 
                 item->size = 4;
                 g_value_set_int (&(item->content), i);
-                g_debug ("Code: %s, content (%d): %d\n", dmap_content_code_string (item->content_code), codesize, i);
                 break;
             }
             case DMAP_TYPE_INT64: {
@@ -470,8 +461,6 @@ dmap_structure_parse_container_buffer (GNode *parent,
                 
                 item->size = 8;
                 g_value_set_int64 (&(item->content), i);
-                g_debug ("Code: %s, content (%d): %"G_GINT64_FORMAT"\n", dmap_content_code_string (item->content_code), codesize, i);
-
                 break;
             }
             case DMAP_TYPE_STRING: {
@@ -479,8 +468,6 @@ dmap_structure_parse_container_buffer (GNode *parent,
 
                 item->size = strlen (s);
                 g_value_set_string (&(item->content), s);
-                g_debug ("Code: %s, content (%d): \"%s\"\n", dmap_content_code_string (item->content_code), codesize, s);
-
                 break;
             }
             case DMAP_TYPE_POINTER: {
@@ -509,12 +496,9 @@ dmap_structure_parse_container_buffer (GNode *parent,
                 
                 item->size = 4;
                 g_value_set_double (&(item->content), v);
-                g_debug ("Code: %s, content: %f\n", dmap_content_code_string (item->content_code), v);
-
                 break;
             }
             case DMAP_TYPE_CONTAINER: {
-                g_debug ("Code: %s, container\n", dmap_content_code_string (item->content_code));
                 dmap_structure_parse_container_buffer (node,&(buf[l]), codesize);
                 break;
             }
diff --git a/libdmapsharing/dpap-connection.c b/libdmapsharing/dpap-connection.c
new file mode 100644
index 0000000..5a08768
--- /dev/null
+++ b/libdmapsharing/dpap-connection.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2004,2005 Charles Schmidt <cschmidt2 emich edu>
+ * Copyright (C) 2006 INDT
+ *  Andre Moreira Magalhaes <andre magalhaes indt org br>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "config.h"
+
+#include <libdmapsharing/dpap-connection.h>
+#include <libdmapsharing/dmap-structure.h>
+
+#define DPAP_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_DPAP_CONNECTION, DPAPConnectionPrivate))
+
+/* FIXME:
+struct DPAPConnectionPrivate {
+};
+*/
+
+static DMAPContentCode
+get_protocol_version_cc (DMAPConnection *connection)
+{
+	return DMAP_CC_PPRO;
+}
+
+static gchar *
+get_query_metadata (void)
+{
+	return g_strdup ("all");
+}
+
+static DMAPRecord *
+handle_mlcl (DMAPConnection *connection, DMAPRecordFactory *factory, GNode *n, int *item_id)
+{
+	GNode *n2;
+	DMAPRecord *record = NULL;
+	const gchar *filename = NULL;
+	const gchar *aspect_ratio = NULL;
+	const gchar *format = NULL;
+	const gchar *comments = NULL;
+	const gchar *thumbnail = NULL;
+	const gchar *ptr = NULL;
+	gint creation_date = 0;
+	gint filesize = 0;
+	gint large_filesize = 0;
+	gint height = 0;
+	gint width = 0;
+	gint rating = 0;
+
+	for (n2 = n->children; n2; n2 = n2->next) {
+		DMAPStructureItem *meta_item;
+
+		meta_item = n2->data;
+
+		switch (meta_item->content_code) {
+			case DMAP_CC_MIID:
+				*item_id = g_value_get_int (&(meta_item->content));
+				break;
+			case DMAP_CC_PIMF:
+				filename = g_value_get_string (&(meta_item->content));
+				break;
+			case DMAP_CC_PASP:
+				aspect_ratio = g_value_get_string (&(meta_item->content));
+				break;
+			case DMAP_CC_PICD:
+				creation_date = g_value_get_int (&(meta_item->content));
+				break;
+			case DMAP_CC_PFMT:
+				format = g_value_get_string (&(meta_item->content));
+				break;
+			case DMAP_CC_PIFS:
+				filesize = g_value_get_int (&(meta_item->content));
+				break;
+			case DMAP_CC_PLSZ:
+				large_filesize = g_value_get_int (&(meta_item->content));
+				break;
+			case DMAP_CC_PHGT:
+				height = g_value_get_int (&(meta_item->content));
+				break;
+			case DMAP_CC_PWTH:
+				width = g_value_get_int (&(meta_item->content));
+				break;
+			case DMAP_CC_PRAT:
+				rating = g_value_get_int (&(meta_item->content));
+				break;
+			case DMAP_CC_PCMT:
+				comments = g_value_get_string (&(meta_item->content));
+				break;
+			case DMAP_CC_PFDT:
+				thumbnail = g_value_get_pointer (&(meta_item->content));
+				break;
+			default:
+				break;
+		}
+	}
+
+	record = dmap_record_factory_create (factory, NULL);
+	if (record == NULL) {
+		goto _return;
+	}
+
+	if (filesize) {
+		ptr = g_new (gchar, filesize);
+		memcpy (ptr, thumbnail, filesize);
+	}
+
+	g_object_set (record,
+		     "filename", filename,
+		     "aspect-ratio", aspect_ratio,
+		     "creation-date", creation_date,
+		     "format", format,
+		     "filesize", filesize,
+		     "large-filesize", large_filesize,
+		     "height", height,
+		     "width", width,
+		     "rating", rating,
+		     "comments", comments,
+		     "thumbnail", ptr,
+		      NULL);
+
+_return:
+	return record;
+}
+
+static void
+dpap_connection_class_init (DPAPConnectionClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	DMAPConnectionClass *parent_class = DMAP_CONNECTION_CLASS (object_class);
+
+	parent_class->get_protocol_version_cc = get_protocol_version_cc;
+	parent_class->get_query_metadata = get_query_metadata;
+	parent_class->handle_mlcl = handle_mlcl;
+
+	/* FIXME:
+	g_type_class_add_private (klass, sizeof (DPAPConnectionPrivate));
+	*/
+}
+
+DPAPConnection *
+dpap_connection_new (const char        *name,
+		     const char        *host,
+		     int                port,
+		     gboolean           password_protected,
+		     DMAPDb            *db,
+		     DMAPRecordFactory *factory)
+{
+	DPAPConnection *connection;
+	
+	connection = g_object_new (TYPE_DPAP_CONNECTION,
+			          "name", name,
+			          "password-protected", password_protected,
+			          "db", db,
+			          "host", host,
+			          "port", port,
+				  "factory", factory,
+			           NULL);
+
+	return connection;
+}
+
+static void
+dpap_connection_init (DPAPConnection *connection)
+{
+	/* FIXME: 
+	connection->priv = DPAP_CONNECTION_GET_PRIVATE (connection);
+	*/
+}
+
+G_DEFINE_TYPE (DPAPConnection, dpap_connection, TYPE_DMAP_CONNECTION)
diff --git a/libdmapsharing/dpap-connection.h b/libdmapsharing/dpap-connection.h
new file mode 100644
index 0000000..d5b8ae0
--- /dev/null
+++ b/libdmapsharing/dpap-connection.h
@@ -0,0 +1,96 @@
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __DPAP_CONNECTION_H
+#define __DPAP_CONNECTION_H
+
+#include <glib-object.h>
+
+#include <libdmapsharing/dmap-connection.h>
+#include <libdmapsharing/dmap-db.h>
+
+G_BEGIN_DECLS
+
+/**
+ * TYPE_DPAP_CONNECTION:
+ *
+ * The type for #DPAPConnection.
+ */
+#define TYPE_DPAP_CONNECTION		(dpap_connection_get_type ())
+/**
+ * DPAP_CONNECTION:
+ * @o: Object which is subject to casting.
+ *
+ * Casts a #DPAPConnection or derived pointer into a (DPAPConnection *) pointer.
+ * Depending on the current debugging level, this function may invoke
+ * certain runtime checks to identify invalid casts.
+ */
+#define DPAP_CONNECTION(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), TYPE_DPAP_CONNECTION, DPAPConnection))
+/**
+ * DPAP_CONNECTION_CLASS:
+ * @k: a valid #DPAPConnectionClass
+ *
+ * Casts a derived #DPAPConnectionClass structure into a #DPAPConnectionClass
+ * structure.
+ */
+#define DPAP_CONNECTION_CLASS(k)	(G_TYPE_CHECK_CLASS_CAST((k), TYPE_DPAP_CONNECTION, DPAPConnectionClass))
+/**
+ * IS_DPAP_CONNECTION:
+ * @o: Instance to check for being a %TYPE_DPAP_CONNECTION.
+ *
+ * Checks whether a valid #GTypeInstance pointer is of type %TYPE_DPAP_CONNECTION.
+ */
+#define IS_DPAP_CONNECTION(o)	(G_TYPE_CHECK_INSTANCE_TYPE ((o), TYPE_DPAP_CONNECTION))
+/**
+ * IS_DPAP_CONNECTION_CLASS:
+ * @k: a #DPAPConnectionClass
+ *
+ * Checks whether @k "is a" valid #DPAPConnectionClass structure of type
+ * %DPAP_CONNECTION or derived.
+ */
+#define IS_DPAP_CONNECTION_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), TYPE_DPAP_CONNECTION))
+/**
+ * DPAP_CONNECTION_GET_CLASS:
+ * @o: a #DPAPConnection instance.
+ *
+ * Get the class structure associated to a #DPAPConnection instance.
+ *
+ * Returns: pointer to object class structure.
+ */
+#define DPAP_CONNECTION_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), TYPE_DPAP_CONNECTION, DPAPConnectionClass))
+
+typedef struct DPAPConnectionPrivate DPAPConnectionPrivate;
+
+typedef struct {
+	DMAPConnectionClass dmap_connection_class;
+} DPAPConnectionClass;
+
+typedef struct {
+	DMAPConnection dmap_connection_instance;
+	DPAPConnectionPrivate *priv;
+} DPAPConnection;
+
+GType              dpap_connection_get_type        (void);
+
+DPAPConnection * dpap_connection_new             (const char              *name,
+						  const char              *host,
+						  int                      port,
+						  gboolean                 password_protected,
+						  DMAPDb		  *db,
+						  DMAPRecordFactory *factory);
+G_END_DECLS
+
+#endif /* __DPAP_CONNECTION_H */
diff --git a/tests/Makefile.am b/tests/Makefile.am
index acf0ee5..34d6521 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,4 +1,4 @@
-noinst_PROGRAMS = test-dmap-client test-dmap-server
+noinst_PROGRAMS = test-dmap-client test-dmap-server dpapview
 
 test_dmap_client_SOURCES = \
 	test-dmap-db.c \
@@ -38,6 +38,28 @@ test_dmap_server_LDADD = \
 	$(IMAGEMAGICK_LIBS) \
 	$(MDNS_LIBS)
 
+dpapview_VALASOURCES = \
+	dpapview.vala
+
+dpapview_VALABUILTSOURCES = $(dpapview_VALASOURCES:.vala=.c)
+
+if MAINTAINER_MODE
+PACKAGES = --pkg gee-1.0 --pkg gtk+-2.0 --pkg gstreamer-0.10 --pkg libdmapsharing-2.2 --pkg libsoup-2.4 --pkg glib-2.0
+BUILT_SOURCES = vala.stamp
+
+vala.stamp: $(dpapview_VALASOURCES)
+	$(VALAC) --vapidir=$(srcdir) $(PACKAGES) $^ -C
+	touch $@
+endif
+
+dpapview_SOURCES = \
+	$(dpapview_VALABUILTSOURCES)
+
+dpapview_LDADD = \
+	$(top_builddir)/libdmapsharing/libdmapsharing.la \
+	$(GTK_LIBS) \
+	$(GEE_LIBS)
+
 AM_CPPFLAGS = \
 	-I$(top_srcdir) \
 	$(GLIB_CFLAGS) \
@@ -48,7 +70,9 @@ AM_CPPFLAGS = \
 	$(MDNS_CFLAGS)
 
 INCLUDES = \
-	$(IMAGEMAGICK_CFLAGS)
+	$(IMAGEMAGICK_CFLAGS) \
+	$(GTK_CFLAGS) \
+	$(GEE_CFLAGS)
 
 noinst_HEADERS = \
 	test-dmap-container-record.h \
@@ -58,3 +82,14 @@ noinst_HEADERS = \
 	test-daap-record-factory.h \
 	test-dpap-record.h \
 	test-dpap-record-factory.h
+
+EXTRA_DIST = \
+	$(dpapview_VALASOURCES) \
+	$(dpapview_VALABUILTSOURCES)
+
+if MAINTAINER_MODE
+CLEANFILES = \
+	$(BUILT_SOURCES) \
+	$(dpapview_VALABUILTSOURCES)
+endif
+
diff --git a/tests/dpapview.ui b/tests/dpapview.ui
new file mode 100644
index 0000000..0805e4e
--- /dev/null
+++ b/tests/dpapview.ui
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <requires lib="gtk+" version="2.20"/>
+  <!-- interface-naming-policy project-wide -->
+  <object class="GtkWindow" id="window">
+    <signal name="destroy" handler="gtk_main_quit" swapped="no"/>
+    <child>
+      <object class="GtkScrolledWindow" id="scrolledwindow">
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="hscrollbar_policy">automatic</property>
+        <property name="vscrollbar_policy">automatic</property>
+        <child>
+          <object class="GtkIconView" id="iconview">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="model">liststore</property>
+          </object>
+        </child>
+      </object>
+    </child>
+  </object>
+  <object class="GtkListStore" id="liststore">
+    <columns>
+      <!-- column-name gdkpixbuf -->
+      <column type="GdkPixbuf"/>
+      <!-- column-name gchararray -->
+      <column type="gchararray"/>
+    </columns>
+  </object>
+</interface>
diff --git a/tests/dpapview.vala b/tests/dpapview.vala
new file mode 100644
index 0000000..5695ec5
--- /dev/null
+++ b/tests/dpapview.vala
@@ -0,0 +1,226 @@
+/*   FILE: dpapviewer.vala -- View DPAP data
+ * AUTHOR: W. Michael Petullo <mike flyn org>
+ *   DATE: 24 November 2010
+ *
+ * Copyright (c) 2010 W. Michael Petullo <new flyn org>
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+private class ViewerDMAPDb : GLib.Object, DMAP.Db {
+	// A dumb database that stores everything in an array
+
+	private Gee.ArrayList<ViewerDPAPRecord> db = new Gee.ArrayList<ViewerDPAPRecord> ();
+
+	public uint add (DMAP.Record record) {
+		db.add (((ViewerDPAPRecord) record));
+		return db.size;
+	}
+
+	public uint add_path (string path) {
+		GLib.error ("add_path not implemented");
+	}
+
+	public uint add_with_id (DMAP.Record record, uint id) {
+		GLib.error ("add_with_id not implemented");
+	}
+
+	public int64 count () {
+		return db.size;
+	}
+
+	public void @foreach (GLib.HFunc func) {
+		int i;
+		for (i = 0; i < db.size; i++) {
+			func (i.to_pointer (), db[i]);
+		}
+	}
+
+	public unowned DMAP.Record lookup_by_id (uint id) {
+		GLib.error ("lookup_by_id not implemented");
+	}
+
+
+	public uint lookup_id_by_location (string location){
+		GLib.error ("lookup_id_by_location not implemented");
+	}
+}
+
+private class ViewerDPAPRecordFactory : GLib.Object, DMAP.RecordFactory {
+	public DMAP.Record create (void* user_data) {
+		return new ViewerDPAPRecord ();
+	}
+}
+
+private class ViewerDPAPRecord : GLib.Object, DMAP.Record, DPAP.Record {
+	private string _location;
+	private string _filename;
+	private string _aspect_ratio;
+	private string _format;
+	private string _comments;
+	private uchar *_thumbnail;
+	private int _filesize;
+	private int _large_filesize;
+	private int _height;
+	private int _width;
+	private int _rating;
+	private int _creation_date;
+
+	public string location {
+		get { return _location; }
+		set { _location = value; }
+	}
+
+	public string filename {
+		get { return _filename; }
+		set { _filename = value; }
+	}
+
+	public string aspect_ratio {
+		get { return _aspect_ratio; }
+		set { _aspect_ratio = value; }
+	}
+
+	public string format {
+		get { return _format; }
+		set { _format = value; }
+	}
+
+	public uchar *thumbnail {
+		get { return _thumbnail; }
+		set { _thumbnail = value; }
+	}
+
+	public string comments {
+		get { return _comments; }
+		set { _comments = value; }
+	}
+
+	public int filesize {
+		get { return _filesize; }
+		set { _filesize = value; }
+	}
+
+	public int large_filesize {
+		get { return _large_filesize; }
+		set { _large_filesize = value; }
+	}
+
+	public int height {
+		get { return _height; }
+		set { _height = value; }
+	}
+
+	public int width {
+		get { return _width; }
+		set { _width = value; }
+	}
+
+	public int rating {
+		get { return _rating; }
+		set { _rating = value; }
+	}
+
+	public int creation_date {
+		get { return _creation_date; }
+		set { _creation_date = value; }
+	}
+
+	public unowned GLib.InputStream read (DPAP.Record record) throws GLib.Error {
+		GLib.error ("read not implemented");
+	}
+
+	public unowned DMAP.Record set_from_blob (GLib.ByteArray blob) {
+		GLib.error ("set_from_blob not implemented");
+	}
+
+	public unowned GLib.ByteArray to_blob () {
+		GLib.error ("to_blob not implemented");
+	}
+}
+
+private class DPAPViewer {
+	private DMAP.MdnsBrowser browser;
+	private DMAP.Connection connection;
+	private Gtk.ListStore liststore;
+	private ViewerDMAPDb db;
+	private ViewerDPAPRecordFactory factory;
+
+	private bool connected_cb (DMAP.Connection connection, bool result, string? reason) {
+		GLib.debug ("%lld entries\n", db.count ());
+
+		db.foreach ((k, v) => {
+			string path;
+			int fd = GLib.FileUtils.open_tmp ("dpapview.XXXXXX", out path);
+			GLib.FileUtils.set_contents (path, (string) ((ViewerDPAPRecord) v).thumbnail, ((ViewerDPAPRecord) v).filesize);
+			var pixbuf = new Gdk.Pixbuf.from_file (path);
+			GLib.FileUtils.close (fd);
+			GLib.FileUtils.unlink (path);
+
+			Gtk.TreeIter iter;
+			liststore.append (out iter);
+			liststore.set (iter, 0, pixbuf, 1, ((ViewerDPAPRecord) v).filename);
+		});
+
+		return true;
+	}
+
+	private void service_added_cb (void *service) {
+		/* FIXME: fix void * argument, see libdmapsharing TODO: */
+		DMAP.MdnsBrowserService *FIXME = service;
+		/* FIXME: fix int cast: should not be requried: */
+		connection = new DPAP.Connection (FIXME->service_name, FIXME->host, (int) FIXME->port, false, db, factory);
+		connection.connect (connected_cb);
+	}
+
+	public DPAPViewer (Gtk.Builder builder) throws GLib.Error {
+		builder.connect_signals (this);
+
+		Gtk.Widget widget = builder.get_object ("window") as Gtk.Widget;
+		Gtk.IconView iconview = builder.get_object ("iconview") as Gtk.IconView;
+		liststore = builder.get_object ("liststore") as Gtk.ListStore;
+		db = new ViewerDMAPDb ();
+		factory = new ViewerDPAPRecordFactory ();
+
+		iconview.set_pixbuf_column (0);
+		iconview.set_text_column (1);
+
+		widget.show_all ();
+
+		browser = new DMAP.MdnsBrowser (DMAP.MdnsBrowserServiceType.DPAP);
+		browser.service_added.connect (service_added_cb);
+		browser.start ();
+	}
+}
+
+int main (string[] args) {     
+	Gtk.init (ref args);
+
+	try {
+		var builder = new Gtk.Builder ();
+		builder.add_from_file ("dpapview.ui");
+
+		var dpapviewer = new DPAPViewer (builder);
+
+		Gtk.main ();
+
+	} catch (GLib.Error e) {
+		stderr.printf ("Error: %s\n", e.message);
+		return 1;
+	} 
+
+	return 0;
+}
diff --git a/tests/test-daap-record.c b/tests/test-daap-record.c
index 01fc448..6111933 100644
--- a/tests/test-daap-record.c
+++ b/tests/test-daap-record.c
@@ -259,9 +259,9 @@ test_daap_record_class_init (TestDAAPRecordClass *klass)
 static void
 test_daap_record_daap_iface_init (gpointer iface, gpointer data)
 {
-	DAAPRecordInterface *daap_record = iface;
+	DAAPRecordIface *daap_record = iface;
 
-	g_assert (G_TYPE_FROM_INTERFACE (daap_record) == TYPE_DAAP_RECORD);
+	g_assert (G_TYPE_FROM_INTERFACE (daap_record) == DAAP_TYPE_RECORD);
 
 	daap_record->read = test_daap_record_read;
 }
@@ -275,7 +275,7 @@ test_daap_record_dmap_iface_init (gpointer iface, gpointer data)
 }
 
 G_DEFINE_TYPE_WITH_CODE (TestDAAPRecord, test_daap_record, G_TYPE_OBJECT, 
-			G_IMPLEMENT_INTERFACE (TYPE_DAAP_RECORD, test_daap_record_daap_iface_init)
+			G_IMPLEMENT_INTERFACE (DAAP_TYPE_RECORD, test_daap_record_daap_iface_init)
 			G_IMPLEMENT_INTERFACE (DMAP_TYPE_RECORD, test_daap_record_dmap_iface_init))
 
 static void
diff --git a/tests/test-dmap-client.c b/tests/test-dmap-client.c
index 1d33086..aa07e8f 100644
--- a/tests/test-dmap-client.c
+++ b/tests/test-dmap-client.c
@@ -87,13 +87,13 @@ service_added_cb (DMAPMdnsBrowser *browser,
         if (factory == NULL) {
    	    g_error ("Error creating record factory");
         }
-        conn = DMAP_CONNECTION (dmap_connection_new (service->name, service->host, service->port, FALSE, db, factory));
+        conn = DMAP_CONNECTION (daap_connection_new (service->name, service->host, service->port, FALSE, db, factory));
     } else {
         factory = DMAP_RECORD_FACTORY (test_dpap_record_factory_new ());
         if (factory == NULL) {
    	    g_error ("Error creating record factory");
         }
-        conn = DMAP_CONNECTION (dmap_connection_new (service->name, service->host, service->port, FALSE, db, factory));
+        conn = DMAP_CONNECTION (dpap_connection_new (service->name, service->host, service->port, FALSE, db, factory));
     }
     dmap_connection_connect (DMAP_CONNECTION (conn), (DMAPConnectionCallback) connected_cb, db);
 }



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