Subversion Repositories Kolibri OS

Rev

Rev 1905 | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1905 Rev 3960
Line 10... Line 10...
10
 
10
 
11
#include "mpg123lib_intern.h"
11
#include "mpg123lib_intern.h"
12
#include 
12
#include 
13
#include 
13
#include 
14
#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_. */
15
/* 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). */
17
#ifdef HAVE_SYS_SELECT_H
16
#ifdef HAVE_SYS_SELECT_H
18
#include 
17
#include 
19
#endif
18
#endif
20
#ifdef HAVE_SYS_TIME_H
19
#ifdef HAVE_SYS_TIME_H
21
#include 
20
#include 
22
#endif
-
 
23
#ifdef HAVE_SYS_TYPES_H
-
 
24
#include 
-
 
25
#endif
-
 
26
#ifdef HAVE_UNISTD_H
-
 
27
#include 
-
 
28
#endif
21
#endif
29
#ifdef _MSC_VER
22
#ifdef _MSC_VER
30
#include 
23
#include 
Line -... Line 24...
-
 
24
#endif
31
#endif
25
 
Line 32... Line 26...
32
 
26
#include "compat.h"
33
#include "debug.h"
27
#include "debug.h"
34
 
28
 
35
static int default_init(mpg123_handle *fr);
29
static int default_init(mpg123_handle *fr);
-
 
30
static off_t get_fileinfo(mpg123_handle *);
Line 36... Line 31...
36
static off_t get_fileinfo(mpg123_handle *);
31
static ssize_t posix_read(int fd, void *buf, size_t count){ return read(fd, buf, count); }
Line -... Line 32...
-
 
32
static off_t   posix_lseek(int fd, off_t offset, int whence){ return lseek(fd, offset, whence); }
-
 
33
static off_t     nix_lseek(int fd, off_t offset, int whence){ return -1; }
-
 
34
 
-
 
35
static ssize_t plain_fullread(mpg123_handle *fr,unsigned char *buf, ssize_t count);
37
static ssize_t posix_read(int fd, void *buf, size_t count){ return read(fd, buf, count); }
36
 
38
static off_t   posix_lseek(int fd, off_t offset, int whence){ return lseek(fd, offset, whence); }
37
/* Wrapper to decide between descriptor-based and external handle-based I/O. */
39
 
38
static off_t io_seek(struct reader_data *rdat, off_t offset, int whence);
40
static ssize_t plain_fullread(mpg123_handle *fr,unsigned char *buf, ssize_t count);
39
static ssize_t io_read(struct reader_data *rdat, void *buf, size_t count);
41
 
40
 
Line 50... Line 49...
50
static int bc_add(struct bufferchain *bc, const unsigned char *data, ssize_t size);
49
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);
50
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);
51
static ssize_t bc_skip(struct bufferchain *bc, ssize_t count);
53
static ssize_t bc_seekback(struct bufferchain *bc, ssize_t count);
52
static ssize_t bc_seekback(struct bufferchain *bc, ssize_t count);
54
static void bc_forget(struct bufferchain *bc);
53
static void bc_forget(struct bufferchain *bc);
55
#else
-
 
56
#define bc_init(a)
-
 
57
#define bc_reset(a)
-
 
58
#endif
54
#endif
Line 59... Line 55...
59
 
55
 
60
/* A normal read and a read with timeout. */
56
/* A normal read and a read with timeout. */
61
static ssize_t plain_read(mpg123_handle *fr, void *buf, size_t count)
57
static ssize_t plain_read(mpg123_handle *fr, void *buf, size_t count)
62
{
58
{
63
	ssize_t ret = fr->rdat.read(fr->rdat.filept, buf, count);
59
	ssize_t ret = io_read(&fr->rdat, buf, count);
64
	if(VERBOSE3) debug2("read %li bytes of %li", (long)ret, (long)count);
60
	if(VERBOSE3) debug2("read %li bytes of %li", (long)ret, (long)count);
65
	return ret;
61
	return ret;
Line -... Line 62...
-
 
62
}
-
 
63
 
-
 
64
#ifdef TIMEOUT_READ
-
 
65
 
-
 
66
/* Wait for data becoming available, allowing soft-broken network connection to die
-
 
67
   This is needed for Shoutcast servers that have forgotten about us while connection was temporarily down. */
-
 
68
static ssize_t timeout_read(mpg123_handle *fr, void *buf, size_t count)
-
 
69
{
-
 
70
	struct timeval tv;
-
 
71
	ssize_t ret = 0;
-
 
72
	fd_set fds;
-
 
73
	tv.tv_sec = fr->rdat.timeout_sec;
-
 
74
	tv.tv_usec = 0;
-
 
75
	FD_ZERO(&fds);
-
 
76
	FD_SET(fr->rdat.filept, &fds);
-
 
77
	ret = select(fr->rdat.filept+1, &fds, NULL, NULL, &tv);
-
 
78
	/* This works only with "my" read function. Not user-replaced. */
-
 
79
	if(ret > 0) ret = read(fr->rdat.filept, buf, count);
-
 
80
	else
-
 
81
	{
-
 
82
		ret=-1; /* no activity is the error */
-
 
83
		if(NOQUIET) error("stream timed out");
-
 
84
	}
-
 
85
	return ret;
-
 
86
}
66
}
87
#endif
67
 
88
 
68
#ifndef NO_ICY
89
#ifndef NO_ICY
69
/* stream based operation  with icy meta data*/
90
/* stream based operation  with icy meta data*/
70
static ssize_t icy_fullread(mpg123_handle *fr, unsigned char *buf, ssize_t count)
91
static ssize_t icy_fullread(mpg123_handle *fr, unsigned char *buf, ssize_t count)
Line 96... Line 117...
96
 
117
 
97
			/* we are near icy-metaint boundary, read up to the boundary */
118
			/* we are near icy-metaint boundary, read up to the boundary */
98
			if(fr->icy.next > 0)
119
			if(fr->icy.next > 0)
