Don't add duplicate tags
[cmus.git] / mpc.c
blobae9e22995b0a93e3da50d791009ca62236afc023
1 /*
2 * Copyright 2006 Chun-Yu Shei <cshei AT cs.indiana.edu>
4 * Cleaned up by Timo Hirvonen <tihirvon@gmail.com>
5 */
7 #include "ip.h"
8 #include "comment.h"
9 #include "file.h"
10 #include "xmalloc.h"
11 #include "read_wrapper.h"
13 #include <mpcdec/mpcdec.h>
14 #include <inttypes.h>
15 #include <errno.h>
17 /* http://www.personal.uni-jena.de/~pfk/mpp/sv8/apetag.html */
19 #define PREAMBLE_SIZE (8)
20 static const char preamble[PREAMBLE_SIZE] = { 'A', 'P', 'E', 'T', 'A', 'G', 'E', 'X' };
22 /* NOTE: not sizeof(struct ape_header)! */
23 #define HEADER_SIZE (32)
25 struct ape_header {
26 /* 1000 or 2000 (1.0, 2.0) */
27 uint32_t version;
29 /* tag size (header + tags, excluding footer) */
30 uint32_t size;
32 /* number of items */
33 uint32_t count;
35 /* global flags for each tag
36 * there are also private flags for every tag
37 * NOTE: 0 for version 1.0 (1000)
39 uint32_t flags;
42 /* ape flags */
43 #define AF_IS_UTF8(f) (((f) & 6) == 0)
44 #define AF_IS_FOOTER(f) (((f) & (1 << 29)) == 0)
46 struct mpc_private {
47 mpc_decoder decoder;
48 mpc_reader reader;
49 mpc_streaminfo info;
51 off_t file_size;
53 int samples_pos;
54 int samples_avail;
56 /* mpcdec/mpcdec.h
58 * the api doc says this is pcm samples per mpc frame
59 * but it's really pcm _frames_ per mpc frame
60 * MPC_FRAME_LENGTH = 36 * 32 (1152)
62 * this is wrong, it should be 2 * MPC_FRAME_LENGTH (2304)
63 * MPC_DECODER_BUFFER_LENGTH = 4 * MPC_FRAME_LENGTH (4608)
65 * use MPC_DECODER_BUFFER_LENGTH just to be sure it works
67 MPC_SAMPLE_FORMAT samples[MPC_DECODER_BUFFER_LENGTH];
70 static inline uint32_t get_le32(const char *buf)
72 const unsigned char *b = (const unsigned char *)buf;
74 return b[0] | (b[1] << 8) | (b[2] << 16) | (b[3] << 24);
77 /* callbacks {{{ */
78 static mpc_int32_t read_impl(void *data, void *ptr, mpc_int32_t size)
80 struct input_plugin_data *ip_data = data;
81 int rc;
83 rc = read_wrapper(ip_data, ptr, size);
84 if (rc == -1)
85 return -1;
86 if (rc == 0) {
87 errno = 0;
88 return 0;
90 return rc;
93 static mpc_bool_t seek_impl(void *data, mpc_int32_t offset)
95 struct input_plugin_data *ip_data = data;
96 int rc;
98 rc = lseek(ip_data->fd, offset, SEEK_SET);
99 if (rc == -1)
100 return FALSE;
101 return TRUE;
104 static mpc_int32_t tell_impl(void *data)
106 struct input_plugin_data *ip_data = data;
108 return lseek(ip_data->fd, 0, SEEK_CUR);
111 static mpc_int32_t get_size_impl(void *data)
113 struct input_plugin_data *ip_data = data;
114 struct mpc_private *priv = ip_data->private;
116 return priv->file_size;
119 static mpc_bool_t canseek_impl(void *data)
121 struct input_plugin_data *ip_data = data;
123 return !ip_data->remote;
125 /* }}} */
127 /* ape {{{ */
129 /* returns position of APE header or -1 if not found */
130 static int find_ape_tag_slow(int fd)
132 char buf[4096];
133 int match = 0;
134 int pos = 0;
136 /* seek to start of file */
137 if (lseek(fd, pos, SEEK_SET) == -1)
138 return -1;
140 while (1) {
141 int i, got = read(fd, buf, sizeof(buf));
143 if (got == -1) {
144 if (errno == EAGAIN || errno == EINTR)
145 continue;
146 break;
148 if (got == 0)
149 break;
151 for (i = 0; i < got; i++) {
152 if (buf[i] != preamble[match]) {
153 match = 0;
154 continue;
157 match++;
158 if (match == PREAMBLE_SIZE)
159 return pos + i + 1 - PREAMBLE_SIZE;
161 pos += got;
163 return -1;
166 static int ape_parse_header(const char *buf, struct ape_header *h)
168 if (memcmp(buf, preamble, PREAMBLE_SIZE))
169 return 0;
171 h->version = get_le32(buf + 8);
172 h->size = get_le32(buf + 12);
173 h->count = get_le32(buf + 16);
174 h->flags = get_le32(buf + 20);
175 return 1;
178 static int read_header(int fd, struct ape_header *h)
180 char buf[HEADER_SIZE];
182 if (read_all(fd, buf, sizeof(buf)) != sizeof(buf))
183 return 0;
184 return ape_parse_header(buf, h);
187 /* sets fd right after the header and returns 1 if found,
188 * otherwise returns 0
190 static int find_ape_tag(int fd, struct ape_header *h)
192 int pos;
194 if (lseek(fd, -HEADER_SIZE, SEEK_END) == -1)
195 return 0;
196 if (read_header(fd, h))
197 return 1;
199 pos = find_ape_tag_slow(fd);
200 if (pos == -1)
201 return 0;
202 if (lseek(fd, pos, SEEK_SET) == -1)
203 return 0;
204 return read_header(fd, h);
208 * All keys are ASCII and length is 2..255
210 * UTF-8: Artist, Album, Title, Genre
211 * Integer: Track (N or N/M)
212 * Date: Year (release), "Record Date"
214 * UTF-8 strings are NOT zero terminated.
216 * Also support "discnumber" (vorbis) and "disc" (non-standard)
218 static int ape_parse_one(const char *buf, int size, char **keyp, char **valp)
220 int pos = 0;
222 while (size - pos > 8) {
223 uint32_t val_len, flags;
224 char *key, *val;
225 int max_key_len, key_len;
227 val_len = get_le32(buf + pos); pos += 4;
228 flags = get_le32(buf + pos); pos += 4;
230 max_key_len = size - pos - val_len - 1;
231 if (max_key_len < 0) {
232 /* corrupt */
233 break;
236 for (key_len = 0; key_len < max_key_len && buf[pos + key_len]; key_len++)
237 ; /* nothing */
238 if (buf[pos + key_len]) {
239 /* corrupt */
240 break;
243 if (!AF_IS_UTF8(flags)) {
244 /* ignore binary data */
245 pos += key_len + 1 + val_len;
246 continue;
249 key = xstrdup(buf + pos);
250 pos += key_len + 1;
252 /* should not be NUL-terminated */
253 val = xstrndup(buf + pos, val_len);
254 pos += val_len;
256 /* could be moved to comment.c but I don't think anyone else would use it */
257 if (!strcasecmp(key, "record date") || !strcasecmp(key, "year")) {
258 free(key);
259 key = xstrdup("date");
262 if (!strcasecmp(key, "date")) {
263 /* Date format
265 * 1999-08-11 12:34:56
266 * 1999-08-11 12:34
267 * 1999-08-11
268 * 1999-08
269 * 1999
270 * 1999-W34 (week 34, totally crazy)
272 * convert to year, pl.c supports only years anyways
274 * FIXME: which one is the most common tag (year or record date)?
276 if (strlen(val) > 4)
277 val[4] = 0;
280 *keyp = key;
281 *valp = val;
282 return pos;
284 return -1;
287 /* }}} */
289 static int mpc_open(struct input_plugin_data *ip_data)
291 struct mpc_private *priv;
293 priv = xnew0(struct mpc_private, 1);
295 priv->file_size = -1;
296 if (!ip_data->remote) {
297 priv->file_size = lseek(ip_data->fd, 0, SEEK_END);
298 lseek(ip_data->fd, 0, SEEK_SET);
301 /* set up an mpc_reader linked to our function implementations */
302 priv->reader.read = read_impl;
303 priv->reader.seek = seek_impl;
304 priv->reader.tell = tell_impl;
305 priv->reader.get_size = get_size_impl;
306 priv->reader.canseek = canseek_impl;
307 priv->reader.data = ip_data;
309 /* must be before mpc_streaminfo_read() */
310 ip_data->private = priv;
312 /* read file's streaminfo data */
313 mpc_streaminfo_init(&priv->info);
314 if (mpc_streaminfo_read(&priv->info, &priv->reader) != ERROR_CODE_OK) {
315 free(priv);
316 return -IP_ERROR_FILE_FORMAT;
319 /* instantiate a decoder with our file reader */
320 mpc_decoder_setup(&priv->decoder, &priv->reader);
321 if (!mpc_decoder_initialize(&priv->decoder, &priv->info)) {
322 free(priv);
323 return -IP_ERROR_FILE_FORMAT;
326 priv->samples_avail = 0;
327 priv->samples_pos = 0;
329 ip_data->sf = sf_rate(priv->info.sample_freq) | sf_channels(priv->info.channels) |
330 sf_bits(16) | sf_signed(1);
331 return 0;
334 static int mpc_close(struct input_plugin_data *ip_data)
336 struct mpc_private *priv = ip_data->private;
338 free(priv);
339 ip_data->private = NULL;
340 return 0;
343 static int scale(struct input_plugin_data *ip_data, char *buffer, int count)
345 struct mpc_private *priv = ip_data->private;
346 const MPC_SAMPLE_FORMAT *samples;
347 const int clip_min = -1 << (16 - 1);
348 const int clip_max = (1 << (16 - 1)) - 1;
349 const int float_scale = 1 << (16 - 1);
350 int i, sample_count;
352 /* number of bytes to 16-bit samples */
353 sample_count = count / 2;
354 if (sample_count > priv->samples_avail)
355 sample_count = priv->samples_avail;
357 /* scale 32-bit samples to 16-bit */
358 samples = priv->samples + priv->samples_pos;
359 for (i = 0; i < sample_count; i++) {
360 int val;
362 val = samples[i] * float_scale;
363 if (val < clip_min) {
364 val = clip_min;
365 } else if (val > clip_max) {
366 val = clip_max;
369 buffer[i * 2 + 0] = val & 0xff;
370 buffer[i * 2 + 1] = val >> 8;
373 priv->samples_pos += sample_count;
374 priv->samples_avail -= sample_count;
375 if (priv->samples_avail == 0)
376 priv->samples_pos = 0;
378 /* number of 16-bit samples to bytes */
379 return sample_count * 2;
382 static int mpc_read(struct input_plugin_data *ip_data, char *buffer, int count)
384 struct mpc_private *priv = ip_data->private;
386 if (priv->samples_avail == 0) {
387 uint32_t status = mpc_decoder_decode(&priv->decoder, priv->samples, NULL, NULL);
389 if (status == (uint32_t)(-1)) {
390 /* right ret val? */
391 return -IP_ERROR_ERRNO;
393 if (status == 0) {
394 /* EOF */
395 return 0;
398 /* status seems to be number of _frames_
399 * the api documentation is wrong
401 priv->samples_avail = status * priv->info.channels;
403 return scale(ip_data, buffer, count);
406 static int mpc_seek(struct input_plugin_data *ip_data, double offset)
408 struct mpc_private *priv = ip_data->private;
410 priv->samples_pos = 0;
411 priv->samples_avail = 0;
413 if (mpc_decoder_seek_seconds(&priv->decoder, offset))
414 return 0;
415 return -1;
418 static const char *gain_to_str(int gain)
420 static char buf[16];
421 int b, a = gain / 100;
423 if (gain < 0) {
424 b = -gain % 100;
425 } else {
426 b = gain % 100;
428 sprintf(buf, "%d.%02d", a, b);
429 return buf;
432 static const char *peak_to_str(unsigned int peak)
434 static char buf[16];
435 sprintf(buf, "%d.%05d", peak / 32767, peak % 32767);
436 return buf;
439 static int mpc_read_comments(struct input_plugin_data *ip_data, struct keyval **comments)
441 struct mpc_private *priv = ip_data->private;
442 int old_pos, fd = ip_data->fd;
443 struct ape_header h;
444 char *buf;
445 GROWING_KEYVALS(c);
447 /* save position */
448 old_pos = lseek(fd, 0, SEEK_CUR);
450 if (!find_ape_tag(fd, &h))
451 goto out;
453 if (AF_IS_FOOTER(h.flags)) {
454 off_t file_size = get_size_impl(ip_data);
455 /* seek back right after the header */
456 if (lseek(fd, file_size - h.size, SEEK_SET) == -1)
457 goto out;
460 /* ignore insane tags */
461 if (h.size > 1024 * 1024)
462 goto out;
464 buf = xnew(char, h.size);
465 if (read_all(fd, buf, h.size) == h.size) {
466 int pos = 0, rc;
468 while (pos < h.size) {
469 char *k, *v;
470 rc = ape_parse_one(buf + pos, h.size - pos, &k, &v);
471 if (rc < 0)
472 break;
474 comments_add(&c, k, v);
475 free(k);
477 pos += rc;
480 free(buf);
481 out:
482 if (priv->info.gain_title && priv->info.peak_title) {
483 comments_add_const(&c, "replaygain_track_gain", gain_to_str(priv->info.gain_title));
484 comments_add_const(&c, "replaygain_track_peak", peak_to_str(priv->info.peak_title));
486 if (priv->info.gain_album && priv->info.peak_album) {
487 comments_add_const(&c, "replaygain_album_gain", gain_to_str(priv->info.gain_album));
488 comments_add_const(&c, "replaygain_album_peak", peak_to_str(priv->info.peak_album));
490 comments_terminate(&c);
492 lseek(fd, old_pos, SEEK_SET);
493 *comments = c.comments;
494 return 0;
497 static int mpc_duration(struct input_plugin_data *ip_data)
499 struct mpc_private *priv = ip_data->private;
501 /* priv->info.pcm_samples seems to be number of frames
502 * priv->info.frames is _not_ pcm frames
504 return priv->info.pcm_samples / priv->info.sample_freq;
507 const struct input_plugin_ops ip_ops = {
508 .open = mpc_open,
509 .close = mpc_close,
510 .read = mpc_read,
511 .seek = mpc_seek,
512 .read_comments = mpc_read_comments,
513 .duration = mpc_duration
516 const char *const ip_extensions[] = { "mpc", "mpp", "mp+", NULL };
517 const char *const ip_mime_types[] = { "audio/x-musepack", NULL };