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