88c0fed26a57193be45dd51c5ac83b94450dfd15
1 /* TODO: Check all read calls (in loops, especially!) for return value 0 (EOF)! */
4 readers.c: reading input data
6 copyright ?-2008 by the mpg123 project - free software under the terms of the LGPL 2.1
7 see COPYING and AUTHORS files in distribution or http://mpg123.org
8 initially written by Michael Hipp
11 #include "mpg123lib_intern.h"
15 /* For select(), I need select.h according to POSIX 2001, else: sys/time.h sys/types.h unistd.h (the latter two included in compat.h already). */
16 #ifdef HAVE_SYS_SELECT_H
17 #include <sys/select.h>
19 #ifdef HAVE_SYS_TIME_H
29 static int default_init(mpg123_handle
*fr
);
30 static off_t
get_fileinfo(mpg123_handle
*);
31 static ssize_t
posix_read(int fd
, void *buf
, size_t count
){ return read(fd
, buf
, count
); }
32 static off_t
posix_lseek(int fd
, off_t offset
, int whence
){ return lseek(fd
, offset
, whence
); }
33 static off_t
nix_lseek(int fd
, off_t offset
, int whence
){ return -1; }
35 static ssize_t
plain_fullread(mpg123_handle
*fr
,unsigned char *buf
, ssize_t count
);
37 /* Wrapper to decide between descriptor-based and external handle-based I/O. */
38 static off_t
io_seek(struct reader_data
*rdat
, off_t offset
, int whence
);
39 static ssize_t
io_read(struct reader_data
*rdat
, void *buf
, size_t count
);
42 /* Bufferchain methods. */
43 static void bc_init(struct bufferchain
*bc
);
44 static void bc_reset(struct bufferchain
*bc
);
45 static int bc_append(struct bufferchain
*bc
, ssize_t size
);
47 static void bc_drop(struct bufferchain
*bc
);
49 static int bc_add(struct bufferchain
*bc
, const unsigned char *data
, ssize_t size
);
50 static ssize_t
bc_give(struct bufferchain
*bc
, unsigned char *out
, ssize_t size
);
51 static ssize_t
bc_skip(struct bufferchain
*bc
, ssize_t count
);
52 static ssize_t
bc_seekback(struct bufferchain
*bc
, ssize_t count
);
53 static void bc_forget(struct bufferchain
*bc
);
56 /* A normal read and a read with timeout. */
57 static ssize_t
plain_read(mpg123_handle
*fr
, void *buf
, size_t count
)
59 ssize_t ret
= io_read(&fr
->rdat
, buf
, count
);
60 if(VERBOSE3
) debug2("read %li bytes of %li", (long)ret
, (long)count
);
66 /* Wait for data becoming available, allowing soft-broken network connection to die
67 This is needed for Shoutcast servers that have forgotten about us while connection was temporarily down. */
68 static ssize_t
timeout_read(mpg123_handle
*fr
, void *buf
, size_t count
)
73 tv
.tv_sec
= fr
->rdat
.timeout_sec
;
76 FD_SET(fr
->rdat
.filept
, &fds
);
77 ret
= select(fr
->rdat
.filept
+1, &fds
, NULL
, NULL
, &tv
);
78 /* This works only with "my" read function. Not user-replaced. */
79 if(ret
> 0) ret
= read(fr
->rdat
.filept
, buf
, count
);
82 ret
=-1; /* no activity is the error */
83 if(NOQUIET
) error("stream timed out");
90 /* stream based operation with icy meta data*/
91 static ssize_t
icy_fullread(mpg123_handle
*fr
, unsigned char *buf
, ssize_t count
)
95 if(fr
->rdat
.flags
& READER_SEEKABLE
)
97 if(NOQUIET
) error("mpg123 programmer error: I don't do ICY on seekable streams.");
101 There used to be a check for expected file end here (length value or ID3 flag).
103 1. EOF is indicated by fdread returning zero bytes anyway.
104 2. We get false positives of EOF for either files that grew or
105 3. ... files that have ID3v1 tags in between (stream with intro).
110 /* all icy code is inside this if block, everything else is the plain fullread we know */
111 /* debug1("read: %li left", (long) count-cnt); */
112 if(fr
->icy
.next
< count
-cnt
)
114 unsigned char temp_buff
;
118 /* we are near icy-metaint boundary, read up to the boundary */
121 cut_pos
= fr
->icy
.next
;
122 ret
= fr
->rdat
.fdread(fr
,buf
+cnt
,cut_pos
);
125 if(ret
== 0) break; /* Just EOF. */
126 if(NOQUIET
) error("icy boundary read");
131 if(!(fr
->rdat
.flags
& READER_BUFFERED
)) fr
->rdat
.filepos
+= ret
;
136 debug1("another try... still %li left", (long)fr
->icy
.next
);
140 /* now off to read icy data */
142 /* one byte icy-meta size (must be multiplied by 16 to get icy-meta length) */
144 ret
= fr
->rdat
.fdread(fr
,&temp_buff
,1); /* Getting one single byte hast to suceed. */
145 if(ret
< 0){ if(NOQUIET
) error("reading icy size"); return READER_ERROR
; }
148 debug2("got meta-size byte: %u, at filepos %li", temp_buff
, (long)fr
->rdat
.filepos
);
149 if(!(fr
->rdat
.flags
& READER_BUFFERED
)) fr
->rdat
.filepos
+= ret
; /* 1... */
151 if((meta_size
= ((size_t) temp_buff
) * 16))
153 /* we have got some metadata */
155 /* TODO: Get rid of this malloc ... perhaps hooking into the reader buffer pool? */
156 meta_buff
= malloc(meta_size
+1);
157 if(meta_buff
!= NULL
)
159 ssize_t left
= meta_size
;
162 ret
= fr
->rdat
.fdread(fr
,meta_buff
+meta_size
-left
,left
);
163 /* 0 is error here, too... there _must_ be the ICY data, the server promised! */
164 if(ret
< 1){ if(NOQUIET
) error("reading icy-meta"); return READER_ERROR
; }
167 meta_buff
[meta_size
] = 0; /* string paranoia */
168 if(!(fr
->rdat
.flags
& READER_BUFFERED
)) fr
->rdat
.filepos
+= ret
;
170 if(fr
->icy
.data
) free(fr
->icy
.data
);
171 fr
->icy
.data
= meta_buff
;
172 fr
->metaflags
|= MPG123_NEW_ICY
;
173 debug2("icy-meta: %s size: %d bytes", fr
->icy
.data
, (int)meta_size
);
177 if(NOQUIET
) error1("cannot allocate memory for meta_buff (%lu bytes) ... trying to skip the metadata!", (unsigned long)meta_size
);
178 fr
->rd
->skip_bytes(fr
, meta_size
);
181 fr
->icy
.next
= fr
->icy
.interval
;
185 ret
= plain_fullread(fr
, buf
+cnt
, count
-cnt
);
186 if(ret
< 0){ if(NOQUIET
) error1("reading the rest of %li", (long)(count
-cnt
)); return READER_ERROR
; }
193 /* debug1("done reading, got %li", (long)cnt); */
197 #define icy_fullread NULL
200 /* stream based operation */
201 static ssize_t
plain_fullread(mpg123_handle
*fr
,unsigned char *buf
, ssize_t count
)
206 debug1("plain fullread of %"SSIZE_P
, (size_p
)count
);
209 There used to be a check for expected file end here (length value or ID3 flag).
211 1. EOF is indicated by fdread returning zero bytes anyway.
212 2. We get false positives of EOF for either files that grew or
213 3. ... files that have ID3v1 tags in between (stream with intro).
217 ret
= fr
->rdat
.fdread(fr
,buf
+cnt
,count
-cnt
);
218 if(ret
< 0) return READER_ERROR
;
220 if(!(fr
->rdat
.flags
& READER_BUFFERED
)) fr
->rdat
.filepos
+= ret
;
226 static off_t
stream_lseek(mpg123_handle
*fr
, off_t pos
, int whence
)
229 ret
= io_seek(&fr
->rdat
, pos
, whence
);
230 if (ret
>= 0) fr
->rdat
.filepos
= ret
;
233 fr
->err
= MPG123_LSEEK_FAILED
;
234 ret
= READER_ERROR
; /* not the original value */
239 static void stream_close(mpg123_handle
*fr
)
241 if(fr
->rdat
.flags
& READER_FD_OPENED
) compat_close(fr
->rdat
.filept
);
246 if(fr
->rdat
.flags
& READER_BUFFERED
) bc_reset(&fr
->rdat
.buffer
);
248 if(fr
->rdat
.flags
& READER_HANDLEIO
)
250 if(fr
->rdat
.cleanup_handle
!= NULL
) fr
->rdat
.cleanup_handle(fr
->rdat
.iohandle
);
252 fr
->rdat
.iohandle
= NULL
;
256 static int stream_seek_frame(mpg123_handle
*fr
, off_t newframe
)
258 debug2("seek_frame to %"OFF_P
" (from %"OFF_P
")", (off_p
)newframe
, (off_p
)fr
->num
);
259 /* Seekable streams can go backwards and jump forwards.
260 Non-seekable streams still can go forward, just not jump. */
261 if((fr
->rdat
.flags
& READER_SEEKABLE
) || (newframe
>= fr
->num
))
263 off_t preframe
; /* a leading frame we jump to */
264 off_t seek_to
; /* the byte offset we want to reach */
265 off_t to_skip
; /* bytes to skip to get there (can be negative) */
267 now seek to nearest leading index position and read from there until newframe is reached.
268 We use skip_bytes, which handles seekable and non-seekable streams
269 (the latter only for positive offset, which we ensured before entering here).
271 seek_to
= frame_index_find(fr
, newframe
, &preframe
);
272 /* No need to seek to index position if we are closer already.
273 But I am picky about fr->num == newframe, play safe by reading the frame again.
274 If you think that's stupid, don't call a seek to the current frame. */
275 if(fr
->num
>= newframe
|| fr
->num
< preframe
)
277 to_skip
= seek_to
- fr
->rd
->tell(fr
);
278 if(fr
->rd
->skip_bytes(fr
, to_skip
) != seek_to
)
281 debug2("going to %lu; just got %lu", (long unsigned)newframe
, (long unsigned)preframe
);
282 fr
->num
= preframe
-1; /* Watch out! I am going to read preframe... fr->num should indicate the frame before! */
284 while(fr
->num
< newframe
)
286 /* try to be non-fatal now... frameNum only gets advanced on success anyway */
287 if(!read_frame(fr
)) break;
289 /* Now the wanted frame should be ready for decoding. */
290 debug1("arrived at %lu", (long unsigned)fr
->num
);
296 fr
->err
= MPG123_NO_SEEK
;
297 return READER_ERROR
; /* invalid, no seek happened */
301 /* return FALSE on error, TRUE on success, READER_MORE on occasion */
302 static int generic_head_read(mpg123_handle
*fr
,unsigned long *newhead
)
304 unsigned char hbuf
[4];
305 int ret
= fr
->rd
->fullread(fr
,hbuf
,4);
306 if(ret
== READER_MORE
) return ret
;
307 if(ret
!= 4) return FALSE
;
309 *newhead
= ((unsigned long) hbuf
[0] << 24) |
310 ((unsigned long) hbuf
[1] << 16) |
311 ((unsigned long) hbuf
[2] << 8) |
312 (unsigned long) hbuf
[3];
317 /* return FALSE on error, TRUE on success, READER_MORE on occasion */
318 static int generic_head_shift(mpg123_handle
*fr
,unsigned long *head
)
321 int ret
= fr
->rd
->fullread(fr
,&hbuf
,1);
322 if(ret
== READER_MORE
) return ret
;
323 if(ret
!= 1) return FALSE
;
331 /* returns reached position... negative ones are bad... */
332 static off_t
stream_skip_bytes(mpg123_handle
*fr
,off_t len
)
334 if(fr
->rdat
.flags
& READER_SEEKABLE
)
336 off_t ret
= stream_lseek(fr
, len
, SEEK_CUR
);
337 return (ret
< 0) ? READER_ERROR
: ret
;
341 unsigned char buf
[1024]; /* ThOr: Compaq cxx complained and it makes sense to me... or should one do a cast? What for? */
345 ssize_t num
= len
< (off_t
)sizeof(buf
) ? (ssize_t
)len
: (ssize_t
)sizeof(buf
);
346 ret
= fr
->rd
->fullread(fr
, buf
, num
);
347 if (ret
< 0) return ret
;
348 else if(ret
== 0) break; /* EOF... an error? interface defined to tell the actual position... */
351 return fr
->rd
->tell(fr
);
354 else if(fr
->rdat
.flags
& READER_BUFFERED
)
355 { /* Perhaps we _can_ go a bit back. */
356 if(fr
->rdat
.buffer
.pos
>= -len
)
358 fr
->rdat
.buffer
.pos
+= len
;
359 return fr
->rd
->tell(fr
);
363 fr
->err
= MPG123_NO_SEEK
;
370 fr
->err
= MPG123_NO_SEEK
;
375 /* Return 0 on success... */
376 static int stream_back_bytes(mpg123_handle
*fr
, off_t bytes
)
378 off_t want
= fr
->rd
->tell(fr
)-bytes
;
379 if(want
< 0) return READER_ERROR
;
380 if(stream_skip_bytes(fr
,-bytes
) != want
) return READER_ERROR
;
386 /* returns size on success... */
387 static int generic_read_frame_body(mpg123_handle
*fr
,unsigned char *buf
, int size
)
391 if((l
=fr
->rd
->fullread(fr
,buf
,size
)) != size
)
400 static off_t
generic_tell(mpg123_handle
*fr
)
403 if(fr
->rdat
.flags
& READER_BUFFERED
)
404 fr
->rdat
.filepos
= fr
->rdat
.buffer
.fileoff
+fr
->rdat
.buffer
.pos
;
407 return fr
->rdat
.filepos
;
410 /* This does not (fully) work for non-seekable streams... You have to check for that flag, pal! */
411 static void stream_rewind(mpg123_handle
*fr
)
413 if(fr
->rdat
.flags
& READER_SEEKABLE
)
415 fr
->rdat
.filepos
= stream_lseek(fr
,0,SEEK_SET
);
417 fr
->rdat
.buffer
.fileoff
= fr
->rdat
.filepos
;
421 if(fr
->rdat
.flags
& READER_BUFFERED
)
423 fr
->rdat
.buffer
.pos
= 0;
424 fr
->rdat
.buffer
.firstpos
= 0;
425 fr
->rdat
.filepos
= fr
->rdat
.buffer
.fileoff
;
431 * returns length of a file (if filept points to a file)
432 * reads the last 128 bytes information into buffer
433 * ... that is not totally safe...
435 static off_t
get_fileinfo(mpg123_handle
*fr
)
439 if((len
=io_seek(&fr
->rdat
,0,SEEK_END
)) < 0) return -1;
441 if(io_seek(&fr
->rdat
,-128,SEEK_END
) < 0) return -1;
443 if(fr
->rd
->fullread(fr
,(unsigned char *)fr
->id3buf
,128) != 128) return -1;
445 if(!strncmp((char*)fr
->id3buf
,"TAG",3)) len
-= 128;
447 if(io_seek(&fr
->rdat
,0,SEEK_SET
) < 0) return -1;
449 if(len
<= 0) return -1;
455 /* Methods for the buffer chain, mainly used for feed reader, but not just that. */
458 static struct buffy
* buffy_new(size_t size
, size_t minsize
)
460 struct buffy
*newbuf
;
461 newbuf
= malloc(sizeof(struct buffy
));
462 if(newbuf
== NULL
) return NULL
;
464 newbuf
->realsize
= size
> minsize
? size
: minsize
;
465 newbuf
->data
= malloc(newbuf
->realsize
);
466 if(newbuf
->data
== NULL
)
476 static void buffy_del(struct buffy
* buf
)
485 /* Delete this buffy and all following buffies. */
486 static void buffy_del_chain(struct buffy
* buf
)
490 struct buffy
* next
= buf
->next
;
496 void bc_prepare(struct bufferchain
*bc
, size_t pool_size
, size_t bufblock
)
498 bc_poolsize(bc
, pool_size
, bufblock
);
501 bc_init(bc
); /* Ensure that members are zeroed for read-only use. */
504 size_t bc_fill(struct bufferchain
*bc
)
506 return (size_t)(bc
->size
- bc
->pos
);
509 void bc_poolsize(struct bufferchain
*bc
, size_t pool_size
, size_t bufblock
)
511 bc
->pool_size
= pool_size
;
512 bc
->bufblock
= bufblock
;
515 void bc_cleanup(struct bufferchain
*bc
)
517 buffy_del_chain(bc
->pool
);
522 /* Fetch a buffer from the pool (if possible) or create one. */
523 static struct buffy
* bc_alloc(struct bufferchain
*bc
, size_t size
)
525 /* Easy route: Just try the first available buffer.
526 Size does not matter, it's only a hint for creation of new buffers. */
529 struct buffy
*buf
= bc
->pool
;
530 bc
->pool
= buf
->next
;
531 buf
->next
= NULL
; /* That shall be set to a sensible value later. */
534 debug2("bc_alloc: picked %p from pool (fill now %"SIZE_P
")", (void*)buf
, (size_p
)bc
->pool_fill
);
537 else return buffy_new(size
, bc
->bufblock
);
540 /* Either stuff the buffer back into the pool or free it for good. */
541 static void bc_free(struct bufferchain
*bc
, struct buffy
* buf
)
545 if(bc
->pool_fill
< bc
->pool_size
)
547 buf
->next
= bc
->pool
;
554 /* Make the buffer count in the pool match the pool size. */
555 static int bc_fill_pool(struct bufferchain
*bc
)
557 /* Remove superfluous ones. */
558 while(bc
->pool_fill
> bc
->pool_size
)
560 /* Lazyness: Just work on the front. */
561 struct buffy
* buf
= bc
->pool
;
562 bc
->pool
= buf
->next
;
567 /* Add missing ones. */
568 while(bc
->pool_fill
< bc
->pool_size
)
570 /* Again, just work on the front. */
572 buf
= buffy_new(0, bc
->bufblock
); /* Use default block size. */
575 buf
->next
= bc
->pool
;
584 static void bc_init(struct bufferchain
*bc
)
587 bc
->last
= bc
->first
;
594 static void bc_reset(struct bufferchain
*bc
)
596 /* Free current chain, possibly stuffing back into the pool. */
599 struct buffy
* buf
= bc
->first
;
600 bc
->first
= buf
->next
;
603 bc_fill_pool(bc
); /* Ignoring an error here... */
607 /* Create a new buffy at the end to be filled. */
608 static int bc_append(struct bufferchain
*bc
, ssize_t size
)
610 struct buffy
*newbuf
;
611 if(size
< 1) return -1;
613 newbuf
= bc_alloc(bc
, size
);
614 if(newbuf
== NULL
) return -2;
616 if(bc
->last
!= NULL
) bc
->last
->next
= newbuf
;
617 else if(bc
->first
== NULL
) bc
->first
= newbuf
;
620 debug3("bc_append: new last buffer %p with %"SSIZE_P
" B (really %"SSIZE_P
")", (void*)bc
->last
, (ssize_p
)bc
->last
->size
, (ssize_p
)bc
->last
->realsize
);
624 /* Append a new buffer and copy content to it. */
625 static int bc_add(struct bufferchain
*bc
, const unsigned char *data
, ssize_t size
)
629 debug2("bc_add: adding %"SSIZE_P
" bytes at %"OFF_P
, (ssize_p
)size
, (off_p
)(bc
->fileoff
+bc
->size
));
630 if(size
>=4) debug4("first bytes: %02x %02x %02x %02x", data
[0], data
[1], data
[2], data
[3]);
634 /* Try to fill up the last buffer block. */
635 if(bc
->last
!= NULL
&& bc
->last
->size
< bc
->last
->realsize
)
637 part
= bc
->last
->realsize
- bc
->last
->size
;
638 if(part
> size
) part
= size
;
640 debug2("bc_add: adding %"SSIZE_P
" B to existing block %p", (ssize_p
)part
, (void*)bc
->last
);
641 memcpy(bc
->last
->data
+bc
->last
->size
, data
, part
);
642 bc
->last
->size
+= part
;
648 /* If there is still data left, put it into a new buffer block. */
649 if(size
> 0 && (ret
= bc_append(bc
, size
)) != 0)
656 /* Common handler for "You want more than I can give." situation. */
657 static ssize_t
bc_need_more(struct bufferchain
*bc
)
659 debug3("hit end, back to beginning (%li - %li < %li)", (long)bc
->size
, (long)bc
->pos
, (long)bc
->size
);
660 /* go back to firstpos, undo the previous reads */
661 bc
->pos
= bc
->firstpos
;
665 /* Give some data, advancing position but not forgetting yet. */
666 static ssize_t
bc_give(struct bufferchain
*bc
, unsigned char *out
, ssize_t size
)
668 struct buffy
*b
= bc
->first
;
669 ssize_t gotcount
= 0;
671 if(bc
->size
- bc
->pos
< size
) return bc_need_more(bc
);
673 /* find the current buffer */
674 while(b
!= NULL
&& (offset
+ b
->size
) <= bc
->pos
)
679 /* now start copying from there */
680 while(gotcount
< size
&& (b
!= NULL
))
682 ssize_t loff
= bc
->pos
- offset
;
683 ssize_t chunk
= size
- gotcount
; /* amount of bytes to get from here... */
684 if(chunk
> b
->size
- loff
) chunk
= b
->size
- loff
;
687 debug3("copying %liB from %p+%li",(long)chunk
, b
->data
, (long)loff
);
690 memcpy(out
+gotcount
, b
->data
+loff
, chunk
);
697 debug2("got %li bytes, pos advanced to %li", (long)gotcount
, (long)bc
->pos
);
703 /* Skip some bytes and return the new position.
704 The buffers are still there, just the read pointer is moved! */
705 static ssize_t
bc_skip(struct bufferchain
*bc
, ssize_t count
)
709 if(bc
->size
- bc
->pos
< count
) return bc_need_more(bc
);
710 else return bc
->pos
+= count
;
712 else return READER_ERROR
;
715 static ssize_t
bc_seekback(struct bufferchain
*bc
, ssize_t count
)
717 if(count
>= 0 && count
<= bc
->pos
) return bc
->pos
-= count
;
718 else return READER_ERROR
;
721 /* Throw away buffies that we passed. */
722 static void bc_forget(struct bufferchain
*bc
)
724 struct buffy
*b
= bc
->first
;
725 /* free all buffers that are def'n'tly outdated */
726 /* we have buffers until filepos... delete all buffers fully below it */
727 if(b
) debug2("bc_forget: block %lu pos %lu", (unsigned long)b
->size
, (unsigned long)bc
->pos
);
728 else debug("forget with nothing there!");
730 while(b
!= NULL
&& bc
->pos
>= b
->size
)
732 struct buffy
*n
= b
->next
; /* != NULL or this is indeed the end and the last cycle anyway */
733 if(n
== NULL
) bc
->last
= NULL
; /* Going to delete the last buffy... */
734 bc
->fileoff
+= b
->size
;
738 debug5("bc_forget: forgot %p with %lu, pos=%li, size=%li, fileoff=%li", (void*)b
->data
, (long)b
->size
, (long)bc
->pos
, (long)bc
->size
, (long)bc
->fileoff
);
744 bc
->firstpos
= bc
->pos
;
747 /* reader for input via manually provided buffers */
749 static int feed_init(mpg123_handle
*fr
)
751 bc_init(&fr
->rdat
.buffer
);
752 bc_fill_pool(&fr
->rdat
.buffer
);
753 fr
->rdat
.filelen
= 0;
754 fr
->rdat
.filepos
= 0;
755 fr
->rdat
.flags
|= READER_BUFFERED
;
759 /* externally called function, returns 0 on success, -1 on error */
760 int feed_more(mpg123_handle
*fr
, const unsigned char *in
, long count
)
763 if(VERBOSE3
) debug("feed_more");
764 if((ret
= bc_add(&fr
->rdat
.buffer
, in
, count
)) != 0)
767 if(NOQUIET
) error1("Failed to add buffer, return: %i", ret
);
769 else /* Not talking about filelen... that stays at 0. */
771 if(VERBOSE3
) debug3("feed_more: %p %luB bufsize=%lu", fr
->rdat
.buffer
.last
->data
,
772 (unsigned long)fr
->rdat
.buffer
.last
->size
, (unsigned long)fr
->rdat
.buffer
.size
);
776 static ssize_t
feed_read(mpg123_handle
*fr
, unsigned char *out
, ssize_t count
)
778 ssize_t gotcount
= bc_give(&fr
->rdat
.buffer
, out
, count
);
779 if(gotcount
>= 0 && gotcount
!= count
) return READER_ERROR
;
780 else return gotcount
;
783 /* returns reached position... negative ones are bad... */
784 static off_t
feed_skip_bytes(mpg123_handle
*fr
,off_t len
)
786 /* This is either the new buffer offset or some negative error value. */
787 off_t res
= bc_skip(&fr
->rdat
.buffer
, (ssize_t
)len
);
788 if(res
< 0) return res
;
790 return fr
->rdat
.buffer
.fileoff
+res
;
793 static int feed_back_bytes(mpg123_handle
*fr
, off_t bytes
)
796 return bc_seekback(&fr
->rdat
.buffer
, (ssize_t
)bytes
) >= 0 ? 0 : READER_ERROR
;
798 return feed_skip_bytes(fr
, -bytes
) >= 0 ? 0 : READER_ERROR
;
801 static int feed_seek_frame(mpg123_handle
*fr
, off_t num
){ return READER_ERROR
; }
803 /* Not just for feed reader, also for self-feeding buffered reader. */
804 static void buffered_forget(mpg123_handle
*fr
)
806 bc_forget(&fr
->rdat
.buffer
);
807 fr
->rdat
.filepos
= fr
->rdat
.buffer
.fileoff
+ fr
->rdat
.buffer
.pos
;
810 off_t
feed_set_pos(mpg123_handle
*fr
, off_t pos
)
812 struct bufferchain
*bc
= &fr
->rdat
.buffer
;
813 if(pos
>= bc
->fileoff
&& pos
-bc
->fileoff
< bc
->size
)
814 { /* We have the position! */
815 bc
->pos
= (ssize_t
)(pos
- bc
->fileoff
);
816 debug1("feed_set_pos inside, next feed from %"OFF_P
, (off_p
)(bc
->fileoff
+bc
->size
));
817 return bc
->fileoff
+bc
->size
; /* Next input after end of buffer... */
820 { /* I expect to get the specific position on next feed. Forget what I have now. */
823 debug1("feed_set_pos outside, buffer reset, next feed from %"OFF_P
, (off_p
)pos
);
824 return pos
; /* Next input from exactly that position. */
828 /* The specific stuff for buffered stream reader. */
830 static ssize_t
buffered_fullread(mpg123_handle
*fr
, unsigned char *out
, ssize_t count
)
832 struct bufferchain
*bc
= &fr
->rdat
.buffer
;
834 if(bc
->size
- bc
->pos
< count
)
835 { /* Add more stuff to buffer. If hitting end of file, adjust count. */
836 unsigned char readbuf
[4096];
837 ssize_t need
= count
- (bc
->size
-bc
->pos
);
841 ssize_t got
= fr
->rdat
.fullread(fr
, readbuf
, sizeof(readbuf
));
844 if(NOQUIET
) error("buffer reading");
848 if(VERBOSE3
) debug1("buffered_fullread: buffering %li bytes from stream (if > 0)", (long)got
);
849 if(got
> 0 && (ret
=bc_add(bc
, readbuf
, got
)) != 0)
851 if(NOQUIET
) error1("unable to add to chain, return: %i", ret
);
855 need
-= got
; /* May underflow here... */
856 if(got
< sizeof(readbuf
)) /* That naturally catches got == 0, too. */
858 if(VERBOSE3
) fprintf(stderr
, "Note: Input data end.\n");
862 if(bc
->size
- bc
->pos
< count
)
863 count
= bc
->size
- bc
->pos
; /* We want only what we got. */
865 gotcount
= bc_give(bc
, out
, count
);
867 if(VERBOSE3
) debug2("wanted %li, got %li", (long)count
, (long)gotcount
);
869 if(gotcount
!= count
){ if(NOQUIET
) error("gotcount != count"); return READER_ERROR
; }
870 else return gotcount
;
873 int feed_more(mpg123_handle
*fr
, const unsigned char *in
, long count
)
875 fr
->err
= MPG123_MISSING_FEATURE
;
878 off_t
feed_set_pos(mpg123_handle
*fr
, off_t pos
)
880 fr
->err
= MPG123_MISSING_FEATURE
;
883 #endif /* NO_FEEDER */
885 /*****************************************************************
889 #define bugger_off { mh->err = MPG123_NO_READER; return MPG123_ERR; }
890 static int bad_init(mpg123_handle
*mh
) bugger_off
891 static void bad_close(mpg123_handle
*mh
){}
892 static ssize_t
bad_fullread(mpg123_handle
*mh
, unsigned char *data
, ssize_t count
) bugger_off
893 static int bad_head_read(mpg123_handle
*mh
, unsigned long *newhead
) bugger_off
894 static int bad_head_shift(mpg123_handle
*mh
, unsigned long *head
) bugger_off
895 static off_t
bad_skip_bytes(mpg123_handle
*mh
, off_t len
) bugger_off
896 static int bad_read_frame_body(mpg123_handle
*mh
, unsigned char *data
, int size
) bugger_off
897 static int bad_back_bytes(mpg123_handle
*mh
, off_t bytes
) bugger_off
898 static int bad_seek_frame(mpg123_handle
*mh
, off_t num
) bugger_off
899 static off_t
bad_tell(mpg123_handle
*mh
) bugger_off
900 static void bad_rewind(mpg123_handle
*mh
){}
903 #define READER_STREAM 0
904 #define READER_ICY_STREAM 1
905 #define READER_FEED 2
906 #define READER_BUF_STREAM 3
907 #define READER_BUF_ICY_STREAM 4
908 static struct reader readers
[] =
910 { /* READER_STREAM */
917 generic_read_frame_body
,
924 { /* READER_ICY_STREAM */
931 generic_read_frame_body
,
939 #define feed_init NULL
940 #define feed_read NULL
941 #define buffered_fullread NULL
942 #define feed_seek_frame NULL
943 #define feed_back_bytes NULL
944 #define feed_skip_bytes NULL
945 #define buffered_forget NULL
954 generic_read_frame_body
,
961 { /* READER_BUF_STREAM */
968 generic_read_frame_body
,
975 { /* READER_BUF_ICY_STREAM */
982 generic_read_frame_body
,
992 NULL
, /* filled in by system_init() */
1007 static struct reader bad_reader
=
1015 bad_read_frame_body
,
1023 static int default_init(mpg123_handle
*fr
)
1026 if(fr
->p
.timeout
> 0)
1029 if(fr
->rdat
.r_read
!= NULL
)
1031 error("Timeout reading does not work with user-provided read function. Implement it yourself!");
1034 flags
= fcntl(fr
->rdat
.filept
, F_GETFL
);
1035 flags
|= O_NONBLOCK
;
1036 fcntl(fr
->rdat
.filept
, F_SETFL
, flags
);
1037 fr
->rdat
.fdread
= timeout_read
;
1038 fr
->rdat
.timeout_sec
= fr
->p
.timeout
;
1039 fr
->rdat
.flags
|= READER_NONBLOCK
;
1043 fr
->rdat
.fdread
= plain_read
;
1045 fr
->rdat
.read
= fr
->rdat
.r_read
!= NULL
? fr
->rdat
.r_read
: posix_read
;
1046 fr
->rdat
.lseek
= fr
->rdat
.r_lseek
!= NULL
? fr
->rdat
.r_lseek
: posix_lseek
;
1048 /* ICY streams of any sort shall not be seekable. */
1049 if(fr
->p
.icy_interval
> 0) fr
->rdat
.lseek
= nix_lseek
;
1052 fr
->rdat
.filelen
= get_fileinfo(fr
);
1053 fr
->rdat
.filepos
= 0;
1055 Don't enable seeking on ICY streams, just plain normal files.
1056 This check is necessary since the client can enforce ICY parsing on files that would otherwise be seekable.
1057 It is a task for the future to make the ICY parsing safe with seeks ... or not.
1059 if(fr
->rdat
.filelen
>= 0)
1061 fr
->rdat
.flags
|= READER_SEEKABLE
;
1062 if(!strncmp((char*)fr
->id3buf
,"TAG",3))
1064 fr
->rdat
.flags
|= READER_ID3TAG
;
1065 fr
->metaflags
|= MPG123_NEW_ID3
;
1068 /* Switch reader to a buffered one, if allowed. */
1069 else if(fr
->p
.flags
& MPG123_SEEKBUFFER
)
1072 error("Buffered readers not supported in this build.");
1073 fr
->err
= MPG123_MISSING_FEATURE
;
1076 if (fr
->rd
== &readers
[READER_STREAM
])
1078 fr
->rd
= &readers
[READER_BUF_STREAM
];
1079 fr
->rdat
.fullread
= plain_fullread
;
1082 else if(fr
->rd
== &readers
[READER_ICY_STREAM
])
1084 fr
->rd
= &readers
[READER_BUF_ICY_STREAM
];
1085 fr
->rdat
.fullread
= icy_fullread
;
1090 if(NOQUIET
) error("mpg123 Programmer's fault: invalid reader");
1093 bc_init(&fr
->rdat
.buffer
);
1094 fr
->rdat
.filelen
= 0; /* We carry the offset, but never know how big the stream is. */
1095 fr
->rdat
.flags
|= READER_BUFFERED
;
1096 #endif /* NO_FEEDER */
1102 void open_bad(mpg123_handle
*mh
)
1106 clear_icy(&mh
->icy
);
1108 mh
->rd
= &bad_reader
;
1111 bc_init(&mh
->rdat
.buffer
);
1113 mh
->rdat
.filelen
= -1;
1116 int open_feed(mpg123_handle
*fr
)
1118 debug("feed reader");
1120 error("Buffered readers not supported in this build.");
1121 fr
->err
= MPG123_MISSING_FEATURE
;
1125 if(fr
->p
.icy_interval
> 0)
1127 if(NOQUIET
) error("Feed reader cannot do ICY parsing!");
1131 clear_icy(&fr
->icy
);
1133 fr
->rd
= &readers
[READER_FEED
];
1135 if(fr
->rd
->init(fr
) < 0) return -1;
1137 debug("feed reader init successful");
1139 #endif /* NO_FEEDER */
1142 /* Final code common to open_stream and open_stream_handle. */
1143 static int open_finish(mpg123_handle
*fr
)
1146 if(fr
->p
.icy_interval
> 0)
1148 debug("ICY reader");
1149 fr
->icy
.interval
= fr
->p
.icy_interval
;
1150 fr
->icy
.next
= fr
->icy
.interval
;
1151 fr
->rd
= &readers
[READER_ICY_STREAM
];
1156 fr
->rd
= &readers
[READER_STREAM
];
1157 debug("stream reader");
1160 if(fr
->rd
->init(fr
) < 0) return -1;
1165 int open_stream(mpg123_handle
*fr
, const char *bs_filenam
, int fd
)
1167 int filept_opened
= 1;
1168 int filept
; /* descriptor of opened file/stream */
1170 clear_icy(&fr
->icy
); /* can be done inside frame_clear ...? */
1172 if(!bs_filenam
) /* no file to open, got a descriptor (stdin) */
1175 filept_opened
= 0; /* and don't try to close it... */
1178 #define O_BINARY (0)
1180 else if((filept
= compat_open(bs_filenam
, O_RDONLY
|O_BINARY
)) < 0) /* a plain old file to open... */
1182 if(NOQUIET
) error2("Cannot open file %s: %s", bs_filenam
, strerror(errno
));
1183 fr
->err
= MPG123_BAD_FILE
;
1184 return MPG123_ERR
; /* error... */
1187 /* now we have something behind filept and can init the reader */
1188 fr
->rdat
.filelen
= -1;
1189 fr
->rdat
.filept
= filept
;
1191 if(filept_opened
) fr
->rdat
.flags
|= READER_FD_OPENED
;
1193 return open_finish(fr
);
1196 int open_stream_handle(mpg123_handle
*fr
, void *iohandle
)
1198 clear_icy(&fr
->icy
); /* can be done inside frame_clear ...? */
1199 fr
->rdat
.filelen
= -1;
1200 fr
->rdat
.filept
= -1;
1201 fr
->rdat
.iohandle
= iohandle
;
1203 fr
->rdat
.flags
|= READER_HANDLEIO
;
1205 return open_finish(fr
);
1208 /* Wrappers for actual reading/seeking... I'm full of wrappers here. */
1209 static off_t
io_seek(struct reader_data
*rdat
, off_t offset
, int whence
)
1211 if(rdat
->flags
& READER_HANDLEIO
)
1213 if(rdat
->r_lseek_handle
!= NULL
)
1215 return rdat
->r_lseek_handle(rdat
->iohandle
, offset
, whence
);
1220 return rdat
->lseek(rdat
->filept
, offset
, whence
);
1223 static ssize_t
io_read(struct reader_data
*rdat
, void *buf
, size_t count
)
1225 if(rdat
->flags
& READER_HANDLEIO
)
1227 if(rdat
->r_read_handle
!= NULL
)
1229 return rdat
->r_read_handle(rdat
->iohandle
, buf
, count
);
1234 return rdat
->read(rdat
->filept
, buf
, count
);