From c04dcc2e7d834218ef2d4194331e383402495ae1 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 10 Apr 2024 20:07:22 +0200 Subject: Adding upstream version 2:20.4+dfsg. Signed-off-by: Daniel Baumann --- libdvdread-embedded/.gitignore | 36 + libdvdread-embedded/.gitlab-ci.yml | 56 + libdvdread-embedded/AUTHORS | 49 + libdvdread-embedded/COPYING | 340 +++ libdvdread-embedded/Makefile.am | 80 + libdvdread-embedded/NEWS | 220 ++ libdvdread-embedded/README.md | 56 + libdvdread-embedded/TODO | 12 + libdvdread-embedded/configure.ac | 137 ++ libdvdread-embedded/doc/doxygen.cfg.in | 1332 +++++++++++ libdvdread-embedded/doc/footer.html | 2 + libdvdread-embedded/doc/header.html | 9 + libdvdread-embedded/m4/attributes.m4 | 296 +++ libdvdread-embedded/misc/dvdread.pc.in | 13 + libdvdread-embedded/msvc/config.h | 56 + libdvdread-embedded/msvc/contrib/dirent/dirent.c | 135 ++ libdvdread-embedded/msvc/contrib/dirent/dirent.h | 32 + libdvdread-embedded/msvc/contrib/dlfcn.c | 96 + libdvdread-embedded/msvc/contrib/win32_cs.h | 40 + libdvdread-embedded/msvc/ifo_dump.dsp | 110 + libdvdread-embedded/msvc/include/dlfcn.h | 18 + libdvdread-embedded/msvc/include/inttypes.h | 32 + libdvdread-embedded/msvc/include/os_types.h | 24 + libdvdread-embedded/msvc/include/sys/time.h | 28 + libdvdread-embedded/msvc/include/unistd.h | 69 + libdvdread-embedded/msvc/install/README | 7 + libdvdread-embedded/msvc/libdvdcss.def | 12 + libdvdread-embedded/msvc/libdvdcss.dsp | 139 ++ libdvdread-embedded/msvc/libdvdnav.def | 73 + libdvdread-embedded/msvc/libdvdnav.dsp | 188 ++ libdvdread-embedded/msvc/libdvdnav.dsw | 101 + libdvdread-embedded/msvc/libwin32utils.def | 77 + libdvdread-embedded/msvc/libwin32utils.dsp | 121 + libdvdread-embedded/msvc/play_title.dsp | 101 + .../msvc/scripts/libdvdcss_install.bat | 8 + .../msvc/scripts/libdvdnav_install.bat | 21 + libdvdread-embedded/msvc/title_info.dsp | 101 + libdvdread-embedded/src/bitreader.c | 163 ++ libdvdread-embedded/src/bswap.h | 118 + libdvdread-embedded/src/dvd_input.c | 483 ++++ libdvdread-embedded/src/dvd_input.h | 71 + libdvdread-embedded/src/dvd_reader.c | 1690 ++++++++++++++ libdvdread-embedded/src/dvd_udf.c | 1033 +++++++++ libdvdread-embedded/src/dvdread/bitreader.h | 40 + libdvdread-embedded/src/dvdread/dvd_reader.h | 365 +++ libdvdread-embedded/src/dvdread/dvd_udf.h | 59 + libdvdread-embedded/src/dvdread/ifo_print.h | 28 + libdvdread-embedded/src/dvdread/ifo_read.h | 229 ++ libdvdread-embedded/src/dvdread/ifo_types.h | 755 +++++++ libdvdread-embedded/src/dvdread/nav_print.h | 52 + libdvdread-embedded/src/dvdread/nav_read.h | 53 + libdvdread-embedded/src/dvdread/nav_types.h | 248 +++ libdvdread-embedded/src/dvdread/version.h.in | 37 + libdvdread-embedded/src/dvdread_internal.h | 86 + libdvdread-embedded/src/ifo_print.c | 1209 ++++++++++ libdvdread-embedded/src/ifo_read.c | 2341 ++++++++++++++++++++ libdvdread-embedded/src/logger.c | 41 + libdvdread-embedded/src/logger.h | 32 + libdvdread-embedded/src/md5.c | 346 +++ libdvdread-embedded/src/md5.h | 46 + libdvdread-embedded/src/nav_print.c | 248 +++ libdvdread-embedded/src/nav_read.c | 272 +++ 62 files changed, 14272 insertions(+) create mode 100644 libdvdread-embedded/.gitignore create mode 100644 libdvdread-embedded/.gitlab-ci.yml create mode 100644 libdvdread-embedded/AUTHORS create mode 100644 libdvdread-embedded/COPYING create mode 100644 libdvdread-embedded/Makefile.am create mode 100644 libdvdread-embedded/NEWS create mode 100644 libdvdread-embedded/README.md create mode 100644 libdvdread-embedded/TODO create mode 100644 libdvdread-embedded/configure.ac create mode 100644 libdvdread-embedded/doc/doxygen.cfg.in create mode 100644 libdvdread-embedded/doc/footer.html create mode 100644 libdvdread-embedded/doc/header.html create mode 100644 libdvdread-embedded/m4/attributes.m4 create mode 100644 libdvdread-embedded/misc/dvdread.pc.in create mode 100644 libdvdread-embedded/msvc/config.h create mode 100644 libdvdread-embedded/msvc/contrib/dirent/dirent.c create mode 100644 libdvdread-embedded/msvc/contrib/dirent/dirent.h create mode 100644 libdvdread-embedded/msvc/contrib/dlfcn.c create mode 100644 libdvdread-embedded/msvc/contrib/win32_cs.h create mode 100644 libdvdread-embedded/msvc/ifo_dump.dsp create mode 100644 libdvdread-embedded/msvc/include/dlfcn.h create mode 100644 libdvdread-embedded/msvc/include/inttypes.h create mode 100644 libdvdread-embedded/msvc/include/os_types.h create mode 100644 libdvdread-embedded/msvc/include/sys/time.h create mode 100644 libdvdread-embedded/msvc/include/unistd.h create mode 100644 libdvdread-embedded/msvc/install/README create mode 100644 libdvdread-embedded/msvc/libdvdcss.def create mode 100644 libdvdread-embedded/msvc/libdvdcss.dsp create mode 100644 libdvdread-embedded/msvc/libdvdnav.def create mode 100644 libdvdread-embedded/msvc/libdvdnav.dsp create mode 100644 libdvdread-embedded/msvc/libdvdnav.dsw create mode 100644 libdvdread-embedded/msvc/libwin32utils.def create mode 100644 libdvdread-embedded/msvc/libwin32utils.dsp create mode 100644 libdvdread-embedded/msvc/play_title.dsp create mode 100755 libdvdread-embedded/msvc/scripts/libdvdcss_install.bat create mode 100755 libdvdread-embedded/msvc/scripts/libdvdnav_install.bat create mode 100644 libdvdread-embedded/msvc/title_info.dsp create mode 100644 libdvdread-embedded/src/bitreader.c create mode 100644 libdvdread-embedded/src/bswap.h create mode 100644 libdvdread-embedded/src/dvd_input.c create mode 100644 libdvdread-embedded/src/dvd_input.h create mode 100644 libdvdread-embedded/src/dvd_reader.c create mode 100644 libdvdread-embedded/src/dvd_udf.c create mode 100644 libdvdread-embedded/src/dvdread/bitreader.h create mode 100644 libdvdread-embedded/src/dvdread/dvd_reader.h create mode 100644 libdvdread-embedded/src/dvdread/dvd_udf.h create mode 100644 libdvdread-embedded/src/dvdread/ifo_print.h create mode 100644 libdvdread-embedded/src/dvdread/ifo_read.h create mode 100644 libdvdread-embedded/src/dvdread/ifo_types.h create mode 100644 libdvdread-embedded/src/dvdread/nav_print.h create mode 100644 libdvdread-embedded/src/dvdread/nav_read.h create mode 100644 libdvdread-embedded/src/dvdread/nav_types.h create mode 100644 libdvdread-embedded/src/dvdread/version.h.in create mode 100644 libdvdread-embedded/src/dvdread_internal.h create mode 100644 libdvdread-embedded/src/ifo_print.c create mode 100644 libdvdread-embedded/src/ifo_read.c create mode 100644 libdvdread-embedded/src/logger.c create mode 100644 libdvdread-embedded/src/logger.h create mode 100644 libdvdread-embedded/src/md5.c create mode 100644 libdvdread-embedded/src/md5.h create mode 100644 libdvdread-embedded/src/nav_print.c create mode 100644 libdvdread-embedded/src/nav_read.c (limited to 'libdvdread-embedded') diff --git a/libdvdread-embedded/.gitignore b/libdvdread-embedded/.gitignore new file mode 100644 index 0000000..d24b27c --- /dev/null +++ b/libdvdread-embedded/.gitignore @@ -0,0 +1,36 @@ +*.la +*.lo +*.o +*~ +.deps/ +.dirstamp +.libs/ +/aclocal.m4 +/autom4te.cache/ +/compile +/config.guess +/config.h +/config.h.in +/config.log +/config.status +/config.sub +/configure +/depcomp +/install-sh +/libdvdread*.tar.bz2 +/libtool +/ltmain.sh +/m4/libtool.m4 +/m4/lt*.m4 +/misc/*.pc +/misc/libdvdread.spec +/missing +/stamp-h1 +/ChangeLog +/Makefile +/Makefile.in +/doc/doxygen.cfg +/doc/html +/stamp-* +/build +/releases diff --git a/libdvdread-embedded/.gitlab-ci.yml b/libdvdread-embedded/.gitlab-ci.yml new file mode 100644 index 0000000..6f808c7 --- /dev/null +++ b/libdvdread-embedded/.gitlab-ci.yml @@ -0,0 +1,56 @@ +stages: + - build + +variables: + GIT_SUBMODULE_STRATEGY: normal + +build-debian: + image: registry.videolan.org/vlc-debian-unstable:20200529132440 + stage: build + tags: + - docker + - amd64 + script: + - autoreconf -fisv + - mkdir build + - cd build + - ../configure + - make -j $(getconf _NPROCESSORS_ONLN) + +build-macos: + stage: build + tags: + - mojave + - amd64 + script: + - autoreconf -fisv + - mkdir build + - cd build + - ../configure + - make -j $(getconf _NPROCESSORS_ONLN) + +build-win64: + image: registry.videolan.org/vlc-debian-win64:20201106143728 + stage: build + tags: + - docker + - amd64 + script: + - autoreconf -fisv + - mkdir build + - cd build + - ../configure --host=x86_64-w64-mingw32 + - make -j $(getconf _NPROCESSORS_ONLN) + +build-win32: + image: registry.videolan.org/vlc-debian-win32:20201106141924 + stage: build + tags: + - docker + - amd64 + script: + - autoreconf -fisv + - mkdir build + - cd build + - ../configure --host=i686-w64-mingw32 + - make -j $(getconf _NPROCESSORS_ONLN) diff --git a/libdvdread-embedded/AUTHORS b/libdvdread-embedded/AUTHORS new file mode 100644 index 0000000..19c5ad5 --- /dev/null +++ b/libdvdread-embedded/AUTHORS @@ -0,0 +1,49 @@ +Jean-Baptiste Kempf +Erik Hovland +Diego Biurrun +Nico Sabbi +Dominik Mierzejewski +Steve Dibb +Diego Elio Pettenò +Petri Hintukainen +John Stebbins +Andrew Clayton +KO Myung-Hun +Thomas Guillem +Dan Nicholson +Reimar Döffinger +Frédéric Marchal +Paul Menzel +Pierre Lamot +Rafaël Carré +Evgeny Grin +Lawrence D'Oliveiro +Marcel Mol +Alexander Roalter +Benjamin Kerensa +Brad Smith +Dominik 'Rathann' Mierzejewski +Doug Springer +Erik Auerswald +Ganael Laplanche +Ingo Brückl +Jindrich Makovicka +Jorgen Lundman +Konstantin Pavlov +LRN +Mike Castle +Mike Gorchak +Nicolas Porcel +Reinhard Tartler +Richard Hulme +Roger Pack +Rémi Duraffort +Thomas Klausner +Thomas Petazzoni +Timothy Gu +Daniel Caujolle-Bert +Frantisek Dvorak +Kees Cook +Michael Roitzsch +Rich Wareha +Thomas Vander Stichele diff --git a/libdvdread-embedded/COPYING b/libdvdread-embedded/COPYING new file mode 100644 index 0000000..a3e9774 --- /dev/null +++ b/libdvdread-embedded/COPYING @@ -0,0 +1,340 @@ + 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 + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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 of the License, 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 + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/libdvdread-embedded/Makefile.am b/libdvdread-embedded/Makefile.am new file mode 100644 index 0000000..f2849b8 --- /dev/null +++ b/libdvdread-embedded/Makefile.am @@ -0,0 +1,80 @@ +ACLOCAL_AMFLAGS = -Im4 + +AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_builddir)/src/dvdread $(CSS_CFLAGS) + +dist_doc_DATA = AUTHORS ChangeLog COPYING NEWS README.md TODO + +MAINTAINERCLEANFILES = ChangeLog + +ChangeLog: $(wildcard $(srcdir)/.git/logs/HEAD) + -cd $(srcdir) && git log > $(abs_builddir)/$(@)-tmp + -test -s $(@)-tmp && mv $(@)-tmp $(@) + -rm -f $(@)-tmp + test -e $(@) || touch $(@) + +EXTRA_DIST = msvc doc/footer.html doc/header.html + +lib_LTLIBRARIES = libdvdread.la + +libdvdread_la_SOURCES = \ + src/bitreader.c \ + src/bswap.h \ + src/dvd_input.c \ + src/dvd_input.h \ + src/dvd_reader.c \ + src/dvd_udf.c \ + src/dvdread_internal.h \ + src/ifo_print.c \ + src/ifo_read.c \ + src/logger.c \ + src/logger.h \ + src/md5.c \ + src/md5.h \ + src/nav_print.c \ + src/nav_read.c \ + msvc/contrib/win32_cs.h + +libdvdread_la_LIBADD = $(CSS_LIBS) + +libdvdread_la_LDFLAGS = -version-info $(DVDREAD_LTVERSION) \ + -export-symbols-regex "(^dvdread.*|^nav.*|^ifo.*|^DVD.*|^UDF.*)" + +pkgincludedir = $(includedir)/dvdread +pkginclude_HEADERS = \ + src/dvdread/bitreader.h \ + src/dvdread/dvd_reader.h \ + src/dvdread/dvd_udf.h \ + src/dvdread/ifo_print.h \ + src/dvdread/ifo_read.h \ + src/dvdread/ifo_types.h \ + src/dvdread/nav_print.h \ + src/dvdread/nav_read.h \ + src/dvdread/nav_types.h \ + src/dvdread/version.h + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = misc/dvdread.pc + +if APIDOC +all-local: apidoc +install-data-local: install-apidoc +uninstall-hook: uninstall-apidoc +endif + +apidoc: stamp-doxygen + +stamp-doxygen: doc/doxygen.cfg + cd doc && doxygen doxygen.cfg + touch $@ + +clean-local: + -rm -Rf stamp-doxygen doc/html + +install-apidoc: + $(MKDIR_P) $(DESTDIR)$(htmldir) + for file in doc/html/*; do \ + $(INSTALL_DATA) $$file "$(DESTDIR)$(htmldir)" || exit 1; \ + done; + +uninstall-apidoc: + -rm -Rf $(DESTDIR)$(htmldir)/*.png $(DESTDIR)$(htmldir)/*.html $(DESTDIR)$(htmldir)/*.css $(DESTDIR)$(htmldir)/*.js diff --git a/libdvdread-embedded/NEWS b/libdvdread-embedded/NEWS new file mode 100644 index 0000000..7c6733a --- /dev/null +++ b/libdvdread-embedded/NEWS @@ -0,0 +1,220 @@ +libdvdread (6.1.3) + * Improvements for OpenBSD + * Fix crashes on some DVD (0 PCGI SRP) + * Misc source fixes and cleanups, including fixes for recent toolchains + +libdvdread (6.1.2) + * Fix Win32 Unicode paths opening + * Fix warnings and build improvements + +libdvdread (6.1.1) + * Fix the soversion following ABI breakage + +libdvdread (6.1.0) + * Introduce DVDOpen2 and DVDOpenStream2 API to provide logger context + * fix playback of broken discs with broken ifo files + * improve getmntent_r detection + * fix crashes in some disc, with empty contiguous ShortAD + * clean obsolete code + +libdvdread (6.0.2) + * use reentrant getmntent_r + * fix playback of some discs, by fixing pgc_t structure + +libdvdread (6.0.1) + * fix a regression on some DVDs, like Resident Evil + * check InternalUDFReadBlocksRaw I/O issues + * fix issues with some DVD burnt by Nero + +libdvdread (6.0.0) + * restrict the number of symbols to be exposed to the shared-object + * remove dvdinput_error function + * improve compatibility with some DVDs (notably the eOne ones) + * fix write after free in ifoFree functions + * fix possible buffer overflow in open + * additional checks on DVDReadBytes arguments + * fix leaks + +libdvdread (5.0.3) + * cache IFO and BUP files (only for ImageFiles) in order to reduce the number + of read/seek access + * fix compilation warnings for OS/2 + +libdvdread (5.0.2) + * add DVDOpenStream to open a dvd from a set of callbacks + +libdvdread (5.0.1) + * support DragonFly BSD bswap + * new md5 implementation, under LGPL + * fix partial reads + * fix warnings and code cleanup + +libdvdread (5.0.0) + * added support for Android + * fix build support for OS/2 + * fix crashes in IFO parsing (Shark Week The Great Bites Collection) + +libdvdread (4.9.9) + * major cleanup + * rewritten build system, including removal of configure2 and dvdread-config + * fix numerous crashes + * added QNX support + * updated to support libdvdcss 1.3.0 + * improved dlopen support for Win32 + * simplify static linking of libdvdcss + +libdvdread (4.2.1) + * fix huge memory consumption when reading DVDs: "Up" and "Dark Knight" + * numerous crashes fixed, notably on ARCCOS protected DVDs, + like Transformers 3, Brave, The Express, Sherlock Holmes + and Cars 2, + * fix packed structures with mingw gcc >= 4.7 + +libdvdread (4.2.0) + * added OS/2 support + * fixed ARM memory alignment issue + * portability fixes for *BSD, Mac OS X, MINGW and OS/2 + * added a missing DVDFileStat function + * exposed the dvd_stat_t struct in header + * fixed libdvdread closing stdin if it can't open the file/device + * fixed a segfault in UDFFileEntry on some badly mastered DVDs + * fixed big-endian builds + * Win32: large file support under Mingw to go over 2G limits + * configure: remove the special case test for uid=0 + * provide BUP file support for more issues + * move UDFReadBlocksRaw declaration to dvdread_internal.h + * fixed double free of parental management information + * configure2: Use a single = instead of == + * fixed crash when PTT is too short + * fixed segfault when reading certain DVDs, for example "Thor" + +libdvdread (4.1.3) + * an embarrassing amount of fixes regarding potential memory and resource leaks + (patches contributed by Erik Hovland) + * added dvdread-config (dvdnav-config's younger brother) + * added pkgconfig support + * split dvdread to a separate tree + +libdvdnav (4.1.2) + * multiple build system fixes + * added dvdnav_describe_title_chapters(title) to get title and chapters + duration + +libdvdnav (4.1.1) + * added dvdnav_audio_stream_channels() to return number of channels + * fixed dvdnav_time_search() in multi-angle dvds (but it still needs + improvements) + * added dvdnav_audio_stream_format() to identify the codec used + in audio streams + * starting DVD playback at specific title/part positions with + dvdnav_{title,part}_play() works again + * removed wrong SPU stream change event filter + (fixes unwanted subtitles in the trailer of "Girl, interrupted", RC2) + * fixed error "Expected NAV packet but none found." occurring sometimes + on resume from menu + +libdvdnav (0.1.10) + * filter the symbols that we export. + * fix LinkNextC assertion failure (fixes LotR-SEE bonus disc image gallery) + * detect zero stilltime still cells inside PGCs, not only at the end + (fixes "Red Dragon" RC2 scene selection) + * PGC stills seem to work, assertion removed + * fix rare race condition after Exit commands + * fix wrong JumpSS_VTSM execution in German RC2 "Anatomie" + (fix ported from Ogle) + +libdvdnav (0.1.9) + * libdvdnav does not depend on libdvdread any more. It has it's own version. + * fix some situations where an unlucky user could trigger assertions + +libdvdnav (0.1.8) + * more timing info in cell change event struct + * documentation review + +libdvdnav (0.1.7) + * fixed a bug in title jumping, where the title number would not be + converted from TTN to VTS_TTN properly + * some minor sanity checks added to prevent segfaults + +libdvdnav (0.1.6) unstable; urgency=low + * new event DVDNAV_WAIT to fix consistency problems in applications with fifos + where libdvdnav is always a bit ahead in the stream, the event forces + the application to wait for its fifos to get empty + * correct HIGHLIGHT reporting when a button is activated + * method to try-run VM operations, now used for safer chapter skipping and menu jumps + * fixed detection of current PTT to not assume a 1:1 mapping between PTTs and PGs + * releasing stills when jumping to menu fixes some state inconsistencies + * do not assume PGs to be physically laid out in sequence on the disc + * optional PGC based seeking + * new event on cell changes for timing info + +libdvdnav (0.1.5) unstable; urgency=low + * some bugfixes + * code cleanup + * build process polishing + * more sensible event order in get_next_block to ensure useful event delivery + * VOBU level resume + * fixed: seeking in a multiangle feature briefly showed the wrong angle + +libdvdnav (0.1.4) unstable; urgency=low + * more read cache improvements + * minor fixes for some problematic DVDs + +libdvdnav (0.1.3-1) unstable; urgency=low + * Zero-copy read cache. + * More support for alternative Menu languages. + + -- Rich Wareham Fri, 2 Aug 2002 08:52:24 +0100 + +libdvdnav (0.1.2-1) unstable; urgency=low + * Read Cache changes. Recommended setting for read_cache is OFF. + Unless one's DVD drive has too small a buffer. + * Should work with xine 0.9.10 or above. + + -- James Courtier-Dutton Sun, 3 Jul 2002 15:30:00 +0000 + +libdvdnav (0.1.1-1) unstable; urgency=low + + * New upstream version. (closes: #148495) + * Include TODO + * Fix config.h problem + * Threaded cache + + -- Philipp Matthias Hahn Sat, 1 Jun 2002 17:47:59 +0200 + +libdvdnav (0.1.0-2) unstable; urgency=low + + * Add manual page dvdnav-config.1 + * Add bug-presubj on Daniel's request + * Get dvdnav.c:1.17 from CVS to fix angle support + * Merge patch from Jamie Wilkinson (#146699) + * Rerun automake to fix dependencies + * Ack NMU from siggi + * Fix include in examples/menus.c + + -- Philipp Hahn Thu, 23 May 2002 09:41:15 +0200 + +libdvdnav (0.1.0-1.1) unstable; urgency=low + + * Prepared for first 'real' release. + * Bug fixes + * Changes to allow apps to 'roll-their-own' dvdnav_get_next_block functions. + * NMU in order to get xine-dvdnav running again + - changed package name to libdvdnav0 + (see patch from Jamie Wilkinson for a better solution) + + -- Siggi Langauf Mon, 20 May 2002 15:57:40 +0200 + +libdvdnav (0.0.1-1) unstable; urgency=low + + * Repackaged using dh-make. + + -- Philipp Matthias Hahn Sun, 7 Apr 2002 16:29:35 +0200 + +libdvdnav (0.0.1) unstable; urgency=low + + * Initial release. + * Split from xine-dvdnav + + -- rjw57 Tue, 12 Mar 2002 19:41:13 +0000 + diff --git a/libdvdread-embedded/README.md b/libdvdread-embedded/README.md new file mode 100644 index 0000000..6227d8d --- /dev/null +++ b/libdvdread-embedded/README.md @@ -0,0 +1,56 @@ +# Goals and features + +**libdvdread** is a library for simple navigation of DVD (DVDs without menus). + +Written in C, cross-platform, it gives low-level access to DVD structures. + +It works well in conjunction with ***libdvdnav*** *(menus)* and ***libdvdcss*** *(cipher)*. + +## Where does it come from? + +This library is based on a lot of code and expertise from the **Ogle project**. +**Ogle** was the first DVD player who implemented **free DVD navigation**. The +**libdvdread** developers wish to express their gratitude to the Ogle people +for all the valuable research work they have done. + +Initially, the dvdnav code was part of a plugin to the xine media player +called xine-dvdnav. Later on, the DVD VM specific code was split +from xine-dvdnav and went into the first version of libdvdnav. + +Then, it was forked, and forked again on MPlayer repositories. +libdvdnav and libdvdread were merged, and then split again. + +## Where is it now? + +Libdvdread is hosted [here](https://code.videolan.org/videolan/libdvdread). + +Libdvdnav is hosted [here](https://code.videolan.org/videolan/libdvdnav). + +You can find more information [here](https://www.videolan.org/developers/libdvdnav.html) + +Please report bugs to the developers mailinglist at +[dvdnav mailing list](https://mailman.videolan.org/listinfo/libdvdnav-devel) + +## License + +**Libdvdread** is completely licensed under GPLv2/v3. You may use it at wish within the +bounds of this license. See the file [COPYING](https://code.videolan.org/videolan/libdvdread/-/blob/master/COPYING) for a copy of the GPL. + +## Using libdvdread + +A detailed description of DVD structures is available [here](http://www.mpucoder.com/dvd/) + +All documentation is also accessible [here](http://dvdnav.mplayerhq.hu/#docs) + +## Deciphering disks + +**Libdvdread** does not do any decryption of the CSS algorithm. This task can be delegated to **libdvdcss**. + +Install *libdvdcss* from source or from your distribution (*libdvd-pkg*) to play full DVDs, +if your country allows this to work legally. + +Note that *libdvdnav* is useful for interactive DVD menus. + +## CoC + +The [VideoLAN Code of Conduct](https://wiki.videolan.org/Code_of_Conduct/) applies to this project. diff --git a/libdvdread-embedded/TODO b/libdvdread-embedded/TODO new file mode 100644 index 0000000..6f624ae --- /dev/null +++ b/libdvdread-embedded/TODO @@ -0,0 +1,12 @@ +* Support DVDs with errors on them. So we can recover from corrupt sectors in + the .VOB. Be able to read the VAT ICB at the last sector of the UDF disk (see + function UDFGetAVDP) +* Support Random and Shuffle Titles. Only sequential Titles are currently supported. +* rework documentation +* implement restriction levels: + 0 - execute everything as the app commands + 1 - do some sensible sanity checking + 2 - be more careful, when operations are prohibited (like not seeking/jumping in the presence of stills or cell commands) + 3 - fully respect user prohibitions +* cleanup public API and fix libtool versioning +* Update decoder.c with some of the more rare commands. Update already done to vmcmd.c diff --git a/libdvdread-embedded/configure.ac b/libdvdread-embedded/configure.ac new file mode 100644 index 0000000..a60ef0c --- /dev/null +++ b/libdvdread-embedded/configure.ac @@ -0,0 +1,137 @@ +dnl library version number +m4_define([dvdread_major], 6) +m4_define([dvdread_minor], 1) +m4_define([dvdread_micro], 3) +m4_define([dvdread_version],[dvdread_major.dvdread_minor.dvdread_micro]) + +AC_INIT(libdvdread, dvdread_version) + +AC_CONFIG_SRCDIR([src/dvd_reader.c]) + +AC_PREREQ(2.53) +AC_CANONICAL_HOST + +AM_INIT_AUTOMAKE([foreign dist-bzip2 no-dist-gzip subdir-objects]) +AM_MAINTAINER_MODE([enable]) +dnl Enable silent rules only when available (automake 1.11 or later). +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + +LT_INIT + +AC_CONFIG_HEADER(config.h) +AC_CONFIG_MACRO_DIR([m4]) + +dnl The libtool version numbers (DVDREAD_LT_*); Don't even think about faking this! +dnl +dnl immediately before every release do: +dnl =================================== +dnl if (the interface is totally unchanged from previous release) +dnl DVDREAD_LT_REVISION ++; +dnl else { /* interfaces have been added, removed or changed */ +dnl DVDREAD_LT_REVISION = 0; +dnl DVDREAD_LT_CURRENT ++; +dnl if (any interfaces have been _added_ since last release) +dnl AGE ++; +dnl if (any interfaces have been _removed_ or _incompatibly changed_) +dnl AGE = 0; +dnl } +dnl +dnl If you want to know more about what you are doing, here are some details: +dnl * DVDREAD_LT_CURRENT is the current API version +dnl * DVDREAD_LT_REVISION is an internal revision number which is increased when the API +dnl itself did not change +dnl * DVDREAD_LT_AGE is the number of previous API versions still supported by this library +dnl * libtool has its own numbering scheme, because local library numbering schemes +dnl are platform dependent +dnl * in Linux, the library will be named +dnl libname.so.(DVDREAD_LT_CURRENT - DVDREAD_LT_AGE).DVDREAD_LT_REVISION.DVDREAD_LT_AGE + +DVDREAD_LT_CURRENT=8 +DVDREAD_LT_AGE=0 +DVDREAD_LT_REVISION=0 + +AC_SUBST([DVDREAD_LTVERSION], [$DVDREAD_LT_CURRENT:$DVDREAD_LT_REVISION:$DVDREAD_LT_AGE]) + +AC_PROG_CC_C99 + +AC_CHECK_HEADERS_ONCE([sys/param.h limits.h dlfcn.h]) + +AC_SYS_LARGEFILE +AC_C_BIGENDIAN + +AS_CASE([$host], + [*mingw32* | *cygwin*], [AC_CHECK_FUNCS(gettimeofday)]) + +AS_CASE([$host], + [*-os2-*], LDFLAGS="-no-undefined -Zbin-files $LDFLAGS") + +AS_CASE([$host], + [*-linux-*], [AC_CHECK_FUNCS([getmntent_r])]) + +AC_ARG_WITH([libdvdcss], + AS_HELP_STRING([--with-libdvdcss], [Link directly against libdvdcss @<:@default=no@:>@])) + +AC_ARG_ENABLE([dlfcn], + [AS_HELP_STRING([--enable-dlfcn], + [use builtin dlfcn for mingw (default is auto)])], + [use_builtin_dlfcn=$enableval], + [use_builtin_dlfcn=no]) + +AS_IF([test x"$with_libdvdcss" = "xyes"], [ + CSS_REQUIRES="libdvdcss >= 1.2" + PKG_CHECK_MODULES([CSS], [$CSS_REQUIRES]) + AC_CHECK_HEADERS(dvdcss/dvdcss.h,, AC_MSG_ERROR(You need libdvdcss (dvdcss.h))) +], [ + AS_CASE([$host], + [*mingw32*], [], + [use_builtin_dlfcn=no]) + + AS_IF([test $use_builtin_dlfcn = "yes"], [ + AC_DEFINE([USING_BUILTIN_DLFCN], [1], ["Define to 1 to use builtin dlfcn"]) + ], [ + AC_SEARCH_LIBS([dlopen], [dl]) + ]) +]) +AC_SUBST([CSS_REQUIRES]) + +CC_CHECK_CFLAGS_APPEND([-Wall -Wsign-compare -Wextra]) + + +AC_ARG_ENABLE([apidoc], + AS_HELP_STRING([--disable-apidoc], [Disable building (with Doxygen) and installing API documentation @<:@default=auto@:@>])) + +AC_PATH_PROG([DOXYGEN], [doxygen]) + +AS_IF([test "x$DOXYGEN" = "x"], [ + AS_IF([test "x$enable_apidoc" = "xyes"], [ + AC_MSG_ERROR([You need Doxygen to build API documentation]) + ]) +]) +AM_CONDITIONAL([APIDOC], [test "x$DOXYGEN" != "x" && test "x$enable_apidoc" = "xyes"]) + +AS_IF([test "x$ac_cv_c_compiler_gnu" = "xyes"], [ + AC_DEFINE([UNUSED], [__attribute__((unused))], [Unused parameter annotation]) +], [ + AC_DEFINE([UNUSED], [], [Unused parameter annotation]) +]) + +AC_FUNC_STRERROR_R +AS_IF([test "x$ac_cv_func_strerror_r" = "xyes"], [], [AC_CHECK_FUNCS([strerror_s])]) + +dnl export library version number +DVDREAD_VERSION_MAJOR=dvdread_major() +DVDREAD_VERSION_MINOR=dvdread_minor() +DVDREAD_VERSION_MICRO=dvdread_micro() +AC_SUBST(DVDREAD_VERSION_MAJOR) +AC_SUBST(DVDREAD_VERSION_MINOR) +AC_SUBST(DVDREAD_VERSION_MICRO) + +dnl --------------------------------------------- +dnl Output configuration files +dnl --------------------------------------------- +AC_OUTPUT([ +Makefile +doc/doxygen.cfg +misc/dvdread.pc +src/dvdread/version.h +]) diff --git a/libdvdread-embedded/doc/doxygen.cfg.in b/libdvdread-embedded/doc/doxygen.cfg.in new file mode 100644 index 0000000..8a89a30 --- /dev/null +++ b/libdvdread-embedded/doc/doxygen.cfg.in @@ -0,0 +1,1332 @@ +# Doxyfile 1.5.6 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = @PACKAGE_NAME + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = @PACKAGE_VERSION@ + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = @top_builddir@/doc + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek, +# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish, +# Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, +# and Ukrainian. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen to replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespace are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = YES + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = @top_srcdir@/src + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 + +FILE_PATTERNS = *.c \ + *.h + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = ../src/config.h + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = *_private.h + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. Otherwise they will link to the documentstion. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = @top_srcdir@/doc/header.html + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = @top_srcdir@/doc/footer.html + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = YES + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to FRAME, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. Other possible values +# for this tag are: HIERARCHIES, which will generate the Groups, Directories, +# and Class Hiererachy pages using a tree view instead of an ordered list; +# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which +# disables this behavior completely. For backwards compatibility with previous +# releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE +# respectively. + +GENERATE_TREEVIEW = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = _DOXYGEN_SKIP_ME + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# By default doxygen will write a font called FreeSans.ttf to the output +# directory and reference it in all dot files that doxygen generates. This +# font does not include all possible unicode characters however, so when you need +# these (or just want a differently looking font) you can specify the font name +# using DOT_FONTNAME. You need need to make sure dot is able to find the font, +# which can be done by putting it in a standard location or by setting the +# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory +# containing the font. + +DOT_FONTNAME = FreeSans + +# By default doxygen will tell dot to use the output directory to look for the +# FreeSans.ttf font (which doxygen will put there itself). If you specify a +# different font using DOT_FONTNAME you can set the path where dot +# can find it using this tag. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = . + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is enabled by default, which results in a transparent +# background. Warning: Depending on the platform used, enabling this option +# may lead to badly anti-aliased labels on the edges of a graph (i.e. they +# become hard to read). + +DOT_TRANSPARENT = YES + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO diff --git a/libdvdread-embedded/doc/footer.html b/libdvdread-embedded/doc/footer.html new file mode 100644 index 0000000..b605728 --- /dev/null +++ b/libdvdread-embedded/doc/footer.html @@ -0,0 +1,2 @@ + + diff --git a/libdvdread-embedded/doc/header.html b/libdvdread-embedded/doc/header.html new file mode 100644 index 0000000..4b43b61 --- /dev/null +++ b/libdvdread-embedded/doc/header.html @@ -0,0 +1,9 @@ + + + + + libdvdread documentation + + + + diff --git a/libdvdread-embedded/m4/attributes.m4 b/libdvdread-embedded/m4/attributes.m4 new file mode 100644 index 0000000..39d02e3 --- /dev/null +++ b/libdvdread-embedded/m4/attributes.m4 @@ -0,0 +1,296 @@ +dnl Macros to check the presence of generic (non-typed) symbols. +dnl Copyright (c) 2006-2007 Diego Pettenò +dnl Copyright (c) 2006-2007 xine project +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +dnl 02110-1301, USA. +dnl +dnl As a special exception, the copyright owners of the +dnl macro gives unlimited permission to copy, distribute and modify the +dnl configure scripts that are the output of Autoconf when processing the +dnl Macro. You need not follow the terms of the GNU General Public +dnl License when using or distributing such scripts, even though portions +dnl of the text of the Macro appear in them. The GNU General Public +dnl License (GPL) does govern all other use of the material that +dnl constitutes the Autoconf Macro. +dnl +dnl This special exception to the GPL applies to versions of the +dnl Autoconf Macro released by this project. When you make and +dnl distribute a modified version of the Autoconf Macro, you may extend +dnl this special exception to the GPL to apply to your modified version as +dnl well. + +dnl Check if the flag is supported by compiler +dnl CC_CHECK_CFLAGS_SILENT([FLAG], [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND]) + +AC_DEFUN([CC_CHECK_CFLAGS_SILENT], [ + AC_CACHE_VAL(AS_TR_SH([cc_cv_cflags_$1]), + [ac_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $1" + AC_LINK_IFELSE([AC_LANG_SOURCE([int main() { return 0; }])], + [eval "AS_TR_SH([cc_cv_cflags_$1])='yes'"], + [eval "AS_TR_SH([cc_cv_cflags_$1])='no'"]) + CFLAGS="$ac_save_CFLAGS" + ]) + + AS_IF([eval test x$]AS_TR_SH([cc_cv_cflags_$1])[ = xyes], + [$2], [$3]) +]) + +dnl Check if the flag is supported by compiler (cacheable) +dnl CC_CHECK_CFLAGS([FLAG], [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND]) + +AC_DEFUN([CC_CHECK_CFLAGS], [ + AC_CACHE_CHECK([if $CC supports $1 flag], + AS_TR_SH([cc_cv_cflags_$1]), + CC_CHECK_CFLAGS_SILENT([$1]) dnl Don't execute actions here! + ) + + AS_IF([eval test x$]AS_TR_SH([cc_cv_cflags_$1])[ = xyes], + [$2], [$3]) +]) + +dnl CC_CHECK_CFLAG_APPEND(FLAG, [action-if-found], [action-if-not-found]) +dnl Check for CFLAG and appends them to CFLAGS if supported +AC_DEFUN([CC_CHECK_CFLAG_APPEND], [ + AC_CACHE_CHECK([if $CC supports $1 flag], + AS_TR_SH([cc_cv_cflags_$1]), + CC_CHECK_CFLAGS_SILENT([$1]) dnl Don't execute actions here! + ) + + AS_IF([eval test x$]AS_TR_SH([cc_cv_cflags_$1])[ = xyes], + [CFLAGS="$CFLAGS $1"; $2], [$3]) +]) + +dnl CC_CHECK_CFLAGS_APPEND([FLAG1 FLAG2], [action-if-found], [action-if-not]) +AC_DEFUN([CC_CHECK_CFLAGS_APPEND], [ + for flag in $1; do + CC_CHECK_CFLAG_APPEND($flag, [$2], [$3]) + done +]) + +dnl Check if the flag is supported by linker (cacheable) +dnl CC_CHECK_LDFLAGS([FLAG], [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND]) + +AC_DEFUN([CC_CHECK_LDFLAGS], [ + AC_CACHE_CHECK([if $CC supports $1 flag], + AS_TR_SH([cc_cv_ldflags_$1]), + [ac_save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $1" + AC_LINK_IFELSE([AC_LANG_SOURCE([int main() { return 1; }])], + [eval "AS_TR_SH([cc_cv_ldflags_$1])='yes'"], + [eval "AS_TR_SH([cc_cv_ldflags_$1])="]) + LDFLAGS="$ac_save_LDFLAGS" + ]) + + AS_IF([eval test x$]AS_TR_SH([cc_cv_ldflags_$1])[ = xyes], + [$2], [$3]) +]) + +dnl Check for a -Werror flag or equivalent. -Werror is the GCC +dnl and ICC flag that tells the compiler to treat all the warnings +dnl as fatal. We usually need this option to make sure that some +dnl constructs (like attributes) are not simply ignored. +dnl +dnl Other compilers don't support -Werror per se, but they support +dnl an equivalent flag: +dnl - Sun Studio compiler supports -errwarn=%all +AC_DEFUN([CC_CHECK_WERROR], [ + AC_CACHE_CHECK( + [for $CC way to treat warnings as errors], + [cc_cv_werror], + [CC_CHECK_CFLAGS_SILENT([-Werror], [cc_cv_werror=-Werror], + [CC_CHECK_CFLAGS_SILENT([-errwarn=%all], [cc_cv_werror=-errwarn=%all])]) + ]) +]) + +AC_DEFUN([CC_CHECK_ATTRIBUTE], [ + AC_REQUIRE([CC_CHECK_WERROR]) + AC_CACHE_CHECK([if $CC supports __attribute__(( ifelse([$2], , [$1], [$2]) ))], + AS_TR_SH([cc_cv_attribute_$1]), + [ac_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $cc_cv_werror" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([$3])], + [eval "AS_TR_SH([cc_cv_attribute_$1])='yes'"], + [eval "AS_TR_SH([cc_cv_attribute_$1])='no'"]) + CFLAGS="$ac_save_CFLAGS" + ]) + + AS_IF([eval test x$]AS_TR_SH([cc_cv_attribute_$1])[ = xyes], + [AC_DEFINE( + AS_TR_CPP([SUPPORT_ATTRIBUTE_$1]), 1, + [Define this if the compiler supports __attribute__(( ifelse([$2], , [$1], [$2]) ))] + ) + $4], + [$5]) +]) + +AC_DEFUN([CC_ATTRIBUTE_CONSTRUCTOR], [ + CC_CHECK_ATTRIBUTE( + [constructor],, + [extern void foo(); + void __attribute__((constructor)) ctor() { foo(); }], + [$1], [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_DESTRUCTOR], [ + CC_CHECK_ATTRIBUTE( + [destructor],, + [extern void foo(); + void __attribute__((destructor)) dtor() { foo(); }], + [$1], [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_FORMAT], [ + CC_CHECK_ATTRIBUTE( + [format], [format(printf, n, n)], + [void __attribute__((format(printf, 1, 2))) printflike(const char *fmt, ...) { fmt = (void *)0; }], + [$1], [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_FORMAT_ARG], [ + CC_CHECK_ATTRIBUTE( + [format_arg], [format_arg(printf)], + [char *__attribute__((format_arg(1))) gettextlike(const char *fmt) { fmt = (void *)0; }], + [$1], [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_VISIBILITY], [ + CC_CHECK_ATTRIBUTE( + [visibility_$1], [visibility("$1")], + [void __attribute__((visibility("$1"))) $1_function() { }], + [$2], [$3]) +]) + +AC_DEFUN([CC_ATTRIBUTE_NONNULL], [ + CC_CHECK_ATTRIBUTE( + [nonnull], [nonnull()], + [void __attribute__((nonnull())) some_function(void *foo, void *bar) { foo = (void*)0; bar = (void*)0; }], + [$1], [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_UNUSED], [ + CC_CHECK_ATTRIBUTE( + [unused], , + [void some_function(void *foo, __attribute__((unused)) void *bar);], + [$1], [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_SENTINEL], [ + CC_CHECK_ATTRIBUTE( + [sentinel], , + [void some_function(void *foo, ...) __attribute__((sentinel));], + [$1], [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_DEPRECATED], [ + CC_CHECK_ATTRIBUTE( + [deprecated], , + [void some_function(void *foo, ...) __attribute__((deprecated));], + [$1], [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_ALIAS], [ + CC_CHECK_ATTRIBUTE( + [alias], [weak, alias], + [void other_function(void *foo) { } + void some_function(void *foo) __attribute__((weak, alias("other_function")));], + [$1], [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_MALLOC], [ + CC_CHECK_ATTRIBUTE( + [malloc], , + [void * __attribute__((malloc)) my_alloc(int n);], + [$1], [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_PACKED], [ + CC_CHECK_ATTRIBUTE( + [packed], , + [struct astructure { char a; int b; long c; void *d; } __attribute__((packed)); + char assert@<:@(sizeof(struct astructure) == (sizeof(char)+sizeof(int)+sizeof(long)+sizeof(void*)))-1@:>@;], + [$1], [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_CONST], [ + CC_CHECK_ATTRIBUTE( + [const], , + [int __attribute__((const)) twopow(int n) { return 1 << n; } ], + [$1], [$2]) +]) + +AC_DEFUN([CC_FLAG_VISIBILITY], [ + AC_REQUIRE([CC_CHECK_WERROR]) + AC_CACHE_CHECK([if $CC supports -fvisibility=hidden], + [cc_cv_flag_visibility], + [cc_flag_visibility_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $cc_cv_werror" + CC_CHECK_CFLAGS_SILENT([-fvisibility=hidden], + cc_cv_flag_visibility='yes', + cc_cv_flag_visibility='no') + CFLAGS="$cc_flag_visibility_save_CFLAGS"]) + + AS_IF([test "x$cc_cv_flag_visibility" = "xyes"], + [AC_DEFINE([SUPPORT_FLAG_VISIBILITY], 1, + [Define this if the compiler supports the -fvisibility flag]) + $1], + [$2]) +]) + +AC_DEFUN([CC_FUNC_EXPECT], [ + AC_REQUIRE([CC_CHECK_WERROR]) + AC_CACHE_CHECK([if compiler has __builtin_expect function], + [cc_cv_func_expect], + [ac_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $cc_cv_werror" + AC_COMPILE_IFELSE( + [int some_function() { + int a = 3; + return (int)__builtin_expect(a, 3); + }], + [cc_cv_func_expect=yes], + [cc_cv_func_expect=no]) + CFLAGS="$ac_save_CFLAGS" + ]) + + AS_IF([test "x$cc_cv_func_expect" = "xyes"], + [AC_DEFINE([SUPPORT__BUILTIN_EXPECT], 1, + [Define this if the compiler supports __builtin_expect() function]) + $1], + [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_ALIGNED], [ + AC_REQUIRE([CC_CHECK_WERROR]) + AC_CACHE_CHECK([highest __attribute__ ((aligned ())) supported], + [cc_cv_attribute_aligned], + [ac_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $cc_cv_werror" + for cc_attribute_align_try in 64 32 16 8 4 2; do + AC_COMPILE_IFELSE([ + int main() { + static char c __attribute__ ((aligned($cc_attribute_align_try))) = 0; + return c; + }], [cc_cv_attribute_aligned=$cc_attribute_align_try; break]) + done + CFLAGS="$ac_save_CFLAGS" + ]) + + if test "x$cc_cv_attribute_aligned" != "x"; then + AC_DEFINE_UNQUOTED([ATTRIBUTE_ALIGNED_MAX], [$cc_cv_attribute_aligned], + [Define the highest alignment supported]) + fi +]) diff --git a/libdvdread-embedded/misc/dvdread.pc.in b/libdvdread-embedded/misc/dvdread.pc.in new file mode 100644 index 0000000..2e8f66a --- /dev/null +++ b/libdvdread-embedded/misc/dvdread.pc.in @@ -0,0 +1,13 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libdvdread +Description: Low level DVD access library +Version: @VERSION@ + +Requires.private: @CSS_REQUIRES@ + +Cflags: -I${includedir} +Libs: -L${libdir} -ldvdread diff --git a/libdvdread-embedded/msvc/config.h b/libdvdread-embedded/msvc/config.h new file mode 100644 index 0000000..4e9b60e --- /dev/null +++ b/libdvdread-embedded/msvc/config.h @@ -0,0 +1,56 @@ +/* config.h. Generated by hand. */ + +#ifndef LIBDVDREAD_CONFIG_H +#define LIBDVDREAD_CONFIG_H + +#define HAVE_DLFCN_H 1 +/* #undef HAVE_DVDCSS_DVDCSS_H*/ +/* #undef HAVE_INTTYPES_H */ +#define HAVE_MEMORY_H 1 +/* #undef HAVE_STDINT_H */ +#define HAVE_STDLIB_H 1 +#define HAVE_STRINGS_H 1 +#define HAVE_STRING_H 1 +#define HAVE_SYS_STAT_H 1 +#define HAVE_SYS_TYPES_H 1 +/* #undef HAVE_UNISTD_H */ +#define PACKAGE "libdvdread" +#define PACKAGE_BUGREPORT "" +#define PACKAGE_NAME "" +#define PACKAGE_STRING "" +#define PACKAGE_TARNAME "" +#define PACKAGE_VERSION "" +#define STDC_HEADERS 1 +#define VERSION "1.2.6" +/* #undef WORDS_BIGENDIAN */ +/* #undef __DARWIN__ */ +/* #undef const */ +#define inline __inline +/* #undef size_t */ + +#define ssize_t __int64 + +#ifndef PATH_MAX +#define PATH_MAX MAX_PATH +#endif + +#define strcasecmp stricmp +#define strncasecmp strnicmp + +#define S_ISDIR(m) ((m) & _S_IFDIR) +#define S_ISREG(m) ((m) & _S_IFREG) +#define S_ISBLK(m) 0 +#define S_ISCHR(m) 0 + +/* Fallback types (very x86-centric, sorry) */ +typedef unsigned char uint8_t; +typedef signed char int8_t; +typedef unsigned short uint16_t; +typedef signed short int16_t; +typedef unsigned int uint32_t; +typedef signed int int32_t; +typedef unsigned __int64 uint64_t; +typedef signed __int64 int64_t; +typedef unsigned int uintptr_t; + +#endif /* LIBDVDREAD_CONFIG_H */ diff --git a/libdvdread-embedded/msvc/contrib/dirent/dirent.c b/libdvdread-embedded/msvc/contrib/dirent/dirent.c new file mode 100644 index 0000000..0eddd90 --- /dev/null +++ b/libdvdread-embedded/msvc/contrib/dirent/dirent.c @@ -0,0 +1,135 @@ +/* + + Implementation of POSIX directory browsing functions and types for Win32. + + Kevlin Henney (mailto:kevlin@acm.org), March 1997. + + Copyright Kevlin Henney, 1997. All rights reserved. + + Permission to use, copy, modify, and distribute this software and its + documentation for any purpose is hereby granted without fee, provided + that this copyright and permissions notice appear in all copies and + derivatives, and that no charge may be made for the software and its + documentation except to cover cost of distribution. + + This software is supplied "as is" without express or implied warranty. + + But that said, if there are any problems please get in touch. + +*/ + +#include +#include +#include +#include +#include + +#ifndef DIR + +struct DIR +{ + long handle; /* -1 for failed rewind */ + struct _finddata_t info; + struct dirent result; /* d_name null iff first time */ + char *name; /* NTBS */ +}; + +#endif + +DIR *opendir(const char *name) +{ + DIR *dir = 0; + + if(name && name[0]) + { + size_t base_length = strlen(name); + const char *all = /* the root directory is a special case... */ + strchr("/\\", name[base_length - 1]) ? "*" : "/*"; + + if((dir = malloc(sizeof *dir)) != 0 && + (dir->name = malloc(base_length + strlen(all) + 1)) != 0) + { + strcat(strcpy(dir->name, name), all); + + if((dir->handle = _findfirst(dir->name, &dir->info)) != -1) + { + dir->result.d_name = 0; + } + else /* rollback */ + { + free(dir->name); + free(dir); + dir = 0; + } + } + else /* rollback */ + { + free(dir); + dir = 0; + errno = ENOMEM; + } + } + else + { + errno = EINVAL; + } + + return dir; +} + +int closedir(DIR *dir) +{ + int result = -1; + + if(dir) + { + if(dir->handle != -1) + { + result = _findclose(dir->handle); + } + + free(dir->name); + free(dir); + } + + if(result == -1) /* map all errors to EBADF */ + { + errno = EBADF; + } + + return result; +} + +struct dirent *readdir(DIR *dir) +{ + struct dirent *result = 0; + + if(dir && dir->handle != -1) + { + if(!dir->result.d_name || _findnext(dir->handle, &dir->info) != -1) + { + result = &dir->result; + result->d_name = dir->info.name; + } + } + else + { + errno = EBADF; + } + + return result; +} + +void rewinddir(DIR *dir) +{ + if(dir && dir->handle != -1) + { + _findclose(dir->handle); + dir->handle = _findfirst(dir->name, &dir->info); + dir->result.d_name = 0; + } + else + { + errno = EBADF; + } +} diff --git a/libdvdread-embedded/msvc/contrib/dirent/dirent.h b/libdvdread-embedded/msvc/contrib/dirent/dirent.h new file mode 100644 index 0000000..28a1773 --- /dev/null +++ b/libdvdread-embedded/msvc/contrib/dirent/dirent.h @@ -0,0 +1,32 @@ +/* + + Declaration of POSIX directory browsing functions and types for Win32. + + Kevlin Henney (mailto:kevlin@acm.org), March 1997. + + Copyright Kevlin Henney, 1997. All rights reserved. + + Permission to use, copy, modify, and distribute this software and its + documentation for any purpose is hereby granted without fee, provided + that this copyright and permissions notice appear in all copies and + derivatives, and that no charge may be made for the software and its + documentation except to cover cost of distribution. + +*/ + +#ifndef DIRENT_INCLUDED +#define DIRENT_INCLUDED + +typedef struct DIR DIR; + +struct dirent +{ + char *d_name; +}; + +DIR *opendir(const char *); +int closedir(DIR *); +struct dirent *readdir(DIR *); +void rewinddir(DIR *); + +#endif diff --git a/libdvdread-embedded/msvc/contrib/dlfcn.c b/libdvdread-embedded/msvc/contrib/dlfcn.c new file mode 100644 index 0000000..01b5781 --- /dev/null +++ b/libdvdread-embedded/msvc/contrib/dlfcn.c @@ -0,0 +1,96 @@ +/* + * Adopted from Apache DSO code. + * Portions copyright Apache Software Foundation + * + * Structures and types used to implement dlopen, dlsym, etc. + * on Windows 95/NT. + */ +#include +#include +#include + +#include "../include/dlfcn.h" +#include "../include/os_types.h" + +void *dlopen(const char *module_name, int mode) +{ + UINT em; + HINSTANCE dsoh; + char path[MAX_PATH], *p; + (void)mode; + /* Load the module... + * per PR2555, the LoadLibraryEx function is very picky about slashes. + * Debugging on NT 4 SP 6a reveals First Chance Exception within NTDLL. + * LoadLibrary in the MS PSDK also reveals that it -explicitly- states + * that backslashes must be used. + * + * Transpose '\' for '/' in the filename. + */ + (void)strncpy(path, module_name, MAX_PATH); + path[MAX_PATH - 1] = 0; + p = path; + while ((p = strchr(p, '/'))) + *p = '\\'; + + /* First assume the dso/dll's required by -this- dso are sitting in the + * same path or can be found in the usual places. Failing that, let's + * let that dso look in the apache root. + */ + em = SetErrorMode(SEM_FAILCRITICALERRORS); + dsoh = LoadLibraryEx(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); + if (!dsoh) + { + SetLastError(0); // clear the last error + dsoh = LoadLibraryEx(path, NULL, 0); + } + SetErrorMode(em); + SetLastError(0); // clear the last error + return (void *)dsoh; +} + +char *dlerror(void) +{ + int len, nErrorCode; + static char errstr[120]; + /* This is -not- threadsafe code, but it's about the best we can do. + * mostly a potential problem for isapi modules, since LoadModule + * errors are handled within a single config thread. + */ + + if((nErrorCode = GetLastError()) == 0) + return((char *)0); + + SetLastError(0); // clear the last error + len = snprintf(errstr, sizeof(errstr), "(%d) ", nErrorCode); + + len += FormatMessage( + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + nErrorCode, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */ + (LPTSTR) errstr + len, + sizeof(errstr) - len, + NULL + ); + /* FormatMessage may have appended a newline (\r\n). So remove it + * and use ": " instead like the Unix errors. The error may also + * end with a . before the return - if so, trash it. + */ + if (len > 1 && errstr[len-2] == '\r' && errstr[len-1] == '\n') { + if (len > 2 && errstr[len-3] == '.') + len--; + errstr[len-2] = ':'; + errstr[len-1] = ' '; + } + return errstr; +} + +int dlclose(void *handle) +{ + return FreeLibrary(handle); +} + +void *dlsym(void *handle, const char *name) +{ + return GetProcAddress(handle, name); +} diff --git a/libdvdread-embedded/msvc/contrib/win32_cs.h b/libdvdread-embedded/msvc/contrib/win32_cs.h new file mode 100644 index 0000000..cb29bac --- /dev/null +++ b/libdvdread-embedded/msvc/contrib/win32_cs.h @@ -0,0 +1,40 @@ +/* + * This file is part of libdvdread. + * + * libdvdread 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 of the License, or + * (at your option) any later version. + * + * libdvdread 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 libdvdread; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include + +static inline wchar_t *_utf8_to_wchar(const char *utf8) +{ + wchar_t *wstr; + int wlen; + + wlen = MultiByteToWideChar (CP_UTF8, 0, utf8, -1, NULL, 0); + if (wlen < 1) { + return NULL; + } + wstr = (wchar_t*)malloc(sizeof(wchar_t) * wlen); + if (!wstr ) { + return NULL; + } + if (!MultiByteToWideChar(CP_UTF8, 0, utf8, -1, wstr, wlen)) { + free(wstr); + return NULL; + } + return wstr; +} diff --git a/libdvdread-embedded/msvc/ifo_dump.dsp b/libdvdread-embedded/msvc/ifo_dump.dsp new file mode 100644 index 0000000..48e718b --- /dev/null +++ b/libdvdread-embedded/msvc/ifo_dump.dsp @@ -0,0 +1,110 @@ +# Microsoft Developer Studio Project File - Name="ifo_dump" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=ifo_dump - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "ifo_dump.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ifo_dump.mak" CFG="ifo_dump - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ifo_dump - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "ifo_dump - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ifo_dump - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "ifo_dump - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "ifo_dump___Win32_Debug" +# PROP BASE Intermediate_Dir "ifo_dump___Win32_Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug\ifo_dump" +# PROP Intermediate_Dir "Debug\ifo_dump" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "include" /I "." /I "install/include" /I ".." /I "../src" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "DVDNAV_COMPILE" /FR /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug/bin/ifo_dump.exe" /pdbtype:sept +# SUBTRACT LINK32 /pdb:none + +!ENDIF + +# Begin Target + +# Name "ifo_dump - Win32 Release" +# Name "ifo_dump - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\src\ifo_dump.c +# End Source File +# Begin Source File + +SOURCE=..\src\ifo_print.c +# End Source File +# Begin Source File + +SOURCE=..\src\vmcmd.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/libdvdread-embedded/msvc/include/dlfcn.h b/libdvdread-embedded/msvc/include/dlfcn.h new file mode 100644 index 0000000..edd03a6 --- /dev/null +++ b/libdvdread-embedded/msvc/include/dlfcn.h @@ -0,0 +1,18 @@ +#ifndef __DLFCN_H__ +# define __DLFCN_H__ + +extern void *dlopen (const char *file, int mode); +extern int dlclose (void *handle); +extern void *dlsym (void * handle, const char * name); +extern char *dlerror (void); + +/* These don't mean anything on windows */ +#define RTLD_NEXT ((void *) -1l) +#define RTLD_DEFAULT ((void *) 0) +#define RTLD_LAZY -1 +#define RTLD_NOW -1 +#define RTLD_BINDING_MASK -1 +#define RTLD_NOLOAD -1 +#define RTLD_GLOBAL -1 + +#endif /* __DLFCN_H__ */ diff --git a/libdvdread-embedded/msvc/include/inttypes.h b/libdvdread-embedded/msvc/include/inttypes.h new file mode 100644 index 0000000..4e1cbe1 --- /dev/null +++ b/libdvdread-embedded/msvc/include/inttypes.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2000-2001 the xine project + * + * This file is part of xine, a unix video player. + * + * xine 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 of the License, or + * (at your option) any later version. + * + * xine 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. + * + * WIN32 PORT, + * by Matthew Grooms + * + * inttypes.h - Standard integer definitions. + * + */ + +#ifndef _SYS_INTTYPES_H_ +#define _SYS_INTTYPES_H_ + +#include + +#endif diff --git a/libdvdread-embedded/msvc/include/os_types.h b/libdvdread-embedded/msvc/include/os_types.h new file mode 100644 index 0000000..eb0f24f --- /dev/null +++ b/libdvdread-embedded/msvc/include/os_types.h @@ -0,0 +1,24 @@ +#ifndef __OS_TYPES_H__ +#define __OS_TYPES_H__ +/* + * win32 types + * 04 Sept 2001 - Chris Wolf create. + */ + +typedef unsigned char uint_8; +typedef unsigned short uint_16; +typedef unsigned int uint_32; +typedef signed char sint_32; +typedef signed short sint_16; +typedef signed int sint_8; + +#define snprintf _snprintf +#define M_PI 3.14159265358979323846 /* pi */ +#define DLLENTRY __declspec(dllexport) + + // Temporarily hardcode this location +#define AO_PLUGIN_PATH "c:\\Program Files\\Common Files\\Xiphophorus\\ao" + +#define SHARED_LIB_EXT ".dll" + +#endif /* __OS_TYPES_H__ */ diff --git a/libdvdread-embedded/msvc/include/sys/time.h b/libdvdread-embedded/msvc/include/sys/time.h new file mode 100644 index 0000000..f7973c1 --- /dev/null +++ b/libdvdread-embedded/msvc/include/sys/time.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2000-2001 the xine project + * + * This file is part of xine, a unix video player. + * + * xine 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 of the License, or + * (at your option) any later version. + * + * xine 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. + * + * WIN32 PORT, + * by Matthew Grooms + * + * sys/time.h - There is no separate sys/time.h for win32 so we simply + * include the standard time header as well as our xine + * timer functions. + */ + +#include diff --git a/libdvdread-embedded/msvc/include/unistd.h b/libdvdread-embedded/msvc/include/unistd.h new file mode 100644 index 0000000..620017c --- /dev/null +++ b/libdvdread-embedded/msvc/include/unistd.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2000-2001 the xine project + * + * This file is part of xine, a unix video player. + * + * xine 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 of the License, or + * (at your option) any later version. + * + * xine 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. + * + * WIN32 PORT, + * by Matthew Grooms + * + * unistd.h - This is mostly a catch all header that maps standard unix + * libc calls to the equivalent win32 functions. + * + */ + +#include +#include +#include +#include + +#include + +#ifndef _SYS_UNISTD_H_ +#define _SYS_UNISTD_H_ + +#define inline __inline + +#define mkdir( A, B ) _mkdir( A ) +#define lstat stat + +#ifndef S_ISDIR +#define S_ISDIR(A) ( S_IFDIR & A ) +#endif + +#define S_IXUSR S_IEXEC +#define S_IXGRP S_IEXEC +#define S_IXOTH S_IEXEC + +#define M_PI 3.14159265358979323846 /* pi */ + +#define bzero( A, B ) memset( A, 0, B ) + +#ifndef strcasecmp +#define strcasecmp _stricmp +#endif + +#ifndef strncasecmp +#define strncasecmp _strnicmp +#endif + +#define snprintf _snprintf +#define vsnprintf _vsnprintf + +// FIXME : I don't remember why this is here +#define readlink + +#endif diff --git a/libdvdread-embedded/msvc/install/README b/libdvdread-embedded/msvc/install/README new file mode 100644 index 0000000..5e6ba4a --- /dev/null +++ b/libdvdread-embedded/msvc/install/README @@ -0,0 +1,7 @@ +MSVC Help +--------- + +In order to build using any application that requires libdvdnav using MSVC the +following directories (lib and include) must be copied to the msvc directory of +the particular application. + diff --git a/libdvdread-embedded/msvc/libdvdcss.def b/libdvdread-embedded/msvc/libdvdcss.def new file mode 100644 index 0000000..0a6e2fd --- /dev/null +++ b/libdvdread-embedded/msvc/libdvdcss.def @@ -0,0 +1,12 @@ +;------------------------------------------------------------ +; LIBDVDCSS DLL DEFINITIONS FILE + +EXPORTS + +dvdcss_interface_2 +dvdcss_open +dvdcss_error +dvdcss_seek +dvdcss_read +dvdcss_close +dvdcss_title \ No newline at end of file diff --git a/libdvdread-embedded/msvc/libdvdcss.dsp b/libdvdread-embedded/msvc/libdvdcss.dsp new file mode 100644 index 0000000..bb91b6a --- /dev/null +++ b/libdvdread-embedded/msvc/libdvdcss.dsp @@ -0,0 +1,139 @@ +# Microsoft Developer Studio Project File - Name="libdvdcss" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=libdvdcss - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libdvdcss.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libdvdcss.mak" CFG="libdvdcss - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libdvdcss - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "libdvdcss - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libdvdcss - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_USRDLL" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "." /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_USRDLL" /D PATH_MAX=2048 /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 /machine:IX86 +# ADD LINK32 /machine:IX86 +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=Create libdvdcss Install +PostBuild_Cmds=scripts\libdvdcss_intstall.bat Release +# End Special Build Tool + +!ELSEIF "$(CFG)" == "libdvdcss - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_USRDLL" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "." /I "../libdvdcss/dvdcss" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_USRDLL" /D MAX_PATH=2048 /YX /FD /GZ ./ "../libdvdcss" /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 /machine:IX86 +# ADD LINK32 /dll /machine:IX86 /out:"Debug/bin/libdvdcss.dll" +# SUBTRACT LINK32 /pdb:none +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=Create libdvdcss Install +PostBuild_Cmds=scripts\libdvdcss_intstall.bat Debug +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "libdvdcss - Win32 Release" +# Name "libdvdcss - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\libdvdcss\css.c +# End Source File +# Begin Source File + +SOURCE=..\..\libdvdcss\device.c +# End Source File +# Begin Source File + +SOURCE=..\..\libdvdcss\error.c +# End Source File +# Begin Source File + +SOURCE=..\..\libdvdcss\ioctl.c +# End Source File +# Begin Source File + +SOURCE=..\..\libdvdcss\libdvdcss.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "DLL Defs" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\libdvdcss.def +# End Source File +# End Group +# End Target +# End Project diff --git a/libdvdread-embedded/msvc/libdvdnav.def b/libdvdread-embedded/msvc/libdvdnav.def new file mode 100644 index 0000000..a483cfd --- /dev/null +++ b/libdvdread-embedded/msvc/libdvdnav.def @@ -0,0 +1,73 @@ +;------------------------------------------------------------ +; LIBDVDNAV DLL DEFINITIONS FILE + +EXPORTS + +DVDOpen +DVDClose +DVDOpenFile +DVDCloseFile +DVDReadBlocks + +navRead_DSI +navRead_PCI + +ifoClose +ifoRead_VOBU_ADMAP +ifoRead_VTS_ATRT +ifoRead_PTL_MAIT +ifoRead_PGCI_UT +ifoRead_TT_SRPT +ifoRead_FP_PGC +ifoOpenVMGI +ifoRead_TITLE_VOBU_ADMAP +ifoRead_PGCIT +ifoRead_VTS_PTT_SRPT +ifoOpenVTSI +ifoPrint + +dvdnav_set_readahead_flag +dvdnav_set_region_mask +dvdnav_spu_language_select +dvdnav_audio_language_select +dvdnav_menu_language_select +dvdnav_get_angle_info +dvdnav_current_title_info +dvdnav_title_play +dvdnav_part_play +dvdnav_get_number_of_titles +dvdnav_get_title_string +dvdnav_open +dvdnav_close +dvdnav_wait_skip +dvdnav_get_video_scale_permission +dvdnav_get_video_aspect +dvdnav_still_skip +dvdnav_err_to_string +dvdnav_get_next_cache_block +dvdnav_free_cache_block +dvdnav_get_position +dvdnav_sector_search +dvdnav_get_current_highlight +dvdnav_button_select_and_activate +dvdnav_right_button_select +dvdnav_left_button_select +dvdnav_lower_button_select +dvdnav_upper_button_select +dvdnav_mouse_select +dvdnav_button_select +dvdnav_mouse_activate +dvdnav_button_activate +dvdnav_angle_change +dvdnav_prev_pg_search +dvdnav_next_pg_search +dvdnav_menu_call +dvdnav_spu_stream_to_lang +dvdnav_get_spu_logical_stream +dvdnav_audio_stream_to_lang +dvdnav_get_audio_logical_stream +dvdnav_is_domain_vts + +dvdnav_set_PGC_positioning_flag +dvdnav_get_number_of_parts +dvdnav_reset diff --git a/libdvdread-embedded/msvc/libdvdnav.dsp b/libdvdread-embedded/msvc/libdvdnav.dsp new file mode 100644 index 0000000..9d8196e --- /dev/null +++ b/libdvdread-embedded/msvc/libdvdnav.dsp @@ -0,0 +1,188 @@ +# Microsoft Developer Studio Project File - Name="libdvdnav" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=libdvdnav - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libdvdnav.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libdvdnav.mak" CFG="libdvdnav - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libdvdnav - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "libdvdnav - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libdvdnav - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +LINK32=link.exe +# ADD BASE LINK32 /machine:IX86 +# ADD LINK32 /machine:IX86 +MTL=midl.exe +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\..\libdvdcss\src" /I "." /I "include" /I "contrib/dirent" /I "../../libdvdcss" /I ".." /I "../src" /I "../src/dvdread" /I "../src/vm" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "DVDNAV_COMPILE" /D "HAVE_CONFIG_H" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"Release\libdvdnav\libdvdnav.lib" +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=Create libdvdnav Install Files +PostBuild_Cmds=scripts\libdvdnav_install.bat Release +# End Special Build Tool + +!ELSEIF "$(CFG)" == "libdvdnav - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +LINK32=link.exe +# ADD BASE LINK32 /machine:IX86 +# ADD LINK32 /debug /machine:IX86 /out:"Debug/libdvdnav.lib" /implib:"Debug/libdvdnav.lib" +# SUBTRACT LINK32 /pdb:none /nodefaultlib +MTL=midl.exe +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "include" /I "contrib/dirent" /I "../../libdvdcss" /I "../src" /I "." /I ".." /I "../src/dvdread" /I "../src/vm" /D "WIN32" /D "_DEBUG" /D "_LIB" /D "DVDNAV_COMPILE" /D "HAVE_CONFIG_H" /FR"Debug/libdvdnav/" /Fp"Debug/libdvdnav/libdvdnav.pch" /YX /Fo"Debug/libdvdnav/" /Fd"Debug/libdvdnav/" /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 libwin32utils.lib /nologo /out:"Debug\libdvdnav\libdvdnav.lib" +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=Create libdvdnav Install Files +PostBuild_Cmds=scripts\libdvdnav_install.bat Debug +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "libdvdnav - Win32 Release" +# Name "libdvdnav - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\src\vm\decoder.c +# End Source File +# Begin Source File + +SOURCE=..\src\dvdread\dvd_input.c +# End Source File +# Begin Source File + +SOURCE=..\src\dvdread\dvd_reader.c +# End Source File +# Begin Source File + +SOURCE=..\src\dvdread\dvd_udf.c +# End Source File +# Begin Source File + +SOURCE=..\src\dvdnav.c +# End Source File +# Begin Source File + +SOURCE=..\src\highlight.c +# End Source File +# Begin Source File + +SOURCE=..\src\dvdread\ifo_print.c +# End Source File +# Begin Source File + +SOURCE=..\src\dvdread\ifo_read.c +# End Source File +# Begin Source File + +SOURCE=..\src\dvdread\md5.c +# End Source File +# Begin Source File + +SOURCE=..\src\dvdread\nav_print.c +# End Source File +# Begin Source File + +SOURCE=..\src\dvdread\nav_read.c +# End Source File +# Begin Source File + +SOURCE=..\src\navigation.c +# End Source File +# Begin Source File + +SOURCE=..\src\read_cache.c +# End Source File +# Begin Source File + +SOURCE=..\src\remap.c +# End Source File +# Begin Source File + +SOURCE=..\src\searching.c +# End Source File +# Begin Source File + +SOURCE=..\src\settings.c +# End Source File +# Begin Source File + +SOURCE=..\src\vm\vm.c +# End Source File +# Begin Source File + +SOURCE=..\src\vm\vmcmd.c +# End Source File +# End Group +# Begin Group "DLL Defs" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\libdvdnav.def +# End Source File +# End Group +# End Target +# End Project diff --git a/libdvdread-embedded/msvc/libdvdnav.dsw b/libdvdread-embedded/msvc/libdvdnav.dsw new file mode 100644 index 0000000..8974efb --- /dev/null +++ b/libdvdread-embedded/msvc/libdvdnav.dsw @@ -0,0 +1,101 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "ifo_dump"=.\ifo_dump.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name libdvdnav + End Project Dependency +}}} + +############################################################################### + +Project: "libdvdcss"=.\libdvdcss.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "libdvdnav"=.\libdvdnav.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name libwin32utils + End Project Dependency +}}} + +############################################################################### + +Project: "libwin32utils"=.\libwin32utils.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "play_title"=.\play_title.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name libdvdnav + End Project Dependency +}}} + +############################################################################### + +Project: "title_info"=.\title_info.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name libdvdnav + End Project Dependency +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/libdvdread-embedded/msvc/libwin32utils.def b/libdvdread-embedded/msvc/libwin32utils.def new file mode 100644 index 0000000..02472a5 --- /dev/null +++ b/libdvdread-embedded/msvc/libwin32utils.def @@ -0,0 +1,77 @@ +;------------------------------------------------------------ +; LIBWIN32UTILS DLL DEFINITIONS FILE + +EXPORTS + +;------------------------------------------------------------ +; dirent exports + +opendir +closedir +readdir +rewinddir + +; +; Needed if !defined(_MSC_VER) && !defined(__cplusplus) +; +ptw32_push_cleanup +ptw32_pop_cleanup +; +; Not for use directly. Needed by macros in pthread.h +; to return internal SEH code. +; +ptw32_get_exception_services_code + +;------------------------------------------------------------ +; timer exports + +adler32 +compress +crc32 +deflate +deflateCopy +deflateEnd +deflateInit2_ +deflateInit_ +deflateParams +deflateReset +deflateSetDictionary +gzclose +gzdopen +gzerror +gzflush +gzopen +gzread +gzwrite +inflate +inflateEnd +inflateInit2_ +inflateInit_ +inflateReset +inflateSetDictionary +inflateSync +uncompress +zlibVersion +gzprintf +gzputc +gzgetc +gzseek +gzrewind +gztell +gzeof +gzsetparams +zError +inflateSyncPoint +get_crc_table +compress2 +gzputs +gzgets + +;------------------------------------------------------------ +; other exports +dlclose +dlsym +dlopen +dlerror + +optind diff --git a/libdvdread-embedded/msvc/libwin32utils.dsp b/libdvdread-embedded/msvc/libwin32utils.dsp new file mode 100644 index 0000000..712b24f --- /dev/null +++ b/libdvdread-embedded/msvc/libwin32utils.dsp @@ -0,0 +1,121 @@ +# Microsoft Developer Studio Project File - Name="libwin32utils" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=libwin32utils - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libwin32utils.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libwin32utils.mak" CFG="libwin32utils - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libwin32utils - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "libwin32utils - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libwin32utils - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release/libwin32utils" +# PROP Intermediate_Dir "Release/libwin32utils" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /machine:I386 +# ADD LINK32 winmm.lib /nologo /machine:I386 /out:"Release/libwin32utils.lib" +MTL=midl.exe +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_LIB" /D "LIBWIN32UTILS_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "include" /I "contrib/dirent" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_LIB" /D "LIBWIN32UTILS_EXPORTS" /D "__CLEANUP_C" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD LIB32 /out:"libwin32utils.lib" + +!ELSEIF "$(CFG)" == "libwin32utils - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug/libwin32utils" +# PROP Intermediate_Dir "Debug/libwin32utils" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /debug /machine:I386 /pdbtype:sept +# ADD LINK32 winmm.lib /nologo /debug /machine:I386 /out:"Debug/libwin32utils.lib" /pdbtype:sept +MTL=midl.exe +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_LIB" /D "LIBWIN32UTILS_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "include" /I "contrib/dirent" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_LIB" /D "LIBWIN32UTILS_EXPORTS" /D "__CLEANUP_C" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD LIB32 winmm.lib /out:"libwin32utils.lib" + +!ENDIF + +# Begin Target + +# Name "libwin32utils - Win32 Release" +# Name "libwin32utils - Win32 Debug" +# Begin Group "Source Files ( dirent )" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\contrib\dirent\dirent.c +# End Source File +# End Group +# +# Begin Group "DLL Defs" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\libwin32utils.def +# End Source File +# End Group +# Begin Group "Source Files ( other )" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\contrib\dlfcn.c +# End Source File +# End Group +# End Target +# End Project diff --git a/libdvdread-embedded/msvc/play_title.dsp b/libdvdread-embedded/msvc/play_title.dsp new file mode 100644 index 0000000..8a3efdf --- /dev/null +++ b/libdvdread-embedded/msvc/play_title.dsp @@ -0,0 +1,101 @@ +# Microsoft Developer Studio Project File - Name="play_title" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=play_title - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "play_title.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "play_title.mak" CFG="play_title - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "play_title - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "play_title - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "play_title - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "play_title - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "play_title___Win32_Debug" +# PROP BASE Intermediate_Dir "play_title___Win32_Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug\play_title" +# PROP Intermediate_Dir "Debug\play_title" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "include" /I "contrib/dirent" /I "../../libdvdcss" /I "install/include" /I "." /I ".." /I "../src" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug/bin/play_title.exe" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "play_title - Win32 Release" +# Name "play_title - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\src\play_title.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/libdvdread-embedded/msvc/scripts/libdvdcss_install.bat b/libdvdread-embedded/msvc/scripts/libdvdcss_install.bat new file mode 100755 index 0000000..84712b1 --- /dev/null +++ b/libdvdread-embedded/msvc/scripts/libdvdcss_install.bat @@ -0,0 +1,8 @@ + +ECHO mkdir dll ... +rmdir /s install\dll +mkdir install\dll + +ECHO libvdvcss dll ... +xcopy /Y %1\bin\libdvdcss.dll install\dll + diff --git a/libdvdread-embedded/msvc/scripts/libdvdnav_install.bat b/libdvdread-embedded/msvc/scripts/libdvdnav_install.bat new file mode 100755 index 0000000..f49f2f2 --- /dev/null +++ b/libdvdread-embedded/msvc/scripts/libdvdnav_install.bat @@ -0,0 +1,21 @@ + +ECHO mkdir install ... +rmdir /s install\include +rmdir /s install\lib +mkdir install\include\dvdnav +mkdir install\lib + +ECHO includes ... +xcopy /Y ..\src\dvdnav.h install\include\dvdnav +xcopy /Y ..\src\dvdnav_events.h install\include\dvdnav +xcopy /Y ..\src\dvd_types.h install\include\dvdnav +xcopy /Y ..\src\dvdread\dvd_reader.h install\include\dvdnav +xcopy /Y ..\src\dvdread\nav_read.h install\include\dvdnav +xcopy /Y ..\src\dvdread\ifo_read.h install\include\dvdnav +xcopy /Y ..\src\dvdread\nav_print.h install\include\dvdnav +xcopy /Y ..\src\dvdread\ifo_print.h install\include\dvdnav +xcopy /Y ..\src\dvdread\ifo_types.h install\include\dvdnav +xcopy /Y ..\src\dvdread\nav_types.h install\include\dvdnav + +ECHO lib ... +xcopy /Y %1\libdvdnav\libdvdnav.lib install\lib diff --git a/libdvdread-embedded/msvc/title_info.dsp b/libdvdread-embedded/msvc/title_info.dsp new file mode 100644 index 0000000..39d3768 --- /dev/null +++ b/libdvdread-embedded/msvc/title_info.dsp @@ -0,0 +1,101 @@ +# Microsoft Developer Studio Project File - Name="title_info" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=title_info - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "title_info.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "title_info.mak" CFG="title_info - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "title_info - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "title_info - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "title_info - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "title_info - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "title_info___Win32_Debug" +# PROP BASE Intermediate_Dir "title_info___Win32_Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "title_info___Win32_Debug" +# PROP Intermediate_Dir "title_info___Win32_Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "include" /I "contrib/dirent" /I "../../libdvdcss" /I "install/include" /I "." /I ".." /I "../src" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"Debug/title_info/title_info.pch" /YX /Fo"Debug/title_info/" /Fd"Debug/title_info/" /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug/bin/title_info.exe" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "title_info - Win32 Release" +# Name "title_info - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\src\title_info.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/libdvdread-embedded/src/bitreader.c b/libdvdread-embedded/src/bitreader.c new file mode 100644 index 0000000..f6a2183 --- /dev/null +++ b/libdvdread-embedded/src/bitreader.c @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2000, 2001, 2002, 2003 Håkan Hjort + * + * This file is part of libdvdread. + * + * libdvdread 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 of the License, or + * (at your option) any later version. + * + * libdvdread 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 libdvdread; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include +#include +#include +#include +#include + +#include "dvdread/bitreader.h" + +int dvdread_getbits_init(getbits_state_t *state, const uint8_t *start) { + if ((state == NULL) || (start == NULL)) return 0; + state->start = start; + state->bit_position = 0; + state->byte_position = 0; + return 1; +} + +/* Non-optimized getbits. */ +/* This can easily be optimized for particular platforms. */ +uint32_t dvdread_getbits(getbits_state_t *state, uint32_t number_of_bits) { + uint32_t result=0; + uint8_t byte=0; + if (number_of_bits > 32) { + printf("Number of bits > 32 in getbits\n"); + abort(); + } + + if ((state->bit_position) > 0) { /* Last getbits left us in the middle of a byte. */ + if (number_of_bits > (8-state->bit_position)) { /* this getbits will span 2 or more bytes. */ + byte = state->start[state->byte_position] << state->bit_position; + byte = byte >> (state->bit_position); + result = byte; + number_of_bits -= (8-state->bit_position); + state->bit_position = 0; + state->byte_position++; + } else { + byte = state->start[state->byte_position] << state->bit_position; + byte = byte >> (8 - number_of_bits); + result = byte; + state->bit_position += number_of_bits; /* Here it is impossible for bit_position > 8 */ + if (state->bit_position == 8) { + state->bit_position = 0; + state->byte_position++; + } + number_of_bits = 0; + } + } + if ((state->bit_position) == 0) { + while (number_of_bits > 7) { + result = (result << 8) + state->start[state->byte_position]; + state->byte_position++; + number_of_bits -= 8; + } + if (number_of_bits > 0) { /* number_of_bits < 8 */ + byte = state->start[state->byte_position] << state->bit_position; + state->bit_position += number_of_bits; /* Here it is impossible for bit_position > 7 */ + byte = byte >> (8 - number_of_bits); + result = (result << number_of_bits) + byte; + number_of_bits = 0; + } + } + + return result; +} + +#if 0 /* TODO: optimized versions not yet used */ + +/* WARNING: This function can only be used on a byte boundary. + No checks are made that we are in fact on a byte boundary. + */ +uint16_t dvdread_get16bits(getbits_state_t *state) { + uint16_t result; + state->byte_position++; + result = (state->byte << 8) + state->start[state->byte_position++]; + state->byte = state->start[state->byte_position]; + return result; +} + +/* WARNING: This function can only be used on a byte boundary. + No checks are made that we are in fact on a byte boundary. + */ +uint32_t dvdread_get32bits(getbits_state_t *state) { + uint32_t result; + state->byte_position++; + result = (state->byte << 8) + state->start[state->byte_position++]; + result = (result << 8) + state->start[state->byte_position++]; + result = (result << 8) + state->start[state->byte_position++]; + state->byte = state->start[state->byte_position]; + return result; +} + +#endif + +#ifdef BITREADER_TESTS + +int main() +{ + uint8_t buff[2] = { + 0x6E, 0xC2 + // 0b 01101110 11000010 + }; + getbits_state_t state; + dvdread_getbits_init(&state, buff); + + uint32_t bits = dvdread_getbits(&state, 3); + assert(bits == 3); + + bits = dvdread_getbits(&state, 3); + assert(bits == 3); + + bits = dvdread_getbits(&state, 4); + assert(bits == 11); + + bits = dvdread_getbits(&state, 6); + assert(bits == 2); + + dvdread_getbits_init(&state, buff); + bits = dvdread_getbits(&state, 10); + assert(bits == 443); + + bits = dvdread_getbits(&state, 6); + assert(bits == 2); + + dvdread_getbits_init(&state, buff); + bits = dvdread_getbits(&state, 16); + assert(bits == 28354); + + buff[0] = buff[1] = 0xFF; + dvdread_getbits_init(&state, buff); + bits = dvdread_getbits(&state, 16); + assert(bits == 0xFFFF); + + uint8_t large[5] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + dvdread_getbits_init(&state, large); + bits = dvdread_getbits(&state, 8); + assert(bits == 0xFF); + bits = dvdread_getbits(&state, 32); + assert(bits == 0xFFFFFFFF); + + return 0; +} + +#endif diff --git a/libdvdread-embedded/src/bswap.h b/libdvdread-embedded/src/bswap.h new file mode 100644 index 0000000..d3b2383 --- /dev/null +++ b/libdvdread-embedded/src/bswap.h @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2000, 2001 Billy Biggs , + * Håkan Hjort + * + * This file is part of libdvdread. + * + * libdvdread 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 of the License, or + * (at your option) any later version. + * + * libdvdread 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 libdvdread; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef LIBDVDREAD_BSWAP_H +#define LIBDVDREAD_BSWAP_H + +#include + +#if defined(WORDS_BIGENDIAN) +/* All bigendian systems are fine, just ignore the swaps. */ +#define B2N_16(x) (void)(x) +#define B2N_32(x) (void)(x) +#define B2N_64(x) (void)(x) + +#else + +/* For __FreeBSD_version */ +#if defined(HAVE_SYS_PARAM_H) +#include +#endif + +#if defined(__linux__) || defined(__GLIBC__) +#include +#define B2N_16(x) x = bswap_16(x) +#define B2N_32(x) x = bswap_32(x) +#define B2N_64(x) x = bswap_64(x) + +#elif defined(__APPLE__) +#include +#define B2N_16(x) x = OSSwapBigToHostInt16(x) +#define B2N_32(x) x = OSSwapBigToHostInt32(x) +#define B2N_64(x) x = OSSwapBigToHostInt64(x) + +#elif defined(__NetBSD__) +#include +#define B2N_16(x) BE16TOH(x) +#define B2N_32(x) BE32TOH(x) +#define B2N_64(x) BE64TOH(x) + +#elif defined(__OpenBSD__) +#include +#define B2N_16(x) x = swap16(x) +#define B2N_32(x) x = swap32(x) +#define B2N_64(x) x = swap64(x) + +#elif defined(__FreeBSD__) && __FreeBSD_version >= 470000 +#include +#define B2N_16(x) x = be16toh(x) +#define B2N_32(x) x = be32toh(x) +#define B2N_64(x) x = be64toh(x) + +#elif defined(__QNXNTO__) +#include +#define B2N_16(x) x = ENDIAN_RET16(x) +#define B2N_32(x) x = ENDIAN_RET32(x) +#define B2N_64(x) x = ENDIAN_RET64(x) + +#elif defined(__DragonFly__) +#include +#define B2N_16(x) x = bswap16(x) +#define B2N_32(x) x = bswap32(x) +#define B2N_64(x) x = bswap64(x) + +/* This is a slow but portable implementation, it has multiple evaluation + * problems so beware. + * Old FreeBSD's and Solaris don't have or any other such + * functionality! + */ + +#elif defined(__FreeBSD__) || defined(__sun) || defined(__bsdi__) || defined(_WIN32) || defined(__CYGWIN__) || defined(__BEOS__) || defined(__OS2__) +#define B2N_16(x) \ + x = ((((x) & 0xff00) >> 8) | \ + (((x) & 0x00ff) << 8)) +#define B2N_32(x) \ + x = ((((x) & 0xff000000) >> 24) | \ + (((x) & 0x00ff0000) >> 8) | \ + (((x) & 0x0000ff00) << 8) | \ + (((x) & 0x000000ff) << 24)) +#define B2N_64(x) \ + x = ((((x) & 0xff00000000000000ULL) >> 56) | \ + (((x) & 0x00ff000000000000ULL) >> 40) | \ + (((x) & 0x0000ff0000000000ULL) >> 24) | \ + (((x) & 0x000000ff00000000ULL) >> 8) | \ + (((x) & 0x00000000ff000000ULL) << 8) | \ + (((x) & 0x0000000000ff0000ULL) << 24) | \ + (((x) & 0x000000000000ff00ULL) << 40) | \ + (((x) & 0x00000000000000ffULL) << 56)) + +#else + +/* If there isn't a header provided with your system with this functionality + * add the relevant || define( ) to the portable implementation above. + */ +#error "You need to add endian swap macros for your system" + +#endif + +#endif /* WORDS_BIGENDIAN */ + +#endif /* LIBDVDREAD_BSWAP_H */ diff --git a/libdvdread-embedded/src/dvd_input.c b/libdvdread-embedded/src/dvd_input.c new file mode 100644 index 0000000..26b6928 --- /dev/null +++ b/libdvdread-embedded/src/dvd_input.c @@ -0,0 +1,483 @@ +/* + * Copyright (C) 2002 Samuel Hocevar , + * Håkan Hjort + * + * This file is part of libdvdread. + * + * libdvdread 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 of the License, or + * (at your option) any later version. + * + * libdvdread 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 libdvdread; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" /* Required for HAVE_DVDCSS_DVDCSS_H */ +#include /* fprintf */ +#include /* free */ +#include /* open */ +#include /* lseek */ +#include /* strerror */ +#include + +#ifdef _WIN32 +#include +#include "../msvc/contrib/win32_cs.h" +#endif + +#include "dvdread/dvd_reader.h" /* DVD_VIDEO_LB_LEN */ +#include "dvdread_internal.h" +#include "dvd_input.h" +#include "logger.h" + + +/* The function pointers that is the exported interface of this file. */ +dvd_input_t (*dvdinput_open) (void *, dvd_logger_cb *, + const char *,dvd_reader_stream_cb *); +int (*dvdinput_close) (dvd_input_t); +int (*dvdinput_seek) (dvd_input_t, int); +int (*dvdinput_title) (dvd_input_t, int); +int (*dvdinput_read) (dvd_input_t, void *, int, int); + +#ifdef HAVE_DVDCSS_DVDCSS_H +/* linking to libdvdcss */ +# include +# define DVDcss_open_stream(a, b) \ + dvdcss_open_stream((void*)(a), (dvdcss_stream_cb*)(b)) +# define DVDcss_open(a) dvdcss_open((char*)(a)) +# define DVDcss_close dvdcss_close +# define DVDcss_seek dvdcss_seek +# define DVDcss_read dvdcss_read +#else + +/* dlopening libdvdcss */ +# if defined(HAVE_DLFCN_H) && !defined(USING_BUILTIN_DLFCN) +# include +# else +# if defined(_WIN32) +/* Only needed on MINGW at the moment */ +# include "../msvc/contrib/dlfcn.c" +# endif +# endif + +typedef struct dvdcss_s *dvdcss_t; +typedef struct dvdcss_stream_cb dvdcss_stream_cb; +static dvdcss_t (*DVDcss_open_stream) (void *, dvdcss_stream_cb *); +static dvdcss_t (*DVDcss_open) (const char *); +static int (*DVDcss_close) (dvdcss_t); +static int (*DVDcss_seek) (dvdcss_t, int, int); +static int (*DVDcss_read) (dvdcss_t, void *, int, int); +#define DVDCSS_SEEK_KEY (1 << 1) +#endif + +#ifdef _WIN32 +static int open_win32(const char *path, int flags) +{ + wchar_t *wpath; + int fd; + + wpath = _utf8_to_wchar(path); + if (!wpath) { + return -1; + } + fd = _wopen(wpath, flags); + free(wpath); + return fd; +} +#endif + +/* The DVDinput handle, add stuff here for new input methods. + * NOTE: All members of this structure must be initialized in dvd_input_New + */ +struct dvd_input_s { + /* libdvdcss handle */ + dvdcss_t dvdcss; + /* */ + void *priv; + dvd_logger_cb *logcb; + off_t ipos; + + /* dummy file input */ + int fd; + /* stream input */ + dvd_reader_stream_cb *stream_cb; +}; + +static dvd_input_t dvd_input_New(void *priv, dvd_logger_cb *logcb) +{ + dvd_input_t dev = calloc(1, sizeof(*dev)); + if(dev) + { + dev->priv = priv; + dev->logcb = logcb; + dev->ipos = 0; + + /* Initialize all inputs to safe defaults */ + dev->dvdcss = NULL; + dev->fd = -1; + dev->stream_cb = NULL; + } + return dev; +} + +/** + * initialize and open a DVD (device or file or stream_cb) + */ +static dvd_input_t css_open(void *priv, dvd_logger_cb *logcb, + const char *target, + dvd_reader_stream_cb *stream_cb) +{ + dvd_input_t dev; + + /* Allocate the handle structure */ + dev = dvd_input_New(priv, logcb); + if(dev == NULL) { + DVDReadLog(priv, logcb, DVD_LOGGER_LEVEL_ERROR, + "Could not allocate memory."); + return NULL; + } + + /* Really open it with libdvdcss */ + if(target) + dev->dvdcss = DVDcss_open(target); + else if(priv && stream_cb) { +#ifdef HAVE_DVDCSS_DVDCSS_H + dev->dvdcss = DVDcss_open_stream(priv, (dvdcss_stream_cb *)stream_cb); +#else + dev->dvdcss = DVDcss_open_stream ? + DVDcss_open_stream(priv, (dvdcss_stream_cb *)stream_cb) : + NULL; +#endif + } + if(dev->dvdcss == NULL) { + DVDReadLog(priv, logcb, DVD_LOGGER_LEVEL_ERROR, + "Could not open %s with libdvdcss.", target); + free(dev); + return NULL; + } + + return dev; +} + +/** + * seek into the device. + */ +static int css_seek(dvd_input_t dev, int blocks) +{ + /* DVDINPUT_NOFLAGS should match the DVDCSS_NOFLAGS value. */ + return DVDcss_seek(dev->dvdcss, blocks, DVDINPUT_NOFLAGS); +} + +/** + * set the block for the beginning of a new title (key). + */ +static int css_title(dvd_input_t dev, int block) +{ + return DVDcss_seek(dev->dvdcss, block, DVDCSS_SEEK_KEY); +} + +/** + * read data from the device. + */ +static int css_read(dvd_input_t dev, void *buffer, int blocks, int flags) +{ + return DVDcss_read(dev->dvdcss, buffer, blocks, flags); +} + +/** + * close the DVD device and clean up the library. + */ +static int css_close(dvd_input_t dev) +{ + int ret; + + ret = DVDcss_close(dev->dvdcss); + + free(dev); + + return ret; +} + +/** + * initialize and open a DVD device or file. + */ +static dvd_input_t file_open(void *priv, dvd_logger_cb *logcb, + const char *target, + dvd_reader_stream_cb *stream_cb) +{ + dvd_input_t dev; + + /* Allocate the library structure */ + dev = dvd_input_New(priv, logcb); + if(dev == NULL) { + DVDReadLog(priv, logcb, DVD_LOGGER_LEVEL_ERROR, + "Could not allocate memory."); + return NULL; + } + + /* Initialize with stream callback if it is specified */ + if (stream_cb) { + if (!stream_cb->pf_read || !stream_cb->pf_seek) { + DVDReadLog(priv, logcb, DVD_LOGGER_LEVEL_ERROR, + "Stream callback provided but lacks of pf_read or pf_seek methods."); + free(dev); + return NULL; + } + dev->stream_cb = stream_cb; + return dev; + } + + /* Open the device */ + if(target == NULL) { + free(dev); + return NULL; + } +#if defined(_WIN32) + dev->fd = open_win32(target, O_RDONLY | O_BINARY); +#elif defined(__OS2__) + dev->fd = open(target, O_RDONLY | O_BINARY); +#else + dev->fd = open(target, O_RDONLY); +#endif + if(dev->fd < 0) { + char buf[256]; +#if defined(HAVE_STRERROR_R) && defined(HAVE_DECL_STRERROR_R) + #ifdef STRERROR_R_CHAR_P + *buf=0; + if(strerror_r(errno, buf, 256) == NULL) + *buf=0; + #else + if(strerror_r(errno, buf, 256) != 0) + *buf=0; + #endif +#else + #if defined(HAVE_STRERR_S) + if(strerror_s(buf, 256, errno) != 0) + *buf=0; + #else + *buf=0; + #endif +#endif + DVDReadLog(priv, logcb, DVD_LOGGER_LEVEL_ERROR, + "Could not open input: %s", buf); + free(dev); + return NULL; + } + + return dev; +} + +/** + * seek into the device. + */ +static int file_seek(dvd_input_t dev, int blocks) +{ + off_t pos = -1; + + if(dev->ipos == blocks) + { + /* We are already in position */ + return blocks; + } + + if (dev->stream_cb) { + /* Returns 0 on successful completion and -1 on error */ + pos = dev->stream_cb->pf_seek(dev->priv, (off_t)blocks * (off_t)DVD_VIDEO_LB_LEN); + + if (!pos) { + dev->ipos = blocks; + } + } else { + /* Returns position as the number of bytes from beginning of file + * or -1 on error + */ + pos = lseek(dev->fd, (off_t)blocks * (off_t)DVD_VIDEO_LB_LEN, SEEK_SET); + + if (pos >= 0) { + dev->ipos = pos / DVD_VIDEO_LB_LEN; + } + } + + if(pos < 0) { + return pos; + } + + /* assert pos % DVD_VIDEO_LB_LEN == 0 */ + return (int) dev->ipos; +} + +/** + * set the block for the beginning of a new title (key). + */ +static int file_title(dvd_input_t dev UNUSED, int block UNUSED) +{ + return -1; +} + +/** + * read data from the device. + */ +static int file_read(dvd_input_t dev, void *buffer, int blocks, + int flags UNUSED) +{ + size_t len, bytes, blocks_read; + + len = (size_t)blocks * DVD_VIDEO_LB_LEN; + bytes = 0; + blocks_read = 0; + + while(len > 0) { + ssize_t ret = -1; + + /* Perform read based on the input type */ + if (dev->stream_cb) { + /* Returns the number of bytes read or -1 on error */ + ret = dev->stream_cb->pf_read(dev->priv, ((char*)buffer) + bytes, len); + } else { + /* Returns the number of bytes read or -1 on error */ + ret = read(dev->fd, ((char*)buffer) + bytes, len); + } + + if(ret < 0) { + /* One of the reads failed, too bad. We won't even bother + * returning the reads that went OK, and as in the POSIX spec + * the file position is left unspecified after a failure. */ + dev->ipos = -1; + return ret; + } + + if(ret == 0) { + /* Nothing more to read. Return all of the whole blocks, if any. + * Adjust the file position back to the previous block boundary. */ + ret = file_seek(dev, dev->ipos + blocks_read); + if(ret < 0) + return ret; + + return (int) blocks_read; + } + + len -= ret; + bytes += ret; + blocks_read = bytes / DVD_VIDEO_LB_LEN; + } + + dev->ipos += blocks_read; + return blocks; +} + +/** + * close the DVD device and clean up. + */ +static int file_close(dvd_input_t dev) +{ + int ret = 0; + + /* close file if it was open */ + + if (dev->fd >= 0) { + ret = close(dev->fd); + } + + free(dev); + + return ret; +} + +/** + * Setup read functions with either libdvdcss or minimal DVD access. + */ +int dvdinput_setup(void *priv, dvd_logger_cb *logcb) +{ + void *dvdcss_library = NULL; + +#ifdef HAVE_DVDCSS_DVDCSS_H + /* linking to libdvdcss */ + dvdcss_library = &dvdcss_library; /* Give it some value != NULL */ + +#else + /* dlopening libdvdcss */ + +#ifdef __APPLE__ + #define CSS_LIB "libdvdcss.2.dylib" +#elif defined(_WIN32) + #define CSS_LIB "libdvdcss-2.dll" +#elif defined(__OS2__) + #define CSS_LIB "dvdcss2.dll" +#elif defined(__OpenBSD__) + #define CSS_LIB "libdvdcss.so" +#else + #define CSS_LIB "libdvdcss.so.2" +#endif + dvdcss_library = dlopen(CSS_LIB, RTLD_LAZY); + + if(dvdcss_library != NULL) { +#ifdef __OS2__ +#define U_S "_" +#else +#define U_S +#endif + DVDcss_open_stream = (dvdcss_t (*)(void *, dvdcss_stream_cb *)) + dlsym(dvdcss_library, U_S "dvdcss_open_stream"); + DVDcss_open = (dvdcss_t (*)(const char*)) + dlsym(dvdcss_library, U_S "dvdcss_open"); + DVDcss_close = (int (*)(dvdcss_t)) + dlsym(dvdcss_library, U_S "dvdcss_close"); + DVDcss_seek = (int (*)(dvdcss_t, int, int)) + dlsym(dvdcss_library, U_S "dvdcss_seek"); + DVDcss_read = (int (*)(dvdcss_t, void*, int, int)) + dlsym(dvdcss_library, U_S "dvdcss_read"); + + if(dlsym(dvdcss_library, U_S "dvdcss_crack")) { + DVDReadLog(priv, logcb, DVD_LOGGER_LEVEL_ERROR, + "Old (pre-0.0.2) version of libdvdcss found. " + "libdvdread: You should get the latest version from " + "http://www.videolan.org/" ); + dlclose(dvdcss_library); + dvdcss_library = NULL; + } else if(!DVDcss_open || !DVDcss_close || !DVDcss_seek + || !DVDcss_read) { + DVDReadLog(priv, logcb, DVD_LOGGER_LEVEL_ERROR, + "Missing symbols in %s, " + "this shouldn't happen !", CSS_LIB); + dlclose(dvdcss_library); + dvdcss_library = NULL; + } + } +#endif /* HAVE_DVDCSS_DVDCSS_H */ + + if(dvdcss_library != NULL) { + /* + char *psz_method = getenv( "DVDCSS_METHOD" ); + char *psz_verbose = getenv( "DVDCSS_VERBOSE" ); + fprintf(stderr, "DVDCSS_METHOD %s\n", psz_method); + fprintf(stderr, "DVDCSS_VERBOSE %s\n", psz_verbose); + */ + + /* libdvdcss wrapper functions */ + dvdinput_open = css_open; + dvdinput_close = css_close; + dvdinput_seek = css_seek; + dvdinput_title = css_title; + dvdinput_read = css_read; + return 1; + + } else { + DVDReadLog(priv, logcb, DVD_LOGGER_LEVEL_WARN, + "Encrypted DVD support unavailable."); + + /* libdvdcss replacement functions */ + dvdinput_open = file_open; + dvdinput_close = file_close; + dvdinput_seek = file_seek; + dvdinput_title = file_title; + dvdinput_read = file_read; + return 0; + } +} diff --git a/libdvdread-embedded/src/dvd_input.h b/libdvdread-embedded/src/dvd_input.h new file mode 100644 index 0000000..470cfa4 --- /dev/null +++ b/libdvdread-embedded/src/dvd_input.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2001, 2002 Samuel Hocevar , + * Håkan Hjort + * + * This file is part of libdvdread. + * + * libdvdread 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 of the License, or + * (at your option) any later version. + * + * libdvdread 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 libdvdread; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef LIBDVDREAD_DVD_INPUT_H +#define LIBDVDREAD_DVD_INPUT_H + +/** + * Defines and flags. Make sure they fit the libdvdcss API! + */ +#define DVDINPUT_NOFLAGS 0 + +#define DVDINPUT_READ_DECRYPT (1 << 0) + +typedef struct dvd_input_s *dvd_input_t; + +#if defined( __MINGW32__ ) +# undef lseek +# define lseek _lseeki64 +# undef off_t +# define off_t off64_t +# undef stat +# define stat _stati64 +# undef fstat +# define fstat _fstati64 +# undef wstat +# define wstat _wstati64 +#endif + +#ifdef __ANDROID__ +# undef lseek +# define lseek lseek64 +# undef off_t +# define off_t off64_t +#endif + +/** + * Function pointers that will be filled in by the input implementation. + * These functions provide the main API. + */ +extern dvd_input_t (*dvdinput_open) (void *, dvd_logger_cb *, + const char *, + dvd_reader_stream_cb *); +extern int (*dvdinput_close) (dvd_input_t); +extern int (*dvdinput_seek) (dvd_input_t, int); +extern int (*dvdinput_title) (dvd_input_t, int); +extern int (*dvdinput_read) (dvd_input_t, void *, int, int); + +/** + * Setup function accessed by dvd_reader.c. Returns 1 if there is CSS support. + */ +int dvdinput_setup(void *, dvd_logger_cb *); + +#endif /* LIBDVDREAD_DVD_INPUT_H */ diff --git a/libdvdread-embedded/src/dvd_reader.c b/libdvdread-embedded/src/dvd_reader.c new file mode 100644 index 0000000..c4d9641 --- /dev/null +++ b/libdvdread-embedded/src/dvd_reader.c @@ -0,0 +1,1690 @@ +/* + * Copyright (C) 2001-2004 Billy Biggs , + * Håkan Hjort , + * Björn Englund + * + * This file is part of libdvdread. + * + * libdvdread 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 of the License, or + * (at your option) any later version. + * + * libdvdread 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 libdvdread; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include /* off_t */ +#include /* stat */ +#include /* For the timing of dvdcss_title crack. */ +#include /* open */ +#include /* free */ +#include /* fprintf */ +#include /* errno, EIN* */ +#include /* memcpy, strlen */ +#include /* pclose */ +#include /* PATH_MAX */ +#include /* opendir, readdir */ +#include /* isalpha */ + +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__bsdi__) || defined(__APPLE__) +# define SYS_BSD 1 +#endif + +#if defined(__sun) +# include +#elif defined(__APPLE__) +# include +# include +# include +#elif defined(SYS_BSD) +# include +#elif defined(__linux__) +# include +# include +#endif + +#include "dvdread/dvd_udf.h" +#include "dvdread/dvd_reader.h" +#include "dvd_input.h" +#include "dvdread_internal.h" +#include "md5.h" +#include "dvdread/ifo_read.h" + +#if defined(_WIN32) +# include +# include "msvc/contrib/win32_cs.h" +#endif + +/* misc win32 helpers */ + +#ifdef _WIN32 +# ifndef HAVE_GETTIMEOFDAY + /* replacement gettimeofday implementation */ +# include +static inline int _private_gettimeofday( struct timeval *tv, void *tz ) +{ + struct timeb t; + ftime( &t ); + tv->tv_sec = t.time; + tv->tv_usec = t.millitm * 1000; + return 0; +} +# define gettimeofday(TV, TZ) _private_gettimeofday((TV), (TZ)) +# endif +#endif /* _WIN32 */ + +/* Compat wrapper for stat() */ + +#if defined(_WIN32) +/* can't re-define stat (used in both function name and struct name) */ +typedef struct _stat64 dvdstat_t; +static inline int dvdstat(const char *path, dvdstat_t *st) +{ + wchar_t *wpath, *it; + int ret; + + wpath = _utf8_to_wchar(path); + if (!wpath) { + return -1; + } + + /* need to strip possible trailing \\ */ + for (it = wpath; *it; it++) + if ((*it == '\\' || *it == '/') && *(it+1) == 0) + *it = 0; + + ret = _wstat64(wpath, st); + free(wpath); + return ret; +} +#else +typedef struct stat dvdstat_t; +static inline int dvdstat(const char *file, dvdstat_t *st) { + return stat(file, st); +} +#endif + +#if defined(_WIN32) +/* UTF-8 aware version of opendir()/readdir() */ + +#include + +typedef struct { + intptr_t handle; + struct _wfinddata_t went; + struct dirent ent; +} win32_dir_t; + +win32_dir_t *win32_opendir(const char *path) +{ + char *filespec; + wchar_t *wfilespec; + win32_dir_t *d; + + d = calloc(1, sizeof(*d)); + if (!d) + return NULL; + + filespec = malloc(strlen(path) + 3); + if (!filespec) { + goto fail; + } + sprintf(filespec, "%s\\*", path); + + wfilespec = _utf8_to_wchar(filespec); + free(filespec); + if (!wfilespec) { + goto fail; + } + + d->handle = _wfindfirst(wfilespec, &d->went); + free(wfilespec); + if (d->handle != -1) { + return d; + } + + fail: + free(d); + return NULL; +} + +static struct dirent *win32_readdir(win32_dir_t *dir) +{ + if (dir->went.name[0]) { + if (!WideCharToMultiByte(CP_UTF8, 0, dir->went.name, -1, dir->ent.d_name, sizeof(dir->ent.d_name), NULL, NULL)) + dir->ent.d_name[0] = 0; /* allow reading next */ + dir->went.name[0] = 0; + _wfindnext(dir->handle, &dir->went); + return &dir->ent; + } + + return NULL; +} + +static void win32_closedir(win32_dir_t *dir) +{ + _findclose(dir->handle); + free(dir); +} + +#define DIR win32_dir_t +#define opendir win32_opendir +#define readdir win32_readdir +#define closedir win32_closedir + +#endif /* _WIN32 */ + +#define DEFAULT_UDF_CACHE_LEVEL 1 + +struct dvd_reader_device_s { + /* Basic information. */ + int isImageFile; + + /* Hack for keeping track of the css status. + * 0: no css, 1: perhaps (need init of keys), 2: have done init */ + int css_state; + int css_title; /* Last title that we have called dvdinpute_title for. */ + + /* Information required for an image file. */ + dvd_input_t dev; + + /* Information required for a directory path drive. */ + char *path_root; + + /* Filesystem cache */ + int udfcache_level; /* 0 - turned off, 1 - on */ + void *udfcache; +}; + +#define TITLES_MAX 9 + +struct dvd_file_s { + /* Basic information. */ + dvd_reader_t *ctx; + + /* Hack for selecting the right css title. */ + int css_title; + + /* Information required for an image file. */ + uint32_t lb_start; + uint32_t seek_pos; + + /* Information required for a directory path drive. */ + size_t title_sizes[ TITLES_MAX ]; + dvd_input_t title_devs[ TITLES_MAX ]; + + /* Calculated at open-time, size in blocks. */ + ssize_t filesize; + + /* Cache of the dvd_file. If not NULL, the cache corresponds to the whole + * dvd_file. Used only for IFO and BUP. */ + unsigned char *cache; +}; + +/** + * Set the level of caching on udf + * level = 0 (no caching) + * level = 1 (caching filesystem info) + */ +int DVDUDFCacheLevel(dvd_reader_t *reader, int level) +{ + dvd_reader_device_t *dev = reader->rd; + + if(level > 0) { + level = 1; + } else if(level < 0) { + return dev->udfcache_level; + } + + dev->udfcache_level = level; + + return level; +} + +void *GetUDFCacheHandle(dvd_reader_t *reader) +{ + dvd_reader_device_t *dev = reader->rd; + + return dev->udfcache; +} + +void SetUDFCacheHandle(dvd_reader_t *reader, void *cache) +{ + dvd_reader_device_t *dev = reader->rd; + + dev->udfcache = cache; +} + + + +/* Loop over all titles and call dvdcss_title to crack the keys. */ +static int initAllCSSKeys( dvd_reader_t *ctx ) +{ + dvd_reader_device_t *dvd = ctx->rd; + struct timeval all_s, all_e; + struct timeval t_s, t_e; + char filename[ MAX_UDF_FILE_NAME_LEN ]; + uint32_t start, len; + int title; + + const char *nokeys_str = getenv("DVDREAD_NOKEYS"); + if(nokeys_str != NULL) + return 0; + + Log2(ctx,"Attempting to retrieve all CSS keys" ); + Log2(ctx,"This can take a _long_ time, please be patient" ); + gettimeofday(&all_s, NULL); + + for( title = 0; title < 100; title++ ) { + gettimeofday( &t_s, NULL ); + if( title == 0 ) { + strcpy( filename, "/VIDEO_TS/VIDEO_TS.VOB" ); + } else { + sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, 0 ); + } + start = UDFFindFile( ctx, filename, &len ); + if( start != 0 && len != 0 ) { + /* Perform CSS key cracking for this title. */ + Log3(ctx,"Get key for %s at 0x%08x",filename, start ); + if( dvdinput_title( dvd->dev, (int)start ) < 0 ) { + Log1(ctx,"Error cracking CSS key for %s (0x%08x)", filename, start); + } + gettimeofday( &t_e, NULL ); + Log3(ctx,"Elapsed time %ld", (long int) t_e.tv_sec - t_s.tv_sec ); + } + + if( title == 0 ) continue; + + gettimeofday( &t_s, NULL ); + sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, 1 ); + start = UDFFindFile( ctx, filename, &len ); + if( start == 0 || len == 0 ) break; + + /* Perform CSS key cracking for this title. */ + Log3(ctx,"Get key for %s at 0x%08x",filename, start ); + if( dvdinput_title( dvd->dev, (int)start ) < 0 ) { + Log1(ctx,"Error cracking CSS key for %s (0x%08x)", filename, start); + } + gettimeofday( &t_e, NULL ); + Log3(ctx,"Elapsed time %ld", (long int) t_e.tv_sec - t_s.tv_sec ); + } + title--; + + Log3(ctx,"Found %d VTS's", title ); + gettimeofday(&all_e, NULL); + Log3(ctx,"Elapsed time %ld", (long int) all_e.tv_sec - all_s.tv_sec ); + + return 0; +} + + + +/** + * Open a DVD image or block device file or use stream_cb functions. + */ +static dvd_reader_device_t *DVDOpenImageFile( dvd_reader_t *ctx, + const char *location, + dvd_reader_stream_cb *stream_cb, + int have_css ) +{ + dvd_reader_device_t *dvd; + dvd_input_t dev; + + dev = dvdinput_open( ctx->priv, &ctx->logcb, location, stream_cb ); + if( !dev ) { + Log0(ctx,"Can't open %s for reading", location ); + return NULL; + } + + dvd = calloc( 1, sizeof( dvd_reader_device_t ) ); + if( !dvd ) { + dvdinput_close(dev); + return NULL; + } + dvd->isImageFile = 1; + dvd->dev = dev; + + dvd->udfcache_level = DEFAULT_UDF_CACHE_LEVEL; + + if( have_css ) { + /* Only if DVDCSS_METHOD = title, a bit if it's disc or if + * DVDCSS_METHOD = key but region mismatch. Unfortunately we + * don't have that information. */ + + dvd->css_state = 1; /* Need key init. */ + } + + return dvd; +} + +static dvd_reader_device_t *DVDOpenPath( const char *path_root ) +{ + dvd_reader_device_t *dvd; + + dvd = calloc( 1, sizeof( dvd_reader_device_t ) ); + if( !dvd ) return NULL; + dvd->path_root = strdup( path_root ); + if(!dvd->path_root) { + free(dvd); + return NULL; + } + dvd->udfcache_level = DEFAULT_UDF_CACHE_LEVEL; + + return dvd; +} + +#if defined(__sun) +/* /dev/rdsk/c0t6d0s0 (link to /devices/...) + /vol/dev/rdsk/c0t6d0/?? + /vol/rdsk/ */ +static char *sun_block2char( const char *path ) +{ + char *new_path; + + /* Must contain "/dsk/" */ + if( !strstr( path, "/dsk/" ) ) return (char *) strdup( path ); + + /* Replace "/dsk/" with "/rdsk/" */ + new_path = malloc( strlen(path) + 2 ); + if(!new_path) return NULL; + strcpy( new_path, path ); + strcpy( strstr( new_path, "/dsk/" ), "" ); + strcat( new_path, "/rdsk/" ); + strcat( new_path, strstr( path, "/dsk/" ) + strlen( "/dsk/" ) ); + + return new_path; +} +#endif + +#if defined(SYS_BSD) +/* FreeBSD /dev/(r)(a)cd0c (a is for atapi), recommended to _not_ use r + update: FreeBSD and DragonFly no longer uses the prefix so don't add it. + OpenBSD /dev/rcd0c, it needs to be the raw device + NetBSD /dev/rcd0[d|c|..] d for x86, c (for non x86), perhaps others + Darwin /dev/rdisk0, it needs to be the raw device + BSD/OS /dev/sr0c (if not mounted) or /dev/rsr0c ('c' any letter will do) + returns a string allocated with strdup. It should be freed when no longer + used. */ +static char *bsd_block2char( const char *path ) +{ +#if defined(__FreeBSD__) || defined(__DragonFly__) + return (char *) strdup( path ); +#else + char *new_path; + + /* If it doesn't start with "/dev/" or does start with "/dev/r" exit */ + if( strncmp( path, "/dev/", 5 ) || !strncmp( path, "/dev/r", 6 ) ) + return (char *) strdup( path ); + + /* Replace "/dev/" with "/dev/r" */ + new_path = malloc( strlen(path) + 2 ); + if(!new_path) return NULL; + strcpy( new_path, "/dev/r" ); + strcat( new_path, path + strlen( "/dev/" ) ); + + return new_path; +#endif /* __FreeBSD__ || __DragonFly__ */ +} +#endif + +static dvd_reader_t *DVDOpenCommon( void *priv, + const dvd_logger_cb *logcb, + const char *ppath, + dvd_reader_stream_cb *stream_cb ) +{ + dvdstat_t fileinfo; + int ret, have_css, cdir = -1; + char *dev_name = NULL; + char *path = NULL, *new_path = NULL, *path_copy = NULL; + dvd_reader_t *ctx = calloc(1, sizeof(*ctx)); + if(!ctx) + return NULL; + + ctx->priv = priv; + if(logcb) + ctx->logcb = *logcb; + +#if defined(_WIN32) || defined(__OS2__) + int len; +#endif + + /* Try to open DVD using stream_cb functions */ + if( priv != NULL && stream_cb != NULL ) + { + have_css = dvdinput_setup( ctx->priv, &ctx->logcb ); + ctx->rd = DVDOpenImageFile( ctx, NULL, stream_cb, have_css ); + if(!ctx->rd) + { + free(ctx); + return NULL; + } + return ctx; + } + + if( ppath == NULL ) + goto DVDOpen_error; + + path = strdup(ppath); + if( path == NULL ) + goto DVDOpen_error; + + /* Try to open libdvdcss or fall back to standard functions */ + have_css = dvdinput_setup( ctx->priv, &ctx->logcb ); + +#if defined(_WIN32) || defined(__OS2__) + /* Strip off the trailing \ if it is not a drive */ + len = strlen(path); + if ((len > 1) && + (path[len - 1] == '\\') && + (path[len - 2] != ':')) + { + path[len-1] = '\0'; + } +#endif + + ret = dvdstat( path, &fileinfo ); + + if( ret < 0 ) { + + /* maybe "host:port" url? try opening it with acCeSS library */ + if( strchr(path,':') ) { + ctx->rd = DVDOpenImageFile( ctx, path, NULL, have_css ); + free(path); + if(!ctx->rd) + { + free(ctx); + return NULL; + } + return ctx; + } + + /* If we can't stat the file, give up */ + Log0(ctx, "Can't stat %s", path ); + perror(""); + goto DVDOpen_error; + } + + /* First check if this is a block/char device or a file*/ + if( S_ISBLK( fileinfo.st_mode ) || + S_ISCHR( fileinfo.st_mode ) || + S_ISREG( fileinfo.st_mode ) ) { + + /** + * Block devices and regular files are assumed to be DVD-Video images. + */ +#if defined(__sun) + dev_name = sun_block2char( path ); +#elif defined(SYS_BSD) + dev_name = bsd_block2char( path ); +#else + dev_name = strdup( path ); +#endif + if(!dev_name) + goto DVDOpen_error; + ctx->rd = DVDOpenImageFile( ctx, dev_name, NULL, have_css ); + free( dev_name ); + free(path); + if(!ctx->rd) + { + free(ctx); + return NULL; + } + return ctx; + } else if( S_ISDIR( fileinfo.st_mode ) ) { +#if defined(SYS_BSD) + struct fstab* fe; +#elif defined(__sun) || defined(__linux__) + FILE *mntfile; +#endif + + /* XXX: We should scream real loud here. */ + if( !(path_copy = strdup( path ) ) ) + goto DVDOpen_error; + +#ifndef _WIN32 /* win32 doesn't have realpath */ + /* Also WIN32 does not have symlinks, so we don't need this bit of code. */ + + /* Resolve any symlinks and get the absolute dir name. */ + { + new_path = realpath( path_copy, NULL ); + if( new_path == NULL ) { + goto DVDOpen_error; + } + free(path_copy); + path_copy = new_path; + new_path = NULL; + } +#endif + + /** + * If we're being asked to open a directory, check if that directory + * is the mount point for a DVD-ROM which we can use instead. + */ + + if( strlen( path_copy ) > 1 ) { + if( path_copy[ strlen( path_copy ) - 1 ] == '/' ) { + path_copy[ strlen( path_copy ) - 1 ] = '\0'; + } + } + +#if defined(_WIN32) || defined(__OS2__) + if( strlen( path_copy ) > 9 ) { + if( !strcasecmp( &(path_copy[ strlen( path_copy ) - 9 ]), + "\\video_ts")) + path_copy[ strlen( path_copy ) - (9-1) ] = '\0'; + } +#endif + if( strlen( path_copy ) > 9 ) { + if( !strcasecmp( &(path_copy[ strlen( path_copy ) - 9 ]), + "/video_ts" ) ) { + path_copy[ strlen( path_copy ) - 9 ] = '\0'; + } + } + + if(path_copy[0] == '\0') { + free( path_copy ); + if( !(path_copy = strdup( "/" ) ) ) + goto DVDOpen_error; + } + +#if defined(__APPLE__) + struct statfs s[128]; + int r = getfsstat(NULL, 0, MNT_NOWAIT); + if (r > 0) { + if (r > 128) + r = 128; + r = getfsstat(s, r * sizeof(s[0]), MNT_NOWAIT); + int i; + for (i=0; ird = DVDOpenImageFile( ctx, dev_name, NULL, have_css ); + break; + } + } + } +#elif defined(SYS_BSD) + if( ( fe = getfsfile( path_copy ) ) ) { + dev_name = bsd_block2char( fe->fs_spec ); + Log3(ctx, "Attempting to use device %s" + " mounted on %s for CSS authentication", + dev_name, + fe->fs_file ); + ctx->rd = DVDOpenImageFile( ctx, dev_name, NULL, have_css ); + } +#elif defined(__sun) + mntfile = fopen( MNTTAB, "r" ); + if( mntfile ) { + struct mnttab mp; + int res; + + while( ( res = getmntent( mntfile, &mp ) ) != -1 ) { + if( res == 0 && !strcmp( mp.mnt_mountp, path_copy ) ) { + dev_name = sun_block2char( mp.mnt_special ); + Log3(ctx, "Attempting to use device %s" + " mounted on %s for CSS authentication", + dev_name, + mp.mnt_mountp ); + ctx->rd = DVDOpenImageFile( ctx, dev_name, NULL, have_css ); + break; + } + } + fclose( mntfile ); + } +#elif defined(__linux__) + mntfile = fopen( _PATH_MOUNTED, "r" ); + if( mntfile ) { + +#ifdef HAVE_GETMNTENT_R + struct mntent *me, mbuf; + char buf [8192]; + while( ( me = getmntent_r( mntfile, &mbuf, buf, sizeof(buf) ) ) ) { +#else + struct mntent *me; + while( ( me = getmntent( mntfile ) ) ) { +#endif + if( !strcmp( me->mnt_dir, path_copy ) ) { + Log3(ctx, "Attempting to use device %s" + " mounted on %s for CSS authentication", + me->mnt_fsname, + me->mnt_dir ); + ctx->rd = DVDOpenImageFile( ctx, me->mnt_fsname, NULL, have_css ); + dev_name = strdup(me->mnt_fsname); + break; + } + } + fclose( mntfile ); + } +#elif defined(_WIN32) || defined(__OS2__) +#ifdef __OS2__ + /* Use DVDOpenImageFile() only if it is a drive */ + if(isalpha(path[0]) && path[1] == ':' && + ( !path[2] || + ((path[2] == '\\' || path[2] == '/') && !path[3]))) +#endif + ctx->rd = DVDOpenImageFile( ctx, path, NULL, have_css ); +#endif + +#if !defined(_WIN32) && !defined(__OS2__) + if( !dev_name ) { + Log0(ctx, "Couldn't find device name." ); + } else if( !ctx->rd ) { + Log0(ctx, "Device %s inaccessible, " + "CSS authentication not available.", dev_name ); + } +#else + if( !ctx->rd ) { + Log0(ctx, "Device %s inaccessible, " + "CSS authentication not available.", path ); + } +#endif + + free( dev_name ); + dev_name = NULL; + free( path_copy ); + path_copy = NULL; + + /** + * If we've opened a drive, just use that. + */ + if(ctx->rd) + { + free(path); + return ctx; + } + /** + * Otherwise, we now try to open the directory tree instead. + */ + ctx->rd = DVDOpenPath( path ); + free( path ); + if(!ctx->rd) + { + free(ctx); + return NULL; + } + return ctx; + } + +DVDOpen_error: + /* If it's none of the above, screw it. */ + Log0(ctx, "Could not open %s", path ); + free( path ); + free( path_copy ); + if ( cdir >= 0 ) + close( cdir ); + free( new_path ); + return NULL; +} + +dvd_reader_t *DVDOpen( const char *ppath ) +{ + return DVDOpenCommon( NULL, NULL, ppath, NULL ); +} + +dvd_reader_t *DVDOpenStream( void *stream, + dvd_reader_stream_cb *stream_cb ) +{ + return DVDOpenCommon( stream, NULL, NULL, stream_cb ); +} + +dvd_reader_t *DVDOpen2( void *priv, const dvd_logger_cb *logcb, + const char *ppath ) +{ + return DVDOpenCommon( priv, logcb, ppath, NULL ); +} + +dvd_reader_t *DVDOpenStream2( void *priv, const dvd_logger_cb *logcb, + dvd_reader_stream_cb *stream_cb ) +{ + return DVDOpenCommon( priv, logcb, NULL, stream_cb ); +} + +void DVDClose( dvd_reader_t *dvd ) +{ + if( dvd ) { + if( dvd->rd->dev ) dvdinput_close( dvd->rd->dev ); + if( dvd->rd->path_root ) free( dvd->rd->path_root ); + if( dvd->rd->udfcache ) FreeUDFCache( dvd->rd->udfcache ); + free( dvd->rd ); + free( dvd ); + } +} + +/** + * Open an unencrypted file on a DVD image file. + */ +static dvd_file_t *DVDOpenFileUDF( dvd_reader_t *ctx, const char *filename, + int do_cache ) +{ + uint32_t start, len; + dvd_file_t *dvd_file; + + start = UDFFindFile( ctx, filename, &len ); + if( !start ) { + Log0(ctx, "DVDOpenFileUDF:UDFFindFile %s failed", filename ); + return NULL; + } + + dvd_file = calloc( 1, sizeof( dvd_file_t ) ); + if( !dvd_file ) { + Log0(ctx, "DVDOpenFileUDF:malloc failed" ); + return NULL; + } + dvd_file->ctx = ctx; + dvd_file->lb_start = start; + dvd_file->filesize = len / DVD_VIDEO_LB_LEN; + + /* Read the whole file in cache (unencrypted) if asked and if it doesn't + * exceed 128KB */ + if( do_cache && len < 64 * DVD_VIDEO_LB_LEN ) { + int ret; + + dvd_file->cache = malloc( len ); + if( !dvd_file->cache ) + return dvd_file; + + ret = InternalUDFReadBlocksRaw( ctx, dvd_file->lb_start, + dvd_file->filesize, dvd_file->cache, + DVDINPUT_NOFLAGS ); + if( ret != dvd_file->filesize ) { + free( dvd_file->cache ); + dvd_file->cache = NULL; + } + } + + return dvd_file; +} + +/** + * Searches for in directory , ignoring case. + * Returns 0 and full filename in . + * or -1 on file not found. + * or -2 on path not found. + */ +static int findDirFile( const char *path, const char *file, char *filename ) +{ + DIR *dir; + struct dirent *ent; + + dir = opendir( path ); + if( !dir ) return -2; + + while( ( ent = readdir( dir ) ) != NULL ) { + if( !strcasecmp( ent->d_name, file ) ) { + sprintf( filename, "%s%s%s", path, + ( ( path[ strlen( path ) - 1 ] == '/' ) ? "" : "/" ), + ent->d_name ); + closedir(dir); + return 0; + } + } + closedir(dir); + return -1; +} + +static int findDVDFile( dvd_reader_t *dvd, const char *file, char *filename ) +{ + const char *nodirfile; + int ret; + + /* Strip off the directory for our search */ + if( !strncasecmp( "/VIDEO_TS/", file, 10 ) ) { + nodirfile = &(file[ 10 ]); + } else { + nodirfile = file; + } + + ret = findDirFile( dvd->rd->path_root, nodirfile, filename ); + if( ret < 0 ) { + char video_path[ PATH_MAX + 1 ]; + + /* Try also with adding the path, just in case. */ + sprintf( video_path, "%s/VIDEO_TS/", dvd->rd->path_root ); + ret = findDirFile( video_path, nodirfile, filename ); + if( ret < 0 ) { + /* Try with the path, but in lower case. */ + sprintf( video_path, "%s/video_ts/", dvd->rd->path_root ); + ret = findDirFile( video_path, nodirfile, filename ); + if( ret < 0 ) { + return 0; + } + } + } + + return 1; +} + +/** + * Open an unencrypted file from a DVD directory tree. + */ +static dvd_file_t *DVDOpenFilePath( dvd_reader_t *ctx, const char *filename ) +{ + char full_path[ PATH_MAX + 1 ]; + dvd_file_t *dvd_file; + dvdstat_t fileinfo; + dvd_input_t dev; + + /* Get the full path of the file. */ + if( !findDVDFile( ctx, filename, full_path ) ) { + Log0(ctx, "DVDOpenFilePath:findDVDFile %s failed", filename ); + return NULL; + } + + dev = dvdinput_open( ctx->priv, &ctx->logcb, full_path, NULL ); + if( !dev ) { + Log0(ctx, "DVDOpenFilePath:dvdinput_open %s failed", full_path ); + return NULL; + } + + dvd_file = calloc( 1, sizeof( dvd_file_t ) ); + if( !dvd_file ) { + Log0(ctx, "DVDOpenFilePath:dvd_file malloc failed" ); + dvdinput_close(dev); + return NULL; + } + dvd_file->ctx = ctx; + + if( dvdstat( full_path, &fileinfo ) < 0 ) { + Log0(ctx, "Can't stat() %s.", filename ); + free( dvd_file ); + dvdinput_close( dev ); + return NULL; + } + dvd_file->title_sizes[ 0 ] = fileinfo.st_size / DVD_VIDEO_LB_LEN; + dvd_file->title_devs[ 0 ] = dev; + dvd_file->filesize = dvd_file->title_sizes[ 0 ]; + + return dvd_file; +} + +static dvd_file_t *DVDOpenVOBUDF( dvd_reader_t *ctx, int title, int menu ) +{ + char filename[ MAX_UDF_FILE_NAME_LEN ]; + uint32_t start, len; + dvd_file_t *dvd_file; + + if( title == 0 ) { + strcpy( filename, "/VIDEO_TS/VIDEO_TS.VOB" ); + } else { + sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, menu ? 0 : 1 ); + } + start = UDFFindFile( ctx, filename, &len ); + if( start == 0 ) return NULL; + + dvd_file = calloc( 1, sizeof( dvd_file_t ) ); + if( !dvd_file ) return NULL; + dvd_file->ctx = ctx; + /*Hack*/ dvd_file->css_title = title << 1 | menu; + dvd_file->lb_start = start; + dvd_file->filesize = len / DVD_VIDEO_LB_LEN; + + /* Calculate the complete file size for every file in the VOBS */ + if( !menu ) { + int cur; + + for( cur = 2; cur < 10; cur++ ) { + sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, cur ); + if( !UDFFindFile( ctx, filename, &len ) ) break; + dvd_file->filesize += len / DVD_VIDEO_LB_LEN; + } + } + + if( ctx->rd->css_state == 1 /* Need key init */ ) { + initAllCSSKeys( ctx ); + ctx->rd->css_state = 2; + } + /* + if( dvdinput_title( dvd_file->dvd->dev, (int)start ) < 0 ) { + Log0(ctx, "Error cracking CSS key for %s", filename ); + } + */ + + return dvd_file; +} + +static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *ctx, int title, int menu ) +{ + char filename[ MAX_UDF_FILE_NAME_LEN ]; + char full_path[ PATH_MAX + 1 ]; + dvdstat_t fileinfo; + dvd_file_t *dvd_file; + + dvd_file = calloc( 1, sizeof( dvd_file_t ) ); + if( !dvd_file ) return NULL; + dvd_file->ctx = ctx; + /*Hack*/ dvd_file->css_title = title << 1 | menu; + + if( menu ) { + dvd_input_t dev; + + if( title == 0 ) { + strcpy( filename, "VIDEO_TS.VOB" ); + } else { + sprintf( filename, "VTS_%02i_0.VOB", title ); + } + if( !findDVDFile( ctx, filename, full_path ) ) { + free( dvd_file ); + return NULL; + } + + dev = dvdinput_open( ctx->priv, &ctx->logcb, full_path, NULL ); + if( dev == NULL ) { + free( dvd_file ); + return NULL; + } + + if( dvdstat( full_path, &fileinfo ) < 0 ) { + Log0(ctx, "Can't stat() %s.", filename ); + dvdinput_close(dev); + free( dvd_file ); + return NULL; + } + dvd_file->title_sizes[ 0 ] = fileinfo.st_size / DVD_VIDEO_LB_LEN; + dvd_file->title_devs[ 0 ] = dev; + dvdinput_title( dvd_file->title_devs[0], 0); + dvd_file->filesize = dvd_file->title_sizes[ 0 ]; + + } else { + int i; + + for( i = 0; i < TITLES_MAX; ++i ) { + + sprintf( filename, "VTS_%02i_%i.VOB", title, i + 1 ); + if( !findDVDFile( ctx, filename, full_path ) ) { + break; + } + + if( dvdstat( full_path, &fileinfo ) < 0 ) { + Log0(ctx, "Can't stat() %s.", filename ); + break; + } + + dvd_file->title_sizes[ i ] = fileinfo.st_size / DVD_VIDEO_LB_LEN; + dvd_file->title_devs[ i ] = dvdinput_open( ctx->priv, &ctx->logcb, full_path, NULL ); + dvdinput_title( dvd_file->title_devs[ i ], 0 ); + dvd_file->filesize += dvd_file->title_sizes[ i ]; + } + if( !dvd_file->title_devs[ 0 ] ) { + free( dvd_file ); + return NULL; + } + } + + return dvd_file; +} + +dvd_file_t *DVDOpenFile( dvd_reader_t *ctx, int titlenum, + dvd_read_domain_t domain ) +{ + dvd_reader_device_t *dvd = ctx->rd; + char filename[ MAX_UDF_FILE_NAME_LEN ]; + int do_cache = 0; + + /* Check arguments. */ + if( dvd == NULL || titlenum < 0 ) + return NULL; + + switch( domain ) { + case DVD_READ_INFO_FILE: + if( titlenum == 0 ) { + strcpy( filename, "/VIDEO_TS/VIDEO_TS.IFO" ); + } else { + sprintf( filename, "/VIDEO_TS/VTS_%02i_0.IFO", titlenum ); + } + do_cache = 1; + break; + case DVD_READ_INFO_BACKUP_FILE: + if( titlenum == 0 ) { + strcpy( filename, "/VIDEO_TS/VIDEO_TS.BUP" ); + } else { + sprintf( filename, "/VIDEO_TS/VTS_%02i_0.BUP", titlenum ); + } + do_cache = 1; + break; + case DVD_READ_MENU_VOBS: + if( dvd->isImageFile ) { + return DVDOpenVOBUDF( ctx, titlenum, 1 ); + } else { + return DVDOpenVOBPath( ctx, titlenum, 1 ); + } + break; + case DVD_READ_TITLE_VOBS: + if( titlenum == 0 ) return NULL; + if( dvd->isImageFile ) { + return DVDOpenVOBUDF( ctx, titlenum, 0 ); + } else { + return DVDOpenVOBPath( ctx, titlenum, 0 ); + } + break; + default: + Log1(ctx, "Invalid domain for file open." ); + return NULL; + } + + if( dvd->isImageFile ) { + return DVDOpenFileUDF( ctx, filename, do_cache ); + } else { + return DVDOpenFilePath( ctx, filename ); + } +} + +void DVDCloseFile( dvd_file_t *dvd_file ) +{ + dvd_reader_device_t *dvd = dvd_file->ctx->rd; + if( dvd_file && dvd ) { + if( !dvd->isImageFile ) { + int i; + + for( i = 0; i < TITLES_MAX; ++i ) { + if( dvd_file->title_devs[ i ] ) { + dvdinput_close( dvd_file->title_devs[i] ); + } + } + } + + free( dvd_file->cache ); + free( dvd_file ); + dvd_file = NULL; + } +} + +static int DVDFileStatVOBUDF( dvd_reader_t *dvd, int title, + int menu, dvd_stat_t *statbuf ) +{ + char filename[ MAX_UDF_FILE_NAME_LEN ]; + uint32_t size; + off_t tot_size; + off_t parts_size[ 9 ]; + int nr_parts = 0; + int n; + + if( title == 0 ) + strcpy( filename, "/VIDEO_TS/VIDEO_TS.VOB" ); + else + sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, menu ? 0 : 1 ); + + if( !UDFFindFile( dvd, filename, &size ) ) + return -1; + + tot_size = size; + nr_parts = 1; + parts_size[ 0 ] = size; + + if( !menu ) { + int cur; + + for( cur = 2; cur < 10; cur++ ) { + sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, cur ); + if( !UDFFindFile( dvd, filename, &size ) ) + break; + + parts_size[ nr_parts ] = size; + tot_size += size; + nr_parts++; + } + } + + statbuf->size = tot_size; + statbuf->nr_parts = nr_parts; + for( n = 0; n < nr_parts; n++ ) + statbuf->parts_size[ n ] = parts_size[ n ]; + + return 0; +} + + +static int DVDFileStatVOBPath( dvd_reader_t *dvd, int title, + int menu, dvd_stat_t *statbuf ) +{ + char filename[ MAX_UDF_FILE_NAME_LEN ]; + char full_path[ PATH_MAX + 1 ]; + dvdstat_t fileinfo; + off_t tot_size; + off_t parts_size[ 9 ]; + int nr_parts = 0; + int n; + + if( title == 0 ) + strcpy( filename, "VIDEO_TS.VOB" ); + else + sprintf( filename, "VTS_%02d_%d.VOB", title, menu ? 0 : 1 ); + + if( !findDVDFile( dvd, filename, full_path ) ) + return -1; + + if( dvdstat( full_path, &fileinfo ) < 0 ) { + Log1(dvd, "Can't stat() %s.", filename ); + return -1; + } + + tot_size = fileinfo.st_size; + nr_parts = 1; + parts_size[ 0 ] = fileinfo.st_size; + + if( !menu ) { + int cur; + for( cur = 2; cur < 10; cur++ ) { + sprintf( filename, "VTS_%02d_%d.VOB", title, cur ); + if( !findDVDFile( dvd, filename, full_path ) ) + break; + + if( dvdstat( full_path, &fileinfo ) < 0 ) { + Log1(dvd, "Can't stat() %s.", filename ); + break; + } + + parts_size[ nr_parts ] = fileinfo.st_size; + tot_size += parts_size[ nr_parts ]; + nr_parts++; + } + } + + statbuf->size = tot_size; + statbuf->nr_parts = nr_parts; + for( n = 0; n < nr_parts; n++ ) + statbuf->parts_size[ n ] = parts_size[ n ]; + + return 0; +} + + +int DVDFileStat( dvd_reader_t *reader, int titlenum, + dvd_read_domain_t domain, dvd_stat_t *statbuf ) +{ + dvd_reader_device_t *dvd = reader->rd; + char filename[ MAX_UDF_FILE_NAME_LEN ]; + dvdstat_t fileinfo; + uint32_t size; + + /* Check arguments. */ + if( dvd == NULL || titlenum < 0 ) { + errno = EINVAL; + return -1; + } + + switch( domain ) { + case DVD_READ_INFO_FILE: + if( titlenum == 0 ) + strcpy( filename, "/VIDEO_TS/VIDEO_TS.IFO" ); + else + sprintf( filename, "/VIDEO_TS/VTS_%02i_0.IFO", titlenum ); + + break; + case DVD_READ_INFO_BACKUP_FILE: + if( titlenum == 0 ) + strcpy( filename, "/VIDEO_TS/VIDEO_TS.BUP" ); + else + sprintf( filename, "/VIDEO_TS/VTS_%02i_0.BUP", titlenum ); + + break; + case DVD_READ_MENU_VOBS: + if( dvd->isImageFile ) + return DVDFileStatVOBUDF( reader, titlenum, 1, statbuf ); + else + return DVDFileStatVOBPath( reader, titlenum, 1, statbuf ); + + break; + case DVD_READ_TITLE_VOBS: + if( titlenum == 0 ) + return -1; + + if( dvd->isImageFile ) + return DVDFileStatVOBUDF( reader, titlenum, 0, statbuf ); + else + return DVDFileStatVOBPath( reader, titlenum, 0, statbuf ); + + break; + default: + Log1(reader, "Invalid domain for file stat." ); + errno = EINVAL; + return -1; + } + + if( dvd->isImageFile ) { + if( UDFFindFile( reader, filename, &size ) ) { + statbuf->size = size; + statbuf->nr_parts = 1; + statbuf->parts_size[ 0 ] = size; + return 0; + } + } else { + char full_path[ PATH_MAX + 1 ]; + + if( findDVDFile( reader, filename, full_path ) ) { + if( dvdstat( full_path, &fileinfo ) < 0 ) + Log1(reader, "Can't stat() %s.", filename ); + else { + statbuf->size = fileinfo.st_size; + statbuf->nr_parts = 1; + statbuf->parts_size[ 0 ] = statbuf->size; + return 0; + } + } + } + return -1; +} + +/* Internal, but used from dvd_udf.c */ +int InternalUDFReadBlocksRaw( const dvd_reader_t *ctx, uint32_t lb_number, + size_t block_count, unsigned char *data, + int encrypted ) +{ + int ret; + + if( !ctx->rd->dev ) { + Log0(ctx, "Fatal error in block read." ); + return -1; + } + + ret = dvdinput_seek( ctx->rd->dev, (int) lb_number ); + if( ret != (int) lb_number ) { + Log1(ctx, "Can't seek to block %u", lb_number ); + return ret; + } + + ret = dvdinput_read( ctx->rd->dev, (char *) data, + (int) block_count, encrypted ); + return ret; +} + +/* This is using a single input and starting from 'dvd_file->lb_start' offset. + * + * Reads 'block_count' blocks from 'dvd_file' at block offset 'offset' + * into the buffer located at 'data' and if 'encrypted' is set + * descramble the data if it's encrypted. Returning either an + * negative error or the number of blocks read. */ +static int DVDReadBlocksUDF( const dvd_file_t *dvd_file, uint32_t offset, + size_t block_count, unsigned char *data, + int encrypted ) +{ + /* If the cache is present and we don't need to decrypt, use the cache to + * feed the data */ + if( dvd_file->cache && (encrypted & DVDINPUT_READ_DECRYPT) == 0 ) { + /* Check if we don't exceed the cache (or file) size */ + if( block_count + offset > (size_t) dvd_file->filesize ) + return 0; + + /* Copy the cache at a specified offset into data. offset and block_count + * must be converted into bytes */ + memcpy( data, dvd_file->cache + (off_t)offset * (off_t)DVD_VIDEO_LB_LEN, + (off_t)block_count * (off_t)DVD_VIDEO_LB_LEN ); + + /* return the amount of blocks copied */ + return block_count; + } else { + /* use dvdinput access */ + return InternalUDFReadBlocksRaw( dvd_file->ctx, dvd_file->lb_start + offset, + block_count, data, encrypted ); + } +} + +/* This is using possibly several inputs and starting from an offset of '0'. + * + * Reads 'block_count' blocks from 'dvd_file' at block offset 'offset' + * into the buffer located at 'data' and if 'encrypted' is set + * descramble the data if it's encrypted. Returning either an + * negative error or the number of blocks read. */ +static int DVDReadBlocksPath( const dvd_file_t *dvd_file, unsigned int offset, + size_t block_count, unsigned char *data, + int encrypted ) +{ + const dvd_reader_t *ctx = dvd_file->ctx; + int i; + int ret, ret2, off; + + ret = 0; + ret2 = 0; + for( i = 0; i < TITLES_MAX; ++i ) { + if( !dvd_file->title_sizes[ i ] ) return 0; /* Past end of file */ + + if( offset < dvd_file->title_sizes[ i ] ) { + if( ( offset + block_count ) <= dvd_file->title_sizes[ i ] ) { + off = dvdinput_seek( dvd_file->title_devs[ i ], (int)offset ); + if( off < 0 || off != (int)offset ) { + Log1(ctx, "Can't seek to block %u", offset ); + return off < 0 ? off : 0; + } + ret = dvdinput_read( dvd_file->title_devs[ i ], data, + (int)block_count, encrypted ); + break; + } else { + size_t part1_size = dvd_file->title_sizes[ i ] - offset; + /* FIXME: Really needs to be a while loop. + * (This is only true if you try and read >1GB at a time) */ + + /* Read part 1 */ + off = dvdinput_seek( dvd_file->title_devs[ i ], (int)offset ); + if( off < 0 || off != (int)offset ) { + Log1(ctx, "Can't seek to block %u", offset ); + return off < 0 ? off : 0; + } + ret = dvdinput_read( dvd_file->title_devs[ i ], data, + (int)part1_size, encrypted ); + if( ret < 0 ) return ret; + /* FIXME: This is wrong if i is the last file in the set. + * also error from this read will not show in ret. */ + + /* Does the next part exist? If not then return now. */ + if( i + 1 >= TITLES_MAX || !dvd_file->title_devs[ i + 1 ] ) + return ret; + + /* Read part 2 */ + off = dvdinput_seek( dvd_file->title_devs[ i + 1 ], 0 ); + if( off < 0 || off != 0 ) { + Log1(ctx, "Can't seek to block %d", 0 ); + return off < 0 ? off : 0; + } + ret2 = dvdinput_read( dvd_file->title_devs[ i + 1 ], + data + ( part1_size + * (int64_t)DVD_VIDEO_LB_LEN ), + (int)(block_count - part1_size), + encrypted ); + if( ret2 < 0 ) return ret2; + break; + } + } else { + offset -= dvd_file->title_sizes[ i ]; + } + } + + return ret + ret2; +} + +/* This is broken reading more than 2Gb at a time is ssize_t is 32-bit. */ +ssize_t DVDReadBlocks( dvd_file_t *dvd_file, int offset, + size_t block_count, unsigned char *data ) +{ + dvd_reader_t *ctx = dvd_file->ctx; + dvd_reader_device_t *dvd = ctx->rd; + int ret; + + /* Check arguments. */ + if( dvd_file == NULL || offset < 0 || data == NULL ) + return -1; + + /* Hack, and it will still fail for multiple opens in a threaded app ! */ + if( dvd->css_title != dvd_file->css_title ) { + dvd->css_title = dvd_file->css_title; + if( dvd->isImageFile ) { + dvdinput_title( dvd->dev, (int)dvd_file->lb_start ); + } + /* Here each vobu has it's own dvdcss handle, so no need to update + else { + dvdinput_title( dvd_file->title_devs[ 0 ], (int)dvd_file->lb_start ); + }*/ + } + + if( dvd->isImageFile ) { + ret = DVDReadBlocksUDF( dvd_file, (uint32_t)offset, + block_count, data, DVDINPUT_READ_DECRYPT ); + } else { + ret = DVDReadBlocksPath( dvd_file, (unsigned int)offset, + block_count, data, DVDINPUT_READ_DECRYPT ); + } + + return (ssize_t)ret; +} + +int32_t DVDFileSeek( dvd_file_t *dvd_file, int32_t offset ) +{ + /* Check arguments. */ + if( dvd_file == NULL || offset < 0 ) + return -1; + + if( offset > dvd_file->filesize * DVD_VIDEO_LB_LEN ) { + return -1; + } + dvd_file->seek_pos = (uint32_t) offset; + return offset; +} + +int DVDFileSeekForce(dvd_file_t *dvd_file, int offset, int force_size) +{ + dvd_reader_t *ctx = dvd_file->ctx; + dvd_reader_device_t *dvd = ctx->rd; + /* Check arguments. */ + if( dvd_file == NULL || offset <= 0 ) + return -1; + + if( dvd->isImageFile ) { + if( force_size < 0 ) + force_size = (offset - 1) / DVD_VIDEO_LB_LEN + 1; + if( dvd_file->filesize < force_size ) { + dvd_file->filesize = force_size; + free(dvd_file->cache); + dvd_file->cache = NULL; + Log2(ctx, "Ignored size of file indicated in UDF."); + } + } + + if( offset > dvd_file->filesize * DVD_VIDEO_LB_LEN ) + return -1; + + dvd_file->seek_pos = (uint32_t) offset; + return offset; +} + +ssize_t DVDReadBytes( dvd_file_t *dvd_file, void *data, size_t byte_size ) +{ + dvd_reader_t *ctx = dvd_file->ctx; + dvd_reader_device_t *dvd = ctx->rd; + unsigned char *secbuf_base, *secbuf; + unsigned int numsec, seek_sector, seek_byte; + int ret; + + /* Check arguments. */ + if( dvd_file == NULL || data == NULL || (ssize_t)byte_size < 0 ) + return -1; + + seek_sector = dvd_file->seek_pos / DVD_VIDEO_LB_LEN; + seek_byte = dvd_file->seek_pos % DVD_VIDEO_LB_LEN; + + numsec = ( ( seek_byte + byte_size ) / DVD_VIDEO_LB_LEN ) + + ( ( ( seek_byte + byte_size ) % DVD_VIDEO_LB_LEN ) ? 1 : 0 ); + + secbuf_base = malloc( numsec * DVD_VIDEO_LB_LEN + 2048 ); + if( !secbuf_base ) { + Log0(ctx, "Can't allocate memory for file read" ); + return 0; + } + secbuf = (unsigned char *)(((uintptr_t)secbuf_base & ~((uintptr_t)2047)) + 2048); + + if( dvd->isImageFile ) { + ret = DVDReadBlocksUDF( dvd_file, (uint32_t) seek_sector, + (size_t) numsec, secbuf, DVDINPUT_NOFLAGS ); + } else { + ret = DVDReadBlocksPath( dvd_file, seek_sector, + (size_t) numsec, secbuf, DVDINPUT_NOFLAGS ); + } + + if( ret != (int) numsec ) { + free( secbuf_base ); + return ret < 0 ? ret : 0; + } + + memcpy( data, &(secbuf[ seek_byte ]), byte_size ); + free( secbuf_base ); + + DVDFileSeekForce(dvd_file, dvd_file->seek_pos + byte_size, -1); + return byte_size; +} + +ssize_t DVDFileSize( dvd_file_t *dvd_file ) +{ + /* Check arguments. */ + if( dvd_file == NULL ) + return -1; + + return dvd_file->filesize; +} + +int DVDDiscID( dvd_reader_t *dvd, unsigned char *discid ) +{ + struct md5_s ctx; + int title; + int title_sets; + int nr_of_files = 0; + ifo_handle_t *vmg_ifo; + + /* Check arguments. */ + if( dvd == NULL || discid == NULL ) + return 0; + + vmg_ifo = ifoOpen( dvd, 0 ); + if( !vmg_ifo ) { + Log0(dvd, "DVDDiscId, failed to open VMG IFO" ); + return -1; + } + + title_sets = vmg_ifo->vmgi_mat->vmg_nr_of_title_sets + 1; + ifoClose( vmg_ifo ); + + if( title_sets > 10 ) + title_sets = 10; + + /* Go through the first IFO:s, in order, up until the tenth, + * and md5sum them, i.e VIDEO_TS.IFO and VTS_0?_0.IFO */ + InitMD5( &ctx ); + for( title = 0; title < title_sets; title++ ) { + dvd_file_t *dvd_file = DVDOpenFile( dvd, title, DVD_READ_INFO_FILE ); + if( dvd_file != NULL ) { + ssize_t bytes_read; + ssize_t file_size = dvd_file->filesize * DVD_VIDEO_LB_LEN; + char *buffer_base = malloc( file_size + 2048 ); + + if( buffer_base == NULL ) { + DVDCloseFile( dvd_file ); + Log0(dvd, "DVDDiscId, failed to allocate memory for file read" ); + return -1; + } + + char *buffer = (char *)(((uintptr_t)buffer_base & ~((uintptr_t)2047)) + 2048); + + bytes_read = DVDReadBytes( dvd_file, buffer, file_size ); + if( bytes_read != file_size ) { + Log1(dvd, "DVDDiscId read returned %zd bytes" + ", wanted %zd", bytes_read, file_size ); + DVDCloseFile( dvd_file ); + free( buffer_base ); + return -1; + } + + AddMD5( &ctx, buffer, file_size ); + + DVDCloseFile( dvd_file ); + free( buffer_base ); + nr_of_files++; + } + } + EndMD5( &ctx ); + memcpy( discid, ctx.buf, 16 ); + if(!nr_of_files) + return -1; + + return 0; +} + + +int DVDISOVolumeInfo( dvd_reader_t *ctx, + char *volid, unsigned int volid_size, + unsigned char *volsetid, unsigned int volsetid_size ) +{ + dvd_reader_device_t *dvd = ctx->rd; + unsigned char *buffer, *buffer_base; + int ret; + + /* Check arguments. */ + if( dvd == NULL ) + return 0; + + if( dvd->dev == NULL ) { + /* No block access, so no ISO... */ + return -1; + } + + buffer_base = malloc( DVD_VIDEO_LB_LEN + 2048 ); + + if( buffer_base == NULL ) { + Log0(ctx, "DVDISOVolumeInfo, failed to " + "allocate memory for file read" ); + return -1; + } + + buffer = (unsigned char *)(((uintptr_t)buffer_base & ~((uintptr_t)2047)) + 2048); + + ret = InternalUDFReadBlocksRaw( ctx, 16, 1, buffer, 0 ); + if( ret != 1 ) { + Log0(ctx, "DVDISOVolumeInfo, failed to " + "read ISO9660 Primary Volume Descriptor" ); + free( buffer_base ); + return -1; + } + + if( (volid != NULL) && (volid_size > 0) ) { + unsigned int n; + for(n = 0; n < 32; n++) { + if(buffer[40+n] == 0x20) { + break; + } + } + + if(volid_size > n+1) { + volid_size = n+1; + } + + memcpy(volid, &buffer[40], volid_size-1); + volid[volid_size-1] = '\0'; + } + + if( (volsetid != NULL) && (volsetid_size > 0) ) { + if(volsetid_size > 128) { + volsetid_size = 128; + } + memcpy(volsetid, &buffer[190], volsetid_size); + } + free( buffer_base ); + return 0; +} + + +int DVDUDFVolumeInfo( dvd_reader_t *ctx, + char *volid, unsigned int volid_size, + unsigned char *volsetid, unsigned int volsetid_size ) +{ + int ret; + /* Check arguments. */ + if( ctx == NULL || ctx->rd == NULL ) + return -1; + + if( ctx->rd->dev == NULL ) { + /* No block access, so no UDF VolumeSet Identifier */ + return -1; + } + + if( (volid != NULL) && (volid_size > 0) ) { + ret = UDFGetVolumeIdentifier(ctx, volid, volid_size); + if(!ret) { + return -1; + } + } + if( (volsetid != NULL) && (volsetid_size > 0) ) { + ret = UDFGetVolumeSetIdentifier(ctx, volsetid, volsetid_size); + if(!ret) { + return -1; + } + } + + return 0; +} diff --git a/libdvdread-embedded/src/dvd_udf.c b/libdvdread-embedded/src/dvd_udf.c new file mode 100644 index 0000000..4d90ba4 --- /dev/null +++ b/libdvdread-embedded/src/dvd_udf.c @@ -0,0 +1,1033 @@ +/* + * This code is based on dvdudf by: + * Christian Wolff . + * + * Modifications by: + * Billy Biggs . + * Björn Englund . + * + * dvdudf: parse and read the UDF volume information of a DVD Video + * Copyright (C) 1999 Christian Wolff for convergence integrated media + * GmbH The author can be reached at scarabaeus@convergence.de, the + * project's page is at http://linuxtv.org/dvd/ + * + * This file is part of libdvdread. + * + * libdvdread 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 of the License, or + * (at your option) any later version. + * + * libdvdread 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 libdvdread; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "dvdread_internal.h" +#include "dvdread/dvd_reader.h" +#include "dvdread/dvd_udf.h" + +/* It's required to either fail or deliver all the blocks asked for. */ +static int DVDReadLBUDF( dvd_reader_t *ctx, uint32_t lb_number, + size_t block_count, unsigned char *data, + int encrypted ) +{ + size_t count = block_count; + + while(count > 0) { + int ret; + + ret = InternalUDFReadBlocksRaw(ctx, lb_number, count, data + DVD_VIDEO_LB_LEN * (block_count - count), encrypted); + + if(ret <= 0) { + /* One of the reads failed or nothing more to read, too bad. + * We won't even bother returning the reads that went ok. */ + return ret; + } + + count -= (size_t)ret; + lb_number += (uint32_t)ret; + } + + return block_count; +} + + +#ifndef NULL +#define NULL ((void *)0) +#endif + +struct Partition { + int valid; + uint16_t Flags; + uint16_t Number; + char Contents[32]; + uint32_t AccessType; + uint32_t Start; + uint32_t Length; +}; + +struct AD { + uint32_t Location; + uint32_t Length; + uint8_t Flags; + uint16_t Partition; +}; + +struct extent_ad { + uint32_t location; + uint32_t length; +}; + +struct avdp_t { + struct extent_ad mvds; + struct extent_ad rvds; +}; + +struct pvd_t { + uint8_t VolumeIdentifier[32]; + uint8_t VolumeSetIdentifier[128]; +}; + +struct lbudf { + uint32_t lb; + uint8_t *data; + /* needed for proper freeing */ + uint8_t *data_base; +}; + +struct icbmap { + uint32_t lbn; + struct AD file; + uint8_t filetype; +}; + +struct udf_cache { + int avdp_valid; + struct avdp_t avdp; + int pvd_valid; + struct pvd_t pvd; + int partition_valid; + struct Partition partition; + int rooticb_valid; + struct AD rooticb; + int lb_num; + struct lbudf *lbs; + int map_num; + struct icbmap *maps; +}; + +typedef enum { + PartitionCache, RootICBCache, LBUDFCache, MapCache, AVDPCache, PVDCache +} UDFCacheType; + +void FreeUDFCache(void *cache) +{ + struct udf_cache *c = (struct udf_cache *)cache; + if(c == NULL) + return; + + if(c->lbs) { + int n; + for(n = 0; n < c->lb_num; n++) + free(c->lbs[n].data_base); + free(c->lbs); + } + if(c->maps) + free(c->maps); + free(c); +} + + +static int GetUDFCache(dvd_reader_t *ctx, UDFCacheType type, + uint32_t nr, void *data) +{ + int n; + struct udf_cache *c; + + if(DVDUDFCacheLevel(ctx, -1) <= 0) + return 0; + + c = (struct udf_cache *)GetUDFCacheHandle(ctx); + + if(c == NULL) + return 0; + + switch(type) { + case AVDPCache: + if(c->avdp_valid) { + *(struct avdp_t *)data = c->avdp; + return 1; + } + break; + case PVDCache: + if(c->pvd_valid) { + *(struct pvd_t *)data = c->pvd; + return 1; + } + break; + case PartitionCache: + if(c->partition_valid) { + *(struct Partition *)data = c->partition; + return 1; + } + break; + case RootICBCache: + if(c->rooticb_valid) { + *(struct AD *)data = c->rooticb; + return 1; + } + break; + case LBUDFCache: + for(n = 0; n < c->lb_num; n++) { + if(c->lbs[n].lb == nr) { + *(uint8_t **)data = c->lbs[n].data; + return 1; + } + } + break; + case MapCache: + for(n = 0; n < c->map_num; n++) { + if(c->maps[n].lbn == nr) { + *(struct icbmap *)data = c->maps[n]; + return 1; + } + } + break; + default: + break; + } + + return 0; +} + +static int SetUDFCache(dvd_reader_t *ctx, UDFCacheType type, + uint32_t nr, void *data) +{ + int n; + struct udf_cache *c; + void *tmp; + + if(DVDUDFCacheLevel(ctx, -1) <= 0) + return 0; + + c = (struct udf_cache *)GetUDFCacheHandle(ctx); + + if(c == NULL) { + c = calloc(1, sizeof(struct udf_cache)); + /* Log3(ctx, "calloc: %d", sizeof(struct udf_cache)); */ + if(c == NULL) + return 0; + SetUDFCacheHandle(ctx, c); + } + + + switch(type) { + case AVDPCache: + c->avdp = *(struct avdp_t *)data; + c->avdp_valid = 1; + break; + case PVDCache: + c->pvd = *(struct pvd_t *)data; + c->pvd_valid = 1; + break; + case PartitionCache: + c->partition = *(struct Partition *)data; + c->partition_valid = 1; + break; + case RootICBCache: + c->rooticb = *(struct AD *)data; + c->rooticb_valid = 1; + break; + case LBUDFCache: + for(n = 0; n < c->lb_num; n++) { + if(c->lbs[n].lb == nr) { + /* replace with new data */ + c->lbs[n].data_base = ((uint8_t **)data)[0]; + c->lbs[n].data = ((uint8_t **)data)[1]; + c->lbs[n].lb = nr; + return 1; + } + } + c->lb_num++; + tmp = realloc(c->lbs, c->lb_num * sizeof(struct lbudf)); + /* + Log3(ctx, "realloc lb: %d * %d = %d", + c->lb_num, sizeof(struct lbudf), + c->lb_num * sizeof(struct lbudf)); + */ + if(tmp == NULL) { + if(c->lbs) free(c->lbs); + c->lb_num = 0; + return 0; + } + c->lbs = tmp; + c->lbs[n].data_base = ((uint8_t **)data)[0]; + c->lbs[n].data = ((uint8_t **)data)[1]; + c->lbs[n].lb = nr; + break; + case MapCache: + for(n = 0; n < c->map_num; n++) { + if(c->maps[n].lbn == nr) { + /* replace with new data */ + c->maps[n] = *(struct icbmap *)data; + c->maps[n].lbn = nr; + return 1; + } + } + c->map_num++; + tmp = realloc(c->maps, c->map_num * sizeof(struct icbmap)); + /* + Log3(ctx, "realloc maps: %d * %d = %d\n", + c->map_num, sizeof(struct icbmap), + c->map_num * sizeof(struct icbmap)); + */ + if(tmp == NULL) { + if(c->maps) free(c->maps); + c->map_num = 0; + return 0; + } + c->maps = tmp; + c->maps[n] = *(struct icbmap *)data; + c->maps[n].lbn = nr; + break; + default: + return 0; + } + + return 1; +} + + +/* For direct data access, LSB first */ +#define GETN1(p) ((uint8_t)data[p]) +#define GETN2(p) ((uint16_t)data[p] | ((uint16_t)data[(p) + 1] << 8)) +#define GETN3(p) ((uint32_t)data[p] | ((uint32_t)data[(p) + 1] << 8) \ + | ((uint32_t)data[(p) + 2] << 16)) +#define GETN4(p) ((uint32_t)data[p] \ + | ((uint32_t)data[(p) + 1] << 8) \ + | ((uint32_t)data[(p) + 2] << 16) \ + | ((uint32_t)data[(p) + 3] << 24)) +/* This is wrong with regard to endianness */ +#define GETN(p, n, target) memcpy(target, &data[p], n) + +static int Unicodedecode( uint8_t *data, int len, char *target ) +{ + int p = 1, i = 0; + int err = 0; + + if( ( data[ 0 ] == 8 ) || ( data[ 0 ] == 16 ) ) do { + if( data[ 0 ] == 16 ) err |= data[p++]; /* character cannot be converted to 8bit, return error */ + if( p < len ) { + target[ i++ ] = data[ p++ ]; + } + } while( p < len ); + + target[ i ] = '\0'; + return !err; +} + +static int UDFDescriptor( uint8_t *data, uint16_t *TagID ) +{ + *TagID = GETN2(0); + /* TODO: check CRC 'n stuff */ + return 0; +} + +static int UDFExtentAD( uint8_t *data, uint32_t *Length, uint32_t *Location ) +{ + *Length = GETN4(0); + *Location = GETN4(4); + return 0; +} + +static int UDFShortAD( uint8_t *data, struct AD *ad, + struct Partition *partition ) +{ + ad->Length = GETN4(0); + ad->Flags = ad->Length >> 30; + ad->Length &= 0x3FFFFFFF; + ad->Location = GETN4(4); + ad->Partition = partition->Number; /* use number of current partition */ + return 0; +} + +static int UDFLongAD( uint8_t *data, struct AD *ad ) +{ + ad->Length = GETN4(0); + ad->Flags = ad->Length >> 30; + ad->Length &= 0x3FFFFFFF; + ad->Location = GETN4(4); + ad->Partition = GETN2(8); + /* GETN(10, 6, Use); */ + return 0; +} + +static int UDFExtAD( uint8_t *data, struct AD *ad ) +{ + ad->Length = GETN4(0); + ad->Flags = ad->Length >> 30; + ad->Length &= 0x3FFFFFFF; + ad->Location = GETN4(12); + ad->Partition = GETN2(16); + /* GETN(10, 6, Use); */ + return 0; +} + +static int UDFICB( uint8_t *data, uint8_t *FileType, uint16_t *Flags ) +{ + *FileType = GETN1(11); + *Flags = GETN2(18); + return 0; +} + + +static int UDFPartition( uint8_t *data, uint16_t *Flags, uint16_t *Number, + char *Contents, uint32_t *Start, uint32_t *Length ) +{ + *Flags = GETN2(20); + *Number = GETN2(22); + GETN(24, 32, Contents); + *Start = GETN4(188); + *Length = GETN4(192); + return 0; +} + +/** + * Reads the volume descriptor and checks the parameters. Returns 0 on OK, 1 + * on error. + */ +static int UDFLogVolume( uint8_t *data ) +{ + uint32_t lbsize; + lbsize = GETN4(212); /* should be 2048 */ + /* MT_L = GETN4(264); */ /* should be 6 */ + /* N_PM = GETN4(268); */ /* should be 1 */ + if (lbsize != DVD_VIDEO_LB_LEN) + return 1; + + return 0; +} + +static int UDFFileEntry( uint8_t *data, uint8_t *FileType, + struct Partition *partition, struct AD *ad ) +{ + uint16_t flags; + uint32_t L_EA, L_AD; + unsigned int p; + struct AD tmpad; + + UDFICB( &data[ 16 ], FileType, &flags ); + + /* Init ad for an empty file (i.e. there isn't a AD, L_AD == 0 ) */ + ad->Length = GETN4( 60 ); /* Really 8 bytes a 56 */ + ad->Flags = 0; + ad->Location = 0; /* what should we put here? */ + ad->Partition = partition->Number; /* use number of current partition */ + + L_EA = GETN4( 168 ); + L_AD = GETN4( 172 ); + + if (176 + L_EA + L_AD > DVD_VIDEO_LB_LEN) + return 0; + + p = 176 + L_EA; + while( p < 176 + L_EA + L_AD ) { + switch( flags & 0x0007 ) { + case 0: + UDFShortAD( &data[ p ], &tmpad, partition ); + if( ad->Location == 0 ) /* We do not support more than one AD */ + *ad = tmpad; /* This was exploited by copy protections adding empty AD */ + p += 8; + break; + case 1: /* FIXME ? UDF 2.60 2.3.7.1 Only Short Allocation Descriptors shall be used */ + UDFLongAD( &data[ p ], ad ); + p += 16; + break; + case 2: + UDFExtAD( &data[ p ], ad ); + p += 20; + break; + case 3: + switch( L_AD ) { + case 8: + UDFShortAD( &data[ p ], ad, partition ); + break; + case 16: + UDFLongAD( &data[ p ], ad ); + break; + case 20: + UDFExtAD( &data[ p ], ad ); + break; + } + p += L_AD; + break; + default: + p += L_AD; + break; + } + } + return 0; +} + +static int UDFFileIdentifier( uint8_t *data, uint8_t *FileCharacteristics, + char *FileName, struct AD *FileICB ) +{ + uint8_t L_FI; + uint16_t L_IU; + + *FileCharacteristics = GETN1(18); + L_FI = GETN1(19); + UDFLongAD(&data[20], FileICB); + L_IU = GETN2(36); + if (L_FI) { + if (!Unicodedecode(&data[38 + L_IU], L_FI, FileName)) FileName[0] = 0; + } else FileName[0] = '\0'; + return 4 * ((38 + L_FI + L_IU + 3) / 4); +} + +/** + * Maps ICB to FileAD + * ICB: Location of ICB of directory to scan + * FileType: Type of the file + * File: Location of file the ICB is pointing to + * return 1 on success, 0 on error; + */ +static int UDFMapICB( dvd_reader_t *ctx, struct AD ICB, uint8_t *FileType, + struct Partition *partition, struct AD *File ) +{ + uint8_t LogBlock_base[DVD_VIDEO_LB_LEN + 2048]; + uint8_t *LogBlock = (uint8_t *)(((uintptr_t)LogBlock_base & ~((uintptr_t)2047)) + 2048); + uint32_t lbnum; + uint16_t TagID; + struct icbmap tmpmap; + int ret; + + lbnum = partition->Start + ICB.Location; + tmpmap.lbn = lbnum; + if(GetUDFCache(ctx, MapCache, lbnum, &tmpmap)) { + *FileType = tmpmap.filetype; + memcpy(File, &tmpmap.file, sizeof(tmpmap.file)); + return 1; + } + + do { + ret = DVDReadLBUDF( ctx, lbnum++, 1, LogBlock, 0 ); + if( ret < 0 ) { + return ret; + } + else if( ret == 0 ) { + TagID = 0; + } + else { + UDFDescriptor( LogBlock, &TagID ); + } + + if( TagID == FileEntry ) { + UDFFileEntry( LogBlock, FileType, partition, File ); + memcpy(&tmpmap.file, File, sizeof(tmpmap.file)); + tmpmap.filetype = *FileType; + SetUDFCache(ctx, MapCache, tmpmap.lbn, &tmpmap); + return 1; + }; + } while( ( lbnum <= partition->Start + ICB.Location + ( ICB.Length - 1 ) + / DVD_VIDEO_LB_LEN ) && ( TagID != FileEntry ) ); + + return 0; +} + +/** + * Dir: Location of directory to scan + * FileName: Name of file to look for + * FileICB: Location of ICB of the found file + * return 1 on success, 0 on error; + */ +static int UDFScanDir( dvd_reader_t *ctx, struct AD Dir, char *FileName, + struct Partition *partition, struct AD *FileICB, + int cache_file_info) +{ + char filename[ MAX_UDF_FILE_NAME_LEN ]; + uint8_t directory_base[ 2 * DVD_VIDEO_LB_LEN + 2048]; + uint8_t *directory = (uint8_t *)(((uintptr_t)directory_base & ~((uintptr_t)2047)) + 2048); + uint32_t lbnum; + uint16_t TagID; + uint8_t filechar; + unsigned int p; + uint8_t *cached_dir_base = NULL, *cached_dir; + uint32_t dir_lba; + struct AD tmpICB; + int ret; + + /* Scan dir for ICB of file */ + lbnum = partition->Start + Dir.Location; + + if(DVDUDFCacheLevel(ctx, -1) > 0) { + int found = 0; + int in_cache = 0; + + /* caching */ + + if(!GetUDFCache(ctx, LBUDFCache, lbnum, &cached_dir)) { + dir_lba = (Dir.Length + DVD_VIDEO_LB_LEN) / DVD_VIDEO_LB_LEN; + if((cached_dir_base = malloc(dir_lba * DVD_VIDEO_LB_LEN + 2048)) == NULL) + return 0; + cached_dir = (uint8_t *)(((uintptr_t)cached_dir_base & ~((uintptr_t)2047)) + 2048); + ret = DVDReadLBUDF( ctx, lbnum, dir_lba, cached_dir, 0); + if( ret <= 0 ) { + free(cached_dir_base); + cached_dir_base = NULL; + cached_dir = NULL; + if( ret < 0 ) + return ret; + } + /* + if(cached_dir) { + Log3(ctx, "malloc dir: %d", dir_lba * DVD_VIDEO_LB_LEN); + } + */ + { + uint8_t *data[2]; + data[0] = cached_dir_base; + data[1] = cached_dir; + SetUDFCache(ctx, LBUDFCache, lbnum, data); + } + } else + in_cache = 1; + + if(cached_dir == NULL) { + free(cached_dir_base); + return 0; + } + + p = 0; + + while( p < Dir.Length ) { + + UDFDescriptor( &cached_dir[ p ], &TagID ); + if( TagID == FileIdentifierDescriptor ) { + p += UDFFileIdentifier( &cached_dir[ p ], &filechar, + filename, &tmpICB ); + if(cache_file_info && !in_cache) { + uint8_t tmpFiletype; + struct AD tmpFile; + + if( !strcasecmp( FileName, filename ) ) { + memcpy(FileICB, &tmpICB, sizeof(tmpICB)); + found = 1; + } + if(!UDFMapICB(ctx, tmpICB, &tmpFiletype, partition, &tmpFile)) + return 0; + + } else { + if( !strcasecmp( FileName, filename ) ) { + memcpy(FileICB, &tmpICB, sizeof(tmpICB)); + return 1; + } + } + } else { + if(cache_file_info && (!in_cache) && found) + return 1; + return 0; + } + } + if(cache_file_info && (!in_cache) && found) + return 1; + return 0; + } + + if( DVDReadLBUDF( ctx, lbnum, 2, directory, 0 ) <= 0 ) + return 0; + + p = 0; + while( p < Dir.Length ) { + if( p > DVD_VIDEO_LB_LEN ) { + ++lbnum; + p -= DVD_VIDEO_LB_LEN; + Dir.Length -= DVD_VIDEO_LB_LEN; + if( DVDReadLBUDF( ctx, lbnum, 2, directory, 0 ) <= 0 ) { + return 0; + } + } + UDFDescriptor( &directory[ p ], &TagID ); + if( TagID == FileIdentifierDescriptor ) { + p += UDFFileIdentifier( &directory[ p ], &filechar, + filename, FileICB ); + if( !strcasecmp( FileName, filename ) ) { + return 1; + } + } else + return 0; + } + + return 0; +} + + +static int UDFGetAVDP( dvd_reader_t *ctx, + struct avdp_t *avdp) +{ + uint8_t Anchor_base[ DVD_VIDEO_LB_LEN + 2048 ]; + uint8_t *Anchor = (uint8_t *)(((uintptr_t)Anchor_base & ~((uintptr_t)2047)) + 2048); + uint32_t lbnum, MVDS_location, MVDS_length; + uint16_t TagID; + uint32_t lastsector; + int terminate; + struct avdp_t; + int ret; + + if(GetUDFCache(ctx, AVDPCache, 0, avdp)) + return 1; + + /* Find Anchor */ + lastsector = 0; + lbnum = 256; /* Try #1, prime anchor */ + terminate = 0; + + for(;;) { + ret = DVDReadLBUDF( ctx, lbnum, 1, Anchor, 0 ); + if( ret < 0 ) { + return ret; + } + else if( ret == 0 ) { + TagID = 0; + } + else { + UDFDescriptor( Anchor, &TagID ); + } + if (TagID != AnchorVolumeDescriptorPointer) { + /* Not an anchor */ + if( terminate ) return 0; /* Final try failed */ + + if( lastsector ) { + /* We already found the last sector. Try #3, alternative + * backup anchor. If that fails, don't try again. + */ + lbnum = lastsector; + terminate = 1; + } else { + /* TODO: Find last sector of the disc (this is optional). */ + if( lastsector ) + /* Try #2, backup anchor */ + lbnum = lastsector - 256; + else + /* Unable to find last sector */ + return 0; + } + } else + /* It's an anchor! We can leave */ + break; + } + /* Main volume descriptor */ + UDFExtentAD( &Anchor[ 16 ], &MVDS_length, &MVDS_location ); + avdp->mvds.location = MVDS_location; + avdp->mvds.length = MVDS_length; + + /* Backup volume descriptor */ + UDFExtentAD( &Anchor[ 24 ], &MVDS_length, &MVDS_location ); + avdp->rvds.location = MVDS_location; + avdp->rvds.length = MVDS_length; + + SetUDFCache(ctx, AVDPCache, 0, avdp); + + return 1; +} + +/** + * Looks for partition on the disc. Returns 1 if partition found, 0 on error. + * partnum: Number of the partition, starting at 0. + * part: structure to fill with the partition information + */ +static int UDFFindPartition( dvd_reader_t *ctx, int partnum, + struct Partition *part ) +{ + uint8_t LogBlock_base[ DVD_VIDEO_LB_LEN + 2048 ]; + uint8_t *LogBlock = (uint8_t *)(((uintptr_t)LogBlock_base & ~((uintptr_t)2047)) + 2048); + uint32_t lbnum, MVDS_location, MVDS_length; + uint16_t TagID; + int i, volvalid, ret; + struct avdp_t avdp; + + if(!UDFGetAVDP(ctx, &avdp)) + return 0; + + /* Main volume descriptor */ + MVDS_location = avdp.mvds.location; + MVDS_length = avdp.mvds.length; + + part->valid = 0; + volvalid = 0; + i = 1; + do { + /* Find Volume Descriptor */ + lbnum = MVDS_location; + do { + + ret = DVDReadLBUDF( ctx, lbnum++, 1, LogBlock, 0 ); + if( ret < 0 ) { + return ret; + } + else if( ret == 0 ) { + TagID = 0; + } + else { + UDFDescriptor( LogBlock, &TagID ); + } + + if( ( TagID == PartitionDescriptor ) && ( !part->valid ) ) { + /* Partition Descriptor */ + UDFPartition( LogBlock, &part->Flags, &part->Number, + part->Contents, &part->Start, &part->Length ); + part->valid = ( partnum == part->Number ); + } else if( ( TagID == LogicalVolumeDescriptor ) && ( !volvalid ) ) { + /* Logical Volume Descriptor */ + if( UDFLogVolume( LogBlock ) ) { + /* TODO: sector size wrong! */ + } else + volvalid = 1; + } + + } while( ( lbnum <= MVDS_location + ( MVDS_length - 1 ) + / DVD_VIDEO_LB_LEN ) && ( TagID != TerminatingDescriptor ) + && ( ( !part->valid ) || ( !volvalid ) ) ); + + if( ( !part->valid) || ( !volvalid ) ) { + /* Backup volume descriptor */ + MVDS_location = avdp.mvds.location; + MVDS_length = avdp.mvds.length; + } + } while( i-- && ( ( !part->valid ) || ( !volvalid ) ) ); + + /* We only care for the partition, not the volume */ + return part->valid; +} + +uint32_t UDFFindFile( dvd_reader_t *ctx, const char *filename, + uint32_t *filesize ) +{ + uint8_t LogBlock_base[ DVD_VIDEO_LB_LEN + 2048 ]; + uint8_t *LogBlock = (uint8_t *)(((uintptr_t)LogBlock_base & ~((uintptr_t)2047)) + 2048); + uint32_t lbnum; + uint16_t TagID; + struct Partition partition; + struct AD RootICB, File, ICB; + char tokenline[ MAX_UDF_FILE_NAME_LEN ]; + uint8_t filetype; + int ret; + + *filesize = 0; + tokenline[0] = '\0'; + strncat(tokenline, filename, MAX_UDF_FILE_NAME_LEN - 1); + memset(&ICB, 0, sizeof(ICB)); + + if(!(GetUDFCache(ctx, PartitionCache, 0, &partition) && + GetUDFCache(ctx, RootICBCache, 0, &RootICB))) { + /* Find partition, 0 is the standard location for DVD Video.*/ + if( !UDFFindPartition( ctx, 0, &partition ) ) return 0; + SetUDFCache(ctx, PartitionCache, 0, &partition); + + /* Find root dir ICB */ + lbnum = partition.Start; + do { + ret = DVDReadLBUDF( ctx, lbnum++, 1, LogBlock, 0 ); + if( ret < 0 ) { + return ret; + } + else if( ret == 0 ) { + TagID = 0; + } + else { + UDFDescriptor( LogBlock, &TagID ); + } + + /* File Set Descriptor */ + if( TagID == FileSetDescriptor ) /* File Set Descriptor */ + UDFLongAD( &LogBlock[ 400 ], &RootICB ); + } while( ( lbnum < partition.Start + partition.Length ) + && ( TagID != TerminatingDescriptor ) && ( TagID != FileSetDescriptor) ); + + /* Sanity checks. */ + if( TagID != FileSetDescriptor ) + return 0; + if( RootICB.Partition != 0 ) + return 0; + SetUDFCache(ctx, RootICBCache, 0, &RootICB); + } + + /* Find root dir */ + if( !UDFMapICB( ctx, RootICB, &filetype, &partition, &File ) ) + return 0; + if( filetype != 4 ) + return 0; /* Root dir should be dir */ + { + int cache_file_info = 0; + /* Tokenize filepath */ + char *token = strtok(tokenline, "/"); + + while( token != NULL ) { + if( !UDFScanDir( ctx, File, token, &partition, &ICB, + cache_file_info)) + return 0; + if( !UDFMapICB( ctx, ICB, &filetype, &partition, &File ) ) + return 0; + if(!strcmp(token, "VIDEO_TS")) + cache_file_info = 1; + token = strtok( NULL, "/" ); + } + } + + /* Sanity check. */ + if( File.Partition != 0 ) + return 0; + *filesize = File.Length; + /* Hack to not return partition.Start for empty files. */ + if( !File.Location ) + return 0; + else + return partition.Start + File.Location; +} + + + +/** + * Gets a Descriptor . + * Returns 1 if descriptor found, 0 on error. + * id, tagid of descriptor + * bufsize, size of BlockBuf (must be >= DVD_VIDEO_LB_LEN). + */ +static int UDFGetDescriptor( dvd_reader_t *ctx, int id, + uint8_t *descriptor, int bufsize) +{ + uint32_t lbnum, MVDS_location, MVDS_length; + struct avdp_t avdp; + uint16_t TagID; + int i, desc_found = 0, ret; + /* Find Anchor */ + lbnum = 256; /* Try #1, prime anchor */ + if(bufsize < DVD_VIDEO_LB_LEN) + return 0; + + if(!UDFGetAVDP(ctx, &avdp)) + return 0; + + /* Main volume descriptor */ + MVDS_location = avdp.mvds.location; + MVDS_length = avdp.mvds.length; + + i = 1; + do { + /* Find Descriptor */ + lbnum = MVDS_location; + do { + ret = DVDReadLBUDF( ctx, lbnum++, 1, descriptor, 0 ); + if( ret < 0 ) { + return ret; + } + else if( ret == 0 ) { + TagID = 0; + } + else { + UDFDescriptor( descriptor, &TagID ); + } + if( (TagID == id) && ( !desc_found ) ) + /* Descriptor */ + desc_found = 1; + } while( ( lbnum <= MVDS_location + ( MVDS_length - 1 ) + / DVD_VIDEO_LB_LEN ) && ( TagID != TerminatingDescriptor ) + && ( !desc_found) ); + + if( !desc_found ) { + /* Backup volume descriptor */ + MVDS_location = avdp.rvds.location; + MVDS_length = avdp.rvds.length; + } + } while( i-- && ( !desc_found ) ); + + return desc_found; +} + + +static int UDFGetPVD(dvd_reader_t *ctx, struct pvd_t *pvd) +{ + uint8_t pvd_buf_base[DVD_VIDEO_LB_LEN + 2048]; + uint8_t *pvd_buf = (uint8_t *)(((uintptr_t)pvd_buf_base & ~((uintptr_t)2047)) + 2048); + if(GetUDFCache(ctx, PVDCache, 0, pvd)) + return 1; + + if(!UDFGetDescriptor( ctx, 1, pvd_buf, DVD_VIDEO_LB_LEN)) + return 0; + + memcpy(pvd->VolumeIdentifier, &pvd_buf[24], 32); + memcpy(pvd->VolumeSetIdentifier, &pvd_buf[72], 128); + SetUDFCache(ctx, PVDCache, 0, pvd); + return 1; +} + +/** + * Gets the Volume Identifier string, in 8bit unicode (latin-1) + * volid, place to put the string + * volid_size, size of the buffer volid points to + * returns the size of buffer needed for all data + */ +int UDFGetVolumeIdentifier(dvd_reader_t *ctx, char *volid, + unsigned int volid_size) +{ + struct pvd_t pvd; + unsigned int volid_len; + + /* get primary volume descriptor */ + if(!UDFGetPVD(ctx, &pvd)) + return 0; + + volid_len = pvd.VolumeIdentifier[31]; + if(volid_len > 31) + /* this field is only 32 bytes something is wrong */ + volid_len = 31; + if(volid_size > volid_len) + volid_size = volid_len; + Unicodedecode(pvd.VolumeIdentifier, volid_size, volid); + + return volid_len; +} + +/** + * Gets the Volume Set Identifier, as a 128-byte dstring (not decoded) + * WARNING This is not a null terminated string + * volsetid, place to put the data + * volsetid_size, size of the buffer volsetid points to + * the buffer should be >=128 bytes to store the whole volumesetidentifier + * returns the size of the available volsetid information (128) + * or 0 on error + */ +int UDFGetVolumeSetIdentifier(dvd_reader_t *ctx, uint8_t *volsetid, + unsigned int volsetid_size) +{ + struct pvd_t pvd; + + /* get primary volume descriptor */ + if(!UDFGetPVD(ctx, &pvd)) + return 0; + + + if(volsetid_size > 128) + volsetid_size = 128; + + memcpy(volsetid, pvd.VolumeSetIdentifier, volsetid_size); + + return 128; +} diff --git a/libdvdread-embedded/src/dvdread/bitreader.h b/libdvdread-embedded/src/dvdread/bitreader.h new file mode 100644 index 0000000..801e3a9 --- /dev/null +++ b/libdvdread-embedded/src/dvdread/bitreader.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2000, 2001, 2002 Håkan Hjort . + * + * This file is part of libdvdread. + * + * libdvdread 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 of the License, or + * (at your option) any later version. + * + * libdvdread 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 libdvdread; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef LIBDVDREAD_BITREADER_H +#define LIBDVDREAD_BITREADER_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + const uint8_t *start; + uint32_t byte_position; + uint32_t bit_position; +} getbits_state_t; + +int dvdread_getbits_init(getbits_state_t *state, const uint8_t *start); +uint32_t dvdread_getbits(getbits_state_t *state, uint32_t number_of_bits); + +#ifdef __cplusplus +}; +#endif +#endif /* LIBDVDREAD_BITREADER_H */ diff --git a/libdvdread-embedded/src/dvdread/dvd_reader.h b/libdvdread-embedded/src/dvdread/dvd_reader.h new file mode 100644 index 0000000..54ef5dd --- /dev/null +++ b/libdvdread-embedded/src/dvdread/dvd_reader.h @@ -0,0 +1,365 @@ +/* + * Copyright (C) 2001, 2002 Billy Biggs , + * Håkan Hjort , + * Björn Englund + * + * This file is part of libdvdread. + * + * libdvdread 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 of the License, or + * (at your option) any later version. + * + * libdvdread 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 libdvdread; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef LIBDVDREAD_DVD_READER_H +#define LIBDVDREAD_DVD_READER_H + +#ifdef _MSC_VER +#include + +#include +#include +#endif + +#include +#include +#include + +/** + * The DVD access interface. + * + * This file contains the functions that form the interface for + * reading files located on a DVD. + */ + +/** + * The current version. + */ +#include "version.h" + +/** + * The length of one Logical Block of a DVD. + */ +#define DVD_VIDEO_LB_LEN 2048 + +/** + * Maximum length of filenames allowed in UDF. + */ +#define MAX_UDF_FILE_NAME_LEN 2048 + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Opaque type that is used as a handle for one instance of an opened DVD. + */ +typedef struct dvd_reader_s dvd_reader_t; +typedef struct dvd_reader_device_s dvd_reader_device_t; + +/** + * Opaque type for a file read handle, much like a normal fd or FILE *. + */ +typedef struct dvd_file_s dvd_file_t; + +struct dvd_reader_stream_cb +{ + int ( *pf_seek ) ( void *p_stream, uint64_t i_pos); + int ( *pf_read ) ( void *p_stream, void* buffer, int i_read); + int ( *pf_readv ) ( void *p_stream, void *p_iovec, int i_blocks); +}; +typedef struct dvd_reader_stream_cb dvd_reader_stream_cb; + +/** + * Custom logger callback for DVDOpen[Stream]2 + * @param private Handle as provided in Open functions + * @param level Log level + * @param fmt Format string + * @param args Arguments list + * pf_log(priv, level, fmt, args); + */ +typedef enum +{ + DVD_LOGGER_LEVEL_INFO, + DVD_LOGGER_LEVEL_ERROR, + DVD_LOGGER_LEVEL_WARN, + DVD_LOGGER_LEVEL_DEBUG, +} dvd_logger_level_t; + +typedef struct +{ + void ( *pf_log ) ( void *, dvd_logger_level_t, const char *, va_list ); +} dvd_logger_cb; + +/** + * Public type that is used to provide statistics on a handle. + */ +typedef struct { + off_t size; /**< Total size of file in bytes */ + int nr_parts; /**< Number of file parts */ + off_t parts_size[9]; /**< Size of each part in bytes */ +} dvd_stat_t; + +/** + * Opens a block device of a DVD-ROM file, or an image file, or a directory + * name for a mounted DVD or HD copy of a DVD. + * The second form of Open function (DVDOpenStream) can be used to + * provide custom stream_cb functions to access the DVD (see libdvdcss). + * + * If the given file is a block device, or is the mountpoint for a block + * device, then that device is used for CSS authentication using libdvdcss. + * If no device is available, then no CSS authentication is performed, + * and we hope that the image is decrypted. + * + * If the path given is a directory, then the files in that directory may be + * in any one of these formats: + * + * path/VIDEO_TS/VTS_01_1.VOB + * path/video_ts/vts_01_1.vob + * path/VTS_01_1.VOB + * path/vts_01_1.vob + * + * @param path Specifies the device, file or directory to be used. + * @param stream is a private handle used by stream_cb + * @param stream_cb is a struct containing seek and read functions + * @return If successful a read handle is returned. Otherwise 0 is returned. + * + * dvd = DVDOpen(path); + * dvd = DVDOpenStream(stream, &stream_cb); + */ +dvd_reader_t *DVDOpen( const char * ); +dvd_reader_t *DVDOpenStream( void *, dvd_reader_stream_cb * ); + +/** + * Same as DVDOpen, but with private handle to be passed back on callbacks + * + * @param path Specifies the device, file or directory to be used. + * @param priv is a private handle + * @param logcb is a custom logger callback struct, or NULL if none needed + * @param stream_cb is a struct containing seek and read functions + * @return If successful a read handle is returned. Otherwise 0 is returned. + * + * dvd = DVDOpen2(priv, logcb, path); + * dvd = DVDOpenStream2(priv, logcb, &stream_cb); + */ +dvd_reader_t *DVDOpen2( void *, const dvd_logger_cb *, const char * ); +dvd_reader_t *DVDOpenStream2( void *, const dvd_logger_cb *, dvd_reader_stream_cb * ); + +/** + * Closes and cleans up the DVD reader object. + * + * You must close all open files before calling this function. + * + * @param dvd A read handle that should be closed. + * + * DVDClose(dvd); + */ +void DVDClose( dvd_reader_t * ); + +/** + * + */ +typedef enum { + DVD_READ_INFO_FILE, /**< VIDEO_TS.IFO or VTS_XX_0.IFO (title) */ + DVD_READ_INFO_BACKUP_FILE, /**< VIDEO_TS.BUP or VTS_XX_0.BUP (title) */ + DVD_READ_MENU_VOBS, /**< VIDEO_TS.VOB or VTS_XX_0.VOB (title) */ + DVD_READ_TITLE_VOBS /**< VTS_XX_[1-9].VOB (title). All files in + the title set are opened and read as a + single file. */ +} dvd_read_domain_t; + +/** + * Stats a file on the DVD given the title number and domain. + * The information about the file is stored in a dvd_stat_t + * which contains information about the size of the file and + * the number of parts in case of a multipart file and the respective + * sizes of the parts. + * A multipart file is for instance VTS_02_1.VOB, VTS_02_2.VOB, VTS_02_3.VOB + * The size of VTS_02_1.VOB will be stored in stat->parts_size[0], + * VTS_02_2.VOB in stat->parts_size[1], ... + * The total size (sum of all parts) is stored in stat->size and + * stat->nr_parts will hold the number of parts. + * Only DVD_READ_TITLE_VOBS (VTS_??_[1-9].VOB) can be multipart files. + * + * This function is only of use if you want to get the size of each file + * in the filesystem. These sizes are not needed to use any other + * functions in libdvdread. + * + * @param dvd A dvd read handle. + * @param titlenum Which Video Title Set should be used, VIDEO_TS is 0. + * @param domain Which domain. + * @param stat Pointer to where the result is stored. + * @return If successful 0, otherwise -1. + * + * int DVDFileStat(dvd, titlenum, domain, stat); + */ +int DVDFileStat(dvd_reader_t *, int, dvd_read_domain_t, dvd_stat_t *); + +/** + * Opens a file on the DVD given the title number and domain. + * + * If the title number is 0, the video manager information is opened + * (VIDEO_TS.[IFO,BUP,VOB]). Returns a file structure which may be + * used for reads, or 0 if the file was not found. + * + * @param dvd A dvd read handle. + * @param titlenum Which Video Title Set should be used, VIDEO_TS is 0. + * @param domain Which domain. + * @return If successful a a file read handle is returned, otherwise 0. + * + * dvd_file = DVDOpenFile(dvd, titlenum, domain); */ +dvd_file_t *DVDOpenFile( dvd_reader_t *, int, dvd_read_domain_t ); + +/** + * Closes a file and frees the associated structure. + * + * @param dvd_file The file read handle to be closed. + * + * DVDCloseFile(dvd_file); + */ +void DVDCloseFile( dvd_file_t * ); + +/** + * Reads block_count number of blocks from the file at the given block offset. + * Returns number of blocks read on success, -1 on error. This call is only + * for reading VOB data, and should not be used when reading the IFO files. + * When reading from an encrypted drive, blocks are decrypted using libdvdcss + * where required. + * + * @param dvd_file A file read handle. + * @param offset Block offset from the start of the file to start reading at. + * @param block_count Number of block to read. + * @param data Pointer to a buffer to write the data into. + * @return Returns number of blocks read on success, -1 on error. + * + * blocks_read = DVDReadBlocks(dvd_file, offset, block_count, data); + */ +ssize_t DVDReadBlocks( dvd_file_t *, int, size_t, unsigned char * ); + +/** + * Seek to the given position in the file. Returns the resulting position in + * bytes from the beginning of the file. The seek position is only used for + * byte reads from the file, the block read call always reads from the given + * offset. + * + * @param dvd_file A file read handle. + * @param seek_offset Byte offset from the start of the file to seek to. + * @return The resulting position in bytes from the beginning of the file. + * + * offset_set = DVDFileSeek(dvd_file, seek_offset); + */ +int32_t DVDFileSeek( dvd_file_t *, int32_t ); + +/** + * Reads the given number of bytes from the file. This call can only be used + * on the information files, and may not be used for reading from a VOB. This + * reads from and increments the current seek position for the file. + * + * @param dvd_file A file read handle. + * @param data Pointer to a buffer to write the data into. + * @param bytes Number of bytes to read. + * @return Returns number of bytes read on success, -1 on error. + * + * bytes_read = DVDReadBytes(dvd_file, data, bytes); + */ +ssize_t DVDReadBytes( dvd_file_t *, void *, size_t ); + +/** + * Returns the file size in blocks. + * + * @param dvd_file A file read handle. + * @return The size of the file in blocks, -1 on error. + * + * blocks = DVDFileSize(dvd_file); + */ +ssize_t DVDFileSize( dvd_file_t * ); + +/** + * Get a unique 128 bit disc ID. + * This is the MD5 sum of VIDEO_TS.IFO and the VTS_0?_0.IFO files + * in title order (those that exist). + * If you need a 'text' representation of the id, print it as a + * hexadecimal number, using lowercase letters, discid[0] first. + * I.e. the same format as the command-line 'md5sum' program uses. + * + * @param dvd A read handle to get the disc ID from + * @param discid The buffer to put the disc ID into. The buffer must + * have room for 128 bits (16 chars). + * @return 0 on success, -1 on error. + */ +int DVDDiscID( dvd_reader_t *, unsigned char * ); + +/** + * Get the UDF VolumeIdentifier and VolumeSetIdentifier + * from the PrimaryVolumeDescriptor. + * + * @param dvd A read handle to get the disc ID from + * @param volid The buffer to put the VolumeIdentifier into. + * The VolumeIdentifier is latin-1 encoded (8bit unicode) + * null terminated and max 32 bytes (including '\0') + * @param volid_size No more than volid_size bytes will be copied to volid. + * If the VolumeIdentifier is truncated because of this + * it will still be null terminated. + * @param volsetid The buffer to put the VolumeSetIdentifier into. + * The VolumeIdentifier is 128 bytes as + * stored in the UDF PrimaryVolumeDescriptor. + * Note that this is not a null terminated string. + * @param volsetid_size At most volsetid_size bytes will be copied to volsetid. + * @return 0 on success, -1 on error. + */ +int DVDUDFVolumeInfo( dvd_reader_t *, char *, unsigned int, + unsigned char *, unsigned int ); + +int DVDFileSeekForce( dvd_file_t *, int offset, int force_size); + +/** + * Get the ISO9660 VolumeIdentifier and VolumeSetIdentifier + * + * * Only use this function as fallback if DVDUDFVolumeInfo returns -1 * + * * this will happen on a disc mastered only with a iso9660 filesystem * + * * All video DVD discs have UDF filesystem * + * + * @param dvd A read handle to get the disc ID from + * @param volid The buffer to put the VolumeIdentifier into. + * The VolumeIdentifier is coded with '0-9','A-Z','_' + * null terminated and max 33 bytes (including '\0') + * @param volid_size No more than volid_size bytes will be copied to volid. + * If the VolumeIdentifier is truncated because of this + * it will still be null terminated. + * @param volsetid The buffer to put the VolumeSetIdentifier into. + * The VolumeIdentifier is 128 bytes as + * stored in the ISO9660 PrimaryVolumeDescriptor. + * Note that this is not a null terminated string. + * @param volsetid_size At most volsetid_size bytes will be copied to volsetid. + * @return 0 on success, -1 on error. + */ +int DVDISOVolumeInfo( dvd_reader_t *, char *, unsigned int, + unsigned char *, unsigned int ); + +/** + * Sets the level of caching that is done when reading from a device + * + * @param dvd A read handle to get the disc ID from + * @param level The level of caching wanted. + * -1 - returns the current setting. + * 0 - UDF Cache turned off. + * 1 - (default level) Pointers to IFO files and some data from + * PrimaryVolumeDescriptor are cached. + * + * @return The level of caching. + */ +int DVDUDFCacheLevel( dvd_reader_t *, int ); + +#ifdef __cplusplus +}; +#endif +#endif /* LIBDVDREAD_DVD_READER_H */ diff --git a/libdvdread-embedded/src/dvdread/dvd_udf.h b/libdvdread-embedded/src/dvdread/dvd_udf.h new file mode 100644 index 0000000..91d5de6 --- /dev/null +++ b/libdvdread-embedded/src/dvdread/dvd_udf.h @@ -0,0 +1,59 @@ +/* + * This code is based on dvdudf by: + * Christian Wolff . + * + * Modifications by: + * Billy Biggs . + * Björn Englund . + * + * dvdudf: parse and read the UDF volume information of a DVD Video + * Copyright (C) 1999 Christian Wolff for convergence integrated media + * GmbH The author can be reached at scarabaeus@convergence.de, the + * project's page is at http://linuxtv.org/dvd/ + * + * This file is part of libdvdread. + * + * libdvdread 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 of the License, or + * (at your option) any later version. + * + * libdvdread 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 libdvdread; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef LIBDVDREAD_DVD_UDF_H +#define LIBDVDREAD_DVD_UDF_H + +#include + +#include "dvdread/dvd_reader.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Looks for a file on the UDF disc/imagefile and returns the block number + * where it begins, or 0 if it is not found. The filename should be an + * absolute pathname on the UDF filesystem, starting with '/'. For example, + * '/VIDEO_TS/VTS_01_1.IFO'. On success, filesize will be set to the size of + * the file in bytes. + */ +uint32_t UDFFindFile( dvd_reader_t *, const char *filename, uint32_t *size ); + +int UDFGetVolumeIdentifier(dvd_reader_t *, + char *volid, unsigned int volid_size); +int UDFGetVolumeSetIdentifier(dvd_reader_t *, + uint8_t *volsetid, unsigned int volsetid_size); + +#ifdef __cplusplus +}; +#endif +#endif /* LIBDVDREAD_DVD_UDF_H */ diff --git a/libdvdread-embedded/src/dvdread/ifo_print.h b/libdvdread-embedded/src/dvdread/ifo_print.h new file mode 100644 index 0000000..c3068cb --- /dev/null +++ b/libdvdread-embedded/src/dvdread/ifo_print.h @@ -0,0 +1,28 @@ +/* + * This file is part of libdvdread. + * + * libdvdread 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 of the License, or + * (at your option) any later version. + * + * libdvdread 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 libdvdread; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef LIBDVDREAD_IFO_PRINT_H +#define LIBDVDREAD_IFO_PRINT_H + +#include +#include "ifo_types.h" + +void ifo_print(dvd_reader_t *dvd, int title); +void dvdread_print_time(dvd_time_t *dtime); + +#endif /* LIBDVDREAD_IFO_PRINT_H */ diff --git a/libdvdread-embedded/src/dvdread/ifo_read.h b/libdvdread-embedded/src/dvdread/ifo_read.h new file mode 100644 index 0000000..df538a8 --- /dev/null +++ b/libdvdread-embedded/src/dvdread/ifo_read.h @@ -0,0 +1,229 @@ +/* + * Copyright (C) 2000, 2001, 2002 Björn Englund , + * Håkan Hjort + * + * This file is part of libdvdread. + * + * libdvdread 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 of the License, or + * (at your option) any later version. + * + * libdvdread 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 libdvdread; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef LIBDVDREAD_IFO_READ_H +#define LIBDVDREAD_IFO_READ_H + +#include "ifo_types.h" +#include "dvdread/dvd_reader.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * handle = ifoOpen(dvd, title); + * + * Opens an IFO and reads in all the data for the IFO file corresponding to the + * given title. If title 0 is given, the video manager IFO file is read. + * Returns a handle to a completely parsed structure. + */ +ifo_handle_t *ifoOpen(dvd_reader_t *, int ); + +/** + * handle = ifoOpenVMGI(dvd); + * + * Opens an IFO and reads in _only_ the vmgi_mat data. This call can be used + * together with the calls below to read in each segment of the IFO file on + * demand. + */ +ifo_handle_t *ifoOpenVMGI(dvd_reader_t *); + +/** + * handle = ifoOpenVTSI(dvd, title); + * + * Opens an IFO and reads in _only_ the vtsi_mat data. This call can be used + * together with the calls below to read in each segment of the IFO file on + * demand. + */ +ifo_handle_t *ifoOpenVTSI(dvd_reader_t *, int); + +/** + * ifoClose(ifofile); + * Cleans up the IFO information. This will free all data allocated for the + * substructures. + */ +void ifoClose(ifo_handle_t *); + +/** + * The following functions are for reading only part of the VMGI/VTSI files. + * Returns 1 if the data was successfully read and 0 on error. + */ + +/** + * okay = ifoRead_PLT_MAIT(ifofile); + * + * Read in the Parental Management Information table, filling the + * ifofile->ptl_mait structure and its substructures. This data is only + * located in the video manager information file. This fills the + * ifofile->ptl_mait structure and all its substructures. + */ +int ifoRead_PTL_MAIT(ifo_handle_t *); + +/** + * okay = ifoRead_VTS_ATRT(ifofile); + * + * Read in the attribute table for the main menu vob, filling the + * ifofile->vts_atrt structure and its substructures. Only located in the + * video manager information file. This fills in the ifofile->vts_atrt + * structure and all its substructures. + */ +int ifoRead_VTS_ATRT(ifo_handle_t *); + +/** + * okay = ifoRead_TT_SRPT(ifofile); + * + * Reads the title info for the main menu, filling the ifofile->tt_srpt + * structure and its substructures. This data is only located in the video + * manager information file. This structure is mandatory in the IFO file. + */ +int ifoRead_TT_SRPT(ifo_handle_t *); + +/** + * okay = ifoRead_VTS_PTT_SRPT(ifofile); + * + * Reads in the part of title search pointer table, filling the + * ifofile->vts_ptt_srpt structure and its substructures. This data is only + * located in the video title set information file. This structure is + * mandatory, and must be included in the VTSI file. + */ +int ifoRead_VTS_PTT_SRPT(ifo_handle_t *); + +/** + * okay = ifoRead_FP_PGC(ifofile); + * + * Reads in the first play program chain data, filling the + * ifofile->first_play_pgc structure. This data is only located in the video + * manager information file (VMGI). This structure is optional. + */ +int ifoRead_FP_PGC(ifo_handle_t *); + +/** + * okay = ifoRead_PGCIT(ifofile); + * + * Reads in the program chain information table for the video title set. Fills + * in the ifofile->vts_pgcit structure and its substructures, which includes + * the data for each program chain in the set. This data is only located in + * the video title set information file. This structure is mandatory, and must + * be included in the VTSI file. + */ +int ifoRead_PGCIT(ifo_handle_t *); + +/** + * okay = ifoRead_PGCI_UT(ifofile); + * + * Reads in the menu PGCI unit table for the menu VOB. For the video manager, + * this corresponds to the VIDEO_TS.VOB file, and for each title set, this + * corresponds to the VTS_XX_0.VOB file. This data is located in both the + * video manager and video title set information files. For VMGI files, this + * fills the ifofile->vmgi_pgci_ut structure and all its substructures. For + * VTSI files, this fills the ifofile->vtsm_pgci_ut structure. + */ +int ifoRead_PGCI_UT(ifo_handle_t *); + +/** + * okay = ifoRead_VTS_TMAPT(ifofile); + * + * Reads in the VTS Time Map Table, this data is only located in the video + * title set information file. This fills the ifofile->vts_tmapt structure + * and all its substructures. When present enables VOBU level time-based + * seeking for One_Sequential_PGC_Titles. + */ +int ifoRead_VTS_TMAPT(ifo_handle_t *); + +/** + * okay = ifoRead_C_ADT(ifofile); + * + * Reads in the cell address table for the menu VOB. For the video manager, + * this corresponds to the VIDEO_TS.VOB file, and for each title set, this + * corresponds to the VTS_XX_0.VOB file. This data is located in both the + * video manager and video title set information files. For VMGI files, this + * fills the ifofile->vmgm_c_adt structure and all its substructures. For VTSI + * files, this fills the ifofile->vtsm_c_adt structure. + */ +int ifoRead_C_ADT(ifo_handle_t *); + +/** + * okay = ifoRead_TITLE_C_ADT(ifofile); + * + * Reads in the cell address table for the video title set corresponding to + * this IFO file. This data is only located in the video title set information + * file. This structure is mandatory, and must be included in the VTSI file. + * This call fills the ifofile->vts_c_adt structure and its substructures. + */ +int ifoRead_TITLE_C_ADT(ifo_handle_t *); + +/** + * okay = ifoRead_VOBU_ADMAP(ifofile); + * + * Reads in the VOBU address map for the menu VOB. For the video manager, this + * corresponds to the VIDEO_TS.VOB file, and for each title set, this + * corresponds to the VTS_XX_0.VOB file. This data is located in both the + * video manager and video title set information files. For VMGI files, this + * fills the ifofile->vmgm_vobu_admap structure and all its substructures. For + * VTSI files, this fills the ifofile->vtsm_vobu_admap structure. + */ +int ifoRead_VOBU_ADMAP(ifo_handle_t *); + +/** + * okay = ifoRead_TITLE_VOBU_ADMAP(ifofile); + * + * Reads in the VOBU address map for the associated video title set. This data + * is only located in the video title set information file. This structure is + * mandatory, and must be included in the VTSI file. Fills the + * ifofile->vts_vobu_admap structure and its substructures. + */ +int ifoRead_TITLE_VOBU_ADMAP(ifo_handle_t *); + +/** + * okay = ifoRead_TXTDT_MGI(ifofile); + * + * Reads in the text data strings for the DVD. Fills the ifofile->txtdt_mgi + * structure and all its substructures. This data is only located in the video + * manager information file. This structure is mandatory, and must be included + * in the VMGI file. + */ +int ifoRead_TXTDT_MGI(ifo_handle_t *); + +/** + * The following functions are used for freeing parsed sections of the + * ifo_handle_t structure and the allocated substructures. The free calls + * below are safe: they will not mind if you attempt to free part of an IFO + * file which was not read in or which does not exist. + */ +void ifoFree_PTL_MAIT(ifo_handle_t *); +void ifoFree_VTS_ATRT(ifo_handle_t *); +void ifoFree_TT_SRPT(ifo_handle_t *); +void ifoFree_VTS_PTT_SRPT(ifo_handle_t *); +void ifoFree_FP_PGC(ifo_handle_t *); +void ifoFree_PGCIT(ifo_handle_t *); +void ifoFree_PGCI_UT(ifo_handle_t *); +void ifoFree_VTS_TMAPT(ifo_handle_t *); +void ifoFree_C_ADT(ifo_handle_t *); +void ifoFree_TITLE_C_ADT(ifo_handle_t *); +void ifoFree_VOBU_ADMAP(ifo_handle_t *); +void ifoFree_TITLE_VOBU_ADMAP(ifo_handle_t *); +void ifoFree_TXTDT_MGI(ifo_handle_t *); + +#ifdef __cplusplus +}; +#endif +#endif /* LIBDVDREAD_IFO_READ_H */ diff --git a/libdvdread-embedded/src/dvdread/ifo_types.h b/libdvdread-embedded/src/dvdread/ifo_types.h new file mode 100644 index 0000000..9293ce7 --- /dev/null +++ b/libdvdread-embedded/src/dvdread/ifo_types.h @@ -0,0 +1,755 @@ +/* + * Copyright (C) 2000, 2001 Björn Englund , + * Håkan Hjort + * + * This file is part of libdvdread. + * + * libdvdread 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 of the License, or + * (at your option) any later version. + * + * libdvdread 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 libdvdread; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef LIBDVDREAD_IFO_TYPES_H +#define LIBDVDREAD_IFO_TYPES_H + +#include +#include "dvdread/dvd_reader.h" + + +#undef ATTRIBUTE_PACKED + +#if defined(__GNUC__) +# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95) +# if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) && !defined(__clang__) +# define ATTRIBUTE_PACKED __attribute__ ((packed,gcc_struct)) +# else +# define ATTRIBUTE_PACKED __attribute__ ((packed)) +# endif +# define PRAGMA_PACK 0 +# endif +#endif + +#if !defined(ATTRIBUTE_PACKED) +#define ATTRIBUTE_PACKED +#define PRAGMA_PACK 1 +#endif + +#if PRAGMA_PACK +#pragma pack(1) +#endif + + +/** + * Common + * + * The following structures are used in both the VMGI and VTSI. + */ + + +/** + * DVD Time Information. + */ +typedef struct { + uint8_t hour; + uint8_t minute; + uint8_t second; + uint8_t frame_u; /* The two high bits are the frame rate. */ +} ATTRIBUTE_PACKED dvd_time_t; + +/** + * Type to store per-command data. + */ +typedef struct { + uint8_t bytes[8]; +} ATTRIBUTE_PACKED vm_cmd_t; +#define COMMAND_DATA_SIZE 8U + + +/** + * Video Attributes. + */ +typedef struct { + unsigned char mpeg_version : 2; + unsigned char video_format : 2; + unsigned char display_aspect_ratio : 2; + unsigned char permitted_df : 2; + + unsigned char line21_cc_1 : 1; + unsigned char line21_cc_2 : 1; + unsigned char unknown1 : 1; + unsigned char bit_rate : 1; + + unsigned char picture_size : 2; + unsigned char letterboxed : 1; + unsigned char film_mode : 1; +} ATTRIBUTE_PACKED video_attr_t; + +/** + * Audio Attributes. + */ +typedef struct { + unsigned char audio_format : 3; + unsigned char multichannel_extension : 1; + unsigned char lang_type : 2; + unsigned char application_mode : 2; + + unsigned char quantization : 2; + unsigned char sample_frequency : 2; + unsigned char unknown1 : 1; + unsigned char channels : 3; + uint16_t lang_code; + uint8_t lang_extension; + uint8_t code_extension; + uint8_t unknown3; + union { + struct ATTRIBUTE_PACKED { + unsigned char unknown4 : 1; + unsigned char channel_assignment : 3; + unsigned char version : 2; + unsigned char mc_intro : 1; /* probably 0: true, 1:false */ + unsigned char mode : 1; /* Karaoke mode 0: solo 1: duet */ + } karaoke; + struct ATTRIBUTE_PACKED { + unsigned char unknown5 : 4; + unsigned char dolby_encoded : 1; /* suitable for surround decoding */ + unsigned char unknown6 : 3; + } surround; + } ATTRIBUTE_PACKED app_info; +} ATTRIBUTE_PACKED audio_attr_t; + + +/** + * MultiChannel Extension + */ +typedef struct { + unsigned char zero1 : 7; + unsigned char ach0_gme : 1; + + unsigned char zero2 : 7; + unsigned char ach1_gme : 1; + + unsigned char zero3 : 4; + unsigned char ach2_gv1e : 1; + unsigned char ach2_gv2e : 1; + unsigned char ach2_gm1e : 1; + unsigned char ach2_gm2e : 1; + + unsigned char zero4 : 4; + unsigned char ach3_gv1e : 1; + unsigned char ach3_gv2e : 1; + unsigned char ach3_gmAe : 1; + unsigned char ach3_se2e : 1; + + unsigned char zero5 : 4; + unsigned char ach4_gv1e : 1; + unsigned char ach4_gv2e : 1; + unsigned char ach4_gmBe : 1; + unsigned char ach4_seBe : 1; + uint8_t zero6[19]; +} ATTRIBUTE_PACKED multichannel_ext_t; + + +/** + * Subpicture Attributes. + */ +typedef struct { + /* + * type: 0 not specified + * 1 language + * 2 other + * coding mode: 0 run length + * 1 extended + * 2 other + * language: indicates language if type == 1 + * lang extension: if type == 1 contains the lang extension + */ + unsigned char code_mode : 3; + unsigned char zero1 : 3; + unsigned char type : 2; + uint8_t zero2; + uint16_t lang_code; + uint8_t lang_extension; + uint8_t code_extension; +} ATTRIBUTE_PACKED subp_attr_t; + + + +/** + * PGC Command Table. + */ +typedef struct { + uint16_t nr_of_pre; + uint16_t nr_of_post; + uint16_t nr_of_cell; + uint16_t last_byte; + vm_cmd_t *pre_cmds; + vm_cmd_t *post_cmds; + vm_cmd_t *cell_cmds; +} ATTRIBUTE_PACKED pgc_command_tbl_t; +#define PGC_COMMAND_TBL_SIZE 8U + +/** + * PGC Program Map + */ +typedef uint8_t pgc_program_map_t; + +/** + * Cell Playback Information. + */ +typedef struct { + unsigned char block_mode : 2; + unsigned char block_type : 2; + unsigned char seamless_play : 1; + unsigned char interleaved : 1; + unsigned char stc_discontinuity: 1; + unsigned char seamless_angle : 1; + unsigned char zero_1 : 1; + unsigned char playback_mode : 1; /**< When set, enter StillMode after each VOBU */ + unsigned char restricted : 1; /**< ?? drop out of fastforward? */ + unsigned char cell_type : 5; /** for karaoke, reserved otherwise */ + uint8_t still_time; + uint8_t cell_cmd_nr; + dvd_time_t playback_time; + uint32_t first_sector; + uint32_t first_ilvu_end_sector; + uint32_t last_vobu_start_sector; + uint32_t last_sector; +} ATTRIBUTE_PACKED cell_playback_t; + +#define BLOCK_TYPE_NONE 0x0 +#define BLOCK_TYPE_ANGLE_BLOCK 0x1 + +#define BLOCK_MODE_NOT_IN_BLOCK 0x0 +#define BLOCK_MODE_FIRST_CELL 0x1 +#define BLOCK_MODE_IN_BLOCK 0x2 +#define BLOCK_MODE_LAST_CELL 0x3 + +/** + * Cell Position Information. + */ +typedef struct { + uint16_t vob_id_nr; + uint8_t zero_1; + uint8_t cell_nr; +} ATTRIBUTE_PACKED cell_position_t; + +/** + * User Operations. + */ +typedef struct { + unsigned char zero : 7; /* 25-31 */ + unsigned char video_pres_mode_change : 1; /* 24 */ + + unsigned char karaoke_audio_pres_mode_change : 1; /* 23 */ + unsigned char angle_change : 1; + unsigned char subpic_stream_change : 1; + unsigned char audio_stream_change : 1; + unsigned char pause_on : 1; + unsigned char still_off : 1; + unsigned char button_select_or_activate : 1; + unsigned char resume : 1; /* 16 */ + + unsigned char chapter_menu_call : 1; /* 15 */ + unsigned char angle_menu_call : 1; + unsigned char audio_menu_call : 1; + unsigned char subpic_menu_call : 1; + unsigned char root_menu_call : 1; + unsigned char title_menu_call : 1; + unsigned char backward_scan : 1; + unsigned char forward_scan : 1; /* 8 */ + + unsigned char next_pg_search : 1; /* 7 */ + unsigned char prev_or_top_pg_search : 1; + unsigned char time_or_chapter_search : 1; + unsigned char go_up : 1; + unsigned char stop : 1; + unsigned char title_play : 1; + unsigned char chapter_search_or_play : 1; + unsigned char title_or_time_play : 1; /* 0 */ +} ATTRIBUTE_PACKED user_ops_t; + +/** + * Program Chain Information. + */ +typedef struct { + uint16_t zero_1; + uint8_t nr_of_programs; + uint8_t nr_of_cells; + dvd_time_t playback_time; + user_ops_t prohibited_ops; + uint16_t audio_control[8]; /* New type? */ + uint32_t subp_control[32]; /* New type? */ + uint16_t next_pgc_nr; + uint16_t prev_pgc_nr; + uint16_t goup_pgc_nr; + uint8_t pg_playback_mode; + uint8_t still_time; + uint32_t palette[16]; /* New type struct {zero_1, Y, Cr, Cb} ? */ + uint16_t command_tbl_offset; + uint16_t program_map_offset; + uint16_t cell_playback_offset; + uint16_t cell_position_offset; + pgc_command_tbl_t *command_tbl; + pgc_program_map_t *program_map; + cell_playback_t *cell_playback; + cell_position_t *cell_position; + int ref_count; +} ATTRIBUTE_PACKED pgc_t; +#define PGC_SIZE 236U + +/** + * Program Chain Information Search Pointer. + */ +typedef struct { + uint8_t entry_id; + unsigned char block_mode : 2; + unsigned char block_type : 2; + unsigned char zero_1 : 4; + uint16_t ptl_id_mask; + uint32_t pgc_start_byte; + pgc_t *pgc; +} ATTRIBUTE_PACKED pgci_srp_t; +#define PGCI_SRP_SIZE 8U + +/** + * Program Chain Information Table. + */ +typedef struct { + uint16_t nr_of_pgci_srp; + uint16_t zero_1; + uint32_t last_byte; + pgci_srp_t *pgci_srp; + int ref_count; +} ATTRIBUTE_PACKED pgcit_t; +#define PGCIT_SIZE 8U + +/** + * Menu PGCI Language Unit. + */ +typedef struct { + uint16_t lang_code; + uint8_t lang_extension; + uint8_t exists; + uint32_t lang_start_byte; + pgcit_t *pgcit; +} ATTRIBUTE_PACKED pgci_lu_t; +#define PGCI_LU_SIZE 8U + +/** + * Menu PGCI Unit Table. + */ +typedef struct { + uint16_t nr_of_lus; + uint16_t zero_1; + uint32_t last_byte; + pgci_lu_t *lu; +} ATTRIBUTE_PACKED pgci_ut_t; +#define PGCI_UT_SIZE 8U + +/** + * Cell Address Information. + */ +typedef struct { + uint16_t vob_id; + uint8_t cell_id; + uint8_t zero_1; + uint32_t start_sector; + uint32_t last_sector; +} ATTRIBUTE_PACKED cell_adr_t; + +/** + * Cell Address Table. + */ +typedef struct { + uint16_t nr_of_vobs; /* VOBs */ + uint16_t zero_1; + uint32_t last_byte; + cell_adr_t *cell_adr_table; /* No explicit size given. */ +} ATTRIBUTE_PACKED c_adt_t; +#define C_ADT_SIZE 8U + +/** + * VOBU Address Map. + */ +typedef struct { + uint32_t last_byte; + uint32_t *vobu_start_sectors; +} ATTRIBUTE_PACKED vobu_admap_t; +#define VOBU_ADMAP_SIZE 4U + + + + +/** + * VMGI + * + * The following structures relate to the Video Manager. + */ + +/** + * Video Manager Information Management Table. + */ +typedef struct { + char vmg_identifier[12]; + uint32_t vmg_last_sector; + uint8_t zero_1[12]; + uint32_t vmgi_last_sector; + uint8_t zero_2; + uint8_t specification_version; + uint32_t vmg_category; + uint16_t vmg_nr_of_volumes; + uint16_t vmg_this_volume_nr; + uint8_t disc_side; + uint8_t zero_3[19]; + uint16_t vmg_nr_of_title_sets; /* Number of VTSs. */ + char provider_identifier[32]; + uint64_t vmg_pos_code; + uint8_t zero_4[24]; + uint32_t vmgi_last_byte; + uint32_t first_play_pgc; + uint8_t zero_5[56]; + uint32_t vmgm_vobs; /* sector */ + uint32_t tt_srpt; /* sector */ + uint32_t vmgm_pgci_ut; /* sector */ + uint32_t ptl_mait; /* sector */ + uint32_t vts_atrt; /* sector */ + uint32_t txtdt_mgi; /* sector */ + uint32_t vmgm_c_adt; /* sector */ + uint32_t vmgm_vobu_admap; /* sector */ + uint8_t zero_6[32]; + + video_attr_t vmgm_video_attr; + uint8_t zero_7; + uint8_t nr_of_vmgm_audio_streams; /* should be 0 or 1 */ + audio_attr_t vmgm_audio_attr; + audio_attr_t zero_8[7]; + uint8_t zero_9[17]; + uint8_t nr_of_vmgm_subp_streams; /* should be 0 or 1 */ + subp_attr_t vmgm_subp_attr; + subp_attr_t zero_10[27]; /* XXX: how much 'padding' here? */ +} ATTRIBUTE_PACKED vmgi_mat_t; + +typedef struct { + unsigned char zero_1 : 1; + unsigned char multi_or_random_pgc_title : 1; /* 0: one sequential pgc title */ + unsigned char jlc_exists_in_cell_cmd : 1; + unsigned char jlc_exists_in_prepost_cmd : 1; + unsigned char jlc_exists_in_button_cmd : 1; + unsigned char jlc_exists_in_tt_dom : 1; + unsigned char chapter_search_or_play : 1; /* UOP 1 */ + unsigned char title_or_time_play : 1; /* UOP 0 */ +} ATTRIBUTE_PACKED playback_type_t; + +/** + * Title Information. + */ +typedef struct { + playback_type_t pb_ty; + uint8_t nr_of_angles; + uint16_t nr_of_ptts; + uint16_t parental_id; + uint8_t title_set_nr; + uint8_t vts_ttn; + uint32_t title_set_sector; +} ATTRIBUTE_PACKED title_info_t; + +/** + * PartOfTitle Search Pointer Table. + */ +typedef struct { + uint16_t nr_of_srpts; + uint16_t zero_1; + uint32_t last_byte; + title_info_t *title; +} ATTRIBUTE_PACKED tt_srpt_t; +#define TT_SRPT_SIZE 8U + + +/** + * Parental Management Information Unit Table. + * Level 1 (US: G), ..., 7 (US: NC-17), 8 + */ +#define PTL_MAIT_NUM_LEVEL 8 +typedef uint16_t pf_level_t[PTL_MAIT_NUM_LEVEL]; + +/** + * Parental Management Information Unit Table. + */ +typedef struct { + uint16_t country_code; + uint16_t zero_1; + uint16_t pf_ptl_mai_start_byte; + uint16_t zero_2; + pf_level_t *pf_ptl_mai; /* table of (nr_of_vtss + 1), video_ts is first */ +} ATTRIBUTE_PACKED ptl_mait_country_t; +#define PTL_MAIT_COUNTRY_SIZE 8U + +/** + * Parental Management Information Table. + */ +typedef struct { + uint16_t nr_of_countries; + uint16_t nr_of_vtss; + uint32_t last_byte; + ptl_mait_country_t *countries; +} ATTRIBUTE_PACKED ptl_mait_t; +#define PTL_MAIT_SIZE 8U + +/** + * Video Title Set Attributes. + */ +typedef struct { + uint32_t last_byte; + uint32_t vts_cat; + + video_attr_t vtsm_vobs_attr; + uint8_t zero_1; + uint8_t nr_of_vtsm_audio_streams; /* should be 0 or 1 */ + audio_attr_t vtsm_audio_attr; + audio_attr_t zero_2[7]; + uint8_t zero_3[16]; + uint8_t zero_4; + uint8_t nr_of_vtsm_subp_streams; /* should be 0 or 1 */ + subp_attr_t vtsm_subp_attr; + subp_attr_t zero_5[27]; + + uint8_t zero_6[2]; + + video_attr_t vtstt_vobs_video_attr; + uint8_t zero_7; + uint8_t nr_of_vtstt_audio_streams; + audio_attr_t vtstt_audio_attr[8]; + uint8_t zero_8[16]; + uint8_t zero_9; + uint8_t nr_of_vtstt_subp_streams; + subp_attr_t vtstt_subp_attr[32]; +} ATTRIBUTE_PACKED vts_attributes_t; +#define VTS_ATTRIBUTES_SIZE 542U +#define VTS_ATTRIBUTES_MIN_SIZE 356U + +/** + * Video Title Set Attribute Table. + */ +typedef struct { + uint16_t nr_of_vtss; + uint16_t zero_1; + uint32_t last_byte; + vts_attributes_t *vts; + uint32_t *vts_atrt_offsets; /* offsets table for each vts_attributes */ +} ATTRIBUTE_PACKED vts_atrt_t; +#define VTS_ATRT_SIZE 8U + +/** + * Text Data. (Incomplete) + */ +typedef struct { + uint32_t last_byte; /* offsets are relative here */ + uint16_t offsets[100]; /* == nr_of_srpts + 1 (first is disc title) */ +#if 0 + uint16_t unknown; /* 0x48 ?? 0x48 words (16bit) info following */ + uint16_t zero_1; + + uint8_t type_of_info; /* ?? 01 == disc, 02 == Title, 04 == Title part */ + uint8_t unknown1; + uint8_t unknown2; + uint8_t unknown3; + uint8_t unknown4; /* ?? always 0x30 language?, text format? */ + uint8_t unknown5; + uint16_t offset; /* from first */ + + char text[12]; /* ended by 0x09 */ +#endif +} ATTRIBUTE_PACKED txtdt_t; + +/** + * Text Data Language Unit. (Incomplete) + */ +typedef struct { + uint16_t lang_code; + uint8_t zero_1; + uint8_t char_set; /* 0x00 reserved Unicode, 0x01 ISO 646, 0x10 JIS Roman & JIS Kanji, 0x11 ISO 8859-1, 0x12 Shift JIS Kanji */ + uint32_t txtdt_start_byte; /* prt, rel start of vmg_txtdt_mgi */ + txtdt_t *txtdt; +} ATTRIBUTE_PACKED txtdt_lu_t; +#define TXTDT_LU_SIZE 8U + +/** + * Text Data Manager Information. (Incomplete) + */ +typedef struct { + char disc_name[12]; + uint16_t unknown1; + uint16_t nr_of_language_units; + uint32_t last_byte; + txtdt_lu_t *lu; +} ATTRIBUTE_PACKED txtdt_mgi_t; +#define TXTDT_MGI_SIZE 20U + + +/** + * VTS + * + * Structures relating to the Video Title Set (VTS). + */ + +/** + * Video Title Set Information Management Table. + */ +typedef struct { + char vts_identifier[12]; + uint32_t vts_last_sector; + uint8_t zero_1[12]; + uint32_t vtsi_last_sector; + uint8_t zero_2; + uint8_t specification_version; + uint32_t vts_category; + uint16_t zero_3; + uint16_t zero_4; + uint8_t zero_5; + uint8_t zero_6[19]; + uint16_t zero_7; + uint8_t zero_8[32]; + uint64_t zero_9; + uint8_t zero_10[24]; + uint32_t vtsi_last_byte; + uint32_t zero_11; + uint8_t zero_12[56]; + uint32_t vtsm_vobs; /* sector */ + uint32_t vtstt_vobs; /* sector */ + uint32_t vts_ptt_srpt; /* sector */ + uint32_t vts_pgcit; /* sector */ + uint32_t vtsm_pgci_ut; /* sector */ + uint32_t vts_tmapt; /* sector */ + uint32_t vtsm_c_adt; /* sector */ + uint32_t vtsm_vobu_admap; /* sector */ + uint32_t vts_c_adt; /* sector */ + uint32_t vts_vobu_admap; /* sector */ + uint8_t zero_13[24]; + + video_attr_t vtsm_video_attr; + uint8_t zero_14; + uint8_t nr_of_vtsm_audio_streams; /* should be 0 or 1 */ + audio_attr_t vtsm_audio_attr; + audio_attr_t zero_15[7]; + uint8_t zero_16[17]; + uint8_t nr_of_vtsm_subp_streams; /* should be 0 or 1 */ + subp_attr_t vtsm_subp_attr; + subp_attr_t zero_17[27]; + uint8_t zero_18[2]; + + video_attr_t vts_video_attr; + uint8_t zero_19; + uint8_t nr_of_vts_audio_streams; + audio_attr_t vts_audio_attr[8]; + uint8_t zero_20[17]; + uint8_t nr_of_vts_subp_streams; + subp_attr_t vts_subp_attr[32]; + uint16_t zero_21; + multichannel_ext_t vts_mu_audio_attr[8]; + /* XXX: how much 'padding' here, if any? */ +} ATTRIBUTE_PACKED vtsi_mat_t; + +/** + * PartOfTitle Unit Information. + */ +typedef struct { + uint16_t pgcn; + uint16_t pgn; +} ATTRIBUTE_PACKED ptt_info_t; + +/** + * PartOfTitle Information. + */ +typedef struct { + uint16_t nr_of_ptts; + ptt_info_t *ptt; +} ATTRIBUTE_PACKED ttu_t; + +/** + * PartOfTitle Search Pointer Table. + */ +typedef struct { + uint16_t nr_of_srpts; + uint16_t zero_1; + uint32_t last_byte; + ttu_t *title; + uint32_t *ttu_offset; /* offset table for each ttu */ +} ATTRIBUTE_PACKED vts_ptt_srpt_t; +#define VTS_PTT_SRPT_SIZE 8U + + +/** + * Time Map Entry. + */ +/* Should this be bit field at all or just the uint32_t? */ +typedef uint32_t map_ent_t; + +/** + * Time Map. + */ +typedef struct { + uint8_t tmu; /* Time unit, in seconds */ + uint8_t zero_1; + uint16_t nr_of_entries; + map_ent_t *map_ent; +} ATTRIBUTE_PACKED vts_tmap_t; +#define VTS_TMAP_SIZE 4U + +/** + * Time Map Table. + */ +typedef struct { + uint16_t nr_of_tmaps; + uint16_t zero_1; + uint32_t last_byte; + vts_tmap_t *tmap; + uint32_t *tmap_offset; /* offset table for each tmap */ +} ATTRIBUTE_PACKED vts_tmapt_t; +#define VTS_TMAPT_SIZE 8U + + +#if PRAGMA_PACK +#pragma pack() +#endif + + +/** + * The following structure defines an IFO file. The structure is divided into + * two parts, the VMGI, or Video Manager Information, which is read from the + * VIDEO_TS.[IFO,BUP] file, and the VTSI, or Video Title Set Information, which + * is read in from the VTS_XX_0.[IFO,BUP] files. + */ +typedef struct { + /* VMGI */ + vmgi_mat_t *vmgi_mat; + tt_srpt_t *tt_srpt; + pgc_t *first_play_pgc; + ptl_mait_t *ptl_mait; + vts_atrt_t *vts_atrt; + txtdt_mgi_t *txtdt_mgi; + + /* Common */ + pgci_ut_t *pgci_ut; + c_adt_t *menu_c_adt; + vobu_admap_t *menu_vobu_admap; + + /* VTSI */ + vtsi_mat_t *vtsi_mat; + vts_ptt_srpt_t *vts_ptt_srpt; + pgcit_t *vts_pgcit; + vts_tmapt_t *vts_tmapt; + c_adt_t *vts_c_adt; + vobu_admap_t *vts_vobu_admap; +} ifo_handle_t; + +#endif /* LIBDVDREAD_IFO_TYPES_H */ diff --git a/libdvdread-embedded/src/dvdread/nav_print.h b/libdvdread-embedded/src/dvdread/nav_print.h new file mode 100644 index 0000000..4960615 --- /dev/null +++ b/libdvdread-embedded/src/dvdread/nav_print.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2001, 2002 Billy Biggs , + * Håkan Hjort + * + * This file is part of libdvdread. + * + * libdvdread 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 of the License, or + * (at your option) any later version. + * + * libdvdread 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 libdvdread; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef LIBDVDREAD_NAV_PRINT_H +#define LIBDVDREAD_NAV_PRINT_H + +#include "nav_types.h" + +/** + * Pretty printing of the NAV packets, PCI and DSI structs. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Prints information contained in the PCI to stdout. + * + * @param pci Pointer to the PCI data structure to be printed. + */ +void navPrint_PCI(pci_t *); + +/** + * Prints information contained in the DSI to stdout. + * + * @param dsi Pointer to the DSI data structure to be printed. + */ +void navPrint_DSI(dsi_t *); + +#ifdef __cplusplus +}; +#endif +#endif /* LIBDVDREAD_NAV_PRINT_H */ diff --git a/libdvdread-embedded/src/dvdread/nav_read.h b/libdvdread-embedded/src/dvdread/nav_read.h new file mode 100644 index 0000000..256fadb --- /dev/null +++ b/libdvdread-embedded/src/dvdread/nav_read.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2000, 2001, 2002 Håkan Hjort . + * + * This file is part of libdvdread. + * + * libdvdread 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 of the License, or + * (at your option) any later version. + * + * libdvdread 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 libdvdread; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef LIBDVDREAD_NAV_READ_H +#define LIBDVDREAD_NAV_READ_H + +#include "nav_types.h" + +/** + * Parsing of NAV data, PCI and DSI parts. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Reads the PCI packet data pointed to into th pci struct. + * + * @param pci Pointer to the PCI data structure to be filled in. + * @param buffer Pointer to the buffer of the on disc PCI data. + */ +void navRead_PCI(pci_t *, unsigned char *); + +/** + * Reads the DSI packet data pointed to into dsi struct. + * + * @param dsi Pointer to the DSI data structure to be filled in. + * @param buffer Pointer to the buffer of the on disc DSI data. + */ +void navRead_DSI(dsi_t *, unsigned char *); + +#ifdef __cplusplus +}; +#endif +#endif /* LIBDVDREAD_NAV_READ_H */ diff --git a/libdvdread-embedded/src/dvdread/nav_types.h b/libdvdread-embedded/src/dvdread/nav_types.h new file mode 100644 index 0000000..3debbee --- /dev/null +++ b/libdvdread-embedded/src/dvdread/nav_types.h @@ -0,0 +1,248 @@ +/* + * Copyright (C) 2000, 2001, 2002 Håkan Hjort + * + * The data structures in this file should represent the layout of the + * pci and dsi packets as they are stored in the stream. Information + * found by reading the source to VOBDUMP is the base for the structure + * and names of these data types. + * + * VOBDUMP: a program for examining DVD .VOB files. + * Copyright 1998, 1999 Eric Smith + * + * VOBDUMP is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 or version 3 as + * published by the Free Software Foundation. Note that I am not + * granting permission to redistribute or modify VOBDUMP under the terms + * of any later version of the General Public License. + * + * This program is distributed in the hope that it will be useful (or at + * least amusing), 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. + */ + +#ifndef LIBDVDREAD_NAV_TYPES_H +#define LIBDVDREAD_NAV_TYPES_H + +#include +#include "ifo_types.h" /* only dvd_time_t, vm_cmd_t and user_ops_t */ + +/* The length including the substream id byte. */ +#define PCI_BYTES 0x3d4 +#define DSI_BYTES 0x3fa + +#define PS2_PCI_SUBSTREAM_ID 0x00 +#define PS2_DSI_SUBSTREAM_ID 0x01 + +/* Remove this */ +#define DSI_START_BYTE 1031 + +/** + * PCI General Information + */ +typedef struct { + uint32_t nv_pck_lbn; /**< sector address of this nav pack */ + uint16_t vobu_cat; /**< 'category' of vobu */ + uint16_t zero1; /**< reserved */ + user_ops_t vobu_uop_ctl; /**< UOP of vobu */ + uint32_t vobu_s_ptm; /**< start presentation time of vobu */ + uint32_t vobu_e_ptm; /**< end presentation time of vobu */ + uint32_t vobu_se_e_ptm; /**< end ptm of sequence end in vobu */ + dvd_time_t e_eltm; /**< Cell elapsed time */ + char vobu_isrc[32]; +} ATTRIBUTE_PACKED pci_gi_t; + +/** + * Non Seamless Angle Information + */ +typedef struct { + uint32_t nsml_agl_dsta[9]; /**< address of destination vobu in AGL_C#n */ +} ATTRIBUTE_PACKED nsml_agli_t; + +/** + * Highlight General Information + * + * For btngrX_dsp_ty the bits have the following meaning: + * 000b: normal 4/3 only buttons + * XX1b: wide (16/9) buttons + * X1Xb: letterbox buttons + * 1XXb: pan&scan buttons + */ +typedef struct { + uint16_t hli_ss; /**< status, only low 2 bits 0: no buttons, 1: different 2: equal 3: eual except for button cmds */ + uint32_t hli_s_ptm; /**< start ptm of hli */ + uint32_t hli_e_ptm; /**< end ptm of hli */ + uint32_t btn_se_e_ptm; /**< end ptm of button select */ + unsigned char zero1 : 2; /**< reserved */ + unsigned char btngr_ns : 2; /**< number of button groups 1, 2 or 3 with 36/18/12 buttons */ + unsigned char zero2 : 1; /**< reserved */ + unsigned char btngr1_dsp_ty : 3; /**< display type of subpic stream for button group 1 */ + unsigned char zero3 : 1; /**< reserved */ + unsigned char btngr2_dsp_ty : 3; /**< display type of subpic stream for button group 2 */ + unsigned char zero4 : 1; /**< reserved */ + unsigned char btngr3_dsp_ty : 3; /**< display type of subpic stream for button group 3 */ + uint8_t btn_ofn; /**< button offset number range 0-255 */ + uint8_t btn_ns; /**< number of valid buttons <= 36/18/12 (low 6 bits) */ + uint8_t nsl_btn_ns; /**< number of buttons selectable by U_BTNNi (low 6 bits) nsl_btn_ns <= btn_ns */ + uint8_t zero5; /**< reserved */ + uint8_t fosl_btnn; /**< forcedly selected button (low 6 bits) */ + uint8_t foac_btnn; /**< forcedly activated button (low 6 bits) */ +} ATTRIBUTE_PACKED hl_gi_t; + + +/** + * Button Color Information Table + * Each entry is a 32bit word that contains the color indices and alpha + * values to use. They are all represented by 4 bit number and stored + * like this [Ci3, Ci2, Ci1, Ci0, A3, A2, A1, A0]. The actual palette + * that the indexes reference is in the PGC. + * @TODO split the uint32_t into a struct + */ +typedef struct { + uint32_t btn_coli[3][2]; /**< [button color number-1][select:0/action:1] */ +} ATTRIBUTE_PACKED btn_colit_t; + +/** + * Button Information + * + * NOTE: I've had to change the structure from the disk layout to get + * the packing to work with Sun's Forte C compiler. + * The 4 and 7 bytes are 'rotated' was: ABC DEF GHIJ is: ABCG DEFH IJ + */ +typedef struct { + unsigned int btn_coln : 2; /**< button color number */ + unsigned int x_start : 10; /**< x start offset within the overlay */ + unsigned int zero1 : 2; /**< reserved */ + unsigned int x_end : 10; /**< x end offset within the overlay */ + + unsigned int auto_action_mode : 2; /**< 0: no, 1: activated if selected */ + unsigned int y_start : 10; /**< y start offset within the overlay */ + unsigned int zero2 : 2; /**< reserved */ + unsigned int y_end : 10; /**< y end offset within the overlay */ + + unsigned int zero3 : 2; /**< reserved */ + unsigned int up : 6; /**< button index when pressing up */ + unsigned int zero4 : 2; /**< reserved */ + unsigned int down : 6; /**< button index when pressing down */ + unsigned int zero5 : 2; /**< reserved */ + unsigned int left : 6; /**< button index when pressing left */ + unsigned int zero6 : 2; /**< reserved */ + unsigned int right : 6; /**< button index when pressing right */ + vm_cmd_t cmd; +} ATTRIBUTE_PACKED btni_t; + +/** + * Highlight Information + */ +typedef struct { + hl_gi_t hl_gi; + btn_colit_t btn_colit; + btni_t btnit[36]; +} ATTRIBUTE_PACKED hli_t; + +/** + * PCI packet + */ +typedef struct { + pci_gi_t pci_gi; + nsml_agli_t nsml_agli; + hli_t hli; + uint8_t zero1[189]; +} ATTRIBUTE_PACKED pci_t; + + + + +/** + * DSI General Information + */ +typedef struct { + uint32_t nv_pck_scr; + uint32_t nv_pck_lbn; /**< sector address of this nav pack */ + uint32_t vobu_ea; /**< end address of this VOBU */ + uint32_t vobu_1stref_ea; /**< end address of the 1st reference image */ + uint32_t vobu_2ndref_ea; /**< end address of the 2nd reference image */ + uint32_t vobu_3rdref_ea; /**< end address of the 3rd reference image */ + uint16_t vobu_vob_idn; /**< VOB Id number that this VOBU is part of */ + uint8_t zero1; /**< reserved */ + uint8_t vobu_c_idn; /**< Cell Id number that this VOBU is part of */ + dvd_time_t c_eltm; /**< Cell elapsed time */ +} ATTRIBUTE_PACKED dsi_gi_t; + +/** + * Seamless Playback Information + */ +typedef struct { + uint16_t category; /**< 'category' of seamless VOBU */ + uint32_t ilvu_ea; /**< end address of interleaved Unit */ + uint32_t ilvu_sa; /**< start address of next interleaved unit */ + uint16_t size; /**< size of next interleaved unit */ + uint32_t vob_v_s_s_ptm; /**< video start ptm in vob */ + uint32_t vob_v_e_e_ptm; /**< video end ptm in vob */ + struct { + uint32_t stp_ptm1; + uint32_t stp_ptm2; + uint32_t gap_len1; + uint32_t gap_len2; + } vob_a[8]; +} ATTRIBUTE_PACKED sml_pbi_t; + +/** + * Seamless Angle Information for one angle + */ +typedef struct { + uint32_t address; /**< offset to next ILVU, high bit is before/after */ + uint16_t size; /**< byte size of the ILVU pointed to by address */ +} ATTRIBUTE_PACKED sml_agl_data_t; + +/** + * Seamless Angle Information + */ +typedef struct { + sml_agl_data_t data[9]; +} ATTRIBUTE_PACKED sml_agli_t; + +/** + * VOBU Search Information + */ +typedef struct { + uint32_t next_video; /**< Next vobu that contains video */ + uint32_t fwda[19]; /**< Forwards, time */ + uint32_t next_vobu; + uint32_t prev_vobu; + uint32_t bwda[19]; /**< Backwards, time */ + uint32_t prev_video; +} ATTRIBUTE_PACKED vobu_sri_t; + +#define SRI_END_OF_CELL 0x3fffffff + +/** + * Synchronous Information + */ +typedef struct { + uint16_t a_synca[8]; /**< offset to first audio packet for this VOBU */ + uint32_t sp_synca[32]; /**< offset to first subpicture packet */ +} ATTRIBUTE_PACKED synci_t; + +/** + * DSI packet + */ +typedef struct { + dsi_gi_t dsi_gi; + sml_pbi_t sml_pbi; + sml_agli_t sml_agli; + vobu_sri_t vobu_sri; + synci_t synci; + uint8_t zero1[471]; +} ATTRIBUTE_PACKED dsi_t; + + +#if PRAGMA_PACK +#pragma pack() +#endif + +#endif /* LIBDVDREAD_NAV_TYPES_H */ diff --git a/libdvdread-embedded/src/dvdread/version.h.in b/libdvdread-embedded/src/dvdread/version.h.in new file mode 100644 index 0000000..0ab1676 --- /dev/null +++ b/libdvdread-embedded/src/dvdread/version.h.in @@ -0,0 +1,37 @@ +/* + * This file is part of libdvdread + * Copyright (C) 2015 VideoLAN + * + * This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * . + */ + +#ifndef DVDREAD_VERSION_H_ +#define DVDREAD_VERSION_H_ + +#define DVDREAD_VERSION_CODE(major, minor, micro) \ + (((major) * 10000) + \ + ((minor) * 100) + \ + ((micro) * 1)) + +#define DVDREAD_VERSION_MAJOR @DVDREAD_VERSION_MAJOR@ +#define DVDREAD_VERSION_MINOR @DVDREAD_VERSION_MINOR@ +#define DVDREAD_VERSION_MICRO @DVDREAD_VERSION_MICRO@ + +#define DVDREAD_VERSION_STRING "@DVDREAD_VERSION_MAJOR@.@DVDREAD_VERSION_MINOR@.@DVDREAD_VERSION_MICRO@" + +#define DVDREAD_VERSION \ + DVDREAD_VERSION_CODE(DVDREAD_VERSION_MAJOR, DVDREAD_VERSION_MINOR, DVDREAD_VERSION_MICRO) + +#endif /* DVDREAD_VERSION_H_ */ diff --git a/libdvdread-embedded/src/dvdread_internal.h b/libdvdread-embedded/src/dvdread_internal.h new file mode 100644 index 0000000..bf4e2e1 --- /dev/null +++ b/libdvdread-embedded/src/dvdread_internal.h @@ -0,0 +1,86 @@ +/* + * This file is part of libdvdread. + * + * libdvdread 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 of the License, or + * (at your option) any later version. + * + * libdvdread 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 libdvdread; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef LIBDVDREAD_DVDREAD_INTERNAL_H +#define LIBDVDREAD_DVDREAD_INTERNAL_H + +#include +#include +#include + +#ifdef _WIN32 +# include +#endif /* _WIN32 */ + +#include "dvdread/dvd_reader.h" +#include "dvdread/ifo_types.h" +#include "logger.h" + +#define container_of(ptr, type, member) \ + ((type *)(((char *)(ptr)) - offsetof(type, member))) + +struct dvd_reader_s +{ + dvd_reader_device_t *rd; + void *priv; /* User provided context */ + dvd_logger_cb logcb; + /* Set 100 flags for BUP fallback, most signifiant left + [0] for upper remaining VTS, [1] for the first Main + 63 VTS */ + uint64_t ifoBUPflags[2]; +}; + +struct ifo_handle_private_s +{ + ifo_handle_t handle; + dvd_reader_t *ctx; + dvd_file_t *file; +}; + +enum TagIdentifier { + /* ECMA 167 3/7.2.1 */ + PrimaryVolumeDescriptor = 1, + AnchorVolumeDescriptorPointer = 2, + VolumeDescriptorPointer = 3, + ImplementationUseVolumeDescriptor = 4, + PartitionDescriptor = 5, + LogicalVolumeDescriptor = 6, + UnallocatedSpaceDescriptor = 7, + TerminatingDescriptor = 8, + LogicalVolumeIntegrityDescriptor = 9, + /* ECMA 167 4/7.2.1 */ + FileSetDescriptor = 256, + FileIdentifierDescriptor = 257, + AllocationExtentDescriptor = 258, + IndirectEntry = 259, + TerminalEntry = 260, + FileEntry = 261, + ExtendedAttributeHeaderDescriptor = 262, + UnallocatedSpaceEntry = 263, + SpaceBitmapDescriptor = 264, + PartitionIntegrityEntry = 265, + ExtendedFileEntry = 266, +}; + +int InternalUDFReadBlocksRaw(const dvd_reader_t *, uint32_t lb_number, + size_t block_count, unsigned char *data, int encrypted); + +void *GetUDFCacheHandle(dvd_reader_t *); +void SetUDFCacheHandle(dvd_reader_t *, void *cache); +void FreeUDFCache(void *cache); + +#endif /* LIBDVDREAD_DVDREAD_INTERNAL_H */ diff --git a/libdvdread-embedded/src/ifo_print.c b/libdvdread-embedded/src/ifo_print.c new file mode 100644 index 0000000..f61a2b3 --- /dev/null +++ b/libdvdread-embedded/src/ifo_print.c @@ -0,0 +1,1209 @@ +/* + * This file is part of libdvdread. + * + * libdvdread 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 of the License, or + * (at your option) any later version. + * + * libdvdread 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 libdvdread; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include +#include +#include +#include +#include +#include +#include + +#include "dvdread/ifo_types.h" +#include "dvdread/ifo_read.h" +#include "dvdread/ifo_print.h" +#include "dvdread_internal.h" +#include "logger.h" + +/* Put this in some other file / package? It's used in nav_print too. */ +static void ifo_print_time(dvd_time_t *dtime) { + const char *rate; + assert((dtime->hour>>4) < 0xa && (dtime->hour&0xf) < 0xa); + assert((dtime->minute>>4) < 0x7 && (dtime->minute&0xf) < 0xa); + assert((dtime->second>>4) < 0x7 && (dtime->second&0xf) < 0xa); + assert((dtime->frame_u&0xf) < 0xa); + + printf("%02x:%02x:%02x.%02x", + dtime->hour, + dtime->minute, + dtime->second, + dtime->frame_u & 0x3f); + switch((dtime->frame_u & 0xc0) >> 6) { + case 1: + rate = "25.00"; + break; + case 3: + rate = "29.97"; + break; + default: + if(dtime->hour == 0 && dtime->minute == 0 + && dtime->second == 0 && dtime->frame_u == 0) + rate = "no"; + else + rate = "(please send a bug report)"; + break; + } + printf(" @ %s fps", rate); +} + +void dvdread_print_time(dvd_time_t *dtime) { + ifo_print_time(dtime); +} + +/* Put this in some other file / package? It's used in nav_print too. + Possibly also by the vm / navigator. */ +static void ifo_print_cmd(int row, vm_cmd_t *command) { + int i; + + printf("(%03d) ", row + 1); + for(i=0;i<8;i++) + printf("%02x ", command->bytes[i]); + printf("| "); +#if 0 + //disabled call of dvdnav function + vm_print_mnemonic(command); +#endif + printf("\n"); +} + +static void ifo_print_video_attributes(video_attr_t *attr) { + + /* The following test is shorter but not correct ISO C, + memcmp(attr,my_friendly_zeros, sizeof(video_attr_t)) */ + if(attr->mpeg_version == 0 + && attr->video_format == 0 + && attr->display_aspect_ratio == 0 + && attr->permitted_df == 0 + && attr->line21_cc_1 == 0 + && attr->line21_cc_2 == 0 + && attr->unknown1 == 0 + && attr->letterboxed == 0 + && attr->film_mode == 0) { + printf("-- Unspecified --"); + return; + } + + switch(attr->mpeg_version) { + case 0: + printf("mpeg1, "); + break; + case 1: + printf("mpeg2, "); + break; + default: + printf("(please send a bug report), "); + } + + switch(attr->video_format) { + case 0: + printf("ntsc, "); + break; + case 1: + printf("pal, "); + break; + default: + printf("(please send a bug report), "); + } + + switch(attr->display_aspect_ratio) { + case 0: + printf("4:3, "); + break; + case 3: + printf("16:9, "); + break; + default: + printf("(please send a bug report), "); + } + + // Wide is always allowed..!!! + switch(attr->permitted_df) { + case 0: + printf("pan&scan+letterboxed, "); + break; + case 1: + printf("only pan&scan, "); //?? + break; + case 2: + printf("only letterboxed, "); + break; + case 3: + printf("not specified, "); + break; + default: + printf("(please send a bug report), "); + } + + if(attr->line21_cc_1 || attr->line21_cc_2) { + printf("NTSC CC "); + if(attr->line21_cc_1) + printf("1, "); + if(attr->line21_cc_2) + printf("2, "); + } + + { + int height = 480; + if(attr->video_format != 0) + height = 576; + switch(attr->picture_size) { + case 0: + printf("720x%d, ", height); + break; + case 1: + printf("704x%d, ", height); + break; + case 2: + printf("352x%d, ", height); + break; + case 3: + printf("352x%d, ", height/2); + break; + default: + printf("(please send a bug report), "); + } + } + + if(attr->letterboxed) { + printf("source letterboxed, "); + } + + if(attr->film_mode) { + printf("film, "); + } else { + printf("video, "); //camera + } + + printf("Unknown1: %x", attr->unknown1); + +} + +static void ifo_print_audio_attributes(audio_attr_t *attr) { + + if(attr->audio_format == 0 + && attr->multichannel_extension == 0 + && attr->lang_type == 0 + && attr->application_mode == 0 + && attr->quantization == 0 + && attr->sample_frequency == 0 + && attr->unknown1 == 0 + && attr->channels == 0 + && attr->lang_extension == 0 + && attr->unknown3 == 0) { + printf("-- Unspecified --"); + return; + } + + switch(attr->audio_format) { + case 0: + printf("ac3 "); + if(attr->quantization != 3) + printf("(please send a bug report) ac3 quant/drc not 3 (%d)", attr->quantization); + break; + case 1: + printf("(please send a bug report) "); + break; + case 2: + printf("mpeg1 "); + /* Falls Through. */ /* to MPEG-2 */ + case 3: + printf("mpeg2ext "); + switch(attr->quantization) { + case 0: + printf("no drc "); + break; + case 1: + printf("drc "); + break; + default: + printf("(please send a bug report) mpeg reserved quant/drc (%d)", attr->quantization); + } + break; + case 4: + printf("lpcm "); + switch(attr->quantization) { + case 0: + printf("16bit "); + break; + case 1: + printf("20bit "); + break; + case 2: + printf("24bit "); + break; + case 3: + printf("(please send a bug report) lpcm reserved quant/drc (%d)", attr->quantization); + break; + } + break; + case 5: + printf("(please send a bug report) "); + break; + case 6: + printf("dts "); + if(attr->quantization != 3) + printf("(please send a bug report) dts quant/drc not 3 (%d)", attr->quantization); + break; + default: + printf("(please send a bug report) "); + } + + if(attr->multichannel_extension) + printf("multichannel_extension "); + + switch(attr->lang_type) { + case 0: + // not specified + if(attr->lang_code != 0 && attr->lang_code != 0xffff) + printf("Lang_code 0x%x, please send a bug report!", attr->lang_code); + break; + case 1: + printf("%c%c ", attr->lang_code>>8, attr->lang_code & 0xff); + break; + default: + printf("(please send a bug report) "); + } + + switch(attr->application_mode) { + case 0: + // not specified + break; + case 1: + printf("karaoke mode "); + break; + case 2: + printf("surround sound mode "); + break; + default: + printf("(please send a bug report) "); + } + + switch(attr->quantization) { + case 0: + printf("16bit "); + break; + case 1: + printf("20bit "); + break; + case 2: + printf("24bit "); + break; + case 3: + printf("drc "); + break; + default: + printf("(please send a bug report) "); + } + + switch(attr->sample_frequency) { + case 0: + printf("48kHz "); + break; + case 1: + printf("??kHz "); + break; + default: + printf("sample_frequency %i (please send a bug report) ", + attr->sample_frequency); + } + + printf("%dCh ", attr->channels + 1); + + switch(attr->lang_extension) { + case 0: + printf("Not specified "); + break; + case 1: // Normal audio + printf("Normal Caption "); + break; + case 2: // visually impaired + printf("Audio for visually impaired "); + break; + case 3: // Directors 1 + printf("Director's comments 1 "); + break; + case 4: // Directors 2 + printf("Director's comments 2 "); + break; + //case 4: // Music score ? + default: + printf("(please send a bug report) "); + } + + printf("Unknown1: %d ", attr->unknown1); + printf("Unknown3: %d ", attr->unknown3); +} + +static void ifo_print_subp_attributes(subp_attr_t *attr) { + + if(attr->type == 0 + && attr->zero1 == 0 + && attr->zero2 == 0 + && attr->lang_code == 0 + && attr->lang_extension== 0) { + printf("-- Unspecified --"); + return; + } + + printf("type %02x ", attr->type); + + if(isalpha((int)(attr->lang_code >> 8)) + && isalpha((int)(attr->lang_code & 0xff))) { + printf("%c%c ", attr->lang_code >> 8, attr->lang_code & 0xff); + } else { + printf("%02x%02x ", 0xff & (unsigned)(attr->lang_code >> 8), + 0xff & (unsigned)(attr->lang_code & 0xff)); + } + + printf("%d ", attr->zero1); + printf("%d ", attr->zero2); + + switch(attr->lang_extension) { + case 0: + printf("Not specified "); + break; + case 1: + printf("Caption with normal size character "); + break; + case 2: + printf("Caption with bigger size character "); + break; + case 3: + printf("Caption for children "); + break; + case 4: + printf("reserved "); + break; + case 5: + printf("Closed Caption with normal size character "); + break; + case 6: + printf("Closed Caption with bigger size character "); + break; + case 7: + printf("Closed Caption for children "); + break; + case 8: + printf("reserved "); + break; + case 9: + printf("Forced Caption"); + break; + case 10: + printf("reserved "); + break; + case 11: + printf("reserved "); + break; + case 12: + printf("reserved "); + break; + case 13: + printf("Director's comments with normal size character "); + break; + case 14: + printf("Director's comments with bigger size character "); + break; + case 15: + printf("Director's comments for children "); + break; + default: + printf("(please send a bug report) "); + } + +} + + +static void ifoPrint_USER_OPS(user_ops_t *user_ops) { + uint32_t uops; + unsigned char *ptr = (unsigned char *)user_ops; + + uops = (*ptr++ << 24); + uops |= (*ptr++ << 16); + uops |= (*ptr++ << 8); + uops |= (*ptr++); + + if(uops == 0) { + printf("None\n"); + } else if(uops == 0x01ffffff) { + printf("All\n"); + } else { + if(user_ops->title_or_time_play) + printf("Title or Time Play, "); + if(user_ops->chapter_search_or_play) + printf("Chapter Search or Play, "); + if(user_ops->title_play) + printf("Title Play, "); + if(user_ops->stop) + printf("Stop, "); + if(user_ops->go_up) + printf("Go Up, "); + if(user_ops->time_or_chapter_search) + printf("Time or Chapter Search, "); + if(user_ops->prev_or_top_pg_search) + printf("Prev or Top PG Search, "); + if(user_ops->next_pg_search) + printf("Next PG Search, "); + if(user_ops->forward_scan) + printf("Forward Scan, "); + if(user_ops->backward_scan) + printf("Backward Scan, "); + if(user_ops->title_menu_call) + printf("Title Menu Call, "); + if(user_ops->root_menu_call) + printf("Root Menu Call, "); + if(user_ops->subpic_menu_call) + printf("SubPic Menu Call, "); + if(user_ops->audio_menu_call) + printf("Audio Menu Call, "); + if(user_ops->angle_menu_call) + printf("Angle Menu Call, "); + if(user_ops->chapter_menu_call) + printf("Chapter Menu Call, "); + if(user_ops->resume) + printf("Resume, "); + if(user_ops->button_select_or_activate) + printf("Button Select or Activate, "); + if(user_ops->still_off) + printf("Still Off, "); + if(user_ops->pause_on) + printf("Pause On, "); + if(user_ops->audio_stream_change) + printf("Audio Stream Change, "); + if(user_ops->subpic_stream_change) + printf("SubPic Stream Change, "); + if(user_ops->angle_change) + printf("Angle Change, "); + if(user_ops->karaoke_audio_pres_mode_change) + printf("Karaoke Audio Pres Mode Change, "); + if(user_ops->video_pres_mode_change) + printf("Video Pres Mode Change, "); + printf("\n"); + } +} + + +static void ifoPrint_VMGI_MAT(vmgi_mat_t *vmgi_mat) { + + printf("VMG Identifier: %.12s\n", vmgi_mat->vmg_identifier); + printf("Last Sector of VMG: %08x\n", vmgi_mat->vmg_last_sector); + printf("Last Sector of VMGI: %08x\n", vmgi_mat->vmgi_last_sector); + printf("Specification version number: %01x.%01x\n", + vmgi_mat->specification_version >> 4, + vmgi_mat->specification_version & 0xf); + /* Byte 2 of 'VMG Category' (00xx0000) is the Region Code */ + printf("VMG Category: %08x (Region Code=%02x)\n", vmgi_mat->vmg_category, ((vmgi_mat->vmg_category >> 16) & 0xff) ^0xff); + printf("VMG Number of Volumes: %i\n", vmgi_mat->vmg_nr_of_volumes); + printf("VMG This Volume: %i\n", vmgi_mat->vmg_this_volume_nr); + printf("Disc side %i\n", vmgi_mat->disc_side); + printf("VMG Number of Title Sets %i\n", vmgi_mat->vmg_nr_of_title_sets); + printf("Provider ID: %.32s\n", vmgi_mat->provider_identifier); + printf("VMG POS Code: %08x", (uint32_t)(vmgi_mat->vmg_pos_code >> 32)); + printf("%08x\n", (uint32_t)vmgi_mat->vmg_pos_code); + printf("End byte of VMGI_MAT: %08x\n", vmgi_mat->vmgi_last_byte); + printf("Start byte of First Play PGC (FP PGC): %08x\n", + vmgi_mat->first_play_pgc); + printf("Start sector of VMGM_VOBS: %08x\n", vmgi_mat->vmgm_vobs); + printf("Start sector of TT_SRPT: %08x\n", vmgi_mat->tt_srpt); + printf("Start sector of VMGM_PGCI_UT: %08x\n", vmgi_mat->vmgm_pgci_ut); + printf("Start sector of PTL_MAIT: %08x\n", vmgi_mat->ptl_mait); + printf("Start sector of VTS_ATRT: %08x\n", vmgi_mat->vts_atrt); + printf("Start sector of TXTDT_MG: %08x\n", vmgi_mat->txtdt_mgi); + printf("Start sector of VMGM_C_ADT: %08x\n", vmgi_mat->vmgm_c_adt); + printf("Start sector of VMGM_VOBU_ADMAP: %08x\n", + vmgi_mat->vmgm_vobu_admap); + printf("Video attributes of VMGM_VOBS: "); + ifo_print_video_attributes(&vmgi_mat->vmgm_video_attr); + printf("\n"); + printf("VMGM Number of Audio attributes: %i\n", + vmgi_mat->nr_of_vmgm_audio_streams); + if(vmgi_mat->nr_of_vmgm_audio_streams > 0) { + printf("\tstream %i status: ", 1); + ifo_print_audio_attributes(&vmgi_mat->vmgm_audio_attr); + printf("\n"); + } + printf("VMGM Number of Sub-picture attributes: %i\n", + vmgi_mat->nr_of_vmgm_subp_streams); + if(vmgi_mat->nr_of_vmgm_subp_streams > 0) { + printf("\tstream %2i status: ", 1); + ifo_print_subp_attributes(&vmgi_mat->vmgm_subp_attr); + printf("\n"); + } +} + + +static void ifoPrint_VTSI_MAT(vtsi_mat_t *vtsi_mat) { + int i; + + printf("VTS Identifier: %.12s\n", vtsi_mat->vts_identifier); + printf("Last Sector of VTS: %08x\n", vtsi_mat->vts_last_sector); + printf("Last Sector of VTSI: %08x\n", vtsi_mat->vtsi_last_sector); + printf("Specification version number: %01x.%01x\n", + vtsi_mat->specification_version>>4, + vtsi_mat->specification_version&0xf); + printf("VTS Category: %08x\n", vtsi_mat->vts_category); + printf("End byte of VTSI_MAT: %08x\n", vtsi_mat->vtsi_last_byte); + printf("Start sector of VTSM_VOBS: %08x\n", vtsi_mat->vtsm_vobs); + printf("Start sector of VTSTT_VOBS: %08x\n", vtsi_mat->vtstt_vobs); + printf("Start sector of VTS_PTT_SRPT: %08x\n", vtsi_mat->vts_ptt_srpt); + printf("Start sector of VTS_PGCIT: %08x\n", vtsi_mat->vts_pgcit); + printf("Start sector of VTSM_PGCI_UT: %08x\n", vtsi_mat->vtsm_pgci_ut); + printf("Start sector of VTS_TMAPT: %08x\n", vtsi_mat->vts_tmapt); + printf("Start sector of VTSM_C_ADT: %08x\n", vtsi_mat->vtsm_c_adt); + printf("Start sector of VTSM_VOBU_ADMAP: %08x\n",vtsi_mat->vtsm_vobu_admap); + printf("Start sector of VTS_C_ADT: %08x\n", vtsi_mat->vts_c_adt); + printf("Start sector of VTS_VOBU_ADMAP: %08x\n", vtsi_mat->vts_vobu_admap); + + printf("Video attributes of VTSM_VOBS: "); + ifo_print_video_attributes(&vtsi_mat->vtsm_video_attr); + printf("\n"); + + printf("VTSM Number of Audio attributes: %i\n", + vtsi_mat->nr_of_vtsm_audio_streams); + if(vtsi_mat->nr_of_vtsm_audio_streams > 0) { + printf("\tstream %i status: ", 1); + ifo_print_audio_attributes(&vtsi_mat->vtsm_audio_attr); + printf("\n"); + } + + printf("VTSM Number of Sub-picture attributes: %i\n", + vtsi_mat->nr_of_vtsm_subp_streams); + if(vtsi_mat->nr_of_vtsm_subp_streams > 0) { + printf("\tstream %2i status: ", 1); + ifo_print_subp_attributes(&vtsi_mat->vtsm_subp_attr); + printf("\n"); + } + + printf("Video attributes of VTS_VOBS: "); + ifo_print_video_attributes(&vtsi_mat->vts_video_attr); + printf("\n"); + + printf("VTS Number of Audio attributes: %i\n", + vtsi_mat->nr_of_vts_audio_streams); + for(i = 0; i < vtsi_mat->nr_of_vts_audio_streams; i++) { + printf("\tstream %i status: ", i); + ifo_print_audio_attributes(&vtsi_mat->vts_audio_attr[i]); + printf("\n"); + } + + printf("VTS Number of Subpicture attributes: %i\n", + vtsi_mat->nr_of_vts_subp_streams); + for(i = 0; i < vtsi_mat->nr_of_vts_subp_streams; i++) { + printf("\tstream %2i status: ", i); + ifo_print_subp_attributes(&vtsi_mat->vts_subp_attr[i]); + printf("\n"); + } +} + + +static void ifoPrint_PGC_COMMAND_TBL(pgc_command_tbl_t *cmd_tbl) { + int i; + + if(cmd_tbl == NULL) { + printf("No Command table present\n"); + return; + } + + printf("Number of Pre commands: %i\n", cmd_tbl->nr_of_pre); + for(i = 0; i < cmd_tbl->nr_of_pre; i++) { + ifo_print_cmd(i, &cmd_tbl->pre_cmds[i]); + } + + printf("Number of Post commands: %i\n", cmd_tbl->nr_of_post); + for(i = 0; i < cmd_tbl->nr_of_post; i++) { + ifo_print_cmd(i, &cmd_tbl->post_cmds[i]); + } + + printf("Number of Cell commands: %i\n", cmd_tbl->nr_of_cell); + for(i = 0; i < cmd_tbl->nr_of_cell; i++) { + ifo_print_cmd(i, &cmd_tbl->cell_cmds[i]); + } +} + + +static void ifoPrint_PGC_PROGRAM_MAP(pgc_program_map_t *program_map, int nr) { + int i; + + if(program_map == NULL) { + printf("No Program map present\n"); + return; + } + + for(i = 0; i < nr; i++) { + printf("Program %3i Entry Cell: %3i\n", i + 1, program_map[i]); + } +} + + +static void ifoPrint_CELL_PLAYBACK(cell_playback_t *cell_playback, int nr) { + int i; + + if(cell_playback == NULL) { + printf("No Cell Playback info present\n"); + return; + } + + for(i=0;inr_of_programs); + printf("Number of Cells: %i\n", pgc->nr_of_cells); + /* Check that time is 0:0:0:0 also if nr_of_programs==0 */ + printf("Playback time: "); + dvdread_print_time(&pgc->playback_time); printf("\n"); + + /* If no programs/no time then does this mean anything? */ + printf("Prohibited user operations: "); + ifoPrint_USER_OPS(&pgc->prohibited_ops); + + for(i = 0; i < 8; i++) { + if(pgc->audio_control[i] & 0x8000) { /* The 'is present' bit */ + printf("Audio stream %i control: %04x\n", + i, pgc->audio_control[i]); + } + } + + for(i = 0; i < 32; i++) { + if(pgc->subp_control[i] & 0x80000000) { /* The 'is present' bit */ + printf("Subpicture stream %2i control: %08x: 4:3=%d, Wide=%d, Letterbox=%d, Pan-Scan=%d\n", + i, pgc->subp_control[i], + (pgc->subp_control[i] >>24) & 0x1f, + (pgc->subp_control[i] >>16) & 0x1f, + (pgc->subp_control[i] >>8) & 0x1f, + (pgc->subp_control[i] ) & 0x1f); + } + } + + printf("Next PGC number: %i\n", pgc->next_pgc_nr); + printf("Prev PGC number: %i\n", pgc->prev_pgc_nr); + printf("GoUp PGC number: %i\n", pgc->goup_pgc_nr); + if(pgc->nr_of_programs != 0) { + printf("Still time: %i seconds (255=inf)\n", pgc->still_time); + printf("PG Playback mode %02x\n", pgc->pg_playback_mode); + } + + if(pgc->nr_of_programs != 0) { + for(i = 0; i < 16; i++) { + printf("Color %2i: %08x\n", i, pgc->palette[i]); + } + } + + /* Memory offsets to div. tables. */ + ifoPrint_PGC_COMMAND_TBL(pgc->command_tbl); + ifoPrint_PGC_PROGRAM_MAP(pgc->program_map, pgc->nr_of_programs); + ifoPrint_CELL_PLAYBACK(pgc->cell_playback, pgc->nr_of_cells); + ifoPrint_CELL_POSITION(pgc->cell_position, pgc->nr_of_cells); +} + + +static void ifoPrint_TT_SRPT(tt_srpt_t *tt_srpt) { + int i; + + printf("Number of TitleTrack search pointers: %i\n", + tt_srpt->nr_of_srpts); + for(i=0;inr_of_srpts;i++) { + printf("Title Track index %i\n", i + 1); + printf("\tTitle set number (VTS): %i", + tt_srpt->title[i].title_set_nr); + printf("\tVTS_TTN: %i\n", tt_srpt->title[i].vts_ttn); + printf("\tNumber of PTTs: %i\n", tt_srpt->title[i].nr_of_ptts); + printf("\tNumber of angles: %i\n", + tt_srpt->title[i].nr_of_angles); + + printf("\tTitle playback type: (%02x)\n", + *(uint8_t *)&(tt_srpt->title[i].pb_ty)); + printf("\t\t%s\n", + tt_srpt->title[i].pb_ty.multi_or_random_pgc_title ? "Random or Shuffle" : "Sequential"); + if (tt_srpt->title[i].pb_ty.jlc_exists_in_cell_cmd) printf("\t\tJump/Link/Call exists in cell cmd\n"); + if (tt_srpt->title[i].pb_ty.jlc_exists_in_prepost_cmd) printf("\t\tJump/Link/Call exists in pre/post cmd\n"); + if (tt_srpt->title[i].pb_ty.jlc_exists_in_button_cmd) printf("\t\tJump/Link/Call exists in button cmd\n"); + if (tt_srpt->title[i].pb_ty.jlc_exists_in_tt_dom) printf("\t\tJump/Link/Call exists in tt_dom cmd\n"); + printf("\t\tTitle or time play:%u\n", tt_srpt->title[i].pb_ty.title_or_time_play); + printf("\t\tChapter search or play:%u\n", tt_srpt->title[i].pb_ty.chapter_search_or_play); + + printf("\tParental ID field: %04x\n", + tt_srpt->title[i].parental_id); + printf("\tTitle set starting sector %08x\n", + tt_srpt->title[i].title_set_sector); + } +} + + +static void ifoPrint_VTS_PTT_SRPT(vts_ptt_srpt_t *vts_ptt_srpt) { + int i, j; + printf(" nr_of_srpts %i last byte %i\n", + vts_ptt_srpt->nr_of_srpts, + vts_ptt_srpt->last_byte); + for(i=0;inr_of_srpts;i++) { + for(j=0;jtitle[i].nr_of_ptts;j++) { + printf("VTS_PTT_SRPT - Title %3i part %3i: PGC: %3i PG: %3i\n", + i + 1, j + 1, + vts_ptt_srpt->title[i].ptt[j].pgcn, + vts_ptt_srpt->title[i].ptt[j].pgn ); + } + } +} + + +static void hexdump(uint8_t *ptr, int len) { + while(len--) + printf("%02x ", *ptr++); +} + +static void ifoPrint_PTL_MAIT(ptl_mait_t *ptl_mait) { + int i, j; + + printf("Number of Countries: %i\n", ptl_mait->nr_of_countries); + printf("Number of VTSs: %i\n", ptl_mait->nr_of_vtss); + //printf("Last byte: %i\n", ptl_mait->last_byte); + + for(i = 0; i < ptl_mait->nr_of_countries; i++) { + printf("Country code: %c%c\n", + ptl_mait->countries[i].country_code >> 8, + ptl_mait->countries[i].country_code & 0xff); + /* + printf("Start byte: %04x %i\n", + ptl_mait->countries[i].pf_ptl_mai_start_byte, + ptl_mait->countries[i].pf_ptl_mai_start_byte); + */ + /* This seems to be pointing at a array with 8 2byte fields per VTS + ? and one extra for the menu? always an odd number of VTSs on + all the dics I tested so it might be padding to even also. + If it is for the menu it probably the first entry. */ + for(j=0;j<8;j++) { + hexdump( (uint8_t *)ptl_mait->countries - PTL_MAIT_COUNTRY_SIZE + + ptl_mait->countries[i].pf_ptl_mai_start_byte + + j*(ptl_mait->nr_of_vtss+1)*2, (ptl_mait->nr_of_vtss+1)*2); + printf("\n"); + } + } +} + +static void ifoPrint_VTS_TMAPT(vts_tmapt_t *vts_tmapt) { + unsigned int timeunit; + int i, j; + + printf("Number of VTS_TMAPS: %i\n", vts_tmapt->nr_of_tmaps); + printf("Last byte: %i\n", vts_tmapt->last_byte); + + for(i = 0; i < vts_tmapt->nr_of_tmaps; i++) { + printf("TMAP %i (number matches title PGC number.)\n", i + 1); + printf(" offset %d relative to VTS_TMAPTI\n", vts_tmapt->tmap_offset[i]); + printf(" Time unit (seconds): %i\n", vts_tmapt->tmap[i].tmu); + printf(" Number of entries: %i\n", vts_tmapt->tmap[i].nr_of_entries); + timeunit = vts_tmapt->tmap[i].tmu; + for(j = 0; j < vts_tmapt->tmap[i].nr_of_entries; j++) { + unsigned int ac_time = timeunit * (j + 1); + printf("Time: %2i:%02i:%02i VOBU Sector: 0x%08x %s\n", + ac_time / (60 * 60), (ac_time / 60) % 60, ac_time % 60, + vts_tmapt->tmap[i].map_ent[j] & 0x7fffffff, + (vts_tmapt->tmap[i].map_ent[j] >> 31) ? "discontinuity" : ""); + } + } +} + +static void ifoPrint_C_ADT(c_adt_t *c_adt) { + int i, entries; + + printf("Number of VOBs in this VOBS: %i\n", c_adt->nr_of_vobs); + //entries = c_adt->nr_of_vobs; + entries = (c_adt->last_byte + 1 - C_ADT_SIZE)/sizeof(c_adt_t); + + for(i = 0; i < entries; i++) { + printf("VOB ID: %3i, Cell ID: %3i ", + c_adt->cell_adr_table[i].vob_id, c_adt->cell_adr_table[i].cell_id); + printf("Sector (first): 0x%08x (last): 0x%08x\n", + c_adt->cell_adr_table[i].start_sector, + c_adt->cell_adr_table[i].last_sector); + } +} + + +static void ifoPrint_VOBU_ADMAP(vobu_admap_t *vobu_admap) { + int i, entries; + + entries = (vobu_admap->last_byte + 1 - VOBU_ADMAP_SIZE)/4; + for(i = 0; i < entries; i++) { + printf("VOBU %5i First sector: 0x%08x\n", i + 1, + vobu_admap->vobu_start_sectors[i]); + } +} + +static const char *ifo_print_menu_name(int type) { + const char *menu_name; + menu_name=""; + switch (type) { + case 2: + menu_name="Title"; + break; + case 3: + menu_name = "Root"; + break; + case 4: + menu_name = "Sub-Picture"; + break; + case 5: + menu_name = "Audio"; + break; + case 6: + menu_name = "Angle"; + break; + case 7: + menu_name = "PTT (Chapter)"; + break; + default: + menu_name = "Unknown"; + break; + } + return &menu_name[0]; +} + +/* pgc_type=1 for menu, 0 for title. */ +static void ifoPrint_PGCIT(pgcit_t *pgcit, int pgc_type) { + int i; + + printf("\nNumber of Program Chains: %3i\n", pgcit->nr_of_pgci_srp); + for(i = 0; i < pgcit->nr_of_pgci_srp; i++) { + printf("\nProgram (PGC): %3i\n", i + 1); + if (pgc_type) { + printf("PGC Category: Entry PGC %d, Menu Type=0x%02x:%s (Entry id 0x%02x), ", + pgcit->pgci_srp[i].entry_id >> 7, + pgcit->pgci_srp[i].entry_id & 0xf, + ifo_print_menu_name(pgcit->pgci_srp[i].entry_id & 0xf), + pgcit->pgci_srp[i].entry_id); + } else { + printf("PGC Category: %s VTS_TTN:0x%02x (Entry id 0x%02x), ", + pgcit->pgci_srp[i].entry_id >> 7 ? "At Start of" : "During", + pgcit->pgci_srp[i].entry_id & 0xf, + pgcit->pgci_srp[i].entry_id); + } + printf("Parental ID mask 0x%04x\n", pgcit->pgci_srp[i].ptl_id_mask); + ifoPrint_PGC(pgcit->pgci_srp[i].pgc); + } +} + + +static void ifoPrint_PGCI_UT(pgci_ut_t *pgci_ut) { + int i, menu; + + printf("Number of Menu Language Units (PGCI_LU): %3i\n", pgci_ut->nr_of_lus); + for(i = 0; i < pgci_ut->nr_of_lus; i++) { + printf("\nMenu Language Unit %d\n", i+1); + printf("\nMenu Language Code: %c%c\n", + pgci_ut->lu[i].lang_code >> 8, + pgci_ut->lu[i].lang_code & 0xff); + + menu = pgci_ut->lu[i].exists; + printf("Menu Existence: %02x: ", menu); + if (menu == 0) { + printf("No menus "); + } + if (menu & 0x80) { + printf("Root "); + menu^=0x80; + } + if (menu & 0x40) { + printf("Sub-Picture "); + menu^=0x40; + } + if (menu & 0x20) { + printf("Audio "); + menu^=0x20; + } + if (menu & 0x10) { + printf("Angle "); + menu^=0x10; + } + if (menu & 0x08) { + printf("PTT "); + menu^=0x08; + } + if (menu > 0) { + printf("Unknown extra menus "); + menu^=0x08; + } + printf("\n"); + ifoPrint_PGCIT(pgci_ut->lu[i].pgcit, 1); + } +} + + +static void ifoPrint_VTS_ATTRIBUTES(vts_attributes_t *vts_attributes) { + int i; + + printf("VTS_CAT Application type: %08x\n", vts_attributes->vts_cat); + + printf("Video attributes of VTSM_VOBS: "); + ifo_print_video_attributes(&vts_attributes->vtsm_vobs_attr); + printf("\n"); + printf("Number of Audio streams: %i\n", + vts_attributes->nr_of_vtsm_audio_streams); + if(vts_attributes->nr_of_vtsm_audio_streams > 0) { + printf("\tstream %i attributes: ", 1); + ifo_print_audio_attributes(&vts_attributes->vtsm_audio_attr); + printf("\n"); + } + printf("Number of Subpicture streams: %i\n", + vts_attributes->nr_of_vtsm_subp_streams); + if(vts_attributes->nr_of_vtsm_subp_streams > 0) { + printf("\tstream %2i attributes: ", 1); + ifo_print_subp_attributes(&vts_attributes->vtsm_subp_attr); + printf("\n"); + } + + printf("Video attributes of VTSTT_VOBS: "); + ifo_print_video_attributes(&vts_attributes->vtstt_vobs_video_attr); + printf("\n"); + printf("Number of Audio streams: %i\n", + vts_attributes->nr_of_vtstt_audio_streams); + for(i = 0; i < vts_attributes->nr_of_vtstt_audio_streams; i++) { + printf("\tstream %i attributes: ", i); + ifo_print_audio_attributes(&vts_attributes->vtstt_audio_attr[i]); + printf("\n"); + } + + printf("Number of Subpicture streams: %i\n", + vts_attributes->nr_of_vtstt_subp_streams); + for(i = 0; i < vts_attributes->nr_of_vtstt_subp_streams; i++) { + printf("\tstream %2i attributes: ", i); + ifo_print_subp_attributes(&vts_attributes->vtstt_subp_attr[i]); + printf("\n"); + } +} + + +static void ifoPrint_VTS_ATRT(vts_atrt_t *vts_atrt) { + int i; + + printf("Number of Video Title Sets: %3i\n", vts_atrt->nr_of_vtss); + for(i = 0; i < vts_atrt->nr_of_vtss; i++) { + printf("\nVideo Title Set %i\n", i + 1); + ifoPrint_VTS_ATTRIBUTES(&vts_atrt->vts[i]); + } +} + + +void ifo_print(dvd_reader_t *dvd, int title) { + ifo_handle_t *ifohandle; + printf("Local ifo_print\n"); + ifohandle = ifoOpen(dvd, title); + if(!ifohandle) { + Log0(dvd, "Can't open info file for title %d", title); + return; + } + + + if(ifohandle->vmgi_mat) { + + printf("VMG top level\n-------------\n"); + ifoPrint_VMGI_MAT(ifohandle->vmgi_mat); + + printf("\nFirst Play PGC\n--------------\n"); + if(ifohandle->first_play_pgc) + ifoPrint_PGC(ifohandle->first_play_pgc); + else + printf("No First Play PGC present\n"); + + printf("\nTitle Track search pointer table\n"); + printf( "------------------------------------------------\n"); + ifoPrint_TT_SRPT(ifohandle->tt_srpt); + + printf("\nMenu PGCI Unit table\n"); + printf( "--------------------\n"); + if(ifohandle->pgci_ut) { + ifoPrint_PGCI_UT(ifohandle->pgci_ut); + } else { + printf("No PGCI Unit table present\n"); + } + + printf("\nParental Management Information table\n"); + printf( "------------------------------------\n"); + if(ifohandle->ptl_mait) { + ifoPrint_PTL_MAIT(ifohandle->ptl_mait); + } else { + printf("No Parental Management Information present\n"); + } + + printf("\nVideo Title Set Attribute Table\n"); + printf( "-------------------------------\n"); + ifoPrint_VTS_ATRT(ifohandle->vts_atrt); + + printf("\nText Data Manager Information\n"); + printf( "-----------------------------\n"); + if(ifohandle->txtdt_mgi) { + //ifo_print_TXTDT_MGI(&(vmgi->txtdt_mgi)); + } else { + printf("No Text Data Manager Information present\n"); + } + + printf("\nMenu Cell Address table\n"); + printf( "-----------------\n"); + if(ifohandle->menu_c_adt) { + ifoPrint_C_ADT(ifohandle->menu_c_adt); + } else { + printf("No Menu Cell Address table present\n"); + } + + printf("\nVideo Manager Menu VOBU address map\n"); + printf( "-----------------\n"); + if(ifohandle->menu_vobu_admap) { + ifoPrint_VOBU_ADMAP(ifohandle->menu_vobu_admap); + } else { + printf("No Menu VOBU address map present\n"); + } + } + + + if(ifohandle->vtsi_mat) { + + printf("VTS top level\n-------------\n"); + ifoPrint_VTSI_MAT(ifohandle->vtsi_mat); + + printf("\nPart of Title Track search pointer table\n"); + printf( "----------------------------------------------\n"); + ifoPrint_VTS_PTT_SRPT(ifohandle->vts_ptt_srpt); + + printf("\nPGCI Unit table\n"); + printf( "--------------------\n"); + ifoPrint_PGCIT(ifohandle->vts_pgcit, 0); + + printf("\nMenu PGCI Unit table\n"); + printf( "--------------------\n"); + if(ifohandle->pgci_ut) { + ifoPrint_PGCI_UT(ifohandle->pgci_ut); + } else { + printf("No Menu PGCI Unit table present\n"); + } + + printf("\nVTS Time Map table\n"); + printf( "-----------------\n"); + if(ifohandle->vts_tmapt) { + ifoPrint_VTS_TMAPT(ifohandle->vts_tmapt); + } else { + printf("No VTS Time Map table present\n"); + } + + printf("\nMenu Cell Address table\n"); + printf( "-----------------\n"); + if(ifohandle->menu_c_adt) { + ifoPrint_C_ADT(ifohandle->menu_c_adt); + } else { + printf("No Cell Address table present\n"); + } + + printf("\nVideo Title Set Menu VOBU address map\n"); + printf( "-----------------\n"); + if(ifohandle->menu_vobu_admap) { + ifoPrint_VOBU_ADMAP(ifohandle->menu_vobu_admap); + } else { + printf("No Menu VOBU address map present\n"); + } + + printf("\nCell Address table\n"); + printf( "-----------------\n"); + ifoPrint_C_ADT(ifohandle->vts_c_adt); + + printf("\nVideo Title Set VOBU address map\n"); + printf( "-----------------\n"); + ifoPrint_VOBU_ADMAP(ifohandle->vts_vobu_admap); + } + + ifoClose(ifohandle); +} diff --git a/libdvdread-embedded/src/ifo_read.c b/libdvdread-embedded/src/ifo_read.c new file mode 100644 index 0000000..6fd913d --- /dev/null +++ b/libdvdread-embedded/src/ifo_read.c @@ -0,0 +1,2341 @@ +/* + * Copyright (C) 2000, 2001, 2002, 2003 + * Björn Englund , + * Håkan Hjort + * + * This file is part of libdvdread. + * + * libdvdread 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 of the License, or + * (at your option) any later version. + * + * libdvdread 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 libdvdread; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" + +#include +#include +#include +#include + +#include "bswap.h" +#include "dvdread/ifo_types.h" +#include "dvdread/ifo_read.h" +#include "dvdread/dvd_reader.h" +#include "dvdread_internal.h" +#include "dvdread/bitreader.h" + +#ifndef DVD_BLOCK_LEN +#define DVD_BLOCK_LEN 2048 +#endif + +#define PRIV(a) container_of(a, struct ifo_handle_private_s, handle) + +#define CHECK_VALUE(arg)\ + if(!(arg)) {\ + Log1(ifop->ctx, "CHECK_VALUE failed in %s:%i for %s",\ + __FILE__, __LINE__, # arg );\ + } + +#ifndef NDEBUG +static inline char * makehexdump(const uint8_t *p_CZ, size_t i_CZ) +{ + char *alloc = malloc(i_CZ * 2 + 1); + if(alloc) + { + *alloc = 0; + for(size_t i = 0; i < i_CZ; i++) + sprintf(&alloc[i*2], "%02x", *((uint8_t*)&p_CZ[i])); + } + return alloc; +} +#define CHECK_ZERO0(arg) \ + if(arg != 0) { \ + Log1(ifop->ctx, "Zero check failed in %s:%i\n for %s = 0x%x", \ + __FILE__, __LINE__, # arg, arg); \ + } +#define CHECK_ZERO(arg) \ + if(memcmp(my_friendly_zeros, &arg, sizeof(arg))) { \ + char *dump = makehexdump((const uint8_t *)&arg, sizeof(arg)); \ + Log0(ifop->ctx, "Zero check failed in %s:%i for %s : 0x%s", \ + __FILE__, __LINE__, # arg, dump ); \ + free(dump); \ + } +static const uint8_t my_friendly_zeros[2048]; +#else +#define CHECK_ZERO0(arg) (void)(arg) +#define CHECK_ZERO(arg) (void)(arg) +#endif + + +/* Prototypes for internal functions */ +static int ifoRead_VMG(ifo_handle_t *ifofile); +static int ifoRead_VTS(ifo_handle_t *ifofile); +static int ifoRead_PGC(ifo_handle_t *ifofile, pgc_t *pgc, unsigned int offset); +static int ifoRead_PGC_COMMAND_TBL(ifo_handle_t *ifofile, + pgc_command_tbl_t *cmd_tbl, + unsigned int offset); +static int ifoRead_PGC_PROGRAM_MAP(ifo_handle_t *ifofile, + pgc_program_map_t *program_map, + unsigned int nr, unsigned int offset); +static int ifoRead_CELL_PLAYBACK_TBL(ifo_handle_t *ifofile, + cell_playback_t *cell_playback, + unsigned int nr, unsigned int offset); +static int ifoRead_CELL_POSITION_TBL(ifo_handle_t *ifofile, + cell_position_t *cell_position, + unsigned int nr, unsigned int offset); +static int ifoRead_VTS_ATTRIBUTES(ifo_handle_t *ifofile, + vts_attributes_t *vts_attributes, + unsigned int offset); +static int ifoRead_C_ADT_internal(ifo_handle_t *ifofile, c_adt_t *c_adt, + unsigned int sector); +static int ifoRead_VOBU_ADMAP_internal(ifo_handle_t *ifofile, + vobu_admap_t *vobu_admap, + unsigned int sector); +static int ifoRead_PGCIT_internal(ifo_handle_t *ifofile, pgcit_t *pgcit, + unsigned int offset); + +static void ifoFree_PGC(pgc_t **pgc); +static void ifoFree_PGC_COMMAND_TBL(pgc_command_tbl_t *cmd_tbl); +static void ifoFree_PGCIT_internal(pgcit_t **pgcit); + +static inline int DVDFileSeekForce_( dvd_file_t *dvd_file, uint32_t offset, int force_size ) { + return (DVDFileSeekForce(dvd_file, (int)offset, force_size) == (int)offset); +} + +static inline int DVDFileSeek_( dvd_file_t *dvd_file, uint32_t offset ) { + return (DVDFileSeek(dvd_file, (int)offset) == (int)offset); +} + +static void read_video_attr(video_attr_t *va) { + getbits_state_t state; + uint8_t buf[sizeof(video_attr_t)]; + + memcpy(buf, va, sizeof(video_attr_t)); + if (!dvdread_getbits_init(&state, buf)) abort(); + va->mpeg_version = dvdread_getbits(&state, 2); + va->video_format = dvdread_getbits(&state, 2); + va->display_aspect_ratio = dvdread_getbits(&state, 2); + va->permitted_df = dvdread_getbits(&state, 2); + va->line21_cc_1 = dvdread_getbits(&state, 1); + va->line21_cc_2 = dvdread_getbits(&state, 1); + va->unknown1 = dvdread_getbits(&state, 1); + va->bit_rate = dvdread_getbits(&state, 1); + va->picture_size = dvdread_getbits(&state, 2); + va->letterboxed = dvdread_getbits(&state, 1); + va->film_mode = dvdread_getbits(&state, 1); +} + +static void read_audio_attr(audio_attr_t *aa) { + getbits_state_t state; + uint8_t buf[sizeof(audio_attr_t)]; + + memcpy(buf, aa, sizeof(audio_attr_t)); + if (!dvdread_getbits_init(&state, buf)) abort(); + aa->audio_format = dvdread_getbits(&state, 3); + aa->multichannel_extension = dvdread_getbits(&state, 1); + aa->lang_type = dvdread_getbits(&state, 2); + aa->application_mode = dvdread_getbits(&state, 2); + aa->quantization = dvdread_getbits(&state, 2); + aa->sample_frequency = dvdread_getbits(&state, 2); + aa->unknown1 = dvdread_getbits(&state, 1); + aa->channels = dvdread_getbits(&state, 3); + aa->lang_code = dvdread_getbits(&state, 16); + aa->lang_extension = dvdread_getbits(&state, 8); + aa->code_extension = dvdread_getbits(&state, 8); + aa->unknown3 = dvdread_getbits(&state, 8); + aa->app_info.karaoke.unknown4 = dvdread_getbits(&state, 1); + aa->app_info.karaoke.channel_assignment = dvdread_getbits(&state, 3); + aa->app_info.karaoke.version = dvdread_getbits(&state, 2); + aa->app_info.karaoke.mc_intro = dvdread_getbits(&state, 1); + aa->app_info.karaoke.mode = dvdread_getbits(&state, 1); +} + +static void read_multichannel_ext(multichannel_ext_t *me) { + getbits_state_t state; + uint8_t buf[sizeof(multichannel_ext_t)]; + + memcpy(buf, me, sizeof(multichannel_ext_t)); + if (!dvdread_getbits_init(&state, buf)) abort(); + me->zero1 = dvdread_getbits(&state, 7); + me->ach0_gme = dvdread_getbits(&state, 1); + me->zero2 = dvdread_getbits(&state, 7); + me->ach1_gme = dvdread_getbits(&state, 1); + me->zero3 = dvdread_getbits(&state, 4); + me->ach2_gv1e = dvdread_getbits(&state, 1); + me->ach2_gv2e = dvdread_getbits(&state, 1); + me->ach2_gm1e = dvdread_getbits(&state, 1); + me->ach2_gm2e = dvdread_getbits(&state, 1); + me->zero4 = dvdread_getbits(&state, 4); + me->ach3_gv1e = dvdread_getbits(&state, 1); + me->ach3_gv2e = dvdread_getbits(&state, 1); + me->ach3_gmAe = dvdread_getbits(&state, 1); + me->ach3_se2e = dvdread_getbits(&state, 1); + me->zero5 = dvdread_getbits(&state, 4); + me->ach4_gv1e = dvdread_getbits(&state, 1); + me->ach4_gv2e = dvdread_getbits(&state, 1); + me->ach4_gmBe = dvdread_getbits(&state, 1); + me->ach4_seBe = dvdread_getbits(&state, 1); +} + +static void read_subp_attr(subp_attr_t *sa) { + getbits_state_t state; + uint8_t buf[sizeof(subp_attr_t)]; + + memcpy(buf, sa, sizeof(subp_attr_t)); + if (!dvdread_getbits_init(&state, buf)) abort(); + sa->code_mode = dvdread_getbits(&state, 3); + sa->zero1 = dvdread_getbits(&state, 3); + sa->type = dvdread_getbits(&state, 2); + sa->zero2 = dvdread_getbits(&state, 8); + sa->lang_code = dvdread_getbits(&state, 16); + sa->lang_extension = dvdread_getbits(&state, 8); + sa->code_extension = dvdread_getbits(&state, 8); +} + +static void read_user_ops(user_ops_t *uo) { + getbits_state_t state; + uint8_t buf[sizeof(user_ops_t)]; + + memcpy(buf, uo, sizeof(user_ops_t)); + if (!dvdread_getbits_init(&state, buf)) abort(); + uo->zero = dvdread_getbits(&state, 7); + uo->video_pres_mode_change = dvdread_getbits(&state, 1); + uo->karaoke_audio_pres_mode_change = dvdread_getbits(&state, 1); + uo->angle_change = dvdread_getbits(&state, 1); + uo->subpic_stream_change = dvdread_getbits(&state, 1); + uo->audio_stream_change = dvdread_getbits(&state, 1); + uo->pause_on = dvdread_getbits(&state, 1); + uo->still_off = dvdread_getbits(&state, 1); + uo->button_select_or_activate = dvdread_getbits(&state, 1); + uo->resume = dvdread_getbits(&state, 1); + uo->chapter_menu_call = dvdread_getbits(&state, 1); + uo->angle_menu_call = dvdread_getbits(&state, 1); + uo->audio_menu_call = dvdread_getbits(&state, 1); + uo->subpic_menu_call = dvdread_getbits(&state, 1); + uo->root_menu_call = dvdread_getbits(&state, 1); + uo->title_menu_call = dvdread_getbits(&state, 1); + uo->backward_scan = dvdread_getbits(&state, 1); + uo->forward_scan = dvdread_getbits(&state, 1); + uo->next_pg_search = dvdread_getbits(&state, 1); + uo->prev_or_top_pg_search = dvdread_getbits(&state, 1); + uo->time_or_chapter_search = dvdread_getbits(&state, 1); + uo->go_up = dvdread_getbits(&state, 1); + uo->stop = dvdread_getbits(&state, 1); + uo->title_play = dvdread_getbits(&state, 1); + uo->chapter_search_or_play = dvdread_getbits(&state, 1); + uo->title_or_time_play = dvdread_getbits(&state, 1); +} + +static void read_pgci_srp(pgci_srp_t *ps) { + getbits_state_t state; + uint8_t buf[sizeof(pgci_srp_t)]; + + memcpy(buf, ps, sizeof(pgci_srp_t)); + if (!dvdread_getbits_init(&state, buf)) abort(); + ps->entry_id = dvdread_getbits(&state, 8); + ps->block_mode = dvdread_getbits(&state, 2); + ps->block_type = dvdread_getbits(&state, 2); + ps->zero_1 = dvdread_getbits(&state, 4); + ps->ptl_id_mask = dvdread_getbits(&state, 16); + ps->pgc_start_byte = dvdread_getbits(&state, 32); +} + +static void read_cell_playback(cell_playback_t *cp) { + getbits_state_t state; + uint8_t buf[sizeof(cell_playback_t)]; + + memcpy(buf, cp, sizeof(cell_playback_t)); + if (!dvdread_getbits_init(&state, buf)) abort(); + cp->block_mode = dvdread_getbits(&state, 2); + cp->block_type = dvdread_getbits(&state, 2); + cp->seamless_play = dvdread_getbits(&state, 1); + cp->interleaved = dvdread_getbits(&state, 1); + cp->stc_discontinuity = dvdread_getbits(&state, 1); + cp->seamless_angle = dvdread_getbits(&state, 1); + cp->zero_1 = dvdread_getbits(&state, 1); + cp->playback_mode = dvdread_getbits(&state, 1); + cp->restricted = dvdread_getbits(&state, 1); + cp->cell_type = dvdread_getbits(&state, 5); + cp->still_time = dvdread_getbits(&state, 8); + cp->cell_cmd_nr = dvdread_getbits(&state, 8); + + cp->playback_time.hour = dvdread_getbits(&state, 8); + cp->playback_time.minute = dvdread_getbits(&state, 8); + cp->playback_time.second = dvdread_getbits(&state, 8); + cp->playback_time.frame_u = dvdread_getbits(&state, 8); + + cp->first_sector = dvdread_getbits(&state, 32); + cp->first_ilvu_end_sector = dvdread_getbits(&state, 32); + cp->last_vobu_start_sector = dvdread_getbits(&state, 32); + cp->last_sector = dvdread_getbits(&state, 32); +} + +static void read_playback_type(playback_type_t *pt) { + getbits_state_t state; + uint8_t buf[sizeof(playback_type_t)]; + + memcpy(buf, pt, sizeof(playback_type_t)); + if (!dvdread_getbits_init(&state, buf)) abort(); + pt->zero_1 = dvdread_getbits(&state, 1); + pt->multi_or_random_pgc_title = dvdread_getbits(&state, 1); + pt->jlc_exists_in_cell_cmd = dvdread_getbits(&state, 1); + pt->jlc_exists_in_prepost_cmd = dvdread_getbits(&state, 1); + pt->jlc_exists_in_button_cmd = dvdread_getbits(&state, 1); + pt->jlc_exists_in_tt_dom = dvdread_getbits(&state, 1); + pt->chapter_search_or_play = dvdread_getbits(&state, 1); + pt->title_or_time_play = dvdread_getbits(&state, 1); +} + +static void free_ptl_mait(ptl_mait_t* ptl_mait, int num_entries) { + int i; + for (i = 0; i < num_entries; i++) + free(ptl_mait->countries[i].pf_ptl_mai); + + free(ptl_mait->countries); + free(ptl_mait); +} + +static ifo_handle_t *ifoOpenFileOrBackup(dvd_reader_t *ctx, int title, + int backup) { + struct ifo_handle_private_s *ifop; + dvd_read_domain_t domain = backup ? DVD_READ_INFO_BACKUP_FILE + : DVD_READ_INFO_FILE; + char ifo_filename[13]; + + ifop = calloc(1, sizeof(*ifop)); + if(!ifop) + return NULL; + + ifop->ctx = ctx; + ifop->file = DVDOpenFile(ctx, title, domain); + if(!ifop->file) + { + free(ifop); + return NULL; + } + + if (title) + snprintf(ifo_filename, 13, "VTS_%02d_0.%s", title, backup ? "BUP" : "IFO"); + else + snprintf(ifo_filename, 13, "VIDEO_TS.%s", backup ? "BUP" : "IFO"); + + if(!ifop->file) { + Log1(ctx, "Can't open file %s.", ifo_filename); + free(ifop); + return NULL; + } + + ifo_handle_t *ifofile = &ifop->handle; + /* First check if this is a VMGI file. */ + if(ifoRead_VMG(ifofile)) { + + /* These are both mandatory. */ + if(!ifoRead_FP_PGC(ifofile) || !ifoRead_TT_SRPT(ifofile)) + goto ifoOpen_fail; + + ifoRead_PGCI_UT(ifofile); + ifoRead_PTL_MAIT(ifofile); + + /* This is also mandatory. */ + if(!ifoRead_VTS_ATRT(ifofile)) + goto ifoOpen_fail; + + ifoRead_TXTDT_MGI(ifofile); + ifoRead_C_ADT(ifofile); + ifoRead_VOBU_ADMAP(ifofile); + + return ifofile; + } + + if(ifoRead_VTS(ifofile)) { + + if(!ifoRead_VTS_PTT_SRPT(ifofile) || !ifoRead_PGCIT(ifofile)) + goto ifoOpen_fail; + + ifoRead_PGCI_UT(ifofile); + ifoRead_VTS_TMAPT(ifofile); + ifoRead_C_ADT(ifofile); + ifoRead_VOBU_ADMAP(ifofile); + + if(!ifoRead_TITLE_C_ADT(ifofile) || !ifoRead_TITLE_VOBU_ADMAP(ifofile)) + goto ifoOpen_fail; + + return ifofile; + } + +ifoOpen_fail: + Log1(ctx, "Invalid IFO for title %d (%s).", title, ifo_filename); + ifoClose(ifofile); + return NULL; +} + +static void ifoSetBupFlag(dvd_reader_t *ctx, int title) +{ + if(title > 63) + ctx->ifoBUPflags[0] |= 1 << (title - 64); + else + ctx->ifoBUPflags[1] |= 1 << title; +} + +static int ifoGetBupFlag(const dvd_reader_t *ctx, int title) +{ + int bupflag; + if(title > 63) + bupflag = !! (ctx->ifoBUPflags[0] & (1 << (title - 64))); + else + bupflag = !! (ctx->ifoBUPflags[1] & (1 << title)); + return bupflag; +} + +ifo_handle_t *ifoOpen(dvd_reader_t *ctx, int title) { + ifo_handle_t *ifofile; + int bupflag = ifoGetBupFlag(ctx, title); + + ifofile = ifoOpenFileOrBackup(ctx, title, bupflag); + if(!ifofile) /* Try backup */ + { + ifofile = ifoOpenFileOrBackup(ctx, title, 1); + if(ifofile && !bupflag) + ifoSetBupFlag(ctx, title); + } + return ifofile; +} + +ifo_handle_t *ifoOpenVMGI(dvd_reader_t *ctx) { + struct ifo_handle_private_s *ifop; + + for(int backup = ifoGetBupFlag(ctx, 0); backup <= 1; backup++) + { + ifop = calloc(1, sizeof(*ifop)); + if(!ifop) + return NULL; + + const dvd_read_domain_t domain = backup ? DVD_READ_INFO_BACKUP_FILE + : DVD_READ_INFO_FILE; + const char *ext = backup ? "BUP" : "IFO"; + + ifop->ctx = ctx; + ifop->file = DVDOpenFile(ctx, 0, domain); + if(!ifop->file) { /* Should really catch any error */ + Log1(ctx, "Can't open file VIDEO_TS.%s.", ext); + free(ifop); + return NULL; + } + + if(ifoRead_VMG(&ifop->handle)) + return &ifop->handle; + + Log1(ctx, "ifoOpenVMGI(): Invalid main menu IFO (VIDEO_TS.%s).", ext); + ifoClose(&ifop->handle); + } + return NULL; +} + + +ifo_handle_t *ifoOpenVTSI(dvd_reader_t *ctx, int title) { + struct ifo_handle_private_s *ifop; + + if(title <= 0 || title > 99) { + Log1(ctx, "ifoOpenVTSI invalid title (%d).", title); + return NULL; + } + + for(int backup = ifoGetBupFlag(ctx, title); backup <= 1; backup++) + { + ifop = calloc(1, sizeof(*ifop)); + if(!ifop) + return NULL; + + const dvd_read_domain_t domain = backup ? DVD_READ_INFO_BACKUP_FILE + : DVD_READ_INFO_FILE; + const char *ext = backup ? "BUP" : "IFO"; + ifop->ctx = ctx; + ifop->file = DVDOpenFile(ctx, title, domain); + /* Should really catch any error */ + if(!ifop->file) { + Log1(ctx, "Can't open file VTS_%02d_0.%s.", title, ext); + free(ifop); + continue; + } + + if(ifoRead_VTS(&ifop->handle) && ifop->handle.vtsi_mat) + return &ifop->handle; + + Log1(ctx, "Invalid IFO for title %d (VTS_%02d_0.%s).", + title, title, ext); + ifoClose(&ifop->handle); + } + + return NULL; +} + + +void ifoClose(ifo_handle_t *ifofile) { + if(!ifofile) + return; + + ifoFree_VOBU_ADMAP(ifofile); + ifoFree_TITLE_VOBU_ADMAP(ifofile); + ifoFree_C_ADT(ifofile); + ifoFree_TITLE_C_ADT(ifofile); + ifoFree_TXTDT_MGI(ifofile); + ifoFree_VTS_ATRT(ifofile); + ifoFree_PTL_MAIT(ifofile); + ifoFree_PGCI_UT(ifofile); + ifoFree_TT_SRPT(ifofile); + ifoFree_FP_PGC(ifofile); + ifoFree_PGCIT(ifofile); + ifoFree_VTS_PTT_SRPT(ifofile); + ifoFree_VTS_TMAPT(ifofile); + + if(ifofile->vmgi_mat) + free(ifofile->vmgi_mat); + + if(ifofile->vtsi_mat) + free(ifofile->vtsi_mat); + + struct ifo_handle_private_s *ifop = PRIV(ifofile); + DVDCloseFile(ifop->file); + free(ifop); +} + + +static int ifoRead_VMG(ifo_handle_t *ifofile) { + struct ifo_handle_private_s *ifop = PRIV(ifofile); + vmgi_mat_t *vmgi_mat; + + vmgi_mat = calloc(1, sizeof(vmgi_mat_t)); + if(!vmgi_mat) + return 0; + + ifofile->vmgi_mat = vmgi_mat; + + if(!DVDFileSeek_(ifop->file, 0)) { + free(ifofile->vmgi_mat); + ifofile->vmgi_mat = NULL; + return 0; + } + + if(!DVDReadBytes(ifop->file, vmgi_mat, sizeof(vmgi_mat_t))) { + free(ifofile->vmgi_mat); + ifofile->vmgi_mat = NULL; + return 0; + } + + if(strncmp("DVDVIDEO-VMG", vmgi_mat->vmg_identifier, 12) != 0) { + free(ifofile->vmgi_mat); + ifofile->vmgi_mat = NULL; + return 0; + } + + B2N_32(vmgi_mat->vmg_last_sector); + B2N_32(vmgi_mat->vmgi_last_sector); + B2N_32(vmgi_mat->vmg_category); + B2N_16(vmgi_mat->vmg_nr_of_volumes); + B2N_16(vmgi_mat->vmg_this_volume_nr); + B2N_16(vmgi_mat->vmg_nr_of_title_sets); + B2N_64(vmgi_mat->vmg_pos_code); + B2N_32(vmgi_mat->vmgi_last_byte); + B2N_32(vmgi_mat->first_play_pgc); + B2N_32(vmgi_mat->vmgm_vobs); + B2N_32(vmgi_mat->tt_srpt); + B2N_32(vmgi_mat->vmgm_pgci_ut); + B2N_32(vmgi_mat->ptl_mait); + B2N_32(vmgi_mat->vts_atrt); + B2N_32(vmgi_mat->txtdt_mgi); + B2N_32(vmgi_mat->vmgm_c_adt); + B2N_32(vmgi_mat->vmgm_vobu_admap); + read_video_attr(&vmgi_mat->vmgm_video_attr); + read_audio_attr(&vmgi_mat->vmgm_audio_attr); + read_subp_attr(&vmgi_mat->vmgm_subp_attr); + + + CHECK_ZERO(vmgi_mat->zero_1); + CHECK_ZERO(vmgi_mat->zero_2); + /* DVDs created by VDR-to-DVD device LG RC590M violate the following check with + * vmgi_mat->zero_3 = 0x00000000010000000000000000000000000000. */ + CHECK_ZERO(vmgi_mat->zero_3); + CHECK_ZERO(vmgi_mat->zero_4); + CHECK_ZERO(vmgi_mat->zero_5); + CHECK_ZERO(vmgi_mat->zero_6); + CHECK_ZERO(vmgi_mat->zero_7); + CHECK_ZERO(vmgi_mat->zero_8); + CHECK_ZERO(vmgi_mat->zero_9); + CHECK_ZERO(vmgi_mat->zero_10); + CHECK_VALUE(vmgi_mat->vmg_last_sector != 0); + CHECK_VALUE(vmgi_mat->vmgi_last_sector != 0); + CHECK_VALUE(vmgi_mat->vmgi_last_sector * 2 <= vmgi_mat->vmg_last_sector); + CHECK_VALUE(vmgi_mat->vmgi_last_sector * 2 <= vmgi_mat->vmg_last_sector); + CHECK_VALUE(vmgi_mat->vmg_nr_of_volumes != 0); + CHECK_VALUE(vmgi_mat->vmg_this_volume_nr != 0); + CHECK_VALUE(vmgi_mat->vmg_this_volume_nr <= vmgi_mat->vmg_nr_of_volumes); + CHECK_VALUE(vmgi_mat->disc_side == 1 || vmgi_mat->disc_side == 2); + CHECK_VALUE(vmgi_mat->vmg_nr_of_title_sets != 0); + CHECK_VALUE(vmgi_mat->vmgi_last_byte >= 341); + CHECK_VALUE(vmgi_mat->vmgi_last_byte / DVD_BLOCK_LEN <= + vmgi_mat->vmgi_last_sector); + /* It seems that first_play_pgc is optional. */ + CHECK_VALUE(vmgi_mat->first_play_pgc < vmgi_mat->vmgi_last_byte); + CHECK_VALUE(vmgi_mat->vmgm_vobs == 0 || + (vmgi_mat->vmgm_vobs > vmgi_mat->vmgi_last_sector && + vmgi_mat->vmgm_vobs < vmgi_mat->vmg_last_sector)); + CHECK_VALUE(vmgi_mat->tt_srpt <= vmgi_mat->vmgi_last_sector); + CHECK_VALUE(vmgi_mat->vmgm_pgci_ut <= vmgi_mat->vmgi_last_sector); + CHECK_VALUE(vmgi_mat->ptl_mait <= vmgi_mat->vmgi_last_sector); + CHECK_VALUE(vmgi_mat->vts_atrt <= vmgi_mat->vmgi_last_sector); + CHECK_VALUE(vmgi_mat->txtdt_mgi <= vmgi_mat->vmgi_last_sector); + CHECK_VALUE(vmgi_mat->vmgm_c_adt <= vmgi_mat->vmgi_last_sector); + CHECK_VALUE(vmgi_mat->vmgm_vobu_admap <= vmgi_mat->vmgi_last_sector); + + CHECK_VALUE(vmgi_mat->nr_of_vmgm_audio_streams <= 1); + CHECK_VALUE(vmgi_mat->nr_of_vmgm_subp_streams <= 1); + + return 1; +} + + +static int ifoRead_VTS(ifo_handle_t *ifofile) { + struct ifo_handle_private_s *ifop = PRIV(ifofile); + vtsi_mat_t *vtsi_mat; + int i; + + vtsi_mat = calloc(1, sizeof(vtsi_mat_t)); + if(!vtsi_mat) + return 0; + + ifofile->vtsi_mat = vtsi_mat; + + if(!DVDFileSeek_(ifop->file, 0)) { + free(ifofile->vtsi_mat); + ifofile->vtsi_mat = NULL; + return 0; + } + + if(!(DVDReadBytes(ifop->file, vtsi_mat, sizeof(vtsi_mat_t)))) { + free(ifofile->vtsi_mat); + ifofile->vtsi_mat = NULL; + return 0; + } + + if(strncmp("DVDVIDEO-VTS", vtsi_mat->vts_identifier, 12) != 0) { + free(ifofile->vtsi_mat); + ifofile->vtsi_mat = NULL; + return 0; + } + + read_video_attr(&vtsi_mat->vtsm_video_attr); + read_video_attr(&vtsi_mat->vts_video_attr); + read_audio_attr(&vtsi_mat->vtsm_audio_attr); + for(i=0; i<8; i++) + read_audio_attr(&vtsi_mat->vts_audio_attr[i]); + read_subp_attr(&vtsi_mat->vtsm_subp_attr); + for(i=0; i<32; i++) + read_subp_attr(&vtsi_mat->vts_subp_attr[i]); + B2N_32(vtsi_mat->vts_last_sector); + B2N_32(vtsi_mat->vtsi_last_sector); + B2N_32(vtsi_mat->vts_category); + B2N_32(vtsi_mat->vtsi_last_byte); + B2N_32(vtsi_mat->vtsm_vobs); + B2N_32(vtsi_mat->vtstt_vobs); + B2N_32(vtsi_mat->vts_ptt_srpt); + B2N_32(vtsi_mat->vts_pgcit); + B2N_32(vtsi_mat->vtsm_pgci_ut); + B2N_32(vtsi_mat->vts_tmapt); + B2N_32(vtsi_mat->vtsm_c_adt); + B2N_32(vtsi_mat->vtsm_vobu_admap); + B2N_32(vtsi_mat->vts_c_adt); + B2N_32(vtsi_mat->vts_vobu_admap); + + + CHECK_ZERO(vtsi_mat->zero_1); + CHECK_ZERO(vtsi_mat->zero_2); + CHECK_ZERO(vtsi_mat->zero_3); + CHECK_ZERO(vtsi_mat->zero_4); + CHECK_ZERO(vtsi_mat->zero_5); + CHECK_ZERO(vtsi_mat->zero_6); + CHECK_ZERO(vtsi_mat->zero_7); + CHECK_ZERO(vtsi_mat->zero_8); + CHECK_ZERO(vtsi_mat->zero_9); + CHECK_ZERO(vtsi_mat->zero_10); + CHECK_ZERO(vtsi_mat->zero_11); + CHECK_ZERO(vtsi_mat->zero_12); + CHECK_ZERO(vtsi_mat->zero_13); + CHECK_ZERO(vtsi_mat->zero_14); + CHECK_ZERO(vtsi_mat->zero_15); + CHECK_ZERO(vtsi_mat->zero_16); + CHECK_ZERO(vtsi_mat->zero_17); + CHECK_ZERO(vtsi_mat->zero_18); + CHECK_ZERO(vtsi_mat->zero_19); + CHECK_ZERO(vtsi_mat->zero_20); + CHECK_ZERO(vtsi_mat->zero_21); + CHECK_VALUE(vtsi_mat->vtsi_last_sector*2 <= vtsi_mat->vts_last_sector); + CHECK_VALUE(vtsi_mat->vtsi_last_byte/DVD_BLOCK_LEN <= vtsi_mat->vtsi_last_sector); + CHECK_VALUE(vtsi_mat->vtsm_vobs == 0 || + (vtsi_mat->vtsm_vobs > vtsi_mat->vtsi_last_sector && + vtsi_mat->vtsm_vobs < vtsi_mat->vts_last_sector)); + CHECK_VALUE(vtsi_mat->vtstt_vobs == 0 || + (vtsi_mat->vtstt_vobs > vtsi_mat->vtsi_last_sector && + vtsi_mat->vtstt_vobs < vtsi_mat->vts_last_sector)); + CHECK_VALUE(vtsi_mat->vts_ptt_srpt <= vtsi_mat->vtsi_last_sector); + CHECK_VALUE(vtsi_mat->vts_pgcit <= vtsi_mat->vtsi_last_sector); + CHECK_VALUE(vtsi_mat->vtsm_pgci_ut <= vtsi_mat->vtsi_last_sector); + CHECK_VALUE(vtsi_mat->vts_tmapt <= vtsi_mat->vtsi_last_sector); + CHECK_VALUE(vtsi_mat->vtsm_c_adt <= vtsi_mat->vtsi_last_sector); + CHECK_VALUE(vtsi_mat->vtsm_vobu_admap <= vtsi_mat->vtsi_last_sector); + CHECK_VALUE(vtsi_mat->vts_c_adt <= vtsi_mat->vtsi_last_sector); + CHECK_VALUE(vtsi_mat->vts_vobu_admap <= vtsi_mat->vtsi_last_sector); + + CHECK_VALUE(vtsi_mat->nr_of_vtsm_audio_streams <= 1); + CHECK_VALUE(vtsi_mat->nr_of_vtsm_subp_streams <= 1); + + CHECK_VALUE(vtsi_mat->nr_of_vts_audio_streams <= 8); + for(i = vtsi_mat->nr_of_vts_audio_streams; i < 8; i++) + CHECK_ZERO(vtsi_mat->vts_audio_attr[i]); + + CHECK_VALUE(vtsi_mat->nr_of_vts_subp_streams <= 32); + for(i = vtsi_mat->nr_of_vts_subp_streams; i < 32; i++) + CHECK_ZERO(vtsi_mat->vts_subp_attr[i]); + + for(i = 0; i < 8; i++) { + read_multichannel_ext(&vtsi_mat->vts_mu_audio_attr[i]); + CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero1); + CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero2); + CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero3); + CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero4); + CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero5); + CHECK_ZERO(vtsi_mat->vts_mu_audio_attr[i].zero6); + } + + return 1; +} + + +static int ifoRead_PGC_COMMAND_TBL(ifo_handle_t *ifofile, + pgc_command_tbl_t *cmd_tbl, + unsigned int offset) { + struct ifo_handle_private_s *ifop = PRIV(ifofile); + if(!DVDFileSeek_(ifop->file, offset)) + return 0; + + if(!(DVDReadBytes(ifop->file, cmd_tbl, PGC_COMMAND_TBL_SIZE))) + return 0; + + B2N_16(cmd_tbl->nr_of_pre); + B2N_16(cmd_tbl->nr_of_post); + B2N_16(cmd_tbl->nr_of_cell); + B2N_16(cmd_tbl->last_byte); + + CHECK_VALUE(cmd_tbl->nr_of_pre + cmd_tbl->nr_of_post + cmd_tbl->nr_of_cell<= 255); + CHECK_VALUE((cmd_tbl->nr_of_pre + cmd_tbl->nr_of_post + cmd_tbl->nr_of_cell) * COMMAND_DATA_SIZE + + PGC_COMMAND_TBL_SIZE <= cmd_tbl->last_byte + 1); + + if(cmd_tbl->nr_of_pre != 0) { + unsigned int pre_cmds_size = cmd_tbl->nr_of_pre * COMMAND_DATA_SIZE; + cmd_tbl->pre_cmds = malloc(pre_cmds_size); + if(!cmd_tbl->pre_cmds) + return 0; + + if(!(DVDReadBytes(ifop->file, cmd_tbl->pre_cmds, pre_cmds_size))) { + free(cmd_tbl->pre_cmds); + return 0; + } + } + + if(cmd_tbl->nr_of_post != 0) { + unsigned int post_cmds_size = cmd_tbl->nr_of_post * COMMAND_DATA_SIZE; + cmd_tbl->post_cmds = malloc(post_cmds_size); + if(!cmd_tbl->post_cmds) { + if(cmd_tbl->pre_cmds) + free(cmd_tbl->pre_cmds); + return 0; + } + if(!(DVDReadBytes(ifop->file, cmd_tbl->post_cmds, post_cmds_size))) { + if(cmd_tbl->pre_cmds) + free(cmd_tbl->pre_cmds); + free(cmd_tbl->post_cmds); + return 0; + } + } + + if(cmd_tbl->nr_of_cell != 0) { + unsigned int cell_cmds_size = cmd_tbl->nr_of_cell * COMMAND_DATA_SIZE; + cmd_tbl->cell_cmds = malloc(cell_cmds_size); + if(!cmd_tbl->cell_cmds) { + if(cmd_tbl->pre_cmds) + free(cmd_tbl->pre_cmds); + if(cmd_tbl->post_cmds) + free(cmd_tbl->post_cmds); + return 0; + } + if(!(DVDReadBytes(ifop->file, cmd_tbl->cell_cmds, cell_cmds_size))) { + if(cmd_tbl->pre_cmds) + free(cmd_tbl->pre_cmds); + if(cmd_tbl->post_cmds) + free(cmd_tbl->post_cmds); + free(cmd_tbl->cell_cmds); + return 0; + } + } + + /* + * Make a run over all the commands and see that we can interpret them all? + */ + return 1; +} + + +static void ifoFree_PGC_COMMAND_TBL(pgc_command_tbl_t *cmd_tbl) { + if(cmd_tbl) { + if(cmd_tbl->nr_of_pre && cmd_tbl->pre_cmds) + free(cmd_tbl->pre_cmds); + if(cmd_tbl->nr_of_post && cmd_tbl->post_cmds) + free(cmd_tbl->post_cmds); + if(cmd_tbl->nr_of_cell && cmd_tbl->cell_cmds) + free(cmd_tbl->cell_cmds); + free(cmd_tbl); + } +} + +static int ifoRead_PGC_PROGRAM_MAP(ifo_handle_t *ifofile, + pgc_program_map_t *program_map, + unsigned int nr, unsigned int offset) { + struct ifo_handle_private_s *ifop = PRIV(ifofile); + unsigned int size = nr * sizeof(pgc_program_map_t); + + if(!DVDFileSeek_(ifop->file, offset)) + return 0; + + if(!(DVDReadBytes(ifop->file, program_map, size))) + return 0; + + return 1; +} + +static int ifoRead_CELL_PLAYBACK_TBL(ifo_handle_t *ifofile, + cell_playback_t *cell_playback, + unsigned int nr, unsigned int offset) { + struct ifo_handle_private_s *ifop = PRIV(ifofile); + unsigned int i; + unsigned int size = nr * sizeof(cell_playback_t); + + if(!DVDFileSeek_(ifop->file, offset)) + return 0; + + if(!(DVDReadBytes(ifop->file, cell_playback, size))) + return 0; + + for(i = 0; i < nr; i++) { + read_cell_playback(&cell_playback[i]); + /* Changed < to <= because this was false in the movie 'Pi'. */ + CHECK_VALUE(cell_playback[i].last_vobu_start_sector <= + cell_playback[i].last_sector); + CHECK_VALUE(cell_playback[i].first_sector <= + cell_playback[i].last_vobu_start_sector); + } + + return 1; +} + + +static int ifoRead_CELL_POSITION_TBL(ifo_handle_t *ifofile, + cell_position_t *cell_position, + unsigned int nr, unsigned int offset) { + struct ifo_handle_private_s *ifop = PRIV(ifofile); + unsigned int i; + unsigned int size = nr * sizeof(cell_position_t); + + if(!DVDFileSeek_(ifop->file, offset)) + return 0; + + if(!(DVDReadBytes(ifop->file, cell_position, size))) + return 0; + + for(i = 0; i < nr; i++) { + B2N_16(cell_position[i].vob_id_nr); + CHECK_ZERO(cell_position[i].zero_1); + } + + return 1; +} + +static int ifoRead_PGC(ifo_handle_t *ifofile, pgc_t *pgc, unsigned int offset) { + struct ifo_handle_private_s *ifop = PRIV(ifofile); + unsigned int i; + + if(!DVDFileSeek_(ifop->file, offset)) + return 0; + + if(!(DVDReadBytes(ifop->file, pgc, PGC_SIZE))) + return 0; + + read_user_ops(&pgc->prohibited_ops); + B2N_16(pgc->next_pgc_nr); + B2N_16(pgc->prev_pgc_nr); + B2N_16(pgc->goup_pgc_nr); + B2N_16(pgc->command_tbl_offset); + B2N_16(pgc->program_map_offset); + B2N_16(pgc->cell_playback_offset); + B2N_16(pgc->cell_position_offset); + + for(i = 0; i < 8; i++) + B2N_16(pgc->audio_control[i]); + for(i = 0; i < 32; i++) + B2N_32(pgc->subp_control[i]); + for(i = 0; i < 16; i++) + B2N_32(pgc->palette[i]); + + CHECK_ZERO(pgc->zero_1); + CHECK_VALUE(pgc->nr_of_programs <= pgc->nr_of_cells); + + /* verify time (look at print_time) */ + for(i = 0; i < 8; i++) + if(!(pgc->audio_control[i] & 0x8000)) /* The 'is present' bit */ + CHECK_ZERO(pgc->audio_control[i]); + for(i = 0; i < 32; i++) + if(!(pgc->subp_control[i] & 0x80000000)) /* The 'is present' bit */ + CHECK_ZERO(pgc->subp_control[i]); + + /* Check that time is 0:0:0:0 also if nr_of_programs == 0 */ + if(pgc->nr_of_programs == 0) { + CHECK_ZERO(pgc->still_time); + CHECK_ZERO(pgc->pg_playback_mode); /* ?? */ + CHECK_VALUE(pgc->program_map_offset == 0); + CHECK_VALUE(pgc->cell_playback_offset == 0); + CHECK_VALUE(pgc->cell_position_offset == 0); + } else { + CHECK_VALUE(pgc->program_map_offset != 0); + CHECK_VALUE(pgc->cell_playback_offset != 0); + CHECK_VALUE(pgc->cell_position_offset != 0); + } + + if(pgc->command_tbl_offset != 0) { + pgc->command_tbl = calloc(1, sizeof(pgc_command_tbl_t)); + if(!pgc->command_tbl) + return 0; + + if(!ifoRead_PGC_COMMAND_TBL(ifofile, pgc->command_tbl, + offset + pgc->command_tbl_offset)) { + return 0; + } + } else { + pgc->command_tbl = NULL; + } + + if(pgc->program_map_offset != 0 && pgc->nr_of_programs>0) { + pgc->program_map = calloc(pgc->nr_of_programs, sizeof(pgc_program_map_t)); + if(!pgc->program_map) { + return 0; + } + if(!ifoRead_PGC_PROGRAM_MAP(ifofile, pgc->program_map,pgc->nr_of_programs, + offset + pgc->program_map_offset)) { + return 0; + } + } else { + pgc->program_map = NULL; + } + + if(pgc->cell_playback_offset != 0 && pgc->nr_of_cells>0) { + pgc->cell_playback = calloc(pgc->nr_of_cells, sizeof(cell_playback_t)); + if(!pgc->cell_playback) { + return 0; + } + if(!ifoRead_CELL_PLAYBACK_TBL(ifofile, pgc->cell_playback, + pgc->nr_of_cells, + offset + pgc->cell_playback_offset)) { + return 0; + } + } else { + pgc->cell_playback = NULL; + } + + if(pgc->cell_position_offset != 0 && pgc->nr_of_cells>0) { + pgc->cell_position = calloc(pgc->nr_of_cells, sizeof(cell_position_t)); + if(!pgc->cell_position) { + return 0; + } + if(!ifoRead_CELL_POSITION_TBL(ifofile, pgc->cell_position, + pgc->nr_of_cells, + offset + pgc->cell_position_offset)) { + return 0; + } + } else { + pgc->cell_position = NULL; + } + + return 1; +} + +int ifoRead_FP_PGC(ifo_handle_t *ifofile) { + + if(!ifofile) + return 0; + + if(!ifofile->vmgi_mat) + return 0; + + /* It seems that first_play_pgc is optional after all. */ + ifofile->first_play_pgc = NULL; + if(!ifofile->vmgi_mat->first_play_pgc) + return 1; + + ifofile->first_play_pgc = calloc(1, sizeof(pgc_t)); + if(!ifofile->first_play_pgc) + return 0; + + ifofile->first_play_pgc->ref_count = 1; + if(!ifoRead_PGC(ifofile, ifofile->first_play_pgc, + ifofile->vmgi_mat->first_play_pgc)) { + ifoFree_PGC(&ifofile->first_play_pgc); + return 0; + } + + return 1; +} + +static void ifoFree_PGC(pgc_t **pgc) { + if(pgc && *pgc && (--(*pgc)->ref_count) <= 0) { + ifoFree_PGC_COMMAND_TBL((*pgc)->command_tbl); + if((*pgc)->program_map) + free((*pgc)->program_map); + if((*pgc)->cell_playback) + free((*pgc)->cell_playback); + if((*pgc)->cell_position) + free((*pgc)->cell_position); + free(*pgc); + } + if (pgc) { + *pgc = NULL; + } +} + +void ifoFree_FP_PGC(ifo_handle_t *ifofile) { + if(!ifofile) + return; + + if(ifofile->first_play_pgc) { + ifoFree_PGC(&ifofile->first_play_pgc); + } +} + + +int ifoRead_TT_SRPT(ifo_handle_t *ifofile) { + struct ifo_handle_private_s *ifop = PRIV(ifofile); + tt_srpt_t *tt_srpt; + unsigned int i; + size_t info_length; + + if(!ifofile) + return 0; + + if(!ifofile->vmgi_mat) + return 0; + + if(ifofile->vmgi_mat->tt_srpt == 0) /* mandatory */ + return 0; + + if(!DVDFileSeek_(ifop->file, ifofile->vmgi_mat->tt_srpt * DVD_BLOCK_LEN)) + return 0; + + tt_srpt = calloc(1, sizeof(tt_srpt_t)); + if(!tt_srpt) + return 0; + + ifofile->tt_srpt = tt_srpt; + + if(!(DVDReadBytes(ifop->file, tt_srpt, TT_SRPT_SIZE))) { + Log0(ifop->ctx, "Unable to read read TT_SRPT."); + free(tt_srpt); + return 0; + } + + B2N_16(tt_srpt->nr_of_srpts); + B2N_32(tt_srpt->last_byte); + + /* E-One releases don't fill this field */ + if(tt_srpt->last_byte == 0) { + tt_srpt->last_byte = tt_srpt->nr_of_srpts * sizeof(title_info_t) - 1 + TT_SRPT_SIZE; + } + info_length = tt_srpt->last_byte + 1 - TT_SRPT_SIZE; + + tt_srpt->title = calloc(1, info_length); + if(!tt_srpt->title) { + free(tt_srpt); + ifofile->tt_srpt = NULL; + return 0; + } + if(!(DVDReadBytes(ifop->file, tt_srpt->title, info_length))) { + Log0(ifop->ctx, "libdvdread: Unable to read read TT_SRPT."); + ifoFree_TT_SRPT(ifofile); + return 0; + } + + if(tt_srpt->nr_of_srpts>info_length/sizeof(title_info_t)){ + Log1(ifop->ctx, "data mismatch: info_length (%zd)!= nr_of_srpts (%d). Truncating.", + info_length/sizeof(title_info_t),tt_srpt->nr_of_srpts); + tt_srpt->nr_of_srpts=info_length/sizeof(title_info_t); + } + + for(i = 0; i < tt_srpt->nr_of_srpts; i++) { + B2N_16(tt_srpt->title[i].nr_of_ptts); + B2N_16(tt_srpt->title[i].parental_id); + B2N_32(tt_srpt->title[i].title_set_sector); + } + + + CHECK_ZERO(tt_srpt->zero_1); + CHECK_VALUE(tt_srpt->nr_of_srpts != 0); + CHECK_VALUE(tt_srpt->nr_of_srpts < 100); /* ?? */ + CHECK_VALUE(tt_srpt->nr_of_srpts * sizeof(title_info_t) <= info_length); + + for(i = 0; i < tt_srpt->nr_of_srpts; i++) { + read_playback_type(&tt_srpt->title[i].pb_ty); + CHECK_VALUE(tt_srpt->title[i].pb_ty.zero_1 == 0); + CHECK_VALUE(tt_srpt->title[i].nr_of_angles != 0); + CHECK_VALUE(tt_srpt->title[i].nr_of_angles < 10); + /* CHECK_VALUE(tt_srpt->title[i].nr_of_ptts != 0); */ + /* XXX: this assertion breaks Ghostbusters: */ + CHECK_VALUE(tt_srpt->title[i].nr_of_ptts < 1000); /* ?? */ + CHECK_VALUE(tt_srpt->title[i].title_set_nr != 0); + CHECK_VALUE(tt_srpt->title[i].title_set_nr < 100); /* ?? */ + CHECK_VALUE(tt_srpt->title[i].vts_ttn != 0); + CHECK_VALUE(tt_srpt->title[i].vts_ttn < 100); /* ?? */ + /* CHECK_VALUE(tt_srpt->title[i].title_set_sector != 0); */ + } + + /* Make this a function */ +#if 0 + if(memcmp((uint8_t *)tt_srpt->title + + tt_srpt->nr_of_srpts * sizeof(title_info_t), + my_friendly_zeros, + info_length - tt_srpt->nr_of_srpts * sizeof(title_info_t))) { + Log1(ifop->ctx, "VMG_PTT_SRPT slack is != 0, "); + hexdump((uint8_t *)tt_srpt->title + + tt_srpt->nr_of_srpts * sizeof(title_info_t), + info_length - tt_srpt->nr_of_srpts * sizeof(title_info_t)); + } +#endif + + return 1; +} + + +void ifoFree_TT_SRPT(ifo_handle_t *ifofile) { + if(!ifofile) + return; + + if(ifofile->tt_srpt) { + free(ifofile->tt_srpt->title); + ifofile->tt_srpt->title = NULL; + free(ifofile->tt_srpt); + ifofile->tt_srpt = NULL; + } +} + + +int ifoRead_VTS_PTT_SRPT(ifo_handle_t *ifofile) { + struct ifo_handle_private_s *ifop = PRIV(ifofile); + vts_ptt_srpt_t *vts_ptt_srpt = NULL; + int info_length, i, j; + uint32_t *data = NULL; + + if(!ifofile) + return 0; + + if(!ifofile->vtsi_mat) + return 0; + + if(ifofile->vtsi_mat->vts_ptt_srpt == 0) /* mandatory */ + return 0; + + if(!DVDFileSeek_(ifop->file, + ifofile->vtsi_mat->vts_ptt_srpt * DVD_BLOCK_LEN)) + return 0; + + vts_ptt_srpt = calloc(1, sizeof(vts_ptt_srpt_t)); + if(!vts_ptt_srpt) + return 0; + + vts_ptt_srpt->title = NULL; + ifofile->vts_ptt_srpt = vts_ptt_srpt; + + if(!(DVDReadBytes(ifop->file, vts_ptt_srpt, VTS_PTT_SRPT_SIZE))) { + Log0(ifop->ctx, "Unable to read PTT search table."); + goto fail; + } + + B2N_16(vts_ptt_srpt->nr_of_srpts); + B2N_32(vts_ptt_srpt->last_byte); + + CHECK_ZERO(vts_ptt_srpt->zero_1); + CHECK_VALUE(vts_ptt_srpt->nr_of_srpts != 0); + CHECK_VALUE(vts_ptt_srpt->nr_of_srpts < 100); /* ?? */ + + /* E-One releases don't fill this field */ + if(vts_ptt_srpt->last_byte == 0) { + vts_ptt_srpt->last_byte = vts_ptt_srpt->nr_of_srpts * sizeof(*data) - 1 + VTS_PTT_SRPT_SIZE; + } + info_length = vts_ptt_srpt->last_byte + 1 - VTS_PTT_SRPT_SIZE; + data = calloc(1, info_length); + if(!data) + goto fail; + + if(!(DVDReadBytes(ifop->file, data, info_length))) { + Log0(ifop->ctx, "Unable to read PTT search table."); + goto fail; + } + + if(vts_ptt_srpt->nr_of_srpts > info_length / sizeof(*data)) { + Log0(ifop->ctx, "PTT search table too small."); + goto fail; + } + + if(vts_ptt_srpt->nr_of_srpts == 0) { + Log0(ifop->ctx, "Zero entries in PTT search table."); + goto fail; + } + + for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) { + /* Transformers 3 has PTT start bytes that point outside the SRPT PTT */ + uint32_t start = data[i]; + B2N_32(start); + if(start + sizeof(ptt_info_t) > vts_ptt_srpt->last_byte + 1) { + /* don't mess with any bytes beyond the end of the allocation */ + vts_ptt_srpt->nr_of_srpts = i; + break; + } + data[i] = start; + /* assert(data[i] + sizeof(ptt_info_t) <= vts_ptt_srpt->last_byte + 1); + Magic Knight Rayearth Daybreak is mastered very strange and has + Titles with 0 PTTs. They all have a data[i] offsets beyond the end of + of the vts_ptt_srpt structure. */ + CHECK_VALUE(data[i] + sizeof(ptt_info_t) <= vts_ptt_srpt->last_byte + 1 + 4); + } + + vts_ptt_srpt->ttu_offset = data; + + vts_ptt_srpt->title = calloc(vts_ptt_srpt->nr_of_srpts, sizeof(ttu_t)); + if(!vts_ptt_srpt->title) + goto fail; + + for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) { + int n; + if(i < vts_ptt_srpt->nr_of_srpts - 1) + n = (data[i+1] - data[i]); + else + n = (vts_ptt_srpt->last_byte + 1 - data[i]); + + /* assert(n > 0 && (n % 4) == 0); + Magic Knight Rayearth Daybreak is mastered very strange and has + Titles with 0 PTTs. */ + if(n < 0) n = 0; + + /* DVDs created by the VDR-to-DVD device LG RC590M violate the following requirement */ + CHECK_VALUE(n % 4 == 0); + + vts_ptt_srpt->title[i].nr_of_ptts = n / 4; + vts_ptt_srpt->title[i].ptt = calloc(n / 4, sizeof(ptt_info_t)); + if(!vts_ptt_srpt->title[i].ptt) { + for(n = 0; n < i; n++) + free(vts_ptt_srpt->title[n].ptt); + + goto fail; + } + for(j = 0; j < vts_ptt_srpt->title[i].nr_of_ptts; j++) { + /* The assert placed here because of Magic Knight Rayearth Daybreak */ + CHECK_VALUE(data[i] + sizeof(ptt_info_t) <= vts_ptt_srpt->last_byte + 1); + vts_ptt_srpt->title[i].ptt[j].pgcn + = *(uint16_t*)(((char *)data) + data[i] + 4*j - VTS_PTT_SRPT_SIZE); + vts_ptt_srpt->title[i].ptt[j].pgn + = *(uint16_t*)(((char *)data) + data[i] + 4*j + 2 - VTS_PTT_SRPT_SIZE); + } + } + + for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) { + for(j = 0; j < vts_ptt_srpt->title[i].nr_of_ptts; j++) { + B2N_16(vts_ptt_srpt->title[i].ptt[j].pgcn); + B2N_16(vts_ptt_srpt->title[i].ptt[j].pgn); + } + } + + for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) { + CHECK_VALUE(vts_ptt_srpt->title[i].nr_of_ptts < 1000); /* ?? */ + for(j = 0; j < vts_ptt_srpt->title[i].nr_of_ptts; j++) { + CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgcn != 0 ); + CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgcn < 1000); /* ?? */ + CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgn != 0); + CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgn < 100); /* ?? */ + //don't abort here. E-One DVDs contain PTT with pgcn or pgn == 0 + } + } + + return 1; + +fail: + free(data); + ifofile->vts_ptt_srpt = NULL; + free(vts_ptt_srpt->title); + free(vts_ptt_srpt); + return 0; +} + + +void ifoFree_VTS_PTT_SRPT(ifo_handle_t *ifofile) { + if(!ifofile) + return; + + if(ifofile->vts_ptt_srpt) { + int i; + for(i = 0; i < ifofile->vts_ptt_srpt->nr_of_srpts; i++) + free(ifofile->vts_ptt_srpt->title[i].ptt); + free(ifofile->vts_ptt_srpt->ttu_offset); + free(ifofile->vts_ptt_srpt->title); + free(ifofile->vts_ptt_srpt); + ifofile->vts_ptt_srpt = 0; + } +} + + +int ifoRead_PTL_MAIT(ifo_handle_t *ifofile) { + struct ifo_handle_private_s *ifop = PRIV(ifofile); + ptl_mait_t *ptl_mait; + int info_length; + unsigned int i, j; + + if(!ifofile) + return 0; + + if(!ifofile->vmgi_mat) + return 0; + + if(!ifofile->vmgi_mat->ptl_mait) + return 1; + + if(!DVDFileSeek_(ifop->file, ifofile->vmgi_mat->ptl_mait * DVD_BLOCK_LEN)) + return 0; + + ptl_mait = calloc(1, sizeof(ptl_mait_t)); + if(!ptl_mait) + return 0; + + ifofile->ptl_mait = ptl_mait; + + if(!(DVDReadBytes(ifop->file, ptl_mait, PTL_MAIT_SIZE))) { + free(ptl_mait); + ifofile->ptl_mait = NULL; + return 0; + } + + B2N_16(ptl_mait->nr_of_countries); + B2N_16(ptl_mait->nr_of_vtss); + B2N_32(ptl_mait->last_byte); + + CHECK_VALUE(ptl_mait->nr_of_countries != 0); + CHECK_VALUE(ptl_mait->nr_of_countries < 100); /* ?? */ + CHECK_VALUE(ptl_mait->nr_of_vtss != 0); + CHECK_VALUE(ptl_mait->nr_of_vtss < 100); /* ?? */ + CHECK_VALUE(ptl_mait->nr_of_countries * PTL_MAIT_COUNTRY_SIZE + <= ptl_mait->last_byte + 1 - PTL_MAIT_SIZE); + + info_length = ptl_mait->nr_of_countries * sizeof(ptl_mait_country_t); + ptl_mait->countries = calloc(1, info_length); + if(!ptl_mait->countries) { + free(ptl_mait); + ifofile->ptl_mait = NULL; + return 0; + } + for(i = 0; i < ptl_mait->nr_of_countries; i++) { + ptl_mait->countries[i].pf_ptl_mai = NULL; + } + + for(i = 0; i < ptl_mait->nr_of_countries; i++) { + if(!(DVDReadBytes(ifop->file, &ptl_mait->countries[i], PTL_MAIT_COUNTRY_SIZE))) { + Log0(ifop->ctx, "Unable to read PTL_MAIT."); + free(ptl_mait->countries); + free(ptl_mait); + ifofile->ptl_mait = NULL; + return 0; + } + } + + for(i = 0; i < ptl_mait->nr_of_countries; i++) { + B2N_16(ptl_mait->countries[i].country_code); + B2N_16(ptl_mait->countries[i].pf_ptl_mai_start_byte); + } + + for(i = 0; i < ptl_mait->nr_of_countries; i++) { + CHECK_ZERO(ptl_mait->countries[i].zero_1); + CHECK_ZERO(ptl_mait->countries[i].zero_2); + CHECK_VALUE(ptl_mait->countries[i].pf_ptl_mai_start_byte + + sizeof(pf_level_t) * (ptl_mait->nr_of_vtss + 1) <= ptl_mait->last_byte + 1); + } + + for(i = 0; i < ptl_mait->nr_of_countries; i++) { + uint16_t *pf_temp; + + if(!DVDFileSeek_(ifop->file, + ifofile->vmgi_mat->ptl_mait * DVD_BLOCK_LEN + + ptl_mait->countries[i].pf_ptl_mai_start_byte)) { + Log0(ifop->ctx, "Unable to seek PTL_MAIT table at index %d.",i); + free(ptl_mait->countries); + free(ptl_mait); + ifofile->ptl_mait = NULL; + return 0; + } + info_length = (ptl_mait->nr_of_vtss + 1) * sizeof(pf_level_t); + pf_temp = calloc(1, info_length); + if(!pf_temp) { + free_ptl_mait(ptl_mait, i); + ifofile->ptl_mait = NULL; + return 0; + } + if(!(DVDReadBytes(ifop->file, pf_temp, info_length))) { + Log0(ifop->ctx, "Unable to read PTL_MAIT table at index %d.",i); + free(pf_temp); + free_ptl_mait(ptl_mait, i); + ifofile->ptl_mait = NULL; + return 0; + } + for (j = 0; j < ((ptl_mait->nr_of_vtss + 1U) * 8U); j++) { + B2N_16(pf_temp[j]); + } + ptl_mait->countries[i].pf_ptl_mai = calloc(1, info_length); + if(!ptl_mait->countries[i].pf_ptl_mai) { + free(pf_temp); + free_ptl_mait(ptl_mait, i); + ifofile->ptl_mait = NULL; + return 0; + } + { /* Transpose the array so we can use C indexing. */ + int level, vts; + for(level = 0; level < PTL_MAIT_NUM_LEVEL; level++) { + for(vts = 0; vts <= ptl_mait->nr_of_vtss; vts++) { + ptl_mait->countries[i].pf_ptl_mai[vts][level] = + pf_temp[(7-level)*(ptl_mait->nr_of_vtss+1) + vts]; + } + } + free(pf_temp); + } + } + return 1; +} + +void ifoFree_PTL_MAIT(ifo_handle_t *ifofile) { + if(!ifofile) + return; + + if(ifofile->ptl_mait) { + unsigned int i; + + for(i = 0; i < ifofile->ptl_mait->nr_of_countries; i++) { + free(ifofile->ptl_mait->countries[i].pf_ptl_mai); + } + free(ifofile->ptl_mait->countries); + free(ifofile->ptl_mait); + ifofile->ptl_mait = NULL; + } +} + +int ifoRead_VTS_TMAPT(ifo_handle_t *ifofile) { + struct ifo_handle_private_s *ifop = PRIV(ifofile); + vts_tmapt_t *vts_tmapt; + uint32_t *vts_tmap_srp; + unsigned int offset; + int info_length; + unsigned int i, j; + + if(!ifofile) + return 0; + + if(!ifofile->vtsi_mat) + return 0; + + if(ifofile->vtsi_mat->vts_tmapt == 0) { + ifofile->vts_tmapt = NULL; + return 1; + } + + offset = ifofile->vtsi_mat->vts_tmapt * DVD_BLOCK_LEN; + + if(!DVDFileSeek_(ifop->file, offset)) + return 0; + + vts_tmapt = calloc(1, sizeof(vts_tmapt_t)); + if(!vts_tmapt) + return 0; + + ifofile->vts_tmapt = vts_tmapt; + + if(!(DVDReadBytes(ifop->file, vts_tmapt, VTS_TMAPT_SIZE))) { + Log0(ifop->ctx, "Unable to read VTS_TMAPT."); + free(vts_tmapt); + ifofile->vts_tmapt = NULL; + return 0; + } + + B2N_16(vts_tmapt->nr_of_tmaps); + B2N_32(vts_tmapt->last_byte); + + CHECK_ZERO(vts_tmapt->zero_1); + + info_length = vts_tmapt->nr_of_tmaps * 4; + + vts_tmap_srp = calloc(1, info_length); + if(!vts_tmap_srp) { + free(vts_tmapt); + ifofile->vts_tmapt = NULL; + return 0; + } + + vts_tmapt->tmap_offset = vts_tmap_srp; + + if(!(DVDReadBytes(ifop->file, vts_tmap_srp, info_length))) { + Log0(ifop->ctx, "Unable to read VTS_TMAPT."); + free(vts_tmap_srp); + free(vts_tmapt); + ifofile->vts_tmapt = NULL; + return 0; + } + + for (i = 0; i < vts_tmapt->nr_of_tmaps; i++) { + B2N_32(vts_tmap_srp[i]); + } + + + info_length = vts_tmapt->nr_of_tmaps * sizeof(vts_tmap_t); + + vts_tmapt->tmap = calloc(1, info_length); + if(!vts_tmapt->tmap) { + free(vts_tmap_srp); + free(vts_tmapt); + ifofile->vts_tmapt = NULL; + return 0; + } + + for(i = 0; i < vts_tmapt->nr_of_tmaps; i++) { + if(!DVDFileSeek_(ifop->file, offset + vts_tmap_srp[i])) { + ifoFree_VTS_TMAPT(ifofile); + return 0; + } + + if(!(DVDReadBytes(ifop->file, &vts_tmapt->tmap[i], VTS_TMAP_SIZE))) { + Log0(ifop->ctx, "Unable to read VTS_TMAP."); + ifoFree_VTS_TMAPT(ifofile); + return 0; + } + + B2N_16(vts_tmapt->tmap[i].nr_of_entries); + CHECK_ZERO(vts_tmapt->tmap[i].zero_1); + + if(vts_tmapt->tmap[i].nr_of_entries == 0) { /* Early out if zero entries */ + vts_tmapt->tmap[i].map_ent = NULL; + continue; + } + + info_length = vts_tmapt->tmap[i].nr_of_entries * sizeof(map_ent_t); + + vts_tmapt->tmap[i].map_ent = calloc(1, info_length); + if(!vts_tmapt->tmap[i].map_ent) { + ifoFree_VTS_TMAPT(ifofile); + return 0; + } + + if(!(DVDReadBytes(ifop->file, vts_tmapt->tmap[i].map_ent, info_length))) { + Log0(ifop->ctx, "Unable to read VTS_TMAP_ENT."); + ifoFree_VTS_TMAPT(ifofile); + return 0; + } + + for(j = 0; j < vts_tmapt->tmap[i].nr_of_entries; j++) + B2N_32(vts_tmapt->tmap[i].map_ent[j]); + } + + return 1; +} + +void ifoFree_VTS_TMAPT(ifo_handle_t *ifofile) { + if(!ifofile) + return; + + if(ifofile->vts_tmapt) { + unsigned int i; + + for(i = 0; i < ifofile->vts_tmapt->nr_of_tmaps; i++) + if(ifofile->vts_tmapt->tmap[i].map_ent) + free(ifofile->vts_tmapt->tmap[i].map_ent); + free(ifofile->vts_tmapt->tmap); + free(ifofile->vts_tmapt->tmap_offset); + free(ifofile->vts_tmapt); + ifofile->vts_tmapt = NULL; + } +} + + +int ifoRead_TITLE_C_ADT(ifo_handle_t *ifofile) { + + if(!ifofile) + return 0; + + if(!ifofile->vtsi_mat) + return 0; + + if(ifofile->vtsi_mat->vts_c_adt == 0) /* mandatory */ + return 0; + + ifofile->vts_c_adt = calloc(1, sizeof(c_adt_t)); + if(!ifofile->vts_c_adt) + return 0; + + if(!ifoRead_C_ADT_internal(ifofile, ifofile->vts_c_adt, + ifofile->vtsi_mat->vts_c_adt)) { + free(ifofile->vts_c_adt); + ifofile->vts_c_adt = NULL; + return 0; + } + + return 1; +} + +int ifoRead_C_ADT(ifo_handle_t *ifofile) { + unsigned int sector; + + if(!ifofile) + return 0; + + if(ifofile->vmgi_mat) { + if(ifofile->vmgi_mat->vmgm_c_adt == 0) + return 1; + sector = ifofile->vmgi_mat->vmgm_c_adt; + } else if(ifofile->vtsi_mat) { + if(ifofile->vtsi_mat->vtsm_c_adt == 0) + return 1; + sector = ifofile->vtsi_mat->vtsm_c_adt; + } else { + return 0; + } + + ifofile->menu_c_adt = calloc(1, sizeof(c_adt_t)); + if(!ifofile->menu_c_adt) + return 0; + + if(!ifoRead_C_ADT_internal(ifofile, ifofile->menu_c_adt, sector)) { + free(ifofile->menu_c_adt); + ifofile->menu_c_adt = NULL; + return 0; + } + + return 1; +} + +static int ifoRead_C_ADT_internal(ifo_handle_t *ifofile, + c_adt_t *c_adt, unsigned int sector) { + struct ifo_handle_private_s *ifop = PRIV(ifofile); + size_t i, info_length; + + if(!DVDFileSeek_(ifop->file, sector * DVD_BLOCK_LEN)) + return 0; + + if(!(DVDReadBytes(ifop->file, c_adt, C_ADT_SIZE))) + return 0; + + B2N_16(c_adt->nr_of_vobs); + B2N_32(c_adt->last_byte); + + if(c_adt->last_byte + 1 < C_ADT_SIZE) + return 0; + + info_length = c_adt->last_byte + 1 - C_ADT_SIZE; + + CHECK_ZERO(c_adt->zero_1); + /* assert(c_adt->nr_of_vobs > 0); + Magic Knight Rayearth Daybreak is mastered very strange and has + Titles with a VOBS that has no cells. */ + CHECK_VALUE(info_length % sizeof(cell_adr_t) == 0); + + /* assert(info_length / sizeof(cell_adr_t) >= c_adt->nr_of_vobs); + Enemy of the State region 2 (de) has Titles where nr_of_vobs field + is to high, they high ones are never referenced though. */ + if(info_length / sizeof(cell_adr_t) < c_adt->nr_of_vobs) { + Log1(ifop->ctx, "C_ADT nr_of_vobs > available info entries"); + c_adt->nr_of_vobs = info_length / sizeof(cell_adr_t); + } + + c_adt->cell_adr_table = calloc(1, info_length); + if(!c_adt->cell_adr_table) + return 0; + + if(info_length && + !(DVDReadBytes(ifop->file, c_adt->cell_adr_table, info_length))) { + free(c_adt->cell_adr_table); + return 0; + } + + for(i = 0; i < info_length/sizeof(cell_adr_t); i++) { + B2N_16(c_adt->cell_adr_table[i].vob_id); + B2N_32(c_adt->cell_adr_table[i].start_sector); + B2N_32(c_adt->cell_adr_table[i].last_sector); + + CHECK_ZERO(c_adt->cell_adr_table[i].zero_1); + CHECK_VALUE(c_adt->cell_adr_table[i].vob_id > 0); + CHECK_VALUE(c_adt->cell_adr_table[i].vob_id <= c_adt->nr_of_vobs); + CHECK_VALUE(c_adt->cell_adr_table[i].cell_id > 0); + CHECK_VALUE(c_adt->cell_adr_table[i].start_sector < + c_adt->cell_adr_table[i].last_sector); + } + + return 1; +} + + +static void ifoFree_C_ADT_internal(c_adt_t *c_adt) { + if(c_adt) { + free(c_adt->cell_adr_table); + free(c_adt); + } +} + +void ifoFree_C_ADT(ifo_handle_t *ifofile) { + if(!ifofile) + return; + + ifoFree_C_ADT_internal(ifofile->menu_c_adt); + ifofile->menu_c_adt = NULL; +} + +void ifoFree_TITLE_C_ADT(ifo_handle_t *ifofile) { + if(!ifofile) + return; + + ifoFree_C_ADT_internal(ifofile->vts_c_adt); + ifofile->vts_c_adt = NULL; +} + +int ifoRead_TITLE_VOBU_ADMAP(ifo_handle_t *ifofile) { + if(!ifofile) + return 0; + + if(!ifofile->vtsi_mat) + return 0; + + if(ifofile->vtsi_mat->vts_vobu_admap == 0) /* mandatory */ + return 0; + + ifofile->vts_vobu_admap = calloc(1, sizeof(vobu_admap_t)); + if(!ifofile->vts_vobu_admap) + return 0; + + if(!ifoRead_VOBU_ADMAP_internal(ifofile, ifofile->vts_vobu_admap, + ifofile->vtsi_mat->vts_vobu_admap)) { + free(ifofile->vts_vobu_admap); + ifofile->vts_vobu_admap = NULL; + return 0; + } + + return 1; +} + +int ifoRead_VOBU_ADMAP(ifo_handle_t *ifofile) { + unsigned int sector; + + if(!ifofile) + return 0; + + if(ifofile->vmgi_mat) { + if(ifofile->vmgi_mat->vmgm_vobu_admap == 0) + return 1; + sector = ifofile->vmgi_mat->vmgm_vobu_admap; + } else if(ifofile->vtsi_mat) { + if(ifofile->vtsi_mat->vtsm_vobu_admap == 0) + return 1; + sector = ifofile->vtsi_mat->vtsm_vobu_admap; + } else { + return 0; + } + + ifofile->menu_vobu_admap = calloc(1, sizeof(vobu_admap_t)); + if(!ifofile->menu_vobu_admap) + return 0; + + if(!ifoRead_VOBU_ADMAP_internal(ifofile, ifofile->menu_vobu_admap, sector)) { + free(ifofile->menu_vobu_admap); + ifofile->menu_vobu_admap = NULL; + return 0; + } + + return 1; +} + +static int ifoRead_VOBU_ADMAP_internal(ifo_handle_t *ifofile, + vobu_admap_t *vobu_admap, + unsigned int sector) { + struct ifo_handle_private_s *ifop = PRIV(ifofile); + unsigned int i; + int info_length; + + if(!DVDFileSeekForce_(ifop->file, sector * DVD_BLOCK_LEN, sector)) + return 0; + + if(!(DVDReadBytes(ifop->file, vobu_admap, VOBU_ADMAP_SIZE))) + return 0; + + B2N_32(vobu_admap->last_byte); + + info_length = vobu_admap->last_byte + 1 - VOBU_ADMAP_SIZE; + /* assert(info_length > 0); + Magic Knight Rayearth Daybreak is mastered very strange and has + Titles with a VOBS that has no VOBUs. */ + CHECK_VALUE(info_length % sizeof(uint32_t) == 0); + + vobu_admap->vobu_start_sectors = calloc(1, info_length); + if(!vobu_admap->vobu_start_sectors) { + return 0; + } + if(info_length && + !(DVDReadBytes(ifop->file, + vobu_admap->vobu_start_sectors, info_length))) { + free(vobu_admap->vobu_start_sectors); + return 0; + } + + for(i = 0; i < info_length/sizeof(uint32_t); i++) + B2N_32(vobu_admap->vobu_start_sectors[i]); + + return 1; +} + + +static void ifoFree_VOBU_ADMAP_internal(vobu_admap_t *vobu_admap) { + if(vobu_admap) { + free(vobu_admap->vobu_start_sectors); + free(vobu_admap); + } +} + +void ifoFree_VOBU_ADMAP(ifo_handle_t *ifofile) { + if(!ifofile) + return; + + ifoFree_VOBU_ADMAP_internal(ifofile->menu_vobu_admap); + ifofile->menu_vobu_admap = NULL; +} + +void ifoFree_TITLE_VOBU_ADMAP(ifo_handle_t *ifofile) { + if(!ifofile) + return; + + ifoFree_VOBU_ADMAP_internal(ifofile->vts_vobu_admap); + ifofile->vts_vobu_admap = NULL; +} + +int ifoRead_PGCIT(ifo_handle_t *ifofile) { + + if(!ifofile) + return 0; + + if(!ifofile->vtsi_mat) + return 0; + + if(ifofile->vtsi_mat->vts_pgcit == 0) /* mandatory */ + return 0; + + ifofile->vts_pgcit = calloc(1, sizeof(pgcit_t)); + if(!ifofile->vts_pgcit) + return 0; + + ifofile->vts_pgcit->ref_count = 1; + if(!ifoRead_PGCIT_internal(ifofile, ifofile->vts_pgcit, + ifofile->vtsi_mat->vts_pgcit * DVD_BLOCK_LEN)) { + free(ifofile->vts_pgcit); + ifofile->vts_pgcit = NULL; + return 0; + } + + return 1; +} + +static int find_dup_pgc(pgci_srp_t *pgci_srp, uint32_t start_byte, int count) { + int i; + + for(i = 0; i < count; i++) { + if(pgci_srp[i].pgc_start_byte == start_byte) { + return i; + } + } + return -1; +} + +static int ifoRead_PGCIT_internal(ifo_handle_t *ifofile, pgcit_t *pgcit, + unsigned int offset) { + struct ifo_handle_private_s *ifop = PRIV(ifofile); + int i, info_length; + uint8_t *data, *ptr; + + if(!DVDFileSeek_(ifop->file, offset)) + return 0; + + if(!(DVDReadBytes(ifop->file, pgcit, PGCIT_SIZE))) + return 0; + + B2N_16(pgcit->nr_of_pgci_srp); + B2N_32(pgcit->last_byte); + + CHECK_ZERO(pgcit->zero_1); + /* assert(pgcit->nr_of_pgci_srp != 0); + Magic Knight Rayearth Daybreak is mastered very strange and has + Titles with 0 PTTs. */ + CHECK_VALUE(pgcit->nr_of_pgci_srp < 10000); /* ?? seen max of 1338 */ + + if (pgcit->nr_of_pgci_srp == 0) { + pgcit->pgci_srp = NULL; + return 1; + } + + info_length = pgcit->nr_of_pgci_srp * PGCI_SRP_SIZE; + data = calloc(1, info_length); + if(!data) + return 0; + + if(info_length && !(DVDReadBytes(ifop->file, data, info_length))) { + free(data); + return 0; + } + + pgcit->pgci_srp = calloc(pgcit->nr_of_pgci_srp, sizeof(pgci_srp_t)); + if(!pgcit->pgci_srp) { + free(data); + return 0; + } + ptr = data; + for(i = 0; i < pgcit->nr_of_pgci_srp; i++) { + memcpy(&pgcit->pgci_srp[i], ptr, PGCI_SRP_SIZE); + ptr += PGCI_SRP_SIZE; + read_pgci_srp(&pgcit->pgci_srp[i]); + CHECK_VALUE(pgcit->pgci_srp[i].zero_1 == 0); + } + free(data); + + for(i = 0; i < pgcit->nr_of_pgci_srp; i++) + CHECK_VALUE(pgcit->pgci_srp[i].pgc_start_byte + PGC_SIZE <= pgcit->last_byte+1); + + for(i = 0; i < pgcit->nr_of_pgci_srp; i++) { + int dup; + if((dup = find_dup_pgc(pgcit->pgci_srp, pgcit->pgci_srp[i].pgc_start_byte, i)) >= 0) { + pgcit->pgci_srp[i].pgc = pgcit->pgci_srp[dup].pgc; + pgcit->pgci_srp[i].pgc->ref_count++; + continue; + } + pgcit->pgci_srp[i].pgc = calloc(1, sizeof(pgc_t)); + if(!pgcit->pgci_srp[i].pgc) { + int j; + for(j = 0; j < i; j++) { + ifoFree_PGC(&pgcit->pgci_srp[j].pgc); + } + goto fail; + } + pgcit->pgci_srp[i].pgc->ref_count = 1; + if(!ifoRead_PGC(ifofile, pgcit->pgci_srp[i].pgc, + offset + pgcit->pgci_srp[i].pgc_start_byte)) { + Log0(ifop->ctx, "Unable to read invalid PCG"); + //E-One releases provide bogus PGC, ie: out of bound start_byte + free(pgcit->pgci_srp[i].pgc); + pgcit->pgci_srp[i].pgc = NULL; + } + } + + return 1; +fail: + free(pgcit->pgci_srp); + pgcit->pgci_srp = NULL; + return 0; +} + +static void ifoFree_PGCIT_internal(pgcit_t **pgcit) { + if(pgcit && *pgcit && (--(*pgcit)->ref_count <= 0)) { + int i; + for(i = 0; i < (*pgcit)->nr_of_pgci_srp; i++) + { + ifoFree_PGC(&(*pgcit)->pgci_srp[i].pgc); + } + free((*pgcit)->pgci_srp); + free(*pgcit); + } + if (pgcit) + *pgcit = NULL; +} + +void ifoFree_PGCIT(ifo_handle_t *ifofile) { + if(!ifofile) + return; + + if(ifofile->vts_pgcit) { + ifoFree_PGCIT_internal(&ifofile->vts_pgcit); + } +} + +static int find_dup_lut(pgci_lu_t *lu, uint32_t start_byte, int count) { + int i; + + for(i = 0; i < count; i++) { + if(lu[i].lang_start_byte == start_byte) { + return i; + } + } + return -1; +} + +int ifoRead_PGCI_UT(ifo_handle_t *ifofile) { + struct ifo_handle_private_s *ifop = PRIV(ifofile); + pgci_ut_t *pgci_ut; + unsigned int sector; + unsigned int i; + int info_length; + uint8_t *data, *ptr; + + if(!ifofile) + return 0; + + if(ifofile->vmgi_mat) { + if(ifofile->vmgi_mat->vmgm_pgci_ut == 0) + return 1; + sector = ifofile->vmgi_mat->vmgm_pgci_ut; + } else if(ifofile->vtsi_mat) { + if(ifofile->vtsi_mat->vtsm_pgci_ut == 0) + return 1; + sector = ifofile->vtsi_mat->vtsm_pgci_ut; + } else { + return 0; + } + + ifofile->pgci_ut = calloc(1, sizeof(pgci_ut_t)); + if(!ifofile->pgci_ut) + return 0; + + if(!DVDFileSeek_(ifop->file, sector * DVD_BLOCK_LEN)) { + free(ifofile->pgci_ut); + ifofile->pgci_ut = NULL; + return 0; + } + + if(!(DVDReadBytes(ifop->file, ifofile->pgci_ut, PGCI_UT_SIZE))) { + free(ifofile->pgci_ut); + ifofile->pgci_ut = NULL; + return 0; + } + + pgci_ut = ifofile->pgci_ut; + + B2N_16(pgci_ut->nr_of_lus); + B2N_32(pgci_ut->last_byte); + + CHECK_ZERO(pgci_ut->zero_1); + CHECK_VALUE(pgci_ut->nr_of_lus != 0); + CHECK_VALUE(pgci_ut->nr_of_lus < 100); /* ?? 3-4 ? */ + CHECK_VALUE((uint32_t)pgci_ut->nr_of_lus * PGCI_LU_SIZE < pgci_ut->last_byte); + + info_length = pgci_ut->nr_of_lus * PGCI_LU_SIZE; + data = calloc(1, info_length); + if(!data) { + free(pgci_ut); + ifofile->pgci_ut = NULL; + return 0; + } + if(!(DVDReadBytes(ifop->file, data, info_length))) { + free(data); + free(pgci_ut); + ifofile->pgci_ut = NULL; + return 0; + } + + pgci_ut->lu = calloc(pgci_ut->nr_of_lus, sizeof(pgci_lu_t)); + if(!pgci_ut->lu) { + free(data); + free(pgci_ut); + ifofile->pgci_ut = NULL; + return 0; + } + ptr = data; + for(i = 0; i < pgci_ut->nr_of_lus; i++) { + memcpy(&pgci_ut->lu[i], ptr, PGCI_LU_SIZE); + ptr += PGCI_LU_SIZE; + B2N_16(pgci_ut->lu[i].lang_code); + B2N_32(pgci_ut->lu[i].lang_start_byte); + } + free(data); + + for(i = 0; i < pgci_ut->nr_of_lus; i++) { + /* Maybe this is only defined for v1.1 and later titles? */ + /* If the bits in 'lu[i].exists' are enumerated abcd efgh then: + VTS_x_yy.IFO VIDEO_TS.IFO + a == 0x83 "Root" 0x82 "Title" + b == 0x84 "Subpicture" + c == 0x85 "Audio" + d == 0x86 "Angle" + e == 0x87 "PTT" + */ + CHECK_VALUE((pgci_ut->lu[i].exists & 0x07) == 0); + } + + for(i = 0; i < pgci_ut->nr_of_lus; i++) { + int dup; + if((dup = find_dup_lut(pgci_ut->lu, pgci_ut->lu[i].lang_start_byte, i)) >= 0) { + pgci_ut->lu[i].pgcit = pgci_ut->lu[dup].pgcit; + pgci_ut->lu[i].pgcit->ref_count++; + continue; + } + pgci_ut->lu[i].pgcit = calloc(1, sizeof(pgcit_t)); + if(!pgci_ut->lu[i].pgcit) { + unsigned int j; + for(j = 0; j < i; j++) { + ifoFree_PGCIT_internal(&pgci_ut->lu[j].pgcit); + } + free(pgci_ut->lu); + free(pgci_ut); + ifofile->pgci_ut = NULL; + return 0; + } + pgci_ut->lu[i].pgcit->ref_count = 1; + if(!ifoRead_PGCIT_internal(ifofile, pgci_ut->lu[i].pgcit, + sector * DVD_BLOCK_LEN + + pgci_ut->lu[i].lang_start_byte)) { + unsigned int j; + for(j = 0; j <= i; j++) { + ifoFree_PGCIT_internal(&pgci_ut->lu[j].pgcit); + } + free(pgci_ut->lu); + free(pgci_ut); + ifofile->pgci_ut = NULL; + return 0; + } + /* FIXME: Iterate and verify that all menus that should exists accordingly + * to pgci_ut->lu[i].exists really do? */ + } + + return 1; +} + + +void ifoFree_PGCI_UT(ifo_handle_t *ifofile) { + if(!ifofile) + return; + + if(ifofile->pgci_ut) { + unsigned int i; + + for(i = 0; i < ifofile->pgci_ut->nr_of_lus; i++) { + ifoFree_PGCIT_internal(&ifofile->pgci_ut->lu[i].pgcit); + } + free(ifofile->pgci_ut->lu); + free(ifofile->pgci_ut); + ifofile->pgci_ut = NULL; + } +} + +static int ifoRead_VTS_ATTRIBUTES(ifo_handle_t *ifofile, + vts_attributes_t *vts_attributes, + unsigned int offset) { + struct ifo_handle_private_s *ifop = PRIV(ifofile); + unsigned int i; + + if(!DVDFileSeek_(ifop->file, offset)) + return 0; + + if(!(DVDReadBytes(ifop->file, vts_attributes, sizeof(vts_attributes_t)))) + return 0; + + read_video_attr(&vts_attributes->vtsm_vobs_attr); + read_video_attr(&vts_attributes->vtstt_vobs_video_attr); + read_audio_attr(&vts_attributes->vtsm_audio_attr); + for(i=0; i<8; i++) + read_audio_attr(&vts_attributes->vtstt_audio_attr[i]); + read_subp_attr(&vts_attributes->vtsm_subp_attr); + for(i=0; i<32; i++) + read_subp_attr(&vts_attributes->vtstt_subp_attr[i]); + B2N_32(vts_attributes->last_byte); + B2N_32(vts_attributes->vts_cat); + + CHECK_ZERO(vts_attributes->zero_1); + CHECK_ZERO(vts_attributes->zero_2); + CHECK_ZERO(vts_attributes->zero_3); + CHECK_ZERO(vts_attributes->zero_4); + CHECK_ZERO(vts_attributes->zero_5); + CHECK_ZERO(vts_attributes->zero_6); + CHECK_ZERO(vts_attributes->zero_7); + CHECK_VALUE(vts_attributes->nr_of_vtsm_audio_streams <= 1); + CHECK_VALUE(vts_attributes->nr_of_vtsm_subp_streams <= 1); + CHECK_VALUE(vts_attributes->nr_of_vtstt_audio_streams <= 8); + for(i = vts_attributes->nr_of_vtstt_audio_streams; i < 8; i++) + CHECK_ZERO(vts_attributes->vtstt_audio_attr[i]); + CHECK_VALUE(vts_attributes->nr_of_vtstt_subp_streams <= 32); + { + unsigned int nr_coded; + CHECK_VALUE(vts_attributes->last_byte + 1 >= VTS_ATTRIBUTES_MIN_SIZE); + nr_coded = (vts_attributes->last_byte + 1 - VTS_ATTRIBUTES_MIN_SIZE)/6; + /* This is often nr_coded = 70, how do you know how many there really are? */ + if(nr_coded > 32) { /* We haven't read more from disk/file anyway */ + nr_coded = 32; + } + CHECK_VALUE(vts_attributes->nr_of_vtstt_subp_streams <= nr_coded); + for(i = vts_attributes->nr_of_vtstt_subp_streams; i < nr_coded; i++) + CHECK_ZERO(vts_attributes->vtstt_subp_attr[i]); + } + + return 1; +} + + + +int ifoRead_VTS_ATRT(ifo_handle_t *ifofile) { + struct ifo_handle_private_s *ifop = PRIV(ifofile); + vts_atrt_t *vts_atrt; + unsigned int i, info_length, sector; + uint32_t *data; + + if(!ifofile) + return 0; + + if(!ifofile->vmgi_mat) + return 0; + + if(ifofile->vmgi_mat->vts_atrt == 0) /* mandatory */ + return 0; + + sector = ifofile->vmgi_mat->vts_atrt; + if(!DVDFileSeek_(ifop->file, sector * DVD_BLOCK_LEN)) + return 0; + + vts_atrt = calloc(1, sizeof(vts_atrt_t)); + if(!vts_atrt) + return 0; + + ifofile->vts_atrt = vts_atrt; + + if(!(DVDReadBytes(ifop->file, vts_atrt, VTS_ATRT_SIZE))) { + free(vts_atrt); + ifofile->vts_atrt = NULL; + return 0; + } + + B2N_16(vts_atrt->nr_of_vtss); + B2N_32(vts_atrt->last_byte); + + CHECK_ZERO(vts_atrt->zero_1); + CHECK_VALUE(vts_atrt->nr_of_vtss != 0); + CHECK_VALUE(vts_atrt->nr_of_vtss < 100); /* ?? */ + CHECK_VALUE((uint32_t)vts_atrt->nr_of_vtss * (4 + VTS_ATTRIBUTES_MIN_SIZE) + + VTS_ATRT_SIZE < vts_atrt->last_byte + 1); + + info_length = vts_atrt->nr_of_vtss * sizeof(uint32_t); + data = calloc(1, info_length); + if(!data) { + free(vts_atrt); + ifofile->vts_atrt = NULL; + return 0; + } + + vts_atrt->vts_atrt_offsets = data; + + if(!(DVDReadBytes(ifop->file, data, info_length))) { + free(data); + free(vts_atrt); + ifofile->vts_atrt = NULL; + return 0; + } + + for(i = 0; i < vts_atrt->nr_of_vtss; i++) { + B2N_32(data[i]); + CHECK_VALUE(data[i] + VTS_ATTRIBUTES_MIN_SIZE < vts_atrt->last_byte + 1); + } + + info_length = vts_atrt->nr_of_vtss * sizeof(vts_attributes_t); + vts_atrt->vts = calloc(1, info_length); + if(!vts_atrt->vts) { + free(data); + free(vts_atrt); + ifofile->vts_atrt = NULL; + return 0; + } + for(i = 0; i < vts_atrt->nr_of_vtss; i++) { + unsigned int offset = data[i]; + if(!ifoRead_VTS_ATTRIBUTES(ifofile, &(vts_atrt->vts[i]), + (sector * DVD_BLOCK_LEN) + offset)) { + free(data); + free(vts_atrt); + ifofile->vts_atrt = NULL; + return 0; + } + + /* This assert can't be in ifoRead_VTS_ATTRIBUTES */ + CHECK_VALUE(offset + vts_atrt->vts[i].last_byte <= vts_atrt->last_byte + 1); + /* Is this check correct? */ + } + + return 1; +} + + +void ifoFree_VTS_ATRT(ifo_handle_t *ifofile) { + if(!ifofile) + return; + + if(ifofile->vts_atrt) { + free(ifofile->vts_atrt->vts); + free(ifofile->vts_atrt->vts_atrt_offsets); + free(ifofile->vts_atrt); + ifofile->vts_atrt = NULL; + } +} + + +int ifoRead_TXTDT_MGI(ifo_handle_t *ifofile) { + struct ifo_handle_private_s *ifop = PRIV(ifofile); + txtdt_mgi_t *txtdt_mgi; + + if(!ifofile) + return 0; + + if(!ifofile->vmgi_mat) + return 0; + + /* Return successfully if there is nothing to read. */ + if(ifofile->vmgi_mat->txtdt_mgi == 0) + return 1; + + if(!DVDFileSeek_(ifop->file, + ifofile->vmgi_mat->txtdt_mgi * DVD_BLOCK_LEN)) + return 0; + + txtdt_mgi = calloc(1, sizeof(txtdt_mgi_t)); + if(!txtdt_mgi) { + return 0; + } + ifofile->txtdt_mgi = txtdt_mgi; + + if(!(DVDReadBytes(ifop->file, txtdt_mgi, TXTDT_MGI_SIZE))) { + Log0(ifop->ctx, "Unable to read TXTDT_MGI."); + free(txtdt_mgi); + ifofile->txtdt_mgi = NULL; + return 0; + } + + /* Log1(ifop->ctx, "-- Not done yet --\n"); */ + return 1; +} + +void ifoFree_TXTDT_MGI(ifo_handle_t *ifofile) { + if(!ifofile) + return; + + if(ifofile->txtdt_mgi) { + free(ifofile->txtdt_mgi); + ifofile->txtdt_mgi = NULL; + } +} diff --git a/libdvdread-embedded/src/logger.c b/libdvdread-embedded/src/logger.c new file mode 100644 index 0000000..c8a45f2 --- /dev/null +++ b/libdvdread-embedded/src/logger.c @@ -0,0 +1,41 @@ +/* + * This file is part of libdvdread. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + */ + +#include "config.h" +#include +#include + +#include "dvdread/dvd_reader.h" +#include "logger.h" + +void DVDReadLog( void *priv, const dvd_logger_cb *logcb, + dvd_logger_level_t level, const char *fmt, ... ) +{ + va_list list; + va_start(list, fmt); + if(logcb && logcb->pf_log) + logcb->pf_log(priv, level, fmt, list); + else + { + FILE *stream = (level == DVD_LOGGER_LEVEL_ERROR) ? stderr : stdout; + fprintf(stream, "libdvdread: "); + vfprintf(stream, fmt, list); + fprintf(stream, "\n"); + } + va_end(list); +} diff --git a/libdvdread-embedded/src/logger.h b/libdvdread-embedded/src/logger.h new file mode 100644 index 0000000..ea3245c --- /dev/null +++ b/libdvdread-embedded/src/logger.h @@ -0,0 +1,32 @@ +/* + * This file is part of libdvdread. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + */ + +#ifndef LIBDVDREAD_LOGGER_H +#define LIBDVDREAD_LOGGER_H + +void DVDReadLog( void *priv, const dvd_logger_cb *logcb, + dvd_logger_level_t level, const char *fmt, ... ); + +#define LOG(ctx, level, ...) \ + DVDReadLog(ctx->priv, &ctx->logcb, level, __VA_ARGS__) +#define Log0(ctx, ...) LOG(ctx, DVD_LOGGER_LEVEL_ERROR, __VA_ARGS__) +#define Log1(ctx, ...) LOG(ctx, DVD_LOGGER_LEVEL_WARN, __VA_ARGS__) +#define Log2(ctx, ...) LOG(ctx, DVD_LOGGER_LEVEL_INFO, __VA_ARGS__) +#define Log3(ctx, ...) LOG(ctx, DVD_LOGGER_LEVEL_DEBUG, __VA_ARGS__) + +#endif diff --git a/libdvdread-embedded/src/md5.c b/libdvdread-embedded/src/md5.c new file mode 100644 index 0000000..54f4ed0 --- /dev/null +++ b/libdvdread-embedded/src/md5.c @@ -0,0 +1,346 @@ +/***************************************************************************** + * md5.c: not so strong MD5 hashing + ***************************************************************************** + * Copyright (C) 1995,1996,1998,1999,2001,2002, + * 2003 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + *****************************************************************************/ + +/* md5.c - MD5 Message-Digest Algorithm + * + * According to the definition of MD5 in RFC 1321 from April 1992. + * NOTE: This is *not* the same file as the one from glibc. + * Written by Ulrich Drepper , 1995. + * heavily modified for GnuPG by Werner Koch + */ + +/* Test values: + * "" D4 1D 8C D9 8F 00 B2 04 E9 80 09 98 EC F8 42 7E + * "a" 0C C1 75 B9 C0 F1 B6 A8 31 C3 99 E2 69 77 26 61 + * "abc 90 01 50 98 3C D2 4F B0 D6 96 3F 7D 28 E1 7F 72 + * "message digest" F9 6B 69 7D 7C B7 93 8D 52 5A 2F 31 AA F1 61 D0 + */ + +#include "config.h" +#include +#include +#include + +#include "md5.h" + +typedef uint32_t u32; +typedef uint8_t byte; +#define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) ) + +typedef struct md5_s MD5_CONTEXT; + + +static void +md5_init( void *context ) +{ + MD5_CONTEXT *ctx = context; + + ctx->A = 0x67452301; + ctx->B = 0xefcdab89; + ctx->C = 0x98badcfe; + ctx->D = 0x10325476; + + ctx->nblocks = 0; + ctx->count = 0; +} + + +/* These are the four functions used in the four steps of the MD5 algorithm + and defined in the RFC 1321. The first function is a little bit optimized + (as found in Colin Plumbs public domain implementation). */ +/* #define FF(b, c, d) ((b & c) | (~b & d)) */ +#define FF(b, c, d) (d ^ (b & (c ^ d))) +#define FG(b, c, d) FF (d, b, c) +#define FH(b, c, d) (b ^ c ^ d) +#define FI(b, c, d) (c ^ (b | ~d)) + + +/**************** + * transform n*64 bytes + */ +static void +transform ( MD5_CONTEXT *ctx, const unsigned char *data ) +{ + u32 correct_words[16]; + register u32 A = ctx->A; + register u32 B = ctx->B; + register u32 C = ctx->C; + register u32 D = ctx->D; + u32 *cwp = correct_words; + +#ifdef WORDS_BIGENDIAN + { + int i; + byte *p2, *p1; + for(i=0, p1=data, p2=(byte*)correct_words; i < 16; i++, p2 += 4 ) + { + p2[3] = *p1++; + p2[2] = *p1++; + p2[1] = *p1++; + p2[0] = *p1++; + } + } +#else + memcpy( correct_words, data, 64 ); +#endif + + +#define OP(a, b, c, d, s, T) \ + do \ + { \ + a += FF (b, c, d) + (*cwp++) + T; \ + a = rol(a, s); \ + a += b; \ + } \ + while (0) + + /* Before we start, one word about the strange constants. + They are defined in RFC 1321 as + + T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64 + */ + + /* Round 1. */ + OP (A, B, C, D, 7, 0xd76aa478); + OP (D, A, B, C, 12, 0xe8c7b756); + OP (C, D, A, B, 17, 0x242070db); + OP (B, C, D, A, 22, 0xc1bdceee); + OP (A, B, C, D, 7, 0xf57c0faf); + OP (D, A, B, C, 12, 0x4787c62a); + OP (C, D, A, B, 17, 0xa8304613); + OP (B, C, D, A, 22, 0xfd469501); + OP (A, B, C, D, 7, 0x698098d8); + OP (D, A, B, C, 12, 0x8b44f7af); + OP (C, D, A, B, 17, 0xffff5bb1); + OP (B, C, D, A, 22, 0x895cd7be); + OP (A, B, C, D, 7, 0x6b901122); + OP (D, A, B, C, 12, 0xfd987193); + OP (C, D, A, B, 17, 0xa679438e); + OP (B, C, D, A, 22, 0x49b40821); + +#undef OP +#define OP(f, a, b, c, d, k, s, T) \ + do \ + { \ + a += f (b, c, d) + correct_words[k] + T; \ + a = rol(a, s); \ + a += b; \ + } \ + while (0) + + /* Round 2. */ + OP (FG, A, B, C, D, 1, 5, 0xf61e2562); + OP (FG, D, A, B, C, 6, 9, 0xc040b340); + OP (FG, C, D, A, B, 11, 14, 0x265e5a51); + OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa); + OP (FG, A, B, C, D, 5, 5, 0xd62f105d); + OP (FG, D, A, B, C, 10, 9, 0x02441453); + OP (FG, C, D, A, B, 15, 14, 0xd8a1e681); + OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8); + OP (FG, A, B, C, D, 9, 5, 0x21e1cde6); + OP (FG, D, A, B, C, 14, 9, 0xc33707d6); + OP (FG, C, D, A, B, 3, 14, 0xf4d50d87); + OP (FG, B, C, D, A, 8, 20, 0x455a14ed); + OP (FG, A, B, C, D, 13, 5, 0xa9e3e905); + OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8); + OP (FG, C, D, A, B, 7, 14, 0x676f02d9); + OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a); + + /* Round 3. */ + OP (FH, A, B, C, D, 5, 4, 0xfffa3942); + OP (FH, D, A, B, C, 8, 11, 0x8771f681); + OP (FH, C, D, A, B, 11, 16, 0x6d9d6122); + OP (FH, B, C, D, A, 14, 23, 0xfde5380c); + OP (FH, A, B, C, D, 1, 4, 0xa4beea44); + OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9); + OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60); + OP (FH, B, C, D, A, 10, 23, 0xbebfbc70); + OP (FH, A, B, C, D, 13, 4, 0x289b7ec6); + OP (FH, D, A, B, C, 0, 11, 0xeaa127fa); + OP (FH, C, D, A, B, 3, 16, 0xd4ef3085); + OP (FH, B, C, D, A, 6, 23, 0x04881d05); + OP (FH, A, B, C, D, 9, 4, 0xd9d4d039); + OP (FH, D, A, B, C, 12, 11, 0xe6db99e5); + OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8); + OP (FH, B, C, D, A, 2, 23, 0xc4ac5665); + + /* Round 4. */ + OP (FI, A, B, C, D, 0, 6, 0xf4292244); + OP (FI, D, A, B, C, 7, 10, 0x432aff97); + OP (FI, C, D, A, B, 14, 15, 0xab9423a7); + OP (FI, B, C, D, A, 5, 21, 0xfc93a039); + OP (FI, A, B, C, D, 12, 6, 0x655b59c3); + OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92); + OP (FI, C, D, A, B, 10, 15, 0xffeff47d); + OP (FI, B, C, D, A, 1, 21, 0x85845dd1); + OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f); + OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0); + OP (FI, C, D, A, B, 6, 15, 0xa3014314); + OP (FI, B, C, D, A, 13, 21, 0x4e0811a1); + OP (FI, A, B, C, D, 4, 6, 0xf7537e82); + OP (FI, D, A, B, C, 11, 10, 0xbd3af235); + OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb); + OP (FI, B, C, D, A, 9, 21, 0xeb86d391); + + /* Put checksum in context given as argument. */ + ctx->A += A; + ctx->B += B; + ctx->C += C; + ctx->D += D; +} + + + +/* The routine updates the message-digest context to + * account for the presence of each of the characters inBuf[0..inLen-1] + * in the message whose digest is being computed. + */ +static void +md5_write( void *context, const void *inbuf_arg , size_t inlen) +{ + const unsigned char *inbuf = inbuf_arg; + MD5_CONTEXT *hd = context; + + if( hd->count == 64 ) /* flush the buffer */ + { + transform( hd, hd->buf ); + hd->count = 0; + hd->nblocks++; + } + if( !inbuf ) + return; + + if( hd->count ) + { + for( ; inlen && hd->count < 64; inlen-- ) + hd->buf[hd->count++] = *inbuf++; + md5_write( hd, NULL, 0 ); + if( !inlen ) + return; + } + + while( inlen >= 64 ) + { + transform( hd, inbuf ); + hd->count = 0; + hd->nblocks++; + inlen -= 64; + inbuf += 64; + } + for( ; inlen && hd->count < 64; inlen-- ) + hd->buf[hd->count++] = *inbuf++; + +} + + + +/* The routine final terminates the message-digest computation and + * ends with the desired message digest in mdContext->digest[0...15]. + * The handle is prepared for a new MD5 cycle. + * Returns 16 bytes representing the digest. + */ + +static void +md5_final( void *context) +{ + MD5_CONTEXT *hd = context; + u32 t, msb, lsb; + byte *p; + + md5_write(hd, NULL, 0); /* flush */; + + t = hd->nblocks; + /* multiply by 64 to make a byte count */ + lsb = t << 6; + msb = t >> 26; + /* add the count */ + t = lsb; + if( (lsb += hd->count) < t ) + msb++; + /* multiply by 8 to make a bit count */ + t = lsb; + lsb <<= 3; + msb <<= 3; + msb |= t >> 29; + + if( hd->count < 56 ) /* enough room */ + { + hd->buf[hd->count++] = 0x80; /* pad */ + while( hd->count < 56 ) + hd->buf[hd->count++] = 0; /* pad */ + } + else /* need one extra block */ + { + hd->buf[hd->count++] = 0x80; /* pad character */ + while( hd->count < 64 ) + hd->buf[hd->count++] = 0; + md5_write(hd, NULL, 0); /* flush */; + memset(hd->buf, 0, 56 ); /* fill next block with zeroes */ + } + /* append the 64 bit count */ + hd->buf[56] = lsb ; + hd->buf[57] = lsb >> 8; + hd->buf[58] = lsb >> 16; + hd->buf[59] = lsb >> 24; + hd->buf[60] = msb ; + hd->buf[61] = msb >> 8; + hd->buf[62] = msb >> 16; + hd->buf[63] = msb >> 24; + transform( hd, hd->buf ); + + p = hd->buf; +#ifdef WORDS_BIGENDIAN +#define X(a) do { *p++ = hd->a ; *p++ = hd->a >> 8; \ + *p++ = hd->a >> 16; *p++ = hd->a >> 24; } while(0) +#else /* little endian */ +#define X(a) do { *(u32*)p = (*hd).a ; p += 4; } while(0) +#endif + X(A); + X(B); + X(C); + X(D); +#undef X + +} + +#if 0 +static byte * +md5_read( void *context ) +{ + MD5_CONTEXT *hd = (MD5_CONTEXT *) context; + return hd->buf; +} +#endif + +void InitMD5( struct md5_s *h ) +{ + md5_init( h ); +} + +void AddMD5( struct md5_s *h, const void *data, size_t len ) +{ + md5_write( h, data, len ); +} + +void EndMD5( struct md5_s *h ) +{ + md5_final( h ); +} diff --git a/libdvdread-embedded/src/md5.h b/libdvdread-embedded/src/md5.h new file mode 100644 index 0000000..50ce88c --- /dev/null +++ b/libdvdread-embedded/src/md5.h @@ -0,0 +1,46 @@ +/***************************************************************************** + * md5.h: MD5 hash + ***************************************************************************** + * Copyright © 2004-2011 VLC authors and VideoLAN + * + * Authors: Rémi Denis-Courmont + * Rafaël Carré + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + *****************************************************************************/ + +#ifndef LIBDVDREAD_MD5_H +#define LIBDVDREAD_MD5_H + +#include + +/** + * \file + * This file defines functions and structures to compute MD5 digests + */ + +struct md5_s +{ + uint32_t A, B, C, D; /* chaining variables */ + uint32_t nblocks; + uint8_t buf[64]; + int count; +}; + +void InitMD5( struct md5_s * ); +void AddMD5( struct md5_s *, const void *, size_t ); +void EndMD5( struct md5_s * ); + +#endif diff --git a/libdvdread-embedded/src/nav_print.c b/libdvdread-embedded/src/nav_print.c new file mode 100644 index 0000000..d8f7b27 --- /dev/null +++ b/libdvdread-embedded/src/nav_print.c @@ -0,0 +1,248 @@ +/* + * Copyright (C) 2000, 2001, 2002, 2003 Håkan Hjort + * + * Much of the contents in this file is based on VOBDUMP. + * + * VOBDUMP: a program for examining DVD .VOB files + * + * Copyright 1998, 1999 Eric Smith + * + * VOBDUMP is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 or version 3 as + * published by the Free Software Foundation. Note that I am not + * granting permission to redistribute or modify VOBDUMP under the + * terms of any later version of the General Public License. + * + * This program is distributed in the hope that it will be useful (or + * at least amusing), 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. + */ + +#include "config.h" +#include +#include + +#include "dvdread/nav_types.h" +#include "dvdread/nav_print.h" +#include "dvdread/ifo_print.h" + +static void navPrint_PCI_GI(pci_gi_t *pci_gi) { + int i; + + printf("pci_gi:\n"); + printf("nv_pck_lbn 0x%08x\n", pci_gi->nv_pck_lbn); + printf("vobu_cat 0x%04x\n", pci_gi->vobu_cat); + printf("vobu_s_ptm 0x%08x\n", pci_gi->vobu_s_ptm); + printf("vobu_e_ptm 0x%08x\n", pci_gi->vobu_e_ptm); + printf("vobu_se_e_ptm 0x%08x\n", pci_gi->vobu_se_e_ptm); + printf("e_eltm "); + dvdread_print_time(&pci_gi->e_eltm); + printf("\n"); + + printf("vobu_isrc \""); + for(i = 0; i < 32; i++) { + char c = pci_gi->vobu_isrc[i]; + if((c >= ' ') && (c <= '~')) + printf("%c", c); + else + printf("."); + } + printf("\"\n"); +} + +static void navPrint_NSML_AGLI(nsml_agli_t *nsml_agli) { + int i, j = 0; + + for(i = 0; i < 9; i++) + j |= nsml_agli->nsml_agl_dsta[i]; + if(j == 0) + return; + + printf("nsml_agli:\n"); + for(i = 0; i < 9; i++) + if(nsml_agli->nsml_agl_dsta[i]) + printf("nsml_agl_c%d_dsta 0x%08x\n", i + 1, + nsml_agli->nsml_agl_dsta[i]); +} + +static void navPrint_HL_GI(hl_gi_t *hl_gi, int *btngr_ns, int *btn_ns) { + + if((hl_gi->hli_ss & 0x03) == 0) + return; + + printf("hl_gi:\n"); + printf("hli_ss 0x%01x\n", hl_gi->hli_ss & 0x03); + printf("hli_s_ptm 0x%08x\n", hl_gi->hli_s_ptm); + printf("hli_e_ptm 0x%08x\n", hl_gi->hli_e_ptm); + printf("btn_se_e_ptm 0x%08x\n", hl_gi->btn_se_e_ptm); + + *btngr_ns = hl_gi->btngr_ns; + printf("btngr_ns %u\n", hl_gi->btngr_ns); + printf("btngr%d_dsp_ty 0x%02x\n", 1, hl_gi->btngr1_dsp_ty); + printf("btngr%d_dsp_ty 0x%02x\n", 2, hl_gi->btngr2_dsp_ty); + printf("btngr%d_dsp_ty 0x%02x\n", 3, hl_gi->btngr3_dsp_ty); + + printf("btn_ofn %d\n", hl_gi->btn_ofn); + *btn_ns = hl_gi->btn_ns; + printf("btn_ns %d\n", hl_gi->btn_ns); + printf("nsl_btn_ns %d\n", hl_gi->nsl_btn_ns); + printf("fosl_btnn %d\n", hl_gi->fosl_btnn); + printf("foac_btnn %d\n", hl_gi->foac_btnn); +} + +static void navPrint_BTN_COLIT(btn_colit_t *btn_colit) { + int i, j; + + j = 0; + for(i = 0; i < 6; i++) + j |= btn_colit->btn_coli[i/2][i&1]; + if(j == 0) + return; + + printf("btn_colit:\n"); + for(i = 0; i < 3; i++) + for(j = 0; j < 2; j++) + printf("btn_cqoli %d %s_coli: %08x\n", + i, (j == 0) ? "sl" : "ac", + btn_colit->btn_coli[i][j]); +} + +static void navPrint_BTNIT(btni_t *btni_table, int btngr_ns, int btn_ns) { + int i, j; + + printf("btnit:\n"); + printf("btngr_ns: %i\n", btngr_ns); + printf("btn_ns: %i\n", btn_ns); + + if(btngr_ns == 0) + return; + + for(i = 0; i < btngr_ns; i++) { + for(j = 0; j < (36 / btngr_ns); j++) { + if(j < btn_ns) { + btni_t *btni = &btni_table[(36 / btngr_ns) * i + j]; + + printf("group %d btni %d: ", i+1, j+1); + printf("btn_coln %u, auto_action_mode %u\n", + btni->btn_coln, btni->auto_action_mode); + printf("coords (%u, %u) .. (%u, %u)\n", + btni->x_start, btni->y_start, btni->x_end, btni->y_end); + + printf("up %u, ", btni->up); + printf("down %u, ", btni->down); + printf("left %u, ", btni->left); + printf("right %u\n", btni->right); + + /* ifoPrint_COMMAND(&btni->cmd); */ + printf("\n"); + } + } + } +} + +static void navPrint_HLI(hli_t *hli) { + int btngr_ns = 0, btn_ns = 0; + + printf("hli:\n"); + navPrint_HL_GI(&hli->hl_gi, & btngr_ns, & btn_ns); + navPrint_BTN_COLIT(&hli->btn_colit); + navPrint_BTNIT(hli->btnit, btngr_ns, btn_ns); +} + +void navPrint_PCI(pci_t *pci) { + printf("pci packet:\n"); + navPrint_PCI_GI(&pci->pci_gi); + navPrint_NSML_AGLI(&pci->nsml_agli); + navPrint_HLI(&pci->hli); +} + +static void navPrint_DSI_GI(dsi_gi_t *dsi_gi) { + printf("dsi_gi:\n"); + printf("nv_pck_scr 0x%08x\n", dsi_gi->nv_pck_scr); + printf("nv_pck_lbn 0x%08x\n", dsi_gi->nv_pck_lbn ); + printf("vobu_ea 0x%08x\n", dsi_gi->vobu_ea); + printf("vobu_1stref_ea 0x%08x\n", dsi_gi->vobu_1stref_ea); + printf("vobu_2ndref_ea 0x%08x\n", dsi_gi->vobu_2ndref_ea); + printf("vobu_3rdref_ea 0x%08x\n", dsi_gi->vobu_3rdref_ea); + printf("vobu_vob_idn 0x%04x\n", dsi_gi->vobu_vob_idn); + printf("vobu_c_idn 0x%02x\n", dsi_gi->vobu_c_idn); + printf("c_eltm "); + dvdread_print_time(&dsi_gi->c_eltm); + printf("\n"); +} + +static void navPrint_SML_PBI(sml_pbi_t *sml_pbi) { + printf("sml_pbi:\n"); + printf("category 0x%04x\n", sml_pbi->category); + if(sml_pbi->category & 0x8000) + printf("VOBU is in preunit\n"); + if(sml_pbi->category & 0x4000) + printf("VOBU is in ILVU\n"); + if(sml_pbi->category & 0x2000) + printf("VOBU at the beginning of ILVU\n"); + if(sml_pbi->category & 0x1000) + printf("VOBU at end of PREU of ILVU\n"); + + printf("ilvu_ea 0x%08x\n", sml_pbi->ilvu_ea); + printf("nxt_ilvu_sa 0x%08x\n", sml_pbi->ilvu_sa); + printf("nxt_ilvu_size 0x%04x\n", sml_pbi->size); + + printf("vob_v_s_s_ptm 0x%08x\n", sml_pbi->vob_v_s_s_ptm); + printf("vob_v_e_e_ptm 0x%08x\n", sml_pbi->vob_v_e_e_ptm); + + /* $$$ more code needed here */ +} + +static void navPrint_SML_AGLI(sml_agli_t *sml_agli) { + int i; + printf("sml_agli:\n"); + for(i = 0; i < 9; i++) { + printf("agl_c%d address: 0x%08x size 0x%04x\n", i, + sml_agli->data[i].address, sml_agli->data[i].size); + } +} + +static void navPrint_VOBU_SRI(vobu_sri_t *vobu_sri) { + int i; + int stime[19] = { 240, 120, 60, 20, 15, 14, 13, 12, 11, + 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; + printf("vobu_sri:\n"); + printf("Next VOBU with Video %08x\n", vobu_sri->next_video); + for(i = 0; i < 19; i++) { + printf("%3.1f %08x ", stime[i]/2.0, vobu_sri->fwda[i]); + } + printf("\n"); + printf("Next VOBU %08x\n", vobu_sri->next_vobu); + printf("--\n"); + printf("Prev VOBU %08x\n", vobu_sri->prev_vobu); + for(i = 0; i < 19; i++) { + printf("%3.1f %08x ", stime[18 - i]/2.0, vobu_sri->bwda[i]); + } + printf("\n"); + printf("Prev VOBU with Video %08x\n", vobu_sri->prev_video); +} + +static void navPrint_SYNCI(synci_t *synci) { + int i; + + printf("synci:\n"); + /* $$$ more code needed here */ + for(i = 0; i < 8; i++) + printf("%04x ", synci->a_synca[i]); + for(i = 0; i < 32; i++) + printf("%08x ", synci->sp_synca[i]); +} + +void navPrint_DSI(dsi_t *dsi) { + printf("dsi packet:\n"); + navPrint_DSI_GI(&dsi->dsi_gi); + navPrint_SML_PBI(&dsi->sml_pbi); + navPrint_SML_AGLI(&dsi->sml_agli); + navPrint_VOBU_SRI(&dsi->vobu_sri); + navPrint_SYNCI(&dsi->synci); +} diff --git a/libdvdread-embedded/src/nav_read.c b/libdvdread-embedded/src/nav_read.c new file mode 100644 index 0000000..bb781cf --- /dev/null +++ b/libdvdread-embedded/src/nav_read.c @@ -0,0 +1,272 @@ +/* + * Copyright (C) 2000, 2001, 2002, 2003 Håkan Hjort + * + * This file is part of libdvdread. + * + * libdvdread 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 of the License, or + * (at your option) any later version. + * + * libdvdread 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 libdvdread; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" + +#include +#include +#include +#include + +#include "bswap.h" +#include "dvdread/nav_types.h" +#include "dvdread/nav_read.h" +#include "dvdread_internal.h" +#include "dvdread/bitreader.h" + +#define getbits_init dvdread_getbits_init +#define getbits dvdread_getbits + +#define CHECK_VALUE(arg)\ + if(!(arg)) {\ + DVDReadLog(NULL, NULL, DVD_LOGGER_LEVEL_WARN,\ + "CHECK_VALUE failed in %s:%i for %s",\ + __FILE__, __LINE__, # arg );\ + } + +void navRead_PCI(pci_t *pci, unsigned char *buffer) { + int32_t i, j; + getbits_state_t state; + if (!getbits_init(&state, buffer)) abort(); /* Passed NULL pointers */ + + /* pci pci_gi */ + pci->pci_gi.nv_pck_lbn = getbits(&state, 32 ); + pci->pci_gi.vobu_cat = getbits(&state, 16 ); + pci->pci_gi.zero1 = getbits(&state, 16 ); + pci->pci_gi.vobu_uop_ctl.zero = getbits(&state, 7 ); + pci->pci_gi.vobu_uop_ctl.video_pres_mode_change = getbits(&state, 1 ); + + pci->pci_gi.vobu_uop_ctl.karaoke_audio_pres_mode_change = getbits(&state, 1 ); + pci->pci_gi.vobu_uop_ctl.angle_change = getbits(&state, 1 ); + pci->pci_gi.vobu_uop_ctl.subpic_stream_change = getbits(&state, 1 ); + pci->pci_gi.vobu_uop_ctl.audio_stream_change = getbits(&state, 1 ); + pci->pci_gi.vobu_uop_ctl.pause_on = getbits(&state, 1 ); + pci->pci_gi.vobu_uop_ctl.still_off = getbits(&state, 1 ); + pci->pci_gi.vobu_uop_ctl.button_select_or_activate = getbits(&state, 1 ); + pci->pci_gi.vobu_uop_ctl.resume = getbits(&state, 1 ); + + pci->pci_gi.vobu_uop_ctl.chapter_menu_call = getbits(&state, 1 ); + pci->pci_gi.vobu_uop_ctl.angle_menu_call = getbits(&state, 1 ); + pci->pci_gi.vobu_uop_ctl.audio_menu_call = getbits(&state, 1 ); + pci->pci_gi.vobu_uop_ctl.subpic_menu_call = getbits(&state, 1 ); + pci->pci_gi.vobu_uop_ctl.root_menu_call = getbits(&state, 1 ); + pci->pci_gi.vobu_uop_ctl.title_menu_call = getbits(&state, 1 ); + pci->pci_gi.vobu_uop_ctl.backward_scan = getbits(&state, 1 ); + pci->pci_gi.vobu_uop_ctl.forward_scan = getbits(&state, 1 ); + + pci->pci_gi.vobu_uop_ctl.next_pg_search = getbits(&state, 1 ); + pci->pci_gi.vobu_uop_ctl.prev_or_top_pg_search = getbits(&state, 1 ); + pci->pci_gi.vobu_uop_ctl.time_or_chapter_search = getbits(&state, 1 ); + pci->pci_gi.vobu_uop_ctl.go_up = getbits(&state, 1 ); + pci->pci_gi.vobu_uop_ctl.stop = getbits(&state, 1 ); + pci->pci_gi.vobu_uop_ctl.title_play = getbits(&state, 1 ); + pci->pci_gi.vobu_uop_ctl.chapter_search_or_play = getbits(&state, 1 ); + pci->pci_gi.vobu_uop_ctl.title_or_time_play = getbits(&state, 1 ); + pci->pci_gi.vobu_s_ptm = getbits(&state, 32 ); + pci->pci_gi.vobu_e_ptm = getbits(&state, 32 ); + pci->pci_gi.vobu_se_e_ptm = getbits(&state, 32 ); + pci->pci_gi.e_eltm.hour = getbits(&state, 8 ); + pci->pci_gi.e_eltm.minute = getbits(&state, 8 ); + pci->pci_gi.e_eltm.second = getbits(&state, 8 ); + pci->pci_gi.e_eltm.frame_u = getbits(&state, 8 ); + for(i = 0; i < 32; i++) + pci->pci_gi.vobu_isrc[i] = getbits(&state, 8 ); + + /* pci nsml_agli */ + for(i = 0; i < 9; i++) + pci->nsml_agli.nsml_agl_dsta[i] = getbits(&state, 32 ); + + /* pci hli hli_gi */ + pci->hli.hl_gi.hli_ss = getbits(&state, 16 ); + pci->hli.hl_gi.hli_s_ptm = getbits(&state, 32 ); + pci->hli.hl_gi.hli_e_ptm = getbits(&state, 32 ); + pci->hli.hl_gi.btn_se_e_ptm = getbits(&state, 32 ); + pci->hli.hl_gi.zero1 = getbits(&state, 2 ); + pci->hli.hl_gi.btngr_ns = getbits(&state, 2 ); + pci->hli.hl_gi.zero2 = getbits(&state, 1 ); + pci->hli.hl_gi.btngr1_dsp_ty = getbits(&state, 3 ); + pci->hli.hl_gi.zero3 = getbits(&state, 1 ); + pci->hli.hl_gi.btngr2_dsp_ty = getbits(&state, 3 ); + pci->hli.hl_gi.zero4 = getbits(&state, 1 ); + pci->hli.hl_gi.btngr3_dsp_ty = getbits(&state, 3 ); + pci->hli.hl_gi.btn_ofn = getbits(&state, 8 ); + pci->hli.hl_gi.btn_ns = getbits(&state, 8 ); + pci->hli.hl_gi.nsl_btn_ns = getbits(&state, 8 ); + pci->hli.hl_gi.zero5 = getbits(&state, 8 ); + pci->hli.hl_gi.fosl_btnn = getbits(&state, 8 ); + pci->hli.hl_gi.foac_btnn = getbits(&state, 8 ); + + /* pci hli btn_colit */ + for(i = 0; i < 3; i++) + for(j = 0; j < 2; j++) + pci->hli.btn_colit.btn_coli[i][j] = getbits(&state, 32 ); + + /* NOTE: I've had to change the structure from the disk layout to get + * the packing to work with Sun's Forte C compiler. */ + + /* pci hli btni */ + for(i = 0; i < 36; i++) { + pci->hli.btnit[i].btn_coln = getbits(&state, 2 ); + pci->hli.btnit[i].x_start = getbits(&state, 10 ); + pci->hli.btnit[i].zero1 = getbits(&state, 2 ); + pci->hli.btnit[i].x_end = getbits(&state, 10 ); + + pci->hli.btnit[i].auto_action_mode = getbits(&state, 2 ); + pci->hli.btnit[i].y_start = getbits(&state, 10 ); + pci->hli.btnit[i].zero2 = getbits(&state, 2 ); + pci->hli.btnit[i].y_end = getbits(&state, 10 ); + + pci->hli.btnit[i].zero3 = getbits(&state, 2 ); + pci->hli.btnit[i].up = getbits(&state, 6 ); + pci->hli.btnit[i].zero4 = getbits(&state, 2 ); + pci->hli.btnit[i].down = getbits(&state, 6 ); + pci->hli.btnit[i].zero5 = getbits(&state, 2 ); + pci->hli.btnit[i].left = getbits(&state, 6 ); + pci->hli.btnit[i].zero6 = getbits(&state, 2 ); + pci->hli.btnit[i].right = getbits(&state, 6 ); + /* pci vm_cmd */ + for(j = 0; j < 8; j++) + pci->hli.btnit[i].cmd.bytes[j] = getbits(&state, 8 ); + } + + +#ifndef NDEBUG + /* Asserts */ + + /* pci pci gi */ + CHECK_VALUE(pci->pci_gi.zero1 == 0); + + /* pci hli hli_gi */ + CHECK_VALUE(pci->hli.hl_gi.zero1 == 0); + CHECK_VALUE(pci->hli.hl_gi.zero2 == 0); + CHECK_VALUE(pci->hli.hl_gi.zero3 == 0); + CHECK_VALUE(pci->hli.hl_gi.zero4 == 0); + CHECK_VALUE(pci->hli.hl_gi.zero5 == 0); + + /* Are there buttons defined here? */ + if((pci->hli.hl_gi.hli_ss & 0x03) != 0) { + CHECK_VALUE(pci->hli.hl_gi.btn_ns != 0); + CHECK_VALUE(pci->hli.hl_gi.btngr_ns != 0); + } else { + CHECK_VALUE((pci->hli.hl_gi.btn_ns != 0 && pci->hli.hl_gi.btngr_ns != 0) + || (pci->hli.hl_gi.btn_ns == 0 && pci->hli.hl_gi.btngr_ns == 0)); + } + + /* pci hli btnit */ + for(i = 0; i < pci->hli.hl_gi.btngr_ns; i++) { + for(j = 0; j < (36 / pci->hli.hl_gi.btngr_ns); j++) { + int n = (36 / pci->hli.hl_gi.btngr_ns) * i + j; + CHECK_VALUE(pci->hli.btnit[n].zero1 == 0); + CHECK_VALUE(pci->hli.btnit[n].zero2 == 0); + CHECK_VALUE(pci->hli.btnit[n].zero3 == 0); + CHECK_VALUE(pci->hli.btnit[n].zero4 == 0); + CHECK_VALUE(pci->hli.btnit[n].zero5 == 0); + CHECK_VALUE(pci->hli.btnit[n].zero6 == 0); + + if (j < pci->hli.hl_gi.btn_ns) { + CHECK_VALUE(pci->hli.btnit[n].x_start <= pci->hli.btnit[n].x_end); + CHECK_VALUE(pci->hli.btnit[n].y_start <= pci->hli.btnit[n].y_end); + CHECK_VALUE(pci->hli.btnit[n].up <= pci->hli.hl_gi.btn_ns); + CHECK_VALUE(pci->hli.btnit[n].down <= pci->hli.hl_gi.btn_ns); + CHECK_VALUE(pci->hli.btnit[n].left <= pci->hli.hl_gi.btn_ns); + CHECK_VALUE(pci->hli.btnit[n].right <= pci->hli.hl_gi.btn_ns); + /* vmcmd_verify(pci->hli.btnit[n].cmd); */ + } else { + int k; + CHECK_VALUE(pci->hli.btnit[n].btn_coln == 0); + CHECK_VALUE(pci->hli.btnit[n].auto_action_mode == 0); + CHECK_VALUE(pci->hli.btnit[n].x_start == 0); + CHECK_VALUE(pci->hli.btnit[n].y_start == 0); + CHECK_VALUE(pci->hli.btnit[n].x_end == 0); + CHECK_VALUE(pci->hli.btnit[n].y_end == 0); + CHECK_VALUE(pci->hli.btnit[n].up == 0); + CHECK_VALUE(pci->hli.btnit[n].down == 0); + CHECK_VALUE(pci->hli.btnit[n].left == 0); + CHECK_VALUE(pci->hli.btnit[n].right == 0); + for (k = 0; k < 8; k++) + CHECK_VALUE(pci->hli.btnit[n].cmd.bytes[k] == 0); /* CHECK_ZERO? */ + } + } + } +#endif /* !NDEBUG */ +} + +void navRead_DSI(dsi_t *dsi, unsigned char *buffer) { + int i; + getbits_state_t state; + if (!getbits_init(&state, buffer)) abort(); /* Passed NULL pointers */ + + /* dsi dsi gi */ + dsi->dsi_gi.nv_pck_scr = getbits(&state, 32 ); + dsi->dsi_gi.nv_pck_lbn = getbits(&state, 32 ); + dsi->dsi_gi.vobu_ea = getbits(&state, 32 ); + dsi->dsi_gi.vobu_1stref_ea = getbits(&state, 32 ); + dsi->dsi_gi.vobu_2ndref_ea = getbits(&state, 32 ); + dsi->dsi_gi.vobu_3rdref_ea = getbits(&state, 32 ); + dsi->dsi_gi.vobu_vob_idn = getbits(&state, 16 ); + dsi->dsi_gi.zero1 = getbits(&state, 8 ); + dsi->dsi_gi.vobu_c_idn = getbits(&state, 8 ); + dsi->dsi_gi.c_eltm.hour = getbits(&state, 8 ); + dsi->dsi_gi.c_eltm.minute = getbits(&state, 8 ); + dsi->dsi_gi.c_eltm.second = getbits(&state, 8 ); + dsi->dsi_gi.c_eltm.frame_u = getbits(&state, 8 ); + + /* dsi sml pbi */ + dsi->sml_pbi.category = getbits(&state, 16 ); + dsi->sml_pbi.ilvu_ea = getbits(&state, 32 ); + dsi->sml_pbi.ilvu_sa = getbits(&state, 32 ); + dsi->sml_pbi.size = getbits(&state, 16 ); + dsi->sml_pbi.vob_v_s_s_ptm = getbits(&state, 32 ); + dsi->sml_pbi.vob_v_e_e_ptm = getbits(&state, 32 ); + for(i = 0; i < 8; i++) { + dsi->sml_pbi.vob_a[i].stp_ptm1 = getbits(&state, 32 ); + dsi->sml_pbi.vob_a[i].stp_ptm2 = getbits(&state, 32 ); + dsi->sml_pbi.vob_a[i].gap_len1 = getbits(&state, 32 ); + dsi->sml_pbi.vob_a[i].gap_len2 = getbits(&state, 32 ); + } + + /* dsi sml agli */ + for(i = 0; i < 9; i++) { + dsi->sml_agli.data[ i ].address = getbits(&state, 32 ); + dsi->sml_agli.data[ i ].size = getbits(&state, 16 ); + } + + /* dsi vobu sri */ + dsi->vobu_sri.next_video = getbits(&state, 32 ); + for(i = 0; i < 19; i++) + dsi->vobu_sri.fwda[i] = getbits(&state, 32 ); + dsi->vobu_sri.next_vobu = getbits(&state, 32 ); + dsi->vobu_sri.prev_vobu = getbits(&state, 32 ); + for(i = 0; i < 19; i++) + dsi->vobu_sri.bwda[i] = getbits(&state, 32 ); + dsi->vobu_sri.prev_video = getbits(&state, 32 ); + + /* dsi synci */ + for(i = 0; i < 8; i++) + dsi->synci.a_synca[i] = getbits(&state, 16 ); + for(i = 0; i < 32; i++) + dsi->synci.sp_synca[i] = getbits(&state, 32 ); + + + /* Asserts */ + + /* dsi dsi gi */ + CHECK_VALUE(dsi->dsi_gi.zero1 == 0); +} -- cgit v1.2.3