zoo: Various improvements
[deark.git] / modules / flac.c
blobee544e22db2d24e245cfcaffd32e367aae5d762d
1 // This file is part of Deark.
2 // Copyright (C) 2018 Jason Summers
3 // See the file COPYING for terms of use.
5 // FLAC audio
7 #include <deark-config.h>
8 #include <deark-private.h>
9 #include <deark-fmtutil.h>
10 DE_DECLARE_MODULE(de_module_flac);
12 typedef struct localctx_struct {
13 int reserved;
14 } lctx;
16 static const char *get_mdblk_name(u8 blktype)
18 const char *name = NULL;
19 switch(blktype) {
20 case 0: name="STREAMINFO"; break;
21 case 1: name="PADDING"; break;
22 case 2: name="APPLICATION"; break;
23 case 3: name="SEEKTABLE"; break;
24 case 4: name="VORBIS_COMMENT"; break;
25 case 5: name="CUESHEET"; break;
26 case 6: name="PICTURE"; break;
28 return name?name:"?";
31 static void do_metadata_block_vorbiscomment(deark *c, lctx *d, i64 pos1, i64 len)
33 de_dbg(c, "vorbis comment block at %"I64_FMT, pos1);
34 de_dbg_indent(c, 1);
35 de_run_module_by_id_on_slice2(c, "ogg", "C", c->infile, pos1, len);
36 de_dbg_indent(c, -1);
39 static void do_metadata_block_picture(deark *c, lctx *d, i64 pos1, i64 len)
41 de_dbg(c, "picture at %"I64_FMT, pos1);
42 de_dbg_indent(c, 1);
43 de_run_module_by_id_on_slice2(c, "id3", "F", c->infile, pos1, len);
44 de_dbg_indent(c, -1);
47 static void do_metadata_block(deark *c, lctx *d, u8 blktype, i64 pos1, i64 len)
49 switch(blktype) {
50 case 4:
51 do_metadata_block_vorbiscomment(c, d, pos1, len);
52 break;
53 case 6:
54 do_metadata_block_picture(c, d, pos1, len);
55 break;
59 static void run_flac_internal(deark *c, lctx *d, i64 pos1, i64 len)
61 i64 pos = pos1;
62 int saved_indent_level;
64 de_dbg(c, "signature at %"I64_FMT, pos);
65 pos += 4;
67 de_dbg_indent_save(c, &saved_indent_level);
68 while(1) {
69 u8 b;
70 i64 blklen;
71 u8 blktype;
72 const char *blkname;
73 u8 is_last;
75 if(pos >= pos1+len) goto done;
76 de_dbg(c, "metadata block at %"I64_FMT, pos);
77 de_dbg_indent(c, 1);
78 b = de_getbyte_p(&pos);
79 is_last = (b&0x80)!=0;
80 de_dbg(c, "is-last: %u", (unsigned int)is_last);
81 blktype = (b&0x7f);
82 blkname = get_mdblk_name(blktype);
83 de_dbg(c, "block type: %u (%s)", (unsigned int)blktype, blkname);
84 blklen = dbuf_getint_ext(c->infile, pos, 3, 0, 0);
85 pos += 3;
86 de_dbg(c, "block len: %u", (unsigned int)blklen);
87 do_metadata_block(c, d, blktype, pos, blklen);
88 pos += blklen;
89 de_dbg_indent(c, -1);
90 if(is_last) break;
93 de_dbg(c, "frames start at %"I64_FMT, pos);
95 done:
96 de_dbg_indent_restore(c, saved_indent_level);
99 static void de_run_flac(deark *c, de_module_params *mparams)
101 lctx *d = NULL;
102 struct de_id3info id3i;
104 d = de_malloc(c, sizeof(lctx));
105 fmtutil_handle_id3(c, c->infile, &id3i, 0);
106 run_flac_internal(c, d, id3i.main_start, id3i.main_end-id3i.main_start);
107 de_free(c, d);
110 static int de_identify_flac(deark *c)
112 i64 pos = 0;
114 if(!c->detection_data->id3.detection_attempted) {
115 de_err(c, "flac detection requires id3 module");
116 return 0;
119 if(c->detection_data->id3.has_id3v2) {
120 pos = (i64)c->detection_data->id3.bytes_at_start;
123 if(!dbuf_memcmp(c->infile, pos, "fLaC", 4))
124 return 100;
126 return 0;
129 void de_module_flac(deark *c, struct deark_module_info *mi)
131 mi->id = "flac";
132 mi->desc = "FLAC";
133 mi->run_fn = de_run_flac;
134 mi->identify_fn = de_identify_flac;