From e2de64d6f1beb9e492daf5b886e19933c1fa41dd Mon Sep 17 00:00:00 2001 From: toma Date: Wed, 25 Nov 2009 17:56:58 +0000 Subject: Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features. BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdemultimedia@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da --- mpg123_artsplugin/mpg123/common.c | 921 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 921 insertions(+) create mode 100644 mpg123_artsplugin/mpg123/common.c (limited to 'mpg123_artsplugin/mpg123/common.c') diff --git a/mpg123_artsplugin/mpg123/common.c b/mpg123_artsplugin/mpg123/common.c new file mode 100644 index 00000000..65d658fd --- /dev/null +++ b/mpg123_artsplugin/mpg123/common.c @@ -0,0 +1,921 @@ +/* GPL clean */ + +#include +#include +#include +#include + +#include +#include +#ifdef WIN32 +#include +#else +#include +#endif + +#include + +#ifdef READ_MMAP +#include +#ifndef MAP_FAILED +#define MAP_FAILED ( (void *) -1 ) +#endif +#endif + +#include "mpg123.h" +#include "genre.h" +#include "common.h" + +int tabsel_123[2][3][16] = { + { {0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,}, + {0,32,48,56, 64, 80, 96,112,128,160,192,224,256,320,384,}, + {0,32,40,48, 56, 64, 80, 96,112,128,160,192,224,256,320,} }, + + { {0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,}, + {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,}, + {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,} } +}; + +long freqs[9] = { 44100, 48000, 32000, 22050, 24000, 16000 , 11025 , 12000 , 8000 }; + +struct bitstream_info bsi; + +static int bsbufend[2]= { 0,0 }; +static int bsbufold_end; +static unsigned char bsspace[2][MAXFRAMESIZE+512]; /* MAXFRAMESIZE */ +static unsigned char *bsbuf=bsspace[1],*bsbufold; +static int bsnum=0; + +static int skip_riff(struct reader *); +static int skip_new_id3(struct reader *); + +unsigned char *pcm_sample; +int pcm_point = 0; +int audiobufsize = AUDIOBUFSIZE; + +static int decode_header(struct frame *fr,unsigned long newhead); + +void safewrite(int fd, const void *buf, size_t count) { + int donesofar = 0; + while(donesofar < count) { + int retval; + char *p = (char*) buf + donesofar; + retval = write(fd,(void*) p,(count-donesofar)); + if(retval == -1) { + if((errno != EINTR) && (errno != EAGAIN)) + exit(fprintf(stderr,"exception on output!\n")); + } else + donesofar += retval; + } +} + +void audio_flush(int outmode, struct audio_info_struct *ai) +{ + if (pcm_point) { + switch (outmode) { +#ifndef NO_DECODE_FILE + case DECODE_FILE: + safewrite (OutputDescriptor, pcm_sample, pcm_point); + break; +#endif +#ifndef NO_DECODE_AUDIO + case DECODE_AUDIO: + audio_play_samples (ai, pcm_sample, pcm_point); + break; +#endif +#ifndef NOXFERMEM + case DECODE_BUFFER: + safewrite (buffer_fd[1], pcm_sample, pcm_point); + break; +#endif +#ifndef NO_DECODE_WAV + case DECODE_WAV: + case DECODE_CDR: + case DECODE_AU: + wav_write(pcm_sample, pcm_point); + break; +#endif + default: + break; + } + pcm_point = 0; + } +} + +#if !defined(WIN32) && !defined(GENERIC) +void (*catchsignal(int signum, void(*handler)()))() +{ + struct sigaction new_sa; + struct sigaction old_sa; + +#ifdef DONT_CATCH_SIGNALS + printf ("Not catching any signals.\n"); + return ((void (*)()) -1); +#endif + + new_sa.sa_handler = handler; + sigemptyset(&new_sa.sa_mask); + new_sa.sa_flags = 0; + if (sigaction(signum, &new_sa, &old_sa) == -1) + return ((void (*)()) -1); + return (old_sa.sa_handler); +} +#endif + +void read_frame_init (struct frame *fr) +{ + fr->firsthead = 0; + fr->thishead = 0; + fr->freeformatsize = 0; +} + +int head_check(unsigned long head) +{ + if( (head & 0xffe00000) != 0xffe00000) + return FALSE; + if(!((head>>17)&3)) + return FALSE; + if( ((head>>12)&0xf) == 0xf) + return FALSE; + if( ((head>>10)&0x3) == 0x3 ) + return FALSE; + + return TRUE; +} + +/* + * return 0: EOF or other stream error + * -1: giving up + * 1: synched + */ +#define MAX_INPUT_FRAMESIZE 1920 +#define SYNC_HEAD_MASK 0xffff0000 +#define SYNC_HEAD_MASK_FF 0x0000f000 +#define LOOK_AHEAD_NUM 3 +#define SCAN_LENGTH 16384 + +#define CHECK_FOR_RIFF 0x0001 +#define CHECK_FOR_ID3_V1 0x0002 +#define CHECK_FOR_ID3_V2 0x0004 + +int sync_stream(struct reader *rds,struct frame *fr,int flags,int *skipped) +{ + int i,j,l,ret; + unsigned long firsthead,nexthead; + struct frame frameInfo,nextInfo; + unsigned char dummybuf[MAX_INPUT_FRAMESIZE]; + int found=0; + int freeformatsize=0; + + for(i=0;ihead_read(rds,&firsthead)) + return 0; + + /* first a few simple checks */ + if( !head_check(firsthead) || !decode_header(&frameInfo,firsthead) ) { + + /* Check for RIFF Headers */ + if( (flags & CHECK_FOR_RIFF) && firsthead == ('R'<<24)+('I'<<16)+('F'<<8)+'F') { + fprintf(stderr,"Found RIFF Header\n"); + ret = skip_riff(rds); + if(ret > 0) { /* RIFF was OK continue with next byte */ + *skipped += ret+4; + continue; + } + if(ret == 0) + return 0; + } + + /* Check for old ID3 Header (or better Footer ;) */ + if( (flags & CHECK_FOR_ID3_V1) && (firsthead>>8) == ('T'<<16)+('A'<<8)+'G') { + fprintf(stderr,"Found old ID3 Header\n"); + } + + /* Check for new ID3 header */ + if( (flags & CHECK_FOR_ID3_V2) && (firsthead>>8) == ('I'<<16)+('D'<<8)+'3') { + if( (firsthead & 0xff) != 0xff) { + fprintf(stderr,"Found new ID3 Header\n"); + ret = skip_new_id3(rds); + if(!ret) + return 0; + if(ret > 0) { + *skipped += ret+4; + continue; + } + } + } + + readers_goto_mark(rds); /* reset to old mark and continue */ + if(!rds->read_frame_body(rds,dummybuf,1)) + return 0; + + (*skipped)++; + continue; + } + + found = 0; + freeformatsize = 0; + + /* + * At the first free format paket we do not know the size + */ + if(frameInfo.bitrate_index == 0) { + int maxframesize = MAX_INPUT_FRAMESIZE; /* FIXME depends on layer and sampling freq */ + +fprintf(stderr,"Searching for next FF header\n"); + + if(!rds->head_read(rds,&nexthead)) + return 0; + + for(j=0;jhead_shift(rds,&nexthead)) + return 0; + } + } + else { + if(!rds->read_frame_body(rds,dummybuf,frameInfo.framesize)) + return 0; + + if(!rds->head_read(rds,&nexthead)) + return 0; + +/* +fprintf(stderr,"S: %08lx %08lx %d %d %d %d\n",firsthead,nexthead, head_check(nexthead),(nexthead & SYNC_HEAD_MASK) == firsthead,(nexthead & SYNC_HEAD_MASK_FF) != 0x0,decode_header(&nextInfo,nexthead)); +*/ + + if( head_check(nexthead) && (nexthead & SYNC_HEAD_MASK) == (firsthead & SYNC_HEAD_MASK) && + (nexthead & SYNC_HEAD_MASK_FF) != 0x0 && decode_header(&nextInfo,nexthead)) { + found = 1; + } + } + + if(!found) { + readers_goto_mark(rds); /* reset to old mark and continue */ + if(!rds->read_frame_body(rds,dummybuf,1)) + return 0; + (*skipped)++; + continue; + } + +/* +fprintf(stderr,"s: %08lx %08lx %d %d %d\n",firsthead,nexthead,frameInfo.framesize,nextInfo.framesize,freeformatsize); +*/ + + /* check some more frames */ + for(l=0;l 0 ) { + size = freeformatsize + nextInfo.padsize; + } + else + size = nextInfo.framesize; + + /* step over data */ + if(!rds->read_frame_body(rds,dummybuf,size)) + return 0; + + if(!rds->head_read(rds,&nexthead)) + return 0; + + if(!head_check(nexthead) || + (nexthead & SYNC_HEAD_MASK) != (firsthead & SYNC_HEAD_MASK) || + !decode_header(&nextInfo,nexthead) ) { + found = 0; + break; + } + if( freeformatsize > 0) { + if( ( nexthead & SYNC_HEAD_MASK_FF ) != 0x0) { + found = 0; + break; + } + } + else { + if( (nexthead & SYNC_HEAD_MASK_FF) == 0x0) { + found = 0; + break; + } + } + } + + if(found) + break; + + readers_goto_mark(rds); /* reset to old mark and continue */ + if(!rds->read_frame_body(rds,dummybuf,1)) /* skip first byte */ + return 0; + (*skipped)++; + + } + + if(i == SCAN_LENGTH) + return -1; + + readers_goto_mark(rds); + fr->freeformatsize = freeformatsize; + fr->firsthead = firsthead; + + return 1; + +} + +/* + * skips the RIFF header at the beginning + * + * returns: 0 = read-error + * -1/-2 = illegal RIFF header (= -2 backstep not valid) + * 1 = skipping succeeded + */ +static int skip_riff(struct reader *rds) +{ + unsigned long length; + unsigned char buf[16]; + + if(!rds->read_frame_body(rds,buf,16)) /* read header information */ + return 0; + + if( strncmp("WAVEfmt ",(char *)buf+4,8) ) /* check 2. signature */ + return -1; + + length = (unsigned long) buf[12] + /* decode the header length */ + (((unsigned long) buf[13])<<8) + + (((unsigned long) buf[14])<<16) + + (((unsigned long) buf[15])<<24); + + if(!rds->skip_bytes(rds,length)) /* will not store data in backbuff! */ + return 0; + + if(!rds->read_frame_body(rds,buf,8)) /* skip "data" plus length */ + return 0; + + if(strncmp("data",(char *)buf,4)) + return -2; + + return length+8+16; +} + +/* + * skips the ID3 header at the beginning + * + * returns: 0 = read-error + * -1 = illegal ID3 header + * 1 = skipping succeeded + */ +static int skip_new_id3(struct reader *rds) +{ + unsigned long length; + unsigned char buf[6]; + + if(!rds->read_frame_body(rds,buf,6)) /* read more header information */ + return 0; + + if(buf[0] == 0xff) + return -1; + + if( (buf[2]|buf[3]|buf[4]|buf[5]) & 0x80) + return -1; + + length = (unsigned long) buf[2] & 0x7f; + length <<= 7; + length += (unsigned long) buf[3] & 0x7f; + length <<= 7; + length += (unsigned long) buf[4] & 0x7f; + length <<= 7; + length += (unsigned long) buf[5] & 0x7f; + + if(!rds->skip_bytes(rds,length)) /* will not store data in backbuff! */ + return 0; + + return length+6; + +} + + + + + +/***************************************************************** + * read next frame + */ +int read_frame(struct reader *rds,struct frame *fr) +{ + unsigned long newhead,oldhead; + static unsigned char ssave[34]; + + oldhead = fr->thishead; + + if (param.halfspeed) { + static int halfphase = 0; + if (halfphase--) { + bsi.bitindex = 0; + bsi.wordpointer = (unsigned char *) bsbuf; + if (fr->lay == 3) + memcpy (bsbuf, ssave, fr->sideInfoSize); + return 1; + } + else + halfphase = param.halfspeed - 1; + } + + while(1) { + + if(!rds->head_read(rds,&newhead)) + return FALSE; + +/* + fprintf(stderr,"n %08lx",newhead); +*/ + + if( !head_check(newhead) || !decode_header(fr,newhead) ) { + if (!param.quiet) + fprintf(stderr,"Illegal Audio-MPEG-Header 0x%08lx at offset 0x%lx.\n", + newhead,rds->tell(rds)-4); + + if(param.tryresync) { + int try = 0; + readers_pushback_header(rds,newhead); + if(sync_stream(rds,fr,0xffff,&try) <= 0) + return 0; + if(!param.quiet) + fprintf (stderr, "Skipped %d bytes in input.\n", try); + } + else + return (0); + } + else + break; + } + +/* + fprintf(stderr,"N %08lx",newhead); +*/ + + fr->header_change = 2; + if(oldhead) { + if((oldhead & 0xc00) == (fr->thishead & 0xc00)) { + if( (oldhead & 0xc0) == 0 && (fr->thishead & 0xc0) == 0) + fr->header_change = 1; + else if( (oldhead & 0xc0) > 0 && (fr->thishead & 0xc0) > 0) + fr->header_change = 1; + } + } + + + if(!fr->bitrate_index) { + fr->framesize = fr->freeformatsize + fr->padsize; + } + +/* +fprintf(stderr,"Reading %d\n",fr->framesize); +*/ + + /* flip/init buffer for Layer 3 */ + /* FIXME for reentrance */ + bsbufold = bsbuf; + bsbufold_end = bsbufend[bsnum]; + bsbuf = bsspace[bsnum]+512; + bsnum = (bsnum + 1) & 1; + bsbufend[bsnum] = fr->framesize; + + /* read main data into memory */ + if(!rds->read_frame_body(rds,bsbuf,fr->framesize)) + return 0; + + { + /* Test */ + static struct vbrHeader head; + static int vbr = 0; /* FIXME */ + if(!vbr) { + getVBRHeader(&head,bsbuf,fr); + vbr = 1; + } + } + + bsi.bitindex = 0; + bsi.wordpointer = (unsigned char *) bsbuf; + + if (param.halfspeed && fr->lay == 3) + memcpy (ssave, bsbuf, fr->sideInfoSize); + + return 1; +} + +/* + * decode a header and write the information + * into the frame structure + */ +static int decode_header(struct frame *fr,unsigned long newhead) +{ + if(!head_check(newhead)) { + fprintf(stderr,"Oopps header is wrong %08lx\n",newhead); + return 0; + } + + if( newhead & (1<<20) ) { + fr->lsf = (newhead & (1<<19)) ? 0x0 : 0x1; + fr->mpeg25 = 0; + } + else { + fr->lsf = 1; + fr->mpeg25 = 1; + } + + /* + * CHECKME: should be add more consistency checks here ? + * changed layer, changed CRC bit, changed sampling frequency + */ + { + fr->lay = 4-((newhead>>17)&3); + if( ((newhead>>10)&0x3) == 0x3) { + fprintf(stderr,"Stream error\n"); + return 0; + } + if(fr->mpeg25) { + fr->sampling_frequency = 6 + ((newhead>>10)&0x3); + } + else + fr->sampling_frequency = ((newhead>>10)&0x3) + (fr->lsf*3); + fr->error_protection = ((newhead>>16)&0x1)^0x1; + } + + fr->bitrate_index = ((newhead>>12)&0xf); + fr->padding = ((newhead>>9)&0x1); + fr->extension = ((newhead>>8)&0x1); + fr->mode = ((newhead>>6)&0x3); + fr->mode_ext = ((newhead>>4)&0x3); + fr->copyright = ((newhead>>3)&0x1); + fr->original = ((newhead>>2)&0x1); + fr->emphasis = newhead & 0x3; + + fr->stereo = (fr->mode == MPG_MD_MONO) ? 1 : 2; + + switch(fr->lay) { + case 1: + fr->framesize = (long) tabsel_123[fr->lsf][0][fr->bitrate_index] * 12000; + fr->framesize /= freqs[fr->sampling_frequency]; + fr->framesize = ((fr->framesize+fr->padding)<<2)-4; + fr->sideInfoSize = 0; + fr->padsize = fr->padding << 2; + break; + case 2: + fr->framesize = (long) tabsel_123[fr->lsf][1][fr->bitrate_index] * 144000; + fr->framesize /= freqs[fr->sampling_frequency]; + fr->framesize += fr->padding - 4; + fr->sideInfoSize = 0; + fr->padsize = fr->padding; + break; + case 3: + if(fr->lsf) + fr->sideInfoSize = (fr->stereo == 1) ? 9 : 17; + else + fr->sideInfoSize = (fr->stereo == 1) ? 17 : 32; + if(fr->error_protection) + fr->sideInfoSize += 2; + fr->framesize = (long) tabsel_123[fr->lsf][2][fr->bitrate_index] * 144000; + fr->framesize /= freqs[fr->sampling_frequency]<<(fr->lsf); + fr->framesize = fr->framesize + fr->padding - 4; + fr->padsize = fr->padding; + break; + default: + fprintf(stderr,"Sorry, unknown layer type.\n"); + return (0); + } + + if(!fr->bitrate_index) { + /* fprintf(stderr,"Warning, Free format not heavily tested: (head %08lx)\n",newhead); */ + fr->framesize = 0; + } + fr->thishead = newhead; + + return 1; +} + +#ifdef MPG123_REMOTE +void print_rheader(struct frame *fr) +{ + static char *modes[4] = { "Stereo", "Joint-Stereo", "Dual-Channel", "Single-Channel" }; + static char *layers[4] = { "Unknown" , "I", "II", "III" }; + static char *mpeg_type[2] = { "1.0" , "2.0" }; + + /* version, layer, freq, mode, channels, bitrate, BPF */ + fprintf(stderr,"@I %s %s %ld %s %d %d %d\n", + mpeg_type[fr->lsf],layers[fr->lay],freqs[fr->sampling_frequency], + modes[fr->mode],fr->stereo, + tabsel_123[fr->lsf][fr->lay-1][fr->bitrate_index], + fr->framesize+4); +} +#endif + +void print_header(struct frame *fr) +{ + static char *modes[4] = { "Stereo", "Joint-Stereo", "Dual-Channel", "Single-Channel" }; + static char *layers[4] = { "Unknown" , "I", "II", "III" }; + + fprintf(stderr,"MPEG %s, Layer: %s, Freq: %ld, mode: %s, modext: %d, BPF : %d\n", + fr->mpeg25 ? "2.5" : (fr->lsf ? "2.0" : "1.0"), + layers[fr->lay],freqs[fr->sampling_frequency], + modes[fr->mode],fr->mode_ext,fr->framesize+4); + fprintf(stderr,"Channels: %d, copyright: %s, original: %s, CRC: %s, emphasis: %d.\n", + fr->stereo,fr->copyright?"Yes":"No", + fr->original?"Yes":"No",fr->error_protection?"Yes":"No", + fr->emphasis); + fprintf(stderr,"Bitrate: %d Kbits/s, Extension value: %d\n", + tabsel_123[fr->lsf][fr->lay-1][fr->bitrate_index],fr->extension); +} + +void print_header_compact(struct frame *fr) +{ + static char *modes[4] = { "stereo", "joint-stereo", "dual-channel", "mono" }; + static char *layers[4] = { "Unknown" , "I", "II", "III" }; + + fprintf(stderr,"MPEG %s layer %s, %d kbit/s, %ld Hz %s\n", + fr->mpeg25 ? "2.5" : (fr->lsf ? "2.0" : "1.0"), + layers[fr->lay], + tabsel_123[fr->lsf][fr->lay-1][fr->bitrate_index], + freqs[fr->sampling_frequency], modes[fr->mode]); +} + +void print_id3_tag(unsigned char *buf) +{ + struct id3tag { + char tag[3]; + char title[30]; + char artist[30]; + char album[30]; + char year[4]; + char comment[30]; + unsigned char genre; + }; + struct id3tag *tag = (struct id3tag *) buf; + char title[31]={0,}; + char artist[31]={0,}; + char album[31]={0,}; + char year[5]={0,}; + char comment[31]={0,}; + char genre[31]={0,}; + + if(param.quiet) + return; + + strncpy(title,tag->title,30); + strncpy(artist,tag->artist,30); + strncpy(album,tag->album,30); + strncpy(year,tag->year,4); + strncpy(comment,tag->comment,30); + + if ( tag->genre < sizeof(genre_table)/sizeof(*genre_table) ) { + strncpy(genre, genre_table[tag->genre], 30); + } else { + strncpy(genre,"Unknown",30); + } + + fprintf(stderr,"Title : %-30s Artist: %s\n",title,artist); + fprintf(stderr,"Album : %-30s Year : %4s\n",album,year); + fprintf(stderr,"Comment: %-30s Genre : %s\n",comment,genre); +} + +#if 0 +/* removed the strndup for better portability */ +/* + * Allocate space for a new string containing the first + * "num" characters of "src". The resulting string is + * always zero-terminated. Returns NULL if malloc fails. + */ +char *strndup (const char *src, int num) +{ + char *dst; + + if (!(dst = (char *) malloc(num+1))) + return (NULL); + dst[num] = '\0'; + return (strncpy(dst, src, num)); +} +#endif + +/* + * Split "path" into directory and filename components. + * + * Return value is 0 if no directory was specified (i.e. + * "path" does not contain a '/'), OR if the directory + * is the same as on the previous call to this function. + * + * Return value is 1 if a directory was specified AND it + * is different from the previous one (if any). + */ + +int split_dir_file (const char *path, char **dname, char **fname) +{ + static char *lastdir = NULL; + char *slashpos; + + if ((slashpos = strrchr(path, '/'))) { + *fname = slashpos + 1; + *dname = strdup(path); /* , 1 + slashpos - path); */ + if(!(*dname)) { + perror("memory"); + exit(1); + } + (*dname)[1 + slashpos - path] = 0; + if (lastdir && !strcmp(lastdir, *dname)) { + /*** same as previous directory ***/ + free (*dname); + *dname = lastdir; + return 0; + } + else { + /*** different directory ***/ + if (lastdir) + free (lastdir); + lastdir = *dname; + return 1; + } + } + else { + /*** no directory specified ***/ + if (lastdir) { + free (lastdir); + lastdir = NULL; + }; + *dname = NULL; + *fname = (char *)path; + return 0; + } +} + +void set_pointer(int ssize,long backstep) +{ + bsi.wordpointer = bsbuf + ssize - backstep; + if (backstep) + memcpy(bsi.wordpointer,bsbufold+bsbufold_end-backstep,backstep); + bsi.bitindex = 0; +} + +/********************************/ + +double compute_bpf(struct frame *fr) +{ + double bpf; + + if(!fr->bitrate_index) { + return fr->freeformatsize + 4; + } + + switch(fr->lay) { + case 1: + bpf = tabsel_123[fr->lsf][0][fr->bitrate_index]; + bpf *= 12000.0 * 4.0; + bpf /= freqs[fr->sampling_frequency] <<(fr->lsf); + break; + case 2: + case 3: + bpf = tabsel_123[fr->lsf][fr->lay-1][fr->bitrate_index]; + bpf *= 144000; + bpf /= freqs[fr->sampling_frequency] << (fr->lsf); + break; + default: + bpf = 1.0; + } + + return bpf; +} + +double compute_tpf(struct frame *fr) +{ + static int bs[4] = { 0,384,1152,1152 }; + double tpf; + + tpf = (double) bs[fr->lay]; + tpf /= freqs[fr->sampling_frequency] << (fr->lsf); + return tpf; +} + +/* + * Returns number of frames queued up in output buffer, i.e. + * offset between currently played and currently decoded frame. + */ + +#ifndef NOXFERMEM +long compute_buffer_offset(struct frame *fr) +{ + long bufsize; + + /* + * buffermem->buf[0] holds output sampling rate, + * buffermem->buf[1] holds number of channels, + * buffermem->buf[2] holds audio format of output. + */ + + if(!param.usebuffer || !(bufsize=xfermem_get_usedspace(buffermem)) + || !buffermem->buf[0] || !buffermem->buf[1]) + return 0; + + bufsize = (long)((double) bufsize / buffermem->buf[0] / + buffermem->buf[1] / compute_tpf(fr)); + + if((buffermem->buf[2] & AUDIO_FORMAT_MASK) == AUDIO_FORMAT_16) + return bufsize/2; + else + return bufsize; +} +#endif + +void print_stat(struct reader *rds,struct frame *fr,int no,long buffsize,struct audio_info_struct *ai) +{ + double bpf,tpf,tim1,tim2; + double dt = 0.0; + int sno,rno; + char outbuf[256]; + + if(!rds || !fr) + return; + + outbuf[0] = 0; + +#ifndef GENERIC + { + struct timeval t; + fd_set serr; + int n,errfd = fileno(stderr); + + t.tv_sec=t.tv_usec=0; + + FD_ZERO(&serr); + FD_SET(errfd,&serr); + n = select(errfd+1,NULL,&serr,NULL,&t); + if(n <= 0) + return; + } +#endif + + bpf = compute_bpf(fr); + tpf = compute_tpf(fr); + + if(buffsize > 0 && ai && ai->rate > 0 && ai->channels > 0) { + dt = (double) buffsize / ai->rate / ai->channels; + if( (ai->format & AUDIO_FORMAT_MASK) == AUDIO_FORMAT_16) + dt *= 0.5; + } + + rno = 0; + sno = no; + if(rds->filelen >= 0) { + long t = rds->tell(rds); + rno = (int)((double)(rds->filelen-t)/bpf); + sno = (int)((double)t/bpf); + } + + sprintf(outbuf+strlen(outbuf),"\rFrame# %5d [%5d], ",sno,rno); + + tim1 = sno*tpf-dt; + tim2 = rno*tpf+dt; +#if 0 + tim1 = tim1 < 0 ? 0.0 : tim1; +#endif + tim2 = tim2 < 0 ? 0.0 : tim2; + + sprintf(outbuf+strlen(outbuf),"Time: %02u:%02u.%02u [%02u:%02u.%02u], ", + (unsigned int)tim1/60, + (unsigned int)tim1%60, + (unsigned int)(tim1*100)%100, + (unsigned int)tim2/60, + (unsigned int)tim2%60, + (unsigned int)(tim2*100)%100); + + if(param.usebuffer) + sprintf(outbuf+strlen(outbuf),"[%8ld] ",(long)buffsize); + write(fileno(stderr),outbuf,strlen(outbuf)); +#if 0 + fflush(out); /* hmm not really nec. */ +#endif +} + +int get_songlen(struct reader *rds,struct frame *fr,int no) +{ + double tpf; + + if(!fr) + return 0; + + if(no < 0) { + if(!rds || rds->filelen < 0) + return 0; + no = (double) rds->filelen / compute_bpf(fr); + } + + tpf = compute_tpf(fr); + return no*tpf; +} + + -- cgit v1.2.1