Initial commit
This commit is contained in:
commit
262601edb8
2025 files changed
+218754
No files matched your search
@@ -0,0 +1,191 @@
|
||||
//
|
||||
// Block.cs: Represents a Flac metadata block.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2007 Brian Nickel
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License version
|
||||
// 2.1 as published by the Free Software Foundation.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
// USA
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace TagLib.Flac
|
||||
{
|
||||
/// <summary>
|
||||
/// This class represents a Flac metadata block.
|
||||
/// </summary>
|
||||
public class Block
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Contains the block header.
|
||||
/// </summary>
|
||||
readonly BlockHeader header;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="Block" /> with a specified header and internal
|
||||
/// data.
|
||||
/// </summary>
|
||||
/// <param name="header">
|
||||
/// A <see cref="BlockHeader" /> object containing the
|
||||
/// header to use for the new instance.
|
||||
/// </param>
|
||||
/// <param name="data">
|
||||
/// A <see cref="ByteVector" /> object containing the data
|
||||
/// to be contained in the new instance.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="data" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
/// <exception cref="CorruptFileException">
|
||||
/// The size of <paramref name="data" /> does not match the
|
||||
/// size specified in <paramref name="header" />.
|
||||
/// </exception>
|
||||
public Block (BlockHeader header, ByteVector data)
|
||||
{
|
||||
if (data == null)
|
||||
throw new ArgumentNullException (nameof (data));
|
||||
|
||||
if (header.BlockSize != data.Count)
|
||||
throw new CorruptFileException ("Data count not equal to block size.");
|
||||
|
||||
this.header = header;
|
||||
Data = data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="Block" /> with of a specified type and internal
|
||||
/// data.
|
||||
/// </summary>
|
||||
/// <param name="type">
|
||||
/// A <see cref="BlockType" /> value indicating the type of
|
||||
/// data stored in <paramref name="data" />.
|
||||
/// </param>
|
||||
/// <param name="data">
|
||||
/// A <see cref="ByteVector" /> object containing the data
|
||||
/// to be contained in the new instance.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="data" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public Block (BlockType type, ByteVector data)
|
||||
{
|
||||
if (data == null)
|
||||
throw new ArgumentNullException (nameof (data));
|
||||
|
||||
header = new BlockHeader (type, (uint)data.Count);
|
||||
|
||||
Data = data;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of data contained in the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="BlockType" /> value indicating the type of
|
||||
/// data contained in <see cref="Data" />.
|
||||
/// </value>
|
||||
public BlockType Type {
|
||||
get { return header.BlockType; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not the block represented by the current
|
||||
/// instance is the last metadata block in the Flac stream.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <see langword="true" /> if the block represented by the
|
||||
/// current instance was the last one to appear in the file
|
||||
/// and is followed immediately by the audio data, or <see
|
||||
/// langword="false" /> if another block appears after the
|
||||
/// current one or the block was not read from disk.
|
||||
/// </value>
|
||||
public bool IsLastBlock {
|
||||
get { return header.IsLastBlock; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of the data contained in the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
public uint DataSize {
|
||||
get { return header.BlockSize; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the total size of the block represented by the
|
||||
/// current instance as it appears on disk.
|
||||
/// </summary>
|
||||
public uint TotalSize {
|
||||
get { return DataSize + BlockHeader.Size; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the data contained in the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="ByteVector" /> object containing the data
|
||||
/// stored in the current instance.
|
||||
/// </value>
|
||||
public ByteVector Data { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Renders the current instance as a raw Flac metadata
|
||||
/// block.
|
||||
/// </summary>
|
||||
/// <param name="isLastBlock">
|
||||
/// A <see cref="bool" /> value indicating whether or not the
|
||||
/// block is to be marked as the last metadata block.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector" /> object containing the
|
||||
/// rendered version of the current instance.
|
||||
/// </returns>
|
||||
public ByteVector Render (bool isLastBlock)
|
||||
{
|
||||
if (Data == null)
|
||||
throw new InvalidOperationException ("Cannot render empty blocks.");
|
||||
|
||||
ByteVector data = header.Render (isLastBlock);
|
||||
data.Add (Data);
|
||||
return data;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2b85066ddbb2e476dacfb9957cb823bc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,175 @@
|
||||
//
|
||||
// BlockHeader.cs:
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2007 Brian Nickel
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License version
|
||||
// 2.1 as published by the Free Software Foundation.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
// USA
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace TagLib.Flac
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the contents of a Flac block in <see cref="BlockHeader"
|
||||
/// />.
|
||||
/// </summary>
|
||||
public enum BlockType
|
||||
{
|
||||
/// <summary>
|
||||
/// The block contains stream information.
|
||||
/// </summary>
|
||||
StreamInfo = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The block contains padding.
|
||||
/// </summary>
|
||||
Padding,
|
||||
|
||||
/// <summary>
|
||||
/// The block contains application data.
|
||||
/// </summary>
|
||||
Application,
|
||||
|
||||
/// <summary>
|
||||
/// The block contains seek table.
|
||||
/// </summary>
|
||||
SeekTable,
|
||||
|
||||
/// <summary>
|
||||
/// The block contains a Xipp comment.
|
||||
/// </summary>
|
||||
XiphComment,
|
||||
|
||||
/// <summary>
|
||||
/// The block contains a cue sheet.
|
||||
/// </summary>
|
||||
CueSheet,
|
||||
|
||||
/// <summary>
|
||||
/// The block contains a picture.
|
||||
/// </summary>
|
||||
Picture
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This structure provides a representation of a Flac metadata block
|
||||
/// header structure.
|
||||
/// </summary>
|
||||
public struct BlockHeader
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// The size of a block header.
|
||||
/// </summary>
|
||||
public const uint Size = 4;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="BlockHeader" /> by reading a raw header from a <see
|
||||
/// cref="ByteVector" /> object.
|
||||
/// </summary>
|
||||
/// <param name="data">
|
||||
/// A <see cref="ByteVector" /> object containing a raw
|
||||
/// block header.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="data" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
/// <exception cref="CorruptFileException">
|
||||
/// <paramref name="data" /> contains less than 4 bytes.
|
||||
/// </exception>
|
||||
public BlockHeader (ByteVector data)
|
||||
{
|
||||
if (data == null)
|
||||
throw new ArgumentNullException (nameof (data));
|
||||
|
||||
if (data.Count < Size)
|
||||
throw new CorruptFileException ("Not enough data in Flac header.");
|
||||
|
||||
BlockType = (BlockType)(data[0] & 0x7f);
|
||||
IsLastBlock = (data[0] & 0x80) != 0;
|
||||
BlockSize = data.Mid (1, 3).ToUInt ();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="BlockHeader" /> for a specified block type and size.
|
||||
/// </summary>
|
||||
/// <param name="type">
|
||||
/// A <see cref="BlockType" /> value describing the contents
|
||||
/// of the block.
|
||||
/// </param>
|
||||
/// <param name="blockSize">
|
||||
/// A <see cref="uint" /> value containing the block data
|
||||
/// size minus the size of the header.
|
||||
/// </param>
|
||||
public BlockHeader (BlockType type, uint blockSize)
|
||||
{
|
||||
BlockType = type;
|
||||
IsLastBlock = false;
|
||||
BlockSize = blockSize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renderes the current instance as a raw Flac block header.
|
||||
/// </summary>
|
||||
/// <param name="isLastBlock">
|
||||
/// A <see cref="bool" /> value specifying whether or not the
|
||||
/// header is the last header of the file.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector" /> object containing the
|
||||
/// rendered header.
|
||||
/// </returns>
|
||||
public ByteVector Render (bool isLastBlock)
|
||||
{
|
||||
ByteVector data = ByteVector.FromUInt (BlockSize);
|
||||
data[0] = (byte)(BlockType + (isLastBlock ? 0x80 : 0));
|
||||
return data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of block described by the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="BlockType" /> value describing the block
|
||||
/// type.
|
||||
/// </value>
|
||||
public BlockType BlockType { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not the block is the last in the file.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <see langword="true" /> if the block is the last in the
|
||||
/// file; otherwise <see langword="false" />.
|
||||
/// </value>
|
||||
public bool IsLastBlock { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of the block described by the current
|
||||
/// instance, minus the block header.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="uint" /> value containing the size of the
|
||||
/// block, minus the header.
|
||||
/// </value>
|
||||
public uint BlockSize { get; private set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bdff34f1d4c26490c97cebf8fd90d80d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,665 @@
|
||||
//
|
||||
// File.cs: Provides tagging and properties support for Xiph's Flac audio files.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Original Source:
|
||||
// flacfile.cpp from TagLib
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
// Copyright (C) 2003-2004 Allan Sandfeld Jensen (Original Implementation)
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License version
|
||||
// 2.1 as published by the Free Software Foundation.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
// USA
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace TagLib.Flac
|
||||
{
|
||||
/// <summary>
|
||||
/// This class extends <see cref="TagLib.NonContainer.File" /> to
|
||||
/// provide tagging and properties support for Xiph's Flac audio
|
||||
/// files.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// A <see cref="TagLib.Ogg.XiphComment" /> will be added
|
||||
/// automatically to any file that doesn't contain one. This change
|
||||
/// does not effect the physical file until <see cref="Save" /> is
|
||||
/// called and can be reversed using the following method:
|
||||
/// <code>file.RemoveTags (file.TagTypes & ~file.TagTypesOnDisk);</code>
|
||||
/// </remarks>
|
||||
[SupportedMimeType ("taglib/flac", "flac")]
|
||||
[SupportedMimeType ("audio/x-flac")]
|
||||
[SupportedMimeType ("application/x-flac")]
|
||||
[SupportedMimeType ("audio/flac")]
|
||||
public class File : TagLib.NonContainer.File
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Contains the Flac metadata tag.
|
||||
/// </summary>
|
||||
Metadata metadata;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the combination of all file tags.
|
||||
/// </summary>
|
||||
CombinedTag tag;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the Flac header block.
|
||||
/// </summary>
|
||||
ByteVector header_block;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the stream start position.
|
||||
/// </summary>
|
||||
long stream_start;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="File" /> for a specified path in the local file
|
||||
/// system and specified read style.
|
||||
/// </summary>
|
||||
/// <param name="path">
|
||||
/// A <see cref="string" /> object containing the path of the
|
||||
/// file to use in the new instance.
|
||||
/// </param>
|
||||
/// <param name="propertiesStyle">
|
||||
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||
/// of accuracy to read the media properties, or <see
|
||||
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="path" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public File (string path, ReadStyle propertiesStyle)
|
||||
: base (path, propertiesStyle)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="File" /> for a specified path in the local file
|
||||
/// system with an average read style.
|
||||
/// </summary>
|
||||
/// <param name="path">
|
||||
/// A <see cref="string" /> object containing the path of the
|
||||
/// file to use in the new instance.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="path" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public File (string path)
|
||||
: base (path)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="File" /> for a specified file abstraction and
|
||||
/// specified read style.
|
||||
/// </summary>
|
||||
/// <param name="abstraction">
|
||||
/// A <see cref="TagLib.File.IFileAbstraction" /> object to use when
|
||||
/// reading from and writing to the file.
|
||||
/// </param>
|
||||
/// <param name="propertiesStyle">
|
||||
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||
/// of accuracy to read the media properties, or <see
|
||||
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="abstraction" /> is <see langword="null"
|
||||
/// />.
|
||||
/// </exception>
|
||||
public File (IFileAbstraction abstraction,
|
||||
ReadStyle propertiesStyle)
|
||||
: base (abstraction, propertiesStyle)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="File" /> for a specified file abstraction with an
|
||||
/// average read style.
|
||||
/// </summary>
|
||||
/// <param name="abstraction">
|
||||
/// A <see cref="TagLib.File.IFileAbstraction" /> object to use when
|
||||
/// reading from and writing to the file.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="abstraction" /> is <see langword="null"
|
||||
/// />.
|
||||
/// </exception>
|
||||
public File (IFileAbstraction abstraction)
|
||||
: base (abstraction)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets a abstract representation of all tags stored in the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="TagLib.Tag" /> object representing all tags
|
||||
/// stored in the current instance.
|
||||
/// </value>
|
||||
public override Tag Tag {
|
||||
get { return tag; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Saves the changes made in the current instance to the
|
||||
/// file it represents.
|
||||
/// </summary>
|
||||
public override void Save ()
|
||||
{
|
||||
// Boilerplate
|
||||
PreSave ();
|
||||
|
||||
Mode = AccessMode.Write;
|
||||
try {
|
||||
// Update the tags at the beginning of the file.
|
||||
long metadata_start = StartTag.Write ();
|
||||
|
||||
// Get all the blocks, but don't read the data for ones
|
||||
// we're filling with stored data.
|
||||
IList<Block> old_blocks = ReadBlocks (ref metadata_start,
|
||||
out var metadata_end, BlockMode.Blacklist,
|
||||
BlockType.XiphComment, BlockType.Picture);
|
||||
|
||||
// Create new vorbis comments is they don't exist.
|
||||
GetTag (TagTypes.Xiph, true);
|
||||
|
||||
// Create new blocks and add the basics.
|
||||
var new_blocks = new List<Block> ();
|
||||
new_blocks.Add (old_blocks[0]);
|
||||
|
||||
// Add blocks we don't deal with from the file.
|
||||
foreach (Block block in old_blocks)
|
||||
if (block.Type != BlockType.StreamInfo &&
|
||||
block.Type != BlockType.XiphComment &&
|
||||
block.Type != BlockType.Picture &&
|
||||
block.Type != BlockType.Padding)
|
||||
new_blocks.Add (block);
|
||||
|
||||
new_blocks.Add (new Block (BlockType.XiphComment,
|
||||
(GetTag (TagTypes.Xiph, true) as Ogg.XiphComment).Render (false)));
|
||||
|
||||
foreach (IPicture picture in metadata.Pictures) {
|
||||
if (picture == null)
|
||||
continue;
|
||||
|
||||
new_blocks.Add (new Block (BlockType.Picture,
|
||||
new Picture (picture).Render ()));
|
||||
}
|
||||
|
||||
// Get the length of the blocks.
|
||||
long length = 0;
|
||||
foreach (Block block in new_blocks)
|
||||
length += block.TotalSize;
|
||||
|
||||
// Find the padding size to avoid trouble. If that fails
|
||||
// make some.
|
||||
long padding_size = metadata_end - metadata_start -
|
||||
BlockHeader.Size - length;
|
||||
if (padding_size < 0)
|
||||
padding_size = 1024 * 4;
|
||||
|
||||
// Add a padding block.
|
||||
if (padding_size != 0)
|
||||
new_blocks.Add (new Block (BlockType.Padding,
|
||||
new ByteVector ((int)padding_size)));
|
||||
|
||||
// Render the blocks.
|
||||
ByteVector block_data = new ByteVector ();
|
||||
for (int i = 0; i < new_blocks.Count; i++)
|
||||
block_data.Add (new_blocks[i].Render (
|
||||
i == new_blocks.Count - 1));
|
||||
|
||||
// Update the blocks.
|
||||
Insert (block_data, metadata_start, metadata_end -
|
||||
metadata_start);
|
||||
|
||||
// Update the tags at the end of the file.
|
||||
EndTag.Write ();
|
||||
|
||||
TagTypesOnDisk = TagTypes;
|
||||
} finally {
|
||||
Mode = AccessMode.Closed;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a tag of a specified type from the current instance,
|
||||
/// optionally creating a new tag if possible.
|
||||
/// </summary>
|
||||
/// <param name="type">
|
||||
/// A <see cref="TagLib.TagTypes" /> value indicating the
|
||||
/// type of tag to read.
|
||||
/// </param>
|
||||
/// <param name="create">
|
||||
/// A <see cref="bool" /> value specifying whether or not to
|
||||
/// try and create the tag if one is not found.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="Tag" /> object containing the tag that was
|
||||
/// found in or added to the current instance. If no
|
||||
/// matching tag was found and none was created, <see
|
||||
/// langword="null" /> is returned.
|
||||
/// </returns>
|
||||
public override Tag GetTag (TagTypes type, bool create)
|
||||
{
|
||||
switch (type) {
|
||||
case TagTypes.Xiph:
|
||||
return metadata.GetComment (create, tag);
|
||||
|
||||
case TagTypes.FlacMetadata:
|
||||
return metadata;
|
||||
}
|
||||
|
||||
Tag t = (base.Tag as TagLib.NonContainer.Tag).GetTag (type);
|
||||
|
||||
if (t != null || !create)
|
||||
return t;
|
||||
|
||||
switch (type) {
|
||||
case TagTypes.Id3v1:
|
||||
return EndTag.AddTag (type, Tag);
|
||||
|
||||
case TagTypes.Id3v2:
|
||||
return StartTag.AddTag (type, Tag);
|
||||
|
||||
case TagTypes.Ape:
|
||||
return EndTag.AddTag (type, Tag);
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a set of tag types from the current instance.
|
||||
/// </summary>
|
||||
/// <param name="types">
|
||||
/// A bitwise combined <see cref="TagLib.TagTypes" /> value
|
||||
/// containing tag types to be removed from the file.
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// In order to remove all tags from a file, pass <see
|
||||
/// cref="TagTypes.AllTags" /> as <paramref name="types" />.
|
||||
/// </remarks>
|
||||
public override void RemoveTags (TagTypes types)
|
||||
{
|
||||
if ((types & TagTypes.Xiph) != 0)
|
||||
metadata.RemoveComment ();
|
||||
|
||||
if ((types & TagTypes.FlacMetadata) != 0)
|
||||
metadata.Clear ();
|
||||
|
||||
base.RemoveTags (types);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
/// <summary>
|
||||
/// Reads format specific information at the start of the
|
||||
/// file.
|
||||
/// </summary>
|
||||
/// <param name="start">
|
||||
/// A <see cref="long" /> value containing the seek position
|
||||
/// at which the tags end and the media data begins.
|
||||
/// </param>
|
||||
/// <param name="propertiesStyle">
|
||||
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||
/// of accuracy to read the media properties, or <see
|
||||
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||
/// </param>
|
||||
protected override void ReadStart (long start, ReadStyle propertiesStyle)
|
||||
{
|
||||
var blocks = ReadBlocks (ref start, out var end, BlockMode.Whitelist, BlockType.StreamInfo, BlockType.XiphComment, BlockType.Picture);
|
||||
metadata = new Metadata (blocks);
|
||||
|
||||
TagTypesOnDisk |= metadata.TagTypes;
|
||||
|
||||
if ((propertiesStyle & ReadStyle.Average) != 0) {
|
||||
// Check that the first block is a
|
||||
// METADATA_BLOCK_STREAMINFO.
|
||||
if (blocks.Count == 0 || blocks[0].Type != BlockType.StreamInfo)
|
||||
throw new CorruptFileException ("FLAC stream does not begin with StreamInfo.");
|
||||
|
||||
// The stream exists from the end of the last
|
||||
// block to the end of the file.
|
||||
stream_start = end;
|
||||
header_block = blocks[0].Data;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads format specific information at the end of the
|
||||
/// file.
|
||||
/// </summary>
|
||||
/// <param name="end">
|
||||
/// A <see cref="long" /> value containing the seek position
|
||||
/// at which the media data ends and the tags begin.
|
||||
/// </param>
|
||||
/// <param name="propertiesStyle">
|
||||
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||
/// of accuracy to read the media properties, or <see
|
||||
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||
/// </param>
|
||||
protected override void ReadEnd (long end, ReadStyle propertiesStyle)
|
||||
{
|
||||
tag = new CombinedTag (metadata, base.Tag);
|
||||
GetTag (TagTypes.Xiph, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the audio properties from the file represented by
|
||||
/// the current instance.
|
||||
/// </summary>
|
||||
/// <param name="start">
|
||||
/// A <see cref="long" /> value containing the seek position
|
||||
/// at which the tags end and the media data begins.
|
||||
/// </param>
|
||||
/// <param name="end">
|
||||
/// A <see cref="long" /> value containing the seek position
|
||||
/// at which the media data ends and the tags begin.
|
||||
/// </param>
|
||||
/// <param name="propertiesStyle">
|
||||
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||
/// of accuracy to read the media properties, or <see
|
||||
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="TagLib.Properties" /> object describing the
|
||||
/// media properties of the file represented by the current
|
||||
/// instance.
|
||||
/// </returns>
|
||||
protected override Properties ReadProperties (long start, long end, ReadStyle propertiesStyle)
|
||||
{
|
||||
var header = new StreamHeader (header_block, end - stream_start);
|
||||
return new Properties (TimeSpan.Zero, header);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Private Methods
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether or not the block types passed into
|
||||
/// <see cref="ReadBlocks" /> are to be white-listed or
|
||||
/// black-listed.
|
||||
/// </summary>
|
||||
enum BlockMode
|
||||
{
|
||||
/// <summary>
|
||||
/// All block types except those provided are to be
|
||||
/// returned.
|
||||
/// </summary>
|
||||
Blacklist,
|
||||
|
||||
/// <summary>
|
||||
/// Only those block types provides should be
|
||||
/// returned.
|
||||
/// </summary>
|
||||
Whitelist
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads all metadata blocks starting from the current
|
||||
/// instance, starting at a specified position.
|
||||
/// </summary>
|
||||
/// <param name="start">
|
||||
/// A <see cref="long" /> value reference specifying the
|
||||
/// position at which to start searching for the blocks. This
|
||||
/// will be updated to the position of the first block.
|
||||
/// </param>
|
||||
/// <param name="end">
|
||||
/// A <see cref="long" /> value reference updated to the
|
||||
/// position at which the last block ends.
|
||||
/// </param>
|
||||
/// <param name="mode">
|
||||
/// A <see cref="BlockMode" /> value indicating whether to
|
||||
/// white-list or black-list the contents of <paramref
|
||||
/// name="types" />.
|
||||
/// </param>
|
||||
/// <param name="types">
|
||||
/// A <see cref="T:BlockType[]" /> containing the types to look
|
||||
/// for or not look for as specified by <paramref name="mode"
|
||||
/// />.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="T:System.Collections.Generic.IList`1" /> object containing the blocks
|
||||
/// read from the current instance.
|
||||
/// </returns>
|
||||
/// <exception cref="CorruptFileException">
|
||||
/// "<c>fLaC</c>" could not be found.
|
||||
/// </exception>
|
||||
IList<Block> ReadBlocks (ref long start, out long end, BlockMode mode, params BlockType[] types)
|
||||
{
|
||||
List<Block> blocks = new List<Block> ();
|
||||
|
||||
long start_position = Find ("fLaC", start);
|
||||
|
||||
if (start_position < 0)
|
||||
throw new CorruptFileException ("FLAC stream not found at starting position.");
|
||||
|
||||
end = start = start_position + 4;
|
||||
|
||||
Seek (start);
|
||||
|
||||
BlockHeader header;
|
||||
|
||||
do {
|
||||
header = new BlockHeader (ReadBlock ((int)BlockHeader.Size));
|
||||
|
||||
bool found = false;
|
||||
foreach (BlockType type in types)
|
||||
if (header.BlockType == type) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((mode == BlockMode.Whitelist && found) ||
|
||||
(mode == BlockMode.Blacklist && !found))
|
||||
blocks.Add (new Block (header, ReadBlock ((int)header.BlockSize)));
|
||||
else
|
||||
Seek (header.BlockSize, System.IO.SeekOrigin.Current);
|
||||
|
||||
end += header.BlockSize + BlockHeader.Size;
|
||||
} while (!header.IsLastBlock);
|
||||
|
||||
return blocks;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// This class extends <see cref="CombinedTag" /> to provide support
|
||||
/// for reading and writing FLAC metadata boxes.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// At this point, only Xiph Comments and pictures are supported.
|
||||
/// </remarks>
|
||||
public class Metadata : CombinedTag
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains the pictures.
|
||||
/// </summary>
|
||||
readonly List<IPicture> pictures = new List<IPicture> ();
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="Metadata" /> using a collection of blocks.
|
||||
/// </summary>
|
||||
/// <param name="blocks">
|
||||
/// A <see cref="T:System.Collections.Generic.List`1" /> object containing <see
|
||||
/// cref="Block" /> objects to use in the new instance.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="blocks" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
[Obsolete ("Use Metadata(IEnumerable<Block>)")]
|
||||
public Metadata (List<Block> blocks)
|
||||
: this (blocks as IEnumerable<Block>)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="Metadata" /> using a collection of blocks.
|
||||
/// </summary>
|
||||
/// <param name="blocks">
|
||||
/// A <see cref="T:System.Collections.Generic.IEnumerable`1" /> object enumerating <see
|
||||
/// cref="Block" /> objects to use in the new instance.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="blocks" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public Metadata (IEnumerable<Block> blocks)
|
||||
{
|
||||
if (blocks == null)
|
||||
throw new ArgumentNullException (nameof (blocks));
|
||||
|
||||
foreach (Block block in blocks) {
|
||||
if (block.Data.Count == 0)
|
||||
continue;
|
||||
|
||||
if (block.Type == BlockType.XiphComment)
|
||||
AddTag (new Ogg.XiphComment (block.Data));
|
||||
else if (block.Type == BlockType.Picture)
|
||||
pictures.Add (new Picture (block.Data));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the first Xiph comment stored in the current
|
||||
/// instance, optionally creating one if necessary.
|
||||
/// </summary>
|
||||
/// <param name="create">
|
||||
/// A <see cref="bool" /> value indicating whether or not a
|
||||
/// comment should be added if one cannot be found.
|
||||
/// </param>
|
||||
/// <param name="copy">
|
||||
/// A <see cref="Tag" /> object containing the source tag to
|
||||
/// copy the values from, or <see langword="null" /> to not
|
||||
/// copy values.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="Ogg.XiphComment" /> object containing the
|
||||
/// tag that was found in or added to the current instance.
|
||||
/// If no matching tag was found and none was created, <see
|
||||
/// langword="null" /> is returned.
|
||||
/// </returns>
|
||||
public Ogg.XiphComment GetComment (bool create, Tag copy)
|
||||
{
|
||||
foreach (Tag t in Tags)
|
||||
if (t is Ogg.XiphComment)
|
||||
return t as Ogg.XiphComment;
|
||||
|
||||
if (!create)
|
||||
return null;
|
||||
|
||||
Ogg.XiphComment c = new Ogg.XiphComment ();
|
||||
|
||||
if (copy != null)
|
||||
copy.CopyTo (c, true);
|
||||
|
||||
AddTag (c);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes all child Xiph Comments from the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
public void RemoveComment ()
|
||||
{
|
||||
Ogg.XiphComment c;
|
||||
|
||||
while ((c = GetComment (false, null)) != null)
|
||||
RemoveTag (c);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the tag types contained in the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A bitwise combined <see cref="TagLib.TagTypes" /> value
|
||||
/// containing the tag types stored in the current instance.
|
||||
/// </value>
|
||||
public override TagTypes TagTypes {
|
||||
get { return TagTypes.FlacMetadata | base.TagTypes; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets a collection of pictures associated with
|
||||
/// the media represented by the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="T:IPicture[]" /> containing a collection of
|
||||
/// pictures associated with the media represented by the
|
||||
/// current instance or an empty array if none are present.
|
||||
/// </value>
|
||||
public override IPicture[] Pictures {
|
||||
get { return pictures.ToArray (); }
|
||||
set {
|
||||
pictures.Clear ();
|
||||
if (value != null)
|
||||
pictures.AddRange (value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears the values stored in the current instance.
|
||||
/// </summary>
|
||||
public override void Clear ()
|
||||
{
|
||||
pictures.Clear ();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2398030dd33fc28e38d41d1975d6aa92
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,268 @@
|
||||
//
|
||||
// Picture.cs:
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2007 Brian Nickel
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License version
|
||||
// 2.1 as published by the Free Software Foundation.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
// USA
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace TagLib.Flac
|
||||
{
|
||||
/// <summary>
|
||||
/// This class implements <see cref="IPicture" /> to provide support
|
||||
/// for reading and writing Flac picture metadata.
|
||||
/// </summary>
|
||||
public class Picture : IPicture
|
||||
{
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="Picture" /> by reading the contents of a raw Flac
|
||||
/// image structure.
|
||||
/// </summary>
|
||||
/// <param name="data">
|
||||
/// A <see cref="ByteVector" /> object containing the raw
|
||||
/// Flac image.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="data" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
/// <exception cref="CorruptFileException">
|
||||
/// <paramref name="data" /> contains less than 32 bytes.
|
||||
/// </exception>
|
||||
public Picture (ByteVector data)
|
||||
{
|
||||
if (data == null)
|
||||
throw new ArgumentNullException (nameof (data));
|
||||
|
||||
if (data.Count < 32)
|
||||
throw new CorruptFileException ("Data must be at least 32 bytes long");
|
||||
|
||||
int pos = 0;
|
||||
Type = (PictureType)data.Mid (pos, 4).ToUInt ();
|
||||
pos += 4;
|
||||
|
||||
int mimetype_length = (int)data.Mid (pos, 4).ToUInt ();
|
||||
pos += 4;
|
||||
|
||||
MimeType = data.ToString (StringType.Latin1, pos,
|
||||
mimetype_length);
|
||||
pos += mimetype_length;
|
||||
|
||||
int description_length = (int)data.Mid (pos, 4)
|
||||
.ToUInt ();
|
||||
pos += 4;
|
||||
|
||||
Description = data.ToString (StringType.UTF8, pos,
|
||||
description_length);
|
||||
pos += description_length;
|
||||
|
||||
Width = (int)data.Mid (pos, 4).ToUInt ();
|
||||
pos += 4;
|
||||
|
||||
Height = (int)data.Mid (pos, 4).ToUInt ();
|
||||
pos += 4;
|
||||
|
||||
ColorDepth = (int)data.Mid (pos, 4).ToUInt ();
|
||||
pos += 4;
|
||||
|
||||
IndexedColors = (int)data.Mid (pos, 4).ToUInt ();
|
||||
pos += 4;
|
||||
|
||||
int data_length = (int)data.Mid (pos, 4).ToUInt ();
|
||||
pos += 4;
|
||||
|
||||
Data = data.Mid (pos, data_length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="Picture" /> by copying the properties of a <see
|
||||
/// cref="IPicture" /> object.
|
||||
/// </summary>
|
||||
/// <param name="picture">
|
||||
/// A <see cref="IPicture" /> object to use for the new
|
||||
/// instance.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="picture" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public Picture (IPicture picture)
|
||||
{
|
||||
if (picture == null)
|
||||
throw new ArgumentNullException (nameof (picture));
|
||||
|
||||
Type = picture.Type;
|
||||
MimeType = picture.MimeType;
|
||||
Filename = picture.Filename;
|
||||
Description = picture.Description;
|
||||
Data = picture.Data;
|
||||
|
||||
if (!(picture is Picture flac_picture))
|
||||
return;
|
||||
|
||||
Width = flac_picture.Width;
|
||||
Height = flac_picture.Height;
|
||||
ColorDepth = flac_picture.ColorDepth;
|
||||
IndexedColors = flac_picture.IndexedColors;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Renders the current instance as a raw Flac picture.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector" /> object containing the
|
||||
/// rendered version of the current instance.
|
||||
/// </returns>
|
||||
public ByteVector Render ()
|
||||
{
|
||||
var data = new ByteVector {
|
||||
ByteVector.FromUInt ((uint)Type)
|
||||
};
|
||||
|
||||
var mime_data = ByteVector.FromString (MimeType,
|
||||
StringType.Latin1);
|
||||
data.Add (ByteVector.FromUInt ((uint)mime_data.Count));
|
||||
data.Add (mime_data);
|
||||
|
||||
var decription_data = ByteVector.FromString (Description, StringType.UTF8);
|
||||
data.Add (ByteVector.FromUInt ((uint)decription_data.Count));
|
||||
data.Add (decription_data);
|
||||
|
||||
data.Add (ByteVector.FromUInt ((uint)Width));
|
||||
data.Add (ByteVector.FromUInt ((uint)Height));
|
||||
data.Add (ByteVector.FromUInt ((uint)ColorDepth));
|
||||
data.Add (ByteVector.FromUInt ((uint)IndexedColors));
|
||||
|
||||
data.Add (ByteVector.FromUInt ((uint)Data.Count));
|
||||
data.Add (Data);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the mime-type of the picture data
|
||||
/// stored in the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="string" /> object containing the mime-type
|
||||
/// of the picture data stored in the current instance.
|
||||
/// </value>
|
||||
public string MimeType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the type of content visible in the picture
|
||||
/// stored in the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="PictureType" /> containing the type of
|
||||
/// content visible in the picture stored in the current
|
||||
/// instance.
|
||||
/// </value>
|
||||
public PictureType Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets a filename of the picture stored in the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="string" /> object containing a fielname, with
|
||||
/// extension, of the picture stored in the current instance.
|
||||
/// </value>
|
||||
public string Filename { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets a description of the picture stored in the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="string" /> object containing a description
|
||||
/// of the picture stored in the current instance.
|
||||
/// </value>
|
||||
public string Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the picture data stored in the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="ByteVector" /> object containing the picture
|
||||
/// data stored in the current instance.
|
||||
/// </value>
|
||||
public ByteVector Data { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the width of the picture in the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing width of the
|
||||
/// picture stored in the current instance.
|
||||
/// </value>
|
||||
public int Width { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the height of the picture in the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing height of the
|
||||
/// picture stored in the current instance.
|
||||
/// </value>
|
||||
public int Height { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the color depth of the picture in the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing color depth of the
|
||||
/// picture stored in the current instance.
|
||||
/// </value>
|
||||
public int ColorDepth { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the number of indexed colors in the picture
|
||||
/// in the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing number of indexed
|
||||
/// colors in the picture, or zero if the picture is not
|
||||
/// stored in an indexed format.
|
||||
/// </value>
|
||||
public int IndexedColors { get; set; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 948078d7fd9adb2fe995d19ef3157a39
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,234 @@
|
||||
//
|
||||
// StreamHeader.cs:
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Original Source:
|
||||
// flagproperties.cpp from TagLib
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
// Copyright (C) 2003 Allan Sandfeld Jensen (Original Implementation)
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License version
|
||||
// 2.1 as published by the Free Software Foundation.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
// USA
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace TagLib.Flac
|
||||
{
|
||||
/// <summary>
|
||||
/// This structure implements <see cref="IAudioCodec" /> and provides
|
||||
/// information about a Flac audio stream.
|
||||
/// </summary>
|
||||
public struct StreamHeader : IAudioCodec, ILosslessAudioCodec
|
||||
{
|
||||
#region Private Properties
|
||||
|
||||
/// <summary>
|
||||
/// Contains the flags.
|
||||
/// </summary>
|
||||
readonly uint flags;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the low portion of the length.
|
||||
/// </summary>
|
||||
readonly uint low_length;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the stream length.
|
||||
/// </summary>
|
||||
readonly long stream_length;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="StreamHeader" /> by reading a raw stream header
|
||||
/// structure and using the stream length.
|
||||
/// </summary>
|
||||
/// <param name="data">
|
||||
/// A <see cref="ByteVector" /> object containing the raw
|
||||
/// stream header.
|
||||
/// </param>
|
||||
/// <param name="streamLength">
|
||||
/// A <see cref="long" /> value containing the length of the
|
||||
/// stream.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="data" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
/// <exception cref="CorruptFileException">
|
||||
/// <paramref name="data" /> contains less than 18 bytes.
|
||||
/// </exception>
|
||||
public StreamHeader (ByteVector data, long streamLength)
|
||||
{
|
||||
if (data == null)
|
||||
throw new ArgumentNullException (nameof (data));
|
||||
|
||||
if (data.Count < 18)
|
||||
throw new CorruptFileException ("Not enough data in FLAC header.");
|
||||
|
||||
stream_length = streamLength;
|
||||
flags = data.Mid (10, 4).ToUInt (true);
|
||||
low_length = data.Mid (14, 4).ToUInt (true);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the duration of the media represented by the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="TimeSpan" /> containing the duration of the
|
||||
/// media represented by the current instance.
|
||||
/// </value>
|
||||
public TimeSpan Duration {
|
||||
get {
|
||||
return (AudioSampleRate > 0 && stream_length > 0)
|
||||
? TimeSpan.FromSeconds (
|
||||
low_length /
|
||||
(double)AudioSampleRate +
|
||||
HighLength) :
|
||||
TimeSpan.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the bitrate of the audio represented by the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing a bitrate of the
|
||||
/// audio represented by the current instance.
|
||||
/// </value>
|
||||
public int AudioBitrate {
|
||||
get {
|
||||
return (int)(Duration > TimeSpan.Zero ?
|
||||
((stream_length * 8L) / Duration.TotalSeconds) / 1000 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the sample rate of the audio represented by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing the sample rate of
|
||||
/// the audio represented by the current instance.
|
||||
/// </value>
|
||||
public int AudioSampleRate {
|
||||
get { return (int)(flags >> 12); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of channels in the audio represented by
|
||||
/// the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing the number of
|
||||
/// channels in the audio represented by the current
|
||||
/// instance.
|
||||
/// </value>
|
||||
public int AudioChannels {
|
||||
get { return (int)(((flags >> 9) & 7) + 1); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the types of media represented by the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Always <see cref="MediaTypes.Audio" />.
|
||||
/// </value>
|
||||
public MediaTypes MediaTypes {
|
||||
get { return MediaTypes.Audio; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the sample width of the audio represented by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing the sample width of
|
||||
/// the audio represented by the current instance.
|
||||
/// </value>
|
||||
[Obsolete ("This property is depreciated, use BitsPerSample instead")]
|
||||
public int AudioSampleWidth {
|
||||
get { return BitsPerSample; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of bits per sample in the audio
|
||||
/// represented by the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing the number of bits
|
||||
/// per sample in the audio represented by the current
|
||||
/// instance.
|
||||
/// </value>
|
||||
public int BitsPerSample {
|
||||
get { return (int)(((flags >> 4) & 31) + 1); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a text description of the media represented by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="string" /> object containing a description
|
||||
/// of the media represented by the current instance.
|
||||
/// </value>
|
||||
public string Description {
|
||||
get { return "Flac Audio"; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Private Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets a high portion of the length of the audio
|
||||
/// represented by the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="uint" /> value containing the high portion
|
||||
/// of the length.
|
||||
/// </value>
|
||||
uint HighLength {
|
||||
get {
|
||||
// The last 4 bits are the most significant 4
|
||||
// bits for the 36 bit stream length in samples.
|
||||
// (Audio files measured in days)
|
||||
return (uint)(AudioSampleRate > 0 ?
|
||||
(((flags & 0xf) << 28) /
|
||||
AudioSampleRate) << 4 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 246c726d80e7bc9c68f191ac3d18e936
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in new issue
Block a user