From 9bad163654064dabe6daaefacf1329fca0260e01 Mon Sep 17 00:00:00 2001 From: Cary Sandvig Date: Wed, 11 Oct 2000 22:56:57 +0000 Subject: [PATCH] foo --- panda/src/mpg123/common.c | 721 +++++++++++++++++++++++++++++++++++++ panda/src/mpg123/common.h | 19 + panda/src/mpg123/genre.h | 263 ++++++++++++++ panda/src/mpg123/getbits.c | 127 +++++++ panda/src/mpg123/getbits.h | 33 ++ panda/src/mpg123/mpg123.h | 411 +++++++++++++++++++++ panda/src/mpg123/xfermem.c | 279 ++++++++++++++ panda/src/mpg123/xfermem.h | 60 +++ 8 files changed, 1913 insertions(+) create mode 100644 panda/src/mpg123/common.c create mode 100644 panda/src/mpg123/common.h create mode 100644 panda/src/mpg123/genre.h create mode 100644 panda/src/mpg123/getbits.c create mode 100644 panda/src/mpg123/getbits.h create mode 100644 panda/src/mpg123/mpg123.h create mode 100644 panda/src/mpg123/xfermem.c create mode 100644 panda/src/mpg123/xfermem.h diff --git a/panda/src/mpg123/common.c b/panda/src/mpg123/common.c new file mode 100644 index 0000000000..90398f463d --- /dev/null +++ b/panda/src/mpg123/common.c @@ -0,0 +1,721 @@ +/* GPL clean */ + +#include +#include +#include + +#include +#include +#include + +#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 fsizeold=0,ssize; +static unsigned char bsspace[2][MAXFRAMESIZE+512]; /* MAXFRAMESIZE */ +static unsigned char *bsbuf=bsspace[1],*bsbufold; +static int bsnum=0; + +static unsigned long oldhead = 0; +unsigned long firsthead=0; + +unsigned char *pcm_sample; +int pcm_point = 0; +int audiobufsize = AUDIOBUFSIZE; + +static int decode_header(struct frame *fr,unsigned long newhead); + +void audio_flush(int outmode, struct audio_info_struct *ai) +{ + if (pcm_point) { + switch (outmode) { + case DECODE_FILE: + write (OutputDescriptor, pcm_sample, pcm_point); + break; + case DECODE_AUDIO: + audio_play_samples (ai, pcm_sample, pcm_point); + break; + case DECODE_BUFFER: + write (buffer_fd[1], pcm_sample, pcm_point); + break; + case DECODE_WAV: + case DECODE_CDR: + case DECODE_AU: + wav_write(pcm_sample, pcm_point); + 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 (void) +{ + oldhead = 0; + firsthead = 0; +} + +int head_check(unsigned long head) +{ +/* fprintf(stderr,"HC"); */ + 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; +#if 0 + /* this would match on MPEG1/Layer1 streams with CRC = off */ + if ((head & 0xffff0000) == 0xffff0000) + return FALSE; +#endif + + return TRUE; +} + + + +/***************************************************************** + * read next frame + */ +int read_frame(struct frame *fr) +{ + unsigned long newhead; + static unsigned char ssave[34]; + + fsizeold=fr->framesize; /* for Layer3 */ + + if (param.halfspeed) { + static int halfphase = 0; + if (halfphase--) { + bsi.bitindex = 0; + bsi.wordpointer = (unsigned char *) bsbuf; + if (fr->lay == 3) + memcpy (bsbuf, ssave, ssize); + return 1; + } + else + halfphase = param.halfspeed - 1; + } + + read_again: + if(!rd->head_read(rd,&newhead)) + return FALSE; + + if(1 || oldhead != newhead || !oldhead) { + + init_resync: + + fr->header_change = 2; + if(oldhead) { + if((oldhead & 0xc00) == (newhead & 0xc00)) { + if( (oldhead & 0xc0) == 0 && (newhead & 0xc0) == 0) + fr->header_change = 1; + else if( (oldhead & 0xc0) > 0 && (newhead & 0xc0) > 0) + fr->header_change = 1; + } + } + + +#ifdef SKIP_JUNK + if(!firsthead && !head_check(newhead) ) { + int i; + + fprintf(stderr,"Junk at the beginning %08lx\n",newhead); + + /* I even saw RIFF headers at the beginning of MPEG streams ;( */ + if(newhead == ('R'<<24)+('I'<<16)+('F'<<8)+'F') { + if(!rd->head_read(rd,&newhead)) + return 0; + while(newhead != ('d'<<24)+('a'<<16)+('t'<<8)+'a') { + if(!rd->head_shift(rd,&newhead)) + return 0; + } + if(!rd->head_read(rd,&newhead)) + return 0; + /* fprintf(stderr,"Skipped RIFF header!\n"); */ + goto read_again; + } + { + /* step in byte steps through next 64K */ + for(i=0;i<65536;i++) { + if(!rd->head_shift(rd,&newhead)) + return 0; + if(head_check(newhead)) + break; + } + if(i == 65536) { + fprintf(stderr,"Giving up searching valid MPEG header\n"); + return 0; + } + } + /* + * should we additionaly check, whether a new frame starts at + * the next expected position? (some kind of read ahead) + * We could implement this easily, at least for files. + */ + } +#endif + + if( (newhead & 0xffe00000) != 0xffe00000) { + if (!param.quiet) + fprintf(stderr,"Illegal Audio-MPEG-Header 0x%08lx at offset 0x%lx.\n", + newhead,rd->tell(rd)-4); + /* and those ugly ID3 tags */ + if((newhead & 0xffffff00) == ('T'<<24)+('A'<<16)+('G'<<8)) { + rd->skip_bytes(rd,124); + fprintf(stderr,"Skipped ID3 Tag!\n"); + goto read_again; + } + if (param.tryresync) { + int try = 0; + /* Read more bytes until we find something that looks + reasonably like a valid header. This is not a + perfect strategy, but it should get us back on the + track within a short time (and hopefully without + too much distortion in the audio output). */ + do { + try++; + if(!rd->head_shift(rd,&newhead)) + return 0; + if (!oldhead) + goto init_resync; /* "considered harmful", eh? */ + + } while ((newhead & HDRCMPMASK) != (oldhead & HDRCMPMASK) + && (newhead & HDRCMPMASK) != (firsthead & HDRCMPMASK)); + if (!param.quiet) + fprintf (stderr, "Skipped %d bytes in input.\n", try); + } + else + return (0); + } + +/* fprintf(stderr,"+"); */ + + if (!firsthead) { + if(!decode_header(fr,newhead)) { +/* fprintf(stderr,"A"); */ + goto read_again; + } + firsthead = newhead; + + } + else if(!decode_header(fr,newhead)) { +/* fprintf(stderr,"B: %08lx\n",newhead); */ + return 0; + } + +/* fprintf(stderr,"-"); */ + } + else + fr->header_change = 0; + +/* fprintf(stderr,"FS: %d\n",fr->framesize); */ + + /* flip/init buffer for Layer 3 */ + bsbufold = bsbuf; + bsbuf = bsspace[bsnum]+512; + bsnum = (bsnum + 1) & 1; + + /* read main data into memory */ + if(!rd->read_frame_body(rd,bsbuf,fr->framesize)) + return 0; + + { + /* Test */ + static struct vbrHeader head; + static int vbr = 0; + if(!vbr) { + getVBRHeader(&head,bsbuf,fr); + vbr = 1; + } + } + +/* fprintf(stderr,"Got it\n"); */ + + bsi.bitindex = 0; + bsi.wordpointer = (unsigned char *) bsbuf; + + if (param.halfspeed && fr->lay == 3) + memcpy (ssave, bsbuf, ssize); + + return 1; +} + +/**************************************** + * HACK,HACK,HACK: step back frames + * can only work if the 'stream' isn't a real stream but a file + */ +int back_frame(struct reader *rds,struct frame *fr,int num) +{ + long bytes; + unsigned long newhead; + + if(!firsthead) + return 0; + + bytes = (fr->framesize+8)*(num+2); + + if(rds->back_bytes(rds,bytes) < 0) + return -1; + if(!rds->head_read(rds,&newhead)) + return -1; + + while( (newhead & HDRCMPMASK) != (firsthead & HDRCMPMASK) ) { + if(!rds->head_shift(rds,&newhead)) + return -1; + } + + if(rds->back_bytes(rds,4) <0) + return -1; + + read_frame(fr); + read_frame(fr); + + if(fr->lay == 3) { + set_pointer(512); + } + + return 0; +} + + +/* + * 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\n"); + return 0; + } + + if( newhead & (1<<20) ) { + fr->lsf = (newhead & (1<<19)) ? 0x0 : 0x1; + fr->mpeg25 = 0; + } + else { + fr->lsf = 1; + fr->mpeg25 = 1; + } + + if (!param.tryresync || !oldhead) { + /* If "tryresync" is true, assume that certain + parameters do not change within the stream! */ + fr->lay = 4-((newhead>>17)&3); + if( ((newhead>>10)&0x3) == 0x3) { + fprintf(stderr,"Stream error\n"); + exit(1); + } + 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; + + oldhead = newhead; + + if(!fr->bitrate_index) { + fprintf(stderr,"Free format not supported: (head %08lx)\n",newhead); + return (0); + } + + 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; + 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; + break; + case 3: + if(fr->lsf) + ssize = (fr->stereo == 1) ? 9 : 17; + else + ssize = (fr->stereo == 1) ? 17 : 32; + if(fr->error_protection) + ssize += 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; + break; + default: + fprintf(stderr,"Sorry, unknown layer type.\n"); + return (0); + } + 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(long backstep) +{ + bsi.wordpointer = bsbuf + ssize - backstep; + if (backstep) + memcpy(bsi.wordpointer,bsbufold+fsizeold-backstep,backstep); + bsi.bitindex = 0; +} + +/********************************/ + +double compute_bpf(struct frame *fr) +{ + double bpf; + + 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. + */ + +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; +} + +void print_stat(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(!rd || !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(rd->filelen >= 0) { + long t = rd->tell(rd); + rno = (int)((double)(rd->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 frame *fr,int no) +{ + double tpf; + + if(!fr) + return 0; + + if(no < 0) { + if(!rd || rd->filelen < 0) + return 0; + no = (double) rd->filelen / compute_bpf(fr); + } + + tpf = compute_tpf(fr); + return no*tpf; +} + + diff --git a/panda/src/mpg123/common.h b/panda/src/mpg123/common.h new file mode 100644 index 0000000000..716a3c836d --- /dev/null +++ b/panda/src/mpg123/common.h @@ -0,0 +1,19 @@ +/* + * common.h + */ + +extern void print_id3_tag(unsigned char *buf); +extern unsigned long firsthead; +extern int tabsel_123[2][3][16]; +extern double compute_tpf(struct frame *fr); +extern double compute_bpf(struct frame *fr); +extern long compute_buffer_offset(struct frame *fr); + +/* +struct bitstream_info { + int bitindex; + unsigned char *wordpointer; +}; +*/ + + diff --git a/panda/src/mpg123/genre.h b/panda/src/mpg123/genre.h new file mode 100644 index 0000000000..3a6c5ba397 --- /dev/null +++ b/panda/src/mpg123/genre.h @@ -0,0 +1,263 @@ +char *genre_table[] = +{ + "Blues", + "Classic Rock", + "Country", + "Dance", + "Disco", + "Funk", + "Grunge", + "Hip-Hop", + "Jazz", + "Metal", + "New Age", + "Oldies", + "Other", + "Pop", + "R&B", + "Rap", + "Reggae", + "Rock", + "Techno", + "Industrial", + "Alternative", + "Ska", + "Death Metal", + "Pranks", + "Soundtrack", + "Euro-Techno", + "Ambient", + "Trip-Hop", + "Vocal", + "Jazz+Funk", + "Fusion", + "Trance", + "Classical", + "Instrumental", + "Acid", + "House", + "Game", + "Sound Clip", + "Gospel", + "Noise", + "AlternRock", + "Bass", + "Soul", + "Punk", + "Space", + "Meditative", + "Instrumental Pop", + "Instrumental Rock", + "Ethnic", + "Gothic", + "Darkwave", + "Techno-Industrial", + "Electronic", + "Pop-Folk", + "Eurodance", + "Dream", + "Southern Rock", + "Comedy", + "Cult", + "Gangsta", + "Top 40", + "Christian Rap", + "Pop/Funk", + "Jungle", + "Native American", + "Cabaret", + "New Wave", + "Psychadelic", + "Rave", + "Showtunes", + "Trailer", + "Lo-Fi", + "Tribal", + "Acid Punk", + "Acid Jazz", + "Polka", + "Retro", + "Musical", + "Rock & Roll", + "Hard Rock", + "Folk", + "Folk/Rock", + "National folk", + "Swing", + "Fast-fusion", + "Bebob", + "Latin", + "Revival", + "Celtic", + "Bluegrass", + "Avantgarde", + "Gothic Rock", + "Progressive Rock", + "Psychedelic Rock", + "Symphonic Rock", + "Slow Rock", + "Big Band", + "Chorus", + "Easy Listening", + "Acoustic", + "Humour", + "Speech", + "Chanson", + "Opera", + "Chamber Music", + "Sonata", + "Symphony", + "Booty Bass", + "Primus", + "Porn Groove", + "Satire", + "Slow Jam", + "Club", + "Tango", + "Samba", + "Folklore", + "Ballad", + "Powder Ballad", + "Rhythmic Soul", + "Freestyle", + "Duet", + "Punk Rock", + "Drum Solo", + "A Capella", + "Euro-House", + "Dance Hall", + "Goa", + "Drum & Bass", + "Club House", + "Hardcore", + "Terror", + "Indie", + "BritPop", + "NegerPunk", + "Polsk Punk", + "Beat", + "Christian Gangsta", + "Heavy Metal", + "Black Metal", + "Crossover", + "Contemporary C", + "Christian Rock", + "Merengue", + "Salsa", + "Thrash Metal", + "Anime", + "JPop", + "SynthPop" +/* , + "Unknown", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" +*/ +}; + +const int genre_count = ((int)(sizeof(genre_table)/sizeof(char*))-1); diff --git a/panda/src/mpg123/getbits.c b/panda/src/mpg123/getbits.c new file mode 100644 index 0000000000..641c6cbba2 --- /dev/null +++ b/panda/src/mpg123/getbits.c @@ -0,0 +1,127 @@ +#include "mpg123.h" +#include "common.h" + +#if 0 +static void check_buffer_range(int size) +{ + int pos = (bsi->wordpointer-bsbuf) + (size>>3); + + if( pos >= fsizeold) { + fprintf(stderr,"Pointer out of range (%d,%d)!\n",pos,fsizeold); + } +} +#endif + +void backbits(struct bitstream_info *bsi,int number_of_bits) +{ + bsi->bitindex -= number_of_bits; + bsi->wordpointer += (bsi->bitindex>>3); + bsi->bitindex &= 0x7; +} + +int getbitoffset(struct bitstream_info *bsi) +{ + return (-bsi->bitindex)&0x7; +} + +int getbyte(struct bitstream_info *bsi) +{ +#ifdef DEBUG_GETBITS + if(bsi->bitindex) + fprintf(stderr,"getbyte called unsynched!\n"); +#endif + return *bsi->wordpointer++; +} + +unsigned int getbits(struct bitstream_info *bsi,int number_of_bits) +{ + unsigned long rval; + +#ifdef DEBUG_GETBITS +fprintf(stderr,"g%d",number_of_bits); +#endif + + if(!number_of_bits) + return 0; + +#if 0 + check_buffer_range(number_of_bits+bsi->bitindex); +#endif + + { + rval = bsi->wordpointer[0]; + rval <<= 8; + rval |= bsi->wordpointer[1]; + rval <<= 8; + rval |= bsi->wordpointer[2]; + + rval <<= bsi->bitindex; + rval &= 0xffffff; + + bsi->bitindex += number_of_bits; + + rval >>= (24-number_of_bits); + + bsi->wordpointer += (bsi->bitindex>>3); + bsi->bitindex &= 7; + } + +#ifdef DEBUG_GETBITS +fprintf(stderr,":%x ",rval); +#endif + + return rval; +} + +unsigned int getbits_fast(struct bitstream_info *bsi,int number_of_bits) +{ + unsigned int rval; +#ifdef DEBUG_GETBITS +fprintf(stderr,"g%d",number_of_bits); +#endif + +#if 0 + check_buffer_range(number_of_bits+bsi->bitindex); +#endif + + rval = (unsigned char) (bsi->wordpointer[0] << bsi->bitindex); + rval |= ((unsigned int) bsi->wordpointer[1]<bitindex)>>8; + rval <<= number_of_bits; + rval >>= 8; + + bsi->bitindex += number_of_bits; + + bsi->wordpointer += (bsi->bitindex>>3); + bsi->bitindex &= 7; + +#ifdef DEBUG_GETBITS +fprintf(stderr,":%x ",rval); +#endif + return rval; +} + +unsigned int get1bit(struct bitstream_info *bsi) +{ + unsigned char rval; + +#ifdef DEBUG_GETBITS +fprintf(stderr,"g%d",1); +#endif + +#if 0 + check_buffer_range(1+bsi->bitindex); +#endif + + rval = *(bsi->wordpointer) << bsi->bitindex; + + bsi->bitindex++; + bsi->wordpointer += (bsi->bitindex>>3); + bsi->bitindex &= 7; + +#ifdef DEBUG_GETBITS +fprintf(stderr,":%d ",rval>>7); +#endif + + return rval>>7; +} + diff --git a/panda/src/mpg123/getbits.h b/panda/src/mpg123/getbits.h new file mode 100644 index 0000000000..034023d4b6 --- /dev/null +++ b/panda/src/mpg123/getbits.h @@ -0,0 +1,33 @@ + +/* that's the same file as getits.c but with defines to + force inlining */ + +static unsigned long rval; +static unsigned char rval_uc; + +#define backbits(nob) ((void)( \ + bsi.bitindex -= (nob), \ + bsi.wordpointer += (bsi.bitindex>>3), \ + bsi.bitindex &= 0x7 )) + +#define getbitoffset() ((-bsi.bitindex)&0x7) +#define getbyte() (*bsi.wordpointer++) + +#define getbits(nob) ( \ + rval = bsi.wordpointer[0], rval <<= 8, rval |= bsi.wordpointer[1], \ + rval <<= 8, rval |= bsi.wordpointer[2], rval <<= bsi.bitindex, \ + rval &= 0xffffff, bsi.bitindex += (nob), \ + rval >>= (24-(nob)), bsi.wordpointer += (bsi.bitindex>>3), \ + bsi.bitindex &= 7,rval) + +#define getbits_fast(nob) ( \ + rval = (unsigned char) (bsi.wordpointer[0] << bsi.bitindex), \ + rval |= ((unsigned long) bsi.wordpointer[1]<>8, \ + rval <<= (nob), rval >>= 8, \ + bsi.bitindex += (nob), bsi.wordpointer += (bsi.bitindex>>3), \ + bsi.bitindex &= 7, rval ) + +#define get1bit() ( \ + rval_uc = *bsi.wordpointer << bsi.bitindex, bsi.bitindex++, \ + bsi.wordpointer += (bsi.bitindex>>3), bsi.bitindex &= 7, rval_uc>>7 ) + diff --git a/panda/src/mpg123/mpg123.h b/panda/src/mpg123/mpg123.h new file mode 100644 index 0000000000..3d7c8d6daa --- /dev/null +++ b/panda/src/mpg123/mpg123.h @@ -0,0 +1,411 @@ +/* + * mpg123 defines + * used source: musicout.h from mpegaudio package + */ + +#include +#include +#include + +#ifndef WIN32 +#include +#include +#endif + +#include + +typedef unsigned char byte; + +#ifdef OS2 +#include +#endif + +#define MPG123_REMOTE +#ifdef HPUX +#define random rand +#define srandom srand +#endif + +#define FRONTEND_NONE 0 +#define FRONTEND_SAJBER 1 +#define FRONTEND_TK3PLAY 2 +#define FRONTEND_GENERIC 3 + +#define SKIP_JUNK 1 + +#ifdef _WIN32 /* Win32 Additions By Tony Million */ +# undef WIN32 +# define WIN32 + +# define M_PI 3.14159265358979323846 +# define M_SQRT2 1.41421356237309504880 +# define REAL_IS_FLOAT +# define NEW_DCT9 + +# define random rand +# define srandom srand + +# undef MPG123_REMOTE /* Get rid of this stuff for Win32 */ +#endif + +#include "xfermem.h" + +#ifdef SUNOS +#define memmove(dst,src,size) bcopy(src,dst,size) +#endif + +#ifdef REAL_IS_FLOAT +# define real float +#elif defined(REAL_IS_LONG_DOUBLE) +# define real long double +#else +# define real double +#endif + +#ifdef __GNUC__ +#define INLINE inline +#else +#define INLINE +#endif + +#include "audio.h" + +/* AUDIOBUFSIZE = n*64 with n=1,2,3 ... */ +#define AUDIOBUFSIZE 16384 + +#define FALSE 0 +#define TRUE 1 + +#define MAX_NAME_SIZE 81 +#define SBLIMIT 32 +#define SCALE_BLOCK 12 +#define SSLIMIT 18 + +#define MPG_MD_STEREO 0 +#define MPG_MD_JOINT_STEREO 1 +#define MPG_MD_DUAL_CHANNEL 2 +#define MPG_MD_MONO 3 + +#define MAXFRAMESIZE 1792 +#define HDRCMPMASK 0xfffffd00 + +#define MAXOUTBURST 32768 + +/* Pre Shift fo 16 to 8 bit converter table */ +#define AUSHIFT (3) + + +struct al_table +{ + short bits; + short d; +}; + +struct frame { + struct al_table *alloc; + int (*synth)(real *,int,unsigned char *,int *); + int (*synth_mono)(real *,unsigned char *,int *); +#ifdef USE_3DNOW + void (*dct36)(real *,real *,real *,real *,real *); +#endif + int stereo; + int jsbound; + int single; + int II_sblimit; + int down_sample_sblimit; + int lsf; + int mpeg25; + int down_sample; + int header_change; + int lay; + int error_protection; + int bitrate_index; + int sampling_frequency; + int padding; + int extension; + int mode; + int mode_ext; + int copyright; + int original; + int emphasis; + int framesize; /* computed framesize */ +}; + +#define VBR_TOC_SIZE 100 + +#define VBR_FRAMES_FLAG 0x0001 +#define VBR_BYTES_FLAG 0x0002 +#define VBR_TOC_FLAG 0x0004 +#define VBR_SCALE_FLAG 0x0008 + +struct vbrHeader { + unsigned long flags; + unsigned long frames; + unsigned long bytes; + unsigned long scale; + unsigned char toc[100]; +}; + +struct parameter { + int aggressive; /* renice to max. priority */ + int shuffle; /* shuffle/random play */ + int remote; /* remote operation */ + int outmode; /* where to out the decoded sampels */ + int quiet; /* shut up! */ + int xterm_title; /* print filename in xterm title */ + long usebuffer; /* second level buffer size */ + int tryresync; /* resync stream after error */ + int verbose; /* verbose level */ +#ifdef TERM_CONTROL + int term_ctrl; +#endif + int force_mono; + int force_stereo; + int force_8bit; + long force_rate; + int down_sample; + int checkrange; + long doublespeed; + long halfspeed; + int force_reopen; + int stat_3dnow; /* automatic/force/force-off 3DNow! optimized code */ + int test_3dnow; + long realtime; + char filename[256]; + char *esdserver; + char *equalfile; + int enable_equalizer; + long outscale; + long startFrame; +}; + +struct bitstream_info { + int bitindex; + unsigned char *wordpointer; +}; + +struct mpstr { + int bsize; + int framesize; + int fsizeold; + struct frame fr; + /* int (*do_layer)(struct mpstr *,struct frame *fr,int,struct audio_info_struct *); */ + unsigned char bsspace[2][MAXFRAMESIZE+512]; /* MAXFRAMESIZE */ + real hybrid_block[2][2][SBLIMIT*SSLIMIT]; + int hybrid_blc[2]; + unsigned long header; + int bsnum; + real synth_buffs[2][2][0x110]; + int synth_bo; + + struct bitstream_info bsi; +}; + +extern struct bitstream_info bsi; + +struct reader { + int (*init)(struct reader *); + void (*close)(struct reader *); + int (*head_read)(struct reader *,unsigned long *newhead); + int (*head_shift)(struct reader *,unsigned long *head); + int (*skip_bytes)(struct reader *,int len); + int (*read_frame_body)(struct reader *,unsigned char *,int size); + int (*back_bytes)(struct reader *,int bytes); + int (*back_frame)(struct reader *,struct frame *,int num); + long (*tell)(struct reader *); + void (*rewind)(struct reader *); + long filelen; + long filepos; + int filept; + int flags; + unsigned char id3buf[128]; +}; +#define READER_FD_OPENED 0x1 +#define READER_ID3TAG 0x2 + +extern struct reader *rd,readers[]; + +extern int halfspeed; +extern int buffer_fd[2]; +extern txfermem *buffermem; +extern char *prgName, *prgVersion; + +#ifndef NOXFERMEM +extern void buffer_loop(struct audio_info_struct *ai,sigset_t *oldsigset); +#endif + + +/* ------ Declarations from "httpget.c" ------ */ + +extern char *proxyurl; +extern unsigned long proxyip; +extern int http_open (char *url); +extern char *httpauth; + +/* ------ Declarations from "common.c" ------ */ + +extern void audio_flush(int, struct audio_info_struct *); +extern void (*catchsignal(int signum, void(*handler)()))(); + +extern void print_header(struct frame *); +extern void print_header_compact(struct frame *); +extern void print_id3_tag(unsigned char *buf); + +extern int split_dir_file(const char *path, char **dname, char **fname); + +extern unsigned int get1bit(struct bitstream_info *); +extern unsigned int getbits(struct bitstream_info *,int); +extern unsigned int getbits_fast(struct bitstream_info *,int); +extern void backbits(struct bitstream_info *,int); +extern int getbitoffset(struct bitstream_info *); +extern int getbyte(struct bitstream_info *); + +extern void set_pointer(long); + +extern unsigned char *pcm_sample; +extern int pcm_point; +extern int audiobufsize; + +extern int OutputDescriptor; + +struct gr_info_s { + int scfsi; + unsigned part2_3_length; + unsigned big_values; + unsigned scalefac_compress; + unsigned block_type; + unsigned mixed_block_flag; + unsigned table_select[3]; + unsigned subblock_gain[3]; + unsigned maxband[3]; + unsigned maxbandl; + unsigned maxb; + unsigned region1start; + unsigned region2start; + unsigned preflag; + unsigned scalefac_scale; + unsigned count1table_select; + real *full_gain[3]; + real *pow2gain; +}; + +struct III_sideinfo +{ + unsigned main_data_begin; + unsigned private_bits; + struct { + struct gr_info_s gr[2]; + } ch[2]; +}; + +extern struct reader *open_stream(char *,int fd); +extern void read_frame_init (void); +extern int read_frame(struct frame *fr); +extern int play_frame(struct mpstr *mp,int init,struct frame *fr); +extern int do_layer3(struct mpstr *mp,struct frame *fr,int,struct audio_info_struct *); +extern int do_layer2(struct mpstr *mp,struct frame *fr,int,struct audio_info_struct *); +extern int do_layer1(struct mpstr *mp,struct frame *fr,int,struct audio_info_struct *); +extern void do_equalizer(real *bandPtr,int channel); + +#ifdef PENTIUM_OPT +extern int synth_1to1_pent (real *,int,unsigned char *); +#endif +extern int synth_1to1 (real *,int,unsigned char *,int *); +extern int synth_1to1_8bit (real *,int,unsigned char *,int *); +extern int synth_1to1_mono (real *,unsigned char *,int *); +extern int synth_1to1_mono2stereo (real *,unsigned char *,int *); +extern int synth_1to1_8bit_mono (real *,unsigned char *,int *); +extern int synth_1to1_8bit_mono2stereo (real *,unsigned char *,int *); + +extern int synth_2to1 (real *,int,unsigned char *,int *); +extern int synth_2to1_8bit (real *,int,unsigned char *,int *); +extern int synth_2to1_mono (real *,unsigned char *,int *); +extern int synth_2to1_mono2stereo (real *,unsigned char *,int *); +extern int synth_2to1_8bit_mono (real *,unsigned char *,int *); +extern int synth_2to1_8bit_mono2stereo (real *,unsigned char *,int *); + +extern int synth_4to1 (real *,int,unsigned char *,int *); +extern int synth_4to1_8bit (real *,int,unsigned char *,int *); +extern int synth_4to1_mono (real *,unsigned char *,int *); +extern int synth_4to1_mono2stereo (real *,unsigned char *,int *); +extern int synth_4to1_8bit_mono (real *,unsigned char *,int *); +extern int synth_4to1_8bit_mono2stereo (real *,unsigned char *,int *); + +extern int synth_ntom (real *,int,unsigned char *,int *); +extern int synth_ntom_8bit (real *,int,unsigned char *,int *); +extern int synth_ntom_mono (real *,unsigned char *,int *); +extern int synth_ntom_mono2stereo (real *,unsigned char *,int *); +extern int synth_ntom_8bit_mono (real *,unsigned char *,int *); +extern int synth_ntom_8bit_mono2stereo (real *,unsigned char *,int *); + +extern void rewindNbits(int bits); +extern int hsstell(void); +extern void set_pointer(long); +extern void huffman_decoder(int ,int *); +extern void huffman_count1(int,int *); +extern void print_stat(struct frame *fr,int no,long buffsize,struct audio_info_struct *ai); +extern int get_songlen(struct frame *fr,int no); + +extern void init_layer3(int); +extern void init_layer2(void); +extern void make_decode_tables(long scale); +extern void make_conv16to8_table(int); +extern void dct64(real *,real *,real *); + +#ifdef USE_MMX +extern void dct64_MMX(short *a,short *b,real *c); +extern int synth_1to1_MMX(real *, int, short *, short *, int *); +#endif + +extern void synth_ntom_set_step(long,long); + +extern void control_generic(struct mpstr *,struct frame *fr); +extern void control_sajber(struct mpstr *,struct frame *fr); +extern void control_tk3play(struct mpstr *,struct frame *fr); + +extern int cdr_open(struct audio_info_struct *ai, char *ame); +extern int au_open(struct audio_info_struct *ai, char *name); +extern int wav_open(struct audio_info_struct *ai, char *wavfilename); +extern int wav_write(unsigned char *buf,int len); +extern int cdr_close(void); +extern int au_close(void); +extern int wav_close(void); + +extern int au_open(struct audio_info_struct *ai, char *aufilename); +extern int au_close(void); + +extern int cdr_open(struct audio_info_struct *ai, char *cdrfilename); +extern int cdr_close(void); + +extern int getVBRHeader(struct vbrHeader *head,unsigned char *buf, + struct frame *fr); + + +extern unsigned char *conv16to8; +extern long freqs[9]; +extern real muls[27][64]; +extern real decwin[512+32]; +#ifndef USE_MMX +extern real *pnts[5]; +#endif + +extern real equalizer[2][32]; +extern real equalizer_sum[2][32]; +extern int equalizer_cnt; + +extern struct audio_name audio_val2name[]; + +extern struct parameter param; + +/* 486 optimizations */ +#define FIR_BUFFER_SIZE 128 +extern void dct64_486(int *a,int *b,real *c); +extern int synth_1to1_486(real *bandPtr,int channel,unsigned char *out,int nb_blocks); + +/* 3DNow! optimizations */ +#ifdef USE_3DNOW +extern int getcpuflags(void); +extern void dct36(real *,real *,real *,real *,real *); +extern void dct36_3dnow(real *,real *,real *,real *,real *); +extern int synth_1to1_3dnow(real *,int,unsigned char *,int *); +#endif diff --git a/panda/src/mpg123/xfermem.c b/panda/src/mpg123/xfermem.c new file mode 100644 index 0000000000..fc8f7e7fcb --- /dev/null +++ b/panda/src/mpg123/xfermem.c @@ -0,0 +1,279 @@ +/* + * xfermem.c + * + * Oliver Fromme + * Sun Apr 6 02:26:26 MET DST 1997 + * + * See xfermem.h for documentation/description. + */ + +#ifndef NOXFERMEM + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef AIX +#include +#endif + +#include "mpg123.h" + +#ifndef USE_MMAP +#include +#include +#endif + +extern int errno; + +#if defined (USE_MMAP) && defined(MAP_ANONYMOUS) && !defined(MAP_ANON) +#define MAP_ANON MAP_ANONYMOUS +#endif + +void xfermem_init (txfermem **xf, int bufsize, int msize, int skipbuf) +{ + int regsize = bufsize + msize + skipbuf + sizeof(txfermem); + extern int preload; + +#ifdef USE_MMAP +# ifdef MAP_ANON + if ((*xf = (txfermem *) mmap(0, regsize, PROT_READ | PROT_WRITE, + MAP_ANON | MAP_SHARED, -1, 0)) == (txfermem *) -1) { + perror ("mmap()"); + exit (1); + } +# else + int devzero; + if ((devzero = open("/dev/zero", O_RDWR, 0)) == -1) { + perror ("open(/dev/zero)"); + exit (1); + } + if ((*xf = (txfermem *) mmap(0, regsize, PROT_READ | PROT_WRITE, + MAP_SHARED, devzero, 0)) == (txfermem *) -1) { + perror ("mmap()"); + exit (1); + } + close (devzero); +# endif +#else + struct shmid_ds shmemds; + int shmemid; + if ((shmemid = shmget(IPC_PRIVATE, regsize, IPC_CREAT | 0600)) == -1) { + perror ("shmget()"); + exit (1); + } + if ((*xf = (txfermem *) shmat(shmemid, 0, 0)) == (txfermem *) -1) { + perror ("shmat()"); + shmctl (shmemid, IPC_RMID, &shmemds); + exit (1); + } + if (shmctl(shmemid, IPC_RMID, &shmemds) == -1) { + perror ("shmctl()"); + xfermem_done (*xf); + exit (1); + } +#endif + if (socketpair(AF_UNIX, SOCK_STREAM, 0, (*xf)->fd) < 0) { + perror ("socketpair()"); + xfermem_done (*xf); + exit (1); + } + (*xf)->freeindex = (*xf)->readindex = 0; + (*xf)->wakeme[0] = (*xf)->wakeme[1] = FALSE; + (*xf)->data = ((byte *) *xf) + sizeof(txfermem) + msize; + (*xf)->metadata = ((byte *) *xf) + sizeof(txfermem); + (*xf)->size = bufsize; + (*xf)->metasize = msize + skipbuf; + preload = bufsize>>3; +} + +void xfermem_done (txfermem *xf) +{ + if(!xf) + return; +#ifdef USE_MMAP + munmap ((caddr_t) xf, xf->size + xf->metasize + sizeof(txfermem)); +#else + if (shmdt((void *) xf) == -1) { + perror ("shmdt()"); + exit (1); + } +#endif +} + +void xfermem_init_writer (txfermem *xf) +{ + if(xf) + close (xf->fd[XF_READER]); +} + +void xfermem_init_reader (txfermem *xf) +{ + if(xf) + close (xf->fd[XF_WRITER]); +} + +int xfermem_get_freespace (txfermem *xf) +{ + int freeindex, readindex; + + if(!xf) + return 0; + + if ((freeindex = xf->freeindex) < 0 + || (readindex = xf->readindex) < 0) + return (0); + if (readindex > freeindex) + return ((readindex - freeindex) - 1); + else + return ((xf->size - (freeindex - readindex)) - 1); +} + +int xfermem_get_usedspace (txfermem *xf) +{ + int freeindex, readindex; + + if(!xf) + return 0; + + if ((freeindex = xf->freeindex) < 0 + || (readindex = xf->readindex) < 0) + return (0); + if (freeindex >= readindex) + return (freeindex - readindex); + else + return (xf->size - (readindex - freeindex)); +} + +int xfermem_getcmd (int fd, int block) +{ + fd_set selfds; + byte cmd; + + for (;;) { + struct timeval selto = {0, 0}; + + FD_ZERO (&selfds); + FD_SET (fd, &selfds); + /* #ifdef HPUX */ /* seems to trigger performance problems? strange */ +#if 0 + switch (select(FD_SETSIZE, (int *) &selfds, NULL, NULL, block ? NULL : &selto)) { +#else + switch (select(FD_SETSIZE, &selfds, NULL, NULL, block ? NULL : &selto)) { +#endif + case 0: + if (!block) + return (0); + continue; + case -1: + if (errno == EINTR) + continue; + return (-2); + case 1: + if (FD_ISSET(fd, &selfds)) + switch (read(fd, &cmd, 1)) { + case 0: /* EOF */ + return (-1); + case -1: + if (errno == EINTR) + continue; + return (-3); + case 1: + return (cmd); + default: /* ?!? */ + return (-4); + } + else /* ?!? */ + return (-5); + default: /* ?!? */ + return (-6); + } + } +} + +int xfermem_putcmd (int fd, byte cmd) +{ + for (;;) { + switch (write(fd, &cmd, 1)) { + case 1: + return (1); + case -1: + if (errno != EINTR) + return (-1); + } + } +} + +int xfermem_block (int readwrite, txfermem *xf) +{ + int myfd = xf->fd[readwrite]; + int result; + + xf->wakeme[readwrite] = TRUE; + if (xf->wakeme[1 - readwrite]) + xfermem_putcmd (myfd, XF_CMD_WAKEUP); + result = xfermem_getcmd(myfd, TRUE); + xf->wakeme[readwrite] = FALSE; + return ((result <= 0) ? -1 : result); +} + +#elif defined(WIN32) +#include +#include +#include +#include +#include +#include + +#include "xfermem.h" + +extern int errno; + +void xfermem_init (txfermem **xf, int bufsize, int msize, int skipbuf) +{ + return 0; +} +void xfermem_done (txfermem *xf) +{ + return 0; +} +void xfermem_init_writer (txfermem *xf) +{ + return 0; +} +void xfermem_init_reader (txfermem *xf) +{ + return 0; +} +int xfermem_get_freespace (txfermem *xf) +{ + return 0; +} +int xfermem_get_usedspace (txfermem *xf) +{ + return 0; +} +int xfermem_getcmd (int fd, int block) +{ + return 0; +} +int xfermem_putcmd (int fd, byte cmd) +{ + return 0; +} +int xfermem_block (int readwrite, txfermem *xf) +{ + return 0; +} +#endif + +/* eof */ + diff --git a/panda/src/mpg123/xfermem.h b/panda/src/mpg123/xfermem.h new file mode 100644 index 0000000000..ae7e5afd80 --- /dev/null +++ b/panda/src/mpg123/xfermem.h @@ -0,0 +1,60 @@ +/* + * xfermem.h + * + * Oliver Fromme + * Sat Mar 29 04:41:34 MET 1997 + * + * This is a stand-alone module which implements a unidirectional, + * fast pipe using mmap(). Its primary use is to transfer large + * amounts of data from a parent process to its child process, + * with a buffer in between which decouples blocking conditions + * on both sides. Control information is transferred between the + * processes through a socketpair. See xftest.c for an example on + * how to use this module. + */ + +#ifndef TRUE +#define FALSE 0 +#define TRUE 1 +#endif + +typedef struct { + int freeindex; /* [W] next free index */ + int readindex; /* [R] next index to read */ + int fd[2]; + int wakeme[2]; + byte *data; + byte *metadata; + int size; + int metasize; + int buf[3]; +} txfermem; +/* + * [W] -- May be written to by the writing process only! + * [R] -- May be written to by the reading process only! + * All other entries are initialized once. + */ + +void xfermem_init (txfermem **xf, int bufsize, int msize,int skipbuf); +void xfermem_init_writer (txfermem *xf); +void xfermem_init_reader (txfermem *xf); + +int xfermem_write (txfermem *xf, byte *data, int count); +int xfermem_read (txfermem *xf, byte *data, int count); + +int xfermem_get_freespace (txfermem *xf); +int xfermem_get_usedspace (txfermem *xf); +#define XF_CMD_WAKEUP_INFO 0x04 +#define XF_CMD_WAKEUP 0x02 +#define XF_CMD_TERMINATE 0x03 +#define XF_WRITER 0 +#define XF_READER 1 +int xfermem_getcmd (int fd, int block); +int xfermem_putcmd (int fd, byte cmd); +int xfermem_block (int fd, txfermem *xf); + +void xfermem_done (txfermem *xf); +#define xfermem_done_writer xfermem_init_reader +#define xfermem_done_reader xfermem_init_writer + +/* EOF */