Source file metadataRIFF.ml
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
open MetadataBase
module R = Reader
let tagn =
[
("IART", "artist");
("ICMT", "comment");
("ICOP", "copyright");
("ICRD", "date");
("ICRD", "date");
("IGNR", "genre");
("INAM", "title");
("IPRD", "album");
("IPRT", "track");
("ISFT", "encoder");
("ITRK", "track");
]
let parse ?format f : metadata =
if R.read f 4 <> "RIFF" then raise Invalid;
let _ = R.int32_le f in
if format <> None && Some (R.read f 4) <> format then raise Invalid;
let ans = ref [] in
let chunk () =
let tag = R.read f 4 in
let size = R.int32_le f in
if tag <> "LIST" then R.drop f size
else (
let subtag = R.read f 4 in
match subtag with
| "INFO" ->
let remaining = ref (size - 4) in
while !remaining > 0 do
let tag = R.read f 4 in
let size = R.int32_le f in
match R.read_tag ~length:(size - 1) ~label:tag f with
| None -> ()
| Some s ->
R.drop f 1;
let padding = size mod 2 in
R.drop f padding;
remaining := !remaining - (8 + size + padding);
let tag =
match List.assoc_opt tag tagn with
| Some tag -> tag
| None -> tag
in
ans := (tag, s) :: !ans
done
| "movi" -> raise Exit
| _ -> R.drop f (size - 4))
in
try
while true do
chunk ()
done;
assert false
with _ -> List.rev !ans
let parse_file ?format ?custom_parser file = R.with_file ?custom_parser (parse ?format) file