2 * Copyright (c) 2022 Omar Polo <op@omarpolo.com>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
27 #include <FLAC/stream_decoder.h>
33 FLAC__StreamDecoder *decoder;
38 sample_seek(struct write_args *wa, int64_t seek)
42 ok = FLAC__stream_decoder_seek_absolute(wa->decoder, seek);
50 static FLAC__StreamDecoderWriteStatus
51 writecb(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame,
52 const int32_t * const *src, void *data)
54 struct write_args *wa = data;
55 static uint8_t buf[BUFSIZ];
60 bps = frame->header.bits_per_sample;
61 chans = frame->header.channels;
63 for (i = 0, len = 0; i < frame->header.blocksize; ++i) {
64 if (len + 4*chans >= sizeof(buf)) {
65 if (!play(buf, len, &seek))
68 if (sample_seek(wa, seek))
76 for (c = 0; c < chans; ++c) {
79 buf[len++] = src[c][i] & 0xff;
82 buf[len++] = src[c][i] & 0xff;
83 buf[len++] = (src[c][i] >> 8) & 0xff;
87 buf[len++] = src[c][i] & 0xff;
88 buf[len++] = (src[c][i] >> 8) & 0xff;
89 buf[len++] = (src[c][i] >> 16) & 0xff;
90 buf[len++] = (src[c][i] >> 24) & 0xff;
93 log_warnx("unsupported flac bps=%d", bps);
99 if (len != 0 && !play(buf, len, &seek))
102 if (seek != -1 && !sample_seek(wa, seek))
105 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
107 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
111 metacb(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *meta,
114 uint32_t sample_rate;
117 if (meta->type == FLAC__METADATA_TYPE_STREAMINFO) {
118 bits = meta->data.stream_info.bits_per_sample;
119 sample_rate = meta->data.stream_info.sample_rate;
120 channels = meta->data.stream_info.channels;
122 if (player_setup(bits, sample_rate, channels) == -1)
123 err(1, "player_setup");
125 player_setduration(meta->data.stream_info.total_samples);
130 errcb(const FLAC__StreamDecoder *decoder,
131 FLAC__StreamDecoderErrorStatus status, void *data)
133 log_warnx("flac error: %s",
134 FLAC__StreamDecoderErrorStatusString[status]);
138 play_flac(int fd, const char **errstr)
141 struct write_args wa;
143 FLAC__StreamDecoder *decoder = NULL;
144 FLAC__StreamDecoderInitStatus init_status;
146 if ((f = fdopen(fd, "r")) == NULL) {
147 *errstr = "fdopen failed";
152 decoder = FLAC__stream_decoder_new();
153 if (decoder == NULL) {
154 *errstr = "FLAC__stream_decoder_new() failed";
159 FLAC__stream_decoder_set_md5_checking(decoder, 1);
161 memset(&wa, 0, sizeof(wa));
162 wa.decoder = decoder;
164 init_status = FLAC__stream_decoder_init_FILE(decoder, f, writecb,
166 if (init_status != FLAC__STREAM_DECODER_INIT_STATUS_OK)
167 errx(1, "flac decoder: %s",
168 FLAC__StreamDecoderInitStatusString[init_status]);
170 ok = FLAC__stream_decoder_process_until_end_of_stream(decoder);
172 s = FLAC__stream_decoder_get_state(decoder);
173 FLAC__stream_decoder_delete(decoder);
176 if (s == FLAC__STREAM_DECODER_ABORTED && !wa.seek_failed)
178 else if (!ok && !wa.seek_failed) {
179 *errstr = "flac decoding error";