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