Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 1905 → Rev 3960

/programs/develop/libraries/libmpg123/readers.c
12,8 → 12,7
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
/* For select(), I need select.h according to POSIX 2001, else: sys/time.h sys/types.h unistd.h */
/* Including these here although it works without on my Linux install... curious about _why_. */
/* 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). */
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
20,16 → 19,11
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef _MSC_VER
#include <io.h>
#endif
 
#include "compat.h"
#include "debug.h"
 
static int default_init(mpg123_handle *fr);
36,9 → 30,14
static off_t get_fileinfo(mpg123_handle *);
static ssize_t posix_read(int fd, void *buf, size_t count){ return read(fd, buf, count); }
static off_t posix_lseek(int fd, off_t offset, int whence){ return lseek(fd, offset, whence); }
static off_t nix_lseek(int fd, off_t offset, int whence){ return -1; }
 
static ssize_t plain_fullread(mpg123_handle *fr,unsigned char *buf, ssize_t count);
 
/* Wrapper to decide between descriptor-based and external handle-based I/O. */
static off_t io_seek(struct reader_data *rdat, off_t offset, int whence);
static ssize_t io_read(struct reader_data *rdat, void *buf, size_t count);
 
#ifndef NO_FEEDER
/* Bufferchain methods. */
static void bc_init(struct bufferchain *bc);
52,19 → 51,41
static ssize_t bc_skip(struct bufferchain *bc, ssize_t count);
static ssize_t bc_seekback(struct bufferchain *bc, ssize_t count);
static void bc_forget(struct bufferchain *bc);
#else
#define bc_init(a)
#define bc_reset(a)
#endif
 
/* A normal read and a read with timeout. */
static ssize_t plain_read(mpg123_handle *fr, void *buf, size_t count)
{
ssize_t ret = fr->rdat.read(fr->rdat.filept, buf, count);
ssize_t ret = io_read(&fr->rdat, buf, count);
if(VERBOSE3) debug2("read %li bytes of %li", (long)ret, (long)count);
return ret;
}
 
#ifdef TIMEOUT_READ
 
/* Wait for data becoming available, allowing soft-broken network connection to die
This is needed for Shoutcast servers that have forgotten about us while connection was temporarily down. */
static ssize_t timeout_read(mpg123_handle *fr, void *buf, size_t count)
{
struct timeval tv;
ssize_t ret = 0;
fd_set fds;
tv.tv_sec = fr->rdat.timeout_sec;
tv.tv_usec = 0;
FD_ZERO(&fds);
FD_SET(fr->rdat.filept, &fds);
ret = select(fr->rdat.filept+1, &fds, NULL, NULL, &tv);
/* This works only with "my" read function. Not user-replaced. */
if(ret > 0) ret = read(fr->rdat.filept, buf, count);
else
{
ret=-1; /* no activity is the error */
if(NOQUIET) error("stream timed out");
}
return ret;
}
#endif
 
