2
readers.c: reading input data
4
copyright ?-2006 by the mpg123 project - free software under the terms of the LGPL 2.1
5
see COPYING and AUTHORS files in distribution or http://mpg123.de
6
initially written by Michael Hipp
11
#include <sys/types.h>
25
#define MAP_FAILED ( (void *) -1 )
30
static off_t get_fileinfo(struct reader *,char *buf);
33
/*******************************************************************
34
* stream based operation
35
* Oh... that count should be size_t or at least long...
37
static ssize_t fullread(struct reader *rds,unsigned char *buf, ssize_t count)
42
* We check against READER_ID3TAG instead of rds->filelen >= 0 because
43
* if we got the ID3 TAG we know we have the end of the file. If we
44
* don't have an ID3 TAG, then it is possible the file has grown since
45
* we started playing, so we want to keep reading from it if possible.
47
if ((rds->flags & READER_ID3TAG) && rds->filepos + count > rds->filelen)
48
count = rds->filelen - rds->filepos;
50
ret = read(rds->filept,buf+cnt,count-cnt);
62
static off_t stream_lseek(struct reader *rds, off_t pos, int whence)
66
ret = lseek(rds->filept, pos, whence);
73
static int default_init(struct reader *rds)
77
rds->filelen = get_fileinfo(rds,buf);
80
if(rds->filelen >= 0) {
81
rds->flags |= READER_SEEKABLE;
82
if(!strncmp(buf,"TAG",3)) {
83
rds->flags |= READER_ID3TAG;
84
memcpy(rds->id3buf,buf,128);
91
void stream_close(struct reader *rds)
93
if (rds->flags & READER_FD_OPENED)
97
/****************************************
98
* HACK,HACK,HACK: step back <num> frames
99
* can only work if the 'stream' isn't a real stream but a file
100
* returns 0 on success;
102
static int stream_back_bytes(struct reader *rds, off_t bytes)
104
if(stream_lseek(rds,-bytes,SEEK_CUR) < 0)
112
/* this function strangely is define to seek num frames _back_ (and is called with -offset - duh!) */
113
/* also... let that int be a long in future! */
114
static int stream_back_frame(struct reader *rds,struct frame *fr,long num)
116
if(rds->flags & READER_SEEKABLE)
118
unsigned long newframe, preframe;
119
if(num > 0) /* back! */
121
if(num > fr->num) newframe = 0;
122
else newframe = fr->num-num;
124
else newframe = fr->num-num;
126
/* two leading frames? hm, doesn't seem to be really needed... */
127
/*if(newframe > 1) newframe -= 2;
130
/* now seek to nearest leading index position and read from there until newframe is reached */
131
if(stream_lseek(rds,frame_index_find(newframe, &preframe),SEEK_SET) < 0)
134
debug2("going to %lu; just got %lu", newframe, preframe);
138
while(fr->num < newframe)
140
/* try to be non-fatal now... frameNum only gets advanced on success anyway */
141
if(!read_frame(fr)) break;
144
/* this is not needed at last? */
152
debug1("arrived at %lu", fr->num);
160
else return -1; /* invalid, no seek happened */
163
static int stream_head_read(struct reader *rds,unsigned long *newhead)
165
unsigned char hbuf[4];
167
if(fullread(rds,hbuf,4) != 4)
170
*newhead = ((unsigned long) hbuf[0] << 24) |
171
((unsigned long) hbuf[1] << 16) |
172
((unsigned long) hbuf[2] << 8) |
173
(unsigned long) hbuf[3];
178
static int stream_head_shift(struct reader *rds,unsigned long *head)
182
if(fullread(rds,&hbuf,1) != 1)
190
/* returns reached position... negative ones are bad */
191
static off_t stream_skip_bytes(struct reader *rds,off_t len)
193
if (rds->filelen >= 0) {
194
off_t ret = stream_lseek(rds, len, SEEK_CUR);
198
} else if (len >= 0) {
199
unsigned char buf[1024]; /* ThOr: Compaq cxx complained and it makes sense to me... or should one do a cast? What for? */
202
off_t num = len < sizeof(buf) ? len : sizeof(buf);
203
ret = fullread(rds, buf, num);
213
static int stream_read_frame_body(struct reader *rds,unsigned char *buf,
218
if( (l=fullread(rds,buf,size)) != size)
222
memset(buf+l,0,size-l);
228
static off_t stream_tell(struct reader *rds)
233
static void stream_rewind(struct reader *rds)
235
stream_lseek(rds,0,SEEK_SET);
241
* returns length of a file (if filept points to a file)
242
* reads the last 128 bytes information into buffer
243
* ... that is not totally safe...
245
static off_t get_fileinfo(struct reader *rds,char *buf)
249
if((len=lseek(rds->filept,0,SEEK_END)) < 0) {
252
if(lseek(rds->filept,-128,SEEK_END) < 0)
254
if(fullread(rds,(unsigned char *)buf,128) != 128) {
257
if(!strncmp(buf,"TAG",3)) {
260
if(lseek(rds->filept,0,SEEK_SET) < 0)
269
disabled that code so that always the new vbr stream seeking routine will be used
270
Also: does anyone really want that operation? I looks like waste of memory for something you can do outside of mpg123 (ramdisk...)
271
Is this needed for some really slow box? Does this slow box have the memory to spare?
275
/*********************************************************+
276
* memory mapped operation
279
static unsigned char *mapbuf;
280
static unsigned char *mappnt;
281
static unsigned char *mapend;
283
static int mapped_init(struct reader *rds)
288
len = get_fileinfo(rds,buf);
289
rds->flags |= READER_SEEKABLE;
293
if(!strncmp(buf,"TAG",3)) {
294
rds->flags |= READER_ID3TAG;
295
memcpy(rds->id3buf,buf,128);
297
mappnt = mapbuf = (unsigned char *)
298
mmap(NULL, len, PROT_READ, MAP_SHARED , rds->filept, 0);
299
if(!mapbuf || mapbuf == MAP_FAILED)
302
mapend = mapbuf + len;
304
if(param.verbose > 1)
305
fprintf(stderr,"Using memory mapped IO for this stream.\n");
311
static void mapped_rewind(struct reader *rds)
318
static void mapped_close(struct reader *rds)
320
munmap((void *)mapbuf,mapend-mapbuf);
321
if (rds->flags & READER_FD_OPENED)
325
static int mapped_head_read(struct reader *rds,unsigned long *newhead)
329
if(mappnt + 4 > mapend)
332
nh = (*mappnt++) << 24;
333
nh |= (*mappnt++) << 16;
334
nh |= (*mappnt++) << 8;
341
static int mapped_head_shift(struct reader *rds,unsigned long *head)
343
if(mappnt + 1 > mapend)
351
static int mapped_skip_bytes(struct reader *rds,int len)
353
if(mappnt + len > mapend)
361
static int mapped_read_frame_body(struct reader *rds,unsigned char *buf,
365
fprintf(stderr,"Ouch. Read_frame called with size <= 0\n");
368
if(mappnt + size > mapend)
370
memcpy(buf,mappnt,size);
376
static int mapped_back_bytes(struct reader *rds,int bytes)
378
if( (mappnt - bytes) < mapbuf || (mappnt - bytes + 4) > mapend)
386
static int mapped_back_frame(struct reader *rds,struct frame *fr,long num)
389
unsigned long newhead;
395
bytes = (fr->framesize+8)*(num+2);
397
/* Buffered mode is a bit trickier. From the size of the buffered
398
* output audio stream we have to make a guess at the number of frames
399
* this corresponds to.
402
bytes += (long)(xfermem_get_usedspace(buffermem) /
403
(buffermem->buf[0] * buffermem->buf[1]
404
* (buffermem->buf[2] & AUDIO_FORMAT_MASK ?
406
* (tabsel_123[fr->lsf][fr->lay-1][fr->bitrate_index] << 10));
408
bytes += (long)(compute_buffer_offset(fr)*compute_bpf(fr));
411
if( (mappnt - bytes) < mapbuf || (mappnt - bytes + 4) > mapend)
415
newhead = (mappnt[0]<<24) + (mappnt[1]<<16) + (mappnt[2]<<8) + mappnt[3];
418
while( (newhead & HDRCMPMASK) != (firsthead & HDRCMPMASK) ) {
419
if(mappnt + 1 > mapend)
422
newhead |= *mappnt++;
423
newhead &= 0xffffffff;
439
static long mapped_tell(struct reader *rds)
441
return mappnt - mapbuf;
447
/*****************************************************************
452
struct reader readers[] = {
455
NULL, /* filled in by system_init() */
471
mapped_read_frame_body,
483
stream_read_frame_body,
492
/* open the device to read the bit stream from it */
494
int open_stream(char *bs_filenam,int fd)
497
int filept_opened = 1;
509
else if (!strncmp(bs_filenam, "http://", 7))
512
filept = http_open(bs_filenam, &mime);
513
if((filept >= 0) && (mime != NULL) && (strcmp(mime, "audio/mpeg")))
515
fprintf(stderr, "Error: unknown mpeg MIME type %s - is it perhaps a playlist (use -@)?\nError: If you know the stream is mpeg1/2 audio, then please report this as "PACKAGE_NAME" bug\n", mime == NULL ? "<nil>" : mime);
518
if(mime != NULL) free(mime);
519
if(filept < 0) return filept;
524
else if ( (filept = open(bs_filenam, O_RDONLY|O_BINARY)) < 0) {
531
readers[i].filelen = -1;
532
readers[i].filept = filept;
533
readers[i].flags = 0;
535
readers[i].flags |= READER_FD_OPENED;
536
if(!readers[i].init) {
537
fprintf(stderr,"Fatal error!\n");
540
if(readers[i].init(readers+i) >= 0) {
546
/* id3tag printing moved to read_frame */