2
* Header for DAAP (iTunes Music Sharing) structures
4
* Copyright (C) 2004,2005 Charles Schmidt <cschmidt2@emich.edu>
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
#include <glib-object.h>
24
#include <gobject/gvaluecollector.h>
25
#include "rb-daap-structure.h"
28
#include <gst/gstutils.h>
33
#define MAKE_CONTENT_CODE(ch0, ch1, ch2, ch3) \
34
(( (gint32)(gchar)(ch0) | ( (gint32)(gchar)(ch1) << 8 ) | \
35
( (gint32)(gchar)(ch2) << 16 ) | \
36
( (gint32)(gchar)(ch3) << 24 ) ))
38
static const RBDAAPContentCodeDefinition cc_defs[] = {
39
{RB_DAAP_CC_MDCL, MAKE_CONTENT_CODE('m','d','c','l'), "dmap.dictionary", "mdcl", RB_DAAP_TYPE_CONTAINER},
40
{RB_DAAP_CC_MSTT, MAKE_CONTENT_CODE('m','s','t','t'), "dmap.status", "mstt", RB_DAAP_TYPE_INT},
41
{RB_DAAP_CC_MIID, MAKE_CONTENT_CODE('m','i','i','d'), "dmap.itemid", "miid", RB_DAAP_TYPE_INT},
42
{RB_DAAP_CC_MINM, MAKE_CONTENT_CODE('m','i','n','m'), "dmap.itemname", "minm", RB_DAAP_TYPE_STRING},
43
{RB_DAAP_CC_MIKD, MAKE_CONTENT_CODE('m','i','k','d'), "dmap.itemkind", "mikd", RB_DAAP_TYPE_BYTE},
44
{RB_DAAP_CC_MPER, MAKE_CONTENT_CODE('m','p','e','r'), "dmap.persistentid", "mper", RB_DAAP_TYPE_INT64},
45
{RB_DAAP_CC_MCON, MAKE_CONTENT_CODE('m','c','o','n'), "dmap.container", "mcon", RB_DAAP_TYPE_CONTAINER},
46
{RB_DAAP_CC_MCTI, MAKE_CONTENT_CODE('m','c','t','i'), "dmap.containeritemid", "mcti", RB_DAAP_TYPE_INT},
47
{RB_DAAP_CC_MPCO, MAKE_CONTENT_CODE('m','p','c','o'), "dmap.parentcontainerid", "mpco", RB_DAAP_TYPE_INT},
48
{RB_DAAP_CC_MSTS, MAKE_CONTENT_CODE('m','s','t','s'), "dmap.statusstring", "msts", RB_DAAP_TYPE_STRING},
49
{RB_DAAP_CC_MIMC, MAKE_CONTENT_CODE('m','i','m','c'), "dmap.itemcount", "mimc", RB_DAAP_TYPE_INT},
50
{RB_DAAP_CC_MCTC, MAKE_CONTENT_CODE('m','c','t','c'), "dmap.containercount", "mctc", RB_DAAP_TYPE_INT},
51
{RB_DAAP_CC_MRCO, MAKE_CONTENT_CODE('m','r','c','o'), "dmap.returnedcount", "mrco", RB_DAAP_TYPE_INT},
52
{RB_DAAP_CC_MTCO, MAKE_CONTENT_CODE('m','t','c','o'), "dmap.specifiedtotalcount", "mtco", RB_DAAP_TYPE_INT},
53
{RB_DAAP_CC_MLCL, MAKE_CONTENT_CODE('m','l','c','l'), "dmap.listing", "mlcl", RB_DAAP_TYPE_CONTAINER},
54
{RB_DAAP_CC_MLIT, MAKE_CONTENT_CODE('m','l','i','t'), "dmap.listingitem", "mlit", RB_DAAP_TYPE_CONTAINER},
55
{RB_DAAP_CC_MBCL, MAKE_CONTENT_CODE('m','b','c','l'), "dmap.bag", "mbcl", RB_DAAP_TYPE_CONTAINER},
56
{RB_DAAP_CC_MSRV, MAKE_CONTENT_CODE('m','s','r','v'), "dmap.serverinforesponse", "msrv", RB_DAAP_TYPE_CONTAINER},
57
{RB_DAAP_CC_MSAU, MAKE_CONTENT_CODE('m','s','a','u'), "dmap.authenticationmethod", "msau", RB_DAAP_TYPE_BYTE},
58
{RB_DAAP_CC_MSLR, MAKE_CONTENT_CODE('m','s','l','r'), "dmap.loginrequired", "mslr", RB_DAAP_TYPE_BYTE},
59
{RB_DAAP_CC_MPRO, MAKE_CONTENT_CODE('m','p','r','o'), "dmap.protocolversion", "mpro", RB_DAAP_TYPE_VERSION},
60
{RB_DAAP_CC_APRO, MAKE_CONTENT_CODE('a','p','r','o'), "daap.protocolversion", "apro", RB_DAAP_TYPE_VERSION},
61
{RB_DAAP_CC_MSAL, MAKE_CONTENT_CODE('m','s','a','l'), "dmap.supportsautologout", "msal", RB_DAAP_TYPE_BYTE},
62
{RB_DAAP_CC_MSUP, MAKE_CONTENT_CODE('m','s','u','p'), "dmap.supportsupdate", "msup", RB_DAAP_TYPE_BYTE},
63
{RB_DAAP_CC_MSPI, MAKE_CONTENT_CODE('m','s','p','i'), "dmap.supportspersistenids", "mspi", RB_DAAP_TYPE_BYTE},
64
{RB_DAAP_CC_MSEX, MAKE_CONTENT_CODE('m','s','e','x'), "dmap.supportsextensions", "msex", RB_DAAP_TYPE_BYTE},
65
{RB_DAAP_CC_MSBR, MAKE_CONTENT_CODE('m','s','b','r'), "dmap.supportsbrowse", "msbr", RB_DAAP_TYPE_BYTE},
66
{RB_DAAP_CC_MSQY, MAKE_CONTENT_CODE('m','s','q','y'), "dmap.supportsquery", "msqy", RB_DAAP_TYPE_BYTE},
67
{RB_DAAP_CC_MSIX, MAKE_CONTENT_CODE('m','s','i','x'), "dmap.supportsindex", "msix", RB_DAAP_TYPE_BYTE},
68
{RB_DAAP_CC_MSRS, MAKE_CONTENT_CODE('m','s','r','s'), "dmap.supportsresolve", "msrs", RB_DAAP_TYPE_BYTE},
69
{RB_DAAP_CC_MSTM, MAKE_CONTENT_CODE('m','s','t','m'), "dmap.timeoutinterval", "mstm", RB_DAAP_TYPE_INT},
70
{RB_DAAP_CC_MSDC, MAKE_CONTENT_CODE('m','s','d','c'), "dmap.databasescount", "msdc", RB_DAAP_TYPE_INT},
71
{RB_DAAP_CC_MCCR, MAKE_CONTENT_CODE('m','c','c','r'), "dmap.contentcodesresponse", "mccr", RB_DAAP_TYPE_CONTAINER},
72
{RB_DAAP_CC_MCNM, MAKE_CONTENT_CODE('m','c','n','m'), "dmap.contentcodesnumber", "mcnm", RB_DAAP_TYPE_INT},
73
{RB_DAAP_CC_MCNA, MAKE_CONTENT_CODE('m','c','n','a'), "dmap.contentcodesname", "mcna", RB_DAAP_TYPE_STRING},
74
{RB_DAAP_CC_MCTY, MAKE_CONTENT_CODE('m','c','t','y'), "dmap.contentcodestype", "mcty", RB_DAAP_TYPE_SHORT},
75
{RB_DAAP_CC_MLOG, MAKE_CONTENT_CODE('m','l','o','g'), "dmap.loginresponse", "mlog", RB_DAAP_TYPE_CONTAINER},
76
{RB_DAAP_CC_MLID, MAKE_CONTENT_CODE('m','l','i','d'), "dmap.sessionid", "mlid", RB_DAAP_TYPE_INT},
77
{RB_DAAP_CC_MUPD, MAKE_CONTENT_CODE('m','u','p','d'), "dmap.updateresponse", "mupd", RB_DAAP_TYPE_CONTAINER},
78
{RB_DAAP_CC_MUSR, MAKE_CONTENT_CODE('m','u','s','r'), "dmap.serverrevision", "musr", RB_DAAP_TYPE_INT},
79
{RB_DAAP_CC_MUTY, MAKE_CONTENT_CODE('m','u','t','y'), "dmap.updatetype", "muty", RB_DAAP_TYPE_BYTE},
80
{RB_DAAP_CC_MUDL, MAKE_CONTENT_CODE('m','u','d','l'), "dmap.deletedidlisting", "mudl", RB_DAAP_TYPE_CONTAINER},
81
{RB_DAAP_CC_AVDB, MAKE_CONTENT_CODE('a','v','d','b'), "daap.serverdatabases", "avdb", RB_DAAP_TYPE_CONTAINER},
82
{RB_DAAP_CC_ABRO, MAKE_CONTENT_CODE('a','b','r','o'), "daap.databasebrowse", "abro", RB_DAAP_TYPE_CONTAINER},
83
{RB_DAAP_CC_ABAL, MAKE_CONTENT_CODE('a','b','a','l'), "daap.browsealbumlisting", "abal", RB_DAAP_TYPE_CONTAINER},
84
{RB_DAAP_CC_ABAR, MAKE_CONTENT_CODE('a','b','a','r'), "daap.browseartistlisting", "abar", RB_DAAP_TYPE_CONTAINER},
85
{RB_DAAP_CC_ABCP, MAKE_CONTENT_CODE('a','b','c','p'), "daap.browsecomposerlisting", "abcp", RB_DAAP_TYPE_CONTAINER},
86
{RB_DAAP_CC_ABGN, MAKE_CONTENT_CODE('a','b','g','n'), "daap.browsegenrelisting", "abgn", RB_DAAP_TYPE_CONTAINER},
87
{RB_DAAP_CC_ADBS, MAKE_CONTENT_CODE('a','d','b','s'), "daap.returndatabasesongs", "adbs", RB_DAAP_TYPE_CONTAINER},
88
{RB_DAAP_CC_ASAL, MAKE_CONTENT_CODE('a','s','a','l'), "daap.songalbum", "asal", RB_DAAP_TYPE_STRING},
89
{RB_DAAP_CC_ASAR, MAKE_CONTENT_CODE('a','s','a','r'), "daap.songartist", "asar", RB_DAAP_TYPE_STRING},
90
{RB_DAAP_CC_ASBT, MAKE_CONTENT_CODE('a','s','b','t'), "daap.songsbeatsperminute", "asbt", RB_DAAP_TYPE_SHORT},
91
{RB_DAAP_CC_ASBR, MAKE_CONTENT_CODE('a','s','b','r'), "daap.songbitrate", "asbr", RB_DAAP_TYPE_SHORT},
92
{RB_DAAP_CC_ASCM, MAKE_CONTENT_CODE('a','s','c','m'), "daap.songcomment", "ascm", RB_DAAP_TYPE_STRING},
93
{RB_DAAP_CC_ASCO, MAKE_CONTENT_CODE('a','s','c','o'), "daap.songcompliation", "asco", RB_DAAP_TYPE_BYTE},
94
{RB_DAAP_CC_ASDA, MAKE_CONTENT_CODE('a','s','d','a'), "daap.songdateadded", "asda", RB_DAAP_TYPE_DATE},
95
{RB_DAAP_CC_ASDM, MAKE_CONTENT_CODE('a','s','d','m'), "daap.songdatemodified", "asdm", RB_DAAP_TYPE_DATE},
96
{RB_DAAP_CC_ASDC, MAKE_CONTENT_CODE('a','s','d','c'), "daap.songdisccount", "asdc", RB_DAAP_TYPE_SHORT},
97
{RB_DAAP_CC_ASDN, MAKE_CONTENT_CODE('a','s','d','n'), "daap.songdiscnumber", "asdn", RB_DAAP_TYPE_SHORT},
98
{RB_DAAP_CC_ASDB, MAKE_CONTENT_CODE('a','s','d','b'), "daap.songdisabled", "asdb", RB_DAAP_TYPE_BYTE},
99
{RB_DAAP_CC_ASEQ, MAKE_CONTENT_CODE('a','s','e','q'), "daap.songeqpreset", "aseq", RB_DAAP_TYPE_STRING},
100
{RB_DAAP_CC_ASFM, MAKE_CONTENT_CODE('a','s','f','m'), "daap.songformat", "asfm", RB_DAAP_TYPE_STRING},
101
{RB_DAAP_CC_ASGN, MAKE_CONTENT_CODE('a','s','g','n'), "daap.songgenre", "asgn", RB_DAAP_TYPE_STRING},
102
{RB_DAAP_CC_ASDT, MAKE_CONTENT_CODE('a','s','d','t'), "daap.songdescription", "asdt", RB_DAAP_TYPE_STRING},
103
{RB_DAAP_CC_ASRV, MAKE_CONTENT_CODE('a','s','r','v'), "daap.songrelativevolume", "asrv", RB_DAAP_TYPE_SIGNED_INT},
104
{RB_DAAP_CC_ASSR, MAKE_CONTENT_CODE('a','s','s','r'), "daap.songsamplerate", "assr", RB_DAAP_TYPE_INT},
105
{RB_DAAP_CC_ASSZ, MAKE_CONTENT_CODE('a','s','s','z'), "daap.songsize", "assz", RB_DAAP_TYPE_INT},
106
{RB_DAAP_CC_ASST, MAKE_CONTENT_CODE('a','s','s','t'), "daap.songstarttime", "asst", RB_DAAP_TYPE_INT},
107
{RB_DAAP_CC_ASSP, MAKE_CONTENT_CODE('a','s','s','p'), "daap.songstoptime", "assp", RB_DAAP_TYPE_INT},
108
{RB_DAAP_CC_ASTM, MAKE_CONTENT_CODE('a','s','t','m'), "daap.songtime", "astm", RB_DAAP_TYPE_INT},
109
{RB_DAAP_CC_ASTC, MAKE_CONTENT_CODE('a','s','t','c'), "daap.songtrackcount", "astc", RB_DAAP_TYPE_SHORT},
110
{RB_DAAP_CC_ASTN, MAKE_CONTENT_CODE('a','s','t','n'), "daap.songtracknumber", "astn", RB_DAAP_TYPE_SHORT},
111
{RB_DAAP_CC_ASUR, MAKE_CONTENT_CODE('a','s','u','r'), "daap.songuserrating", "asur", RB_DAAP_TYPE_BYTE},
112
{RB_DAAP_CC_ASYR, MAKE_CONTENT_CODE('a','s','y','r'), "daap.songyear", "asyr", RB_DAAP_TYPE_SHORT},
113
{RB_DAAP_CC_ASDK, MAKE_CONTENT_CODE('a','s','d','k'), "daap.songdatakind", "asdk", RB_DAAP_TYPE_BYTE},
114
{RB_DAAP_CC_ASUL, MAKE_CONTENT_CODE('a','s','u','l'), "daap.songdataurl", "asul", RB_DAAP_TYPE_STRING},
115
{RB_DAAP_CC_APLY, MAKE_CONTENT_CODE('a','p','l','y'), "daap.databaseplaylists", "aply", RB_DAAP_TYPE_CONTAINER},
116
{RB_DAAP_CC_ABPL, MAKE_CONTENT_CODE('a','b','p','l'), "daap.baseplaylist", "abpl", RB_DAAP_TYPE_BYTE},
117
{RB_DAAP_CC_APSO, MAKE_CONTENT_CODE('a','p','s','o'), "daap.playlistsongs", "apso", RB_DAAP_TYPE_CONTAINER},
118
{RB_DAAP_CC_PRSV, MAKE_CONTENT_CODE('p','r','s','v'), "daap.resolve", "prsv", RB_DAAP_TYPE_CONTAINER},
119
{RB_DAAP_CC_ARIF, MAKE_CONTENT_CODE('a','r','i','f'), "daap.resolveinfo", "arif", RB_DAAP_TYPE_CONTAINER},
120
{RB_DAAP_CC_AESV, MAKE_CONTENT_CODE('a','e','S','V'), "com.applie.itunes.music-sharing-version", "aesv", RB_DAAP_TYPE_INT},
121
{RB_DAAP_CC_MSAS, MAKE_CONTENT_CODE('m','s','a','s'), "daap.authentication.schemes", "msas", RB_DAAP_TYPE_BYTE},
122
{RB_DAAP_CC_AGRP, MAKE_CONTENT_CODE('a','g','r','p'), "daap.songgrouping", "agrp", RB_DAAP_TYPE_STRING},
123
{RB_DAAP_CC_ASCP, MAKE_CONTENT_CODE('a','s','c','p'), "daap.songcomposer", "ascp", RB_DAAP_TYPE_STRING}
128
rb_daap_content_code_name (RBDAAPContentCode code)
130
return cc_defs[code-1].name;
134
rb_daap_content_code_rb_daap_type (RBDAAPContentCode code)
136
return cc_defs[code-1].type;
140
rb_daap_content_code_string (RBDAAPContentCode code)
142
return cc_defs[code-1].string;
146
rb_daap_content_code_gtype (RBDAAPContentCode code)
148
switch (rb_daap_content_code_rb_daap_type (code)) {
149
case RB_DAAP_TYPE_BYTE:
150
case RB_DAAP_TYPE_SIGNED_INT:
152
case RB_DAAP_TYPE_SHORT:
153
case RB_DAAP_TYPE_INT:
154
case RB_DAAP_TYPE_DATE:
156
case RB_DAAP_TYPE_INT64:
158
case RB_DAAP_TYPE_VERSION:
159
return G_TYPE_DOUBLE;
160
case RB_DAAP_TYPE_STRING:
161
return G_TYPE_STRING;
162
case RB_DAAP_TYPE_CONTAINER:
169
rb_daap_structure_add (GNode *parent,
170
RBDAAPContentCode cc,
173
RBDAAPType rb_daap_type;
182
rb_daap_type = rb_daap_content_code_rb_daap_type (cc);
183
gtype = rb_daap_content_code_gtype (cc);
185
item = g_new0(RBDAAPItem, 1);
186
item->content_code = cc;
188
if (gtype != G_TYPE_NONE) {
189
g_value_init (&(item->content), gtype);
192
if (rb_daap_type != RB_DAAP_TYPE_STRING && rb_daap_type != RB_DAAP_TYPE_CONTAINER) {
193
G_VALUE_COLLECT (&(item->content), list, G_VALUE_NOCOPY_CONTENTS, &error);
200
switch (rb_daap_type) {
201
case RB_DAAP_TYPE_BYTE:
202
case RB_DAAP_TYPE_SIGNED_INT:
205
case RB_DAAP_TYPE_SHORT:
208
case RB_DAAP_TYPE_DATE:
209
case RB_DAAP_TYPE_INT:
210
case RB_DAAP_TYPE_VERSION:
213
case RB_DAAP_TYPE_INT64:
216
case RB_DAAP_TYPE_STRING: {
217
gchar *s = va_arg (list, gchar *);
219
g_value_set_string (&(item->content), s);
221
/* we dont use G_VALUE_COLLECT for this because we also
223
item->size = strlen (s);
226
case RB_DAAP_TYPE_CONTAINER:
231
node = g_node_new (item);
234
g_node_append (parent, node);
237
RBDAAPItem *parent_item = parent->data;
239
parent_item->size += (4 + 4 + item->size);
241
parent = parent->parent;
249
rb_daap_structure_node_serialize (GNode *node,
252
RBDAAPItem *item = node->data;
253
RBDAAPType rb_daap_type;
254
guint32 size = GINT32_TO_BE (item->size);
256
g_byte_array_append (array, (const guint8 *)rb_daap_content_code_string (item->content_code), 4);
257
g_byte_array_append (array, (const guint8 *)&size, 4);
259
rb_daap_type = rb_daap_content_code_rb_daap_type (item->content_code);
261
switch (rb_daap_type) {
262
case RB_DAAP_TYPE_BYTE:
263
case RB_DAAP_TYPE_SIGNED_INT: {
264
gchar c = g_value_get_char (&(item->content));
266
g_byte_array_append (array, (const guint8 *)&c, 1);
270
case RB_DAAP_TYPE_SHORT: {
271
gint32 i = g_value_get_int (&(item->content));
272
gint16 s = GINT16_TO_BE ((gint16) i);
274
g_byte_array_append (array, (const guint8 *)&s, 2);
278
case RB_DAAP_TYPE_DATE:
279
case RB_DAAP_TYPE_INT: {
280
gint32 i = g_value_get_int (&(item->content));
281
gint32 s = GINT32_TO_BE (i);
283
g_byte_array_append (array, (const guint8 *)&s, 4);
287
case RB_DAAP_TYPE_VERSION: {
288
gdouble v = g_value_get_double (&(item->content));
294
minor = (gint8)(v - ((gdouble)major));
296
major = GINT16_TO_BE (major);
298
g_byte_array_append (array, (const guint8 *)&major, 2);
299
g_byte_array_append (array, (const guint8 *)&minor, 1);
300
g_byte_array_append (array, (const guint8 *)&patch, 1);
304
case RB_DAAP_TYPE_INT64: {
305
gint64 i = g_value_get_int64 (&(item->content));
306
gint64 s = GINT64_TO_BE (i);
308
g_byte_array_append (array, (const guint8 *)&s, 8);
312
case RB_DAAP_TYPE_STRING: {
313
const gchar *s = g_value_get_string (&(item->content));
315
g_byte_array_append (array, (const guint8 *)s, strlen (s));
319
case RB_DAAP_TYPE_CONTAINER:
328
rb_daap_structure_serialize (GNode *structure,
334
array = g_byte_array_new ();
337
g_node_traverse (structure, G_PRE_ORDER, G_TRAVERSE_ALL, -1, (GNodeTraverseFunc)rb_daap_structure_node_serialize, array);
340
data = (gchar *) array->data;
341
*length = array->len;
342
g_byte_array_free (array, FALSE);
347
static RBDAAPContentCode
348
rb_daap_buffer_read_content_code (const gchar *buf)
350
gint32 c = MAKE_CONTENT_CODE (buf[0], buf[1], buf[2], buf[3]);
353
for (i = 0; i < G_N_ELEMENTS (cc_defs); i++) {
354
if (cc_defs[i].int_code == c) {
355
return cc_defs[i].code;
359
return RB_DAAP_CC_INVALID;
362
#define rb_daap_buffer_read_int8(b) GST_READ_UINT8 (b)
363
#define rb_daap_buffer_read_int16(b) (gint16) GST_READ_UINT16_BE (b)
364
#define rb_daap_buffer_read_int32(b) (gint32) GST_READ_UINT32_BE (b)
365
#define rb_daap_buffer_read_int64(b) (gint64) GST_READ_UINT64_BE (b)
368
rb_daap_buffer_read_string (const gchar *buf, gssize size)
370
if (g_utf8_validate (buf, size, NULL) == TRUE) {
371
return g_strndup (buf, size);
373
return g_strdup ("");
377
//#define PARSE_DEBUG
378
#define PARSE_DEBUG_FILE "daapbuffer"
382
#include <sys/stat.h>
387
rb_daap_structure_parse_container_buffer (GNode *parent,
393
while (l < buf_length) {
394
RBDAAPContentCode cc;
396
RBDAAPItem *item = NULL;
401
g_print ("l is %d and buf_length is %d\n", l, buf_length);
404
/* we need at least 8 bytes, 4 of content_code and 4 of size */
405
if (buf_length - l < 8) {
407
g_print ("Malformed response recieved\n");
412
cc = rb_daap_buffer_read_content_code ((const gchar*)&(buf[l]));
413
if (cc == RB_DAAP_CC_INVALID) {
415
g_print ("Invalid content_code recieved\n");
421
codesize = rb_daap_buffer_read_int32(&(buf[l]));
423
* if the buffer length (minus 8 for the content code & size)
424
* is smaller than the read codesize (ie, someone sent us
425
* a codesize that is larger than the remaining data)
426
* then get out before we start processing it
428
if (codesize > buf_length - l - 4 || codesize < 0) {
430
g_print ("Invalid codesize %d recieved in buf_length %d\n", codesize, buf_length);
437
g_print ("content_code = %d, codesize is %d, l is %d\n", cc, codesize, l);
440
item = g_new0 (RBDAAPItem, 1);
441
item->content_code = cc;
442
node = g_node_new (item);
443
g_node_append (parent, node);
445
gtype = rb_daap_content_code_gtype (item->content_code);
447
if (gtype != G_TYPE_NONE) {
448
g_value_init (&(item->content), gtype);
455
for (i = 2; i < g_node_depth (node); i++) {
461
// FIXME USE THE G_TYPE CONVERTOR FUNCTION rb_daap_type_to_gtype
462
switch (rb_daap_content_code_rb_daap_type (item->content_code)) {
463
case RB_DAAP_TYPE_SIGNED_INT:
464
case RB_DAAP_TYPE_BYTE: {
468
c = (gchar) rb_daap_buffer_read_int8(&(buf[l]));
471
g_value_set_char (&(item->content), c);
473
g_print ("Code: %s, content (%d): \"%c\"\n", rb_daap_content_code_string (item->content_code), codesize, (gchar)c);
478
case RB_DAAP_TYPE_SHORT: {
482
s = rb_daap_buffer_read_int16(&(buf[l]));
485
g_value_set_int (&(item->content),(gint32)s);
487
g_print ("Code: %s, content (%d): %hi\n", rb_daap_content_code_string (item->content_code), codesize, s);
492
case RB_DAAP_TYPE_DATE:
493
case RB_DAAP_TYPE_INT: {
497
i = rb_daap_buffer_read_int32(&(buf[l]));
500
g_value_set_int (&(item->content), i);
502
g_print ("Code: %s, content (%d): %d\n", rb_daap_content_code_string (item->content_code), codesize, i);
506
case RB_DAAP_TYPE_INT64: {
510
i = rb_daap_buffer_read_int16(&(buf[l]));
513
g_value_set_int64 (&(item->content), i);
515
g_print ("Code: %s, content (%d): %"G_GINT64_FORMAT"\n", rb_daap_content_code_string (item->content_code), codesize, i);
520
case RB_DAAP_TYPE_STRING: {
521
gchar *s = rb_daap_buffer_read_string ((const gchar*)&(buf[l]), codesize);
523
g_value_take_string (&(item->content), s);
525
g_print ("Code: %s, content (%d): \"%s\"\n", rb_daap_content_code_string (item->content_code), codesize, s);
530
case RB_DAAP_TYPE_VERSION: {
537
major = rb_daap_buffer_read_int16(&(buf[l]));
538
minor = rb_daap_buffer_read_int8(&(buf[l]) + 2);
539
patch = rb_daap_buffer_read_int8(&(buf[l]) + 3);
543
v += (gdouble)(minor * 0.1);
544
v += (gdouble)(patch * 0.01);
546
g_value_set_double (&(item->content), v);
548
g_print ("Code: %s, content: %f\n", rb_daap_content_code_string (item->content_code), v);
553
case RB_DAAP_TYPE_CONTAINER: {
555
g_print ("Code: %s, container\n", rb_daap_content_code_string (item->content_code));
557
rb_daap_structure_parse_container_buffer (node,&(buf[l]), codesize);
569
rb_daap_structure_parse (const gchar *buf,
579
fd = open (PARSE_DEBUG_FILE, O_WRONLY | O_CREAT);
580
write (fd, (const void *)buf, (size_t)buf_length);
585
root = g_node_new (NULL);
587
rb_daap_structure_parse_container_buffer (root, (guchar *)buf, buf_length);
589
child = root->children;
591
g_node_unlink (child);
593
g_node_destroy (root);
599
RBDAAPContentCode code;
604
gnode_find_node (GNode *node,
607
struct NodeFinder *finder = (struct NodeFinder *)data;
608
RBDAAPItem *item = node->data;
610
if (item->content_code == finder->code) {
619
rb_daap_structure_find_item (GNode *structure,
620
RBDAAPContentCode code)
624
node = rb_daap_structure_find_node (structure, code);
634
rb_daap_structure_find_node (GNode *structure,
635
RBDAAPContentCode code)
637
struct NodeFinder *finder;
640
finder = g_new0(struct NodeFinder,1);
643
g_node_traverse (structure, G_IN_ORDER, G_TRAVERSE_ALL, -1, gnode_find_node, finder);
655
rb_daap_item_free (RBDAAPItem *item)
657
if (rb_daap_content_code_rb_daap_type (item->content_code) != RB_DAAP_TYPE_CONTAINER) {
658
g_value_unset (&(item->content));
665
gnode_free_rb_daap_item (GNode *node,
668
rb_daap_item_free ((RBDAAPItem *)node->data);
674
rb_daap_structure_destroy (GNode *structure)
677
g_node_traverse (structure, G_IN_ORDER, G_TRAVERSE_ALL, -1, gnode_free_rb_daap_item, NULL);
679
g_node_destroy (structure);
685
const RBDAAPContentCodeDefinition *
686
rb_daap_content_codes (guint *number)
688
*number = G_N_ELEMENTS (cc_defs);
694
rb_daap_content_code_string_as_int32 (const gchar *str)
701
strncpy (u.str, str, 4);
707
print_rb_daap_item (GNode *node,
715
for (i = 1; i < g_node_depth (node); i++) {
721
name = rb_daap_content_code_name (item->content_code);
723
if (G_IS_VALUE (&(item->content))) {
724
value = g_strdup_value_contents (&(item->content));
726
value = g_strdup ("");
729
g_print ("%d, %s = %s (%d)\n", g_node_depth (node), name, value, item->size);
736
rb_daap_structure_print (GNode *structure)
739
g_node_traverse (structure, G_PRE_ORDER, G_TRAVERSE_ALL, -1, (GNodeTraverseFunc)print_rb_daap_item, NULL);