Initial commit
This commit is contained in:
commit
262601edb8
2025 files changed
+218754
No files matched your search
@@ -0,0 +1,215 @@
|
||||
//
|
||||
// SimpleTag.cs:
|
||||
//
|
||||
// Author:
|
||||
// Sebastien Mouy <starwer@laposte.net>
|
||||
//
|
||||
// Copyright (C) 2017 Starwer
|
||||
//
|
||||
// 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.IO;
|
||||
|
||||
namespace TagLib.Matroska
|
||||
{
|
||||
/// <summary>
|
||||
/// Describes a Matroska Attachment.
|
||||
/// Attachments may be pictures, but also any other content type.
|
||||
/// </summary>
|
||||
public class Attachment : PictureLazy, IUIDElement
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="Attachment" /> with no data or values.
|
||||
/// </summary>
|
||||
public Attachment ()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="Attachment" /> by reading in the contents of a
|
||||
/// specified file.
|
||||
/// </summary>
|
||||
/// <param name="path">
|
||||
/// A <see cref="string"/> object containing the path of the
|
||||
/// file to read.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="path" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public Attachment (string path)
|
||||
: base (path)
|
||||
{
|
||||
SetTypeFromFilename ();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="Attachment" /> by reading in the contents of a
|
||||
/// specified file abstraction.
|
||||
/// </summary>
|
||||
/// <param name="abstraction">
|
||||
/// A <see cref="TagLib.File.IFileAbstraction"/> object containing
|
||||
/// abstraction of the file to read.
|
||||
/// </param>
|
||||
/// <param name="offset">
|
||||
/// The position in bytes where the picture is located in the
|
||||
/// <see cref="T:File.IFileAbstraction"/>.
|
||||
/// </param>
|
||||
/// <param name="size">
|
||||
/// The size in bytes of the picture in the
|
||||
/// <see cref="T:File.IFileAbstraction"/> (default: read all).
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="abstraction" /> is <see langword="null"
|
||||
/// />.
|
||||
/// </exception>
|
||||
public Attachment (TagLib.File.IFileAbstraction abstraction, long offset = 0, long size = -1)
|
||||
: base (abstraction, offset, size)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="Attachment" /> by using the contents of a <see
|
||||
/// cref="ByteVector" /> object.
|
||||
/// </summary>
|
||||
/// <param name="data">
|
||||
/// A <see cref="ByteVector"/> object containing picture data
|
||||
/// to use.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="data" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public Attachment (ByteVector data)
|
||||
: base (data)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="Attachment" /> by doing a shallow copy of <see
|
||||
/// cref="IPicture" />.
|
||||
/// </summary>
|
||||
/// <param name="picture">
|
||||
/// A <see cref="IPicture"/> object containing picture data
|
||||
/// to convert to an Attachment.
|
||||
/// </param>
|
||||
public Attachment (IPicture picture)
|
||||
: base (picture)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <summary>
|
||||
/// Derive the Picture-type from the the file-name.
|
||||
/// It change the <see cref="P:Type"/> from the <see cref="P:Filename"/>.
|
||||
/// </summary>
|
||||
public void SetTypeFromFilename ()
|
||||
{
|
||||
if (MimeType != null && !MimeType.StartsWith ("image/")) {
|
||||
Type = PictureType.NotAPicture;
|
||||
return;
|
||||
}
|
||||
|
||||
if (Filename == null) {
|
||||
Type = PictureType.Other;
|
||||
return;
|
||||
}
|
||||
|
||||
PictureType type = PictureType.Other;
|
||||
string fname = Filename.ToLower ();
|
||||
|
||||
foreach (var ptype in Enum.GetNames (typeof (PictureType))) {
|
||||
if (fname.Contains (ptype.ToLower ())) {
|
||||
type = (PictureType)Enum.Parse (typeof (PictureType), ptype);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (type == PictureType.Other && ((fname.Contains ("cover") || fname.Contains ("poster")))) {
|
||||
type = PictureType.FrontCover;
|
||||
}
|
||||
|
||||
Type = type;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Derive thefile-name from the the Piture type.
|
||||
/// It change the <see cref="P:Filename"/> from the <see cref="P:Type"/> if required,
|
||||
/// but not if the filename already matches the type.
|
||||
/// </summary>
|
||||
/// <returns>true if <see cref="P:Filename"/> changed</returns>
|
||||
public bool SetFilenameFromType ()
|
||||
{
|
||||
PictureType type = Type;
|
||||
|
||||
if (!string.IsNullOrEmpty (Filename)) {
|
||||
SetTypeFromFilename ();
|
||||
|
||||
// Filename already matches the type, so do not change it
|
||||
if (type == Type) return false;
|
||||
|
||||
// restore the type
|
||||
Type = type;
|
||||
}
|
||||
|
||||
// Derive extension from file or MimeType
|
||||
string ext = null;
|
||||
if (Filename != null) ext = Path.GetExtension (Filename);
|
||||
if (ext == null && MimeType != null && MimeType.StartsWith ("image/")) ext = "." + MimeType.Substring (6);
|
||||
if (ext == null || ext.Length < 2) ext = "";
|
||||
|
||||
// Change the filename
|
||||
Filename = type + ext;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region IUIDElement Boilerplate
|
||||
|
||||
/// <summary>
|
||||
/// Unique ID representing the element, as random as possible (setting zero will generate automatically a new one).
|
||||
/// </summary>
|
||||
public ulong UID {
|
||||
get { return _UID; }
|
||||
set { _UID = UIDElement.GenUID (value); }
|
||||
}
|
||||
|
||||
ulong _UID = UIDElement.GenUID ();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get the Tag type the UID should be represented by, or 0 if undefined
|
||||
/// </summary>
|
||||
public MatroskaID UIDType { get { return MatroskaID.TagAttachmentUID; } }
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f61f84258e7ab3b6ebcb9b16ff0b9e53
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,146 @@
|
||||
//
|
||||
// AudioTrack.cs:
|
||||
//
|
||||
// Author:
|
||||
// Julien Moutte <julien@fluendo.com>
|
||||
//
|
||||
// Copyright (C) 2011 FLUENDO S.A.
|
||||
//
|
||||
// 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.Collections.Generic;
|
||||
|
||||
namespace TagLib.Matroska
|
||||
{
|
||||
/// <summary>
|
||||
/// Describes a Matroska Audio track.
|
||||
/// </summary>
|
||||
public class AudioTrack : Track, IAudioCodec
|
||||
{
|
||||
#region Private fields
|
||||
|
||||
#pragma warning disable 414 // Assigned, never used
|
||||
readonly double rate;
|
||||
readonly ulong channels;
|
||||
readonly ulong depth;
|
||||
#pragma warning restore 414
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Construct a <see cref="AudioTrack" /> reading information from
|
||||
/// provided file data.
|
||||
/// Parsing will be done reading from _file at position references by
|
||||
/// parent element's data section.
|
||||
/// </summary>
|
||||
/// <param name="_file"><see cref="File" /> instance to read from.</param>
|
||||
/// <param name="element">Parent <see cref="EBMLreader" />.</param>
|
||||
public AudioTrack (File _file, EBMLreader element)
|
||||
: base (_file, element)
|
||||
{
|
||||
// Here we handle the unknown elements we know, and store the rest
|
||||
foreach (EBMLreader elem in base.UnknownElements) {
|
||||
var matroska_id = elem.ID;
|
||||
|
||||
|
||||
switch (matroska_id) {
|
||||
case MatroskaID.TrackAudio: {
|
||||
ulong i = 0;
|
||||
|
||||
while (i < elem.DataSize) {
|
||||
EBMLreader child = new EBMLreader (_file, elem.DataOffset + i);
|
||||
|
||||
matroska_id = child.ID;
|
||||
|
||||
switch (matroska_id) {
|
||||
case MatroskaID.AudioChannels:
|
||||
channels = child.ReadULong ();
|
||||
break;
|
||||
case MatroskaID.AudioBitDepth:
|
||||
depth = child.ReadULong ();
|
||||
break;
|
||||
case MatroskaID.AudioSamplingFreq:
|
||||
rate = child.ReadDouble ();
|
||||
break;
|
||||
default:
|
||||
UnknownElements.Add (child);
|
||||
break;
|
||||
}
|
||||
|
||||
i += child.Size;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
UnknownElements.Add (elem);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public fields
|
||||
|
||||
/// <summary>
|
||||
/// List of unknown elements encountered while parsing.
|
||||
/// </summary>
|
||||
public new List<EBMLreader> UnknownElements { get; } = new List<EBMLreader>();
|
||||
|
||||
#endregion
|
||||
|
||||
#region ICodec
|
||||
|
||||
/// <summary>
|
||||
/// This type of track only has audio media type.
|
||||
/// </summary>
|
||||
public override MediaTypes MediaTypes {
|
||||
get { return MediaTypes.Audio; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IAudioCodec
|
||||
|
||||
/// <summary>
|
||||
/// Audio track bitrate.
|
||||
/// </summary>
|
||||
public int AudioBitrate {
|
||||
get { return 0; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Audio track sampling rate.
|
||||
/// </summary>
|
||||
public int AudioSampleRate {
|
||||
get { return (int)rate; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Number of audio channels in this track.
|
||||
/// </summary>
|
||||
public int AudioChannels {
|
||||
get { return (int)channels; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4acff302cab1d869f8d197a37fc3f624
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,420 @@
|
||||
//
|
||||
// EBMLElement.cs:
|
||||
//
|
||||
// Author:
|
||||
// Sebastien Mouy <starwer@laposte.net>
|
||||
//
|
||||
// Copyright (C) 2011 FLUENDO S.A.
|
||||
//
|
||||
// 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.Matroska
|
||||
{
|
||||
/// <summary>
|
||||
/// Represent a generic EBML Element and its content.
|
||||
/// </summary>
|
||||
public class EBMLelement
|
||||
{
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs an empty <see cref="EBMLelement" />.
|
||||
/// </summary>
|
||||
public EBMLelement ()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Construct a <see cref="EBMLelement" /> to contain children elements.
|
||||
/// </summary>
|
||||
/// <param name="ebmlid">EBML ID of the element to be created.</param>
|
||||
public EBMLelement (MatroskaID ebmlid)
|
||||
{
|
||||
ID = ebmlid;
|
||||
Children = new List<EBMLelement> ();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a <see cref="EBMLelement" /> to contain data.
|
||||
/// </summary>
|
||||
/// <param name="ebmlid">EBML ID of the element to be created.</param>
|
||||
/// <param name="data">EBML data of the element to be created.</param>
|
||||
public EBMLelement (MatroskaID ebmlid, ByteVector data)
|
||||
{
|
||||
ID = ebmlid;
|
||||
Data = data;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Construct <see cref="EBMLelement" /> to contain data.
|
||||
/// </summary>
|
||||
/// <param name="ebmlid">EBML ID of the element to be created.</param>
|
||||
/// <param name="value">EBML data as an <see cref="ulong"/> value.</param>
|
||||
public EBMLelement (MatroskaID ebmlid, ulong value)
|
||||
{
|
||||
ID = ebmlid;
|
||||
SetData (value);
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// EBML Element Identifier.
|
||||
/// </summary>
|
||||
public MatroskaID ID = 0;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get or set the data represented by the EBML
|
||||
/// </summary>
|
||||
public ByteVector Data;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get or set the element embedded in the EBML
|
||||
/// </summary>
|
||||
public List<EBMLelement> Children;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get or set whether the EBML should have a size of one byte more
|
||||
/// than the optimal size.
|
||||
/// </summary>
|
||||
public bool IncSize;
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// EBML Element size in bytes.
|
||||
/// </summary>
|
||||
public long Size {
|
||||
get {
|
||||
long size_length = DataSize;
|
||||
return IDSize + EBMLByteSize ((ulong)size_length) + (IncSize ? 1 : 0) + size_length;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get the size of the EBML ID, in bytes
|
||||
/// </summary>
|
||||
public long IDSize {
|
||||
get {
|
||||
uint ebml_id = (uint)ID;
|
||||
|
||||
// Figure out the ID size in bytes
|
||||
long mask = 0xFF000000, id_length = 4;
|
||||
while (id_length > 0 && (ebml_id & mask) == 0) {
|
||||
id_length--;
|
||||
mask >>= 8;
|
||||
}
|
||||
if (id_length == 0)
|
||||
throw new CorruptFileException ("invalid EBML ID (zero)");
|
||||
|
||||
return id_length;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the size of the EBML data-size, in bytes
|
||||
/// </summary>
|
||||
public long DataSizeSize {
|
||||
get { return EBMLByteSize ((ulong)DataSize) + (IncSize ? 1 : 0); }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// EBML Element data/content size in bytes.
|
||||
/// </summary>
|
||||
public long DataSize {
|
||||
get {
|
||||
long ret = 0;
|
||||
|
||||
if (Data != null) {
|
||||
// Get Data size
|
||||
ret = Data.Count;
|
||||
|
||||
if (Children != null)
|
||||
throw new UnsupportedFormatException ("EBML element cannot contain both Data and Children");
|
||||
} else {
|
||||
// Get the content size
|
||||
foreach (var child in Children) {
|
||||
ret += child.Size;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Try to increase the size of the EBML by 1 byte.
|
||||
/// </summary>
|
||||
/// <returns>True if successfully increased size, false if failed.</returns>
|
||||
public bool IncrementSize ()
|
||||
{
|
||||
// Try to extend current DataSizeSize
|
||||
if (!IncSize && DataSizeSize < 8) {
|
||||
return IncSize = true;
|
||||
}
|
||||
|
||||
// Try to extend one of the children
|
||||
if (Children != null) {
|
||||
foreach (var child in Children) {
|
||||
if (child.IncrementSize ()) return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Failed
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get the EBML ID and data-size as a vector of bytes.
|
||||
/// </summary>
|
||||
public ByteVector Header {
|
||||
get {
|
||||
// Retrieve sizes
|
||||
var id_length = IDSize;
|
||||
var size_length = DataSizeSize;
|
||||
|
||||
// Create vector
|
||||
ByteVector vector = new ByteVector ((int)(id_length + size_length));
|
||||
|
||||
// Construct the ID field
|
||||
uint ebml_id = (uint)ID;
|
||||
uint mask = ebml_id;
|
||||
for (int i = (int)id_length - 1; i >= 0; i--) {
|
||||
vector[i] = (byte)(mask & 0xFF);
|
||||
mask >>= 8;
|
||||
}
|
||||
|
||||
// Construct the data-size field
|
||||
ulong lmask = (ulong)DataSize;
|
||||
for (int i = (int)(id_length + size_length - 1); i >= id_length; i--) {
|
||||
vector[i] = (byte)(lmask & 0xFF);
|
||||
lmask >>= 8;
|
||||
}
|
||||
|
||||
// Set the marker bit of the Data-size
|
||||
vector[(int)id_length] |= (byte)(0x100 >> (int)size_length);
|
||||
|
||||
|
||||
return vector;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Class functions
|
||||
|
||||
/// <summary>
|
||||
/// Get the byte-size required to encode an EBML value with the leading 1.
|
||||
/// </summary>
|
||||
/// <param name="value">Encoded value</param>
|
||||
/// <returns>size in bytes</returns>
|
||||
public static long EBMLByteSize (ulong value)
|
||||
{
|
||||
// Figure out the required data-size size in bytes
|
||||
long size_length;
|
||||
if (value == 0x7F) {
|
||||
// Special case: Avoid element-size reserved word of 0xFF (all ones)
|
||||
size_length = 2;
|
||||
} else {
|
||||
size_length = 8;
|
||||
ulong mask = (ulong)0x7F << (7 * 7);
|
||||
while (size_length > 1 && (value & mask) == 0) {
|
||||
size_length--;
|
||||
mask >>= 7;
|
||||
}
|
||||
}
|
||||
|
||||
return size_length;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Public Methods Data access
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get a string from EBML Element's data section (UTF-8).
|
||||
/// Handle null-termination.
|
||||
/// </summary>
|
||||
/// <returns>a string object containing the parsed value.</returns>
|
||||
public string GetString ()
|
||||
{
|
||||
if (Data == null) return null;
|
||||
var idx = Data.IndexOf (0x00); // Detected Null termination
|
||||
if (idx >= 0) return Data.ToString (StringType.UTF8, 0, idx);
|
||||
return Data.ToString (StringType.UTF8);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a boolean from EBML Element's data section.
|
||||
/// </summary>
|
||||
/// <returns>a bool containing the parsed value.</returns>
|
||||
public bool GetBool ()
|
||||
{
|
||||
if (Data == null) return false;
|
||||
return (Data.ToUInt () > 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a double from EBML Element's data section.
|
||||
/// </summary>
|
||||
/// <returns>a double containing the parsed value.</returns>
|
||||
public double GetDouble ()
|
||||
{
|
||||
if (Data == null) return 0;
|
||||
|
||||
double result = 0.0;
|
||||
|
||||
if (Data.Count == 4) {
|
||||
result = Data.ToFloat ();
|
||||
} else if (Data.Count == 8) {
|
||||
result = Data.ToDouble ();
|
||||
} else {
|
||||
throw new UnsupportedFormatException ("Can not read a Double with sizes differing from 4 or 8");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get an unsigned integer (any size from 1 to 8 bytes) from EBML Element's data section.
|
||||
/// </summary>
|
||||
/// <returns>a ulong containing the parsed value.</returns>
|
||||
public ulong GetULong ()
|
||||
{
|
||||
if (Data == null) return 0;
|
||||
return Data.ToULong ();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get a bytes vector from EBML Element's data section.
|
||||
/// </summary>
|
||||
/// <returns>a <see cref="ByteVector" /> containing the parsed value.</returns>
|
||||
public ByteVector GetBytes ()
|
||||
{
|
||||
return Data;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Set data content as <see cref="string"/> to the EBML file
|
||||
/// </summary>
|
||||
/// <param name="data">data as <see cref="string"/></param>
|
||||
public void SetData (string data)
|
||||
{
|
||||
Data = data;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Set data content as <see cref="ulong"/> to the EBML file
|
||||
/// </summary>
|
||||
/// <param name="data">unsigned long number to write</param>
|
||||
public void SetData (ulong data)
|
||||
{
|
||||
const ulong mask = 0xffffffff00000000;
|
||||
bool isLong = (data & mask) != 0;
|
||||
|
||||
ByteVector vector = new ByteVector (isLong ? 8 : 4);
|
||||
for (int i = vector.Count - 1; i >= 0; i--) {
|
||||
vector[i] = (byte)(data & 0xff);
|
||||
data >>= 8;
|
||||
}
|
||||
|
||||
Data = vector;
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Public Methods Write to file
|
||||
|
||||
/// <summary>
|
||||
/// Write the EMBL (and all its data/content) to a file.
|
||||
/// </summary>
|
||||
/// <param name="file">A <see cref="File"/> representing the file to write to.</param>
|
||||
/// <param name="position">The byte-position in the file to write the EBML to.</param>
|
||||
/// <param name="reserved">The reserved size in bytes that the EBML may overwrite from the given position. (Default: 0, insert)</param>
|
||||
public void Write (File file, long position, long reserved = 0)
|
||||
{
|
||||
if (file == null)
|
||||
throw new ArgumentNullException (nameof (file));
|
||||
|
||||
if (position > file.Length || position < 0)
|
||||
throw new ArgumentOutOfRangeException (nameof (position));
|
||||
|
||||
if (Data != null && Children != null)
|
||||
throw new UnsupportedFormatException ("EBML element cannot contain both Data and Children");
|
||||
|
||||
|
||||
// Reserve required size upfront to speed up writing
|
||||
var size = Size;
|
||||
if (size > reserved) {
|
||||
// Extend reserved size
|
||||
file.Insert (size - reserved, position + reserved);
|
||||
reserved = size;
|
||||
}
|
||||
|
||||
// Write the Header
|
||||
var header = Header;
|
||||
file.Insert (header, position, header.Count);
|
||||
position += header.Count;
|
||||
reserved -= header.Count;
|
||||
|
||||
// Write the data/content
|
||||
if (Data != null) {
|
||||
file.Insert (Data, position, Data.Count);
|
||||
} else if (Children != null) {
|
||||
foreach (var child in Children) {
|
||||
child.Write (file, position, reserved);
|
||||
var csize = child.Size;
|
||||
position += csize;
|
||||
reserved -= csize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2c23a6d98ba04c36aa2f7a19dece41aa
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,76 @@
|
||||
//
|
||||
// EBMLIDs.cs:
|
||||
//
|
||||
// Author:
|
||||
// Julien Moutte <julien@fluendo.com>
|
||||
//
|
||||
// Copyright (C) 2011 FLUENDO S.A.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
|
||||
namespace TagLib.Matroska
|
||||
{
|
||||
/// <summary>
|
||||
/// Public enumeration listing the possible EBML element identifiers.
|
||||
/// </summary>
|
||||
public enum EBMLID
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates an EBML Header element.
|
||||
/// </summary>
|
||||
EBMLHeader = 0x1A45DFA3,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates an EBML Version element.
|
||||
/// </summary>
|
||||
EBMLVersion = 0x4286,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates an EBML Read Version element.
|
||||
/// </summary>
|
||||
EBMLReadVersion = 0x42F7,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates an EBML Max ID Length element.
|
||||
/// </summary>
|
||||
EBMLMaxIDLength = 0x42F2,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates an EBML Max Size Length element.
|
||||
/// </summary>
|
||||
EBMLMaxSizeLength = 0x42F3,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates an EBML Doc Type element.
|
||||
/// </summary>
|
||||
EBMLDocType = 0x4282,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates an EBML Doc Type Version element.
|
||||
/// </summary>
|
||||
EBMLDocTypeVersion = 0x4287,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates an EBML Doc Type Read Version element.
|
||||
/// </summary>
|
||||
EBMLDocTypeReadVersion = 0x4285,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates an EBML Void element.
|
||||
/// </summary>
|
||||
EBMLVoid = 0xEC
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f47242669f076f52f84ea6b8b4204168
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,483 @@
|
||||
//
|
||||
// EBMLElement.cs:
|
||||
//
|
||||
// Author:
|
||||
// Julien Moutte <julien@fluendo.com>
|
||||
// Sebastien Mouy <starwer@laposte.net>
|
||||
//
|
||||
// Copyright (C) 2011 FLUENDO S.A.
|
||||
//
|
||||
// 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.Matroska
|
||||
{
|
||||
/// <summary>
|
||||
/// Read a Matroska EBML element from a file, but also provides basic modifications to an
|
||||
/// EBML element directly on the file (write). This can also represent an abstract EBML
|
||||
/// on the file (placeholder).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This was intitialy called <see cref="EBMLelement"/>, but this was in fact a file-reader.
|
||||
/// The name <see cref="EBMLelement"/> correspond more to the class which has been created to
|
||||
/// represent an EBML structure (regardless of file-issues) to support the EBML writing to file.
|
||||
/// </remarks>
|
||||
public class EBMLreader
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
File file;
|
||||
ulong offset;
|
||||
uint ebml_id;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a root <see cref="EBMLreader" /> instance, by reading from
|
||||
/// the provided file position.
|
||||
/// </summary>
|
||||
/// <param name="_file"><see cref="File" /> File instance to read from.</param>
|
||||
/// <param name="position">Position in the file to start reading from.</param>
|
||||
public EBMLreader (File _file, ulong position)
|
||||
{
|
||||
// Keep a reference to the file
|
||||
file = _file;
|
||||
Parent = null;
|
||||
|
||||
// Initialize attributes
|
||||
offset = position;
|
||||
DataOffset = position;
|
||||
ebml_id = 0;
|
||||
DataSize = 0;
|
||||
|
||||
// Actually read the EBML on the file
|
||||
Read (true);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a child <see cref="EBMLreader" /> reading the data from the
|
||||
/// EBML parent at the provided file position.
|
||||
/// </summary>
|
||||
/// <param name="parent">The <see cref="EBMLreader" /> that contains the instance to be created.</param>
|
||||
/// <param name="position">Position in the file to start reading from.</param>
|
||||
public EBMLreader (EBMLreader parent, ulong position)
|
||||
{
|
||||
if (parent == null)
|
||||
throw new ArgumentNullException (nameof (parent));
|
||||
|
||||
// Keep a reference to the file
|
||||
file = parent.file;
|
||||
Parent = parent;
|
||||
|
||||
// Initialize attributes
|
||||
offset = position;
|
||||
DataOffset = position;
|
||||
ebml_id = 0;
|
||||
DataSize = 0;
|
||||
|
||||
|
||||
// Actually read the EBML on the file
|
||||
Read (true);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Create a new abstract <see cref="EBMLreader" /> with arbitrary attributes,
|
||||
/// without reading its information on the file.
|
||||
/// </summary>
|
||||
/// <param name="parent">The <see cref="EBMLreader" /> that contains the instance to be described.</param>
|
||||
/// <param name="position">Position in the file.</param>
|
||||
/// <param name="ebmlid">EBML ID of the element</param>
|
||||
/// <param name="size">Total size of the EBML, in bytes</param>
|
||||
public EBMLreader (EBMLreader parent, ulong position, MatroskaID ebmlid, ulong size = 0)
|
||||
{
|
||||
// Keep a reference to the file
|
||||
if (parent != null)
|
||||
file = parent.file;
|
||||
|
||||
Parent = parent;
|
||||
|
||||
// Initialize attributes
|
||||
offset = position;
|
||||
DataOffset = offset;
|
||||
ebml_id = (uint)ebmlid;
|
||||
DataSize = size;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// EBML Element Identifier.
|
||||
/// </summary>
|
||||
public MatroskaID ID {
|
||||
get { return (MatroskaID)ebml_id; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// EBML Parent instance.
|
||||
/// </summary>
|
||||
public EBMLreader Parent { get; }
|
||||
|
||||
/// <summary>
|
||||
/// EBML Element size in bytes.
|
||||
/// </summary>
|
||||
public ulong Size {
|
||||
set { DataSize = value - (DataOffset - offset); }
|
||||
get { return (DataOffset - offset) + DataSize; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// EBML Element data size in bytes.
|
||||
/// </summary>
|
||||
public ulong DataSize { set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// EBML Element data offset position in file in bytes.
|
||||
/// </summary>
|
||||
public ulong DataOffset { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// EBML Element offset position in file in bytes.
|
||||
/// </summary>
|
||||
public ulong Offset {
|
||||
set {
|
||||
DataOffset = (ulong)((long)DataOffset + ((long)value - (long)offset));
|
||||
offset = value;
|
||||
}
|
||||
get { return offset; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines that the EBML element is not read-out from file,
|
||||
/// but is an abstract representation of an element on the disk.
|
||||
/// </summary>
|
||||
public bool Abstract {
|
||||
get { return offset == DataOffset; }
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods for Reading
|
||||
|
||||
/// <summary>
|
||||
/// Read EBML header and data-size if it is an abstract one.
|
||||
/// It then becomes a non abstract EBML.
|
||||
/// </summary>
|
||||
/// <param name="throwException">Throw exception on invalid EBML read if true (Default: false).</param>
|
||||
/// <returns>True if successful.</returns>
|
||||
public bool Read (bool throwException = false)
|
||||
{
|
||||
if (!Abstract) return true;
|
||||
|
||||
if (file == null)
|
||||
throw new ArgumentNullException (nameof(file));
|
||||
|
||||
try {
|
||||
var ex = new InvalidOperationException ("Invalid EBML format Read");
|
||||
|
||||
if (offset >= (ulong)(file.Length) - 1) throw ex;
|
||||
|
||||
// Prepare for Consitency check
|
||||
uint ebml_id_check = ebml_id;
|
||||
ulong ebml_size_check = Size;
|
||||
|
||||
|
||||
file.Seek ((long)offset);
|
||||
|
||||
// Get the header byte
|
||||
ByteVector vector = file.ReadBlock (1);
|
||||
byte header_byte = vector[0];
|
||||
// Define a mask
|
||||
byte mask = 0x80, id_length = 1;
|
||||
// Figure out the size in bytes
|
||||
while (id_length <= 4 && (header_byte & mask) == 0) {
|
||||
id_length++;
|
||||
mask >>= 1;
|
||||
}
|
||||
if (id_length > 4) throw ex;
|
||||
|
||||
// Now read the rest of the EBML ID
|
||||
if (id_length > 1) {
|
||||
vector.Add (file.ReadBlock (id_length - 1));
|
||||
}
|
||||
|
||||
ebml_id = vector.ToUInt ();
|
||||
|
||||
vector.Clear ();
|
||||
|
||||
// Get the size length
|
||||
vector = file.ReadBlock (1);
|
||||
header_byte = vector[0];
|
||||
mask = 0x80;
|
||||
byte size_length = 1;
|
||||
|
||||
// Iterate through various possibilities
|
||||
while (size_length <= 8 && (header_byte & mask) == 0) {
|
||||
size_length++;
|
||||
mask >>= 1;
|
||||
}
|
||||
|
||||
|
||||
if (size_length > 8)
|
||||
size_length = 1; // Special: Empty element (all zero state)
|
||||
else
|
||||
vector[0] &= (byte)(mask - 1); // Clear the marker bit
|
||||
|
||||
|
||||
// Now read the rest of the EBML element size
|
||||
if (size_length > 1) {
|
||||
vector.Add (file.ReadBlock (size_length - 1));
|
||||
}
|
||||
|
||||
DataSize = vector.ToULong ();
|
||||
|
||||
// Special: Auto-size (0xFF byte)
|
||||
if (size_length == 1 && DataSize == 0x7F) {
|
||||
// Resolve auto-size to fill in to its containing element
|
||||
ulong bound = Parent == null ? (ulong)file.Length : Parent.Offset + Parent.Size;
|
||||
DataSize = bound - offset - (ulong)(id_length + size_length);
|
||||
}
|
||||
|
||||
DataOffset = offset + id_length + size_length;
|
||||
|
||||
// Consistency check: Detect descrepencies between read data and abstract data
|
||||
if (ebml_id_check != 0 && ebml_id_check != ebml_id) throw ex;
|
||||
if (ebml_size_check != 0 && ebml_size_check != Size) throw ex;
|
||||
|
||||
return true;
|
||||
|
||||
} catch (Exception) {
|
||||
if (throwException)
|
||||
throw;
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Reads a vector of bytes (raw data) from EBML Element's data section.
|
||||
/// </summary>
|
||||
/// <returns>a <see cref="ByteVector" /> containing the parsed value.</returns>
|
||||
public ByteVector ReadBytes ()
|
||||
{
|
||||
if (file == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
file.Seek ((long)DataOffset);
|
||||
|
||||
ByteVector vector = file.ReadBlock ((int)DataSize);
|
||||
|
||||
return vector;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a string from EBML Element's data section (UTF-8).
|
||||
/// </summary>
|
||||
/// <returns>a string object containing the parsed value.</returns>
|
||||
public string ReadString ()
|
||||
{
|
||||
if (file == null) return null;
|
||||
ByteVector vector = ReadBytes ();
|
||||
var ebml = new EBMLelement ((MatroskaID)ebml_id, vector);
|
||||
return ebml.GetString ();
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a boolean from EBML Element's data section.
|
||||
/// </summary>
|
||||
/// <returns>a bool containing the parsed value.</returns>
|
||||
public bool ReadBool ()
|
||||
{
|
||||
if (file == null || DataSize == 0) return false;
|
||||
ByteVector vector = ReadBytes ();
|
||||
var ebml = new EBMLelement ((MatroskaID)ebml_id, vector);
|
||||
return ebml.GetBool ();
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a double from EBML Element's data section.
|
||||
/// </summary>
|
||||
/// <returns>a double containing the parsed value.</returns>
|
||||
public double ReadDouble ()
|
||||
{
|
||||
if (file == null || DataSize == 0) return 0;
|
||||
ByteVector vector = ReadBytes ();
|
||||
var ebml = new EBMLelement ((MatroskaID)ebml_id, vector);
|
||||
return ebml.GetDouble ();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads an unsigned integer (any size from 1 to 8 bytes) from EBML Element's data section.
|
||||
/// </summary>
|
||||
/// <returns>a ulong containing the parsed value.</returns>
|
||||
public ulong ReadULong ()
|
||||
{
|
||||
if (file == null || DataSize == 0) return 0;
|
||||
ByteVector vector = ReadBytes ();
|
||||
var ebml = new EBMLelement ((MatroskaID)ebml_id, vector);
|
||||
return ebml.GetULong ();
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods for Writing
|
||||
|
||||
/// <summary>
|
||||
/// Write the <see cref="DataSize"/> to the EBML file.
|
||||
/// Resize the data-size length to 8 bytes.
|
||||
/// This will *not* insert extra bytes, but overwrite next contiguous bytes.
|
||||
/// It will claim the size added on the value of the data-size.
|
||||
/// </summary>
|
||||
/// <returns>Offset created in Writing the new data-size</returns>
|
||||
public long WriteDataSize ()
|
||||
{
|
||||
ulong value = DataSize;
|
||||
const ulong newsize_length = 8;
|
||||
|
||||
// Figure out the ID size in bytes
|
||||
ulong mask = 0xFF000000, id_length = 4;
|
||||
while (id_length > 0 && (ebml_id & mask) == 0) {
|
||||
id_length--;
|
||||
mask >>= 8;
|
||||
}
|
||||
if (id_length == 0)
|
||||
throw new CorruptFileException ("invalid EBML ID (zero)");
|
||||
|
||||
// Figure out the Data size length in bytes
|
||||
ulong size_length = DataOffset - offset - id_length;
|
||||
if (size_length > 8)
|
||||
throw new CorruptFileException ("invalid EBML element size");
|
||||
|
||||
// Construct the data-size field
|
||||
ByteVector vector = new ByteVector ((int)newsize_length);
|
||||
mask = value;
|
||||
for (int i = (int)newsize_length - 1; i >= 0; i--) {
|
||||
vector[i] = (byte)(mask & 0xFF);
|
||||
mask >>= 8;
|
||||
}
|
||||
// Set the marker bit
|
||||
vector[0] |= 0x100 >> (int)newsize_length;
|
||||
|
||||
// Write data-size field to file
|
||||
file.Insert (vector, (long)(offset + id_length), (long)newsize_length);
|
||||
|
||||
// Update fields
|
||||
ulong woffset = newsize_length - size_length;
|
||||
DataOffset += woffset;
|
||||
DataSize = value - woffset;
|
||||
|
||||
return (long)woffset;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Change an EBML element to a Abstract Void element, but do not write to the file.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// To do a real conversion to Void EBML element on the file, use <see cref="WriteVoid()"/>.
|
||||
/// </remarks>
|
||||
public void SetVoid ()
|
||||
{
|
||||
ulong size = Size;
|
||||
|
||||
// Update this object
|
||||
ebml_id = (uint)MatroskaID.Void;
|
||||
DataOffset = offset; // This will make it abstract
|
||||
DataSize = size; // Keep the size unchanged
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Change an EBML element to a Void element directly on the file.
|
||||
/// </summary>
|
||||
public void WriteVoid ()
|
||||
{
|
||||
if (Size < 2) throw new ArgumentOutOfRangeException (nameof(Size), "WriteVoid Size < 2");
|
||||
|
||||
if (file == null)
|
||||
throw new ArgumentNullException (nameof(file), "WriteVoid file");
|
||||
|
||||
if (offset + Size > (ulong)(file.Length))
|
||||
throw new ArgumentOutOfRangeException (nameof(file), "WriteVoid tries to write out of the file");
|
||||
|
||||
|
||||
ByteVector vector;
|
||||
int datasize;
|
||||
|
||||
if (Size < 100) {
|
||||
vector = new ByteVector (2);
|
||||
datasize = (int)Size - 2;
|
||||
vector[0] = (byte)MatroskaID.Void; // size = 1
|
||||
vector[1] = (byte)(0x80 | datasize); // Marker + data-size
|
||||
} else {
|
||||
vector = new ByteVector (9);
|
||||
datasize = (int)Size - 9;
|
||||
vector[0] = (byte)MatroskaID.Void; // size = 1
|
||||
vector[1] = 0x01; // set marker
|
||||
|
||||
// Set data size
|
||||
int mask = datasize;
|
||||
for (int i = 8; i > 1; i--) {
|
||||
vector[i] = (byte)(mask & 0xFF);
|
||||
mask >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
file.Insert (vector, (long)Offset, vector.Count);
|
||||
|
||||
// Update this object
|
||||
ebml_id = (uint)MatroskaID.Void;
|
||||
DataOffset = Offset + (ulong)vector.Count;
|
||||
DataSize = (ulong)datasize;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Remove the EBML element from the file
|
||||
/// </summary>
|
||||
/// <returns>Size difference compare to previous EBML size</returns>
|
||||
public long Remove ()
|
||||
{
|
||||
long ret = -(long)Size;
|
||||
|
||||
file.RemoveBlock ((long)Offset, (long)Size);
|
||||
|
||||
// Invalidate this object
|
||||
ebml_id = 0;
|
||||
DataOffset = offset;
|
||||
DataSize = 0;
|
||||
file = null;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9935d41c1f28aa7579c5e3b81a11e1da
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 00e44660739fad50fb5cb7c788045b12
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,119 @@
|
||||
//
|
||||
// SimpleTag.cs:
|
||||
//
|
||||
// Author:
|
||||
// Sebastien Mouy <starwer@laposte.net>
|
||||
//
|
||||
// Copyright (C) 2017 Starwer
|
||||
//
|
||||
// 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.Matroska
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Represent a Matroska element that has an Unique Identifier, and can be tagged.
|
||||
/// </summary>
|
||||
public interface IUIDElement
|
||||
{
|
||||
/// <summary>
|
||||
/// Unique ID representing the file, as random as possible (setting zero will generate automatically a new one).
|
||||
/// </summary>
|
||||
ulong UID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the Tag type the UID should be represented by, or 0 if undefined
|
||||
/// </summary>
|
||||
MatroskaID UIDType { get; }
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Represent a basic Matroska UID element
|
||||
/// </summary>
|
||||
public class UIDElement : IUIDElement
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Create a UIDElement Stub
|
||||
/// </summary>
|
||||
/// <param name="type">Tag-type the UID represents</param>
|
||||
/// <param name="uid">UID of the element</param>
|
||||
public UIDElement (MatroskaID type, ulong uid)
|
||||
{
|
||||
UID = uid;
|
||||
|
||||
if (type == MatroskaID.TagTrackUID
|
||||
|| type == MatroskaID.TagEditionUID
|
||||
|| type == MatroskaID.TagChapterUID
|
||||
|| type == MatroskaID.TagAttachmentUID)
|
||||
UIDType = type;
|
||||
else
|
||||
UIDType = 0;
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Statics
|
||||
|
||||
static readonly Random random = new Random ();
|
||||
|
||||
/// <summary>
|
||||
/// Generate a new random UID
|
||||
/// </summary>
|
||||
/// <param name="ret">Value of the UID to be generated. A zero value will randomize it.</param>
|
||||
/// <returns>Generated UID.</returns>
|
||||
public static ulong GenUID (ulong ret = 0)
|
||||
{
|
||||
while (ret == 0) {
|
||||
ret = ((ulong)random.Next ()) << 32;
|
||||
ret |= (uint)random.Next ();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region IUIDElement Boilerplate
|
||||
|
||||
/// <summary>
|
||||
/// Unique ID representing the element, as random as possible (setting zero will generate automatically a new one).
|
||||
/// </summary>
|
||||
public ulong UID {
|
||||
get { return _UID; }
|
||||
set { _UID = GenUID (value); }
|
||||
}
|
||||
|
||||
ulong _UID = GenUID ();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get the Tag type the UID should be represented by, or 0 if undefined
|
||||
/// </summary>
|
||||
public MatroskaID UIDType { get; private set; } = 0;
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0fe1585063c4447dc9d30b572628a8ef
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,549 @@
|
||||
//
|
||||
// MatroskaIDs.cs:
|
||||
//
|
||||
// Author:
|
||||
// Julien Moutte <julien@fluendo.com>
|
||||
// Sebastien Mouy <starwer@laposte.net>
|
||||
//
|
||||
// Copyright (C) 2011 FLUENDO S.A.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
|
||||
namespace TagLib.Matroska
|
||||
{
|
||||
/// <summary>
|
||||
/// Public enumeration listing Matroska specific EBML Identifiers.
|
||||
/// </summary>
|
||||
public enum MatroskaID : uint
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates a Matroska Segment EBML element.
|
||||
/// </summary>
|
||||
Segment = 0x18538067,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates a Matroska Segment Info EBML element.
|
||||
/// </summary>
|
||||
SegmentInfo = 0x1549A966,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates a Matroska Tracks EBML Element.
|
||||
/// </summary>
|
||||
Tracks = 0x1654AE6B,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates a Matroska Cues EBML element.
|
||||
/// </summary>
|
||||
Cues = 0x1C53BB6B,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates a Matroska Tags EBML element.
|
||||
/// </summary>
|
||||
Tags = 0x1254C367,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates a Matroska Seek Head EBML element.
|
||||
/// </summary>
|
||||
SeekHead = 0x114D9B74,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates a Matroska Cluster EBML element.
|
||||
/// </summary>
|
||||
Cluster = 0x1F43B675,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates a Matroska Attachments EBML element.
|
||||
/// </summary>
|
||||
Attachments = 0x1941A469,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates a Matroska Chapters EBML element.
|
||||
/// </summary>
|
||||
Chapters = 0x1043A770,
|
||||
|
||||
/* IDs in the SegmentInfo master */
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Code Scale EBML element.
|
||||
/// </summary>
|
||||
TimeCodeScale = 0x2AD7B1,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates a Matroska Duration EBML element.
|
||||
/// </summary>
|
||||
Duration = 0x4489,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates a Matroska Writing App EBML element.
|
||||
/// </summary>
|
||||
WrittingApp = 0x5741,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates a Matroska Muxing App EBML element.
|
||||
/// </summary>
|
||||
MuxingApp = 0x4D80,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Date UTC EBML element.
|
||||
/// </summary>
|
||||
DateUTC = 0x4461,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Segment UID EBML element.
|
||||
/// </summary>
|
||||
SegmentUID = 0x73A4,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Segment File Name EBML element.
|
||||
/// </summary>
|
||||
SegmentFileName = 0x7384,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Prev UID EBML element.
|
||||
/// </summary>
|
||||
PrevUID = 0x3CB923,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Prev File Name EBML element.
|
||||
/// </summary>
|
||||
PrevFileName = 0x3C83AB,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Nex UID EBML element.
|
||||
/// </summary>
|
||||
NexUID = 0x3EB923,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Nex File Name EBML element.
|
||||
/// </summary>
|
||||
NexFileName = 0x3E83BB,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Title EBML element.
|
||||
/// </summary>
|
||||
Title = 0x7BA9,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Segment Family EBML element.
|
||||
/// </summary>
|
||||
SegmentFamily = 0x4444,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Chapter Translate EBML element.
|
||||
/// </summary>
|
||||
ChapterTranslate = 0x6924,
|
||||
|
||||
/* ID in the Tracks master */
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Track Entry EBML element.
|
||||
/// </summary>
|
||||
TrackEntry = 0xAE,
|
||||
|
||||
/* IDs in the TrackEntry master */
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Track Number EBML element.
|
||||
/// </summary>
|
||||
TrackNumber = 0xD7,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Track UID EBML element.
|
||||
/// </summary>
|
||||
TrackUID = 0x73C5,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Track Type EBML element.
|
||||
/// </summary>
|
||||
TrackType = 0x83,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Track Audio EBML element.
|
||||
/// </summary>
|
||||
TrackAudio = 0xE1,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Track Video EBML element.
|
||||
/// </summary>
|
||||
TrackVideo = 0xE0,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Void EBML element.
|
||||
/// </summary>
|
||||
Void = 0xEC,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska CRC-32 EBML element.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The CRC is computed on all the data of the Master-element it's in.
|
||||
/// The CRC Element should be the first in it's parent master for easier reading.
|
||||
/// All level 1 Elements should include a CRC-32. The CRC in use is the IEEE CRC32 Little Endian.
|
||||
/// </remarks>
|
||||
CRC32 = 0xBF,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Track Encoding EBML element.
|
||||
/// </summary>
|
||||
ContentEncodings = 0x6D80,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Codec ID EBML element.
|
||||
/// </summary>
|
||||
CodecID = 0x86,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Codec Private EBML element.
|
||||
/// </summary>
|
||||
CodecPrivate = 0x63A2,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Codec Name EBML element.
|
||||
/// </summary>
|
||||
CodecName = 0x258688,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Track Name EBML element.
|
||||
/// </summary>
|
||||
TrackName = 0x536E,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Track Language EBML element.
|
||||
/// </summary>
|
||||
TrackLanguage = 0x22B59C,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Track Enabled EBML element.
|
||||
/// </summary>
|
||||
TrackFlagEnabled = 0xB9,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Track Flag Default EBML element.
|
||||
/// </summary>
|
||||
TrackFlagDefault = 0x88,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Track Flag Forced EBML element.
|
||||
/// </summary>
|
||||
TrackFlagForced = 0x55AA,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Track Flag Lacing EBML element.
|
||||
/// </summary>
|
||||
TrackFlagLacing = 0x9C,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Track Min Cache EBML element.
|
||||
/// </summary>
|
||||
TrackMinCache = 0x6DE7,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Track Max Cache EBML element.
|
||||
/// </summary>
|
||||
TrackMaxCache = 0x6DF8,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Track Default Duration EBML element.
|
||||
/// </summary>
|
||||
TrackDefaultDuration = 0x23E383,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Track Time Code Scale EBML element.
|
||||
/// </summary>
|
||||
TrackTimeCodeScale = 0x23314F,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Track Max Block Addition EBML element.
|
||||
/// </summary>
|
||||
MaxBlockAdditionID = 0x55EE,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Track Attachment Link EBML element.
|
||||
/// </summary>
|
||||
TrackAttachmentLink = 0x7446,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Track Overlay EBML element.
|
||||
/// </summary>
|
||||
TrackOverlay = 0x6FAB,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Track Translate EBML element.
|
||||
/// </summary>
|
||||
TrackTranslate = 0x6624,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Track Offset element.
|
||||
/// </summary>
|
||||
TrackOffset = 0x537F,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Codec Settings EBML element.
|
||||
/// </summary>
|
||||
CodecSettings = 0x3A9697,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Codec Info URL EBML element.
|
||||
/// </summary>
|
||||
CodecInfoUrl = 0x3B4040,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Codec Download URL EBML element.
|
||||
/// </summary>
|
||||
CodecDownloadUrl = 0x26B240,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Codec Decode All EBML element.
|
||||
/// </summary>
|
||||
CodecDecodeAll = 0xAA,
|
||||
|
||||
/* IDs in the TrackVideo master */
|
||||
/* NOTE: This one is here only for backward compatibility.
|
||||
* Use _TRACKDEFAULDURATION */
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Video Frame Rate EBML element.
|
||||
/// </summary>
|
||||
VideoFrameRate = 0x2383E3,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Video Display Width EBML element.
|
||||
/// </summary>
|
||||
VideoDisplayWidth = 0x54B0,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Video Display Height EBML element.
|
||||
/// </summary>
|
||||
VideoDisplayHeight = 0x54BA,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Video Display Unit EBML element.
|
||||
/// </summary>
|
||||
VideoDisplayUnit = 0x54B2,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Video Pixel Width EBML element.
|
||||
/// </summary>
|
||||
VideoPixelWidth = 0xB0,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Video Pixel Height EBML element.
|
||||
/// </summary>
|
||||
VideoPixelHeight = 0xBA,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Video Pixel Crop Bottom EBML element.
|
||||
/// </summary>
|
||||
VideoPixelCropBottom = 0x54AA,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Video Pixel Crop Top EBML element.
|
||||
/// </summary>
|
||||
VideoPixelCropTop = 0x54BB,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Video Pixel Crop Left EBML element.
|
||||
/// </summary>
|
||||
VideoPixelCropLeft = 0x54CC,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Video Pixel Crop Right EBML element.
|
||||
/// </summary>
|
||||
VideoPixelCropRight = 0x54DD,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Video Flag Interlaced EBML element.
|
||||
/// </summary>
|
||||
VideoFlagInterlaced = 0x9A,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Video Stereo Mode EBML element.
|
||||
/// </summary>
|
||||
VideoStereoMode = 0x53B8,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Video Aspect Ratio Type EBML element.
|
||||
/// </summary>
|
||||
VideoAspectRatioType = 0x54B3,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Video Colour Space EBML element.
|
||||
/// </summary>
|
||||
VideoColourSpace = 0x2EB524,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Video Gamma Value EBML element.
|
||||
/// </summary>
|
||||
VideoGammaValue = 0x2FB523,
|
||||
|
||||
/* in the Matroska Seek Head master */
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Seek Entry (Master).
|
||||
/// </summary>
|
||||
Seek = 0x4DBB,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Seek ID (Binary).
|
||||
/// </summary>
|
||||
SeekID = 0x53AB,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Seek Position (uint).
|
||||
/// </summary>
|
||||
SeekPosition = 0x53AC,
|
||||
|
||||
|
||||
/* IDs in the TrackAudio master */
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Audio Sampling Freq EBML element.
|
||||
/// </summary>
|
||||
AudioSamplingFreq = 0xB5,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Audio Bit Depth EBML element.
|
||||
/// </summary>
|
||||
AudioBitDepth = 0x6264,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Audio Channels EBML element.
|
||||
/// </summary>
|
||||
AudioChannels = 0x9F,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Audio Channels Position EBML element.
|
||||
/// </summary>
|
||||
AudioChannelsPositions = 0x7D7B,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Audio Output Sampling Freq EBML element.
|
||||
/// </summary>
|
||||
AudioOutputSamplingFreq = 0x78B5,
|
||||
|
||||
/* IDs in the Tags master */
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Tag EBML element.
|
||||
/// </summary>
|
||||
Tag = 0x7373,
|
||||
|
||||
/* in the Tag master */
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Simple Tag EBML element.
|
||||
/// </summary>
|
||||
SimpleTag = 0x67C8,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Targets EBML element.
|
||||
/// </summary>
|
||||
Targets = 0x63C0,
|
||||
|
||||
/* in the SimpleTag master */
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Tag Name EBML element.
|
||||
/// </summary>
|
||||
TagName = 0x45A3,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Tag String EBML element.
|
||||
/// </summary>
|
||||
TagString = 0x4487,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Tag Language EBML element.
|
||||
/// </summary>
|
||||
TagLanguage = 0x447A,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Tag Default EBML element.
|
||||
/// </summary>
|
||||
TagDefault = 0x4484,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Tag Binary EBML element.
|
||||
/// </summary>
|
||||
TagBinary = 0x4485,
|
||||
|
||||
/* in the Targets master */
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Target Type Value EBML element (UINT).
|
||||
/// </summary>
|
||||
TargetTypeValue = 0x68CA,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Target Type EBML element (string).
|
||||
/// </summary>
|
||||
TargetType = 0x63CA,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Target Tag Track UID EBML element (UINT).
|
||||
/// </summary>
|
||||
TagTrackUID = 0x63C5,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Target Tag Edition UID EBML element (UINT).
|
||||
/// </summary>
|
||||
TagEditionUID = 0x63C9,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Target Tag Chapter UID EBML element (UINT).
|
||||
/// </summary>
|
||||
TagChapterUID = 0x63C4,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Target Tag Attachment UID EBML element (UINT).
|
||||
/// </summary>
|
||||
TagAttachmentUID = 0x63C6,
|
||||
|
||||
|
||||
/* in the Attachments master */
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska attached file.
|
||||
/// </summary>
|
||||
AttachedFile = 0x61A7,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska human-friendly name for the attached file.
|
||||
/// </summary>
|
||||
FileDescription = 0x467E,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Filename of the attached file.
|
||||
/// </summary>
|
||||
FileName = 0x466E,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska MIME type of the file.
|
||||
/// </summary>
|
||||
FileMimeType = 0x4660,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska data of the file.
|
||||
/// </summary>
|
||||
FileData = 0x465C,
|
||||
|
||||
/// <summary>
|
||||
/// Indicate a Matroska Unique ID representing the file, as random as possible.
|
||||
/// </summary>
|
||||
FileUID = 0x46AE
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dd175d3dd62b5062ca13ba2d98028987
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,125 @@
|
||||
//
|
||||
// SimpleTag.cs:
|
||||
//
|
||||
// Author:
|
||||
// Sebastien Mouy <starwer@laposte.net>
|
||||
//
|
||||
// Copyright (C) 2017 Starwer
|
||||
//
|
||||
// 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.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
namespace TagLib.Matroska
|
||||
{
|
||||
/// <summary>
|
||||
/// Describes a SimpleTag content. The TagName property is not part of the SimpleTag.
|
||||
/// A <see cref="Tag"/> object may contain several <see cref="SimpleTag"/>.
|
||||
/// A <see cref="SimpleTag"/> object may contains several <see cref="SimpleTag"/>.
|
||||
/// </summary>
|
||||
public class SimpleTag : ByteVector
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
public SimpleTag ()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Construct from value
|
||||
/// </summary>
|
||||
public SimpleTag (ByteVector value)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Indicate if the content of the SimpleTag is in binary (true) or as a string (false).
|
||||
/// </summary>
|
||||
public bool TagBinary = false;
|
||||
|
||||
/// <summary>
|
||||
/// Indication to know if this is the default/original language to use for the given tag.
|
||||
/// </summary>
|
||||
public bool TagDefault = true;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the language of the tag, as a string.
|
||||
/// </summary>
|
||||
public string TagLanguage {
|
||||
get {
|
||||
var ret = Language.ToString ();
|
||||
return string.IsNullOrEmpty (ret) ? "und" : ret;
|
||||
}
|
||||
set {
|
||||
if (string.IsNullOrEmpty (value) || value == "und") {
|
||||
Language = CultureInfo.InvariantCulture;
|
||||
} else {
|
||||
try {
|
||||
Language = new CultureInfo (value);
|
||||
} catch {
|
||||
Language = CultureInfo.InvariantCulture;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the language of the tag.
|
||||
/// </summary>
|
||||
public CultureInfo Language = CultureInfo.InvariantCulture;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get/Set the data contained in the SimpleTag
|
||||
/// </summary>
|
||||
public ByteVector Value {
|
||||
get { return this; }
|
||||
set { Clear (); Add (value); }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Children SimpleTag nested inside this SimpleTag
|
||||
/// </summary>
|
||||
public Dictionary<string, List<SimpleTag>> SimpleTags = null;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Implicit Conversions
|
||||
|
||||
/// <summary>
|
||||
/// Convert a SimpleTag to a String in the Default encoding
|
||||
/// </summary>
|
||||
/// <param name="v"></param>
|
||||
public static implicit operator string (SimpleTag v)
|
||||
{
|
||||
return v?.ToString (StringType.UTF8);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eddebb00e71a62b07a3df8087973aa93
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,86 @@
|
||||
//
|
||||
// SubtitleTrack.cs:
|
||||
//
|
||||
// Author:
|
||||
// Julien Moutte <julien@fluendo.com>
|
||||
//
|
||||
// Copyright (C) 2011 FLUENDO S.A.
|
||||
//
|
||||
// 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.Collections.Generic;
|
||||
|
||||
namespace TagLib.Matroska
|
||||
{
|
||||
/// <summary>
|
||||
/// Describes a Matroska Subtitle Track.
|
||||
/// </summary>
|
||||
public class SubtitleTrack : Track
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a <see cref="SubtitleTrack" /> parsing from provided
|
||||
/// file data.
|
||||
/// Parsing will be done reading from _file at position references by
|
||||
/// parent element's data section.
|
||||
/// </summary>
|
||||
/// <param name="_file"><see cref="File" /> instance to read from.</param>
|
||||
/// <param name="element">Parent <see cref="EBMLreader" />.</param>
|
||||
public SubtitleTrack (File _file, EBMLreader element)
|
||||
: base (_file, element)
|
||||
{
|
||||
// Here we handle the unknown elements we know, and store the rest
|
||||
foreach (EBMLreader elem in base.UnknownElements) {
|
||||
MatroskaID matroska_id = elem.ID;
|
||||
|
||||
switch (matroska_id) {
|
||||
default:
|
||||
UnknownElements.Add (elem);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public fields
|
||||
|
||||
/// <summary>
|
||||
/// List of unknown elements encountered while parsing.
|
||||
/// </summary>
|
||||
public new List<EBMLreader> UnknownElements { get; } = new List<EBMLreader>();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public methods
|
||||
|
||||
#endregion
|
||||
|
||||
#region ICodec
|
||||
|
||||
/// <summary>
|
||||
/// This type of track only has text media type.
|
||||
/// </summary>
|
||||
public override MediaTypes MediaTypes {
|
||||
get {
|
||||
return MediaTypes.Text;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 168f0a6ea9893b8d08c795623d1e72e4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 68b75afa0a1569beea982c60cd9da977
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,292 @@
|
||||
//
|
||||
// Tags.cs:
|
||||
//
|
||||
// Author:
|
||||
// Sebastien Mouy <starwer@laposte.net>
|
||||
//
|
||||
// Copyright (C) 2017 Starwer
|
||||
//
|
||||
// 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;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace TagLib.Matroska
|
||||
{
|
||||
/// <summary>
|
||||
/// Describes all the Matroska Tags in a file as a list, ordered from higher TargetTypeValue to lower.
|
||||
/// A <see cref="Tags"/> object contains several <see cref="Tag"/>
|
||||
/// </summary>
|
||||
public class Tags : Collection<Tag>
|
||||
{
|
||||
#region Private fields/Properties
|
||||
|
||||
// Store the Attachments
|
||||
Attachment[] attachments = new Attachment[0];
|
||||
|
||||
readonly List<Track> _Tracks;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="tracks">List of Matroska tracks</param>
|
||||
public Tags (List<Track> tracks)
|
||||
{
|
||||
_Tracks = tracks;
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Override Collection, to keep the items ordered
|
||||
|
||||
/// <summary>
|
||||
/// Try to Insert an element to the Tag list at a given index, but can insert it at another index if the
|
||||
/// index doesn't keep this list sorted by descending TargetTypeValue
|
||||
/// </summary>
|
||||
/// <param name="index">index at which the Tag element should be preferably inserted</param>
|
||||
/// <param name="tag">Tag element to be inserted in the Tag list</param>
|
||||
protected override void InsertItem (int index, Tag tag)
|
||||
{
|
||||
if (tag == null)
|
||||
throw new ArgumentNullException (nameof(tag), "Can't add a null Matroska.Tag to a Matroska.Tags object");
|
||||
|
||||
// Remove duplicate
|
||||
for (int j = 0; j < Count; j++) {
|
||||
if (this[j] == tag) {
|
||||
RemoveAt (j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (index < 0 || index >= Count || this[index].TargetTypeValue < tag.TargetTypeValue || (index + 1 < Count && this[index + 1].TargetTypeValue > tag.TargetTypeValue)) {
|
||||
for (index = Count - 1; index >= 0; index--) {
|
||||
if (this[index].TargetTypeValue > tag.TargetTypeValue)
|
||||
break;
|
||||
if (this[index].TargetTypeValue == tag.TargetTypeValue && (this[index].Elements == null || tag.Elements != null))
|
||||
break;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
base.InsertItem (index, tag);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Replace a tag in the list.
|
||||
/// </summary>
|
||||
/// <param name="index">Index of the lement to be replaced</param>
|
||||
/// <param name="tag">tag to replace the older one</param>
|
||||
protected override void SetItem (int index, Tag tag)
|
||||
{
|
||||
RemoveItem (index);
|
||||
InsertItem (index, tag);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears the values stored in the current Tags and Children.
|
||||
/// </summary>
|
||||
protected override void ClearItems ()
|
||||
{
|
||||
Title = null;
|
||||
var medium = Medium;
|
||||
|
||||
foreach (var tag in this) {
|
||||
tag.Clear ();
|
||||
}
|
||||
|
||||
base.ClearItems ();
|
||||
|
||||
// Keep Medium Tag reference unchanged (if any)
|
||||
if (medium != null) Add (medium);
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <summary>
|
||||
/// Find the first Tag of a given TargetTypeValue
|
||||
/// </summary>
|
||||
/// <param name="targetType">TargetTypeValue to find</param>
|
||||
/// <param name="medium">null: any kind, true: represent the current medium, false: represent a sub-element</param>
|
||||
/// <returns>the Tag if match found, null otherwise</returns>
|
||||
public Tag Get (TargetType targetType, bool? medium = true)
|
||||
{
|
||||
Tag ret = null;
|
||||
int i;
|
||||
|
||||
|
||||
// Coerce: Valid values are: 10 20 30 40 50 60 70
|
||||
ushort targetTypeValue = (ushort)targetType;
|
||||
targetTypeValue = (ushort)
|
||||
(targetTypeValue > 70 ? 70
|
||||
: targetTypeValue < 10 ? 10
|
||||
: (targetTypeValue / 10) * 10
|
||||
);
|
||||
|
||||
// Find first match of the given targetValue
|
||||
// List is sorted in descending TargetTypeValue
|
||||
for (i = Count - 1; i >= 0; i--) {
|
||||
if (targetTypeValue == this[i].TargetTypeValue) {
|
||||
ret = this[i];
|
||||
if (medium != null) {
|
||||
bool isMedium = (ret.Elements == null);
|
||||
if (medium == isMedium) break;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return i >= 0 ? ret : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find the first Tag applying to an object (Matroska UID), matching a TargetTypeValue
|
||||
/// </summary>
|
||||
/// <param name="UIDelement">Matroska Track, Edition, Chapter or Attachment (element having an UID)</param>
|
||||
/// <param name="targetTypeValue">TargetTypeValue to match (default: match any)</param>
|
||||
/// <returns>the first matching Tag representing the UID, or null if not found.</returns>
|
||||
public Tag Get (IUIDElement UIDelement, ushort targetTypeValue = 0)
|
||||
{
|
||||
int i;
|
||||
|
||||
ulong UID = UIDelement.UID;
|
||||
|
||||
for (i = Count - 1; i >= 0; i--) {
|
||||
if (targetTypeValue == 0 || targetTypeValue == this[i].TargetTypeValue) {
|
||||
var ret = this[i];
|
||||
if (ret.Elements != null) {
|
||||
foreach (var uid in ret.Elements) {
|
||||
if (uid.UID == UID) return ret; // found
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Properties
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Define if this represent a video content (true), or an audio content (false)
|
||||
/// </summary>
|
||||
public bool IsVideo = false;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Title of the medium, from the Segment
|
||||
/// </summary>
|
||||
public string Title { get; set; }
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the Tag that represents the current medium (file)
|
||||
/// </summary>
|
||||
public Tag Medium {
|
||||
get {
|
||||
Tag ret = null;
|
||||
bool vid = IsVideo;
|
||||
|
||||
// Try to find a default TargetType
|
||||
for (int i = Count - 1; i >= 0; i--) {
|
||||
ret = this[i];
|
||||
if (ret.TargetType == TargetType.DEFAULT) // Avoid CD/DVD
|
||||
{
|
||||
if (ret.Elements == null) return ret;
|
||||
}
|
||||
}
|
||||
|
||||
// Lower level without UID is the Tag representing the file
|
||||
// List is sorted in descending TargetTypeValue
|
||||
for (int i = Count - 1; i >= 0; i--) {
|
||||
ret = this[i];
|
||||
if (ret.TargetTypeValue != 40 || !vid) // Avoid CD/DVD
|
||||
{
|
||||
if (ret.Elements == null) break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the Tag that represents the Collection the current medium (file) belongs to.
|
||||
/// For Audio, this should be an Album, type 50 (itself if the mka file represents an album).
|
||||
/// For Video, this should be a Collection, type 70.
|
||||
/// </summary>
|
||||
public Tag Album {
|
||||
get {
|
||||
TargetType targetValue = IsVideo ? TargetType.COLLECTION : TargetType.ALBUM;
|
||||
return Get (targetValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets a collection of Attachments associated with
|
||||
/// the media represented by the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="T:Attachment[]" /> containing a collection of
|
||||
/// attachments associated with the media represented by the
|
||||
/// current instance or an empty array if none are present.
|
||||
/// </value>
|
||||
public Attachment[] Attachments {
|
||||
get {
|
||||
return attachments;
|
||||
}
|
||||
set {
|
||||
if (value == null) {
|
||||
if (attachments.Length > 0) attachments = new Attachment[0];
|
||||
} else {
|
||||
attachments = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get direct access to the Matroska Tracks.
|
||||
/// </summary>
|
||||
public ReadOnlyCollection<Track> Tracks {
|
||||
get { return _Tracks.AsReadOnly (); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2e5e763ff71b52aaca2d8b8be98ad491
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,146 @@
|
||||
//
|
||||
// TargetType.cs:
|
||||
//
|
||||
// Author:
|
||||
// Sebastien Mouy <starwer@laposte.net>
|
||||
//
|
||||
// Copyright (C) 2011 FLUENDO S.A.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
|
||||
namespace TagLib.Matroska
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a Matroska TargetType.
|
||||
/// The TargetType element allows tagging of different parts that are inside or outside a given file.
|
||||
/// For example in an audio file with one song you could have information about the album it comes
|
||||
/// from and even the CD set even if it's not found in the file.
|
||||
/// </summary>
|
||||
public enum TargetType : ushort
|
||||
{
|
||||
/// <summary>
|
||||
/// Audio/Video: The high hierarchy consisting of many different lower items
|
||||
/// </summary>
|
||||
COLLECTION = 70,
|
||||
|
||||
/// <summary>
|
||||
/// Audio/Video: a list of lower levels grouped together
|
||||
/// </summary>
|
||||
VOLUME = 60,
|
||||
|
||||
/// <summary>
|
||||
/// Audio: a list of lower levels grouped together
|
||||
/// </summary>
|
||||
///
|
||||
EDITION = 61,
|
||||
|
||||
/// <summary>
|
||||
/// Audio: a list of lower levels grouped together
|
||||
/// </summary>
|
||||
ISSUE = 62,
|
||||
|
||||
/// <summary>
|
||||
/// Audio: a list of lower levels grouped together
|
||||
/// </summary>
|
||||
OPUS = 63,
|
||||
|
||||
/// <summary>
|
||||
/// Video: a list of lower levels grouped together
|
||||
/// </summary>
|
||||
SEASON = 64,
|
||||
|
||||
/// <summary>
|
||||
/// Video: a list of lower levels grouped together
|
||||
/// </summary>
|
||||
SEQUEL = 65,
|
||||
|
||||
/// <summary>
|
||||
/// Audio: the most common grouping level of music and video (equals to an episode for TV series)
|
||||
/// </summary>
|
||||
ALBUM = 50,
|
||||
|
||||
/// <summary>
|
||||
/// Audio: the most common grouping level of music and video (equals to an episode for TV series)
|
||||
/// </summary>
|
||||
OPERA = 51,
|
||||
|
||||
/// <summary>
|
||||
/// Audio/Video: the most common grouping level of music and video (equals to an episode for TV series)
|
||||
/// </summary>
|
||||
CONCERT = 52,
|
||||
|
||||
/// <summary>
|
||||
/// Video: the most common grouping level of music and video (equals to an episode for TV series)
|
||||
/// </summary>
|
||||
MOVIE = 53,
|
||||
|
||||
/// <summary>
|
||||
/// Video: the most common grouping level of music and video (equals to an episode for TV series)
|
||||
/// </summary>
|
||||
EPISODE = 54,
|
||||
|
||||
/// <summary>
|
||||
/// Represent the default TargetType (an empty Targets), i.e. targets everything in the segment.
|
||||
/// </summary>
|
||||
DEFAULT = 55,
|
||||
|
||||
/// <summary>
|
||||
/// Audio/Video: when an album or episode has different logical parts
|
||||
/// </summary>
|
||||
PART = 40,
|
||||
|
||||
/// <summary>
|
||||
/// Audio/Video: when an album or episode has different logical parts
|
||||
/// </summary>
|
||||
SESSION = 41,
|
||||
|
||||
/// <summary>
|
||||
/// Audio: the common parts of an album or a movie
|
||||
/// </summary>
|
||||
TRACK = 30,
|
||||
|
||||
/// <summary>
|
||||
/// Audio: the common parts of an album or a movie
|
||||
/// </summary>
|
||||
SONG = 31,
|
||||
|
||||
/// <summary>
|
||||
/// Video: the common parts of an album or a movie
|
||||
/// </summary>
|
||||
CHAPTER = 32,
|
||||
|
||||
/// <summary>
|
||||
/// Audio: corresponds to parts of a track for audio (like a movement)
|
||||
/// </summary>
|
||||
SUBTRACK = 20,
|
||||
|
||||
/// <summary>
|
||||
/// Audio: corresponds to parts of a track for audio (like a movement)
|
||||
/// </summary>
|
||||
MOVEMENT = 21,
|
||||
|
||||
/// <summary>
|
||||
/// Video: corresponds to parts of a track for audio (like a movement)
|
||||
/// </summary>
|
||||
SCENE = 22,
|
||||
|
||||
/// <summary>
|
||||
/// Video: the lowest hierarchy found in music or movies
|
||||
/// </summary>
|
||||
SHOT = 10
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0a619c5df2be0e25da875bc2dfc28c85
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,170 @@
|
||||
//
|
||||
// Track.cs:
|
||||
//
|
||||
// Author:
|
||||
// Julien Moutte <julien@fluendo.com>
|
||||
//
|
||||
// Copyright (C) 2011 FLUENDO S.A.
|
||||
//
|
||||
// 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.Matroska
|
||||
{
|
||||
/// <summary>
|
||||
/// Describes a Matroska Track.
|
||||
/// </summary>
|
||||
public class Track : ICodec, IUIDElement
|
||||
{
|
||||
#region Private fields
|
||||
|
||||
#pragma warning disable 414 // Assigned, never used
|
||||
readonly ulong track_number;
|
||||
readonly string track_codec_id;
|
||||
readonly string track_codec_name;
|
||||
readonly string track_name;
|
||||
readonly string track_language;
|
||||
readonly bool track_enabled;
|
||||
readonly bool track_default;
|
||||
readonly ByteVector codec_data;
|
||||
#pragma warning restore 414
|
||||
|
||||
readonly List<EBMLreader> unknown_elems = new List<EBMLreader> ();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a <see cref="Track" /> parsing from provided
|
||||
/// file data.
|
||||
/// Parsing will be done reading from _file at position references by
|
||||
/// parent element's data section.
|
||||
/// </summary>
|
||||
/// <param name="_file"><see cref="File" /> instance to read from.</param>
|
||||
/// <param name="element">Parent <see cref="EBMLreader" />.</param>
|
||||
public Track (File _file, EBMLreader element)
|
||||
{
|
||||
ulong i = 0;
|
||||
|
||||
while (i < element.DataSize) {
|
||||
EBMLreader child = new EBMLreader (_file, element.DataOffset + i);
|
||||
|
||||
MatroskaID matroska_id = child.ID;
|
||||
|
||||
switch (matroska_id) {
|
||||
case MatroskaID.TrackNumber:
|
||||
track_number = child.ReadULong ();
|
||||
break;
|
||||
case MatroskaID.TrackUID:
|
||||
_UID = child.ReadULong ();
|
||||
break;
|
||||
case MatroskaID.CodecID:
|
||||
track_codec_id = child.ReadString ();
|
||||
break;
|
||||
case MatroskaID.CodecName:
|
||||
track_codec_name = child.ReadString ();
|
||||
break;
|
||||
case MatroskaID.TrackName:
|
||||
track_name = child.ReadString ();
|
||||
break;
|
||||
case MatroskaID.TrackLanguage:
|
||||
track_language = child.ReadString ();
|
||||
break;
|
||||
case MatroskaID.TrackFlagEnabled:
|
||||
track_enabled = child.ReadBool ();
|
||||
break;
|
||||
case MatroskaID.TrackFlagDefault:
|
||||
track_default = child.ReadBool ();
|
||||
break;
|
||||
case MatroskaID.CodecPrivate:
|
||||
codec_data = child.ReadBytes ();
|
||||
break;
|
||||
default:
|
||||
unknown_elems.Add (child);
|
||||
break;
|
||||
}
|
||||
|
||||
i += child.Size;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public fields
|
||||
|
||||
/// <summary>
|
||||
/// List of unknown elements encountered while parsing.
|
||||
/// </summary>
|
||||
public List<EBMLreader> UnknownElements {
|
||||
get { return unknown_elems; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public methods
|
||||
|
||||
#endregion
|
||||
|
||||
#region ICodec
|
||||
|
||||
/// <summary>
|
||||
/// Describes track duration.
|
||||
/// </summary>
|
||||
public virtual TimeSpan Duration {
|
||||
get { return TimeSpan.Zero; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Describes track media types.
|
||||
/// </summary>
|
||||
public virtual MediaTypes MediaTypes {
|
||||
get { return MediaTypes.None; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Track description.
|
||||
/// </summary>
|
||||
public virtual string Description {
|
||||
get { return $"{track_codec_name} {track_language}"; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IUIDElement Boilerplate
|
||||
|
||||
/// <summary>
|
||||
/// Unique ID representing the element, as random as possible (setting zero will generate automatically a new one).
|
||||
/// </summary>
|
||||
public ulong UID {
|
||||
get { return _UID; }
|
||||
set { _UID = UIDElement.GenUID (value); }
|
||||
}
|
||||
|
||||
ulong _UID = UIDElement.GenUID ();
|
||||
|
||||
/// <summary>
|
||||
/// Get the Tag type the UID should be represented by, or 0 if undefined
|
||||
/// </summary>
|
||||
public MatroskaID UIDType { get { return MatroskaID.TagTrackUID; } }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 25d4925cb4f75c09ead02371134648e0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,189 @@
|
||||
//
|
||||
// VideoTrack.cs:
|
||||
//
|
||||
// Author:
|
||||
// Julien Moutte <julien@fluendo.com>
|
||||
//
|
||||
// Copyright (C) 2011 FLUENDO S.A.
|
||||
//
|
||||
// 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.Collections.Generic;
|
||||
|
||||
namespace TagLib.Matroska
|
||||
{
|
||||
/// <summary>
|
||||
/// Enumeration describing supported Video Aspect Ratio types.
|
||||
/// </summary>
|
||||
public enum VideoAspectRatioType
|
||||
{
|
||||
/// <summary>
|
||||
/// Free Aspect Ratio.
|
||||
/// </summary>
|
||||
AspectRatioModeFree = 0x0,
|
||||
/// <summary>
|
||||
/// Keep Aspect Ratio.
|
||||
/// </summary>
|
||||
AspectRatioModeKeep = 0x1,
|
||||
/// <summary>
|
||||
/// Fixed Aspect Ratio.
|
||||
/// </summary>
|
||||
AspectRatioModeFixed = 0x2
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Describes a Matroska Video Track.
|
||||
/// </summary>
|
||||
public class VideoTrack : Track, IVideoCodec
|
||||
{
|
||||
#region Private fields
|
||||
|
||||
#pragma warning disable 414 // Assigned, never used
|
||||
readonly ulong width;
|
||||
readonly ulong height;
|
||||
readonly ulong disp_width;
|
||||
readonly ulong disp_height;
|
||||
readonly double framerate;
|
||||
readonly bool interlaced;
|
||||
readonly VideoAspectRatioType ratio_type;
|
||||
readonly ByteVector fourcc;
|
||||
#pragma warning restore 414
|
||||
|
||||
readonly List<EBMLreader> unknown_elems = new List<EBMLreader> ();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a <see cref="VideoTrack" /> parsing from provided
|
||||
/// file data.
|
||||
/// Parsing will be done reading from _file at position references by
|
||||
/// parent element's data section.
|
||||
/// </summary>
|
||||
/// <param name="_file"><see cref="File" /> instance to read from.</param>
|
||||
/// <param name="element">Parent <see cref="EBMLreader" />.</param>
|
||||
public VideoTrack (File _file, EBMLreader element)
|
||||
: base (_file, element)
|
||||
{
|
||||
// Here we handle the unknown elements we know, and store the rest
|
||||
foreach (EBMLreader elem in base.UnknownElements) {
|
||||
var matroska_id = elem.ID;
|
||||
|
||||
|
||||
switch (matroska_id) {
|
||||
case MatroskaID.TrackVideo: {
|
||||
ulong i = 0;
|
||||
|
||||
while (i < elem.DataSize) {
|
||||
EBMLreader child = new EBMLreader (_file, elem.DataOffset + i);
|
||||
|
||||
matroska_id = child.ID;
|
||||
|
||||
switch (matroska_id) {
|
||||
case MatroskaID.VideoDisplayWidth:
|
||||
disp_width = child.ReadULong ();
|
||||
break;
|
||||
case MatroskaID.VideoDisplayHeight:
|
||||
disp_height = child.ReadULong ();
|
||||
break;
|
||||
case MatroskaID.VideoPixelWidth:
|
||||
width = child.ReadULong ();
|
||||
break;
|
||||
case MatroskaID.VideoPixelHeight:
|
||||
height = child.ReadULong ();
|
||||
break;
|
||||
case MatroskaID.VideoFrameRate:
|
||||
framerate = child.ReadDouble ();
|
||||
break;
|
||||
case MatroskaID.VideoFlagInterlaced:
|
||||
interlaced = child.ReadBool ();
|
||||
break;
|
||||
case MatroskaID.VideoAspectRatioType:
|
||||
ratio_type = (VideoAspectRatioType)child.ReadULong ();
|
||||
break;
|
||||
case MatroskaID.VideoColourSpace:
|
||||
fourcc = child.ReadBytes ();
|
||||
break;
|
||||
default:
|
||||
unknown_elems.Add (child);
|
||||
break;
|
||||
}
|
||||
|
||||
i += child.Size;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case MatroskaID.TrackDefaultDuration:
|
||||
ulong tmp = elem.ReadULong ();
|
||||
framerate = 1000000000.0 / tmp;
|
||||
break;
|
||||
|
||||
default:
|
||||
unknown_elems.Add (elem);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public fields
|
||||
|
||||
/// <summary>
|
||||
/// List of unknown elements encountered while parsing.
|
||||
/// </summary>
|
||||
public new List<EBMLreader> UnknownElements {
|
||||
get { return unknown_elems; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public methods
|
||||
|
||||
#endregion
|
||||
|
||||
#region ICodec
|
||||
|
||||
/// <summary>
|
||||
/// This type of track only has video media type.
|
||||
/// </summary>
|
||||
public override MediaTypes MediaTypes {
|
||||
get { return MediaTypes.Video; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IVideoCodec
|
||||
|
||||
/// <summary>
|
||||
/// Describes video track width in pixels.
|
||||
/// </summary>
|
||||
public int VideoWidth {
|
||||
get { return (int)width; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Describes video track height in pixels.
|
||||
/// </summary>
|
||||
public int VideoHeight {
|
||||
get { return (int)height; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e6bf8418b23fcca31a4d61dbe9a8e909
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in new issue
Block a user