Initial commit
This commit is contained in:
parent
464d2aceed
commit
62b2a5c57c
90
CMakeLists.txt
Normal file
90
CMakeLists.txt
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.17)
|
||||||
|
project(AtomicParsley)
|
||||||
|
|
||||||
|
if(NOT CMAKE_BUILD_TYPE)
|
||||||
|
set(CMAKE_BUILD_TYPE Release)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_program(GIT git)
|
||||||
|
if(GIT)
|
||||||
|
execute_process(
|
||||||
|
COMMAND "${GIT}" "show" "-s" "--format=%H;%cd" "--date=format:%Y%m%d.%H%M%S.0"
|
||||||
|
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||||
|
RESULT_VARIABLE git_result
|
||||||
|
OUTPUT_VARIABLE git_data
|
||||||
|
ERROR_VARIABLE git_err
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
)
|
||||||
|
if(git_result EQUAL 0)
|
||||||
|
list(GET git_data 0 BUILD_INFO)
|
||||||
|
list(GET git_data 1 PACKAGE_VERSION)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include(CheckSymbolExists)
|
||||||
|
check_symbol_exists(strsep "string.h" HAVE_STRSEP)
|
||||||
|
if(HAVE_STRSEP)
|
||||||
|
add_definitions(-DHAVE_STRSEP)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_definitions(
|
||||||
|
-DPACKAGE_VERSION="${PACKAGE_VERSION}"
|
||||||
|
-DBUILD_INFO="${BUILD_INFO}"
|
||||||
|
-D_FILE_OFFSET_BITS=64
|
||||||
|
)
|
||||||
|
|
||||||
|
find_package(ZLIB)
|
||||||
|
if(ZLIB_FOUND)
|
||||||
|
include_directories(${ZLIB_INCLUDE_DIRS})
|
||||||
|
add_definitions(-DHAVE_ZLIB_H)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
list(APPEND sources
|
||||||
|
src/CDtoc.cpp
|
||||||
|
src/arrays.cpp
|
||||||
|
src/compress.cpp
|
||||||
|
src/extracts.cpp
|
||||||
|
src/iconv.cpp
|
||||||
|
src/id3v2.cpp
|
||||||
|
src/main.cpp
|
||||||
|
src/metalist.cpp
|
||||||
|
src/parsley.cpp
|
||||||
|
src/sha1.cpp
|
||||||
|
src/util.cpp
|
||||||
|
src/uuid.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
||||||
|
list(APPEND sources
|
||||||
|
src/nsfile.mm
|
||||||
|
src/nsimage.mm
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
list(APPEND sources
|
||||||
|
src/extras/getopt.c
|
||||||
|
src/extras/getopt1.c
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_executable(
|
||||||
|
AtomicParsley
|
||||||
|
${sources}
|
||||||
|
)
|
||||||
|
|
||||||
|
if(ZLIB_FOUND)
|
||||||
|
target_link_libraries(
|
||||||
|
AtomicParsley
|
||||||
|
${ZLIB_LIBRARIES}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
||||||
|
target_link_libraries(
|
||||||
|
AtomicParsley
|
||||||
|
"-framework Cocoa"
|
||||||
|
"-framework Foundation"
|
||||||
|
"-framework IOKit"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
280
COPYING
Normal file
280
COPYING
Normal file
@ -0,0 +1,280 @@
|
|||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 2, June 1991
|
||||||
|
|
||||||
|
Copyright (C) 1989, 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.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
License is intended to guarantee your freedom to share and change free
|
||||||
|
software--to make sure the software is free for all its users. This
|
||||||
|
General Public License applies to most of the Free Software
|
||||||
|
Foundation's software and to any other program whose authors commit to
|
||||||
|
using it. (Some other Free Software Foundation software is covered by
|
||||||
|
the GNU Library General Public License instead.) You can apply it to
|
||||||
|
your programs, 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 software, or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must give the recipients all the rights that
|
||||||
|
you have. You must make sure that they, too, receive or can get the
|
||||||
|
source code. And you must show them these terms so they know their
|
||||||
|
rights.
|
||||||
|
|
||||||
|
We protect your rights with two steps: (1) copyright the software, and
|
||||||
|
(2) offer you this license which gives you legal permission to copy,
|
||||||
|
distribute and/or modify the software.
|
||||||
|
|
||||||
|
Also, for each author's protection and ours, we want to make certain
|
||||||
|
that everyone understands that there is no warranty for this free
|
||||||
|
software. If the software is modified by someone else and passed on, we
|
||||||
|
want its recipients to know that what they have is not the original, 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 redistributors of a free
|
||||||
|
program will individually obtain patent licenses, in effect making the
|
||||||
|
program proprietary. To prevent this, we have made it clear that any
|
||||||
|
patent must be licensed for everyone's free use or not licensed at all.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License applies to any program or other work which contains
|
||||||
|
a notice placed by the copyright holder saying it may be distributed
|
||||||
|
under the terms of this General Public License. The "Program", below,
|
||||||
|
refers to any such program or work, and a "work based on the Program"
|
||||||
|
means either the Program or any derivative work under copyright law:
|
||||||
|
that is to say, a work containing the Program or a portion of it,
|
||||||
|
either verbatim or with modifications and/or translated into another
|
||||||
|
language. (Hereinafter, translation is included without limitation in
|
||||||
|
the term "modification".) Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running the Program is not restricted, and the output from the Program
|
||||||
|
is covered only if its contents constitute a work based on the
|
||||||
|
Program (independent of having been made by running the Program).
|
||||||
|
Whether that is true depends on what the Program does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Program's
|
||||||
|
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 give any other recipients of the Program a copy of this License
|
||||||
|
along with the Program.
|
||||||
|
|
||||||
|
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 Program or any portion
|
||||||
|
of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
b) You must cause any work that you distribute or publish, that in
|
||||||
|
whole or in part contains or is derived from the Program or any
|
||||||
|
part thereof, to be licensed as a whole at no charge to all third
|
||||||
|
parties under the terms of this License.
|
||||||
|
|
||||||
|
c) If the modified program normally reads commands interactively
|
||||||
|
when run, you must cause it, when started running for such
|
||||||
|
interactive use in the most ordinary way, to print or display an
|
||||||
|
announcement including an appropriate copyright notice and a
|
||||||
|
notice that there is no warranty (or else, saying that you provide
|
||||||
|
a warranty) and that users may redistribute the program under
|
||||||
|
these conditions, and telling the user how to view a copy of this
|
||||||
|
License. (Exception: if the Program itself is interactive but
|
||||||
|
does not normally print such an announcement, your work based on
|
||||||
|
the Program is not required to print an announcement.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Program,
|
||||||
|
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 Program, 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 Program.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Program
|
||||||
|
with the Program (or with a work based on the Program) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may copy and distribute the Program (or a work based on it,
|
||||||
|
under Section 2) in object code or executable form under the terms of
|
||||||
|
Sections 1 and 2 above provided that you also do one of the following:
|
||||||
|
|
||||||
|
a) 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; or,
|
||||||
|
|
||||||
|
b) Accompany it with a written offer, valid for at least three
|
||||||
|
years, to give any third party, for a charge no more than your
|
||||||
|
cost of physically performing source distribution, a complete
|
||||||
|
machine-readable copy of the corresponding source code, to be
|
||||||
|
distributed under the terms of Sections 1 and 2 above on a medium
|
||||||
|
customarily used for software interchange; or,
|
||||||
|
|
||||||
|
c) Accompany it with the information you received as to the offer
|
||||||
|
to distribute corresponding source code. (This alternative is
|
||||||
|
allowed only for noncommercial distribution and only if you
|
||||||
|
received the program in object code or executable form with such
|
||||||
|
an offer, in accord with Subsection b above.)
|
||||||
|
|
||||||
|
The source code for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For an executable work, 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 executable. 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.
|
||||||
|
|
||||||
|
If distribution of executable or 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 counts as
|
||||||
|
distribution of the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
4. You may not copy, modify, sublicense, or distribute the Program
|
||||||
|
except as expressly provided under this License. Any attempt
|
||||||
|
otherwise to copy, modify, sublicense or distribute the Program 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.
|
||||||
|
|
||||||
|
5. 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 Program or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Program (or any work based on the
|
||||||
|
Program), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Program or works based on it.
|
||||||
|
|
||||||
|
6. Each time you redistribute the Program (or any work based on the
|
||||||
|
Program), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute or modify the Program 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.
|
||||||
|
|
||||||
|
7. 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 Program at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Program 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 Program.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
8. If the distribution and/or use of the Program is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Program 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.
|
||||||
|
|
||||||
|
9. The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the 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 Program
|
||||||
|
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 Program does not specify a version number of
|
||||||
|
this License, you may choose any version ever published by the Free Software
|
||||||
|
Foundation.
|
||||||
|
|
||||||
|
10. If you wish to incorporate parts of the Program into other free
|
||||||
|
programs whose distribution conditions are different, 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
|
||||||
|
|
||||||
|
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||||
|
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||||
|
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||||
|
PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE
|
||||||
|
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||||
|
REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER
|
||||||
|
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
48
CREDITS
Normal file
48
CREDITS
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
AtomicParsley is GPL software; you can freely distribute,
|
||||||
|
redistribute, modify & use under the terms of the GNU General
|
||||||
|
Public License; either version 2 or its successor.
|
||||||
|
|
||||||
|
AtomicParsley is distributed under the GPL "AS IS", without
|
||||||
|
any warranty; without the implied warranty of merchantability
|
||||||
|
or fitness for either an expressed or implied particular purpose.
|
||||||
|
|
||||||
|
Please see the included GNU General Public License (GPL) for
|
||||||
|
your rights and further details; see the file COPYING. If you
|
||||||
|
cannot, write to the Free Software Foundation, 59 Temple Place
|
||||||
|
Suite 330, Boston, MA 02111-1307, USA. Or www.fsf.org
|
||||||
|
|
||||||
|
Copyright (C) 2005-2007, puck_lock
|
||||||
|
Copyright (C) 2009-2012, Wez Furlong
|
||||||
|
Copyright (C) 2010-2012, Oleg Oshmyan
|
||||||
|
Copyright (C) 2009, 2011, Santino Fuentes
|
||||||
|
Copyright (C) 2011, John D Pell
|
||||||
|
Copyright (C) 2010, Edriss Mirzadeh
|
||||||
|
Copyright (C) 2009, Josh Aune
|
||||||
|
Copyright (C) 2014, Paul Foose
|
||||||
|
|
||||||
|
Miscellaneous Contributions made at unknown (to the current maintainers) times,
|
||||||
|
except that the changes are presumably circa 2005-2007:
|
||||||
|
|
||||||
|
* Mellow_Flow
|
||||||
|
* Mike Brancato
|
||||||
|
* Brian Story
|
||||||
|
* Lowell Stewart
|
||||||
|
* SLarew
|
||||||
|
|
||||||
|
Contains code derived from code that is:
|
||||||
|
|
||||||
|
Copyright (C) 1998-2003 Daniel Veillard. All Rights Reserved.
|
||||||
|
(See iconv.cpp for license)
|
||||||
|
Original code for IsoLatin1 and UTF-16 by "Martin J. Duerst" <duerst@w3.org>
|
||||||
|
|
||||||
|
Copyright (C) 2000, 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||||
|
Authors: Scott G. Miller, Robert Klep <robert@ilse.nl>
|
||||||
|
(See sha1.cpp)
|
||||||
|
|
||||||
|
Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc.
|
||||||
|
Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. &
|
||||||
|
Digital Equipment Corporation, Maynard, Mass.
|
||||||
|
Copyright (c) 1998 Microsoft.
|
||||||
|
(See uuid.cpp)
|
||||||
|
|
||||||
|
|
||||||
536
Changes.txt
Normal file
536
Changes.txt
Normal file
@ -0,0 +1,536 @@
|
|||||||
|
v0.1 10/05/2005
|
||||||
|
|
||||||
|
Parsing of atoms
|
||||||
|
|
||||||
|
intial Tree printout
|
||||||
|
|
||||||
|
extraction of all "covr.data" atoms out
|
||||||
|
to files
|
||||||
|
|
||||||
|
v0.2 11/10/2005
|
||||||
|
|
||||||
|
AtomicInfo.NextAtomNumber introduced to facilitate dynamic atom tree
|
||||||
|
reorganization
|
||||||
|
|
||||||
|
CreateSparseAtom added
|
||||||
|
|
||||||
|
v0.5 11/22/2005
|
||||||
|
|
||||||
|
Writes artist properly of variable lengths properly into an iTMS m4p file
|
||||||
|
properly (other files don't fare well due to the stsd atom non-standard
|
||||||
|
nature)
|
||||||
|
|
||||||
|
a number of code-uglifying workarounds were employed to get get that
|
||||||
|
far;
|
||||||
|
|
||||||
|
v0.6 11/25/2005
|
||||||
|
|
||||||
|
Added genre string/numerical support, support for genre's dual-atom ©gen/gnre
|
||||||
|
nature, genre string->integer
|
||||||
|
|
||||||
|
bug fixes to APar_LocateAtomInsertionPoint when
|
||||||
|
an atom is missing
|
||||||
|
|
||||||
|
APar_CreateSparseAtom for ordinary non-data atoms are now
|
||||||
|
type -1 (which means they aren't of any interest to us besides length & name);
|
||||||
|
implemnted the Integer data class
|
||||||
|
|
||||||
|
char4short
|
||||||
|
|
||||||
|
verified iTunes standard genres
|
||||||
|
only go up to "Hard Rock"
|
||||||
|
|
||||||
|
added jpg/png artwork embedding into "covr" atoms;
|
||||||
|
slight bugfix for APar_FindAtom (created spurious trailing "covr" atoms).
|
||||||
|
|
||||||
|
v0.6 GPL'ed at sourceforge.net
|
||||||
|
|
||||||
|
v0.65 11/25/2005
|
||||||
|
|
||||||
|
bugfixes to newly introduced bugs in APar_FindAtom
|
||||||
|
|
||||||
|
metaEnema to remove all
|
||||||
|
metadata (safe even for m4p drm files)
|
||||||
|
|
||||||
|
year implemented properly (tagtime
|
||||||
|
moved onto non-standard 'tdtg' atom ala id3v2.4 - because I like that tag);
|
||||||
|
added setting compilation "cpil" tag (an annoying 5byte tag)
|
||||||
|
|
||||||
|
added advisory
|
||||||
|
setting (maybe it'll give me a kick one cold winter day-do a "Get Info" in
|
||||||
|
iTunes & in the main "Summary" tab view will be a new little icon next to
|
||||||
|
artwork)
|
||||||
|
|
||||||
|
v0.7 11/26/2005
|
||||||
|
|
||||||
|
added a writeBack flag to for a less beta-like future
|
||||||
|
|
||||||
|
integrated NSImage
|
||||||
|
resizing of artwork
|
||||||
|
|
||||||
|
environmental preferences for artwork modifications
|
||||||
|
|
||||||
|
build
|
||||||
|
system mods for Mac-specific compiling
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
v0.7.1 11/27/2005
|
||||||
|
|
||||||
|
modified parsing & writing to support Apple Lossless (alac) mp4 files. The
|
||||||
|
lovely "alac.alac" non-standard atoms (parents & carry data) caused unplayable
|
||||||
|
files to be written. Only QT ISMA files get screwed now (no idea about Nero)
|
||||||
|
|
||||||
|
v0.7.2 11/29/2005
|
||||||
|
|
||||||
|
creates iTunes-required meta.hdlr
|
||||||
|
|
||||||
|
all the tags now get spit back when reading
|
||||||
|
them (--textdata)
|
||||||
|
|
||||||
|
slight fix to how atoms are parsed
|
||||||
|
|
||||||
|
all known m4a files now
|
||||||
|
tag properly: iTunes (m4a, m4b, chapterized, alac), Quicktime (ISMA & mpeg4 -
|
||||||
|
change filename ext to .m4a to see art
|
||||||
|
|
||||||
|
all QT products require the meta.hdlr
|
||||||
|
addition), faac, Helix Producer & Nero
|
||||||
|
|
||||||
|
slight change to how PrintDataAtoms
|
||||||
|
called FindParentAtom
|
||||||
|
|
||||||
|
added tag time on "©ed1" (edit date-might only really
|
||||||
|
belong directly under udta)
|
||||||
|
|
||||||
|
added "©url" to hold url
|
||||||
|
|
||||||
|
fixes to
|
||||||
|
APar_RemoveAtom
|
||||||
|
|
||||||
|
added cli ability to remove all artwork
|
||||||
|
|
||||||
|
v0.7.3 12/02/2005
|
||||||
|
|
||||||
|
handles stsd (and child) atoms better
|
||||||
|
|
||||||
|
modifies all stco offsets when needed
|
||||||
|
(not just the first)
|
||||||
|
|
||||||
|
new oddball iTMS video "drmi" atom handling
|
||||||
|
|
||||||
|
new "stik"
|
||||||
|
atom support (sets iTunes GetInfo->options:Movie,TV Show, Music Video)
|
||||||
|
|
||||||
|
writes
|
||||||
|
iTMS video drm TV shows well now
|
||||||
|
|
||||||
|
diffs in a hex editor are moov atom length,
|
||||||
|
and then into stco, so all is well
|
||||||
|
|
||||||
|
v0.7.4 12/03/2005
|
||||||
|
|
||||||
|
"desc", "tvnn", "tvsh", "tven" & "tves" setting
|
||||||
|
|
||||||
|
v0.7.5b 12/09/2005
|
||||||
|
|
||||||
|
forced 'mdat' into being childless (chapterized mpeg4 files have atoms
|
||||||
|
scattered througout mdat, but they aren't children)
|
||||||
|
|
||||||
|
fixed issues with ffmpeg
|
||||||
|
created mpeg4 files (that have mdat as 2nd atom
|
||||||
|
|
||||||
|
moov & chilren as last atoms);
|
||||||
|
moved ffmpeg mdat atoms around to end
|
||||||
|
|
||||||
|
better atom adding at the end
|
||||||
|
|
||||||
|
subbed
|
||||||
|
getopt_long_only to getopt_long for pre-10.4 users
|
||||||
|
|
||||||
|
added progressbar
|
||||||
|
|
||||||
|
v0.7.5c 12/10/2005
|
||||||
|
|
||||||
|
funnguy0's linux patches (thanks so much for that)
|
||||||
|
|
||||||
|
v0.7.5d 12/11/2005
|
||||||
|
|
||||||
|
endian issues for x86 mostly resolved
|
||||||
|
|
||||||
|
setting genre's segfaults
|
||||||
|
|
||||||
|
stik doesn't
|
||||||
|
get set in a multi-option command, but does as a single atom setting
|
||||||
|
|
||||||
|
Debian
|
||||||
|
port added to binaries (compiled under debian-31r0a-i386 with g++4.02-2,
|
||||||
|
libc6_2.3.5-8 & libstdc++6_4.0.2-2) - under VirtualPC - with the nano editor!
|
||||||
|
|
||||||
|
v0.7.5e 12/16/2005
|
||||||
|
|
||||||
|
ammends how atoms are added at the end of the hierarchy (notably this affects
|
||||||
|
ffmpeg video files)
|
||||||
|
|
||||||
|
writes "keyw", "catg", "pcst", "aART" atoms
|
||||||
|
|
||||||
|
read-only
|
||||||
|
"purl" & "egid" added
|
||||||
|
|
||||||
|
v0.7.6 12/31/2005
|
||||||
|
|
||||||
|
ceased flawed null-termination (which was implemented more in my mind) of text
|
||||||
|
'data' atoms
|
||||||
|
|
||||||
|
UTF-8 output on Mac OS X & Linux - comment in DUSE_ICONV_CONVERSION in the
|
||||||
|
build file to test it other platforms (maybe my win98Se isn't utf8 aware?)
|
||||||
|
|
||||||
|
cygwin build accommodations
|
||||||
|
|
||||||
|
fix to the secondary "of" number for track/disk on non-PPC
|
||||||
|
|
||||||
|
implemented user-defined completely sanctioned 'uuid' atoms to hold....
|
||||||
|
anything (text only for now)
|
||||||
|
|
||||||
|
"--tagtime", "--url" & "--information" now get set onto uuid atoms
|
||||||
|
|
||||||
|
allow creation of uuid atoms directly from the cli
|
||||||
|
|
||||||
|
cygwin-win98SE port added to binary releases
|
||||||
|
|
||||||
|
added '--freefree' to remove any&all 'free' atoms
|
||||||
|
|
||||||
|
v0.8 01/14/2006
|
||||||
|
|
||||||
|
switched over to uint8_t for former ADC_CPIL_TMPO & former ADC_Integer
|
||||||
|
|
||||||
|
added podcast stik setting & purl/egid
|
||||||
|
|
||||||
|
bugfixes to APar_RemoveAtom
|
||||||
|
|
||||||
|
bugfixes & optimizations to APar_FindAtom
|
||||||
|
|
||||||
|
changes to text output & set values for stik atom
|
||||||
|
|
||||||
|
increase in buffer size
|
||||||
|
|
||||||
|
limit non-uuid strings to 255bytes
|
||||||
|
|
||||||
|
fixed retreats in progress bar
|
||||||
|
|
||||||
|
added purd atom
|
||||||
|
|
||||||
|
support mdat.length=0 atom (length=1/64-bit isn't supported
|
||||||
|
|
||||||
|
I'll somehow cope with a < 4GB file)
|
||||||
|
|
||||||
|
switch from long to uint32_t
|
||||||
|
|
||||||
|
better x86 bitshifting
|
||||||
|
|
||||||
|
added swtich to prevent moving mdat atoms (possible PSP requires mdat before
|
||||||
|
moov)
|
||||||
|
|
||||||
|
universal binary for Mac OS X release
|
||||||
|
|
||||||
|
no text limit on lyrics tag
|
||||||
|
|
||||||
|
v0.8.4 02/25/2006
|
||||||
|
|
||||||
|
fixed an imaging bug from preferences
|
||||||
|
|
||||||
|
fixed metaEnema screwing up the meta atom (APar_RemoveAtom bugfix to remove a
|
||||||
|
direct_find atom)
|
||||||
|
|
||||||
|
added --output, --overWrite
|
||||||
|
|
||||||
|
added --metaDump to dump ONLY metadata tags to a file
|
||||||
|
|
||||||
|
versioning for cvs builds
|
||||||
|
|
||||||
|
limited support for 64-bit mdat atoms (limited to a little less than a 32-bit
|
||||||
|
atom > 4GB)
|
||||||
|
|
||||||
|
bugfixes to APar_RemoveAtom for removing uuid atoms or non-existing atoms & to
|
||||||
|
delete all artwork, then add in 1 command ("--artwork REMOVE_ALL --artwork
|
||||||
|
/path --artwork /path")
|
||||||
|
|
||||||
|
support 64-bit co64 atom
|
||||||
|
|
||||||
|
support MacOSX-style type/creator codes for tempfiles that end in ".mp4" (no
|
||||||
|
need to change extn to ".m4v"/".m4a" anymore)
|
||||||
|
|
||||||
|
moved purl/egid onto AtomicDataClass_UInteger (0x00 instead of 0x15) to mirror
|
||||||
|
Apple's change on these tags
|
||||||
|
|
||||||
|
start incorporating Brian's Win32 fixes (if you malloc, memset is sure to
|
||||||
|
follow fopen)
|
||||||
|
|
||||||
|
give the 'name' atom for '---' iTunes-internal tags for metadata printouts
|
||||||
|
|
||||||
|
allow --freefree remove 'free's up to a certain level (preserves iTunes
|
||||||
|
padding)
|
||||||
|
|
||||||
|
squash some memory leaks
|
||||||
|
|
||||||
|
change how CreateSparseAtom was matching atoms to accommodate EliminateAtom-ed
|
||||||
|
atoms (facilitates the previous artwork amendments)
|
||||||
|
|
||||||
|
exit on unsupported 'ftyp' file brands
|
||||||
|
|
||||||
|
anonymous 3rd party native win32 contributions
|
||||||
|
|
||||||
|
reworked APar_DetermineAtomLengths to accommodate proper tag setting with
|
||||||
|
--mdatLock
|
||||||
|
|
||||||
|
parsing atoms under 'stsd' is no longer internally used - only for tree
|
||||||
|
printing
|
||||||
|
|
||||||
|
reworked Mac OS X TYPE determination based on new stsd_codec structure member
|
||||||
|
|
||||||
|
revisit co64 offset calculations
|
||||||
|
|
||||||
|
start extracting track-level details (dates, language, encoder, channels)
|
||||||
|
|
||||||
|
changed stco/co64 calculations to support non-muxed files
|
||||||
|
|
||||||
|
anonymous "Everyday is NOT like Sunday" contribution
|
||||||
|
|
||||||
|
changed unknown 0x15 flagged metadata atoms to hex printouts
|
||||||
|
|
||||||
|
move mdat only when moov precedes mdat
|
||||||
|
|
||||||
|
new flexible esds parsing
|
||||||
|
|
||||||
|
v0.8.8 05/21/2006
|
||||||
|
|
||||||
|
prevent libmp4v2 artwork from a hexdump
|
||||||
|
|
||||||
|
changed how short strings were set
|
||||||
|
|
||||||
|
win32 change for uuid atoms to avoid sprintf
|
||||||
|
|
||||||
|
skip parsing 'free' atoms
|
||||||
|
|
||||||
|
work around foobar2000 0.9 non-compliant tagging scheme & added cli switch to
|
||||||
|
give 'tags' the GoLytely - aka '--foobar2000Enema'
|
||||||
|
|
||||||
|
ability to read/set completely separate 3gp tags subset (3GPP TS 26.444 version
|
||||||
|
6.4.0 Release 6 compliant & more like QuickTime-style tags)
|
||||||
|
|
||||||
|
added libxml's utf8 & utf16 conversion functions
|
||||||
|
|
||||||
|
new windows (windows2000 & later) unicode (utf16) console output (literal utf8
|
||||||
|
bytes in win98 & earlier
|
||||||
|
|
||||||
|
memset standard means of initializing
|
||||||
|
|
||||||
|
simplified setting of arbitrary info uniformly onto parsedAtoms.AtomicData
|
||||||
|
|
||||||
|
win32 switch to CP_UTF8 codepage on redirected console output for better
|
||||||
|
unicode output support
|
||||||
|
|
||||||
|
eliminate need for libiconv - use xml's utf8<->latin1 functions to supplant
|
||||||
|
libiconv
|
||||||
|
|
||||||
|
properly display atoms like '©nam' under Windows for trees & atom printouts
|
||||||
|
|
||||||
|
support setting unicode on Windows CP_UTF8
|
||||||
|
|
||||||
|
added 3GP keyword
|
||||||
|
|
||||||
|
fixed bug removing last 3GP asset to reset the length of 'udta'
|
||||||
|
|
||||||
|
added 'manualAtomRemove' for manually removing iTunes-style atoms
|
||||||
|
|
||||||
|
improved tracking of filesize/percentage when large free atoms impinge on % of
|
||||||
|
new filesize
|
||||||
|
|
||||||
|
added 3GP location 'loci' (El Loco) atom - all known 3GP assets can now be
|
||||||
|
set/viewed (except support for multiple same atoms of different languages)
|
||||||
|
|
||||||
|
->forced<- elimination of Nero tagging scheme (their foobar2000 inspired 'tags'
|
||||||
|
atom) on 3GP files
|
||||||
|
|
||||||
|
prevent iTunes-style tags on 3GP files or 3GP assets on MPEG-4 files
|
||||||
|
|
||||||
|
fix offsets in fragmented files ("moof.traf.tfhd") up MAX_ATOMS to 1024
|
||||||
|
|
||||||
|
Windows support for full utf16 (unicode) for cli args & filenames
|
||||||
|
|
||||||
|
v0.9.0 09/15/2006
|
||||||
|
|
||||||
|
new file scanning method based on an array of known atoms/KnownAtoms struct
|
||||||
|
added to list the gamut of known atoms & their basic properties
|
||||||
|
|
||||||
|
better atom versioning & flags support
|
||||||
|
|
||||||
|
allow negatives in 3gp asset coordinates (switch to high-bit ascii for
|
||||||
|
getopt_long for assets)
|
||||||
|
|
||||||
|
fixed minor bug that crept in on non-Win systems in removing files
|
||||||
|
|
||||||
|
switch from moving mdat(s) to moving moov to reorder atoms
|
||||||
|
|
||||||
|
mellow_flow's genre fix
|
||||||
|
|
||||||
|
SLarew's utf16 fix for printing 3gp assets on Win32
|
||||||
|
|
||||||
|
reorder moov's child atoms so that udta is last (as per ISO spec
|
||||||
|
recommendations) in moov
|
||||||
|
|
||||||
|
enable use of 'free' atom padding for rapid updating, pad with a (user-defined)
|
||||||
|
default amount of padding with a complete file rewrite
|
||||||
|
|
||||||
|
switch remaining AtomicInfo variables over to pointers
|
||||||
|
|
||||||
|
add support for multiple same atoms with differing languages (like 3gp assets);
|
||||||
|
more flexible 'stik' setting/retrieving & added Audiobook
|
||||||
|
|
||||||
|
genre bugfix (again!!)
|
||||||
|
|
||||||
|
added ability to list std genres & stik strings
|
||||||
|
|
||||||
|
switch output for rtng's "Lyrics" to "Content"
|
||||||
|
|
||||||
|
list file brands
|
||||||
|
|
||||||
|
bugfix for removing some cli metadata
|
||||||
|
|
||||||
|
prevent optimizing on PSP mpeg-4 files (but allow dynamic updating, and don't
|
||||||
|
add padding to psp files)
|
||||||
|
|
||||||
|
new APar_FindAtom routine eliminating some loops
|
||||||
|
|
||||||
|
updated routine to find 'moov.udta.meta.hdlr' or iTunes-style tagging
|
||||||
|
|
||||||
|
simplified APar_RemoveAtom
|
||||||
|
|
||||||
|
3gp assets differing in language are grouped now instead of being fifo
|
||||||
|
|
||||||
|
simplified printing of non-string iTunes-style tags
|
||||||
|
|
||||||
|
work around 3rd party bug affecting 'cprt' corruption
|
||||||
|
|
||||||
|
switch to fseeko to support files between 2.5GB & 4GB (and ancillary routines
|
||||||
|
off of filesize like progress bar)
|
||||||
|
|
||||||
|
fix co64 reduction offsets
|
||||||
|
|
||||||
|
prevent optimizing when just getting a tree or tags (screwed up track level
|
||||||
|
details)
|
||||||
|
|
||||||
|
bashfulbladder's booklet stik, only allow dynamic updating with --overWrite &
|
||||||
|
new "AP -t +" routine to show padding & supplemental info
|
||||||
|
|
||||||
|
changing win32 filename to '-utf8.exe' forces raw utf8 input/output
|
||||||
|
|
||||||
|
win32 longhelp is converted to utf16 (for atom names)
|
||||||
|
|
||||||
|
new shorthelp added as default help page
|
||||||
|
|
||||||
|
bugfix removing non-existing atoms
|
||||||
|
|
||||||
|
an actual change (removal/addition/change) of an atom is now required for any
|
||||||
|
type of write action
|
||||||
|
|
||||||
|
fix channel listing for 'esds' without sec5 info
|
||||||
|
|
||||||
|
added ability to force image dimensions on MacOSX
|
||||||
|
|
||||||
|
revamped track level details
|
||||||
|
|
||||||
|
255 byte limit for strings changed to 255 utf8 *character* limit
|
||||||
|
|
||||||
|
--stik Audiobook now changes file extension to '.m4b' (for Mac OS X, finder
|
||||||
|
Type code is changed to 'M4B ' too)
|
||||||
|
|
||||||
|
fix --3gp-year "" in APar_RemoveAtom
|
||||||
|
|
||||||
|
bugfix setting string lengths in 3gp keyword
|
||||||
|
|
||||||
|
added ability to add ISO 'cprt' copyright at movie or track level
|
||||||
|
|
||||||
|
implemented v5 sha1 namepsace/name uuids
|
||||||
|
|
||||||
|
fixed crash on finding any atom with full uuids (like psp files)
|
||||||
|
|
||||||
|
more extensive type/profiles/levels in track level details
|
||||||
|
|
||||||
|
add support for embedding files on uuid atoms
|
||||||
|
|
||||||
|
switch to reading artwork directly into memory (as opposed to copying from
|
||||||
|
a->b) when setting artwork
|
||||||
|
|
||||||
|
modified ExtractPixPrefs for leaks - defaults now to deleting temp pic files
|
||||||
|
|
||||||
|
skip sprintf for uuid binary strings ('qlts' is why) & switch to (less
|
||||||
|
flexible) memcpy
|
||||||
|
|
||||||
|
accommodate iTunes 7.0 adding aprox. 2k of NULL bytes outside of any atom
|
||||||
|
structure
|
||||||
|
|
||||||
|
add 'pgap' atom
|
||||||
|
|
||||||
|
defaults to duplicating the gapless padding at the end of file now (but can be
|
||||||
|
optionally skipped)
|
||||||
|
|
||||||
|
fixed clipping when setting unicode characters
|
||||||
|
|
||||||
|
v0.9.X ??/??/2007
|
||||||
|
|
||||||
|
now checks/lists 3 letter language codes
|
||||||
|
|
||||||
|
allow setting 3gp assets at track level
|
||||||
|
|
||||||
|
fix double fclose & relative paths with --overWrite
|
||||||
|
|
||||||
|
coalesce iso copyright notices into the new APar_UserData_atom_Init
|
||||||
|
|
||||||
|
initial support for setting iTunes reverseDNS atoms
|
||||||
|
|
||||||
|
fix validation test for 'trak' child atoms for atypical order
|
||||||
|
|
||||||
|
add mjpeg2000 (mjp2) major brand support (for copyright notices & uuid atoms)
|
||||||
|
|
||||||
|
restyled listings of all text metadata tags (-t 1)
|
||||||
|
|
||||||
|
fix multiple BOM prints on printouts
|
||||||
|
|
||||||
|
limit offset adjustments to local (non-external) data
|
||||||
|
|
||||||
|
added support for adjusting item location offsets
|
||||||
|
|
||||||
|
switch to a makefile/configure/config.h build system
|
||||||
|
|
||||||
|
start of ID3v2 2.4 implementation to go into ID32 atoms
|
||||||
|
|
||||||
|
limit chunk offset updates to local data
|
||||||
|
|
||||||
|
extend atom creation to file level (FL meta gets created after 'moov')
|
||||||
|
|
||||||
|
much of ID3v2 2.4 is completed: multiple text fields, counters, APIC/GEOB
|
||||||
|
setting/extracting, group symbols & zlib compression
|
||||||
|
|
||||||
|
add 3gp7 brands
|
||||||
|
|
||||||
|
allow ID32 based on compatible ftyp branding
|
||||||
|
|
||||||
|
refactoring & splitting of metadata listings
|
||||||
|
|
||||||
|
allow multiple entries in reverseDNS atoms (excepting iTunes domain)
|
||||||
|
|
||||||
|
initial (unfinished) revisit of file reorganizing/padding
|
||||||
|
|
||||||
|
update mvhd/tkhd modification timestamps
|
||||||
|
|
||||||
|
v0.9.6 02/22/2014
|
||||||
|
|
||||||
|
update for iTunes 11 compatibility
|
||||||
|
if stik "Movie" is used, set value to 9, instead of 0
|
||||||
|
iTunes now views stick value 0 as "Home Video"
|
||||||
|
left "Short Film" to also set stik 9, for backward compatibility with work-arounds using "Short Film" to set stik to 9
|
||||||
|
|
||||||
|
Swapped TV-Y and TV-Y7 to conform with iTunes usage.
|
||||||
|
|
||||||
|
|
||||||
57
README.md
57
README.md
@ -1,3 +1,56 @@
|
|||||||
# atomicparsley
|
# AtomicParsley
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
### macOS
|
||||||
|
|
||||||
|
* Navigate to the [latest release](https://github.com/wez/atomicparsley/releases/latest)
|
||||||
|
* Download the `AtomicParsleyMacOS.zip` file and extract `AtomicParsley`
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
|
||||||
|
* Navigate to the [latest release](https://github.com/wez/atomicparsley/releases/latest)
|
||||||
|
* Download the `AtomicParsleyWindows.zip` file and extract `AtomicParsley.exe`
|
||||||
|
|
||||||
|
### Building from Source
|
||||||
|
|
||||||
|
If you are building from source you will need `cmake` and `make`.
|
||||||
|
On Windows systems you'll need Visual Studio or MingW.
|
||||||
|
|
||||||
|
```
|
||||||
|
cmake .
|
||||||
|
cmake --build . --config Release
|
||||||
|
```
|
||||||
|
|
||||||
|
will generate an `AtomicParsley` executable.
|
||||||
|
|
||||||
|
### Dependencies:
|
||||||
|
|
||||||
|
zlib - used to compress ID3 frames & expand already compressed frames
|
||||||
|
available from http://www.zlib.net
|
||||||
|
|
||||||
|
|
||||||
|
## A note on maintenance!
|
||||||
|
|
||||||
|
> I made some fixes to the original project on sourceforge back in
|
||||||
|
> in 2009 and became the de-facto fork of AtomicParsley as a
|
||||||
|
> result. However, I haven't used this tool myself in many years and have
|
||||||
|
> acted in a very loose guiding role since then.
|
||||||
|
>
|
||||||
|
> In 2020 Bitbucket decided to cease hosting Mercurial based repositories
|
||||||
|
> which meant that I had to move it in order to keep it alive, so you'll
|
||||||
|
> see a flurry of recent activity.
|
||||||
|
>
|
||||||
|
> I'll consider merging pull requests if they are easy to review, but because
|
||||||
|
> I don't use this tool myself I have no way to verify complex changes.
|
||||||
|
> If you'd like to make such a change, please consider contributing some
|
||||||
|
> kind of basic automated test with a corresponding small test file.
|
||||||
|
>
|
||||||
|
> This repo has GitHub Actions enabled for the three major platforms
|
||||||
|
> so bootstrapping some test coverage is feasible.
|
||||||
|
>
|
||||||
|
> You are welcome to report issues using the issue tracker, but I am
|
||||||
|
> unlikely to act upon them.
|
||||||
|
|
||||||
atomicparsley repo (used for Alpine Linux)
|
|
||||||
9
src/.clang-format
Normal file
9
src/.clang-format
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
BasedOnStyle: LLVM
|
||||||
|
IndentWidth: 2
|
||||||
|
BinPackArguments: false
|
||||||
|
BinPackParameters: false
|
||||||
|
IncludeIsMainRegex: AtomicParse
|
||||||
|
---
|
||||||
|
Language: Cpp
|
||||||
|
---
|
||||||
389
src/AtomDefs.h
Normal file
389
src/AtomDefs.h
Normal file
@ -0,0 +1,389 @@
|
|||||||
|
//==================================================================//
|
||||||
|
/*
|
||||||
|
AtomicParsley - AtomDefs.h
|
||||||
|
|
||||||
|
AtomicParsley is GPL software; you can freely distribute,
|
||||||
|
redistribute, modify & use under the terms of the GNU General
|
||||||
|
Public License; either version 2 or its successor.
|
||||||
|
|
||||||
|
AtomicParsley is distributed under the GPL "AS IS", without
|
||||||
|
any warranty; without the implied warranty of merchantability
|
||||||
|
or fitness for either an expressed or implied particular purpose.
|
||||||
|
|
||||||
|
Please see the included GNU General Public License (GPL) for
|
||||||
|
your rights and further details; see the file COPYING. If you
|
||||||
|
cannot, write to the Free Software Foundation, 59 Temple Place
|
||||||
|
Suite 330, Boston, MA 02111-1307, USA. Or www.fsf.org
|
||||||
|
|
||||||
|
Copyright ©2006-2007 puck_lock
|
||||||
|
with contributions from others; see the CREDITS file
|
||||||
|
*/
|
||||||
|
//==================================================================//
|
||||||
|
|
||||||
|
#include "AtomicParsley.h"
|
||||||
|
|
||||||
|
atomDefinition KnownAtoms[] = {
|
||||||
|
// name parent atom(s) container
|
||||||
|
// number
|
||||||
|
// box_type
|
||||||
|
{"<()>",
|
||||||
|
{"_ANY_LEVEL"},
|
||||||
|
UNKNOWN_ATOM_TYPE,
|
||||||
|
UKNOWN_REQUIREMENTS,
|
||||||
|
UNKNOWN_ATOM}, // our unknown atom (self-defined)
|
||||||
|
|
||||||
|
{"ftyp", {"FILE_LEVEL"}, CHILD_ATOM, REQUIRED_ONCE, SIMPLE_ATOM},
|
||||||
|
|
||||||
|
{"moov", {"FILE_LEVEL"}, PARENT_ATOM, REQUIRED_ONCE, SIMPLE_ATOM},
|
||||||
|
|
||||||
|
{"mdat", {"FILE_LEVEL"}, CHILD_ATOM, OPTIONAL_MANY, SIMPLE_ATOM},
|
||||||
|
|
||||||
|
{"pdin", {"FILE_LEVEL"}, CHILD_ATOM, OPTIONAL_ONCE, VERSIONED_ATOM},
|
||||||
|
|
||||||
|
{"moof", {"FILE_LEVEL"}, PARENT_ATOM, OPTIONAL_MANY, SIMPLE_ATOM},
|
||||||
|
{"mfhd", {"moof"}, CHILD_ATOM, REQUIRED_ONE, VERSIONED_ATOM},
|
||||||
|
{"traf", {"moof"}, PARENT_ATOM, OPTIONAL_ONE, SIMPLE_ATOM},
|
||||||
|
{"tfhd", {"traf"}, CHILD_ATOM, REQUIRED_ONE, VERSIONED_ATOM},
|
||||||
|
{"trun", {"traf"}, CHILD_ATOM, REQUIRED_ONE, VERSIONED_ATOM},
|
||||||
|
|
||||||
|
{"mfra", {"FILE_LEVEL"}, PARENT_ATOM, OPTIONAL_ONCE, SIMPLE_ATOM},
|
||||||
|
{"tfra", {"mfra"}, CHILD_ATOM, OPTIONAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"mfro", {"mfra"}, CHILD_ATOM, REQUIRED_ONE, VERSIONED_ATOM},
|
||||||
|
|
||||||
|
{"free", {"_ANY_LEVEL"}, CHILD_ATOM, OPTIONAL_MANY, SIMPLE_ATOM},
|
||||||
|
{"skip", {"_ANY_LEVEL"}, CHILD_ATOM, OPTIONAL_MANY, SIMPLE_ATOM},
|
||||||
|
|
||||||
|
{"uuid", {"_ANY_LEVEL"}, CHILD_ATOM, REQUIRED_ONCE, EXTENDED_ATOM},
|
||||||
|
|
||||||
|
{"mvhd", {"moov"}, CHILD_ATOM, REQUIRED_ONCE, VERSIONED_ATOM},
|
||||||
|
{"iods", {"moov"}, CHILD_ATOM, OPTIONAL_ONCE, VERSIONED_ATOM},
|
||||||
|
{"drm ",
|
||||||
|
{"moov"},
|
||||||
|
CHILD_ATOM,
|
||||||
|
OPTIONAL_ONCE,
|
||||||
|
VERSIONED_ATOM}, // 3gp/MobileMP4
|
||||||
|
{"trak", {"moov"}, PARENT_ATOM, OPTIONAL_MANY, SIMPLE_ATOM},
|
||||||
|
|
||||||
|
{"tkhd", {"trak"}, CHILD_ATOM, OPTIONAL_MANY, VERSIONED_ATOM},
|
||||||
|
{"tref", {"trak"}, PARENT_ATOM, OPTIONAL_MANY, SIMPLE_ATOM},
|
||||||
|
{"mdia", {"trak"}, PARENT_ATOM, OPTIONAL_ONE, SIMPLE_ATOM},
|
||||||
|
|
||||||
|
{"tapt", {"trak"}, PARENT_ATOM, OPTIONAL_ONE, SIMPLE_ATOM},
|
||||||
|
{"clef", {"tapt"}, CHILD_ATOM, OPTIONAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"prof", {"tapt"}, CHILD_ATOM, OPTIONAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"enof", {"tapt"}, CHILD_ATOM, OPTIONAL_ONE, VERSIONED_ATOM},
|
||||||
|
|
||||||
|
{"mdhd", {"mdia"}, CHILD_ATOM, OPTIONAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"minf", {"mdia"}, PARENT_ATOM, REQUIRED_ONE, SIMPLE_ATOM},
|
||||||
|
|
||||||
|
{"hdlr",
|
||||||
|
{"mdia", "meta", "minf"},
|
||||||
|
CHILD_ATOM,
|
||||||
|
REQUIRED_ONE,
|
||||||
|
VERSIONED_ATOM}, // minf parent present in chapterized
|
||||||
|
|
||||||
|
{"vmhd", {"minf"}, CHILD_ATOM, REQ_FAMILIAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"smhd", {"minf"}, CHILD_ATOM, REQ_FAMILIAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"hmhd", {"minf"}, CHILD_ATOM, REQ_FAMILIAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"nmhd", {"minf"}, CHILD_ATOM, REQ_FAMILIAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"gmhd",
|
||||||
|
{"minf"},
|
||||||
|
CHILD_ATOM,
|
||||||
|
REQ_FAMILIAL_ONE,
|
||||||
|
VERSIONED_ATOM}, // present in chapterized
|
||||||
|
|
||||||
|
{"dinf",
|
||||||
|
{"minf", "meta"},
|
||||||
|
PARENT_ATOM,
|
||||||
|
OPTIONAL_ONE,
|
||||||
|
SIMPLE_ATOM}, // required in minf
|
||||||
|
|
||||||
|
{"dref", {"dinf"}, DUAL_STATE_ATOM, REQUIRED_ONE, VERSIONED_ATOM},
|
||||||
|
|
||||||
|
{"url ", {"dref"}, CHILD_ATOM, OPTIONAL_MANY, VERSIONED_ATOM},
|
||||||
|
{"urn ", {"dref"}, CHILD_ATOM, OPTIONAL_MANY, VERSIONED_ATOM},
|
||||||
|
{"alis", {"dref"}, CHILD_ATOM, OPTIONAL_MANY, VERSIONED_ATOM},
|
||||||
|
{"cios", {"dref"}, CHILD_ATOM, OPTIONAL_MANY, VERSIONED_ATOM},
|
||||||
|
|
||||||
|
{"stbl", {"minf"}, PARENT_ATOM, REQUIRED_ONE, SIMPLE_ATOM},
|
||||||
|
{"stts", {"stbl"}, CHILD_ATOM, REQUIRED_ONE, VERSIONED_ATOM},
|
||||||
|
{"ctts", {"stbl"}, CHILD_ATOM, OPTIONAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"stsd", {"stbl"}, DUAL_STATE_ATOM, REQUIRED_ONE, VERSIONED_ATOM},
|
||||||
|
|
||||||
|
{"stsz", {"stbl"}, CHILD_ATOM, REQ_FAMILIAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"stz2", {"stbl"}, CHILD_ATOM, REQ_FAMILIAL_ONE, VERSIONED_ATOM},
|
||||||
|
|
||||||
|
{"stsc", {"stbl"}, CHILD_ATOM, REQUIRED_ONE, VERSIONED_ATOM},
|
||||||
|
|
||||||
|
{"stco", {"stbl"}, CHILD_ATOM, REQ_FAMILIAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"co64", {"stbl"}, CHILD_ATOM, REQ_FAMILIAL_ONE, VERSIONED_ATOM},
|
||||||
|
|
||||||
|
{"stss", {"stbl"}, CHILD_ATOM, OPTIONAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"stsh", {"stbl"}, CHILD_ATOM, OPTIONAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"stdp", {"stbl"}, CHILD_ATOM, OPTIONAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"padb", {"stbl"}, CHILD_ATOM, OPTIONAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"sdtp", {"stbl", "traf"}, CHILD_ATOM, OPTIONAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"sbgp", {"stbl", "traf"}, CHILD_ATOM, OPTIONAL_MANY, VERSIONED_ATOM},
|
||||||
|
{"sbgp", {"stbl"}, CHILD_ATOM, OPTIONAL_MANY, VERSIONED_ATOM},
|
||||||
|
{"stps", {"stbl"}, CHILD_ATOM, OPTIONAL_ONE, VERSIONED_ATOM},
|
||||||
|
|
||||||
|
{"edts", {"trak"}, PARENT_ATOM, OPTIONAL_ONE, SIMPLE_ATOM},
|
||||||
|
{"elst", {"edts"}, CHILD_ATOM, OPTIONAL_ONE, VERSIONED_ATOM},
|
||||||
|
|
||||||
|
{"udta", {"moov", "trak"}, PARENT_ATOM, OPTIONAL_ONE, SIMPLE_ATOM},
|
||||||
|
|
||||||
|
{"meta",
|
||||||
|
{"FILE_LEVEL", "moov", "trak", "udta"},
|
||||||
|
DUAL_STATE_ATOM,
|
||||||
|
OPTIONAL_ONE,
|
||||||
|
VERSIONED_ATOM}, // optionally contains info
|
||||||
|
|
||||||
|
{"mvex", {"moov"}, PARENT_ATOM, OPTIONAL_ONCE, SIMPLE_ATOM},
|
||||||
|
{"mehd", {"mvex"}, CHILD_ATOM, OPTIONAL_ONCE, VERSIONED_ATOM},
|
||||||
|
{"trex", {"mvex"}, CHILD_ATOM, REQUIRED_ONE, VERSIONED_ATOM},
|
||||||
|
|
||||||
|
//{"stsl", {"????"}, CHILD_ATOM,
|
||||||
|
// OPTIONAL_ONE,
|
||||||
|
// VERSIONED_ATOM }, //contained by a sample
|
||||||
|
// entry
|
||||||
|
// box
|
||||||
|
{"subs", {"stbl", "traf"}, CHILD_ATOM, OPTIONAL_ONE, VERSIONED_ATOM},
|
||||||
|
|
||||||
|
{"xml ", {"meta"}, CHILD_ATOM, OPTIONAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"bxml", {"meta"}, CHILD_ATOM, OPTIONAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"iloc", {"meta"}, CHILD_ATOM, OPTIONAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"pitm", {"meta"}, CHILD_ATOM, OPTIONAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"ipro", {"meta"}, PARENT_ATOM, OPTIONAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"iinf", {"meta"}, DUAL_STATE_ATOM, OPTIONAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"infe", {"iinf"}, CHILD_ATOM, OPTIONAL_ONE, VERSIONED_ATOM},
|
||||||
|
|
||||||
|
{"sinf",
|
||||||
|
{"ipro", "drms", "drmi"},
|
||||||
|
PARENT_ATOM,
|
||||||
|
REQUIRED_ONE,
|
||||||
|
SIMPLE_ATOM}, // parent atom is also "Protected Sample Entry"
|
||||||
|
{"frma", {"sinf"}, CHILD_ATOM, REQUIRED_ONE, SIMPLE_ATOM},
|
||||||
|
{"imif", {"sinf"}, CHILD_ATOM, OPTIONAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"schm", {"sinf", "srpp"}, CHILD_ATOM, OPTIONAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"schi", {"sinf", "srpp"}, DUAL_STATE_ATOM, OPTIONAL_ONE, SIMPLE_ATOM},
|
||||||
|
{"skcr", {"sinf"}, CHILD_ATOM, OPTIONAL_ONE, VERSIONED_ATOM},
|
||||||
|
|
||||||
|
{"user", {"schi"}, CHILD_ATOM, OPTIONAL_ONE, SIMPLE_ATOM},
|
||||||
|
{"key ",
|
||||||
|
{"schi"},
|
||||||
|
CHILD_ATOM,
|
||||||
|
OPTIONAL_ONE,
|
||||||
|
VERSIONED_ATOM}, // could be required in 'drms'/'drmi'
|
||||||
|
{"iviv", {"schi"}, CHILD_ATOM, OPTIONAL_ONE, SIMPLE_ATOM},
|
||||||
|
{"righ", {"schi"}, CHILD_ATOM, OPTIONAL_ONE, SIMPLE_ATOM},
|
||||||
|
{"name", {"schi"}, CHILD_ATOM, OPTIONAL_ONE, SIMPLE_ATOM},
|
||||||
|
{"priv", {"schi"}, CHILD_ATOM, OPTIONAL_ONE, SIMPLE_ATOM},
|
||||||
|
|
||||||
|
{"iKMS",
|
||||||
|
{"schi"},
|
||||||
|
CHILD_ATOM,
|
||||||
|
OPTIONAL_ONE,
|
||||||
|
VERSIONED_ATOM}, // 'iAEC', '264b', 'iOMA', 'ICSD'
|
||||||
|
{"iSFM", {"schi"}, CHILD_ATOM, OPTIONAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"iSLT",
|
||||||
|
{"schi"},
|
||||||
|
CHILD_ATOM,
|
||||||
|
OPTIONAL_ONE,
|
||||||
|
SIMPLE_ATOM}, // boxes with 'k***' are also here; reserved
|
||||||
|
{"IKEY", {"tref"}, CHILD_ATOM, OPTIONAL_ONE, SIMPLE_ATOM},
|
||||||
|
{"hint", {"tref"}, CHILD_ATOM, OPTIONAL_ONE, SIMPLE_ATOM},
|
||||||
|
{"dpnd", {"tref"}, CHILD_ATOM, OPTIONAL_ONE, SIMPLE_ATOM},
|
||||||
|
{"ipir", {"tref"}, CHILD_ATOM, OPTIONAL_ONE, SIMPLE_ATOM},
|
||||||
|
{"mpod", {"tref"}, CHILD_ATOM, OPTIONAL_ONE, SIMPLE_ATOM},
|
||||||
|
{"sync", {"tref"}, CHILD_ATOM, OPTIONAL_ONE, SIMPLE_ATOM},
|
||||||
|
{"chap",
|
||||||
|
{"tref"},
|
||||||
|
CHILD_ATOM,
|
||||||
|
OPTIONAL_ONE,
|
||||||
|
SIMPLE_ATOM}, //?possible versioned?
|
||||||
|
|
||||||
|
{"ipmc", {"moov", "meta"}, CHILD_ATOM, OPTIONAL_ONE, VERSIONED_ATOM},
|
||||||
|
|
||||||
|
{"tims", {"rtp "}, CHILD_ATOM, REQUIRED_ONE, SIMPLE_ATOM},
|
||||||
|
{"tsro", {"rtp "}, CHILD_ATOM, OPTIONAL_ONE, SIMPLE_ATOM},
|
||||||
|
{"snro", {"rtp "}, CHILD_ATOM, OPTIONAL_ONE, SIMPLE_ATOM},
|
||||||
|
|
||||||
|
{"srpp", {"srtp"}, CHILD_ATOM, REQUIRED_ONE, VERSIONED_ATOM},
|
||||||
|
|
||||||
|
{"hnti", {"udta"}, PARENT_ATOM, OPTIONAL_ONE, SIMPLE_ATOM},
|
||||||
|
{"rtp ",
|
||||||
|
{"hnti"},
|
||||||
|
CHILD_ATOM,
|
||||||
|
OPTIONAL_ONE,
|
||||||
|
SIMPLE_ATOM}, //'rtp ' is defined twice in different containers
|
||||||
|
{"sdp ", {"hnti"}, CHILD_ATOM, OPTIONAL_ONE, SIMPLE_ATOM},
|
||||||
|
|
||||||
|
{"hinf", {"udta"}, PARENT_ATOM, OPTIONAL_ONE, SIMPLE_ATOM},
|
||||||
|
{"name", {"udta"}, CHILD_ATOM, OPTIONAL_ONE, SIMPLE_ATOM},
|
||||||
|
{"trpy", {"hinf"}, CHILD_ATOM, OPTIONAL_ONE, SIMPLE_ATOM},
|
||||||
|
{"nump", {"hinf"}, CHILD_ATOM, OPTIONAL_ONE, SIMPLE_ATOM},
|
||||||
|
{"tpyl", {"hinf"}, CHILD_ATOM, OPTIONAL_ONE, SIMPLE_ATOM},
|
||||||
|
{"totl", {"hinf"}, CHILD_ATOM, OPTIONAL_ONE, SIMPLE_ATOM},
|
||||||
|
{"npck", {"hinf"}, CHILD_ATOM, OPTIONAL_ONE, SIMPLE_ATOM},
|
||||||
|
{"maxr", {"hinf"}, CHILD_ATOM, OPTIONAL_MANY, SIMPLE_ATOM},
|
||||||
|
{"dmed", {"hinf"}, CHILD_ATOM, OPTIONAL_ONE, SIMPLE_ATOM},
|
||||||
|
{"dimm", {"hinf"}, CHILD_ATOM, OPTIONAL_ONE, SIMPLE_ATOM},
|
||||||
|
{"drep", {"hinf"}, CHILD_ATOM, OPTIONAL_ONE, SIMPLE_ATOM},
|
||||||
|
{"tmin", {"hinf"}, CHILD_ATOM, OPTIONAL_ONE, SIMPLE_ATOM},
|
||||||
|
{"tmax", {"hinf"}, CHILD_ATOM, OPTIONAL_ONE, SIMPLE_ATOM},
|
||||||
|
{"pmax", {"hinf"}, CHILD_ATOM, OPTIONAL_ONE, SIMPLE_ATOM},
|
||||||
|
{"dmax", {"hinf"}, CHILD_ATOM, OPTIONAL_ONE, SIMPLE_ATOM},
|
||||||
|
{"payt", {"hinf"}, CHILD_ATOM, OPTIONAL_ONE, SIMPLE_ATOM},
|
||||||
|
{"tpay", {"hinf"}, CHILD_ATOM, OPTIONAL_ONE, SIMPLE_ATOM},
|
||||||
|
|
||||||
|
{"drms", {"stsd"}, DUAL_STATE_ATOM, REQ_FAMILIAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"drmi", {"stsd"}, DUAL_STATE_ATOM, REQ_FAMILIAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"alac", {"stsd"}, DUAL_STATE_ATOM, REQ_FAMILIAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"mp4a", {"stsd"}, DUAL_STATE_ATOM, REQ_FAMILIAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"mp4s", {"stsd"}, DUAL_STATE_ATOM, REQ_FAMILIAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"mp4v", {"stsd"}, DUAL_STATE_ATOM, REQ_FAMILIAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"avc1", {"stsd"}, DUAL_STATE_ATOM, REQ_FAMILIAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"avcp", {"stsd"}, DUAL_STATE_ATOM, REQ_FAMILIAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"text", {"stsd"}, DUAL_STATE_ATOM, REQ_FAMILIAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"jpeg", {"stsd"}, DUAL_STATE_ATOM, REQ_FAMILIAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"tx3g", {"stsd"}, DUAL_STATE_ATOM, REQ_FAMILIAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"rtp ",
|
||||||
|
{"stsd"},
|
||||||
|
DUAL_STATE_ATOM,
|
||||||
|
REQ_FAMILIAL_ONE,
|
||||||
|
VERSIONED_ATOM}, //"rtp " occurs twice; disparate meanings
|
||||||
|
{"srtp", {"stsd"}, DUAL_STATE_ATOM, REQ_FAMILIAL_ONE, SIMPLE_ATOM},
|
||||||
|
{"enca", {"stsd"}, DUAL_STATE_ATOM, REQ_FAMILIAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"encv", {"stsd"}, DUAL_STATE_ATOM, REQ_FAMILIAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"enct", {"stsd"}, DUAL_STATE_ATOM, REQ_FAMILIAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"encs", {"stsd"}, DUAL_STATE_ATOM, REQ_FAMILIAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"samr", {"stsd"}, DUAL_STATE_ATOM, REQ_FAMILIAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"sawb", {"stsd"}, DUAL_STATE_ATOM, REQ_FAMILIAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"sawp", {"stsd"}, DUAL_STATE_ATOM, REQ_FAMILIAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"s263", {"stsd"}, DUAL_STATE_ATOM, REQ_FAMILIAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"sevc", {"stsd"}, DUAL_STATE_ATOM, REQ_FAMILIAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"sqcp", {"stsd"}, DUAL_STATE_ATOM, REQ_FAMILIAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"ssmv", {"stsd"}, DUAL_STATE_ATOM, REQ_FAMILIAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"tmcd", {"stsd"}, DUAL_STATE_ATOM, REQ_FAMILIAL_ONE, VERSIONED_ATOM},
|
||||||
|
{"mjp2",
|
||||||
|
{"stsd"},
|
||||||
|
DUAL_STATE_ATOM,
|
||||||
|
REQ_FAMILIAL_ONE,
|
||||||
|
VERSIONED_ATOM}, // mjpeg2000
|
||||||
|
|
||||||
|
{"alac", {"alac"}, CHILD_ATOM, REQUIRED_ONE, SIMPLE_ATOM},
|
||||||
|
{"avcC", {"avc1", "drmi"}, CHILD_ATOM, REQUIRED_ONE, SIMPLE_ATOM},
|
||||||
|
{"damr", {"samr", "sawb"}, CHILD_ATOM, REQUIRED_ONE, SIMPLE_ATOM},
|
||||||
|
{"d263", {"s263"}, CHILD_ATOM, REQUIRED_ONE, SIMPLE_ATOM},
|
||||||
|
{"dawp", {"sawp"}, CHILD_ATOM, REQUIRED_ONE, SIMPLE_ATOM},
|
||||||
|
{"devc", {"sevc"}, CHILD_ATOM, REQUIRED_ONE, SIMPLE_ATOM},
|
||||||
|
{"dqcp", {"sqcp"}, CHILD_ATOM, REQUIRED_ONE, SIMPLE_ATOM},
|
||||||
|
{"dsmv", {"ssmv"}, CHILD_ATOM, REQUIRED_ONE, SIMPLE_ATOM},
|
||||||
|
{"bitr", {"d263"}, CHILD_ATOM, REQUIRED_ONE, SIMPLE_ATOM},
|
||||||
|
{"btrt",
|
||||||
|
{"avc1"},
|
||||||
|
CHILD_ATOM,
|
||||||
|
OPTIONAL_ONE,
|
||||||
|
SIMPLE_ATOM}, // found in NeroAVC
|
||||||
|
{"m4ds",
|
||||||
|
{"avc1"},
|
||||||
|
CHILD_ATOM,
|
||||||
|
OPTIONAL_ONE,
|
||||||
|
SIMPLE_ATOM}, //?possible versioned?
|
||||||
|
{"ftab", {"tx3g"}, CHILD_ATOM, OPTIONAL_ONE, SIMPLE_ATOM},
|
||||||
|
{"jp2h", {"mjp2"}, PARENT_ATOM, OPTIONAL_ONE, SIMPLE_ATOM}, // mjpeg2000
|
||||||
|
|
||||||
|
{"ihdr", {"jp2h"}, CHILD_ATOM, OPTIONAL_ONE, SIMPLE_ATOM}, // mjpeg2000
|
||||||
|
{"colr", {"jp2h"}, CHILD_ATOM, OPTIONAL_ONE, VERSIONED_ATOM}, // mjpeg2000
|
||||||
|
{"fiel", {"mjp2"}, CHILD_ATOM, OPTIONAL_ONE, SIMPLE_ATOM}, // mjpeg2000
|
||||||
|
{"jp2p", {"mjp2"}, CHILD_ATOM, OPTIONAL_ONE, VERSIONED_ATOM}, // mjpeg2000
|
||||||
|
{"jsub", {"mjp2"}, CHILD_ATOM, OPTIONAL_ONE, SIMPLE_ATOM}, // mjpeg2000
|
||||||
|
{"orfo", {"mjp2"}, CHILD_ATOM, OPTIONAL_ONE, SIMPLE_ATOM}, // mjpeg2000
|
||||||
|
|
||||||
|
{"cprt",
|
||||||
|
{"udta"},
|
||||||
|
CHILD_ATOM,
|
||||||
|
OPTIONAL_MANY,
|
||||||
|
PACKED_LANG_ATOM}, // the only ISO defined metadata tag; also a 3gp asset
|
||||||
|
{"titl",
|
||||||
|
{"udta"},
|
||||||
|
CHILD_ATOM,
|
||||||
|
OPTIONAL_MANY,
|
||||||
|
PACKED_LANG_ATOM}, // 3gp assets
|
||||||
|
{"auth", {"udta"}, CHILD_ATOM, OPTIONAL_MANY, PACKED_LANG_ATOM},
|
||||||
|
{"perf", {"udta"}, CHILD_ATOM, OPTIONAL_MANY, PACKED_LANG_ATOM},
|
||||||
|
{"gnre", {"udta"}, CHILD_ATOM, OPTIONAL_MANY, PACKED_LANG_ATOM},
|
||||||
|
{"dscp", {"udta"}, CHILD_ATOM, OPTIONAL_MANY, PACKED_LANG_ATOM},
|
||||||
|
{"albm", {"udta"}, CHILD_ATOM, OPTIONAL_MANY, PACKED_LANG_ATOM},
|
||||||
|
{"yrrc", {"udta"}, CHILD_ATOM, OPTIONAL_MANY, VERSIONED_ATOM},
|
||||||
|
{"rtng", {"udta"}, CHILD_ATOM, OPTIONAL_MANY, PACKED_LANG_ATOM},
|
||||||
|
{"clsf", {"udta"}, CHILD_ATOM, OPTIONAL_MANY, PACKED_LANG_ATOM},
|
||||||
|
{"kywd", {"udta"}, CHILD_ATOM, OPTIONAL_MANY, PACKED_LANG_ATOM},
|
||||||
|
{"loci", {"udta"}, CHILD_ATOM, OPTIONAL_MANY, PACKED_LANG_ATOM},
|
||||||
|
|
||||||
|
{"ID32",
|
||||||
|
{"meta"},
|
||||||
|
CHILD_ATOM,
|
||||||
|
OPTIONAL_MANY,
|
||||||
|
PACKED_LANG_ATOM}, // id3v2 tag
|
||||||
|
{"tsel",
|
||||||
|
{"udta"},
|
||||||
|
CHILD_ATOM,
|
||||||
|
OPTIONAL_MANY,
|
||||||
|
SIMPLE_ATOM}, // but only at track level in a 3gp file
|
||||||
|
|
||||||
|
//{"chpl", {"udta"}, CHILD_ATOM,
|
||||||
|
// OPTIONAL_ONCE,
|
||||||
|
// VERSIONED_ATOM }, //Nero - seems to be versioned
|
||||||
|
//{"ndrm", {"udta"}, CHILD_ATOM,
|
||||||
|
// OPTIONAL_ONCE,
|
||||||
|
// VERSIONED_ATOM }, //Nero - seems to be versioned
|
||||||
|
//{"tags", {"udta"}, CHILD_ATOM,
|
||||||
|
// OPTIONAL_ONCE,
|
||||||
|
// SIMPLE_ATOM }, //Another Nero-Creationª
|
||||||
|
// ...so if they claim that "tags doesn't have any children",
|
||||||
|
// why does nerotags.exe say "tshd atom"? If 'tags' doesn't
|
||||||
|
// have any children, then tshd can't be an atom....
|
||||||
|
// Clearly, they are EternallyRightª and everyone else is
|
||||||
|
// always wrong.
|
||||||
|
|
||||||
|
// Pish! Seems that Nero is simply unable to register any atoms.
|
||||||
|
|
||||||
|
{"ilst",
|
||||||
|
{"meta"},
|
||||||
|
PARENT_ATOM,
|
||||||
|
OPTIONAL_ONCE,
|
||||||
|
SIMPLE_ATOM}, // iTunes metadata container
|
||||||
|
{"----",
|
||||||
|
{"ilst"},
|
||||||
|
PARENT_ATOM,
|
||||||
|
OPTIONAL_MANY,
|
||||||
|
SIMPLE_ATOM}, // reverse dns metadata
|
||||||
|
{"mean", {"----"}, CHILD_ATOM, REQUIRED_ONE, VERSIONED_ATOM},
|
||||||
|
{"name", {"----"}, CHILD_ATOM, REQUIRED_ONE, VERSIONED_ATOM},
|
||||||
|
|
||||||
|
{".><.",
|
||||||
|
{"dref"},
|
||||||
|
CHILD_ATOM,
|
||||||
|
OPTIONAL_MANY,
|
||||||
|
VERSIONED_ATOM}, // support any future named child to dref; keep 4th from
|
||||||
|
// end; manual return
|
||||||
|
|
||||||
|
{"esds",
|
||||||
|
{"SAMPLE_DESC"},
|
||||||
|
CHILD_ATOM,
|
||||||
|
REQUIRED_ONE,
|
||||||
|
SIMPLE_ATOM}, // multiple parents; keep 3rd from end; manual return
|
||||||
|
|
||||||
|
{"(..)",
|
||||||
|
{"ilst"},
|
||||||
|
PARENT_ATOM,
|
||||||
|
OPTIONAL_ONE,
|
||||||
|
SIMPLE_ATOM}, // multiple parents; keep 2nd from end; manual return
|
||||||
|
{"data",
|
||||||
|
{"ITUNES_METADATA"},
|
||||||
|
CHILD_ATOM,
|
||||||
|
PARENT_SPECIFIC,
|
||||||
|
VERSIONED_ATOM} // multiple parents
|
||||||
|
|
||||||
|
};
|
||||||
458
src/AtomicParsley.h
Normal file
458
src/AtomicParsley.h
Normal file
@ -0,0 +1,458 @@
|
|||||||
|
#ifndef ATOMIC_PARSLEY_H
|
||||||
|
#define ATOMIC_PARSLEY_H
|
||||||
|
|
||||||
|
//==================================================================//
|
||||||
|
/*
|
||||||
|
AtomicParsley - AtomicParsley.h
|
||||||
|
|
||||||
|
AtomicParsley is GPL software; you can freely distribute,
|
||||||
|
redistribute, modify & use under the terms of the GNU General
|
||||||
|
Public License; either version 2 or its successor.
|
||||||
|
|
||||||
|
AtomicParsley is distributed under the GPL "AS IS", without
|
||||||
|
any warranty; without the implied warranty of merchantability
|
||||||
|
or fitness for either an expressed or implied particular purpose.
|
||||||
|
|
||||||
|
Please see the included GNU General Public License (GPL) for
|
||||||
|
your rights and further details; see the file COPYING. If you
|
||||||
|
cannot, write to the Free Software Foundation, 59 Temple Place
|
||||||
|
Suite 330, Boston, MA 02111-1307, USA. Or www.fsf.org
|
||||||
|
|
||||||
|
Copyright ©2005-2007 puck_lock
|
||||||
|
with contributions from others; see the CREDITS file
|
||||||
|
*/
|
||||||
|
//==================================================================//
|
||||||
|
|
||||||
|
#if defined HAVE_WINDOWS_H && !defined _WIN32
|
||||||
|
#define _WIN32
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#ifndef _UNICODE
|
||||||
|
#define _UNICODE
|
||||||
|
#endif
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#define strncasecmp _strnicmp
|
||||||
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
|
#pragma warning(disable : 4244) // int64_t assignments to int32_t etc.
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define __STDC_LIMIT_MACROS
|
||||||
|
#define __STDC_FORMAT_MACROS
|
||||||
|
#define __STDC_CONSTANT_MACROS
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#ifdef __GLIBC__
|
||||||
|
#define HAVE_LROUNDF 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#ifndef _WIN32
|
||||||
|
#include <sys/time.h>
|
||||||
|
#endif
|
||||||
|
#include <errno.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#ifndef _WIN32
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#endif
|
||||||
|
#ifdef __linux__
|
||||||
|
#include <linux/cdrom.h>
|
||||||
|
#include <sys/mount.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#endif
|
||||||
|
#ifdef _WIN32
|
||||||
|
// Don't break std::min!
|
||||||
|
#define NOMINMAX
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
#include <wchar.h>
|
||||||
|
#ifndef _WIN32
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <io.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
|
#ifndef _WIN32
|
||||||
|
#include <getopt.h>
|
||||||
|
#else
|
||||||
|
#include "extras/getopt.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PRIu64
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define PRIu64 "I64u"
|
||||||
|
#else
|
||||||
|
#define PRIu64 "llu"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#ifndef PRIu32
|
||||||
|
#define PRIu32 "u"
|
||||||
|
#endif
|
||||||
|
#ifndef PRIx32
|
||||||
|
#define PRIx32 "x"
|
||||||
|
#endif
|
||||||
|
#ifndef SCNu64
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define SCNu64 "I64u"
|
||||||
|
#else
|
||||||
|
#define SCNu64 "llu"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#ifndef SCNu32
|
||||||
|
#define SCNu32 "u"
|
||||||
|
#endif
|
||||||
|
#ifndef SCNu16
|
||||||
|
#define SCNu16 "hu"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MAXPATHLEN
|
||||||
|
#define MAXPATHLEN 255
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
#define MAX_ATOMS 2048
|
||||||
|
#define MAXDATA_PAYLOAD 1256
|
||||||
|
#define DEFAULT_PADDING_LENGTH 2048;
|
||||||
|
#define MINIMUM_REQUIRED_PADDING_LENGTH 0;
|
||||||
|
#define MAXIMUM_REQUIRED_PADDING_LENGTH 5000;
|
||||||
|
|
||||||
|
#include "ap_types.h"
|
||||||
|
|
||||||
|
extern atomDefinition KnownAtoms[];
|
||||||
|
extern bool parsedfile;
|
||||||
|
extern bool file_opened;
|
||||||
|
extern bool modified_atoms;
|
||||||
|
extern bool alter_original;
|
||||||
|
extern bool preserve_timestamps;
|
||||||
|
extern bool deep_atom_scan;
|
||||||
|
extern bool cvs_build;
|
||||||
|
extern bool force_existing_hierarchy;
|
||||||
|
extern bool move_moov_atom;
|
||||||
|
extern bool moov_atom_was_mooved;
|
||||||
|
|
||||||
|
extern int metadata_style;
|
||||||
|
extern uint32_t brand;
|
||||||
|
extern uint64_t mdatData;
|
||||||
|
extern uint64_t file_size;
|
||||||
|
extern uint64_t gapless_void_padding;
|
||||||
|
|
||||||
|
extern EmployedCodecs track_codecs;
|
||||||
|
|
||||||
|
extern AtomicInfo parsedAtoms[];
|
||||||
|
extern short atom_number;
|
||||||
|
extern char *ISObasemediafile;
|
||||||
|
extern FILE *source_file;
|
||||||
|
|
||||||
|
extern padding_preferences pad_prefs;
|
||||||
|
|
||||||
|
extern uint8_t UnicodeOutputStatus;
|
||||||
|
|
||||||
|
extern uint8_t forced_suffix_type;
|
||||||
|
|
||||||
|
extern char *twenty_byte_buffer;
|
||||||
|
extern DynamicUpdateStat dynUpd;
|
||||||
|
|
||||||
|
extern ID3FrameDefinition KnownFrames[];
|
||||||
|
extern ID3v2FieldDefinition FrameTypeConstructionList[];
|
||||||
|
extern ImageFileFormatDefinition ImageList[];
|
||||||
|
extern ID3ImageType ImageTypeList[];
|
||||||
|
|
||||||
|
void ShowVersionInfo();
|
||||||
|
void APar_FreeMemory();
|
||||||
|
|
||||||
|
short APar_FindParentAtom(int order_in_tree, uint8_t this_atom_level);
|
||||||
|
|
||||||
|
AtomicInfo *APar_FindAtomInTrack(uint8_t &total_tracks,
|
||||||
|
uint8_t &track_num,
|
||||||
|
const char *search_atom_str);
|
||||||
|
|
||||||
|
AtomicInfo *APar_FindAtom(const char *atom_name,
|
||||||
|
bool createMissing,
|
||||||
|
uint8_t atom_type,
|
||||||
|
uint16_t atom_lang,
|
||||||
|
bool match_full_uuids = false,
|
||||||
|
const char *reverseDNSdomain = NULL);
|
||||||
|
|
||||||
|
int APar_MatchToKnownAtom(const char *atom_name,
|
||||||
|
const char *atom_container,
|
||||||
|
bool fromFile,
|
||||||
|
const char *find_atom_path);
|
||||||
|
|
||||||
|
void APar_ScanAtoms(const char *path, bool deepscan_REQ = false);
|
||||||
|
void APar_IdentifyBrand(char *file_brand);
|
||||||
|
|
||||||
|
AtomicInfo *APar_CreateSparseAtom(AtomicInfo *surrogate_atom,
|
||||||
|
AtomicInfo *parent_atom,
|
||||||
|
short preceding_atom);
|
||||||
|
|
||||||
|
void APar_Unified_atom_Put(AtomicInfo *target_atom,
|
||||||
|
const char *unicode_data,
|
||||||
|
uint8_t text_tag_style,
|
||||||
|
uint64_t ancillary_data,
|
||||||
|
uint8_t anc_bit_width);
|
||||||
|
|
||||||
|
void APar_atom_Binary_Put(AtomicInfo *target_atom,
|
||||||
|
const char *binary_data,
|
||||||
|
uint32_t bytecount,
|
||||||
|
uint64_t atomic_data_offset);
|
||||||
|
|
||||||
|
/* iTunes-style metadata */
|
||||||
|
void APar_MetaData_atomArtwork_Set(const char *artworkPath,
|
||||||
|
char *env_PicOptions);
|
||||||
|
|
||||||
|
void APar_MetaData_atomGenre_Set(const char *atomPayload);
|
||||||
|
void APar_MetaData_atomLyrics_Set(const char *lyricsPath);
|
||||||
|
void APar_MetaData_atom_QuickInit(short atom_num,
|
||||||
|
const uint32_t atomFlags,
|
||||||
|
uint32_t supplemental_length,
|
||||||
|
uint32_t allotment = MAXDATA_PAYLOAD + 1);
|
||||||
|
|
||||||
|
AtomicInfo *APar_MetaData_atom_Init(const char *atom_path,
|
||||||
|
const char *MD_Payload,
|
||||||
|
const uint32_t atomFlags);
|
||||||
|
|
||||||
|
AtomicInfo *APar_reverseDNS_atom_Init(const char *rDNS_atom_name,
|
||||||
|
const char *rDNS_payload,
|
||||||
|
const uint32_t *atomFlags,
|
||||||
|
const char *rDNS_domain);
|
||||||
|
|
||||||
|
/* uuid user extension metadata; made to look much like iTunes-style metadata
|
||||||
|
* with a 4byte NULL */
|
||||||
|
AtomicInfo *APar_uuid_atom_Init(const char *atom_path,
|
||||||
|
const char *uuidName,
|
||||||
|
const uint32_t dataType,
|
||||||
|
const char *uuidValue,
|
||||||
|
bool shellAtom);
|
||||||
|
|
||||||
|
// test whether the ipod uuid can be added for a video track
|
||||||
|
uint16_t APar_TestVideoDescription(AtomicInfo *video_desc_atom,
|
||||||
|
FILE *ISObmff_file);
|
||||||
|
|
||||||
|
void APar_Generate_iPod_uuid(char *atom_path);
|
||||||
|
|
||||||
|
/* 3GP-style metadata */
|
||||||
|
uint32_t APar_3GP_Keyword_atom_Format(char *keywords_globbed,
|
||||||
|
uint8_t keyword_count,
|
||||||
|
bool set_UTF16_text,
|
||||||
|
char *&formed_keyword_struct);
|
||||||
|
|
||||||
|
AtomicInfo *APar_UserData_atom_Init(const char *userdata_atom_name,
|
||||||
|
const char *atom_payload,
|
||||||
|
uint8_t udta_container,
|
||||||
|
uint8_t track_idx,
|
||||||
|
uint16_t userdata_lang);
|
||||||
|
|
||||||
|
/* ID3v2 (2.4) style metadata, non-external form */
|
||||||
|
AtomicInfo *APar_ID32_atom_Init(const char *frameID_str,
|
||||||
|
char meta_area,
|
||||||
|
const char *lang_str,
|
||||||
|
uint16_t id32_lang);
|
||||||
|
|
||||||
|
void APar_RemoveAtom(const char *atom_path,
|
||||||
|
uint8_t atom_type,
|
||||||
|
uint16_t UD_lang,
|
||||||
|
const char *rDNS_domain = NULL);
|
||||||
|
|
||||||
|
void APar_freefree(int purge_level);
|
||||||
|
|
||||||
|
void APar_MetadataFileDump(const char *ISObasemediafile);
|
||||||
|
|
||||||
|
void APar_Optimize(bool mdat_test_only);
|
||||||
|
void APar_DetermineAtomLengths();
|
||||||
|
void APar_WriteFile(const char *ISObasemediafile,
|
||||||
|
const char *outfile,
|
||||||
|
bool rewrite_original);
|
||||||
|
|
||||||
|
void APar_zlib_inflate(char *in_buffer,
|
||||||
|
uint32_t in_buf_len,
|
||||||
|
char *out_buffer,
|
||||||
|
uint32_t out_buf_len);
|
||||||
|
|
||||||
|
uint32_t APar_zlib_deflate(char *in_buffer,
|
||||||
|
uint32_t in_buf_len,
|
||||||
|
char *out_buffer,
|
||||||
|
uint32_t out_buf_len);
|
||||||
|
|
||||||
|
void APar_print_uuid(ap_uuid_t *uuid, bool new_line = true);
|
||||||
|
void APar_sprintf_uuid(ap_uuid_t *uuid, char *destination);
|
||||||
|
uint8_t APar_uuid_scanf(char *in_formed_uuid, const char *raw_uuid);
|
||||||
|
|
||||||
|
void APar_endian_uuid_bin_str_conversion(char *raw_uuid);
|
||||||
|
|
||||||
|
uint8_t APar_extract_uuid_version(ap_uuid_t *uuid, char *binary_uuid_str);
|
||||||
|
void APar_generate_uuid_from_atomname(char *atom_name, char *uuid_binary_str);
|
||||||
|
void APar_generate_random_uuid(char *uuid_binary_str);
|
||||||
|
|
||||||
|
/* Initialize structure containing state of computation. */
|
||||||
|
extern void sha1_init_ctx(struct sha1_ctx *ctx);
|
||||||
|
|
||||||
|
/* Starting with the result of former calls of this function (or the
|
||||||
|
initialization function update the context for the next LEN bytes
|
||||||
|
starting at BUFFER.
|
||||||
|
It is necessary that LEN is a multiple of 64!!! */
|
||||||
|
extern void
|
||||||
|
sha1_process_block(const void *buffer, size_t len, struct sha1_ctx *ctx);
|
||||||
|
|
||||||
|
/* Starting with the result of former calls of this function (or the
|
||||||
|
initialization function update the context for the next LEN bytes
|
||||||
|
starting at BUFFER.
|
||||||
|
It is NOT required that LEN is a multiple of 64. */
|
||||||
|
extern void
|
||||||
|
sha1_process_bytes(const void *buffer, size_t len, struct sha1_ctx *ctx);
|
||||||
|
|
||||||
|
/* Process the remaining bytes in the buffer and put result from CTX
|
||||||
|
in first 20 bytes following RESBUF. The result is always in little
|
||||||
|
endian byte order, so that a byte-wise output yields to the wanted
|
||||||
|
ASCII representation of the message digest.
|
||||||
|
|
||||||
|
IMPORTANT: On some systems it is required that RESBUF be correctly
|
||||||
|
aligned for a 32 bits value. */
|
||||||
|
extern void *sha1_finish_ctx(struct sha1_ctx *ctx, void *resbuf);
|
||||||
|
|
||||||
|
/* Put result from CTX in first 20 bytes following RESBUF. The result is
|
||||||
|
always in little endian byte order, so that a byte-wise output yields
|
||||||
|
to the wanted ASCII representation of the message digest.
|
||||||
|
|
||||||
|
IMPORTANT: On some systems it is required that RESBUF is correctly
|
||||||
|
aligned for a 32 bits value. */
|
||||||
|
extern void *sha1_read_ctx(const struct sha1_ctx *ctx, void *resbuf);
|
||||||
|
|
||||||
|
/* Compute SHA1 message digest for bytes read from STREAM. The
|
||||||
|
resulting message digest number will be written into the 20 bytes
|
||||||
|
beginning at RESBLOCK. */
|
||||||
|
extern int sha1_stream(FILE *stream, void *resblock);
|
||||||
|
|
||||||
|
/* Compute SHA1 message digest for LEN bytes beginning at BUFFER. The
|
||||||
|
result is always in little endian byte order, so that a byte-wise
|
||||||
|
output yields to the wanted ASCII representation of the message
|
||||||
|
digest. */
|
||||||
|
extern void *sha1_buffer(const char *buffer, size_t len, void *resblock);
|
||||||
|
|
||||||
|
int isolat1ToUTF8(unsigned char *out,
|
||||||
|
int outlen,
|
||||||
|
const unsigned char *in,
|
||||||
|
int inlen);
|
||||||
|
|
||||||
|
int UTF8Toisolat1(unsigned char *out,
|
||||||
|
int outlen,
|
||||||
|
const unsigned char *in,
|
||||||
|
int inlen);
|
||||||
|
|
||||||
|
int UTF16BEToUTF8(unsigned char *out,
|
||||||
|
int outlen,
|
||||||
|
const unsigned char *inb,
|
||||||
|
int inlenb);
|
||||||
|
|
||||||
|
int UTF8ToUTF16BE(unsigned char *outb,
|
||||||
|
int outlen,
|
||||||
|
const unsigned char *in,
|
||||||
|
int inlen);
|
||||||
|
|
||||||
|
int UTF16LEToUTF8(unsigned char *out,
|
||||||
|
int outlen,
|
||||||
|
const unsigned char *inb,
|
||||||
|
int inlenb);
|
||||||
|
|
||||||
|
int UTF8ToUTF16LE(unsigned char *outb,
|
||||||
|
int outlen,
|
||||||
|
const unsigned char *in,
|
||||||
|
int inlen);
|
||||||
|
|
||||||
|
int isUTF8(const char *in_string);
|
||||||
|
|
||||||
|
unsigned int utf8_length(const char *in_string, unsigned int char_limit);
|
||||||
|
|
||||||
|
int strip_bogusUTF16toRawUTF8(unsigned char *out,
|
||||||
|
int inlen,
|
||||||
|
wchar_t *in,
|
||||||
|
int outlen);
|
||||||
|
|
||||||
|
int test_conforming_alpha_string(char *in_string);
|
||||||
|
bool test_limited_ascii(char *in_string, unsigned int str_len);
|
||||||
|
|
||||||
|
void APar_ExtractDetails(FILE *isofile, uint8_t optional_output);
|
||||||
|
void APar_ExtractBrands(char *filepath);
|
||||||
|
|
||||||
|
void printBOM();
|
||||||
|
void APar_fprintf_UTF8_data(const char *utf8_encoded_data);
|
||||||
|
void APar_unicode_win32Printout(wchar_t *unicode_out, char *utf8_out);
|
||||||
|
|
||||||
|
void APar_Extract_uuid_binary_file(AtomicInfo *uuid_atom,
|
||||||
|
const char *originating_file,
|
||||||
|
char *output_path);
|
||||||
|
|
||||||
|
void APar_Print_APuuid_atoms(const char *path,
|
||||||
|
char *output_path,
|
||||||
|
uint8_t target_information);
|
||||||
|
|
||||||
|
void APar_Print_iTunesData(const char *path,
|
||||||
|
char *output_path,
|
||||||
|
uint8_t supplemental_info,
|
||||||
|
uint8_t target_information,
|
||||||
|
AtomicInfo *ilstAtom = NULL);
|
||||||
|
|
||||||
|
void APar_PrintUserDataAssests(bool quantum_listing = false);
|
||||||
|
|
||||||
|
void APar_Extract_ID3v2_file(AtomicInfo *id32_atom,
|
||||||
|
const char *frame_str,
|
||||||
|
const char *originfile,
|
||||||
|
const char *destination_folder,
|
||||||
|
AdjunctArgs *id3args);
|
||||||
|
|
||||||
|
void APar_Print_ID3v2_tags(AtomicInfo *id32_atom);
|
||||||
|
|
||||||
|
void APar_Print_ISO_UserData_per_track();
|
||||||
|
void APar_Mark_UserData_area(uint8_t track_num,
|
||||||
|
short userdata_atom,
|
||||||
|
bool quantum_listing);
|
||||||
|
|
||||||
|
// trees
|
||||||
|
void APar_PrintAtomicTree();
|
||||||
|
void APar_SimpleAtomPrintout();
|
||||||
|
|
||||||
|
uint32_t APar_4CC_CreatorCode(const char *filepath, uint32_t new_type_code);
|
||||||
|
void APar_SupplySelectiveTypeCreatorCodes(const char *inputPath,
|
||||||
|
const char *outputPath,
|
||||||
|
uint8_t forced_type_code);
|
||||||
|
|
||||||
|
bool ResizeGivenImage(const char *filePath,
|
||||||
|
PicPrefs myPicPrefs,
|
||||||
|
char *resized_path);
|
||||||
|
|
||||||
|
char *GenreIntToString(int genre);
|
||||||
|
uint8_t StringGenreToInt(const char *genre_string);
|
||||||
|
void ListGenresValues();
|
||||||
|
|
||||||
|
stiks *MatchStikString(const char *stik_string);
|
||||||
|
stiks *MatchStikNumber(uint8_t in_stik_num);
|
||||||
|
void ListStikValues();
|
||||||
|
|
||||||
|
sfIDs *MatchStoreFrontNumber(uint32_t storefrontnum);
|
||||||
|
|
||||||
|
bool MatchLanguageCode(const char *in_code);
|
||||||
|
void ListLanguageCodes();
|
||||||
|
|
||||||
|
void ListMediaRatings();
|
||||||
|
void ListTVGenreIDValues();
|
||||||
|
void ListMovieGenreIDValues();
|
||||||
|
const char *Expand_cli_mediastring(const char *cli_rating);
|
||||||
|
|
||||||
|
char *ID3GenreIntToString(int genre);
|
||||||
|
uint8_t ID3StringGenreToInt(const char *genre_string);
|
||||||
|
|
||||||
|
#endif /* ATOMIC_PARSLEY_H */
|
||||||
|
|
||||||
|
// vim:ts=2:sw=2:et:
|
||||||
589
src/CDtoc.cpp
Normal file
589
src/CDtoc.cpp
Normal file
@ -0,0 +1,589 @@
|
|||||||
|
//==================================================================//
|
||||||
|
/*
|
||||||
|
AtomicParsley - CDtoc.cpp
|
||||||
|
|
||||||
|
AtomicParsley is GPL software; you can freely distribute,
|
||||||
|
redistribute, modify & use under the terms of the GNU General
|
||||||
|
Public License; either version 2 or its successor.
|
||||||
|
|
||||||
|
AtomicParsley is distributed under the GPL "AS IS", without
|
||||||
|
any warranty; without the implied warranty of merchantability
|
||||||
|
or fitness for either an expressed or implied particular purpose.
|
||||||
|
|
||||||
|
Please see the included GNU General Public License (GPL) for
|
||||||
|
your rights and further details; see the file COPYING. If you
|
||||||
|
cannot, write to the Free Software Foundation, 59 Temple Place
|
||||||
|
Suite 330, Boston, MA 02111-1307, USA. Or www.fsf.org
|
||||||
|
|
||||||
|
Copyright (C)2006-2007 puck_lock
|
||||||
|
with contributions from others; see the CREDITS file
|
||||||
|
*/
|
||||||
|
//==================================================================//
|
||||||
|
|
||||||
|
// gathering of a CD's Table of Contents is going to be hardware specific
|
||||||
|
// currently only Mac OS X is implemented - using IOKit framework.
|
||||||
|
// another avenue (applicable to other *nix platforms): ioctl
|
||||||
|
|
||||||
|
#include "AtomicParsley.h"
|
||||||
|
#include "CDtoc.h"
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
|
#include <IOKit/IOBSD.h>
|
||||||
|
#include <IOKit/IOKitLib.h>
|
||||||
|
#include <IOKit/storage/IOCDMedia.h>
|
||||||
|
#include <IOKit/storage/IOCDTypes.h>
|
||||||
|
|
||||||
|
const uint8_t MACOSX_LEADOUT_TRACK = 0xA2;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const uint8_t CDOBJECT_DATACD = 0;
|
||||||
|
const uint8_t CDOBJECT_AUDIOCD = 1;
|
||||||
|
|
||||||
|
struct CD_TDesc {
|
||||||
|
uint8_t session;
|
||||||
|
uint8_t controladdress;
|
||||||
|
uint8_t unused1; // refered to as 'tno' which equates to "track number" -
|
||||||
|
// but... its 'point' that actually is the tracknumber in
|
||||||
|
// mode1 TOC. set to zero for all mode1 TOC
|
||||||
|
uint8_t tracknumber; // refered to as 'point', but this is actually the
|
||||||
|
// tracknumber in mode1 audio toc entries.
|
||||||
|
uint8_t rel_minutes;
|
||||||
|
uint8_t rel_seconds;
|
||||||
|
uint8_t rel_frames;
|
||||||
|
uint8_t zero_space;
|
||||||
|
uint8_t abs_minutes;
|
||||||
|
uint8_t abs_seconds;
|
||||||
|
uint8_t abs_frames;
|
||||||
|
void *next_description;
|
||||||
|
};
|
||||||
|
typedef struct CD_TDesc CD_TDesc;
|
||||||
|
|
||||||
|
struct CD_TOC_ {
|
||||||
|
uint16_t toc_length;
|
||||||
|
uint8_t first_session;
|
||||||
|
uint8_t last_session;
|
||||||
|
CD_TDesc *track_description; // entry to the first track in the linked list
|
||||||
|
};
|
||||||
|
typedef struct CD_TOC_ CD_TOC_;
|
||||||
|
|
||||||
|
CD_TOC_ *cdTOC = NULL;
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
uint8_t LEADOUT_TRACK_NUMBER = MACOSX_LEADOUT_TRACK;
|
||||||
|
#elif defined(__linux__)
|
||||||
|
uint8_t LEADOUT_TRACK_NUMBER = CDROM_LEADOUT;
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
uint8_t LEADOUT_TRACK_NUMBER =
|
||||||
|
0xAA; // NOTE: for WinXP IOCTL_CDROM_READ_TOC_EX code, its 0xA2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
MCDI describes the CD TOC - actually talks about "a binary dump of the TOC".
|
||||||
|
So, a TOC is made up of: a 4 byte TOC header (2 bytes length of the entire TOC,
|
||||||
|
1 byte start session, 1 byte end session) an array of track entries, and
|
||||||
|
depending on the mode, of varying lengths. For audio CDs, TOC track entries are
|
||||||
|
mode1 (or for CD-R/RW mode5, but lets stick to mode1) a mode1 track entry is 11
|
||||||
|
bytes: 1byte session, 1 byte (packed control/address), 1byte NULL (unused TNO),
|
||||||
|
1 byte for tracknumber (expressed as the word POINT in mmc nomenclature),
|
||||||
|
3bytes relative start frametime, 1 byte NULL, 3 bytes duration timeframe
|
||||||
|
|
||||||
|
while "binary dump of the TOC" is there, its also modified so that the
|
||||||
|
timeframe listing in mm:ss::frames (3bytes) is converted to a 4byte LBA
|
||||||
|
timecode. Combining the first 4 bytes of the "binary dump of the TOC" with the
|
||||||
|
modifications of the 3byte(frame)->4byte(block), we arrive at MCDI as:
|
||||||
|
|
||||||
|
struct mcdi_track_entry {
|
||||||
|
uint8_t cd_toc_session;
|
||||||
|
uint8_t cd_toc_controladdress; //bitpacked uint4_t of control & address
|
||||||
|
uint8_t cd_toc_TNO = 0; //hardcoded to 0 for mode1 audio tracks in the TOC
|
||||||
|
uint8_t cd_toc_tracknumber; //this is the 1-99 tracknumber (listed in mmc-2
|
||||||
|
as POINT) uint32_t cd_frame_address; //converted from the 3byte mm:ss:frame
|
||||||
|
absolute duration
|
||||||
|
};
|
||||||
|
struct toc_header {
|
||||||
|
uint16_t toc_length;
|
||||||
|
uin8_t first_track;
|
||||||
|
uint8_t last_track;
|
||||||
|
};
|
||||||
|
struct mcdi_frame {
|
||||||
|
struct toc_header;
|
||||||
|
struct mcdi_track_entry[total_audio_tracks];
|
||||||
|
struct mcdi_track_entry lead_out;
|
||||||
|
};
|
||||||
|
|
||||||
|
The problem with including the TOC header is that it can't be used directly
|
||||||
|
because on the CD toc entries are 3byte msf address, but here they are 4byte
|
||||||
|
LBA. In any event this header should not have ever been included because the
|
||||||
|
length can be deduced from the frame length & tracks by dividing by 8. So, the
|
||||||
|
header length that MCDI refers to: is it for MSF or LBA addressing? Well, since
|
||||||
|
the rest of MCDI is LBA-based, lets say LBA - which means it needs to be
|
||||||
|
calculated. As it just so happens, then its the length of the frame. All that
|
||||||
|
needs to be added are the first & last tracks.
|
||||||
|
|
||||||
|
Unfortunately, this frame can't be used as a CD Identifier *AS IS* across
|
||||||
|
platforms. Because the leadout track is platform specific (a Linux leadout is
|
||||||
|
0xAA, MacOSX leadout is 0xA2), consideration of the leadout track would have to
|
||||||
|
be given by anything else using this frame.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// Generating MCDI data from a CD TOC //
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
uint8_t DataControlField(uint8_t controlfield) {
|
||||||
|
#if defined(__ppc__) || defined(__ppc64__)
|
||||||
|
if (controlfield & 0x04) { // data uninterrupted or increment OR reserved;
|
||||||
|
// this field is already bitpacked as controlfield
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (controlfield &
|
||||||
|
0x40) { // data uninterrupted or increment OR reserved; bitpacked already
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t DetermineCDType(CD_TOC_ *cdTOCdata) {
|
||||||
|
CD_TDesc *track_TOC_desc = cdTOCdata->track_description;
|
||||||
|
while (track_TOC_desc != NULL) {
|
||||||
|
if (track_TOC_desc->tracknumber >= 1 && track_TOC_desc->tracknumber <= 99 &&
|
||||||
|
!DataControlField(track_TOC_desc->controladdress)) {
|
||||||
|
return CDOBJECT_AUDIOCD;
|
||||||
|
}
|
||||||
|
track_TOC_desc = (CD_TDesc *)track_TOC_desc->next_description;
|
||||||
|
}
|
||||||
|
return CDOBJECT_DATACD;
|
||||||
|
}
|
||||||
|
|
||||||
|
CD_TDesc *LeadOutTrack(CD_TOC_ *cdTOCdata) {
|
||||||
|
CD_TDesc *track_TOC_desc = cdTOCdata->track_description;
|
||||||
|
while (track_TOC_desc != NULL) {
|
||||||
|
if (track_TOC_desc->tracknumber == LEADOUT_TRACK_NUMBER) {
|
||||||
|
return track_TOC_desc;
|
||||||
|
}
|
||||||
|
track_TOC_desc = (CD_TDesc *)track_TOC_desc->next_description;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t FillSingleMCDIentry(CD_TDesc *atrack, char *mcdi_data_entry) {
|
||||||
|
mcdi_data_entry[0] = atrack->session;
|
||||||
|
mcdi_data_entry[1] = atrack->controladdress;
|
||||||
|
mcdi_data_entry[2] = 0;
|
||||||
|
mcdi_data_entry[3] = atrack->tracknumber;
|
||||||
|
// LBA=(M*60+S)*75+F - 150 (table 374)
|
||||||
|
uint32_t frameduration =
|
||||||
|
((((atrack->abs_minutes * 60) + atrack->abs_seconds) * 75) +
|
||||||
|
atrack->abs_frames) -
|
||||||
|
150;
|
||||||
|
UInt32_TO_String4(frameduration, mcdi_data_entry + 4);
|
||||||
|
return 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t FormMCDIdata(char *mcdi_data) {
|
||||||
|
uint16_t mcdi_len = 0;
|
||||||
|
uint8_t first_track = 0;
|
||||||
|
uint8_t last_track = 0;
|
||||||
|
|
||||||
|
CD_TDesc *track_TOC_desc = cdTOC->track_description;
|
||||||
|
|
||||||
|
if (cdTOC->track_description != NULL) {
|
||||||
|
mcdi_len += 4;
|
||||||
|
|
||||||
|
while (track_TOC_desc != NULL) {
|
||||||
|
if (track_TOC_desc->tracknumber >= 1 &&
|
||||||
|
track_TOC_desc->tracknumber <= 99 &&
|
||||||
|
!DataControlField(track_TOC_desc->controladdress)) {
|
||||||
|
mcdi_len += FillSingleMCDIentry(track_TOC_desc, mcdi_data + mcdi_len);
|
||||||
|
if (first_track == 0) {
|
||||||
|
first_track = track_TOC_desc->tracknumber;
|
||||||
|
}
|
||||||
|
last_track = track_TOC_desc->tracknumber;
|
||||||
|
}
|
||||||
|
track_TOC_desc = (CD_TDesc *)track_TOC_desc->next_description;
|
||||||
|
}
|
||||||
|
if (mcdi_len > 0) {
|
||||||
|
CD_TDesc *leadout = LeadOutTrack(cdTOC);
|
||||||
|
if (leadout != NULL) {
|
||||||
|
mcdi_len += FillSingleMCDIentry(leadout, mcdi_data + mcdi_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// backtrack & fill in the header
|
||||||
|
UInt16_TO_String2(mcdi_len, mcdi_data);
|
||||||
|
mcdi_data[2] = first_track;
|
||||||
|
mcdi_data[3] = last_track;
|
||||||
|
}
|
||||||
|
return mcdi_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Platform Specifics //
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#if defined(__linux__)
|
||||||
|
void Linux_ReadCDTOC(int cd_fd) {
|
||||||
|
cdrom_tochdr toc_header;
|
||||||
|
cdrom_tocentry toc_entry;
|
||||||
|
CD_TDesc *a_TOC_desc = NULL;
|
||||||
|
CD_TDesc *prev_desc = NULL;
|
||||||
|
|
||||||
|
if (ioctl(cd_fd, CDROMREADTOCHDR, &toc_header) == -1) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"AtomicParsley error: there was an error reading the CD "
|
||||||
|
"Table of Contents header.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cdTOC = (CD_TOC_ *)calloc(1, sizeof(CD_TOC_));
|
||||||
|
cdTOC->track_description = NULL;
|
||||||
|
|
||||||
|
for (uint8_t i = toc_header.cdth_trk0; i <= toc_header.cdth_trk1 + 1; i++) {
|
||||||
|
memset(&toc_entry, 0, sizeof(toc_entry));
|
||||||
|
if (i == toc_header.cdth_trk1 + 1) {
|
||||||
|
toc_entry.cdte_track = CDROM_LEADOUT;
|
||||||
|
} else {
|
||||||
|
toc_entry.cdte_track = i;
|
||||||
|
}
|
||||||
|
toc_entry.cdte_format =
|
||||||
|
CDROM_MSF; // although it could just be easier to use CDROM_LBA
|
||||||
|
|
||||||
|
if (ioctl(cd_fd, CDROMREADTOCENTRY, &toc_entry) == -1) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"AtomicParsley error: there was an error reading a "
|
||||||
|
"CD Table of Contents entry (linux cdrom).\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cdTOC->track_description == NULL) {
|
||||||
|
cdTOC->track_description = (CD_TDesc *)calloc(1, (sizeof(CD_TDesc)));
|
||||||
|
a_TOC_desc = cdTOC->track_description;
|
||||||
|
prev_desc = a_TOC_desc;
|
||||||
|
} else {
|
||||||
|
prev_desc->next_description = (CD_TDesc *)calloc(1, (sizeof(CD_TDesc)));
|
||||||
|
a_TOC_desc = (CD_TDesc *)prev_desc->next_description;
|
||||||
|
prev_desc = a_TOC_desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
a_TOC_desc->session = 1; // and for vanilla audio CDs it is session 1, but
|
||||||
|
// for multi-session...
|
||||||
|
#if defined(__ppc__) || defined(__ppc64__)
|
||||||
|
a_TOC_desc->controladdress =
|
||||||
|
(toc_entry.cdte_ctrl << 4) | toc_entry.cdte_adr;
|
||||||
|
#else
|
||||||
|
a_TOC_desc->controladdress =
|
||||||
|
(toc_entry.cdte_adr << 4) | toc_entry.cdte_ctrl;
|
||||||
|
#endif
|
||||||
|
a_TOC_desc->unused1 = 0;
|
||||||
|
a_TOC_desc->tracknumber = toc_entry.cdte_track;
|
||||||
|
a_TOC_desc->rel_minutes =
|
||||||
|
0; // is there anyway to even find this out on
|
||||||
|
// linux without playing the track? //cdmsf_min0
|
||||||
|
a_TOC_desc->rel_seconds = 0;
|
||||||
|
a_TOC_desc->rel_frames = 0;
|
||||||
|
a_TOC_desc->zero_space = 0;
|
||||||
|
a_TOC_desc->abs_minutes = toc_entry.cdte_addr.msf.minute;
|
||||||
|
a_TOC_desc->abs_seconds = toc_entry.cdte_addr.msf.second;
|
||||||
|
a_TOC_desc->abs_frames = toc_entry.cdte_addr.msf.frame;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t Linux_ioctlProbeTargetDrive(const char *id3args_drive,
|
||||||
|
char *mcdi_data) {
|
||||||
|
uint16_t mcdi_data_len = 0;
|
||||||
|
int cd_fd = 0;
|
||||||
|
|
||||||
|
cd_fd = open(id3args_drive, O_RDONLY | O_NONBLOCK);
|
||||||
|
|
||||||
|
if (cd_fd != -1) {
|
||||||
|
int cd_mode = ioctl(cd_fd, CDROM_DISC_STATUS);
|
||||||
|
if (cd_mode != CDS_AUDIO || cd_mode != CDS_MIXED) {
|
||||||
|
Linux_ReadCDTOC(cd_fd);
|
||||||
|
mcdi_data_len = FormMCDIdata(mcdi_data);
|
||||||
|
} else {
|
||||||
|
// scan for available devices
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// scan for available devices
|
||||||
|
}
|
||||||
|
|
||||||
|
return mcdi_data_len;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
uint16_t Extract_cdTOCrawdata(CFDataRef cdTOCdata, char *cdTOCrawdata) {
|
||||||
|
CFRange cdrange;
|
||||||
|
CFIndex cdTOClen = CFDataGetLength(cdTOCdata);
|
||||||
|
cdTOCrawdata = (char *)calloc(1, sizeof(char) * cdTOClen + 1);
|
||||||
|
cdrange = CFRangeMake(0, cdTOClen + 1);
|
||||||
|
CFDataGetBytes(cdTOCdata, cdrange, (unsigned char *)cdTOCrawdata);
|
||||||
|
|
||||||
|
cdTOC = (CD_TOC_ *)calloc(1, sizeof(CD_TOC_));
|
||||||
|
cdTOC->toc_length = UInt16FromBigEndian(cdTOCrawdata);
|
||||||
|
cdTOC->first_session = cdTOCrawdata[2];
|
||||||
|
cdTOC->first_session = cdTOCrawdata[3];
|
||||||
|
cdTOC->track_description = NULL;
|
||||||
|
|
||||||
|
CD_TDesc *a_TOC_desc = NULL;
|
||||||
|
CD_TDesc *prev_desc = NULL;
|
||||||
|
|
||||||
|
uint16_t toc_offset = 0;
|
||||||
|
for (toc_offset = 4; toc_offset <= cdTOClen; toc_offset += 11) {
|
||||||
|
if (cdTOC->track_description == NULL) {
|
||||||
|
cdTOC->track_description = (CD_TDesc *)calloc(1, (sizeof(CD_TDesc)));
|
||||||
|
a_TOC_desc = cdTOC->track_description;
|
||||||
|
prev_desc = a_TOC_desc;
|
||||||
|
} else {
|
||||||
|
prev_desc->next_description = (CD_TDesc *)calloc(1, (sizeof(CD_TDesc)));
|
||||||
|
a_TOC_desc = (CD_TDesc *)prev_desc->next_description;
|
||||||
|
prev_desc = a_TOC_desc;
|
||||||
|
}
|
||||||
|
a_TOC_desc->session = cdTOCrawdata[toc_offset];
|
||||||
|
a_TOC_desc->controladdress = cdTOCrawdata[toc_offset + 1];
|
||||||
|
a_TOC_desc->unused1 = cdTOCrawdata[toc_offset + 2];
|
||||||
|
a_TOC_desc->tracknumber = cdTOCrawdata[toc_offset + 3];
|
||||||
|
a_TOC_desc->rel_minutes = cdTOCrawdata[toc_offset + 4];
|
||||||
|
a_TOC_desc->rel_seconds = cdTOCrawdata[toc_offset + 5];
|
||||||
|
a_TOC_desc->rel_frames = cdTOCrawdata[toc_offset + 6];
|
||||||
|
a_TOC_desc->zero_space = 0;
|
||||||
|
a_TOC_desc->abs_minutes = cdTOCrawdata[toc_offset + 8];
|
||||||
|
a_TOC_desc->abs_seconds = cdTOCrawdata[toc_offset + 9];
|
||||||
|
a_TOC_desc->abs_frames = cdTOCrawdata[toc_offset + 10];
|
||||||
|
}
|
||||||
|
|
||||||
|
return (uint16_t)cdTOClen;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OSX_ReadCDTOC(io_object_t cdobject) {
|
||||||
|
CFMutableDictionaryRef cd_props = 0;
|
||||||
|
CFDataRef cdTOCdata = NULL;
|
||||||
|
char *cdTOCrawdata = NULL;
|
||||||
|
|
||||||
|
if (IORegistryEntryCreateCFProperties(
|
||||||
|
cdobject, &cd_props, kCFAllocatorDefault, kNilOptions) !=
|
||||||
|
kIOReturnSuccess)
|
||||||
|
return;
|
||||||
|
|
||||||
|
cdTOCdata =
|
||||||
|
(CFDataRef)CFDictionaryGetValue(cd_props, CFSTR(kIOCDMediaTOCKey));
|
||||||
|
if (cdTOCdata != NULL) {
|
||||||
|
Extract_cdTOCrawdata(cdTOCdata, cdTOCrawdata);
|
||||||
|
}
|
||||||
|
CFRelease(cd_props);
|
||||||
|
cd_props = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OSX_ScanForCDDrive() {
|
||||||
|
io_iterator_t drive_iter = MACH_PORT_NULL;
|
||||||
|
io_object_t driveobject = MACH_PORT_NULL;
|
||||||
|
CFTypeRef drive_path = NULL;
|
||||||
|
char drive_path_str[20];
|
||||||
|
if (IOServiceGetMatchingServices(kIOMasterPortDefault,
|
||||||
|
IOServiceMatching(kIOCDMediaClass),
|
||||||
|
&drive_iter) !=
|
||||||
|
kIOReturnSuccess) { // create the iterator
|
||||||
|
fprintf(stdout, "No device capable of reading cd media present\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
driveobject = IOIteratorNext(drive_iter);
|
||||||
|
while (driveobject != MACH_PORT_NULL) {
|
||||||
|
drive_path = IORegistryEntryCreateCFProperty(
|
||||||
|
driveobject, CFSTR(kIOBSDNameKey), kCFAllocatorDefault, 0);
|
||||||
|
if (drive_path != NULL) {
|
||||||
|
CFStringGetCString((CFStringRef)drive_path,
|
||||||
|
(char *)&drive_path_str,
|
||||||
|
20,
|
||||||
|
kCFStringEncodingASCII);
|
||||||
|
fprintf(stdout, "Device '%s' contains cd media\n", drive_path_str);
|
||||||
|
OSX_ReadCDTOC(driveobject);
|
||||||
|
if (cdTOC != NULL) {
|
||||||
|
uint8_t cdType = DetermineCDType(cdTOC);
|
||||||
|
if (cdType == CDOBJECT_AUDIOCD) {
|
||||||
|
fprintf(stdout,
|
||||||
|
"Good news, device '%s' is an Audio CD and can be used for "
|
||||||
|
"'MCDI' setting\n",
|
||||||
|
drive_path_str);
|
||||||
|
} else {
|
||||||
|
fprintf(stdout, "Tragically, it was a data CD.\n");
|
||||||
|
}
|
||||||
|
free(cdTOC); // the other malloced members should be freed also
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IOObjectRelease(driveobject);
|
||||||
|
driveobject = IOIteratorNext(drive_iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (drive_path_str[0] == (uint8_t)0x00) {
|
||||||
|
fprintf(stdout, "No CD media was found in any device\n");
|
||||||
|
}
|
||||||
|
IOObjectRelease(drive_iter);
|
||||||
|
drive_iter = MACH_PORT_NULL;
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t OSX_ProbeTargetDrive(const char *id3args_drive, char *mcdi_data) {
|
||||||
|
uint16_t mcdi_data_len = 0;
|
||||||
|
io_object_t cdobject = MACH_PORT_NULL;
|
||||||
|
|
||||||
|
if (strncmp(id3args_drive, "disk", 4) != 0) {
|
||||||
|
OSX_ScanForCDDrive();
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
cdobject = IOServiceGetMatchingService(
|
||||||
|
kIOMasterPortDefault,
|
||||||
|
IOBSDNameMatching(kIOMasterPortDefault, 0, id3args_drive));
|
||||||
|
|
||||||
|
if (cdobject == MACH_PORT_NULL) {
|
||||||
|
fprintf(stdout,
|
||||||
|
"No device found at %s; searching for possible drives...\n",
|
||||||
|
id3args_drive);
|
||||||
|
OSX_ScanForCDDrive();
|
||||||
|
|
||||||
|
} else if (IOObjectConformsTo(cdobject, kIOCDMediaClass) == false) {
|
||||||
|
fprintf(stdout, "No cd present in drive at %s\n", id3args_drive);
|
||||||
|
IOObjectRelease(cdobject);
|
||||||
|
cdobject = MACH_PORT_NULL;
|
||||||
|
OSX_ScanForCDDrive();
|
||||||
|
} else {
|
||||||
|
// we now have a cd object
|
||||||
|
OSX_ReadCDTOC(cdobject);
|
||||||
|
if (cdTOC != NULL) {
|
||||||
|
uint8_t cdType = DetermineCDType(cdTOC);
|
||||||
|
if (cdType == CDOBJECT_AUDIOCD) {
|
||||||
|
mcdi_data_len = FormMCDIdata(mcdi_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IOObjectRelease(cdobject);
|
||||||
|
cdobject = MACH_PORT_NULL;
|
||||||
|
return mcdi_data_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
void Windows_ioctlReadCDTOC(HANDLE cdrom_device) {
|
||||||
|
DWORD bytes_returned;
|
||||||
|
CDROM_TOC win_cdrom_toc;
|
||||||
|
|
||||||
|
// WARNING: "This IOCTL is obsolete beginning with the Microsoft Windows
|
||||||
|
// Vista. Do not use this IOCTL to develop drivers in Microsoft Windows
|
||||||
|
// Vista."
|
||||||
|
if (DeviceIoControl(cdrom_device,
|
||||||
|
IOCTL_CDROM_READ_TOC,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
&win_cdrom_toc,
|
||||||
|
sizeof(CDROM_TOC),
|
||||||
|
&bytes_returned,
|
||||||
|
NULL) == 0) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"AtomicParsley error: there was an error reading the CD "
|
||||||
|
"Table of Contents header (win32).\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cdTOC = (CD_TOC_ *)calloc(1, sizeof(CD_TOC_));
|
||||||
|
cdTOC->toc_length = ((win_cdrom_toc.Length[0] & 0xFF) << 8) |
|
||||||
|
(win_cdrom_toc.Length[1] & 0xFF);
|
||||||
|
// cdTOC->first_session = 0; //seems windows doesn't store session info with
|
||||||
|
// IOCTL_CDROM_READ_TOC, all tracks from all sessions are available
|
||||||
|
// cdTOC->last_session = 0; //not used anyway; IOCTL_CDROM_READ_TOC_EX could
|
||||||
|
// be used to get session information, but its only available on XP
|
||||||
|
//...............and interestingly enough in XP, IOCTL_CDROM_TOC_EX returns
|
||||||
|
// the leadout track as 0xA2, which makes a Win2k MCDI & a WinXP MCDI
|
||||||
|
// different (by 1 byte)
|
||||||
|
cdTOC->track_description = NULL;
|
||||||
|
|
||||||
|
CD_TDesc *a_TOC_desc = NULL;
|
||||||
|
CD_TDesc *prev_desc = NULL;
|
||||||
|
|
||||||
|
for (uint8_t i = win_cdrom_toc.FirstTrack; i <= win_cdrom_toc.LastTrack + 1;
|
||||||
|
i++) {
|
||||||
|
TRACK_DATA *thisTrackData = &(win_cdrom_toc.TrackData[i - 1]);
|
||||||
|
|
||||||
|
if (cdTOC->track_description == NULL) {
|
||||||
|
cdTOC->track_description = (CD_TDesc *)calloc(1, (sizeof(CD_TDesc)));
|
||||||
|
a_TOC_desc = cdTOC->track_description;
|
||||||
|
prev_desc = a_TOC_desc;
|
||||||
|
} else {
|
||||||
|
prev_desc->next_description = (CD_TDesc *)calloc(1, (sizeof(CD_TDesc)));
|
||||||
|
a_TOC_desc = (CD_TDesc *)prev_desc->next_description;
|
||||||
|
prev_desc = a_TOC_desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
a_TOC_desc->session = 1; // and for vanilla audio CDs it is session 1, but
|
||||||
|
// for multi-session...
|
||||||
|
#if defined(__ppc__) || defined(__ppc64__)
|
||||||
|
a_TOC_desc->controladdress =
|
||||||
|
(thisTrackData->Control << 4) | thisTrackData->Adr;
|
||||||
|
#else
|
||||||
|
a_TOC_desc->controladdress =
|
||||||
|
(thisTrackData->Adr << 4) | thisTrackData->Control;
|
||||||
|
#endif
|
||||||
|
a_TOC_desc->unused1 = 0;
|
||||||
|
a_TOC_desc->tracknumber = thisTrackData->TrackNumber;
|
||||||
|
a_TOC_desc->rel_minutes =
|
||||||
|
0; // didn't look too much into finding this since it is unused
|
||||||
|
a_TOC_desc->rel_seconds = 0;
|
||||||
|
a_TOC_desc->rel_frames = 0;
|
||||||
|
a_TOC_desc->zero_space = 0;
|
||||||
|
a_TOC_desc->abs_minutes = thisTrackData->Address[1];
|
||||||
|
a_TOC_desc->abs_seconds = thisTrackData->Address[2];
|
||||||
|
a_TOC_desc->abs_frames = thisTrackData->Address[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t Windows_ioctlProbeTargetDrive(const char *id3args_drive,
|
||||||
|
char *mcdi_data) {
|
||||||
|
uint16_t mcdi_data_len = 0;
|
||||||
|
char cd_device_path[16];
|
||||||
|
|
||||||
|
memset(cd_device_path, 0, 16);
|
||||||
|
sprintf(cd_device_path, "\\\\.\\%s:", id3args_drive);
|
||||||
|
|
||||||
|
HANDLE cdrom_device = APar_OpenFileWin32(cd_device_path,
|
||||||
|
GENERIC_READ,
|
||||||
|
FILE_SHARE_READ,
|
||||||
|
NULL,
|
||||||
|
OPEN_EXISTING,
|
||||||
|
FILE_ATTRIBUTE_NORMAL,
|
||||||
|
NULL);
|
||||||
|
if (cdrom_device != INVALID_HANDLE_VALUE) {
|
||||||
|
Windows_ioctlReadCDTOC(cdrom_device);
|
||||||
|
if (cdTOC != NULL) {
|
||||||
|
uint8_t cdType = DetermineCDType(cdTOC);
|
||||||
|
if (cdType == CDOBJECT_AUDIOCD) {
|
||||||
|
mcdi_data_len = FormMCDIdata(mcdi_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CloseHandle(cdrom_device);
|
||||||
|
}
|
||||||
|
|
||||||
|
return mcdi_data_len;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
// CD TOC Entry Area //
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
uint16_t GenerateMCDIfromCD(const char *drive, char *dest_buffer) {
|
||||||
|
uint16_t mcdi_bytes = 0;
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
mcdi_bytes = OSX_ProbeTargetDrive(drive, dest_buffer);
|
||||||
|
#elif defined(__linux__)
|
||||||
|
mcdi_bytes = Linux_ioctlProbeTargetDrive(drive, dest_buffer);
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
mcdi_bytes = Windows_ioctlProbeTargetDrive(drive, dest_buffer);
|
||||||
|
#endif
|
||||||
|
return mcdi_bytes;
|
||||||
|
}
|
||||||
80
src/CDtoc.h
Normal file
80
src/CDtoc.h
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
//==================================================================//
|
||||||
|
/*
|
||||||
|
AtomicParsley - CDtoc.h
|
||||||
|
|
||||||
|
AtomicParsley is GPL software; you can freely distribute,
|
||||||
|
redistribute, modify & use under the terms of the GNU General
|
||||||
|
Public License; either version 2 or its successor.
|
||||||
|
|
||||||
|
AtomicParsley is distributed under the GPL "AS IS", without
|
||||||
|
any warranty; without the implied warranty of merchantability
|
||||||
|
or fitness for either an expressed or implied particular purpose.
|
||||||
|
|
||||||
|
Please see the included GNU General Public License (GPL) for
|
||||||
|
your rights and further details; see the file COPYING. If you
|
||||||
|
cannot, write to the Free Software Foundation, 59 Temple Place
|
||||||
|
Suite 330, Boston, MA 02111-1307, USA. Or www.fsf.org
|
||||||
|
|
||||||
|
Copyright ©2006-2007 puck_lock
|
||||||
|
with contributions from others; see the CREDITS file
|
||||||
|
*/
|
||||||
|
//==================================================================//
|
||||||
|
|
||||||
|
#include "ap_types.h"
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
// these #defines & structs are copied from the MS W2k DDK headers so the entire
|
||||||
|
// DDK isn't required to be installed to compile AP_CDTOC for MCDI support
|
||||||
|
#ifndef DEVICE_TYPE
|
||||||
|
#define DEVICE_TYPE ULONG
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define FILE_DEVICE_CD_ROM 0x00000002
|
||||||
|
|
||||||
|
#define IOCTL_CDROM_BASE FILE_DEVICE_CD_ROM
|
||||||
|
|
||||||
|
#define METHOD_BUFFERED 0
|
||||||
|
|
||||||
|
#define FILE_READ_ACCESS (0x0001) // file & pipe
|
||||||
|
|
||||||
|
#define CTL_CODE(DeviceType, Function, Method, Access) \
|
||||||
|
(((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method))
|
||||||
|
|
||||||
|
#define IOCTL_CDROM_READ_TOC \
|
||||||
|
CTL_CODE(IOCTL_CDROM_BASE, 0x0000, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||||
|
|
||||||
|
#define MAXIMUM_NUMBER_TRACKS 100
|
||||||
|
|
||||||
|
//
|
||||||
|
// CD ROM Table OF Contents (TOC)
|
||||||
|
// Format 0 - Get table of contents
|
||||||
|
//
|
||||||
|
|
||||||
|
typedef struct _TRACK_DATA {
|
||||||
|
UCHAR Reserved;
|
||||||
|
UCHAR Control : 4;
|
||||||
|
UCHAR Adr : 4;
|
||||||
|
UCHAR TrackNumber;
|
||||||
|
UCHAR Reserved1;
|
||||||
|
UCHAR Address[4];
|
||||||
|
} TRACK_DATA, *PTRACK_DATA;
|
||||||
|
|
||||||
|
typedef struct _CDROM_TOC {
|
||||||
|
|
||||||
|
//
|
||||||
|
// Header
|
||||||
|
//
|
||||||
|
|
||||||
|
UCHAR Length[2];
|
||||||
|
UCHAR FirstTrack;
|
||||||
|
UCHAR LastTrack;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Track data
|
||||||
|
//
|
||||||
|
|
||||||
|
TRACK_DATA TrackData[MAXIMUM_NUMBER_TRACKS];
|
||||||
|
} CDROM_TOC, *PCDROM_TOC;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint16_t GenerateMCDIfromCD(const char *drive, char *dest_buffer);
|
||||||
384
src/ap_types.h
Normal file
384
src/ap_types.h
Normal file
@ -0,0 +1,384 @@
|
|||||||
|
#ifndef AP_TYPES_H
|
||||||
|
#define AP_TYPES_H
|
||||||
|
|
||||||
|
// Atom version 1byte/ Atom flags 3 bytes; 0x00 00 00 00
|
||||||
|
#define AtomFlags_Data_Binary 0
|
||||||
|
|
||||||
|
// UTF-8, no termination
|
||||||
|
#define AtomFlags_Data_Text 1
|
||||||
|
|
||||||
|
// \x0D
|
||||||
|
#define AtomFlags_Data_JPEGBinary 13
|
||||||
|
|
||||||
|
// \x0E
|
||||||
|
#define AtomFlags_Data_PNGBinary 14
|
||||||
|
|
||||||
|
// \x15 for cpil, tmpo, rtng; iTMS atoms: cnID, atID, plID, geID, sfID, akID
|
||||||
|
#define AtomFlags_Data_UInt 21
|
||||||
|
|
||||||
|
// 0x58 for uuid atoms that contain files
|
||||||
|
#define AtomFlags_Data_uuid_binary 88
|
||||||
|
|
||||||
|
enum {
|
||||||
|
UTF8_iTunesStyle_256glyphLimited = 0, // no NULL termination
|
||||||
|
UTF8_iTunesStyle_Unlimited = 1, // no NULL termination
|
||||||
|
UTF8_iTunesStyle_Binary = 3, // no NULL termination, used in purl & egid
|
||||||
|
UTF8_3GP_Style = 8, // terminated with a NULL uint8_t
|
||||||
|
UTF16_3GP_Style = 16 // terminated with a NULL uint16_t
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
UNDEFINED_STYLE = 0,
|
||||||
|
ITUNES_STYLE = 100,
|
||||||
|
THIRD_GEN_PARTNER = 300, // 3gpp files prior to 3gp6
|
||||||
|
THIRD_GEN_PARTNER_VER1_REL6 =
|
||||||
|
306, // 3GPP Release6 the first spec to contain the complement of assets
|
||||||
|
THIRD_GEN_PARTNER_VER1_REL7 = 307, // 3GPP Release7 introduces ID32 atoms
|
||||||
|
THIRD_GEN_PARTNER_VER2 = 320, // 3gp2 files
|
||||||
|
THIRD_GEN_PARTNER_VER2_REL_A =
|
||||||
|
321, // 3gp2 files, 3GPP2 C.S0050-A introduces 'gadi'
|
||||||
|
MOTIONJPEG2000 = 400
|
||||||
|
};
|
||||||
|
|
||||||
|
#include "id3v2types.h"
|
||||||
|
struct AtomicInfo {
|
||||||
|
short AtomicNumber;
|
||||||
|
uint64_t AtomicStart;
|
||||||
|
uint64_t AtomicLength;
|
||||||
|
uint64_t AtomicLengthExtended;
|
||||||
|
char *AtomicName;
|
||||||
|
char *ReverseDNSname;
|
||||||
|
char *ReverseDNSdomain;
|
||||||
|
uint8_t AtomicContainerState;
|
||||||
|
uint8_t AtomicClassification;
|
||||||
|
uint32_t AtomicVerFlags; // used by versioned atoms and derivatives
|
||||||
|
uint16_t AtomicLanguage; // used by 3gp assets & ID32 atoms only
|
||||||
|
uint8_t AtomicLevel;
|
||||||
|
char *AtomicData;
|
||||||
|
int NextAtomNumber; // our first atom is numbered 0; the last points back to
|
||||||
|
// it - so watch it!
|
||||||
|
uint32_t
|
||||||
|
ancillary_data; // just contains a simple number for atoms that contains
|
||||||
|
// some interesting info (like stsd codec used)
|
||||||
|
uint8_t uuid_style;
|
||||||
|
char *uuid_ap_atomname;
|
||||||
|
ID3v2Tag *ID32_TagInfo;
|
||||||
|
};
|
||||||
|
#include "id3v2.h"
|
||||||
|
|
||||||
|
// currently this is only used on Mac OS X to set type/creator for generic
|
||||||
|
// '.mp4' file extension files. The Finder 4 character code TYPE is what
|
||||||
|
// determines whether a file appears as a video or an audio file in a broad
|
||||||
|
// sense.
|
||||||
|
struct EmployedCodecs {
|
||||||
|
bool has_avc1;
|
||||||
|
bool has_mp4v;
|
||||||
|
bool has_drmi;
|
||||||
|
bool has_alac;
|
||||||
|
bool has_mp4a;
|
||||||
|
bool has_drms;
|
||||||
|
bool has_timed_text; // carries the URL - in the mdat stream at a specific
|
||||||
|
// time - thus it too is timed.
|
||||||
|
bool has_timed_jpeg; // no idea of podcasts support 'png ' or 'tiff'
|
||||||
|
bool has_timed_tx3g; // this IS true timed text stream
|
||||||
|
bool has_mp4s; // MPEG-4 Systems
|
||||||
|
bool has_rtp_hint; //'rtp '; implies hinting
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
MEDIADATA__PRECEDES__MOOV = 2,
|
||||||
|
ROOT_META__PRECEDES__MOOV = 4,
|
||||||
|
MOOV_META__PRECEDES__TRACKS = 8,
|
||||||
|
MOOV_UDTA__PRECEDES__TRACKS = 16,
|
||||||
|
|
||||||
|
PADDING_AT_EOF = 0x1000000
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FreeAtomListing {
|
||||||
|
AtomicInfo *free_atom;
|
||||||
|
FreeAtomListing *next_free_listing;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DynamicUpdateStat {
|
||||||
|
bool updage_by_padding;
|
||||||
|
bool reorder_moov;
|
||||||
|
bool moov_was_mooved;
|
||||||
|
bool prevent_dynamic_update;
|
||||||
|
|
||||||
|
uint32_t optimization_flags;
|
||||||
|
|
||||||
|
uint64_t padding_bytes;
|
||||||
|
short consolidated_padding_insertion;
|
||||||
|
|
||||||
|
AtomicInfo *last_trak_child_atom;
|
||||||
|
AtomicInfo *moov_atom;
|
||||||
|
AtomicInfo *moov_udta_atom;
|
||||||
|
AtomicInfo *iTunes_list_handler_atom;
|
||||||
|
AtomicInfo *moov_meta_atom;
|
||||||
|
AtomicInfo *file_meta_atom;
|
||||||
|
AtomicInfo *first_mdat_atom;
|
||||||
|
AtomicInfo *first_movielevel_metadata_tagging_atom;
|
||||||
|
AtomicInfo *initial_update_atom;
|
||||||
|
AtomicInfo *first_otiose_freespace_atom;
|
||||||
|
AtomicInfo *padding_store;
|
||||||
|
AtomicInfo *padding_resevoir;
|
||||||
|
FreeAtomListing *first_padding_atom;
|
||||||
|
FreeAtomListing *last_padding_atom;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct padding_preferences {
|
||||||
|
uint32_t default_padding_size;
|
||||||
|
uint32_t minimum_required_padding_size;
|
||||||
|
uint32_t maximum_present_padding_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Structure that defines the known atoms used by mpeg-4 family of
|
||||||
|
// specifications.
|
||||||
|
typedef struct {
|
||||||
|
const char *known_atom_name;
|
||||||
|
const char *known_parent_atoms[5]; // max known to be tested
|
||||||
|
uint32_t container_state;
|
||||||
|
int presence_requirements;
|
||||||
|
uint32_t box_type;
|
||||||
|
} atomDefinition;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t uuid_form;
|
||||||
|
char *binary_uuid;
|
||||||
|
char *uuid_AP_atom_name;
|
||||||
|
} uuid_vitals;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PARENT_ATOM = 0, // container atom
|
||||||
|
SIMPLE_PARENT_ATOM = 1,
|
||||||
|
DUAL_STATE_ATOM =
|
||||||
|
2, // acts as both parent (contains other atoms) & child (carries data)
|
||||||
|
CHILD_ATOM = 3, // atom that does NOT contain any children
|
||||||
|
UNKNOWN_ATOM_TYPE = 4
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
REQUIRED_ONCE = 30, // means total of 1 atom per file (or total of 1 if
|
||||||
|
// parent atom is required to be present)
|
||||||
|
REQUIRED_ONE = 31, // means 1 atom per container atom; totalling many per file
|
||||||
|
// (or required present if optional parent atom is present)
|
||||||
|
REQUIRED_VARIABLE =
|
||||||
|
32, // means 1 or more atoms per container atom are required to be present
|
||||||
|
PARENT_SPECIFIC =
|
||||||
|
33, // means (iTunes-style metadata) the atom defines how many are
|
||||||
|
// present; most are MAX 1 'data' atoms; 'covr' is ?unlimited?
|
||||||
|
OPTIONAL_ONCE = 34, // means total of 1 atom per file, but not required
|
||||||
|
OPTIONAL_ONE = 35, // means 1 atom per container atom but not required; many
|
||||||
|
// may be present in a file
|
||||||
|
OPTIONAL_MANY = 36, // means more than 1 occurrence per container atom
|
||||||
|
REQ_FAMILIAL_ONE =
|
||||||
|
OPTIONAL_ONE, // means that one of the family of atoms defined by the spec
|
||||||
|
// is required by the parent atom
|
||||||
|
UKNOWN_REQUIREMENTS = 38
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
SIMPLE_ATOM = 50,
|
||||||
|
VERSIONED_ATOM = 51,
|
||||||
|
EXTENDED_ATOM = 52,
|
||||||
|
PACKED_LANG_ATOM = 53,
|
||||||
|
UNKNOWN_ATOM = 59
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PRINT_DATA = 1,
|
||||||
|
PRINT_FREE_SPACE = 2,
|
||||||
|
PRINT_PADDING_SPACE = 4,
|
||||||
|
PRINT_USER_DATA_SPACE = 8,
|
||||||
|
PRINT_MEDIA_SPACE = 16,
|
||||||
|
EXTRACT_ARTWORK = 20,
|
||||||
|
EXTRACT_ALL_UUID_BINARYS = 21
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char *stik_string;
|
||||||
|
uint8_t stik_number;
|
||||||
|
} stiks;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char *storefront_string;
|
||||||
|
uint32_t storefront_number;
|
||||||
|
} sfIDs;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char *iso639_2_code;
|
||||||
|
const char *iso639_1_code;
|
||||||
|
const char *language_in_english;
|
||||||
|
} iso639_lang;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char *media_rating;
|
||||||
|
const char *media_rating_cli_str;
|
||||||
|
} m_ratings;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char *genre_id_movie_string;
|
||||||
|
uint16_t genre_id_movie_value;
|
||||||
|
} geIDMovie;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char *genre_id_tv_string;
|
||||||
|
uint16_t genre_id_tv_value;
|
||||||
|
} geIDTV;
|
||||||
|
|
||||||
|
enum { UNIVERSAL_UTF8, WIN32_UTF16 };
|
||||||
|
|
||||||
|
enum { FORCE_M4B_TYPE = 85, NO_TYPE_FORCING = 90 };
|
||||||
|
|
||||||
|
enum { FILE_LEVEL_ATOM, MOVIE_LEVEL_ATOM, ALL_TRACKS_ATOM, SINGLE_TRACK_ATOM };
|
||||||
|
|
||||||
|
enum {
|
||||||
|
UUID_DEPRECATED_FORM,
|
||||||
|
UUID_SHA1_NAMESPACE,
|
||||||
|
UUID_AP_SHA1_NAMESPACE,
|
||||||
|
UUID_OTHER
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Declarations of functions and data types used for SHA1 sum
|
||||||
|
library functions.
|
||||||
|
Copyright (C) 2000, 2001, 2003, 2005 Free Software Foundation, Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t time_low;
|
||||||
|
uint16_t time_mid;
|
||||||
|
uint16_t time_hi_and_version;
|
||||||
|
uint8_t clock_seq_hi_and_reserved;
|
||||||
|
uint8_t clock_seq_low;
|
||||||
|
unsigned char node[6];
|
||||||
|
} ap_uuid_t;
|
||||||
|
|
||||||
|
typedef uint32_t md5_uint32;
|
||||||
|
|
||||||
|
/* Structure to save state of computation between the single steps. */
|
||||||
|
struct sha1_ctx {
|
||||||
|
md5_uint32 A;
|
||||||
|
md5_uint32 B;
|
||||||
|
md5_uint32 C;
|
||||||
|
md5_uint32 D;
|
||||||
|
md5_uint32 E;
|
||||||
|
|
||||||
|
md5_uint32 total[2];
|
||||||
|
md5_uint32 buflen;
|
||||||
|
char buffer[128]; // char buffer[128] __attribute__ ((__aligned__ (__alignof__
|
||||||
|
// (md5_uint32))));
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct { // if any of these are unused, they are set to 0xFF
|
||||||
|
uint8_t od_profile_level;
|
||||||
|
uint8_t scene_profile_level;
|
||||||
|
uint8_t audio_profile;
|
||||||
|
uint8_t video_profile_level;
|
||||||
|
uint8_t graphics_profile_level;
|
||||||
|
} iods_OD;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_t creation_time;
|
||||||
|
uint64_t modified_time;
|
||||||
|
uint64_t duration;
|
||||||
|
bool track_enabled;
|
||||||
|
unsigned char unpacked_lang[4];
|
||||||
|
char track_hdlr_name[100];
|
||||||
|
char encoder_name[100];
|
||||||
|
|
||||||
|
uint32_t track_type;
|
||||||
|
uint32_t track_codec;
|
||||||
|
uint32_t protected_codec;
|
||||||
|
|
||||||
|
bool contains_esds;
|
||||||
|
|
||||||
|
uint64_t section3_length;
|
||||||
|
uint64_t section4_length;
|
||||||
|
uint8_t ObjectTypeIndication;
|
||||||
|
uint32_t max_bitrate;
|
||||||
|
uint32_t avg_bitrate;
|
||||||
|
uint64_t section5_length;
|
||||||
|
uint8_t descriptor_object_typeID;
|
||||||
|
uint16_t channels;
|
||||||
|
uint64_t section6_length; // unused
|
||||||
|
|
||||||
|
// specifics
|
||||||
|
uint8_t m4v_profile;
|
||||||
|
uint8_t avc_version;
|
||||||
|
uint8_t profile;
|
||||||
|
uint8_t level;
|
||||||
|
uint16_t video_height;
|
||||||
|
uint16_t video_width;
|
||||||
|
uint32_t macroblocks;
|
||||||
|
uint64_t sample_aggregate;
|
||||||
|
uint16_t amr_modes;
|
||||||
|
|
||||||
|
uint8_t type_of_track;
|
||||||
|
|
||||||
|
} TrackInfo;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_t creation_time;
|
||||||
|
uint64_t modified_time;
|
||||||
|
uint32_t timescale;
|
||||||
|
uint32_t duration;
|
||||||
|
uint32_t playback_rate; // fixed point 16.16
|
||||||
|
uint16_t volume; // fixed 8.8 point
|
||||||
|
|
||||||
|
double seconds;
|
||||||
|
double simple_bitrate_calc;
|
||||||
|
|
||||||
|
bool contains_iods;
|
||||||
|
} MovieInfo;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t total_tracks;
|
||||||
|
uint8_t track_num;
|
||||||
|
short track_atom;
|
||||||
|
} Trackage;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t hours;
|
||||||
|
uint8_t minutes;
|
||||||
|
uint8_t seconds;
|
||||||
|
double rem_millisecs;
|
||||||
|
} ap_time;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
UNKNOWN_TRACK = 0,
|
||||||
|
VIDEO_TRACK = 2,
|
||||||
|
AUDIO_TRACK = 4,
|
||||||
|
DRM_PROTECTED_TRACK = 8,
|
||||||
|
OTHER_TRACK = 16
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
MP4V_TRACK = 65,
|
||||||
|
AVC1_TRACK = 66,
|
||||||
|
S_AMR_TRACK = 67,
|
||||||
|
S263_TRACK = 68,
|
||||||
|
EVRC_TRACK = 69,
|
||||||
|
QCELP_TRACK = 70,
|
||||||
|
SMV_TRACK = 71
|
||||||
|
};
|
||||||
|
|
||||||
|
enum { SHOW_TRACK_INFO = 2, SHOW_DATE_INFO = 4 };
|
||||||
|
|
||||||
|
struct PicPrefs {
|
||||||
|
int max_dimension;
|
||||||
|
int dpi;
|
||||||
|
int max_Kbytes;
|
||||||
|
bool squareUp;
|
||||||
|
bool allJPEG;
|
||||||
|
bool allPNG;
|
||||||
|
bool addBOTHpix;
|
||||||
|
bool removeTempPix;
|
||||||
|
bool force_dimensions;
|
||||||
|
int force_height;
|
||||||
|
int force_width;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* vim:ts=2:sw=2:et:
|
||||||
|
*/
|
||||||
945
src/arrays.cpp
Normal file
945
src/arrays.cpp
Normal file
@ -0,0 +1,945 @@
|
|||||||
|
//==================================================================//
|
||||||
|
/*
|
||||||
|
AtomicParsley - arrays.cpp
|
||||||
|
|
||||||
|
AtomicParsley is GPL software; you can freely distribute,
|
||||||
|
redistribute, modify & use under the terms of the GNU General
|
||||||
|
Public License; either version 2 or its successor.
|
||||||
|
|
||||||
|
AtomicParsley is distributed under the GPL "AS IS", without
|
||||||
|
any warranty; without the implied warranty of merchantability
|
||||||
|
or fitness for either an expressed or implied particular purpose.
|
||||||
|
|
||||||
|
Please see the included GNU General Public License (GPL) for
|
||||||
|
your rights and further details; see the file COPYING. If you
|
||||||
|
cannot, write to the Free Software Foundation, 59 Temple Place
|
||||||
|
Suite 330, Boston, MA 02111-1307, USA. Or www.fsf.org
|
||||||
|
|
||||||
|
Copyright (C) 2005-2007 puck_lock
|
||||||
|
with contributions from others; see the CREDITS file
|
||||||
|
|
||||||
|
----------------------
|
||||||
|
Code Contributions by:
|
||||||
|
|
||||||
|
* Mellow_Flow - fix genre matching/verify genre limits
|
||||||
|
*/
|
||||||
|
//==================================================================//
|
||||||
|
|
||||||
|
#include "AtomicParsley.h"
|
||||||
|
|
||||||
|
//////////////
|
||||||
|
|
||||||
|
static const char *ID3v1GenreList[] = {"Blues",
|
||||||
|
"Classic Rock",
|
||||||
|
"Country",
|
||||||
|
"Dance",
|
||||||
|
"Disco",
|
||||||
|
"Funk",
|
||||||
|
"Grunge",
|
||||||
|
"Hip-Hop",
|
||||||
|
"Jazz",
|
||||||
|
"Metal",
|
||||||
|
"New Age",
|
||||||
|
"Oldies",
|
||||||
|
"Other",
|
||||||
|
"Pop",
|
||||||
|
"R&B",
|
||||||
|
"Rap",
|
||||||
|
"Reggae",
|
||||||
|
"Rock",
|
||||||
|
"Techno",
|
||||||
|
"Industrial",
|
||||||
|
"Alternative",
|
||||||
|
"Ska",
|
||||||
|
"Death Metal",
|
||||||
|
"Pranks",
|
||||||
|
"Soundtrack",
|
||||||
|
"Euro-Techno",
|
||||||
|
"Ambient",
|
||||||
|
"Trip-Hop",
|
||||||
|
"Vocal",
|
||||||
|
"Jazz+Funk",
|
||||||
|
"Fusion",
|
||||||
|
"Trance",
|
||||||
|
"Classical",
|
||||||
|
"Instrumental",
|
||||||
|
"Acid",
|
||||||
|
"House",
|
||||||
|
"Game",
|
||||||
|
"Sound Clip",
|
||||||
|
"Gospel",
|
||||||
|
"Noise",
|
||||||
|
"AlternRock",
|
||||||
|
"Bass",
|
||||||
|
"Soul",
|
||||||
|
"Punk",
|
||||||
|
"Space",
|
||||||
|
"Meditative",
|
||||||
|
"Instrumental Pop",
|
||||||
|
"Instrumental Rock",
|
||||||
|
"Ethnic",
|
||||||
|
"Gothic",
|
||||||
|
"Darkwave",
|
||||||
|
"Techno-Industrial",
|
||||||
|
"Electronic",
|
||||||
|
"Pop-Folk",
|
||||||
|
"Eurodance",
|
||||||
|
"Dream",
|
||||||
|
"Southern Rock",
|
||||||
|
"Comedy",
|
||||||
|
"Cult",
|
||||||
|
"Gangsta",
|
||||||
|
"Top 40",
|
||||||
|
"Christian Rap",
|
||||||
|
"Pop/Funk",
|
||||||
|
"Jungle",
|
||||||
|
"Native American",
|
||||||
|
"Cabaret",
|
||||||
|
"New Wave",
|
||||||
|
"Psychadelic",
|
||||||
|
"Rave",
|
||||||
|
"Showtunes",
|
||||||
|
"Trailer",
|
||||||
|
"Lo-Fi",
|
||||||
|
"Tribal",
|
||||||
|
"Acid Punk",
|
||||||
|
"Acid Jazz",
|
||||||
|
"Polka",
|
||||||
|
"Retro",
|
||||||
|
"Musical",
|
||||||
|
"Rock & Roll",
|
||||||
|
"Hard Rock",
|
||||||
|
"Folk",
|
||||||
|
"Folk/Rock",
|
||||||
|
"National Folk",
|
||||||
|
"Swing",
|
||||||
|
"Fast Fusion",
|
||||||
|
"Bebob",
|
||||||
|
"Latin",
|
||||||
|
"Revival",
|
||||||
|
"Celtic",
|
||||||
|
"Bluegrass",
|
||||||
|
"Avantgarde",
|
||||||
|
"Gothic Rock",
|
||||||
|
"Progressive Rock",
|
||||||
|
"Psychedelic Rock",
|
||||||
|
"Symphonic Rock",
|
||||||
|
"Slow Rock",
|
||||||
|
"Big Band",
|
||||||
|
"Chorus",
|
||||||
|
"Easy Listening",
|
||||||
|
"Acoustic",
|
||||||
|
"Humour",
|
||||||
|
"Speech",
|
||||||
|
"Chanson",
|
||||||
|
"Opera",
|
||||||
|
"Chamber Music",
|
||||||
|
"Sonata",
|
||||||
|
"Symphony",
|
||||||
|
"Booty Bass",
|
||||||
|
"Primus",
|
||||||
|
"Porn Groove",
|
||||||
|
"Satire",
|
||||||
|
"Slow Jam",
|
||||||
|
"Club",
|
||||||
|
"Tango",
|
||||||
|
"Samba",
|
||||||
|
"Folklore",
|
||||||
|
"Ballad",
|
||||||
|
"Power Ballad",
|
||||||
|
"Rhythmic Soul",
|
||||||
|
"Freestyle",
|
||||||
|
"Duet",
|
||||||
|
"Punk Rock",
|
||||||
|
"Drum Solo",
|
||||||
|
"A Capella",
|
||||||
|
"Euro-House",
|
||||||
|
"Dance Hall"};
|
||||||
|
/*
|
||||||
|
"Goa", "Drum & Bass", "Club House", "Hardcore",
|
||||||
|
"Terror", "Indie", "BritPop", "NegerPunk", "Polsk Punk",
|
||||||
|
"Beat", "Christian Gangsta", "Heavy Metal", "Black Metal", "Crossover",
|
||||||
|
"Contemporary C", "Christian Rock", "Merengue", "Salsa", "Thrash Metal",
|
||||||
|
"Anime", "JPop", "SynthPop",
|
||||||
|
}; */ //apparently the other winamp id3v1 extensions aren't valid
|
||||||
|
|
||||||
|
stiks stikArray[] = {{"Home Video", 0},
|
||||||
|
{"Normal", 1},
|
||||||
|
{"Audiobook", 2},
|
||||||
|
{"Whacked Bookmark", 5},
|
||||||
|
{"Music Video", 6},
|
||||||
|
{"Movie", 9},
|
||||||
|
{"Short Film", 9},
|
||||||
|
{"TV Show", 10},
|
||||||
|
{"Booklet", 11}};
|
||||||
|
|
||||||
|
geIDMovie genreidmovie[] = {{"Action & Adventure", 4401},
|
||||||
|
{"Anime", 4402},
|
||||||
|
{"Classics", 4403},
|
||||||
|
{"Comedy", 4404},
|
||||||
|
{"Documentary", 4405},
|
||||||
|
{"Drama", 4406},
|
||||||
|
{"Foreign", 4407},
|
||||||
|
{"Horror", 4408},
|
||||||
|
{"Independent", 4409},
|
||||||
|
{"Kids & Family", 4410},
|
||||||
|
{"Musicals", 4411},
|
||||||
|
{"Romance", 4412},
|
||||||
|
{"Sci-Fi & Fantasy", 4413},
|
||||||
|
{"Short Films", 4414},
|
||||||
|
{"Special Interest", 4415},
|
||||||
|
{"Thriller", 4416},
|
||||||
|
{"Sports", 4417},
|
||||||
|
{"Western", 4418},
|
||||||
|
{"Urban", 4419},
|
||||||
|
{"Holiday", 4420},
|
||||||
|
{"Made for TV", 4421},
|
||||||
|
{"Concert Films", 4422},
|
||||||
|
{"Music Documentaries", 4423},
|
||||||
|
{"Music Feature Films", 4424},
|
||||||
|
{"Japanese Cinema", 4425},
|
||||||
|
{"Jidaigeki", 4426},
|
||||||
|
{"Tokusatsu", 4427},
|
||||||
|
{"Korean Cinema", 4428}};
|
||||||
|
|
||||||
|
geIDTV genreidtv[] = {{"Comedy", 4000},
|
||||||
|
{"Drama", 4001},
|
||||||
|
{"Animation", 4002},
|
||||||
|
{"Action & Adventure", 4003},
|
||||||
|
{"Classic", 4004},
|
||||||
|
{"Kids", 4005},
|
||||||
|
{"Nonfiction", 4005},
|
||||||
|
{"Reality TV", 4007},
|
||||||
|
{"Sci-Fi & Fantasy", 4008},
|
||||||
|
{"Sports", 4009},
|
||||||
|
{"Teens", 4010},
|
||||||
|
{"Latino TV", 4011}};
|
||||||
|
|
||||||
|
// from William Herrera:
|
||||||
|
// http://search.cpan.org/src/BILLH/LWP-UserAgent-iTMS_Client-0.16/lib/LWP/UserAgent/iTMS_Client.pm
|
||||||
|
sfIDs storefronts[] = {
|
||||||
|
{"United States", 143441}, {"France", 143442}, {"Germany", 143443},
|
||||||
|
{"United Kingdom", 143444}, {"Austria", 143445}, {"Belgium", 143446},
|
||||||
|
{"Finland", 143447}, {"Greece", 143448}, {"Ireland", 143449},
|
||||||
|
{"Italy", 143450}, {"Luxembourg", 143451}, {"Netherlands", 143452},
|
||||||
|
{"Portugal", 143453}, {"Spain", 143454}, {"Canada", 143455},
|
||||||
|
{"Sweden", 143456}, {"Norway", 143457}, {"Denmark", 143458},
|
||||||
|
{"Switzerland", 143459}, {"Australia", 143460}, {"New Zealand", 143461},
|
||||||
|
{"Japan", 143462}};
|
||||||
|
|
||||||
|
iso639_lang known_languages[] = {
|
||||||
|
{"aar", "aa", "Afar"},
|
||||||
|
{"abk", "ab", "Abkhazian"},
|
||||||
|
{"ace", NULL, "Achinese"},
|
||||||
|
{"ach", NULL, "Acoli"},
|
||||||
|
{"ada", NULL, "Adangme"},
|
||||||
|
{"ady", NULL, "Adyghe; Adygei"},
|
||||||
|
{"afa", NULL, "Afro-Asiatic (Other)"},
|
||||||
|
{"afh", NULL, "Afrihili"},
|
||||||
|
{"afr", "af", "Afrikaans"},
|
||||||
|
{"ain", NULL, "Ainu"},
|
||||||
|
{"aka", "ak", "Akan"},
|
||||||
|
{"akk", NULL, "Akkadian"},
|
||||||
|
{"alb/sqi", "sq", "Albanian"}, // dual codes
|
||||||
|
{"ale", NULL, "Aleut"},
|
||||||
|
{"alg", NULL, "Algonquian languages"},
|
||||||
|
{"alt", NULL, "Southern Altai"},
|
||||||
|
{"amh", "am", "Amharic"},
|
||||||
|
{"ang", NULL, "English, Old (ca.450-1100)"},
|
||||||
|
{"anp", NULL, "Angika"},
|
||||||
|
{"apa", NULL, "Apache languages"},
|
||||||
|
{"ara", "ar", "Arabic"},
|
||||||
|
{"arc", NULL, "Aramaic"},
|
||||||
|
{"arg", "an", "Aragonese"},
|
||||||
|
{"arm/hye", "hy", "Armenian"}, // dual codes
|
||||||
|
{"arn", NULL, "Araucanian"},
|
||||||
|
{"arp", NULL, "Arapaho"},
|
||||||
|
{"art", NULL, "Artificial (Other)"},
|
||||||
|
{"arw", NULL, "Arawak"},
|
||||||
|
{"asm", "as", "Assamese"},
|
||||||
|
{"ast", NULL, "Asturian; Bable"},
|
||||||
|
{"ath", NULL, "Athapascan languages"},
|
||||||
|
{"aus", NULL, "Australian languages"},
|
||||||
|
{"ava", "av", "Avaric"},
|
||||||
|
{"ave", "ae", "Avestan"},
|
||||||
|
{"awa", NULL, "Awadhi"},
|
||||||
|
{"aym", "ay", "Aymara"},
|
||||||
|
{"aze", "az", "Azerbaijani"},
|
||||||
|
{"bad", NULL, "Banda"},
|
||||||
|
{"bai", NULL, "Bamileke languages"},
|
||||||
|
{"bak", "ba", "Bashkir"},
|
||||||
|
{"bal", NULL, "Baluchi"},
|
||||||
|
{"bam", "bm", "Bambara"},
|
||||||
|
{"ban", NULL, "Balinese"},
|
||||||
|
{"baq/eus", "eu", "Basque"}, // dual codes
|
||||||
|
{"bas", NULL, "Basa"},
|
||||||
|
{"bat", NULL, "Baltic (Other)"},
|
||||||
|
{"bej", NULL, "Beja"},
|
||||||
|
{"bel", "be", "Belarusian"},
|
||||||
|
{"bem", NULL, "Bemba"},
|
||||||
|
{"ben", "bn", "Bengali"},
|
||||||
|
{"ber", NULL, "Berber (Other)"},
|
||||||
|
{"bho", NULL, "Bhojpuri"},
|
||||||
|
{"bih", "bh", "Bihari"},
|
||||||
|
{"bik", NULL, "Bikol"},
|
||||||
|
{"bin", NULL, "Bini"},
|
||||||
|
{"bis", "bi", "Bislama"},
|
||||||
|
{"bla", NULL, "Siksika"},
|
||||||
|
{"bnt", NULL, "Bantu (Other)"},
|
||||||
|
{"bos", "bs", "Bosnian"},
|
||||||
|
{"bra", NULL, "Braj"},
|
||||||
|
{"bre", "br", "Breton"},
|
||||||
|
{"btk", NULL, "Batak (Indonesia)"},
|
||||||
|
{"bua", NULL, "Buriat"},
|
||||||
|
{"bug", NULL, "Buginese"},
|
||||||
|
{"bul", "bg", "Bulgarian"},
|
||||||
|
{"bur/mya", "my", "Burmese"}, // dual codes
|
||||||
|
{"byn", NULL, "Blin; Bilin"},
|
||||||
|
{"cad", NULL, "Caddo"},
|
||||||
|
{"cai", NULL, "Central American Indian (Other)"},
|
||||||
|
{"car", NULL, "Carib"},
|
||||||
|
{"cat", "ca", "Catalan; Valencian"},
|
||||||
|
{"cau", NULL, "Caucasian (Other)"},
|
||||||
|
{"ceb", NULL, "Cebuano"},
|
||||||
|
{"cel", NULL, "Celtic (Other)"},
|
||||||
|
{"cha", "ch", "Chamorro"},
|
||||||
|
{"chb", NULL, "Chibcha"},
|
||||||
|
{"che", "ce", "Chechen"},
|
||||||
|
{"chg", NULL, "Chagatai"},
|
||||||
|
{"chk", NULL, "Chuukese"},
|
||||||
|
{"chm", NULL, "Mari"},
|
||||||
|
{"chn", NULL, "Chinook jargon"},
|
||||||
|
{"cho", NULL, "Choctaw"},
|
||||||
|
{"chp", NULL, "Chipewyan"},
|
||||||
|
{"chr", NULL, "Cherokee"},
|
||||||
|
{"chu",
|
||||||
|
"cu",
|
||||||
|
"Church Slavic; Old Slavonic; Church Slavonic; Old Bulgarian; Old Church "
|
||||||
|
"Slavonic"},
|
||||||
|
{"chv", "cv", "Chuvash"},
|
||||||
|
{"chy", NULL, "Cheyenne"},
|
||||||
|
{"cmc", NULL, "Chamic languages"},
|
||||||
|
{"cop", NULL, "Coptic"},
|
||||||
|
{"cor", "kw", "Cornish"},
|
||||||
|
{"cos", "co", "Corsican"},
|
||||||
|
{"cpe", NULL, "Creoles and pidgins, English based (Other)"},
|
||||||
|
{"cpf", NULL, "Creoles and pidgins, French-based (Other)"},
|
||||||
|
{"cpp", NULL, "Creoles and pidgins, Portuguese-based (Other)"},
|
||||||
|
{"cre", "cr", "Cree"},
|
||||||
|
{"crh", NULL, "Crimean Tatar; Crimean Turkish"},
|
||||||
|
{"crp", NULL, "Creoles and pidgins (Other)"},
|
||||||
|
{"csb", NULL, "Kashubian"},
|
||||||
|
{"cus", NULL, "Cushitic (Other)"},
|
||||||
|
{"cze/ces", "cs", "Czech"}, // dual codes
|
||||||
|
{"dak", NULL, "Dakota"},
|
||||||
|
{"dan", "da", "Danish"},
|
||||||
|
{"dar", NULL, "Dargwa"},
|
||||||
|
{"day", NULL, "Dayak"},
|
||||||
|
{"del", NULL, "Delaware"},
|
||||||
|
{"den", NULL, "Slave (Athapascan)"},
|
||||||
|
{"dgr", NULL, "Dogrib"},
|
||||||
|
{"din", NULL, "Dinka"},
|
||||||
|
{"div", "dv", "Divehi; Dhivehi; Maldivian"},
|
||||||
|
{"doi", NULL, "Dogri"},
|
||||||
|
{"dra", NULL, "Dravidian (Other)"},
|
||||||
|
{"dsb", NULL, "Lower Sorbian"},
|
||||||
|
{"dua", NULL, "Duala"},
|
||||||
|
{"dum", NULL, "Dutch, Middle (ca.1050-1350)"},
|
||||||
|
{"dut/nld", "nl", "Dutch; Flemish"}, // dual codes
|
||||||
|
{"dyu", NULL, "Dyula"},
|
||||||
|
{"dzo", "dz", "Dzongkha"},
|
||||||
|
{"efi", NULL, "Efik"},
|
||||||
|
{"egy", NULL, "Egyptian (Ancient)"},
|
||||||
|
{"eka", NULL, "Ekajuk"},
|
||||||
|
{"elx", NULL, "Elamite"},
|
||||||
|
{"eng", "en", "English"},
|
||||||
|
{"enm", NULL, "English, Middle (1100-1500)"},
|
||||||
|
{"epo", "eo", "Esperanto"},
|
||||||
|
{"est", "et", "Estonian"},
|
||||||
|
{"ewe", "ee", "Ewe"},
|
||||||
|
{"ewo", NULL, "Ewondo"},
|
||||||
|
{"fan", NULL, "Fang"},
|
||||||
|
{"fao", "fo", "Faroese"},
|
||||||
|
{"fat", NULL, "Fanti"},
|
||||||
|
{"fij", "fj", "Fijian"},
|
||||||
|
{"fil", NULL, "Filipino; Pilipino"},
|
||||||
|
{"fin", "fi", "Finnish"},
|
||||||
|
{"fiu", NULL, "Finno-Ugrian (Other)"},
|
||||||
|
{"fon", NULL, "Fon"},
|
||||||
|
{"fre/fra", "fr", "French"}, // dual codes
|
||||||
|
{"frm", NULL, "French, Middle (ca.1400-1600)"},
|
||||||
|
{"fro", NULL, "French, Old (842-ca.1400)"},
|
||||||
|
{"frr", NULL, "Northern Frisian"},
|
||||||
|
{"frs", NULL, "Eastern Frisian"},
|
||||||
|
{"fry", "fy", "Western Frisian"},
|
||||||
|
{"ful", "ff", "Fulah"},
|
||||||
|
{"fur", NULL, "Friulian"},
|
||||||
|
{"gaa", NULL, "Ga"},
|
||||||
|
{"gay", NULL, "Gayo"},
|
||||||
|
{"gba", NULL, "Gbaya"},
|
||||||
|
{"gem", NULL, "Germanic (Other)"},
|
||||||
|
{"geo/kat", "ka", "Georgian"}, // dual codes
|
||||||
|
{"ger/deu", "de", "German"}, // dual codes
|
||||||
|
{"gez", NULL, "Geez"},
|
||||||
|
{"gil", NULL, "Gilbertese"},
|
||||||
|
{"gla", "gd", "Gaelic; Scottish Gaelic"},
|
||||||
|
{"gle", "ga", "Irish"},
|
||||||
|
{"glg", "gl", "Galician"},
|
||||||
|
{"glv", "gv", "Manx"},
|
||||||
|
{"gmh", NULL, "German, Middle High (ca.1050-1500)"},
|
||||||
|
{"goh", NULL, "German, Old High (ca.750-1050)"},
|
||||||
|
{"gon", NULL, "Gondi"},
|
||||||
|
{"gor", NULL, "Gorontalo"},
|
||||||
|
{"got", NULL, "Gothic"},
|
||||||
|
{"grb", NULL, "Grebo"},
|
||||||
|
{"grc", NULL, "Greek, Ancient (to 1453)"},
|
||||||
|
{"gre/ell", "el", "Greek, Modern (1453-)"}, // dual codes
|
||||||
|
{"grn", "gn", "Guarani"},
|
||||||
|
{"gsw", NULL, "Alemanic; Swiss German"},
|
||||||
|
{"guj", "gu", "Gujarati"},
|
||||||
|
{"gwi", NULL, "Gwich\u00abin"},
|
||||||
|
{"hai", NULL, "Haida"},
|
||||||
|
{"hat", "ht", "Haitian; Haitian Creole"},
|
||||||
|
{"hau", "ha", "Hausa"},
|
||||||
|
{"haw", NULL, "Hawaiian"},
|
||||||
|
{"heb", "he", "Hebrew"},
|
||||||
|
{"her", "hz", "Herero"},
|
||||||
|
{"hil", NULL, "Hiligaynon"},
|
||||||
|
{"him", NULL, "Himachali"},
|
||||||
|
{"hin", "hi", "Hindi"},
|
||||||
|
{"hit", NULL, "Hittite"},
|
||||||
|
{"hmn", NULL, "Hmong"},
|
||||||
|
{"hmo", "ho", "Hiri Motu"},
|
||||||
|
{"hsb", NULL, "Upper Sorbian"},
|
||||||
|
{"hun", "hu", "Hungarian"},
|
||||||
|
{"hup", NULL, "Hupa"},
|
||||||
|
{"arm/hye", "hy", "Armenian"},
|
||||||
|
{"iba", NULL, "Iban"},
|
||||||
|
{"ibo", "ig", "Igbo"},
|
||||||
|
{"ice/isl", "is", "Icelandic"}, // dual codes
|
||||||
|
{"ido", "io", "Ido"},
|
||||||
|
{"iii", "ii", "Sichuan Yi"},
|
||||||
|
{"ijo", NULL, "Ijo"},
|
||||||
|
{"iku", "iu", "Inuktitut"},
|
||||||
|
{"ile", "ie", "Interlingue"},
|
||||||
|
{"ilo", NULL, "Iloko"},
|
||||||
|
{"ina",
|
||||||
|
"ia",
|
||||||
|
"Interlingua (International Auxiliary, Language Association)"},
|
||||||
|
{"inc", NULL, "Indic (Other)"},
|
||||||
|
{"ind", "id", "Indonesian"},
|
||||||
|
{"ine", NULL, "Indo-European (Other)"},
|
||||||
|
{"inh", NULL, "Ingush"},
|
||||||
|
{"ipk", "ik", "Inupiaq"},
|
||||||
|
{"ira", NULL, "Iranian (Other)"},
|
||||||
|
{"iro", NULL, "Iroquoian languages"},
|
||||||
|
{"ita", "it", "Italian"},
|
||||||
|
{"jav", "jv", "Javanese"},
|
||||||
|
{"jbo", NULL, "Lojban"},
|
||||||
|
{"jpn", "ja", "Japanese"},
|
||||||
|
{"jpr", NULL, "Judeo-Persian"},
|
||||||
|
{"jrb", NULL, "Judeo-Arabic"},
|
||||||
|
{"kaa", NULL, "Kara-Kalpak"},
|
||||||
|
{"kab", NULL, "Kabyle"},
|
||||||
|
{"kac", NULL, "Kachin"},
|
||||||
|
{"kal", "kl", "Kalaallisut; Greenlandic"},
|
||||||
|
{"kam", NULL, "Kamba"},
|
||||||
|
{"kan", "kn", "Kannada"},
|
||||||
|
{"kar", NULL, "Karen"},
|
||||||
|
{"kas", "ks", "Kashmiri"},
|
||||||
|
{"kau", "kr", "Kanuri"},
|
||||||
|
{"kaw", NULL, "Kawi"},
|
||||||
|
{"kaz", "kk", "Kazakh"},
|
||||||
|
{"kbd", NULL, "Kabardian"},
|
||||||
|
{"kha", NULL, "Khasi"},
|
||||||
|
{"khi", NULL, "Khoisan (Other)"},
|
||||||
|
{"khm", "km", "Khmer"},
|
||||||
|
{"kho", NULL, "Khotanese"},
|
||||||
|
{"kik", "ki", "Kikuyu; Gikuyu"},
|
||||||
|
{"kin", "rw", "Kinyarwanda"},
|
||||||
|
{"kir", "ky", "Kirghiz"},
|
||||||
|
{"kmb", NULL, "Kimbundu"},
|
||||||
|
{"kok", NULL, "Konkani"},
|
||||||
|
{"kom", "kv", "Komi"},
|
||||||
|
{"kon", "kg", "Kongo"},
|
||||||
|
{"kor", "ko", "Korean"},
|
||||||
|
{"kos", NULL, "Kosraean"},
|
||||||
|
{"kpe", NULL, "Kpelle"},
|
||||||
|
{"krc", NULL, "Karachay-Balkar"},
|
||||||
|
{"krl", NULL, "Karelian"},
|
||||||
|
{"kro", NULL, "Kru"},
|
||||||
|
{"kru", NULL, "Kurukh"},
|
||||||
|
{"kua", "kj", "Kuanyama; Kwanyama"},
|
||||||
|
{"kum", NULL, "Kumyk"},
|
||||||
|
{"kur", "ku", "Kurdish"},
|
||||||
|
{"kut", NULL, "Kutenai"},
|
||||||
|
{"lad", NULL, "Ladino"},
|
||||||
|
{"lah", NULL, "Lahnda"},
|
||||||
|
{"lam", NULL, "Lamba"},
|
||||||
|
{"lao", "lo", "Lao"},
|
||||||
|
{"lat", "la", "Latin"},
|
||||||
|
{"lav", "lv", "Latvian"},
|
||||||
|
{"lez", NULL, "Lezghian"},
|
||||||
|
{"lim", "li", "Limburgan; Limburger; Limburgish"},
|
||||||
|
{"lin", "ln", "Lingala"},
|
||||||
|
{"lit", "lt", "Lithuanian"},
|
||||||
|
{"lol", NULL, "Mongo"},
|
||||||
|
{"loz", NULL, "Lozi"},
|
||||||
|
{"ltz", "lb", "Luxembourgish; Letzeburgesch"},
|
||||||
|
{"lua", NULL, "Luba-Lulua"},
|
||||||
|
{"lub", "lu", "Luba-Katanga"},
|
||||||
|
{"lug", "lg", "Ganda"},
|
||||||
|
{"lui", NULL, "Luiseno"},
|
||||||
|
{"lun", NULL, "Lunda"},
|
||||||
|
{"luo", NULL, "Luo (Kenya and Tanzania)"},
|
||||||
|
{"lus", NULL, "Lushai"},
|
||||||
|
{"mad", NULL, "Madurese"},
|
||||||
|
{"mag", NULL, "Magahi"},
|
||||||
|
{"mah", "mh", "Marshallese"},
|
||||||
|
{"mai", NULL, "Maithili"},
|
||||||
|
{"mak", NULL, "Makasar"},
|
||||||
|
{"mal", "ml", "Malayalam"},
|
||||||
|
{"man", NULL, "Mandingo"},
|
||||||
|
{"map", NULL, "Austronesian (Other)"},
|
||||||
|
{"mar", "mr", "Marathi"},
|
||||||
|
{"mas", NULL, "Masai"},
|
||||||
|
{"may/msa", "ms", "Malay"}, // dual codes
|
||||||
|
{"mdf", NULL, "Moksha"},
|
||||||
|
{"mdr", NULL, "Mandar"},
|
||||||
|
{"men", NULL, "Mende"},
|
||||||
|
{"mga", NULL, "Irish, Middle (900-1200)"},
|
||||||
|
{"mic", NULL, "Mi'kmaq; Micmac"},
|
||||||
|
{"min", NULL, "Minangkabau"},
|
||||||
|
{"mis", NULL, "Miscellaneous languages"},
|
||||||
|
{"mac/mkd", "mk", "Macedonian"}, // dual codes
|
||||||
|
{"mkh", NULL, "Mon-Khmer (Other)"},
|
||||||
|
{"mlg", "mg", "Malagasy"},
|
||||||
|
{"mlt", "mt", "Maltese"},
|
||||||
|
{"mnc", NULL, "Manchu"},
|
||||||
|
{"mni", NULL, "Manipuri"},
|
||||||
|
{"mno", NULL, "Manobo languages"},
|
||||||
|
{"moh", NULL, "Mohawk"},
|
||||||
|
{"mol", "mo", "Moldavian"},
|
||||||
|
{"mon", "mn", "Mongolian"},
|
||||||
|
{"mos", NULL, "Mossi"},
|
||||||
|
{"mao/mri", "mi", "Maori"}, // dual codes
|
||||||
|
{"mul", NULL, "Multiple languages"},
|
||||||
|
{"mun", NULL, "Munda languages"},
|
||||||
|
{"mus", NULL, "Creek"},
|
||||||
|
{"mwl", NULL, "Mirandese"},
|
||||||
|
{"mwr", NULL, "Marwari"},
|
||||||
|
{"myn", NULL, "Mayan languages"},
|
||||||
|
{"myv", NULL, "Erzya"},
|
||||||
|
{"nah", NULL, "Nahuatl"},
|
||||||
|
{"nai", NULL, "North American Indian"},
|
||||||
|
{"nap", NULL, "Neapolitan"},
|
||||||
|
{"nau", "na", "Nauru"},
|
||||||
|
{"nav", "nv", "Navajo; Navaho"},
|
||||||
|
{"nbl", "nr", "Ndebele, South; South Ndebele"},
|
||||||
|
{"nde", "nd", "Ndebele, North; North Ndebele"},
|
||||||
|
{"ndo", "ng", "Ndonga"},
|
||||||
|
{"nds", NULL, "Low German; Low Saxon; German, Low; Saxon, Low"},
|
||||||
|
{"nep", "ne", "Nepali"},
|
||||||
|
{"new", NULL, "Newari; Nepal Bhasa"},
|
||||||
|
{"nia", NULL, "Nias"},
|
||||||
|
{"nic", NULL, "Niger-Kordofanian (Other)"},
|
||||||
|
{"niu", NULL, "Niuean"},
|
||||||
|
{"nno", "nn", "Norwegian Nynorsk; Nynorsk, Norwegian"},
|
||||||
|
{"nob", "nb", "Norwegian Bokm\x8cl; Bokm\x8cl, Norwegian"},
|
||||||
|
{"nog", NULL, "Nogai"},
|
||||||
|
{"non", NULL, "Norse, Old"},
|
||||||
|
{"nor", "no", "Norwegian"},
|
||||||
|
{"nqo", NULL, "N'ko"},
|
||||||
|
{"nso", NULL, "Northern Sotho, Pedi; Sepedi"},
|
||||||
|
{"nub", NULL, "Nubian languages"},
|
||||||
|
{"nwc", NULL, "Classical Newari; Old Newari; Classical Nepal Bhasa"},
|
||||||
|
{"nya", "ny", "Chichewa; Chewa; Nyanja"},
|
||||||
|
{"nym", NULL, "Nyamwezi"},
|
||||||
|
{"nyn", NULL, "Nyankole"},
|
||||||
|
{"nyo", NULL, "Nyoro"},
|
||||||
|
{"nzi", NULL, "Nzima"},
|
||||||
|
{"oci", "oc", "Occitan (post 1500); Proven\u00c7al"},
|
||||||
|
{"oji", "oj", "Ojibwa"},
|
||||||
|
{"ori", "or", "Oriya"},
|
||||||
|
{"orm", "om", "Oromo"},
|
||||||
|
{"osa", NULL, "Osage"},
|
||||||
|
{"oss", "os", "Ossetian; Ossetic"},
|
||||||
|
{"ota", NULL, "Turkish, Ottoman (1500-1928)"},
|
||||||
|
{"oto", NULL, "Otomian languages"},
|
||||||
|
{"paa", NULL, "Papuan (Other)"},
|
||||||
|
{"pag", NULL, "Pangasinan"},
|
||||||
|
{"pal", NULL, "Pahlavi"},
|
||||||
|
{"pam", NULL, "Pampanga"},
|
||||||
|
{"pan", "pa", "Panjabi; Punjabi"},
|
||||||
|
{"pap", NULL, "Papiamento"},
|
||||||
|
{"pau", NULL, "Palauan"},
|
||||||
|
{"peo", NULL, "Persian, Old (ca.600-400 B.C.)"},
|
||||||
|
{"per/fas", "fa", "Persian"}, // dual codes
|
||||||
|
{"phi", NULL, "Philippine (Other)"},
|
||||||
|
{"phn", NULL, "Phoenician"},
|
||||||
|
{"pli", "pi", "Pali"},
|
||||||
|
{"pol", "pl", "Polish"},
|
||||||
|
{"pon", NULL, "Pohnpeian"},
|
||||||
|
{"por", "pt", "Portuguese"},
|
||||||
|
{"pra", NULL, "Prakrit languages"},
|
||||||
|
{"pro", NULL, "Proven\u00c7al, Old (to 1500)"},
|
||||||
|
{"pus", "ps", "Pushto"},
|
||||||
|
//{ "qaa-qtz", NULL, "Reserved for local use" },
|
||||||
|
{"que", "qu", "Quechua"},
|
||||||
|
{"raj", NULL, "Rajasthani"},
|
||||||
|
{"rap", NULL, "Rapanui"},
|
||||||
|
{"rar", NULL, "Rarotongan"},
|
||||||
|
{"roa", NULL, "Romance (Other)"},
|
||||||
|
{"roh", "rm", "Raeto-Romance"},
|
||||||
|
{"rom", NULL, "Romany"},
|
||||||
|
{"rum/ron", "ro", "Romanian"}, // dual codes
|
||||||
|
{"run", "rn", "Rundi"},
|
||||||
|
{"rup", NULL, "Aromanian; Arumanian; Macedo-Romanian"},
|
||||||
|
{"rus", "ru", "Russian"},
|
||||||
|
{"sad", NULL, "Sandawe"},
|
||||||
|
{"sag", "sg", "Sango"},
|
||||||
|
{"sah", NULL, "Yakut"},
|
||||||
|
{"sai", NULL, "South American Indian (Other)"},
|
||||||
|
{"sal", NULL, "Salishan languages"},
|
||||||
|
{"sam", NULL, "Samaritan Aramaic"},
|
||||||
|
{"san", "sa", "Sanskrit"},
|
||||||
|
{"sas", NULL, "Sasak"},
|
||||||
|
{"sat", NULL, "Santali"},
|
||||||
|
{"scn", NULL, "Sicilian"},
|
||||||
|
{"sco", NULL, "Scots"},
|
||||||
|
{"scr/hrv", "hr", "Croatian"}, // dual codes
|
||||||
|
{"sel", NULL, "Selkup"},
|
||||||
|
{"sem", NULL, "Semitic (Other)"},
|
||||||
|
{"sga", NULL, "Irish, Old (to 900)"},
|
||||||
|
{"sgn", NULL, "Sign Languages"},
|
||||||
|
{"shn", NULL, "Shan"},
|
||||||
|
{"sid", NULL, "Sidamo"},
|
||||||
|
{"sin", "si", "Sinhala; Sinhalese"},
|
||||||
|
{"sio", NULL, "Siouan languages"},
|
||||||
|
{"sit", NULL, "Sino-Tibetan (Other)"},
|
||||||
|
{"sla", NULL, "Slavic (Other)"},
|
||||||
|
{"slo/slk", "sk", "Slovak"}, // dual codes
|
||||||
|
{"slv", "sl", "Slovenian"},
|
||||||
|
{"sma", NULL, "Southern Sami"},
|
||||||
|
{"sme", "se", "Northern Sami"},
|
||||||
|
{"smi", NULL, "Sami languages (Other)"},
|
||||||
|
{"smj", NULL, "Lule Sami"},
|
||||||
|
{"smn", NULL, "Inari Sami"},
|
||||||
|
{"smo", "sm", "Samoan"},
|
||||||
|
{"sms", NULL, "Skolt Sami"},
|
||||||
|
{"sna", "sn", "Shona"},
|
||||||
|
{"snd", "sd", "Sindhi"},
|
||||||
|
{"snk", NULL, "Soninke"},
|
||||||
|
{"sog", NULL, "Sogdian"},
|
||||||
|
{"som", "so", "Somali"},
|
||||||
|
{"son", NULL, "Songhai"},
|
||||||
|
{"sot", "st", "Sotho, Southern"},
|
||||||
|
{"spa", "es", "Spanish; Castilian"},
|
||||||
|
{"srd", "sc", "Sardinian"},
|
||||||
|
{"srn", NULL, "Sranan Togo"},
|
||||||
|
{"scc/srp", "sr", "Serbian"}, // dual codes
|
||||||
|
{"srr", NULL, "Serer"},
|
||||||
|
{"ssa", NULL, "Nilo-Saharan (Other)"},
|
||||||
|
{"ssw", "ss", "Swati"},
|
||||||
|
{"suk", NULL, "Sukuma"},
|
||||||
|
{"sun", "su", "Sundanese"},
|
||||||
|
{"sus", NULL, "Susu"},
|
||||||
|
{"sux", NULL, "Sumerian"},
|
||||||
|
{"swa", "sw", "Swahili"},
|
||||||
|
{"swe", "sv", "Swedish"},
|
||||||
|
{"syr", NULL, "Syriac"},
|
||||||
|
{"tah", "ty", "Tahitian"},
|
||||||
|
{"tai", NULL, "Tai (Other)"},
|
||||||
|
{"tam", "ta", "Tamil"},
|
||||||
|
{"tat", "tt", "Tatar"},
|
||||||
|
{"tel", "te", "Telugu"},
|
||||||
|
{"tem", NULL, "Timne"},
|
||||||
|
{"ter", NULL, "Tereno"},
|
||||||
|
{"tet", NULL, "Tetum"},
|
||||||
|
{"tgk", "tg", "Tajik"},
|
||||||
|
{"tgl", "tl", "Tagalog"},
|
||||||
|
{"tha", "th", "Thai"},
|
||||||
|
{"tib/bod", "bo", "Tibetan"}, // dual codes
|
||||||
|
{"tig", NULL, "Tigre"},
|
||||||
|
{"tir", "ti", "Tigrinya"},
|
||||||
|
{"tiv", NULL, "Tiv"},
|
||||||
|
{"tkl", NULL, "Tokelau"},
|
||||||
|
{"tlh", NULL, "Klingon; tlhIngan-Hol"},
|
||||||
|
{"tli", NULL, "Tlingit"},
|
||||||
|
{"tmh", NULL, "Tamashek"},
|
||||||
|
{"tog", NULL, "Tonga (Nyasa)"},
|
||||||
|
{"ton", "to", "Tonga (Tonga Islands)"},
|
||||||
|
{"tpi", NULL, "Tok Pisin"},
|
||||||
|
{"tsi", NULL, "Tsimshian"},
|
||||||
|
{"tsn", "tn", "Tswana"},
|
||||||
|
{"tso", "ts", "Tsonga"},
|
||||||
|
{"tuk", "tk", "Turkmen"},
|
||||||
|
{"tum", NULL, "Tumbuka"},
|
||||||
|
{"tup", NULL, "Tupi languages"},
|
||||||
|
{"tur", "tr", "Turkish"},
|
||||||
|
{"tut", NULL, "Altaic (Other)"},
|
||||||
|
{"tvl", NULL, "Tuvalu"},
|
||||||
|
{"twi", "tw", "Twi"},
|
||||||
|
{"tyv", NULL, "Tuvinian"},
|
||||||
|
{"udm", NULL, "Udmurt"},
|
||||||
|
{"uga", NULL, "Ugaritic"},
|
||||||
|
{"uig", "ug", "Uighur; Uyghur"},
|
||||||
|
{"ukr", "uk", "Ukrainian"},
|
||||||
|
{"umb", NULL, "Umbundu"},
|
||||||
|
{"und", NULL, "Undetermined"},
|
||||||
|
{"urd", "ur", "Urdu"},
|
||||||
|
{"uzb", "uz", "Uzbek"},
|
||||||
|
{"vai", NULL, "Vai"},
|
||||||
|
{"ven", "ve", "Venda"},
|
||||||
|
{"vie", "vi", "Vietnamese"},
|
||||||
|
{"vol", "vo", "Volap\u00fck"},
|
||||||
|
{"vot", NULL, "Votic"},
|
||||||
|
{"wak", NULL, "Wakashan languages"},
|
||||||
|
{"wal", NULL, "Walamo"},
|
||||||
|
{"war", NULL, "Waray"},
|
||||||
|
{"was", NULL, "Washo"},
|
||||||
|
{"wel/cym", "cy", "Welsh"}, // //dual codes
|
||||||
|
{"wen", NULL, "Sorbian languages"},
|
||||||
|
{"wln", "wa", "Walloon"},
|
||||||
|
{"wol", "wo", "Wolof"},
|
||||||
|
{"xal", NULL, "Kalmyk; Oirat"},
|
||||||
|
{"xho", "xh", "Xhosa"},
|
||||||
|
{"yao", NULL, "Yao"},
|
||||||
|
{"yap", NULL, "Yapese"},
|
||||||
|
{"yid", "yi", "Yiddish"},
|
||||||
|
{"yor", "yo", "Yoruba"},
|
||||||
|
{"ypk", NULL, "Yupik languages"},
|
||||||
|
{"zap", NULL, "Zapotec"},
|
||||||
|
{"zen", NULL, "Zenaga"},
|
||||||
|
{"zha", "za", "Zhuang; Chuang"},
|
||||||
|
{"chi/zho", "zh", "Chinese"}, // dual codes
|
||||||
|
{"znd", NULL, "Zande"},
|
||||||
|
{"zul", "zu", "Zulu"},
|
||||||
|
{"zun", NULL, "Zuni"},
|
||||||
|
{"zxx", NULL, "No linguistic content"}};
|
||||||
|
|
||||||
|
m_ratings known_ratings[] = {
|
||||||
|
{"us-tv|TV-MA|600|", "TV-MA"},
|
||||||
|
{"us-tv|TV-14|500|", "TV-14"},
|
||||||
|
{"us-tv|TV-PG|400|", "TV-PG"},
|
||||||
|
{"us-tv|TV-G|300|", "TV-G"},
|
||||||
|
{"us-tv|TV-Y7|200|", "TV-Y7"},
|
||||||
|
{"us-tv|TV-Y|100|", "TV-Y"},
|
||||||
|
//{ "us-tv||0|", "not-applicable" }, //though its a valid flag &
|
||||||
|
// some files have this, AP won't be setting it.
|
||||||
|
{"mpaa|UNRATED|600|", "Unrated"},
|
||||||
|
{"mpaa|NC-17|500|", "NC-17"},
|
||||||
|
{"mpaa|R|400|", "R"},
|
||||||
|
{"mpaa|PG-13|300|", "PG-13"},
|
||||||
|
{"mpaa|PG|200|", "PG"},
|
||||||
|
{"mpaa|G|100|", "G"}
|
||||||
|
//{ "mpaa||0|", "not-applicable" } //see above
|
||||||
|
};
|
||||||
|
|
||||||
|
char *GenreIntToString(int genre) {
|
||||||
|
char *return_string = NULL;
|
||||||
|
if (genre > 0 &&
|
||||||
|
genre <= (int)(sizeof(ID3v1GenreList) / sizeof(*ID3v1GenreList))) {
|
||||||
|
return_string = (char *)ID3v1GenreList[genre - 1];
|
||||||
|
}
|
||||||
|
return return_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t StringGenreToInt(const char *genre_string) {
|
||||||
|
uint8_t return_genre = 0;
|
||||||
|
uint8_t total_genres =
|
||||||
|
(uint8_t)(sizeof(ID3v1GenreList) / sizeof(*ID3v1GenreList));
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < total_genres; i++) {
|
||||||
|
if (strcmp(genre_string, ID3v1GenreList[i]) == 0) {
|
||||||
|
return_genre =
|
||||||
|
i + 1; // the list starts at 0; the embedded genres start at 1
|
||||||
|
// fprintf(stdout, "Genre %s is %i\n", ID3v1GenreList[i], return_genre);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (return_genre > total_genres) {
|
||||||
|
return_genre = 0;
|
||||||
|
}
|
||||||
|
return return_genre;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ListGenresValues() {
|
||||||
|
uint8_t total_genres =
|
||||||
|
(uint8_t)(sizeof(ID3v1GenreList) / sizeof(*ID3v1GenreList));
|
||||||
|
fprintf(stdout, "\tAvailable standard genres - case sensitive.\n");
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < total_genres; i++) {
|
||||||
|
fprintf(stdout, "(%i.) %s\n", i + 1, ID3v1GenreList[i]);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
stiks *MatchStikString(const char *in_stik_string) {
|
||||||
|
stiks *matching_stik = NULL;
|
||||||
|
uint8_t total_known_stiks = (sizeof(stikArray) / sizeof(*stikArray));
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < total_known_stiks; i++) {
|
||||||
|
if (strcmp(in_stik_string, stikArray[i].stik_string) == 0) {
|
||||||
|
matching_stik = &stikArray[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return matching_stik;
|
||||||
|
}
|
||||||
|
|
||||||
|
stiks *MatchStikNumber(uint8_t in_stik_num) {
|
||||||
|
stiks *matching_stik = NULL;
|
||||||
|
uint8_t total_known_stiks = (sizeof(stikArray) / sizeof(*stikArray));
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < total_known_stiks; i++) {
|
||||||
|
if (stikArray[i].stik_number == in_stik_num) {
|
||||||
|
matching_stik = &stikArray[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return matching_stik;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ListStikValues() {
|
||||||
|
uint8_t total_known_stiks = (sizeof(stikArray) / sizeof(*stikArray));
|
||||||
|
fprintf(stdout,
|
||||||
|
"\tAvailable stik settings - case sensitive (number in "
|
||||||
|
"parens shows the stik value).\n");
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < total_known_stiks; i++) {
|
||||||
|
fprintf(stdout,
|
||||||
|
"(%u) %s\n",
|
||||||
|
stikArray[i].stik_number,
|
||||||
|
stikArray[i].stik_string);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sfIDs *MatchStoreFrontNumber(uint32_t storefrontnum) {
|
||||||
|
sfIDs *matching_sfID = NULL;
|
||||||
|
uint8_t total_known_sfs = (sizeof(storefronts) / sizeof(*storefronts));
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < total_known_sfs; i++) {
|
||||||
|
if (storefronts[i].storefront_number == storefrontnum) {
|
||||||
|
matching_sfID = &storefronts[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return matching_sfID;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MatchLanguageCode(const char *in_code) {
|
||||||
|
bool matching_lang = false;
|
||||||
|
uint16_t total_known_langs =
|
||||||
|
(uint16_t)(sizeof(known_languages) / sizeof(*known_languages));
|
||||||
|
|
||||||
|
for (uint16_t i = 0; i < total_known_langs; i++) {
|
||||||
|
if (strncmp(in_code, known_languages[i].iso639_2_code, 3) == 0) {
|
||||||
|
matching_lang = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (strlen(known_languages[i].iso639_2_code) > 3) {
|
||||||
|
if (strncmp(in_code, known_languages[i].iso639_2_code + 4, 3) == 0) {
|
||||||
|
matching_lang = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return matching_lang;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ListLanguageCodes() {
|
||||||
|
uint16_t total_known_langs =
|
||||||
|
(uint16_t)(sizeof(known_languages) / sizeof(*known_languages));
|
||||||
|
fprintf(stdout,
|
||||||
|
"\tAvailable language codes\nISO639-2 code ... English name:\n");
|
||||||
|
|
||||||
|
for (uint16_t i = 0; i < total_known_langs; i++) {
|
||||||
|
fprintf(stdout,
|
||||||
|
" %s ... %s\n",
|
||||||
|
known_languages[i].iso639_2_code,
|
||||||
|
known_languages[i].language_in_english);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ListMediaRatings() {
|
||||||
|
uint16_t total_known_ratings =
|
||||||
|
(uint16_t)(sizeof(known_ratings) / sizeof(*known_ratings));
|
||||||
|
fprintf(stdout, "\tAvailable ratings for the U.S. rating system:\n");
|
||||||
|
|
||||||
|
for (uint16_t i = 0; i < total_known_ratings; i++) {
|
||||||
|
fprintf(stdout, " %s\n", known_ratings[i].media_rating_cli_str);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ListTVGenreIDValues() {
|
||||||
|
uint16_t total_genreidtv = (uint16_t)(sizeof(genreidtv) / sizeof(*genreidtv));
|
||||||
|
fprintf(stdout, "\tAvailable iTunes TV Genre IDs:\n");
|
||||||
|
|
||||||
|
for (uint16_t i = 0; i < total_genreidtv; i++) {
|
||||||
|
fprintf(stdout,
|
||||||
|
"(%u) %s\n",
|
||||||
|
genreidtv[i].genre_id_tv_value,
|
||||||
|
genreidtv[i].genre_id_tv_string);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ListMovieGenreIDValues() {
|
||||||
|
uint16_t total_genreidmovie =
|
||||||
|
(uint16_t)(sizeof(genreidmovie) / sizeof(*genreidmovie));
|
||||||
|
fprintf(stdout, "\tAvailable iTunes Movie Genre IDs:\n");
|
||||||
|
|
||||||
|
for (uint16_t i = 0; i < total_genreidmovie; i++) {
|
||||||
|
fprintf(stdout,
|
||||||
|
"(%u) %s\n",
|
||||||
|
genreidmovie[i].genre_id_movie_value,
|
||||||
|
genreidmovie[i].genre_id_movie_string);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *Expand_cli_mediastring(const char *cli_rating) {
|
||||||
|
const char *media_rating = NULL;
|
||||||
|
uint16_t total_known_ratings =
|
||||||
|
(uint16_t)(sizeof(known_ratings) / sizeof(*known_ratings));
|
||||||
|
uint8_t rating_len = strlen(cli_rating);
|
||||||
|
|
||||||
|
for (uint16_t i = 0; i < total_known_ratings; i++) {
|
||||||
|
if (strncasecmp(known_ratings[i].media_rating_cli_str,
|
||||||
|
cli_rating,
|
||||||
|
rating_len + 1) == 0) {
|
||||||
|
media_rating = known_ratings[i].media_rating;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return media_rating;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ID32 for ID3 frame functions
|
||||||
|
char *ID3GenreIntToString(int genre) {
|
||||||
|
char *return_string = NULL;
|
||||||
|
if (genre >= 0 && genre <= 79) {
|
||||||
|
return_string = (char *)ID3v1GenreList[genre];
|
||||||
|
}
|
||||||
|
return return_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ID3StringGenreToInt(const char *genre_string) {
|
||||||
|
uint8_t return_genre = 0xFF;
|
||||||
|
uint8_t total_genres = 80;
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < total_genres; i++) {
|
||||||
|
if (strcmp(genre_string, ID3v1GenreList[i]) == 0) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (return_genre > total_genres) {
|
||||||
|
return_genre = 0xFF;
|
||||||
|
}
|
||||||
|
return return_genre;
|
||||||
|
}
|
||||||
95
src/compress.cpp
Normal file
95
src/compress.cpp
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
//==================================================================//
|
||||||
|
/*
|
||||||
|
AtomicParsley - compress.cpp
|
||||||
|
|
||||||
|
AtomicParsley is GPL software; you can freely distribute,
|
||||||
|
redistribute, modify & use under the terms of the GNU General
|
||||||
|
Public License; either version 2 or its successor.
|
||||||
|
|
||||||
|
AtomicParsley is distributed under the GPL "AS IS", without
|
||||||
|
any warranty; without the implied warranty of merchantability
|
||||||
|
or fitness for either an expressed or implied particular purpose.
|
||||||
|
|
||||||
|
Please see the included GNU General Public License (GPL) for
|
||||||
|
your rights and further details; see the file COPYING. If you
|
||||||
|
cannot, write to the Free Software Foundation, 59 Temple Place
|
||||||
|
Suite 330, Boston, MA 02111-1307, USA. Or www.fsf.org
|
||||||
|
|
||||||
|
Copyright (C) 2006-2007 puck_lock
|
||||||
|
with contributions from others; see the CREDITS file
|
||||||
|
*/
|
||||||
|
//==================================================================//
|
||||||
|
|
||||||
|
#include "AtomicParsley.h"
|
||||||
|
#ifdef HAVE_ZLIB_H
|
||||||
|
#include <zlib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void *zalloc(void *opaque, unsigned int items, unsigned int size) {
|
||||||
|
return calloc(items, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void zfree(void *opaque, void *ptr) { free(ptr); }
|
||||||
|
|
||||||
|
/*----------------------
|
||||||
|
APar_zlib_inflate
|
||||||
|
in_buffer - pointer to already compressed data
|
||||||
|
in_buf_len - length of compressed data
|
||||||
|
out_buffer - pointer to a buffer to store decompressed/inflated data
|
||||||
|
out_buf_len - length of the out_buffer/max allowable decompressed size
|
||||||
|
|
||||||
|
fill
|
||||||
|
----------------------*/
|
||||||
|
void APar_zlib_inflate(char *in_buffer,
|
||||||
|
uint32_t in_buf_len,
|
||||||
|
char *out_buffer,
|
||||||
|
uint32_t out_buf_len) {
|
||||||
|
#if defined HAVE_ZLIB_H
|
||||||
|
z_stream zlib;
|
||||||
|
|
||||||
|
memset(&zlib, 0, sizeof(zlib));
|
||||||
|
|
||||||
|
// Decompress to another buffer
|
||||||
|
zlib.zalloc = zalloc;
|
||||||
|
zlib.zfree = zfree;
|
||||||
|
zlib.opaque = NULL;
|
||||||
|
zlib.avail_out = out_buf_len + 1;
|
||||||
|
zlib.next_out = (unsigned char *)out_buffer;
|
||||||
|
zlib.avail_in = in_buf_len;
|
||||||
|
zlib.next_in = (unsigned char *)in_buffer;
|
||||||
|
inflateInit(&zlib);
|
||||||
|
inflate(&zlib, Z_PARTIAL_FLUSH);
|
||||||
|
inflateEnd(&zlib);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t APar_zlib_deflate(char *in_buffer,
|
||||||
|
uint32_t in_buf_len,
|
||||||
|
char *out_buffer,
|
||||||
|
uint32_t out_buf_len) {
|
||||||
|
uint32_t compressed_bytes = 0;
|
||||||
|
|
||||||
|
#if defined HAVE_ZLIB_H
|
||||||
|
z_stream zlib;
|
||||||
|
|
||||||
|
memset(&zlib, 0, sizeof(zlib));
|
||||||
|
|
||||||
|
// Compress(default level 6) to another buffer
|
||||||
|
zlib.zalloc = zalloc;
|
||||||
|
zlib.zfree = zfree;
|
||||||
|
zlib.opaque = NULL;
|
||||||
|
zlib.avail_out = out_buf_len + 1;
|
||||||
|
zlib.next_out = (unsigned char *)out_buffer;
|
||||||
|
zlib.avail_in = in_buf_len;
|
||||||
|
zlib.next_in = (unsigned char *)in_buffer;
|
||||||
|
zlib.total_out = 0;
|
||||||
|
deflateInit(&zlib, Z_DEFAULT_COMPRESSION);
|
||||||
|
if (Z_STREAM_END == deflate(&zlib, Z_FINISH)) {
|
||||||
|
compressed_bytes = zlib.total_out;
|
||||||
|
deflateEnd(&zlib);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return compressed_bytes;
|
||||||
|
}
|
||||||
1785
src/extracts.cpp
Normal file
1785
src/extracts.cpp
Normal file
File diff suppressed because it is too large
Load Diff
981
src/extras/getopt.c
Normal file
981
src/extras/getopt.c
Normal file
@ -0,0 +1,981 @@
|
|||||||
|
/* Getopt for GNU.
|
||||||
|
NOTE: getopt is now part of the C library, so if you don't know what
|
||||||
|
"Keep this file name-space clean" means, talk to drepper@gnu.org
|
||||||
|
before changing it!
|
||||||
|
|
||||||
|
Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98
|
||||||
|
Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
NOTE: The canonical source of this file is maintained with the GNU C Library.
|
||||||
|
Bugs can be reported to bug-glibc@gnu.org.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by the
|
||||||
|
Free Software Foundation; either version 2, or (at your option) any
|
||||||
|
later version.
|
||||||
|
|
||||||
|
This program 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||||
|
USA. */
|
||||||
|
|
||||||
|
/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
|
||||||
|
Ditto for AIX 3.2 and <stdlib.h>. */
|
||||||
|
#ifndef _NO_PROTO
|
||||||
|
# define _NO_PROTO
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined __STDC__ || !__STDC__
|
||||||
|
/* This is a separate conditional since some stdc systems
|
||||||
|
reject `defined (const)'. */
|
||||||
|
# ifndef const
|
||||||
|
# define const
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/* Comment out all this code if we are using the GNU C Library, and are not
|
||||||
|
actually compiling the library itself. This code is part of the GNU C
|
||||||
|
Library, but also included in many other GNU distributions. Compiling
|
||||||
|
and linking in this code is a waste when using the GNU C library
|
||||||
|
(especially if it is a shared library). Rather than having every GNU
|
||||||
|
program understand `configure --with-gnu-libc' and omit the object files,
|
||||||
|
it is simpler to just do this in the source for each such file. */
|
||||||
|
|
||||||
|
#define GETOPT_INTERFACE_VERSION 2
|
||||||
|
#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
|
||||||
|
# include <gnu-versions.h>
|
||||||
|
# if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
|
||||||
|
# define ELIDE_CODE
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ELIDE_CODE
|
||||||
|
|
||||||
|
|
||||||
|
/* This needs to come after some library #include
|
||||||
|
to get __GNU_LIBRARY__ defined. */
|
||||||
|
#ifdef __GNU_LIBRARY__
|
||||||
|
/* Don't include stdlib.h for non-GNU C libraries because some of them
|
||||||
|
contain conflicting prototypes for getopt. */
|
||||||
|
# include <stdlib.h>
|
||||||
|
# include <unistd.h>
|
||||||
|
#endif /* GNU C library. */
|
||||||
|
|
||||||
|
#ifdef VMS
|
||||||
|
# include <unixlib.h>
|
||||||
|
# if HAVE_STRING_H - 0
|
||||||
|
# include <string.h>
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _
|
||||||
|
/* This is for other GNU distributions with internationalized messages.
|
||||||
|
When compiling libc, the _ macro is predefined. */
|
||||||
|
# ifdef HAVE_LIBINTL_H
|
||||||
|
# include <libintl.h>
|
||||||
|
# define _(msgid) gettext (msgid)
|
||||||
|
# else
|
||||||
|
# define _(msgid) (msgid)
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* This version of `getopt' appears to the caller like standard Unix `getopt'
|
||||||
|
but it behaves differently for the user, since it allows the user
|
||||||
|
to intersperse the options with the other arguments.
|
||||||
|
|
||||||
|
As `getopt' works, it permutes the elements of ARGV so that,
|
||||||
|
when it is done, all the options precede everything else. Thus
|
||||||
|
all application programs are extended to handle flexible argument order.
|
||||||
|
|
||||||
|
Setting the environment variable POSIXLY_CORRECT disables permutation.
|
||||||
|
Then the behavior is completely standard.
|
||||||
|
|
||||||
|
GNU application programs can use a third alternative mode in which
|
||||||
|
they can distinguish the relative order of options and other arguments. */
|
||||||
|
|
||||||
|
#include "getopt.h"
|
||||||
|
|
||||||
|
/* For communication from `getopt' to the caller.
|
||||||
|
When `getopt' finds an option that takes an argument,
|
||||||
|
the argument value is returned here.
|
||||||
|
Also, when `ordering' is RETURN_IN_ORDER,
|
||||||
|
each non-option ARGV-element is returned here. */
|
||||||
|
|
||||||
|
char *optarg = NULL;
|
||||||
|
|
||||||
|
/* Index in ARGV of the next element to be scanned.
|
||||||
|
This is used for communication to and from the caller
|
||||||
|
and for communication between successive calls to `getopt'.
|
||||||
|
|
||||||
|
On entry to `getopt', zero means this is the first call; initialize.
|
||||||
|
|
||||||
|
When `getopt' returns -1, this is the index of the first of the
|
||||||
|
non-option elements that the caller should itself scan.
|
||||||
|
|
||||||
|
Otherwise, `optind' communicates from one call to the next
|
||||||
|
how much of ARGV has been scanned so far. */
|
||||||
|
|
||||||
|
/* 1003.2 says this must be 1 before any call. */
|
||||||
|
int optind = 1;
|
||||||
|
|
||||||
|
/* Formerly, initialization of getopt depended on optind==0, which
|
||||||
|
causes problems with re-calling getopt as programs generally don't
|
||||||
|
know that. */
|
||||||
|
|
||||||
|
int __getopt_initialized = 0;
|
||||||
|
|
||||||
|
/* The next char to be scanned in the option-element
|
||||||
|
in which the last option character we returned was found.
|
||||||
|
This allows us to pick up the scan where we left off.
|
||||||
|
|
||||||
|
If this is zero, or a null string, it means resume the scan
|
||||||
|
by advancing to the next ARGV-element. */
|
||||||
|
|
||||||
|
static char *nextchar;
|
||||||
|
|
||||||
|
/* Callers store zero here to inhibit the error message
|
||||||
|
for unrecognized options. */
|
||||||
|
|
||||||
|
int opterr = 1;
|
||||||
|
|
||||||
|
/* Set to an option character which was unrecognized.
|
||||||
|
This must be initialized on some systems to avoid linking in the
|
||||||
|
system's own getopt implementation. */
|
||||||
|
|
||||||
|
int optopt = '?';
|
||||||
|
|
||||||
|
/* Describe how to deal with options that follow non-option ARGV-elements.
|
||||||
|
|
||||||
|
If the caller did not specify anything,
|
||||||
|
the default is REQUIRE_ORDER if the environment variable
|
||||||
|
POSIXLY_CORRECT is defined, PERMUTE otherwise.
|
||||||
|
|
||||||
|
REQUIRE_ORDER means don't recognize them as options;
|
||||||
|
stop option processing when the first non-option is seen.
|
||||||
|
This is what Unix does.
|
||||||
|
This mode of operation is selected by either setting the environment
|
||||||
|
variable POSIXLY_CORRECT, or using `+' as the first character
|
||||||
|
of the list of option characters.
|
||||||
|
|
||||||
|
PERMUTE is the default. We permute the contents of ARGV as we scan,
|
||||||
|
so that eventually all the non-options are at the end. This allows options
|
||||||
|
to be given in any order, even with programs that were not written to
|
||||||
|
expect this.
|
||||||
|
|
||||||
|
RETURN_IN_ORDER is an option available to programs that were written
|
||||||
|
to expect options and other ARGV-elements in any order and that care about
|
||||||
|
the ordering of the two. We describe each non-option ARGV-element
|
||||||
|
as if it were the argument of an option with character code 1.
|
||||||
|
Using `-' as the first character of the list of option characters
|
||||||
|
selects this mode of operation.
|
||||||
|
|
||||||
|
The special argument `--' forces an end of option-scanning regardless
|
||||||
|
of the value of `ordering'. In the case of RETURN_IN_ORDER, only
|
||||||
|
`--' can cause `getopt' to return -1 with `optind' != ARGC. */
|
||||||
|
|
||||||
|
static enum
|
||||||
|
{
|
||||||
|
REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
|
||||||
|
} ordering;
|
||||||
|
|
||||||
|
/* Value of POSIXLY_CORRECT environment variable. */
|
||||||
|
static char *posixly_correct;
|
||||||
|
|
||||||
|
#ifdef __GNU_LIBRARY__
|
||||||
|
/* We want to avoid inclusion of string.h with non-GNU libraries
|
||||||
|
because there are many ways it can cause trouble.
|
||||||
|
On some systems, it contains special magic macros that don't work
|
||||||
|
in GCC. */
|
||||||
|
# include <string.h>
|
||||||
|
# define my_index strchr
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define HAVE_STRING_H 1
|
||||||
|
# if HAVE_STRING_H
|
||||||
|
# include <string.h>
|
||||||
|
# else
|
||||||
|
# include <strings.h>
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/* Avoid depending on library functions or files
|
||||||
|
whose names are inconsistent. */
|
||||||
|
|
||||||
|
#ifndef getenv
|
||||||
|
extern char *getenv ();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static char *
|
||||||
|
my_index (str, chr)
|
||||||
|
const char *str;
|
||||||
|
int chr;
|
||||||
|
{
|
||||||
|
while (*str)
|
||||||
|
{
|
||||||
|
if (*str == chr)
|
||||||
|
return (char *) str;
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If using GCC, we can safely declare strlen this way.
|
||||||
|
If not using GCC, it is ok not to declare it. */
|
||||||
|
#ifdef __GNUC__
|
||||||
|
/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
|
||||||
|
That was relevant to code that was here before. */
|
||||||
|
# if (!defined __STDC__ || !__STDC__) && !defined strlen
|
||||||
|
/* gcc with -traditional declares the built-in strlen to return int,
|
||||||
|
and has done so at least since version 2.4.5. -- rms. */
|
||||||
|
extern int strlen (const char *);
|
||||||
|
# endif /* not __STDC__ */
|
||||||
|
#endif /* __GNUC__ */
|
||||||
|
|
||||||
|
#endif /* not __GNU_LIBRARY__ */
|
||||||
|
|
||||||
|
/* Handle permutation of arguments. */
|
||||||
|
|
||||||
|
/* Describe the part of ARGV that contains non-options that have
|
||||||
|
been skipped. `first_nonopt' is the index in ARGV of the first of them;
|
||||||
|
`last_nonopt' is the index after the last of them. */
|
||||||
|
|
||||||
|
static int first_nonopt;
|
||||||
|
static int last_nonopt;
|
||||||
|
|
||||||
|
#ifdef _LIBC
|
||||||
|
/* Bash 2.0 gives us an environment variable containing flags
|
||||||
|
indicating ARGV elements that should not be considered arguments. */
|
||||||
|
|
||||||
|
/* Defined in getopt_init.c */
|
||||||
|
extern char *__getopt_nonoption_flags;
|
||||||
|
|
||||||
|
static int nonoption_flags_max_len;
|
||||||
|
static int nonoption_flags_len;
|
||||||
|
|
||||||
|
static int original_argc;
|
||||||
|
static char *const *original_argv;
|
||||||
|
|
||||||
|
/* Make sure the environment variable bash 2.0 puts in the environment
|
||||||
|
is valid for the getopt call we must make sure that the ARGV passed
|
||||||
|
to getopt is that one passed to the process. */
|
||||||
|
static void
|
||||||
|
__attribute__ ((unused))
|
||||||
|
store_args_and_env (int argc, char *const *argv)
|
||||||
|
{
|
||||||
|
/* XXX This is no good solution. We should rather copy the args so
|
||||||
|
that we can compare them later. But we must not use malloc(3). */
|
||||||
|
original_argc = argc;
|
||||||
|
original_argv = argv;
|
||||||
|
}
|
||||||
|
# ifdef text_set_element
|
||||||
|
text_set_element (__libc_subinit, store_args_and_env);
|
||||||
|
# endif /* text_set_element */
|
||||||
|
|
||||||
|
# define SWAP_FLAGS(ch1, ch2) \
|
||||||
|
if (nonoption_flags_len > 0) \
|
||||||
|
{ \
|
||||||
|
char __tmp = __getopt_nonoption_flags[ch1]; \
|
||||||
|
__getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \
|
||||||
|
__getopt_nonoption_flags[ch2] = __tmp; \
|
||||||
|
}
|
||||||
|
#else /* !_LIBC */
|
||||||
|
# define SWAP_FLAGS(ch1, ch2)
|
||||||
|
#endif /* _LIBC */
|
||||||
|
|
||||||
|
/* Exchange two adjacent subsequences of ARGV.
|
||||||
|
One subsequence is elements [first_nonopt,last_nonopt)
|
||||||
|
which contains all the non-options that have been skipped so far.
|
||||||
|
The other is elements [last_nonopt,optind), which contains all
|
||||||
|
the options processed since those non-options were skipped.
|
||||||
|
|
||||||
|
`first_nonopt' and `last_nonopt' are relocated so that they describe
|
||||||
|
the new indices of the non-options in ARGV after they are moved. */
|
||||||
|
|
||||||
|
#if defined __STDC__ && __STDC__
|
||||||
|
static void exchange (char **);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void
|
||||||
|
exchange (argv)
|
||||||
|
char **argv;
|
||||||
|
{
|
||||||
|
int bottom = first_nonopt;
|
||||||
|
int middle = last_nonopt;
|
||||||
|
int top = optind;
|
||||||
|
char *tem;
|
||||||
|
|
||||||
|
/* Exchange the shorter segment with the far end of the longer segment.
|
||||||
|
That puts the shorter segment into the right place.
|
||||||
|
It leaves the longer segment in the right place overall,
|
||||||
|
but it consists of two parts that need to be swapped next. */
|
||||||
|
|
||||||
|
#ifdef _LIBC
|
||||||
|
/* First make sure the handling of the `__getopt_nonoption_flags'
|
||||||
|
string can work normally. Our top argument must be in the range
|
||||||
|
of the string. */
|
||||||
|
if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len)
|
||||||
|
{
|
||||||
|
/* We must extend the array. The user plays games with us and
|
||||||
|
presents new arguments. */
|
||||||
|
char *new_str = malloc (top + 1);
|
||||||
|
if (new_str == NULL)
|
||||||
|
nonoption_flags_len = nonoption_flags_max_len = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memset (__mempcpy (new_str, __getopt_nonoption_flags,
|
||||||
|
nonoption_flags_max_len),
|
||||||
|
'\0', top + 1 - nonoption_flags_max_len);
|
||||||
|
nonoption_flags_max_len = top + 1;
|
||||||
|
__getopt_nonoption_flags = new_str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
while (top > middle && middle > bottom)
|
||||||
|
{
|
||||||
|
if (top - middle > middle - bottom)
|
||||||
|
{
|
||||||
|
/* Bottom segment is the short one. */
|
||||||
|
int len = middle - bottom;
|
||||||
|
register int i;
|
||||||
|
|
||||||
|
/* Swap it with the top part of the top segment. */
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
tem = argv[bottom + i];
|
||||||
|
argv[bottom + i] = argv[top - (middle - bottom) + i];
|
||||||
|
argv[top - (middle - bottom) + i] = tem;
|
||||||
|
SWAP_FLAGS (bottom + i, top - (middle - bottom) + i);
|
||||||
|
}
|
||||||
|
/* Exclude the moved bottom segment from further swapping. */
|
||||||
|
top -= len;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Top segment is the short one. */
|
||||||
|
int len = top - middle;
|
||||||
|
register int i;
|
||||||
|
|
||||||
|
/* Swap it with the bottom part of the bottom segment. */
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
tem = argv[bottom + i];
|
||||||
|
argv[bottom + i] = argv[middle + i];
|
||||||
|
argv[middle + i] = tem;
|
||||||
|
SWAP_FLAGS (bottom + i, middle + i);
|
||||||
|
}
|
||||||
|
/* Exclude the moved top segment from further swapping. */
|
||||||
|
bottom += len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update records for the slots the non-options now occupy. */
|
||||||
|
|
||||||
|
first_nonopt += (optind - last_nonopt);
|
||||||
|
last_nonopt = optind;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize the internal data when the first call is made. */
|
||||||
|
|
||||||
|
#if defined __STDC__ && __STDC__
|
||||||
|
static const char *_getopt_initialize (int, char *const *, const char *);
|
||||||
|
#endif
|
||||||
|
static const char *
|
||||||
|
_getopt_initialize (argc, argv, optstring)
|
||||||
|
int argc;
|
||||||
|
char *const *argv;
|
||||||
|
const char *optstring;
|
||||||
|
{
|
||||||
|
/* Start processing options with ARGV-element 1 (since ARGV-element 0
|
||||||
|
is the program name); the sequence of previously skipped
|
||||||
|
non-option ARGV-elements is empty. */
|
||||||
|
|
||||||
|
first_nonopt = last_nonopt = optind;
|
||||||
|
|
||||||
|
nextchar = NULL;
|
||||||
|
|
||||||
|
posixly_correct = getenv ("POSIXLY_CORRECT");
|
||||||
|
|
||||||
|
/* Determine how to handle the ordering of options and nonoptions. */
|
||||||
|
|
||||||
|
if (optstring[0] == '-')
|
||||||
|
{
|
||||||
|
ordering = RETURN_IN_ORDER;
|
||||||
|
++optstring;
|
||||||
|
}
|
||||||
|
else if (optstring[0] == '+')
|
||||||
|
{
|
||||||
|
ordering = REQUIRE_ORDER;
|
||||||
|
++optstring;
|
||||||
|
}
|
||||||
|
else if (posixly_correct != NULL)
|
||||||
|
ordering = REQUIRE_ORDER;
|
||||||
|
else
|
||||||
|
ordering = PERMUTE;
|
||||||
|
|
||||||
|
#ifdef _LIBC
|
||||||
|
if (posixly_correct == NULL
|
||||||
|
&& argc == original_argc && argv == original_argv)
|
||||||
|
{
|
||||||
|
if (nonoption_flags_max_len == 0)
|
||||||
|
{
|
||||||
|
if (__getopt_nonoption_flags == NULL
|
||||||
|
|| __getopt_nonoption_flags[0] == '\0')
|
||||||
|
nonoption_flags_max_len = -1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const char *orig_str = __getopt_nonoption_flags;
|
||||||
|
int len = nonoption_flags_max_len = strlen (orig_str);
|
||||||
|
if (nonoption_flags_max_len < argc)
|
||||||
|
nonoption_flags_max_len = argc;
|
||||||
|
__getopt_nonoption_flags =
|
||||||
|
(char *) malloc (nonoption_flags_max_len);
|
||||||
|
if (__getopt_nonoption_flags == NULL)
|
||||||
|
nonoption_flags_max_len = -1;
|
||||||
|
else
|
||||||
|
memset (__mempcpy (__getopt_nonoption_flags, orig_str, len),
|
||||||
|
'\0', nonoption_flags_max_len - len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nonoption_flags_len = nonoption_flags_max_len;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
nonoption_flags_len = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return optstring;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Scan elements of ARGV (whose length is ARGC) for option characters
|
||||||
|
given in OPTSTRING.
|
||||||
|
|
||||||
|
If an element of ARGV starts with '-', and is not exactly "-" or "--",
|
||||||
|
then it is an option element. The characters of this element
|
||||||
|
(aside from the initial '-') are option characters. If `getopt'
|
||||||
|
is called repeatedly, it returns successively each of the option characters
|
||||||
|
from each of the option elements.
|
||||||
|
|
||||||
|
If `getopt' finds another option character, it returns that character,
|
||||||
|
updating `optind' and `nextchar' so that the next call to `getopt' can
|
||||||
|
resume the scan with the following option character or ARGV-element.
|
||||||
|
|
||||||
|
If there are no more option characters, `getopt' returns -1.
|
||||||
|
Then `optind' is the index in ARGV of the first ARGV-element
|
||||||
|
that is not an option. (The ARGV-elements have been permuted
|
||||||
|
so that those that are not options now come last.)
|
||||||
|
|
||||||
|
OPTSTRING is a string containing the legitimate option characters.
|
||||||
|
If an option character is seen that is not listed in OPTSTRING,
|
||||||
|
return '?' after printing an error message. If you set `opterr' to
|
||||||
|
zero, the error message is suppressed but we still return '?'.
|
||||||
|
|
||||||
|
If a char in OPTSTRING is followed by a colon, that means it wants an arg,
|
||||||
|
so the following text in the same ARGV-element, or the text of the following
|
||||||
|
ARGV-element, is returned in `optarg'. Two colons mean an option that
|
||||||
|
wants an optional arg; if there is text in the current ARGV-element,
|
||||||
|
it is returned in `optarg', otherwise `optarg' is set to zero.
|
||||||
|
|
||||||
|
If OPTSTRING starts with `-' or `+', it requests different methods of
|
||||||
|
handling the non-option ARGV-elements.
|
||||||
|
See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
|
||||||
|
|
||||||
|
Long-named options begin with `--' instead of `-'.
|
||||||
|
Their names may be abbreviated as long as the abbreviation is unique
|
||||||
|
or is an exact match for some defined option. If they have an
|
||||||
|
argument, it follows the option name in the same ARGV-element, separated
|
||||||
|
from the option name by a `=', or else the in next ARGV-element.
|
||||||
|
When `getopt' finds a long-named option, it returns 0 if that option's
|
||||||
|
`flag' field is nonzero, the value of the option's `val' field
|
||||||
|
if the `flag' field is zero.
|
||||||
|
|
||||||
|
The elements of ARGV aren't really const, because we permute them.
|
||||||
|
But we pretend they're const in the prototype to be compatible
|
||||||
|
with other systems.
|
||||||
|
|
||||||
|
LONGOPTS is a vector of `struct option' terminated by an
|
||||||
|
element containing a name which is zero.
|
||||||
|
|
||||||
|
LONGIND returns the index in LONGOPT of the long-named option found.
|
||||||
|
It is only valid when a long-named option has been found by the most
|
||||||
|
recent call.
|
||||||
|
|
||||||
|
If LONG_ONLY is nonzero, '-' as well as '--' can introduce
|
||||||
|
long-named options. */
|
||||||
|
|
||||||
|
int
|
||||||
|
_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
|
||||||
|
int argc;
|
||||||
|
char *const *argv;
|
||||||
|
const char *optstring;
|
||||||
|
const struct option *longopts;
|
||||||
|
int *longind;
|
||||||
|
int long_only;
|
||||||
|
{
|
||||||
|
optarg = NULL;
|
||||||
|
|
||||||
|
if (optind == 0 || !__getopt_initialized)
|
||||||
|
{
|
||||||
|
if (optind == 0)
|
||||||
|
optind = 1; /* Don't scan ARGV[0], the program name. */
|
||||||
|
optstring = _getopt_initialize (argc, argv, optstring);
|
||||||
|
__getopt_initialized = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test whether ARGV[optind] points to a non-option argument.
|
||||||
|
Either it does not have option syntax, or there is an environment flag
|
||||||
|
from the shell indicating it is not an option. The later information
|
||||||
|
is only used when the used in the GNU libc. */
|
||||||
|
#ifdef _LIBC
|
||||||
|
# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \
|
||||||
|
|| (optind < nonoption_flags_len \
|
||||||
|
&& __getopt_nonoption_flags[optind] == '1'))
|
||||||
|
#else
|
||||||
|
# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0')
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (nextchar == NULL || *nextchar == '\0')
|
||||||
|
{
|
||||||
|
/* Advance to the next ARGV-element. */
|
||||||
|
|
||||||
|
/* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been
|
||||||
|
moved back by the user (who may also have changed the arguments). */
|
||||||
|
if (last_nonopt > optind)
|
||||||
|
last_nonopt = optind;
|
||||||
|
if (first_nonopt > optind)
|
||||||
|
first_nonopt = optind;
|
||||||
|
|
||||||
|
if (ordering == PERMUTE)
|
||||||
|
{
|
||||||
|
/* If we have just processed some options following some non-options,
|
||||||
|
exchange them so that the options come first. */
|
||||||
|
|
||||||
|
if (first_nonopt != last_nonopt && last_nonopt != optind)
|
||||||
|
exchange ((char **) argv);
|
||||||
|
else if (last_nonopt != optind)
|
||||||
|
first_nonopt = optind;
|
||||||
|
|
||||||
|
/* Skip any additional non-options
|
||||||
|
and extend the range of non-options previously skipped. */
|
||||||
|
|
||||||
|
while (optind < argc && NONOPTION_P)
|
||||||
|
optind++;
|
||||||
|
last_nonopt = optind;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The special ARGV-element `--' means premature end of options.
|
||||||
|
Skip it like a null option,
|
||||||
|
then exchange with previous non-options as if it were an option,
|
||||||
|
then skip everything else like a non-option. */
|
||||||
|
|
||||||
|
if (optind != argc && !strcmp (argv[optind], "--"))
|
||||||
|
{
|
||||||
|
optind++;
|
||||||
|
|
||||||
|
if (first_nonopt != last_nonopt && last_nonopt != optind)
|
||||||
|
exchange ((char **) argv);
|
||||||
|
else if (first_nonopt == last_nonopt)
|
||||||
|
first_nonopt = optind;
|
||||||
|
last_nonopt = argc;
|
||||||
|
|
||||||
|
optind = argc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we have done all the ARGV-elements, stop the scan
|
||||||
|
and back over any non-options that we skipped and permuted. */
|
||||||
|
|
||||||
|
if (optind == argc)
|
||||||
|
{
|
||||||
|
/* Set the next-arg-index to point at the non-options
|
||||||
|
that we previously skipped, so the caller will digest them. */
|
||||||
|
if (first_nonopt != last_nonopt)
|
||||||
|
optind = first_nonopt;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we have come to a non-option and did not permute it,
|
||||||
|
either stop the scan or describe it to the caller and pass it by. */
|
||||||
|
|
||||||
|
if (NONOPTION_P)
|
||||||
|
{
|
||||||
|
if (ordering == REQUIRE_ORDER)
|
||||||
|
return -1;
|
||||||
|
optarg = argv[optind++];
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We have found another option-ARGV-element.
|
||||||
|
Skip the initial punctuation. */
|
||||||
|
|
||||||
|
nextchar = (argv[optind] + 1
|
||||||
|
+ (longopts != NULL && argv[optind][1] == '-'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Decode the current option-ARGV-element. */
|
||||||
|
|
||||||
|
/* Check whether the ARGV-element is a long option.
|
||||||
|
|
||||||
|
If long_only and the ARGV-element has the form "-f", where f is
|
||||||
|
a valid short option, don't consider it an abbreviated form of
|
||||||
|
a long option that starts with f. Otherwise there would be no
|
||||||
|
way to give the -f short option.
|
||||||
|
|
||||||
|
On the other hand, if there's a long option "fubar" and
|
||||||
|
the ARGV-element is "-fu", do consider that an abbreviation of
|
||||||
|
the long option, just like "--fu", and not "-f" with arg "u".
|
||||||
|
|
||||||
|
This distinction seems to be the most useful approach. */
|
||||||
|
|
||||||
|
if (longopts != NULL
|
||||||
|
&& (argv[optind][1] == '-'
|
||||||
|
|| (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
|
||||||
|
{
|
||||||
|
char *nameend;
|
||||||
|
const struct option *p;
|
||||||
|
const struct option *pfound = NULL;
|
||||||
|
int exact = 0;
|
||||||
|
int ambig = 0;
|
||||||
|
int indfound = -1;
|
||||||
|
int option_index;
|
||||||
|
|
||||||
|
for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
|
||||||
|
/* Do nothing. */ ;
|
||||||
|
|
||||||
|
/* Test all long options for either exact match
|
||||||
|
or abbreviated matches. */
|
||||||
|
for (p = longopts, option_index = 0; p->name; p++, option_index++)
|
||||||
|
if (!strncmp (p->name, nextchar, nameend - nextchar))
|
||||||
|
{
|
||||||
|
if ((unsigned int) (nameend - nextchar)
|
||||||
|
== (unsigned int) strlen (p->name))
|
||||||
|
{
|
||||||
|
/* Exact match found. */
|
||||||
|
pfound = p;
|
||||||
|
indfound = option_index;
|
||||||
|
exact = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (pfound == NULL)
|
||||||
|
{
|
||||||
|
/* First nonexact match found. */
|
||||||
|
pfound = p;
|
||||||
|
indfound = option_index;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* Second or later nonexact match found. */
|
||||||
|
ambig = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ambig && !exact)
|
||||||
|
{
|
||||||
|
if (opterr)
|
||||||
|
fprintf (stderr, _("%s: option `%s' is ambiguous\n"),
|
||||||
|
argv[0], argv[optind]);
|
||||||
|
nextchar += strlen (nextchar);
|
||||||
|
optind++;
|
||||||
|
optopt = 0;
|
||||||
|
return '?';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pfound != NULL)
|
||||||
|
{
|
||||||
|
option_index = indfound;
|
||||||
|
optind++;
|
||||||
|
if (*nameend)
|
||||||
|
{
|
||||||
|
/* Don't test has_arg with >, because some C compilers don't
|
||||||
|
allow it to be used on enums. */
|
||||||
|
if (pfound->has_arg)
|
||||||
|
optarg = nameend + 1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (opterr)
|
||||||
|
if (argv[optind - 1][1] == '-')
|
||||||
|
/* --option */
|
||||||
|
fprintf (stderr,
|
||||||
|
_("%s: option `--%s' doesn't allow an argument\n"),
|
||||||
|
argv[0], pfound->name);
|
||||||
|
else
|
||||||
|
/* +option or -option */
|
||||||
|
fprintf (stderr,
|
||||||
|
_("%s: option `%c%s' doesn't allow an argument\n"),
|
||||||
|
argv[0], argv[optind - 1][0], pfound->name);
|
||||||
|
|
||||||
|
nextchar += strlen (nextchar);
|
||||||
|
|
||||||
|
optopt = pfound->val;
|
||||||
|
return '?';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (pfound->has_arg == 1)
|
||||||
|
{
|
||||||
|
if (optind < argc)
|
||||||
|
optarg = argv[optind++];
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (opterr)
|
||||||
|
fprintf (stderr,
|
||||||
|
_("%s: option `%s' requires an argument\n"),
|
||||||
|
argv[0], argv[optind - 1]);
|
||||||
|
nextchar += strlen (nextchar);
|
||||||
|
optopt = pfound->val;
|
||||||
|
return optstring[0] == ':' ? ':' : '?';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nextchar += strlen (nextchar);
|
||||||
|
if (longind != NULL)
|
||||||
|
*longind = option_index;
|
||||||
|
if (pfound->flag)
|
||||||
|
{
|
||||||
|
*(pfound->flag) = pfound->val;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return pfound->val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Can't find it as a long option. If this is not getopt_long_only,
|
||||||
|
or the option starts with '--' or is not a valid short
|
||||||
|
option, then it's an error.
|
||||||
|
Otherwise interpret it as a short option. */
|
||||||
|
if (!long_only || argv[optind][1] == '-'
|
||||||
|
|| my_index (optstring, *nextchar) == NULL)
|
||||||
|
{
|
||||||
|
if (opterr)
|
||||||
|
{
|
||||||
|
if (argv[optind][1] == '-')
|
||||||
|
/* --option */
|
||||||
|
fprintf (stderr, _("%s: unrecognized option `--%s'\n"),
|
||||||
|
argv[0], nextchar);
|
||||||
|
else
|
||||||
|
/* +option or -option */
|
||||||
|
fprintf (stderr, _("%s: unrecognized option `%c%s'\n"),
|
||||||
|
argv[0], argv[optind][0], nextchar);
|
||||||
|
}
|
||||||
|
nextchar = (char *) "";
|
||||||
|
optind++;
|
||||||
|
optopt = 0;
|
||||||
|
return '?';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Look at and handle the next short option-character. */
|
||||||
|
|
||||||
|
{
|
||||||
|
char c = *nextchar++;
|
||||||
|
char *temp = my_index (optstring, c);
|
||||||
|
|
||||||
|
/* Increment `optind' when we start to process its last character. */
|
||||||
|
if (*nextchar == '\0')
|
||||||
|
++optind;
|
||||||
|
|
||||||
|
if (temp == NULL || c == ':')
|
||||||
|
{
|
||||||
|
if (opterr)
|
||||||
|
{
|
||||||
|
if (posixly_correct)
|
||||||
|
/* 1003.2 specifies the format of this message. */
|
||||||
|
fprintf (stderr, _("%s: illegal option -- %c\n"),
|
||||||
|
argv[0], c);
|
||||||
|
else
|
||||||
|
fprintf (stderr, _("%s: invalid option -- %c\n"),
|
||||||
|
argv[0], c);
|
||||||
|
}
|
||||||
|
optopt = c;
|
||||||
|
return '?';
|
||||||
|
}
|
||||||
|
/* Convenience. Treat POSIX -W foo same as long option --foo */
|
||||||
|
if (temp[0] == 'W' && temp[1] == ';')
|
||||||
|
{
|
||||||
|
char *nameend;
|
||||||
|
const struct option *p;
|
||||||
|
const struct option *pfound = NULL;
|
||||||
|
int exact = 0;
|
||||||
|
int ambig = 0;
|
||||||
|
int indfound = 0;
|
||||||
|
int option_index;
|
||||||
|
|
||||||
|
/* This is an option that requires an argument. */
|
||||||
|
if (*nextchar != '\0')
|
||||||
|
{
|
||||||
|
optarg = nextchar;
|
||||||
|
/* If we end this ARGV-element by taking the rest as an arg,
|
||||||
|
we must advance to the next element now. */
|
||||||
|
optind++;
|
||||||
|
}
|
||||||
|
else if (optind == argc)
|
||||||
|
{
|
||||||
|
if (opterr)
|
||||||
|
{
|
||||||
|
/* 1003.2 specifies the format of this message. */
|
||||||
|
fprintf (stderr, _("%s: option requires an argument -- %c\n"),
|
||||||
|
argv[0], c);
|
||||||
|
}
|
||||||
|
optopt = c;
|
||||||
|
if (optstring[0] == ':')
|
||||||
|
c = ':';
|
||||||
|
else
|
||||||
|
c = '?';
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* We already incremented `optind' once;
|
||||||
|
increment it again when taking next ARGV-elt as argument. */
|
||||||
|
optarg = argv[optind++];
|
||||||
|
|
||||||
|
/* optarg is now the argument, see if it's in the
|
||||||
|
table of longopts. */
|
||||||
|
|
||||||
|
for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++)
|
||||||
|
/* Do nothing. */ ;
|
||||||
|
|
||||||
|
/* Test all long options for either exact match
|
||||||
|
or abbreviated matches. */
|
||||||
|
for (p = longopts, option_index = 0; p->name; p++, option_index++)
|
||||||
|
if (!strncmp (p->name, nextchar, nameend - nextchar))
|
||||||
|
{
|
||||||
|
if ((unsigned int) (nameend - nextchar) == strlen (p->name))
|
||||||
|
{
|
||||||
|
/* Exact match found. */
|
||||||
|
pfound = p;
|
||||||
|
indfound = option_index;
|
||||||
|
exact = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (pfound == NULL)
|
||||||
|
{
|
||||||
|
/* First nonexact match found. */
|
||||||
|
pfound = p;
|
||||||
|
indfound = option_index;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* Second or later nonexact match found. */
|
||||||
|
ambig = 1;
|
||||||
|
}
|
||||||
|
if (ambig && !exact)
|
||||||
|
{
|
||||||
|
if (opterr)
|
||||||
|
fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"),
|
||||||
|
argv[0], argv[optind]);
|
||||||
|
nextchar += strlen (nextchar);
|
||||||
|
optind++;
|
||||||
|
return '?';
|
||||||
|
}
|
||||||
|
if (pfound != NULL)
|
||||||
|
{
|
||||||
|
option_index = indfound;
|
||||||
|
if (*nameend)
|
||||||
|
{
|
||||||
|
/* Don't test has_arg with >, because some C compilers don't
|
||||||
|
allow it to be used on enums. */
|
||||||
|
if (pfound->has_arg)
|
||||||
|
optarg = nameend + 1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (opterr)
|
||||||
|
fprintf (stderr, _("\
|
||||||
|
%s: option `-W %s' doesn't allow an argument\n"),
|
||||||
|
argv[0], pfound->name);
|
||||||
|
|
||||||
|
nextchar += strlen (nextchar);
|
||||||
|
return '?';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (pfound->has_arg == 1)
|
||||||
|
{
|
||||||
|
if (optind < argc)
|
||||||
|
optarg = argv[optind++];
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (opterr)
|
||||||
|
fprintf (stderr,
|
||||||
|
_("%s: option `%s' requires an argument\n"),
|
||||||
|
argv[0], argv[optind - 1]);
|
||||||
|
nextchar += strlen (nextchar);
|
||||||
|
return optstring[0] == ':' ? ':' : '?';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nextchar += strlen (nextchar);
|
||||||
|
if (longind != NULL)
|
||||||
|
*longind = option_index;
|
||||||
|
if (pfound->flag)
|
||||||
|
{
|
||||||
|
*(pfound->flag) = pfound->val;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return pfound->val;
|
||||||
|
}
|
||||||
|
nextchar = NULL;
|
||||||
|
return 'W'; /* Let the application handle it. */
|
||||||
|
}
|
||||||
|
if (temp[1] == ':')
|
||||||
|
{
|
||||||
|
if (temp[2] == ':')
|
||||||
|
{
|
||||||
|
/* This is an option that accepts an argument optionally. */
|
||||||
|
if (*nextchar != '\0')
|
||||||
|
{
|
||||||
|
optarg = nextchar;
|
||||||
|
optind++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
optarg = NULL;
|
||||||
|
nextchar = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* This is an option that requires an argument. */
|
||||||
|
if (*nextchar != '\0')
|
||||||
|
{
|
||||||
|
optarg = nextchar;
|
||||||
|
/* If we end this ARGV-element by taking the rest as an arg,
|
||||||
|
we must advance to the next element now. */
|
||||||
|
optind++;
|
||||||
|
}
|
||||||
|
else if (optind == argc)
|
||||||
|
{
|
||||||
|
if (opterr)
|
||||||
|
{
|
||||||
|
/* 1003.2 specifies the format of this message. */
|
||||||
|
fprintf (stderr,
|
||||||
|
_("%s: option requires an argument -- %c\n"),
|
||||||
|
argv[0], c);
|
||||||
|
}
|
||||||
|
optopt = c;
|
||||||
|
if (optstring[0] == ':')
|
||||||
|
c = ':';
|
||||||
|
else
|
||||||
|
c = '?';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* We already incremented `optind' once;
|
||||||
|
increment it again when taking next ARGV-elt as argument. */
|
||||||
|
optarg = argv[optind++];
|
||||||
|
nextchar = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
getopt (argc, argv, optstring)
|
||||||
|
int argc;
|
||||||
|
char *const *argv;
|
||||||
|
const char *optstring;
|
||||||
|
{
|
||||||
|
return _getopt_internal (argc, argv, optstring,
|
||||||
|
(const struct option *) 0,
|
||||||
|
(int *) 0,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* Not ELIDE_CODE. */
|
||||||
127
src/extras/getopt.h
Normal file
127
src/extras/getopt.h
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
/* Declarations for getopt.
|
||||||
|
Copyright (C) 1989,90,91,92,93,94,96,97 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
NOTE: The canonical source of this file is maintained with the GNU C Library.
|
||||||
|
Bugs can be reported to bug-glibc@gnu.org.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by the
|
||||||
|
Free Software Foundation; either version 2, or (at your option) any
|
||||||
|
later version.
|
||||||
|
|
||||||
|
This program 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||||
|
USA. */
|
||||||
|
|
||||||
|
#ifndef _GETOPT_H
|
||||||
|
#define _GETOPT_H 1
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* For communication from `getopt' to the caller.
|
||||||
|
When `getopt' finds an option that takes an argument,
|
||||||
|
the argument value is returned here.
|
||||||
|
Also, when `ordering' is RETURN_IN_ORDER,
|
||||||
|
each non-option ARGV-element is returned here. */
|
||||||
|
|
||||||
|
extern char *optarg;
|
||||||
|
|
||||||
|
/* Index in ARGV of the next element to be scanned.
|
||||||
|
This is used for communication to and from the caller
|
||||||
|
and for communication between successive calls to `getopt'.
|
||||||
|
|
||||||
|
On entry to `getopt', zero means this is the first call; initialize.
|
||||||
|
|
||||||
|
When `getopt' returns -1, this is the index of the first of the
|
||||||
|
non-option elements that the caller should itself scan.
|
||||||
|
|
||||||
|
Otherwise, `optind' communicates from one call to the next
|
||||||
|
how much of ARGV has been scanned so far. */
|
||||||
|
|
||||||
|
extern int optind;
|
||||||
|
|
||||||
|
/* Callers store zero here to inhibit the error message `getopt' prints
|
||||||
|
for unrecognized options. */
|
||||||
|
|
||||||
|
extern int opterr;
|
||||||
|
|
||||||
|
/* Set to an option character which was unrecognized. */
|
||||||
|
|
||||||
|
extern int optopt;
|
||||||
|
|
||||||
|
/* Describe the long-named options requested by the application.
|
||||||
|
The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
|
||||||
|
of `struct option' terminated by an element containing a name which is
|
||||||
|
zero.
|
||||||
|
|
||||||
|
The field `has_arg' is:
|
||||||
|
no_argument (or 0) if the option does not take an argument,
|
||||||
|
required_argument (or 1) if the option requires an argument,
|
||||||
|
optional_argument (or 2) if the option takes an optional argument.
|
||||||
|
|
||||||
|
If the field `flag' is not NULL, it points to a variable that is set
|
||||||
|
to the value given in the field `val' when the option is found, but
|
||||||
|
left unchanged if the option is not found.
|
||||||
|
|
||||||
|
To have a long-named option do something other than set an `int' to
|
||||||
|
a compiled-in constant, such as set a value from `optarg', set the
|
||||||
|
option's `flag' field to zero and its `val' field to a nonzero
|
||||||
|
value (the equivalent single-letter option character, if there is
|
||||||
|
one). For long options that have a zero `flag' field, `getopt'
|
||||||
|
returns the contents of the `val' field. */
|
||||||
|
|
||||||
|
struct option
|
||||||
|
{
|
||||||
|
#if defined (__STDC__) && __STDC__
|
||||||
|
const char *name;
|
||||||
|
#else
|
||||||
|
char *name;
|
||||||
|
#endif
|
||||||
|
/* has_arg can't be an enum because some compilers complain about
|
||||||
|
type mismatches in all the code that assumes it is an int. */
|
||||||
|
int has_arg;
|
||||||
|
int *flag;
|
||||||
|
int val;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Names for the values of the `has_arg' field of `struct option'. */
|
||||||
|
|
||||||
|
#define no_argument 0
|
||||||
|
#define required_argument 1
|
||||||
|
#define optional_argument 2
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __GNU_LIBRARY__
|
||||||
|
/* Many other libraries have conflicting prototypes for getopt, with
|
||||||
|
differences in the consts, in stdlib.h. To avoid compilation
|
||||||
|
errors, only prototype getopt for the GNU C library. */
|
||||||
|
extern int getopt (int argc, char *const *argv, const char *shortopts);
|
||||||
|
#else /* not __GNU_LIBRARY__ */
|
||||||
|
extern int getopt ();
|
||||||
|
#endif /* __GNU_LIBRARY__ */
|
||||||
|
extern int getopt_long (int argc, char *const *argv, const char *shortopts,
|
||||||
|
const struct option *longopts, int *longind);
|
||||||
|
extern int getopt_long_only (int argc, char *const *argv,
|
||||||
|
const char *shortopts,
|
||||||
|
const struct option *longopts, int *longind);
|
||||||
|
|
||||||
|
/* Internal only. Users should not call this directly. */
|
||||||
|
extern int _getopt_internal (int argc, char *const *argv,
|
||||||
|
const char *shortopts,
|
||||||
|
const struct option *longopts, int *longind,
|
||||||
|
int long_only);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* getopt.h */
|
||||||
87
src/extras/getopt1.c
Normal file
87
src/extras/getopt1.c
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/* getopt_long and getopt_long_only entry points for GNU getopt.
|
||||||
|
Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98
|
||||||
|
Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
NOTE: The canonical source of this file is maintained with the GNU C Library.
|
||||||
|
Bugs can be reported to bug-glibc@gnu.org.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by the
|
||||||
|
Free Software Foundation; either version 2, or (at your option) any
|
||||||
|
later version.
|
||||||
|
|
||||||
|
This program 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||||
|
USA. */
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "getopt.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/* Comment out all this code if we are using the GNU C Library, and are not
|
||||||
|
actually compiling the library itself. This code is part of the GNU C
|
||||||
|
Library, but also included in many other GNU distributions. Compiling
|
||||||
|
and linking in this code is a waste when using the GNU C library
|
||||||
|
(especially if it is a shared library). Rather than having every GNU
|
||||||
|
program understand `configure --with-gnu-libc' and omit the object files,
|
||||||
|
it is simpler to just do this in the source for each such file. */
|
||||||
|
|
||||||
|
#define GETOPT_INTERFACE_VERSION 2
|
||||||
|
#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
|
||||||
|
#include <gnu-versions.h>
|
||||||
|
#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
|
||||||
|
#define ELIDE_CODE
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ELIDE_CODE
|
||||||
|
|
||||||
|
|
||||||
|
/* This needs to come after some library #include
|
||||||
|
to get __GNU_LIBRARY__ defined. */
|
||||||
|
#ifdef __GNU_LIBRARY__
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef NULL
|
||||||
|
#define NULL 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int
|
||||||
|
getopt_long (int argc,
|
||||||
|
char *const *argv,
|
||||||
|
const char *options,
|
||||||
|
const struct option *long_options,
|
||||||
|
int *opt_index)
|
||||||
|
{
|
||||||
|
return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Like getopt_long, but '-' as well as '--' can indicate a long option.
|
||||||
|
If an option that starts with '-' (not '--') doesn't match a long option,
|
||||||
|
but does match a short option, it is parsed as a short option
|
||||||
|
instead. */
|
||||||
|
|
||||||
|
int
|
||||||
|
getopt_long_only (int argc,
|
||||||
|
char *const *argv,
|
||||||
|
const char *options,
|
||||||
|
const struct option *long_options,
|
||||||
|
int *opt_index)
|
||||||
|
{
|
||||||
|
return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* Not ELIDE_CODE. */
|
||||||
993
src/iconv.cpp
Normal file
993
src/iconv.cpp
Normal file
@ -0,0 +1,993 @@
|
|||||||
|
//==================================================================//
|
||||||
|
/*
|
||||||
|
AtomicParsley - iconv.cpp
|
||||||
|
|
||||||
|
AtomicParsley is GPL software; you can freely distribute,
|
||||||
|
redistribute, modify & use under the terms of the GNU General
|
||||||
|
Public License; either version 2 or its successor.
|
||||||
|
|
||||||
|
AtomicParsley is distributed under the GPL "AS IS", without
|
||||||
|
any warranty; without the implied warranty of merchantability
|
||||||
|
or fitness for either an expressed or implied particular purpose.
|
||||||
|
|
||||||
|
Please see the included GNU General Public License (GPL) for
|
||||||
|
your rights and further details; see the file COPYING. If you
|
||||||
|
cannot, write to the Free Software Foundation, 59 Temple Place
|
||||||
|
Suite 330, Boston, MA 02111-1307, USA. Or www.fsf.org
|
||||||
|
|
||||||
|
Copyright (C) 2005-2007 puck_lock
|
||||||
|
with contributions from others; see the CREDITS file
|
||||||
|
*/
|
||||||
|
//==================================================================//
|
||||||
|
//==================================================================//
|
||||||
|
// utf conversion functions from libxml2
|
||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (C) 1998-2003 Daniel Veillard. All Rights Reserved.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is fur-
|
||||||
|
nished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
|
||||||
|
NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
DANIEL VEILLARD BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON-
|
||||||
|
NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
Except as contained in this notice, the name of Daniel Veillard shall not
|
||||||
|
be used in advertising or otherwise to promote the sale, use or other deal-
|
||||||
|
ings in this Software without prior written authorization from him.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Original code for IsoLatin1 and UTF-16 by "Martin J. Duerst" <duerst@w3.org>
|
||||||
|
|
||||||
|
#include "AtomicParsley.h"
|
||||||
|
|
||||||
|
const unsigned short cp437upperbytes[128] = {
|
||||||
|
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA,
|
||||||
|
0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, 0x00C9, 0x00E6,
|
||||||
|
0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC,
|
||||||
|
0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192, 0x00E1, 0x00ED, 0x00F3, 0x00FA,
|
||||||
|
0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC,
|
||||||
|
0x00A1, 0x00AB, 0x00BB, 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561,
|
||||||
|
0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B,
|
||||||
|
0x2510, 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F,
|
||||||
|
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, 0x2568,
|
||||||
|
0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518,
|
||||||
|
0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, 0x03B1, 0x00DF, 0x0393,
|
||||||
|
0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4,
|
||||||
|
0x221E, 0x03C6, 0x03B5, 0x2229, 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320,
|
||||||
|
0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2,
|
||||||
|
0x25A0, 0x00A0};
|
||||||
|
|
||||||
|
const unsigned short cp850upperbytes[128] = {
|
||||||
|
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA,
|
||||||
|
0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, 0x00C9, 0x00E6,
|
||||||
|
0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC,
|
||||||
|
0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192, 0x00E1, 0x00ED, 0x00F3, 0x00FA,
|
||||||
|
0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC,
|
||||||
|
0x00A1, 0x00AB, 0x00BB, 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1,
|
||||||
|
0x00C2, 0x00C0, 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5,
|
||||||
|
0x2510, 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3,
|
||||||
|
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, 0x00F0,
|
||||||
|
0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x0131, 0x00CD, 0x00CE, 0x00CF, 0x2518,
|
||||||
|
0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580, 0x00D3, 0x00DF, 0x00D4,
|
||||||
|
0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE, 0x00DE, 0x00DA, 0x00DB, 0x00D9,
|
||||||
|
0x00FD, 0x00DD, 0x00AF, 0x00B4, 0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6,
|
||||||
|
0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2,
|
||||||
|
0x25A0, 0x00A0};
|
||||||
|
|
||||||
|
const unsigned short cp852upperbytes[128] = {
|
||||||
|
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x016F, 0x0107, 0x00E7, 0x0142,
|
||||||
|
0x00EB, 0x0150, 0x0151, 0x00EE, 0x0179, 0x00C4, 0x0106, 0x00C9, 0x0139,
|
||||||
|
0x013A, 0x00F4, 0x00F6, 0x013D, 0x013E, 0x015A, 0x015B, 0x00D6, 0x00DC,
|
||||||
|
0x0164, 0x0165, 0x0141, 0x00D7, 0x010D, 0x00E1, 0x00ED, 0x00F3, 0x00FA,
|
||||||
|
0x0104, 0x0105, 0x017D, 0x017E, 0x0118, 0x0119, 0x00AC, 0x017A, 0x010C,
|
||||||
|
0x015F, 0x00AB, 0x00BB, 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1,
|
||||||
|
0x00C2, 0x011A, 0x015E, 0x2563, 0x2551, 0x2557, 0x255D, 0x017B, 0x017C,
|
||||||
|
0x2510, 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0102, 0x0103,
|
||||||
|
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, 0x0111,
|
||||||
|
0x0110, 0x010E, 0x00CB, 0x010F, 0x0147, 0x00CD, 0x00CE, 0x011B, 0x2518,
|
||||||
|
0x250C, 0x2588, 0x2584, 0x0162, 0x016E, 0x2580, 0x00D3, 0x00DF, 0x00D4,
|
||||||
|
0x0143, 0x0144, 0x0148, 0x0160, 0x0161, 0x0154, 0x00DA, 0x0155, 0x0170,
|
||||||
|
0x00FD, 0x00DD, 0x0163, 0x00B4, 0x00AD, 0x02DD, 0x02DB, 0x02C7, 0x02D8,
|
||||||
|
0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x02D9, 0x0171, 0x0158, 0x0159,
|
||||||
|
0x25A0, 0x00A0};
|
||||||
|
|
||||||
|
const unsigned short cp855upperbytes[128] = {
|
||||||
|
0x0452, 0x0402, 0x0453, 0x0403, 0x0451, 0x0401, 0x0454, 0x0404, 0x0455,
|
||||||
|
0x0405, 0x0456, 0x0406, 0x0457, 0x0407, 0x0458, 0x0408, 0x0459, 0x0409,
|
||||||
|
0x045A, 0x040A, 0x045B, 0x040B, 0x045C, 0x040C, 0x045E, 0x040E, 0x045F,
|
||||||
|
0x040F, 0x044E, 0x042E, 0x044A, 0x042A, 0x0430, 0x0410, 0x0431, 0x0411,
|
||||||
|
0x0446, 0x0426, 0x0434, 0x0414, 0x0435, 0x0415, 0x0444, 0x0424, 0x0433,
|
||||||
|
0x0413, 0x00AB, 0x00BB, 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0445,
|
||||||
|
0x0425, 0x0438, 0x0418, 0x2563, 0x2551, 0x2557, 0x255D, 0x0439, 0x0419,
|
||||||
|
0x2510, 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x043A, 0x041A,
|
||||||
|
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, 0x043B,
|
||||||
|
0x041B, 0x043C, 0x041C, 0x043D, 0x041D, 0x043E, 0x041E, 0x043F, 0x2518,
|
||||||
|
0x250C, 0x2588, 0x2584, 0x041F, 0x044F, 0x2580, 0x042F, 0x0440, 0x0420,
|
||||||
|
0x0441, 0x0421, 0x0442, 0x0422, 0x0443, 0x0423, 0x0436, 0x0416, 0x0432,
|
||||||
|
0x0412, 0x044C, 0x042C, 0x2116, 0x00AD, 0x044B, 0x042B, 0x0437, 0x0417,
|
||||||
|
0x0448, 0x0428, 0x044D, 0x042D, 0x0449, 0x0429, 0x0447, 0x0427, 0x00A7,
|
||||||
|
0x25A0, 0x00A0};
|
||||||
|
|
||||||
|
const unsigned short cp858upperbytes[128] = {
|
||||||
|
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA,
|
||||||
|
0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, 0x00C9, 0x00E6,
|
||||||
|
0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC,
|
||||||
|
0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192, 0x00E1, 0x00ED, 0x00F3, 0x00FA,
|
||||||
|
0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC,
|
||||||
|
0x00A1, 0x00AB, 0x00BB, 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1,
|
||||||
|
0x00C2, 0x00C0, 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5,
|
||||||
|
0x2510, 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3,
|
||||||
|
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, 0x00F0,
|
||||||
|
0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x20AC, 0x00CD, 0x00CE, 0x00CF, 0x2518,
|
||||||
|
0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580, 0x00D3, 0x00DF, 0x00D4,
|
||||||
|
0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE, 0x00DE, 0x00DA, 0x00DB, 0x00D9,
|
||||||
|
0x00FD, 0x00DD, 0x00AF, 0x00B4, 0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6,
|
||||||
|
0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2,
|
||||||
|
0x25A0, 0x00A0};
|
||||||
|
|
||||||
|
//==================================================================//
|
||||||
|
// utf conversion functions from libxml2
|
||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (C) 1998-2003 Daniel Veillard. All Rights Reserved.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is fur-
|
||||||
|
nished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
|
||||||
|
NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
DANIEL VEILLARD BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON-
|
||||||
|
NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
Except as contained in this notice, the name of Daniel Veillard shall not
|
||||||
|
be used in advertising or otherwise to promote the sale, use or other deal-
|
||||||
|
ings in this Software without prior written authorization from him.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Original code for IsoLatin1 and UTF-16 by "Martin J. Duerst" <duerst@w3.org>
|
||||||
|
|
||||||
|
static int xmlLittleEndian =
|
||||||
|
#ifdef WORDS_BIGENDIAN
|
||||||
|
0
|
||||||
|
#else
|
||||||
|
1
|
||||||
|
#endif
|
||||||
|
;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* isolat1ToUTF8:
|
||||||
|
* @out: a pointer to an array of bytes to store the result
|
||||||
|
* @outlen: the length of @out
|
||||||
|
* @in: a pointer to an array of ISO Latin 1 chars
|
||||||
|
* @inlen: the length of @in
|
||||||
|
*
|
||||||
|
* Take a block of ISO Latin 1 chars in and try to convert it to an UTF-8
|
||||||
|
* block of chars out.
|
||||||
|
* Returns the number of bytes written if success, or -1 otherwise
|
||||||
|
* The value of @inlen after return is the number of octets consumed
|
||||||
|
* if the return value is positive, else unpredictable.
|
||||||
|
* The value of @outlen after return is the number of octets consumed.
|
||||||
|
*/
|
||||||
|
int isolat1ToUTF8(unsigned char *out,
|
||||||
|
int outlen,
|
||||||
|
const unsigned char *in,
|
||||||
|
int inlen) {
|
||||||
|
unsigned char *outstart = out;
|
||||||
|
const unsigned char *base = in;
|
||||||
|
unsigned char *outend;
|
||||||
|
const unsigned char *inend;
|
||||||
|
const unsigned char *instop;
|
||||||
|
|
||||||
|
if ((out == NULL) || (in == NULL) || (outlen == 0) || (inlen == 0))
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
outend = out + outlen;
|
||||||
|
inend = in + (inlen);
|
||||||
|
instop = inend;
|
||||||
|
|
||||||
|
while (in < inend && out < outend - 1) {
|
||||||
|
if (*in >= 0x80) {
|
||||||
|
*out++ = (((*in) >> 6) & 0x1F) | 0xC0;
|
||||||
|
*out++ = ((*in) & 0x3F) | 0x80;
|
||||||
|
++in;
|
||||||
|
}
|
||||||
|
if (instop - in > outend - out)
|
||||||
|
instop = in + (outend - out);
|
||||||
|
while (in < instop && *in < 0x80) {
|
||||||
|
*out++ = *in++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (in < inend && out < outend && *in < 0x80) {
|
||||||
|
*out++ = *in++;
|
||||||
|
}
|
||||||
|
outlen = out - outstart;
|
||||||
|
inlen = in - base;
|
||||||
|
return (outlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UTF8Toisolat1:
|
||||||
|
* @out: a pointer to an array of bytes to store the result
|
||||||
|
* @outlen: the length of @out
|
||||||
|
* @in: a pointer to an array of UTF-8 chars
|
||||||
|
* @inlen: the length of @in
|
||||||
|
*
|
||||||
|
* Take a block of UTF-8 chars in and try to convert it to an ISO Latin 1
|
||||||
|
* block of chars out.
|
||||||
|
*
|
||||||
|
* Returns the number of bytes written if success, -2 if the transcoding fails,
|
||||||
|
or -1 otherwise
|
||||||
|
* The value of @inlen after return is the number of octets consumed
|
||||||
|
* if the return value is positive, else unpredictable.
|
||||||
|
* The value of @outlen after return is the number of octets consumed.
|
||||||
|
*/
|
||||||
|
int UTF8Toisolat1(unsigned char *out,
|
||||||
|
int outlen,
|
||||||
|
const unsigned char *in,
|
||||||
|
int inlen) {
|
||||||
|
const unsigned char *processed = in;
|
||||||
|
const unsigned char *outend;
|
||||||
|
const unsigned char *outstart = out;
|
||||||
|
const unsigned char *instart = in;
|
||||||
|
const unsigned char *inend;
|
||||||
|
unsigned int c, d;
|
||||||
|
int trailing;
|
||||||
|
|
||||||
|
if ((out == NULL) || (outlen == 0) || (inlen == 0))
|
||||||
|
return (-1);
|
||||||
|
if (in == NULL) {
|
||||||
|
/*
|
||||||
|
* initialization nothing to do
|
||||||
|
*/
|
||||||
|
outlen = 0;
|
||||||
|
inlen = 0;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
inend = in + (inlen);
|
||||||
|
outend = out + (outlen);
|
||||||
|
while (in < inend) {
|
||||||
|
d = *in++;
|
||||||
|
if (d < 0x80) {
|
||||||
|
c = d;
|
||||||
|
trailing = 0;
|
||||||
|
} else if (d < 0xC0) {
|
||||||
|
/* trailing byte in leading position */
|
||||||
|
outlen = out - outstart;
|
||||||
|
inlen = processed - instart;
|
||||||
|
return (-2);
|
||||||
|
} else if (d < 0xE0) {
|
||||||
|
c = d & 0x1F;
|
||||||
|
trailing = 1;
|
||||||
|
} else if (d < 0xF0) {
|
||||||
|
c = d & 0x0F;
|
||||||
|
trailing = 2;
|
||||||
|
} else if (d < 0xF8) {
|
||||||
|
c = d & 0x07;
|
||||||
|
trailing = 3;
|
||||||
|
} else {
|
||||||
|
/* no chance for this in IsoLat1 */
|
||||||
|
outlen = out - outstart;
|
||||||
|
inlen = processed - instart;
|
||||||
|
return (-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inend - in < trailing) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; trailing; trailing--) {
|
||||||
|
if (in >= inend)
|
||||||
|
break;
|
||||||
|
if (((d = *in++) & 0xC0) != 0x80) {
|
||||||
|
outlen = out - outstart;
|
||||||
|
inlen = processed - instart;
|
||||||
|
return (-2);
|
||||||
|
}
|
||||||
|
c <<= 6;
|
||||||
|
c |= d & 0x3F;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* assertion: c is a single UTF-4 value */
|
||||||
|
if (c <= 0xFF) {
|
||||||
|
if (out >= outend)
|
||||||
|
break;
|
||||||
|
*out++ = c;
|
||||||
|
} else {
|
||||||
|
/* no chance for this in IsoLat1 */
|
||||||
|
outlen = out - outstart;
|
||||||
|
inlen = processed - instart;
|
||||||
|
return (-2);
|
||||||
|
}
|
||||||
|
processed = in;
|
||||||
|
}
|
||||||
|
outlen = out - outstart;
|
||||||
|
inlen = processed - instart;
|
||||||
|
return (outlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UTF16BEToUTF8:
|
||||||
|
* @out: a pointer to an array of bytes to store the result
|
||||||
|
* @outlen: the length of @out
|
||||||
|
* @inb: a pointer to an array of UTF-16 passed as a byte array
|
||||||
|
* @inlenb: the length of @in in UTF-16 chars
|
||||||
|
*
|
||||||
|
* Take a block of UTF-16 ushorts in and try to convert it to an UTF-8
|
||||||
|
* block of chars out. This function assumes the endian property
|
||||||
|
* is the same between the native type of this machine and the
|
||||||
|
* inputed one.
|
||||||
|
*
|
||||||
|
* Returns the number of bytes written, or -1 if lack of space, or -2
|
||||||
|
* if the transcoding fails (if *in is not a valid utf16 string)
|
||||||
|
* The value of *inlen after return is the number of octets consumed
|
||||||
|
* if the return value is positive, else unpredictable.
|
||||||
|
*/
|
||||||
|
int UTF16BEToUTF8(unsigned char *out,
|
||||||
|
int outlen,
|
||||||
|
const unsigned char *inb,
|
||||||
|
int inlenb) {
|
||||||
|
unsigned char *outstart = out;
|
||||||
|
const unsigned char *processed = inb;
|
||||||
|
unsigned char *outend = out + outlen;
|
||||||
|
unsigned short *in = (unsigned short *)inb;
|
||||||
|
unsigned short *inend;
|
||||||
|
unsigned int c, d, inlen;
|
||||||
|
unsigned char *tmp;
|
||||||
|
int bits;
|
||||||
|
|
||||||
|
if ((inlenb % 2) == 1)
|
||||||
|
(inlenb)--;
|
||||||
|
inlen = inlenb / 2;
|
||||||
|
inend = in + inlen;
|
||||||
|
while (in < inend) {
|
||||||
|
if (xmlLittleEndian) {
|
||||||
|
tmp = (unsigned char *)in;
|
||||||
|
c = *tmp++;
|
||||||
|
c = c << 8;
|
||||||
|
c = c | (unsigned int)*tmp;
|
||||||
|
in++;
|
||||||
|
} else {
|
||||||
|
c = *in++;
|
||||||
|
|
||||||
|
if (c == 0xFEFF) {
|
||||||
|
c = *in++; // skip BOM
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((c & 0xFC00) == 0xD800) { /* surrogates */
|
||||||
|
if (in >= inend) { /* (in > inend) shouldn't happens */
|
||||||
|
outlen = out - outstart;
|
||||||
|
inlenb = processed - inb;
|
||||||
|
return (-2);
|
||||||
|
}
|
||||||
|
if (xmlLittleEndian) {
|
||||||
|
tmp = (unsigned char *)in;
|
||||||
|
d = *tmp++;
|
||||||
|
d = d << 8;
|
||||||
|
d = d | (unsigned int)*tmp;
|
||||||
|
in++;
|
||||||
|
} else {
|
||||||
|
d = *in++;
|
||||||
|
}
|
||||||
|
if ((d & 0xFC00) == 0xDC00) {
|
||||||
|
c &= 0x03FF;
|
||||||
|
c <<= 10;
|
||||||
|
c |= d & 0x03FF;
|
||||||
|
c += 0x10000;
|
||||||
|
} else {
|
||||||
|
outlen = out - outstart;
|
||||||
|
inlenb = processed - inb;
|
||||||
|
return (-2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* assertion: c is a single UTF-4 value */
|
||||||
|
if (out >= outend)
|
||||||
|
break;
|
||||||
|
if (c < 0x80) {
|
||||||
|
*out++ = c;
|
||||||
|
bits = -6;
|
||||||
|
} else if (c < 0x800) {
|
||||||
|
*out++ = ((c >> 6) & 0x1F) | 0xC0;
|
||||||
|
bits = 0;
|
||||||
|
} else if (c < 0x10000) {
|
||||||
|
*out++ = ((c >> 12) & 0x0F) | 0xE0;
|
||||||
|
bits = 6;
|
||||||
|
} else {
|
||||||
|
*out++ = ((c >> 18) & 0x07) | 0xF0;
|
||||||
|
bits = 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; bits >= 0; bits -= 6) {
|
||||||
|
if (out >= outend)
|
||||||
|
break;
|
||||||
|
*out++ = ((c >> bits) & 0x3F) | 0x80;
|
||||||
|
}
|
||||||
|
processed = (const unsigned char *)in;
|
||||||
|
}
|
||||||
|
outlen = out - outstart;
|
||||||
|
inlenb = processed - inb;
|
||||||
|
return (outlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UTF8ToUTF16BE:
|
||||||
|
* @outb: a pointer to an array of bytes to store the result
|
||||||
|
* @outlen: the length of @outb
|
||||||
|
* @in: a pointer to an array of UTF-8 chars
|
||||||
|
* @inlen: the length of @in
|
||||||
|
*
|
||||||
|
* Take a block of UTF-8 chars in and try to convert it to an UTF-16BE
|
||||||
|
* block of chars out.
|
||||||
|
*
|
||||||
|
* Returns the number of byte written, or -1 by lack of space, or -2
|
||||||
|
* if the transcoding failed.
|
||||||
|
*/
|
||||||
|
int UTF8ToUTF16BE(unsigned char *outb,
|
||||||
|
int outlen,
|
||||||
|
const unsigned char *in,
|
||||||
|
int inlen) {
|
||||||
|
unsigned short *out = (unsigned short *)outb;
|
||||||
|
const unsigned char *processed = in;
|
||||||
|
const unsigned char *const instart = in;
|
||||||
|
unsigned short *outstart = out;
|
||||||
|
unsigned short *outend;
|
||||||
|
const unsigned char *inend = in + inlen;
|
||||||
|
unsigned int c, d;
|
||||||
|
int trailing;
|
||||||
|
unsigned char *tmp;
|
||||||
|
unsigned short tmp1, tmp2;
|
||||||
|
|
||||||
|
/* UTF-16BE has no BOM */
|
||||||
|
if ((outb == NULL) || (outlen == 0) || (inlen == 0))
|
||||||
|
return (-1);
|
||||||
|
if (in == NULL) {
|
||||||
|
outlen = 0;
|
||||||
|
inlen = 0;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
outend = out + (outlen / 2);
|
||||||
|
while (in < inend) {
|
||||||
|
d = *in++;
|
||||||
|
if (d < 0x80) {
|
||||||
|
c = d;
|
||||||
|
trailing = 0;
|
||||||
|
} else if (d < 0xC0) {
|
||||||
|
/* trailing byte in leading position */
|
||||||
|
outlen = out - outstart;
|
||||||
|
inlen = processed - instart;
|
||||||
|
return (-2);
|
||||||
|
} else if (d < 0xE0) {
|
||||||
|
c = d & 0x1F;
|
||||||
|
trailing = 1;
|
||||||
|
} else if (d < 0xF0) {
|
||||||
|
c = d & 0x0F;
|
||||||
|
trailing = 2;
|
||||||
|
} else if (d < 0xF8) {
|
||||||
|
c = d & 0x07;
|
||||||
|
trailing = 3;
|
||||||
|
} else {
|
||||||
|
/* no chance for this in UTF-16 */
|
||||||
|
outlen = out - outstart;
|
||||||
|
inlen = processed - instart;
|
||||||
|
return (-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inend - in < trailing) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; trailing; trailing--) {
|
||||||
|
if ((in >= inend) || (((d = *in++) & 0xC0) != 0x80))
|
||||||
|
break;
|
||||||
|
c <<= 6;
|
||||||
|
c |= d & 0x3F;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* assertion: c is a single UTF-4 value */
|
||||||
|
if (c < 0x10000) {
|
||||||
|
if (out >= outend)
|
||||||
|
break;
|
||||||
|
if (xmlLittleEndian) {
|
||||||
|
tmp = (unsigned char *)out;
|
||||||
|
*tmp = c >> 8;
|
||||||
|
*(tmp + 1) = c;
|
||||||
|
out++;
|
||||||
|
} else {
|
||||||
|
*out++ = c;
|
||||||
|
}
|
||||||
|
} else if (c < 0x110000) {
|
||||||
|
if (out + 1 >= outend)
|
||||||
|
break;
|
||||||
|
c -= 0x10000;
|
||||||
|
if (xmlLittleEndian) {
|
||||||
|
tmp1 = 0xD800 | (c >> 10);
|
||||||
|
tmp = (unsigned char *)out;
|
||||||
|
*tmp = tmp1 >> 8;
|
||||||
|
*(tmp + 1) = (unsigned char)tmp1;
|
||||||
|
out++;
|
||||||
|
|
||||||
|
tmp2 = 0xDC00 | (c & 0x03FF);
|
||||||
|
tmp = (unsigned char *)out;
|
||||||
|
*tmp = tmp2 >> 8;
|
||||||
|
*(tmp + 1) = (unsigned char)tmp2;
|
||||||
|
out++;
|
||||||
|
} else {
|
||||||
|
*out++ = 0xD800 | (c >> 10);
|
||||||
|
*out++ = 0xDC00 | (c & 0x03FF);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
break;
|
||||||
|
processed = in;
|
||||||
|
}
|
||||||
|
outlen = (out - outstart) * 2;
|
||||||
|
inlen = processed - instart;
|
||||||
|
return (outlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UTF16LEToUTF8:
|
||||||
|
* @out: a pointer to an array of bytes to store the result
|
||||||
|
* @outlen: the length of @out
|
||||||
|
* @inb: a pointer to an array of UTF-16LE passwd as a byte array
|
||||||
|
* @inlenb: the length of @in in UTF-16LE chars
|
||||||
|
*
|
||||||
|
* Take a block of UTF-16LE ushorts in and try to convert it to an UTF-8
|
||||||
|
* block of chars out. This function assumes the endian property
|
||||||
|
* is the same between the native type of this machine and the
|
||||||
|
* inputed one.
|
||||||
|
*
|
||||||
|
* Returns the number of bytes written, or -1 if lack of space, or -2
|
||||||
|
* if the transcoding fails (if *in is not a valid utf16 string)
|
||||||
|
* The value of *inlen after return is the number of octets consumed
|
||||||
|
* if the return value is positive, else unpredictable.
|
||||||
|
*/
|
||||||
|
int UTF16LEToUTF8(unsigned char *out,
|
||||||
|
int outlen,
|
||||||
|
const unsigned char *inb,
|
||||||
|
int inlenb) {
|
||||||
|
unsigned char *outstart = out;
|
||||||
|
const unsigned char *processed = inb;
|
||||||
|
unsigned char *outend = out + outlen;
|
||||||
|
unsigned short *in = (unsigned short *)inb;
|
||||||
|
unsigned short *inend;
|
||||||
|
unsigned int c, d, inlen;
|
||||||
|
unsigned char *tmp;
|
||||||
|
int bits;
|
||||||
|
|
||||||
|
if ((inlenb % 2) == 1)
|
||||||
|
(inlenb)--;
|
||||||
|
inlen = inlenb / 2;
|
||||||
|
inend = in + inlen;
|
||||||
|
while ((in < inend) && (out - outstart + 5 < outlen)) {
|
||||||
|
if (xmlLittleEndian) {
|
||||||
|
c = *in++;
|
||||||
|
} else {
|
||||||
|
tmp = (unsigned char *)in;
|
||||||
|
c = *tmp++;
|
||||||
|
c = c | (((unsigned int)*tmp) << 8);
|
||||||
|
in++;
|
||||||
|
}
|
||||||
|
if ((c & 0xFC00) == 0xD800) { /* surrogates */
|
||||||
|
if (in >= inend) { /* (in > inend) shouldn't happens */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (xmlLittleEndian) {
|
||||||
|
d = *in++;
|
||||||
|
} else {
|
||||||
|
tmp = (unsigned char *)in;
|
||||||
|
d = *tmp++;
|
||||||
|
d = d | (((unsigned int)*tmp) << 8);
|
||||||
|
in++;
|
||||||
|
}
|
||||||
|
if ((d & 0xFC00) == 0xDC00) {
|
||||||
|
c &= 0x03FF;
|
||||||
|
c <<= 10;
|
||||||
|
c |= d & 0x03FF;
|
||||||
|
c += 0x10000;
|
||||||
|
} else {
|
||||||
|
outlen = out - outstart;
|
||||||
|
inlenb = processed - inb;
|
||||||
|
return (-2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* assertion: c is a single UTF-4 value */
|
||||||
|
if (out >= outend)
|
||||||
|
break;
|
||||||
|
if (c < 0x80) {
|
||||||
|
*out++ = c;
|
||||||
|
bits = -6;
|
||||||
|
} else if (c < 0x800) {
|
||||||
|
*out++ = ((c >> 6) & 0x1F) | 0xC0;
|
||||||
|
bits = 0;
|
||||||
|
} else if (c < 0x10000) {
|
||||||
|
*out++ = ((c >> 12) & 0x0F) | 0xE0;
|
||||||
|
bits = 6;
|
||||||
|
} else {
|
||||||
|
*out++ = ((c >> 18) & 0x07) | 0xF0;
|
||||||
|
bits = 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; bits >= 0; bits -= 6) {
|
||||||
|
if (out >= outend)
|
||||||
|
break;
|
||||||
|
*out++ = ((c >> bits) & 0x3F) | 0x80;
|
||||||
|
}
|
||||||
|
processed = (const unsigned char *)in;
|
||||||
|
}
|
||||||
|
outlen = out - outstart;
|
||||||
|
inlenb = processed - inb;
|
||||||
|
return (outlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UTF8ToUTF16LE:
|
||||||
|
* @outb: a pointer to an array of bytes to store the result
|
||||||
|
* @outlen: the length of @outb
|
||||||
|
* @in: a pointer to an array of UTF-8 chars
|
||||||
|
* @inlen: the length of @in
|
||||||
|
*
|
||||||
|
* Take a block of UTF-8 chars in and try to convert it to an UTF-16LE
|
||||||
|
* block of chars out.
|
||||||
|
*
|
||||||
|
* Returns the number of bytes written, or -1 if lack of space, or -2
|
||||||
|
* if the transcoding failed.
|
||||||
|
*/
|
||||||
|
int UTF8ToUTF16LE(unsigned char *outb,
|
||||||
|
int outlen,
|
||||||
|
const unsigned char *in,
|
||||||
|
int inlen) {
|
||||||
|
unsigned short *out = (unsigned short *)outb;
|
||||||
|
const unsigned char *processed = in;
|
||||||
|
const unsigned char *const instart = in;
|
||||||
|
unsigned short *outstart = out;
|
||||||
|
unsigned short *outend;
|
||||||
|
const unsigned char *inend = in + inlen;
|
||||||
|
unsigned int c, d;
|
||||||
|
int trailing;
|
||||||
|
unsigned char *tmp;
|
||||||
|
unsigned short tmp1, tmp2;
|
||||||
|
|
||||||
|
/* UTF16LE encoding has no BOM */
|
||||||
|
if ((out == NULL) || (outlen == 0) || (inlen == 0))
|
||||||
|
return (-1);
|
||||||
|
if (in == NULL) {
|
||||||
|
outlen = 0;
|
||||||
|
inlen = 0;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
outend = out + (outlen / 2);
|
||||||
|
while (in < inend) {
|
||||||
|
d = *in++;
|
||||||
|
if (d < 0x80) {
|
||||||
|
c = d;
|
||||||
|
trailing = 0;
|
||||||
|
} else if (d < 0xC0) {
|
||||||
|
/* trailing byte in leading position */
|
||||||
|
outlen = (out - outstart) * 2;
|
||||||
|
inlen = processed - instart;
|
||||||
|
return (-2);
|
||||||
|
} else if (d < 0xE0) {
|
||||||
|
c = d & 0x1F;
|
||||||
|
trailing = 1;
|
||||||
|
} else if (d < 0xF0) {
|
||||||
|
c = d & 0x0F;
|
||||||
|
trailing = 2;
|
||||||
|
} else if (d < 0xF8) {
|
||||||
|
c = d & 0x07;
|
||||||
|
trailing = 3;
|
||||||
|
} else {
|
||||||
|
/* no chance for this in UTF-16 */
|
||||||
|
outlen = (out - outstart) * 2;
|
||||||
|
inlen = processed - instart;
|
||||||
|
return (-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inend - in < trailing) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; trailing; trailing--) {
|
||||||
|
if ((in >= inend) || (((d = *in++) & 0xC0) != 0x80))
|
||||||
|
break;
|
||||||
|
c <<= 6;
|
||||||
|
c |= d & 0x3F;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* assertion: c is a single UTF-4 value */
|
||||||
|
if (c < 0x10000) {
|
||||||
|
if (out >= outend)
|
||||||
|
break;
|
||||||
|
if (xmlLittleEndian) {
|
||||||
|
*out++ = c;
|
||||||
|
} else {
|
||||||
|
tmp = (unsigned char *)out;
|
||||||
|
*tmp = c;
|
||||||
|
*(tmp + 1) = c >> 8;
|
||||||
|
out++;
|
||||||
|
}
|
||||||
|
} else if (c < 0x110000) {
|
||||||
|
if (out + 1 >= outend)
|
||||||
|
break;
|
||||||
|
c -= 0x10000;
|
||||||
|
if (xmlLittleEndian) {
|
||||||
|
*out++ = 0xD800 | (c >> 10);
|
||||||
|
*out++ = 0xDC00 | (c & 0x03FF);
|
||||||
|
} else {
|
||||||
|
tmp1 = 0xD800 | (c >> 10);
|
||||||
|
tmp = (unsigned char *)out;
|
||||||
|
*tmp = (unsigned char)tmp1;
|
||||||
|
*(tmp + 1) = tmp1 >> 8;
|
||||||
|
out++;
|
||||||
|
|
||||||
|
tmp2 = 0xDC00 | (c & 0x03FF);
|
||||||
|
tmp = (unsigned char *)out;
|
||||||
|
*tmp = (unsigned char)tmp2;
|
||||||
|
*(tmp + 1) = tmp2 >> 8;
|
||||||
|
out++;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
break;
|
||||||
|
processed = in;
|
||||||
|
}
|
||||||
|
outlen = (out - outstart) * 2;
|
||||||
|
inlen = processed - instart;
|
||||||
|
return (outlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
int isUTF8(const char *in_string) {
|
||||||
|
// fprintf(stdout, "utf8 test-> %s\n", in_string);
|
||||||
|
int str_bytes = 0;
|
||||||
|
if (in_string != NULL) {
|
||||||
|
str_bytes = strlen(in_string);
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_validUTF8 = true;
|
||||||
|
bool is_high_ascii = false;
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
while (index < str_bytes && is_validUTF8) {
|
||||||
|
char achar = in_string[index];
|
||||||
|
int supplemental_bytes = 0;
|
||||||
|
|
||||||
|
if ((unsigned char)achar > 0x80) {
|
||||||
|
is_high_ascii = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((achar & 0x80) == 0) { // 0xxxxxxx
|
||||||
|
++index;
|
||||||
|
|
||||||
|
} else if ((achar & 0xF8) == 0xF0) { // 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx
|
||||||
|
++index;
|
||||||
|
supplemental_bytes = 3;
|
||||||
|
is_high_ascii = true;
|
||||||
|
|
||||||
|
} else if ((achar & 0xE0) == 0xE0) { // 1110zzzz 10yyyyyy 10xxxxxx
|
||||||
|
++index;
|
||||||
|
supplemental_bytes = 2;
|
||||||
|
is_high_ascii = true;
|
||||||
|
|
||||||
|
} else if ((achar & 0xE0) == 0xC0) { // 110yyyyy 10xxxxxx
|
||||||
|
++index;
|
||||||
|
supplemental_bytes = 1;
|
||||||
|
is_high_ascii = true;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
is_validUTF8 = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (is_validUTF8 && supplemental_bytes--) {
|
||||||
|
if (index >= str_bytes) {
|
||||||
|
is_validUTF8 = false;
|
||||||
|
} else if ((in_string[index++] & 0xC0) != 0x80) { // 10uuzzzz
|
||||||
|
is_validUTF8 = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_high_ascii) {
|
||||||
|
return 8;
|
||||||
|
} else if (is_validUTF8) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------
|
||||||
|
utf8_length
|
||||||
|
in_string - pointer to location of a utf8 string
|
||||||
|
char_limit - either 0 (count all characters) or non-zero (limit utf8 to
|
||||||
|
that character count)
|
||||||
|
|
||||||
|
Because of the lovely way utf8 is aligned, test only the first byte in each.
|
||||||
|
If char_limit is 0, return the number of CHARACTERS in the string, if the
|
||||||
|
char_limit is not zero (the char_limit will equal
|
||||||
|
utf_string_leghth because of the break), so change gears, save space and just
|
||||||
|
return the byte_count.
|
||||||
|
----------------------*/
|
||||||
|
#include <stdio.h>
|
||||||
|
unsigned int utf8_length(const char *in_string, unsigned int char_limit) {
|
||||||
|
const char *utf8_str = in_string;
|
||||||
|
unsigned int utf8_string_length = 0;
|
||||||
|
unsigned int in_str_len = strlen(in_string);
|
||||||
|
unsigned int byte_count = 0;
|
||||||
|
unsigned int bytes_in_char = 0;
|
||||||
|
|
||||||
|
if (in_string == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
while (byte_count < in_str_len) {
|
||||||
|
bytes_in_char = 0;
|
||||||
|
if ((*utf8_str & 0x80) == 0x00)
|
||||||
|
bytes_in_char = 1;
|
||||||
|
else if ((*utf8_str & 0xE0) == 0xC0)
|
||||||
|
bytes_in_char = 2;
|
||||||
|
else if ((*utf8_str & 0xF0) == 0xE0)
|
||||||
|
bytes_in_char = 3;
|
||||||
|
else if ((*utf8_str & 0xF8) == 0xF0)
|
||||||
|
bytes_in_char = 4;
|
||||||
|
|
||||||
|
if (bytes_in_char > 0) {
|
||||||
|
utf8_string_length++;
|
||||||
|
utf8_str += bytes_in_char;
|
||||||
|
byte_count += bytes_in_char;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (char_limit != 0 && char_limit == utf8_string_length) {
|
||||||
|
utf8_string_length = byte_count;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return utf8_string_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||||
|
unsigned char APar_Return_rawutf8_CP(unsigned short cp_bound_glyph) {
|
||||||
|
unsigned short total_known_points = 0;
|
||||||
|
unsigned int win32cp = GetConsoleCP();
|
||||||
|
|
||||||
|
if (win32cp == 437 || win32cp == 850 || win32cp == 852 || win32cp == 855 ||
|
||||||
|
win32cp == 858) {
|
||||||
|
total_known_points = 128;
|
||||||
|
} else {
|
||||||
|
if (cp_bound_glyph >= 0x0080) {
|
||||||
|
exit(win32cp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cp_bound_glyph < 0x0080) {
|
||||||
|
return cp_bound_glyph << 0;
|
||||||
|
} else if (total_known_points) {
|
||||||
|
if (win32cp == 437) {
|
||||||
|
for (uint16_t i = 0; i < total_known_points; i++) {
|
||||||
|
if (cp_bound_glyph == cp437upperbytes[i]) {
|
||||||
|
return i + 128;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (win32cp == 850) {
|
||||||
|
for (uint16_t i = 0; i < total_known_points; i++) {
|
||||||
|
if (cp_bound_glyph == cp850upperbytes[i]) {
|
||||||
|
return i + 128;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (win32cp == 852) {
|
||||||
|
for (uint16_t i = 0; i < total_known_points; i++) {
|
||||||
|
if (cp_bound_glyph == cp852upperbytes[i]) {
|
||||||
|
return i + 128;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (win32cp == 855) {
|
||||||
|
for (uint16_t i = 0; i < total_known_points; i++) {
|
||||||
|
if (cp_bound_glyph == cp855upperbytes[i]) {
|
||||||
|
return i + 128;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (win32cp == 858) {
|
||||||
|
for (uint16_t i = 0; i < total_known_points; i++) {
|
||||||
|
if (cp_bound_glyph == cp858upperbytes[i]) {
|
||||||
|
return i + 128;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fprintf(stderr,
|
||||||
|
"AtomicParsley error: this windows codepage(%u) is "
|
||||||
|
"unsupported.\nProvide the output of the 'CPTester' utility run "
|
||||||
|
"from the bat script\n",
|
||||||
|
win32cp);
|
||||||
|
exit(win32cp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int strip_bogusUTF16toRawUTF8(unsigned char *out,
|
||||||
|
int inlen,
|
||||||
|
wchar_t *in,
|
||||||
|
int outlen) {
|
||||||
|
|
||||||
|
unsigned char *outstart = out;
|
||||||
|
unsigned char *outend;
|
||||||
|
const wchar_t *inend;
|
||||||
|
const wchar_t *instop;
|
||||||
|
|
||||||
|
if ((out == NULL) || (in == NULL) || (outlen == 0) || (inlen == 0))
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
outend = out + outlen;
|
||||||
|
inend = in + (inlen);
|
||||||
|
instop = inend;
|
||||||
|
|
||||||
|
while (in < inend && out < outend - 1) {
|
||||||
|
*out++ = APar_Return_rawutf8_CP(*in); //*in << 0;
|
||||||
|
++in;
|
||||||
|
}
|
||||||
|
outlen = out - outstart;
|
||||||
|
return (outlen);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*----------------------
|
||||||
|
test_conforming_alpha_string
|
||||||
|
in_string - pointer to location of a utf8 string
|
||||||
|
|
||||||
|
limit string to A-Z or a-z
|
||||||
|
----------------------*/
|
||||||
|
int test_conforming_alpha_string(char *in_string) {
|
||||||
|
int valid_bytes = 0;
|
||||||
|
int string_len = 0;
|
||||||
|
char *test_str = in_string;
|
||||||
|
if (in_string != NULL) {
|
||||||
|
string_len = strlen(in_string);
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (valid_bytes < string_len) {
|
||||||
|
if ((*test_str >= 65 && *test_str <= 90) ||
|
||||||
|
(*test_str >= 97 && *test_str <= 122) || *test_str == 95 ||
|
||||||
|
(*test_str >= 48 && *test_str <= 57)) {
|
||||||
|
valid_bytes++;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
test_str++;
|
||||||
|
}
|
||||||
|
return valid_bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool test_limited_ascii(char *in_string, unsigned int str_len) {
|
||||||
|
char *test_str = in_string;
|
||||||
|
while (test_str < in_string + str_len) {
|
||||||
|
if (*test_str < 32 || *test_str > 126) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
test_str++;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
3119
src/id3v2.cpp
Normal file
3119
src/id3v2.cpp
Normal file
File diff suppressed because it is too large
Load Diff
68
src/id3v2.h
Normal file
68
src/id3v2.h
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
//==================================================================//
|
||||||
|
/*
|
||||||
|
AtomicParsley - id3v2.h
|
||||||
|
|
||||||
|
AtomicParsley is GPL software; you can freely distribute,
|
||||||
|
redistribute, modify & use under the terms of the GNU General
|
||||||
|
Public License; either version 2 or its successor.
|
||||||
|
|
||||||
|
AtomicParsley is distributed under the GPL "AS IS", without
|
||||||
|
any warranty; without the implied warranty of merchantability
|
||||||
|
or fitness for either an expressed or implied particular purpose.
|
||||||
|
|
||||||
|
Please see the included GNU General Public License (GPL) for
|
||||||
|
your rights and further details; see the file COPYING. If you
|
||||||
|
cannot, write to the Free Software Foundation, 59 Temple Place
|
||||||
|
Suite 330, Boston, MA 02111-1307, USA. Or www.fsf.org
|
||||||
|
|
||||||
|
Copyright ©2006-2007 puck_lock
|
||||||
|
with contributions from others; see the CREDITS file
|
||||||
|
*/
|
||||||
|
//==================================================================//
|
||||||
|
|
||||||
|
struct AdjunctArgs {
|
||||||
|
const char *targetLang;
|
||||||
|
const char *descripArg;
|
||||||
|
const char *mimeArg;
|
||||||
|
const char *pictypeArg;
|
||||||
|
const char *filenameArg;
|
||||||
|
const char *ratingArg;
|
||||||
|
const char *dataArg; // multipurposed: PRIV's binary data, GRID's group data,
|
||||||
|
// UFID's binary data, POPM's counter field
|
||||||
|
uint8_t pictype_uint8;
|
||||||
|
uint8_t groupSymbol;
|
||||||
|
bool zlibCompressed;
|
||||||
|
bool multistringtext;
|
||||||
|
};
|
||||||
|
|
||||||
|
uint64_t syncsafeXX_to_UInt64(char *syncsafe_int, uint8_t syncsafe_len);
|
||||||
|
uint32_t syncsafe32_to_UInt32(char *syncsafe_int);
|
||||||
|
|
||||||
|
bool ID3v2_TestTagFlag(uint8_t TagFlag, uint8_t TagBit);
|
||||||
|
bool ID3v2_TestFrameFlag(uint16_t FrameFlag, uint16_t FrameBit);
|
||||||
|
uint8_t ImageListMembers();
|
||||||
|
|
||||||
|
void ListID3FrameIDstrings();
|
||||||
|
void List_imagtype_strings();
|
||||||
|
const char *ConvertCLIFrameStr_TO_frameID(const char *frame_str);
|
||||||
|
bool TestCLI_for_FrameParams(int frametype, uint8_t testparam);
|
||||||
|
|
||||||
|
int MatchID3FrameIDstr(const char *foundFrameID, uint8_t tagVersion);
|
||||||
|
uint8_t GetFrameCompositionDescription(int ID3v2_FrameTypeID);
|
||||||
|
int FrameStr_TO_FrameType(const char *frame_str);
|
||||||
|
|
||||||
|
void APar_ID32_ScanID3Tag(FILE *source_file, AtomicInfo *id32_atom);
|
||||||
|
|
||||||
|
uint32_t APar_GetTagSize(AtomicInfo *id32_atom);
|
||||||
|
uint32_t APar_Render_ID32_Tag(AtomicInfo *id32_atom, uint32_t max_alloc);
|
||||||
|
|
||||||
|
char *APar_ConvertField_to_UTF8(ID3v2Frame *targetframe, int fieldtype);
|
||||||
|
|
||||||
|
void APar_ID3Tag_Init(AtomicInfo *id32_atom);
|
||||||
|
void APar_ID3FrameAmmend(AtomicInfo *id32_atom,
|
||||||
|
const char *frame_str,
|
||||||
|
const char *frame_payload,
|
||||||
|
AdjunctArgs *adjunct_payloads,
|
||||||
|
uint8_t str_encoding);
|
||||||
|
|
||||||
|
void APar_FreeID32Memory(ID3v2Tag *id32tag);
|
||||||
597
src/id3v2defs.h
Normal file
597
src/id3v2defs.h
Normal file
@ -0,0 +1,597 @@
|
|||||||
|
//==================================================================//
|
||||||
|
/*
|
||||||
|
AtomicParsley - id3v2defs.h
|
||||||
|
|
||||||
|
AtomicParsley is GPL software; you can freely distribute,
|
||||||
|
redistribute, modify & use under the terms of the GNU General
|
||||||
|
Public License; either version 2 or its successor.
|
||||||
|
|
||||||
|
AtomicParsley is distributed under the GPL "AS IS", without
|
||||||
|
any warranty; without the implied warranty of merchantability
|
||||||
|
or fitness for either an expressed or implied particular purpose.
|
||||||
|
|
||||||
|
Please see the included GNU General Public License (GPL) for
|
||||||
|
your rights and further details; see the file COPYING. If you
|
||||||
|
cannot, write to the Free Software Foundation, 59 Temple Place
|
||||||
|
Suite 330, Boston, MA 02111-1307, USA. Or www.fsf.org
|
||||||
|
|
||||||
|
Copyright ©2006-2007 puck_lock
|
||||||
|
with contributions from others; see the CREDITS file
|
||||||
|
*/
|
||||||
|
//==================================================================//
|
||||||
|
|
||||||
|
ID3FrameDefinition KnownFrames[] = {
|
||||||
|
{"", "", "", "Unknown frame", "", ID3v2_UNKNOWN_FRAME, ID3_UNKNOWN_FRAME},
|
||||||
|
{"TAL",
|
||||||
|
"TALB",
|
||||||
|
"TALB",
|
||||||
|
"Album/Movie/Show title",
|
||||||
|
"album",
|
||||||
|
ID3v2_FRAME_ALBUM,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
{"TBP",
|
||||||
|
"TBPM",
|
||||||
|
"TBPM",
|
||||||
|
"BPM (beats per minute)",
|
||||||
|
"bpm",
|
||||||
|
ID3v2_FRAME_BPM,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
{"TCM",
|
||||||
|
"TCOM",
|
||||||
|
"TCOM",
|
||||||
|
"Composer",
|
||||||
|
"composer",
|
||||||
|
ID3v2_FRAME_COMPOSER,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
{"TCO",
|
||||||
|
"TCON",
|
||||||
|
"TCON",
|
||||||
|
"Content Type/Genre",
|
||||||
|
"genre",
|
||||||
|
ID3v2_FRAME_CONTENTTYPE,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
{"TCP",
|
||||||
|
"TCOP",
|
||||||
|
"TCOP",
|
||||||
|
"Copyright message",
|
||||||
|
"copyright",
|
||||||
|
ID3v2_FRAME_COPYRIGHT,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
{"",
|
||||||
|
"",
|
||||||
|
"TDEN",
|
||||||
|
"Encoding time",
|
||||||
|
"",
|
||||||
|
ID3v2_FRAME_ENCODINGTIME,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
{"TDY",
|
||||||
|
"TDLY",
|
||||||
|
"TDLY",
|
||||||
|
"Playlist delay",
|
||||||
|
"",
|
||||||
|
ID3v2_FRAME_PLAYLISTDELAY,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
{"",
|
||||||
|
"",
|
||||||
|
"TDOR",
|
||||||
|
"Original release time",
|
||||||
|
"",
|
||||||
|
ID3v2_FRAME_ORIGRELTIME,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
{"",
|
||||||
|
"",
|
||||||
|
"TDRC",
|
||||||
|
"Recording time",
|
||||||
|
"date",
|
||||||
|
ID3v2_FRAME_RECORDINGTIME,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
{"",
|
||||||
|
"",
|
||||||
|
"TDRL",
|
||||||
|
"Release time",
|
||||||
|
"released",
|
||||||
|
ID3v2_FRAME_RELEASETIME,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
{"",
|
||||||
|
"",
|
||||||
|
"TDTG",
|
||||||
|
"Tagging time",
|
||||||
|
"tagged",
|
||||||
|
ID3v2_FRAME_TAGGINGTIME,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
{"TEN",
|
||||||
|
"TENC",
|
||||||
|
"TENC",
|
||||||
|
"Encoded by",
|
||||||
|
"encoder",
|
||||||
|
ID3v2_FRAME_ENCODER,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
{"TXT",
|
||||||
|
"TEXT",
|
||||||
|
"TEXT",
|
||||||
|
"Lyricist/Text writer",
|
||||||
|
"writer",
|
||||||
|
ID3v2_FRAME_LYRICIST,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
{"TFT",
|
||||||
|
"TFLT",
|
||||||
|
"TFLT",
|
||||||
|
"File type",
|
||||||
|
"",
|
||||||
|
ID3v2_FRAME_FILETYPE,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
{"",
|
||||||
|
"",
|
||||||
|
"TIPL",
|
||||||
|
"Involved people list",
|
||||||
|
"",
|
||||||
|
ID3v2_FRAME_INVOLVEDPEOPLE,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
{"TT1",
|
||||||
|
"TIT1",
|
||||||
|
"TIT1",
|
||||||
|
"Content group description",
|
||||||
|
"grouping",
|
||||||
|
ID3v2_FRAME_GROUP_DESC,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
{"TT2",
|
||||||
|
"TIT2",
|
||||||
|
"TIT2",
|
||||||
|
"Title/songname/content description",
|
||||||
|
"title",
|
||||||
|
ID3v2_FRAME_TITLE,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
{"TT3",
|
||||||
|
"TIT3",
|
||||||
|
"TIT3",
|
||||||
|
"Subtitle/Description refinement",
|
||||||
|
"subtitle",
|
||||||
|
ID3v2_FRAME_SUBTITLE,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
{"TKE",
|
||||||
|
"TKEY",
|
||||||
|
"TKEY",
|
||||||
|
"Initial key",
|
||||||
|
"",
|
||||||
|
ID3v2_FRAME_INITIALKEY,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
{"TLA",
|
||||||
|
"TLAN",
|
||||||
|
"TLAN",
|
||||||
|
"Language(s)",
|
||||||
|
"",
|
||||||
|
ID3v2_FRAME_LANGUAGE,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
{"TLE",
|
||||||
|
"TLEN",
|
||||||
|
"TLEN",
|
||||||
|
"Length",
|
||||||
|
"",
|
||||||
|
ID3v2_FRAME_TIMELENGTH,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
{"",
|
||||||
|
"",
|
||||||
|
"TMCL",
|
||||||
|
"Musician credits list",
|
||||||
|
"credits",
|
||||||
|
ID3v2_FRAME_MUSICIANLIST,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
{"TMT",
|
||||||
|
"TMED",
|
||||||
|
"TMED",
|
||||||
|
"Media type",
|
||||||
|
"media",
|
||||||
|
ID3v2_FRAME_MEDIATYPE,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
{"", "", "TMOO", "Mood", "mood", ID3v2_FRAME_MOOD, ID3_TEXT_FRAME},
|
||||||
|
{"TOT",
|
||||||
|
"TOAL",
|
||||||
|
"TOAL",
|
||||||
|
"Original album/movie/show title",
|
||||||
|
"",
|
||||||
|
ID3v2_FRAME_ORIGALBUM,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
{"TOF",
|
||||||
|
"TOFN",
|
||||||
|
"TOFN",
|
||||||
|
"Original filename",
|
||||||
|
"",
|
||||||
|
ID3v2_FRAME_ORIGFILENAME,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
{"TOL",
|
||||||
|
"TOLY",
|
||||||
|
"TOLY",
|
||||||
|
"Original lyricist(s)/text writer(s)",
|
||||||
|
"",
|
||||||
|
ID3v2_FRAME_ORIGWRITER,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
{"TOA",
|
||||||
|
"TOPE",
|
||||||
|
"TOPE",
|
||||||
|
"Original artist(s)/performer(s)",
|
||||||
|
"",
|
||||||
|
ID3v2_FRAME_ORIGARTIST,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
{"",
|
||||||
|
"TOWN",
|
||||||
|
"TOWN",
|
||||||
|
"File owner/licensee",
|
||||||
|
"",
|
||||||
|
ID3v2_FRAME_FILEOWNER,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
{"TP1",
|
||||||
|
"TPE1",
|
||||||
|
"TPE1",
|
||||||
|
"Artist/Lead performer(s)/Soloist(s)",
|
||||||
|
"artist",
|
||||||
|
ID3v2_FRAME_ARTIST,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
{"TP2",
|
||||||
|
"TPE2",
|
||||||
|
"TPE2",
|
||||||
|
"Album artist/Band/orchestra/accompaniment",
|
||||||
|
"album artist",
|
||||||
|
ID3v2_FRAME_ALBUMARTIST,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
{"TP3",
|
||||||
|
"TPE3",
|
||||||
|
"TPE3",
|
||||||
|
"Conductor/performer refinement",
|
||||||
|
"conductor",
|
||||||
|
ID3v2_FRAME_CONDUCTOR,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
{"TP4",
|
||||||
|
"TPE4",
|
||||||
|
"TPE4",
|
||||||
|
"Interpreted or remixed by",
|
||||||
|
"remixer",
|
||||||
|
ID3v2_FRAME_REMIXER,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
{"TPA",
|
||||||
|
"TPOS",
|
||||||
|
"TPOS",
|
||||||
|
"Part of a set",
|
||||||
|
"",
|
||||||
|
ID3v2_FRAME_PART_O_SET,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
{"",
|
||||||
|
"",
|
||||||
|
"TPRO",
|
||||||
|
"Produced notice",
|
||||||
|
"",
|
||||||
|
ID3v2_FRAME_PRODNOTICE,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
{"TPB",
|
||||||
|
"TPUB",
|
||||||
|
"TPUB",
|
||||||
|
"Publisher",
|
||||||
|
"publisher",
|
||||||
|
ID3v2_FRAME_PUBLISHER,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
{"TRK",
|
||||||
|
"TRCK",
|
||||||
|
"TRCK",
|
||||||
|
"Track number/Position in set",
|
||||||
|
"trk#",
|
||||||
|
ID3v2_FRAME_TRACKNUM,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
{"",
|
||||||
|
"TRSN",
|
||||||
|
"TRSN",
|
||||||
|
"Internet radio station name",
|
||||||
|
"",
|
||||||
|
ID3v2_FRAME_IRADIONAME,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
{"",
|
||||||
|
"TRSO",
|
||||||
|
"TRSO",
|
||||||
|
"Internet radio station owner",
|
||||||
|
"",
|
||||||
|
ID3v2_FRAME_IRADIOOWNER,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
{"",
|
||||||
|
"",
|
||||||
|
"TSOA",
|
||||||
|
"Album sort order",
|
||||||
|
"",
|
||||||
|
ID3v2_FRAME_ALBUMSORT,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
{"",
|
||||||
|
"",
|
||||||
|
"TSOP",
|
||||||
|
"Performer sort order",
|
||||||
|
"",
|
||||||
|
ID3v2_FRAME_PERFORMERSORT,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
{"",
|
||||||
|
"",
|
||||||
|
"TSOT",
|
||||||
|
"Title sort order",
|
||||||
|
"",
|
||||||
|
ID3v2_FRAME_TITLESORT,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
{"TRC", "TSRC", "TSRC", "ISRC", "", ID3v2_FRAME_ISRC, ID3_TEXT_FRAME},
|
||||||
|
{"TSS",
|
||||||
|
"TSSE",
|
||||||
|
"TSSE",
|
||||||
|
"Software/Hardware and settings used for encoding",
|
||||||
|
"",
|
||||||
|
ID3v2_FRAME_ENCODINGSETTINGS,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
{"",
|
||||||
|
"",
|
||||||
|
"TSST",
|
||||||
|
"Set subtitle",
|
||||||
|
"",
|
||||||
|
ID3v2_FRAME_SETSUBTITLE,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
|
||||||
|
{"TDA", "TDAT", "", "Date", "", ID3v2_DATE, ID3_TEXT_FRAME},
|
||||||
|
{"TIM", "TIME", "", "TIME", "", ID3v2_TIME, ID3_TEXT_FRAME},
|
||||||
|
{"TOR",
|
||||||
|
"TORY",
|
||||||
|
"",
|
||||||
|
"Original Release Year",
|
||||||
|
"",
|
||||||
|
ID3v2_ORIGRELYEAR,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
{"TRD",
|
||||||
|
"TRDA",
|
||||||
|
"",
|
||||||
|
"Recording dates",
|
||||||
|
"",
|
||||||
|
ID3v2_RECORDINGDATE,
|
||||||
|
ID3_TEXT_FRAME},
|
||||||
|
{"TSI", "TSIZ", "", "Size", "", ID3v2_FRAME_SIZE, ID3_TEXT_FRAME},
|
||||||
|
{"TYE", "TYER", "", "YEAR", "", ID3v2_FRAME_YEAR, ID3_TEXT_FRAME},
|
||||||
|
|
||||||
|
{"TXX",
|
||||||
|
"TXXX",
|
||||||
|
"TXXX",
|
||||||
|
"User defined text information frame",
|
||||||
|
"",
|
||||||
|
ID3v2_FRAME_USERDEF_TEXT,
|
||||||
|
ID3_TEXT_FRAME_USERDEF},
|
||||||
|
|
||||||
|
// some of these (like WCOM, WOAF) allow for muliple frames - but (sigh)
|
||||||
|
// alas, such is not the case in AP.
|
||||||
|
{"WCM",
|
||||||
|
"WCOM",
|
||||||
|
"WCOM",
|
||||||
|
"Commercial information",
|
||||||
|
"",
|
||||||
|
ID3v2_FRAME_URLCOMMINFO,
|
||||||
|
ID3_URL_FRAME},
|
||||||
|
{"WCP",
|
||||||
|
"WCOP",
|
||||||
|
"WCOP",
|
||||||
|
"Copyright/Legal information",
|
||||||
|
"",
|
||||||
|
ID3v2_FRAME_URLCOPYRIGHT,
|
||||||
|
ID3_URL_FRAME},
|
||||||
|
{"WAF",
|
||||||
|
"WOAF",
|
||||||
|
"WOAF",
|
||||||
|
"Official audio file webpage",
|
||||||
|
"",
|
||||||
|
ID3v2_FRAME_URLAUDIOFILE,
|
||||||
|
ID3_URL_FRAME},
|
||||||
|
{"WAR",
|
||||||
|
"WOAR",
|
||||||
|
"WOAR",
|
||||||
|
"Official artist/performer webpage",
|
||||||
|
"",
|
||||||
|
ID3v2_FRAME_URLARTIST,
|
||||||
|
ID3_URL_FRAME},
|
||||||
|
{"WAS",
|
||||||
|
"WOAS",
|
||||||
|
"WOAS",
|
||||||
|
"Official audio source webpage",
|
||||||
|
"",
|
||||||
|
ID3v2_FRAME_URLAUDIOSOURCE,
|
||||||
|
ID3_URL_FRAME},
|
||||||
|
{"",
|
||||||
|
"WORS",
|
||||||
|
"WORS",
|
||||||
|
"Official Internet radio station homepage",
|
||||||
|
"",
|
||||||
|
ID3v2_FRAME_URLIRADIO,
|
||||||
|
ID3_URL_FRAME},
|
||||||
|
{"", "WPAY", "WPAY", "Payment", "", ID3v2_FRAME_URLPAYMENT, ID3_URL_FRAME},
|
||||||
|
{"WPB",
|
||||||
|
"WPUB",
|
||||||
|
"WPUB",
|
||||||
|
"Publishers official webpage",
|
||||||
|
"",
|
||||||
|
ID3v2_FRAME_URLPUBLISHER,
|
||||||
|
ID3_URL_FRAME},
|
||||||
|
{"WXX",
|
||||||
|
"WXXX",
|
||||||
|
"WXXX",
|
||||||
|
"User defined URL link frame",
|
||||||
|
"",
|
||||||
|
ID3v2_FRAME_USERDEF_URL,
|
||||||
|
ID3_URL_FRAME_USERDEF},
|
||||||
|
|
||||||
|
{"UFI",
|
||||||
|
"UFID",
|
||||||
|
"UFID",
|
||||||
|
"Unique file identifier",
|
||||||
|
"",
|
||||||
|
ID3v2_FRAME_UFID,
|
||||||
|
ID3_UNIQUE_FILE_ID_FRAME},
|
||||||
|
{"MCI",
|
||||||
|
"MCID",
|
||||||
|
"MCDI",
|
||||||
|
"Music CD Identifier",
|
||||||
|
"",
|
||||||
|
ID3v2_FRAME_MUSIC_CD_ID,
|
||||||
|
ID3_CD_ID_FRAME},
|
||||||
|
|
||||||
|
{"COM",
|
||||||
|
"COMM",
|
||||||
|
"COMM",
|
||||||
|
"Comment",
|
||||||
|
"comment",
|
||||||
|
ID3v2_FRAME_COMMENT,
|
||||||
|
ID3_DESCRIBED_TEXT_FRAME},
|
||||||
|
{"ULT",
|
||||||
|
"USLT",
|
||||||
|
"USLT",
|
||||||
|
"Unsynchronised lyrics",
|
||||||
|
"lyrics",
|
||||||
|
ID3v2_FRAME_UNSYNCLYRICS,
|
||||||
|
ID3_DESCRIBED_TEXT_FRAME},
|
||||||
|
|
||||||
|
{"",
|
||||||
|
"APIC",
|
||||||
|
"APIC",
|
||||||
|
"Attached picture",
|
||||||
|
"",
|
||||||
|
ID3v2_EMBEDDED_PICTURE,
|
||||||
|
ID3_ATTACHED_PICTURE_FRAME},
|
||||||
|
{"PIC",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"Attached picture",
|
||||||
|
"",
|
||||||
|
ID3v2_EMBEDDED_PICTURE_V2P2,
|
||||||
|
ID3_OLD_V2P2_PICTURE_FRAME},
|
||||||
|
{"GEO",
|
||||||
|
"GEOB",
|
||||||
|
"GEOB",
|
||||||
|
"Attached object",
|
||||||
|
"",
|
||||||
|
ID3v2_EMBEDDED_OBJECT,
|
||||||
|
ID3_ATTACHED_OBJECT_FRAME},
|
||||||
|
|
||||||
|
{"",
|
||||||
|
"GRID",
|
||||||
|
"GRID",
|
||||||
|
"Group ID registration",
|
||||||
|
"",
|
||||||
|
ID3v2_FRAME_GRID,
|
||||||
|
ID3_GROUP_ID_FRAME},
|
||||||
|
{"",
|
||||||
|
"",
|
||||||
|
"SIGN",
|
||||||
|
"Signature",
|
||||||
|
"",
|
||||||
|
ID3v2_FRAME_SIGNATURE,
|
||||||
|
ID3_SIGNATURE_FRAME},
|
||||||
|
{"",
|
||||||
|
"PRIV",
|
||||||
|
"PRIV",
|
||||||
|
"Private frame",
|
||||||
|
"",
|
||||||
|
ID3v2_FRAME_PRIVATE,
|
||||||
|
ID3_PRIVATE_FRAME},
|
||||||
|
{"CNT",
|
||||||
|
"PCNT",
|
||||||
|
"PCNT",
|
||||||
|
"Play counter",
|
||||||
|
"",
|
||||||
|
ID3v2_FRAME_PLAYCOUNTER,
|
||||||
|
ID3_PLAYCOUNTER_FRAME},
|
||||||
|
{"POP",
|
||||||
|
"POPM",
|
||||||
|
"POPM",
|
||||||
|
"Popularimeter",
|
||||||
|
"",
|
||||||
|
ID3v2_FRAME_POPULARITY,
|
||||||
|
ID3_POPULAR_FRAME}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// the field listing array is mostly used for mental clarification instead of
|
||||||
|
// internal use - frames are parsed/rendered hardcoded irrespective of ordering
|
||||||
|
// here
|
||||||
|
ID3v2FieldDefinition FrameTypeConstructionList[] = {
|
||||||
|
{ID3_UNKNOWN_FRAME, 1, {ID3_UNKNOWN_FIELD}},
|
||||||
|
{ID3_TEXT_FRAME, 2, {ID3_TEXT_ENCODING_FIELD, ID3_TEXT_FIELD}},
|
||||||
|
{ID3_TEXT_FRAME_USERDEF,
|
||||||
|
3,
|
||||||
|
{ID3_TEXT_ENCODING_FIELD, ID3_DESCRIPTION_FIELD, ID3_TEXT_FIELD}},
|
||||||
|
{ID3_URL_FRAME, 1, {ID3_URL_FIELD}},
|
||||||
|
{ID3_URL_FRAME_USERDEF,
|
||||||
|
3,
|
||||||
|
{ID3_TEXT_ENCODING_FIELD, ID3_DESCRIPTION_FIELD, ID3_URL_FIELD}},
|
||||||
|
{ID3_UNIQUE_FILE_ID_FRAME, 2, {ID3_OWNER_FIELD, ID3_BINARY_DATA_FIELD}},
|
||||||
|
{ID3_CD_ID_FRAME, 1, {ID3_BINARY_DATA_FIELD}},
|
||||||
|
{ID3_DESCRIBED_TEXT_FRAME,
|
||||||
|
4,
|
||||||
|
{ID3_TEXT_ENCODING_FIELD,
|
||||||
|
ID3_LANGUAGE_FIELD,
|
||||||
|
ID3_DESCRIPTION_FIELD,
|
||||||
|
ID3_TEXT_FIELD}},
|
||||||
|
{ID3_ATTACHED_PICTURE_FRAME,
|
||||||
|
5,
|
||||||
|
{ID3_TEXT_ENCODING_FIELD,
|
||||||
|
ID3_MIME_TYPE_FIELD,
|
||||||
|
ID3_PIC_TYPE_FIELD,
|
||||||
|
ID3_DESCRIPTION_FIELD,
|
||||||
|
ID3_BINARY_DATA_FIELD}},
|
||||||
|
{ID3_ATTACHED_OBJECT_FRAME,
|
||||||
|
5,
|
||||||
|
{ID3_TEXT_ENCODING_FIELD,
|
||||||
|
ID3_MIME_TYPE_FIELD,
|
||||||
|
ID3_FILENAME_FIELD,
|
||||||
|
ID3_DESCRIPTION_FIELD,
|
||||||
|
ID3_BINARY_DATA_FIELD}},
|
||||||
|
{ID3_GROUP_ID_FRAME,
|
||||||
|
3,
|
||||||
|
{ID3_OWNER_FIELD, ID3_GROUPSYMBOL_FIELD, ID3_BINARY_DATA_FIELD}},
|
||||||
|
{ID3_SIGNATURE_FRAME, 2, {ID3_GROUPSYMBOL_FIELD, ID3_BINARY_DATA_FIELD}},
|
||||||
|
{ID3_PRIVATE_FRAME, 2, {ID3_OWNER_FIELD, ID3_BINARY_DATA_FIELD}},
|
||||||
|
{ID3_PLAYCOUNTER_FRAME, 1, {ID3_COUNTER_FIELD}},
|
||||||
|
{ID3_POPULAR_FRAME,
|
||||||
|
3,
|
||||||
|
{ID3_OWNER_FIELD, ID3_BINARY_DATA_FIELD, ID3_COUNTER_FIELD}},
|
||||||
|
{ID3_OLD_V2P2_PICTURE_FRAME,
|
||||||
|
5,
|
||||||
|
{ID3_TEXT_ENCODING_FIELD,
|
||||||
|
ID3_IMAGEFORMAT_FIELD,
|
||||||
|
ID3_PIC_TYPE_FIELD,
|
||||||
|
ID3_DESCRIPTION_FIELD,
|
||||||
|
ID3_BINARY_DATA_FIELD}}};
|
||||||
|
|
||||||
|
// used to determine mimetype for APIC image writing
|
||||||
|
ImageFileFormatDefinition ImageList[] = {
|
||||||
|
{"image/jpeg", ".jpg", 3, "\xFF\xD8\xFF"},
|
||||||
|
{"image/png", ".png", 8, "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A"},
|
||||||
|
{"image/pdf", ".pdf", 7, "%PDF-1."},
|
||||||
|
{"image/jp2",
|
||||||
|
".jp2",
|
||||||
|
12,
|
||||||
|
"\x00\x00\x00\x0C\x6A\x50\x20\x20\x0D\x0A\x87\x0A\x00\x00\x00\x14\x66\x74"
|
||||||
|
"\x79\x70\x6A\x70\x32\x20"},
|
||||||
|
{"image/gif", ".gif", 6, "GIF89a"},
|
||||||
|
{"image/tiff", ".tiff", 4, "\x4D\x4D\x00\x2A"},
|
||||||
|
{"image/tiff", ".tiff", 4, "\x49\x49\x2A\x00"},
|
||||||
|
{"image/bmp", ".bmp", 2, "\x42\x4D"},
|
||||||
|
{"image/bmp", ".bmp", 2, "\x42\x41"},
|
||||||
|
{"image/photoshop", ".psd", 4, "8BPS"},
|
||||||
|
{"image/other", ".img", 0, ""}};
|
||||||
|
|
||||||
|
ID3ImageType ImageTypeList[] = {
|
||||||
|
{0x00, "0x00", "Other"},
|
||||||
|
{0x01, "0x01", "32x32 pixels 'file icon' (PNG only)"},
|
||||||
|
{0x02, "0x02", "Other file icon"},
|
||||||
|
{0x03, "0x03", "Cover (front)"},
|
||||||
|
{0x04, "0x04", "Cover (back)"},
|
||||||
|
{0x05, "0x05", "Leaflet page"},
|
||||||
|
{0x06, "0x06", "Media (e.g. label side of CD)"},
|
||||||
|
{0x07, "0x07", "Lead artist/lead performer/soloist"},
|
||||||
|
{0x08, "0x08", "Artist/performer"},
|
||||||
|
{0x09, "0x09", "Conductor"},
|
||||||
|
{0x0A, "0x0A", "Band/Orchestra"},
|
||||||
|
{0x0B, "0x0B", "Composer"},
|
||||||
|
{0x0C, "0x0C", "Lyricist/text writer"},
|
||||||
|
{0x0D, "0x0D", "Recording Location"},
|
||||||
|
{0x0E, "0x0E", "During recording"},
|
||||||
|
{0x0F, "0x0F", "During performance"},
|
||||||
|
{0x10, "0x10", "Movie/video screen capture"},
|
||||||
|
{0x11, "0x11", "A bright coloured fish"},
|
||||||
|
{0x12, "0x12", "Illustration"},
|
||||||
|
{0x13, "0x13", "Band/artist logotype"},
|
||||||
|
{0x14, "0x14", "Publisher/Studio logotype"}};
|
||||||
280
src/id3v2types.h
Normal file
280
src/id3v2types.h
Normal file
@ -0,0 +1,280 @@
|
|||||||
|
//==================================================================//
|
||||||
|
/*
|
||||||
|
AtomicParsley - id3v2types.h
|
||||||
|
|
||||||
|
AtomicParsley is GPL software; you can freely distribute,
|
||||||
|
redistribute, modify & use under the terms of the GNU General
|
||||||
|
Public License; either version 2 or its successor.
|
||||||
|
|
||||||
|
AtomicParsley is distributed under the GPL "AS IS", without
|
||||||
|
any warranty; without the implied warranty of merchantability
|
||||||
|
or fitness for either an expressed or implied particular purpose.
|
||||||
|
|
||||||
|
Please see the included GNU General Public License (GPL) for
|
||||||
|
your rights and further details; see the file COPYING. If you
|
||||||
|
cannot, write to the Free Software Foundation, 59 Temple Place
|
||||||
|
Suite 330, Boston, MA 02111-1307, USA. Or www.fsf.org
|
||||||
|
|
||||||
|
Copyright ©2006-2007 puck_lock
|
||||||
|
with contributions from others; see the CREDITS file
|
||||||
|
*/
|
||||||
|
//==================================================================//
|
||||||
|
|
||||||
|
enum ID3_FieldTypes {
|
||||||
|
ID3_UNKNOWN_FIELD = -1,
|
||||||
|
ID3_TEXT_FIELD,
|
||||||
|
ID3_TEXT_ENCODING_FIELD,
|
||||||
|
ID3_OWNER_FIELD, // UFID,PRIV
|
||||||
|
ID3_DESCRIPTION_FIELD, // TXXX, WXXX
|
||||||
|
ID3_URL_FIELD,
|
||||||
|
ID3_LANGUAGE_FIELD, // USLT
|
||||||
|
ID3_MIME_TYPE_FIELD, // APIC
|
||||||
|
ID3_PIC_TYPE_FIELD, // APIC
|
||||||
|
ID3_BINARY_DATA_FIELD, // APIC,GEOB
|
||||||
|
ID3_FILENAME_FIELD, // GEOB
|
||||||
|
ID3_GROUPSYMBOL_FIELD,
|
||||||
|
ID3_COUNTER_FIELD,
|
||||||
|
ID3_IMAGEFORMAT_FIELD // PIC in v2.2
|
||||||
|
};
|
||||||
|
|
||||||
|
// the order of these frame types must exactly match the order listed in the
|
||||||
|
// FrameTypeConstructionList[] array!!!
|
||||||
|
enum ID3v2FrameType {
|
||||||
|
ID3_UNKNOWN_FRAME = -1,
|
||||||
|
ID3_TEXT_FRAME,
|
||||||
|
ID3_TEXT_FRAME_USERDEF,
|
||||||
|
ID3_URL_FRAME,
|
||||||
|
ID3_URL_FRAME_USERDEF,
|
||||||
|
ID3_UNIQUE_FILE_ID_FRAME,
|
||||||
|
ID3_CD_ID_FRAME,
|
||||||
|
ID3_DESCRIBED_TEXT_FRAME, // oy... these frames (COMM, USLT) can differ by
|
||||||
|
// description
|
||||||
|
ID3_ATTACHED_PICTURE_FRAME,
|
||||||
|
ID3_ATTACHED_OBJECT_FRAME,
|
||||||
|
ID3_GROUP_ID_FRAME,
|
||||||
|
ID3_SIGNATURE_FRAME,
|
||||||
|
ID3_PRIVATE_FRAME,
|
||||||
|
ID3_PLAYCOUNTER_FRAME,
|
||||||
|
ID3_POPULAR_FRAME,
|
||||||
|
ID3_OLD_V2P2_PICTURE_FRAME
|
||||||
|
};
|
||||||
|
|
||||||
|
// the order of these frames must exactly match the order listed in the
|
||||||
|
// KnownFrames[] array!!!
|
||||||
|
enum ID3v2FrameIDs {
|
||||||
|
ID3v2_UNKNOWN_FRAME = -1,
|
||||||
|
ID3v2_FRAME_ALBUM,
|
||||||
|
ID3v2_FRAME_BPM,
|
||||||
|
ID3v2_FRAME_COMPOSER,
|
||||||
|
ID3v2_FRAME_CONTENTTYPE,
|
||||||
|
ID3v2_FRAME_COPYRIGHT,
|
||||||
|
ID3v2_FRAME_ENCODINGTIME,
|
||||||
|
ID3v2_FRAME_PLAYLISTDELAY,
|
||||||
|
ID3v2_FRAME_ORIGRELTIME,
|
||||||
|
ID3v2_FRAME_RECORDINGTIME,
|
||||||
|
ID3v2_FRAME_RELEASETIME,
|
||||||
|
ID3v2_FRAME_TAGGINGTIME,
|
||||||
|
ID3v2_FRAME_ENCODER,
|
||||||
|
ID3v2_FRAME_LYRICIST,
|
||||||
|
ID3v2_FRAME_FILETYPE,
|
||||||
|
ID3v2_FRAME_INVOLVEDPEOPLE,
|
||||||
|
ID3v2_FRAME_GROUP_DESC,
|
||||||
|
ID3v2_FRAME_TITLE,
|
||||||
|
ID3v2_FRAME_SUBTITLE,
|
||||||
|
ID3v2_FRAME_INITIALKEY,
|
||||||
|
ID3v2_FRAME_LANGUAGE,
|
||||||
|
ID3v2_FRAME_TIMELENGTH,
|
||||||
|
ID3v2_FRAME_MUSICIANLIST,
|
||||||
|
ID3v2_FRAME_MEDIATYPE,
|
||||||
|
ID3v2_FRAME_MOOD,
|
||||||
|
ID3v2_FRAME_ORIGALBUM,
|
||||||
|
ID3v2_FRAME_ORIGFILENAME,
|
||||||
|
ID3v2_FRAME_ORIGWRITER,
|
||||||
|
ID3v2_FRAME_ORIGARTIST,
|
||||||
|
ID3v2_FRAME_FILEOWNER,
|
||||||
|
ID3v2_FRAME_ARTIST,
|
||||||
|
ID3v2_FRAME_ALBUMARTIST,
|
||||||
|
ID3v2_FRAME_CONDUCTOR,
|
||||||
|
ID3v2_FRAME_REMIXER,
|
||||||
|
ID3v2_FRAME_PART_O_SET,
|
||||||
|
ID3v2_FRAME_PRODNOTICE,
|
||||||
|
ID3v2_FRAME_PUBLISHER,
|
||||||
|
ID3v2_FRAME_TRACKNUM,
|
||||||
|
ID3v2_FRAME_IRADIONAME,
|
||||||
|
ID3v2_FRAME_IRADIOOWNER,
|
||||||
|
ID3v2_FRAME_ALBUMSORT,
|
||||||
|
ID3v2_FRAME_PERFORMERSORT,
|
||||||
|
ID3v2_FRAME_TITLESORT,
|
||||||
|
ID3v2_FRAME_ISRC,
|
||||||
|
ID3v2_FRAME_ENCODINGSETTINGS,
|
||||||
|
ID3v2_FRAME_SETSUBTITLE,
|
||||||
|
ID3v2_DATE,
|
||||||
|
ID3v2_TIME,
|
||||||
|
ID3v2_ORIGRELYEAR,
|
||||||
|
ID3v2_RECORDINGDATE,
|
||||||
|
ID3v2_FRAME_SIZE,
|
||||||
|
ID3v2_FRAME_YEAR,
|
||||||
|
ID3v2_FRAME_USERDEF_TEXT,
|
||||||
|
ID3v2_FRAME_URLCOMMINFO,
|
||||||
|
ID3v2_FRAME_URLCOPYRIGHT,
|
||||||
|
ID3v2_FRAME_URLAUDIOFILE,
|
||||||
|
ID3v2_FRAME_URLARTIST,
|
||||||
|
ID3v2_FRAME_URLAUDIOSOURCE,
|
||||||
|
ID3v2_FRAME_URLIRADIO,
|
||||||
|
ID3v2_FRAME_URLPAYMENT,
|
||||||
|
ID3v2_FRAME_URLPUBLISHER,
|
||||||
|
ID3v2_FRAME_USERDEF_URL,
|
||||||
|
ID3v2_FRAME_UFID,
|
||||||
|
ID3v2_FRAME_MUSIC_CD_ID,
|
||||||
|
ID3v2_FRAME_COMMENT,
|
||||||
|
ID3v2_FRAME_UNSYNCLYRICS,
|
||||||
|
ID3v2_EMBEDDED_PICTURE,
|
||||||
|
ID3v2_EMBEDDED_PICTURE_V2P2,
|
||||||
|
ID3v2_EMBEDDED_OBJECT,
|
||||||
|
ID3v2_FRAME_GRID,
|
||||||
|
ID3v2_FRAME_SIGNATURE,
|
||||||
|
ID3v2_FRAME_PRIVATE,
|
||||||
|
ID3v2_FRAME_PLAYCOUNTER,
|
||||||
|
ID3v2_FRAME_POPULARITY
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ID3v2_TagFlags {
|
||||||
|
ID32_TAGFLAG_BIT0 = 0x01,
|
||||||
|
ID32_TAGFLAG_BIT1 = 0x02,
|
||||||
|
ID32_TAGFLAG_BIT2 = 0x04,
|
||||||
|
ID32_TAGFLAG_BIT3 = 0x08,
|
||||||
|
ID32_TAGFLAG_FOOTER = 0x10,
|
||||||
|
ID32_TAGFLAG_EXPERIMENTAL = 0x20,
|
||||||
|
ID32_TAGFLAG_EXTENDEDHEADER = 0x40,
|
||||||
|
ID32_TAGFLAG_UNSYNCRONIZATION = 0x80
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ID3v2_FrameFlags {
|
||||||
|
ID32_FRAMEFLAG_STATUS = 0x4000,
|
||||||
|
ID32_FRAMEFLAG_PRESERVE = 0x2000,
|
||||||
|
ID32_FRAMEFLAG_READONLY = 0x1000,
|
||||||
|
ID32_FRAMEFLAG_GROUPING = 0x0040,
|
||||||
|
ID32_FRAMEFLAG_COMPRESSED = 0x0008,
|
||||||
|
ID32_FRAMEFLAG_ENCRYPTED = 0x0004,
|
||||||
|
ID32_FRAMEFLAG_UNSYNCED = 0x0002,
|
||||||
|
ID32_FRAMEFLAG_LENINDICATED = 0x0001
|
||||||
|
};
|
||||||
|
|
||||||
|
// the wording of the ID3 (v2.4 in this case) 'informal standard' is not always
|
||||||
|
// replete with clarity. text encodings are worded as having a NULL terminator
|
||||||
|
// (8or16bit), even for the body of text frames with that in hand, then a
|
||||||
|
// description field from COMM should look much like a utf8 text field and yet
|
||||||
|
// for TXXX, description is expressely worded as:
|
||||||
|
//
|
||||||
|
// "The frame body consists of a description of the string, represented as a
|
||||||
|
// terminated string, followed by the actual string."
|
||||||
|
//
|
||||||
|
// Description <text string according to encoding> $00 (00)
|
||||||
|
// Value <text string according to encoding>
|
||||||
|
//
|
||||||
|
// Note how description is expressly *worded* as having a NULL terminator, but
|
||||||
|
// the text field is not. GEOB text clarifies things better: "The first two
|
||||||
|
// strings [mime & filename] may be omitted, leaving only their terminations.
|
||||||
|
//
|
||||||
|
// MIME type <text string> $00
|
||||||
|
// Filename <text string according to encoding> $00 (00)
|
||||||
|
//
|
||||||
|
// so these trailing $00 (00) are the terminators for the strings - not
|
||||||
|
// separators between n-length string fields. If the string is devoid of
|
||||||
|
// content (not NULLed out, but *devoid* of info), then the only thing that
|
||||||
|
// should exist is for a utf16 BOM to exist on text encoding 0x01. The
|
||||||
|
// (required) terminator for mime & filename are specifically enumerated in the
|
||||||
|
// frame format, which matches the wording of the frame description. ...and so
|
||||||
|
// AP does not terminate text fields
|
||||||
|
//
|
||||||
|
// Further sealing the case is the reference implementation for id3v2.3
|
||||||
|
// (id3lib) doesn't terminate text fields:
|
||||||
|
//
|
||||||
|
// http://sourceforge.net/project/showfiles.php?group_id=979&package_id=4679
|
||||||
|
|
||||||
|
enum text_encodings {
|
||||||
|
TE_LATIN1 = 0,
|
||||||
|
TE_UTF16LE_WITH_BOM = 1,
|
||||||
|
TE_UTF16BE_NO_BOM = 2,
|
||||||
|
TE_UTF8 = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
// Structure that defines the (subset) known ID3 frames defined by id3 informal
|
||||||
|
// specification.
|
||||||
|
typedef struct {
|
||||||
|
const char *ID3V2p2_FrameID;
|
||||||
|
const char *ID3V2p3_FrameID;
|
||||||
|
const char *ID3V2p4_FrameID;
|
||||||
|
const char *ID3V2_FrameDescription;
|
||||||
|
const char *CLI_frameIDpreset;
|
||||||
|
int ID3v2_InternalFrameID;
|
||||||
|
int ID3v2_FrameType;
|
||||||
|
} ID3FrameDefinition;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char *image_mimetype;
|
||||||
|
const char *image_fileextn;
|
||||||
|
uint8_t image_testbytes;
|
||||||
|
const char *image_binaryheader;
|
||||||
|
} ImageFileFormatDefinition;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t hexcode;
|
||||||
|
const char *hexstring;
|
||||||
|
const char *imagetype_str;
|
||||||
|
} ID3ImageType;
|
||||||
|
|
||||||
|
// Structure that defines how any ID3v2FrameType is constructed, listing an
|
||||||
|
// array of its constituent ID3_FieldTypes
|
||||||
|
typedef struct {
|
||||||
|
ID3v2FrameType ID3_FrameType;
|
||||||
|
uint8_t ID3_FieldCount;
|
||||||
|
ID3_FieldTypes ID3_FieldComponents[5]; // max known to be tested
|
||||||
|
} ID3v2FieldDefinition;
|
||||||
|
|
||||||
|
struct ID3v2Fields {
|
||||||
|
int ID3v2_Field_Type;
|
||||||
|
uint32_t field_length;
|
||||||
|
uint32_t alloc_length;
|
||||||
|
char *field_string;
|
||||||
|
ID3v2Fields *next_field;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ID3v2Frame {
|
||||||
|
char ID3v2_Frame_Namestr[5];
|
||||||
|
uint32_t ID3v2_Frame_Length; // this is the real length, not a syncsafe int;
|
||||||
|
// note: does not include frame ID (like 'TIT2',
|
||||||
|
// 'TCO' - 3or4 bytes) or frame flags (2bytes)
|
||||||
|
uint16_t ID3v2_Frame_Flags;
|
||||||
|
|
||||||
|
// these next 2 values can be potentially be stored based on bitsetting in
|
||||||
|
// frame flags;
|
||||||
|
uint8_t ID3v2_Frame_GroupingSymbol;
|
||||||
|
uint32_t ID3v2_Frame_ExpandedLength;
|
||||||
|
|
||||||
|
int ID3v2_Frame_ID;
|
||||||
|
int ID3v2_FrameType;
|
||||||
|
uint8_t ID3v2_FieldCount;
|
||||||
|
uint8_t textfield_tally;
|
||||||
|
ID3v2Fields *ID3v2_Frame_Fields; // malloc
|
||||||
|
ID3v2Frame *ID3v2_NextFrame;
|
||||||
|
bool eliminate_frame;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ID3v2Tag {
|
||||||
|
uint8_t ID3v2Tag_MajorVersion;
|
||||||
|
uint8_t ID3v2Tag_RevisionVersion;
|
||||||
|
uint8_t ID3v2Tag_Flags;
|
||||||
|
uint32_t ID3v2Tag_Length; // this is a bonafide uint_32_t length, not a
|
||||||
|
// syncsafe int
|
||||||
|
|
||||||
|
// this extended header section depends on a bitsetting in ID3v2Tag_Flags
|
||||||
|
uint32_t
|
||||||
|
ID3v2_Tag_ExtendedHeader_Length; // the entire extended header section is
|
||||||
|
// unimplemented flags & flag frames
|
||||||
|
|
||||||
|
ID3v2Frame *ID3v2_FirstFrame;
|
||||||
|
ID3v2Frame *ID3v2_FrameList;
|
||||||
|
uint16_t ID3v2_FrameCount;
|
||||||
|
bool modified_tag;
|
||||||
|
};
|
||||||
4482
src/main.cpp
Normal file
4482
src/main.cpp
Normal file
File diff suppressed because it is too large
Load Diff
2163
src/metalist.cpp
Normal file
2163
src/metalist.cpp
Normal file
File diff suppressed because it is too large
Load Diff
182
src/nsfile.mm
Normal file
182
src/nsfile.mm
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
//==================================================================//
|
||||||
|
/*
|
||||||
|
AtomicParsley - nsfile.mm
|
||||||
|
|
||||||
|
AtomicParsley is GPL software; you can freely distribute,
|
||||||
|
redistribute, modify & use under the terms of the GNU General
|
||||||
|
Public License; either version 2 or its successor.
|
||||||
|
|
||||||
|
AtomicParsley is distributed under the GPL "AS IS", without
|
||||||
|
any warranty; without the implied warranty of merchantability
|
||||||
|
or fitness for either an expressed or implied particular purpose.
|
||||||
|
|
||||||
|
Please see the included GNU General Public License (GPL) for
|
||||||
|
your rights and further details; see the file COPYING. If you
|
||||||
|
cannot, write to the Free Software Foundation, 59 Temple Place
|
||||||
|
Suite 330, Boston, MA 02111-1307, USA. Or www.fsf.org
|
||||||
|
|
||||||
|
Copyright ©2006-2007 puck_lock
|
||||||
|
with contributions from others; see the CREDITS file
|
||||||
|
*/
|
||||||
|
//==================================================================//
|
||||||
|
|
||||||
|
#include "AtomicParsley.h"
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
/*----------------------
|
||||||
|
APar_TestTracksForKind
|
||||||
|
|
||||||
|
By testing which tracks are contained within the file, for Mac OS X we can avoid having to change file extension by instead using Finder.app metadata to signal
|
||||||
|
the same info as file extension. For each trak atom, find the 'stsd' atom - its ancillary_data will contain the track type that is contained - the info is filled
|
||||||
|
in as the file was initially parsed in APar_ScanAtoms. Then using Mac OS X Cocoa calls (in AP_NSFile_utils), set the Finder TYPE/CREATOR codes to signal to the
|
||||||
|
OS/Finder/iTunes that this file is .m4a or .m4v without having to change its extension based on what the tracks actually contain.
|
||||||
|
|
||||||
|
There are 2 issues with this - iTunes requires the Quicktime player type/creator codes for video that has multi-channel audio, and for chapterized video files.
|
||||||
|
TODO: address these issues.
|
||||||
|
----------------------*/
|
||||||
|
void APar_TestTracksForKind() {
|
||||||
|
uint8_t total_tracks = 0;
|
||||||
|
uint8_t track_num = 0;
|
||||||
|
AtomicInfo* codec_atom = NULL; //short codec_atom = 0;
|
||||||
|
|
||||||
|
//With track_num set to 0, it will return the total trak atom into total_tracks here.
|
||||||
|
APar_FindAtomInTrack(total_tracks, track_num, NULL);
|
||||||
|
|
||||||
|
if (total_tracks > 0) {
|
||||||
|
while (total_tracks > track_num) {
|
||||||
|
track_num+= 1;
|
||||||
|
|
||||||
|
codec_atom = APar_FindAtomInTrack(total_tracks, track_num, "stsd");
|
||||||
|
if (codec_atom == NULL) return;
|
||||||
|
|
||||||
|
//now test this trak's stsd codec against these 4cc codes:
|
||||||
|
switch(codec_atom->ancillary_data) {
|
||||||
|
//video types
|
||||||
|
case 0x61766331 : // "avc1"
|
||||||
|
track_codecs.has_avc1 = true;
|
||||||
|
break;
|
||||||
|
case 0x6D703476 : // "mp4v"
|
||||||
|
track_codecs.has_mp4v = true;
|
||||||
|
break;
|
||||||
|
case 0x64726D69 : // "drmi"
|
||||||
|
track_codecs.has_drmi = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
//audio types
|
||||||
|
case 0x616C6163 : // "alac"
|
||||||
|
track_codecs.has_alac = true;
|
||||||
|
break;
|
||||||
|
case 0x6D703461 : // "mp4a"
|
||||||
|
track_codecs.has_mp4a = true;
|
||||||
|
break;
|
||||||
|
case 0x64726D73 : // "drms"
|
||||||
|
track_codecs.has_drms = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
//chapterized types (audio podcasts or movies)
|
||||||
|
case 0x74657874 : // "text"
|
||||||
|
track_codecs.has_timed_text = true;
|
||||||
|
break;
|
||||||
|
case 0x6A706567 : // "jpeg"
|
||||||
|
track_codecs.has_timed_jpeg = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
//either podcast type (audio-only) or timed text subtitles
|
||||||
|
case 0x74783367 : // "tx3g"
|
||||||
|
track_codecs.has_timed_tx3g = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
//other
|
||||||
|
case 0x6D703473 : // "mp4s"
|
||||||
|
track_codecs.has_mp4s = true;
|
||||||
|
break;
|
||||||
|
case 0x72747020 : // "rtp "
|
||||||
|
track_codecs.has_rtp_hint = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//TODO: there is a problem with this code seen in: "5.1channel audio-orig.mp4"
|
||||||
|
//it makes no difference what the file contains, iTunes won't see any (ANY) metadata if its hook/'M4A '.
|
||||||
|
//in fact, iTunes won't play the file at all
|
||||||
|
//changing the exact file (with all kinds of metadata) to TVOD/mpg4 - iTunes can play it fine, but doesn't fetch any metadata
|
||||||
|
//
|
||||||
|
//it might be beneficial to eval for channels and if its audio only & multichannel to NOT change the TYPE/creator codes
|
||||||
|
|
||||||
|
uint32_t APar_4CC_CreatorCode(const char* filepath, uint32_t new_type_code) {
|
||||||
|
uint32_t return_value = 0;
|
||||||
|
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
|
||||||
|
|
||||||
|
NSString *inFile = [NSString stringWithUTF8String: filepath];
|
||||||
|
|
||||||
|
if (new_type_code) {
|
||||||
|
NSNumber* creator_code = [NSNumber numberWithUnsignedLong:'hook'];
|
||||||
|
NSNumber* type_code = [NSNumber numberWithUnsignedLong:new_type_code];
|
||||||
|
NSDictionary* output_attributes = [NSDictionary dictionaryWithObjectsAndKeys:creator_code, NSFileHFSCreatorCode,
|
||||||
|
type_code, NSFileHFSTypeCode, nil];
|
||||||
|
|
||||||
|
if (![[NSFileManager defaultManager] changeFileAttributes:output_attributes atPath:inFile]) {
|
||||||
|
NSLog(@" AtomicParsley error: setting type and creator code on %@", inFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
NSDictionary* file_attributes = [[NSFileManager defaultManager] fileAttributesAtPath:inFile traverseLink:YES];
|
||||||
|
return_value = [[file_attributes objectForKey:NSFileHFSTypeCode] unsignedLongValue ];
|
||||||
|
|
||||||
|
//NSLog(@"code: %@\n", [file_attributes objectForKey:NSFileHFSTypeCode] );
|
||||||
|
}
|
||||||
|
|
||||||
|
[pool release];
|
||||||
|
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
//there is a scenario that is as of now unsupported (or botched, depending if you use the feature), although it would be easy to implement. To make a file bookmarkable, the TYPE code is set to 'M4B ' - which can be *also* done by changing the extension to ".m4b". However, due to the way that the file is tested here, a ".mp4" with 'M4B ' type code will get changed into a normal audio file (not-bookmarkable).
|
||||||
|
|
||||||
|
void APar_SupplySelectiveTypeCreatorCodes(const char *inputPath, const char *outputPath, uint8_t forced_type_code) {
|
||||||
|
if (forced_type_code != NO_TYPE_FORCING) {
|
||||||
|
if (forced_type_code == FORCE_M4B_TYPE) {
|
||||||
|
APar_4CC_CreatorCode(outputPath, 'M4B ');
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* input_suffix = strrchr(inputPath, '.');
|
||||||
|
//user-defined output paths may have the original file as ".m4a" & show up fine when output to ".m4a"
|
||||||
|
//output to ".mp4" and it becomes a generic (sans TYPE/CREATOR) file that defaults to Quicktime Player
|
||||||
|
const char* output_suffix = strrchr(outputPath, '.');
|
||||||
|
|
||||||
|
char* typecode = (char*)malloc( sizeof(char)* 4 );
|
||||||
|
memset(typecode, 0, sizeof(char)*4);
|
||||||
|
|
||||||
|
uint32_t type_code = APar_4CC_CreatorCode(inputPath, 0);
|
||||||
|
|
||||||
|
UInt32_TO_String4(type_code, typecode);
|
||||||
|
|
||||||
|
//fprintf(stdout, "%s - %s\n", typecode, input_suffix);
|
||||||
|
APar_TestTracksForKind();
|
||||||
|
|
||||||
|
if (strncasecmp(input_suffix, ".mp4", 4) == 0 || strncasecmp(output_suffix, ".mp4", 4) == 0) { //only work on the generic .mp4 extension
|
||||||
|
if (track_codecs.has_avc1 || track_codecs.has_mp4v || track_codecs.has_drmi) {
|
||||||
|
type_code = APar_4CC_CreatorCode(outputPath, 'M4V ');
|
||||||
|
|
||||||
|
//for a podcast an audio track with either a text, jpeg or url track is required, otherwise it will fall through to generic m4a;
|
||||||
|
//files that are already .m4b or 'M4B ' don't even enter into this situation, so they are safe
|
||||||
|
//if the file had video with subtitles (tx3g), then it would get taken care of above in the video section - unsupported by QT currently
|
||||||
|
} else if (track_codecs.has_mp4a && (track_codecs.has_timed_text || track_codecs.has_timed_jpeg || track_codecs.has_timed_tx3g) ) {
|
||||||
|
type_code = APar_4CC_CreatorCode(outputPath, 'M4B ');
|
||||||
|
|
||||||
|
//default to audio; technically so would a drms iTMS drm audio file with ".mp4". But that would also mean it was renamed. They should be 'M4P '
|
||||||
|
} else {
|
||||||
|
type_code = APar_4CC_CreatorCode(outputPath, 'M4A ');
|
||||||
|
}
|
||||||
|
} else if (track_codecs.has_avc1 || track_codecs.has_mp4v || track_codecs.has_drmi) {
|
||||||
|
type_code = APar_4CC_CreatorCode(outputPath, 'M4V ');
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
244
src/nsimage.mm
Normal file
244
src/nsimage.mm
Normal file
@ -0,0 +1,244 @@
|
|||||||
|
//==================================================================//
|
||||||
|
/*
|
||||||
|
AtomicParsley - nsimage.mm
|
||||||
|
|
||||||
|
AtomicParsley is GPL software; you can freely distribute,
|
||||||
|
redistribute, modify & use under the terms of the GNU General
|
||||||
|
Public License; either version 2 or its successor.
|
||||||
|
|
||||||
|
AtomicParsley is distributed under the GPL "AS IS", without
|
||||||
|
any warranty; without the implied warranty of merchantability
|
||||||
|
or fitness for either an expressed or implied particular purpose.
|
||||||
|
|
||||||
|
Please see the included GNU General Public License (GPL) for
|
||||||
|
your rights and further details; see the file COPYING. If you
|
||||||
|
cannot, write to the Free Software Foundation, 59 Temple Place
|
||||||
|
Suite 330, Boston, MA 02111-1307, USA. Or www.fsf.org
|
||||||
|
|
||||||
|
Copyright ©2005-2007 puck_lock
|
||||||
|
with contributions from others; see the CREDITS file
|
||||||
|
*/
|
||||||
|
//==================================================================//
|
||||||
|
|
||||||
|
#include "AtomicParsley.h"
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
bool isJPEG=false;
|
||||||
|
bool isPNG=false;
|
||||||
|
|
||||||
|
void DetermineType(const char *picfilePath) {
|
||||||
|
char* picHeader = (char*)calloc(1, sizeof(char)*20);
|
||||||
|
u_int64_t r;
|
||||||
|
|
||||||
|
FILE *pic_file = NULL;
|
||||||
|
pic_file = fopen(picfilePath, "rb");
|
||||||
|
r = fread(picHeader, 8, 1, pic_file);
|
||||||
|
fclose(pic_file);
|
||||||
|
|
||||||
|
if (memcmp(picHeader, "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A", 8) == 0) {
|
||||||
|
isPNG=true;
|
||||||
|
isJPEG=false;
|
||||||
|
} else if (memcmp(picHeader, "\xFF\xD8\xFF", 3) == 0) {
|
||||||
|
isJPEG=true;
|
||||||
|
isPNG=false;
|
||||||
|
}
|
||||||
|
free(picHeader);
|
||||||
|
picHeader=NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* DeriveNewPath(const char *filePath, PicPrefs myPicPrefs, char* newpath) {
|
||||||
|
const char* suffix = strrchr(filePath, '.');
|
||||||
|
|
||||||
|
size_t filepath_len = strlen(filePath);
|
||||||
|
memset(newpath, 0, MAXPATHLEN+1);
|
||||||
|
size_t base_len = filepath_len-strlen(suffix);
|
||||||
|
memcpy(newpath, filePath, base_len);
|
||||||
|
memcpy(newpath+base_len, "-resized-", 9);
|
||||||
|
|
||||||
|
char* randstring = (char*)calloc(1, sizeof(char)*20);
|
||||||
|
struct timeval tv;
|
||||||
|
gettimeofday (&tv, NULL);
|
||||||
|
|
||||||
|
srand( (int) tv.tv_usec / 1000 ); //Seeds rand()
|
||||||
|
int randNum = rand()%10000;
|
||||||
|
sprintf(randstring, "%i", randNum);
|
||||||
|
strcat(newpath, randstring);
|
||||||
|
|
||||||
|
if (myPicPrefs.allJPEG) {
|
||||||
|
strcat(newpath, ".jpg");
|
||||||
|
} else if (myPicPrefs.allPNG) {
|
||||||
|
strcat(newpath, ".png");
|
||||||
|
} else {
|
||||||
|
strcat(newpath, suffix);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( (strncmp(suffix,".jpg",4) == 0) || (strncmp(suffix,".jpeg",5) == 0) || (strncmp(suffix,".JPG",4) == 0) || (strncmp(suffix,".JPEG",5) == 0) ) {
|
||||||
|
isJPEG=true;
|
||||||
|
} else if ((strncmp(suffix,".png",4) == 0) || (strncmp(suffix,".PNG",4) == 0)) {
|
||||||
|
isPNG=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(randstring);
|
||||||
|
randstring=NULL;
|
||||||
|
return newpath;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ResizeGivenImage(const char* filePath, PicPrefs myPicPrefs, char* resized_path) {
|
||||||
|
bool resize = false;
|
||||||
|
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||||
|
|
||||||
|
NSImage* source = [ [NSImage alloc] initWithContentsOfFile: [NSString stringWithUTF8String: filePath] ];
|
||||||
|
[source setScalesWhenResized: YES];
|
||||||
|
if ( source == nil ) {
|
||||||
|
fprintf( stderr, "Image '%s' could not be loaded.\n", filePath );
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
NSSize sourceSize = [source size];
|
||||||
|
float hmax, vmax, aspect;
|
||||||
|
hmax = sourceSize.width;
|
||||||
|
vmax = sourceSize.height;
|
||||||
|
aspect = sourceSize.height / sourceSize.width;
|
||||||
|
//fprintf(stdout, "aspect %f2.4\n", aspect);
|
||||||
|
if (myPicPrefs.max_dimension != 0) {
|
||||||
|
if ( ( (int)sourceSize.width > myPicPrefs.max_dimension) || ( (int)sourceSize.height > myPicPrefs.max_dimension) ) {
|
||||||
|
resize = true; //only if dimensions are LARGER than our max do we resize
|
||||||
|
if (hmax > vmax) {
|
||||||
|
hmax = myPicPrefs.max_dimension;
|
||||||
|
vmax = myPicPrefs.max_dimension * aspect;
|
||||||
|
} else {
|
||||||
|
hmax = myPicPrefs.max_dimension / aspect;
|
||||||
|
vmax = myPicPrefs.max_dimension;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///// determine dpi/ppi
|
||||||
|
float hres, vres, hdpi, vdpi;
|
||||||
|
NSImageRep *myRep = [[source representations] objectAtIndex:0];
|
||||||
|
hres = [myRep pixelsWide]; //native pixel dimensions
|
||||||
|
vres = [myRep pixelsHigh];
|
||||||
|
hdpi = hres/sourceSize.width; //in native resolution (multiply by 72 to get native dpi)
|
||||||
|
vdpi = vres/sourceSize.height;
|
||||||
|
|
||||||
|
if ( ( (int)hdpi != 1 ) || ( (int)vdpi != 1) ) {
|
||||||
|
resize = true;
|
||||||
|
hmax = hres;
|
||||||
|
vmax = vres;
|
||||||
|
if (myPicPrefs.max_dimension != 0) {
|
||||||
|
//we also need to recheck we don't go over our max dimensions (again)
|
||||||
|
if ( ( (int)hres > myPicPrefs.max_dimension) || ( (int)vres > myPicPrefs.max_dimension) ) {
|
||||||
|
if (hmax > vmax) {
|
||||||
|
hmax = myPicPrefs.max_dimension;
|
||||||
|
vmax = myPicPrefs.max_dimension * aspect;
|
||||||
|
} else {
|
||||||
|
hmax = myPicPrefs.max_dimension / aspect;
|
||||||
|
vmax = myPicPrefs.max_dimension;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (myPicPrefs.squareUp) {
|
||||||
|
if (myPicPrefs.max_dimension != 0) {
|
||||||
|
vmax = myPicPrefs.max_dimension;
|
||||||
|
hmax = myPicPrefs.max_dimension;
|
||||||
|
resize = true;
|
||||||
|
} else {
|
||||||
|
//this will stretch the image to the largest dimension. Hope you don't try to scale a 160x1200 image... it could get ugly
|
||||||
|
if (hmax > vmax) {
|
||||||
|
vmax = hmax;
|
||||||
|
resize = true;
|
||||||
|
} else if (vmax > hmax) {
|
||||||
|
hmax = vmax;
|
||||||
|
resize = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (myPicPrefs.force_dimensions) {
|
||||||
|
if (myPicPrefs.force_height > 0 && myPicPrefs.force_width > 0) {
|
||||||
|
vmax = myPicPrefs.force_height;
|
||||||
|
hmax = myPicPrefs.force_width;
|
||||||
|
resize = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t pic_file_size = findFileSize(filePath);
|
||||||
|
if ( ( (int)pic_file_size > myPicPrefs.max_Kbytes) && ( myPicPrefs.max_Kbytes != 0) ) {
|
||||||
|
resize = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
DetermineType(filePath);
|
||||||
|
if ( (isJPEG && myPicPrefs.allPNG) || (isPNG && myPicPrefs.allJPEG) ) { //handle jpeg->png & png->jpg conversion
|
||||||
|
resize = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
NSRect destinationRect = NSMakeRect( 0, 0, hmax, vmax );
|
||||||
|
NSSize size = NSMakeSize( hmax, vmax );
|
||||||
|
|
||||||
|
if (resize) {
|
||||||
|
[NSApplication sharedApplication];
|
||||||
|
[[NSGraphicsContext currentContext] setImageInterpolation: NSImageInterpolationHigh];
|
||||||
|
|
||||||
|
[source setSize: size];
|
||||||
|
|
||||||
|
NSImage* image = [[NSImage alloc] initWithSize:size];
|
||||||
|
[image lockFocus];
|
||||||
|
|
||||||
|
NSEraseRect( destinationRect );
|
||||||
|
[source drawInRect: destinationRect
|
||||||
|
fromRect: destinationRect
|
||||||
|
operation: NSCompositeCopy fraction: 1.0];
|
||||||
|
|
||||||
|
NSBitmapImageRep* bitmap = [ [NSBitmapImageRep alloc]
|
||||||
|
initWithFocusedViewRect: destinationRect ];
|
||||||
|
NSBitmapImageFileType filetype;
|
||||||
|
NSDictionary *props;
|
||||||
|
|
||||||
|
if ( (isPNG && !myPicPrefs.allJPEG) || myPicPrefs.allPNG) {
|
||||||
|
filetype = NSPNGFileType;
|
||||||
|
props = nil;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
filetype = NSJPEGFileType;
|
||||||
|
props = [ NSDictionary dictionaryWithObject:
|
||||||
|
[NSNumber numberWithFloat: 0.7] forKey: NSImageCompressionFactor];
|
||||||
|
}
|
||||||
|
NSData* data = [bitmap representationUsingType:filetype properties:props];
|
||||||
|
|
||||||
|
unsigned dataLength = [data length]; //holds the file length
|
||||||
|
|
||||||
|
int iter = 0;
|
||||||
|
float compression = 0.65;
|
||||||
|
if ( (myPicPrefs.max_Kbytes != 0) && (filetype == NSJPEGFileType) ) {
|
||||||
|
while ( (dataLength > (unsigned)myPicPrefs.max_Kbytes) && (iter < 10) ) {
|
||||||
|
props = [ NSDictionary dictionaryWithObject:
|
||||||
|
[NSNumber numberWithFloat: compression] forKey: NSImageCompressionFactor];
|
||||||
|
data = [bitmap representationUsingType:filetype properties:props];
|
||||||
|
dataLength = [data length];
|
||||||
|
compression = compression - 0.05;
|
||||||
|
iter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[bitmap release];
|
||||||
|
NSString *outFile= [NSString stringWithUTF8String: DeriveNewPath(filePath, myPicPrefs, resized_path)];
|
||||||
|
//NSLog(outFile);
|
||||||
|
[[NSFileManager defaultManager]
|
||||||
|
createFileAtPath: outFile
|
||||||
|
contents: data
|
||||||
|
attributes: nil ];
|
||||||
|
|
||||||
|
[image unlockFocus];
|
||||||
|
[image release];
|
||||||
|
isJPEG=false;
|
||||||
|
isPNG=false;
|
||||||
|
memcpy(resized_path, [outFile cStringUsingEncoding: NSUTF8StringEncoding], [outFile lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
|
||||||
|
}
|
||||||
|
[source release];
|
||||||
|
[pool release];
|
||||||
|
return resize;
|
||||||
|
}
|
||||||
6537
src/parsley.cpp
Normal file
6537
src/parsley.cpp
Normal file
File diff suppressed because it is too large
Load Diff
402
src/sha1.cpp
Normal file
402
src/sha1.cpp
Normal file
@ -0,0 +1,402 @@
|
|||||||
|
/* sha1.cpp - Functions to compute SHA1 message digest of files or
|
||||||
|
memory blocks according to the NIST specification FIPS-180-1.
|
||||||
|
|
||||||
|
Copyright (C) 2000, 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by the
|
||||||
|
Free Software Foundation; either version 2, or (at your option) any
|
||||||
|
later version.
|
||||||
|
|
||||||
|
This program 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software Foundation,
|
||||||
|
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||||
|
|
||||||
|
/* Written by Scott G. Miller
|
||||||
|
Credits:
|
||||||
|
Robert Klep <robert@ilse.nl> -- Expansion function fix
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
This file has been modified from the original found in
|
||||||
|
http://www.gnu.org/software/coreutils/ coreutils-5.97 for use within
|
||||||
|
AtomicParsley. Modifications are : endian detection change a cast for
|
||||||
|
compiling under g++ file renaming eliminated SWAP in favor of swap32 & swap16
|
||||||
|
in util.h alignment macros (for msvc)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "AtomicParsley.h"
|
||||||
|
|
||||||
|
/* SWAP does an endian swap on architectures that are little-endian,
|
||||||
|
as SHA1 needs some data in a big-endian form. */
|
||||||
|
/*
|
||||||
|
#if defined (__ppc__) || defined (__ppc64__)
|
||||||
|
# define SWAP(n) (n)
|
||||||
|
#else
|
||||||
|
# define SWAP(n) \
|
||||||
|
(((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
|
||||||
|
#endif
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define BLOCKSIZE 4096
|
||||||
|
#if BLOCKSIZE % 64 != 0
|
||||||
|
#error "invalid BLOCKSIZE"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* This array contains the bytes used to pad the buffer to the next
|
||||||
|
64-byte boundary. (RFC 1321, 3.1: Step 1) */
|
||||||
|
static const unsigned char fillbuf[64] = {0x80, 0 /* , 0, 0, ... */};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Takes a pointer to a 160 bit block of data (five 32 bit ints) and
|
||||||
|
intializes it to the start constants of the SHA1 algorithm. This
|
||||||
|
must be called before using hash in the call to sha1_hash.
|
||||||
|
*/
|
||||||
|
void sha1_init_ctx(struct sha1_ctx *ctx) {
|
||||||
|
ctx->A = 0x67452301;
|
||||||
|
ctx->B = 0xefcdab89;
|
||||||
|
ctx->C = 0x98badcfe;
|
||||||
|
ctx->D = 0x10325476;
|
||||||
|
ctx->E = 0xc3d2e1f0;
|
||||||
|
|
||||||
|
ctx->total[0] = ctx->total[1] = 0;
|
||||||
|
ctx->buflen = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Put result from CTX in first 20 bytes following RESBUF. The result
|
||||||
|
must be in little endian byte order.
|
||||||
|
|
||||||
|
IMPORTANT: On some systems it is required that RESBUF is correctly
|
||||||
|
aligned for a 32 bits value. */
|
||||||
|
void *sha1_read_ctx(const struct sha1_ctx *ctx, void *resbuf) {
|
||||||
|
((md5_uint32 *)resbuf)[0] = SWAP32(ctx->A);
|
||||||
|
((md5_uint32 *)resbuf)[1] = SWAP32(ctx->B);
|
||||||
|
((md5_uint32 *)resbuf)[2] = SWAP32(ctx->C);
|
||||||
|
((md5_uint32 *)resbuf)[3] = SWAP32(ctx->D);
|
||||||
|
((md5_uint32 *)resbuf)[4] = SWAP32(ctx->E);
|
||||||
|
|
||||||
|
return resbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Process the remaining bytes in the internal buffer and the usual
|
||||||
|
prolog according to the standard and write the result to RESBUF.
|
||||||
|
|
||||||
|
IMPORTANT: On some systems it is required that RESBUF is correctly
|
||||||
|
aligned for a 32 bits value. */
|
||||||
|
void *sha1_finish_ctx(struct sha1_ctx *ctx, void *resbuf) {
|
||||||
|
/* Take yet unprocessed bytes into account. */
|
||||||
|
md5_uint32 bytes = ctx->buflen;
|
||||||
|
size_t pad;
|
||||||
|
|
||||||
|
/* Now count remaining bytes. */
|
||||||
|
ctx->total[0] += bytes;
|
||||||
|
if (ctx->total[0] < bytes)
|
||||||
|
++ctx->total[1];
|
||||||
|
|
||||||
|
pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
|
||||||
|
memcpy(&ctx->buffer[bytes], fillbuf, pad);
|
||||||
|
|
||||||
|
/* Put the 64-bit file length in *bits* at the end of the buffer. */
|
||||||
|
*(md5_uint32 *)&ctx->buffer[bytes + pad + 4] = SWAP32(ctx->total[0] << 3);
|
||||||
|
*(md5_uint32 *)&ctx->buffer[bytes + pad] =
|
||||||
|
SWAP32((ctx->total[1] << 3) | (ctx->total[0] >> 29));
|
||||||
|
|
||||||
|
/* Process last bytes. */
|
||||||
|
sha1_process_block(ctx->buffer, bytes + pad + 8, ctx);
|
||||||
|
|
||||||
|
return sha1_read_ctx(ctx, resbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compute SHA1 message digest for bytes read from STREAM. The
|
||||||
|
resulting message digest number will be written into the 16 bytes
|
||||||
|
beginning at RESBLOCK. */
|
||||||
|
int sha1_stream(FILE *stream, void *resblock) {
|
||||||
|
struct sha1_ctx ctx;
|
||||||
|
char buffer[BLOCKSIZE + 72];
|
||||||
|
size_t sum;
|
||||||
|
|
||||||
|
/* Initialize the computation context. */
|
||||||
|
sha1_init_ctx(&ctx);
|
||||||
|
|
||||||
|
/* Iterate over full file contents. */
|
||||||
|
while (1) {
|
||||||
|
/* We read the file in blocks of BLOCKSIZE bytes. One call of the
|
||||||
|
computation function processes the whole buffer so that with the
|
||||||
|
next round of the loop another block can be read. */
|
||||||
|
size_t n;
|
||||||
|
sum = 0;
|
||||||
|
|
||||||
|
/* Read block. Take care for partial reads. */
|
||||||
|
while (1) {
|
||||||
|
n = fread(buffer + sum, 1, BLOCKSIZE - sum, stream);
|
||||||
|
|
||||||
|
sum += n;
|
||||||
|
|
||||||
|
if (sum == BLOCKSIZE)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (n == 0) {
|
||||||
|
/* Check for the error flag IFF N == 0, so that we don't
|
||||||
|
exit the loop after a partial read due to e.g., EAGAIN
|
||||||
|
or EWOULDBLOCK. */
|
||||||
|
if (ferror(stream))
|
||||||
|
return 1;
|
||||||
|
goto process_partial_block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We've read at least one byte, so ignore errors. But always
|
||||||
|
check for EOF, since feof may be true even though N > 0.
|
||||||
|
Otherwise, we could end up calling fread after EOF. */
|
||||||
|
if (feof(stream))
|
||||||
|
goto process_partial_block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Process buffer with BLOCKSIZE bytes. Note that
|
||||||
|
BLOCKSIZE % 64 == 0
|
||||||
|
*/
|
||||||
|
sha1_process_block(buffer, BLOCKSIZE, &ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
process_partial_block:;
|
||||||
|
|
||||||
|
/* Process any remaining bytes. */
|
||||||
|
if (sum > 0)
|
||||||
|
sha1_process_bytes(buffer, sum, &ctx);
|
||||||
|
|
||||||
|
/* Construct result in desired memory. */
|
||||||
|
sha1_finish_ctx(&ctx, resblock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The
|
||||||
|
result is always in little endian byte order, so that a byte-wise
|
||||||
|
output yields to the wanted ASCII representation of the message
|
||||||
|
digest. */
|
||||||
|
void *sha1_buffer(const char *buffer, size_t len, void *resblock) {
|
||||||
|
struct sha1_ctx ctx;
|
||||||
|
|
||||||
|
/* Initialize the computation context. */
|
||||||
|
sha1_init_ctx(&ctx);
|
||||||
|
|
||||||
|
/* Process whole buffer but last len % 64 bytes. */
|
||||||
|
sha1_process_bytes(buffer, len, &ctx);
|
||||||
|
|
||||||
|
/* Put result in desired memory area. */
|
||||||
|
return sha1_finish_ctx(&ctx, resblock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sha1_process_bytes(const void *buffer, size_t len, struct sha1_ctx *ctx) {
|
||||||
|
/* When we already have some bits in our internal buffer concatenate
|
||||||
|
both inputs first. */
|
||||||
|
if (ctx->buflen != 0) {
|
||||||
|
size_t left_over = ctx->buflen;
|
||||||
|
size_t add = 128 - left_over > len ? len : 128 - left_over;
|
||||||
|
|
||||||
|
memcpy(&ctx->buffer[left_over], buffer, add);
|
||||||
|
ctx->buflen += add;
|
||||||
|
|
||||||
|
if (ctx->buflen > 64) {
|
||||||
|
sha1_process_block(ctx->buffer, ctx->buflen & ~63, ctx);
|
||||||
|
|
||||||
|
ctx->buflen &= 63;
|
||||||
|
/* The regions in the following copy operation cannot overlap. */
|
||||||
|
memcpy(ctx->buffer, &ctx->buffer[(left_over + add) & ~63], ctx->buflen);
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = (const char *)buffer + add;
|
||||||
|
len -= add;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Process available complete blocks. */
|
||||||
|
if (len >= 64) {
|
||||||
|
#if !_STRING_ARCH_unaligned
|
||||||
|
#define alignof(type) \
|
||||||
|
offsetof( \
|
||||||
|
struct { \
|
||||||
|
char c; \
|
||||||
|
type x; \
|
||||||
|
}, \
|
||||||
|
x)
|
||||||
|
#define UNALIGNED_P(p) \
|
||||||
|
(((size_t)p) % 4 != \
|
||||||
|
0) //# define UNALIGNED_P(p) (((size_t) p) % alignof (md5_uint32) != 0)
|
||||||
|
if (UNALIGNED_P(buffer))
|
||||||
|
while (len > 64) {
|
||||||
|
sha1_process_block(memcpy(ctx->buffer, buffer, 64), 64, ctx);
|
||||||
|
buffer = (const char *)buffer + 64;
|
||||||
|
len -= 64;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
sha1_process_block(buffer, len & ~63, ctx);
|
||||||
|
buffer = (const char *)buffer + (len & ~63);
|
||||||
|
len &= 63;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Move remaining bytes in internal buffer. */
|
||||||
|
if (len > 0) {
|
||||||
|
size_t left_over = ctx->buflen;
|
||||||
|
|
||||||
|
memcpy(&ctx->buffer[left_over], buffer, len);
|
||||||
|
left_over += len;
|
||||||
|
if (left_over >= 64) {
|
||||||
|
sha1_process_block(ctx->buffer, 64, ctx);
|
||||||
|
left_over -= 64;
|
||||||
|
memcpy(ctx->buffer, &ctx->buffer[64], left_over);
|
||||||
|
}
|
||||||
|
ctx->buflen = left_over;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Code below is the primary difference between md5.c and sha1.c --- */
|
||||||
|
|
||||||
|
/* SHA1 round constants */
|
||||||
|
#define K1 0x5a827999L
|
||||||
|
#define K2 0x6ed9eba1L
|
||||||
|
#define K3 0x8f1bbcdcL
|
||||||
|
#define K4 0xca62c1d6L
|
||||||
|
|
||||||
|
/* Round functions. Note that F2 is the same as F4. */
|
||||||
|
#define F1(B, C, D) (D ^ (B & (C ^ D)))
|
||||||
|
#define F2(B, C, D) (B ^ C ^ D)
|
||||||
|
#define F3(B, C, D) ((B & C) | (D & (B | C)))
|
||||||
|
#define F4(B, C, D) (B ^ C ^ D)
|
||||||
|
|
||||||
|
/* Process LEN bytes of BUFFER, accumulating context into CTX.
|
||||||
|
It is assumed that LEN % 64 == 0.
|
||||||
|
Most of this code comes from GnuPG's cipher/sha1.c. */
|
||||||
|
|
||||||
|
void sha1_process_block(const void *buffer, size_t len, struct sha1_ctx *ctx) {
|
||||||
|
const md5_uint32 *words = (md5_uint32 *)buffer;
|
||||||
|
size_t nwords = len / sizeof(md5_uint32);
|
||||||
|
const md5_uint32 *endp = words + nwords;
|
||||||
|
md5_uint32 x[16];
|
||||||
|
md5_uint32 a = ctx->A;
|
||||||
|
md5_uint32 b = ctx->B;
|
||||||
|
md5_uint32 c = ctx->C;
|
||||||
|
md5_uint32 d = ctx->D;
|
||||||
|
md5_uint32 e = ctx->E;
|
||||||
|
|
||||||
|
/* First increment the byte count. RFC 1321 specifies the possible
|
||||||
|
length of the file up to 2^64 bits. Here we only compute the
|
||||||
|
number of bytes. Do a double word increment. */
|
||||||
|
ctx->total[0] += len;
|
||||||
|
if (ctx->total[0] < len)
|
||||||
|
++ctx->total[1];
|
||||||
|
|
||||||
|
#define rol(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
|
||||||
|
|
||||||
|
#define M(I) \
|
||||||
|
(tm = x[I & 0x0f] ^ x[(I - 14) & 0x0f] ^ x[(I - 8) & 0x0f] ^ \
|
||||||
|
x[(I - 3) & 0x0f], \
|
||||||
|
(x[I & 0x0f] = rol(tm, 1)))
|
||||||
|
|
||||||
|
#define R(A, B, C, D, E, F, K, M) \
|
||||||
|
do { \
|
||||||
|
E += rol(A, 5) + F(B, C, D) + K + M; \
|
||||||
|
B = rol(B, 30); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
while (words < endp) {
|
||||||
|
md5_uint32 tm;
|
||||||
|
int t;
|
||||||
|
for (t = 0; t < 16; t++) {
|
||||||
|
x[t] = SWAP32(*words);
|
||||||
|
words++;
|
||||||
|
}
|
||||||
|
|
||||||
|
R(a, b, c, d, e, F1, K1, x[0]);
|
||||||
|
R(e, a, b, c, d, F1, K1, x[1]);
|
||||||
|
R(d, e, a, b, c, F1, K1, x[2]);
|
||||||
|
R(c, d, e, a, b, F1, K1, x[3]);
|
||||||
|
R(b, c, d, e, a, F1, K1, x[4]);
|
||||||
|
R(a, b, c, d, e, F1, K1, x[5]);
|
||||||
|
R(e, a, b, c, d, F1, K1, x[6]);
|
||||||
|
R(d, e, a, b, c, F1, K1, x[7]);
|
||||||
|
R(c, d, e, a, b, F1, K1, x[8]);
|
||||||
|
R(b, c, d, e, a, F1, K1, x[9]);
|
||||||
|
R(a, b, c, d, e, F1, K1, x[10]);
|
||||||
|
R(e, a, b, c, d, F1, K1, x[11]);
|
||||||
|
R(d, e, a, b, c, F1, K1, x[12]);
|
||||||
|
R(c, d, e, a, b, F1, K1, x[13]);
|
||||||
|
R(b, c, d, e, a, F1, K1, x[14]);
|
||||||
|
R(a, b, c, d, e, F1, K1, x[15]);
|
||||||
|
R(e, a, b, c, d, F1, K1, M(16));
|
||||||
|
R(d, e, a, b, c, F1, K1, M(17));
|
||||||
|
R(c, d, e, a, b, F1, K1, M(18));
|
||||||
|
R(b, c, d, e, a, F1, K1, M(19));
|
||||||
|
R(a, b, c, d, e, F2, K2, M(20));
|
||||||
|
R(e, a, b, c, d, F2, K2, M(21));
|
||||||
|
R(d, e, a, b, c, F2, K2, M(22));
|
||||||
|
R(c, d, e, a, b, F2, K2, M(23));
|
||||||
|
R(b, c, d, e, a, F2, K2, M(24));
|
||||||
|
R(a, b, c, d, e, F2, K2, M(25));
|
||||||
|
R(e, a, b, c, d, F2, K2, M(26));
|
||||||
|
R(d, e, a, b, c, F2, K2, M(27));
|
||||||
|
R(c, d, e, a, b, F2, K2, M(28));
|
||||||
|
R(b, c, d, e, a, F2, K2, M(29));
|
||||||
|
R(a, b, c, d, e, F2, K2, M(30));
|
||||||
|
R(e, a, b, c, d, F2, K2, M(31));
|
||||||
|
R(d, e, a, b, c, F2, K2, M(32));
|
||||||
|
R(c, d, e, a, b, F2, K2, M(33));
|
||||||
|
R(b, c, d, e, a, F2, K2, M(34));
|
||||||
|
R(a, b, c, d, e, F2, K2, M(35));
|
||||||
|
R(e, a, b, c, d, F2, K2, M(36));
|
||||||
|
R(d, e, a, b, c, F2, K2, M(37));
|
||||||
|
R(c, d, e, a, b, F2, K2, M(38));
|
||||||
|
R(b, c, d, e, a, F2, K2, M(39));
|
||||||
|
R(a, b, c, d, e, F3, K3, M(40));
|
||||||
|
R(e, a, b, c, d, F3, K3, M(41));
|
||||||
|
R(d, e, a, b, c, F3, K3, M(42));
|
||||||
|
R(c, d, e, a, b, F3, K3, M(43));
|
||||||
|
R(b, c, d, e, a, F3, K3, M(44));
|
||||||
|
R(a, b, c, d, e, F3, K3, M(45));
|
||||||
|
R(e, a, b, c, d, F3, K3, M(46));
|
||||||
|
R(d, e, a, b, c, F3, K3, M(47));
|
||||||
|
R(c, d, e, a, b, F3, K3, M(48));
|
||||||
|
R(b, c, d, e, a, F3, K3, M(49));
|
||||||
|
R(a, b, c, d, e, F3, K3, M(50));
|
||||||
|
R(e, a, b, c, d, F3, K3, M(51));
|
||||||
|
R(d, e, a, b, c, F3, K3, M(52));
|
||||||
|
R(c, d, e, a, b, F3, K3, M(53));
|
||||||
|
R(b, c, d, e, a, F3, K3, M(54));
|
||||||
|
R(a, b, c, d, e, F3, K3, M(55));
|
||||||
|
R(e, a, b, c, d, F3, K3, M(56));
|
||||||
|
R(d, e, a, b, c, F3, K3, M(57));
|
||||||
|
R(c, d, e, a, b, F3, K3, M(58));
|
||||||
|
R(b, c, d, e, a, F3, K3, M(59));
|
||||||
|
R(a, b, c, d, e, F4, K4, M(60));
|
||||||
|
R(e, a, b, c, d, F4, K4, M(61));
|
||||||
|
R(d, e, a, b, c, F4, K4, M(62));
|
||||||
|
R(c, d, e, a, b, F4, K4, M(63));
|
||||||
|
R(b, c, d, e, a, F4, K4, M(64));
|
||||||
|
R(a, b, c, d, e, F4, K4, M(65));
|
||||||
|
R(e, a, b, c, d, F4, K4, M(66));
|
||||||
|
R(d, e, a, b, c, F4, K4, M(67));
|
||||||
|
R(c, d, e, a, b, F4, K4, M(68));
|
||||||
|
R(b, c, d, e, a, F4, K4, M(69));
|
||||||
|
R(a, b, c, d, e, F4, K4, M(70));
|
||||||
|
R(e, a, b, c, d, F4, K4, M(71));
|
||||||
|
R(d, e, a, b, c, F4, K4, M(72));
|
||||||
|
R(c, d, e, a, b, F4, K4, M(73));
|
||||||
|
R(b, c, d, e, a, F4, K4, M(74));
|
||||||
|
R(a, b, c, d, e, F4, K4, M(75));
|
||||||
|
R(e, a, b, c, d, F4, K4, M(76));
|
||||||
|
R(d, e, a, b, c, F4, K4, M(77));
|
||||||
|
R(c, d, e, a, b, F4, K4, M(78));
|
||||||
|
R(b, c, d, e, a, F4, K4, M(79));
|
||||||
|
|
||||||
|
a = ctx->A += a;
|
||||||
|
b = ctx->B += b;
|
||||||
|
c = ctx->C += c;
|
||||||
|
d = ctx->D += d;
|
||||||
|
e = ctx->E += e;
|
||||||
|
}
|
||||||
|
}
|
||||||
1107
src/util.cpp
Normal file
1107
src/util.cpp
Normal file
File diff suppressed because it is too large
Load Diff
118
src/util.h
Normal file
118
src/util.h
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
//==================================================================//
|
||||||
|
/*
|
||||||
|
AtomicParsley - util.h
|
||||||
|
|
||||||
|
AtomicParsley is GPL software; you can freely distribute,
|
||||||
|
redistribute, modify & use under the terms of the GNU General
|
||||||
|
Public License; either version 2 or its successor.
|
||||||
|
|
||||||
|
AtomicParsley is distributed under the GPL "AS IS", without
|
||||||
|
any warranty; without the implied warranty of merchantability
|
||||||
|
or fitness for either an expressed or implied particular purpose.
|
||||||
|
|
||||||
|
Please see the included GNU General Public License (GPL) for
|
||||||
|
your rights and further details; see the file COPYING. If you
|
||||||
|
cannot, write to the Free Software Foundation, 59 Temple Place
|
||||||
|
Suite 330, Boston, MA 02111-1307, USA. Or www.fsf.org
|
||||||
|
|
||||||
|
Copyright ©2006-2007 puck_lock
|
||||||
|
with contributions from others; see the CREDITS file
|
||||||
|
*/
|
||||||
|
//==================================================================//
|
||||||
|
#include "ap_types.h"
|
||||||
|
|
||||||
|
#if defined(__ppc__) || defined(__ppc64__)
|
||||||
|
#define SWAP16(x) (x)
|
||||||
|
#define SWAP32(x) (x)
|
||||||
|
#else
|
||||||
|
#define SWAP16(x) ((((x)&0xFF) << 8) | (((x) >> 8) & 0xFF))
|
||||||
|
#define SWAP32(x) \
|
||||||
|
((((x)&0xFF) << 24) | (((x) >> 24) & 0xFF) | (((x)&0x0000FF00) << 8) | \
|
||||||
|
(((x)&0x00FF0000) >> 8))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN32) && defined(_MSC_VER)
|
||||||
|
#undef HAVE_GETOPT_H
|
||||||
|
#undef HAVE_LROUNDF
|
||||||
|
#undef HAVE_STRSEP
|
||||||
|
//#undef HAVE_ZLIB_H //comment this IN when compiling on win32 withOUT zlib
|
||||||
|
// present #define HAVE_ZLIB_H 1 //and comment this OUT
|
||||||
|
#undef HAVE_SRANDDEV
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MAXTIME_32 6377812095ULL
|
||||||
|
|
||||||
|
uint64_t findFileSize(const char *utf8_filepath);
|
||||||
|
FILE *APar_OpenFile(const char *utf8_filepath, const char *file_flags);
|
||||||
|
FILE *APar_OpenISOBaseMediaFile(const char *file, bool open); // openSomeFile
|
||||||
|
void TestFileExistence(const char *filePath, bool errorOut);
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#ifndef HAVE_FSEEKO
|
||||||
|
int fseeko(FILE *stream, uint64_t pos, int whence);
|
||||||
|
#endif
|
||||||
|
HANDLE APar_OpenFileWin32(const char *utf8_filepath,
|
||||||
|
DWORD dwDesiredAccess,
|
||||||
|
DWORD dwShareMode,
|
||||||
|
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
||||||
|
DWORD dwCreationDisposition,
|
||||||
|
DWORD dwFlagsAndAttributes,
|
||||||
|
HANDLE hTemplateFile);
|
||||||
|
#endif
|
||||||
|
bool IsUnicodeWinOS();
|
||||||
|
|
||||||
|
const char *APar_strferror(FILE *f);
|
||||||
|
uint8_t APar_read8(FILE *ISObasemediafile, uint64_t pos);
|
||||||
|
uint16_t APar_read16(char *buffer, FILE *ISObasemediafile, uint64_t pos);
|
||||||
|
uint32_t APar_read32(char *buffer, FILE *ISObasemediafile, uint64_t pos);
|
||||||
|
uint64_t APar_read64(char *buffer, FILE *ISObasemediafile, uint64_t pos);
|
||||||
|
void APar_readX_noseek(char *buffer, FILE *ISObasemediafile, uint32_t length);
|
||||||
|
void APar_readX(char *buffer,
|
||||||
|
FILE *ISObasemediafile,
|
||||||
|
uint64_t pos,
|
||||||
|
uint32_t length);
|
||||||
|
uint32_t
|
||||||
|
APar_ReadFile(char *destination_buffer, FILE *a_file, uint32_t bytes_to_read);
|
||||||
|
uint32_t APar_FindValueInAtom(char *uint32_buffer,
|
||||||
|
FILE *ISObasemediafile,
|
||||||
|
short an_atom,
|
||||||
|
uint64_t start_position,
|
||||||
|
uint32_t eval_number);
|
||||||
|
|
||||||
|
void APar_UnpackLanguage(unsigned char lang_code[], uint16_t packed_language);
|
||||||
|
uint16_t PackLanguage(const char *language_code, uint8_t lang_offset);
|
||||||
|
|
||||||
|
#ifndef HAVE_STRSEP
|
||||||
|
char *strsep(char **stringp, const char *delim);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
char *APar_extract_UTC(uint64_t total_secs);
|
||||||
|
uint32_t APar_get_mpeg4_time();
|
||||||
|
void APar_StandardTime(char *&formed_time);
|
||||||
|
|
||||||
|
wchar_t *Convert_multibyteUTF16_to_wchar(char *input_unicode,
|
||||||
|
size_t glyph_length,
|
||||||
|
bool skip_BOM);
|
||||||
|
unsigned char *Convert_multibyteUTF16_to_UTF8(char *input_utf8,
|
||||||
|
size_t glyph_length,
|
||||||
|
size_t byte_count);
|
||||||
|
wchar_t *Convert_multibyteUTF8_to_wchar(const char *input_utf8);
|
||||||
|
uint32_t
|
||||||
|
findstringNULLterm(char *in_string, uint8_t encodingFlag, uint32_t max_len);
|
||||||
|
uint32_t skipNULLterm(char *in_string, uint8_t encodingFlag, uint32_t max_len);
|
||||||
|
|
||||||
|
uint16_t UInt16FromBigEndian(const char *string);
|
||||||
|
uint32_t UInt32FromBigEndian(const char *string);
|
||||||
|
uint64_t UInt64FromBigEndian(const char *string);
|
||||||
|
void UInt16_TO_String2(uint16_t snum, char *data);
|
||||||
|
void UInt32_TO_String4(uint32_t lnum, char *data);
|
||||||
|
void UInt64_TO_String8(uint64_t ullnum, char *data);
|
||||||
|
|
||||||
|
uint32_t float_to_16x16bit_fixed_point(double floating_val);
|
||||||
|
double fixed_point_16x16bit_to_double(uint32_t fixed_point);
|
||||||
|
|
||||||
|
uint32_t widechar_len(char *instring, uint32_t _bytes_);
|
||||||
|
|
||||||
|
bool APar_assert(bool expression, int error_msg, const char *supplemental_info);
|
||||||
|
|
||||||
|
unsigned long xor4096i();
|
||||||
467
src/uuid.cpp
Normal file
467
src/uuid.cpp
Normal file
@ -0,0 +1,467 @@
|
|||||||
|
//==================================================================//
|
||||||
|
/*
|
||||||
|
AtomicParsley - uuid.cpp
|
||||||
|
|
||||||
|
AtomicParsley is GPL software; you can freely distribute,
|
||||||
|
redistribute, modify & use under the terms of the GNU General
|
||||||
|
Public License; either version 2 or its successor.
|
||||||
|
|
||||||
|
AtomicParsley is distributed under the GPL "AS IS", without
|
||||||
|
any warranty; without the implied warranty of merchantability
|
||||||
|
or fitness for either an expressed or implied particular purpose.
|
||||||
|
|
||||||
|
Please see the included GNU General Public License (GPL) for
|
||||||
|
your rights and further details; see the file COPYING. If you
|
||||||
|
cannot, write to the Free Software Foundation, 59 Temple Place
|
||||||
|
Suite 330, Boston, MA 02111-1307, USA. Or www.fsf.org
|
||||||
|
|
||||||
|
Copyright (C) 2006-2007 puck_lock
|
||||||
|
with contributions from others; see the CREDITS file
|
||||||
|
*/
|
||||||
|
//==================================================================//
|
||||||
|
|
||||||
|
//==================================================================//
|
||||||
|
/*
|
||||||
|
Much of AP_Create_UUID_ver5_sha1_name was derived from
|
||||||
|
http://www.ietf.org/rfc/rfc4122.txt
|
||||||
|
which I don't believe conflicts with or restricts the GPL.
|
||||||
|
And this page:
|
||||||
|
http://home.famkruithof.net/guid-uuid-namebased.html
|
||||||
|
tells me I'm not on crack when I try to calculate the uuids
|
||||||
|
myself.
|
||||||
|
|
||||||
|
Copyright (c) 1990- 1993, 1996 Open Software Foundation,
|
||||||
|
Inc. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital
|
||||||
|
Equipment Corporation, Maynard, Mass. Copyright (c) 1998 Microsoft. To anyone
|
||||||
|
who acknowledges that this file is provided "AS IS" without any express or
|
||||||
|
implied warranty: permission to use, copy, modify, and distribute this file
|
||||||
|
for any purpose is hereby granted without fee, provided that the above
|
||||||
|
copyright notices and this notice appears in all source code copies, and that
|
||||||
|
none of the names of Open Software Foundation, Inc., Hewlett-Packard Company,
|
||||||
|
Microsoft, or Digital Equipment Corporation be used in advertising or
|
||||||
|
publicity pertaining to distribution of the software without specific,
|
||||||
|
written prior permission. Neither Open Software Foundation, Inc.,
|
||||||
|
Hewlett-Packard Company, Microsoft, nor Digital Equipment Corporation makes
|
||||||
|
any representations about the suitability of this software for any purpose.
|
||||||
|
*/
|
||||||
|
//==================================================================//
|
||||||
|
|
||||||
|
#include "AtomicParsley.h"
|
||||||
|
|
||||||
|
/*----------------------
|
||||||
|
print_hash
|
||||||
|
hash - the string array of the sha1 hash
|
||||||
|
|
||||||
|
prints out the hex representation of the 16 byte hash - this
|
||||||
|
relates to sha1, but its here to keep the sha1 files as close to original as
|
||||||
|
possible
|
||||||
|
----------------------*/
|
||||||
|
void print_hash(char hash[]) {
|
||||||
|
for (int i = 0; i < 20; i++) {
|
||||||
|
fprintf(stdout, "%02x", (uint8_t)hash[i]);
|
||||||
|
}
|
||||||
|
fprintf(stdout, "\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------
|
||||||
|
Swap_Char
|
||||||
|
in_str - the string to have the swap operation performed on
|
||||||
|
str_len - the amount of bytes to swap in the string
|
||||||
|
|
||||||
|
Make a pointer to the start & end of the string, as well as a
|
||||||
|
temporary string to hold the swapped byte. As the start increments up, the end
|
||||||
|
decrements down. Copy the byte at each advancing start position. Copy the byte
|
||||||
|
of the diminishing end string into the start byte, then advance the start byte.
|
||||||
|
Finaly, set each byte of the decrementing end pointer to the temp string byte.
|
||||||
|
----------------------*/
|
||||||
|
void Swap_Char(char *in_str, uint8_t str_len) {
|
||||||
|
char *start_str, *end_str, temp_str;
|
||||||
|
|
||||||
|
start_str = in_str;
|
||||||
|
end_str = start_str + str_len;
|
||||||
|
while (start_str < --end_str) {
|
||||||
|
temp_str = *start_str;
|
||||||
|
*start_str++ = *end_str;
|
||||||
|
*end_str = temp_str;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------
|
||||||
|
APar_endian_uuid_bin_str_conversion
|
||||||
|
raw_uuid - a binary string representation of a uuid
|
||||||
|
|
||||||
|
As a string representation of a uuid, there is a 32-bit & 2
|
||||||
|
16-bit numbers in the uuid. These members need to be swapped on big endian
|
||||||
|
systems.
|
||||||
|
----------------------*/
|
||||||
|
void APar_endian_uuid_bin_str_conversion(char *raw_uuid) {
|
||||||
|
#if defined(__ppc__) || defined(__ppc64__)
|
||||||
|
return; // we are *naturally* network byte ordered - simplicity
|
||||||
|
#else
|
||||||
|
Swap_Char(raw_uuid, 4);
|
||||||
|
Swap_Char(raw_uuid + 4, 2);
|
||||||
|
Swap_Char(raw_uuid + 4 + 2, 2);
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------
|
||||||
|
APar_print_uuid
|
||||||
|
uuid - a uuid structure containing the uuid
|
||||||
|
|
||||||
|
Print out a full string representation of a uuid
|
||||||
|
----------------------*/
|
||||||
|
void APar_print_uuid(ap_uuid_t *uuid, bool new_line) {
|
||||||
|
fprintf(stdout,
|
||||||
|
"%08" PRIx32 "-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
|
||||||
|
uuid->time_low,
|
||||||
|
uuid->time_mid,
|
||||||
|
uuid->time_hi_and_version,
|
||||||
|
uuid->clock_seq_hi_and_reserved,
|
||||||
|
uuid->clock_seq_low,
|
||||||
|
uuid->node[0],
|
||||||
|
uuid->node[1],
|
||||||
|
uuid->node[2],
|
||||||
|
uuid->node[3],
|
||||||
|
uuid->node[4],
|
||||||
|
uuid->node[5]);
|
||||||
|
if (new_line)
|
||||||
|
fprintf(stdout, "\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------
|
||||||
|
APar_sprintf_uuid
|
||||||
|
uuid - a uuid structure containing the uuid
|
||||||
|
destination - the end result uuid will be placed here
|
||||||
|
|
||||||
|
Put a binary representation of a uuid to a human-readable
|
||||||
|
ordered uuid string
|
||||||
|
----------------------*/
|
||||||
|
void APar_sprintf_uuid(ap_uuid_t *uuid, char *destination) {
|
||||||
|
sprintf(destination,
|
||||||
|
"%08" PRIx32 "-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
|
||||||
|
uuid->time_low,
|
||||||
|
uuid->time_mid,
|
||||||
|
uuid->time_hi_and_version,
|
||||||
|
uuid->clock_seq_hi_and_reserved,
|
||||||
|
uuid->clock_seq_low,
|
||||||
|
uuid->node[0],
|
||||||
|
uuid->node[1],
|
||||||
|
uuid->node[2],
|
||||||
|
uuid->node[3],
|
||||||
|
uuid->node[4],
|
||||||
|
uuid->node[5]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------
|
||||||
|
APar_uuid_scanf
|
||||||
|
in_formed_uuid - pointer to a string (or a place in a string) where to place a
|
||||||
|
binary (hex representation) string uuid of 16 bytes raw_uuid - the string that
|
||||||
|
contains a string representation of a uuid (from cli input for example). This
|
||||||
|
string isn't 16 bytes - its 36
|
||||||
|
|
||||||
|
Skip past a hyphen, make any upper case characters lower (ahh,
|
||||||
|
that hex 'Q') to do a manual scanf on the string. Add its hex representation as
|
||||||
|
a number for 1/2 of the bits (a single byte is 2 hex characters), shift it over
|
||||||
|
to the upper bits, and repeat adding the lower bits. Repeat until done.
|
||||||
|
----------------------*/
|
||||||
|
uint8_t APar_uuid_scanf(char *in_formed_uuid, const char *raw_uuid_in) {
|
||||||
|
char *uuid_str, *end_uuid_str, *uuid_byte;
|
||||||
|
uint8_t uuid_pos, uuid_len;
|
||||||
|
uint8_t keeprap = 0;
|
||||||
|
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||||
|
char *raw_uuid = _strdup(raw_uuid_in);
|
||||||
|
#else
|
||||||
|
char *raw_uuid = strdup(raw_uuid_in);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uuid_len = strlen(
|
||||||
|
raw_uuid); // it will be like "55534d54-21d2-4fce-bb88-695cfac9c740"
|
||||||
|
uuid_str = raw_uuid;
|
||||||
|
uuid_pos = 0;
|
||||||
|
end_uuid_str = uuid_str + uuid_len;
|
||||||
|
|
||||||
|
while (uuid_str < end_uuid_str) {
|
||||||
|
uuid_byte = &in_formed_uuid[uuid_pos];
|
||||||
|
if (uuid_str[0] == '-')
|
||||||
|
uuid_str++;
|
||||||
|
if (uuid_str[0] >= 'A' && uuid_str[0] <= 90)
|
||||||
|
uuid_str[0] += 32;
|
||||||
|
if (uuid_str[1] >= 'A' && uuid_str[1] <= 90)
|
||||||
|
uuid_str[0] += 32;
|
||||||
|
|
||||||
|
for (int i = 0; i <= 1; i++) {
|
||||||
|
switch (uuid_str[i]) {
|
||||||
|
case '0': {
|
||||||
|
keeprap = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case '1': {
|
||||||
|
keeprap = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case '2': {
|
||||||
|
keeprap = 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case '3': {
|
||||||
|
keeprap = 3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case '4': {
|
||||||
|
keeprap = 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case '5': {
|
||||||
|
keeprap = 5;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case '6': {
|
||||||
|
keeprap = 6;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case '7': {
|
||||||
|
keeprap = 7;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case '8': {
|
||||||
|
keeprap = 8;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case '9': {
|
||||||
|
keeprap = 9;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'a': {
|
||||||
|
keeprap = 10;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'b': {
|
||||||
|
keeprap = 11;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'c': {
|
||||||
|
keeprap = 12;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'd': {
|
||||||
|
keeprap = 13;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'e': {
|
||||||
|
keeprap = 14;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'f': {
|
||||||
|
keeprap = 15;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
|
*uuid_byte = keeprap << 4;
|
||||||
|
} else {
|
||||||
|
*uuid_byte |= keeprap; //(keeprap & 0xF0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uuid_str += 2;
|
||||||
|
uuid_pos++;
|
||||||
|
}
|
||||||
|
APar_endian_uuid_bin_str_conversion(in_formed_uuid);
|
||||||
|
free(raw_uuid);
|
||||||
|
return uuid_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------
|
||||||
|
APar_extract_uuid_version
|
||||||
|
uuid - a uuid structure containing the uuid
|
||||||
|
binary_uuid_str - a binary string rep of a uuid (without dashes, just
|
||||||
|
the hex)
|
||||||
|
|
||||||
|
Test the 6th byte in a str and push the bits to get the version
|
||||||
|
or take the 3rd member of a uuid (uint16_t) and shift bits by 12
|
||||||
|
----------------------*/
|
||||||
|
uint8_t APar_extract_uuid_version(ap_uuid_t *uuid, char *binary_uuid_str) {
|
||||||
|
uint8_t uuid_ver = 0;
|
||||||
|
if (binary_uuid_str != NULL) {
|
||||||
|
uuid_ver = (binary_uuid_str[6] >> 4);
|
||||||
|
} else if (uuid != NULL) {
|
||||||
|
uuid_ver = (uuid->time_hi_and_version >> 12);
|
||||||
|
}
|
||||||
|
return uuid_ver;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------
|
||||||
|
AP_Create_UUID_ver5_sha1_name
|
||||||
|
uuid - pointer to the final version 5 sha1 hash bashed uuid
|
||||||
|
desired_namespace - the input uuid used as a basis for the hash; a ver5
|
||||||
|
uuid is a namespace/name uuid. This is the namespace portion name - this is the
|
||||||
|
name portion used to make a v5 sha1 hash namelen - length of name (currently a
|
||||||
|
strlen() value)
|
||||||
|
|
||||||
|
This will create a version 5 sha1 based uuid of a name in a
|
||||||
|
namespace. The desired_namespace has its endian members swapped to newtwork byte
|
||||||
|
ordering. The sha1 hash algorithm is fed the reordered netord_namespace uuid to
|
||||||
|
create a hash; the name is then added to the hash to create a hash of the name
|
||||||
|
in the namespace. The final hash is then copied into the out_uuid, and the
|
||||||
|
endian members of the ap_uuid_t are swapped to endian ordering.
|
||||||
|
----------------------*/
|
||||||
|
void AP_Create_UUID_ver5_sha1_name(ap_uuid_t *out_uuid,
|
||||||
|
ap_uuid_t desired_namespace,
|
||||||
|
const char *name,
|
||||||
|
int namelen) {
|
||||||
|
sha1_ctx sha_state;
|
||||||
|
char hash[20];
|
||||||
|
ap_uuid_t networkorderd_namespace;
|
||||||
|
|
||||||
|
// swap the endian members of uuid to network byte order for hash uniformity
|
||||||
|
// across platforms (the NULL or AP.sf.net uuid)
|
||||||
|
networkorderd_namespace = desired_namespace;
|
||||||
|
networkorderd_namespace.time_low = SWAP32(networkorderd_namespace.time_low);
|
||||||
|
networkorderd_namespace.time_mid = SWAP16(networkorderd_namespace.time_mid);
|
||||||
|
networkorderd_namespace.time_hi_and_version =
|
||||||
|
SWAP16(networkorderd_namespace.time_hi_and_version);
|
||||||
|
|
||||||
|
// make a hash of the input desired_namespace (as netord_ns); add the name
|
||||||
|
// (the AP.sf.net namespace as string or the atom name)
|
||||||
|
|
||||||
|
sha1_init_ctx(&sha_state);
|
||||||
|
sha1_process_bytes((char *)&networkorderd_namespace,
|
||||||
|
sizeof networkorderd_namespace,
|
||||||
|
&sha_state);
|
||||||
|
sha1_process_bytes(name, namelen, &sha_state);
|
||||||
|
sha1_finish_ctx(&sha_state, hash);
|
||||||
|
|
||||||
|
// quasi uuid sha1hash is network byte ordered. swap the endian members of the
|
||||||
|
// uuid (uint32_t & uint16_t) to local byte order this creates additional
|
||||||
|
// requirements later that have to be APar_endian_uuid_bin_str_conversion()
|
||||||
|
// swapped, but leave this for now for coherence
|
||||||
|
memcpy(out_uuid, hash, sizeof *out_uuid);
|
||||||
|
out_uuid->time_low = SWAP32(out_uuid->time_low);
|
||||||
|
out_uuid->time_mid = SWAP16(out_uuid->time_mid);
|
||||||
|
out_uuid->time_hi_and_version = SWAP16(out_uuid->time_hi_and_version);
|
||||||
|
|
||||||
|
out_uuid->time_hi_and_version &= 0x0FFF; // mask hash octes 6&7
|
||||||
|
out_uuid->time_hi_and_version |=
|
||||||
|
(5 << 12); // set bits 12-15 to the version (5 for sha1 namespace/name
|
||||||
|
// hash uuids)
|
||||||
|
out_uuid->clock_seq_hi_and_reserved &= 0x3F; // mask hash octet 8
|
||||||
|
out_uuid->clock_seq_hi_and_reserved |=
|
||||||
|
0x80; // Set the two most significant bits (bits 6 and 7) of the
|
||||||
|
// clock_seq_hi_and_reserved to zero and one, respectively.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------
|
||||||
|
AP_Create_UUID_ver3_random
|
||||||
|
out_uuid - pointer to the final version 3 randomly generated uuid
|
||||||
|
|
||||||
|
Use a high quality random number generator (still requiring a
|
||||||
|
seed) to generate a random uuid. In 2.5 million creations, all have been unique
|
||||||
|
(at least on Mac OS X with sranddev providing the initial seed).
|
||||||
|
----------------------*/
|
||||||
|
void AP_Create_UUID_ver3_random(ap_uuid_t *out_uuid) {
|
||||||
|
uint32_t rand1 = 0;
|
||||||
|
|
||||||
|
out_uuid->time_low = xor4096i();
|
||||||
|
rand1 = xor4096i();
|
||||||
|
out_uuid->time_mid = (rand1 >> 16) & 0xFFFF;
|
||||||
|
out_uuid->node[0] = (rand1 >> 8) & 0xFF;
|
||||||
|
out_uuid->node[1] = (rand1 >> 0) & 0xFF;
|
||||||
|
rand1 = xor4096i();
|
||||||
|
out_uuid->node[2] = (rand1 >> 24) & 0xFF;
|
||||||
|
out_uuid->node[3] = (rand1 >> 16) & 0xFF;
|
||||||
|
out_uuid->node[4] = (rand1 >> 8) & 0xFF;
|
||||||
|
out_uuid->node[5] = (rand1 >> 0) & 0xFF;
|
||||||
|
rand1 = xor4096i();
|
||||||
|
out_uuid->time_hi_and_version = (rand1 >> 16) & 0xFFFF;
|
||||||
|
out_uuid->clock_seq_low = (rand1 >> 8) & 0xFF;
|
||||||
|
out_uuid->clock_seq_hi_and_reserved = (rand1 >> 0) & 0x3F;
|
||||||
|
out_uuid->clock_seq_hi_and_reserved |=
|
||||||
|
0x40; // bits 6 & 7 must be 0 & 1 respectively
|
||||||
|
|
||||||
|
out_uuid->time_hi_and_version &= 0x0FFF;
|
||||||
|
out_uuid->time_hi_and_version |=
|
||||||
|
(3 << 12); // set bits 12-15 to the version (3 for peusdo-random/random)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------
|
||||||
|
APar_generate_uuid_from_atomname
|
||||||
|
atom_name - the 4 character atom name to create a uuid for
|
||||||
|
uuid_binary_str - the destination for the created uuid (as a hex string)
|
||||||
|
|
||||||
|
This will create a 16-byte universal unique identifier for any
|
||||||
|
atom name in the AtomicParsley namespace.
|
||||||
|
1. Make a namespace for all uuids to derive from (here its
|
||||||
|
AP.sf.net)
|
||||||
|
2. Make a sha1 hash of the namespace string; use that hash as
|
||||||
|
the basis for a v5 uuid into a NULL/blank uuid to create an AP namespace uuid
|
||||||
|
3. Make a sha2 hash of the atom_name string; use that hash as
|
||||||
|
the basis for a v5 uuid into an AtomicParsley namespace uuid to create the final
|
||||||
|
uuid.
|
||||||
|
4. copy the uuid structure into a binary string representation
|
||||||
|
----------------------*/
|
||||||
|
void APar_generate_uuid_from_atomname(char *atom_name, char *uuid_binary_str) {
|
||||||
|
|
||||||
|
ap_uuid_t blank_namespace = {0x00000000,
|
||||||
|
0x0000,
|
||||||
|
0x0000,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
|
||||||
|
ap_uuid_t APar_namespace_uuid;
|
||||||
|
ap_uuid_t AP_atom_uuid;
|
||||||
|
|
||||||
|
AP_Create_UUID_ver5_sha1_name(
|
||||||
|
&APar_namespace_uuid, blank_namespace, "AtomicParsley.sf.net", 20);
|
||||||
|
AP_Create_UUID_ver5_sha1_name(
|
||||||
|
&AP_atom_uuid, APar_namespace_uuid, atom_name, 4);
|
||||||
|
|
||||||
|
memset(uuid_binary_str, 0, 20);
|
||||||
|
memcpy(uuid_binary_str, &AP_atom_uuid, sizeof(AP_atom_uuid));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void APar_generate_random_uuid(char *uuid_binary_str) {
|
||||||
|
ap_uuid_t rand_uuid = {0x00000000,
|
||||||
|
0x0000,
|
||||||
|
0x0000,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
|
||||||
|
AP_Create_UUID_ver3_random(&rand_uuid);
|
||||||
|
memcpy(uuid_binary_str, &rand_uuid, sizeof(rand_uuid));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void APar_generate_test_uuid() {
|
||||||
|
ap_uuid_t blank_ns = {0x00000000,
|
||||||
|
0x0000,
|
||||||
|
0x0000,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
|
||||||
|
ap_uuid_t APar_ns_uuid;
|
||||||
|
ap_uuid_t APar_test_uuid;
|
||||||
|
|
||||||
|
AP_Create_UUID_ver5_sha1_name(
|
||||||
|
&APar_ns_uuid, blank_ns, "AtomicParsley.sf.net", 20);
|
||||||
|
APar_print_uuid(
|
||||||
|
&APar_ns_uuid); // should be aa80eaf3-1f72-5575-9faa-de9388dc2a90
|
||||||
|
fprintf(stdout, "uuid for 'cprt' in AP namespace: ");
|
||||||
|
AP_Create_UUID_ver5_sha1_name(&APar_test_uuid, APar_ns_uuid, "cprt", 4);
|
||||||
|
APar_print_uuid(
|
||||||
|
&APar_test_uuid); //'cprt' should be 4bd39a57-e2c8-5655-a4fb-7a19620ef151
|
||||||
|
// uuid_t domain_ns_uuid = { 0x6ba7b810, 0x9dad, 0x11d1,
|
||||||
|
// 0x80,
|
||||||
|
// 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 }; //
|
||||||
|
// 6ba7b810-9dad-11d1-80b4-00c04fd430c8 a blank representation of a blank
|
||||||
|
// domain
|
||||||
|
return;
|
||||||
|
}
|
||||||
2
tools/format-code.sh
Executable file
2
tools/format-code.sh
Executable file
@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
clang-format -i src/*.cpp src/*.h
|
||||||
230
tools/iTunMOVI-1.1.pl
Executable file
230
tools/iTunMOVI-1.1.pl
Executable file
@ -0,0 +1,230 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
#
|
||||||
|
# build --rDNSatom iTunMOVI data for AtomicParsley and write or print to file
|
||||||
|
#
|
||||||
|
# by HolyRoses
|
||||||
|
#
|
||||||
|
# example line from film "Extract"
|
||||||
|
# http://www.imdb.com/title/tt1225822/fullcredits
|
||||||
|
#
|
||||||
|
#./iTunMOVI.pl --cast "Jason Bateman" --cast "Mila Kunis,Kristen Wiig" --directors "Mike Judge" --producers "John Altschuler,Michael Flynn" --studio "Miramax Films" --copy_warning "FBI ANTI-PIRACY WARNING: UNAUTHORIZED COPYING IS PUNISHABLE UNDER FEDERAL LAW." --screenwriters "Mike Judge" --codirectors "Jasmine Alhambra,Maria Mantia" --print
|
||||||
|
|
||||||
|
use Getopt::Long;
|
||||||
|
#Getopt::Long::Configure ("bundling");
|
||||||
|
|
||||||
|
# default values for some items.
|
||||||
|
$ripper = "HolyRoses";
|
||||||
|
$copy_warning = "Help control the pet population. Have your pets spayed or neutered.";
|
||||||
|
$studio = "A $ripper Production";
|
||||||
|
|
||||||
|
GetOptions (
|
||||||
|
'version' => \$version,
|
||||||
|
'help' => \$help,
|
||||||
|
'print'=> \$print,
|
||||||
|
'write' => \$write,
|
||||||
|
'file=s' => \$file,
|
||||||
|
'copy_warning=s' => \$copy_warning,
|
||||||
|
'studio=s' => \$studio,
|
||||||
|
'cast|actors=s' => \@cast,
|
||||||
|
'directors=s' => \@directors,
|
||||||
|
'codirectors=s' => \@codirectors,
|
||||||
|
'screenwriters=s' => \@screenwriters,
|
||||||
|
'producers=s' => \@producers);
|
||||||
|
|
||||||
|
#print help
|
||||||
|
if ( $help ) {
|
||||||
|
print << "EOF";
|
||||||
|
|
||||||
|
AtomicParsley iTunMOVI writer for Apple TV and iTunes.
|
||||||
|
|
||||||
|
The options cast|actors, directors, codirectors, screenwriters, producers can take multiple of the same type.
|
||||||
|
|
||||||
|
You can issue --cast "x person" --cast "y person" or --cast "x person,y person,b person"
|
||||||
|
-------------------------------------------------------------------------------------------------------------
|
||||||
|
Atom options:
|
||||||
|
--copy_warning: Add copy warning (displayed in iTunes summary page)
|
||||||
|
--studio: Add film studio (displayed on Apple TV)
|
||||||
|
--cast|actors: Add Actors (displayed on Apple TV and iTunes under long description)
|
||||||
|
--directors: Add Directors (displayed on Apple TV and iTunes under long description)
|
||||||
|
--producers: Add Producers (displayed on Apple TV and iTunes under long description)
|
||||||
|
--codirectors: Add Co-Directors (displayed in iTunes under long description)
|
||||||
|
--screenwriters: Add ScreenWriters (displayed in iTunes under long description)
|
||||||
|
|
||||||
|
Write and print options:
|
||||||
|
--print: Display XML data to screen
|
||||||
|
--file: MP4 file to write XML information to
|
||||||
|
--write: Write XML data to MP4 file with AtomicParlsey
|
||||||
|
|
||||||
|
Misc options:
|
||||||
|
--version: Displays version
|
||||||
|
--help: Displays help
|
||||||
|
-------------------------------------------------------------------------------------------------------------
|
||||||
|
If there is more than 1 entry of cast, directors, producers, codirectors, screenwriters then in iTunes the verbage changes to plural. (PRODUCER -> PRODUCERS).
|
||||||
|
|
||||||
|
Apple TV display items:
|
||||||
|
Actors, Directors, Producers are displayed for Movies.
|
||||||
|
Actors are displayed for TV shows.
|
||||||
|
Studio is displayed on all videos (while video is playing press up arrow 2x, it is located under Title).
|
||||||
|
|
||||||
|
EOF
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
# version
|
||||||
|
$version_number = "1.1";
|
||||||
|
|
||||||
|
if ( $version ) {
|
||||||
|
print "\n$0 v$version_number\n\n";
|
||||||
|
print "Written by HolyRoses\n\n";
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# process arrays, join multiple --options of same type and join options seperated by commas
|
||||||
|
@cast = split(/,/,join(',',@cast));
|
||||||
|
@directors = split(/,/,join(',',@directors));
|
||||||
|
@producers = split(/,/,join(',',@producers));
|
||||||
|
@codirectors = split(/,/,join(',',@codirectors));
|
||||||
|
@screenwriters = split(/,/,join(',',@screenwriters));
|
||||||
|
|
||||||
|
# set header
|
||||||
|
$iTunMOVI_data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
|
||||||
|
<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">
|
||||||
|
<plist version=\"1.0\">
|
||||||
|
<dict>
|
||||||
|
";
|
||||||
|
|
||||||
|
# set copy-warning
|
||||||
|
$iTunMOVI_data .= " <key>copy-warning</key>
|
||||||
|
<string>$copy_warning</string>
|
||||||
|
";
|
||||||
|
# set studio
|
||||||
|
$iTunMOVI_data .= " <key>studio</key>
|
||||||
|
<string>$studio</string>
|
||||||
|
";
|
||||||
|
|
||||||
|
# assigned a default producer
|
||||||
|
if ($producers[0] eq '') {
|
||||||
|
@producers = ("$ripper");
|
||||||
|
}
|
||||||
|
|
||||||
|
# Process cast array
|
||||||
|
if ($cast[0] ne '') {
|
||||||
|
$iTunMOVI_data .= " <key>cast</key>
|
||||||
|
<array>
|
||||||
|
";
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach $actor (@cast) {
|
||||||
|
$iTunMOVI_data .= " <dict>
|
||||||
|
<key>name</key>
|
||||||
|
<string>$actor</string>
|
||||||
|
</dict>
|
||||||
|
";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($cast[0] ne '') {
|
||||||
|
$iTunMOVI_data .= " </array>
|
||||||
|
";
|
||||||
|
}
|
||||||
|
|
||||||
|
# Process directors array
|
||||||
|
if ($directors[0] ne '') {
|
||||||
|
$iTunMOVI_data .= " <key>directors</key>
|
||||||
|
<array>
|
||||||
|
";
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach $director (@directors) {
|
||||||
|
$iTunMOVI_data .= " <dict>
|
||||||
|
<key>name</key>
|
||||||
|
<string>$director</string>
|
||||||
|
</dict>
|
||||||
|
";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($directors[0] ne '') {
|
||||||
|
$iTunMOVI_data .= " </array>
|
||||||
|
";
|
||||||
|
}
|
||||||
|
|
||||||
|
# Process producers array
|
||||||
|
if ($producers[0] ne '') {
|
||||||
|
$iTunMOVI_data .= " <key>producers</key>
|
||||||
|
<array>
|
||||||
|
";
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach $producer (@producers) {
|
||||||
|
$iTunMOVI_data .= " <dict>
|
||||||
|
<key>name</key>
|
||||||
|
<string>$producer</string>
|
||||||
|
</dict>
|
||||||
|
";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($producers[0] ne '') {
|
||||||
|
$iTunMOVI_data .= " </array>
|
||||||
|
";
|
||||||
|
}
|
||||||
|
|
||||||
|
# Process codirectors array
|
||||||
|
if ($codirectors[0] ne '') {
|
||||||
|
$iTunMOVI_data .= " <key>codirectors</key>
|
||||||
|
<array>
|
||||||
|
";
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach $codirector (@codirectors) {
|
||||||
|
$iTunMOVI_data .= " <dict>
|
||||||
|
<key>name</key>
|
||||||
|
<string>$codirector</string>
|
||||||
|
</dict>
|
||||||
|
";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($codirectors[0] ne '') {
|
||||||
|
$iTunMOVI_data .= " </array>
|
||||||
|
";
|
||||||
|
}
|
||||||
|
|
||||||
|
# Process screenwriters array
|
||||||
|
if ($screenwriters[0] ne '') {
|
||||||
|
$iTunMOVI_data .= " <key>screenwriters</key>
|
||||||
|
<array>
|
||||||
|
";
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach $screenwriter (@screenwriters) {
|
||||||
|
$iTunMOVI_data .= " <dict>
|
||||||
|
<key>name</key>
|
||||||
|
<string>$screenwriter</string>
|
||||||
|
</dict>
|
||||||
|
";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($screenwriters[0] ne '') {
|
||||||
|
$iTunMOVI_data .= " </array>
|
||||||
|
";
|
||||||
|
}
|
||||||
|
|
||||||
|
# set footer
|
||||||
|
$iTunMOVI_data .= "</dict>
|
||||||
|
</plist>
|
||||||
|
";
|
||||||
|
|
||||||
|
# print output
|
||||||
|
if ( $print ) {
|
||||||
|
print "$iTunMOVI_data\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
# check if file they want to write to can be opened
|
||||||
|
if ( $file ) {
|
||||||
|
open(FILE, "$file") or die "Cannot open file <$file>: $!";
|
||||||
|
close(FILE);
|
||||||
|
}
|
||||||
|
|
||||||
|
# do the AtomicParsley write
|
||||||
|
if ( $file && $write ) {
|
||||||
|
`AtomicParsley \"$file\" --rDNSatom \'$iTunMOVI_data\' name=iTunMOVI domain=com.apple.iTunes --overWrite`;
|
||||||
|
}
|
||||||
3
tools/tag-release.sh
Executable file
3
tools/tag-release.sh
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
TAGNAME=$(git "show" "-s" "--format=%cd.%h" "--date=format:%Y%m%d.%H%M%S")
|
||||||
|
git tag $TAGNAME
|
||||||
Loading…
Reference in New Issue
Block a user