~ubuntu-branches/ubuntu/lucid/mpg123/lucid

« back to all changes in this revision

Viewing changes to src/readers.c

Tags: upstream-0.60
ImportĀ upstreamĀ versionĀ 0.60

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
        readers.c: reading input data
 
3
 
 
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
 
7
*/
 
8
 
 
9
#include <stdlib.h>
 
10
 
 
11
#include <sys/types.h>
 
12
#include <sys/stat.h>
 
13
#include <fcntl.h>
 
14
 
 
15
#include "config.h"
 
16
#include "mpg123.h"
 
17
#include "debug.h"
 
18
#include "buffer.h"
 
19
#include "common.h"
 
20
 
 
21
#if 0
 
22
#ifdef READ_MMAP
 
23
#include <sys/mman.h>
 
24
#ifndef MAP_FAILED
 
25
#define MAP_FAILED ( (void *) -1 )
 
26
#endif
 
27
#endif
 
28
#endif
 
29
 
 
30
static off_t get_fileinfo(struct reader *,char *buf);
 
31
 
 
32
 
 
33
/*******************************************************************
 
34
 * stream based operation
 
35
 * Oh... that count should be size_t or at least long...
 
36
 */
 
37
static ssize_t fullread(struct reader *rds,unsigned char *buf, ssize_t count)
 
38
{
 
39
  ssize_t ret,cnt=0;
 
40
 
 
41
  /*
 
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.
 
46
   */
 
47
  if ((rds->flags & READER_ID3TAG) && rds->filepos + count > rds->filelen)
 
48
    count = rds->filelen - rds->filepos;
 
49
  while(cnt < count) {
 
50
    ret = read(rds->filept,buf+cnt,count-cnt);
 
51
    if(ret < 0)
 
52
      return ret;
 
53
    if(ret == 0)
 
54
      break;
 
55
    rds->filepos += ret;
 
56
    cnt += ret;
 
57
  } 
 
58
 
 
59
  return cnt;
 
60
}
 
61
 
 
62
static off_t stream_lseek(struct reader *rds, off_t pos, int whence)
 
63
{
 
64
  off_t ret;
 
65
 
 
66
  ret = lseek(rds->filept, pos, whence);
 
67
  if (ret >= 0)
 
68
    rds->filepos = ret;
 
69
 
 
70
  return ret;
 
71
}
 
72
 
 
73
static int default_init(struct reader *rds)
 
74
{
 
75
  char buf[128];
 
76
 
 
77
  rds->filelen = get_fileinfo(rds,buf);
 
78
  rds->filepos = 0;
 
79
        
 
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);
 
85
    }
 
86
  }
 
87
 
 
88
  return 0;
 
89
}
 
90
 
 
91
void stream_close(struct reader *rds)
 
92
{
 
93
    if (rds->flags & READER_FD_OPENED)
 
94
        close(rds->filept);
 
95
}
 
96
 
 
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; 
 
101
 */
 
102
static int stream_back_bytes(struct reader *rds, off_t bytes)
 
103
{
 
104
  if(stream_lseek(rds,-bytes,SEEK_CUR) < 0)
 
105
    return -1;
 
106
  if(param.usebuffer)
 
107
          buffer_resync();
 
108
  return 0;
 
109
}
 
110
 
 
111
 
 
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)
 
115
{
 
116
        if(rds->flags & READER_SEEKABLE)
 
117
        {
 
118
                unsigned long newframe, preframe;
 
119
                if(num > 0) /* back! */
 
120
                {
 
121
                        if(num > fr->num) newframe = 0;
 
122
                        else newframe = fr->num-num;
 
123
                }
 
124
                else newframe = fr->num-num;
 
125
                
 
126
                /* two leading frames? hm, doesn't seem to be really needed... */
 
127
                /*if(newframe > 1) newframe -= 2;
 
128
                else newframe = 0;*/
 
129
                
 
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)
 
132
                return -1;
 
133
                
 
134
                debug2("going to %lu; just got %lu", newframe, preframe);
 
135
                
 
136
                fr->num = preframe;
 
137
                
 
138
                while(fr->num < newframe)
 
139
                {
 
140
                        /* try to be non-fatal now... frameNum only gets advanced on success anyway */
 
141
                        if(!read_frame(fr)) break;
 
142
                }
 
143
 
 
144
                /* this is not needed at last? */
 
145
                /*read_frame(fr);
 
146
                read_frame(fr);*/
 
147
 
 
148
                if(fr->lay == 3) {
 
149
                        set_pointer(512);
 
150
                }
 
151
 
 
152
                debug1("arrived at %lu", fr->num);
 
153
 
 
154
                if(param.usebuffer)
 
155
                        buffer_resync();
 
156
 
 
157
                return 0;
 
158
 
 
159
        }
 
