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