change type val for UNKNOWN metadata block from 127 (now reserved) to 126
[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_unknown(const FLAC__StreamMetadata_Unknown *block, const FLAC__StreamMetadata_Unknown *blockcopy, unsigned block_length)
293 {
294         if(0 == block->data || 0 == blockcopy->data) {
295                 if(block->data != blockcopy->data) {
296                         printf("FAILED, data mismatch (%s's data pointer is null)\n", 0==block->data?"original":"copy");
297                         return false;
298                 }
299                 else if(block_length > 0) {
300                         printf("FAILED, data pointer is null but block length is not 0\n");
301                         return false;
302                 }
303         }
304         else {
305                 if(block_length == 0) {
306                         printf("FAILED, data pointer is not null but block length is 0\n");
307                         return false;
308                 }
309                 else if(0 != memcmp(blockcopy->data, block->data, block_length)) {
310                         printf("FAILED, data mismatch\n");
311                         return false;
312                 }
313         }
314         return true;
315 }
316
317 FLAC__bool mutils__compare_block(const FLAC__StreamMetadata *block, const FLAC__StreamMetadata *blockcopy)
318 {
319         if(blockcopy->type != block->type) {
320                 printf("FAILED, type mismatch, expected %s, got %s\n", FLAC__MetadataTypeString[block->type], FLAC__MetadataTypeString[blockcopy->type]);
321                 return false;
322         }
323         if(blockcopy->is_last != block->is_last) {
324                 printf("FAILED, is_last mismatch, expected %u, got %u\n", (unsigned)block->is_last, (unsigned)blockcopy->is_last);
325                 return false;
326         }
327         if(blockcopy->length != block->length) {
328                 printf("FAILED, length mismatch, expected %u, got %u\n", block->length, blockcopy->length);
329                 return false;
330         }
331         switch(block->type) {
332                 case FLAC__METADATA_TYPE_STREAMINFO:
333                         return mutils__compare_block_data_streaminfo(&block->data.stream_info, &blockcopy->data.stream_info);
334                 case FLAC__METADATA_TYPE_PADDING:
335                         return mutils__compare_block_data_padding(&block->data.padding, &blockcopy->data.padding, block->length);
336                 case FLAC__METADATA_TYPE_APPLICATION:
337                         return mutils__compare_block_data_application(&block->data.application, &blockcopy->data.application, block->length);
338                 case FLAC__METADATA_TYPE_SEEKTABLE:
339                         return mutils__compare_block_data_seektable(&block->data.seek_table, &blockcopy->data.seek_table);
340                 case FLAC__METADATA_TYPE_VORBIS_COMMENT:
341                         return mutils__compare_block_data_vorbiscomment(&block->data.vorbis_comment, &blockcopy->data.vorbis_comment);
342                 case FLAC__METADATA_TYPE_CUESHEET:
343                         return mutils__compare_block_data_cuesheet(&block->data.cue_sheet, &blockcopy->data.cue_sheet);
344                 default:
345                         return mutils__compare_block_data_unknown(&block->data.unknown, &blockcopy->data.unknown, block->length);
346         }
347 }
348 static void *malloc_or_die_(size_t size)
349 {
350         void *x = malloc(size);
351         if(0 == x) {
352                 fprintf(stderr, "ERROR: out of memory allocating %u bytes\n", (unsigned)size);
353                 exit(1);
354         }
355         return x;
356 }
357
358 static void *calloc_or_die_(size_t n, size_t size)
359 {
360         void *x = calloc(n, size);
361         if(0 == x) {
362                 fprintf(stderr, "ERROR: out of memory allocating %u bytes\n", (unsigned)n * (unsigned)size);
363                 exit(1);
364         }
365         return x;
366 }
367
368 void mutils__init_metadata_blocks(
369         FLAC__StreamMetadata *streaminfo,
370         FLAC__StreamMetadata *padding,
371         FLAC__StreamMetadata *seektable,
372         FLAC__StreamMetadata *application1,
373         FLAC__StreamMetadata *application2,
374         FLAC__StreamMetadata *vorbiscomment,
375         FLAC__StreamMetadata *cuesheet,
376         FLAC__StreamMetadata *unknown
377 )
378 {
379         /*
380                 most of the actual numbers and data in the blocks don't matter,
381                 we just want to make sure the decoder parses them correctly
382
383                 remember, the metadata interface gets tested after the decoders,
384                 so we do all the metadata manipulation here without it.
385         */
386
387         /* min/max_framesize and md5sum don't get written at first, so we have to leave them 0 */
388         streaminfo->is_last = false;
389         streaminfo->type = FLAC__METADATA_TYPE_STREAMINFO;
390         streaminfo->length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
391         streaminfo->data.stream_info.min_blocksize = 576;
392         streaminfo->data.stream_info.max_blocksize = 576;
393         streaminfo->data.stream_info.min_framesize = 0;
394         streaminfo->data.stream_info.max_framesize = 0;
395         streaminfo->data.stream_info.sample_rate = 44100;
396         streaminfo->data.stream_info.channels = 1;
397         streaminfo->data.stream_info.bits_per_sample = 8;
398         streaminfo->data.stream_info.total_samples = 0;
399         memset(streaminfo->data.stream_info.md5sum, 0, 16);
400
401         padding->is_last = false;
402         padding->type = FLAC__METADATA_TYPE_PADDING;
403         padding->length = 1234;
404
405         seektable->is_last = false;
406         seektable->type = FLAC__METADATA_TYPE_SEEKTABLE;
407         seektable->data.seek_table.num_points = 2;
408         seektable->length = seektable->data.seek_table.num_points * FLAC__STREAM_METADATA_SEEKPOINT_LENGTH;
409         seektable->data.seek_table.points = (FLAC__StreamMetadata_SeekPoint*)malloc_or_die_(seektable->data.seek_table.num_points * sizeof(FLAC__StreamMetadata_SeekPoint));
410         seektable->data.seek_table.points[0].sample_number = 0;
411         seektable->data.seek_table.points[0].stream_offset = 0;
412         seektable->data.seek_table.points[0].frame_samples = streaminfo->data.stream_info.min_blocksize;
413         seektable->data.seek_table.points[1].sample_number = FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER;
414         seektable->data.seek_table.points[1].stream_offset = 1000;
415         seektable->data.seek_table.points[1].frame_samples = streaminfo->data.stream_info.min_blocksize;
416
417         application1->is_last = false;
418         application1->type = FLAC__METADATA_TYPE_APPLICATION;
419         application1->length = 8;
420         memcpy(application1->data.application.id, "\xfe\xdc\xba\x98", 4);
421         application1->data.application.data = (FLAC__byte*)malloc_or_die_(4);
422         memcpy(application1->data.application.data, "\xf0\xe1\xd2\xc3", 4);
423
424         application2->is_last = false;
425         application2->type = FLAC__METADATA_TYPE_APPLICATION;
426         application2->length = 4;
427         memcpy(application2->data.application.id, "\x76\x54\x32\x10", 4);
428         application2->data.application.data = 0;
429
430         {
431                 const unsigned vendor_string_length = (unsigned)strlen(FLAC__VENDOR_STRING);
432                 vorbiscomment->is_last = false;
433                 vorbiscomment->type = FLAC__METADATA_TYPE_VORBIS_COMMENT;
434                 vorbiscomment->length = (4 + vendor_string_length) + 4 + (4 + 5) + (4 + 0);
435                 vorbiscomment->data.vorbis_comment.vendor_string.length = vendor_string_length;
436                 vorbiscomment->data.vorbis_comment.vendor_string.entry = (FLAC__byte*)malloc_or_die_(vendor_string_length+1);
437                 memcpy(vorbiscomment->data.vorbis_comment.vendor_string.entry, FLAC__VENDOR_STRING, vendor_string_length+1);
438                 vorbiscomment->data.vorbis_comment.num_comments = 2;
439                 vorbiscomment->data.vorbis_comment.comments = (FLAC__StreamMetadata_VorbisComment_Entry*)malloc_or_die_(vorbiscomment->data.vorbis_comment.num_comments * sizeof(FLAC__StreamMetadata_VorbisComment_Entry));
440                 vorbiscomment->data.vorbis_comment.comments[0].length = 5;
441                 vorbiscomment->data.vorbis_comment.comments[0].entry = (FLAC__byte*)malloc_or_die_(5+1);
442                 memcpy(vorbiscomment->data.vorbis_comment.comments[0].entry, "ab=cd", 5+1);
443                 vorbiscomment->data.vorbis_comment.comments[1].length = 0;
444                 vorbiscomment->data.vorbis_comment.comments[1].entry = 0;
445         }
446
447         cuesheet->is_last = false;
448         cuesheet->type = FLAC__METADATA_TYPE_CUESHEET;
449         cuesheet->length =
450                 /* cuesheet guts */
451                 (
452                         FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN +
453                         FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN +
454                         FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN +
455                         FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN +
456                         FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN
457                 ) / 8 +
458                 /* 2 tracks */
459                 3 * (
460                         FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN +
461                         FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN +
462                         FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN +
463                         FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN +
464                         FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN +
465                         FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN +
466                         FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN
467                 ) / 8 +
468                 /* 3 index points */
469                 3 * (
470                         FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN +
471                         FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN +
472                         FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN
473                 ) / 8
474         ;
475         memset(cuesheet->data.cue_sheet.media_catalog_number, 0, sizeof(cuesheet->data.cue_sheet.media_catalog_number));
476         cuesheet->data.cue_sheet.media_catalog_number[0] = 'j';
477         cuesheet->data.cue_sheet.media_catalog_number[1] = 'C';
478         cuesheet->data.cue_sheet.lead_in = 2 * 44100;
479         cuesheet->data.cue_sheet.is_cd = true;
480         cuesheet->data.cue_sheet.num_tracks = 3;
481         cuesheet->data.cue_sheet.tracks = (FLAC__StreamMetadata_CueSheet_Track*)calloc_or_die_(cuesheet->data.cue_sheet.num_tracks, sizeof(FLAC__StreamMetadata_CueSheet_Track));
482         cuesheet->data.cue_sheet.tracks[0].offset = 0;
483         cuesheet->data.cue_sheet.tracks[0].number = 1;
484         memcpy(cuesheet->data.cue_sheet.tracks[0].isrc, "ACBDE1234567", sizeof(cuesheet->data.cue_sheet.tracks[0].isrc));
485         cuesheet->data.cue_sheet.tracks[0].type = 0;
486         cuesheet->data.cue_sheet.tracks[0].pre_emphasis = 1;
487         cuesheet->data.cue_sheet.tracks[0].num_indices = 2;
488         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));
489         cuesheet->data.cue_sheet.tracks[0].indices[0].offset = 0;
490         cuesheet->data.cue_sheet.tracks[0].indices[0].number = 0;
491         cuesheet->data.cue_sheet.tracks[0].indices[1].offset = 123 * 588;
492         cuesheet->data.cue_sheet.tracks[0].indices[1].number = 1;
493         cuesheet->data.cue_sheet.tracks[1].offset = 1234 * 588;
494         cuesheet->data.cue_sheet.tracks[1].number = 2;
495         memcpy(cuesheet->data.cue_sheet.tracks[1].isrc, "ACBDE7654321", sizeof(cuesheet->data.cue_sheet.tracks[1].isrc));
496         cuesheet->data.cue_sheet.tracks[1].type = 1;
497         cuesheet->data.cue_sheet.tracks[1].pre_emphasis = 0;
498         cuesheet->data.cue_sheet.tracks[1].num_indices = 1;
499         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));
500         cuesheet->data.cue_sheet.tracks[1].indices[0].offset = 0;
501         cuesheet->data.cue_sheet.tracks[1].indices[0].number = 1;
502         cuesheet->data.cue_sheet.tracks[2].offset = 12345 * 588;
503         cuesheet->data.cue_sheet.tracks[2].number = 170;
504         cuesheet->data.cue_sheet.tracks[2].num_indices = 0;
505
506         unknown->is_last = true;
507         unknown->type = 126;
508         unknown->length = 8;
509         unknown->data.unknown.data = (FLAC__byte*)malloc_or_die_(unknown->length);
510         memcpy(unknown->data.unknown.data, "\xfe\xdc\xba\x98\xf0\xe1\xd2\xc3", unknown->length);
511 }
512
513 void mutils__free_metadata_blocks(
514         FLAC__StreamMetadata *streaminfo,
515         FLAC__StreamMetadata *padding,
516         FLAC__StreamMetadata *seektable,
517         FLAC__StreamMetadata *application1,
518         FLAC__StreamMetadata *application2,
519         FLAC__StreamMetadata *vorbiscomment,
520         FLAC__StreamMetadata *cuesheet,
521         FLAC__StreamMetadata *unknown
522 )
523 {
524         (void)streaminfo, (void)padding, (void)application2;
525         free(seektable->data.seek_table.points);
526         free(application1->data.application.data);
527         free(vorbiscomment->data.vorbis_comment.vendor_string.entry);
528         free(vorbiscomment->data.vorbis_comment.comments[0].entry);
529         free(vorbiscomment->data.vorbis_comment.comments);
530         free(cuesheet->data.cue_sheet.tracks[0].indices);
531         free(cuesheet->data.cue_sheet.tracks[1].indices);
532         free(cuesheet->data.cue_sheet.tracks);
533         free(unknown->data.unknown.data);
534 }