160
        else return -1; /* invalid, no seek happened */
 
161
}
 
162
 
 
163
static int stream_head_read(struct reader *rds,unsigned long *newhead)
 
164
{
 
165
  unsigned char hbuf[4];
 
166
 
 
167
  if(fullread(rds,hbuf,4) != 4)
 
168
    return FALSE;
 
169
  
 
170
  *newhead = ((unsigned long) hbuf[0] << 24) |
 
171
    ((unsigned long) hbuf[1] << 16) |
 
172
    ((unsigned long) hbuf[2] << 8)  |
 
173
    (unsigned long) hbuf[3];
 
174
  
 
175
  return TRUE;
 
176
}
 
177
 
 
178
static int stream_head_shift(struct reader *rds,unsigned long *head)
 
179
{
 
180
  unsigned char hbuf;
 
181
 
 
182
  if(fullread(rds,&hbuf,1) != 1)
 
183
    return 0;
 
184
  *head <<= 8;
 
185
  *head |= hbuf;
 
186
  *head &= 0xffffffff;
 
187
  return 1;
 
188
}
 
189
 
 
190
/* returns reached position... negative ones are bad */
 
191
static off_t stream_skip_bytes(struct reader *rds,off_t len)
 
192
{
 
193
  if (rds->filelen >= 0) {
 
194
    off_t ret = stream_lseek(rds, len, SEEK_CUR);
 
195
    if (param.usebuffer)
 
196
      buffer_resync();
 
197
    return ret;
 
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? */
 
200
    off_t ret;
 
201
    while (len > 0) {
 
202
      off_t num = len < sizeof(buf) ? len : sizeof(buf);
 
203
      ret = fullread(rds, buf, num);
 
204
      if (ret < 0)
 
205
        return ret;
 
206
      len -= ret;
 
207
    }
 
208
    return rds->filepos;
 
209
  } else
 
210
    return -1;
 
211
}
 
212
 
 
213
static int stream_read_frame_body(struct reader *rds,unsigned char *buf,
 
214
                                  int size)
 
215
{
 
216
  long l;
 
217
 
 
218
  if( (l=fullread(rds,buf,size)) != size)
 
219
  {
 
220
    if(l <= 0)
 
221
      return 0;
 
222
    memset(buf+l,0,size-l);
 
223
  }
 
224
 
 
225
  return 1;
 
226
}
 
227
 
 
228
static off_t stream_tell(struct reader *rds)
 
229
{
 
230
  return rds->filepos;
 
231
}
 
232
 
 
233
static void stream_rewind(struct reader *rds)
 
234
{
 
235
  stream_lseek(rds,0,SEEK_SET);
 
236
  if(param.usebuffer) 
 
237
          buffer_resync();
 
238
}
 
239
 
 
240
/*
 
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...
 
244
 */
 
245
static off_t get_fileinfo(struct reader *rds,char *buf)
 
246
{
 
247
        off_t len;
 
248
 
 
249
        if((len=lseek(rds->filept,0,SEEK_END)) < 0) {
 
250
                return -1;
 
251
        }
 
252
        if(lseek(rds->filept,-128,SEEK_END) < 0)
 
253
                return -1;
 
254
        if(fullread(rds,(unsigned char *)buf,128) != 128) {
 
255
                return -1;
 
256
        }
 
257
        if(!strncmp(buf,"TAG",3)) {
 
258
                len -= 128;
 
259
        }
 
260
        if(lseek(rds->filept,0,SEEK_SET) < 0)
 
261
                return -1;
 
262
        if(len <= 0)
 
263
                return -1;
 
264
        return len;
 
265
}
 
266
 
 
267
 
 
268
/*
 
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?
 
272
        */
 
273
#if 0
 
274
#ifdef READ_MMAP
 
275
/*********************************************************+
 
276
 * memory mapped operation 
 
277
 *
 
278
 */
 
279
static unsigned char *mapbuf;
 
280
static unsigned char *mappnt;
 
281
static unsigned char *mapend;
 
282
 
 
283
static int mapped_init(struct reader *rds) 
 
