Switch to the new taglib-sharp version. Add support for opus.

This commit is contained in:
Grigory Chudov
2018-03-11 21:35:46 -04:00
parent 284da94ac0
commit 807063f4f2
284 changed files with 50 additions and 92502 deletions

View File

@@ -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>

View File

@@ -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));
}
}
}

View File

@@ -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>

View File

@@ -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>

View File

@@ -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" />

View File

@@ -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" />

View File

@@ -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}

View File

@@ -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>

View File

@@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 B

View File

@@ -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);

View File

@@ -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

View File

@@ -1,3 +0,0 @@
[submodule "tests/raw-samples"]
path = tests/raw-samples
url = git://gitorious.org/taglib-sharp/raw-samples.git

View File

@@ -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>

View File

@@ -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!

File diff suppressed because it is too large Load Diff

View File

@@ -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"

View File

@@ -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.

View File

@@ -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

View File

@@ -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

View File

@@ -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."

View File

@@ -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

View File

@@ -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>

View File

@@ -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;
}
}

View File

@@ -1,4 +0,0 @@
<?xml version="1.0"?>
<monodoc>
<source provider="ecma" basefile="taglib-sharp-docs" path="classlib-taglib-sharp" />
</monodoc>

View File

@@ -1,2 +0,0 @@
extractKey
listData

View File

@@ -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();
}
}
}

View File

@@ -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
}

View File

@@ -1,13 +0,0 @@
using System;
using TagLib;
public class ListSupportedMimeTypes
{
public static void Main()
{
foreach(string type in SupportedMimeType.AllMimeTypes) {
Console.WriteLine(type);
}
}
}

View File

@@ -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

View File

@@ -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 ("---------------------------------------");
}
}

View File

@@ -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)

View File

@@ -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 ();
}
}

View File

@@ -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>

View File

@@ -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);
}
}

View File

@@ -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>

View File

@@ -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 ();
}
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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)]

View File

@@ -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)]

View File

@@ -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

View File

@@ -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
}
}

View File

@@ -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
}
}

View File

@@ -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 &amp; ~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
}
}

View File

@@ -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
}
}

View File

@@ -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
}
}

View File

@@ -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 &amp; ~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
}
}

View File

@@ -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
}
}

View File

@@ -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
}
}

View File

@@ -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
}

File diff suppressed because it is too large Load Diff

View File

@@ -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
}
}

View File

@@ -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
}
}

View File

@@ -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
}
}

View File

@@ -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
}
}

View File

@@ -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
}
}

View File

@@ -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
}
}

View File

@@ -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");
}
}

View File

@@ -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
}
}

View File

@@ -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
}
}

View File

@@ -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
}
}

View File

@@ -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
}
}

View File

@@ -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
}
}

View File

@@ -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
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -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
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -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);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -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 &lt;System.dll>
/// #using &lt;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)
{
}
}
}

View File

@@ -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;
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -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;}
}
}
}

View File

@@ -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
}
}

View File

@@ -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;}
}
}
}

View File

@@ -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 &amp; ~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 ();
}
}
}

View File

@@ -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
}
}

View File

@@ -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
}
}

View File

@@ -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;
}
}
}

View File

@@ -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) {}
}
}

View File

@@ -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
}
}

View File

@@ -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
}
}

View File

@@ -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;}
}
}

View File

@@ -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
}
}

View File

@@ -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
}
}

View File

@@ -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
}
}

View File

@@ -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
}
}

View File

@@ -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
}
}

View File

@@ -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
}
}

View File

@@ -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
}
}

View File

@@ -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
}
}

View File

@@ -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
}
}

Some files were not shown because too many files have changed in this diff Show More