Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenreaders.c
Go to the documentation of this file.
00001 /* TODO: Check all read calls (in loops, especially!) for return value 0 (EOF)! */ 00002 00003 /* 00004 readers.c: reading input data 00005 00006 copyright ?-2008 by the mpg123 project - free software under the terms of the LGPL 2.1 00007 see COPYING and AUTHORS files in distribution or http://mpg123.org 00008 initially written by Michael Hipp 00009 */ 00010 00011 #include "mpg123lib_intern.h" 00012 #include <sys/stat.h> 00013 #include <fcntl.h> 00014 #include <errno.h> 00015 /* 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). */ 00016 #ifdef HAVE_SYS_SELECT_H 00017 #include <sys/select.h> 00018 #endif 00019 #ifdef HAVE_SYS_TIME_H 00020 #include <sys/time.h> 00021 #endif 00022 #ifdef _MSC_VER 00023 #include <io.h> 00024 #endif 00025 00026 #include "compat.h" 00027 #include "debug.h" 00028 00029 static int default_init(mpg123_handle *fr); 00030 static off_t get_fileinfo(mpg123_handle *); 00031 static long posix_read(int fd, void *buf, size_t count){ return read(fd, buf, count); } 00032 static off_t posix_lseek(int fd, off_t offset, int whence){ return lseek(fd, offset, whence); } 00033 00034 static long plain_fullread(mpg123_handle *fr,unsigned char *buf, long count); 00035 00036 /* Wrapper to decide between descriptor-based and external handle-based I/O. */ 00037 static off_t io_seek(struct reader_data *rdat, off_t offset, int whence); 00038 static long io_read(struct reader_data *rdat, void *buf, size_t count); 00039 00040 #ifndef NO_FEEDER 00041 /* Bufferchain methods. */ 00042 static void bc_init(struct bufferchain *bc); 00043 static void bc_reset(struct bufferchain *bc); 00044 static int bc_append(struct bufferchain *bc, long size); 00045 #if 0 00046 static void bc_drop(struct bufferchain *bc); 00047 #endif 00048 static int bc_add(struct bufferchain *bc, const unsigned char *data, long size); 00049 static long bc_give(struct bufferchain *bc, unsigned char *out, long size); 00050 static long bc_skip(struct bufferchain *bc, long count); 00051 static long bc_seekback(struct bufferchain *bc, long count); 00052 static void bc_forget(struct bufferchain *bc); 00053 #else 00054 #define bc_init(a) 00055 #define bc_reset(a) 00056 #endif 00057 00058 /* A normal read and a read with timeout. */ 00059 static long plain_read(mpg123_handle *fr, void *buf, size_t count) 00060 { 00061 long ret = io_read(&fr->rdat, buf, count); 00062 if(VERBOSE3) debug2("read %li bytes of %li", (long)ret, (long)count); 00063 return ret; 00064 } 00065 00066 #ifdef TIMEOUT_READ 00067 00068 /* Wait for data becoming available, allowing soft-broken network connection to die 00069 This is needed for Shoutcast servers that have forgotten about us while connection was temporarily down. */ 00070 static long timeout_read(mpg123_handle *fr, void *buf, size_t count) 00071 { 00072 struct timeval tv; 00073 long ret = 0; 00074 fd_set fds; 00075 tv.tv_sec = fr->rdat.timeout_sec; 00076 tv.tv_usec = 0; 00077 FD_ZERO(&fds); 00078 FD_SET(fr->rdat.filept, &fds); 00079 ret = select(fr->rdat.filept+1, &fds, NULL, NULL, &tv); 00080 /* This works only with "my" read function. Not user-replaced. */ 00081 if(ret > 0) ret = read(fr->rdat.filept, buf, count); 00082 else 00083 { 00084 ret=-1; /* no activity is the error */ 00085 if(NOQUIET) error("stream timed out"); 00086 } 00087 return ret; 00088 } 00089 #endif 00090 00091 #ifndef NO_ICY 00092 /* stream based operation with icy meta data*/ 00093 static long icy_fullread(mpg123_handle *fr, unsigned char *buf, long count) 00094 { 00095 long ret,cnt; 00096 cnt = 0; 00097 if(fr->rdat.flags & READER_SEEKABLE) 00098 { 00099 if(NOQUIET) error("mpg123 programmer error: I don't do ICY on seekable streams."); 00100 return -1; 00101 } 00102 /* 00103 There used to be a check for expected file end here (length value or ID3 flag). 00104 This is not needed: 00105 1. EOF is indicated by fdread returning zero bytes anyway. 00106 2. We get false positives of EOF for either files that grew or 00107 3. ... files that have ID3v1 tags in between (stream with intro). 00108 */ 00109 00110 while(cnt < count) 00111 { 00112 /* all icy code is inside this if block, everything else is the plain fullread we know */ 00113 /* debug1("read: %li left", (long) count-cnt); */ 00114 if(fr->icy.next < count-cnt) 00115 { 00116 unsigned char temp_buff; 00117 size_t meta_size; 00118 long cut_pos; 00119 00120 /* we are near icy-metaint boundary, read up to the boundary */ 00121 if(fr->icy.next > 0) 00122 { 00123 cut_pos = fr->icy.next; 00124 ret = fr->rdat.fdread(fr,buf+cnt,cut_pos); 00125 if(ret < 1) 00126 { 00127 if(ret == 0) break; /* Just EOF. */ 00128 if(NOQUIET) error("icy boundary read"); 00129 00130 return READER_ERROR; 00131 } 00132 00133 if(!(fr->rdat.flags & READER_BUFFERED)) fr->rdat.filepos += ret; 00134 cnt += ret; 00135 fr->icy.next -= ret; 00136 if(fr->icy.next > 0) 00137 { 00138 debug1("another try... still %li left", (long)fr->icy.next); 00139 continue; 00140 } 00141 } 00142 /* now off to read icy data */ 00143 00144 /* one byte icy-meta size (must be multiplied by 16 to get icy-meta length) */ 00145 00146 ret = fr->rdat.fdread(fr,&temp_buff,1); /* Getting one single byte hast to suceed. */ 00147 if(ret < 0){ if(NOQUIET) error("reading icy size"); return READER_ERROR; } 00148 if(ret == 0) break; 00149 00150 debug2("got meta-size byte: %u, at filepos %li", temp_buff, (long)fr->rdat.filepos ); 00151 if(!(fr->rdat.flags & READER_BUFFERED)) fr->rdat.filepos += ret; /* 1... */ 00152 00153 if((meta_size = ((size_t) temp_buff) * 16)) 00154 { 00155 /* we have got some metadata */ 00156 char *meta_buff; 00157 meta_buff = malloc(meta_size+1); 00158 if(meta_buff != NULL) 00159 { 00160 long left = meta_size; 00161 while(left > 0) 00162 { 00163 ret = fr->rdat.fdread(fr,meta_buff+meta_size-left,left); 00164 /* 0 is error here, too... there _must_ be the ICY data, the server promised! */ 00165 if(ret < 1){ if(NOQUIET) error("reading icy-meta"); return READER_ERROR; } 00166 left -= ret; 00167 } 00168 meta_buff[meta_size] = 0; /* string paranoia */ 00169 if(!(fr->rdat.flags & READER_BUFFERED)) fr->rdat.filepos += ret; 00170 00171 if(fr->icy.data) free(fr->icy.data); 00172 fr->icy.data = meta_buff; 00173 fr->metaflags |= MPG123_NEW_ICY; 00174 debug2("icy-meta: %s size: %d bytes", fr->icy.data, (int)meta_size); 00175 } 00176 else 00177 { 00178 if(NOQUIET) error1("cannot allocate memory for meta_buff (%lu bytes) ... trying to skip the metadata!", (unsigned long)meta_size); 00179 fr->rd->skip_bytes(fr, meta_size); 00180 } 00181 } 00182 fr->icy.next = fr->icy.interval; 00183 } 00184 else 00185 { 00186 ret = plain_fullread(fr, buf+cnt, count-cnt); 00187 if(ret < 0){ if(NOQUIET) error1("reading the rest of %li", (long)(count-cnt)); return READER_ERROR; } 00188 if(ret == 0) break; 00189 00190 cnt += ret; 00191 fr->icy.next -= ret; 00192 } 00193 } 00194 /* debug1("done reading, got %li", (long)cnt); */ 00195 return cnt; 00196 } 00197 #else 00198 #define icy_fullread NULL 00199 #endif /* NO_ICY */ 00200 00201 /* stream based operation */ 00202 static long plain_fullread(mpg123_handle *fr,unsigned char *buf, long count) 00203 { 00204 long ret,cnt=0; 00205 00206 /* 00207 There used to be a check for expected file end here (length value or ID3 flag). 00208 This is not needed: 00209 1. EOF is indicated by fdread returning zero bytes anyway. 00210 2. We get false positives of EOF for either files that grew or 00211 3. ... files that have ID3v1 tags in between (stream with intro). 00212 */ 00213 while(cnt < count) 00214 { 00215 ret = fr->rdat.fdread(fr,buf+cnt,count-cnt); 00216 if(ret < 0) return READER_ERROR; 00217 if(ret == 0) break; 00218 if(!(fr->rdat.flags & READER_BUFFERED)) fr->rdat.filepos += ret; 00219 cnt += ret; 00220 } 00221 return cnt; 00222 } 00223 00224 static off_t stream_lseek(mpg123_handle *fr, off_t pos, int whence) 00225 { 00226 off_t ret; 00227 ret = io_seek(&fr->rdat, pos, whence); 00228 if (ret >= 0) fr->rdat.filepos = ret; 00229 else 00230 { 00231 fr->err = MPG123_LSEEK_FAILED; 00232 ret = READER_ERROR; /* not the original value */ 00233 } 00234 return ret; 00235 } 00236 00237 static void stream_close(mpg123_handle *fr) 00238 { 00239 if(fr->rdat.flags & READER_FD_OPENED) compat_close(fr->rdat.filept); 00240 00241 fr->rdat.filept = 0; 00242 00243 if(fr->rdat.flags & READER_BUFFERED) bc_reset(&fr->rdat.buffer); 00244 if(fr->rdat.flags & READER_HANDLEIO) 00245 { 00246 if(fr->rdat.cleanup_handle != NULL) fr->rdat.cleanup_handle(fr->rdat.iohandle); 00247 00248 fr->rdat.iohandle = NULL; 00249 } 00250 } 00251 00252 static int stream_seek_frame(mpg123_handle *fr, off_t newframe) 00253 { 00254 debug2("seek_frame to %"OFF_P" (from %"OFF_P")", (off_p)newframe, (off_p)fr->num); 00255 /* Seekable streams can go backwards and jump forwards. 00256 Non-seekable streams still can go forward, just not jump. */ 00257 if((fr->rdat.flags & READER_SEEKABLE) || (newframe >= fr->num)) 00258 { 00259 off_t preframe; /* a leading frame we jump to */ 00260 off_t seek_to; /* the byte offset we want to reach */ 00261 off_t to_skip; /* bytes to skip to get there (can be negative) */ 00262 /* 00263 now seek to nearest leading index position and read from there until newframe is reached. 00264 We use skip_bytes, which handles seekable and non-seekable streams 00265 (the latter only for positive offset, which we ensured before entering here). 00266 */ 00267 seek_to = frame_index_find(fr, newframe, &preframe); 00268 /* No need to seek to index position if we are closer already. 00269 But I am picky about fr->num == newframe, play safe by reading the frame again. 00270 If you think that's stupid, don't call a seek to the current frame. */ 00271 if(fr->num >= newframe || fr->num < preframe) 00272 { 00273 to_skip = seek_to - fr->rd->tell(fr); 00274 if(fr->rd->skip_bytes(fr, to_skip) != seek_to) 00275 return READER_ERROR; 00276 00277 debug2("going to %lu; just got %lu", (long unsigned)newframe, (long unsigned)preframe); 00278 fr->num = preframe-1; /* Watch out! I am going to read preframe... fr->num should indicate the frame before! */ 00279 } 00280 while(fr->num < newframe) 00281 { 00282 /* try to be non-fatal now... frameNum only gets advanced on success anyway */ 00283 if(!read_frame(fr)) break; 00284 } 00285 /* Now the wanted frame should be ready for decoding. */ 00286 debug1("arrived at %lu", (long unsigned)fr->num); 00287 00288 return MPG123_OK; 00289 } 00290 else 00291 { 00292 fr->err = MPG123_NO_SEEK; 00293 return READER_ERROR; /* invalid, no seek happened */ 00294 } 00295 } 00296 00297 /* return FALSE on error, TRUE on success, READER_MORE on occasion */ 00298 static int generic_head_read(mpg123_handle *fr,unsigned long *newhead) 00299 { 00300 unsigned char hbuf[4]; 00301 int ret = fr->rd->fullread(fr,hbuf,4); 00302 if(ret == READER_MORE) return ret; 00303 if(ret != 4) return FALSE; 00304 00305 *newhead = ((unsigned long) hbuf[0] << 24) | 00306 ((unsigned long) hbuf[1] << 16) | 00307 ((unsigned long) hbuf[2] << 8) | 00308 (unsigned long) hbuf[3]; 00309 00310 return TRUE; 00311 } 00312 00313 /* return FALSE on error, TRUE on success, READER_MORE on occasion */ 00314 static int generic_head_shift(mpg123_handle *fr,unsigned long *head) 00315 { 00316 unsigned char hbuf; 00317 int ret = fr->rd->fullread(fr,&hbuf,1); 00318 if(ret == READER_MORE) return ret; 00319 if(ret != 1) return FALSE; 00320 00321 *head <<= 8; 00322 *head |= hbuf; 00323 *head &= 0xffffffff; 00324 return TRUE; 00325 } 00326 00327 /* returns reached position... negative ones are bad... */ 00328 static off_t stream_skip_bytes(mpg123_handle *fr,off_t len) 00329 { 00330 if(fr->rdat.flags & READER_SEEKABLE) 00331 { 00332 off_t ret = stream_lseek(fr, len, SEEK_CUR); 00333 return (ret < 0) ? READER_ERROR : ret; 00334 } 00335 else if(len >= 0) 00336 { 00337 unsigned char buf[1024]; /* ThOr: Compaq cxx complained and it makes sense to me... or should one do a cast? What for? */ 00338 long ret; 00339 while (len > 0) 00340 { 00341 long num = len < (off_t)sizeof(buf) ? (long)len : (long)sizeof(buf); 00342 ret = fr->rd->fullread(fr, buf, num); 00343 if (ret < 0) return ret; 00344 else if(ret == 0) break; /* EOF... an error? interface defined to tell the actual position... */ 00345 len -= ret; 00346 } 00347 return fr->rd->tell(fr); 00348 } 00349 else if(fr->rdat.flags & READER_BUFFERED) 00350 { /* Perhaps we _can_ go a bit back. */ 00351 if(fr->rdat.buffer.pos >= -len) 00352 { 00353 fr->rdat.buffer.pos += len; 00354 return fr->rd->tell(fr); 00355 } 00356 else 00357 { 00358 fr->err = MPG123_NO_SEEK; 00359 return READER_ERROR; 00360 } 00361 } 00362 else 00363 { 00364 fr->err = MPG123_NO_SEEK; 00365 return READER_ERROR; 00366 } 00367 } 00368 00369 /* Return 0 on success... */ 00370 static int stream_back_bytes(mpg123_handle *fr, off_t bytes) 00371 { 00372 off_t want = fr->rd->tell(fr)-bytes; 00373 if(want < 0) return READER_ERROR; 00374 if(stream_skip_bytes(fr,-bytes) != want) return READER_ERROR; 00375 00376 return 0; 00377 } 00378 00379 00380 /* returns size on success... */ 00381 static int generic_read_frame_body(mpg123_handle *fr,unsigned char *buf, int size) 00382 { 00383 long l; 00384 00385 if((l=fr->rd->fullread(fr,buf,size)) != size) 00386 { 00387 long ll = l; 00388 if(ll <= 0) ll = 0; 00389 return READER_MORE; 00390 } 00391 return l; 00392 } 00393 00394 static off_t generic_tell(mpg123_handle *fr) 00395 { 00396 if(fr->rdat.flags & READER_BUFFERED) 00397 fr->rdat.filepos = fr->rdat.buffer.fileoff+fr->rdat.buffer.pos; 00398 00399 return fr->rdat.filepos; 00400 } 00401 00402 /* This does not (fully) work for non-seekable streams... You have to check for that flag, pal! */ 00403 static void stream_rewind(mpg123_handle *fr) 00404 { 00405 if(fr->rdat.flags & READER_SEEKABLE) 00406 fr->rdat.buffer.fileoff = fr->rdat.filepos = stream_lseek(fr,0,SEEK_SET); 00407 if(fr->rdat.flags & READER_BUFFERED) 00408 { 00409 fr->rdat.buffer.pos = 0; 00410 fr->rdat.buffer.firstpos = 0; 00411 fr->rdat.filepos = fr->rdat.buffer.fileoff; 00412 } 00413 } 00414 00415 /* 00416 * returns length of a file (if filept points to a file) 00417 * reads the last 128 bytes information into buffer 00418 * ... that is not totally safe... 00419 */ 00420 static off_t get_fileinfo(mpg123_handle *fr) 00421 { 00422 off_t len; 00423 00424 if((len=io_seek(&fr->rdat,0,SEEK_END)) < 0) return -1; 00425 00426 if(io_seek(&fr->rdat,-128,SEEK_END) < 0) return -1; 00427 00428 if(fr->rd->fullread(fr,(unsigned char *)fr->id3buf,128) != 128) return -1; 00429 00430 if(!strncmp((char*)fr->id3buf,"TAG",3)) len -= 128; 00431 00432 if(io_seek(&fr->rdat,0,SEEK_SET) < 0) return -1; 00433 00434 if(len <= 0) return -1; 00435 00436 return len; 00437 } 00438 00439 /* Let's work in nice 4K blocks, that may be nicely reusable (by malloc(), even). */ 00440 #define BUFFBLOCK 4096 00441 00442 #ifndef NO_FEEDER 00443 /* Methods for the buffer chain, mainly used for feed reader, but not just that. */ 00444 00445 static void bc_init(struct bufferchain *bc) 00446 { 00447 bc->first = NULL; 00448 bc->last = bc->first; 00449 bc->size = 0; 00450 bc->pos = 0; 00451 bc->firstpos = 0; 00452 bc->fileoff = 0; 00453 } 00454 00455 static void bc_reset(struct bufferchain *bc) 00456 { 00457 /* free the buffer chain */ 00458 struct buffy *b = bc->first; 00459 while(b != NULL) 00460 { 00461 struct buffy *n = b->next; 00462 free(b->data); 00463 free(b); 00464 b = n; 00465 } 00466 bc_init(bc); 00467 } 00468 00469 /* Create a new buffy at the end to be filled. */ 00470 static int bc_append(struct bufferchain *bc, long size) 00471 { 00472 struct buffy *newbuf; 00473 if(size < 1) return -1; 00474 00475 newbuf = malloc(sizeof(struct buffy)); 00476 if(newbuf == NULL) return -2; 00477 00478 newbuf->realsize = size > BUFFBLOCK ? size : BUFFBLOCK; 00479 newbuf->data = malloc(newbuf->realsize); 00480 if(newbuf->data == NULL) 00481 { 00482 free(newbuf); 00483 return -3; 00484 } 00485 newbuf->size = size; 00486 newbuf->next = NULL; 00487 if(bc->last != NULL) bc->last->next = newbuf; 00488 else if(bc->first == NULL) bc->first = newbuf; 00489 00490 bc->last = newbuf; 00491 bc->size += size; 00492 return 0; 00493 } 00494 00495 #if 0 00496 /* Drop the last one (again). 00497 This is not optimal but should happen on error situations only, anyway. */ 00498 static void bc_drop(struct bufferchain *bc) 00499 { 00500 struct buffy *cur = bc->first; 00501 if(bc->first == NULL || bc->last == NULL) return; 00502 /* Special case: only one buffer there. */ 00503 if(cur->next == NULL) 00504 { 00505 free(cur->data); 00506 free(cur); 00507 bc->first = bc->last = NULL; 00508 bc->size = 0; 00509 return; 00510 } 00511 /* Find the pre-last buffy. If chain is consistent, this _will_ succeed. */ 00512 while(cur->next != bc->last){ cur = cur->next; } 00513 00514 bc->size -= bc->last->size; 00515 free(bc->last->data); 00516 free(bc->last); 00517 cur->next = NULL; 00518 bc->last = cur; 00519 } 00520 #endif 00521 00522 /* Append a new buffer and copy content to it. */ 00523 static int bc_add(struct bufferchain *bc, const unsigned char *data, long size) 00524 { 00525 int ret = 0; 00526 long part = 0; 00527 debug2("bc_add: adding %"SSIZE_P" bytes at %"OFF_P, (ssize_p)size, (off_p)(bc->fileoff+bc->size)); 00528 if(size >=4) debug4("first bytes: %02x %02x %02x %02x", data[0], data[1], data[2], data[3]); 00529 00530 /* Try to fill up the last buffer block. */ 00531 if(bc->last != NULL && bc->last->size < bc->last->realsize) 00532 { 00533 part = bc->last->realsize - bc->last->size; 00534 if(part > size) part = size; 00535 00536 memcpy(bc->last->data+bc->last->size, data, part); 00537 bc->last->size += part; 00538 size -= part; 00539 bc->size += part; 00540 } 00541 00542 00543 /* If there is still data left, put it into a new buffer block. */ 00544 if(size > 0 && (ret = bc_append(bc, size)) == 0) 00545 memcpy(bc->last->data, data+part, size); 00546 00547 return ret; 00548 } 00549 00550 /* Common handler for "You want more than I can give." situation. */ 00551 static long bc_need_more(struct bufferchain *bc) 00552 { 00553 debug3("hit end, back to beginning (%li - %li < %li)", (long)bc->size, (long)bc->pos, (long)bc->size); 00554 /* go back to firstpos, undo the previous reads */ 00555 bc->pos = bc->firstpos; 00556 return READER_MORE; 00557 } 00558 00559 /* Give some data, advancing position but not forgetting yet. */ 00560 static long bc_give(struct bufferchain *bc, unsigned char *out, long size) 00561 { 00562 struct buffy *b = bc->first; 00563 long gotcount = 0; 00564 long offset = 0; 00565 if(bc->size - bc->pos < size) return bc_need_more(bc); 00566 00567 /* find the current buffer */ 00568 while(b != NULL && (offset + b->size) <= bc->pos) 00569 { 00570 offset += b->size; 00571 b = b->next; 00572 } 00573 /* now start copying from there */ 00574 while(gotcount < size && (b != NULL)) 00575 { 00576 long loff = bc->pos - offset; 00577 long chunk = size - gotcount; /* amount of bytes to get from here... */ 00578 if(chunk > b->size - loff) chunk = b->size - loff; 00579 00580 #ifdef EXTRA_DEBUG 00581 debug3("copying %liB from %p+%li",(long)chunk, b->data, (long)loff); 00582 #endif 00583 00584 memcpy(out+gotcount, b->data+loff, chunk); 00585 gotcount += chunk; 00586 bc->pos += chunk; 00587 offset += b->size; 00588 b = b->next; 00589 } 00590 #ifdef EXTRA_DEBUG 00591 debug2("got %li bytes, pos advanced to %li", (long)gotcount, (long)bc->pos); 00592 #endif 00593 00594 return gotcount; 00595 } 00596 00597 /* Skip some bytes and return the new position. 00598 The buffers are still there, just the read pointer is moved! */ 00599 static long bc_skip(struct bufferchain *bc, long count) 00600 { 00601 if(count >= 0) 00602 { 00603 if(bc->size - bc->pos < count) return bc_need_more(bc); 00604 else return bc->pos += count; 00605 } 00606 else return READER_ERROR; 00607 } 00608 00609 static long bc_seekback(struct bufferchain *bc, long count) 00610 { 00611 if(count >= 0 && count <= bc->pos) return bc->pos -= count; 00612 else return READER_ERROR; 00613 } 00614 00615 /* Throw away buffies that we passed. */ 00616 static void bc_forget(struct bufferchain *bc) 00617 { 00618 struct buffy *b = bc->first; 00619 /* free all buffers that are def'n'tly outdated */ 00620 /* we have buffers until filepos... delete all buffers fully below it */ 00621 if(b) debug2("bc_forget: block %lu pos %lu", (unsigned long)b->size, (unsigned long)bc->pos); 00622 else debug("forget with nothing there!"); 00623 00624 while(b != NULL && bc->pos >= b->size) 00625 { 00626 struct buffy *n = b->next; /* != NULL or this is indeed the end and the last cycle anyway */ 00627 if(n == NULL) bc->last = NULL; /* Going to delete the last buffy... */ 00628 bc->fileoff += b->size; 00629 bc->pos -= b->size; 00630 bc->size -= b->size; 00631 00632 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); 00633 00634 free(b->data); 00635 free(b); 00636 b = n; 00637 } 00638 bc->first = b; 00639 bc->firstpos = bc->pos; 00640 } 00641 00642 /* reader for input via manually provided buffers */ 00643 00644 static int feed_init(mpg123_handle *fr) 00645 { 00646 bc_init(&fr->rdat.buffer); 00647 fr->rdat.filelen = 0; 00648 fr->rdat.filepos = 0; 00649 fr->rdat.flags |= READER_BUFFERED; 00650 return 0; 00651 } 00652 00653 /* externally called function, returns 0 on success, -1 on error */ 00654 int feed_more(mpg123_handle *fr, const unsigned char *in, long count) 00655 { 00656 int ret = 0; 00657 if(VERBOSE3) debug("feed_more"); 00658 if((ret = bc_add(&fr->rdat.buffer, in, count)) != 0) 00659 { 00660 ret = READER_ERROR; 00661 if(NOQUIET) error1("Failed to add buffer, return: %i", ret); 00662 } 00663 else /* Not talking about filelen... that stays at 0. */ 00664 00665 if(VERBOSE3) debug3("feed_more: %p %luB bufsize=%lu", fr->rdat.buffer.last->data, 00666 (unsigned long)fr->rdat.buffer.last->size, (unsigned long)fr->rdat.buffer.size); 00667 return ret; 00668 } 00669 00670 static long feed_read(mpg123_handle *fr, unsigned char *out, long count) 00671 { 00672 long gotcount = bc_give(&fr->rdat.buffer, out, count); 00673 if(gotcount >= 0 && gotcount != count) return READER_ERROR; 00674 else return gotcount; 00675 } 00676 00677 /* returns reached position... negative ones are bad... */ 00678 static off_t feed_skip_bytes(mpg123_handle *fr,off_t len) 00679 { 00680 /* This is either the new buffer offset or some negative error value. */ 00681 off_t res = bc_skip(&fr->rdat.buffer, (long)len); 00682 if(res < 0) return res; 00683 00684 return fr->rdat.buffer.fileoff+res; 00685 } 00686 00687 static int feed_back_bytes(mpg123_handle *fr, off_t bytes) 00688 { 00689 if(bytes >=0) 00690 return bc_seekback(&fr->rdat.buffer, (long)bytes) >= 0 ? 0 : READER_ERROR; 00691 else 00692 return feed_skip_bytes(fr, -bytes) >= 0 ? 0 : READER_ERROR; 00693 } 00694 00695 static int feed_seek_frame(mpg123_handle *fr, off_t num){ return READER_ERROR; } 00696 00697 /* Not just for feed reader, also for self-feeding buffered reader. */ 00698 static void buffered_forget(mpg123_handle *fr) 00699 { 00700 bc_forget(&fr->rdat.buffer); 00701 fr->rdat.filepos = fr->rdat.buffer.fileoff + fr->rdat.buffer.pos; 00702 } 00703 00704 off_t feed_set_pos(mpg123_handle *fr, off_t pos) 00705 { 00706 struct bufferchain *bc = &fr->rdat.buffer; 00707 if(pos >= bc->fileoff && pos-bc->fileoff < bc->size) 00708 { /* We have the position! */ 00709 bc->pos = (long)(pos - bc->fileoff); 00710 debug1("feed_set_pos inside, next feed from %"OFF_P, (off_p)(bc->fileoff+bc->size)); 00711 return bc->fileoff+bc->size; /* Next input after end of buffer... */ 00712 } 00713 else 00714 { /* I expect to get the specific position on next feed. Forget what I have now. */ 00715 bc_reset(bc); 00716 bc->fileoff = pos; 00717 debug1("feed_set_pos outside, buffer reset, next feed from %"OFF_P, (off_p)pos); 00718 return pos; /* Next input from exactly that position. */ 00719 } 00720 } 00721 00722 /* The specific stuff for buffered stream reader. */ 00723 00724 static long buffered_fullread(mpg123_handle *fr, unsigned char *out, long count) 00725 { 00726 struct bufferchain *bc = &fr->rdat.buffer; 00727 long gotcount; 00728 if(bc->size - bc->pos < count) 00729 { /* Add more stuff to buffer. If hitting end of file, adjust count. */ 00730 unsigned char readbuf[BUFFBLOCK]; 00731 long need = count - (bc->size-bc->pos); 00732 while(need>0) 00733 { 00734 int ret; 00735 long got = fr->rdat.fullread(fr, readbuf, BUFFBLOCK); 00736 if(got < 0) 00737 { 00738 if(NOQUIET) error("buffer reading"); 00739 return READER_ERROR; 00740 } 00741 00742 if(VERBOSE3) debug1("buffered_fullread: buffering %li bytes from stream (if > 0)", (long)got); 00743 if(got > 0 && (ret=bc_add(bc, readbuf, got)) != 0) 00744 { 00745 if(NOQUIET) error1("unable to add to chain, return: %i", ret); 00746 return READER_ERROR; 00747 } 00748 00749 need -= got; /* May underflow here... */ 00750 if(got < BUFFBLOCK) /* That naturally catches got == 0, too. */ 00751 { 00752 if(VERBOSE3) fprintf(stderr, "Note: Input data end.\n"); 00753 break; /* End. */ 00754 } 00755 } 00756 if(bc->size - bc->pos < count) 00757 count = bc->size - bc->pos; /* We want only what we got. */ 00758 } 00759 gotcount = bc_give(bc, out, count); 00760 00761 if(VERBOSE3) debug2("wanted %li, got %li", (long)count, (long)gotcount); 00762 00763 if(gotcount != count){ if(NOQUIET) error("gotcount != count"); return READER_ERROR; } 00764 else return gotcount; 00765 } 00766 #else 00767 int feed_more(mpg123_handle *fr, const unsigned char *in, long count) 00768 { 00769 fr->err = MPG123_MISSING_FEATURE; 00770 return -1; 00771 } 00772 off_t feed_set_pos(mpg123_handle *fr, off_t pos) 00773 { 00774 fr->err = MPG123_MISSING_FEATURE; 00775 return -1; 00776 } 00777 #endif /* NO_FEEDER */ 00778 00779 /***************************************************************** 00780 * read frame helper 00781 */ 00782 00783 #define bugger_off { mh->err = MPG123_NO_READER; return MPG123_ERR; } 00784 int bad_init(mpg123_handle *mh) bugger_off 00785 void bad_close(mpg123_handle *mh){} 00786 long bad_fullread(mpg123_handle *mh, unsigned char *data, long count) bugger_off 00787 int bad_head_read(mpg123_handle *mh, unsigned long *newhead) bugger_off 00788 int bad_head_shift(mpg123_handle *mh, unsigned long *head) bugger_off 00789 off_t bad_skip_bytes(mpg123_handle *mh, off_t len) bugger_off 00790 int bad_read_frame_body(mpg123_handle *mh, unsigned char *data, int size) bugger_off 00791 int bad_back_bytes(mpg123_handle *mh, off_t bytes) bugger_off 00792 int bad_seek_frame(mpg123_handle *mh, off_t num) bugger_off 00793 off_t bad_tell(mpg123_handle *mh) bugger_off 00794 void bad_rewind(mpg123_handle *mh){} 00795 #undef bugger_off 00796 00797 #define READER_STREAM 0 00798 #define READER_ICY_STREAM 1 00799 #define READER_FEED 2 00800 #define READER_BUF_STREAM 3 00801 #define READER_BUF_ICY_STREAM 4 00802 struct reader readers[] = 00803 { 00804 { /* READER_STREAM */ 00805 default_init, 00806 stream_close, 00807 plain_fullread, 00808 generic_head_read, 00809 generic_head_shift, 00810 stream_skip_bytes, 00811 generic_read_frame_body, 00812 stream_back_bytes, 00813 stream_seek_frame, 00814 generic_tell, 00815 stream_rewind, 00816 NULL 00817 } , 00818 { /* READER_ICY_STREAM */ 00819 default_init, 00820 stream_close, 00821 icy_fullread, 00822 generic_head_read, 00823 generic_head_shift, 00824 stream_skip_bytes, 00825 generic_read_frame_body, 00826 stream_back_bytes, 00827 stream_seek_frame, 00828 generic_tell, 00829 stream_rewind, 00830 NULL 00831 }, 00832 #ifdef NO_FEEDER 00833 #define feed_init NULL 00834 #define feed_read NULL 00835 #define buffered_fullread NULL 00836 #define feed_seek_frame NULL 00837 #define feed_back_bytes NULL 00838 #define feed_skip_bytes NULL 00839 #define buffered_forget NULL 00840 #endif 00841 { /* READER_FEED */ 00842 feed_init, 00843 stream_close, 00844 feed_read, 00845 generic_head_read, 00846 generic_head_shift, 00847 feed_skip_bytes, 00848 generic_read_frame_body, 00849 feed_back_bytes, 00850 feed_seek_frame, 00851 generic_tell, 00852 stream_rewind, 00853 buffered_forget 00854 }, 00855 { /* READER_BUF_STREAM */ 00856 default_init, 00857 stream_close, 00858 buffered_fullread, 00859 generic_head_read, 00860 generic_head_shift, 00861 stream_skip_bytes, 00862 generic_read_frame_body, 00863 stream_back_bytes, 00864 stream_seek_frame, 00865 generic_tell, 00866 stream_rewind, 00867 buffered_forget 00868 } , 00869 { /* READER_BUF_ICY_STREAM */ 00870 default_init, 00871 stream_close, 00872 buffered_fullread, 00873 generic_head_read, 00874 generic_head_shift, 00875 stream_skip_bytes, 00876 generic_read_frame_body, 00877 stream_back_bytes, 00878 stream_seek_frame, 00879 generic_tell, 00880 stream_rewind, 00881 buffered_forget 00882 }, 00883 #ifdef READ_SYSTEM 00884 ,{ 00885 system_init, 00886 NULL, /* filled in by system_init() */ 00887 fullread, 00888 NULL, 00889 NULL, 00890 NULL, 00891 NULL, 00892 NULL, 00893 NULL, 00894 NULL, 00895 NULL, 00896 NULL, 00897 } 00898 #endif 00899 }; 00900 00901 struct reader bad_reader = 00902 { 00903 bad_init, 00904 bad_close, 00905 bad_fullread, 00906 bad_head_read, 00907 bad_head_shift, 00908 bad_skip_bytes, 00909 bad_read_frame_body, 00910 bad_back_bytes, 00911 bad_seek_frame, 00912 bad_tell, 00913 bad_rewind, 00914 NULL 00915 }; 00916 00917 static int default_init(mpg123_handle *fr) 00918 { 00919 #ifdef TIMEOUT_READ 00920 if(fr->p.timeout > 0) 00921 { 00922 int flags; 00923 if(fr->rdat.r_read != NULL) 00924 { 00925 error("Timeout reading does not work with user-provided read function. Implement it yourself!"); 00926 return -1; 00927 } 00928 flags = fcntl(fr->rdat.filept, F_GETFL); 00929 flags |= O_NONBLOCK; 00930 fcntl(fr->rdat.filept, F_SETFL, flags); 00931 fr->rdat.fdread = timeout_read; 00932 fr->rdat.timeout_sec = fr->p.timeout; 00933 fr->rdat.flags |= READER_NONBLOCK; 00934 } 00935 else 00936 #endif 00937 fr->rdat.fdread = plain_read; 00938 00939 fr->rdat.read = fr->rdat.r_read != NULL ? fr->rdat.r_read : posix_read; 00940 fr->rdat.lseek = fr->rdat.r_lseek != NULL ? fr->rdat.r_lseek : posix_lseek; 00941 fr->rdat.filelen = get_fileinfo(fr); 00942 fr->rdat.filepos = 0; 00943 if(fr->rdat.filelen >= 0) 00944 { 00945 fr->rdat.flags |= READER_SEEKABLE; 00946 if(!strncmp((char*)fr->id3buf,"TAG",3)) 00947 { 00948 fr->rdat.flags |= READER_ID3TAG; 00949 fr->metaflags |= MPG123_NEW_ID3; 00950 } 00951 } 00952 /* Switch reader to a buffered one, if allowed. */ 00953 else if(fr->p.flags & MPG123_SEEKBUFFER) 00954 { 00955 #ifdef NO_FEEDER 00956 error("Buffered readers not supported in this build."); 00957 fr->err = MPG123_MISSING_FEATURE; 00958 return -1; 00959 #else 00960 if (fr->rd == &readers[READER_STREAM]) 00961 { 00962 fr->rd = &readers[READER_BUF_STREAM]; 00963 fr->rdat.fullread = plain_fullread; 00964 } 00965 #ifndef NO_ICY 00966 else if(fr->rd == &readers[READER_ICY_STREAM]) 00967 { 00968 fr->rd = &readers[READER_BUF_ICY_STREAM]; 00969 fr->rdat.fullread = icy_fullread; 00970 } 00971 #endif 00972 else 00973 { 00974 if(NOQUIET) error("mpg123 Programmer's fault: invalid reader"); 00975 return -1; 00976 } 00977 bc_init(&fr->rdat.buffer); 00978 fr->rdat.filelen = 0; /* We carry the offset, but never know how big the stream is. */ 00979 fr->rdat.flags |= READER_BUFFERED; 00980 #endif /* NO_FEEDER */ 00981 } 00982 return 0; 00983 } 00984 00985 00986 void open_bad(mpg123_handle *mh) 00987 { 00988 #ifndef NO_ICY 00989 clear_icy(&mh->icy); 00990 #endif 00991 mh->rd = &bad_reader; 00992 mh->rdat.flags = 0; 00993 bc_init(&mh->rdat.buffer); 00994 } 00995 00996 int open_feed(mpg123_handle *fr) 00997 { 00998 debug("feed reader"); 00999 #ifdef NO_FEEDER 01000 error("Buffered readers not supported in this build."); 01001 fr->err = MPG123_MISSING_FEATURE; 01002 return -1; 01003 #else 01004 #ifndef NO_ICY 01005 if(fr->p.icy_interval > 0) 01006 { 01007 if(NOQUIET) error("Feed reader cannot do ICY parsing!"); 01008 01009 return -1; 01010 } 01011 clear_icy(&fr->icy); 01012 #endif 01013 fr->rd = &readers[READER_FEED]; 01014 fr->rdat.flags = 0; 01015 if(fr->rd->init(fr) < 0) return -1; 01016 return 0; 01017 #endif /* NO_FEEDER */ 01018 } 01019 01020 /* Final code common to open_stream and open_stream_handle. */ 01021 static int open_finish(mpg123_handle *fr) 01022 { 01023 #ifndef NO_ICY 01024 if(fr->p.icy_interval > 0) 01025 { 01026 debug("ICY reader"); 01027 fr->icy.interval = fr->p.icy_interval; 01028 fr->icy.next = fr->icy.interval; 01029 fr->rd = &readers[READER_ICY_STREAM]; 01030 } 01031 else 01032 #endif 01033 { 01034 fr->rd = &readers[READER_STREAM]; 01035 debug("stream reader"); 01036 } 01037 01038 if(fr->rd->init(fr) < 0) return -1; 01039 01040 return MPG123_OK; 01041 } 01042 01043 int open_stream(mpg123_handle *fr, const char *bs_filenam, int fd) 01044 { 01045 int filept_opened = 1; 01046 int filept; /* descriptor of opened file/stream */ 01047 01048 clear_icy(&fr->icy); /* can be done inside frame_clear ...? */ 01049 01050 if(!bs_filenam) /* no file to open, got a descriptor (stdin) */ 01051 { 01052 filept = fd; 01053 filept_opened = 0; /* and don't try to close it... */ 01054 } 01055 #ifndef O_BINARY 01056 #define O_BINARY (0) 01057 #endif 01058 else if((filept = compat_open(bs_filenam, O_RDONLY|O_BINARY)) < 0) /* a plain old file to open... */ 01059 { 01060 if(NOQUIET) error2("Cannot open file %s: %s", bs_filenam, strerror(errno)); 01061 fr->err = MPG123_BAD_FILE; 01062 return MPG123_ERR; /* error... */ 01063 } 01064 01065 /* now we have something behind filept and can init the reader */ 01066 fr->rdat.filelen = -1; 01067 fr->rdat.filept = filept; 01068 fr->rdat.flags = 0; 01069 if(filept_opened) fr->rdat.flags |= READER_FD_OPENED; 01070 01071 return open_finish(fr); 01072 } 01073 01074 int open_stream_handle(mpg123_handle *fr, void *iohandle) 01075 { 01076 clear_icy(&fr->icy); /* can be done inside frame_clear ...? */ 01077 fr->rdat.filelen = -1; 01078 fr->rdat.filept = -1; 01079 fr->rdat.iohandle = iohandle; 01080 fr->rdat.flags = 0; 01081 fr->rdat.flags |= READER_HANDLEIO; 01082 01083 return open_finish(fr); 01084 } 01085 01086 /* Wrappers for actual reading/seeking... I'm full of wrappers here. */ 01087 static off_t io_seek(struct reader_data *rdat, off_t offset, int whence) 01088 { 01089 if(rdat->flags & READER_HANDLEIO) 01090 { 01091 if(rdat->r_lseek_handle != NULL) 01092 { 01093 return rdat->r_lseek_handle(rdat->iohandle, offset, whence); 01094 } 01095 else return -1; 01096 } 01097 else 01098 return rdat->lseek(rdat->filept, offset, whence); 01099 } 01100 01101 static long io_read(struct reader_data *rdat, void *buf, size_t count) 01102 { 01103 if(rdat->flags & READER_HANDLEIO) 01104 { 01105 if(rdat->r_read_handle != NULL) 01106 { 01107 return rdat->r_read_handle(rdat->iohandle, buf, count); 01108 } 01109 else return -1; 01110 } 01111 else 01112 return rdat->read(rdat->filept, buf, count); 01113 } Generated on Fri May 25 2012 04:32:37 for ReactOS by
1.7.6.1
|