Initial commit
This commit is contained in:
commit
262601edb8
2025 files changed
+218754
No files matched your search
@@ -0,0 +1,363 @@
|
||||
//
|
||||
// EndTag.cs: Provides support for accessing and modifying a collection of tags
|
||||
// appearing at the end of a file.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2007 Brian Nickel
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace TagLib.NonContainer
|
||||
{
|
||||
/// <summary>
|
||||
/// This class extends <see cref="CombinedTag" />, providing support
|
||||
/// for accessing and modifying a collection of tags appearing at the
|
||||
/// end of a file.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>This class is used by <see cref="TagLib.NonContainer.File"
|
||||
/// /> to read all the tags appearing at the end of the file but
|
||||
/// could be used by other classes. It currently supports ID3v1,
|
||||
/// ID3v2, and APE tags.</para>
|
||||
/// </remarks>
|
||||
public class EndTag : CombinedTag
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Contains the file to operate on.
|
||||
/// </summary>
|
||||
readonly TagLib.File file;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the number of bytes that must be read to
|
||||
/// hold all applicable indicators.
|
||||
/// </summary>
|
||||
static readonly int read_size = (int)Math.Max (Math.Max (Ape.Footer.Size, Id3v2.Footer.Size), Id3v1.Tag.Size);
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="EndTag" /> for a specified <see cref="TagLib.File"
|
||||
/// />.
|
||||
/// </summary>
|
||||
/// <param name="file">
|
||||
/// A <see cref="TagLib.File" /> object on which the new
|
||||
/// instance will perform its operations.
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// Constructing a new instance does not automatically read
|
||||
/// the contents from the disk. <see cref="Read" /> must be
|
||||
/// called to read the tags.
|
||||
/// </remarks>
|
||||
public EndTag (TagLib.File file)
|
||||
{
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the total size of the tags located at the end of the
|
||||
/// file by reading from the file.
|
||||
/// </summary>
|
||||
public long TotalSize {
|
||||
get {
|
||||
long start = file.Length;
|
||||
|
||||
while (ReadTagInfo (ref start) != TagTypes.None)
|
||||
;
|
||||
|
||||
return file.Length - start;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Reads the tags stored at the end of the file into the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="long" /> value indicating the seek position
|
||||
/// in the file at which the read tags begin. This also
|
||||
/// marks the seek position at which the media ends.
|
||||
/// </returns>
|
||||
public long Read (ReadStyle style)
|
||||
{
|
||||
TagLib.Tag tag;
|
||||
ClearTags ();
|
||||
long start = file.Length;
|
||||
|
||||
while ((tag = ReadTag (ref start, style)) != null)
|
||||
InsertTag (0, tag);
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders the tags contained in the current instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector" /> object containing the
|
||||
/// physical representation of the tags stored in the current
|
||||
/// instance.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// The tags are rendered in the order that they are stored
|
||||
/// in the current instance.
|
||||
/// </remarks>
|
||||
public ByteVector Render ()
|
||||
{
|
||||
ByteVector data = new ByteVector ();
|
||||
foreach (TagLib.Tag t in Tags) {
|
||||
if (t is Ape.Tag tag)
|
||||
data.Add (tag.Render ());
|
||||
else if (t is Id3v2.Tag tag1)
|
||||
data.Add (tag1.Render ());
|
||||
else if (t is Id3v1.Tag tag2)
|
||||
data.Add (tag2.Render ());
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the tags contained in the current instance to the
|
||||
/// end of the file that created it, overwriting the existing
|
||||
/// tags.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="long" /> value indicating the seek position
|
||||
/// in the file at which the written tags begin. This also
|
||||
/// marks the seek position at which the media ends.
|
||||
/// </returns>
|
||||
public long Write ()
|
||||
{
|
||||
long total_size = TotalSize;
|
||||
ByteVector data = Render ();
|
||||
file.Insert (data, file.Length - total_size, total_size);
|
||||
return file.Length - data.Count;
|
||||
}
|
||||
|
||||
/// <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 void RemoveTags (TagTypes types)
|
||||
{
|
||||
for (int i = Tags.Length - 1; i >= 0; i--) {
|
||||
var tag = Tags[i];
|
||||
if (types == TagTypes.AllTags || (tag.TagTypes & types) == tag.TagTypes) {
|
||||
RemoveTag (tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a tag of a specified type to the current instance,
|
||||
/// optionally copying values from an existing type.
|
||||
/// </summary>
|
||||
/// <param name="type">
|
||||
/// A <see cref="TagTypes" /> value specifying the type of
|
||||
/// tag to add to the current instance. At the time of this
|
||||
/// writing, this is limited to <see cref="TagTypes.Ape" />,
|
||||
/// <see cref="TagTypes.Id3v1" />, and <see
|
||||
/// cref="TagTypes.Id3v2" />.
|
||||
/// </param>
|
||||
/// <param name="copy">
|
||||
/// A <see cref="TagLib.Tag" /> to copy values from using
|
||||
/// <see cref="TagLib.Tag.CopyTo" />, or <see
|
||||
/// langword="null" /> if no tag is to be copied.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The <see cref="TagLib.Tag" /> object added to the current
|
||||
/// instance, or <see langword="null" /> if it couldn't be
|
||||
/// created.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// ID3v2 tags are added at the end of the current instance,
|
||||
/// while other tags are added to the beginning.
|
||||
/// </remarks>
|
||||
public TagLib.Tag AddTag (TagTypes type, TagLib.Tag copy)
|
||||
{
|
||||
TagLib.Tag tag = null;
|
||||
|
||||
if (type == TagTypes.Id3v1) {
|
||||
tag = new TagLib.Id3v1.Tag ();
|
||||
} else if (type == TagTypes.Id3v2) {
|
||||
Id3v2.Tag tag32 = new Id3v2.Tag {
|
||||
Version = 4
|
||||
};
|
||||
tag32.Flags |= Id3v2.HeaderFlags.FooterPresent;
|
||||
tag = tag32;
|
||||
} else if (type == TagTypes.Ape) {
|
||||
tag = new TagLib.Ape.Tag ();
|
||||
}
|
||||
|
||||
if (tag != null) {
|
||||
copy?.CopyTo (tag, true);
|
||||
|
||||
if (type == TagTypes.Id3v1)
|
||||
AddTag (tag);
|
||||
else
|
||||
InsertTag (0, tag);
|
||||
}
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Private Methods
|
||||
|
||||
/// <summary>
|
||||
/// Reads a tag ending at a specified position and moves the
|
||||
/// cursor to its start position.
|
||||
/// </summary>
|
||||
/// <param name="end">
|
||||
/// A <see cref="long" /> value reference specifying at what
|
||||
/// position the potential tag ends at. If a tag is found,
|
||||
/// this value will be updated to the position at which the
|
||||
/// found tag starts.
|
||||
/// </param>
|
||||
/// <param name="style">
|
||||
/// A <see cref="ReadStyle"/> value specifying how the media
|
||||
/// data is to be read into the current instance.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="TagLib.Tag" /> object representing the tag
|
||||
/// found at the specified position, or <see langword="null"
|
||||
/// /> if no tag was found.
|
||||
/// </returns>
|
||||
TagLib.Tag ReadTag (ref long end, ReadStyle style)
|
||||
{
|
||||
long start = end;
|
||||
TagTypes type = ReadTagInfo (ref start);
|
||||
TagLib.Tag tag = null;
|
||||
|
||||
try {
|
||||
switch (type) {
|
||||
case TagTypes.Ape:
|
||||
tag = new TagLib.Ape.Tag (file, end - Ape.Footer.Size);
|
||||
break;
|
||||
case TagTypes.Id3v2:
|
||||
tag = new TagLib.Id3v2.Tag (file, start, style);
|
||||
break;
|
||||
case TagTypes.Id3v1:
|
||||
tag = new TagLib.Id3v1.Tag (file, start);
|
||||
break;
|
||||
}
|
||||
|
||||
end = start;
|
||||
} catch (CorruptFileException) {
|
||||
}
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks for a tag ending at a specified position and moves
|
||||
/// the cursor to its start position.
|
||||
/// </summary>
|
||||
/// <param name="position">
|
||||
/// A <see cref="long" /> value reference specifying at what
|
||||
/// position the potential tag ends. If a tag is found,
|
||||
/// this value will be updated to the position at which the
|
||||
/// found tag starts.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="TagLib.TagTypes" /> value specifying the
|
||||
/// type of tag found at the specified position, or <see
|
||||
/// cref="TagTypes.None" /> if no tag was found.
|
||||
/// </returns>
|
||||
TagTypes ReadTagInfo (ref long position)
|
||||
{
|
||||
if (position - read_size < 0)
|
||||
return TagTypes.None;
|
||||
|
||||
file.Seek (position - read_size);
|
||||
ByteVector data = file.ReadBlock (read_size);
|
||||
|
||||
try {
|
||||
int offset = (int)(data.Count - Ape.Footer.Size);
|
||||
if (data.ContainsAt (Ape.Footer.FileIdentifier, offset)) {
|
||||
Ape.Footer footer = new Ape.Footer (data.Mid (offset));
|
||||
|
||||
// If the complete tag size is zero or
|
||||
// the tag is a header, this indicates
|
||||
// some sort of corruption.
|
||||
if (footer.CompleteTagSize == 0 ||
|
||||
(footer.Flags & Ape.FooterFlags.IsHeader) != 0)
|
||||
return TagTypes.None;
|
||||
|
||||
position -= footer.CompleteTagSize;
|
||||
return TagTypes.Ape;
|
||||
}
|
||||
|
||||
offset = (int)(data.Count - Id3v2.Footer.Size);
|
||||
if (data.ContainsAt (Id3v2.Footer.FileIdentifier,
|
||||
offset)) {
|
||||
var footer = new Id3v2.Footer (data.Mid (offset));
|
||||
|
||||
position -= footer.CompleteTagSize;
|
||||
return TagTypes.Id3v2;
|
||||
}
|
||||
|
||||
if (data.StartsWith (Id3v1.Tag.FileIdentifier)) {
|
||||
position -= Id3v1.Tag.Size;
|
||||
return TagTypes.Id3v1;
|
||||
}
|
||||
} catch (CorruptFileException) {
|
||||
}
|
||||
|
||||
return TagTypes.None;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b20e4c11d4e603cf7b5f02f321bc6c4e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,398 @@
|
||||
//
|
||||
// File.cs: Provides tagging and properties for files that contain an
|
||||
// indeterminite number of tags at their beginning or end.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2007 Brian Nickel
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace TagLib.NonContainer
|
||||
{
|
||||
/// <summary>
|
||||
/// This abstract class extends <see cref="TagLib.File" /> to provide
|
||||
/// tagging and properties for files that contain an indeterminite
|
||||
/// number of tags at their beginning or end.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>When extending this class, <see cref="ReadStart" />, <see
|
||||
/// cref="ReadEnd" />, and <see cref="ReadProperties" /> should be
|
||||
/// overrided methods that read the format specific information from
|
||||
/// the file.</para>
|
||||
/// <para>The file is read upon construction in the following
|
||||
/// manner:</para>
|
||||
/// <list type="number">
|
||||
/// <item><term>The file is opened for reading.</term></item>
|
||||
/// <item><term>The tags at the start of the file are
|
||||
/// read.</term></item>
|
||||
/// <item><term><see cref="ReadStart" /> is called.</term></item>
|
||||
/// <item><term>The tags at the end of the file are
|
||||
/// read.</term></item>
|
||||
/// <item><term><see cref="ReadEnd" /> is called.</term></item>
|
||||
/// <item><term>If reading with a style other than <see
|
||||
/// cref="ReadStyle.None" />, <see cref="ReadProperties" /> is
|
||||
/// called.</term></item>
|
||||
/// <item><term>The file is closed.</term></item>
|
||||
/// </list>
|
||||
/// </remarks>
|
||||
public abstract class File : TagLib.File
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Contains the tags.
|
||||
/// </summary>
|
||||
Tag tag;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the media properties.
|
||||
/// </summary>
|
||||
Properties properties;
|
||||
|
||||
#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>
|
||||
protected File (string path, ReadStyle propertiesStyle)
|
||||
: base (path)
|
||||
{
|
||||
Read (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>
|
||||
protected File (string path) : this (path, ReadStyle.Average)
|
||||
{
|
||||
}
|
||||
|
||||
/// <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>
|
||||
protected File (IFileAbstraction abstraction, ReadStyle propertiesStyle)
|
||||
: base (abstraction)
|
||||
{
|
||||
Read (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>
|
||||
protected File (IFileAbstraction abstraction)
|
||||
: this (abstraction, ReadStyle.Average)
|
||||
{
|
||||
}
|
||||
|
||||
#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 TagLib.Tag Tag {
|
||||
get { return tag; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the media properties of the file represented by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="TagLib.Properties" /> object containing the
|
||||
/// media properties of the file represented by the current
|
||||
/// instance.
|
||||
/// </value>
|
||||
public override Properties Properties {
|
||||
get { return properties; }
|
||||
}
|
||||
|
||||
#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 {
|
||||
tag.Write (out var start, out var end);
|
||||
InvariantStartPosition = start;
|
||||
InvariantEndPosition = end;
|
||||
TagTypesOnDisk = TagTypes;
|
||||
} finally {
|
||||
Mode = AccessMode.Closed;
|
||||
}
|
||||
}
|
||||
|
||||
/// <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)
|
||||
{
|
||||
tag.RemoveTags (types);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Protected Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the collection of tags appearing at the start of the
|
||||
/// file.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="TagLib.NonContainer.StartTag" /> storing the
|
||||
/// tags for the start of the file.
|
||||
/// </value>
|
||||
protected StartTag StartTag {
|
||||
get { return tag.StartTag; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the collection of tags appearing at the end of the
|
||||
/// file.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="TagLib.NonContainer.EndTag" /> storing the
|
||||
/// tags for the end of the file.
|
||||
/// </value>
|
||||
protected EndTag EndTag {
|
||||
get { return tag.EndTag; }
|
||||
}
|
||||
|
||||
#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>
|
||||
/// <remarks>
|
||||
/// This method is called by the constructor immediately
|
||||
/// after the tags at the start of the file have been read
|
||||
/// and as such (so the internal seek mechanism is close to
|
||||
/// the start). It should be used for reading any content
|
||||
/// specific information, such as an audio header from the
|
||||
/// start of the file.
|
||||
/// </remarks>
|
||||
protected virtual void ReadStart (long start, ReadStyle propertiesStyle)
|
||||
{
|
||||
}
|
||||
|
||||
/// <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>
|
||||
/// <remarks>
|
||||
/// This method is called by the constructor immediately
|
||||
/// after the tags at the end of the file have been read
|
||||
/// and as such (so the internal seek mechanism is close to
|
||||
/// the end). It should be used for reading any content
|
||||
/// specific information, such as an audio header from the
|
||||
/// end of the file.
|
||||
/// </remarks>
|
||||
protected virtual void ReadEnd (long end, ReadStyle propertiesStyle)
|
||||
{
|
||||
}
|
||||
|
||||
/// <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>
|
||||
/// <remarks>
|
||||
/// This method is called ONLY IF the file is constructed
|
||||
/// with a read style other than <see cref="ReadStyle.None"
|
||||
/// />, and as such MUST NOT return <see langword="null" />.
|
||||
/// It is guaranteed that <see cref="ReadStart" /> and <see
|
||||
/// cref="ReadEnd" /> will have been called first and this
|
||||
/// method should be strictly used to perform final
|
||||
/// processing on already read data.
|
||||
/// </remarks>
|
||||
protected abstract Properties ReadProperties (long start, long end, ReadStyle propertiesStyle);
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Private Methods
|
||||
|
||||
/// <summary>
|
||||
/// Reads the file with a specified read style.
|
||||
/// </summary>
|
||||
/// <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>
|
||||
void Read (ReadStyle propertiesStyle)
|
||||
{
|
||||
Mode = AccessMode.Read;
|
||||
try {
|
||||
tag = new Tag (this);
|
||||
|
||||
// Read the tags and property data at the beginning of
|
||||
// the file.
|
||||
InvariantStartPosition = tag.ReadStart (propertiesStyle);
|
||||
TagTypesOnDisk |= StartTag.TagTypes;
|
||||
ReadStart (InvariantStartPosition, propertiesStyle);
|
||||
|
||||
// Read the tags and property data at the end of the
|
||||
// file.
|
||||
InvariantEndPosition =
|
||||
(InvariantStartPosition == Length) ?
|
||||
Length : tag.ReadEnd (propertiesStyle);
|
||||
TagTypesOnDisk |= EndTag.TagTypes;
|
||||
ReadEnd (InvariantEndPosition, propertiesStyle);
|
||||
|
||||
// Read the audio properties.
|
||||
properties = (propertiesStyle & ReadStyle.Average) != 0 ?
|
||||
ReadProperties (InvariantStartPosition,
|
||||
InvariantEndPosition, propertiesStyle) :
|
||||
null;
|
||||
} finally {
|
||||
Mode = AccessMode.Closed;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 91aa532d414f80daf872bb59170f7f74
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,328 @@
|
||||
//
|
||||
// StartTag.cs: Provides support for accessing and modifying a collection of
|
||||
// tags appearing at the start of a file.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2007 Brian Nickel
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace TagLib.NonContainer
|
||||
{
|
||||
/// <summary>
|
||||
/// This class extends <see cref="CombinedTag" />, providing support
|
||||
/// for accessing and modifying a collection of tags appearing at the
|
||||
/// start of a file.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>This class is used by <see cref="TagLib.NonContainer.File"
|
||||
/// /> to read all the tags appearing at the start of the file but
|
||||
/// could be used by other classes. It currently supports ID3v2
|
||||
/// and APE tags.</para>
|
||||
/// </remarks>
|
||||
public class StartTag : CombinedTag
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Contains the file to operate on.
|
||||
/// </summary>
|
||||
readonly TagLib.File file;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the number of bytes that must be read to
|
||||
/// hold all applicable indicators.
|
||||
/// </summary>
|
||||
readonly int read_size = (int)Math.Max (Ape.Footer.Size, Id3v2.Header.Size);
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="StartTag" /> for a specified <see
|
||||
/// cref="TagLib.File" />.
|
||||
/// </summary>
|
||||
/// <param name="file">
|
||||
/// A <see cref="TagLib.File" /> object on which the new
|
||||
/// instance will perform its operations.
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// Constructing a new instance does not automatically read
|
||||
/// the contents from the disk. <see cref="Read" /> must be
|
||||
/// called to read the tags.
|
||||
/// </remarks>
|
||||
public StartTag (TagLib.File file)
|
||||
{
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the total size of the tags located at the end of the
|
||||
/// file by reading from the file.
|
||||
/// </summary>
|
||||
public long TotalSize {
|
||||
get {
|
||||
long size = 0;
|
||||
|
||||
while (ReadTagInfo (ref size) != TagTypes.None)
|
||||
;
|
||||
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Reads the tags stored at the start of the file into the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="long" /> value indicating the seek position
|
||||
/// in the file at which the read tags end. This also
|
||||
/// marks the seek position at which the media begins.
|
||||
/// </returns>
|
||||
public long Read (ReadStyle style)
|
||||
{
|
||||
TagLib.Tag tag;
|
||||
ClearTags ();
|
||||
long end = 0;
|
||||
|
||||
while ((tag = ReadTag (ref end, style)) != null)
|
||||
AddTag (tag);
|
||||
|
||||
return end;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders the tags contained in the current instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector" /> object containing the
|
||||
/// physical representation of the tags stored in the current
|
||||
/// instance.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// The tags are rendered in the order that they are stored
|
||||
/// in the current instance.
|
||||
/// </remarks>
|
||||
public ByteVector Render ()
|
||||
{
|
||||
ByteVector data = new ByteVector ();
|
||||
foreach (TagLib.Tag t in Tags) {
|
||||
if (t is Ape.Tag)
|
||||
data.Add ((t as TagLib.Ape.Tag).Render ());
|
||||
else if (t is Id3v2.Tag)
|
||||
data.Add ((t as TagLib.Id3v2.Tag).Render ());
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the tags contained in the current instance to the
|
||||
/// beginning of the file that created it, overwriting the
|
||||
/// existing tags.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="long" /> value indicating the seek position
|
||||
/// in the file at which the written tags end. This also
|
||||
/// marks the seek position at which the media begins.
|
||||
/// </returns>
|
||||
public long Write ()
|
||||
{
|
||||
ByteVector data = Render ();
|
||||
file.Insert (data, 0, TotalSize);
|
||||
return data.Count;
|
||||
}
|
||||
|
||||
/// <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 void RemoveTags (TagTypes types)
|
||||
{
|
||||
for (int i = Tags.Length - 1; i >= 0; i--) {
|
||||
var tag = Tags[i];
|
||||
if (types == TagTypes.AllTags || (tag.TagTypes & types) == tag.TagTypes) {
|
||||
RemoveTag (tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a tag of a specified type to the current instance,
|
||||
/// optionally copying values from an existing type.
|
||||
/// </summary>
|
||||
/// <param name="type">
|
||||
/// A <see cref="TagTypes" /> value specifying the type of
|
||||
/// tag to add to the current instance. At the time of this
|
||||
/// writing, this is limited to <see cref="TagTypes.Ape" />
|
||||
/// and <see cref="TagTypes.Id3v2" />.
|
||||
/// </param>
|
||||
/// <param name="copy">
|
||||
/// A <see cref="TagLib.Tag" /> to copy values from using
|
||||
/// <see cref="TagLib.Tag.CopyTo" />, or <see
|
||||
/// langword="null" /> if no tag is to be copied.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The <see cref="TagLib.Tag" /> object added to the current
|
||||
/// instance, or <see langword="null" /> if it couldn't be
|
||||
/// created.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// ID3v2 tags are added at the end of the current instance,
|
||||
/// while other tags are added to the beginning.
|
||||
/// </remarks>
|
||||
public TagLib.Tag AddTag (TagTypes type, TagLib.Tag copy)
|
||||
{
|
||||
TagLib.Tag tag = null;
|
||||
|
||||
if (type == TagTypes.Id3v2) {
|
||||
tag = new TagLib.Id3v2.Tag ();
|
||||
} else if (type == TagTypes.Ape) {
|
||||
tag = new TagLib.Ape.Tag ();
|
||||
((Ape.Tag) tag).HeaderPresent = true;
|
||||
}
|
||||
|
||||
if (tag != null) {
|
||||
copy?.CopyTo (tag, true);
|
||||
|
||||
AddTag (tag);
|
||||
}
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Private Methods
|
||||
|
||||
/// <summary>
|
||||
/// Reads a tag starting at a specified position and moves the
|
||||
/// cursor to its start position.
|
||||
/// </summary>
|
||||
/// <param name="start">
|
||||
/// A <see cref="long" /> value reference specifying at what
|
||||
/// position the potential tag starts. If a tag is found,
|
||||
/// this value will be updated to the position at which the
|
||||
/// found tag ends.
|
||||
/// </param>
|
||||
/// <param name="style">
|
||||
/// A <see cref="ReadStyle"/> value specifying how the media
|
||||
/// data is to be read into the current instance.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="TagLib.Tag" /> object representing the tag
|
||||
/// found at the specified position, or <see langword="null"
|
||||
/// /> if no tag was found.
|
||||
/// </returns>
|
||||
TagLib.Tag ReadTag (ref long start, ReadStyle style)
|
||||
{
|
||||
long end = start;
|
||||
TagTypes type = ReadTagInfo (ref end);
|
||||
TagLib.Tag tag = null;
|
||||
|
||||
switch (type) {
|
||||
case TagTypes.Ape:
|
||||
tag = new TagLib.Ape.Tag (file, start);
|
||||
break;
|
||||
case TagTypes.Id3v2:
|
||||
tag = new TagLib.Id3v2.Tag (file, start, style);
|
||||
break;
|
||||
}
|
||||
|
||||
start = end;
|
||||
return tag;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks for a tag starting at a specified position and moves
|
||||
/// the cursor to its start position.
|
||||
/// </summary>
|
||||
/// <param name="position">
|
||||
/// A <see cref="long" /> value reference specifying at what
|
||||
/// position the potential tag starts. If a tag is found,
|
||||
/// this value will be updated to the position at which the
|
||||
/// found tag ends.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="TagLib.TagTypes" /> value specifying the
|
||||
/// type of tag found at the specified position, or <see
|
||||
/// cref="TagTypes.None" /> if no tag was found.
|
||||
/// </returns>
|
||||
TagTypes ReadTagInfo (ref long position)
|
||||
{
|
||||
file.Seek (position);
|
||||
ByteVector data = file.ReadBlock (read_size);
|
||||
|
||||
try {
|
||||
if (data.StartsWith (Ape.Footer.FileIdentifier)) {
|
||||
Ape.Footer footer =
|
||||
new Ape.Footer (data);
|
||||
|
||||
position += footer.CompleteTagSize;
|
||||
return TagTypes.Ape;
|
||||
}
|
||||
|
||||
if (data.StartsWith (Id3v2.Header.FileIdentifier)) {
|
||||
Id3v2.Header header =
|
||||
new Id3v2.Header (data);
|
||||
|
||||
position += header.CompleteTagSize;
|
||||
return TagTypes.Id3v2;
|
||||
}
|
||||
} catch (CorruptFileException) {
|
||||
}
|
||||
|
||||
return TagTypes.None;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4fffde839a40fa2dca6c46e99e9d8e66
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,246 @@
|
||||
//
|
||||
// Tag.cs: Combines StartTag and EndTag in such a way as their children appear
|
||||
// as its children.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2007 Brian Nickel
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace TagLib.NonContainer
|
||||
{
|
||||
/// <summary>
|
||||
/// This class extends <see cref="CombinedTag" />, combining <see
|
||||
/// cref="StartTag" /> and <see cref="EndTag" /> in such a way as
|
||||
/// their children appear as its children.
|
||||
/// </summary>
|
||||
public class Tag : CombinedTag
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="Tag" /> for a specified <see cref="TagLib.File" />.
|
||||
/// </summary>
|
||||
/// <param name="file">
|
||||
/// A <see cref="TagLib.File" /> object on which the new
|
||||
/// instance will perform its operations.
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// Constructing a new instance does not automatically read
|
||||
/// the contents from the disk. <see cref="Read" /> must be
|
||||
/// called to read the tags.
|
||||
/// </remarks>
|
||||
public Tag (File file)
|
||||
{
|
||||
StartTag = new StartTag (file);
|
||||
EndTag = new EndTag (file);
|
||||
AddTag (StartTag);
|
||||
AddTag (EndTag);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the collection of tags appearing at the start of the
|
||||
/// file.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="TagLib.NonContainer.StartTag" /> storing the
|
||||
/// tags for the start of the file.
|
||||
/// </value>
|
||||
public StartTag StartTag { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the collection of tags appearing at the end of the
|
||||
/// file.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="TagLib.NonContainer.EndTag" /> storing the
|
||||
/// tags for the end of the file.
|
||||
/// </value>
|
||||
public EndTag EndTag { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the tag types contained in the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A bitwise combined <see cref="TagLib.TagTypes" />
|
||||
/// containing the tag types contained in the current
|
||||
/// instance.
|
||||
/// </value>
|
||||
public override TagTypes TagTypes {
|
||||
get { return StartTag.TagTypes | EndTag.TagTypes; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the tags combined in the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="T:TagLib.Tag[]" /> containing the tags combined in
|
||||
/// the current instance.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// This contains the combined children of <see
|
||||
/// cref="Tag.StartTag" /> and <see cref="Tag.EndTag" />.
|
||||
/// </remarks>
|
||||
public override TagLib.Tag[] Tags {
|
||||
get {
|
||||
List<TagLib.Tag> tags = new List<TagLib.Tag> ();
|
||||
tags.AddRange (StartTag.Tags);
|
||||
tags.AddRange (EndTag.Tags);
|
||||
return tags.ToArray ();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Gets a tag of a specified type from the current instance.
|
||||
/// </summary>
|
||||
/// <param name="type">
|
||||
/// A <see cref="TagLib.TagTypes" /> value indicating the
|
||||
/// type of tag to read.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="Tag" /> object containing the tag that was
|
||||
/// found in the current instance. If no
|
||||
/// matching tag was found and none was created, <see
|
||||
/// langword="null" /> is returned.
|
||||
/// </returns>
|
||||
public TagLib.Tag GetTag (TagTypes type)
|
||||
{
|
||||
foreach (TagLib.Tag t in Tags) {
|
||||
if (type == TagTypes.Id3v1 && t is Id3v1.Tag)
|
||||
return t;
|
||||
|
||||
if (type == TagTypes.Id3v2 && t is Id3v2.Tag)
|
||||
return t;
|
||||
|
||||
if (type == TagTypes.Ape && t is Ape.Tag)
|
||||
return t;
|
||||
}
|
||||
|
||||
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 void RemoveTags (TagTypes types)
|
||||
{
|
||||
StartTag.RemoveTags (types);
|
||||
EndTag.RemoveTags (types);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the tags at the start and end of the file.
|
||||
/// </summary>
|
||||
/// <param name="start">
|
||||
/// A <see cref="long" /> value reference which will be set
|
||||
/// to contain the seek position in the file at which the
|
||||
/// tags at the start end. This also marks the seek position
|
||||
/// at which the media begins.
|
||||
/// </param>
|
||||
/// <param name="end">
|
||||
/// A <see cref="long" /> value reference which will be set
|
||||
/// to contain the seek position in the file at which the
|
||||
/// tags at the end begin. This also marks the seek position
|
||||
/// at which the media ends.
|
||||
/// </param>
|
||||
public void Read (out long start, out long end)
|
||||
{
|
||||
start = ReadStart (ReadStyle.None);
|
||||
end = ReadEnd (ReadStyle.None);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the tags stored at the start of the file into the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="long" /> value indicating the seek position
|
||||
/// in the file at which the read tags end. This also
|
||||
/// marks the seek position at which the media begins.
|
||||
/// </returns>
|
||||
public long ReadStart (ReadStyle style)
|
||||
{
|
||||
return StartTag.Read (style);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the tags stored at the end of the file into the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="long" /> value indicating the seek position
|
||||
/// in the file at which the read tags begin. This also
|
||||
/// marks the seek position at which the media ends.
|
||||
/// </returns>
|
||||
public long ReadEnd (ReadStyle style)
|
||||
{
|
||||
return EndTag.Read (style);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the tags to the start and end of the file.
|
||||
/// </summary>
|
||||
/// <param name="start">
|
||||
/// A <see cref="long" /> value reference which will be set
|
||||
/// to contain the new seek position in the file at which the
|
||||
/// tags at the start end. This also marks the seek position
|
||||
/// at which the media begins.
|
||||
/// </param>
|
||||
/// <param name="end">
|
||||
/// A <see cref="long" /> value reference which will be set
|
||||
/// to contain the new seek position in the file at which the
|
||||
/// tags at the end begin. This also marks the seek position
|
||||
/// at which the media ends.
|
||||
/// </param>
|
||||
public void Write (out long start, out long end)
|
||||
{
|
||||
start = StartTag.Write ();
|
||||
end = EndTag.Write ();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f989da13f485d8b94b8b06320aa07630
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in new issue
Block a user