Removed taglib. Prepare for upgrade!
This commit is contained in:
parent
511b18cdd6
commit
70b19e6cfa
181 changed files with 0 additions and 29273 deletions
|
@ -1,11 +0,0 @@
|
||||||
Scott Wheeler <wheeler@kde.org>
|
|
||||||
Author, maintainer
|
|
||||||
Ismael Orenstein <orenstein@kde.org>
|
|
||||||
Xing header implementation
|
|
||||||
Allan Sandfeld Jensen <kde@carewolf.org>
|
|
||||||
FLAC metadata implementation
|
|
||||||
Teemu Tervo <teemu.tervo@gmx.net>
|
|
||||||
Numerous bug reports and fixes
|
|
||||||
|
|
||||||
Please send all patches and questions to taglib-devel@kde.org rather than to
|
|
||||||
individual developers!
|
|
|
@ -1,481 +0,0 @@
|
||||||
GNU LIBRARY GENERAL PUBLIC LICENSE
|
|
||||||
Version 2, June 1991
|
|
||||||
|
|
||||||
Copyright (C) 1991 Free Software Foundation, Inc.
|
|
||||||
59 Temple Place - Suite 330
|
|
||||||
Boston, MA 02111-1307, 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 library GPL. It is
|
|
||||||
numbered 2 because it goes with version 2 of the ordinary GPL.]
|
|
||||||
|
|
||||||
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 Library General Public License, applies to some
|
|
||||||
specially designated Free Software Foundation software, and to any
|
|
||||||
other libraries whose authors decide to use it. You can use it for
|
|
||||||
your libraries, too.
|
|
||||||
|
|
||||||
When we speak of free software, we are referring to freedom, 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 or use pieces of it
|
|
||||||
in new free programs; and that you know you can do these things.
|
|
||||||
|
|
||||||
To protect your rights, we need to make restrictions that forbid
|
|
||||||
anyone to deny you these rights or to ask you to surrender the 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 a program 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.
|
|
||||||
|
|
||||||
Our method of protecting your rights has two steps: (1) copyright
|
|
||||||
the library, and (2) offer you this license which gives you legal
|
|
||||||
permission to copy, distribute and/or modify the library.
|
|
||||||
|
|
||||||
Also, for each distributor's protection, we want to make certain
|
|
||||||
that everyone understands that there is no warranty for this free
|
|
||||||
library. If the library is modified by someone else and passed on, we
|
|
||||||
want its recipients to know that what they have is not the original
|
|
||||||
version, so that any problems introduced by others will not reflect on
|
|
||||||
the original authors' reputations.
|
|
||||||
|
|
||||||
Finally, any free program is threatened constantly by software
|
|
||||||
patents. We wish to avoid the danger that companies distributing free
|
|
||||||
software will individually obtain patent licenses, thus in effect
|
|
||||||
transforming the program into proprietary software. To prevent this,
|
|
||||||
we have made it clear that any patent must be licensed for everyone's
|
|
||||||
free use or not licensed at all.
|
|
||||||
|
|
||||||
Most GNU software, including some libraries, is covered by the ordinary
|
|
||||||
GNU General Public License, which was designed for utility programs. This
|
|
||||||
license, the GNU Library General Public License, applies to certain
|
|
||||||
designated libraries. This license is quite different from the ordinary
|
|
||||||
one; be sure to read it in full, and don't assume that anything in it is
|
|
||||||
the same as in the ordinary license.
|
|
||||||
|
|
||||||
The reason we have a separate public license for some libraries is that
|
|
||||||
they blur the distinction we usually make between modifying or adding to a
|
|
||||||
program and simply using it. Linking a program with a library, without
|
|
||||||
changing the library, is in some sense simply using the library, and is
|
|
||||||
analogous to running a utility program or application program. However, in
|
|
||||||
a textual and legal sense, the linked executable is a combined work, a
|
|
||||||
derivative of the original library, and the ordinary General Public License
|
|
||||||
treats it as such.
|
|
||||||
|
|
||||||
Because of this blurred distinction, using the ordinary General
|
|
||||||
Public License for libraries did not effectively promote software
|
|
||||||
sharing, because most developers did not use the libraries. We
|
|
||||||
concluded that weaker conditions might promote sharing better.
|
|
||||||
|
|
||||||
However, unrestricted linking of non-free programs would deprive the
|
|
||||||
users of those programs of all benefit from the free status of the
|
|
||||||
libraries themselves. This Library General Public License is intended to
|
|
||||||
permit developers of non-free programs to use free libraries, while
|
|
||||||
preserving your freedom as a user of such programs to change the free
|
|
||||||
libraries that are incorporated in them. (We have not seen how to achieve
|
|
||||||
this as regards changes in header files, but we have achieved it as regards
|
|
||||||
changes in the actual functions of the Library.) The hope is that this
|
|
||||||
will lead to faster development of free libraries.
|
|
||||||
|
|
||||||
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, while the latter only
|
|
||||||
works together with the library.
|
|
||||||
|
|
||||||
Note that it is possible for a library to be covered by the ordinary
|
|
||||||
General Public License rather than by this special one.
|
|
||||||
|
|
||||||
GNU LIBRARY GENERAL PUBLIC LICENSE
|
|
||||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
|
||||||
|
|
||||||
0. This License Agreement applies to any software library which
|
|
||||||
contains a notice placed by the copyright holder or other authorized
|
|
||||||
party saying it may be distributed under the terms of this Library
|
|
||||||
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 compile 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) 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.
|
|
||||||
|
|
||||||
c) 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.
|
|
||||||
|
|
||||||
d) 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 source code 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 to
|
|
||||||
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 Library 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 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
|
|
||||||
Also add information on how to contact you by electronic and paper mail.
|
|
||||||
|
|
||||||
You should also get your employer (if you work as a programmer) or your
|
|
||||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
|
||||||
necessary. Here is a sample; alter the names:
|
|
||||||
|
|
||||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
|
||||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
|
||||||
|
|
||||||
<signature of Ty Coon>, 1 April 1990
|
|
||||||
Ty Coon, President of Vice
|
|
||||||
|
|
||||||
That's all there is to it!
|
|
|
@ -1,167 +0,0 @@
|
||||||
Basic Installation
|
|
||||||
==================
|
|
||||||
|
|
||||||
These are generic installation instructions.
|
|
||||||
|
|
||||||
The `configure' shell script attempts to guess correct values for
|
|
||||||
various system-dependent variables used during compilation. It uses
|
|
||||||
those values to create a `Makefile' in each directory of the package.
|
|
||||||
It may also create one or more `.h' files containing system-dependent
|
|
||||||
definitions. Finally, it creates a shell script `config.status' that
|
|
||||||
you can run in the future to recreate the current configuration, a file
|
|
||||||
`config.cache' that saves the results of its tests to speed up
|
|
||||||
reconfiguring, and a file `config.log' containing compiler output
|
|
||||||
(useful mainly for debugging `configure').
|
|
||||||
|
|
||||||
If you need to do unusual things to compile the package, please try
|
|
||||||
to figure out how `configure' could check whether to do them, and mail
|
|
||||||
diffs or instructions to the address given in the `README' so they can
|
|
||||||
be considered for the next release. If at some point `config.cache'
|
|
||||||
contains results you don't want to keep, you may remove or edit it.
|
|
||||||
|
|
||||||
The file `configure.in' is used to create `configure' by a program
|
|
||||||
called `autoconf'. You only need `configure.in' if you want to change
|
|
||||||
it or regenerate `configure' using a newer version of `autoconf'.
|
|
||||||
|
|
||||||
The simplest way to compile this package is:
|
|
||||||
|
|
||||||
1. `cd' to the directory containing the package's source code and type
|
|
||||||
`./configure' to configure the package for your system. If you're
|
|
||||||
using `csh' on an old version of System V, you might need to type
|
|
||||||
`sh ./configure' instead to prevent `csh' from trying to execute
|
|
||||||
`configure' itself.
|
|
||||||
|
|
||||||
Running `configure' takes a while. While running, it prints some
|
|
||||||
messages telling which features it is checking for.
|
|
||||||
|
|
||||||
2. Type `make' to compile the package.
|
|
||||||
|
|
||||||
3. Type `make install' to install the programs and any data files and
|
|
||||||
documentation.
|
|
||||||
|
|
||||||
4. You can remove the program binaries and object files from the
|
|
||||||
source code directory by typing `make clean'.
|
|
||||||
|
|
||||||
Compilers and Options
|
|
||||||
=====================
|
|
||||||
|
|
||||||
Some systems require unusual options for compilation or linking that
|
|
||||||
the `configure' script does not know about. You can give `configure'
|
|
||||||
initial values for variables by setting them in the environment. Using
|
|
||||||
a Bourne-compatible shell, you can do that on the command line like
|
|
||||||
this:
|
|
||||||
CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
|
|
||||||
|
|
||||||
Or on systems that have the `env' program, you can do it like this:
|
|
||||||
env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
|
|
||||||
|
|
||||||
Compiling For Multiple Architectures
|
|
||||||
====================================
|
|
||||||
|
|
||||||
You can compile the package for more than one kind of computer at the
|
|
||||||
same time, by placing the object files for each architecture in their
|
|
||||||
own directory. To do this, you must use a version of `make' that
|
|
||||||
supports the `VPATH' variable, such as GNU `make'. `cd' to the
|
|
||||||
directory where you want the object files and executables to go and run
|
|
||||||
the `configure' script. `configure' automatically checks for the
|
|
||||||
source code in the directory that `configure' is in and in `..'.
|
|
||||||
|
|
||||||
If you have to use a `make' that does not supports the `VPATH'
|
|
||||||
variable, you have to compile the package for one architecture at a time
|
|
||||||
in the source code directory. After you have installed the package for
|
|
||||||
one architecture, use `make distclean' before reconfiguring for another
|
|
||||||
architecture.
|
|
||||||
|
|
||||||
Installation Names
|
|
||||||
==================
|
|
||||||
|
|
||||||
By default, `make install' will install the package's files in
|
|
||||||
`/usr/local/bin', `/usr/local/man', etc. You can specify an
|
|
||||||
installation prefix other than `/usr/local' by giving `configure' the
|
|
||||||
option `--prefix=PATH'.
|
|
||||||
|
|
||||||
You can specify separate installation prefixes for
|
|
||||||
architecture-specific files and architecture-independent files. If you
|
|
||||||
give `configure' the option `--exec-prefix=PATH', the package will use
|
|
||||||
PATH as the prefix for installing programs and libraries.
|
|
||||||
Documentation and other data files will still use the regular prefix.
|
|
||||||
|
|
||||||
If the package supports it, you can cause programs to be installed
|
|
||||||
with an extra prefix or suffix on their names by giving `configure' the
|
|
||||||
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
|
|
||||||
|
|
||||||
Optional Features
|
|
||||||
=================
|
|
||||||
|
|
||||||
Some packages pay attention to `--enable-FEATURE' options to
|
|
||||||
`configure', where FEATURE indicates an optional part of the package.
|
|
||||||
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
|
|
||||||
is something like `gnu-as' or `x' (for the X Window System). The
|
|
||||||
`README' should mention any `--enable-' and `--with-' options that the
|
|
||||||
package recognizes.
|
|
||||||
|
|
||||||
For packages that use the X Window System, `configure' can usually
|
|
||||||
find the X include and library files automatically, but if it doesn't,
|
|
||||||
you can use the `configure' options `--x-includes=DIR' and
|
|
||||||
`--x-libraries=DIR' to specify their locations.
|
|
||||||
|
|
||||||
Specifying the System Type
|
|
||||||
==========================
|
|
||||||
|
|
||||||
There may be some features `configure' can not figure out
|
|
||||||
automatically, but needs to determine by the type of host the package
|
|
||||||
will run on. Usually `configure' can figure that out, but if it prints
|
|
||||||
a message saying it can not guess the host type, give it the
|
|
||||||
`--host=TYPE' option. TYPE can either be a short name for the system
|
|
||||||
type, such as `sun4', or a canonical name with three fields:
|
|
||||||
CPU-COMPANY-SYSTEM
|
|
||||||
|
|
||||||
See the file `config.sub' for the possible values of each field. If
|
|
||||||
`config.sub' isn't included in this package, then this package doesn't
|
|
||||||
need to know the host type.
|
|
||||||
|
|
||||||
If you are building compiler tools for cross-compiling, you can also
|
|
||||||
use the `--target=TYPE' option to select the type of system they will
|
|
||||||
produce code for and the `--build=TYPE' option to select the type of
|
|
||||||
system on which you are compiling the package.
|
|
||||||
|
|
||||||
Sharing Defaults
|
|
||||||
================
|
|
||||||
|
|
||||||
If you want to set default values for `configure' scripts to share,
|
|
||||||
you can create a site shell script called `config.site' that gives
|
|
||||||
default values for variables like `CC', `cache_file', and `prefix'.
|
|
||||||
`configure' looks for `PREFIX/share/config.site' if it exists, then
|
|
||||||
`PREFIX/etc/config.site' if it exists. Or, you can set the
|
|
||||||
`CONFIG_SITE' environment variable to the location of the site script.
|
|
||||||
A warning: not all `configure' scripts look for a site script.
|
|
||||||
|
|
||||||
Operation Controls
|
|
||||||
==================
|
|
||||||
|
|
||||||
`configure' recognizes the following options to control how it
|
|
||||||
operates.
|
|
||||||
|
|
||||||
`--cache-file=FILE'
|
|
||||||
Use and save the results of the tests in FILE instead of
|
|
||||||
`./config.cache'. Set FILE to `/dev/null' to disable caching, for
|
|
||||||
debugging `configure'.
|
|
||||||
|
|
||||||
`--help'
|
|
||||||
Print a summary of the options to `configure', and exit.
|
|
||||||
|
|
||||||
`--quiet'
|
|
||||||
`--silent'
|
|
||||||
`-q'
|
|
||||||
Do not print messages saying which checks are being made.
|
|
||||||
|
|
||||||
`--srcdir=DIR'
|
|
||||||
Look for the package's source code in directory DIR. Usually
|
|
||||||
`configure' can determine that directory automatically.
|
|
||||||
|
|
||||||
`--version'
|
|
||||||
Print the version of Autoconf used to generate the `configure'
|
|
||||||
script, and exit.
|
|
||||||
|
|
||||||
`configure' also accepts some other, not widely useful, options.
|
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
There are a few other people that have done bindings externally that I have
|
|
||||||
been made aware of. I have not personally reviewed these bindings, but I'm
|
|
||||||
listing them here so that those who find them useful are able to find them:
|
|
||||||
|
|
||||||
- Ruby - http://www.hakubi.us/ruby-taglib/
|
|
||||||
- Python - http://namingmuse.berlios.de/
|
|
|
@ -1,262 +0,0 @@
|
||||||
/***************************************************************************
|
|
||||||
copyright : (C) 2003 by Scott Wheeler
|
|
||||||
email : wheeler@kde.org
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* 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 *
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
#include "tag_c.h"
|
|
||||||
|
|
||||||
#include <fileref.h>
|
|
||||||
#include <tfile.h>
|
|
||||||
#include <vorbisfile.h>
|
|
||||||
#include <mpegfile.h>
|
|
||||||
#include <flacfile.h>
|
|
||||||
#include <oggflacfile.h>
|
|
||||||
#include <mpcfile.h>
|
|
||||||
#include <tag.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <id3v2framefactory.h>
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
|
|
||||||
static List<char *> strings;
|
|
||||||
static bool unicodeStrings = true;
|
|
||||||
static bool stringManagementEnabled = true;
|
|
||||||
|
|
||||||
void taglib_set_strings_unicode(BOOL unicode)
|
|
||||||
{
|
|
||||||
unicodeStrings = bool(unicode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void taglib_set_string_management_enabled(BOOL management)
|
|
||||||
{
|
|
||||||
stringManagementEnabled = bool(management);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// TagLib::File wrapper
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
TagLib_File *taglib_file_new(const char *filename)
|
|
||||||
{
|
|
||||||
return reinterpret_cast<TagLib_File *>(FileRef::create(filename));
|
|
||||||
}
|
|
||||||
|
|
||||||
TagLib_File *taglib_file_new_type(const char *filename, TagLib_File_Type type)
|
|
||||||
{
|
|
||||||
switch(type) {
|
|
||||||
case TagLib_File_MPEG:
|
|
||||||
return reinterpret_cast<TagLib_File *>(new MPEG::File(filename));
|
|
||||||
case TagLib_File_OggVorbis:
|
|
||||||
return reinterpret_cast<TagLib_File *>(new Vorbis::File(filename));
|
|
||||||
case TagLib_File_FLAC:
|
|
||||||
return reinterpret_cast<TagLib_File *>(new FLAC::File(filename));
|
|
||||||
case TagLib_File_MPC:
|
|
||||||
return reinterpret_cast<TagLib_File *>(new MPC::File(filename));
|
|
||||||
case TagLib_File_OggFlac:
|
|
||||||
return reinterpret_cast<TagLib_File *>(new Ogg::FLAC::File(filename));
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void taglib_file_free(TagLib_File *file)
|
|
||||||
{
|
|
||||||
delete reinterpret_cast<File *>(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
TagLib_Tag *taglib_file_tag(const TagLib_File *file)
|
|
||||||
{
|
|
||||||
const File *f = reinterpret_cast<const File *>(file);
|
|
||||||
return reinterpret_cast<TagLib_Tag *>(f->tag());
|
|
||||||
}
|
|
||||||
|
|
||||||
const TagLib_AudioProperties *taglib_file_audioproperties(const TagLib_File *file)
|
|
||||||
{
|
|
||||||
const File *f = reinterpret_cast<const File *>(file);
|
|
||||||
return reinterpret_cast<const TagLib_AudioProperties *>(f->audioProperties());
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL taglib_file_save(TagLib_File *file)
|
|
||||||
{
|
|
||||||
return reinterpret_cast<File *>(file)->save();
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// TagLib::Tag wrapper
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
char *taglib_tag_title(const TagLib_Tag *tag)
|
|
||||||
{
|
|
||||||
const Tag *t = reinterpret_cast<const Tag *>(tag);
|
|
||||||
char *s = ::strdup(t->title().toCString(unicodeStrings));
|
|
||||||
if(stringManagementEnabled)
|
|
||||||
strings.append(s);
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *taglib_tag_artist(const TagLib_Tag *tag)
|
|
||||||
{
|
|
||||||
const Tag *t = reinterpret_cast<const Tag *>(tag);
|
|
||||||
char *s = ::strdup(t->artist().toCString(unicodeStrings));
|
|
||||||
if(stringManagementEnabled)
|
|
||||||
strings.append(s);
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *taglib_tag_album(const TagLib_Tag *tag)
|
|
||||||
{
|
|
||||||
const Tag *t = reinterpret_cast<const Tag *>(tag);
|
|
||||||
char *s = ::strdup(t->album().toCString(unicodeStrings));
|
|
||||||
if(stringManagementEnabled)
|
|
||||||
strings.append(s);
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *taglib_tag_comment(const TagLib_Tag *tag)
|
|
||||||
{
|
|
||||||
const Tag *t = reinterpret_cast<const Tag *>(tag);
|
|
||||||
char *s = ::strdup(t->comment().toCString(unicodeStrings));
|
|
||||||
if(stringManagementEnabled)
|
|
||||||
strings.append(s);
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *taglib_tag_genre(const TagLib_Tag *tag)
|
|
||||||
{
|
|
||||||
const Tag *t = reinterpret_cast<const Tag *>(tag);
|
|
||||||
char *s = ::strdup(t->genre().toCString(unicodeStrings));
|
|
||||||
if(stringManagementEnabled)
|
|
||||||
strings.append(s);
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int taglib_tag_year(const TagLib_Tag *tag)
|
|
||||||
{
|
|
||||||
const Tag *t = reinterpret_cast<const Tag *>(tag);
|
|
||||||
return t->year();
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int taglib_tag_track(const TagLib_Tag *tag)
|
|
||||||
{
|
|
||||||
const Tag *t = reinterpret_cast<const Tag *>(tag);
|
|
||||||
return t->track();
|
|
||||||
}
|
|
||||||
|
|
||||||
void taglib_tag_set_title(TagLib_Tag *tag, const char *title)
|
|
||||||
{
|
|
||||||
Tag *t = reinterpret_cast<Tag *>(tag);
|
|
||||||
t->setTitle(String(title, unicodeStrings ? String::UTF8 : String::Latin1));
|
|
||||||
}
|
|
||||||
|
|
||||||
void taglib_tag_set_artist(TagLib_Tag *tag, const char *artist)
|
|
||||||
{
|
|
||||||
Tag *t = reinterpret_cast<Tag *>(tag);
|
|
||||||
t->setArtist(String(artist, unicodeStrings ? String::UTF8 : String::Latin1));
|
|
||||||
}
|
|
||||||
|
|
||||||
void taglib_tag_set_album(TagLib_Tag *tag, const char *album)
|
|
||||||
{
|
|
||||||
Tag *t = reinterpret_cast<Tag *>(tag);
|
|
||||||
t->setAlbum(String(album, unicodeStrings ? String::UTF8 : String::Latin1));
|
|
||||||
}
|
|
||||||
|
|
||||||
void taglib_tag_set_comment(TagLib_Tag *tag, const char *comment)
|
|
||||||
{
|
|
||||||
Tag *t = reinterpret_cast<Tag *>(tag);
|
|
||||||
t->setComment(String(comment, unicodeStrings ? String::UTF8 : String::Latin1));
|
|
||||||
}
|
|
||||||
|
|
||||||
void taglib_tag_set_genre(TagLib_Tag *tag, const char *genre)
|
|
||||||
{
|
|
||||||
Tag *t = reinterpret_cast<Tag *>(tag);
|
|
||||||
t->setGenre(String(genre, unicodeStrings ? String::UTF8 : String::Latin1));
|
|
||||||
}
|
|
||||||
|
|
||||||
void taglib_tag_set_year(TagLib_Tag *tag, unsigned int year)
|
|
||||||
{
|
|
||||||
Tag *t = reinterpret_cast<Tag *>(tag);
|
|
||||||
t->setYear(year);
|
|
||||||
}
|
|
||||||
|
|
||||||
void taglib_tag_set_track(TagLib_Tag *tag, unsigned int track)
|
|
||||||
{
|
|
||||||
Tag *t = reinterpret_cast<Tag *>(tag);
|
|
||||||
t->setTrack(track);
|
|
||||||
}
|
|
||||||
|
|
||||||
void taglib_tag_free_strings()
|
|
||||||
{
|
|
||||||
if(!stringManagementEnabled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for(List<char *>::Iterator it = strings.begin(); it != strings.end(); ++it)
|
|
||||||
free(*it);
|
|
||||||
strings.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// TagLib::AudioProperties wrapper
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
int taglib_audioproperties_length(const TagLib_AudioProperties *audioProperties)
|
|
||||||
{
|
|
||||||
const AudioProperties *p = reinterpret_cast<const AudioProperties *>(audioProperties);
|
|
||||||
return p->length();
|
|
||||||
}
|
|
||||||
|
|
||||||
int taglib_audioproperties_bitrate(const TagLib_AudioProperties *audioProperties)
|
|
||||||
{
|
|
||||||
const AudioProperties *p = reinterpret_cast<const AudioProperties *>(audioProperties);
|
|
||||||
return p->bitrate();
|
|
||||||
}
|
|
||||||
|
|
||||||
int taglib_audioproperties_samplerate(const TagLib_AudioProperties *audioProperties)
|
|
||||||
{
|
|
||||||
const AudioProperties *p = reinterpret_cast<const AudioProperties *>(audioProperties);
|
|
||||||
return p->sampleRate();
|
|
||||||
}
|
|
||||||
|
|
||||||
int taglib_audioproperties_channels(const TagLib_AudioProperties *audioProperties)
|
|
||||||
{
|
|
||||||
const AudioProperties *p = reinterpret_cast<const AudioProperties *>(audioProperties);
|
|
||||||
return p->channels();
|
|
||||||
}
|
|
||||||
|
|
||||||
void taglib_id3v2_set_default_text_encoding(TagLib_ID3v2_Encoding encoding)
|
|
||||||
{
|
|
||||||
String::Type type = String::Latin1;
|
|
||||||
|
|
||||||
switch(encoding)
|
|
||||||
{
|
|
||||||
case TagLib_ID3v2_Latin1:
|
|
||||||
type = String::Latin1;
|
|
||||||
break;
|
|
||||||
case TagLib_ID3v2_UTF16:
|
|
||||||
type = String::UTF16;
|
|
||||||
break;
|
|
||||||
case TagLib_ID3v2_UTF16BE:
|
|
||||||
type = String::UTF16BE;
|
|
||||||
break;
|
|
||||||
case TagLib_ID3v2_UTF8:
|
|
||||||
type = String::UTF8;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ID3v2::FrameFactory::instance()->setDefaultTextEncoding(type);
|
|
||||||
}
|
|
|
@ -1,268 +0,0 @@
|
||||||
/***************************************************************************
|
|
||||||
copyright : (C) 2003 by Scott Wheeler
|
|
||||||
email : wheeler@kde.org
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* 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 *
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
#ifndef TAGLIB_TAG_C
|
|
||||||
#define TAGLIB_TAG_C
|
|
||||||
|
|
||||||
/* Do not include this in the main TagLib documentation. */
|
|
||||||
#ifndef DO_NOT_DOCUMENT
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef BOOL
|
|
||||||
#define BOOL int
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
* [ TagLib C Binding ]
|
|
||||||
*
|
|
||||||
* This is an interface to TagLib's "simple" API, meaning that you can read and
|
|
||||||
* modify media files in a generic, but not specialized way. This is a rough
|
|
||||||
* representation of TagLib::File and TagLib::Tag, for which the documentation
|
|
||||||
* is somewhat more complete and worth consulting.
|
|
||||||
*******************************************************************************/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* These are used for type provide some type safety to the C API (as opposed to
|
|
||||||
* using void *, but pointers to them are simply cast to the corresponding C++
|
|
||||||
* types in the implementation.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct { int dummy; } TagLib_File;
|
|
||||||
typedef struct { int dummy; } TagLib_Tag;
|
|
||||||
typedef struct { int dummy; } TagLib_AudioProperties;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* By default all strings coming into or out of TagLib's C API are in UTF8.
|
|
||||||
* However, it may be desirable for TagLib to operate on Latin1 (ISO-8859-1)
|
|
||||||
* strings in which case this should be set to FALSE.
|
|
||||||
*/
|
|
||||||
void taglib_set_strings_unicode(BOOL unicode);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* TagLib can keep track of strings that are created when outputting tag values
|
|
||||||
* and clear them using taglib_tag_clear_strings(). This is enabled by default.
|
|
||||||
* However if you wish to do more fine grained management of strings, you can do
|
|
||||||
* so by setting \a management to FALSE.
|
|
||||||
*/
|
|
||||||
void taglib_set_string_management_enabled(BOOL management);
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
* File API
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
TagLib_File_MPEG,
|
|
||||||
TagLib_File_OggVorbis,
|
|
||||||
TagLib_File_FLAC,
|
|
||||||
TagLib_File_MPC,
|
|
||||||
TagLib_File_OggFlac
|
|
||||||
} TagLib_File_Type;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Creates a TagLib file based on \a filename. TagLib will try to guess the file
|
|
||||||
* type.
|
|
||||||
*
|
|
||||||
* \returns NULL if the file type cannot be determined or the file cannot
|
|
||||||
* be opened.
|
|
||||||
*/
|
|
||||||
TagLib_File *taglib_file_new(const char *filename);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Creates a TagLib file based on \a filename. Rather than attempting to guess
|
|
||||||
* the type, it will use the one specified by \a type.
|
|
||||||
*/
|
|
||||||
TagLib_File *taglib_file_new_type(const char *filename, TagLib_File_Type type);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Frees and closes the file.
|
|
||||||
*/
|
|
||||||
void taglib_file_free(TagLib_File *file);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns a pointer to the tag associated with this file. This will be freed
|
|
||||||
* automatically when the file is freed.
|
|
||||||
*/
|
|
||||||
TagLib_Tag *taglib_file_tag(const TagLib_File *file);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns a pointer to the the audio properties associated with this file. This
|
|
||||||
* will be freed automatically when the file is freed.
|
|
||||||
*/
|
|
||||||
const TagLib_AudioProperties *taglib_file_audioproperties(const TagLib_File *file);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Saves the \a file to disk.
|
|
||||||
*/
|
|
||||||
BOOL taglib_file_save(TagLib_File *file);
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* Tag API
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns a string with this tag's title.
|
|
||||||
*
|
|
||||||
* \note By default this string should be UTF8 encoded and its memory should be
|
|
||||||
* freed using taglib_tag_free_strings().
|
|
||||||
*/
|
|
||||||
char *taglib_tag_title(const TagLib_Tag *tag);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns a string with this tag's artist.
|
|
||||||
*
|
|
||||||
* \note By default this string should be UTF8 encoded and its memory should be
|
|
||||||
* freed using taglib_tag_free_strings().
|
|
||||||
*/
|
|
||||||
char *taglib_tag_artist(const TagLib_Tag *tag);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns a string with this tag's album name.
|
|
||||||
*
|
|
||||||
* \note By default this string should be UTF8 encoded and its memory should be
|
|
||||||
* freed using taglib_tag_free_strings().
|
|
||||||
*/
|
|
||||||
char *taglib_tag_album(const TagLib_Tag *tag);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns a string with this tag's comment.
|
|
||||||
*
|
|
||||||
* \note By default this string should be UTF8 encoded and its memory should be
|
|
||||||
* freed using taglib_tag_free_strings().
|
|
||||||
*/
|
|
||||||
char *taglib_tag_comment(const TagLib_Tag *tag);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns a string with this tag's genre.
|
|
||||||
*
|
|
||||||
* \note By default this string should be UTF8 encoded and its memory should be
|
|
||||||
* freed using taglib_tag_free_strings().
|
|
||||||
*/
|
|
||||||
char *taglib_tag_genre(const TagLib_Tag *tag);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the tag's year or 0 if year is not set.
|
|
||||||
*/
|
|
||||||
unsigned int taglib_tag_year(const TagLib_Tag *tag);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the tag's track number or 0 if track number is not set.
|
|
||||||
*/
|
|
||||||
unsigned int taglib_tag_track(const TagLib_Tag *tag);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Sets the tag's title.
|
|
||||||
*
|
|
||||||
* \note By default this string should be UTF8 encoded.
|
|
||||||
*/
|
|
||||||
void taglib_tag_set_title(TagLib_Tag *tag, const char *title);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Sets the tag's artist.
|
|
||||||
*
|
|
||||||
* \note By default this string should be UTF8 encoded.
|
|
||||||
*/
|
|
||||||
void taglib_tag_set_artist(TagLib_Tag *tag, const char *artist);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Sets the tag's album.
|
|
||||||
*
|
|
||||||
* \note By default this string should be UTF8 encoded.
|
|
||||||
*/
|
|
||||||
void taglib_tag_set_album(TagLib_Tag *tag, const char *album);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Sets the tag's comment.
|
|
||||||
*
|
|
||||||
* \note By default this string should be UTF8 encoded.
|
|
||||||
*/
|
|
||||||
void taglib_tag_set_comment(TagLib_Tag *tag, const char *comment);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Sets the tag's genre.
|
|
||||||
*
|
|
||||||
* \note By default this string should be UTF8 encoded.
|
|
||||||
*/
|
|
||||||
void taglib_tag_set_genre(TagLib_Tag *tag, const char *genre);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Sets the tag's year. 0 indicates that this field should be cleared.
|
|
||||||
*/
|
|
||||||
void taglib_tag_set_year(TagLib_Tag *tag, unsigned int year);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Sets the tag's track number. 0 indicates that this field should be cleared.
|
|
||||||
*/
|
|
||||||
void taglib_tag_set_track(TagLib_Tag *tag, unsigned int track);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Frees all of the strings that have been created by the tag.
|
|
||||||
*/
|
|
||||||
void taglib_tag_free_strings(void);
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* Audio Properties API
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the length of the file in seconds.
|
|
||||||
*/
|
|
||||||
int taglib_audioproperties_length(const TagLib_AudioProperties *audioProperties);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the bitrate of the file in kb/s.
|
|
||||||
*/
|
|
||||||
int taglib_audioproperties_bitrate(const TagLib_AudioProperties *audioProperties);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the sample rate of the file in Hz.
|
|
||||||
*/
|
|
||||||
int taglib_audioproperties_samplerate(const TagLib_AudioProperties *audioProperties);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the number of channels in the audio stream.
|
|
||||||
*/
|
|
||||||
int taglib_audioproperties_channels(const TagLib_AudioProperties *audioProperties);
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
* Special convenience ID3v2 functions
|
|
||||||
*******************************************************************************/
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
TagLib_ID3v2_Latin1,
|
|
||||||
TagLib_ID3v2_UTF16,
|
|
||||||
TagLib_ID3v2_UTF16BE,
|
|
||||||
TagLib_ID3v2_UTF8
|
|
||||||
} TagLib_ID3v2_Encoding;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* This sets the default encoding for ID3v2 frames that are written to tags.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void taglib_id3v2_set_default_text_encoding(TagLib_ID3v2_Encoding encoding);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif /* DO_NOT_DOCUMENT */
|
|
||||||
#endif
|
|
|
@ -1,62 +0,0 @@
|
||||||
/* config.h. Generated from config.h.in by configure. */
|
|
||||||
/* config.h.in. Generated from configure.in by autoheader. */
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
|
||||||
#define HAVE_DLFCN_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
|
||||||
#define HAVE_INTTYPES_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <memory.h> header file. */
|
|
||||||
#define HAVE_MEMORY_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdint.h> header file. */
|
|
||||||
#define HAVE_STDINT_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
|
||||||
#define HAVE_STDLIB_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <strings.h> header file. */
|
|
||||||
#define HAVE_STRINGS_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <string.h> header file. */
|
|
||||||
#define HAVE_STRING_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
|
||||||
#define HAVE_SYS_STAT_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
|
||||||
#define HAVE_SYS_TYPES_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <unistd.h> header file. */
|
|
||||||
#define HAVE_UNISTD_H 1
|
|
||||||
|
|
||||||
/* have zlib */
|
|
||||||
#define HAVE_ZLIB 0
|
|
||||||
|
|
||||||
/* Suffix for lib directories */
|
|
||||||
#define KDELIBSUFF ""
|
|
||||||
|
|
||||||
/* Name of package */
|
|
||||||
#define PACKAGE "taglib"
|
|
||||||
|
|
||||||
/* Define to the address where bug reports for this package should be sent. */
|
|
||||||
#define PACKAGE_BUGREPORT ""
|
|
||||||
|
|
||||||
/* Define to the full name of this package. */
|
|
||||||
#define PACKAGE_NAME ""
|
|
||||||
|
|
||||||
/* Define to the full name and version of this package. */
|
|
||||||
#define PACKAGE_STRING ""
|
|
||||||
|
|
||||||
/* Define to the one symbol short name of this package. */
|
|
||||||
#define PACKAGE_TARNAME ""
|
|
||||||
|
|
||||||
/* Define to the version of this package. */
|
|
||||||
#define PACKAGE_VERSION ""
|
|
||||||
|
|
||||||
/* Define to 1 if you have the ANSI C header files. */
|
|
||||||
#define STDC_HEADERS 1
|
|
||||||
|
|
||||||
/* Version number of package */
|
|
||||||
#define VERSION "1.4"
|
|
|
@ -1,170 +0,0 @@
|
||||||
================================================================================
|
|
||||||
= APE Tag Specification, Version 2.000
|
|
||||||
================================================================================
|
|
||||||
|
|
||||||
Original Content (C) 2004, Frank Klemm <frank.klemm@elster.offl.uni-jena.de>
|
|
||||||
Formatting / Editing (C) 2004, Scott Wheeler <wheeler@kde.org>
|
|
||||||
|
|
||||||
================================================================================
|
|
||||||
= Contents
|
|
||||||
================================================================================
|
|
||||||
|
|
||||||
1 - APE Tag General Structure
|
|
||||||
2 - APE Tag Header / Footer Format
|
|
||||||
3 - APE Tag Flags
|
|
||||||
4 - APE Tag Item Format
|
|
||||||
5 - APE Tag Item Supported Keys
|
|
||||||
6 - APE Tag Item Content
|
|
||||||
7 - Data Types
|
|
||||||
7.1 - Data Types / UTF-8
|
|
||||||
7.2 - Data Types / Dates
|
|
||||||
7.3 - Data Types / Timestamps
|
|
||||||
|
|
||||||
================================================================================
|
|
||||||
= 1 - APE Tag General Structure
|
|
||||||
================================================================================
|
|
||||||
|
|
||||||
Member of Basic Components of SV8 Stream Note:
|
|
||||||
|
|
||||||
It is strongly recommended that the data size be stored in the tags. The size
|
|
||||||
should normally be in the roughly one kilobyte, never more than 8 kilobytes.
|
|
||||||
|
|
||||||
Larger data should be stored externally using link entries. Linked data is much
|
|
||||||
easier to process by normal programs, so for instance JPEG data should not be
|
|
||||||
included inside the audio file.
|
|
||||||
|
|
||||||
APE Tag Version 2.000 (with header, recommended):
|
|
||||||
|
|
||||||
/================================\
|
|
||||||
| APE Tag Header | 32 bytes |
|
|
||||||
|-------------------|------------|
|
|
||||||
| APE Tag Item 1 | > 10 bytes |
|
|
||||||
| APE Tag Item 2 | > 10 bytes |
|
|
||||||
| APE Tag Item n-1 | > 10 bytes |
|
|
||||||
| APE Tag Item n | > 10 bytes |
|
|
||||||
|-------------------|------------|
|
|
||||||
| APE Tag Footer | 32 bytes |
|
|
||||||
\================================/
|
|
||||||
|
|
||||||
|
|
||||||
APE tag items should be sorted ascending by size. When streaming, parts of the
|
|
||||||
APE tag may be dropped to reduce the danger of drop outs between tracks. This
|
|
||||||
is not required, but is strongly recommended. It would be desirable for the i
|
|
||||||
tems to be sorted by importance / size, but this is not feasible. This
|
|
||||||
convention should only be broken when adding less important small items and it
|
|
||||||
is not desirable to rewrite the entire tag. An APE tag at the end of a file
|
|
||||||
(the recommended location) must have at least a footer; an APE tag at the
|
|
||||||
beginning of a file (strongly discouraged) must have at least a header.
|
|
||||||
|
|
||||||
APE Tag Version 1.000 (without header, deprecated)
|
|
||||||
|
|
||||||
/================================\
|
|
||||||
| APE Tag Item 1 | > 10 bytes |
|
|
||||||
| APE Tag Item 2 | > 10 bytes |
|
|
||||||
| APE Tag Item n-1 | > 10 bytes |
|
|
||||||
| APE Tag Item n | > 10 bytes |
|
|
||||||
|-------------------|------------|
|
|
||||||
| APE Tag Footer | 32 bytes |
|
|
||||||
\================================/
|
|
||||||
|
|
||||||
================================================================================
|
|
||||||
= 2 - APE Tag Header / Footer Format
|
|
||||||
================================================================================
|
|
||||||
|
|
||||||
Contains number, length and attributes of all tag items
|
|
||||||
|
|
||||||
Header and Footer are different in 1 bit in the Tags Flags to distinguish
|
|
||||||
between them.
|
|
||||||
|
|
||||||
Member of APE Tag 2.0
|
|
||||||
|
|
||||||
/===========================================================================\
|
|
||||||
| Preamble | 8 bytes | { 'A', 'P', 'E', 'T', 'A', 'G', 'E', 'X' } |
|
|
||||||
|----------------|---------|------------------------------------------------|
|
|
||||||
| Version Number | 4 bytes | 1000 = Version 1.000, 2000 = Version 2.000 |
|
|
||||||
|----------------|---------|------------------------------------------------|
|
|
||||||
| Tag Size | 4 bytes | Tag size in bytes including footer and all tag |
|
|
||||||
| | | items excluding the header (for 1.000 |
|
|
||||||
| | | compatibility) |
|
|
||||||
|----------------|---------|------------------------------------------------|
|
|
||||||
| Item Count | 4 bytes | Number of items in the tag |
|
|
||||||
|----------------|---------|------------------------------------------------|
|
|
||||||
| Tag Flags | 4 bytes | Global flags |
|
|
||||||
|----------------|---------|------------------------------------------------|
|
|
||||||
| Reserved | 8 bytes | Must be zeroed |
|
|
||||||
\===========================================================================/
|
|
||||||
|
|
||||||
================================================================================
|
|
||||||
= 3 - APE Tag Flags
|
|
||||||
================================================================================
|
|
||||||
|
|
||||||
The general flag structure for either items or headers / footers is the same.
|
|
||||||
Bits 31, 30 and 29 are specific to headers / footers, whereas 2 through 0 are
|
|
||||||
item specific.
|
|
||||||
|
|
||||||
Note: APE Tags from Version 1.0 do not use any of the following. All flags in
|
|
||||||
that version are zeroed and ignored when reading.
|
|
||||||
|
|
||||||
/=================================================================\
|
|
||||||
| Contains Header | Bit 31 | 1 - has header | 0 - no header |
|
|
||||||
|-----------------|-------------|---------------------------------|
|
|
||||||
| Contains Footer | Bit 30 | 1 - has footer | 0 - no footer |
|
|
||||||
|-----------------|-------------|---------------------------------|
|
|
||||||
| Is Header | Bit 29 | 1 - is header | 0 - is footer |
|
|
||||||
|-----------------|-------------|---------------------------------|
|
|
||||||
| Undefined | Bits 28 - 3 | Undefined, must be zeroed |
|
|
||||||
|-----------------|-------------|---------------------------------|
|
|
||||||
| Encoding | Bits 2 - 1 | 00 - UTF-8 |
|
|
||||||
| | | 01 - Binary Data * |
|
|
||||||
| | | 10 - External Reference ** |
|
|
||||||
| | | 11 - Reserved |
|
|
||||||
|-----------------|-------------|---------------------------------|
|
|
||||||
| Read Only | Bit 0 | 1 - read only | 0 - read/write |
|
|
||||||
\=================================================================/
|
|
||||||
|
|
||||||
(*) Should be ignored by tools for editing text values
|
|
||||||
(**) Allowed external reference formats:
|
|
||||||
- http://host/directory/filename.ext
|
|
||||||
- ftp://host/directory/filename.ext
|
|
||||||
- filename.ext
|
|
||||||
- /directory/filename.ext
|
|
||||||
- DRIVE:/directory/filename.ext
|
|
||||||
|
|
||||||
Note: External references are also UTF-8 encoded.
|
|
||||||
|
|
||||||
================================================================================
|
|
||||||
= 4 - APE Tag Item Format
|
|
||||||
================================================================================
|
|
||||||
|
|
||||||
APE Tag Items are stored as key-value pairs. APE Tags Item Key are case
|
|
||||||
sensitive, however it is illegal to use keys which only differ in case and
|
|
||||||
it is recommended that tag reading not be case sensitive.
|
|
||||||
|
|
||||||
Every key can only occur (at most) once. It is not possible to repeat a key
|
|
||||||
to signify updated contents.
|
|
||||||
|
|
||||||
Tags can be partially or completely repeated in the streaming format. This
|
|
||||||
makes it possible to display an artist and / or title if it was missed at the
|
|
||||||
beginning of the stream. It is recommended that the important information like
|
|
||||||
artist, album and title should occur approximately every 2 minutes in the
|
|
||||||
stream and again 5 to 10 seconds before the end. However, care should be tak
|
|
||||||
en not to replicate this information too often or during passages with high
|
|
||||||
bitrate demands to avoid unnecessary drop-outs.
|
|
||||||
|
|
||||||
/==============================================================================\
|
|
||||||
| Content Size | 4 bytes | Length of the value in bytes |
|
|
||||||
|----------------|---------------|---------------------------------------------|
|
|
||||||
| Flags | 4 bytes | Item flags |
|
|
||||||
|----------------|---------------|---------------------------------------------|
|
|
||||||
| Key | 2 - 255 bytes | Item key |
|
|
||||||
|----------------|---------------|---------------------------------------------|
|
|
||||||
| Key Terminator | 1 byte | Null byte that indicates the end of the key |
|
|
||||||
|----------------|---------------|---------------------------------------------|
|
|
||||||
| Value | variable | Content (formatted according to the flags) |
|
|
||||||
\==============================================================================/
|
|
||||||
|
|
||||||
================================================================================
|
|
||||||
|
|
||||||
Sections 5 - 7 haven't yet been converted from:
|
|
||||||
|
|
||||||
http://www.personal.uni-jena.de/~pfk/mpp/sv8/apetag.html
|
|
|
@ -1,232 +0,0 @@
|
||||||
/***************************************************************************
|
|
||||||
copyright : (C) 2004 by Allan Sandfeld Jensen
|
|
||||||
(C) 2002, 2003 by Scott Wheeler (id3v2header.cpp)
|
|
||||||
email : kde@carewolf.org
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* 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 *
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <bitset>
|
|
||||||
|
|
||||||
#include <tstring.h>
|
|
||||||
#include <tdebug.h>
|
|
||||||
|
|
||||||
#include "apefooter.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
using namespace APE;
|
|
||||||
|
|
||||||
class Footer::FooterPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
FooterPrivate() : version(0),
|
|
||||||
footerPresent(true),
|
|
||||||
headerPresent(false),
|
|
||||||
isHeader(false),
|
|
||||||
itemCount(0),
|
|
||||||
tagSize(0) {}
|
|
||||||
|
|
||||||
~FooterPrivate() {}
|
|
||||||
|
|
||||||
uint version;
|
|
||||||
|
|
||||||
bool footerPresent;
|
|
||||||
bool headerPresent;
|
|
||||||
|
|
||||||
bool isHeader;
|
|
||||||
|
|
||||||
uint itemCount;
|
|
||||||
uint tagSize;
|
|
||||||
|
|
||||||
static const uint size = 32;
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// static members
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
TagLib::uint Footer::size()
|
|
||||||
{
|
|
||||||
return FooterPrivate::size;
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteVector Footer::fileIdentifier()
|
|
||||||
{
|
|
||||||
return ByteVector::fromCString("APETAGEX");
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// public members
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
Footer::Footer()
|
|
||||||
{
|
|
||||||
d = new FooterPrivate;
|
|
||||||
}
|
|
||||||
|
|
||||||
Footer::Footer(const ByteVector &data)
|
|
||||||
{
|
|
||||||
d = new FooterPrivate;
|
|
||||||
parse(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
Footer::~Footer()
|
|
||||||
{
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
TagLib::uint Footer::version() const
|
|
||||||
{
|
|
||||||
return d->version;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Footer::headerPresent() const
|
|
||||||
{
|
|
||||||
return d->headerPresent;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Footer::footerPresent() const
|
|
||||||
{
|
|
||||||
return d->footerPresent;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Footer::isHeader() const
|
|
||||||
{
|
|
||||||
return d->isHeader;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Footer::setHeaderPresent(bool b) const
|
|
||||||
{
|
|
||||||
d->headerPresent = b;
|
|
||||||
}
|
|
||||||
|
|
||||||
TagLib::uint Footer::itemCount() const
|
|
||||||
{
|
|
||||||
return d->itemCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Footer::setItemCount(uint s)
|
|
||||||
{
|
|
||||||
d->itemCount = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
TagLib::uint Footer::tagSize() const
|
|
||||||
{
|
|
||||||
return d->tagSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
TagLib::uint Footer::completeTagSize() const
|
|
||||||
{
|
|
||||||
if(d->headerPresent)
|
|
||||||
return d->tagSize + d->size;
|
|
||||||
else
|
|
||||||
return d->tagSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Footer::setTagSize(uint s)
|
|
||||||
{
|
|
||||||
d->tagSize = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Footer::setData(const ByteVector &data)
|
|
||||||
{
|
|
||||||
parse(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteVector Footer::renderFooter() const
|
|
||||||
{
|
|
||||||
return render(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteVector Footer::renderHeader() const
|
|
||||||
{
|
|
||||||
if (!d->headerPresent) return ByteVector();
|
|
||||||
|
|
||||||
return render(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// protected members
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
void Footer::parse(const ByteVector &data)
|
|
||||||
{
|
|
||||||
if(data.size() < size())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// The first eight bytes, data[0..7], are the File Identifier, "APETAGEX".
|
|
||||||
|
|
||||||
// Read the version number
|
|
||||||
|
|
||||||
d->version = data.mid(8, 4).toUInt(false);
|
|
||||||
|
|
||||||
// Read the tag size
|
|
||||||
|
|
||||||
d->tagSize = data.mid(12, 4).toUInt(false);
|
|
||||||
|
|
||||||
// Read the item count
|
|
||||||
|
|
||||||
d->itemCount = data.mid(16, 4).toUInt(false);
|
|
||||||
|
|
||||||
// Read the flags
|
|
||||||
|
|
||||||
std::bitset<32> flags(data.mid(20, 4).toUInt(false));
|
|
||||||
|
|
||||||
d->headerPresent = flags[31];
|
|
||||||
d->footerPresent = !flags[30];
|
|
||||||
d->isHeader = flags[29];
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteVector Footer::render(bool isHeader) const
|
|
||||||
{
|
|
||||||
ByteVector v;
|
|
||||||
|
|
||||||
// add the file identifier -- "APETAGEX"
|
|
||||||
|
|
||||||
v.append(fileIdentifier());
|
|
||||||
|
|
||||||
// add the version number -- we always render a 2.000 tag regardless of what
|
|
||||||
// the tag originally was.
|
|
||||||
|
|
||||||
v.append(ByteVector::fromUInt(2000, false));
|
|
||||||
|
|
||||||
// add the tag size
|
|
||||||
|
|
||||||
v.append(ByteVector::fromUInt(d->tagSize, false));
|
|
||||||
|
|
||||||
// add the item count
|
|
||||||
|
|
||||||
v.append(ByteVector::fromUInt(d->itemCount, false));
|
|
||||||
|
|
||||||
// render and add the flags
|
|
||||||
|
|
||||||
std::bitset<32> flags;
|
|
||||||
|
|
||||||
flags[31] = d->headerPresent;
|
|
||||||
flags[30] = false; // footer is always present
|
|
||||||
flags[29] = isHeader;
|
|
||||||
|
|
||||||
v.append(ByteVector::fromUInt(flags.to_ulong(), false));
|
|
||||||
|
|
||||||
// add the reserved 64bit
|
|
||||||
|
|
||||||
v.append(ByteVector::fromLongLong(0));
|
|
||||||
|
|
||||||
return v;
|
|
||||||
}
|
|
|
@ -1,168 +0,0 @@
|
||||||
/***************************************************************************
|
|
||||||
copyright : (C) 2004 by Allan Sandfeld Jensen
|
|
||||||
email : kde@carewolf.org
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* 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 *
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
#ifndef TAGLIB_APEFOOTER_H
|
|
||||||
#define TAGLIB_APEFOOTER_H
|
|
||||||
|
|
||||||
#include "tbytevector.h"
|
|
||||||
|
|
||||||
namespace TagLib {
|
|
||||||
|
|
||||||
namespace APE {
|
|
||||||
|
|
||||||
//! An implementation of APE footers
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* This class implements APE footers (and headers). It attempts to follow, both
|
|
||||||
* semantically and programatically, the structure specified in
|
|
||||||
* the APE v2.0 standard. The API is based on the properties of APE footer and
|
|
||||||
* headers specified there.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class Footer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/*!
|
|
||||||
* Constructs an empty APE footer.
|
|
||||||
*/
|
|
||||||
Footer();
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Constructs an APE footer based on \a data. parse() is called
|
|
||||||
* immediately.
|
|
||||||
*/
|
|
||||||
Footer(const ByteVector &data);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Destroys the footer.
|
|
||||||
*/
|
|
||||||
virtual ~Footer();
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the version number. (Note: This is the 1000 or 2000.)
|
|
||||||
*/
|
|
||||||
uint version() const;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns true if a header is present in the tag.
|
|
||||||
*/
|
|
||||||
bool headerPresent() const;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns true if a footer is present in the tag.
|
|
||||||
*/
|
|
||||||
bool footerPresent() const;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns true this is actually the header.
|
|
||||||
*/
|
|
||||||
bool isHeader() const;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Sets whether the header should be rendered or not
|
|
||||||
*/
|
|
||||||
void setHeaderPresent(bool b) const;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the number of items in the tag.
|
|
||||||
*/
|
|
||||||
uint itemCount() const;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Set the item count to \a s.
|
|
||||||
* \see itemCount()
|
|
||||||
*/
|
|
||||||
void setItemCount(uint s);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the tag size in bytes. This is the size of the frame content and footer.
|
|
||||||
* The size of the \e entire tag will be this plus the header size, if present.
|
|
||||||
*
|
|
||||||
* \see completeTagSize()
|
|
||||||
*/
|
|
||||||
uint tagSize() const;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the tag size, including if present, the header
|
|
||||||
* size.
|
|
||||||
*
|
|
||||||
* \see tagSize()
|
|
||||||
*/
|
|
||||||
uint completeTagSize() const;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Set the tag size to \a s.
|
|
||||||
* \see tagSize()
|
|
||||||
*/
|
|
||||||
void setTagSize(uint s);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the size of the footer. Presently this is always 32 bytes.
|
|
||||||
*/
|
|
||||||
static uint size();
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the string used to identify an APE tag inside of a file.
|
|
||||||
* Presently this is always "APETAGEX".
|
|
||||||
*/
|
|
||||||
static ByteVector fileIdentifier();
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Sets the data that will be used as the footer. 32 bytes,
|
|
||||||
* starting from \a data will be used.
|
|
||||||
*/
|
|
||||||
void setData(const ByteVector &data);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Renders the footer back to binary format.
|
|
||||||
*/
|
|
||||||
ByteVector renderFooter() const;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Renders the header corresponding to the footer. If headerPresent is
|
|
||||||
* set to false, it returns an empty ByteVector.
|
|
||||||
*/
|
|
||||||
ByteVector renderHeader() const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/*!
|
|
||||||
* Called by setData() to parse the footer data. It makes this information
|
|
||||||
* available through the public API.
|
|
||||||
*/
|
|
||||||
void parse(const ByteVector &data);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Called by renderFooter and renderHeader
|
|
||||||
*/
|
|
||||||
ByteVector render(bool isHeader) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Footer(const Footer &);
|
|
||||||
Footer &operator=(const Footer &);
|
|
||||||
|
|
||||||
class FooterPrivate;
|
|
||||||
FooterPrivate *d;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,220 +0,0 @@
|
||||||
/***************************************************************************
|
|
||||||
copyright : (C) 2004 by Allan Sandfeld Jensen
|
|
||||||
email : kde@carewolf.com
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* 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 *
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
#include <tbytevectorlist.h>
|
|
||||||
#include <tdebug.h>
|
|
||||||
|
|
||||||
#include "apeitem.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
using namespace APE;
|
|
||||||
|
|
||||||
class APE::Item::ItemPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ItemPrivate() : type(Text), readOnly(false) {}
|
|
||||||
|
|
||||||
Item::ItemTypes type;
|
|
||||||
String key;
|
|
||||||
ByteVector value;
|
|
||||||
StringList text;
|
|
||||||
bool readOnly;
|
|
||||||
};
|
|
||||||
|
|
||||||
APE::Item::Item()
|
|
||||||
{
|
|
||||||
d = new ItemPrivate;
|
|
||||||
}
|
|
||||||
|
|
||||||
APE::Item::Item(const String &key, const String &value)
|
|
||||||
{
|
|
||||||
d = new ItemPrivate;
|
|
||||||
d->key = key;
|
|
||||||
d->text.append(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
APE::Item::Item(const String &key, const StringList &values)
|
|
||||||
{
|
|
||||||
d = new ItemPrivate;
|
|
||||||
d->key = key;
|
|
||||||
d->text = values;
|
|
||||||
}
|
|
||||||
|
|
||||||
APE::Item::Item(const Item &item)
|
|
||||||
{
|
|
||||||
d = new ItemPrivate(*item.d);
|
|
||||||
}
|
|
||||||
|
|
||||||
APE::Item::~Item()
|
|
||||||
{
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
Item &APE::Item::operator=(const Item &item)
|
|
||||||
{
|
|
||||||
delete d;
|
|
||||||
d = new ItemPrivate(*item.d);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void APE::Item::setReadOnly(bool readOnly)
|
|
||||||
{
|
|
||||||
d->readOnly = readOnly;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool APE::Item::isReadOnly() const
|
|
||||||
{
|
|
||||||
return d->readOnly;
|
|
||||||
}
|
|
||||||
|
|
||||||
void APE::Item::setType(APE::Item::ItemTypes val)
|
|
||||||
{
|
|
||||||
d->type = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
APE::Item::ItemTypes APE::Item::type() const
|
|
||||||
{
|
|
||||||
return d->type;
|
|
||||||
}
|
|
||||||
|
|
||||||
String APE::Item::key() const
|
|
||||||
{
|
|
||||||
return d->key;
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteVector APE::Item::value() const
|
|
||||||
{
|
|
||||||
// This seems incorrect as it won't be actually rendering the value to keep it
|
|
||||||
// up to date.
|
|
||||||
|
|
||||||
return d->value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void APE::Item::setKey(const String &key)
|
|
||||||
{
|
|
||||||
d->key = key;
|
|
||||||
}
|
|
||||||
|
|
||||||
void APE::Item::setValue(const String &value)
|
|
||||||
{
|
|
||||||
d->text = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void APE::Item::setValues(const StringList &value)
|
|
||||||
{
|
|
||||||
d->text = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void APE::Item::appendValue(const String &value)
|
|
||||||
{
|
|
||||||
d->text.append(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void APE::Item::appendValues(const StringList &values)
|
|
||||||
{
|
|
||||||
d->text.append(values);
|
|
||||||
}
|
|
||||||
|
|
||||||
int APE::Item::size() const
|
|
||||||
{
|
|
||||||
return 8 + d->key.size() + 1 + d->value.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
StringList APE::Item::toStringList() const
|
|
||||||
{
|
|
||||||
return d->text;
|
|
||||||
}
|
|
||||||
|
|
||||||
String APE::Item::toString() const
|
|
||||||
{
|
|
||||||
return isEmpty() ? String::null : d->text.front();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool APE::Item::isEmpty() const
|
|
||||||
{
|
|
||||||
switch(d->type) {
|
|
||||||
case 0:
|
|
||||||
case 1:
|
|
||||||
if(d->text.isEmpty())
|
|
||||||
return true;
|
|
||||||
if(d->text.size() == 1 && d->text.front().isEmpty())
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
case 2:
|
|
||||||
return d->value.isEmpty();
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void APE::Item::parse(const ByteVector &data)
|
|
||||||
{
|
|
||||||
// 11 bytes is the minimum size for an APE item
|
|
||||||
|
|
||||||
if(data.size() < 11) {
|
|
||||||
debug("APE::Item::parse() -- no data in item");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint valueLength = data.mid(0, 4).toUInt(false);
|
|
||||||
uint flags = data.mid(4, 4).toUInt(false);
|
|
||||||
|
|
||||||
d->key = String(data.mid(8), String::UTF8);
|
|
||||||
|
|
||||||
d->value = data.mid(8 + d->key.size() + 1, valueLength);
|
|
||||||
|
|
||||||
setReadOnly(flags & 1);
|
|
||||||
setType(ItemTypes((flags >> 1) & 3));
|
|
||||||
|
|
||||||
if(int(d->type) < 2)
|
|
||||||
d->text = StringList(ByteVectorList::split(d->value, '\0'), String::UTF8);
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteVector APE::Item::render() const
|
|
||||||
{
|
|
||||||
ByteVector data;
|
|
||||||
TagLib::uint flags = ((d->readOnly) ? 1 : 0) | (d->type << 1);
|
|
||||||
ByteVector value;
|
|
||||||
|
|
||||||
if(isEmpty())
|
|
||||||
return data;
|
|
||||||
|
|
||||||
if(d->type != Item::Binary) {
|
|
||||||
StringList::ConstIterator it = d->text.begin();
|
|
||||||
value.append(it->data(String::UTF8));
|
|
||||||
it++;
|
|
||||||
for(; it != d->text.end(); ++it) {
|
|
||||||
value.append('\0');
|
|
||||||
value.append(it->data(String::UTF8));
|
|
||||||
}
|
|
||||||
d->value = value;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
value.append(d->value);
|
|
||||||
|
|
||||||
data.append(ByteVector::fromUInt(value.size(), false));
|
|
||||||
data.append(ByteVector::fromUInt(flags, false));
|
|
||||||
data.append(d->key.data(String::UTF8));
|
|
||||||
data.append(ByteVector('\0'));
|
|
||||||
data.append(value);
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
|
@ -1,193 +0,0 @@
|
||||||
/***************************************************************************
|
|
||||||
copyright : (C) 2004 by Allan Sandfeld Jensen
|
|
||||||
email : kde@carewolf.org
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* 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 *
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
#ifndef TAGLIB_APEITEM_H
|
|
||||||
#define TAGLIB_APEITEM_H
|
|
||||||
|
|
||||||
#include "tbytevector.h"
|
|
||||||
#include "tstring.h"
|
|
||||||
#include "tstringlist.h"
|
|
||||||
|
|
||||||
namespace TagLib {
|
|
||||||
|
|
||||||
namespace APE {
|
|
||||||
|
|
||||||
//! An implementation of APE-items
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* This class provides the features of items in the APEv2 standard.
|
|
||||||
*/
|
|
||||||
class Item
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/*!
|
|
||||||
* Enum of types an Item can have. The value of 3 is reserved.
|
|
||||||
*/
|
|
||||||
enum ItemTypes {
|
|
||||||
//! Item contains text information coded in UTF-8
|
|
||||||
Text = 0,
|
|
||||||
//! Item contains binary information
|
|
||||||
Binary = 1,
|
|
||||||
//! Item is a locator of external stored information
|
|
||||||
Locator = 2
|
|
||||||
};
|
|
||||||
/*!
|
|
||||||
* Constructs an empty item.
|
|
||||||
*/
|
|
||||||
Item();
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Constructs an item with \a key and \a value.
|
|
||||||
*/
|
|
||||||
Item(const String &key, const String &value);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Constructs an item with \a key and \a values.
|
|
||||||
*/
|
|
||||||
Item(const String &key, const StringList &values);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Construct an item as a copy of \a item.
|
|
||||||
*/
|
|
||||||
Item(const Item &item);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Destroys the item.
|
|
||||||
*/
|
|
||||||
virtual ~Item();
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Copies the contents of \a item into this item.
|
|
||||||
*/
|
|
||||||
Item &operator=(const Item &item);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the key.
|
|
||||||
*/
|
|
||||||
String key() const;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the binary value.
|
|
||||||
*
|
|
||||||
* \deprecated This will be removed in the next binary incompatible version
|
|
||||||
* as it is not kept in sync with the things that are set using setValue()
|
|
||||||
* and friends.
|
|
||||||
*/
|
|
||||||
ByteVector value() const;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Sets the key for the item to \a key.
|
|
||||||
*/
|
|
||||||
void setKey(const String &key);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Sets the value of the item to \a value and clears any previous contents.
|
|
||||||
*
|
|
||||||
* \see toString()
|
|
||||||
*/
|
|
||||||
void setValue(const String &value);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Sets the value of the item to the list of values in \a value and clears
|
|
||||||
* any previous contents.
|
|
||||||
*
|
|
||||||
* \see toStringList()
|
|
||||||
*/
|
|
||||||
void setValues(const StringList &values);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Appends \a value to create (or extend) the current list of values.
|
|
||||||
*
|
|
||||||
* \see toString()
|
|
||||||
*/
|
|
||||||
void appendValue(const String &value);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Appends \a values to extend the current list of values.
|
|
||||||
*
|
|
||||||
* \see toStringList()
|
|
||||||
*/
|
|
||||||
void appendValues(const StringList &values);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the size of the full item.
|
|
||||||
*/
|
|
||||||
int size() const;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the value as a single string. In case of multiple strings,
|
|
||||||
* the first is returned.
|
|
||||||
*/
|
|
||||||
String toString() const;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the value as a string list.
|
|
||||||
*/
|
|
||||||
StringList toStringList() const;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Render the item to a ByteVector.
|
|
||||||
*/
|
|
||||||
ByteVector render() const;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Parse the item from the ByteVector \a data.
|
|
||||||
*/
|
|
||||||
void parse(const ByteVector& data);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Set the item to read-only.
|
|
||||||
*/
|
|
||||||
void setReadOnly(bool readOnly);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Return true if the item is read-only.
|
|
||||||
*/
|
|
||||||
bool isReadOnly() const;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Sets the type of the item to \a type.
|
|
||||||
*
|
|
||||||
* \see ItemTypes
|
|
||||||
*/
|
|
||||||
void setType(ItemTypes type);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the type of the item.
|
|
||||||
*/
|
|
||||||
ItemTypes type() const;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns if the item has any real content.
|
|
||||||
*/
|
|
||||||
bool isEmpty() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
class ItemPrivate;
|
|
||||||
ItemPrivate *d;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
|
@ -1,263 +0,0 @@
|
||||||
/***************************************************************************
|
|
||||||
copyright : (C) 2004 by Allan Sandfeld Jensen
|
|
||||||
email : kde@carewolf.com
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* 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 *
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
#ifdef __SUNPRO_CC
|
|
||||||
// Sun Studio finds multiple specializations of Map because
|
|
||||||
// it considers specializations with and without class types
|
|
||||||
// to be different; this define forces Map to use only the
|
|
||||||
// specialization with the class keyword.
|
|
||||||
#define WANT_CLASS_INSTANTIATION_OF_MAP (1)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <tdebug.h>
|
|
||||||
#include <tfile.h>
|
|
||||||
#include <tstring.h>
|
|
||||||
#include <tmap.h>
|
|
||||||
|
|
||||||
#include "apetag.h"
|
|
||||||
#include "apefooter.h"
|
|
||||||
#include "apeitem.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
using namespace APE;
|
|
||||||
|
|
||||||
class APE::Tag::TagPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TagPrivate() : file(0), tagOffset(-1), tagLength(0) {}
|
|
||||||
|
|
||||||
File *file;
|
|
||||||
long tagOffset;
|
|
||||||
long tagLength;
|
|
||||||
|
|
||||||
Footer footer;
|
|
||||||
|
|
||||||
ItemListMap itemListMap;
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// public methods
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
APE::Tag::Tag() : TagLib::Tag()
|
|
||||||
{
|
|
||||||
d = new TagPrivate;
|
|
||||||
}
|
|
||||||
|
|
||||||
APE::Tag::Tag(File *file, long tagOffset) : TagLib::Tag()
|
|
||||||
{
|
|
||||||
d = new TagPrivate;
|
|
||||||
d->file = file;
|
|
||||||
d->tagOffset = tagOffset;
|
|
||||||
|
|
||||||
read();
|
|
||||||
}
|
|
||||||
|
|
||||||
APE::Tag::~Tag()
|
|
||||||
{
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteVector APE::Tag::fileIdentifier()
|
|
||||||
{
|
|
||||||
return ByteVector::fromCString("APETAGEX");
|
|
||||||
}
|
|
||||||
|
|
||||||
String APE::Tag::title() const
|
|
||||||
{
|
|
||||||
if(d->itemListMap["TITLE"].isEmpty())
|
|
||||||
return String::null;
|
|
||||||
return d->itemListMap["TITLE"].toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
String APE::Tag::artist() const
|
|
||||||
{
|
|
||||||
if(d->itemListMap["ARTIST"].isEmpty())
|
|
||||||
return String::null;
|
|
||||||
return d->itemListMap["ARTIST"].toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
String APE::Tag::album() const
|
|
||||||
{
|
|
||||||
if(d->itemListMap["ALBUM"].isEmpty())
|
|
||||||
return String::null;
|
|
||||||
return d->itemListMap["ALBUM"].toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
String APE::Tag::comment() const
|
|
||||||
{
|
|
||||||
if(d->itemListMap["COMMENT"].isEmpty())
|
|
||||||
return String::null;
|
|
||||||
return d->itemListMap["COMMENT"].toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
String APE::Tag::genre() const
|
|
||||||
{
|
|
||||||
if(d->itemListMap["GENRE"].isEmpty())
|
|
||||||
return String::null;
|
|
||||||
return d->itemListMap["GENRE"].toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
TagLib::uint APE::Tag::year() const
|
|
||||||
{
|
|
||||||
if(d->itemListMap["YEAR"].isEmpty())
|
|
||||||
return 0;
|
|
||||||
return d->itemListMap["YEAR"].toString().toInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
TagLib::uint APE::Tag::track() const
|
|
||||||
{
|
|
||||||
if(d->itemListMap["TRACK"].isEmpty())
|
|
||||||
return 0;
|
|
||||||
return d->itemListMap["TRACK"].toString().toInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
void APE::Tag::setTitle(const String &s)
|
|
||||||
{
|
|
||||||
addValue("TITLE", s, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void APE::Tag::setArtist(const String &s)
|
|
||||||
{
|
|
||||||
addValue("ARTIST", s, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void APE::Tag::setAlbum(const String &s)
|
|
||||||
{
|
|
||||||
addValue("ALBUM", s, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void APE::Tag::setComment(const String &s)
|
|
||||||
{
|
|
||||||
addValue("COMMENT", s, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void APE::Tag::setGenre(const String &s)
|
|
||||||
{
|
|
||||||
addValue("GENRE", s, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void APE::Tag::setYear(uint i)
|
|
||||||
{
|
|
||||||
if(i <= 0)
|
|
||||||
removeItem("YEAR");
|
|
||||||
else
|
|
||||||
addValue("YEAR", String::number(i), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void APE::Tag::setTrack(uint i)
|
|
||||||
{
|
|
||||||
if(i <= 0)
|
|
||||||
removeItem("TRACK");
|
|
||||||
else
|
|
||||||
addValue("TRACK", String::number(i), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
APE::Footer *APE::Tag::footer() const
|
|
||||||
{
|
|
||||||
return &d->footer;
|
|
||||||
}
|
|
||||||
|
|
||||||
const APE::ItemListMap& APE::Tag::itemListMap() const
|
|
||||||
{
|
|
||||||
return d->itemListMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
void APE::Tag::removeItem(const String &key)
|
|
||||||
{
|
|
||||||
Map<const String, Item>::Iterator it = d->itemListMap.find(key.upper());
|
|
||||||
if(it != d->itemListMap.end())
|
|
||||||
d->itemListMap.erase(it);
|
|
||||||
}
|
|
||||||
|
|
||||||
void APE::Tag::addValue(const String &key, const String &value, bool replace)
|
|
||||||
{
|
|
||||||
if(replace)
|
|
||||||
removeItem(key);
|
|
||||||
if(!value.isEmpty()) {
|
|
||||||
if(d->itemListMap.contains(key) || !replace)
|
|
||||||
d->itemListMap[key.upper()].appendValue(value);
|
|
||||||
else
|
|
||||||
setItem(key, Item(key, value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void APE::Tag::setItem(const String &key, const Item &item)
|
|
||||||
{
|
|
||||||
d->itemListMap.insert(key.upper(), item);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// protected methods
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
void APE::Tag::read()
|
|
||||||
{
|
|
||||||
if(d->file && d->file->isValid()) {
|
|
||||||
|
|
||||||
d->file->seek(d->tagOffset);
|
|
||||||
d->footer.setData(d->file->readBlock(Footer::size()));
|
|
||||||
|
|
||||||
if(d->footer.tagSize() == 0 ||
|
|
||||||
d->footer.tagSize() > uint(d->file->length()))
|
|
||||||
return;
|
|
||||||
|
|
||||||
d->file->seek(d->tagOffset + Footer::size() - d->footer.tagSize());
|
|
||||||
parse(d->file->readBlock(d->footer.tagSize() - Footer::size()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteVector APE::Tag::render() const
|
|
||||||
{
|
|
||||||
ByteVector data;
|
|
||||||
uint itemCount = 0;
|
|
||||||
|
|
||||||
{
|
|
||||||
for(Map<const String, Item>::ConstIterator it = d->itemListMap.begin();
|
|
||||||
it != d->itemListMap.end(); ++it)
|
|
||||||
{
|
|
||||||
data.append(it->second.render());
|
|
||||||
itemCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
d->footer.setItemCount(itemCount);
|
|
||||||
d->footer.setTagSize(data.size()+Footer::size());
|
|
||||||
d->footer.setHeaderPresent(true);
|
|
||||||
|
|
||||||
return d->footer.renderHeader() + data + d->footer.renderFooter();
|
|
||||||
}
|
|
||||||
|
|
||||||
void APE::Tag::parse(const ByteVector &data)
|
|
||||||
{
|
|
||||||
uint pos = 0;
|
|
||||||
|
|
||||||
// 11 bytes is the minimum size for an APE item
|
|
||||||
|
|
||||||
for(uint i = 0; i < d->footer.itemCount() && pos <= data.size() - 11; i++) {
|
|
||||||
APE::Item item;
|
|
||||||
item.parse(data.mid(pos));
|
|
||||||
|
|
||||||
d->itemListMap.insert(item.key().upper(), item);
|
|
||||||
|
|
||||||
pos += item.size();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,157 +0,0 @@
|
||||||
/***************************************************************************
|
|
||||||
copyright : (C) 2004 by Allan Sandfeld Jensen
|
|
||||||
email : kde@carewolf.org
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* 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 *
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
#ifndef TAGLIB_APETAG_H
|
|
||||||
#define TAGLIB_APETAG_H
|
|
||||||
|
|
||||||
#include "tag.h"
|
|
||||||
#include "tbytevector.h"
|
|
||||||
#include "tmap.h"
|
|
||||||
#include "tstring.h"
|
|
||||||
|
|
||||||
#include "apeitem.h"
|
|
||||||
|
|
||||||
namespace TagLib {
|
|
||||||
|
|
||||||
class File;
|
|
||||||
|
|
||||||
//! An implementation of the APE tagging format
|
|
||||||
|
|
||||||
namespace APE {
|
|
||||||
|
|
||||||
class Footer;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* A mapping between a list of item names, or keys, and the associated item.
|
|
||||||
*
|
|
||||||
* \see APE::Tag::itemListMap()
|
|
||||||
*/
|
|
||||||
typedef Map<const String, Item> ItemListMap;
|
|
||||||
|
|
||||||
|
|
||||||
//! An APE tag implementation
|
|
||||||
|
|
||||||
class Tag : public TagLib::Tag
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/*!
|
|
||||||
* Create an APE tag with default values.
|
|
||||||
*/
|
|
||||||
Tag();
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Create an APE tag and parse the data in \a file with APE footer at
|
|
||||||
* \a tagOffset.
|
|
||||||
*/
|
|
||||||
Tag(File *file, long tagOffset);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Destroys this Tag instance.
|
|
||||||
*/
|
|
||||||
virtual ~Tag();
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Renders the in memory values to a ByteVector suitable for writing to
|
|
||||||
* the file.
|
|
||||||
*/
|
|
||||||
ByteVector render() const;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the string "APETAGEX" suitable for usage in locating the tag in a
|
|
||||||
* file.
|
|
||||||
*/
|
|
||||||
static ByteVector fileIdentifier();
|
|
||||||
|
|
||||||
// Reimplementations.
|
|
||||||
|
|
||||||
virtual String title() const;
|
|
||||||
virtual String artist() const;
|
|
||||||
virtual String album() const;
|
|
||||||
virtual String comment() const;
|
|
||||||
virtual String genre() const;
|
|
||||||
virtual uint year() const;
|
|
||||||
virtual uint track() const;
|
|
||||||
|
|
||||||
virtual void setTitle(const String &s);
|
|
||||||
virtual void setArtist(const String &s);
|
|
||||||
virtual void setAlbum(const String &s);
|
|
||||||
virtual void setComment(const String &s);
|
|
||||||
virtual void setGenre(const String &s);
|
|
||||||
virtual void setYear(uint i);
|
|
||||||
virtual void setTrack(uint i);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns a pointer to the tag's footer.
|
|
||||||
*/
|
|
||||||
Footer *footer() const;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns a reference to the item list map. This is an ItemListMap of
|
|
||||||
* all of the items in the tag.
|
|
||||||
*
|
|
||||||
* This is the most powerfull structure for accessing the items of the tag.
|
|
||||||
*
|
|
||||||
* \warning You should not modify this data structure directly, instead
|
|
||||||
* use setItem() and removeItem().
|
|
||||||
*/
|
|
||||||
const ItemListMap &itemListMap() const;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Removes the \a key item from the tag
|
|
||||||
*/
|
|
||||||
void removeItem(const String &key);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Adds to the item specified by \a key the data \a value. If \a replace
|
|
||||||
* is true, then all of the other values on the same key will be removed
|
|
||||||
* first.
|
|
||||||
*/
|
|
||||||
void addValue(const String &key, const String &value, bool replace = true);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Sets the \a key item to the value of \a item. If an item with the \a key is already
|
|
||||||
* present, it will be replaced.
|
|
||||||
*/
|
|
||||||
void setItem(const String &key, const Item &item);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Reads from the file specified in the constructor.
|
|
||||||
*/
|
|
||||||
void read();
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Parses the body of the tag in \a data.
|
|
||||||
*/
|
|
||||||
void parse(const ByteVector &data);
|
|
||||||
|
|
||||||
private:
|
|
||||||
Tag(const Tag &);
|
|
||||||
Tag &operator=(const Tag &);
|
|
||||||
|
|
||||||
class TagPrivate;
|
|
||||||
TagPrivate *d;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,47 +0,0 @@
|
||||||
/***************************************************************************
|
|
||||||
copyright : (C) 2003 by Scott Wheeler
|
|
||||||
email : wheeler@kde.org
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* 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 *
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
#include "audioproperties.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
|
|
||||||
class AudioProperties::AudioPropertiesPrivate
|
|
||||||
{
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// public methods
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
AudioProperties::~AudioProperties()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// protected methods
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
AudioProperties::AudioProperties(ReadStyle)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,106 +0,0 @@
|
||||||
/***************************************************************************
|
|
||||||
copyright : (C) 2003 by Scott Wheeler
|
|
||||||
email : wheeler@kde.org
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* 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 *
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
#ifndef TAGLIB_AUDIOPROPERTIES_H
|
|
||||||
#define TAGLIB_AUDIOPROPERTIES_H
|
|
||||||
|
|
||||||
#include "taglib_export.h"
|
|
||||||
|
|
||||||
namespace TagLib {
|
|
||||||
|
|
||||||
//! A simple, abstract interface to common audio properties
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* The values here are common to most audio formats. For more specific, codec
|
|
||||||
* dependant values, please see see the subclasses APIs. This is meant to
|
|
||||||
* compliment the TagLib::File and TagLib::Tag APIs in providing a simple
|
|
||||||
* interface that is sufficient for most applications.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class TAGLIB_EXPORT AudioProperties
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Reading audio properties from a file can sometimes be very time consuming
|
|
||||||
* and for the most accurate results can often involve reading the entire
|
|
||||||
* file. Because in many situations speed is critical or the accuracy of the
|
|
||||||
* values is not particularly important this allows the level of desired
|
|
||||||
* accuracy to be set.
|
|
||||||
*/
|
|
||||||
enum ReadStyle {
|
|
||||||
//! Read as little of the file as possible
|
|
||||||
Fast,
|
|
||||||
//! Read more of the file and make better values guesses
|
|
||||||
Average,
|
|
||||||
//! Read as much of the file as needed to report accurate values
|
|
||||||
Accurate
|
|
||||||
};
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Destroys this AudioProperties instance.
|
|
||||||
*/
|
|
||||||
virtual ~AudioProperties();
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the length of the file in seconds.
|
|
||||||
*/
|
|
||||||
virtual int length() const = 0;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the most appropriate bit rate for the file in kb/s. For constant
|
|
||||||
* bitrate formats this is simply the bitrate of the file. For variable
|
|
||||||
* bitrate formats this is either the average or nominal bitrate.
|
|
||||||
*/
|
|
||||||
virtual int bitrate() const = 0;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the sample rate in Hz.
|
|
||||||
*/
|
|
||||||
virtual int sampleRate() const = 0;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the number of audio channels.
|
|
||||||
*/
|
|
||||||
virtual int channels() const = 0;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Construct an audio properties instance. This is protected as this class
|
|
||||||
* should not be instantiated directly, but should be instantiated via its
|
|
||||||
* subclasses and can be fetched from the FileRef or File APIs.
|
|
||||||
*
|
|
||||||
* \see ReadStyle
|
|
||||||
*/
|
|
||||||
AudioProperties(ReadStyle style);
|
|
||||||
|
|
||||||
private:
|
|
||||||
AudioProperties(const AudioProperties &);
|
|
||||||
AudioProperties &operator=(const AudioProperties &);
|
|
||||||
|
|
||||||
class AudioPropertiesPrivate;
|
|
||||||
AudioPropertiesPrivate *d;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,184 +0,0 @@
|
||||||
/***************************************************************************
|
|
||||||
copyright : (C) 2003 by Scott Wheeler
|
|
||||||
email : wheeler@kde.org
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* 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 *
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
#include <tfile.h>
|
|
||||||
#include <tstring.h>
|
|
||||||
|
|
||||||
#include "fileref.h"
|
|
||||||
#include "mpegfile.h"
|
|
||||||
#include "vorbisfile.h"
|
|
||||||
#include "flacfile.h"
|
|
||||||
#include "mpcfile.h"
|
|
||||||
#include "mp4file.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
|
|
||||||
class FileRef::FileRefPrivate : public RefCounter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
FileRefPrivate(File *f) : RefCounter(), file(f) {}
|
|
||||||
~FileRefPrivate() {
|
|
||||||
delete file;
|
|
||||||
}
|
|
||||||
|
|
||||||
File *file;
|
|
||||||
static List<const FileTypeResolver *> fileTypeResolvers;
|
|
||||||
};
|
|
||||||
|
|
||||||
List<const FileRef::FileTypeResolver *> FileRef::FileRefPrivate::fileTypeResolvers;
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// public members
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
FileRef::FileRef()
|
|
||||||
{
|
|
||||||
d = new FileRefPrivate(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
FileRef::FileRef(const char *fileName, bool readAudioProperties,
|
|
||||||
AudioProperties::ReadStyle audioPropertiesStyle)
|
|
||||||
{
|
|
||||||
d = new FileRefPrivate(create(fileName, readAudioProperties, audioPropertiesStyle));
|
|
||||||
}
|
|
||||||
|
|
||||||
FileRef::FileRef(File *file)
|
|
||||||
{
|
|
||||||
d = new FileRefPrivate(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
FileRef::FileRef(const FileRef &ref) : d(ref.d)
|
|
||||||
{
|
|
||||||
d->ref();
|
|
||||||
}
|
|
||||||
|
|
||||||
FileRef::~FileRef()
|
|
||||||
{
|
|
||||||
if(d->deref())
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
Tag *FileRef::tag() const
|
|
||||||
{
|
|
||||||
return d->file->tag();
|
|
||||||
}
|
|
||||||
|
|
||||||
AudioProperties *FileRef::audioProperties() const
|
|
||||||
{
|
|
||||||
return d->file->audioProperties();
|
|
||||||
}
|
|
||||||
|
|
||||||
File *FileRef::file() const
|
|
||||||
{
|
|
||||||
return d->file;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FileRef::save()
|
|
||||||
{
|
|
||||||
return d->file->save();
|
|
||||||
}
|
|
||||||
|
|
||||||
const FileRef::FileTypeResolver *FileRef::addFileTypeResolver(const FileRef::FileTypeResolver *resolver) // static
|
|
||||||
{
|
|
||||||
FileRefPrivate::fileTypeResolvers.prepend(resolver);
|
|
||||||
return resolver;
|
|
||||||
}
|
|
||||||
|
|
||||||
StringList FileRef::defaultFileExtensions()
|
|
||||||
{
|
|
||||||
StringList l;
|
|
||||||
|
|
||||||
l.append("ogg");
|
|
||||||
l.append("flac");
|
|
||||||
l.append("mp3");
|
|
||||||
l.append("mpc");
|
|
||||||
l.append("m4a");
|
|
||||||
//l.append("m4p");
|
|
||||||
|
|
||||||
return l;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FileRef::isNull() const
|
|
||||||
{
|
|
||||||
return !d->file || !d->file->isValid();
|
|
||||||
}
|
|
||||||
|
|
||||||
FileRef &FileRef::operator=(const FileRef &ref)
|
|
||||||
{
|
|
||||||
if(&ref == this)
|
|
||||||
return *this;
|
|
||||||
|
|
||||||
if(d->deref())
|
|
||||||
delete d;
|
|
||||||
|
|
||||||
d = ref.d;
|
|
||||||
d->ref();
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FileRef::operator==(const FileRef &ref) const
|
|
||||||
{
|
|
||||||
return ref.d->file == d->file;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FileRef::operator!=(const FileRef &ref) const
|
|
||||||
{
|
|
||||||
return ref.d->file != d->file;
|
|
||||||
}
|
|
||||||
|
|
||||||
File *FileRef::create(const char *fileName, bool readAudioProperties,
|
|
||||||
AudioProperties::ReadStyle audioPropertiesStyle) // static
|
|
||||||
{
|
|
||||||
|
|
||||||
List<const FileTypeResolver *>::ConstIterator it = FileRefPrivate::fileTypeResolvers.begin();
|
|
||||||
|
|
||||||
for(; it != FileRefPrivate::fileTypeResolvers.end(); ++it) {
|
|
||||||
File *file = (*it)->createFile(fileName, readAudioProperties, audioPropertiesStyle);
|
|
||||||
if(file)
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ok, this is really dumb for now, but it works for testing.
|
|
||||||
|
|
||||||
String s = fileName;
|
|
||||||
|
|
||||||
// If this list is updated, the method defaultFileExtensions() should also be
|
|
||||||
// updated. However at some point that list should be created at the same time
|
|
||||||
// that a default file type resolver is created.
|
|
||||||
|
|
||||||
if(s.size() > 4) {
|
|
||||||
if(s.substr(s.size() - 4, 4).upper() == ".OGG")
|
|
||||||
return new Vorbis::File(fileName, readAudioProperties, audioPropertiesStyle);
|
|
||||||
if(s.substr(s.size() - 4, 4).upper() == ".MP3")
|
|
||||||
return new MPEG::File(fileName, readAudioProperties, audioPropertiesStyle);
|
|
||||||
if(s.substr(s.size() - 5, 5).upper() == ".FLAC")
|
|
||||||
return new FLAC::File(fileName, readAudioProperties, audioPropertiesStyle);
|
|
||||||
if(s.substr(s.size() - 4, 4).upper() == ".MPC")
|
|
||||||
return new MPC::File(fileName, readAudioProperties, audioPropertiesStyle);
|
|
||||||
if(s.substr(s.size() - 4, 4).upper() == ".M4A")
|
|
||||||
return new MP4::File(fileName, readAudioProperties, audioPropertiesStyle);
|
|
||||||
//if(s.substr(s.size() - 4, 4).upper() == ".M4P")
|
|
||||||
//return new MP4::File(fileName, readAudioProperties, audioPropertiesStyle);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,256 +0,0 @@
|
||||||
/***************************************************************************
|
|
||||||
copyright : (C) 2003 by Scott Wheeler
|
|
||||||
email : wheeler@kde.org
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* 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 *
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
#ifndef TAGLIB_FILEREF_H
|
|
||||||
#define TAGLIB_FILEREF_H
|
|
||||||
|
|
||||||
#include "tstringlist.h"
|
|
||||||
|
|
||||||
#include "taglib_export.h"
|
|
||||||
#include "audioproperties.h"
|
|
||||||
|
|
||||||
namespace TagLib {
|
|
||||||
|
|
||||||
class String;
|
|
||||||
class File;
|
|
||||||
class Tag;
|
|
||||||
|
|
||||||
//! This class provides a simple abstraction for creating and handling files
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* FileRef exists to provide a minimal, generic and value-based wrapper around
|
|
||||||
* a File. It is lightweight and implicitly shared, and as such suitable for
|
|
||||||
* pass-by-value use. This hides some of the uglier details of TagLib::File
|
|
||||||
* and the non-generic portions of the concrete file implementations.
|
|
||||||
*
|
|
||||||
* This class is useful in a "simple usage" situation where it is desirable
|
|
||||||
* to be able to get and set some of the tag information that is similar
|
|
||||||
* across file types.
|
|
||||||
*
|
|
||||||
* Also note that it is probably a good idea to plug this into your mime
|
|
||||||
* type system rather than using the constructor that accepts a file name using
|
|
||||||
* the FileTypeResolver.
|
|
||||||
*
|
|
||||||
* \see FileTypeResolver
|
|
||||||
* \see addFileTypeResolver()
|
|
||||||
*/
|
|
||||||
|
|
||||||
class TAGLIB_EXPORT FileRef
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
//! A class for pluggable file type resolution.
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* This class is used to add extend TagLib's very basic file name based file
|
|
||||||
* type resolution.
|
|
||||||
*
|
|
||||||
* This can be accomplished with:
|
|
||||||
*
|
|
||||||
* \code
|
|
||||||
*
|
|
||||||
* class MyFileTypeResolver : FileTypeResolver
|
|
||||||
* {
|
|
||||||
* TagLib::File *createFile(const char *fileName, bool, AudioProperties::ReadStyle)
|
|
||||||
* {
|
|
||||||
* if(someCheckForAnMP3File(fileName))
|
|
||||||
* return new TagLib::MPEG::File(fileName);
|
|
||||||
* return 0;
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* FileRef::addFileTypeResolver(new MyFileTypeResolver);
|
|
||||||
*
|
|
||||||
* \endcode
|
|
||||||
*
|
|
||||||
* Naturally a less contrived example would be slightly more complex. This
|
|
||||||
* can be used to plug in mime-type detection systems or to add new file types
|
|
||||||
* to TagLib.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class FileTypeResolver
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/*!
|
|
||||||
* This method must be overridden to provide an additional file type
|
|
||||||
* resolver. If the resolver is able to determine the file type it should
|
|
||||||
* return a valid File object; if not it should return 0.
|
|
||||||
*
|
|
||||||
* \note The created file is then owned by the FileRef and should not be
|
|
||||||
* deleted. Deletion will happen automatically when the FileRef passes
|
|
||||||
* out of scope.
|
|
||||||
*/
|
|
||||||
virtual File *createFile(const char *fileName,
|
|
||||||
bool readAudioProperties = true,
|
|
||||||
AudioProperties::ReadStyle
|
|
||||||
audioPropertiesStyle = AudioProperties::Average) const = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Creates a null FileRef.
|
|
||||||
*/
|
|
||||||
FileRef();
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Create a FileRef from \a fileName. If \a readAudioProperties is true then
|
|
||||||
* the audio properties will be read using \a audioPropertiesStyle. If
|
|
||||||
* \a readAudioProperties is false then \a audioPropertiesStyle will be
|
|
||||||
* ignored.
|
|
||||||
*
|
|
||||||
* Also see the note in the class documentation about why you may not want to
|
|
||||||
* use this method in your application.
|
|
||||||
*/
|
|
||||||
explicit FileRef(const char *fileName,
|
|
||||||
bool readAudioProperties = true,
|
|
||||||
AudioProperties::ReadStyle
|
|
||||||
audioPropertiesStyle = AudioProperties::Average);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Contruct a FileRef using \a file. The FileRef now takes ownership of the
|
|
||||||
* pointer and will delete the File when it passes out of scope.
|
|
||||||
*/
|
|
||||||
explicit FileRef(File *file);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Make a copy of \a ref.
|
|
||||||
*/
|
|
||||||
FileRef(const FileRef &ref);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Destroys this FileRef instance.
|
|
||||||
*/
|
|
||||||
virtual ~FileRef();
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns a pointer to represented file's tag.
|
|
||||||
*
|
|
||||||
* \warning This pointer will become invalid when this FileRef and all
|
|
||||||
* copies pass out of scope.
|
|
||||||
*
|
|
||||||
* \see File::tag()
|
|
||||||
*/
|
|
||||||
Tag *tag() const;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the audio properties for this FileRef. If no audio properties
|
|
||||||
* were read then this will returns a null pointer.
|
|
||||||
*/
|
|
||||||
AudioProperties *audioProperties() const;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns a pointer to the file represented by this handler class.
|
|
||||||
*
|
|
||||||
* As a general rule this call should be avoided since if you need to work
|
|
||||||
* with file objects directly, you are probably better served instantiating
|
|
||||||
* the File subclasses (i.e. MPEG::File) manually and working with their APIs.
|
|
||||||
*
|
|
||||||
* This <i>handle</i> exists to provide a minimal, generic and value-based
|
|
||||||
* wrapper around a File. Accessing the file directly generally indicates
|
|
||||||
* a moving away from this simplicity (and into things beyond the scope of
|
|
||||||
* FileRef).
|
|
||||||
*
|
|
||||||
* \warning This pointer will become invalid when this FileRef and all
|
|
||||||
* copies pass out of scope.
|
|
||||||
*/
|
|
||||||
File *file() const;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Saves the file. Returns true on success.
|
|
||||||
*/
|
|
||||||
bool save();
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Adds a FileTypeResolver to the list of those used by TagLib. Each
|
|
||||||
* additional FileTypeResolver is added to the front of a list of resolvers
|
|
||||||
* that are tried. If the FileTypeResolver returns zero the next resolver
|
|
||||||
* is tried.
|
|
||||||
*
|
|
||||||
* Returns a pointer to the added resolver (the same one that's passed in --
|
|
||||||
* this is mostly so that static inialializers have something to use for
|
|
||||||
* assignment).
|
|
||||||
*
|
|
||||||
* \see FileTypeResolver
|
|
||||||
*/
|
|
||||||
static const FileTypeResolver *addFileTypeResolver(const FileTypeResolver *resolver);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* As is mentioned elsewhere in this class's documentation, the default file
|
|
||||||
* type resolution code provided by TagLib only works by comparing file
|
|
||||||
* extensions.
|
|
||||||
*
|
|
||||||
* This method returns the list of file extensions that are used by default.
|
|
||||||
*
|
|
||||||
* The extensions are all returned in lowercase, though the comparison used
|
|
||||||
* by TagLib for resolution is case-insensitive.
|
|
||||||
*
|
|
||||||
* \note This does not account for any additional file type resolvers that
|
|
||||||
* are plugged in. Also note that this is not intended to replace a propper
|
|
||||||
* mime-type resolution system, but is just here for reference.
|
|
||||||
*
|
|
||||||
* \see FileTypeResolver
|
|
||||||
*/
|
|
||||||
static StringList defaultFileExtensions();
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns true if the file (and as such other pointers) are null.
|
|
||||||
*/
|
|
||||||
bool isNull() const;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Assign the file pointed to by \a ref to this FileRef.
|
|
||||||
*/
|
|
||||||
FileRef &operator=(const FileRef &ref);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns true if this FileRef and \a ref point to the same File object.
|
|
||||||
*/
|
|
||||||
bool operator==(const FileRef &ref) const;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns true if this FileRef and \a ref do not point to the same File
|
|
||||||
* object.
|
|
||||||
*/
|
|
||||||
bool operator!=(const FileRef &ref) const;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* A simple implementation of file type guessing. If \a readAudioProperties
|
|
||||||
* is true then the audio properties will be read using
|
|
||||||
* \a audioPropertiesStyle. If \a readAudioProperties is false then
|
|
||||||
* \a audioPropertiesStyle will be ignored.
|
|
||||||
*
|
|
||||||
* \note You generally shouldn't use this method, but instead the constructor
|
|
||||||
* directly.
|
|
||||||
*
|
|
||||||
* \deprecated
|
|
||||||
*/
|
|
||||||
static File *create(const char *fileName,
|
|
||||||
bool readAudioProperties = true,
|
|
||||||
AudioProperties::ReadStyle audioPropertiesStyle = AudioProperties::Average);
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
class FileRefPrivate;
|
|
||||||
FileRefPrivate *d;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace TagLib
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,468 +0,0 @@
|
||||||
/***************************************************************************
|
|
||||||
copyright : (C) 2003-2004 by Allan Sandfeld Jensen
|
|
||||||
email : kde@carewolf.org
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* 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 *
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
#include <tbytevector.h>
|
|
||||||
#include <tstring.h>
|
|
||||||
#include <tlist.h>
|
|
||||||
#include <tdebug.h>
|
|
||||||
|
|
||||||
#include <id3v2header.h>
|
|
||||||
#include <id3v2tag.h>
|
|
||||||
#include <id3v1tag.h>
|
|
||||||
|
|
||||||
#include "flacfile.h"
|
|
||||||
#include "flactag.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
|
|
||||||
namespace TagLib {
|
|
||||||
namespace FLAC {
|
|
||||||
enum BlockType { StreamInfo = 0, Padding, Application, SeekTable, VorbisComment, CueSheet };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class FLAC::File::FilePrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
FilePrivate() :
|
|
||||||
ID3v2FrameFactory(ID3v2::FrameFactory::instance()),
|
|
||||||
ID3v2Tag(0),
|
|
||||||
ID3v2Location(-1),
|
|
||||||
ID3v2OriginalSize(0),
|
|
||||||
ID3v1Tag(0),
|
|
||||||
ID3v1Location(-1),
|
|
||||||
comment(0),
|
|
||||||
tag(0),
|
|
||||||
properties(0),
|
|
||||||
flacStart(0),
|
|
||||||
streamStart(0),
|
|
||||||
streamLength(0),
|
|
||||||
scanned(false),
|
|
||||||
hasXiphComment(false),
|
|
||||||
hasID3v2(false),
|
|
||||||
hasID3v1(false) {}
|
|
||||||
|
|
||||||
~FilePrivate()
|
|
||||||
{
|
|
||||||
delete ID3v2Tag;
|
|
||||||
delete ID3v1Tag;
|
|
||||||
delete comment;
|
|
||||||
delete properties;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ID3v2::FrameFactory *ID3v2FrameFactory;
|
|
||||||
ID3v2::Tag *ID3v2Tag;
|
|
||||||
long ID3v2Location;
|
|
||||||
uint ID3v2OriginalSize;
|
|
||||||
|
|
||||||
ID3v1::Tag *ID3v1Tag;
|
|
||||||
long ID3v1Location;
|
|
||||||
|
|
||||||
Ogg::XiphComment *comment;
|
|
||||||
|
|
||||||
FLAC::Tag *tag;
|
|
||||||
|
|
||||||
Properties *properties;
|
|
||||||
ByteVector streamInfoData;
|
|
||||||
ByteVector xiphCommentData;
|
|
||||||
|
|
||||||
long flacStart;
|
|
||||||
long streamStart;
|
|
||||||
long streamLength;
|
|
||||||
bool scanned;
|
|
||||||
|
|
||||||
bool hasXiphComment;
|
|
||||||
bool hasID3v2;
|
|
||||||
bool hasID3v1;
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// public members
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
FLAC::File::File(ID3v2::FrameFactory *frameFactory) : TagLib::File()
|
|
||||||
{
|
|
||||||
d = new FilePrivate;
|
|
||||||
if (frameFactory)
|
|
||||||
d->ID3v2FrameFactory = frameFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
FLAC::File::File(const char *file, bool readProperties,
|
|
||||||
Properties::ReadStyle propertiesStyle) :
|
|
||||||
TagLib::File(file)
|
|
||||||
{
|
|
||||||
d = new FilePrivate;
|
|
||||||
read(readProperties, propertiesStyle);
|
|
||||||
}
|
|
||||||
|
|
||||||
FLAC::File::File(const char *file, ID3v2::FrameFactory *frameFactory,
|
|
||||||
bool readProperties, Properties::ReadStyle propertiesStyle) :
|
|
||||||
TagLib::File(file)
|
|
||||||
{
|
|
||||||
d = new FilePrivate;
|
|
||||||
d->ID3v2FrameFactory = frameFactory;
|
|
||||||
read(readProperties, propertiesStyle);
|
|
||||||
}
|
|
||||||
|
|
||||||
FLAC::File::~File()
|
|
||||||
{
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
TagLib::Tag *FLAC::File::tag() const
|
|
||||||
{
|
|
||||||
return d->tag;
|
|
||||||
}
|
|
||||||
|
|
||||||
FLAC::Properties *FLAC::File::audioProperties() const
|
|
||||||
{
|
|
||||||
return d->properties;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FLAC::File::read(bool readProperties, Properties::ReadStyle propertiesStyle)
|
|
||||||
{
|
|
||||||
// Look for an ID3v2 tag
|
|
||||||
|
|
||||||
d->ID3v2Location = findID3v2();
|
|
||||||
|
|
||||||
if(d->ID3v2Location >= 0) {
|
|
||||||
|
|
||||||
d->ID3v2Tag = new ID3v2::Tag(this, d->ID3v2Location, d->ID3v2FrameFactory);
|
|
||||||
|
|
||||||
d->ID3v2OriginalSize = d->ID3v2Tag->header()->completeTagSize();
|
|
||||||
|
|
||||||
if(d->ID3v2Tag->header()->tagSize() <= 0) {
|
|
||||||
delete d->ID3v2Tag;
|
|
||||||
d->ID3v2Tag = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
d->hasID3v2 = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Look for an ID3v1 tag
|
|
||||||
|
|
||||||
d->ID3v1Location = findID3v1();
|
|
||||||
|
|
||||||
if(d->ID3v1Location >= 0) {
|
|
||||||
d->ID3v1Tag = new ID3v1::Tag(this, d->ID3v1Location);
|
|
||||||
d->hasID3v1 = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Look for FLAC metadata, including vorbis comments
|
|
||||||
|
|
||||||
scan();
|
|
||||||
|
|
||||||
if (!isValid()) return;
|
|
||||||
|
|
||||||
if(d->hasXiphComment)
|
|
||||||
d->comment = new Ogg::XiphComment(xiphCommentData());
|
|
||||||
|
|
||||||
if(d->hasXiphComment || d->hasID3v2 || d->hasID3v1)
|
|
||||||
d->tag = new FLAC::Tag(d->comment, d->ID3v2Tag, d->ID3v1Tag);
|
|
||||||
else
|
|
||||||
d->tag = new FLAC::Tag(new Ogg::XiphComment);
|
|
||||||
|
|
||||||
if(readProperties)
|
|
||||||
d->properties = new Properties(streamInfoData(), streamLength(), propertiesStyle);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FLAC::File::save()
|
|
||||||
{
|
|
||||||
if(readOnly()) {
|
|
||||||
debug("FLAC::File::save() - Cannot save to a read only file.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create new vorbis comments
|
|
||||||
|
|
||||||
if(!d->comment) {
|
|
||||||
d->comment = new Ogg::XiphComment;
|
|
||||||
if(d->tag)
|
|
||||||
Tag::duplicate(d->tag, d->comment, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
d->xiphCommentData = d->comment->render(false);
|
|
||||||
|
|
||||||
// A Xiph comment portion of the data stream starts with a 4-byte descriptor.
|
|
||||||
// The first byte indicates the frame type. The last three bytes are used
|
|
||||||
// to give the length of the data segment. Here we start
|
|
||||||
|
|
||||||
ByteVector data = ByteVector::fromUInt(d->xiphCommentData.size());
|
|
||||||
|
|
||||||
data[0] = char(VorbisComment);
|
|
||||||
data.append(d->xiphCommentData);
|
|
||||||
|
|
||||||
|
|
||||||
// If file already have comment => find and update it
|
|
||||||
// if not => insert one
|
|
||||||
|
|
||||||
// TODO: Search for padding and use that
|
|
||||||
|
|
||||||
if(d->hasXiphComment) {
|
|
||||||
|
|
||||||
long nextBlockOffset = d->flacStart;
|
|
||||||
bool isLastBlock = false;
|
|
||||||
|
|
||||||
while(!isLastBlock) {
|
|
||||||
seek(nextBlockOffset);
|
|
||||||
|
|
||||||
ByteVector header = readBlock(4);
|
|
||||||
char blockType = header[0] & 0x7f;
|
|
||||||
isLastBlock = (header[0] & 0x80) != 0;
|
|
||||||
uint blockLength = header.mid(1, 3).toUInt();
|
|
||||||
|
|
||||||
if(blockType == VorbisComment) {
|
|
||||||
data[0] = header[0];
|
|
||||||
insert(data, nextBlockOffset, blockLength + 4);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
nextBlockOffset += blockLength + 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
|
|
||||||
const long firstBlockOffset = d->flacStart;
|
|
||||||
seek(firstBlockOffset);
|
|
||||||
|
|
||||||
ByteVector header = readBlock(4);
|
|
||||||
bool isLastBlock = (header[0] & 0x80) != 0;
|
|
||||||
uint blockLength = header.mid(1, 3).toUInt();
|
|
||||||
|
|
||||||
if(isLastBlock) {
|
|
||||||
|
|
||||||
// If the first block was previously also the last block, then we want to
|
|
||||||
// mark it as no longer being the first block (the writeBlock() call) and
|
|
||||||
// then set the data for the block that we're about to write to mark our
|
|
||||||
// new block as the last block.
|
|
||||||
|
|
||||||
seek(firstBlockOffset);
|
|
||||||
writeBlock(static_cast<char>(header[0] & 0x7F));
|
|
||||||
data[0] |= 0x80;
|
|
||||||
}
|
|
||||||
|
|
||||||
insert(data, firstBlockOffset + blockLength + 4, 0);
|
|
||||||
d->hasXiphComment = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update ID3 tags
|
|
||||||
|
|
||||||
if(d->ID3v2Tag) {
|
|
||||||
if(d->hasID3v2) {
|
|
||||||
if(d->ID3v2Location < d->flacStart)
|
|
||||||
debug("FLAC::File::save() -- This can't be right -- an ID3v2 tag after the "
|
|
||||||
"start of the FLAC bytestream? Not writing the ID3v2 tag.");
|
|
||||||
else
|
|
||||||
insert(d->ID3v2Tag->render(), d->ID3v2Location, d->ID3v2OriginalSize);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
insert(d->ID3v2Tag->render(), 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(d->ID3v1Tag) {
|
|
||||||
seek(d->ID3v1Tag ? -128 : 0, End);
|
|
||||||
writeBlock(d->ID3v1Tag->render());
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
ID3v2::Tag *FLAC::File::ID3v2Tag(bool create)
|
|
||||||
{
|
|
||||||
if(!create || d->ID3v2Tag)
|
|
||||||
return d->ID3v2Tag;
|
|
||||||
|
|
||||||
// no ID3v2 tag exists and we've been asked to create one
|
|
||||||
|
|
||||||
d->ID3v2Tag = new ID3v2::Tag;
|
|
||||||
return d->ID3v2Tag;
|
|
||||||
}
|
|
||||||
|
|
||||||
ID3v1::Tag *FLAC::File::ID3v1Tag(bool create)
|
|
||||||
{
|
|
||||||
if(!create || d->ID3v1Tag)
|
|
||||||
return d->ID3v1Tag;
|
|
||||||
|
|
||||||
// no ID3v1 tag exists and we've been asked to create one
|
|
||||||
|
|
||||||
d->ID3v1Tag = new ID3v1::Tag;
|
|
||||||
return d->ID3v1Tag;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ogg::XiphComment *FLAC::File::xiphComment(bool create)
|
|
||||||
{
|
|
||||||
if(!create || d->comment)
|
|
||||||
return d->comment;
|
|
||||||
|
|
||||||
// no XiphComment exists and we've been asked to create one
|
|
||||||
|
|
||||||
d->comment = new Ogg::XiphComment;
|
|
||||||
return d->comment;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FLAC::File::setID3v2FrameFactory(const ID3v2::FrameFactory *factory)
|
|
||||||
{
|
|
||||||
d->ID3v2FrameFactory = factory;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// private members
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
ByteVector FLAC::File::streamInfoData()
|
|
||||||
{
|
|
||||||
if (isValid())
|
|
||||||
return d->streamInfoData;
|
|
||||||
else
|
|
||||||
return ByteVector();
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteVector FLAC::File::xiphCommentData()
|
|
||||||
{
|
|
||||||
if (isValid() && d->hasXiphComment)
|
|
||||||
return d->xiphCommentData;
|
|
||||||
else
|
|
||||||
return ByteVector();
|
|
||||||
}
|
|
||||||
|
|
||||||
long FLAC::File::streamLength()
|
|
||||||
{
|
|
||||||
return d->streamLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FLAC::File::scan()
|
|
||||||
{
|
|
||||||
// Scan the metadata pages
|
|
||||||
|
|
||||||
if(d->scanned)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if(!isValid())
|
|
||||||
return;
|
|
||||||
|
|
||||||
long nextBlockOffset;
|
|
||||||
|
|
||||||
if(d->hasID3v2)
|
|
||||||
nextBlockOffset = find("fLaC", d->ID3v2Location + d->ID3v2OriginalSize);
|
|
||||||
else
|
|
||||||
nextBlockOffset = find("fLaC");
|
|
||||||
|
|
||||||
if(nextBlockOffset < 0) {
|
|
||||||
debug("FLAC::File::scan() -- FLAC stream not found");
|
|
||||||
setValid(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
nextBlockOffset += 4;
|
|
||||||
d->flacStart = nextBlockOffset;
|
|
||||||
|
|
||||||
seek(nextBlockOffset);
|
|
||||||
|
|
||||||
ByteVector header = readBlock(4);
|
|
||||||
|
|
||||||
// Header format (from spec):
|
|
||||||
// <1> Last-metadata-block flag
|
|
||||||
// <7> BLOCK_TYPE
|
|
||||||
// 0 : STREAMINFO
|
|
||||||
// 1 : PADDING
|
|
||||||
// ..
|
|
||||||
// 4 : VORBIS_COMMENT
|
|
||||||
// ..
|
|
||||||
// <24> Length of metadata to follow
|
|
||||||
|
|
||||||
char blockType = header[0] & 0x7f;
|
|
||||||
bool isLastBlock = (header[0] & 0x80) != 0;
|
|
||||||
uint length = header.mid(1, 3).toUInt();
|
|
||||||
|
|
||||||
// First block should be the stream_info metadata
|
|
||||||
|
|
||||||
if(blockType != StreamInfo) {
|
|
||||||
debug("FLAC::File::scan() -- invalid FLAC stream");
|
|
||||||
setValid(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
d->streamInfoData = readBlock(length);
|
|
||||||
nextBlockOffset += length + 4;
|
|
||||||
|
|
||||||
// Search through the remaining metadata
|
|
||||||
|
|
||||||
while(!isLastBlock) {
|
|
||||||
header = readBlock(4);
|
|
||||||
blockType = header[0] & 0x7f;
|
|
||||||
isLastBlock = (header[0] & 0x80) != 0;
|
|
||||||
length = header.mid(1, 3).toUInt();
|
|
||||||
|
|
||||||
if(blockType == Padding) {
|
|
||||||
// debug("FLAC::File::scan() -- Padding found");
|
|
||||||
}
|
|
||||||
// Found the vorbis-comment
|
|
||||||
else if(blockType == VorbisComment) {
|
|
||||||
d->xiphCommentData = readBlock(length);
|
|
||||||
d->hasXiphComment = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
nextBlockOffset += length + 4;
|
|
||||||
|
|
||||||
if(nextBlockOffset >= File::length()) {
|
|
||||||
debug("FLAC::File::scan() -- FLAC stream corrupted");
|
|
||||||
setValid(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
seek(nextBlockOffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
// End of metadata, now comes the datastream
|
|
||||||
d->streamStart = nextBlockOffset;
|
|
||||||
d->streamLength = File::length() - d->streamStart;
|
|
||||||
if (d->hasID3v1)
|
|
||||||
d->streamLength -= 128;
|
|
||||||
|
|
||||||
d->scanned = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
long FLAC::File::findID3v1()
|
|
||||||
{
|
|
||||||
if(!isValid())
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
seek(-128, End);
|
|
||||||
long p = tell();
|
|
||||||
|
|
||||||
if(readBlock(3) == ID3v1::Tag::fileIdentifier())
|
|
||||||
return p;
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
long FLAC::File::findID3v2()
|
|
||||||
{
|
|
||||||
if(!isValid())
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
seek(0);
|
|
||||||
|
|
||||||
if(readBlock(3) == ID3v2::Header::fileIdentifier())
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
|
@ -1,210 +0,0 @@
|
||||||
/***************************************************************************
|
|
||||||
copyright : (C) 2003 by Allan Sandfeld Jensen
|
|
||||||
email : kde@carewolf.org
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* 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 *
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
#ifndef TAGLIB_FLACFILE_H
|
|
||||||
#define TAGLIB_FLACFILE_H
|
|
||||||
|
|
||||||
#include "taglib_export.h"
|
|
||||||
#include "tfile.h"
|
|
||||||
|
|
||||||
#include "flacproperties.h"
|
|
||||||
|
|
||||||
namespace TagLib {
|
|
||||||
|
|
||||||
class Tag;
|
|
||||||
|
|
||||||
namespace ID3v2 { class FrameFactory; class Tag; }
|
|
||||||
namespace ID3v1 { class Tag; }
|
|
||||||
namespace Ogg { class XiphComment; }
|
|
||||||
|
|
||||||
//! An implementation of FLAC metadata
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* This is implementation of FLAC metadata for non-Ogg FLAC files. At some
|
|
||||||
* point when Ogg / FLAC is more common there will be a similar implementation
|
|
||||||
* under the Ogg hiearchy.
|
|
||||||
*
|
|
||||||
* This supports ID3v1, ID3v2 and Xiph style comments as well as reading stream
|
|
||||||
* properties from the file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace FLAC {
|
|
||||||
|
|
||||||
//! An implementation of TagLib::File with FLAC specific methods
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* This implements and provides an interface for FLAC files to the
|
|
||||||
* TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing
|
|
||||||
* the abstract TagLib::File API as well as providing some additional
|
|
||||||
* information specific to FLAC files.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class TAGLIB_EXPORT File : public TagLib::File
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/*!
|
|
||||||
* Contructs a FLAC file object without reading a file. Allows object
|
|
||||||
* fields to be set up before reading.
|
|
||||||
*/
|
|
||||||
File(ID3v2::FrameFactory *frameFactory = NULL);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Contructs a FLAC file from \a file. If \a readProperties is true the
|
|
||||||
* file's audio properties will also be read using \a propertiesStyle. If
|
|
||||||
* false, \a propertiesStyle is ignored.
|
|
||||||
*
|
|
||||||
* \deprecated This constructor will be dropped in favor of the one below
|
|
||||||
* in a future version.
|
|
||||||
*/
|
|
||||||
File(const char *file, bool readProperties = true,
|
|
||||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Contructs a FLAC file from \a file. If \a readProperties is true the
|
|
||||||
* file's audio properties will also be read using \a propertiesStyle. If
|
|
||||||
* false, \a propertiesStyle is ignored.
|
|
||||||
*
|
|
||||||
* If this file contains and ID3v2 tag the frames will be created using
|
|
||||||
* \a frameFactory.
|
|
||||||
*/
|
|
||||||
// BIC: merge with the above constructor
|
|
||||||
File(const char *file, ID3v2::FrameFactory *frameFactory,
|
|
||||||
bool readProperties = true,
|
|
||||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Destroys this instance of the File.
|
|
||||||
*/
|
|
||||||
virtual ~File();
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the Tag for this file. This will be a union of XiphComment,
|
|
||||||
* ID3v1 and ID3v2 tags.
|
|
||||||
*
|
|
||||||
* \see ID3v2Tag()
|
|
||||||
* \see ID3v1Tag()
|
|
||||||
* \see XiphComment()
|
|
||||||
*/
|
|
||||||
virtual TagLib::Tag *tag() const;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the FLAC::Properties for this file. If no audio properties
|
|
||||||
* were read then this will return a null pointer.
|
|
||||||
*/
|
|
||||||
virtual Properties *audioProperties() const;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Reads from FLAC file. If \a readProperties is true the file's audio
|
|
||||||
* properties will also be read using \a propertiesStyle. If false,
|
|
||||||
* \a propertiesStyle is ignored.
|
|
||||||
*/
|
|
||||||
void read(bool readProperties = true,
|
|
||||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Save the file. This will primarily save the XiphComment, but
|
|
||||||
* will also keep any old ID3-tags up to date. If the file
|
|
||||||
* has no XiphComment, one will be constructed from the ID3-tags.
|
|
||||||
*
|
|
||||||
* This returns true if the save was successful.
|
|
||||||
*/
|
|
||||||
virtual bool save();
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns a pointer to the ID3v2 tag of the file.
|
|
||||||
*
|
|
||||||
* If \a create is false (the default) this will return a null pointer
|
|
||||||
* if there is no valid ID3v2 tag. If \a create is true it will create
|
|
||||||
* an ID3v2 tag if one does not exist.
|
|
||||||
*
|
|
||||||
* \note The Tag <b>is still</b> owned by the FLAC::File and should not be
|
|
||||||
* deleted by the user. It will be deleted when the file (object) is
|
|
||||||
* destroyed.
|
|
||||||
*/
|
|
||||||
ID3v2::Tag *ID3v2Tag(bool create = false);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns a pointer to the ID3v1 tag of the file.
|
|
||||||
*
|
|
||||||
* If \a create is false (the default) this will return a null pointer
|
|
||||||
* if there is no valid ID3v1 tag. If \a create is true it will create
|
|
||||||
* an ID3v1 tag if one does not exist.
|
|
||||||
*
|
|
||||||
* \note The Tag <b>is still</b> owned by the FLAC::File and should not be
|
|
||||||
* deleted by the user. It will be deleted when the file (object) is
|
|
||||||
* destroyed.
|
|
||||||
*/
|
|
||||||
ID3v1::Tag *ID3v1Tag(bool create = false);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns a pointer to the XiphComment for the file.
|
|
||||||
*
|
|
||||||
* If \a create is false (the default) this will return a null pointer
|
|
||||||
* if there is no valid XiphComment. If \a create is true it will create
|
|
||||||
* a XiphComment if one does not exist.
|
|
||||||
*
|
|
||||||
* \note The Tag <b>is still</b> owned by the FLAC::File and should not be
|
|
||||||
* deleted by the user. It will be deleted when the file (object) is
|
|
||||||
* destroyed.
|
|
||||||
*/
|
|
||||||
Ogg::XiphComment *xiphComment(bool create = false);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Set the ID3v2::FrameFactory to something other than the default. This
|
|
||||||
* can be used to specify the way that ID3v2 frames will be interpreted
|
|
||||||
* when
|
|
||||||
*
|
|
||||||
* \see ID3v2FrameFactory
|
|
||||||
*/
|
|
||||||
void setID3v2FrameFactory(const ID3v2::FrameFactory *factory);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the block of data used by FLAC::Properties for parsing the
|
|
||||||
* stream properties.
|
|
||||||
*
|
|
||||||
* \deprecated This method will not be public in a future release.
|
|
||||||
*/
|
|
||||||
ByteVector streamInfoData(); // BIC: remove
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the length of the audio-stream, used by FLAC::Properties for
|
|
||||||
* calculating the bitrate.
|
|
||||||
*
|
|
||||||
* \deprecated This method will not be public in a future release.
|
|
||||||
*/
|
|
||||||
long streamLength(); // BIC: remove
|
|
||||||
|
|
||||||
private:
|
|
||||||
File(const File &);
|
|
||||||
File &operator=(const File &);
|
|
||||||
|
|
||||||
void scan();
|
|
||||||
long findID3v2();
|
|
||||||
long findID3v1();
|
|
||||||
ByteVector xiphCommentData();
|
|
||||||
|
|
||||||
class FilePrivate;
|
|
||||||
FilePrivate *d;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,146 +0,0 @@
|
||||||
/***************************************************************************
|
|
||||||
copyright : (C) 2003 by Allan Sandfeld Jensen
|
|
||||||
email : kde@carewolf.org
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* 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 *
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
#include <tstring.h>
|
|
||||||
#include <tdebug.h>
|
|
||||||
|
|
||||||
#include "flacproperties.h"
|
|
||||||
#include "flacfile.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
|
|
||||||
class FLAC::Properties::PropertiesPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PropertiesPrivate(ByteVector d, long st, ReadStyle s) :
|
|
||||||
data(d),
|
|
||||||
streamLength(st),
|
|
||||||
style(s),
|
|
||||||
length(0),
|
|
||||||
bitrate(0),
|
|
||||||
sampleRate(0),
|
|
||||||
sampleWidth(0),
|
|
||||||
channels(0) {}
|
|
||||||
|
|
||||||
ByteVector data;
|
|
||||||
long streamLength;
|
|
||||||
ReadStyle style;
|
|
||||||
int length;
|
|
||||||
int bitrate;
|
|
||||||
int sampleRate;
|
|
||||||
int sampleWidth;
|
|
||||||
int channels;
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// public members
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
FLAC::Properties::Properties(ByteVector data, long streamLength, ReadStyle style) : AudioProperties(style)
|
|
||||||
{
|
|
||||||
d = new PropertiesPrivate(data, streamLength, style);
|
|
||||||
read();
|
|
||||||
}
|
|
||||||
|
|
||||||
FLAC::Properties::Properties(File *file, ReadStyle style) : AudioProperties(style)
|
|
||||||
{
|
|
||||||
d = new PropertiesPrivate(file->streamInfoData(), file->streamLength(), style);
|
|
||||||
read();
|
|
||||||
}
|
|
||||||
|
|
||||||
FLAC::Properties::~Properties()
|
|
||||||
{
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
int FLAC::Properties::length() const
|
|
||||||
{
|
|
||||||
return d->length;
|
|
||||||
}
|
|
||||||
|
|
||||||
int FLAC::Properties::bitrate() const
|
|
||||||
{
|
|
||||||
return d->bitrate;
|
|
||||||
}
|
|
||||||
|
|
||||||
int FLAC::Properties::sampleRate() const
|
|
||||||
{
|
|
||||||
return d->sampleRate;
|
|
||||||
}
|
|
||||||
|
|
||||||
int FLAC::Properties::sampleWidth() const
|
|
||||||
{
|
|
||||||
return d->sampleWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
int FLAC::Properties::channels() const
|
|
||||||
{
|
|
||||||
return d->channels;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// private members
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
void FLAC::Properties::read()
|
|
||||||
{
|
|
||||||
if(d->data.size() < 18) {
|
|
||||||
debug("FLAC::Properties::read() - FLAC properties must contain at least 18 bytes.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int pos = 0;
|
|
||||||
|
|
||||||
// Minimum block size (in samples)
|
|
||||||
pos += 2;
|
|
||||||
|
|
||||||
// Maximum block size (in samples)
|
|
||||||
pos += 2;
|
|
||||||
|
|
||||||
// Minimum frame size (in bytes)
|
|
||||||
pos += 3;
|
|
||||||
|
|
||||||
// Maximum frame size (in bytes)
|
|
||||||
pos += 3;
|
|
||||||
|
|
||||||
uint flags = d->data.mid(pos, 4).toUInt(true);
|
|
||||||
d->sampleRate = flags >> 12;
|
|
||||||
d->channels = ((flags >> 9) & 7) + 1;
|
|
||||||
d->sampleWidth = ((flags >> 4) & 31) + 1;
|
|
||||||
|
|
||||||
// The last 4 bits are the most significant 4 bits for the 36 bit
|
|
||||||
// stream length in samples. (Audio files measured in days)
|
|
||||||
|
|
||||||
uint highLength =d->sampleRate > 0 ? (((flags & 0xf) << 28) / d->sampleRate) << 4 : 0;
|
|
||||||
pos += 4;
|
|
||||||
|
|
||||||
d->length = d->sampleRate > 0 ?
|
|
||||||
(d->data.mid(pos, 4).toUInt(true)) / d->sampleRate + highLength : 0;
|
|
||||||
pos += 4;
|
|
||||||
|
|
||||||
// Uncompressed bitrate:
|
|
||||||
|
|
||||||
//d->bitrate = ((d->sampleRate * d->channels) / 1000) * d->sampleWidth;
|
|
||||||
|
|
||||||
// Real bitrate:
|
|
||||||
|
|
||||||
d->bitrate = d->length > 0 ? ((d->streamLength * 8L) / d->length) / 1000 : 0;
|
|
||||||
}
|
|
|
@ -1,84 +0,0 @@
|
||||||
/***************************************************************************
|
|
||||||
copyright : (C) 2003 by Allan Sandfeld Jensen
|
|
||||||
email : kde@carewolf.org
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* 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 *
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
#ifndef TAGLIB_FLACPROPERTIES_H
|
|
||||||
#define TAGLIB_FLACPROPERTIES_H
|
|
||||||
|
|
||||||
#include "audioproperties.h"
|
|
||||||
|
|
||||||
namespace TagLib {
|
|
||||||
|
|
||||||
namespace FLAC {
|
|
||||||
|
|
||||||
class File;
|
|
||||||
|
|
||||||
//! An implementation of audio property reading for FLAC
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* This reads the data from an FLAC stream found in the AudioProperties
|
|
||||||
* API.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class Properties : public AudioProperties
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/*!
|
|
||||||
* Create an instance of FLAC::Properties with the data read from the
|
|
||||||
* ByteVector \a data.
|
|
||||||
*/
|
|
||||||
// BIC: switch to const reference
|
|
||||||
Properties(ByteVector data, long streamLength, ReadStyle style = Average);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Create an instance of FLAC::Properties with the data read from the
|
|
||||||
* FLAC::File \a file.
|
|
||||||
*/
|
|
||||||
// BIC: remove
|
|
||||||
Properties(File *file, ReadStyle style = Average);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Destroys this FLAC::Properties instance.
|
|
||||||
*/
|
|
||||||
virtual ~Properties();
|
|
||||||
|
|
||||||
// Reimplementations.
|
|
||||||
|
|
||||||
virtual int length() const;
|
|
||||||
virtual int bitrate() const;
|
|
||||||
virtual int sampleRate() const;
|
|
||||||
virtual int channels() const;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the sample width as read from the FLAC identification
|
|
||||||
* header.
|
|
||||||
*/
|
|
||||||
int sampleWidth() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void read();
|
|
||||||
|
|
||||||
class PropertiesPrivate;
|
|
||||||
PropertiesPrivate *d;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,212 +0,0 @@
|
||||||
/***************************************************************************
|
|
||||||
copyright : (C) 2003 by Allan Sandfeld Jensen
|
|
||||||
email : kde@carewolf.org
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* 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 *
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
#ifndef DO_NOT_DOCUMENT // Tell Doxygen not to document this header
|
|
||||||
|
|
||||||
#ifndef TAGLIB_FLACTAG_H
|
|
||||||
#define TAGLIB_FLACTAG_H
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Note that this header is not installed.
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#include <xiphcomment.h>
|
|
||||||
#include <id3v2tag.h>
|
|
||||||
#include <id3v1tag.h>
|
|
||||||
|
|
||||||
namespace TagLib {
|
|
||||||
|
|
||||||
namespace FLAC {
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* A union of Xiph, ID3v2 and ID3v1 tags.
|
|
||||||
*/
|
|
||||||
class Tag : public TagLib::Tag
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Tag(Ogg::XiphComment *xiph, ID3v2::Tag *id3v2 = 0, ID3v1::Tag *id3v1 = 0) :
|
|
||||||
TagLib::Tag(),
|
|
||||||
xiph(xiph), id3v2(id3v2), id3v1(id3v1) {}
|
|
||||||
|
|
||||||
virtual String title() const {
|
|
||||||
if(xiph && !xiph->title().isEmpty())
|
|
||||||
return xiph->title();
|
|
||||||
|
|
||||||
if(id3v2 && !id3v2->title().isEmpty())
|
|
||||||
return id3v2->title();
|
|
||||||
|
|
||||||
if(id3v1)
|
|
||||||
return id3v1->title();
|
|
||||||
|
|
||||||
return String::null;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual String artist() const {
|
|
||||||
if(xiph && !xiph->artist().isEmpty())
|
|
||||||
return xiph->artist();
|
|
||||||
|
|
||||||
if(id3v2 && !id3v2->artist().isEmpty())
|
|
||||||
return id3v2->artist();
|
|
||||||
|
|
||||||
if(id3v1)
|
|
||||||
return id3v1->artist();
|
|
||||||
|
|
||||||
return String::null;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual String album() const {
|
|
||||||
if(xiph && !xiph->album().isEmpty())
|
|
||||||
return xiph->album();
|
|
||||||
|
|
||||||
if(id3v2 && !id3v2->album().isEmpty())
|
|
||||||
return id3v2->album();
|
|
||||||
|
|
||||||
if(id3v1)
|
|
||||||
return id3v1->album();
|
|
||||||
|
|
||||||
return String::null;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual String comment() const {
|
|
||||||
if(xiph && !xiph->comment().isEmpty())
|
|
||||||
return xiph->comment();
|
|
||||||
|
|
||||||
if(id3v2 && !id3v2->comment().isEmpty())
|
|
||||||
return id3v2->comment();
|
|
||||||
|
|
||||||
if(id3v1)
|
|
||||||
return id3v1->comment();
|
|
||||||
|
|
||||||
return String::null;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual String genre() const {
|
|
||||||
if(xiph && !xiph->genre().isEmpty())
|
|
||||||
return xiph->genre();
|
|
||||||
|
|
||||||
if(id3v2 && !id3v2->genre().isEmpty())
|
|
||||||
return id3v2->genre();
|
|
||||||
|
|
||||||
if(id3v1)
|
|
||||||
return id3v1->genre();
|
|
||||||
|
|
||||||
return String::null;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint year() const {
|
|
||||||
if(xiph && xiph->year() > 0)
|
|
||||||
return xiph->year();
|
|
||||||
|
|
||||||
if(id3v2 && id3v2->year() > 0)
|
|
||||||
return id3v2->year();
|
|
||||||
|
|
||||||
if(id3v1)
|
|
||||||
return id3v1->year();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint track() const {
|
|
||||||
if(xiph && xiph->track() > 0)
|
|
||||||
return xiph->track();
|
|
||||||
|
|
||||||
if(id3v2 && id3v2->track() > 0)
|
|
||||||
return id3v2->track();
|
|
||||||
|
|
||||||
if(id3v1)
|
|
||||||
return id3v1->track();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void setTitle(const String &s) {
|
|
||||||
if(xiph)
|
|
||||||
xiph->setTitle(s);
|
|
||||||
if(id3v2)
|
|
||||||
id3v2->setTitle(s);
|
|
||||||
if(id3v1)
|
|
||||||
id3v1->setTitle(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void setArtist(const String &s) {
|
|
||||||
if(xiph)
|
|
||||||
xiph->setArtist(s);
|
|
||||||
if(id3v2)
|
|
||||||
id3v2->setArtist(s);
|
|
||||||
if(id3v1)
|
|
||||||
id3v1->setArtist(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void setAlbum(const String &s) {
|
|
||||||
if(xiph)
|
|
||||||
xiph->setAlbum(s);
|
|
||||||
if(id3v2)
|
|
||||||
id3v2->setAlbum(s);
|
|
||||||
if(id3v1)
|
|
||||||
id3v1->setAlbum(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void setComment(const String &s) {
|
|
||||||
if(xiph)
|
|
||||||
xiph->setComment(s);
|
|
||||||
if(id3v2)
|
|
||||||
id3v2->setComment(s);
|
|
||||||
if(id3v1)
|
|
||||||
id3v1->setComment(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void setGenre(const String &s) {
|
|
||||||
if(xiph)
|
|
||||||
xiph->setGenre(s);
|
|
||||||
if(id3v2)
|
|
||||||
id3v2->setGenre(s);
|
|
||||||
if(id3v1)
|
|
||||||
id3v1->setGenre(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void setYear(uint i) {
|
|
||||||
if(xiph)
|
|
||||||
xiph->setYear(i);
|
|
||||||
if(id3v2)
|
|
||||||
id3v2->setYear(i);
|
|
||||||
if(id3v1)
|
|
||||||
id3v1->setYear(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void setTrack(uint i) {
|
|
||||||
if(xiph)
|
|
||||||
xiph->setTrack(i);
|
|
||||||
if(id3v2)
|
|
||||||
id3v2->setTrack(i);
|
|
||||||
if(id3v1)
|
|
||||||
id3v1->setTrack(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Ogg::XiphComment *xiph;
|
|
||||||
ID3v2::Tag *id3v2;
|
|
||||||
ID3v1::Tag *id3v1;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
#endif
|
|
|
@ -1,129 +0,0 @@
|
||||||
#include <iostream>
|
|
||||||
#include "tstring.h"
|
|
||||||
#include "boxfactory.h"
|
|
||||||
#include "mp4skipbox.h"
|
|
||||||
#include "mp4moovbox.h"
|
|
||||||
#include "mp4mvhdbox.h"
|
|
||||||
#include "mp4trakbox.h"
|
|
||||||
#include "mp4mdiabox.h"
|
|
||||||
#include "mp4minfbox.h"
|
|
||||||
#include "mp4stblbox.h"
|
|
||||||
#include "mp4stsdbox.h"
|
|
||||||
#include "mp4hdlrbox.h"
|
|
||||||
#include "mp4udtabox.h"
|
|
||||||
#include "mp4metabox.h"
|
|
||||||
#include "mp4ilstbox.h"
|
|
||||||
#include "itunesnambox.h"
|
|
||||||
#include "itunesartbox.h"
|
|
||||||
#include "itunesalbbox.h"
|
|
||||||
#include "itunesgenbox.h"
|
|
||||||
#include "itunesdaybox.h"
|
|
||||||
#include "itunestrknbox.h"
|
|
||||||
#include "itunescmtbox.h"
|
|
||||||
#include "itunesgrpbox.h"
|
|
||||||
#include "ituneswrtbox.h"
|
|
||||||
#include "itunesdiskbox.h"
|
|
||||||
#include "itunestmpobox.h"
|
|
||||||
#include "itunescvrbox.h"
|
|
||||||
#include "itunesdatabox.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
|
|
||||||
MP4::BoxFactory::BoxFactory()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::BoxFactory::~BoxFactory()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
//! factory function
|
|
||||||
MP4::Mp4IsoBox* MP4::BoxFactory::createInstance( TagLib::File* anyfile, MP4::Fourcc fourcc, uint size, long offset ) const
|
|
||||||
{
|
|
||||||
MP4::File * file = static_cast<MP4::File *>(anyfile);
|
|
||||||
if(!file)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
//std::cout << "creating box for: " << fourcc.toString() << std::endl;
|
|
||||||
|
|
||||||
switch( fourcc )
|
|
||||||
{
|
|
||||||
case 0x6d6f6f76: // 'moov'
|
|
||||||
return new MP4::Mp4MoovBox( file, fourcc, size, offset );
|
|
||||||
break;
|
|
||||||
case 0x6d766864: // 'mvhd'
|
|
||||||
return new MP4::Mp4MvhdBox( file, fourcc, size, offset );
|
|
||||||
break;
|
|
||||||
case 0x7472616b: // 'trak'
|
|
||||||
return new MP4::Mp4TrakBox( file, fourcc, size, offset );
|
|
||||||
break;
|
|
||||||
case 0x6d646961: // 'mdia'
|
|
||||||
return new MP4::Mp4MdiaBox( file, fourcc, size, offset );
|
|
||||||
break;
|
|
||||||
case 0x6d696e66: // 'minf'
|
|
||||||
return new MP4::Mp4MinfBox( file, fourcc, size, offset );
|
|
||||||
break;
|
|
||||||
case 0x7374626c: // 'stbl'
|
|
||||||
return new MP4::Mp4StblBox( file, fourcc, size, offset );
|
|
||||||
break;
|
|
||||||
case 0x73747364: // 'stsd'
|
|
||||||
return new MP4::Mp4StsdBox( file, fourcc, size, offset );
|
|
||||||
break;
|
|
||||||
case 0x68646c72: // 'hdlr'
|
|
||||||
return new MP4::Mp4HdlrBox( file, fourcc, size, offset );
|
|
||||||
break;
|
|
||||||
case 0x75647461: // 'udta'
|
|
||||||
return new MP4::Mp4UdtaBox( file, fourcc, size, offset );
|
|
||||||
break;
|
|
||||||
case 0x6d657461: // 'meta'
|
|
||||||
return new MP4::Mp4MetaBox( file, fourcc, size, offset );
|
|
||||||
break;
|
|
||||||
case 0x696c7374: // 'ilst'
|
|
||||||
return new MP4::Mp4IlstBox( file, fourcc, size, offset );
|
|
||||||
break;
|
|
||||||
case 0xa96e616d: // '_nam'
|
|
||||||
return new MP4::ITunesNamBox( file, fourcc, size, offset );
|
|
||||||
break;
|
|
||||||
case 0xa9415254: // '_ART'
|
|
||||||
return new MP4::ITunesArtBox( file, fourcc, size, offset );
|
|
||||||
break;
|
|
||||||
case 0xa9616c62: // '_alb'
|
|
||||||
return new MP4::ITunesAlbBox( file, fourcc, size, offset );
|
|
||||||
break;
|
|
||||||
case 0xa967656e: // '_gen'
|
|
||||||
return new MP4::ITunesGenBox( file, fourcc, size, offset );
|
|
||||||
break;
|
|
||||||
case 0x676e7265: // 'gnre'
|
|
||||||
return new MP4::ITunesGenBox( file, fourcc, size, offset );
|
|
||||||
break;
|
|
||||||
case 0xa9646179: // '_day'
|
|
||||||
return new MP4::ITunesDayBox( file, fourcc, size, offset );
|
|
||||||
break;
|
|
||||||
case 0x74726b6e: // 'trkn'
|
|
||||||
return new MP4::ITunesTrknBox( file, fourcc, size, offset );
|
|
||||||
break;
|
|
||||||
case 0xa9636d74: // '_cmt'
|
|
||||||
return new MP4::ITunesCmtBox( file, fourcc, size, offset );
|
|
||||||
break;
|
|
||||||
case 0xa9677270: // '_grp'
|
|
||||||
return new MP4::ITunesGrpBox( file, fourcc, size, offset );
|
|
||||||
break;
|
|
||||||
case 0xa9777274: // '_wrt'
|
|
||||||
return new MP4::ITunesWrtBox( file, fourcc, size, offset );
|
|
||||||
break;
|
|
||||||
case 0x6469736b: // 'disk'
|
|
||||||
return new MP4::ITunesDiskBox( file, fourcc, size, offset );
|
|
||||||
break;
|
|
||||||
case 0x746d706f: // 'tmpo'
|
|
||||||
return new MP4::ITunesTmpoBox( file, fourcc, size, offset );
|
|
||||||
break;
|
|
||||||
case 0x636f7672: // 'covr'
|
|
||||||
return new MP4::ITunesCvrBox( file, fourcc, size, offset );
|
|
||||||
break;
|
|
||||||
case 0x64616461: // 'data'
|
|
||||||
return new MP4::ITunesDataBox( file, fourcc, size, offset );
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return new MP4::Mp4SkipBox( file, fourcc, size, offset );
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
#ifndef BOXFACTORY_H
|
|
||||||
#define BOXFACTORY_H
|
|
||||||
|
|
||||||
#include "taglib.h"
|
|
||||||
#include "mp4isobox.h"
|
|
||||||
|
|
||||||
namespace TagLib
|
|
||||||
{
|
|
||||||
namespace MP4
|
|
||||||
{
|
|
||||||
class BoxFactory
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
BoxFactory();
|
|
||||||
~BoxFactory();
|
|
||||||
|
|
||||||
//! factory function
|
|
||||||
Mp4IsoBox* createInstance( TagLib::File* anyfile, MP4::Fourcc fourcc, uint size, long offset ) const;
|
|
||||||
}; // class BoxFactory
|
|
||||||
|
|
||||||
} // namepace MP4
|
|
||||||
} // namepace TagLib
|
|
||||||
|
|
||||||
#endif // BOXFACTORY_H
|
|
|
@ -1,68 +0,0 @@
|
||||||
#include <iostream>
|
|
||||||
#include "itunesalbbox.h"
|
|
||||||
#include "itunesdatabox.h"
|
|
||||||
#include "mp4isobox.h"
|
|
||||||
#include "mp4file.h"
|
|
||||||
#include "tfile.h"
|
|
||||||
#include "mp4tagsproxy.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
|
|
||||||
class MP4::ITunesAlbBox::ITunesAlbBoxPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ITunesDataBox* dataBox;
|
|
||||||
};
|
|
||||||
|
|
||||||
MP4::ITunesAlbBox::ITunesAlbBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset )
|
|
||||||
:Mp4IsoBox(file, fourcc, size, offset)
|
|
||||||
{
|
|
||||||
d = new MP4::ITunesAlbBox::ITunesAlbBoxPrivate();
|
|
||||||
d->dataBox = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::ITunesAlbBox::~ITunesAlbBox()
|
|
||||||
{
|
|
||||||
if( d->dataBox != 0 )
|
|
||||||
delete d->dataBox;
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! parse the content of the box
|
|
||||||
void MP4::ITunesAlbBox::parse()
|
|
||||||
{
|
|
||||||
TagLib::MP4::File* mp4file = static_cast<MP4::File*>( file() );
|
|
||||||
|
|
||||||
// parse data box
|
|
||||||
TagLib::uint size;
|
|
||||||
MP4::Fourcc fourcc;
|
|
||||||
|
|
||||||
if(mp4file->readSizeAndType( size, fourcc ) == true)
|
|
||||||
{
|
|
||||||
// check for type - must be 'data'
|
|
||||||
if( fourcc != MP4::Fourcc("data") )
|
|
||||||
{
|
|
||||||
std::cerr << "bad atom in itunes tag - skipping it." << std::endl;
|
|
||||||
// jump over data tag
|
|
||||||
mp4file->seek( size-8, TagLib::File::Current );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
d->dataBox = new ITunesDataBox( mp4file, fourcc, size, mp4file->tell() );
|
|
||||||
d->dataBox->parsebox();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// reading unsuccessful - serious error!
|
|
||||||
std::cerr << "Error in parsing ITunesAlbBox - serious Error in taglib!" << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// register data box
|
|
||||||
mp4file->tagProxy()->registerBox( Mp4TagsProxy::album, d->dataBox );
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
// get data pointer - just for debuging...
|
|
||||||
TagLib::String dataString( d->dataBox->data() );
|
|
||||||
std::cout << "Content of album box: " << dataString << std::endl;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
#ifndef ITUNESALBBOX_H
|
|
||||||
#define ITUNESALBBOX_H
|
|
||||||
|
|
||||||
#include "mp4isobox.h"
|
|
||||||
#include "mp4fourcc.h"
|
|
||||||
|
|
||||||
namespace TagLib
|
|
||||||
{
|
|
||||||
namespace MP4
|
|
||||||
{
|
|
||||||
class ITunesAlbBox: public Mp4IsoBox
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ITunesAlbBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset );
|
|
||||||
~ITunesAlbBox();
|
|
||||||
|
|
||||||
private:
|
|
||||||
//! parse the content of the box
|
|
||||||
virtual void parse();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
class ITunesAlbBoxPrivate;
|
|
||||||
ITunesAlbBoxPrivate* d;
|
|
||||||
}; // class ITunesAlbBox
|
|
||||||
|
|
||||||
} // namespace MP4
|
|
||||||
} // namespace TagLib
|
|
||||||
|
|
||||||
#endif // ITUNESALBBOX_H
|
|
|
@ -1,68 +0,0 @@
|
||||||
#include <iostream>
|
|
||||||
#include "itunesartbox.h"
|
|
||||||
#include "itunesdatabox.h"
|
|
||||||
#include "mp4isobox.h"
|
|
||||||
#include "mp4file.h"
|
|
||||||
#include "tfile.h"
|
|
||||||
#include "mp4tagsproxy.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
|
|
||||||
class MP4::ITunesArtBox::ITunesArtBoxPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ITunesDataBox* dataBox;
|
|
||||||
};
|
|
||||||
|
|
||||||
MP4::ITunesArtBox::ITunesArtBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset )
|
|
||||||
:Mp4IsoBox(file, fourcc, size, offset)
|
|
||||||
{
|
|
||||||
d = new MP4::ITunesArtBox::ITunesArtBoxPrivate();
|
|
||||||
d->dataBox = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::ITunesArtBox::~ITunesArtBox()
|
|
||||||
{
|
|
||||||
if( d->dataBox != 0 )
|
|
||||||
delete d->dataBox;
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! parse the content of the box
|
|
||||||
void MP4::ITunesArtBox::parse()
|
|
||||||
{
|
|
||||||
TagLib::MP4::File* mp4file = static_cast<MP4::File*>( file() );
|
|
||||||
|
|
||||||
// parse data box
|
|
||||||
TagLib::uint size;
|
|
||||||
MP4::Fourcc fourcc;
|
|
||||||
|
|
||||||
if(mp4file->readSizeAndType( size, fourcc ) == true)
|
|
||||||
{
|
|
||||||
// check for type - must be 'data'
|
|
||||||
if( fourcc != MP4::Fourcc("data") )
|
|
||||||
{
|
|
||||||
std::cerr << "bad atom in itunes tag - skipping it." << std::endl;
|
|
||||||
// jump over data tag
|
|
||||||
mp4file->seek( size-8, TagLib::File::Current );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
d->dataBox = new ITunesDataBox( mp4file, fourcc, size, mp4file->tell() );
|
|
||||||
d->dataBox->parsebox();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// reading unsuccessful - serious error!
|
|
||||||
std::cerr << "Error in parsing ITunesArtBox - serious Error in taglib!" << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// register data box
|
|
||||||
mp4file->tagProxy()->registerBox( Mp4TagsProxy::artist, d->dataBox );
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
// get data pointer - just for debuging...
|
|
||||||
TagLib::String dataString( d->dataBox->data() );
|
|
||||||
std::cout << "Content of artist box: " << dataString << std::endl;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
#ifndef ITUNESARTBOX_H
|
|
||||||
#define ITUNESARTBOX_H
|
|
||||||
|
|
||||||
#include "mp4isobox.h"
|
|
||||||
#include "mp4fourcc.h"
|
|
||||||
|
|
||||||
namespace TagLib
|
|
||||||
{
|
|
||||||
namespace MP4
|
|
||||||
{
|
|
||||||
class ITunesArtBox: public Mp4IsoBox
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ITunesArtBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset );
|
|
||||||
~ITunesArtBox();
|
|
||||||
|
|
||||||
private:
|
|
||||||
//! parse the content of the box
|
|
||||||
virtual void parse();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
class ITunesArtBoxPrivate;
|
|
||||||
ITunesArtBoxPrivate* d;
|
|
||||||
}; // class ITunesArtBox
|
|
||||||
|
|
||||||
} // namespace MP4
|
|
||||||
} // namespace TagLib
|
|
||||||
|
|
||||||
#endif // ITUNESARTBOX_H
|
|
|
@ -1,68 +0,0 @@
|
||||||
#include <iostream>
|
|
||||||
#include "itunescmtbox.h"
|
|
||||||
#include "itunesdatabox.h"
|
|
||||||
#include "mp4isobox.h"
|
|
||||||
#include "mp4file.h"
|
|
||||||
#include "tfile.h"
|
|
||||||
#include "mp4tagsproxy.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
|
|
||||||
class MP4::ITunesCmtBox::ITunesCmtBoxPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ITunesDataBox* dataBox;
|
|
||||||
};
|
|
||||||
|
|
||||||
MP4::ITunesCmtBox::ITunesCmtBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset )
|
|
||||||
:Mp4IsoBox(file, fourcc, size, offset)
|
|
||||||
{
|
|
||||||
d = new MP4::ITunesCmtBox::ITunesCmtBoxPrivate();
|
|
||||||
d->dataBox = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::ITunesCmtBox::~ITunesCmtBox()
|
|
||||||
{
|
|
||||||
if( d->dataBox != 0 )
|
|
||||||
delete d->dataBox;
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! parse the content of the box
|
|
||||||
void MP4::ITunesCmtBox::parse()
|
|
||||||
{
|
|
||||||
TagLib::MP4::File* mp4file = static_cast<MP4::File*>( file() );
|
|
||||||
|
|
||||||
// parse data box
|
|
||||||
TagLib::uint size;
|
|
||||||
MP4::Fourcc fourcc;
|
|
||||||
|
|
||||||
if(mp4file->readSizeAndType( size, fourcc ) == true)
|
|
||||||
{
|
|
||||||
// check for type - must be 'data'
|
|
||||||
if( fourcc != MP4::Fourcc("data") )
|
|
||||||
{
|
|
||||||
std::cerr << "bad atom in itunes tag - skipping it." << std::endl;
|
|
||||||
// jump over data tag
|
|
||||||
mp4file->seek( size-8, TagLib::File::Current );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
d->dataBox = new ITunesDataBox( mp4file, fourcc, size, mp4file->tell() );
|
|
||||||
d->dataBox->parsebox();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// reading unsuccessful - serious error!
|
|
||||||
std::cerr << "Error in parsing ITunesCmtBox - serious Error in taglib!" << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// register data box
|
|
||||||
mp4file->tagProxy()->registerBox( Mp4TagsProxy::comment, d->dataBox );
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
// get data pointer - just for debuging...
|
|
||||||
TagLib::String dataString( d->dataBox->data() );
|
|
||||||
std::cout << "Content of title box: " << dataString << std::endl;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
#ifndef ITUNESCMTBOX_H
|
|
||||||
#define ITUNESCMTBOX_H
|
|
||||||
|
|
||||||
#include "mp4isobox.h"
|
|
||||||
#include "mp4fourcc.h"
|
|
||||||
|
|
||||||
namespace TagLib
|
|
||||||
{
|
|
||||||
namespace MP4
|
|
||||||
{
|
|
||||||
class ITunesCmtBox: public Mp4IsoBox
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ITunesCmtBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset );
|
|
||||||
~ITunesCmtBox();
|
|
||||||
|
|
||||||
private:
|
|
||||||
//! parse the content of the box
|
|
||||||
virtual void parse();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
class ITunesCmtBoxPrivate;
|
|
||||||
ITunesCmtBoxPrivate* d;
|
|
||||||
}; // class ITunesCmtBox
|
|
||||||
|
|
||||||
} // namespace MP4
|
|
||||||
} // namespace TagLib
|
|
||||||
|
|
||||||
#endif // ITUNESCMTBOX_H
|
|
|
@ -1,68 +0,0 @@
|
||||||
#include <iostream>
|
|
||||||
#include "itunescvrbox.h"
|
|
||||||
#include "itunesdatabox.h"
|
|
||||||
#include "mp4isobox.h"
|
|
||||||
#include "mp4file.h"
|
|
||||||
#include "tfile.h"
|
|
||||||
#include "mp4tagsproxy.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
|
|
||||||
class MP4::ITunesCvrBox::ITunesCvrBoxPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ITunesDataBox* dataBox;
|
|
||||||
};
|
|
||||||
|
|
||||||
MP4::ITunesCvrBox::ITunesCvrBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset )
|
|
||||||
:Mp4IsoBox(file, fourcc, size, offset)
|
|
||||||
{
|
|
||||||
d = new MP4::ITunesCvrBox::ITunesCvrBoxPrivate();
|
|
||||||
d->dataBox = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::ITunesCvrBox::~ITunesCvrBox()
|
|
||||||
{
|
|
||||||
if( d->dataBox != 0 )
|
|
||||||
delete d->dataBox;
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! parse the content of the box
|
|
||||||
void MP4::ITunesCvrBox::parse()
|
|
||||||
{
|
|
||||||
TagLib::MP4::File* mp4file = static_cast<MP4::File*>( file() );
|
|
||||||
|
|
||||||
// parse data box
|
|
||||||
TagLib::uint size;
|
|
||||||
MP4::Fourcc fourcc;
|
|
||||||
|
|
||||||
if(mp4file->readSizeAndType( size, fourcc ) == true)
|
|
||||||
{
|
|
||||||
// check for type - must be 'data'
|
|
||||||
if( fourcc != MP4::Fourcc("data") )
|
|
||||||
{
|
|
||||||
std::cerr << "bad atom in itunes tag - skipping it." << std::endl;
|
|
||||||
// jump over data tag
|
|
||||||
mp4file->seek( size-8, TagLib::File::Current );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
d->dataBox = new ITunesDataBox( mp4file, fourcc, size, mp4file->tell() );
|
|
||||||
d->dataBox->parsebox();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// reading unsuccessful - serious error!
|
|
||||||
std::cerr << "Error in parsing ITunesCvrBox - serious Error in taglib!" << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// register data box
|
|
||||||
mp4file->tagProxy()->registerBox( Mp4TagsProxy::cover, d->dataBox );
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
// get data pointer - just for debuging...
|
|
||||||
TagLib::String dataString( d->dataBox->data() );
|
|
||||||
std::cout << "Content of album box: " << dataString << std::endl;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
#ifndef ITUNESCVRBOX_H
|
|
||||||
#define ITUNESCVRBOX_H
|
|
||||||
|
|
||||||
#include "mp4isobox.h"
|
|
||||||
#include "mp4fourcc.h"
|
|
||||||
|
|
||||||
namespace TagLib
|
|
||||||
{
|
|
||||||
namespace MP4
|
|
||||||
{
|
|
||||||
class ITunesCvrBox: public Mp4IsoBox
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ITunesCvrBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset );
|
|
||||||
~ITunesCvrBox();
|
|
||||||
|
|
||||||
private:
|
|
||||||
//! parse the content of the box
|
|
||||||
virtual void parse();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
class ITunesCvrBoxPrivate;
|
|
||||||
ITunesCvrBoxPrivate* d;
|
|
||||||
}; // class ITunesCvrBox
|
|
||||||
|
|
||||||
} // namespace MP4
|
|
||||||
} // namespace TagLib
|
|
||||||
|
|
||||||
#endif // ITUNESCVRBOX_H
|
|
|
@ -1,42 +0,0 @@
|
||||||
#include <iostream>
|
|
||||||
#include "itunesdatabox.h"
|
|
||||||
#include "tbytevector.h"
|
|
||||||
#include "mp4isobox.h"
|
|
||||||
#include "tfile.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
|
|
||||||
class MP4::ITunesDataBox::ITunesDataBoxPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ByteVector data;
|
|
||||||
};
|
|
||||||
|
|
||||||
MP4::ITunesDataBox::ITunesDataBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset )
|
|
||||||
:Mp4IsoFullBox(file, fourcc, size, offset)
|
|
||||||
{
|
|
||||||
d = new MP4::ITunesDataBox::ITunesDataBoxPrivate();
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::ITunesDataBox::~ITunesDataBox()
|
|
||||||
{
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteVector MP4::ITunesDataBox::data() const
|
|
||||||
{
|
|
||||||
return d->data;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! parse the content of the box
|
|
||||||
void MP4::ITunesDataBox::parse()
|
|
||||||
{
|
|
||||||
// skip first 4 byte - don't know what they are supposed to be for - simply 4 zeros
|
|
||||||
file()->seek( 4, TagLib::File::Current );
|
|
||||||
// read contents - remaining size is box_size-12-4 (12:fullbox header, 4:starting zeros of data box)
|
|
||||||
#if 0
|
|
||||||
std::cout << " reading data box with data length: " << size()-16 << std::endl;
|
|
||||||
#endif
|
|
||||||
d->data = file()->readBlock( size()-12-4 );
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
#ifndef ITUNESDATABOX_H
|
|
||||||
#define ITUNESDATABOX_H
|
|
||||||
|
|
||||||
#include "mp4isofullbox.h"
|
|
||||||
#include "mp4fourcc.h"
|
|
||||||
|
|
||||||
namespace TagLib
|
|
||||||
{
|
|
||||||
namespace MP4
|
|
||||||
{
|
|
||||||
class ITunesDataBox: public Mp4IsoFullBox
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ITunesDataBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset );
|
|
||||||
~ITunesDataBox();
|
|
||||||
|
|
||||||
//! get the internal data, which can be txt or binary data as well
|
|
||||||
ByteVector data() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
//! parse the content of the box
|
|
||||||
virtual void parse();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
class ITunesDataBoxPrivate;
|
|
||||||
ITunesDataBoxPrivate* d;
|
|
||||||
}; // class ITunesDataBox
|
|
||||||
|
|
||||||
} // namespace MP4
|
|
||||||
} // namespace TagLib
|
|
||||||
|
|
||||||
#endif // ITUNESDATABOX_H
|
|
|
@ -1,68 +0,0 @@
|
||||||
#include <iostream>
|
|
||||||
#include "itunesdaybox.h"
|
|
||||||
#include "itunesdatabox.h"
|
|
||||||
#include "mp4isobox.h"
|
|
||||||
#include "mp4file.h"
|
|
||||||
#include "tfile.h"
|
|
||||||
#include "mp4tagsproxy.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
|
|
||||||
class MP4::ITunesDayBox::ITunesDayBoxPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ITunesDataBox* dataBox;
|
|
||||||
};
|
|
||||||
|
|
||||||
MP4::ITunesDayBox::ITunesDayBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset )
|
|
||||||
:Mp4IsoBox(file, fourcc, size, offset)
|
|
||||||
{
|
|
||||||
d = new MP4::ITunesDayBox::ITunesDayBoxPrivate();
|
|
||||||
d->dataBox = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::ITunesDayBox::~ITunesDayBox()
|
|
||||||
{
|
|
||||||
if( d->dataBox != 0 )
|
|
||||||
delete d->dataBox;
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! parse the content of the box
|
|
||||||
void MP4::ITunesDayBox::parse()
|
|
||||||
{
|
|
||||||
TagLib::MP4::File* mp4file = static_cast<MP4::File*>( file() );
|
|
||||||
|
|
||||||
// parse data box
|
|
||||||
TagLib::uint size;
|
|
||||||
MP4::Fourcc fourcc;
|
|
||||||
|
|
||||||
if(mp4file->readSizeAndType( size, fourcc ) == true)
|
|
||||||
{
|
|
||||||
// check for type - must be 'data'
|
|
||||||
if( fourcc != MP4::Fourcc("data") )
|
|
||||||
{
|
|
||||||
std::cerr << "bad atom in itunes tag - skipping it." << std::endl;
|
|
||||||
// jump over data tag
|
|
||||||
mp4file->seek( size-8, TagLib::File::Current );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
d->dataBox = new ITunesDataBox( mp4file, fourcc, size, mp4file->tell() );
|
|
||||||
d->dataBox->parsebox();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// reading unsuccessful - serious error!
|
|
||||||
std::cerr << "Error in parsing ITunesDayBox - serious Error in taglib!" << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// register data box
|
|
||||||
mp4file->tagProxy()->registerBox( Mp4TagsProxy::year, d->dataBox );
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
// get data pointer - just for debuging...
|
|
||||||
TagLib::String dataString( d->dataBox->data() );
|
|
||||||
std::cout << "Content of day box: " << dataString.substr(0,4) << std::endl;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
#ifndef ITUNESDAYBOX_H
|
|
||||||
#define ITUNESDAYBOX_H
|
|
||||||
|
|
||||||
#include "mp4isobox.h"
|
|
||||||
#include "mp4fourcc.h"
|
|
||||||
|
|
||||||
namespace TagLib
|
|
||||||
{
|
|
||||||
namespace MP4
|
|
||||||
{
|
|
||||||
class ITunesDayBox: public Mp4IsoBox
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ITunesDayBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset );
|
|
||||||
~ITunesDayBox();
|
|
||||||
|
|
||||||
private:
|
|
||||||
//! parse the content of the box
|
|
||||||
virtual void parse();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
class ITunesDayBoxPrivate;
|
|
||||||
ITunesDayBoxPrivate* d;
|
|
||||||
}; // class ITunesDayBox
|
|
||||||
|
|
||||||
} // namespace MP4
|
|
||||||
} // namespace TagLib
|
|
||||||
|
|
||||||
#endif // ITUNESDAYBOX_H
|
|
|
@ -1,72 +0,0 @@
|
||||||
#include <iostream>
|
|
||||||
#include "itunesdiskbox.h"
|
|
||||||
#include "itunesdatabox.h"
|
|
||||||
#include "mp4isobox.h"
|
|
||||||
#include "mp4file.h"
|
|
||||||
#include "tfile.h"
|
|
||||||
#include "mp4tagsproxy.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
|
|
||||||
class MP4::ITunesDiskBox::ITunesDiskBoxPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ITunesDataBox* dataBox;
|
|
||||||
};
|
|
||||||
|
|
||||||
MP4::ITunesDiskBox::ITunesDiskBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset )
|
|
||||||
:Mp4IsoBox(file, fourcc, size, offset)
|
|
||||||
{
|
|
||||||
d = new MP4::ITunesDiskBox::ITunesDiskBoxPrivate();
|
|
||||||
d->dataBox = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::ITunesDiskBox::~ITunesDiskBox()
|
|
||||||
{
|
|
||||||
if( d->dataBox != 0 )
|
|
||||||
delete d->dataBox;
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! parse the content of the box
|
|
||||||
void MP4::ITunesDiskBox::parse()
|
|
||||||
{
|
|
||||||
TagLib::MP4::File* mp4file = static_cast<MP4::File*>( file() );
|
|
||||||
|
|
||||||
// parse data box
|
|
||||||
TagLib::uint size;
|
|
||||||
MP4::Fourcc fourcc;
|
|
||||||
|
|
||||||
if(mp4file->readSizeAndType( size, fourcc ) == true)
|
|
||||||
{
|
|
||||||
// check for type - must be 'data'
|
|
||||||
if( fourcc != MP4::Fourcc("data") )
|
|
||||||
{
|
|
||||||
std::cerr << "bad atom in itunes tag - skipping it." << std::endl;
|
|
||||||
// jump over data tag
|
|
||||||
mp4file->seek( size-8, TagLib::File::Current );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
d->dataBox = new ITunesDataBox( mp4file, fourcc, size, mp4file->tell() );
|
|
||||||
d->dataBox->parsebox();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// reading unsuccessful - serious error!
|
|
||||||
std::cerr << "Error in parsing ITunesDiskBox - serious Error in taglib!" << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// register data box
|
|
||||||
mp4file->tagProxy()->registerBox( Mp4TagsProxy::disk, d->dataBox );
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
// get data pointer - just for debuging...
|
|
||||||
TagLib::ByteVector trknData = d->dataBox->data();
|
|
||||||
TagLib::String trknumber = TagLib::String::number( static_cast<int>( static_cast<unsigned char>(trknData[0]) << 24 |
|
|
||||||
static_cast<unsigned char>(trknData[1]) << 16 |
|
|
||||||
static_cast<unsigned char>(trknData[2]) << 8 |
|
|
||||||
static_cast<unsigned char>(trknData[3]) ) );
|
|
||||||
std::cout << "Content of tracknumber box: " << trknumber << std::endl;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
#ifndef ITUNESDISKBOX_H
|
|
||||||
#define ITUNESDISKBOX_H
|
|
||||||
|
|
||||||
#include "mp4isobox.h"
|
|
||||||
#include "mp4fourcc.h"
|
|
||||||
|
|
||||||
namespace TagLib
|
|
||||||
{
|
|
||||||
namespace MP4
|
|
||||||
{
|
|
||||||
class ITunesDiskBox: public Mp4IsoBox
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ITunesDiskBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset );
|
|
||||||
~ITunesDiskBox();
|
|
||||||
|
|
||||||
private:
|
|
||||||
//! parse the content of the box
|
|
||||||
virtual void parse();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
class ITunesDiskBoxPrivate;
|
|
||||||
ITunesDiskBoxPrivate* d;
|
|
||||||
}; // class ITunesDiskBox
|
|
||||||
|
|
||||||
} // namespace MP4
|
|
||||||
} // namespace TagLib
|
|
||||||
|
|
||||||
#endif // ITUNESDISKBOX_H
|
|
|
@ -1,68 +0,0 @@
|
||||||
#include <iostream>
|
|
||||||
#include "itunesgenbox.h"
|
|
||||||
#include "itunesdatabox.h"
|
|
||||||
#include "mp4isobox.h"
|
|
||||||
#include "mp4file.h"
|
|
||||||
#include "tfile.h"
|
|
||||||
#include "mp4tagsproxy.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
|
|
||||||
class MP4::ITunesGenBox::ITunesGenBoxPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ITunesDataBox* dataBox;
|
|
||||||
};
|
|
||||||
|
|
||||||
MP4::ITunesGenBox::ITunesGenBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset )
|
|
||||||
:Mp4IsoBox(file, fourcc, size, offset)
|
|
||||||
{
|
|
||||||
d = new MP4::ITunesGenBox::ITunesGenBoxPrivate();
|
|
||||||
d->dataBox = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::ITunesGenBox::~ITunesGenBox()
|
|
||||||
{
|
|
||||||
if( d->dataBox != 0 )
|
|
||||||
delete d->dataBox;
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! parse the content of the box
|
|
||||||
void MP4::ITunesGenBox::parse()
|
|
||||||
{
|
|
||||||
TagLib::MP4::File* mp4file = static_cast<MP4::File*>( file() );
|
|
||||||
|
|
||||||
// parse data box
|
|
||||||
TagLib::uint size;
|
|
||||||
MP4::Fourcc fourcc;
|
|
||||||
|
|
||||||
if(mp4file->readSizeAndType( size, fourcc ) == true)
|
|
||||||
{
|
|
||||||
// check for type - must be 'data'
|
|
||||||
if( fourcc != MP4::Fourcc("data") )
|
|
||||||
{
|
|
||||||
std::cerr << "bad atom in itunes tag - skipping it." << std::endl;
|
|
||||||
// jump over data tag
|
|
||||||
mp4file->seek( size-8, TagLib::File::Current );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
d->dataBox = new ITunesDataBox( mp4file, fourcc, size, mp4file->tell() );
|
|
||||||
d->dataBox->parsebox();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// reading unsuccessful - serious error!
|
|
||||||
std::cerr << "Error in parsing ITunesGenBox - serious Error in taglib!" << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// register data box
|
|
||||||
mp4file->tagProxy()->registerBox( Mp4TagsProxy::genre, d->dataBox );
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
// get data pointer - just for debuging...
|
|
||||||
TagLib::String dataString( d->dataBox->data() );
|
|
||||||
std::cout << "Content of genre box: " << dataString << std::endl;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
#ifndef ITUNESGENBOX_H
|
|
||||||
#define ITUNESGENBOX_H
|
|
||||||
|
|
||||||
#include "mp4isobox.h"
|
|
||||||
#include "mp4fourcc.h"
|
|
||||||
|
|
||||||
namespace TagLib
|
|
||||||
{
|
|
||||||
namespace MP4
|
|
||||||
{
|
|
||||||
class ITunesGenBox: public Mp4IsoBox
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ITunesGenBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset );
|
|
||||||
~ITunesGenBox();
|
|
||||||
|
|
||||||
private:
|
|
||||||
//! parse the content of the box
|
|
||||||
virtual void parse();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
class ITunesGenBoxPrivate;
|
|
||||||
ITunesGenBoxPrivate* d;
|
|
||||||
}; // class ITunesGenBox
|
|
||||||
|
|
||||||
} // namespace MP4
|
|
||||||
} // namespace TagLib
|
|
||||||
|
|
||||||
#endif // ITUNESGENBOX_H
|
|
|
@ -1,68 +0,0 @@
|
||||||
#include <iostream>
|
|
||||||
#include "itunesgrpbox.h"
|
|
||||||
#include "itunesdatabox.h"
|
|
||||||
#include "mp4isobox.h"
|
|
||||||
#include "mp4file.h"
|
|
||||||
#include "tfile.h"
|
|
||||||
#include "mp4tagsproxy.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
|
|
||||||
class MP4::ITunesGrpBox::ITunesGrpBoxPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ITunesDataBox* dataBox;
|
|
||||||
};
|
|
||||||
|
|
||||||
MP4::ITunesGrpBox::ITunesGrpBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset )
|
|
||||||
:Mp4IsoBox(file, fourcc, size, offset)
|
|
||||||
{
|
|
||||||
d = new MP4::ITunesGrpBox::ITunesGrpBoxPrivate();
|
|
||||||
d->dataBox = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::ITunesGrpBox::~ITunesGrpBox()
|
|
||||||
{
|
|
||||||
if( d->dataBox != 0 )
|
|
||||||
delete d->dataBox;
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! parse the content of the box
|
|
||||||
void MP4::ITunesGrpBox::parse()
|
|
||||||
{
|
|
||||||
TagLib::MP4::File* mp4file = static_cast<MP4::File*>( file() );
|
|
||||||
|
|
||||||
// parse data box
|
|
||||||
TagLib::uint size;
|
|
||||||
MP4::Fourcc fourcc;
|
|
||||||
|
|
||||||
if(mp4file->readSizeAndType( size, fourcc ) == true)
|
|
||||||
{
|
|
||||||
// check for type - must be 'data'
|
|
||||||
if( fourcc != MP4::Fourcc("data") )
|
|
||||||
{
|
|
||||||
std::cerr << "bad atom in itunes tag - skipping it." << std::endl;
|
|
||||||
// jump over data tag
|
|
||||||
mp4file->seek( size-8, TagLib::File::Current );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
d->dataBox = new ITunesDataBox( mp4file, fourcc, size, mp4file->tell() );
|
|
||||||
d->dataBox->parsebox();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// reading unsuccessful - serious error!
|
|
||||||
std::cerr << "Error in parsing ITunesGrpBox - serious Error in taglib!" << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// register data box
|
|
||||||
mp4file->tagProxy()->registerBox( Mp4TagsProxy::grouping, d->dataBox );
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
// get data pointer - just for debuging...
|
|
||||||
TagLib::String dataString( d->dataBox->data() );
|
|
||||||
std::cout << "Content of title box: " << dataString << std::endl;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
#ifndef ITUNESGRPBOX_H
|
|
||||||
#define ITUNESGRPBOX_H
|
|
||||||
|
|
||||||
#include "mp4isobox.h"
|
|
||||||
#include "mp4fourcc.h"
|
|
||||||
|
|
||||||
namespace TagLib
|
|
||||||
{
|
|
||||||
namespace MP4
|
|
||||||
{
|
|
||||||
class ITunesGrpBox: public Mp4IsoBox
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ITunesGrpBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset );
|
|
||||||
~ITunesGrpBox();
|
|
||||||
|
|
||||||
private:
|
|
||||||
//! parse the content of the box
|
|
||||||
virtual void parse();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
class ITunesGrpBoxPrivate;
|
|
||||||
ITunesGrpBoxPrivate* d;
|
|
||||||
}; // class ITunesGrpBox
|
|
||||||
|
|
||||||
} // namespace MP4
|
|
||||||
} // namespace TagLib
|
|
||||||
|
|
||||||
#endif // ITUNESGRPBOX_H
|
|
|
@ -1,68 +0,0 @@
|
||||||
#include <iostream>
|
|
||||||
#include "itunesnambox.h"
|
|
||||||
#include "itunesdatabox.h"
|
|
||||||
#include "mp4isobox.h"
|
|
||||||
#include "mp4file.h"
|
|
||||||
#include "tfile.h"
|
|
||||||
#include "mp4tagsproxy.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
|
|
||||||
class MP4::ITunesNamBox::ITunesNamBoxPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ITunesDataBox* dataBox;
|
|
||||||
};
|
|
||||||
|
|
||||||
MP4::ITunesNamBox::ITunesNamBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset )
|
|
||||||
:Mp4IsoBox(file, fourcc, size, offset)
|
|
||||||
{
|
|
||||||
d = new MP4::ITunesNamBox::ITunesNamBoxPrivate();
|
|
||||||
d->dataBox = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::ITunesNamBox::~ITunesNamBox()
|
|
||||||
{
|
|
||||||
if( d->dataBox != 0 )
|
|
||||||
delete d->dataBox;
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! parse the content of the box
|
|
||||||
void MP4::ITunesNamBox::parse()
|
|
||||||
{
|
|
||||||
TagLib::MP4::File* mp4file = static_cast<MP4::File*>( file() );
|
|
||||||
|
|
||||||
// parse data box
|
|
||||||
TagLib::uint size;
|
|
||||||
MP4::Fourcc fourcc;
|
|
||||||
|
|
||||||
if(mp4file->readSizeAndType( size, fourcc ) == true)
|
|
||||||
{
|
|
||||||
// check for type - must be 'data'
|
|
||||||
if( fourcc != MP4::Fourcc("data") )
|
|
||||||
{
|
|
||||||
std::cerr << "bad atom in itunes tag - skipping it." << std::endl;
|
|
||||||
// jump over data tag
|
|
||||||
mp4file->seek( size-8, TagLib::File::Current );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
d->dataBox = new ITunesDataBox( mp4file, fourcc, size, mp4file->tell() );
|
|
||||||
d->dataBox->parsebox();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// reading unsuccessful - serious error!
|
|
||||||
std::cerr << "Error in parsing ITunesNamBox - serious Error in taglib!" << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// register data box
|
|
||||||
mp4file->tagProxy()->registerBox( Mp4TagsProxy::title, d->dataBox );
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
// get data pointer - just for debuging...
|
|
||||||
TagLib::String dataString( d->dataBox->data() );
|
|
||||||
std::cout << "Content of title box: " << dataString << std::endl;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
#ifndef ITUNESNAMBOX_H
|
|
||||||
#define ITUNESNAMBOX_H
|
|
||||||
|
|
||||||
#include "mp4isobox.h"
|
|
||||||
#include "mp4fourcc.h"
|
|
||||||
|
|
||||||
namespace TagLib
|
|
||||||
{
|
|
||||||
namespace MP4
|
|
||||||
{
|
|
||||||
class ITunesNamBox: public Mp4IsoBox
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ITunesNamBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset );
|
|
||||||
~ITunesNamBox();
|
|
||||||
|
|
||||||
private:
|
|
||||||
//! parse the content of the box
|
|
||||||
virtual void parse();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
class ITunesNamBoxPrivate;
|
|
||||||
ITunesNamBoxPrivate* d;
|
|
||||||
}; // class ITunesNamBox
|
|
||||||
|
|
||||||
} // namespace MP4
|
|
||||||
} // namespace TagLib
|
|
||||||
|
|
||||||
#endif // ITUNESNAMBOX_H
|
|
|
@ -1,72 +0,0 @@
|
||||||
#include <iostream>
|
|
||||||
#include "itunestmpobox.h"
|
|
||||||
#include "itunesdatabox.h"
|
|
||||||
#include "mp4isobox.h"
|
|
||||||
#include "mp4file.h"
|
|
||||||
#include "tfile.h"
|
|
||||||
#include "mp4tagsproxy.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
|
|
||||||
class MP4::ITunesTmpoBox::ITunesTmpoBoxPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ITunesDataBox* dataBox;
|
|
||||||
};
|
|
||||||
|
|
||||||
MP4::ITunesTmpoBox::ITunesTmpoBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset )
|
|
||||||
:Mp4IsoBox(file, fourcc, size, offset)
|
|
||||||
{
|
|
||||||
d = new MP4::ITunesTmpoBox::ITunesTmpoBoxPrivate();
|
|
||||||
d->dataBox = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::ITunesTmpoBox::~ITunesTmpoBox()
|
|
||||||
{
|
|
||||||
if( d->dataBox != 0 )
|
|
||||||
delete d->dataBox;
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! parse the content of the box
|
|
||||||
void MP4::ITunesTmpoBox::parse()
|
|
||||||
{
|
|
||||||
TagLib::MP4::File* mp4file = static_cast<MP4::File*>( file() );
|
|
||||||
|
|
||||||
// parse data box
|
|
||||||
TagLib::uint size;
|
|
||||||
MP4::Fourcc fourcc;
|
|
||||||
|
|
||||||
if(mp4file->readSizeAndType( size, fourcc ) == true)
|
|
||||||
{
|
|
||||||
// check for type - must be 'data'
|
|
||||||
if( fourcc != MP4::Fourcc("data") )
|
|
||||||
{
|
|
||||||
std::cerr << "bad atom in itunes tag - skipping it." << std::endl;
|
|
||||||
// jump over data tag
|
|
||||||
mp4file->seek( size-8, TagLib::File::Current );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
d->dataBox = new ITunesDataBox( mp4file, fourcc, size, mp4file->tell() );
|
|
||||||
d->dataBox->parsebox();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// reading unsuccessful - serious error!
|
|
||||||
std::cerr << "Error in parsing ITunesTmpoBox - serious Error in taglib!" << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// register data box
|
|
||||||
mp4file->tagProxy()->registerBox( Mp4TagsProxy::bpm, d->dataBox );
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
// get data pointer - just for debuging...
|
|
||||||
TagLib::ByteVector trknData = d->dataBox->data();
|
|
||||||
TagLib::String trknumber = TagLib::String::number( static_cast<int>( static_cast<unsigned char>(trknData[0]) << 24 |
|
|
||||||
static_cast<unsigned char>(trknData[1]) << 16 |
|
|
||||||
static_cast<unsigned char>(trknData[2]) << 8 |
|
|
||||||
static_cast<unsigned char>(trknData[3]) ) );
|
|
||||||
std::cout << "Content of tracknumber box: " << trknumber << std::endl;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
#ifndef ITUNESTMPOBOX_H
|
|
||||||
#define ITUNESTMPOBOX_H
|
|
||||||
|
|
||||||
#include "mp4isobox.h"
|
|
||||||
#include "mp4fourcc.h"
|
|
||||||
|
|
||||||
namespace TagLib
|
|
||||||
{
|
|
||||||
namespace MP4
|
|
||||||
{
|
|
||||||
class ITunesTmpoBox: public Mp4IsoBox
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ITunesTmpoBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset );
|
|
||||||
~ITunesTmpoBox();
|
|
||||||
|
|
||||||
private:
|
|
||||||
//! parse the content of the box
|
|
||||||
virtual void parse();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
class ITunesTmpoBoxPrivate;
|
|
||||||
ITunesTmpoBoxPrivate* d;
|
|
||||||
}; // class ITunesTmpoBox
|
|
||||||
|
|
||||||
} // namespace MP4
|
|
||||||
} // namespace TagLib
|
|
||||||
|
|
||||||
#endif // ITUNESTMPOBOX_H
|
|
|
@ -1,72 +0,0 @@
|
||||||
#include <iostream>
|
|
||||||
#include "itunestrknbox.h"
|
|
||||||
#include "itunesdatabox.h"
|
|
||||||
#include "mp4isobox.h"
|
|
||||||
#include "mp4file.h"
|
|
||||||
#include "tfile.h"
|
|
||||||
#include "mp4tagsproxy.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
|
|
||||||
class MP4::ITunesTrknBox::ITunesTrknBoxPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ITunesDataBox* dataBox;
|
|
||||||
};
|
|
||||||
|
|
||||||
MP4::ITunesTrknBox::ITunesTrknBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset )
|
|
||||||
:Mp4IsoBox(file, fourcc, size, offset)
|
|
||||||
{
|
|
||||||
d = new MP4::ITunesTrknBox::ITunesTrknBoxPrivate();
|
|
||||||
d->dataBox = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::ITunesTrknBox::~ITunesTrknBox()
|
|
||||||
{
|
|
||||||
if( d->dataBox != 0 )
|
|
||||||
delete d->dataBox;
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! parse the content of the box
|
|
||||||
void MP4::ITunesTrknBox::parse()
|
|
||||||
{
|
|
||||||
TagLib::MP4::File* mp4file = static_cast<MP4::File*>( file() );
|
|
||||||
|
|
||||||
// parse data box
|
|
||||||
TagLib::uint size;
|
|
||||||
MP4::Fourcc fourcc;
|
|
||||||
|
|
||||||
if(mp4file->readSizeAndType( size, fourcc ) == true)
|
|
||||||
{
|
|
||||||
// check for type - must be 'data'
|
|
||||||
if( fourcc != MP4::Fourcc("data") )
|
|
||||||
{
|
|
||||||
std::cerr << "bad atom in itunes tag - skipping it." << std::endl;
|
|
||||||
// jump over data tag
|
|
||||||
mp4file->seek( size-8, TagLib::File::Current );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
d->dataBox = new ITunesDataBox( mp4file, fourcc, size, mp4file->tell() );
|
|
||||||
d->dataBox->parsebox();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// reading unsuccessful - serious error!
|
|
||||||
std::cerr << "Error in parsing ITunesTrknBox - serious Error in taglib!" << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// register data box
|
|
||||||
mp4file->tagProxy()->registerBox( Mp4TagsProxy::trackno, d->dataBox );
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
// get data pointer - just for debuging...
|
|
||||||
TagLib::ByteVector trknData = d->dataBox->data();
|
|
||||||
TagLib::String trknumber = TagLib::String::number( static_cast<int>( static_cast<unsigned char>(trknData[0]) << 24 |
|
|
||||||
static_cast<unsigned char>(trknData[1]) << 16 |
|
|
||||||
static_cast<unsigned char>(trknData[2]) << 8 |
|
|
||||||
static_cast<unsigned char>(trknData[3]) ) );
|
|
||||||
std::cout << "Content of tracknumber box: " << trknumber << std::endl;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
#ifndef ITUNESTRKNBOX_H
|
|
||||||
#define ITUNESTRKNBOX_H
|
|
||||||
|
|
||||||
#include "mp4isobox.h"
|
|
||||||
#include "mp4fourcc.h"
|
|
||||||
|
|
||||||
namespace TagLib
|
|
||||||
{
|
|
||||||
namespace MP4
|
|
||||||
{
|
|
||||||
class ITunesTrknBox: public Mp4IsoBox
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ITunesTrknBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset );
|
|
||||||
~ITunesTrknBox();
|
|
||||||
|
|
||||||
private:
|
|
||||||
//! parse the content of the box
|
|
||||||
virtual void parse();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
class ITunesTrknBoxPrivate;
|
|
||||||
ITunesTrknBoxPrivate* d;
|
|
||||||
}; // class ITunesTrknBox
|
|
||||||
|
|
||||||
} // namespace MP4
|
|
||||||
} // namespace TagLib
|
|
||||||
|
|
||||||
#endif // ITUNESTRKNBOX_H
|
|
|
@ -1,68 +0,0 @@
|
||||||
#include <iostream>
|
|
||||||
#include "ituneswrtbox.h"
|
|
||||||
#include "itunesdatabox.h"
|
|
||||||
#include "mp4isobox.h"
|
|
||||||
#include "mp4file.h"
|
|
||||||
#include "tfile.h"
|
|
||||||
#include "mp4tagsproxy.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
|
|
||||||
class MP4::ITunesWrtBox::ITunesWrtBoxPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ITunesDataBox* dataBox;
|
|
||||||
};
|
|
||||||
|
|
||||||
MP4::ITunesWrtBox::ITunesWrtBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset )
|
|
||||||
:Mp4IsoBox(file, fourcc, size, offset)
|
|
||||||
{
|
|
||||||
d = new MP4::ITunesWrtBox::ITunesWrtBoxPrivate();
|
|
||||||
d->dataBox = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::ITunesWrtBox::~ITunesWrtBox()
|
|
||||||
{
|
|
||||||
if( d->dataBox != 0 )
|
|
||||||
delete d->dataBox;
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! parse the content of the box
|
|
||||||
void MP4::ITunesWrtBox::parse()
|
|
||||||
{
|
|
||||||
TagLib::MP4::File* mp4file = static_cast<MP4::File*>( file() );
|
|
||||||
|
|
||||||
// parse data box
|
|
||||||
TagLib::uint size;
|
|
||||||
MP4::Fourcc fourcc;
|
|
||||||
|
|
||||||
if(mp4file->readSizeAndType( size, fourcc ) == true)
|
|
||||||
{
|
|
||||||
// check for type - must be 'data'
|
|
||||||
if( fourcc != MP4::Fourcc("data") )
|
|
||||||
{
|
|
||||||
std::cerr << "bad atom in itunes tag - skipping it." << std::endl;
|
|
||||||
// jump over data tag
|
|
||||||
mp4file->seek( size-8, TagLib::File::Current );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
d->dataBox = new ITunesDataBox( mp4file, fourcc, size, mp4file->tell() );
|
|
||||||
d->dataBox->parsebox();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// reading unsuccessful - serious error!
|
|
||||||
std::cerr << "Error in parsing ITunesWrtBox - serious Error in taglib!" << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// register data box
|
|
||||||
mp4file->tagProxy()->registerBox( Mp4TagsProxy::composer, d->dataBox );
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
// get data pointer - just for debuging...
|
|
||||||
TagLib::String dataString( d->dataBox->data() );
|
|
||||||
std::cout << "Content of title box: " << dataString << std::endl;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
#ifndef ITUNESWRTBOX_H
|
|
||||||
#define ITUNESWRTBOX_H
|
|
||||||
|
|
||||||
#include "mp4isobox.h"
|
|
||||||
#include "mp4fourcc.h"
|
|
||||||
|
|
||||||
namespace TagLib
|
|
||||||
{
|
|
||||||
namespace MP4
|
|
||||||
{
|
|
||||||
class ITunesWrtBox: public Mp4IsoBox
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ITunesWrtBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset );
|
|
||||||
~ITunesWrtBox();
|
|
||||||
|
|
||||||
private:
|
|
||||||
//! parse the content of the box
|
|
||||||
virtual void parse();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
class ITunesWrtBoxPrivate;
|
|
||||||
ITunesWrtBoxPrivate* d;
|
|
||||||
}; // class ITunesWrtBox
|
|
||||||
|
|
||||||
} // namespace MP4
|
|
||||||
} // namespace TagLib
|
|
||||||
|
|
||||||
#endif // ITUNESWRTBOX_H
|
|
|
@ -1,54 +0,0 @@
|
||||||
#include "mp4audioproperties.h"
|
|
||||||
#include "mp4propsproxy.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
|
|
||||||
class MP4::AudioProperties::AudioPropertiesPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
MP4::Mp4PropsProxy* propsproxy;
|
|
||||||
}; // AudioPropertiesPrivate
|
|
||||||
|
|
||||||
MP4::AudioProperties::AudioProperties():TagLib::AudioProperties(TagLib::AudioProperties::Average)
|
|
||||||
{
|
|
||||||
d = new MP4::AudioProperties::AudioPropertiesPrivate();
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::AudioProperties::~AudioProperties()
|
|
||||||
{
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MP4::AudioProperties::setProxy( Mp4PropsProxy* proxy )
|
|
||||||
{
|
|
||||||
d->propsproxy = proxy;
|
|
||||||
}
|
|
||||||
|
|
||||||
int MP4::AudioProperties::length() const
|
|
||||||
{
|
|
||||||
if( d->propsproxy == 0 )
|
|
||||||
return 0;
|
|
||||||
return d->propsproxy->seconds();
|
|
||||||
}
|
|
||||||
|
|
||||||
int MP4::AudioProperties::bitrate() const
|
|
||||||
{
|
|
||||||
if( d->propsproxy == 0 )
|
|
||||||
return 0;
|
|
||||||
return d->propsproxy->bitRate()/1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
int MP4::AudioProperties::sampleRate() const
|
|
||||||
{
|
|
||||||
if( d->propsproxy == 0 )
|
|
||||||
return 0;
|
|
||||||
return d->propsproxy->sampleRate();
|
|
||||||
}
|
|
||||||
|
|
||||||
int MP4::AudioProperties::channels() const
|
|
||||||
{
|
|
||||||
if( d->propsproxy == 0 )
|
|
||||||
return 0;
|
|
||||||
return d->propsproxy->channels();
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,52 +0,0 @@
|
||||||
#ifndef MP4AUDIOPROPERTIES_H
|
|
||||||
#define MP4AUDIOPROPERTIES_H MP4AUDIOPROPERTIES_H
|
|
||||||
|
|
||||||
#include "audioproperties.h"
|
|
||||||
|
|
||||||
namespace TagLib
|
|
||||||
{
|
|
||||||
namespace MP4
|
|
||||||
{
|
|
||||||
class Mp4PropsProxy;
|
|
||||||
|
|
||||||
class AudioProperties : public TagLib::AudioProperties
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//! constructor
|
|
||||||
AudioProperties();
|
|
||||||
//! destructor
|
|
||||||
~AudioProperties();
|
|
||||||
|
|
||||||
//! function to set the proxy
|
|
||||||
void setProxy( Mp4PropsProxy* proxy );
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the lenght of the file in seconds.
|
|
||||||
*/
|
|
||||||
int length() const;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the most appropriate bit rate for the file in kb/s. For constant
|
|
||||||
* bitrate formats this is simply the bitrate of the file. For variable
|
|
||||||
* bitrate formats this is either the average or nominal bitrate.
|
|
||||||
*/
|
|
||||||
int bitrate() const;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the sample rate in Hz.
|
|
||||||
*/
|
|
||||||
int sampleRate() const;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the number of audio channels.
|
|
||||||
*/
|
|
||||||
int channels() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
class AudioPropertiesPrivate;
|
|
||||||
AudioPropertiesPrivate* d;
|
|
||||||
};
|
|
||||||
} // namespace MP4
|
|
||||||
} // namespace TagLib
|
|
||||||
|
|
||||||
#endif // MP4AUDIOPROPERTIES_H
|
|
|
@ -1,124 +0,0 @@
|
||||||
#include <iostream>
|
|
||||||
#include "mp4audiosampleentry.h"
|
|
||||||
#include "mp4isobox.h"
|
|
||||||
#include "mp4file.h"
|
|
||||||
#include "mp4propsproxy.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
|
|
||||||
class MP4::Mp4AudioSampleEntry::Mp4AudioSampleEntryPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TagLib::uint channelcount;
|
|
||||||
TagLib::uint samplerate;
|
|
||||||
TagLib::uint bitrate;
|
|
||||||
};
|
|
||||||
|
|
||||||
MP4::Mp4AudioSampleEntry::Mp4AudioSampleEntry( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset )
|
|
||||||
:Mp4SampleEntry(file, fourcc, size, offset)
|
|
||||||
{
|
|
||||||
d = new MP4::Mp4AudioSampleEntry::Mp4AudioSampleEntryPrivate();
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::Mp4AudioSampleEntry::~Mp4AudioSampleEntry()
|
|
||||||
{
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
TagLib::uint MP4::Mp4AudioSampleEntry::channels() const
|
|
||||||
{
|
|
||||||
return d->channelcount;
|
|
||||||
}
|
|
||||||
|
|
||||||
TagLib::uint MP4::Mp4AudioSampleEntry::samplerate() const
|
|
||||||
{
|
|
||||||
return d->samplerate;
|
|
||||||
}
|
|
||||||
|
|
||||||
TagLib::uint MP4::Mp4AudioSampleEntry::bitrate() const
|
|
||||||
{
|
|
||||||
return d->bitrate;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MP4::Mp4AudioSampleEntry::parseEntry()
|
|
||||||
{
|
|
||||||
TagLib::MP4::File* mp4file = static_cast<TagLib::MP4::File*>(file());
|
|
||||||
if(!mp4file)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// read 8 reserved bytes
|
|
||||||
mp4file->seek( 8, TagLib::File::Current );
|
|
||||||
// read channelcount
|
|
||||||
if(!mp4file->readShort( d->channelcount ))
|
|
||||||
return;
|
|
||||||
// seek over samplesize, pre_defined and reserved
|
|
||||||
mp4file->seek( 6, TagLib::File::Current );
|
|
||||||
// read samplerate
|
|
||||||
if(!mp4file->readInt( d->samplerate ))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// register box at proxy
|
|
||||||
mp4file->propProxy()->registerAudioSampleEntry( this );
|
|
||||||
|
|
||||||
|
|
||||||
//std::cout << "fourcc of audio sample entry: " << fourcc().toString() << std::endl;
|
|
||||||
// check for both mp4a (plain files) and drms (encrypted files)
|
|
||||||
if( (fourcc() == MP4::Fourcc("mp4a")) ||
|
|
||||||
(fourcc() == MP4::Fourcc("drms")) )
|
|
||||||
{
|
|
||||||
TagLib::MP4::Fourcc fourcc;
|
|
||||||
TagLib::uint esds_size;
|
|
||||||
|
|
||||||
mp4file->readSizeAndType( esds_size, fourcc );
|
|
||||||
|
|
||||||
// read esds' main parts
|
|
||||||
if( size()-48 > 0 )
|
|
||||||
ByteVector flags_version = mp4file->readBlock(4);
|
|
||||||
else
|
|
||||||
return;
|
|
||||||
|
|
||||||
ByteVector EsDescrTag = mp4file->readBlock(1);
|
|
||||||
// first 4 bytes contain full box specifics (version & flags)
|
|
||||||
// upcoming byte must be ESDescrTag (0x03)
|
|
||||||
if( EsDescrTag[0] == 0x03 )
|
|
||||||
{
|
|
||||||
TagLib::uint descr_len = mp4file->readSystemsLen();
|
|
||||||
TagLib::uint EsId;
|
|
||||||
if( !mp4file->readShort( EsId ) )
|
|
||||||
return;
|
|
||||||
ByteVector priority = mp4file->readBlock(1);
|
|
||||||
if( descr_len < 20 )
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TagLib::uint EsId;
|
|
||||||
if( !mp4file->readShort( EsId ) )
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// read decoder configuration tag (0x04)
|
|
||||||
ByteVector DecCfgTag = mp4file->readBlock(1);
|
|
||||||
if( DecCfgTag[0] != 0x04 )
|
|
||||||
return;
|
|
||||||
// read decoder configuration length
|
|
||||||
TagLib::uint deccfg_len = mp4file->readSystemsLen();
|
|
||||||
// read object type Id
|
|
||||||
ByteVector objId = mp4file->readBlock(1);
|
|
||||||
// read stream type id
|
|
||||||
ByteVector strId = mp4file->readBlock(1);
|
|
||||||
// read buffer Size DB
|
|
||||||
ByteVector bufferSizeDB = mp4file->readBlock(3);
|
|
||||||
// read max bitrate
|
|
||||||
TagLib::uint max_bitrate;
|
|
||||||
if( !mp4file->readInt( max_bitrate ) )
|
|
||||||
return;
|
|
||||||
// read average bitrate
|
|
||||||
if( !mp4file->readInt( d->bitrate ) )
|
|
||||||
return;
|
|
||||||
// skip the rest
|
|
||||||
mp4file->seek( offset()+size()-8, File::Beginning );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
mp4file->seek( size()-36, File::Current );
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
#ifndef MP4AUDIOSAMPLEENTRY_H
|
|
||||||
#define MP4AUDIOSAMPLEENTRY_H
|
|
||||||
|
|
||||||
#include "mp4sampleentry.h"
|
|
||||||
#include "mp4fourcc.h"
|
|
||||||
|
|
||||||
namespace TagLib
|
|
||||||
{
|
|
||||||
namespace MP4
|
|
||||||
{
|
|
||||||
class Mp4AudioSampleEntry: public Mp4SampleEntry
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Mp4AudioSampleEntry( File* file, MP4::Fourcc fourcc, uint size, long offset );
|
|
||||||
~Mp4AudioSampleEntry();
|
|
||||||
|
|
||||||
//! function to get the number of channels
|
|
||||||
TagLib::uint channels() const;
|
|
||||||
//! function to get the sample rate
|
|
||||||
TagLib::uint samplerate() const;
|
|
||||||
//! function to get the average bitrate of the audio stream
|
|
||||||
TagLib::uint bitrate() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
//! parse the content of the box
|
|
||||||
void parseEntry();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
class Mp4AudioSampleEntryPrivate;
|
|
||||||
Mp4AudioSampleEntryPrivate* d;
|
|
||||||
}; // class Mp4AudioSampleEntry
|
|
||||||
|
|
||||||
} // namespace MP4
|
|
||||||
} // namespace TagLib
|
|
||||||
|
|
||||||
#endif // MP4AUDIOSAMPLEENTRY_H
|
|
|
@ -1,390 +0,0 @@
|
||||||
#include <tbytevector.h>
|
|
||||||
#include <tstring.h>
|
|
||||||
#include <tdebug.h>
|
|
||||||
#include "tlist.h"
|
|
||||||
|
|
||||||
#include "id3v1genres.h"
|
|
||||||
|
|
||||||
#include "mp4itunestag.h"
|
|
||||||
#include "mp4file.h"
|
|
||||||
#include "boxfactory.h"
|
|
||||||
#include "mp4tagsproxy.h"
|
|
||||||
#include "mp4propsproxy.h"
|
|
||||||
#include "mp4audioproperties.h"
|
|
||||||
#include "itunesdatabox.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
|
|
||||||
class MP4::File::FilePrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//! list for all boxes of the mp4 file
|
|
||||||
TagLib::List<MP4::Mp4IsoBox*> boxes;
|
|
||||||
//! the box factory - will create all boxes by tag and size
|
|
||||||
MP4::BoxFactory boxfactory;
|
|
||||||
//! proxy for the tags is filled after parsing
|
|
||||||
MP4::Mp4TagsProxy tagsProxy;
|
|
||||||
//! proxy for audio properties
|
|
||||||
MP4::Mp4PropsProxy propsProxy;
|
|
||||||
//! the tag returned by tag() function
|
|
||||||
MP4::Tag mp4tag;
|
|
||||||
//! container for the audio properties returned by properties() function
|
|
||||||
MP4::AudioProperties mp4audioproperties;
|
|
||||||
//! is set to valid after successfull parsing
|
|
||||||
bool isValid;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! function to fill the tags with converted proxy data, which has been parsed out of the file previously
|
|
||||||
static void fillTagFromProxy( MP4::Mp4TagsProxy& proxy, MP4::Tag& mp4tag );
|
|
||||||
|
|
||||||
MP4::File::File() : TagLib::File()
|
|
||||||
{
|
|
||||||
// create member container
|
|
||||||
d = new MP4::File::FilePrivate();
|
|
||||||
d->isValid = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::File::File(const char *file, bool , AudioProperties::ReadStyle )
|
|
||||||
:TagLib::File( file )
|
|
||||||
{
|
|
||||||
// create member container
|
|
||||||
d = new MP4::File::FilePrivate();
|
|
||||||
|
|
||||||
read();
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::File::~File()
|
|
||||||
{
|
|
||||||
TagLib::List<Mp4IsoBox*>::Iterator delIter;
|
|
||||||
for( delIter = d->boxes.begin();
|
|
||||||
delIter != d->boxes.end();
|
|
||||||
delIter++ )
|
|
||||||
{
|
|
||||||
delete *delIter;
|
|
||||||
}
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
Tag *MP4::File::tag() const
|
|
||||||
{
|
|
||||||
return &d->mp4tag;
|
|
||||||
}
|
|
||||||
|
|
||||||
AudioProperties * MP4::File::audioProperties() const
|
|
||||||
{
|
|
||||||
d->mp4audioproperties.setProxy( &d->propsProxy );
|
|
||||||
return &d->mp4audioproperties;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MP4::File::read( bool, TagLib::AudioProperties::ReadStyle )
|
|
||||||
{
|
|
||||||
d->isValid = false;
|
|
||||||
TagLib::uint size;
|
|
||||||
MP4::Fourcc fourcc;
|
|
||||||
|
|
||||||
while( readSizeAndType( size, fourcc ) == true )
|
|
||||||
{
|
|
||||||
// create the appropriate subclass and parse it
|
|
||||||
MP4::Mp4IsoBox* curbox = d->boxfactory.createInstance( this, fourcc, size, tell() );
|
|
||||||
curbox->parsebox();
|
|
||||||
d->boxes.append( curbox );
|
|
||||||
}
|
|
||||||
|
|
||||||
for( TagLib::List<MP4::Mp4IsoBox*>::Iterator iter = d->boxes.begin();
|
|
||||||
iter != d->boxes.end();
|
|
||||||
iter++ )
|
|
||||||
{
|
|
||||||
if( (*iter)->fourcc() == MP4::Fourcc("moov") )
|
|
||||||
{
|
|
||||||
d->isValid = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( d->isValid )
|
|
||||||
debug( "file is valid" );
|
|
||||||
else
|
|
||||||
debug( "file is NOT valid" );
|
|
||||||
|
|
||||||
// fill tags from proxy data
|
|
||||||
fillTagFromProxy( d->tagsProxy, d->mp4tag );
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MP4::File::save()
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MP4::File::remove()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
TagLib::uint MP4::File::readSystemsLen()
|
|
||||||
{
|
|
||||||
TagLib::uint length = 0;
|
|
||||||
TagLib::uint nbytes = 0;
|
|
||||||
ByteVector input;
|
|
||||||
TagLib::uchar tmp_input;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
input = readBlock(1);
|
|
||||||
tmp_input = static_cast<TagLib::uchar>(input[0]);
|
|
||||||
nbytes++;
|
|
||||||
length = (length<<7) | (tmp_input&0x7F);
|
|
||||||
} while( (tmp_input&0x80) && (nbytes<4) );
|
|
||||||
|
|
||||||
return length;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MP4::File::readSizeAndType( TagLib::uint& size, MP4::Fourcc& fourcc )
|
|
||||||
{
|
|
||||||
// read the two blocks from file
|
|
||||||
ByteVector readsize = readBlock(4);
|
|
||||||
ByteVector readtype = readBlock(4);
|
|
||||||
|
|
||||||
if( (readsize.size() != 4) || (readtype.size() != 4) )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// set size
|
|
||||||
size = static_cast<unsigned char>(readsize[0]) << 24 |
|
|
||||||
static_cast<unsigned char>(readsize[1]) << 16 |
|
|
||||||
static_cast<unsigned char>(readsize[2]) << 8 |
|
|
||||||
static_cast<unsigned char>(readsize[3]);
|
|
||||||
if (size == 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// set fourcc
|
|
||||||
fourcc = readtype.data();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MP4::File::readInt( TagLib::uint& toRead )
|
|
||||||
{
|
|
||||||
ByteVector readbuffer = readBlock(4);
|
|
||||||
if( readbuffer.size() != 4 )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
toRead = static_cast<unsigned char>(readbuffer[0]) << 24 |
|
|
||||||
static_cast<unsigned char>(readbuffer[1]) << 16 |
|
|
||||||
static_cast<unsigned char>(readbuffer[2]) << 8 |
|
|
||||||
static_cast<unsigned char>(readbuffer[3]);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MP4::File::readShort( TagLib::uint& toRead )
|
|
||||||
{
|
|
||||||
ByteVector readbuffer = readBlock(2);
|
|
||||||
if( readbuffer.size() != 2 )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
toRead = static_cast<unsigned char>(readbuffer[0]) << 8 |
|
|
||||||
static_cast<unsigned char>(readbuffer[1]);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MP4::File::readLongLong( TagLib::ulonglong& toRead )
|
|
||||||
{
|
|
||||||
ByteVector readbuffer = readBlock(8);
|
|
||||||
if( readbuffer.size() != 8 )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
toRead = static_cast<ulonglong>(static_cast<unsigned char>(readbuffer[0])) << 56 |
|
|
||||||
static_cast<ulonglong>(static_cast<unsigned char>(readbuffer[1])) << 48 |
|
|
||||||
static_cast<ulonglong>(static_cast<unsigned char>(readbuffer[2])) << 40 |
|
|
||||||
static_cast<ulonglong>(static_cast<unsigned char>(readbuffer[3])) << 32 |
|
|
||||||
static_cast<ulonglong>(static_cast<unsigned char>(readbuffer[4])) << 24 |
|
|
||||||
static_cast<ulonglong>(static_cast<unsigned char>(readbuffer[5])) << 16 |
|
|
||||||
static_cast<ulonglong>(static_cast<unsigned char>(readbuffer[6])) << 8 |
|
|
||||||
static_cast<ulonglong>(static_cast<unsigned char>(readbuffer[7]));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MP4::File::readFourcc( TagLib::MP4::Fourcc& fourcc )
|
|
||||||
{
|
|
||||||
ByteVector readtype = readBlock(4);
|
|
||||||
|
|
||||||
if( readtype.size() != 4)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// set fourcc
|
|
||||||
fourcc = readtype.data();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::Mp4TagsProxy* MP4::File::tagProxy() const
|
|
||||||
{
|
|
||||||
return &d->tagsProxy;
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::Mp4PropsProxy* MP4::File::propProxy() const
|
|
||||||
{
|
|
||||||
return &d->propsProxy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This function has been updated based on information at */
|
|
||||||
/* "http://atomicparsley.sourceforge.net/mpeg-4files.html". */
|
|
||||||
void fillTagFromProxy( MP4::Mp4TagsProxy& proxy, MP4::Tag& mp4tag )
|
|
||||||
{
|
|
||||||
// tmp buffer for each tag
|
|
||||||
MP4::ITunesDataBox* databox;
|
|
||||||
|
|
||||||
databox = proxy.titleData();
|
|
||||||
if( databox != 0 )
|
|
||||||
{
|
|
||||||
// convert data to string
|
|
||||||
TagLib::String datastring( databox->data(), String::UTF8 );
|
|
||||||
// check if string was set
|
|
||||||
if( !(datastring == "") )
|
|
||||||
mp4tag.setTitle( datastring );
|
|
||||||
}
|
|
||||||
|
|
||||||
databox = proxy.artistData();
|
|
||||||
if( databox != 0 )
|
|
||||||
{
|
|
||||||
// convert data to string
|
|
||||||
TagLib::String datastring( databox->data(), String::UTF8 );
|
|
||||||
// check if string was set
|
|
||||||
if( !(datastring == "") )
|
|
||||||
mp4tag.setArtist( datastring );
|
|
||||||
}
|
|
||||||
|
|
||||||
databox = proxy.albumData();
|
|
||||||
if( databox != 0 )
|
|
||||||
{
|
|
||||||
// convert data to string
|
|
||||||
TagLib::String datastring( databox->data(), String::UTF8 );
|
|
||||||
// check if string was set
|
|
||||||
if( !(datastring == "") )
|
|
||||||
mp4tag.setAlbum( datastring );
|
|
||||||
}
|
|
||||||
|
|
||||||
databox = proxy.genreData();
|
|
||||||
if( databox != 0 )
|
|
||||||
{
|
|
||||||
if (databox->flags() == 0)
|
|
||||||
{
|
|
||||||
// convert data to uint
|
|
||||||
TagLib::ByteVector datavec = databox->data();
|
|
||||||
int genreVal = static_cast<int>( datavec[1] );
|
|
||||||
if (genreVal > 0)
|
|
||||||
{
|
|
||||||
TagLib::String datastring = ID3v1::genre( genreVal - 1 );
|
|
||||||
// check if string was set
|
|
||||||
if( !(datastring == "") )
|
|
||||||
mp4tag.setGenre( datastring );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// convert data to string
|
|
||||||
TagLib::String datastring( databox->data(), String::UTF8 );
|
|
||||||
// check if string was set
|
|
||||||
if( !(datastring == "") )
|
|
||||||
mp4tag.setGenre( datastring );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
databox = proxy.yearData();
|
|
||||||
if( databox != 0 )
|
|
||||||
{
|
|
||||||
// convert data to string
|
|
||||||
TagLib::String datastring( databox->data(), String::UTF8 );
|
|
||||||
// check if string was set
|
|
||||||
if( !(datastring == "") )
|
|
||||||
mp4tag.setYear( datastring.toInt() );
|
|
||||||
}
|
|
||||||
|
|
||||||
databox = proxy.trknData();
|
|
||||||
if( databox != 0 )
|
|
||||||
{
|
|
||||||
// convert data to uint
|
|
||||||
TagLib::ByteVector datavec = databox->data();
|
|
||||||
if( datavec.size() >= 6 )
|
|
||||||
{
|
|
||||||
TagLib::uint notracks = static_cast<TagLib::uint>( datavec[5] );
|
|
||||||
mp4tag.setNumTracks( notracks );
|
|
||||||
}
|
|
||||||
if( datavec.size() >= 4 )
|
|
||||||
{
|
|
||||||
TagLib::uint trackno = static_cast<TagLib::uint>( datavec[3] );
|
|
||||||
mp4tag.setTrack( trackno );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
mp4tag.setTrack( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
databox = proxy.commentData();
|
|
||||||
if( databox != 0 )
|
|
||||||
{
|
|
||||||
// convert data to string
|
|
||||||
TagLib::String datastring( databox->data(), String::UTF8 );
|
|
||||||
// check if string was set
|
|
||||||
if( !(datastring == "") )
|
|
||||||
mp4tag.setComment( datastring );
|
|
||||||
}
|
|
||||||
|
|
||||||
databox = proxy.groupingData();
|
|
||||||
if( databox != 0 )
|
|
||||||
{
|
|
||||||
// convert data to string
|
|
||||||
TagLib::String datastring( databox->data(), String::UTF8 );
|
|
||||||
// check if string was set
|
|
||||||
if( !(datastring == "") )
|
|
||||||
mp4tag.setGrouping( datastring );
|
|
||||||
}
|
|
||||||
|
|
||||||
databox = proxy.composerData();
|
|
||||||
if( databox != 0 )
|
|
||||||
{
|
|
||||||
// convert data to string
|
|
||||||
TagLib::String datastring( databox->data(), String::UTF8 );
|
|
||||||
// check if string was set
|
|
||||||
if( !(datastring == "") )
|
|
||||||
mp4tag.setComposer( datastring );
|
|
||||||
}
|
|
||||||
|
|
||||||
databox = proxy.diskData();
|
|
||||||
if( databox != 0 )
|
|
||||||
{
|
|
||||||
// convert data to uint
|
|
||||||
TagLib::ByteVector datavec = databox->data();
|
|
||||||
if( datavec.size() >= 6 )
|
|
||||||
{
|
|
||||||
TagLib::uint nodiscs = static_cast<TagLib::uint>( datavec[5] );
|
|
||||||
mp4tag.setNumDisks( nodiscs );
|
|
||||||
}
|
|
||||||
if( datavec.size() >= 4 )
|
|
||||||
{
|
|
||||||
TagLib::uint discno = static_cast<TagLib::uint>( datavec[3] );
|
|
||||||
mp4tag.setDisk( discno );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
mp4tag.setDisk( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
databox = proxy.bpmData();
|
|
||||||
if( databox != 0 )
|
|
||||||
{
|
|
||||||
// convert data to uint
|
|
||||||
TagLib::ByteVector datavec = databox->data();
|
|
||||||
|
|
||||||
if( datavec.size() >= 2 )
|
|
||||||
{
|
|
||||||
TagLib::uint bpm = static_cast<TagLib::uint>( static_cast<unsigned char>(datavec[0]) << 8 |
|
|
||||||
static_cast<unsigned char>(datavec[1]) );
|
|
||||||
mp4tag.setBpm( bpm );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
mp4tag.setBpm( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
databox = proxy.coverData();
|
|
||||||
if( databox != 0 )
|
|
||||||
{
|
|
||||||
// get byte vector
|
|
||||||
mp4tag.setCover( databox->data() );
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,162 +0,0 @@
|
||||||
/***************************************************************************
|
|
||||||
copyright : (C) 2002, 2003 by Jochen Issing
|
|
||||||
email : jochen.issing@isign-softart.de
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* 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 *
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
#ifndef TAGLIB_MP4FILE_H
|
|
||||||
#define TAGLIB_MP4FILE_H
|
|
||||||
|
|
||||||
#include <tfile.h>
|
|
||||||
#include <audioproperties.h>
|
|
||||||
|
|
||||||
#include "mp4fourcc.h"
|
|
||||||
|
|
||||||
namespace TagLib {
|
|
||||||
|
|
||||||
typedef unsigned long long ulonglong;
|
|
||||||
|
|
||||||
class Tag;
|
|
||||||
|
|
||||||
namespace MP4
|
|
||||||
{
|
|
||||||
class Mp4TagsProxy;
|
|
||||||
class Mp4PropsProxy;
|
|
||||||
|
|
||||||
//! An implementation of TagLib::File with mp4 itunes specific methods
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* This implements and provides an interface for mp4 itunes files to the
|
|
||||||
* TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing
|
|
||||||
* the abstract TagLib::File API as well as providing some additional
|
|
||||||
* information specific to mp4 itunes files. (TODO)
|
|
||||||
*/
|
|
||||||
|
|
||||||
class File : public TagLib::File
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/*!
|
|
||||||
* Contructs an mp4 itunes file object without reading a file. Allows object
|
|
||||||
* fields to be set up before reading.
|
|
||||||
*/
|
|
||||||
File();
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Contructs an mp4 itunes file from \a file. If \a readProperties is true the
|
|
||||||
* file's audio properties will also be read using \a propertiesStyle. If
|
|
||||||
* false, \a propertiesStyle is ignored.
|
|
||||||
*/
|
|
||||||
File(const char *file, bool readProperties = true,
|
|
||||||
TagLib::AudioProperties::ReadStyle propertiesStyle = TagLib::AudioProperties::Average);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Destroys this instance of the File.
|
|
||||||
*/
|
|
||||||
virtual ~File();
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the Tag for this file. This will be an APE tag, an ID3v1 tag
|
|
||||||
* or a combination of the two.
|
|
||||||
*/
|
|
||||||
virtual TagLib::Tag *tag() const;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the mp4 itunes::Properties for this file. If no audio properties
|
|
||||||
* were read then this will return a null pointer.
|
|
||||||
*/
|
|
||||||
virtual AudioProperties *audioProperties() const;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Reads from mp4 itunes file. If \a readProperties is true the file's
|
|
||||||
* audio properties will also be read using \a propertiesStyle. If false,
|
|
||||||
* \a propertiesStyle is ignored.
|
|
||||||
*/
|
|
||||||
void read(bool readProperties = true,
|
|
||||||
TagLib::AudioProperties::ReadStyle propertiesStyle = TagLib::AudioProperties::Average);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Saves the file.
|
|
||||||
*/
|
|
||||||
virtual bool save();
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* This will remove all tags.
|
|
||||||
*
|
|
||||||
* \note This will also invalidate pointers to the tags
|
|
||||||
* as their memory will be freed.
|
|
||||||
* \note In order to make the removal permanent save() still needs to be called
|
|
||||||
*/
|
|
||||||
void remove();
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Helper function for parsing the MP4 file - reads the size and type of the next box.
|
|
||||||
* Returns true if read succeeded - not at EOF
|
|
||||||
*/
|
|
||||||
bool readSizeAndType( TagLib::uint& size, MP4::Fourcc& fourcc );
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Helper function to read the length of an descriptor in systems manner
|
|
||||||
*/
|
|
||||||
TagLib::uint readSystemsLen();
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Helper function for reading an unsigned int out of the file (big endian method)
|
|
||||||
*/
|
|
||||||
bool readInt( TagLib::uint& toRead );
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Helper function for reading an unsigned short out of the file (big endian method)
|
|
||||||
*/
|
|
||||||
bool readShort( TagLib::uint& toRead );
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Helper function for reading an unsigned long long (64bit) out of the file (big endian method)
|
|
||||||
*/
|
|
||||||
bool readLongLong( TagLib::ulonglong& toRead );
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Helper function to read a fourcc code
|
|
||||||
*/
|
|
||||||
bool readFourcc( TagLib::MP4::Fourcc& fourcc );
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Function to get the tags proxy for registration of the tags boxes.
|
|
||||||
* The proxy provides direct access to the data boxes of the certain tags - normally
|
|
||||||
* covered by several levels of subboxes
|
|
||||||
*/
|
|
||||||
Mp4TagsProxy* tagProxy() const;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Function to get the properties proxy for registration of the properties boxes.
|
|
||||||
* The proxy provides direct access to the needed boxes describing audio properties.
|
|
||||||
*/
|
|
||||||
Mp4PropsProxy* propProxy() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
File(const File &);
|
|
||||||
File &operator=(const File &);
|
|
||||||
|
|
||||||
class FilePrivate;
|
|
||||||
FilePrivate *d;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace MP4
|
|
||||||
|
|
||||||
} // namespace TagLib
|
|
||||||
|
|
||||||
#endif // TAGLIB_MP4FILE_H
|
|
|
@ -1,63 +0,0 @@
|
||||||
#include "mp4fourcc.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
|
|
||||||
MP4::Fourcc::Fourcc()
|
|
||||||
{
|
|
||||||
m_fourcc = 0U;
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::Fourcc::Fourcc( TagLib::String fourcc )
|
|
||||||
{
|
|
||||||
m_fourcc = 0U;
|
|
||||||
|
|
||||||
if( fourcc.size() >= 4 )
|
|
||||||
m_fourcc = static_cast<unsigned char>(fourcc[0]) << 24 |
|
|
||||||
static_cast<unsigned char>(fourcc[1]) << 16 |
|
|
||||||
static_cast<unsigned char>(fourcc[2]) << 8 |
|
|
||||||
static_cast<unsigned char>(fourcc[3]);
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::Fourcc::~Fourcc()
|
|
||||||
{}
|
|
||||||
|
|
||||||
TagLib::String MP4::Fourcc::toString() const
|
|
||||||
{
|
|
||||||
TagLib::String fourcc;
|
|
||||||
fourcc.append(static_cast<char>(m_fourcc >> 24 & 0xFF));
|
|
||||||
fourcc.append(static_cast<char>(m_fourcc >> 16 & 0xFF));
|
|
||||||
fourcc.append(static_cast<char>(m_fourcc >> 8 & 0xFF));
|
|
||||||
fourcc.append(static_cast<char>(m_fourcc & 0xFF));
|
|
||||||
|
|
||||||
return fourcc;
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::Fourcc::operator unsigned int() const
|
|
||||||
{
|
|
||||||
return m_fourcc;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MP4::Fourcc::operator == (unsigned int fourccB ) const
|
|
||||||
{
|
|
||||||
return (m_fourcc==fourccB);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MP4::Fourcc::operator != (unsigned int fourccB ) const
|
|
||||||
{
|
|
||||||
return (m_fourcc!=fourccB);
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::Fourcc& MP4::Fourcc::operator = (unsigned int fourcc )
|
|
||||||
{
|
|
||||||
m_fourcc = fourcc;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::Fourcc& MP4::Fourcc::operator = (char fourcc[4])
|
|
||||||
{
|
|
||||||
m_fourcc = static_cast<unsigned char>(fourcc[0]) << 24 |
|
|
||||||
static_cast<unsigned char>(fourcc[1]) << 16 |
|
|
||||||
static_cast<unsigned char>(fourcc[2]) << 8 |
|
|
||||||
static_cast<unsigned char>(fourcc[3]);
|
|
||||||
return *this;
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
#ifndef MP4FOURCC_H
|
|
||||||
#define MP4FOURCC_H
|
|
||||||
|
|
||||||
#include "tstring.h"
|
|
||||||
|
|
||||||
namespace TagLib
|
|
||||||
{
|
|
||||||
namespace MP4
|
|
||||||
{
|
|
||||||
/*! union for easy fourcc / type handling */
|
|
||||||
class Fourcc
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//! std constructor
|
|
||||||
Fourcc();
|
|
||||||
//! string constructor
|
|
||||||
Fourcc(TagLib::String fourcc);
|
|
||||||
|
|
||||||
//! destructor
|
|
||||||
~Fourcc();
|
|
||||||
|
|
||||||
//! function to get a string version of the fourcc
|
|
||||||
TagLib::String toString() const;
|
|
||||||
//! cast operator to unsigned int
|
|
||||||
operator unsigned int() const;
|
|
||||||
//! comparison operator
|
|
||||||
bool operator == (unsigned int fourccB ) const;
|
|
||||||
//! comparison operator
|
|
||||||
bool operator != (unsigned int fourccB ) const;
|
|
||||||
//! assigment operator for unsigned int
|
|
||||||
Fourcc& operator = (unsigned int fourcc );
|
|
||||||
//! assigment operator for character string
|
|
||||||
Fourcc& operator = (char fourcc[4]);
|
|
||||||
|
|
||||||
private:
|
|
||||||
uint m_fourcc; /*!< integer code of the fourcc */
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace MP4
|
|
||||||
} // namespace TagLib
|
|
||||||
|
|
||||||
#endif // MP4FOURCC_H
|
|
|
@ -1,54 +0,0 @@
|
||||||
#include <deque>
|
|
||||||
#include <iostream>
|
|
||||||
#include "mp4hdlrbox.h"
|
|
||||||
#include "boxfactory.h"
|
|
||||||
#include "mp4file.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
|
|
||||||
class MP4::Mp4HdlrBox::Mp4HdlrBoxPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TagLib::uint pre_defined;
|
|
||||||
MP4::Fourcc handler_type;
|
|
||||||
TagLib::String hdlr_string;
|
|
||||||
}; // class Mp4HdlrBoxPrivate
|
|
||||||
|
|
||||||
MP4::Mp4HdlrBox::Mp4HdlrBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset )
|
|
||||||
: Mp4IsoFullBox( file, fourcc, size, offset )
|
|
||||||
{
|
|
||||||
d = new MP4::Mp4HdlrBox::Mp4HdlrBoxPrivate();
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::Mp4HdlrBox::~Mp4HdlrBox()
|
|
||||||
{
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::Fourcc MP4::Mp4HdlrBox::hdlr_type() const
|
|
||||||
{
|
|
||||||
return d->handler_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
TagLib::String MP4::Mp4HdlrBox::hdlr_string() const
|
|
||||||
{
|
|
||||||
return d->hdlr_string;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MP4::Mp4HdlrBox::parse()
|
|
||||||
{
|
|
||||||
TagLib::uint totalread = 12+20;
|
|
||||||
|
|
||||||
TagLib::MP4::File* mp4file = static_cast<MP4::File*>( file() );
|
|
||||||
if( mp4file->readInt( d->pre_defined ) == false )
|
|
||||||
return;
|
|
||||||
if( mp4file->readFourcc( d->handler_type ) == false )
|
|
||||||
return;
|
|
||||||
|
|
||||||
// read reserved into trash
|
|
||||||
mp4file->seek( 3*4, TagLib::File::Current );
|
|
||||||
|
|
||||||
// check if there are bytes remaining - used for hdlr string
|
|
||||||
if( size() - totalread != 0 )
|
|
||||||
d->hdlr_string = mp4file->readBlock( size()-totalread );
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
#ifndef MP4HDLRBOX_H
|
|
||||||
#define MP4HDLRBOX_H
|
|
||||||
|
|
||||||
#include "mp4isofullbox.h"
|
|
||||||
#include "mp4fourcc.h"
|
|
||||||
|
|
||||||
namespace TagLib
|
|
||||||
{
|
|
||||||
namespace MP4
|
|
||||||
{
|
|
||||||
class Mp4HdlrBox: public Mp4IsoFullBox
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Mp4HdlrBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset );
|
|
||||||
~Mp4HdlrBox();
|
|
||||||
|
|
||||||
//! parse hdlr contents
|
|
||||||
void parse();
|
|
||||||
//! get the handler type
|
|
||||||
MP4::Fourcc hdlr_type() const;
|
|
||||||
//! get the hdlr string
|
|
||||||
TagLib::String hdlr_string() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
class Mp4HdlrBoxPrivate;
|
|
||||||
Mp4HdlrBoxPrivate* d;
|
|
||||||
}; // Mp4HdlrBox
|
|
||||||
|
|
||||||
} // namespace MP4
|
|
||||||
} // namespace TagLib
|
|
||||||
|
|
||||||
#endif // MP4HDLRBOX_H
|
|
|
@ -1,76 +0,0 @@
|
||||||
#include "tlist.h"
|
|
||||||
#include <iostream>
|
|
||||||
#include "mp4ilstbox.h"
|
|
||||||
#include "boxfactory.h"
|
|
||||||
#include "mp4file.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
|
|
||||||
class MP4::Mp4IlstBox::Mp4IlstBoxPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//! container for all boxes in ilst box
|
|
||||||
TagLib::List<Mp4IsoBox*> ilstBoxes;
|
|
||||||
//! a box factory for creating the appropriate boxes
|
|
||||||
MP4::BoxFactory boxfactory;
|
|
||||||
}; // class Mp4IlstBoxPrivate
|
|
||||||
|
|
||||||
MP4::Mp4IlstBox::Mp4IlstBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset )
|
|
||||||
: Mp4IsoBox( file, fourcc, size, offset )
|
|
||||||
{
|
|
||||||
d = new MP4::Mp4IlstBox::Mp4IlstBoxPrivate();
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::Mp4IlstBox::~Mp4IlstBox()
|
|
||||||
{
|
|
||||||
TagLib::List<Mp4IsoBox*>::Iterator delIter;
|
|
||||||
for( delIter = d->ilstBoxes.begin();
|
|
||||||
delIter != d->ilstBoxes.end();
|
|
||||||
delIter++ )
|
|
||||||
{
|
|
||||||
delete *delIter;
|
|
||||||
}
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MP4::Mp4IlstBox::parse()
|
|
||||||
{
|
|
||||||
#if 0
|
|
||||||
std::cout << " parsing ilst box" << std::endl;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
TagLib::MP4::File* mp4file = static_cast<MP4::File*>( file() );
|
|
||||||
|
|
||||||
TagLib::uint totalsize = 8;
|
|
||||||
// parse all contained boxes
|
|
||||||
TagLib::uint size;
|
|
||||||
MP4::Fourcc fourcc;
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
std::cout << " ";
|
|
||||||
#endif
|
|
||||||
while( (mp4file->readSizeAndType( size, fourcc ) == true) )
|
|
||||||
{
|
|
||||||
totalsize += size;
|
|
||||||
|
|
||||||
// check for errors
|
|
||||||
if( totalsize > MP4::Mp4IsoBox::size() )
|
|
||||||
{
|
|
||||||
std::cerr << "Error in mp4 file " << mp4file->name() << " ilst box contains bad box with name: " << fourcc.toString() << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// create the appropriate subclass and parse it
|
|
||||||
MP4::Mp4IsoBox* curbox = d->boxfactory.createInstance( mp4file, fourcc, size, mp4file->tell() );
|
|
||||||
curbox->parsebox();
|
|
||||||
d->ilstBoxes.append( curbox );
|
|
||||||
|
|
||||||
// check for end of ilst box
|
|
||||||
if( totalsize == MP4::Mp4IsoBox::size() )
|
|
||||||
break;
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
std::cout << " ";
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
#ifndef MP4ILSTBOX_H
|
|
||||||
#define MP4ILSTBOX_H
|
|
||||||
|
|
||||||
#include "mp4isobox.h"
|
|
||||||
#include "mp4fourcc.h"
|
|
||||||
|
|
||||||
namespace TagLib
|
|
||||||
{
|
|
||||||
namespace MP4
|
|
||||||
{
|
|
||||||
class Mp4IlstBox: public Mp4IsoBox
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Mp4IlstBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset );
|
|
||||||
~Mp4IlstBox();
|
|
||||||
|
|
||||||
//! parse ilst contents
|
|
||||||
void parse();
|
|
||||||
|
|
||||||
private:
|
|
||||||
class Mp4IlstBoxPrivate;
|
|
||||||
Mp4IlstBoxPrivate* d;
|
|
||||||
}; // Mp4IlstBox
|
|
||||||
|
|
||||||
} // namespace MP4
|
|
||||||
} // namespace TagLib
|
|
||||||
|
|
||||||
#endif // MP4ILSTBOX_H
|
|
|
@ -1,55 +0,0 @@
|
||||||
#include "mp4isobox.h"
|
|
||||||
#include "tfile.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
|
|
||||||
class MP4::Mp4IsoBox::Mp4IsoBoxPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
MP4::Fourcc fourcc;
|
|
||||||
TagLib::uint size;
|
|
||||||
long offset;
|
|
||||||
TagLib::File* file;
|
|
||||||
};
|
|
||||||
|
|
||||||
MP4::Mp4IsoBox::Mp4IsoBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset )
|
|
||||||
{
|
|
||||||
d = new MP4::Mp4IsoBox::Mp4IsoBoxPrivate();
|
|
||||||
d->file = file;
|
|
||||||
d->fourcc = fourcc;
|
|
||||||
d->size = size;
|
|
||||||
d->offset = offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::Mp4IsoBox::~Mp4IsoBox()
|
|
||||||
{
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MP4::Mp4IsoBox::parsebox()
|
|
||||||
{
|
|
||||||
// seek to offset
|
|
||||||
file()->seek( offset(), File::Beginning );
|
|
||||||
// simply call parse method of sub class
|
|
||||||
parse();
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::Fourcc MP4::Mp4IsoBox::fourcc() const
|
|
||||||
{
|
|
||||||
return d->fourcc;
|
|
||||||
}
|
|
||||||
|
|
||||||
TagLib::uint MP4::Mp4IsoBox::size() const
|
|
||||||
{
|
|
||||||
return d->size;
|
|
||||||
}
|
|
||||||
|
|
||||||
long MP4::Mp4IsoBox::offset() const
|
|
||||||
{
|
|
||||||
return d->offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
TagLib::File* MP4::Mp4IsoBox::file() const
|
|
||||||
{
|
|
||||||
return d->file;
|
|
||||||
}
|
|
|
@ -1,46 +0,0 @@
|
||||||
#ifndef MP4ISOBOX_H
|
|
||||||
#define MP4ISOBOX_H
|
|
||||||
|
|
||||||
#include "taglib.h"
|
|
||||||
#include "mp4fourcc.h"
|
|
||||||
|
|
||||||
namespace TagLib
|
|
||||||
{
|
|
||||||
class File;
|
|
||||||
|
|
||||||
namespace MP4
|
|
||||||
{
|
|
||||||
class Mp4IsoBox
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//! constructor for base class
|
|
||||||
Mp4IsoBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset );
|
|
||||||
//! destructor - simply freeing private ptr
|
|
||||||
virtual ~Mp4IsoBox();
|
|
||||||
|
|
||||||
//! function to get the fourcc code
|
|
||||||
MP4::Fourcc fourcc() const;
|
|
||||||
//! function to get the size of tha atom/box
|
|
||||||
uint size() const;
|
|
||||||
//! function to get the offset of the atom in the mp4 file
|
|
||||||
long offset() const;
|
|
||||||
|
|
||||||
//! parse wrapper to get common interface for both box and fullbox
|
|
||||||
virtual void parsebox();
|
|
||||||
//! pure virtual function for all subclasses to implement
|
|
||||||
virtual void parse() = 0;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
//! function to get the file pointer
|
|
||||||
TagLib::File* file() const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
class Mp4IsoBoxPrivate;
|
|
||||||
Mp4IsoBoxPrivate* d;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace MP4
|
|
||||||
} // namespace TagLib
|
|
||||||
|
|
||||||
#endif // MP4ISOBOX_H
|
|
||||||
|
|
|
@ -1,46 +0,0 @@
|
||||||
#include "mp4isofullbox.h"
|
|
||||||
#include "tfile.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
|
|
||||||
class MP4::Mp4IsoFullBox::Mp4IsoFullBoxPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
uchar version;
|
|
||||||
uint flags;
|
|
||||||
}; // Mp4IsoFullBoxPrivate
|
|
||||||
|
|
||||||
|
|
||||||
MP4::Mp4IsoFullBox::Mp4IsoFullBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset )
|
|
||||||
: Mp4IsoBox( file, fourcc, size, offset )
|
|
||||||
{
|
|
||||||
d = new MP4::Mp4IsoFullBox::Mp4IsoFullBoxPrivate();
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::Mp4IsoFullBox::~Mp4IsoFullBox()
|
|
||||||
{
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MP4::Mp4IsoFullBox::parsebox()
|
|
||||||
{
|
|
||||||
// seek to offset
|
|
||||||
Mp4IsoBox::file()->seek(Mp4IsoBox::offset(), File::Beginning );
|
|
||||||
// parse version and flags
|
|
||||||
ByteVector version_flags = Mp4IsoBox::file()->readBlock(4);
|
|
||||||
d->version = version_flags[0];
|
|
||||||
d->flags = version_flags[1] << 16 || version_flags[2] << 8 || version_flags[3];
|
|
||||||
// call parse method of subclass
|
|
||||||
parse();
|
|
||||||
}
|
|
||||||
|
|
||||||
TagLib::uchar MP4::Mp4IsoFullBox::version()
|
|
||||||
{
|
|
||||||
return d->version;
|
|
||||||
}
|
|
||||||
|
|
||||||
TagLib::uint MP4::Mp4IsoFullBox::flags()
|
|
||||||
{
|
|
||||||
return d->flags;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
#ifndef MP4ISOFULLBOX_H
|
|
||||||
#define MP4ISOFULLBOX_H
|
|
||||||
|
|
||||||
#include "mp4isobox.h"
|
|
||||||
#include "mp4fourcc.h"
|
|
||||||
|
|
||||||
namespace TagLib
|
|
||||||
{
|
|
||||||
namespace MP4
|
|
||||||
{
|
|
||||||
class Mp4IsoFullBox : public Mp4IsoBox
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//! constructor for full box
|
|
||||||
Mp4IsoFullBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset );
|
|
||||||
//! destructor for mp4 iso full box
|
|
||||||
virtual ~Mp4IsoFullBox();
|
|
||||||
|
|
||||||
//! function to get the version of box
|
|
||||||
uchar version();
|
|
||||||
//! function to get the flag map
|
|
||||||
uint flags();
|
|
||||||
|
|
||||||
//! parse wrapper to get common interface for both box and fullbox
|
|
||||||
virtual void parsebox();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
class Mp4IsoFullBoxPrivate;
|
|
||||||
Mp4IsoFullBoxPrivate* d;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace MP4
|
|
||||||
} // namespace TagLib
|
|
||||||
|
|
||||||
#endif // MP4ISOFULLBOX_H
|
|
||||||
|
|
|
@ -1,202 +0,0 @@
|
||||||
#include "mp4itunestag.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
|
|
||||||
class MP4::Tag::TagPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
MP4::File* mp4file;
|
|
||||||
TagLib::String title;
|
|
||||||
TagLib::String artist;
|
|
||||||
TagLib::String album;
|
|
||||||
TagLib::String genre;
|
|
||||||
TagLib::uint year;
|
|
||||||
TagLib::uint track;
|
|
||||||
TagLib::uint numTracks;
|
|
||||||
TagLib::String comment;
|
|
||||||
TagLib::String grouping;
|
|
||||||
TagLib::String composer;
|
|
||||||
TagLib::uint disk;
|
|
||||||
TagLib::uint numDisks;
|
|
||||||
TagLib::uint bpm;
|
|
||||||
bool isEmpty;
|
|
||||||
TagLib::ByteVector cover;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
MP4::Tag::Tag( )
|
|
||||||
{
|
|
||||||
d = new TagPrivate();
|
|
||||||
d->year = 0;
|
|
||||||
d->track = 0;
|
|
||||||
d->numTracks = 0;
|
|
||||||
d->disk = 0;
|
|
||||||
d->numTracks = 0;
|
|
||||||
d->bpm = 0;
|
|
||||||
d->isEmpty = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::Tag::~Tag()
|
|
||||||
{
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
String MP4::Tag::title() const
|
|
||||||
{
|
|
||||||
return d->title;
|
|
||||||
}
|
|
||||||
|
|
||||||
String MP4::Tag::artist() const
|
|
||||||
{
|
|
||||||
return d->artist;
|
|
||||||
}
|
|
||||||
|
|
||||||
String MP4::Tag::album() const
|
|
||||||
{
|
|
||||||
return d->album;
|
|
||||||
}
|
|
||||||
|
|
||||||
String MP4::Tag::comment() const
|
|
||||||
{
|
|
||||||
return d->comment;
|
|
||||||
}
|
|
||||||
|
|
||||||
String MP4::Tag::genre() const
|
|
||||||
{
|
|
||||||
return d->genre;
|
|
||||||
}
|
|
||||||
|
|
||||||
TagLib::uint MP4::Tag::year() const
|
|
||||||
{
|
|
||||||
return d->year;
|
|
||||||
}
|
|
||||||
|
|
||||||
TagLib::uint MP4::Tag::track() const
|
|
||||||
{
|
|
||||||
return d->track;
|
|
||||||
}
|
|
||||||
|
|
||||||
TagLib::uint MP4::Tag::numTracks() const
|
|
||||||
{
|
|
||||||
return d->numTracks;
|
|
||||||
}
|
|
||||||
|
|
||||||
String MP4::Tag::grouping() const
|
|
||||||
{
|
|
||||||
return d->grouping;
|
|
||||||
}
|
|
||||||
|
|
||||||
String MP4::Tag::composer() const
|
|
||||||
{
|
|
||||||
return d->composer;
|
|
||||||
}
|
|
||||||
|
|
||||||
TagLib::uint MP4::Tag::disk() const
|
|
||||||
{
|
|
||||||
return d->disk;
|
|
||||||
}
|
|
||||||
|
|
||||||
TagLib::uint MP4::Tag::numDisks() const
|
|
||||||
{
|
|
||||||
return d->numDisks;
|
|
||||||
}
|
|
||||||
|
|
||||||
TagLib::uint MP4::Tag::bpm() const
|
|
||||||
{
|
|
||||||
return d->bpm;
|
|
||||||
}
|
|
||||||
|
|
||||||
TagLib::ByteVector MP4::Tag::cover() const
|
|
||||||
{
|
|
||||||
return d->cover;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MP4::Tag::setTitle(const String &s)
|
|
||||||
{
|
|
||||||
d->title = s;
|
|
||||||
d->isEmpty = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MP4::Tag::setArtist(const String &s)
|
|
||||||
{
|
|
||||||
d->artist = s;
|
|
||||||
d->isEmpty = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MP4::Tag::setAlbum(const String &s)
|
|
||||||
{
|
|
||||||
d->album = s;
|
|
||||||
d->isEmpty = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MP4::Tag::setComment(const String &s)
|
|
||||||
{
|
|
||||||
d->comment = s;
|
|
||||||
d->isEmpty = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MP4::Tag::setGenre(const String &s)
|
|
||||||
{
|
|
||||||
d->genre = s;
|
|
||||||
d->isEmpty = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MP4::Tag::setYear(TagLib::uint i)
|
|
||||||
{
|
|
||||||
d->year = i;
|
|
||||||
d->isEmpty = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MP4::Tag::setTrack(TagLib::uint i)
|
|
||||||
{
|
|
||||||
d->track = i;
|
|
||||||
d->isEmpty = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MP4::Tag::setNumTracks(TagLib::uint i)
|
|
||||||
{
|
|
||||||
d->numTracks = i;
|
|
||||||
d->isEmpty = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MP4::Tag::setGrouping(const String &s)
|
|
||||||
{
|
|
||||||
d->grouping = s;
|
|
||||||
d->isEmpty = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MP4::Tag::setComposer(const String &s)
|
|
||||||
{
|
|
||||||
d->composer = s;
|
|
||||||
d->isEmpty = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MP4::Tag::setDisk(const TagLib::uint i)
|
|
||||||
{
|
|
||||||
d->disk = i;
|
|
||||||
d->isEmpty = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MP4::Tag::setNumDisks(const TagLib::uint i)
|
|
||||||
{
|
|
||||||
d->numDisks = i;
|
|
||||||
d->isEmpty = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MP4::Tag::setBpm(const TagLib::uint i)
|
|
||||||
{
|
|
||||||
d->bpm = i;
|
|
||||||
d->isEmpty = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MP4::Tag::setCover(const TagLib::ByteVector& c)
|
|
||||||
{
|
|
||||||
d->cover = c;
|
|
||||||
d->isEmpty = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MP4::Tag::isEmpty() const
|
|
||||||
{
|
|
||||||
return d->isEmpty;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,76 +0,0 @@
|
||||||
#ifndef MP4ITUNESTAG_H
|
|
||||||
#define MP4ITUNESTAG_H
|
|
||||||
|
|
||||||
#include "taglib.h"
|
|
||||||
#include "tstring.h"
|
|
||||||
#include "tag.h"
|
|
||||||
|
|
||||||
namespace TagLib
|
|
||||||
{
|
|
||||||
namespace MP4
|
|
||||||
{
|
|
||||||
class File;
|
|
||||||
|
|
||||||
class Tag : public TagLib::Tag
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/*!
|
|
||||||
* Constructs an empty MP4 iTunes tag.
|
|
||||||
*/
|
|
||||||
Tag( );
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Destroys this Tag instance.
|
|
||||||
*/
|
|
||||||
virtual ~Tag();
|
|
||||||
|
|
||||||
// Reimplementations.
|
|
||||||
|
|
||||||
virtual String title() const;
|
|
||||||
virtual String artist() const;
|
|
||||||
virtual String album() const;
|
|
||||||
virtual String comment() const;
|
|
||||||
virtual String genre() const;
|
|
||||||
virtual uint year() const;
|
|
||||||
virtual uint track() const;
|
|
||||||
|
|
||||||
virtual void setTitle(const String &s);
|
|
||||||
virtual void setArtist(const String &s);
|
|
||||||
virtual void setAlbum(const String &s);
|
|
||||||
virtual void setComment(const String &s);
|
|
||||||
virtual void setGenre(const String &s);
|
|
||||||
virtual void setYear(uint i);
|
|
||||||
virtual void setTrack(uint i);
|
|
||||||
|
|
||||||
// MP4 specific fields
|
|
||||||
|
|
||||||
String grouping() const;
|
|
||||||
String composer() const;
|
|
||||||
uint numTracks() const;
|
|
||||||
uint disk() const;
|
|
||||||
uint numDisks() const;
|
|
||||||
uint bpm() const;
|
|
||||||
ByteVector cover() const;
|
|
||||||
|
|
||||||
void setGrouping(const String &s);
|
|
||||||
void setComposer(const String &s);
|
|
||||||
void setNumTracks(const uint i);
|
|
||||||
void setDisk(const uint i);
|
|
||||||
void setNumDisks(const uint i);
|
|
||||||
void setBpm(const uint i);
|
|
||||||
void setCover( const ByteVector& cover );
|
|
||||||
|
|
||||||
virtual bool isEmpty() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Tag(const Tag &);
|
|
||||||
Tag &operator=(const Tag &);
|
|
||||||
|
|
||||||
class TagPrivate;
|
|
||||||
TagPrivate *d;
|
|
||||||
};
|
|
||||||
} // namespace MP4
|
|
||||||
|
|
||||||
} // namespace TagLib
|
|
||||||
|
|
||||||
#endif // MP4ITUNESTAG_H
|
|
|
@ -1,90 +0,0 @@
|
||||||
#include "tlist.h"
|
|
||||||
#include <iostream>
|
|
||||||
#include "mp4mdiabox.h"
|
|
||||||
#include "mp4hdlrbox.h"
|
|
||||||
#include "mp4minfbox.h"
|
|
||||||
#include "boxfactory.h"
|
|
||||||
#include "mp4file.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
|
|
||||||
class MP4::Mp4MdiaBox::Mp4MdiaBoxPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//! container for all boxes in mdia box
|
|
||||||
TagLib::List<Mp4IsoBox*> mdiaBoxes;
|
|
||||||
//! a box factory for creating the appropriate boxes
|
|
||||||
MP4::BoxFactory boxfactory;
|
|
||||||
}; // class Mp4MdiaBoxPrivate
|
|
||||||
|
|
||||||
MP4::Mp4MdiaBox::Mp4MdiaBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset )
|
|
||||||
: Mp4IsoBox( file, fourcc, size, offset )
|
|
||||||
{
|
|
||||||
d = new MP4::Mp4MdiaBox::Mp4MdiaBoxPrivate();
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::Mp4MdiaBox::~Mp4MdiaBox()
|
|
||||||
{
|
|
||||||
TagLib::List<Mp4IsoBox*>::Iterator delIter;
|
|
||||||
for( delIter = d->mdiaBoxes.begin();
|
|
||||||
delIter != d->mdiaBoxes.end();
|
|
||||||
delIter++ )
|
|
||||||
{
|
|
||||||
delete *delIter;
|
|
||||||
}
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MP4::Mp4MdiaBox::parse()
|
|
||||||
{
|
|
||||||
TagLib::MP4::File* mp4file = static_cast<MP4::File*>( file() );
|
|
||||||
|
|
||||||
TagLib::uint totalsize = 8;
|
|
||||||
// parse all contained boxes
|
|
||||||
TagLib::uint size;
|
|
||||||
MP4::Fourcc fourcc;
|
|
||||||
|
|
||||||
// stores the current handler type
|
|
||||||
TagLib::MP4::Fourcc hdlrtype;
|
|
||||||
|
|
||||||
while( (mp4file->readSizeAndType( size, fourcc ) == true) )
|
|
||||||
{
|
|
||||||
totalsize += size;
|
|
||||||
|
|
||||||
// check for errors
|
|
||||||
if( totalsize > MP4::Mp4IsoBox::size() )
|
|
||||||
{
|
|
||||||
std::cerr << "Error in mp4 file " << mp4file->name() << " mdia box contains bad box with name: " << fourcc.toString() << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// create the appropriate subclass and parse it
|
|
||||||
MP4::Mp4IsoBox* curbox = d->boxfactory.createInstance( mp4file, fourcc, size, mp4file->tell() );
|
|
||||||
if( static_cast<TagLib::uint>( fourcc ) == 0x6d696e66 /*"minf"*/ )
|
|
||||||
{
|
|
||||||
// cast to minf
|
|
||||||
Mp4MinfBox* minfbox = static_cast<Mp4MinfBox*>( curbox );
|
|
||||||
if(!minfbox)
|
|
||||||
return;
|
|
||||||
// set handler type
|
|
||||||
minfbox->setHandlerType( hdlrtype );
|
|
||||||
}
|
|
||||||
|
|
||||||
curbox->parsebox();
|
|
||||||
d->mdiaBoxes.append( curbox );
|
|
||||||
|
|
||||||
if(static_cast<TagLib::uint>( fourcc ) == 0x68646c72 /*"hdlr"*/ )
|
|
||||||
{
|
|
||||||
// cast to hdlr box
|
|
||||||
Mp4HdlrBox* hdlrbox = static_cast<Mp4HdlrBox*>( curbox );
|
|
||||||
if(!hdlrbox)
|
|
||||||
return;
|
|
||||||
// get handler type
|
|
||||||
hdlrtype = hdlrbox->hdlr_type();
|
|
||||||
}
|
|
||||||
// check for end of mdia box
|
|
||||||
if( totalsize == MP4::Mp4IsoBox::size() )
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
#ifndef MP4MDIABOX_H
|
|
||||||
#define MP4MDIABOX_H
|
|
||||||
|
|
||||||
#include "mp4isobox.h"
|
|
||||||
#include "mp4fourcc.h"
|
|
||||||
|
|
||||||
namespace TagLib
|
|
||||||
{
|
|
||||||
namespace MP4
|
|
||||||
{
|
|
||||||
class Mp4MdiaBox: public Mp4IsoBox
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Mp4MdiaBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset );
|
|
||||||
~Mp4MdiaBox();
|
|
||||||
|
|
||||||
//! parse mdia contents
|
|
||||||
void parse();
|
|
||||||
|
|
||||||
private:
|
|
||||||
class Mp4MdiaBoxPrivate;
|
|
||||||
Mp4MdiaBoxPrivate* d;
|
|
||||||
}; // Mp4MdiaBox
|
|
||||||
|
|
||||||
} // namespace MP4
|
|
||||||
} // namespace TagLib
|
|
||||||
|
|
||||||
#endif // MP4MDIABOX_H
|
|
|
@ -1,65 +0,0 @@
|
||||||
#include <tlist.h>
|
|
||||||
#include <iostream>
|
|
||||||
#include "mp4metabox.h"
|
|
||||||
#include "boxfactory.h"
|
|
||||||
#include "mp4file.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
|
|
||||||
class MP4::Mp4MetaBox::Mp4MetaBoxPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//! container for all boxes in meta box
|
|
||||||
TagLib::List<Mp4IsoBox*> metaBoxes;
|
|
||||||
//! a box factory for creating the appropriate boxes
|
|
||||||
MP4::BoxFactory boxfactory;
|
|
||||||
}; // class Mp4MetaBoxPrivate
|
|
||||||
|
|
||||||
MP4::Mp4MetaBox::Mp4MetaBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset )
|
|
||||||
: Mp4IsoFullBox( file, fourcc, size, offset )
|
|
||||||
{
|
|
||||||
d = new MP4::Mp4MetaBox::Mp4MetaBoxPrivate();
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::Mp4MetaBox::~Mp4MetaBox()
|
|
||||||
{
|
|
||||||
TagLib::List<Mp4IsoBox*>::Iterator delIter;
|
|
||||||
for( delIter = d->metaBoxes.begin();
|
|
||||||
delIter != d->metaBoxes.end();
|
|
||||||
delIter++ )
|
|
||||||
{
|
|
||||||
delete *delIter;
|
|
||||||
}
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MP4::Mp4MetaBox::parse()
|
|
||||||
{
|
|
||||||
TagLib::MP4::File* mp4file = static_cast<MP4::File*>( file() );
|
|
||||||
|
|
||||||
TagLib::uint totalsize = 12; // initial size of box
|
|
||||||
// parse all contained boxes
|
|
||||||
TagLib::uint size;
|
|
||||||
MP4::Fourcc fourcc;
|
|
||||||
|
|
||||||
while( (mp4file->readSizeAndType( size, fourcc ) == true) )
|
|
||||||
{
|
|
||||||
totalsize += size;
|
|
||||||
|
|
||||||
// check for errors
|
|
||||||
if( totalsize > MP4::Mp4IsoBox::size() )
|
|
||||||
{
|
|
||||||
std::cerr << "Error in mp4 file " << mp4file->name() << " meta box contains bad box with name: " << fourcc.toString() << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// create the appropriate subclass and parse it
|
|
||||||
MP4::Mp4IsoBox* curbox = d->boxfactory.createInstance( mp4file, fourcc, size, mp4file->tell() );
|
|
||||||
curbox->parsebox();
|
|
||||||
d->metaBoxes.append( curbox );
|
|
||||||
|
|
||||||
// check for end of meta box
|
|
||||||
if( totalsize == MP4::Mp4IsoBox::size() )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
#ifndef MP4METABOX_H
|
|
||||||
#define MP4METABOX_H
|
|
||||||
|
|
||||||
#include "mp4isofullbox.h"
|
|
||||||
#include "mp4fourcc.h"
|
|
||||||
|
|
||||||
namespace TagLib
|
|
||||||
{
|
|
||||||
namespace MP4
|
|
||||||
{
|
|
||||||
class Mp4MetaBox: public Mp4IsoFullBox
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Mp4MetaBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset );
|
|
||||||
~Mp4MetaBox();
|
|
||||||
|
|
||||||
//! parse meta contents
|
|
||||||
void parse();
|
|
||||||
|
|
||||||
private:
|
|
||||||
class Mp4MetaBoxPrivate;
|
|
||||||
Mp4MetaBoxPrivate* d;
|
|
||||||
}; // Mp4MetaBox
|
|
||||||
|
|
||||||
} // namespace MP4
|
|
||||||
} // namespace TagLib
|
|
||||||
|
|
||||||
#endif // MP4METABOX_H
|
|
|
@ -1,83 +0,0 @@
|
||||||
#include "tlist.h"
|
|
||||||
#include <iostream>
|
|
||||||
#include "mp4minfbox.h"
|
|
||||||
#include "mp4stblbox.h"
|
|
||||||
#include "boxfactory.h"
|
|
||||||
#include "mp4file.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
|
|
||||||
class MP4::Mp4MinfBox::Mp4MinfBoxPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//! container for all boxes in minf box
|
|
||||||
TagLib::List<Mp4IsoBox*> minfBoxes;
|
|
||||||
//! a box factory for creating the appropriate boxes
|
|
||||||
MP4::BoxFactory boxfactory;
|
|
||||||
//! stores the handler type of the current trak
|
|
||||||
MP4::Fourcc handler_type;
|
|
||||||
}; // class Mp4MinfBoxPrivate
|
|
||||||
|
|
||||||
MP4::Mp4MinfBox::Mp4MinfBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset )
|
|
||||||
: Mp4IsoBox( file, fourcc, size, offset )
|
|
||||||
{
|
|
||||||
d = new MP4::Mp4MinfBox::Mp4MinfBoxPrivate();
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::Mp4MinfBox::~Mp4MinfBox()
|
|
||||||
{
|
|
||||||
TagLib::List<Mp4IsoBox*>::Iterator delIter;
|
|
||||||
for( delIter = d->minfBoxes.begin();
|
|
||||||
delIter != d->minfBoxes.end();
|
|
||||||
delIter++ )
|
|
||||||
{
|
|
||||||
delete *delIter;
|
|
||||||
}
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MP4::Mp4MinfBox::setHandlerType( MP4::Fourcc fourcc )
|
|
||||||
{
|
|
||||||
d->handler_type = fourcc;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MP4::Mp4MinfBox::parse()
|
|
||||||
{
|
|
||||||
TagLib::MP4::File* mp4file = static_cast<MP4::File*>( file() );
|
|
||||||
|
|
||||||
TagLib::uint totalsize = 8;
|
|
||||||
// parse all contained boxes
|
|
||||||
TagLib::uint size;
|
|
||||||
MP4::Fourcc fourcc;
|
|
||||||
|
|
||||||
while( (mp4file->readSizeAndType( size, fourcc ) == true) )
|
|
||||||
{
|
|
||||||
totalsize += size;
|
|
||||||
|
|
||||||
// check for errors
|
|
||||||
if( totalsize > MP4::Mp4IsoBox::size() )
|
|
||||||
{
|
|
||||||
std::cerr << "Error in mp4 file " << mp4file->name() << " minf box contains bad box with name: " << fourcc.toString() << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// create the appropriate subclass and parse it
|
|
||||||
MP4::Mp4IsoBox* curbox = d->boxfactory.createInstance( mp4file, fourcc, size, mp4file->tell() );
|
|
||||||
if(static_cast<TagLib::uint>( fourcc ) == 0x7374626c /*stbl*/ )
|
|
||||||
{
|
|
||||||
// cast to hdlr box
|
|
||||||
Mp4StblBox* stblbox = static_cast<Mp4StblBox*>( curbox );
|
|
||||||
if(!stblbox)
|
|
||||||
return;
|
|
||||||
// set handler type
|
|
||||||
stblbox->setHandlerType( d->handler_type );
|
|
||||||
}
|
|
||||||
|
|
||||||
curbox->parsebox();
|
|
||||||
d->minfBoxes.append( curbox );
|
|
||||||
|
|
||||||
// check for end of minf box
|
|
||||||
if( totalsize == MP4::Mp4IsoBox::size() )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
#ifndef MP4MINFBOX_H
|
|
||||||
#define MP4MINFBOX_H
|
|
||||||
|
|
||||||
#include "mp4isobox.h"
|
|
||||||
#include "mp4fourcc.h"
|
|
||||||
|
|
||||||
namespace TagLib
|
|
||||||
{
|
|
||||||
namespace MP4
|
|
||||||
{
|
|
||||||
class Mp4MinfBox: public Mp4IsoBox
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Mp4MinfBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset );
|
|
||||||
~Mp4MinfBox();
|
|
||||||
|
|
||||||
//! parse minf contents
|
|
||||||
void parse();
|
|
||||||
//! set the handler type - needed for stsd
|
|
||||||
void setHandlerType( MP4::Fourcc fourcc );
|
|
||||||
|
|
||||||
private:
|
|
||||||
class Mp4MinfBoxPrivate;
|
|
||||||
Mp4MinfBoxPrivate* d;
|
|
||||||
}; // Mp4MinfBox
|
|
||||||
|
|
||||||
} // namespace MP4
|
|
||||||
} // namespace TagLib
|
|
||||||
|
|
||||||
#endif // MP4MINFBOX_H
|
|
|
@ -1,65 +0,0 @@
|
||||||
#include "tlist.h"
|
|
||||||
#include <iostream>
|
|
||||||
#include "mp4moovbox.h"
|
|
||||||
#include "boxfactory.h"
|
|
||||||
#include "mp4file.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
|
|
||||||
class MP4::Mp4MoovBox::Mp4MoovBoxPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//! container for all boxes in moov box
|
|
||||||
TagLib::List<Mp4IsoBox*> moovBoxes;
|
|
||||||
//! a box factory for creating the appropriate boxes
|
|
||||||
MP4::BoxFactory boxfactory;
|
|
||||||
}; // class Mp4MoovBoxPrivate
|
|
||||||
|
|
||||||
MP4::Mp4MoovBox::Mp4MoovBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset )
|
|
||||||
: Mp4IsoBox( file, fourcc, size, offset )
|
|
||||||
{
|
|
||||||
d = new MP4::Mp4MoovBox::Mp4MoovBoxPrivate();
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::Mp4MoovBox::~Mp4MoovBox()
|
|
||||||
{
|
|
||||||
TagLib::List<Mp4IsoBox*>::Iterator delIter;
|
|
||||||
for( delIter = d->moovBoxes.begin();
|
|
||||||
delIter != d->moovBoxes.end();
|
|
||||||
delIter++ )
|
|
||||||
{
|
|
||||||
delete *delIter;
|
|
||||||
}
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MP4::Mp4MoovBox::parse()
|
|
||||||
{
|
|
||||||
TagLib::MP4::File* mp4file = static_cast<MP4::File*>( file() );
|
|
||||||
|
|
||||||
TagLib::uint totalsize = 8;
|
|
||||||
// parse all contained boxes
|
|
||||||
TagLib::uint size;
|
|
||||||
MP4::Fourcc fourcc;
|
|
||||||
|
|
||||||
while( (mp4file->readSizeAndType( size, fourcc ) == true) )
|
|
||||||
{
|
|
||||||
totalsize += size;
|
|
||||||
|
|
||||||
// check for errors
|
|
||||||
if( totalsize > MP4::Mp4IsoBox::size() )
|
|
||||||
{
|
|
||||||
std::cerr << "Error in mp4 file " << mp4file->name() << " moov box contains bad box with name: " << fourcc.toString() << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// create the appropriate subclass and parse it
|
|
||||||
MP4::Mp4IsoBox* curbox = d->boxfactory.createInstance( mp4file, fourcc, size, mp4file->tell() );
|
|
||||||
curbox->parsebox();
|
|
||||||
d->moovBoxes.append( curbox );
|
|
||||||
|
|
||||||
// check for end of moov box
|
|
||||||
if( totalsize == MP4::Mp4IsoBox::size() )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
#ifndef MP4MOOVBOX_H
|
|
||||||
#define MP4MOOVBOX_H
|
|
||||||
|
|
||||||
#include "mp4isobox.h"
|
|
||||||
#include "mp4fourcc.h"
|
|
||||||
|
|
||||||
namespace TagLib
|
|
||||||
{
|
|
||||||
namespace MP4
|
|
||||||
{
|
|
||||||
class Mp4MoovBox: public Mp4IsoBox
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Mp4MoovBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset );
|
|
||||||
~Mp4MoovBox();
|
|
||||||
|
|
||||||
//! parse moov contents
|
|
||||||
void parse();
|
|
||||||
|
|
||||||
private:
|
|
||||||
class Mp4MoovBoxPrivate;
|
|
||||||
Mp4MoovBoxPrivate* d;
|
|
||||||
}; // Mp4MoovBox
|
|
||||||
|
|
||||||
} // namespace MP4
|
|
||||||
} // namespace TagLib
|
|
||||||
|
|
||||||
#endif // MP4MOOVBOX_H
|
|
|
@ -1,119 +0,0 @@
|
||||||
#include <deque>
|
|
||||||
#include <iostream>
|
|
||||||
#include "mp4mvhdbox.h"
|
|
||||||
#include "boxfactory.h"
|
|
||||||
#include "mp4file.h"
|
|
||||||
#include "mp4propsproxy.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
|
|
||||||
class MP4::Mp4MvhdBox::Mp4MvhdBoxPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//! creation time of the file
|
|
||||||
TagLib::ulonglong creationTime;
|
|
||||||
//! modification time of the file - since midnight, Jan. 1, 1904, UTC-time
|
|
||||||
TagLib::ulonglong modificationTime;
|
|
||||||
//! timescale for the file - referred by all time specifications in this box
|
|
||||||
TagLib::uint timescale;
|
|
||||||
//! duration of presentation
|
|
||||||
TagLib::ulonglong duration;
|
|
||||||
//! playout speed
|
|
||||||
TagLib::uint rate;
|
|
||||||
//! volume for entire presentation
|
|
||||||
TagLib::uint volume;
|
|
||||||
//! track ID for an additional track (next new track)
|
|
||||||
TagLib::uint nextTrackID;
|
|
||||||
}; // class Mp4MvhdBoxPrivate
|
|
||||||
|
|
||||||
MP4::Mp4MvhdBox::Mp4MvhdBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset )
|
|
||||||
: Mp4IsoFullBox( file, fourcc, size, offset )
|
|
||||||
{
|
|
||||||
d = new MP4::Mp4MvhdBox::Mp4MvhdBoxPrivate();
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::Mp4MvhdBox::~Mp4MvhdBox()
|
|
||||||
{
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
TagLib::ulonglong MP4::Mp4MvhdBox::creationTime() const
|
|
||||||
{
|
|
||||||
return d->creationTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
TagLib::ulonglong MP4::Mp4MvhdBox::modificationTime() const
|
|
||||||
{
|
|
||||||
return d->modificationTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
TagLib::uint MP4::Mp4MvhdBox::timescale() const
|
|
||||||
{
|
|
||||||
return d->timescale;
|
|
||||||
}
|
|
||||||
|
|
||||||
TagLib::ulonglong MP4::Mp4MvhdBox::duration() const
|
|
||||||
{
|
|
||||||
return d->duration;
|
|
||||||
}
|
|
||||||
|
|
||||||
TagLib::uint MP4::Mp4MvhdBox::rate() const
|
|
||||||
{
|
|
||||||
return d->rate;
|
|
||||||
}
|
|
||||||
|
|
||||||
TagLib::uint MP4::Mp4MvhdBox::volume() const
|
|
||||||
{
|
|
||||||
return d->volume;
|
|
||||||
}
|
|
||||||
|
|
||||||
TagLib::uint MP4::Mp4MvhdBox::nextTrackID() const
|
|
||||||
{
|
|
||||||
return d->nextTrackID;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void MP4::Mp4MvhdBox::parse()
|
|
||||||
{
|
|
||||||
TagLib::MP4::File* mp4file = static_cast<MP4::File*>( file() );
|
|
||||||
|
|
||||||
if( version() == 1 )
|
|
||||||
{
|
|
||||||
if( !mp4file->readLongLong( d->creationTime ) )
|
|
||||||
return;
|
|
||||||
if( !mp4file->readLongLong( d->modificationTime ) )
|
|
||||||
return;
|
|
||||||
if( !mp4file->readInt( d->timescale ) )
|
|
||||||
return;
|
|
||||||
if( !mp4file->readLongLong( d->duration ) )
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TagLib::uint creationTime_tmp, modificationTime_tmp, duration_tmp;
|
|
||||||
|
|
||||||
if( !mp4file->readInt( creationTime_tmp ) )
|
|
||||||
return;
|
|
||||||
if( !mp4file->readInt( modificationTime_tmp ) )
|
|
||||||
return;
|
|
||||||
if( !mp4file->readInt( d->timescale ) )
|
|
||||||
return;
|
|
||||||
if( !mp4file->readInt( duration_tmp ) )
|
|
||||||
return;
|
|
||||||
|
|
||||||
d->creationTime = creationTime_tmp;
|
|
||||||
d->modificationTime = modificationTime_tmp;
|
|
||||||
d->duration = duration_tmp;
|
|
||||||
}
|
|
||||||
if( !mp4file->readInt( d->rate ) )
|
|
||||||
return;
|
|
||||||
if( !mp4file->readInt( d->volume ) )
|
|
||||||
return;
|
|
||||||
// jump over unused fields
|
|
||||||
mp4file->seek( 68, File::Current );
|
|
||||||
|
|
||||||
if( !mp4file->readInt( d->nextTrackID ) )
|
|
||||||
return;
|
|
||||||
// register at proxy
|
|
||||||
mp4file->propProxy()->registerMvhd( this );
|
|
||||||
}
|
|
|
@ -1,44 +0,0 @@
|
||||||
#ifndef MP4MVHDBOX_H
|
|
||||||
#define MP4MVHDBOX_H
|
|
||||||
|
|
||||||
#include "mp4isofullbox.h"
|
|
||||||
#include "mp4fourcc.h"
|
|
||||||
#include "mp4file.h" // ulonglong
|
|
||||||
|
|
||||||
namespace TagLib
|
|
||||||
{
|
|
||||||
namespace MP4
|
|
||||||
{
|
|
||||||
class Mp4MvhdBox: public Mp4IsoFullBox
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Mp4MvhdBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset );
|
|
||||||
~Mp4MvhdBox();
|
|
||||||
|
|
||||||
//! function to get the creation time of the mp4 file
|
|
||||||
ulonglong creationTime() const;
|
|
||||||
//! function to get the modification time of the mp4 file
|
|
||||||
ulonglong modificationTime() const;
|
|
||||||
//! function to get the timescale referenced by the above timestamps
|
|
||||||
uint timescale() const;
|
|
||||||
//! function to get the presentation duration in the mp4 file
|
|
||||||
ulonglong duration() const;
|
|
||||||
//! function to get the rate (playout speed) - typically 1.0;
|
|
||||||
uint rate() const;
|
|
||||||
//! function to get volume level for presentation - typically 1.0;
|
|
||||||
uint volume() const;
|
|
||||||
//! function to get the track ID for adding new tracks - useless for this lib
|
|
||||||
uint nextTrackID() const;
|
|
||||||
|
|
||||||
//! parse mvhd contents
|
|
||||||
void parse();
|
|
||||||
|
|
||||||
private:
|
|
||||||
class Mp4MvhdBoxPrivate;
|
|
||||||
Mp4MvhdBoxPrivate* d;
|
|
||||||
}; // Mp4MvhdBox
|
|
||||||
|
|
||||||
} // namespace MP4
|
|
||||||
} // namespace TagLib
|
|
||||||
|
|
||||||
#endif // MP4MVHDBOX_H
|
|
|
@ -1,68 +0,0 @@
|
||||||
#include "mp4propsproxy.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
|
|
||||||
class MP4::Mp4PropsProxy::Mp4PropsProxyPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//! the movie header box
|
|
||||||
MP4::Mp4MvhdBox* mvhdbox;
|
|
||||||
//! the sample table box
|
|
||||||
MP4::Mp4AudioSampleEntry* audiosampleentry;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
MP4::Mp4PropsProxy::Mp4PropsProxy()
|
|
||||||
{
|
|
||||||
d = new MP4::Mp4PropsProxy::Mp4PropsProxyPrivate();
|
|
||||||
d->mvhdbox = 0;
|
|
||||||
d->audiosampleentry = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::Mp4PropsProxy::~Mp4PropsProxy()
|
|
||||||
{
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
TagLib::uint MP4::Mp4PropsProxy::seconds() const
|
|
||||||
{
|
|
||||||
if( d->mvhdbox )
|
|
||||||
return static_cast<TagLib::uint>( d->mvhdbox->duration() / d->mvhdbox->timescale() );
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
TagLib::uint MP4::Mp4PropsProxy::channels() const
|
|
||||||
{
|
|
||||||
if( d->audiosampleentry )
|
|
||||||
return d->audiosampleentry->channels();
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
TagLib::uint MP4::Mp4PropsProxy::sampleRate() const
|
|
||||||
{
|
|
||||||
if( d->audiosampleentry )
|
|
||||||
return (d->audiosampleentry->samplerate()>>16);
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
TagLib::uint MP4::Mp4PropsProxy::bitRate() const
|
|
||||||
{
|
|
||||||
if( d->audiosampleentry )
|
|
||||||
return (d->audiosampleentry->bitrate());
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MP4::Mp4PropsProxy::registerMvhd( MP4::Mp4MvhdBox* mvhdbox )
|
|
||||||
{
|
|
||||||
d->mvhdbox = mvhdbox;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MP4::Mp4PropsProxy::registerAudioSampleEntry( MP4::Mp4AudioSampleEntry* audioSampleEntry )
|
|
||||||
{
|
|
||||||
d->audiosampleentry = audioSampleEntry;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,44 +0,0 @@
|
||||||
#ifndef MP4PROPSPROXY_H
|
|
||||||
#define MP4PROPSPROXY_H MP4PROPSPROXY_H
|
|
||||||
#include "mp4mvhdbox.h"
|
|
||||||
#include "mp4audiosampleentry.h"
|
|
||||||
|
|
||||||
namespace TagLib
|
|
||||||
{
|
|
||||||
namespace MP4
|
|
||||||
{
|
|
||||||
//! Mp4PropsProxy is used to access the stsd box and mvhd box directly
|
|
||||||
/*! this class works as a shortcut to avoid stepping through all parent boxes
|
|
||||||
* to access the boxes in question
|
|
||||||
*/
|
|
||||||
class Mp4PropsProxy
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//! constructor for properties proxy
|
|
||||||
Mp4PropsProxy();
|
|
||||||
//! destructor
|
|
||||||
~Mp4PropsProxy();
|
|
||||||
|
|
||||||
//! function to get length of media in seconds
|
|
||||||
TagLib::uint seconds() const;
|
|
||||||
//! function to get the nunmber of channels
|
|
||||||
TagLib::uint channels() const;
|
|
||||||
//! function to get the sample rate
|
|
||||||
TagLib::uint sampleRate() const;
|
|
||||||
//! function to get the bitrate rate
|
|
||||||
TagLib::uint bitRate() const;
|
|
||||||
|
|
||||||
//! function to register the movie header box - mvhd
|
|
||||||
void registerMvhd( MP4::Mp4MvhdBox* mvhdbox );
|
|
||||||
//! function to register the sample description box
|
|
||||||
void registerAudioSampleEntry( MP4::Mp4AudioSampleEntry* audiosampleentry );
|
|
||||||
|
|
||||||
private:
|
|
||||||
class Mp4PropsProxyPrivate;
|
|
||||||
Mp4PropsProxyPrivate* d;
|
|
||||||
|
|
||||||
}; // Mp4PropsProxy
|
|
||||||
} // MP4
|
|
||||||
} // TagLib
|
|
||||||
|
|
||||||
#endif // MP4PROPSPROXY_H
|
|
|
@ -1,38 +0,0 @@
|
||||||
#include "mp4sampleentry.h"
|
|
||||||
#include "mp4isobox.h"
|
|
||||||
#include "mp4file.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
|
|
||||||
class MP4::Mp4SampleEntry::Mp4SampleEntryPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TagLib::uint data_reference_index;
|
|
||||||
};
|
|
||||||
|
|
||||||
MP4::Mp4SampleEntry::Mp4SampleEntry( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset )
|
|
||||||
:Mp4IsoBox(file, fourcc, size, offset)
|
|
||||||
{
|
|
||||||
d = new MP4::Mp4SampleEntry::Mp4SampleEntryPrivate();
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::Mp4SampleEntry::~Mp4SampleEntry()
|
|
||||||
{
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! parse the content of the box
|
|
||||||
void MP4::Mp4SampleEntry::parse()
|
|
||||||
{
|
|
||||||
TagLib::MP4::File* mp4file = static_cast<TagLib::MP4::File*>(file());
|
|
||||||
if(!mp4file)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// skip the first 6 bytes
|
|
||||||
mp4file->seek( 6, TagLib::File::Current );
|
|
||||||
// read data reference index
|
|
||||||
if(!mp4file->readShort( d->data_reference_index))
|
|
||||||
return;
|
|
||||||
parseEntry();
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
#ifndef MP4SAMPLEENTRY_H
|
|
||||||
#define MP4SAMPLEENTRY_H
|
|
||||||
|
|
||||||
#include "mp4isobox.h"
|
|
||||||
#include "mp4fourcc.h"
|
|
||||||
|
|
||||||
namespace TagLib
|
|
||||||
{
|
|
||||||
namespace MP4
|
|
||||||
{
|
|
||||||
class Mp4SampleEntry: public Mp4IsoBox
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Mp4SampleEntry( File* file, MP4::Fourcc fourcc, uint size, long offset );
|
|
||||||
~Mp4SampleEntry();
|
|
||||||
|
|
||||||
public:
|
|
||||||
//! parse the content of the box
|
|
||||||
virtual void parse();
|
|
||||||
|
|
||||||
private:
|
|
||||||
//! function to be implemented in subclass
|
|
||||||
virtual void parseEntry() = 0;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
class Mp4SampleEntryPrivate;
|
|
||||||
Mp4SampleEntryPrivate* d;
|
|
||||||
}; // class Mp4SampleEntry
|
|
||||||
|
|
||||||
} // namespace MP4
|
|
||||||
} // namespace TagLib
|
|
||||||
|
|
||||||
#endif // MP4SAMPLEENTRY_H
|
|
|
@ -1,29 +0,0 @@
|
||||||
#include "mp4skipbox.h"
|
|
||||||
#include "mp4isobox.h"
|
|
||||||
#include "tfile.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
|
|
||||||
class MP4::Mp4SkipBox::Mp4SkipBoxPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
};
|
|
||||||
|
|
||||||
MP4::Mp4SkipBox::Mp4SkipBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset )
|
|
||||||
:Mp4IsoBox(file, fourcc, size, offset)
|
|
||||||
{
|
|
||||||
d = new MP4::Mp4SkipBox::Mp4SkipBoxPrivate();
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::Mp4SkipBox::~Mp4SkipBox()
|
|
||||||
{
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! parse the content of the box
|
|
||||||
void MP4::Mp4SkipBox::parse()
|
|
||||||
{
|
|
||||||
// skip contents
|
|
||||||
file()->seek( size() - 8, TagLib::File::Current );
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
#ifndef MP4SKIPBOX_H
|
|
||||||
#define MP4SKIPBOX_H
|
|
||||||
|
|
||||||
#include "mp4isobox.h"
|
|
||||||
#include "mp4fourcc.h"
|
|
||||||
|
|
||||||
namespace TagLib
|
|
||||||
{
|
|
||||||
namespace MP4
|
|
||||||
{
|
|
||||||
class Mp4SkipBox: public Mp4IsoBox
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Mp4SkipBox( File* file, MP4::Fourcc fourcc, uint size, long offset );
|
|
||||||
~Mp4SkipBox();
|
|
||||||
|
|
||||||
private:
|
|
||||||
//! parse the content of the box
|
|
||||||
virtual void parse();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
class Mp4SkipBoxPrivate;
|
|
||||||
Mp4SkipBoxPrivate* d;
|
|
||||||
}; // class Mp4SkipBox
|
|
||||||
|
|
||||||
} // namespace MP4
|
|
||||||
} // namespace TagLib
|
|
||||||
|
|
||||||
#endif // MP4SKIPBOX_H
|
|
|
@ -1,84 +0,0 @@
|
||||||
#include "tlist.h"
|
|
||||||
#include <iostream>
|
|
||||||
#include "mp4stblbox.h"
|
|
||||||
#include "mp4stsdbox.h"
|
|
||||||
#include "boxfactory.h"
|
|
||||||
#include "mp4file.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
|
|
||||||
class MP4::Mp4StblBox::Mp4StblBoxPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//! container for all boxes in stbl box
|
|
||||||
TagLib::List<Mp4IsoBox*> stblBoxes;
|
|
||||||
//! a box factory for creating the appropriate boxes
|
|
||||||
MP4::BoxFactory boxfactory;
|
|
||||||
//! the handler type for the current trak
|
|
||||||
MP4::Fourcc handler_type;
|
|
||||||
}; // class Mp4StblBoxPrivate
|
|
||||||
|
|
||||||
MP4::Mp4StblBox::Mp4StblBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset )
|
|
||||||
: Mp4IsoBox( file, fourcc, size, offset )
|
|
||||||
{
|
|
||||||
d = new MP4::Mp4StblBox::Mp4StblBoxPrivate();
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::Mp4StblBox::~Mp4StblBox()
|
|
||||||
{
|
|
||||||
TagLib::List<Mp4IsoBox*>::Iterator delIter;
|
|
||||||
for( delIter = d->stblBoxes.begin();
|
|
||||||
delIter != d->stblBoxes.end();
|
|
||||||
delIter++ )
|
|
||||||
{
|
|
||||||
delete *delIter;
|
|
||||||
}
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MP4::Mp4StblBox::setHandlerType( MP4::Fourcc fourcc )
|
|
||||||
{
|
|
||||||
d->handler_type = fourcc;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MP4::Mp4StblBox::parse()
|
|
||||||
{
|
|
||||||
TagLib::MP4::File* mp4file = static_cast<MP4::File*>( file() );
|
|
||||||
|
|
||||||
TagLib::uint totalsize = 8;
|
|
||||||
// parse all contained boxes
|
|
||||||
TagLib::uint size;
|
|
||||||
MP4::Fourcc fourcc;
|
|
||||||
|
|
||||||
while( (mp4file->readSizeAndType( size, fourcc ) == true) )
|
|
||||||
{
|
|
||||||
totalsize += size;
|
|
||||||
|
|
||||||
// check for errors
|
|
||||||
if( totalsize > MP4::Mp4IsoBox::size() )
|
|
||||||
{
|
|
||||||
std::cerr << "Error in mp4 file " << mp4file->name() << " stbl box contains bad box with name: " << fourcc.toString() << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// create the appropriate subclass and parse it
|
|
||||||
MP4::Mp4IsoBox* curbox = d->boxfactory.createInstance( mp4file, fourcc, size, mp4file->tell() );
|
|
||||||
|
|
||||||
// check for stsd
|
|
||||||
if( static_cast<TagLib::uint>(fourcc) == 0x73747364 /*'stsd'*/ )
|
|
||||||
{
|
|
||||||
// cast to stsd box
|
|
||||||
MP4::Mp4StsdBox* stsdbox = static_cast<MP4::Mp4StsdBox*>(curbox);
|
|
||||||
if(!stsdbox)
|
|
||||||
return;
|
|
||||||
// set the handler type
|
|
||||||
stsdbox->setHandlerType( d->handler_type );
|
|
||||||
}
|
|
||||||
curbox->parsebox();
|
|
||||||
d->stblBoxes.append( curbox );
|
|
||||||
|
|
||||||
// check for end of stbl box
|
|
||||||
if( totalsize == MP4::Mp4IsoBox::size() )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
#ifndef MP4STBLBOX_H
|
|
||||||
#define MP4STBLBOX_H
|
|
||||||
|
|
||||||
#include "mp4isobox.h"
|
|
||||||
#include "mp4fourcc.h"
|
|
||||||
|
|
||||||
namespace TagLib
|
|
||||||
{
|
|
||||||
namespace MP4
|
|
||||||
{
|
|
||||||
class Mp4StblBox: public Mp4IsoBox
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Mp4StblBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset );
|
|
||||||
~Mp4StblBox();
|
|
||||||
|
|
||||||
//! parse stbl contents
|
|
||||||
void parse();
|
|
||||||
//! set the handler type - needed for stsd
|
|
||||||
void setHandlerType( MP4::Fourcc fourcc );
|
|
||||||
|
|
||||||
private:
|
|
||||||
class Mp4StblBoxPrivate;
|
|
||||||
Mp4StblBoxPrivate* d;
|
|
||||||
}; // Mp4StblBox
|
|
||||||
|
|
||||||
} // namespace MP4
|
|
||||||
} // namespace TagLib
|
|
||||||
|
|
||||||
#endif // MP4STBLBOX_H
|
|
|
@ -1,70 +0,0 @@
|
||||||
#include "tlist.h"
|
|
||||||
#include <iostream>
|
|
||||||
#include "mp4stsdbox.h"
|
|
||||||
#include "mp4audiosampleentry.h"
|
|
||||||
#include "mp4file.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
|
|
||||||
class MP4::Mp4StsdBox::Mp4StsdBoxPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//! the handler type for the current trak
|
|
||||||
MP4::Fourcc handler_type;
|
|
||||||
//! the audio sample entry
|
|
||||||
MP4::Mp4AudioSampleEntry* audioSampleEntry;
|
|
||||||
}; // class Mp4StsdBoxPrivate
|
|
||||||
|
|
||||||
MP4::Mp4StsdBox::Mp4StsdBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset )
|
|
||||||
: Mp4IsoFullBox( file, fourcc, size, offset )
|
|
||||||
{
|
|
||||||
d = new MP4::Mp4StsdBox::Mp4StsdBoxPrivate();
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::Mp4StsdBox::~Mp4StsdBox()
|
|
||||||
{
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MP4::Mp4StsdBox::setHandlerType( MP4::Fourcc fourcc )
|
|
||||||
{
|
|
||||||
d->handler_type = fourcc;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MP4::Mp4StsdBox::parse()
|
|
||||||
{
|
|
||||||
MP4::File* mp4file = static_cast<MP4::File*>( file() );
|
|
||||||
if(!mp4file)
|
|
||||||
return;
|
|
||||||
|
|
||||||
TagLib::uint totalsize = 12; // initial size of box
|
|
||||||
|
|
||||||
// check for handler type - only parse if 'soun':
|
|
||||||
if( static_cast<TagLib::uint>(d->handler_type) == 0x736f756e )
|
|
||||||
{
|
|
||||||
// read entry count
|
|
||||||
TagLib::uint entry_count;
|
|
||||||
if(!mp4file->readInt( entry_count ))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// simply read first entry and skip all following
|
|
||||||
// read size and type
|
|
||||||
TagLib::uint cursize;
|
|
||||||
MP4::Fourcc fourcc;
|
|
||||||
if( !mp4file->readSizeAndType( cursize, fourcc ))
|
|
||||||
return;
|
|
||||||
|
|
||||||
totalsize += 12;
|
|
||||||
// alocate an AudioSampleEntry
|
|
||||||
d->audioSampleEntry = new MP4::Mp4AudioSampleEntry( mp4file, fourcc, cursize, mp4file->tell() );
|
|
||||||
// parse the AudioSampleEntry
|
|
||||||
d->audioSampleEntry->parse();
|
|
||||||
totalsize += cursize-8;
|
|
||||||
// skip the remaining box contents
|
|
||||||
mp4file->seek( size()-totalsize, TagLib::File::Current );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mp4file->seek( size()-totalsize, TagLib::File::Current );
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
#ifndef MP4STSDBOX_H
|
|
||||||
#define MP4STSDBOX_H
|
|
||||||
|
|
||||||
#include "mp4isofullbox.h"
|
|
||||||
#include "mp4fourcc.h"
|
|
||||||
|
|
||||||
namespace TagLib
|
|
||||||
{
|
|
||||||
namespace MP4
|
|
||||||
{
|
|
||||||
class Mp4StsdBox: public Mp4IsoFullBox
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Mp4StsdBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset );
|
|
||||||
~Mp4StsdBox();
|
|
||||||
|
|
||||||
//! parse stsd contents
|
|
||||||
void parse();
|
|
||||||
//! set the handler type - needed for stsd
|
|
||||||
void setHandlerType( MP4::Fourcc fourcc );
|
|
||||||
|
|
||||||
private:
|
|
||||||
class Mp4StsdBoxPrivate;
|
|
||||||
Mp4StsdBoxPrivate* d;
|
|
||||||
}; // Mp4StsdBox
|
|
||||||
|
|
||||||
} // namespace MP4
|
|
||||||
} // namespace TagLib
|
|
||||||
|
|
||||||
#endif // MP4STSDBOX_H
|
|
|
@ -1,147 +0,0 @@
|
||||||
#include "mp4tagsproxy.h"
|
|
||||||
#include "itunesdatabox.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
|
|
||||||
class MP4::Mp4TagsProxy::Mp4TagsProxyPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ITunesDataBox* titleData;
|
|
||||||
ITunesDataBox* artistData;
|
|
||||||
ITunesDataBox* albumData;
|
|
||||||
ITunesDataBox* coverData;
|
|
||||||
ITunesDataBox* genreData;
|
|
||||||
ITunesDataBox* yearData;
|
|
||||||
ITunesDataBox* trknData;
|
|
||||||
ITunesDataBox* commentData;
|
|
||||||
ITunesDataBox* groupingData;
|
|
||||||
ITunesDataBox* composerData;
|
|
||||||
ITunesDataBox* diskData;
|
|
||||||
ITunesDataBox* bpmData;
|
|
||||||
};
|
|
||||||
|
|
||||||
MP4::Mp4TagsProxy::Mp4TagsProxy()
|
|
||||||
{
|
|
||||||
d = new MP4::Mp4TagsProxy::Mp4TagsProxyPrivate();
|
|
||||||
d->titleData = 0;
|
|
||||||
d->artistData = 0;
|
|
||||||
d->albumData = 0;
|
|
||||||
d->coverData = 0;
|
|
||||||
d->genreData = 0;
|
|
||||||
d->yearData = 0;
|
|
||||||
d->trknData = 0;
|
|
||||||
d->commentData = 0;
|
|
||||||
d->groupingData = 0;
|
|
||||||
d->composerData = 0;
|
|
||||||
d->diskData = 0;
|
|
||||||
d->bpmData = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::Mp4TagsProxy::~Mp4TagsProxy()
|
|
||||||
{
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::ITunesDataBox* MP4::Mp4TagsProxy::titleData() const
|
|
||||||
{
|
|
||||||
return d->titleData;
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::ITunesDataBox* MP4::Mp4TagsProxy::artistData() const
|
|
||||||
{
|
|
||||||
return d->artistData;
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::ITunesDataBox* MP4::Mp4TagsProxy::albumData() const
|
|
||||||
{
|
|
||||||
return d->albumData;
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::ITunesDataBox* MP4::Mp4TagsProxy::genreData() const
|
|
||||||
{
|
|
||||||
return d->genreData;
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::ITunesDataBox* MP4::Mp4TagsProxy::yearData() const
|
|
||||||
{
|
|
||||||
return d->yearData;
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::ITunesDataBox* MP4::Mp4TagsProxy::trknData() const
|
|
||||||
{
|
|
||||||
return d->trknData;
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::ITunesDataBox* MP4::Mp4TagsProxy::commentData() const
|
|
||||||
{
|
|
||||||
return d->commentData;
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::ITunesDataBox* MP4::Mp4TagsProxy::groupingData() const
|
|
||||||
{
|
|
||||||
return d->groupingData;
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::ITunesDataBox* MP4::Mp4TagsProxy::composerData() const
|
|
||||||
{
|
|
||||||
return d->composerData;
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::ITunesDataBox* MP4::Mp4TagsProxy::diskData() const
|
|
||||||
{
|
|
||||||
return d->diskData;
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::ITunesDataBox* MP4::Mp4TagsProxy::bpmData() const
|
|
||||||
{
|
|
||||||
return d->bpmData;
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::ITunesDataBox* MP4::Mp4TagsProxy::coverData() const
|
|
||||||
{
|
|
||||||
return d->coverData;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MP4::Mp4TagsProxy::registerBox( EBoxType boxtype, ITunesDataBox* databox )
|
|
||||||
{
|
|
||||||
switch( boxtype )
|
|
||||||
{
|
|
||||||
case title:
|
|
||||||
d->titleData = databox;
|
|
||||||
break;
|
|
||||||
case artist:
|
|
||||||
d->artistData = databox;
|
|
||||||
break;
|
|
||||||
case album:
|
|
||||||
d->albumData = databox;
|
|
||||||
break;
|
|
||||||
case cover:
|
|
||||||
d->coverData = databox;
|
|
||||||
break;
|
|
||||||
case genre:
|
|
||||||
d->genreData = databox;
|
|
||||||
break;
|
|
||||||
case year:
|
|
||||||
d->yearData = databox;
|
|
||||||
break;
|
|
||||||
case trackno:
|
|
||||||
d->trknData = databox;
|
|
||||||
break;
|
|
||||||
case comment:
|
|
||||||
d->commentData = databox;
|
|
||||||
break;
|
|
||||||
case grouping:
|
|
||||||
d->groupingData = databox;
|
|
||||||
break;
|
|
||||||
case composer:
|
|
||||||
d->composerData = databox;
|
|
||||||
break;
|
|
||||||
case disk:
|
|
||||||
d->diskData = databox;
|
|
||||||
break;
|
|
||||||
case bpm:
|
|
||||||
d->bpmData = databox;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,78 +0,0 @@
|
||||||
#ifndef MP4TAGSPROXY_H
|
|
||||||
#define MP4TAGSPROXY_H
|
|
||||||
|
|
||||||
namespace TagLib
|
|
||||||
{
|
|
||||||
namespace MP4
|
|
||||||
{
|
|
||||||
// forward declaration(s)
|
|
||||||
class ITunesDataBox;
|
|
||||||
/*! proxy for mp4 itunes tag relevant boxes
|
|
||||||
*
|
|
||||||
* this class works as a proxy for the specific tag boxes
|
|
||||||
* in an mp4 itunes file. the boxes are mired in
|
|
||||||
* the mp4 file structure and stepping through all box layers
|
|
||||||
* is avoided by registration at the proxy object.
|
|
||||||
*/
|
|
||||||
class Mp4TagsProxy
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/*! enum for all supported box types */
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
title = 0,
|
|
||||||
artist,
|
|
||||||
album,
|
|
||||||
cover,
|
|
||||||
genre,
|
|
||||||
year,
|
|
||||||
trackno,
|
|
||||||
comment,
|
|
||||||
grouping,
|
|
||||||
composer,
|
|
||||||
disk,
|
|
||||||
bpm
|
|
||||||
} EBoxType;
|
|
||||||
|
|
||||||
//! constructor
|
|
||||||
Mp4TagsProxy();
|
|
||||||
//! destructor
|
|
||||||
~Mp4TagsProxy();
|
|
||||||
|
|
||||||
//! function to get the data box for the title
|
|
||||||
ITunesDataBox* titleData() const;
|
|
||||||
//! function to get the data box for the artist
|
|
||||||
ITunesDataBox* artistData() const;
|
|
||||||
//! function to get the data box for the album
|
|
||||||
ITunesDataBox* albumData() const;
|
|
||||||
//! function to get the data box for the genre
|
|
||||||
ITunesDataBox* genreData() const;
|
|
||||||
//! function to get the data box for the year
|
|
||||||
ITunesDataBox* yearData() const;
|
|
||||||
//! function to get the data box for the track number
|
|
||||||
ITunesDataBox* trknData() const;
|
|
||||||
//! function to get the data box for the comment
|
|
||||||
ITunesDataBox* commentData() const;
|
|
||||||
//! function to get the data box for the grouping
|
|
||||||
ITunesDataBox* groupingData() const;
|
|
||||||
//! function to get the data box for the composer
|
|
||||||
ITunesDataBox* composerData() const;
|
|
||||||
//! function to get the data box for the disk number
|
|
||||||
ITunesDataBox* diskData() const;
|
|
||||||
//! function to get the data box for the bpm
|
|
||||||
ITunesDataBox* bpmData() const;
|
|
||||||
//! function to get the data box for the cover
|
|
||||||
ITunesDataBox* coverData() const;
|
|
||||||
|
|
||||||
//! function to register a data box for a certain box type
|
|
||||||
void registerBox( EBoxType boxtype, ITunesDataBox* databox );
|
|
||||||
|
|
||||||
private:
|
|
||||||
class Mp4TagsProxyPrivate;
|
|
||||||
//! private data of tags proxy
|
|
||||||
Mp4TagsProxyPrivate* d;
|
|
||||||
}; // class Mp4TagsProxy
|
|
||||||
} // namespace MP4
|
|
||||||
} // namespace TagLib
|
|
||||||
|
|
||||||
#endif // MP4TAGSPROXY_H
|
|
|
@ -1,65 +0,0 @@
|
||||||
#include "tlist.h"
|
|
||||||
#include <iostream>
|
|
||||||
#include "mp4trakbox.h"
|
|
||||||
#include "boxfactory.h"
|
|
||||||
#include "mp4file.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
|
|
||||||
class MP4::Mp4TrakBox::Mp4TrakBoxPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//! container for all boxes in trak box
|
|
||||||
TagLib::List<Mp4IsoBox*> trakBoxes;
|
|
||||||
//! a box factory for creating the appropriate boxes
|
|
||||||
MP4::BoxFactory boxfactory;
|
|
||||||
}; // class Mp4TrakBoxPrivate
|
|
||||||
|
|
||||||
MP4::Mp4TrakBox::Mp4TrakBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset )
|
|
||||||
: Mp4IsoBox( file, fourcc, size, offset )
|
|
||||||
{
|
|
||||||
d = new MP4::Mp4TrakBox::Mp4TrakBoxPrivate();
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::Mp4TrakBox::~Mp4TrakBox()
|
|
||||||
{
|
|
||||||
TagLib::List<Mp4IsoBox*>::Iterator delIter;
|
|
||||||
for( delIter = d->trakBoxes.begin();
|
|
||||||
delIter != d->trakBoxes.end();
|
|
||||||
delIter++ )
|
|
||||||
{
|
|
||||||
delete *delIter;
|
|
||||||
}
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MP4::Mp4TrakBox::parse()
|
|
||||||
{
|
|
||||||
TagLib::MP4::File* mp4file = static_cast<MP4::File*>( file() );
|
|
||||||
|
|
||||||
TagLib::uint totalsize = 8;
|
|
||||||
// parse all contained boxes
|
|
||||||
TagLib::uint size;
|
|
||||||
MP4::Fourcc fourcc;
|
|
||||||
|
|
||||||
while( (mp4file->readSizeAndType( size, fourcc ) == true) )
|
|
||||||
{
|
|
||||||
totalsize += size;
|
|
||||||
|
|
||||||
// check for errors
|
|
||||||
if( totalsize > MP4::Mp4IsoBox::size() )
|
|
||||||
{
|
|
||||||
std::cerr << "Error in mp4 file " << mp4file->name() << " trak box contains bad box with name: " << fourcc.toString() << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// create the appropriate subclass and parse it
|
|
||||||
MP4::Mp4IsoBox* curbox = d->boxfactory.createInstance( mp4file, fourcc, size, mp4file->tell() );
|
|
||||||
curbox->parsebox();
|
|
||||||
d->trakBoxes.append( curbox );
|
|
||||||
|
|
||||||
// check for end of trak box
|
|
||||||
if( totalsize == MP4::Mp4IsoBox::size() )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
#ifndef MP4TRAKBOX_H
|
|
||||||
#define MP4TRAKBOX_H
|
|
||||||
|
|
||||||
#include "mp4isobox.h"
|
|
||||||
#include "mp4fourcc.h"
|
|
||||||
|
|
||||||
namespace TagLib
|
|
||||||
{
|
|
||||||
namespace MP4
|
|
||||||
{
|
|
||||||
class Mp4TrakBox: public Mp4IsoBox
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Mp4TrakBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset );
|
|
||||||
~Mp4TrakBox();
|
|
||||||
|
|
||||||
//! parse trak contents
|
|
||||||
void parse();
|
|
||||||
|
|
||||||
private:
|
|
||||||
class Mp4TrakBoxPrivate;
|
|
||||||
Mp4TrakBoxPrivate* d;
|
|
||||||
}; // Mp4TrakBox
|
|
||||||
|
|
||||||
} // namespace MP4
|
|
||||||
} // namespace TagLib
|
|
||||||
|
|
||||||
#endif // MP4TRAKBOX_H
|
|
|
@ -1,74 +0,0 @@
|
||||||
#include "tlist.h"
|
|
||||||
#include <iostream>
|
|
||||||
#include "mp4udtabox.h"
|
|
||||||
#include "boxfactory.h"
|
|
||||||
#include "mp4file.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
|
|
||||||
class MP4::Mp4UdtaBox::Mp4UdtaBoxPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//! container for all boxes in udta box
|
|
||||||
TagLib::List<Mp4IsoBox*> udtaBoxes;
|
|
||||||
//! a box factory for creating the appropriate boxes
|
|
||||||
MP4::BoxFactory boxfactory;
|
|
||||||
}; // class Mp4UdtaBoxPrivate
|
|
||||||
|
|
||||||
MP4::Mp4UdtaBox::Mp4UdtaBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset )
|
|
||||||
: Mp4IsoBox( file, fourcc, size, offset )
|
|
||||||
{
|
|
||||||
d = new MP4::Mp4UdtaBox::Mp4UdtaBoxPrivate();
|
|
||||||
}
|
|
||||||
|
|
||||||
MP4::Mp4UdtaBox::~Mp4UdtaBox()
|
|
||||||
{
|
|
||||||
TagLib::List<Mp4IsoBox*>::Iterator delIter;
|
|
||||||
for( delIter = d->udtaBoxes.begin();
|
|
||||||
delIter != d->udtaBoxes.end();
|
|
||||||
delIter++ )
|
|
||||||
{
|
|
||||||
delete *delIter;
|
|
||||||
}
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MP4::Mp4UdtaBox::parse()
|
|
||||||
{
|
|
||||||
#if 0
|
|
||||||
std::cout << " parsing udta box" << std::endl;
|
|
||||||
#endif
|
|
||||||
TagLib::MP4::File* mp4file = static_cast<MP4::File*>( file() );
|
|
||||||
|
|
||||||
TagLib::uint totalsize = 8;
|
|
||||||
// parse all contained boxes
|
|
||||||
TagLib::uint size;
|
|
||||||
MP4::Fourcc fourcc;
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
std::cout << " ";
|
|
||||||
#endif
|
|
||||||
while( (mp4file->readSizeAndType( size, fourcc ) == true) )
|
|
||||||
{
|
|
||||||
totalsize += size;
|
|
||||||
|
|
||||||
// check for errors
|
|
||||||
if( totalsize > MP4::Mp4IsoBox::size() )
|
|
||||||
{
|
|
||||||
std::cerr << "Error in mp4 file " << mp4file->name() << " udta box contains bad box with name: " << fourcc.toString() << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// create the appropriate subclass and parse it
|
|
||||||
MP4::Mp4IsoBox* curbox = d->boxfactory.createInstance( mp4file, fourcc, size, mp4file->tell() );
|
|
||||||
curbox->parsebox();
|
|
||||||
d->udtaBoxes.append( curbox );
|
|
||||||
|
|
||||||
// check for end of udta box
|
|
||||||
if( totalsize == MP4::Mp4IsoBox::size() )
|
|
||||||
break;
|
|
||||||
#if 0
|
|
||||||
std::cout << " ";
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
#ifndef MP4UDTABOX_H
|
|
||||||
#define MP4UDTABOX_H
|
|
||||||
|
|
||||||
#include "mp4isobox.h"
|
|
||||||
#include "mp4fourcc.h"
|
|
||||||
|
|
||||||
namespace TagLib
|
|
||||||
{
|
|
||||||
namespace MP4
|
|
||||||
{
|
|
||||||
class Mp4UdtaBox: public Mp4IsoBox
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Mp4UdtaBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset );
|
|
||||||
~Mp4UdtaBox();
|
|
||||||
|
|
||||||
//! parse moov contents
|
|
||||||
void parse();
|
|
||||||
|
|
||||||
private:
|
|
||||||
class Mp4UdtaBoxPrivate;
|
|
||||||
Mp4UdtaBoxPrivate* d;
|
|
||||||
}; // Mp4UdtaBox
|
|
||||||
|
|
||||||
} // namespace MP4
|
|
||||||
} // namespace TagLib
|
|
||||||
|
|
||||||
#endif // MP4UDTABOX_H
|
|
|
@ -1,171 +0,0 @@
|
||||||
/***************************************************************************
|
|
||||||
copyright : (C) 2004 by Allan Sandfeld Jensen
|
|
||||||
email : kde@carewolf.org
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* 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 *
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
#ifndef DO_NOT_DOCUMENT // Tell Doxygen not to document this header
|
|
||||||
|
|
||||||
#ifndef TAGLIB_COMBINEDTAG_H
|
|
||||||
#define TAGLIB_COMBINEDTAG_H
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Note that this header is not installed.
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#include <tag.h>
|
|
||||||
|
|
||||||
namespace TagLib {
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* A union of two TagLib::Tags.
|
|
||||||
*/
|
|
||||||
class CombinedTag : public TagLib::Tag
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CombinedTag(Tag *tag1 = 0, Tag *tag2 = 0)
|
|
||||||
: TagLib::Tag(),
|
|
||||||
tag1(tag1), tag2(tag2) {}
|
|
||||||
|
|
||||||
virtual String title() const {
|
|
||||||
if(tag1 && !tag1->title().isEmpty())
|
|
||||||
return tag1->title();
|
|
||||||
|
|
||||||
if(tag2)
|
|
||||||
return tag2->title();
|
|
||||||
|
|
||||||
return String::null;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual String artist() const {
|
|
||||||
if(tag1 && !tag1->artist().isEmpty())
|
|
||||||
return tag1->artist();
|
|
||||||
|
|
||||||
if(tag2)
|
|
||||||
return tag2->artist();
|
|
||||||
|
|
||||||
return String::null;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual String album() const {
|
|
||||||
if(tag1 && !tag1->album().isEmpty())
|
|
||||||
return tag1->album();
|
|
||||||
|
|
||||||
if(tag2)
|
|
||||||
return tag2->album();
|
|
||||||
|
|
||||||
return String::null;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual String comment() const {
|
|
||||||
if(tag1 && !tag1->comment().isEmpty())
|
|
||||||
return tag1->comment();
|
|
||||||
|
|
||||||
if(tag2)
|
|
||||||
return tag2->comment();
|
|
||||||
|
|
||||||
return String::null;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual String genre() const {
|
|
||||||
if(tag1 && !tag1->genre().isEmpty())
|
|
||||||
return tag1->genre();
|
|
||||||
|
|
||||||
if(tag2)
|
|
||||||
return tag2->genre();
|
|
||||||
|
|
||||||
return String::null;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint year() const {
|
|
||||||
if(tag1 && tag1->year() > 0)
|
|
||||||
return tag1->year();
|
|
||||||
|
|
||||||
if(tag2)
|
|
||||||
return tag2->year();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uint track() const {
|
|
||||||
if(tag1 && tag1->track() > 0)
|
|
||||||
return tag1->track();
|
|
||||||
|
|
||||||
if(tag2)
|
|
||||||
return tag2->track();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void setTitle(const String &s) {
|
|
||||||
if(tag1)
|
|
||||||
tag1->setTitle(s);
|
|
||||||
if(tag2)
|
|
||||||
tag2->setTitle(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void setArtist(const String &s) {
|
|
||||||
if(tag1)
|
|
||||||
tag1->setArtist(s);
|
|
||||||
if(tag2)
|
|
||||||
tag2->setArtist(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void setAlbum(const String &s) {
|
|
||||||
if(tag1)
|
|
||||||
tag1->setAlbum(s);
|
|
||||||
if(tag2)
|
|
||||||
tag2->setAlbum(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void setComment(const String &s) {
|
|
||||||
if(tag1)
|
|
||||||
tag1->setComment(s);
|
|
||||||
if(tag2)
|
|
||||||
tag2->setComment(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void setGenre(const String &s) {
|
|
||||||
if(tag1)
|
|
||||||
tag1->setGenre(s);
|
|
||||||
if(tag2)
|
|
||||||
tag2->setGenre(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void setYear(uint i) {
|
|
||||||
if(tag1)
|
|
||||||
tag1->setYear(i);
|
|
||||||
if(tag2)
|
|
||||||
tag2->setYear(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void setTrack(uint i) {
|
|
||||||
if(tag1)
|
|
||||||
tag1->setTrack(i);
|
|
||||||
if(tag2)
|
|
||||||
tag2->setTrack(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Tag *tag1;
|
|
||||||
Tag *tag2;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
#endif
|
|
|
@ -1,366 +0,0 @@
|
||||||
/***************************************************************************
|
|
||||||
copyright : (C) 2004 by Allan Sandfeld Jensen
|
|
||||||
email : kde@carewolf.org
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* 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 *
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
#include <tbytevector.h>
|
|
||||||
#include <tstring.h>
|
|
||||||
#include <tdebug.h>
|
|
||||||
|
|
||||||
#include "mpcfile.h"
|
|
||||||
#include "id3v1tag.h"
|
|
||||||
#include "id3v2header.h"
|
|
||||||
#include "apetag.h"
|
|
||||||
#include "apefooter.h"
|
|
||||||
#include "combinedtag.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
|
|
||||||
class MPC::File::FilePrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
FilePrivate() :
|
|
||||||
APETag(0),
|
|
||||||
APELocation(-1),
|
|
||||||
APESize(0),
|
|
||||||
ID3v1Tag(0),
|
|
||||||
ID3v1Location(-1),
|
|
||||||
ID3v2Header(0),
|
|
||||||
ID3v2Location(-1),
|
|
||||||
ID3v2Size(0),
|
|
||||||
tag(0),
|
|
||||||
properties(0),
|
|
||||||
scanned(false),
|
|
||||||
hasAPE(false),
|
|
||||||
hasID3v1(false),
|
|
||||||
hasID3v2(false) {}
|
|
||||||
|
|
||||||
~FilePrivate()
|
|
||||||
{
|
|
||||||
if (tag != ID3v1Tag && tag != APETag) delete tag;
|
|
||||||
delete ID3v1Tag;
|
|
||||||
delete APETag;
|
|
||||||
delete ID3v2Header;
|
|
||||||
delete properties;
|
|
||||||
}
|
|
||||||
|
|
||||||
APE::Tag *APETag;
|
|
||||||
// long APEFooter;
|
|
||||||
long APELocation;
|
|
||||||
uint APESize;
|
|
||||||
|
|
||||||
ID3v1::Tag *ID3v1Tag;
|
|
||||||
long ID3v1Location;
|
|
||||||
|
|
||||||
ID3v2::Header *ID3v2Header;
|
|
||||||
long ID3v2Location;
|
|
||||||
uint ID3v2Size;
|
|
||||||
|
|
||||||
Tag *tag;
|
|
||||||
|
|
||||||
Properties *properties;
|
|
||||||
bool scanned;
|
|
||||||
|
|
||||||
// These indicate whether the file *on disk* has these tags, not if
|
|
||||||
// this data structure does. This is used in computing offsets.
|
|
||||||
|
|
||||||
bool hasAPE;
|
|
||||||
bool hasID3v1;
|
|
||||||
bool hasID3v2;
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// public members
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
MPC::File::File() : TagLib::File()
|
|
||||||
{
|
|
||||||
d = new FilePrivate;
|
|
||||||
}
|
|
||||||
|
|
||||||
MPC::File::File(const char *file, bool readProperties,
|
|
||||||
Properties::ReadStyle propertiesStyle) : TagLib::File(file)
|
|
||||||
{
|
|
||||||
d = new FilePrivate;
|
|
||||||
read(readProperties, propertiesStyle);
|
|
||||||
}
|
|
||||||
|
|
||||||
MPC::File::~File()
|
|
||||||
{
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
TagLib::Tag *MPC::File::tag() const
|
|
||||||
{
|
|
||||||
return d->tag;
|
|
||||||
}
|
|
||||||
|
|
||||||
MPC::Properties *MPC::File::audioProperties() const
|
|
||||||
{
|
|
||||||
return d->properties;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MPC::File::read(bool readProperties, Properties::ReadStyle /* propertiesStyle */)
|
|
||||||
{
|
|
||||||
// Look for an ID3v1 tag
|
|
||||||
|
|
||||||
d->ID3v1Location = findID3v1();
|
|
||||||
|
|
||||||
if(d->ID3v1Location >= 0) {
|
|
||||||
d->ID3v1Tag = new ID3v1::Tag(this, d->ID3v1Location);
|
|
||||||
d->hasID3v1 = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Look for an APE tag
|
|
||||||
|
|
||||||
findAPE();
|
|
||||||
|
|
||||||
d->APELocation = findAPE();
|
|
||||||
|
|
||||||
if(d->APELocation >= 0) {
|
|
||||||
d->APETag = new APE::Tag(this, d->APELocation);
|
|
||||||
d->APESize = d->APETag->footer()->completeTagSize();
|
|
||||||
d->APELocation = d->APELocation + d->APETag->footer()->size() - d->APESize;
|
|
||||||
d->hasAPE = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(d->hasID3v1 && d->hasAPE)
|
|
||||||
d->tag = new CombinedTag(d->APETag, d->ID3v1Tag);
|
|
||||||
else {
|
|
||||||
if(d->hasID3v1)
|
|
||||||
d->tag = d->ID3v1Tag;
|
|
||||||
else {
|
|
||||||
if(d->hasAPE)
|
|
||||||
d->tag = d->APETag;
|
|
||||||
else
|
|
||||||
d->tag = d->APETag = new APE::Tag;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Look for and skip an ID3v2 tag
|
|
||||||
|
|
||||||
d->ID3v2Location = findID3v2();
|
|
||||||
|
|
||||||
if(d->ID3v2Location >= 0) {
|
|
||||||
seek(d->ID3v2Location);
|
|
||||||
d->ID3v2Header = new ID3v2::Header(readBlock(ID3v2::Header::size()));
|
|
||||||
d->ID3v2Size = d->ID3v2Header->completeTagSize();
|
|
||||||
d->hasID3v2 = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(d->hasID3v2)
|
|
||||||
seek(d->ID3v2Location + d->ID3v2Size);
|
|
||||||
else
|
|
||||||
seek(0);
|
|
||||||
|
|
||||||
// Look for MPC metadata
|
|
||||||
|
|
||||||
if(readProperties) {
|
|
||||||
d->properties = new Properties(readBlock(MPC::HeaderSize),
|
|
||||||
length() - d->ID3v2Size - d->APESize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MPC::File::save()
|
|
||||||
{
|
|
||||||
if(readOnly()) {
|
|
||||||
debug("MPC::File::save() -- File is read only.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Possibly strip ID3v2 tag
|
|
||||||
|
|
||||||
if(d->hasID3v2 && !d->ID3v2Header) {
|
|
||||||
removeBlock(d->ID3v2Location, d->ID3v2Size);
|
|
||||||
d->hasID3v2 = false;
|
|
||||||
if(d->hasID3v1)
|
|
||||||
d->ID3v1Location -= d->ID3v2Size;
|
|
||||||
if(d->hasAPE)
|
|
||||||
d->APELocation -= d->ID3v2Size;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update ID3v1 tag
|
|
||||||
|
|
||||||
if(d->ID3v1Tag) {
|
|
||||||
if(d->hasID3v1) {
|
|
||||||
seek(d->ID3v1Location);
|
|
||||||
writeBlock(d->ID3v1Tag->render());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
seek(0, End);
|
|
||||||
d->ID3v1Location = tell();
|
|
||||||
writeBlock(d->ID3v1Tag->render());
|
|
||||||
d->hasID3v1 = true;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
if(d->hasID3v1) {
|
|
||||||
removeBlock(d->ID3v1Location, 128);
|
|
||||||
d->hasID3v1 = false;
|
|
||||||
if(d->hasAPE) {
|
|
||||||
if(d->APELocation > d->ID3v1Location)
|
|
||||||
d->APELocation -= 128;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update APE tag
|
|
||||||
|
|
||||||
if(d->APETag) {
|
|
||||||
if(d->hasAPE)
|
|
||||||
insert(d->APETag->render(), d->APELocation, d->APESize);
|
|
||||||
else {
|
|
||||||
if(d->hasID3v1) {
|
|
||||||
insert(d->APETag->render(), d->ID3v1Location, 0);
|
|
||||||
d->APESize = d->APETag->footer()->completeTagSize();
|
|
||||||
d->hasAPE = true;
|
|
||||||
d->APELocation = d->ID3v1Location;
|
|
||||||
d->ID3v1Location += d->APESize;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
seek(0, End);
|
|
||||||
d->APELocation = tell();
|
|
||||||
writeBlock(d->APETag->render());
|
|
||||||
d->APESize = d->APETag->footer()->completeTagSize();
|
|
||||||
d->hasAPE = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
if(d->hasAPE) {
|
|
||||||
removeBlock(d->APELocation, d->APESize);
|
|
||||||
d->hasAPE = false;
|
|
||||||
if(d->hasID3v1) {
|
|
||||||
if (d->ID3v1Location > d->APELocation)
|
|
||||||
d->ID3v1Location -= d->APESize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
ID3v1::Tag *MPC::File::ID3v1Tag(bool create)
|
|
||||||
{
|
|
||||||
if(!create || d->ID3v1Tag)
|
|
||||||
return d->ID3v1Tag;
|
|
||||||
|
|
||||||
// no ID3v1 tag exists and we've been asked to create one
|
|
||||||
|
|
||||||
d->ID3v1Tag = new ID3v1::Tag;
|
|
||||||
|
|
||||||
if(d->APETag)
|
|
||||||
d->tag = new CombinedTag(d->APETag, d->ID3v1Tag);
|
|
||||||
else
|
|
||||||
d->tag = d->ID3v1Tag;
|
|
||||||
|
|
||||||
return d->ID3v1Tag;
|
|
||||||
}
|
|
||||||
|
|
||||||
APE::Tag *MPC::File::APETag(bool create)
|
|
||||||
{
|
|
||||||
if(!create || d->APETag)
|
|
||||||
return d->APETag;
|
|
||||||
|
|
||||||
// no APE tag exists and we've been asked to create one
|
|
||||||
|
|
||||||
d->APETag = new APE::Tag;
|
|
||||||
|
|
||||||
if(d->ID3v1Tag)
|
|
||||||
d->tag = new CombinedTag(d->APETag, d->ID3v1Tag);
|
|
||||||
else
|
|
||||||
d->tag = d->APETag;
|
|
||||||
|
|
||||||
return d->APETag;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MPC::File::remove(int tags)
|
|
||||||
{
|
|
||||||
if(tags & ID3v1) {
|
|
||||||
delete d->ID3v1Tag;
|
|
||||||
d->ID3v1Tag = 0;
|
|
||||||
|
|
||||||
if(d->APETag)
|
|
||||||
d->tag = d->APETag;
|
|
||||||
else
|
|
||||||
d->tag = d->APETag = new APE::Tag;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(tags & ID3v2) {
|
|
||||||
delete d->ID3v2Header;
|
|
||||||
d->ID3v2Header = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(tags & APE) {
|
|
||||||
delete d->APETag;
|
|
||||||
d->APETag = 0;
|
|
||||||
|
|
||||||
if(d->ID3v1Tag)
|
|
||||||
d->tag = d->ID3v1Tag;
|
|
||||||
else
|
|
||||||
d->tag = d->APETag = new APE::Tag;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// private members
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
long MPC::File::findAPE()
|
|
||||||
{
|
|
||||||
if(!isValid())
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if(d->hasID3v1)
|
|
||||||
seek(-160, End);
|
|
||||||
else
|
|
||||||
seek(-32, End);
|
|
||||||
|
|
||||||
long p = tell();
|
|
||||||
|
|
||||||
if(readBlock(8) == APE::Tag::fileIdentifier())
|
|
||||||
return p;
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
long MPC::File::findID3v1()
|
|
||||||
{
|
|
||||||
if(!isValid())
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
seek(-128, End);
|
|
||||||
long p = tell();
|
|
||||||
|
|
||||||
if(readBlock(3) == ID3v1::Tag::fileIdentifier())
|
|
||||||
return p;
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
long MPC::File::findID3v2()
|
|
||||||
{
|
|
||||||
if(!isValid())
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
seek(0);
|
|
||||||
|
|
||||||
if(readBlock(3) == ID3v2::Header::fileIdentifier())
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
|
@ -1,176 +0,0 @@
|
||||||
/***************************************************************************
|
|
||||||
copyright : (C) 2004 by Allan Sandfeld Jensen
|
|
||||||
email : kde@carewolf.org
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* 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 *
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
#ifndef TAGLIB_MPCFILE_H
|
|
||||||
#define TAGLIB_MPCFILE_H
|
|
||||||
|
|
||||||
#include "taglib_export.h"
|
|
||||||
#include "tfile.h"
|
|
||||||
|
|
||||||
#include "mpcproperties.h"
|
|
||||||
|
|
||||||
namespace TagLib {
|
|
||||||
|
|
||||||
class Tag;
|
|
||||||
|
|
||||||
namespace ID3v1 { class Tag; }
|
|
||||||
namespace APE { class Tag; }
|
|
||||||
|
|
||||||
//! An implementation of MPC metadata
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* This is implementation of MPC metadata.
|
|
||||||
*
|
|
||||||
* This supports ID3v1 and APE (v1 and v2) style comments as well as reading stream
|
|
||||||
* properties from the file. ID3v2 tags are invalid in MPC-files, but will be skipped
|
|
||||||
* and ignored.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace MPC {
|
|
||||||
|
|
||||||
//! An implementation of TagLib::File with MPC specific methods
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* This implements and provides an interface for MPC files to the
|
|
||||||
* TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing
|
|
||||||
* the abstract TagLib::File API as well as providing some additional
|
|
||||||
* information specific to MPC files.
|
|
||||||
* The only invalid tag combination supported is an ID3v1 tag after an APE tag.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class TAGLIB_EXPORT File : public TagLib::File
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/*!
|
|
||||||
* This set of flags is used for various operations and is suitable for
|
|
||||||
* being OR-ed together.
|
|
||||||
*/
|
|
||||||
enum TagTypes {
|
|
||||||
//! Empty set. Matches no tag types.
|
|
||||||
NoTags = 0x0000,
|
|
||||||
//! Matches ID3v1 tags.
|
|
||||||
ID3v1 = 0x0001,
|
|
||||||
//! Matches ID3v2 tags.
|
|
||||||
ID3v2 = 0x0002,
|
|
||||||
//! Matches APE tags.
|
|
||||||
APE = 0x0004,
|
|
||||||
//! Matches all tag types.
|
|
||||||
AllTags = 0xffff
|
|
||||||
};
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Contructs an MPC file object without reading a file. Allows object
|
|
||||||
* fields to be set up before reading.
|
|
||||||
*/
|
|
||||||
File();
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Contructs an MPC file from \a file. If \a readProperties is true the
|
|
||||||
* file's audio properties will also be read using \a propertiesStyle. If
|
|
||||||
* false, \a propertiesStyle is ignored.
|
|
||||||
*/
|
|
||||||
File(const char *file, bool readProperties = true,
|
|
||||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Destroys this instance of the File.
|
|
||||||
*/
|
|
||||||
virtual ~File();
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the Tag for this file. This will be an APE tag, an ID3v1 tag
|
|
||||||
* or a combination of the two.
|
|
||||||
*/
|
|
||||||
virtual TagLib::Tag *tag() const;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the MPC::Properties for this file. If no audio properties
|
|
||||||
* were read then this will return a null pointer.
|
|
||||||
*/
|
|
||||||
virtual Properties *audioProperties() const;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Reads from MPC file. If \a readProperties is true the file's audio
|
|
||||||
* properties will also be read using \a propertiesStyle. If false,
|
|
||||||
* \a propertiesStyle is ignored.
|
|
||||||
*/
|
|
||||||
void read(bool readProperties = true,
|
|
||||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Saves the file.
|
|
||||||
*/
|
|
||||||
virtual bool save();
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns a pointer to the ID3v1 tag of the file.
|
|
||||||
*
|
|
||||||
* If \a create is false (the default) this will return a null pointer
|
|
||||||
* if there is no valid ID3v1 tag. If \a create is true it will create
|
|
||||||
* an ID3v1 tag if one does not exist. If there is already an APE tag, the
|
|
||||||
* new ID3v1 tag will be placed after it.
|
|
||||||
*
|
|
||||||
* \note The Tag <b>is still</b> owned by the APE::File and should not be
|
|
||||||
* deleted by the user. It will be deleted when the file (object) is
|
|
||||||
* destroyed.
|
|
||||||
*/
|
|
||||||
ID3v1::Tag *ID3v1Tag(bool create = false);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns a pointer to the APE tag of the file.
|
|
||||||
*
|
|
||||||
* If \a create is false (the default) this will return a null pointer
|
|
||||||
* if there is no valid APE tag. If \a create is true it will create
|
|
||||||
* a APE tag if one does not exist. If there is already an ID3v1 tag, thes
|
|
||||||
* new APE tag will be placed before it.
|
|
||||||
*
|
|
||||||
* \note The Tag <b>is still</b> owned by the APE::File and should not be
|
|
||||||
* deleted by the user. It will be deleted when the file (object) is
|
|
||||||
* destroyed.
|
|
||||||
*/
|
|
||||||
APE::Tag *APETag(bool create = false);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* This will remove the tags that match the OR-ed together TagTypes from the
|
|
||||||
* file. By default it removes all tags.
|
|
||||||
*
|
|
||||||
* \note This will also invalidate pointers to the tags
|
|
||||||
* as their memory will be freed.
|
|
||||||
* \note In order to make the removal permanent save() still needs to be called
|
|
||||||
*/
|
|
||||||
void remove(int tags = AllTags);
|
|
||||||
|
|
||||||
private:
|
|
||||||
File(const File &);
|
|
||||||
File &operator=(const File &);
|
|
||||||
|
|
||||||
void scan();
|
|
||||||
long findAPE();
|
|
||||||
long findID3v1();
|
|
||||||
long findID3v2();
|
|
||||||
|
|
||||||
class FilePrivate;
|
|
||||||
FilePrivate *d;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,136 +0,0 @@
|
||||||
/***************************************************************************
|
|
||||||
copyright : (C) 2004 by Allan Sandfeld Jensen
|
|
||||||
email : kde@carewolf.org
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* 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 *
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
#include <tstring.h>
|
|
||||||
#include <tdebug.h>
|
|
||||||
#include <bitset>
|
|
||||||
|
|
||||||
#include "mpcproperties.h"
|
|
||||||
#include "mpcfile.h"
|
|
||||||
|
|
||||||
using namespace TagLib;
|
|
||||||
|
|
||||||
class MPC::Properties::PropertiesPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PropertiesPrivate(const ByteVector &d, long length, ReadStyle s) :
|
|
||||||
data(d),
|
|
||||||
streamLength(length),
|
|
||||||
style(s),
|
|
||||||
version(0),
|
|
||||||
length(0),
|
|
||||||
bitrate(0),
|
|
||||||
sampleRate(0),
|
|
||||||
channels(0) {}
|
|
||||||
|
|
||||||
ByteVector data;
|
|
||||||
long streamLength;
|
|
||||||
ReadStyle style;
|
|
||||||
int version;
|
|
||||||
int length;
|
|
||||||
int bitrate;
|
|
||||||
int sampleRate;
|
|
||||||
int channels;
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// public members
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
MPC::Properties::Properties(const ByteVector &data, long streamLength, ReadStyle style) : AudioProperties(style)
|
|
||||||
{
|
|
||||||
d = new PropertiesPrivate(data, streamLength, style);
|
|
||||||
read();
|
|
||||||
}
|
|
||||||
|
|
||||||
MPC::Properties::~Properties()
|
|
||||||
{
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
int MPC::Properties::length() const
|
|
||||||
{
|
|
||||||
return d->length;
|
|
||||||
}
|
|
||||||
|
|
||||||
int MPC::Properties::bitrate() const
|
|
||||||
{
|
|
||||||
return d->bitrate;
|
|
||||||
}
|
|
||||||
|
|
||||||
int MPC::Properties::sampleRate() const
|
|
||||||
{
|
|
||||||
return d->sampleRate;
|
|
||||||
}
|
|
||||||
|
|
||||||
int MPC::Properties::channels() const
|
|
||||||
{
|
|
||||||
return d->channels;
|
|
||||||
}
|
|
||||||
|
|
||||||
int MPC::Properties::mpcVersion() const
|
|
||||||
{
|
|
||||||
return d->version;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// private members
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
static const unsigned short sftable [4] = { 44100, 48000, 37800, 32000 };
|
|
||||||
|
|
||||||
void MPC::Properties::read()
|
|
||||||
{
|
|
||||||
if(!d->data.startsWith("MP+"))
|
|
||||||
return;
|
|
||||||
|
|
||||||
d->version = d->data[3] & 15;
|
|
||||||
|
|
||||||
unsigned int frames;
|
|
||||||
|
|
||||||
if(d->version >= 7) {
|
|
||||||
frames = d->data.mid(4, 4).toUInt(false);
|
|
||||||
|
|
||||||
std::bitset<32> flags = d->data.mid(8, 4).toUInt(false);
|
|
||||||
d->sampleRate = sftable[flags[17] * 2 + flags[16]];
|
|
||||||
d->channels = 2;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
uint headerData = d->data.mid(0, 4).toUInt(false);
|
|
||||||
|
|
||||||
d->bitrate = (headerData >> 23) & 0x01ff;
|
|
||||||
d->version = (headerData >> 11) & 0x03ff;
|
|
||||||
d->sampleRate = 44100;
|
|
||||||
d->channels = 2;
|
|
||||||
|
|
||||||
if(d->version >= 5)
|
|
||||||
frames = d->data.mid(4, 4).toUInt(false);
|
|
||||||
else
|
|
||||||
frames = d->data.mid(6, 2).toUInt(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint samples = frames * 1152 - 576;
|
|
||||||
|
|
||||||
d->length = d->sampleRate > 0 ? (samples + (d->sampleRate / 2)) / d->sampleRate : 0;
|
|
||||||
|
|
||||||
if(!d->bitrate)
|
|
||||||
d->bitrate = d->length > 0 ? ((d->streamLength * 8L) / d->length) / 1000 : 0;
|
|
||||||
}
|
|
|
@ -1,77 +0,0 @@
|
||||||
/***************************************************************************
|
|
||||||
copyright : (C) 2004 by Allan Sandfeld Jensen
|
|
||||||
email : kde@carewolf.org
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
* 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 *
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
#ifndef TAGLIB_MPCPROPERTIES_H
|
|
||||||
#define TAGLIB_MPCPROPERTIES_H
|
|
||||||
|
|
||||||
#include "audioproperties.h"
|
|
||||||
|
|
||||||
namespace TagLib {
|
|
||||||
|
|
||||||
namespace MPC {
|
|
||||||
|
|
||||||
class File;
|
|
||||||
|
|
||||||
static const uint HeaderSize = 8*7;
|
|
||||||
|
|
||||||
//! An implementation of audio property reading for MPC
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* This reads the data from an MPC stream found in the AudioProperties
|
|
||||||
* API.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class Properties : public AudioProperties
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/*!
|
|
||||||
* Create an instance of MPC::Properties with the data read from the
|
|
||||||
* ByteVector \a data.
|
|
||||||
*/
|
|
||||||
Properties(const ByteVector &data, long streamLength, ReadStyle style = Average);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Destroys this MPC::Properties instance.
|
|
||||||
*/
|
|
||||||
virtual ~Properties();
|
|
||||||
|
|
||||||
// Reimplementations.
|
|
||||||
|
|
||||||
virtual int length() const;
|
|
||||||
virtual int bitrate() const;
|
|
||||||
virtual int sampleRate() const;
|
|
||||||
virtual int channels() const;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the version of the bitstream (SV4-SV7)
|
|
||||||
*/
|
|
||||||
int mpcVersion() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void read();
|
|
||||||
|
|
||||||
class PropertiesPrivate;
|
|
||||||
PropertiesPrivate *d;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue