add support for new PICTURE metadata block
[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->data_length != block->data_length) {
332                 printf("FAILED, data_length mismatch, expected %u, got %u\n", block->data_length, blockcopy->data_length);
333                 return false;
334         }
335         if(memcmp(blockcopy->data, block->data, block->data_length)) {
336                 printf("FAILED, data mismatch\n");
337                 return false;
338         }
339         return true;
340 }
341
342 FLAC__bool mutils__compare_block_data_unknown(const FLAC__StreamMetadata_Unknown *block, const FLAC__StreamMetadata_Unknown *blockcopy, unsigned block_length)
343 {
344         if(0 == block->data || 0 == blockcopy->data) {
345                 if(block->data != blockcopy->data) {
346                         printf("FAILED, data mismatch (%s's data pointer is null)\n", 0==block->data?"original":"copy");
347                         return false;
348                 }
349                 else if(block_length > 0) {
350                         printf("FAILED, data pointer is null but block length is not 0\n");
351                         return false;
352                 }
353         }
354         else {
355                 if(block_length == 0) {
356                         printf("FAILED, data pointer is not null but block length is 0\n");
357                         return false;
358                 }
359                 else if(0 != memcmp(blockcopy->data, block->data, block_length)) {
360                         printf("FAILED, data mismatch\n");
361                         return false;
362                 }
363         }
364         return true;
365 }
366
367 FLAC__bool mutils__compare_block(const FLAC__StreamMetadata *block, const FLAC__StreamMetadata *blockcopy)
368 {
369         if(blockcopy->type != block->type) {
370                 printf("FAILED, type mismatch, expected %s, got %s\n", FLAC__MetadataTypeString[block->type], FLAC__MetadataTypeString[blockcopy->type]);
371                 return false;
372         }
373         if(blockcopy->is_last != block->is_last) {
374                 printf("FAILED, is_last mismatch, expected %u, got %u\n", (unsigned)block->is_last, (unsigned)blockcopy->is_last);
375                 return false;
376         }
377         if(blockcopy->length != block->length) {
378                 printf("FAILED, length mismatch, expected %u, got %u\n", block->length, blockcopy->length);
379                 return false;
380         }
381         switch(block->type) {
382                 case FLAC__METADATA_TYPE_STREAMINFO:
383                         return mutils__compare_block_data_streaminfo(&block->data.stream_info, &blockcopy->data.stream_info);
384                 case FLAC__METADATA_TYPE_PADDING:
385                         return mutils__compare_block_data_padding(&block->data.padding, &blockcopy->data.padding, block->length);
386                 case FLAC__METADATA_TYPE_APPLICATION:
387                         return mutils__compare_block_data_application(&block->data.application, &blockcopy->data.application, block->length);
388                 case FLAC__METADATA_TYPE_SEEKTABLE:
389                         return mutils__compare_block_data_seektable(&block->data.seek_table, &blockcopy->data.seek_table);
390                 case FLAC__METADATA_TYPE_VORBIS_COMMENT:
391                         return mutils__compare_block_data_vorbiscomment(&block->data.vorbis_comment, &blockcopy->data.vorbis_comment);
392                 case FLAC__METADATA_TYPE_CUESHEET:
393                         return mutils__compare_block_data_cuesheet(&block->data.cue_sheet, &blockcopy->data.cue_sheet);
394                 case FLAC__METADATA_TYPE_PICTURE:
395                         return mutils__compare_block_data_picture(&block->data.picture, &blockcopy->data.picture);
396                 default:
397                         return mutils__compare_block_data_unknown(&block->data.unknown, &blockcopy->data.unknown, block->length);
398         }
399 }
400
401 static void *malloc_or_die_(size_t size)
402 {
403         void *x = malloc(size);
404         if(0 == x) {
405                 fprintf(stderr, "ERROR: out of memory allocating %u bytes\n", (unsigned)size);
406                 exit(1);
407         }
408         return x;
409 }
410
411 static void *calloc_or_die_(size_t n, size_t size)
412 {
413         void *x = calloc(n, size);
414         if(0 == x) {
415                 fprintf(stderr, "ERROR: out of memory allocating %u bytes\n", (unsigned)n * (unsigned)size);
416                 exit(1);
417         }
418         return x;
419 }
420
421 static char *strdup_or_die_(const char *s)
422 {
423         char *x = strdup(s);
424         if(0 == x) {
425                 fprintf(stderr, "ERROR: out of memory copying string \"%s\"\n", s);
426                 exit(1);
427         }
428         return x;
429 }
430
431 void mutils__init_metadata_blocks(
432         FLAC__StreamMetadata *streaminfo,
433         FLAC__StreamMetadata *padding,
434         FLAC__StreamMetadata *seektable,
435         FLAC__StreamMetadata *application1,
436         FLAC__StreamMetadata *application2,
437         FLAC__StreamMetadata *vorbiscomment,
438         FLAC__StreamMetadata *cuesheet,
439         FLAC__StreamMetadata *picture,
440         FLAC__StreamMetadata *unknown
441 )
442 {
443         /*
444                 most of the actual numbers and data in the blocks don't matter,
445                 we just want to make sure the decoder parses them correctly
446
447                 remember, the metadata interface gets tested after the decoders,
448                 so we do all the metadata manipulation here without it.
449         */
450
451         /* min/max_framesize and md5sum don't get written at first, so we have to leave them 0 */
452         streaminfo->is_last = false;
453         streaminfo->type = FLAC__METADATA_TYPE_STREAMINFO;
454         streaminfo->length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
455         streaminfo->data.stream_info.min_blocksize = 576;
456         streaminfo->data.stream_info.max_blocksize = 576;
457         streaminfo->data.stream_info.min_framesize = 0;
458         streaminfo->data.stream_info.max_framesize = 0;
459         streaminfo->data.stream_info.sample_rate = 44100;
460         streaminfo->data.stream_info.channels = 1;
461         streaminfo->data.stream_info.bits_per_sample = 8;
462         streaminfo->data.stream_info.total_samples = 0;
463         memset(streaminfo->data.stream_info.md5sum, 0, 16);
464
465         padding->is_last = false;
466         padding->type = FLAC__METADATA_TYPE_PADDING;
467         padding->length = 1234;
468
469         seektable->is_last = false;
470         seektable->type = FLAC__METADATA_TYPE_SEEKTABLE;
471         seektable->data.seek_table.num_points = 2;
472         seektable->length = seektable->data.seek_table.num_points * FLAC__STREAM_METADATA_SEEKPOINT_LENGTH;
473         seektable->data.seek_table.points = (FLAC__StreamMetadata_SeekPoint*)malloc_or_die_(seektable->data.seek_table.num_points * sizeof(FLAC__StreamMetadata_SeekPoint));
474         seektable->data.seek_table.points[0].sample_number = 0;
475         seektable->data.seek_table.points[0].stream_offset = 0;
476         seektable->data.seek_table.points[0].frame_samples = streaminfo->data.stream_info.min_blocksize;
477         seektable->data.seek_table.points[1].sample_number = FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER;
478         seektable->data.seek_table.points[1].stream_offset = 1000;
479         seektable->data.seek_table.points[1].frame_samples = streaminfo->data.stream_info.min_blocksize;
480
481         application1->is_last = false;
482         application1->type = FLAC__METADATA_TYPE_APPLICATION;
483         application1->length = 8;
484         memcpy(application1->data.application.id, "\xfe\xdc\xba\x98", 4);
485         application1->data.application.data = (FLAC__byte*)malloc_or_die_(4);
486         memcpy(application1->data.application.data, "\xf0\xe1\xd2\xc3", 4);
487
488         application2->is_last = false;
489         application2->type = FLAC__METADATA_TYPE_APPLICATION;
490         application2->length = 4;
491         memcpy(application2->data.application.id, "\x76\x54\x32\x10", 4);
492         application2->data.application.data = 0;
493
494         {
495                 const unsigned vendor_string_length = (unsigned)strlen(FLAC__VENDOR_STRING);
496                 vorbiscomment->is_last = false;
497                 vorbiscomment->type = FLAC__METADATA_TYPE_VORBIS_COMMENT;
498                 vorbiscomment->length = (4 + vendor_string_length) + 4 + (4 + 5) + (4 + 0);
499                 vorbiscomment->data.vorbis_comment.vendor_string.length = vendor_string_length;
500                 vorbiscomment->data.vorbis_comment.vendor_string.entry = (FLAC__byte*)malloc_or_die_(vendor_string_length+1);
501                 memcpy(vorbiscomment->data.vorbis_comment.vendor_string.entry, FLAC__VENDOR_STRING, vendor_string_length+1);
502                 vorbiscomment->data.vorbis_comment.num_comments = 2;
503                 vorbiscomment->data.vorbis_comment.comments = (FLAC__StreamMetadata_VorbisComment_Entry*)malloc_or_die_(vorbiscomment->data.vorbis_comment.num_comments * sizeof(FLAC__StreamMetadata_VorbisComment_Entry));
504                 vorbiscomment->data.vorbis_comment.comments[0].length = 5;
505                 vorbiscomment->data.vorbis_comment.comments[0].entry = (FLAC__byte*)malloc_or_die_(5+1);
506                 memcpy(vorbiscomment->data.vorbis_comment.comments[0].entry, "ab=cd", 5+1);
507                 vorbiscomment->data.vorbis_comment.comments[1].length = 0;
508                 vorbiscomment->data.vorbis_comment.comments[1].entry = 0;
509         }
510
511         cuesheet->is_last = false;
512         cuesheet->type = FLAC__METADATA_TYPE_CUESHEET;
513         cuesheet->length =
514                 /* cuesheet guts */
515                 (
516                         FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN +
517                         FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN +
518                         FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN +
519                         FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN +
520                         FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN
521                 ) / 8 +
522                 /* 2 tracks */
523                 3 * (
524                         FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN +
525                         FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN +
526                         FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN +
527                         FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN +
528                         FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN +
529                         FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN +
530                         FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN
531                 ) / 8 +
532                 /* 3 index points */
533                 3 * (
534                         FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN +
535                         FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN +
536                         FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN
537                 ) / 8
538         ;
539         memset(cuesheet->data.cue_sheet.media_catalog_number, 0, sizeof(cuesheet->data.cue_sheet.media_catalog_number));
540         cuesheet->data.cue_sheet.media_catalog_number[0] = 'j';
541         cuesheet->data.cue_sheet.media_catalog_number[1] = 'C';
542         cuesheet->data.cue_sheet.lead_in = 2 * 44100;
543         cuesheet->data.cue_sheet.is_cd = true;
544         cuesheet->data.cue_sheet.num_tracks = 3;
545         cuesheet->data.cue_sheet.tracks = (FLAC__StreamMetadata_CueSheet_Track*)calloc_or_die_(cuesheet->data.cue_sheet.num_tracks, sizeof(FLAC__StreamMetadata_CueSheet_Track));
546         cuesheet->data.cue_sheet.tracks[0].offset = 0;
547         cuesheet->data.cue_sheet.tracks[0].number = 1;
548         memcpy(cuesheet->data.cue_sheet.tracks[0].isrc, "ACBDE1234567", sizeof(cuesheet->data.cue_sheet.tracks[0].isrc));
549         cuesheet->data.cue_sheet.tracks[0].type = 0;
550         cuesheet->data.cue_sheet.tracks[0].pre_emphasis = 1;
551         cuesheet->data.cue_sheet.tracks[0].num_indices = 2;
552         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));
553         cuesheet->data.cue_sheet.tracks[0].indices[0].offset = 0;
554         cuesheet->data.cue_sheet.tracks[0].indices[0].number = 0;
555         cuesheet->data.cue_sheet.tracks[0].indices[1].offset = 123 * 588;
556         cuesheet->data.cue_sheet.tracks[0].indices[1].number = 1;
557         cuesheet->data.cue_sheet.tracks[1].offset = 1234 * 588;
558         cuesheet->data.cue_sheet.tracks[1].number = 2;
559         memcpy(cuesheet->data.cue_sheet.tracks[1].isrc, "ACBDE7654321", sizeof(cuesheet->data.cue_sheet.tracks[1].isrc));
560         cuesheet->data.cue_sheet.tracks[1].type = 1;
561         cuesheet->data.cue_sheet.tracks[1].pre_emphasis = 0;
562         cuesheet->data.cue_sheet.tracks[1].num_indices = 1;
563         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));
564         cuesheet->data.cue_sheet.tracks[1].indices[0].offset = 0;
565         cuesheet->data.cue_sheet.tracks[1].indices[0].number = 1;
566         cuesheet->data.cue_sheet.tracks[2].offset = 12345 * 588;
567         cuesheet->data.cue_sheet.tracks[2].number = 170;
568         cuesheet->data.cue_sheet.tracks[2].num_indices = 0;
569
570         picture->is_last = false;
571         picture->type = FLAC__METADATA_TYPE_PICTURE;
572         picture->length =
573                 (
574                         FLAC__STREAM_METADATA_PICTURE_TYPE_LEN +
575                         FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN + /* will add the length for the string later */
576                         FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN + /* will add the length for the string later */
577                         FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN +
578                         FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN +
579                         FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN +
580                         FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN /* will add the length for the data later */
581                 ) / 8
582         ;
583         picture->data.picture.type = FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER;
584         picture->data.picture.mime_type = strdup_or_die_("image/jpeg");
585         picture->length += strlen(picture->data.picture.mime_type);
586         picture->data.picture.description = (FLAC__byte*)strdup_or_die_("desc");
587         picture->length += strlen((const char *)picture->data.picture.description);
588         picture->data.picture.width = 300;
589         picture->data.picture.height = 300;
590         picture->data.picture.depth = 24;
591         picture->data.picture.data = (FLAC__byte*)strdup_or_die_("SOMEJPEGDATA");
592         picture->data.picture.data_length = strlen((const char *)picture->data.picture.data);
593         picture->length += picture->data.picture.data_length;
594
595         unknown->is_last = true;
596         unknown->type = 126;
597         unknown->length = 8;
598         unknown->data.unknown.data = (FLAC__byte*)malloc_or_die_(unknown->length);
599         memcpy(unknown->data.unknown.data, "\xfe\xdc\xba\x98\xf0\xe1\xd2\xc3", unknown->length);
600 }
601
602 void mutils__free_metadata_blocks(
603         FLAC__StreamMetadata *streaminfo,
604         FLAC__StreamMetadata *padding,
605         FLAC__StreamMetadata *seektable,
606         FLAC__StreamMetadata *application1,
607         FLAC__StreamMetadata *application2,
608         FLAC__StreamMetadata *vorbiscomment,
609         FLAC__StreamMetadata *cuesheet,
610         FLAC__StreamMetadata *picture,
611         FLAC__StreamMetadata *unknown
612 )
613 {
614         (void)streaminfo, (void)padding, (void)application2;
615         free(seektable->data.seek_table.points);
616         free(application1->data.application.data);
617         free(vorbiscomment->data.vorbis_comment.vendor_string.entry);
618         free(vorbiscomment->data.vorbis_comment.comments[0].entry);
619         free(vorbiscomment->data.vorbis_comment.comments);
620         free(cuesheet->data.cue_sheet.tracks[0].indices);
621         free(cuesheet->data.cue_sheet.tracks[1].indices);
622         free(cuesheet->data.cue_sheet.tracks);
623         free(picture->data.picture.mime_type);
624         free(picture->data.picture.description);
625         free(picture->data.picture.data);
626         free(unknown->data.unknown.data);
627 }