99
			{
120
			{
100
				cut_pos = fr->icy.next;
121
				cut_pos = fr->icy.next;
101
				ret = fr->rdat.fdread(fr,buf,cut_pos);
122
				ret = fr->rdat.fdread(fr,buf+cnt,cut_pos);
102
				if(ret < 1)
123
				if(ret < 1)
103
				{
124
				{
104
					if(ret == 0) break; /* Just EOF. */
125
					if(ret == 0) break; /* Just EOF. */
Line 105... Line 126...
105
					if(NOQUIET) error("icy boundary read");
126
					if(NOQUIET) error("icy boundary read");
106
 
127
 
-
 
128
					return READER_ERROR;
107
					return READER_ERROR;
129
				}
108
				}
130
 
109
				fr->rdat.filepos += ret;
131
				if(!(fr->rdat.flags & READER_BUFFERED)) fr->rdat.filepos += ret;
110
				cnt += ret;
132
				cnt += ret;
111
				fr->icy.next -= ret;
133
				fr->icy.next -= ret;
112
				if(fr->icy.next > 0)
134
				if(fr->icy.next > 0)
Line 128... Line 150...
128
 
150
 
129
			if((meta_size = ((size_t) temp_buff) * 16))
151
			if((meta_size = ((size_t) temp_buff) * 16))
130
			{
152
			{
131
				/* we have got some metadata */
153
				/* we have got some metadata */
-
 
154
				char *meta_buff;
132
				char *meta_buff;
155
				/* TODO: Get rid of this malloc ... perhaps hooking into the reader buffer pool? */
133
				meta_buff = malloc(meta_size+1);
156
				meta_buff = malloc(meta_size+1);
134
				if(meta_buff != NULL)
157
				if(meta_buff != NULL)
135
				{
158
				{
136
					ssize_t left = meta_size;
159
					ssize_t left = meta_size;
Line 155... Line 178...
155
					fr->rd->skip_bytes(fr, meta_size);
178
					fr->rd->skip_bytes(fr, meta_size);
156
				}
179
				}
157
			}
180
			}
158
			fr->icy.next = fr->icy.interval;
181
			fr->icy.next = fr->icy.interval;
159
		}
182
		}
-
 
183
		else
160
 
184
		{
161
		ret = plain_fullread(fr, buf+cnt, count-cnt);
185
			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; }
186
			if(ret < 0){ if(NOQUIET) error1("reading the rest of %li", (long)(count-cnt)); return READER_ERROR; }
163
		if(ret == 0) break;
187
			if(ret == 0) break;
Line 164... Line 188...
164
 
188
 
165
		cnt += ret;
189
			cnt += ret;
166
		fr->icy.next -= ret;
190
			fr->icy.next -= ret;
-
 
191
		}
167
	}
192
	}
168
	/* debug1("done reading, got %li", (long)cnt); */
193
	/* debug1("done reading, got %li", (long)cnt); */
169
	return cnt;
194
	return cnt;
170
}
195
}
171
#else
196
#else
Line 175... Line 200...
175
/* stream based operation */
200
/* stream based operation */
176
static ssize_t plain_fullread(mpg123_handle *fr,unsigned char *buf, ssize_t count)
201
static ssize_t plain_fullread(mpg123_handle *fr,unsigned char *buf, ssize_t count)
177
{
202
{
178
	ssize_t ret,cnt=0;
203
	ssize_t ret,cnt=0;
Line -... Line 204...
-
 
204
 
-
 
205
#ifdef EXTRA_DEBUG
-
 
206
	debug1("plain fullread of %"SSIZE_P, (size_p)count);
179
 
207
#endif
180
	/*
208
	/*
181
		There used to be a check for expected file end here (length value or ID3 flag).
209
		There used to be a check for expected file end here (length value or ID3 flag).
182
		This is not needed:
210
		This is not needed:
183
		1. EOF is indicated by fdread returning zero bytes anyway.
211
		1. EOF is indicated by fdread returning zero bytes anyway.
Line 196... Line 224...
196
}
224
}
Line 197... Line 225...
197
 
225
 
198
static off_t stream_lseek(mpg123_handle *fr, off_t pos, int whence)
226
static off_t stream_lseek(mpg123_handle *fr, off_t pos, int whence)
199
{
227
{
200
	off_t ret;
228
	off_t ret;
201
	ret = fr->rdat.lseek(fr->rdat.filept, pos, whence);
229
	ret = io_seek(&fr->rdat, pos, whence);
202
	if (ret >= 0)	fr->rdat.filepos = ret;
230
	if (ret >= 0)	fr->rdat.filepos = ret;
203
	else
231
	else
204
	{
232
	{
205
		fr->err = MPG123_LSEEK_FAILED;
233
		fr->err = MPG123_LSEEK_FAILED;
Line 208... Line 236...
208
	return ret;
236
	return ret;
209
}
237
}
Line 210... Line 238...
210
 
238
 
211
static void stream_close(mpg123_handle *fr)
239
static void stream_close(mpg123_handle *fr)
212
{
240
{
-
 
241
	if(fr->rdat.flags & READER_FD_OPENED) compat_close(fr->rdat.filept);
-
 
242
 
-
 
243
	fr->rdat.filept = 0;
-
 
244
 
213
	if(fr->rdat.flags & READER_FD_OPENED) close(fr->rdat.filept);
245
#ifndef NO_FEEDER
-
 
246
	if(fr->rdat.flags & READER_BUFFERED)  bc_reset(&fr->rdat.buffer);
-
 
247
#endif
-
 
248
	if(fr->rdat.flags & READER_HANDLEIO)
-
 
249
	{
-
 
250
		if(fr->rdat.cleanup_handle != NULL) fr->rdat.cleanup_handle(fr->rdat.iohandle);
-
 
251
 
-
 
252
		fr->rdat.iohandle = NULL;
214
	if(fr->rdat.flags & READER_BUFFERED)  bc_reset(&fr->rdat.buffer);
253
	}
Line 215... Line 254...
215
}
254
}
216
 
255
 
217
static int stream_seek_frame(mpg123_handle *fr, off_t newframe)
256
static int stream_seek_frame(mpg123_handle *fr, off_t newframe)
Line 309... Line 348...
309
			else if(ret == 0) break; /* EOF... an error? interface defined to tell the actual position... */
348
			else if(ret == 0) break; /* EOF... an error? interface defined to tell the actual position... */
310
			len -= ret;
349
			len -= ret;
311
		}
350
		}
312
		return fr->rd->tell(fr);
351
		return fr->rd->tell(fr);
313
	}
352
	}
-
 
353
#ifndef NO_FEEDER
314
	else if(fr->rdat.flags & READER_BUFFERED)
354
	else if(fr->rdat.flags & READER_BUFFERED)
