2 * Copyright (c) 2022 Omar Polo <op@openbsd.org>
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.
17 #include <sys/types.h>
18 #include <sys/queue.h>
31 #include <FLAC/stream_decoder.h>
37 FLAC__StreamDecoder *decoder;
42 sample_seek(struct write_args *wa, int64_t seek)
46 ok = FLAC__stream_decoder_seek_absolute(wa->decoder, seek);
54 static FLAC__StreamDecoderWriteStatus
55 writecb(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame,
56 const int32_t * const *src, void *data)
58 struct write_args *wa = data;
59 static uint8_t buf[BUFSIZ];
64 bps = frame->header.bits_per_sample;
65 chans = frame->header.channels;
67 for (i = 0, len = 0; i < frame->header.blocksize; ++i) {
68 if (len + 4*chans >= sizeof(buf)) {
69 if (!play(buf, len, &seek))
72 if (sample_seek(wa, seek))
80 for (c = 0; c < chans; ++c) {
83 buf[len++] = src[c][i] & 0xff;
86 buf[len++] = src[c][i] & 0xff;
87 buf[len++] = (src[c][i] >> 8) & 0xff;
91 buf[len++] = src[c][i] & 0xff;
92 buf[len++] = (src[c][i] >> 8) & 0xff;
93 buf[len++] = (src[c][i] >> 16) & 0xff;
94 buf[len++] = (src[c][i] >> 24) & 0xff;
97 log_warnx("unsupported flac bps=%d", bps);
103 if (len != 0 && !play(buf, len, &seek))
106 if (seek != -1 && !sample_seek(wa, seek))
109 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
111 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
115 metacb(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *meta,
118 uint32_t sample_rate;
121 if (meta->type == FLAC__METADATA_TYPE_STREAMINFO) {
122 bits = meta->data.stream_info.bits_per_sample;
123 sample_rate = meta->data.stream_info.sample_rate;
124 channels = meta->data.stream_info.channels;
126 if (player_setup(bits, sample_rate, channels) == -1)
127 err(1, "player_setup");
129 player_setduration(meta->data.stream_info.total_samples);
134 errcb(const FLAC__StreamDecoder *decoder,
135 FLAC__StreamDecoderErrorStatus status, void *data)
137 log_warnx("flac error: %s",
138 FLAC__StreamDecoderErrorStatusString[status]);
142 play_flac(int fd, const char **errstr)
145 struct write_args wa;
147 FLAC__StreamDecoder *decoder = NULL;
148 FLAC__StreamDecoderInitStatus init_status;
150 if ((f = fdopen(fd, "r")) == NULL)
153 decoder = FLAC__stream_decoder_new();
155 err(1, "flac stream decoder");
157 FLAC__stream_decoder_set_md5_checking(decoder, 1);
159 memset(&wa, 0, sizeof(wa));
160 wa.decoder = decoder;
162 init_status = FLAC__stream_decoder_init_FILE(decoder, f, writecb,
164 if (init_status != FLAC__STREAM_DECODER_INIT_STATUS_OK)
165 errx(1, "flac decoder: %s",
166 FLAC__StreamDecoderInitStatusString[init_status]);
168 ok = FLAC__stream_decoder_process_until_end_of_stream(decoder);
170 s = FLAC__stream_decoder_get_state(decoder);
171 FLAC__stream_decoder_delete(decoder);
174 if (s == FLAC__STREAM_DECODER_ABORTED && !wa.seek_failed)
176 else if (!ok && !wa.seek_failed) {
177 *errstr = "flac decoding error";