--- /dev/null
+diff -ruP src/ao.h libshairport.new/src/ao.h
+--- src/ao.h 2012-05-07 22:26:53.000000000 +0200
++++ src/ao.h 2012-05-08 18:46:42.000000000 +0200
+@@ -152,5 +152,7 @@
+ /* -- Device Setup/Playback/Teardown -- */
+ int (*ao_append_option)(ao_option **, const char *, const char *);
+ void (*ao_free_options)(ao_option *);
+- char* (*ao_get_option)(ao_option *, const char* );
++ char* (*ao_get_option)(ao_option *, const char* );
++ void (*ao_set_metadata)(const char *buffer, unsigned int size);
++ void (*ao_set_metadata_coverart)(const char *buffer, unsigned int size);
+ };
+diff -ruP src/hairtunes.c src/hairtunes.c
+--- src/hairtunes.c 2012-05-07 22:26:53.000000000 +0200
++++ src/hairtunes.c 2012-05-08 18:45:51.000000000 +0200
+@@ -267,6 +267,16 @@
+ fix_volume = 65536.0 * volume;
+ }
+
++void hairtunes_set_metadata(const char *buffer, unsigned int size)
++{
++ g_ao.ao_set_metadata(buffer, size);
++}
++
++void hairtunes_set_metadata_coverart(const char *buffer, unsigned int size)
++{
++ g_ao.ao_set_metadata_coverart(buffer, size);
++}
++
+ void hairtunes_flush(void)
+ {
+ pthread_mutex_lock(&ab_mutex);
+diff -ruP src/hairtunes.h src/hairtunes.h
+--- src/hairtunes.h 2011-08-21 00:06:21.000000000 +0200
++++ src/hairtunes.h 2012-05-08 18:46:00.000000000 +0200
+@@ -4,6 +4,8 @@
+ int hairtunes_init(char *pAeskey, char *pAesiv, char *pFmtpstr, int pCtrlPort, int pTimingPort,
+ int pDataPort, char *pRtpHost, char*pPipeName, char *pLibaoDriver, char *pLibaoDeviceName, char *pLibaoDeviceId);
+ void hairtunes_setvolume(float vol);
++void hairtunes_set_metadata(const char *buffer, unsigned int size);
++void hairtunes_set_metadata_coverart(const char *buffer, unsigned int size);
+ void hairtunes_flush(void);
+ void hairtunes_cleanup(void);
+
+diff -ruP src/shairport.c src/shairport.c
+--- src/shairport.c 2012-05-07 22:26:53.000000000 +0200
++++ src/shairport.c 2012-05-08 18:45:30.000000000 +0200
+@@ -513,7 +513,8 @@
+ while(1 == tMoreDataNeeded)
+ {
+ tError = readDataFromClient(pSock, &(tConn.recv));
+- if(!tError && strlen(tConn.recv.data) > 0)
++ //if(!tError && strlen(tConn.recv.data) > 0)
++ if(!tError && tConn.recv.current > 0)
+ {
+ xprintf("Finished Reading some data from client\n");
+ // parse client request
+@@ -632,7 +633,7 @@
+ }
+
+ tSize = (int) (tShortest - tFound);
+- xprintf("Found %.*s length: %d\n", tSize, tFound, tSize);
++ xprintf("Found %s length: %d\n",tFound, tSize);
+ if(pReturnSize != NULL)
+ {
+ *pReturnSize = tSize;
+@@ -744,7 +745,7 @@
+ if(tContent != NULL)
+ {
+ int tContentSize = atoi(tContent);
+- if(pConn->recv.marker == 0 || strlen(pConn->recv.data+pConn->recv.marker) != tContentSize)
++ if(pConn->recv.marker == 0 || pConn->recv.current-pConn->recv.marker != tContentSize)
+ {
+ if(isLogEnabledFor(HEADER_LOG_LEVEL))
+ {
+@@ -752,7 +753,7 @@
+ if(pConn->recv.marker != 0)
+ {
+ xprintf("ContentPtr has %d, but needs %d\n",
+- strlen(pConn->recv.data+pConn->recv.marker), tContentSize);
++ (pConn->recv.current-pConn->recv.marker), tContentSize);
+ }
+ }
+ // check if value in tContent > 2nd read from client.
+@@ -989,15 +990,67 @@
+ {
+ propogateCSeq(pConn);
+ int tSize = 0;
++ char *buffer = NULL;
++ char *contentType = getFromHeader(pConn->recv.data, "Content-Type", &tSize);
++ char *tContent = getFromHeader(pConn->recv.data, "Content-Length", NULL);
++ int iContentSize = 0;
++ int isJpg = 0;
++
++ if(tContent != NULL)
++ {
++ iContentSize = atoi(tContent);
++ }
++
++ if( tSize > 1 &&
++ (strncmp(contentType, "application/x-dmap-tagged", tSize) == 0) ||
++ (strncmp(contentType, "image/jpeg", tSize) == 0) )
++ {
++ if( (pConn->recv.current - pConn->recv.marker) == iContentSize && pConn->recv.marker != 0)
++ {
++ if(strncmp(contentType, "image/jpeg", tSize) == 0)
++ {
++ isJpg = 1;
++ }
++ buffer = (char *)malloc(iContentSize * sizeof(char));
++ memcpy(buffer, pConn->recv.data + pConn->recv.marker, iContentSize);
++ }
++ else
++ {
++ iContentSize = 0;
++ }
++ }
++ else
++ {
++ iContentSize = 0;
++ }
+ char *tVol = getFromHeader(pConn->recv.data, "volume", &tSize);
+- xprintf("About to write [vol: %.*s] data to hairtunes\n", tSize, tVol);
++ if( tVol)
++ {
++ xprintf("About to write [vol: %.*s] data to hairtunes\n", tSize, tVol);
++ }
+ // TBD VOLUME
+ #ifndef XBMC
+ write(pConn->hairtunes->in[1], "vol: ", 5);
+ write(pConn->hairtunes->in[1], tVol, tSize);
+ write(pConn->hairtunes->in[1], "\n", 1);
+ #else
+- hairtunes_setvolume(atof(tVol));
++ if(tVol)
++ {
++ hairtunes_setvolume(atof(tVol));
++ }
++
++ if(iContentSize)
++ {
++ if(isJpg)
++ {
++ hairtunes_set_metadata_coverart(buffer, iContentSize);
++ }
++ else
++ {
++ hairtunes_set_metadata(buffer, iContentSize);
++ }
++ free(buffer);
++ }
+ #endif
+ xprintf("Finished writing data write data to hairtunes\n");
+ }