#ifndef NO_ICY
/* stream based operation with icy meta data*/
static ssize_t icy_fullread(mpg123_handle *fr, unsigned char *buf, ssize_t count)
98,7 → 119,7
if(fr->icy.next > 0)
{
cut_pos = fr->icy.next;
ret = fr->rdat.fdread(fr,buf,cut_pos);
ret = fr->rdat.fdread(fr,buf+cnt,cut_pos);
if(ret < 1)
{
if(ret == 0) break; /* Just EOF. */
106,7 → 127,8
 
return READER_ERROR;
}
fr->rdat.filepos += ret;
 
if(!(fr->rdat.flags & READER_BUFFERED)) fr->rdat.filepos += ret;
cnt += ret;
fr->icy.next -= ret;
if(fr->icy.next > 0)
130,6 → 152,7
{
/* we have got some metadata */
char *meta_buff;
/* TODO: Get rid of this malloc ... perhaps hooking into the reader buffer pool? */
meta_buff = malloc(meta_size+1);
if(meta_buff != NULL)
{
157,7 → 180,8
}
fr->icy.next = fr->icy.interval;
}
 
else
{
ret = plain_fullread(fr, buf+cnt, count-cnt);
if(ret < 0){ if(NOQUIET) error1("reading the rest of %li", (long)(count-cnt)); return READER_ERROR; }
if(ret == 0) break;
165,6 → 189,7
cnt += ret;
fr->icy.next -= ret;
}
}
/* debug1("done reading, got %li", (long)cnt); */
return cnt;
}
177,6 → 202,9
{
ssize_t ret,cnt=0;
 
#ifdef EXTRA_DEBUG
debug1("plain fullread of %"SSIZE_P, (size_p)count);
#endif
/*
There used to be a check for expected file end here (length value or ID3 flag).
This is not needed:
198,7 → 226,7
static off_t stream_lseek(mpg123_handle *fr, off_t pos, int whence)
{
off_t ret;
ret = fr->rdat.lseek(fr->rdat.filept, pos, whence);
ret = io_seek(&fr->rdat, pos, whence);
if (ret >= 0) fr->rdat.filepos = ret;
else
{
210,9 → 238,20
 
static void stream_close(mpg123_handle *fr)
{
if(fr->rdat.flags & READER_FD_OPENED) close(fr->rdat.filept);
if(fr->rdat.flags & READER_FD_OPENED) compat_close(fr->rdat.filept);
 
fr->rdat.filept = 0;
 
#ifndef NO_FEEDER
if(fr->rdat.flags & READER_BUFFERED) bc_reset(&fr->rdat.buffer);
#endif
if(fr->rdat.flags & READER_HANDLEIO)
{
if(fr->rdat.cleanup_handle != NULL) fr->rdat.cleanup_handle(fr->rdat.iohandle);
 
fr->rdat.iohandle = NULL;
}
}
 
static int stream_seek_frame(mpg123_handle *fr, off_t newframe)
{
311,6 → 350,7
}
return fr->rd->tell(fr);
}
#ifndef NO_FEEDER
else if(fr->rdat.flags & READER_BUFFERED)
{ /* Perhaps we _can_ go a bit back. */
if(fr->rdat.buffer.pos >= -len)
324,6 → 364,7
return READER_ERROR;
}
}
#endif
else
{
fr->err = MPG123_NO_SEEK;
351,9 → 392,7
{
long ll = l;
if(ll <= 0) ll = 0;
 
/* This allows partial frames at the end... do we really want to pad and decode these?! */
memset(buf+ll,0,size-ll);
return READER_MORE;
}
return l;
}
360,8 → 399,10
 
static off_t generic_tell(mpg123_handle *fr)
{
#ifndef NO_FEEDER
if(fr->rdat.flags & READER_BUFFERED)
fr->rdat.filepos = fr->rdat.buffer.fileoff+fr->rdat.buffer.pos;
#endif
 
return fr->rdat.filepos;
}
370,7 → 411,13
static void stream_rewind(mpg123_handle *fr)
{
if(fr->rdat.flags & READER_SEEKABLE)
fr->rdat.buffer.fileoff = fr->rdat.filepos = stream_lseek(fr,0,SEEK_SET);
{
fr->rdat.filepos = stream_lseek(fr,0,SEEK_SET);
#ifndef NO_FEEDER
fr->rdat.buffer.fileoff = fr->rdat.filepos;
#endif
}
#ifndef NO_FEEDER
if(fr->rdat.flags & READER_BUFFERED)
{
fr->rdat.buffer.pos = 0;
377,6 → 424,7
fr->rdat.buffer.firstpos = 0;
fr->rdat.filepos = fr->rdat.buffer.fileoff;
}
#endif
}
 
/*
384,20 → 432,19
* reads the last 128 bytes information into buffer
* ... that is not totally safe...
*/
 
