mirror of
https://github.com/claunia/cuetools.net.git
synced 2025-12-16 18:14:25 +00:00
taglib-sharp initial import (r553)
This commit is contained in:
31
taglib-sharp/.gitignore
vendored
Normal file
31
taglib-sharp/.gitignore
vendored
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
INSTALL
|
||||||
|
Makefile
|
||||||
|
Makefile.in
|
||||||
|
aclocal.m4
|
||||||
|
autom4te.cache/
|
||||||
|
bin/
|
||||||
|
config.log
|
||||||
|
config.status
|
||||||
|
configure
|
||||||
|
*.exe
|
||||||
|
*.mdb
|
||||||
|
*.pidb
|
||||||
|
*.config
|
||||||
|
install-sh
|
||||||
|
missing
|
||||||
|
src/AssemblyInfo.cs
|
||||||
|
*.pc
|
||||||
|
*.zip
|
||||||
|
tests/samples/tmp*
|
||||||
|
docs/*.xml
|
||||||
|
docs/*/*
|
||||||
|
docs/*.tree
|
||||||
|
*.dll.xml
|
||||||
|
examples/*.dll
|
||||||
|
*.userprefs
|
||||||
|
src/*.dll
|
||||||
|
src/*.snk
|
||||||
|
tests/*.dll
|
||||||
|
tests/*.xml
|
||||||
|
test-results
|
||||||
|
.*.swp
|
||||||
3
taglib-sharp/.gitmodules
vendored
Normal file
3
taglib-sharp/.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[submodule "tests/raw-samples"]
|
||||||
|
path = tests/raw-samples
|
||||||
|
url = git://gitorious.org/taglib-sharp/raw-samples.git
|
||||||
29
taglib-sharp/AUTHORS
Normal file
29
taglib-sharp/AUTHORS
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
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>
|
||||||
504
taglib-sharp/COPYING
Normal file
504
taglib-sharp/COPYING
Normal file
@@ -0,0 +1,504 @@
|
|||||||
|
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!
|
||||||
|
|
||||||
|
|
||||||
7032
taglib-sharp/ChangeLog
Normal file
7032
taglib-sharp/ChangeLog
Normal file
File diff suppressed because it is too large
Load Diff
76
taglib-sharp/Makefile.am
Normal file
76
taglib-sharp/Makefile.am
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
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"
|
||||||
333
taglib-sharp/NEWS
Normal file
333
taglib-sharp/NEWS
Normal file
@@ -0,0 +1,333 @@
|
|||||||
|
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.
|
||||||
29
taglib-sharp/README
Normal file
29
taglib-sharp/README
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
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
|
||||||
136
taglib-sharp/autogen.sh
Normal file
136
taglib-sharp/autogen.sh
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
#!/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
|
||||||
153
taglib-sharp/configure.ac
Normal file
153
taglib-sharp/configure.ac
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
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."
|
||||||
66
taglib-sharp/docs/Makefile.am
Normal file
66
taglib-sharp/docs/Makefile.am
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
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
|
||||||
221
taglib-sharp/docs/Package.en.xml.in
Normal file
221
taglib-sharp/docs/Package.en.xml.in
Normal file
@@ -0,0 +1,221 @@
|
|||||||
|
<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>
|
||||||
191
taglib-sharp/docs/XmlInjector.cs
Normal file
191
taglib-sharp/docs/XmlInjector.cs
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
4
taglib-sharp/docs/taglib-sharp-docs.source
Normal file
4
taglib-sharp/docs/taglib-sharp-docs.source
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<monodoc>
|
||||||
|
<source provider="ecma" basefile="taglib-sharp-docs" path="classlib-taglib-sharp" />
|
||||||
|
</monodoc>
|
||||||
2
taglib-sharp/examples/.gitignore
vendored
Normal file
2
taglib-sharp/examples/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
extractKey
|
||||||
|
listData
|
||||||
131
taglib-sharp/examples/BatchSet.cs
Normal file
131
taglib-sharp/examples/BatchSet.cs
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
924
taglib-sharp/examples/GenerateTestFixture.cs
Normal file
924
taglib-sharp/examples/GenerateTestFixture.cs
Normal file
@@ -0,0 +1,924 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
}
|
||||||
13
taglib-sharp/examples/ListSupportedMimeTypes.cs
Normal file
13
taglib-sharp/examples/ListSupportedMimeTypes.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
using System;
|
||||||
|
using TagLib;
|
||||||
|
|
||||||
|
public class ListSupportedMimeTypes
|
||||||
|
{
|
||||||
|
public static void Main()
|
||||||
|
{
|
||||||
|
foreach(string type in SupportedMimeType.AllMimeTypes) {
|
||||||
|
Console.WriteLine(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
61
taglib-sharp/examples/Makefile.am
Normal file
61
taglib-sharp/examples/Makefile.am
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
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
|
||||||
|
|
||||||
82
taglib-sharp/examples/ParsePhoto.cs
Normal file
82
taglib-sharp/examples/ParsePhoto.cs
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
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 ("---------------------------------------");
|
||||||
|
}
|
||||||
|
}
|
||||||
136
taglib-sharp/examples/ReadFromUri.boo
Normal file
136
taglib-sharp/examples/ReadFromUri.boo
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
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)
|
||||||
171
taglib-sharp/examples/ReadFromUri.cs
Normal file
171
taglib-sharp/examples/ReadFromUri.cs
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
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 ();
|
||||||
|
}
|
||||||
|
}
|
||||||
55
taglib-sharp/examples/ReadFromUri.csproj
Normal file
55
taglib-sharp/examples/ReadFromUri.csproj
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
<?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>
|
||||||
28
taglib-sharp/examples/SetPictures.cs
Normal file
28
taglib-sharp/examples/SetPictures.cs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
52
taglib-sharp/examples/SetPictures.csproj
Normal file
52
taglib-sharp/examples/SetPictures.csproj
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
<?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>
|
||||||
117
taglib-sharp/examples/StripImageData.cs
Normal file
117
taglib-sharp/examples/StripImageData.cs
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
|
||||||
|
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 ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
taglib-sharp/examples/covers/sample_a.jpg
Normal file
BIN
taglib-sharp/examples/covers/sample_a.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 30 KiB |
BIN
taglib-sharp/examples/covers/sample_a.png
Normal file
BIN
taglib-sharp/examples/covers/sample_a.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
BIN
taglib-sharp/examples/covers/sample_b.jpg
Normal file
BIN
taglib-sharp/examples/covers/sample_b.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
BIN
taglib-sharp/examples/covers/sample_b.png
Normal file
BIN
taglib-sharp/examples/covers/sample_b.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
BIN
taglib-sharp/examples/covers/sample_c.jpg
Normal file
BIN
taglib-sharp/examples/covers/sample_c.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 30 KiB |
BIN
taglib-sharp/examples/covers/sample_c.png
Normal file
BIN
taglib-sharp/examples/covers/sample_c.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
41
taglib-sharp/examples/extractKey.cpp
Normal file
41
taglib-sharp/examples/extractKey.cpp
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#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;
|
||||||
|
}
|
||||||
62
taglib-sharp/examples/listData.cpp
Normal file
62
taglib-sharp/examples/listData.cpp
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
#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;
|
||||||
|
}
|
||||||
36
taglib-sharp/src/AssemblyInfo.cs.in
Normal file
36
taglib-sharp/src/AssemblyInfo.cs.in
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
//
|
||||||
|
// 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)]
|
||||||
69
taglib-sharp/src/Makefile.am
Normal file
69
taglib-sharp/src/Makefile.am
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
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
|
||||||
433
taglib-sharp/src/TagLib/Aac/AudioHeader.cs
Normal file
433
taglib-sharp/src/TagLib/Aac/AudioHeader.cs
Normal file
@@ -0,0 +1,433 @@
|
|||||||
|
//
|
||||||
|
// 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 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
|
||||||
|
}
|
||||||
|
}
|
||||||
110
taglib-sharp/src/TagLib/Aac/BitStream.cs
Normal file
110
taglib-sharp/src/TagLib/Aac/BitStream.cs
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
282
taglib-sharp/src/TagLib/Aac/File.cs
Normal file
282
taglib-sharp/src/TagLib/Aac/File.cs
Normal file
@@ -0,0 +1,282 @@
|
|||||||
|
//
|
||||||
|
// File.cs: Provides tagging and properties support for ADTS AAC files
|
||||||
|
//
|
||||||
|
// Here is the ADTS Header description used for implementation:
|
||||||
|
// http://www.hydrogenaudio.org/forums/lofiversion/index.php/t21617.html
|
||||||
|
//
|
||||||
|
// Copyright (C) 2009 Patrick Dehne
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Lesser General Public License version
|
||||||
|
// 2.1 as published by the Free Software Foundation.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful, but
|
||||||
|
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
|
// USA
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace TagLib.Aac
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This class extends <see cref="TagLib.NonContainer.File" /> to
|
||||||
|
/// provide tagging and properties support for ADTS AAC audio files.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// A <see cref="TagLib.Id3v1.Tag" /> and <see
|
||||||
|
/// cref="TagLib.Id3v2.Tag" /> will be added automatically to any
|
||||||
|
/// file that doesn't contain one. This change does not effect the
|
||||||
|
/// file until it is saved and can be reversed using the following
|
||||||
|
/// method:
|
||||||
|
/// <code>file.RemoveTags (file.TagTypes & ~file.TagTypesOnDisk);</code>
|
||||||
|
/// </remarks>
|
||||||
|
[SupportedMimeType("taglib/aac", "aac")]
|
||||||
|
[SupportedMimeType("audio/aac")]
|
||||||
|
public class File : TagLib.NonContainer.File
|
||||||
|
{
|
||||||
|
#region Private Fields
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Contains the first audio header.
|
||||||
|
/// </summary>
|
||||||
|
private AudioHeader first_header;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs and initializes a new instance of <see
|
||||||
|
/// cref="File" /> for a specified path in the local
|
||||||
|
/// file system and specified read style.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">
|
||||||
|
/// A <see cref="string" /> object containing the path of the
|
||||||
|
/// file to use in the new instance.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="propertiesStyle">
|
||||||
|
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||||
|
/// of accuracy to read the media properties, or <see
|
||||||
|
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||||
|
/// </param>
|
||||||
|
/// <exception cref="ArgumentNullException">
|
||||||
|
/// <paramref name="path" /> is <see langword="null" />.
|
||||||
|
/// </exception>
|
||||||
|
public File (string path, ReadStyle propertiesStyle)
|
||||||
|
: base (path, propertiesStyle)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs and initializes a new instance of <see
|
||||||
|
/// cref="File" /> for a specified path in the local
|
||||||
|
/// file system with an average read style.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">
|
||||||
|
/// A <see cref="string" /> object containing the path of the
|
||||||
|
/// file to use in the new instance.
|
||||||
|
/// </param>
|
||||||
|
/// <exception cref="ArgumentNullException">
|
||||||
|
/// <paramref name="path" /> is <see langword="null" />.
|
||||||
|
/// </exception>
|
||||||
|
public File (string path) : base (path)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs and initializes a new instance of <see
|
||||||
|
/// cref="File" /> for a specified file abstraction and
|
||||||
|
/// specified read style.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="abstraction">
|
||||||
|
/// A <see cref="TagLib.File.IFileAbstraction" /> object to use when
|
||||||
|
/// reading from and writing to the file.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="propertiesStyle">
|
||||||
|
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||||
|
/// of accuracy to read the media properties, or <see
|
||||||
|
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||||
|
/// </param>
|
||||||
|
/// <exception cref="ArgumentNullException">
|
||||||
|
/// <paramref name="abstraction" /> is <see langword="null"
|
||||||
|
/// />.
|
||||||
|
/// </exception>
|
||||||
|
public File (File.IFileAbstraction abstraction,
|
||||||
|
ReadStyle propertiesStyle)
|
||||||
|
: base (abstraction, propertiesStyle)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs and initializes a new instance of <see
|
||||||
|
/// cref="File" /> for a specified file abstraction with
|
||||||
|
/// an average read style.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="abstraction">
|
||||||
|
/// A <see cref="TagLib.File.IFileAbstraction" /> object to use when
|
||||||
|
/// reading from and writing to the file.
|
||||||
|
/// </param>
|
||||||
|
/// <exception cref="ArgumentNullException">
|
||||||
|
/// <paramref name="abstraction" /> is <see langword="null"
|
||||||
|
/// />.
|
||||||
|
/// </exception>
|
||||||
|
public File (File.IFileAbstraction abstraction)
|
||||||
|
: base (abstraction)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region Public Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a tag of a specified type from the current instance,
|
||||||
|
/// optionally creating a new tag if possible.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type">
|
||||||
|
/// A <see cref="TagLib.TagTypes" /> value indicating the
|
||||||
|
/// type of tag to read.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="create">
|
||||||
|
/// A <see cref="bool" /> value specifying whether or not to
|
||||||
|
/// try and create the tag if one is not found.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
/// A <see cref="Tag" /> object containing the tag that was
|
||||||
|
/// found in or added to the current instance. If no
|
||||||
|
/// matching tag was found and none was created, <see
|
||||||
|
/// langword="null" /> is returned.
|
||||||
|
/// </returns>
|
||||||
|
/// <remarks>
|
||||||
|
/// If a <see cref="TagLib.Id3v2.Tag" /> is added to the
|
||||||
|
/// current instance, it will be placed at the start of the
|
||||||
|
/// file. On the other hand, <see cref="TagLib.Id3v1.Tag" />
|
||||||
|
/// <see cref="TagLib.Ape.Tag" /> will be added to the end of
|
||||||
|
/// the file. All other tag types will be ignored.
|
||||||
|
/// </remarks>
|
||||||
|
public override TagLib.Tag GetTag (TagTypes type, bool create)
|
||||||
|
{
|
||||||
|
Tag t = (Tag as TagLib.NonContainer.Tag).GetTag (type);
|
||||||
|
|
||||||
|
if (t != null || !create)
|
||||||
|
return t;
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case TagTypes.Id3v1:
|
||||||
|
return EndTag.AddTag (type, Tag);
|
||||||
|
|
||||||
|
case TagTypes.Id3v2:
|
||||||
|
return StartTag.AddTag (type, Tag);
|
||||||
|
|
||||||
|
case TagTypes.Ape:
|
||||||
|
return EndTag.AddTag (type, Tag);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region Protected Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads format specific information at the start of the
|
||||||
|
/// file.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="start">
|
||||||
|
/// A <see cref="long" /> value containing the seek position
|
||||||
|
/// at which the tags end and the media data begins.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="propertiesStyle">
|
||||||
|
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||||
|
/// of accuracy to read the media properties, or <see
|
||||||
|
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||||
|
/// </param>
|
||||||
|
/// <remarks>
|
||||||
|
/// This method only searches for an audio header in the
|
||||||
|
/// first 16384 bytes of code to avoid searching forever in
|
||||||
|
/// corrupt files.
|
||||||
|
/// </remarks>
|
||||||
|
protected override void ReadStart (long start,
|
||||||
|
ReadStyle propertiesStyle)
|
||||||
|
{
|
||||||
|
// Only check the first 16 bytes so we're not stuck
|
||||||
|
// reading a bad file forever.
|
||||||
|
if (propertiesStyle != ReadStyle.None &&
|
||||||
|
!AudioHeader.Find (out first_header, this,
|
||||||
|
start, 0x4000))
|
||||||
|
throw new CorruptFileException (
|
||||||
|
"ADTS audio header not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads format specific information at the end of the
|
||||||
|
/// file.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="end">
|
||||||
|
/// A <see cref="long" /> value containing the seek position
|
||||||
|
/// at which the media data ends and the tags begin.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="propertiesStyle">
|
||||||
|
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||||
|
/// of accuracy to read the media properties, or <see
|
||||||
|
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||||
|
/// </param>
|
||||||
|
protected override void ReadEnd (long end,
|
||||||
|
ReadStyle propertiesStyle)
|
||||||
|
{
|
||||||
|
// Make sure we have ID3v1 and ID3v2 tags.
|
||||||
|
GetTag (TagTypes.Id3v1, true);
|
||||||
|
GetTag (TagTypes.Id3v2, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads the audio properties from the file represented by
|
||||||
|
/// the current instance.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="start">
|
||||||
|
/// A <see cref="long" /> value containing the seek position
|
||||||
|
/// at which the tags end and the media data begins.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="end">
|
||||||
|
/// A <see cref="long" /> value containing the seek position
|
||||||
|
/// at which the media data ends and the tags begin.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="propertiesStyle">
|
||||||
|
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||||
|
/// of accuracy to read the media properties, or <see
|
||||||
|
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
/// A <see cref="TagLib.Properties" /> object describing the
|
||||||
|
/// media properties of the file represented by the current
|
||||||
|
/// instance.
|
||||||
|
/// </returns>
|
||||||
|
protected override Properties ReadProperties (long start,
|
||||||
|
long end,
|
||||||
|
ReadStyle propertiesStyle)
|
||||||
|
{
|
||||||
|
first_header.SetStreamLength (end - start);
|
||||||
|
return new Properties (TimeSpan.Zero, first_header);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
481
taglib-sharp/src/TagLib/Aiff/File.cs
Normal file
481
taglib-sharp/src/TagLib/Aiff/File.cs
Normal file
@@ -0,0 +1,481 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
324
taglib-sharp/src/TagLib/Aiff/StreamHeader.cs
Normal file
324
taglib-sharp/src/TagLib/Aiff/StreamHeader.cs
Normal file
@@ -0,0 +1,324 @@
|
|||||||
|
//
|
||||||
|
// 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 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
|
||||||
|
}
|
||||||
|
}
|
||||||
280
taglib-sharp/src/TagLib/Ape/File.cs
Normal file
280
taglib-sharp/src/TagLib/Ape/File.cs
Normal file
@@ -0,0 +1,280 @@
|
|||||||
|
//
|
||||||
|
// File.cs: Provides tagging and properties support for Monkey's Audio APE
|
||||||
|
// files.
|
||||||
|
//
|
||||||
|
// Author:
|
||||||
|
// Helmut Wahrmann
|
||||||
|
//
|
||||||
|
// Copyright (C) 2007 Helmut Wahrmann
|
||||||
|
// Copyright (C) 2007 Brian Nickel
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Lesser General Public License version
|
||||||
|
// 2.1 as published by the Free Software Foundation.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful, but
|
||||||
|
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
|
// USA
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace TagLib.Ape {
|
||||||
|
/// <summary>
|
||||||
|
/// This class extends <see cref="TagLib.NonContainer.File" /> to
|
||||||
|
/// provide tagging and properties support for Monkey's Audio APE
|
||||||
|
/// files.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// A <see cref="TagLib.Ape.Tag" /> will be added automatically to
|
||||||
|
/// any file that doesn't contain one. This change does not effect
|
||||||
|
/// the physical file until <see cref="Save" /> is called and can be
|
||||||
|
/// reversed using the following method:
|
||||||
|
/// <code>file.RemoveTags (file.TagTypes & ~file.TagTypesOnDisk);</code>
|
||||||
|
/// </remarks>
|
||||||
|
[SupportedMimeType("taglib/ape", "ape")]
|
||||||
|
[SupportedMimeType("audio/x-ape")]
|
||||||
|
[SupportedMimeType("audio/ape")]
|
||||||
|
[SupportedMimeType("application/x-ape")]
|
||||||
|
public class File : TagLib.NonContainer.File
|
||||||
|
{
|
||||||
|
#region Private Fields
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Contains the block with the audio header.
|
||||||
|
/// </summary>
|
||||||
|
private ByteVector header_block = null;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs and initializes a new instance of <see
|
||||||
|
/// cref="File" /> for a specified path in the local file
|
||||||
|
/// system and specified read style.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">
|
||||||
|
/// A <see cref="string" /> object containing the path of the
|
||||||
|
/// file to use in the new instance.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="propertiesStyle">
|
||||||
|
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||||
|
/// of accuracy to read the media properties, or <see
|
||||||
|
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||||
|
/// </param>
|
||||||
|
/// <exception cref="ArgumentNullException">
|
||||||
|
/// <paramref name="path" /> is <see langword="null" />.
|
||||||
|
/// </exception>
|
||||||
|
public File (string path, ReadStyle propertiesStyle)
|
||||||
|
: base (path, propertiesStyle)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs and initializes a new instance of <see
|
||||||
|
/// cref="File" /> for a specified path in the local file
|
||||||
|
/// system with an average read style.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">
|
||||||
|
/// A <see cref="string" /> object containing the path of the
|
||||||
|
/// file to use in the new instance.
|
||||||
|
/// </param>
|
||||||
|
/// <exception cref="ArgumentNullException">
|
||||||
|
/// <paramref name="path" /> is <see langword="null" />.
|
||||||
|
/// </exception>
|
||||||
|
public File (string path)
|
||||||
|
: base (path)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs and initializes a new instance of <see
|
||||||
|
/// cref="File" /> for a specified file abstraction and
|
||||||
|
/// specified read style.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="abstraction">
|
||||||
|
/// A <see cref="IFileAbstraction" /> object to use when
|
||||||
|
/// reading from and writing to the file.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="propertiesStyle">
|
||||||
|
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||||
|
/// of accuracy to read the media properties, or <see
|
||||||
|
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||||
|
/// </param>
|
||||||
|
/// <exception cref="ArgumentNullException">
|
||||||
|
/// <paramref name="abstraction" /> is <see langword="null"
|
||||||
|
/// />.
|
||||||
|
/// </exception>
|
||||||
|
public File (File.IFileAbstraction abstraction,
|
||||||
|
ReadStyle propertiesStyle)
|
||||||
|
: base (abstraction, propertiesStyle)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs and initializes a new instance of <see
|
||||||
|
/// cref="File" /> for a specified file abstraction with an
|
||||||
|
/// average read style.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="abstraction">
|
||||||
|
/// A <see cref="IFileAbstraction" /> object to use when
|
||||||
|
/// reading from and writing to the file.
|
||||||
|
/// </param>
|
||||||
|
/// <exception cref="ArgumentNullException">
|
||||||
|
/// <paramref name="abstraction" /> is <see langword="null"
|
||||||
|
/// />.
|
||||||
|
/// </exception>
|
||||||
|
public File (File.IFileAbstraction abstraction)
|
||||||
|
: base (abstraction)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region Public Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a tag of a specified type from the current instance,
|
||||||
|
/// optionally creating a new tag if possible.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type">
|
||||||
|
/// A <see cref="TagLib.TagTypes" /> value indicating the
|
||||||
|
/// type of tag to read.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="create">
|
||||||
|
/// A <see cref="bool" /> value specifying whether or not to
|
||||||
|
/// try and create the tag if one is not found.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
/// A <see cref="Tag" /> object containing the tag that was
|
||||||
|
/// found in or added to the current instance. If no
|
||||||
|
/// matching tag was found and none was created, <see
|
||||||
|
/// langword="null" /> is returned.
|
||||||
|
/// </returns>
|
||||||
|
/// <remarks>
|
||||||
|
/// If a <see cref="TagLib.Id3v2.Tag" /> is added to the
|
||||||
|
/// current instance, it will be placed at the start of the
|
||||||
|
/// file. On the other hand, <see cref="TagLib.Id3v1.Tag" />
|
||||||
|
/// <see cref="TagLib.Ape.Tag" /> will be added to the end of
|
||||||
|
/// the file. All other tag types will be ignored.
|
||||||
|
/// </remarks>
|
||||||
|
public override TagLib.Tag GetTag(TagTypes type, bool create)
|
||||||
|
{
|
||||||
|
TagLib.Tag t = (Tag as TagLib.NonContainer.Tag)
|
||||||
|
.GetTag (type);
|
||||||
|
|
||||||
|
if (t != null || !create)
|
||||||
|
return t;
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case TagTypes.Id3v1:
|
||||||
|
return EndTag.AddTag (type, Tag);
|
||||||
|
|
||||||
|
case TagTypes.Id3v2:
|
||||||
|
return StartTag.AddTag (type, Tag);
|
||||||
|
|
||||||
|
case TagTypes.Ape:
|
||||||
|
return EndTag.AddTag (type, Tag);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region Protected Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads format specific information at the start of the
|
||||||
|
/// file.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="start">
|
||||||
|
/// A <see cref="long" /> value containing the seek position
|
||||||
|
/// at which the tags end and the media data begins.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="propertiesStyle">
|
||||||
|
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||||
|
/// of accuracy to read the media properties, or <see
|
||||||
|
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||||
|
/// </param>
|
||||||
|
protected override void ReadStart (long start,
|
||||||
|
ReadStyle propertiesStyle)
|
||||||
|
{
|
||||||
|
if (header_block != null &&
|
||||||
|
propertiesStyle == ReadStyle.None)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Seek(start);
|
||||||
|
header_block = ReadBlock ((int)StreamHeader.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads format specific information at the end of the
|
||||||
|
/// file.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="end">
|
||||||
|
/// A <see cref="long" /> value containing the seek position
|
||||||
|
/// at which the media data ends and the tags begin.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="propertiesStyle">
|
||||||
|
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||||
|
/// of accuracy to read the media properties, or <see
|
||||||
|
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||||
|
/// </param>
|
||||||
|
protected override void ReadEnd (long end,
|
||||||
|
ReadStyle propertiesStyle)
|
||||||
|
{
|
||||||
|
// Make sure we have an APE tag.
|
||||||
|
GetTag (TagTypes.Ape, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads the audio properties from the file represented by
|
||||||
|
/// the current instance.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="start">
|
||||||
|
/// A <see cref="long" /> value containing the seek position
|
||||||
|
/// at which the tags end and the media data begins.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="end">
|
||||||
|
/// A <see cref="long" /> value containing the seek position
|
||||||
|
/// at which the media data ends and the tags begin.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="propertiesStyle">
|
||||||
|
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||||
|
/// of accuracy to read the media properties, or <see
|
||||||
|
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
/// A <see cref="TagLib.Properties" /> object describing the
|
||||||
|
/// media properties of the file represented by the current
|
||||||
|
/// instance.
|
||||||
|
/// </returns>
|
||||||
|
protected override Properties ReadProperties (long start,
|
||||||
|
long end,
|
||||||
|
ReadStyle propertiesStyle)
|
||||||
|
{
|
||||||
|
StreamHeader header = new StreamHeader (header_block,
|
||||||
|
end - start);
|
||||||
|
|
||||||
|
return new Properties(TimeSpan.Zero, header);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
418
taglib-sharp/src/TagLib/Ape/Footer.cs
Normal file
418
taglib-sharp/src/TagLib/Ape/Footer.cs
Normal file
@@ -0,0 +1,418 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
532
taglib-sharp/src/TagLib/Ape/Item.cs
Normal file
532
taglib-sharp/src/TagLib/Ape/Item.cs
Normal file
@@ -0,0 +1,532 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
372
taglib-sharp/src/TagLib/Ape/StreamHeader.cs
Normal file
372
taglib-sharp/src/TagLib/Ape/StreamHeader.cs
Normal file
@@ -0,0 +1,372 @@
|
|||||||
|
//
|
||||||
|
// 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 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
|
||||||
|
}
|
||||||
1563
taglib-sharp/src/TagLib/Ape/Tag.cs
Normal file
1563
taglib-sharp/src/TagLib/Ape/Tag.cs
Normal file
File diff suppressed because it is too large
Load Diff
270
taglib-sharp/src/TagLib/Asf/ContentDescriptionObject.cs
Normal file
270
taglib-sharp/src/TagLib/Asf/ContentDescriptionObject.cs
Normal file
@@ -0,0 +1,270 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
494
taglib-sharp/src/TagLib/Asf/ContentDescriptor.cs
Normal file
494
taglib-sharp/src/TagLib/Asf/ContentDescriptor.cs
Normal file
@@ -0,0 +1,494 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
617
taglib-sharp/src/TagLib/Asf/DescriptionRecord.cs
Normal file
617
taglib-sharp/src/TagLib/Asf/DescriptionRecord.cs
Normal file
@@ -0,0 +1,617 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
276
taglib-sharp/src/TagLib/Asf/ExtendedContentDescriptionObject.cs
Normal file
276
taglib-sharp/src/TagLib/Asf/ExtendedContentDescriptionObject.cs
Normal file
@@ -0,0 +1,276 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
431
taglib-sharp/src/TagLib/Asf/File.cs
Normal file
431
taglib-sharp/src/TagLib/Asf/File.cs
Normal file
@@ -0,0 +1,431 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
319
taglib-sharp/src/TagLib/Asf/FilePropertiesObject.cs
Normal file
319
taglib-sharp/src/TagLib/Asf/FilePropertiesObject.cs
Normal file
@@ -0,0 +1,319 @@
|
|||||||
|
//
|
||||||
|
// 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;}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <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
|
||||||
|
}
|
||||||
|
}
|
||||||
111
taglib-sharp/src/TagLib/Asf/Guid.cs
Normal file
111
taglib-sharp/src/TagLib/Asf/Guid.cs
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
//
|
||||||
|
// 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");
|
||||||
|
}
|
||||||
|
}
|
||||||
176
taglib-sharp/src/TagLib/Asf/HeaderExtensionObject.cs
Normal file
176
taglib-sharp/src/TagLib/Asf/HeaderExtensionObject.cs
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
275
taglib-sharp/src/TagLib/Asf/HeaderObject.cs
Normal file
275
taglib-sharp/src/TagLib/Asf/HeaderObject.cs
Normal file
@@ -0,0 +1,275 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
298
taglib-sharp/src/TagLib/Asf/MetadataLibraryObject.cs
Normal file
298
taglib-sharp/src/TagLib/Asf/MetadataLibraryObject.cs
Normal file
@@ -0,0 +1,298 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
253
taglib-sharp/src/TagLib/Asf/Object.cs
Normal file
253
taglib-sharp/src/TagLib/Asf/Object.cs
Normal file
@@ -0,0 +1,253 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
139
taglib-sharp/src/TagLib/Asf/PaddingObject.cs
Normal file
139
taglib-sharp/src/TagLib/Asf/PaddingObject.cs
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
270
taglib-sharp/src/TagLib/Asf/StreamPropertiesObject.cs
Normal file
270
taglib-sharp/src/TagLib/Asf/StreamPropertiesObject.cs
Normal file
@@ -0,0 +1,270 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
1416
taglib-sharp/src/TagLib/Asf/Tag.cs
Normal file
1416
taglib-sharp/src/TagLib/Asf/Tag.cs
Normal file
File diff suppressed because it is too large
Load Diff
110
taglib-sharp/src/TagLib/Asf/UnknownObject.cs
Normal file
110
taglib-sharp/src/TagLib/Asf/UnknownObject.cs
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
2704
taglib-sharp/src/TagLib/ByteVector.cs
Normal file
2704
taglib-sharp/src/TagLib/ByteVector.cs
Normal file
File diff suppressed because it is too large
Load Diff
281
taglib-sharp/src/TagLib/ByteVectorList.cs
Normal file
281
taglib-sharp/src/TagLib/ByteVectorList.cs
Normal file
@@ -0,0 +1,281 @@
|
|||||||
|
//
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
1513
taglib-sharp/src/TagLib/CombinedTag.cs
Normal file
1513
taglib-sharp/src/TagLib/CombinedTag.cs
Normal file
File diff suppressed because it is too large
Load Diff
168
taglib-sharp/src/TagLib/CorruptFileException.cs
Normal file
168
taglib-sharp/src/TagLib/CorruptFileException.cs
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
//
|
||||||
|
// CorruptFileException.cs:
|
||||||
|
//
|
||||||
|
// Author:
|
||||||
|
// Aaron Bockover (abockover@novell.com)
|
||||||
|
//
|
||||||
|
// Original Source:
|
||||||
|
// Entagged#
|
||||||
|
//
|
||||||
|
// Copyright (C) 2006 Novell, Inc.
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Lesser General Public License version
|
||||||
|
// 2.1 as published by the Free Software Foundation.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful, but
|
||||||
|
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
|
// USA
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
|
||||||
|
namespace TagLib {
|
||||||
|
/// <summary>
|
||||||
|
/// This class extends <see cref="Exception" /> and is used to
|
||||||
|
/// indicate that a file or tag is corrupt.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This exception will be thrown if invalid data interferes with the
|
||||||
|
/// reading of the file or tag. One common example is in the (legal)
|
||||||
|
/// downloading of media files with BitTorrent, in which case large
|
||||||
|
/// portions of the file will contain zeroed bytes.
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// <para>Catching an exception when creating a <see
|
||||||
|
/// cref="File" />.</para>
|
||||||
|
/// <code lang="C#">
|
||||||
|
/// using System;
|
||||||
|
/// using TagLib;
|
||||||
|
///
|
||||||
|
/// public class ExceptionTest
|
||||||
|
/// {
|
||||||
|
/// public static void Main ()
|
||||||
|
/// {
|
||||||
|
/// try {
|
||||||
|
/// File file = File.Create ("partial.mp3"); // Partial download.
|
||||||
|
/// } catch (CorruptFileException e) {
|
||||||
|
/// Console.WriteLine ("That file is corrupt: {0}", e.ToString ());
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// </code>
|
||||||
|
/// <code lang="C++">
|
||||||
|
/// #using <System.dll>
|
||||||
|
/// #using <taglib-sharp.dll>
|
||||||
|
///
|
||||||
|
/// using System;
|
||||||
|
/// using TagLib;
|
||||||
|
///
|
||||||
|
/// void main ()
|
||||||
|
/// {
|
||||||
|
/// try {
|
||||||
|
/// File file = File::Create ("partial.mp3"); // Partial download.
|
||||||
|
/// } catch (CorruptFileException^ e) {
|
||||||
|
/// Console::WriteLine ("That file is corrupt: {0}", e);
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// </code>
|
||||||
|
/// <code lang="VB">
|
||||||
|
/// Imports System
|
||||||
|
/// Imports TagLib
|
||||||
|
///
|
||||||
|
/// Public Class ExceptionTest
|
||||||
|
/// Public Shared Sub Main ()
|
||||||
|
/// Try
|
||||||
|
/// file As File = File.Create ("partial.mp3") ' Partial download.
|
||||||
|
/// Catch e As CorruptFileException
|
||||||
|
/// Console.WriteLine ("That file is corrupt: {0}", e.ToString ());
|
||||||
|
/// End Try
|
||||||
|
/// End Sub
|
||||||
|
/// End Class
|
||||||
|
/// </code>
|
||||||
|
/// <code lang="Boo">
|
||||||
|
/// import System
|
||||||
|
/// import TagLib
|
||||||
|
///
|
||||||
|
/// try:
|
||||||
|
/// file As File = File.Create ("partial.mp3") # Partial download.
|
||||||
|
/// catch e as CorruptFileException:
|
||||||
|
/// Console.WriteLine ("That file is corrupt: {0}", e.ToString ());
|
||||||
|
/// </code>
|
||||||
|
/// </example>
|
||||||
|
[Serializable]
|
||||||
|
public class CorruptFileException : Exception
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs and initializes a new instance of <see
|
||||||
|
/// cref="CorruptFileException" /> with a specified
|
||||||
|
/// message.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="message">
|
||||||
|
/// A <see cref="string" /> containing a message explaining
|
||||||
|
/// the reason for the exception.
|
||||||
|
/// </param>
|
||||||
|
public CorruptFileException (string message) : base(message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs and initializes a new instance of <see
|
||||||
|
/// cref="CorruptFileException" /> with the default
|
||||||
|
/// values.
|
||||||
|
/// </summary>
|
||||||
|
public CorruptFileException () : base()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs and initializes a new instance of <see
|
||||||
|
/// cref="CorruptFileException" /> with a specified
|
||||||
|
/// message containing a specified exception.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="message">
|
||||||
|
/// A <see cref="string" /> containing a message explaining
|
||||||
|
/// the reason for the exception.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="innerException">
|
||||||
|
/// A <see cref="Exception" /> object to be contained in the
|
||||||
|
/// new exception. For example, previously caught exception.
|
||||||
|
/// </param>
|
||||||
|
public CorruptFileException (string message,
|
||||||
|
Exception innerException)
|
||||||
|
: base (message, innerException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs and initializes a new instance of <see
|
||||||
|
/// cref="CorruptFileException" /> from a specified
|
||||||
|
/// serialization info and streaming context.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="info">
|
||||||
|
/// A <see cref="SerializationInfo" /> object containing the
|
||||||
|
/// serialized data to be used for the new instance.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="context">
|
||||||
|
/// A <see cref="StreamingContext" /> object containing the
|
||||||
|
/// streaming context information for the new instance.
|
||||||
|
/// </param>
|
||||||
|
/// <remarks>
|
||||||
|
/// This constructor is implemented because <see
|
||||||
|
/// cref="CorruptFileException" /> implements the <see
|
||||||
|
/// cref="ISerializable" /> interface.
|
||||||
|
/// </remarks>
|
||||||
|
protected CorruptFileException (SerializationInfo info,
|
||||||
|
StreamingContext context)
|
||||||
|
: base(info, context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
144
taglib-sharp/src/TagLib/Debugger.cs
Normal file
144
taglib-sharp/src/TagLib/Debugger.cs
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
//
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1835
taglib-sharp/src/TagLib/File.cs
Normal file
1835
taglib-sharp/src/TagLib/File.cs
Normal file
File diff suppressed because it is too large
Load Diff
148
taglib-sharp/src/TagLib/FileTypes.cs
Normal file
148
taglib-sharp/src/TagLib/FileTypes.cs
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
//
|
||||||
|
// 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;}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
200
taglib-sharp/src/TagLib/Flac/Block.cs
Normal file
200
taglib-sharp/src/TagLib/Flac/Block.cs
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
197
taglib-sharp/src/TagLib/Flac/BlockHeader.cs
Normal file
197
taglib-sharp/src/TagLib/Flac/BlockHeader.cs
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
//
|
||||||
|
// 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;}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
682
taglib-sharp/src/TagLib/Flac/File.cs
Normal file
682
taglib-sharp/src/TagLib/Flac/File.cs
Normal file
@@ -0,0 +1,682 @@
|
|||||||
|
//
|
||||||
|
// File.cs: Provides tagging and properties support for Xiph's Flac audio files.
|
||||||
|
//
|
||||||
|
// Author:
|
||||||
|
// Brian Nickel (brian.nickel@gmail.com)
|
||||||
|
//
|
||||||
|
// Original Source:
|
||||||
|
// flacfile.cpp from TagLib
|
||||||
|
//
|
||||||
|
// Copyright (C) 2006-2007 Brian Nickel
|
||||||
|
// Copyright (C) 2003-2004 Allan Sandfeld Jensen (Original Implementation)
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Lesser General Public License version
|
||||||
|
// 2.1 as published by the Free Software Foundation.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful, but
|
||||||
|
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
|
// USA
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace TagLib.Flac {
|
||||||
|
/// <summary>
|
||||||
|
/// This class extends <see cref="TagLib.NonContainer.File" /> to
|
||||||
|
/// provide tagging and properties support for Xiph's Flac audio
|
||||||
|
/// files.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// A <see cref="TagLib.Ogg.XiphComment" /> will be added
|
||||||
|
/// automatically to any file that doesn't contain one. This change
|
||||||
|
/// does not effect the physical file until <see cref="Save" /> is
|
||||||
|
/// called and can be reversed using the following method:
|
||||||
|
/// <code>file.RemoveTags (file.TagTypes & ~file.TagTypesOnDisk);</code>
|
||||||
|
/// </remarks>
|
||||||
|
[SupportedMimeType("taglib/flac", "flac")]
|
||||||
|
[SupportedMimeType("audio/x-flac")]
|
||||||
|
[SupportedMimeType("application/x-flac")]
|
||||||
|
[SupportedMimeType("audio/flac")]
|
||||||
|
public class File : TagLib.NonContainer.File
|
||||||
|
{
|
||||||
|
#region Private Fields
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Contains the Flac metadata tag.
|
||||||
|
/// </summary>
|
||||||
|
private Metadata metadata = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Contains the combination of all file tags.
|
||||||
|
/// </summary>
|
||||||
|
private CombinedTag tag = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Contains the Flac header block.
|
||||||
|
/// </summary>
|
||||||
|
private ByteVector header_block = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Contains the stream start position.
|
||||||
|
/// </summary>
|
||||||
|
private long stream_start = 0;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs and initializes a new instance of <see
|
||||||
|
/// cref="File" /> for a specified path in the local file
|
||||||
|
/// system and specified read style.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">
|
||||||
|
/// A <see cref="string" /> object containing the path of the
|
||||||
|
/// file to use in the new instance.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="propertiesStyle">
|
||||||
|
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||||
|
/// of accuracy to read the media properties, or <see
|
||||||
|
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||||
|
/// </param>
|
||||||
|
/// <exception cref="ArgumentNullException">
|
||||||
|
/// <paramref name="path" /> is <see langword="null" />.
|
||||||
|
/// </exception>
|
||||||
|
public File (string path, ReadStyle propertiesStyle)
|
||||||
|
: base (path, propertiesStyle)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs and initializes a new instance of <see
|
||||||
|
/// cref="File" /> for a specified path in the local file
|
||||||
|
/// system with an average read style.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">
|
||||||
|
/// A <see cref="string" /> object containing the path of the
|
||||||
|
/// file to use in the new instance.
|
||||||
|
/// </param>
|
||||||
|
/// <exception cref="ArgumentNullException">
|
||||||
|
/// <paramref name="path" /> is <see langword="null" />.
|
||||||
|
/// </exception>
|
||||||
|
public File (string path)
|
||||||
|
: base (path)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs and initializes a new instance of <see
|
||||||
|
/// cref="File" /> for a specified file abstraction and
|
||||||
|
/// specified read style.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="abstraction">
|
||||||
|
/// A <see cref="IFileAbstraction" /> object to use when
|
||||||
|
/// reading from and writing to the file.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="propertiesStyle">
|
||||||
|
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||||
|
/// of accuracy to read the media properties, or <see
|
||||||
|
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||||
|
/// </param>
|
||||||
|
/// <exception cref="ArgumentNullException">
|
||||||
|
/// <paramref name="abstraction" /> is <see langword="null"
|
||||||
|
/// />.
|
||||||
|
/// </exception>
|
||||||
|
public File (File.IFileAbstraction abstraction,
|
||||||
|
ReadStyle propertiesStyle)
|
||||||
|
: base (abstraction, propertiesStyle)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs and initializes a new instance of <see
|
||||||
|
/// cref="File" /> for a specified file abstraction with an
|
||||||
|
/// average read style.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="abstraction">
|
||||||
|
/// A <see cref="IFileAbstraction" /> object to use when
|
||||||
|
/// reading from and writing to the file.
|
||||||
|
/// </param>
|
||||||
|
/// <exception cref="ArgumentNullException">
|
||||||
|
/// <paramref name="abstraction" /> is <see langword="null"
|
||||||
|
/// />.
|
||||||
|
/// </exception>
|
||||||
|
public File (File.IFileAbstraction abstraction)
|
||||||
|
: base (abstraction)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region Public Properties
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a abstract representation of all tags stored in the
|
||||||
|
/// current instance.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>
|
||||||
|
/// A <see cref="TagLib.Tag" /> object representing all tags
|
||||||
|
/// stored in the current instance.
|
||||||
|
/// </value>
|
||||||
|
public override TagLib.Tag Tag {
|
||||||
|
get {return tag;}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region Public Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Saves the changes made in the current instance to the
|
||||||
|
/// file it represents.
|
||||||
|
/// </summary>
|
||||||
|
public override void Save ()
|
||||||
|
{
|
||||||
|
Mode = AccessMode.Write;
|
||||||
|
try {
|
||||||
|
// Update the tags at the beginning of the file.
|
||||||
|
long metadata_start = StartTag.Write ();
|
||||||
|
long metadata_end;
|
||||||
|
|
||||||
|
// Get all the blocks, but don't read the data for ones
|
||||||
|
// we're filling with stored data.
|
||||||
|
IList<Block> old_blocks = ReadBlocks (ref metadata_start,
|
||||||
|
out metadata_end, BlockMode.Blacklist,
|
||||||
|
BlockType.XiphComment, BlockType.Picture);
|
||||||
|
|
||||||
|
// Create new vorbis comments is they don't exist.
|
||||||
|
GetTag (TagTypes.Xiph, true);
|
||||||
|
|
||||||
|
// Create new blocks and add the basics.
|
||||||
|
List<Block> new_blocks = new List<Block> ();
|
||||||
|
new_blocks.Add (old_blocks [0]);
|
||||||
|
|
||||||
|
// Add blocks we don't deal with from the file.
|
||||||
|
foreach (Block block in old_blocks)
|
||||||
|
if (block.Type != BlockType.StreamInfo &&
|
||||||
|
block.Type != BlockType.XiphComment &&
|
||||||
|
block.Type != BlockType.Picture &&
|
||||||
|
block.Type != BlockType.Padding)
|
||||||
|
new_blocks.Add (block);
|
||||||
|
|
||||||
|
new_blocks.Add (new Block (BlockType.XiphComment,
|
||||||
|
(GetTag (TagTypes.Xiph, true) as
|
||||||
|
Ogg.XiphComment).Render (false)));
|
||||||
|
|
||||||
|
foreach (IPicture picture in metadata.Pictures) {
|
||||||
|
if (picture == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
new_blocks.Add (new Block (BlockType.Picture,
|
||||||
|
new Picture (picture).Render ()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the length of the blocks.
|
||||||
|
long length = 0;
|
||||||
|
foreach (Block block in new_blocks)
|
||||||
|
length += block.TotalSize;
|
||||||
|
|
||||||
|
// Find the padding size to avoid trouble. If that fails
|
||||||
|
// make some.
|
||||||
|
long padding_size = metadata_end - metadata_start -
|
||||||
|
BlockHeader.Size - length;
|
||||||
|
if (padding_size < 0)
|
||||||
|
padding_size = 1024 * 4;
|
||||||
|
|
||||||
|
// Add a padding block.
|
||||||
|
if (padding_size != 0)
|
||||||
|
new_blocks.Add (new Block (BlockType.Padding,
|
||||||
|
new ByteVector ((int) padding_size)));
|
||||||
|
|
||||||
|
// Render the blocks.
|
||||||
|
ByteVector block_data = new ByteVector ();
|
||||||
|
for (int i = 0; i < new_blocks.Count; i ++)
|
||||||
|
block_data.Add (new_blocks [i].Render (
|
||||||
|
i == new_blocks.Count - 1));
|
||||||
|
|
||||||
|
// Update the blocks.
|
||||||
|
Insert (block_data, metadata_start, metadata_end -
|
||||||
|
metadata_start);
|
||||||
|
|
||||||
|
// Update the tags at the end of the file.
|
||||||
|
EndTag.Write ();
|
||||||
|
|
||||||
|
TagTypesOnDisk = TagTypes;
|
||||||
|
} finally {
|
||||||
|
Mode = AccessMode.Closed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a tag of a specified type from the current instance,
|
||||||
|
/// optionally creating a new tag if possible.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type">
|
||||||
|
/// A <see cref="TagLib.TagTypes" /> value indicating the
|
||||||
|
/// type of tag to read.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="create">
|
||||||
|
/// A <see cref="bool" /> value specifying whether or not to
|
||||||
|
/// try and create the tag if one is not found.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
/// A <see cref="Tag" /> object containing the tag that was
|
||||||
|
/// found in or added to the current instance. If no
|
||||||
|
/// matching tag was found and none was created, <see
|
||||||
|
/// langword="null" /> is returned.
|
||||||
|
/// </returns>
|
||||||
|
public override TagLib.Tag GetTag (TagTypes type, bool create)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case TagTypes.Xiph:
|
||||||
|
return metadata.GetComment (create, tag);
|
||||||
|
|
||||||
|
case TagTypes.FlacMetadata:
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
Tag t = (base.Tag as TagLib.NonContainer.Tag).GetTag (type);
|
||||||
|
|
||||||
|
if (t != null || !create)
|
||||||
|
return t;
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case TagTypes.Id3v1:
|
||||||
|
return EndTag.AddTag (type, Tag);
|
||||||
|
|
||||||
|
case TagTypes.Id3v2:
|
||||||
|
return StartTag.AddTag (type, Tag);
|
||||||
|
|
||||||
|
case TagTypes.Ape:
|
||||||
|
return EndTag.AddTag (type, Tag);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes a set of tag types from the current instance.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="types">
|
||||||
|
/// A bitwise combined <see cref="TagLib.TagTypes" /> value
|
||||||
|
/// containing tag types to be removed from the file.
|
||||||
|
/// </param>
|
||||||
|
/// <remarks>
|
||||||
|
/// In order to remove all tags from a file, pass <see
|
||||||
|
/// cref="TagTypes.AllTags" /> as <paramref name="types" />.
|
||||||
|
/// </remarks>
|
||||||
|
public override void RemoveTags (TagTypes types)
|
||||||
|
{
|
||||||
|
if ((types & TagTypes.Xiph) != 0)
|
||||||
|
metadata.RemoveComment ();
|
||||||
|
|
||||||
|
if ((types & TagTypes.FlacMetadata) != 0)
|
||||||
|
metadata.Clear ();
|
||||||
|
|
||||||
|
base.RemoveTags (types);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region Protected Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads format specific information at the start of the
|
||||||
|
/// file.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="start">
|
||||||
|
/// A <see cref="long" /> value containing the seek position
|
||||||
|
/// at which the tags end and the media data begins.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="propertiesStyle">
|
||||||
|
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||||
|
/// of accuracy to read the media properties, or <see
|
||||||
|
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||||
|
/// </param>
|
||||||
|
protected override void ReadStart (long start,
|
||||||
|
ReadStyle propertiesStyle)
|
||||||
|
{
|
||||||
|
long end;
|
||||||
|
IList<Block> blocks = ReadBlocks (ref start, out end,
|
||||||
|
BlockMode.Whitelist, BlockType.StreamInfo,
|
||||||
|
BlockType.XiphComment, BlockType.Picture);
|
||||||
|
metadata = new Metadata (blocks);
|
||||||
|
|
||||||
|
TagTypesOnDisk |= metadata.TagTypes;
|
||||||
|
|
||||||
|
if (propertiesStyle != ReadStyle.None) {
|
||||||
|
// Check that the first block is a
|
||||||
|
// METADATA_BLOCK_STREAMINFO.
|
||||||
|
if (blocks.Count == 0 ||
|
||||||
|
blocks [0].Type != BlockType.StreamInfo)
|
||||||
|
throw new CorruptFileException (
|
||||||
|
"FLAC stream does not begin with StreamInfo.");
|
||||||
|
|
||||||
|
// The stream exists from the end of the last
|
||||||
|
// block to the end of the file.
|
||||||
|
stream_start = end;
|
||||||
|
header_block = blocks [0].Data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads format specific information at the end of the
|
||||||
|
/// file.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="end">
|
||||||
|
/// A <see cref="long" /> value containing the seek position
|
||||||
|
/// at which the media data ends and the tags begin.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="propertiesStyle">
|
||||||
|
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||||
|
/// of accuracy to read the media properties, or <see
|
||||||
|
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||||
|
/// </param>
|
||||||
|
protected override void ReadEnd (long end,
|
||||||
|
ReadStyle propertiesStyle)
|
||||||
|
{
|
||||||
|
tag = new CombinedTag (metadata, base.Tag);
|
||||||
|
GetTag (TagTypes.Xiph, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads the audio properties from the file represented by
|
||||||
|
/// the current instance.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="start">
|
||||||
|
/// A <see cref="long" /> value containing the seek position
|
||||||
|
/// at which the tags end and the media data begins.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="end">
|
||||||
|
/// A <see cref="long" /> value containing the seek position
|
||||||
|
/// at which the media data ends and the tags begin.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="propertiesStyle">
|
||||||
|
/// A <see cref="ReadStyle" /> value specifying at what level
|
||||||
|
/// of accuracy to read the media properties, or <see
|
||||||
|
/// cref="ReadStyle.None" /> to ignore the properties.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
/// A <see cref="TagLib.Properties" /> object describing the
|
||||||
|
/// media properties of the file represented by the current
|
||||||
|
/// instance.
|
||||||
|
/// </returns>
|
||||||
|
protected override Properties ReadProperties (long start,
|
||||||
|
long end,
|
||||||
|
ReadStyle propertiesStyle)
|
||||||
|
{
|
||||||
|
StreamHeader header = new StreamHeader (header_block,
|
||||||
|
end - stream_start);
|
||||||
|
return new Properties (TimeSpan.Zero, header);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region Private Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether or not the block types passed into
|
||||||
|
/// <see cref="ReadBlocks" /> are to be white-listed or
|
||||||
|
/// black-listed.
|
||||||
|
/// </summary>
|
||||||
|
private enum BlockMode
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// All block types except those provided are to be
|
||||||
|
/// returned.
|
||||||
|
/// </summary>
|
||||||
|
Blacklist,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Only those block types provides should be
|
||||||
|
/// returned.
|
||||||
|
/// </summary>
|
||||||
|
Whitelist
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads all metadata blocks starting from the current
|
||||||
|
/// instance, starting at a specified position.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="start">
|
||||||
|
/// A <see cref="long" /> value reference specifying the
|
||||||
|
/// position at which to start searching for the blocks. This
|
||||||
|
/// will be updated to the position of the first block.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="end">
|
||||||
|
/// A <see cref="long" /> value reference updated to the
|
||||||
|
/// position at which the last block ends.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="mode">
|
||||||
|
/// A <see cref="BlockMode" /> value indicating whether to
|
||||||
|
/// white-list or black-list the contents of <paramref
|
||||||
|
/// name="types" />.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="types">
|
||||||
|
/// A <see cref="BlockType[]" /> containing the types to look
|
||||||
|
/// for or not look for as specified by <paramref name="mode"
|
||||||
|
/// />.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
/// A <see cref="T:System.Collections.Generic.IList`1" /> object containing the blocks
|
||||||
|
/// read from the current instance.
|
||||||
|
/// </returns>
|
||||||
|
/// <exception cref="CorruptFileException">
|
||||||
|
/// "<c>fLaC</c>" could not be found.
|
||||||
|
/// </exception>
|
||||||
|
private IList<Block> ReadBlocks (ref long start, out long end,
|
||||||
|
BlockMode mode,
|
||||||
|
params BlockType[] types)
|
||||||
|
{
|
||||||
|
List<Block> blocks = new List<Block> ();
|
||||||
|
|
||||||
|
long start_position = Find ("fLaC", start);
|
||||||
|
|
||||||
|
if (start_position < 0)
|
||||||
|
throw new CorruptFileException (
|
||||||
|
"FLAC stream not found at starting position.");
|
||||||
|
|
||||||
|
end = start = start_position + 4;
|
||||||
|
|
||||||
|
Seek (start);
|
||||||
|
|
||||||
|
BlockHeader header;
|
||||||
|
|
||||||
|
do {
|
||||||
|
header = new BlockHeader (ReadBlock ((int)
|
||||||
|
BlockHeader.Size));
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
foreach (BlockType type in types)
|
||||||
|
if (header.BlockType == type) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mode == BlockMode.Whitelist && found) ||
|
||||||
|
(mode == BlockMode.Blacklist && !found))
|
||||||
|
blocks.Add (new Block (header,
|
||||||
|
ReadBlock ((int)
|
||||||
|
header.BlockSize)));
|
||||||
|
else
|
||||||
|
Seek (header.BlockSize,
|
||||||
|
System.IO.SeekOrigin.Current);
|
||||||
|
|
||||||
|
end += header.BlockSize + BlockHeader.Size;
|
||||||
|
} while (!header.IsLastBlock);
|
||||||
|
|
||||||
|
return blocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This class extends <see cref="CombinedTag" /> to provide support
|
||||||
|
/// for reading and writing FLAC metadata boxes.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// At this point, only Xiph Comments and pictures are supported.
|
||||||
|
/// </remarks>
|
||||||
|
public class Metadata : CombinedTag
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Contains the pictures.
|
||||||
|
/// </summary>
|
||||||
|
private List<IPicture> pictures = new List<IPicture>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs and initializes a new instance of <see
|
||||||
|
/// cref="Metadata" /> using a collection of blocks.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="blocks">
|
||||||
|
/// A <see cref="T:System.Collections.Generic.List`1" /> object containing <see
|
||||||
|
/// cref="Block" /> objects to use in the new instance.
|
||||||
|
/// </param>
|
||||||
|
/// <exception cref="ArgumentNullException">
|
||||||
|
/// <paramref name="blocks" /> is <see langword="null" />.
|
||||||
|
/// </exception>
|
||||||
|
[Obsolete("Use Metadata(IEnumerable<Block>)")]
|
||||||
|
public Metadata (List<Block> blocks)
|
||||||
|
: this (blocks as IEnumerable<Block>)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs and initializes a new instance of <see
|
||||||
|
/// cref="Metadata" /> using a collection of blocks.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="blocks">
|
||||||
|
/// A <see cref="T:System.Collections.Generic.IEnumerable`1" /> object enumerating <see
|
||||||
|
/// cref="Block" /> objects to use in the new instance.
|
||||||
|
/// </param>
|
||||||
|
/// <exception cref="ArgumentNullException">
|
||||||
|
/// <paramref name="blocks" /> is <see langword="null" />.
|
||||||
|
/// </exception>
|
||||||
|
public Metadata (IEnumerable<Block> blocks)
|
||||||
|
{
|
||||||
|
if (blocks == null)
|
||||||
|
throw new ArgumentNullException ("blocks");
|
||||||
|
|
||||||
|
foreach (Block block in blocks) {
|
||||||
|
if (block.Data.Count == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (block.Type == BlockType.XiphComment)
|
||||||
|
AddTag (new Ogg.XiphComment (block.Data));
|
||||||
|
else if (block.Type == BlockType.Picture)
|
||||||
|
pictures.Add (new Picture (block.Data));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the first Xiph comment stored in the current
|
||||||
|
/// instance, optionally creating one if necessary.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="create">
|
||||||
|
/// A <see cref="bool" /> value indicating whether or not a
|
||||||
|
/// comment should be added if one cannot be found.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="copy">
|
||||||
|
/// A <see cref="Tag" /> object containing the source tag to
|
||||||
|
/// copy the values from, or <see langword="null" /> to not
|
||||||
|
/// copy values.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
/// A <see cref="Ogg.XiphComment" /> object containing the
|
||||||
|
/// tag that was found in or added to the current instance.
|
||||||
|
/// If no matching tag was found and none was created, <see
|
||||||
|
/// langword="null" /> is returned.
|
||||||
|
/// </returns>
|
||||||
|
public Ogg.XiphComment GetComment (bool create, Tag copy)
|
||||||
|
{
|
||||||
|
foreach (Tag t in Tags)
|
||||||
|
if (t is Ogg.XiphComment)
|
||||||
|
return t as Ogg.XiphComment;
|
||||||
|
|
||||||
|
if (!create)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
Ogg.XiphComment c = new Ogg.XiphComment ();
|
||||||
|
|
||||||
|
if (copy != null)
|
||||||
|
copy.CopyTo (c, true);
|
||||||
|
|
||||||
|
AddTag (c);
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes all child Xiph Comments from the current
|
||||||
|
/// instance.
|
||||||
|
/// </summary>
|
||||||
|
public void RemoveComment ()
|
||||||
|
{
|
||||||
|
Ogg.XiphComment c;
|
||||||
|
|
||||||
|
while ((c = GetComment (false, null)) != null)
|
||||||
|
RemoveTag (c);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the tag types contained in the current instance.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>
|
||||||
|
/// A bitwise combined <see cref="TagLib.TagTypes" /> value
|
||||||
|
/// containing the tag types stored in the current instance.
|
||||||
|
/// </value>
|
||||||
|
public override TagTypes TagTypes {
|
||||||
|
get {return TagTypes.FlacMetadata | base.TagTypes;}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets and sets a collection of pictures associated with
|
||||||
|
/// the media represented by the current instance.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>
|
||||||
|
/// A <see cref="IPicture[]" /> containing a collection of
|
||||||
|
/// pictures associated with the media represented by the
|
||||||
|
/// current instance or an empty array if none are present.
|
||||||
|
/// </value>
|
||||||
|
public override IPicture[] Pictures {
|
||||||
|
get {return pictures.ToArray ();}
|
||||||
|
set {
|
||||||
|
pictures.Clear ();
|
||||||
|
if (value != null)
|
||||||
|
pictures.AddRange (value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clears the values stored in the current instance.
|
||||||
|
/// </summary>
|
||||||
|
public override void Clear ()
|
||||||
|
{
|
||||||
|
pictures.Clear ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
332
taglib-sharp/src/TagLib/Flac/Picture.cs
Normal file
332
taglib-sharp/src/TagLib/Flac/Picture.cs
Normal file
@@ -0,0 +1,332 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
237
taglib-sharp/src/TagLib/Flac/StreamHeader.cs
Normal file
237
taglib-sharp/src/TagLib/Flac/StreamHeader.cs
Normal file
@@ -0,0 +1,237 @@
|
|||||||
|
//
|
||||||
|
// 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 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
|
||||||
|
}
|
||||||
|
}
|
||||||
406
taglib-sharp/src/TagLib/Genres.cs
Normal file
406
taglib-sharp/src/TagLib/Genres.cs
Normal file
@@ -0,0 +1,406 @@
|
|||||||
|
//
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
62
taglib-sharp/src/TagLib/Gif/Codec.cs
Normal file
62
taglib-sharp/src/TagLib/Gif/Codec.cs
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
//
|
||||||
|
// 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) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
781
taglib-sharp/src/TagLib/Gif/File.cs
Normal file
781
taglib-sharp/src/TagLib/Gif/File.cs
Normal file
@@ -0,0 +1,781 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
103
taglib-sharp/src/TagLib/Gif/GifCommentTag.cs
Normal file
103
taglib-sharp/src/TagLib/Gif/GifCommentTag.cs
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
244
taglib-sharp/src/TagLib/ICodec.cs
Normal file
244
taglib-sharp/src/TagLib/ICodec.cs
Normal file
@@ -0,0 +1,244 @@
|
|||||||
|
//
|
||||||
|
// 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 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;}
|
||||||
|
}
|
||||||
|
}
|
||||||
100
taglib-sharp/src/TagLib/IFD/Entries/ByteIFDEntry.cs
Normal file
100
taglib-sharp/src/TagLib/IFD/Entries/ByteIFDEntry.cs
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
100
taglib-sharp/src/TagLib/IFD/Entries/ByteVectorIFDEntry.cs
Normal file
100
taglib-sharp/src/TagLib/IFD/Entries/ByteVectorIFDEntry.cs
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
89
taglib-sharp/src/TagLib/IFD/Entries/LongArrayIFDEntry.cs
Normal file
89
taglib-sharp/src/TagLib/IFD/Entries/LongArrayIFDEntry.cs
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
100
taglib-sharp/src/TagLib/IFD/Entries/LongIFDEntry.cs
Normal file
100
taglib-sharp/src/TagLib/IFD/Entries/LongIFDEntry.cs
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
279
taglib-sharp/src/TagLib/IFD/Entries/MakernoteIFDEntry.cs
Normal file
279
taglib-sharp/src/TagLib/IFD/Entries/MakernoteIFDEntry.cs
Normal file
@@ -0,0 +1,279 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
174
taglib-sharp/src/TagLib/IFD/Entries/Rational.cs
Normal file
174
taglib-sharp/src/TagLib/IFD/Entries/Rational.cs
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
92
taglib-sharp/src/TagLib/IFD/Entries/RationalArrayIFDEntry.cs
Normal file
92
taglib-sharp/src/TagLib/IFD/Entries/RationalArrayIFDEntry.cs
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
104
taglib-sharp/src/TagLib/IFD/Entries/RationalIFDEntry.cs
Normal file
104
taglib-sharp/src/TagLib/IFD/Entries/RationalIFDEntry.cs
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
100
taglib-sharp/src/TagLib/IFD/Entries/SByteIFDEntry.cs
Normal file
100
taglib-sharp/src/TagLib/IFD/Entries/SByteIFDEntry.cs
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
89
taglib-sharp/src/TagLib/IFD/Entries/SLongArrayIFDEntry.cs
Normal file
89
taglib-sharp/src/TagLib/IFD/Entries/SLongArrayIFDEntry.cs
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
//
|
||||||
|
// SLongArrayIFDEntry.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 SLONG value with a count > 1
|
||||||
|
/// </summary>
|
||||||
|
public class SLongArrayIFDEntry : ArrayIFDEntry<int>
|
||||||
|
{
|
||||||
|
|
||||||
|
#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.Int32[]"/> to be stored
|
||||||
|
/// </param>
|
||||||
|
public SLongArrayIFDEntry (ushort tag, int [] 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 (int value in Values)
|
||||||
|
data.Add (ByteVector.FromInt (value, is_bigendian));
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
100
taglib-sharp/src/TagLib/IFD/Entries/SLongIFDEntry.cs
Normal file
100
taglib-sharp/src/TagLib/IFD/Entries/SLongIFDEntry.cs
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
//
|
||||||
|
// SLongIFDEntry.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 LONG value.
|
||||||
|
/// </summary>
|
||||||
|
public class SLongIFDEntry : 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 int 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.Int32"/> to be stored
|
||||||
|
/// </param>
|
||||||
|
public SLongIFDEntry (ushort tag, int 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.SLong;
|
||||||
|
count = 1;
|
||||||
|
|
||||||
|
return ByteVector.FromInt (Value, is_bigendian);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
175
taglib-sharp/src/TagLib/IFD/Entries/SRational.cs
Normal file
175
taglib-sharp/src/TagLib/IFD/Entries/SRational.cs
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
//
|
||||||
|
// SRational.cs: A structure to represent signed 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 a signed rational value
|
||||||
|
/// </summary>
|
||||||
|
public struct SRational : IFormattable
|
||||||
|
{
|
||||||
|
#region Private Fields
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The numerator of the rational value
|
||||||
|
/// </summary>
|
||||||
|
private int numerator;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The denominator of the rational value
|
||||||
|
/// </summary>
|
||||||
|
private int denominator;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructor
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new Rational value
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="numerator">
|
||||||
|
/// A <see cref="System.Int32"/> with the numerator of the
|
||||||
|
/// rational value
|
||||||
|
/// </param>
|
||||||
|
/// <param name="denominator">
|
||||||
|
/// A <see cref="System.Int32"/> with the denominator of the
|
||||||
|
/// rational value. It must be not 0.
|
||||||
|
/// </param>
|
||||||
|
public SRational (int numerator, int 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="SRational"/>
|
||||||
|
/// </returns>
|
||||||
|
public SRational Reduce ()
|
||||||
|
{
|
||||||
|
int den_sign = Math.Sign (Denominator);
|
||||||
|
int gcd = Math.Abs (Denominator);
|
||||||
|
int b = Math.Abs (Numerator);
|
||||||
|
|
||||||
|
while (b != 0) {
|
||||||
|
int tmp = gcd % b;
|
||||||
|
gcd = b;
|
||||||
|
b = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new SRational (den_sign * (Numerator / gcd), Math.Abs (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) {
|
||||||
|
|
||||||
|
SRational 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 int Numerator {
|
||||||
|
get { return numerator; }
|
||||||
|
set { numerator = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <value>
|
||||||
|
/// The denominator of the rational value
|
||||||
|
/// </value>
|
||||||
|
/// <remarks>
|
||||||
|
/// Cannot be 0.
|
||||||
|
/// </remarks>
|
||||||
|
public int 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 (SRational rat)
|
||||||
|
{
|
||||||
|
return (double) rat.Numerator / (double) rat.Denominator;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
//
|
||||||
|
// SRationalArrayIFDEntry.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 SRATIONAL value with a count > 1
|
||||||
|
/// </summary>
|
||||||
|
public class SRationalArrayIFDEntry : ArrayIFDEntry<SRational>
|
||||||
|
{
|
||||||
|
|
||||||
|
#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="SRational[]"/> to be stored
|
||||||
|
/// </param>
|
||||||
|
public SRationalArrayIFDEntry (ushort tag, SRational [] 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.SRational;
|
||||||
|
count = (uint) Values.Length;
|
||||||
|
|
||||||
|
ByteVector data = new ByteVector ();
|
||||||
|
foreach (SRational rational in Values) {
|
||||||
|
data.Add (ByteVector.FromInt (rational.Numerator, is_bigendian));
|
||||||
|
data.Add (ByteVector.FromInt (rational.Denominator, is_bigendian));
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
104
taglib-sharp/src/TagLib/IFD/Entries/SRationalIFDEntry.cs
Normal file
104
taglib-sharp/src/TagLib/IFD/Entries/SRationalIFDEntry.cs
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
//
|
||||||
|
// SRationalIFDEntry.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 SRATIONAL value.
|
||||||
|
/// </summary>
|
||||||
|
public class SRationalIFDEntry : 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 SRational 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="SRational"/> to be stored
|
||||||
|
/// </param>
|
||||||
|
public SRationalIFDEntry (ushort tag, SRational 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.SRational;
|
||||||
|
count = 1;
|
||||||
|
|
||||||
|
ByteVector data = new ByteVector ();
|
||||||
|
data.Add (ByteVector.FromInt (Value.Numerator, is_bigendian));
|
||||||
|
data.Add (ByteVector.FromInt (Value.Denominator, is_bigendian));
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
89
taglib-sharp/src/TagLib/IFD/Entries/SShortArrayIFDEntry.cs
Normal file
89
taglib-sharp/src/TagLib/IFD/Entries/SShortArrayIFDEntry.cs
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
//
|
||||||
|
// SShortArrayIFDEntry.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 SSHORT value with a count > 1
|
||||||
|
/// </summary>
|
||||||
|
public class SShortArrayIFDEntry : ArrayIFDEntry<short>
|
||||||
|
{
|
||||||
|
|
||||||
|
#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.Int16[]"/> to be stored
|
||||||
|
/// </param>
|
||||||
|
public SShortArrayIFDEntry (ushort tag, short [] 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.SShort;
|
||||||
|
count = (uint) Values.Length;
|
||||||
|
|
||||||
|
ByteVector data = new ByteVector ();
|
||||||
|
foreach (ushort value in Values)
|
||||||
|
data.Add (ByteVector.FromUShort ((ushort) value, is_bigendian));
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
100
taglib-sharp/src/TagLib/IFD/Entries/SShortIFDEntry.cs
Normal file
100
taglib-sharp/src/TagLib/IFD/Entries/SShortIFDEntry.cs
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
//
|
||||||
|
// SShortIFDEntry.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 SHORT value.
|
||||||
|
/// </summary>
|
||||||
|
public class SShortIFDEntry : 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 short 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.Int16"/> to be stored
|
||||||
|
/// </param>
|
||||||
|
public SShortIFDEntry (ushort tag, short 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.SShort;
|
||||||
|
count = 1;
|
||||||
|
|
||||||
|
return ByteVector.FromUShort ((ushort) Value, is_bigendian);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
89
taglib-sharp/src/TagLib/IFD/Entries/ShortArrayIFDEntry.cs
Normal file
89
taglib-sharp/src/TagLib/IFD/Entries/ShortArrayIFDEntry.cs
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
//
|
||||||
|
// ShortArrayIFDEntry.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 SHORT value with a count > 1
|
||||||
|
/// </summary>
|
||||||
|
public class ShortArrayIFDEntry : ArrayIFDEntry<ushort>
|
||||||
|
{
|
||||||
|
|
||||||
|
#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.UInt16[]"/> to be stored
|
||||||
|
/// </param>
|
||||||
|
public ShortArrayIFDEntry (ushort tag, ushort [] 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.Short;
|
||||||
|
count = (uint) Values.Length;
|
||||||
|
|
||||||
|
ByteVector data = new ByteVector ();
|
||||||
|
foreach (ushort value in Values)
|
||||||
|
data.Add (ByteVector.FromUShort (value, is_bigendian));
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
100
taglib-sharp/src/TagLib/IFD/Entries/ShortIFDEntry.cs
Normal file
100
taglib-sharp/src/TagLib/IFD/Entries/ShortIFDEntry.cs
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
//
|
||||||
|
// ShortIFDEntry.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 SHORT value.
|
||||||
|
/// </summary>
|
||||||
|
public class ShortIFDEntry : 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 ushort 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.UInt16"/> to be stored
|
||||||
|
/// </param>
|
||||||
|
public ShortIFDEntry (ushort tag, ushort 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.Short;
|
||||||
|
count = 1;
|
||||||
|
|
||||||
|
return ByteVector.FromUShort (Value, is_bigendian);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
104
taglib-sharp/src/TagLib/IFD/Entries/StringIFDEntry.cs
Normal file
104
taglib-sharp/src/TagLib/IFD/Entries/StringIFDEntry.cs
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
//
|
||||||
|
// StringIFDEntry.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 ASCII STRING value.
|
||||||
|
/// </summary>
|
||||||
|
public class StringIFDEntry : 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 string 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.String"/> to be stored
|
||||||
|
/// </param>
|
||||||
|
public StringIFDEntry (ushort tag, string 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.Ascii;
|
||||||
|
|
||||||
|
ByteVector data = Value;
|
||||||
|
data.Add ("\0");
|
||||||
|
|
||||||
|
count = (uint) data.Count;
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
151
taglib-sharp/src/TagLib/IFD/Entries/StripOffsetsIFDEntry.cs
Normal file
151
taglib-sharp/src/TagLib/IFD/Entries/StripOffsetsIFDEntry.cs
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
//
|
||||||
|
// StripOffsetsIFDEntry.cs:
|
||||||
|
//
|
||||||
|
// Author:
|
||||||
|
// Mike Gemuende (mike@gemuende.de)
|
||||||
|
//
|
||||||
|
// 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;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
|
||||||
|
namespace TagLib.IFD.Entries
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Contains the offsets to the image data strips.
|
||||||
|
/// </summary>
|
||||||
|
public class StripOffsetsIFDEntry : ArrayIFDEntry<uint>
|
||||||
|
{
|
||||||
|
|
||||||
|
#region Private Fields
|
||||||
|
|
||||||
|
/// <value>
|
||||||
|
/// Store the strip length to read them before writing.
|
||||||
|
/// </value>
|
||||||
|
private uint[] byte_counts;
|
||||||
|
|
||||||
|
/// <value>
|
||||||
|
/// The file the offsets belong to
|
||||||
|
/// </value>
|
||||||
|
private File file;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </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[]"/> with the strip offsets.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="byte_counts">
|
||||||
|
/// The length of the strips.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="file">
|
||||||
|
/// The file from which the strips will be read.
|
||||||
|
/// </param>
|
||||||
|
public StripOffsetsIFDEntry (ushort tag, uint[] values, uint[] byte_counts, File file) : base (tag)
|
||||||
|
{
|
||||||
|
Values = values;
|
||||||
|
this.byte_counts = byte_counts;
|
||||||
|
this.file = file;
|
||||||
|
|
||||||
|
if (values.Length != byte_counts.Length)
|
||||||
|
throw new Exception ("strip offsets and strip byte counts do not have the same length");
|
||||||
|
}
|
||||||
|
|
||||||
|
#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)
|
||||||
|
{
|
||||||
|
// The StripOffsets are an array of offsets, where the image data can be found.
|
||||||
|
// We store the offsets and behind the offsets the image data is stored. Therfore,
|
||||||
|
// the ByteVector data first collects the image data and the offsets itself are
|
||||||
|
// collected by offset_data. Then both are concatenated.
|
||||||
|
ByteVector data = new ByteVector ();
|
||||||
|
ByteVector offset_data = new ByteVector ();
|
||||||
|
|
||||||
|
// every offset needs 4 byte, we need to reserve the bytes.
|
||||||
|
uint data_offset = offset + (uint) (4 * Values.Length);
|
||||||
|
|
||||||
|
for (int i = 0; i < Values.Length; i++) {
|
||||||
|
uint new_offset = (uint) (data_offset + data.Count);
|
||||||
|
|
||||||
|
file.Seek (Values[i], SeekOrigin.Begin);
|
||||||
|
data.Add (file.ReadBlock ((int) byte_counts[i]));
|
||||||
|
|
||||||
|
// update strip offset data to new offset
|
||||||
|
Values[i] = new_offset;
|
||||||
|
|
||||||
|
offset_data.Add (ByteVector.FromUInt (new_offset, is_bigendian));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the StripOffsets only consists of one offset, this doesn't work, because this offset
|
||||||
|
// should be stored inside the IFD as a value. But, because of the additional image data,
|
||||||
|
// it is not stored there. We need to fix this, that the offset is adjusted correctly.
|
||||||
|
// Therefore, the offset_data is only added if it contains more than one value.
|
||||||
|
// Then, the offset is set correctly. (However, we need to ensure, that the image data
|
||||||
|
// consists at least of 4 bytes, which is probably the case every time, but to be sure ...)
|
||||||
|
// However, the strip offset in the array must also be adjusted, if the offset_data is ignored.
|
||||||
|
if (Values.Length > 1)
|
||||||
|
data.Insert (0, offset_data);
|
||||||
|
else
|
||||||
|
Values[0] = offset;
|
||||||
|
|
||||||
|
while (data.Count < 4)
|
||||||
|
data.Add (0x00);
|
||||||
|
|
||||||
|
// the entry is a single long entry where the value is an offset to the data
|
||||||
|
// the offset is automatically updated by the renderer.
|
||||||
|
type = (ushort) IFDEntryType.Long;
|
||||||
|
count = (uint) Values.Length;
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
97
taglib-sharp/src/TagLib/IFD/Entries/SubIFDArrayEntry.cs
Normal file
97
taglib-sharp/src/TagLib/IFD/Entries/SubIFDArrayEntry.cs
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
//
|
||||||
|
// SubIFDArrayEntry.cs:
|
||||||
|
//
|
||||||
|
// Author:
|
||||||
|
// Ruben Vermeersch (ruben@savanne.be)
|
||||||
|
//
|
||||||
|
// Copyright (C) 2010 Ruben Vermeersch
|
||||||
|
//
|
||||||
|
// 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.IFD.Entries
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Contains the SubIFDs IFD entry.
|
||||||
|
/// </summary>
|
||||||
|
public class SubIFDArrayEntry : IFDEntry
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <value>
|
||||||
|
/// The ID of the tag, the current instance belongs to
|
||||||
|
/// </value>
|
||||||
|
public ushort Tag {
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <value>
|
||||||
|
/// The structures of the IFDs to which this entry points.
|
||||||
|
/// </value>
|
||||||
|
public IFDStructure [] Entries { get; private set; }
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tag">
|
||||||
|
/// A <see cref="System.UInt16"/> with the tag ID of the entry this instance
|
||||||
|
/// represents
|
||||||
|
/// </param>
|
||||||
|
/// <param name="entries">
|
||||||
|
/// A set of ifd structures.
|
||||||
|
/// </param>
|
||||||
|
public SubIFDArrayEntry (ushort tag, List<IFDStructure> entries)
|
||||||
|
{
|
||||||
|
Tag = tag;
|
||||||
|
Entries = entries.ToArray ();
|
||||||
|
}
|
||||||
|
|
||||||
|
#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)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException ("Not implemented yet!");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
128
taglib-sharp/src/TagLib/IFD/Entries/SubIFDEntry.cs
Normal file
128
taglib-sharp/src/TagLib/IFD/Entries/SubIFDEntry.cs
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
//
|
||||||
|
// SubIFDEntry.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 Sub IFD.
|
||||||
|
/// </summary>
|
||||||
|
public class SubIFDEntry : IFDEntry
|
||||||
|
{
|
||||||
|
|
||||||
|
#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 IFD entry.
|
||||||
|
/// </value>
|
||||||
|
public ushort Type { get; private set; }
|
||||||
|
|
||||||
|
/// <value>
|
||||||
|
/// The count of the IFD entry.
|
||||||
|
/// </value>
|
||||||
|
public uint Count { get; private set; }
|
||||||
|
|
||||||
|
/// <value>
|
||||||
|
/// The structure of the sub-ifd which is stored by the current
|
||||||
|
/// instance
|
||||||
|
/// </value>
|
||||||
|
public IFDStructure Structure { get; private set; }
|
||||||
|
|
||||||
|
/// <value>
|
||||||
|
/// The number of entries in the entire IFD.
|
||||||
|
/// </value>
|
||||||
|
public int ChildCount {
|
||||||
|
get {
|
||||||
|
int sum = 0;
|
||||||
|
foreach (var directory in Structure.Directories)
|
||||||
|
sum += directory.Count;
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Construcor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tag">
|
||||||
|
/// A <see cref="System.UInt16"/> with the tag ID of the entry this instance
|
||||||
|
/// represents
|
||||||
|
/// </param>
|
||||||
|
/// <param name="type">
|
||||||
|
/// A <see cref="System.UInt16"/> with the type of the IFD entry.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="count">
|
||||||
|
/// A <see cref="System.UInt32"/> with the count of the IFD entry.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="structure">
|
||||||
|
/// A <see cref="IFDStructure"/> to be stored
|
||||||
|
/// </param>
|
||||||
|
public SubIFDEntry (ushort tag, ushort type, uint count, IFDStructure structure)
|
||||||
|
{
|
||||||
|
Tag = tag;
|
||||||
|
Type = type;
|
||||||
|
Count = count;
|
||||||
|
Structure = structure;
|
||||||
|
}
|
||||||
|
|
||||||
|
#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) Type;
|
||||||
|
count = 1;
|
||||||
|
|
||||||
|
count = Count;
|
||||||
|
return new IFDRenderer (is_bigendian, Structure, offset).Render ();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user