225 lines
6.9 KiB
Plaintext
225 lines
6.9 KiB
Plaintext
$NetBSD: patch-ae,v 1.9 2009/09/26 21:16:58 martin Exp $
|
|
|
|
--- mserv/mp3info.c.orig 2003-07-29 02:17:48.000000000 +0200
|
|
+++ mserv/mp3info.c 2009-09-26 22:11:43.000000000 +0200
|
|
@@ -26,7 +26,17 @@
|
|
#define h_id(val) ((val>>19)&1)
|
|
#define h_thing(val) ((val>>20)&0xfff)
|
|
|
|
+#ifdef STANDALONE
|
|
+#define VERBOSE
|
|
+#endif
|
|
+#ifdef VERBOSE
|
|
+#define LOGF(ARG) printf ARG
|
|
+#else
|
|
+#define LOGF(ARG)
|
|
+#endif
|
|
+
|
|
#define ID3V2HEADERLEN 10
|
|
+#define min(x,y) ((x)<(y)?(x):(y))
|
|
|
|
/* mp3 bit rate and sampling frequency tables */
|
|
|
|
@@ -45,12 +55,14 @@ const int sampling_freq_table[2][3] =
|
|
/* structure of id3 tag in mp3 file */
|
|
|
|
typedef struct id3tag_disc_str
|
|
-{
|
|
- char title[MP3ID3_TITLELEN];
|
|
- char artist[MP3ID3_ARTISTLEN];
|
|
- char album[MP3ID3_ALBUMLEN];
|
|
- char year[MP3ID3_YEARLEN];
|
|
- char comment[MP3ID3_COMMENTLEN];
|
|
+{ /* These are all fixed lengths.
|
|
+ * Avoid #define'd lengths that get get redefined for other uses
|
|
+ */
|
|
+ char title[30];
|
|
+ char artist[30];
|
|
+ char album[30];
|
|
+ char year[4];
|
|
+ char comment[28];
|
|
unsigned char genre;
|
|
} id3tag_disc;
|
|
|
|
@@ -228,11 +240,28 @@ static int read_id3v2_frame(FILE *f, id3
|
|
if (fread(frame->data, 1, frame->datalen, f) != frame->datalen)
|
|
return -1;
|
|
if (frame->frameid[0] == 'T' && memcmp(frame->frameid + 1, "XXX", 3)) {
|
|
- frame->data[frame->datalen] = 0;
|
|
- if (frame->data[0] == 0) /* Only handle non unicode */
|
|
+ if (frame->data[0] == 0) {
|
|
+ /* ISO8859-1 */
|
|
+ frame->data[frame->datalen] = 0;
|
|
strcpy(frame->data, frame->data + 1);
|
|
- else
|
|
- frame->data[0] = 0;
|
|
+ } else if (frame->data[0] == 1 && frame->datalen >= 5) {
|
|
+ /* unicode, convert as long as it is 8 bit only */
|
|
+ int d = 0, i = 1, off0 = 0, off1 = 1;
|
|
+ /* check BOM vs. endianess */
|
|
+ if ((unsigned char)frame->data[i] == 0xff && (unsigned char)frame->data[i+1] == 0xfe) {
|
|
+ off0 = 1; off1 = 0;
|
|
+ } else if ((unsigned char)frame->data[i] == 0xfe && (unsigned char)frame->data[i+1] == 0xff) {
|
|
+ off1 = 1; off0 = 0;
|
|
+ } else {
|
|
+ return -1;
|
|
+ }
|
|
+ for (i=3; (i+1) < frame->datalen /* && frame->data[i] == 0 */; i+=2) {
|
|
+ frame->data[d++] = frame->data[i+off1];
|
|
+ if (frame->data[i] == 0 && frame->data[i+1] == 0)
|
|
+ break;
|
|
+ }
|
|
+ frame->data[d] = 0;
|
|
+ }
|
|
}
|
|
return 0;
|
|
}
|
|
@@ -264,12 +293,12 @@ int mserv_mp3info_readlen(const char *fn
|
|
{
|
|
FILE *f;
|
|
int bitrate, fs, length, headerlen;
|
|
- long int filelen;
|
|
+ long int filelen, skipped;
|
|
float mean_frame_size;
|
|
char tag[3];
|
|
unsigned char data[4];
|
|
unsigned long int flags;
|
|
- int errnok;
|
|
+ int errnok, found;
|
|
char *e;
|
|
|
|
if (id3tag)
|
|
@@ -281,15 +310,39 @@ int mserv_mp3info_readlen(const char *fn
|
|
if ((headerlen = mp3_id3v2head(f)) == -1)
|
|
goto error;
|
|
|
|
- if (fseek(f, headerlen, SEEK_SET) == -1 || fread(&data, 4, 1, f) != 1)
|
|
+ if (fseek(f, headerlen, SEEK_SET) == -1 || fread(&data[0], 1, 1, f) != 1) {
|
|
+ LOGF(("%s: can't read after headerlen %d\n", fname, headerlen));
|
|
goto error;
|
|
+ }
|
|
|
|
- /* endian independent to 32-bit flags */
|
|
- flags = (data[0]<<24)+(data[1]<<16)+(data[2]<<8)+data[3];
|
|
- if (!is_mp3(flags)) {
|
|
- errno = EDOM;
|
|
+ found = skipped = 0;
|
|
+ for (;;) {
|
|
+ while (data[0] != 0xff) {
|
|
+ /* skip junk at beginning or after header - happens quite often */
|
|
+ if (fread(&data[0], 1, 1, f) != 1)
|
|
+ goto error;
|
|
+ skipped++;
|
|
+ if (headerlen < 1 && skipped > 4096)
|
|
+ break; /* we are not sure this even is a mp3 file */
|
|
+ }
|
|
+ if (fread(&data[1], 1, 3, f) != 3)
|
|
+ goto error;
|
|
+
|
|
+ /* endian independent to 32-bit flags */
|
|
+ flags = (data[0]<<24)+(data[1]<<16)+(data[2]<<8)+data[3];
|
|
+ if (is_mp3(flags)) {
|
|
+ found = 1;
|
|
+ break;
|
|
+ }
|
|
+ if (headerlen < 1 && skipped > 4096)
|
|
+ break; /* we are not sure this even is a mp3 file */
|
|
+ }
|
|
+ if (!found) {
|
|
+ LOGF(("%s: no header found within 4k\n", fname));
|
|
goto error;
|
|
}
|
|
+ if (skipped)
|
|
+ LOGF(("%s: skipped %ld bytes\n", fname, skipped));
|
|
|
|
bitrate = bitrate_table[h_id(flags)][3-h_layer(flags)]
|
|
[h_bitrate_index(flags)];
|
|
@@ -312,38 +365,44 @@ int mserv_mp3info_readlen(const char *fn
|
|
if (id3tag)
|
|
{
|
|
id3tag_disc tag_disc;
|
|
+ int len;
|
|
|
|
if (fread(&tag_disc, 1, 125, f) != 125)
|
|
goto error;
|
|
|
|
id3tag->present = 1;
|
|
|
|
- memcpy(id3tag->title, tag_disc.title, MP3ID3_TITLELEN);
|
|
- id3tag->title[MP3ID3_TITLELEN] = '\0';
|
|
+ len = min(MP3ID3_TITLELEN, sizeof(tag_disc.title));
|
|
+ memcpy(id3tag->title, tag_disc.title, len);
|
|
+ id3tag->title[len] = '\0';
|
|
e = id3tag->title + strlen(id3tag->title);
|
|
while (e > id3tag->title && *(e-1) == ' ')
|
|
*--e = '\0';
|
|
|
|
- memcpy(id3tag->artist, tag_disc.artist, MP3ID3_ARTISTLEN);
|
|
- id3tag->artist[MP3ID3_ARTISTLEN] = '\0';
|
|
+ len = min(MP3ID3_ARTISTLEN, sizeof(tag_disc.artist));
|
|
+ memcpy(id3tag->artist, tag_disc.artist, len);
|
|
+ id3tag->artist[len] = '\0';
|
|
e = id3tag->artist + strlen(id3tag->artist);
|
|
while (e > id3tag->artist && *(e-1) == ' ')
|
|
*--e = '\0';
|
|
|
|
- memcpy(id3tag->album, tag_disc.album, MP3ID3_ALBUMLEN);
|
|
- id3tag->album[MP3ID3_ALBUMLEN] = '\0';
|
|
+ len = min(MP3ID3_ALBUMLEN, sizeof(tag_disc.album));
|
|
+ memcpy(id3tag->album, tag_disc.album, len);
|
|
+ id3tag->album[len] = '\0';
|
|
e = id3tag->album + strlen(id3tag->album);
|
|
while (e > id3tag->album && *(e-1) == ' ')
|
|
*--e = '\0';
|
|
|
|
- memcpy(id3tag->year, tag_disc.year, MP3ID3_YEARLEN);
|
|
- id3tag->year[MP3ID3_YEARLEN] = '\0';
|
|
+ len = min(MP3ID3_YEARLEN, sizeof(tag_disc.year));
|
|
+ memcpy(id3tag->year, tag_disc.year, len);
|
|
+ id3tag->year[len] = '\0';
|
|
e = id3tag->year + strlen(id3tag->year);
|
|
while (e > id3tag->year && *(e-1) == ' ')
|
|
*--e = '\0';
|
|
|
|
- memcpy(id3tag->comment, tag_disc.comment, MP3ID3_COMMENTLEN);
|
|
- id3tag->comment[MP3ID3_COMMENTLEN] = '\0';
|
|
+ len = min(MP3ID3_COMMENTLEN, sizeof(tag_disc.comment));
|
|
+ memcpy(id3tag->comment, tag_disc.comment, len);
|
|
+ id3tag->comment[len] = '\0';
|
|
e = id3tag->comment + strlen(id3tag->comment);
|
|
while (e > id3tag->comment && *(e-1) == ' ')
|
|
*--e = '\0';
|
|
@@ -395,3 +454,32 @@ int mserv_mp3info_readlen(const char *fn
|
|
errno = errnok;
|
|
return -1;
|
|
}
|
|
+
|
|
+#ifdef STANDALONE
|
|
+int main(int argc, char **argv)
|
|
+{
|
|
+ t_id3tag tag;
|
|
+ int bitrate, len;
|
|
+
|
|
+ if (argc < 2) {
|
|
+ printf("usage: minfo (filename)\n");
|
|
+ return 1;
|
|
+ }
|
|
+ len = mserv_mp3info_readlen(argv[1], &bitrate, &tag);
|
|
+ if (len < 0) {
|
|
+ printf("no mp3 found\n");
|
|
+ } else {
|
|
+ if (bitrate)
|
|
+ printf("bitrate %d kbit/s, estimated length "
|
|
+ "%d:%02d.%02d s\n",
|
|
+ bitrate, len/6000, (len%6000)/100, len%100);
|
|
+ if (tag.present) {
|
|
+ printf("title: %s\n", tag.title);
|
|
+ printf("album: %s\n", tag.album);
|
|
+ printf("artist: %s\n", tag.artist);
|
|
+ printf("year: %s\n", tag.year);
|
|
+ }
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+#endif
|