Example #1
0
        public void WriteMetadata(Stream stream, MetadataDictionary metadata, SettingsDictionary settings)
        {
            bool usePadding;

            if (string.IsNullOrEmpty(settings["UsePadding"]))
            {
                usePadding = false;
            }
            else if (!bool.TryParse(settings["UsePadding"], out usePadding))
            {
                throw new InvalidSettingException(string.Format(CultureInfo.CurrentCulture,
                                                                Resources.MetadataEncoderBadUsePadding, settings["UsePadding"]));
            }

            NativeVorbisCommentBlock vorbisCommentBlock = null;
            NativePictureBlock       pictureBlock       = null;

            try
            {
                using (var chain = new NativeMetadataChain(stream))
                {
                    if (!chain.Read())
                    {
                        MetadataChainStatus chainStatus = chain.GetStatus();
                        if (chainStatus == MetadataChainStatus.NotAFlacFile)
                        {
                            throw new UnsupportedAudioException(Resources.MetadataEncoderNotFlacError);
                        }
                        else
                        {
                            throw new IOException(string.Format(CultureInfo.CurrentCulture,
                                                                Resources.MetadataEncoderReadError, chainStatus));
                        }
                    }

                    // Create a Vorbis Comment block, even if empty:
                    vorbisCommentBlock = new NativeVorbisCommentBlock();
                    foreach (var item in new MetadataToVorbisCommentAdapter(metadata))
                    {
                        vorbisCommentBlock.Append(item.Key, item.Value);
                    }

                    // Create a Picture block if cover art is available:
                    if (metadata.CoverArt != null)
                    {
                        pictureBlock = new CoverArtToPictureBlockAdapter(metadata.CoverArt);
                    }

                    // Iterate over the existing blocks, replacing and deleting as needed:
                    using (var iterator = new NativeMetadataIterator(chain.Handle))
                        UpdateMetadata(iterator, vorbisCommentBlock, pictureBlock);

                    if (chain.CheckIfTempFileNeeded(usePadding))
                    {
                        // If FLAC requests a temporary file, use a MemoryStream instead. Then overwrite the original:
                        using (var tempStream = new MemoryStream())
                        {
                            if (!chain.WriteWithTempFile(usePadding, tempStream))
                            {
                                throw new IOException(string.Format(CultureInfo.CurrentCulture,
                                                                    Resources.MetadataEncoderTempFileError, chain.GetStatus()));
                            }

                            // Clear the original stream, and copy the temporary one over it:
                            stream.SetLength(tempStream.Length);
                            stream.Position = 0;
                            tempStream.WriteTo(stream);
                        }
                    }
                    else if (!chain.Write(usePadding))
                    {
                        throw new IOException(string.Format(CultureInfo.CurrentCulture,
                                                            Resources.MetadataEncoderWriteError, chain.GetStatus()));
                    }
                }
            }
            finally
            {
                vorbisCommentBlock?.Dispose();
                pictureBlock?.Dispose();
            }
        }
Example #2
0
        public void Initialize(Stream stream, AudioInfo audioInfo, MetadataDictionary metadata, SettingsDictionary settings)
        {
            Contract.Ensures(_encoder != null);
            Contract.Ensures(_encoder.GetState() == EncoderState.Ok);
            Contract.Ensures(_multiplier > 0);

            _encoder        = InitializeEncoder(audioInfo, stream);
            _metadataBlocks = new List <NativeMetadataBlock>(3); // Assumes one metadata block, one picture and one seek table
            _multiplier     = (float)Math.Pow(2, audioInfo.BitsPerSample - 1);

            uint compressionLevel;

            if (string.IsNullOrEmpty(settings["CompressionLevel"]))
            {
                compressionLevel = 5;
            }
            else if (!uint.TryParse(settings["CompressionLevel"], out compressionLevel) || compressionLevel > 8)
            {
                throw new InvalidSettingException(string.Format(CultureInfo.CurrentCulture,
                                                                Resources.SampleEncoderBadCompressionLevel, settings["CompressionLevel"]));
            }
            _encoder.SetCompressionLevel(compressionLevel);

            var vorbisCommentBlock = new NativeVorbisCommentBlock();

            foreach (var field in new MetadataToVorbisCommentAdapter(metadata))
            {
                vorbisCommentBlock.Append(field.Key, field.Value);
            }
            _metadataBlocks.Add(vorbisCommentBlock);

            // Add a seek table, unless SeekPointInterval = 0:
            uint seekPointInterval;

            if (string.IsNullOrEmpty(settings["SeekPointInterval"]))
            {
                seekPointInterval = 10;
            }
            else if (!uint.TryParse(settings["SeekPointInterval"], out seekPointInterval))
            {
                throw new InvalidSettingException(string.Format(CultureInfo.CurrentCulture,
                                                                Resources.SampleEncoderBadSeekPointInterval, settings["SeekPointInterval"]));
            }
            if (seekPointInterval > 0)
            {
                _metadataBlocks.Add(new NativeSeekTableBlock(
                                        (int)Math.Ceiling(audioInfo.SampleCount / (double)audioInfo.SampleRate / seekPointInterval),
                                        audioInfo.SampleCount));
            }

            // Add a picture block, if cover art is available:
            if (metadata.CoverArt != null)
            {
                _metadataBlocks.Add(new CoverArtToPictureBlockAdapter(metadata.CoverArt));
            }

            _encoder.SetMetadata(_metadataBlocks);

            EncoderInitStatus initStatus = _encoder.Initialize();

            if (initStatus != EncoderInitStatus.Ok)
            {
                throw new IOException(string.Format(CultureInfo.CurrentCulture,
                                                    Resources.SampleEncoderInitializationError, initStatus));
            }
        }