Path: blob/master/libs/mpg123/src/libmpg123/libmpg123.c
4394 views
/*1libmpg123: MPEG Audio Decoder library23copyright 1995-2023 by the mpg123 project - free software under the terms of the LGPL 2.14see COPYING and AUTHORS files in distribution or http://mpg123.org56*/78#include "mpg123lib_intern.h"9#include "../version.h"10#include "icy2utf8.h"1112#include "gapless.h"13/* Want accurate rounding function regardless of decoder setup. */14#define FORCE_ACCURATE15#include "../common/sample.h"16#include "parse.h"17#include "lfs_wrap.h"1819#include "../common/debug.h"2021#define SEEKFRAME(mh) ((mh)->ignoreframe < 0 ? 0 : (mh)->ignoreframe)222324const char * attribute_align_arg mpg123_distversion(unsigned int *major, unsigned int *minor, unsigned int *patch)25{26if(major)27*major = MPG123_MAJOR;28if(minor)29*minor = MPG123_MINOR;30if(patch)31*patch = MPG123_PATCH;32return MPG123_VERSION;33}3435unsigned int attribute_align_arg mpg123_libversion(unsigned int *patch)36{37if(patch)38*patch = MPG123_PATCHLEVEL;39return MPG123_API_VERSION;40}4142int attribute_align_arg mpg123_init(void)43{44// Since 1.27.0, this is a no-op and shall stay that way.45return MPG123_OK;46}4748void attribute_align_arg mpg123_exit(void)49{50// Nothing to ever happen here.51}5253/* create a new handle with specified decoder, decoder can be "", "auto" or NULL for auto-detection */54mpg123_handle attribute_align_arg *mpg123_new(const char* decoder, int *error)55{56return mpg123_parnew(NULL, decoder, error);57}5859// Runtime table calculation is back for specific uses that want minimal60// binary size. It's hidden in handle initialization, not in mpg123_init(),61// any user of such a minimal build should ensure that there is no trouble62// from concurrency or just call mpg123_new() once in single-threaded context.6364/* ...the full routine with optional initial parameters to override defaults. */65mpg123_handle attribute_align_arg *mpg123_parnew(mpg123_pars *mp, const char* decoder, int *error)66{67mpg123_handle *fr = NULL;68int err = MPG123_OK;6970#ifdef RUNTIME_TABLES71static char tables_initialized = 0;72if(!tables_initialized)73{74#ifndef NO_LAYER1275INT123_init_layer12(); /* inits also shared tables with layer1 */76#endif77#ifndef NO_LAYER378INT123_init_layer3();79#endif80INT123_init_costabs();81tables_initialized = 1;82}83#endif8485// Silly paranoia checks. Really silly, but libmpg123 has been ported to strange86// platforms in the past.87if((sizeof(short) != 2) || (sizeof(long) < 4))88{89if(error != NULL) *error = MPG123_BAD_TYPES;90return NULL;91}9293#if (defined REAL_IS_FLOAT) && (defined IEEE_FLOAT)94/* This is rather pointless but it eases my mind to check that we did95not enable the special rounding on a VAX or something. */96if(12346 != REAL_TO_SHORT_ACCURATE(12345.67f))97{98if(error != NULL) *error = MPG123_BAD_FLOAT;99return NULL;100}101#endif102103fr = (mpg123_handle*) malloc(sizeof(mpg123_handle));104if(fr != NULL)105{106INT123_frame_init_par(fr, mp);107debug("cpu opt setting");108if(INT123_frame_cpu_opt(fr, decoder) != 1)109{110err = MPG123_BAD_DECODER;111INT123_frame_exit(fr);112free(fr);113fr = NULL;114}115}116if(fr != NULL)117{118fr->decoder_change = 1;119}120else if(err == MPG123_OK) err = MPG123_OUT_OF_MEM;121122if(error != NULL) *error = err;123return fr;124}125126int attribute_align_arg mpg123_decoder(mpg123_handle *mh, const char* decoder)127{128enum optdec dt = INT123_dectype(decoder);129130if(mh == NULL) return MPG123_BAD_HANDLE;131132if(dt == nodec)133{134mh->err = MPG123_BAD_DECODER;135return MPG123_ERR;136}137if(dt == mh->cpu_opts.type) return MPG123_OK;138139/* Now really change. */140/* INT123_frame_exit(mh);141INT123_frame_init(mh); */142debug("cpu opt setting");143if(INT123_frame_cpu_opt(mh, decoder) != 1)144{145mh->err = MPG123_BAD_DECODER;146INT123_frame_exit(mh);147return MPG123_ERR;148}149/* New buffers for decoder are created in INT123_frame_buffers() */150if((INT123_frame_outbuffer(mh) != 0))151{152mh->err = MPG123_NO_BUFFERS;153INT123_frame_exit(mh);154return MPG123_ERR;155}156/* Do _not_ call INT123_decode_update here! That is only allowed after a first MPEG frame has been met. */157mh->decoder_change = 1;158return MPG123_OK;159}160161int attribute_align_arg mpg123_param(mpg123_handle *mh, enum mpg123_parms key, long val, double fval)162{163int r;164165if(mh == NULL) return MPG123_BAD_HANDLE;166r = mpg123_par(&mh->p, key, val, fval);167if(r != MPG123_OK){ mh->err = r; r = MPG123_ERR; }168else169{ /* Special treatment for some settings. */170#ifdef FRAME_INDEX171if(key == MPG123_INDEX_SIZE)172{ /* Apply frame index size and grow property on the fly. */173r = INT123_frame_index_setup(mh);174if(r != MPG123_OK) mh->err = MPG123_INDEX_FAIL;175}176#endif177#ifndef NO_FEEDER178/* Feeder pool size is applied right away, reader will react to that. */179if(key == MPG123_FEEDPOOL || key == MPG123_FEEDBUFFER)180INT123_bc_poolsize(&mh->rdat.buffer, mh->p.feedpool, mh->p.feedbuffer);181#endif182}183return r;184}185186int attribute_align_arg mpg123_param2(mpg123_handle *mh, int key, long val, double fval)187{188return mpg123_param(mh, key, val, fval);189}190191int attribute_align_arg mpg123_par(mpg123_pars *mp, enum mpg123_parms key, long val, double fval)192{193int ret = MPG123_OK;194195if(mp == NULL) return MPG123_BAD_PARS;196switch(key)197{198case MPG123_VERBOSE:199mp->verbose = val;200break;201case MPG123_FLAGS:202#ifndef GAPLESS203if(val & MPG123_GAPLESS) ret = MPG123_NO_GAPLESS;204#endif205if(ret == MPG123_OK) mp->flags = val;206debug1("set flags to 0x%lx", (unsigned long) mp->flags);207break;208case MPG123_ADD_FLAGS:209#ifndef GAPLESS210/* Enabling of gapless mode doesn't work when it's not there, but disabling (below) is no problem. */211if(val & MPG123_GAPLESS) ret = MPG123_NO_GAPLESS;212else213#endif214mp->flags |= val;215debug1("set flags to 0x%lx", (unsigned long) mp->flags);216break;217case MPG123_REMOVE_FLAGS:218mp->flags &= ~val;219debug1("set flags to 0x%lx", (unsigned long) mp->flags);220break;221case MPG123_FORCE_RATE: /* should this trigger something? */222#ifdef NO_NTOM223if(val > 0)224ret = MPG123_BAD_RATE;225#else226if(val > 96000) ret = MPG123_BAD_RATE;227else mp->force_rate = val < 0 ? 0 : val; /* >0 means enable, 0 disable */228#endif229break;230case MPG123_DOWN_SAMPLE:231#ifdef NO_DOWNSAMPLE232if(val != 0) ret = MPG123_BAD_RATE;233#else234if(val < 0 || val > 2) ret = MPG123_BAD_RATE;235else mp->down_sample = (int)val;236#endif237break;238case MPG123_RVA:239if(val < 0 || val > MPG123_RVA_MAX) ret = MPG123_BAD_RVA;240else mp->rva = (int)val;241break;242case MPG123_DOWNSPEED:243mp->halfspeed = val < 0 ? 0 : val;244break;245case MPG123_UPSPEED:246mp->doublespeed = val < 0 ? 0 : val;247break;248case MPG123_ICY_INTERVAL:249#ifndef NO_ICY250mp->icy_interval = val > 0 ? val : 0;251#else252if(val > 0) ret = MPG123_BAD_PARAM;253#endif254break;255case MPG123_OUTSCALE:256/* Choose the value that is non-zero, if any.257Downscaling integers to 1.0 . */258mp->outscale = val == 0 ? fval : (double)val/SHORT_SCALE;259break;260case MPG123_TIMEOUT:261#ifdef TIMEOUT_READ262mp->timeout = val >= 0 ? val : 0;263#else264if(val > 0) ret = MPG123_NO_TIMEOUT;265#endif266break;267case MPG123_RESYNC_LIMIT:268mp->resync_limit = val;269break;270case MPG123_INDEX_SIZE:271#ifdef FRAME_INDEX272mp->index_size = val;273#else274if(val) // It is only an eror if you want to enable the index.275ret = MPG123_NO_INDEX;276#endif277break;278case MPG123_PREFRAMES:279if(val >= 0) mp->preframes = val;280else ret = MPG123_BAD_VALUE;281break;282case MPG123_FEEDPOOL:283#ifndef NO_FEEDER284if(val >= 0) mp->feedpool = val;285else ret = MPG123_BAD_VALUE;286#else287ret = MPG123_MISSING_FEATURE;288#endif289break;290case MPG123_FEEDBUFFER:291#ifndef NO_FEEDER292if(val > 0) mp->feedbuffer = val;293else ret = MPG123_BAD_VALUE;294#else295ret = MPG123_MISSING_FEATURE;296#endif297break;298case MPG123_FREEFORMAT_SIZE:299mp->freeformat_framesize = val;300break;301default:302ret = MPG123_BAD_PARAM;303}304return ret;305}306307int attribute_align_arg mpg123_par2(mpg123_pars *mp, int key, long val, double fval)308{309return mpg123_par(mp, key, val, fval);310}311312int attribute_align_arg mpg123_getparam(mpg123_handle *mh, enum mpg123_parms key, long *val, double *fval)313{314int r;315316if(mh == NULL) return MPG123_BAD_HANDLE;317r = mpg123_getpar(&mh->p, key, val, fval);318if(r != MPG123_OK){ mh->err = r; r = MPG123_ERR; }319return r;320}321322int attribute_align_arg mpg123_getparam2(mpg123_handle *mh, int key, long *val, double *fval)323{324return mpg123_getparam(mh, key, val, fval);325}326327int attribute_align_arg mpg123_getpar(mpg123_pars *mp, enum mpg123_parms key, long *val, double *fval)328{329int ret = 0;330331if(mp == NULL) return MPG123_BAD_PARS;332switch(key)333{334case MPG123_VERBOSE:335if(val) *val = mp->verbose;336break;337case MPG123_FLAGS:338case MPG123_ADD_FLAGS:339if(val) *val = mp->flags;340break;341case MPG123_FORCE_RATE:342if(val)343#ifdef NO_NTOM344*val = 0;345#else346*val = mp->force_rate;347#endif348break;349case MPG123_DOWN_SAMPLE:350if(val) *val = mp->down_sample;351break;352case MPG123_RVA:353if(val) *val = mp->rva;354break;355case MPG123_DOWNSPEED:356if(val) *val = mp->halfspeed;357break;358case MPG123_UPSPEED:359if(val) *val = mp->doublespeed;360break;361case MPG123_ICY_INTERVAL:362#ifndef NO_ICY363if(val) *val = (long)mp->icy_interval;364#else365if(val) *val = 0;366#endif367break;368case MPG123_OUTSCALE:369if(fval) *fval = mp->outscale;370if(val) *val = (long)(mp->outscale*SHORT_SCALE);371break;372case MPG123_RESYNC_LIMIT:373if(val) *val = mp->resync_limit;374break;375case MPG123_INDEX_SIZE:376if(val)377#ifdef FRAME_INDEX378*val = mp->index_size;379#else380*val = 0; /* graceful fallback: no index is index of zero size */381#endif382break;383case MPG123_PREFRAMES:384*val = mp->preframes;385break;386case MPG123_FEEDPOOL:387#ifndef NO_FEEDER388*val = mp->feedpool;389#else390ret = MPG123_MISSING_FEATURE;391#endif392break;393case MPG123_FEEDBUFFER:394#ifndef NO_FEEDER395*val = mp->feedbuffer;396#else397ret = MPG123_MISSING_FEATURE;398#endif399break;400case MPG123_FREEFORMAT_SIZE:401*val = mp->freeformat_framesize;402break;403default:404ret = MPG123_BAD_PARAM;405}406return ret;407}408409int attribute_align_arg mpg123_getpar2(mpg123_pars *mp, int key, long *val, double *fval)410{411return mpg123_getpar(mp, key, val, fval);412}413414int attribute_align_arg mpg123_getstate(mpg123_handle *mh, enum mpg123_state key, long *val, double *fval)415{416int ret = MPG123_OK;417long theval = 0;418double thefval = 0.;419420if(mh == NULL) return MPG123_BAD_HANDLE;421422switch(key)423{424case MPG123_ACCURATE:425theval = mh->state_flags & FRAME_ACCURATE;426break;427case MPG123_FRANKENSTEIN:428theval = mh->state_flags & FRAME_FRANKENSTEIN;429break;430case MPG123_BUFFERFILL:431#ifndef NO_FEEDER432{433size_t sval = INT123_bc_fill(&mh->rdat.buffer);434theval = (long)sval;435if(theval < 0 || (size_t)theval != sval)436{437mh->err = MPG123_INT_OVERFLOW;438ret = MPG123_ERR;439}440}441#else442mh->err = MPG123_MISSING_FEATURE;443ret = MPG123_ERR;444#endif445break;446case MPG123_FRESH_DECODER:447theval = mh->state_flags & FRAME_FRESH_DECODER;448mh->state_flags &= ~FRAME_FRESH_DECODER;449break;450case MPG123_ENC_DELAY:451theval = mh->enc_delay;452break;453case MPG123_ENC_PADDING:454theval = mh->enc_padding;455break;456case MPG123_DEC_DELAY:457theval = mh->hdr.lay == 3 ? GAPLESS_DELAY : -1;458break;459default:460mh->err = MPG123_BAD_KEY;461ret = MPG123_ERR;462}463464if(val != NULL) *val = theval;465if(fval != NULL) *fval = thefval;466467return ret;468}469470int attribute_align_arg mpg123_getstate2(mpg123_handle *mh, int key, long *val, double *fval)471{472return mpg123_getstate(mh, key, val, fval);473}474475int attribute_align_arg mpg123_eq(mpg123_handle *mh, enum mpg123_channels channel, int band, double val)476{477if(mh == NULL) return MPG123_BAD_HANDLE;478#ifndef NO_EQUALIZER479if(band < 0 || band > 31){ mh->err = MPG123_BAD_BAND; return MPG123_ERR; }480switch(channel)481{482case MPG123_LEFT|MPG123_RIGHT:483mh->equalizer[0][band] = mh->equalizer[1][band] = DOUBLE_TO_REAL(val);484break;485case MPG123_LEFT: mh->equalizer[0][band] = DOUBLE_TO_REAL(val); break;486case MPG123_RIGHT: mh->equalizer[1][band] = DOUBLE_TO_REAL(val); break;487default:488mh->err=MPG123_BAD_CHANNEL;489return MPG123_ERR;490}491mh->have_eq_settings = TRUE;492#endif493return MPG123_OK;494}495496int attribute_align_arg mpg123_eq2(mpg123_handle *mh, int channel, int band, double val)497{498return mpg123_eq(mh, channel, band, val);499}500501int attribute_align_arg mpg123_eq_bands(mpg123_handle *mh, int channel, int a, int b, double factor)502{503if(mh == NULL) return MPG123_BAD_HANDLE;504#ifndef NO_EQUALIZER505int ret;506// Always count up.507if(a>b){ int s=a; a=b; b=s; }508for(int n=a; n<=b; ++n)509if( (ret=mpg123_eq(mh, channel, n, factor)) != MPG123_OK )510return ret;511#endif512return MPG123_OK;513}514515int attribute_align_arg mpg123_eq_change(mpg123_handle *mh, int channel, int a, int b, double db)516{517if(mh == NULL) return MPG123_BAD_HANDLE;518#ifndef NO_EQUALIZER519// Always count up.520if(a>b){ int s=a; a=b; b=s; }521for(int band=a; band<=b; ++band)522{523if(band < 0 || band > 31){ mh->err = MPG123_BAD_BAND; return MPG123_ERR; }524if(channel & MPG123_LEFT)525mh->equalizer[0][band] = DOUBLE_TO_REAL(dbchange(REAL_TO_DOUBLE(mh->equalizer[0][band]), db));526if(channel & MPG123_RIGHT)527mh->equalizer[1][band] = DOUBLE_TO_REAL(dbchange(REAL_TO_DOUBLE(mh->equalizer[1][band]), db));528mh->have_eq_settings = TRUE;529}530#endif531return MPG123_OK;532}533534double attribute_align_arg mpg123_geteq(mpg123_handle *mh, enum mpg123_channels channel, int band)535{536double ret = 1.;537#ifndef NO_EQUALIZER538539/* Handle this gracefully. When there is no band, it has no volume. */540if(mh != NULL && band > -1 && band < 32)541switch(channel)542{543case MPG123_LEFT|MPG123_RIGHT:544ret = 0.5*(REAL_TO_DOUBLE(mh->equalizer[0][band])+REAL_TO_DOUBLE(mh->equalizer[1][band]));545break;546case MPG123_LEFT: ret = REAL_TO_DOUBLE(mh->equalizer[0][band]); break;547case MPG123_RIGHT: ret = REAL_TO_DOUBLE(mh->equalizer[1][band]); break;548/* Default case is already handled: ret = 0 */549}550#endif551return ret;552}553554double attribute_align_arg mpg123_geteq2(mpg123_handle *mh, int channel, int band)555{556return mpg123_geteq(mh, channel, band);557}558559// LFS wrapper code is so agnostic to it all now that internal I/O is portable560// as long as you do not mix in off_t API.561int attribute_align_arg mpg123_open64(mpg123_handle *mh, const char *path)562{563if(mh == NULL) return MPG123_BAD_HANDLE;564565mpg123_close(mh);566if(!path)567return MPG123_ERR;568// sets callbacks, only allocating wrapperdata handle if internal callbacks involved569int ret = INT123_wrap_open( mh, NULL, path, -1570, mh->p.timeout, mh->p.flags & MPG123_QUIET );571if(!ret)572ret = INT123_open_stream_handle(mh, mh->wrapperdata);573return ret;574}575576#ifndef PORTABLE_API577578#ifdef FORCED_OFF_64579// Only _64 symbols for a system-wide enforced _FILE_OFFSET_BITS=64.580#define mpg123_open mpg123_open_64581#define mpg123_open_fixed mpg123_open_fixed_64582#define mpg123_open_fd mpg123_open_fd_64583#define mpg123_open_handle mpg123_open_handle_64584#endif585586// This now is agnostic to off_t choice, but still subject to renaming587// for legacy reasons.588int attribute_align_arg mpg123_open(mpg123_handle *mh, const char *path)589{590return mpg123_open64(mh, path);591}592#endif // PORTABLE_API593594// The convenience function mpg123_open_fixed() wraps over acual mpg123_open595// and hence needs to have the exact same code in lfs_wrap.c. The flesh is596// in INT123_open_fixed_pre() and INT123_open_fixed_post(), wich are only defined here.597// Update: The open routines are just alias calls now, since the conversion to598// int64_t internally.599static int INT123_open_fixed_pre(mpg123_handle *mh, int channels, int encoding)600{601if(!mh)602return MPG123_BAD_HANDLE;603mh->p.flags |= MPG123_NO_FRANKENSTEIN;604int err = mpg123_format_none(mh);605if(err == MPG123_OK)606err = mpg123_format2(mh, 0, channels, encoding);607return err;608}609610static int INT123_open_fixed_post(mpg123_handle *mh, int channels, int encoding)611{612if(!mh)613return MPG123_BAD_HANDLE;614long rate;615int err = mpg123_getformat(mh, &rate, &channels, &encoding);616if(err == MPG123_OK)617err = mpg123_format_none(mh);618if(err == MPG123_OK)619err = mpg123_format(mh, rate, channels, encoding);620if(err == MPG123_OK)621{622if(mh->track_frames < 1 && (mh->rdat.flags & READER_SEEKABLE))623{624debug("INT123_open_fixed_post: scan because we can seek and do not know track_frames");625err = mpg123_scan(mh);626}627}628if(err != MPG123_OK)629mpg123_close(mh);630return err;631}632633int attribute_align_arg mpg123_open_fixed64( mpg123_handle *mh, const char *path634, int channels, int encoding )635{636int err = INT123_open_fixed_pre(mh, channels, encoding);637if(err == MPG123_OK)638err = mpg123_open64(mh, path);639if(err == MPG123_OK)640err = INT123_open_fixed_post(mh, channels, encoding);641return err;642}643644#ifndef PORTABLE_API645// Only to have the modern offset-agnostic open under a fixed name.646int attribute_align_arg mpg123_open_fixed( mpg123_handle *mh, const char *path647, int channels, int encoding )648{649return mpg123_open_fixed64(mh, path, channels, encoding);650}651652// Won't define a 'portable' variant of this, as I cannot guess653// properties of the handed-in fd, which in theory, on specific platforms,654// could not support large files.655int attribute_align_arg mpg123_open_fd(mpg123_handle *mh, int fd)656{657if(mh == NULL) return MPG123_BAD_HANDLE;658659mpg123_close(mh);660if(fd < 0)661return MPG123_ERR;662int ret = INT123_wrap_open( mh, NULL, NULL, fd663, mh->p.timeout, mh->p.flags & MPG123_QUIET );664if(!ret)665ret = INT123_open_stream_handle(mh, mh->wrapperdata);666return ret;667}668#endif // PORTABLE_API669670// Only works with int64 reader setup.671int attribute_align_arg mpg123_open_handle64(mpg123_handle *mh, void *iohandle)672{673if(mh == NULL) return MPG123_BAD_HANDLE;674675mpg123_close(mh);676return INT123_open_stream_handle(mh, iohandle);677}678679#ifndef PORTABLE_API680// Change from 1.32: No largefile-renamed symbols in a library with strict681// portable API.682// I allow that breaking change since this is far from a standard libmpg123 build.683int attribute_align_arg mpg123_open_handle(mpg123_handle *mh, void *iohandle)684{685if(mh == NULL) return MPG123_BAD_HANDLE;686687mpg123_close(mh);688int ret;689ret = INT123_wrap_open( mh, iohandle, NULL, -1690, mh->p.timeout, mh->p.flags & MPG123_QUIET );691iohandle = ret == LFS_WRAP_NONE ? iohandle : mh->wrapperdata;692if(ret >= 0)693ret = INT123_open_stream_handle(mh, iohandle);694return ret;695}696#endif697698int attribute_align_arg mpg123_open_feed(mpg123_handle *mh)699{700if(mh == NULL) return MPG123_BAD_HANDLE;701702mpg123_close(mh);703return INT123_open_feed(mh);704}705706static int64_t no_lseek64(void *handle, int64_t off, int whence)707{708return -1;709}710711// The simplest direct wrapper, actually no wrapping at all.712int attribute_align_arg mpg123_reader64( mpg123_handle *mh713, int (*r_read) (void *, void *, size_t, size_t *)714, int64_t (*r_lseek)(void *, int64_t, int)715, void (*cleanup)(void*) )716{717if(mh == NULL)718return MPG123_BAD_HANDLE;719720mpg123_close(mh);721722if(!r_read)723return MPG123_NULL_POINTER;724725mh->rdat.r_read64 = r_read;726mh->rdat.r_lseek64 = r_lseek ? r_lseek : no_lseek64;727mh->rdat.cleanup_handle = cleanup;728return MPG123_OK;729}730731// All other I/O gets routed through predefined wrapper.732733/* Update decoding engine for734a) a new choice of decoder735b) a changed native format of the MPEG stream736... calls are only valid after parsing some MPEG frame! */737int INT123_decode_update(mpg123_handle *mh)738{739long native_rate;740int b;741742mh->state_flags &= ~FRAME_DECODER_LIVE;743if(mh->num < 0)744{745if(!(mh->p.flags & MPG123_QUIET)) error("INT123_decode_update() has been called before reading the first MPEG frame! Internal programming error.");746747mh->err = MPG123_BAD_DECODER_SETUP;748return MPG123_ERR;749}750751mh->state_flags |= FRAME_FRESH_DECODER;752native_rate = INT123_frame_freq(mh);753754b = INT123_frame_output_format(mh); /* Select the new output format based on given constraints. */755if(b < 0) return MPG123_ERR;756757if(b == 1) mh->new_format = 1; /* Store for later... */758759debug3("updating decoder structure with native rate %li and af.rate %li (new format: %i)", native_rate, mh->af.rate, mh->new_format);760if(mh->af.rate == native_rate) mh->down_sample = 0;761else if(mh->af.rate == native_rate>>1) mh->down_sample = 1;762else if(mh->af.rate == native_rate>>2) mh->down_sample = 2;763else mh->down_sample = 3; /* flexible (fixed) rate */764switch(mh->down_sample)765{766case 0:767case 1:768case 2:769mh->down_sample_sblimit = SBLIMIT>>(mh->down_sample);770/* With downsampling I get less samples per frame */771mh->outblock = INT123_outblock_bytes(mh, (mh->spf>>mh->down_sample));772break;773#ifndef NO_NTOM774case 3:775{776if(INT123_synth_ntom_set_step(mh) != 0) return -1;777if(INT123_frame_freq(mh) > mh->af.rate)778{779mh->down_sample_sblimit = SBLIMIT * mh->af.rate;780mh->down_sample_sblimit /= INT123_frame_freq(mh);781if(mh->down_sample_sblimit < 1)782mh->down_sample_sblimit = 1;783}784else mh->down_sample_sblimit = SBLIMIT;785mh->outblock = INT123_outblock_bytes(mh,786( ( NTOM_MUL-1+mh->spf787* (((size_t)NTOM_MUL*mh->af.rate)/INT123_frame_freq(mh))788)/NTOM_MUL ));789}790break;791#endif792}793794if(!(mh->p.flags & MPG123_FORCE_MONO))795{796if(mh->af.channels == 1) mh->single = SINGLE_MIX;797else mh->single = SINGLE_STEREO;798}799else mh->single = (mh->p.flags & MPG123_FORCE_MONO)-1;800if(INT123_set_synth_functions(mh) != 0) return -1;801802/* The needed size of output buffer may have changed. */803if(INT123_frame_outbuffer(mh) != MPG123_OK) return -1;804805INT123_do_rva(mh);806debug3("done updating decoder structure with native rate %li and af.rate %li and down_sample %i", INT123_frame_freq(mh), mh->af.rate, mh->down_sample);807808mh->decoder_change = 0;809mh->state_flags |= FRAME_DECODER_LIVE;810return 0;811}812813size_t attribute_align_arg mpg123_safe_buffer(void)814{815/* real is the largest possible output (it's 32bit float, 32bit int or 64bit double). */816return sizeof(real)*2*1152*NTOM_MAX;817}818819size_t attribute_align_arg mpg123_outblock(mpg123_handle *mh)820{821/* Try to be helpful and never return zero output block size. */822if(mh != NULL && mh->outblock > 0) return mh->outblock;823else return mpg123_safe_buffer();824}825826/* Read in the next frame we actually want for decoding.827This includes skipping/ignoring frames, in additon to skipping junk in the parser. */828static int get_next_frame(mpg123_handle *mh)829{830int change = mh->decoder_change;831/* Ensure we got proper decoder for ignoring frames.832Header can be changed from seeking around. But be careful: Only after at833least one frame got read, decoder update makes sense. */834if(mh->header_change > 1 && mh->num >= 0)835{836change = 1;837mh->header_change = 0;838debug("starting with big header change");839if(INT123_decode_update(mh) < 0)840return MPG123_ERR;841}842843do844{845int b;846/* Decode & discard some frame(s) before beginning. */847if(mh->to_ignore && mh->num < mh->firstframe && mh->num >= mh->ignoreframe)848{849debug1("ignoring frame %li", (long)mh->num);850/* Decoder structure must be current! INT123_decode_update has been called before... */851(mh->do_layer)(mh); mh->buffer.fill = 0;852#ifndef NO_NTOM853/* The ignored decoding may have failed. Make sure ntom stays consistent. */854if(mh->down_sample == 3) INT123_ntom_set_ntom(mh, mh->num+1);855#endif856mh->to_ignore = mh->to_decode = FALSE;857}858/* Read new frame data; possibly breaking out here for MPG123_NEED_MORE. */859debug("read frame");860mh->to_decode = FALSE;861b = INT123_read_frame(mh); /* That sets to_decode only if a full frame was read. */862debug4("read of frame %"PRIi64" returned %i (to_decode=%i) at sample %"PRIi64, mh->num, b, mh->to_decode, mpg123_tell64(mh));863if(b == MPG123_NEED_MORE) return MPG123_NEED_MORE; /* need another call with data */864else if(b <= 0)865{866/* More sophisticated error control? */867if(b==0 || (mh->rdat.filelen >= 0 && mh->rdat.filepos == mh->rdat.filelen))868{ /* We simply reached the end. */869mh->track_frames = mh->num + 1;870debug("What about updating/checking gapless sample count here?");871return MPG123_DONE;872}873else return MPG123_ERR; /* Some real error. */874}875/* Now, there should be new data to decode ... and also possibly new stream properties */876if(mh->header_change > 1 || mh->decoder_change)877{878debug("big header or decoder change");879change = 1;880mh->header_change = 0;881/* Need to update decoder structure right away since frame might need to882be decoded on next loop iteration for properly ignoring its output. */883if(INT123_decode_update(mh) < 0)884return MPG123_ERR;885}886/* Now some accounting: Look at the numbers and decide if we want this frame. */887++mh->playnum;888/* Plain skipping without decoding, only when frame is not ignored on next cycle. */889if(mh->num < mh->firstframe || (mh->p.doublespeed && (mh->playnum % mh->p.doublespeed)))890{891if(!(mh->to_ignore && mh->num < mh->firstframe && mh->num >= mh->ignoreframe))892{893INT123_frame_skip(mh);894/* Should one fix NtoM here or not?895It is not work the trouble for doublespeed, but what with leading frames? */896}897}898/* Or, we are finally done and have a new frame. */899else break;900} while(1);901902/* If we reach this point, we got a new frame ready to be decoded.903All other situations resulted in returns from the loop. */904if(change)905{906if(mh->fresh)907{908#ifdef GAPLESS909int b=0;910/* Prepare offsets for gapless decoding. */911debug1("preparing gapless stuff with native rate %li", INT123_frame_freq(mh));912INT123_frame_gapless_realinit(mh);913INT123_frame_set_frameseek(mh, mh->num);914#endif915mh->fresh = 0;916#ifdef GAPLESS917/* Could this possibly happen? With a real big gapless offset... */918if(mh->num < mh->firstframe) b = get_next_frame(mh);919if(b < 0) return b; /* Could be error, need for more, new format... */920#endif921}922}923return MPG123_OK;924}925926/* Assumption: A buffer full of zero samples can be constructed by repetition of this byte.927Oh, and it handles some format conversion.928Only to be used by decode_the_frame() ... */929static int zero_byte(mpg123_handle *fr)930{931#ifndef NO_8BIT932return fr->af.encoding & MPG123_ENC_8 ? fr->conv16to8[0] : 0;933#else934return 0; /* All normal signed formats have the zero here (even in byte form -- that may be an assumption for your funny machine...). */935#endif936}937938/*939Not part of the api. This just decodes the frame and fills missing bits with zeroes.940There can be frames that are broken and thus make do_layer() fail.941*/942static void decode_the_frame(mpg123_handle *fr)943{944size_t needed_bytes = INT123_decoder_synth_bytes(fr, INT123_frame_expect_outsamples(fr));945fr->clip += (fr->do_layer)(fr);946/* There could be less data than promised.947Also, then debugging, we look out for coding errors that could result in _more_ data than expected. */948#ifdef DEBUG949if(fr->buffer.fill != needed_bytes)950{951#endif952if(fr->buffer.fill < needed_bytes)953{954if(VERBOSE2)955fprintf( stderr, "Note: broken frame %li, filling up with %zu zeroes, from %zu\n"956, (long)fr->num, (needed_bytes-fr->buffer.fill), fr->buffer.fill );957958/*959One could do a loop with individual samples instead... but zero is zero960Actually, that is wrong: zero is mostly a series of null bytes,961but we have funny 8bit formats that have a different opinion on zero...962Unsigned 16 or 32 bit formats are handled later.963*/964memset( fr->buffer.data + fr->buffer.fill, zero_byte(fr), needed_bytes - fr->buffer.fill );965966fr->buffer.fill = needed_bytes;967#ifndef NO_NTOM968/* INT123_ntom_val will be wrong when the decoding wasn't carried out completely */969INT123_ntom_set_ntom(fr, fr->num+1);970#endif971}972#ifdef DEBUG973else974{975if(NOQUIET)976error2("I got _more_ bytes than expected (%zu / %zu), that should not be possible!", fr->buffer.fill, needed_bytes);977}978}979#endif980INT123_postprocess_buffer(fr);981}982983/*984Decode the current frame into the frame structure's buffer, accessible at the location stored in <audio>, with <bytes> bytes available.985<num> will contain the last decoded frame number. This function should be called after mpg123_framebyframe_next positioned the stream at a986valid mp3 frame. The buffer contents will get lost on the next call to mpg123_framebyframe_next or mpg123_framebyframe_decode.987returns988MPG123_OK -- successfully decoded or ignored the frame, you get your output data or in case of ignored frames 0 bytes989MPG123_DONE -- decoding finished, should not happen990MPG123_ERR -- some error occured.991MPG123_ERR_NULL -- audio or bytes are not pointing to valid storage addresses992MPG123_BAD_HANDLE -- mh has not been initialized993MPG123_NO_SPACE -- not enough space in buffer for safe decoding, should not happen994*/995int attribute_align_arg mpg123_framebyframe_decode64(mpg123_handle *mh, int64_t *num, unsigned char **audio, size_t *bytes)996{997if(bytes == NULL) return MPG123_ERR_NULL;998if(audio == NULL) return MPG123_ERR_NULL;999if(mh == NULL) return MPG123_BAD_HANDLE;1000if(mh->buffer.size < mh->outblock) return MPG123_NO_SPACE;10011002*audio = NULL;1003*bytes = 0;1004mh->buffer.fill = 0; /* always start fresh */1005if(!mh->to_decode) return MPG123_OK;10061007if(num != NULL) *num = mh->num;1008debug("decoding");1009if(!(mh->state_flags & FRAME_DECODER_LIVE))1010return MPG123_ERR;1011decode_the_frame(mh);1012mh->to_decode = mh->to_ignore = FALSE;1013mh->buffer.p = mh->buffer.data;1014FRAME_BUFFERCHECK(mh);1015*audio = mh->buffer.p;1016*bytes = mh->buffer.fill;1017return MPG123_OK;1018}10191020/*1021Find, read and parse the next mp3 frame while skipping junk and parsing id3 tags, lame headers, etc.1022Prepares everything for decoding using mpg123_framebyframe_decode.1023returns1024MPG123_OK -- new frame was read and parsed, call mpg123_framebyframe_decode to actually decode1025MPG123_NEW_FORMAT -- new frame was read, it results in changed output format, call mpg123_framebyframe_decode to actually decode1026MPG123_BAD_HANDLE -- mh has not been initialized1027MPG123_NEED_MORE -- more input data is needed to advance to the next frame. supply more input data using mpg123_feed1028*/1029int attribute_align_arg mpg123_framebyframe_next(mpg123_handle *mh)1030{1031int b;1032if(mh == NULL) return MPG123_BAD_HANDLE;10331034mh->to_decode = mh->to_ignore = FALSE;1035mh->buffer.fill = 0;10361037b = get_next_frame(mh);1038if(b < 0) return b;1039debug1("got next frame, %i", mh->to_decode);10401041/* mpg123_framebyframe_decode will return MPG123_OK with 0 bytes decoded if mh->to_decode is 0 */1042if(!mh->to_decode)1043return MPG123_OK;10441045if(mh->new_format)1046{1047debug("notifiying new format");1048mh->new_format = 0;1049return MPG123_NEW_FORMAT;1050}10511052return MPG123_OK;1053}10541055/*1056Put _one_ decoded frame into the frame structure's buffer, accessible at the location stored in <audio>, with <bytes> bytes available.1057The buffer contents will be lost on next call to mpg123_decode_frame.1058MPG123_OK -- successfully decoded the frame, you get your output data1059MPg123_DONE -- This is it. End.1060MPG123_ERR -- some error occured...1061MPG123_NEW_FORMAT -- new frame was read, it results in changed output format -> will be decoded on next call1062MPG123_NEED_MORE -- that should not happen as this function is intended for in-library stream reader but if you force it...1063MPG123_NO_SPACE -- not enough space in buffer for safe decoding, also should not happen10641065num will be updated to the last decoded frame number (may possibly _not_ increase, p.ex. when format changed).1066*/1067int attribute_align_arg mpg123_decode_frame64(mpg123_handle *mh, int64_t *num, unsigned char **audio, size_t *bytes)1068{1069if(bytes != NULL) *bytes = 0;1070if(mh == NULL) return MPG123_BAD_HANDLE;1071if(mh->buffer.size < mh->outblock) return MPG123_NO_SPACE;1072mh->buffer.fill = 0; /* always start fresh */1073/* Be nice: Set these also for sensible values in case of error. */1074if(audio) *audio = NULL;1075if(bytes) *bytes = 0;1076while(TRUE)1077{1078/* decode if possible */1079if(mh->to_decode)1080{1081if(num != NULL) *num = mh->num;1082if(mh->new_format)1083{1084debug("notifiying new format");1085mh->new_format = 0;1086return MPG123_NEW_FORMAT;1087}1088debug("decoding");10891090if( (mh->decoder_change && INT123_decode_update(mh) < 0)1091|| !(mh->state_flags & FRAME_DECODER_LIVE) )1092return MPG123_ERR;1093decode_the_frame(mh);10941095mh->to_decode = mh->to_ignore = FALSE;1096mh->buffer.p = mh->buffer.data;1097FRAME_BUFFERCHECK(mh);1098if(audio != NULL) *audio = mh->buffer.p;1099if(bytes != NULL) *bytes = mh->buffer.fill;11001101return MPG123_OK;1102}1103else1104{1105int b = get_next_frame(mh);1106if(b < 0) return b;1107debug1("got next frame, %i", mh->to_decode);1108}1109}1110}111111121113int attribute_align_arg mpg123_read(mpg123_handle *mh, void *out, size_t size, size_t *done)1114{1115return mpg123_decode(mh, NULL, 0, out, size, done);1116}11171118int attribute_align_arg mpg123_feed(mpg123_handle *mh, const unsigned char *in, size_t size)1119{1120if(mh == NULL) return MPG123_BAD_HANDLE;1121#ifndef NO_FEEDER1122if(size > 0)1123{1124if(in != NULL)1125{1126if(INT123_feed_more(mh, in, size) != 0) return MPG123_ERR;1127else1128{1129/* The need for more data might have triggered an error.1130This one is outdated now with the new data. */1131if(mh->err == MPG123_ERR_READER) mh->err = MPG123_OK;11321133return MPG123_OK;1134}1135}1136else1137{1138mh->err = MPG123_NULL_BUFFER;1139return MPG123_ERR;1140}1141}1142return MPG123_OK;1143#else1144mh->err = MPG123_MISSING_FEATURE;1145return MPG123_ERR;1146#endif1147}11481149/*1150The old picture:1151while(1) {1152len = read(0,buf,16384);1153if(len <= 0)1154break;1155ret = decodeMP3(&mp,buf,len,out,8192,&size);1156while(ret == MP3_OK) {1157write(1,out,size);1158ret = decodeMP3(&mp,NULL,0,out,8192,&size);1159}1160}1161*/11621163int attribute_align_arg mpg123_decode(mpg123_handle *mh, const unsigned char *inmemory, size_t inmemsize, void *outmem, size_t outmemsize, size_t *done)1164{1165int ret = MPG123_OK;1166size_t mdone = 0;1167unsigned char *outmemory = outmem;11681169if(done != NULL) *done = 0;1170if(mh == NULL) return MPG123_BAD_HANDLE;1171if(inmemsize > 0 && mpg123_feed(mh, inmemory, inmemsize) != MPG123_OK)1172{1173ret = MPG123_ERR;1174goto decodeend;1175}1176if(outmemory == NULL) outmemsize = 0; /* Not just give error, give chance to get a status message. */11771178while(ret == MPG123_OK)1179{1180debug4("decode loop, fill %i (%li vs. %li); to_decode: %i", (int)mh->buffer.fill, (long)mh->num, (long)mh->firstframe, mh->to_decode);1181/* Decode a frame that has been read before.1182This only happens when buffer is empty! */1183if(mh->to_decode)1184{1185if(mh->new_format)1186{1187debug("notifiying new format");1188mh->new_format = 0;1189ret = MPG123_NEW_FORMAT;1190goto decodeend;1191}1192if(mh->buffer.size - mh->buffer.fill < mh->outblock)1193{1194ret = MPG123_NO_SPACE;1195goto decodeend;1196}1197if( (mh->decoder_change && INT123_decode_update(mh) < 0)1198|| ! (mh->state_flags & FRAME_DECODER_LIVE) )1199{1200ret = MPG123_ERR;1201goto decodeend;1202}1203decode_the_frame(mh);1204mh->to_decode = mh->to_ignore = FALSE;1205mh->buffer.p = mh->buffer.data;1206debug2("decoded frame %li, got %li samples in buffer", (long)mh->num, (long)(mh->buffer.fill / (INT123_samples_to_bytes(mh, 1))));1207FRAME_BUFFERCHECK(mh);1208}1209if(mh->buffer.fill) /* Copy (part of) the decoded data to the caller's buffer. */1210{1211/* get what is needed - or just what is there */1212int a = mh->buffer.fill > (outmemsize - mdone) ? outmemsize - mdone : mh->buffer.fill;1213debug4("buffer fill: %i; copying %i (%i - %li)", (int)mh->buffer.fill, a, (int)outmemsize, (long)mdone);1214memcpy(outmemory, mh->buffer.p, a);1215/* less data in frame buffer, less needed, output pointer increase, more data given... */1216mh->buffer.fill -= a;1217outmemory += a;1218mdone += a;1219mh->buffer.p += a;1220if(!(outmemsize > mdone)) goto decodeend;1221}1222else /* If we didn't have data, get a new frame. */1223{1224int b = get_next_frame(mh);1225if(b < 0){ ret = b; goto decodeend; }1226}1227}1228decodeend:1229if(done != NULL) *done = mdone;1230return ret;1231}12321233long attribute_align_arg mpg123_clip(mpg123_handle *mh)1234{1235long ret = 0;12361237if(mh != NULL)1238{1239ret = mh->clip;1240mh->clip = 0;1241}1242return ret;1243}12441245/* Simples: Track needs initializtion if no initial frame has been read yet. */1246#define track_need_init(mh) ((mh)->num < 0)12471248static int init_track(mpg123_handle *mh)1249{1250if(track_need_init(mh))1251{1252/* Fresh track, need first frame for basic info. */1253int b = get_next_frame(mh);1254if(b < 0) return b;1255}1256return 0;1257}12581259// Duplicating the code for the changed member types in struct mpg123_frameinfo2.1260#define MPG123_INFO_FUNC \1261{ \1262int b; \1263\1264if(mh == NULL) return MPG123_BAD_HANDLE; \1265if(mi == NULL) \1266{ \1267mh->err = MPG123_ERR_NULL; \1268return MPG123_ERR; \1269} \1270b = init_track(mh); \1271if(b < 0) return b; \1272\1273mi->version = mh->hdr.mpeg25 ? MPG123_2_5 : (mh->hdr.lsf ? MPG123_2_0 : MPG123_1_0); \1274mi->layer = mh->hdr.lay; \1275mi->rate = INT123_frame_freq(mh); \1276switch(mh->hdr.mode) \1277{ \1278case 0: mi->mode = MPG123_M_STEREO; break; \1279case 1: mi->mode = MPG123_M_JOINT; break; \1280case 2: mi->mode = MPG123_M_DUAL; break; \1281case 3: mi->mode = MPG123_M_MONO; break; \1282default: mi->mode = 0; /* Nothing good to do here. */ \1283} \1284mi->mode_ext = mh->hdr.mode_ext; \1285mi->framesize = mh->hdr.framesize+4; /* Include header. */ \1286mi->flags = 0; \1287if(mh->hdr.error_protection) mi->flags |= MPG123_CRC; \1288if(mh->hdr.copyright) mi->flags |= MPG123_COPYRIGHT; \1289if(mh->hdr.extension) mi->flags |= MPG123_PRIVATE; \1290if(mh->hdr.original) mi->flags |= MPG123_ORIGINAL; \1291mi->emphasis = mh->hdr.emphasis; \1292mi->bitrate = INT123_frame_bitrate(mh); \1293mi->abr_rate = mh->abr_rate; \1294mi->vbr = mh->vbr; \1295return MPG123_OK; \1296}12971298int attribute_align_arg mpg123_info(mpg123_handle *mh, struct mpg123_frameinfo *mi)1299MPG123_INFO_FUNC13001301int attribute_align_arg mpg123_info2(mpg123_handle *mh, struct mpg123_frameinfo2 *mi)1302MPG123_INFO_FUNC13031304int attribute_align_arg mpg123_getformat2( mpg123_handle *mh1305, long *rate, int *channels, int *encoding, int clear_flag )1306{1307int b;13081309if(mh == NULL) return MPG123_BAD_HANDLE;1310b = init_track(mh);1311if(b < 0) return b;13121313if(rate != NULL) *rate = mh->af.rate;1314if(channels != NULL) *channels = mh->af.channels;1315if(encoding != NULL) *encoding = mh->af.encoding;1316if(clear_flag) mh->new_format = 0;1317return MPG123_OK;1318}13191320int attribute_align_arg mpg123_getformat(mpg123_handle *mh, long *rate, int *channels, int *encoding)1321{1322return mpg123_getformat2(mh, rate, channels, encoding, 1);1323}13241325int64_t attribute_align_arg mpg123_timeframe64(mpg123_handle *mh, double seconds)1326{1327int64_t b;13281329if(mh == NULL) return MPG123_ERR;1330b = init_track(mh);1331if(b<0) return b;1332// Overflow checking here would be a bit more elaborate. TODO?1333return (int64_t)(seconds/mpg123_tpf(mh));1334}13351336/*1337Now, where are we? We need to know the last decoded frame... and what's left of it in buffer.1338The current frame number can mean the last decoded frame or the to-be-decoded frame.1339If mh->to_decode, then mh->num frames have been decoded, the frame mh->num now coming next.1340If not, we have the possibility of mh->num+1 frames being decoded or nothing at all.1341Then, there is firstframe...when we didn't reach it yet, then the next data will come from there.1342mh->num starts with -11343*/1344int64_t attribute_align_arg mpg123_tell64(mpg123_handle *mh)1345{1346if(mh == NULL) return MPG123_ERR;1347if(track_need_init(mh)) return 0;1348/* Now we have all the info at hand. */1349debug5("tell: %li/%i first %li buffer %lu; INT123_frame_outs=%li", (long)mh->num, mh->to_decode, (long)mh->firstframe, (unsigned long)mh->buffer.fill, (long)INT123_frame_outs(mh, mh->num));13501351{ /* Funny block to keep C89 happy. */1352int64_t pos = 0;1353if((mh->num < mh->firstframe) || (mh->num == mh->firstframe && mh->to_decode))1354{ /* We are at the beginning, expect output from firstframe on. */1355pos = INT123_frame_outs(mh, mh->firstframe);1356#ifdef GAPLESS1357pos += mh->firstoff;1358#endif1359}1360else if(mh->to_decode)1361{ /* We start fresh with this frame. Buffer should be empty, but we make sure to count it in. */1362pos = INT123_frame_outs(mh, mh->num) - INT123_bytes_to_samples(mh, mh->buffer.fill);1363}1364else1365{ /* We serve what we have in buffer and then the beginning of next frame... */1366pos = INT123_frame_outs(mh, mh->num+1) - INT123_bytes_to_samples(mh, mh->buffer.fill);1367}1368/* Substract padding and delay from the beginning. */1369pos = SAMPLE_ADJUST(mh,pos);1370/* Negative sample offsets are not right, less than nothing is still nothing. */1371return pos>0 ? pos : 0;1372}1373}13741375int64_t attribute_align_arg mpg123_tellframe64(mpg123_handle *mh)1376{1377if(mh == NULL) return MPG123_ERR;1378if(mh->num < mh->firstframe) return mh->firstframe;1379if(mh->to_decode) return mh->num;1380/* Consider firstoff? */1381return mh->buffer.fill ? mh->num : mh->num + 1;1382}13831384int64_t attribute_align_arg mpg123_tell_stream64(mpg123_handle *mh)1385{1386if(mh == NULL) return MPG123_ERR;1387/* mh->rd is at least a bad_reader, so no worry. */1388return mh->rd->tell(mh);1389}13901391static int do_the_seek(mpg123_handle *mh)1392{1393int b;1394int64_t fnum = SEEKFRAME(mh);1395mh->buffer.fill = 0;13961397/* If we are inside the ignoreframe - firstframe window, we may get away without actual seeking. */1398if(mh->num < mh->firstframe)1399{1400mh->to_decode = FALSE; /* In any case, don't decode the current frame, perhaps ignore instead. */1401if(mh->num > fnum) return MPG123_OK;1402}14031404/* If we are already there, we are fine either for decoding or for ignoring. */1405if(mh->num == fnum && (mh->to_decode || fnum < mh->firstframe)) return MPG123_OK;1406/* We have the frame before... just go ahead as normal. */1407if(mh->num == fnum-1)1408{1409mh->to_decode = FALSE;1410return MPG123_OK;1411}14121413/* OK, real seeking follows... clear buffers and go for it. */1414INT123_frame_buffers_reset(mh);1415#ifndef NO_NTOM1416if(mh->down_sample == 3)1417{1418INT123_ntom_set_ntom(mh, fnum);1419debug3("fixed ntom for frame %"PRIi64" to %lu, num=%"PRIi64, fnum, mh->INT123_ntom_val[0], mh->num);1420}1421#endif1422b = mh->rd->seek_frame(mh, fnum);1423if(mh->header_change > 1)1424{1425if(INT123_decode_update(mh) < 0) return MPG123_ERR;1426mh->header_change = 0;1427}1428debug1("seek_frame returned: %i", b);1429if(b<0) return b;1430/* Only mh->to_ignore is TRUE. */1431if(mh->num < mh->firstframe) mh->to_decode = FALSE;14321433mh->playnum = mh->num;1434return 0;1435}14361437int64_t attribute_align_arg mpg123_seek64(mpg123_handle *mh, int64_t sampleoff, int whence)1438{1439int b;1440int64_t pos;14411442pos = mpg123_tell64(mh); /* adjusted samples */1443/* pos < 0 also can mean that simply a former seek failed at the lower levels.1444In that case, we only allow absolute seeks. */1445if(pos < 0 && whence != SEEK_SET)1446{ /* Unless we got the obvious error of NULL handle, this is a special seek failure. */1447if(mh != NULL) mh->err = MPG123_NO_RELSEEK;1448return MPG123_ERR;1449}1450if((b=init_track(mh)) < 0) return b;1451switch(whence)1452{1453case SEEK_CUR: pos += sampleoff; break;1454case SEEK_SET: pos = sampleoff; break;1455case SEEK_END:1456// Fix for a bug that existed since the beginning of libmpg123: SEEK_END offsets are1457// also pointing forward for SEEK_END in lseek(). In libmpg123, they used to interpreted1458// as positive from the end towards the beginning. Since just swapping the sign now would1459// break existing programs and seeks beyond the end just don't make sense for a1460// read-only library, we simply ignore the sign and always assumne negative offsets1461// (pointing towards the beginning). Assuming INT64_MIN <= -INT64_MAX.1462if(sampleoff > 0)1463sampleoff = -sampleoff;1464/* When we do not know the end already, we can try to find it. */1465if(mh->track_frames < 1 && (mh->rdat.flags & READER_SEEKABLE))1466mpg123_scan(mh);1467if(mh->track_frames > 0) pos = SAMPLE_ADJUST(mh,INT123_frame_outs(mh, mh->track_frames)) + sampleoff;1468#ifdef GAPLESS1469else if(mh->end_os > 0) pos = SAMPLE_ADJUST(mh,mh->end_os) + sampleoff;1470#endif1471else1472{1473mh->err = MPG123_NO_SEEK_FROM_END;1474return MPG123_ERR;1475}1476break;1477default: mh->err = MPG123_BAD_WHENCE; return MPG123_ERR;1478}1479if(pos < 0) pos = 0;1480/* pos now holds the wanted sample offset in adjusted samples */1481INT123_frame_set_seek(mh, SAMPLE_UNADJUST(mh,pos));1482pos = do_the_seek(mh);1483if(pos < 0) return pos;14841485return mpg123_tell64(mh);1486}14871488/*1489A bit more tricky... libmpg123 does not do the seeking itself.1490All it can do is to ignore frames until the wanted one is there.1491The caller doesn't know where a specific frame starts and mpg123 also only knows the general region after it scanned the file.1492Well, it is tricky...14931494Wow, there was no input checking at all ... I'll better add it.1495*/1496int64_t attribute_align_arg mpg123_feedseek64(mpg123_handle *mh, int64_t sampleoff, int whence, int64_t *input_offset)1497{1498int b;1499int64_t pos;1500int64_t inoff = 0;1501if(!mh)1502return MPG123_BAD_HANDLE;15031504pos = mpg123_tell64(mh); /* adjusted samples */1505debug3("seek from %li to %li (whence=%i)", (long)pos, (long)sampleoff, whence);1506/* The special seek error handling does not apply here... there is no lowlevel I/O. */1507if(pos < 0) return pos; /* mh == NULL is covered in mpg123_tell() */1508#ifndef NO_FEEDER1509if(input_offset == NULL)1510{1511mh->err = MPG123_NULL_POINTER;1512return MPG123_ERR;1513}15141515if((b=init_track(mh)) < 0) return b; /* May need more to do anything at all. */15161517switch(whence)1518{1519case SEEK_CUR: pos += sampleoff; break;1520case SEEK_SET: pos = sampleoff; break;1521case SEEK_END:1522if(mh->track_frames > 0) pos = SAMPLE_ADJUST(mh,INT123_frame_outs(mh, mh->track_frames)) - sampleoff;1523#ifdef GAPLESS1524else if(mh->end_os >= 0) pos = SAMPLE_ADJUST(mh,mh->end_os) - sampleoff;1525#endif1526else1527{1528mh->err = MPG123_NO_SEEK_FROM_END;1529return MPG123_ERR;1530}1531break;1532default: mh->err = MPG123_BAD_WHENCE; return MPG123_ERR;1533}1534if(pos < 0) pos = 0;1535INT123_frame_set_seek(mh, SAMPLE_UNADJUST(mh,pos));1536pos = SEEKFRAME(mh);1537mh->buffer.fill = 0;15381539/* Shortcuts without modifying input stream. */1540inoff = mh->rdat.buffer.fileoff + mh->rdat.buffer.size;1541if(mh->num < mh->firstframe) mh->to_decode = FALSE;1542if(mh->num == pos && mh->to_decode) goto feedseekend;1543if(mh->num == pos-1) goto feedseekend;1544/* Whole way. */1545inoff = INT123_feed_set_pos(mh, INT123_frame_index_find(mh, SEEKFRAME(mh), &pos));1546mh->num = pos-1; /* The next read frame will have num = pos. */1547if(input_offset)1548*input_offset = inoff;1549if(inoff < 0)1550return MPG123_ERR;15511552feedseekend:1553return mpg123_tell64(mh);1554#else1555mh->err = MPG123_MISSING_FEATURE;1556return MPG123_ERR;1557#endif1558}15591560int64_t attribute_align_arg mpg123_seek_frame64(mpg123_handle *mh, int64_t offset, int whence)1561{1562int b;1563int64_t pos = 0;15641565if(mh == NULL) return MPG123_ERR;1566if((b=init_track(mh)) < 0) return b;15671568/* Could play games here with to_decode... */1569pos = mh->num;1570switch(whence)1571{1572case SEEK_CUR: pos += offset; break;1573case SEEK_SET: pos = offset; break;1574case SEEK_END:1575if(mh->track_frames > 0) pos = mh->track_frames - offset;1576else1577{1578mh->err = MPG123_NO_SEEK_FROM_END;1579return MPG123_ERR;1580}1581break;1582default:1583mh->err = MPG123_BAD_WHENCE;1584return MPG123_ERR;1585}1586if(pos < 0) pos = 0;1587/* Not limiting the possible position on end for the chance that there might be more to the stream than announced via track_frames. */15881589INT123_frame_set_frameseek(mh, pos);1590pos = do_the_seek(mh);1591if(pos < 0) return pos;15921593return mpg123_tellframe64(mh);1594}15951596int attribute_align_arg mpg123_set_filesize64(mpg123_handle *mh, int64_t size)1597{1598if(mh == NULL) return MPG123_BAD_HANDLE;15991600mh->rdat.filelen = size;1601return MPG123_OK;1602}16031604int64_t attribute_align_arg mpg123_framelength64(mpg123_handle *mh)1605{1606int b;1607if(mh == NULL)1608return MPG123_ERR;1609b = init_track(mh);1610if(b<0)1611return b;1612if(mh->track_frames > 0)1613return mh->track_frames;1614if(mh->rdat.filelen > 0)1615{ /* A bad estimate. Ignoring tags 'n stuff. */1616double bpf = mh->mean_framesize > 0.1617? mh->mean_framesize1618: INT123_compute_bpf(mh);1619return (int64_t)((double)(mh->rdat.filelen)/bpf+0.5);1620}1621/* Last resort: No view of the future, can at least count the frames that1622were already parsed. */1623if(mh->num > -1)1624return mh->num+1;1625/* Giving up. */1626return MPG123_ERR;1627}16281629int64_t attribute_align_arg mpg123_length64(mpg123_handle *mh)1630{1631int b;1632int64_t length;16331634if(mh == NULL) return MPG123_ERR;1635b = init_track(mh);1636if(b<0) return b;1637if(mh->track_samples > -1) length = mh->track_samples;1638else if(mh->track_frames > 0) length = mh->track_frames*mh->spf;1639else if(mh->rdat.filelen > 0) /* Let the case of 0 length just fall through. */1640{1641/* A bad estimate. Ignoring tags 'n stuff. */1642double bpf = mh->mean_framesize ? mh->mean_framesize : INT123_compute_bpf(mh);1643length = (int64_t)((double)(mh->rdat.filelen)/bpf*mh->spf);1644}1645else if(mh->rdat.filelen == 0) return mpg123_tell64(mh); /* we could be in feeder mode */1646else return MPG123_ERR; /* No length info there! */16471648debug1("mpg123_length: internal sample length: %"PRIi64, length);16491650length = INT123_frame_ins2outs(mh, length);1651debug1("mpg123_length: external sample length: %"PRIi64, length);1652length = SAMPLE_ADJUST(mh,length);1653return length;1654}16551656int attribute_align_arg mpg123_scan(mpg123_handle *mh)1657{1658int b;1659int64_t oldpos;1660int64_t track_frames = 0;1661int64_t track_samples = 0;16621663if(mh == NULL) return MPG123_BAD_HANDLE;1664if(!(mh->rdat.flags & READER_SEEKABLE)){ mh->err = MPG123_NO_SEEK; return MPG123_ERR; }1665/* Scan through the _whole_ file, since the current position is no count but computed assuming constant samples per frame. */1666/* Also, we can just keep the current buffer and seek settings. Just operate on input frames here. */1667debug("issuing scan");1668b = init_track(mh); /* mh->num >= 0 !! */1669if(b<0)1670{1671if(b == MPG123_DONE) return MPG123_OK;1672else return MPG123_ERR; /* Must be error here, NEED_MORE is not for seekable streams. */1673}1674oldpos = mpg123_tell64(mh);1675b = mh->rd->seek_frame(mh, 0);1676if(b<0 || mh->num != 0) return MPG123_ERR;1677/* One frame must be there now. */1678track_frames = 1;1679track_samples = mh->spf; /* Internal samples. */1680debug("TODO: We should disable gapless code when encountering inconsistent mh->spf!");1681debug(" ... at least unset MPG123_ACCURATE.");1682/* Do not increment mh->track_frames in the loop as tha would confuse Frankenstein detection. */1683while(INT123_read_frame(mh) == 1)1684{1685++track_frames;1686track_samples += mh->spf;1687}1688mh->track_frames = track_frames;1689mh->track_samples = track_samples;1690debug2("Scanning yielded %"PRIi64" track samples, %"PRIi64" frames."1691, mh->track_samples, mh->track_frames);1692#ifdef GAPLESS1693/* Also, think about usefulness of that extra value track_samples ... it could be used for consistency checking. */1694if(mh->p.flags & MPG123_GAPLESS) INT123_frame_gapless_update(mh, mh->track_samples);1695#endif1696return mpg123_seek64(mh, oldpos, SEEK_SET) >= 0 ? MPG123_OK : MPG123_ERR;1697}16981699int attribute_align_arg mpg123_meta_check(mpg123_handle *mh)1700{1701if(mh != NULL) return mh->metaflags;1702else return 0;1703}17041705void attribute_align_arg mpg123_meta_free(mpg123_handle *mh)1706{1707if(mh == NULL) return;17081709INT123_reset_id3(mh);1710INT123_reset_icy(&mh->icy);1711}17121713int attribute_align_arg mpg123_id3(mpg123_handle *mh, mpg123_id3v1 **v1, mpg123_id3v2 **v2)1714{1715if(v1 != NULL) *v1 = NULL;1716if(v2 != NULL) *v2 = NULL;1717if(mh == NULL) return MPG123_BAD_HANDLE;17181719if(mh->metaflags & MPG123_ID3)1720{1721INT123_id3_link(mh);1722if(v1 != NULL && mh->rdat.flags & READER_ID3TAG) *v1 = (mpg123_id3v1*) mh->id3buf;1723if(v2 != NULL)1724#ifdef NO_ID3V21725*v2 = NULL;1726#else1727*v2 = &mh->id3v2;1728#endif17291730mh->metaflags |= MPG123_ID3;1731mh->metaflags &= ~MPG123_NEW_ID3;1732}1733return MPG123_OK;1734}17351736int attribute_align_arg mpg123_id3_raw( mpg123_handle *mh1737, unsigned char **v1, size_t *v1_size1738, unsigned char **v2, size_t *v2_size )1739{1740if(!mh)1741return MPG123_ERR;1742if(v1 != NULL)1743*v1 = mh->id3buf[0] ? mh->id3buf : NULL;1744if(v1_size != NULL)1745*v1_size = mh->id3buf[0] ? 128 : 0;1746if(v2 != NULL)1747*v2 = mh->id3v2_raw;1748if(v2_size != NULL)1749*v2_size = mh->id3v2_size;1750return MPG123_OK;1751}17521753int attribute_align_arg mpg123_icy(mpg123_handle *mh, char **icy_meta)1754{1755if(mh == NULL) return MPG123_BAD_HANDLE;1756#ifndef NO_ICY1757if(icy_meta == NULL)1758{1759mh->err = MPG123_NULL_POINTER;1760return MPG123_ERR;1761}1762*icy_meta = NULL;17631764if(mh->metaflags & MPG123_ICY)1765{1766*icy_meta = mh->icy.data;1767mh->metaflags |= MPG123_ICY;1768mh->metaflags &= ~MPG123_NEW_ICY;1769}1770return MPG123_OK;1771#else1772mh->err = MPG123_MISSING_FEATURE;1773return MPG123_ERR;1774#endif1775}17761777char* attribute_align_arg mpg123_icy2utf8(const char* icy_text)1778{1779#ifndef NO_ICY1780return INT123_icy2utf8(icy_text, 0);1781#else1782return NULL;1783#endif1784}17851786/* That one is always defined... it's not worth it to remove it for NO_ID3V2. */1787enum mpg123_text_encoding attribute_align_arg mpg123_enc_from_id3(unsigned char id3_enc_byte)1788{1789switch(id3_enc_byte)1790{1791case mpg123_id3_latin1: return mpg123_text_latin1;1792case mpg123_id3_utf16bom: return mpg123_text_utf16bom; /* ID3v2.3 has UCS-2 with BOM here. */1793case mpg123_id3_utf16be: return mpg123_text_utf16be;1794case mpg123_id3_utf8: return mpg123_text_utf8;1795default: return mpg123_text_unknown;1796}1797}17981799int attribute_align_arg mpg123_enc_from_id3_2(unsigned char id3_enc_byte)1800{1801return mpg123_enc_from_id3(id3_enc_byte);1802}18031804#ifndef NO_STRING1805int attribute_align_arg mpg123_store_utf8(mpg123_string *sb, enum mpg123_text_encoding enc, const unsigned char *source, size_t source_size)1806{1807switch(enc)1808{1809#ifndef NO_ID3V21810/* The encodings we get from ID3v2 tags. */1811case mpg123_text_utf8:1812INT123_id3_to_utf8(sb, mpg123_id3_utf8, source, source_size, 0);1813break;1814case mpg123_text_latin1:1815INT123_id3_to_utf8(sb, mpg123_id3_latin1, source, source_size, 0);1816break;1817case mpg123_text_utf16bom:1818case mpg123_text_utf16:1819INT123_id3_to_utf8(sb, mpg123_id3_utf16bom, source, source_size, 0);1820break;1821/* Special because one cannot skip zero bytes here. */1822case mpg123_text_utf16be:1823INT123_id3_to_utf8(sb, mpg123_id3_utf16be, source, source_size, 0);1824break;1825#endif1826#ifndef NO_ICY1827/* ICY encoding... */1828case mpg123_text_icy:1829case mpg123_text_cp1252:1830{1831mpg123_free_string(sb);1832/* Paranoia: Make sure that the string ends inside the buffer... */1833if(source[source_size-1] == 0)1834{1835/* Convert from ICY encoding... with force applied or not. */1836char *tmpstring = INT123_icy2utf8((const char*)source, enc == mpg123_text_cp1252 ? 1 : 0);1837if(tmpstring != NULL)1838{1839mpg123_set_string(sb, tmpstring);1840free(tmpstring);1841}1842}1843}1844break;1845#endif1846default:1847mpg123_free_string(sb);1848}1849/* At least a trailing null of some form should be there... */1850return (sb->fill > 0) ? 1 : 0;1851}18521853int attribute_align_arg mpg123_store_utf8_2(mpg123_string *sb, int enc, const unsigned char *source, size_t source_size)1854{1855return mpg123_store_utf8(sb, enc, source, source_size);1856}1857#endif18581859int attribute_align_arg mpg123_index64(mpg123_handle *mh, int64_t **offsets, int64_t *step, size_t *fill)1860{1861if(mh == NULL) return MPG123_BAD_HANDLE;1862if(offsets == NULL || step == NULL || fill == NULL)1863{1864mh->err = MPG123_BAD_INDEX_PAR;1865return MPG123_ERR;1866}1867#ifdef FRAME_INDEX1868*offsets = mh->index.data;1869*step = mh->index.step;1870*fill = mh->index.fill;1871#else1872*offsets = NULL;1873*step = 0;1874*fill = 0;1875#endif1876return MPG123_OK;1877}18781879int attribute_align_arg mpg123_set_index64(mpg123_handle *mh, int64_t *offsets, int64_t step, size_t fill)1880{1881if(mh == NULL) return MPG123_BAD_HANDLE;1882#ifdef FRAME_INDEX1883if(step == 0)1884{1885mh->err = MPG123_BAD_INDEX_PAR;1886return MPG123_ERR;1887}1888if(INT123_fi_set(&mh->index, offsets, step, fill) == -1)1889{1890mh->err = MPG123_OUT_OF_MEM;1891return MPG123_ERR;1892}1893return MPG123_OK;1894#else1895mh->err = MPG123_MISSING_FEATURE;1896return MPG123_ERR;1897#endif1898}189919001901int attribute_align_arg mpg123_close(mpg123_handle *mh)1902{1903if(mh == NULL) return MPG123_BAD_HANDLE;19041905/* mh->rd is never NULL! */1906if(mh->rd->close != NULL) mh->rd->close(mh);19071908if(mh->new_format)1909{1910debug("Hey, we are closing a track before the new format has been queried...");1911INT123_invalidate_format(&mh->af);1912mh->new_format = 0;1913}1914/* Always reset the frame buffers on close, so we cannot forget it in funky opening routines (wrappers, even). */1915INT123_frame_reset(mh);1916return MPG123_OK;1917}19181919void attribute_align_arg mpg123_delete(mpg123_handle *mh)1920{1921if(mh != NULL)1922{1923mpg123_close(mh);1924#ifndef PORTABLE_API1925INT123_wrap_destroy(mh->wrapperdata);1926#endif1927INT123_frame_exit(mh); /* free buffers in frame */1928free(mh); /* free struct; cast? */1929}1930}19311932void attribute_align_arg mpg123_free(void *ptr)1933{1934free(ptr);1935}19361937static const char *mpg123_error[] =1938{1939"No error... (code 0)",1940"Unable to set up output format! (code 1)",1941"Invalid channel number specified. (code 2)",1942"Invalid sample rate specified. (code 3)",1943"Unable to allocate memory for 16 to 8 converter table! (code 4)",1944"Bad parameter id! (code 5)",1945"Bad buffer given -- invalid pointer or too small size. (code 6)",1946"Out of memory -- some malloc() failed. (code 7)",1947"You didn't initialize the library! (code 8)",1948"Invalid decoder choice. (code 9)",1949"Invalid mpg123 handle. (code 10)",1950"Unable to initialize frame buffers (out of memory?)! (code 11)",1951"Invalid RVA mode. (code 12)",1952"This build doesn't support gapless decoding. (code 13)",1953"Not enough buffer space. (code 14)",1954"Incompatible numeric data types. (code 15)",1955"Bad equalizer band. (code 16)",1956"Null pointer given where valid storage address needed. (code 17)",1957"Error reading the stream. (code 18)",1958"Cannot seek from end (end is not known). (code 19)",1959"Invalid 'whence' for seek function. (code 20)",1960"Build does not support stream timeouts. (code 21)",1961"File access error. (code 22)",1962"Seek not supported by stream. (code 23)",1963"No stream opened or missing reader setup while opening. (code 24)",1964"Bad parameter handle. (code 25)",1965"Invalid parameter addresses for index retrieval. (code 26)",1966"Lost track in the bytestream and did not attempt resync. (code 27)",1967"Failed to find valid MPEG data within limit on resync. (code 28)",1968"No 8bit encoding possible. (code 29)",1969"Stack alignment is not good. (code 30)",1970"You gave me a NULL buffer? (code 31)",1971"File position is screwed up, please do an absolute seek (code 32)",1972"Inappropriate NULL-pointer provided.",1973"Bad key value given.",1974"There is no frame index (disabled in this build).",1975"Frame index operation failed.",1976"Decoder setup failed (invalid combination of settings?)",1977"Feature not in this build."1978,"Some bad value has been provided."1979,"Low-level seeking has failed (call to lseek(), usually)."1980,"Custom I/O obviously not prepared."1981,"Overflow in LFS (large file support) conversion."1982,"Overflow in integer conversion."1983,"Bad IEEE 754 rounding. Re-build libmpg123 properly."1984};19851986const char* attribute_align_arg mpg123_plain_strerror(int errcode)1987{1988if(errcode >= 0 && errcode < sizeof(mpg123_error)/sizeof(char*))1989return mpg123_error[errcode];1990else switch(errcode)1991{1992case MPG123_ERR:1993return "A generic mpg123 error.";1994case MPG123_DONE:1995return "Message: I am done with this track.";1996case MPG123_NEED_MORE:1997return "Message: Feed me more input data!";1998case MPG123_NEW_FORMAT:1999return "Message: Prepare for a changed audio format (query the new one)!";2000default:2001return "I have no idea - an unknown error code!";2002}2003}20042005int attribute_align_arg mpg123_errcode(mpg123_handle *mh)2006{2007if(mh != NULL) return mh->err;2008return MPG123_BAD_HANDLE;2009}20102011const char* attribute_align_arg mpg123_strerror(mpg123_handle *mh)2012{2013return mpg123_plain_strerror(mpg123_errcode(mh));2014}20152016#ifndef PORTABLE_API2017// Isolation of lfs_wrap.c code, limited hook to get at its data and2018// for storing error codes.20192020void ** INT123_wrap_handle(mpg123_handle *mh)2021{2022if(mh == NULL)2023return NULL;2024return &(mh->wrapperdata);2025}20262027int INT123_set_err(mpg123_handle *mh, int err)2028{2029if(mh)2030mh->err = err;2031return MPG123_ERR;2032}2033#endif203420352036