1
0
mirror of https://github.com/SineVector241/VoiceCraft-MCBE_Proximity_Chat.git synced 2024-11-20 10:27:45 +00:00
VoiceCraft-MCBE_Proximity_Chat/ATL/AudioData/MetaDataIOFactory.cs
2024-07-13 11:16:08 +10:00

167 lines
6.9 KiB
C#

using System;
using System.Collections.Generic;
namespace ATL.AudioData
{
/// <summary>
/// Factory for metadata (tag) I/O classes
/// </summary>
public class MetaDataIOFactory : Factory
{
/// <summary>
/// Metadata type
/// </summary>
public enum TagType
{
/// <summary>
/// ID3v1
/// </summary>
ID3V1 = 0,
/// <summary>
/// ID3v2
/// </summary>
ID3V2 = 1,
/// <summary>
/// APEtag
/// </summary>
APE = 2,
/// <summary>
/// Native tag format associated with the audio container (ex : MP4 built-in tagging format)
/// </summary>
NATIVE = 3,
/// <summary>
/// Recommended tag type (according to an audio format)
/// </summary>
RECOMMENDED = 98,
/// <summary>
/// Whenever tag type is not known in advance and may apply to any available tag
/// </summary>
ANY = 99
}
// The instance of this factory
private static MetaDataIOFactory theFactory = null;
private static readonly object _lockable = new object();
/// <summary>
/// Sets whether the next created metadatareaders should use cross-tag reading
/// - false : the most important tagging standard (according to priorities)
/// detected on the track is exclusively used to populate fields
/// - true (default) : for each field, the most important tagging standard (according to
/// priorities) is first read. If the value is empty, the next
/// tagging standard (according to priorities) is read, and so on...
/// </summary>
public bool CrossReading { get; set; } = true;
/// <summary>
/// Ordered list of tags to consider while reading, starting by the one with the highest priority
/// </summary>
public TagType[] TagPriority { get; set; }
// ------------------------------------------------------------------------------------------
/// <summary>
/// Gets the instance of this factory (Singleton pattern)
/// </summary>
/// <returns>Instance of the MetaReaderFactory of the application</returns>
public static MetaDataIOFactory GetInstance()
{
if (!BitConverter.IsLittleEndian) throw new PlatformNotSupportedException("Big-endian based platforms are not supported by ATL");
lock (_lockable)
{
if (null == theFactory)
{
theFactory = new MetaDataIOFactory();
theFactory.TagPriority = new TagType[4];
theFactory.TagPriority[0] = TagType.ID3V2;
theFactory.TagPriority[1] = TagType.APE;
theFactory.TagPriority[2] = TagType.NATIVE;
theFactory.TagPriority[3] = TagType.ID3V1;
theFactory.formatListByExt = new Dictionary<string, IList<Format>>();
theFactory.formatListByMime = new Dictionary<string, IList<Format>>();
Format tempFmt = new Format((int)TagType.ID3V1 * 1000, "ID3v1");
tempFmt.AddExtension("id3v1");
theFactory.addFormat(tempFmt);
tempFmt = new Format((int)TagType.ID3V2 * 1000, "ID3v2");
tempFmt.AddExtension("id3v2");
theFactory.addFormat(tempFmt);
tempFmt = new Format((int)TagType.APE * 1000, "APEtag");
tempFmt.AddExtension("ape");
theFactory.addFormat(tempFmt);
tempFmt = new Format((int)TagType.NATIVE * 1000, "Native");
tempFmt.AddExtension("native");
theFactory.addFormat(tempFmt);
}
}
return theFactory;
}
/// <summary>
/// Modifies the default reading priority of the metadata
/// </summary>
/// <param name="type">Identifier of the metadata type</param>
/// <param name="rank">Reading priority : range [0..TAG_TYPE_COUNT[</param>
public void SetTagPriority(TagType type, int rank)
{
if (rank > -1 && rank < TagPriority.Length) TagPriority[rank] = type;
}
/// <summary>
/// Gets the appropriate metadata reader for a given file / physical data reader
/// </summary>
/// <param name="theDataManager">AudioDataReader produced for this file</param>
/// <param name="forceTagType">Forces a certain tag type to be read regardless of the current "cross reading" settings</param>
/// <returns>Metadata reader able to give metadata info for this file (or the dummy reader if the format is unknown)</returns>
public IMetaDataIO GetMetaReader(AudioDataManager theDataManager, TagType forceTagType = TagType.ANY)
{
IMetaDataIO theMetaReader = null;
int tagCount = 0;
if (theDataManager.HasNativeMeta()) tagCount++;
if (theDataManager.ID3v1.Exists) tagCount++;
if (theDataManager.ID3v2.Exists) tagCount++;
if (theDataManager.APEtag.Exists) tagCount++;
if (CrossReading && tagCount > 1 && forceTagType.Equals(TagType.ANY))
{
theMetaReader = new CrossMetadataReader(theDataManager, TagPriority);
}
else
{
foreach (var prio in TagPriority)
{
if (((TagType.NATIVE == prio && forceTagType.Equals(TagType.ANY)) || forceTagType.Equals(TagType.NATIVE)) && theDataManager.HasNativeMeta())
{
theMetaReader = theDataManager.NativeTag; break;
}
if (((TagType.ID3V1 == prio && forceTagType.Equals(TagType.ANY)) || forceTagType.Equals(TagType.ID3V1)) && theDataManager.ID3v1.Exists)
{
theMetaReader = theDataManager.ID3v1; break;
}
if (((TagType.ID3V2 == prio && forceTagType.Equals(TagType.ANY)) || forceTagType.Equals(TagType.ID3V2)) && theDataManager.ID3v2.Exists)
{
theMetaReader = theDataManager.ID3v2; break;
}
if (((TagType.APE == prio && forceTagType.Equals(TagType.ANY)) || forceTagType.Equals(TagType.APE)) && theDataManager.APEtag.Exists)
{
theMetaReader = theDataManager.APEtag; break;
}
}
}
if (null == theMetaReader) theMetaReader = new IO.DummyTag();
return theMetaReader;
}
}
}