// prepare to decode the track, fill in mandatory plugin fields // return -1 on failure static int example_init (DB_fileinfo_t *_info, DB_playItem_t *it) { example_info_t *info = (example_info_t *)_info; // take this parameters from your input file // we set constants for clarity sake _info->fmt.bps = 16; _info->fmt.channels = 2; _info->fmt.samplerate = 44100; for (int i = 0; i < _info->fmt.channels; i++) { _info->fmt.channelmask |= 1 << i; } _info->readpos = 0; _info->plugin = &plugin; if (it->endsample > 0) { info->startsample = it->startsample; info->endsample = it->endsample; plugin.seek_sample (_info, 0); } else { info->startsample = 0; int TOTALSAMPLES = 1000; // calculate from file info->endsample = TOTALSAMPLES-1; } return 0; }
static int tta_init (DB_fileinfo_t *_info, DB_playItem_t *it) { tta_info_t *info = (tta_info_t *)_info; deadbeef->pl_lock (); const char *fname = deadbeef->pl_find_meta (it, ":URI") trace ("open_tta_file %s\n", fname); if (open_tta_file (fname, &info->tta, 0) != 0) { deadbeef->pl_unlock (); fprintf (stderr, "tta: failed to open %s\n", fname); return -1; } if (player_init (&info->tta) != 0) { deadbeef->pl_unlock (); fprintf (stderr, "tta: failed to init player for %s\n", fname); return -1; } deadbeef->pl_unlock (); _info->fmt.bps = info->tta.BPS; _info->fmt.channels = info->tta.NCH; _info->fmt.samplerate = info->tta.SAMPLERATE; for (int i = 0; i < _info->fmt.channels; i++) { _info->fmt.channelmask |= 1 << i; } _info->readpos = 0; _info->plugin = &plugin; int64_t endsample = deadbeef->pl_item_get_endsample (it); if (endsample > 0) { info->startsample = deadbeef->pl_item_get_startsample (it); info->endsample = endsample; plugin.seek_sample (_info, 0); } else { info->startsample = 0; info->endsample = (info->tta.DATALENGTH)-1; } trace ("open_tta_file %s success!\n", deadbeef->pl_find_meta (it, ":URI")); return 0; }
static int aac_init (DB_fileinfo_t *_info, DB_playItem_t *it) { aac_info_t *info = (aac_info_t *)_info; info->file = deadbeef->fopen (deadbeef->pl_find_meta (it, ":URI")); if (!info->file) { return -1; } // probe float duration = -1; int samplerate = -1; int channels = -1; int totalsamples = -1; info->junk = deadbeef->junk_get_leading_size (info->file); if (!info->file->vfs->is_streaming ()) { if (info->junk >= 0) { deadbeef->fseek (info->file, info->junk, SEEK_SET); } else { info->junk = 0; } } else { deadbeef->fset_track (info->file, it); } info->mp4track = -1; #if USE_MP4FF info->mp4reader.read = aac_fs_read; info->mp4reader.write = NULL; info->mp4reader.seek = aac_fs_seek; info->mp4reader.truncate = NULL; info->mp4reader.user_data = info; #else info->mp4reader.open = aac_fs_open; info->mp4reader.seek = aac_fs_seek; info->mp4reader.read = aac_fs_read; info->mp4reader.write = NULL; info->mp4reader.close = aac_fs_close; #endif if (!info->file->vfs->is_streaming ()) { #ifdef USE_MP4FF trace ("aac_init: mp4ff_open_read %s\n", deadbeef->pl_find_meta (it, ":URI")); info->mp4file = mp4ff_open_read (&info->mp4reader); if (info->mp4file) { int ntracks = mp4ff_total_tracks (info->mp4file); if (ntracks > 0) { trace ("m4a container detected, ntracks=%d\n", ntracks); int i = -1; unsigned char* buff = 0; unsigned int buff_size = 0; for (i = 0; i < ntracks; i++) { mp4AudioSpecificConfig mp4ASC; mp4ff_get_decoder_config (info->mp4file, i, &buff, &buff_size); if(buff){ int rc = AudioSpecificConfig(buff, buff_size, &mp4ASC); if(rc < 0) continue; break; } } trace ("mp4 probe-buffer size: %d\n", buff_size); if (i != ntracks && buff) { trace ("mp4 track: %d\n", i); int samples = mp4ff_num_samples(info->mp4file, i); info->mp4samples = samples; info->mp4track = i; // init mp4 decoding info->dec = NeAACDecOpen (); unsigned long srate; unsigned char ch; if (NeAACDecInit2(info->dec, buff, buff_size, &srate, &ch) < 0) { trace ("NeAACDecInit2 returned error\n"); free (buff); return -1; } samplerate = srate; channels = ch; samples = (int64_t)samples * srate / mp4ff_time_scale (info->mp4file, i); totalsamples = samples; NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration (info->dec); conf->dontUpSampleImplicitSBR = 1; NeAACDecSetConfiguration (info->dec, conf); mp4AudioSpecificConfig mp4ASC; if (NeAACDecAudioSpecificConfig(buff, buff_size, &mp4ASC) >= 0) { info->mp4framesize = 1024; if (mp4ASC.frameLengthFlag == 1) { info->mp4framesize = 960; } // if (mp4ASC.sbr_present_flag == 1) { // info->mp4framesize *= 2; // } } totalsamples *= info->mp4framesize; duration = (float)totalsamples / samplerate; } else { mp4ff_close (info->mp4file); info->mp4file = NULL; } if (buff) { free (buff); } } else { mp4ff_close (info->mp4file); info->mp4file = NULL; } } // {{{ libmp4v2 code #else trace ("aac_init: MP4ReadProvider %s\n", deadbeef->pl_find_meta (it, ":URI")); info->mp4file = MP4ReadProvider (deadbeef->pl_find_meta (it, ":URI"), 0, &info->mp4reader); info->mp4track = MP4FindTrackId(info->mp4file, 0, "audio", 0); trace ("aac_init: MP4FindTrackId returned %d\n", info->mp4track); if (info->mp4track >= 0) { info->timescale = MP4GetTrackTimeScale(info->mp4file, info->mp4track); u_int8_t* pConfig; uint32_t configSize = 0; bool res = MP4GetTrackESConfiguration(info->mp4file, info->mp4track, &pConfig, &configSize); mp4AudioSpecificConfig mp4ASC; int rc = AudioSpecificConfig(pConfig, configSize, &mp4ASC); if (rc >= 0) { _info->samplerate = mp4ASC.samplingFrequency; _info->channels = MP4GetTrackAudioChannels (info->mp4file, info->mp4track); totalsamples = MP4GetTrackNumberOfSamples (info->mp4file, info->mp4track) * 1024 * _info->channels; // init mp4 decoding info->dec = NeAACDecOpen (); unsigned long srate; unsigned char ch; if (NeAACDecInit2(info->dec, pConfig, configSize, &srate, &ch) < 0) { trace ("NeAACDecInit2 returned error\n"); return -1; } samplerate = srate; channels = ch; NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration (info->dec); conf->dontUpSampleImplicitSBR = 1; NeAACDecSetConfiguration (info->dec, conf); mp4AudioSpecificConfig mp4ASC; if (NeAACDecAudioSpecificConfig(pConfig, configSize, &mp4ASC) >= 0) { info->mp4framesize = 1024; if (mp4ASC.frameLengthFlag == 1) { info->mp4framesize = 960; } // if (mp4ASC.sbr_present_flag == 1) { // info->mp4framesize *= 2; // } } //totalsamples *= info->mp4framesize; free (pConfig); info->maxSampleSize = MP4GetTrackMaxSampleSize(info->mp4file, info->mp4track); info->samplebuffer = malloc (info->maxSampleSize); info->mp4sample = 1; } else { MP4Close (info->mp4file); info->mp4file = NULL; } } else { MP4Close (info->mp4file); info->mp4file = NULL; } #endif // }}} if (!info->mp4file) { trace ("mp4 track not found, looking for aac stream...\n"); if (info->junk >= 0) { deadbeef->fseek (info->file, info->junk, SEEK_SET); } else { deadbeef->rewind (info->file); } int offs = parse_aac_stream (info->file, &samplerate, &channels, &duration, &totalsamples); if (offs == -1) { trace ("aac stream not found\n"); return -1; } if (offs > info->junk) { info->junk = offs; } if (info->junk >= 0) { deadbeef->fseek (info->file, info->junk, SEEK_SET); } else { deadbeef->rewind (info->file); } trace ("found aac stream (junk: %d, offs: %d)\n", info->junk, offs); } _info->fmt.channels = channels; _info->fmt.samplerate = samplerate; } else { // sync before attempting to init int samplerate, channels; float duration; int offs = parse_aac_stream (info->file, &samplerate, &channels, &duration, NULL); if (offs < 0) { trace ("aac: parse_aac_stream failed\n"); return -1; } if (offs > info->junk) { info->junk = offs; } trace("parse_aac_stream returned %x\n", offs); deadbeef->pl_replace_meta (it, "!FILETYPE", "AAC"); } // duration = (float)totalsamples / samplerate; // deadbeef->pl_set_item_duration (it, duration); _info->fmt.bps = 16; _info->plugin = &plugin; if (!info->mp4file) { //trace ("NeAACDecGetCapabilities\n"); //unsigned long caps = NeAACDecGetCapabilities(); trace ("NeAACDecOpen\n"); info->dec = NeAACDecOpen (); trace ("prepare for NeAACDecInit: fread %d from offs %lld\n", AAC_BUFFER_SIZE, deadbeef->ftell (info->file)); info->remaining = deadbeef->fread (info->buffer, 1, AAC_BUFFER_SIZE, info->file); NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration (info->dec); // conf->dontUpSampleImplicitSBR = 1; NeAACDecSetConfiguration (info->dec, conf); unsigned long srate; unsigned char ch; trace ("NeAACDecInit (%d bytes)\n", info->remaining); int consumed = NeAACDecInit (info->dec, info->buffer, info->remaining, &srate, &ch); trace ("NeAACDecInit returned samplerate=%d, channels=%d, consumed: %d\n", (int)srate, (int)ch, consumed); if (consumed < 0) { trace ("NeAACDecInit returned %d\n", consumed); return -1; } if (consumed > info->remaining) { trace ("NeAACDecInit consumed more than available! wtf?\n"); return -1; } if (consumed == info->remaining) { info->remaining = 0; } else if (consumed > 0) { memmove (info->buffer, info->buffer + consumed, info->remaining - consumed); info->remaining -= consumed; } _info->fmt.channels = ch; _info->fmt.samplerate = srate; } if (!info->file->vfs->is_streaming ()) { if (it->endsample > 0) { info->startsample = it->startsample; info->endsample = it->endsample; plugin.seek_sample (_info, 0); } else { info->startsample = 0; info->endsample = totalsamples-1; } } trace ("totalsamples: %d, endsample: %d, samples-from-duration: %d\n", totalsamples-1, info->endsample, (int)deadbeef->pl_get_item_duration (it)*44100); for (int i = 0; i < _info->fmt.channels; i++) { _info->fmt.channelmask |= 1 << i; } info->noremap = 0; info->remap[0] = -1; trace ("init success\n"); return 0; }
static int wv_init (DB_fileinfo_t *_info, DB_playItem_t *it) { wvctx_t *info = (wvctx_t *)_info; deadbeef->pl_lock (); info->file = deadbeef->fopen (deadbeef->pl_find_meta (it, ":URI")); deadbeef->pl_unlock (); if (!info->file) { return -1; } #ifndef TINYWV deadbeef->pl_lock (); const char *uri = deadbeef->pl_find_meta (it, ":URI"); char *c_fname = alloca (strlen (uri) + 2); if (c_fname) { strcpy (c_fname, uri); strcat (c_fname, "c"); info->c_file = deadbeef->fopen (c_fname); } else { fprintf (stderr, "wavpack warning: failed to alloc memory for correction file name\n"); } deadbeef->pl_unlock (); #endif char error[80]; #ifdef TINYWV info->ctx = WavpackOpenFileInput (wv_read_stream, info->file, error); #else info->ctx = WavpackOpenFileInputEx (&wsr, info->file, info->c_file, error, OPEN_NORMALIZE, 0); #endif if (!info->ctx) { fprintf (stderr, "wavpack error: %s\n", error); return -1; } _info->plugin = &plugin; _info->fmt.bps = WavpackGetBytesPerSample (info->ctx) * 8; _info->fmt.channels = WavpackGetNumChannels (info->ctx); _info->fmt.samplerate = WavpackGetSampleRate (info->ctx); _info->fmt.is_float = (WavpackGetMode (info->ctx) & MODE_FLOAT) ? 1 : 0; // FIXME: streamer and maybe output plugins need to be fixed to support // arbitrary channelmask // _info->fmt.channelmask = WavpackGetChannelMask (info->ctx); for (int i = 0; i < _info->fmt.channels; i++) { _info->fmt.channelmask |= 1 << i; } _info->readpos = 0; if (it->endsample > 0) { info->startsample = it->startsample; info->endsample = it->endsample; if (plugin.seek_sample (_info, 0) < 0) { return -1; } } else { info->startsample = 0; info->endsample = WavpackGetNumSamples (info->ctx)-1; } return 0; }
static int aac_init (DB_fileinfo_t *_info, DB_playItem_t *it) { aac_info_t *info = (aac_info_t *)_info; deadbeef->pl_lock (); info->file = deadbeef->fopen (deadbeef->pl_find_meta (it, ":URI")); deadbeef->pl_unlock (); if (!info->file) { return -1; } // probe float duration = -1; int samplerate = -1; int channels = -1; int totalsamples = -1; info->junk = deadbeef->junk_get_leading_size (info->file); if (!info->file->vfs->is_streaming ()) { if (info->junk >= 0) { deadbeef->fseek (info->file, info->junk, SEEK_SET); } else { info->junk = 0; } } else { deadbeef->fset_track (info->file, it); } info->mp4track = -1; info->mp4reader.read = aac_fs_read; info->mp4reader.write = NULL; info->mp4reader.seek = aac_fs_seek; info->mp4reader.truncate = NULL; info->mp4reader.user_data = info; if (!info->file->vfs->is_streaming ()) { trace ("aac_init: mp4ff_open_read %s\n", deadbeef->pl_find_meta (it, ":URI")); info->mp4 = mp4ff_open_read (&info->mp4reader); if (info->mp4) { int ntracks = mp4ff_total_tracks (info->mp4); for (int i = 0; i < ntracks; i++) { if (mp4ff_get_track_type (info->mp4, i) != TRACK_AUDIO) { continue; } int res = mp4_track_get_info (info->mp4, i, &duration, &samplerate, &channels, &totalsamples, &info->mp4framesize); if (res >= 0 && duration > 0) { info->mp4track = i; break; } } trace ("track: %d\n", info->mp4track); if (info->mp4track >= 0) { // prepare decoder int res = mp4_track_get_info (info->mp4, info->mp4track, &duration, &samplerate, &channels, &totalsamples, &info->mp4framesize); if (res != 0) { trace ("aac: mp4_track_get_info(%d) returned error\n", info->mp4track); return -1; } // init mp4 decoding info->mp4samples = mp4ff_num_samples(info->mp4, info->mp4track); info->dec = NeAACDecOpen (); unsigned long srate; unsigned char ch; unsigned char* buff = 0; unsigned int buff_size = 0; mp4AudioSpecificConfig mp4ASC; mp4ff_get_decoder_config (info->mp4, info->mp4track, &buff, &buff_size); if (NeAACDecInit2(info->dec, buff, buff_size, &srate, &ch) < 0) { trace ("NeAACDecInit2 returned error\n"); free (buff); return -1; } if (buff) { free (buff); } trace ("aac: successfully initialized track %d\n", info->mp4track); _info->fmt.samplerate = samplerate; _info->fmt.channels = channels; } else { trace ("aac: track not found in mp4 container\n"); mp4ff_close (info->mp4); info->mp4 = NULL; } } if (!info->mp4) { trace ("aac: looking for raw stream...\n"); if (info->junk >= 0) { deadbeef->fseek (info->file, info->junk, SEEK_SET); } else { deadbeef->rewind (info->file); } int offs = parse_aac_stream (info->file, &samplerate, &channels, &duration, &totalsamples); if (offs == -1) { trace ("aac stream not found\n"); return -1; } if (offs > info->junk) { info->junk = offs; } if (info->junk >= 0) { deadbeef->fseek (info->file, info->junk, SEEK_SET); } else { deadbeef->rewind (info->file); } trace ("found aac stream (junk: %d, offs: %d)\n", info->junk, offs); _info->fmt.channels = channels; _info->fmt.samplerate = samplerate; } } else { // sync before attempting to init int samplerate, channels; float duration; int offs = parse_aac_stream (info->file, &samplerate, &channels, &duration, NULL); if (offs < 0) { trace ("aac: parse_aac_stream failed\n"); return -1; } if (offs > info->junk) { info->junk = offs; } trace("parse_aac_stream returned %x\n", offs); deadbeef->pl_replace_meta (it, "!FILETYPE", "AAC"); } // duration = (float)totalsamples / samplerate; // deadbeef->pl_set_item_duration (it, duration); _info->fmt.bps = 16; _info->plugin = &plugin; if (!info->mp4) { trace ("NeAACDecOpen for raw stream\n"); info->dec = NeAACDecOpen (); trace ("prepare for NeAACDecInit: fread %d from offs %lld\n", AAC_BUFFER_SIZE, deadbeef->ftell (info->file)); info->remaining = deadbeef->fread (info->buffer, 1, AAC_BUFFER_SIZE, info->file); NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration (info->dec); // conf->dontUpSampleImplicitSBR = 1; NeAACDecSetConfiguration (info->dec, conf); unsigned long srate; unsigned char ch; trace ("NeAACDecInit (%d bytes)\n", info->remaining); int consumed = NeAACDecInit (info->dec, info->buffer, info->remaining, &srate, &ch); trace ("NeAACDecInit returned samplerate=%d, channels=%d, consumed: %d\n", (int)srate, (int)ch, consumed); if (consumed < 0) { trace ("NeAACDecInit returned %d\n", consumed); return -1; } if (consumed > info->remaining) { trace ("NeAACDecInit consumed more than available! wtf?\n"); return -1; } if (consumed == info->remaining) { info->remaining = 0; } else if (consumed > 0) { memmove (info->buffer, info->buffer + consumed, info->remaining - consumed); info->remaining -= consumed; } _info->fmt.channels = ch; _info->fmt.samplerate = srate; } if (!info->file->vfs->is_streaming ()) { if (it->endsample > 0) { info->startsample = it->startsample; info->endsample = it->endsample; plugin.seek_sample (_info, 0); } else { info->startsample = 0; info->endsample = totalsamples-1; } } if (_info->fmt.channels == 7) { _info->fmt.channels = 8; } trace ("totalsamples: %d, endsample: %d, samples-from-duration: %d, samplerate %d, channels %d\n", totalsamples-1, info->endsample, (int)deadbeef->pl_get_item_duration (it)*44100, _info->fmt.samplerate, _info->fmt.channels); for (int i = 0; i < _info->fmt.channels; i++) { _info->fmt.channelmask |= 1 << i; } info->noremap = 0; info->remap[0] = -1; trace ("init success\n"); return 0; }
static int sndfile_init (DB_fileinfo_t *_info, DB_playItem_t *it) { sndfile_info_t *info = (sndfile_info_t*)_info; SF_INFO inf; DB_FILE *fp = deadbeef->fopen (deadbeef->pl_find_meta (it, ":URI")); if (!fp) { trace ("sndfile: failed to open %s\n", deadbeef->pl_find_meta (it, ":URI")); return -1; } int fsize = deadbeef->fgetlength (fp); info->file = fp; info->ctx = sf_open_virtual (&vfs, SFM_READ, &inf, info); if (!info->ctx) { trace ("sndfile: %s: unsupported file format\n"); return -1; } _info->plugin = &plugin; info->sf_format = inf.format&0x000f; switch (inf.format&0x000f) { case SF_FORMAT_PCM_S8: case SF_FORMAT_PCM_U8: _info->fmt.bps = 8; break; case SF_FORMAT_PCM_16: _info->fmt.bps = 16; break; case SF_FORMAT_PCM_24: _info->fmt.bps = 24; break; case SF_FORMAT_FLOAT: _info->fmt.is_float = 1; case SF_FORMAT_PCM_32: _info->fmt.bps = 32; break; default: info->read_as_short = 1; _info->fmt.bps = 16; trace ("[sndfile] unidentified input format: 0x%X\n", inf.format&0x000f); break; } _info->fmt.channels = inf.channels; _info->fmt.samplerate = inf.samplerate; int channel_map [inf.channels]; int cmdres = sf_command (info->ctx, SFC_GET_CHANNEL_MAP_INFO, channel_map, sizeof (channel_map)) ; if (cmdres != SF_FALSE) { // channel map found, convert to channel mask _info->fmt.channelmask = wavex_gen_channel_mask (channel_map, inf.channels); } else { // channel map not found, generate from channel number for (int i = 0; i < inf.channels; i++) { _info->fmt.channelmask |= 1 << i; } } _info->readpos = 0; if (it->endsample > 0) { info->startsample = it->startsample; info->endsample = it->endsample; if (plugin.seek_sample (_info, 0) < 0) { return -1; } } else { info->startsample = 0; info->endsample = inf.frames-1; } // hack bitrate int totalsamples = inf.frames; float sec = (float)totalsamples / inf.samplerate; if (sec > 0) { info->bitrate = fsize / sec * 8 / 1000; } else { info->bitrate = -1; } return 0; }