diff options
author | Moshe Piekarski <dev.rockbox@melachim.net> | 2020-06-24 05:53:44 -0400 |
---|---|---|
committer | Solomon Peachy <pizza@shaftnet.org> | 2020-07-15 18:30:07 +0000 |
commit | e884140eae2b093cc33dae3af20fc72ab621c518 (patch) | |
tree | d0ace2d21481bebc5598af23860507c023280dbb | |
parent | ff8cca70a4651e6a9db9599d3778d7b5d7926d96 (diff) | |
download | rockbox-e884140eae2b093cc33dae3af20fc72ab621c518.tar.gz rockbox-e884140eae2b093cc33dae3af20fc72ab621c518.zip |
Add support for ID3 tags embedded in AIFF files
Change-Id: I15eb50b6ba1c26052f08e01861f47faede3b9b3b
-rw-r--r-- | lib/rbcodec/codecs/aiff.c | 4 | ||||
-rw-r--r-- | lib/rbcodec/metadata/aiff.c | 33 | ||||
-rw-r--r-- | lib/rbcodec/metadata/id3tags.c | 11 |
3 files changed, 43 insertions, 5 deletions
diff --git a/lib/rbcodec/codecs/aiff.c b/lib/rbcodec/codecs/aiff.c index 2900ed2ecb..a82ae5f2e2 100644 --- a/lib/rbcodec/codecs/aiff.c +++ b/lib/rbcodec/codecs/aiff.c | |||
@@ -198,6 +198,10 @@ enum codec_status codec_run(void) | |||
198 | } else if (is_aifc && (memcmp(buf, "FVER", 4)==0)) { | 198 | } else if (is_aifc && (memcmp(buf, "FVER", 4)==0)) { |
199 | /* Format Version Chunk (AIFC only chunk) */ | 199 | /* Format Version Chunk (AIFC only chunk) */ |
200 | /* skip this chunk */ | 200 | /* skip this chunk */ |
201 | } else if ( (memcmp(buf, "NAME", 4)==0) || (memcmp(buf, "AUTH", 4)==0) | ||
202 | || (memcmp(buf, "ANNO", 4)==0)) { | ||
203 | /* Text chunks containing only metadata */ | ||
204 | /* skip this chunk */ | ||
201 | } else { | 205 | } else { |
202 | DEBUGF("unsupported AIFF chunk: '%c%c%c%c', size=%lu\n", | 206 | DEBUGF("unsupported AIFF chunk: '%c%c%c%c', size=%lu\n", |
203 | buf[0], buf[1], buf[2], buf[3], (unsigned long)size); | 207 | buf[0], buf[1], buf[2], buf[3], (unsigned long)size); |
diff --git a/lib/rbcodec/metadata/aiff.c b/lib/rbcodec/metadata/aiff.c index 1bb95f3ed2..eb0b5589d9 100644 --- a/lib/rbcodec/metadata/aiff.c +++ b/lib/rbcodec/metadata/aiff.c | |||
@@ -34,15 +34,24 @@ | |||
34 | /* compressionType: AIFC QuickTime IMA ADPCM */ | 34 | /* compressionType: AIFC QuickTime IMA ADPCM */ |
35 | #define AIFC_FORMAT_QT_IMA_ADPCM "ima4" | 35 | #define AIFC_FORMAT_QT_IMA_ADPCM "ima4" |
36 | 36 | ||
37 | static void read_id3_tags(int fd, struct mp3entry* id3) | ||
38 | { | ||
39 | id3->tracknum = 0; | ||
40 | id3->discnum = 0; | ||
41 | setid3v2title(fd, id3); | ||
42 | } | ||
43 | |||
37 | bool get_aiff_metadata(int fd, struct mp3entry* id3) | 44 | bool get_aiff_metadata(int fd, struct mp3entry* id3) |
38 | { | 45 | { |
39 | unsigned char buf[512]; | 46 | unsigned char buf[512]; |
40 | unsigned long numChannels = 0; | 47 | unsigned long numChannels = 0; |
41 | unsigned long numSampleFrames = 0; | 48 | unsigned long numSampleFrames = 0; |
42 | unsigned long numbytes = 0; | 49 | unsigned long numbytes = 0; |
50 | unsigned long offset = 0; | ||
43 | bool is_aifc = false; | 51 | bool is_aifc = false; |
44 | char *p=id3->id3v2buf; | 52 | char *p=id3->id3v2buf; |
45 | 53 | ||
54 | |||
46 | if ((lseek(fd, 0, SEEK_SET) < 0) || (read(fd, &buf[0], 12) < 12) || | 55 | if ((lseek(fd, 0, SEEK_SET) < 0) || (read(fd, &buf[0], 12) < 12) || |
47 | (memcmp(&buf[0], "FORM", 4) != 0) || (memcmp(&buf[8], "AIF", 3) != 0) || | 56 | (memcmp(&buf[0], "FORM", 4) != 0) || (memcmp(&buf[8], "AIF", 3) != 0) || |
48 | (!(is_aifc = (buf[11] == 'C')) && buf[11] != 'F')) | 57 | (!(is_aifc = (buf[11] == 'C')) && buf[11] != 'F')) |
@@ -50,6 +59,7 @@ bool get_aiff_metadata(int fd, struct mp3entry* id3) | |||
50 | return false; | 59 | return false; |
51 | } | 60 | } |
52 | 61 | ||
62 | |||
53 | while (read(fd, &buf[0], 8) == 8) | 63 | while (read(fd, &buf[0], 8) == 8) |
54 | { | 64 | { |
55 | size_t size = get_long_be(&buf[4]); /* chunkSize */ | 65 | size_t size = get_long_be(&buf[4]); /* chunkSize */ |
@@ -57,6 +67,18 @@ bool get_aiff_metadata(int fd, struct mp3entry* id3) | |||
57 | if (memcmp(&buf[0], "SSND", 4) == 0) | 67 | if (memcmp(&buf[0], "SSND", 4) == 0) |
58 | { | 68 | { |
59 | numbytes = size - 8; | 69 | numbytes = size - 8; |
70 | |||
71 | /* check for ID3 tag */ | ||
72 | offset=lseek(fd, 0, SEEK_CUR); | ||
73 | lseek(fd, size, SEEK_CUR); | ||
74 | if ((read(fd, &buf[0], 8) == 8) && (memcmp(&buf[0], "ID3", 3) == 0)) | ||
75 | { | ||
76 | id3->id3v2len = get_long_be(&buf[4]); | ||
77 | read_id3_tags(fd, id3); | ||
78 | } | ||
79 | else | ||
80 | DEBUGF("ID3 tag not present immediately after sound data"); | ||
81 | lseek(fd, offset, SEEK_SET); | ||
60 | break; /* assume COMM was already read */ | 82 | break; /* assume COMM was already read */ |
61 | } | 83 | } |
62 | 84 | ||
@@ -72,25 +94,30 @@ bool get_aiff_metadata(int fd, struct mp3entry* id3) | |||
72 | 94 | ||
73 | if (memcmp(&buf[0], "NAME", 4) == 0) | 95 | if (memcmp(&buf[0], "NAME", 4) == 0) |
74 | { | 96 | { |
75 | read_string(fd, p, 512, 20, size); | 97 | read_string(fd, p, 512, 0, size); |
76 | id3->title=p; | 98 | id3->title=p; |
77 | p+=size; | 99 | p+=size; |
78 | } | 100 | } |
79 | 101 | ||
80 | else if (memcmp(&buf[0], "AUTH", 4) == 0) | 102 | else if (memcmp(&buf[0], "AUTH", 4) == 0) |
81 | { | 103 | { |
82 | read_string(fd, p, 512, 20, size); | 104 | read_string(fd, p, 512, 0, size); |
83 | id3->artist=p; | 105 | id3->artist=p; |
84 | p+=size; | 106 | p+=size; |
85 | } | 107 | } |
86 | 108 | ||
87 | else if (memcmp(&buf[0], "ANNO", 4) == 0) | 109 | else if (memcmp(&buf[0], "ANNO", 4) == 0) |
88 | { | 110 | { |
89 | read_string(fd, p, 512, 20, size); | 111 | read_string(fd, p, 512, 0, size); |
90 | id3->comment=p; | 112 | id3->comment=p; |
91 | p+=size; | 113 | p+=size; |
92 | } | 114 | } |
93 | 115 | ||
116 | else if (memcmp(&buf[0], "ID3", 3) == 0) | ||
117 | { | ||
118 | read_id3_tags(fd, id3); | ||
119 | } | ||
120 | |||
94 | 121 | ||
95 | else if (memcmp(&buf[0], "COMM", 4) == 0) | 122 | else if (memcmp(&buf[0], "COMM", 4) == 0) |
96 | { | 123 | { |
diff --git a/lib/rbcodec/metadata/id3tags.c b/lib/rbcodec/metadata/id3tags.c index 8236244d79..84b3c593ef 100644 --- a/lib/rbcodec/metadata/id3tags.c +++ b/lib/rbcodec/metadata/id3tags.c | |||
@@ -717,6 +717,9 @@ bool setid3v1title(int fd, struct mp3entry *entry) | |||
717 | * entry - the entry to set the title in | 717 | * entry - the entry to set the title in |
718 | * | 718 | * |
719 | * Returns: true if a title was found and created, else false | 719 | * Returns: true if a title was found and created, else false |
720 | * | ||
721 | * Assumes that the offset of file is at the start of the ID3 header. | ||
722 | * (if the header is at the begining of the file getid3v2len() will ensure this.) | ||
720 | */ | 723 | */ |
721 | void setid3v2title(int fd, struct mp3entry *entry) | 724 | void setid3v2title(int fd, struct mp3entry *entry) |
722 | { | 725 | { |
@@ -749,8 +752,9 @@ void setid3v2title(int fd, struct mp3entry *entry) | |||
749 | if(entry->id3v2len < 10) | 752 | if(entry->id3v2len < 10) |
750 | return; | 753 | return; |
751 | 754 | ||
752 | /* Read the ID3 tag version from the header */ | 755 | |
753 | lseek(fd, 0, SEEK_SET); | 756 | /* Read the ID3 tag version from the header. |
757 | Assumes fd is already at the begining of the header */ | ||
754 | if(10 != read(fd, header, 10)) | 758 | if(10 != read(fd, header, 10)) |
755 | return; | 759 | return; |
756 | 760 | ||
@@ -1177,12 +1181,15 @@ int getid3v2len(int fd) | |||
1177 | 1181 | ||
1178 | /* Now check what the ID3v2 size field says */ | 1182 | /* Now check what the ID3v2 size field says */ |
1179 | else | 1183 | else |
1184 | { | ||
1180 | if(read(fd, buf, 4) != 4) | 1185 | if(read(fd, buf, 4) != 4) |
1181 | offset = 0; | 1186 | offset = 0; |
1182 | else | 1187 | else |
1183 | offset = unsync(buf[0], buf[1], buf[2], buf[3]) + 10; | 1188 | offset = unsync(buf[0], buf[1], buf[2], buf[3]) + 10; |
1189 | } | ||
1184 | 1190 | ||
1185 | logf("ID3V2 Length: 0x%x", offset); | 1191 | logf("ID3V2 Length: 0x%x", offset); |
1192 | lseek(fd, -10, SEEK_CUR); | ||
1186 | return offset; | 1193 | return offset; |
1187 | } | 1194 | } |
1188 | 1195 | ||