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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 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
}
127 rb_daap_content_code_name (RBDAAPContentCode code
)
129 return cc_defs
[code
-1].name
;
133 rb_daap_content_code_rb_daap_type (RBDAAPContentCode code
)
135 return cc_defs
[code
-1].type
;
139 rb_daap_content_code_string (RBDAAPContentCode code
)
141 return cc_defs
[code
-1].string
;
145 rb_daap_content_code_gtype (RBDAAPContentCode code
)
147 switch (rb_daap_content_code_rb_daap_type (code
)) {
148 case RB_DAAP_TYPE_BYTE
:
149 case RB_DAAP_TYPE_SIGNED_INT
:
151 case RB_DAAP_TYPE_SHORT
:
152 case RB_DAAP_TYPE_INT
:
153 case RB_DAAP_TYPE_DATE
:
155 case RB_DAAP_TYPE_INT64
:
157 case RB_DAAP_TYPE_VERSION
:
158 return G_TYPE_DOUBLE
;
159 case RB_DAAP_TYPE_STRING
:
160 return G_TYPE_STRING
;
161 case RB_DAAP_TYPE_CONTAINER
:
168 rb_daap_structure_add (GNode
*parent
,
169 RBDAAPContentCode cc
,
172 RBDAAPType rb_daap_type
;
181 rb_daap_type
= rb_daap_content_code_rb_daap_type (cc
);
182 gtype
= rb_daap_content_code_gtype (cc
);
184 item
= g_new0(RBDAAPItem
, 1);
185 item
->content_code
= cc
;
187 if (gtype
!= G_TYPE_NONE
) {
188 g_value_init (&(item
->content
), gtype
);
191 if (rb_daap_type
!= RB_DAAP_TYPE_STRING
&& rb_daap_type
!= RB_DAAP_TYPE_CONTAINER
) {
192 G_VALUE_COLLECT (&(item
->content
), list
, G_VALUE_NOCOPY_CONTENTS
, &error
);
199 switch (rb_daap_type
) {
200 case RB_DAAP_TYPE_BYTE
:
201 case RB_DAAP_TYPE_SIGNED_INT
:
204 case RB_DAAP_TYPE_SHORT
:
207 case RB_DAAP_TYPE_DATE
:
208 case RB_DAAP_TYPE_INT
:
209 case RB_DAAP_TYPE_VERSION
:
212 case RB_DAAP_TYPE_INT64
:
215 case RB_DAAP_TYPE_STRING
: {
216 gchar
*s
= va_arg (list
, gchar
*);
218 g_value_set_string (&(item
->content
), s
);
220 /* we dont use G_VALUE_COLLECT for this because we also
222 item
->size
= strlen (s
);
225 case RB_DAAP_TYPE_CONTAINER
:
230 node
= g_node_new (item
);
233 g_node_append (parent
, node
);
236 RBDAAPItem
*parent_item
= parent
->data
;
238 parent_item
->size
+= (4 + 4 + item
->size
);
240 parent
= parent
->parent
;
248 rb_daap_structure_node_serialize (GNode
*node
,
251 RBDAAPItem
*item
= node
->data
;
252 RBDAAPType rb_daap_type
;
253 guint32 size
= GINT32_TO_BE (item
->size
);
255 g_byte_array_append (array
, (const guint8
*)rb_daap_content_code_string (item
->content_code
), 4);
256 g_byte_array_append (array
, (const guint8
*)&size
, 4);
258 rb_daap_type
= rb_daap_content_code_rb_daap_type (item
->content_code
);
260 switch (rb_daap_type
) {
261 case RB_DAAP_TYPE_BYTE
:
262 case RB_DAAP_TYPE_SIGNED_INT
: {
263 gchar c
= g_value_get_char (&(item
->content
));
265 g_byte_array_append (array
, (const guint8
*)&c
, 1);
269 case RB_DAAP_TYPE_SHORT
: {
270 gint32 i
= g_value_get_int (&(item
->content
));
271 gint16 s
= GINT16_TO_BE ((gint16
) i
);
273 g_byte_array_append (array
, (const guint8
*)&s
, 2);
277 case RB_DAAP_TYPE_DATE
:
278 case RB_DAAP_TYPE_INT
: {
279 gint32 i
= g_value_get_int (&(item
->content
));
280 gint32 s
= GINT32_TO_BE (i
);
282 g_byte_array_append (array
, (const guint8
*)&s
, 4);
286 case RB_DAAP_TYPE_VERSION
: {
287 gdouble v
= g_value_get_double (&(item
->content
));
293 minor
= (gint8
)(v
- ((gdouble
)major
));
295 major
= GINT16_TO_BE (major
);
297 g_byte_array_append (array
, (const guint8
*)&major
, 2);
298 g_byte_array_append (array
, (const guint8
*)&minor
, 1);
299 g_byte_array_append (array
, (const guint8
*)&patch
, 1);
303 case RB_DAAP_TYPE_INT64
: {
304 gint64 i
= g_value_get_int64 (&(item
->content
));
305 gint64 s
= GINT64_TO_BE (i
);
307 g_byte_array_append (array
, (const guint8
*)&s
, 8);
311 case RB_DAAP_TYPE_STRING
: {
312 const gchar
*s
= g_value_get_string (&(item
->content
));
314 g_byte_array_append (array
, (const guint8
*)s
, strlen (s
));
318 case RB_DAAP_TYPE_CONTAINER
:
327 rb_daap_structure_serialize (GNode
*structure
,
333 array
= g_byte_array_new ();
336 g_node_traverse (structure
, G_PRE_ORDER
, G_TRAVERSE_ALL
, -1, (GNodeTraverseFunc
)rb_daap_structure_node_serialize
, array
);
339 data
= (gchar
*) array
->data
;
340 *length
= array
->len
;
341 g_byte_array_free (array
, FALSE
);
346 static RBDAAPContentCode
347 rb_daap_buffer_read_content_code (const gchar
*buf
)
349 gint32 c
= MAKE_CONTENT_CODE (buf
[0], buf
[1], buf
[2], buf
[3]);
352 for (i
= 0; i
< G_N_ELEMENTS (cc_defs
); i
++) {
353 if (cc_defs
[i
].int_code
== c
) {
354 return cc_defs
[i
].code
;
358 return RB_DAAP_CC_INVALID
;
361 #define rb_daap_buffer_read_int8(b) GST_READ_UINT8 (b)
362 #define rb_daap_buffer_read_int16(b) (gint16) GST_READ_UINT16_BE (b)
363 #define rb_daap_buffer_read_int32(b) (gint32) GST_READ_UINT32_BE (b)
364 #define rb_daap_buffer_read_int64(b) (gint64) GST_READ_UINT64_BE (b)
367 rb_daap_buffer_read_string (const gchar
*buf
, gssize size
)
369 if (g_utf8_validate (buf
, size
, NULL
) == TRUE
) {
370 return g_strndup (buf
, size
);
372 return g_strdup ("");
376 //#define PARSE_DEBUG
377 #define PARSE_DEBUG_FILE "daapbuffer"
381 #include <sys/stat.h>
386 rb_daap_structure_parse_container_buffer (GNode
*parent
,
392 while (l
< buf_length
) {
393 RBDAAPContentCode cc
;
395 RBDAAPItem
*item
= NULL
;
400 g_print ("l is %d and buf_length is %d\n", l
, buf_length
);
403 /* we need at least 8 bytes, 4 of content_code and 4 of size */
404 if (buf_length
- l
< 8) {
406 g_print ("Malformed response recieved\n");
411 cc
= rb_daap_buffer_read_content_code ((const gchar
*)&(buf
[l
]));
412 if (cc
== RB_DAAP_CC_INVALID
) {
414 g_print ("Invalid content_code recieved\n");
420 codesize
= rb_daap_buffer_read_int32(&(buf
[l
]));
422 * if the buffer length (minus 8 for the content code & size)
423 * is smaller than the read codesize (ie, someone sent us
424 * a codesize that is larger than the remaining data)
425 * then get out before we start processing it
427 if (codesize
> buf_length
- l
- 4 || codesize
< 0) {
429 g_print ("Invalid codesize %d recieved in buf_length %d\n", codesize
, buf_length
);
436 g_print ("content_code = %d, codesize is %d, l is %d\n", cc
, codesize
, l
);
439 item
= g_new0 (RBDAAPItem
, 1);
440 item
->content_code
= cc
;
441 node
= g_node_new (item
);
442 g_node_append (parent
, node
);
444 gtype
= rb_daap_content_code_gtype (item
->content_code
);
446 if (gtype
!= G_TYPE_NONE
) {
447 g_value_init (&(item
->content
), gtype
);
454 for (i
= 2; i
< g_node_depth (node
); i
++) {
460 // FIXME USE THE G_TYPE CONVERTOR FUNCTION rb_daap_type_to_gtype
461 switch (rb_daap_content_code_rb_daap_type (item
->content_code
)) {
462 case RB_DAAP_TYPE_SIGNED_INT
:
463 case RB_DAAP_TYPE_BYTE
: {
467 c
= (gchar
) rb_daap_buffer_read_int8(&(buf
[l
]));
470 g_value_set_char (&(item
->content
), c
);
472 g_print ("Code: %s, content (%d): \"%c\"\n", rb_daap_content_code_string (item
->content_code
), codesize
, (gchar
)c
);
477 case RB_DAAP_TYPE_SHORT
: {
481 s
= rb_daap_buffer_read_int16(&(buf
[l
]));
484 g_value_set_int (&(item
->content
),(gint32
)s
);
486 g_print ("Code: %s, content (%d): %hi\n", rb_daap_content_code_string (item
->content_code
), codesize
, s
);
491 case RB_DAAP_TYPE_DATE
:
492 case RB_DAAP_TYPE_INT
: {
496 i
= rb_daap_buffer_read_int32(&(buf
[l
]));
499 g_value_set_int (&(item
->content
), i
);
501 g_print ("Code: %s, content (%d): %d\n", rb_daap_content_code_string (item
->content_code
), codesize
, i
);
505 case RB_DAAP_TYPE_INT64
: {
509 i
= rb_daap_buffer_read_int16(&(buf
[l
]));
512 g_value_set_int64 (&(item
->content
), i
);
514 g_print ("Code: %s, content (%d): %"G_GINT64_FORMAT
"\n", rb_daap_content_code_string (item
->content_code
), codesize
, i
);
519 case RB_DAAP_TYPE_STRING
: {
520 gchar
*s
= rb_daap_buffer_read_string ((const gchar
*)&(buf
[l
]), codesize
);
522 g_value_take_string (&(item
->content
), s
);
524 g_print ("Code: %s, content (%d): \"%s\"\n", rb_daap_content_code_string (item
->content_code
), codesize
, s
);
529 case RB_DAAP_TYPE_VERSION
: {
536 major
= rb_daap_buffer_read_int16(&(buf
[l
]));
537 minor
= rb_daap_buffer_read_int8(&(buf
[l
]) + 2);
538 patch
= rb_daap_buffer_read_int8(&(buf
[l
]) + 3);
542 v
+= (gdouble
)(minor
* 0.1);
543 v
+= (gdouble
)(patch
* 0.01);
545 g_value_set_double (&(item
->content
), v
);
547 g_print ("Code: %s, content: %f\n", rb_daap_content_code_string (item
->content_code
), v
);
552 case RB_DAAP_TYPE_CONTAINER
: {
554 g_print ("Code: %s, container\n", rb_daap_content_code_string (item
->content_code
));
556 rb_daap_structure_parse_container_buffer (node
,&(buf
[l
]), codesize
);
568 rb_daap_structure_parse (const gchar
*buf
,
578 fd
= open (PARSE_DEBUG_FILE
, O_WRONLY
| O_CREAT
);
579 write (fd
, (const void *)buf
, (size_t)buf_length
);
584 root
= g_node_new (NULL
);
586 rb_daap_structure_parse_container_buffer (root
, (guchar
*)buf
, buf_length
);
588 child
= root
->children
;
590 g_node_unlink (child
);
592 g_node_destroy (root
);
598 RBDAAPContentCode code
;
603 gnode_find_node (GNode
*node
,
606 struct NodeFinder
*finder
= (struct NodeFinder
*)data
;
607 RBDAAPItem
*item
= node
->data
;
609 if (item
->content_code
== finder
->code
) {
618 rb_daap_structure_find_item (GNode
*structure
,
619 RBDAAPContentCode code
)
623 node
= rb_daap_structure_find_node (structure
, code
);
633 rb_daap_structure_find_node (GNode
*structure
,
634 RBDAAPContentCode code
)
636 struct NodeFinder
*finder
;
639 finder
= g_new0(struct NodeFinder
,1);
642 g_node_traverse (structure
, G_IN_ORDER
, G_TRAVERSE_ALL
, -1, gnode_find_node
, finder
);
652 rb_daap_item_free (RBDAAPItem
*item
)
654 if (rb_daap_content_code_rb_daap_type (item
->content_code
) != RB_DAAP_TYPE_CONTAINER
) {
655 g_value_unset (&(item
->content
));
662 gnode_free_rb_daap_item (GNode
*node
,
665 rb_daap_item_free ((RBDAAPItem
*)node
->data
);
671 rb_daap_structure_destroy (GNode
*structure
)
674 g_node_traverse (structure
, G_IN_ORDER
, G_TRAVERSE_ALL
, -1, gnode_free_rb_daap_item
, NULL
);
676 g_node_destroy (structure
);
682 const RBDAAPContentCodeDefinition
*
683 rb_daap_content_codes (guint
*number
)
685 *number
= G_N_ELEMENTS (cc_defs
);
691 rb_daap_content_code_string_as_int32 (const gchar
*str
)
698 strncpy (u
.str
, str
, 4);
700 return g_htonl (u
.i
);
704 print_rb_daap_item (GNode
*node
,
712 for (i
= 1; i
< g_node_depth (node
); i
++) {
718 name
= rb_daap_content_code_name (item
->content_code
);
720 if (G_IS_VALUE (&(item
->content
))) {
721 value
= g_strdup_value_contents (&(item
->content
));
723 value
= g_strdup ("");
726 g_print ("%d, %s = %s (%d)\n", g_node_depth (node
), name
, value
, item
->size
);
733 rb_daap_structure_print (GNode
*structure
)
736 g_node_traverse (structure
, G_PRE_ORDER
, G_TRAVERSE_ALL
, -1, (GNodeTraverseFunc
)print_rb_daap_item
, NULL
);