server: Fix --autoplay-delay.
[paraslash.git] / flac_afh.c
1 /*
2  * Copyright (C) 2011 Andre Noll <maan@tuebingen.mpg.de>
3  *
4  * Licensed under the GPL v2. For licencing details see COPYING.
5  */
6
7 /** \file flac_afh.c Audio format handler for flac files. */
8
9 #include <regex.h>
10 #include <FLAC/stream_decoder.h>
11 #include <FLAC/metadata.h>
12
13 #include "para.h"
14 #include "error.h"
15 #include "afh.h"
16 #include "string.h"
17 #include "fd.h"
18
19 struct private_flac_afh_data {
20         const char *map;
21         size_t map_bytes;
22         size_t fpos;
23         struct afh_info *afhi;
24         unsigned blocksize;
25 };
26
27 static size_t copy_data(struct private_flac_afh_data *pfad, void *buf,
28                 size_t want)
29 {
30         size_t copy, have = pfad->map_bytes - pfad->fpos;
31
32         if (have == 0)
33                 return 0;
34         copy = have < want? have : want;
35         memcpy(buf, pfad->map + pfad->fpos, copy);
36         pfad->fpos += copy;
37         return copy;
38 }
39
40 static size_t meta_read_cb(void *ptr, size_t size, size_t nmemb,
41                 FLAC__IOHandle handle)
42 {
43         struct private_flac_afh_data *pfad = handle;
44         return copy_data(pfad, ptr, nmemb * size);
45 }
46
47 static int meta_seek_cb(FLAC__IOHandle handle, FLAC__int64 offset, int whence)
48 {
49         struct private_flac_afh_data *pfad = handle;
50
51         if (offset < 0)
52                 return -1;
53
54         switch (whence) {
55         case SEEK_SET:
56                 if (offset >= pfad->map_bytes)
57                         return -1;
58                 pfad->fpos = offset;
59                 return 0;
60         case SEEK_CUR:
61                 if (pfad->fpos + offset >= pfad->map_bytes)
62                         return -1;
63                 pfad->fpos += offset;
64                 return 0;
65         case SEEK_END:
66                 if (offset >= pfad->map_bytes)
67                         return -1;
68                 pfad->fpos = offset;
69                 return 0;
70         default:
71                 return -1;
72         }
73 }
74
75 static FLAC__int64 meta_tell_cb(FLAC__IOHandle handle)
76 {
77         struct private_flac_afh_data *pfad = handle;
78         return pfad->fpos;
79 }
80
81 static int meta_eof_cb(FLAC__IOHandle handle)
82 {
83         struct private_flac_afh_data *pfad = handle;
84         return pfad->fpos == pfad->map_bytes;
85 }
86
87 static int meta_close_cb(FLAC__IOHandle __a_unused handle)
88 {
89         return 0;
90 }
91
92 static const FLAC__IOCallbacks meta_callbacks = {
93         .read = meta_read_cb,
94         .write = NULL,
95         .seek = meta_seek_cb,
96         .tell = meta_tell_cb,
97         .eof = meta_eof_cb,
98         .close = meta_close_cb
99 };
100
101 static void free_tags(struct taginfo *tags)
102 {
103         freep(&tags->artist);
104         freep(&tags->title);
105         freep(&tags->album);
106         freep(&tags->year);
107         freep(&tags->comment);
108 }
109
110 static bool copy_if_tag_type(const char *tag, int taglen, const char *type,
111                 char **p)
112 {
113         char *q = key_value_copy(tag, taglen, type);
114         if (!q)
115                 return false;
116         free(*p);
117         *p = q;
118         return true;
119 }
120
121 static void flac_read_vorbis_comments(FLAC__StreamMetadata_VorbisComment *vc,
122                 struct taginfo *tags)
123 {
124         int i;
125         FLAC__StreamMetadata_VorbisComment_Entry *comment = vc->comments;
126
127         PARA_INFO_LOG("found %u vorbis comments\n", vc->num_comments);
128         for (i = 0; i < vc->num_comments; i++) {
129                 char *e = (char *)comment[i].entry;
130                 int len = comment[i].length;
131                 if (copy_if_tag_type(e, len, "artist", &tags->artist))
132                         continue;
133                 if (copy_if_tag_type(e, len, "title", &tags->title))
134                         continue;
135                 if (copy_if_tag_type(e, len, "album", &tags->album))
136                         continue;
137                 if (copy_if_tag_type(e, len, "year", &tags->year))
138                         continue;
139                 if (copy_if_tag_type(e, len, "comment", &tags->comment))
140                         continue;
141         }
142 }
143
144 /*
145  * FLAC__metadata_object_vorbiscomment_replace_comment() is buggy in some
146  * libFLAC versions (see commit e95399c1 in the flac git repository). Hence we
147  * use delete and add as a workaround.
148  */
149 static int flac_replace_vorbis_comment(FLAC__StreamMetadata *b,
150                 const char *tag, const char* val)
151 {
152         FLAC__bool ok;
153         FLAC__StreamMetadata_VorbisComment_Entry entry;
154         int ret;
155
156         PARA_INFO_LOG("replacing %s\n", tag);
157         ret = FLAC__metadata_object_vorbiscomment_remove_entries_matching(
158                 b, tag);
159         if (ret < 0)
160                 return -E_FLAC_REPLACE_COMMENT;
161         ok = FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(
162                 &entry, tag, val? val : "");
163         if (!ok)
164                 return -E_FLAC_REPLACE_COMMENT;
165         ok = FLAC__metadata_object_vorbiscomment_append_comment(b, entry,
166                 false /* no copy */);
167         if (!ok) {
168                 free(entry.entry);
169                 return -E_FLAC_REPLACE_COMMENT;
170         }
171         return 1;
172 }
173
174 static int flac_replace_vorbis_comments(FLAC__Metadata_Chain *chain,
175                 FLAC__StreamMetadata *b, struct taginfo *tags)
176 {
177         FLAC__bool ok;
178         int ret;
179
180         ret = flac_replace_vorbis_comment(b, "artist", tags->artist);
181         if (ret < 0)
182                 return ret;
183         ret = flac_replace_vorbis_comment(b, "title", tags->title);
184         if (ret < 0)
185                 return ret;
186         ret = flac_replace_vorbis_comment(b, "album", tags->album);
187         if (ret < 0)
188                 return ret;
189         ret = flac_replace_vorbis_comment(b, "year", tags->year);
190         if (ret < 0)
191                 return ret;
192         ret = flac_replace_vorbis_comment(b, "comment", tags->comment);
193         if (ret < 0)
194                 return ret;
195         /*
196          * Even if padding is disabled, libflac will try to modify the original
197          * file inplace if the metadata size has not changed. This won't work
198          * here though, because the original file is mapped read-only. Since
199          * there is no option to force the use of a temp file we work around
200          * this shortcoming by adding a dummy entry which increases the size of
201          * the meta data. If the entry already exists, we simply remove it.
202          */
203         ok = FLAC__metadata_chain_check_if_tempfile_needed(chain,
204                 false /* no padding */);
205         if (!ok) {
206                 PARA_INFO_LOG("adding/removing dummy comment\n");
207                 ret = FLAC__metadata_object_vorbiscomment_remove_entries_matching(
208                         b, "comment2");
209                 if (ret < 0)
210                         return -E_FLAC_REPLACE_COMMENT;
211                 if (ret == 0) { /* nothing was removed */
212                         ret = flac_replace_vorbis_comment(b, "comment2",
213                                 "avoid inplace write");
214                         if (ret < 0)
215                                 return ret;
216                 }
217                 assert(FLAC__metadata_chain_check_if_tempfile_needed(chain,
218                         false /* no padding */));
219         }
220         return 1;
221 }
222
223 static int flac_init_meta(struct private_flac_afh_data *pfad,
224                 FLAC__Metadata_Chain **chainp, FLAC__Metadata_Iterator **iterp)
225 {
226         int ret;
227         FLAC__bool ok;
228         FLAC__Metadata_Chain *chain;
229         FLAC__Metadata_Iterator *iter;
230
231         *chainp = NULL;
232         *iterp = NULL;
233         chain = FLAC__metadata_chain_new();
234         if (!chain)
235                 return -E_FLAC_CHAIN_ALLOC;
236         ret = -E_FLAC_CHAIN_READ;
237         ok = FLAC__metadata_chain_read_with_callbacks(chain, pfad,
238                 meta_callbacks);
239         if (!ok)
240                 goto free_chain;
241         ret = -E_FLAC_ITER_ALLOC;
242         iter = FLAC__metadata_iterator_new();
243         if (!iter)
244                 goto free_chain;
245         FLAC__metadata_iterator_init(iter, chain);
246         *iterp = iter;
247         *chainp = chain;
248         return 1;
249 free_chain:
250         FLAC__metadata_chain_delete(chain);
251         return ret;
252 }
253
254 static int flac_read_meta(struct private_flac_afh_data *pfad)
255 {
256         int ret;
257         FLAC__Metadata_Chain *chain;
258         FLAC__Metadata_Iterator *iter;
259         FLAC__StreamMetadata_StreamInfo *info = NULL;
260         FLAC__bool ok;
261
262         ret = flac_init_meta(pfad, &chain, &iter);
263         if (ret < 0)
264                 return ret;
265         for (;;) {
266                 FLAC__StreamMetadata *b;
267                 b = FLAC__metadata_iterator_get_block(iter);
268                 if (!b)
269                         break;
270                 if (b->type == FLAC__METADATA_TYPE_STREAMINFO) {
271                         info = &b->data.stream_info;
272                         ret = -E_FLAC_VARBLOCK;
273                         if (info->min_blocksize != info->max_blocksize)
274                                 goto free_iter;
275                         pfad->afhi->frequency = info->sample_rate;
276                         pfad->afhi->channels = info->channels;
277                         pfad->blocksize = info->min_blocksize;
278                 }
279                 if (b->type == FLAC__METADATA_TYPE_VORBIS_COMMENT)
280                         flac_read_vorbis_comments(&b->data.vorbis_comment,
281                                 &pfad->afhi->tags);
282                 ok = FLAC__metadata_iterator_next(iter);
283                 if (!ok)
284                         break;
285         }
286         ret = info? 0: -E_FLAC_STREAMINFO;
287 free_iter:
288         FLAC__metadata_iterator_delete(iter);
289         FLAC__metadata_chain_delete(chain);
290         if (ret < 0)
291                 free_tags(&pfad->afhi->tags);
292         return ret;
293 }
294
295 static FLAC__StreamDecoderReadStatus read_cb(
296                 __a_unused const FLAC__StreamDecoder *decoder,
297                 FLAC__byte buffer[], size_t *bytes, void *client_data)
298 {
299         struct private_flac_afh_data *pfad = client_data;
300
301         assert(*bytes > 0);
302         *bytes = copy_data(pfad, buffer, *bytes);
303         if (*bytes == 0)
304                 return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
305         else
306                 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
307 }
308
309 static FLAC__StreamDecoderTellStatus tell_cb(
310                 __a_unused const FLAC__StreamDecoder *decoder,
311                 FLAC__uint64 *absolute_byte_offset, void *client_data)
312 {
313         struct private_flac_afh_data *pfad = client_data;
314
315         *absolute_byte_offset = pfad->fpos;
316         return FLAC__STREAM_DECODER_TELL_STATUS_OK;
317 }
318
319 /* libflac insists on this callback being present. */
320 static FLAC__StreamDecoderWriteStatus write_cb(
321                 __a_unused const FLAC__StreamDecoder *decoder,
322                 __a_unused const FLAC__Frame *frame,
323                 __a_unused const FLAC__int32 *const buffer[],
324                 __a_unused void *client_data)
325 {
326         return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
327 }
328
329 static void error_cb(
330                 __a_unused const FLAC__StreamDecoder *decoder,
331                 FLAC__StreamDecoderErrorStatus status,
332                 __a_unused void *client_data)
333 {
334         PARA_ERROR_LOG("%s\n", FLAC__StreamDecoderErrorStatusString[status]);
335 }
336
337 static int flac_afh_read_chunks(struct private_flac_afh_data *pfad)
338 {
339         FLAC__StreamDecoder *decoder;
340         FLAC__StreamDecoderInitStatus init_status;
341         FLAC__bool ok;
342         FLAC__uint64 c;
343         unsigned chunk_table_size = 0;
344         int ret;
345         struct afh_info *afhi = pfad->afhi;
346
347         PARA_INFO_LOG("reading chunk table\n");
348         afhi->chunk_table = NULL;
349         decoder = FLAC__stream_decoder_new();
350         if (!decoder)
351                 return -E_FLAC_AFH_DECODER_ALLOC;
352         ret = -E_FLAC_AFH_DECODER_INIT;
353         init_status = FLAC__stream_decoder_init_stream(
354                 decoder,
355                 read_cb,
356                 NULL, /* seek */
357                 tell_cb,
358                 NULL, /* length */
359                 NULL, /* eof */
360                 write_cb,
361                 NULL,
362                 error_cb,
363                 pfad
364         );
365         if (init_status != FLAC__STREAM_DECODER_INIT_STATUS_OK)
366                 goto free_decoder;
367         ret = -E_FLAC_SKIP_META;
368         ok = FLAC__stream_decoder_process_until_end_of_metadata(decoder);
369         if (!ok)
370                 goto free_decoder;
371         for (c = 0;; c++) {
372                 FLAC__uint64 pos;
373                 FLAC__StreamDecoderState state;
374
375                 ret = -E_FLAC_DECODE_POS;
376                 ok = FLAC__stream_decoder_get_decode_position(decoder, &pos);
377                 if (!ok)
378                         goto free_decoder;
379                 if (c >= chunk_table_size) {
380                         chunk_table_size = 2 * chunk_table_size + 100;
381                         afhi->chunk_table = para_realloc(afhi->chunk_table,
382                                 chunk_table_size * sizeof(uint32_t));
383                 }
384                 afhi->chunk_table[c] = pos;
385
386                 ok = FLAC__stream_decoder_skip_single_frame(decoder);
387                 if (!ok)
388                         break;
389                 state = FLAC__stream_decoder_get_state(decoder);
390                 if (state == FLAC__STREAM_DECODER_END_OF_STREAM)
391                         break;
392         }
393         afhi->chunks_total = c;
394         ret = 1;
395 free_decoder:
396         FLAC__stream_decoder_finish(decoder);
397         FLAC__stream_decoder_delete(decoder);
398         if (ret < 0)
399                 freep(&afhi->chunk_table);
400         return ret;
401 }
402
403 static int flac_get_file_info(char *map, size_t map_bytes, __a_unused int fd,
404                 struct afh_info *afhi)
405 {
406         struct private_flac_afh_data pfad_struct = {
407                 .map = map,
408                 .map_bytes = map_bytes,
409                 .afhi = afhi
410         }, *pfad = &pfad_struct;
411         int ret;
412         double chunk_time;
413
414         afhi->header_len = 0;
415         ret = flac_read_meta(pfad);
416         if (ret < 0)
417                 return ret;
418         pfad->fpos = 0;
419         ret = flac_afh_read_chunks(pfad);
420         if (ret < 0) {
421                 free_tags(&afhi->tags);
422                 return ret;
423         }
424         afhi->techinfo = make_message("blocksize: %u", pfad->blocksize);
425         afhi->seconds_total = DIV_ROUND_UP(afhi->chunks_total * pfad->blocksize,
426                 afhi->frequency);
427         afhi->bitrate = pfad->map_bytes * 8 / afhi->seconds_total / 1024;
428         chunk_time = (double)pfad->blocksize / afhi->frequency;
429         afhi->chunk_tv.tv_sec = chunk_time;
430         chunk_time *= 1000 * 1000;
431         chunk_time -= afhi->chunk_tv.tv_sec * 1000 * 1000;
432         afhi->chunk_tv.tv_usec = chunk_time;
433         return 1;
434 }
435
436 static size_t temp_write_cb(const void *ptr, size_t size, size_t nmemb,
437         FLAC__IOHandle handle)
438 {
439         int ret, fd = *(int *)handle;
440         size_t n = size * nmemb; /* FIXME: possible overflow */
441
442         ret = write_all(fd, ptr, n);
443
444         /*
445          * libflac expects POSIX semantics: If an error occurs, or the end of
446          * the file is reached, the return value is a short item count or zero.
447          */
448         if (ret < 0) {
449                 PARA_ERROR_LOG("%s\n", para_strerror(-ret));
450                 return 0;
451         }
452         return nmemb;
453 }
454
455 /* only the write callback needs to be supplied for writing the temp file. */
456 static const FLAC__IOCallbacks temp_callbacks = {
457         .write = temp_write_cb,
458 };
459
460 static int flac_write_chain(FLAC__Metadata_Chain *chain,
461                 struct private_flac_afh_data *pfad, int fd)
462 {
463         FLAC__bool ok;
464
465         ok = FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain,
466                 false /* no padding*/, pfad,
467                 meta_callbacks, &fd, temp_callbacks);
468         if (!ok) {
469                 FLAC__Metadata_ChainStatus st;
470                 st = FLAC__metadata_chain_status(chain);
471                 PARA_ERROR_LOG("chain status: %d\n", st);
472                 if (st == FLAC__METADATA_CHAIN_STATUS_READ_ERROR)
473                         PARA_ERROR_LOG("read error\n");
474                 return -E_FLAC_WRITE_CHAIN;
475         }
476         return 1;
477 }
478
479 static int flac_rewrite_tags(const char *map, size_t map_bytes,
480                 struct taginfo *tags, int fd, __a_unused const char *filename)
481 {
482         int ret;
483         FLAC__Metadata_Chain *chain;
484         FLAC__Metadata_Iterator *iter;
485         FLAC__StreamMetadata *b = NULL;
486         FLAC__bool ok;
487         struct private_flac_afh_data *pfad = para_calloc(sizeof(*pfad));
488
489         pfad->map = map;
490         pfad->map_bytes = map_bytes;
491         pfad->fpos = 0;
492
493         ret = flac_init_meta(pfad, &chain, &iter);
494         if (ret < 0)
495                 goto free_pfad;
496         for (ok = true; ok; ok = FLAC__metadata_iterator_next(iter)) {
497                 b = FLAC__metadata_iterator_get_block(iter);
498                 assert(b);
499                 if (b->type == FLAC__METADATA_TYPE_VORBIS_COMMENT)
500                         break;
501                 b = NULL;
502         }
503         ret = -E_FLAC_REPLACE_COMMENT;
504         if (!b)
505                 goto out;
506         ret = flac_replace_vorbis_comments(chain, b, tags);
507         if (ret < 0)
508                 goto out;
509         ret = flac_write_chain(chain, pfad, fd);
510 out:
511         FLAC__metadata_iterator_delete(iter);
512         FLAC__metadata_chain_delete(chain);
513 free_pfad:
514         free(pfad);
515         return ret;
516 }
517
518 static const char * const flac_suffixes[] = {"flac", NULL};
519
520 /**
521  * The init function of the flac audio format handler.
522  *
523  * \param afh pointer to the struct to initialize
524  */
525 void flac_afh_init(struct audio_format_handler *afh)
526 {
527         afh->get_file_info = flac_get_file_info,
528         afh->suffixes = flac_suffixes;
529         afh->rewrite_tags = flac_rewrite_tags;
530 }