284
{
 
285
        long len;
 
286
        char buf[128];
 
287
 
 
288
        len = get_fileinfo(rds,buf);
 
289
        rds->flags |= READER_SEEKABLE;
 
290
        if(len < 0)
 
291
                return -1;
 
292
 
 
293
        if(!strncmp(buf,"TAG",3)) {
 
294
          rds->flags |= READER_ID3TAG;
 
295
          memcpy(rds->id3buf,buf,128);
 
296
        }
 
297
        mappnt = mapbuf = (unsigned char *)
 
298
                mmap(NULL, len, PROT_READ, MAP_SHARED , rds->filept, 0);
 
299
        if(!mapbuf || mapbuf == MAP_FAILED)
 
300
                return -1;
 
301
 
 
302
        mapend = mapbuf + len;
 
303
        
 
304
        if(param.verbose > 1)
 
305
                fprintf(stderr,"Using memory mapped IO for this stream.\n");
 
306
 
 
307
        rds->filelen = len;
 
308
        return 0;
 
309
}
 
310
 
 
311
static void mapped_rewind(struct reader *rds)
 
312
{
 
313
        mappnt = mapbuf;
 
314
        if (param.usebuffer) 
 
315
                buffer_resync();        
 
316
}
 
317
 
 
318
static void mapped_close(struct reader *rds)
 
319
{
 
320
        munmap((void *)mapbuf,mapend-mapbuf);
 
321
        if (rds->flags & READER_FD_OPENED)
 
322
                close(rds->filept);
 
323
}
 
324
 
 
325
static int mapped_head_read(struct reader *rds,unsigned long *newhead) 
 
326
{
 
327
        unsigned long nh;
 
328
 
 
329
        if(mappnt + 4 > mapend)
 
330
                return FALSE;
 
331
 
 
332
        nh = (*mappnt++)  << 24;
 
333
        nh |= (*mappnt++) << 16;
 
334
        nh |= (*mappnt++) << 8;
 
335
        nh |= (*mappnt++) ;
 
336
 
 
337
        *newhead = nh;
 
338
        return TRUE;
 
339
}
 
340
 
 
341
static int mapped_head_shift(struct reader *rds,unsigned long *head)
 
342
{
 
343
  if(mappnt + 1 > mapend)
 
344
    return FALSE;
 
345
  *head <<= 8;
 
346
  *head |= *mappnt++;
 
347
  *head &= 0xffffffff;
 
348
  return TRUE;
 
349
}
 
350
 
 
351
static int mapped_skip_bytes(struct reader *rds,int len)
 
352
{
 
353
  if(mappnt + len > mapend)
 
354
    return FALSE;
 
355
  mappnt += len;
 
356
  if (param.usebuffer)
 
357
          buffer_resync();
 
358
  return TRUE;
 
359
}
 
360
 
 
361
static int mapped_read_frame_body(struct reader *rds,unsigned char *buf,
 
362
                                  int size)
 
363
{
 
364
  if(size <= 0) {
 
365
    fprintf(stderr,"Ouch. Read_frame called with size <= 0\n");
 
366
    return FALSE;
 
367
  }
 
368
  if(mappnt + size > mapend)
 
369
    return FALSE;
 
370
  memcpy(buf,mappnt,size);
 
371
  mappnt += size;
 
372
 
 
373
  return TRUE;
 
374
}
 
375
 
 
376
static int mapped_back_bytes(struct reader *rds,int bytes)
 
377
{
 
378
    if( (mappnt - bytes) < mapbuf || (mappnt - bytes + 4) > mapend)
 
379
        return -1;
 
380
    mappnt -= bytes;
 
381
    if(param.usebuffer)
 
382
            buffer_resync();
 
383
    return 0;
 
384
}
 
385
 
 
386
static int mapped_back_frame(struct reader *rds,struct frame *fr,long num)
 
387
{
 
388
    long bytes;
 
389
    unsigned long newhead;
 
390
 
 
391
 
 
392
    if(!firsthead)
 
393
        return 0;
 
394
 
 
395
    bytes = (fr->framesize+8)*(num+2);
 
396
 
 
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.
 
400
     */
 
401
    if(param.usebuffer) 
 
402
                bytes += (long)(xfermem_get_usedspace(buffermem) /
 
403
                        (buffermem->buf[0] * buffermem->buf[1] 
 
404
                                * (buffermem->buf[2] & AUDIO_FORMAT_MASK ?
 
405
                        16.0 : 8.0 )) 
 
406
                        * (tabsel_123[fr->lsf][fr->lay-1][fr->bitrate_index] << 10));
 
407
/*
 
408
                bytes += (long)(compute_buffer_offset(fr)*compute_bpf(fr));  
 
409
*/
 
410
 
 
411
    if( (mappnt - bytes) < mapbuf || (mappnt - bytes + 4) > mapend)
 
412
        return -1;
 
413
    mappnt -= bytes;
 
414
 
 
415
    newhead = (mappnt[0]<<24) + (mappnt[1]<<16) + (mappnt[2]<<8) + mappnt[3];
 
416
    mappnt += 4;
 
417
 
 
418
    while( (newhead & HDRCMPMASK) != (firsthead & HDRCMPMASK) ) {
 
419
        if(mappnt + 1 > mapend)
 
420
            return -1;
 
421
        newhead <<= 8;
 
422
        newhead |= *mappnt++;
 
423
        newhead &= 0xffffffff;
 
424
    }
 
425
    mappnt -= 4;
 
426
 
 
427
    read_frame(fr);
 
428
    read_frame(fr);
 
429
 
 
430
    if(fr->lay == 3)
 
431
        set_pointer(512);
 
432
 
 
433
    if(param.usebuffer)
 
434
            buffer_resync();
 
435
    
 
436
    return 0;
 
437
}
 