315
	{ /* Perhaps we _can_ go a bit back. */
355
	{ /* Perhaps we _can_ go a bit back. */
316
		if(fr->rdat.buffer.pos >= -len)
356
		if(fr->rdat.buffer.pos >= -len)
317
		{
357
		{
318
			fr->rdat.buffer.pos += len;
358
			fr->rdat.buffer.pos += len;
Line 322... Line 362...
322
		{
362
		{
323
			fr->err = MPG123_NO_SEEK;
363
			fr->err = MPG123_NO_SEEK;
324
			return READER_ERROR;
364
			return READER_ERROR;
325
		}
365
		}
326
	}
366
	}
-
 
367
#endif
327
	else
368
	else
328
	{
369
	{
329
		fr->err = MPG123_NO_SEEK;
370
		fr->err = MPG123_NO_SEEK;
330
		return READER_ERROR;
371
		return READER_ERROR;
331
	}
372
	}
Line 349... Line 390...
349
 
390
 
350
	if((l=fr->rd->fullread(fr,buf,size)) != size)
391
	if((l=fr->rd->fullread(fr,buf,size)) != size)
351
	{
392
	{
352
		long ll = l;
393
		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?! */
394
		if(ll <= 0) ll = 0;
356
		memset(buf+ll,0,size-ll);
395
		return READER_MORE;
357
	}
396
	}
358
	return l;
397
	return l;
Line 359... Line 398...
359
}
398
}
360
 
399
 
-
 
400
static off_t generic_tell(mpg123_handle *fr)
361
static off_t generic_tell(mpg123_handle *fr)
401
{
362
{
402
#ifndef NO_FEEDER
-
 
403
	if(fr->rdat.flags & READER_BUFFERED)
Line 363... Line 404...
363
	if(fr->rdat.flags & READER_BUFFERED)
404
	fr->rdat.filepos = fr->rdat.buffer.fileoff+fr->rdat.buffer.pos;
364
	fr->rdat.filepos = fr->rdat.buffer.fileoff+fr->rdat.buffer.pos;
405
#endif
Line 365... Line 406...
365
 
406
 
366
	return fr->rdat.filepos;
407
	return fr->rdat.filepos;
367
}
408
}
368
 
409
 
-
 
410
/* This does not (fully) work for non-seekable streams... You have to check for that flag, pal! */
369
/* This does not (fully) work for non-seekable streams... You have to check for that flag, pal! */
411
static void stream_rewind(mpg123_handle *fr)
-
 
412
{
-
 
413
	if(fr->rdat.flags & READER_SEEKABLE)
-
 
414
	{
-
 
415
		fr->rdat.filepos = stream_lseek(fr,0,SEEK_SET);
-
 
416
#ifndef NO_FEEDER
370
static void stream_rewind(mpg123_handle *fr)
417
		fr->rdat.buffer.fileoff = fr->rdat.filepos;
371
{
418
#endif
372
	if(fr->rdat.flags & READER_SEEKABLE)
419
	}
373
	fr->rdat.buffer.fileoff = fr->rdat.filepos = stream_lseek(fr,0,SEEK_SET);
420
#ifndef NO_FEEDER
374
	if(fr->rdat.flags & READER_BUFFERED)
421
	if(fr->rdat.flags & READER_BUFFERED)
375
	{
422
	{
-
 
423
		fr->rdat.buffer.pos      = 0;
376
		fr->rdat.buffer.pos      = 0;
424
		fr->rdat.buffer.firstpos = 0;
Line 377... Line 425...
377
		fr->rdat.buffer.firstpos = 0;
425
		fr->rdat.filepos = fr->rdat.buffer.fileoff;
378
		fr->rdat.filepos = fr->rdat.buffer.fileoff;
426
	}
379
	}
427
#endif
380
}
428
}
381
 
429
 
382
/*
-
 
383
 * returns length of a file (if filept points to a file)
430
/*
384
 * reads the last 128 bytes information into buffer
431
 * returns length of a file (if filept points to a file)
385
 * ... that is not totally safe...
432
 * reads the last 128 bytes information into buffer
Line 386... Line 433...
386
 */
433
 * ... that is not totally safe...
Line 387... Line 434...
387
 
434
 */
