This commit is contained in:
Cary Sandvig 2000-10-11 22:56:57 +00:00
parent c8b6ece0de
commit 9bad163654
8 changed files with 1913 additions and 0 deletions

721
panda/src/mpg123/common.c Normal file
View File

@ -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
panda/src/mpg123/common.h Normal file
View File

@ -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
panda/src/mpg123/genre.h Normal file
View File

@ -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
panda/src/mpg123/getbits.c Normal file
View File

@ -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;
}

View File

@ -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
panda/src/mpg123/mpg123.h Normal file
View File

@ -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
panda/src/mpg123/xfermem.c Normal file
View File

@ -0,0 +1,279 @@
/*
* xfermem.c
*
* Oliver Fromme <oliver.fromme@heim3.tu-clausthal.de>
* 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 */

View File

@ -0,0 +1,60 @@
/*
* xfermem.h
*
* Oliver Fromme <oliver.fromme@heim3.tu-clausthal.de>
* 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 */