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