1 /*
2 MusePack decoder plugin for DeaDBeeF Player
3 Copyright (C) 2009-2014 Alexey Yakovenko
4 Uses Musepack SV8 libs (r435), (C) 2005-2009, The Musepack Development Team
5
6 This software is provided 'as-is', without any express or implied
7 warranty. In no event will the authors be held liable for any damages
8 arising from the use of this software.
9
10 Permission is granted to anyone to use this software for any purpose,
11 including commercial applications, and to alter it and redistribute it
12 freely, subject to the following restrictions:
13
14 1. The origin of this software must not be misrepresented; you must not
15 claim that you wrote the original software. If you use this software
16 in a product, an acknowledgment in the product documentation would be
17 appreciated but is not required.
18
19 2. Altered source versions must be plainly marked as such, and must not be
20 misrepresented as being the original software.
21
22 3. This notice may not be removed or altered from any source distribution.
23 */
24
25 #include <string.h>
26 #include <stdlib.h>
27 #include <assert.h>
28 #include <limits.h>
29 #include <unistd.h>
30 #include <math.h>
31 #include "mpc/mpcdec.h"
32 #ifdef HAVE_CONFIG_H
33 # include <config.h>
34 #endif
35 #include "../../deadbeef.h"
36
37 #define min(x,y) ((x)<(y)?(x):(y))
38 #define max(x,y) ((x)>(y)?(x):(y))
39
40 //#define trace(...) { fprintf (stderr, __VA_ARGS__); }
41 #define trace(fmt,...)
42
43 static DB_decoder_t plugin;
44 static DB_functions_t *deadbeef;
45
46 typedef struct {
47 DB_fileinfo_t info;
48 mpc_streaminfo si;
49 mpc_demux *demux;
50 // mpc_decoder *mpcdec;
51 mpc_reader reader;
52 int currentsample;
53 int startsample;
54 int endsample;
55 mpc_uint32_t vbr_update_acc;
56 mpc_uint32_t vbr_update_bits;
57 MPC_SAMPLE_FORMAT buffer[MPC_DECODER_BUFFER_LENGTH];
58 int remaining;
59 } musepack_info_t;
60
musepack_vfs_read(mpc_reader * r,void * ptr,mpc_int32_t size)61 mpc_int32_t musepack_vfs_read (mpc_reader *r, void *ptr, mpc_int32_t size) {
62 return deadbeef->fread(ptr, 1, size, (DB_FILE *)r->data);
63 }
64
65 /// Seeks to byte position offset.
musepack_vfs_seek(mpc_reader * r,mpc_int32_t offset)66 mpc_bool_t musepack_vfs_seek (mpc_reader *r, mpc_int32_t offset) {
67 int res = deadbeef->fseek ((DB_FILE *)r->data, offset, SEEK_SET);
68 if (res == 0) {
69 return 1;
70 }
71 return 0;
72 }
73
74 /// Returns the current byte offset in the stream.
musepack_vfs_tell(mpc_reader * r)75 mpc_int32_t musepack_vfs_tell (mpc_reader *r) {
76 return deadbeef->ftell ((DB_FILE *)r->data);
77 }
78
79 /// Returns the total length of the source stream, in bytes.
musepack_vfs_get_size(mpc_reader * r)80 mpc_int32_t musepack_vfs_get_size (mpc_reader *r) {
81 return deadbeef->fgetlength ((DB_FILE *)r->data);
82 }
83
84 /// True if the stream is a seekable stream.
musepack_vfs_canseek(mpc_reader * r)85 mpc_bool_t musepack_vfs_canseek (mpc_reader *r) {
86 return 1;
87 }
88
89 static DB_fileinfo_t *
musepack_open(uint32_t hints)90 musepack_open (uint32_t hints) {
91 DB_fileinfo_t *_info = malloc (sizeof (musepack_info_t));
92 musepack_info_t *info = (musepack_info_t *)_info;
93 memset (info, 0, sizeof (musepack_info_t));
94 return _info;
95 }
96
97 static int
musepack_init(DB_fileinfo_t * _info,DB_playItem_t * it)98 musepack_init (DB_fileinfo_t *_info, DB_playItem_t *it) {
99 musepack_info_t *info = (musepack_info_t *)_info;
100
101 info->reader.read = musepack_vfs_read;
102 info->reader.seek = musepack_vfs_seek;
103 info->reader.tell = musepack_vfs_tell;
104 info->reader.get_size = musepack_vfs_get_size;
105 info->reader.canseek = musepack_vfs_canseek;
106
107 deadbeef->pl_lock ();
108 DB_FILE *fp = deadbeef->fopen (deadbeef->pl_find_meta (it, ":URI"));
109 deadbeef->pl_unlock ();
110 if (!fp) {
111 return -1;
112 }
113 info->reader.data = fp;
114
115 info->demux = mpc_demux_init (&info->reader);
116 if (!info->demux) {
117 fprintf (stderr, "mpc: mpc_demux_init failed\n");
118 deadbeef->fclose (fp);
119 info->reader.data = NULL;
120 return -1;
121 }
122 mpc_demux_get_info (info->demux, &info->si);
123
124 info->vbr_update_acc = 0;
125 info->vbr_update_bits = 0;
126 info->remaining = 0;
127
128 _info->fmt.is_float = 1;
129 _info->fmt.bps = 32;
130 _info->fmt.channels = info->si.channels;
131 _info->fmt.samplerate = info->si.sample_freq;
132 int i;
133 for (i = 0; i < _info->fmt.channels; i++) {
134 _info->fmt.channelmask |= 1 << i;
135 }
136 _info->readpos = 0;
137 _info->plugin = &plugin;
138
139 if (it->endsample > 0) {
140 info->startsample = it->startsample;
141 info->endsample = it->endsample;
142 plugin.seek_sample (_info, 0);
143 }
144 else {
145 info->startsample = 0;
146 info->endsample = mpc_streaminfo_get_length_samples (&info->si)-1;
147 }
148
149 return 0;
150 }
151
152 static void
musepack_free(DB_fileinfo_t * _info)153 musepack_free (DB_fileinfo_t *_info) {
154 musepack_info_t *info = (musepack_info_t *)_info;
155 if (info) {
156 if (info->demux) {
157 mpc_demux_exit (info->demux);
158 info->demux = NULL;
159 }
160 if (info->reader.data) {
161 deadbeef->fclose ((DB_FILE *)info->reader.data);
162 info->reader.data = NULL;
163 }
164 free (info);
165 }
166 }
167
168 #if 0
169 static int
170 musepack_read (DB_fileinfo_t *_info, char *bytes, int size) {
171 musepack_info_t *info = (musepack_info_t *)_info;
172
173 int samplesize = _info->fmt.bps / 8 * _info->fmt.channels;
174 if (info->currentsample + size / samplesize > info->endsample) {
175 size = (info->endsample - info->currentsample + 1) * samplesize;
176 if (size <= 0) {
177 return 0;
178 }
179 }
180
181 int initsize = size;
182
183 while (size > 0) {
184 if (info->remaining > 0) {
185 int n = size / samplesize;
186 n = min (n, info->remaining);
187 int nn = n;
188 float *p = info->buffer;
189 while (n > 0) {
190 int sample = (int)(*p * 32767.0f);
191 if (sample > 32767) {
192 sample = 32767;
193 }
194 else if (sample < -32768) {
195 sample = -32768;
196 }
197 *((int16_t *)bytes) = (int16_t)sample;
198 bytes += 2;
199 if (_info->fmt.channels == 2) {
200 sample = (int)(*(p+1) * 32767.0f);
201 if (sample > 32767) {
202 sample = 32767;
203 }
204 else if (sample < -32768) {
205 sample = -32768;
206 }
207 *((int16_t *)bytes) = (int16_t)sample;
208 bytes += 2;
209 }
210 n--;
211 size -= samplesize;
212 p += info->si.channels;
213 }
214 if (info->remaining > nn) {
215 memmove (info->buffer, p, (info->remaining - nn) * sizeof (float) * _info->fmt.channels);
216 }
217 info->remaining -= nn;
218 }
219
220 if (size > 0 && !info->remaining) {
221 mpc_frame_info frame;
222 frame.buffer = info->buffer;
223 mpc_status err = mpc_demux_decode (info->demux, &frame);
224 if (err != 0 || frame.bits == -1) {
225 break;
226 }
227
228 info->remaining = frame.samples;
229 }
230 }
231 info->currentsample += (initsize-size) / samplesize;
232 return initsize-size;
233 }
234 #endif
235
236 static int
musepack_read(DB_fileinfo_t * _info,char * bytes,int size)237 musepack_read (DB_fileinfo_t *_info, char *bytes, int size) {
238 musepack_info_t *info = (musepack_info_t *)_info;
239 int samplesize = _info->fmt.bps / 8 * _info->fmt.channels;
240
241 if (info->currentsample + size / samplesize > info->endsample) {
242 size = (info->endsample - info->currentsample + 1) * samplesize;
243 if (size <= 0) {
244 return 0;
245 }
246 }
247
248 int initsize = size;
249
250 while (size > 0) {
251 if (info->remaining > 0) {
252 int n = size / samplesize;
253 n = min (n, info->remaining);
254
255 memcpy (bytes, info->buffer, n * samplesize);
256
257 size -= n * samplesize;
258 bytes += n * samplesize;
259
260 if (info->remaining > n) {
261 memmove (info->buffer, ((char *)info->buffer) + n * samplesize, (info->remaining - n) * samplesize);
262 }
263 info->remaining -= n;
264 }
265
266 if (size > 0 && !info->remaining) {
267 mpc_frame_info frame;
268 frame.buffer = info->buffer;
269 mpc_status err = mpc_demux_decode (info->demux, &frame);
270 if (err != 0 || frame.bits == -1) {
271 break;
272 }
273
274 info->remaining = frame.samples;
275 }
276 }
277 info->currentsample += (initsize-size) / samplesize;
278 return initsize-size;
279 }
280
281 static int
musepack_seek_sample(DB_fileinfo_t * _info,int sample)282 musepack_seek_sample (DB_fileinfo_t *_info, int sample) {
283 musepack_info_t *info = (musepack_info_t *)_info;
284 mpc_status err = mpc_demux_seek_sample (info->demux, sample + info->startsample);
285 if (err != 0) {
286 fprintf (stderr, "musepack: seek failed\n");
287 return -1;
288 }
289 info->currentsample = sample + info->startsample;
290 _info->readpos = (float)sample / _info->fmt.samplerate;
291 info->remaining = 0;
292 return 0;
293 }
294
295 static int
musepack_seek(DB_fileinfo_t * _info,float time)296 musepack_seek (DB_fileinfo_t *_info, float time) {
297 musepack_info_t *info = (musepack_info_t *)_info;
298 return musepack_seek_sample (_info, time * _info->fmt.samplerate);
299 }
300
301 void
mpc_set_trk_properties(DB_playItem_t * it,mpc_streaminfo * si,int64_t fsize)302 mpc_set_trk_properties (DB_playItem_t *it, mpc_streaminfo *si, int64_t fsize) {
303 char s[100];
304 snprintf (s, sizeof (s), "%lld", fsize);
305 deadbeef->pl_add_meta (it, ":FILE_SIZE", s);
306 deadbeef->pl_add_meta (it, ":BPS", "32");
307 snprintf (s, sizeof (s), "%d", si->channels);
308 deadbeef->pl_add_meta (it, ":CHANNELS", s);
309 snprintf (s, sizeof (s), "%d", si->sample_freq);
310 deadbeef->pl_add_meta (it, ":SAMPLERATE", s);
311 snprintf (s, sizeof (s), "%d", (int)(si->average_bitrate/1000));
312 deadbeef->pl_add_meta (it, ":BITRATE", s);
313 snprintf (s, sizeof (s), "%f", si->profile);
314 deadbeef->pl_add_meta (it, ":MPC_QUALITY_PROFILE", s);
315 deadbeef->pl_add_meta (it, ":MPC_PROFILE_NAME", si->profile_name);
316 deadbeef->pl_add_meta (it, ":MPC_ENCODER", si->encoder);
317 snprintf (s, sizeof (s), "%d.%d", (si->encoder_version&0xff000000)>>24, (si->encoder_version&0x00ff0000)>>16);
318 deadbeef->pl_add_meta (it, ":MPC_ENCODER_VERSION", s);
319 deadbeef->pl_add_meta (it, ":MPC_PNS_USED", si->pns ? "1" : "0");
320 deadbeef->pl_add_meta (it, ":MPC_TRUE_GAPLESS", si->is_true_gapless ? "1" : "0");
321 snprintf (s, sizeof (s), "%lld", (int64_t)si->beg_silence);
322 deadbeef->pl_add_meta (it, ":MPC_BEG_SILENCE", s);
323 snprintf (s, sizeof (s), "%d", si->stream_version);
324 deadbeef->pl_add_meta (it, ":MPC_STREAM_VERSION", s);
325 snprintf (s, sizeof (s), "%d", si->max_band);
326 deadbeef->pl_add_meta (it, ":MPC_MAX_BAND", s);
327 deadbeef->pl_add_meta (it, ":MPC_MS", si->ms ? "1" : "0");
328 deadbeef->pl_add_meta (it, ":MPC_FAST_SEEK", si->fast_seek ? "1" : "0");
329 }
330
331 static DB_playItem_t *
musepack_insert(ddb_playlist_t * plt,DB_playItem_t * after,const char * fname)332 musepack_insert (ddb_playlist_t *plt, DB_playItem_t *after, const char *fname) {
333 trace ("mpc: inserting %s\n", fname);
334 mpc_reader reader = {
335 .read = musepack_vfs_read,
336 .seek = musepack_vfs_seek,
337 .tell = musepack_vfs_tell,
338 .get_size = musepack_vfs_get_size,
339 .canseek = musepack_vfs_canseek,
340 };
341
342 DB_FILE *fp = deadbeef->fopen (fname);
343 if (!fp) {
344 trace ("mpc: insert failed to open %s\n", fname);
345 return NULL;
346 }
347 int64_t fsize = deadbeef->fgetlength (fp);
348 reader.data = fp;
349
350 mpc_demux *demux = mpc_demux_init (&reader);
351 if (!demux) {
352 trace ("mpc: mpc_demux_init failed\n");
353 deadbeef->fclose (fp);
354 return NULL;
355 }
356
357 mpc_streaminfo si;
358 //mpc_streaminfo_init (&si);
359 mpc_demux_get_info (demux, &si);
360
361 int totalsamples = mpc_streaminfo_get_length_samples (&si);
362 double dur = mpc_streaminfo_get_length (&si);
363
364 // replay gain
365 float gain_title = 0.f;
366 float gain_album = 0.f;
367 float peak_title = 1.f;
368 float peak_album = 1.f;
369 if (si.gain_title != 0) {
370 gain_title = 64.82-si.gain_title/256.0;
371 }
372 if (si.gain_album != 0) {
373 gain_album = 64.82-si.gain_album/256.0;
374 }
375 if (si.peak_title != 0) {
376 peak_title = pow (10, si.peak_title / (20.0 * 256.0)) / (1<<15);
377 }
378 if (si.peak_album != 0) {
379 peak_album = pow (10, si.peak_album / (20.0 * 256.0)) / (1<<15);
380 }
381
382 // chapters
383 int nchapters = mpc_demux_chap_nb (demux);
384 DB_playItem_t *prev = NULL;
385 DB_playItem_t *meta = NULL;
386 if (nchapters > 1) {
387 int i;
388 for (i = 0; i < nchapters; i++) {
389 const mpc_chap_info *ch = mpc_demux_chap (demux, i);
390 DB_playItem_t *it = deadbeef->pl_item_alloc_init (fname, plugin.plugin.id);
391 deadbeef->pl_add_meta (it, ":FILETYPE", "MusePack");
392 deadbeef->pl_set_meta_int (it, ":TRACKNUM", i);
393 it->startsample = ch->sample;
394 it->endsample = totalsamples-1;
395 float gain = gain_title, peak = peak_title;
396 if (ch->gain != 0) {
397 gain = 64.82-ch->gain/256.0;
398 }
399 if (ch->peak != 0) {
400 peak = pow (10, ch->peak / (20.0 * 256.0)) / (1<<15);
401 }
402 deadbeef->pl_set_item_replaygain (it, DDB_REPLAYGAIN_ALBUMGAIN, gain_album);
403 deadbeef->pl_set_item_replaygain (it, DDB_REPLAYGAIN_ALBUMPEAK, peak_album);
404 deadbeef->pl_set_item_replaygain (it, DDB_REPLAYGAIN_TRACKGAIN, gain_title);
405 deadbeef->pl_set_item_replaygain (it, DDB_REPLAYGAIN_TRACKPEAK, peak_title);
406 if (!prev) {
407 meta = deadbeef->pl_item_alloc ();
408 /*int apeerr = */deadbeef->junk_apev2_read (meta, fp);
409 }
410 else {
411 prev->endsample = it->startsample-1;
412 float dur = (prev->endsample - prev->startsample) / (float)si.sample_freq;
413 deadbeef->plt_set_item_duration (plt, prev, dur);
414 }
415 if (i == nchapters - 1) {
416 float dur = (it->endsample - it->startsample) / (float)si.sample_freq;
417 deadbeef->plt_set_item_duration (plt, it, dur);
418 }
419 if (ch->tag_size > 0) {
420 uint8_t *tag = ch->tag;
421 deadbeef->junk_apev2_read_mem (it, ch->tag, ch->tag_size);
422 if (meta) {
423 deadbeef->pl_items_copy_junk (meta, it, it);
424 }
425 }
426
427 mpc_set_trk_properties (it, &si, fsize);
428
429 deadbeef->pl_set_item_flags (it, deadbeef->pl_get_item_flags (it) | DDB_IS_SUBTRACK);
430 after = deadbeef->plt_insert_item (plt, after, it);
431 prev = it;
432 deadbeef->pl_item_unref (it);
433 }
434 mpc_demux_exit (demux);
435 demux = NULL;
436 deadbeef->fclose (fp);
437 if (meta) {
438 deadbeef->pl_item_unref (meta);
439 }
440 return after;
441 }
442
443 DB_playItem_t *it = deadbeef->pl_item_alloc_init (fname, plugin.plugin.id);
444 deadbeef->pl_add_meta (it, ":FILETYPE", "MusePack");
445 deadbeef->plt_set_item_duration (plt, it, dur);
446
447 /*int apeerr = */deadbeef->junk_apev2_read (it, fp);
448 deadbeef->pl_set_item_replaygain (it, DDB_REPLAYGAIN_ALBUMGAIN, gain_album);
449 deadbeef->pl_set_item_replaygain (it, DDB_REPLAYGAIN_ALBUMPEAK, peak_album);
450 deadbeef->pl_set_item_replaygain (it, DDB_REPLAYGAIN_TRACKGAIN, gain_title);
451 deadbeef->pl_set_item_replaygain (it, DDB_REPLAYGAIN_TRACKPEAK, peak_title);
452
453 deadbeef->fclose (fp);
454
455 deadbeef->pl_lock ();
456
457 // embedded cue
458 const char *cuesheet = deadbeef->pl_find_meta (it, "cuesheet");
459 DB_playItem_t *cue = NULL;
460 if (cuesheet) {
461 cue = deadbeef->plt_insert_cue_from_buffer (plt, after, it, cuesheet, strlen (cuesheet), totalsamples, si.sample_freq);
462 if (cue) {
463 deadbeef->pl_item_unref (it);
464 deadbeef->pl_item_unref (cue);
465 deadbeef->pl_unlock ();
466 mpc_demux_exit (demux);
467 demux = NULL;
468 return cue;
469 }
470 }
471 deadbeef->pl_unlock ();
472
473 mpc_set_trk_properties (it, &si, fsize);
474 cue = deadbeef->plt_insert_cue (plt, after, it, totalsamples, si.sample_freq);
475 if (cue) {
476 deadbeef->pl_item_unref (it);
477 deadbeef->pl_item_unref (cue);
478 mpc_demux_exit (demux);
479 demux = NULL;
480
481 return cue;
482 }
483
484 deadbeef->pl_add_meta (it, "title", NULL);
485 after = deadbeef->plt_insert_item (plt, after, it);
486 deadbeef->pl_item_unref (it);
487
488 mpc_demux_exit (demux);
489 demux = NULL;
490
491 return after;
492 }
493
musepack_read_metadata(DB_playItem_t * it)494 static int musepack_read_metadata (DB_playItem_t *it) {
495 deadbeef->pl_lock ();
496 DB_FILE *fp = deadbeef->fopen (deadbeef->pl_find_meta (it, ":URI"));
497 deadbeef->pl_unlock ();
498 if (!fp) {
499 return -1;
500 }
501 deadbeef->pl_delete_all_meta (it);
502 /*int apeerr = */deadbeef->junk_apev2_read (it, fp);
503 deadbeef->pl_add_meta (it, "title", NULL);
504 deadbeef->fclose (fp);
505 return 0;
506 }
507
musepack_write_metadata(DB_playItem_t * it)508 static int musepack_write_metadata (DB_playItem_t *it) {
509 // get options
510 int strip_apev2 = deadbeef->conf_get_int ("ape.strip_apev2", 0);
511 int write_apev2 = deadbeef->conf_get_int ("ape.write_apev2", 1);
512
513 uint32_t junk_flags = 0;
514 if (strip_apev2) {
515 junk_flags |= JUNK_STRIP_APEV2;
516 }
517 if (write_apev2) {
518 junk_flags |= JUNK_WRITE_APEV2;
519 }
520
521 return deadbeef->junk_rewrite_tags (it, junk_flags, 4, NULL);
522 }
523
524
525 static int
musepack_start(void)526 musepack_start (void) {
527 return 0;
528 }
529
530 static int
musepack_stop(void)531 musepack_stop (void) {
532 return 0;
533 }
534
535 static const char * exts[] = { "mpc", "mpp", "mp+", NULL };
536
537 // define plugin interface
538 static DB_decoder_t plugin = {
539 .plugin.api_vmajor = 1,
540 .plugin.api_vminor = 0,
541 .plugin.version_major = 1,
542 .plugin.version_minor = 0,
543 .plugin.type = DB_PLUGIN_DECODER,
544 .plugin.id = "musepack",
545 .plugin.name = "MusePack decoder",
546 .plugin.descr = "Musepack decoder using libmppdec",
547 .plugin.copyright =
548 "MusePack decoder plugin for DeaDBeeF Player\n"
549 "Copyright (C) 2009-2014 Alexey Yakovenko\n"
550 "Uses Musepack SV8 libs (r435), (C) 2005-2009, The Musepack Development Team\n"
551 "\n"
552 "This software is provided 'as-is', without any express or implied\n"
553 "warranty. In no event will the authors be held liable for any damages\n"
554 "arising from the use of this software.\n"
555 "\n"
556 "Permission is granted to anyone to use this software for any purpose,\n"
557 "including commercial applications, and to alter it and redistribute it\n"
558 "freely, subject to the following restrictions:\n"
559 "\n"
560 "1. The origin of this software must not be misrepresented; you must not\n"
561 " claim that you wrote the original software. If you use this software\n"
562 " in a product, an acknowledgment in the product documentation would be\n"
563 " appreciated but is not required.\n"
564 "\n"
565 "2. Altered source versions must be plainly marked as such, and must not be\n"
566 " misrepresented as being the original software.\n"
567 "\n"
568 "3. This notice may not be removed or altered from any source distribution.\n"
569 ,
570 .plugin.website = "http://deadbeef.sf.net",
571 .plugin.start = musepack_start,
572 .plugin.stop = musepack_stop,
573 .open = musepack_open,
574 .init = musepack_init,
575 .free = musepack_free,
576 .read = musepack_read,
577 .seek = musepack_seek,
578 .seek_sample = musepack_seek_sample,
579 .insert = musepack_insert,
580 .read_metadata = musepack_read_metadata,
581 .write_metadata = musepack_write_metadata,
582 .exts = exts,
583 };
584
585 DB_plugin_t *
musepack_load(DB_functions_t * api)586 musepack_load (DB_functions_t *api) {
587 deadbeef = api;
588 return DB_PLUGIN (&plugin);
589 }
590