add number-of-colors field to PICTURE metadata block
[platform/upstream/flac.git] / src / test_libs_common / metadata_utils.c
1 /* test_libFLAC - Unit tester for libFLAC
2  * Copyright (C) 2002,2003,2004,2005,2006  Josh Coalson
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17  */
18
19 /*
20  * These are not tests, just utility functions used by the metadata tests
21  */
22
23 #if HAVE_CONFIG_H
24 #  include <config.h>
25 #endif
26
27 #include "FLAC/metadata.h"
28 #include "test_libs_common/metadata_utils.h"
29 #include <stdio.h>
30 #include <stdlib.h> /* for malloc() */
31 #include <string.h> /* for memcmp() */
32
33 FLAC__bool mutils__compare_block_data_streaminfo(const FLAC__StreamMetadata_StreamInfo *block, const FLAC__StreamMetadata_StreamInfo *blockcopy)
34 {
35         if(blockcopy->min_blocksize != block->min_blocksize) {
36                 printf("FAILED, min_blocksize mismatch, expected %u, got %u\n", block->min_blocksize, blockcopy->min_blocksize);
37                 return false;
38         }
39         if(blockcopy->max_blocksize != block->max_blocksize) {
40                 printf("FAILED, max_blocksize mismatch, expected %u, got %u\n", block->max_blocksize, blockcopy->max_blocksize);
41                 return false;
42         }
43         if(blockcopy->min_framesize != block->min_framesize) {
44                 printf("FAILED, min_framesize mismatch, expected %u, got %u\n", block->min_framesize, blockcopy->min_framesize);
45                 return false;
46         }
47         if(blockcopy->max_framesize != block->max_framesize) {
48                 printf("FAILED, max_framesize mismatch, expected %u, got %u\n", block->max_framesize, blockcopy->max_framesize);
49                 return false;
50         }
51         if(blockcopy->sample_rate != block->sample_rate) {
52                 printf("FAILED, sample_rate mismatch, expected %u, got %u\n", block->sample_rate, blockcopy->sample_rate);
53                 return false;
54         }
55         if(blockcopy->channels != block->channels) {
56                 printf("FAILED, channels mismatch, expected %u, got %u\n", block->channels, blockcopy->channels);
57                 return false;
58         }
59         if(blockcopy->bits_per_sample != block->bits_per_sample) {
60                 printf("FAILED, bits_per_sample mismatch, expected %u, got %u\n", block->bits_per_sample, blockcopy->bits_per_sample);
61                 return false;
62         }
63         if(blockcopy->total_samples != block->total_samples) {
64                 printf("FAILED, total_samples mismatch, expected %llu, got %llu\n", block->total_samples, blockcopy->total_samples);
65                 return false;
66         }
67         if(0 != memcmp(blockcopy->md5sum, block->md5sum, sizeof(block->md5sum))) {
68                 printf("FAILED, md5sum mismatch, expected %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X, got %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n",
69                         (unsigned)block->md5sum[0],
70                         (unsigned)block->md5sum[1],
71                         (unsigned)block->md5sum[2],
72                         (unsigned)block->md5sum[3],
73                         (unsigned)block->md5sum[4],
74                         (unsigned)block->md5sum[5],
75                         (unsigned)block->md5sum[6],
76                         (unsigned)block->md5sum[7],
77                         (unsigned)block->md5sum[8],
78                         (unsigned)block->md5sum[9],
79                         (unsigned)block->md5sum[10],
80                         (unsigned)block->md5sum[11],
81                         (unsigned)block->md5sum[12],
82                         (unsigned)block->md5sum[13],
83                         (unsigned)block->md5sum[14],
84                         (unsigned)block->md5sum[15],
85                         (unsigned)blockcopy->md5sum[0],
86                         (unsigned)blockcopy->md5sum[1],
87                         (unsigned)blockcopy->md5sum[2],
88                         (unsigned)blockcopy->md5sum[3],
89                         (unsigned)blockcopy->md5sum[4],
90                         (unsigned)blockcopy->md5sum[5],
91                         (unsigned)blockcopy->md5sum[6],
92                         (unsigned)blockcopy->md5sum[7],
93                         (unsigned)blockcopy->md5sum[8],
94                         (unsigned)blockcopy->md5sum[9],
95                         (unsigned)blockcopy->md5sum[10],
96                         (unsigned)blockcopy->md5sum[11],
97                         (unsigned)blockcopy->md5sum[12],
98                         (unsigned)blockcopy->md5sum[13],
99                         (unsigned)blockcopy->md5sum[14],
100                         (unsigned)blockcopy->md5sum[15]
101                 );
102                 return false;
103         }
104         return true;
105 }
106
107 FLAC__bool mutils__compare_block_data_padding(const FLAC__StreamMetadata_Padding *block, const FLAC__StreamMetadata_Padding *blockcopy, unsigned block_length)
108 {
109         /* we don't compare the padding guts */
110         (void)block, (void)blockcopy, (void)block_length;
111         return true;
112 }
113
114 FLAC__bool mutils__compare_block_data_application(const FLAC__StreamMetadata_Application *block, const FLAC__StreamMetadata_Application *blockcopy, unsigned block_length)
115 {
116         if(block_length < sizeof(block->id)) {
117                 printf("FAILED, bad block length = %u\n", block_length);
118                 return false;
119         }
120         if(0 != memcmp(blockcopy->id, block->id, sizeof(block->id))) {
121                 printf("FAILED, id mismatch, expected %02X%02X%02X%02X, got %02X%02X%02X%02X\n",
122                         (unsigned)block->id[0],
123                         (unsigned)block->id[1],
124                         (unsigned)block->id[2],
125                         (unsigned)block->id[3],
126                         (unsigned)blockcopy->id[0],
127                         (unsigned)blockcopy->id[1],
128                         (unsigned)blockcopy->id[2],
129                         (unsigned)blockcopy->id[3]
130                 );
131                 return false;
132         }
133         if(0 == block->data || 0 == blockcopy->data) {
134                 if(block->data != blockcopy->data) {
135                         printf("FAILED, data mismatch (%s's data pointer is null)\n", 0==block->data?"original":"copy");
136                         return false;
137                 }
138                 else if(block_length - sizeof(block->id) > 0) {
139                         printf("FAILED, data pointer is null but block length is not 0\n");
140                         return false;
141                 }
142         }
143         else {
144                 if(block_length - sizeof(block->id) == 0) {
145                         printf("FAILED, data pointer is not null but block length is 0\n");
146                         return false;
147                 }
148                 else if(0 != memcmp(blockcopy->data, block->data, block_length - sizeof(block->id))) {
149                         printf("FAILED, data mismatch\n");
150                         return false;
151                 }
152         }
153         return true;
154 }
155
156 FLAC__bool mutils__compare_block_data_seektable(const FLAC__StreamMetadata_SeekTable *block, const FLAC__StreamMetadata_SeekTable *blockcopy)
157 {
158         unsigned i;
159         if(blockcopy->num_points != block->num_points) {
160                 printf("FAILED, num_points mismatch, expected %u, got %u\n", block->num_points, blockcopy->num_points);
161                 return false;
162         }
163         for(i = 0; i < block->num_points; i++) {
164                 if(blockcopy->points[i].sample_number != block->points[i].sample_number) {
165                         printf("FAILED, points[%u].sample_number mismatch, expected %llu, got %llu\n", i, block->points[i].sample_number, blockcopy->points[i].sample_number);
166                         return false;
167                 }
168                 if(blockcopy->points[i].stream_offset != block->points[i].stream_offset) {
169                         printf("FAILED, points[%u].stream_offset mismatch, expected %llu, got %llu\n", i, block->points[i].stream_offset, blockcopy->points[i].stream_offset);
170                         return false;
171                 }
172                 if(blockcopy->points[i].frame_samples != block->points[i].frame_samples) {
173                         printf("FAILED, points[%u].frame_samples mismatch, expected %u, got %u\n", i, block->points[i].frame_samples, blockcopy->points[i].frame_samples);
174                         return false;
175                 }
176         }
177         return true;
178 }
179
180 FLAC__bool mutils__compare_block_data_vorbiscomment(const FLAC__StreamMetadata_VorbisComment *block, const FLAC__StreamMetadata_VorbisComment *blockcopy)
181 {
182         unsigned i;
183         if(blockcopy->vendor_string.length != block->vendor_string.length) {
184                 printf("FAILED, vendor_string.length mismatch, expected %u, got %u\n", block->vendor_string.length, blockcopy->vendor_string.length);
185                 return false;
186         }
187         if(0 == block->vendor_string.entry || 0 == blockcopy->vendor_string.entry) {
188                 if(block->vendor_string.entry != blockcopy->vendor_string.entry) {
189                         printf("FAILED, vendor_string.entry mismatch\n");
190                         return false;
191                 }
192         }
193         else if(0 != memcmp(blockcopy->vendor_string.entry, block->vendor_string.entry, block->vendor_string.length)) {
194                 printf("FAILED, vendor_string.entry mismatch\n");
195                 return false;
196         }
197         if(blockcopy->num_comments != block->num_comments) {
198                 printf("FAILED, num_comments mismatch, expected %u, got %u\n", block->num_comments, blockcopy->num_comments);
199                 return false;
200         }
201         for(i = 0; i < block->num_comments; i++) {
202                 if(blockcopy->comments[i].length != block->comments[i].length) {
203                         printf("FAILED, comments[%u].length mismatch, expected %u, got %u\n", i, block->comments[i].length, blockcopy->comments[i].length);
204                         return false;
205                 }
206                 if(0 == block->comments[i].entry || 0 == blockcopy->comments[i].entry) {
207                         if(block->comments[i].entry != blockcopy->comments[i].entry) {
208                                 printf("FAILED, comments[%u].entry mismatch\n", i);
209                                 return false;
210                         }
211                 }
212                 else {
213                         if(0 != memcmp(blockcopy->comments[i].entry, block->comments[i].entry, block->comments[i].length)) {
214                                 printf("FAILED, comments[%u].entry mismatch\n", i);
215                                 return false;
216                         }
217                 }
218         }
219         return true;
220 }
221
222 FLAC__bool mutils__compare_block_data_cuesheet(const FLAC__StreamMetadata_CueSheet *block, const FLAC__StreamMetadata_CueSheet *blockcopy)
223 {
224         unsigned i, j;
225
226         if(0 != strcmp(blockcopy->media_catalog_number, block->media_catalog_number)) {
227                 printf("FAILED, media_catalog_number mismatch, expected %s, got %s\n", block->media_catalog_number, blockcopy->media_catalog_number);
228                 return false;
229         }
230         if(blockcopy->lead_in != block->lead_in) {
231                 printf("FAILED, lead_in mismatch, expected %llu, got %llu\n", block->lead_in, blockcopy->lead_in);
232                 return false;
233         }
234         if(blockcopy->is_cd != block->is_cd) {
235                 printf("FAILED, is_cd mismatch, expected %u, got %u\n", (unsigned)block->is_cd, (unsigned)blockcopy->is_cd);
236                 return false;
237         }
238         if(blockcopy->num_tracks != block->num_tracks) {
239                 printf("FAILED, num_tracks mismatch, expected %u, got %u\n", block->num_tracks, blockcopy->num_tracks);
240                 return false;
241         }
242         for(i = 0; i < block->num_tracks; i++) {
243                 if(blockcopy->tracks[i].offset != block->tracks[i].offset) {
244                         printf("FAILED, tracks[%u].offset mismatch, expected %llu, got %llu\n", i, block->tracks[i].offset, blockcopy->tracks[i].offset);
245                         return false;
246                 }
247                 if(blockcopy->tracks[i].number != block->tracks[i].number) {
248                         printf("FAILED, tracks[%u].number mismatch, expected %u, got %u\n", i, (unsigned)block->tracks[i].number, (unsigned)blockcopy->tracks[i].number);
249                         return false;
250                 }
251                 if(blockcopy->tracks[i].num_indices != block->tracks[i].num_indices) {
252                         printf("FAILED, tracks[%u].num_indices mismatch, expected %u, got %u\n", i, (unsigned)block->tracks[i].num_indices, (unsigned)blockcopy->tracks[i].num_indices);
253                         return false;
254                 }
255                 /* num_indices == 0 means lead-out track so only the track offset and number are valid */
256                 if(block->tracks[i].num_indices > 0) {
257                         if(0 != strcmp(blockcopy->tracks[i].isrc, block->tracks[i].isrc)) {
258                                 printf("FAILED, tracks[%u].isrc mismatch, expected %s, got %s\n", i, block->tracks[i].isrc, blockcopy->tracks[i].isrc);
259                                 return false;
260                         }
261                         if(blockcopy->tracks[i].type != block->tracks[i].type) {
262                                 printf("FAILED, tracks[%u].type mismatch, expected %u, got %u\n", i, (unsigned)block->tracks[i].type, (unsigned)blockcopy->tracks[i].type);
263                                 return false;
264                         }
265                         if(blockcopy->tracks[i].pre_emphasis != block->tracks[i].pre_emphasis) {
266                                 printf("FAILED, tracks[%u].pre_emphasis mismatch, expected %u, got %u\n", i, (unsigned)block->tracks[i].pre_emphasis, (unsigned)blockcopy->tracks[i].pre_emphasis);
267                                 return false;
268                         }
269                         if(0 == block->tracks[i].indices || 0 == blockcopy->tracks[i].indices) {
270                                 if(block->tracks[i].indices != blockcopy->tracks[i].indices) {
271                                         printf("FAILED, tracks[%u].indices mismatch\n", i);
272                                         return false;
273                                 }
274                         }
275                         else {
276                                 for(j = 0; j < block->tracks[i].num_indices; j++) {
277                                         if(blockcopy->tracks[i].indices[j].offset != block->tracks[i].indices[j].offset) {
278                                                 printf("FAILED, tracks[%u].indices[%u].offset mismatch, expected %llu, got %llu\n", i, j, block->tracks[i].indices[j].offset, blockcopy->tracks[i].indices[j].offset);
279                                                 return false;
280                                         }
281                                         if(blockcopy->tracks[i].indices[j].number != block->tracks[i].indices[j].number) {
282                                                 printf("FAILED, tracks[%u].indices[%u].number mismatch, expected %u, got %u\n", i, j, (unsigned)block->tracks[i].indices[j].number, (unsigned)blockcopy->tracks[i].indices[j].number);
283                                                 return false;
284                                         }
285                                 }
286                         }
287                 }
288         }
289         return true;
290 }
291
292 FLAC__bool mutils__compare_block_data_picture(const FLAC__StreamMetadata_Picture *block, const FLAC__StreamMetadata_Picture *blockcopy)
293 {
294         size_t len, lencopy;
295         if(blockcopy->type != block->type) {
296                 printf("FAILED, type mismatch, expected %u, got %u\n", (unsigned)block->type, (unsigned)blockcopy->type);
297                 return false;
298         }
299         len = strlen(block->mime_type);
300         lencopy = strlen(blockcopy->mime_type);
301         if(lencopy != len) {
302                 printf("FAILED, mime_type length mismatch, expected %u, got %u\n", (unsigned)len, (unsigned)lencopy);
303                 return false;
304         }
305         if(strcmp(blockcopy->mime_type, block->mime_type)) {
306                 printf("FAILED, mime_type mismatch, expected %s, got %s\n", block->mime_type, blockcopy->mime_type);
307                 return false;
308         }
309         len = strlen((const char *)block->description);
310         lencopy = strlen((const char *)blockcopy->description);
311         if(lencopy != len) {
312                 printf("FAILED, description length mismatch, expected %u, got %u\n", (unsigned)len, (unsigned)lencopy);
313                 return false;
314         }
315         if(strcmp((const char *)blockcopy->description, (const char *)block->description)) {
316                 printf("FAILED, description mismatch, expected %s, got %s\n", block->description, blockcopy->description);
317                 return false;
318         }
319         if(blockcopy->width != block->width) {
320                 printf("FAILED, width mismatch, expected %u, got %u\n", block->width, blockcopy->width);
321                 return false;
322         }
323         if(blockcopy->height != block->height) {
324                 printf("FAILED, height mismatch, expected %u, got %u\n", block->height, blockcopy->height);
325                 return false;
326         }
327         if(blockcopy->depth != block->depth) {
328                 printf("FAILED, depth mismatch, expected %u, got %u\n", block->depth, blockcopy->depth);
329                 return false;
330         }
331         if(blockcopy->colors != block->colors) {
332                 printf("FAILED, colors mismatch, expected %u, got %u\n", block->colors, blockcopy->colors);
333                 return false;
334         }
335         if(blockcopy->data_length != block->data_length) {
336                 printf("FAILED, data_length mismatch, expected %u, got %u\n", block->data_length, blockcopy->data_length);
337                 return false;
338         }
339         if(memcmp(blockcopy->data, block->data, block->data_length)) {
340                 printf("FAILED, data mismatch\n");
341                 return false;
342         }
343         return true;
344 }
345
346 FLAC__bool mutils__compare_block_data_unknown(const FLAC__StreamMetadata_Unknown *block, const FLAC__StreamMetadata_Unknown *blockcopy, unsigned block_length)
347 {
348         if(0 == block->data || 0 == blockcopy->data) {
349                 if(block->data != blockcopy->data) {
350                         printf("FAILED, data mismatch (%s's data pointer is null)\n", 0==block->data?"original":"copy");
351                         return false;
352                 }
353                 else if(block_length > 0) {
354                         printf("FAILED, data pointer is null but block length is not 0\n");
355                         return false;
356                 }
357         }
358         else {
359                 if(block_length == 0) {
360                         printf("FAILED, data pointer is not null but block length is 0\n");
361                         return false;
362                 }
363                 else if(0 != memcmp(blockcopy->data, block->data, block_length)) {
364                         printf("FAILED, data mismatch\n");
365                         return false;
366                 }
367         }
368         return true;
369 }
370
371 FLAC__bool mutils__compare_block(const FLAC__StreamMetadata *block, const FLAC__StreamMetadata *blockcopy)
372 {
373         if(blockcopy->type != block->type) {
374                 printf("FAILED, type mismatch, expected %s, got %s\n", FLAC__MetadataTypeString[block->type], FLAC__MetadataTypeString[blockcopy->type]);
375                 return false;
376         }
377         if(blockcopy->is_last != block->is_last) {
378                 printf("FAILED, is_last mismatch, expected %u, got %u\n", (unsigned)block->is_last, (unsigned)blockcopy->is_last);
379                 return false;
380         }
381         if(blockcopy->length != block->length) {
382                 printf("FAILED, length mismatch, expected %u, got %u\n", block->length, blockcopy->length);
383                 return false;
384         }
385         switch(block->type) {
386                 case FLAC__METADATA_TYPE_STREAMINFO:
387                         return mutils__compare_block_data_streaminfo(&block->data.stream_info, &blockcopy->data.stream_info);
388                 case FLAC__METADATA_TYPE_PADDING:
389                         return mutils__compare_block_data_padding(&block->data.padding, &blockcopy->data.padding, block->length);
390                 case FLAC__METADATA_TYPE_APPLICATION:
391                         return mutils__compare_block_data_application(&block->data.application, &blockcopy->data.application, block->length);
392                 case FLAC__METADATA_TYPE_SEEKTABLE:
393                         return mutils__compare_block_data_seektable(&block->data.seek_table, &blockcopy->data.seek_table);
394                 case FLAC__METADATA_TYPE_VORBIS_COMMENT:
395                         return mutils__compare_block_data_vorbiscomment(&block->data.vorbis_comment, &blockcopy->data.vorbis_comment);
396                 case FLAC__METADATA_TYPE_CUESHEET:
397                         return mutils__compare_block_data_cuesheet(&block->data.cue_sheet, &blockcopy->data.cue_sheet);
398                 case FLAC__METADATA_TYPE_PICTURE:
399                         return mutils__compare_block_data_picture(&block->data.picture, &blockcopy->data.picture);
400                 default:
401                         return mutils__compare_block_data_unknown(&block->data.unknown, &blockcopy->data.unknown, block->length);
402         }
403 }
404
405 static void *malloc_or_die_(size_t size)
406 {
407         void *x = malloc(size);
408         if(0 == x) {
409                 fprintf(stderr, "ERROR: out of memory allocating %u bytes\n", (unsigned)size);
410                 exit(1);
411         }
412         return x;
413 }
414
415 static void *calloc_or_die_(size_t n, size_t size)
416 {
417         void *x = calloc(n, size);
418         if(0 == x) {
419                 fprintf(stderr, "ERROR: out of memory allocating %u bytes\n", (unsigned)n * (unsigned)size);
420                 exit(1);
421         }
422         return x;
423 }
424
425 static char *strdup_or_die_(const char *s)
426 {
427         char *x = strdup(s);
428         if(0 == x) {
429                 fprintf(stderr, "ERROR: out of memory copying string \"%s\"\n", s);
430                 exit(1);
431         }
432         return x;
433 }
434
435 void mutils__init_metadata_blocks(
436         FLAC__StreamMetadata *streaminfo,
437         FLAC__StreamMetadata *padding,
438         FLAC__StreamMetadata *seektable,
439         FLAC__StreamMetadata *application1,
440         FLAC__StreamMetadata *application2,
441         FLAC__StreamMetadata *vorbiscomment,
442         FLAC__StreamMetadata *cuesheet,
443         FLAC__StreamMetadata *picture,
444         FLAC__StreamMetadata *unknown
445 )
446 {
447         /*
448                 most of the actual numbers and data in the blocks don't matter,
449                 we just want to make sure the decoder parses them correctly
450
451                 remember, the metadata interface gets tested after the decoders,
452                 so we do all the metadata manipulation here without it.
453         */
454
455         /* min/max_framesize and md5sum don't get written at first, so we have to leave them 0 */
456         streaminfo->is_last = false;
457         streaminfo->type = FLAC__METADATA_TYPE_STREAMINFO;
458         streaminfo->length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
459         streaminfo->data.stream_info.min_blocksize = 576;
460         streaminfo->data.stream_info.max_blocksize = 576;
461         streaminfo->data.stream_info.min_framesize = 0;
462         streaminfo->data.stream_info.max_framesize = 0;
463         streaminfo->data.stream_info.sample_rate = 44100;
464         streaminfo->data.stream_info.channels = 1;
465         streaminfo->data.stream_info.bits_per_sample = 8;
466         streaminfo->data.stream_info.total_samples = 0;
467         memset(streaminfo->data.stream_info.md5sum, 0, 16);
468
469         padding->is_last = false;
470         padding->type = FLAC__METADATA_TYPE_PADDING;
471         padding->length = 1234;
472
473         seektable->is_last = false;
474         seektable->type = FLAC__METADATA_TYPE_SEEKTABLE;
475         seektable->data.seek_table.num_points = 2;
476         seektable->length = seektable->data.seek_table.num_points * FLAC__STREAM_METADATA_SEEKPOINT_LENGTH;
477         seektable->data.seek_table.points = (FLAC__StreamMetadata_SeekPoint*)malloc_or_die_(seektable->data.seek_table.num_points * sizeof(FLAC__StreamMetadata_SeekPoint));
478         seektable->data.seek_table.points[0].sample_number = 0;
479         seektable->data.seek_table.points[0].stream_offset = 0;
480         seektable->data.seek_table.points[0].frame_samples = streaminfo->data.stream_info.min_blocksize;
481         seektable->data.seek_table.points[1].sample_number = FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER;
482         seektable->data.seek_table.points[1].stream_offset = 1000;
483         seektable->data.seek_table.points[1].frame_samples = streaminfo->data.stream_info.min_blocksize;
484
485         application1->is_last = false;
486         application1->type = FLAC__METADATA_TYPE_APPLICATION;
487         application1->length = 8;
488         memcpy(application1->data.application.id, "\xfe\xdc\xba\x98", 4);
489         application1->data.application.data = (FLAC__byte*)malloc_or_die_(4);
490         memcpy(application1->data.application.data, "\xf0\xe1\xd2\xc3", 4);
491
492         application2->is_last = false;
493         application2->type = FLAC__METADATA_TYPE_APPLICATION;
494         application2->length = 4;
495         memcpy(application2->data.application.id, "\x76\x54\x32\x10", 4);
496         application2->data.application.data = 0;
497
498         {
499                 const unsigned vendor_string_length = (unsigned)strlen(FLAC__VENDOR_STRING);
500                 vorbiscomment->is_last = false;
501                 vorbiscomment->type = FLAC__METADATA_TYPE_VORBIS_COMMENT;
502                 vorbiscomment->length = (4 + vendor_string_length) + 4 + (4 + 5) + (4 + 0);
503                 vorbiscomment->data.vorbis_comment.vendor_string.length = vendor_string_length;
504                 vorbiscomment->data.vorbis_comment.vendor_string.entry = (FLAC__byte*)malloc_or_die_(vendor_string_length+1);
505                 memcpy(vorbiscomment->data.vorbis_comment.vendor_string.entry, FLAC__VENDOR_STRING, vendor_string_length+1);
506                 vorbiscomment->data.vorbis_comment.num_comments = 2;
507                 vorbiscomment->data.vorbis_comment.comments = (FLAC__StreamMetadata_VorbisComment_Entry*)malloc_or_die_(vorbiscomment->data.vorbis_comment.num_comments * sizeof(FLAC__StreamMetadata_VorbisComment_Entry));
508                 vorbiscomment->data.vorbis_comment.comments[0].length = 5;
509                 vorbiscomment->data.vorbis_comment.comments[0].entry = (FLAC__byte*)malloc_or_die_(5+1);
510                 memcpy(vorbiscomment->data.vorbis_comment.comments[0].entry, "ab=cd", 5+1);
511                 vorbiscomment->data.vorbis_comment.comments[1].length = 0;
512                 vorbiscomment->data.vorbis_comment.comments[1].entry = 0;
513         }
514
515         cuesheet->is_last = false;
516         cuesheet->type = FLAC__METADATA_TYPE_CUESHEET;
517         cuesheet->length =
518                 /* cuesheet guts */
519                 (
520                         FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN +
521                         FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN +
522                         FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN +
523                         FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN +
524                         FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN
525                 ) / 8 +
526                 /* 2 tracks */
527                 3 * (
528                         FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN +
529                         FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN +
530                         FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN +
531                         FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN +
532                         FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN +
533                         FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN +
534                         FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN
535                 ) / 8 +
536                 /* 3 index points */
537                 3 * (
538                         FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN +
539                         FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN +
540                         FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN
541                 ) / 8
542         ;
543         memset(cuesheet->data.cue_sheet.media_catalog_number, 0, sizeof(cuesheet->data.cue_sheet.media_catalog_number));
544         cuesheet->data.cue_sheet.media_catalog_number[0] = 'j';
545         cuesheet->data.cue_sheet.media_catalog_number[1] = 'C';
546         cuesheet->data.cue_sheet.lead_in = 2 * 44100;
547         cuesheet->data.cue_sheet.is_cd = true;
548         cuesheet->data.cue_sheet.num_tracks = 3;
549         cuesheet->data.cue_sheet.tracks = (FLAC__StreamMetadata_CueSheet_Track*)calloc_or_die_(cuesheet->data.cue_sheet.num_tracks, sizeof(FLAC__StreamMetadata_CueSheet_Track));
550         cuesheet->data.cue_sheet.tracks[0].offset = 0;
551         cuesheet->data.cue_sheet.tracks[0].number = 1;
552         memcpy(cuesheet->data.cue_sheet.tracks[0].isrc, "ACBDE1234567", sizeof(cuesheet->data.cue_sheet.tracks[0].isrc));
553         cuesheet->data.cue_sheet.tracks[0].type = 0;
554         cuesheet->data.cue_sheet.tracks[0].pre_emphasis = 1;
555         cuesheet->data.cue_sheet.tracks[0].num_indices = 2;
556         cuesheet->data.cue_sheet.tracks[0].indices = (FLAC__StreamMetadata_CueSheet_Index*)malloc_or_die_(cuesheet->data.cue_sheet.tracks[0].num_indices * sizeof(FLAC__StreamMetadata_CueSheet_Index));
557         cuesheet->data.cue_sheet.tracks[0].indices[0].offset = 0;
558         cuesheet->data.cue_sheet.tracks[0].indices[0].number = 0;
559         cuesheet->data.cue_sheet.tracks[0].indices[1].offset = 123 * 588;
560         cuesheet->data.cue_sheet.tracks[0].indices[1].number = 1;
561         cuesheet->data.cue_sheet.tracks[1].offset = 1234 * 588;
562         cuesheet->data.cue_sheet.tracks[1].number = 2;
563         memcpy(cuesheet->data.cue_sheet.tracks[1].isrc, "ACBDE7654321", sizeof(cuesheet->data.cue_sheet.tracks[1].isrc));
564         cuesheet->data.cue_sheet.tracks[1].type = 1;
565         cuesheet->data.cue_sheet.tracks[1].pre_emphasis = 0;
566         cuesheet->data.cue_sheet.tracks[1].num_indices = 1;
567         cuesheet->data.cue_sheet.tracks[1].indices = (FLAC__StreamMetadata_CueSheet_Index*)malloc_or_die_(cuesheet->data.cue_sheet.tracks[1].num_indices * sizeof(FLAC__StreamMetadata_CueSheet_Index));
568         cuesheet->data.cue_sheet.tracks[1].indices[0].offset = 0;
569         cuesheet->data.cue_sheet.tracks[1].indices[0].number = 1;
570         cuesheet->data.cue_sheet.tracks[2].offset = 12345 * 588;
571         cuesheet->data.cue_sheet.tracks[2].number = 170;
572         cuesheet->data.cue_sheet.tracks[2].num_indices = 0;
573
574         picture->is_last = false;
575         picture->type = FLAC__METADATA_TYPE_PICTURE;
576         picture->length =
577                 (
578                         FLAC__STREAM_METADATA_PICTURE_TYPE_LEN +
579                         FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN + /* will add the length for the string later */
580                         FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN + /* will add the length for the string later */
581                         FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN +
582                         FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN +
583                         FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN +
584                         FLAC__STREAM_METADATA_PICTURE_COLORS_LEN +
585                         FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN /* will add the length for the data later */
586                 ) / 8
587         ;
588         picture->data.picture.type = FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER;
589         picture->data.picture.mime_type = strdup_or_die_("image/jpeg");
590         picture->length += strlen(picture->data.picture.mime_type);
591         picture->data.picture.description = (FLAC__byte*)strdup_or_die_("desc");
592         picture->length += strlen((const char *)picture->data.picture.description);
593         picture->data.picture.width = 300;
594         picture->data.picture.height = 300;
595         picture->data.picture.depth = 24;
596         picture->data.picture.colors = 0;
597         picture->data.picture.data = (FLAC__byte*)strdup_or_die_("SOMEJPEGDATA");
598         picture->data.picture.data_length = strlen((const char *)picture->data.picture.data);
599         picture->length += picture->data.picture.data_length;
600
601         unknown->is_last = true;
602         unknown->type = 126;
603         unknown->length = 8;
604         unknown->data.unknown.data = (FLAC__byte*)malloc_or_die_(unknown->length);
605         memcpy(unknown->data.unknown.data, "\xfe\xdc\xba\x98\xf0\xe1\xd2\xc3", unknown->length);
606 }
607
608 void mutils__free_metadata_blocks(
609         FLAC__StreamMetadata *streaminfo,
610         FLAC__StreamMetadata *padding,
611         FLAC__StreamMetadata *seektable,
612         FLAC__StreamMetadata *application1,
613         FLAC__StreamMetadata *application2,
614         FLAC__StreamMetadata *vorbiscomment,
615         FLAC__StreamMetadata *cuesheet,
616         FLAC__StreamMetadata *picture,
617         FLAC__StreamMetadata *unknown
618 )
619 {
620         (void)streaminfo, (void)padding, (void)application2;
621         free(seektable->data.seek_table.points);
622         free(application1->data.application.data);
623         free(vorbiscomment->data.vorbis_comment.vendor_string.entry);
624         free(vorbiscomment->data.vorbis_comment.comments[0].entry);
625         free(vorbiscomment->data.vorbis_comment.comments);
626         free(cuesheet->data.cue_sheet.tracks[0].indices);
627         free(cuesheet->data.cue_sheet.tracks[1].indices);
628         free(cuesheet->data.cue_sheet.tracks);
629         free(picture->data.picture.mime_type);
630         free(picture->data.picture.description);
631         free(picture->data.picture.data);
632         free(unknown->data.unknown.data);
633 }