Switch to the new taglib-sharp version. Add support for opus.
@@ -181,8 +181,8 @@
|
||||
<Project>{8DD1E84B-0B03-4C0B-9B42-1E49F75E7CB1}</Project>
|
||||
<Name>ProgressODoom</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\taglib-sharp\src\taglib-sharp.csproj">
|
||||
<Project>{6B143A39-C7B2-4743-9917-92262C60E9A6}</Project>
|
||||
<ProjectReference Include="..\ThirdParty\taglib-sharp\src\taglib-sharp.csproj">
|
||||
<Project>{1219a514-d3fa-40db-bbb2-92ce05e35839}</Project>
|
||||
<Name>taglib-sharp</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
|
||||
@@ -56,6 +56,7 @@ namespace CUETools.Codecs
|
||||
encoders.Add(new CUEToolsUDC("VBR (lame.exe)", "mp3", false, "V9 V8 V7 V6 V5 V4 V3 V2 V1 V0", "V2", "lame.exe", "--vbr-new -%M - %O"));
|
||||
encoders.Add(new CUEToolsUDC("CBR (lame.exe)", "mp3", false, "96 128 192 256 320", "256", "lame.exe", "-m s -q 0 -b %M --noreplaygain - %O"));
|
||||
encoders.Add(new CUEToolsUDC("oggenc", "ogg", false, "-1 -0.5 0 0.5 1 1.5 2 2.5 3 3.5 4 4.5 5 5.5 6 6.5 7 7.5 8", "3", "oggenc.exe", "-q %M - -o %O"));
|
||||
encoders.Add(new CUEToolsUDC("opusenc", "opus", false, "6 16 32 48 64 96 128 192 256", "128", "opusenc.exe", "--bitrate %M - %O"));
|
||||
encoders.Add(new CUEToolsUDC("nero aac", "m4a", false, "0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9", "0.4", "neroAacEnc.exe", "-q %M -if - -of %O"));
|
||||
encoders.Add(new CUEToolsUDC("qaac tvbr", "m4a", false, "10 20 30 40 50 60 70 80 90 100 110 127", "80", "qaac.exe", "-s -V %M -q 2 - -o %O"));
|
||||
|
||||
@@ -80,6 +81,7 @@ namespace CUETools.Codecs
|
||||
formats.Add("wma", new CUEToolsFormat("wma", CUEToolsTagger.TagLibSharp, true, true, false, true, encoders.GetDefault("wma", true), encoders.GetDefault("wma", false), decoders.GetDefault("wma", true)));
|
||||
formats.Add("mp3", new CUEToolsFormat("mp3", CUEToolsTagger.TagLibSharp, false, true, false, true, null, encoders.GetDefault("mp3", false), null));
|
||||
formats.Add("ogg", new CUEToolsFormat("ogg", CUEToolsTagger.TagLibSharp, false, true, false, true, null, encoders.GetDefault("ogg", false), null));
|
||||
formats.Add("opus", new CUEToolsFormat("opus", CUEToolsTagger.TagLibSharp, false, true, false, true, null, encoders.GetDefault("opus", false), null));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\CUETools.Codecs\CUETools.Codecs.csproj" />
|
||||
<ProjectReference Include="..\taglib-sharp\src\taglib-sharp.csproj" />
|
||||
<ProjectReference Include="..\CUETools.Processor\CUETools.Processor.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -30,7 +30,9 @@
|
||||
<ProjectReference Include="..\CUETools.CTDB\CUETools.CTDB.csproj" />
|
||||
<ProjectReference Include="..\CUETools.Ripper\CUETools.Ripper.csproj" />
|
||||
<ProjectReference Include="..\Freedb\Freedb.csproj" />
|
||||
<ProjectReference Include="..\taglib-sharp\src\taglib-sharp.csproj" />
|
||||
<ProjectReference Include="..\ThirdParty\taglib-sharp\src\taglib-sharp.csproj">
|
||||
<Private>true</Private>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\CUETools.Codecs\CUETools.Codecs.csproj" />
|
||||
<ProjectReference Include="..\taglib-sharp\src\taglib-sharp.csproj" />
|
||||
<ProjectReference Include="..\CUETools.Processor\CUETools.Processor.csproj" />
|
||||
<ProjectReference Include="..\CUETools.CTDB\CUETools.CTDB.csproj" />
|
||||
<ProjectReference Include="..\CUETools.Codecs.BDLPCM\CUETools.Codecs.BDLPCM.csproj" />
|
||||
|
||||
@@ -276,8 +276,8 @@
|
||||
<Project>{5ADCFD6D-BFEA-4B10-BB45-9083BBB56AF4}</Project>
|
||||
<Name>Freedb</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\taglib-sharp\src\taglib-sharp.csproj">
|
||||
<Project>{6b143a39-c7b2-4743-9917-92262c60e9a6}</Project>
|
||||
<ProjectReference Include="..\ThirdParty\taglib-sharp\src\taglib-sharp.csproj">
|
||||
<Project>{1219a514-d3fa-40db-bbb2-92ce05e35839}</Project>
|
||||
<Name>taglib-sharp</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
@@ -319,6 +319,7 @@
|
||||
<None Include="Resources\picture.ico" />
|
||||
<None Include="Resources\wma.ico" />
|
||||
<None Include="Resources\more\card--pencil.png" />
|
||||
<Content Include="Resources\opus.ico" />
|
||||
<Content Include="unrar.dll">
|
||||
</Content>
|
||||
<Content Include="Resources\accuraterip_16.bmp" />
|
||||
|
||||
@@ -107,9 +107,6 @@ EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CUETools.Codecs.TTA", "..\CUETools.Codecs.TTA\CUETools.Codecs.TTA.vcxproj", "{1D1E99BC-6D22-41C0-BD94-FF4DD5EC725B}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CUETools.Converter", "..\CUETools.Converter\CUETools.Converter.csproj", "{115CC5B0-0385-41CD-8A23-6A7EA4C51926}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{6B143A39-C7B2-4743-9917-92262C60E9A6} = {6B143A39-C7B2-4743-9917-92262C60E9A6}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CUEControls", "..\CUEControls\CUEControls.csproj", "{CA4D64E6-6544-4A29-8BA5-7DB08D50D072}"
|
||||
EndProject
|
||||
@@ -173,8 +170,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CUETools.AVX", "..\CUETools
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Third Party Libraries", "Third Party Libraries", "{7E402406-7E51-4F0D-8209-60824C1CD6E8}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "taglib-sharp", "..\taglib-sharp\src\taglib-sharp.csproj", "{6B143A39-C7B2-4743-9917-92262C60E9A6}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WindowsMediaLib", "..\WindowsMediaLib\WindowsMediaLib.csproj", "{7EA4160F-3BBD-47C9-A38C-4053B64B24A8}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CUETools.Codecs.WMA", "..\CUETools.Codecs.WMA\CUETools.Codecs.WMA.csproj", "{082D6B9E-326E-4D15-9798-DE70A6EDAE9E}"
|
||||
@@ -193,6 +188,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CUETools.CTDB.Types", "..\C
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CUETools.Codecs.libFLAC", "..\CUETools.Codecs.libFLAC\CUETools.Codecs.libFLAC.csproj", "{F10AB92C-9AFB-4FC0-94E0-06FCD3CA8155}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "taglib-sharp", "..\ThirdParty\taglib-sharp\src\taglib-sharp.csproj", "{1219A514-D3FA-40DB-BBB2-92CE05E35839}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -983,20 +980,6 @@ Global
|
||||
{CC022842-F2E9-4016-82B8-65A264B642D5}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{CC022842-F2E9-4016-82B8-65A264B642D5}.Release|x64.ActiveCfg = Release|x64
|
||||
{CC022842-F2E9-4016-82B8-65A264B642D5}.Release|x86.ActiveCfg = Release|Win32
|
||||
{6B143A39-C7B2-4743-9917-92262C60E9A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6B143A39-C7B2-4743-9917-92262C60E9A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6B143A39-C7B2-4743-9917-92262C60E9A6}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{6B143A39-C7B2-4743-9917-92262C60E9A6}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{6B143A39-C7B2-4743-9917-92262C60E9A6}.Debug|Win32.ActiveCfg = Debug|Any CPU
|
||||
{6B143A39-C7B2-4743-9917-92262C60E9A6}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{6B143A39-C7B2-4743-9917-92262C60E9A6}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{6B143A39-C7B2-4743-9917-92262C60E9A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6B143A39-C7B2-4743-9917-92262C60E9A6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6B143A39-C7B2-4743-9917-92262C60E9A6}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{6B143A39-C7B2-4743-9917-92262C60E9A6}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{6B143A39-C7B2-4743-9917-92262C60E9A6}.Release|Win32.ActiveCfg = Release|Any CPU
|
||||
{6B143A39-C7B2-4743-9917-92262C60E9A6}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{6B143A39-C7B2-4743-9917-92262C60E9A6}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{7EA4160F-3BBD-47C9-A38C-4053B64B24A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7EA4160F-3BBD-47C9-A38C-4053B64B24A8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7EA4160F-3BBD-47C9-A38C-4053B64B24A8}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
@@ -1117,6 +1100,26 @@ Global
|
||||
{F10AB92C-9AFB-4FC0-94E0-06FCD3CA8155}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{F10AB92C-9AFB-4FC0-94E0-06FCD3CA8155}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{F10AB92C-9AFB-4FC0-94E0-06FCD3CA8155}.Release|x86.Build.0 = Release|Any CPU
|
||||
{1219A514-D3FA-40DB-BBB2-92CE05E35839}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1219A514-D3FA-40DB-BBB2-92CE05E35839}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1219A514-D3FA-40DB-BBB2-92CE05E35839}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{1219A514-D3FA-40DB-BBB2-92CE05E35839}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{1219A514-D3FA-40DB-BBB2-92CE05E35839}.Debug|Win32.ActiveCfg = Debug|Any CPU
|
||||
{1219A514-D3FA-40DB-BBB2-92CE05E35839}.Debug|Win32.Build.0 = Debug|Any CPU
|
||||
{1219A514-D3FA-40DB-BBB2-92CE05E35839}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{1219A514-D3FA-40DB-BBB2-92CE05E35839}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{1219A514-D3FA-40DB-BBB2-92CE05E35839}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{1219A514-D3FA-40DB-BBB2-92CE05E35839}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{1219A514-D3FA-40DB-BBB2-92CE05E35839}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1219A514-D3FA-40DB-BBB2-92CE05E35839}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1219A514-D3FA-40DB-BBB2-92CE05E35839}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{1219A514-D3FA-40DB-BBB2-92CE05E35839}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{1219A514-D3FA-40DB-BBB2-92CE05E35839}.Release|Win32.ActiveCfg = Release|Any CPU
|
||||
{1219A514-D3FA-40DB-BBB2-92CE05E35839}.Release|Win32.Build.0 = Release|Any CPU
|
||||
{1219A514-D3FA-40DB-BBB2-92CE05E35839}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{1219A514-D3FA-40DB-BBB2-92CE05E35839}.Release|x64.Build.0 = Release|Any CPU
|
||||
{1219A514-D3FA-40DB-BBB2-92CE05E35839}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{1219A514-D3FA-40DB-BBB2-92CE05E35839}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -1166,7 +1169,6 @@ Global
|
||||
{84EBB7CB-02C9-40A9-9D32-C641B822DAA2} = {D9D97BB6-002F-4858-8EF2-49B4C4C4DDB4}
|
||||
{0AC7691C-562A-4879-8A11-6C7890BF659B} = {86BBE3FC-E4E5-4190-B675-C6745EAF4E64}
|
||||
{F8C29953-A697-4462-82DC-DA7146654A64} = {4B59E09C-A51F-4B80-91BE-987904DCEF7D}
|
||||
{6B143A39-C7B2-4743-9917-92262C60E9A6} = {7E402406-7E51-4F0D-8209-60824C1CD6E8}
|
||||
{7EA4160F-3BBD-47C9-A38C-4053B64B24A8} = {7E402406-7E51-4F0D-8209-60824C1CD6E8}
|
||||
{082D6B9E-326E-4D15-9798-DE70A6EDAE9E} = {93B7AE1D-DEF6-4A04-A222-5CDE09DF262D}
|
||||
{E75F7CCD-4266-42E1-A039-DC7EB5EDD8F6} = {93B7AE1D-DEF6-4A04-A222-5CDE09DF262D}
|
||||
@@ -1174,6 +1176,7 @@ Global
|
||||
{678875A6-6B3A-4AAC-83B6-D9A72D9016CF} = {BC0C1801-0212-4ECC-92D5-8F2D6F69E888}
|
||||
{2D8D7A03-DFFA-44EF-9299-8BB56D122245} = {BC0C1801-0212-4ECC-92D5-8F2D6F69E888}
|
||||
{F10AB92C-9AFB-4FC0-94E0-06FCD3CA8155} = {93B7AE1D-DEF6-4A04-A222-5CDE09DF262D}
|
||||
{1219A514-D3FA-40DB-BBB2-92CE05E35839} = {7E402406-7E51-4F0D-8209-60824C1CD6E8}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {C634D169-5814-4203-94B6-6A11371DDA95}
|
||||
|
||||
10
CUETools/Properties/Resources.Designer.cs
generated
@@ -439,6 +439,16 @@ namespace JDP.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
|
||||
/// </summary>
|
||||
internal static System.Drawing.Icon opus {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("opus", resourceCulture);
|
||||
return ((System.Drawing.Icon)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
|
||||
/// </summary>
|
||||
|
||||
@@ -112,10 +112,10 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="basket" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
@@ -277,8 +277,10 @@
|
||||
<data name="alarm-clock--minus" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\alarm-clock--minus.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="card--pencil" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\more\card--pencil.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="opus" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\opus.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
</root>
|
||||
BIN
CUETools/Resources/opus.ico
Normal file
|
After Width: | Height: | Size: 766 B |
@@ -64,6 +64,7 @@ namespace JDP
|
||||
m_icon_mgr.SetExtensionIcon(".m4a", global::JDP.Properties.Resources.ipod_sound);
|
||||
m_icon_mgr.SetExtensionIcon(".wma", global::JDP.Properties.Resources.wma);
|
||||
m_icon_mgr.SetExtensionIcon(".ogg", global::JDP.Properties.Resources.ogg);
|
||||
m_icon_mgr.SetExtensionIcon(".opus", global::JDP.Properties.Resources.opus);
|
||||
m_icon_mgr.SetExtensionIcon(".cue", global::JDP.Properties.Resources.cue3);
|
||||
m_icon_mgr.SetExtensionIcon(".#puzzle", global::JDP.Properties.Resources.puzzle);
|
||||
m_icon_mgr.SetExtensionIcon(".#users", global::JDP.Properties.Resources.users);
|
||||
|
||||
2
ThirdParty/taglib-sharp
vendored
31
taglib-sharp/.gitignore
vendored
@@ -1,31 +0,0 @@
|
||||
INSTALL
|
||||
Makefile
|
||||
Makefile.in
|
||||
aclocal.m4
|
||||
autom4te.cache/
|
||||
bin/
|
||||
config.log
|
||||
config.status
|
||||
configure
|
||||
*.exe
|
||||
*.mdb
|
||||
*.pidb
|
||||
*.config
|
||||
install-sh
|
||||
missing
|
||||
src/AssemblyInfo.cs
|
||||
*.pc
|
||||
*.zip
|
||||
tests/samples/tmp*
|
||||
docs/*.xml
|
||||
docs/*/*
|
||||
docs/*.tree
|
||||
*.dll.xml
|
||||
examples/*.dll
|
||||
*.userprefs
|
||||
src/*.dll
|
||||
src/*.snk
|
||||
tests/*.dll
|
||||
tests/*.xml
|
||||
test-results
|
||||
.*.swp
|
||||
3
taglib-sharp/.gitmodules
vendored
@@ -1,3 +0,0 @@
|
||||
[submodule "tests/raw-samples"]
|
||||
path = tests/raw-samples
|
||||
url = git://gitorious.org/taglib-sharp/raw-samples.git
|
||||
@@ -1,29 +0,0 @@
|
||||
Maintainer:
|
||||
Gabriel Burt <gabriel.burt@gmail.com>
|
||||
|
||||
Contributors:
|
||||
Aaron Bockover
|
||||
Alexander Kojevnikov
|
||||
Andrés G. Aragoneses
|
||||
Andy Beal
|
||||
Bernd Niedergesaess
|
||||
Bertrand Lorentz
|
||||
Colin Turner
|
||||
Eamon Nerbonne
|
||||
Félix Velasco
|
||||
Gregory S. Chudov
|
||||
Helmut Wahrmann
|
||||
Jeffrey Stedfast
|
||||
Jeroen Asselman
|
||||
John Millikin
|
||||
Julien Moutte
|
||||
Marek Habersack
|
||||
Mike Gemünde
|
||||
Patrick Dehne
|
||||
Paul Lange
|
||||
Ruben Vermeersch
|
||||
Stephane Delcroix
|
||||
Tim Howard
|
||||
|
||||
Creator, past maintainer:
|
||||
Brian Nickel <brian.nickel@gmail.com>
|
||||
@@ -1,504 +0,0 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
||||
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
SUBDIRS = \
|
||||
src \
|
||||
examples \
|
||||
docs
|
||||
|
||||
if !IN_DIST
|
||||
SUBDIRS += tests
|
||||
endif
|
||||
|
||||
DIST_SUBDIRS = \
|
||||
src \
|
||||
examples \
|
||||
docs
|
||||
|
||||
pkgconfig_in_files = taglib-sharp.pc.in
|
||||
pkgconfigdir = $(datadir)/pkgconfig
|
||||
pkgconfig_DATA = $(pkgconfig_in_files:.pc.in=.pc)
|
||||
|
||||
EXTRA_DIST = \
|
||||
$(pkgconfig_in_files) \
|
||||
taglib-sharp.snk \
|
||||
taglib-sharp.sln
|
||||
|
||||
DISTCLEANFILES = taglib-sharp.pc
|
||||
|
||||
MAINTAINERCLEANFILES = \
|
||||
compile \
|
||||
INSTALL \
|
||||
config.h.in \
|
||||
aclocal.m4 \
|
||||
ltmain.sh \
|
||||
Makefile.in \
|
||||
depcomp \
|
||||
missing \
|
||||
install-sh \
|
||||
configure \
|
||||
config.sub \
|
||||
config.guess \
|
||||
mkinstalldirs
|
||||
|
||||
if !IN_DIST
|
||||
test:
|
||||
cd tests; make test; cd ..;
|
||||
endif
|
||||
|
||||
distwin: all
|
||||
mkdir -p $(srcdir)/$(WINDIR)
|
||||
cp $(srcdir)/NEWS $(srcdir)/$(WINDIR)/NEWS.txt
|
||||
cp $(srcdir)/ChangeLog $(srcdir)/$(WINDIR)/ChangeLog.txt
|
||||
cp $(srcdir)/COPYING $(srcdir)/$(WINDIR)/COPYING.txt
|
||||
cp $(srcdir)/README $(srcdir)/$(WINDIR)/README.txt
|
||||
cp $(srcdir)/AUTHORS $(srcdir)/$(WINDIR)/AUTHORS.txt
|
||||
if [ -e $(srcdir)/windows-files ]; \
|
||||
then cp -r $(srcdir)/windows-files/* $(srcdir)/$(WINDIR); \
|
||||
fi
|
||||
cd $(srcdir)/src && make distwin
|
||||
zip -9 -r $(srcdir)/$(WINDIR).zip $(srcdir)/$(WINDIR)
|
||||
rm -rf $(srcdir)/$(WINDIR)
|
||||
|
||||
UPLOAD_HOST = "$$BANSHEE_USER@banshee.fm"
|
||||
UPLOAD_PATH = "web/download.banshee.fm/taglib-sharp"
|
||||
push-release: distcheck distwin
|
||||
[[ -z "$$BANSHEE_USER" ]] && { echo "Set BANSHEE_USER"; exit 1; } || true
|
||||
[[ -z "$$MONO_USER" ]] && { echo "Set MONO_USER"; exit 1; } || true
|
||||
mkdir -p release
|
||||
mv $(WINDIR).zip release
|
||||
mv $(PACKAGE)-$(VERSION).tar.* release
|
||||
cp ChangeLog release/$(PACKAGE)-$(VERSION).changes
|
||||
cp NEWS release/$(PACKAGE)-$(VERSION).news
|
||||
pushd release; sha256sum * > $(PACKAGE)-$(VERSION).sha256sum; popd
|
||||
scp -r release $(UPLOAD_HOST):$(UPLOAD_PATH)/$(VERSION)
|
||||
rm -rf release
|
||||
ssh $(UPLOAD_HOST) rm -f $(UPLOAD_PATH)/LATEST-IS\*
|
||||
ssh $(UPLOAD_HOST) touch $(UPLOAD_PATH)/LATEST-IS-$(VERSION)
|
||||
git tag -a -m "Tag for taglib-sharp release ${VERSION}" taglib-sharp-${VERSION} || bail "Could not create tag"
|
||||
git push origin taglib-sharp-${VERSION} || bail "Failed to push tag to remote"
|
||||
@@ -1,333 +0,0 @@
|
||||
Version 2.0.4.0
|
||||
April 13, 2011
|
||||
|
||||
Fixes and Features in this release include:
|
||||
* Support for Photo metadata
|
||||
+ read/write for EXIF, XMP, PNG, JPEG, TIFF
|
||||
+ read support for many RAW formats
|
||||
+ see examples/ParsePhoto.cs
|
||||
* Support for Matroska metadata reading (eg WebM and .mkv)
|
||||
* Fix File.ReadBlock for slow connections (bgo#639817)
|
||||
|
||||
Contributors to this release:
|
||||
Alexander Kojevnikov, Colin Turner, Gabriel Burt, Jeroen Asselman,
|
||||
Julien Moutte, Marek Habersack, Mike Gemünde, Paul Lange,
|
||||
Ruben Vermeersch, Stephane Delcroix, Tim Howard
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Version 2.0.3.7
|
||||
March 20, 2010
|
||||
|
||||
TagLib# bugs are now tracked at http://bugzilla.gnome.org.
|
||||
|
||||
Fixes and Features in this release include:
|
||||
* Solution/projects migrated to VS format
|
||||
* Fix ID3v2 unsyncing (bgo#593138)
|
||||
* Fix ID3v2.3 exetended header size calculation (bgo#604488)
|
||||
* Make TagLib.File IDisposable (closes any open streams)
|
||||
* Don't throw an exception if RVA2 data is partially incorrect
|
||||
* Fall back to nunit-console is nunit-console2 not found (bgo#593673)
|
||||
* Add build check for `al` tool (bgo#575303)
|
||||
|
||||
Contributors to this release:
|
||||
Alexander Kojevnikov, Andrés G. Aragoneses, Bertrand Lorentz,
|
||||
Eamon Nerbonne, Ruben Vermeersch
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Version 2.0.3.6
|
||||
February 24, 2010
|
||||
|
||||
TagLib# bugs are now tracked at http://bugzilla.gnome.org.
|
||||
|
||||
Fixes and Features in this release include:
|
||||
* Reverse small API break introduced in 2.0.3.5
|
||||
|
||||
Contributors to this release:
|
||||
Gabriel Burt
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Version 2.0.3.5
|
||||
February 23, 2010
|
||||
|
||||
TagLib# bugs are now tracked at http://bugzilla.gnome.org.
|
||||
|
||||
Fixes and Features in this release include:
|
||||
* Add BitsPerSample property (bgo#610585)
|
||||
* Support COMPILATION in ogg (bgo#586336)
|
||||
* Fix removing some/all tag-types (bgo#574653)
|
||||
|
||||
Contributors to this release:
|
||||
Alexander Kojevnikov, Helmut Wahrmann
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Version 2.0.3.4
|
||||
January 26, 2010
|
||||
|
||||
TagLib# bugs are now tracked at http://bugzilla.gnome.org.
|
||||
|
||||
Get releases from http://download.banshee-project.org/taglib-sharp/
|
||||
|
||||
Fixes and Features in this release include:
|
||||
* Fix IndexOutOfRangeException (bgo#607376)
|
||||
* Fix issue with converting/parsing year (bgo#606283)
|
||||
* Support the 'alis' handler code/track type (bgo#584193)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Version 2.0.3.3
|
||||
September 30, 2009
|
||||
|
||||
TagLib# bugs are now tracked at http://bugzilla.gnome.org.
|
||||
|
||||
Get releases from http://download.banshee-project.org/taglib-sharp/
|
||||
|
||||
Fixes and Features in this release include:
|
||||
* Be more robust with tags with NULL bytes in the middle (bgo#558123)
|
||||
* Support AIFF file format (bgo#579261)
|
||||
* Support ADTS AAC files (bgo#580553)
|
||||
* Support for m2v files (bgo#574411)
|
||||
* Support for Sort* values in Ape tags (bgo#571421)
|
||||
* Add new properties: MusicBrainz, ArtistId, ReleaseId, ReleaseArtistId,
|
||||
TrackId, DiscId, ReleaseStatus, ReleaseType, ReleaseCountry, MusicIpId,
|
||||
and AmazonId (bgo#563170)
|
||||
* Add fallback options for album artist getter (bgo#574652)
|
||||
* Fixed bug with Ape.Tag's Pictures setter (bgo#575943)
|
||||
* Fix crashing when parsing some comment frames (bgo#582735)
|
||||
* Fixed CopyTo method (bgo#572382)
|
||||
* Fixed typo in Ogg DiscNumber setter that wrote TrackCount
|
||||
to the DISCTOTAL field (bgo#572382)
|
||||
* Fixed NRE when calling GetTag on FLAC file (bgo#572380)
|
||||
* Build improvements
|
||||
* API documentation fixes
|
||||
|
||||
Contributors to this release:
|
||||
Alexander Kojevnikov, Andy Beal, Bernd Niedergesaess, Bertrand Lorentz,
|
||||
Félix Velasco, Gabriel Burt, Gregory S. Chudov, Helmut Wahrmann,
|
||||
John Millikin, Patrick Dehne
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Version 2.0.3.2
|
||||
February 16, 2009
|
||||
|
||||
TagLib# bugs are now tracked at http://bugzilla.gnome.org.
|
||||
|
||||
Get releases from http://download.banshee-project.org/taglib-sharp/
|
||||
|
||||
Contributors to this release:
|
||||
Aaron Bockover, Andy Beal, Bernd Niedergesaess,
|
||||
Bertrand Lorentz, Gabriel Burt, John Millikin
|
||||
|
||||
Fixes in this release include:
|
||||
* Fix infinite loops when reading/writing video files
|
||||
* Fix parsing ID3v2 with Data Length Indicator set
|
||||
* Fix install/build issues with the docs
|
||||
* Fix casing of APE tags
|
||||
* Add support for *Sort values for artist, album, etc
|
||||
* Install .pc file to datadir since we're noarch
|
||||
* New unit tests for AVI files
|
||||
* Recognize mp1/mp2 extensions and mimetypes
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Version 2.0.3.1
|
||||
January 20, 2009
|
||||
|
||||
TagLib# bugs are now tracked at http://bugzilla.gnome.org.
|
||||
|
||||
Contributors to this release:
|
||||
Andy Beal, Gabriel Burt, Jeffrey Stedfast, John Millikin
|
||||
|
||||
Fixes in this release include:
|
||||
* Add support for artwork in ogg files
|
||||
* Recognize .oga, ogv, .m4b, and some other mimetypes
|
||||
* Add support for Mpeg4 dash atoms
|
||||
* Fix bug with parsing ID3v2 w/ the tag-wide Unsync flag set
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Version 2.0.3.0
|
||||
January 10, 2008
|
||||
|
||||
This release of TagLib# features many bug fixes and a complete rework of the
|
||||
documentation to better serve the Windows community. Fixes include:
|
||||
* Make Asf.Tag enumerable.
|
||||
* Don't duplicate genres stored in "(0)Blues" format.
|
||||
* Save Id3v2.RelativeVolumeFrame as XRVA and XRV in ID3v2.3 and ID3v2.2.
|
||||
* Insert new comments before other comment frames in Id3v2.Tag
|
||||
* Use CultureInfo.CurrentCulture to get the correct comment language in
|
||||
Id3v2.Tag.
|
||||
* Skip iTunes comments in Id3v2.CommentsFrame.
|
||||
* Save multi-string values as a single box with a semicolon separator
|
||||
in Mpeg4.AppleTag to improve compatability with iTunes.
|
||||
* Make the Id3v2.Tag.DefaultVersion = 3 because most commercial programs
|
||||
have some crippling ID3v2.4 problem.
|
||||
* Added Id3v2.Tag.IsCompilation
|
||||
* Don't crash on misformatted field in XiphComment.
|
||||
* Recognize the .divx extension as a RIFF file.
|
||||
* Use one byte rather than four to store compilation in Mpeg4.AppleTag.
|
||||
* Don't check the image format flags anymore in Mpeg4.AppleTag, just use
|
||||
the file contents.
|
||||
* Don't crash in NonContainer.EndTag when the file is less than 128
|
||||
bytes.
|
||||
* Allow saving of multi-page comment packets in Ogg through massive
|
||||
rewrite of pagination.
|
||||
* Allow correct reading of multi-page comment packets in Ogg.Bitstream.
|
||||
* Use try/finally on all load and save operations to prevent files from
|
||||
being left open.
|
||||
* Produce correct output on empty ID3v1 tag.
|
||||
* Remove broken Id3v1.Tag.IsEmpty.
|
||||
* src/TagLib/Riff/List.cs: Make sure fields are cleared when SetValue
|
||||
* Clear value when null is passed in Riff.List.SetValue.
|
||||
* Make Riff.DivXTag.Clear clear the title.
|
||||
* Read genres correctly in Riff.MovieIdTag.
|
||||
* Complete codec descriptions for RIFF and ASF files.
|
||||
* Fix reading of UTF16-BE Id3v2.SynchronizedLyricsFrames.
|
||||
* Throw NotImplementedException for private frames in ID3v2.2.
|
||||
* Fix writing Id3v2.GeneralEncapulatedObjectFrame in UTF16.
|
||||
* Added support for multiple non-indexed artists in ID3v2.3
|
||||
* Correctly parse nil separated UTF-16BE strings.
|
||||
* Allow parsing of variable length years in Ape.Tag.
|
||||
* Fix writing of Mpeg4 files by correctly reading in values to
|
||||
Mpeg4.FileParser.UtdaTree.
|
||||
* Allow parsing of all year lengths in Mpeg4.AppleTag and correctly
|
||||
clear zeroed values.
|
||||
* Use Semicolons rather than commas in Tag.Joined* to reflect the
|
||||
behavior of Windows Media Player.
|
||||
* Remove "WM/GenreID" from Asf.Tag when storing a new genre.
|
||||
* Switch ordering of check in looking for ASF content descriptors to
|
||||
emphasize name rather than order.
|
||||
* Don't throw exception on zero byte strings in ByteVector.ToString ().
|
||||
* Use ContentDescriptionObject.Copyright in Asf.Tag.
|
||||
* Switch order of play_duration and send_duration in Asf.HeaderObject.
|
||||
This is backwards from the specification but conforms to actual files.
|
||||
* Don't count preroll in ASF durations.
|
||||
* Don't double-count position when counting frames.
|
||||
* Ensure Id3v2.FrameHeader is converting headers from versions 2 and 3.
|
||||
* Always set the encoding to default in Id3v2.Tag when writing a frame
|
||||
to prevent misencoding.
|
||||
* Stopped ArgumentOutOfRangeExceptions from occuring when corrupt
|
||||
RelativeVolumeframe is encountered.
|
||||
* Fixed rendering of Ape.Item on non-latin characters.
|
||||
* Added new constructors to Picture to obsolete CreateFromFile,
|
||||
CreateFromPath.
|
||||
* Changed Asf.Tag to write large pictures to the ASF Metadata Library
|
||||
Object rather than ignoring them.
|
||||
* Changed the way Mpeg.AudioHeader checked for Xing identifier to
|
||||
prevent first change exception if none was found.
|
||||
* Use StringBuilder instead of string addition.
|
||||
* Don't crash if Mpeg4.IsoHandlerBox does not contain a nil delimiter.
|
||||
* Limit scanning in Mpeg.AudioFile to 4096 bytes of audio stream to
|
||||
prevent reading whole file if corrupt.
|
||||
* Replace protected CombinedTag constructor with public one to allow
|
||||
compiling in Orcas.
|
||||
* Include MonoDevelop files in distributed package.
|
||||
* Correctly parse beats per minute when they contain floating point
|
||||
numbers.
|
||||
|
||||
Added features:
|
||||
* Added support for Fraunhofer VBRI header. (Authored by hwahrmann.)
|
||||
* Obsoleted Tag.Duplicate in favor of Tag.CopyTo which can be extended
|
||||
to provide better support for copying between matching tag types.
|
||||
* Added ByteVector.UseBrokenLatin1Behavior that when true reads tags
|
||||
from the system encoding instead of Latin1.
|
||||
* Added support for reading APE files. (Authored by hwahrmann.)
|
||||
* Added generic Id3v2.GetFrames<T>() to reduce casting.
|
||||
* Added support for one of each type of cover image in Ape.Tag
|
||||
* Added recognition of BMP and GIF images in Picture.
|
||||
* Added Id3v2.PopularimeterFrame capable of handling ratings from
|
||||
Windows Media Player.
|
||||
* Added Id3v2.Tag.UseNumericGenres which can be disabled to prevent
|
||||
genres from being written as indices.
|
||||
* Added File.InvariantStartPosition and File.InvariantEndPosition to
|
||||
mark the edges of the media portion of the file.
|
||||
|
||||
Special thanks to those who contributed since the last release:
|
||||
AgentS, codi, craig, Dakuja, DavidT@Imerge, evgeni, hwahrmann, jms,
|
||||
jmurphy, jocker, jonx, jposen, kajic, kurros, nokturnal, oliphant,
|
||||
renzska, sambeckett, sukhjinder, and anyone else who I may have
|
||||
forgotten.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Version 2.0.2.0
|
||||
July 3, 2007
|
||||
|
||||
This is the second bug fix release for TagLib#. Fixes include:
|
||||
* Read AttachedPictureFrame correctly when UTF-16 encoded.
|
||||
* Stop infinite recursion with rare Xing header.
|
||||
* Add "VBR" to the MPEG Audio description if a Xing header is present.
|
||||
* Update unit tests for changes in 2.0.1.
|
||||
* Fix Artists (added in 2.0.1) to point to Performers. Was pointing
|
||||
nowhere.
|
||||
* Make ByteVector.Find return correctly if (data.Count == pattern.Count
|
||||
+ offset).
|
||||
* Set to this.data instead of data in PrivateFrame constructor.
|
||||
|
||||
Outstanding bugs:
|
||||
* MPEG-4 tags do not show up in Nokia N95 Phone.
|
||||
* Large pictures should be stored in the ASF HeaderExtensionObject.
|
||||
|
||||
Outstanding feature requests:
|
||||
* Add slow read support to get correct information from VBR MP3's
|
||||
lacking Xing headers.
|
||||
* Add TagLib.Tag.Key
|
||||
* Add TagLib.Id3v2.PopularimeterFrame
|
||||
* Support ID3v2 chapters.
|
||||
* Return invariant data sections for a file.
|
||||
|
||||
Special thanks to those who contributed in some way to the project over the past
|
||||
year:
|
||||
Aaron Bockover, Alan, Alexander Hixon, Andrés Gómez Aragoneses,
|
||||
Clint Banzhaf, D Bera, David Wu, Da_FileServer, Dennis Cranston,
|
||||
Fabrice Deshayes aka Xtream, Gabriel Rosenhouse, gozza11, Gustavo Rubio,
|
||||
Herman Mahone, HugoPalma, Ilya Konstantinov, Ion Todirel, jc BAUDHUIN,
|
||||
jmurphy, JustinC, lindea, Michael Monreal, maciej, mikec, mtampe,
|
||||
Patrick Laplante, pipes, renzska, sambeckett, Sebastian Dröge,
|
||||
Timm Preetz, wilson, and anyone else who I may have forgotten.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Version 2.0.1
|
||||
June 24, 2007
|
||||
|
||||
This is the first bug fix release for TagLib#. Fixes include:
|
||||
* Use Picard Tag mapping for all tags to improve constistency.
|
||||
* Add JoinedAlbumArtists and FirstAlbumArtist for clarity.
|
||||
* Add Artist pointing to Performers with an ObsoleteAttribute.
|
||||
* Handle ID3v2 comments ending with text delimiters better.
|
||||
* Clear ID3v2 pictures when Pictures is set to null.
|
||||
* Don't try storing pictures larger than 64K in ASF files.
|
||||
* Don't throw an exception when saving MPEG-4 files without UTDA boxes.
|
||||
* Fix the clearing of MPEG-4 boxes.
|
||||
* Use Box.DataSize instead of Header.DataSize when calculating the
|
||||
MPEG-4 padding.
|
||||
* Recognize WMA Lossless in the codec description.
|
||||
|
||||
Outstanding bugs:
|
||||
* MPEG-4 tags do not show up in Nokia N95 Phone.
|
||||
|
||||
Special thanks to those who contributed in some way to the project over the past
|
||||
year:
|
||||
Aaron Bockover, Alan, Alexander Hixon, Andrés Gómez Aragoneses,
|
||||
Clint Banzhaf, D Bera, David Wu, Da_FileServer, Dennis Cranston,
|
||||
Fabrice Deshayes aka Xtream, Gabriel Rosenhouse, gozza11, Gustavo Rubio,
|
||||
Herman Mahone, HugoPalma, Ilya Konstantinov, Ion Todirel, jc BAUDHUIN,
|
||||
jmurphy, JustinC, lindea, Michael Monreal, maciej, mikec, mtampe,
|
||||
Patrick Laplante, renzska, Sebastian Dröge, Timm Preetz, wilson, and
|
||||
anyone else who I may have forgotten.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Version 2.0.0
|
||||
June 11, 2007
|
||||
|
||||
This is the first stable release of TagLib#. TagLib# is a .NET 2.0 library for
|
||||
reading and writing tagging data from audio and video files. In addition it
|
||||
supports the reading of audio and video properties and can be used for media
|
||||
validation. Special thanks to Aaron Bockover and Da_FileServer their help, and
|
||||
everyone who has submitted a bug report or feature request.
|
||||
@@ -1,29 +0,0 @@
|
||||
TagLib# (aka taglib-sharp) is a library for reading and writing
|
||||
metadata in media files, including video, audio, and photo formats.
|
||||
|
||||
It is API stable, with only API additions (not changes or removals)
|
||||
occuring in the 2.0 series.
|
||||
|
||||
* Bugs: http://bugzilla.gnome.org/browse.cgi?product=taglib-sharp
|
||||
* Tarballs: http://download.banshee.fm/taglib-sharp/
|
||||
* IRC: Several TagLib# developers are often in #banshee on irc.gnome.org
|
||||
* Git: http://github.com/mono/taglib-sharp
|
||||
git://github.com/mono/taglib-sharp.git
|
||||
|
||||
TagLib# is free/open source software, released under the LGPL.
|
||||
We welcome contributions! Please try to match our coding style,
|
||||
and include unit tests with any patches. Patches can be submitted
|
||||
by filing a bug and attaching the diff to it.
|
||||
|
||||
To Build From Git:
|
||||
git clone git://github.com/mono/taglib-sharp.git
|
||||
cd taglib-sharp
|
||||
./autogen.sh && make
|
||||
|
||||
To Build From Tarball:
|
||||
./configure && make
|
||||
|
||||
You can also build from MonoDevelop or Visual Studio using taglib-sharp.sln
|
||||
|
||||
To Test:
|
||||
make test
|
||||
@@ -1,136 +0,0 @@
|
||||
#!/bin/sh
|
||||
# Run this to generate all the initial makefiles, etc.
|
||||
# Ripped off from GNOME macros version
|
||||
|
||||
DIE=0
|
||||
|
||||
srcdir=`dirname $0`
|
||||
test -z "$srcdir" && srcdir=.
|
||||
|
||||
if [ -n "$MONO_PATH" ]; then
|
||||
# from -> /mono/lib:/another/mono/lib
|
||||
# to -> /mono /another/mono
|
||||
for i in `echo ${MONO_PATH} | tr ":" " "`; do
|
||||
i=`dirname ${i}`
|
||||
if [ -n "{i}" -a -d "${i}/share/aclocal" ]; then
|
||||
ACLOCAL_FLAGS="-I ${i}/share/aclocal $ACLOCAL_FLAGS"
|
||||
fi
|
||||
if [ -n "{i}" -a -d "${i}/bin" ]; then
|
||||
PATH="${i}/bin:$PATH"
|
||||
fi
|
||||
done
|
||||
export PATH
|
||||
fi
|
||||
|
||||
(autoconf --version) < /dev/null > /dev/null 2>&1 || {
|
||||
echo
|
||||
echo "**Error**: You must have \`autoconf' installed to compile Mono."
|
||||
echo "Download the appropriate package for your distribution,"
|
||||
echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
|
||||
DIE=1
|
||||
}
|
||||
|
||||
if [ -z "$LIBTOOL" ]; then
|
||||
LIBTOOL=`which glibtool 2>/dev/null`
|
||||
if [ ! -x "$LIBTOOL" ]; then
|
||||
LIBTOOL=`which libtool`
|
||||
fi
|
||||
fi
|
||||
|
||||
(grep "^AM_PROG_LIBTOOL" $srcdir/configure.ac >/dev/null) && {
|
||||
($LIBTOOL --version) < /dev/null > /dev/null 2>&1 || {
|
||||
echo
|
||||
echo "**Error**: You must have \`libtool' installed to compile Mono."
|
||||
echo "Get ftp://ftp.gnu.org/pub/gnu/libtool-1.2d.tar.gz"
|
||||
echo "(or a newer version if it is available)"
|
||||
DIE=1
|
||||
}
|
||||
}
|
||||
|
||||
grep "^AM_GNU_GETTEXT" $srcdir/configure.ac >/dev/null && {
|
||||
grep "sed.*POTFILES" $srcdir/configure.ac >/dev/null || \
|
||||
(gettext --version) < /dev/null > /dev/null 2>&1 || {
|
||||
echo
|
||||
echo "**Error**: You must have \`gettext' installed to compile Mono."
|
||||
echo "Get ftp://alpha.gnu.org/gnu/gettext-0.10.35.tar.gz"
|
||||
echo "(or a newer version if it is available)"
|
||||
DIE=1
|
||||
}
|
||||
}
|
||||
|
||||
(automake --version) < /dev/null > /dev/null 2>&1 || {
|
||||
echo
|
||||
echo "**Error**: You must have \`automake' installed to compile Mono."
|
||||
echo "Get ftp://ftp.gnu.org/pub/gnu/automake-1.3.tar.gz"
|
||||
echo "(or a newer version if it is available)"
|
||||
DIE=1
|
||||
NO_AUTOMAKE=yes
|
||||
}
|
||||
|
||||
|
||||
# if no automake, don't bother testing for aclocal
|
||||
test -n "$NO_AUTOMAKE" || (aclocal --version) < /dev/null > /dev/null 2>&1 || {
|
||||
echo
|
||||
echo "**Error**: Missing \`aclocal'. The version of \`automake'"
|
||||
echo "installed doesn't appear recent enough."
|
||||
echo "Get ftp://ftp.gnu.org/pub/gnu/automake-1.3.tar.gz"
|
||||
echo "(or a newer version if it is available)"
|
||||
DIE=1
|
||||
}
|
||||
|
||||
if test "$DIE" -eq 1; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test -z "$*"; then
|
||||
echo "**Warning**: I am going to run \`configure' with no arguments."
|
||||
echo "If you wish to pass any to it, please specify them on the"
|
||||
echo \`$0\'" command line."
|
||||
echo
|
||||
fi
|
||||
|
||||
case $CC in
|
||||
xlc )
|
||||
am_opt=--include-deps;;
|
||||
esac
|
||||
|
||||
|
||||
if grep "^AM_PROG_LIBTOOL" configure.ac >/dev/null; then
|
||||
if test -z "$NO_LIBTOOLIZE" ; then
|
||||
echo "Running libtoolize..."
|
||||
${LIBTOOL}ize --force --copy
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Running aclocal $ACLOCAL_FLAGS ..."
|
||||
aclocal $ACLOCAL_FLAGS || {
|
||||
echo
|
||||
echo "**Error**: aclocal failed. This may mean that you have not"
|
||||
echo "installed all of the packages you need, or you may need to"
|
||||
echo "set ACLOCAL_FLAGS to include \"-I \$prefix/share/aclocal\""
|
||||
echo "for the prefix where you installed the packages whose"
|
||||
echo "macros were not found"
|
||||
exit 1
|
||||
}
|
||||
|
||||
if grep "^AM_CONFIG_HEADER" configure.ac >/dev/null; then
|
||||
echo "Running autoheader..."
|
||||
autoheader || { echo "**Error**: autoheader failed."; exit 1; }
|
||||
fi
|
||||
|
||||
echo "Running automake --gnu $am_opt ..."
|
||||
automake --add-missing --gnu $am_opt ||
|
||||
{ echo "**Error**: automake failed."; exit 1; }
|
||||
echo "Running autoconf ..."
|
||||
autoconf || { echo "**Error**: autoconf failed."; exit 1; }
|
||||
|
||||
|
||||
conf_flags="--enable-maintainer-mode --enable-compile-warnings" #--enable-iso-c
|
||||
|
||||
if test x$NOCONFIGURE = x; then
|
||||
echo Running $srcdir/configure $conf_flags "$@" ...
|
||||
$srcdir/configure $conf_flags "$@" \
|
||||
&& echo Now type \`make\' to compile $PKG_NAME || exit 1
|
||||
else
|
||||
echo Skipping configure process.
|
||||
fi
|
||||
@@ -1,153 +0,0 @@
|
||||
AC_INIT([taglib-sharp], [2.0.4.0])
|
||||
AM_INIT_AUTOMAKE([1.9 dist-bzip2 tar-ustar])
|
||||
AM_MAINTAINER_MODE
|
||||
|
||||
ASSEMBLY_NAME="$PACKAGE"
|
||||
ASSEMBLY_VERSION="$VERSION"
|
||||
|
||||
POLICY_2_0_VERSIONS="2.0.0.0-$ASSEMBLY_VERSION"
|
||||
AC_SUBST(POLICY_2_0_VERSIONS)
|
||||
|
||||
AC_SUBST(VERSION)
|
||||
AC_SUBST(ASSEMBLY_VERSION)
|
||||
AC_SUBST(ASSEMBLY_NAME)
|
||||
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_GREP
|
||||
|
||||
MONODOC_REQUIRED=1.1.9
|
||||
|
||||
WINDIR="$ASSEMBLY_NAME-$VERSION-windows"
|
||||
AC_SUBST(WINDIR)
|
||||
|
||||
DISTCHECK_CONFIGURE_FLAGS="--disable-docs"
|
||||
AC_SUBST(DISTCHECK_CONFIGURE_FLAGS)
|
||||
|
||||
dnl Check for Mono
|
||||
AC_PATH_PROG(MCS, gmcs)
|
||||
if test x$MCS = x; then
|
||||
AC_MSG_ERROR(You need mcs)
|
||||
fi
|
||||
|
||||
AC_PATH_PROG(MONO, mono)
|
||||
if test x$MONO = x; then
|
||||
AC_MSG_ERROR(You need mono)
|
||||
fi
|
||||
|
||||
MCS_FLAGS="-codepage:utf8 -debug"
|
||||
MONO_FLAGS=
|
||||
|
||||
if test $USE_MAINTAINER_MODE = yes; then
|
||||
MONO_FLAGS="$MONO_FLAGS --debug"
|
||||
fi
|
||||
|
||||
AC_SUBST(MCS_FLAGS)
|
||||
AC_SUBST(MONO_FLAGS)
|
||||
|
||||
AC_PATH_PROG(AL, al)
|
||||
if test "x$AL" = "x"; then
|
||||
AC_MSG_ERROR([No al tool found. You need to install mono])
|
||||
fi
|
||||
|
||||
dnl GAC
|
||||
AC_PATH_PROG(GACUTIL, gacutil)
|
||||
if test x$GACUTIL = x; then
|
||||
AC_MSG_ERROR(You need gacutil)
|
||||
fi
|
||||
|
||||
GACUTIL_FLAGS='/package $(ASSEMBLY_NAME) /gacdir $(prefix)/lib /root $(DESTDIR)$(prefix)/lib'
|
||||
AC_SUBST(GACUTIL_FLAGS)
|
||||
GACUTIL_POLICY_FLAGS='/gacdir $(prefix)/lib /root $(DESTDIR)$(prefix)/lib'
|
||||
AC_SUBST(GACUTIL_POLICY_FLAGS)
|
||||
|
||||
AC_ARG_ENABLE(docs, AC_HELP_STRING([--disable-docs], [Do not build documentation]), with_docs=no, with_docs=yes)
|
||||
|
||||
PKG_PROG_PKG_CONFIG
|
||||
|
||||
dnl Monodoc
|
||||
if test "x$with_docs" = "xyes"; then
|
||||
AC_PATH_PROG(MONODOCER, monodocer, no)
|
||||
if test "x$MONODOCER" = "xno"; then
|
||||
AC_MSG_ERROR([You need to install monodoc, or pass --disable-docs to configure to skip documentation installation])
|
||||
fi
|
||||
|
||||
AC_PATH_PROG(MDASSEMBLER, mdassembler, no)
|
||||
if test "x$MDASSEMBLER" = "xno"; then
|
||||
AC_MSG_ERROR([You need to install mdassembler, or pass --disable-docs to configure to skip documentation installation])
|
||||
fi
|
||||
|
||||
DOCDIR=`$PKG_CONFIG monodoc --variable=sourcesdir`
|
||||
AC_SUBST(DOCDIR)
|
||||
AM_CONDITIONAL(BUILD_DOCS, true)
|
||||
else
|
||||
AC_MSG_NOTICE([not building Banshee API documentation])
|
||||
AM_CONDITIONAL(BUILD_DOCS, false)
|
||||
fi
|
||||
|
||||
# checking for ICSharpCode.SharpZipLib.dll
|
||||
AC_MSG_CHECKING([Mono GAC for ICSharpCode.SharpZipLib.dll])
|
||||
if $GACUTIL -l | $GREP -q ICSharpCode.SharpZipLib; \
|
||||
then \
|
||||
AC_MSG_RESULT([found])
|
||||
AM_CONDITIONAL(HAVE_SHARPZIPLIB, true)
|
||||
else
|
||||
AC_MSG_RESULT([not found])
|
||||
AM_CONDITIONAL(HAVE_SHARPZIPLIB, false)
|
||||
fi
|
||||
|
||||
|
||||
PKG_CHECK_MODULES(GNOME_SHARP, gnome-sharp-2.0, have_gnome_sharp=yes, have_gnome_sharp=no)
|
||||
if test "x$have_gnome_sharp" = "xyes"; then
|
||||
AC_SUBST(GNOME_SHARP_LIBS)
|
||||
AM_CONDITIONAL(HAVE_GNOME_SHARP, true)
|
||||
else
|
||||
AM_CONDITIONAL(HAVE_GNOME_SHARP, false)
|
||||
fi
|
||||
|
||||
PKG_CHECK_MODULES(EXIV2, exiv2, have_exiv2=yes, have_exiv2=no)
|
||||
if test "x$have_exiv2" = "xyes"; then
|
||||
AC_SUBST(EXIV2_LIBS)
|
||||
AM_CONDITIONAL(HAVE_EXIV2, true)
|
||||
else
|
||||
AM_CONDITIONAL(HAVE_EXIV2, false)
|
||||
fi
|
||||
|
||||
PKG_CHECK_MODULES(MONO_NUNIT, mono-nunit >= 1.0, do_tests="yes", do_tests="no") AC_SUBST(MONO_NUNIT_LIBS)
|
||||
AM_CONDITIONAL(ENABLE_TESTS, test "x$do_tests" = "xyes")
|
||||
if test "x$do_tests" = "xno"; then
|
||||
AC_MSG_WARN([Could not find mono-nunit: tests will not be available.])
|
||||
else
|
||||
AC_PATH_PROG(NUNIT_CMD, nunit-console2, nunit-console)
|
||||
AC_SUBST(NUNIT_CMD)
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(raw-tests, AC_HELP_STRING([--enable-raw-tests], [Enable RAW image files NUnit tests]),
|
||||
enable_raw_tests=$enableval, enable_raw_tests="no")
|
||||
if test "x$enable_raw_tests" = "xno"; then
|
||||
AC_MSG_WARN([RAW image file tests disabled.])
|
||||
AM_CONDITIONAL(ENABLE_RAW_TESTS, false)
|
||||
else
|
||||
AM_CONDITIONAL(ENABLE_RAW_TESTS, true)
|
||||
fi
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
taglib-sharp.pc
|
||||
src/Makefile
|
||||
src/AssemblyInfo.cs
|
||||
src/policy.2.0.taglib-sharp.config
|
||||
examples/Makefile
|
||||
docs/Makefile
|
||||
docs/Package.en.xml
|
||||
])
|
||||
|
||||
# Test suite is not shipped, only builds from git.
|
||||
if test -d tests; then
|
||||
AC_CONFIG_FILES([tests/Makefile])
|
||||
AM_CONDITIONAL(IN_DIST, false)
|
||||
else
|
||||
AM_CONDITIONAL(IN_DIST, true)
|
||||
fi
|
||||
AC_OUTPUT
|
||||
|
||||
echo "TagLib# ($ASSEMBLY_NAME-$ASSEMBLY_VERSION) is ready to be compiled."
|
||||
@@ -1,66 +0,0 @@
|
||||
DOC_UPDATER = @MONODOCER@ -delete -pretty
|
||||
DOC_ASSEMBLER = @MDASSEMBLER@ --out taglib-sharp-docs --ecma
|
||||
|
||||
ASSEMBLY = $(top_builddir)/src/$(ASSEMBLY_NAME).dll
|
||||
SLASHDOC = $(ASSEMBLY).xml
|
||||
|
||||
if BUILD_DOCS
|
||||
all: XmlInjector.exe
|
||||
|
||||
XmlInjector.exe: XmlInjector.cs
|
||||
$(MCS) -out:$@ -r:System.Xml $<
|
||||
|
||||
monodocdir = $(DOCDIR)
|
||||
monodoc_DATA = \
|
||||
taglib-sharp-docs.zip \
|
||||
taglib-sharp-docs.tree \
|
||||
taglib-sharp-docs.source
|
||||
|
||||
en/index.xml: $(ASSEMBLY) $(SLASHDOC) XmlInjector.exe Package.en.xml
|
||||
# monodocer will create duplicate tags if run multiple times. Delete the whole
|
||||
# directory and start over.
|
||||
if [ -d en ]; then \
|
||||
rm -rf en; \
|
||||
fi
|
||||
$(DOC_UPDATER) -assembly:$(ASSEMBLY) -importslashdoc:$(SLASHDOC) -path:en > /dev/null
|
||||
$(MONO) XmlInjector.exe Package.en.xml InsertMissingValues
|
||||
|
||||
update-html: en
|
||||
if [ -d taglib-sharp-web-docs ]; then \
|
||||
rm -rf taglib-sharp-web-docs; \
|
||||
fi; \
|
||||
mkdir taglib-sharp-web-docs; \
|
||||
monodocs2html -o taglib-sharp-web-docs en;
|
||||
|
||||
taglib-sharp-docs.tree: taglib-sharp-docs.zip
|
||||
|
||||
taglib-sharp-docs.zip: en/index.xml
|
||||
$(DOC_ASSEMBLER) en
|
||||
|
||||
install-data-hook: XmlInjector.exe Package.en.xml
|
||||
$(MONO) XmlInjector.exe Package.en.xml InjectMenuItem
|
||||
|
||||
uninstall-hook: XmlInjector.exe Package.en.xml
|
||||
$(MONO) XmlInjector.exe Package.en.xml RemoveMenuItem
|
||||
|
||||
clean-local:
|
||||
if [ -d en ]; then \
|
||||
rm -rf en; \
|
||||
fi
|
||||
|
||||
endif
|
||||
|
||||
EXTRA_DIST = \
|
||||
taglib-sharp-docs.source \
|
||||
XmlInjector.cs \
|
||||
Package.en.xml.in
|
||||
|
||||
DISTCLEANFILES = \
|
||||
taglib-sharp-docs.zip \
|
||||
taglib-sharp-docs.tree
|
||||
|
||||
MAINTAINERCLEANFILES = \
|
||||
Makefile.in
|
||||
|
||||
CLEANFILES = \
|
||||
XmlInjector.exe
|
||||
@@ -1,221 +0,0 @@
|
||||
<Package>
|
||||
<Overview>
|
||||
<Title>TagLib#</Title>
|
||||
<Remarks>This package provides support for reading and writing
|
||||
the tagging information for a large number of tagging formats,
|
||||
as well as reading media properties for many standard audio and video formats.</Remarks>
|
||||
<Copyright>Copyright (C) 2007-2008 Brian Nickel</Copyright>
|
||||
</Overview>
|
||||
<Namespace Name="TagLib">
|
||||
<Docs>
|
||||
<summary>TagLib provides a generic interface for reading
|
||||
media properties and editing tags on different audio and
|
||||
video files.</summary>
|
||||
<remarks>The most straightforward way to read a file is
|
||||
through <see cref="M:TagLib.File.Create(System.String)"
|
||||
/>, which does type detection to create the correct <see
|
||||
cref="T:TagLib.File" />.</remarks>
|
||||
</Docs>
|
||||
</Namespace>
|
||||
<Namespace Name="TagLib.Aac">
|
||||
<Docs>
|
||||
<summary><para>The TagLib.Aac namespace contains classes
|
||||
for handling the AAC file format.</para></summary>
|
||||
<remarks><para>See
|
||||
http://www.hydrogenaudio.org/forums/lofiversion/index.php/t21617.html
|
||||
for the complete specification.</para></remarks>
|
||||
</Docs>
|
||||
</Namespace>
|
||||
<Namespace Name="TagLib.Aiff">
|
||||
<Docs>
|
||||
<summary><para>The TagLib.Aiff namespace contains classes
|
||||
for handling the AIFF file format.</para></summary>
|
||||
<remarks><para>See
|
||||
http://en.wikipedia.org/wiki/Audio_Interchange_File_Format for
|
||||
the complete specification.</para></remarks>
|
||||
</Docs>
|
||||
</Namespace>
|
||||
<Namespace Name="TagLib.Ape">
|
||||
<Docs>
|
||||
<summary><para>The TagLib.Ape namespace contains classes
|
||||
for reading APE tags.</para></summary>
|
||||
<remarks><para>See
|
||||
http://wiki.hydrogenaudio.org/index.php?title=APEv2 for
|
||||
the complete specification.</para></remarks>
|
||||
</Docs>
|
||||
</Namespace>
|
||||
<Namespace Name="TagLib.Asf">
|
||||
<Docs>
|
||||
<summary>The TagLib.Asf namespace contains classes for
|
||||
handling the Microsoft Advanced Systems Format file
|
||||
format.</summary>
|
||||
<remarks>See
|
||||
http://www.microsoft.com/windows/windowsmedia/forpros/format/asfspec.aspx
|
||||
for the complete specification.</remarks>
|
||||
</Docs>
|
||||
</Namespace>
|
||||
<Namespace Name="TagLib.Flac">
|
||||
<Docs>
|
||||
<summary>The TagLib.Flac namespace contains classes for
|
||||
handling the Xiph FLAC file format.</summary>
|
||||
<remarks>See http://flac.sourceforge.net/format.html for
|
||||
the complete specification.</remarks>
|
||||
</Docs>
|
||||
</Namespace>
|
||||
<Namespace Name="TagLib.Id3v1">
|
||||
<Docs>
|
||||
<summary>The TagLib.Id3v1 namespace contains classes for
|
||||
handling the ID3v1.1 tagging format.</summary>
|
||||
<remarks>See http://www.id3.org/ID3v1 for the complete
|
||||
specification.</remarks>
|
||||
</Docs>
|
||||
</Namespace>
|
||||
<Namespace Name="TagLib.Id3v2">
|
||||
<Docs>
|
||||
<summary>The TagLib.Id3v2 namespace contains classes for
|
||||
handling the ID3v2 tagging format.</summary>
|
||||
<remarks>See http://www.id3.org/Developer_Information
|
||||
for the complete specification.</remarks>
|
||||
</Docs>
|
||||
</Namespace>
|
||||
<Namespace Name="TagLib.Mpeg4">
|
||||
<Docs>
|
||||
<summary>The TagLib.Mpeg4 namespace contains classes for
|
||||
handling the MPEG-4 file format.</summary>
|
||||
<remarks>See
|
||||
http://standards.iso.org/ittf/PubliclyAvailableStandards/c041828_ISO_IEC_14496-12_2005(E).zip
|
||||
for the complete specification.</remarks>
|
||||
</Docs>
|
||||
</Namespace>
|
||||
<Namespace Name="TagLib.Mpeg">
|
||||
<Docs>
|
||||
<summary>The TagLib.Mpeg namespace contains classes for handling
|
||||
MPEG-1/2 files and MPEG audio files.</summary>
|
||||
<remarks />
|
||||
</Docs>
|
||||
</Namespace>
|
||||
<Namespace Name="TagLib.MusePack">
|
||||
<Docs>
|
||||
<summary>The TagLib.MusePack namespace contains classes for
|
||||
handling the MusePack file format.</summary>
|
||||
<remarks>See http://www.musepack.net/ for the complete
|
||||
specification.</remarks>
|
||||
</Docs>
|
||||
</Namespace>
|
||||
<Namespace Name="TagLib.NonContainer">
|
||||
<Docs>
|
||||
<summary>The TagLib.NonContainer namespace provides
|
||||
classes for dealing with files that do not have a
|
||||
standardized tagging mechanism and may have any number
|
||||
of tags at their beginning or end.</summary>
|
||||
<remarks>The FLAC file format is included in this
|
||||
because despite having a standard tagging mechanism, ID3
|
||||
and APE tags are not uncommonly attached to the
|
||||
file.</remarks>
|
||||
</Docs>
|
||||
</Namespace>
|
||||
<Namespace Name="TagLib.Ogg.Codecs">
|
||||
<Docs>
|
||||
<summary>The TagLib.Ogg.Codecs namespace contains
|
||||
standard codecs used in Xiph Ogg files.</summary>
|
||||
<remarks />
|
||||
</Docs>
|
||||
</Namespace>
|
||||
<Namespace Name="TagLib.Ogg">
|
||||
<Docs>
|
||||
<summary>The TagLib.Ogg namespace contains classes for
|
||||
handling the Xiph OGG file format.</summary>
|
||||
<remarks>See http://www.xiph.org/ogg/ for the complete
|
||||
specification.</remarks>
|
||||
</Docs>
|
||||
</Namespace>
|
||||
<Namespace Name="TagLib.Riff">
|
||||
<Docs>
|
||||
<summary>The TagLib.Riff namespace contains all classes
|
||||
relevant to the reading of Microsoft RIFF files. These
|
||||
files include namely the WAV and AVI file
|
||||
formats.</summary>
|
||||
<remarks>See
|
||||
http://msdn2.microsoft.com/en-us/library/ms779636.aspx
|
||||
for information on the RIFF AVI format.</remarks>
|
||||
</Docs>
|
||||
</Namespace>
|
||||
<Namespace Name="TagLib.WavPack">
|
||||
<Docs>
|
||||
<summary>The TagLib.WavPack namespace contains all
|
||||
classes relevant to the reading of WavPack
|
||||
files.</summary>
|
||||
<remarks>See http://www.wavpack.com/ for the complete
|
||||
specification.</remarks>
|
||||
</Docs>
|
||||
</Namespace>
|
||||
<ActionSet Name="InjectMenuItem">
|
||||
<File Path="@DOCDIR@/../monodoc.xml">
|
||||
<Insert Target="/node/node[@name='various']" IfMissing="//node[@name='classlib-taglib-sharp']">
|
||||
<node label="TagLib#" name="classlib-taglib-sharp" />
|
||||
</Insert>
|
||||
</File>
|
||||
</ActionSet>
|
||||
|
||||
<ActionSet Name="RemoveMenuItem">
|
||||
<File Path="@DOCDIR@/../monodoc.xml">
|
||||
<Remove Target="//node[@name='classlib-taglib-sharp']" />
|
||||
</File>
|
||||
</ActionSet>
|
||||
|
||||
<ActionSet Name="InsertMissingValues">
|
||||
<File Path="en/index.xml">
|
||||
<Replace Source="/Package/Overview/Title" Target="/Overview/Title" />
|
||||
<Replace Source="/Package/Overview/Copyright" Target="/Overview/Copyright" />
|
||||
<Replace Source="/Package/Overview/Remarks" Target="/Overview/Remarks" />
|
||||
</File>
|
||||
<File Path="en/ns-TagLib.xml">
|
||||
<Replace Source="/Package/Namespace[@Name='TagLib']/Docs" Target="/Namespace/Docs" />
|
||||
</File>
|
||||
<File Path="en/ns-TagLib.Aac.xml">
|
||||
<Replace Source="/Package/Namespace[@Name='TagLib.Aac']/Docs" Target="/Namespace/Docs" />
|
||||
</File>
|
||||
<File Path="en/ns-TagLib.Aiff.xml">
|
||||
<Replace Source="/Package/Namespace[@Name='TagLib.Aiff']/Docs" Target="/Namespace/Docs" />
|
||||
</File>
|
||||
<File Path="en/ns-TagLib.Ape.xml">
|
||||
<Replace Source="/Package/Namespace[@Name='TagLib.Ape']/Docs" Target="/Namespace/Docs" />
|
||||
</File>
|
||||
<File Path="en/ns-TagLib.Asf.xml">
|
||||
<Replace Source="/Package/Namespace[@Name='TagLib.Asf']/Docs" Target="/Namespace/Docs" />
|
||||
</File>
|
||||
<File Path="en/ns-TagLib.Flac.xml">
|
||||
<Replace Source="/Package/Namespace[@Name='TagLib.Flac']/Docs" Target="/Namespace/Docs" />
|
||||
</File>
|
||||
<File Path="en/ns-TagLib.Id3v1.xml">
|
||||
<Replace Source="/Package/Namespace[@Name='TagLib.Id3v1']/Docs" Target="/Namespace/Docs" />
|
||||
</File>
|
||||
<File Path="en/ns-TagLib.Id3v2.xml">
|
||||
<Replace Source="/Package/Namespace[@Name='TagLib.Id3v2']/Docs" Target="/Namespace/Docs" />
|
||||
</File>
|
||||
<File Path="en/ns-TagLib.Mpeg4.xml">
|
||||
<Replace Source="/Package/Namespace[@Name='TagLib.Mpeg4']/Docs" Target="/Namespace/Docs" />
|
||||
</File>
|
||||
<File Path="en/ns-TagLib.Mpeg.xml">
|
||||
<Replace Source="/Package/Namespace[@Name='TagLib.Mpeg']/Docs" Target="/Namespace/Docs" />
|
||||
</File>
|
||||
<File Path="en/ns-TagLib.MusePack.xml">
|
||||
<Replace Source="/Package/Namespace[@Name='TagLib.MusePack']/Docs" Target="/Namespace/Docs" />
|
||||
</File>
|
||||
<File Path="en/ns-TagLib.NonContainer.xml">
|
||||
<Replace Source="/Package/Namespace[@Name='TagLib.NonContainer']/Docs" Target="/Namespace/Docs" />
|
||||
</File>
|
||||
<File Path="en/ns-TagLib.Ogg.Codecs.xml">
|
||||
<Replace Source="/Package/Namespace[@Name='TagLib.Ogg.Codecs']/Docs" Target="/Namespace/Docs" />
|
||||
</File>
|
||||
<File Path="en/ns-TagLib.Ogg.xml">
|
||||
<Replace Source="/Package/Namespace[@Name='TagLib.Ogg']/Docs" Target="/Namespace/Docs" />
|
||||
</File>
|
||||
<File Path="en/ns-TagLib.Riff.xml">
|
||||
<Replace Source="/Package/Namespace[@Name='TagLib.Riff']/Docs" Target="/Namespace/Docs" />
|
||||
</File>
|
||||
<File Path="en/ns-TagLib.WavPack.xml">
|
||||
<Replace Source="/Package/Namespace[@Name='TagLib.WavPack']/Docs" Target="/Namespace/Docs" />
|
||||
</File>
|
||||
</ActionSet>
|
||||
</Package>
|
||||
@@ -1,191 +0,0 @@
|
||||
/***************************************************************************
|
||||
* XmlInjector.cs
|
||||
*
|
||||
* Copyright (C) 2008 Brian Nickel
|
||||
* Written by Brian Nickel (brian.nickel@gmail.com)
|
||||
****************************************************************************/
|
||||
|
||||
/* THIS FILE IS LICENSED UNDER THE MIT LICENSE AS OUTLINED IMMEDIATELY BELOW:
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Xml;
|
||||
|
||||
public static class XmlInjector
|
||||
{
|
||||
public static int Main (string [] args)
|
||||
{
|
||||
if (args.Length != 2) {
|
||||
Console.WriteLine ("XmlInjector.exe ACTIONFILE.XML ACTION_NAME");
|
||||
return 1;
|
||||
}
|
||||
|
||||
XmlDocument doc = new XmlDocument ();
|
||||
try {
|
||||
doc.Load (args [0]);
|
||||
} catch {
|
||||
Console.WriteLine ("Could not open {0}.", args [0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
string dir = System.IO.Directory.GetParent (args [0]).FullName;
|
||||
Console.WriteLine ("Setting working directory to {0}.", dir);
|
||||
System.IO.Directory.SetCurrentDirectory (dir);
|
||||
|
||||
string path = string.Format ("//ActionSet[@Name='{0}']/File[@Path]", args [1]);
|
||||
foreach (XmlNode node in doc.SelectNodes (path))
|
||||
if (!RunFileAction (node))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static bool RunFileAction (XmlNode fileElement)
|
||||
{
|
||||
string path = GetAttribute (fileElement, "Path");
|
||||
XmlDocument doc = new XmlDocument ();
|
||||
try {
|
||||
doc.Load (path);
|
||||
} catch {
|
||||
Console.WriteLine ("ERROR: Could not open {0}.", path);
|
||||
return false;
|
||||
}
|
||||
|
||||
Console.WriteLine ("Processing {0}...", path);
|
||||
|
||||
foreach (XmlNode element in fileElement.SelectNodes ("Replace"))
|
||||
if (!ReplaceNode (fileElement.OwnerDocument, doc, element))
|
||||
return false;
|
||||
|
||||
foreach (XmlNode element in fileElement.SelectNodes ("Insert"))
|
||||
if (!InsertNode (fileElement.OwnerDocument, doc, element))
|
||||
return false;
|
||||
|
||||
foreach (XmlNode element in fileElement.SelectNodes ("Remove"))
|
||||
if (!RemoveNodes (doc, element))
|
||||
return false;
|
||||
|
||||
doc.Save (path);
|
||||
Console.WriteLine ("{0} saved.", path);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool ReplaceNode (XmlDocument sourceDocument,
|
||||
XmlDocument targetDocument,
|
||||
XmlNode replaceElement)
|
||||
{
|
||||
string sourcePath = GetAttribute (replaceElement, "Source");
|
||||
string targetPath = GetAttribute (replaceElement, "Target");
|
||||
|
||||
if (OperationNotNeccessary (targetDocument, replaceElement)) {
|
||||
Console.WriteLine (" Skipping replacement of {0}.", targetPath);
|
||||
return true;
|
||||
}
|
||||
|
||||
Console.WriteLine (" Replacing {0}.", targetPath);
|
||||
XmlNode sourceNode = sourcePath == null ? null : sourceDocument.SelectSingleNode (sourcePath);
|
||||
XmlNode targetNode = targetPath == null ? null : targetDocument.SelectSingleNode (targetPath);
|
||||
|
||||
if (sourceNode == null)
|
||||
sourceNode = replaceElement.FirstChild;
|
||||
|
||||
if (sourceNode == null) {
|
||||
Console.WriteLine ("ERROR: Could not find source node: {0}", sourcePath);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (targetNode == null) {
|
||||
Console.WriteLine ("ERROR: Could not find target node: {0}", targetPath);
|
||||
return false;
|
||||
}
|
||||
|
||||
targetNode.ParentNode.ReplaceChild (targetDocument.ImportNode (sourceNode, true), targetNode);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool InsertNode (XmlDocument sourceDocument, XmlDocument targetDocument, XmlNode insertElement)
|
||||
{
|
||||
string sourcePath = GetAttribute (insertElement, "Source");
|
||||
string targetPath = GetAttribute (insertElement, "Target");
|
||||
|
||||
if (OperationNotNeccessary (targetDocument, insertElement)) {
|
||||
Console.WriteLine (" Skipping insertion into {0}.", targetPath);
|
||||
return true;
|
||||
}
|
||||
|
||||
Console.WriteLine (" Inserting into {0}.", targetPath);
|
||||
XmlNode sourceNode = sourcePath == null ? null : sourceDocument.SelectSingleNode (sourcePath);
|
||||
XmlNode targetNode = targetPath == null ? null : targetDocument.SelectSingleNode (targetPath);
|
||||
|
||||
if (sourceNode == null)
|
||||
sourceNode = insertElement.FirstChild;
|
||||
|
||||
if (sourceNode == null) {
|
||||
Console.WriteLine ("ERROR: Could not find source node: {0}", sourcePath);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (targetNode == null) {
|
||||
Console.WriteLine ("ERROR: Could not find target node: {0}", targetPath);
|
||||
return false;
|
||||
}
|
||||
|
||||
targetNode.AppendChild (targetDocument.ImportNode (sourceNode, true));
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool RemoveNodes (XmlDocument targetDocument,
|
||||
XmlNode removeElement)
|
||||
{
|
||||
string targetPath = GetAttribute (removeElement, "Target");
|
||||
|
||||
if (OperationNotNeccessary (targetDocument, removeElement)) {
|
||||
Console.WriteLine (" Skipping removal of {0}.", targetPath);
|
||||
return true;
|
||||
}
|
||||
|
||||
Console.WriteLine (" Removing {0}.", targetPath);
|
||||
|
||||
while (true) {
|
||||
XmlNode targetNode = targetDocument.SelectSingleNode (targetPath);
|
||||
|
||||
if (targetNode == null)
|
||||
return true;
|
||||
|
||||
targetNode.ParentNode.RemoveChild (targetNode);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool OperationNotNeccessary (XmlDocument targetDocument, XmlNode actionElement)
|
||||
{
|
||||
string ifMissingPath = GetAttribute (actionElement, "IfMissing");
|
||||
if (ifMissingPath != null && targetDocument.SelectSingleNode (ifMissingPath) != null)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static string GetAttribute (XmlNode node, string attribute)
|
||||
{
|
||||
XmlAttribute xmlAttr = node.Attributes [attribute];
|
||||
return xmlAttr == null ? null : xmlAttr.Value;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<monodoc>
|
||||
<source provider="ecma" basefile="taglib-sharp-docs" path="classlib-taglib-sharp" />
|
||||
</monodoc>
|
||||
2
taglib-sharp/examples/.gitignore
vendored
@@ -1,2 +0,0 @@
|
||||
extractKey
|
||||
listData
|
||||
@@ -1,131 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using TagLib;
|
||||
|
||||
public class BatchSet
|
||||
{
|
||||
private enum Mode {
|
||||
Tag, Value, File
|
||||
}
|
||||
|
||||
public static void Main(string [] args)
|
||||
{
|
||||
if(args.Length < 3) {
|
||||
Console.Error.WriteLine ("USAGE: BatchSet.exe -tag value [-tag2 value ...] File1 [File2 ...]");
|
||||
return;
|
||||
}
|
||||
|
||||
Mode mode = Mode.Tag;
|
||||
List<string> files = new List<string> ();
|
||||
Dictionary<string,string> tags = new Dictionary<string,string> ();
|
||||
|
||||
string tag = null;
|
||||
|
||||
foreach (string str in args) {
|
||||
if (mode == Mode.Tag) {
|
||||
if (str [0] == '-') {
|
||||
if (str == "--") {
|
||||
mode = Mode.File;
|
||||
} else {
|
||||
tag = str.Substring (1);
|
||||
mode = Mode.Value;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
mode = Mode.File;
|
||||
}
|
||||
|
||||
if (mode == Mode.Value) {
|
||||
if (!tags.ContainsKey (tag))
|
||||
tags.Add (tag, str);
|
||||
mode = Mode.Tag;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mode == Mode.File)
|
||||
files.Add (str);
|
||||
}
|
||||
|
||||
foreach (string filename in files) {
|
||||
TagLib.File file = TagLib.File.Create (filename);
|
||||
if (file == null)
|
||||
continue;
|
||||
|
||||
Console.WriteLine ("Updating Tags For: " + filename);
|
||||
|
||||
foreach (string key in tags.Keys) {
|
||||
string value = tags [key];
|
||||
try {
|
||||
switch (key) {
|
||||
case "id3version":
|
||||
byte number = byte.Parse (value);
|
||||
if (number == 1) {
|
||||
file.RemoveTags (TagTypes.Id3v2);
|
||||
} else {
|
||||
TagLib.Id3v2.Tag v2 =
|
||||
file.GetTag (TagTypes.Id3v2, true)
|
||||
as TagLib.Id3v2.Tag;
|
||||
|
||||
if (v2 != null)
|
||||
v2.Version = number;
|
||||
}
|
||||
break;
|
||||
case "album":
|
||||
file.Tag.Album = value;
|
||||
break;
|
||||
case "artists":
|
||||
file.Tag.AlbumArtists = value.Split (new char [] {';'});
|
||||
break;
|
||||
case "comment":
|
||||
file.Tag.Comment = value;
|
||||
break;
|
||||
case "lyrics":
|
||||
file.Tag.Lyrics = value;
|
||||
break;
|
||||
case "composers":
|
||||
file.Tag.Composers = value.Split (new char [] {';'});
|
||||
break;
|
||||
case "disc":
|
||||
file.Tag.Disc = uint.Parse (value);
|
||||
break;
|
||||
case "disccount":
|
||||
file.Tag.DiscCount = uint.Parse (value);
|
||||
break;
|
||||
case "genres":
|
||||
file.Tag.Genres = value.Split (new char [] {';'});
|
||||
break;
|
||||
case "performers":
|
||||
file.Tag.Performers = value.Split (new char [] {';'});
|
||||
break;
|
||||
case "title":
|
||||
file.Tag.Title = value;
|
||||
break;
|
||||
case "track":
|
||||
file.Tag.Track = uint.Parse (value);
|
||||
break;
|
||||
case "trackcount":
|
||||
file.Tag.TrackCount = uint.Parse (value);
|
||||
break;
|
||||
case "year":
|
||||
file.Tag.Year = uint.Parse (value);
|
||||
break;
|
||||
case "pictures":
|
||||
List<Picture> pics = new List<Picture> ();
|
||||
if (!string.IsNullOrEmpty (value))
|
||||
foreach (string path in value.Split (new char [] {';'})) {
|
||||
pics.Add (new Picture (path));
|
||||
}
|
||||
file.Tag.Pictures = pics.ToArray ();
|
||||
break;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Console.WriteLine ("Error setting tag " + key + ":");
|
||||
Console.WriteLine (e);
|
||||
}
|
||||
}
|
||||
|
||||
file.Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,924 +0,0 @@
|
||||
//
|
||||
// This application parses a photo and compares the output to the output of exiv2.
|
||||
//
|
||||
// It can be used to make test fixtures. Manual validation is always required.
|
||||
//
|
||||
// You need the exiv2 app for this to work.
|
||||
//
|
||||
|
||||
using GLib;
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Cryptography;
|
||||
using TagLib;
|
||||
using TagLib.IFD;
|
||||
using TagLib.IFD.Tags;
|
||||
using TagLib.Xmp;
|
||||
|
||||
public class GenerateTestFixtureApp
|
||||
{
|
||||
private static MD5 md5 = MD5.Create ();
|
||||
|
||||
public static void Main (string [] args)
|
||||
{
|
||||
if(args.Length != 2) {
|
||||
Console.Error.WriteLine ("USAGE: mono GenerateTestFixture.exe NAME PATH");
|
||||
return;
|
||||
}
|
||||
|
||||
string name = args[0];
|
||||
string path = args[1];
|
||||
|
||||
EmitHeader (name, path);
|
||||
GenerateIFDFixture (name, path);
|
||||
GenerateXMPFixture (name, path);
|
||||
EmitFooter ();
|
||||
}
|
||||
|
||||
static Dictionary<string, int> sub_ifds = new Dictionary<string, int> ();
|
||||
static Dictionary<string, bool> sub_ifds_emitted = new Dictionary<string, bool> ();
|
||||
|
||||
static void GenerateIFDFixture (string name, string path)
|
||||
{
|
||||
// First run exiv2 on it.
|
||||
string output, err;
|
||||
int code;
|
||||
var result = GLib.Process.SpawnCommandLineSync (String.Format ("./listData e {0}", path), out output, out err, out code);
|
||||
if (!result) {
|
||||
Console.Error.WriteLine ("Invoking listData failed, are you running from the examples folder?");
|
||||
return;
|
||||
}
|
||||
|
||||
Write ("// ---------- Start of IFD tests ----------");
|
||||
|
||||
foreach (string line in output.Split ('\n')) {
|
||||
string[] parts = line.Split (new char[] {'\t'}, 5);
|
||||
if (parts.Length == 0 || line.Trim ().Equals (String.Empty) || parts.Length != 5)
|
||||
continue;
|
||||
string tag_label = parts[0];
|
||||
ushort tag = ushort.Parse (parts[1].Substring(2), System.Globalization.NumberStyles.HexNumber);
|
||||
string ifd = parts[2];
|
||||
string type = parts[3];
|
||||
uint length = uint.Parse (parts[4]);
|
||||
|
||||
if (ifd == "NikonSi02xx" || ifd == "NikonVr" || ifd == "NikonPc" || ifd == "NikonWt" || ifd == "NikonIi" || ifd == "NikonLd3") {
|
||||
continue; // Exiv2 makes these up.
|
||||
}
|
||||
|
||||
string val = ExtractKey (path, String.Format ("Exif.{0}.{1}", ifd, tag_label));
|
||||
|
||||
if (tag_label == "SubIFDs") {
|
||||
for (int i = 0; i < val.Split (' ').Length; i++) {
|
||||
var sub_ifd = String.Format ("SubImage{0}", sub_ifds.Count + 1);
|
||||
sub_ifds.Add (sub_ifd, sub_ifds.Count);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
EnsureIFD (ifd);
|
||||
|
||||
if (tag_label.Equals ("ExifTag"))
|
||||
type = "SubIFD";
|
||||
if (tag_label.Equals ("MakerNote")) {
|
||||
type = "MakerNote";
|
||||
val = String.Empty; // No need to echo.
|
||||
}
|
||||
if (tag_label.Equals ("InteroperabilityTag"))
|
||||
type = "SubIFD";
|
||||
if (tag_label.Equals ("GPSTag"))
|
||||
type = "SubIFD";
|
||||
if (tag_label.Equals ("JPEGInterchangeFormat"))
|
||||
type = "ThumbnailDataIFD";
|
||||
if (tag_label.Equals ("Preview") && ifd.Equals ("Nikon3"))
|
||||
type = "SubIFD";
|
||||
if (tag_label.Equals ("UserComment") && ifd.Equals ("Photo"))
|
||||
type = "UserComment";
|
||||
if (tag_label.Equals ("StripOffsets"))
|
||||
type = "StripOffsets";
|
||||
if (tag_label.Equals ("IPTCNAA"))
|
||||
type = "IPTCNAA";
|
||||
if (tag_label.Equals ("XMLPacket"))
|
||||
type = "XMLPacket";
|
||||
|
||||
if (ifd.Equals ("MakerNote"))
|
||||
continue; // Exiv2 makes these up.
|
||||
|
||||
Write ("// {1}.0x{0:X4} ({2}/{3}/{4}) \"{5}\"", tag, ifd, tag_label, type, length, length > 512 ? "(Value ommitted)" : val);
|
||||
|
||||
if (ifd.Equals ("Image")) {
|
||||
EmitTestIFDEntryOpen ("structure", 0, tag, ifd);
|
||||
} else if (ifd.Equals ("Thumbnail")) {
|
||||
EmitTestIFDEntryOpen ("structure", 1, tag, ifd);
|
||||
} else if (ifd.Equals ("Image2")) {
|
||||
EmitTestIFDEntryOpen ("structure", 2, tag, ifd);
|
||||
} else if (ifd.Equals ("Image3")) {
|
||||
EmitTestIFDEntryOpen ("structure", 3, tag, ifd);
|
||||
} else if (ifd.Equals ("Photo")) {
|
||||
EmitTestIFDEntryOpen ("exif_structure", 0, tag, ifd);
|
||||
} else if (IsPartOfMakernote (ifd)) {
|
||||
EmitTestIFDEntryOpen ("makernote_structure", 0, tag, ifd);
|
||||
} else if (ifd.Equals ("NikonPreview")) {
|
||||
EmitTestIFDEntryOpen ("nikonpreview_structure", 0, tag, ifd);
|
||||
} else if (ifd.Equals ("Iop")) {
|
||||
EmitTestIFDEntryOpen ("iop_structure", 0, tag, ifd);
|
||||
} else if (ifd.Equals ("GPSInfo")) {
|
||||
EmitTestIFDEntryOpen ("gps_structure", 0, tag, ifd);
|
||||
} else if (ifd.Equals ("CanonCs")) {
|
||||
EmitTestIFDEntryOpen ("makernote_structure", 0, (ushort) CanonMakerNoteEntryTag.CameraSettings, ifd);
|
||||
} else if (ifd.Equals ("CanonSi")) {
|
||||
EmitTestIFDEntryOpen ("makernote_structure", 0, (ushort) CanonMakerNoteEntryTag.ShotInfo, ifd);
|
||||
} else if (ifd.Equals ("CanonCf")) {
|
||||
EmitTestIFDEntryOpen ("makernote_structure", 0, (ushort) CanonMakerNoteEntryTag.CustomFunctions, ifd);
|
||||
} else if (ifd.Equals ("CanonPi")) {
|
||||
EmitTestIFDEntryOpen ("makernote_structure", 0, (ushort) CanonMakerNoteEntryTag.PictureInfo, ifd);
|
||||
} else if (ifd.Equals ("CanonFi")) {
|
||||
EmitTestIFDEntryOpen ("makernote_structure", 0, (ushort) 0x93, ifd);
|
||||
} else if (ifd.Equals ("PanasonicRaw")) {
|
||||
EmitTestIFDEntryOpen ("pana_structure", 0, tag, ifd);
|
||||
} else if (sub_ifds.ContainsKey (ifd)) {
|
||||
EmitTestIFDEntryOpen (String.Format ("{0}_structure", ifd), 0, tag, ifd);
|
||||
} else {
|
||||
throw new Exception (String.Format ("Unknown IFD: {0}", ifd));
|
||||
}
|
||||
|
||||
if (ifd.Equals ("CanonCs") || ifd.Equals ("CanonSi") || ifd.Equals ("CanonCf") || ifd.Equals ("CanonPi")) {
|
||||
// This are a made-up directory by exiv2
|
||||
EmitTestIFDIndexedShortEntry (tag, val);
|
||||
} else if (ifd.Equals ("CanonFi")) {
|
||||
// This are a made-up directory by exiv2
|
||||
// And the fist both entries are combined to a long by exiv2.
|
||||
if (tag == 0x0001) {
|
||||
string val1 = ((ushort) UInt32.Parse (val)).ToString ();
|
||||
string val2 = ((ushort) (UInt32.Parse (val) >> 16)).ToString ();
|
||||
EmitTestIFDIndexedShortEntry (tag, val1);
|
||||
EmitTestIFDIndexedShortEntry (tag + 1, val2);
|
||||
} else {
|
||||
EmitTestIFDIndexedShortEntry (tag, val);
|
||||
}
|
||||
} else if (type.Equals ("Ascii")) {
|
||||
EmitTestIFDStringEntry (val);
|
||||
} else if (type.Equals ("Short") && length == 1) {
|
||||
EmitTestIFDShortEntry (val);
|
||||
} else if (type.Equals ("Short") && length > 1) {
|
||||
EmitTestIFDShortArrayEntry (val);
|
||||
} else if (type.Equals ("SShort") && length == 1) {
|
||||
EmitTestIFDSShortEntry (val);
|
||||
} else if (type.Equals ("SShort") && length > 1) {
|
||||
EmitTestIFDSShortArrayEntry (val);
|
||||
} else if (type.Equals ("Rational") && length == 1) {
|
||||
EmitTestIFDRationalEntry (val);
|
||||
} else if (type.Equals ("Rational") && length > 1) {
|
||||
EmitTestIFDRationalArrayEntry (val);
|
||||
} else if (type.Equals ("SRational") && length == 1) {
|
||||
EmitTestIFDSRationalEntry (val);
|
||||
} else if (type.Equals ("SRational") && length > 1) {
|
||||
EmitTestIFDSRationalArrayEntry (val);
|
||||
} else if (type.Equals ("Long") && length == 1) {
|
||||
EmitTestIFDLongEntry (val);
|
||||
} else if (type.Equals ("Long") && length > 1) {
|
||||
EmitTestIFDLongArrayEntry (val);
|
||||
} else if (type.Equals ("SLong") && length == 1) {
|
||||
EmitTestIFDSLongEntry (val);
|
||||
} else if (type.Equals ("Byte") && length == 1) {
|
||||
EmitTestIFDByteEntry (val);
|
||||
} else if (type.Equals ("Byte") && length > 1) {
|
||||
EmitTestIFDByteArrayEntry (val);
|
||||
} else if (type.Equals ("SByte") && length == 1) {
|
||||
EmitTestIFDSByteEntry (val);
|
||||
} else if (type.Equals ("SubIFD")) {
|
||||
EmitTestIFDSubIFDEntry (val);
|
||||
} else if (type.Equals ("ThumbnailDataIFD")) {
|
||||
EmitTestIFDThumbnailDataIFDEntry (val);
|
||||
} else if (type.Equals ("MakerNote")) {
|
||||
EmitTestIFDMakerNoteIFDEntry (val);
|
||||
} else if (type.Equals ("UserComment")) {
|
||||
EmitTestIFDUserCommentIFDEntry (val);
|
||||
} else if (type.Equals ("Undefined")) {
|
||||
EmitTestIFDUndefinedEntry (val);
|
||||
} else if (type.Equals ("StripOffsets")) {
|
||||
EmitTestIFDStripOffsetsEntry (val);
|
||||
} else if (type.Equals ("IPTCNAA")) {
|
||||
EmitTestIFDIPTCNAAEntry (val);
|
||||
} else if (type.Equals ("XMLPacket")) {
|
||||
EmitTestIFDXMLPacketEntry (val);
|
||||
} else {
|
||||
throw new Exception ("Unknown type: " + type);
|
||||
}
|
||||
|
||||
EmitTestIFDEntryClose ();
|
||||
}
|
||||
|
||||
Write ();
|
||||
Write ("// ---------- End of IFD tests ----------");
|
||||
Write ();
|
||||
}
|
||||
|
||||
static Dictionary<string, string> xmp_prefixes = new Dictionary<string, string> ();
|
||||
|
||||
static void GenerateXMPFixture (string name, string path)
|
||||
{
|
||||
// First run exiv2 on it.
|
||||
string output, err;
|
||||
int code;
|
||||
var result = GLib.Process.SpawnCommandLineSync (String.Format ("./listData x {0}", path), out output, out err, out code);
|
||||
if (!result) {
|
||||
Console.Error.WriteLine ("Invoking exiv2 failed, do you have it installed?");
|
||||
return;
|
||||
}
|
||||
|
||||
if (output.Trim ().Equals (""))
|
||||
return;
|
||||
|
||||
Write ();
|
||||
Write ("// ---------- Start of XMP tests ----------");
|
||||
Write ();
|
||||
|
||||
Write ("XmpTag xmp = file.GetTag (TagTypes.XMP) as XmpTag;");
|
||||
|
||||
// Build prefix lookup dictionary.
|
||||
Type t = typeof(XmpTag);
|
||||
foreach (var member in t.GetMembers()) {
|
||||
if (!member.Name.EndsWith ("_NS"))
|
||||
continue;
|
||||
string val = (member as System.Reflection.FieldInfo).GetValue (null) as string;
|
||||
string prefix = XmpTag.NamespacePrefixes [val];
|
||||
xmp_prefixes [prefix] = member.Name;
|
||||
}
|
||||
|
||||
foreach (string line in output.Split ('\n')) {
|
||||
string[] parts = line.Split (new char[] {'\t'}, 3);
|
||||
if (parts.Length == 0 || line.Trim ().Equals (String.Empty))
|
||||
continue;
|
||||
string label = parts[0];
|
||||
string type = parts[1];
|
||||
uint length = uint.Parse (parts[2]);
|
||||
string val = ExtractKey (path, label).Trim ();
|
||||
|
||||
EmitXmpTest (label, type, length, val);
|
||||
}
|
||||
|
||||
Write ();
|
||||
Write ("// ---------- End of XMP tests ----------");
|
||||
Write ();
|
||||
}
|
||||
|
||||
static void EmitXmpTest (string label, string type, uint length, string val)
|
||||
{
|
||||
if (label.Equals ("Xmp.xmpMM.InstanceID"))
|
||||
return; // Continue this, exiv2 makes it up from the about attr
|
||||
if (label.Equals ("Xmp.tiff.Orientation"))
|
||||
return; // exiv2 destroys this value
|
||||
|
||||
var node_path = label.Split ('/');
|
||||
Write ("// {0} ({1}/{2}) \"{3}\"", label, type, length, val);
|
||||
Write ("{");
|
||||
Write ("var node = xmp.NodeTree;");
|
||||
|
||||
// Navigate to the correct node.
|
||||
foreach (var node in node_path) {
|
||||
var parts = node.Split ('.');
|
||||
var partscolon = node.Split (':');
|
||||
if (parts.Length == 3) {
|
||||
// Plain node
|
||||
int index = 0;
|
||||
string name = parts[2];
|
||||
if (parts[2].EndsWith("]")) {
|
||||
int index_start = parts[2].LastIndexOf ("[");
|
||||
string index_str = parts[2].Substring (index_start+1, parts[2].Length-index_start-2);
|
||||
index = int.Parse (index_str);
|
||||
name = parts[2].Substring (0, index_start);
|
||||
}
|
||||
string ns = GetXmpNs (parts[1]);
|
||||
Write ("node = node.GetChild ({0}, \"{1}\");", ns, name);
|
||||
Write ("Assert.IsNotNull (node);");
|
||||
|
||||
if (index > 0) {
|
||||
Write ("node = node.Children [{0}];", index - 1);
|
||||
Write ("Assert.IsNotNull (node);");
|
||||
}
|
||||
} else if (partscolon.Length == 2) {
|
||||
string ns = GetXmpNs (partscolon[0]);
|
||||
string name = partscolon[1];
|
||||
Write ("node = node.GetChild ({0}, \"{1}\");", ns, name);
|
||||
Write ("Assert.IsNotNull (node);");
|
||||
} else {
|
||||
throw new Exception ("Can't navigate to "+node);
|
||||
}
|
||||
}
|
||||
|
||||
if (length > 0 && type.Equals ("XmpText")) {
|
||||
Write ("Assert.AreEqual (\"{0}\", node.Value);", val);
|
||||
Write ("Assert.AreEqual (XmpNodeType.Simple, node.Type);");
|
||||
Write ("Assert.AreEqual (0, node.Children.Count);");
|
||||
} else if (type.Equals ("XmpBag") && length == 1) {
|
||||
Write ("Assert.AreEqual (XmpNodeType.Bag, node.Type);");
|
||||
Write ("Assert.AreEqual (\"\", node.Value);");
|
||||
Write ("Assert.AreEqual ({0}, node.Children.Count);", length);
|
||||
Write ("Assert.AreEqual (\"{0}\", node.Children [0].Value);", val);
|
||||
} else if (type.Equals ("LangAlt") && length == 1) {
|
||||
var langparts = val.Split (new char [] {' '}, 2);
|
||||
string lang = langparts[0].Substring (langparts[0].IndexOf ('"')+1, langparts [0].Length - langparts[0].IndexOf ('"')-2);
|
||||
Write ("Assert.AreEqual (\"{0}\", node.Children [0].GetQualifier (XmpTag.XML_NS, \"lang\").Value);", lang);
|
||||
Write ("Assert.AreEqual (\"{0}\", node.Children [0].Value);", langparts[1]);
|
||||
} else if (type.Equals ("XmpSeq") && length == 1) {
|
||||
Write ("Assert.AreEqual (XmpNodeType.Seq, node.Type);");
|
||||
Write ("Assert.AreEqual (\"\", node.Value);");
|
||||
Write ("Assert.AreEqual ({0}, node.Children.Count);", length);
|
||||
Write ("Assert.AreEqual (\"{0}\", node.Children [0].Value);", val);
|
||||
} else if (type.Equals ("XmpSeq") && length > 1) {
|
||||
string [] vals = val.Split (',');
|
||||
Write ("Assert.AreEqual (XmpNodeType.Seq, node.Type);");
|
||||
Write ("Assert.AreEqual (\"\", node.Value);");
|
||||
Write ("Assert.AreEqual ({0}, node.Children.Count);", length);
|
||||
var per_iter = vals.Length / length;
|
||||
for (int i = 0; i < length; i++) {
|
||||
var builder = new List<string> ();
|
||||
for (int j = 0; j < per_iter; j++) {
|
||||
builder.Add (vals[per_iter*i + j].Trim ());
|
||||
}
|
||||
Write ("Assert.AreEqual (\"{0}\", node.Children [{1}].Value);", String.Join (", ", builder.ToArray ()), i);
|
||||
}
|
||||
} else if (type.Equals ("XmpBag") && length > 1) {
|
||||
string [] vals = val.Split (',');
|
||||
Write ("Assert.AreEqual (XmpNodeType.Bag, node.Type);");
|
||||
Write ("Assert.AreEqual (\"\", node.Value);");
|
||||
Write ("Assert.AreEqual ({0}, node.Children.Count);", length);
|
||||
Write ("var children_array = new System.Collections.Generic.List<string> ();");
|
||||
Write ("foreach (var child in node.Children)");
|
||||
Write ("{");
|
||||
Write ("children_array.Add (child.Value);");
|
||||
Write ("}");
|
||||
var per_iter = vals.Length / length;
|
||||
for (int i = 0; i < length; i++) {
|
||||
var builder = new List<string> ();
|
||||
for (int j = 0; j < per_iter; j++) {
|
||||
builder.Add (vals[per_iter*i + j].Trim ());
|
||||
}
|
||||
Write ("Assert.IsTrue (children_array.Contains (\"{0}\"));", String.Join (", ", builder.ToArray ()));
|
||||
}
|
||||
} else if (type.Equals ("XmpText") && length == 0 && val.StartsWith ("type=")) {
|
||||
if (val.Equals ("type=\"Bag\"")) {
|
||||
Write ("Assert.AreEqual (XmpNodeType.Bag, node.Type);");
|
||||
} else if (val.Equals ("type=\"Struct\"")) {
|
||||
// We disagree with exiv2 on the meaning of Struct. In Taglib#,
|
||||
// struct is meant to denote parseType=Resource types only, not
|
||||
// the shorthand equivalent. Also see XmpNode.RenderInto()
|
||||
//Write ("Assert.AreEqual (XmpNodeType.Struct, node.Type);");
|
||||
} else {
|
||||
throw new Exception ("Unknown type");
|
||||
}
|
||||
} else {
|
||||
throw new Exception (String.Format ("Can't test this (type: {0}, length: {1})", type, length));
|
||||
}
|
||||
Write ("}");
|
||||
}
|
||||
|
||||
static string ExtractKey (string file, string key)
|
||||
{
|
||||
string output, err;
|
||||
int code;
|
||||
var result = GLib.Process.SpawnCommandLineSync (String.Format ("./extractKey {0} {1}", file, key), out output, out err, out code);
|
||||
if (!result) {
|
||||
Console.Error.WriteLine ("Invoking extractKey failed, are you running from the examples folder?");
|
||||
return String.Empty;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
static string GetXmpNs (string prefix)
|
||||
{
|
||||
string result;
|
||||
if (prefix.Equals ("xmpBJ"))
|
||||
prefix = "xapBJ";
|
||||
if (prefix.Equals ("xmpMM"))
|
||||
prefix = "xapMM";
|
||||
if (prefix.Equals ("xmpRights"))
|
||||
prefix = "xapRights";
|
||||
if (prefix.Equals ("MicrosoftPhoto_1_")) // We correct this invalid namespace internally
|
||||
prefix = "MicrosoftPhoto";
|
||||
if (xmp_prefixes.TryGetValue (prefix, out result))
|
||||
return String.Format ("XmpTag.{0}", result);
|
||||
throw new Exception ("Unknown namespace prefix: "+prefix);
|
||||
}
|
||||
|
||||
static bool IsPartOfMakernote (string ifd) {
|
||||
return ifd.Equals ("MakerNote") ||
|
||||
ifd.Equals ("Canon") ||
|
||||
ifd.Equals ("Sony") ||
|
||||
ifd.Equals ("Nikon1") ||
|
||||
ifd.Equals ("Nikon2") ||
|
||||
ifd.Equals ("Nikon3") ||
|
||||
ifd.Equals ("Panasonic") ||
|
||||
ifd.Equals ("Olympus") ||
|
||||
ifd.Equals ("Pentax");
|
||||
}
|
||||
|
||||
static void EmitHeader (string name, string path)
|
||||
{
|
||||
int start = path.LastIndexOf ('/');
|
||||
string filename = path.Substring (start+1);
|
||||
Write ("// TODO: This file is automatically generated");
|
||||
Write ("// TODO: Further manual verification is needed");
|
||||
Write ();
|
||||
Write ("using System;");
|
||||
Write ("using NUnit.Framework;");
|
||||
Write ("using TagLib.IFD;");
|
||||
Write ("using TagLib.IFD.Entries;");
|
||||
Write ("using TagLib.IFD.Tags;");
|
||||
Write ("using TagLib.Xmp;");
|
||||
Write ("using TagLib.Tests.Images.Validators;");
|
||||
Write ();
|
||||
Write ("namespace TagLib.Tests.Images");
|
||||
Write ("{");
|
||||
Write ("[TestFixture]");
|
||||
Write ("public class {0}", name);
|
||||
Write ("{");
|
||||
Write ("[Test]");
|
||||
Write ("public void Test ()");
|
||||
Write ("{");
|
||||
Write ("ImageTest.Run (\"{0}\",", filename);
|
||||
level++;
|
||||
Write ("new {0}InvariantValidator (),", name);
|
||||
Write ("NoModificationValidator.Instance");
|
||||
level--;
|
||||
Write (");");
|
||||
Write ("}");
|
||||
Write ("}");
|
||||
Write ();
|
||||
Write ("public class {0}InvariantValidator : IMetadataInvariantValidator", name);
|
||||
Write ("{");
|
||||
Write ("public void ValidateMetadataInvariants (Image.File file)");
|
||||
Write ("{");
|
||||
Write ("Assert.IsNotNull (file);");
|
||||
}
|
||||
|
||||
static void EmitFooter ()
|
||||
{
|
||||
Write ("}"); // Method
|
||||
Write ("}"); // Class
|
||||
Write ("}"); // Namespace
|
||||
}
|
||||
|
||||
static bool is_panasonic_raw = false;
|
||||
|
||||
static bool structure_emitted = false;
|
||||
static bool exif_emitted = false;
|
||||
static bool makernote_emitted = false;
|
||||
static bool makernote_is_canon = false;
|
||||
static bool makernote_is_nikon1 = false;
|
||||
static bool makernote_is_nikon2 = false;
|
||||
static bool makernote_is_nikon3 = false;
|
||||
static bool makernote_is_panasonic = false;
|
||||
static bool nikonpreview_emitted = false;
|
||||
static bool iop_emitted = false;
|
||||
static bool gps_emitted = false;
|
||||
|
||||
static void EnsureIFD (string ifd) {
|
||||
if (ifd.Equals ("PanasonicRaw")) {
|
||||
if (is_panasonic_raw)
|
||||
return;
|
||||
|
||||
Write ();
|
||||
Write ("var tag = file.GetTag (TagTypes.TiffIFD) as IFDTag;");
|
||||
Write ("Assert.IsNotNull (tag, \"IFD tag not found\");");
|
||||
Write ();
|
||||
Write ("var pana_structure = tag.Structure;");
|
||||
Write ();
|
||||
Write ("var jpg_file = (file as TagLib.Tiff.Rw2.File).JpgFromRaw;");
|
||||
Write ("Assert.IsNotNull (tag, \"JpgFromRaw not found!\");");
|
||||
Write ("var jpg_tag = jpg_file.GetTag (TagTypes.TiffIFD) as IFDTag;");
|
||||
Write ("Assert.IsNotNull (tag, \"Jpg has no Exif tag!\");");
|
||||
Write ("var structure = jpg_tag.Structure;");
|
||||
|
||||
is_panasonic_raw = true;
|
||||
}
|
||||
|
||||
if (ifd.Equals ("Image") && !is_panasonic_raw) {
|
||||
if (structure_emitted)
|
||||
return;
|
||||
Write ();
|
||||
Write ("var tag = file.GetTag (TagTypes.TiffIFD) as IFDTag;");
|
||||
Write ("Assert.IsNotNull (tag, \"IFD tag not found\");");
|
||||
Write ();
|
||||
Write ("var structure = tag.Structure;");
|
||||
Write ();
|
||||
structure_emitted = true;
|
||||
}
|
||||
|
||||
if (ifd.Equals ("Photo")) {
|
||||
if (exif_emitted)
|
||||
return;
|
||||
EnsureIFD ("Image");
|
||||
Write ();
|
||||
Write ("var exif = structure.GetEntry (0, (ushort) IFDEntryTag.ExifIFD) as SubIFDEntry;");
|
||||
Write ("Assert.IsNotNull (exif, \"Exif tag not found\");");
|
||||
Write ("var exif_structure = exif.Structure;");
|
||||
Write ();
|
||||
exif_emitted = true;
|
||||
}
|
||||
|
||||
if (ifd.Equals ("MakerNote")) {
|
||||
if (makernote_emitted)
|
||||
return;
|
||||
EnsureIFD ("Photo");
|
||||
Write ();
|
||||
Write ("var makernote = exif_structure.GetEntry (0, (ushort) ExifEntryTag.MakerNote) as MakernoteIFDEntry;");
|
||||
Write ("Assert.IsNotNull (makernote, \"MakerNote tag not found\");");
|
||||
Write ("var makernote_structure = makernote.Structure;");
|
||||
Write ();
|
||||
makernote_emitted = true;
|
||||
}
|
||||
|
||||
if (ifd.Equals ("Canon") || ifd.Equals ("CanonCs") || ifd.Equals ("CanonSi")) {
|
||||
if (makernote_is_canon)
|
||||
return;
|
||||
EnsureIFD ("MakerNote");
|
||||
Write ();
|
||||
Write ("Assert.AreEqual (MakernoteType.Canon, makernote.MakernoteType);");
|
||||
Write ();
|
||||
makernote_is_canon = true;
|
||||
}
|
||||
|
||||
if (ifd.Equals ("Nikon1")) {
|
||||
if (makernote_is_nikon1)
|
||||
return;
|
||||
EnsureIFD ("MakerNote");
|
||||
Write ();
|
||||
Write ("Assert.AreEqual (MakernoteType.Nikon1, makernote.MakernoteType);");
|
||||
Write ();
|
||||
makernote_is_nikon1 = true;
|
||||
}
|
||||
|
||||
if (ifd.Equals ("Nikon2")) {
|
||||
if (makernote_is_nikon2)
|
||||
return;
|
||||
EnsureIFD ("MakerNote");
|
||||
Write ();
|
||||
Write ("Assert.AreEqual (MakernoteType.Nikon2, makernote.MakernoteType);");
|
||||
Write ();
|
||||
makernote_is_nikon2 = true;
|
||||
}
|
||||
|
||||
if (ifd.Equals ("Nikon3")) {
|
||||
if (makernote_is_nikon3)
|
||||
return;
|
||||
EnsureIFD ("MakerNote");
|
||||
Write ();
|
||||
Write ("Assert.AreEqual (MakernoteType.Nikon3, makernote.MakernoteType);");
|
||||
Write ();
|
||||
makernote_is_nikon3 = true;
|
||||
}
|
||||
|
||||
if (ifd.Equals ("NikonPreview")) {
|
||||
if (nikonpreview_emitted)
|
||||
return;
|
||||
EnsureIFD ("Nikon3");
|
||||
Write ();
|
||||
Write ("var nikonpreview = makernote_structure.GetEntry (0, (ushort) Nikon3MakerNoteEntryTag.Preview) as SubIFDEntry;");
|
||||
Write ("Assert.IsNotNull (nikonpreview, \"Nikon preview tag not found\");");
|
||||
Write ("var nikonpreview_structure = nikonpreview.Structure;");
|
||||
Write ();
|
||||
nikonpreview_emitted = true;
|
||||
}
|
||||
|
||||
if (ifd.Equals ("Panasonic")) {
|
||||
if (makernote_is_panasonic)
|
||||
return;
|
||||
EnsureIFD ("MakerNote");
|
||||
Write ();
|
||||
Write ("Assert.AreEqual (MakernoteType.Panasonic, makernote.MakernoteType);");
|
||||
Write ();
|
||||
makernote_is_panasonic = true;
|
||||
}
|
||||
|
||||
if (ifd.Equals ("Iop")) {
|
||||
if (iop_emitted)
|
||||
return;
|
||||
EnsureIFD ("Photo");
|
||||
Write ();
|
||||
Write ("var iop = exif_structure.GetEntry (0, (ushort) IFDEntryTag.InteroperabilityIFD) as SubIFDEntry;");
|
||||
Write ("Assert.IsNotNull (iop, \"Iop tag not found\");");
|
||||
Write ("var iop_structure = iop.Structure;");
|
||||
Write ();
|
||||
iop_emitted = true;
|
||||
}
|
||||
|
||||
if (ifd.Equals ("GPSInfo")) {
|
||||
if (gps_emitted)
|
||||
return;
|
||||
EnsureIFD ("Image");
|
||||
Write ();
|
||||
Write ("var gps = structure.GetEntry (0, (ushort) IFDEntryTag.GPSIFD) as SubIFDEntry;");
|
||||
Write ("Assert.IsNotNull (gps, \"GPS tag not found\");");
|
||||
Write ("var gps_structure = gps.Structure;");
|
||||
Write ();
|
||||
gps_emitted = true;
|
||||
}
|
||||
|
||||
if (sub_ifds.ContainsKey (ifd) && !sub_ifds_emitted.ContainsKey (ifd)) {
|
||||
Write ();
|
||||
Write ("var {0}_structure = (structure.GetEntry (0, (ushort) IFDEntryTag.SubIFDs) as SubIFDArrayEntry).Entries [{1}];", ifd, sub_ifds[ifd]);
|
||||
Write ("Assert.IsNotNull ({0}_structure, \"{0} structure not found\");", ifd);
|
||||
Write ();
|
||||
sub_ifds_emitted.Add (ifd, true);
|
||||
}
|
||||
}
|
||||
|
||||
static void EmitTestIFDEntryOpen (string src, int ifd, ushort tag, string ifd_label)
|
||||
{
|
||||
Write ("{");
|
||||
Write (String.Format ("var entry = {0}.GetEntry ({1}, (ushort) {2});", src, ifd, StringifyEntryTag (ifd_label, tag)));
|
||||
Write (String.Format ("Assert.IsNotNull (entry, \"Entry 0x{0:X4} missing in IFD {1}\");", tag, ifd));
|
||||
}
|
||||
|
||||
static void EmitTestIFDEntryClose ()
|
||||
{
|
||||
Write ("}");
|
||||
}
|
||||
|
||||
static void EmitTestIFDStringEntry (string val)
|
||||
{
|
||||
Write ("Assert.IsNotNull (entry as StringIFDEntry, \"Entry is not a string!\");");
|
||||
Write ("Assert.AreEqual (\"{0}\", (entry as StringIFDEntry).Value{1});", val, val == String.Empty ? ".Trim ()" : "");
|
||||
}
|
||||
|
||||
static void EmitTestIFDShortEntry (string val)
|
||||
{
|
||||
Write ("Assert.IsNotNull (entry as ShortIFDEntry, \"Entry is not a short!\");");
|
||||
Write ("Assert.AreEqual ({0}, (entry as ShortIFDEntry).Value);", val);
|
||||
}
|
||||
|
||||
static void EmitTestIFDSShortEntry (string val)
|
||||
{
|
||||
Write ("Assert.IsNotNull (entry as SShortIFDEntry, \"Entry is not a signed short!\");");
|
||||
Write ("Assert.AreEqual ({0}, (entry as SShortIFDEntry).Value);", val);
|
||||
}
|
||||
|
||||
static void EmitTestIFDShortArrayEntry (string val)
|
||||
{
|
||||
val = String.Format ("new ushort [] {{ {0} }}", String.Join (", ", val.Split(' ')));
|
||||
Write ("Assert.IsNotNull (entry as ShortArrayIFDEntry, \"Entry is not a short array!\");");
|
||||
Write ("Assert.AreEqual ({0}, (entry as ShortArrayIFDEntry).Values);", val);
|
||||
}
|
||||
|
||||
static void EmitTestIFDSShortArrayEntry (string val)
|
||||
{
|
||||
val = String.Format ("new short [] {{ {0} }}", String.Join (", ", val.Split(' ')));
|
||||
Write ("Assert.IsNotNull (entry as SShortArrayIFDEntry, \"Entry is not a signed short array!\");");
|
||||
Write ("Assert.AreEqual ({0}, (entry as SShortArrayIFDEntry).Values);", val);
|
||||
}
|
||||
|
||||
static void EmitTestIFDRationalEntry (string val)
|
||||
{
|
||||
Write ("Assert.IsNotNull (entry as RationalIFDEntry, \"Entry is not a rational!\");");
|
||||
string[] parts = val.Split('/');
|
||||
Write ("Assert.AreEqual ({0}, (entry as RationalIFDEntry).Value.Numerator);", parts [0]);
|
||||
Write ("Assert.AreEqual ({0}, (entry as RationalIFDEntry).Value.Denominator);", parts [1]);
|
||||
}
|
||||
|
||||
static void EmitTestIFDRationalArrayEntry (string val)
|
||||
{
|
||||
var parts = val.Split(' ');
|
||||
Write ("Assert.IsNotNull (entry as RationalArrayIFDEntry, \"Entry is not a rational array!\");");
|
||||
Write ("var parts = (entry as RationalArrayIFDEntry).Values;");
|
||||
Write ("Assert.AreEqual ({0}, parts.Length);", parts.Length);
|
||||
for (int i = 0; i < parts.Length; i++) {
|
||||
var pieces = parts[i].Split('/');
|
||||
Write ("Assert.AreEqual ({0}, parts[{1}].Numerator);", pieces[0], i);
|
||||
Write ("Assert.AreEqual ({0}, parts[{1}].Denominator);", pieces[1], i);
|
||||
}
|
||||
}
|
||||
|
||||
static void EmitTestIFDSRationalEntry (string val)
|
||||
{
|
||||
Write ("Assert.IsNotNull (entry as SRationalIFDEntry, \"Entry is not a srational!\");");
|
||||
string[] parts = val.Split('/');
|
||||
Write ("Assert.AreEqual ({0}, (entry as SRationalIFDEntry).Value.Numerator);", parts [0]);
|
||||
Write ("Assert.AreEqual ({0}, (entry as SRationalIFDEntry).Value.Denominator);", parts [1]);
|
||||
}
|
||||
|
||||
static void EmitTestIFDSRationalArrayEntry (string val)
|
||||
{
|
||||
var parts = val.Split(' ');
|
||||
Write ("Assert.IsNotNull (entry as SRationalArrayIFDEntry, \"Entry is not a srational array!\");");
|
||||
Write ("var parts = (entry as SRationalArrayIFDEntry).Values;");
|
||||
Write ("Assert.AreEqual ({0}, parts.Length);", parts.Length);
|
||||
for (int i = 0; i < parts.Length; i++) {
|
||||
var pieces = parts[i].Split('/');
|
||||
Write ("Assert.AreEqual ({0}, parts[{1}].Numerator);", pieces[0], i);
|
||||
Write ("Assert.AreEqual ({0}, parts[{1}].Denominator);", pieces[1], i);
|
||||
}
|
||||
}
|
||||
|
||||
static void EmitTestIFDLongEntry (string val)
|
||||
{
|
||||
Write ("Assert.IsNotNull (entry as LongIFDEntry, \"Entry is not a long!\");");
|
||||
Write ("Assert.AreEqual ({0}, (entry as LongIFDEntry).Value);", val);
|
||||
}
|
||||
|
||||
static void EmitTestIFDLongArrayEntry (string val)
|
||||
{
|
||||
val = String.Format ("new long [] {{ {0} }}", String.Join (", ", val.Split(' ')));
|
||||
Write ("Assert.IsNotNull (entry as LongArrayIFDEntry, \"Entry is not a long array!\");");
|
||||
Write ("Assert.AreEqual ({0}, (entry as LongArrayIFDEntry).Values);", val);
|
||||
}
|
||||
|
||||
static void EmitTestIFDSLongEntry (string val)
|
||||
{
|
||||
Write ("Assert.IsNotNull (entry as SLongIFDEntry, \"Entry is not a signed long!\");");
|
||||
Write ("Assert.AreEqual ({0}, (entry as SLongIFDEntry).Value);", val);
|
||||
}
|
||||
|
||||
static void EmitTestIFDByteEntry (string val)
|
||||
{
|
||||
Write ("Assert.IsNotNull (entry as ByteIFDEntry, \"Entry is not a byte!\");");
|
||||
Write ("Assert.AreEqual ({0}, (entry as ByteIFDEntry).Value);", val);
|
||||
}
|
||||
|
||||
static void EmitTestIFDByteArrayEntry (string val)
|
||||
{
|
||||
EmitByteArrayComparison (val, "ByteVectorIFDEntry", "a byte array");
|
||||
}
|
||||
|
||||
static void EmitTestIFDSByteEntry (string val)
|
||||
{
|
||||
Write ("Assert.IsNotNull (entry as SByteIFDEntry, \"Entry is not a signed byte!\");");
|
||||
Write ("Assert.AreEqual ({0}, (entry as SByteIFDEntry).Value);", val);
|
||||
}
|
||||
|
||||
static void EmitTestIFDIPTCNAAEntry (string val)
|
||||
{
|
||||
Write ("Assert.IsNotNull (entry as ByteVectorIFDEntry, \"Entry is not a byte array!\");");
|
||||
}
|
||||
|
||||
static void EmitTestIFDXMLPacketEntry (string val)
|
||||
{
|
||||
Write ("Assert.IsNotNull (entry as ByteVectorIFDEntry, \"Entry is not a byte array!\");");
|
||||
}
|
||||
|
||||
static void EmitTestIFDUndefinedEntry (string val)
|
||||
{
|
||||
EmitByteArrayComparison (val, "UndefinedIFDEntry", "an undefined IFD entry");
|
||||
}
|
||||
|
||||
static void EmitByteArrayComparison (string val, string type, string type_desc)
|
||||
{
|
||||
Write ("Assert.IsNotNull (entry as {0}, \"Entry is not {1}!\");", type, type_desc);
|
||||
Write ("var parsed_bytes = (entry as {0}).Data.Data;", type);
|
||||
var parts = val.Trim ().Split(' ');
|
||||
if (parts.Length < 512) {
|
||||
Write ("var bytes = new byte [] {{ {0} }};", String.Join (", ", parts));
|
||||
Write ("Assert.AreEqual (bytes, parsed_bytes);");
|
||||
} else {
|
||||
// Starting with 512 byte items, we compare based on an MD5 hash, should be faster and reduces
|
||||
// the size of the test fixtures.
|
||||
byte [] data = new byte [parts.Length];
|
||||
for (int i = 0; i < parts.Length; i++) {
|
||||
data [i] = Byte.Parse (parts [i]);
|
||||
}
|
||||
var hash = md5.ComputeHash (data);
|
||||
|
||||
StringBuilder shash = new StringBuilder ();
|
||||
for (int i = 0; i < hash.Length; i++) {
|
||||
shash.Append (hash[i].ToString ("x2"));
|
||||
}
|
||||
|
||||
Write ("var parsed_hash = Utils.Md5Encode (parsed_bytes);");
|
||||
Write ("Assert.AreEqual (\"{0}\", parsed_hash);", shash.ToString ());
|
||||
Write ("Assert.AreEqual ({0}, parsed_bytes.Length);", parts.Length);
|
||||
}
|
||||
}
|
||||
|
||||
static void EmitTestIFDSubIFDEntry (string val)
|
||||
{
|
||||
Write ("Assert.IsNotNull (entry as SubIFDEntry, \"Entry is not a sub IFD!\");");
|
||||
}
|
||||
|
||||
static void EmitTestIFDThumbnailDataIFDEntry (string val)
|
||||
{
|
||||
Write ("Assert.IsNotNull (entry as ThumbnailDataIFDEntry, \"Entry is not a thumbnail IFD!\");");
|
||||
}
|
||||
|
||||
static void EmitTestIFDMakerNoteIFDEntry (string val)
|
||||
{
|
||||
Write ("Assert.IsNotNull (entry as MakernoteIFDEntry, \"Entry is not a makernote IFD!\");");
|
||||
}
|
||||
|
||||
static void EmitTestIFDUserCommentIFDEntry (string val)
|
||||
{
|
||||
Write ("Assert.IsNotNull (entry as UserCommentIFDEntry, \"Entry is not a user comment!\");");
|
||||
if (val.StartsWith ("charset=\"Ascii\""))
|
||||
val = val.Substring (15).Trim ();
|
||||
Write ("Assert.AreEqual (\"{0}\", (entry as UserCommentIFDEntry).Value.Trim ());", val);
|
||||
}
|
||||
|
||||
static void EmitTestIFDStripOffsetsEntry (string val)
|
||||
{
|
||||
// The offsets may change after writing. Therfore we cannot compare them directly.
|
||||
string offset_count = String.Format ("{0}", val.Split(' ').Length);
|
||||
//val = String.Format ("new long [] {{ {0} }}", String.Join (", ", val.Split(' ')));
|
||||
Write ("Assert.IsNotNull (entry as StripOffsetsIFDEntry, \"Entry is not a strip offsets entry!\");");
|
||||
//Write ("Assert.AreEqual ({0}, (entry as StripOffsetsIFDEntry).Values);", val);
|
||||
Write ("Assert.AreEqual ({0}, (entry as StripOffsetsIFDEntry).Values.Length);", offset_count);
|
||||
}
|
||||
|
||||
static void EmitTestIFDIndexedShortEntry (int index, string val)
|
||||
{
|
||||
Write ("Assert.IsNotNull (entry as ShortArrayIFDEntry, \"Entry is not a short array!\");");
|
||||
var parts = val.Trim ().Split (' ');
|
||||
Write ("Assert.IsTrue ({0} <= (entry as ShortArrayIFDEntry).Values.Length);", index + parts.Length);
|
||||
for (int i = 0; i < parts.Length; i++)
|
||||
Write ("Assert.AreEqual ({0}, (entry as ShortArrayIFDEntry).Values [{1}]);", parts [i], index + i);
|
||||
}
|
||||
|
||||
#region IFD tag names lookup
|
||||
|
||||
static Dictionary<string, Dictionary<ushort, string>> tag_names = null;
|
||||
|
||||
static string StringifyEntryTag (string src, ushort tag)
|
||||
{
|
||||
if (tag_names == null)
|
||||
BuildTagNamesTable ();
|
||||
Dictionary<ushort, string> table;
|
||||
string result;
|
||||
if (tag_names.TryGetValue (src, out table)) {
|
||||
if (table.TryGetValue (tag, out result))
|
||||
return result;
|
||||
}
|
||||
Write ("// TODO: Unknown IFD tag: {1} / 0x{0:X4}", tag, src);
|
||||
return String.Format ("0x{0:X4}", tag);
|
||||
}
|
||||
|
||||
static void BuildTagNamesTable ()
|
||||
{
|
||||
tag_names = new Dictionary<string, Dictionary<ushort, string>> ();
|
||||
|
||||
IndexTagType ("Image", typeof (IFDEntryTag), "IFDEntryTag");
|
||||
IndexTagType ("Image2", typeof (IFDEntryTag), "IFDEntryTag");
|
||||
IndexTagType ("Image3", typeof (IFDEntryTag), "IFDEntryTag");
|
||||
IndexTagType ("SubImage1", typeof (IFDEntryTag), "IFDEntryTag");
|
||||
IndexTagType ("SubImage2", typeof (IFDEntryTag), "IFDEntryTag");
|
||||
IndexTagType ("Thumbnail", typeof (IFDEntryTag), "IFDEntryTag"); // IFD1, for thumbnails
|
||||
IndexTagType ("Photo", typeof (IFDEntryTag), "IFDEntryTag");
|
||||
IndexTagType ("Photo", typeof (ExifEntryTag), "ExifEntryTag");
|
||||
IndexTagType ("Image", typeof (ExifEntryTag), "ExifEntryTag"); // Also put exif into Image, for DNG
|
||||
IndexTagType ("GPSInfo", typeof (GPSEntryTag), "GPSEntryTag");
|
||||
IndexTagType ("Iop", typeof (IOPEntryTag), "IOPEntryTag");
|
||||
IndexTagType ("Canon", typeof (CanonMakerNoteEntryTag), "CanonMakerNoteEntryTag");
|
||||
IndexTagType ("CanonCs", typeof (CanonMakerNoteEntryTag), "CanonMakerNoteEntryTag");
|
||||
IndexTagType ("CanonSi", typeof (CanonMakerNoteEntryTag), "CanonMakerNoteEntryTag");
|
||||
IndexTagType ("CanonCf", typeof (CanonMakerNoteEntryTag), "CanonMakerNoteEntryTag");
|
||||
IndexTagType ("CanonFi", typeof (CanonFileInfoEntryTag), "CanonFileInfoEntryTag");
|
||||
IndexTagType ("CanonFi", typeof (CanonMakerNoteEntryTag), "CanonMakerNoteEntryTag");
|
||||
IndexTagType ("CanonPi", typeof (CanonPictureInfoEntryTag), "CanonPictureInfoEntryTag");
|
||||
IndexTagType ("CanonPi", typeof (CanonMakerNoteEntryTag), "CanonMakerNoteEntryTag");
|
||||
IndexTagType ("Sony", typeof (SonyMakerNoteEntryTag), "SonyMakerNoteEntryTag");
|
||||
IndexTagType ("Olympus", typeof (OlympusMakerNoteEntryTag), "OlympusMakerNoteEntryTag");
|
||||
IndexTagType ("Pentax", typeof (PentaxMakerNoteEntryTag), "PentaxMakerNoteEntryTag");
|
||||
IndexTagType ("Nikon3", typeof (Nikon3MakerNoteEntryTag), "Nikon3MakerNoteEntryTag");
|
||||
IndexTagType ("NikonPreview", typeof (NikonPreviewMakerNoteEntryTag), "NikonPreviewMakerNoteEntryTag");
|
||||
IndexTagType ("Panasonic", typeof (PanasonicMakerNoteEntryTag), "PanasonicMakerNoteEntryTag");
|
||||
IndexTagType ("PanasonicRaw", typeof (IFDEntryTag), "IFDEntryTag");
|
||||
}
|
||||
|
||||
static void IndexTagType (string ifd, Type t, string typename)
|
||||
{
|
||||
if (!tag_names.ContainsKey (ifd))
|
||||
tag_names[ifd] = new Dictionary<ushort, string> ();
|
||||
foreach (string name in Enum.GetNames (t)) {
|
||||
ushort tag = (ushort) Enum.Parse (t, name);
|
||||
tag_names[ifd][tag] = String.Format ("{1}.{0}", name, typename);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Code emission
|
||||
|
||||
static int level = 0;
|
||||
|
||||
static void Write (string str, params object[] p)
|
||||
{
|
||||
Console.Write (new String ('\t', level));
|
||||
Console.WriteLine (str, p);
|
||||
}
|
||||
|
||||
static void Write ()
|
||||
{
|
||||
Console.WriteLine ();
|
||||
}
|
||||
|
||||
static void Write (string str)
|
||||
{
|
||||
if (str.Equals ("}"))
|
||||
level--;
|
||||
Console.Write (new String ('\t', level));
|
||||
Console.WriteLine (str);
|
||||
if (str.Equals ("{"))
|
||||
level++;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
using System;
|
||||
using TagLib;
|
||||
|
||||
public class ListSupportedMimeTypes
|
||||
{
|
||||
public static void Main()
|
||||
{
|
||||
foreach(string type in SupportedMimeType.AllMimeTypes) {
|
||||
Console.WriteLine(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
READ_FROM_URI = ReadFromUri
|
||||
SET_PICTURES = SetPictures
|
||||
LIST_TYPES = ListSupportedMimeTypes
|
||||
BATCH_SET = BatchSet
|
||||
PARSE_PHOTO = ParsePhoto
|
||||
STRIP_IMAGE = StripImageData
|
||||
GENERATE_TEST_FIXTURE = GenerateTestFixture
|
||||
|
||||
REFERENCES = -r:taglib-sharp.dll
|
||||
EXAMPLES_BUILD = taglib-sharp.dll $(SET_PICTURES).exe $(LIST_TYPES).exe $(BATCH_SET).exe $(PARSE_PHOTO).exe $(STRIP_IMAGE).exe
|
||||
|
||||
if HAVE_GNOME_SHARP
|
||||
EXAMPLES_BUILD += $(READ_FROM_URI).exe
|
||||
if HAVE_EXIV2
|
||||
EXAMPLES_BUILD += $(GENERATE_TEST_FIXTURE).exe
|
||||
endif
|
||||
endif
|
||||
|
||||
all: $(EXAMPLES_BUILD)
|
||||
|
||||
taglib-sharp.dll:
|
||||
if [ ! -e $@ ]; then ln -s $(top_builddir)/src/taglib-sharp.dll $@; fi
|
||||
|
||||
if HAVE_GNOME_SHARP
|
||||
$(READ_FROM_URI).exe: $(READ_FROM_URI).cs
|
||||
$(MCS) -out:$@ -debug $(REFERENCES) $(GNOME_SHARP_LIBS) $<
|
||||
|
||||
if HAVE_EXIV2
|
||||
$(GENERATE_TEST_FIXTURE).exe: $(GENERATE_TEST_FIXTURE).cs listData extractKey
|
||||
$(MCS) -out:$@ -debug $(REFERENCES) $(GNOME_SHARP_LIBS) $<
|
||||
|
||||
listData: listData.cpp
|
||||
g++ -o $@ $(EXIV2_LIBS) $<
|
||||
|
||||
extractKey: extractKey.cpp
|
||||
g++ -o $@ $(EXIV2_LIBS) $<
|
||||
endif
|
||||
endif
|
||||
|
||||
$(SET_PICTURES).exe: $(SET_PICTURES).cs
|
||||
$(MCS) -out:$@ -debug $(REFERENCES) $<
|
||||
|
||||
$(LIST_TYPES).exe: $(LIST_TYPES).cs
|
||||
$(MCS) -out:$@ -debug $(REFERENCES) $<
|
||||
|
||||
$(BATCH_SET).exe: $(BATCH_SET).cs
|
||||
$(MCS) -out:$@ -debug $(REFERENCES) $<
|
||||
|
||||
$(PARSE_PHOTO).exe: $(PARSE_PHOTO).cs
|
||||
$(MCS) -out:$@ -debug $(REFERENCES) $<
|
||||
|
||||
$(STRIP_IMAGE).exe: $(STRIP_IMAGE).cs
|
||||
$(MCS) -out:$@ -debug $(REFERENCES) $<
|
||||
|
||||
EXTRA_DIST = $(READ_FROM_URI).cs $(SET_PICTURES).cs $(LIST_TYPES).cs $(BATCH_SET).cs $(PARSE_PHOTO).cs $(STRIP_IMAGE).cs $(GENERATE_TEST_FIXTURE).cs \
|
||||
$(srcdir)/covers/sample*
|
||||
|
||||
DISTCLEANFILES = *.pidb
|
||||
CLEANFILES = *.dll *.exe *.mdb
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
using System;
|
||||
|
||||
public class ParsePhotoApp
|
||||
{
|
||||
public static void Main (string [] args)
|
||||
{
|
||||
if(args.Length == 0) {
|
||||
Console.Error.WriteLine("USAGE: mono ParsePhoto.exe PATH [...]");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (string path in args)
|
||||
ParsePhoto (path);
|
||||
}
|
||||
|
||||
static void ParsePhoto (string path)
|
||||
{
|
||||
TagLib.File file = null;
|
||||
|
||||
try {
|
||||
file = TagLib.File.Create(path);
|
||||
} catch (TagLib.UnsupportedFormatException) {
|
||||
Console.WriteLine ("UNSUPPORTED FILE: " + path);
|
||||
Console.WriteLine (String.Empty);
|
||||
Console.WriteLine ("---------------------------------------");
|
||||
Console.WriteLine (String.Empty);
|
||||
return;
|
||||
}
|
||||
|
||||
var image = file as TagLib.Image.File;
|
||||
if (file == null) {
|
||||
Console.WriteLine ("NOT AN IMAGE FILE: " + path);
|
||||
Console.WriteLine (String.Empty);
|
||||
Console.WriteLine ("---------------------------------------");
|
||||
Console.WriteLine (String.Empty);
|
||||
return;
|
||||
}
|
||||
|
||||
Console.WriteLine (String.Empty);
|
||||
Console.WriteLine (path);
|
||||
Console.WriteLine (String.Empty);
|
||||
|
||||
Console.WriteLine("Tags in object : " + image.TagTypes);
|
||||
Console.WriteLine (String.Empty);
|
||||
|
||||
Console.WriteLine("Comment : " + image.ImageTag.Comment);
|
||||
Console.Write("Keywords : ");
|
||||
foreach (var keyword in image.ImageTag.Keywords) {
|
||||
Console.Write (keyword + " ");
|
||||
}
|
||||
Console.WriteLine ();
|
||||
Console.WriteLine("Rating : " + image.ImageTag.Rating);
|
||||
Console.WriteLine("DateTime : " + image.ImageTag.DateTime);
|
||||
Console.WriteLine("Orientation : " + image.ImageTag.Orientation);
|
||||
Console.WriteLine("Software : " + image.ImageTag.Software);
|
||||
Console.WriteLine("ExposureTime : " + image.ImageTag.ExposureTime);
|
||||
Console.WriteLine("FNumber : " + image.ImageTag.FNumber);
|
||||
Console.WriteLine("ISOSpeedRatings : " + image.ImageTag.ISOSpeedRatings);
|
||||
Console.WriteLine("FocalLength : " + image.ImageTag.FocalLength);
|
||||
Console.WriteLine("FocalLength35mm : " + image.ImageTag.FocalLengthIn35mmFilm);
|
||||
Console.WriteLine("Make : " + image.ImageTag.Make);
|
||||
Console.WriteLine("Model : " + image.ImageTag.Model);
|
||||
|
||||
if (image.Properties != null) {
|
||||
Console.WriteLine("Width : " + image.Properties.PhotoWidth);
|
||||
Console.WriteLine("Height : " + image.Properties.PhotoHeight);
|
||||
Console.WriteLine("Type : " + image.Properties.Description);
|
||||
}
|
||||
|
||||
Console.WriteLine ();
|
||||
Console.WriteLine("Writable? : " + image.Writeable.ToString ());
|
||||
Console.WriteLine("Corrupt? : " + image.PossiblyCorrupt.ToString ());
|
||||
|
||||
if (image.PossiblyCorrupt) {
|
||||
foreach (string reason in image.CorruptionReasons) {
|
||||
Console.WriteLine (" * " + reason);
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine ("---------------------------------------");
|
||||
}
|
||||
}
|
||||
@@ -1,136 +0,0 @@
|
||||
import TagLib from "taglib-sharp.dll"
|
||||
import Gnome.Vfs from "gnome-vfs-sharp"
|
||||
import System
|
||||
import System.IO
|
||||
|
||||
def ReadFromUri(argv as (string)):
|
||||
|
||||
if len(argv) < 1:
|
||||
print "Usage: booi ReadFromUri.boo PATH [...]"
|
||||
return
|
||||
|
||||
Vfs.Initialize()
|
||||
|
||||
TagLib.File.SetFileAbstractionCreator(TagLib.File.FileAbstractionCreator(CreateFile))
|
||||
|
||||
start = DateTime.Now
|
||||
songs_read = 0
|
||||
|
||||
try:
|
||||
for path as string in argv:
|
||||
print path
|
||||
|
||||
file_info as System.IO.FileInfo = System.IO.FileInfo(path)
|
||||
uri as string = Gnome.Vfs.Uri.GetUriFromLocalPath (file_info.FullName)
|
||||
file as TagLib.File = null
|
||||
|
||||
try:
|
||||
file = TagLib.File.Create(uri)
|
||||
except UnsupportedFormatException:
|
||||
print "UNSUPPORTED FILE: ${path}"
|
||||
print string.Empty
|
||||
print "---------------------------------------"
|
||||
print string.Empty
|
||||
continue
|
||||
|
||||
print "Title: ${file.Tag.Title}"
|
||||
|
||||
if file.Tag.AlbumArtists is null:
|
||||
print "Artists:"
|
||||
else:
|
||||
print "Artists: ${string.Join ('\n ', file.Tag.AlbumArtists)}"
|
||||
|
||||
if file.Tag.Performers is null:
|
||||
print 'Performers:'
|
||||
else:
|
||||
print "Performers: ${string.Join ('\n ', file.Tag.Performers)}"
|
||||
|
||||
if file.Tag.Composers is null:
|
||||
print 'Composers:'
|
||||
else:
|
||||
print "Composers: ${string.Join ('\n ', file.Tag.Composers)}"
|
||||
|
||||
print "Album: ${file.Tag.Album}"
|
||||
print "Comment: ${file.Tag.Comment}"
|
||||
|
||||
if file.Tag.Genres is null:
|
||||
print 'Genres:'
|
||||
else:
|
||||
print "Genres: ${string.Join ('\n ', file.Tag.Genres)}"
|
||||
|
||||
print "Year: ${file.Tag.Year}"
|
||||
print "Track: ${file.Tag.Track}"
|
||||
print "TrackCount: ${file.Tag.TrackCount}"
|
||||
print "Disc: ${file.Tag.Disc}"
|
||||
print "DiscCount: ${file.Tag.DiscCount}"
|
||||
print "Lyrics:\n${file.Tag.Lyrics}"
|
||||
print string.Empty
|
||||
|
||||
print "Media Types: ${file.Properties.MediaTypes}"
|
||||
print string.Empty
|
||||
|
||||
for codec as ICodec in file.Properties.Codecs:
|
||||
|
||||
if codec.MediaTypes & MediaTypes.Audio:
|
||||
print "Audio Properties : ${(codec as IAudioCodec).Description}"
|
||||
print "Bitrate: ${(codec as IAudioCodec).AudioBitrate}"
|
||||
print "SampleRate: ${(codec as IAudioCodec).AudioSampleRate}"
|
||||
print "Channels: ${(codec as IAudioCodec).AudioChannels}"
|
||||
print string.Empty
|
||||
|
||||
if codec.MediaTypes & MediaTypes.Video:
|
||||
print "Video Properties : ${(codec as IVideoCodec).Description}"
|
||||
print "Width: ${(codec as IVideoCodec).VideoWidth}"
|
||||
print "Height: ${(codec as IVideoCodec).VideoHeight}"
|
||||
print string.Empty
|
||||
|
||||
if file.Properties.MediaTypes:
|
||||
print "Length: ${file.Properties.Duration}"
|
||||
print string.Empty
|
||||
|
||||
print "Embedded Pictures: ${file.Tag.Pictures.Length}"
|
||||
|
||||
for picture in file.Tag.Pictures:
|
||||
print picture.Description
|
||||
print " MimeType: ${picture.MimeType}"
|
||||
print " Size: ${picture.Data.Count}"
|
||||
print " Type: ${picture.Type}"
|
||||
|
||||
print ""
|
||||
print "---------------------------------------"
|
||||
print ""
|
||||
|
||||
songs_read = songs_read + 1
|
||||
|
||||
ensure:
|
||||
Vfs.Shutdown()
|
||||
|
||||
end as DateTime = DateTime.Now;
|
||||
|
||||
print "Total running time: ${end - start}"
|
||||
print "Total files read: ${songs_read}"
|
||||
print "Average time per file: ${TimeSpan ((end - start).Ticks / songs_read)}"
|
||||
|
||||
class VfsFileAbstraction(TagLib.File.IFileAbstraction):
|
||||
|
||||
_name as string
|
||||
|
||||
def constructor(file as string):
|
||||
_name = file
|
||||
|
||||
Name:
|
||||
get:
|
||||
return _name
|
||||
|
||||
ReadStream:
|
||||
get:
|
||||
return VfsStream(_name, FileMode.Open)
|
||||
|
||||
WriteStream:
|
||||
get:
|
||||
return VfsStream(_name, FileMode.Open)
|
||||
|
||||
def CreateFile(path):
|
||||
return VfsFileAbstraction(path)
|
||||
|
||||
ReadFromUri(argv)
|
||||
@@ -1,171 +0,0 @@
|
||||
using System;
|
||||
using TagLib;
|
||||
using Gnome.Vfs;
|
||||
|
||||
public class ReadFromUri
|
||||
{
|
||||
public static void Write (string name, object value)
|
||||
{
|
||||
Console.WriteLine ("{0,20}: {1}",
|
||||
name, value == null ? "" : value
|
||||
);
|
||||
}
|
||||
|
||||
public static void Write (string name, string [] values)
|
||||
{
|
||||
Console.WriteLine ("{0,20}: {1}",
|
||||
name,
|
||||
values == null ? "" : String.Join ("\n ", values)
|
||||
);
|
||||
}
|
||||
|
||||
public static void Main(string [] args)
|
||||
{
|
||||
if(args.Length == 0) {
|
||||
Console.Error.WriteLine("USAGE: mono ReadFromUri.exe PATH [...]");
|
||||
return;
|
||||
}
|
||||
|
||||
Gnome.Vfs.Vfs.Initialize();
|
||||
|
||||
DateTime start = DateTime.Now;
|
||||
int songs_read = 0;
|
||||
try {
|
||||
foreach (string path in args)
|
||||
{
|
||||
string uri = path;
|
||||
Console.WriteLine (uri);
|
||||
TagLib.File file = null;
|
||||
|
||||
try {
|
||||
System.IO.FileInfo file_info = new System.IO.FileInfo(uri);
|
||||
uri = Gnome.Vfs.Uri.GetUriFromLocalPath (file_info.FullName);
|
||||
} catch {
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
file = TagLib.File.Create(new VfsFileAbstraction (uri));
|
||||
}
|
||||
catch (TagLib.UnsupportedFormatException)
|
||||
{
|
||||
Console.WriteLine ("UNSUPPORTED FILE: " + uri);
|
||||
Console.WriteLine (String.Empty);
|
||||
Console.WriteLine ("---------------------------------------");
|
||||
Console.WriteLine (String.Empty);
|
||||
continue;
|
||||
}
|
||||
|
||||
Console.WriteLine("Tags on disk: " + file.TagTypesOnDisk);
|
||||
Console.WriteLine("Tags in object: " + file.TagTypes);
|
||||
Console.WriteLine (String.Empty);
|
||||
|
||||
Write ("Grouping", file.Tag.Grouping);
|
||||
Write ("Title", file.Tag.Title);
|
||||
Write ("TitleSort", file.Tag.TitleSort);
|
||||
Write ("Album Artists", file.Tag.AlbumArtists);
|
||||
Write ("Album Artists Sort", file.Tag.AlbumArtistsSort);
|
||||
Write ("Performers", file.Tag.Performers);
|
||||
Write ("Performers Sort", file.Tag.PerformersSort);
|
||||
Write ("Composers", file.Tag.Composers);
|
||||
Write ("Composers Sort", file.Tag.ComposersSort);
|
||||
Write ("Conductor", file.Tag.Conductor);
|
||||
Write ("Album", file.Tag.Album);
|
||||
Write ("Album Sort", file.Tag.AlbumSort);
|
||||
Write ("Comment", file.Tag.Comment);
|
||||
Write ("Copyright", file.Tag.Copyright);
|
||||
Write ("Genres", file.Tag.Genres);
|
||||
Write ("BPM", file.Tag.BeatsPerMinute);
|
||||
Write ("Year", file.Tag.Year);
|
||||
Write ("Track", file.Tag.Track);
|
||||
Write ("TrackCount", file.Tag.TrackCount);
|
||||
Write ("Disc", file.Tag.Disc);
|
||||
Write ("DiscCount", file.Tag.DiscCount);
|
||||
|
||||
Console.WriteLine("Lyrics:\n" + file.Tag.Lyrics + "\n");
|
||||
|
||||
Console.WriteLine("Media Types: " + file.Properties.MediaTypes + "\n");
|
||||
|
||||
foreach (TagLib.ICodec codec in file.Properties.Codecs)
|
||||
{
|
||||
TagLib.IAudioCodec acodec = codec as TagLib.IAudioCodec;
|
||||
TagLib.IVideoCodec vcodec = codec as TagLib.IVideoCodec;
|
||||
|
||||
if (acodec != null && (acodec.MediaTypes & TagLib.MediaTypes.Audio) != TagLib.MediaTypes.None)
|
||||
{
|
||||
Console.WriteLine("Audio Properties : " + acodec.Description);
|
||||
Console.WriteLine("Bitrate: " + acodec.AudioBitrate);
|
||||
Console.WriteLine("SampleRate: " + acodec.AudioSampleRate);
|
||||
Console.WriteLine("Channels: " + acodec.AudioChannels + "\n");
|
||||
}
|
||||
|
||||
if (vcodec != null && (vcodec.MediaTypes & TagLib.MediaTypes.Video) != TagLib.MediaTypes.None)
|
||||
{
|
||||
Console.WriteLine("Video Properties : " + vcodec.Description);
|
||||
Console.WriteLine("Width: " + vcodec.VideoWidth);
|
||||
Console.WriteLine("Height: " + vcodec.VideoHeight + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (file.Properties.MediaTypes != TagLib.MediaTypes.None)
|
||||
Console.WriteLine("Length: " + file.Properties.Duration + "\n");
|
||||
|
||||
IPicture [] pictures = file.Tag.Pictures;
|
||||
|
||||
Console.WriteLine("Embedded Pictures: " + pictures.Length);
|
||||
|
||||
foreach(IPicture picture in pictures) {
|
||||
Console.WriteLine(picture.Description);
|
||||
Console.WriteLine(" MimeType: " + picture.MimeType);
|
||||
Console.WriteLine(" Size: " + picture.Data.Count);
|
||||
Console.WriteLine(" Type: " + picture.Type);
|
||||
}
|
||||
|
||||
Console.WriteLine (String.Empty);
|
||||
Console.WriteLine ("---------------------------------------");
|
||||
Console.WriteLine (String.Empty);
|
||||
|
||||
songs_read ++;
|
||||
}
|
||||
} finally {
|
||||
Gnome.Vfs.Vfs.Shutdown();
|
||||
}
|
||||
|
||||
DateTime end = DateTime.Now;
|
||||
|
||||
Console.WriteLine ("Total running time: " + (end - start));
|
||||
Console.WriteLine ("Total files read: " + songs_read);
|
||||
|
||||
if (songs_read > 0)
|
||||
{
|
||||
Console.WriteLine ("Average time per file: " + new TimeSpan ((end - start).Ticks / songs_read));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class VfsFileAbstraction : TagLib.File.IFileAbstraction
|
||||
{
|
||||
private string name;
|
||||
|
||||
public VfsFileAbstraction(string file)
|
||||
{
|
||||
name = file;
|
||||
}
|
||||
|
||||
public string Name {
|
||||
get { return name; }
|
||||
}
|
||||
|
||||
public System.IO.Stream ReadStream {
|
||||
get { return new VfsStream(Name, System.IO.FileMode.Open); }
|
||||
}
|
||||
|
||||
public System.IO.Stream WriteStream {
|
||||
get { return new VfsStream(Name, System.IO.FileMode.Open); }
|
||||
}
|
||||
|
||||
public void CloseStream (System.IO.Stream stream)
|
||||
{
|
||||
stream.Close ();
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="3.5" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>9.0.21022</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{AB35577D-31CB-4848-AC41-13F00A5171A6}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>ReadFromUri</RootNamespace>
|
||||
<AssemblyName>ReadFromUri</AssemblyName>
|
||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>.</OutputPath>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Commandlineparameters>../tests/samples/sample.ogg</Commandlineparameters>
|
||||
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
|
||||
<Execution>
|
||||
<Execution clr-version="Net_2_0" />
|
||||
</Execution>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>none</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>.</OutputPath>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Commandlineparameters>../tests/samples/sample_v2_only.mp3</Commandlineparameters>
|
||||
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
|
||||
<Execution>
|
||||
<Execution clr-version="Net_2_0" />
|
||||
</Execution>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ReadFromUri.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\src\taglib-sharp.csproj">
|
||||
<Project>{6B143A39-C7B2-4743-9917-92262C60E9A6}</Project>
|
||||
<Name>taglib-sharp</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="gnome-vfs-sharp, Version=2.8.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
@@ -1,28 +0,0 @@
|
||||
using System;
|
||||
using TagLib;
|
||||
|
||||
public class SetPictures
|
||||
{
|
||||
public static void Main(string [] args)
|
||||
{
|
||||
if(args.Length < 2) {
|
||||
Console.Error.WriteLine("USAGE: mono SetPictures.exe AUDIO_PATH IMAGE_PATH_1[...IMAGE_PATH_N]");
|
||||
return;
|
||||
}
|
||||
|
||||
TagLib.File file = TagLib.File.Create(args[0]);
|
||||
Console.WriteLine("Current picture count: " + file.Tag.Pictures.Length);
|
||||
|
||||
Picture [] pictures = new Picture[args.Length - 1];
|
||||
|
||||
for(int i = 1; i < args.Length; i++) {
|
||||
Picture picture = new Picture(args[i]);
|
||||
pictures[i - 1] = picture;
|
||||
}
|
||||
|
||||
file.Tag.Pictures = pictures;
|
||||
file.Save();
|
||||
|
||||
Console.WriteLine("New picture count: " + file.Tag.Pictures.Length);
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="3.5" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>9.0.21022</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{0C4645BE-7413-43FC-8856-1ECF1A790FF8}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>SetPictures</RootNamespace>
|
||||
<AssemblyName>SetPictures</AssemblyName>
|
||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>.</OutputPath>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Commandlineparameters>../tests/samples/sample_v2_only.mp3 covers/sample_a.png covers/sample_b.jpg</Commandlineparameters>
|
||||
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
|
||||
<Execution>
|
||||
<Execution clr-version="Net_2_0" />
|
||||
</Execution>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>none</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>.</OutputPath>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Commandlineparameters>../tests/samples/sample_v2_only.mp3 covers/sample_a.png covers/sample_b.jpg</Commandlineparameters>
|
||||
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
|
||||
<Execution>
|
||||
<Execution clr-version="Net_2_0" />
|
||||
</Execution>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="SetPictures.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\src\taglib-sharp.csproj">
|
||||
<Project>{6B143A39-C7B2-4743-9917-92262C60E9A6}</Project>
|
||||
<Name>taglib-sharp</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
@@ -1,117 +0,0 @@
|
||||
|
||||
using System;
|
||||
using TagLib;
|
||||
|
||||
public class StripImageData
|
||||
{
|
||||
private static byte[] image_data = new byte[] {
|
||||
0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x01, 0x00,
|
||||
0x02, 0x11, 0x03, 0x11, 0x00, 0x3F, 0x00,
|
||||
0x8C, 0x80, 0x07, 0xFF, 0xD9
|
||||
};
|
||||
|
||||
public static void Main (string [] args)
|
||||
{
|
||||
if (args.Length != 1) {
|
||||
Console.Out.WriteLine ("usage: mono StripImageData.exe [jpegfile]");
|
||||
return;
|
||||
}
|
||||
|
||||
ImageFile file = new ImageFile (args [0]);
|
||||
|
||||
file.Mode = File.AccessMode.Write;
|
||||
|
||||
long greatest_segment_position = 0;
|
||||
long greatest_segment_length = 0;
|
||||
|
||||
// collect data segments
|
||||
while (true) {
|
||||
|
||||
long sos = file.Find (new byte [] {0xFF, 0xDA}, file.Tell);
|
||||
|
||||
if (sos == -1)
|
||||
break;
|
||||
|
||||
file.Seek (sos);
|
||||
|
||||
long segment_length = SkipDataSegment (file);
|
||||
|
||||
if (segment_length > greatest_segment_length) {
|
||||
greatest_segment_length = segment_length;
|
||||
greatest_segment_position = sos;
|
||||
}
|
||||
}
|
||||
|
||||
if (greatest_segment_length == 0)
|
||||
{
|
||||
Console.Out.WriteLine ("doesn't look like an jpeg file");
|
||||
return;
|
||||
}
|
||||
|
||||
System.Console.WriteLine ("Stripping data segment at {0}", greatest_segment_position);
|
||||
|
||||
file.RemoveBlock (greatest_segment_position, greatest_segment_length);
|
||||
file.Seek (greatest_segment_position);
|
||||
file.WriteBlock (image_data);
|
||||
file.Mode = File.AccessMode.Closed;
|
||||
}
|
||||
|
||||
private static long SkipDataSegment (ImageFile file)
|
||||
{
|
||||
long position = file.Tell;
|
||||
|
||||
// skip sos maker
|
||||
if (file.ReadBlock (2).ToUInt () != 0xFFDA)
|
||||
throw new Exception (String.Format ("Not a data segment at position: {0}", position));
|
||||
|
||||
while (true) {
|
||||
if (0xFF == (byte) file.ReadBlock (1)[0]) {
|
||||
byte maker = (byte) file.ReadBlock (1)[0];
|
||||
|
||||
if (maker != 0x00 && (maker <= 0xD0 || maker >= 0xD7))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
long length = file.Tell - position - 2;
|
||||
|
||||
System.Console.WriteLine ("Data segment of length {0} found at {1}", length, position);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
private class ImageFile : File {
|
||||
|
||||
// Hacky implementation to make use of some methods defined in TagLib.File
|
||||
|
||||
public ImageFile (string path)
|
||||
: base (new File.LocalFileAbstraction (path)) {}
|
||||
|
||||
public override Tag GetTag (TagLib.TagTypes type, bool create)
|
||||
{
|
||||
throw new System.NotImplementedException ();
|
||||
}
|
||||
|
||||
public override Properties Properties {
|
||||
get {
|
||||
throw new System.NotImplementedException ();
|
||||
}
|
||||
}
|
||||
|
||||
public override void RemoveTags (TagLib.TagTypes types)
|
||||
{
|
||||
throw new System.NotImplementedException ();
|
||||
}
|
||||
|
||||
public override void Save ()
|
||||
{
|
||||
throw new System.NotImplementedException ();
|
||||
}
|
||||
|
||||
public override Tag Tag {
|
||||
get {
|
||||
throw new System.NotImplementedException ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 14 KiB |
@@ -1,41 +0,0 @@
|
||||
#include <exiv2/image.hpp>
|
||||
#include <exiv2/exif.hpp>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <cassert>
|
||||
|
||||
int main(int argc, char* const argv[])
|
||||
|
||||
try {
|
||||
if (argc != 3) {
|
||||
std::cout << "Usage: " << argv[0] << " file key\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(argv[1]);
|
||||
assert(image.get() != 0);
|
||||
image->readMetadata();
|
||||
|
||||
try {
|
||||
Exiv2::ExifData &exifData = image->exifData();
|
||||
const Exiv2::Value &value = exifData[argv[2]].value();
|
||||
std::cout << value;
|
||||
} catch (Exiv2::AnyError &e) {}
|
||||
|
||||
try {
|
||||
Exiv2::IptcData &iptcData = image->iptcData();
|
||||
const Exiv2::Value &value = iptcData[argv[2]].value();
|
||||
std::cout << value;
|
||||
} catch (Exiv2::AnyError &e) {}
|
||||
|
||||
try {
|
||||
Exiv2::XmpData &xmpData = image->xmpData();
|
||||
const Exiv2::Value &value = xmpData[argv[2]].value();
|
||||
std::cout << value;
|
||||
} catch (Exiv2::AnyError &e) {}
|
||||
|
||||
return 0;
|
||||
} catch (Exiv2::AnyError& e) {
|
||||
std::cout << "Caught Exiv2 exception '" << e << "'\n";
|
||||
return -1;
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
#include <exiv2/image.hpp>
|
||||
#include <exiv2/exif.hpp>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <cassert>
|
||||
|
||||
int main(int argc, char* const argv[])
|
||||
|
||||
try {
|
||||
if (argc != 3) {
|
||||
std::cout << "Usage: " << argv[0] << " mode file\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(argv[2]);
|
||||
assert(image.get() != 0);
|
||||
image->readMetadata();
|
||||
|
||||
if (argv[1][0] == 'e') {
|
||||
Exiv2::ExifData &exifData = image->exifData();
|
||||
if (!exifData.empty()) {
|
||||
Exiv2::ExifData::const_iterator exifEnd = exifData.end();
|
||||
for (Exiv2::ExifData::const_iterator i = exifData.begin(); i != exifEnd; ++i) {
|
||||
std::cout << i->tagName() << "\t"
|
||||
<< "0x" << std::setw(4) << std::setfill('0') << std::right
|
||||
<< std::hex << i->tag() << std::dec << "\t"
|
||||
<< i->groupName() << "\t"
|
||||
<< i->typeName() << "\t"
|
||||
<< i->count() << "\t"
|
||||
<< "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (argv[1][0] == 'i') {
|
||||
Exiv2::IptcData &iptcData = image->iptcData();
|
||||
if (!iptcData.empty()) {
|
||||
Exiv2::IptcData::const_iterator iptcEnd = iptcData.end();
|
||||
for (Exiv2::IptcData::const_iterator i = iptcData.begin(); i != iptcEnd; ++i) {
|
||||
std::cout << i->key() << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (argv[1][0] == 'x') {
|
||||
Exiv2::XmpData &xmpData = image->xmpData();
|
||||
if (!xmpData.empty()) {
|
||||
Exiv2::XmpData::const_iterator xmpEnd = xmpData.end();
|
||||
for (Exiv2::XmpData::const_iterator i = xmpData.begin(); i != xmpEnd; ++i) {
|
||||
std::cout << i->key() << "\t"
|
||||
<< i->typeName() << "\t"
|
||||
<< i->count() << "\t"
|
||||
<< "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
} catch (Exiv2::AnyError& e) {
|
||||
std::cout << "Caught Exiv2 exception '" << e << "'\n";
|
||||
return -1;
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
//
|
||||
// AssemblyInfo.cs.in: Contains flags to use for the assembly.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
//
|
||||
// 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.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
[assembly:AssemblyVersion("2.0.4.0")]
|
||||
[assembly:AssemblyTitle ("TagLib#")]
|
||||
[assembly:AssemblyDescription ("A library for reading and writing audio metatags.")]
|
||||
[assembly:AssemblyCopyright ("Copyright (c) 2006-2007 Brian Nickel. Copyright (c) 2009-2010 Other contributors")]
|
||||
[assembly:AssemblyCompany ("")]
|
||||
[assembly:AssemblyDelaySign(false)]
|
||||
[assembly:CLSCompliant(false)]
|
||||
[assembly: ComVisibleAttribute(false)]
|
||||
@@ -1,36 +0,0 @@
|
||||
//
|
||||
// AssemblyInfo.cs.in: Contains flags to use for the assembly.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
//
|
||||
// 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.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
[assembly:AssemblyVersion("@ASSEMBLY_VERSION@")]
|
||||
[assembly:AssemblyTitle ("TagLib#")]
|
||||
[assembly:AssemblyDescription ("A library for reading and writing audio metatags.")]
|
||||
[assembly:AssemblyCopyright ("Copyright (c) 2006-2007 Brian Nickel. Copyright (c) 2009-2010 Other contributors")]
|
||||
[assembly:AssemblyCompany ("")]
|
||||
[assembly:AssemblyDelaySign(false)]
|
||||
[assembly:AssemblyKeyFile("taglib-sharp.snk")]
|
||||
[assembly:CLSCompliant(false)]
|
||||
@@ -1,69 +0,0 @@
|
||||
POLICIES = policy.2.0.$(ASSEMBLY_NAME).dll
|
||||
ASSEMBLY = $(ASSEMBLY_NAME).dll
|
||||
TARGET = $(ASSEMBLY)
|
||||
|
||||
if BUILD_DOCS
|
||||
DOCFILE = $(ASSEMBLY).xml
|
||||
DOCFLAGS = /doc:$(DOCFILE) /warn:4
|
||||
else
|
||||
DOCFILE =
|
||||
DOCFLAGS =
|
||||
endif
|
||||
|
||||
if HAVE_SHARPZIPLIB
|
||||
SHARPZIPLIB_FLAGS = -r:ICSharpCode.SharpZipLib.dll -define:HAVE_SHARPZIPLIB
|
||||
endif
|
||||
|
||||
CSC = $(MCS) $(MCS_FLAGS) $(CSFLAGS)
|
||||
|
||||
include $(srcdir)/TagLib/TagLib.sources
|
||||
|
||||
taglib-sharp.snk: $(top_srcdir)/taglib-sharp.snk
|
||||
cp $(top_srcdir)/taglib-sharp.snk .
|
||||
|
||||
taglib_sources_in = AssemblyInfo.cs.in
|
||||
taglib_generated_sources = $(taglib_sources_in:.in=)
|
||||
taglib_policy_names = $(POLICIES:.dll=)
|
||||
taglib_policy_configs = $(POLICIES:.dll=.config)
|
||||
taglib_policy_configs_in = $(POLICIES:.dll=.config.in)
|
||||
|
||||
$(ASSEMBLY): $(TAGLIB_CSFILES) $(taglib_generated_sources) taglib-sharp.snk
|
||||
$(CSC) /target:library $(LIBFLAGS) $(SHARPZIPLIB_FLAGS) $(DOCFLAGS) /define:SIGN /out:$@ $(TAGLIB_CSFILES) $(taglib_generated_sources)
|
||||
|
||||
policy.%.$(ASSEMBLY_NAME).dll: policy.%.$(ASSEMBLY_NAME).config
|
||||
$(AL) /link:$< /out:$@ /keyfile:taglib-sharp.snk
|
||||
|
||||
all: $(ASSEMBLY) $(POLICIES)
|
||||
|
||||
EXTRA_DIST = $(TAGLIB_CSFILES) $(taglib_sources_in) $(taglib_policy_configs_in) taglib-sharp.csproj
|
||||
DISTCLEANFILES = *.pidb
|
||||
CLEANFILES = $(ASSEMBLY) $(ASSEMBLY).mdb $(POLICIES) taglib-sharp.snk $(DOCFILE)
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
|
||||
install-data-local:
|
||||
@if test -n '$(TARGET)'; then \
|
||||
echo "$(GACUTIL) /i $(ASSEMBLY) /f $(GACUTIL_FLAGS)"; \
|
||||
$(GACUTIL) /i $(ASSEMBLY) /f $(GACUTIL_FLAGS) || exit 1; \
|
||||
for POLICY in $(POLICIES); \
|
||||
do echo "$(GACUTIL) /i $$POLICY /f $(GACUTIL_POLICY_FLAGS)"; \
|
||||
$(GACUTIL) /i $$POLICY /f $(GACUTIL_POLICY_FLAGS) || exit 1; \
|
||||
done \
|
||||
fi
|
||||
|
||||
uninstall-local:
|
||||
@if test -n '$(TARGET)'; then \
|
||||
echo "$(GACUTIL) /u $(ASSEMBLY_NAME) $(GACUTIL_FLAGS)"; \
|
||||
$(GACUTIL) /u $(ASSEMBLY_NAME) $(GACUTIL_FLAGS) || exit 1; \
|
||||
for POLICY in $(taglib_policy_names); \
|
||||
do echo "$(GACUTIL) /u $$POLICY /f $(GACUTIL_POLICY_FLAGS)"; \
|
||||
$(GACUTIL) /u $$POLICY /f $(GACUTIL_POLICY_FLAGS) || exit 1; \
|
||||
done \
|
||||
fi
|
||||
|
||||
distwin:
|
||||
mkdir -p $(srcdir)/../$(WINDIR)/Libraries
|
||||
cp $(srcdir)/*.dll $(srcdir)/*.config $(srcdir)/../$(WINDIR)/Libraries
|
||||
for FILE in $(TAGLIB_CSFILES) $(taglib_generated_sources); \
|
||||
do mkdir -p $(srcdir)/../$(WINDIR)/src/`dirname $$FILE`; \
|
||||
cp $$FILE $(srcdir)/../$(WINDIR)/src/`dirname $$FILE`; \
|
||||
done
|
||||
@@ -1,449 +0,0 @@
|
||||
//
|
||||
// AudioHeader.cs: Provides information about an ADTS AAC audio stream.
|
||||
//
|
||||
// Copyright (C) 2009 Patrick Dehne
|
||||
//
|
||||
// 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.Aac
|
||||
{
|
||||
/// <summary>
|
||||
/// This structure implements <see cref="IAudioCodec" /> and provides
|
||||
/// information about an ADTS AAC audio stream.
|
||||
/// </summary>
|
||||
public class AudioHeader : IAudioCodec
|
||||
{
|
||||
#region Private Static Value Arrays
|
||||
|
||||
/// <summary>
|
||||
/// Contains a sample rate table for ADTS AAC audio.
|
||||
/// </summary>
|
||||
private static readonly int[] sample_rates = new int[13] {
|
||||
96000, 88200, 64000, 48000, 44100, 32000,
|
||||
24000, 22050, 16000, 12000, 11025, 8000, 7350
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Contains a channel table for ADTS AAC audio.
|
||||
/// </summary>
|
||||
private static readonly int[] channels = new int[8] {
|
||||
0, 1, 2, 3, 4, 5, 6, 8
|
||||
};
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Private Properties
|
||||
|
||||
/// <summary>
|
||||
/// Contains the audio stream length.
|
||||
/// </summary>
|
||||
private long stream_length;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the audio stream duration.
|
||||
/// </summary>
|
||||
private TimeSpan duration;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the number of channels in the audio
|
||||
/// </summary>
|
||||
private int audiochannels;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the bitrate of the audio stream
|
||||
/// </summary>
|
||||
private int audiobitrate;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the samplerate of the audio stream
|
||||
/// </summary>
|
||||
private int audiosamplerate;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Fields
|
||||
|
||||
/// <summary>
|
||||
/// An empty and unset header.
|
||||
/// </summary>
|
||||
public static readonly AudioHeader Unknown =
|
||||
new AudioHeader();
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new empty instance of <see
|
||||
/// cref="AudioHeader" />
|
||||
/// </summary>
|
||||
private AudioHeader()
|
||||
{
|
||||
this.stream_length = 0;
|
||||
this.duration = TimeSpan.Zero;
|
||||
this.audiochannels = 0;
|
||||
this.audiobitrate = 0;
|
||||
this.audiosamplerate = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="AudioHeader" /> by populating it with specified
|
||||
/// values.
|
||||
/// </summary>
|
||||
/// <param name="channels">
|
||||
/// A <see cref="int" /> value indicating the number
|
||||
/// of channels in the audio stream
|
||||
/// </param>
|
||||
/// <param name="bitrate">
|
||||
/// A <see cref="int" /> value indicating the bitrate
|
||||
/// of the audio stream
|
||||
/// </param>
|
||||
/// <param name="samplerate">
|
||||
/// A <see cref="int" /> value indicating the samplerate
|
||||
/// of the audio stream
|
||||
/// </param>
|
||||
/// <param name="numberofsamples">
|
||||
/// A <see cref="int" /> value indicating the number
|
||||
/// of samples in the audio stream
|
||||
/// </param>
|
||||
/// <param name="numberofframes">
|
||||
/// A <see cref="int" /> value indicating the number
|
||||
/// of frames in the audio stream
|
||||
/// </param>
|
||||
private AudioHeader(int channels, int bitrate,
|
||||
int samplerate, int numberofsamples, int numberofframes)
|
||||
{
|
||||
this.duration = TimeSpan.Zero;
|
||||
this.stream_length = 0;
|
||||
this.audiochannels = channels;
|
||||
this.audiobitrate = bitrate;
|
||||
this.audiosamplerate = samplerate;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets a text description of the media represented by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="string" /> object containing a description
|
||||
/// of the media represented by the current instance.
|
||||
/// </value>
|
||||
public string Description
|
||||
{
|
||||
get
|
||||
{
|
||||
return "ADTS AAC";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the types of media represented by the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Always <see cref="MediaTypes.Audio" />.
|
||||
/// </value>
|
||||
public MediaTypes MediaTypes
|
||||
{
|
||||
get { return MediaTypes.Audio; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the duration of the media represented by the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="TimeSpan" /> containing the duration of the
|
||||
/// media represented by the current instance.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// If <see cref="SetStreamLength" /> has not been called, this
|
||||
/// value will not be correct.
|
||||
/// </remarks>
|
||||
public TimeSpan Duration
|
||||
{
|
||||
get
|
||||
{
|
||||
return duration;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the bitrate of the audio represented by the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing a bitrate of the
|
||||
/// audio represented by the current instance.
|
||||
/// </value>
|
||||
public int AudioBitrate
|
||||
{
|
||||
get
|
||||
{
|
||||
return audiobitrate;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the sample count of the audio represented by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing the sample count
|
||||
/// of the audio represented by the current instance.
|
||||
/// </value>
|
||||
public long AudioSampleCount
|
||||
{
|
||||
get
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the sample rate of the audio represented by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing the sample rate of
|
||||
/// the audio represented by the current instance.
|
||||
/// </value>
|
||||
public int AudioSampleRate
|
||||
{
|
||||
get
|
||||
{
|
||||
return audiosamplerate;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of channels in the audio represented by
|
||||
/// the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing the number of
|
||||
/// channels in the audio represented by the current
|
||||
/// instance.
|
||||
/// </value>
|
||||
public int AudioChannels
|
||||
{
|
||||
get { return audiochannels; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Sets the length of the audio stream represented by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <param name="streamLength">
|
||||
/// A <see cref="long" /> value specifying the length in
|
||||
/// bytes of the audio stream represented by the current
|
||||
/// instance.
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// The this value has been set, <see cref="Duration" /> will
|
||||
/// return an incorrect value.
|
||||
/// </remarks>
|
||||
public void SetStreamLength(long streamLength)
|
||||
{
|
||||
this.stream_length = streamLength;
|
||||
duration = TimeSpan.FromSeconds(((double)this.stream_length) * 8.0 / ((double)this.audiobitrate));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Static Methods
|
||||
|
||||
/// <summary>
|
||||
/// Searches for an audio header in a <see cref="TagLib.File"
|
||||
/// /> starting at a specified position and searching through
|
||||
/// a specified number of bytes.
|
||||
/// </summary>
|
||||
/// <param name="header">
|
||||
/// A <see cref="AudioHeader" /> object in which the found
|
||||
/// header will be stored.
|
||||
/// </param>
|
||||
/// <param name="file">
|
||||
/// A <see cref="TagLib.File" /> object to search.
|
||||
/// </param>
|
||||
/// <param name="position">
|
||||
/// A <see cref="long" /> value specifying the seek position
|
||||
/// in <paramref name="file" /> at which to start searching.
|
||||
/// </param>
|
||||
/// <param name="length">
|
||||
/// A <see cref="int" /> value specifying the maximum number
|
||||
/// of bytes to search before aborting.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="bool" /> value indicating whether or not a
|
||||
/// header was found.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="file" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public static bool Find(out AudioHeader header,
|
||||
TagLib.File file, long position, int length)
|
||||
{
|
||||
if (file == null)
|
||||
throw new ArgumentNullException("file");
|
||||
|
||||
long end = position + length;
|
||||
header = AudioHeader.Unknown;
|
||||
|
||||
file.Seek(position);
|
||||
|
||||
ByteVector buffer = file.ReadBlock(3);
|
||||
|
||||
if (buffer.Count < 3)
|
||||
return false;
|
||||
|
||||
do
|
||||
{
|
||||
file.Seek(position + 3);
|
||||
buffer = buffer.Mid(buffer.Count - 3);
|
||||
buffer.Add(file.ReadBlock(
|
||||
(int)File.BufferSize));
|
||||
|
||||
for (int i = 0; i < buffer.Count - 3 &&
|
||||
(length < 0 || position + i < end); i++)
|
||||
if (buffer[i] == 0xFF
|
||||
&& buffer[i+1] >= 0xF0) // 0xFFF
|
||||
try
|
||||
{
|
||||
BitStream bits = new BitStream(buffer.Mid(i, 7).Data);
|
||||
|
||||
// 12 bits sync header
|
||||
bits.ReadInt32(12);
|
||||
|
||||
// 1 bit mpeg 2/4
|
||||
bits.ReadInt32(1);
|
||||
|
||||
// 2 bits layer
|
||||
bits.ReadInt32(2);
|
||||
|
||||
// 1 bit protection absent
|
||||
bits.ReadInt32(1);
|
||||
|
||||
// 2 bits profile object type
|
||||
bits.ReadInt32(2);
|
||||
|
||||
// 4 bits sampling frequency index
|
||||
int samplerateindex = bits.ReadInt32(4);
|
||||
if(samplerateindex >= sample_rates.Length)
|
||||
return false;
|
||||
long samplerate = sample_rates[samplerateindex];
|
||||
|
||||
// 1 bit private bit
|
||||
bits.ReadInt32(1);
|
||||
|
||||
// 3 bits channel configuration
|
||||
int channelconfigindex = bits.ReadInt32(3);
|
||||
if (channelconfigindex >= channels.Length)
|
||||
return false;
|
||||
|
||||
// 4 copyright bits
|
||||
bits.ReadInt32(4);
|
||||
|
||||
// 13 bits frame length
|
||||
long framelength = bits.ReadInt32(13); // double check framelength
|
||||
if (framelength < 7)
|
||||
return false;
|
||||
|
||||
// 11 bits buffer fullness
|
||||
bits.ReadInt32(11);
|
||||
|
||||
// 2 bits number of raw data blocks in frame
|
||||
int numberofframes = bits.ReadInt32(2) + 1;
|
||||
|
||||
long numberofsamples = numberofframes * 1024;
|
||||
long bitrate = framelength * 8 * samplerate / numberofsamples;
|
||||
|
||||
header = new AudioHeader(channels[channelconfigindex],
|
||||
(int)bitrate,
|
||||
(int)samplerate,
|
||||
(int)numberofsamples,
|
||||
numberofframes);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (CorruptFileException)
|
||||
{
|
||||
}
|
||||
|
||||
position += File.BufferSize;
|
||||
} while (buffer.Count > 3 && (length < 0 || position < end));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Searches for an audio header in a <see cref="TagLib.File"
|
||||
/// /> starting at a specified position and searching to the
|
||||
/// end of the file.
|
||||
/// </summary>
|
||||
/// <param name="header">
|
||||
/// A <see cref="AudioHeader" /> object in which the found
|
||||
/// header will be stored.
|
||||
/// </param>
|
||||
/// <param name="file">
|
||||
/// A <see cref="TagLib.File" /> object to search.
|
||||
/// </param>
|
||||
/// <param name="position">
|
||||
/// A <see cref="long" /> value specifying the seek position
|
||||
/// in <paramref name="file" /> at which to start searching.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="bool" /> value indicating whether or not a
|
||||
/// header was found.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// Searching to the end of the file can be very, very slow
|
||||
/// especially for corrupt or non-MPEG files. It is
|
||||
/// recommended to use <see
|
||||
/// cref="Find(AudioHeader,TagLib.File,long,int)" />
|
||||
/// instead.
|
||||
/// </remarks>
|
||||
public static bool Find(out AudioHeader header,
|
||||
TagLib.File file, long position)
|
||||
{
|
||||
return Find(out header, file, position, -1);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
//
|
||||
// BitStream.cs: Helper to read bits from a byte array.
|
||||
//
|
||||
// Copyright (C) 2009 Patrick Dehne
|
||||
//
|
||||
// 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.Text;
|
||||
using System.Collections;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace TagLib.Aac
|
||||
{
|
||||
/// <summary>
|
||||
/// This class is used to help reading arbitary number of bits from
|
||||
/// a fixed array of bytes
|
||||
/// </summary>
|
||||
public class BitStream
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
private BitArray bits;
|
||||
private int bitindex;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new <see cref="BitStream"/>.
|
||||
/// </summary>
|
||||
/// <param name="buffer">
|
||||
/// A <see cref="System.Byte[]"/>, must be 7 bytes long.
|
||||
/// </param>
|
||||
public BitStream(byte[] buffer)
|
||||
{
|
||||
Debug.Assert(buffer.Length == 7, "buffer.Length == 7", "buffer size invalid");
|
||||
|
||||
if (buffer.Length != 7)
|
||||
throw new ArgumentException("Buffer size must be 7 bytes");
|
||||
|
||||
// Reverse bits
|
||||
bits = new BitArray(buffer.Length * 8);
|
||||
for (int i = 0; i < buffer.Length; i++)
|
||||
{
|
||||
for (int y = 0; y < 8; y++)
|
||||
{
|
||||
bits[i * 8 + y] = ((buffer[i] & (1 << (7 - y))) > 0);
|
||||
}
|
||||
}
|
||||
|
||||
bitindex = 0;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Reads an Int32 from the bitstream
|
||||
/// </summary>
|
||||
/// <param name="numberOfBits">
|
||||
/// A <see cref="int" /> value containing the number
|
||||
/// of bits to read from the bitstream
|
||||
/// </param>
|
||||
public int ReadInt32(int numberOfBits)
|
||||
{
|
||||
Debug.Assert(numberOfBits > 0, "numberOfBits < 1");
|
||||
Debug.Assert(numberOfBits <= 32, "numberOfBits <= 32");
|
||||
|
||||
if (numberOfBits <= 0)
|
||||
throw new ArgumentException("Number of bits to read must be >= 1");
|
||||
|
||||
if (numberOfBits > 32)
|
||||
throw new ArgumentException("Number of bits to read must be <= 32");
|
||||
|
||||
int value = 0;
|
||||
int start = bitindex + numberOfBits - 1;
|
||||
for (int i = 0; i < numberOfBits; i++)
|
||||
{
|
||||
value += bits[start] ? (1 << i) : 0;
|
||||
bitindex++;
|
||||
start--;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,282 +0,0 @@
|
||||
//
|
||||
// File.cs: Provides tagging and properties support for ADTS AAC files
|
||||
//
|
||||
// Here is the ADTS Header description used for implementation:
|
||||
// http://www.hydrogenaudio.org/forums/lofiversion/index.php/t21617.html
|
||||
//
|
||||
// Copyright (C) 2009 Patrick Dehne
|
||||
//
|
||||
// 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.Text;
|
||||
|
||||
namespace TagLib.Aac
|
||||
{
|
||||
/// <summary>
|
||||
/// This class extends <see cref="TagLib.NonContainer.File" /> to
|
||||
/// provide tagging and properties support for ADTS AAC audio files.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// A <see cref="TagLib.Id3v1.Tag" /> and <see
|
||||
/// cref="TagLib.Id3v2.Tag" /> will be added automatically to any
|
||||
/// file that doesn't contain one. This change does not effect the
|
||||
/// file until it is saved and can be reversed using the following
|
||||
/// method:
|
||||
/// <code>file.RemoveTags (file.TagTypes & ~file.TagTypesOnDisk);</code>
|
||||
/// </remarks>
|
||||
[SupportedMimeType("taglib/aac", "aac")]
|
||||
[SupportedMimeType("audio/aac")]
|
||||
public class File : TagLib.NonContainer.File
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Contains the first audio header.
|
||||
/// </summary>
|
||||
private AudioHeader first_header;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="File" /> for a specified path in the local
|
||||
/// file system and specified read style.
|
||||
/// </summary>
|
||||
/// <param name="path">
|
||||
/// A <see cref="string" /> object containing the path of the
|
||||
/// file to use in the new instance.
|
||||
/// </param>
|
||||
/// <param name="propertiesStyle">
|
||||
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||
/// of accuracy to read the media properties, or <see
|
||||
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="path" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public File (string path, ReadStyle propertiesStyle)
|
||||
: base (path, propertiesStyle)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="File" /> for a specified path in the local
|
||||
/// file system with an average read style.
|
||||
/// </summary>
|
||||
/// <param name="path">
|
||||
/// A <see cref="string" /> object containing the path of the
|
||||
/// file to use in the new instance.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="path" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public File (string path) : base (path)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="File" /> for a specified file abstraction and
|
||||
/// specified read style.
|
||||
/// </summary>
|
||||
/// <param name="abstraction">
|
||||
/// A <see cref="TagLib.File.IFileAbstraction" /> object to use when
|
||||
/// reading from and writing to the file.
|
||||
/// </param>
|
||||
/// <param name="propertiesStyle">
|
||||
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||
/// of accuracy to read the media properties, or <see
|
||||
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="abstraction" /> is <see langword="null"
|
||||
/// />.
|
||||
/// </exception>
|
||||
public File (File.IFileAbstraction abstraction,
|
||||
ReadStyle propertiesStyle)
|
||||
: base (abstraction, propertiesStyle)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="File" /> for a specified file abstraction with
|
||||
/// an average read style.
|
||||
/// </summary>
|
||||
/// <param name="abstraction">
|
||||
/// A <see cref="TagLib.File.IFileAbstraction" /> object to use when
|
||||
/// reading from and writing to the file.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="abstraction" /> is <see langword="null"
|
||||
/// />.
|
||||
/// </exception>
|
||||
public File (File.IFileAbstraction abstraction)
|
||||
: base (abstraction)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Gets a tag of a specified type from the current instance,
|
||||
/// optionally creating a new tag if possible.
|
||||
/// </summary>
|
||||
/// <param name="type">
|
||||
/// A <see cref="TagLib.TagTypes" /> value indicating the
|
||||
/// type of tag to read.
|
||||
/// </param>
|
||||
/// <param name="create">
|
||||
/// A <see cref="bool" /> value specifying whether or not to
|
||||
/// try and create the tag if one is not found.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="Tag" /> object containing the tag that was
|
||||
/// found in or added to the current instance. If no
|
||||
/// matching tag was found and none was created, <see
|
||||
/// langword="null" /> is returned.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// If a <see cref="TagLib.Id3v2.Tag" /> is added to the
|
||||
/// current instance, it will be placed at the start of the
|
||||
/// file. On the other hand, <see cref="TagLib.Id3v1.Tag" />
|
||||
/// <see cref="TagLib.Ape.Tag" /> will be added to the end of
|
||||
/// the file. All other tag types will be ignored.
|
||||
/// </remarks>
|
||||
public override TagLib.Tag GetTag (TagTypes type, bool create)
|
||||
{
|
||||
Tag t = (Tag as TagLib.NonContainer.Tag).GetTag (type);
|
||||
|
||||
if (t != null || !create)
|
||||
return t;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case TagTypes.Id3v1:
|
||||
return EndTag.AddTag (type, Tag);
|
||||
|
||||
case TagTypes.Id3v2:
|
||||
return StartTag.AddTag (type, Tag);
|
||||
|
||||
case TagTypes.Ape:
|
||||
return EndTag.AddTag (type, Tag);
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
/// <summary>
|
||||
/// Reads format specific information at the start of the
|
||||
/// file.
|
||||
/// </summary>
|
||||
/// <param name="start">
|
||||
/// A <see cref="long" /> value containing the seek position
|
||||
/// at which the tags end and the media data begins.
|
||||
/// </param>
|
||||
/// <param name="propertiesStyle">
|
||||
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||
/// of accuracy to read the media properties, or <see
|
||||
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// This method only searches for an audio header in the
|
||||
/// first 16384 bytes of code to avoid searching forever in
|
||||
/// corrupt files.
|
||||
/// </remarks>
|
||||
protected override void ReadStart (long start,
|
||||
ReadStyle propertiesStyle)
|
||||
{
|
||||
// Only check the first 16 bytes so we're not stuck
|
||||
// reading a bad file forever.
|
||||
if (propertiesStyle != ReadStyle.None &&
|
||||
!AudioHeader.Find (out first_header, this,
|
||||
start, 0x4000))
|
||||
throw new CorruptFileException (
|
||||
"ADTS audio header not found.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads format specific information at the end of the
|
||||
/// file.
|
||||
/// </summary>
|
||||
/// <param name="end">
|
||||
/// A <see cref="long" /> value containing the seek position
|
||||
/// at which the media data ends and the tags begin.
|
||||
/// </param>
|
||||
/// <param name="propertiesStyle">
|
||||
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||
/// of accuracy to read the media properties, or <see
|
||||
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||
/// </param>
|
||||
protected override void ReadEnd (long end,
|
||||
ReadStyle propertiesStyle)
|
||||
{
|
||||
// Make sure we have ID3v1 and ID3v2 tags.
|
||||
GetTag (TagTypes.Id3v1, true);
|
||||
GetTag (TagTypes.Id3v2, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the audio properties from the file represented by
|
||||
/// the current instance.
|
||||
/// </summary>
|
||||
/// <param name="start">
|
||||
/// A <see cref="long" /> value containing the seek position
|
||||
/// at which the tags end and the media data begins.
|
||||
/// </param>
|
||||
/// <param name="end">
|
||||
/// A <see cref="long" /> value containing the seek position
|
||||
/// at which the media data ends and the tags begin.
|
||||
/// </param>
|
||||
/// <param name="propertiesStyle">
|
||||
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||
/// of accuracy to read the media properties, or <see
|
||||
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="TagLib.Properties" /> object describing the
|
||||
/// media properties of the file represented by the current
|
||||
/// instance.
|
||||
/// </returns>
|
||||
protected override Properties ReadProperties (long start,
|
||||
long end,
|
||||
ReadStyle propertiesStyle)
|
||||
{
|
||||
first_header.SetStreamLength (end - start);
|
||||
return new Properties (TimeSpan.Zero, first_header);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,481 +0,0 @@
|
||||
//
|
||||
// File.cs: Provides tagging and properties support for Apple's AIFF
|
||||
// files.
|
||||
//
|
||||
// Author:
|
||||
// Helmut Wahrmann
|
||||
//
|
||||
// Copyright (C) 2009 Helmut Wahrmann
|
||||
//
|
||||
// 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 TagLib.Id3v2;
|
||||
|
||||
namespace TagLib.Aiff
|
||||
{
|
||||
/// <summary>
|
||||
/// This class extends <see cref="TagLib.File" /> to provide
|
||||
/// support for reading and writing tags and properties for files
|
||||
/// using the AIFF file format.
|
||||
/// </summary>
|
||||
[SupportedMimeType("taglib/aif", "aif")]
|
||||
[SupportedMimeType("audio/x-aiff")]
|
||||
[SupportedMimeType("audio/aiff")]
|
||||
[SupportedMimeType("sound/aiff")]
|
||||
[SupportedMimeType("application/x-aiff")]
|
||||
public class File : TagLib.File
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Contains the address of the AIFF header block.
|
||||
/// </summary>
|
||||
private ByteVector header_block = null;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the Id3v2 tag.
|
||||
/// </summary>
|
||||
private Id3v2.Tag tag = null;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the media properties.
|
||||
/// </summary>
|
||||
private Properties properties = null;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Static Fields
|
||||
|
||||
/// <summary>
|
||||
/// The identifier used to recognize a AIFF files.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// "FORM"
|
||||
/// </value>
|
||||
public static readonly ReadOnlyByteVector FileIdentifier = "FORM";
|
||||
|
||||
/// <summary>
|
||||
/// The identifier used to recognize a AIFF Common chunk.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// "COMM"
|
||||
/// </value>
|
||||
public static readonly ReadOnlyByteVector CommIdentifier = "COMM";
|
||||
|
||||
/// <summary>
|
||||
/// The identifier used to recognize a AIFF Sound Data Chunk.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// "SSND"
|
||||
/// </value>
|
||||
public static readonly ReadOnlyByteVector SoundIdentifier = "SSND";
|
||||
|
||||
/// <summary>
|
||||
/// The identifier used to recognize a AIFF ID3 chunk.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// "ID3 "
|
||||
/// </value>
|
||||
public static readonly ReadOnlyByteVector ID3Identifier = "ID3 ";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="File" /> for a specified path in the local file
|
||||
/// system and specified read style.
|
||||
/// </summary>
|
||||
/// <param name="path">
|
||||
/// A <see cref="string" /> object containing the path of the
|
||||
/// file to use in the new instance.
|
||||
/// </param>
|
||||
/// <param name="propertiesStyle">
|
||||
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||
/// of accuracy to read the media properties, or <see
|
||||
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="path" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public File(string path, ReadStyle propertiesStyle)
|
||||
: this(new File.LocalFileAbstraction(path),
|
||||
propertiesStyle)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="File" /> for a specified path in the local file
|
||||
/// system with an average read style.
|
||||
/// </summary>
|
||||
/// <param name="path">
|
||||
/// A <see cref="string" /> object containing the path of the
|
||||
/// file to use in the new instance.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="path" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public File(string path)
|
||||
: this(path, ReadStyle.Average)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="File" /> for a specified file abstraction and
|
||||
/// specified read style.
|
||||
/// </summary>
|
||||
/// <param name="abstraction">
|
||||
/// A <see cref="IFileAbstraction" /> object to use when
|
||||
/// reading from and writing to the file.
|
||||
/// </param>
|
||||
/// <param name="propertiesStyle">
|
||||
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||
/// of accuracy to read the media properties, or <see
|
||||
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="abstraction" /> is <see langword="null"
|
||||
/// />.
|
||||
/// </exception>
|
||||
public File(File.IFileAbstraction abstraction,
|
||||
ReadStyle propertiesStyle)
|
||||
: base(abstraction)
|
||||
{
|
||||
Mode = AccessMode.Read;
|
||||
try
|
||||
{
|
||||
uint aiff_size;
|
||||
long tag_start, tag_end;
|
||||
Read(true, propertiesStyle, out aiff_size,
|
||||
out tag_start, out tag_end);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Mode = AccessMode.Closed;
|
||||
}
|
||||
|
||||
TagTypesOnDisk = TagTypes;
|
||||
|
||||
GetTag(TagTypes.Id3v2, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="File" /> for a specified file abstraction with an
|
||||
/// average read style.
|
||||
/// </summary>
|
||||
/// <param name="abstraction">
|
||||
/// A <see cref="IFileAbstraction" /> object to use when
|
||||
/// reading from and writing to the file.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="abstraction" /> is <see langword="null"
|
||||
/// />.
|
||||
/// </exception>
|
||||
public File(File.IFileAbstraction abstraction)
|
||||
: this(abstraction, ReadStyle.Average)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets a abstract representation of all tags stored in the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="TagLib.Tag" /> object representing all tags
|
||||
/// stored in the current instance.
|
||||
/// </value>
|
||||
public override Tag Tag
|
||||
{
|
||||
get { return tag; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the media properties of the file represented by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="TagLib.Properties" /> object containing the
|
||||
/// media properties of the file represented by the current
|
||||
/// instance.
|
||||
/// </value>
|
||||
public override TagLib.Properties Properties
|
||||
{
|
||||
get { return properties; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Saves the changes made in the current instance to the
|
||||
/// file it represents.
|
||||
/// </summary>
|
||||
public override void Save()
|
||||
{
|
||||
Mode = AccessMode.Write;
|
||||
try
|
||||
{
|
||||
ByteVector data = new ByteVector();
|
||||
|
||||
// Add the ID3 chunk and ID32 tag to the vector
|
||||
if (tag != null)
|
||||
{
|
||||
ByteVector tag_data = tag.Render();
|
||||
if (tag_data.Count > 10)
|
||||
{
|
||||
if (tag_data.Count%2 == 1)
|
||||
tag_data.Add(0);
|
||||
|
||||
data.Add("ID3 ");
|
||||
data.Add(ByteVector.FromUInt(
|
||||
(uint) tag_data.Count,
|
||||
true));
|
||||
data.Add(tag_data);
|
||||
}
|
||||
}
|
||||
|
||||
// Read the file to determine the current AIFF
|
||||
// size and the area tagging is in.
|
||||
uint aiff_size;
|
||||
long tag_start, tag_end;
|
||||
Read(false, ReadStyle.None, out aiff_size,
|
||||
out tag_start, out tag_end);
|
||||
|
||||
// If tagging info cannot be found, place it at
|
||||
// the end of the file.
|
||||
if (tag_start < 12 || tag_end < tag_start)
|
||||
tag_start = tag_end = Length;
|
||||
|
||||
int length = (int) (tag_end - tag_start + 8);
|
||||
|
||||
// Insert the tagging data.
|
||||
Insert(data, tag_start, length);
|
||||
|
||||
// If the data size changed update the aiff size.
|
||||
if (data.Count - length != 0 &&
|
||||
tag_start <= aiff_size)
|
||||
{
|
||||
// Depending, if a Tag has been added or removed,
|
||||
// the length needs to be adjusted
|
||||
if (tag == null)
|
||||
{
|
||||
length -= 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
length -= 8;
|
||||
}
|
||||
|
||||
Insert(ByteVector.FromUInt((uint)
|
||||
(aiff_size + data.Count - length),
|
||||
true), 4, 4);
|
||||
}
|
||||
// Update the tag types.
|
||||
TagTypesOnDisk = TagTypes;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Mode = AccessMode.Closed;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a set of tag types from the current instance.
|
||||
/// </summary>
|
||||
/// <param name="types">
|
||||
/// A bitwise combined <see cref="TagLib.TagTypes" /> value
|
||||
/// containing tag types to be removed from the file.
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// In order to remove all tags from a file, pass <see
|
||||
/// cref="TagTypes.AllTags" /> as <paramref name="types" />.
|
||||
/// </remarks>
|
||||
public override void RemoveTags(TagTypes types)
|
||||
{
|
||||
if (types == TagLib.TagTypes.Id3v2 ||
|
||||
types == TagLib.TagTypes.AllTags)
|
||||
{
|
||||
tag = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a tag of a specified type from the current instance,
|
||||
/// optionally creating a new tag if possible.
|
||||
/// </summary>
|
||||
/// <param name="type">
|
||||
/// A <see cref="TagLib.TagTypes" /> value indicating the
|
||||
/// type of tag to read.
|
||||
/// </param>
|
||||
/// <param name="create">
|
||||
/// A <see cref="bool" /> value specifying whether or not to
|
||||
/// try and create the tag if one is not found.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="Tag" /> object containing the tag that was
|
||||
/// found in or added to the current instance. If no
|
||||
/// matching tag was found and none was created, <see
|
||||
/// langword="null" /> is returned.
|
||||
/// </returns>
|
||||
public override TagLib.Tag GetTag(TagTypes type, bool create)
|
||||
{
|
||||
TagLib.Tag id32_tag = null;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case TagTypes.Id3v2:
|
||||
if (tag == null && create)
|
||||
{
|
||||
tag = new Id3v2.Tag();
|
||||
tag.Version = 2;
|
||||
}
|
||||
|
||||
id32_tag = tag;
|
||||
break;
|
||||
}
|
||||
|
||||
return id32_tag;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
/// <summary>
|
||||
/// Reads the contents of the current instance determining
|
||||
/// the size of the riff data, the area the tagging is in,
|
||||
/// and optionally reading in the tags and media properties.
|
||||
/// </summary>
|
||||
/// <param name="read_tags">
|
||||
/// If <see langword="true" />, any tags found will be read
|
||||
/// into the current instance.
|
||||
/// </param>
|
||||
/// <param name="style">
|
||||
/// A <see cref="ReadStyle"/> value specifying how the media
|
||||
/// data is to be read into the current instance.
|
||||
/// </param>
|
||||
/// <param name="aiff_size">
|
||||
/// A <see cref="uint"/> value reference to be filled with
|
||||
/// the size of the RIFF data as read from the file.
|
||||
/// </param>
|
||||
/// <param name="tag_start">
|
||||
/// A <see cref="long" /> value reference to be filled with
|
||||
/// the absolute seek position at which the tagging data
|
||||
/// starts.
|
||||
/// </param>
|
||||
/// <param name="tag_end">
|
||||
/// A <see cref="long" /> value reference to be filled with
|
||||
/// the absolute seek position at which the tagging data
|
||||
/// ends.
|
||||
/// </param>
|
||||
/// <exception cref="CorruptFileException">
|
||||
/// The file does not begin with <see cref="FileIdentifier"
|
||||
/// />.
|
||||
/// </exception>
|
||||
private void Read(bool read_tags, ReadStyle style,
|
||||
out uint aiff_size, out long tag_start,
|
||||
out long tag_end)
|
||||
{
|
||||
Seek(0);
|
||||
if (ReadBlock(4) != FileIdentifier)
|
||||
throw new CorruptFileException(
|
||||
"File does not begin with AIFF identifier");
|
||||
|
||||
aiff_size = ReadBlock(4).ToUInt(true);
|
||||
tag_start = -1;
|
||||
tag_end = -1;
|
||||
|
||||
// Get the properties of the file
|
||||
if (header_block == null &&
|
||||
style != ReadStyle.None)
|
||||
{
|
||||
long common_chunk_pos = Find(CommIdentifier, 0);
|
||||
|
||||
if (common_chunk_pos == -1)
|
||||
{
|
||||
throw new CorruptFileException(
|
||||
"No Common chunk available in AIFF file.");
|
||||
}
|
||||
|
||||
Seek(common_chunk_pos);
|
||||
header_block = ReadBlock((int) StreamHeader.Size);
|
||||
|
||||
StreamHeader header = new StreamHeader(header_block, aiff_size);
|
||||
properties = new Properties(TimeSpan.Zero, header);
|
||||
}
|
||||
|
||||
// Now we search for the ID3 chunk.
|
||||
// Normally it appears after the Sound data chunk. But as the order of
|
||||
// chunks is free, it might be the case that the ID3 chunk appears before
|
||||
// the sound data chunk.
|
||||
// So we search first for the Sound data chunk and see, if an ID3 chunk appears before
|
||||
long id3_chunk_pos = -1;
|
||||
long sound_chunk_pos = Find(SoundIdentifier, 0, ID3Identifier);
|
||||
if (sound_chunk_pos == -1)
|
||||
{
|
||||
// The ID3 chunk appears before the Sound chunk
|
||||
id3_chunk_pos = Find(ID3Identifier, 0);
|
||||
}
|
||||
|
||||
// Now let's look for the Sound chunk again
|
||||
// Since a previous return value of -1 does mean, that the ID3 chunk was found first
|
||||
sound_chunk_pos = Find(SoundIdentifier, 0);
|
||||
if (sound_chunk_pos == -1)
|
||||
{
|
||||
throw new CorruptFileException(
|
||||
"No Sound chunk available in AIFF file.");
|
||||
}
|
||||
|
||||
// Get the length of the Sound chunk and use this as a start value to look for the ID3 chunk
|
||||
Seek(sound_chunk_pos + 4);
|
||||
ulong sound_chunk_length = ReadBlock(4).ToULong(true);
|
||||
long start_search_pos = (long) sound_chunk_length + sound_chunk_pos + 4;
|
||||
|
||||
if (id3_chunk_pos == -1)
|
||||
{
|
||||
id3_chunk_pos = Find(ID3Identifier, start_search_pos);
|
||||
}
|
||||
|
||||
if (id3_chunk_pos > -1)
|
||||
{
|
||||
if (read_tags && tag == null)
|
||||
{
|
||||
tag = new Id3v2.Tag(this,
|
||||
id3_chunk_pos + 8);
|
||||
}
|
||||
|
||||
// Get the length of the tag out of the ID3 chunk
|
||||
Seek(id3_chunk_pos + 4);
|
||||
uint tag_size = ReadBlock(4).ToUInt(true) + 8;
|
||||
|
||||
tag_start = InvariantStartPosition = id3_chunk_pos;
|
||||
tag_end = InvariantEndPosition = tag_start + tag_size;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,340 +0,0 @@
|
||||
//
|
||||
// StreamHeader.cs: Provides support for reading Apple's AIFF stream
|
||||
// properties.
|
||||
//
|
||||
// Author:
|
||||
// Helmut Wahrmann
|
||||
//
|
||||
// Copyright (C) 2009 Helmut Wahrmann
|
||||
//
|
||||
// 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.Globalization;
|
||||
|
||||
namespace TagLib.Aiff
|
||||
{
|
||||
/// <summary>
|
||||
/// This struct implements <see cref="IAudioCodec" /> to provide
|
||||
/// support for reading Apple's AIFF stream properties.
|
||||
/// </summary>
|
||||
public struct StreamHeader : IAudioCodec, ILosslessAudioCodec
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Contains the number of channels.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This value is stored in bytes (9,10).
|
||||
/// 1 is monophonic, 2 is stereo, 4 means 4 channels, etc..
|
||||
/// any number of audio channels may be represented
|
||||
/// </remarks>
|
||||
private ushort channels;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the number of sample frames in the Sound Data chunk.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This value is stored in bytes (11-14).
|
||||
/// </remarks>
|
||||
private ulong total_frames;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the number of bits per sample.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This value is stored in bytes (15,16).
|
||||
/// It can be any number from 1 to 32.
|
||||
/// </remarks>
|
||||
private ushort bits_per_sample;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the sample rate.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This value is stored in bytes (17-26).
|
||||
/// the sample rate at which the sound is to be played back,
|
||||
/// in sample frames per second
|
||||
/// </remarks>
|
||||
private ulong sample_rate;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the length of the audio stream.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This value is provided by the constructor.
|
||||
/// </remarks>
|
||||
private long stream_length;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Static Fields
|
||||
|
||||
/// <summary>
|
||||
/// The size of an AIFF Common chunk
|
||||
/// </summary>
|
||||
public const uint Size = 26;
|
||||
|
||||
/// <summary>
|
||||
/// The identifier used to recognize a AIFF file.
|
||||
/// Altough an AIFF file start with "FORM2, we're interested
|
||||
/// in the Common chunk only, which contains the properties we need.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// "COMM"
|
||||
/// </value>
|
||||
public static readonly ReadOnlyByteVector FileIdentifier =
|
||||
"COMM";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="StreamHeader" /> for a specified header block and
|
||||
/// stream length.
|
||||
/// </summary>
|
||||
/// <param name="data">
|
||||
/// A <see cref="ByteVector" /> object containing the stream
|
||||
/// header data.
|
||||
/// </param>
|
||||
/// <param name="streamLength">
|
||||
/// A <see cref="long" /> value containing the length of the
|
||||
/// AIFF Audio stream in bytes.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="data" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
/// <exception cref="CorruptFileException">
|
||||
/// <paramref name="data" /> does not begin with <see
|
||||
/// cref="FileIdentifier" />
|
||||
/// </exception>
|
||||
public StreamHeader(ByteVector data, long streamLength)
|
||||
{
|
||||
if (data == null)
|
||||
throw new ArgumentNullException("data");
|
||||
|
||||
|
||||
if (!data.StartsWith(FileIdentifier))
|
||||
throw new CorruptFileException(
|
||||
"Data does not begin with identifier.");
|
||||
|
||||
stream_length = streamLength;
|
||||
|
||||
// The first 8 bytes contain the Common chunk identifier "COMM"
|
||||
// And the size of the common chunk, which is always 18
|
||||
channels = data.Mid(8, 2).ToUShort(true);
|
||||
total_frames = data.Mid(10, 4).ToULong(true);
|
||||
bits_per_sample = data.Mid(14, 2).ToUShort(true);
|
||||
|
||||
ByteVector sample_rate_indicator = data.Mid(17, 1);
|
||||
ulong sample_rate_tmp = data.Mid(18, 2).ToULong(true);
|
||||
sample_rate = 44100; // Set 44100 as default sample rate
|
||||
|
||||
// The following are combinations that iTunes 8 encodes to.
|
||||
// There may be other combinations in the field, but i couldn't test them.
|
||||
switch (sample_rate_tmp)
|
||||
{
|
||||
case 44100:
|
||||
if (sample_rate_indicator == 0x0E)
|
||||
{
|
||||
sample_rate = 44100;
|
||||
}
|
||||
else if (sample_rate_indicator == 0x0D)
|
||||
{
|
||||
sample_rate = 22050;
|
||||
}
|
||||
else if (sample_rate_indicator == 0x0C)
|
||||
{
|
||||
sample_rate = 11025;
|
||||
}
|
||||
break;
|
||||
|
||||
case 48000:
|
||||
if (sample_rate_indicator == 0x0E)
|
||||
{
|
||||
sample_rate = 48000;
|
||||
}
|
||||
else if (sample_rate_indicator == 0x0D)
|
||||
{
|
||||
sample_rate = 24000;
|
||||
}
|
||||
break;
|
||||
|
||||
case 64000:
|
||||
if (sample_rate_indicator == 0x0D)
|
||||
{
|
||||
sample_rate = 32000;
|
||||
}
|
||||
else if (sample_rate_indicator == 0x0C)
|
||||
{
|
||||
sample_rate = 16000;
|
||||
}
|
||||
else if (sample_rate_indicator == 0x0B)
|
||||
{
|
||||
sample_rate = 8000;
|
||||
}
|
||||
break;
|
||||
|
||||
case 44510:
|
||||
if (sample_rate_indicator == 0x0D)
|
||||
{
|
||||
sample_rate = 22255;
|
||||
}
|
||||
break;
|
||||
|
||||
case 44508:
|
||||
if (sample_rate_indicator == 0x0C)
|
||||
{
|
||||
sample_rate = 11127;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the duration of the media represented by the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="TimeSpan" /> containing the duration of the
|
||||
/// media represented by the current instance.
|
||||
/// </value>
|
||||
public TimeSpan Duration
|
||||
{
|
||||
get
|
||||
{
|
||||
if (sample_rate <= 0 || total_frames <= 0)
|
||||
return TimeSpan.Zero;
|
||||
|
||||
return TimeSpan.FromSeconds(
|
||||
(double) total_frames/
|
||||
(double) sample_rate);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the types of media represented by the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Always <see cref="MediaTypes.Audio" />.
|
||||
/// </value>
|
||||
public MediaTypes MediaTypes
|
||||
{
|
||||
get { return MediaTypes.Audio; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a text description of the media represented by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="string" /> object containing a description
|
||||
/// of the media represented by the current instance.
|
||||
/// </value>
|
||||
public string Description
|
||||
{
|
||||
get { return "AIFF Audio"; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the bitrate of the audio represented by the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing a bitrate of the
|
||||
/// audio represented by the current instance.
|
||||
/// </value>
|
||||
public int AudioBitrate
|
||||
{
|
||||
get
|
||||
{
|
||||
TimeSpan d = Duration;
|
||||
if (d <= TimeSpan.Zero)
|
||||
return 0;
|
||||
|
||||
return (int) ((stream_length*8L)/
|
||||
d.TotalSeconds)/1000;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the sample count of the audio represented by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing the sample count
|
||||
/// of the audio represented by the current instance.
|
||||
/// </value>
|
||||
public long AudioSampleCount
|
||||
{
|
||||
get
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the sample rate of the audio represented by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing the sample rate of
|
||||
/// the audio represented by the current instance.
|
||||
/// </value>
|
||||
public int AudioSampleRate
|
||||
{
|
||||
get { return (int) sample_rate; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of channels in the audio represented by
|
||||
/// the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing the number of
|
||||
/// channels in the audio represented by the current
|
||||
/// instance.
|
||||
/// </value>
|
||||
public int AudioChannels
|
||||
{
|
||||
get { return channels; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of bits per sample in the audio
|
||||
/// represented by the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing the number of bits
|
||||
/// per sample in the audio represented by the current
|
||||
/// instance.
|
||||
/// </value>
|
||||
public int BitsPerSample
|
||||
{
|
||||
get { return bits_per_sample; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,280 +0,0 @@
|
||||
//
|
||||
// File.cs: Provides tagging and properties support for Monkey's Audio APE
|
||||
// files.
|
||||
//
|
||||
// Author:
|
||||
// Helmut Wahrmann
|
||||
//
|
||||
// Copyright (C) 2007 Helmut Wahrmann
|
||||
// Copyright (C) 2007 Brian Nickel
|
||||
//
|
||||
// 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.Ape {
|
||||
/// <summary>
|
||||
/// This class extends <see cref="TagLib.NonContainer.File" /> to
|
||||
/// provide tagging and properties support for Monkey's Audio APE
|
||||
/// files.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// A <see cref="TagLib.Ape.Tag" /> will be added automatically to
|
||||
/// any file that doesn't contain one. This change does not effect
|
||||
/// the physical file until <see cref="Save" /> is called and can be
|
||||
/// reversed using the following method:
|
||||
/// <code>file.RemoveTags (file.TagTypes & ~file.TagTypesOnDisk);</code>
|
||||
/// </remarks>
|
||||
[SupportedMimeType("taglib/ape", "ape")]
|
||||
[SupportedMimeType("audio/x-ape")]
|
||||
[SupportedMimeType("audio/ape")]
|
||||
[SupportedMimeType("application/x-ape")]
|
||||
public class File : TagLib.NonContainer.File
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Contains the block with the audio header.
|
||||
/// </summary>
|
||||
private ByteVector header_block = null;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="File" /> for a specified path in the local file
|
||||
/// system and specified read style.
|
||||
/// </summary>
|
||||
/// <param name="path">
|
||||
/// A <see cref="string" /> object containing the path of the
|
||||
/// file to use in the new instance.
|
||||
/// </param>
|
||||
/// <param name="propertiesStyle">
|
||||
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||
/// of accuracy to read the media properties, or <see
|
||||
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="path" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public File (string path, ReadStyle propertiesStyle)
|
||||
: base (path, propertiesStyle)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="File" /> for a specified path in the local file
|
||||
/// system with an average read style.
|
||||
/// </summary>
|
||||
/// <param name="path">
|
||||
/// A <see cref="string" /> object containing the path of the
|
||||
/// file to use in the new instance.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="path" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public File (string path)
|
||||
: base (path)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="File" /> for a specified file abstraction and
|
||||
/// specified read style.
|
||||
/// </summary>
|
||||
/// <param name="abstraction">
|
||||
/// A <see cref="IFileAbstraction" /> object to use when
|
||||
/// reading from and writing to the file.
|
||||
/// </param>
|
||||
/// <param name="propertiesStyle">
|
||||
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||
/// of accuracy to read the media properties, or <see
|
||||
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="abstraction" /> is <see langword="null"
|
||||
/// />.
|
||||
/// </exception>
|
||||
public File (File.IFileAbstraction abstraction,
|
||||
ReadStyle propertiesStyle)
|
||||
: base (abstraction, propertiesStyle)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="File" /> for a specified file abstraction with an
|
||||
/// average read style.
|
||||
/// </summary>
|
||||
/// <param name="abstraction">
|
||||
/// A <see cref="IFileAbstraction" /> object to use when
|
||||
/// reading from and writing to the file.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="abstraction" /> is <see langword="null"
|
||||
/// />.
|
||||
/// </exception>
|
||||
public File (File.IFileAbstraction abstraction)
|
||||
: base (abstraction)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Gets a tag of a specified type from the current instance,
|
||||
/// optionally creating a new tag if possible.
|
||||
/// </summary>
|
||||
/// <param name="type">
|
||||
/// A <see cref="TagLib.TagTypes" /> value indicating the
|
||||
/// type of tag to read.
|
||||
/// </param>
|
||||
/// <param name="create">
|
||||
/// A <see cref="bool" /> value specifying whether or not to
|
||||
/// try and create the tag if one is not found.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="Tag" /> object containing the tag that was
|
||||
/// found in or added to the current instance. If no
|
||||
/// matching tag was found and none was created, <see
|
||||
/// langword="null" /> is returned.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// If a <see cref="TagLib.Id3v2.Tag" /> is added to the
|
||||
/// current instance, it will be placed at the start of the
|
||||
/// file. On the other hand, <see cref="TagLib.Id3v1.Tag" />
|
||||
/// <see cref="TagLib.Ape.Tag" /> will be added to the end of
|
||||
/// the file. All other tag types will be ignored.
|
||||
/// </remarks>
|
||||
public override TagLib.Tag GetTag(TagTypes type, bool create)
|
||||
{
|
||||
TagLib.Tag t = (Tag as TagLib.NonContainer.Tag)
|
||||
.GetTag (type);
|
||||
|
||||
if (t != null || !create)
|
||||
return t;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case TagTypes.Id3v1:
|
||||
return EndTag.AddTag (type, Tag);
|
||||
|
||||
case TagTypes.Id3v2:
|
||||
return StartTag.AddTag (type, Tag);
|
||||
|
||||
case TagTypes.Ape:
|
||||
return EndTag.AddTag (type, Tag);
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
/// <summary>
|
||||
/// Reads format specific information at the start of the
|
||||
/// file.
|
||||
/// </summary>
|
||||
/// <param name="start">
|
||||
/// A <see cref="long" /> value containing the seek position
|
||||
/// at which the tags end and the media data begins.
|
||||
/// </param>
|
||||
/// <param name="propertiesStyle">
|
||||
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||
/// of accuracy to read the media properties, or <see
|
||||
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||
/// </param>
|
||||
protected override void ReadStart (long start,
|
||||
ReadStyle propertiesStyle)
|
||||
{
|
||||
if (header_block != null &&
|
||||
propertiesStyle == ReadStyle.None)
|
||||
return;
|
||||
|
||||
Seek(start);
|
||||
header_block = ReadBlock ((int)StreamHeader.Size);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads format specific information at the end of the
|
||||
/// file.
|
||||
/// </summary>
|
||||
/// <param name="end">
|
||||
/// A <see cref="long" /> value containing the seek position
|
||||
/// at which the media data ends and the tags begin.
|
||||
/// </param>
|
||||
/// <param name="propertiesStyle">
|
||||
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||
/// of accuracy to read the media properties, or <see
|
||||
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||
/// </param>
|
||||
protected override void ReadEnd (long end,
|
||||
ReadStyle propertiesStyle)
|
||||
{
|
||||
// Make sure we have an APE tag.
|
||||
GetTag (TagTypes.Ape, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the audio properties from the file represented by
|
||||
/// the current instance.
|
||||
/// </summary>
|
||||
/// <param name="start">
|
||||
/// A <see cref="long" /> value containing the seek position
|
||||
/// at which the tags end and the media data begins.
|
||||
/// </param>
|
||||
/// <param name="end">
|
||||
/// A <see cref="long" /> value containing the seek position
|
||||
/// at which the media data ends and the tags begin.
|
||||
/// </param>
|
||||
/// <param name="propertiesStyle">
|
||||
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||
/// of accuracy to read the media properties, or <see
|
||||
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="TagLib.Properties" /> object describing the
|
||||
/// media properties of the file represented by the current
|
||||
/// instance.
|
||||
/// </returns>
|
||||
protected override Properties ReadProperties (long start,
|
||||
long end,
|
||||
ReadStyle propertiesStyle)
|
||||
{
|
||||
StreamHeader header = new StreamHeader (header_block,
|
||||
end - start);
|
||||
|
||||
return new Properties(TimeSpan.Zero, header);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,418 +0,0 @@
|
||||
//
|
||||
// Footer.cs: Provides a representation of an APEv2 tag footer which can be read
|
||||
// from and written to disk.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Original Source:
|
||||
// apefooter.cpp from TagLib
|
||||
//
|
||||
// Copyright (C) 2005-2007 Brian Nickel
|
||||
// Copyright (C) 2004 Allan Sandfeld Jensen (Original Implementation)
|
||||
// copyright (C) 2002, 2003 Scott Wheeler (Original Implementation)
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License version
|
||||
// 2.1 as published by the Free Software Foundation.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
// USA
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace TagLib.Ape {
|
||||
#region Enums
|
||||
|
||||
/// <summary>
|
||||
/// Indicates the flags applied to a <see cref="Footer" /> object.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum FooterFlags : uint {
|
||||
/// <summary>
|
||||
/// The tag lacks a footer object.
|
||||
/// </summary>
|
||||
FooterAbsent = 0x40000000,
|
||||
|
||||
/// <summary>
|
||||
/// The footer is actually a header.
|
||||
/// </summary>
|
||||
IsHeader = 0x20000000,
|
||||
|
||||
/// <summary>
|
||||
/// The tag contains a header.
|
||||
/// </summary>
|
||||
HeaderPresent = 0x80000000
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// This structure provides a representation of an APEv2 tag footer
|
||||
/// which can be read from and written to disk.
|
||||
/// </summary>
|
||||
public struct Footer : IEquatable<Footer>
|
||||
{
|
||||
#region Private Properties
|
||||
|
||||
/// <summary>
|
||||
/// Contains the APE tag version.
|
||||
/// </summary>
|
||||
private uint version;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the footer flags.
|
||||
/// </summary>
|
||||
private FooterFlags flags;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the number of items in the tag.
|
||||
/// </summary>
|
||||
private uint item_count;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the tag size including the footer but excluding
|
||||
/// the header.
|
||||
/// </summary>
|
||||
private uint tag_size;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Static Fields
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the size of an APEv2 footer.
|
||||
/// </summary>
|
||||
public const uint Size = 32;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the identifier used find an APEv2 footer in a
|
||||
/// file.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// "<c>APETAGEX</c>"
|
||||
/// </value>
|
||||
public static readonly ReadOnlyByteVector FileIdentifier = "APETAGEX";
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="Footer" /> by reading it from raw footer data.
|
||||
/// </summary>
|
||||
/// <param name="data">
|
||||
/// A <see cref="ByteVector" /> object containing the raw
|
||||
/// data to build the new instance from.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="data" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
/// <exception cref="CorruptFileException">
|
||||
/// <paramref name="data" /> is smaller than <see
|
||||
/// cref="Size" /> or does not begin with <see
|
||||
/// cref="FileIdentifier" />.
|
||||
/// </exception>
|
||||
public Footer (ByteVector data)
|
||||
{
|
||||
if (data == null)
|
||||
throw new ArgumentNullException ("data");
|
||||
|
||||
if (data.Count < Size)
|
||||
throw new CorruptFileException (
|
||||
"Provided data is smaller than object size.");
|
||||
|
||||
if (!data.StartsWith (FileIdentifier))
|
||||
throw new CorruptFileException (
|
||||
"Provided data does not start with File Identifier");
|
||||
|
||||
version = data.Mid (8, 4).ToUInt (false);
|
||||
tag_size = data.Mid (12, 4).ToUInt (false);
|
||||
item_count = data.Mid (16, 4).ToUInt (false);
|
||||
flags = (FooterFlags) data.Mid (20, 4).ToUInt (false);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the version of APE tag described by the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="uint" /> value containing the version of the
|
||||
/// APE tag described by the current instance.
|
||||
/// </value>
|
||||
public uint Version {
|
||||
get {return version == 0 ? 2000 : version;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the flags that apply to the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A bitwise combined <see cref="FooterFlags" /> value
|
||||
/// containing the flags that apply to the current instance.
|
||||
/// </value>
|
||||
public FooterFlags Flags {
|
||||
get {return flags;}
|
||||
set {flags = value;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the number of items in the tag represented
|
||||
/// by the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="uint" /> value containing the number of
|
||||
/// items in the tag represented by the current instance.
|
||||
/// </value>
|
||||
public uint ItemCount {
|
||||
get {return item_count;}
|
||||
set {item_count = value;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of the tag represented by the current
|
||||
/// instance, including the footer but excluding the header
|
||||
/// if applicable.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="uint" /> value containing the size of the
|
||||
/// tag represented by the current instance.
|
||||
/// </value>
|
||||
public uint TagSize {
|
||||
get {return tag_size;}
|
||||
set {tag_size = value;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the complete size of the tag represented by the
|
||||
/// current instance, including the header and footer.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="uint" /> value containing the size of the
|
||||
/// tag represented by the current instance.
|
||||
/// </value>
|
||||
public uint CompleteTagSize {
|
||||
get {
|
||||
return TagSize + ((Flags &
|
||||
FooterFlags.HeaderPresent) != 0 ?
|
||||
Size : 0);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Renders the current instance as an APE tag footer.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector" /> object containing the
|
||||
/// rendered version of the current instance.
|
||||
/// </returns>
|
||||
public ByteVector RenderFooter ()
|
||||
{
|
||||
return Render (false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders the current instance as an APE tag header.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector" /> object containing the
|
||||
/// rendered version of the current instance or an empty
|
||||
/// <see cref="ByteVector" /> object if <see cref="Flags" />
|
||||
/// does not include <see cref="FooterFlags.HeaderPresent"
|
||||
/// />.
|
||||
/// </returns>
|
||||
public ByteVector RenderHeader ()
|
||||
{
|
||||
return (Flags & FooterFlags.HeaderPresent) != 0 ?
|
||||
Render (true) : new ByteVector ();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Private Methods
|
||||
|
||||
/// <summary>
|
||||
/// Renders the current instance as either an APE tag header
|
||||
/// or footer.
|
||||
/// </summary>
|
||||
/// <param name="isHeader">
|
||||
/// A <see cref="bool" /> value indicating whether or not the
|
||||
/// current instance is to be rendered as a header.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector" /> object containing the
|
||||
/// rendered version of the current instance.
|
||||
/// </returns>
|
||||
private ByteVector Render (bool isHeader)
|
||||
{
|
||||
ByteVector v = new ByteVector ();
|
||||
|
||||
// add the file identifier -- "APETAGEX"
|
||||
v.Add (FileIdentifier);
|
||||
|
||||
// add the version number -- we always render a 2.000
|
||||
// tag regardless of what the tag originally was.
|
||||
v.Add (ByteVector.FromUInt (2000, false));
|
||||
|
||||
// add the tag size
|
||||
v.Add (ByteVector.FromUInt (tag_size, false));
|
||||
|
||||
// add the item count
|
||||
v.Add (ByteVector.FromUInt (item_count, false));
|
||||
|
||||
// render and add the flags
|
||||
uint flags = 0;
|
||||
|
||||
if ((Flags & FooterFlags.HeaderPresent) != 0)
|
||||
flags |= (uint) FooterFlags.HeaderPresent;
|
||||
|
||||
// footer is always present
|
||||
if (isHeader)
|
||||
flags |= (uint) FooterFlags.IsHeader;
|
||||
else
|
||||
flags &= (uint) ~FooterFlags.IsHeader;
|
||||
|
||||
v.Add (ByteVector.FromUInt (flags, false));
|
||||
|
||||
// add the reserved 64bit
|
||||
v.Add (ByteVector.FromULong (0));
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region IEquatable
|
||||
|
||||
/// <summary>
|
||||
/// Generates a hash code for the current instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="int" /> value containing the hash code for
|
||||
/// the current instance.
|
||||
/// </returns>
|
||||
public override int GetHashCode ()
|
||||
{
|
||||
unchecked {
|
||||
return (int) ((uint) flags ^ tag_size ^
|
||||
item_count ^ version);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether or not the current instance is equal to
|
||||
/// another object.
|
||||
/// </summary>
|
||||
/// <param name="other">
|
||||
/// A <see cref="object" /> to compare to the current
|
||||
/// instance.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="bool" /> value indicating whether or not the
|
||||
/// current instance is equal to <paramref name="other" />.
|
||||
/// </returns>
|
||||
/// <seealso cref="M:System.IEquatable`1.Equals" />
|
||||
public override bool Equals (object other)
|
||||
{
|
||||
if (!(other is Footer))
|
||||
return false;
|
||||
|
||||
return Equals ((Footer) other);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether or not the current instance is equal to
|
||||
/// another instance of <see cref="Footer" />.
|
||||
/// </summary>
|
||||
/// <param name="other">
|
||||
/// A <see cref="Footer" /> object to compare to the current
|
||||
/// instance.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="bool" /> value indicating whether or not the
|
||||
/// current instance is equal to <paramref name="other" />.
|
||||
/// </returns>
|
||||
/// <seealso cref="M:System.IEquatable`1.Equals" />
|
||||
public bool Equals (Footer other)
|
||||
{
|
||||
return flags == other.flags &&
|
||||
tag_size == other.tag_size &&
|
||||
item_count == other.item_count &&
|
||||
version == other.version;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not two instances of <see cref="Footer"
|
||||
/// /> are equal to eachother.
|
||||
/// </summary>
|
||||
/// <param name="first">
|
||||
/// The first <see cref="Footer" /> object to compare.
|
||||
/// </param>
|
||||
/// <param name="second">
|
||||
/// The second <see cref="Footer" /> object to compare.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// <see langword="true" /> if <paramref name="first" /> is
|
||||
/// equal to <paramref name="second" />. Otherwise, <see
|
||||
/// langword="false" />.
|
||||
/// </returns>
|
||||
public static bool operator == (Footer first, Footer second)
|
||||
{
|
||||
return first.Equals (second);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not two instances of <see cref="Footer"
|
||||
/// /> are unequal to eachother.
|
||||
/// </summary>
|
||||
/// <param name="first">
|
||||
/// The first <see cref="Footer" /> object to compare.
|
||||
/// </param>
|
||||
/// <param name="second">
|
||||
/// The second <see cref="Footer" /> object to compare.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// <see langword="true" /> if <paramref name="first" /> is
|
||||
/// unequal to <paramref name="second" />. Otherwise, <see
|
||||
/// langword="false" />.
|
||||
/// </returns>
|
||||
public static bool operator != (Footer first, Footer second)
|
||||
{
|
||||
return !first.Equals (second);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,532 +0,0 @@
|
||||
//
|
||||
// Item.cs: Provides a representation of an APEv2 tag item which can be read
|
||||
// from and written to disk.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Original Source:
|
||||
// apeitem.cpp from TagLib
|
||||
//
|
||||
// Copyright (C) 2005-2007 Brian Nickel
|
||||
// Copyright (C) 2004 by Allan Sandfeld Jensen (Original Implementation)
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License version
|
||||
// 2.1 as published by the Free Software Foundation.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
// USA
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace TagLib.Ape {
|
||||
/// <summary>
|
||||
/// Indicates the type of data stored in a <see cref="Item" />
|
||||
/// object.
|
||||
/// </summary>
|
||||
public enum ItemType {
|
||||
/// <summary>
|
||||
/// The item contains Unicode text.
|
||||
/// </summary>
|
||||
Text = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The item contains binary data.
|
||||
/// </summary>
|
||||
Binary = 1,
|
||||
|
||||
/// <summary>
|
||||
/// The item contains a locator (file path/URL) for external
|
||||
/// information.
|
||||
/// </summary>
|
||||
Locator = 2
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This class provides a representation of an APEv2 tag item which
|
||||
/// can be read from and written to disk.
|
||||
/// </summary>
|
||||
public class Item : ICloneable
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Contains the type of data stored in the item.
|
||||
/// </summary>
|
||||
private ItemType type = ItemType.Text;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the item key.
|
||||
/// </summary>
|
||||
private string key = null;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the item value.
|
||||
/// </summary>
|
||||
private ReadOnlyByteVector data = null;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the item text.
|
||||
/// </summary>
|
||||
private string [] text = null;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether or not the item is read only.
|
||||
/// </summary>
|
||||
private bool read_only = false;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the size of the item on disk.
|
||||
/// </summary>
|
||||
private int size_on_disk;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="Item" /> by reading in a raw APEv2 item.
|
||||
/// </summary>
|
||||
/// <param name="data">
|
||||
/// A <see cref="ByteVector" /> object containing the item to
|
||||
/// read.
|
||||
/// </param>
|
||||
/// <param name="offset">
|
||||
/// A <see cref="int" /> value specifying the offset in
|
||||
/// <paramref name="data" /> at which the item data begins.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="data" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// <paramref name="offset" /> is less than zero.
|
||||
/// </exception>
|
||||
/// <exception cref="CorruptFileException">
|
||||
/// A complete item could not be read.
|
||||
/// </exception>
|
||||
public Item (ByteVector data, int offset)
|
||||
{
|
||||
if (data == null)
|
||||
throw new ArgumentNullException ("data");
|
||||
|
||||
Parse (data, offset);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="Item" /> with a specified key and value.
|
||||
/// </summary>
|
||||
/// <param name="key">
|
||||
/// A <see cref="string" /> object containing the key to use
|
||||
/// for the current instance.
|
||||
/// </param>
|
||||
/// <param name="value">
|
||||
/// A <see cref="string" /> object containing the value to
|
||||
/// store in the new instance.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="key" /> or <paramref name="value" /> is
|
||||
/// <see langword="null" />.
|
||||
/// </exception>
|
||||
public Item (string key, string value)
|
||||
{
|
||||
if (key == null)
|
||||
throw new ArgumentNullException ("key");
|
||||
|
||||
if (value == null)
|
||||
throw new ArgumentNullException ("value");
|
||||
|
||||
this.key = key;
|
||||
this.text = new string [] {value};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="Item" /> with a specified key and collection of
|
||||
/// values.
|
||||
/// </summary>
|
||||
/// <param name="key">
|
||||
/// A <see cref="string" /> object containing the key to use
|
||||
/// for the current instance.
|
||||
/// </param>
|
||||
/// <param name="value">
|
||||
/// A <see cref="string[]" /> containing the values to store
|
||||
/// in the new instance.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="key" /> or <paramref name="value" /> is
|
||||
/// <see langword="null" />.
|
||||
/// </exception>
|
||||
public Item (string key, params string [] value)
|
||||
{
|
||||
if (key == null)
|
||||
throw new ArgumentNullException ("key");
|
||||
|
||||
if (value == null)
|
||||
throw new ArgumentNullException ("value");
|
||||
|
||||
this.key = key;
|
||||
this.text = (string[]) value.Clone ();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="Item" /> with a specified key and collection of
|
||||
/// values.
|
||||
/// </summary>
|
||||
/// <param name="key">
|
||||
/// A <see cref="string" /> object containing the key to use
|
||||
/// for the current instance.
|
||||
/// </param>
|
||||
/// <param name="value">
|
||||
/// A <see cref="StringCollection" /> object containing the
|
||||
/// values to store in the new instance.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="key" /> or <paramref name="value" /> is
|
||||
/// <see langword="null" />.
|
||||
/// </exception>
|
||||
/// <seealso cref="Item(string,string[])" />
|
||||
[Obsolete("Use Item(string,string[])")]
|
||||
public Item (string key, StringCollection value)
|
||||
{
|
||||
if (key == null)
|
||||
throw new ArgumentNullException ("key");
|
||||
|
||||
if (value == null)
|
||||
throw new ArgumentNullException ("value");
|
||||
|
||||
this.key = key;
|
||||
this.text = value.ToArray ();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="Item" /> with a specified key and raw data.
|
||||
/// </summary>
|
||||
/// <param name="key">
|
||||
/// A <see cref="string" /> object containing the key to use
|
||||
/// for the current instance.
|
||||
/// </param>
|
||||
/// <param name="value">
|
||||
/// A <see cref="StringCollection" /> object containing the
|
||||
/// values to store in the new instance.
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// This constructor automatically marks the new instance as
|
||||
/// <see cref="ItemType.Binary" />.
|
||||
/// </remarks>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="key" /> or <paramref name="value" /> is
|
||||
/// <see langword="null" />.
|
||||
/// </exception>
|
||||
/// <seealso cref="Item(string,string[])" />
|
||||
public Item (string key, ByteVector value)
|
||||
{
|
||||
this.key = key;
|
||||
this.type = ItemType.Binary;
|
||||
|
||||
data = value as ReadOnlyByteVector;
|
||||
if (data == null)
|
||||
data = new ReadOnlyByteVector (value);
|
||||
}
|
||||
|
||||
private Item (Item item)
|
||||
{
|
||||
type = item.type;
|
||||
key = item.key;
|
||||
if (item.data != null)
|
||||
data = new ReadOnlyByteVector (item.data);
|
||||
if (item.text != null)
|
||||
text = (string[]) item.text.Clone ();
|
||||
read_only = item.read_only;
|
||||
size_on_disk = item.size_on_disk;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the key used to identify the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="string" /> object containing the key used to
|
||||
/// identify the current instance.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// This value is used for specifying the contents of the
|
||||
/// item in a common and consistant fashion. For example,
|
||||
/// <c>"TITLE"</c> specifies that the item contains the title
|
||||
/// of the track.
|
||||
/// </remarks>
|
||||
public string Key {
|
||||
get {return key;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the binary value stored in the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="ByteVector" /> object containing the binary
|
||||
/// value stored in the current instance, or <see
|
||||
/// langword="null" /> if the item contains text.
|
||||
/// </value>
|
||||
public ByteVector Value {
|
||||
get {return (type == ItemType.Binary) ? data : null;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of the current instance as it last appeared
|
||||
/// on disk.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing the size of the
|
||||
/// current instance as it last appeared on disk.
|
||||
/// </value>
|
||||
public int Size {
|
||||
get {return size_on_disk;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the type of value contained in the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="ItemType" /> value indicating the type of
|
||||
/// value contained in the current instance.
|
||||
/// </value>
|
||||
public ItemType Type {
|
||||
get {return type;}
|
||||
set {type = value;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets whether or not the current instance is
|
||||
/// flagged as read-only on disk.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="bool" /> value indicating whether or not the
|
||||
/// current instance is flagged as read-only on disk.
|
||||
/// </value>
|
||||
public bool ReadOnly {
|
||||
get {return read_only;}
|
||||
set {read_only = value;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not the current instance is empty.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="bool" /> value indicating whether or not the
|
||||
/// current instance contains no value.
|
||||
/// </value>
|
||||
public bool IsEmpty {
|
||||
get {
|
||||
if (type != ItemType.Binary)
|
||||
return text == null || text.Length == 0;
|
||||
else
|
||||
return data == null || data.IsEmpty;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Gets the contents of the current instance as a <see
|
||||
/// cref="string" />.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// <para>A <see cref="string" /> object containing the text
|
||||
/// stored in the current instance, or <see langword="null"
|
||||
/// /> if the item is empty of contains binary data.</para>
|
||||
/// <para>If the current instance contains multiple string
|
||||
/// values, they will be returned as a comma separated
|
||||
/// value.</para>
|
||||
/// </returns>
|
||||
public override string ToString ()
|
||||
{
|
||||
if (type == ItemType.Binary || text == null)
|
||||
return null;
|
||||
else
|
||||
return string.Join (", ", text);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the contents of the current instance as a <see
|
||||
/// cref="string" /> array.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="string[]" /> containing the text stored in
|
||||
/// the current instance, or an empty array if the item
|
||||
/// contains binary data.
|
||||
/// </returns>
|
||||
public string [] ToStringArray ()
|
||||
{
|
||||
if (type == ItemType.Binary || text == null)
|
||||
return new string [0];
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders the current instance as an APEv2 item.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector" /> object containing the
|
||||
/// rendered version of the current instance.
|
||||
/// </returns>
|
||||
public ByteVector Render ()
|
||||
{
|
||||
uint flags = (uint) ((ReadOnly) ? 1 : 0) |
|
||||
((uint) Type << 1);
|
||||
|
||||
if (IsEmpty)
|
||||
return new ByteVector ();
|
||||
|
||||
ByteVector result = null;
|
||||
|
||||
if (type == ItemType.Binary) {
|
||||
if (text == null && data != null)
|
||||
result = data;
|
||||
}
|
||||
|
||||
if (result == null && text != null) {
|
||||
result = new ByteVector ();
|
||||
|
||||
for (int i = 0; i < text.Length; i ++) {
|
||||
if (i != 0)
|
||||
result.Add ((byte) 0);
|
||||
|
||||
result.Add (ByteVector.FromString (
|
||||
text [i], StringType.UTF8));
|
||||
}
|
||||
}
|
||||
|
||||
// If no data is stored, don't write the item.
|
||||
if (result == null || result.Count == 0)
|
||||
return new ByteVector ();
|
||||
|
||||
ByteVector output = new ByteVector ();
|
||||
output.Add (ByteVector.FromUInt ((uint) result.Count,
|
||||
false));
|
||||
output.Add (ByteVector.FromUInt (flags, false));
|
||||
output.Add (ByteVector.FromString (key, StringType.UTF8));
|
||||
output.Add ((byte) 0);
|
||||
output.Add (result);
|
||||
|
||||
size_on_disk = output.Count;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
/// <summary>
|
||||
/// Populates the current instance by reading in a raw APEv2
|
||||
/// item.
|
||||
/// </summary>
|
||||
/// <param name="data">
|
||||
/// A <see cref="ByteVector" /> object containing the item to
|
||||
/// read.
|
||||
/// </param>
|
||||
/// <param name="offset">
|
||||
/// A <see cref="int" /> value specifying the offset in
|
||||
/// <paramref name="data" /> at which the item data begins.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="data" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// <paramref name="offset" /> is less than zero.
|
||||
/// </exception>
|
||||
/// <exception cref="CorruptFileException">
|
||||
/// A complete item could not be read.
|
||||
/// </exception>
|
||||
protected void Parse (ByteVector data, int offset)
|
||||
{
|
||||
if (data == null)
|
||||
throw new ArgumentNullException ("data");
|
||||
|
||||
if (offset < 0)
|
||||
throw new ArgumentOutOfRangeException ("offset");
|
||||
|
||||
|
||||
// 11 bytes is the minimum size for an APE item
|
||||
if(data.Count < offset + 11)
|
||||
throw new CorruptFileException (
|
||||
"Not enough data for APE Item");
|
||||
|
||||
uint value_length = data.Mid (offset, 4).ToUInt (false);
|
||||
uint flags = data.Mid (offset + 4, 4).ToUInt (false);
|
||||
|
||||
ReadOnly = (flags & 1) == 1;
|
||||
Type = (ItemType) ((flags >> 1) & 3);
|
||||
|
||||
int pos = data.Find (ByteVector.TextDelimiter (
|
||||
StringType.UTF8), offset + 8);
|
||||
|
||||
key = data.ToString (StringType.UTF8,
|
||||
offset + 8, pos - offset - 8);
|
||||
|
||||
if (value_length > data.Count - pos - 1)
|
||||
throw new CorruptFileException (
|
||||
"Invalid data length.");
|
||||
|
||||
size_on_disk = pos + 1 + (int) value_length - offset;
|
||||
|
||||
if (Type == ItemType.Binary)
|
||||
this.data = new ReadOnlyByteVector (
|
||||
data.Mid (pos + 1, (int) value_length));
|
||||
else
|
||||
this.text = data.Mid (pos + 1,
|
||||
(int) value_length).ToStrings (
|
||||
StringType.UTF8, 0);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region ICloneable
|
||||
|
||||
/// <summary>
|
||||
/// Creates a deep copy of the current instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A new <see cref="Item"/> object identical to the current
|
||||
/// instance.
|
||||
/// </returns>
|
||||
public Item Clone ()
|
||||
{
|
||||
return new Item (this);
|
||||
}
|
||||
|
||||
object ICloneable.Clone ()
|
||||
{
|
||||
return Clone ();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,388 +0,0 @@
|
||||
//
|
||||
// StreamHeader.cs: Provides support for reading Monkey's Audio APE stream
|
||||
// properties.
|
||||
//
|
||||
// Author:
|
||||
// Helmut Wahrmann
|
||||
//
|
||||
// Copyright (C) 2007 Helmut Wahrmann
|
||||
// Copyright (C) 2007 Brian Nickel
|
||||
//
|
||||
// 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.Globalization;
|
||||
|
||||
namespace TagLib.Ape {
|
||||
/// <summary>
|
||||
/// Indicates the compression level used when encoding a Monkey's
|
||||
/// Audio APE file.
|
||||
/// </summary>
|
||||
public enum CompressionLevel {
|
||||
/// <summary>
|
||||
/// The audio is not compressed.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The audio is mildly compressed.
|
||||
/// </summary>
|
||||
Fast = 1000,
|
||||
|
||||
/// <summary>
|
||||
/// The audio is compressed at a normal level.
|
||||
/// </summary>
|
||||
Normal = 2000,
|
||||
|
||||
/// <summary>
|
||||
/// The audio is highly compressed.
|
||||
/// </summary>
|
||||
High = 3000,
|
||||
|
||||
/// <summary>
|
||||
/// The audio is extremely highly compressed.
|
||||
/// </summary>
|
||||
ExtraHigh = 4000,
|
||||
|
||||
/// <summary>
|
||||
/// The audio is compressed to an insane level.
|
||||
/// </summary>
|
||||
Insane
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This struct implements <see cref="IAudioCodec" /> to provide
|
||||
/// support for reading Monkey's Audio APE stream properties.
|
||||
/// </summary>
|
||||
public struct StreamHeader : IAudioCodec, ILosslessAudioCodec
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Contains the APE version.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This value is stored in bytes (4,5) of the file and is
|
||||
/// 1000 times the actual version number, so 3810 indicates
|
||||
/// version 3.81.
|
||||
/// </remarks>
|
||||
private ushort version;
|
||||
|
||||
// Ape Header (24 bytes) starting at Offest 52 into the file
|
||||
/// <summary>
|
||||
/// Contains the compression level.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This value is stored in bytes (51,52).
|
||||
/// </remarks>
|
||||
private CompressionLevel compression_level;
|
||||
|
||||
/*
|
||||
/// <summary>
|
||||
/// Contains the format flags.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This value is stored in bytes (53,54).
|
||||
/// </remarks>
|
||||
private ushort format_flags;
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Contains the number of audio blocks in one frame.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This value is stored in bytes (55-58).
|
||||
/// </remarks>
|
||||
private uint blocks_per_frame;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the number of audio blocks in the final frame.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This value is stored in bytes (59-62).
|
||||
/// </remarks>
|
||||
private uint final_frame_blocks;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the total number of frames.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This value is stored in bytes (63-66).
|
||||
/// </remarks>
|
||||
private uint total_frames;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the number of bits per sample.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This value is stored in bytes (67,68) and is typically
|
||||
/// 16.
|
||||
/// </remarks>
|
||||
private ushort bits_per_sample;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the number of channels.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This value is stored in bytes (69,70) and is typically
|
||||
/// 1 or 2.
|
||||
/// </remarks>
|
||||
private ushort channels;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the sample rate.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This value is stored in bytes (71-74) and is typically
|
||||
/// 44100.
|
||||
/// </remarks>
|
||||
private uint sample_rate;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the length of the audio stream.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This value is provided by the constructor.
|
||||
/// </remarks>
|
||||
private long stream_length;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Static Fields
|
||||
|
||||
/// <summary>
|
||||
/// The size of a Monkey Audio header.
|
||||
/// </summary>
|
||||
public const uint Size = 76;
|
||||
|
||||
/// <summary>
|
||||
/// The identifier used to recognize a WavPack file.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// "MAC "
|
||||
/// </value>
|
||||
public static readonly ReadOnlyByteVector FileIdentifier =
|
||||
"MAC ";
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="StreamHeader" /> for a specified header block and
|
||||
/// stream length.
|
||||
/// </summary>
|
||||
/// <param name="data">
|
||||
/// A <see cref="ByteVector" /> object containing the stream
|
||||
/// header data.
|
||||
/// </param>
|
||||
/// <param name="streamLength">
|
||||
/// A <see cref="long" /> value containing the length of the
|
||||
/// Monkey Audio stream in bytes.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="data" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
/// <exception cref="CorruptFileException">
|
||||
/// <paramref name="data" /> does not begin with <see
|
||||
/// cref="FileIdentifier" /> or is less than <see cref="Size"
|
||||
/// /> bytes long.
|
||||
/// </exception>
|
||||
public StreamHeader(ByteVector data, long streamLength)
|
||||
{
|
||||
if (data == null)
|
||||
throw new ArgumentNullException("data");
|
||||
|
||||
if (!data.StartsWith(FileIdentifier))
|
||||
throw new CorruptFileException(
|
||||
"Data does not begin with identifier.");
|
||||
|
||||
if (data.Count < Size)
|
||||
throw new CorruptFileException(
|
||||
"Insufficient data in stream header");
|
||||
|
||||
stream_length = streamLength;
|
||||
version = data.Mid (4, 2).ToUShort(false);
|
||||
compression_level = (CompressionLevel) data.Mid(52, 2)
|
||||
.ToUShort(false);
|
||||
// format_flags = data.Mid(54, 2).ToUShort(false);
|
||||
blocks_per_frame = data.Mid(56, 4).ToUInt(false);
|
||||
final_frame_blocks = data.Mid(60, 4).ToUInt(false);
|
||||
total_frames = data.Mid(64, 4).ToUInt(false);
|
||||
bits_per_sample = data.Mid(68, 2).ToUShort(false);
|
||||
channels = data.Mid(70, 2).ToUShort(false);
|
||||
sample_rate = data.Mid(72, 4).ToUInt(false);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the duration of the media represented by the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="TimeSpan" /> containing the duration of the
|
||||
/// media represented by the current instance.
|
||||
/// </value>
|
||||
public TimeSpan Duration {
|
||||
get {
|
||||
if (sample_rate <= 0 || total_frames <= 0)
|
||||
return TimeSpan.Zero;
|
||||
|
||||
return TimeSpan.FromSeconds (
|
||||
(double) ((total_frames - 1) *
|
||||
blocks_per_frame + final_frame_blocks) /
|
||||
(double) sample_rate);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the types of media represented by the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Always <see cref="MediaTypes.Audio" />.
|
||||
/// </value>
|
||||
public MediaTypes MediaTypes {
|
||||
get {return MediaTypes.Audio;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a text description of the media represented by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="string" /> object containing a description
|
||||
/// of the media represented by the current instance.
|
||||
/// </value>
|
||||
public string Description {
|
||||
get {
|
||||
return string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"Monkey's Audio APE Version {0:0.000}",
|
||||
Version);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the bitrate of the audio represented by the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing a bitrate of the
|
||||
/// audio represented by the current instance.
|
||||
/// </value>
|
||||
public int AudioBitrate {
|
||||
get {
|
||||
TimeSpan d = Duration;
|
||||
if (d <= TimeSpan.Zero)
|
||||
return 0;
|
||||
|
||||
return (int) ((stream_length * 8L) /
|
||||
d.TotalSeconds) / 1000;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the sample count of the audio represented by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing the sample count
|
||||
/// of the audio represented by the current instance.
|
||||
/// </value>
|
||||
public long AudioSampleCount
|
||||
{
|
||||
get
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the sample rate of the audio represented by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing the sample rate of
|
||||
/// the audio represented by the current instance.
|
||||
/// </value>
|
||||
public int AudioSampleRate {
|
||||
get {return (int)sample_rate;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of channels in the audio represented by
|
||||
/// the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing the number of
|
||||
/// channels in the audio represented by the current
|
||||
/// instance.
|
||||
/// </value>
|
||||
public int AudioChannels {
|
||||
get {return channels;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the APE version of the audio represented by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="double" /> value containing the APE version
|
||||
/// of the audio represented by the current instance.
|
||||
/// </value>
|
||||
public double Version {
|
||||
get {return (double) version / (double) 1000;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of bits per sample in the audio
|
||||
/// represented by the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing the number of bits
|
||||
/// per sample in the audio represented by the current
|
||||
/// instance.
|
||||
/// </value>
|
||||
public int BitsPerSample {
|
||||
get {return bits_per_sample;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the level of compression used when encoding the
|
||||
/// audio represented by the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="CompressionLevel" /> value indicating the
|
||||
/// level of compression used when encoding the audio
|
||||
/// represented by the current instance.
|
||||
/// </value>
|
||||
public CompressionLevel Compression {
|
||||
get {return compression_level;}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -1,270 +0,0 @@
|
||||
//
|
||||
// ContentDescriptionObject.cs: Provides a representation of an ASF Content
|
||||
// Description object which can be read from and written to disk.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
//
|
||||
// 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.Asf {
|
||||
/// <summary>
|
||||
/// This class extends <see cref="Object" /> to provide a
|
||||
/// representation of an ASF Content Description object which can be
|
||||
/// read from and written to disk.
|
||||
/// </summary>
|
||||
public class ContentDescriptionObject : Object
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Contains the media title.
|
||||
/// </summary>
|
||||
private string title = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the author/performer.
|
||||
/// </summary>
|
||||
private string author = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the copyright information.
|
||||
/// </summary>
|
||||
private string copyright = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the description of the media.
|
||||
/// </summary>
|
||||
private string description = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the rating of the media.
|
||||
/// </summary>
|
||||
private string rating = string.Empty;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="ContentDescriptionObject" /> by reading the
|
||||
/// contents from a specified position in a specified file.
|
||||
/// </summary>
|
||||
/// <param name="file">
|
||||
/// A <see cref="Asf.File" /> object containing the file from
|
||||
/// which the contents of the new instance are to be read.
|
||||
/// </param>
|
||||
/// <param name="position">
|
||||
/// A <see cref="long" /> value specify at what position to
|
||||
/// read the object.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="file" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// <paramref name="position" /> is less than zero or greater
|
||||
/// than the size of the file.
|
||||
/// </exception>
|
||||
/// <exception cref="CorruptFileException">
|
||||
/// The object read from disk does not have the correct GUID
|
||||
/// or smaller than the minimum size.
|
||||
/// </exception>
|
||||
public ContentDescriptionObject (Asf.File file, long position)
|
||||
: base (file, position)
|
||||
{
|
||||
if (Guid != Asf.Guid.AsfContentDescriptionObject)
|
||||
throw new CorruptFileException (
|
||||
"Object GUID incorrect.");
|
||||
|
||||
if (OriginalSize < 34)
|
||||
throw new CorruptFileException (
|
||||
"Object size too small.");
|
||||
|
||||
ushort title_length = file.ReadWord ();
|
||||
ushort author_length = file.ReadWord ();
|
||||
ushort copyright_length = file.ReadWord ();
|
||||
ushort description_length = file.ReadWord ();
|
||||
ushort rating_length = file.ReadWord ();
|
||||
|
||||
title = file.ReadUnicode (title_length);
|
||||
author = file.ReadUnicode (author_length);
|
||||
copyright = file.ReadUnicode (copyright_length);
|
||||
description = file.ReadUnicode (description_length);
|
||||
rating = file.ReadUnicode (rating_length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="ContentDescriptionObject" /> with no contents.
|
||||
/// </summary>
|
||||
public ContentDescriptionObject ()
|
||||
: base (Asf.Guid.AsfContentDescriptionObject)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Region
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the title of the media described by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="string" /> object containing the title of
|
||||
/// the media or <see langword="null" /> if it is not set.
|
||||
/// </value>
|
||||
public string Title {
|
||||
get {return title.Length == 0 ? null : title;}
|
||||
set {
|
||||
title = string.IsNullOrEmpty (value) ?
|
||||
string.Empty : value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the author or performer of the media
|
||||
/// described by the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="string" /> object containing the author of
|
||||
/// the media or <see langword="null" /> if it is not set.
|
||||
/// </value>
|
||||
public string Author {
|
||||
get {return author.Length == 0 ? null : author;}
|
||||
set {
|
||||
author = string.IsNullOrEmpty (value) ?
|
||||
string.Empty : value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the copyright information for the media
|
||||
/// described by the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="string" /> object containing the copyright
|
||||
/// information for the media or <see langword="null" /> if
|
||||
/// it is not set.
|
||||
/// </value>
|
||||
public string Copyright {
|
||||
get {return copyright.Length == 0 ? null : copyright;}
|
||||
set {
|
||||
copyright = string.IsNullOrEmpty (value) ?
|
||||
string.Empty : value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the description of the media described by
|
||||
/// the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="string" /> object containing a description
|
||||
/// of the media or <see langword="null" /> if it is not set.
|
||||
/// </value>
|
||||
public string Description {
|
||||
get {
|
||||
return description.Length == 0 ?
|
||||
null : description;
|
||||
}
|
||||
set {
|
||||
description = string.IsNullOrEmpty (value) ?
|
||||
string.Empty : value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the rating of the media described by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="string" /> object containing a rating of the
|
||||
/// media or <see langword="null" /> if it is not set.
|
||||
/// </value>
|
||||
public string Rating {
|
||||
get {return rating.Length == 0 ? null : rating;}
|
||||
set {
|
||||
rating = string.IsNullOrEmpty (value) ?
|
||||
string.Empty : value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not the current instance is empty.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <see langword="true" /> if all the values are cleared.
|
||||
/// Otherwise <see langword="false" />.
|
||||
/// </value>
|
||||
public bool IsEmpty {
|
||||
get {
|
||||
return title.Length == 0 &&
|
||||
author.Length == 0 &&
|
||||
copyright.Length == 0 &&
|
||||
description.Length == 0 &&
|
||||
rating.Length == 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Region
|
||||
|
||||
/// <summary>
|
||||
/// Renders the current instance as a raw ASF object.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector" /> object containing the
|
||||
/// rendered version of the current instance.
|
||||
/// </returns>
|
||||
public override ByteVector Render ()
|
||||
{
|
||||
ByteVector title_bytes = RenderUnicode (title);
|
||||
ByteVector author_bytes = RenderUnicode (author);
|
||||
ByteVector copyright_bytes = RenderUnicode (copyright);
|
||||
ByteVector description_bytes =
|
||||
RenderUnicode (description);
|
||||
ByteVector rating_bytes = RenderUnicode (rating);
|
||||
|
||||
ByteVector output = RenderWord ((ushort)
|
||||
title_bytes.Count);
|
||||
output.Add (RenderWord ((ushort) author_bytes.Count));
|
||||
output.Add (RenderWord ((ushort) copyright_bytes.Count));
|
||||
output.Add (RenderWord ((ushort)
|
||||
description_bytes.Count));
|
||||
output.Add (RenderWord ((ushort) rating_bytes.Count));
|
||||
output.Add (title_bytes);
|
||||
output.Add (author_bytes);
|
||||
output.Add (copyright_bytes);
|
||||
output.Add (description_bytes);
|
||||
output.Add (rating_bytes);
|
||||
|
||||
return Render (output);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,494 +0,0 @@
|
||||
//
|
||||
// ContentDescriptor.cs: Provides a representation of an ASF Content Descriptor
|
||||
// to be used in combination with ExtendedContentDescriptionObject.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
//
|
||||
// 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.Asf {
|
||||
/// <summary>
|
||||
/// Indicates the type of data stored in a <see
|
||||
/// cref="ContentDescriptor" /> or <see cref="DescriptionRecord" />
|
||||
/// object.
|
||||
/// </summary>
|
||||
public enum DataType {
|
||||
/// <summary>
|
||||
/// The descriptor contains Unicode (UTF-16LE) text.
|
||||
/// </summary>
|
||||
Unicode = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The descriptor contains binary data.
|
||||
/// </summary>
|
||||
Bytes = 1,
|
||||
|
||||
/// <summary>
|
||||
/// The descriptor contains a boolean value.
|
||||
/// </summary>
|
||||
Bool = 2,
|
||||
|
||||
/// <summary>
|
||||
/// The descriptor contains a 4-byte DWORD value.
|
||||
/// </summary>
|
||||
DWord = 3,
|
||||
|
||||
/// <summary>
|
||||
/// The descriptor contains a 8-byte QWORD value.
|
||||
/// </summary>
|
||||
QWord = 4,
|
||||
|
||||
/// <summary>
|
||||
/// The descriptor contains a 2-byte WORD value.
|
||||
/// </summary>
|
||||
Word = 5,
|
||||
|
||||
/// <summary>
|
||||
/// The descriptor contains a 16-byte GUID value.
|
||||
/// </summary>
|
||||
Guid = 6
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This class provides a representation of an ASF Content
|
||||
/// Descriptor to be used in combination with <see
|
||||
/// cref="ExtendedContentDescriptionObject" />.
|
||||
/// </summary>
|
||||
public class ContentDescriptor
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Contains the data type.
|
||||
/// </summary>
|
||||
private DataType type = DataType.Unicode;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the descriptor name.
|
||||
/// </summary>
|
||||
private string name = null;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the string value.
|
||||
/// </summary>
|
||||
private string strValue = null;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the byte value.
|
||||
/// </summary>
|
||||
private ByteVector byteValue = null;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the long value.
|
||||
/// </summary>
|
||||
private ulong longValue = 0;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="ContentDescriptor" /> with a specified name and
|
||||
/// and value.
|
||||
/// </summary>
|
||||
/// <param name="name">
|
||||
/// A <see cref="string" /> object containing the name of the
|
||||
/// new instance.
|
||||
/// </param>
|
||||
/// <param name="value">
|
||||
/// A <see cref="string" /> object containing the value for
|
||||
/// the new instance.
|
||||
/// </param>
|
||||
public ContentDescriptor (string name, string value)
|
||||
{
|
||||
this.name = name;
|
||||
this.strValue = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="ContentDescriptor" /> with a specified name and
|
||||
/// and value.
|
||||
/// </summary>
|
||||
/// <param name="name">
|
||||
/// A <see cref="string" /> object containing the name of the
|
||||
/// new instance.
|
||||
/// </param>
|
||||
/// <param name="value">
|
||||
/// A <see cref="ByteVector" /> object containing the value
|
||||
/// for the new instance.
|
||||
/// </param>
|
||||
public ContentDescriptor (string name, ByteVector value)
|
||||
{
|
||||
this.name = name;
|
||||
this.type = DataType.Bytes;
|
||||
this.byteValue = new ByteVector (value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="ContentDescriptor" /> with a specified name and
|
||||
/// and value.
|
||||
/// </summary>
|
||||
/// <param name="name">
|
||||
/// A <see cref="string" /> object containing the name of the
|
||||
/// new instance.
|
||||
/// </param>
|
||||
/// <param name="value">
|
||||
/// A <see cref="uint" /> value containing the value
|
||||
/// for the new instance.
|
||||
/// </param>
|
||||
public ContentDescriptor (string name, uint value)
|
||||
{
|
||||
this.name = name;
|
||||
this.type = DataType.DWord;
|
||||
this.longValue = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="ContentDescriptor" /> with a specified name and
|
||||
/// and value.
|
||||
/// </summary>
|
||||
/// <param name="name">
|
||||
/// A <see cref="string" /> object containing the name of the
|
||||
/// new instance.
|
||||
/// </param>
|
||||
/// <param name="value">
|
||||
/// A <see cref="ulong" /> value containing the value
|
||||
/// for the new instance.
|
||||
/// </param>
|
||||
public ContentDescriptor (string name, ulong value)
|
||||
{
|
||||
this.name = name;
|
||||
this.type = DataType.QWord;
|
||||
this.longValue = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="ContentDescriptor" /> with a specified name and
|
||||
/// and value.
|
||||
/// </summary>
|
||||
/// <param name="name">
|
||||
/// A <see cref="string" /> object containing the name of the
|
||||
/// new instance.
|
||||
/// </param>
|
||||
/// <param name="value">
|
||||
/// A <see cref="ushort" /> value containing the value
|
||||
/// for the new instance.
|
||||
/// </param>
|
||||
public ContentDescriptor (string name, ushort value)
|
||||
{
|
||||
this.name = name;
|
||||
this.type = DataType.Word;
|
||||
this.longValue = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="ContentDescriptor" /> with a specified name and
|
||||
/// and value.
|
||||
/// </summary>
|
||||
/// <param name="name">
|
||||
/// A <see cref="string" /> object containing the name of the
|
||||
/// new instance.
|
||||
/// </param>
|
||||
/// <param name="value">
|
||||
/// A <see cref="bool" /> value containing the value
|
||||
/// for the new instance.
|
||||
/// </param>
|
||||
public ContentDescriptor (string name, bool value)
|
||||
{
|
||||
this.name = name;
|
||||
this.type = DataType.Bool;
|
||||
this.longValue = value ? 1uL : 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="ContentDescriptor" /> by reading its contents from
|
||||
/// a file.
|
||||
/// </summary>
|
||||
/// <param name="file">
|
||||
/// A <see cref="Asf.File" /> object to read the raw ASF
|
||||
/// Description Record from.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="file" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
/// <exception cref="CorruptFileException">
|
||||
/// A valid descriptor could not be read.
|
||||
/// </exception>
|
||||
/// <remarks>
|
||||
/// <paramref name="file" /> must be at a seek position at
|
||||
/// which the descriptor can be read.
|
||||
/// </remarks>
|
||||
protected internal ContentDescriptor (Asf.File file)
|
||||
{
|
||||
if (file == null)
|
||||
throw new ArgumentNullException ("file");
|
||||
|
||||
if (!Parse (file))
|
||||
throw new CorruptFileException (
|
||||
"Failed to parse content descriptor.");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="string" /> object containing the name of the
|
||||
/// current instance.
|
||||
/// </value>
|
||||
public string Name {
|
||||
get {return name;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of data contained in the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="DataType" /> value indicating type of data
|
||||
/// contained in the current instance.
|
||||
/// </value>
|
||||
public DataType Type {
|
||||
get {return type;}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Gets a string representation of the current instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="string" /> object containing the value of
|
||||
/// the current instance.
|
||||
/// </returns>
|
||||
public override string ToString ()
|
||||
{
|
||||
if (type == DataType.Unicode)
|
||||
return strValue;
|
||||
|
||||
if (type == DataType.Bytes)
|
||||
return byteValue.ToString (StringType.UTF16LE);
|
||||
|
||||
return longValue.ToString ();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the binary contents of the current instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector" /> object containing the
|
||||
/// contents of the current instance, or <see langword="null"
|
||||
/// /> if <see cref="Type" /> is unequal to <see
|
||||
/// cref="DataType.Bytes" />.
|
||||
/// </returns>
|
||||
public ByteVector ToByteVector ()
|
||||
{
|
||||
return byteValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the boolean value contained in the current instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="bool" /> value containing the value of the
|
||||
/// current instance.
|
||||
/// </returns>
|
||||
public bool ToBool ()
|
||||
{
|
||||
return longValue != 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the DWORD value contained in the current instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="uint" /> value containing the value of the
|
||||
/// current instance.
|
||||
/// </returns>
|
||||
public uint ToDWord ()
|
||||
{
|
||||
uint value;
|
||||
if (type == DataType.Unicode && strValue != null &&
|
||||
uint.TryParse (strValue, out value))
|
||||
return value;
|
||||
|
||||
return (uint) longValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the QWORD value contained in the current instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="ulong" /> value containing the value of the
|
||||
/// current instance.
|
||||
/// </returns>
|
||||
public ulong ToQWord ()
|
||||
{
|
||||
ulong value;
|
||||
if (type == DataType.Unicode && strValue != null &&
|
||||
ulong.TryParse (strValue, out value))
|
||||
return value;
|
||||
|
||||
return longValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the WORD value contained in the current instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="ushort" /> value containing the value of the
|
||||
/// current instance.
|
||||
/// </returns>
|
||||
public ushort ToWord ()
|
||||
{
|
||||
ushort value;
|
||||
if (type == DataType.Unicode && strValue != null &&
|
||||
ushort.TryParse (strValue, out value))
|
||||
return value;
|
||||
|
||||
return (ushort) longValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders the current instance as a raw ASF Description
|
||||
/// Record.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector" /> object containing the
|
||||
/// rendered version of the current instance.
|
||||
/// </returns>
|
||||
public ByteVector Render ()
|
||||
{
|
||||
ByteVector value = null;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case DataType.Unicode:
|
||||
value = Object.RenderUnicode (strValue);
|
||||
break;
|
||||
case DataType.Bytes:
|
||||
value = byteValue;
|
||||
break;
|
||||
case DataType.Bool:
|
||||
case DataType.DWord:
|
||||
value = Object.RenderDWord ((uint) longValue);
|
||||
break;
|
||||
case DataType.QWord:
|
||||
value = Object.RenderQWord (longValue);
|
||||
break;
|
||||
case DataType.Word:
|
||||
value = Object.RenderWord ((ushort) longValue);
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
ByteVector name = Object.RenderUnicode (this.name);
|
||||
|
||||
ByteVector output = new ByteVector ();
|
||||
output.Add (Object.RenderWord ((ushort) name.Count));
|
||||
output.Add (name);
|
||||
output.Add (Object.RenderWord ((ushort) type));
|
||||
output.Add (Object.RenderWord ((ushort) value.Count));
|
||||
output.Add (value);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
/// <summary>
|
||||
/// Populates the current instance by reading in the contents
|
||||
/// from a file.
|
||||
/// </summary>
|
||||
/// <param name="file">
|
||||
/// A <see cref="Asf.File" /> object to read the raw ASF
|
||||
/// Content Descriptor from.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// <see langword="true" /> if the data was read correctly.
|
||||
/// Otherwise <see langword="false" />.
|
||||
/// </returns>
|
||||
protected bool Parse (Asf.File file)
|
||||
{
|
||||
int name_count = file.ReadWord ();
|
||||
name = file.ReadUnicode (name_count);
|
||||
|
||||
type = (DataType) file.ReadWord ();
|
||||
|
||||
int value_count = file.ReadWord ();
|
||||
switch (type)
|
||||
{
|
||||
case DataType.Word:
|
||||
longValue = file.ReadWord ();
|
||||
break;
|
||||
|
||||
case DataType.Bool:
|
||||
longValue = file.ReadDWord ();
|
||||
break;
|
||||
|
||||
case DataType.DWord:
|
||||
longValue = file.ReadDWord ();
|
||||
break;
|
||||
|
||||
case DataType.QWord:
|
||||
longValue = file.ReadQWord ();
|
||||
break;
|
||||
|
||||
case DataType.Unicode:
|
||||
strValue = file.ReadUnicode (value_count);
|
||||
break;
|
||||
|
||||
case DataType.Bytes:
|
||||
byteValue = file.ReadBlock (value_count);
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,617 +0,0 @@
|
||||
//
|
||||
// DescriptionRecord.cs: Provides a representation of an ASF Description Record
|
||||
// to be used in combination with MetadataLibaryObject.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
//
|
||||
// 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.Asf {
|
||||
/// <summary>
|
||||
/// This class provides a representation of an ASF Description Record
|
||||
/// to be used in combination with <see cref="MetadataLibraryObject"
|
||||
/// />.
|
||||
/// </summary>
|
||||
public class DescriptionRecord
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Contains the data type.
|
||||
/// </summary>
|
||||
private DataType type = DataType.Unicode;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the language list index.
|
||||
/// </summary>
|
||||
private ushort lang_list_index = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the stream number.
|
||||
/// </summary>
|
||||
private ushort stream_number = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the record name.
|
||||
/// </summary>
|
||||
private string name = null;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the string value.
|
||||
/// </summary>
|
||||
private string strValue = null;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the byte value.
|
||||
/// </summary>
|
||||
private ByteVector byteValue = null;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the long value.
|
||||
/// </summary>
|
||||
private ulong longValue = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the GUID value.
|
||||
/// </summary>
|
||||
private System.Guid guidValue = System.Guid.Empty;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="DescriptionRecord" /> with a specified language,
|
||||
/// stream, name, and value.
|
||||
/// </summary>
|
||||
/// <param name="languageListIndex">
|
||||
/// A <see cref="ushort" /> value containing the language
|
||||
/// list index of the new instance.
|
||||
/// </param>
|
||||
/// <param name="streamNumber">
|
||||
/// A <see cref="ushort" /> value containing the stream
|
||||
/// number of the new instance.
|
||||
/// </param>
|
||||
/// <param name="name">
|
||||
/// A <see cref="string" /> object containing the name of the
|
||||
/// new instance.
|
||||
/// </param>
|
||||
/// <param name="value">
|
||||
/// A <see cref="string" /> object containing the value for
|
||||
/// the new instance.
|
||||
/// </param>
|
||||
public DescriptionRecord (ushort languageListIndex,
|
||||
ushort streamNumber, string name,
|
||||
string value)
|
||||
{
|
||||
this.lang_list_index = languageListIndex;
|
||||
this.stream_number = streamNumber;
|
||||
this.name = name;
|
||||
this.strValue = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="DescriptionRecord" /> with a specified language,
|
||||
/// stream, name, and value.
|
||||
/// </summary>
|
||||
/// <param name="languageListIndex">
|
||||
/// A <see cref="ushort" /> value containing the language
|
||||
/// list index of the new instance.
|
||||
/// </param>
|
||||
/// <param name="streamNumber">
|
||||
/// A <see cref="ushort" /> value containing the stream
|
||||
/// number of the new instance.
|
||||
/// </param>
|
||||
/// <param name="name">
|
||||
/// A <see cref="string" /> object containing the name of the
|
||||
/// new instance.
|
||||
/// </param>
|
||||
/// <param name="value">
|
||||
/// A <see cref="ByteVector" /> object containing the value
|
||||
/// for the new instance.
|
||||
/// </param>
|
||||
public DescriptionRecord (ushort languageListIndex,
|
||||
ushort streamNumber, string name,
|
||||
ByteVector value)
|
||||
{
|
||||
this.lang_list_index = languageListIndex;
|
||||
this.stream_number = streamNumber;
|
||||
this.name = name;
|
||||
this.type = DataType.Bytes;
|
||||
this.byteValue = new ByteVector (value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="DescriptionRecord" /> with a specified language,
|
||||
/// stream, name, and value.
|
||||
/// </summary>
|
||||
/// <param name="languageListIndex">
|
||||
/// A <see cref="ushort" /> value containing the language
|
||||
/// list index of the new instance.
|
||||
/// </param>
|
||||
/// <param name="streamNumber">
|
||||
/// A <see cref="ushort" /> value containing the stream
|
||||
/// number of the new instance.
|
||||
/// </param>
|
||||
/// <param name="name">
|
||||
/// A <see cref="string" /> object containing the name of the
|
||||
/// new instance.
|
||||
/// </param>
|
||||
/// <param name="value">
|
||||
/// A <see cref="uint" /> value containing the value
|
||||
/// for the new instance.
|
||||
/// </param>
|
||||
public DescriptionRecord (ushort languageListIndex,
|
||||
ushort streamNumber, string name,
|
||||
uint value)
|
||||
{
|
||||
this.lang_list_index = languageListIndex;
|
||||
this.stream_number = streamNumber;
|
||||
this.name = name;
|
||||
this.type = DataType.DWord;
|
||||
this.longValue = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="DescriptionRecord" /> with a specified language,
|
||||
/// stream, name, and value.
|
||||
/// </summary>
|
||||
/// <param name="languageListIndex">
|
||||
/// A <see cref="ushort" /> value containing the language
|
||||
/// list index of the new instance.
|
||||
/// </param>
|
||||
/// <param name="streamNumber">
|
||||
/// A <see cref="ushort" /> value containing the stream
|
||||
/// number of the new instance.
|
||||
/// </param>
|
||||
/// <param name="name">
|
||||
/// A <see cref="string" /> object containing the name of the
|
||||
/// new instance.
|
||||
/// </param>
|
||||
/// <param name="value">
|
||||
/// A <see cref="ulong" /> value containing the value
|
||||
/// for the new instance.
|
||||
/// </param>
|
||||
public DescriptionRecord (ushort languageListIndex,
|
||||
ushort streamNumber, string name,
|
||||
ulong value)
|
||||
{
|
||||
this.lang_list_index = languageListIndex;
|
||||
this.stream_number = streamNumber;
|
||||
this.name = name;
|
||||
this.type = DataType.QWord;
|
||||
this.longValue = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="DescriptionRecord" /> with a specified language,
|
||||
/// stream, name, and value.
|
||||
/// </summary>
|
||||
/// <param name="languageListIndex">
|
||||
/// A <see cref="ushort" /> value containing the language
|
||||
/// list index of the new instance.
|
||||
/// </param>
|
||||
/// <param name="streamNumber">
|
||||
/// A <see cref="ushort" /> value containing the stream
|
||||
/// number of the new instance.
|
||||
/// </param>
|
||||
/// <param name="name">
|
||||
/// A <see cref="string" /> object containing the name of the
|
||||
/// new instance.
|
||||
/// </param>
|
||||
/// <param name="value">
|
||||
/// A <see cref="ushort" /> value containing the value
|
||||
/// for the new instance.
|
||||
/// </param>
|
||||
public DescriptionRecord (ushort languageListIndex,
|
||||
ushort streamNumber, string name,
|
||||
ushort value)
|
||||
{
|
||||
this.lang_list_index = languageListIndex;
|
||||
this.stream_number = streamNumber;
|
||||
this.name = name;
|
||||
this.type = DataType.Word;
|
||||
this.longValue = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="DescriptionRecord" /> with a specified language,
|
||||
/// stream, name, and value.
|
||||
/// </summary>
|
||||
/// <param name="languageListIndex">
|
||||
/// A <see cref="ushort" /> value containing the language
|
||||
/// list index of the new instance.
|
||||
/// </param>
|
||||
/// <param name="streamNumber">
|
||||
/// A <see cref="ushort" /> value containing the stream
|
||||
/// number of the new instance.
|
||||
/// </param>
|
||||
/// <param name="name">
|
||||
/// A <see cref="string" /> object containing the name of the
|
||||
/// new instance.
|
||||
/// </param>
|
||||
/// <param name="value">
|
||||
/// A <see cref="bool" /> value containing the value
|
||||
/// for the new instance.
|
||||
/// </param>
|
||||
public DescriptionRecord (ushort languageListIndex,
|
||||
ushort streamNumber, string name,
|
||||
bool value)
|
||||
{
|
||||
this.lang_list_index = languageListIndex;
|
||||
this.stream_number = streamNumber;
|
||||
this.name = name;
|
||||
this.type = DataType.Bool;
|
||||
this.longValue = value ? 1uL : 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="DescriptionRecord" /> with a specified language,
|
||||
/// stream, name, and value.
|
||||
/// </summary>
|
||||
/// <param name="languageListIndex">
|
||||
/// A <see cref="ushort" /> value containing the language
|
||||
/// list index of the new instance.
|
||||
/// </param>
|
||||
/// <param name="streamNumber">
|
||||
/// A <see cref="ushort" /> value containing the stream
|
||||
/// number of the new instance.
|
||||
/// </param>
|
||||
/// <param name="name">
|
||||
/// A <see cref="string" /> object containing the name of the
|
||||
/// new instance.
|
||||
/// </param>
|
||||
/// <param name="value">
|
||||
/// A <see cref="System.Guid" /> value containing the value
|
||||
/// for the new instance.
|
||||
/// </param>
|
||||
public DescriptionRecord (ushort languageListIndex,
|
||||
ushort streamNumber, string name,
|
||||
System.Guid value)
|
||||
{
|
||||
this.lang_list_index = languageListIndex;
|
||||
this.stream_number = streamNumber;
|
||||
this.name = name;
|
||||
this.type = DataType.Guid;
|
||||
this.guidValue = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="DescriptionRecord" /> by reading its contents from
|
||||
/// a file.
|
||||
/// </summary>
|
||||
/// <param name="file">
|
||||
/// A <see cref="Asf.File" /> object to read the raw ASF
|
||||
/// Description Record from.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="file" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
/// <exception cref="CorruptFileException">
|
||||
/// A valid record could not be read.
|
||||
/// </exception>
|
||||
/// <remarks>
|
||||
/// <paramref name="file" /> must be at a seek position at
|
||||
/// which the record can be read.
|
||||
/// </remarks>
|
||||
protected internal DescriptionRecord (Asf.File file)
|
||||
{
|
||||
if (file == null)
|
||||
throw new ArgumentNullException ("file");
|
||||
|
||||
if (!Parse (file))
|
||||
throw new CorruptFileException (
|
||||
"Failed to parse description record.");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the index of the language associated with the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="ushort" /> value containing the index of the
|
||||
/// language associated with the current instance.
|
||||
/// </value>
|
||||
public ushort LanguageListIndex {
|
||||
get {return lang_list_index;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the index of the stream associated with the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="ushort" /> value containing the index of the
|
||||
/// stream associated with the current instance.
|
||||
/// </value>
|
||||
public ushort StreamNumber {
|
||||
get {return stream_number;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="string" /> object containing the name of the
|
||||
/// current instance.
|
||||
/// </value>
|
||||
public string Name {
|
||||
get {return name;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of data contained in the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="DataType" /> value indicating type of data
|
||||
/// contained in the current instance.
|
||||
/// </value>
|
||||
public DataType Type {
|
||||
get {return type;}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Gets a string representation of the current instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="string" /> object containing the value of
|
||||
/// the current instance.
|
||||
/// </returns>
|
||||
public override string ToString ()
|
||||
{
|
||||
if (type == DataType.Unicode)
|
||||
return strValue;
|
||||
|
||||
if (type == DataType.Bytes)
|
||||
return byteValue.ToString (StringType.UTF16LE);
|
||||
|
||||
return longValue.ToString ();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the binary contents of the current instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector" /> object containing the
|
||||
/// contents of the current instance, or <see langword="null"
|
||||
/// /> if <see cref="Type" /> is unequal to <see
|
||||
/// cref="DataType.Bytes" />.
|
||||
/// </returns>
|
||||
public ByteVector ToByteVector ()
|
||||
{
|
||||
return byteValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the boolean value contained in the current instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="bool" /> value containing the value of the
|
||||
/// current instance.
|
||||
/// </returns>
|
||||
public bool ToBool ()
|
||||
{
|
||||
return longValue != 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the DWORD value contained in the current instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="uint" /> value containing the value of the
|
||||
/// current instance.
|
||||
/// </returns>
|
||||
public uint ToDWord ()
|
||||
{
|
||||
uint value;
|
||||
if (type == DataType.Unicode && strValue != null &&
|
||||
uint.TryParse (strValue, out value))
|
||||
return value;
|
||||
|
||||
return (uint) longValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the QWORD value contained in the current instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="ulong" /> value containing the value of the
|
||||
/// current instance.
|
||||
/// </returns>
|
||||
public ulong ToQWord ()
|
||||
{
|
||||
ulong value;
|
||||
if (type == DataType.Unicode && strValue != null &&
|
||||
ulong.TryParse (strValue, out value))
|
||||
return value;
|
||||
|
||||
return longValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the WORD value contained in the current instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="ushort" /> value containing the value of the
|
||||
/// current instance.
|
||||
/// </returns>
|
||||
public ushort ToWord ()
|
||||
{
|
||||
ushort value;
|
||||
if (type == DataType.Unicode && strValue != null &&
|
||||
ushort.TryParse (strValue, out value))
|
||||
return value;
|
||||
|
||||
return (ushort) longValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the GUID value contained in the current instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="System.Guid" /> value containing the value
|
||||
/// of the current instance.
|
||||
/// </returns>
|
||||
public System.Guid ToGuid ()
|
||||
{
|
||||
return guidValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders the current instance as a raw ASF Description
|
||||
/// Record.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector" /> object containing the
|
||||
/// rendered version of the current instance.
|
||||
/// </returns>
|
||||
public ByteVector Render ()
|
||||
{
|
||||
ByteVector value = null;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case DataType.Unicode:
|
||||
value = Object.RenderUnicode (strValue);
|
||||
break;
|
||||
case DataType.Bytes:
|
||||
value = byteValue;
|
||||
break;
|
||||
case DataType.Bool:
|
||||
case DataType.DWord:
|
||||
value = Object.RenderDWord ((uint) longValue);
|
||||
break;
|
||||
case DataType.QWord:
|
||||
value = Object.RenderQWord (longValue);
|
||||
break;
|
||||
case DataType.Word:
|
||||
value = Object.RenderWord ((ushort) longValue);
|
||||
break;
|
||||
case DataType.Guid:
|
||||
value = guidValue.ToByteArray ();
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
ByteVector name = Object.RenderUnicode (this.name);
|
||||
|
||||
ByteVector output = new ByteVector ();
|
||||
output.Add (Object.RenderWord (lang_list_index));
|
||||
output.Add (Object.RenderWord (stream_number));
|
||||
output.Add (Object.RenderWord ((ushort) name.Count));
|
||||
output.Add (Object.RenderWord ((ushort) type));
|
||||
output.Add (Object.RenderDWord ((uint) value.Count));
|
||||
output.Add (name);
|
||||
output.Add (value);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
/// <summary>
|
||||
/// Populates the current instance by reading in the contents
|
||||
/// from a file.
|
||||
/// </summary>
|
||||
/// <param name="file">
|
||||
/// A <see cref="Asf.File" /> object to read the raw ASF
|
||||
/// Description Record from.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// <see langword="true" /> if the data was read correctly.
|
||||
/// Otherwise <see langword="false" />.
|
||||
/// </returns>
|
||||
protected bool Parse (Asf.File file)
|
||||
{
|
||||
// Field name Field type Size (bits)
|
||||
// Language List Index WORD 16
|
||||
// Stream Number WORD 16
|
||||
// Name Length WORD 16
|
||||
// Data Type WORD 16
|
||||
// Data Length DWORD 32
|
||||
// Name WCHAR varies
|
||||
// Data See below varies
|
||||
|
||||
lang_list_index = file.ReadWord ();
|
||||
stream_number = file.ReadWord ();
|
||||
ushort name_length = file.ReadWord ();
|
||||
type = (DataType) file.ReadWord ();
|
||||
int data_length = (int) file.ReadDWord ();
|
||||
name = file.ReadUnicode (name_length);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case DataType.Word:
|
||||
longValue = file.ReadWord ();
|
||||
break;
|
||||
case DataType.Bool:
|
||||
case DataType.DWord:
|
||||
longValue = file.ReadDWord ();
|
||||
break;
|
||||
case DataType.QWord:
|
||||
longValue = file.ReadQWord ();
|
||||
break;
|
||||
case DataType.Unicode:
|
||||
strValue = file.ReadUnicode (data_length);
|
||||
break;
|
||||
case DataType.Bytes:
|
||||
byteValue = file.ReadBlock (data_length);
|
||||
break;
|
||||
case DataType.Guid:
|
||||
guidValue = file.ReadGuid ();
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,276 +0,0 @@
|
||||
//
|
||||
// ExtendedContentDescriptionObject.cs: Provides a representation of an ASF
|
||||
// Extended Content Description object which can be read from and written to
|
||||
// disk.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
//
|
||||
// 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.Asf {
|
||||
/// <summary>
|
||||
/// This class extends <see cref="Object" /> to provide a
|
||||
/// representation of an ASF Extended Content Description object
|
||||
/// which can be read from and written to disk.
|
||||
/// </summary>
|
||||
public class ExtendedContentDescriptionObject : Object,
|
||||
IEnumerable<ContentDescriptor>
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Contains the content descriptors.
|
||||
/// </summary>
|
||||
private List<ContentDescriptor> descriptors =
|
||||
new List<ContentDescriptor> ();
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="ExtendedContentDescriptionObject" /> by reading the
|
||||
/// contents from a specified position in a specified file.
|
||||
/// </summary>
|
||||
/// <param name="file">
|
||||
/// A <see cref="Asf.File" /> object containing the file from
|
||||
/// which the contents of the new instance are to be read.
|
||||
/// </param>
|
||||
/// <param name="position">
|
||||
/// A <see cref="long" /> value specify at what position to
|
||||
/// read the object.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="file" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// <paramref name="position" /> is less than zero or greater
|
||||
/// than the size of the file.
|
||||
/// </exception>
|
||||
/// <exception cref="CorruptFileException">
|
||||
/// The object read from disk does not have the correct GUID
|
||||
/// or smaller than the minimum size.
|
||||
/// </exception>
|
||||
public ExtendedContentDescriptionObject (Asf.File file,
|
||||
long position)
|
||||
: base (file, position)
|
||||
{
|
||||
if (!Guid.Equals (
|
||||
Asf.Guid.AsfExtendedContentDescriptionObject))
|
||||
throw new CorruptFileException (
|
||||
"Object GUID incorrect.");
|
||||
|
||||
if (OriginalSize < 26)
|
||||
throw new CorruptFileException (
|
||||
"Object size too small.");
|
||||
|
||||
ushort count = file.ReadWord ();
|
||||
|
||||
for (ushort i = 0; i < count; i ++)
|
||||
AddDescriptor (new ContentDescriptor (file));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="ExtendedContentDescriptionObject" /> with no
|
||||
/// contents.
|
||||
/// </summary>
|
||||
public ExtendedContentDescriptionObject ()
|
||||
: base (Asf.Guid.AsfExtendedContentDescriptionObject)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not the current instance is empty.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <see langword="true" /> if the current instance doesn't
|
||||
/// contain any <see cref="ContentDescriptor" /> objects.
|
||||
/// Otherwise <see langword="false" />.
|
||||
/// </value>
|
||||
public bool IsEmpty {
|
||||
get {return descriptors.Count == 0;}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Renders the current instance as a raw ASF object.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector" /> object containing the
|
||||
/// rendered version of the current instance.
|
||||
/// </returns>
|
||||
public override ByteVector Render ()
|
||||
{
|
||||
ByteVector output = new ByteVector ();
|
||||
ushort count = 0;
|
||||
|
||||
foreach (ContentDescriptor desc in descriptors) {
|
||||
count ++;
|
||||
output.Add (desc.Render ());
|
||||
}
|
||||
|
||||
return Render (RenderWord (count) + output);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes all descriptors with a given name from the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <param name="name">
|
||||
/// A <see cref="string" /> object containing the name of the
|
||||
/// descriptors to be removed.
|
||||
/// </param>
|
||||
public void RemoveDescriptors (string name)
|
||||
{
|
||||
for (int i = descriptors.Count - 1; i >= 0; i --)
|
||||
if (name == descriptors [i].Name)
|
||||
descriptors.RemoveAt (i);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all descriptors with any of a collection of names
|
||||
/// from the current instance.
|
||||
/// </summary>
|
||||
/// <param name="names">
|
||||
/// A <see cref="string[]" /> containing the names of the
|
||||
/// descriptors to be retrieved.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="names" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
/// <returns>
|
||||
/// A <see cref="T:System.Collections.Generic.IEnumerable`1" /> object enumerating
|
||||
/// through the <see cref="ContentDescriptor" /> objects
|
||||
/// retrieved from the current instance.
|
||||
/// </returns>
|
||||
public IEnumerable<ContentDescriptor> GetDescriptors (params string [] names)
|
||||
{
|
||||
if (names == null)
|
||||
throw new ArgumentNullException ("names");
|
||||
|
||||
foreach (string name in names)
|
||||
foreach (ContentDescriptor desc in descriptors)
|
||||
if (desc.Name == name)
|
||||
yield return desc;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a descriptor to the current instance.
|
||||
/// </summary>
|
||||
/// <param name="descriptor">
|
||||
/// A <see cref="ContentDescriptor" /> object to add to the
|
||||
/// current instance.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="descriptor" /> is <see langword="null"
|
||||
/// />.
|
||||
/// </exception>
|
||||
public void AddDescriptor (ContentDescriptor descriptor)
|
||||
{
|
||||
if (descriptor == null)
|
||||
throw new ArgumentNullException ("descriptor");
|
||||
|
||||
descriptors.Add (descriptor);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the a collection of desciptors for a given name,
|
||||
/// removing the existing matching records.
|
||||
/// </summary>
|
||||
/// <param name="name">
|
||||
/// A <see cref="string" /> object containing the name of the
|
||||
/// descriptors to be added.
|
||||
/// </param>
|
||||
/// <param name="descriptors">
|
||||
/// A <see cref="ContentDescriptor[]" /> containing
|
||||
/// descriptors to add to the new instance.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="name" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
/// <remarks>
|
||||
/// All added entries in <paramref name="descriptors" />
|
||||
/// should match <paramref name="name" /> but it is not
|
||||
/// verified by the method. The descriptors will be added
|
||||
/// with their own names and not the one provided in this
|
||||
/// method, which are used for removing existing values and
|
||||
/// determining where to position the new objects.
|
||||
/// </remarks>
|
||||
public void SetDescriptors (string name,
|
||||
params ContentDescriptor [] descriptors)
|
||||
{
|
||||
if (name == null)
|
||||
throw new ArgumentNullException ("name");
|
||||
|
||||
int position = this.descriptors.Count;
|
||||
for (int i = this.descriptors.Count - 1; i >= 0; i --) {
|
||||
if (name == this.descriptors [i].Name) {
|
||||
this.descriptors.RemoveAt (i);
|
||||
position = i;
|
||||
}
|
||||
}
|
||||
this.descriptors.InsertRange (position, descriptors);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region IEnumerable
|
||||
|
||||
/// <summary>
|
||||
/// Gets an enumerator for enumerating through the content
|
||||
/// descriptors.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="T:System.Collections.IEnumerator`1" /> for
|
||||
/// enumerating through the content descriptors.
|
||||
/// </returns>
|
||||
public IEnumerator<ContentDescriptor> GetEnumerator ()
|
||||
{
|
||||
return descriptors.GetEnumerator ();
|
||||
}
|
||||
|
||||
System.Collections.IEnumerator
|
||||
System.Collections.IEnumerable.GetEnumerator ()
|
||||
{
|
||||
return descriptors.GetEnumerator ();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,431 +0,0 @@
|
||||
//
|
||||
// File.cs: Provides tagging and properties support for Microsoft's ASF files.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
//
|
||||
// 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.Asf {
|
||||
/// <summary>
|
||||
/// This class extends <see cref="TagLib.File" /> to provide tagging
|
||||
/// and properties support for Microsoft's ASF files.
|
||||
/// </summary>
|
||||
[SupportedMimeType("taglib/wma", "wma")]
|
||||
[SupportedMimeType("taglib/wmv", "wmv")]
|
||||
[SupportedMimeType("taglib/asf", "asf")]
|
||||
[SupportedMimeType("audio/x-ms-wma")]
|
||||
[SupportedMimeType("audio/x-ms-asf")]
|
||||
[SupportedMimeType("video/x-ms-asf")]
|
||||
public class File : TagLib.File
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Contains the file's tag.
|
||||
/// </summary>
|
||||
private Asf.Tag asf_tag = null;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the file's properties.
|
||||
/// </summary>
|
||||
private Properties properties = null;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="File" /> for a specified path in the local file
|
||||
/// system and specified read style.
|
||||
/// </summary>
|
||||
/// <param name="path">
|
||||
/// A <see cref="string" /> object containing the path of the
|
||||
/// file to use in the new instance.
|
||||
/// </param>
|
||||
/// <param name="propertiesStyle">
|
||||
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||
/// of accuracy to read the media properties, or <see
|
||||
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="path" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public File (string path, ReadStyle propertiesStyle)
|
||||
: base (path)
|
||||
{
|
||||
Read (propertiesStyle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="File" /> for a specified path in the local file
|
||||
/// system with an average read style.
|
||||
/// </summary>
|
||||
/// <param name="path">
|
||||
/// A <see cref="string" /> object containing the path of the
|
||||
/// file to use in the new instance.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="path" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public File (string path) : this (path, ReadStyle.Average)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="File" /> for a specified file abstraction and
|
||||
/// specified read style.
|
||||
/// </summary>
|
||||
/// <param name="abstraction">
|
||||
/// A <see cref="IFileAbstraction" /> object to use when
|
||||
/// reading from and writing to the file.
|
||||
/// </param>
|
||||
/// <param name="propertiesStyle">
|
||||
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||
/// of accuracy to read the media properties, or <see
|
||||
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="abstraction" /> is <see langword="null"
|
||||
/// />.
|
||||
/// </exception>
|
||||
public File (File.IFileAbstraction abstraction,
|
||||
ReadStyle propertiesStyle) : base (abstraction)
|
||||
{
|
||||
Read (propertiesStyle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="File" /> for a specified file abstraction with an
|
||||
/// average read style.
|
||||
/// </summary>
|
||||
/// <param name="abstraction">
|
||||
/// A <see cref="IFileAbstraction" /> object to use when
|
||||
/// reading from and writing to the file.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="abstraction" /> is <see langword="null"
|
||||
/// />.
|
||||
/// </exception>
|
||||
public File (File.IFileAbstraction abstraction)
|
||||
: this (abstraction, ReadStyle.Average)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets a abstract representation of all tags stored in the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="TagLib.Tag" /> object representing all tags
|
||||
/// stored in the current instance.
|
||||
/// </value>
|
||||
public override TagLib.Tag Tag {
|
||||
get {return asf_tag;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the media properties of the file represented by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="TagLib.Properties" /> object containing the
|
||||
/// media properties of the file represented by the current
|
||||
/// instance.
|
||||
/// </value>
|
||||
public override TagLib.Properties Properties {
|
||||
get {return properties;}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Saves the changes made in the current instance to the
|
||||
/// file it represents.
|
||||
/// </summary>
|
||||
public override void Save ()
|
||||
{
|
||||
Mode = AccessMode.Write;
|
||||
try {
|
||||
HeaderObject header = new HeaderObject (this, 0);
|
||||
|
||||
if (asf_tag == null) {
|
||||
header.RemoveContentDescriptors ();
|
||||
TagTypesOnDisk &= ~ TagTypes.Asf;
|
||||
} else {
|
||||
TagTypesOnDisk |= TagTypes.Asf;
|
||||
header.AddUniqueObject (
|
||||
asf_tag.ContentDescriptionObject);
|
||||
header.AddUniqueObject (
|
||||
asf_tag.ExtendedContentDescriptionObject);
|
||||
header.Extension.AddUniqueObject (
|
||||
asf_tag.MetadataLibraryObject);
|
||||
}
|
||||
|
||||
ByteVector output = header.Render ();
|
||||
long diff = output.Count - (long) header.OriginalSize;
|
||||
Insert (output, 0, (long) header.OriginalSize);
|
||||
|
||||
InvariantStartPosition += diff;
|
||||
InvariantEndPosition += diff;
|
||||
} finally {
|
||||
Mode = AccessMode.Closed;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a tag of a specified type from the current instance,
|
||||
/// optionally creating a new tag if possible.
|
||||
/// </summary>
|
||||
/// <param name="type">
|
||||
/// A <see cref="TagLib.TagTypes" /> value indicating the
|
||||
/// type of tag to read.
|
||||
/// </param>
|
||||
/// <param name="create">
|
||||
/// A <see cref="bool" /> value specifying whether or not to
|
||||
/// try and create the tag if one is not found.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="Tag" /> object containing the tag that was
|
||||
/// found in or added to the current instance. If no
|
||||
/// matching tag was found and none was created, <see
|
||||
/// langword="null" /> is returned.
|
||||
/// </returns>
|
||||
public override TagLib.Tag GetTag (TagTypes type, bool create)
|
||||
{
|
||||
if (type == TagTypes.Asf)
|
||||
return asf_tag;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a set of tag types from the current instance.
|
||||
/// </summary>
|
||||
/// <param name="types">
|
||||
/// A bitwise combined <see cref="TagLib.TagTypes" /> value
|
||||
/// containing tag types to be removed from the file.
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// In order to remove all tags from a file, pass <see
|
||||
/// cref="TagTypes.AllTags" /> as <paramref name="types" />.
|
||||
/// </remarks>
|
||||
public override void RemoveTags (TagTypes types)
|
||||
{
|
||||
if ((types & TagTypes.Asf) == TagTypes.Asf)
|
||||
asf_tag.Clear ();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a 2-byte WORD from the current instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="ushort" /> value containing the WORD read
|
||||
/// from the current instance.
|
||||
/// </returns>
|
||||
public ushort ReadWord ()
|
||||
{
|
||||
return ReadBlock (2).ToUShort (false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a 4-byte DWORD from the current instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="uint" /> value containing the DWORD read
|
||||
/// from the current instance.
|
||||
/// </returns>
|
||||
public uint ReadDWord ()
|
||||
{
|
||||
return ReadBlock (4).ToUInt (false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a 8-byte QWORD from the current instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="ulong" /> value containing the QWORD read
|
||||
/// from the current instance.
|
||||
/// </returns>
|
||||
public ulong ReadQWord ()
|
||||
{
|
||||
return ReadBlock (8).ToULong (false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a 16-byte GUID from the current instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="System.Guid" /> value containing the GUID
|
||||
/// read from the current instance.
|
||||
/// </returns>
|
||||
public System.Guid ReadGuid ()
|
||||
{
|
||||
return new System.Guid (ReadBlock (16).Data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a Unicode (UTF-16LE) string of specified length
|
||||
/// from the current instance.
|
||||
/// </summary>
|
||||
/// <param name="length">
|
||||
/// A <see cref="int" /> value specifying the number of bytes
|
||||
/// to read. This should always be an even number.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="string" /> object containing the Unicode
|
||||
/// string read from the current instance.
|
||||
/// </returns>
|
||||
public string ReadUnicode (int length)
|
||||
{
|
||||
ByteVector data = ReadBlock (length);
|
||||
string output = data.ToString (StringType.UTF16LE);
|
||||
int i = output.IndexOf ('\0');
|
||||
return (i >= 0) ? output.Substring (0, i) : output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a collection of objects from the current instance.
|
||||
/// </summary>
|
||||
/// <param name="count">
|
||||
/// A <see cref="uint" /> value specifying the number of
|
||||
/// objects to read.
|
||||
/// </param>
|
||||
/// <param name="position">
|
||||
/// A <see cref="long" /> value specifying the seek position
|
||||
/// at which to start reading.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A new <see cref="T:System.Collections.Generic.IEnumerable`1" /> object enumerating
|
||||
/// through the <see cref="Object" /> objects read from the
|
||||
/// current instance.
|
||||
/// </returns>
|
||||
public IEnumerable<Object> ReadObjects (uint count,
|
||||
long position)
|
||||
{
|
||||
for (int i = 0; i < (int) count; i ++) {
|
||||
Object obj = ReadObject (position);
|
||||
position += (long) obj.OriginalSize;
|
||||
yield return obj;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a <see cref="Object" /> from the current instance.
|
||||
/// </summary>
|
||||
/// <param name="position">
|
||||
/// A <see cref="long" /> value specifying the seek position
|
||||
/// at which to start reading.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A new <see cref="Object" /> object of appropriate type as
|
||||
/// read from the current instance.
|
||||
/// </returns>
|
||||
public Object ReadObject (long position)
|
||||
{
|
||||
Seek (position);
|
||||
System.Guid id = ReadGuid ();
|
||||
|
||||
if (id.Equals (Guid.AsfFilePropertiesObject))
|
||||
return new FilePropertiesObject (this,
|
||||
position);
|
||||
|
||||
if (id.Equals (Guid.AsfStreamPropertiesObject))
|
||||
return new StreamPropertiesObject (this,
|
||||
position);
|
||||
|
||||
if (id.Equals (Guid.AsfContentDescriptionObject))
|
||||
return new ContentDescriptionObject (this,
|
||||
position);
|
||||
|
||||
if (id.Equals (
|
||||
Guid.AsfExtendedContentDescriptionObject))
|
||||
return new ExtendedContentDescriptionObject (
|
||||
this, position);
|
||||
|
||||
if (id.Equals (Guid.AsfPaddingObject))
|
||||
return new PaddingObject (this, position);
|
||||
|
||||
if (id.Equals (Guid.AsfHeaderExtensionObject))
|
||||
return new HeaderExtensionObject (this,
|
||||
position);
|
||||
|
||||
if (id.Equals (Guid.AsfMetadataLibraryObject))
|
||||
return new MetadataLibraryObject (this,
|
||||
position);
|
||||
|
||||
return new UnknownObject (this, position);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Private Methods
|
||||
|
||||
/// <summary>
|
||||
/// Reads the contents of the current instance.
|
||||
/// </summary>
|
||||
/// <param name="propertiesStyle">
|
||||
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||
/// of accuracy to read the media properties, or <see
|
||||
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||
/// </param>
|
||||
private void Read (ReadStyle propertiesStyle)
|
||||
{
|
||||
Mode = AccessMode.Read;
|
||||
try {
|
||||
HeaderObject header = new HeaderObject (this, 0);
|
||||
|
||||
if (header.HasContentDescriptors)
|
||||
TagTypesOnDisk |= TagTypes.Asf;
|
||||
|
||||
asf_tag = new Asf.Tag (header);
|
||||
|
||||
InvariantStartPosition = (long) header.OriginalSize;
|
||||
InvariantEndPosition = Length;
|
||||
|
||||
if (propertiesStyle != ReadStyle.None)
|
||||
properties = header.Properties;
|
||||
} finally {
|
||||
Mode = AccessMode.Closed;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,327 +0,0 @@
|
||||
//
|
||||
// FilePropertiesObject.cs: Provides a representation of an ASF File Properties
|
||||
// object which can be read from and written to disk.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
//
|
||||
// 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.Asf {
|
||||
/// <summary>
|
||||
/// This class extends <see cref="Object" /> to provide a
|
||||
/// representation of an ASF File Properties object which can be read
|
||||
/// from and written to disk.
|
||||
/// </summary>
|
||||
public class FilePropertiesObject : Object
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Contains the GUID for the file.
|
||||
/// </summary>
|
||||
private System.Guid file_id;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the file size.
|
||||
/// </summary>
|
||||
private ulong file_size;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the creation date.
|
||||
/// </summary>
|
||||
private ulong creation_date;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the packet count.
|
||||
/// </summary>
|
||||
private ulong data_packets_count;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the play duration.
|
||||
/// </summary>
|
||||
private ulong play_duration;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the send duration.
|
||||
/// </summary>
|
||||
private ulong send_duration;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the preroll.
|
||||
/// </summary>
|
||||
private ulong preroll;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the file flags.
|
||||
/// </summary>
|
||||
private uint flags;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the minimum packet size.
|
||||
/// </summary>
|
||||
private uint minimum_data_packet_size;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the maxximum packet size.
|
||||
/// </summary>
|
||||
private uint maximum_data_packet_size;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the maximum bitrate of the file.
|
||||
/// </summary>
|
||||
private uint maximum_bitrate;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="FilePropertiesObject" /> by reading the contents
|
||||
/// from a specified position in a specified file.
|
||||
/// </summary>
|
||||
/// <param name="file">
|
||||
/// A <see cref="Asf.File" /> object containing the file from
|
||||
/// which the contents of the new instance are to be read.
|
||||
/// </param>
|
||||
/// <param name="position">
|
||||
/// A <see cref="long" /> value specify at what position to
|
||||
/// read the object.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="file" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// <paramref name="position" /> is less than zero or greater
|
||||
/// than the size of the file.
|
||||
/// </exception>
|
||||
/// <exception cref="CorruptFileException">
|
||||
/// The object read from disk does not have the correct GUID
|
||||
/// or smaller than the minimum size.
|
||||
/// </exception>
|
||||
public FilePropertiesObject (Asf.File file, long position)
|
||||
: base (file, position)
|
||||
{
|
||||
if (!Guid.Equals (Asf.Guid.AsfFilePropertiesObject))
|
||||
throw new CorruptFileException (
|
||||
"Object GUID incorrect.");
|
||||
|
||||
if (OriginalSize < 104)
|
||||
throw new CorruptFileException (
|
||||
"Object size too small.");
|
||||
|
||||
file_id = file.ReadGuid ();
|
||||
file_size = file.ReadQWord ();
|
||||
creation_date = file.ReadQWord ();
|
||||
data_packets_count = file.ReadQWord ();
|
||||
send_duration = file.ReadQWord ();
|
||||
play_duration = file.ReadQWord ();
|
||||
preroll = file.ReadQWord ();
|
||||
flags = file.ReadDWord ();
|
||||
minimum_data_packet_size = file.ReadDWord ();
|
||||
maximum_data_packet_size = file.ReadDWord ();
|
||||
maximum_bitrate = file.ReadDWord ();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the GUID for the file described by the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="System.Guid" /> value containing the GUID
|
||||
/// for the file described by the current instance.
|
||||
/// </value>
|
||||
public System.Guid FileId {
|
||||
get {return file_id;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of the file described by the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="ulong" /> value containing the size of the
|
||||
/// file described by the current instance.
|
||||
/// </value>
|
||||
public ulong FileSize {
|
||||
get {return file_size;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the creation date of the file described by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="DateTime" /> value containing the creation
|
||||
/// date of the file described by the current instance.
|
||||
/// </value>
|
||||
public DateTime CreationDate {
|
||||
get {return new DateTime ((long)creation_date);}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of data packets in the file described by
|
||||
/// the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="ulong" /> value containing the number of
|
||||
/// data packets in the file described by the current
|
||||
/// instance.
|
||||
/// </value>
|
||||
public ulong DataPacketsCount {
|
||||
get {return data_packets_count;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the play duration of the file described by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="TimeSpan" /> value containing the play
|
||||
/// duration of the file described by the current instance.
|
||||
/// </value>
|
||||
public TimeSpan PlayDuration {
|
||||
get {return new TimeSpan ((long)play_duration);}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the send duration of the file described by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="TimeSpan" /> value containing the send
|
||||
/// duration of the file described by the current instance.
|
||||
/// </value>
|
||||
public TimeSpan SendDuration {
|
||||
get {return new TimeSpan ((long)send_duration);}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the pre-roll of the file described by the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="ulong" /> value containing the pre-roll of
|
||||
/// the file described by the current instance.
|
||||
/// </value>
|
||||
public ulong Preroll {
|
||||
get {return preroll;}
|
||||
}
|
||||
|
||||
//public long AudioSampleCount
|
||||
//{
|
||||
// get
|
||||
// {
|
||||
// return (((long) send_duration - (long) preroll * 10000) * 44100 + 5000000) / 10000000;
|
||||
// }
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the flags of the file described by the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="uint" /> value containing the flags of the
|
||||
/// file described by the current instance.
|
||||
/// </value>
|
||||
public uint Flags {
|
||||
get {return flags;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the minimum data packet size of the file described
|
||||
/// by the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="uint" /> value containing the minimum data
|
||||
/// packet size of the file described by the current
|
||||
/// instance.
|
||||
/// </value>
|
||||
public uint MinimumDataPacketSize {
|
||||
get {return minimum_data_packet_size;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the maximum data packet size of the file described
|
||||
/// by the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="uint" /> value containing the maximum data
|
||||
/// packet size of the file described by the current
|
||||
/// instance.
|
||||
/// </value>
|
||||
public uint MaximumDataPacketSize {
|
||||
get {return maximum_data_packet_size;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the maximum bitrate of the file described by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="uint" /> value containing the maximum
|
||||
/// bitrate of the file described by the current instance.
|
||||
/// </value>
|
||||
public uint MaximumBitrate {
|
||||
get {return maximum_bitrate;}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Renders the current instance as a raw ASF object.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector" /> object containing the
|
||||
/// rendered version of the current instance.
|
||||
/// </returns>
|
||||
public override ByteVector Render ()
|
||||
{
|
||||
ByteVector output = file_id.ToByteArray ();
|
||||
output.Add (RenderQWord (file_size));
|
||||
output.Add (RenderQWord (creation_date));
|
||||
output.Add (RenderQWord (data_packets_count));
|
||||
output.Add (RenderQWord (send_duration));
|
||||
output.Add (RenderQWord (play_duration));
|
||||
output.Add (RenderQWord (preroll));
|
||||
output.Add (RenderDWord (flags));
|
||||
output.Add (RenderDWord (minimum_data_packet_size));
|
||||
output.Add (RenderDWord (maximum_data_packet_size));
|
||||
output.Add (RenderDWord (maximum_bitrate));
|
||||
|
||||
return Render (output);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
//
|
||||
// Guid.cs: Provides common GUID values used by ASF Objects.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
//
|
||||
// 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.Asf {
|
||||
/// <summary>
|
||||
/// This static class contains common <see cref="System.Guid" />
|
||||
/// values used by ASF Objects.
|
||||
/// </summary>
|
||||
public static class Guid
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates that an object is a <see
|
||||
/// cref="ContentDescriptionObject" />.
|
||||
/// </summary>
|
||||
public static readonly System.Guid AsfContentDescriptionObject =
|
||||
new System.Guid ("75B22633-668E-11CF-A6D9-00AA0062CE6C");
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that an object is a <see
|
||||
/// cref="ExtendedContentDescriptionObject" />.
|
||||
/// </summary>
|
||||
public static readonly System.Guid AsfExtendedContentDescriptionObject =
|
||||
new System.Guid ("D2D0A440-E307-11D2-97F0-00A0C95EA850");
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that an object is a <see
|
||||
/// cref="FilePropertiesObject" />.
|
||||
/// </summary>
|
||||
public static readonly System.Guid AsfFilePropertiesObject =
|
||||
new System.Guid ("8CABDCA1-A947-11CF-8EE4-00C00C205365");
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that an object is a <see
|
||||
/// cref="HeaderExtensionObject" />.
|
||||
/// </summary>
|
||||
public static readonly System.Guid AsfHeaderExtensionObject =
|
||||
new System.Guid ("5FBF03B5-A92E-11CF-8EE3-00C00C205365");
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that an object is a <see
|
||||
/// cref="HeaderObject" />.
|
||||
/// </summary>
|
||||
public static readonly System.Guid AsfHeaderObject =
|
||||
new System.Guid ("75B22630-668E-11CF-A6D9-00AA0062CE6C");
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that an object is a <see
|
||||
/// cref="MetadataLibraryObject" />.
|
||||
/// </summary>
|
||||
public static readonly System.Guid AsfMetadataLibraryObject =
|
||||
new System.Guid ("44231C94-9498-49D1-A141-1D134E457054");
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that an object is a <see
|
||||
/// cref="PaddingObject" />.
|
||||
/// </summary>
|
||||
public static readonly System.Guid AsfPaddingObject =
|
||||
new System.Guid ("1806D474-CADF-4509-A4BA-9AABCB96AAE8");
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that an object is a <see
|
||||
/// cref="StreamPropertiesObject" />.
|
||||
/// </summary>
|
||||
public static readonly System.Guid AsfStreamPropertiesObject =
|
||||
new System.Guid ("B7DC0791-A9B7-11CF-8EE6-00C00C205365");
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that a <see cref="StreamPropertiesObject" />
|
||||
/// contains information about an audio stream.
|
||||
/// </summary>
|
||||
public static readonly System.Guid AsfAudioMedia =
|
||||
new System.Guid ("F8699E40-5B4D-11CF-A8FD-00805F5C442B");
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that a <see cref="StreamPropertiesObject" />
|
||||
/// contains information about an video stream.
|
||||
/// </summary>
|
||||
public static readonly System.Guid AsfVideoMedia =
|
||||
new System.Guid ("BC19EFC0-5B4D-11CF-A8FD-00805F5C442B");
|
||||
|
||||
/// <summary>
|
||||
/// Indicates a placeholder portion of a file is correctly
|
||||
/// encoded.
|
||||
/// </summary>
|
||||
public static readonly System.Guid AsfReserved1 =
|
||||
new System.Guid ("ABD3D211-A9BA-11cf-8EE6-00C00C205365");
|
||||
}
|
||||
}
|
||||
@@ -1,176 +0,0 @@
|
||||
//
|
||||
// HeaderExtensionObject.cs: Provides a representation of an ASF Header
|
||||
// Extension object which can be read from and written to disk.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
//
|
||||
// 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;
|
||||
|
||||
namespace TagLib.Asf {
|
||||
/// <summary>
|
||||
/// This class extends <see cref="Object" /> to provide a
|
||||
/// representation of an ASF Header Extension object which can be
|
||||
/// read from and written to disk.
|
||||
/// </summary>
|
||||
public class HeaderExtensionObject : Object
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Contains the child objects.
|
||||
/// </summary>
|
||||
private List<Object> children = new List<Object> ();
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="HeaderExtensionObject" /> by reading the contents
|
||||
/// from a specified position in a specified file.
|
||||
/// </summary>
|
||||
/// <param name="file">
|
||||
/// A <see cref="Asf.File" /> object containing the file from
|
||||
/// which the contents of the new instance are to be read.
|
||||
/// </param>
|
||||
/// <param name="position">
|
||||
/// A <see cref="long" /> value specify at what position to
|
||||
/// read the object.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="file" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// <paramref name="position" /> is less than zero or greater
|
||||
/// than the size of the file.
|
||||
/// </exception>
|
||||
/// <exception cref="CorruptFileException">
|
||||
/// The object read from disk does not have the correct GUID
|
||||
/// or contents.
|
||||
/// </exception>
|
||||
public HeaderExtensionObject (Asf.File file, long position)
|
||||
: base (file, position)
|
||||
{
|
||||
if (!Guid.Equals (Asf.Guid.AsfHeaderExtensionObject))
|
||||
throw new CorruptFileException (
|
||||
"Object GUID incorrect.");
|
||||
|
||||
if (file.ReadGuid () != Asf.Guid.AsfReserved1)
|
||||
throw new CorruptFileException (
|
||||
"Reserved1 GUID expected.");
|
||||
|
||||
if (file.ReadWord () != 6)
|
||||
throw new CorruptFileException (
|
||||
"Invalid reserved WORD. Expected '6'.");
|
||||
|
||||
uint size_remaining = file.ReadDWord ();
|
||||
position += 0x170 / 8;
|
||||
|
||||
while (size_remaining > 0) {
|
||||
Object obj = file.ReadObject (position);
|
||||
position += (long) obj.OriginalSize;
|
||||
size_remaining -= (uint) obj.OriginalSize;
|
||||
children.Add (obj);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the child objects contained in the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="T:System.Collections.Generic.IEnumerable`1" /> object enumerating
|
||||
/// through the children of the current instance.
|
||||
/// </value>
|
||||
public IEnumerable<Object> Children {
|
||||
get {return children;}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Renders the current instance as a raw ASF object.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector" /> object containing the
|
||||
/// rendered version of the current instance.
|
||||
/// </returns>
|
||||
public override ByteVector Render ()
|
||||
{
|
||||
ByteVector output = new ByteVector ();
|
||||
|
||||
foreach (Object child in children)
|
||||
output.Add (child.Render ());
|
||||
|
||||
output.Insert (0, RenderDWord ((uint) output.Count));
|
||||
output.Insert (0, RenderWord (6));
|
||||
output.Insert (0, Asf.Guid.AsfReserved1.ToByteArray ());
|
||||
|
||||
return Render (output);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a child object to the current instance.
|
||||
/// </summary>
|
||||
/// <param name="obj">
|
||||
/// A <see cref="Object" /> object to add to the current
|
||||
/// instance.
|
||||
/// </param>
|
||||
public void AddObject (Object obj)
|
||||
{
|
||||
children.Add (obj);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a child unique child object to the current instance,
|
||||
/// replacing and existing child if present.
|
||||
/// </summary>
|
||||
/// <param name="obj">
|
||||
/// A <see cref="Object" /> object to add to the current
|
||||
/// instance.
|
||||
/// </param>
|
||||
public void AddUniqueObject (Object obj)
|
||||
{
|
||||
for (int i = 0; i < children.Count; i ++)
|
||||
if (((Object) children [i]).Guid == obj.Guid) {
|
||||
children [i] = obj;
|
||||
return;
|
||||
}
|
||||
|
||||
children.Add (obj);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,275 +0,0 @@
|
||||
//
|
||||
// HeaderObject.cs: Provides a representation of an ASF Header object which can
|
||||
// be read from and written to disk.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
//
|
||||
// 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.Asf {
|
||||
/// <summary>
|
||||
/// This class extends <see cref="Object" /> to provide a
|
||||
/// representation of an ASF Header object which can be read from and
|
||||
/// written to disk.
|
||||
/// </summary>
|
||||
public class HeaderObject : Object
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Contains the reserved header data.
|
||||
/// </summary>
|
||||
private ByteVector reserved;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the child objects.
|
||||
/// </summary>
|
||||
private List<Object> children;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="HeaderObject" /> by reading the contents from a
|
||||
/// specified position in a specified file.
|
||||
/// </summary>
|
||||
/// <param name="file">
|
||||
/// A <see cref="Asf.File" /> object containing the file from
|
||||
/// which the contents of the new instance are to be read.
|
||||
/// </param>
|
||||
/// <param name="position">
|
||||
/// A <see cref="long" /> value specify at what position to
|
||||
/// read the object.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="file" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// <paramref name="position" /> is less than zero or greater
|
||||
/// than the size of the file.
|
||||
/// </exception>
|
||||
/// <exception cref="CorruptFileException">
|
||||
/// The object read from disk does not have the correct GUID
|
||||
/// or smaller than the minimum size.
|
||||
/// </exception>
|
||||
public HeaderObject (Asf.File file, long position)
|
||||
: base (file, position)
|
||||
{
|
||||
if (!Guid.Equals (Asf.Guid.AsfHeaderObject))
|
||||
throw new CorruptFileException (
|
||||
"Object GUID incorrect.");
|
||||
|
||||
if (OriginalSize < 26)
|
||||
throw new CorruptFileException (
|
||||
"Object size too small.");
|
||||
|
||||
children = new List<Object> ();
|
||||
|
||||
uint child_count = file.ReadDWord ();
|
||||
|
||||
reserved = file.ReadBlock (2);
|
||||
|
||||
children.AddRange (file.ReadObjects (child_count,
|
||||
file.Tell));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the header extension object contained in the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="HeaderExtensionObject" /> object containing
|
||||
/// the header extension object.
|
||||
/// </value>
|
||||
public HeaderExtensionObject Extension {
|
||||
get {
|
||||
foreach (Object child in children)
|
||||
if (child is HeaderExtensionObject)
|
||||
return child as HeaderExtensionObject;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the child objects contained in the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="T:System.Collections.Generic.IEnumerable`1" /> object enumerating
|
||||
/// through the children of the current instance.
|
||||
/// </value>
|
||||
public IEnumerable<Object> Children {
|
||||
get {return children;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the media properties contained within the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="Properties" /> object containing the media
|
||||
/// properties of the current instance.
|
||||
/// </value>
|
||||
public Properties Properties {
|
||||
get {
|
||||
TimeSpan duration = TimeSpan.Zero;
|
||||
List<ICodec> codecs = new List<ICodec> ();
|
||||
|
||||
foreach (Object obj in Children) {
|
||||
FilePropertiesObject fpobj = obj as
|
||||
FilePropertiesObject;
|
||||
|
||||
if (fpobj != null) {
|
||||
duration = fpobj.PlayDuration -
|
||||
new TimeSpan((long) fpobj.Preroll);
|
||||
continue;
|
||||
}
|
||||
|
||||
StreamPropertiesObject spobj = obj as
|
||||
StreamPropertiesObject;
|
||||
|
||||
if (spobj != null) {
|
||||
codecs.Add (spobj.Codec);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return new Properties (duration, codecs);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not the current instance contains either
|
||||
/// type of content descriptiors.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <see langword="true" /> if the current instance contains
|
||||
/// a <see cref="ContentDescriptionObject" /> or a <see
|
||||
/// cref="ExtendedContentDescriptionObject" />. Otherwise
|
||||
/// <see langword="false" />.
|
||||
/// </value>
|
||||
public bool HasContentDescriptors {
|
||||
get {
|
||||
foreach (Asf.Object child in children)
|
||||
if (child.Guid == Asf.Guid.AsfContentDescriptionObject ||
|
||||
child.Guid == Asf.Guid.AsfExtendedContentDescriptionObject)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Renders the current instance as a raw ASF object.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector" /> object containing the
|
||||
/// rendered version of the current instance.
|
||||
/// </returns>
|
||||
public override ByteVector Render ()
|
||||
{
|
||||
ByteVector output = new ByteVector ();
|
||||
uint child_count = 0;
|
||||
|
||||
foreach (Object child in children)
|
||||
if (child.Guid != Asf.Guid.AsfPaddingObject) {
|
||||
output.Add (child.Render ());
|
||||
child_count ++;
|
||||
}
|
||||
|
||||
long size_diff = (long) output.Count + 30 -
|
||||
(long) OriginalSize;
|
||||
|
||||
if (size_diff != 0) {
|
||||
PaddingObject obj = new PaddingObject ((uint)
|
||||
(size_diff > 0 ? 4096 : - size_diff));
|
||||
|
||||
output.Add (obj.Render ());
|
||||
child_count ++;
|
||||
}
|
||||
|
||||
output.Insert (0, reserved);
|
||||
output.Insert (0, RenderDWord (child_count));
|
||||
return Render (output);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a child object to the current instance.
|
||||
/// </summary>
|
||||
/// <param name="obj">
|
||||
/// A <see cref="Object" /> object to add to the current
|
||||
/// instance.
|
||||
/// </param>
|
||||
public void AddObject (Object obj)
|
||||
{
|
||||
children.Add (obj);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a child unique child object to the current instance,
|
||||
/// replacing and existing child if present.
|
||||
/// </summary>
|
||||
/// <param name="obj">
|
||||
/// A <see cref="Object" /> object to add to the current
|
||||
/// instance.
|
||||
/// </param>
|
||||
public void AddUniqueObject (Object obj)
|
||||
{
|
||||
for (int i = 0; i < children.Count; i ++)
|
||||
if (children [i].Guid == obj.Guid) {
|
||||
children [i] = obj;
|
||||
return;
|
||||
}
|
||||
|
||||
children.Add (obj);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the content description objects from the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
public void RemoveContentDescriptors ()
|
||||
{
|
||||
for (int i = children.Count - 1; i >= 0; i --)
|
||||
if (children [i].Guid == Asf.Guid.AsfContentDescriptionObject ||
|
||||
children [i].Guid == Asf.Guid.AsfExtendedContentDescriptionObject)
|
||||
children.RemoveAt (i);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,298 +0,0 @@
|
||||
//
|
||||
// MetadataLibraryObject.cs: Provides a representation of an ASF Metadata
|
||||
// Library object which can be read from and written to disk.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
//
|
||||
// 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.Asf {
|
||||
/// <summary>
|
||||
/// This class extends <see cref="Object" /> to provide a
|
||||
/// representation of an ASF Metadata Library object which can be
|
||||
/// read from and written to disk.
|
||||
/// </summary>
|
||||
public class MetadataLibraryObject : Object,
|
||||
IEnumerable<DescriptionRecord>
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Contains the description records.
|
||||
/// </summary>
|
||||
private List<DescriptionRecord> records =
|
||||
new List<DescriptionRecord> ();
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="MetadataLibraryObject" /> by reading the contents
|
||||
/// from a specified position in a specified file.
|
||||
/// </summary>
|
||||
/// <param name="file">
|
||||
/// A <see cref="Asf.File" /> object containing the file from
|
||||
/// which the contents of the new instance are to be read.
|
||||
/// </param>
|
||||
/// <param name="position">
|
||||
/// A <see cref="long" /> value specify at what position to
|
||||
/// read the object.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="file" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// <paramref name="position" /> is less than zero or greater
|
||||
/// than the size of the file.
|
||||
/// </exception>
|
||||
/// <exception cref="CorruptFileException">
|
||||
/// The object read from disk does not have the correct GUID
|
||||
/// or smaller than the minimum size.
|
||||
/// </exception>
|
||||
public MetadataLibraryObject (Asf.File file, long position)
|
||||
: base (file, position)
|
||||
{
|
||||
if (!Guid.Equals (Asf.Guid.AsfMetadataLibraryObject))
|
||||
throw new CorruptFileException (
|
||||
"Object GUID incorrect.");
|
||||
|
||||
if (OriginalSize < 26)
|
||||
throw new CorruptFileException (
|
||||
"Object size too small.");
|
||||
|
||||
ushort count = file.ReadWord ();
|
||||
|
||||
for (ushort i = 0; i < count; i ++) {
|
||||
DescriptionRecord rec = new DescriptionRecord (
|
||||
file);
|
||||
AddRecord (rec);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="MetadataLibraryObject" /> with no contents.
|
||||
/// </summary>
|
||||
public MetadataLibraryObject ()
|
||||
: base (Asf.Guid.AsfMetadataLibraryObject)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not the current instance is empty.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <see langword="true" /> if the current instance doesn't
|
||||
/// contain any <see cref="DescriptionRecord" /> objects.
|
||||
/// Otherwise <see langword="false" />.
|
||||
/// </value>
|
||||
public bool IsEmpty {
|
||||
get {return records.Count == 0;}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Renders the current instance as a raw ASF object.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector" /> object containing the
|
||||
/// rendered version of the current instance.
|
||||
/// </returns>
|
||||
public override ByteVector Render ()
|
||||
{
|
||||
ByteVector output = new ByteVector ();
|
||||
ushort count = 0;
|
||||
|
||||
foreach (DescriptionRecord rec in records) {
|
||||
count ++;
|
||||
output.Add (rec.Render ());
|
||||
}
|
||||
|
||||
return Render (RenderWord (count) + output);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes all records with a given language, stream, and
|
||||
/// name from the current instance.
|
||||
/// </summary>
|
||||
/// <param name="languageListIndex">
|
||||
/// A <see cref="ushort" /> value containing the language
|
||||
/// list index of the records to be removed.
|
||||
/// </param>
|
||||
/// <param name="streamNumber">
|
||||
/// A <see cref="ushort" /> value containing the stream
|
||||
/// number of the records to be removed.
|
||||
/// </param>
|
||||
/// <param name="name">
|
||||
/// A <see cref="string" /> object containing the name of the
|
||||
/// records to be removed.
|
||||
/// </param>
|
||||
public void RemoveRecords (ushort languageListIndex,
|
||||
ushort streamNumber,
|
||||
string name)
|
||||
{
|
||||
for (int i = records.Count - 1; i >= 0; i --) {
|
||||
DescriptionRecord rec = records [i];
|
||||
if (rec.LanguageListIndex == languageListIndex &&
|
||||
rec.StreamNumber == streamNumber &&
|
||||
rec.Name == name)
|
||||
records.RemoveAt (i);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all records with a given language, stream, and any
|
||||
/// of a collection of names from the current instance.
|
||||
/// </summary>
|
||||
/// <param name="languageListIndex">
|
||||
/// A <see cref="ushort" /> value containing the language
|
||||
/// list index of the records to be retrieved.
|
||||
/// </param>
|
||||
/// <param name="streamNumber">
|
||||
/// A <see cref="ushort" /> value containing the stream
|
||||
/// number of the records to be retrieved.
|
||||
/// </param>
|
||||
/// <param name="names">
|
||||
/// A <see cref="string[]" /> containing the names of the
|
||||
/// records to be retrieved.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="T:System.Collections.Generic.IEnumerable`1" /> object enumerating
|
||||
/// through the <see cref="DescriptionRecord" /> objects
|
||||
/// retrieved from the current instance.
|
||||
/// </returns>
|
||||
public IEnumerable<DescriptionRecord> GetRecords (ushort languageListIndex,
|
||||
ushort streamNumber,
|
||||
params string [] names)
|
||||
{
|
||||
foreach (DescriptionRecord rec in records) {
|
||||
if (rec.LanguageListIndex != languageListIndex ||
|
||||
rec.StreamNumber != streamNumber)
|
||||
continue;
|
||||
|
||||
foreach (string name in names)
|
||||
if (rec.Name == name)
|
||||
yield return rec;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a record to the current instance.
|
||||
/// </summary>
|
||||
/// <param name="record">
|
||||
/// A <see cref="DescriptionRecord" /> object to add to the
|
||||
/// current instance.
|
||||
/// </param>
|
||||
public void AddRecord (DescriptionRecord record)
|
||||
{
|
||||
records.Add (record);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the a collection of records for a given language,
|
||||
/// stream, and name, removing the existing matching records.
|
||||
/// </summary>
|
||||
/// <param name="languageListIndex">
|
||||
/// A <see cref="ushort" /> value containing the language
|
||||
/// list index of the records to be added.
|
||||
/// </param>
|
||||
/// <param name="streamNumber">
|
||||
/// A <see cref="ushort" /> value containing the stream
|
||||
/// number of the records to be added.
|
||||
/// </param>
|
||||
/// <param name="name">
|
||||
/// A <see cref="string" /> object containing the name of the
|
||||
/// records to be added.
|
||||
/// </param>
|
||||
/// <param name="records">
|
||||
/// A <see cref="DescriptionRecord[]" /> containing records
|
||||
/// to add to the new instance.
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// All added entries in <paramref name="records" /> should
|
||||
/// match <paramref name="languageListIndex" />, <paramref
|
||||
/// name="streamNumber" /> and <paramref name="name" /> but
|
||||
/// it is not verified by the method. The records will be
|
||||
/// added with their own values and not those provided in
|
||||
/// this method, which are used for removing existing values
|
||||
/// and determining where to position the new object.
|
||||
/// </remarks>
|
||||
public void SetRecords (ushort languageListIndex,
|
||||
ushort streamNumber, string name,
|
||||
params DescriptionRecord [] records)
|
||||
{
|
||||
int position = this.records.Count;
|
||||
for (int i = this.records.Count - 1; i >= 0; i --) {
|
||||
DescriptionRecord rec = this.records [i];
|
||||
if (rec.LanguageListIndex == languageListIndex &&
|
||||
rec.StreamNumber == streamNumber &&
|
||||
rec.Name == name) {
|
||||
this.records.RemoveAt (i);
|
||||
position = i;
|
||||
}
|
||||
}
|
||||
this.records.InsertRange (position, records);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region IEnumerable
|
||||
|
||||
/// <summary>
|
||||
/// Gets an enumerator for enumerating through the
|
||||
/// description records.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="T:System.Collections.IEnumerator`1" /> for
|
||||
/// enumerating through the description records.
|
||||
/// </returns>
|
||||
public IEnumerator<DescriptionRecord> GetEnumerator ()
|
||||
{
|
||||
return records.GetEnumerator ();
|
||||
}
|
||||
|
||||
System.Collections.IEnumerator
|
||||
System.Collections.IEnumerable.GetEnumerator ()
|
||||
{
|
||||
return records.GetEnumerator ();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,253 +0,0 @@
|
||||
//
|
||||
// Object.cs: Provides a basic representation of an ASF object which can be read
|
||||
// from and written to disk.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
//
|
||||
// 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.Asf {
|
||||
/// <summary>
|
||||
/// This abstract class provides a basic representation of an ASF
|
||||
/// object which can be read from and written to disk.
|
||||
/// </summary>
|
||||
public abstract class Object
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Contains the GUID of the object.
|
||||
/// </summary>
|
||||
private System.Guid id;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the size of the object on disk.
|
||||
/// </summary>
|
||||
private ulong size;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="Object" /> by reading the contents from a
|
||||
/// specified position in a specified file.
|
||||
/// </summary>
|
||||
/// <param name="file">
|
||||
/// A <see cref="Asf.File" /> object containing the file from
|
||||
/// which the contents of the new instance are to be read.
|
||||
/// </param>
|
||||
/// <param name="position">
|
||||
/// A <see cref="long" /> value specify at what position to
|
||||
/// read the object.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="file" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// <paramref name="position" /> is less than zero or greater
|
||||
/// than the size of the file.
|
||||
/// </exception>
|
||||
protected Object (Asf.File file, long position)
|
||||
{
|
||||
if (file == null)
|
||||
throw new ArgumentNullException ("file");
|
||||
|
||||
if (position < 0 ||
|
||||
position > file.Length - 24)
|
||||
throw new ArgumentOutOfRangeException (
|
||||
"position");
|
||||
|
||||
file.Seek (position);
|
||||
id = file.ReadGuid ();
|
||||
size = file.ReadQWord ();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="Object" /> with a specified GUID.
|
||||
/// </summary>
|
||||
/// <param name="guid">
|
||||
/// A <see cref="System.Guid" /> value containing the GUID to
|
||||
/// use for the new instance.
|
||||
/// </param>
|
||||
protected Object (System.Guid guid)
|
||||
{
|
||||
id = guid;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the GUID for the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="System.Guid" /> object containing the GUID
|
||||
/// of the current instance.
|
||||
/// </value>
|
||||
public System.Guid Guid {
|
||||
get {return id;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the original size of the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="ulong" /> value containing the size of the
|
||||
/// current instance as it originally appeared on disk.
|
||||
/// </value>
|
||||
public ulong OriginalSize {
|
||||
get {return size;}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Renders the current instance as a raw ASF object.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector" /> object containing the
|
||||
/// rendered version of the current instance.
|
||||
/// </returns>
|
||||
/// <seealso cref="Render(ByteVector)" />
|
||||
public abstract ByteVector Render ();
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Static Methods
|
||||
|
||||
/// <summary>
|
||||
/// Renders a Unicode (wide) string.
|
||||
/// </summary>
|
||||
/// <param name="value">
|
||||
/// A <see cref="string" /> object containing the text to
|
||||
/// render.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector" /> object containing the
|
||||
/// rendered value.
|
||||
/// </returns>
|
||||
public static ByteVector RenderUnicode (string value)
|
||||
{
|
||||
ByteVector v = ByteVector.FromString (value,
|
||||
StringType.UTF16LE);
|
||||
v.Add (RenderWord (0));
|
||||
return v;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders a 4-byte DWORD.
|
||||
/// </summary>
|
||||
/// <param name="value">
|
||||
/// A <see cref="uint" /> value containing the DWORD to
|
||||
/// render.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector" /> object containing the
|
||||
/// rendered value.
|
||||
/// </returns>
|
||||
public static ByteVector RenderDWord (uint value)
|
||||
{
|
||||
return ByteVector.FromUInt (value, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders a 8-byte QWORD.
|
||||
/// </summary>
|
||||
/// <param name="value">
|
||||
/// A <see cref="ulong" /> value containing the QWORD to
|
||||
/// render.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector" /> object containing the
|
||||
/// rendered value.
|
||||
/// </returns>
|
||||
public static ByteVector RenderQWord (ulong value)
|
||||
{
|
||||
return ByteVector.FromULong (value, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders a 2-byte WORD.
|
||||
/// </summary>
|
||||
/// <param name="value">
|
||||
/// A <see cref="ushort" /> value containing the WORD to
|
||||
/// render.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector" /> object containing the
|
||||
/// rendered value.
|
||||
/// </returns>
|
||||
public static ByteVector RenderWord (ushort value)
|
||||
{
|
||||
return ByteVector.FromUShort (value, false);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
/// <summary>
|
||||
/// Renders the current instance as a raw ASF object
|
||||
/// containing specified data.
|
||||
/// </summary>
|
||||
/// <param name="data">
|
||||
/// A <see cref="ByteVector" /> object containing the data to
|
||||
/// contained in the rendered version of the current
|
||||
/// instance.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector" /> object containing the
|
||||
/// rendered version of the current instance.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// Child classes implementing <see cref="Render()" /> should
|
||||
/// render their contents and then send the data through this
|
||||
/// method to produce the final output.
|
||||
/// </remarks>
|
||||
protected ByteVector Render (ByteVector data)
|
||||
{
|
||||
ulong length = (ulong)
|
||||
((data != null ? data.Count : 0) + 24);
|
||||
ByteVector v = id.ToByteArray ();
|
||||
v.Add (RenderQWord (length));
|
||||
v.Add (data);
|
||||
return v;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,139 +0,0 @@
|
||||
//
|
||||
// PaddingObject.cs: Provides a representation of an ASF Padding object which
|
||||
// can be read from and written to disk.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
//
|
||||
// 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.Asf {
|
||||
/// <summary>
|
||||
/// This class extends <see cref="Object" /> to provide a
|
||||
/// representation of an ASF Padding object which can be read from
|
||||
/// and written to disk.
|
||||
/// </summary>
|
||||
public class PaddingObject : Object
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Contains the size of the current instance.
|
||||
/// </summary>
|
||||
private ulong size;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="PaddingObject" /> by reading the contents from a
|
||||
/// specified position in a specified file.
|
||||
/// </summary>
|
||||
/// <param name="file">
|
||||
/// A <see cref="Asf.File" /> object containing the file from
|
||||
/// which the contents of the new instance are to be read.
|
||||
/// </param>
|
||||
/// <param name="position">
|
||||
/// A <see cref="long" /> value specify at what position to
|
||||
/// read the object.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="file" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// <paramref name="position" /> is less than zero or greater
|
||||
/// than the size of the file.
|
||||
/// </exception>
|
||||
/// <exception cref="CorruptFileException">
|
||||
/// The object read from disk does not have the correct GUID
|
||||
/// or smaller than the minimum size.
|
||||
/// </exception>
|
||||
public PaddingObject (Asf.File file, long position)
|
||||
: base (file, position)
|
||||
{
|
||||
if (!Guid.Equals (Asf.Guid.AsfPaddingObject))
|
||||
throw new CorruptFileException (
|
||||
"Object GUID incorrect.");
|
||||
|
||||
if (OriginalSize < 24)
|
||||
throw new CorruptFileException (
|
||||
"Object size too small.");
|
||||
|
||||
size = OriginalSize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="PaddingObject" /> of a specified size.
|
||||
/// </summary>
|
||||
/// <param name="size">
|
||||
/// A <see cref="uint" /> value specifying the number of
|
||||
/// bytes the new instance is to take up on disk.
|
||||
/// </param>
|
||||
public PaddingObject (uint size)
|
||||
: base (Asf.Guid.AsfPaddingObject)
|
||||
{
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Prublic Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the number of bytes the current instance
|
||||
/// will take up on disk.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="ulong" /> value containing the size of the
|
||||
/// current instance on disk.
|
||||
/// </value>
|
||||
public ulong Size {
|
||||
get {return size;}
|
||||
set {size = value;}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Renders the current instance as a raw ASF object.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector" /> object containing the
|
||||
/// rendered version of the current instance.
|
||||
/// </returns>
|
||||
public override ByteVector Render ()
|
||||
{
|
||||
return Render (new ByteVector ((int) (size - 24)));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,270 +0,0 @@
|
||||
//
|
||||
// StreamPropertiesObject.cs: Provides a representation of an ASF Stream
|
||||
// Properties object which can be read from and written to disk.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
//
|
||||
// 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.Text;
|
||||
|
||||
namespace TagLib.Asf {
|
||||
/// <summary>
|
||||
/// This class extends <see cref="Object" /> to provide a
|
||||
/// representation of an ASF Stream Properties object which can be
|
||||
/// read from and written to disk.
|
||||
/// </summary>
|
||||
public class StreamPropertiesObject : Object
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Contains the stream type GUID.
|
||||
/// </summary>
|
||||
private System.Guid stream_type;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the error correction type GUID.
|
||||
/// </summary>
|
||||
private System.Guid error_correction_type;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the time offset of the stream.
|
||||
/// </summary>
|
||||
private ulong time_offset;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the stream flags.
|
||||
/// </summary>
|
||||
private ushort flags;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the reserved data.
|
||||
/// </summary>
|
||||
private uint reserved;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the type specific data.
|
||||
/// </summary>
|
||||
private ByteVector type_specific_data;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the error correction data.
|
||||
/// </summary>
|
||||
private ByteVector error_correction_data;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="PaddingObject" /> by reading the contents from a
|
||||
/// specified position in a specified file.
|
||||
/// </summary>
|
||||
/// <param name="file">
|
||||
/// A <see cref="Asf.File" /> object containing the file from
|
||||
/// which the contents of the new instance are to be read.
|
||||
/// </param>
|
||||
/// <param name="position">
|
||||
/// A <see cref="long" /> value specify at what position to
|
||||
/// read the object.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="file" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// <paramref name="position" /> is less than zero or greater
|
||||
/// than the size of the file.
|
||||
/// </exception>
|
||||
/// <exception cref="CorruptFileException">
|
||||
/// The object read from disk does not have the correct GUID
|
||||
/// or smaller than the minimum size.
|
||||
/// </exception>
|
||||
public StreamPropertiesObject (Asf.File file, long position)
|
||||
: base (file, position)
|
||||
{
|
||||
if (!Guid.Equals (Asf.Guid.AsfStreamPropertiesObject))
|
||||
throw new CorruptFileException (
|
||||
"Object GUID incorrect.");
|
||||
|
||||
if (OriginalSize < 78)
|
||||
throw new CorruptFileException (
|
||||
"Object size too small.");
|
||||
|
||||
stream_type = file.ReadGuid ();
|
||||
error_correction_type = file.ReadGuid ();
|
||||
time_offset = file.ReadQWord ();
|
||||
|
||||
int type_specific_data_length = (int) file.ReadDWord ();
|
||||
int error_correction_data_length = (int)
|
||||
file.ReadDWord ();
|
||||
|
||||
flags = file.ReadWord ();
|
||||
reserved = file.ReadDWord ();
|
||||
type_specific_data =
|
||||
file.ReadBlock (type_specific_data_length);
|
||||
error_correction_data =
|
||||
file.ReadBlock (error_correction_data_length);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the codec information contained in the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="ICodec" /> object containing the codec
|
||||
/// information read from <see cref="TypeSpecificData" /> or
|
||||
/// <see langword="null" /> if the data could not be decoded.
|
||||
/// </value>
|
||||
public ICodec Codec {
|
||||
get {
|
||||
if (stream_type == Asf.Guid.AsfAudioMedia)
|
||||
return new Riff.WaveFormatEx (
|
||||
type_specific_data, 0);
|
||||
|
||||
if (stream_type == Asf.Guid.AsfVideoMedia)
|
||||
return new TagLib.Riff.BitmapInfoHeader (
|
||||
type_specific_data, 11);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the stream type GUID of the current instance.
|
||||
/// </summary>
|
||||
/// <summary>
|
||||
/// A <see cref="System.Guid" /> object containing the stream
|
||||
/// type GUID of the current instance.
|
||||
/// </summary>
|
||||
public System.Guid StreamType {
|
||||
get {return stream_type;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the error correction type GUID of the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <summary>
|
||||
/// A <see cref="System.Guid" /> object containing the error
|
||||
/// correction type GUID of the current instance.
|
||||
/// </summary>
|
||||
public System.Guid ErrorCorrectionType {
|
||||
get {return error_correction_type;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the time offset at which the stream described by the
|
||||
/// current instance begins.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="TimeSpan" /> value containing the time
|
||||
/// offset at which the stream described by the current
|
||||
/// instance begins.
|
||||
/// </value>
|
||||
public TimeSpan TimeOffset {
|
||||
get {return new TimeSpan ((long)time_offset);}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the flags that apply to the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="ushort" /> value containing the flags that
|
||||
/// apply to the current instance.
|
||||
/// </value>
|
||||
public ushort Flags {
|
||||
get {return flags;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type specific data contained in the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="ByteVector" /> object containing the type
|
||||
/// specific data contained in the current instance.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// The contents of this value are dependant on the type
|
||||
/// contained in <see cref="StreamType" />.
|
||||
/// </remarks>
|
||||
public ByteVector TypeSpecificData {
|
||||
get {return type_specific_data;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the error correction data contained in the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="ByteVector" /> object containing the error
|
||||
/// correction data contained in the current instance.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// The contents of this value are dependant on the type
|
||||
/// contained in <see cref="ErrorCorrectionType" />.
|
||||
/// </remarks>
|
||||
public ByteVector ErrorCorrectionData {
|
||||
get {return error_correction_data;}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Renders the current instance as a raw ASF object.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector" /> object containing the
|
||||
/// rendered version of the current instance.
|
||||
/// </returns>
|
||||
public override ByteVector Render ()
|
||||
{
|
||||
ByteVector output = stream_type.ToByteArray ();
|
||||
output.Add (error_correction_type.ToByteArray ());
|
||||
output.Add (RenderQWord (time_offset));
|
||||
output.Add (RenderDWord ((uint)
|
||||
type_specific_data.Count));
|
||||
output.Add (RenderDWord ((uint)
|
||||
error_correction_data.Count));
|
||||
output.Add (RenderWord (flags));
|
||||
output.Add (RenderDWord (reserved));
|
||||
output.Add (type_specific_data);
|
||||
output.Add (error_correction_data);
|
||||
|
||||
return Render (output);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
//
|
||||
// UnknownObject.cs: Provides a simple and generic representation of an object
|
||||
// not identified by TagLib# so that its contents may be preserved.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
//
|
||||
// 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.Asf
|
||||
{
|
||||
/// <summary>
|
||||
/// This class extends <see cref="Object" /> to provide a
|
||||
/// representation of an unknown object which can be read from and
|
||||
/// written to disk.
|
||||
/// </summary>
|
||||
public class UnknownObject : Object
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
private ByteVector data;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="UnknownObject" /> by reading the contents from a
|
||||
/// specified position in a specified file.
|
||||
/// </summary>
|
||||
/// <param name="file">
|
||||
/// A <see cref="Asf.File" /> object containing the file from
|
||||
/// which the contents of the new instance are to be read.
|
||||
/// </param>
|
||||
/// <param name="position">
|
||||
/// A <see cref="long" /> value specify at what position to
|
||||
/// read the object.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="file" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// <paramref name="position" /> is less than zero or greater
|
||||
/// than the size of the file.
|
||||
/// </exception>
|
||||
public UnknownObject (Asf.File file, long position)
|
||||
: base (file, position)
|
||||
{
|
||||
data = file.ReadBlock ((int) (OriginalSize - 24));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the data contained in the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="ByteVector" /> object containing the data
|
||||
/// contained in the current instance.
|
||||
/// </value>
|
||||
public ByteVector Data {
|
||||
get {return data;}
|
||||
set {data = value;}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Renders the current instance as a raw ASF object.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector" /> object containing the
|
||||
/// rendered version of the current instance.
|
||||
/// </returns>
|
||||
public override ByteVector Render ()
|
||||
{
|
||||
return Render (data);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,281 +0,0 @@
|
||||
//
|
||||
// ByteVectorList.cs:
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
// Aaron Bockover (abockover@novell.com)
|
||||
//
|
||||
// Original Source:
|
||||
// tbytevectorlist.cpp from TagLib
|
||||
//
|
||||
// Copyright (C) 2005-2007 Brian Nickel
|
||||
// Copyright (C) 2006 Novell, Inc.
|
||||
// Copyright (C) 2002,2003 Scott Wheeler (Original Implementation)
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License version
|
||||
// 2.1 as published by the Free Software Foundation.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
// USA
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace TagLib {
|
||||
/// <summary>
|
||||
/// This class extends <see cref="T:TagLib.ListBase`1"/> to represent
|
||||
/// a collection of <see cref="ByteVector" /> objects.
|
||||
/// </summary>
|
||||
[ComVisible(false)]
|
||||
public class ByteVectorCollection : ListBase<ByteVector>
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="ByteVectorCollection" /> with no contents.
|
||||
/// </summary>
|
||||
public ByteVectorCollection ()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="ByteVectorCollection" /> with specified contents.
|
||||
/// </summary>
|
||||
/// <param name="list">
|
||||
/// A <see cref="T:System.Collections.Generic.IEnumerable`1"
|
||||
/// /> containing <see cref="ByteVector" /> objects to add to
|
||||
/// the current instance.
|
||||
/// </param>
|
||||
public ByteVectorCollection(IEnumerable<ByteVector> list)
|
||||
{
|
||||
if (list != null)
|
||||
Add (list);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="ByteVectorCollection" /> with specified contents.
|
||||
/// </summary>
|
||||
/// <param name="list">
|
||||
/// A <see cref="ByteVector[]" /> containing objects to add to
|
||||
/// the current instance.
|
||||
/// </param>
|
||||
public ByteVectorCollection (params ByteVector[] list)
|
||||
{
|
||||
if (list != null)
|
||||
Add (list);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a sorted insert of a <see cref="ByteVector" />
|
||||
/// object into the current instance, optionally only adding
|
||||
/// if the item is unique.
|
||||
/// </summary>
|
||||
/// <param name="item">
|
||||
/// A <see cref="ByteVector" /> object to add to the current
|
||||
/// instance.
|
||||
/// </param>
|
||||
/// <param name="unique">
|
||||
/// If <see langword="true" />, the object will only be added
|
||||
/// if an identical value is not already contained in the
|
||||
/// current instance.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="item" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public override void SortedInsert (ByteVector item, bool unique)
|
||||
{
|
||||
if (item == null)
|
||||
throw new ArgumentNullException ("item");
|
||||
|
||||
// FIXME: This is not used, but if it is a faster
|
||||
// method could be used.
|
||||
int i = 0;
|
||||
for(; i < Count; i++) {
|
||||
if (item == this[i] && unique)
|
||||
return;
|
||||
|
||||
if (item >= this[i])
|
||||
break;
|
||||
}
|
||||
|
||||
Insert (i + 1, item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the current instance to a <see cref="ByteVector"
|
||||
/// /> by joining the contents together with a specified
|
||||
/// separator.
|
||||
/// </summary>
|
||||
/// <param name="separator">
|
||||
/// A <see cref="ByteVector"/> object to separate the
|
||||
/// combined contents of the current instance.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A new <see cref="ByteVector"/> object containing the
|
||||
/// joined contents of the current instance.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="separator" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public ByteVector ToByteVector (ByteVector separator)
|
||||
{
|
||||
if (separator == null)
|
||||
throw new ArgumentNullException ("separator");
|
||||
|
||||
ByteVector vector = new ByteVector();
|
||||
|
||||
for(int i = 0; i < Count; i++) {
|
||||
if(i != 0 && separator.Count > 0)
|
||||
vector.Add(separator);
|
||||
|
||||
vector.Add(this[i]);
|
||||
}
|
||||
|
||||
return vector;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Splits a <see cref="ByteVector" /> object using a
|
||||
/// pattern.
|
||||
/// </summary>
|
||||
/// <param name="vector">
|
||||
/// A <see cref="ByteVector"/> object to split.
|
||||
/// </param>
|
||||
/// <param name="pattern">
|
||||
/// A <see cref="ByteVector"/> object to use to split
|
||||
/// <paramref name="vector" /> with.
|
||||
/// </param>
|
||||
/// <param name="byteAlign">
|
||||
/// A <see cref="int" /> specifying the byte align to use
|
||||
/// when splitting. In order to split when a pattern is
|
||||
/// encountered, the index at which it is found must be
|
||||
// divisible by <paramref name="byteAlign" />.
|
||||
/// </param>
|
||||
/// <param name="max">
|
||||
/// A <see cref="int" /> value specifying the maximum number
|
||||
/// of objects to return, or zero to not to limit the number.
|
||||
/// If that that number is reached, the last value will
|
||||
/// contain the remainder of the file even if it contains
|
||||
/// more instances of <paramref name="pattern" />.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVectorCollection" /> object containing
|
||||
/// the split contents of the current instance.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="vector" /> or <paramref name="pattern" />
|
||||
/// is <see langword="null" />.
|
||||
/// </exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// <paramref name="byteAlign" /> is less than 1.
|
||||
/// </exception>
|
||||
public static ByteVectorCollection Split (ByteVector vector,
|
||||
ByteVector pattern,
|
||||
int byteAlign,
|
||||
int max)
|
||||
{
|
||||
if (vector == null)
|
||||
throw new ArgumentNullException ("vector");
|
||||
|
||||
if (pattern == null)
|
||||
throw new ArgumentNullException ("pattern");
|
||||
|
||||
if (byteAlign < 1)
|
||||
throw new ArgumentOutOfRangeException (
|
||||
"byteAlign",
|
||||
"byteAlign must be at least 1.");
|
||||
|
||||
ByteVectorCollection list = new ByteVectorCollection ();
|
||||
int previous_offset = 0;
|
||||
|
||||
for (int offset = vector.Find(pattern, 0, byteAlign);
|
||||
offset != -1 && (max < 1 ||
|
||||
max > list.Count + 1);
|
||||
offset = vector.Find (pattern,
|
||||
offset + pattern.Count, byteAlign)) {
|
||||
list.Add (vector.Mid (previous_offset,
|
||||
offset - previous_offset));
|
||||
previous_offset = offset + pattern.Count;
|
||||
}
|
||||
|
||||
if (previous_offset < vector.Count)
|
||||
list.Add (vector.Mid (previous_offset,
|
||||
vector.Count - previous_offset));
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Splits a <see cref="ByteVector" /> object using a
|
||||
/// pattern.
|
||||
/// </summary>
|
||||
/// <param name="vector">
|
||||
/// A <see cref="ByteVector"/> object to split.
|
||||
/// </param>
|
||||
/// <param name="pattern">
|
||||
/// A <see cref="ByteVector"/> object to use to split
|
||||
/// <paramref name="vector" /> with.
|
||||
/// </param>
|
||||
/// <param name="byteAlign">
|
||||
/// A <see cref="int" /> specifying the byte align to use
|
||||
/// when splitting. In order to split when a pattern is
|
||||
/// encountered, the index at which it is found must be
|
||||
// divisible by <paramref name="byteAlign" />.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVectorCollection" /> object containing
|
||||
/// the split contents of the current instance.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="vector" /> or <paramref name="pattern" />
|
||||
/// is <see langword="null" />.
|
||||
/// </exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// <paramref name="byteAlign" /> is less than 1.
|
||||
/// </exception>
|
||||
public static ByteVectorCollection Split (ByteVector vector,
|
||||
ByteVector pattern,
|
||||
int byteAlign)
|
||||
{
|
||||
return Split(vector, pattern, byteAlign, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Splits a <see cref="ByteVector" /> object using a
|
||||
/// pattern.
|
||||
/// </summary>
|
||||
/// <param name="vector">
|
||||
/// A <see cref="ByteVector"/> object to split.
|
||||
/// </param>
|
||||
/// <param name="pattern">
|
||||
/// A <see cref="ByteVector"/> object to use to split
|
||||
/// <paramref name="vector" /> with.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVectorCollection" /> object containing
|
||||
/// the split contents of the current instance.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="vector" /> or <paramref name="pattern" />
|
||||
/// is <see langword="null" />.
|
||||
/// </exception>
|
||||
public static ByteVectorCollection Split (ByteVector vector,
|
||||
ByteVector pattern)
|
||||
{
|
||||
return Split(vector, pattern, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,168 +0,0 @@
|
||||
//
|
||||
// CorruptFileException.cs:
|
||||
//
|
||||
// Author:
|
||||
// Aaron Bockover (abockover@novell.com)
|
||||
//
|
||||
// Original Source:
|
||||
// Entagged#
|
||||
//
|
||||
// Copyright (C) 2006 Novell, Inc.
|
||||
//
|
||||
// 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.Runtime.Serialization;
|
||||
|
||||
namespace TagLib {
|
||||
/// <summary>
|
||||
/// This class extends <see cref="Exception" /> and is used to
|
||||
/// indicate that a file or tag is corrupt.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This exception will be thrown if invalid data interferes with the
|
||||
/// reading of the file or tag. One common example is in the (legal)
|
||||
/// downloading of media files with BitTorrent, in which case large
|
||||
/// portions of the file will contain zeroed bytes.
|
||||
/// </remarks>
|
||||
/// <example>
|
||||
/// <para>Catching an exception when creating a <see
|
||||
/// cref="File" />.</para>
|
||||
/// <code lang="C#">
|
||||
/// using System;
|
||||
/// using TagLib;
|
||||
///
|
||||
/// public class ExceptionTest
|
||||
/// {
|
||||
/// public static void Main ()
|
||||
/// {
|
||||
/// try {
|
||||
/// File file = File.Create ("partial.mp3"); // Partial download.
|
||||
/// } catch (CorruptFileException e) {
|
||||
/// Console.WriteLine ("That file is corrupt: {0}", e.ToString ());
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// </code>
|
||||
/// <code lang="C++">
|
||||
/// #using <System.dll>
|
||||
/// #using <taglib-sharp.dll>
|
||||
///
|
||||
/// using System;
|
||||
/// using TagLib;
|
||||
///
|
||||
/// void main ()
|
||||
/// {
|
||||
/// try {
|
||||
/// File file = File::Create ("partial.mp3"); // Partial download.
|
||||
/// } catch (CorruptFileException^ e) {
|
||||
/// Console::WriteLine ("That file is corrupt: {0}", e);
|
||||
/// }
|
||||
/// }
|
||||
/// </code>
|
||||
/// <code lang="VB">
|
||||
/// Imports System
|
||||
/// Imports TagLib
|
||||
///
|
||||
/// Public Class ExceptionTest
|
||||
/// Public Shared Sub Main ()
|
||||
/// Try
|
||||
/// file As File = File.Create ("partial.mp3") ' Partial download.
|
||||
/// Catch e As CorruptFileException
|
||||
/// Console.WriteLine ("That file is corrupt: {0}", e.ToString ());
|
||||
/// End Try
|
||||
/// End Sub
|
||||
/// End Class
|
||||
/// </code>
|
||||
/// <code lang="Boo">
|
||||
/// import System
|
||||
/// import TagLib
|
||||
///
|
||||
/// try:
|
||||
/// file As File = File.Create ("partial.mp3") # Partial download.
|
||||
/// catch e as CorruptFileException:
|
||||
/// Console.WriteLine ("That file is corrupt: {0}", e.ToString ());
|
||||
/// </code>
|
||||
/// </example>
|
||||
[Serializable]
|
||||
public class CorruptFileException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="CorruptFileException" /> with a specified
|
||||
/// message.
|
||||
/// </summary>
|
||||
/// <param name="message">
|
||||
/// A <see cref="string" /> containing a message explaining
|
||||
/// the reason for the exception.
|
||||
/// </param>
|
||||
public CorruptFileException (string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="CorruptFileException" /> with the default
|
||||
/// values.
|
||||
/// </summary>
|
||||
public CorruptFileException () : base()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="CorruptFileException" /> with a specified
|
||||
/// message containing a specified exception.
|
||||
/// </summary>
|
||||
/// <param name="message">
|
||||
/// A <see cref="string" /> containing a message explaining
|
||||
/// the reason for the exception.
|
||||
/// </param>
|
||||
/// <param name="innerException">
|
||||
/// A <see cref="Exception" /> object to be contained in the
|
||||
/// new exception. For example, previously caught exception.
|
||||
/// </param>
|
||||
public CorruptFileException (string message,
|
||||
Exception innerException)
|
||||
: base (message, innerException)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="CorruptFileException" /> from a specified
|
||||
/// serialization info and streaming context.
|
||||
/// </summary>
|
||||
/// <param name="info">
|
||||
/// A <see cref="SerializationInfo" /> object containing the
|
||||
/// serialized data to be used for the new instance.
|
||||
/// </param>
|
||||
/// <param name="context">
|
||||
/// A <see cref="StreamingContext" /> object containing the
|
||||
/// streaming context information for the new instance.
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// This constructor is implemented because <see
|
||||
/// cref="CorruptFileException" /> implements the <see
|
||||
/// cref="ISerializable" /> interface.
|
||||
/// </remarks>
|
||||
protected CorruptFileException (SerializationInfo info,
|
||||
StreamingContext context)
|
||||
: base(info, context)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
//
|
||||
// Debugger.cs:
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
//
|
||||
// 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 {
|
||||
internal static class Debugger
|
||||
{
|
||||
public delegate void DebugMessageSentHandler (string message);
|
||||
|
||||
public static event DebugMessageSentHandler DebugMessageSent;
|
||||
|
||||
public static void Debug (string message)
|
||||
{
|
||||
if (DebugMessageSent != null)
|
||||
DebugMessageSent (message);
|
||||
}
|
||||
|
||||
public static void DumpHex (ByteVector data)
|
||||
{
|
||||
DumpHex (data.Data);
|
||||
}
|
||||
|
||||
public static void DumpHex (byte [] data)
|
||||
{
|
||||
int cols = 16;
|
||||
int rows = data.Length / cols +
|
||||
(data.Length % cols != 0 ? 1 : 0);
|
||||
|
||||
for (int row = 0; row < rows; row ++) {
|
||||
for (int col = 0; col < cols; col ++) {
|
||||
if (row == rows - 1 &&
|
||||
data.Length % cols != 0 &&
|
||||
col >= data.Length % cols)
|
||||
Console.Write (" ");
|
||||
else
|
||||
Console.Write (" {0:x2}",
|
||||
data [row * cols + col]);
|
||||
}
|
||||
|
||||
Console.Write (" | ");
|
||||
|
||||
for (int col = 0; col < cols; col ++) {
|
||||
if (row == rows - 1 &&
|
||||
data.Length % cols != 0 &&
|
||||
col >= data.Length % cols)
|
||||
Console.Write (" ");
|
||||
else
|
||||
WriteByte2 (
|
||||
data [row * cols + col]);
|
||||
}
|
||||
|
||||
Console.WriteLine ();
|
||||
}
|
||||
Console.WriteLine ();
|
||||
}
|
||||
|
||||
private static void WriteByte2 (byte data)
|
||||
{
|
||||
foreach (char c in allowed)
|
||||
if (c == data) {
|
||||
Console.Write (c);
|
||||
return;
|
||||
}
|
||||
|
||||
Console.Write (".");
|
||||
}
|
||||
|
||||
private static string allowed = "0123456789abcdefghijklmnopqr" +
|
||||
"stuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ`~!@#$%^&*()_+-={}" +
|
||||
"[];:'\",.<>?/\\|";
|
||||
|
||||
|
||||
private static Dictionary <object, Dictionary <object, DebugTimeData>>
|
||||
debug_times = new Dictionary <object, Dictionary <object, DebugTimeData>> ();
|
||||
|
||||
public static void AddDebugTime (object o1, object o2, DateTime start)
|
||||
{
|
||||
DebugTimeData data = new DebugTimeData (DateTime.Now - start, 1);
|
||||
if (debug_times.ContainsKey (o1) && debug_times [o1].ContainsKey (o2)) {
|
||||
data.time += debug_times [o1][o2].time;
|
||||
data.occurances += debug_times [o1][o2].occurances;
|
||||
}
|
||||
|
||||
if (!debug_times.ContainsKey (o1))
|
||||
debug_times.Add (o1, new Dictionary <object, DebugTimeData> ());
|
||||
|
||||
if (!debug_times [o1].ContainsKey (o2))
|
||||
debug_times [o1].Add (o2, data);
|
||||
else
|
||||
debug_times [o1][o2] = data;
|
||||
}
|
||||
|
||||
public static void DumpDebugTime (object o1)
|
||||
{
|
||||
Console.WriteLine (o1.ToString ());
|
||||
if (!debug_times.ContainsKey (o1))
|
||||
return;
|
||||
|
||||
foreach (KeyValuePair <object, DebugTimeData> pair in debug_times [o1]) {
|
||||
Console.WriteLine (" {0}", pair.Key.ToString ());
|
||||
Console.WriteLine (" Objects: {0}", pair.Value.time);
|
||||
Console.WriteLine (" Total: {0}", pair.Value.occurances);
|
||||
Console.WriteLine (" Average: {0}", new TimeSpan (pair.Value.time.Ticks / pair.Value.occurances));
|
||||
Console.WriteLine (String.Empty);
|
||||
}
|
||||
|
||||
debug_times.Remove (o1);
|
||||
}
|
||||
|
||||
private struct DebugTimeData
|
||||
{
|
||||
public TimeSpan time;
|
||||
public long occurances;
|
||||
|
||||
public DebugTimeData (TimeSpan time, int occurances)
|
||||
{
|
||||
this.time = time;
|
||||
this.occurances = occurances;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,148 +0,0 @@
|
||||
//
|
||||
// FileTypes.cs: Provides a mechanism for registering file classes and mime-
|
||||
// types, to be used when constructing a class via TagLib.File.Create.
|
||||
//
|
||||
// Author:
|
||||
// Aaron Bockover (abockover@novell.com)
|
||||
//
|
||||
// Copyright (C) 2006 Novell, Inc.
|
||||
//
|
||||
// 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 {
|
||||
/// <summary>
|
||||
/// This static class provides a mechanism for registering file
|
||||
/// classes and mime-types, to be used when constructing a class via
|
||||
/// <see cref="File.Create(string)" />.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>The default types built into the taglib-sharp.dll assembly
|
||||
/// are registered automatically when the class is initialized. To
|
||||
/// register your own custom types, use <see cref="Register"
|
||||
/// />.</para>
|
||||
/// </remarks>
|
||||
/// <seealso cref="SupportedMimeType" />
|
||||
public static class FileTypes
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains a mapping between mime-types and the <see
|
||||
/// cref="File" /> subclasses that support them.
|
||||
/// </summary>
|
||||
private static Dictionary<string, Type> file_types;
|
||||
|
||||
/// <summary>
|
||||
/// Contains a static array of file types contained in the
|
||||
/// TagLib# assembly.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// A static Type array is used instead of getting types by
|
||||
/// reflecting the executing assembly as Assembly.GetTypes is
|
||||
/// very inefficient and leaks every type instance under
|
||||
/// Mono. Not reflecting taglib-sharp.dll saves about 120KB
|
||||
/// of heap.
|
||||
/// </remarks>
|
||||
private static Type [] static_file_types = new Type [] {
|
||||
typeof(TagLib.Aac.File),
|
||||
typeof(TagLib.Aiff.File),
|
||||
typeof(TagLib.Ape.File),
|
||||
typeof(TagLib.Asf.File),
|
||||
typeof(TagLib.Flac.File),
|
||||
typeof(TagLib.Matroska.File),
|
||||
typeof(TagLib.Gif.File),
|
||||
typeof(TagLib.Image.NoMetadata.File),
|
||||
typeof(TagLib.Jpeg.File),
|
||||
typeof(TagLib.Mpeg4.File),
|
||||
typeof(TagLib.Mpeg.AudioFile),
|
||||
typeof(TagLib.Mpeg.File),
|
||||
typeof(TagLib.MusePack.File),
|
||||
typeof(TagLib.Ogg.File),
|
||||
typeof(TagLib.Png.File),
|
||||
typeof(TagLib.Riff.File),
|
||||
typeof(TagLib.Tiff.Arw.File),
|
||||
typeof(TagLib.Tiff.Cr2.File),
|
||||
typeof(TagLib.Tiff.Dng.File),
|
||||
typeof(TagLib.Tiff.File),
|
||||
typeof(TagLib.Tiff.Nef.File),
|
||||
typeof(TagLib.Tiff.Pef.File),
|
||||
typeof(TagLib.Tiff.Rw2.File),
|
||||
typeof(TagLib.WavPack.File)
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes the <see cref="FileTypes" />
|
||||
/// class by registering the default types.
|
||||
/// </summary>
|
||||
static FileTypes ()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the class by registering the default types.
|
||||
/// </summary>
|
||||
internal static void Init ()
|
||||
{
|
||||
if(file_types != null)
|
||||
return;
|
||||
|
||||
file_types = new Dictionary<string, Type>();
|
||||
|
||||
foreach(Type type in static_file_types)
|
||||
Register (type);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers a <see cref="File" /> subclass to be used when
|
||||
/// creating files via <see cref="File.Create(string)" />.
|
||||
/// </summary>
|
||||
/// <param name="type">
|
||||
/// A <see cref="Type" /> object for the class to register.
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// In order to register mime-types, the class represented by
|
||||
/// <paramref name="type" /> should use the <see
|
||||
/// cref="SupportedMimeType" /> custom attribute.
|
||||
/// </remarks>
|
||||
public static void Register (Type type)
|
||||
{
|
||||
Attribute [] attrs = Attribute.GetCustomAttributes (type,
|
||||
typeof(SupportedMimeType), false);
|
||||
|
||||
if(attrs == null || attrs.Length == 0)
|
||||
return;
|
||||
|
||||
foreach(SupportedMimeType attr in attrs)
|
||||
file_types.Add(attr.MimeType, type);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a dictionary containing all the supported mime-types
|
||||
/// and file classes used by <see cref="File.Create(string)"
|
||||
/// />.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="T:System.Collections.Generic.IDictionary`2" /> object containing the
|
||||
/// supported mime-types.
|
||||
/// </value>
|
||||
public static IDictionary<string, Type> AvailableTypes {
|
||||
get {return file_types;}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,200 +0,0 @@
|
||||
//
|
||||
// Block.cs: Represents a Flac metadata block.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2007 Brian Nickel
|
||||
//
|
||||
// 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.Flac {
|
||||
/// <summary>
|
||||
/// This class represents a Flac metadata block.
|
||||
/// </summary>
|
||||
public class Block
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Contains the block header.
|
||||
/// </summary>
|
||||
private BlockHeader header;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the block data.
|
||||
/// </summary>
|
||||
private ByteVector data;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="Block" /> with a specified header and internal
|
||||
/// data.
|
||||
/// </summary>
|
||||
/// <param name="header">
|
||||
/// A <see cref="BlockHeader" /> object containing the
|
||||
/// header to use for the new instance.
|
||||
/// </param>
|
||||
/// <param name="data">
|
||||
/// A <see cref="ByteVector" /> object containing the data
|
||||
/// to be contained in the new instance.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="data" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
/// <exception cref="CorruptFileException">
|
||||
/// The size of <paramref name="data" /> does not match the
|
||||
/// size specified in <paramref name="header" />.
|
||||
/// </exception>
|
||||
public Block (BlockHeader header, ByteVector data)
|
||||
{
|
||||
if (data == null)
|
||||
throw new ArgumentNullException ("data");
|
||||
|
||||
if (header.BlockSize != data.Count)
|
||||
throw new CorruptFileException (
|
||||
"Data count not equal to block size.");
|
||||
|
||||
this.header = header;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="Block" /> with of a specified type and internal
|
||||
/// data.
|
||||
/// </summary>
|
||||
/// <param name="type">
|
||||
/// A <see cref="BlockType" /> value indicating the type of
|
||||
/// data stored in <paramref name="data" />.
|
||||
/// </param>
|
||||
/// <param name="data">
|
||||
/// A <see cref="ByteVector" /> object containing the data
|
||||
/// to be contained in the new instance.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="data" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public Block (BlockType type, ByteVector data)
|
||||
{
|
||||
if (data == null)
|
||||
throw new ArgumentNullException ("data");
|
||||
|
||||
header = new BlockHeader (type, (uint) data.Count);
|
||||
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of data contained in the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="BlockType" /> value indicating the type of
|
||||
/// data contained in <see cref="Data" />.
|
||||
/// </value>
|
||||
public BlockType Type {
|
||||
get {return header.BlockType;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not the block represented by the current
|
||||
/// instance is the last metadata block in the Flac stream.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <see langword="true" /> if the block represented by the
|
||||
/// current instance was the last one to appear in the file
|
||||
/// and is followed immediately by the audio data, or <see
|
||||
/// langword="false" /> if another block appears after the
|
||||
/// current one or the block was not read from disk.
|
||||
/// </value>
|
||||
public bool IsLastBlock {
|
||||
get {return header.IsLastBlock;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of the data contained in the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
public uint DataSize {
|
||||
get {return header.BlockSize;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the total size of the block represented by the
|
||||
/// current instance as it appears on disk.
|
||||
/// </summary>
|
||||
public uint TotalSize {
|
||||
get {return DataSize + BlockHeader.Size;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the data contained in the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="ByteVector" /> object containing the data
|
||||
/// stored in the current instance.
|
||||
/// </value>
|
||||
public ByteVector Data {
|
||||
get {return data;}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Renders the current instance as a raw Flac metadata
|
||||
/// block.
|
||||
/// </summary>
|
||||
/// <param name="isLastBlock">
|
||||
/// A <see cref="bool" /> value indicating whether or not the
|
||||
/// block is to be marked as the last metadata block.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector" /> object containing the
|
||||
/// rendered version of the current instance.
|
||||
/// </returns>
|
||||
public ByteVector Render (bool isLastBlock)
|
||||
{
|
||||
if (this.data == null)
|
||||
throw new InvalidOperationException (
|
||||
"Cannot render empty blocks.");
|
||||
|
||||
ByteVector data = header.Render (isLastBlock);
|
||||
data.Add (this.data);
|
||||
return data;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,197 +0,0 @@
|
||||
//
|
||||
// BlockHeader.cs:
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2007 Brian Nickel
|
||||
//
|
||||
// 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;
|
||||
|
||||
namespace TagLib.Flac
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the contents of a Flac block in <see cref="BlockHeader"
|
||||
/// />.
|
||||
/// </summary>
|
||||
public enum BlockType
|
||||
{
|
||||
/// <summary>
|
||||
/// The block contains stream information.
|
||||
/// </summary>
|
||||
StreamInfo = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The block contains padding.
|
||||
/// </summary>
|
||||
Padding,
|
||||
|
||||
/// <summary>
|
||||
/// The block contains application data.
|
||||
/// </summary>
|
||||
Application,
|
||||
|
||||
/// <summary>
|
||||
/// The block contains seek table.
|
||||
/// </summary>
|
||||
SeekTable,
|
||||
|
||||
/// <summary>
|
||||
/// The block contains a Xipp comment.
|
||||
/// </summary>
|
||||
XiphComment,
|
||||
|
||||
/// <summary>
|
||||
/// The block contains a cue sheet.
|
||||
/// </summary>
|
||||
CueSheet,
|
||||
|
||||
/// <summary>
|
||||
/// The block contains a picture.
|
||||
/// </summary>
|
||||
Picture
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This structure provides a representation of a Flac metadata block
|
||||
/// header structure.
|
||||
/// </summary>
|
||||
public struct BlockHeader
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains the block type.
|
||||
/// </summary>
|
||||
private BlockType block_type;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether or not this is the last metadata block.
|
||||
/// </summary>
|
||||
private bool is_last_block;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the block size.
|
||||
/// </summary>
|
||||
private uint block_size;
|
||||
|
||||
/// <summary>
|
||||
/// The size of a block header.
|
||||
/// </summary>
|
||||
public const uint Size = 4;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="BlockHeader" /> by reading a raw header from a <see
|
||||
/// cref="ByteVector" /> object.
|
||||
/// </summary>
|
||||
/// <param name="data">
|
||||
/// A <see cref="ByteVector" /> object containing a raw
|
||||
/// block header.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="data" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
/// <exception cref="CorruptFileException">
|
||||
/// <paramref name="data" /> contains less than 4 bytes.
|
||||
/// </exception>
|
||||
public BlockHeader (ByteVector data)
|
||||
{
|
||||
if (data == null)
|
||||
throw new ArgumentNullException ("data");
|
||||
|
||||
if (data.Count < Size)
|
||||
throw new CorruptFileException (
|
||||
"Not enough data in Flac header.");
|
||||
|
||||
block_type = (BlockType) (data[0] & 0x7f);
|
||||
is_last_block = (data[0] & 0x80) != 0;
|
||||
block_size = data.Mid (1,3).ToUInt ();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="BlockHeader" /> for a specified block type and size.
|
||||
/// </summary>
|
||||
/// <param name="type">
|
||||
/// A <see cref="BlockType" /> value describing the contents
|
||||
/// of the block.
|
||||
/// </param>
|
||||
/// <param name="blockSize">
|
||||
/// A <see cref="uint" /> value containing the block data
|
||||
/// size minus the size of the header.
|
||||
/// </param>
|
||||
public BlockHeader (BlockType type, uint blockSize)
|
||||
{
|
||||
block_type = type;
|
||||
is_last_block = false;
|
||||
block_size = blockSize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renderes the current instance as a raw Flac block header.
|
||||
/// </summary>
|
||||
/// <param name="isLastBlock">
|
||||
/// A <see cref="bool" /> value specifying whether or not the
|
||||
/// header is the last header of the file.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector" /> object containing the
|
||||
/// rendered header.
|
||||
/// </returns>
|
||||
public ByteVector Render (bool isLastBlock)
|
||||
{
|
||||
ByteVector data = ByteVector.FromUInt (block_size);
|
||||
data [0] = (byte)(block_type + (isLastBlock ? 0x80 : 0));
|
||||
return data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of block described by the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="BlockType" /> value describing the block
|
||||
/// type.
|
||||
/// </value>
|
||||
public BlockType BlockType {
|
||||
get {return block_type;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether or not the block is the last in the file.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <see langword="true" /> if the block is the last in the
|
||||
/// file; otherwise <see langword="false" />.
|
||||
/// </value>
|
||||
public bool IsLastBlock {
|
||||
get {return is_last_block;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of the block described by the current
|
||||
/// instance, minus the block header.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="uint" /> value containing the size of the
|
||||
/// block, minus the header.
|
||||
/// </value>
|
||||
public uint BlockSize {
|
||||
get {return block_size;}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,682 +0,0 @@
|
||||
//
|
||||
// File.cs: Provides tagging and properties support for Xiph's Flac audio files.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Original Source:
|
||||
// flacfile.cpp from TagLib
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
// Copyright (C) 2003-2004 Allan Sandfeld Jensen (Original Implementation)
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License version
|
||||
// 2.1 as published by the Free Software Foundation.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
// USA
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace TagLib.Flac {
|
||||
/// <summary>
|
||||
/// This class extends <see cref="TagLib.NonContainer.File" /> to
|
||||
/// provide tagging and properties support for Xiph's Flac audio
|
||||
/// files.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// A <see cref="TagLib.Ogg.XiphComment" /> will be added
|
||||
/// automatically to any file that doesn't contain one. This change
|
||||
/// does not effect the physical file until <see cref="Save" /> is
|
||||
/// called and can be reversed using the following method:
|
||||
/// <code>file.RemoveTags (file.TagTypes & ~file.TagTypesOnDisk);</code>
|
||||
/// </remarks>
|
||||
[SupportedMimeType("taglib/flac", "flac")]
|
||||
[SupportedMimeType("audio/x-flac")]
|
||||
[SupportedMimeType("application/x-flac")]
|
||||
[SupportedMimeType("audio/flac")]
|
||||
public class File : TagLib.NonContainer.File
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Contains the Flac metadata tag.
|
||||
/// </summary>
|
||||
private Metadata metadata = null;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the combination of all file tags.
|
||||
/// </summary>
|
||||
private CombinedTag tag = null;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the Flac header block.
|
||||
/// </summary>
|
||||
private ByteVector header_block = null;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the stream start position.
|
||||
/// </summary>
|
||||
private long stream_start = 0;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="File" /> for a specified path in the local file
|
||||
/// system and specified read style.
|
||||
/// </summary>
|
||||
/// <param name="path">
|
||||
/// A <see cref="string" /> object containing the path of the
|
||||
/// file to use in the new instance.
|
||||
/// </param>
|
||||
/// <param name="propertiesStyle">
|
||||
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||
/// of accuracy to read the media properties, or <see
|
||||
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="path" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public File (string path, ReadStyle propertiesStyle)
|
||||
: base (path, propertiesStyle)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="File" /> for a specified path in the local file
|
||||
/// system with an average read style.
|
||||
/// </summary>
|
||||
/// <param name="path">
|
||||
/// A <see cref="string" /> object containing the path of the
|
||||
/// file to use in the new instance.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="path" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public File (string path)
|
||||
: base (path)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="File" /> for a specified file abstraction and
|
||||
/// specified read style.
|
||||
/// </summary>
|
||||
/// <param name="abstraction">
|
||||
/// A <see cref="IFileAbstraction" /> object to use when
|
||||
/// reading from and writing to the file.
|
||||
/// </param>
|
||||
/// <param name="propertiesStyle">
|
||||
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||
/// of accuracy to read the media properties, or <see
|
||||
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="abstraction" /> is <see langword="null"
|
||||
/// />.
|
||||
/// </exception>
|
||||
public File (File.IFileAbstraction abstraction,
|
||||
ReadStyle propertiesStyle)
|
||||
: base (abstraction, propertiesStyle)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="File" /> for a specified file abstraction with an
|
||||
/// average read style.
|
||||
/// </summary>
|
||||
/// <param name="abstraction">
|
||||
/// A <see cref="IFileAbstraction" /> object to use when
|
||||
/// reading from and writing to the file.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="abstraction" /> is <see langword="null"
|
||||
/// />.
|
||||
/// </exception>
|
||||
public File (File.IFileAbstraction abstraction)
|
||||
: base (abstraction)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets a abstract representation of all tags stored in the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="TagLib.Tag" /> object representing all tags
|
||||
/// stored in the current instance.
|
||||
/// </value>
|
||||
public override TagLib.Tag Tag {
|
||||
get {return tag;}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Saves the changes made in the current instance to the
|
||||
/// file it represents.
|
||||
/// </summary>
|
||||
public override void Save ()
|
||||
{
|
||||
Mode = AccessMode.Write;
|
||||
try {
|
||||
// Update the tags at the beginning of the file.
|
||||
long metadata_start = StartTag.Write ();
|
||||
long metadata_end;
|
||||
|
||||
// Get all the blocks, but don't read the data for ones
|
||||
// we're filling with stored data.
|
||||
IList<Block> old_blocks = ReadBlocks (ref metadata_start,
|
||||
out metadata_end, BlockMode.Blacklist,
|
||||
BlockType.XiphComment, BlockType.Picture);
|
||||
|
||||
// Create new vorbis comments is they don't exist.
|
||||
GetTag (TagTypes.Xiph, true);
|
||||
|
||||
// Create new blocks and add the basics.
|
||||
List<Block> new_blocks = new List<Block> ();
|
||||
new_blocks.Add (old_blocks [0]);
|
||||
|
||||
// Add blocks we don't deal with from the file.
|
||||
foreach (Block block in old_blocks)
|
||||
if (block.Type != BlockType.StreamInfo &&
|
||||
block.Type != BlockType.XiphComment &&
|
||||
block.Type != BlockType.Picture &&
|
||||
block.Type != BlockType.Padding)
|
||||
new_blocks.Add (block);
|
||||
|
||||
new_blocks.Add (new Block (BlockType.XiphComment,
|
||||
(GetTag (TagTypes.Xiph, true) as
|
||||
Ogg.XiphComment).Render (false)));
|
||||
|
||||
foreach (IPicture picture in metadata.Pictures) {
|
||||
if (picture == null)
|
||||
continue;
|
||||
|
||||
new_blocks.Add (new Block (BlockType.Picture,
|
||||
new Picture (picture).Render ()));
|
||||
}
|
||||
|
||||
// Get the length of the blocks.
|
||||
long length = 0;
|
||||
foreach (Block block in new_blocks)
|
||||
length += block.TotalSize;
|
||||
|
||||
// Find the padding size to avoid trouble. If that fails
|
||||
// make some.
|
||||
long padding_size = metadata_end - metadata_start -
|
||||
BlockHeader.Size - length;
|
||||
if (padding_size < 0)
|
||||
padding_size = 1024 * 4;
|
||||
|
||||
// Add a padding block.
|
||||
if (padding_size != 0)
|
||||
new_blocks.Add (new Block (BlockType.Padding,
|
||||
new ByteVector ((int) padding_size)));
|
||||
|
||||
// Render the blocks.
|
||||
ByteVector block_data = new ByteVector ();
|
||||
for (int i = 0; i < new_blocks.Count; i ++)
|
||||
block_data.Add (new_blocks [i].Render (
|
||||
i == new_blocks.Count - 1));
|
||||
|
||||
// Update the blocks.
|
||||
Insert (block_data, metadata_start, metadata_end -
|
||||
metadata_start);
|
||||
|
||||
// Update the tags at the end of the file.
|
||||
EndTag.Write ();
|
||||
|
||||
TagTypesOnDisk = TagTypes;
|
||||
} finally {
|
||||
Mode = AccessMode.Closed;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a tag of a specified type from the current instance,
|
||||
/// optionally creating a new tag if possible.
|
||||
/// </summary>
|
||||
/// <param name="type">
|
||||
/// A <see cref="TagLib.TagTypes" /> value indicating the
|
||||
/// type of tag to read.
|
||||
/// </param>
|
||||
/// <param name="create">
|
||||
/// A <see cref="bool" /> value specifying whether or not to
|
||||
/// try and create the tag if one is not found.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="Tag" /> object containing the tag that was
|
||||
/// found in or added to the current instance. If no
|
||||
/// matching tag was found and none was created, <see
|
||||
/// langword="null" /> is returned.
|
||||
/// </returns>
|
||||
public override TagLib.Tag GetTag (TagTypes type, bool create)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case TagTypes.Xiph:
|
||||
return metadata.GetComment (create, tag);
|
||||
|
||||
case TagTypes.FlacMetadata:
|
||||
return metadata;
|
||||
}
|
||||
|
||||
Tag t = (base.Tag as TagLib.NonContainer.Tag).GetTag (type);
|
||||
|
||||
if (t != null || !create)
|
||||
return t;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case TagTypes.Id3v1:
|
||||
return EndTag.AddTag (type, Tag);
|
||||
|
||||
case TagTypes.Id3v2:
|
||||
return StartTag.AddTag (type, Tag);
|
||||
|
||||
case TagTypes.Ape:
|
||||
return EndTag.AddTag (type, Tag);
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a set of tag types from the current instance.
|
||||
/// </summary>
|
||||
/// <param name="types">
|
||||
/// A bitwise combined <see cref="TagLib.TagTypes" /> value
|
||||
/// containing tag types to be removed from the file.
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// In order to remove all tags from a file, pass <see
|
||||
/// cref="TagTypes.AllTags" /> as <paramref name="types" />.
|
||||
/// </remarks>
|
||||
public override void RemoveTags (TagTypes types)
|
||||
{
|
||||
if ((types & TagTypes.Xiph) != 0)
|
||||
metadata.RemoveComment ();
|
||||
|
||||
if ((types & TagTypes.FlacMetadata) != 0)
|
||||
metadata.Clear ();
|
||||
|
||||
base.RemoveTags (types);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
/// <summary>
|
||||
/// Reads format specific information at the start of the
|
||||
/// file.
|
||||
/// </summary>
|
||||
/// <param name="start">
|
||||
/// A <see cref="long" /> value containing the seek position
|
||||
/// at which the tags end and the media data begins.
|
||||
/// </param>
|
||||
/// <param name="propertiesStyle">
|
||||
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||
/// of accuracy to read the media properties, or <see
|
||||
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||
/// </param>
|
||||
protected override void ReadStart (long start,
|
||||
ReadStyle propertiesStyle)
|
||||
{
|
||||
long end;
|
||||
IList<Block> blocks = ReadBlocks (ref start, out end,
|
||||
BlockMode.Whitelist, BlockType.StreamInfo,
|
||||
BlockType.XiphComment, BlockType.Picture);
|
||||
metadata = new Metadata (blocks);
|
||||
|
||||
TagTypesOnDisk |= metadata.TagTypes;
|
||||
|
||||
if (propertiesStyle != ReadStyle.None) {
|
||||
// Check that the first block is a
|
||||
// METADATA_BLOCK_STREAMINFO.
|
||||
if (blocks.Count == 0 ||
|
||||
blocks [0].Type != BlockType.StreamInfo)
|
||||
throw new CorruptFileException (
|
||||
"FLAC stream does not begin with StreamInfo.");
|
||||
|
||||
// The stream exists from the end of the last
|
||||
// block to the end of the file.
|
||||
stream_start = end;
|
||||
header_block = blocks [0].Data;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads format specific information at the end of the
|
||||
/// file.
|
||||
/// </summary>
|
||||
/// <param name="end">
|
||||
/// A <see cref="long" /> value containing the seek position
|
||||
/// at which the media data ends and the tags begin.
|
||||
/// </param>
|
||||
/// <param name="propertiesStyle">
|
||||
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||
/// of accuracy to read the media properties, or <see
|
||||
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||
/// </param>
|
||||
protected override void ReadEnd (long end,
|
||||
ReadStyle propertiesStyle)
|
||||
{
|
||||
tag = new CombinedTag (metadata, base.Tag);
|
||||
GetTag (TagTypes.Xiph, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the audio properties from the file represented by
|
||||
/// the current instance.
|
||||
/// </summary>
|
||||
/// <param name="start">
|
||||
/// A <see cref="long" /> value containing the seek position
|
||||
/// at which the tags end and the media data begins.
|
||||
/// </param>
|
||||
/// <param name="end">
|
||||
/// A <see cref="long" /> value containing the seek position
|
||||
/// at which the media data ends and the tags begin.
|
||||
/// </param>
|
||||
/// <param name="propertiesStyle">
|
||||
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||
/// of accuracy to read the media properties, or <see
|
||||
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="TagLib.Properties" /> object describing the
|
||||
/// media properties of the file represented by the current
|
||||
/// instance.
|
||||
/// </returns>
|
||||
protected override Properties ReadProperties (long start,
|
||||
long end,
|
||||
ReadStyle propertiesStyle)
|
||||
{
|
||||
StreamHeader header = new StreamHeader (header_block,
|
||||
end - stream_start);
|
||||
return new Properties (TimeSpan.Zero, header);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Private Methods
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether or not the block types passed into
|
||||
/// <see cref="ReadBlocks" /> are to be white-listed or
|
||||
/// black-listed.
|
||||
/// </summary>
|
||||
private enum BlockMode
|
||||
{
|
||||
/// <summary>
|
||||
/// All block types except those provided are to be
|
||||
/// returned.
|
||||
/// </summary>
|
||||
Blacklist,
|
||||
|
||||
/// <summary>
|
||||
/// Only those block types provides should be
|
||||
/// returned.
|
||||
/// </summary>
|
||||
Whitelist
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads all metadata blocks starting from the current
|
||||
/// instance, starting at a specified position.
|
||||
/// </summary>
|
||||
/// <param name="start">
|
||||
/// A <see cref="long" /> value reference specifying the
|
||||
/// position at which to start searching for the blocks. This
|
||||
/// will be updated to the position of the first block.
|
||||
/// </param>
|
||||
/// <param name="end">
|
||||
/// A <see cref="long" /> value reference updated to the
|
||||
/// position at which the last block ends.
|
||||
/// </param>
|
||||
/// <param name="mode">
|
||||
/// A <see cref="BlockMode" /> value indicating whether to
|
||||
/// white-list or black-list the contents of <paramref
|
||||
/// name="types" />.
|
||||
/// </param>
|
||||
/// <param name="types">
|
||||
/// A <see cref="BlockType[]" /> containing the types to look
|
||||
/// for or not look for as specified by <paramref name="mode"
|
||||
/// />.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="T:System.Collections.Generic.IList`1" /> object containing the blocks
|
||||
/// read from the current instance.
|
||||
/// </returns>
|
||||
/// <exception cref="CorruptFileException">
|
||||
/// "<c>fLaC</c>" could not be found.
|
||||
/// </exception>
|
||||
private IList<Block> ReadBlocks (ref long start, out long end,
|
||||
BlockMode mode,
|
||||
params BlockType[] types)
|
||||
{
|
||||
List<Block> blocks = new List<Block> ();
|
||||
|
||||
long start_position = Find ("fLaC", start);
|
||||
|
||||
if (start_position < 0)
|
||||
throw new CorruptFileException (
|
||||
"FLAC stream not found at starting position.");
|
||||
|
||||
end = start = start_position + 4;
|
||||
|
||||
Seek (start);
|
||||
|
||||
BlockHeader header;
|
||||
|
||||
do {
|
||||
header = new BlockHeader (ReadBlock ((int)
|
||||
BlockHeader.Size));
|
||||
|
||||
bool found = false;
|
||||
foreach (BlockType type in types)
|
||||
if (header.BlockType == type) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((mode == BlockMode.Whitelist && found) ||
|
||||
(mode == BlockMode.Blacklist && !found))
|
||||
blocks.Add (new Block (header,
|
||||
ReadBlock ((int)
|
||||
header.BlockSize)));
|
||||
else
|
||||
Seek (header.BlockSize,
|
||||
System.IO.SeekOrigin.Current);
|
||||
|
||||
end += header.BlockSize + BlockHeader.Size;
|
||||
} while (!header.IsLastBlock);
|
||||
|
||||
return blocks;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// This class extends <see cref="CombinedTag" /> to provide support
|
||||
/// for reading and writing FLAC metadata boxes.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// At this point, only Xiph Comments and pictures are supported.
|
||||
/// </remarks>
|
||||
public class Metadata : CombinedTag
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains the pictures.
|
||||
/// </summary>
|
||||
private List<IPicture> pictures = new List<IPicture>();
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="Metadata" /> using a collection of blocks.
|
||||
/// </summary>
|
||||
/// <param name="blocks">
|
||||
/// A <see cref="T:System.Collections.Generic.List`1" /> object containing <see
|
||||
/// cref="Block" /> objects to use in the new instance.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="blocks" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
[Obsolete("Use Metadata(IEnumerable<Block>)")]
|
||||
public Metadata (List<Block> blocks)
|
||||
: this (blocks as IEnumerable<Block>)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="Metadata" /> using a collection of blocks.
|
||||
/// </summary>
|
||||
/// <param name="blocks">
|
||||
/// A <see cref="T:System.Collections.Generic.IEnumerable`1" /> object enumerating <see
|
||||
/// cref="Block" /> objects to use in the new instance.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="blocks" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public Metadata (IEnumerable<Block> blocks)
|
||||
{
|
||||
if (blocks == null)
|
||||
throw new ArgumentNullException ("blocks");
|
||||
|
||||
foreach (Block block in blocks) {
|
||||
if (block.Data.Count == 0)
|
||||
continue;
|
||||
|
||||
if (block.Type == BlockType.XiphComment)
|
||||
AddTag (new Ogg.XiphComment (block.Data));
|
||||
else if (block.Type == BlockType.Picture)
|
||||
pictures.Add (new Picture (block.Data));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the first Xiph comment stored in the current
|
||||
/// instance, optionally creating one if necessary.
|
||||
/// </summary>
|
||||
/// <param name="create">
|
||||
/// A <see cref="bool" /> value indicating whether or not a
|
||||
/// comment should be added if one cannot be found.
|
||||
/// </param>
|
||||
/// <param name="copy">
|
||||
/// A <see cref="Tag" /> object containing the source tag to
|
||||
/// copy the values from, or <see langword="null" /> to not
|
||||
/// copy values.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="Ogg.XiphComment" /> object containing the
|
||||
/// tag that was found in or added to the current instance.
|
||||
/// If no matching tag was found and none was created, <see
|
||||
/// langword="null" /> is returned.
|
||||
/// </returns>
|
||||
public Ogg.XiphComment GetComment (bool create, Tag copy)
|
||||
{
|
||||
foreach (Tag t in Tags)
|
||||
if (t is Ogg.XiphComment)
|
||||
return t as Ogg.XiphComment;
|
||||
|
||||
if (!create)
|
||||
return null;
|
||||
|
||||
Ogg.XiphComment c = new Ogg.XiphComment ();
|
||||
|
||||
if (copy != null)
|
||||
copy.CopyTo (c, true);
|
||||
|
||||
AddTag (c);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes all child Xiph Comments from the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
public void RemoveComment ()
|
||||
{
|
||||
Ogg.XiphComment c;
|
||||
|
||||
while ((c = GetComment (false, null)) != null)
|
||||
RemoveTag (c);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the tag types contained in the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A bitwise combined <see cref="TagLib.TagTypes" /> value
|
||||
/// containing the tag types stored in the current instance.
|
||||
/// </value>
|
||||
public override TagTypes TagTypes {
|
||||
get {return TagTypes.FlacMetadata | base.TagTypes;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets a collection of pictures associated with
|
||||
/// the media represented by the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="IPicture[]" /> containing a collection of
|
||||
/// pictures associated with the media represented by the
|
||||
/// current instance or an empty array if none are present.
|
||||
/// </value>
|
||||
public override IPicture[] Pictures {
|
||||
get {return pictures.ToArray ();}
|
||||
set {
|
||||
pictures.Clear ();
|
||||
if (value != null)
|
||||
pictures.AddRange (value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears the values stored in the current instance.
|
||||
/// </summary>
|
||||
public override void Clear ()
|
||||
{
|
||||
pictures.Clear ();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,332 +0,0 @@
|
||||
//
|
||||
// Picture.cs:
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2007 Brian Nickel
|
||||
//
|
||||
// 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.Flac
|
||||
{
|
||||
/// <summary>
|
||||
/// This class implements <see cref="IPicture" /> to provide support
|
||||
/// for reading and writing Flac picture metadata.
|
||||
/// </summary>
|
||||
public class Picture : IPicture
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Contains the picture type.
|
||||
/// </summary>
|
||||
private PictureType type;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the mime-type.
|
||||
/// </summary>
|
||||
private string mime_type;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the description.
|
||||
/// </summary>
|
||||
private string description;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the width.
|
||||
/// </summary>
|
||||
private int width = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the height.
|
||||
/// </summary>
|
||||
private int height = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the color depth.
|
||||
/// </summary>
|
||||
private int color_depth = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the number of indexed colors.
|
||||
/// </summary>
|
||||
private int indexed_colors = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the picture data.
|
||||
/// </summary>
|
||||
private ByteVector picture_data;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="Picture" /> by reading the contents of a raw Flac
|
||||
/// image structure.
|
||||
/// </summary>
|
||||
/// <param name="data">
|
||||
/// A <see cref="ByteVector" /> object containing the raw
|
||||
/// Flac image.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="data" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
/// <exception cref="CorruptFileException">
|
||||
/// <paramref name="data" /> contains less than 32 bytes.
|
||||
/// </exception>
|
||||
public Picture (ByteVector data)
|
||||
{
|
||||
if (data == null)
|
||||
throw new ArgumentNullException ("data");
|
||||
|
||||
if (data.Count < 32)
|
||||
throw new CorruptFileException (
|
||||
"Data must be at least 32 bytes long");
|
||||
|
||||
int pos = 0;
|
||||
type = (PictureType) data.Mid (pos, 4).ToUInt ();
|
||||
pos += 4;
|
||||
|
||||
int mimetype_length = (int) data.Mid (pos, 4).ToUInt ();
|
||||
pos += 4;
|
||||
|
||||
mime_type = data.ToString (StringType.Latin1, pos,
|
||||
mimetype_length);
|
||||
pos += mimetype_length;
|
||||
|
||||
int description_length = (int) data.Mid (pos, 4)
|
||||
.ToUInt ();
|
||||
pos += 4;
|
||||
|
||||
description = data.ToString (StringType.UTF8, pos,
|
||||
description_length);
|
||||
pos += description_length;
|
||||
|
||||
width = (int) data.Mid (pos, 4).ToUInt ();
|
||||
pos += 4;
|
||||
|
||||
height = (int) data.Mid (pos, 4).ToUInt ();
|
||||
pos += 4;
|
||||
|
||||
color_depth = (int) data.Mid (pos, 4).ToUInt ();
|
||||
pos += 4;
|
||||
|
||||
indexed_colors = (int) data.Mid (pos, 4).ToUInt ();
|
||||
pos += 4;
|
||||
|
||||
int data_length = (int) data.Mid (pos, 4).ToUInt ();
|
||||
pos += 4;
|
||||
|
||||
picture_data = data.Mid (pos, data_length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="Picture" /> by copying the properties of a <see
|
||||
/// cref="IPicture" /> object.
|
||||
/// </summary>
|
||||
/// <param name="picture">
|
||||
/// A <see cref="IPicture" /> object to use for the new
|
||||
/// instance.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="picture" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public Picture (IPicture picture)
|
||||
{
|
||||
if (picture == null)
|
||||
throw new ArgumentNullException ("picture");
|
||||
|
||||
type = picture.Type;
|
||||
mime_type = picture.MimeType;
|
||||
description = picture.Description;
|
||||
picture_data = picture.Data;
|
||||
|
||||
TagLib.Flac.Picture flac_picture =
|
||||
picture as TagLib.Flac.Picture;
|
||||
|
||||
if (flac_picture == null)
|
||||
return;
|
||||
|
||||
width = flac_picture.Width;
|
||||
height = flac_picture.Height;
|
||||
color_depth = flac_picture.ColorDepth;
|
||||
indexed_colors = flac_picture.IndexedColors;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Renders the current instance as a raw Flac picture.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector" /> object containing the
|
||||
/// rendered version of the current instance.
|
||||
/// </returns>
|
||||
public ByteVector Render ()
|
||||
{
|
||||
ByteVector data = new ByteVector ();
|
||||
|
||||
data.Add (ByteVector.FromUInt ((uint) Type));
|
||||
|
||||
ByteVector mime_data = ByteVector.FromString (MimeType,
|
||||
StringType.Latin1);
|
||||
data.Add (ByteVector.FromUInt ((uint) mime_data.Count));
|
||||
data.Add (mime_data);
|
||||
|
||||
ByteVector decription_data = ByteVector.FromString (
|
||||
Description, StringType.UTF8);
|
||||
data.Add (ByteVector.FromUInt ((uint)
|
||||
decription_data.Count));
|
||||
data.Add (decription_data);
|
||||
|
||||
data.Add (ByteVector.FromUInt ((uint) Width));
|
||||
data.Add (ByteVector.FromUInt ((uint) Height));
|
||||
data.Add (ByteVector.FromUInt ((uint) ColorDepth));
|
||||
data.Add (ByteVector.FromUInt ((uint) IndexedColors));
|
||||
|
||||
data.Add (ByteVector.FromUInt ((uint) Data.Count));
|
||||
data.Add (Data);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the mime-type of the picture data
|
||||
/// stored in the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="string" /> object containing the mime-type
|
||||
/// of the picture data stored in the current instance.
|
||||
/// </value>
|
||||
public string MimeType {
|
||||
get {return mime_type;}
|
||||
set {mime_type = value;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the type of content visible in the picture
|
||||
/// stored in the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="PictureType" /> containing the type of
|
||||
/// content visible in the picture stored in the current
|
||||
/// instance.
|
||||
/// </value>
|
||||
public PictureType Type {
|
||||
get {return type;}
|
||||
set {type = value;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets a description of the picture stored in the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="string" /> object containing a description
|
||||
/// of the picture stored in the current instance.
|
||||
/// </value>
|
||||
public string Description {
|
||||
get {return description;}
|
||||
set {description = value;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the picture data stored in the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="ByteVector" /> object containing the picture
|
||||
/// data stored in the current instance.
|
||||
/// </value>
|
||||
public ByteVector Data {
|
||||
get {return picture_data;}
|
||||
set {picture_data = value;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the width of the picture in the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing width of the
|
||||
/// picture stored in the current instance.
|
||||
/// </value>
|
||||
public int Width {
|
||||
get {return width;}
|
||||
set {width = value;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the height of the picture in the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing height of the
|
||||
/// picture stored in the current instance.
|
||||
/// </value>
|
||||
public int Height {
|
||||
get {return height;}
|
||||
set {height = value;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the color depth of the picture in the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing color depth of the
|
||||
/// picture stored in the current instance.
|
||||
/// </value>
|
||||
public int ColorDepth {
|
||||
get {return color_depth;}
|
||||
set {color_depth = value;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the number of indexed colors in the picture
|
||||
/// in the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing number of indexed
|
||||
/// colors in the picture, or zero if the picture is not
|
||||
/// stored in an indexed format.
|
||||
/// </value>
|
||||
public int IndexedColors {
|
||||
get {return indexed_colors;}
|
||||
set {indexed_colors = value;}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,253 +0,0 @@
|
||||
//
|
||||
// StreamHeader.cs:
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Original Source:
|
||||
// flagproperties.cpp from TagLib
|
||||
//
|
||||
// Copyright (C) 2006-2007 Brian Nickel
|
||||
// Copyright (C) 2003 Allan Sandfeld Jensen (Original Implementation)
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License version
|
||||
// 2.1 as published by the Free Software Foundation.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
// USA
|
||||
//
|
||||
|
||||
using System.Collections;
|
||||
using System;
|
||||
|
||||
namespace TagLib.Flac
|
||||
{
|
||||
/// <summary>
|
||||
/// This structure implements <see cref="IAudioCodec" /> and provides
|
||||
/// information about a Flac audio stream.
|
||||
/// </summary>
|
||||
public struct StreamHeader : IAudioCodec, ILosslessAudioCodec
|
||||
{
|
||||
#region Private Properties
|
||||
|
||||
/// <summary>
|
||||
/// Contains the flags.
|
||||
/// </summary>
|
||||
private uint flags;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the low portion of the length.
|
||||
/// </summary>
|
||||
private uint low_length;
|
||||
|
||||
/// <summary>
|
||||
/// Contains the stream length.
|
||||
/// </summary>
|
||||
private long stream_length;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="StreamHeader" /> by reading a raw stream header
|
||||
/// structure and using the stream length.
|
||||
/// </summary>
|
||||
/// <param name="data">
|
||||
/// A <see cref="ByteVector" /> object containing the raw
|
||||
/// stream header.
|
||||
/// </param>
|
||||
/// <param name="streamLength">
|
||||
/// A <see cref="long" /> value containing the length of the
|
||||
/// stream.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="data" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
/// <exception cref="CorruptFileException">
|
||||
/// <paramref name="data" /> contains less than 18 bytes.
|
||||
/// </exception>
|
||||
public StreamHeader (ByteVector data, long streamLength)
|
||||
{
|
||||
if (data == null)
|
||||
throw new ArgumentNullException ("data");
|
||||
|
||||
if (data.Count < 18)
|
||||
throw new CorruptFileException (
|
||||
"Not enough data in FLAC header.");
|
||||
|
||||
this.stream_length = streamLength;
|
||||
this.flags = data.Mid (10, 4).ToUInt (true);
|
||||
low_length = data.Mid (14, 4).ToUInt (true);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the duration of the media represented by the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="TimeSpan" /> containing the duration of the
|
||||
/// media represented by the current instance.
|
||||
/// </value>
|
||||
public TimeSpan Duration {
|
||||
get {
|
||||
return (AudioSampleRate > 0 && stream_length > 0)
|
||||
? TimeSpan.FromSeconds (
|
||||
(double) low_length /
|
||||
(double) AudioSampleRate +
|
||||
(double) HighLength) :
|
||||
TimeSpan.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the bitrate of the audio represented by the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing a bitrate of the
|
||||
/// audio represented by the current instance.
|
||||
/// </value>
|
||||
public int AudioBitrate {
|
||||
get {
|
||||
return (int) (Duration > TimeSpan.Zero ?
|
||||
((stream_length * 8L) /
|
||||
Duration.TotalSeconds) / 1000 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the sample count of the audio represented by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing the sample count
|
||||
/// of the audio represented by the current instance.
|
||||
/// </value>
|
||||
public long AudioSampleCount
|
||||
{
|
||||
get
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the sample rate of the audio represented by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing the sample rate of
|
||||
/// the audio represented by the current instance.
|
||||
/// </value>
|
||||
public int AudioSampleRate {
|
||||
get {return (int) (flags >> 12);}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of channels in the audio represented by
|
||||
/// the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing the number of
|
||||
/// channels in the audio represented by the current
|
||||
/// instance.
|
||||
/// </value>
|
||||
public int AudioChannels {
|
||||
get {return (int) (((flags >> 9) & 7) + 1);}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the types of media represented by the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Always <see cref="MediaTypes.Audio" />.
|
||||
/// </value>
|
||||
public MediaTypes MediaTypes {
|
||||
get {return MediaTypes.Audio;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the sample width of the audio represented by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing the sample width of
|
||||
/// the audio represented by the current instance.
|
||||
/// </value>
|
||||
[Obsolete ("This property is depreciated, use BitsPerSample instead")]
|
||||
public int AudioSampleWidth {
|
||||
get {return BitsPerSample;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of bits per sample in the audio
|
||||
/// represented by the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing the number of bits
|
||||
/// per sample in the audio represented by the current
|
||||
/// instance.
|
||||
/// </value>
|
||||
public int BitsPerSample {
|
||||
get {return (int) (((flags >> 4) & 31) + 1);}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a text description of the media represented by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="string" /> object containing a description
|
||||
/// of the media represented by the current instance.
|
||||
/// </value>
|
||||
public string Description {
|
||||
get {return "Flac Audio";}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Private Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets a high portion of the length of the audio
|
||||
/// represented by the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="uint" /> value containing the high portion
|
||||
/// of the length.
|
||||
/// </value>
|
||||
private uint HighLength {
|
||||
get {
|
||||
// The last 4 bits are the most significant 4
|
||||
// bits for the 36 bit stream length in samples.
|
||||
// (Audio files measured in days)
|
||||
return (uint) (AudioSampleRate > 0 ?
|
||||
(((flags & 0xf) << 28) /
|
||||
AudioSampleRate) << 4 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,406 +0,0 @@
|
||||
//
|
||||
// Genres.cs: Provides convenience functions for converting between String
|
||||
// genres and their respective audio and video indices as used by several
|
||||
// formats.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Original Source:
|
||||
// id3v1genres.cpp from TagLib
|
||||
//
|
||||
// Copyright (C) 2005-2007 Brian Nickel
|
||||
// Copyright (C) 2002 Scott Wheeler (Original Implementation)
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License version
|
||||
// 2.1 as published by the Free Software Foundation.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
// USA
|
||||
//
|
||||
|
||||
using System.Collections;
|
||||
using System;
|
||||
|
||||
namespace TagLib {
|
||||
/// <summary>
|
||||
/// This static class provides convenience functions for converting
|
||||
/// between <see cref="string" /> genres and their respective audio
|
||||
/// and video indices as used by several formats.
|
||||
/// </summary>
|
||||
public static class Genres
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains a list of ID3v1 audio generes.
|
||||
/// </summary>
|
||||
private static readonly string [] audio = {
|
||||
"Blues",
|
||||
"Classic Rock",
|
||||
"Country",
|
||||
"Dance",
|
||||
"Disco",
|
||||
"Funk",
|
||||
"Grunge",
|
||||
"Hip-Hop",
|
||||
"Jazz",
|
||||
"Metal",
|
||||
"New Age",
|
||||
"Oldies",
|
||||
"Other",
|
||||
"Pop",
|
||||
"R&B",
|
||||
"Rap",
|
||||
"Reggae",
|
||||
"Rock",
|
||||
"Techno",
|
||||
"Industrial",
|
||||
"Alternative",
|
||||
"Ska",
|
||||
"Death Metal",
|
||||
"Pranks",
|
||||
"Soundtrack",
|
||||
"Euro-Techno",
|
||||
"Ambient",
|
||||
"Trip-Hop",
|
||||
"Vocal",
|
||||
"Jazz+Funk",
|
||||
"Fusion",
|
||||
"Trance",
|
||||
"Classical",
|
||||
"Instrumental",
|
||||
"Acid",
|
||||
"House",
|
||||
"Game",
|
||||
"Sound Clip",
|
||||
"Gospel",
|
||||
"Noise",
|
||||
"Alternative Rock",
|
||||
"Bass",
|
||||
"Soul",
|
||||
"Punk",
|
||||
"Space",
|
||||
"Meditative",
|
||||
"Instrumental Pop",
|
||||
"Instrumental Rock",
|
||||
"Ethnic",
|
||||
"Gothic",
|
||||
"Darkwave",
|
||||
"Techno-Industrial",
|
||||
"Electronic",
|
||||
"Pop-Folk",
|
||||
"Eurodance",
|
||||
"Dream",
|
||||
"Southern Rock",
|
||||
"Comedy",
|
||||
"Cult",
|
||||
"Gangsta",
|
||||
"Top 40",
|
||||
"Christian Rap",
|
||||
"Pop/Funk",
|
||||
"Jungle",
|
||||
"Native American",
|
||||
"Cabaret",
|
||||
"New Wave",
|
||||
"Psychedelic",
|
||||
"Rave",
|
||||
"Showtunes",
|
||||
"Trailer",
|
||||
"Lo-Fi",
|
||||
"Tribal",
|
||||
"Acid Punk",
|
||||
"Acid Jazz",
|
||||
"Polka",
|
||||
"Retro",
|
||||
"Musical",
|
||||
"Rock & Roll",
|
||||
"Hard Rock",
|
||||
"Folk",
|
||||
"Folk/Rock",
|
||||
"National Folk",
|
||||
"Swing",
|
||||
"Fusion",
|
||||
"Bebob",
|
||||
"Latin",
|
||||
"Revival",
|
||||
"Celtic",
|
||||
"Bluegrass",
|
||||
"Avantgarde",
|
||||
"Gothic Rock",
|
||||
"Progressive Rock",
|
||||
"Psychedelic Rock",
|
||||
"Symphonic Rock",
|
||||
"Slow Rock",
|
||||
"Big Band",
|
||||
"Chorus",
|
||||
"Easy Listening",
|
||||
"Acoustic",
|
||||
"Humour",
|
||||
"Speech",
|
||||
"Chanson",
|
||||
"Opera",
|
||||
"Chamber Music",
|
||||
"Sonata",
|
||||
"Symphony",
|
||||
"Booty Bass",
|
||||
"Primus",
|
||||
"Porn Groove",
|
||||
"Satire",
|
||||
"Slow Jam",
|
||||
"Club",
|
||||
"Tango",
|
||||
"Samba",
|
||||
"Folklore",
|
||||
"Ballad",
|
||||
"Power Ballad",
|
||||
"Rhythmic Soul",
|
||||
"Freestyle",
|
||||
"Duet",
|
||||
"Punk Rock",
|
||||
"Drum Solo",
|
||||
"A Cappella",
|
||||
"Euro-House",
|
||||
"Dance Hall",
|
||||
"Goa",
|
||||
"Drum & Bass",
|
||||
"Club-House",
|
||||
"Hardcore",
|
||||
"Terror",
|
||||
"Indie",
|
||||
"BritPop",
|
||||
"Negerpunk",
|
||||
"Polsk Punk",
|
||||
"Beat",
|
||||
"Christian Gangsta Rap",
|
||||
"Heavy Metal",
|
||||
"Black Metal",
|
||||
"Crossover",
|
||||
"Contemporary Christian",
|
||||
"Christian Rock",
|
||||
"Merengue",
|
||||
"Salsa",
|
||||
"Thrash Metal",
|
||||
"Anime",
|
||||
"Jpop",
|
||||
"Synthpop"
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Contains a list of DivX audio generes.
|
||||
/// </summary>
|
||||
private static readonly string [] video = new string [] {
|
||||
"Action",
|
||||
"Action/Adventure",
|
||||
"Adult",
|
||||
"Adventure",
|
||||
"Catastrophe",
|
||||
"Child's",
|
||||
"Claymation",
|
||||
"Comedy",
|
||||
"Concert",
|
||||
"Documentary",
|
||||
"Drama",
|
||||
"Eastern",
|
||||
"Entertaining",
|
||||
"Erotic",
|
||||
"Extremal Sport",
|
||||
"Fantasy",
|
||||
"Fashion",
|
||||
"Historical",
|
||||
"Horror",
|
||||
"Horror/Mystic",
|
||||
"Humor",
|
||||
"Indian",
|
||||
"Informercial",
|
||||
"Melodrama",
|
||||
"Military & War",
|
||||
"Music Video",
|
||||
"Musical",
|
||||
"Mystery",
|
||||
"Nature",
|
||||
"Political Satire",
|
||||
"Popular Science",
|
||||
"Psychological Thriller",
|
||||
"Religion",
|
||||
"Science Fiction",
|
||||
"Scifi Action",
|
||||
"Slapstick",
|
||||
"Splatter",
|
||||
"Sports",
|
||||
"Thriller",
|
||||
"Western"
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of standard audio generes.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="string[]" /> containing standard audio
|
||||
/// genres.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// The genres are stored in the same order and with the same
|
||||
/// values as in the ID3v1 format.
|
||||
/// </remarks>
|
||||
public static string [] Audio {
|
||||
get {return (string []) audio.Clone ();}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of standard video generes.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="string[]" /> containing standard video
|
||||
/// genres.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// The genres are stored in the same order and with the same
|
||||
/// values as in the DivX format.
|
||||
/// </remarks>
|
||||
public static string [] Video {
|
||||
get {return (string []) video.Clone ();}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the genre index for a specified audio genre.
|
||||
/// </summary>
|
||||
/// <param name="name">
|
||||
/// A <see cref="string" /> object containing the name of the
|
||||
/// genre to look up.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="byte" /> value containing the index of the
|
||||
/// genre in the audio array or 255 if it could not be found.
|
||||
/// </returns>
|
||||
public static byte AudioToIndex (string name)
|
||||
{
|
||||
for (byte i = 0; i < audio.Length; i ++)
|
||||
if (name == audio [i])
|
||||
return i;
|
||||
return 255;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the genre index for a specified video genre.
|
||||
/// </summary>
|
||||
/// <param name="name">
|
||||
/// A <see cref="string" /> object containing the name of the
|
||||
/// genre to look up.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="byte" /> value containing the index of the
|
||||
/// genre in the video array or 255 if it could not be found.
|
||||
/// </returns>
|
||||
public static byte VideoToIndex (string name)
|
||||
{
|
||||
for (byte i = 0; i < video.Length; i ++)
|
||||
if (name == video [i])
|
||||
return i;
|
||||
return 255;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the audio genre from its index in the array.
|
||||
/// </summary>
|
||||
/// <param name="index">
|
||||
/// A <see cref="byte" /> value containing the index to
|
||||
/// aquire the genre from.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="string" /> object containing the audio genre
|
||||
/// found at the index, or <see langword="null" /> if it does
|
||||
/// not exist.
|
||||
/// </returns>
|
||||
public static string IndexToAudio (byte index)
|
||||
{
|
||||
return (index < audio.Length) ? audio [index] : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the video genre from its index in the array.
|
||||
/// </summary>
|
||||
/// <param name="index">
|
||||
/// A <see cref="byte" /> value containing the index to
|
||||
/// aquire the genre from.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="string" /> object containing the video genre
|
||||
/// found at the index, or <see langword="null" /> if it does
|
||||
/// not exist.
|
||||
/// </returns>
|
||||
public static string IndexToVideo (byte index)
|
||||
{
|
||||
return (index < video.Length) ? video [index] : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the audio genre from its index in the array.
|
||||
/// </summary>
|
||||
/// <param name="text">
|
||||
/// A <see cref="string" /> object, either in the format
|
||||
/// <c>"(123)"</c> or <c>"123"</c>.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="string" /> object containing the audio genre
|
||||
/// found at the index, or <see langword="null" /> if it does
|
||||
/// not exist.
|
||||
/// </returns>
|
||||
public static string IndexToAudio (string text)
|
||||
{
|
||||
return IndexToAudio (StringToByte (text));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the video genre from its index in the array.
|
||||
/// </summary>
|
||||
/// <param name="text">
|
||||
/// A <see cref="string" /> object, either in the format
|
||||
/// <c>"(123)"</c> or <c>"123"</c>.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="string" /> object containing the video genre
|
||||
/// found at the index, or <see langword="null" /> if it does
|
||||
/// not exist.
|
||||
/// </returns>
|
||||
public static string IndexToVideo (string text)
|
||||
{
|
||||
return IndexToVideo (StringToByte (text));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a string, either in the format <c>"(123)"</c> or
|
||||
/// <c>"123"</c> into a byte or equal numeric value.
|
||||
/// </summary>
|
||||
/// <param name="text">
|
||||
/// A <see cref="string" /> object, either in the format
|
||||
/// <c>"(123)"</c> or <c>"123"</c>, to be converted.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="byte" /> value containing the numeric value
|
||||
/// of <paramref name="text" /> or 255 if no numeric value
|
||||
/// could be extracted.
|
||||
/// </returns>
|
||||
private static byte StringToByte (string text)
|
||||
{
|
||||
byte value;
|
||||
int last_pos;
|
||||
if (text != null && text.Length > 2 && text [0] == '('
|
||||
&& (last_pos = text.IndexOf (')')) != -1
|
||||
&& byte.TryParse (text.Substring (1,
|
||||
last_pos - 1), out value))
|
||||
return value;
|
||||
|
||||
if (text != null && byte.TryParse (text, out value))
|
||||
return value;
|
||||
|
||||
return 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
//
|
||||
// Codec.cs:
|
||||
//
|
||||
// Author:
|
||||
// Mike Gemuende (mike@gemuende.be)
|
||||
//
|
||||
// Copyright (C) 2010 Mike Gemuende
|
||||
//
|
||||
// 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.Gif
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// A Gif photo codec. Contains basic photo details.
|
||||
/// </summary>
|
||||
public class Codec : Image.Codec
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Gets a text description of the media represented by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="string" /> object containing a description
|
||||
/// of the media represented by the current instance.
|
||||
/// </value>
|
||||
public override string Description { get { return "GIF File"; } }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new <see cref="Codec" /> with the given width
|
||||
/// and height.
|
||||
/// </summary>
|
||||
/// <param name="width">
|
||||
/// The width of the photo.
|
||||
/// </param>
|
||||
/// <param name="height">
|
||||
/// The height of the photo.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A new <see cref="Codec" /> instance.
|
||||
/// </returns>
|
||||
public Codec (int width, int height)
|
||||
: base (width, height) {}
|
||||
}
|
||||
}
|
||||
@@ -1,781 +0,0 @@
|
||||
//
|
||||
// File.cs: Provides tagging for GIF files
|
||||
//
|
||||
// Author:
|
||||
// Mike Gemuende (mike@gemuende.be)
|
||||
//
|
||||
// Copyright (C) 2010 Mike Gemuende
|
||||
//
|
||||
// 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;
|
||||
|
||||
using TagLib;
|
||||
using TagLib.Image;
|
||||
using TagLib.Xmp;
|
||||
|
||||
|
||||
namespace TagLib.Gif
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// This class extends <see cref="TagLib.Image.ImageBlockFile" /> to provide tagging
|
||||
/// and property support for Gif files.
|
||||
/// </summary>
|
||||
[SupportedMimeType("taglib/gif", "gif")]
|
||||
[SupportedMimeType("image/gif")]
|
||||
public class File : TagLib.Image.ImageBlockFile
|
||||
{
|
||||
|
||||
#region GIF specific constants
|
||||
|
||||
/// <summary>
|
||||
/// Gif file signature which occurs at the begin of the file
|
||||
/// </summary>
|
||||
protected static readonly string SIGNATURE = "GIF";
|
||||
|
||||
/// <summary>
|
||||
/// String which is used to indicate version the gif file format version 87a
|
||||
/// </summary>
|
||||
protected static readonly string VERSION_87A = "87a";
|
||||
|
||||
/// <summary>
|
||||
/// String which is used to indicate version the gif file format version 89a
|
||||
/// </summary>
|
||||
protected static readonly string VERSION_89A = "89a";
|
||||
|
||||
/// <summary>
|
||||
/// Application Extension Identifier for an XMP Block
|
||||
/// </summary>
|
||||
private static readonly string XMP_IDENTIFIER = "XMP Data";
|
||||
|
||||
/// <summary>
|
||||
/// Application Authentication Extension Code for an XMP Block
|
||||
/// </summary>
|
||||
private static readonly string XMP_AUTH_CODE = "XMP";
|
||||
|
||||
/// <summary>
|
||||
/// The Magic Trailer for XMP Data
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The storage of XMP data in GIF does not follow the GIF specification. According to the
|
||||
/// specification, extension data is stored in so-called sub-blocks, which start with a length
|
||||
/// byte which specifies the number of data bytes contained in the sub block. So a block can at
|
||||
/// most contain 256 data bytes. After a sub-block, the next sub-block begins. The sequence ends,
|
||||
/// when a sub-block starts with 0. So readers, which are not aware of the XMP data not following
|
||||
/// this scheme, will get confused by the XMP data. To fix this, this trailer is added to the end.
|
||||
/// It has a length of 258 bytes, so that it is ensured that a reader which tries to skip the
|
||||
/// XMP data reads one of this bytes as length of a sub-block. But, each byte points with its length
|
||||
/// to the last one. Therefoe, independent of the byte, the reader reads as sub-block length, it is
|
||||
/// redirected to the last byte of the trailer and therfore to the end of the XMP data.
|
||||
/// </remarks>
|
||||
private static readonly byte [] XMP_MAGIC_TRAILER = new byte [] {
|
||||
0x01, 0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1,
|
||||
0xF0, 0xEF, 0xEE, 0xED, 0xEC, 0xEB, 0xEA, 0xE9, 0xE8, 0xE7, 0xE6, 0xE5, 0xE4, 0xE3, 0xE2, 0xE1,
|
||||
0xE0, 0xDF, 0xDE, 0xDD, 0xDC, 0xDB, 0xDA, 0xD9, 0xD8, 0xD7, 0xD6, 0xD5, 0xD4, 0xD3, 0xD2, 0xD1,
|
||||
0xD0, 0xCF, 0xCE, 0xCD, 0xCC, 0xCB, 0xCA, 0xC9, 0xC8, 0xC7, 0xC6, 0xC5, 0xC4, 0xC3, 0xC2, 0xC1,
|
||||
0xC0, 0xBF, 0xBE, 0xBD, 0xBC, 0xBB, 0xBA, 0xB9, 0xB8, 0xB7, 0xB6, 0xB5, 0xB4, 0xB3, 0xB2, 0xB1,
|
||||
0xB0, 0xAF, 0xAE, 0xAD, 0xAC, 0xAB, 0xAA, 0xA9, 0xA8, 0xA7, 0xA6, 0xA5, 0xA4, 0xA3, 0xA2, 0xA1,
|
||||
0xA0, 0x9F, 0x9E, 0x9D, 0x9C, 0x9B, 0x9A, 0x99, 0x98, 0x97, 0x96, 0x95, 0x94, 0x93, 0x92, 0x91,
|
||||
0x90, 0x8F, 0x8E, 0x8D, 0x8C, 0x8B, 0x8A, 0x89, 0x88, 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81,
|
||||
0x80, 0x7F, 0x7E, 0x7D, 0x7C, 0x7B, 0x7A, 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x71,
|
||||
0x70, 0x6F, 0x6E, 0x6D, 0x6C, 0x6B, 0x6A, 0x69, 0x68, 0x67, 0x66, 0x65, 0x64, 0x63, 0x62, 0x61,
|
||||
0x60, 0x5F, 0x5E, 0x5D, 0x5C, 0x5B, 0x5A, 0x59, 0x58, 0x57, 0x56, 0x55, 0x54, 0x53, 0x52, 0x51,
|
||||
0x50, 0x4F, 0x4E, 0x4D, 0x4C, 0x4B, 0x4A, 0x49, 0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41,
|
||||
0x40, 0x3F, 0x3E, 0x3D, 0x3C, 0x3B, 0x3A, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31,
|
||||
0x30, 0x2F, 0x2E, 0x2D, 0x2C, 0x2B, 0x2A, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21,
|
||||
0x20, 0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11,
|
||||
0x10, 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01,
|
||||
0x00, 0x00
|
||||
};
|
||||
|
||||
#endregion
|
||||
|
||||
#region private fields
|
||||
|
||||
/// <summary>
|
||||
/// The width of the image
|
||||
/// </summary>
|
||||
private int width;
|
||||
|
||||
/// <summary>
|
||||
/// The height of the image
|
||||
/// </summary>
|
||||
private int height;
|
||||
|
||||
/// <summary>
|
||||
/// The Properties of the image
|
||||
/// </summary>
|
||||
private Properties properties;
|
||||
|
||||
/// <summary>
|
||||
/// The version of the file format
|
||||
/// </summary>
|
||||
private string version;
|
||||
|
||||
/// <summary>
|
||||
/// The start of the first block in file after the header.
|
||||
/// </summary>
|
||||
private long start_of_blocks = -1;
|
||||
|
||||
#endregion
|
||||
|
||||
#region public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the media properties of the file represented by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="TagLib.Properties" /> object containing the
|
||||
/// media properties of the file represented by the current
|
||||
/// instance.
|
||||
/// </value>
|
||||
public override TagLib.Properties Properties {
|
||||
get { return properties; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="File" /> for a specified path in the local file
|
||||
/// system and specified read style.
|
||||
/// </summary>
|
||||
/// <param name="path">
|
||||
/// A <see cref="string" /> object containing the path of the
|
||||
/// file to use in the new instance.
|
||||
/// </param>
|
||||
/// <param name="propertiesStyle">
|
||||
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||
/// of accuracy to read the media properties, or <see
|
||||
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="path" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public File (string path, ReadStyle propertiesStyle)
|
||||
: this (new File.LocalFileAbstraction (path),
|
||||
propertiesStyle)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="File" /> for a specified path in the local file
|
||||
/// system.
|
||||
/// </summary>
|
||||
/// <param name="path">
|
||||
/// A <see cref="string" /> object containing the path of the
|
||||
/// file to use in the new instance.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="path" /> is <see langword="null" />.
|
||||
/// </exception>
|
||||
public File (string path) : this (path, ReadStyle.Average)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="File" /> for a specified file abstraction and
|
||||
/// specified read style.
|
||||
/// </summary>
|
||||
/// <param name="abstraction">
|
||||
/// A <see cref="IFileAbstraction" /> object to use when
|
||||
/// reading from and writing to the file.
|
||||
/// </param>
|
||||
/// <param name="propertiesStyle">
|
||||
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||
/// of accuracy to read the media properties, or <see
|
||||
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="abstraction" /> is <see langword="null"
|
||||
/// />.
|
||||
/// </exception>
|
||||
public File (File.IFileAbstraction abstraction,
|
||||
ReadStyle propertiesStyle) : base (abstraction)
|
||||
{
|
||||
Read (propertiesStyle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a new instance of <see
|
||||
/// cref="File" /> for a specified file abstraction.
|
||||
/// </summary>
|
||||
/// <param name="abstraction">
|
||||
/// A <see cref="IFileAbstraction" /> object to use when
|
||||
/// reading from and writing to the file.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="abstraction" /> is <see langword="null"
|
||||
/// />.
|
||||
/// </exception>
|
||||
protected File (IFileAbstraction abstraction)
|
||||
: this (abstraction, ReadStyle.Average)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Saves the changes made in the current instance to the
|
||||
/// file it represents.
|
||||
/// </summary>
|
||||
public override void Save ()
|
||||
{
|
||||
Mode = AccessMode.Write;
|
||||
try {
|
||||
SaveMetadata ();
|
||||
|
||||
TagTypesOnDisk = TagTypes;
|
||||
} finally {
|
||||
Mode = AccessMode.Closed;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Private Methods
|
||||
|
||||
/// <summary>
|
||||
/// Reads the information from file with a specified read style.
|
||||
/// </summary>
|
||||
/// <param name="propertiesStyle">
|
||||
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||
/// of accuracy to read the media properties, or <see
|
||||
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||
/// </param>
|
||||
private void Read (ReadStyle propertiesStyle)
|
||||
{
|
||||
Mode = AccessMode.Read;
|
||||
try {
|
||||
ImageTag = new CombinedImageTag (TagTypes.XMP | TagTypes.GifComment);
|
||||
|
||||
ReadHeader ();
|
||||
ReadMetadata ();
|
||||
|
||||
TagTypesOnDisk = TagTypes;
|
||||
|
||||
if (propertiesStyle != ReadStyle.None)
|
||||
properties = ExtractProperties ();
|
||||
|
||||
} finally {
|
||||
Mode = AccessMode.Closed;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Reads a single byte form file. This is needed often for Gif files.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="System.Byte"/> with the read data.
|
||||
/// </returns>
|
||||
private byte ReadByte ()
|
||||
{
|
||||
ByteVector data = ReadBlock (1);
|
||||
|
||||
if (data.Count != 1)
|
||||
throw new CorruptFileException ("Unexpected end of file");
|
||||
|
||||
return data[0];
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Reads the Header and the Logical Screen Descriptor of the GIF file and,
|
||||
/// if there is one, skips the global color table. It also extracts the
|
||||
/// image width and height from it.
|
||||
/// </summary>
|
||||
private void ReadHeader ()
|
||||
{
|
||||
// The header consists of:
|
||||
//
|
||||
// 3 Bytes Signature
|
||||
// 3 Bytes Version
|
||||
//
|
||||
// The Logical Screen Descriptor of:
|
||||
//
|
||||
// 2 Bytes Width (little endian)
|
||||
// 2 Bytes Height (little endian)
|
||||
// 1 Byte Screen and Color Map (packed field)
|
||||
// 1 Byte Background Color
|
||||
// 1 Byte Aspect Ratio
|
||||
//
|
||||
// Whereas the bits of the packed field contains some special information.
|
||||
ByteVector data = ReadBlock (13);
|
||||
|
||||
if (data.Count != 13)
|
||||
throw new CorruptFileException ("Unexpected end of Header");
|
||||
|
||||
if (data.Mid (0, 3).ToString () != SIGNATURE)
|
||||
throw new CorruptFileException (String.Format ("Expected a GIF signature at start of file, but found: {0}", data.Mid (0, 3).ToString ()));
|
||||
|
||||
// We do not care about the version here, because we can read both versions in the same way.
|
||||
// We just care when writing metadata, that, if necessary, the version is increased to 89a.
|
||||
var read_version = data.Mid (3, 3).ToString ();
|
||||
if (read_version == VERSION_87A || read_version == VERSION_89A)
|
||||
version = read_version;
|
||||
else
|
||||
throw new UnsupportedFormatException (
|
||||
String.Format ("Only GIF versions 87a and 89a are currently supported, but not: {0}", read_version));
|
||||
|
||||
// Read Image Size (little endian)
|
||||
width = data.Mid (6, 2).ToUShort (false);
|
||||
height = data.Mid (8, 2).ToUShort (false);
|
||||
|
||||
// Skip optional global color table
|
||||
SkipColorTable (data [10]);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Reads the metadata from file. The current position must point to the
|
||||
/// start of the first block after the Header and Logical Screen
|
||||
/// Descriptor (and, if there is one, the Global Color Table)
|
||||
/// </summary>
|
||||
private void ReadMetadata ()
|
||||
{
|
||||
start_of_blocks = Tell;
|
||||
|
||||
// Read Blocks until end of file is reached.
|
||||
while (true) {
|
||||
byte identifier = ReadByte ();
|
||||
|
||||
switch (identifier) {
|
||||
case 0x2c:
|
||||
SkipImage ();
|
||||
break;
|
||||
|
||||
case 0x21:
|
||||
ReadExtensionBlock ();
|
||||
break;
|
||||
|
||||
case 0x3B:
|
||||
return;
|
||||
|
||||
default:
|
||||
throw new CorruptFileException (
|
||||
String.Format ("Do not know what to do with byte 0x{0:X2} at the beginning of a block ({1}).", identifier, Tell - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads an Extension Block at the current position. The current position must
|
||||
/// point to the 2nd byte of the comment block. (The other byte is usually
|
||||
/// read before to identify the comment block)
|
||||
/// </summary>
|
||||
private void ReadExtensionBlock ()
|
||||
{
|
||||
// Extension Block
|
||||
//
|
||||
// 1 Byte Extension Introducer (0x21)
|
||||
// 1 Byte Extension Identifier
|
||||
// ....
|
||||
//
|
||||
// Note, the Extension Introducer was read before to
|
||||
// identify the Extension Block. Therefore, it has not
|
||||
// to be handled here.
|
||||
byte identifier = ReadByte ();
|
||||
|
||||
switch (identifier) {
|
||||
case 0xFE:
|
||||
ReadCommentBlock ();
|
||||
break;
|
||||
|
||||
case 0xFF:
|
||||
ReadApplicationExtensionBlock ();
|
||||
break;
|
||||
|
||||
// Control Extension Block, ...
|
||||
case 0xF9:
|
||||
// ... Plain Text Extension ...
|
||||
case 0x01:
|
||||
// ... and all other unknown blocks can be skipped by just
|
||||
// reading sub-blocks.
|
||||
default:
|
||||
SkipSubBlocks ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Reads an Application Extension Block at the current position. The current
|
||||
/// position must point to the 3rd byte of the comment block. (The other 2 bytes
|
||||
/// are usually read before to identify the comment block)
|
||||
/// </summary>
|
||||
private void ReadApplicationExtensionBlock ()
|
||||
{
|
||||
// Application Extension Block
|
||||
//
|
||||
// 1 Byte Extension Introducer (0x21)
|
||||
// 1 Byte Application Extension Label (0xFF)
|
||||
// 1 Byte Block Size (0x0B - 11)
|
||||
// 8 Bytes Application Identifier
|
||||
// 3 Bytes Application Auth. Code
|
||||
// N Bytes Application Data (sub blocks)
|
||||
// 1 Byte Block Terminator (0x00)
|
||||
//
|
||||
// Note, the first 2 bytes are still read to identify the Comment Block.
|
||||
// Therefore, we only need to read the sub blocks and extract the data.
|
||||
long position = Tell;
|
||||
ByteVector data = ReadBlock (12);
|
||||
|
||||
if (data.Count != 12)
|
||||
throw new CorruptFileException ("");
|
||||
|
||||
// Contains XMP data
|
||||
if (data.Mid (1, 8) == XMP_IDENTIFIER &&
|
||||
data.Mid (9, 3) == XMP_AUTH_CODE) {
|
||||
// XMP Data is not organized in sub-blocks
|
||||
|
||||
// start of xmp data
|
||||
long data_start = Tell;
|
||||
|
||||
// start of trailer start
|
||||
// FIXME: Since File.Find is still buggy, the following call does not work to find the end of the
|
||||
// XMP data. Therfore, we use here a different way for now.
|
||||
//long xmp_trailer_start = Find (new ByteVector (0x00), data_start);
|
||||
|
||||
// Since searching just one byte is save, we search for the end of the xmp trailer which
|
||||
// consists of two 0x00 bytes and compute the expected start.
|
||||
long xmp_trailer_start = Find (new byte [] {0x00}, data_start) - XMP_MAGIC_TRAILER.Length + 2;
|
||||
|
||||
Seek (data_start, SeekOrigin.Begin);
|
||||
|
||||
if (xmp_trailer_start <= data_start)
|
||||
throw new CorruptFileException ("No End of XMP data found");
|
||||
|
||||
// length of xmp data
|
||||
int data_length = (int) (xmp_trailer_start - data_start);
|
||||
|
||||
ByteVector xmp_data = ReadBlock (data_length);
|
||||
ImageTag.AddTag (new XmpTag (xmp_data.ToString (StringType.UTF8), this));
|
||||
|
||||
// 2 bytes where read before
|
||||
AddMetadataBlock (position - 2, 14 + data_length + XMP_MAGIC_TRAILER.Length);
|
||||
|
||||
// set position behind the XMP block
|
||||
Seek (xmp_trailer_start + XMP_MAGIC_TRAILER.Length, SeekOrigin.Begin);
|
||||
|
||||
} else {
|
||||
SkipSubBlocks ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Reads a Comment Block at the current position. The current position must
|
||||
/// point to the 3rd byte of the comment block. (The other 2 bytes are usually
|
||||
/// read before to identify the comment block)
|
||||
/// </summary>
|
||||
private void ReadCommentBlock ()
|
||||
{
|
||||
long position = Tell;
|
||||
|
||||
// Comment Extension
|
||||
//
|
||||
// 1 Byte Extension Introducer (0x21)
|
||||
// 1 Byte Comment Label (0xFE)
|
||||
// N Bytes Comment Data (Sub Blocks)
|
||||
// 1 Byte Block Terminator (0x00)
|
||||
//
|
||||
// Note, the first 2 bytes are still read to identify the Comment Block.
|
||||
// Therefore, we only need to read the sub blocks and extract the data.
|
||||
|
||||
string comment = ReadSubBlocks ();
|
||||
|
||||
// Only add the tag, if no one is still contained.
|
||||
if ((TagTypes & TagTypes.GifComment) == 0x00) {
|
||||
ImageTag.AddTag (new GifCommentTag (comment));
|
||||
|
||||
// 2 bytes where read before
|
||||
AddMetadataBlock (position - 2, Tell - position + 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Skips the color table if there is one
|
||||
/// </summary>
|
||||
/// <param name="packed_data">
|
||||
/// A <see cref="System.Byte"/> with the packed data which is
|
||||
/// contained Logical Screen Descriptor or in the Image Descriptor.
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// The data contained in the packed data is different for the Logical
|
||||
/// Screen Descriptor and for the Image Descriptor. But fortunately,
|
||||
/// the bits which are used do identifying the exitstance and the size
|
||||
/// of the color table are at the same position.
|
||||
/// </remarks>
|
||||
private void SkipColorTable (byte packed_data)
|
||||
{
|
||||
// Packed Field (Information with Bit 0 is LSB)
|
||||
//
|
||||
// Bit 0-2 Size of Color Table
|
||||
// Bit 3-6 Other stuff
|
||||
// Bit 7 (Local|Global) Color Table Flag
|
||||
//
|
||||
// We are interested in Bit 7 which indicates if a global color table is
|
||||
// present or not and the Bits 0-2 which indicate the size of the color
|
||||
// table.
|
||||
if ((packed_data & 0x80) == 0x80) {
|
||||
// 2^(size + 1) for each color.
|
||||
int table_size = 3 * (1 << ((packed_data & 0x07) + 1));
|
||||
|
||||
// and simply skip the color table
|
||||
ByteVector color_table = ReadBlock (table_size);
|
||||
|
||||
if (color_table.Count != table_size)
|
||||
throw new CorruptFileException ("Unexpected end of Color Table");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Skip over the image data at the current position. The current position must
|
||||
/// point to 2nd byte of the Image Descriptor. (First byte is usually read before
|
||||
/// to identify the image descriptor.)
|
||||
/// </summary>
|
||||
private void SkipImage ()
|
||||
{
|
||||
// Image Descriptor
|
||||
//
|
||||
// 1 Byte Separator (0x2C)
|
||||
// 2 Bytes Image Left Position (little endian)
|
||||
// 2 Bytes Image Right Position (little endian)
|
||||
// 2 Bytes Image Witdh (little endian)
|
||||
// 2 Bytes Image Height (little endian)
|
||||
// 1 Byte Packed Data
|
||||
//
|
||||
// Note, the Separator was read before to identify the Image Block
|
||||
// Therefore, we only need to read 9 bytes here.
|
||||
ByteVector data = ReadBlock (9);
|
||||
|
||||
if (data.Count != 9)
|
||||
throw new CorruptFileException ("Unexpected end of Image Descriptor");
|
||||
|
||||
// Skip an optional local color table
|
||||
SkipColorTable (data [8]);
|
||||
|
||||
|
||||
// Image Data
|
||||
//
|
||||
// 1 Byte LZW Minimum Code Size
|
||||
// N Bytes Image Data (Sub-Blocks)
|
||||
//
|
||||
// Before the image data, one byte for LZW encoding information is used.
|
||||
// This byte is read first, then the sub-blocks are skipped.
|
||||
ReadBlock (1);
|
||||
SkipSubBlocks ();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Reads a sequence of sub-blocks from the current position and concatenates the data
|
||||
/// from the sub-blocks to a string. The current position must point to the size-byte
|
||||
/// of the first subblock to skip.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="System.String"/> with the data contained in the sub-blocks.
|
||||
/// </returns>
|
||||
private string ReadSubBlocks ()
|
||||
{
|
||||
// Sub Block
|
||||
// Starts with one byte with the number of data bytes
|
||||
// following. The last sub block is terminated by length 0
|
||||
System.Text.StringBuilder builder = new System.Text.StringBuilder ();
|
||||
|
||||
byte length = 0;
|
||||
|
||||
do {
|
||||
|
||||
if (length >= 0)
|
||||
builder.Append (ReadBlock (length).ToString ());
|
||||
|
||||
// read new length byte
|
||||
length = ReadByte ();
|
||||
|
||||
// The sub-blocks are terminated with 0
|
||||
} while (length != 0);
|
||||
|
||||
return builder.ToString ();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Skips over a sequence of sub-blocks from the current position in the file.
|
||||
/// The current position must point to the size-byte of the first subblock to skip.
|
||||
/// </summary>
|
||||
private void SkipSubBlocks ()
|
||||
{
|
||||
// Sub Block
|
||||
// Starts with one byte with the number of data bytes
|
||||
// following. The last sub block is terminated by length 0
|
||||
byte length = 0;
|
||||
|
||||
do {
|
||||
|
||||
if (Tell + length >= Length)
|
||||
throw new CorruptFileException ("Unexpected end of Sub-Block");
|
||||
|
||||
// Seek to end of sub-block and update the position
|
||||
Seek (Tell + length, SeekOrigin.Begin);
|
||||
|
||||
|
||||
// read new length byte
|
||||
length = ReadByte ();
|
||||
|
||||
// The sub-blocks are terminated with 0
|
||||
} while (length != 0);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Save the metadata to file.
|
||||
/// </summary>
|
||||
private void SaveMetadata ()
|
||||
{
|
||||
ByteVector comment_block = RenderGifCommentBlock ();
|
||||
ByteVector xmp_block = RenderXMPBlock ();
|
||||
|
||||
// If we write metadata and the version is not 89a, bump the format version
|
||||
// because application extension blocks and comment extension blocks are
|
||||
// specified in 89a.
|
||||
// If we do not write metadata or if metadata is deleted, we do not care
|
||||
// about the version, because it may be wrong before.
|
||||
if (comment_block != null && xmp_block != null && version != VERSION_89A) {
|
||||
Insert (VERSION_89A, 3, VERSION_89A.Length);
|
||||
}
|
||||
|
||||
// now, only metadata is stored at the beginning of the file, and we can overwrite it.
|
||||
ByteVector metadata_blocks = new ByteVector ();
|
||||
metadata_blocks.Add (comment_block);
|
||||
metadata_blocks.Add (xmp_block);
|
||||
|
||||
SaveMetadata (metadata_blocks, start_of_blocks);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Renders the XMP data to a Application Extension Block which can be
|
||||
/// embedded in a Gif file.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector"/> with the Application Extension Block for the
|
||||
/// XMP data, or <see langword="null" /> if the file does not have XMP data.
|
||||
/// </returns>
|
||||
private ByteVector RenderXMPBlock ()
|
||||
{
|
||||
// Check, if XmpTag is contained
|
||||
XmpTag xmp = ImageTag.Xmp;
|
||||
if (xmp == null)
|
||||
return null;
|
||||
|
||||
ByteVector xmp_data = new ByteVector ();
|
||||
|
||||
// Add Extension Introducer (0x21), Application Extension Label (0xFF) and
|
||||
// the Block Size (0x0B
|
||||
xmp_data.Add (new byte [] {0x21, 0xFF, 0x0B});
|
||||
|
||||
// Application Identifier and Appl. Auth. Code
|
||||
xmp_data.Add (XMP_IDENTIFIER);
|
||||
xmp_data.Add (XMP_AUTH_CODE);
|
||||
|
||||
// Add XMP data and Magic Trailer
|
||||
// For XMP, we do not need to store the data in sub-blocks, therfore we
|
||||
// can just add the whole rendered data. (The trailer fixes this)
|
||||
xmp_data.Add (xmp.Render ());
|
||||
xmp_data.Add (XMP_MAGIC_TRAILER);
|
||||
|
||||
return xmp_data;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Renders the Gif Comment to a Comment Extension Block which can be
|
||||
/// embedded in a Gif file.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector"/> with the Comment Extension Block for the
|
||||
/// Gif Comment, or <see langword="null" /> if the file does not have
|
||||
/// a Gif Comment.
|
||||
/// </returns>
|
||||
private ByteVector RenderGifCommentBlock ()
|
||||
{
|
||||
// Check, if GifCommentTag is contained
|
||||
GifCommentTag comment_tag = GetTag (TagTypes.GifComment) as GifCommentTag;
|
||||
if (comment_tag == null)
|
||||
return null;
|
||||
|
||||
string comment = comment_tag.Comment;
|
||||
if (comment == null)
|
||||
return null;
|
||||
|
||||
ByteVector comment_data = new ByteVector ();
|
||||
|
||||
// Add Extension Introducer (0x21) and Comment Label (0xFE)
|
||||
comment_data.Add (new byte [] {0x21, 0xFE});
|
||||
|
||||
// Add data of comment in sub-blocks of max length 256.
|
||||
ByteVector comment_bytes = new ByteVector (comment);
|
||||
byte block_max = 255;
|
||||
for (int start = 0; start < comment_bytes.Count; start += block_max) {
|
||||
byte block_length = (byte) Math.Min (comment_bytes.Count - start, block_max);
|
||||
|
||||
comment_data.Add (block_length);
|
||||
comment_data.Add (comment_bytes.Mid (start, block_length));
|
||||
}
|
||||
comment_data.Add (new byte [] {0x00});
|
||||
|
||||
return comment_data;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to extract the media properties of the main
|
||||
/// photo.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="Properties" /> object with a best effort guess
|
||||
/// at the right values. When no guess at all can be made,
|
||||
/// <see langword="null" /> is returned.
|
||||
/// </returns>
|
||||
private Properties ExtractProperties ()
|
||||
{
|
||||
if (width > 0 && height > 0)
|
||||
return new Properties (TimeSpan.Zero, new Codec (width, height));
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
//
|
||||
// GifCommentTag.cs:
|
||||
//
|
||||
// Author:
|
||||
// Ruben Vermeersch (ruben@savanne.be)
|
||||
// Mike Gemuende (mike@gemuende.de)
|
||||
//
|
||||
// Copyright (C) 2009 Ruben Vermeersch
|
||||
// Copyright (C) 2010 Mike Gemuende
|
||||
//
|
||||
// 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 TagLib.Image;
|
||||
|
||||
namespace TagLib.Gif
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains the Gif comment.
|
||||
/// </summary>
|
||||
public class GifCommentTag : ImageTag
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="value">
|
||||
/// The value of the comment.
|
||||
/// </param>
|
||||
public GifCommentTag (string value)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor. Creates a new empty comment.
|
||||
/// </summary>
|
||||
public GifCommentTag () {
|
||||
Value = null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// The value of the comment represented by the current instance.
|
||||
/// </summary>
|
||||
public string Value { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the comment for the image described
|
||||
/// by the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="string" /> containing the comment of the
|
||||
/// current instace.
|
||||
/// </value>
|
||||
public override string Comment {
|
||||
get { return Value; }
|
||||
set { Value = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Gets the tag types contained in the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Always <see cref="TagTypes.GifComment" />.
|
||||
/// </value>
|
||||
public override TagTypes TagTypes {
|
||||
get { return TagTypes.GifComment; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears the values stored in the current instance.
|
||||
/// </summary>
|
||||
public override void Clear ()
|
||||
{
|
||||
Value = null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,254 +0,0 @@
|
||||
//
|
||||
// ICodec.cs: Provides ICodec, IAudioCodec, and IVideoCodec interfaces.
|
||||
//
|
||||
// Author:
|
||||
// Brian Nickel (brian.nickel@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2007 Brian Nickel
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace TagLib {
|
||||
/// <summary>
|
||||
/// Indicates the types of media represented by a <see cref="ICodec"
|
||||
/// /> or <see cref="Properties" /> object.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// These values can be bitwise combined to represent multiple media
|
||||
/// types.
|
||||
/// </remarks>
|
||||
[Flags]
|
||||
public enum MediaTypes
|
||||
{
|
||||
/// <summary>
|
||||
/// No media is present.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Audio is present.
|
||||
/// </summary>
|
||||
Audio = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Video is present.
|
||||
/// </summary>
|
||||
Video = 2,
|
||||
|
||||
/// <summary>
|
||||
/// A Photo is present.
|
||||
/// </summary>
|
||||
Photo = 4,
|
||||
|
||||
/// <summary>
|
||||
/// Text is present.
|
||||
/// </summary>
|
||||
Text = 8
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This interface provides basic information, common to all media
|
||||
/// codecs.
|
||||
/// </summary>
|
||||
public interface ICodec
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the duration of the media represented by the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="TimeSpan" /> containing the duration of the
|
||||
/// media represented by the current instance.
|
||||
/// </value>
|
||||
TimeSpan Duration {get;}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the types of media represented by the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A bitwise combined <see cref="MediaTypes" /> containing
|
||||
/// the types of media represented by the current instance.
|
||||
/// </value>
|
||||
MediaTypes MediaTypes {get;}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a text description of the media represented by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="string" /> object containing a description
|
||||
/// of the media represented by the current instance.
|
||||
/// </value>
|
||||
string Description {get;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This interface inherits <see cref="ICodec" /> to provide
|
||||
/// information about an audio codec.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>When dealing with a <see cref="ICodec" />, if <see
|
||||
/// cref="ICodec.MediaTypes" /> contains <see cref="MediaTypes.Audio"
|
||||
/// />, it is safe to assume that the object also inherits <see
|
||||
/// cref="IAudioCodec" /> and can be recast without issue.</para>
|
||||
/// </remarks>
|
||||
public interface IAudioCodec : ICodec
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the bitrate of the audio represented by the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing a bitrate of the
|
||||
/// audio represented by the current instance.
|
||||
/// </value>
|
||||
int AudioBitrate {get;}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the sample count of the audio represented by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing the sample count
|
||||
/// of the audio represented by the current instance.
|
||||
/// </value>
|
||||
long AudioSampleCount {get;}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the sample rate of the audio represented by the
|
||||
/// current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing the sample rate of
|
||||
/// the audio represented by the current instance.
|
||||
/// </value>
|
||||
int AudioSampleRate {get;}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of channels in the audio represented by
|
||||
/// the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing the number of
|
||||
/// channels in the audio represented by the current
|
||||
/// instance.
|
||||
/// </value>
|
||||
int AudioChannels {get;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This interface provides information specific
|
||||
/// to lossless audio codecs.
|
||||
/// </summary>
|
||||
public interface ILosslessAudioCodec
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the number of bits per sample in the audio
|
||||
/// represented by the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing the number of bits
|
||||
/// per sample in the audio represented by the current
|
||||
/// instance.
|
||||
/// </value>
|
||||
int BitsPerSample {get;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This interface inherits <see cref="ICodec" /> to provide
|
||||
/// information about a video codec.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>When dealing with a <see cref="ICodec" />, if <see
|
||||
/// cref="ICodec.MediaTypes" /> contains <see cref="MediaTypes.Video"
|
||||
/// />, it is safe to assume that the object also inherits <see
|
||||
/// cref="IVideoCodec" /> and can be recast without issue.</para>
|
||||
/// </remarks>
|
||||
public interface IVideoCodec : ICodec
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the width of the video represented by the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing the width of the
|
||||
/// video represented by the current instance.
|
||||
/// </value>
|
||||
int VideoWidth {get;}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the height of the video represented by the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing the height of the
|
||||
/// video represented by the current instance.
|
||||
/// </value>
|
||||
int VideoHeight {get;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This interface inherits <see cref="ICodec" /> to provide
|
||||
/// information about a photo.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>When dealing with a <see cref="ICodec" />, if <see
|
||||
/// cref="ICodec.MediaTypes" /> contains <see cref="MediaTypes.Photo"
|
||||
/// />, it is safe to assume that the object also inherits <see
|
||||
/// cref="IPhotoCodec" /> and can be recast without issue.</para>
|
||||
/// </remarks>
|
||||
public interface IPhotoCodec : ICodec
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the width of the photo represented by the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing the width of the
|
||||
/// photo represented by the current instance.
|
||||
/// </value>
|
||||
int PhotoWidth {get;}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the height of the photo represented by the current
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value containing the height of the
|
||||
/// photo represented by the current instance.
|
||||
/// </value>
|
||||
int PhotoHeight {get;}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the (format specific) quality indicator of the photo
|
||||
/// represented by the current instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="int" /> value indicating the quality. A value
|
||||
/// 0 means that there was no quality indicator for the format
|
||||
/// or the file.
|
||||
/// </value>
|
||||
int PhotoQuality {get;}
|
||||
}
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
//
|
||||
// ByteIFDEntry.cs:
|
||||
//
|
||||
// Author:
|
||||
// Ruben Vermeersch (ruben@savanne.be)
|
||||
// Mike Gemuende (mike@gemuende.de)
|
||||
//
|
||||
// Copyright (C) 2009 Ruben Vermeersch
|
||||
// Copyright (C) 2009 Mike Gemuende
|
||||
//
|
||||
// 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.IFD.Entries
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains a byte value
|
||||
/// </summary>
|
||||
public class ByteIFDEntry : IFDEntry
|
||||
{
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <value>
|
||||
/// The ID of the tag, the current instance belongs to
|
||||
/// </value>
|
||||
public ushort Tag { get; private set; }
|
||||
|
||||
/// <value>
|
||||
/// The value which is stored by the current instance
|
||||
/// </value>
|
||||
public byte Value { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Construcor.
|
||||
/// </summary>
|
||||
/// <param name="tag">
|
||||
/// A <see cref="System.UInt16"/> with the tag ID of the entry this instance
|
||||
/// represents
|
||||
/// </param>
|
||||
/// <param name="value">
|
||||
/// A <see cref="System.Byte"/> to be stored
|
||||
/// </param>
|
||||
public ByteIFDEntry (ushort tag, byte value)
|
||||
{
|
||||
Tag = tag;
|
||||
Value = value;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Renders the current instance to a <see cref="ByteVector"/>
|
||||
/// </summary>
|
||||
/// <param name="is_bigendian">
|
||||
/// A <see cref="System.Boolean"/> indicating the endianess for rendering.
|
||||
/// </param>
|
||||
/// <param name="offset">
|
||||
/// A <see cref="System.UInt32"/> with the offset, the data is stored.
|
||||
/// </param>
|
||||
/// <param name="type">
|
||||
/// A <see cref="System.UInt16"/> the ID of the type, which is rendered
|
||||
/// </param>
|
||||
/// <param name="count">
|
||||
/// A <see cref="System.UInt32"/> with the count of the values which are
|
||||
/// rendered.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector"/> with the rendered data.
|
||||
/// </returns>
|
||||
public ByteVector Render (bool is_bigendian, uint offset, out ushort type, out uint count)
|
||||
{
|
||||
type = (ushort) IFDEntryType.Byte;
|
||||
count = 1;
|
||||
|
||||
return Value;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
//
|
||||
// ByteVectorIFDEntry.cs:
|
||||
//
|
||||
// Author:
|
||||
// Ruben Vermeersch (ruben@savanne.be)
|
||||
// Mike Gemuende (mike@gemuende.de)
|
||||
//
|
||||
// Copyright (C) 2009 Ruben Vermeersch
|
||||
// Copyright (C) 2009 Mike Gemuende
|
||||
//
|
||||
// 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.IFD.Entries
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains an BYTE value with a count > 1 (byte sequence).
|
||||
/// </summary>
|
||||
public class ByteVectorIFDEntry : IFDEntry
|
||||
{
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <value>
|
||||
/// The ID of the tag, the current instance belongs to
|
||||
/// </value>
|
||||
public ushort Tag { get; private set; }
|
||||
|
||||
/// <value>
|
||||
/// The data which is stored by the current instance
|
||||
/// </value>
|
||||
public ByteVector Data { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Construcor.
|
||||
/// </summary>
|
||||
/// <param name="tag">
|
||||
/// A <see cref="System.UInt16"/> with the tag ID of the entry this instance
|
||||
/// represents
|
||||
/// </param>
|
||||
/// <param name="data">
|
||||
/// A <see cref="ByteVector"/> to be stored
|
||||
/// </param>
|
||||
public ByteVectorIFDEntry (ushort tag, ByteVector data)
|
||||
{
|
||||
Tag = tag;
|
||||
Data = data;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Renders the current instance to a <see cref="ByteVector"/>
|
||||
/// </summary>
|
||||
/// <param name="is_bigendian">
|
||||
/// A <see cref="System.Boolean"/> indicating the endianess for rendering.
|
||||
/// </param>
|
||||
/// <param name="offset">
|
||||
/// A <see cref="System.UInt32"/> with the offset, the data is stored.
|
||||
/// </param>
|
||||
/// <param name="type">
|
||||
/// A <see cref="System.UInt16"/> the ID of the type, which is rendered
|
||||
/// </param>
|
||||
/// <param name="count">
|
||||
/// A <see cref="System.UInt32"/> with the count of the values which are
|
||||
/// rendered.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector"/> with the rendered data.
|
||||
/// </returns>
|
||||
public ByteVector Render (bool is_bigendian, uint offset, out ushort type, out uint count)
|
||||
{
|
||||
type = (ushort) IFDEntryType.Byte;
|
||||
count = (uint) Data.Count;
|
||||
|
||||
return Data;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
//
|
||||
// LongArrayIFDEntry.cs:
|
||||
//
|
||||
// Author:
|
||||
// Ruben Vermeersch (ruben@savanne.be)
|
||||
// Mike Gemuende (mike@gemuende.de)
|
||||
//
|
||||
// Copyright (C) 2009 Ruben Vermeersch
|
||||
// Copyright (C) 2009 Mike Gemuende
|
||||
//
|
||||
// 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.IFD.Entries
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains a LONG value with a count > 1
|
||||
/// </summary>
|
||||
public class LongArrayIFDEntry : ArrayIFDEntry<uint>
|
||||
{
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Construcor.
|
||||
/// </summary>
|
||||
/// <param name="tag">
|
||||
/// A <see cref="System.UInt16"/> with the tag ID of the entry this instance
|
||||
/// represents
|
||||
/// </param>
|
||||
/// <param name="values">
|
||||
/// A <see cref="System.UInt32[]"/> to be stored
|
||||
/// </param>
|
||||
public LongArrayIFDEntry (ushort tag, uint [] values) : base (tag)
|
||||
{
|
||||
Values = values;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Renders the current instance to a <see cref="ByteVector"/>
|
||||
/// </summary>
|
||||
/// <param name="is_bigendian">
|
||||
/// A <see cref="System.Boolean"/> indicating the endianess for rendering.
|
||||
/// </param>
|
||||
/// <param name="offset">
|
||||
/// A <see cref="System.UInt32"/> with the offset, the data is stored.
|
||||
/// </param>
|
||||
/// <param name="type">
|
||||
/// A <see cref="System.UInt16"/> the ID of the type, which is rendered
|
||||
/// </param>
|
||||
/// <param name="count">
|
||||
/// A <see cref="System.UInt32"/> with the count of the values which are
|
||||
/// rendered.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector"/> with the rendered data.
|
||||
/// </returns>
|
||||
public override ByteVector Render (bool is_bigendian, uint offset, out ushort type, out uint count)
|
||||
{
|
||||
type = (ushort) IFDEntryType.Long;
|
||||
count = (uint) Values.Length;
|
||||
|
||||
ByteVector data = new ByteVector ();
|
||||
foreach (uint value in Values)
|
||||
data.Add (ByteVector.FromUInt (value, is_bigendian));
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
//
|
||||
// LongIFDEntry.cs:
|
||||
//
|
||||
// Author:
|
||||
// Ruben Vermeersch (ruben@savanne.be)
|
||||
// Mike Gemuende (mike@gemuende.de)
|
||||
//
|
||||
// Copyright (C) 2009 Ruben Vermeersch
|
||||
// Copyright (C) 2009 Mike Gemuende
|
||||
//
|
||||
// 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.IFD.Entries
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains a LONG value.
|
||||
/// </summary>
|
||||
public class LongIFDEntry : IFDEntry
|
||||
{
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <value>
|
||||
/// The ID of the tag, the current instance belongs to
|
||||
/// </value>
|
||||
public ushort Tag { get; private set; }
|
||||
|
||||
/// <value>
|
||||
/// The value which is stored by the current instance
|
||||
/// </value>
|
||||
public uint Value { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Construcor.
|
||||
/// </summary>
|
||||
/// <param name="tag">
|
||||
/// A <see cref="System.UInt16"/> with the tag ID of the entry this instance
|
||||
/// represents
|
||||
/// </param>
|
||||
/// <param name="value">
|
||||
/// A <see cref="System.UInt32"/> to be stored
|
||||
/// </param>
|
||||
public LongIFDEntry (ushort tag, uint value)
|
||||
{
|
||||
Tag = tag;
|
||||
Value = value;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Renders the current instance to a <see cref="ByteVector"/>
|
||||
/// </summary>
|
||||
/// <param name="is_bigendian">
|
||||
/// A <see cref="System.Boolean"/> indicating the endianess for rendering.
|
||||
/// </param>
|
||||
/// <param name="offset">
|
||||
/// A <see cref="System.UInt32"/> with the offset, the data is stored.
|
||||
/// </param>
|
||||
/// <param name="type">
|
||||
/// A <see cref="System.UInt16"/> the ID of the type, which is rendered
|
||||
/// </param>
|
||||
/// <param name="count">
|
||||
/// A <see cref="System.UInt32"/> with the count of the values which are
|
||||
/// rendered.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector"/> with the rendered data.
|
||||
/// </returns>
|
||||
public ByteVector Render (bool is_bigendian, uint offset, out ushort type, out uint count)
|
||||
{
|
||||
type = (ushort) IFDEntryType.Long;
|
||||
count = 1;
|
||||
|
||||
return ByteVector.FromUInt (Value, is_bigendian);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,279 +0,0 @@
|
||||
//
|
||||
// MakernoteIFDEntry.cs:
|
||||
//
|
||||
// Author:
|
||||
// Ruben Vermeersch (ruben@savanne.be)
|
||||
// Mike Gemuende (mike@gemuende.de)
|
||||
//
|
||||
// Copyright (C) 2009 Ruben Vermeersch
|
||||
// Copyright (C) 2009 Mike Gemuende
|
||||
//
|
||||
// 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.IFD.Entries
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// An enum to represent the manufactor of the makernote
|
||||
/// The information of the makernote types is from:
|
||||
/// http://exiv2.org/makernote.html
|
||||
/// </summary>
|
||||
public enum MakernoteType {
|
||||
|
||||
/// <summary>
|
||||
/// The manufactor could not be determined
|
||||
/// </summary>
|
||||
Unknown,
|
||||
|
||||
/// <summary>
|
||||
/// Canon makernote.
|
||||
/// Standard IFD without a special prefix.
|
||||
/// </summary>
|
||||
Canon,
|
||||
|
||||
/// <summary>
|
||||
/// Panasonic makernote.
|
||||
/// "Panasonic\0\0\0" prefix and IFD starting at offset 12.
|
||||
/// The next-IFD pointer is missing
|
||||
/// </summary>
|
||||
Panasonic,
|
||||
|
||||
/// <summary>
|
||||
/// Leica makernote.
|
||||
/// "LEICA\0\0\0" prefix and IFD starting at offset 10.
|
||||
/// </summary>
|
||||
Leica,
|
||||
|
||||
/// <summary>
|
||||
/// Pentax makernote.
|
||||
/// "AOC\0" + 2 unknown bytes as prefix. The IFD starts at
|
||||
/// offset 6.
|
||||
/// </summary>
|
||||
Pentax,
|
||||
|
||||
/// <summary>
|
||||
/// Nikon makernote (type 1).
|
||||
/// Standard IFD without a special prefix.
|
||||
/// </summary>
|
||||
Nikon1,
|
||||
|
||||
/// <summary>
|
||||
/// Nikon makernote (type 2).
|
||||
/// "Nikon\0" + 2 unknown bytes prefix. The IFD starts at
|
||||
/// offset 8.
|
||||
/// </summary>
|
||||
Nikon2,
|
||||
|
||||
/// <summary>
|
||||
/// Nikon makernote (type 3).
|
||||
/// "Nikon\0" + 4 bytes with verison code + Tiff header.
|
||||
/// The IFD starts usually at offset 18. The offsets of the IFD
|
||||
/// are relative to start of the Tiff header (byte 10)
|
||||
/// </summary>
|
||||
Nikon3,
|
||||
|
||||
/// <summary>
|
||||
/// Olympus makernote (type 1).
|
||||
/// "OLYMP\0" + 2 unknown bytes as prefix. The IFD starts at
|
||||
/// offset 8.
|
||||
/// </summary>
|
||||
Olympus1,
|
||||
|
||||
/// <summary>
|
||||
/// Olympus makernote (type 2)
|
||||
/// "OLYMPUS\0II" + 2 unknown bytes as prefix. The IFD starts at
|
||||
/// offset 12. The offsets of the IFD are relative to the
|
||||
/// beginning of the makernote.
|
||||
/// </summary>
|
||||
Olympus2,
|
||||
|
||||
/// <summary>
|
||||
/// Sony makernote (type 1).
|
||||
/// "SONY DSC \0\0\0" as prefix. The IFD starts at offset 12. A
|
||||
/// next-IFD pointer is missing.
|
||||
/// </summary>
|
||||
Sony
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Contains a Makernote IFD.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Makernote IFDs are mostly of the same form. They start with and
|
||||
/// Manufactor specific prefix indicating the type and contain then
|
||||
/// a IFD structure.
|
||||
/// It must be distinguished, where the offsets in the IFD belongs to.
|
||||
/// For some makernotes the offset refers to the beginning of the
|
||||
/// surrounding metadata IFD structure, for others they refer to the
|
||||
/// start of the makernote.
|
||||
/// In addition the endianess of the makernote can be different to the
|
||||
/// endianess of the surrounding metadata.
|
||||
/// This class takes care about all those things.
|
||||
/// </remarks>
|
||||
public class MakernoteIFDEntry : IFDEntry
|
||||
{
|
||||
|
||||
#region Private Fields
|
||||
|
||||
/// <value>
|
||||
/// Stores the prefix of the makernote
|
||||
/// </value>
|
||||
private ByteVector prefix;
|
||||
|
||||
/// <value>
|
||||
/// Stores the offset of the IFD contained in makernote
|
||||
/// </value>
|
||||
private uint ifd_offset;
|
||||
|
||||
/// <value>
|
||||
/// Indicates, if the offsets are relative to the current makernote
|
||||
/// or absolut to the base_offset of the surrounding IFD.
|
||||
/// </value>
|
||||
private bool absolute_offset;
|
||||
|
||||
/// <value>
|
||||
/// Stores, if the makernote is encoded in big- or little endian.
|
||||
/// If the field is <see langword="null"/>, the endianess of the
|
||||
/// surrounding IFD is used.
|
||||
/// </value>
|
||||
private bool? is_bigendian;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <value>
|
||||
/// The ID of the tag, the current instance belongs to
|
||||
/// </value>
|
||||
public ushort Tag { get; private set; }
|
||||
|
||||
/// <value>
|
||||
/// The type of the makernote the current instance represents
|
||||
/// </value>
|
||||
public MakernoteType MakernoteType { get; private set; }
|
||||
|
||||
/// <value>
|
||||
/// The pure <see cref="IFDStructure"/> which is stored by the
|
||||
/// makernote.
|
||||
/// </value>
|
||||
public IFDStructure Structure { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Construcor.
|
||||
/// </summary>
|
||||
/// <param name="tag">
|
||||
/// A <see cref="System.UInt16"/> with the tag ID of the entry this instance
|
||||
/// represents
|
||||
/// </param>
|
||||
/// <param name="structure">
|
||||
/// A <see cref="IFDStructure"/> with the IFD structure, which is stored by this
|
||||
/// instance
|
||||
/// </param>
|
||||
/// <param name="makernote_type">
|
||||
/// A <see cref="MakernoteType"/> with the type of the makernote.
|
||||
/// </param>
|
||||
/// <param name="prefix">
|
||||
/// A <see cref="ByteVector"/> containing the prefix, which should be rendered
|
||||
/// before the real IFD.
|
||||
/// </param>
|
||||
/// <param name="ifd_offset">
|
||||
/// A <see cref="System.UInt32"/> with the offset in addition to the relative
|
||||
/// offsets in the IFD
|
||||
/// </param>
|
||||
/// <param name="absolute_offset">
|
||||
/// A <see cref="System.Boolean"/> indicating if the offsets of the IFD are relative
|
||||
/// to the <paramref name="ifd_offset"/>, or absolut to the base offset of the
|
||||
/// surrounding IFD.
|
||||
/// </param>
|
||||
/// <param name="is_bigendian">
|
||||
/// A <see cref="System.Nullable"/> indicating if the current IFD is encoded in
|
||||
/// big- or little endian. It it is <see langword="null"/>, the endianess of the
|
||||
/// surrounding IFD is used.
|
||||
/// </param>
|
||||
public MakernoteIFDEntry (ushort tag, IFDStructure structure, MakernoteType makernote_type, ByteVector prefix, uint ifd_offset, bool absolute_offset, bool? is_bigendian)
|
||||
{
|
||||
Tag = tag;
|
||||
Structure = structure;
|
||||
MakernoteType = makernote_type;
|
||||
this.prefix = prefix;
|
||||
this.ifd_offset = ifd_offset;
|
||||
this.absolute_offset = absolute_offset;
|
||||
this.is_bigendian = is_bigendian;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor. Creates a makernote instance just containing an IFD and
|
||||
/// without any special prefix or offset behavior.
|
||||
/// </summary>
|
||||
/// <param name="tag">
|
||||
/// A <see cref="System.UInt16"/> with the tag ID of the entry this instance
|
||||
/// represents
|
||||
/// </param>
|
||||
/// <param name="structure">
|
||||
/// A <see cref="IFDStructure"/> with the IFD structure, which is stored by this
|
||||
/// instance
|
||||
/// </param>
|
||||
/// <param name="makernote_type">
|
||||
/// A <see cref="MakernoteType"/> with the type of the makernote.
|
||||
/// </param>
|
||||
public MakernoteIFDEntry (ushort tag, IFDStructure structure, MakernoteType makernote_type)
|
||||
: this (tag, structure, makernote_type, null, 0, true, null) {}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Renders the current instance to a <see cref="ByteVector"/>
|
||||
/// </summary>
|
||||
/// <param name="is_bigendian">
|
||||
/// A <see cref="System.Boolean"/> indicating the endianess for rendering.
|
||||
/// </param>
|
||||
/// <param name="offset">
|
||||
/// A <see cref="System.UInt32"/> with the offset, the data is stored.
|
||||
/// </param>
|
||||
/// <param name="type">
|
||||
/// A <see cref="System.UInt16"/> the ID of the type, which is rendered
|
||||
/// </param>
|
||||
/// <param name="count">
|
||||
/// A <see cref="System.UInt32"/> with the count of the values which are
|
||||
/// rendered.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector"/> with the rendered data.
|
||||
/// </returns>
|
||||
public ByteVector Render (bool is_bigendian, uint offset, out ushort type, out uint count)
|
||||
{
|
||||
type = (ushort) IFDEntryType.Undefined;
|
||||
|
||||
var renderer =
|
||||
new IFDRenderer (this.is_bigendian ?? is_bigendian, Structure, absolute_offset ? offset + ifd_offset : ifd_offset);
|
||||
|
||||
ByteVector data = renderer.Render ();
|
||||
data.Insert (0, prefix);
|
||||
count = (uint) data.Count;
|
||||
return data;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,174 +0,0 @@
|
||||
//
|
||||
// Rational.cs: A structure to represent rational values by a numerator and
|
||||
// a denominator.
|
||||
//
|
||||
// Author:
|
||||
// Mike Gemuende (mike@gemuende.de)
|
||||
//
|
||||
// Copyright (C) 2009 Ruben Vermeersch
|
||||
// Copyright (C) 2009 Mike Gemuende
|
||||
//
|
||||
// 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.IFD.Entries
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Representation of an unsigned rational value
|
||||
/// </summary>
|
||||
public struct Rational : IFormattable
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// The numerator of the rational value
|
||||
/// </summary>
|
||||
private uint numerator;
|
||||
|
||||
/// <summary>
|
||||
/// The denominator of the rational value
|
||||
/// </summary>
|
||||
private uint denominator;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new Rational value
|
||||
/// </summary>
|
||||
/// <param name="numerator">
|
||||
/// A <see cref="System.UInt32"/> with the numerator of the
|
||||
/// rational value
|
||||
/// </param>
|
||||
/// <param name="denominator">
|
||||
/// A <see cref="System.UInt32"/> with the denominator of the
|
||||
/// rational value. It must be not 0.
|
||||
/// </param>
|
||||
public Rational (uint numerator, uint denominator)
|
||||
{
|
||||
if (denominator == 0)
|
||||
throw new ArgumentException ("denominator");
|
||||
this.numerator = numerator;
|
||||
this.denominator = denominator;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Returns a rational value with reduced nominator and denominator
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="Rational"/>
|
||||
/// </returns>
|
||||
public Rational Reduce ()
|
||||
{
|
||||
uint gcd = Denominator;
|
||||
uint b = Numerator;
|
||||
|
||||
while (b != 0) {
|
||||
uint tmp = gcd % b;
|
||||
gcd = b;
|
||||
b = tmp;
|
||||
}
|
||||
|
||||
return new Rational (Numerator / gcd, Denominator / gcd);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Formatprovider to allow formatting of a value. <see cref="IFormattable"/>
|
||||
/// </summary>
|
||||
/// <param name="format">
|
||||
/// A <see cref="System.String"/>. <see cref="IFormattable"/>
|
||||
/// </param>
|
||||
/// <param name="provider">
|
||||
/// A <see cref="IFormatProvider"/>. <see cref="IFormattable"/>
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="System.String"/> formated according to the given parameter
|
||||
/// </returns>
|
||||
public string ToString (string format, IFormatProvider provider) {
|
||||
|
||||
Rational reduced = Reduce ();
|
||||
|
||||
return String.Format ("{0}/{1}", reduced.Numerator, reduced.Denominator);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the value to a <see cref="System.String"/>.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="System.String"/> with the current value.
|
||||
/// </returns>
|
||||
public override string ToString ()
|
||||
{
|
||||
return String.Format ("{0}", this);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <value>
|
||||
/// The numerator of the rational value
|
||||
/// </value>
|
||||
public uint Numerator {
|
||||
get { return numerator; }
|
||||
set { numerator = value; }
|
||||
}
|
||||
|
||||
/// <value>
|
||||
/// The denominator of the rational value
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// Cannot be 0.
|
||||
/// </remarks>
|
||||
public uint Denominator {
|
||||
get { return denominator; }
|
||||
set {
|
||||
if (value == 0)
|
||||
throw new ArgumentException ("denominator");
|
||||
|
||||
denominator = value;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Static Methods
|
||||
|
||||
/// <summary>
|
||||
/// Cast the <see cref="Rational"/> value to a <see cref="System.Double"/>.
|
||||
/// </summary>
|
||||
/// <param name="rat">
|
||||
/// A <see cref="Rational"/> with the value to cast.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="System.Double"/> with the double.
|
||||
/// </returns>
|
||||
public static implicit operator double (Rational rat)
|
||||
{
|
||||
return (double) rat.Numerator / (double) rat.Denominator;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
//
|
||||
// RationalArrayIFDEntry.cs:
|
||||
//
|
||||
// Author:
|
||||
// Ruben Vermeersch (ruben@savanne.be)
|
||||
// Mike Gemuende (mike@gemuende.de)
|
||||
//
|
||||
// Copyright (C) 2009 Ruben Vermeersch
|
||||
// Copyright (C) 2009 Mike Gemuende
|
||||
//
|
||||
// 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.IFD.Entries
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains a RATIONAL value with a count > 1
|
||||
/// </summary>
|
||||
public class RationalArrayIFDEntry : ArrayIFDEntry<Rational>
|
||||
{
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Construcor.
|
||||
/// </summary>
|
||||
/// <param name="tag">
|
||||
/// A <see cref="System.UInt16"/> with the tag ID of the entry this instance
|
||||
/// represents
|
||||
/// </param>
|
||||
/// <param name="entries">
|
||||
/// A <see cref="Rational[]"/> to be stored
|
||||
/// </param>
|
||||
public RationalArrayIFDEntry (ushort tag, Rational [] entries)
|
||||
: base (tag)
|
||||
{
|
||||
Values = entries;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Renders the current instance to a <see cref="ByteVector"/>
|
||||
/// </summary>
|
||||
/// <param name="is_bigendian">
|
||||
/// A <see cref="System.Boolean"/> indicating the endianess for rendering.
|
||||
/// </param>
|
||||
/// <param name="offset">
|
||||
/// A <see cref="System.UInt32"/> with the offset, the data is stored.
|
||||
/// </param>
|
||||
/// <param name="type">
|
||||
/// A <see cref="System.UInt16"/> the ID of the type, which is rendered
|
||||
/// </param>
|
||||
/// <param name="count">
|
||||
/// A <see cref="System.UInt32"/> with the count of the values which are
|
||||
/// rendered.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector"/> with the rendered data.
|
||||
/// </returns>
|
||||
public override ByteVector Render (bool is_bigendian, uint offset, out ushort type, out uint count)
|
||||
{
|
||||
type = (ushort) IFDEntryType.Rational;
|
||||
count = (uint) Values.Length;
|
||||
|
||||
ByteVector data = new ByteVector ();
|
||||
foreach (Rational rational in Values) {
|
||||
data.Add (ByteVector.FromUInt (rational.Numerator, is_bigendian));
|
||||
data.Add (ByteVector.FromUInt (rational.Denominator, is_bigendian));
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
//
|
||||
// RationalIFDEntry.cs:
|
||||
//
|
||||
// Author:
|
||||
// Ruben Vermeersch (ruben@savanne.be)
|
||||
// Mike Gemuende (mike@gemuende.de)
|
||||
//
|
||||
// Copyright (C) 2009 Ruben Vermeersch
|
||||
// Copyright (C) 2009 Mike Gemuende
|
||||
//
|
||||
// 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.IFD.Entries
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains a RATIONAL value.
|
||||
/// </summary>
|
||||
public class RationalIFDEntry : IFDEntry
|
||||
{
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <value>
|
||||
/// The ID of the tag, the current instance belongs to
|
||||
/// </value>
|
||||
public ushort Tag { get; private set; }
|
||||
|
||||
/// <value>
|
||||
/// The value which is stored by the current instance
|
||||
/// </value>
|
||||
public Rational Value { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Construcor.
|
||||
/// </summary>
|
||||
/// <param name="tag">
|
||||
/// A <see cref="System.UInt16"/> with the tag ID of the entry this instance
|
||||
/// represents
|
||||
/// </param>
|
||||
/// <param name="value">
|
||||
/// A <see cref="Rational"/>
|
||||
/// </param>
|
||||
public RationalIFDEntry (ushort tag, Rational value)
|
||||
{
|
||||
Tag = tag;
|
||||
Value = value;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Renders the current instance to a <see cref="ByteVector"/>
|
||||
/// </summary>
|
||||
/// <param name="is_bigendian">
|
||||
/// A <see cref="System.Boolean"/> indicating the endianess for rendering.
|
||||
/// </param>
|
||||
/// <param name="offset">
|
||||
/// A <see cref="System.UInt32"/> with the offset, the data is stored.
|
||||
/// </param>
|
||||
/// <param name="type">
|
||||
/// A <see cref="System.UInt16"/> the ID of the type, which is rendered
|
||||
/// </param>
|
||||
/// <param name="count">
|
||||
/// A <see cref="System.UInt32"/> with the count of the values which are
|
||||
/// rendered.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector"/> with the rendered data.
|
||||
/// </returns>
|
||||
public ByteVector Render (bool is_bigendian, uint offset, out ushort type, out uint count)
|
||||
{
|
||||
type = (ushort) IFDEntryType.Rational;
|
||||
count = 1;
|
||||
|
||||
ByteVector data = new ByteVector ();
|
||||
data.Add (ByteVector.FromUInt (Value.Numerator, is_bigendian));
|
||||
data.Add (ByteVector.FromUInt (Value.Denominator, is_bigendian));
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
//
|
||||
// SByteIFDEntry.cs:
|
||||
//
|
||||
// Author:
|
||||
// Ruben Vermeersch (ruben@savanne.be)
|
||||
// Mike Gemuende (mike@gemuende.de)
|
||||
//
|
||||
// Copyright (C) 2009 Ruben Vermeersch
|
||||
// Copyright (C) 2009 Mike Gemuende
|
||||
//
|
||||
// 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.IFD.Entries
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains a signed byte value
|
||||
/// </summary>
|
||||
public class SByteIFDEntry : IFDEntry
|
||||
{
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <value>
|
||||
/// The ID of the tag, the current instance belongs to
|
||||
/// </value>
|
||||
public ushort Tag { get; private set; }
|
||||
|
||||
/// <value>
|
||||
/// The value which is stored by the current instance
|
||||
/// </value>
|
||||
public sbyte Value { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Construcor.
|
||||
/// </summary>
|
||||
/// <param name="tag">
|
||||
/// A <see cref="System.UInt16"/> with the tag ID of the entry this instance
|
||||
/// represents
|
||||
/// </param>
|
||||
/// <param name="value">
|
||||
/// A <see cref="System.SByte"/> to be stored
|
||||
/// </param>
|
||||
public SByteIFDEntry (ushort tag, sbyte value)
|
||||
{
|
||||
Tag = tag;
|
||||
Value = value;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Renders the current instance to a <see cref="ByteVector"/>
|
||||
/// </summary>
|
||||
/// <param name="is_bigendian">
|
||||
/// A <see cref="System.Boolean"/> indicating the endianess for rendering.
|
||||
/// </param>
|
||||
/// <param name="offset">
|
||||
/// A <see cref="System.UInt32"/> with the offset, the data is stored.
|
||||
/// </param>
|
||||
/// <param name="type">
|
||||
/// A <see cref="System.UInt16"/> the ID of the type, which is rendered
|
||||
/// </param>
|
||||
/// <param name="count">
|
||||
/// A <see cref="System.UInt32"/> with the count of the values which are
|
||||
/// rendered.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="ByteVector"/> with the rendered data.
|
||||
/// </returns>
|
||||
public ByteVector Render (bool is_bigendian, uint offset, out ushort type, out uint count)
|
||||
{
|
||||
type = (ushort) IFDEntryType.SByte;
|
||||
count = 1;
|
||||
|
||||
return (byte) Value;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||