Esempio n. 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();
            }
        }
Esempio n. 2
0
        static void UpdateMetadata(NativeMetadataIterator iterator, NativeVorbisCommentBlock newComments, NativePictureBlock newPicture)
        {
            Contract.Requires(iterator != null);
            Contract.Requires(newComments != null);

            var metadataInserted = false;
            var pictureInserted  = false;

            do
            {
                switch ((MetadataType)Marshal.ReadInt32(iterator.GetBlock()))
                {
                // Replace the existing Vorbis comment:
                case MetadataType.VorbisComment:
                    if (!iterator.DeleteBlock(false))
                    {
                        throw new IOException(Resources.MetadataEncoderDeleteError);
                    }
                    if (!iterator.InsertBlockAfter(newComments.Handle))
                    {
                        throw new IOException(Resources.MetadataEncoderInsertBlockError);
                    }
                    metadataInserted = true;
                    break;

                // Replace the existing Picture block:
                case MetadataType.Picture:
                    if (!iterator.DeleteBlock(false))
                    {
                        throw new IOException(Resources.MetadataEncoderDeleteError);
                    }
                    if (newPicture != null && !iterator.InsertBlockAfter(newPicture.Handle))
                    {
                        throw new IOException(Resources.MetadataEncoderInsertBlockError);
                    }
                    pictureInserted = true;
                    break;

                // Delete any padding:
                case MetadataType.Padding:
                    if (!iterator.DeleteBlock(false))
                    {
                        throw new IOException(Resources.MetadataEncoderDeleteError);
                    }
                    break;
                }
            } while (iterator.Next());

            // If there was no existing metadata block to replace, insert it now:
            if (!metadataInserted && !iterator.InsertBlockAfter(newComments.Handle))
            {
                throw new IOException(Resources.MetadataEncoderInsertBlockError);
            }

            // If there was no existing picture block to replace, and a new one is available, insert it now:
            if (newPicture != null && !pictureInserted && !iterator.InsertBlockAfter(newPicture.Handle))
            {
                throw new IOException(Resources.MetadataEncoderInsertBlockError);
            }

            newComments.ReleaseHandleOwnership();
            newPicture?.ReleaseHandleOwnership();
        }