Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1905 | serge | 1 | /* TODO: Check all read calls (in loops, especially!) for return value 0 (EOF)! */ |
2 | |||
3 | /* |
||
4 | readers.c: reading input data |
||
5 | |||
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 |
||
9 | */ |
||
10 | |||
11 | #include "mpg123lib_intern.h" |
||
12 | #include |
||
13 | #include |
||
14 | #include |
||
15 | /* For select(), I need select.h according to POSIX 2001, else: sys/time.h sys/types.h unistd.h */ |
||
16 | /* Including these here although it works without on my Linux install... curious about _why_. */ |
||
17 | #ifdef HAVE_SYS_SELECT_H |
||
18 | #include |
||
19 | #endif |
||
20 | #ifdef HAVE_SYS_TIME_H |
||
21 | #include |
||
22 | #endif |
||
23 | #ifdef HAVE_SYS_TYPES_H |
||
24 | #include |
||
25 | #endif |
||
26 | #ifdef HAVE_UNISTD_H |
||
27 | #include |
||
28 | #endif |
||
29 | #ifdef _MSC_VER |
||
30 | #include |
||
31 | #endif |
||
32 | |||
33 | #include "debug.h" |
||
34 | |||
35 | static int default_init(mpg123_handle *fr); |
||
36 | static off_t get_fileinfo(mpg123_handle *); |
||
37 | static ssize_t posix_read(int fd, void *buf, size_t count){ return read(fd, buf, count); } |
||
38 | static off_t posix_lseek(int fd, off_t offset, int whence){ return lseek(fd, offset, whence); } |
||
39 | |||
40 | static ssize_t plain_fullread(mpg123_handle *fr,unsigned char *buf, ssize_t count); |
||
41 | |||
42 | #ifndef NO_FEEDER |
||
43 | /* Bufferchain methods. */ |
||
44 | static void bc_init(struct bufferchain *bc); |
||
45 | static void bc_reset(struct bufferchain *bc); |
||
46 | static int bc_append(struct bufferchain *bc, ssize_t size); |
||
47 | #if 0 |
||
48 | static void bc_drop(struct bufferchain *bc); |
||
49 | #endif |
||
50 | static int bc_add(struct bufferchain *bc, const unsigned char *data, ssize_t size); |
||
51 | static ssize_t bc_give(struct bufferchain *bc, unsigned char *out, ssize_t size); |
||
52 | static ssize_t bc_skip(struct bufferchain *bc, ssize_t count); |
||
53 | static ssize_t bc_seekback(struct bufferchain *bc, ssize_t count); |
||
54 | static void bc_forget(struct bufferchain *bc); |
||
55 | #else |
||
56 | #define bc_init(a) |
||
57 | #define bc_reset(a) |
||
58 | #endif |
||
59 | |||
60 | /* A normal read and a read with timeout. */ |
||
61 | static ssize_t plain_read(mpg123_handle *fr, void *buf, size_t count) |
||
62 | { |
||
63 | ssize_t ret = fr->rdat.read(fr->rdat.filept, buf, count); |
||
64 | if(VERBOSE3) debug2("read %li bytes of %li", (long)ret, (long)count); |
||
65 | return ret; |
||
66 | } |
||
67 | |||
68 | #ifndef NO_ICY |
||
69 | /* stream based operation with icy meta data*/ |
||
70 | static ssize_t icy_fullread(mpg123_handle *fr, unsigned char *buf, ssize_t count) |
||
71 | { |
||
72 | ssize_t ret,cnt; |
||
73 | cnt = 0; |
||
74 | if(fr->rdat.flags & READER_SEEKABLE) |
||
75 | { |
||
76 | if(NOQUIET) error("mpg123 programmer error: I don't do ICY on seekable streams."); |
||
77 | return -1; |
||
78 | } |
||
79 | /* |
||
80 | There used to be a check for expected file end here (length value or ID3 flag). |
||
81 | This is not needed: |
||
82 | 1. EOF is indicated by fdread returning zero bytes anyway. |
||
83 | 2. We get false positives of EOF for either files that grew or |
||
84 | 3. ... files that have ID3v1 tags in between (stream with intro). |
||
85 | */ |
||
86 | |||
87 | while(cnt < count) |
||
88 | { |
||
89 | /* all icy code is inside this if block, everything else is the plain fullread we know */ |
||
90 | /* debug1("read: %li left", (long) count-cnt); */ |
||
91 | if(fr->icy.next < count-cnt) |
||
92 | { |
||
93 | unsigned char temp_buff; |
||
94 | size_t meta_size; |
||
95 | ssize_t cut_pos; |
||
96 | |||
97 | /* we are near icy-metaint boundary, read up to the boundary */ |
||
98 | if(fr->icy.next > 0) |
||
99 | { |
||
100 | cut_pos = fr->icy.next; |
||
101 | ret = fr->rdat.fdread(fr,buf,cut_pos); |
||
102 | if(ret < 1) |
||
103 | { |
||
104 | if(ret == 0) break; /* Just EOF. */ |
||
105 | if(NOQUIET) error("icy boundary read"); |
||
106 | |||
107 | return READER_ERROR; |
||
108 | } |
||
109 | fr->rdat.filepos += ret; |
||
110 | cnt += ret; |
||
111 | fr->icy.next -= ret; |
||
112 | if(fr->icy.next > 0) |
||
113 | { |
||
114 | debug1("another try... still %li left", (long)fr->icy.next); |
||
115 | continue; |
||
116 | } |
||
117 | } |
||
118 | /* now off to read icy data */ |
||
119 | |||
120 | /* one byte icy-meta size (must be multiplied by 16 to get icy-meta length) */ |
||
121 | |||
122 | ret = fr->rdat.fdread(fr,&temp_buff,1); /* Getting one single byte hast to suceed. */ |
||
123 | if(ret < 0){ if(NOQUIET) error("reading icy size"); return READER_ERROR; } |
||
124 | if(ret == 0) break; |
||
125 | |||
126 | debug2("got meta-size byte: %u, at filepos %li", temp_buff, (long)fr->rdat.filepos ); |
||
127 | if(!(fr->rdat.flags & READER_BUFFERED)) fr->rdat.filepos += ret; /* 1... */ |
||
128 | |||
129 | if((meta_size = ((size_t) temp_buff) * 16)) |
||
130 | { |
||
131 | /* we have got some metadata */ |
||
132 | char *meta_buff; |
||
133 | meta_buff = malloc(meta_size+1); |
||
134 | if(meta_buff != NULL) |
||
135 | { |
||
136 | ssize_t left = meta_size; |
||
137 | while(left > 0) |
||
138 | { |
||
139 | ret = fr->rdat.fdread(fr,meta_buff+meta_size-left,left); |
||
140 | /* 0 is error here, too... there _must_ be the ICY data, the server promised! */ |
||
141 | if(ret < 1){ if(NOQUIET) error("reading icy-meta"); return READER_ERROR; } |
||
142 | left -= ret; |
||
143 | } |
||
144 | meta_buff[meta_size] = 0; /* string paranoia */ |
||
145 | if(!(fr->rdat.flags & READER_BUFFERED)) fr->rdat.filepos += ret; |
||
146 | |||
147 | if(fr->icy.data) free(fr->icy.data); |
||
148 | fr->icy.data = meta_buff; |
||
149 | fr->metaflags |= MPG123_NEW_ICY; |
||
150 | debug2("icy-meta: %s size: %d bytes", fr->icy.data, (int)meta_size); |
||
151 | } |
||
152 | else |
||
153 | { |
||
154 | if(NOQUIET) error1("cannot allocate memory for meta_buff (%lu bytes) ... trying to skip the metadata!", (unsigned long)meta_size); |
||
155 | fr->rd->skip_bytes(fr, meta_size); |
||
156 | } |
||
157 | } |
||
158 | fr->icy.next = fr->icy.interval; |
||
159 | } |
||
160 | |||
161 | ret = plain_fullread(fr, buf+cnt, count-cnt); |
||
162 | if(ret < 0){ if(NOQUIET) error1("reading the rest of %li", (long)(count-cnt)); return READER_ERROR; } |
||
163 | if(ret == 0) break; |
||
164 | |||
165 | cnt += ret; |
||
166 | fr->icy.next -= ret; |
||
167 | } |
||
168 | /* debug1("done reading, got %li", (long)cnt); */ |
||
169 | return cnt; |
||
170 | } |
||
171 | #else |
||
172 | #define icy_fullread NULL |
||
173 | #endif /* NO_ICY */ |
||
174 | |||
175 | /* stream based operation */ |
||
176 | static ssize_t plain_fullread(mpg123_handle *fr,unsigned char *buf, ssize_t count) |
||
177 | { |
||
178 | ssize_t ret,cnt=0; |
||
179 | |||
180 | /* |
||
181 | There used to be a check for expected file end here (length value or ID3 flag). |
||
182 | This is not needed: |
||
183 | 1. EOF is indicated by fdread returning zero bytes anyway. |
||
184 | 2. We get false positives of EOF for either files that grew or |
||
185 | 3. ... files that have ID3v1 tags in between (stream with intro). |
||
186 | */ |
||
187 | while(cnt < count) |
||
188 | { |
||
189 | ret = fr->rdat.fdread(fr,buf+cnt,count-cnt); |
||
190 | if(ret < 0) return READER_ERROR; |
||
191 | if(ret == 0) break; |
||
192 | if(!(fr->rdat.flags & READER_BUFFERED)) fr->rdat.filepos += ret; |
||
193 | cnt += ret; |
||
194 | } |
||
195 | return cnt; |
||
196 | } |
||
197 | |||
198 | static off_t stream_lseek(mpg123_handle *fr, off_t pos, int whence) |
||
199 | { |
||
200 | off_t ret; |
||
201 | ret = fr->rdat.lseek(fr->rdat.filept, pos, whence); |
||
202 | if (ret >= 0) fr->rdat.filepos = ret; |
||
203 | else |
||
204 | { |
||
205 | fr->err = MPG123_LSEEK_FAILED; |
||
206 | ret = READER_ERROR; /* not the original value */ |
||
207 | } |
||
208 | return ret; |
||
209 | } |
||
210 | |||
211 | static void stream_close(mpg123_handle *fr) |
||
212 | { |
||
213 | if(fr->rdat.flags & READER_FD_OPENED) close(fr->rdat.filept); |
||
214 | if(fr->rdat.flags & READER_BUFFERED) bc_reset(&fr->rdat.buffer); |
||
215 | } |
||
216 | |||
217 | static int stream_seek_frame(mpg123_handle *fr, off_t newframe) |
||
218 | { |
||
219 | debug2("seek_frame to %"OFF_P" (from %"OFF_P")", (off_p)newframe, (off_p)fr->num); |
||
220 | /* Seekable streams can go backwards and jump forwards. |
||
221 | Non-seekable streams still can go forward, just not jump. */ |
||
222 | if((fr->rdat.flags & READER_SEEKABLE) || (newframe >= fr->num)) |
||
223 | { |
||
224 | off_t preframe; /* a leading frame we jump to */ |
||
225 | off_t seek_to; /* the byte offset we want to reach */ |
||
226 | off_t to_skip; /* bytes to skip to get there (can be negative) */ |
||
227 | /* |
||
228 | now seek to nearest leading index position and read from there until newframe is reached. |
||
229 | We use skip_bytes, which handles seekable and non-seekable streams |
||
230 | (the latter only for positive offset, which we ensured before entering here). |
||
231 | */ |
||
232 | seek_to = frame_index_find(fr, newframe, &preframe); |
||
233 | /* No need to seek to index position if we are closer already. |
||
234 | But I am picky about fr->num == newframe, play safe by reading the frame again. |
||
235 | If you think that's stupid, don't call a seek to the current frame. */ |
||
236 | if(fr->num >= newframe || fr->num < preframe) |
||
237 | { |
||
238 | to_skip = seek_to - fr->rd->tell(fr); |
||
239 | if(fr->rd->skip_bytes(fr, to_skip) != seek_to) |
||
240 | return READER_ERROR; |
||
241 | |||
242 | debug2("going to %lu; just got %lu", (long unsigned)newframe, (long unsigned)preframe); |
||
243 | fr->num = preframe-1; /* Watch out! I am going to read preframe... fr->num should indicate the frame before! */ |
||
244 | } |
||
245 | while(fr->num < newframe) |
||
246 | { |
||
247 | /* try to be non-fatal now... frameNum only gets advanced on success anyway */ |
||
248 | if(!read_frame(fr)) break; |
||
249 | } |
||
250 | /* Now the wanted frame should be ready for decoding. */ |
||
251 | debug1("arrived at %lu", (long unsigned)fr->num); |
||
252 | |||
253 | return MPG123_OK; |
||
254 | } |
||
255 | else |
||
256 | { |
||
257 | fr->err = MPG123_NO_SEEK; |
||
258 | return READER_ERROR; /* invalid, no seek happened */ |
||
259 | } |
||
260 | } |
||
261 | |||
262 | /* return FALSE on error, TRUE on success, READER_MORE on occasion */ |
||
263 | static int generic_head_read(mpg123_handle *fr,unsigned long *newhead) |
||
264 | { |
||
265 | unsigned char hbuf[4]; |
||
266 | int ret = fr->rd->fullread(fr,hbuf,4); |
||
267 | if(ret == READER_MORE) return ret; |
||
268 | if(ret != 4) return FALSE; |
||
269 | |||
270 | *newhead = ((unsigned long) hbuf[0] << 24) | |
||
271 | ((unsigned long) hbuf[1] << 16) | |
||
272 | ((unsigned long) hbuf[2] << 8) | |
||
273 | (unsigned long) hbuf[3]; |
||
274 | |||
275 | return TRUE; |
||
276 | } |
||
277 | |||
278 | /* return FALSE on error, TRUE on success, READER_MORE on occasion */ |
||
279 | static int generic_head_shift(mpg123_handle *fr,unsigned long *head) |
||
280 | { |
||
281 | unsigned char hbuf; |
||
282 | int ret = fr->rd->fullread(fr,&hbuf,1); |
||
283 | if(ret == READER_MORE) return ret; |
||
284 | if(ret != 1) return FALSE; |
||
285 | |||
286 | *head <<= 8; |
||
287 | *head |= hbuf; |
||
288 | *head &= 0xffffffff; |
||
289 | return TRUE; |
||
290 | } |
||
291 | |||
292 | /* returns reached position... negative ones are bad... */ |
||
293 | static off_t stream_skip_bytes(mpg123_handle *fr,off_t len) |
||
294 | { |
||
295 | if(fr->rdat.flags & READER_SEEKABLE) |
||
296 | { |
||
297 | off_t ret = stream_lseek(fr, len, SEEK_CUR); |
||
298 | return (ret < 0) ? READER_ERROR : ret; |
||
299 | } |
||
300 | else if(len >= 0) |
||
301 | { |
||
302 | unsigned char buf[1024]; /* ThOr: Compaq cxx complained and it makes sense to me... or should one do a cast? What for? */ |
||
303 | ssize_t ret; |
||
304 | while (len > 0) |
||
305 | { |
||
306 | ssize_t num = len < (off_t)sizeof(buf) ? (ssize_t)len : (ssize_t)sizeof(buf); |
||
307 | ret = fr->rd->fullread(fr, buf, num); |
||
308 | if (ret < 0) return ret; |
||
309 | else if(ret == 0) break; /* EOF... an error? interface defined to tell the actual position... */ |
||
310 | len -= ret; |
||
311 | } |
||
312 | return fr->rd->tell(fr); |
||
313 | } |
||
314 | else if(fr->rdat.flags & READER_BUFFERED) |
||
315 | { /* Perhaps we _can_ go a bit back. */ |
||
316 | if(fr->rdat.buffer.pos >= -len) |
||
317 | { |
||
318 | fr->rdat.buffer.pos += len; |
||
319 | return fr->rd->tell(fr); |
||
320 | } |
||
321 | else |
||
322 | { |
||
323 | fr->err = MPG123_NO_SEEK; |
||
324 | return READER_ERROR; |
||
325 | } |
||
326 | } |
||
327 | else |
||
328 | { |
||
329 | fr->err = MPG123_NO_SEEK; |
||
330 | return READER_ERROR; |
||
331 | } |
||
332 | } |
||
333 | |||
334 | /* Return 0 on success... */ |
||
335 | static int stream_back_bytes(mpg123_handle *fr, off_t bytes) |
||
336 | { |
||
337 | off_t want = fr->rd->tell(fr)-bytes; |
||
338 | if(want < 0) return READER_ERROR; |
||
339 | if(stream_skip_bytes(fr,-bytes) != want) return READER_ERROR; |
||
340 | |||
341 | return 0; |
||
342 | } |
||
343 | |||
344 | |||
345 | /* returns size on success... */ |
||
346 | static int generic_read_frame_body(mpg123_handle *fr,unsigned char *buf, int size) |
||
347 | { |
||
348 | long l; |
||
349 | |||
350 | if((l=fr->rd->fullread(fr,buf,size)) != size) |
||
351 | { |
||
352 | long ll = l; |
||
353 | if(ll <= 0) ll = 0; |
||
354 | |||
355 | /* This allows partial frames at the end... do we really want to pad and decode these?! */ |
||
356 | memset(buf+ll,0,size-ll); |
||
357 | } |
||
358 | return l; |
||
359 | } |
||
360 | |||
361 | static off_t generic_tell(mpg123_handle *fr) |
||
362 | { |
||
363 | if(fr->rdat.flags & READER_BUFFERED) |
||
364 | fr->rdat.filepos = fr->rdat.buffer.fileoff+fr->rdat.buffer.pos; |
||
365 | |||
366 | return fr->rdat.filepos; |
||
367 | } |
||
368 | |||
369 | /* This does not (fully) work for non-seekable streams... You have to check for that flag, pal! */ |
||
370 | static void stream_rewind(mpg123_handle *fr) |
||
371 | { |
||
372 | if(fr->rdat.flags & READER_SEEKABLE) |
||
373 | fr->rdat.buffer.fileoff = fr->rdat.filepos = stream_lseek(fr,0,SEEK_SET); |
||
374 | if(fr->rdat.flags & READER_BUFFERED) |
||
375 | { |
||
376 | fr->rdat.buffer.pos = 0; |
||
377 | fr->rdat.buffer.firstpos = 0; |
||
378 | fr->rdat.filepos = fr->rdat.buffer.fileoff; |
||
379 | } |
||
380 | } |
||
381 | |||
382 | /* |
||
383 | * returns length of a file (if filept points to a file) |
||
384 | * reads the last 128 bytes information into buffer |
||
385 | * ... that is not totally safe... |
||
386 | */ |
||
387 | |||
388 | static off_t get_fileinfo(mpg123_handle *fr) |
||
389 | { |
||
390 | off_t len; |
||
391 | |||
392 | if((len=fr->rdat.lseek(fr->rdat.filept,0,SEEK_END)) < 0) return -1; |
||
393 | |||
394 | if(fr->rdat.lseek(fr->rdat.filept,-128,SEEK_END) < 0) return -1; |
||
395 | |||
396 | if(fr->rd->fullread(fr,(unsigned char *)fr->id3buf,128) != 128) return -1; |
||
397 | |||
398 | if(!strncmp((char*)fr->id3buf,"TAG",3)) len -= 128; |
||
399 | |||
400 | if(fr->rdat.lseek(fr->rdat.filept,0,SEEK_SET) < 0) return -1; |
||
401 | |||
402 | if(len <= 0) return -1; |
||
403 | |||
404 | return len; |
||
405 | } |
||
406 | |||
407 | #ifndef NO_FEEDER |
||
408 | /* Methods for the buffer chain, mainly used for feed reader, but not just that. */ |
||
409 | |||
410 | static void bc_init(struct bufferchain *bc) |
||
411 | { |
||
412 | bc->first = NULL; |
||
413 | bc->last = bc->first; |
||
414 | bc->size = 0; |
||
415 | bc->pos = 0; |
||
416 | bc->firstpos = 0; |
||
417 | bc->fileoff = 0; |
||
418 | } |
||
419 | |||
420 | static void bc_reset(struct bufferchain *bc) |
||
421 | { |
||
422 | /* free the buffer chain */ |
||
423 | struct buffy *b = bc->first; |
||
424 | while(b != NULL) |
||
425 | { |
||
426 | struct buffy *n = b->next; |
||
427 | free(b->data); |
||
428 | free(b); |
||
429 | b = n; |
||
430 | } |
||
431 | bc_init(bc); |
||
432 | } |
||
433 | |||
434 | /* Create a new buffy at the end to be filled. */ |
||
435 | static int bc_append(struct bufferchain *bc, ssize_t size) |
||
436 | { |
||
437 | struct buffy *newbuf; |
||
438 | if(size < 1) return -1; |
||
439 | |||
440 | newbuf = malloc(sizeof(struct buffy)); |
||
441 | if(newbuf == NULL) return -2; |
||
442 | |||
443 | newbuf->data = malloc(size); |
||
444 | if(newbuf->data == NULL) |
||
445 | { |
||
446 | free(newbuf); |
||
447 | return -3; |
||
448 | } |
||
449 | newbuf->size = size; |
||
450 | newbuf->next = NULL; |
||
451 | if(bc->last != NULL) bc->last->next = newbuf; |
||
452 | else if(bc->first == NULL) bc->first = newbuf; |
||
453 | |||
454 | bc->last = newbuf; |
||
455 | bc->size += size; |
||
456 | return 0; |
||
457 | } |
||
458 | |||
459 | |||
460 | /* Append a new buffer and copy content to it. */ |
||
461 | static int bc_add(struct bufferchain *bc, const unsigned char *data, ssize_t size) |
||
462 | { |
||
463 | int ret = 0; |
||
464 | if((ret = bc_append(bc, size)) == 0) |
||
465 | memcpy(bc->last->data, data, size); |
||
466 | |||
467 | return ret; |
||
468 | } |
||
469 | |||
470 | /* Give some data, advancing position but not forgetting yet. */ |
||
471 | static ssize_t bc_give(struct bufferchain *bc, unsigned char *out, ssize_t size) |
||
472 | { |
||
473 | struct buffy *b = bc->first; |
||
474 | ssize_t gotcount = 0; |
||
475 | ssize_t offset = 0; |
||
476 | if(bc->size - bc->pos < size) |
||
477 | { |
||
478 | debug3("hit end, back to beginning (%li - %li < %li)", (long)bc->size, (long)bc->pos, (long)size); |
||
479 | /* go back to firstpos, undo the previous reads */ |
||
480 | bc->pos = bc->firstpos; |
||
481 | return READER_MORE; |
||
482 | } |
||
483 | /* find the current buffer */ |
||
484 | while(b != NULL && (offset + b->size) <= bc->pos) |
||
485 | { |
||
486 | offset += b->size; |
||
487 | b = b->next; |
||
488 | } |
||
489 | /* now start copying from there */ |
||
490 | while(gotcount < size && (b != NULL)) |
||
491 | { |
||
492 | ssize_t loff = bc->pos - offset; |
||
493 | ssize_t chunk = size - gotcount; /* amount of bytes to get from here... */ |
||
494 | if(chunk > b->size - loff) chunk = b->size - loff; |
||
495 | |||
496 | #ifdef EXTRA_DEBUG |
||
497 | debug3("copying %liB from %p+%li",(long)chunk, b->data, (long)loff); */ |
||
498 | #endif |
||
499 | |||
500 | memcpy(out+gotcount, b->data+loff, chunk); |
||
501 | gotcount += chunk; |
||
502 | bc->pos += chunk; |
||
503 | offset += b->size; |
||
504 | b = b->next; |
||
505 | } |
||
506 | #ifdef EXTRA_DEBUG |
||
507 | debug2("got %li bytes, pos advanced to %li", (long)gotcount, (long)bc->pos); |
||
508 | #endif |
||
509 | |||
510 | return gotcount; |
||
511 | } |
||
512 | |||
513 | /* Skip some bytes and return the new position. |
||
514 | The buffers are still there, just the read pointer is moved! */ |
||
515 | static ssize_t bc_skip(struct bufferchain *bc, ssize_t count) |
||
516 | { |
||
517 | if(count >= 0) |
||
518 | { |
||
519 | if(bc->size - bc->pos < count) return READER_MORE; |
||
520 | else return bc->pos += count; |
||
521 | } |
||
522 | else return READER_ERROR; |
||
523 | } |
||
524 | |||
525 | static ssize_t bc_seekback(struct bufferchain *bc, ssize_t count) |
||
526 | { |
||
527 | if(count >= 0 && count <= bc->pos) return bc->pos -= count; |
||
528 | else return READER_ERROR; |
||
529 | } |
||
530 | |||
531 | /* Throw away buffies that we passed. */ |
||
532 | static void bc_forget(struct bufferchain *bc) |
||
533 | { |
||
534 | struct buffy *b = bc->first; |
||
535 | /* free all buffers that are def'n'tly outdated */ |
||
536 | /* we have buffers until filepos... delete all buffers fully below it */ |
||
537 | #ifdef EXTRA_DEBUG |
||
538 | if(b) debug2("bc_forget: block %lu pos %lu", (unsigned long)b->size, (unsigned long)bc->pos); |
||
539 | else debug("forget with nothing there!"); |
||
540 | #endif |
||
541 | while(b != NULL && bc->pos >= b->size) |
||
542 | { |
||
543 | struct buffy *n = b->next; /* != NULL or this is indeed the end and the last cycle anyway */ |
||
544 | if(n == NULL) bc->last = NULL; /* Going to delete the last buffy... */ |
||
545 | bc->fileoff += b->size; |
||
546 | bc->pos -= b->size; |
||
547 | bc->size -= b->size; |
||
548 | #ifdef EXTRA_DEBUG |
||
549 | 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); |
||
550 | #endif |
||
551 | free(b->data); |
||
552 | free(b); |
||
553 | b = n; |
||
554 | } |
||
555 | bc->first = b; |
||
556 | bc->firstpos = bc->pos; |
||
557 | } |
||
558 | |||
559 | /* reader for input via manually provided buffers */ |
||
560 | |||
561 | static int feed_init(mpg123_handle *fr) |
||
562 | { |
||
563 | bc_init(&fr->rdat.buffer); |
||
564 | fr->rdat.filelen = 0; |
||
565 | fr->rdat.filepos = 0; |
||
566 | fr->rdat.flags |= READER_BUFFERED; |
||
567 | return 0; |
||
568 | } |
||
569 | |||
570 | /* externally called function, returns 0 on success, -1 on error */ |
||
571 | int feed_more(mpg123_handle *fr, const unsigned char *in, long count) |
||
572 | { |
||
573 | int ret = 0; |
||
574 | if(VERBOSE3) debug("feed_more"); |
||
575 | if((ret = bc_add(&fr->rdat.buffer, in, count)) != 0) |
||
576 | { |
||
577 | ret = READER_ERROR; |
||
578 | if(NOQUIET) error1("Failed to add buffer, return: %i", ret); |
||
579 | } |
||
580 | else /* Not talking about filelen... that stays at 0. */ |
||
581 | |||
582 | if(VERBOSE3) debug3("feed_more: %p %luB bufsize=%lu", fr->rdat.buffer.last->data, |
||
583 | (unsigned long)fr->rdat.buffer.last->size, (unsigned long)fr->rdat.buffer.size); |
||
584 | return ret; |
||
585 | } |
||
586 | |||
587 | static ssize_t feed_read(mpg123_handle *fr, unsigned char *out, ssize_t count) |
||
588 | { |
||
589 | ssize_t gotcount = bc_give(&fr->rdat.buffer, out, count); |
||
590 | if(gotcount >= 0 && gotcount != count) return READER_ERROR; |
||
591 | else return gotcount; |
||
592 | } |
||
593 | |||
594 | /* returns reached position... negative ones are bad... */ |
||
595 | static off_t feed_skip_bytes(mpg123_handle *fr,off_t len) |
||
596 | { |
||
597 | return fr->rdat.buffer.fileoff+bc_skip(&fr->rdat.buffer, (ssize_t)len); |
||
598 | } |
||
599 | |||
600 | static int feed_back_bytes(mpg123_handle *fr, off_t bytes) |
||
601 | { |
||
602 | if(bytes >=0) |
||
603 | return bc_seekback(&fr->rdat.buffer, (ssize_t)bytes) >= 0 ? 0 : READER_ERROR; |
||
604 | else |
||
605 | return feed_skip_bytes(fr, -bytes) >= 0 ? 0 : READER_ERROR; |
||
606 | } |
||
607 | |||
608 | static int feed_seek_frame(mpg123_handle *fr, off_t num){ return READER_ERROR; } |
||
609 | |||
610 | /* Not just for feed reader, also for self-feeding buffered reader. */ |
||
611 | static void buffered_forget(mpg123_handle *fr) |
||
612 | { |
||
613 | bc_forget(&fr->rdat.buffer); |
||
614 | fr->rdat.filepos = fr->rdat.buffer.fileoff + fr->rdat.buffer.pos; |
||
615 | } |
||
616 | |||
617 | off_t feed_set_pos(mpg123_handle *fr, off_t pos) |
||
618 | { |
||
619 | struct bufferchain *bc = &fr->rdat.buffer; |
||
620 | if(pos >= bc->fileoff && pos-bc->fileoff < bc->size) |
||
621 | { /* We have the position! */ |
||
622 | bc->pos = (ssize_t)(pos - bc->fileoff); |
||
623 | return pos+bc->size; /* Next input after end of buffer... */ |
||
624 | } |
||
625 | else |
||
626 | { /* I expect to get the specific position on next feed. Forget what I have now. */ |
||
627 | bc_reset(bc); |
||
628 | bc->fileoff = pos; |
||
629 | return pos; /* Next input from exactly that position. */ |
||
630 | } |
||
631 | } |
||
632 | |||
633 | /* The specific stuff for buffered stream reader. */ |
||
634 | |||
635 | /* Let's work in nice 4K blocks, that may be nicely reusable (by malloc(), even). */ |
||
636 | #define BUFFBLOCK 4096 |
||
637 | static ssize_t buffered_fullread(mpg123_handle *fr, unsigned char *out, ssize_t count) |
||
638 | { |
||
639 | struct bufferchain *bc = &fr->rdat.buffer; |
||
640 | ssize_t gotcount; |
||
641 | if(bc->size - bc->pos < count) |
||
642 | { /* Add more stuff to buffer. If hitting end of file, adjust count. */ |
||
643 | unsigned char readbuf[BUFFBLOCK]; |
||
644 | ssize_t need = count - (bc->size-bc->pos); |
||
645 | while(need>0) |
||
646 | { |
||
647 | int ret; |
||
648 | ssize_t got = fr->rdat.fullread(fr, readbuf, BUFFBLOCK); |
||
649 | if(got < 0) |
||
650 | { |
||
651 | if(NOQUIET) error("buffer reading"); |
||
652 | return READER_ERROR; |
||
653 | } |
||
654 | |||
655 | if(VERBOSE3) debug1("buffered_fullread: buffering %li bytes from stream (if > 0)", (long)got); |
||
656 | if(got > 0 && (ret=bc_add(bc, readbuf, got)) != 0) |
||
657 | { |
||
658 | if(NOQUIET) error1("unable to add to chain, return: %i", ret); |
||
659 | return READER_ERROR; |
||
660 | } |
||
661 | |||
662 | need -= got; /* May underflow here... */ |
||
663 | if(got < BUFFBLOCK) /* That naturally catches got == 0, too. */ |
||
664 | { |
||
665 | if(VERBOSE3) fprintf(stderr, "Note: Input data end.\n"); |
||
666 | break; /* End. */ |
||
667 | } |
||
668 | } |
||
669 | if(bc->size - bc->pos < count) |
||
670 | count = bc->size - bc->pos; /* We want only what we got. */ |
||
671 | } |
||
672 | gotcount = bc_give(bc, out, count); |
||
673 | |||
674 | if(VERBOSE3) debug2("wanted %li, got %li", (long)count, (long)gotcount); |
||
675 | |||
676 | if(gotcount != count){ if(NOQUIET) error("gotcount != count"); return READER_ERROR; } |
||
677 | else return gotcount; |
||
678 | } |
||
679 | #else |
||
680 | int feed_more(mpg123_handle *fr, const unsigned char *in, long count) |
||
681 | { |
||
682 | fr->err = MPG123_MISSING_FEATURE; |
||
683 | return -1; |
||
684 | } |
||
685 | off_t feed_set_pos(mpg123_handle *fr, off_t pos) |
||
686 | { |
||
687 | fr->err = MPG123_MISSING_FEATURE; |
||
688 | return -1; |
||
689 | } |
||
690 | #endif /* NO_FEEDER */ |
||
691 | |||
692 | /***************************************************************** |
||
693 | * read frame helper |
||
694 | */ |
||
695 | |||
696 | #define bugger_off { mh->err = MPG123_NO_READER; return MPG123_ERR; } |
||
697 | int bad_init(mpg123_handle *mh) bugger_off |
||
698 | void bad_close(mpg123_handle *mh){} |
||
699 | ssize_t bad_fullread(mpg123_handle *mh, unsigned char *data, ssize_t count) bugger_off |
||
700 | int bad_head_read(mpg123_handle *mh, unsigned long *newhead) bugger_off |
||
701 | int bad_head_shift(mpg123_handle *mh, unsigned long *head) bugger_off |
||
702 | off_t bad_skip_bytes(mpg123_handle *mh, off_t len) bugger_off |
||
703 | int bad_read_frame_body(mpg123_handle *mh, unsigned char *data, int size) bugger_off |
||
704 | int bad_back_bytes(mpg123_handle *mh, off_t bytes) bugger_off |
||
705 | int bad_seek_frame(mpg123_handle *mh, off_t num) bugger_off |
||
706 | off_t bad_tell(mpg123_handle *mh) bugger_off |
||
707 | void bad_rewind(mpg123_handle *mh){} |
||
708 | #undef bugger_off |
||
709 | |||
710 | #define READER_STREAM 0 |
||
711 | #define READER_ICY_STREAM 1 |
||
712 | #define READER_FEED 2 |
||
713 | #define READER_BUF_STREAM 3 |
||
714 | #define READER_BUF_ICY_STREAM 4 |
||
715 | struct reader readers[] = |
||
716 | { |
||
717 | { /* READER_STREAM */ |
||
718 | default_init, |
||
719 | stream_close, |
||
720 | plain_fullread, |
||
721 | generic_head_read, |
||
722 | generic_head_shift, |
||
723 | stream_skip_bytes, |
||
724 | generic_read_frame_body, |
||
725 | stream_back_bytes, |
||
726 | stream_seek_frame, |
||
727 | generic_tell, |
||
728 | stream_rewind, |
||
729 | NULL |
||
730 | } , |
||
731 | { /* READER_ICY_STREAM */ |
||
732 | default_init, |
||
733 | stream_close, |
||
734 | icy_fullread, |
||
735 | generic_head_read, |
||
736 | generic_head_shift, |
||
737 | stream_skip_bytes, |
||
738 | generic_read_frame_body, |
||
739 | stream_back_bytes, |
||
740 | stream_seek_frame, |
||
741 | generic_tell, |
||
742 | stream_rewind, |
||
743 | NULL |
||
744 | }, |
||
745 | #ifdef NO_FEEDER |
||
746 | #define feed_init NULL |
||
747 | #define feed_read NULL |
||
748 | #define buffered_fullread NULL |
||
749 | #define feed_seek_frame NULL |
||
750 | #define feed_back_bytes NULL |
||
751 | #define feed_skip_bytes NULL |
||
752 | #define buffered_forget NULL |
||
753 | #endif |
||
754 | { /* READER_FEED */ |
||
755 | feed_init, |
||
756 | stream_close, |
||
757 | feed_read, |
||
758 | generic_head_read, |
||
759 | generic_head_shift, |
||
760 | feed_skip_bytes, |
||
761 | generic_read_frame_body, |
||
762 | feed_back_bytes, |
||
763 | feed_seek_frame, |
||
764 | generic_tell, |
||
765 | stream_rewind, |
||
766 | buffered_forget |
||
767 | }, |
||
768 | { /* READER_BUF_STREAM */ |
||
769 | default_init, |
||
770 | stream_close, |
||
771 | buffered_fullread, |
||
772 | generic_head_read, |
||
773 | generic_head_shift, |
||
774 | stream_skip_bytes, |
||
775 | generic_read_frame_body, |
||
776 | stream_back_bytes, |
||
777 | stream_seek_frame, |
||
778 | generic_tell, |
||
779 | stream_rewind, |
||
780 | buffered_forget |
||
781 | } , |
||
782 | { /* READER_BUF_ICY_STREAM */ |
||
783 | default_init, |
||
784 | stream_close, |
||
785 | buffered_fullread, |
||
786 | generic_head_read, |
||
787 | generic_head_shift, |
||
788 | stream_skip_bytes, |
||
789 | generic_read_frame_body, |
||
790 | stream_back_bytes, |
||
791 | stream_seek_frame, |
||
792 | generic_tell, |
||
793 | stream_rewind, |
||
794 | buffered_forget |
||
795 | }, |
||
796 | #ifdef READ_SYSTEM |
||
797 | ,{ |
||
798 | system_init, |
||
799 | NULL, /* filled in by system_init() */ |
||
800 | fullread, |
||
801 | NULL, |
||
802 | NULL, |
||
803 | NULL, |
||
804 | NULL, |
||
805 | NULL, |
||
806 | NULL, |
||
807 | NULL, |
||
808 | NULL, |
||
809 | NULL, |
||
810 | } |
||
811 | #endif |
||
812 | }; |
||
813 | |||
814 | struct reader bad_reader = |
||
815 | { |
||
816 | bad_init, |
||
817 | bad_close, |
||
818 | bad_fullread, |
||
819 | bad_head_read, |
||
820 | bad_head_shift, |
||
821 | bad_skip_bytes, |
||
822 | bad_read_frame_body, |
||
823 | bad_back_bytes, |
||
824 | bad_seek_frame, |
||
825 | bad_tell, |
||
826 | bad_rewind, |
||
827 | NULL |
||
828 | }; |
||
829 | |||
830 | static int default_init(mpg123_handle *fr) |
||
831 | { |
||
832 | fr->rdat.fdread = plain_read; |
||
833 | |||
834 | fr->rdat.read = fr->rdat.r_read != NULL ? fr->rdat.r_read : posix_read; |
||
835 | fr->rdat.lseek = fr->rdat.r_lseek != NULL ? fr->rdat.r_lseek : posix_lseek; |
||
836 | fr->rdat.filelen = get_fileinfo(fr); |
||
837 | fr->rdat.filepos = 0; |
||
838 | if(fr->rdat.filelen >= 0) |
||
839 | { |
||
840 | fr->rdat.flags |= READER_SEEKABLE; |
||
841 | if(!strncmp((char*)fr->id3buf,"TAG",3)) |
||
842 | { |
||
843 | fr->rdat.flags |= READER_ID3TAG; |
||
844 | fr->metaflags |= MPG123_NEW_ID3; |
||
845 | } |
||
846 | } |
||
847 | /* Switch reader to a buffered one, if allowed. */ |
||
848 | else if(fr->p.flags & MPG123_SEEKBUFFER) |
||
849 | { |
||
850 | #ifdef NO_FEEDER |
||
851 | error("Buffered readers not supported in this build."); |
||
852 | fr->err = MPG123_MISSING_FEATURE; |
||
853 | return -1; |
||
854 | #else |
||
855 | if (fr->rd == &readers[READER_STREAM]) |
||
856 | { |
||
857 | fr->rd = &readers[READER_BUF_STREAM]; |
||
858 | fr->rdat.fullread = plain_fullread; |
||
859 | } |
||
860 | #ifndef NO_ICY |
||
861 | else if(fr->rd == &readers[READER_ICY_STREAM]) |
||
862 | { |
||
863 | fr->rd = &readers[READER_BUF_ICY_STREAM]; |
||
864 | fr->rdat.fullread = icy_fullread; |
||
865 | } |
||
866 | #endif |
||
867 | else |
||
868 | { |
||
869 | if(NOQUIET) error("mpg123 Programmer's fault: invalid reader"); |
||
870 | return -1; |
||
871 | } |
||
872 | bc_init(&fr->rdat.buffer); |
||
873 | fr->rdat.filelen = 0; /* We carry the offset, but never know how big the stream is. */ |
||
874 | fr->rdat.flags |= READER_BUFFERED; |
||
875 | #endif /* NO_FEEDER */ |
||
876 | } |
||
877 | return 0; |
||
878 | } |
||
879 | |||
880 | |||
881 | void open_bad(mpg123_handle *mh) |
||
882 | { |
||
883 | #ifndef NO_ICY |
||
884 | clear_icy(&mh->icy); |
||
885 | #endif |
||
886 | mh->rd = &bad_reader; |
||
887 | mh->rdat.flags = 0; |
||
888 | bc_init(&mh->rdat.buffer); |
||
889 | } |
||
890 | |||
891 | int open_feed(mpg123_handle *fr) |
||
892 | { |
||
893 | debug("feed reader"); |
||
894 | #ifdef NO_FEEDER |
||
895 | error("Buffered readers not supported in this build."); |
||
896 | fr->err = MPG123_MISSING_FEATURE; |
||
897 | return -1; |
||
898 | #else |
||
899 | #ifndef NO_ICY |
||
900 | if(fr->p.icy_interval > 0) |
||
901 | { |
||
902 | if(NOQUIET) error("Feed reader cannot do ICY parsing!"); |
||
903 | |||
904 | return -1; |
||
905 | } |
||
906 | clear_icy(&fr->icy); |
||
907 | #endif |
||
908 | fr->rd = &readers[READER_FEED]; |
||
909 | fr->rdat.flags = 0; |
||
910 | if(fr->rd->init(fr) < 0) return -1; |
||
911 | return 0; |
||
912 | #endif /* NO_FEEDER */ |
||
913 | } |
||
914 | |||
915 | int open_stream(mpg123_handle *fr, const char *bs_filenam, int fd) |
||
916 | { |
||
917 | int filept_opened = 1; |
||
918 | int filept; /* descriptor of opened file/stream */ |
||
919 | |||
920 | clear_icy(&fr->icy); /* can be done inside frame_clear ...? */ |
||
921 | if(!bs_filenam) /* no file to open, got a descriptor (stdin) */ |
||
922 | { |
||
923 | filept = fd; |
||
924 | filept_opened = 0; /* and don't try to close it... */ |
||
925 | } |
||
926 | #ifndef O_BINARY |
||
927 | #define O_BINARY (0) |
||
928 | #endif |
||
929 | else if((filept = open(bs_filenam, O_RDONLY|O_BINARY)) < 0) /* a plain old file to open... */ |
||
930 | { |
||
931 | if(NOQUIET) error2("Cannot open file %s: %s", bs_filenam, strerror(errno)); |
||
932 | fr->err = MPG123_BAD_FILE; |
||
933 | return MPG123_ERR; /* error... */ |
||
934 | } |
||
935 | |||
936 | /* now we have something behind filept and can init the reader */ |
||
937 | fr->rdat.filelen = -1; |
||
938 | fr->rdat.filept = filept; |
||
939 | fr->rdat.flags = 0; |
||
940 | if(filept_opened) fr->rdat.flags |= READER_FD_OPENED; |
||
941 | |||
942 | #ifndef NO_ICY |
||
943 | if(fr->p.icy_interval > 0) |
||
944 | { |
||
945 | debug("ICY reader"); |
||
946 | fr->icy.interval = fr->p.icy_interval; |
||
947 | fr->icy.next = fr->icy.interval; |
||
948 | fr->rd = &readers[READER_ICY_STREAM]; |
||
949 | } |
||
950 | else |
||
951 | #endif |
||
952 | { |
||
953 | fr->rd = &readers[READER_STREAM]; |
||
954 | debug("stream reader"); |
||
955 | } |
||
956 | |||
957 | if(fr->rd->init(fr) < 0) return -1; |
||
958 | |||
959 | return MPG123_OK; |
||
960 | }>>>>>>>>=>>>=>>>>=>>>>=>>>>>=><=>><>><>><>>>>>>>>>>> |