Skip to content

Commit

Permalink
Generalise the DIDL parser
Browse files Browse the repository at this point in the history
  • Loading branch information
rossburton committed Nov 8, 2010
1 parent 050281f commit 3c45a0c
Showing 1 changed file with 66 additions and 23 deletions.
89 changes: 66 additions & 23 deletions tracknotify.c
Expand Up @@ -2,20 +2,49 @@
#include <libgupnp/gupnp-control-point.h>
#include <libnotify/notify.h>
#include <string.h>
#include <time.h>

typedef struct {
char *class;
char *title;
char *artist;
} DIDL;

static void
scrob (DIDL *didl)
{
char *command;
int res;

command = g_strdup_printf ("dbus-send --print-reply --dest=com.burtonini.Scrobbler "
"/com/burtonini/Scrobbler "
"com.burtonini.Scrobbler.Submit "
"uint32:%ld " /* timestamp */
"string:\"%s\" " /* artist */
"string:\"%s\" " /* title */
"uint32:0 " /* track number */
"uint32:0 " /* length */
"string: " /* album */
"string: " /* musicbrainz ID */
"string:P", /* type */
time (NULL), didl->artist, didl->title);
res = system (command);
g_free (command);
}

static void
notify (const char *title, const char *artist)
notify (DIDL *didl)
{
GError *error = NULL;
NotifyNotification *notify;
char *message;

if (title && artist)
message = g_markup_printf_escaped ("Playing %s by %s", title, artist);
else if (title && !artist)
message = g_markup_printf_escaped ("Playing %s", title);
else if (!title && artist)
message = g_markup_printf_escaped ("Playing %s", artist);
if (didl->title && didl->artist)
message = g_markup_printf_escaped ("Playing %s by %s", didl->title, didl->artist);
else if (didl->title && !didl->artist)
message = g_markup_printf_escaped ("Playing %s", didl->title);
else if (!didl->title && didl->artist)
message = g_markup_printf_escaped ("Playing %s", didl->artist);
else
return;

Expand All @@ -36,37 +65,51 @@ notify (const char *title, const char *artist)
g_free (message);
}

static const struct {
const char *node;
int offset;
} map[] = {
{ "upnp:class", G_STRUCT_OFFSET (DIDL, class) },
{ "dc:title", G_STRUCT_OFFSET (DIDL, title) },
{ "upnp:artist", G_STRUCT_OFFSET (DIDL, artist) },
};

static void
parse_meta (const xmlChar *xml)
{
DIDL didl = { NULL, NULL, NULL };
xmlTextReader *reader;
int res;
char *title = NULL, *artist = NULL;
int i, res;

reader = xmlReaderForDoc (xml, NULL, NULL, 0);

while ((res = xmlTextReaderRead (reader)) == 1) {
if (xmlTextReaderNodeType (reader) == XML_READER_TYPE_ELEMENT &&
xmlStrcmp (xmlTextReaderConstName (reader), (xmlChar*)"dc:title") == 0) {
xmlTextReaderRead (reader);
title = (char*)xmlTextReaderValue (reader);
const xmlChar *tagname;

if (xmlTextReaderNodeType (reader) != XML_READER_TYPE_ELEMENT)
continue;
}

if (xmlTextReaderNodeType (reader) == XML_READER_TYPE_ELEMENT &&
xmlStrcmp (xmlTextReaderConstName (reader), (xmlChar*)"upnp:artist") == 0) {
tagname = xmlTextReaderConstName (reader);

for (i = 0; i < G_N_ELEMENTS (map); i++) {
if (xmlStrcmp (tagname, (xmlChar*)map[i].node) != 0)
continue;

xmlTextReaderRead (reader);
artist = (char*)xmlTextReaderValue (reader);
continue;

G_STRUCT_MEMBER (xmlChar*, &didl, map[i].offset) = xmlTextReaderValue (reader);
}
}
xmlFreeTextReader (reader);

if (title || artist)
notify (title, artist);
if (didl.title || didl.artist) {
notify (&didl);
scrob (&didl);
}

xmlFreeTextReader (reader);
g_free (title);
g_free (artist);
g_free (didl.class);
g_free (didl.title);
g_free (didl.artist);
}

static void
Expand Down

0 comments on commit 3c45a0c

Please sign in to comment.