Cary Sandvig 25 anos atrás
pai
commit
9bad163654

+ 721 - 0
panda/src/mpg123/common.c

@@ -0,0 +1,721 @@
+/* GPL clean */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <signal.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#include <fcntl.h>
+
+#ifdef READ_MMAP
+#include <sys/mman.h>
+#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 <num> 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;
+}
+
+

+ 19 - 0
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;
+};
+*/
+
+

+ 263 - 0
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);

+ 127 - 0
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]<<bsi->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;
+}
+

+ 33 - 0
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]<<bsi.bitindex)>>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 )
+

+ 411 - 0
panda/src/mpg123/mpg123.h

@@ -0,0 +1,411 @@
+/*
+ * mpg123 defines 
+ * used source: musicout.h from mpegaudio package
+ */
+
+#include        <stdio.h>
+#include        <string.h>
+#include        <signal.h>
+
+#ifndef WIN32
+#include        <sys/signal.h>
+#include        <unistd.h>
+#endif
+
+#include        <math.h>
+
+typedef unsigned char byte;
+
+#ifdef OS2
+#include <float.h>
+#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

+ 279 - 0
panda/src/mpg123/xfermem.c

@@ -0,0 +1,279 @@
+/*
+ *   xfermem.c
+ *
+ *   Oliver Fromme  <[email protected]>
+ *   Sun Apr  6 02:26:26 MET DST 1997
+ *
+ *   See xfermem.h for documentation/description.
+ */
+
+#ifndef NOXFERMEM
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/uio.h>
+#include <sys/mman.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+
+#ifdef AIX
+#include <sys/select.h>
+#endif
+
+#include "mpg123.h"
+
+#ifndef USE_MMAP
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <fcntl.h>
+
+#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 */
+

+ 60 - 0
panda/src/mpg123/xfermem.h

@@ -0,0 +1,60 @@
+/*
+ *   xfermem.h
+ *
+ *   Oliver Fromme  <[email protected]>
+ *   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 */