1c2c66affSColin Finck /*
2c2c66affSColin Finck libmpg123: MPEG Audio Decoder library
3c2c66affSColin Finck
4*aa811c00SThomas Faber copyright 1995-2020 by the mpg123 project - free software under the terms of the LGPL 2.1
5c2c66affSColin Finck see COPYING and AUTHORS files in distribution or http://mpg123.org
6c2c66affSColin Finck
7c2c66affSColin Finck */
8c2c66affSColin Finck
9c2c66affSColin Finck #include "mpg123lib_intern.h"
10c2c66affSColin Finck #include "icy2utf8.h"
11c2c66affSColin Finck #include "debug.h"
12c2c66affSColin Finck
13c2c66affSColin Finck #include "gapless.h"
14c2c66affSColin Finck /* Want accurate rounding function regardless of decoder setup. */
15c2c66affSColin Finck #define FORCE_ACCURATE
16c2c66affSColin Finck #include "sample.h"
17*aa811c00SThomas Faber #include "parse.h"
18c2c66affSColin Finck
19c2c66affSColin Finck #define SEEKFRAME(mh) ((mh)->ignoreframe < 0 ? 0 : (mh)->ignoreframe)
20c2c66affSColin Finck
21c2c66affSColin Finck static int initialized = 0;
22c2c66affSColin Finck
mpg123_init(void)23c2c66affSColin Finck int attribute_align_arg mpg123_init(void)
24c2c66affSColin Finck {
25c2c66affSColin Finck if((sizeof(short) != 2) || (sizeof(long) < 4)) return MPG123_BAD_TYPES;
26c2c66affSColin Finck
27c2c66affSColin Finck if(initialized) return MPG123_OK; /* no need to initialize twice */
28c2c66affSColin Finck
29c2c66affSColin Finck #ifndef NO_LAYER12
30c2c66affSColin Finck init_layer12(); /* inits also shared tables with layer1 */
31c2c66affSColin Finck #endif
32c2c66affSColin Finck #ifndef NO_LAYER3
33c2c66affSColin Finck init_layer3();
34c2c66affSColin Finck #endif
35c2c66affSColin Finck prepare_decode_tables();
36c2c66affSColin Finck check_decoders();
37c2c66affSColin Finck initialized = 1;
38c2c66affSColin Finck #if (defined REAL_IS_FLOAT) && (defined IEEE_FLOAT)
39c2c66affSColin Finck /* This is rather pointless but it eases my mind to check that we did
40c2c66affSColin Finck not enable the special rounding on a VAX or something. */
41c2c66affSColin Finck if(12346 != REAL_TO_SHORT_ACCURATE(12345.67f))
42c2c66affSColin Finck {
43c2c66affSColin Finck error("Bad IEEE 754 rounding. Re-build libmpg123 properly.");
44c2c66affSColin Finck return MPG123_ERR;
45c2c66affSColin Finck }
46c2c66affSColin Finck #endif
47c2c66affSColin Finck return MPG123_OK;
48c2c66affSColin Finck }
49c2c66affSColin Finck
mpg123_exit(void)50c2c66affSColin Finck void attribute_align_arg mpg123_exit(void)
51c2c66affSColin Finck {
52c2c66affSColin Finck /* nothing yet, but something later perhaps */
53*aa811c00SThomas Faber /* Nope. This is dead space. */
54c2c66affSColin Finck }
55c2c66affSColin Finck
56c2c66affSColin Finck /* create a new handle with specified decoder, decoder can be "", "auto" or NULL for auto-detection */
mpg123_new(const char * decoder,int * error)57c2c66affSColin Finck mpg123_handle attribute_align_arg *mpg123_new(const char* decoder, int *error)
58c2c66affSColin Finck {
59c2c66affSColin Finck return mpg123_parnew(NULL, decoder, error);
60c2c66affSColin Finck }
61c2c66affSColin Finck
62c2c66affSColin Finck /* ...the full routine with optional initial parameters to override defaults. */
mpg123_parnew(mpg123_pars * mp,const char * decoder,int * error)63c2c66affSColin Finck mpg123_handle attribute_align_arg *mpg123_parnew(mpg123_pars *mp, const char* decoder, int *error)
64c2c66affSColin Finck {
65c2c66affSColin Finck mpg123_handle *fr = NULL;
66c2c66affSColin Finck int err = MPG123_OK;
67c2c66affSColin Finck
68c2c66affSColin Finck if(initialized) fr = (mpg123_handle*) malloc(sizeof(mpg123_handle));
69c2c66affSColin Finck else err = MPG123_NOT_INITIALIZED;
70c2c66affSColin Finck if(fr != NULL)
71c2c66affSColin Finck {
72c2c66affSColin Finck frame_init_par(fr, mp);
73c2c66affSColin Finck debug("cpu opt setting");
74c2c66affSColin Finck if(frame_cpu_opt(fr, decoder) != 1)
75c2c66affSColin Finck {
76c2c66affSColin Finck err = MPG123_BAD_DECODER;
77c2c66affSColin Finck frame_exit(fr);
78c2c66affSColin Finck free(fr);
79c2c66affSColin Finck fr = NULL;
80c2c66affSColin Finck }
81c2c66affSColin Finck }
82c2c66affSColin Finck if(fr != NULL)
83c2c66affSColin Finck {
84c2c66affSColin Finck fr->decoder_change = 1;
85c2c66affSColin Finck }
86c2c66affSColin Finck else if(err == MPG123_OK) err = MPG123_OUT_OF_MEM;
87c2c66affSColin Finck
88c2c66affSColin Finck if(error != NULL) *error = err;
89c2c66affSColin Finck return fr;
90c2c66affSColin Finck }
91c2c66affSColin Finck
mpg123_decoder(mpg123_handle * mh,const char * decoder)92c2c66affSColin Finck int attribute_align_arg mpg123_decoder(mpg123_handle *mh, const char* decoder)
93c2c66affSColin Finck {
94c2c66affSColin Finck enum optdec dt = dectype(decoder);
95c2c66affSColin Finck
96c2c66affSColin Finck if(mh == NULL) return MPG123_BAD_HANDLE;
97c2c66affSColin Finck
98c2c66affSColin Finck if(dt == nodec)
99c2c66affSColin Finck {
100c2c66affSColin Finck mh->err = MPG123_BAD_DECODER;
101c2c66affSColin Finck return MPG123_ERR;
102c2c66affSColin Finck }
103c2c66affSColin Finck if(dt == mh->cpu_opts.type) return MPG123_OK;
104c2c66affSColin Finck
105c2c66affSColin Finck /* Now really change. */
106c2c66affSColin Finck /* frame_exit(mh);
107c2c66affSColin Finck frame_init(mh); */
108c2c66affSColin Finck debug("cpu opt setting");
109c2c66affSColin Finck if(frame_cpu_opt(mh, decoder) != 1)
110c2c66affSColin Finck {
111c2c66affSColin Finck mh->err = MPG123_BAD_DECODER;
112c2c66affSColin Finck frame_exit(mh);
113c2c66affSColin Finck return MPG123_ERR;
114c2c66affSColin Finck }
115c2c66affSColin Finck /* New buffers for decoder are created in frame_buffers() */
116c2c66affSColin Finck if((frame_outbuffer(mh) != 0))
117c2c66affSColin Finck {
118c2c66affSColin Finck mh->err = MPG123_NO_BUFFERS;
119c2c66affSColin Finck frame_exit(mh);
120c2c66affSColin Finck return MPG123_ERR;
121c2c66affSColin Finck }
122c2c66affSColin Finck /* Do _not_ call decode_update here! That is only allowed after a first MPEG frame has been met. */
123c2c66affSColin Finck mh->decoder_change = 1;
124c2c66affSColin Finck return MPG123_OK;
125c2c66affSColin Finck }
126c2c66affSColin Finck
mpg123_param(mpg123_handle * mh,enum mpg123_parms key,long val,double fval)127c2c66affSColin Finck int attribute_align_arg mpg123_param(mpg123_handle *mh, enum mpg123_parms key, long val, double fval)
128c2c66affSColin Finck {
129c2c66affSColin Finck int r;
130c2c66affSColin Finck
131c2c66affSColin Finck if(mh == NULL) return MPG123_BAD_HANDLE;
132c2c66affSColin Finck r = mpg123_par(&mh->p, key, val, fval);
133c2c66affSColin Finck if(r != MPG123_OK){ mh->err = r; r = MPG123_ERR; }
134c2c66affSColin Finck else
135c2c66affSColin Finck { /* Special treatment for some settings. */
136c2c66affSColin Finck #ifdef FRAME_INDEX
137c2c66affSColin Finck if(key == MPG123_INDEX_SIZE)
138c2c66affSColin Finck { /* Apply frame index size and grow property on the fly. */
139c2c66affSColin Finck r = frame_index_setup(mh);
140c2c66affSColin Finck if(r != MPG123_OK) mh->err = MPG123_INDEX_FAIL;
141c2c66affSColin Finck }
142c2c66affSColin Finck #endif
143c2c66affSColin Finck #ifndef NO_FEEDER
144c2c66affSColin Finck /* Feeder pool size is applied right away, reader will react to that. */
145c2c66affSColin Finck if(key == MPG123_FEEDPOOL || key == MPG123_FEEDBUFFER)
146c2c66affSColin Finck bc_poolsize(&mh->rdat.buffer, mh->p.feedpool, mh->p.feedbuffer);
147c2c66affSColin Finck #endif
148c2c66affSColin Finck }
149c2c66affSColin Finck return r;
150c2c66affSColin Finck }
151c2c66affSColin Finck
mpg123_par(mpg123_pars * mp,enum mpg123_parms key,long val,double fval)152c2c66affSColin Finck int attribute_align_arg mpg123_par(mpg123_pars *mp, enum mpg123_parms key, long val, double fval)
153c2c66affSColin Finck {
154c2c66affSColin Finck int ret = MPG123_OK;
155c2c66affSColin Finck
156c2c66affSColin Finck if(mp == NULL) return MPG123_BAD_PARS;
157c2c66affSColin Finck switch(key)
158c2c66affSColin Finck {
159c2c66affSColin Finck case MPG123_VERBOSE:
160c2c66affSColin Finck mp->verbose = val;
161c2c66affSColin Finck break;
162c2c66affSColin Finck case MPG123_FLAGS:
163c2c66affSColin Finck #ifndef GAPLESS
164c2c66affSColin Finck if(val & MPG123_GAPLESS) ret = MPG123_NO_GAPLESS;
165c2c66affSColin Finck #endif
166c2c66affSColin Finck if(ret == MPG123_OK) mp->flags = val;
167c2c66affSColin Finck debug1("set flags to 0x%lx", (unsigned long) mp->flags);
168c2c66affSColin Finck break;
169c2c66affSColin Finck case MPG123_ADD_FLAGS:
170c2c66affSColin Finck #ifndef GAPLESS
171c2c66affSColin Finck /* Enabling of gapless mode doesn't work when it's not there, but disabling (below) is no problem. */
172c2c66affSColin Finck if(val & MPG123_GAPLESS) ret = MPG123_NO_GAPLESS;
173c2c66affSColin Finck else
174c2c66affSColin Finck #endif
175c2c66affSColin Finck mp->flags |= val;
176c2c66affSColin Finck debug1("set flags to 0x%lx", (unsigned long) mp->flags);
177c2c66affSColin Finck break;
178c2c66affSColin Finck case MPG123_REMOVE_FLAGS:
179c2c66affSColin Finck mp->flags &= ~val;
180c2c66affSColin Finck debug1("set flags to 0x%lx", (unsigned long) mp->flags);
181c2c66affSColin Finck break;
182c2c66affSColin Finck case MPG123_FORCE_RATE: /* should this trigger something? */
183c2c66affSColin Finck #ifdef NO_NTOM
184c2c66affSColin Finck if(val > 0)
185c2c66affSColin Finck ret = MPG123_BAD_RATE;
186c2c66affSColin Finck #else
187c2c66affSColin Finck if(val > 96000) ret = MPG123_BAD_RATE;
188c2c66affSColin Finck else mp->force_rate = val < 0 ? 0 : val; /* >0 means enable, 0 disable */
189c2c66affSColin Finck #endif
190c2c66affSColin Finck break;
191c2c66affSColin Finck case MPG123_DOWN_SAMPLE:
192c2c66affSColin Finck #ifdef NO_DOWNSAMPLE
193c2c66affSColin Finck if(val != 0) ret = MPG123_BAD_RATE;
194c2c66affSColin Finck #else
195c2c66affSColin Finck if(val < 0 || val > 2) ret = MPG123_BAD_RATE;
196c2c66affSColin Finck else mp->down_sample = (int)val;
197c2c66affSColin Finck #endif
198c2c66affSColin Finck break;
199c2c66affSColin Finck case MPG123_RVA:
200c2c66affSColin Finck if(val < 0 || val > MPG123_RVA_MAX) ret = MPG123_BAD_RVA;
201c2c66affSColin Finck else mp->rva = (int)val;
202c2c66affSColin Finck break;
203c2c66affSColin Finck case MPG123_DOWNSPEED:
204c2c66affSColin Finck mp->halfspeed = val < 0 ? 0 : val;
205c2c66affSColin Finck break;
206c2c66affSColin Finck case MPG123_UPSPEED:
207c2c66affSColin Finck mp->doublespeed = val < 0 ? 0 : val;
208c2c66affSColin Finck break;
209c2c66affSColin Finck case MPG123_ICY_INTERVAL:
210c2c66affSColin Finck #ifndef NO_ICY
211c2c66affSColin Finck mp->icy_interval = val > 0 ? val : 0;
212c2c66affSColin Finck #else
213c2c66affSColin Finck if(val > 0) ret = MPG123_BAD_PARAM;
214c2c66affSColin Finck #endif
215c2c66affSColin Finck break;
216c2c66affSColin Finck case MPG123_OUTSCALE:
217c2c66affSColin Finck /* Choose the value that is non-zero, if any.
218c2c66affSColin Finck Downscaling integers to 1.0 . */
219c2c66affSColin Finck mp->outscale = val == 0 ? fval : (double)val/SHORT_SCALE;
220c2c66affSColin Finck break;
221c2c66affSColin Finck case MPG123_TIMEOUT:
222c2c66affSColin Finck #ifdef TIMEOUT_READ
223c2c66affSColin Finck mp->timeout = val >= 0 ? val : 0;
224c2c66affSColin Finck #else
225c2c66affSColin Finck if(val > 0) ret = MPG123_NO_TIMEOUT;
226c2c66affSColin Finck #endif
227c2c66affSColin Finck break;
228c2c66affSColin Finck case MPG123_RESYNC_LIMIT:
229c2c66affSColin Finck mp->resync_limit = val;
230c2c66affSColin Finck break;
231c2c66affSColin Finck case MPG123_INDEX_SIZE:
232c2c66affSColin Finck #ifdef FRAME_INDEX
233c2c66affSColin Finck mp->index_size = val;
234c2c66affSColin Finck #else
235*aa811c00SThomas Faber if(val) // It is only an eror if you want to enable the index.
236c2c66affSColin Finck ret = MPG123_NO_INDEX;
237c2c66affSColin Finck #endif
238c2c66affSColin Finck break;
239c2c66affSColin Finck case MPG123_PREFRAMES:
240c2c66affSColin Finck if(val >= 0) mp->preframes = val;
241c2c66affSColin Finck else ret = MPG123_BAD_VALUE;
242c2c66affSColin Finck break;
243c2c66affSColin Finck case MPG123_FEEDPOOL:
244c2c66affSColin Finck #ifndef NO_FEEDER
245c2c66affSColin Finck if(val >= 0) mp->feedpool = val;
246c2c66affSColin Finck else ret = MPG123_BAD_VALUE;
247c2c66affSColin Finck #else
248c2c66affSColin Finck ret = MPG123_MISSING_FEATURE;
249c2c66affSColin Finck #endif
250c2c66affSColin Finck break;
251c2c66affSColin Finck case MPG123_FEEDBUFFER:
252c2c66affSColin Finck #ifndef NO_FEEDER
253c2c66affSColin Finck if(val > 0) mp->feedbuffer = val;
254c2c66affSColin Finck else ret = MPG123_BAD_VALUE;
255c2c66affSColin Finck #else
256c2c66affSColin Finck ret = MPG123_MISSING_FEATURE;
257c2c66affSColin Finck #endif
258c2c66affSColin Finck break;
259*aa811c00SThomas Faber case MPG123_FREEFORMAT_SIZE:
260*aa811c00SThomas Faber mp->freeformat_framesize = val;
261*aa811c00SThomas Faber break;
262c2c66affSColin Finck default:
263c2c66affSColin Finck ret = MPG123_BAD_PARAM;
264c2c66affSColin Finck }
265c2c66affSColin Finck return ret;
266c2c66affSColin Finck }
267c2c66affSColin Finck
mpg123_getparam(mpg123_handle * mh,enum mpg123_parms key,long * val,double * fval)268c2c66affSColin Finck int attribute_align_arg mpg123_getparam(mpg123_handle *mh, enum mpg123_parms key, long *val, double *fval)
269c2c66affSColin Finck {
270c2c66affSColin Finck int r;
271c2c66affSColin Finck
272c2c66affSColin Finck if(mh == NULL) return MPG123_BAD_HANDLE;
273c2c66affSColin Finck r = mpg123_getpar(&mh->p, key, val, fval);
274c2c66affSColin Finck if(r != MPG123_OK){ mh->err = r; r = MPG123_ERR; }
275c2c66affSColin Finck return r;
276c2c66affSColin Finck }
277c2c66affSColin Finck
mpg123_getpar(mpg123_pars * mp,enum mpg123_parms key,long * val,double * fval)278c2c66affSColin Finck int attribute_align_arg mpg123_getpar(mpg123_pars *mp, enum mpg123_parms key, long *val, double *fval)
279c2c66affSColin Finck {
280c2c66affSColin Finck int ret = 0;
281c2c66affSColin Finck
282c2c66affSColin Finck if(mp == NULL) return MPG123_BAD_PARS;
283c2c66affSColin Finck switch(key)
284c2c66affSColin Finck {
285c2c66affSColin Finck case MPG123_VERBOSE:
286c2c66affSColin Finck if(val) *val = mp->verbose;
287c2c66affSColin Finck break;
288c2c66affSColin Finck case MPG123_FLAGS:
289c2c66affSColin Finck case MPG123_ADD_FLAGS:
290c2c66affSColin Finck if(val) *val = mp->flags;
291c2c66affSColin Finck break;
292c2c66affSColin Finck case MPG123_FORCE_RATE:
293c2c66affSColin Finck if(val)
294c2c66affSColin Finck #ifdef NO_NTOM
295c2c66affSColin Finck *val = 0;
296c2c66affSColin Finck #else
297c2c66affSColin Finck *val = mp->force_rate;
298c2c66affSColin Finck #endif
299c2c66affSColin Finck break;
300c2c66affSColin Finck case MPG123_DOWN_SAMPLE:
301c2c66affSColin Finck if(val) *val = mp->down_sample;
302c2c66affSColin Finck break;
303c2c66affSColin Finck case MPG123_RVA:
304c2c66affSColin Finck if(val) *val = mp->rva;
305c2c66affSColin Finck break;
306c2c66affSColin Finck case MPG123_DOWNSPEED:
307c2c66affSColin Finck if(val) *val = mp->halfspeed;
308c2c66affSColin Finck break;
309c2c66affSColin Finck case MPG123_UPSPEED:
310c2c66affSColin Finck if(val) *val = mp->doublespeed;
311c2c66affSColin Finck break;
312c2c66affSColin Finck case MPG123_ICY_INTERVAL:
313c2c66affSColin Finck #ifndef NO_ICY
314c2c66affSColin Finck if(val) *val = (long)mp->icy_interval;
315c2c66affSColin Finck #else
316c2c66affSColin Finck if(val) *val = 0;
317c2c66affSColin Finck #endif
318c2c66affSColin Finck break;
319c2c66affSColin Finck case MPG123_OUTSCALE:
320c2c66affSColin Finck if(fval) *fval = mp->outscale;
321c2c66affSColin Finck if(val) *val = (long)(mp->outscale*SHORT_SCALE);
322c2c66affSColin Finck break;
323c2c66affSColin Finck case MPG123_RESYNC_LIMIT:
324c2c66affSColin Finck if(val) *val = mp->resync_limit;
325c2c66affSColin Finck break;
326c2c66affSColin Finck case MPG123_INDEX_SIZE:
327c2c66affSColin Finck if(val)
328c2c66affSColin Finck #ifdef FRAME_INDEX
329c2c66affSColin Finck *val = mp->index_size;
330c2c66affSColin Finck #else
331c2c66affSColin Finck *val = 0; /* graceful fallback: no index is index of zero size */
332c2c66affSColin Finck #endif
333c2c66affSColin Finck break;
334c2c66affSColin Finck case MPG123_PREFRAMES:
335c2c66affSColin Finck *val = mp->preframes;
336c2c66affSColin Finck break;
337c2c66affSColin Finck case MPG123_FEEDPOOL:
338c2c66affSColin Finck #ifndef NO_FEEDER
339c2c66affSColin Finck *val = mp->feedpool;
340c2c66affSColin Finck #else
341c2c66affSColin Finck ret = MPG123_MISSING_FEATURE;
342c2c66affSColin Finck #endif
343c2c66affSColin Finck break;
344c2c66affSColin Finck case MPG123_FEEDBUFFER:
345c2c66affSColin Finck #ifndef NO_FEEDER
346c2c66affSColin Finck *val = mp->feedbuffer;
347c2c66affSColin Finck #else
348c2c66affSColin Finck ret = MPG123_MISSING_FEATURE;
349c2c66affSColin Finck #endif
350c2c66affSColin Finck break;
351*aa811c00SThomas Faber case MPG123_FREEFORMAT_SIZE:
352*aa811c00SThomas Faber *val = mp->freeformat_framesize;
353*aa811c00SThomas Faber break;
354c2c66affSColin Finck default:
355c2c66affSColin Finck ret = MPG123_BAD_PARAM;
356c2c66affSColin Finck }
357c2c66affSColin Finck return ret;
358c2c66affSColin Finck }
359c2c66affSColin Finck
mpg123_getstate(mpg123_handle * mh,enum mpg123_state key,long * val,double * fval)360c2c66affSColin Finck int attribute_align_arg mpg123_getstate(mpg123_handle *mh, enum mpg123_state key, long *val, double *fval)
361c2c66affSColin Finck {
362c2c66affSColin Finck int ret = MPG123_OK;
363c2c66affSColin Finck long theval = 0;
364c2c66affSColin Finck double thefval = 0.;
365c2c66affSColin Finck
366c2c66affSColin Finck if(mh == NULL) return MPG123_BAD_HANDLE;
367c2c66affSColin Finck
368c2c66affSColin Finck switch(key)
369c2c66affSColin Finck {
370c2c66affSColin Finck case MPG123_ACCURATE:
371c2c66affSColin Finck theval = mh->state_flags & FRAME_ACCURATE;
372c2c66affSColin Finck break;
373c2c66affSColin Finck case MPG123_FRANKENSTEIN:
374c2c66affSColin Finck theval = mh->state_flags & FRAME_FRANKENSTEIN;
375c2c66affSColin Finck break;
376c2c66affSColin Finck case MPG123_BUFFERFILL:
377c2c66affSColin Finck #ifndef NO_FEEDER
378c2c66affSColin Finck {
379c2c66affSColin Finck size_t sval = bc_fill(&mh->rdat.buffer);
380c2c66affSColin Finck theval = (long)sval;
381c2c66affSColin Finck if(theval < 0 || (size_t)theval != sval)
382c2c66affSColin Finck {
383c2c66affSColin Finck mh->err = MPG123_INT_OVERFLOW;
384c2c66affSColin Finck ret = MPG123_ERR;
385c2c66affSColin Finck }
386c2c66affSColin Finck }
387c2c66affSColin Finck #else
388c2c66affSColin Finck mh->err = MPG123_MISSING_FEATURE;
389c2c66affSColin Finck ret = MPG123_ERR;
390c2c66affSColin Finck #endif
391c2c66affSColin Finck break;
392c2c66affSColin Finck case MPG123_FRESH_DECODER:
393c2c66affSColin Finck theval = mh->state_flags & FRAME_FRESH_DECODER;
394c2c66affSColin Finck mh->state_flags &= ~FRAME_FRESH_DECODER;
395c2c66affSColin Finck break;
396*aa811c00SThomas Faber case MPG123_ENC_DELAY:
397*aa811c00SThomas Faber theval = mh->enc_delay;
398*aa811c00SThomas Faber break;
399*aa811c00SThomas Faber case MPG123_ENC_PADDING:
400*aa811c00SThomas Faber theval = mh->enc_padding;
401*aa811c00SThomas Faber break;
402*aa811c00SThomas Faber case MPG123_DEC_DELAY:
403*aa811c00SThomas Faber theval = mh->lay == 3 ? GAPLESS_DELAY : -1;
404*aa811c00SThomas Faber break;
405c2c66affSColin Finck default:
406c2c66affSColin Finck mh->err = MPG123_BAD_KEY;
407c2c66affSColin Finck ret = MPG123_ERR;
408c2c66affSColin Finck }
409c2c66affSColin Finck
410c2c66affSColin Finck if(val != NULL) *val = theval;
411c2c66affSColin Finck if(fval != NULL) *fval = thefval;
412c2c66affSColin Finck
413c2c66affSColin Finck return ret;
414c2c66affSColin Finck }
415*aa811c00SThomas Faber
mpg123_eq(mpg123_handle * mh,enum mpg123_channels channel,int band,double val)416c2c66affSColin Finck int attribute_align_arg mpg123_eq(mpg123_handle *mh, enum mpg123_channels channel, int band, double val)
417c2c66affSColin Finck {
418c2c66affSColin Finck #ifndef NO_EQUALIZER
419c2c66affSColin Finck if(mh == NULL) return MPG123_BAD_HANDLE;
420c2c66affSColin Finck if(band < 0 || band > 31){ mh->err = MPG123_BAD_BAND; return MPG123_ERR; }
421c2c66affSColin Finck switch(channel)
422c2c66affSColin Finck {
423c2c66affSColin Finck case MPG123_LEFT|MPG123_RIGHT:
424c2c66affSColin Finck mh->equalizer[0][band] = mh->equalizer[1][band] = DOUBLE_TO_REAL(val);
425c2c66affSColin Finck break;
426c2c66affSColin Finck case MPG123_LEFT: mh->equalizer[0][band] = DOUBLE_TO_REAL(val); break;
427c2c66affSColin Finck case MPG123_RIGHT: mh->equalizer[1][band] = DOUBLE_TO_REAL(val); break;
428c2c66affSColin Finck default:
429c2c66affSColin Finck mh->err=MPG123_BAD_CHANNEL;
430c2c66affSColin Finck return MPG123_ERR;
431c2c66affSColin Finck }
432c2c66affSColin Finck mh->have_eq_settings = TRUE;
433c2c66affSColin Finck #endif
434c2c66affSColin Finck return MPG123_OK;
435c2c66affSColin Finck }
436c2c66affSColin Finck
mpg123_geteq(mpg123_handle * mh,enum mpg123_channels channel,int band)437c2c66affSColin Finck double attribute_align_arg mpg123_geteq(mpg123_handle *mh, enum mpg123_channels channel, int band)
438c2c66affSColin Finck {
439c2c66affSColin Finck double ret = 0.;
440c2c66affSColin Finck #ifndef NO_EQUALIZER
441c2c66affSColin Finck
442c2c66affSColin Finck /* Handle this gracefully. When there is no band, it has no volume. */
443c2c66affSColin Finck if(mh != NULL && band > -1 && band < 32)
444c2c66affSColin Finck switch(channel)
445c2c66affSColin Finck {
446c2c66affSColin Finck case MPG123_LEFT|MPG123_RIGHT:
447c2c66affSColin Finck ret = 0.5*(REAL_TO_DOUBLE(mh->equalizer[0][band])+REAL_TO_DOUBLE(mh->equalizer[1][band]));
448c2c66affSColin Finck break;
449c2c66affSColin Finck case MPG123_LEFT: ret = REAL_TO_DOUBLE(mh->equalizer[0][band]); break;
450c2c66affSColin Finck case MPG123_RIGHT: ret = REAL_TO_DOUBLE(mh->equalizer[1][band]); break;
451c2c66affSColin Finck /* Default case is already handled: ret = 0 */
452c2c66affSColin Finck }
453c2c66affSColin Finck #endif
454c2c66affSColin Finck return ret;
455c2c66affSColin Finck }
456c2c66affSColin Finck
457c2c66affSColin Finck /* plain file access, no http! */
mpg123_open(mpg123_handle * mh,const char * path)458c2c66affSColin Finck int attribute_align_arg mpg123_open(mpg123_handle *mh, const char *path)
459c2c66affSColin Finck {
460c2c66affSColin Finck if(mh == NULL) return MPG123_BAD_HANDLE;
461c2c66affSColin Finck
462c2c66affSColin Finck mpg123_close(mh);
463c2c66affSColin Finck return open_stream(mh, path, -1);
464c2c66affSColin Finck }
465c2c66affSColin Finck
466*aa811c00SThomas Faber // The convenience function mpg123_open_fixed() wraps over acual mpg123_open
467*aa811c00SThomas Faber // and hence needs to have the exact same code in lfs_wrap.c. The flesh is
468*aa811c00SThomas Faber // in open_fixed_pre() and open_fixed_post(), wich are only defined here.
open_fixed_pre(mpg123_handle * mh,int channels,int encoding)469*aa811c00SThomas Faber int open_fixed_pre(mpg123_handle *mh, int channels, int encoding)
470*aa811c00SThomas Faber {
471*aa811c00SThomas Faber if(!mh)
472*aa811c00SThomas Faber return MPG123_BAD_HANDLE;
473*aa811c00SThomas Faber mh->p.flags |= MPG123_NO_FRANKENSTEIN;
474*aa811c00SThomas Faber int err = mpg123_format_none(mh);
475*aa811c00SThomas Faber if(err == MPG123_OK)
476*aa811c00SThomas Faber err = mpg123_format2(mh, 0, channels, encoding);
477*aa811c00SThomas Faber return err;
478*aa811c00SThomas Faber }
479*aa811c00SThomas Faber
open_fixed_post(mpg123_handle * mh,int channels,int encoding)480*aa811c00SThomas Faber int open_fixed_post(mpg123_handle *mh, int channels, int encoding)
481*aa811c00SThomas Faber {
482*aa811c00SThomas Faber if(!mh)
483*aa811c00SThomas Faber return MPG123_BAD_HANDLE;
484*aa811c00SThomas Faber long rate;
485*aa811c00SThomas Faber int err = mpg123_getformat(mh, &rate, &channels, &encoding);
486*aa811c00SThomas Faber if(err == MPG123_OK)
487*aa811c00SThomas Faber err = mpg123_format_none(mh);
488*aa811c00SThomas Faber if(err == MPG123_OK)
489*aa811c00SThomas Faber err = mpg123_format(mh, rate, channels, encoding);
490*aa811c00SThomas Faber if(err == MPG123_OK)
491*aa811c00SThomas Faber {
492*aa811c00SThomas Faber if(mh->track_frames < 1 && (mh->rdat.flags & READER_SEEKABLE))
493*aa811c00SThomas Faber {
494*aa811c00SThomas Faber debug("open_fixed_post: scan because we can seek and do not know track_frames");
495*aa811c00SThomas Faber err = mpg123_scan(mh);
496*aa811c00SThomas Faber }
497*aa811c00SThomas Faber }
498*aa811c00SThomas Faber if(err != MPG123_OK)
499*aa811c00SThomas Faber mpg123_close(mh);
500*aa811c00SThomas Faber return err;
501*aa811c00SThomas Faber }
502*aa811c00SThomas Faber
mpg123_open_fixed(mpg123_handle * mh,const char * path,int channels,int encoding)503*aa811c00SThomas Faber int attribute_align_arg mpg123_open_fixed( mpg123_handle *mh, const char *path
504*aa811c00SThomas Faber , int channels, int encoding )
505*aa811c00SThomas Faber {
506*aa811c00SThomas Faber int err = open_fixed_pre(mh, channels, encoding);
507*aa811c00SThomas Faber if(err == MPG123_OK)
508*aa811c00SThomas Faber err = mpg123_open(mh, path);
509*aa811c00SThomas Faber if(err == MPG123_OK)
510*aa811c00SThomas Faber err = open_fixed_post(mh, channels, encoding);
511*aa811c00SThomas Faber return err;
512*aa811c00SThomas Faber }
513*aa811c00SThomas Faber
mpg123_open_fd(mpg123_handle * mh,int fd)514c2c66affSColin Finck int attribute_align_arg mpg123_open_fd(mpg123_handle *mh, int fd)
515c2c66affSColin Finck {
516c2c66affSColin Finck if(mh == NULL) return MPG123_BAD_HANDLE;
517c2c66affSColin Finck
518c2c66affSColin Finck mpg123_close(mh);
519c2c66affSColin Finck return open_stream(mh, NULL, fd);
520c2c66affSColin Finck }
521c2c66affSColin Finck
mpg123_open_handle(mpg123_handle * mh,void * iohandle)522c2c66affSColin Finck int attribute_align_arg mpg123_open_handle(mpg123_handle *mh, void *iohandle)
523c2c66affSColin Finck {
524c2c66affSColin Finck if(mh == NULL) return MPG123_BAD_HANDLE;
525c2c66affSColin Finck
526c2c66affSColin Finck mpg123_close(mh);
527c2c66affSColin Finck if(mh->rdat.r_read_handle == NULL)
528c2c66affSColin Finck {
529c2c66affSColin Finck mh->err = MPG123_BAD_CUSTOM_IO;
530c2c66affSColin Finck return MPG123_ERR;
531c2c66affSColin Finck }
532c2c66affSColin Finck return open_stream_handle(mh, iohandle);
533c2c66affSColin Finck }
534c2c66affSColin Finck
mpg123_open_feed(mpg123_handle * mh)535c2c66affSColin Finck int attribute_align_arg mpg123_open_feed(mpg123_handle *mh)
536c2c66affSColin Finck {
537c2c66affSColin Finck if(mh == NULL) return MPG123_BAD_HANDLE;
538c2c66affSColin Finck
539c2c66affSColin Finck mpg123_close(mh);
540c2c66affSColin Finck return open_feed(mh);
541c2c66affSColin Finck }
542c2c66affSColin Finck
mpg123_replace_reader(mpg123_handle * mh,ssize_t (* r_read)(int,void *,size_t),off_t (* r_lseek)(int,off_t,int))543c2c66affSColin Finck int attribute_align_arg mpg123_replace_reader( mpg123_handle *mh,
544c2c66affSColin Finck ssize_t (*r_read) (int, void *, size_t),
545c2c66affSColin Finck off_t (*r_lseek)(int, off_t, int) )
546c2c66affSColin Finck {
547c2c66affSColin Finck if(mh == NULL) return MPG123_BAD_HANDLE;
548c2c66affSColin Finck
549c2c66affSColin Finck mpg123_close(mh);
550c2c66affSColin Finck mh->rdat.r_read = r_read;
551c2c66affSColin Finck mh->rdat.r_lseek = r_lseek;
552c2c66affSColin Finck return MPG123_OK;
553c2c66affSColin Finck }
554c2c66affSColin Finck
mpg123_replace_reader_handle(mpg123_handle * mh,ssize_t (* r_read)(void *,void *,size_t),off_t (* r_lseek)(void *,off_t,int),void (* cleanup)(void *))555c2c66affSColin Finck int attribute_align_arg mpg123_replace_reader_handle( mpg123_handle *mh,
556c2c66affSColin Finck ssize_t (*r_read) (void*, void *, size_t),
557c2c66affSColin Finck off_t (*r_lseek)(void*, off_t, int),
558c2c66affSColin Finck void (*cleanup)(void*) )
559c2c66affSColin Finck {
560c2c66affSColin Finck if(mh == NULL) return MPG123_BAD_HANDLE;
561c2c66affSColin Finck
562c2c66affSColin Finck mpg123_close(mh);
563c2c66affSColin Finck mh->rdat.r_read_handle = r_read;
564c2c66affSColin Finck mh->rdat.r_lseek_handle = r_lseek;
565c2c66affSColin Finck mh->rdat.cleanup_handle = cleanup;
566c2c66affSColin Finck return MPG123_OK;
567c2c66affSColin Finck }
568c2c66affSColin Finck
569c2c66affSColin Finck /* Update decoding engine for
570c2c66affSColin Finck a) a new choice of decoder
571c2c66affSColin Finck b) a changed native format of the MPEG stream
572c2c66affSColin Finck ... calls are only valid after parsing some MPEG frame! */
decode_update(mpg123_handle * mh)573c2c66affSColin Finck int decode_update(mpg123_handle *mh)
574c2c66affSColin Finck {
575c2c66affSColin Finck long native_rate;
576c2c66affSColin Finck int b;
577c2c66affSColin Finck
578c2c66affSColin Finck if(mh->num < 0)
579c2c66affSColin Finck {
580c2c66affSColin Finck if(!(mh->p.flags & MPG123_QUIET)) error("decode_update() has been called before reading the first MPEG frame! Internal programming error.");
581c2c66affSColin Finck
582c2c66affSColin Finck mh->err = MPG123_BAD_DECODER_SETUP;
583c2c66affSColin Finck return MPG123_ERR;
584c2c66affSColin Finck }
585c2c66affSColin Finck
586c2c66affSColin Finck mh->state_flags |= FRAME_FRESH_DECODER;
587c2c66affSColin Finck native_rate = frame_freq(mh);
588c2c66affSColin Finck
589c2c66affSColin Finck b = frame_output_format(mh); /* Select the new output format based on given constraints. */
590c2c66affSColin Finck if(b < 0) return MPG123_ERR;
591c2c66affSColin Finck
592c2c66affSColin Finck if(b == 1) mh->new_format = 1; /* Store for later... */
593c2c66affSColin Finck
594c2c66affSColin Finck debug3("updating decoder structure with native rate %li and af.rate %li (new format: %i)", native_rate, mh->af.rate, mh->new_format);
595c2c66affSColin Finck if(mh->af.rate == native_rate) mh->down_sample = 0;
596c2c66affSColin Finck else if(mh->af.rate == native_rate>>1) mh->down_sample = 1;
597c2c66affSColin Finck else if(mh->af.rate == native_rate>>2) mh->down_sample = 2;
598c2c66affSColin Finck else mh->down_sample = 3; /* flexible (fixed) rate */
599c2c66affSColin Finck switch(mh->down_sample)
600c2c66affSColin Finck {
601c2c66affSColin Finck case 0:
602c2c66affSColin Finck case 1:
603c2c66affSColin Finck case 2:
604c2c66affSColin Finck mh->down_sample_sblimit = SBLIMIT>>(mh->down_sample);
605c2c66affSColin Finck /* With downsampling I get less samples per frame */
606c2c66affSColin Finck mh->outblock = outblock_bytes(mh, (mh->spf>>mh->down_sample));
607c2c66affSColin Finck break;
608c2c66affSColin Finck #ifndef NO_NTOM
609c2c66affSColin Finck case 3:
610c2c66affSColin Finck {
611c2c66affSColin Finck if(synth_ntom_set_step(mh) != 0) return -1;
612c2c66affSColin Finck if(frame_freq(mh) > mh->af.rate)
613c2c66affSColin Finck {
614c2c66affSColin Finck mh->down_sample_sblimit = SBLIMIT * mh->af.rate;
615c2c66affSColin Finck mh->down_sample_sblimit /= frame_freq(mh);
616*aa811c00SThomas Faber if(mh->down_sample_sblimit < 1)
617*aa811c00SThomas Faber mh->down_sample_sblimit = 1;
618c2c66affSColin Finck }
619c2c66affSColin Finck else mh->down_sample_sblimit = SBLIMIT;
620c2c66affSColin Finck mh->outblock = outblock_bytes(mh,
621c2c66affSColin Finck ( ( NTOM_MUL-1+mh->spf
622c2c66affSColin Finck * (((size_t)NTOM_MUL*mh->af.rate)/frame_freq(mh))
623c2c66affSColin Finck )/NTOM_MUL ));
624c2c66affSColin Finck }
625c2c66affSColin Finck break;
626c2c66affSColin Finck #endif
627c2c66affSColin Finck }
628c2c66affSColin Finck
629c2c66affSColin Finck if(!(mh->p.flags & MPG123_FORCE_MONO))
630c2c66affSColin Finck {
631c2c66affSColin Finck if(mh->af.channels == 1) mh->single = SINGLE_MIX;
632c2c66affSColin Finck else mh->single = SINGLE_STEREO;
633c2c66affSColin Finck }
634c2c66affSColin Finck else mh->single = (mh->p.flags & MPG123_FORCE_MONO)-1;
635c2c66affSColin Finck if(set_synth_functions(mh) != 0) return -1;;
636c2c66affSColin Finck
637c2c66affSColin Finck /* The needed size of output buffer may have changed. */
638c2c66affSColin Finck if(frame_outbuffer(mh) != MPG123_OK) return -1;
639c2c66affSColin Finck
640c2c66affSColin Finck do_rva(mh);
641c2c66affSColin Finck debug3("done updating decoder structure with native rate %li and af.rate %li and down_sample %i", frame_freq(mh), mh->af.rate, mh->down_sample);
642c2c66affSColin Finck
643*aa811c00SThomas Faber mh->decoder_change = 0;
644c2c66affSColin Finck return 0;
645c2c66affSColin Finck }
646c2c66affSColin Finck
mpg123_safe_buffer(void)647c2c66affSColin Finck size_t attribute_align_arg mpg123_safe_buffer(void)
648c2c66affSColin Finck {
649c2c66affSColin Finck /* real is the largest possible output (it's 32bit float, 32bit int or 64bit double). */
650c2c66affSColin Finck return sizeof(real)*2*1152*NTOM_MAX;
651c2c66affSColin Finck }
652c2c66affSColin Finck
mpg123_outblock(mpg123_handle * mh)653c2c66affSColin Finck size_t attribute_align_arg mpg123_outblock(mpg123_handle *mh)
654c2c66affSColin Finck {
655c2c66affSColin Finck /* Try to be helpful and never return zero output block size. */
656c2c66affSColin Finck if(mh != NULL && mh->outblock > 0) return mh->outblock;
657c2c66affSColin Finck else return mpg123_safe_buffer();
658c2c66affSColin Finck }
659c2c66affSColin Finck
660c2c66affSColin Finck /* Read in the next frame we actually want for decoding.
661c2c66affSColin Finck This includes skipping/ignoring frames, in additon to skipping junk in the parser. */
get_next_frame(mpg123_handle * mh)662c2c66affSColin Finck static int get_next_frame(mpg123_handle *mh)
663c2c66affSColin Finck {
664c2c66affSColin Finck int change = mh->decoder_change;
665c2c66affSColin Finck /* Ensure we got proper decoder for ignoring frames.
666c2c66affSColin Finck Header can be changed from seeking around. But be careful: Only after at
667c2c66affSColin Finck least one frame got read, decoder update makes sense. */
668c2c66affSColin Finck if(mh->header_change > 1 && mh->num >= 0)
669c2c66affSColin Finck {
670c2c66affSColin Finck change = 1;
671c2c66affSColin Finck mh->header_change = 0;
672c2c66affSColin Finck debug("starting with big header change");
673c2c66affSColin Finck if(decode_update(mh) < 0)
674c2c66affSColin Finck return MPG123_ERR;
675c2c66affSColin Finck }
676c2c66affSColin Finck
677c2c66affSColin Finck do
678c2c66affSColin Finck {
679c2c66affSColin Finck int b;
680c2c66affSColin Finck /* Decode & discard some frame(s) before beginning. */
681c2c66affSColin Finck if(mh->to_ignore && mh->num < mh->firstframe && mh->num >= mh->ignoreframe)
682c2c66affSColin Finck {
683c2c66affSColin Finck debug1("ignoring frame %li", (long)mh->num);
684c2c66affSColin Finck /* Decoder structure must be current! decode_update has been called before... */
685c2c66affSColin Finck (mh->do_layer)(mh); mh->buffer.fill = 0;
686c2c66affSColin Finck #ifndef NO_NTOM
687c2c66affSColin Finck /* The ignored decoding may have failed. Make sure ntom stays consistent. */
688c2c66affSColin Finck if(mh->down_sample == 3) ntom_set_ntom(mh, mh->num+1);
689c2c66affSColin Finck #endif
690c2c66affSColin Finck mh->to_ignore = mh->to_decode = FALSE;
691c2c66affSColin Finck }
692c2c66affSColin Finck /* Read new frame data; possibly breaking out here for MPG123_NEED_MORE. */
693c2c66affSColin Finck debug("read frame");
694c2c66affSColin Finck mh->to_decode = FALSE;
695c2c66affSColin Finck b = read_frame(mh); /* That sets to_decode only if a full frame was read. */
696c2c66affSColin Finck debug4("read of frame %li returned %i (to_decode=%i) at sample %li", (long)mh->num, b, mh->to_decode, (long)mpg123_tell(mh));
697c2c66affSColin Finck if(b == MPG123_NEED_MORE) return MPG123_NEED_MORE; /* need another call with data */
698c2c66affSColin Finck else if(b <= 0)
699c2c66affSColin Finck {
700c2c66affSColin Finck /* More sophisticated error control? */
701c2c66affSColin Finck if(b==0 || (mh->rdat.filelen >= 0 && mh->rdat.filepos == mh->rdat.filelen))
702c2c66affSColin Finck { /* We simply reached the end. */
703c2c66affSColin Finck mh->track_frames = mh->num + 1;
704c2c66affSColin Finck debug("What about updating/checking gapless sample count here?");
705c2c66affSColin Finck return MPG123_DONE;
706c2c66affSColin Finck }
707c2c66affSColin Finck else return MPG123_ERR; /* Some real error. */
708c2c66affSColin Finck }
709c2c66affSColin Finck /* Now, there should be new data to decode ... and also possibly new stream properties */
710*aa811c00SThomas Faber if(mh->header_change > 1 || mh->decoder_change)
711c2c66affSColin Finck {
712*aa811c00SThomas Faber debug("big header or decoder change");
713c2c66affSColin Finck change = 1;
714c2c66affSColin Finck mh->header_change = 0;
715c2c66affSColin Finck /* Need to update decoder structure right away since frame might need to
716c2c66affSColin Finck be decoded on next loop iteration for properly ignoring its output. */
717c2c66affSColin Finck if(decode_update(mh) < 0)
718c2c66affSColin Finck return MPG123_ERR;
719c2c66affSColin Finck }
720c2c66affSColin Finck /* Now some accounting: Look at the numbers and decide if we want this frame. */
721c2c66affSColin Finck ++mh->playnum;
722c2c66affSColin Finck /* Plain skipping without decoding, only when frame is not ignored on next cycle. */
723c2c66affSColin Finck if(mh->num < mh->firstframe || (mh->p.doublespeed && (mh->playnum % mh->p.doublespeed)))
724c2c66affSColin Finck {
725c2c66affSColin Finck if(!(mh->to_ignore && mh->num < mh->firstframe && mh->num >= mh->ignoreframe))
726c2c66affSColin Finck {
727c2c66affSColin Finck frame_skip(mh);
728c2c66affSColin Finck /* Should one fix NtoM here or not?
729c2c66affSColin Finck It is not work the trouble for doublespeed, but what with leading frames? */
730c2c66affSColin Finck }
731c2c66affSColin Finck }
732c2c66affSColin Finck /* Or, we are finally done and have a new frame. */
733c2c66affSColin Finck else break;
734c2c66affSColin Finck } while(1);
735c2c66affSColin Finck
736c2c66affSColin Finck /* If we reach this point, we got a new frame ready to be decoded.
737c2c66affSColin Finck All other situations resulted in returns from the loop. */
738c2c66affSColin Finck if(change)
739c2c66affSColin Finck {
740c2c66affSColin Finck if(mh->fresh)
741c2c66affSColin Finck {
742c2c66affSColin Finck #ifdef GAPLESS
743c2c66affSColin Finck int b=0;
744c2c66affSColin Finck /* Prepare offsets for gapless decoding. */
745c2c66affSColin Finck debug1("preparing gapless stuff with native rate %li", frame_freq(mh));
746c2c66affSColin Finck frame_gapless_realinit(mh);
747c2c66affSColin Finck frame_set_frameseek(mh, mh->num);
748c2c66affSColin Finck #endif
749c2c66affSColin Finck mh->fresh = 0;
750c2c66affSColin Finck #ifdef GAPLESS
751c2c66affSColin Finck /* Could this possibly happen? With a real big gapless offset... */
752c2c66affSColin Finck if(mh->num < mh->firstframe) b = get_next_frame(mh);
753c2c66affSColin Finck if(b < 0) return b; /* Could be error, need for more, new format... */
754c2c66affSColin Finck #endif
755c2c66affSColin Finck }
756c2c66affSColin Finck }
757c2c66affSColin Finck return MPG123_OK;
758c2c66affSColin Finck }
759c2c66affSColin Finck
760c2c66affSColin Finck /* Assumption: A buffer full of zero samples can be constructed by repetition of this byte.
761c2c66affSColin Finck Oh, and it handles some format conversion.
762c2c66affSColin Finck Only to be used by decode_the_frame() ... */
zero_byte(mpg123_handle * fr)763c2c66affSColin Finck static int zero_byte(mpg123_handle *fr)
764c2c66affSColin Finck {
765c2c66affSColin Finck #ifndef NO_8BIT
766c2c66affSColin Finck return fr->af.encoding & MPG123_ENC_8 ? fr->conv16to8[0] : 0;
767c2c66affSColin Finck #else
768c2c66affSColin Finck return 0; /* All normal signed formats have the zero here (even in byte form -- that may be an assumption for your funny machine...). */
769c2c66affSColin Finck #endif
770c2c66affSColin Finck }
771c2c66affSColin Finck
772c2c66affSColin Finck /*
773c2c66affSColin Finck Not part of the api. This just decodes the frame and fills missing bits with zeroes.
774c2c66affSColin Finck There can be frames that are broken and thus make do_layer() fail.
775c2c66affSColin Finck */
decode_the_frame(mpg123_handle * fr)776c2c66affSColin Finck static void decode_the_frame(mpg123_handle *fr)
777c2c66affSColin Finck {
778c2c66affSColin Finck size_t needed_bytes = decoder_synth_bytes(fr, frame_expect_outsamples(fr));
779c2c66affSColin Finck fr->clip += (fr->do_layer)(fr);
780c2c66affSColin Finck /*fprintf(stderr, "frame %"OFF_P": got %"SIZE_P" / %"SIZE_P"\n", fr->num,(size_p)fr->buffer.fill, (size_p)needed_bytes);*/
781c2c66affSColin Finck /* There could be less data than promised.
782c2c66affSColin Finck Also, then debugging, we look out for coding errors that could result in _more_ data than expected. */
783c2c66affSColin Finck #ifdef DEBUG
784c2c66affSColin Finck if(fr->buffer.fill != needed_bytes)
785c2c66affSColin Finck {
786c2c66affSColin Finck #endif
787c2c66affSColin Finck if(fr->buffer.fill < needed_bytes)
788c2c66affSColin Finck {
789c2c66affSColin Finck if(VERBOSE2)
790c2c66affSColin Finck fprintf(stderr, "Note: broken frame %li, filling up with %"SIZE_P" zeroes, from %"SIZE_P"\n", (long)fr->num, (size_p)(needed_bytes-fr->buffer.fill), (size_p)fr->buffer.fill);
791c2c66affSColin Finck
792c2c66affSColin Finck /*
793c2c66affSColin Finck One could do a loop with individual samples instead... but zero is zero
794c2c66affSColin Finck Actually, that is wrong: zero is mostly a series of null bytes,
795c2c66affSColin Finck but we have funny 8bit formats that have a different opinion on zero...
796c2c66affSColin Finck Unsigned 16 or 32 bit formats are handled later.
797c2c66affSColin Finck */
798c2c66affSColin Finck memset( fr->buffer.data + fr->buffer.fill, zero_byte(fr), needed_bytes - fr->buffer.fill );
799c2c66affSColin Finck
800c2c66affSColin Finck fr->buffer.fill = needed_bytes;
801c2c66affSColin Finck #ifndef NO_NTOM
802c2c66affSColin Finck /* ntom_val will be wrong when the decoding wasn't carried out completely */
803c2c66affSColin Finck ntom_set_ntom(fr, fr->num+1);
804c2c66affSColin Finck #endif
805c2c66affSColin Finck }
806c2c66affSColin Finck #ifdef DEBUG
807c2c66affSColin Finck else
808c2c66affSColin Finck {
809c2c66affSColin Finck if(NOQUIET)
810c2c66affSColin Finck error2("I got _more_ bytes than expected (%"SIZE_P" / %"SIZE_P"), that should not be possible!", (size_p)fr->buffer.fill, (size_p)needed_bytes);
811c2c66affSColin Finck }
812c2c66affSColin Finck }
813c2c66affSColin Finck #endif
814c2c66affSColin Finck postprocess_buffer(fr);
815c2c66affSColin Finck }
816c2c66affSColin Finck
817c2c66affSColin Finck /*
818c2c66affSColin Finck Decode the current frame into the frame structure's buffer, accessible at the location stored in <audio>, with <bytes> bytes available.
819c2c66affSColin Finck <num> will contain the last decoded frame number. This function should be called after mpg123_framebyframe_next positioned the stream at a
820c2c66affSColin Finck valid mp3 frame. The buffer contents will get lost on the next call to mpg123_framebyframe_next or mpg123_framebyframe_decode.
821c2c66affSColin Finck returns
822c2c66affSColin Finck MPG123_OK -- successfully decoded or ignored the frame, you get your output data or in case of ignored frames 0 bytes
823c2c66affSColin Finck MPG123_DONE -- decoding finished, should not happen
824c2c66affSColin Finck MPG123_ERR -- some error occured.
825c2c66affSColin Finck MPG123_ERR_NULL -- audio or bytes are not pointing to valid storage addresses
826c2c66affSColin Finck MPG123_BAD_HANDLE -- mh has not been initialized
827c2c66affSColin Finck MPG123_NO_SPACE -- not enough space in buffer for safe decoding, should not happen
828c2c66affSColin Finck */
mpg123_framebyframe_decode(mpg123_handle * mh,off_t * num,unsigned char ** audio,size_t * bytes)829c2c66affSColin Finck int attribute_align_arg mpg123_framebyframe_decode(mpg123_handle *mh, off_t *num, unsigned char **audio, size_t *bytes)
830c2c66affSColin Finck {
831c2c66affSColin Finck if(bytes == NULL) return MPG123_ERR_NULL;
832c2c66affSColin Finck if(audio == NULL) return MPG123_ERR_NULL;
833c2c66affSColin Finck if(mh == NULL) return MPG123_BAD_HANDLE;
834c2c66affSColin Finck if(mh->buffer.size < mh->outblock) return MPG123_NO_SPACE;
835c2c66affSColin Finck
836c2c66affSColin Finck *bytes = 0;
837c2c66affSColin Finck mh->buffer.fill = 0; /* always start fresh */
838c2c66affSColin Finck if(!mh->to_decode) return MPG123_OK;
839c2c66affSColin Finck
840c2c66affSColin Finck if(num != NULL) *num = mh->num;
841c2c66affSColin Finck debug("decoding");
842c2c66affSColin Finck decode_the_frame(mh);
843c2c66affSColin Finck mh->to_decode = mh->to_ignore = FALSE;
844c2c66affSColin Finck mh->buffer.p = mh->buffer.data;
845c2c66affSColin Finck FRAME_BUFFERCHECK(mh);
846c2c66affSColin Finck *audio = mh->buffer.p;
847c2c66affSColin Finck *bytes = mh->buffer.fill;
848c2c66affSColin Finck return MPG123_OK;
849c2c66affSColin Finck }
850c2c66affSColin Finck
851c2c66affSColin Finck /*
852c2c66affSColin Finck Find, read and parse the next mp3 frame while skipping junk and parsing id3 tags, lame headers, etc.
853c2c66affSColin Finck Prepares everything for decoding using mpg123_framebyframe_decode.
854c2c66affSColin Finck returns
855c2c66affSColin Finck MPG123_OK -- new frame was read and parsed, call mpg123_framebyframe_decode to actually decode
856c2c66affSColin Finck MPG123_NEW_FORMAT -- new frame was read, it results in changed output format, call mpg123_framebyframe_decode to actually decode
857c2c66affSColin Finck MPG123_BAD_HANDLE -- mh has not been initialized
858c2c66affSColin Finck MPG123_NEED_MORE -- more input data is needed to advance to the next frame. supply more input data using mpg123_feed
859c2c66affSColin Finck */
mpg123_framebyframe_next(mpg123_handle * mh)860c2c66affSColin Finck int attribute_align_arg mpg123_framebyframe_next(mpg123_handle *mh)
861c2c66affSColin Finck {
862c2c66affSColin Finck int b;
863c2c66affSColin Finck if(mh == NULL) return MPG123_BAD_HANDLE;
864c2c66affSColin Finck
865c2c66affSColin Finck mh->to_decode = mh->to_ignore = FALSE;
866c2c66affSColin Finck mh->buffer.fill = 0;
867c2c66affSColin Finck
868c2c66affSColin Finck b = get_next_frame(mh);
869c2c66affSColin Finck if(b < 0) return b;
870c2c66affSColin Finck debug1("got next frame, %i", mh->to_decode);
871c2c66affSColin Finck
872c2c66affSColin Finck /* mpg123_framebyframe_decode will return MPG123_OK with 0 bytes decoded if mh->to_decode is 0 */
873c2c66affSColin Finck if(!mh->to_decode)
874c2c66affSColin Finck return MPG123_OK;
875c2c66affSColin Finck
876c2c66affSColin Finck if(mh->new_format)
877c2c66affSColin Finck {
878c2c66affSColin Finck debug("notifiying new format");
879c2c66affSColin Finck mh->new_format = 0;
880c2c66affSColin Finck return MPG123_NEW_FORMAT;
881c2c66affSColin Finck }
882c2c66affSColin Finck
883c2c66affSColin Finck return MPG123_OK;
884c2c66affSColin Finck }
885c2c66affSColin Finck
886c2c66affSColin Finck /*
887c2c66affSColin Finck Put _one_ decoded frame into the frame structure's buffer, accessible at the location stored in <audio>, with <bytes> bytes available.
888c2c66affSColin Finck The buffer contents will be lost on next call to mpg123_decode_frame.
889c2c66affSColin Finck MPG123_OK -- successfully decoded the frame, you get your output data
890c2c66affSColin Finck MPg123_DONE -- This is it. End.
891c2c66affSColin Finck MPG123_ERR -- some error occured...
892c2c66affSColin Finck MPG123_NEW_FORMAT -- new frame was read, it results in changed output format -> will be decoded on next call
893c2c66affSColin Finck MPG123_NEED_MORE -- that should not happen as this function is intended for in-library stream reader but if you force it...
894c2c66affSColin Finck MPG123_NO_SPACE -- not enough space in buffer for safe decoding, also should not happen
895c2c66affSColin Finck
896c2c66affSColin Finck num will be updated to the last decoded frame number (may possibly _not_ increase, p.ex. when format changed).
897c2c66affSColin Finck */
mpg123_decode_frame(mpg123_handle * mh,off_t * num,unsigned char ** audio,size_t * bytes)898c2c66affSColin Finck int attribute_align_arg mpg123_decode_frame(mpg123_handle *mh, off_t *num, unsigned char **audio, size_t *bytes)
899c2c66affSColin Finck {
900c2c66affSColin Finck if(bytes != NULL) *bytes = 0;
901c2c66affSColin Finck if(mh == NULL) return MPG123_BAD_HANDLE;
902c2c66affSColin Finck if(mh->buffer.size < mh->outblock) return MPG123_NO_SPACE;
903c2c66affSColin Finck mh->buffer.fill = 0; /* always start fresh */
904*aa811c00SThomas Faber /* Be nice: Set these also for sensible values in case of error. */
905*aa811c00SThomas Faber if(audio) *audio = NULL;
906*aa811c00SThomas Faber if(bytes) *bytes = 0;
907c2c66affSColin Finck while(TRUE)
908c2c66affSColin Finck {
909c2c66affSColin Finck /* decode if possible */
910c2c66affSColin Finck if(mh->to_decode)
911c2c66affSColin Finck {
912*aa811c00SThomas Faber if(num != NULL) *num = mh->num;
913c2c66affSColin Finck if(mh->new_format)
914c2c66affSColin Finck {
915c2c66affSColin Finck debug("notifiying new format");
916c2c66affSColin Finck mh->new_format = 0;
917c2c66affSColin Finck return MPG123_NEW_FORMAT;
918c2c66affSColin Finck }
919c2c66affSColin Finck debug("decoding");
920c2c66affSColin Finck
921*aa811c00SThomas Faber if(mh->decoder_change && decode_update(mh) < 0)
922*aa811c00SThomas Faber return MPG123_ERR;
923c2c66affSColin Finck decode_the_frame(mh);
924c2c66affSColin Finck
925c2c66affSColin Finck mh->to_decode = mh->to_ignore = FALSE;
926c2c66affSColin Finck mh->buffer.p = mh->buffer.data;
927c2c66affSColin Finck FRAME_BUFFERCHECK(mh);
928c2c66affSColin Finck if(audio != NULL) *audio = mh->buffer.p;
929c2c66affSColin Finck if(bytes != NULL) *bytes = mh->buffer.fill;
930c2c66affSColin Finck
931c2c66affSColin Finck return MPG123_OK;
932c2c66affSColin Finck }
933c2c66affSColin Finck else
934c2c66affSColin Finck {
935c2c66affSColin Finck int b = get_next_frame(mh);
936c2c66affSColin Finck if(b < 0) return b;
937c2c66affSColin Finck debug1("got next frame, %i", mh->to_decode);
938c2c66affSColin Finck }
939c2c66affSColin Finck }
940c2c66affSColin Finck }
941c2c66affSColin Finck
mpg123_read(mpg123_handle * mh,void * out,size_t size,size_t * done)942*aa811c00SThomas Faber int attribute_align_arg mpg123_read(mpg123_handle *mh, void *out, size_t size, size_t *done)
943c2c66affSColin Finck {
944c2c66affSColin Finck return mpg123_decode(mh, NULL, 0, out, size, done);
945c2c66affSColin Finck }
946c2c66affSColin Finck
mpg123_feed(mpg123_handle * mh,const unsigned char * in,size_t size)947c2c66affSColin Finck int attribute_align_arg mpg123_feed(mpg123_handle *mh, const unsigned char *in, size_t size)
948c2c66affSColin Finck {
949c2c66affSColin Finck if(mh == NULL) return MPG123_BAD_HANDLE;
950c2c66affSColin Finck #ifndef NO_FEEDER
951c2c66affSColin Finck if(size > 0)
952c2c66affSColin Finck {
953c2c66affSColin Finck if(in != NULL)
954c2c66affSColin Finck {
955c2c66affSColin Finck if(feed_more(mh, in, size) != 0) return MPG123_ERR;
956c2c66affSColin Finck else
957c2c66affSColin Finck {
958c2c66affSColin Finck /* The need for more data might have triggered an error.
959c2c66affSColin Finck This one is outdated now with the new data. */
960c2c66affSColin Finck if(mh->err == MPG123_ERR_READER) mh->err = MPG123_OK;
961c2c66affSColin Finck
962c2c66affSColin Finck return MPG123_OK;
963c2c66affSColin Finck }
964c2c66affSColin Finck }
965c2c66affSColin Finck else
966c2c66affSColin Finck {
967c2c66affSColin Finck mh->err = MPG123_NULL_BUFFER;
968c2c66affSColin Finck return MPG123_ERR;
969c2c66affSColin Finck }
970c2c66affSColin Finck }
971c2c66affSColin Finck return MPG123_OK;
972c2c66affSColin Finck #else
973c2c66affSColin Finck mh->err = MPG123_MISSING_FEATURE;
974c2c66affSColin Finck return MPG123_ERR;
975c2c66affSColin Finck #endif
976c2c66affSColin Finck }
977c2c66affSColin Finck
978c2c66affSColin Finck /*
979c2c66affSColin Finck The old picture:
980c2c66affSColin Finck while(1) {
981c2c66affSColin Finck len = read(0,buf,16384);
982c2c66affSColin Finck if(len <= 0)
983c2c66affSColin Finck break;
984c2c66affSColin Finck ret = decodeMP3(&mp,buf,len,out,8192,&size);
985c2c66affSColin Finck while(ret == MP3_OK) {
986c2c66affSColin Finck write(1,out,size);
987c2c66affSColin Finck ret = decodeMP3(&mp,NULL,0,out,8192,&size);
988c2c66affSColin Finck }
989c2c66affSColin Finck }
990c2c66affSColin Finck */
991c2c66affSColin Finck
mpg123_decode(mpg123_handle * mh,const unsigned char * inmemory,size_t inmemsize,void * outmem,size_t outmemsize,size_t * done)992*aa811c00SThomas Faber int attribute_align_arg mpg123_decode(mpg123_handle *mh, const unsigned char *inmemory, size_t inmemsize, void *outmem, size_t outmemsize, size_t *done)
993c2c66affSColin Finck {
994c2c66affSColin Finck int ret = MPG123_OK;
995c2c66affSColin Finck size_t mdone = 0;
996*aa811c00SThomas Faber unsigned char *outmemory = outmem;
997c2c66affSColin Finck
998c2c66affSColin Finck if(done != NULL) *done = 0;
999c2c66affSColin Finck if(mh == NULL) return MPG123_BAD_HANDLE;
1000c2c66affSColin Finck if(inmemsize > 0 && mpg123_feed(mh, inmemory, inmemsize) != MPG123_OK)
1001c2c66affSColin Finck {
1002c2c66affSColin Finck ret = MPG123_ERR;
1003c2c66affSColin Finck goto decodeend;
1004c2c66affSColin Finck }
1005c2c66affSColin Finck if(outmemory == NULL) outmemsize = 0; /* Not just give error, give chance to get a status message. */
1006c2c66affSColin Finck
1007c2c66affSColin Finck while(ret == MPG123_OK)
1008c2c66affSColin Finck {
1009c2c66affSColin Finck debug4("decode loop, fill %i (%li vs. %li); to_decode: %i", (int)mh->buffer.fill, (long)mh->num, (long)mh->firstframe, mh->to_decode);
1010c2c66affSColin Finck /* Decode a frame that has been read before.
1011c2c66affSColin Finck This only happens when buffer is empty! */
1012c2c66affSColin Finck if(mh->to_decode)
1013c2c66affSColin Finck {
1014c2c66affSColin Finck if(mh->new_format)
1015c2c66affSColin Finck {
1016c2c66affSColin Finck debug("notifiying new format");
1017c2c66affSColin Finck mh->new_format = 0;
1018c2c66affSColin Finck ret = MPG123_NEW_FORMAT;
1019c2c66affSColin Finck goto decodeend;
1020c2c66affSColin Finck }
1021c2c66affSColin Finck if(mh->buffer.size - mh->buffer.fill < mh->outblock)
1022c2c66affSColin Finck {
1023c2c66affSColin Finck ret = MPG123_NO_SPACE;
1024c2c66affSColin Finck goto decodeend;
1025c2c66affSColin Finck }
1026*aa811c00SThomas Faber if(mh->decoder_change && decode_update(mh) < 0)
1027*aa811c00SThomas Faber {
1028*aa811c00SThomas Faber ret = MPG123_ERR;
1029*aa811c00SThomas Faber goto decodeend;
1030*aa811c00SThomas Faber }
1031c2c66affSColin Finck decode_the_frame(mh);
1032c2c66affSColin Finck mh->to_decode = mh->to_ignore = FALSE;
1033c2c66affSColin Finck mh->buffer.p = mh->buffer.data;
1034c2c66affSColin Finck debug2("decoded frame %li, got %li samples in buffer", (long)mh->num, (long)(mh->buffer.fill / (samples_to_bytes(mh, 1))));
1035c2c66affSColin Finck FRAME_BUFFERCHECK(mh);
1036c2c66affSColin Finck }
1037c2c66affSColin Finck if(mh->buffer.fill) /* Copy (part of) the decoded data to the caller's buffer. */
1038c2c66affSColin Finck {
1039c2c66affSColin Finck /* get what is needed - or just what is there */
1040c2c66affSColin Finck int a = mh->buffer.fill > (outmemsize - mdone) ? outmemsize - mdone : mh->buffer.fill;
1041c2c66affSColin Finck debug4("buffer fill: %i; copying %i (%i - %li)", (int)mh->buffer.fill, a, (int)outmemsize, (long)mdone);
1042c2c66affSColin Finck memcpy(outmemory, mh->buffer.p, a);
1043c2c66affSColin Finck /* less data in frame buffer, less needed, output pointer increase, more data given... */
1044c2c66affSColin Finck mh->buffer.fill -= a;
1045c2c66affSColin Finck outmemory += a;
1046c2c66affSColin Finck mdone += a;
1047c2c66affSColin Finck mh->buffer.p += a;
1048c2c66affSColin Finck if(!(outmemsize > mdone)) goto decodeend;
1049c2c66affSColin Finck }
1050c2c66affSColin Finck else /* If we didn't have data, get a new frame. */
1051c2c66affSColin Finck {
1052c2c66affSColin Finck int b = get_next_frame(mh);
1053c2c66affSColin Finck if(b < 0){ ret = b; goto decodeend; }
1054c2c66affSColin Finck }
1055c2c66affSColin Finck }
1056c2c66affSColin Finck decodeend:
1057c2c66affSColin Finck if(done != NULL) *done = mdone;
1058c2c66affSColin Finck return ret;
1059c2c66affSColin Finck }
1060c2c66affSColin Finck
mpg123_clip(mpg123_handle * mh)1061c2c66affSColin Finck long attribute_align_arg mpg123_clip(mpg123_handle *mh)
1062c2c66affSColin Finck {
1063c2c66affSColin Finck long ret = 0;
1064c2c66affSColin Finck
1065c2c66affSColin Finck if(mh != NULL)
1066c2c66affSColin Finck {
1067c2c66affSColin Finck ret = mh->clip;
1068c2c66affSColin Finck mh->clip = 0;
1069c2c66affSColin Finck }
1070c2c66affSColin Finck return ret;
1071c2c66affSColin Finck }
1072c2c66affSColin Finck
1073c2c66affSColin Finck /* Simples: Track needs initializtion if no initial frame has been read yet. */
1074c2c66affSColin Finck #define track_need_init(mh) ((mh)->num < 0)
1075c2c66affSColin Finck
init_track(mpg123_handle * mh)1076c2c66affSColin Finck static int init_track(mpg123_handle *mh)
1077c2c66affSColin Finck {
1078c2c66affSColin Finck if(track_need_init(mh))
1079c2c66affSColin Finck {
1080c2c66affSColin Finck /* Fresh track, need first frame for basic info. */
1081c2c66affSColin Finck int b = get_next_frame(mh);
1082c2c66affSColin Finck if(b < 0) return b;
1083c2c66affSColin Finck }
1084c2c66affSColin Finck return 0;
1085c2c66affSColin Finck }
1086c2c66affSColin Finck
mpg123_info(mpg123_handle * mh,struct mpg123_frameinfo * mi)1087c2c66affSColin Finck int attribute_align_arg mpg123_info(mpg123_handle *mh, struct mpg123_frameinfo *mi)
1088c2c66affSColin Finck {
1089c2c66affSColin Finck int b;
1090c2c66affSColin Finck
1091c2c66affSColin Finck if(mh == NULL) return MPG123_BAD_HANDLE;
1092c2c66affSColin Finck if(mi == NULL)
1093c2c66affSColin Finck {
1094c2c66affSColin Finck mh->err = MPG123_ERR_NULL;
1095c2c66affSColin Finck return MPG123_ERR;
1096c2c66affSColin Finck }
1097c2c66affSColin Finck b = init_track(mh);
1098c2c66affSColin Finck if(b < 0) return b;
1099c2c66affSColin Finck
1100c2c66affSColin Finck mi->version = mh->mpeg25 ? MPG123_2_5 : (mh->lsf ? MPG123_2_0 : MPG123_1_0);
1101c2c66affSColin Finck mi->layer = mh->lay;
1102c2c66affSColin Finck mi->rate = frame_freq(mh);
1103c2c66affSColin Finck switch(mh->mode)
1104c2c66affSColin Finck {
1105c2c66affSColin Finck case 0: mi->mode = MPG123_M_STEREO; break;
1106c2c66affSColin Finck case 1: mi->mode = MPG123_M_JOINT; break;
1107c2c66affSColin Finck case 2: mi->mode = MPG123_M_DUAL; break;
1108c2c66affSColin Finck case 3: mi->mode = MPG123_M_MONO; break;
1109*aa811c00SThomas Faber default: mi->mode = 0; // Nothing good to do here.
1110c2c66affSColin Finck }
1111c2c66affSColin Finck mi->mode_ext = mh->mode_ext;
1112c2c66affSColin Finck mi->framesize = mh->framesize+4; /* Include header. */
1113c2c66affSColin Finck mi->flags = 0;
1114c2c66affSColin Finck if(mh->error_protection) mi->flags |= MPG123_CRC;
1115c2c66affSColin Finck if(mh->copyright) mi->flags |= MPG123_COPYRIGHT;
1116c2c66affSColin Finck if(mh->extension) mi->flags |= MPG123_PRIVATE;
1117c2c66affSColin Finck if(mh->original) mi->flags |= MPG123_ORIGINAL;
1118c2c66affSColin Finck mi->emphasis = mh->emphasis;
1119c2c66affSColin Finck mi->bitrate = frame_bitrate(mh);
1120c2c66affSColin Finck mi->abr_rate = mh->abr_rate;
1121c2c66affSColin Finck mi->vbr = mh->vbr;
1122c2c66affSColin Finck return MPG123_OK;
1123c2c66affSColin Finck }
1124c2c66affSColin Finck
mpg123_getformat2(mpg123_handle * mh,long * rate,int * channels,int * encoding,int clear_flag)1125c2c66affSColin Finck int attribute_align_arg mpg123_getformat2( mpg123_handle *mh
1126c2c66affSColin Finck , long *rate, int *channels, int *encoding, int clear_flag )
1127c2c66affSColin Finck {
1128c2c66affSColin Finck int b;
1129c2c66affSColin Finck
1130c2c66affSColin Finck if(mh == NULL) return MPG123_BAD_HANDLE;
1131c2c66affSColin Finck b = init_track(mh);
1132c2c66affSColin Finck if(b < 0) return b;
1133c2c66affSColin Finck
1134c2c66affSColin Finck if(rate != NULL) *rate = mh->af.rate;
1135c2c66affSColin Finck if(channels != NULL) *channels = mh->af.channels;
1136c2c66affSColin Finck if(encoding != NULL) *encoding = mh->af.encoding;
1137c2c66affSColin Finck if(clear_flag) mh->new_format = 0;
1138c2c66affSColin Finck return MPG123_OK;
1139c2c66affSColin Finck }
1140c2c66affSColin Finck
mpg123_getformat(mpg123_handle * mh,long * rate,int * channels,int * encoding)1141c2c66affSColin Finck int attribute_align_arg mpg123_getformat(mpg123_handle *mh, long *rate, int *channels, int *encoding)
1142c2c66affSColin Finck {
1143c2c66affSColin Finck return mpg123_getformat2(mh, rate, channels, encoding, 1);
1144c2c66affSColin Finck }
1145c2c66affSColin Finck
mpg123_timeframe(mpg123_handle * mh,double seconds)1146c2c66affSColin Finck off_t attribute_align_arg mpg123_timeframe(mpg123_handle *mh, double seconds)
1147c2c66affSColin Finck {
1148c2c66affSColin Finck off_t b;
1149c2c66affSColin Finck
1150c2c66affSColin Finck if(mh == NULL) return MPG123_ERR;
1151c2c66affSColin Finck b = init_track(mh);
1152c2c66affSColin Finck if(b<0) return b;
1153c2c66affSColin Finck return (off_t)(seconds/mpg123_tpf(mh));
1154c2c66affSColin Finck }
1155c2c66affSColin Finck
1156c2c66affSColin Finck /*
1157c2c66affSColin Finck Now, where are we? We need to know the last decoded frame... and what's left of it in buffer.
1158c2c66affSColin Finck The current frame number can mean the last decoded frame or the to-be-decoded frame.
1159c2c66affSColin Finck If mh->to_decode, then mh->num frames have been decoded, the frame mh->num now coming next.
1160c2c66affSColin Finck If not, we have the possibility of mh->num+1 frames being decoded or nothing at all.
1161c2c66affSColin Finck Then, there is firstframe...when we didn't reach it yet, then the next data will come from there.
1162c2c66affSColin Finck mh->num starts with -1
1163c2c66affSColin Finck */
mpg123_tell(mpg123_handle * mh)1164c2c66affSColin Finck off_t attribute_align_arg mpg123_tell(mpg123_handle *mh)
1165c2c66affSColin Finck {
1166c2c66affSColin Finck if(mh == NULL) return MPG123_ERR;
1167c2c66affSColin Finck if(track_need_init(mh)) return 0;
1168c2c66affSColin Finck /* Now we have all the info at hand. */
1169c2c66affSColin Finck debug5("tell: %li/%i first %li buffer %lu; frame_outs=%li", (long)mh->num, mh->to_decode, (long)mh->firstframe, (unsigned long)mh->buffer.fill, (long)frame_outs(mh, mh->num));
1170c2c66affSColin Finck
1171c2c66affSColin Finck { /* Funny block to keep C89 happy. */
1172c2c66affSColin Finck off_t pos = 0;
1173c2c66affSColin Finck if((mh->num < mh->firstframe) || (mh->num == mh->firstframe && mh->to_decode))
1174c2c66affSColin Finck { /* We are at the beginning, expect output from firstframe on. */
1175c2c66affSColin Finck pos = frame_outs(mh, mh->firstframe);
1176c2c66affSColin Finck #ifdef GAPLESS
1177c2c66affSColin Finck pos += mh->firstoff;
1178c2c66affSColin Finck #endif
1179c2c66affSColin Finck }
1180c2c66affSColin Finck else if(mh->to_decode)
1181c2c66affSColin Finck { /* We start fresh with this frame. Buffer should be empty, but we make sure to count it in. */
1182c2c66affSColin Finck pos = frame_outs(mh, mh->num) - bytes_to_samples(mh, mh->buffer.fill);
1183c2c66affSColin Finck }
1184c2c66affSColin Finck else
1185c2c66affSColin Finck { /* We serve what we have in buffer and then the beginning of next frame... */
1186c2c66affSColin Finck pos = frame_outs(mh, mh->num+1) - bytes_to_samples(mh, mh->buffer.fill);
1187c2c66affSColin Finck }
1188c2c66affSColin Finck /* Substract padding and delay from the beginning. */
1189c2c66affSColin Finck pos = SAMPLE_ADJUST(mh,pos);
1190c2c66affSColin Finck /* Negative sample offsets are not right, less than nothing is still nothing. */
1191c2c66affSColin Finck return pos>0 ? pos : 0;
1192c2c66affSColin Finck }
1193c2c66affSColin Finck }
1194c2c66affSColin Finck
mpg123_tellframe(mpg123_handle * mh)1195c2c66affSColin Finck off_t attribute_align_arg mpg123_tellframe(mpg123_handle *mh)
1196c2c66affSColin Finck {
1197c2c66affSColin Finck if(mh == NULL) return MPG123_ERR;
1198c2c66affSColin Finck if(mh->num < mh->firstframe) return mh->firstframe;
1199c2c66affSColin Finck if(mh->to_decode) return mh->num;
1200c2c66affSColin Finck /* Consider firstoff? */
1201c2c66affSColin Finck return mh->buffer.fill ? mh->num : mh->num + 1;
1202c2c66affSColin Finck }
1203c2c66affSColin Finck
mpg123_tell_stream(mpg123_handle * mh)1204c2c66affSColin Finck off_t attribute_align_arg mpg123_tell_stream(mpg123_handle *mh)
1205c2c66affSColin Finck {
1206c2c66affSColin Finck if(mh == NULL) return MPG123_ERR;
1207c2c66affSColin Finck /* mh->rd is at least a bad_reader, so no worry. */
1208c2c66affSColin Finck return mh->rd->tell(mh);
1209c2c66affSColin Finck }
1210c2c66affSColin Finck
do_the_seek(mpg123_handle * mh)1211c2c66affSColin Finck static int do_the_seek(mpg123_handle *mh)
1212c2c66affSColin Finck {
1213c2c66affSColin Finck int b;
1214c2c66affSColin Finck off_t fnum = SEEKFRAME(mh);
1215c2c66affSColin Finck mh->buffer.fill = 0;
1216c2c66affSColin Finck
1217c2c66affSColin Finck /* If we are inside the ignoreframe - firstframe window, we may get away without actual seeking. */
1218c2c66affSColin Finck if(mh->num < mh->firstframe)
1219c2c66affSColin Finck {
1220c2c66affSColin Finck mh->to_decode = FALSE; /* In any case, don't decode the current frame, perhaps ignore instead. */
1221c2c66affSColin Finck if(mh->num > fnum) return MPG123_OK;
1222c2c66affSColin Finck }
1223c2c66affSColin Finck
1224c2c66affSColin Finck /* If we are already there, we are fine either for decoding or for ignoring. */
1225c2c66affSColin Finck if(mh->num == fnum && (mh->to_decode || fnum < mh->firstframe)) return MPG123_OK;
1226c2c66affSColin Finck /* We have the frame before... just go ahead as normal. */
1227c2c66affSColin Finck if(mh->num == fnum-1)
1228c2c66affSColin Finck {
1229c2c66affSColin Finck mh->to_decode = FALSE;
1230c2c66affSColin Finck return MPG123_OK;
1231c2c66affSColin Finck }
1232c2c66affSColin Finck
1233c2c66affSColin Finck /* OK, real seeking follows... clear buffers and go for it. */
1234c2c66affSColin Finck frame_buffers_reset(mh);
1235c2c66affSColin Finck #ifndef NO_NTOM
1236c2c66affSColin Finck if(mh->down_sample == 3)
1237c2c66affSColin Finck {
1238c2c66affSColin Finck ntom_set_ntom(mh, fnum);
1239c2c66affSColin Finck debug3("fixed ntom for frame %"OFF_P" to %lu, num=%"OFF_P, (off_p)fnum, mh->ntom_val[0], (off_p)mh->num);
1240c2c66affSColin Finck }
1241c2c66affSColin Finck #endif
1242c2c66affSColin Finck b = mh->rd->seek_frame(mh, fnum);
1243c2c66affSColin Finck if(mh->header_change > 1)
1244c2c66affSColin Finck {
1245c2c66affSColin Finck if(decode_update(mh) < 0) return MPG123_ERR;
1246c2c66affSColin Finck mh->header_change = 0;
1247c2c66affSColin Finck }
1248c2c66affSColin Finck debug1("seek_frame returned: %i", b);
1249c2c66affSColin Finck if(b<0) return b;
1250c2c66affSColin Finck /* Only mh->to_ignore is TRUE. */
1251c2c66affSColin Finck if(mh->num < mh->firstframe) mh->to_decode = FALSE;
1252c2c66affSColin Finck
1253c2c66affSColin Finck mh->playnum = mh->num;
1254c2c66affSColin Finck return 0;
1255c2c66affSColin Finck }
1256c2c66affSColin Finck
mpg123_seek(mpg123_handle * mh,off_t sampleoff,int whence)1257c2c66affSColin Finck off_t attribute_align_arg mpg123_seek(mpg123_handle *mh, off_t sampleoff, int whence)
1258c2c66affSColin Finck {
1259c2c66affSColin Finck int b;
1260c2c66affSColin Finck off_t pos;
1261c2c66affSColin Finck
1262c2c66affSColin Finck pos = mpg123_tell(mh); /* adjusted samples */
1263c2c66affSColin Finck /* pos < 0 also can mean that simply a former seek failed at the lower levels.
1264c2c66affSColin Finck In that case, we only allow absolute seeks. */
1265c2c66affSColin Finck if(pos < 0 && whence != SEEK_SET)
1266c2c66affSColin Finck { /* Unless we got the obvious error of NULL handle, this is a special seek failure. */
1267c2c66affSColin Finck if(mh != NULL) mh->err = MPG123_NO_RELSEEK;
1268c2c66affSColin Finck return MPG123_ERR;
1269c2c66affSColin Finck }
1270c2c66affSColin Finck if((b=init_track(mh)) < 0) return b;
1271c2c66affSColin Finck switch(whence)
1272c2c66affSColin Finck {
1273c2c66affSColin Finck case SEEK_CUR: pos += sampleoff; break;
1274c2c66affSColin Finck case SEEK_SET: pos = sampleoff; break;
1275c2c66affSColin Finck case SEEK_END:
1276c2c66affSColin Finck /* When we do not know the end already, we can try to find it. */
1277c2c66affSColin Finck if(mh->track_frames < 1 && (mh->rdat.flags & READER_SEEKABLE))
1278c2c66affSColin Finck mpg123_scan(mh);
1279c2c66affSColin Finck if(mh->track_frames > 0) pos = SAMPLE_ADJUST(mh,frame_outs(mh, mh->track_frames)) - sampleoff;
1280c2c66affSColin Finck #ifdef GAPLESS
1281c2c66affSColin Finck else if(mh->end_os > 0) pos = SAMPLE_ADJUST(mh,mh->end_os) - sampleoff;
1282c2c66affSColin Finck #endif
1283c2c66affSColin Finck else
1284c2c66affSColin Finck {
1285c2c66affSColin Finck mh->err = MPG123_NO_SEEK_FROM_END;
1286c2c66affSColin Finck return MPG123_ERR;
1287c2c66affSColin Finck }
1288c2c66affSColin Finck break;
1289c2c66affSColin Finck default: mh->err = MPG123_BAD_WHENCE; return MPG123_ERR;
1290c2c66affSColin Finck }
1291c2c66affSColin Finck if(pos < 0) pos = 0;
1292c2c66affSColin Finck /* pos now holds the wanted sample offset in adjusted samples */
1293c2c66affSColin Finck frame_set_seek(mh, SAMPLE_UNADJUST(mh,pos));
1294c2c66affSColin Finck pos = do_the_seek(mh);
1295c2c66affSColin Finck if(pos < 0) return pos;
1296c2c66affSColin Finck
1297c2c66affSColin Finck return mpg123_tell(mh);
1298c2c66affSColin Finck }
1299c2c66affSColin Finck
1300c2c66affSColin Finck /*
1301c2c66affSColin Finck A bit more tricky... libmpg123 does not do the seeking itself.
1302c2c66affSColin Finck All it can do is to ignore frames until the wanted one is there.
1303c2c66affSColin Finck The caller doesn't know where a specific frame starts and mpg123 also only knows the general region after it scanned the file.
1304c2c66affSColin Finck Well, it is tricky...
1305c2c66affSColin Finck */
mpg123_feedseek(mpg123_handle * mh,off_t sampleoff,int whence,off_t * input_offset)1306c2c66affSColin Finck off_t attribute_align_arg mpg123_feedseek(mpg123_handle *mh, off_t sampleoff, int whence, off_t *input_offset)
1307c2c66affSColin Finck {
1308c2c66affSColin Finck int b;
1309c2c66affSColin Finck off_t pos;
1310c2c66affSColin Finck
1311c2c66affSColin Finck pos = mpg123_tell(mh); /* adjusted samples */
1312c2c66affSColin Finck debug3("seek from %li to %li (whence=%i)", (long)pos, (long)sampleoff, whence);
1313c2c66affSColin Finck /* The special seek error handling does not apply here... there is no lowlevel I/O. */
1314c2c66affSColin Finck if(pos < 0) return pos; /* mh == NULL is covered in mpg123_tell() */
1315c2c66affSColin Finck #ifndef NO_FEEDER
1316c2c66affSColin Finck if(input_offset == NULL)
1317c2c66affSColin Finck {
1318c2c66affSColin Finck mh->err = MPG123_NULL_POINTER;
1319c2c66affSColin Finck return MPG123_ERR;
1320c2c66affSColin Finck }
1321c2c66affSColin Finck
1322c2c66affSColin Finck if((b=init_track(mh)) < 0) return b; /* May need more to do anything at all. */
1323c2c66affSColin Finck
1324c2c66affSColin Finck switch(whence)
1325c2c66affSColin Finck {
1326c2c66affSColin Finck case SEEK_CUR: pos += sampleoff; break;
1327c2c66affSColin Finck case SEEK_SET: pos = sampleoff; break;
1328c2c66affSColin Finck case SEEK_END:
1329c2c66affSColin Finck if(mh->track_frames > 0) pos = SAMPLE_ADJUST(mh,frame_outs(mh, mh->track_frames)) - sampleoff;
1330c2c66affSColin Finck #ifdef GAPLESS
1331c2c66affSColin Finck else if(mh->end_os >= 0) pos = SAMPLE_ADJUST(mh,mh->end_os) - sampleoff;
1332c2c66affSColin Finck #endif
1333c2c66affSColin Finck else
1334c2c66affSColin Finck {
1335c2c66affSColin Finck mh->err = MPG123_NO_SEEK_FROM_END;
1336c2c66affSColin Finck return MPG123_ERR;
1337c2c66affSColin Finck }
1338c2c66affSColin Finck break;
1339c2c66affSColin Finck default: mh->err = MPG123_BAD_WHENCE; return MPG123_ERR;
1340c2c66affSColin Finck }
1341c2c66affSColin Finck if(pos < 0) pos = 0;
1342c2c66affSColin Finck frame_set_seek(mh, SAMPLE_UNADJUST(mh,pos));
1343c2c66affSColin Finck pos = SEEKFRAME(mh);
1344c2c66affSColin Finck mh->buffer.fill = 0;
1345c2c66affSColin Finck
1346c2c66affSColin Finck /* Shortcuts without modifying input stream. */
1347c2c66affSColin Finck *input_offset = mh->rdat.buffer.fileoff + mh->rdat.buffer.size;
1348c2c66affSColin Finck if(mh->num < mh->firstframe) mh->to_decode = FALSE;
1349c2c66affSColin Finck if(mh->num == pos && mh->to_decode) goto feedseekend;
1350c2c66affSColin Finck if(mh->num == pos-1) goto feedseekend;
1351c2c66affSColin Finck /* Whole way. */
1352c2c66affSColin Finck *input_offset = feed_set_pos(mh, frame_index_find(mh, SEEKFRAME(mh), &pos));
1353c2c66affSColin Finck mh->num = pos-1; /* The next read frame will have num = pos. */
1354c2c66affSColin Finck if(*input_offset < 0) return MPG123_ERR;
1355c2c66affSColin Finck
1356c2c66affSColin Finck feedseekend:
1357c2c66affSColin Finck return mpg123_tell(mh);
1358c2c66affSColin Finck #else
1359c2c66affSColin Finck mh->err = MPG123_MISSING_FEATURE;
1360c2c66affSColin Finck return MPG123_ERR;
1361c2c66affSColin Finck #endif
1362c2c66affSColin Finck }
1363c2c66affSColin Finck
mpg123_seek_frame(mpg123_handle * mh,off_t offset,int whence)1364c2c66affSColin Finck off_t attribute_align_arg mpg123_seek_frame(mpg123_handle *mh, off_t offset, int whence)
1365c2c66affSColin Finck {
1366c2c66affSColin Finck int b;
1367c2c66affSColin Finck off_t pos = 0;
1368c2c66affSColin Finck
1369c2c66affSColin Finck if(mh == NULL) return MPG123_ERR;
1370c2c66affSColin Finck if((b=init_track(mh)) < 0) return b;
1371c2c66affSColin Finck
1372c2c66affSColin Finck /* Could play games here with to_decode... */
1373c2c66affSColin Finck pos = mh->num;
1374c2c66affSColin Finck switch(whence)
1375c2c66affSColin Finck {
1376c2c66affSColin Finck case SEEK_CUR: pos += offset; break;
1377c2c66affSColin Finck case SEEK_SET: pos = offset; break;
1378c2c66affSColin Finck case SEEK_END:
1379c2c66affSColin Finck if(mh->track_frames > 0) pos = mh->track_frames - offset;
1380c2c66affSColin Finck else
1381c2c66affSColin Finck {
1382c2c66affSColin Finck mh->err = MPG123_NO_SEEK_FROM_END;
1383c2c66affSColin Finck return MPG123_ERR;
1384c2c66affSColin Finck }
1385c2c66affSColin Finck break;
1386c2c66affSColin Finck default:
1387c2c66affSColin Finck mh->err = MPG123_BAD_WHENCE;
1388c2c66affSColin Finck return MPG123_ERR;
1389c2c66affSColin Finck }
1390c2c66affSColin Finck if(pos < 0) pos = 0;
1391c2c66affSColin Finck /* Not limiting the possible position on end for the chance that there might be more to the stream than announced via track_frames. */
1392c2c66affSColin Finck
1393c2c66affSColin Finck frame_set_frameseek(mh, pos);
1394c2c66affSColin Finck pos = do_the_seek(mh);
1395c2c66affSColin Finck if(pos < 0) return pos;
1396c2c66affSColin Finck
1397c2c66affSColin Finck return mpg123_tellframe(mh);
1398c2c66affSColin Finck }
1399c2c66affSColin Finck
mpg123_set_filesize(mpg123_handle * mh,off_t size)1400c2c66affSColin Finck int attribute_align_arg mpg123_set_filesize(mpg123_handle *mh, off_t size)
1401c2c66affSColin Finck {
1402c2c66affSColin Finck if(mh == NULL) return MPG123_BAD_HANDLE;
1403c2c66affSColin Finck
1404c2c66affSColin Finck mh->rdat.filelen = size;
1405c2c66affSColin Finck return MPG123_OK;
1406c2c66affSColin Finck }
1407c2c66affSColin Finck
mpg123_framelength(mpg123_handle * mh)1408c2c66affSColin Finck off_t attribute_align_arg mpg123_framelength(mpg123_handle *mh)
1409c2c66affSColin Finck {
1410c2c66affSColin Finck int b;
1411c2c66affSColin Finck if(mh == NULL)
1412c2c66affSColin Finck return MPG123_ERR;
1413c2c66affSColin Finck b = init_track(mh);
1414c2c66affSColin Finck if(b<0)
1415c2c66affSColin Finck return b;
1416c2c66affSColin Finck if(mh->track_frames > 0)
1417c2c66affSColin Finck return mh->track_frames;
1418c2c66affSColin Finck if(mh->rdat.filelen > 0)
1419c2c66affSColin Finck { /* A bad estimate. Ignoring tags 'n stuff. */
1420c2c66affSColin Finck double bpf = mh->mean_framesize > 0.
1421c2c66affSColin Finck ? mh->mean_framesize
1422c2c66affSColin Finck : compute_bpf(mh);
1423c2c66affSColin Finck return (off_t)((double)(mh->rdat.filelen)/bpf+0.5);
1424c2c66affSColin Finck }
1425c2c66affSColin Finck /* Last resort: No view of the future, can at least count the frames that
1426c2c66affSColin Finck were already parsed. */
1427c2c66affSColin Finck if(mh->num > -1)
1428c2c66affSColin Finck return mh->num+1;
1429c2c66affSColin Finck /* Giving up. */
1430c2c66affSColin Finck return MPG123_ERR;
1431c2c66affSColin Finck }
1432c2c66affSColin Finck
mpg123_length(mpg123_handle * mh)1433c2c66affSColin Finck off_t attribute_align_arg mpg123_length(mpg123_handle *mh)
1434c2c66affSColin Finck {
1435c2c66affSColin Finck int b;
1436c2c66affSColin Finck off_t length;
1437c2c66affSColin Finck
1438c2c66affSColin Finck if(mh == NULL) return MPG123_ERR;
1439c2c66affSColin Finck b = init_track(mh);
1440c2c66affSColin Finck if(b<0) return b;
1441c2c66affSColin Finck if(mh->track_samples > -1) length = mh->track_samples;
1442c2c66affSColin Finck else if(mh->track_frames > 0) length = mh->track_frames*mh->spf;
1443c2c66affSColin Finck else if(mh->rdat.filelen > 0) /* Let the case of 0 length just fall through. */
1444c2c66affSColin Finck {
1445c2c66affSColin Finck /* A bad estimate. Ignoring tags 'n stuff. */
1446c2c66affSColin Finck double bpf = mh->mean_framesize ? mh->mean_framesize : compute_bpf(mh);
1447c2c66affSColin Finck length = (off_t)((double)(mh->rdat.filelen)/bpf*mh->spf);
1448c2c66affSColin Finck }
1449c2c66affSColin Finck else if(mh->rdat.filelen == 0) return mpg123_tell(mh); /* we could be in feeder mode */
1450c2c66affSColin Finck else return MPG123_ERR; /* No length info there! */
1451c2c66affSColin Finck
1452c2c66affSColin Finck debug1("mpg123_length: internal sample length: %"OFF_P, (off_p)length);
1453c2c66affSColin Finck
1454c2c66affSColin Finck length = frame_ins2outs(mh, length);
1455c2c66affSColin Finck debug1("mpg123_length: external sample length: %"OFF_P, (off_p)length);
1456c2c66affSColin Finck length = SAMPLE_ADJUST(mh,length);
1457c2c66affSColin Finck return length;
1458c2c66affSColin Finck }
1459c2c66affSColin Finck
1460c2c66affSColin Finck
mpg123_scan(mpg123_handle * mh)1461c2c66affSColin Finck int attribute_align_arg mpg123_scan(mpg123_handle *mh)
1462c2c66affSColin Finck {
1463c2c66affSColin Finck int b;
1464c2c66affSColin Finck off_t oldpos;
1465c2c66affSColin Finck off_t track_frames = 0;
1466c2c66affSColin Finck off_t track_samples = 0;
1467c2c66affSColin Finck
1468c2c66affSColin Finck if(mh == NULL) return MPG123_BAD_HANDLE;
1469c2c66affSColin Finck if(!(mh->rdat.flags & READER_SEEKABLE)){ mh->err = MPG123_NO_SEEK; return MPG123_ERR; }
1470c2c66affSColin Finck /* Scan through the _whole_ file, since the current position is no count but computed assuming constant samples per frame. */
1471c2c66affSColin Finck /* Also, we can just keep the current buffer and seek settings. Just operate on input frames here. */
1472c2c66affSColin Finck debug("issuing scan");
1473c2c66affSColin Finck b = init_track(mh); /* mh->num >= 0 !! */
1474c2c66affSColin Finck if(b<0)
1475c2c66affSColin Finck {
1476c2c66affSColin Finck if(b == MPG123_DONE) return MPG123_OK;
1477c2c66affSColin Finck else return MPG123_ERR; /* Must be error here, NEED_MORE is not for seekable streams. */
1478c2c66affSColin Finck }
1479c2c66affSColin Finck oldpos = mpg123_tell(mh);
1480c2c66affSColin Finck b = mh->rd->seek_frame(mh, 0);
1481c2c66affSColin Finck if(b<0 || mh->num != 0) return MPG123_ERR;
1482c2c66affSColin Finck /* One frame must be there now. */
1483c2c66affSColin Finck track_frames = 1;
1484c2c66affSColin Finck track_samples = mh->spf; /* Internal samples. */
1485c2c66affSColin Finck debug("TODO: We should disable gapless code when encountering inconsistent mh->spf!");
1486c2c66affSColin Finck debug(" ... at least unset MPG123_ACCURATE.");
1487c2c66affSColin Finck /* Do not increment mh->track_frames in the loop as tha would confuse Frankenstein detection. */
1488c2c66affSColin Finck while(read_frame(mh) == 1)
1489c2c66affSColin Finck {
1490c2c66affSColin Finck ++track_frames;
1491c2c66affSColin Finck track_samples += mh->spf;
1492c2c66affSColin Finck }
1493c2c66affSColin Finck mh->track_frames = track_frames;
1494c2c66affSColin Finck mh->track_samples = track_samples;
1495c2c66affSColin Finck debug2("Scanning yielded %"OFF_P" track samples, %"OFF_P" frames.", (off_p)mh->track_samples, (off_p)mh->track_frames);
1496c2c66affSColin Finck #ifdef GAPLESS
1497c2c66affSColin Finck /* Also, think about usefulness of that extra value track_samples ... it could be used for consistency checking. */
1498c2c66affSColin Finck if(mh->p.flags & MPG123_GAPLESS) frame_gapless_update(mh, mh->track_samples);
1499c2c66affSColin Finck #endif
1500c2c66affSColin Finck return mpg123_seek(mh, oldpos, SEEK_SET) >= 0 ? MPG123_OK : MPG123_ERR;
1501c2c66affSColin Finck }
1502c2c66affSColin Finck
mpg123_meta_check(mpg123_handle * mh)1503c2c66affSColin Finck int attribute_align_arg mpg123_meta_check(mpg123_handle *mh)
1504c2c66affSColin Finck {
1505c2c66affSColin Finck if(mh != NULL) return mh->metaflags;
1506c2c66affSColin Finck else return 0;
1507c2c66affSColin Finck }
1508c2c66affSColin Finck
mpg123_meta_free(mpg123_handle * mh)1509c2c66affSColin Finck void attribute_align_arg mpg123_meta_free(mpg123_handle *mh)
1510c2c66affSColin Finck {
1511c2c66affSColin Finck if(mh == NULL) return;
1512c2c66affSColin Finck
1513c2c66affSColin Finck reset_id3(mh);
1514c2c66affSColin Finck reset_icy(&mh->icy);
1515c2c66affSColin Finck }
1516c2c66affSColin Finck
mpg123_id3(mpg123_handle * mh,mpg123_id3v1 ** v1,mpg123_id3v2 ** v2)1517c2c66affSColin Finck int attribute_align_arg mpg123_id3(mpg123_handle *mh, mpg123_id3v1 **v1, mpg123_id3v2 **v2)
1518c2c66affSColin Finck {
1519c2c66affSColin Finck if(v1 != NULL) *v1 = NULL;
1520c2c66affSColin Finck if(v2 != NULL) *v2 = NULL;
1521c2c66affSColin Finck if(mh == NULL) return MPG123_BAD_HANDLE;
1522c2c66affSColin Finck
1523c2c66affSColin Finck if(mh->metaflags & MPG123_ID3)
1524c2c66affSColin Finck {
1525c2c66affSColin Finck id3_link(mh);
1526c2c66affSColin Finck if(v1 != NULL && mh->rdat.flags & READER_ID3TAG) *v1 = (mpg123_id3v1*) mh->id3buf;
1527c2c66affSColin Finck if(v2 != NULL)
1528c2c66affSColin Finck #ifdef NO_ID3V2
1529c2c66affSColin Finck *v2 = NULL;
1530c2c66affSColin Finck #else
1531c2c66affSColin Finck *v2 = &mh->id3v2;
1532c2c66affSColin Finck #endif
1533c2c66affSColin Finck
1534c2c66affSColin Finck mh->metaflags |= MPG123_ID3;
1535c2c66affSColin Finck mh->metaflags &= ~MPG123_NEW_ID3;
1536c2c66affSColin Finck }
1537c2c66affSColin Finck return MPG123_OK;
1538c2c66affSColin Finck }
1539c2c66affSColin Finck
mpg123_id3_raw(mpg123_handle * mh,unsigned char ** v1,size_t * v1_size,unsigned char ** v2,size_t * v2_size)1540*aa811c00SThomas Faber int attribute_align_arg mpg123_id3_raw( mpg123_handle *mh
1541*aa811c00SThomas Faber , unsigned char **v1, size_t *v1_size
1542*aa811c00SThomas Faber , unsigned char **v2, size_t *v2_size )
1543*aa811c00SThomas Faber {
1544*aa811c00SThomas Faber if(!mh)
1545*aa811c00SThomas Faber return MPG123_ERR;
1546*aa811c00SThomas Faber if(v1 != NULL)
1547*aa811c00SThomas Faber *v1 = mh->id3buf[0] ? mh->id3buf : NULL;
1548*aa811c00SThomas Faber if(v1_size != NULL)
1549*aa811c00SThomas Faber *v1_size = mh->id3buf[0] ? 128 : 0;
1550*aa811c00SThomas Faber if(v2 != NULL)
1551*aa811c00SThomas Faber *v2 = mh->id3v2_raw;
1552*aa811c00SThomas Faber if(v2_size != NULL)
1553*aa811c00SThomas Faber *v2_size = mh->id3v2_size;
1554*aa811c00SThomas Faber return MPG123_OK;
1555*aa811c00SThomas Faber }
1556*aa811c00SThomas Faber
mpg123_icy(mpg123_handle * mh,char ** icy_meta)1557c2c66affSColin Finck int attribute_align_arg mpg123_icy(mpg123_handle *mh, char **icy_meta)
1558c2c66affSColin Finck {
1559c2c66affSColin Finck if(mh == NULL) return MPG123_BAD_HANDLE;
1560c2c66affSColin Finck #ifndef NO_ICY
1561c2c66affSColin Finck if(icy_meta == NULL)
1562c2c66affSColin Finck {
1563c2c66affSColin Finck mh->err = MPG123_NULL_POINTER;
1564c2c66affSColin Finck return MPG123_ERR;
1565c2c66affSColin Finck }
1566c2c66affSColin Finck *icy_meta = NULL;
1567c2c66affSColin Finck
1568c2c66affSColin Finck if(mh->metaflags & MPG123_ICY)
1569c2c66affSColin Finck {
1570c2c66affSColin Finck *icy_meta = mh->icy.data;
1571c2c66affSColin Finck mh->metaflags |= MPG123_ICY;
1572c2c66affSColin Finck mh->metaflags &= ~MPG123_NEW_ICY;
1573c2c66affSColin Finck }
1574c2c66affSColin Finck return MPG123_OK;
1575c2c66affSColin Finck #else
1576c2c66affSColin Finck mh->err = MPG123_MISSING_FEATURE;
1577c2c66affSColin Finck return MPG123_ERR;
1578c2c66affSColin Finck #endif
1579c2c66affSColin Finck }
1580c2c66affSColin Finck
mpg123_icy2utf8(const char * icy_text)1581c2c66affSColin Finck char* attribute_align_arg mpg123_icy2utf8(const char* icy_text)
1582c2c66affSColin Finck {
1583c2c66affSColin Finck #ifndef NO_ICY
1584c2c66affSColin Finck return icy2utf8(icy_text, 0);
1585c2c66affSColin Finck #else
1586c2c66affSColin Finck return NULL;
1587c2c66affSColin Finck #endif
1588c2c66affSColin Finck }
1589c2c66affSColin Finck
1590c2c66affSColin Finck /* That one is always defined... it's not worth it to remove it for NO_ID3V2. */
mpg123_enc_from_id3(unsigned char id3_enc_byte)1591c2c66affSColin Finck enum mpg123_text_encoding attribute_align_arg mpg123_enc_from_id3(unsigned char id3_enc_byte)
1592c2c66affSColin Finck {
1593c2c66affSColin Finck switch(id3_enc_byte)
1594c2c66affSColin Finck {
1595c2c66affSColin Finck case mpg123_id3_latin1: return mpg123_text_latin1;
1596c2c66affSColin Finck case mpg123_id3_utf16bom: return mpg123_text_utf16bom; /* ID3v2.3 has UCS-2 with BOM here. */
1597c2c66affSColin Finck case mpg123_id3_utf16be: return mpg123_text_utf16be;
1598c2c66affSColin Finck case mpg123_id3_utf8: return mpg123_text_utf8;
1599c2c66affSColin Finck default: return mpg123_text_unknown;
1600c2c66affSColin Finck }
1601c2c66affSColin Finck }
1602c2c66affSColin Finck
1603c2c66affSColin Finck #ifndef NO_STRING
mpg123_store_utf8(mpg123_string * sb,enum mpg123_text_encoding enc,const unsigned char * source,size_t source_size)1604c2c66affSColin Finck int mpg123_store_utf8(mpg123_string *sb, enum mpg123_text_encoding enc, const unsigned char *source, size_t source_size)
1605c2c66affSColin Finck {
1606c2c66affSColin Finck switch(enc)
1607c2c66affSColin Finck {
1608c2c66affSColin Finck #ifndef NO_ID3V2
1609c2c66affSColin Finck /* The encodings we get from ID3v2 tags. */
1610c2c66affSColin Finck case mpg123_text_utf8:
1611c2c66affSColin Finck id3_to_utf8(sb, mpg123_id3_utf8, source, source_size, 0);
1612c2c66affSColin Finck break;
1613c2c66affSColin Finck case mpg123_text_latin1:
1614c2c66affSColin Finck id3_to_utf8(sb, mpg123_id3_latin1, source, source_size, 0);
1615c2c66affSColin Finck break;
1616c2c66affSColin Finck case mpg123_text_utf16bom:
1617c2c66affSColin Finck case mpg123_text_utf16:
1618c2c66affSColin Finck id3_to_utf8(sb, mpg123_id3_utf16bom, source, source_size, 0);
1619c2c66affSColin Finck break;
1620c2c66affSColin Finck /* Special because one cannot skip zero bytes here. */
1621c2c66affSColin Finck case mpg123_text_utf16be:
1622c2c66affSColin Finck id3_to_utf8(sb, mpg123_id3_utf16be, source, source_size, 0);
1623c2c66affSColin Finck break;
1624c2c66affSColin Finck #endif
1625c2c66affSColin Finck #ifndef NO_ICY
1626c2c66affSColin Finck /* ICY encoding... */
1627c2c66affSColin Finck case mpg123_text_icy:
1628c2c66affSColin Finck case mpg123_text_cp1252:
1629c2c66affSColin Finck {
1630c2c66affSColin Finck mpg123_free_string(sb);
1631c2c66affSColin Finck /* Paranoia: Make sure that the string ends inside the buffer... */
1632c2c66affSColin Finck if(source[source_size-1] == 0)
1633c2c66affSColin Finck {
1634c2c66affSColin Finck /* Convert from ICY encoding... with force applied or not. */
1635c2c66affSColin Finck char *tmpstring = icy2utf8((const char*)source, enc == mpg123_text_cp1252 ? 1 : 0);
1636c2c66affSColin Finck if(tmpstring != NULL)
1637c2c66affSColin Finck {
1638c2c66affSColin Finck mpg123_set_string(sb, tmpstring);
1639c2c66affSColin Finck free(tmpstring);
1640c2c66affSColin Finck }
1641c2c66affSColin Finck }
1642c2c66affSColin Finck }
1643c2c66affSColin Finck break;
1644c2c66affSColin Finck #endif
1645c2c66affSColin Finck default:
1646c2c66affSColin Finck mpg123_free_string(sb);
1647c2c66affSColin Finck }
1648c2c66affSColin Finck /* At least a trailing null of some form should be there... */
1649c2c66affSColin Finck return (sb->fill > 0) ? 1 : 0;
1650c2c66affSColin Finck }
1651c2c66affSColin Finck #endif
1652c2c66affSColin Finck
mpg123_index(mpg123_handle * mh,off_t ** offsets,off_t * step,size_t * fill)1653c2c66affSColin Finck int attribute_align_arg mpg123_index(mpg123_handle *mh, off_t **offsets, off_t *step, size_t *fill)
1654c2c66affSColin Finck {
1655c2c66affSColin Finck if(mh == NULL) return MPG123_BAD_HANDLE;
1656c2c66affSColin Finck if(offsets == NULL || step == NULL || fill == NULL)
1657c2c66affSColin Finck {
1658c2c66affSColin Finck mh->err = MPG123_BAD_INDEX_PAR;
1659c2c66affSColin Finck return MPG123_ERR;
1660c2c66affSColin Finck }
1661c2c66affSColin Finck #ifdef FRAME_INDEX
1662c2c66affSColin Finck *offsets = mh->index.data;
1663c2c66affSColin Finck *step = mh->index.step;
1664c2c66affSColin Finck *fill = mh->index.fill;
1665c2c66affSColin Finck #else
1666c2c66affSColin Finck *offsets = NULL;
1667c2c66affSColin Finck *step = 0;
1668c2c66affSColin Finck *fill = 0;
1669c2c66affSColin Finck #endif
1670c2c66affSColin Finck return MPG123_OK;
1671c2c66affSColin Finck }
1672c2c66affSColin Finck
mpg123_set_index(mpg123_handle * mh,off_t * offsets,off_t step,size_t fill)1673c2c66affSColin Finck int attribute_align_arg mpg123_set_index(mpg123_handle *mh, off_t *offsets, off_t step, size_t fill)
1674c2c66affSColin Finck {
1675c2c66affSColin Finck if(mh == NULL) return MPG123_BAD_HANDLE;
1676c2c66affSColin Finck #ifdef FRAME_INDEX
1677c2c66affSColin Finck if(step == 0)
1678c2c66affSColin Finck {
1679c2c66affSColin Finck mh->err = MPG123_BAD_INDEX_PAR;
1680c2c66affSColin Finck return MPG123_ERR;
1681c2c66affSColin Finck }
1682c2c66affSColin Finck if(fi_set(&mh->index, offsets, step, fill) == -1)
1683c2c66affSColin Finck {
1684c2c66affSColin Finck mh->err = MPG123_OUT_OF_MEM;
1685c2c66affSColin Finck return MPG123_ERR;
1686c2c66affSColin Finck }
1687c2c66affSColin Finck return MPG123_OK;
1688c2c66affSColin Finck #else
1689c2c66affSColin Finck mh->err = MPG123_MISSING_FEATURE;
1690c2c66affSColin Finck return MPG123_ERR;
1691c2c66affSColin Finck #endif
1692c2c66affSColin Finck }
1693c2c66affSColin Finck
mpg123_close(mpg123_handle * mh)1694c2c66affSColin Finck int attribute_align_arg mpg123_close(mpg123_handle *mh)
1695c2c66affSColin Finck {
1696c2c66affSColin Finck if(mh == NULL) return MPG123_BAD_HANDLE;
1697c2c66affSColin Finck
1698c2c66affSColin Finck /* mh->rd is never NULL! */
1699c2c66affSColin Finck if(mh->rd->close != NULL) mh->rd->close(mh);
1700c2c66affSColin Finck
1701c2c66affSColin Finck if(mh->new_format)
1702c2c66affSColin Finck {
1703c2c66affSColin Finck debug("Hey, we are closing a track before the new format has been queried...");
1704c2c66affSColin Finck invalidate_format(&mh->af);
1705c2c66affSColin Finck mh->new_format = 0;
1706c2c66affSColin Finck }
1707c2c66affSColin Finck /* Always reset the frame buffers on close, so we cannot forget it in funky opening routines (wrappers, even). */
1708c2c66affSColin Finck frame_reset(mh);
1709c2c66affSColin Finck return MPG123_OK;
1710c2c66affSColin Finck }
1711c2c66affSColin Finck
mpg123_delete(mpg123_handle * mh)1712c2c66affSColin Finck void attribute_align_arg mpg123_delete(mpg123_handle *mh)
1713c2c66affSColin Finck {
1714c2c66affSColin Finck if(mh != NULL)
1715c2c66affSColin Finck {
1716c2c66affSColin Finck mpg123_close(mh);
1717c2c66affSColin Finck frame_exit(mh); /* free buffers in frame */
1718c2c66affSColin Finck free(mh); /* free struct; cast? */
1719c2c66affSColin Finck }
1720c2c66affSColin Finck }
1721c2c66affSColin Finck
mpg123_free(void * ptr)1722*aa811c00SThomas Faber void attribute_align_arg mpg123_free(void *ptr)
1723*aa811c00SThomas Faber {
1724*aa811c00SThomas Faber free(ptr);
1725*aa811c00SThomas Faber }
1726*aa811c00SThomas Faber
1727c2c66affSColin Finck static const char *mpg123_error[] =
1728c2c66affSColin Finck {
1729c2c66affSColin Finck "No error... (code 0)",
1730c2c66affSColin Finck "Unable to set up output format! (code 1)",
1731c2c66affSColin Finck "Invalid channel number specified. (code 2)",
1732c2c66affSColin Finck "Invalid sample rate specified. (code 3)",
1733c2c66affSColin Finck "Unable to allocate memory for 16 to 8 converter table! (code 4)",
1734c2c66affSColin Finck "Bad parameter id! (code 5)",
1735c2c66affSColin Finck "Bad buffer given -- invalid pointer or too small size. (code 6)",
1736c2c66affSColin Finck "Out of memory -- some malloc() failed. (code 7)",
1737c2c66affSColin Finck "You didn't initialize the library! (code 8)",
1738c2c66affSColin Finck "Invalid decoder choice. (code 9)",
1739c2c66affSColin Finck "Invalid mpg123 handle. (code 10)",
1740c2c66affSColin Finck "Unable to initialize frame buffers (out of memory?)! (code 11)",
1741c2c66affSColin Finck "Invalid RVA mode. (code 12)",
1742c2c66affSColin Finck "This build doesn't support gapless decoding. (code 13)",
1743c2c66affSColin Finck "Not enough buffer space. (code 14)",
1744c2c66affSColin Finck "Incompatible numeric data types. (code 15)",
1745c2c66affSColin Finck "Bad equalizer band. (code 16)",
1746c2c66affSColin Finck "Null pointer given where valid storage address needed. (code 17)",
1747c2c66affSColin Finck "Error reading the stream. (code 18)",
1748c2c66affSColin Finck "Cannot seek from end (end is not known). (code 19)",
1749c2c66affSColin Finck "Invalid 'whence' for seek function. (code 20)",
1750c2c66affSColin Finck "Build does not support stream timeouts. (code 21)",
1751c2c66affSColin Finck "File access error. (code 22)",
1752c2c66affSColin Finck "Seek not supported by stream. (code 23)",
1753c2c66affSColin Finck "No stream opened. (code 24)",
1754c2c66affSColin Finck "Bad parameter handle. (code 25)",
1755c2c66affSColin Finck "Invalid parameter addresses for index retrieval. (code 26)",
1756c2c66affSColin Finck "Lost track in the bytestream and did not attempt resync. (code 27)",
1757c2c66affSColin Finck "Failed to find valid MPEG data within limit on resync. (code 28)",
1758c2c66affSColin Finck "No 8bit encoding possible. (code 29)",
1759c2c66affSColin Finck "Stack alignment is not good. (code 30)",
1760c2c66affSColin Finck "You gave me a NULL buffer? (code 31)",
1761c2c66affSColin Finck "File position is screwed up, please do an absolute seek (code 32)",
1762c2c66affSColin Finck "Inappropriate NULL-pointer provided.",
1763c2c66affSColin Finck "Bad key value given.",
1764c2c66affSColin Finck "There is no frame index (disabled in this build).",
1765c2c66affSColin Finck "Frame index operation failed.",
1766c2c66affSColin Finck "Decoder setup failed (invalid combination of settings?)",
1767c2c66affSColin Finck "Feature not in this build."
1768c2c66affSColin Finck ,"Some bad value has been provided."
1769c2c66affSColin Finck ,"Low-level seeking has failed (call to lseek(), usually)."
1770c2c66affSColin Finck ,"Custom I/O obviously not prepared."
1771c2c66affSColin Finck ,"Overflow in LFS (large file support) conversion."
1772c2c66affSColin Finck ,"Overflow in integer conversion."
1773c2c66affSColin Finck };
1774c2c66affSColin Finck
mpg123_plain_strerror(int errcode)1775c2c66affSColin Finck const char* attribute_align_arg mpg123_plain_strerror(int errcode)
1776c2c66affSColin Finck {
1777c2c66affSColin Finck if(errcode >= 0 && errcode < sizeof(mpg123_error)/sizeof(char*))
1778c2c66affSColin Finck return mpg123_error[errcode];
1779c2c66affSColin Finck else switch(errcode)
1780c2c66affSColin Finck {
1781c2c66affSColin Finck case MPG123_ERR:
1782c2c66affSColin Finck return "A generic mpg123 error.";
1783c2c66affSColin Finck case MPG123_DONE:
1784c2c66affSColin Finck return "Message: I am done with this track.";
1785c2c66affSColin Finck case MPG123_NEED_MORE:
1786c2c66affSColin Finck return "Message: Feed me more input data!";
1787c2c66affSColin Finck case MPG123_NEW_FORMAT:
1788c2c66affSColin Finck return "Message: Prepare for a changed audio format (query the new one)!";
1789c2c66affSColin Finck default:
1790c2c66affSColin Finck return "I have no idea - an unknown error code!";
1791c2c66affSColin Finck }
1792c2c66affSColin Finck }
1793c2c66affSColin Finck
mpg123_errcode(mpg123_handle * mh)1794c2c66affSColin Finck int attribute_align_arg mpg123_errcode(mpg123_handle *mh)
1795c2c66affSColin Finck {
1796c2c66affSColin Finck if(mh != NULL) return mh->err;
1797c2c66affSColin Finck return MPG123_BAD_HANDLE;
1798c2c66affSColin Finck }
1799c2c66affSColin Finck
mpg123_strerror(mpg123_handle * mh)1800c2c66affSColin Finck const char* attribute_align_arg mpg123_strerror(mpg123_handle *mh)
1801c2c66affSColin Finck {
1802c2c66affSColin Finck return mpg123_plain_strerror(mpg123_errcode(mh));
1803c2c66affSColin Finck }
1804