Line 388... Line 435...
388
static off_t get_fileinfo(mpg123_handle *fr)
435
static off_t get_fileinfo(mpg123_handle *fr)
Line 389... Line 436...
389
{
436
{
Line 390... Line 437...
390
	off_t len;
437
	off_t len;
Line 391... Line 438...
391
 
438
 
Line 392... Line 439...
392
	if((len=fr->rdat.lseek(fr->rdat.filept,0,SEEK_END)) < 0)	return -1;
439
	if((len=io_seek(&fr->rdat,0,SEEK_END)) < 0)	return -1;
393
 
440
 
Line 394... Line 441...
394
	if(fr->rdat.lseek(fr->rdat.filept,-128,SEEK_END) < 0) return -1;
441
	if(io_seek(&fr->rdat,-128,SEEK_END) < 0) return -1;
395
 
442
 
Line -... Line 443...
-
 
443
	if(fr->rd->fullread(fr,(unsigned char *)fr->id3buf,128) != 128)	return -1;
-
 
444
 
-
 
445
	if(!strncmp((char*)fr->id3buf,"TAG",3))	len -= 128;
-
 
446
 
-
 
447
	if(io_seek(&fr->rdat,0,SEEK_SET) < 0)	return -1;
-
 
448
 
-
 
449
	if(len <= 0)	return -1;
-
 
450
 
-
 
451
	return len;
-
 
452
}
-
 
453
 
-
 
454
#ifndef NO_FEEDER
-
 
455
/* Methods for the buffer chain, mainly used for feed reader, but not just that. */
-
 
456
 
-
 
457
 
-
 
458
static struct buffy* buffy_new(size_t size, size_t minsize)
-
 
459
{
-
 
460
	struct buffy *newbuf;
-
 
461
	newbuf = malloc(sizeof(struct buffy));
-
 
462
	if(newbuf == NULL) return NULL;
-
 
463
 
-
 
464
	newbuf->realsize = size > minsize ? size : minsize;
-
 
465
	newbuf->data = malloc(newbuf->realsize);
-
 
466
	if(newbuf->data == NULL)
-
 
467
	{
-
 
468
		free(newbuf);
-
 
469
		return NULL;
-
 
470
	}
-
 
471
	newbuf->size = 0;
-
 
472
	newbuf->next = NULL;
-
 
473
	return newbuf;
-
 
474
}
-
 
475
 
-
 
476
static void buffy_del(struct buffy* buf)
-
 
477
{
-
 
478
	if(buf)
-
 
479
	{
-
 
480
		free(buf->data);
-
 
481
		free(buf);
-
 
482
	}
-
 
483
}
-
 
484
 
-
 
485
/* Delete this buffy and all following buffies. */
-
 
486
static void buffy_del_chain(struct buffy* buf)
-
 
487
{
-
 
488
	while(buf)
-
 
489
	{
-
 
490
		struct buffy* next = buf->next;
-
 
491
		buffy_del(buf);
-
 
492
		buf = next;
-
 
493
	}
-
 
494
}
-
 
495
 
-
 
496
void bc_prepare(struct bufferchain *bc, size_t pool_size, size_t bufblock)
-
 
497
{
-
 
498
	bc_poolsize(bc, pool_size, bufblock);
-
 
499
	bc->pool = NULL;
-
 
500
	bc->pool_fill = 0;
-
 
501
	bc_init(bc); /* Ensure that members are zeroed for read-only use. */
-
 
502
}
-
 
503
 
-
 
504
size_t bc_fill(struct bufferchain *bc)
-
 
505
{
-
 
506
	return (size_t)(bc->size - bc->pos);
-
 
507
}
-
 
508
 
-
 
509
void bc_poolsize(struct bufferchain *bc, size_t pool_size, size_t bufblock)
-
 
510
{
-
 
511
	bc->pool_size = pool_size;
-
 
512
	bc->bufblock = bufblock;
-
 
513
}
-
 
514
 
-
 
515
void bc_cleanup(struct bufferchain *bc)
-
 
516
{
-
 
517
	buffy_del_chain(bc->pool);
-
 
518
	bc->pool = NULL;
-
 
519
	bc->pool_fill = 0;
-
 
520
}
-
 
521
 
-
 
522
/* Fetch a buffer from the pool (if possible) or create one. */
-
 
523
static struct buffy* bc_alloc(struct bufferchain *bc, size_t size)
-
 
524
{
-
 
525
	/* Easy route: Just try the first available buffer.
-
 
526
	   Size does not matter, it's only a hint for creation of new buffers. */
-
 
527
	if(bc->pool)
-
 
528
	{
-
 
529
		struct buffy *buf = bc->pool;
-
 
530
		bc->pool = buf->next;
-
 
531
		buf->next = NULL; /* That shall be set to a sensible value later. */
-
 
532
		buf->size = 0;
-
 
533
		--bc->pool_fill;
-
 
534
		debug2("bc_alloc: picked %p from pool (fill now %"SIZE_P")", (void*)buf, (size_p)bc->pool_fill);
-
 
535
		return buf;
-
 
536
	}
-
 
537
	else return buffy_new(size, bc->bufblock);
-
 
538
}
-
 
539
 
-
 
540
/* Either stuff the buffer back into the pool or free it for good. */
-
 
541
static void bc_free(struct bufferchain *bc, struct buffy* buf)
-
 
542
{
-
 
543
	if(!buf) return;
-
 
544
 
-
 
545
	if(bc->pool_fill < bc->pool_size)
-
 
546
	{
-
 
547
		buf->next = bc->pool;
-
 
548
		bc->pool = buf;
-
 
549
		++bc->pool_fill;
-
 
550
	}
-
 
551
	else buffy_del(buf);
-
 
552
}
-
 
553
 
-
 
554
/* Make the buffer count in the pool match the pool size. */
-
 
555
static int bc_fill_pool(struct bufferchain *bc)
-
 
556
{
-
 
557
	/* Remove superfluous ones. */
-
 
558
	while(bc->pool_fill > bc->pool_size)
-
 
559
	{
-
 
560
		/* Lazyness: Just work on the front. */
-
 
561
		struct buffy* buf = bc->pool;
-
 
562
		bc->pool = buf->next;
-
 
563
		buffy_del(buf);
-
 
564
		--bc->pool_fill;
-
 
565
	}
-
 
566
 
-
 
567
	/* Add missing ones. */
-
 
568
	while(bc->pool_fill < bc->pool_size)
-
 
569
	{
396
	if(fr->rd->fullread(fr,(unsigned char *)fr->id3buf,128) != 128)	return -1;
570
		/* Again, just work on the front. */
397
 
571
		struct buffy* buf;
398
	if(!strncmp((char*)fr->id3buf,"TAG",3))	len -= 128;
572
		buf = buffy_new(0, bc->bufblock); /* Use default block size. */
399
 
573
		if(!buf) return -1;
400
	if(fr->rdat.lseek(fr->rdat.filept,0,SEEK_SET) < 0)	return -1;
574
 
Line 417... Line 591...
417
	bc->fileoff  = 0;
591
	bc->fileoff  = 0;
418
}
592
}
Line 419... Line 593...
419
 
593
 
420
static void bc_reset(struct bufferchain *bc)
594
static void bc_reset(struct bufferchain *bc)
421
{
595
{
422
	/* free the buffer chain */
-
 
423
	struct buffy *b = bc->first;
596
	/* Free current chain, possibly stuffing back into the pool. */
424
	while(b != NULL)
597
	while(bc->first)
425
	{
598
	{
426
		struct buffy *n = b->next;
599
		struct buffy* buf = bc->first;
427
		free(b->data);
600
		bc->first = buf->next;
428
		free(b);
-
 
429
		b = n;
601
		bc_free(bc, buf);
-
 
602
	}
430
	}
603
	bc_fill_pool(bc); /* Ignoring an error here... */
431
	bc_init(bc);
604
	bc_init(bc);
Line 432... Line 605...
432
}
605
}
433
 
606
 
434
/* Create a new buffy at the end to be filled. */
607
/* Create a new buffy at the end to be filled. */
435
static int bc_append(struct bufferchain *bc, ssize_t size)
608
static int bc_append(struct bufferchain *bc, ssize_t size)
436
{
609
{
Line 437... Line 610...
437
	struct buffy *newbuf;
610
	struct buffy *newbuf;
438
	if(size < 1) return -1;
611
	if(size < 1) return -1;
Line 439... Line -...
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;
612
 
448
	}
613
	newbuf = bc_alloc(bc, size);
Line 449... Line 614...
449
	newbuf->size = size;
614
	if(newbuf == NULL) return -2;
450
	newbuf->next = NULL;
615
 
451
	if(bc->last != NULL)  bc->last->next = newbuf;
616
	if(bc->last != NULL)  bc->last->next = newbuf;
452
	else if(bc->first == NULL) bc->first = newbuf;
617
	else if(bc->first == NULL) bc->first = newbuf;
Line 453... Line -...
453
 
-
 
454
	bc->last  = newbuf;
618
 
455
	bc->size += size;
619
	bc->last  = newbuf;
456
	return 0;
620
	debug3("bc_append: new last buffer %p with %"SSIZE_P" B (really %"SSIZE_P")", (void*)bc->last, (ssize_p)bc->last->size, (ssize_p)bc->last->realsize);
457
}
621
	return 0;
-
 
622
}
-
 
