static OggPacket GetCommentPacket(MetadataDictionary metadata)
        {
            Contract.Requires(metadata != null);

            var comment = new VorbisComment();

            try
            {
                SafeNativeMethods.VorbisCommentInitialize(out comment);

                foreach (var item in new MetadataToVorbisCommentAdapter(metadata))
                {
                    // The key and value need to be marshaled as null-terminated UTF-8 strings:
                    var keyBytes = new byte[Encoding.UTF8.GetByteCount(item.Key) + 1];
                    Encoding.UTF8.GetBytes(item.Key, 0, item.Key.Length, keyBytes, 0);

                    var valueBytes = new byte[Encoding.UTF8.GetByteCount(item.Value) + 1];
                    Encoding.UTF8.GetBytes(item.Value, 0, item.Value.Length, valueBytes, 0);

                    SafeNativeMethods.VorbisCommentAddTag(ref comment, keyBytes, valueBytes);
                }

                OggPacket result;
                if (SafeNativeMethods.VorbisCommentHeaderOut(ref comment, out result) != 0)
                {
                    throw new IOException(Resources.MetadataEncoderHeaderOutError);
                }

                return(result);
            }
            finally
            {
                SafeNativeMethods.VorbisCommentClear(ref comment);
            }
        }
Beispiel #2
0
        internal void HeaderOut(ref VorbisComment comment, out OggPacket first, out OggPacket second, out OggPacket third)
        {
            Result result = SafeNativeMethods.VorbisAnalysisHeaderOut(_dspState, ref comment,
                                                                      out first, out second, out third);

            if (result != Result.Ok)
            {
                throw new IOException(string.Format(CultureInfo.CurrentCulture,
                                                    Resources.NativeVorbisEncoderHeaderOutError, result));
            }
        }
        internal void HeaderIn(ref VorbisComment comment, ref OggPacket packet)
        {
            Result result = SafeNativeMethods.VorbisSynthesisHeaderIn(_info, ref comment, ref packet);

            switch (result)
            {
            case Result.Ok:
                return;

            case Result.NotVorbisError:
                throw new UnsupportedAudioException(Resources.NativeVorbisDecoderNotVorbisError);

            default:
                throw new IOException(string.Format(CultureInfo.CurrentCulture, Resources.NativeVorbisDecoderHeaderInError, result));
            }
        }
        void WriteHeader(MetadataDictionary metadata, Stream stream)
        {
            Contract.Requires(metadata != null);
            Contract.Requires(stream != null);
            Contract.Requires(stream.CanWrite);

            var vorbisComment = new VorbisComment();

            try
            {
                SafeNativeMethods.VorbisCommentInitialize(out vorbisComment);

                foreach (var item in new MetadataToVorbisCommentAdapter(metadata))
                {
                    // The key and value need to be marshaled as null-terminated UTF-8 strings:
                    var keyBytes = new byte[Encoding.UTF8.GetByteCount(item.Key) + 1];
                    Encoding.UTF8.GetBytes(item.Key, 0, item.Key.Length, keyBytes, 0);

                    var valueBytes = new byte[Encoding.UTF8.GetByteCount(item.Value) + 1];
                    Encoding.UTF8.GetBytes(item.Value, 0, item.Value.Length, valueBytes, 0);

                    SafeNativeMethods.VorbisCommentAddTag(ref vorbisComment, keyBytes, valueBytes);
                }

                OggPacket first;
                OggPacket second;
                OggPacket third;
                _encoder.HeaderOut(ref vorbisComment, out first, out second, out third);

                _oggStream.PacketIn(ref first);
                _oggStream.PacketIn(ref second);
                _oggStream.PacketIn(ref third);
            }
            finally
            {
                SafeNativeMethods.VorbisCommentClear(ref vorbisComment);
            }

            OggPage page;

            while (_oggStream.Flush(out page))
            {
                WritePage(page, stream);
            }
        }
        internal VorbisCommentToMetadataAdapter(VorbisComment vorbisComment)
        {
            var commentLengths = new int[vorbisComment.Comments];

            Marshal.Copy(vorbisComment.CommentLengths, commentLengths, 0, commentLengths.Length);

            var commentPtrs = new IntPtr[vorbisComment.Comments];

            Marshal.Copy(vorbisComment.UserComments, commentPtrs, 0, commentPtrs.Length);

            for (var i = 0; i < vorbisComment.Comments; i++)
            {
                var commentBytes = new byte[commentLengths[i]];
                Marshal.Copy(commentPtrs[i], commentBytes, 0, commentLengths[i]);

                string[] comment = Encoding.UTF8.GetString(commentBytes).Split(new[] { '=' }, 2);

                Contract.Assert(comment.Length == 2);

                // The track number and count may be packed into the same comment:
                switch (comment[0])
                {
                case "TRACKNUMBER":
                    string[] segments = comment[1].Split('/');
                    base["TrackNumber"] = segments[0];
                    if (segments.Length > 1)
                    {
                        base["TrackCount"] = segments[1];
                    }
                    break;

                case "DATE":
                case "YEAR":
                    // The DATE comment may contain a full date, or only the year:
                    DateTime result;
                    if (DateTime.TryParse(comment[1], CultureInfo.CurrentCulture,
                                          DateTimeStyles.NoCurrentDateDefault, out result) && result.Year >= 1000)
                    {
                        base["Day"]   = result.Day.ToString(CultureInfo.InvariantCulture);
                        base["Month"] = result.Month.ToString(CultureInfo.InvariantCulture);
                        base["Year"]  = result.Year.ToString(CultureInfo.InvariantCulture);
                    }
                    else
                    {
                        base["Year"] = comment[1];
                    }
                    break;

                case "METADATA_BLOCK_PICTURE":
                    var picture = new MetadataBlockPicture(comment[1]);
                    if (picture.Type == PictureType.CoverFront || picture.Type == PictureType.Other)
                    {
                        try
                        {
                            CoverArt = new CoverArt(picture.Data);
                        }
                        catch (UnsupportedCoverArtException)
                        { }
                    }
                    break;

                case "COVERART":
                    try
                    {
                        // Deprecated way to store cover art:
                        CoverArt = new CoverArt(Convert.FromBase64String(comment[1]));
                    }
                    catch (UnsupportedCoverArtException)
                    { }
                    break;

                default:
                    string mappedKey;
                    if (_map.TryGetValue(comment[0], out mappedKey))
                    {
                        base[mappedKey] = comment[1];
                    }
                    break;
                }
            }
        }
