1 /*
2 DeaDBeeF - The Ultimate Music Player
3 Copyright (C) 2009-2013 Alexey Yakovenko <waker@users.sourceforge.net>
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8
9 - Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11
12 - Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15
16 - Neither the name of the DeaDBeeF Player nor the names of its
17 contributors may be used to endorse or promote products derived from
18 this software without specific prior written permission.
19
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
24 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #ifdef HAVE_CONFIG_H
34 #include <config.h>
35 #endif
36 #include <string.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <stdbool.h>
40 #include <math.h>
41 #include <FLAC/stream_decoder.h>
42 #include <FLAC/metadata.h>
43 #include <limits.h>
44 #include "../../deadbeef.h"
45 #include "../artwork/artwork.h"
46 #include "../liboggedit/oggedit.h"
47 #include "../../strdupa.h"
48
49 static DB_decoder_t plugin;
50 static DB_functions_t *deadbeef;
51
52 //#define trace(...) { fprintf(stderr, __VA_ARGS__); }
53 #define trace(fmt,...)
54
55 #define min(x,y) ((x)<(y)?(x):(y))
56 #define max(x,y) ((x)>(y)?(x):(y))
57
58 #define BUFFERSIZE 100000
59
60 typedef struct {
61 DB_fileinfo_t info;
62 FLAC__StreamDecoder *decoder;
63 char *buffer;
64 int remaining; // bytes remaining in buffer from last read
65 int64_t startsample;
66 int64_t endsample;
67 int64_t currentsample;
68 int64_t totalsamples;
69 int flac_critical_error;
70 int init_stop_decoding;
71 int set_bitrate;
72 DB_FILE *file;
73
74 // used only on insert
75 ddb_playlist_t *plt;
76 DB_playItem_t *after;
77 DB_playItem_t *last;
78 DB_playItem_t *it;
79 const char *fname;
80 int bitrate;
81 FLAC__StreamMetadata *flac_cue_sheet;
82
83 int got_vorbis_comments;
84 } flac_info_t;
85
86 // callbacks
flac_read_cb(const FLAC__StreamDecoder * decoder,FLAC__byte buffer[],size_t * bytes,void * client_data)87 FLAC__StreamDecoderReadStatus flac_read_cb (const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data) {
88 flac_info_t *info = (flac_info_t *)client_data;
89 size_t r = deadbeef->fread (buffer, 1, *bytes, info->file);
90 *bytes = r;
91 if (r == 0) {
92 return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
93 }
94 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
95 }
96
flac_seek_cb(const FLAC__StreamDecoder * decoder,FLAC__uint64 absolute_byte_offset,void * client_data)97 FLAC__StreamDecoderSeekStatus flac_seek_cb (const FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data) {
98 flac_info_t *info = (flac_info_t *)client_data;
99 int r = deadbeef->fseek (info->file, absolute_byte_offset, SEEK_SET);
100 if (r) {
101 return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
102 }
103 return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
104 }
105
flac_tell_cb(const FLAC__StreamDecoder * decoder,FLAC__uint64 * absolute_byte_offset,void * client_data)106 FLAC__StreamDecoderTellStatus flac_tell_cb (const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data) {
107 flac_info_t *info = (flac_info_t *)client_data;
108 size_t r = deadbeef->ftell (info->file);
109 *absolute_byte_offset = r;
110 return FLAC__STREAM_DECODER_TELL_STATUS_OK;
111 }
112
flac_length_cb(const FLAC__StreamDecoder * decoder,FLAC__uint64 * stream_length,void * client_data)113 FLAC__StreamDecoderLengthStatus flac_length_cb (const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data) {
114 flac_info_t *info = (flac_info_t *)client_data;
115 size_t pos = deadbeef->ftell (info->file);
116 deadbeef->fseek (info->file, 0, SEEK_END);
117 *stream_length = deadbeef->ftell (info->file);
118 deadbeef->fseek (info->file, pos, SEEK_SET);
119 return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
120 }
121
flac_eof_cb(const FLAC__StreamDecoder * decoder,void * client_data)122 FLAC__bool flac_eof_cb (const FLAC__StreamDecoder *decoder, void *client_data) {
123 return 0;
124 }
125
126 static FLAC__StreamDecoderWriteStatus
cflac_write_callback(const FLAC__StreamDecoder * decoder,const FLAC__Frame * frame,const FLAC__int32 * const inputbuffer[],void * client_data)127 cflac_write_callback (const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const inputbuffer[], void *client_data) {
128 flac_info_t *info = (flac_info_t *)client_data;
129 DB_fileinfo_t *_info = &info->info;
130
131 if (frame->header.blocksize == 0) {
132 trace ("flac: blocksize=0 is invalid, aborted.\n");
133 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
134 }
135
136 int channels = _info->fmt.channels;
137 int samplesize = channels * _info->fmt.bps / 8;
138 int bufsize = BUFFERSIZE - info->remaining;
139 int bufsamples = bufsize / samplesize;
140 int nsamples = min (bufsamples, frame->header.blocksize);
141
142 char *bufptr = info->buffer + info->remaining;
143
144 int readbytes = frame->header.blocksize * samplesize;
145
146 unsigned bps = FLAC__stream_decoder_get_bits_per_sample(decoder);
147
148 if (bps == 16) {
149 for (int i = 0; i < nsamples; i++) {
150 for (int c = 0; c < channels; c++) {
151 int32_t sample = inputbuffer[c][i];
152 *bufptr++ = sample&0xff;
153 *bufptr++ = (sample&0xff00)>>8;
154 }
155 }
156 }
157 else if (bps == 24) {
158 for (int i = 0; i < nsamples; i++) {
159 for (int c = 0; c < channels; c++) {
160 int32_t sample = inputbuffer[c][i];
161 *bufptr++ = sample&0xff;
162 *bufptr++ = (sample&0xff00)>>8;
163 *bufptr++ = (sample&0xff0000)>>16;
164 }
165 }
166 }
167 else if (bps == 32) {
168 for (int i = 0; i < nsamples; i++) {
169 for (int c = 0; c < channels; c++) {
170 int32_t sample = inputbuffer[c][i];
171 *((int32_t*)bufptr) = sample;
172 bufptr += 4;
173 }
174 }
175 }
176 else if (bps == 8) {
177 for (int i = 0; i < nsamples; i++) {
178 for (int c = 0; c < channels; c++) {
179 int32_t sample = inputbuffer[c][i];
180 *bufptr++ = sample&0xff;
181 }
182 }
183 }
184 else if (bps & 7) {
185 // support for non-byte-aligned bps
186 unsigned shift = _info->fmt.bps - bps;
187 bps = _info->fmt.bps;
188 int nsamples = min(bufsize / samplesize, frame->header.blocksize);
189 for (int s = 0; s < nsamples; s++) {
190 for (int c = 0; c < channels; c++) {
191 FLAC__int32 sample = inputbuffer[c][s] << shift;
192 *bufptr++ = sample & 0xff;
193 if (bps > 8) {
194 *bufptr++ = (sample>>8) & 0xff;
195 if (bps > 16) {
196 *bufptr++ = (sample>>16) & 0xff;
197 if (bps > 24) {
198 *bufptr++ = (sample>>24) & 0xff;
199 }
200 }
201 }
202 }
203 }
204 }
205 else {
206 trace ("flac: unsupported bits per sample: %d\n", bps);
207 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
208 }
209
210 info->remaining = (int)(bufptr - info->buffer);
211
212 if (readbytes > bufsize) {
213 trace ("flac: buffer overflow, distortion will occur\n");
214 // return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
215 }
216 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
217 }
218
219 inline static int
fix_bps(int bps)220 fix_bps (int bps) {
221 int mod = bps & 7;
222 return bps - mod + (mod ? 8 : 0);
223 }
224
225 static void
cflac_metadata_callback(const FLAC__StreamDecoder * decoder,const FLAC__StreamMetadata * metadata,void * client_data)226 cflac_metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) {
227 DB_fileinfo_t *_info = (DB_fileinfo_t *)client_data;
228 flac_info_t *info = (flac_info_t *)_info;
229 info->totalsamples = metadata->data.stream_info.total_samples;
230 _info->fmt.samplerate = metadata->data.stream_info.sample_rate;
231 _info->fmt.channels = metadata->data.stream_info.channels;
232 _info->fmt.bps = fix_bps (metadata->data.stream_info.bits_per_sample);
233 for (int i = 0; i < _info->fmt.channels; i++) {
234 _info->fmt.channelmask |= 1 << i;
235 }
236 }
237
238 static void
cflac_error_callback(const FLAC__StreamDecoder * decoder,FLAC__StreamDecoderErrorStatus status,void * client_data)239 cflac_error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) {
240 DB_fileinfo_t *_info = (DB_fileinfo_t *)client_data;
241 flac_info_t *info = (flac_info_t *)_info;
242 if (status != FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC
243 && status != FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH) {
244 trace ("cflac: got error callback: %s\n", FLAC__StreamDecoderErrorStatusString[status]);
245 info->flac_critical_error = 1;
246 }
247 }
248
249 static void
cflac_init_error_callback(const FLAC__StreamDecoder * decoder,FLAC__StreamDecoderErrorStatus status,void * client_data)250 cflac_init_error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) {
251 if (status != FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC) {
252 DB_fileinfo_t *_info = (DB_fileinfo_t *)client_data;
253 flac_info_t *info = (flac_info_t *)_info;
254 fprintf(stderr, "cflac: got error callback: %s\n", FLAC__StreamDecoderErrorStatusString[status]);
255 info->init_stop_decoding = 1;
256 }
257 }
258
259 static flac_info_t *
cflac_open_int(uint32_t hints)260 cflac_open_int (uint32_t hints) {
261 flac_info_t *info = calloc(1, sizeof(flac_info_t));
262 if (info && hints&DDB_DECODER_HINT_NEED_BITRATE) {
263 info->set_bitrate = 1;
264 }
265 return info;
266 }
267
268 static DB_fileinfo_t *
cflac_open(uint32_t hints)269 cflac_open (uint32_t hints) {
270 return (DB_fileinfo_t *)cflac_open_int(hints);
271 }
272
273 static DB_fileinfo_t *
cflac_open2(uint32_t hints,DB_playItem_t * it)274 cflac_open2 (uint32_t hints, DB_playItem_t *it) {
275 flac_info_t *info = cflac_open_int(hints);
276 if (!info) {
277 return NULL;
278 }
279
280 deadbeef->pl_lock();
281 info->file = deadbeef->fopen(deadbeef->pl_find_meta(it, ":URI"));
282 if (!info->file) {
283 trace("cflac_open2 failed to open file %s\n", deadbeef->pl_find_meta(it, ":URI"));
284 }
285 deadbeef->pl_unlock();
286
287 return (DB_fileinfo_t *)info;
288 }
289
290 static int
cflac_init(DB_fileinfo_t * _info,DB_playItem_t * it)291 cflac_init (DB_fileinfo_t *_info, DB_playItem_t *it) {
292 trace ("cflac_init %s\n", deadbeef->pl_find_meta (it, ":URI"));
293 flac_info_t *info = (flac_info_t *)_info;
294
295 if (!info->file) {
296 deadbeef->pl_lock ();
297 info->file = deadbeef->fopen (deadbeef->pl_find_meta (it, ":URI"));
298 deadbeef->pl_unlock ();
299 if (!info->file) {
300 trace ("cflac_init failed to open file %s\n", deadbeef->pl_find_meta(it, ":URI"));
301 return -1;
302 }
303 }
304
305 deadbeef->pl_lock();
306 const char *uri = deadbeef->pl_find_meta(it, ":URI");
307 const char *ext = strrchr(uri, '.');
308 if (ext) {
309 ext++;
310 }
311 deadbeef->pl_unlock();
312
313 int isogg = 0;
314 int skip = 0;
315 if (ext && !strcasecmp (ext, "flac")) {
316 skip = deadbeef->junk_get_leading_size (info->file);
317 if (skip > 0) {
318 deadbeef->fseek (info->file, skip, SEEK_SET);
319 }
320 char sign[4];
321 if (deadbeef->fread (sign, 1, 4, info->file) != 4) {
322 trace ("cflac_init failed to read signature\n");
323 return -1;
324 }
325 if (strncmp (sign, "fLaC", 4)) {
326 trace ("cflac_init bad signature\n");
327 return -1;
328 }
329 deadbeef->fseek (info->file, -4, SEEK_CUR);
330 }
331 else if (!FLAC_API_SUPPORTS_OGG_FLAC) {
332 trace ("flac: ogg transport support is not compiled into FLAC library\n");
333 return -1;
334 }
335 else {
336 isogg = 1;
337 }
338
339 FLAC__StreamDecoderInitStatus status;
340 info->decoder = FLAC__stream_decoder_new ();
341 if (!info->decoder) {
342 trace ("FLAC__stream_decoder_new failed\n");
343 return -1;
344 }
345 FLAC__stream_decoder_set_md5_checking (info->decoder, 0);
346 if (isogg) {
347 status = FLAC__stream_decoder_init_ogg_stream (info->decoder, flac_read_cb, flac_seek_cb, flac_tell_cb, flac_length_cb, flac_eof_cb, cflac_write_callback, cflac_metadata_callback, cflac_error_callback, info);
348 }
349 else {
350 status = FLAC__stream_decoder_init_stream (info->decoder, flac_read_cb, flac_seek_cb, flac_tell_cb, flac_length_cb, flac_eof_cb, cflac_write_callback, cflac_metadata_callback, cflac_error_callback, info);
351 }
352 if (status != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
353 trace ("cflac_init bad decoder status\n");
354 return -1;
355 }
356 //_info->fmt.samplerate = -1;
357 if (!FLAC__stream_decoder_process_until_end_of_metadata (info->decoder)) {
358 trace ("cflac_init metadata failed\n");
359 return -1;
360 }
361
362 // bps/samplerate/channels were set by callbacks
363 _info->plugin = &plugin;
364 _info->readpos = 0;
365
366 if (_info->fmt.samplerate <= 0) { // not a FLAC stream
367 fprintf (stderr, "corrupted/invalid flac stream\n");
368 return -1;
369 }
370 info->bitrate = deadbeef->pl_find_meta_int(it, ":BITRATE", -1);
371
372 deadbeef->pl_lock ();
373 {
374 const char *channelmask = deadbeef->pl_find_meta (it, "WAVEFORMAT_EXTENSIBLE_CHANNELMASK");
375 if (channelmask) {
376 uint32_t cm = 0;
377 if (1 == sscanf (channelmask, "0x%X", &cm)) {
378 _info->fmt.channelmask = cm;
379 }
380 }
381 }
382 deadbeef->pl_unlock ();
383
384 info->buffer = malloc (BUFFERSIZE);
385 info->remaining = 0;
386 if (it->endsample > 0) {
387 info->startsample = it->startsample;
388 info->endsample = it->endsample;
389 if (plugin.seek_sample (_info, 0) < 0) {
390 trace ("cflac_init failed to seek to sample 0\n");
391 return -1;
392 }
393 trace ("flac(cue): startsample=%d, endsample=%d, totalsamples=%d, currentsample=%d\n", info->startsample, info->endsample, info->totalsamples, info->currentsample);
394 }
395 else {
396 info->startsample = 0;
397 info->endsample = info->totalsamples-1;
398 info->currentsample = 0;
399 trace ("flac: startsample=%d, endsample=%d, totalsamples=%d\n", info->startsample, info->endsample, info->totalsamples);
400 }
401
402 if (info->flac_critical_error) {
403 trace ("flac: critical error while initializing\n");
404 return -1;
405 }
406
407 return 0;
408 }
409
410 static void
cflac_free(DB_fileinfo_t * _info)411 cflac_free (DB_fileinfo_t *_info) {
412 if (_info) {
413 flac_info_t *info = (flac_info_t *)_info;
414 if (info->flac_cue_sheet) {
415 FLAC__metadata_object_delete (info->flac_cue_sheet);
416 }
417 if (info->decoder) {
418 FLAC__stream_decoder_delete (info->decoder);
419 }
420 if (info->buffer) {
421 free (info->buffer);
422 }
423 if (info->file) {
424 deadbeef->fclose (info->file);
425 }
426 free (_info);
427 }
428 }
429
430 static int
cflac_read(DB_fileinfo_t * _info,char * bytes,int size)431 cflac_read (DB_fileinfo_t *_info, char *bytes, int size) {
432 flac_info_t *info = (flac_info_t *)_info;
433 if (info->set_bitrate && info->bitrate != deadbeef->streamer_get_apx_bitrate()) {
434 deadbeef->streamer_set_bitrate (info->bitrate);
435 }
436
437 int samplesize = _info->fmt.channels * _info->fmt.bps / 8;
438 if (info->endsample >= 0) {
439 if (size / samplesize + info->currentsample > info->endsample) {
440 size = (int)(info->endsample - info->currentsample + 1) * samplesize;
441 trace ("size truncated to %d bytes, cursample=%d, endsample=%d\n", size, info->currentsample, info->endsample);
442 if (size <= 0) {
443 return 0;
444 }
445 }
446 }
447 int initsize = size;
448 do {
449 if (info->remaining) {
450 int sz = min(size, info->remaining);
451 memcpy (bytes, info->buffer, sz);
452
453 size -= sz;
454 bytes += sz;
455 if (sz < info->remaining) {
456 memmove (info->buffer, &info->buffer[sz], info->remaining - sz);
457 }
458 info->remaining -= sz;
459 int n = sz / samplesize;
460 info->currentsample += sz / samplesize;
461 _info->readpos += (float)n / _info->fmt.samplerate;
462 }
463 if (!size) {
464 break;
465 }
466 if (!FLAC__stream_decoder_process_single (info->decoder)) {
467 trace ("FLAC__stream_decoder_process_single error\n");
468 break;
469 }
470 if (FLAC__stream_decoder_get_state (info->decoder) == FLAC__STREAM_DECODER_END_OF_STREAM) {
471 trace ("FLAC__stream_decoder_get_state error\n");
472 break;
473 }
474 if (info->flac_critical_error) {
475 trace ("flac: got critical error while decoding\n");
476 return 0;
477 }
478 } while (size > 0);
479
480 return initsize - size;
481 }
482
483 #if 0
484 static int
485 cflac_read_float32 (DB_fileinfo_t *_info, char *bytes, int size) {
486 flac_info_t *info = (flac_info_t *)_info;
487 if (size / (4 * _info->fmt.channels) + info->currentsample > info->endsample) {
488 size = (info->endsample - info->currentsample + 1) * 4 * _info->fmt.channels;
489 trace ("size truncated to %d bytes, cursample=%d, endsample=%d\n", size, info->currentsample, info->endsample);
490 if (size <= 0) {
491 return 0;
492 }
493 }
494 int n_output_channels = _info->fmt.channels;
495 if (n_output_channels > 2) {
496 n_output_channels = 2;
497 }
498 int initsize = size;
499 do {
500 if (info->remaining) {
501 int n_input_frames = info->remaining / sizeof (float) / n_output_channels;
502 int n_output_frames = size / n_output_channels / sizeof (float);
503 int n = min (n_input_frames, n_output_frames);
504
505 float *in = (float *)info->buffer;
506 for (int i = 0; i < n; i++) {
507 *((float *)bytes) = *in;
508 size -= sizeof (float);
509 bytes += sizeof (float);
510 if (n_output_channels == 2) {
511 *((float *)bytes) = *(in+1);
512 size -= sizeof (float);
513 bytes += sizeof (float);
514 }
515 in += n_output_channels;
516 }
517 int sz = n * sizeof (float) * n_output_channels;
518 if (sz < info->remaining) {
519 memmove (info->buffer, &info->buffer[sz], info->remaining-sz);
520 }
521 info->remaining -= sz;
522 info->currentsample += n;
523 _info->readpos += (float)n / _info->fmt.samplerate;
524 }
525 if (!size) {
526 break;
527 }
528 if (!FLAC__stream_decoder_process_single (info->decoder)) {
529 trace ("FLAC__stream_decoder_process_single error\n");
530 break;
531 }
532 if (FLAC__stream_decoder_get_state (info->decoder) == FLAC__STREAM_DECODER_END_OF_STREAM) {
533 trace ("FLAC__stream_decoder_get_state eof\n");
534 break;
535 }
536 if (info->flac_critical_error) {
537 trace ("flac: got critical error while decoding\n");
538 return 0;
539 }
540 } while (size > 0);
541
542 return initsize - size;
543 }
544 #endif
545
546 static int
cflac_seek_sample(DB_fileinfo_t * _info,int sample)547 cflac_seek_sample (DB_fileinfo_t *_info, int sample) {
548 flac_info_t *info = (flac_info_t *)_info;
549 sample += info->startsample;
550 info->currentsample = sample;
551 info->remaining = 0;
552 if (!FLAC__stream_decoder_seek_absolute (info->decoder, (FLAC__uint64)(sample))) {
553 return -1;
554 }
555 _info->readpos = (float)(sample - info->startsample)/ _info->fmt.samplerate;
556 return 0;
557 }
558
559 static int
cflac_seek(DB_fileinfo_t * _info,float time)560 cflac_seek (DB_fileinfo_t *_info, float time) {
561 return cflac_seek_sample (_info, time * _info->fmt.samplerate);
562 }
563
564 static FLAC__StreamDecoderWriteStatus
cflac_init_write_callback(const FLAC__StreamDecoder * decoder,const FLAC__Frame * frame,const FLAC__int32 * const inputbuffer[],void * client_data)565 cflac_init_write_callback (const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const inputbuffer[], void *client_data) {
566 flac_info_t *info = (flac_info_t *)client_data;
567 if (frame->header.blocksize == 0 || info->init_stop_decoding) {
568 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
569 }
570 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
571 }
572
573 static const char *metainfo[] = {
574 "ARTIST", "artist",
575 "TITLE", "title",
576 "ALBUM", "album",
577 "TRACKNUMBER", "track",
578 "TRACKTOTAL", "numtracks",
579 "TOTALTRACKS", "numtracks",
580 "DATE", "year",
581 "GENRE", "genre",
582 "COMMENT", "comment",
583 "PERFORMER", "performer",
584 "COMPOSER", "composer",
585 "ENCODED-BY", "vendor",
586 "DISCNUMBER", "disc",
587 "DISCTOTAL", "numdiscs",
588 "TOTALDISCS", "numdiscs",
589 "COPYRIGHT", "copyright",
590 "ORIGINALDATE","original_release_time",
591 "ORIGINALYEAR","original_release_year",
592 NULL
593 };
594
595 static int
add_track_meta(DB_playItem_t * it,char * track)596 add_track_meta (DB_playItem_t *it, char *track) {
597 char *slash = strchr (track, '/');
598 if (slash) {
599 // split into track/totaltracks
600 *slash = 0;
601 slash++;
602 deadbeef->pl_add_meta (it, "numtracks", slash);
603 }
604 deadbeef->pl_add_meta (it, "track", track);
605 return 0;
606 }
607
608 static int
add_disc_meta(DB_playItem_t * it,char * disc)609 add_disc_meta (DB_playItem_t *it, char *disc) {
610 char *slash = strchr (disc, '/');
611 if (slash) {
612 // split into disc/totaldiscs
613 *slash = 0;
614 slash++;
615 deadbeef->pl_add_meta (it, "numdiscs", slash);
616 }
617 deadbeef->pl_add_meta (it, "disc", disc);
618 return 0;
619 }
620
621 static void
cflac_add_metadata(DB_playItem_t * it,const char * s,int length)622 cflac_add_metadata (DB_playItem_t *it, const char *s, int length) {
623 int m;
624 for (m = 0; metainfo[m]; m += 2) {
625 size_t l = strlen (metainfo[m]);
626 if (length > l && !strncasecmp (metainfo[m], s, l) && s[l] == '=') {
627 const char *val = s + l + 1;
628 if (!strcmp (metainfo[m+1], "track")) {
629 add_track_meta (it, strdupa (val));
630 }
631 else if (!strcmp (metainfo[m+1], "disc")) {
632 add_disc_meta (it, strdupa (val));
633 }
634 else {
635 deadbeef->pl_append_meta (it, metainfo[m+1], val);
636 }
637 break;
638 }
639 }
640 if (!metainfo[m]) {
641 if (!strncasecmp (s, "CUESHEET=", 9)) {
642 deadbeef->pl_add_meta (it, "cuesheet", s + 9);
643 }
644 else if (!strncasecmp (s, "replaygain_album_gain=", 22)) {
645 deadbeef->pl_set_item_replaygain (it, DDB_REPLAYGAIN_ALBUMGAIN, atof (s+22));
646 }
647 else if (!strncasecmp (s, "replaygain_album_peak=", 22)) {
648 deadbeef->pl_set_item_replaygain (it, DDB_REPLAYGAIN_ALBUMPEAK, atof (s+22));
649 }
650 else if (!strncasecmp (s, "replaygain_track_gain=", 22)) {
651 deadbeef->pl_set_item_replaygain (it, DDB_REPLAYGAIN_TRACKGAIN, atof (s+22));
652 }
653 else if (!strncasecmp (s, "replaygain_track_peak=", 22)) {
654 deadbeef->pl_set_item_replaygain (it, DDB_REPLAYGAIN_TRACKPEAK, atof (s+22));
655 }
656 else {
657 const char *eq = strchr (s, '=');
658 if (eq) {
659 char key[eq - s+1];
660 strncpy (key, s, eq-s);
661 key[eq-s] = 0;
662 deadbeef->pl_append_meta (it, key, eq+1);
663 }
664 }
665 }
666 }
667
668 static void
cflac_init_metadata_callback(const FLAC__StreamDecoder * decoder,const FLAC__StreamMetadata * metadata,void * client_data)669 cflac_init_metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) {
670 flac_info_t *info = (flac_info_t *)client_data;
671 DB_fileinfo_t *_info = &info->info;
672 if (info->init_stop_decoding) {
673 trace ("error flag is set, ignoring init_metadata callback..\n");
674 return;
675 }
676 DB_playItem_t *it = info->it;
677 //it->tracknum = 0;
678 if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
679 trace ("flac: samplerate=%d, channels=%d, totalsamples=%d\n", metadata->data.stream_info.sample_rate, metadata->data.stream_info.channels, metadata->data.stream_info.total_samples);
680 _info->fmt.samplerate = metadata->data.stream_info.sample_rate;
681 _info->fmt.channels = metadata->data.stream_info.channels;
682 _info->fmt.bps = fix_bps (metadata->data.stream_info.bits_per_sample);
683 info->totalsamples = metadata->data.stream_info.total_samples;
684 if (metadata->data.stream_info.total_samples > 0) {
685 deadbeef->plt_set_item_duration (info->plt, it, metadata->data.stream_info.total_samples / (float)metadata->data.stream_info.sample_rate);
686 }
687 else {
688 deadbeef->plt_set_item_duration (info->plt, it, -1);
689 }
690 }
691 else if (metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
692 const FLAC__StreamMetadata_VorbisComment *vc = &metadata->data.vorbis_comment;
693 for (int i = 0; i < vc->num_comments; i++) {
694 const FLAC__StreamMetadata_VorbisComment_Entry *c = &vc->comments[i];
695 if (c->length > 0) {
696 const char *s = (const char *)c->entry;
697 cflac_add_metadata (it, s, c->length);
698 }
699 }
700 deadbeef->pl_add_meta (it, "title", NULL);
701 if (vc->num_comments > 0) {
702 uint32_t f = deadbeef->pl_get_item_flags (it);
703 f &= ~DDB_TAG_MASK;
704 f |= DDB_TAG_VORBISCOMMENTS;
705 deadbeef->pl_set_item_flags (it, f);
706 }
707 info->got_vorbis_comments = 1;
708 }
709 else if (metadata->type == FLAC__METADATA_TYPE_CUESHEET) {
710 if (!info->flac_cue_sheet) {
711 info->flac_cue_sheet = FLAC__metadata_object_clone (metadata);
712 }
713 }
714 }
715
716 static DB_playItem_t *
cflac_insert_with_embedded_cue(ddb_playlist_t * plt,DB_playItem_t * after,DB_playItem_t * origin,const FLAC__StreamMetadata_CueSheet * cuesheet,int totalsamples,int samplerate)717 cflac_insert_with_embedded_cue (ddb_playlist_t *plt, DB_playItem_t *after, DB_playItem_t *origin, const FLAC__StreamMetadata_CueSheet *cuesheet, int totalsamples, int samplerate) {
718 static const char err_invalid_cuesheet[] = "The flac %s has invalid FLAC__METADATA_TYPE_CUESHEET block, which will get ignored. You should remove it using metaflac.\n";
719 DB_playItem_t *ins = after;
720
721 // first check if cuesheet is matching the data
722 for (int i = 0; i < cuesheet->num_tracks; i++) {
723 if (cuesheet->tracks[i].offset > totalsamples) {
724 fprintf (stderr, err_invalid_cuesheet, deadbeef->pl_find_meta_raw (origin, ":URI"));
725 return NULL;
726 }
727 }
728
729 // use libflac to validate the cuesheet as well
730 if(!FLAC__format_cuesheet_is_legal (cuesheet, 1, NULL)) {
731 fprintf (stderr, err_invalid_cuesheet, deadbeef->pl_find_meta_raw (origin, ":URI"));
732 return NULL;
733 }
734
735 for (int i = 0; i < cuesheet->num_tracks-1; i++) {
736 const char *uri = deadbeef->pl_find_meta_raw (origin, ":URI");
737 const char *dec = deadbeef->pl_find_meta_raw (origin, ":DECODER");
738 const char *ftype= "FLAC";
739
740 DB_playItem_t *it = deadbeef->pl_item_alloc_init (uri, dec);
741 deadbeef->pl_set_meta_int (it, ":TRACKNUM", i+1);
742 deadbeef->pl_set_meta_int (it, "TRACK", i+1);
743 char id[100];
744 snprintf (id, sizeof (id), "TITLE[%d]", i+1);
745 deadbeef->pl_add_meta (it, "title", deadbeef->pl_find_meta (origin, id));
746 snprintf (id, sizeof (id), "ARTIST[%d]", i+1);
747 deadbeef->pl_add_meta (it, "artist", deadbeef->pl_find_meta (origin, id));
748 deadbeef->pl_add_meta (it, "band", deadbeef->pl_find_meta (origin, "artist"));
749 it->startsample = cuesheet->tracks[i].offset;
750 it->endsample = cuesheet->tracks[i+1].offset-1;
751 deadbeef->pl_replace_meta (it, ":FILETYPE", ftype);
752 deadbeef->plt_set_item_duration (plt, it, (float)(it->endsample - it->startsample + 1) / samplerate);
753 after = deadbeef->plt_insert_item (plt, after, it);
754 deadbeef->pl_item_unref (it);
755 }
756 deadbeef->pl_item_ref (after);
757
758 DB_playItem_t *first = deadbeef->pl_get_next (ins, PL_MAIN);
759
760 if (!first) {
761 first = deadbeef->plt_get_first (plt, PL_MAIN);
762 }
763
764 if (!first) {
765 return NULL;
766 }
767 trace ("aac: split by chapters success\n");
768 // copy metadata from embedded tags
769 uint32_t f = deadbeef->pl_get_item_flags (origin);
770 f |= DDB_IS_SUBTRACK;
771 deadbeef->pl_set_item_flags (origin, f);
772 deadbeef->pl_items_copy_junk (origin, first, after);
773 deadbeef->pl_item_unref (first);
774
775 return after;
776 }
777
778 static void
cflac_free_temp(DB_fileinfo_t * _info)779 cflac_free_temp (DB_fileinfo_t *_info) {
780 if (_info) {
781 flac_info_t *info = (flac_info_t *)_info;
782 if (info->flac_cue_sheet) {
783 FLAC__metadata_object_delete (info->flac_cue_sheet);
784 }
785 if (info->decoder) {
786 FLAC__stream_decoder_delete (info->decoder);
787 }
788 if (info->buffer) {
789 free (info->buffer);
790 }
791 if (info->file) {
792 deadbeef->fclose (info->file);
793 }
794 }
795 }
796
797 static int
798 cflac_read_metadata (DB_playItem_t *it);
799
800 static DB_playItem_t *
cflac_insert(ddb_playlist_t * plt,DB_playItem_t * after,const char * fname)801 cflac_insert (ddb_playlist_t *plt, DB_playItem_t *after, const char *fname) {
802 trace ("flac: inserting %s\n", fname);
803 DB_playItem_t *it = NULL;
804 FLAC__StreamDecoder *decoder = NULL;
805 flac_info_t info;
806 memset (&info, 0, sizeof (info));
807 DB_fileinfo_t *_info = &info.info;
808 info.fname = fname;
809 info.after = after;
810 info.last = after;
811 info.plt = plt;
812 info.file = deadbeef->fopen (fname);
813 if (!info.file) {
814 goto cflac_insert_fail;
815 }
816
817 const char *ext = fname + strlen (fname);
818 while (ext > fname && *ext != '/' && *ext != '.') {
819 ext--;
820 }
821 if (*ext == '.') {
822 ext++;
823 }
824 else {
825 ext = NULL;
826 }
827
828 int isogg = 0;
829 int skip = 0;
830 if (ext && !strcasecmp (ext, "flac")) {
831 // skip id3 junk and verify fLaC signature
832 skip = deadbeef->junk_get_leading_size (info.file);
833 if (skip > 0) {
834 deadbeef->fseek (info.file, skip, SEEK_SET);
835 }
836 char sign[4];
837 if (deadbeef->fread (sign, 1, 4, info.file) != 4) {
838 trace ("flac: failed to read signature\n");
839 goto cflac_insert_fail;
840 }
841 if (strncmp (sign, "fLaC", 4)) {
842 trace ("flac: file signature is not fLaC\n");
843 goto cflac_insert_fail;
844 }
845 deadbeef->fseek (info.file, -4, SEEK_CUR);
846 }
847 else if (!FLAC_API_SUPPORTS_OGG_FLAC) {
848 trace ("flac: ogg transport support is not compiled into FLAC library\n");
849 goto cflac_insert_fail;
850 }
851 else {
852 isogg = 1;
853 }
854 info.init_stop_decoding = 0;
855
856 // open decoder for metadata reading
857 FLAC__StreamDecoderInitStatus status;
858 decoder = FLAC__stream_decoder_new();
859 if (!decoder) {
860 trace ("flac: failed to create decoder\n");
861 goto cflac_insert_fail;
862 }
863
864 // read all metadata
865 FLAC__stream_decoder_set_md5_checking(decoder, 0);
866 FLAC__stream_decoder_set_metadata_respond_all (decoder);
867 it = deadbeef->pl_item_alloc_init (fname, plugin.plugin.id);
868 info.it = it;
869 if (skip > 0) {
870 deadbeef->fseek (info.file, skip, SEEK_SET);
871 }
872 else {
873 deadbeef->rewind (info.file);
874 }
875 deadbeef->fseek (info.file, -4, SEEK_CUR);
876 if (isogg) {
877 status = FLAC__stream_decoder_init_ogg_stream (decoder, flac_read_cb, flac_seek_cb, flac_tell_cb, flac_length_cb, flac_eof_cb, cflac_init_write_callback, cflac_init_metadata_callback, cflac_init_error_callback, &info);
878 }
879 else {
880 status = FLAC__stream_decoder_init_stream (decoder, flac_read_cb, flac_seek_cb, flac_tell_cb, flac_length_cb, flac_eof_cb, cflac_init_write_callback, cflac_init_metadata_callback, cflac_init_error_callback, &info);
881 }
882 if (status != FLAC__STREAM_DECODER_INIT_STATUS_OK || info.init_stop_decoding) {
883 trace ("flac: FLAC__stream_decoder_init_stream [2] failed\n");
884 goto cflac_insert_fail;
885 }
886 if (!FLAC__stream_decoder_process_until_end_of_metadata (decoder) || info.init_stop_decoding) {
887 trace ("flac: FLAC__stream_decoder_process_until_end_of_metadata [2] failed\n");
888 goto cflac_insert_fail;
889 }
890
891 if (info.info.fmt.samplerate <= 0) {
892 goto cflac_insert_fail;
893 }
894 int64_t fsize = deadbeef->fgetlength (info.file);
895 int is_streaming = info.file->vfs->is_streaming ();
896
897 deadbeef->pl_add_meta (it, ":FILETYPE", isogg ? "OggFLAC" : "FLAC");
898
899 char s[100];
900 snprintf (s, sizeof (s), "%lld", fsize);
901 deadbeef->pl_add_meta (it, ":FILE_SIZE", s);
902 snprintf (s, sizeof (s), "%d", info.info.fmt.channels);
903 deadbeef->pl_add_meta (it, ":CHANNELS", s);
904 snprintf (s, sizeof (s), "%d", info.info.fmt.bps);
905 deadbeef->pl_add_meta (it, ":BPS", s);
906 snprintf (s, sizeof (s), "%d", info.info.fmt.samplerate);
907 deadbeef->pl_add_meta (it, ":SAMPLERATE", s);
908 if ( deadbeef->pl_get_item_duration (it) > 0) {
909 if (!isogg) {
910 FLAC__uint64 position;
911 if (FLAC__stream_decoder_get_decode_position (decoder, &position))
912 fsize -= position;
913 }
914 #if USE_OGGEDIT
915 else {
916 const off_t stream_size = oggedit_flac_stream_info(deadbeef->fopen(fname), 0, 0);
917 if (stream_size > 0)
918 fsize = stream_size;
919 }
920 #endif
921 deadbeef->pl_set_meta_int (it, ":BITRATE", (int)roundf(fsize / deadbeef->pl_get_item_duration (it) * 8 / 1000));
922 }
923 FLAC__stream_decoder_delete(decoder);
924 decoder = NULL;
925
926 deadbeef->fclose (info.file);
927 info.file = NULL;
928
929 if (!info.got_vorbis_comments && !is_streaming) {
930 cflac_read_metadata (it);
931 }
932
933 // try embedded cue
934 deadbeef->pl_lock ();
935 if (info.flac_cue_sheet) {
936 DB_playItem_t *cue = cflac_insert_with_embedded_cue (plt, after, it, &info.flac_cue_sheet->data.cue_sheet, info.totalsamples, info.info.fmt.samplerate);
937 if (cue) {
938 cflac_free_temp (_info);
939 deadbeef->pl_item_unref (it);
940 deadbeef->pl_item_unref (cue);
941 deadbeef->pl_unlock ();
942 return cue;
943 }
944 }
945 const char *cuesheet = deadbeef->pl_find_meta (it, "cuesheet");
946 if (cuesheet) {
947 DB_playItem_t *last = deadbeef->plt_insert_cue_from_buffer (plt, after, it, (const uint8_t *)cuesheet, strlen (cuesheet), info.totalsamples, info.info.fmt.samplerate);
948 if (last) {
949 cflac_free_temp (_info);
950 deadbeef->pl_item_unref (it);
951 deadbeef->pl_item_unref (last);
952 deadbeef->pl_unlock ();
953 return last;
954 }
955 }
956 deadbeef->pl_unlock ();
957
958 // try external cue
959 DB_playItem_t *cue_after = deadbeef->plt_insert_cue (plt, after, it, info.totalsamples, info.info.fmt.samplerate);
960 if (cue_after) {
961 cflac_free_temp (_info);
962 deadbeef->pl_item_unref (it);
963 deadbeef->pl_item_unref (cue_after);
964 trace ("flac: loaded external cuesheet\n");
965 return cue_after;
966 }
967 after = deadbeef->plt_insert_item (plt, after, it);
968 deadbeef->pl_item_unref (it);
969 cflac_free_temp (_info);
970 return after;
971 cflac_insert_fail:
972 if (it) {
973 deadbeef->pl_item_unref (it);
974 }
975 cflac_free_temp (_info);
976 return NULL;
977 }
978
979 static size_t
flac_io_read(void * ptr,size_t size,size_t nmemb,FLAC__IOHandle handle)980 flac_io_read (void *ptr, size_t size, size_t nmemb, FLAC__IOHandle handle) {
981 return deadbeef->fread (ptr, size, nmemb, (DB_FILE *)handle);
982 }
983
984 static int
flac_io_seek(FLAC__IOHandle handle,FLAC__int64 offset,int whence)985 flac_io_seek (FLAC__IOHandle handle, FLAC__int64 offset, int whence) {
986 return deadbeef->fseek ((DB_FILE *)handle, offset, whence);
987 }
988
989 static FLAC__int64
flac_io_tell(FLAC__IOHandle handle)990 flac_io_tell (FLAC__IOHandle handle) {
991 return deadbeef->ftell ((DB_FILE *)handle);
992 }
993
994 static int
flac_io_eof(FLAC__IOHandle handle)995 flac_io_eof (FLAC__IOHandle handle) {
996 int64_t pos = deadbeef->ftell ((DB_FILE *)handle);
997 return pos == deadbeef->fgetlength ((DB_FILE *)handle);
998 }
999
1000 static int
flac_io_close(FLAC__IOHandle handle)1001 flac_io_close (FLAC__IOHandle handle) {
1002 deadbeef->fclose ((DB_FILE *)handle);
1003 return 0;
1004 }
1005
1006 static FLAC__IOCallbacks iocb = {
1007 .read = flac_io_read,
1008 .write = NULL,
1009 .seek = flac_io_seek,
1010 .tell = flac_io_tell,
1011 .eof = flac_io_eof,
1012 .close = flac_io_close,
1013 };
1014
1015 static int
cflac_read_metadata(DB_playItem_t * it)1016 cflac_read_metadata (DB_playItem_t *it) {
1017 int err = -1;
1018 FLAC__Metadata_Chain *chain = NULL;
1019 FLAC__Metadata_Iterator *iter = NULL;
1020
1021 chain = FLAC__metadata_chain_new ();
1022 if (!chain) {
1023 trace ("cflac_read_metadata: FLAC__metadata_chain_new failed\n");
1024 return -1;
1025 }
1026 deadbeef->pl_lock ();
1027 DB_FILE *file = deadbeef->fopen (deadbeef->pl_find_meta (it, ":URI"));
1028 deadbeef->pl_unlock ();
1029 if (!file) {
1030 return -1;
1031 }
1032 FLAC__bool res = FLAC__metadata_chain_read_with_callbacks (chain, (FLAC__IOHandle)file, iocb);
1033 if (!res && FLAC__metadata_chain_status(chain) == FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_A_FLAC_FILE) {
1034 res = FLAC__metadata_chain_read_ogg_with_callbacks (chain, (FLAC__IOHandle)file, iocb);
1035 }
1036 deadbeef->fclose (file);
1037 file = NULL;
1038 if (!res) {
1039 trace ("cflac_read_metadata: FLAC__metadata_chain_read(_ogg) failed\n");
1040 goto error;
1041 }
1042 FLAC__metadata_chain_merge_padding (chain);
1043
1044 iter = FLAC__metadata_iterator_new ();
1045 if (!iter) {
1046 trace ("cflac_read_metadata: FLAC__metadata_iterator_new failed\n");
1047 goto error;
1048 }
1049 deadbeef->pl_delete_all_meta (it);
1050 FLAC__metadata_iterator_init (iter, chain);
1051 do {
1052 FLAC__StreamMetadata *data = FLAC__metadata_iterator_get_block (iter);
1053 if (data && data->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
1054 const FLAC__StreamMetadata_VorbisComment *vc = &data->data.vorbis_comment;
1055 for (int i = 0; i < vc->num_comments; i++) {
1056 const FLAC__StreamMetadata_VorbisComment_Entry *c = &vc->comments[i];
1057 if (c->length > 0) {
1058 const char *s = (const char *)c->entry;
1059 cflac_add_metadata (it, s, c->length);
1060 }
1061 }
1062 deadbeef->pl_add_meta (it, "title", NULL);
1063 if (vc->num_comments > 0) {
1064 uint32_t f = deadbeef->pl_get_item_flags (it);
1065 f &= ~DDB_TAG_MASK;
1066 f |= DDB_TAG_VORBISCOMMENTS;
1067 deadbeef->pl_set_item_flags (it, f);
1068 }
1069 }
1070 } while (FLAC__metadata_iterator_next (iter));
1071
1072 FLAC__metadata_iterator_delete (iter);
1073 err = 0;
1074 deadbeef->pl_add_meta (it, "title", NULL);
1075 uint32_t f = deadbeef->pl_get_item_flags (it);
1076 f &= ~DDB_TAG_MASK;
1077 f |= DDB_TAG_VORBISCOMMENTS;
1078 deadbeef->pl_set_item_flags (it, f);
1079 error:
1080 if (chain) {
1081 FLAC__metadata_chain_delete (chain);
1082 }
1083 if (err != 0) {
1084 deadbeef->pl_delete_all_meta (it);
1085 deadbeef->pl_add_meta (it, "title", NULL);
1086 }
1087
1088 return err;
1089 }
1090 #if USE_OGGEDIT
1091 int
cflac_write_metadata_ogg(DB_playItem_t * it,FLAC__StreamMetadata_VorbisComment * vc)1092 cflac_write_metadata_ogg (DB_playItem_t *it, FLAC__StreamMetadata_VorbisComment *vc)
1093 {
1094 char fname[PATH_MAX];
1095 deadbeef->pl_get_meta (it, ":URI", fname, sizeof (fname));
1096
1097 size_t num_tags = vc->num_comments;
1098 char **tags = calloc(num_tags+1, sizeof(char **));
1099 for (size_t i = 0; i < num_tags; i++)
1100 tags[i] = (char *)vc->comments[i].entry;
1101 const off_t file_size = oggedit_write_flac_metadata (deadbeef->fopen(fname), fname, 0, num_tags, tags);
1102 if (file_size <= 0) {
1103 trace ("cflac_write_metadata_ogg: oggedit_write_flac_metadata failed: code %d\n", file_size);
1104 return -1;
1105 }
1106
1107 free(tags);
1108
1109 return 0;
1110 }
1111 #endif
1112 int
cflac_write_metadata(DB_playItem_t * it)1113 cflac_write_metadata (DB_playItem_t *it) {
1114 int err = -1;
1115 FLAC__Metadata_Chain *chain = NULL;
1116 FLAC__Metadata_Iterator *iter = NULL;
1117
1118 chain = FLAC__metadata_chain_new ();
1119 if (!chain) {
1120 fprintf (stderr, "cflac_write_metadata: FLAC__metadata_chain_new failed\n");
1121 return -1;
1122 }
1123 deadbeef->pl_lock ();
1124 FLAC__bool res = FLAC__metadata_chain_read (chain, deadbeef->pl_find_meta (it, ":URI"));
1125 FLAC__bool isogg = false;
1126 #if USE_OGGEDIT
1127 if (!res && FLAC__metadata_chain_status(chain) == FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_A_FLAC_FILE) {
1128 isogg = true;
1129 res = FLAC__metadata_chain_read_ogg (chain, deadbeef->pl_find_meta (it, ":URI"));
1130 }
1131 #endif
1132 deadbeef->pl_unlock ();
1133 if (!res) {
1134 fprintf (stderr, "cflac_write_metadata: FLAC__metadata_chain_read(_ogg) failed - code %d\n", res);
1135 goto error;
1136 }
1137 FLAC__metadata_chain_merge_padding (chain);
1138
1139 iter = FLAC__metadata_iterator_new ();
1140 if (!iter) {
1141 trace ("cflac_write_metadata: FLAC__metadata_iterator_new failed\n");
1142 goto error;
1143 }
1144 FLAC__StreamMetadata *data = NULL;
1145
1146 // find existing vorbiscomment block
1147 FLAC__metadata_iterator_init (iter, chain);
1148 do {
1149 data = FLAC__metadata_iterator_get_block (iter);
1150 if (data && data->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
1151 break;
1152 }
1153 else {
1154 data = NULL;
1155 }
1156 } while (FLAC__metadata_iterator_next (iter));
1157
1158 if (data) {
1159 FLAC__StreamMetadata_VorbisComment *vc = &data->data.vorbis_comment;
1160 int vc_comments = vc->num_comments;
1161 for (int i = 0; i < vc_comments; i++) {
1162 const FLAC__StreamMetadata_VorbisComment_Entry *c = &vc->comments[i];
1163 if (c->length > 0) {
1164 FLAC__metadata_object_vorbiscomment_delete_comment (data, i);
1165 vc_comments--;
1166 i--;
1167 }
1168 }
1169 }
1170 else {
1171 // create new and add to chain
1172 data = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT);
1173 if (!data) {
1174 fprintf (stderr, "flac: failed to allocate new vorbis comment block\n");
1175 goto error;
1176 }
1177 if(!FLAC__metadata_iterator_insert_block_after(iter, data)) {
1178 fprintf (stderr, "flac: failed to append vorbis comment block to chain\n");
1179 goto error;
1180 }
1181 }
1182
1183 deadbeef->pl_lock ();
1184 DB_metaInfo_t *m = deadbeef->pl_get_metadata_head (it);
1185 while (m) {
1186 if (m->key[0] != ':') {
1187 int i;
1188 for (i = 0; metainfo[i]; i += 2) {
1189 if (!strcasecmp (metainfo[i+1], m->key)) {
1190 break;
1191 }
1192 }
1193 const char *val = m->value;
1194 if (val && *val) {
1195 while (val) {
1196 const char *next = strchr (val, '\n');
1197 size_t l;
1198 if (next) {
1199 l = next - val;
1200 next++;
1201 }
1202 else {
1203 l = strlen (val);
1204 }
1205 if (l > 0) {
1206 char s[100+l+1];
1207 int n = snprintf (s, sizeof (s), "%s=", metainfo[i] ? metainfo[i] : m->key);
1208 strncpy (s+n, val, l);
1209 *(s+n+l) = 0;
1210 FLAC__StreamMetadata_VorbisComment_Entry ent = {
1211 .length = (FLAC__uint32)strlen (s),
1212 .entry = (FLAC__byte*)s
1213 };
1214 FLAC__metadata_object_vorbiscomment_append_comment (data, ent, 1);
1215 }
1216 val = next;
1217 }
1218 }
1219 }
1220 m = m->next;
1221 }
1222
1223 static const char *tag_rg_names[] = {
1224 "replaygain_album_gain",
1225 "replaygain_album_peak",
1226 "replaygain_track_gain",
1227 "replaygain_track_peak",
1228 NULL
1229 };
1230
1231 // replaygain key names in deadbeef internal metadata
1232 static const char *ddb_internal_rg_keys[] = {
1233 ":REPLAYGAIN_ALBUMGAIN",
1234 ":REPLAYGAIN_ALBUMPEAK",
1235 ":REPLAYGAIN_TRACKGAIN",
1236 ":REPLAYGAIN_TRACKPEAK",
1237 NULL
1238 };
1239
1240 // add replaygain values
1241 for (int n = 0; ddb_internal_rg_keys[n]; n++) {
1242 if (deadbeef->pl_find_meta (it, ddb_internal_rg_keys[n])) {
1243 float value = deadbeef->pl_get_item_replaygain (it, n);
1244 char s[100];
1245 snprintf (s, sizeof (s), "%s=%f", tag_rg_names[n], value);
1246 FLAC__StreamMetadata_VorbisComment_Entry ent = {
1247 .length = (FLAC__uint32)strlen (s),
1248 .entry = (FLAC__byte*)s
1249 };
1250 FLAC__metadata_object_vorbiscomment_append_comment (data, ent, 1);
1251 }
1252 }
1253
1254 deadbeef->pl_unlock ();
1255
1256 if (!isogg) {
1257 res = FLAC__metadata_chain_write (chain, 1, 0);
1258 }
1259 #if USE_OGGEDIT
1260 else {
1261 if (cflac_write_metadata_ogg(it, &data->data.vorbis_comment)) {
1262 res = 0;
1263 }
1264 }
1265 #endif
1266 if (!res) {
1267 fprintf (stderr, "cflac_write_metadata: failed to write tags: code %d\n", res);
1268 goto error;
1269 }
1270
1271 err = 0;
1272 error:
1273 FLAC__metadata_iterator_delete (iter);
1274 if (chain) {
1275 FLAC__metadata_chain_delete (chain);
1276 }
1277
1278 return err;
1279 }
1280
1281 static const char *exts[] = { "flac", "oga", NULL };
1282
1283 // define plugin interface
1284 static DB_decoder_t plugin = {
1285 .plugin.api_vmajor = 1,
1286 .plugin.api_vminor = 7,
1287 .plugin.version_major = 1,
1288 .plugin.version_minor = 0,
1289 .plugin.type = DB_PLUGIN_DECODER,
1290 .plugin.id = "stdflac",
1291 .plugin.name = "FLAC decoder",
1292 .plugin.descr = "FLAC decoder using libFLAC",
1293 .plugin.copyright =
1294 "Copyright (C) 2009-2013 Alexey Yakovenko et al.\n"
1295 "Uses libFLAC (C) Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson\n"
1296 "Uses libogg Copyright (c) 2002, Xiph.org Foundation\n"
1297 "\n"
1298 "Redistribution and use in source and binary forms, with or without\n"
1299 "modification, are permitted provided that the following conditions\n"
1300 "are met:\n"
1301 "\n"
1302 "- Redistributions of source code must retain the above copyright\n"
1303 "notice, this list of conditions and the following disclaimer.\n"
1304 "\n"
1305 "- Redistributions in binary form must reproduce the above copyright\n"
1306 "notice, this list of conditions and the following disclaimer in the\n"
1307 "documentation and/or other materials provided with the distribution.\n"
1308 "\n"
1309 "- Neither the name of the DeaDBeeF Player nor the names of its\n"
1310 "contributors may be used to endorse or promote products derived from\n"
1311 "this software without specific prior written permission.\n"
1312 "\n"
1313 "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
1314 "``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
1315 "LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
1316 "A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR\n"
1317 "CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n"
1318 "EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n"
1319 "PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n"
1320 "PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n"
1321 "LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n"
1322 "NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n"
1323 "SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
1324 ,
1325 .plugin.website = "http://deadbeef.sf.net",
1326 .open = cflac_open,
1327 .open2 = cflac_open2,
1328 .init = cflac_init,
1329 .free = cflac_free,
1330 .read = cflac_read,
1331 .seek = cflac_seek,
1332 .seek_sample = cflac_seek_sample,
1333 .insert = cflac_insert,
1334 .read_metadata = cflac_read_metadata,
1335 .write_metadata = cflac_write_metadata,
1336 .exts = exts,
1337 };
1338
1339 DB_plugin_t *
flac_load(DB_functions_t * api)1340 flac_load (DB_functions_t *api) {
1341 deadbeef = api;
1342 return DB_PLUGIN (&plugin);
1343 }
1344