static off_t get_fileinfo(mpg123_handle *fr)
{
off_t len;
 
if((len=fr->rdat.lseek(fr->rdat.filept,0,SEEK_END)) < 0) return -1;
if((len=io_seek(&fr->rdat,0,SEEK_END)) < 0) return -1;
 
if(fr->rdat.lseek(fr->rdat.filept,-128,SEEK_END) < 0) return -1;
if(io_seek(&fr->rdat,-128,SEEK_END) < 0) return -1;
 
if(fr->rd->fullread(fr,(unsigned char *)fr->id3buf,128) != 128) return -1;
 
if(!strncmp((char*)fr->id3buf,"TAG",3)) len -= 128;
 
if(fr->rdat.lseek(fr->rdat.filept,0,SEEK_SET) < 0) return -1;
if(io_seek(&fr->rdat,0,SEEK_SET) < 0) return -1;
 
if(len <= 0) return -1;
 
407,6 → 454,133
#ifndef NO_FEEDER
/* Methods for the buffer chain, mainly used for feed reader, but not just that. */
 
 
static struct buffy* buffy_new(size_t size, size_t minsize)
{
struct buffy *newbuf;
newbuf = malloc(sizeof(struct buffy));
if(newbuf == NULL) return NULL;
 
newbuf->realsize = size > minsize ? size : minsize;
newbuf->data = malloc(newbuf->realsize);
if(newbuf->data == NULL)
{
free(newbuf);
return NULL;
}
newbuf->size = 0;
newbuf->next = NULL;
return newbuf;
}
 
static void buffy_del(struct buffy* buf)
{
if(buf)
{
free(buf->data);
free(buf);
}
}
 
/* Delete this buffy and all following buffies. */
static void buffy_del_chain(struct buffy* buf)
{
while(buf)
{
struct buffy* next = buf->next;
buffy_del(buf);
buf = next;
}
}
 
void bc_prepare(struct bufferchain *bc, size_t pool_size, size_t bufblock)
{
bc_poolsize(bc, pool_size, bufblock);
bc->pool = NULL;
bc->pool_fill = 0;
bc_init(bc); /* Ensure that members are zeroed for read-only use. */
}
 
size_t bc_fill(struct bufferchain *bc)
{
return (size_t)(bc->size - bc->pos);
}
 
void bc_poolsize(struct bufferchain *bc, size_t pool_size, size_t bufblock)
{
bc->pool_size = pool_size;
bc->bufblock = bufblock;
}
 
void bc_cleanup(struct bufferchain *bc)
{
buffy_del_chain(bc->pool);
bc->pool = NULL;
bc->pool_fill = 0;
}
 
/* Fetch a buffer from the pool (if possible) or create one. */
static struct buffy* bc_alloc(struct bufferchain *bc, size_t size)
{
/* Easy route: Just try the first available buffer.
Size does not matter, it's only a hint for creation of new buffers. */
if(bc->pool)
{
struct buffy *buf = bc->pool;
bc->pool = buf->next;
buf->next = NULL; /* That shall be set to a sensible value later. */
buf->size = 0;
--bc->pool_fill;
debug2("bc_alloc: picked %p from pool (fill now %"SIZE_P")", (void*)buf, (size_p)bc->pool_fill);
return buf;
}
else return buffy_new(size, bc->bufblock);
}
 
/* Either stuff the buffer back into the pool or free it for good. */
static void bc_free(struct bufferchain *bc, struct buffy* buf)
{
if(!buf) return;
 
if(bc->pool_fill < bc->pool_size)
{
buf->next = bc->pool;
bc->pool = buf;
++bc->pool_fill;
}
else buffy_del(buf);
}
 
/* Make the buffer count in the pool match the pool size. */
static int bc_fill_pool(struct bufferchain *bc)
{
/* Remove superfluous ones. */
while(bc->pool_fill > bc->pool_size)
{
/* Lazyness: Just work on the front. */
struct buffy* buf = bc->pool;
bc->pool = buf->next;
buffy_del(buf);
--bc->pool_fill;
}
 
/* Add missing ones. */
while(bc->pool_fill < bc->pool_size)
{
/* Again, just work on the front. */
struct buffy* buf;
buf = buffy_new(0, bc->bufblock); /* Use default block size. */
if(!buf) return -1;
 
buf->next = bc->pool;
bc->pool = buf;
++bc->pool_fill;
}
 
return 0;
}
 
 
static void bc_init(struct bufferchain *bc)
{
bc->first = NULL;
419,15 → 593,14
 
static void bc_reset(struct bufferchain *bc)
{
/* free the buffer chain */
struct buffy *b = bc->first;
while(b != NULL)
/* Free current chain, possibly stuffing back into the pool. */
while(bc->first)
{
struct buffy *n = b->next;
free(b->data);
free(b);
b = n;
struct buffy* buf = bc->first;
bc->first = buf->next;
bc_free(bc, buf);
}
bc_fill_pool(bc); /* Ignoring an error here... */
bc_init(bc);
}
 
437,36 → 610,58
struct buffy *newbuf;
if(size < 1) return -1;
 
newbuf = malloc(sizeof(struct buffy));
newbuf = bc_alloc(bc, size);
if(newbuf == NULL) return -2;
 
newbuf->data = malloc(size);
if(newbuf->data == NULL)
{
free(newbuf);
return -3;
}
newbuf->size = size;
newbuf->next = NULL;
if(bc->last != NULL) bc->last->next = newbuf;
else if(bc->first == NULL) bc->first = newbuf;
 
bc->last = newbuf;
bc->size += size;
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);
return 0;
}
 
 
/* Append a new buffer and copy content to it. */
static int bc_add(struct bufferchain *bc, const unsigned char *data, ssize_t size)
{
int ret = 0;
if((ret = bc_append(bc, size)) == 0)
memcpy(bc->last->data, data, size);
ssize_t part = 0;
debug2("bc_add: adding %"SSIZE_P" bytes at %"OFF_P, (ssize_p)size, (off_p)(bc->fileoff+bc->size));
if(size >=4) debug4("first bytes: %02x %02x %02x %02x", data[0], data[1], data[2], data[3]);
 
while(size > 0)
{
/* Try to fill up the last buffer block. */
if(bc->last != NULL && bc->last->size < bc->last->realsize)
{
part = bc->last->realsize - bc->last->size;
if(part > size) part = size;
 
debug2("bc_add: adding %"SSIZE_P" B to existing block %p", (ssize_p)part, (void*)bc->last);
memcpy(bc->last->data+bc->last->size, data, part);
bc->last->size += part;
size -= part;
bc->size += part;
data += part;
}
 
/* If there is still data left, put it into a new buffer block. */
if(size > 0 && (ret = bc_append(bc, size)) != 0)
break;
}
 
return ret;
}
 
