summaryrefslogtreecommitdiff
path: root/lib/rbcodec/metadata
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rbcodec/metadata')
-rw-r--r--lib/rbcodec/metadata/metadata.c40
-rw-r--r--lib/rbcodec/metadata/metadata.h13
-rw-r--r--lib/rbcodec/metadata/metadata_parsers.h3
-rw-r--r--lib/rbcodec/metadata/vtx.c150
4 files changed, 184 insertions, 22 deletions
diff --git a/lib/rbcodec/metadata/metadata.c b/lib/rbcodec/metadata/metadata.c
index 9c41347975..aec72db97f 100644
--- a/lib/rbcodec/metadata/metadata.c
+++ b/lib/rbcodec/metadata/metadata.c
@@ -43,7 +43,7 @@ static bool get_shn_metadata(int fd, struct mp3entry *id3)
43} 43}
44 44
45static bool get_other_asap_metadata(int fd, struct mp3entry *id3) 45static bool get_other_asap_metadata(int fd, struct mp3entry *id3)
46{ 46{
47 id3->bitrate = 706; 47 id3->bitrate = 706;
48 id3->frequency = 44100; 48 id3->frequency = 44100;
49 id3->vbr = false; 49 id3->vbr = false;
@@ -85,7 +85,7 @@ const struct afmt_entry audio_formats[AFMT_NUM_CODECS] =
85 /* Musepack SV7 */ 85 /* Musepack SV7 */
86 [AFMT_MPC_SV7] = 86 [AFMT_MPC_SV7] =
87 AFMT_ENTRY("MPCv7", "mpc", NULL, get_musepack_metadata,"mpc\0"), 87 AFMT_ENTRY("MPCv7", "mpc", NULL, get_musepack_metadata,"mpc\0"),
88 /* A/52 (aka AC3) audio */ 88 /* A/52 (aka AC3) audio */
89 [AFMT_A52] = 89 [AFMT_A52] =
90 AFMT_ENTRY("AC3", "a52", NULL, get_a52_metadata, "a52\0ac3\0"), 90 AFMT_ENTRY("AC3", "a52", NULL, get_a52_metadata, "a52\0ac3\0"),
91 /* WavPack */ 91 /* WavPack */
@@ -109,7 +109,7 @@ const struct afmt_entry audio_formats[AFMT_NUM_CODECS] =
109 /* NESM (NES Sound Format) */ 109 /* NESM (NES Sound Format) */
110 [AFMT_NSF] = 110 [AFMT_NSF] =
111 AFMT_ENTRY("NSF", "nsf", NULL, get_nsf_metadata, "nsf\0nsfe\0"), 111 AFMT_ENTRY("NSF", "nsf", NULL, get_nsf_metadata, "nsf\0nsfe\0"),
112 /* Speex File Format */ 112 /* Speex File Format */
113 [AFMT_SPEEX] = 113 [AFMT_SPEEX] =
114 AFMT_ENTRY("Speex", "speex",NULL, get_ogg_metadata, "spx\0"), 114 AFMT_ENTRY("Speex", "speex",NULL, get_ogg_metadata, "spx\0"),
115 /* SPC700 Save State */ 115 /* SPC700 Save State */
@@ -162,12 +162,12 @@ const struct afmt_entry audio_formats[AFMT_NUM_CODECS] =
162 AFMT_ENTRY("DLT", "asap", NULL, get_other_asap_metadata,"dlt\0"), 162 AFMT_ENTRY("DLT", "asap", NULL, get_other_asap_metadata,"dlt\0"),
163 /* Atari MPT File */ 163 /* Atari MPT File */
164 [AFMT_MPT] = 164 [AFMT_MPT] =
165 AFMT_ENTRY("MPT", "asap", NULL, get_other_asap_metadata,"mpt\0"), 165 AFMT_ENTRY("MPT", "asap", NULL, get_other_asap_metadata,"mpt\0"),
166 /* Atari MPD File */ 166 /* Atari MPD File */
167 [AFMT_MPD] = 167 [AFMT_MPD] =
168 AFMT_ENTRY("MPD", "asap", NULL, get_other_asap_metadata,"mpd\0"), 168 AFMT_ENTRY("MPD", "asap", NULL, get_other_asap_metadata,"mpd\0"),
169 /* Atari RMT File */ 169 /* Atari RMT File */
170 [AFMT_RMT] = 170 [AFMT_RMT] =
171 AFMT_ENTRY("RMT", "asap", NULL, get_other_asap_metadata,"rmt\0"), 171 AFMT_ENTRY("RMT", "asap", NULL, get_other_asap_metadata,"rmt\0"),
172 /* Atari TMC File */ 172 /* Atari TMC File */
173 [AFMT_TMC] = 173 [AFMT_TMC] =
@@ -177,10 +177,10 @@ const struct afmt_entry audio_formats[AFMT_NUM_CODECS] =
177 AFMT_ENTRY("TM8", "asap", NULL, get_other_asap_metadata,"tm8\0"), 177 AFMT_ENTRY("TM8", "asap", NULL, get_other_asap_metadata,"tm8\0"),
178 /* Atari TM2 File */ 178 /* Atari TM2 File */
179 [AFMT_TM2] = 179 [AFMT_TM2] =
180 AFMT_ENTRY("TM2", "asap", NULL, get_other_asap_metadata,"tm2\0"), 180 AFMT_ENTRY("TM2", "asap", NULL, get_other_asap_metadata,"tm2\0"),
181 /* Atrac3 in Sony OMA Container */ 181 /* Atrac3 in Sony OMA Container */
182 [AFMT_OMA_ATRAC3] = 182 [AFMT_OMA_ATRAC3] =
183 AFMT_ENTRY("ATRAC3","atrac3_oma",NULL, get_oma_metadata, "oma\0aa3\0"), 183 AFMT_ENTRY("ATRAC3","atrac3_oma",NULL, get_oma_metadata, "oma\0aa3\0"),
184 /* SMAF (Synthetic music Mobile Application Format) */ 184 /* SMAF (Synthetic music Mobile Application Format) */
185 [AFMT_SMAF] = 185 [AFMT_SMAF] =
186 AFMT_ENTRY("SMAF", "smaf", NULL, get_smaf_metadata, "mmf\0"), 186 AFMT_ENTRY("SMAF", "smaf", NULL, get_smaf_metadata, "mmf\0"),
@@ -194,7 +194,7 @@ const struct afmt_entry audio_formats[AFMT_NUM_CODECS] =
194 [AFMT_WAVE64] = 194 [AFMT_WAVE64] =
195 AFMT_ENTRY("WAVE64","wav64",NULL, get_wave64_metadata,"w64\0"), 195 AFMT_ENTRY("WAVE64","wav64",NULL, get_wave64_metadata,"w64\0"),
196 /* True Audio */ 196 /* True Audio */
197 [AFMT_TTA] = 197 [AFMT_TTA] =
198 AFMT_ENTRY("TTA", "tta", NULL, get_tta_metadata, "tta\0"), 198 AFMT_ENTRY("TTA", "tta", NULL, get_tta_metadata, "tta\0"),
199 /* WMA Voice in ASF */ 199 /* WMA Voice in ASF */
200 [AFMT_WMAVOICE] = 200 [AFMT_WMAVOICE] =
@@ -206,8 +206,13 @@ const struct afmt_entry audio_formats[AFMT_NUM_CODECS] =
206 [AFMT_MP4_AAC_HE] = 206 [AFMT_MP4_AAC_HE] =
207 AFMT_ENTRY("AAC-HE","aac", NULL, get_mp4_metadata, "mp4\0"), 207 AFMT_ENTRY("AAC-HE","aac", NULL, get_mp4_metadata, "mp4\0"),
208 /* AY (ZX Spectrum, Amstrad CPC Sound Format) */ 208 /* AY (ZX Spectrum, Amstrad CPC Sound Format) */
209 [AFMT_AY] = 209 [AFMT_AY] =
210 AFMT_ENTRY("AY", "ay", NULL, get_ay_metadata, "ay\0"), 210 AFMT_ENTRY("AY", "ay", NULL, get_ay_metadata, "ay\0"),
211 /* AY (ZX Spectrum Sound Format) */
212#ifdef HAVE_FPU
213 [AFMT_VTX] =
214 AFMT_ENTRY("VTX", "vtx", NULL, get_vtx_metadata, "vtx\0"),
215#endif
211 /* GBS (Game Boy Sound Format) */ 216 /* GBS (Game Boy Sound Format) */
212 [AFMT_GBS] = 217 [AFMT_GBS] =
213 AFMT_ENTRY("GBS", "gbs", NULL, get_gbs_metadata, "gbs\0"), 218 AFMT_ENTRY("GBS", "gbs", NULL, get_gbs_metadata, "gbs\0"),
@@ -313,6 +318,9 @@ bool rbcodec_format_is_atomic(int afmt)
313 case AFMT_MOD: 318 case AFMT_MOD:
314 case AFMT_SAP: 319 case AFMT_SAP:
315 case AFMT_AY: 320 case AFMT_AY:
321#ifdef HAVE_FPU
322 case AFMT_VTX:
323#endif
316 case AFMT_GBS: 324 case AFMT_GBS:
317 case AFMT_HES: 325 case AFMT_HES:
318 case AFMT_SGC: 326 case AFMT_SGC:
@@ -352,17 +360,17 @@ unsigned int probe_file_format(const char *filename)
352{ 360{
353 char *suffix; 361 char *suffix;
354 unsigned int i; 362 unsigned int i;
355 363
356 suffix = strrchr(filename, '.'); 364 suffix = strrchr(filename, '.');
357 365
358 if (suffix == NULL) 366 if (suffix == NULL)
359 { 367 {
360 return AFMT_UNKNOWN; 368 return AFMT_UNKNOWN;
361 } 369 }
362 370
363 /* skip '.' */ 371 /* skip '.' */
364 suffix++; 372 suffix++;
365 373
366 for (i = 1; i < AFMT_NUM_CODECS; i++) 374 for (i = 1; i < AFMT_NUM_CODECS; i++)
367 { 375 {
368 /* search extension list for type */ 376 /* search extension list for type */
@@ -379,7 +387,7 @@ unsigned int probe_file_format(const char *filename)
379 } 387 }
380 while (*ext != '\0'); 388 while (*ext != '\0');
381 } 389 }
382 390
383 return AFMT_UNKNOWN; 391 return AFMT_UNKNOWN;
384} 392}
385 393
@@ -418,7 +426,7 @@ bool get_metadata(struct mp3entry* id3, int fd, const char* trackname)
418 close(logfd); 426 close(logfd);
419 } 427 }
420 } 428 }
421 429
422 /* Clear the mp3entry to avoid having bogus pointers appear */ 430 /* Clear the mp3entry to avoid having bogus pointers appear */
423 wipe_mp3entry(id3); 431 wipe_mp3entry(id3);
424 432
@@ -454,7 +462,7 @@ bool get_metadata(struct mp3entry* id3, int fd, const char* trackname)
454void strip_tags(int handle_id) 462void strip_tags(int handle_id)
455{ 463{
456 static const unsigned char tag[] = "TAG"; 464 static const unsigned char tag[] = "TAG";
457 static const unsigned char apetag[] = "APETAGEX"; 465 static const unsigned char apetag[] = "APETAGEX";
458 size_t len, version; 466 size_t len, version;
459 void *tail; 467 void *tail;
460 468
@@ -502,7 +510,7 @@ void adjust_mp3entry(struct mp3entry *entry, void *dest, const void *orig)
502 MOVE_ENTRY(entry->artist) 510 MOVE_ENTRY(entry->artist)
503 MOVE_ENTRY(entry->album) 511 MOVE_ENTRY(entry->album)
504 512
505 if (entry->genre_string > (char*)orig && 513 if (entry->genre_string > (char*)orig &&
506 entry->genre_string < (char*)orig + sizeof(struct mp3entry)) 514 entry->genre_string < (char*)orig + sizeof(struct mp3entry))
507 /* Don't adjust that if it points to an entry of the "genres" array */ 515 /* Don't adjust that if it points to an entry of the "genres" array */
508 entry->genre_string += offset; 516 entry->genre_string += offset;
diff --git a/lib/rbcodec/metadata/metadata.h b/lib/rbcodec/metadata/metadata.h
index 5c78eae9d4..fc9c1d062c 100644
--- a/lib/rbcodec/metadata/metadata.h
+++ b/lib/rbcodec/metadata/metadata.h
@@ -83,6 +83,9 @@ enum
83 AFMT_MPC_SV8, /* Musepack SV8 */ 83 AFMT_MPC_SV8, /* Musepack SV8 */
84 AFMT_MP4_AAC_HE, /* Advanced Audio Coding (AAC-HE) in M4A container */ 84 AFMT_MP4_AAC_HE, /* Advanced Audio Coding (AAC-HE) in M4A container */
85 AFMT_AY, /* AY (ZX Spectrum, Amstrad CPC Sound Format) */ 85 AFMT_AY, /* AY (ZX Spectrum, Amstrad CPC Sound Format) */
86#ifdef HAVE_FPU
87 AFMT_VTX, /* VTX (ZX Spectrum Sound Format) */
88#endif
86 AFMT_GBS, /* GBS (Game Boy Sound Format) */ 89 AFMT_GBS, /* GBS (Game Boy Sound Format) */
87 AFMT_HES, /* HES (Hudson Entertainment System Sound Format) */ 90 AFMT_HES, /* HES (Hudson Entertainment System Sound Format) */
88 AFMT_SGC, /* SGC (Sega Master System, Game Gear, Coleco Vision Sound Format) */ 91 AFMT_SGC, /* SGC (Sega Master System, Game Gear, Coleco Vision Sound Format) */
@@ -140,7 +143,7 @@ enum rec_format_indexes
140 REC_FORMAT_CFG_NUM_BITS = 2 143 REC_FORMAT_CFG_NUM_BITS = 2
141}; 144};
142 145
143#define REC_FORMAT_CFG_VAL_LIST "wave,aiff,wvpk,mpa3" 146#define REC_FORMAT_CFG_VAL_LIST "wave,aiff,wvpk,mpa3"
144 147
145/* get REC_FORMAT_* corresponding AFMT_* */ 148/* get REC_FORMAT_* corresponding AFMT_* */
146extern const int rec_format_afmt[REC_NUM_FORMATS]; 149extern const int rec_format_afmt[REC_NUM_FORMATS];
@@ -232,7 +235,7 @@ struct mp3entry {
232 char* comment; 235 char* comment;
233 char* albumartist; 236 char* albumartist;
234 char* grouping; 237 char* grouping;
235 int discnum; 238 int discnum;
236 int tracknum; 239 int tracknum;
237 int layer; 240 int layer;
238 int year; 241 int year;
@@ -283,7 +286,7 @@ struct mp3entry {
283 286
284#ifdef HAVE_TAGCACHE 287#ifdef HAVE_TAGCACHE
285 unsigned char autoresumable; /* caches result of autoresumable() */ 288 unsigned char autoresumable; /* caches result of autoresumable() */
286 289
287 /* runtime database fields */ 290 /* runtime database fields */
288 long tagcache_idx; /* 0=invalid, otherwise idx+1 */ 291 long tagcache_idx; /* 0=invalid, otherwise idx+1 */
289 int rating; 292 int rating;
@@ -292,7 +295,7 @@ struct mp3entry {
292 long lastplayed; 295 long lastplayed;
293 long playtime; 296 long playtime;
294#endif 297#endif
295 298
296 /* replaygain support */ 299 /* replaygain support */
297 long track_level; /* holds the level in dB * (1<<FP_BITS) */ 300 long track_level; /* holds the level in dB * (1<<FP_BITS) */
298 long album_level; 301 long album_level;
@@ -329,5 +332,3 @@ bool rbcodec_format_is_atomic(int afmt);
329bool format_buffers_with_offset(int afmt); 332bool format_buffers_with_offset(int afmt);
330 333
331#endif 334#endif
332
333
diff --git a/lib/rbcodec/metadata/metadata_parsers.h b/lib/rbcodec/metadata/metadata_parsers.h
index cc7d8a102e..6a4da51b63 100644
--- a/lib/rbcodec/metadata/metadata_parsers.h
+++ b/lib/rbcodec/metadata/metadata_parsers.h
@@ -49,6 +49,9 @@ bool get_vox_metadata(int fd, struct mp3entry* id3);
49bool get_wave64_metadata(int fd, struct mp3entry* id3); 49bool get_wave64_metadata(int fd, struct mp3entry* id3);
50bool get_tta_metadata(int fd, struct mp3entry* id3); 50bool get_tta_metadata(int fd, struct mp3entry* id3);
51bool get_ay_metadata(int fd, struct mp3entry* id3); 51bool get_ay_metadata(int fd, struct mp3entry* id3);
52#ifdef HAVE_FPU
53bool get_vtx_metadata(int fd, struct mp3entry* id3);
54#endif
52bool get_gbs_metadata(int fd, struct mp3entry* id3); 55bool get_gbs_metadata(int fd, struct mp3entry* id3);
53bool get_hes_metadata(int fd, struct mp3entry* id3); 56bool get_hes_metadata(int fd, struct mp3entry* id3);
54bool get_sgc_metadata(int fd, struct mp3entry* id3); 57bool get_sgc_metadata(int fd, struct mp3entry* id3);
diff --git a/lib/rbcodec/metadata/vtx.c b/lib/rbcodec/metadata/vtx.c
new file mode 100644
index 0000000000..eb06528b29
--- /dev/null
+++ b/lib/rbcodec/metadata/vtx.c
@@ -0,0 +1,150 @@
1#include <stdio.h>
2#include <string.h>
3#include <stdlib.h>
4#include <ctype.h>
5#include <inttypes.h>
6#include "platform.h"
7
8#include "metadata.h"
9#include "metadata_common.h"
10#include "metadata_parsers.h"
11#include "rbunicode.h"
12#include "string-extra.h"
13
14typedef unsigned char uchar;
15typedef unsigned short ushort;
16typedef unsigned int uint;
17typedef unsigned long ulong;
18
19typedef enum {
20 VTX_CHIP_AY = 0, /* emulate AY */
21 VTX_CHIP_YM /* emulate YM */
22} vtx_chiptype_t;
23
24typedef enum {
25 VTX_LAYOUT_MONO = 0,
26 VTX_LAYOUT_ABC,
27 VTX_LAYOUT_ACB,
28 VTX_LAYOUT_BAC,
29 VTX_LAYOUT_BCA,
30 VTX_LAYOUT_CAB,
31 VTX_LAYOUT_CBA,
32 VTX_LAYOUT_CUSTOM
33} vtx_layout_t;
34
35typedef struct {
36 vtx_chiptype_t chiptype; /* Type of sound chip */
37 vtx_layout_t layout; /* stereo layout */
38 uint loop; /* song loop */
39 uint chipfreq; /* AY chip freq (1773400 for ZX) */
40 uint playerfreq; /* 50 Hz for ZX, 60 Hz for yamaha */
41 uint year; /* year song composed */
42 char *title; /* song title */
43 char *author; /* song author */
44 char *from; /* song from */
45 char *tracker; /* tracker */
46 char *comment; /* comment */
47 uint regdata_size; /* size of unpacked data */
48 uint frames; /* number of AY data frames */
49} vtx_info_t;
50
51#define VTX_STRING_MAX 254
52
53static uint Reader_ReadByte(int fd) {
54 unsigned char c;
55 read(fd, &c, sizeof(c));
56 return c;
57}
58
59static uint Reader_ReadWord(int fd) {
60 unsigned short s;
61 read(fd, &s, sizeof(s));
62 return letoh16(s);
63}
64
65static uint Reader_ReadDWord(int fd) {
66 unsigned int i;
67 read(fd, &i, sizeof(i));
68 return letoh32(i);
69}
70
71static char* Reader_ReadString(int fd, char *str) {
72 int i = 0;
73 char c = 1;
74 char *p = str;
75
76 if (str)
77 *str = 0;
78
79 while (i < VTX_STRING_MAX && c) {
80 read(fd, &c, sizeof(c));
81 if (str)
82 *str++ = c;
83 i++;
84 }
85
86 if (str)
87 *str = 0;
88
89 return p;
90}
91
92/* vtx info */
93
94bool get_vtx_metadata(int fd, struct mp3entry* id3)
95{
96 vtx_info_t info;
97 char *p = id3->id3v2buf;
98 char buf[VTX_STRING_MAX+1];
99
100 if (lseek(fd, 0, SEEK_SET) < 0)
101 goto exit_bad;
102
103 if (filesize(fd) < 20)
104 goto exit_bad;
105
106 uint hdr = Reader_ReadWord(fd);
107
108 if ((hdr != 0x7961) && (hdr != 0x6d79))
109 goto exit_bad;
110
111 info.layout = (vtx_layout_t)Reader_ReadByte(fd);
112 info.loop = Reader_ReadWord(fd);
113 info.chipfreq = Reader_ReadDWord(fd);
114 info.playerfreq = Reader_ReadByte(fd);
115 info.year = Reader_ReadWord(fd);
116 info.regdata_size = Reader_ReadDWord(fd);
117 info.frames = info.regdata_size / 14;
118 info.title = Reader_ReadString(fd, buf);
119 if (buf[0]) {
120 /* Title */
121 id3->title = p;
122 p += strlcpy(p, info.title, VTX_STRING_MAX) + 1;
123 }
124 info.author = Reader_ReadString(fd, buf);
125 if (buf[0]) {
126 /* Artist */
127 id3->artist = p;
128 p += strlcpy(p, info.author, VTX_STRING_MAX) + 1;
129 }
130 info.from = Reader_ReadString(fd, NULL);
131 info.tracker = Reader_ReadString(fd, NULL);
132 info.comment = Reader_ReadString(fd, buf);
133 if (buf[0]) {
134 /* Comment */
135 id3->comment = p;
136 p += strlcpy(p, info.comment, VTX_STRING_MAX) + 1;
137 }
138
139 id3->vbr = false;
140 id3->bitrate = 706;
141 id3->frequency = 44100; // XXX allow this to be configured?
142
143 id3->filesize = filesize(fd);
144 id3->length = info.frames * 1000 / info.playerfreq;
145
146 return true;
147
148exit_bad:
149 return false;
150}