438
 
 
439
static long mapped_tell(struct reader *rds)
 
440
{
 
441
  return mappnt - mapbuf;
 
442
}
 
443
 
 
444
#endif
 
445
#endif
 
446
 
 
447
/*****************************************************************
 
448
 * read frame helper
 
449
 */
 
450
 
 
451
struct reader *rd;
 
452
struct reader readers[] = {
 
453
#ifdef READ_SYSTEM
 
454
 { system_init,
 
455
   NULL,        /* filled in by system_init() */
 
456
   NULL,
 
457
   NULL,
 
458
   NULL,
 
459
   NULL,
 
460
   NULL,
 
461
   NULL,
 
462
   NULL } ,
 
463
#endif
 
464
#if 0
 
465
#ifdef READ_MMAP
 
466
 { mapped_init,
 
467
   mapped_close,
 
468
   mapped_head_read,
 
469
   mapped_head_shift,
 
470
   mapped_skip_bytes,
 
471
   mapped_read_frame_body,
 
472
   mapped_back_bytes,
 
473
   mapped_back_frame,
 
474
   mapped_tell,
 
475
   mapped_rewind } , 
 
476
#endif 
 
477
#endif
 
478
 { default_init,
 
479
   stream_close,
 
480
   stream_head_read,
 
481
   stream_head_shift,
 
482
   stream_skip_bytes,
 
483
   stream_read_frame_body,
 
484
   stream_back_bytes,
 
485
   stream_back_frame,
 
486
   stream_tell,
 
487
   stream_rewind } ,
 
488
 { NULL, }
 
489
};
 
490
 
 
491
 
 
492
/* open the device to read the bit stream from it */
 
493
 
 
494
int open_stream(char *bs_filenam,int fd)
 
495
{
 
496
    int i;
 
497
    int filept_opened = 1;
 
498
    int filept;
 
499
 
 
500
    if (!bs_filenam)
 
501
                {
 
502
                        if(fd < 0)
 
503
                        {
 
504
                                filept = 0;
 
505
                                filept_opened = 0;
 
506
                        }
 
507
                        else filept = fd;
 
508
                }
 
509
                else if (!strncmp(bs_filenam, "http://", 7))
 
510
                {
 
511
                        char* mime = NULL;
 
512
                        filept = http_open(bs_filenam, &mime);
 
513
                        if((filept >= 0) && (mime != NULL) && (strcmp(mime, "audio/mpeg")))
 
514
                        {
 
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);
 
516
                                filept = -1;
 
517
                        }
 
518
                        if(mime != NULL) free(mime);
 
519
                        if(filept < 0) return filept;
 
520
                }
 
521
#ifndef O_BINARY
 
522
#define O_BINARY (0)
 
523
#endif
 
524
        else if ( (filept = open(bs_filenam, O_RDONLY|O_BINARY)) < 0) {
 
525
                perror (bs_filenam);
 
526
               return filept;
 
527
        }
 
528
 
 
529
    rd = NULL;
 
530
    for(i=0;;i++) {
 
531
      readers[i].filelen = -1;
 
532
      readers[i].filept  = filept;
 
533
      readers[i].flags = 0;
 
534
      if(filept_opened)
 
535
        readers[i].flags |= READER_FD_OPENED;
 
536
      if(!readers[i].init) {
 
537
        fprintf(stderr,"Fatal error!\n");
 
538
        exit(1);
 
539
      }
 
540
      if(readers[i].init(readers+i) >= 0) {
 
541
        rd = &readers[i];
 
542
        break;
 
543
      }
 
544
    }
 
545
 
 
546
    /* id3tag printing moved to read_frame */
 
547
    return filept;
 
548
}