1 /*******************************************************************************
2 lqt_codecfile.c
3
4 libquicktime - A library for reading and writing quicktime/avi/mp4 files.
5 http://libquicktime.sourceforge.net
6
7 Copyright (C) 2002 Heroine Virtual Ltd.
8 Copyright (C) 2002-2011 Members of the libquicktime project.
9
10 Modified by Napoleon E. Cornejo
11 May 4, 2007, San Salvador, El Salvador
12 - Validated user home directory in create_filename()
13
14 This library is free software; you can redistribute it and/or modify it under
15 the terms of the GNU Lesser General Public License as published by the Free
16 Software Foundation; either version 2.1 of the License, or (at your option)
17 any later version.
18
19 This library is distributed in the hope that it will be useful, but WITHOUT
20 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
21 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
22 details.
23
24 You should have received a copy of the GNU Lesser General Public License along
25 with this library; if not, write to the Free Software Foundation, Inc., 51
26 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27 *******************************************************************************/
28
29 /*
30 * Codec file handling
31 */
32
33 #include "lqt_private.h"
34 #include "lqt_codecinfo_private.h"
35 #include <unistd.h>
36 #include <stdlib.h>
37 #include <stdio.h>
38 #include <string.h>
39 #include <limits.h>
40
41 #define LOG_DOMAIN "codecfile"
42
43 /*
44 * The keywords are defined globaly, so they are automatically
45 * the same in reading and writing functions
46 */
47
48 static const char * begin_codec_key = "BeginCodec: ";
49 static const char * end_codec_key = "EndCodec";
50
51 /*
52 * Start string for parameter definition:
53 * These 2 strings (for en- and decoding MUST have the same length)
54 */
55
56 static const char * begin_parameter_e_key = "BeginParameterE: ";
57 static const char * begin_parameter_d_key = "BeginParameterD: ";
58
59 static const char * end_parameter_key = "EndParameter";
60
61 static const char * long_name_key = "LongName: ";
62 static const char * description_key = "Description: ";
63
64 static const char * type_key = "Type: ";
65
66 /* Types for codecs */
67
68 static const char * type_audio = "Audio";
69 static const char * type_video = "Video";
70
71
72 /* Codec direction */
73
74 static const char * direction_key = "Direction: ";
75 static const char * direction_encode = "Encode";
76 static const char * direction_decode = "Decode";
77 static const char * direction_both = "Both";
78
79 static const char * num_fourccs_key = "NumFourccs: ";
80 static const char * fourccs_key = "Fourccs: ";
81
82 static const char * num_wav_ids_key = "NumWavIds: ";
83 static const char * wav_ids_key = "WavIds: ";
84
85 static const char * compatibility_key = "Compatibility: ";
86 static const char * compression_id_key = "CompressionID: ";
87
88 /* Module filename and module index */
89
90 static const char * module_filename_key = "ModuleFilename: ";
91 static const char * module_index_key = "ModuleIndex: ";
92 static const char * module_file_time_key = "FileTime: ";
93
94 static const char * gettext_domain_key = "GettextDomain";
95 static const char * gettext_directory_key = "GettextDirectory";
96
97
98 /* Types for parameters */
99
100 static const char * type_int = "Integer";
101 static const char * type_float = "Float";
102 static const char * type_string = "String";
103 static const char * type_stringlist = "Stringlist";
104 static const char * type_section = "Section";
105
106 static const char * help_string_key = "HelpString: ";
107 static const char * num_digits_key = "NumDigits";
108
109
110 static const char * num_encoding_parameters_key = "NumEncodingParameters: ";
111 static const char * num_decoding_parameters_key = "NumDecodingParameters: ";
112
113 static const char * value_key = "Value: ";
114 static const char * min_value_key = "ValueMin: ";
115 static const char * max_value_key = "ValueMax: ";
116
117 static const char * real_name_key = "RealName: ";
118
119 static const char * num_options_key = "NumOptions: ";
120 static const char * option_key = "Options: ";
121 static const char * label_key = "OptionLabels: ";
122
123 /* Encoding colormodels */
124
125 static const char *
126 num_encoding_colormodels_key = "NumEncodingColormodels: ";
127
128 static const char *
129 encoding_colormodel_key = "EncodingColormodel: ";
130
131 static const char *
132 num_image_sizes_key = "NumImageSizes: ";
133
134 static const char *
135 image_size_key = "ImageSize: ";
136
137 /* Codec order */
138
139 static const char * audio_order_key = "AudioOrder: ";
140 static const char * video_order_key = "VideoOrder: ";
141
142 #define READ_BUFFER_SIZE 2048
143
144 #define CHECK_KEYWORD(key) (!strncmp(line, key, strlen(key)))
145
create_filename()146 static char * create_filename()
147 {
148 char * filename_buffer;
149 /* Obtain the home directory */
150
151 char * fdir;
152
153 /* First look for a system-wide codec file if available. If not
154 look into users home */
155
156 fdir = getenv("LQT_CODEC_FILE");
157 if (fdir == NULL ) {
158
159 lqt_log(NULL, LQT_LOG_DEBUG, LOG_DOMAIN,
160 "no system-wide codec file. Looking in user's home.");
161
162 fdir = getenv("HOME");
163 if(!fdir)
164 return NULL;
165 filename_buffer = malloc(strlen(fdir) + 22);
166 strcpy(filename_buffer, fdir);
167 strcat(filename_buffer, "/.libquicktime_codecs");
168
169 } else
170 {
171 filename_buffer = malloc(strlen(fdir) + 1);
172 strcpy(filename_buffer, fdir);
173 }
174 return filename_buffer;
175
176 }
177
__lqt_strdup(const char * string)178 static char * __lqt_strdup(const char * string)
179 {
180 char * ret = malloc(strlen(string)+1);
181 strcpy(ret, string);
182 return ret;
183 }
184
read_parameter_value(char * pos,lqt_parameter_value_t * ret,lqt_parameter_type_t type)185 static void read_parameter_value(char * pos,
186 lqt_parameter_value_t * ret,
187 lqt_parameter_type_t type)
188 {
189 switch(type)
190 {
191 case LQT_PARAMETER_INT:
192 ret->val_int = atoi(pos);
193 break;
194 case LQT_PARAMETER_FLOAT:
195 ret->val_float = strtod(pos, (char**)0);
196 break;
197 case LQT_PARAMETER_STRING:
198 case LQT_PARAMETER_STRINGLIST:
199 ret->val_string = __lqt_strdup(pos);
200 break;
201 case LQT_PARAMETER_SECTION:
202 break;
203 }
204 }
205
convert_help_string(char * str)206 static char * convert_help_string(char * str)
207 {
208 char * ret;
209 char * src_pos, *dst_pos;
210
211 ret = malloc(strlen(str)+1);
212
213 src_pos = str;
214 dst_pos = ret;
215
216 while(*src_pos != '\0')
217 {
218 if((src_pos[0] == '\\') && (src_pos[1] == 'n'))
219 {
220 *dst_pos = '\n';
221 src_pos += 2;
222 dst_pos++;
223 }
224 else
225 {
226 *dst_pos = *src_pos;
227 src_pos++;
228 dst_pos++;
229 }
230 }
231 *dst_pos = '\0';
232 free(str);
233 return ret;
234 }
235
read_parameter_info(FILE * input,lqt_parameter_info_t * info,char * line)236 static void read_parameter_info(FILE * input,
237 lqt_parameter_info_t * info,
238 char * line)
239 {
240 char * pos;
241 int options_read = 0;
242 int labels_read = 0;
243
244 /* First, get the name */
245
246 pos = line + strlen(begin_parameter_e_key);
247 info->name = __lqt_strdup(pos);
248
249 while(1)
250 {
251 fgets(line, READ_BUFFER_SIZE-1, input);
252 if(feof(input))
253 break;
254 pos = strchr(line, '\n');
255 if(pos)
256 *pos = '\0';
257
258 /* Now, go through the syntax */
259
260 if(CHECK_KEYWORD(type_key))
261 {
262 pos = line + strlen(type_key);
263
264 if(!strcmp(pos, type_int))
265 {
266 info->type = LQT_PARAMETER_INT;
267
268 /*
269 * We set them here for the case, they are not set after
270 * (which can happen for min and max)
271 */
272
273 info->val_default.val_int = 0;
274 info->val_min.val_int = 0;
275 info->val_max.val_int = 0;
276 }
277 if(!strcmp(pos, type_float))
278 {
279 info->type = LQT_PARAMETER_FLOAT;
280
281 /*
282 * We set them here for the case, they are not set after
283 * (which can happen for min and max)
284 */
285
286 info->val_default.val_float = 0;
287 info->val_min.val_float = 0;
288 info->val_max.val_float = 0;
289 info->num_digits = 1;
290 }
291
292 /*
293 * Important: type_stringlist must be checked
294 * BEFORE type_string
295 */
296
297 else if(!strcmp(pos, type_stringlist))
298 {
299 info->type = LQT_PARAMETER_STRINGLIST;
300 info->val_default.val_string = (char*)0;
301 }
302 else if(!strcmp(pos, type_string))
303 {
304 info->type = LQT_PARAMETER_STRING;
305 info->val_default.val_string = (char*)0;
306 }
307 else if(!strcmp(pos, type_section))
308 {
309 info->type = LQT_PARAMETER_SECTION;
310 info->val_default.val_string = (char*)0;
311 }
312 }
313 else if(CHECK_KEYWORD(real_name_key))
314 {
315 pos = line + strlen(real_name_key);
316 info->real_name = __lqt_strdup(pos);
317 }
318
319 else if(CHECK_KEYWORD(value_key))
320 {
321 pos = line + strlen(value_key);
322 read_parameter_value(pos, &info->val_default, info->type);
323 }
324
325 else if(CHECK_KEYWORD(min_value_key))
326 {
327 pos = line + strlen(min_value_key);
328 if(info->type == LQT_PARAMETER_INT)
329 info->val_min.val_int = atoi(pos);
330 else if(info->type == LQT_PARAMETER_FLOAT)
331 info->val_min.val_float = strtod(pos, (char**)0);
332 }
333
334 else if(CHECK_KEYWORD(max_value_key))
335 {
336 pos = line + strlen(max_value_key);
337 if(info->type == LQT_PARAMETER_INT)
338 info->val_max.val_int = atoi(pos);
339 else if(info->type == LQT_PARAMETER_FLOAT)
340 info->val_max.val_float = strtod(pos, (char**)0);
341 }
342 else if(CHECK_KEYWORD(num_options_key))
343 {
344 pos = line + strlen(num_options_key);
345 info->num_stringlist_options = atoi(pos);
346 info->stringlist_options = calloc(info->num_stringlist_options,
347 sizeof(char*));
348 info->stringlist_labels = calloc(info->num_stringlist_options,
349 sizeof(char*));
350 }
351 else if(CHECK_KEYWORD(option_key))
352 {
353 pos = line + strlen(option_key);
354 info->stringlist_options[options_read] = __lqt_strdup(pos);
355 options_read++;
356 }
357 else if(CHECK_KEYWORD(label_key))
358 {
359 pos = line + strlen(label_key);
360 info->stringlist_labels[labels_read] = __lqt_strdup(pos);
361 labels_read++;
362 }
363 else if(CHECK_KEYWORD(help_string_key))
364 {
365 pos = line + strlen(help_string_key);
366 info->help_string = __lqt_strdup(pos);
367 info->help_string = convert_help_string(info->help_string);
368 }
369 else if(CHECK_KEYWORD(num_digits_key))
370 {
371 pos = line + strlen(num_digits_key);
372 info->num_digits = atoi(pos);
373 }
374 else if(CHECK_KEYWORD(end_parameter_key))
375 break;
376 }
377 }
378
read_codec_info(FILE * input,lqt_codec_info_t * codec,char * line)379 static void read_codec_info(FILE * input, lqt_codec_info_t * codec,
380 char * line)
381 {
382 char * pos, *rest;
383 int i;
384
385 int encoding_parameters_read = 0;
386 int decoding_parameters_read = 0;
387 int encoding_colormodels_read = 0;
388 int image_sizes_read = 0;
389
390 uint32_t tmp_fourcc;
391
392 /* First, get the name */
393
394 pos = line + strlen(begin_codec_key);
395 codec->name = __lqt_strdup(pos);
396
397 while(1)
398 {
399 fgets(line, READ_BUFFER_SIZE-1, input);
400 if(feof(input))
401 break;
402 pos = strchr(line, '\n');
403 if(pos)
404 *pos = '\0';
405
406 /* Long name */
407
408 if(CHECK_KEYWORD(long_name_key))
409 {
410 pos = line + strlen(long_name_key);
411 codec->long_name = __lqt_strdup(pos);
412 }
413
414 /* Description */
415
416 else if(CHECK_KEYWORD(description_key))
417 {
418 pos = line + strlen(description_key);
419 codec->description = __lqt_strdup(pos);
420 }
421
422 /* Type */
423
424 else if(CHECK_KEYWORD(type_key))
425 {
426 pos = line + strlen(type_key);
427 if(!strcmp(pos, type_audio))
428 codec->type = LQT_CODEC_AUDIO;
429 else if(!strcmp(pos, type_video))
430 codec->type = LQT_CODEC_VIDEO;
431 }
432
433 /* Compression ID */
434
435 else if(CHECK_KEYWORD(compression_id_key))
436 {
437 pos = line + strlen(compression_id_key);
438 codec->compression_id =
439 lqt_compression_id_from_string(pos);
440 }
441
442 /* Direction */
443
444 else if(CHECK_KEYWORD(direction_key))
445 {
446 pos = line + strlen(direction_key);
447 if(!strcmp(pos, direction_encode))
448 codec->direction = LQT_DIRECTION_ENCODE;
449 else if(!strcmp(pos, direction_decode))
450 codec->direction = LQT_DIRECTION_DECODE;
451 else if(!strcmp(pos, direction_both))
452 codec->direction = LQT_DIRECTION_BOTH;
453 }
454
455 /* Compatibility flags */
456 else if(CHECK_KEYWORD(compatibility_key))
457 {
458 pos = line + strlen(compatibility_key);
459 codec->compatibility_flags = strtoul(pos, (char**)0, 16);
460 }
461
462 /* Module filename */
463
464 else if(CHECK_KEYWORD(module_filename_key))
465 {
466 pos = line + strlen(module_filename_key);
467 codec->module_filename = __lqt_strdup(pos);
468 }
469
470 /* Gettext domain */
471
472 else if(CHECK_KEYWORD(gettext_domain_key))
473 {
474 pos = line + strlen(gettext_domain_key);
475 codec->gettext_domain = __lqt_strdup(pos);
476 }
477
478 /* Gettext directory */
479
480 else if(CHECK_KEYWORD(gettext_directory_key))
481 {
482 pos = line + strlen(gettext_directory_key);
483 codec->gettext_directory = __lqt_strdup(pos);
484 }
485
486 /* Module Index */
487
488 else if(CHECK_KEYWORD(module_index_key))
489 {
490 pos = line + strlen(module_index_key);
491 codec->module_index = atoi(pos);
492 }
493
494 /* File modification time */
495
496 else if(CHECK_KEYWORD(module_file_time_key))
497 {
498 pos = line + strlen(module_file_time_key);
499 codec->file_time = strtoul(pos, (char**)0, 10);
500 }
501
502 /* Number of Fourccs */
503
504 else if(CHECK_KEYWORD(num_fourccs_key))
505 {
506 pos = line + strlen(num_fourccs_key);
507 codec->num_fourccs = atoi(pos);
508
509 /* We allocate memory here */
510 if(codec->num_fourccs)
511 {
512 codec->fourccs = malloc(codec->num_fourccs * sizeof(char*));
513 for(i = 0; i < codec->num_fourccs; i++)
514 codec->fourccs[i] = malloc(5 * sizeof(char));
515 }
516 }
517
518 /* Fourccs */
519
520 else if(CHECK_KEYWORD(fourccs_key))
521 {
522 pos = line + strlen(fourccs_key);
523 for(i = 0; i < codec->num_fourccs; i++)
524 {
525 tmp_fourcc = strtoul(pos, &rest, 16);
526 LQT_FOURCC_2_STRING(codec->fourccs[i], tmp_fourcc);
527 if(rest == pos)
528 break;
529 pos = rest;
530 }
531 }
532
533 /* Number of wav ids */
534
535 else if(CHECK_KEYWORD(num_wav_ids_key))
536 {
537 pos = line + strlen(num_wav_ids_key);
538 codec->num_wav_ids = atoi(pos);
539
540 /* We allocate memory here */
541
542 codec->wav_ids = malloc(codec->num_wav_ids * sizeof(int));
543 }
544
545 /* Wav ids */
546
547 else if(CHECK_KEYWORD(wav_ids_key))
548 {
549 pos = line + strlen(wav_ids_key);
550 for(i = 0; i < codec->num_wav_ids; i++)
551 {
552 codec->wav_ids[i] = strtoul(pos, &rest, 16);
553 pos = rest;
554 }
555 }
556
557 /* Number of encoding colormodels */
558
559 else if(CHECK_KEYWORD(num_encoding_colormodels_key))
560 {
561 pos = line + strlen(num_encoding_colormodels_key);
562 codec->num_encoding_colormodels = atoi(pos);
563 if(codec->num_encoding_colormodels)
564 {
565 codec->encoding_colormodels =
566 malloc((codec->num_encoding_colormodels+1) *
567 sizeof(*codec->encoding_colormodels));
568 /* terminate */
569 codec->encoding_colormodels[codec->num_encoding_colormodels] =
570 LQT_COLORMODEL_NONE;
571 }
572 else
573 codec->encoding_colormodels = (int*)0;
574 }
575
576 /* Encoding colormodels */
577
578 else if(CHECK_KEYWORD(encoding_colormodel_key))
579 {
580 pos = line + strlen(encoding_colormodel_key);
581 codec->encoding_colormodels[encoding_colormodels_read] =
582 lqt_string_to_colormodel(pos);
583 encoding_colormodels_read++;
584 }
585
586 /* Number of image sizes */
587
588 else if(CHECK_KEYWORD(num_image_sizes_key))
589 {
590 pos = line + strlen(num_image_sizes_key);
591 codec->num_image_sizes = atoi(pos);
592 if(codec->num_image_sizes)
593 codec->image_sizes =
594 malloc(codec->num_image_sizes *
595 sizeof(*codec->image_sizes));
596 else
597 codec->image_sizes = NULL;
598 }
599
600 /* Image size */
601
602 else if(CHECK_KEYWORD(image_size_key))
603 {
604 pos = line + strlen(image_size_key);
605
606 sscanf(pos, "%d %d", &codec->image_sizes[image_sizes_read].width,
607 &codec->image_sizes[image_sizes_read].height);
608 image_sizes_read++;
609 }
610
611 /* Number of parameters */
612
613 else if(CHECK_KEYWORD(num_encoding_parameters_key))
614 {
615 pos = line + strlen(num_encoding_parameters_key);
616 codec->num_encoding_parameters = atoi(pos);
617 if(codec->num_encoding_parameters)
618 codec->encoding_parameters =
619 calloc(codec->num_encoding_parameters,
620 sizeof(lqt_parameter_info_t));
621 else
622 codec->encoding_parameters =
623 (lqt_parameter_info_t*)0;
624 }
625 else if(CHECK_KEYWORD(num_decoding_parameters_key))
626 {
627 pos = line + strlen(num_decoding_parameters_key);
628 codec->num_decoding_parameters = atoi(pos);
629 if(codec->num_decoding_parameters)
630 codec->decoding_parameters =
631 calloc(codec->num_decoding_parameters,
632 sizeof(lqt_parameter_info_t));
633 else
634 codec->decoding_parameters =
635 (lqt_parameter_info_t*)0;
636
637 }
638
639 /* Read parameters */
640
641 else if(CHECK_KEYWORD(begin_parameter_e_key))
642 {
643 read_parameter_info(input,
644 &codec->encoding_parameters[encoding_parameters_read],
645 line);
646 encoding_parameters_read++;
647 }
648
649 else if(CHECK_KEYWORD(begin_parameter_d_key))
650 {
651 read_parameter_info(input,
652 &codec->decoding_parameters[decoding_parameters_read],
653 line);
654 decoding_parameters_read++;
655 }
656 else if(CHECK_KEYWORD(end_codec_key))
657 break;
658 }
659
660 }
661
662
lqt_registry_read(char ** audio_order,char ** video_order)663 lqt_codec_info_t * lqt_registry_read(char ** audio_order, char ** video_order)
664 {
665 FILE * input;
666 char * line;
667 char * pos = (char*)0;
668 char * filename_buffer = create_filename();
669 lqt_codec_info_t * ret = (lqt_codec_info_t *)0;
670 lqt_codec_info_t * ret_end = (lqt_codec_info_t *)0;
671
672 if(!filename_buffer || (*filename_buffer == '\0'))
673 return NULL;
674
675 input = fopen(filename_buffer, "r");
676
677 if(!input)
678 {
679 free(filename_buffer);
680 return (lqt_codec_info_t*)0;
681 }
682
683 line = malloc(READ_BUFFER_SIZE);
684
685 while(1)
686 {
687 fgets(line, READ_BUFFER_SIZE-1, input);
688 if(feof(input))
689 break;
690 pos = strchr(line, '\n');
691 if(pos)
692 *pos = '\0';
693
694 pos = line;
695
696 /* Skip comment lines */
697
698 if(*pos == '#')
699 continue;
700
701 else if(CHECK_KEYWORD(audio_order_key))
702 {
703 if(audio_order)
704 {
705 pos += strlen(audio_order_key);
706 *audio_order = __lqt_strdup(pos);
707 }
708 continue;
709 }
710 else if(CHECK_KEYWORD(video_order_key))
711 {
712 if(video_order)
713 {
714 pos += strlen(video_order_key);
715 *video_order = __lqt_strdup(pos);
716 }
717 continue;
718 }
719
720 else if(CHECK_KEYWORD(begin_codec_key))
721 {
722 if(!ret_end)
723 {
724 ret = calloc(1, sizeof(lqt_codec_info_t));
725 ret_end = ret;
726 }
727 else
728 {
729 ret_end->next = calloc(1, sizeof(lqt_codec_info_t));
730 ret_end = ret_end->next;
731 }
732 read_codec_info(input, ret_end, pos);
733
734 ret_end->next = (lqt_codec_info_t*)0;
735 }
736 }
737
738
739 fclose(input);
740 free(filename_buffer);
741 free(line);
742 return ret;
743 }
744
write_help_string(FILE * output,char * help_string)745 static void write_help_string(FILE * output, char * help_string)
746 {
747 int i, imax;
748 fprintf(output, "%s", help_string_key);
749
750 imax = strlen(help_string);
751 for(i = 0; i < imax; i++)
752 {
753 if(help_string[i] == '\n')
754 fprintf(output, "\\n");
755 else
756 fprintf(output, "%c", help_string[i]);
757 }
758 fprintf(output, "\n");
759 }
760
write_parameter_info(FILE * output,const lqt_parameter_info_t * info,int encode)761 static void write_parameter_info(FILE * output,
762 const lqt_parameter_info_t * info,
763 int encode)
764 {
765 const char * tmp = (const char*)0;
766 int i;
767
768 fprintf(output, "%s%s\n",
769 (encode ? begin_parameter_e_key : begin_parameter_d_key),
770 info->name);
771 fprintf(output, "%s%s\n", real_name_key, info->real_name);
772 switch(info->type)
773 {
774 case LQT_PARAMETER_INT:
775 tmp = type_int;
776 break;
777 case LQT_PARAMETER_FLOAT:
778 tmp = type_float;
779 break;
780 case LQT_PARAMETER_STRING:
781 tmp = type_string;
782 break;
783 case LQT_PARAMETER_STRINGLIST:
784 tmp = type_stringlist;
785 break;
786 case LQT_PARAMETER_SECTION:
787 tmp = type_section;
788 break;
789 }
790
791 fprintf(output, "%s%s\n", type_key, tmp);
792
793 /*
794 * Print the value
795 */
796
797 switch(info->type)
798 {
799 case LQT_PARAMETER_INT:
800 fprintf(output, "%s%d\n", value_key, info->val_default.val_int);
801
802 if(info->val_min.val_int < info->val_max.val_int)
803 {
804 fprintf(output, "%s%d\n", min_value_key, info->val_min.val_int);
805 fprintf(output, "%s%d\n", max_value_key, info->val_max.val_int);
806 }
807
808 break;
809 case LQT_PARAMETER_FLOAT:
810 fprintf(output, "%s%f\n", value_key, info->val_default.val_float);
811
812 if(info->val_min.val_float < info->val_max.val_float)
813 {
814 fprintf(output, "%s%f\n", min_value_key, info->val_min.val_float);
815 fprintf(output, "%s%f\n", max_value_key, info->val_max.val_float);
816 }
817 fprintf(output, "%s%d\n", num_digits_key, info->num_digits);
818 break;
819 case LQT_PARAMETER_STRING:
820 fprintf(output, "%s%s\n", value_key, info->val_default.val_string);
821 break;
822 case LQT_PARAMETER_STRINGLIST:
823 fprintf(output, "%s%s\n", value_key, info->val_default.val_string);
824
825 /*
826 * Print options
827 */
828 fprintf(output, "%s%d\n", num_options_key, info->num_stringlist_options);
829
830 for(i = 0; i < info->num_stringlist_options; i++)
831 fprintf(output, "%s%s\n", option_key, info->stringlist_options[i]);
832 for(i = 0; i < info->num_stringlist_options; i++)
833 fprintf(output, "%s%s\n", label_key, info->stringlist_labels[i]);
834 break;
835 case LQT_PARAMETER_SECTION:
836 break;
837 }
838
839 if(info->help_string)
840 {
841 write_help_string(output, info->help_string);
842 }
843
844 fprintf(output, "%s\n", end_parameter_key);
845
846 }
847
848 /*
849 * Write codec info, return FALSE on error
850 */
851
write_codec_info(const lqt_codec_info_t * info,FILE * output)852 static int write_codec_info(const lqt_codec_info_t * info, FILE * output)
853 {
854 const char * tmp;
855
856 int i;
857
858 fprintf(output, "%s%s\n", begin_codec_key, info->name);
859 fprintf(output, "%s%s\n", long_name_key, info->long_name);
860
861 fprintf(output, "%s%s\n", description_key, info->description);
862
863 tmp = NULL;
864
865 switch(info->type)
866 {
867 case LQT_CODEC_AUDIO:
868 tmp = type_audio;
869 break;
870 case LQT_CODEC_VIDEO:
871 tmp = type_video;
872 break;
873 }
874
875 if(tmp)
876 fprintf(output, "%s%s\n", type_key, tmp);
877
878 if(info->compression_id != LQT_COMPRESSION_NONE)
879 {
880 fprintf(output, "%s%s\n", compression_id_key,
881 lqt_compression_id_to_string(info->compression_id));
882 }
883
884 switch(info->direction)
885 {
886 case LQT_DIRECTION_DECODE:
887 tmp = direction_decode;
888 break;
889 case LQT_DIRECTION_ENCODE:
890 tmp = direction_encode;
891 break;
892 case LQT_DIRECTION_BOTH:
893 tmp = direction_both;
894 break;
895 }
896
897 if(tmp)
898 fprintf(output, "%s%s\n", direction_key, tmp);
899
900 fprintf(output, "%s%08x\n", compatibility_key, info->compatibility_flags);
901
902
903 if(info->num_fourccs)
904 {
905 fprintf(output, "%s%d\n", num_fourccs_key, info->num_fourccs);
906
907 fprintf(output, "%s", fourccs_key);
908
909 for(i = 0; i < info->num_fourccs; i++)
910 fprintf(output, "0x%08X ", LQT_STRING_2_FOURCC(info->fourccs[i]));
911 fprintf(output, "\n");
912 }
913
914 if(info->num_wav_ids)
915 {
916 fprintf(output, "%s%d\n", num_wav_ids_key, info->num_wav_ids);
917 fprintf(output, "%s", wav_ids_key);
918 for(i = 0; i < info->num_wav_ids; i++)
919 fprintf(output, "0x%02X ", info->wav_ids[i]);
920 fprintf(output, "\n");
921 }
922
923 fprintf(output, "%s%d\n", num_encoding_parameters_key,
924 info->num_encoding_parameters);
925
926 for(i = 0; i < info->num_encoding_parameters; i++)
927 {
928 write_parameter_info(output, &info->encoding_parameters[i], 1);
929 }
930
931 fprintf(output, "%s%d\n", num_decoding_parameters_key,
932 info->num_decoding_parameters);
933
934 for(i = 0; i < info->num_decoding_parameters; i++)
935 {
936 write_parameter_info(output, &info->decoding_parameters[i], 0);
937 }
938
939 if((info->type == LQT_CODEC_VIDEO) &&
940 (info->direction != LQT_DIRECTION_DECODE))
941 {
942 fprintf(output, "%s%d\n", num_encoding_colormodels_key,
943 info->num_encoding_colormodels);
944
945 for(i = 0; i < info->num_encoding_colormodels; i++)
946 {
947 fprintf(output, "%s%s\n", encoding_colormodel_key,
948 lqt_colormodel_to_string(info->encoding_colormodels[i]));
949 }
950 }
951
952 if((info->type == LQT_CODEC_VIDEO) &&
953 (info->direction != LQT_DIRECTION_DECODE))
954 {
955 fprintf(output, "%s%d\n", num_image_sizes_key,
956 info->num_image_sizes);
957 for(i = 0; i < info->num_image_sizes; i++)
958 {
959 fprintf(output, "%s%d %d\n", image_size_key,
960 info->image_sizes[i].width, info->image_sizes[i].height);
961 }
962 }
963
964 /* Module filename and index */
965 fprintf(output, "%s%s\n", module_filename_key, info->module_filename);
966 fprintf(output, "%s%d\n", module_index_key, info->module_index);
967 fprintf(output, "%s%u\n", module_file_time_key, info->file_time);
968
969 if(info->gettext_domain)
970 fprintf(output, "%s%s\n", gettext_domain_key, info->gettext_domain);
971 if(info->gettext_directory)
972 fprintf(output, "%s%s\n", gettext_directory_key, info->gettext_directory);
973
974 if(fprintf(output, "%s\n", end_codec_key) < 0)
975 return 0;
976 return 1;
977 }
978
lqt_registry_write()979 void lqt_registry_write()
980 {
981 int i;
982 FILE * output;
983 char * filename_buffer = create_filename();
984 lqt_codec_info_t * codec_info;
985
986 lqt_registry_lock();
987
988 if(!filename_buffer || (*filename_buffer == '\0'))
989 {
990 lqt_log(NULL, LQT_LOG_ERROR, LOG_DOMAIN, "Codec registry filename could not be generated");
991 return;
992 }
993
994 output = fopen(filename_buffer, "w");
995
996 if(!output)
997 {
998 lqt_registry_unlock();
999 free(filename_buffer);
1000 return;
1001 }
1002
1003 /*
1004 * Write initial comment
1005 */
1006
1007 fprintf(output, "# This is the codec database file for libquicktime\n\
1008 # It is automatically generated and should not be edited.\n\
1009 # If you changed it and your libquicktime program doesn't work\n\
1010 # anymore, delete it, and you will get a new one\n");
1011
1012 /* Write the sort strings */
1013
1014 if(lqt_num_audio_codecs)
1015 {
1016 codec_info = lqt_audio_codecs;
1017
1018 fprintf(output, "%s", audio_order_key);
1019 for(i = 0; i < lqt_num_audio_codecs; i++)
1020 {
1021 fprintf(output, "%s", codec_info->name);
1022 if(i == lqt_num_audio_codecs - 1)
1023 fprintf(output, "\n");
1024 else
1025 fprintf(output, ",");
1026 codec_info = codec_info->next;
1027 }
1028 }
1029
1030 if(lqt_num_video_codecs)
1031 {
1032 codec_info = lqt_video_codecs;
1033 fprintf(output, "%s", video_order_key);
1034 for(i = 0; i < lqt_num_video_codecs; i++)
1035 {
1036 fprintf(output, "%s", codec_info->name);
1037 if(i == lqt_num_video_codecs - 1)
1038 fprintf(output, "\n");
1039 else
1040 fprintf(output, ",");
1041 codec_info = codec_info->next;
1042 }
1043 }
1044
1045 codec_info = lqt_audio_codecs;
1046
1047 for(i = 0; i < lqt_num_audio_codecs; i++)
1048 {
1049 if(!write_codec_info(codec_info, output))
1050 goto fail;
1051 codec_info = codec_info->next;
1052 }
1053
1054 codec_info = lqt_video_codecs;
1055 for(i = 0; i < lqt_num_video_codecs; i++)
1056 {
1057 if(!write_codec_info(codec_info, output))
1058 goto fail;
1059 codec_info = codec_info->next;
1060 }
1061 fclose(output);
1062 lqt_registry_unlock();
1063 free(filename_buffer);
1064 return;
1065 fail:
1066 fclose(output);
1067 lqt_registry_unlock();
1068 free(filename_buffer);
1069 lqt_log(NULL, LQT_LOG_INFO, LOG_DOMAIN,
1070 "%s could not be written, deleting imcomplete file", filename_buffer);
1071 remove(filename_buffer);
1072 }
1073