2009-02-22 07:47:56 +00:00
|
|
|
//
|
|
|
|
|
// File.cs: Provides tagging and properties support for WavPack files.
|
|
|
|
|
//
|
|
|
|
|
// Author:
|
|
|
|
|
// Brian Nickel (brian.nickel@gmail.com)
|
|
|
|
|
//
|
|
|
|
|
// Original Source:
|
|
|
|
|
// wvfile.cpp from libtunepimp
|
|
|
|
|
//
|
|
|
|
|
// Copyright (C) 2006-2007 Brian Nickel
|
|
|
|
|
// Copyright (C) 2006 by Lukáš Lalinský (Original Implementation)
|
|
|
|
|
// Copyright (C) 2004 by 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;
|
2009-05-01 15:16:26 +00:00
|
|
|
using System.Collections.Generic;
|
2009-02-22 07:47:56 +00:00
|
|
|
using TagLib;
|
2013-06-05 03:02:43 -04:00
|
|
|
using CUETools.Codecs;
|
2009-02-22 07:47:56 +00:00
|
|
|
|
|
|
|
|
namespace TagLib.UserDefined {
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// This class extends <see cref="TagLib.NonContainer.File" /> to
|
|
|
|
|
/// provide tagging and properties support for user defined format files.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <remarks>
|
|
|
|
|
/// A <see cref="TagLib.Ape.Tag" /> will be added automatically to
|
|
|
|
|
/// any file that doesn't contain one. This change does not effect
|
|
|
|
|
/// the file and can be reversed using the following method:
|
|
|
|
|
/// <code>file.RemoveTags (file.TagTypes & ~file.TagTypesOnDisk);</code>
|
|
|
|
|
/// </remarks>
|
|
|
|
|
[SupportedMimeType("taglib/misc", "misc")]
|
|
|
|
|
public class File : TagLib.NonContainer.File
|
|
|
|
|
{
|
|
|
|
|
#region Private Fields
|
|
|
|
|
|
2013-06-05 03:02:43 -04:00
|
|
|
private CUEToolsTagger tagger;
|
2009-02-22 07:47:56 +00:00
|
|
|
|
|
|
|
|
#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>
|
2013-06-05 03:02:43 -04:00
|
|
|
public File (string path, ReadStyle propertiesStyle, CUEToolsTagger _tagger)
|
2009-02-22 07:47:56 +00:00
|
|
|
: base (path, propertiesStyle)
|
|
|
|
|
{
|
2009-05-01 15:16:26 +00:00
|
|
|
tagger = _tagger;
|
|
|
|
|
// Make sure we have a tag.
|
|
|
|
|
switch (tagger)
|
|
|
|
|
{
|
2013-06-05 03:02:43 -04:00
|
|
|
case CUEToolsTagger.APEv2:
|
2009-05-01 15:16:26 +00:00
|
|
|
GetTag(TagTypes.Ape, true);
|
|
|
|
|
break;
|
2013-06-05 03:02:43 -04:00
|
|
|
case CUEToolsTagger.ID3v2:
|
2009-02-19 06:26:56 +00:00
|
|
|
GetTag(TagTypes.Id3v2, true);
|
2009-05-01 15:16:26 +00:00
|
|
|
break;
|
|
|
|
|
}
|
2009-02-22 07:47:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <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" />.
|
2009-02-19 06:26:56 +00:00
|
|
|
/// </exception>
|
2013-06-05 03:02:43 -04:00
|
|
|
public File(string path, CUEToolsTagger _tagger)
|
2009-02-22 07:47:56 +00:00
|
|
|
: base(path)
|
|
|
|
|
{
|
2009-05-01 15:16:26 +00:00
|
|
|
tagger = _tagger;
|
|
|
|
|
// Make sure we have a tag.
|
|
|
|
|
switch (tagger)
|
|
|
|
|
{
|
2013-06-05 03:02:43 -04:00
|
|
|
case CUEToolsTagger.APEv2:
|
2009-05-01 15:16:26 +00:00
|
|
|
GetTag(TagTypes.Ape, true);
|
|
|
|
|
break;
|
2013-06-05 03:02:43 -04:00
|
|
|
case CUEToolsTagger.ID3v2:
|
2009-02-19 06:26:56 +00:00
|
|
|
GetTag(TagTypes.Id3v2, true);
|
2009-05-01 15:16:26 +00:00
|
|
|
break;
|
|
|
|
|
}
|
2009-02-22 07:47:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <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="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>
|
2009-02-19 06:26:56 +00:00
|
|
|
public File (File.IFileAbstraction abstraction,
|
2013-06-05 03:02:43 -04:00
|
|
|
ReadStyle propertiesStyle, CUEToolsTagger _tagger)
|
2009-02-22 07:47:56 +00:00
|
|
|
: base (abstraction, propertiesStyle)
|
|
|
|
|
{
|
2009-05-01 15:16:26 +00:00
|
|
|
tagger = _tagger;
|
|
|
|
|
// Make sure we have a tag.
|
|
|
|
|
switch (tagger)
|
|
|
|
|
{
|
2013-06-05 03:02:43 -04:00
|
|
|
case CUEToolsTagger.APEv2:
|
2009-05-01 15:16:26 +00:00
|
|
|
GetTag(TagTypes.Ape, true);
|
|
|
|
|
break;
|
2013-06-05 03:02:43 -04:00
|
|
|
case CUEToolsTagger.ID3v2:
|
2009-02-19 06:26:56 +00:00
|
|
|
GetTag(TagTypes.Id3v2, true);
|
2009-05-01 15:16:26 +00:00
|
|
|
break;
|
|
|
|
|
}
|
2009-02-22 07:47:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <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="IFileAbstraction" /> object to use when
|
|
|
|
|
/// reading from and writing to the file.
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <exception cref="ArgumentNullException">
|
|
|
|
|
/// <paramref name="abstraction" /> is <see langword="null"
|
|
|
|
|
/// />.
|
2009-02-19 06:26:56 +00:00
|
|
|
/// </exception>
|
2013-06-05 03:02:43 -04:00
|
|
|
public File(File.IFileAbstraction abstraction, CUEToolsTagger _tagger)
|
2009-02-22 07:47:56 +00:00
|
|
|
: base (abstraction)
|
|
|
|
|
{
|
2009-05-01 15:16:26 +00:00
|
|
|
tagger = _tagger;
|
|
|
|
|
// Make sure we have a tag.
|
|
|
|
|
switch (tagger)
|
|
|
|
|
{
|
2013-06-05 03:02:43 -04:00
|
|
|
case CUEToolsTagger.APEv2:
|
2009-05-01 15:16:26 +00:00
|
|
|
GetTag(TagTypes.Ape, true);
|
|
|
|
|
break;
|
2013-06-05 03:02:43 -04:00
|
|
|
case CUEToolsTagger.ID3v2:
|
2009-02-19 06:26:56 +00:00
|
|
|
GetTag(TagTypes.Id3v2, true);
|
2009-05-01 15:16:26 +00:00
|
|
|
break;
|
|
|
|
|
}
|
2009-02-22 07:47:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#region Public Methods
|
|
|
|
|
|
2013-06-05 03:02:43 -04:00
|
|
|
public CUEToolsTagger Tagger
|
2009-02-22 07:47:56 +00:00
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
2009-05-01 15:16:26 +00:00
|
|
|
return tagger;
|
2009-02-22 07:47:56 +00:00
|
|
|
}
|
2009-05-01 15:16:26 +00:00
|
|
|
}
|
2009-02-22 07:47:56 +00:00
|
|
|
|
|
|
|
|
/// <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>
|
|
|
|
|
/// <remarks>
|
|
|
|
|
/// If a <see cref="TagLib.Id3v2.Tag" /> is added to the
|
|
|
|
|
/// current instance, it will be placed at the start of the
|
|
|
|
|
/// file. On the other hand, <see cref="TagLib.Id3v1.Tag" />
|
|
|
|
|
/// <see cref="TagLib.Ape.Tag" /> will be added to the end of
|
|
|
|
|
/// the file. All other tag types will be ignored.
|
|
|
|
|
/// </remarks>
|
|
|
|
|
public override TagLib.Tag GetTag (TagTypes type, bool create)
|
|
|
|
|
{
|
|
|
|
|
Tag t = (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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#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)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <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)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <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)
|
|
|
|
|
{
|
|
|
|
|
return new Properties ();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static class AdditionalFileTypes
|
|
|
|
|
{
|
2009-02-19 04:09:59 +00:00
|
|
|
private static bool inited = false;
|
2013-06-11 21:19:48 -04:00
|
|
|
private static CUEToolsCodecsConfig _config;
|
2009-02-19 04:09:59 +00:00
|
|
|
|
2013-06-11 21:19:48 -04:00
|
|
|
public static CUEToolsCodecsConfig Config
|
2009-02-19 04:09:59 +00:00
|
|
|
{
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
Init();
|
|
|
|
|
_config = value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static TagLib.File UserDefinedResolver(TagLib.File.IFileAbstraction abstraction, string mimetype, TagLib.ReadStyle style)
|
|
|
|
|
{
|
2013-06-05 03:02:43 -04:00
|
|
|
foreach (KeyValuePair<string,CUEToolsFormat> fmt in _config.formats)
|
|
|
|
|
if (fmt.Value.tagger != CUEToolsTagger.TagLibSharp && mimetype == "taglib/" + fmt.Key)
|
2009-05-01 15:16:26 +00:00
|
|
|
return new File(abstraction, style, fmt.Value.tagger);
|
2009-02-19 04:09:59 +00:00
|
|
|
return null;
|
|
|
|
|
}
|
2009-02-22 07:47:56 +00:00
|
|
|
|
|
|
|
|
static AdditionalFileTypes ()
|
|
|
|
|
{
|
|
|
|
|
Init();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal static void Init()
|
|
|
|
|
{
|
|
|
|
|
if (inited)
|
2009-02-19 04:09:59 +00:00
|
|
|
return;
|
|
|
|
|
TagLib.File.AddFileTypeResolver(new TagLib.File.FileTypeResolver(UserDefinedResolver));
|
2009-02-22 07:47:56 +00:00
|
|
|
//FileTypes.Register(typeof(TagLib.NonContainer.File));
|
|
|
|
|
inited = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|