623
 
-
 
624
/* Append a new buffer and copy content to it. */
-
 
625
static int bc_add(struct bufferchain *bc, const unsigned char *data, ssize_t size)
-
 
626
{
-
 
627
	int ret = 0;
-
 
628
	ssize_t part = 0;
-
 
629
	debug2("bc_add: adding %"SSIZE_P" bytes at %"OFF_P, (ssize_p)size, (off_p)(bc->fileoff+bc->size));
-
 
630
	if(size >=4) debug4("first bytes: %02x %02x %02x %02x", data[0], data[1], data[2], data[3]);
-
 
631
 
458
 
632
	while(size > 0)
-
 
633
	{
-
 
634
		/* Try to fill up the last buffer block. */
459
 
635
		if(bc->last != NULL && bc->last->size < bc->last->realsize)
-
 
636
		{
-
 
637
			part = bc->last->realsize - bc->last->size;
-
 
638
			if(part > size) part = size;
-
 
639
 
-
 
640
			debug2("bc_add: adding %"SSIZE_P" B to existing block %p", (ssize_p)part, (void*)bc->last);
-
 
641
			memcpy(bc->last->data+bc->last->size, data, part);
-
 
642
			bc->last->size += part;
-
 
643
			size -= part;
-
 
644
			bc->size += part;
-
 
645
			data += part;
Line 460... Line 646...
460
/* Append a new buffer and copy content to it. */
646
		}
461
static int bc_add(struct bufferchain *bc, const unsigned char *data, ssize_t size)
647
 
Line -... Line 648...
-
 
648
		/* If there is still data left, put it into a new buffer block. */
-
 
649
		if(size > 0 && (ret = bc_append(bc, size)) != 0)
-
 
650
		break;
-
 
651
	}
-
 
652
 
-
 
653
	return ret;
-
 
654
}
-
 
655
 
-
 
656
/* Common handler for "You want more than I can give." situation. */
462
{
657
static ssize_t bc_need_more(struct bufferchain *bc)
463
	int ret = 0;
658
{
464
	if((ret = bc_append(bc, size)) == 0)
659
	debug3("hit end, back to beginning (%li - %li < %li)", (long)bc->size, (long)bc->pos, (long)bc->size);
465
	memcpy(bc->last->data, data, size);
660
	/* go back to firstpos, undo the previous reads */
466
 
661
	bc->pos = bc->firstpos;
467
	return ret;
662
	return READER_MORE;
468
}
663
}
469
 
664
 
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;
665
/* Give some data, advancing position but not forgetting yet. */
476
	if(bc->size - bc->pos < size)
666
static ssize_t bc_give(struct bufferchain *bc, unsigned char *out, ssize_t size)
477
	{
667
{
478
		debug3("hit end, back to beginning (%li - %li < %li)", (long)bc->size, (long)bc->pos, (long)size);
668
	struct buffy *b = bc->first;
479
		/* go back to firstpos, undo the previous reads */
669
	ssize_t gotcount = 0;
Line 492... Line 682...
492
		ssize_t loff = bc->pos - offset;
682
		ssize_t loff = bc->pos - offset;
493
		ssize_t chunk = size - gotcount; /* amount of bytes to get from here... */
683
		ssize_t chunk = size - gotcount; /* amount of bytes to get from here... */
494
		if(chunk > b->size - loff) chunk = b->size - loff;
684
		if(chunk > b->size - loff) chunk = b->size - loff;
Line 495... Line 685...
495
 
685
 
496
#ifdef EXTRA_DEBUG
686
#ifdef EXTRA_DEBUG
497
		debug3("copying %liB from %p+%li",(long)chunk, b->data, (long)loff); */
687
		debug3("copying %liB from %p+%li",(long)chunk, b->data, (long)loff);
Line 498... Line 688...
498
#endif
688
#endif
499
 
689
 
500
		memcpy(out+gotcount, b->data+loff, chunk);
690
		memcpy(out+gotcount, b->data+loff, chunk);
Line 514... Line 704...
514
   The buffers are still there, just the read pointer is moved! */
704
   The buffers are still there, just the read pointer is moved! */
515
static ssize_t bc_skip(struct bufferchain *bc, ssize_t count)
705
static ssize_t bc_skip(struct bufferchain *bc, ssize_t count)
516
{
706
{
517
	if(count >= 0)
707
	if(count >= 0)
518
	{
708
	{
519
		if(bc->size - bc->pos < count) return READER_MORE;
709
		if(bc->size - bc->pos < count) return bc_need_more(bc);
520
		else return bc->pos += count;
710
		else return bc->pos += count;
521
	}
711
	}
522
	else return READER_ERROR;
712
	else return READER_ERROR;
523
}
713
}
Line 532... Line 722...
532
static void bc_forget(struct bufferchain *bc)
722
static void bc_forget(struct bufferchain *bc)
533
{
723
{
534
	struct buffy *b = bc->first;
724
	struct buffy *b = bc->first;
535
	/* free all buffers that are def'n'tly outdated */
725
	/* free all buffers that are def'n'tly outdated */
536
	/* we have buffers until filepos... delete all buffers fully below it */
726
	/* 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);
727
	if(b) debug2("bc_forget: block %lu pos %lu", (unsigned long)b->size, (unsigned long)bc->pos);
539
	else debug("forget with nothing there!");
728
	else debug("forget with nothing there!");
540
#endif
729
 
541
	while(b != NULL && bc->pos >= b->size)
730
	while(b != NULL && bc->pos >= b->size)
542
	{
731
	{
543
		struct buffy *n = b->next; /* != NULL or this is indeed the end and the last cycle anyway */
732
		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... */
733
		if(n == NULL) bc->last = NULL; /* Going to delete the last buffy... */
545
		bc->fileoff += b->size;
734
		bc->fileoff += b->size;
546
		bc->pos  -= b->size;
735
		bc->pos  -= b->size;
547
		bc->size -= b->size;
736
		bc->size -= b->size;
548
#ifdef EXTRA_DEBUG
-
 
-
 
737
 
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);
738
		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
739
 
551
		free(b->data);
-
 
552
		free(b);
740
		bc_free(bc, b);
553
		b = n;
741
		b = n;
554
	}
742
	}
555
	bc->first = b;
743
	bc->first = b;
556
	bc->firstpos = bc->pos;
744
	bc->firstpos = bc->pos;
557
}
745
}
Line 559... Line 747...
559
/* reader for input via manually provided buffers */
747
/* reader for input via manually provided buffers */
Line 560... Line 748...
560
 
