6 #include <FLAC/seekable_stream_decoder.h>
7 #include <FLAC/metadata.h>
14 #define UINT64_MAX ((uint64_t)-1)
17 /* Reduce typing. Namespaces are nice but FLAC API is fscking ridiculous. */
19 /* functions, types, enums */
20 #define F(s) FLAC__seekable_stream_decoder_ ## s
21 #define T(s) FLAC__SeekableStreamDecoder ## s
22 #define Dec FLAC__SeekableStreamDecoder
23 #define E(s) FLAC__SEEKABLE_STREAM_DECODER_ ## s
26 /* file/stream position and length */
34 unsigned int buf_size
;
35 unsigned int buf_wpos
;
36 unsigned int buf_rpos
;
38 struct keyval
*comments
;
42 unsigned int ignore_next_write
: 1;
45 static T(ReadStatus
) read_cb(const Dec
*dec
, unsigned char *buf
, unsigned *size
, void *data
)
47 struct input_plugin_data
*ip_data
= data
;
48 struct flac_private
*priv
= ip_data
->private;
53 d_print("EOF! EOF! EOF!\n");
54 return E(READ_STATUS_OK
);
57 return E(READ_STATUS_OK
);
59 rc
= read(ip_data
->fd
, buf
, *size
);
62 if (errno
== EINTR
|| errno
== EAGAIN
) {
63 /* FIXME: not sure how the flac decoder handles this */
64 d_print("interrupted\n");
65 return E(READ_STATUS_OK
);
67 return E(READ_STATUS_ERROR
);
70 d_print("%d != %d\n", rc
, *size
);
78 return E(READ_STATUS_OK
);
80 return E(READ_STATUS_OK
);
83 static T(SeekStatus
) seek_cb(const Dec
*dec
, uint64_t offset
, void *data
)
85 struct input_plugin_data
*ip_data
= data
;
86 struct flac_private
*priv
= ip_data
->private;
89 if (priv
->len
== UINT64_MAX
)
90 return E(SEEK_STATUS_ERROR
);
91 off
= lseek(ip_data
->fd
, offset
, SEEK_SET
);
93 return E(SEEK_STATUS_ERROR
);
96 return E(SEEK_STATUS_OK
);
99 static T(TellStatus
) tell_cb(const Dec
*dec
, uint64_t *offset
, void *data
)
101 struct input_plugin_data
*ip_data
= data
;
102 struct flac_private
*priv
= ip_data
->private;
106 return E(TELL_STATUS_OK
);
109 static T(LengthStatus
) length_cb(const Dec
*dec
, uint64_t *len
, void *data
)
111 struct input_plugin_data
*ip_data
= data
;
112 struct flac_private
*priv
= ip_data
->private;
115 if (ip_data
->remote
) {
116 return E(LENGTH_STATUS_ERROR
);
119 return E(LENGTH_STATUS_OK
);
122 static int eof_cb(const Dec
*dec
, void *data
)
124 struct input_plugin_data
*ip_data
= data
;
125 struct flac_private
*priv
= ip_data
->private;
133 #if defined(WORDS_BIGENDIAN)
135 static inline uint16_t LE16(uint16_t x
)
137 return (x
>> 8) | (x
<< 8);
140 static inline uint32_t LE32(uint32_t x
)
142 uint32_t x3
= x
<< 24;
143 uint32_t x0
= x
>> 24;
144 uint32_t x2
= (x
& 0xff00) << 8;
145 uint32_t x1
= (x
>> 8) & 0xff00;
146 return x3
| x2
| x1
| x0
;
156 static FLAC__StreamDecoderWriteStatus
write_cb(const Dec
*dec
, const FLAC__Frame
*frame
,
157 const int32_t * const *buf
, void *data
)
159 struct input_plugin_data
*ip_data
= data
;
160 struct flac_private
*priv
= ip_data
->private;
161 int frames
, bytes
, size
, channels
, bits
, depth
;
164 if (ip_data
->sf
== 0) {
165 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE
;
168 if (priv
->ignore_next_write
) {
169 priv
->ignore_next_write
= 0;
170 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE
;
173 frames
= frame
->header
.blocksize
;
174 channels
= sf_get_channels(ip_data
->sf
);
175 bits
= sf_get_bits(ip_data
->sf
);
176 bytes
= frames
* bits
/ 8 * channels
;
177 size
= priv
->buf_size
;
179 if (size
- priv
->buf_wpos
< bytes
) {
183 priv
->buf
= xrenew(char, priv
->buf
, size
);
184 priv
->buf_size
= size
;
187 depth
= frame
->header
.bits_per_sample
;
189 char *b
= priv
->buf
+ priv
->buf_wpos
;
191 for (i
= 0; i
< frames
; i
++) {
192 for (ch
= 0; ch
< channels
; ch
++)
195 } else if (depth
== 16) {
196 int16_t *b
= (int16_t *)(priv
->buf
+ priv
->buf_wpos
);
198 for (i
= 0; i
< frames
; i
++) {
199 for (ch
= 0; ch
< channels
; ch
++)
200 b
[j
++] = LE16(buf
[ch
][i
]);
202 } else if (depth
== 32) {
203 int32_t *b
= (int32_t *)(priv
->buf
+ priv
->buf_wpos
);
205 for (i
= 0; i
< frames
; i
++) {
206 for (ch
= 0; ch
< channels
; ch
++)
207 b
[j
++] = LE32(buf
[ch
][i
]);
209 } else if (depth
== 12) { /* -> 16 */
210 int16_t *b
= (int16_t *)(priv
->buf
+ priv
->buf_wpos
);
212 for (i
= 0; i
< frames
; i
++) {
213 for (ch
= 0; ch
< channels
; ch
++)
214 b
[j
++] = LE16(buf
[ch
][i
] << 4);
216 } else if (depth
== 20) { /* -> 32 */
217 int32_t *b
= (int32_t *)(priv
->buf
+ priv
->buf_wpos
);
219 for (i
= 0; i
< frames
; i
++) {
220 for (ch
= 0; ch
< channels
; ch
++)
221 b
[j
++] = LE32(buf
[ch
][i
] << 12);
223 } else if (depth
== 24) { /* -> 32 */
224 int32_t *b
= (int32_t *)(priv
->buf
+ priv
->buf_wpos
);
226 for (i
= 0; i
< frames
; i
++) {
227 for (ch
= 0; ch
< channels
; ch
++)
228 b
[j
++] = LE32(buf
[ch
][i
] << 8);
231 d_print("bits per sample changed to %d\n", depth
);
234 priv
->buf_wpos
+= bytes
;
235 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE
;
238 /* You should make a copy of metadata with FLAC__metadata_object_clone() if you will
239 * need it elsewhere. Since metadata blocks can potentially be large, by
240 * default the decoder only calls the metadata callback for the STREAMINFO
241 * block; you can instruct the decoder to pass or filter other blocks with
242 * FLAC__stream_decoder_set_metadata_*() calls.
244 static void metadata_cb(const Dec
*dec
, const FLAC__StreamMetadata
*metadata
, void *data
)
246 struct input_plugin_data
*ip_data
= data
;
247 struct flac_private
*priv
= ip_data
->private;
249 switch (metadata
->type
) {
250 case FLAC__METADATA_TYPE_STREAMINFO
:
252 const FLAC__StreamMetadata_StreamInfo
*si
= &metadata
->data
.stream_info
;
255 switch (si
->bits_per_sample
) {
259 bits
= si
->bits_per_sample
;
270 ip_data
->sf
= sf_rate(si
->sample_rate
) |
273 sf_channels(si
->channels
);
274 if (!ip_data
->remote
&& si
->total_samples
)
275 priv
->duration
= si
->total_samples
/ si
->sample_rate
;
278 case FLAC__METADATA_TYPE_VORBIS_COMMENT
:
279 d_print("VORBISCOMMENT\n");
280 if (priv
->comments
) {
281 d_print("Ignoring\n");
286 nr
= metadata
->data
.vorbis_comment
.num_comments
;
287 c
= xnew0(struct keyval
, nr
+ 1);
288 for (s
= 0, d
= 0; s
< nr
; s
++) {
291 /* until you have finished reading this function name
292 * you have already forgot WTF you're doing */
293 if (!FLAC__metadata_object_vorbiscomment_entry_to_name_value_pair(
294 metadata
->data
.vorbis_comment
.comments
[s
],
298 if (!is_interesting_key(key
)) {
303 if (!strcasecmp(key
, "tracknumber") || !strcasecmp(key
, "discnumber"))
304 fix_track_or_disc(val
);
306 d_print("comment: '%s=%s'\n", key
, val
);
315 d_print("something else\n");
320 static void error_cb(const Dec
*dec
, FLAC__StreamDecoderErrorStatus status
, void *data
)
322 static const char *strings
[3] = {
327 const char *str
= "unknown error";
329 if (status
>= 0 && status
< 3)
330 str
= strings
[status
];
331 d_print("%d %s\n", status
, str
);
334 static void free_priv(struct input_plugin_data
*ip_data
)
336 struct flac_private
*priv
= ip_data
->private;
339 F(finish
)(priv
->dec
);
340 F(delete)(priv
->dec
);
342 comments_free(priv
->comments
);
345 ip_data
->private = NULL
;
349 static int flac_open(struct input_plugin_data
*ip_data
)
351 struct flac_private
*priv
;
356 return -IP_ERROR_INTERNAL
;
358 priv
= xnew0(struct flac_private
, 1);
361 if (ip_data
->remote
) {
362 priv
->len
= UINT64_MAX
;
364 off_t off
= lseek(ip_data
->fd
, 0, SEEK_END
);
366 if (off
== -1 || lseek(ip_data
->fd
, 0, SEEK_SET
) == -1) {
372 return -IP_ERROR_ERRNO
;
376 ip_data
->private = priv
;
378 F(set_read_callback
)(dec
, read_cb
);
379 F(set_seek_callback
)(dec
, seek_cb
);
380 F(set_tell_callback
)(dec
, tell_cb
);
381 F(set_length_callback
)(dec
, length_cb
);
382 F(set_eof_callback
)(dec
, eof_cb
);
383 F(set_write_callback
)(dec
, write_cb
);
384 F(set_metadata_callback
)(dec
, metadata_cb
);
385 F(set_error_callback
)(dec
, error_cb
);
386 F(set_client_data
)(dec
, ip_data
);
388 /* FLAC__METADATA_TYPE_STREAMINFO already accepted */
389 F(set_metadata_respond
)(dec
, FLAC__METADATA_TYPE_VORBIS_COMMENT
);
391 if (F(init
)(dec
) != E(OK
)) {
394 d_print("init failed\n");
395 F(delete)(priv
->dec
);
397 ip_data
->private = NULL
;
399 return -IP_ERROR_ERRNO
;
403 while (priv
->buf_wpos
== 0 && !priv
->eof
) {
404 if (!F(process_single
)(priv
->dec
)) {
406 return -IP_ERROR_ERRNO
;
412 return -IP_ERROR_FILE_FORMAT
;
414 if (!sf_get_bits(ip_data
->sf
)) {
416 return -IP_ERROR_SAMPLE_FORMAT
;
419 d_print("sr: %d, ch: %d, bits: %d\n",
420 sf_get_rate(ip_data
->sf
),
421 sf_get_channels(ip_data
->sf
),
422 sf_get_bits(ip_data
->sf
));
426 static int flac_close(struct input_plugin_data
*ip_data
)
432 static int flac_read(struct input_plugin_data
*ip_data
, char *buffer
, int count
)
434 struct flac_private
*priv
= ip_data
->private;
436 int libflac_suck_count
= 0;
439 int old_pos
= priv
->buf_wpos
;
441 avail
= priv
->buf_wpos
- priv
->buf_rpos
;
447 if (!F(process_single
)(priv
->dec
)) {
448 d_print("process_single failed\n");
451 if (old_pos
== priv
->buf_wpos
) {
452 libflac_suck_count
++;
454 libflac_suck_count
= 0;
456 if (libflac_suck_count
> 5) {
457 d_print("libflac sucks\n");
464 memcpy(buffer
, priv
->buf
+ priv
->buf_rpos
, count
);
465 priv
->buf_rpos
+= count
;
466 BUG_ON(priv
->buf_rpos
> priv
->buf_wpos
);
467 if (priv
->buf_rpos
== priv
->buf_wpos
) {
474 /* Flush the input and seek to an absolute sample. Decoding will resume at the
475 * given sample. Note that because of this, the next write callback may contain
478 static int flac_seek(struct input_plugin_data
*ip_data
, double offset
)
480 struct flac_private
*priv
= ip_data
->private;
483 sample
= (uint64_t)(offset
* (double)sf_get_rate(ip_data
->sf
) + 0.5);
484 if (!F(seek_absolute
)(priv
->dec
, sample
)) {
485 return -IP_ERROR_ERRNO
;
487 priv
->ignore_next_write
= 1;
493 static int flac_read_comments(struct input_plugin_data
*ip_data
, struct keyval
**comments
)
495 struct flac_private
*priv
= ip_data
->private;
497 if (priv
->comments
) {
498 *comments
= comments_dup(priv
->comments
);
500 *comments
= xnew0(struct keyval
, 1);
505 static int flac_duration(struct input_plugin_data
*ip_data
)
507 struct flac_private
*priv
= ip_data
->private;
509 return priv
->duration
;
512 const struct input_plugin_ops ip_ops
= {
517 .read_comments
= flac_read_comments
,
518 .duration
= flac_duration
521 const char * const ip_extensions
[] = { "flac", "fla", NULL
};
522 const char * const ip_mime_types
[] = { NULL
};