|
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Collections;
using Tags.ID3.ID3v2Frames;
using System.Text.RegularExpressions;
namespace Tags.ID3
{
/// <summary>
/// The main class for any type of frame to inherit
/// </summary>
public abstract class Frame : ILengthable
{
private string _FrameID; // Contain FrameID of current Frame
private FrameFlags _FrameFlags; // Contain Flags of current frame
// After reading frame if must drop value were true it means frame is not readable
private bool _IsLinked; // indicate is current frame a linked frame or not
private ID3Exception _Exception;
/// <summary>
/// Create a new Frame class
/// </summary>
/// <param name="FrameID">4 Characters tag identifier</param>
/// <param name="Flags">Frame Falgs</param>
protected Frame(string FrameID, FrameFlags Flags)
{
// All FrameID letters must be capital
FrameID = FrameID.ToUpper();
if (!ValidatingFrameID(FrameID, ExceptionLevels.Error))
return;
_FrameFlags = Flags;
_FrameID = FrameID;
_IsLinked = false;
}
/// <summary>
/// Get or Set flags of current frame
/// </summary>
protected FrameFlags FrameFlag
{
get
{ return _FrameFlags; }
set
{ _FrameFlags = value; }
}
/// <summary>
/// Exception Occured while reading file
/// </summary>
/// <param name="Ex">Exception to add to list</param>
protected void ExceptionOccured(ID3Exception Ex)
{
_Exception = Ex;
}
#region -> Static Get Members <-
/// <summary>
/// Get length of Specific string according to Encoding
/// </summary>
/// <param name="Text">Text to get length</param>
/// <param name="TEncoding">TextEncoding to use for Length calculation</param>
/// <param name="AddNullCharacter">Indicate Add null character at the end of string or not</param>
/// <returns>Length of text</returns>
protected static int GetTextLength(string Text, TextEncodings TEncoding, bool AddNullCharacter)
{
int StringLength;
StringLength = Text.Length;
if (TEncoding == TextEncodings.UTF_16 || TEncoding == TextEncodings.UTF_16BE)
StringLength *= 2; // in UTF-16 each character is 2 bytes
if (AddNullCharacter)
{
if (TEncoding == TextEncodings.UTF_16 || TEncoding == TextEncodings.UTF_16BE)
StringLength += 2;
else
StringLength++;
}
return StringLength;
}
#endregion
#region -> Validating Methods <-
/// <summary>
/// Indicate is value of Enumeration valid for that enum
/// </summary>
/// <param name="Enumeration">Enumeration to control value for</param>
/// <param name="ErrorType">if not valid how error occur</param>
/// <param name="FrameID">FrameID just for using in Exception message</param>
/// <returns>true if valid otherwise false</returns>
protected bool IsValidEnumValue(Enum Enumeration, ExceptionLevels ErrorType, string FrameID)
{
if (IsValidEnumValue(Enumeration))
return true;
else
{
ID3Exception FEx = new ID3Exception(Enumeration.ToString() +
" is out of range of " + Enumeration.GetType().ToString(), FrameID, ErrorType);
if (ErrorType != ExceptionLevels.Error)
ExceptionOccured(FEx);
else
throw FEx;
return false;
}
}
/// <summary>
/// Indicate if value of enumeration is valid
/// </summary>
/// <param name="Enumeration">Enum to check</param>
/// <returns>true if valid otherwise false</returns>
protected bool IsValidEnumValue(Enum Enumeration)
{
return (Enum.IsDefined(Enumeration.GetType(), Enumeration));
}
/// <summary>
/// Indicate is specific FrameID valid or not
/// </summary>
/// <param name="FrameIdentifier">FrameID to check</param>
/// <param name="ErrorType">Error type that must occur if frame identifier was not valid</param>
/// <returns>true if frame identifer was valid otherwise false</returns>
protected bool ValidatingFrameID(string FrameIdentifier, ExceptionLevels ErrorType)
{
bool IsValid = FramesInfo.IsValidFrameID(FrameIdentifier);
if (!IsValid)
{
ID3Exception Ex = new ID3Exception(FrameIdentifier + " is not valid FrameID", FrameIdentifier, ErrorType);
if (ErrorType == ExceptionLevels.Error)
throw Ex;
else if (ErrorType == ExceptionLevels.Error)
ExceptionOccured(Ex);
}
return IsValid;
}
#endregion
/// <summary>
/// Indicate if current frame isvalid according to ExceptionLevel and validating data
/// </summary>
public bool IsValid
{
get
{
if (_Exception == null)
return this.OnValidating();
else
return (_Exception.Level == ExceptionLevels.Error) ||
this.OnValidating();
}
}
/// <summary>
/// Write data of current frame to specific TagStream
/// </summary>
/// <param name="writer">TagStream to write data to</param>
/// <param name="MinorVersion">MinorVersion of ID3</param>
public void WriteData(TagStream writer, int MinorVersion)
{
WriteFrameHeader(writer, MinorVersion);
OnWritingData(writer, MinorVersion);
}
private void WriteFrameHeader(TagStream writer, int MinorVersion)
{
byte[] Buf;
int FrameIDLength = MinorVersion == 2 ? 3 : 4; // Length of FrameID according to version
string Temp = _FrameID;
// if minor version of ID3 were 2, the frameID is 3 character length
if (MinorVersion == 2)
{
Temp = FramesInfo.Get3CharID(Temp);
if (Temp == null) // This frame is not availabe in this version
return;
}
writer.WriteText(Temp, TextEncodings.Ascii, false); // Write FrameID
Buf = BitConverter.GetBytes(Length);
Array.Reverse(Buf);
if (MinorVersion == 2)
writer.Write(Buf, 1, Buf.Length - 1); // Write Frame Size
else
writer.Write(Buf, 0, Buf.Length); // Write Frame Size
if (MinorVersion != 2)
{
// If newer than version 2 it have Flags
Buf = BitConverter.GetBytes((ushort)_FrameFlags);
Array.Reverse(Buf);
writer.Write(Buf, 0, Buf.Length); // Write Frame Flag
}
}
#region -> Virtual method and properties <-
/// <summary>
/// Call when frame need to write it's data to stream
/// </summary>
/// <param name="writer">TagStream to write data</param>
/// <param name="MinorVersion">ID3 minor version</param>
protected virtual void OnWritingData(TagStream writer, int MinorVersion)
{ }
/// <summary>
/// Occur when want to validate frame information
/// </summary>
/// <returns>true if was valid frame otherwise false</returns>
protected virtual bool OnValidating()
{
return true;
}
/// <summary>
/// Gets length of current frame in byte
/// </summary>
/// <returns>int contain length of current frame</returns>
protected virtual int OnGetLength()
{ return 0; }
#endregion
#region -> Frame Flags Properties <-
/// <summary>
/// Get FrameID of current frame
/// </summary>
public string FrameID
{
get
{ return _FrameID; }
}
/// <summary>
/// Gets or sets if current frame is ReadOnly
/// </summary>
public bool ReadOnly
{
get
{
if ((_FrameFlags & FrameFlags.ReadOnly)
== FrameFlags.ReadOnly)
return true;
else
return false;
}
set
{
if (value == true)
_FrameFlags |= FrameFlags.ReadOnly;
else
_FrameFlags &= ~FrameFlags.ReadOnly;
}
}
/// <summary>
/// Gets or sets if current frame is Encrypted
/// </summary>
public bool Encryption
{
get
{
if ((_FrameFlags & FrameFlags.Encryption)
== FrameFlags.Encryption)
return true;
else
return false;
}
set
{
if (value == true)
_FrameFlags |= FrameFlags.Encryption;
else
_FrameFlags &= ~FrameFlags.Encryption;
}
}
/// <summary>
/// Gets or sets whether or not frame belongs in a group with other frames
/// </summary>
public bool GroupIdentity
{
get
{
if ((_FrameFlags & FrameFlags.GroupingIdentity)
== FrameFlags.GroupingIdentity)
return true;
else
return false;
}
set
{
if (value == true)
_FrameFlags |= FrameFlags.GroupingIdentity;
else
_FrameFlags &= ~FrameFlags.GroupingIdentity;
}
}
/// <summary>
/// Gets or sets whether or not this frame was compressed
/// </summary>
public bool Compression
{
get
{
if ((_FrameFlags & FrameFlags.Compression)
== FrameFlags.Compression)
return true;
else
return false;
}
set
{
if (value == true)
_FrameFlags |= FrameFlags.Compression;
else
_FrameFlags &= ~FrameFlags.Compression;
}
}
/// <summary>
/// Gets or sets if it's unknown frame it should be preserved or discared
/// </summary>
public bool TagAlterPreservation
{
get
{
if ((_FrameFlags & FrameFlags.TagAlterPreservation)
== FrameFlags.TagAlterPreservation)
return true;
else
return false;
}
set
{
if (value == true)
_FrameFlags |= FrameFlags.TagAlterPreservation;
else
_FrameFlags &= ~FrameFlags.TagAlterPreservation;
}
}
/// <summary>
/// Gets or sets what to do if file excluding frame, Preseved or discared
/// </summary>
public bool FileAlterPreservation
{
get
{
if ((_FrameFlags & FrameFlags.FileAlterPreservation)
== FrameFlags.FileAlterPreservation)
return true;
else
return false;
}
set
{
if (value == true)
_FrameFlags |= FrameFlags.FileAlterPreservation;
else
_FrameFlags &= ~FrameFlags.FileAlterPreservation;
}
}
/// <summary>
/// Gets or sets is current frame a linked frame
/// </summary>
public bool IsLinked
{
get
{ return _IsLinked; }
set
{ _IsLinked = value; }
}
#endregion
/// <summary>
/// Retrun a string that represent FrameID of current Frame
/// </summary>
/// <returns>FrameID of current Frame</returns>
public override string ToString()
{
return _FrameID;
}
/// <summary>
/// Exception that occured in reading frame
/// </summary>
public ID3Exception Exception
{
get
{ return _Exception; }
}
/// <summary>
/// Get Length of current frame
/// </summary>
public int Length
{
get
{ return OnGetLength(); }
}
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.