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