2 * Copyright 2006 Chun-Yu Shei <cshei AT cs.indiana.edu>
4 * Cleaned up by Timo Hirvonen <tihirvon@gmail.com>
11 #include <read_wrapper.h>
13 #include <mpcdec/mpcdec.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)
26 /* 1000 or 2000 (1.0, 2.0) */
29 /* tag size (header + tags, excluding footer) */
35 /* global flags for each tag
36 * there are also private flags for every tag
37 * NOTE: 0 for version 1.0 (1000)
43 #define AF_IS_UTF8(f) (((f) & 6) == 0)
44 #define AF_IS_FOOTER(f) (((f) & (1 << 29)) == 0)
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);
78 static mpc_int32_t
read_impl(void *data
, void *ptr
, mpc_int32_t size
)
80 struct input_plugin_data
*ip_data
= data
;
83 rc
= read_wrapper(ip_data
, ptr
, size
);
93 static mpc_bool_t
seek_impl(void *data
, mpc_int32_t offset
)
95 struct input_plugin_data
*ip_data
= data
;
98 rc
= lseek(ip_data
->fd
, offset
, SEEK_SET
);
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
;
129 /* returns position of APE header or -1 if not found */
130 static int find_ape_tag_slow(int fd
)
136 /* seek to start of file */
137 if (lseek(fd
, pos
, SEEK_SET
) == -1)
141 int i
, got
= read(fd
, buf
, sizeof(buf
));
144 if (errno
== EAGAIN
|| errno
== EINTR
)
151 for (i
= 0; i
< got
; i
++) {
152 if (buf
[i
] != preamble
[match
]) {
158 if (match
== PREAMBLE_SIZE
)
159 return pos
+ i
+ 1 - PREAMBLE_SIZE
;
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
))
172 if (memcmp(buf
, preamble
, PREAMBLE_SIZE
))
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);
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
)
189 if (lseek(fd
, -HEADER_SIZE
, SEEK_END
) == -1)
191 if (read_header(fd
, h
))
194 pos
= find_ape_tag_slow(fd
);
197 if (lseek(fd
, pos
, SEEK_SET
) == -1)
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
)
218 c
= xnew0(struct keyval
, count
+ 1);
221 for (n
= 0; n
< count
; n
++) {
222 uint32_t val_len
, flags
;
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) {
235 for (key_len
= 0; key_len
< max_key_len
&& buf
[pos
+ key_len
]; key_len
++)
237 if (buf
[pos
+ key_len
]) {
242 if (!AF_IS_UTF8(flags
)) {
243 /* ignore binary data */
244 pos
+= key_len
+ 1 + val_len
;
248 key
= xstrdup(buf
+ pos
);
251 /* should not be NUL-terminated */
252 val
= xstrndup(buf
+ pos
, val_len
);
255 /* normalize key names */
256 if (!strcasecmp(key
, "track")) {
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
265 key
= xstrdup("discnumber");
268 if (!is_interesting_key(key
)) {
274 if (!strcasecmp(key
, "tracknumber") || !strcasecmp(key
, "discnumber")) {
275 fix_track_or_disc(val
);
276 } else if (!strcasecmp(key
, "year") || !strcasecmp(key
, "record date")) {
279 * 1999-08-11 12:34:56
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)?
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
) {
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
)) {
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);
349 static int mpc_close(struct input_plugin_data
*ip_data
)
351 struct mpc_private
*priv
= ip_data
->private;
354 ip_data
->private = NULL
;
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);
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
++) {
377 val
= samples
[i
] * float_scale
;
378 if (val
< clip_min
) {
380 } else if (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)) {
406 return -IP_ERROR_ERRNO
;
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
))
433 static int mpc_read_comments(struct input_plugin_data
*ip_data
, struct keyval
**comments
)
435 int old_pos
, fd
= ip_data
->fd
;
442 old_pos
= lseek(fd
, 0, SEEK_CUR
);
444 if (!find_ape_tag(fd
, &h
))
447 if (AF_IS_FOOTER(h
.flags
)) {
448 /* seek back right after the header */
449 if (lseek(fd
, -h
.size
, SEEK_CUR
) == -1)
453 /* ignore insane tags */
454 if (h
.size
> 1024 * 1024)
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
);
462 if (*comments
== NULL
)
463 *comments
= xnew0(struct keyval
, 1);
464 lseek(fd
, old_pos
, SEEK_SET
);
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
= {
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
};