summaryrefslogtreecommitdiff
path: root/audio/mserv/patches/patch-ae
blob: 57a54bdea19313fb1acea9e111b8e00c5a99057e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
$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