Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/mpg123/src/libmpg123/readers.c
4394 views
1
/* TODO: Check all read calls (in loops, especially!) for return value 0 (EOF)! */
2
/* Check if get_fileinfo should read ID3 info or not, seems a bit out of place here. */
3
/* #define EXTRA_DEBUG */
4
/*
5
readers.c: reading input data
6
7
copyright ?-2023 by the mpg123 project - free software under the terms of the LGPL 2.1
8
see COPYING and AUTHORS files in distribution or http://mpg123.org
9
initially written by Michael Hipp
10
*/
11
12
#include "mpg123lib_intern.h"
13
14
#include "../common/debug.h"
15
16
static int stream_init(mpg123_handle *fr);
17
static int64_t get_fileinfo(mpg123_handle *);
18
19
static ptrdiff_t plain_fullread(mpg123_handle *fr,unsigned char *buf, ptrdiff_t count);
20
21
#ifndef NO_FEEDER
22
/* Bufferchain methods. */
23
static void bc_init(struct bufferchain *bc);
24
static void bc_reset(struct bufferchain *bc);
25
static int bc_append(struct bufferchain *bc, ptrdiff_t size);
26
#if 0
27
static void bc_drop(struct bufferchain *bc);
28
#endif
29
static int bc_add(struct bufferchain *bc, const unsigned char *data, ptrdiff_t size);
30
static ptrdiff_t bc_give(struct bufferchain *bc, unsigned char *out, ptrdiff_t size);
31
static ptrdiff_t bc_skip(struct bufferchain *bc, ptrdiff_t count);
32
static ptrdiff_t bc_seekback(struct bufferchain *bc, ptrdiff_t count);
33
static void bc_forget(struct bufferchain *bc);
34
#endif
35
36
// This is only for streams, so READER_HANDLEIO must be set.
37
static ptrdiff_t fdread(mpg123_handle *fr, void *buf, size_t count)
38
{
39
if((fr->rdat.flags & READER_HANDLEIO) && fr->rdat.r_read64)
40
{
41
size_t got = 0;
42
int ret = fr->rdat.r_read64(fr->rdat.iohandle, buf, count, &got);
43
if(ret<0)
44
{
45
if(NOQUIET) merror("error reading %zu bytes", count);
46
return -1;
47
}
48
if(VERBOSE3) mdebug("read %zu bytes of %zu", got, count);
49
// Stupid handling, but at least some handling of never-occuring case.
50
return (ptrdiff_t)(got > PTRDIFF_MAX ? PTRDIFF_MAX : got);
51
}
52
if(NOQUIET) error("no reader setup");
53
return -1;
54
}
55
56
static int64_t fdseek(mpg123_handle *fr, int64_t offset, int whence)
57
{
58
if((fr->rdat.flags & READER_HANDLEIO) && fr->rdat.r_lseek64)
59
return (fr->rdat.flags & READER_NOSEEK)
60
? -1
61
: fr->rdat.r_lseek64(fr->rdat.iohandle, offset, whence);
62
if(NOQUIET) error("no reader setup");
63
return -1;
64
}
65
66
#ifndef NO_ICY
67
/* stream based operation with icy meta data*/
68
static ptrdiff_t icy_fullread(mpg123_handle *fr, unsigned char *buf, ptrdiff_t count)
69
{
70
ptrdiff_t ret,cnt;
71
cnt = 0;
72
if(fr->rdat.flags & READER_SEEKABLE)
73
{
74
if(NOQUIET) error("mpg123 programmer error: I don't do ICY on seekable streams.");
75
return -1;
76
}
77
/*
78
There used to be a check for expected file end here (length value or ID3 flag).
79
This is not needed:
80
1. EOF is indicated by fdread returning zero bytes anyway.
81
2. We get false positives of EOF for either files that grew or
82
3. ... files that have ID3v1 tags in between (stream with intro).
83
*/
84
85
while(cnt < count)
86
{
87
/* all icy code is inside this if block, everything else is the plain fullread we know */
88
/* debug1("read: %li left", (long) count-cnt); */
89
if(fr->icy.next < count-cnt)
90
{
91
unsigned char temp_buff;
92
size_t meta_size;
93
ptrdiff_t cut_pos;
94
95
/* we are near icy-metaint boundary, read up to the boundary */
96
if(fr->icy.next > 0)
97
{
98
cut_pos = fr->icy.next;
99
ret = fdread(fr,buf+cnt,cut_pos);
100
if(ret < 1)
101
{
102
if(ret == 0) break; /* Just EOF. */
103
if(NOQUIET) error("icy boundary read");
104
105
return READER_ERROR;
106
}
107
108
if(!(fr->rdat.flags & READER_BUFFERED))
109
SATURATE_ADD(fr->rdat.filepos, ret, INT64_MAX);
110
cnt += ret;
111
fr->icy.next -= ret;
112
if(fr->icy.next > 0)
113
{
114
debug1("another try... still %li left", (long)fr->icy.next);
115
continue;
116
}
117
}
118
/* now off to read icy data */
119
120
/* one byte icy-meta size (must be multiplied by 16 to get icy-meta length) */
121
122
ret = fdread(fr,&temp_buff,1); /* Getting one single byte hast to suceed. */
123
if(ret < 0){ if(NOQUIET) error("reading icy size"); return READER_ERROR; }
124
if(ret == 0) break;
125
126
debug2("got meta-size byte: %u, at filepos %li", temp_buff, (long)fr->rdat.filepos );
127
if(!(fr->rdat.flags & READER_BUFFERED))
128
SATURATE_ADD(fr->rdat.filepos, ret, INT64_MAX); /* 1... */
129
130
if((meta_size = ((size_t) temp_buff) * 16))
131
{
132
/* we have got some metadata */
133
char *meta_buff;
134
/* TODO: Get rid of this malloc ... perhaps hooking into the reader buffer pool? */
135
meta_buff = malloc(meta_size+1);
136
if(meta_buff != NULL)
137
{
138
ptrdiff_t left = meta_size;
139
while(left > 0)
140
{
141
ret = fdread(fr,meta_buff+meta_size-left,left);
142
/* 0 is error here, too... there _must_ be the ICY data, the server promised! */
143
if(ret < 1){ if(NOQUIET) error("reading icy-meta"); return READER_ERROR; }
144
left -= ret;
145
}
146
meta_buff[meta_size] = 0; /* string paranoia */
147
if(!(fr->rdat.flags & READER_BUFFERED))
148
SATURATE_ADD(fr->rdat.filepos, ret, INT64_MAX);
149
150
if(fr->icy.data) free(fr->icy.data);
151
fr->icy.data = meta_buff;
152
fr->metaflags |= MPG123_NEW_ICY;
153
debug2("icy-meta: %s size: %d bytes", fr->icy.data, (int)meta_size);
154
}
155
else
156
{
157
if(NOQUIET) error1("cannot allocate memory for meta_buff (%lu bytes) ... trying to skip the metadata!", (unsigned long)meta_size);
158
fr->rd->skip_bytes(fr, meta_size);
159
}
160
}
161
fr->icy.next = fr->icy.interval;
162
}
163
else
164
{
165
ret = plain_fullread(fr, buf+cnt, count-cnt);
166
if(ret < 0){ if(NOQUIET) error1("reading the rest of %li", (long)(count-cnt)); return READER_ERROR; }
167
if(ret == 0) break;
168
169
cnt += ret;
170
fr->icy.next -= ret;
171
}
172
}
173
/* debug1("done reading, got %li", (long)cnt); */
174
return cnt;
175
}
176
#else
177
#define icy_fullread NULL
178
#endif /* NO_ICY */
179
180
/* stream based operation */
181
static ptrdiff_t plain_fullread(mpg123_handle *fr,unsigned char *buf, ptrdiff_t count)
182
{
183
ptrdiff_t ret,cnt=0;
184
185
#ifdef EXTRA_DEBUG
186
mdebug("plain fullread of %td", count);
187
#endif
188
/*
189
There used to be a check for expected file end here (length value or ID3 flag).
190
This is not needed:
191
1. EOF is indicated by fdread returning zero bytes anyway.
192
2. We get false positives of EOF for either files that grew or
193
3. ... files that have ID3v1 tags in between (stream with intro).
194
*/
195
while(cnt < count)
196
{
197
ret = fdread(fr,buf+cnt,count-cnt);
198
if(ret < 0) return READER_ERROR;
199
if(ret == 0) break;
200
if(!(fr->rdat.flags & READER_BUFFERED))
201
SATURATE_ADD(fr->rdat.filepos, ret, INT64_MAX);
202
cnt += ret;
203
}
204
return cnt;
205
}
206
207
static int64_t stream_lseek(mpg123_handle *fr, int64_t pos, int whence)
208
{
209
int64_t ret = fdseek(fr, pos, whence);
210
if (ret >= 0)
211
fr->rdat.filepos = ret;
212
else
213
{
214
fr->err = MPG123_LSEEK_FAILED;
215
ret = READER_ERROR; /* not the original value */
216
}
217
return ret;
218
}
219
220
static void stream_close(mpg123_handle *fr)
221
{
222
#ifndef NO_FEEDER
223
if(fr->rdat.flags & READER_BUFFERED) bc_reset(&fr->rdat.buffer);
224
#endif
225
if(fr->rdat.flags & READER_HANDLEIO)
226
{
227
if(fr->rdat.cleanup_handle != NULL)
228
fr->rdat.cleanup_handle(fr->rdat.iohandle);
229
230
fr->rdat.iohandle = NULL;
231
}
232
}
233
234
static int stream_seek_frame(mpg123_handle *fr, int64_t newframe)
235
{
236
debug2("seek_frame to %"PRIi64" (from %"PRIi64")", newframe, fr->num);
237
/* Seekable streams can go backwards and jump forwards.
238
Non-seekable streams still can go forward, just not jump. */
239
if((fr->rdat.flags & READER_SEEKABLE) || (newframe >= fr->num))
240
{
241
int64_t preframe; /* a leading frame we jump to */
242
int64_t seek_to; /* the byte offset we want to reach */
243
int64_t to_skip; /* bytes to skip to get there (can be negative) */
244
/*
245
now seek to nearest leading index position and read from there until newframe is reached.
246
We use skip_bytes, which handles seekable and non-seekable streams
247
(the latter only for positive offset, which we ensured before entering here).
248
*/
249
seek_to = INT123_frame_index_find(fr, newframe, &preframe);
250
/* No need to seek to index position if we are closer already.
251
But I am picky about fr->num == newframe, play safe by reading the frame again.
252
If you think that's stupid, don't call a seek to the current frame. */
253
if(fr->num >= newframe || fr->num < preframe)
254
{
255
to_skip = seek_to - fr->rd->tell(fr);
256
if(fr->rd->skip_bytes(fr, to_skip) != seek_to)
257
return READER_ERROR;
258
259
debug2("going to %lu; just got %lu", (long unsigned)newframe, (long unsigned)preframe);
260
fr->num = preframe-1; /* Watch out! I am going to read preframe... fr->num should indicate the frame before! */
261
}
262
while(fr->num < newframe)
263
{
264
/* try to be non-fatal now... frameNum only gets advanced on success anyway */
265
if(!INT123_read_frame(fr)) break;
266
}
267
/* Now the wanted frame should be ready for decoding. */
268
debug1("arrived at %"PRIi64, fr->num);
269
270
return MPG123_OK;
271
}
272
else
273
{
274
fr->err = MPG123_NO_SEEK;
275
return READER_ERROR; /* invalid, no seek happened */
276
}
277
}
278
279
/* return FALSE on error, TRUE on success, READER_MORE on occasion */
280
static int generic_head_read(mpg123_handle *fr,unsigned long *newhead)
281
{
282
unsigned char hbuf[4];
283
int ret = fr->rd->fullread(fr,hbuf,4);
284
if(ret == READER_MORE) return ret;
285
if(ret != 4) return FALSE;
286
287
*newhead = ((unsigned long) hbuf[0] << 24) |
288
((unsigned long) hbuf[1] << 16) |
289
((unsigned long) hbuf[2] << 8) |
290
(unsigned long) hbuf[3];
291
292
return TRUE;
293
}
294
295
/* return FALSE on error, TRUE on success, READER_MORE on occasion */
296
static int generic_head_shift(mpg123_handle *fr,unsigned long *head)
297
{
298
unsigned char hbuf;
299
int ret = fr->rd->fullread(fr,&hbuf,1);
300
if(ret == READER_MORE) return ret;
301
if(ret != 1) return FALSE;
302
303
*head <<= 8;
304
*head |= hbuf;
305
*head &= 0xffffffff;
306
return TRUE;
307
}
308
309
/* returns reached position... negative ones are bad... */
310
static int64_t stream_skip_bytes(mpg123_handle *fr, int64_t len)
311
{
312
if(fr->rdat.flags & READER_SEEKABLE)
313
{
314
int64_t ret = stream_lseek(fr, len, SEEK_CUR);
315
return (ret < 0) ? READER_ERROR : ret;
316
}
317
else if(len >= 0)
318
{
319
unsigned char buf[1024]; /* ThOr: Compaq cxx complained and it makes sense to me... or should one do a cast? What for? */
320
ptrdiff_t ret;
321
while (len > 0)
322
{
323
ptrdiff_t num = len < (ptrdiff_t)sizeof(buf) ? (ptrdiff_t)len : (ptrdiff_t)sizeof(buf);
324
ret = fr->rd->fullread(fr, buf, num);
325
if (ret < 0) return ret;
326
else if(ret == 0) break; /* EOF... an error? interface defined to tell the actual position... */
327
len -= ret;
328
}
329
return fr->rd->tell(fr);
330
}
331
#ifndef NO_FEEDER
332
else if(fr->rdat.flags & READER_BUFFERED)
333
{ /* Perhaps we _can_ go a bit back. */
334
if(fr->rdat.buffer.pos >= -len)
335
{
336
fr->rdat.buffer.pos += len;
337
return fr->rd->tell(fr);
338
}
339
else
340
{
341
fr->err = MPG123_NO_SEEK;
342
return READER_ERROR;
343
}
344
}
345
#endif
346
else
347
{
348
fr->err = MPG123_NO_SEEK;
349
return READER_ERROR;
350
}
351
}
352
353
/* Return 0 on success... */
354
static int stream_back_bytes(mpg123_handle *fr, int64_t bytes)
355
{
356
int64_t want = fr->rd->tell(fr)-bytes;
357
if(want < 0) return READER_ERROR;
358
if(stream_skip_bytes(fr,-bytes) != want) return READER_ERROR;
359
360
return 0;
361
}
362
363
364
/* returns size on success... otherwise an error code < 0 */
365
static int generic_read_frame_body(mpg123_handle *fr,unsigned char *buf, int size)
366
{
367
ptrdiff_t l;
368
l=fr->rd->fullread(fr,buf,size);
369
return (l >= 0 && l<size) ? READER_ERROR : (int)l;
370
}
371
372
static int64_t generic_tell(mpg123_handle *fr)
373
{
374
#ifndef NO_FEEDER
375
if(fr->rdat.flags & READER_BUFFERED)
376
{
377
fr->rdat.filepos = fr->rdat.buffer.fileoff;
378
SATURATE_ADD(fr->rdat.filepos, fr->rdat.buffer.pos, INT64_MAX);
379
}
380
#endif
381
382
return fr->rdat.filepos;
383
}
384
385
/* This does not (fully) work for non-seekable streams... You have to check for that flag, pal! */
386
static void stream_rewind(mpg123_handle *fr)
387
{
388
if(fr->rdat.flags & READER_SEEKABLE)
389
{
390
fr->rdat.filepos = stream_lseek(fr,0,SEEK_SET);
391
#ifndef NO_FEEDER
392
fr->rdat.buffer.fileoff = fr->rdat.filepos;
393
#endif
394
}
395
#ifndef NO_FEEDER
396
if(fr->rdat.flags & READER_BUFFERED)
397
{
398
fr->rdat.buffer.pos = 0;
399
fr->rdat.buffer.firstpos = 0;
400
fr->rdat.filepos = fr->rdat.buffer.fileoff;
401
}
402
#endif
403
}
404
405
/*
406
* returns length of a file (if filept points to a file)
407
* reads the last 128 bytes information into buffer
408
* ... that is not totally safe...
409
*/
410
static int64_t get_fileinfo(mpg123_handle *fr)
411
{
412
int64_t len;
413
414
if((len=fdseek(fr,0,SEEK_END)) < 0)
415
{
416
debug("cannot seek to end");
417
return -1;
418
} else if(len >= 128)
419
{
420
if(fdseek(fr,-128,SEEK_END) < 0)
421
{
422
debug("cannot seek to END-128");
423
return -1;
424
}
425
if(fr->rd->fullread(fr,(unsigned char *)fr->id3buf,128) != 128)
426
{
427
debug("cannot read ID3v1?!");
428
return -1;
429
}
430
if(!strncmp((char*)fr->id3buf,"TAG",3)) len -= 128;
431
} else
432
{
433
debug("stream too short for ID3");
434
}
435
436
if(fdseek(fr,0,SEEK_SET) < 0)
437
{
438
debug("cannot seek back");
439
return -1;
440
}
441
fr->rdat.filepos = 0; // un-do our seeking here
442
443
debug1("returning length: %"PRIi64, len);
444
return len;
445
}
446
447
#ifndef NO_FEEDER
448
/* Methods for the buffer chain, mainly used for feed reader, but not just that. */
449
450
451
static struct buffy* buffy_new(ptrdiff_t size, ptrdiff_t minsize)
452
{
453
struct buffy *newbuf;
454
if(size > PTRDIFF_MAX)
455
return NULL;
456
newbuf = malloc(sizeof(struct buffy));
457
if(newbuf == NULL) return NULL;
458
459
newbuf->realsize = size > minsize ? size : minsize;
460
newbuf->data = malloc((size_t)newbuf->realsize);
461
if(newbuf->data == NULL)
462
{
463
free(newbuf);
464
return NULL;
465
}
466
newbuf->size = 0;
467
newbuf->next = NULL;
468
return newbuf;
469
}
470
471
static void buffy_del(struct buffy* buf)
472
{
473
if(buf)
474
{
475
free(buf->data);
476
free(buf);
477
}
478
}
479
480
/* Delete this buffy and all following buffies. */
481
static void buffy_del_chain(struct buffy* buf)
482
{
483
while(buf)
484
{
485
struct buffy* next = buf->next;
486
buffy_del(buf);
487
buf = next;
488
}
489
}
490
491
void INT123_bc_prepare(struct bufferchain *bc, size_t pool_size, size_t bufblock)
492
{
493
INT123_bc_poolsize(bc, pool_size, bufblock);
494
bc->pool = NULL;
495
bc->pool_fill = 0;
496
bc_init(bc); /* Ensure that members are zeroed for read-only use. */
497
}
498
499
size_t INT123_bc_fill(struct bufferchain *bc)
500
{
501
return (size_t)(bc->size - bc->pos);
502
}
503
504
void INT123_bc_poolsize(struct bufferchain *bc, size_t pool_size, size_t bufblock)
505
{
506
bc->pool_size = pool_size;
507
bc->bufblock = bufblock;
508
}
509
510
void INT123_bc_cleanup(struct bufferchain *bc)
511
{
512
buffy_del_chain(bc->pool);
513
bc->pool = NULL;
514
bc->pool_fill = 0;
515
}
516
517
/* Fetch a buffer from the pool (if possible) or create one. */
518
static struct buffy* bc_alloc(struct bufferchain *bc, size_t size)
519
{
520
/* Easy route: Just try the first available buffer.
521
Size does not matter, it's only a hint for creation of new buffers. */
522
if(bc->pool)
523
{
524
struct buffy *buf = bc->pool;
525
bc->pool = buf->next;
526
buf->next = NULL; /* That shall be set to a sensible value later. */
527
buf->size = 0;
528
--bc->pool_fill;
529
debug2("bc_alloc: picked %p from pool (fill now %zu)", (void*)buf, bc->pool_fill);
530
return buf;
531
}
532
else return buffy_new(size, bc->bufblock);
533
}
534
535
/* Either stuff the buffer back into the pool or free it for good. */
536
static void bc_free(struct bufferchain *bc, struct buffy* buf)
537
{
538
if(!buf) return;
539
540
if(bc->pool_fill < bc->pool_size)
541
{
542
buf->next = bc->pool;
543
bc->pool = buf;
544
++bc->pool_fill;
545
}
546
else buffy_del(buf);
547
}
548
549
/* Make the buffer count in the pool match the pool size. */
550
static int bc_fill_pool(struct bufferchain *bc)
551
{
552
/* Remove superfluous ones. */
553
while(bc->pool_fill > bc->pool_size)
554
{
555
/* Lazyness: Just work on the front. */
556
struct buffy* buf = bc->pool;
557
bc->pool = buf->next;
558
buffy_del(buf);
559
--bc->pool_fill;
560
}
561
562
/* Add missing ones. */
563
while(bc->pool_fill < bc->pool_size)
564
{
565
/* Again, just work on the front. */
566
struct buffy* buf;
567
buf = buffy_new(0, bc->bufblock); /* Use default block size. */
568
if(!buf) return -1;
569
570
buf->next = bc->pool;
571
bc->pool = buf;
572
++bc->pool_fill;
573
}
574
575
return 0;
576
}
577
578
579
static void bc_init(struct bufferchain *bc)
580
{
581
bc->first = NULL;
582
bc->last = bc->first;
583
bc->size = 0;
584
bc->pos = 0;
585
bc->firstpos = 0;
586
bc->fileoff = 0;
587
}
588
589
static void bc_reset(struct bufferchain *bc)
590
{
591
/* Free current chain, possibly stuffing back into the pool. */
592
while(bc->first)
593
{
594
struct buffy* buf = bc->first;
595
bc->first = buf->next;
596
bc_free(bc, buf);
597
}
598
bc_fill_pool(bc); /* Ignoring an error here... */
599
bc_init(bc);
600
}
601
602
/* Create a new buffy at the end to be filled. */
603
static int bc_append(struct bufferchain *bc, ptrdiff_t size)
604
{
605
struct buffy *newbuf;
606
if(size < 1) return -1;
607
608
newbuf = bc_alloc(bc, size);
609
if(newbuf == NULL) return -2;
610
611
if(bc->last != NULL) bc->last->next = newbuf;
612
else if(bc->first == NULL) bc->first = newbuf;
613
614
bc->last = newbuf;
615
debug3("bc_append: new last buffer %p with %td B (really %td)", (void*)bc->last, bc->last->size, bc->last->realsize);
616
return 0;
617
}
618
619
/* Append a new buffer and copy content to it. */
620
static int bc_add(struct bufferchain *bc, const unsigned char *data, ptrdiff_t size)
621
{
622
int ret = 0;
623
ptrdiff_t part = 0;
624
if((size_t)(PTRDIFF_MAX - bc->size) < size)
625
return -1;
626
debug2("bc_add: adding %zu bytes at %"PRIi64, size, (int64_t)(bc->fileoff+bc->size));
627
if(size >=4) debug4("first bytes: %02x %02x %02x %02x", data[0], data[1], data[2], data[3]);
628
629
while(size > 0)
630
{
631
/* Try to fill up the last buffer block. */
632
if(bc->last != NULL && bc->last->size < bc->last->realsize)
633
{
634
part = bc->last->realsize - bc->last->size;
635
if(part > size) part = size;
636
637
debug2("bc_add: adding %td B to existing block %p", part, (void*)bc->last);
638
memcpy(bc->last->data+bc->last->size, data, part);
639
bc->last->size += part;
640
size -= part;
641
bc->size += part;
642
data += part;
643
}
644
645
/* If there is still data left, put it into a new buffer block. */
646
if(size > 0 && (ret = bc_append(bc, size)) != 0)
647
break;
648
}
649
650
return ret;
651
}
652
653
/* Common handler for "You want more than I can give." situation. */
654
static ptrdiff_t bc_need_more(struct bufferchain *bc, ptrdiff_t size)
655
{
656
debug3("hit end, back to beginning (%td - %td < %td)", bc->size, bc->pos, size);
657
/* go back to firstpos, undo the previous reads */
658
bc->pos = bc->firstpos;
659
return READER_MORE;
660
}
661
662
/* Give some data, advancing position but not forgetting yet. */
663
static ptrdiff_t bc_give(struct bufferchain *bc, unsigned char *out, ptrdiff_t size)
664
{
665
struct buffy *b = bc->first;
666
ptrdiff_t gotcount = 0;
667
ptrdiff_t offset = 0;
668
if(bc->size - bc->pos < size) return bc_need_more(bc, size);
669
670
/* find the current buffer */
671
while(b != NULL && (offset + b->size) <= bc->pos)
672
{
673
offset += b->size;
674
b = b->next;
675
}
676
/* now start copying from there */
677
while(gotcount < size && (b != NULL))
678
{
679
ptrdiff_t loff = bc->pos - offset;
680
ptrdiff_t chunk = size - gotcount; /* amount of bytes to get from here... */
681
if(chunk > b->size - loff) chunk = b->size - loff;
682
683
#ifdef EXTRA_DEBUG
684
debug3("copying %liB from %p+%li",(long)chunk, b->data, (long)loff);
685
#endif
686
687
memcpy(out+gotcount, b->data+loff, chunk);
688
gotcount += chunk;
689
bc->pos += chunk;
690
offset += b->size;
691
b = b->next;
692
}
693
#ifdef EXTRA_DEBUG
694
debug2("got %li bytes, pos advanced to %li", (long)gotcount, (long)bc->pos);
695
#endif
696
697
return gotcount;
698
}
699
700
/* Skip some bytes and return the new position.
701
The buffers are still there, just the read pointer is moved! */
702
static ptrdiff_t bc_skip(struct bufferchain *bc, ptrdiff_t count)
703
{
704
if(count >= 0)
705
{
706
if(bc->size - bc->pos < count) return bc_need_more(bc, count);
707
else return bc->pos += count;
708
}
709
else return READER_ERROR;
710
}
711
712
static ptrdiff_t bc_seekback(struct bufferchain *bc, ptrdiff_t count)
713
{
714
if(count >= 0 && count <= bc->pos) return bc->pos -= count;
715
else return READER_ERROR;
716
}
717
718
/* Throw away buffies that we passed. */
719
static void bc_forget(struct bufferchain *bc)
720
{
721
struct buffy *b = bc->first;
722
/* free all buffers that are def'n'tly outdated */
723
/* we have buffers until filepos... delete all buffers fully below it */
724
if(b) debug2("bc_forget: block %td pos %td", b->size, bc->pos);
725
else debug("forget with nothing there!");
726
727
while(b != NULL && bc->pos >= b->size)
728
{
729
struct buffy *n = b->next; /* != NULL or this is indeed the end and the last cycle anyway */
730
if(n == NULL) bc->last = NULL; /* Going to delete the last buffy... */
731
bc->fileoff += b->size;
732
bc->pos -= b->size;
733
bc->size -= b->size;
734
735
debug5("bc_forget: forgot %p with %td, pos=%td, size=%td, fileoff=%"PRIi64
736
, (void*)b->data, b->size, bc->pos, bc->size, bc->fileoff);
737
738
bc_free(bc, b);
739
b = n;
740
}
741
bc->first = b;
742
bc->firstpos = bc->pos;
743
}
744
745
/* reader for input via manually provided buffers */
746
747
static int feed_init(mpg123_handle *fr)
748
{
749
bc_init(&fr->rdat.buffer);
750
bc_fill_pool(&fr->rdat.buffer);
751
fr->rdat.filelen = 0;
752
fr->rdat.filepos = 0;
753
fr->rdat.flags |= READER_BUFFERED;
754
return 0;
755
}
756
757
/* externally called function, returns 0 on success, -1 on error */
758
// External API uses size_t, we use signed ptrdiff_t internally. Overflow
759
// is a theoretical possibility.
760
int INT123_feed_more(mpg123_handle *fr, const unsigned char *in, size_t count)
761
{
762
int ret = 0;
763
if(VERBOSE3) debug("INT123_feed_more");
764
if(count > PTRDIFF_MAX)
765
return READER_ERROR;
766
if((ret = bc_add(&fr->rdat.buffer, in, (ptrdiff_t)count)) != 0)
767
{
768
ret = READER_ERROR;
769
if(NOQUIET) error1("Failed to add buffer, return: %i", ret);
770
}
771
else /* Not talking about filelen... that stays at 0. */
772
773
if(VERBOSE3) debug3("INT123_feed_more: %p %luB bufsize=%lu", fr->rdat.buffer.last->data,
774
(unsigned long)fr->rdat.buffer.last->size, (unsigned long)fr->rdat.buffer.size);
775
return ret;
776
}
777
778
static ptrdiff_t feed_read(mpg123_handle *fr, unsigned char *out, ptrdiff_t count)
779
{
780
ptrdiff_t gotcount = bc_give(&fr->rdat.buffer, out, count);
781
if(gotcount >= 0 && gotcount != count) return READER_ERROR;
782
else return gotcount;
783
}
784
785
/* returns reached position... negative ones are bad... */
786
static int64_t feed_skip_bytes(mpg123_handle *fr, int64_t len)
787
{
788
/* This is either the new buffer offset or some negative error value. */
789
int64_t res = bc_skip(&fr->rdat.buffer, (ptrdiff_t)len);
790
if(res < 0) return res;
791
792
return fr->rdat.buffer.fileoff+res;
793
}
794
795
static int feed_back_bytes(mpg123_handle *fr, int64_t bytes)
796
{
797
if(bytes >=0)
798
return bc_seekback(&fr->rdat.buffer, (ptrdiff_t)bytes) >= 0 ? 0 : READER_ERROR;
799
else
800
return feed_skip_bytes(fr, -bytes) >= 0 ? 0 : READER_ERROR;
801
}
802
803
static int feed_seek_frame(mpg123_handle *fr, int64_t num){ return READER_ERROR; }
804
805
/* Not just for feed reader, also for self-feeding buffered reader. */
806
static void buffered_forget(mpg123_handle *fr)
807
{
808
bc_forget(&fr->rdat.buffer);
809
fr->rdat.filepos = fr->rdat.buffer.fileoff;
810
SATURATE_ADD(fr->rdat.filepos, fr->rdat.buffer.pos, INT64_MAX);
811
}
812
813
int64_t INT123_feed_set_pos(mpg123_handle *fr, int64_t pos)
814
{
815
struct bufferchain *bc = &fr->rdat.buffer;
816
if(pos >= bc->fileoff && pos-bc->fileoff < bc->size)
817
{ /* We have the position! */
818
bc->pos = (ptrdiff_t)(pos - bc->fileoff);
819
debug1("INT123_feed_set_pos inside, next feed from %"PRIi64, (int64_t)(bc->fileoff+bc->size));
820
return bc->fileoff+bc->size; /* Next input after end of buffer... */
821
}
822
else
823
{ /* I expect to get the specific position on next feed. Forget what I have now. */
824
bc_reset(bc);
825
bc->fileoff = pos;
826
debug1("INT123_feed_set_pos outside, buffer reset, next feed from %"PRIi64, pos);
827
return pos; /* Next input from exactly that position. */
828
}
829
}
830
831
/* The specific stuff for buffered stream reader. */
832
833
static ptrdiff_t buffered_fullread(mpg123_handle *fr, unsigned char *out, ptrdiff_t count
834
, ptrdiff_t (*fullread)(mpg123_handle *, unsigned char *, ptrdiff_t))
835
{
836
struct bufferchain *bc = &fr->rdat.buffer;
837
ptrdiff_t gotcount;
838
if(VERBOSE3)
839
mdebug("buffered_fullread: want %zd", count);
840
if(bc->size - bc->pos < count)
841
{ /* Add more stuff to buffer. If hitting end of file, adjust count. */
842
unsigned char readbuf[4096];
843
ptrdiff_t need = count - (bc->size-bc->pos);
844
while(need>0)
845
{
846
int ret;
847
ptrdiff_t got = fullread(fr, readbuf, sizeof(readbuf));
848
if(got < 0)
849
{
850
if(NOQUIET) error("buffer reading");
851
return READER_ERROR;
852
}
853
854
if(VERBOSE3)
855
debug1("buffered_fullread: buffering %td bytes from stream (if > 0)", got);
856
if(got > 0 && (ret=bc_add(bc, readbuf, got)) != 0)
857
{
858
if(NOQUIET) error1("unable to add to chain, return: %i", ret);
859
return READER_ERROR;
860
}
861
862
need -= got; /* May underflow here... */
863
if(got < sizeof(readbuf)) /* That naturally catches got == 0, too. */
864
{
865
if(VERBOSE3) fprintf(stderr, "Note: Input data end.\n");
866
break; /* End. */
867
}
868
}
869
if(bc->size - bc->pos < count)
870
count = bc->size - bc->pos; /* We want only what we got. */
871
}
872
gotcount = bc_give(bc, out, count);
873
if(VERBOSE3)
874
mdebug("buffered_fullread: got %td", gotcount);
875
if(gotcount != count){ if(NOQUIET) error("gotcount != count"); return READER_ERROR; }
876
else return gotcount;
877
}
878
879
static ptrdiff_t buffered_plain_fullread(mpg123_handle *fr, unsigned char *out, ptrdiff_t count)
880
{
881
return buffered_fullread(fr, out, count, plain_fullread);
882
}
883
884
static ptrdiff_t buffered_icy_fullread(mpg123_handle *fr, unsigned char *out, ptrdiff_t count)
885
{
886
return buffered_fullread(fr, out, count, icy_fullread);
887
}
888
889
#else
890
int INT123_feed_more(mpg123_handle *fr, const unsigned char *in, size_t count)
891
{
892
fr->err = MPG123_MISSING_FEATURE;
893
return -1;
894
}
895
int64_t INT123_feed_set_pos(mpg123_handle *fr, int64_t pos)
896
{
897
fr->err = MPG123_MISSING_FEATURE;
898
return -1;
899
}
900
#endif /* NO_FEEDER */
901
902
/*****************************************************************
903
* read frame helper
904
*/
905
906
#define bugger_off { mh->err = MPG123_NO_READER; return MPG123_ERR; }
907
static int bad_init(mpg123_handle *mh) bugger_off
908
static void bad_close(mpg123_handle *mh){}
909
static ptrdiff_t bad_fullread(mpg123_handle *mh, unsigned char *data, ptrdiff_t count) bugger_off
910
static int bad_head_read(mpg123_handle *mh, unsigned long *newhead) bugger_off
911
static int bad_head_shift(mpg123_handle *mh, unsigned long *head) bugger_off
912
static int64_t bad_skip_bytes(mpg123_handle *mh, int64_t len) bugger_off
913
static int bad_read_frame_body(mpg123_handle *mh, unsigned char *data, int size) bugger_off
914
static int bad_back_bytes(mpg123_handle *mh, int64_t bytes) bugger_off
915
static int bad_seek_frame(mpg123_handle *mh, int64_t num) bugger_off
916
static int64_t bad_tell(mpg123_handle *mh) bugger_off
917
static void bad_rewind(mpg123_handle *mh){}
918
#undef bugger_off
919
920
#define READER_STREAM 0
921
#define READER_ICY_STREAM 1
922
#define READER_FEED 2
923
#define READER_BUF_STREAM 3
924
#define READER_BUF_ICY_STREAM 4
925
static struct reader readers[] =
926
{
927
{ /* READER_STREAM */
928
stream_init,
929
stream_close,
930
plain_fullread,
931
generic_head_read,
932
generic_head_shift,
933
stream_skip_bytes,
934
generic_read_frame_body,
935
stream_back_bytes,
936
stream_seek_frame,
937
generic_tell,
938
stream_rewind,
939
NULL
940
} ,
941
{ /* READER_ICY_STREAM */
942
stream_init,
943
stream_close,
944
icy_fullread,
945
generic_head_read,
946
generic_head_shift,
947
stream_skip_bytes,
948
generic_read_frame_body,
949
stream_back_bytes,
950
stream_seek_frame,
951
generic_tell,
952
stream_rewind,
953
NULL
954
},
955
#ifdef NO_FEEDER
956
#define feed_init NULL
957
#define feed_read NULL
958
#define buffered_fullread NULL
959
#define buffered_plain_fullread NULL
960
#define buffered_icy_fullread NULL
961
#define feed_seek_frame NULL
962
#define feed_back_bytes NULL
963
#define feed_skip_bytes NULL
964
#define buffered_forget NULL
965
#endif
966
{ /* READER_FEED */
967
feed_init,
968
stream_close,
969
feed_read,
970
generic_head_read,
971
generic_head_shift,
972
feed_skip_bytes,
973
generic_read_frame_body,
974
feed_back_bytes,
975
feed_seek_frame,
976
generic_tell,
977
stream_rewind,
978
buffered_forget
979
},
980
{ /* READER_BUF_STREAM */
981
stream_init,
982
stream_close,
983
buffered_plain_fullread,
984
generic_head_read,
985
generic_head_shift,
986
stream_skip_bytes,
987
generic_read_frame_body,
988
stream_back_bytes,
989
stream_seek_frame,
990
generic_tell,
991
stream_rewind,
992
buffered_forget
993
} ,
994
{ /* READER_BUF_ICY_STREAM */
995
stream_init,
996
stream_close,
997
buffered_icy_fullread,
998
generic_head_read,
999
generic_head_shift,
1000
stream_skip_bytes,
1001
generic_read_frame_body,
1002
stream_back_bytes,
1003
stream_seek_frame,
1004
generic_tell,
1005
stream_rewind,
1006
buffered_forget
1007
},
1008
};
1009
1010
static struct reader bad_reader =
1011
{
1012
bad_init,
1013
bad_close,
1014
bad_fullread,
1015
bad_head_read,
1016
bad_head_shift,
1017
bad_skip_bytes,
1018
bad_read_frame_body,
1019
bad_back_bytes,
1020
bad_seek_frame,
1021
bad_tell,
1022
bad_rewind,
1023
NULL
1024
};
1025
1026
static int stream_init(mpg123_handle *fr)
1027
{
1028
#ifndef NO_ICY
1029
/* ICY streams of any sort shall not be seekable. */
1030
if(fr->p.icy_interval > 0) fr->rdat.flags |= READER_NOSEEK;
1031
#endif
1032
1033
fr->rdat.filepos = 0;
1034
fr->rdat.filelen = fr->p.flags & MPG123_NO_PEEK_END ? -1 : get_fileinfo(fr);
1035
if(fr->p.flags & MPG123_FORCE_SEEKABLE)
1036
{
1037
fr->rdat.flags |= READER_SEEKABLE;
1038
fr->rdat.flags &= ~READER_NOSEEK;
1039
}
1040
/*
1041
Don't enable seeking on ICY streams, just plain normal files.
1042
This check is necessary since the client can enforce ICY parsing on files that would otherwise be seekable.
1043
It is a task for the future to make the ICY parsing safe with seeks ... or not.
1044
*/
1045
if(fr->rdat.filelen >= 0)
1046
{
1047
debug("seekable stream");
1048
fr->rdat.flags |= READER_SEEKABLE;
1049
if(!strncmp((char*)fr->id3buf,"TAG",3))
1050
{
1051
fr->rdat.flags |= READER_ID3TAG;
1052
fr->metaflags |= MPG123_NEW_ID3;
1053
}
1054
}
1055
/* Switch reader to a buffered one, if allowed. */
1056
else if(fr->p.flags & MPG123_SEEKBUFFER)
1057
{
1058
#ifdef NO_FEEDER
1059
if(NOQUIET)
1060
error("Buffered readers not supported in this build.");
1061
fr->err = MPG123_MISSING_FEATURE;
1062
return -1;
1063
#else
1064
if (fr->rd == &readers[READER_STREAM])
1065
{
1066
debug("switching to buffered stream reader");
1067
fr->rd = &readers[READER_BUF_STREAM];
1068
}
1069
#ifndef NO_ICY
1070
else if(fr->rd == &readers[READER_ICY_STREAM])
1071
{
1072
debug("switching to buffered ICY stream reader");
1073
fr->rd = &readers[READER_BUF_ICY_STREAM];
1074
}
1075
#endif
1076
else
1077
{
1078
if(NOQUIET) error("mpg123 Programmer's fault: invalid reader");
1079
return -1;
1080
}
1081
bc_init(&fr->rdat.buffer);
1082
fr->rdat.filelen = 0; /* We carry the offset, but never know how big the stream is. */
1083
fr->rdat.flags |= READER_BUFFERED;
1084
#endif /* NO_ICY */
1085
}
1086
return 0;
1087
}
1088
1089
1090
void INT123_open_bad(mpg123_handle *mh)
1091
{
1092
debug("INT123_open_bad");
1093
#ifndef NO_ICY
1094
INT123_clear_icy(&mh->icy);
1095
#endif
1096
mh->rd = &bad_reader;
1097
mh->rdat.flags = 0;
1098
#ifndef NO_FEEDER
1099
bc_init(&mh->rdat.buffer);
1100
#endif
1101
mh->rdat.filelen = -1;
1102
}
1103
1104
int INT123_open_feed(mpg123_handle *fr)
1105
{
1106
debug("feed reader");
1107
#ifdef NO_FEEDER
1108
if(NOQUIET)
1109
error("Buffered readers not supported in this build.");
1110
fr->err = MPG123_MISSING_FEATURE;
1111
return -1;
1112
#else
1113
#ifndef NO_ICY
1114
if(fr->p.icy_interval > 0)
1115
{
1116
if(NOQUIET) error("Feed reader cannot do ICY parsing!");
1117
1118
return -1;
1119
}
1120
INT123_clear_icy(&fr->icy);
1121
#endif
1122
fr->rd = &readers[READER_FEED];
1123
fr->rdat.flags = 0;
1124
if(fr->rd->init(fr) < 0) return -1;
1125
1126
debug("feed reader init successful");
1127
return 0;
1128
#endif /* NO_FEEDER */
1129
}
1130
1131
/* Final code common to open_stream and INT123_open_stream_handle. */
1132
int INT123_open_stream_handle(mpg123_handle *fr, void *iohandle)
1133
{
1134
INT123_clear_icy(&fr->icy); /* can be done inside frame_clear ...? */
1135
fr->rdat.filelen = -1;
1136
fr->rdat.iohandle = iohandle;
1137
fr->rdat.flags = 0;
1138
fr->rdat.flags |= READER_HANDLEIO;
1139
1140
#ifndef NO_ICY
1141
if(fr->p.icy_interval > 0)
1142
{
1143
debug("ICY reader");
1144
fr->icy.interval = fr->p.icy_interval;
1145
fr->icy.next = fr->icy.interval;
1146
fr->rd = &readers[READER_ICY_STREAM];
1147
}
1148
else
1149
#endif
1150
{
1151
fr->rd = &readers[READER_STREAM];
1152
debug("stream reader");
1153
}
1154
1155
if(fr->rd->init(fr) < 0) return -1;
1156
1157
return MPG123_OK;
1158
}
1159
1160