3 * This program is distributed under the GNU General Public License, version 2.
4 * A copy of this license is included with this source.
6 * Copyright 2000-2005, Michael Smith <msmith@xiph.org>
8 * Portions from Vorbize, (c) Kenneth Arnold <kcarnold-xiph@arnoldnet.net>
9 * and libvorbis examples, (c) Monty <monty@xiph.org>
16 /* Watcom C unistd.h defines the vars? */
17 #define DONT_DEFINE_GETOPT_VARS
27 #include <sys/types.h>
29 #if defined WIN32 || defined _WIN32
39 #define CHUNK 4096 /* We do reads, etc. in multiples of this */
41 struct option long_options[] = {
44 {"skeleton",no_argument,NULL, 'k'},
51 {"name-remove",1,0,'X'},
52 {"name-replace",1,0,'P'},
59 {"raw-endianness",1,0, 0},
61 {"min-bitrate",1,0,'m'},
62 {"max-bitrate",1,0,'M'},
71 {"advanced-encode-option", 1, 0, 0},
72 {"discard-comments", 0, 0, 0},
74 {"ignorelength", 0, 0, 0},
76 {"lyrics-language",1,0,'Y'},
80 static char *generate_name_string(char *format, char *remove_list,
81 char *replace_list, char *artist, char *title, char *album,
82 char *track, char *date, char *genre);
83 static void parse_options(int argc, char **argv, oe_options *opt);
84 static void build_comments(vorbis_comment *vc, oe_options *opt, int filenum,
85 char **artist,char **album, char **title, char **tracknum, char **date,
87 static void usage(void);
89 int main(int argc, char **argv)
93 NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0,
94 NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0,
97 NULL, DEFAULT_NAMEFMT_REMOVE, DEFAULT_NAMEFMT_REPLACE,
110 get_args_from_ucs16(&argc, &argv);
112 setlocale(LC_ALL, "");
113 bindtextdomain(PACKAGE, LOCALEDIR);
116 parse_options(argc, argv, &opt);
120 fprintf(stderr, _("ERROR: No input files specified. Use -h for help.\n"));
125 infiles = argv + optind;
126 numfiles = argc - optind;
129 /* Now, do some checking for illegal argument combinations */
131 for(i = 0; i < numfiles; i++)
133 if(!strcmp(infiles[i], "-") && numfiles > 1)
135 fprintf(stderr, _("ERROR: Multiple files specified when using stdin\n"));
140 if(numfiles > 1 && opt.outfile)
142 fprintf(stderr, _("ERROR: Multiple input files with specified output filename: suggest using -n\n"));
148 /* We randomly pick a serial number. This is then incremented for each
149 file. The random seed includes the PID so two copies of oggenc that
150 start in the same second will generate different serial numbers. */
151 /* Jonathan C: MS-DOS does not have getpid() nor can it run multiple instances concurrently */
155 opt.skeleton_serial = opt.serial + numfiles;
156 opt.kate_serial = opt.skeleton_serial + numfiles;
158 for(i = 0; i < numfiles; i++)
160 /* Once through the loop for each file */
165 FILE *in, *out = NULL;
167 int closeout = 0, closein = 0;
168 char *artist=NULL, *album=NULL, *title=NULL, *track=NULL;
169 char *date=NULL, *genre=NULL;
170 char *lyrics=NULL, *lyrics_language=NULL;
171 input_format *format;
174 /* Set various encoding defaults */
176 enc_opts.serialno = opt.serial++;
177 enc_opts.skeleton_serialno = opt.skeleton_serial++;
178 enc_opts.kate_serialno = opt.kate_serial++;
179 enc_opts.progress_update = update_statistics_full;
180 enc_opts.start_encode = start_encode_full;
181 enc_opts.end_encode = final_statistics;
182 enc_opts.error = encode_error;
183 enc_opts.comments = &vc;
184 enc_opts.copy_comments = opt.copy_comments;
185 enc_opts.with_skeleton = opt.with_skeleton;
186 enc_opts.ignorelength = opt.ignorelength;
188 /* OK, let's build the vorbis_comments structure */
189 build_comments(&vc, &opt, i, &artist, &album, &title, &track,
194 if(i >= opt.lyrics_count)
199 lyrics = opt.lyrics[i];
202 if(opt.lyrics_language_count)
204 if(i >= opt.lyrics_language_count)
207 fprintf(stderr, _("WARNING: Insufficient lyrics languages specified, defaulting to final lyrics language.\n"));
208 lyrics_language = opt.lyrics_language[opt.lyrics_language_count-1];
211 lyrics_language = opt.lyrics_language[i];
214 if(!strcmp(infiles[i], "-"))
227 in = oggenc_fopen(infiles[i], "rb", opt.isutf8);
231 fprintf(stderr, _("ERROR: Cannot open input file \"%s\": %s\n"), infiles[i], strerror(errno));
240 /* Now, we need to select an input audio format - we do this before opening
241 the output file so that we don't end up with a 0-byte file if the input
242 file can't be read */
246 input_format raw_format = {NULL, 0, raw_open, wav_close, "raw",
247 N_("RAW file reader")};
249 enc_opts.rate=opt.raw_samplerate;
250 enc_opts.channels=opt.raw_channels;
251 enc_opts.samplesize=opt.raw_samplesize;
252 enc_opts.endianness=opt.raw_endianness;
254 format = &raw_format;
255 format->open_func(in, &enc_opts, NULL, 0);
260 format = open_audio_file(in, &enc_opts);
264 fprintf(stderr, _("Opening with %s module: %s\n"),
265 format->format, format->description);
273 fprintf(stderr, _("ERROR: Input file \"%s\" is not a supported format\n"), infiles[i]?infiles[i]:"(stdin)");
280 /* Ok. We can read the file - so now open the output file */
282 if(opt.outfile && !strcmp(opt.outfile, "-"))
291 out_fn = strdup(opt.outfile);
295 out_fn = generate_name_string(opt.namefmt, opt.namefmt_remove,
296 opt.namefmt_replace, artist, title, album, track,date,
299 /* This bit was widely derided in mid-2002, so it's been removed */
303 out_fn = malloc(strlen(title) + 5);
304 strcpy(out_fn, title);
305 strcat(out_fn, ".ogg");
310 /* Create a filename from existing filename, replacing extension with .ogg or .oga */
314 /* if adding Skeleton or Kate, we're not Vorbis I anymore */
315 extension = (opt.with_skeleton || opt.lyrics_count>0) ? ".oga" : ".ogg";
318 end = strrchr(infiles[i], '.');
319 end = end?end:(start + strlen(infiles[i])+1);
321 /* NTS: Looking over this code carefully, it either appends ".ogg" or replaces the extension with ".ogg"
322 * which is perfectly fine for this MS-DOS port knowing that DOS 8.3 limitations would not like
323 * ".wav.ogg". If the user is running us under FreeDOS with the LFN driver enabled, or in a Windows 9x
324 * DOS Box, then the limit does not apply. ---Jonathan C */
325 out_fn = malloc(end - start + 5);
326 strncpy(out_fn, start, end-start);
327 out_fn[end-start] = 0;
328 strcat(out_fn, extension);
331 /* if adding skeleton or kate, we're not Vorbis I anymore */
332 if (opt.with_skeleton || opt.lyrics_count>0)
333 out_fn = strdup("default.oga");
335 out_fn = strdup("default.ogg");
336 fprintf(stderr, _("WARNING: No filename, defaulting to \"%s\"\n"), out_fn);
339 /* Create any missing subdirectories, if possible */
340 if(create_directories(out_fn, opt.isutf8)) {
343 fprintf(stderr, _("ERROR: Could not create required subdirectories for output filename \"%s\"\n"), out_fn);
349 if(infiles[i] && !strcmp(infiles[i], out_fn)) {
350 fprintf(stderr, _("ERROR: Input filename is the same as output filename \"%s\"\n"), out_fn);
356 out = oggenc_fopen(out_fn, "wb", opt.isutf8);
361 fprintf(stderr, _("ERROR: Cannot open output file \"%s\": %s\n"), out_fn, strerror(errno));
369 /* Now, set the rest of the options */
371 enc_opts.comments = &vc;
374 enc_opts.filename = NULL;
375 enc_opts.infilename = NULL;
376 utf8_decode(out_fn, &enc_opts.filename);
377 utf8_decode(infiles[i], &enc_opts.infilename);
379 enc_opts.filename = strdup(out_fn);
380 enc_opts.infilename = strdup(infiles[i]);
383 enc_opts.filename = out_fn;
384 enc_opts.infilename = infiles[i];
386 enc_opts.managed = opt.managed;
387 enc_opts.bitrate = opt.nominal_bitrate;
388 enc_opts.min_bitrate = opt.min_bitrate;
389 enc_opts.max_bitrate = opt.max_bitrate;
390 enc_opts.quality = opt.quality;
391 enc_opts.quality_set = opt.quality_set;
392 enc_opts.advopt = opt.advopt;
393 enc_opts.advopt_count = opt.advopt_count;
394 enc_opts.lyrics = lyrics;
395 enc_opts.lyrics_language = lyrics_language;
397 if(opt.resamplefreq && opt.resamplefreq != enc_opts.rate) {
398 int fromrate = enc_opts.rate;
401 enc_opts.resamplefreq = opt.resamplefreq;
402 if(setup_resample(&enc_opts)) {
407 fprintf(stderr, _("Resampling input from %d Hz to %d Hz\n"), fromrate, opt.resamplefreq);
411 if(enc_opts.channels == 2) {
412 setup_downmix(&enc_opts);
414 fprintf(stderr, _("Downmixing stereo to mono\n"));
417 fprintf(stderr, _("WARNING: Can't downmix except from stereo to mono\n"));
422 if(opt.scale > 0.f) {
423 setup_scaler(&enc_opts, opt.scale);
425 fprintf(stderr, _("Scaling input to %f\n"), opt.scale);
429 if(!enc_opts.total_samples_per_channel)
430 enc_opts.progress_update = update_statistics_notime;
434 enc_opts.start_encode = start_encode_null;
435 enc_opts.progress_update = update_statistics_null;
436 enc_opts.end_encode = final_statistics_null;
439 if(oe_encode(&enc_opts))
443 clear_scaler(&enc_opts);
445 clear_downmix(&enc_opts);
447 clear_resample(&enc_opts);
450 if(out_fn) free(out_fn);
451 if(opt.outfile) free(opt.outfile);
453 if(enc_opts.filename) free(enc_opts.filename);
454 if(enc_opts.infilename) free(enc_opts.infilename);
456 vorbis_comment_clear(&vc);
457 format->close_func(enc_opts.readdata);
463 }/* Finished this file, loop around to next... */
469 static void usage(void)
471 fprintf(stdout, _("oggenc from %s %s"), PACKAGE, VERSION);
472 fprintf(stdout, _(" by the Xiph.Org Foundation (http://www.xiph.org/)\n\n"));
473 fprintf(stdout, _("Usage: oggenc [options] inputfile [...]\n\n"));
474 fprintf(stdout, _("OPTIONS:\n"
476 " -Q, --quiet Produce no output to stderr\n"
477 " -h, --help Print this help text\n"
478 " -V, --version Print the version number\n"));
480 " -k, --skeleton Adds an Ogg Skeleton bitstream\n"
481 " -r, --raw Raw mode. Input files are read directly as PCM data\n"
482 " -B, --raw-bits=n Set bits/sample for raw input; default is 16\n"
483 " -C, --raw-chan=n Set number of channels for raw input; default is 2\n"
484 " -R, --raw-rate=n Set samples/sec for raw input; default is 44100\n"
485 " --raw-endianness 1 for bigendian, 0 for little (defaults to 0)\n"));
487 " -b, --bitrate Choose a nominal bitrate to encode at. Attempt\n"
488 " to encode at a bitrate averaging this. Takes an\n"
489 " argument in kbps. By default, this produces a VBR\n"
490 " encoding, equivalent to using -q or --quality.\n"
491 " See the --managed option to use a managed bitrate\n"
492 " targetting the selected bitrate.\n"));
494 " --managed Enable the bitrate management engine. This will allow\n"
495 " much greater control over the precise bitrate(s) used,\n"
496 " but encoding will be much slower. Don't use it unless\n"
497 " you have a strong need for detailed control over\n"
498 " bitrate, such as for streaming.\n"));
500 " -m, --min-bitrate Specify a minimum bitrate (in kbps). Useful for\n"
501 " encoding for a fixed-size channel. Using this will\n"
502 " automatically enable managed bitrate mode (see\n"
504 " -M, --max-bitrate Specify a maximum bitrate in kbps. Useful for\n"
505 " streaming applications. Using this will automatically\n"
506 " enable managed bitrate mode (see --managed).\n"));
508 " --advanced-encode-option option=value\n"
509 " Sets an advanced encoder option to the given value.\n"
510 " The valid options (and their values) are documented\n"
511 " in the man page supplied with this program. They are\n"
512 " for advanced users only, and should be used with\n"
515 " -q, --quality Specify quality, between -1 (very low) and 10 (very\n"
516 " high), instead of specifying a particular bitrate.\n"
517 " This is the normal mode of operation.\n"
518 " Fractional qualities (e.g. 2.75) are permitted\n"
519 " The default quality level is 3.\n"));
521 " --resample n Resample input data to sampling rate n (Hz)\n"
522 " --downmix Downmix stereo to mono. Only allowed on stereo\n"
524 " -s, --serial Specify a serial number for the stream. If encoding\n"
525 " multiple files, this will be incremented for each\n"
526 " stream after the first.\n"));
528 " --discard-comments Prevents comments in FLAC and Ogg FLAC files from\n"
529 " being copied to the output Ogg Vorbis file.\n"
530 " --ignorelength Ignore the datalength in Wave headers. This allows\n"
531 " support for files > 4GB and STDIN data streams. \n"
535 " -o, --output=fn Write file to fn (only valid in single-file mode)\n"
536 " -n, --names=string Produce filenames as this string, with %%a, %%t, %%l,\n"
537 " %%n, %%d replaced by artist, title, album, track number,\n"
538 " and date, respectively (see below for specifying these).\n"
539 " %%%% gives a literal %%.\n"));
541 " -X, --name-remove=s Remove the specified characters from parameters to the\n"
542 " -n format string. Useful to ensure legal filenames.\n"
543 " -P, --name-replace=s Replace characters removed by --name-remove with the\n"
544 " characters specified. If this string is shorter than the\n"
545 " --name-remove list or is not specified, the extra\n"
546 " characters are just removed.\n"
547 " Default settings for the above two arguments are platform\n"
550 " --utf8 Tells oggenc that the command line parameters date, title,\n"
551 " album, artist, genre, and comment are already in UTF-8.\n"
552 " On Windows, this switch applies to file names too.\n"
553 " -c, --comment=c Add the given string as an extra comment. This may be\n"
554 " used multiple times. The argument should be in the\n"
555 " format \"tag=value\".\n"
556 " -d, --date Date for track (usually date of performance)\n"));
558 " -N, --tracknum Track number for this track\n"
559 " -t, --title Title for this track\n"
560 " -l, --album Name of album\n"
561 " -a, --artist Name of artist\n"
562 " -G, --genre Genre of track\n"));
564 " -L, --lyrics Include lyrics from given file (.srt or .lrc format)\n"
565 " -Y, --lyrics-language Sets the language for the lyrics\n"));
567 " If multiple input files are given, then multiple\n"
568 " instances of the previous eight arguments will be used,\n"
569 " in the order they are given. If fewer titles are\n"
570 " specified than files, OggEnc will print a warning, and\n"
571 " reuse the final one for the remaining files. If fewer\n"
572 " track numbers are given, the remaining files will be\n"
573 " unnumbered. If fewer lyrics are given, the remaining\n"
574 " files will not have lyrics added. For the others, the\n"
575 " final tag will be reused for all others without warning\n"
576 " (so you can specify a date once, for example, and have\n"
577 " it used for all the files)\n"
581 " OggEnc input files must currently be 24, 16, or 8 bit PCM Wave, AIFF, or AIFF/C\n"
582 " files, 32 bit IEEE floating point Wave, and optionally FLAC or Ogg FLAC. Files\n"
583 " may be mono or stereo (or more channels) and any sample rate.\n"
584 " Alternatively, the --raw option may be used to use a raw PCM data file, which\n"
585 " must be 16 bit stereo little-endian PCM ('headerless Wave'), unless additional\n"
586 " parameters for raw mode are specified.\n"
587 " You can specify taking the file from stdin by using - as the input filename.\n"
588 " In this mode, output is to stdout unless an output filename is specified\n"
590 " Lyrics files may be in SubRip (.srt) or LRC (.lrc) format\n"
594 static int strncpy_filtered(char *dst, char *src, int len, char *remove_list,
597 char *hit, *drop_margin;
600 if(remove_list == NULL || *remove_list == 0)
602 strncpy(dst, src, len-1);
607 drop_margin = remove_list + (replace_list == NULL?0:strlen(replace_list));
609 while(*src && used < len-1)
611 if((hit = strchr(remove_list, *src)) != NULL)
613 if(hit < drop_margin)
615 *dst++ = replace_list[hit - remove_list];
631 static char *generate_name_string(char *format, char *remove_list,
632 char *replace_list, char *artist, char *title, char *album,
633 char *track, char *date, char *genre)
641 buffer = calloc(CHUNK+1,1);
644 while(*format && used < buflen)
653 *(buffer+(used++)) = '%';
656 string = artist?artist:_("(none)");
657 used += strncpy_filtered(buffer+used, string, buflen-used,
658 remove_list, replace_list);
661 string = date?date:_("(none)");
662 used += strncpy_filtered(buffer+used, string, buflen-used,
663 remove_list, replace_list);
666 string = genre?genre:_("(none)");
667 used += strncpy_filtered(buffer+used, string, buflen-used,
668 remove_list, replace_list);
671 string = title?title:_("(none)");
672 used += strncpy_filtered(buffer+used, string, buflen-used,
673 remove_list, replace_list);
676 string = album?album:_("(none)");
677 used += strncpy_filtered(buffer+used, string, buflen-used,
678 remove_list, replace_list);
681 string = track?track:_("(none)");
682 used += strncpy_filtered(buffer+used, string, buflen-used,
683 remove_list, replace_list);
686 fprintf(stderr, _("WARNING: Ignoring illegal escape character '%c' in name format\n"), *(format - 1));
691 *(buffer + (used++)) = next;
697 static void parse_options(int argc, char **argv, oe_options *opt)
700 int option_index = 1;
702 while((ret = getopt_long(argc, argv, "a:b:B:c:C:d:G:hkl:L:m:M:n:N:o:P:q:QrR:s:t:VX:Y:",
703 long_options, &option_index)) != -1)
708 if(!strcmp(long_options[option_index].name, "skeleton")) {
709 opt->with_skeleton = 1;
711 else if(!strcmp(long_options[option_index].name, "managed")) {
715 _("Enabling bitrate management engine\n"));
719 else if(!strcmp(long_options[option_index].name,
721 if (opt->rawmode != 1)
724 fprintf(stderr, _("WARNING: Raw endianness specified for non-raw data. Assuming input is raw.\n"));
726 if(sscanf(optarg, "%d", &opt->raw_endianness) != 1) {
727 fprintf(stderr, _("WARNING: Couldn't read endianness argument \"%s\"\n"), optarg);
728 opt->raw_endianness = 0;
731 else if(!strcmp(long_options[option_index].name,
733 if(sscanf(optarg, "%d", &opt->resamplefreq) != 1) {
734 fprintf(stderr, _("WARNING: Couldn't read resampling frequency \"%s\"\n"), optarg);
735 opt->resamplefreq = 0;
737 if(opt->resamplefreq < 100) /* User probably specified it
740 _("WARNING: Resample rate specified as %d Hz. Did you mean %d Hz?\n"),
741 opt->resamplefreq, opt->resamplefreq*1000);
743 else if(!strcmp(long_options[option_index].name, "downmix")) {
746 else if(!strcmp(long_options[option_index].name, "scale")) {
747 opt->scale = atof(optarg);
748 if(sscanf(optarg, "%f", &opt->scale) != 1) {
750 fprintf(stderr, _("WARNING: Couldn't parse scaling factor \"%s\"\n"),
754 else if(!strcmp(long_options[option_index].name, "utf8")) {
757 else if(!strcmp(long_options[option_index].name, "advanced-encode-option")) {
758 char *arg = strdup(optarg);
761 if(strcmp("disable_coupling",arg)){
762 val = strchr(arg, '=');
764 fprintf(stderr, _("No value for advanced encoder option found\n"));
772 opt->advopt = realloc(opt->advopt, (++opt->advopt_count)*sizeof(adv_opt));
773 opt->advopt[opt->advopt_count - 1].arg = arg;
774 opt->advopt[opt->advopt_count - 1].val = val;
776 else if(!strcmp(long_options[option_index].name, "discard-comments")) {
777 opt->copy_comments = 0;
779 else if(!strcmp(long_options[option_index].name, "ignorelength")) {
780 opt->ignorelength = 1;
784 fprintf(stderr, _("Internal error parsing command line options\n"));
790 opt->artist = realloc(opt->artist, (++opt->artist_count)*sizeof(char *));
791 opt->artist[opt->artist_count - 1] = strdup(optarg);
794 if(strchr(optarg, '=') == NULL) {
795 fprintf(stderr, _("WARNING: Illegal comment used (\"%s\"), ignoring.\n"), optarg);
798 opt->comments = realloc(opt->comments, (++opt->comment_count)*sizeof(char *));
799 opt->comments[opt->comment_count - 1] = strdup(optarg);
802 opt->dates = realloc(opt->dates, (++opt->date_count)*sizeof(char *));
803 opt->dates[opt->date_count - 1] = strdup(optarg);
806 opt->genre = realloc(opt->genre, (++opt->genre_count)*sizeof(char *));
807 opt->genre[opt->genre_count - 1] = strdup(optarg);
814 opt->album = realloc(opt->album, (++opt->album_count)*sizeof(char *));
815 opt->album[opt->album_count - 1] = strdup(optarg);
818 /* Would just use atoi(), but that doesn't deal with unsigned
820 if(sscanf(optarg, "%u", &opt->serial) != 1)
821 opt->serial = 0; /* Failed, so just set to zero */
823 opt->fixedserial = 1;
826 opt->title = realloc(opt->title, (++opt->title_count)*sizeof(char *));
827 opt->title[opt->title_count - 1] = strdup(optarg);
830 if(sscanf(optarg, "%d", &opt->nominal_bitrate)
832 fprintf(stderr, _("WARNING: nominal bitrate \"%s\" not recognised\n"), optarg);
833 opt->nominal_bitrate = -1;
838 if(sscanf(optarg, "%d", &opt->min_bitrate)
840 fprintf(stderr, _("WARNING: minimum bitrate \"%s\" not recognised\n"), optarg);
841 opt->min_bitrate = -1;
846 _("Enabling bitrate management engine\n"));
851 if(sscanf(optarg, "%d", &opt->max_bitrate)
853 fprintf(stderr, _("WARNING: maximum bitrate \"%s\" not recognised\n"), optarg);
854 opt->max_bitrate = -1;
859 _("Enabling bitrate management engine\n"));
864 if(sscanf(optarg, "%f", &opt->quality) != 1) {
865 fprintf(stderr, _("Quality option \"%s\" not recognised, ignoring\n"), optarg);
870 if(opt->quality > 1.0f)
873 fprintf(stderr, _("WARNING: quality setting too high, setting to maximum quality.\n"));
879 fprintf(stderr, _("WARNING: Multiple name formats specified, using final\n"));
882 opt->namefmt = strdup(optarg);
885 if(opt->namefmt_remove &&
886 strcmp(opt->namefmt_remove, DEFAULT_NAMEFMT_REMOVE))
888 fprintf(stderr, _("WARNING: Multiple name format filters specified, using final\n"));
889 free(opt->namefmt_remove);
891 opt->namefmt_remove = strdup(optarg);
894 if(opt->namefmt_replace &&
895 strcmp(opt->namefmt_replace, DEFAULT_NAMEFMT_REPLACE))
897 fprintf(stderr, _("WARNING: Multiple name format filter replacements specified, using final\n"));
898 free(opt->namefmt_replace);
900 opt->namefmt_replace = strdup(optarg);
905 fprintf(stderr, _("WARNING: Multiple output files specified, suggest using -n\n"));
908 opt->outfile = strdup(optarg);
917 fprintf(stdout, _("oggenc from %s %s\n"), PACKAGE, VERSION);
921 if (opt->rawmode != 1)
924 fprintf(stderr, _("WARNING: Raw bits/sample specified for non-raw data. Assuming input is raw.\n"));
926 if(sscanf(optarg, "%u", &opt->raw_samplesize) != 1)
928 opt->raw_samplesize = 16; /* Failed, so just set to 16 */
929 fprintf(stderr, _("WARNING: Invalid bits/sample specified, assuming 16.\n"));
931 if((opt->raw_samplesize != 8) && (opt->raw_samplesize != 16))
933 fprintf(stderr, _("WARNING: Invalid bits/sample specified, assuming 16.\n"));
937 if (opt->rawmode != 1)
940 fprintf(stderr, _("WARNING: Raw channel count specified for non-raw data. Assuming input is raw.\n"));
942 if(sscanf(optarg, "%u", &opt->raw_channels) != 1)
944 opt->raw_channels = 2; /* Failed, so just set to 2 */
945 fprintf(stderr, _("WARNING: Invalid channel count specified, assuming 2.\n"));
949 opt->tracknum = realloc(opt->tracknum, (++opt->track_count)*sizeof(char *));
950 opt->tracknum[opt->track_count - 1] = strdup(optarg);
953 if (opt->rawmode != 1)
956 fprintf(stderr, _("WARNING: Raw sample rate specified for non-raw data. Assuming input is raw.\n"));
958 if(sscanf(optarg, "%u", &opt->raw_samplerate) != 1)
960 opt->raw_samplerate = 44100; /* Failed, so just set to 44100 */
961 fprintf(stderr, _("WARNING: Invalid sample rate specified, assuming 44100.\n"));
965 opt->with_skeleton = 1;
969 opt->lyrics = realloc(opt->lyrics, (++opt->lyrics_count)*sizeof(char *));
970 opt->lyrics[opt->lyrics_count - 1] = strdup(optarg);
971 opt->with_skeleton = 1;
973 fprintf(stderr, _("WARNING: Kate support not compiled in; lyrics will not be included.\n"));
978 opt->lyrics_language = realloc(opt->lyrics_language, (++opt->lyrics_language_count)*sizeof(char *));
979 opt->lyrics_language[opt->lyrics_language_count - 1] = strdup(optarg);
980 if (strlen(opt->lyrics_language[opt->lyrics_language_count - 1]) > 15) {
981 fprintf(stderr, _("WARNING: language can not be longer than 15 characters; truncated.\n"));
982 opt->lyrics_language[opt->lyrics_language_count - 1][15] = 0;
985 fprintf(stderr, _("WARNING: Kate support not compiled in; lyrics will not be included.\n"));
989 fprintf(stderr, _("WARNING: Unknown option specified, ignoring->\n"));
999 static void add_tag(vorbis_comment *vc, oe_options *opt,char *name, char *value)
1002 fprintf(stderr,"WARNING: This build does not accept UTF-8 tags\n");
1006 vorbis_comment_add(vc, value);
1008 vorbis_comment_add_tag(vc, name, value);
1012 static void build_comments(vorbis_comment *vc, oe_options *opt, int filenum,
1013 char **artist, char **album, char **title, char **tracknum,
1014 char **date, char **genre)
1018 vorbis_comment_init(vc);
1020 for(i = 0; i < opt->comment_count; i++)
1021 add_tag(vc, opt, NULL, opt->comments[i]);
1023 if(opt->title_count)
1025 if(filenum >= opt->title_count)
1028 fprintf(stderr, _("WARNING: Insufficient titles specified, defaulting to final title.\n"));
1029 i = opt->title_count-1;
1034 *title = opt->title[i];
1035 add_tag(vc, opt, "title", opt->title[i]);
1038 if(opt->artist_count)
1040 if(filenum >= opt->artist_count)
1041 i = opt->artist_count-1;
1045 *artist = opt->artist[i];
1046 add_tag(vc, opt, "artist", opt->artist[i]);
1049 if(opt->genre_count)
1051 if(filenum >= opt->genre_count)
1052 i = opt->genre_count-1;
1056 *genre = opt->genre[i];
1057 add_tag(vc, opt, "genre", opt->genre[i]);
1062 if(filenum >= opt->date_count)
1063 i = opt->date_count-1;
1067 *date = opt->dates[i];
1068 add_tag(vc, opt, "date", opt->dates[i]);
1071 if(opt->album_count)
1073 if(filenum >= opt->album_count)
1075 i = opt->album_count-1;
1080 *album = opt->album[i];
1081 add_tag(vc, opt, "album", opt->album[i]);
1084 if(filenum < opt->track_count)
1087 *tracknum = opt->tracknum[i];
1088 add_tag(vc, opt, "tracknumber", opt->tracknum[i]);