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