2
* Copyright (C) 2009-2010 Julien BLACHE <jb@jblache.org>
4
* This program is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License as published by
6
* the Free Software Foundation; either version 2 of the License, or
7
* (at your option) any later version.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software
16
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27
#include "evhttp/evhttp.h"
32
#include "dmap_common.h"
35
/* gperf static hash, dmap_fields.gperf */
36
#include "dmap_fields_hash.c"
39
const struct dmap_field *
40
dmap_get_fields_table(int *nfields)
42
*nfields = sizeof(dmap_fields) / sizeof(dmap_fields[0]);
49
dmap_add_container(struct evbuffer *evbuf, char *tag, int len)
53
evbuffer_add(evbuf, tag, 4);
55
/* Container length */
56
buf[0] = (len >> 24) & 0xff;
57
buf[1] = (len >> 16) & 0xff;
58
buf[2] = (len >> 8) & 0xff;
61
evbuffer_add(evbuf, buf, sizeof(buf));
65
dmap_add_long(struct evbuffer *evbuf, char *tag, int64_t val)
67
unsigned char buf[12];
69
evbuffer_add(evbuf, tag, 4);
78
buf[4] = (val >> 56) & 0xff;
79
buf[5] = (val >> 48) & 0xff;
80
buf[6] = (val >> 40) & 0xff;
81
buf[7] = (val >> 32) & 0xff;
82
buf[8] = (val >> 24) & 0xff;
83
buf[9] = (val >> 16) & 0xff;
84
buf[10] = (val >> 8) & 0xff;
87
evbuffer_add(evbuf, buf, sizeof(buf));
91
dmap_add_int(struct evbuffer *evbuf, char *tag, int val)
95
evbuffer_add(evbuf, tag, 4);
104
buf[4] = (val >> 24) & 0xff;
105
buf[5] = (val >> 16) & 0xff;
106
buf[6] = (val >> 8) & 0xff;
109
evbuffer_add(evbuf, buf, sizeof(buf));
113
dmap_add_short(struct evbuffer *evbuf, char *tag, short val)
115
unsigned char buf[6];
117
evbuffer_add(evbuf, tag, 4);
126
buf[4] = (val >> 8) & 0xff;
129
evbuffer_add(evbuf, buf, sizeof(buf));
133
dmap_add_char(struct evbuffer *evbuf, char *tag, char val)
135
unsigned char buf[5];
137
evbuffer_add(evbuf, tag, 4);
148
evbuffer_add(evbuf, buf, sizeof(buf));
152
dmap_add_literal(struct evbuffer *evbuf, char *tag, char *str, int len)
156
evbuffer_add(evbuf, tag, 4);
159
buf[0] = (len >> 24) & 0xff;
160
buf[1] = (len >> 16) & 0xff;
161
buf[2] = (len >> 8) & 0xff;
164
evbuffer_add(evbuf, buf, sizeof(buf));
166
if (str && (len > 0))
167
evbuffer_add(evbuf, str, len);
171
dmap_add_string(struct evbuffer *evbuf, char *tag, const char *str)
173
unsigned char buf[4];
181
evbuffer_add(evbuf, tag, 4);
184
buf[0] = (len >> 24) & 0xff;
185
buf[1] = (len >> 16) & 0xff;
186
buf[2] = (len >> 8) & 0xff;
189
evbuffer_add(evbuf, buf, sizeof(buf));
192
evbuffer_add(evbuf, str, len);
196
dmap_add_field(struct evbuffer *evbuf, const struct dmap_field *df, char *strval, int32_t intval)
206
if (strval && (df->type != DMAP_TYPE_STRING))
211
case DMAP_TYPE_UBYTE:
212
case DMAP_TYPE_USHORT:
214
ret = safe_atou32(strval, &val.v_u32);
220
case DMAP_TYPE_SHORT:
222
ret = safe_atoi32(strval, &val.v_i32);
227
case DMAP_TYPE_ULONG:
228
ret = safe_atou64(strval, &val.v_u64);
234
ret = safe_atoi64(strval, &val.v_i64);
239
/* DMAP_TYPE_VERSION & DMAP_TYPE_LIST not handled here */
241
DPRINTF(E_LOG, L_DAAP, "Unsupported DMAP type %d for DMAP field %s\n", df->type, df->desc);
245
else if (!strval && (df->type != DMAP_TYPE_STRING))
250
case DMAP_TYPE_UBYTE:
251
case DMAP_TYPE_USHORT:
257
case DMAP_TYPE_SHORT:
262
case DMAP_TYPE_ULONG:
270
/* DMAP_TYPE_VERSION & DMAP_TYPE_LIST not handled here */
272
DPRINTF(E_LOG, L_DAAP, "Unsupported DMAP type %d for DMAP field %s\n", df->type, df->desc);
279
case DMAP_TYPE_UBYTE:
281
dmap_add_char(evbuf, df->tag, val.v_u32);
286
dmap_add_char(evbuf, df->tag, val.v_i32);
289
case DMAP_TYPE_USHORT:
291
dmap_add_short(evbuf, df->tag, val.v_u32);
294
case DMAP_TYPE_SHORT:
296
dmap_add_short(evbuf, df->tag, val.v_i32);
302
dmap_add_int(evbuf, df->tag, val.v_u32);
307
dmap_add_int(evbuf, df->tag, val.v_i32);
310
case DMAP_TYPE_ULONG:
312
dmap_add_long(evbuf, df->tag, val.v_u64);
317
dmap_add_long(evbuf, df->tag, val.v_i64);
320
case DMAP_TYPE_STRING:
322
dmap_add_string(evbuf, df->tag, strval);
325
case DMAP_TYPE_VERSION:
333
dmap_send_error(struct evhttp_request *req, char *container, char *errmsg)
335
struct evbuffer *evbuf;
339
evbuf = evbuffer_new();
342
DPRINTF(E_LOG, L_DMAP, "Could not allocate evbuffer for DMAP error\n");
344
evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");
348
len = 12 + 8 + 8 + strlen(errmsg);
350
ret = evbuffer_expand(evbuf, len);
353
DPRINTF(E_LOG, L_DMAP, "Could not expand evbuffer for DMAP error\n");
355
evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");
357
evbuffer_free(evbuf);
361
dmap_add_container(evbuf, container, len - 8);
362
dmap_add_int(evbuf, "mstt", 500);
363
dmap_add_string(evbuf, "msts", errmsg);
365
evhttp_send_reply(req, HTTP_OK, "OK", evbuf);
367
evbuffer_free(evbuf);
372
dmap_encode_file_metadata(struct evbuffer *songlist, struct evbuffer *song, struct db_media_file_info *dbmfi, const struct dmap_field **meta, int nmeta, int force_wav)
374
const struct dmap_field_map *dfm;
375
const struct dmap_field *df;
392
/* Specific meta tags requested (or default list) */
401
/* No specific meta tags requested, send out everything */
405
if (i == (sizeof(dmap_fields) / sizeof(dmap_fields[0])))
408
df = &dmap_fields[i];
409
dfm = dmap_fields[i].dfm;
412
/* Not in struct media_file_info */
413
if (dfm->mfi_offset < 0)
416
/* Will be prepended to the list */
417
if (dfm == &dfm_dmap_mikd)
423
else if (dfm == &dfm_dmap_asdk)
430
DPRINTF(E_DBG, L_DAAP, "Investigating %s\n", df->desc);
432
strval = (char **) ((char *)dbmfi + dfm->mfi_offset);
434
if (!(*strval) || (**strval == '\0'))
437
/* Here's one exception ... codectype (ascd) is actually an integer */
438
if (dfm == &dfm_dmap_ascd)
440
dmap_add_literal(song, df->tag, *strval, 4);
448
switch (dfm->mfi_offset)
450
case dbmfi_offsetof(type):
455
case dbmfi_offsetof(bitrate):
457
ret = safe_atoi32(dbmfi->samplerate, &val);
458
if ((ret < 0) || (val == 0))
461
val = (val * 8) / 250;
467
case dbmfi_offsetof(description):
468
ptr = "wav audio file";
477
dmap_add_field(song, df, *strval, val);
479
DPRINTF(E_DBG, L_DAAP, "Done with meta tag %s (%s)\n", df->desc, *strval);
488
dmap_add_container(songlist, "mlit", EVBUFFER_LENGTH(song) + val);
490
/* Prepend mikd & asdk if needed */
493
/* dmap.itemkind must come first */
494
ret = safe_atoi32(dbmfi->item_kind, &val);
496
val = 2; /* music by default */
497
dmap_add_char(songlist, "mikd", val);
501
ret = safe_atoi32(dbmfi->data_kind, &val);
504
dmap_add_char(songlist, "asdk", val);
507
ret = evbuffer_add_buffer(songlist, song);
510
DPRINTF(E_LOG, L_DAAP, "Could not add song to song list\n");