748
 
561
static int feed_init(mpg123_handle *fr)
749
static int feed_init(mpg123_handle *fr)
562
{
750
{
-
 
751
	bc_init(&fr->rdat.buffer);
563
	bc_init(&fr->rdat.buffer);
752
	bc_fill_pool(&fr->rdat.buffer);
564
	fr->rdat.filelen = 0;
753
	fr->rdat.filelen = 0;
565
	fr->rdat.filepos = 0;
754
	fr->rdat.filepos = 0;
566
	fr->rdat.flags |= READER_BUFFERED;
755
	fr->rdat.flags |= READER_BUFFERED;
567
	return 0;
756
	return 0;
Line 592... Line 781...
592
}
781
}
Line 593... Line 782...
593
 
782
 
594
/* returns reached position... negative ones are bad... */
783
/* returns reached position... negative ones are bad... */
595
static off_t feed_skip_bytes(mpg123_handle *fr,off_t len)
784
static off_t feed_skip_bytes(mpg123_handle *fr,off_t len)
-
 
785
{
596
{
786
	/* This is either the new buffer offset or some negative error value. */
-
 
787
	off_t res = bc_skip(&fr->rdat.buffer, (ssize_t)len);
-
 
788
	if(res < 0) return res;
-
 
789
 
597
	return fr->rdat.buffer.fileoff+bc_skip(&fr->rdat.buffer, (ssize_t)len);
790
	return fr->rdat.buffer.fileoff+res;
Line 598... Line 791...
598
}
791
}
599
 
792
 
600
static int feed_back_bytes(mpg123_handle *fr, off_t bytes)
793
static int feed_back_bytes(mpg123_handle *fr, off_t bytes)
Line 618... Line 811...
618
{
811
{
619
	struct bufferchain *bc = &fr->rdat.buffer;
812
	struct bufferchain *bc = &fr->rdat.buffer;
620
	if(pos >= bc->fileoff && pos-bc->fileoff < bc->size)
813
	if(pos >= bc->fileoff && pos-bc->fileoff < bc->size)
621
	{ /* We have the position! */
814
	{ /* We have the position! */
622
		bc->pos = (ssize_t)(pos - bc->fileoff);
815
		bc->pos = (ssize_t)(pos - bc->fileoff);
-
 
816
		debug1("feed_set_pos inside, next feed from %"OFF_P, (off_p)(bc->fileoff+bc->size));
623
		return pos+bc->size; /* Next input after end of buffer... */
817
		return bc->fileoff+bc->size; /* Next input after end of buffer... */
624
	}
818
	}
625
	else
819
	else
626
	{ /* I expect to get the specific position on next feed. Forget what I have now. */
820
	{ /* I expect to get the specific position on next feed. Forget what I have now. */
627
		bc_reset(bc);
821
		bc_reset(bc);
628
		bc->fileoff = pos;
822
		bc->fileoff = pos;
-
 
823
		debug1("feed_set_pos outside, buffer reset, next feed from %"OFF_P, (off_p)pos);
629
		return pos; /* Next input from exactly that position. */
824
		return pos; /* Next input from exactly that position. */
630
	}
825
	}
631
}
826
}
Line 632... Line 827...
632
 
827
 
Line 633... Line -...
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). */
828
/* The specific stuff for buffered stream reader. */
636
#define BUFFBLOCK 4096
829
 
