summaryrefslogtreecommitdiff
path: root/audio/mserv/patches/patch-ai
blob: c9a51e1f8520b90db2d7cd3579b1a138a9bc551e (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
$NetBSD: patch-ai,v 1.3 2002/10/03 15:46:58 abs Exp $

--- mserv/mp3info.c.orig	Thu Oct  3 16:10:58 2002
+++ mserv/mp3info.c
@@ -7,6 +7,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
+#include "mserv.h"
 #include "mp3info.h"
 
 /* mp3 frame header structure */
@@ -25,6 +26,8 @@
 #define h_id(val)             ((val>>19)&1)
 #define h_thing(val)          ((val>>20)&0xfff)
 
+#define ID3V2HEADERLEN		10
+
 /* mp3 bit rate and sampling frequency tables */
 
 const int bitrate_table[2][3][16] =
@@ -51,6 +54,16 @@ typedef struct id3tag_disc_str
   unsigned char genre;
 } id3tag_disc;
 
+/* id3 v2 frame tag data */
+
+typedef struct id3v2_frame_str
+{
+   char frameid[4];
+   uint32_t size;
+   uint16_t flags;
+   char data[1024];
+   size_t datalen;
+} id3v2_frame;
 /* id3 tags genre */
 
 const char *genres_table[] = {
@@ -201,20 +214,46 @@ static int is_mp3(unsigned long int flag
   return 1;
 }
 
+/* returns 0 if id3v2 frame found, -1 otherwise */
+
+static int read_id3v2_frame(FILE *f, id3v2_frame *frame)
+{
+  if (fread(frame->frameid, 1, 4, f) != 4 ||
+      fread(&frame->size, 1, 4, f) != 4 || fread(&frame->flags, 1, 2, f) != 2)
+    return -1;
+  frame->size = ntohl(frame->size);
+  frame->flags = ntohs(frame->flags);
+  frame->datalen = (frame->size >= sizeof(frame->data) - 1)
+			?(sizeof(frame->data) - 1) :frame->size;
+  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 */
+      strcpy(frame->data, frame->data + 1);
+    else
+      frame->data[0] = 0;
+  }
+  return 0;
+}
+
 /* returns 0 if no id3v2 header, otherwise returns tag length, or -1
    and errno set */
 
 static int mp3_id3v2head(FILE *f)
 {
   char tag[3];
+  char size[4];
   if (fseek(f, 0, SEEK_SET) == -1 || fread(tag, 1, 3, f) != 3)
     return -1;
 
   if (strncmp(tag, "ID3", 3))
     return 0; /* no header */
+  if (fseek(f, 2 + 1, SEEK_CUR) == -1 || fread(size, 1, 4, f) != 4)
+    return -1;
 
-  errno = ENOSYS;
-  return -1;
+  return ID3V2HEADERLEN + size[3] + (size[2] << 7) + (size[1] << 14) +
+							    (size[0] << 21);
 }
 
 /* determines length and bitrate of an mp3. returns -1 on failure with errno
@@ -321,12 +360,35 @@ int mserv_mp3info_readlen(const char *fn
     /* No ID3 tag present; last 128 bytes is music. */
     filelen += 128;
   }
-  fclose(f); /* ignore error */
 
   *bitrate_ret = bitrate;
   length = ((filelen - headerlen) / mean_frame_size ) *
            ((115200/2) * (1+h_id(flags)) ) / fs; /* in 1/100 seconds */
+
+  /* If mp3v2 header present, read its contents */
+  if (headerlen && fseek(f, ID3V2HEADERLEN, SEEK_SET) != -1) {
+    id3v2_frame frame;
+    while (read_id3v2_frame(f, &frame) != -1) {
+      if (!memcmp(frame.frameid, "TALB", 4)) {
+	memcpy(id3tag->album, frame.data, sizeof(id3tag->album) - 1);
+	id3tag->album[sizeof(id3tag->album) - 1] = 0;
+      }
+      else if (!memcmp(frame.frameid, "TPE1", 4)) {
+	memcpy(id3tag->artist, frame.data, sizeof(id3tag->artist) - 1);
+	id3tag->artist[sizeof(id3tag->artist) - 1] = 0;
+      }
+      else if (!memcmp(frame.frameid, "TIT2", 4)) {
+	memcpy(id3tag->title, frame.data, sizeof(id3tag->title) - 1);
+	id3tag->title[sizeof(id3tag->title) - 1] = 0;
+      }
+      if (ftell(f) >= headerlen)
+	break;
+    }
+  }
+
+  fclose(f); /* ignore error */
   return length;
+
  error:
   errnok = errno;
   fclose(f); /* ignore error */