📄 readers.c
字号:
free(bc->last); cur->next = NULL; bc->last = cur;}#endif/* Append a new buffer and copy content to it. */static int bc_add(struct bufferchain *bc, unsigned char *data, ssize_t size){ int ret = 0; if((ret = bc_append(bc, size)) == 0) memcpy(bc->last->data, data, size); return ret;}/* Give some data, advancing position but not forgetting yet. */static ssize_t bc_give(struct bufferchain *bc, unsigned char *out, size_t size){ 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; } /* find the current buffer */ while(b != NULL && (offset + b->size) <= bc->pos) { offset += b->size; b = b->next; } /* now start copying from there */ while(gotcount < size && (b != NULL)) { ssize_t loff = bc->pos - offset; ssize_t chunk = size - gotcount; /* amount of bytes to get from here... */ if(chunk > b->size - loff) chunk = b->size - loff; debug3("copying %liB from %p+%li",(long)chunk, b->data, (long)loff); memcpy(out+gotcount, b->data+loff, chunk); gotcount += chunk; bc->pos += chunk; offset += b->size; b = b->next; } debug2("got %li bytes, pos advanced to %li", (long)gotcount, (long)bc->pos); return gotcount;}/* Skip some bytes and return the new position. The buffers are still there, just the read pointer is moved! */static ssize_t bc_skip(struct bufferchain *bc, ssize_t count){ if(count >= 0) { if(bc->size - bc->pos < count) return READER_MORE; else return bc->pos += count; } else return READER_ERROR;}static ssize_t bc_seekback(struct bufferchain *bc, ssize_t count){ if(count >= 0 && count <= bc->pos) return bc->pos -= count; else return READER_ERROR;}/* Throw away buffies that we passed. */static void bc_forget(struct bufferchain *bc){ 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 */ if(b) debug2("bc_forget: block %lu pos %lu", (unsigned long)b->size, (unsigned long)bc->pos); else debug("forget with nothing there!"); while(b != NULL && bc->pos >= b->size) { struct buffy *n = b->next; /* != NULL or this is indeed the end and the last cycle anyway */ if(n == NULL) bc->last = NULL; /* Going to delete the last buffy... */ bc->fileoff += b->size; bc->pos -= b->size; bc->size -= b->size; 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); free(b->data); free(b); b = n; } bc->first = b; bc->firstpos = bc->pos;}/* reader for input via manually provided buffers */static int feed_init(mpg123_handle *fr){ bc_init(&fr->rdat.buffer); fr->rdat.filelen = 0; fr->rdat.filepos = 0; fr->rdat.flags |= READER_BUFFERED; return 0;}/* externally called function, returns 0 on success, -1 on error */int feed_more(mpg123_handle *fr, unsigned char *in, long count){ int ret = 0; debug("feed_more"); if((ret = bc_add(&fr->rdat.buffer, in, count)) != 0) { ret = READER_ERROR; if(NOQUIET) error1("Failed to add buffer, return: %i", ret); } else /* Not talking about filelen... that stays at 0. */ debug3("feed_more: %p %luB bufsize=%lu", fr->rdat.buffer.last->data, (unsigned long)fr->rdat.buffer.last->size, (unsigned long)fr->rdat.buffer.size); return ret;}static ssize_t feed_read(mpg123_handle *fr, unsigned char *out, ssize_t count){ ssize_t gotcount = bc_give(&fr->rdat.buffer, out, count); if(gotcount >= 0 && gotcount != count) return READER_ERROR; else return gotcount;}/* 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);}static int feed_back_bytes(mpg123_handle *fr, off_t bytes){ if(bytes >=0) return bc_seekback(&fr->rdat.buffer, (ssize_t)bytes) >= 0 ? 0 : READER_ERROR; else return feed_skip_bytes(fr, -bytes) >= 0 ? 0 : READER_ERROR;}static int buffered_seek_frame(mpg123_handle *fr, off_t num){ return READER_ERROR; }/* Not just for feed reader, also for self-feeding buffered reader. */static void buffered_forget(mpg123_handle *fr){ bc_forget(&fr->rdat.buffer); fr->rdat.filepos = fr->rdat.buffer.fileoff + fr->rdat.buffer.pos;}off_t feed_set_pos(mpg123_handle *fr, off_t pos){ struct bufferchain *bc = &fr->rdat.buffer; 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... */ } else { /* I expect to get the specific position on next feed. Forget what I have now. */ bc_reset(bc); bc->fileoff = pos; return pos; /* Next input from exactly that position. */ }}/* The specific stuff for buffered stream reader. *//* Let's work in nice 4K blocks, that may be nicely reusable (by malloc(), even). */#define BUFFBLOCK 4096static ssize_t buffered_fullread(mpg123_handle *fr, unsigned char *out, ssize_t count){ struct bufferchain *bc = &fr->rdat.buffer; 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]; ssize_t need = count - (bc->size-bc->pos); while(need>0) { int ret; ssize_t got = fr->rdat.fullread(fr, readbuf, BUFFBLOCK); if(got < 0) { if(NOQUIET) error("buffer reading"); return READER_ERROR; } debug1("buffered_fullread: buffering %li bytes from stream (if > 0)", (long)got); if(got > 0 && (ret=bc_add(bc, readbuf, got)) != 0) { if(NOQUIET) error1("unable to add to chain, return: %i", ret); return READER_ERROR; } need -= got; /* May underflow here... */ if(got < BUFFBLOCK) /* That naturally catches got == 0, too. */ { if(VERBOSE3) fprintf(stderr, "Note: Input data end.\n"); break; /* End. */ } } if(bc->size - bc->pos < count) count = bc->size - bc->pos; /* We want only what we got. */ } gotcount = bc_give(bc, out, count); debug2("wanted %li, got %li", (long)count, (long)gotcount); if(gotcount != count){ if(NOQUIET) error("gotcount != count"); return READER_ERROR; } else return gotcount;}/***************************************************************** * read frame helper */#define bugger_off { mh->err = MPG123_NO_READER; return MPG123_ERR; }int bad_init(mpg123_handle *mh) bugger_offvoid bad_close(mpg123_handle *mh){}ssize_t bad_fullread(mpg123_handle *mh, unsigned char *data, ssize_t count) bugger_offint bad_head_read(mpg123_handle *mh, unsigned long *newhead) bugger_offint bad_head_shift(mpg123_handle *mh, unsigned long *head) bugger_offoff_t bad_skip_bytes(mpg123_handle *mh, off_t len) bugger_offint bad_read_frame_body(mpg123_handle *mh, unsigned char *data, int size) bugger_offint bad_back_bytes(mpg123_handle *mh, off_t bytes) bugger_offint bad_seek_frame(mpg123_handle *mh, off_t num) bugger_offoff_t bad_tell(mpg123_handle *mh) bugger_offvoid bad_rewind(mpg123_handle *mh){}#undef bugger_off#define READER_STREAM 0#define READER_ICY_STREAM 1#define READER_FEED 2#define READER_BUF_STREAM 3#define READER_BUF_ICY_STREAM 4struct reader readers[] ={ { /* READER_STREAM */ default_init, stream_close, plain_fullread, generic_head_read, generic_head_shift, stream_skip_bytes, generic_read_frame_body, stream_back_bytes, stream_seek_frame, generic_tell, stream_rewind, NULL } , { /* READER_ICY_STREAM */ default_init, stream_close, icy_fullread, generic_head_read, generic_head_shift, stream_skip_bytes, generic_read_frame_body, stream_back_bytes, stream_seek_frame, generic_tell, stream_rewind, NULL }, { /* READER_FEED */ feed_init, stream_close, feed_read, generic_head_read, generic_head_shift, feed_skip_bytes, generic_read_frame_body, feed_back_bytes, buffered_seek_frame, generic_tell, stream_rewind, buffered_forget }, { /* READER_BUF_STREAM */ default_init, stream_close, buffered_fullread, generic_head_read, generic_head_shift, stream_skip_bytes, generic_read_frame_body, stream_back_bytes, buffered_seek_frame, generic_tell, stream_rewind, buffered_forget } , { /* READER_BUF_ICY_STREAM */ default_init, stream_close, buffered_fullread, generic_head_read, generic_head_shift, stream_skip_bytes, generic_read_frame_body, stream_back_bytes, buffered_seek_frame, generic_tell, stream_rewind, buffered_forget },#ifdef READ_SYSTEM ,{ system_init, NULL, /* filled in by system_init() */ fullread, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }#endif};struct reader bad_reader ={ bad_init, bad_close, bad_fullread, bad_head_read, bad_head_shift, bad_skip_bytes, bad_read_frame_body, bad_back_bytes, bad_seek_frame, bad_tell, bad_rewind, NULL};static int default_init(mpg123_handle *fr){#ifndef WIN32 if(fr->p.timeout > 0) { fcntl(fr->rdat.filept, F_SETFL, O_NONBLOCK); 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; fr->rdat.filelen = get_fileinfo(fr); fr->rdat.filepos = 0; if(fr->rdat.filelen >= 0) { fr->rdat.flags |= READER_SEEKABLE; if(!strncmp((char*)fr->id3buf,"TAG",3)) { fr->rdat.flags |= READER_ID3TAG; fr->metaflags |= MPG123_NEW_ID3; } } /* Switch reader to a buffered one, if allowed. */ else if(fr->p.flags & MPG123_SEEKBUFFER) { if (fr->rd == &readers[READER_STREAM]) { fr->rd = &readers[READER_BUF_STREAM]; fr->rdat.fullread = plain_fullread; } else if(fr->rd == &readers[READER_ICY_STREAM]) { fr->rd = &readers[READER_BUF_ICY_STREAM]; fr->rdat.fullread = icy_fullread; } else { if(NOQUIET) error("mpg123 Programmer's fault: invalid reader"); return -1; } bc_init(&fr->rdat.buffer); fr->rdat.filelen = 0; /* We carry the offset, but never know how big the stream is. */ fr->rdat.flags |= READER_BUFFERED; } return 0;}void open_bad(mpg123_handle *mh){ clear_icy(&mh->icy); mh->rd = &bad_reader; mh->rdat.flags = 0; bc_init(&mh->rdat.buffer);}int open_feed(mpg123_handle *fr){ debug("feed reader"); clear_icy(&fr->icy); fr->rd = &readers[READER_FEED]; fr->rdat.flags = 0; if(fr->rd->init(fr) < 0) return -1; return 0;}int open_stream(mpg123_handle *fr, char *bs_filenam, int fd){ int filept_opened = 1; 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; filept_opened = 0; /* and don't try to close it... */ } #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... */ { if(NOQUIET) error2("Cannot file %s: %s", bs_filenam, strerror(errno)); fr->err = MPG123_BAD_FILE; return filept; /* error... */ } /* now we have something behind filept and can init the reader */ fr->rdat.filelen = -1; fr->rdat.filept = filept; fr->rdat.flags = 0; if(filept_opened) fr->rdat.flags |= READER_FD_OPENED; 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 { fr->rd = &readers[READER_STREAM]; debug("stream reader"); } if(fr->rd->init(fr) < 0) return -1; return MPG123_OK;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -