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