637
static ssize_t buffered_fullread(mpg123_handle *fr, unsigned char *out, ssize_t count)
830
static ssize_t buffered_fullread(mpg123_handle *fr, unsigned char *out, ssize_t count)
638
{
831
{
639
	struct bufferchain *bc = &fr->rdat.buffer;
832
	struct bufferchain *bc = &fr->rdat.buffer;
640
	ssize_t gotcount;
833
	ssize_t gotcount;
641
	if(bc->size - bc->pos < count)
834
	if(bc->size - bc->pos < count)
642
	{ /* Add more stuff to buffer. If hitting end of file, adjust count. */
835
	{ /* Add more stuff to buffer. If hitting end of file, adjust count. */
643
		unsigned char readbuf[BUFFBLOCK];
836
		unsigned char readbuf[4096];
644
		ssize_t need = count - (bc->size-bc->pos);
837
		ssize_t need = count - (bc->size-bc->pos);
645
		while(need>0)
838
		while(need>0)
646
		{
839
		{
647
			int ret;
840
			int ret;
648
			ssize_t got = fr->rdat.fullread(fr, readbuf, BUFFBLOCK);
841
			ssize_t got = fr->rdat.fullread(fr, readbuf, sizeof(readbuf));
649
			if(got < 0)
842
			if(got < 0)
650
			{
843
			{
651
				if(NOQUIET) error("buffer reading");
844
				if(NOQUIET) error("buffer reading");
Line 658... Line 851...
658
				if(NOQUIET) error1("unable to add to chain, return: %i", ret);
851
				if(NOQUIET) error1("unable to add to chain, return: %i", ret);
659
				return READER_ERROR;
852
				return READER_ERROR;
660
			}
853
			}
Line 661... Line 854...
661
 
854
 
662
			need -= got; /* May underflow here... */
855
			need -= got; /* May underflow here... */
663
			if(got < BUFFBLOCK) /* That naturally catches got == 0, too. */
856
			if(got < sizeof(readbuf)) /* That naturally catches got == 0, too. */
664
			{
857
			{
665
				if(VERBOSE3) fprintf(stderr, "Note: Input data end.\n");
858
				if(VERBOSE3) fprintf(stderr, "Note: Input data end.\n");
666
				break; /* End. */
859
				break; /* End. */
667
			}
860
			}
Line 692... Line 885...
692
/*****************************************************************
885
/*****************************************************************
693
 * read frame helper
886
 * read frame helper
694
 */
887
 */
Line 695... Line 888...
695
 
888
 
696
#define bugger_off { mh->err = MPG123_NO_READER; return MPG123_ERR; }
889
#define bugger_off { mh->err = MPG123_NO_READER; return MPG123_ERR; }
697
int bad_init(mpg123_handle *mh) bugger_off
890
static int bad_init(mpg123_handle *mh) bugger_off
698
void bad_close(mpg123_handle *mh){}
891
static void bad_close(mpg123_handle *mh){}
699
ssize_t bad_fullread(mpg123_handle *mh, unsigned char *data, ssize_t count) bugger_off
892
static 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
893
static 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
894
static 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
895
static 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
896
static 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
897
static 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
898
static int bad_seek_frame(mpg123_handle *mh, off_t num) bugger_off
706
off_t bad_tell(mpg123_handle *mh) bugger_off
899
static off_t bad_tell(mpg123_handle *mh) bugger_off
707
void bad_rewind(mpg123_handle *mh){}
900
static void bad_rewind(mpg123_handle *mh){}
Line 708... Line 901...
708
#undef bugger_off
901
#undef bugger_off
709
 
902
 
710
#define READER_STREAM 0
903
#define READER_STREAM 0
711
#define READER_ICY_STREAM 1
904
#define READER_ICY_STREAM 1
712
#define READER_FEED       2
905
#define READER_FEED       2
713
#define READER_BUF_STREAM 3
906
#define READER_BUF_STREAM 3
714
#define READER_BUF_ICY_STREAM 4
907
#define READER_BUF_ICY_STREAM 4
715
struct reader readers[] =
908
static struct reader readers[] =
716
{
909
{
717
	{ /* READER_STREAM */
910
	{ /* READER_STREAM */
718
		default_init,
911
		default_init,
Line 809... Line 1002...
809
		NULL,
1002
		NULL,
810
	}
1003
	}
811
#endif
1004
#endif
812
};
1005
};
Line 813... Line 1006...
813
 
1006
 
814
struct reader bad_reader =
1007
static struct reader bad_reader =
815
{
1008
{
816
	bad_init,
1009
	bad_init,
817
	bad_close,
1010
	bad_close,
818
	bad_fullread,
1011
	bad_fullread,
Line 827... Line 1020...
827
	NULL
1020
	NULL
828
};
1021
};
Line 829... Line 1022...
829
 
1022
 
830
static int default_init(mpg123_handle *fr)
1023
static int default_init(mpg123_handle *fr)
-
 
1024
{
-
 
1025
#ifdef TIMEOUT_READ
-
 
1026
	if(fr->p.timeout > 0)
-
 
1027
	{
-
 
1028
		int flags;
-
 
1029
		if(fr->rdat.r_read != NULL)
-
 
1030
		{
-
 
1031
			error("Timeout reading does not work with user-provided read function. Implement it yourself!");
-
 
1032
			return -1;
-
 
1033
		}
-
 
1034
		flags = fcntl(fr->rdat.filept, F_GETFL);
-
 
1035
		flags |= O_NONBLOCK;
-
 
1036
		fcntl(fr->rdat.filept, F_SETFL, flags);
-
 
1037
		fr->rdat.fdread = timeout_read;
-
 
1038
		fr->rdat.timeout_sec = fr->p.timeout;
-
 
1039
		fr->rdat.flags |= READER_NONBLOCK;
-
 
1040
	}
-
 
1041
	else
831
{
1042
#endif
Line 832... Line 1043...
832
    fr->rdat.fdread = plain_read;
1043
	fr->rdat.fdread = plain_read;
833
 
1044
 
-
 
1045
	fr->rdat.read  = fr->rdat.r_read  != NULL ? fr->rdat.r_read  : posix_read;
-
 
1046
	fr->rdat.lseek = fr->rdat.r_lseek != NULL ? fr->rdat.r_lseek : posix_lseek;
-
 
1047
#ifndef NO_ICY
-
 
1048
	/* ICY streams of any sort shall not be seekable. */
-
 
1049
	if(fr->p.icy_interval > 0) fr->rdat.lseek = nix_lseek;
834
	fr->rdat.read  = fr->rdat.r_read  != NULL ? fr->rdat.r_read  : posix_read;
1050
#endif
835
	fr->rdat.lseek = fr->rdat.r_lseek != NULL ? fr->rdat.r_lseek : posix_lseek;
1051
 
-
 
1052
	fr->rdat.filelen = get_fileinfo(fr);
-
 
1053
	fr->rdat.filepos = 0;
-
 
1054
	/*
-
 
1055
		Don't enable seeking on ICY streams, just plain normal files.
-
 
1056
		This check is necessary since the client can enforce ICY parsing on files that would otherwise be seekable.
836
	fr->rdat.filelen = get_fileinfo(fr);
1057
		It is a task for the future to make the ICY parsing safe with seeks ... or not.
837
	fr->rdat.filepos = 0;
1058
	*/
838
	if(fr->rdat.filelen >= 0)
1059
	if(fr->rdat.filelen >= 0)
839
	{
1060
	{
840
		fr->rdat.flags |= READER_SEEKABLE;
1061
		fr->rdat.flags |= READER_SEEKABLE;
Line 878... Line 1099...
878
}
1099
}
Line 879... Line 1100...
879
 
1100
 
880
 
1101
 
-
 
1102
void open_bad(mpg123_handle *mh)
881
void open_bad(mpg123_handle *mh)
1103
{
882
{
1104
	debug("open_bad");
883
#ifndef NO_ICY
1105
#ifndef NO_ICY
884
	clear_icy(&mh->icy);
1106
	clear_icy(&mh->icy);
885
#endif
1107
#endif
-
 
1108
	mh->rd = &bad_reader;
886
	mh->rd = &bad_reader;
1109
	mh->rdat.flags = 0;
-
 
1110
#ifndef NO_FEEDER
-
 
1111
	bc_init(&mh->rdat.buffer);
887
	mh->rdat.flags = 0;
1112
#endif
Line 888... Line 1113...
888
	bc_init(&mh->rdat.buffer);
1113
	mh->rdat.filelen = -1;
889
}
1114
}
890
 
1115
 
Line 906... Line 1131...
906
	clear_icy(&fr->icy);
1131
	clear_icy(&fr->icy);
907
#endif
1132
#endif
908
	fr->rd = &readers[READER_FEED];
1133
	fr->rd = &readers[READER_FEED];
909
	fr->rdat.flags = 0;
1134
	fr->rdat.flags = 0;
910
	if(fr->rd->init(fr) < 0) return -1;
1135
	if(fr->rd->init(fr) < 0) return -1;
-
 
1136
 
-
 
1137
	debug("feed reader init successful");
911
	return 0;
1138
	return 0;
912
#endif /* NO_FEEDER */
1139
#endif /* NO_FEEDER */
913
}
1140
}
Line -... Line 1141...
-
 
1141
 
-
 
1142
/* Final code common to open_stream and open_stream_handle. */
-
 
1143
static int open_finish(mpg123_handle *fr)
-
 
1144
{
-
 
1145
#ifndef NO_ICY
-
 
1146
	if(fr->p.icy_interval > 0)
-
 
1147
	{
-
 
1148
		debug("ICY reader");
-
 
1149
		fr->icy.interval = fr->p.icy_interval;
-
 
1150
		fr->icy.next = fr->icy.interval;
-
 
1151
		fr->rd = &readers[READER_ICY_STREAM];
-
 
1152
	}
-
 
1153
	else
-
 
1154
#endif
-
 
1155
	{
-
 
1156
		fr->rd = &readers[READER_STREAM];
-
 
1157
		debug("stream reader");
-
 
1158
	}
-
 
1159
 
-
 
1160
	if(fr->rd->init(fr) < 0) return -1;
-
 
1161
 
-
 
1162
	return MPG123_OK;
-
 
1163
}
914
 
1164
 
915
int open_stream(mpg123_handle *fr, const char *bs_filenam, int fd)
1165
int open_stream(mpg123_handle *fr, const char *bs_filenam, int fd)
916
{
1166
{
917
	int filept_opened = 1;
1167
	int filept_opened = 1;
Line 918... Line 1168...
918
	int filept; /* descriptor of opened file/stream */
1168
	int filept; /* descriptor of opened file/stream */
-
 
1169
 
919
 
1170
	clear_icy(&fr->icy); /* can be done inside frame_clear ...? */
920
	clear_icy(&fr->icy); /* can be done inside frame_clear ...? */
1171
 
921
	if(!bs_filenam) /* no file to open, got a descriptor (stdin) */
1172
	if(!bs_filenam) /* no file to open, got a descriptor (stdin) */
922
	{
1173
	{
923
		filept = fd;
1174
		filept = fd;
924
		filept_opened = 0; /* and don't try to close it... */
1175
		filept_opened = 0; /* and don't try to close it... */
925
	}
1176
	}
926
	#ifndef O_BINARY
1177
	#ifndef O_BINARY
927
	#define O_BINARY (0)
1178
	#define O_BINARY (0)
928
	#endif
1179
	#endif
929
	else if((filept = open(bs_filenam, O_RDONLY|O_BINARY)) < 0) /* a plain old file to open... */
1180
	else if((filept = compat_open(bs_filenam, O_RDONLY|O_BINARY)) < 0) /* a plain old file to open... */
930
	{
1181
	{
931
		if(NOQUIET) error2("Cannot open file %s: %s", bs_filenam, strerror(errno));
1182
		if(NOQUIET) error2("Cannot open file %s: %s", bs_filenam, strerror(errno));
932
		fr->err = MPG123_BAD_FILE;
1183
		fr->err = MPG123_BAD_FILE;
Line 937... Line 1188...
937
	fr->rdat.filelen = -1;
1188
	fr->rdat.filelen = -1;
938
	fr->rdat.filept  = filept;
1189
	fr->rdat.filept  = filept;
939
	fr->rdat.flags = 0;
1190
	fr->rdat.flags = 0;
940
	if(filept_opened)	fr->rdat.flags |= READER_FD_OPENED;
1191
	if(filept_opened)	fr->rdat.flags |= READER_FD_OPENED;
Line 941... Line -...
941
 
-
 
942
#ifndef NO_ICY
-
 
943
	if(fr->p.icy_interval > 0)
-
 
944
	{
1192
 
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];
1193
	return open_finish(fr);
949
	}
1194
}
950
	else
1195
 
951
#endif
1196
int open_stream_handle(mpg123_handle *fr, void *iohandle)
-
 
1197
{
-
 
1198
	clear_icy(&fr->icy); /* can be done inside frame_clear ...? */
-
 
1199
	fr->rdat.filelen = -1;
-
 
1200
	fr->rdat.filept  = -1;
-
 
1201
	fr->rdat.iohandle = iohandle;
952
	{
1202
	fr->rdat.flags = 0;
-
 
1203
	fr->rdat.flags |= READER_HANDLEIO;
953
		fr->rd = &readers[READER_STREAM];
1204
 
954
		debug("stream reader");
1205
	return open_finish(fr);
Line -... Line 1206...
-
 
1206
}
-
 
1207
 
-
 
1208
/* Wrappers for actual reading/seeking... I'm full of wrappers here. */
955
	}
1209
static off_t io_seek(struct reader_data *rdat, off_t offset, int whence)
-
 
1210
{
-
 
1211
	if(rdat->flags & READER_HANDLEIO)
-
 
1212
	{
-
 
1213
		if(rdat->r_lseek_handle != NULL)
-
 
1214
		{
-
 
1215
			return rdat->r_lseek_handle(rdat->iohandle, offset, whence);
-
 
1216
		}
-
 
1217
		else return -1;
-
 
1218
	}
-
 
1219
	else
Line -... Line 1220...
-
 
1220
	return rdat->lseek(rdat->filept, offset, whence);
-
 
1221
}
-
 
1222
 
-
 
1223
static ssize_t io_read(struct reader_data *rdat, void *buf, size_t count)
-
 
1224
{
-
 
1225
	if(rdat->flags & READER_HANDLEIO)
-
 
1226
	{
-
 
1227
		if(rdat->r_read_handle != NULL)
956
 
1228
		{
-
 
1229
			return rdat->r_read_handle(rdat->iohandle, buf, count);
-
 
1230
		}
-
 
1231
		else return -1;
957
	if(fr->rd->init(fr) < 0) return -1;
1232
	}