Remove extraneous "`"
[cmus.git] / mpc.c
blobcdd1bdf23a814a8f58f34c4d22827b31e5e51f32
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 read_header(int fd, struct ape_header *h)
168 char buf[HEADER_SIZE];
170 if (read_all(fd, buf, sizeof(buf)) != sizeof(buf))
171 return 0;
172 if (memcmp(buf, preamble, PREAMBLE_SIZE))
173 return 0;
175 h->version = get_le32(buf + 8);
176 h->size = get_le32(buf + 12);
177 h->count = get_le32(buf + 16);
178 h->flags = get_le32(buf + 20);
179 return 1;
182 /* sets fd right after the header and returns 1 if found,
183 * otherwise returns 0
185 static int find_ape_tag(int fd, struct ape_header *h)
187 int pos;
189 if (lseek(fd, -HEADER_SIZE, SEEK_END) == -1)
190 return 0;
191 if (read_header(fd, h))
192 return 1;
194 pos = find_ape_tag_slow(fd);
195 if (pos == -1)
196 return 0;
197 if (lseek(fd, pos, SEEK_SET) == -1)
198 return 0;
199 return read_header(fd, h);
203 * All keys are ASCII and length is 2..255
205 * UTF-8: Artist, Album, Title, Genre
206 * Integer: Track (N or N/M)
207 * Date: Year (release), "Record Date"
209 * UTF-8 strings are NOT zero terminated.
211 * Also support "discnumber" (vorbis) and "disc" (non-standard)
213 static int parse_ape_tag(char *buf, const int size, const int count, struct keyval **comments)
215 struct keyval *c;
216 int i, n, pos;
218 c = xnew0(struct keyval, count + 1);
219 i = 0;
220 pos = 0;
221 for (n = 0; n < count; n++) {
222 uint32_t val_len, flags;
223 char *key, *val;
224 int max_key_len, key_len;
226 val_len = get_le32(buf + pos); pos += 4;
227 flags = get_le32(buf + pos); pos += 4;
229 max_key_len = size - pos - val_len - 1;
230 if (max_key_len < 0) {
231 /* corrupt */
232 break;
235 for (key_len = 0; key_len < max_key_len && buf[pos + key_len]; key_len++)
236 ; /* nothing */
237 if (buf[pos + key_len]) {
238 /* corrupt */
239 break;
242 if (!AF_IS_UTF8(flags)) {
243 /* ignore binary data */
244 pos += key_len + 1 + val_len;
245 continue;
248 key = xstrdup(buf + pos);
249 pos += key_len + 1;
251 /* should not be NUL-terminated */
252 val = xstrndup(buf + pos, val_len);
253 pos += val_len;
255 /* normalize key names */
256 if (!strcasecmp(key, "track")) {
257 free(key);
258 key = xstrdup("tracknumber");
259 } else if (!strcasecmp(key, "disc")) {
260 /* "disc" is totally non-standard but since there is
261 * "track" to "tracknumber" conversion this might make sense,
262 * at least this is totally harmless
264 free(key);
265 key = xstrdup("discnumber");
268 if (!is_interesting_key(key)) {
269 free(key);
270 free(val);
271 continue;
274 if (!strcasecmp(key, "tracknumber") || !strcasecmp(key, "discnumber")) {
275 fix_track_or_disc(val);
276 } else if (!strcasecmp(key, "year") || !strcasecmp(key, "record date")) {
277 /* Date format
279 * 1999-08-11 12:34:56
280 * 1999-08-11 12:34
281 * 1999-08-11
282 * 1999-08
283 * 1999
284 * 1999-W34 (week 34, totally crazy)
286 * convert to year, pl.c supports only years anyways
288 * FIXME: which one is the most common tag (year or record date)?
290 if (strlen(val) > 4)
291 val[4] = 0;
294 c[i].key = key;
295 c[i].val = val;
296 i++;
299 *comments = c;
300 return 0;
302 /* }}} */
304 static int mpc_open(struct input_plugin_data *ip_data)
306 struct mpc_private *priv;
308 priv = xnew0(struct mpc_private, 1);
310 priv->file_size = -1;
311 if (!ip_data->remote) {
312 priv->file_size = lseek(ip_data->fd, 0, SEEK_END);
313 lseek(ip_data->fd, 0, SEEK_SET);
316 /* set up an mpc_reader linked to our function implementations */
317 priv->reader.read = read_impl;
318 priv->reader.seek = seek_impl;
319 priv->reader.tell = tell_impl;
320 priv->reader.get_size = get_size_impl;
321 priv->reader.canseek = canseek_impl;
322 priv->reader.data = ip_data;
324 /* must be before mpc_streaminfo_read() */
325 ip_data->private = priv;
327 /* read file's streaminfo data */
328 mpc_streaminfo_init(&priv->info);
329 if (mpc_streaminfo_read(&priv->info, &priv->reader) != ERROR_CODE_OK) {
330 free(priv);
331 return -IP_ERROR_FILE_FORMAT;
334 /* instantiate a decoder with our file reader */
335 mpc_decoder_setup(&priv->decoder, &priv->reader);
336 if (!mpc_decoder_initialize(&priv->decoder, &priv->info)) {
337 free(priv);
338 return -IP_ERROR_FILE_FORMAT;
341 priv->samples_avail = 0;
342 priv->samples_pos = 0;
344 ip_data->sf = sf_rate(priv->info.sample_freq) | sf_channels(priv->info.channels) |
345 sf_bits(16) | sf_signed(1);
346 return 0;
349 static int mpc_close(struct input_plugin_data *ip_data)
351 struct mpc_private *priv = ip_data->private;
353 free(priv);
354 ip_data->private = NULL;
355 return 0;
358 static int scale(struct input_plugin_data *ip_data, char *buffer, int count)
360 struct mpc_private *priv = ip_data->private;
361 const MPC_SAMPLE_FORMAT *samples;
362 const int clip_min = -1 << (16 - 1);
363 const int clip_max = (1 << (16 - 1)) - 1;
364 const int float_scale = 1 << (16 - 1);
365 int i, sample_count;
367 /* number of bytes to 16-bit samples */
368 sample_count = count / 2;
369 if (sample_count > priv->samples_avail)
370 sample_count = priv->samples_avail;
372 /* scale 32-bit samples to 16-bit */
373 samples = priv->samples + priv->samples_pos;
374 for (i = 0; i < sample_count; i++) {
375 int val;
377 val = samples[i] * float_scale;
378 if (val < clip_min) {
379 val = clip_min;
380 } else if (val > clip_max) {
381 val = clip_max;
384 buffer[i * 2 + 0] = val & 0xff;
385 buffer[i * 2 + 1] = val >> 8;
388 priv->samples_pos += sample_count;
389 priv->samples_avail -= sample_count;
390 if (priv->samples_avail == 0)
391 priv->samples_pos = 0;
393 /* number of 16-bit samples to bytes */
394 return sample_count * 2;
397 static int mpc_read(struct input_plugin_data *ip_data, char *buffer, int count)
399 struct mpc_private *priv = ip_data->private;
401 if (priv->samples_avail == 0) {
402 uint32_t status = mpc_decoder_decode(&priv->decoder, priv->samples, NULL, NULL);
404 if (status == (uint32_t)(-1)) {
405 /* right ret val? */
406 return -IP_ERROR_ERRNO;
408 if (status == 0) {
409 /* EOF */
410 return 0;
413 /* status seems to be number of _frames_
414 * the api documentation is wrong
416 priv->samples_avail = status * priv->info.channels;
418 return scale(ip_data, buffer, count);
421 static int mpc_seek(struct input_plugin_data *ip_data, double offset)
423 struct mpc_private *priv = ip_data->private;
425 priv->samples_pos = 0;
426 priv->samples_avail = 0;
428 if (mpc_decoder_seek_seconds(&priv->decoder, offset))
429 return 0;
430 return -1;
433 static int mpc_read_comments(struct input_plugin_data *ip_data, struct keyval **comments)
435 int old_pos, fd = ip_data->fd;
436 struct ape_header h;
437 char *buf;
439 *comments = NULL;
441 /* save position */
442 old_pos = lseek(fd, 0, SEEK_CUR);
444 if (!find_ape_tag(fd, &h))
445 goto out;
447 if (AF_IS_FOOTER(h.flags)) {
448 /* seek back right after the header */
449 if (lseek(fd, -h.size, SEEK_CUR) == -1)
450 goto out;
453 /* ignore insane tags */
454 if (h.size > 1024 * 1024)
455 goto out;
457 buf = xnew(char, h.size);
458 if (read_all(fd, buf, h.size) == h.size)
459 parse_ape_tag(buf, h.size, h.count, comments);
460 free(buf);
461 out:
462 if (*comments == NULL)
463 *comments = xnew0(struct keyval, 1);
464 lseek(fd, old_pos, SEEK_SET);
465 return 0;
468 static int mpc_duration(struct input_plugin_data *ip_data)
470 struct mpc_private *priv = ip_data->private;
472 /* priv->info.pcm_samples seems to be number of frames
473 * priv->info.frames is _not_ pcm frames
475 return priv->info.pcm_samples / priv->info.sample_freq;
478 const struct input_plugin_ops ip_ops = {
479 .open = mpc_open,
480 .close = mpc_close,
481 .read = mpc_read,
482 .seek = mpc_seek,
483 .read_comments = mpc_read_comments,
484 .duration = mpc_duration
487 const char *const ip_extensions[] = { "mpc", "mpp", "mp+", NULL };
488 const char *const ip_mime_types[] = { "audio/x-musepack", NULL };