+
+ if(!parse_cuesheet(&static_metadata.cuesheet, options.cuesheet_filename, e->inbasefilename, sample_rate, is_cdda, e->total_samples_to_encode, e->treat_warnings_as_errors))
+ return false;
+
+ if(!convert_to_seek_table_template(options.requested_seek_points, options.num_requested_seek_points, options.cued_seekpoints? static_metadata.cuesheet : 0, e)) {
+ flac__utils_printf(stderr, 1, "%s: ERROR allocating memory for seek table\n", e->inbasefilename);
+ static_metadata_clear(&static_metadata);
+ return false;
+ }
+
+ /* build metadata */
+ if(flac_decoder_data) {
+ /*
+ * we're encoding from FLAC so we will use the FLAC file's
+ * metadata as the basis for the encoded file
+ */
+ {
+ unsigned i;
+ /*
+ * first handle pictures: simple append any --pictures
+ * specified.
+ */
+ for(i = 0; i < options.num_pictures; i++) {
+ FLAC__StreamMetadata *pic = FLAC__metadata_object_clone(options.pictures[i]);
+ if(0 == pic) {
+ flac__utils_printf(stderr, 1, "%s: ERROR allocating memory for PICTURE block\n", e->inbasefilename);
+ static_metadata_clear(&static_metadata);
+ return false;
+ }
+ flac_decoder_data->metadata_blocks[flac_decoder_data->num_metadata_blocks++] = pic;
+ }
+ }
+ {
+ /*
+ * next handle vorbis comment: if any tags were specified
+ * or there is no existing vorbis comment, we create a
+ * new vorbis comment (discarding any existing one); else
+ * we keep the existing one. also need to make sure to
+ * propagate any channel mask tag.
+ */
+ /* @@@ change to append -T values from options.vorbis_comment if input has VC already? */
+ size_t i, j;
+ FLAC__bool vc_found = false;
+ for(i = 0, j = 0; i < flac_decoder_data->num_metadata_blocks; i++) {
+ if(flac_decoder_data->metadata_blocks[i]->type == FLAC__METADATA_TYPE_VORBIS_COMMENT)
+ vc_found = true;
+ if(flac_decoder_data->metadata_blocks[i]->type == FLAC__METADATA_TYPE_VORBIS_COMMENT && options.vorbis_comment->data.vorbis_comment.num_comments > 0) {
+ (void) flac__utils_get_channel_mask_tag(flac_decoder_data->metadata_blocks[i], &e->info.channel_mask);
+ flac__utils_printf(stderr, 1, "%s: WARNING, replacing tags from input FLAC file with those given on the command-line\n", e->inbasefilename);
+ if(e->treat_warnings_as_errors) {
+ static_metadata_clear(&static_metadata);
+ return false;
+ }
+ FLAC__metadata_object_delete(flac_decoder_data->metadata_blocks[i]);
+ flac_decoder_data->metadata_blocks[i] = 0;
+ }
+ else
+ flac_decoder_data->metadata_blocks[j++] = flac_decoder_data->metadata_blocks[i];
+ }
+ flac_decoder_data->num_metadata_blocks = j;
+ if((!vc_found || options.vorbis_comment->data.vorbis_comment.num_comments > 0) && flac_decoder_data->num_metadata_blocks < sizeof(flac_decoder_data->metadata_blocks)/sizeof(flac_decoder_data->metadata_blocks[0])) {
+ /* prepend ours */
+ FLAC__StreamMetadata *vc = FLAC__metadata_object_clone(options.vorbis_comment);
+ if(0 == vc || (e->info.channel_mask && !flac__utils_set_channel_mask_tag(vc, e->info.channel_mask))) {
+ flac__utils_printf(stderr, 1, "%s: ERROR allocating memory for VORBIS_COMMENT block\n", e->inbasefilename);
+ static_metadata_clear(&static_metadata);
+ return false;
+ }
+ for(i = flac_decoder_data->num_metadata_blocks; i > 1; i--)
+ flac_decoder_data->metadata_blocks[i] = flac_decoder_data->metadata_blocks[i-1];
+ flac_decoder_data->metadata_blocks[1] = vc;
+ flac_decoder_data->num_metadata_blocks++;
+ }
+ }
+ {
+ /*
+ * next handle cuesheet: if --cuesheet was specified, use
+ * it; else if file has existing CUESHEET and cuesheet's
+ * lead-out offset is correct, keep it; else no CUESHEET
+ */
+ size_t i, j;
+ for(i = 0, j = 0; i < flac_decoder_data->num_metadata_blocks; i++) {
+ FLAC__bool existing_cuesheet_is_bad = false;
+ /* check if existing cuesheet matches the input audio */
+ if(flac_decoder_data->metadata_blocks[i]->type == FLAC__METADATA_TYPE_CUESHEET && 0 == static_metadata.cuesheet) {
+ const FLAC__StreamMetadata_CueSheet *cs = &flac_decoder_data->metadata_blocks[i]->data.cue_sheet;
+ if(e->total_samples_to_encode == 0) {
+ flac__utils_printf(stderr, 1, "%s: WARNING, cuesheet in input FLAC file cannot be kept if input size is not known, dropping it...\n", e->inbasefilename);
+ if(e->treat_warnings_as_errors) {
+ static_metadata_clear(&static_metadata);
+ return false;
+ }
+ existing_cuesheet_is_bad = true;
+ }
+ else if(e->total_samples_to_encode != cs->tracks[cs->num_tracks-1].offset) {
+ flac__utils_printf(stderr, 1, "%s: WARNING, lead-out offset of cuesheet in input FLAC file does not match input length, dropping existing cuesheet...\n", e->inbasefilename);
+ if(e->treat_warnings_as_errors) {
+ static_metadata_clear(&static_metadata);
+ return false;
+ }
+ existing_cuesheet_is_bad = true;
+ }
+ }
+ if(flac_decoder_data->metadata_blocks[i]->type == FLAC__METADATA_TYPE_CUESHEET && (existing_cuesheet_is_bad || 0 != static_metadata.cuesheet)) {
+ if(0 != static_metadata.cuesheet) {
+ flac__utils_printf(stderr, 1, "%s: WARNING, replacing cuesheet in input FLAC file with the one given on the command-line\n", e->inbasefilename);
+ if(e->treat_warnings_as_errors) {
+ static_metadata_clear(&static_metadata);
+ return false;
+ }
+ }
+ FLAC__metadata_object_delete(flac_decoder_data->metadata_blocks[i]);
+ flac_decoder_data->metadata_blocks[i] = 0;
+ }
+ else
+ flac_decoder_data->metadata_blocks[j++] = flac_decoder_data->metadata_blocks[i];
+ }
+ flac_decoder_data->num_metadata_blocks = j;
+ if(0 != static_metadata.cuesheet && flac_decoder_data->num_metadata_blocks < sizeof(flac_decoder_data->metadata_blocks)/sizeof(flac_decoder_data->metadata_blocks[0])) {
+ /* prepend ours */
+ FLAC__StreamMetadata *cs = FLAC__metadata_object_clone(static_metadata.cuesheet);
+ if(0 == cs) {
+ flac__utils_printf(stderr, 1, "%s: ERROR allocating memory for CUESHEET block\n", e->inbasefilename);
+ static_metadata_clear(&static_metadata);
+ return false;
+ }
+ for(i = flac_decoder_data->num_metadata_blocks; i > 1; i--)
+ flac_decoder_data->metadata_blocks[i] = flac_decoder_data->metadata_blocks[i-1];
+ flac_decoder_data->metadata_blocks[1] = cs;
+ flac_decoder_data->num_metadata_blocks++;
+ }
+ }
+ {
+ /*
+ * next handle seektable: if -S- was specified, no
+ * SEEKTABLE; else if -S was specified, use it/them;
+ * else if file has existing SEEKTABLE and input size is
+ * preserved (no --skip/--until/etc specified), keep it;
+ * else use default seektable options
+ *
+ * note: meanings of num_requested_seek_points:
+ * -1 : no -S option given, default to some value
+ * 0 : -S- given (no seektable)
+ * >0 : one or more -S options given
+ */
+ size_t i, j;
+ FLAC__bool existing_seektable = false;
+ for(i = 0, j = 0; i < flac_decoder_data->num_metadata_blocks; i++) {
+ if(flac_decoder_data->metadata_blocks[i]->type == FLAC__METADATA_TYPE_SEEKTABLE)
+ existing_seektable = true;
+ if(flac_decoder_data->metadata_blocks[i]->type == FLAC__METADATA_TYPE_SEEKTABLE && (e->total_samples_to_encode != flac_decoder_data->metadata_blocks[0]->data.stream_info.total_samples || options.num_requested_seek_points >= 0)) {
+ if(options.num_requested_seek_points > 0) {
+ flac__utils_printf(stderr, 1, "%s: WARNING, replacing seektable in input FLAC file with the one given on the command-line\n", e->inbasefilename);
+ if(e->treat_warnings_as_errors) {
+ static_metadata_clear(&static_metadata);
+ return false;
+ }
+ }
+ else if(options.num_requested_seek_points == 0)
+ ; /* no warning, silently delete existing SEEKTABLE since user specified --no-seektable (-S-) */
+ else {
+ flac__utils_printf(stderr, 1, "%s: WARNING, can't use existing seektable in input FLAC since the input size is changing or unknown, dropping existing SEEKTABLE block...\n", e->inbasefilename);
+ if(e->treat_warnings_as_errors) {
+ static_metadata_clear(&static_metadata);
+ return false;
+ }
+ }
+ FLAC__metadata_object_delete(flac_decoder_data->metadata_blocks[i]);
+ flac_decoder_data->metadata_blocks[i] = 0;
+ existing_seektable = false;
+ }
+ else
+ flac_decoder_data->metadata_blocks[j++] = flac_decoder_data->metadata_blocks[i];
+ }
+ flac_decoder_data->num_metadata_blocks = j;
+ if((options.num_requested_seek_points > 0 || (options.num_requested_seek_points < 0 && !existing_seektable)) && flac_decoder_data->num_metadata_blocks < sizeof(flac_decoder_data->metadata_blocks)/sizeof(flac_decoder_data->metadata_blocks[0])) {
+ /* prepend ours */
+ FLAC__StreamMetadata *st = FLAC__metadata_object_clone(e->seek_table_template);
+ if(0 == st) {
+ flac__utils_printf(stderr, 1, "%s: ERROR allocating memory for SEEKTABLE block\n", e->inbasefilename);
+ static_metadata_clear(&static_metadata);
+ return false;
+ }
+ for(i = flac_decoder_data->num_metadata_blocks; i > 1; i--)
+ flac_decoder_data->metadata_blocks[i] = flac_decoder_data->metadata_blocks[i-1];
+ flac_decoder_data->metadata_blocks[1] = st;
+ flac_decoder_data->num_metadata_blocks++;
+ }
+ }
+ {
+ /*
+ * finally handle padding: if --no-padding was specified,
+ * then delete all padding; else if -P was specified,
+ * use that instead of existing padding (if any); else
+ * if existing file has padding, move all existing
+ * padding blocks to one padding block at the end; else
+ * use default padding.
+ */
+ int p = -1;
+ size_t i, j;
+ for(i = 0, j = 0; i < flac_decoder_data->num_metadata_blocks; i++) {
+ if(flac_decoder_data->metadata_blocks[i]->type == FLAC__METADATA_TYPE_PADDING) {
+ if(p < 0)
+ p = 0;
+ p += flac_decoder_data->metadata_blocks[i]->length;
+ FLAC__metadata_object_delete(flac_decoder_data->metadata_blocks[i]);
+ flac_decoder_data->metadata_blocks[i] = 0;
+ }
+ else
+ flac_decoder_data->metadata_blocks[j++] = flac_decoder_data->metadata_blocks[i];
+ }
+ flac_decoder_data->num_metadata_blocks = j;
+ if(options.padding > 0)
+ p = options.padding;
+ if(p < 0)
+ p = e->total_samples_to_encode / sample_rate < 20*60? FLAC_ENCODE__DEFAULT_PADDING : FLAC_ENCODE__DEFAULT_PADDING*8;
+ if(options.padding != 0) {
+ if(p > 0 && flac_decoder_data->num_metadata_blocks < sizeof(flac_decoder_data->metadata_blocks)/sizeof(flac_decoder_data->metadata_blocks[0])) {
+ flac_decoder_data->metadata_blocks[flac_decoder_data->num_metadata_blocks] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING);
+ if(0 == flac_decoder_data->metadata_blocks[flac_decoder_data->num_metadata_blocks]) {
+ flac__utils_printf(stderr, 1, "%s: ERROR allocating memory for PADDING block\n", e->inbasefilename);
+ static_metadata_clear(&static_metadata);
+ return false;
+ }
+ flac_decoder_data->metadata_blocks[flac_decoder_data->num_metadata_blocks]->is_last = false; /* the encoder will set this for us */
+ flac_decoder_data->metadata_blocks[flac_decoder_data->num_metadata_blocks]->length = p;
+ flac_decoder_data->num_metadata_blocks++;
+ }
+ }
+ }
+ metadata = &flac_decoder_data->metadata_blocks[1]; /* don't include STREAMINFO */
+ num_metadata = flac_decoder_data->num_metadata_blocks - 1;