--- xmms-mad-0.7/src/xmms-mad.c.orig 2004-10-30 14:20:05 +0400 +++ xmms-mad-0.7/src/xmms-mad.c 2005-02-19 21:33:42 +0300 @@ -76,12 +76,125 @@ xmmsmad_set_eq (int on, float preamp, fl //printf("set_eq\n"); } +/* needed for read_wav_id() */ +static int read_n_bytes(FILE * file, guint8 * buf, int n) +{ + + if (fread(buf, 1, n, file) != n) + { + return FALSE; + } + return TRUE; +} + +static guint32 convert_to_header(guint8 * buf) +{ + + return (buf[0] << 24) + (buf[1] << 16) + (buf[2] << 8) + buf[3]; +} + +static guint32 convert_to_long(guint8 * buf) +{ + + return (buf[3] << 24) + (buf[2] << 16) + (buf[1] << 8) + buf[0]; +} + +static guint16 read_wav_id(char *filename) +{ + FILE *file; + guint16 wavid; + guint8 buf[4]; + guint32 head; + long seek; + + if (!(file = fopen(filename, "rb"))) + { /* Could not open file */ + return 0; + } + if (!(read_n_bytes(file, buf, 4))) + { + fclose(file); + return 0; + } + head = convert_to_header(buf); + if (head == ('R' << 24) + ('I' << 16) + ('F' << 8) + 'F') + { /* Found a riff -- maybe WAVE */ + if (fseek(file, 4, SEEK_CUR) != 0) + { /* some error occured */ + fclose(file); + return 0; + } + if (!(read_n_bytes(file, buf, 4))) + { + fclose(file); + return 0; + } + head = convert_to_header(buf); + if (head == ('W' << 24) + ('A' << 16) + ('V' << 8) + 'E') + { /* Found a WAVE */ + seek = 0; + do + { + /* we'll be looking for the fmt-chunk which comes before the data-chunk */ + /* A chunk consists of an header identifier (4 bytes), the length of the chunk + (4 bytes), and the chunkdata itself, padded to be an even number of bytes. + We'll skip all chunks until we find the "data"-one which could contain + mpeg-data */ + if (seek != 0) + { + if (fseek(file, seek, SEEK_CUR) != 0) + { /* some error occured */ + fclose(file); + return 0; + } + } + if (!(read_n_bytes(file, buf, 4))) + { + fclose(file); + return 0; + } + head = convert_to_header(buf); + if (!(read_n_bytes(file, buf, 4))) + { + fclose(file); + return 0; + } + seek = convert_to_long(buf); + seek = seek + (seek % 2); /* Has to be even (padding) */ + if (seek >= 2 && head == ('f' << 24) + ('m' << 16) + ('t' << 8) + ' ') + { + if (!(read_n_bytes(file, buf, 2))) + { + fclose(file); + return 0; + } + wavid = buf[0] + 256 * buf[1]; + seek -= 2; + /* we could go on looking for + other things, but all we + wanted was the wavid */ + fclose(file); + return wavid; + } + } + while (head != ('d' << 24) + ('a' << 16) + ('t' << 8) + 'a'); + /* it's RIFF WAVE */ + } + /* it's RIFF */ + } + /* it's not even RIFF */ + fclose(file); + return 0; +} + static int xmmsmad_is_our_file (char *filename) { int fin = 0; int rtn = 0; guchar check [4]; + char *ext; + guint16 wavid; if (strncasecmp ("http://", filename, 7) == 0) { @@ -94,41 +207,24 @@ xmmsmad_is_our_file (char *filename) else { fin = open (filename, O_RDONLY); - if (fin >= 0 && read (fin, check, 4) == 4) + ext = strrchr(filename, '.'); + if (ext) { - /* If first two bytes are a sync header or three bytes are "ID3" */ - if ( (check[0] == 0xff && (check[1] & 0x70) == 0x70) - || memcmp (check, "ID3", 3) == 0) + if (!strncasecmp(ext, ".mp3", 4) && fin >= 0) { rtn = 1; + /* do more proper wave header checks than old one */ } - else if (memcmp (check, "RIFF", 4) == 0) /* RIFF data */ - { - lseek (fin, 4, SEEK_CUR); - read (fin, check, 4); - - if (memcmp (check, "RMP3", 4) == 0) - { - rtn = 1; - } -#if 0 - /* FIXME: make this test endian safe */ - else if (memcmp (check, "WAVE")) - { - /* seek to codec ID and see if it's MP3 */ - lseek (fin, 20, SEEK_SET); - check = 0L; - read (fin, &check, 2); - if (check == 0x55) - { - rtn = 1; - } - } -#endif + else if (!strncasecmp(ext, ".wav", 4)) + { + wavid = read_wav_id(filename); + if (wavid == 85 || wavid == 80) + { /* Microsoft says 80, files say 85... */ + rtn = 1; + } } - } + } } - close (fin); return rtn; }