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