/* Common handler for "You want more than I can give." situation. */
static ssize_t bc_need_more(struct bufferchain *bc)
{
debug3("hit end, back to beginning (%li - %li < %li)", (long)bc->size, (long)bc->pos, (long)bc->size);
/* go back to firstpos, undo the previous reads */
bc->pos = bc->firstpos;
return READER_MORE;
}
 
/* Give some data, advancing position but not forgetting yet. */
static ssize_t bc_give(struct bufferchain *bc, unsigned char *out, ssize_t size)
{
473,13 → 668,8
struct buffy *b = bc->first;
ssize_t gotcount = 0;
ssize_t offset = 0;
if(bc->size - bc->pos < size)
{
debug3("hit end, back to beginning (%li - %li < %li)", (long)bc->size, (long)bc->pos, (long)size);
/* go back to firstpos, undo the previous reads */
bc->pos = bc->firstpos;
return READER_MORE;
}
if(bc->size - bc->pos < size) return bc_need_more(bc);
 
/* find the current buffer */
while(b != NULL && (offset + b->size) <= bc->pos)
{
494,7 → 684,7
if(chunk > b->size - loff) chunk = b->size - loff;
 
#ifdef EXTRA_DEBUG
debug3("copying %liB from %p+%li",(long)chunk, b->data, (long)loff); */
debug3("copying %liB from %p+%li",(long)chunk, b->data, (long)loff);
#endif
 
memcpy(out+gotcount, b->data+loff, chunk);
516,7 → 706,7
{
if(count >= 0)
{
if(bc->size - bc->pos < count) return READER_MORE;
if(bc->size - bc->pos < count) return bc_need_more(bc);
else return bc->pos += count;
}
else return READER_ERROR;
534,10 → 724,9
struct buffy *b = bc->first;
/* free all buffers that are def'n'tly outdated */
/* we have buffers until filepos... delete all buffers fully below it */
#ifdef EXTRA_DEBUG
if(b) debug2("bc_forget: block %lu pos %lu", (unsigned long)b->size, (unsigned long)bc->pos);
else debug("forget with nothing there!");
#endif
 
while(b != NULL && bc->pos >= b->size)
{
struct buffy *n = b->next; /* != NULL or this is indeed the end and the last cycle anyway */
545,11 → 734,10
bc->fileoff += b->size;
bc->pos -= b->size;
bc->size -= b->size;
#ifdef EXTRA_DEBUG
 
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);
#endif
free(b->data);
free(b);
 
bc_free(bc, b);
b = n;
}
bc->first = b;
561,6 → 749,7
static int feed_init(mpg123_handle *fr)
{
bc_init(&fr->rdat.buffer);
bc_fill_pool(&fr->rdat.buffer);
fr->rdat.filelen = 0;
fr->rdat.filepos = 0;
fr->rdat.flags |= READER_BUFFERED;
594,7 → 783,11
/* returns reached position... negative ones are bad... */
static off_t feed_skip_bytes(mpg123_handle *fr,off_t len)
{
return fr->rdat.buffer.fileoff+bc_skip(&fr->rdat.buffer, (ssize_t)len);
/* This is either the new buffer offset or some negative error value. */
off_t res = bc_skip(&fr->rdat.buffer, (ssize_t)len);
if(res < 0) return res;
 
return fr->rdat.buffer.fileoff+res;
}
 
static int feed_back_bytes(mpg123_handle *fr, off_t bytes)
620,12 → 813,14
if(pos >= bc->fileoff && pos-bc->fileoff < bc->size)
{ /* We have the position! */
bc->pos = (ssize_t)(pos - bc->fileoff);
return pos+bc->size; /* Next input after end of buffer... */
debug1("feed_set_pos inside, next feed from %"OFF_P, (off_p)(bc->fileoff+bc->size));
return bc->fileoff+bc->size; /* Next input after end of buffer... */
}
else
{ /* I expect to get the specific position on next feed. Forget what I have now. */
bc_reset(bc);
bc->fileoff = pos;
debug1("feed_set_pos outside, buffer reset, next feed from %"OFF_P, (off_p)pos);
return pos; /* Next input from exactly that position. */
}
}
632,8 → 827,6
 
/* The specific stuff for buffered stream reader. */
 
/* Let's work in nice 4K blocks, that may be nicely reusable (by malloc(), even). */
#define BUFFBLOCK 4096
static ssize_t buffered_fullread(mpg123_handle *fr, unsigned char *out, ssize_t count)
{
struct bufferchain *bc = &fr->rdat.buffer;
640,12 → 833,12
ssize_t gotcount;
if(bc->size - bc->pos < count)
{ /* Add more stuff to buffer. If hitting end of file, adjust count. */
unsigned char readbuf[BUFFBLOCK];
unsigned char readbuf[4096];
ssize_t need = count - (bc->size-bc->pos);
while(need>0)
{
int ret;
ssize_t got = fr->rdat.fullread(fr, readbuf, BUFFBLOCK);
ssize_t got = fr->rdat.fullread(fr, readbuf, sizeof(readbuf));
if(got < 0)
{
if(NOQUIET) error("buffer reading");
660,7 → 853,7
}
 
need -= got; /* May underflow here... */
if(got < BUFFBLOCK) /* That naturally catches got == 0, too. */
if(got < sizeof(readbuf)) /* That naturally catches got == 0, too. */
{
if(VERBOSE3) fprintf(stderr, "Note: Input data end.\n");
break; /* End. */
694,17 → 887,17
*/
 
#define bugger_off { mh->err = MPG123_NO_READER; return MPG123_ERR; }
int bad_init(mpg123_handle *mh) bugger_off
void bad_close(mpg123_handle *mh){}
ssize_t bad_fullread(mpg123_handle *mh, unsigned char *data, ssize_t count) bugger_off
int bad_head_read(mpg123_handle *mh, unsigned long *newhead) bugger_off
int bad_head_shift(mpg123_handle *mh, unsigned long *head) bugger_off
off_t bad_skip_bytes(mpg123_handle *mh, off_t len) bugger_off
int bad_read_frame_body(mpg123_handle *mh, unsigned char *data, int size) bugger_off
int bad_back_bytes(mpg123_handle *mh, off_t bytes) bugger_off
int bad_seek_frame(mpg123_handle *mh, off_t num) bugger_off
off_t bad_tell(mpg123_handle *mh) bugger_off
void bad_rewind(mpg123_handle *mh){}
static int bad_init(mpg123_handle *mh) bugger_off
static void bad_close(mpg123_handle *mh){}
static ssize_t bad_fullread(mpg123_handle *mh, unsigned char *data, ssize_t count) bugger_off
static int bad_head_read(mpg123_handle *mh, unsigned long *newhead) bugger_off
static int bad_head_shift(mpg123_handle *mh, unsigned long *head) bugger_off
static off_t bad_skip_bytes(mpg123_handle *mh, off_t len) bugger_off
static int bad_read_frame_body(mpg123_handle *mh, unsigned char *data, int size) bugger_off
static int bad_back_bytes(mpg123_handle *mh, off_t bytes) bugger_off
static int bad_seek_frame(mpg123_handle *mh, off_t num) bugger_off
static off_t bad_tell(mpg123_handle *mh) bugger_off
static void bad_rewind(mpg123_handle *mh){}
#undef bugger_off
 
#define READER_STREAM 0
712,7 → 905,7
#define READER_FEED 2
#define READER_BUF_STREAM 3
#define READER_BUF_ICY_STREAM 4
struct reader readers[] =
static struct reader readers[] =
{
{ /* READER_STREAM */
default_init,
811,7 → 1004,7
#endif
};
 
struct reader bad_reader =
static struct reader bad_reader =
{
bad_init,
bad_close,
829,12 → 1022,40
 
static int default_init(mpg123_handle *fr)
{
#ifdef TIMEOUT_READ
if(fr->p.timeout > 0)
{
int flags;
if(fr->rdat.r_read != NULL)
{
error("Timeout reading does not work with user-provided read function. Implement it yourself!");
return -1;
}
flags = fcntl(fr->rdat.filept, F_GETFL);
flags |= O_NONBLOCK;
fcntl(fr->rdat.filept, F_SETFL, flags);
fr->rdat.fdread = timeout_read;
fr->rdat.timeout_sec = fr->p.timeout;
fr->rdat.flags |= READER_NONBLOCK;
}
else
#endif
fr->rdat.fdread = plain_read;
 
fr->rdat.read = fr->rdat.r_read != NULL ? fr->rdat.r_read : posix_read;
fr->rdat.lseek = fr->rdat.r_lseek != NULL ? fr->rdat.r_lseek : posix_lseek;
#ifndef NO_ICY
/* ICY streams of any sort shall not be seekable. */
if(fr->p.icy_interval > 0) fr->rdat.lseek = nix_lseek;
#endif
 
fr->rdat.filelen = get_fileinfo(fr);
fr->rdat.filepos = 0;
/*
Don't enable seeking on ICY streams, just plain normal files.
This check is necessary since the client can enforce ICY parsing on files that would otherwise be seekable.
It is a task for the future to make the ICY parsing safe with seeks ... or not.
*/
if(fr->rdat.filelen >= 0)
{
fr->rdat.flags |= READER_SEEKABLE;
880,12 → 1101,16
 
void open_bad(mpg123_handle *mh)
{
debug("open_bad");
#ifndef NO_ICY
clear_icy(&mh->icy);
#endif
mh->rd = &bad_reader;
mh->rdat.flags = 0;
#ifndef NO_FEEDER
bc_init(&mh->rdat.buffer);
#endif
mh->rdat.filelen = -1;
}
 
int open_feed(mpg123_handle *fr)
908,10 → 1133,35
fr->rd = &readers[READER_FEED];
fr->rdat.flags = 0;
if(fr->rd->init(fr) < 0) return -1;
 
debug("feed reader init successful");
return 0;
#endif /* NO_FEEDER */
}
 
/* Final code common to open_stream and open_stream_handle. */
static int open_finish(mpg123_handle *fr)
{
#ifndef NO_ICY
if(fr->p.icy_interval > 0)
{
debug("ICY reader");
fr->icy.interval = fr->p.icy_interval;
fr->icy.next = fr->icy.interval;
fr->rd = &readers[READER_ICY_STREAM];
}
else
#endif
{
fr->rd = &readers[READER_STREAM];
debug("stream reader");
}
 
if(fr->rd->init(fr) < 0) return -1;
 
return MPG123_OK;
}
 
int open_stream(mpg123_handle *fr, const char *bs_filenam, int fd)
{
int filept_opened = 1;
918,6 → 1168,7
int filept; /* descriptor of opened file/stream */
 
clear_icy(&fr->icy); /* can be done inside frame_clear ...? */
 
if(!bs_filenam) /* no file to open, got a descriptor (stdin) */
{
filept = fd;
926,7 → 1177,7
#ifndef O_BINARY
#define O_BINARY (0)
#endif
else if((filept = open(bs_filenam, O_RDONLY|O_BINARY)) < 0) /* a plain old file to open... */
else if((filept = compat_open(bs_filenam, O_RDONLY|O_BINARY)) < 0) /* a plain old file to open... */
{
if(NOQUIET) error2("Cannot open file %s: %s", bs_filenam, strerror(errno));
fr->err = MPG123_BAD_FILE;
939,22 → 1190,46
fr->rdat.flags = 0;
if(filept_opened) fr->rdat.flags |= READER_FD_OPENED;
 
#ifndef NO_ICY
if(fr->p.icy_interval > 0)
return open_finish(fr);
}
 
int open_stream_handle(mpg123_handle *fr, void *iohandle)
{
debug("ICY reader");
fr->icy.interval = fr->p.icy_interval;
fr->icy.next = fr->icy.interval;
fr->rd = &readers[READER_ICY_STREAM];
clear_icy(&fr->icy); /* can be done inside frame_clear ...? */
fr->rdat.filelen = -1;
fr->rdat.filept = -1;
fr->rdat.iohandle = iohandle;
fr->rdat.flags = 0;
fr->rdat.flags |= READER_HANDLEIO;
 
return open_finish(fr);
}
else
#endif
 
/* Wrappers for actual reading/seeking... I'm full of wrappers here. */
static off_t io_seek(struct reader_data *rdat, off_t offset, int whence)
{
fr->rd = &readers[READER_STREAM];
debug("stream reader");
if(rdat->flags & READER_HANDLEIO)
{
if(rdat->r_lseek_handle != NULL)
{
return rdat->r_lseek_handle(rdat->iohandle, offset, whence);
}
else return -1;
}
else
return rdat->lseek(rdat->filept, offset, whence);
}
 
if(fr->rd->init(fr) < 0) return -1;
 
return MPG123_OK;
static ssize_t io_read(struct reader_data *rdat, void *buf, size_t count)
{
if(rdat->flags & READER_HANDLEIO)
{
if(rdat->r_read_handle != NULL)
{
return rdat->r_read_handle(rdat->iohandle, buf, count);
}
else return -1;
}
else
return rdat->read(rdat->filept, buf, count);
}