Tab complete only interesting files
[cmus.git] / flac.c
blob3c6b4ae264068be5b48043a27d5d8271d31da3b0
1 /*
2 * Copyright 2005 Timo Hirvonen
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * 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
17 * 02111-1307, USA.
20 #include <ip.h>
21 #include <comment.h>
22 #include <xmalloc.h>
23 #include <debug.h>
25 #include <FLAC/seekable_stream_decoder.h>
26 #include <FLAC/metadata.h>
27 #include <inttypes.h>
28 #include <sys/types.h>
29 #include <unistd.h>
30 #include <errno.h>
32 #ifndef UINT64_MAX
33 #define UINT64_MAX ((uint64_t)-1)
34 #endif
36 /* Reduce typing. Namespaces are nice but FLAC API is fscking ridiculous. */
38 /* functions, types, enums */
39 #define F(s) FLAC__seekable_stream_decoder_ ## s
40 #define T(s) FLAC__SeekableStreamDecoder ## s
41 #define Dec FLAC__SeekableStreamDecoder
42 #define E(s) FLAC__SEEKABLE_STREAM_DECODER_ ## s
44 struct flac_private {
45 /* file/stream position and length */
46 uint64_t pos;
47 uint64_t len;
49 Dec *dec;
51 /* PCM data */
52 char *buf;
53 unsigned int buf_size;
54 unsigned int buf_wpos;
55 unsigned int buf_rpos;
57 struct keyval *comments;
58 int duration;
60 unsigned int eof : 1;
61 unsigned int ignore_next_write : 1;
64 static T(ReadStatus) read_cb(const Dec *dec, unsigned char *buf, unsigned *size, void *data)
66 struct input_plugin_data *ip_data = data;
67 struct flac_private *priv = ip_data->private;
68 int rc;
70 if (priv->eof) {
71 *size = 0;
72 d_print("EOF! EOF! EOF!\n");
73 return E(READ_STATUS_OK);
75 if (*size == 0)
76 return E(READ_STATUS_OK);
78 rc = read(ip_data->fd, buf, *size);
79 if (rc == -1) {
80 *size = 0;
81 if (errno == EINTR || errno == EAGAIN) {
82 /* FIXME: not sure how the flac decoder handles this */
83 d_print("interrupted\n");
84 return E(READ_STATUS_OK);
86 return E(READ_STATUS_ERROR);
88 if (*size != rc) {
89 d_print("%d != %d\n", rc, *size);
91 priv->pos += rc;
92 *size = rc;
93 if (rc == 0) {
94 /* never reached! */
95 priv->eof = 1;
96 d_print("EOF\n");
97 return E(READ_STATUS_OK);
99 return E(READ_STATUS_OK);
102 static T(SeekStatus) seek_cb(const Dec *dec, uint64_t offset, void *data)
104 struct input_plugin_data *ip_data = data;
105 struct flac_private *priv = ip_data->private;
106 off_t off;
108 if (priv->len == UINT64_MAX)
109 return E(SEEK_STATUS_ERROR);
110 off = lseek(ip_data->fd, offset, SEEK_SET);
111 if (off == -1) {
112 return E(SEEK_STATUS_ERROR);
114 priv->pos = off;
115 return E(SEEK_STATUS_OK);
118 static T(TellStatus) tell_cb(const Dec *dec, uint64_t *offset, void *data)
120 struct input_plugin_data *ip_data = data;
121 struct flac_private *priv = ip_data->private;
123 d_print("\n");
124 *offset = priv->pos;
125 return E(TELL_STATUS_OK);
128 static T(LengthStatus) length_cb(const Dec *dec, uint64_t *len, void *data)
130 struct input_plugin_data *ip_data = data;
131 struct flac_private *priv = ip_data->private;
133 d_print("\n");
134 if (ip_data->remote) {
135 return E(LENGTH_STATUS_ERROR);
137 *len = priv->len;
138 return E(LENGTH_STATUS_OK);
141 static int eof_cb(const Dec *dec, void *data)
143 struct input_plugin_data *ip_data = data;
144 struct flac_private *priv = ip_data->private;
146 d_print("%d\n", priv->eof);
147 return priv->eof;
150 static FLAC__StreamDecoderWriteStatus write_cb(const Dec *dec, const FLAC__Frame *frame,
151 const int32_t * const *buf, void *data)
153 struct input_plugin_data *ip_data = data;
154 struct flac_private *priv = ip_data->private;
155 int samples, bytes, size, channels, bits;
157 if (ip_data->sf == 0) {
158 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
161 if (priv->ignore_next_write) {
162 priv->ignore_next_write = 0;
163 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
166 samples = frame->header.blocksize;
167 channels = sf_get_channels(ip_data->sf);
168 bits = sf_get_bits(ip_data->sf);
169 bytes = samples * frame->header.bits_per_sample / 8 * channels;
170 size = priv->buf_size;
172 if (size - priv->buf_wpos < bytes) {
173 if (size < bytes)
174 size = bytes;
175 size *= 2;
176 priv->buf = xrenew(char, priv->buf, size);
177 priv->buf_size = size;
180 if (bits == 8) {
181 char *b = priv->buf + priv->buf_wpos;
182 int ch, i, j = 0;
184 for (i = 0; i < samples; i++) {
185 for (ch = 0; ch < channels; ch++)
186 b[j++] = buf[ch][i];
188 } else if (bits == 16) {
189 int16_t *b = (int16_t *)(priv->buf + priv->buf_wpos);
190 int ch, i, j = 0;
192 for (i = 0; i < samples; i++) {
193 for (ch = 0; ch < channels; ch++)
194 b[j++] = buf[ch][i];
196 } else if (bits == 24) {
197 char *b = (char *)(priv->buf + priv->buf_wpos);
198 int ch, i, j = 0;
200 /* NOT TESTED! */
201 for (i = 0; i < samples; i++) {
202 for (ch = 0; ch < channels; ch++) {
203 int32_t sample = buf[ch][i];
205 /* FIXME: doesn't work with bin-endian machines? */
206 b[j++] = sample & 0xff; sample >>= 8;
207 b[j++] = sample & 0xff; sample >>= 8;
208 b[j++] = sample & 0xff;
211 } else { /* 32 */
212 int32_t *b = (int32_t *)(priv->buf + priv->buf_wpos);
213 int ch, i, j = 0;
215 /* NOT TESTED! */
216 for (i = 0; i < samples; i++) {
217 for (ch = 0; ch < channels; ch++)
218 b[j++] = buf[ch][i];
222 priv->buf_wpos += bytes;
223 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
226 /* You should make a copy of metadata with FLAC__metadata_object_clone() if you will
227 * need it elsewhere. Since metadata blocks can potentially be large, by
228 * default the decoder only calls the metadata callback for the STREAMINFO
229 * block; you can instruct the decoder to pass or filter other blocks with
230 * FLAC__stream_decoder_set_metadata_*() calls.
232 static void metadata_cb(const Dec *dec, const FLAC__StreamMetadata *metadata, void *data)
234 struct input_plugin_data *ip_data = data;
235 struct flac_private *priv = ip_data->private;
237 switch (metadata->type) {
238 case FLAC__METADATA_TYPE_STREAMINFO:
240 const FLAC__StreamMetadata_StreamInfo *si = &metadata->data.stream_info;
242 d_print("STREAMINFO\n");
243 ip_data->sf = sf_rate(si->sample_rate) | sf_bits(si->bits_per_sample) |
244 sf_signed(1) | sf_channels(si->channels);
245 if (!ip_data->remote && si->total_samples)
246 priv->duration = si->total_samples / si->sample_rate;
248 break;
249 case FLAC__METADATA_TYPE_VORBIS_COMMENT:
250 d_print("VORBISCOMMENT\n");
251 if (priv->comments) {
252 d_print("Ignoring\n");
253 } else {
254 struct keyval *c;
255 int s, d, nr;
257 nr = metadata->data.vorbis_comment.num_comments;
258 c = xnew0(struct keyval, nr + 1);
259 for (s = 0, d = 0; s < nr; s++) {
260 char *key, *val;
262 /* until you have finished reading this function name
263 * you have already forgot WTF you're doing */
264 if (!FLAC__metadata_object_vorbiscomment_entry_to_name_value_pair(
265 metadata->data.vorbis_comment.comments[s],
266 &key, &val))
267 continue;
269 if (!is_interesting_key(key)) {
270 free(key);
271 free(val);
272 continue;
274 if (!strcasecmp(key, "tracknumber") || !strcasecmp(key, "discnumber"))
275 fix_track_or_disc(val);
277 d_print("comment: '%s=%s'\n", key, val);
278 c[d].key = key;
279 c[d].val = val;
280 d++;
282 priv->comments = c;
284 break;
285 default:
286 d_print("something else\n");
287 break;
291 static void error_cb(const Dec *dec, FLAC__StreamDecoderErrorStatus status, void *data)
293 /* struct input_plugin_data *ip_data = data; */
294 /* struct flac_private *priv = ip_data->private; */
296 d_print("\n");
299 static int flac_open(struct input_plugin_data *ip_data)
301 struct flac_private *priv;
302 Dec *dec;
304 dec = F(new)();
305 if (dec == NULL)
306 return -IP_ERROR_INTERNAL;
308 priv = xnew(struct flac_private, 1);
309 priv->dec = dec;
310 priv->buf = NULL;
311 priv->buf_size = 0;
312 priv->buf_wpos = 0;
313 priv->buf_rpos = 0;
314 priv->eof = 0;
315 priv->ignore_next_write = 0;
316 priv->pos = 0;
317 priv->comments = NULL;
318 priv->duration = -1;
319 if (ip_data->remote) {
320 priv->len = UINT64_MAX;
321 } else {
322 off_t off = lseek(ip_data->fd, 0, SEEK_END);
324 if (off == -1 || lseek(ip_data->fd, 0, SEEK_SET) == -1) {
325 int save = errno;
327 F(delete)(dec);
328 free(priv);
329 errno = save;
330 return -IP_ERROR_ERRNO;
332 priv->len = off;
334 ip_data->private = priv;
336 F(set_read_callback)(dec, read_cb);
337 F(set_seek_callback)(dec, seek_cb);
338 F(set_tell_callback)(dec, tell_cb);
339 F(set_length_callback)(dec, length_cb);
340 F(set_eof_callback)(dec, eof_cb);
341 F(set_write_callback)(dec, write_cb);
342 F(set_metadata_callback)(dec, metadata_cb);
343 F(set_error_callback)(dec, error_cb);
344 F(set_client_data)(dec, ip_data);
346 /* FLAC__METADATA_TYPE_STREAMINFO already accepted */
347 F(set_metadata_respond)(dec, FLAC__METADATA_TYPE_VORBIS_COMMENT);
349 if (F(init)(dec) != E(OK)) {
350 int save = errno;
352 d_print("init failed\n");
353 F(delete)(priv->dec);
354 free(priv);
355 ip_data->private = NULL;
356 errno = save;
357 return -IP_ERROR_ERRNO;
360 ip_data->sf = 0;
361 while (priv->buf_wpos == 0 && !priv->eof) {
362 if (!F(process_single)(priv->dec)) {
363 int save = errno;
365 d_print("process_single failed\n");
366 F(finish)(priv->dec);
367 F(delete)(priv->dec);
368 if (priv->comments)
369 free(priv->comments);
370 free(priv->buf);
371 free(priv);
372 ip_data->private = NULL;
373 errno = save;
374 return -IP_ERROR_ERRNO;
377 BUG_ON(ip_data->sf == 0);
378 d_print("sr: %d, ch: %d, bits: %d\n", sf_get_rate(ip_data->sf),
379 sf_get_channels(ip_data->sf), sf_get_bits(ip_data->sf));
380 return 0;
383 static int flac_close(struct input_plugin_data *ip_data)
385 struct flac_private *priv = ip_data->private;
387 F(finish)(priv->dec);
388 F(delete)(priv->dec);
389 if (priv->comments)
390 comments_free(priv->comments);
391 free(priv->buf);
392 free(priv);
393 ip_data->private = NULL;
394 return 0;
397 static int flac_read(struct input_plugin_data *ip_data, char *buffer, int count)
399 struct flac_private *priv = ip_data->private;
400 int avail;
401 int libflac_suck_count = 0;
403 while (1) {
404 int old_pos = priv->buf_wpos;
406 avail = priv->buf_wpos - priv->buf_rpos;
407 BUG_ON(avail < 0);
408 if (avail > 0)
409 break;
410 if (priv->eof)
411 return 0;
412 if (!F(process_single)(priv->dec)) {
413 d_print("process_single failed\n");
414 return -1;
416 if (old_pos == priv->buf_wpos) {
417 libflac_suck_count++;
418 } else {
419 libflac_suck_count = 0;
421 if (libflac_suck_count > 5) {
422 d_print("libflac sucks\n");
423 priv->eof = 1;
424 return 0;
427 if (count > avail)
428 count = avail;
429 memcpy(buffer, priv->buf + priv->buf_rpos, count);
430 priv->buf_rpos += count;
431 BUG_ON(priv->buf_rpos > priv->buf_wpos);
432 if (priv->buf_rpos == priv->buf_wpos) {
433 priv->buf_rpos = 0;
434 priv->buf_wpos = 0;
436 return count;
439 /* Flush the input and seek to an absolute sample. Decoding will resume at the
440 * given sample. Note that because of this, the next write callback may contain
441 * a partial block.
443 static int flac_seek(struct input_plugin_data *ip_data, double offset)
445 struct flac_private *priv = ip_data->private;
446 uint64_t sample;
448 if (ip_data->remote)
449 return -IP_ERROR_ERRNO;
451 sample = (uint64_t)(offset * (double)sf_get_rate(ip_data->sf) + 0.5);
452 if (!F(seek_absolute)(priv->dec, sample)) {
453 return -IP_ERROR_ERRNO;
455 priv->ignore_next_write = 1;
456 priv->buf_rpos = 0;
457 priv->buf_wpos = 0;
458 return 0;
461 static int flac_read_comments(struct input_plugin_data *ip_data, struct keyval **comments)
463 struct flac_private *priv = ip_data->private;
465 if (priv->comments) {
466 *comments = comments_dup(priv->comments);
467 } else {
468 *comments = xnew0(struct keyval, 1);
470 return 0;
473 static int flac_duration(struct input_plugin_data *ip_data)
475 struct flac_private *priv = ip_data->private;
477 return priv->duration;
480 const struct input_plugin_ops ip_ops = {
481 .open = flac_open,
482 .close = flac_close,
483 .read = flac_read,
484 .seek = flac_seek,
485 .read_comments = flac_read_comments,
486 .duration = flac_duration
489 const char * const ip_extensions[] = { "flac", "fla", NULL };
490 const char * const ip_mime_types[] = { NULL };