Beispiel #6
0
        public AudioInfo ReadAudioInfo(Stream stream)
        {
            Contract.Ensures(Contract.Result <AudioInfo>() != null);

            var buffer = new byte[4096];

            using (var decoder = new NativeVorbisDecoder())
            {
                NativeOggStream oggStream     = null;
                var             vorbisComment = new VorbisComment();

                try
                {
                    SafeNativeMethods.VorbisCommentInitialize(out vorbisComment);

                    using (var sync = new NativeOggSync())
                    {
                        OggPage page;

                        do
                        {
                            // Read from the buffer into a page:
                            while (sync.PageOut(out page) != 1)
                            {
                                int bytesRead = stream.Read(buffer, 0, buffer.Length);
                                if (bytesRead == 0)
                                {
                                    throw new IOException(Resources.ReadError);
                                }

                                IntPtr nativeBuffer = sync.Buffer(bytesRead);
                                Marshal.Copy(buffer, 0, nativeBuffer, bytesRead);

                                sync.Wrote(bytesRead);
                            }

                            if (oggStream == null)
                            {
                                oggStream = new NativeOggStream(SafeNativeMethods.OggPageGetSerialNumber(ref page));
                            }

                            oggStream.PageIn(ref page);

                            OggPacket packet;
                            while (oggStream.PacketOut(out packet) == 1)
                            {
                                decoder.HeaderIn(ref vorbisComment, ref packet);

                                VorbisInfo info = decoder.GetInfo();
                                return(new AudioInfo(string.Format(CultureInfo.CurrentCulture,
                                                                   "{0}kbps Ogg Vorbis", info.BitrateNominal / 1000), info.Channels, 0, info.Rate, 0));
                            }
                        } while (SafeNativeMethods.OggPageEndOfStream(ref page) == 0);

                        throw new IOException(Resources.EndOfStreamError);
                    }
                }
                finally
                {
                    oggStream?.Dispose();

                    SafeNativeMethods.VorbisCommentClear(ref vorbisComment);
                }
            }
        }
Beispiel #7
0
 internal static extern void VorbisCommentInitialize(out VorbisComment comment);
Beispiel #8
0
 internal static extern Result VorbisAnalysisHeaderOut(IntPtr dspState, ref VorbisComment comment, out OggPacket first, out OggPacket second, out OggPacket third);
Beispiel #9
0
 internal static extern Result VorbisSynthesisHeaderIn(IntPtr info, ref VorbisComment comment, ref OggPacket packet);
Beispiel #10
0
 internal static extern void VorbisCommentClear(ref VorbisComment comment);
Beispiel #11
0
 internal static extern int VorbisCommentHeaderOut(ref VorbisComment comment, out OggPacket packet);
Beispiel #12
0
 internal static extern void VorbisCommentAddTag(ref VorbisComment comment, byte[] tag, byte[] contents);
Beispiel #13
0
        public MetadataDictionary ReadMetadata(Stream stream)
        {
            Contract.Ensures(Contract.Result <MetadataDictionary>() != null);

            var buffer = new byte[4096];

            using (var decoder = new NativeVorbisDecoder())
            {
                NativeOggStream oggStream     = null;
                var             vorbisComment = new VorbisComment();

                try
                {
                    SafeNativeMethods.VorbisCommentInitialize(out vorbisComment);

                    using (var sync = new NativeOggSync())
                    {
                        OggPage page;

                        do
                        {
                            // Read from the buffer into a page:
                            while (sync.PageOut(out page) != 1)
                            {
                                int bytesRead = stream.Read(buffer, 0, buffer.Length);
                                if (bytesRead == 0)
                                {
                                    throw new IOException(Resources.ReadError);
                                }

                                IntPtr nativeBuffer = sync.Buffer(bytesRead);
                                Marshal.Copy(buffer, 0, nativeBuffer, bytesRead);

                                sync.Wrote(bytesRead);
                            }

                            if (oggStream == null)
                            {
                                oggStream = new NativeOggStream(SafeNativeMethods.OggPageGetSerialNumber(ref page));
                            }

                            oggStream.PageIn(ref page);

                            OggPacket packet;
                            while (oggStream.PacketOut(out packet) == 1)
                            {
                                decoder.HeaderIn(ref vorbisComment, ref packet);

                                if (packet.PacketNumber == 1)
                                {
                                    return(new VorbisCommentToMetadataAdapter(vorbisComment));
                                }
                            }
                        } while (SafeNativeMethods.OggPageEndOfStream(ref page) == 0);

                        throw new IOException(Resources.EndOfStreamError);
                    }
                }
                finally
                {
                    oggStream?.Dispose();

                    SafeNativeMethods.VorbisCommentClear(ref vorbisComment);
                }
            }
        }