diff options
author | theuni <theuni-nospam-@xbmc.org> | 2011-01-24 16:05:21 -0500 |
---|---|---|
committer | theuni <theuni-nospam-@xbmc.org> | 2011-01-24 16:05:21 -0500 |
commit | c51b1189e3d5353e842991f5859ddcea0f73e426 (patch) | |
tree | ef2cb8a6184699aa614f3655dca4ce661cdc108e /lib/libdvd | |
parent | be61ebdc9e897fe40c6f371111724de79ddee8d5 (diff) |
Merged cptspiff's code-reshuffle branch.
Squashed commit due to build breakage during code-reshuffle history.
Conflicts:
xbmc/Util.cpp
xbmc/cdrip/CDDARipper.cpp
xbmc/filesystem/Directory.cpp
xbmc/filesystem/File.cpp
Diffstat (limited to 'lib/libdvd')
202 files changed, 45794 insertions, 0 deletions
diff --git a/lib/libdvd/Makefile.in b/lib/libdvd/Makefile.in new file mode 100644 index 0000000000..e7910dae16 --- /dev/null +++ b/lib/libdvd/Makefile.in @@ -0,0 +1,75 @@ + +ARCH=@ARCH@ +SYSDIR=@abs_top_srcdir@/system/players/dvdplayer +SOS= libdvdnav-$(ARCH).so +DIRS= libdvdread \ + libdvdnav + +WRAPPER=@abs_top_srcdir@/xbmc/cores/DllLoader/exports/wrapper.o +WRAPPER_OSX=@abs_top_srcdir@/tools/Mach5/wrapper.rb + +LDFLAGS += -shared -fPIC -rdynamic +ifeq ($(ARCH), powerpc-osx) + # Add -lbundle1.o for powerpc-osx + BUNDLE1_O = -lbundle1.o +endif + +# Allows us to optionally build xbmc with DVDCSS support +ifeq (@BUILD_DVDCSS@,1) + DIRS += libdvdcss + SOS += libdvdcss-$(ARCH).so + DVDCSS_A = libdvdcss/src/.libs/libdvdcss.a + DVDCSS_O = libdvdcss/src/.libs/*.o + DVDNAV_PREREQ = libdvdcss +endif + +SLIB=$(addprefix $(SYSDIR)/, $(SOS)) + +DISTCLEAN_FILES=includes/dvdread/*.h \ + includes/dvdcss/*.h \ + libdvdnav/config.h \ + libdvdread/config.h + +.PHONY: $(DIRS) compile + +all: $(SLIB) + +ifeq ($(findstring osx,$(ARCH)), osx) + +$(SYSDIR)/libdvdcss-$(ARCH).so: $(WRAPPER_OSX) libdvdcss/src/.libs/libdvdcss.a + ld -bundle -flat_namespace -undefined suppress -o $@ \ + libdvdcss/src/*.o $(BUNDLE1_O) + $(WRAPPER_OSX) $@;mv output.so $@ + +$(SYSDIR)/libdvdnav-$(ARCH).so: $(WRAPPER_OSX) $(DVDCSS_A) libdvdread/obj/libdvdread.a libdvdnav/obj/libdvdnav.a + ld -bundle -flat_namespace -undefined suppress -o $@ \ + $(DVDCSS_O) libdvdread/obj/*.o libdvdnav/obj/*.o $(BUNDLE1_O) + $(WRAPPER_OSX) $@;mv output.so $@ + +else + +$(SYSDIR)/libdvdcss-$(ARCH).so: $(WRAPPER) libdvdcss/src/.libs/libdvdcss.a + $(CC) -o $@ $(LDFLAGS) --soname,$@ \ + libdvdcss/src/*.o \ + `cat $(WRAPPER:.o=.def)` $(WRAPPER) + +$(SYSDIR)/libdvdnav-$(ARCH).so: $(WRAPPER) $(DVDCSS_A) libdvdread/obj/libdvdread.a libdvdnav/obj/libdvdnav.a + $(CC) -o $@ $(LDFLAGS) --soname,$@ $(DVDCSS_O) libdvdread/obj/*.o libdvdnav/obj/*.o \ + `cat $(WRAPPER:.o=.def)` $(WRAPPER) + +endif + +libdvdcss/src/.libs/libdvdcss.a: libdvdcss +libdvdcss: compile + $(MAKE) -C $@ + +libdvdread/obj/libdvdread.a: libdvdread +libdvdread: compile + $(MAKE) -C $@ + +libdvdnav/obj/libdvdnav.a: libdvdnav +libdvdnav: compile + $(MAKE) -C $@ + +include @abs_top_srcdir@/Makefile.include + diff --git a/lib/libdvd/build-xbmc-win32.sh b/lib/libdvd/build-xbmc-win32.sh new file mode 100644 index 0000000000..db39eef2d8 --- /dev/null +++ b/lib/libdvd/build-xbmc-win32.sh @@ -0,0 +1,59 @@ +#!/bin/sh + +#libdvdcss +cd libdvdcss +echo "***** Cleaning libdvdcss *****" +make distclean +echo "***** Building libdvdcss *****" +sh bootstrap +./configure \ + CFLAGS="-DNDEBUG" \ + --disable-doc \ + --enable-static \ + --with-pic +make +strip -S src/.libs/libdvdcss-2.dll +cd .. +mkdir -p includes/dvdcss +cp libdvdcss/src/dvdcss/dvdcss.h includes/dvdcss +cp libdvdcss/src/.libs/libdvdcss-2.dll ../../../../../system/players/dvdplayer/ + +#libdvdread +cd libdvdread +echo "***** Cleaning libdvdread *****" +make distclean +echo "***** Building libdvdread *****" +./configure2 \ + --disable-shared \ + --enable-static \ + --extra-cflags="-DHAVE_DVDCSS_DVDCSS_H -D_XBMC -DNDEBUG -D_MSC_VER -I`pwd`/../includes" \ + --disable-debug +mkdir -p ../includes/dvdread +cp ../libdvdread/src/*.h ../includes/dvdread +make +cd .. + +#libdvdnav +cd libdvdnav +echo "***** Cleaning libdvdnav *****" +make distclean +echo "***** Building libdvdnav *****" +./configure2 \ + --disable-shared \ + --enable-static \ + --extra-cflags="-D_XBMC -DNDEBUG -I`pwd`/../includes" \ + --with-dvdread-config="`pwd`/../libdvdread/obj/dvdread-config" \ + --disable-debug +make +gcc \ + -shared \ + -o obj/libdvdnav.dll \ + ../libdvdread/obj/*.o obj/*.o ../libdvdcss/src/.libs/libdvdcss.dll.a \ + -ldl \ + -Wl,--enable-auto-image-base \ + -Xlinker --enable-auto-import + +strip -S obj/libdvdnav.dll +cd .. +cp libdvdnav/obj/libdvdnav.dll ../../../../../system/players/dvdplayer/ +echo "***** Done *****" diff --git a/lib/libdvd/includes/dvdcss/.ignoreme b/lib/libdvd/includes/dvdcss/.ignoreme new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/lib/libdvd/includes/dvdcss/.ignoreme diff --git a/lib/libdvd/includes/dvdread/.ignoreme b/lib/libdvd/includes/dvdread/.ignoreme new file mode 100644 index 0000000000..62d0910142 --- /dev/null +++ b/lib/libdvd/includes/dvdread/.ignoreme @@ -0,0 +1,2 @@ +Dummy file so that this directory shows up for git users. +Ignore this file. diff --git a/lib/libdvd/libdvdcss/AUTHORS b/lib/libdvd/libdvdcss/AUTHORS new file mode 100644 index 0000000000..810cbdd0e2 --- /dev/null +++ b/lib/libdvd/libdvdcss/AUTHORS @@ -0,0 +1,69 @@ +# The format of this file was inspired by the Linux kernel CREDITS file. +# +# Authors and contributors are listed alphabetically. +# +# The fields are: name (N), email (E), web-address (W), CVS account login (C), +# PGP key ID and fingerprint (P), description (D), and snail-mail address (S). + +N: Billy Biggs +E: vektor@dumbterm.net +D: libdvdcss enhancements + +N: Stéphane Borel +E: stef@via.ecp.fr +C: stef +D: original CSS decryption code from vlc + +N: Sven Heithecker +E: sven.heithecker@web.de +D: cache bug fix for discs with identical content but different keys + +N: Håkan Hjort +E: d95hjort@dtek.chalmers.se +D: Solaris port of the DVD ioctls +D: libdvdcss enhancements + +N: Samuel Hocevar +E: sam@zoy.org +C: sam +D: original CSS decryption code from vlc + +N: Eugenio Jarosiewicz +E: ej0@cise.ufl.edu +C: ej +D: MacOS X DVD ioctls + +N: Jon Lech Johansen +E: jon-vl@nanocrew.net +C: jlj +D: Win32 port +D: Fixes to the Darwin port + +N: Markus Kuespert +E: ltlBeBoy@beosmail.com +D: BeOS port of the DVD ioctls + +N: Pascal Levesque +E: Pascal.Levesque@mindready.com +D: QNX port + +N: Steven M. Schultz +E: sms@TO.GD-ES.COM +D: BSD/OS port + +N: David Siebörger +E: drs-videolan@rucus.ru.ac.za +D: HP-UX port of the DVD ioctls + +N: Alex Strelnikov +E: lelik@os2.ru +D: OS/2 port + +N: German Tischler +E: tanis@gaspode.franken.de +D: FreeBSD DVD input patch + +N: Gildas Bazin +E: gbazin@netcourrier.com +C: gbazin +D: various fixes to the Win32 port diff --git a/lib/libdvd/libdvdcss/COPYING b/lib/libdvd/libdvdcss/COPYING new file mode 100644 index 0000000000..d60c31a97a --- /dev/null +++ b/lib/libdvd/libdvdcss/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. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + 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. + + <signature of Ty Coon>, 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/lib/libdvd/libdvdcss/ChangeLog b/lib/libdvd/libdvdcss/ChangeLog new file mode 100644 index 0000000000..7b3abcacc8 --- /dev/null +++ b/lib/libdvd/libdvdcss/ChangeLog @@ -0,0 +1,2171 @@ +------------------------------------------------------------------------ +r217 | sam | 2008-08-29 18:57:52 +0000 (Fri, 29 Aug 2008) | 2 lines +Changed paths: + M /trunk/src/Makefile.am + + * src/Makefile.am: bump the library minor version since we ship an extra + symbole (dvdcss_is_scrambled). +------------------------------------------------------------------------ +r216 | sam | 2008-08-29 18:57:51 +0000 (Fri, 29 Aug 2008) | 1 line +Changed paths: + M /trunk/configure.ac + M /trunk/src/Makefile.am + A /trunk/src/libdvdcss.pc.in + + * Ship a .pc file with the library. +------------------------------------------------------------------------ +r215 | sam | 2008-08-29 18:57:48 +0000 (Fri, 29 Aug 2008) | 1 line +Changed paths: + M /trunk/libdvdcss.spec + M /trunk/src/common.h + M /trunk/src/css.c + M /trunk/src/device.h + M /trunk/src/dvdcss/dvdcss.h + M /trunk/src/error.c + M /trunk/src/ioctl.c + M /trunk/src/ioctl.h + M /trunk/src/libdvdcss.c + M /trunk/src/libdvdcss.h + M /trunk/test/csstest.c + + * Update copyeight information here and there. +------------------------------------------------------------------------ +r214 | sam | 2008-08-29 18:57:45 +0000 (Fri, 29 Aug 2008) | 3 lines +Changed paths: + A /trunk/.gitignore + M /trunk/bootstrap + M /trunk/configure.ac + + * bootstrap: update bootstrapping script. + * configure.ac: hide autotools files in .auto/. + * .gitignore: add an ignore file for git-svn users. +------------------------------------------------------------------------ +r213 | sam | 2008-08-29 18:57:42 +0000 (Fri, 29 Aug 2008) | 2 lines +Changed paths: + M /trunk/src/libdvdcss.c + + * libdvdcss.c: ignore failure to get the disc key in case we have a + chance to decrypt anyway afterwards. Patch courtesy of Diego Biurrun. +------------------------------------------------------------------------ +r212 | sam | 2008-07-13 12:52:22 +0000 (Sun, 13 Jul 2008) | 2 lines +Changed paths: + M /trunk/src/css.c + M /trunk/src/css.h + M /trunk/src/csstables.h + M /trunk/src/device.c + M /trunk/src/device.h + M /trunk/src/dvdcss/dvdcss.h + M /trunk/src/ioctl.c + M /trunk/src/libdvdcss.c + M /trunk/src/libdvdcss.h + + * Convert all source code to UTF-8, or Doxygen will fail to generate proper + LaTeX documents. +------------------------------------------------------------------------ +r211 | sam | 2008-07-13 12:52:19 +0000 (Sun, 13 Jul 2008) | 1 line +Changed paths: + M /trunk/doc/doxygen.cfg.in + + * Update outdated Doxygen configuration file using doxygen -u. +------------------------------------------------------------------------ +r210 | massiot | 2008-07-12 12:19:57 +0000 (Sat, 12 Jul 2008) | 5 lines +Changed paths: + M /trunk/src/css.c + M /trunk/src/libdvdcss.c + + * src/libdvdcss.c: initialize p_disc_key in the case when DVD is encrypted + but no ioctl is available ; + * src/css.c: initialize p_disc_key in the case when key decryption fails. +Patch by Kirill Belokurov. + +------------------------------------------------------------------------ +r209 | massiot | 2008-07-11 17:23:25 +0000 (Fri, 11 Jul 2008) | 3 lines +Changed paths: + M /trunk/src/dvdcss/dvdcss.h + M /trunk/src/libdvdcss.c + + * src/libdvdcss.c: add dvdcss_is_scrambled() function, patch courtesy of + Olivier Rolland. + +------------------------------------------------------------------------ +r208 | robux4 | 2008-01-07 16:48:35 +0000 (Mon, 07 Jan 2008) | 1 line +Changed paths: + M /trunk/src/dvdcss/dvdcss.h + +nicer comment, patch by Diego Biurrun +------------------------------------------------------------------------ +r207 | robux4 | 2007-09-17 12:10:20 +0000 (Mon, 17 Sep 2007) | 1 line +Changed paths: + M /trunk/src/bsdi_dvd.h + M /trunk/src/dvdcss/dvdcss.h + M /trunk/src/ioctl.h + +(from Diego Biurrun) Identifiers starting with two underscores or an underscore and capital letters are reserved for the system in C. +------------------------------------------------------------------------ +r206 | robux4 | 2007-09-17 12:07:41 +0000 (Mon, 17 Sep 2007) | 4 lines +Changed paths: + M /trunk/src/libdvdcss.c + +(from Diego Biurrun) This patch removes the following warning when compiling MPlayer: + +libdvdcss.c:145: warning: redundant redeclaration of 'dvdcss_interface_2' +dvdcss/dvdcss.h:70: warning: previous declaration of 'dvdcss_interface_2' was here +------------------------------------------------------------------------ +r205 | robux4 | 2007-07-29 10:14:53 +0000 (Sun, 29 Jul 2007) | 7 lines +Changed paths: + M /trunk/src/libdvdcss.c + +Pathc from iive (via Diego Biurrun) +Date: Sat Jul 7 01:22:51 2007 + +Fix crash on some DVDs +sprintf(tmp,"%.02x",(char)0xef); would print "ffffffef" instead of "ef", +in this case this leads to local array buffer overflow and hard to trace stack corruption. +The quick, easy & dirty solution is to use (unsigned char) or (uint8_t) +------------------------------------------------------------------------ +r204 | xtophe | 2007-07-15 22:23:39 +0000 (Sun, 15 Jul 2007) | 2 lines +Changed paths: + M /trunk/bootstrap + +support automake 1.10 + +------------------------------------------------------------------------ +r203 | robux4 | 2006-11-07 16:27:40 +0000 (Tue, 07 Nov 2006) | 2 lines +Changed paths: + M /trunk/src/common.h + M /trunk/src/device.c + +fix cygwin compilation regarding the lseek change +(patch by Diego Biurrun) +------------------------------------------------------------------------ +r202 | robux4 | 2006-11-01 14:31:51 +0000 (Wed, 01 Nov 2006) | 2 lines +Changed paths: + M /trunk/src/common.h + +fix compilation on MINGW (patch by Diego Biurrun) +(lseek vs lseek64 typo) +------------------------------------------------------------------------ +r201 | sam | 2006-09-19 23:03:53 +0000 (Tue, 19 Sep 2006) | 2 lines +Changed paths: + M /trunk/src/libdvdcss.c + + * Fixed spelling in documentation. Also testing buildbot. + +------------------------------------------------------------------------ +r200 | sam | 2006-09-19 22:28:06 +0000 (Tue, 19 Sep 2006) | 2 lines +Changed paths: + M /trunk/src/css.c + M /trunk/src/libdvdcss.c + + * Fix warnings due to signed / unsigned pointer targets. + +------------------------------------------------------------------------ +r199 | sam | 2006-09-19 22:27:46 +0000 (Tue, 19 Sep 2006) | 2 lines +Changed paths: + M /trunk/bootstrap + + * Update bootstrap script. + +------------------------------------------------------------------------ +r198 | robux4 | 2006-09-13 13:12:23 +0000 (Wed, 13 Sep 2006) | 4 lines +Changed paths: + M /trunk/src/libdvdcss.c + +fallback to USERPROFILE environment variable for caching CSS keys when +HOME is not set (for MinGW builds running outside of MinGW). +patch from MPlayer via Diego Biurrun (diego at biurrun dot de) + +------------------------------------------------------------------------ +r197 | robux4 | 2006-09-13 13:11:25 +0000 (Wed, 13 Sep 2006) | 2 lines +Changed paths: + M /trunk/src/device.c + +now accepts X:\ as a device name, as well as X: +patch from MPlayer via Diego Biurrun (diego at biurrun dot de) +------------------------------------------------------------------------ +r196 | sam | 2006-03-30 14:31:12 +0000 (Thu, 30 Mar 2006) | 2 lines +Changed paths: + M /trunk/configure.ac + + * Oops, forgot to commit configure.ac when removing the debian/ directory. + +------------------------------------------------------------------------ +r195 | sam | 2006-03-30 14:30:43 +0000 (Thu, 30 Mar 2006) | 3 lines +Changed paths: + M /trunk/Makefile.am + D /trunk/debian + + * Removed the debian/ directory. Debian packaging is now handled + separately, in the pkg-multimedia repository. + +------------------------------------------------------------------------ +r194 | sam | 2006-01-26 20:48:06 +0000 (Thu, 26 Jan 2006) | 3 lines +Changed paths: + M /trunk/src/device.c + + * src/device.c: reduced code duplication and fixed a pointer/integer + confusion in the OS X drive detection. + +------------------------------------------------------------------------ +r193 | sam | 2005-11-09 22:12:32 +0000 (Wed, 09 Nov 2005) | 3 lines +Changed paths: + M /trunk/src/common.h + + * src/common.h: do not override lseek on Cygwin, only on mingw32. Cygwin + provides its own 64-bit offset lseek. Patch courtesy of the MPlayer team. + +------------------------------------------------------------------------ +r192 | sam | 2005-10-26 16:58:08 +0000 (Wed, 26 Oct 2005) | 2 lines +Changed paths: + M /trunk/debian/control + + * debian/control: build-depend on tetex-extra (needed by doxygen). + +------------------------------------------------------------------------ +r191 | robux4 | 2005-09-04 08:49:23 +0000 (Sun, 04 Sep 2005) | 1 line +Changed paths: + M /trunk/src/dvdcss/dvdcss.h + +* libdvdcss: more fixes for DLL building +------------------------------------------------------------------------ +r190 | robux4 | 2005-09-04 08:31:58 +0000 (Sun, 04 Sep 2005) | 1 line +Changed paths: + M /trunk/msvc/config.h + +* libdvdcss: the current version is 1.2.9 +------------------------------------------------------------------------ +r189 | robux4 | 2005-09-04 08:31:26 +0000 (Sun, 04 Sep 2005) | 1 line +Changed paths: + M /trunk/src/device.c + +* libdvdcss: MSVC7 compilation fixes (shouldn't break mingw32) +------------------------------------------------------------------------ +r188 | robux4 | 2005-09-04 08:25:26 +0000 (Sun, 04 Sep 2005) | 1 line +Changed paths: + M /trunk/src/common.h + M /trunk/src/ioctl.h + M /trunk/src/libdvdcss.h + +* libdvdcss: MSVC7 compilation fixes (shouldn't break mingw32) +------------------------------------------------------------------------ +r187 | robux4 | 2005-09-04 07:54:41 +0000 (Sun, 04 Sep 2005) | 1 line +Changed paths: + M /trunk/src/dvdcss/dvdcss.h + M /trunk/src/libdvdcss.c + +* libdvdcss: oops mismatch #ifdef +------------------------------------------------------------------------ +r186 | robux4 | 2005-09-04 07:43:15 +0000 (Sun, 04 Sep 2005) | 1 line +Changed paths: + M /trunk/AUTHORS + M /trunk/COPYING + M /trunk/ChangeLog + M /trunk/INSTALL + M /trunk/Makefile.am + M /trunk/NEWS + M /trunk/README + M /trunk/debian/Makefile.am + M /trunk/doc/Makefile.am + M /trunk/doc/doxygen.cfg.in + M /trunk/doc/footer.html + M /trunk/doc/header.html + M /trunk/msvc/config.h + M /trunk/msvc/csstest.dsp + M /trunk/msvc/libdvdcss.dsp + M /trunk/msvc/workspace.dsw + M /trunk/src/Makefile.am + M /trunk/src/bsdi_dvd.h + M /trunk/src/bsdi_ioctl.c + M /trunk/src/common.h + M /trunk/src/css.c + M /trunk/src/css.h + M /trunk/src/csstables.h + M /trunk/src/device.c + M /trunk/src/device.h + M /trunk/src/dvdcss/Makefile.am + M /trunk/src/dvdcss/dvdcss.h + M /trunk/src/error.c + M /trunk/src/ioctl.c + M /trunk/src/ioctl.h + M /trunk/src/libdvdcss.c + M /trunk/src/libdvdcss.h + M /trunk/test/Makefile.am + M /trunk/test/csstest.c + M /trunk/test/dvd_region.c + +* libdvdcss: set EOL style in SVN +------------------------------------------------------------------------ +r185 | robux4 | 2005-09-04 07:39:37 +0000 (Sun, 04 Sep 2005) | 1 line +Changed paths: + M /trunk/src/dvdcss/dvdcss.h + +* libdvdcss: better DLL/library difference +------------------------------------------------------------------------ +r184 | robux4 | 2005-09-04 07:36:01 +0000 (Sun, 04 Sep 2005) | 1 line +Changed paths: + M /trunk/src/dvdcss/dvdcss.h + +* libdvdcss: allow building DLL exports +------------------------------------------------------------------------ +r183 | sam | 2005-09-03 13:17:55 +0000 (Sat, 03 Sep 2005) | 4 lines +Changed paths: + M /trunk/configure.ac + M /trunk/doc + M /trunk/test + + * configure.ac: patch from Diego Pettenò to let the user disable the + documentation build. + * test doc: added missing svn:ignore entries. + +------------------------------------------------------------------------ +r182 | massiot | 2005-09-01 17:12:42 +0000 (Thu, 01 Sep 2005) | 2 lines +Changed paths: + M /trunk/bootstrap + + * Revert [181] since it breaks on some OS X versions. + +------------------------------------------------------------------------ +r181 | massiot | 2005-09-01 12:40:25 +0000 (Thu, 01 Sep 2005) | 3 lines +Changed paths: + M /trunk/bootstrap + + * bootstrap: Use libtoolize instead of glibtoolize when it is available + because libtool under OS X sucks. + +------------------------------------------------------------------------ +r180 | massiot | 2005-08-31 19:07:00 +0000 (Wed, 31 Aug 2005) | 2 lines +Changed paths: + M /trunk/src/device.c + + * src/device.c: Under Windows remove the trailing backslash. + +------------------------------------------------------------------------ +r179 | sam | 2005-08-30 10:20:18 +0000 (Tue, 30 Aug 2005) | 2 lines +Changed paths: + M /trunk/configure.ac + M /trunk/src/Makefile.am + + * configure.ac: forward -framework options to the linker. + +------------------------------------------------------------------------ +r178 | massiot | 2005-08-30 09:48:19 +0000 (Tue, 30 Aug 2005) | 2 lines +Changed paths: + M /trunk/src/device.c + + * src/device.c: Fixed compilation under Darwin. + +------------------------------------------------------------------------ +r177 | sam | 2005-08-29 22:25:20 +0000 (Mon, 29 Aug 2005) | 2 lines +Changed paths: + M /trunk/src/device.c + + * src/device.c: tried to port the device autodetection to OS X. + +------------------------------------------------------------------------ +r176 | sam | 2005-08-29 22:02:55 +0000 (Mon, 29 Aug 2005) | 3 lines +Changed paths: + M /trunk/src/device.c + M /trunk/src/device.h + M /trunk/src/libdvdcss.c + + * src/device.c: if the target is the empty string, attempt to autodetect + the DVD drive instead of giving up. + +------------------------------------------------------------------------ +r175 | sam | 2005-08-23 16:15:38 +0000 (Tue, 23 Aug 2005) | 3 lines +Changed paths: + M /trunk/doc/Makefile.am + D /trunk/doc/doxygen.cfg + A /trunk/doc/doxygen.cfg.in (from /trunk/doc/doxygen.cfg:174) + + * doc/Makefile.am: fixed build in a separate directory. Patch courtesy + of Bernard Leak with a few additions. + +------------------------------------------------------------------------ +r173 | sam | 2005-07-11 12:32:57 +0000 (Mon, 11 Jul 2005) | 2 lines +Changed paths: + M /trunk/ChangeLog + + * Updated ChangeLog. + +------------------------------------------------------------------------ +r172 | sam | 2005-07-11 12:31:58 +0000 (Mon, 11 Jul 2005) | 2 lines +Changed paths: + M /trunk/src/Makefile.am + + * src/Makefile.am: bumped libtool version information. + +------------------------------------------------------------------------ +r171 | sam | 2005-07-11 12:25:18 +0000 (Mon, 11 Jul 2005) | 2 lines +Changed paths: + M /trunk/debian/changelog + M /trunk/debian/control + + * debian/*: updated Debian packaging information. + +------------------------------------------------------------------------ +r170 | sam | 2005-07-11 12:23:07 +0000 (Mon, 11 Jul 2005) | 2 lines +Changed paths: + M /trunk/src/css.c + + * src/css.c: grmbl, compile fix. + +------------------------------------------------------------------------ +r169 | massiot | 2005-07-11 12:15:10 +0000 (Mon, 11 Jul 2005) | 2 lines +Changed paths: + M /trunk/NEWS + M /trunk/configure.ac + M /trunk/debian/changelog + M /trunk/libdvdcss.spec + + * Bumped up version number to 1.2.9. + +------------------------------------------------------------------------ +r168 | sam | 2005-07-11 12:10:43 +0000 (Mon, 11 Jul 2005) | 2 lines +Changed paths: + M /trunk/src/css.c + + * src/css.c: reworked my verbosity patch to fix a compilation issue. + +------------------------------------------------------------------------ +r167 | sam | 2005-07-11 11:58:58 +0000 (Mon, 11 Jul 2005) | 3 lines +Changed paths: + M /trunk/src/ioctl.c + + * src/ioctl.c: under Solaris, use libsmedia for ioctls when available. Code + reworked from a patch courtesy of the MPlayer team. + +------------------------------------------------------------------------ +r166 | sam | 2005-07-11 11:41:15 +0000 (Mon, 11 Jul 2005) | 3 lines +Changed paths: + M /trunk/src/bsdi_ioctl.c + + * src/bsdi_ioctl.c: use memset instead of bzero. Patch courtesy of the + MPlayer team. + +------------------------------------------------------------------------ +r165 | sam | 2005-07-11 11:32:33 +0000 (Mon, 11 Jul 2005) | 3 lines +Changed paths: + M /trunk/src/device.c + M /trunk/src/ioctl.h + + * src/device.c src/ioctl.h: cosmetic fix that uses real Win32 types for + dynamically loaded functions and gets rid of lvalue casts. + +------------------------------------------------------------------------ +r164 | sam | 2005-07-11 11:25:47 +0000 (Mon, 11 Jul 2005) | 2 lines +Changed paths: + M /trunk/src/css.c + + * src/css.c: be slightly more verbose in which keys we manipulate. + +------------------------------------------------------------------------ +r163 | sam | 2005-07-11 11:22:33 +0000 (Mon, 11 Jul 2005) | 2 lines +Changed paths: + M /trunk/bootstrap + + * bootstrap: allow to bootstrap with aclocal/automake version 1.9. + +------------------------------------------------------------------------ +r162 | gbazin | 2004-09-02 12:17:13 +0000 (Thu, 02 Sep 2004) | 1 line +Changed paths: + M /trunk/src/common.h + +* src/common.h: use lseeki64 for file seeking on win32 (works above the 2.1G boundary). +------------------------------------------------------------------------ +r161 | sam | 2004-08-13 13:53:27 +0000 (Fri, 13 Aug 2004) | 4 lines +Changed paths: + M /trunk/src/css.c + + * src/css.c: + + Save the cached key as ASCII in hexadecimal form. + + Overwrite cached files if the data was invalid. + +------------------------------------------------------------------------ +r160 | sam | 2004-08-13 13:40:44 +0000 (Fri, 13 Aug 2004) | 4 lines +Changed paths: + M /trunk/src/libdvdcss.c + + * src/libdvdcss.c: + + Recreate the cache dir information on each launch, in case the + information it contains ever changes. + +------------------------------------------------------------------------ +r159 | sam | 2004-08-11 23:26:35 +0000 (Wed, 11 Aug 2004) | 2 lines +Changed paths: + M /trunk + M /trunk/Makefile.am + D /trunk/autotools + M /trunk/bootstrap + M /trunk/configure.ac + + * Don't put autotools/ under revision control. + +------------------------------------------------------------------------ +r158 | sam | 2004-08-11 23:24:54 +0000 (Wed, 11 Aug 2004) | 2 lines +Changed paths: + D /trunk/autotools/Makefile.am + + * Don't put autotools/ under revision control. + +------------------------------------------------------------------------ +r157 | sam | 2004-08-11 23:04:39 +0000 (Wed, 11 Aug 2004) | 2 lines +Changed paths: + M /trunk/libdvdcss.spec + + * libdvdcss.spec: updated Red Hat rules for RH9. + +------------------------------------------------------------------------ +r156 | sam | 2004-08-11 22:59:42 +0000 (Wed, 11 Aug 2004) | 4 lines +Changed paths: + M /trunk/src/libdvdcss.c + + * src/libdvdcss.c: + + Support for cache directory tags, as proposed on + http://www.brynosaurus.com/cachedir/spec.html . + +------------------------------------------------------------------------ +r155 | sam | 2004-08-11 22:15:30 +0000 (Wed, 11 Aug 2004) | 6 lines +Changed paths: + M /trunk/AUTHORS + M /trunk/src/libdvdcss.c + + * src/libdvdcss.c: + + Append the disc key to the cache directory name to avoid issues with + identical discs which have different encryption keys, thanks to Sven + Heithecker. + + Use - instead of # as a separator in the cache filename. + +------------------------------------------------------------------------ +r154 | sam | 2004-07-05 09:17:20 +0000 (Mon, 05 Jul 2004) | 2 lines +Changed paths: + M /trunk/bootstrap + + * bootstrap: fixed a syntax error. + +------------------------------------------------------------------------ +r153 | sam | 2004-07-05 09:15:35 +0000 (Mon, 05 Jul 2004) | 4 lines +Changed paths: + M /trunk/bootstrap + + * bootstrap: + + Run libtoolize before aclocal. + + Support automake 1.8. + +------------------------------------------------------------------------ +r152 | sam | 2004-02-24 15:47:00 +0000 (Tue, 24 Feb 2004) | 2 lines +Changed paths: + M /trunk + D /trunk/.cvsignore + M /trunk/NEWS + M /trunk/README + M /trunk/autotools + D /trunk/autotools/.cvsignore + M /trunk/bootstrap + M /trunk/debian + D /trunk/debian/.cvsignore + M /trunk/doc + D /trunk/doc/.cvsignore + M /trunk/doc/footer.html + M /trunk/doc/header.html + M /trunk/msvc + D /trunk/msvc/.cvsignore + M /trunk/src + D /trunk/src/.cvsignore + M /trunk/src/bsdi_dvd.h + M /trunk/src/common.h + M /trunk/src/css.c + M /trunk/src/css.h + M /trunk/src/csstables.h + M /trunk/src/device.c + M /trunk/src/device.h + M /trunk/src/dvdcss + D /trunk/src/dvdcss/.cvsignore + M /trunk/src/dvdcss/dvdcss.h + M /trunk/src/error.c + M /trunk/src/ioctl.c + M /trunk/src/ioctl.h + M /trunk/src/libdvdcss.c + M /trunk/src/libdvdcss.h + M /trunk/test + D /trunk/test/.cvsignore + + * Added proper SVN keywords to files and directories (for $Id and ignores). + +------------------------------------------------------------------------ +r141 | sam | 2003-12-11 15:13:40 +0000 (Thu, 11 Dec 2003) | 3 lines +Changed paths: + M /trunk/doc/.cvsignore + M /trunk/doc/doxygen.cfg + + * doc/doxygen.cfg: Updated doxygen configuration. + * doc/.cvsignore: Ignore stamp files. + +------------------------------------------------------------------------ +r140 | sam | 2003-12-11 15:12:42 +0000 (Thu, 11 Dec 2003) | 5 lines +Changed paths: + M /trunk/src/device.c + + * src/device.c: + + Store the off_t values for seek and read in a temporary variable to + work around a strange gentoo gcc behaviour as seen here: + http://www.via.ecp.fr/via/ml/libdvdcss-devel/200312/msg00000.html + +------------------------------------------------------------------------ +r139 | sam | 2003-11-26 20:16:38 +0000 (Wed, 26 Nov 2003) | 2 lines +Changed paths: + M /trunk/libdvdcss.spec + + * libdvdcss.spec: Fixed a syntax error (#1488). + +------------------------------------------------------------------------ +r138 | sam | 2003-11-06 10:12:38 +0000 (Thu, 06 Nov 2003) | 2 lines +Changed paths: + M /trunk/bootstrap + + * bootstrap: remove autom4te.cache before running autoconf + +------------------------------------------------------------------------ +r137 | sam | 2003-09-15 17:12:46 +0000 (Mon, 15 Sep 2003) | 2 lines +Changed paths: + M /trunk/src/css.c + M /trunk/src/libdvdcss.c + + * libdvdcss.c: Added more debug messages. + +------------------------------------------------------------------------ +r136 | sam | 2003-09-09 13:17:24 +0000 (Tue, 09 Sep 2003) | 2 lines +Changed paths: + M /trunk/configure.ac + M /trunk/src/css.c + M /trunk/src/device.c + + * src/css.c, src/device.c: more meaningful error messages. + +------------------------------------------------------------------------ +r135 | sam | 2003-09-09 12:32:40 +0000 (Tue, 09 Sep 2003) | 4 lines +Changed paths: + M /trunk/.cvsignore + M /trunk/Makefile.am + M /trunk/NEWS + M /trunk/README + M /trunk/configure.ac + M /trunk/debian/Makefile.am + M /trunk/debian/changelog + A /trunk/debian/compat + M /trunk/debian/control + M /trunk/debian/rules + M /trunk/doc/Makefile.am + M /trunk/doc/footer.html + M /trunk/doc/header.html + M /trunk/test/csstest.c + + * configure.ac: check for doxygen and latex to build documentation. + * doc/Makefile.am: conditionally build documentation. + * debian/*: use debian/compat instead of DH_COMPAT. + +------------------------------------------------------------------------ +r134 | sam | 2003-09-09 12:05:44 +0000 (Tue, 09 Sep 2003) | 2 lines +Changed paths: + M /trunk/bootstrap + + * bootstrap: code clean-up. + +------------------------------------------------------------------------ +r133 | sam | 2003-09-09 10:03:48 +0000 (Tue, 09 Sep 2003) | 3 lines +Changed paths: + M /trunk/src/css.c + M /trunk/src/device.c + M /trunk/src/error.c + M /trunk/src/libdvdcss.c + M /trunk/src/libdvdcss.h + + * Changed _dvdcss_error and _dvdcss_debug to print_error and print_debug + because they aren't libdvdcss functions. + +------------------------------------------------------------------------ +r132 | gbazin | 2003-07-29 19:49:13 +0000 (Tue, 29 Jul 2003) | 3 lines +Changed paths: + M /trunk/NEWS + + +* NEWS: forgot to update this one for the release. + +------------------------------------------------------------------------ +r131 | gbazin | 2003-07-29 19:03:02 +0000 (Tue, 29 Jul 2003) | 3 lines +Changed paths: + M /trunk/libdvdcss.spec + + +* libdvdcss.spec: fixed typo. + +------------------------------------------------------------------------ +r130 | gbazin | 2003-07-28 23:41:52 +0000 (Mon, 28 Jul 2003) | 3 lines +Changed paths: + M /trunk/ChangeLog + M /trunk/configure.ac + M /trunk/debian/changelog + M /trunk/libdvdcss.spec + + +* ALL: bumped version number to 1.2.8 + +------------------------------------------------------------------------ +r129 | sam | 2003-07-16 21:40:01 +0000 (Wed, 16 Jul 2003) | 7 lines +Changed paths: + M /trunk/src/css.c + + * src/css.c: + + Workaround in CrackTitleKey for strange discs that report read errors + seemingly at random. Testcase was on Linux 2.4.20, with a region 2 RPC2 + drive, and the region 1 copy of "Chasing Amy". + + Used macros instead of numerals where appropriate. + + Fixed spelling here and there. + +------------------------------------------------------------------------ +r128 | gbazin | 2003-07-08 18:00:54 +0000 (Tue, 08 Jul 2003) | 3 lines +Changed paths: + M /trunk/src/device.c + + +* src/device.c: grmblgrmbl!! Fixed a bug that prevented encrypted dvds from working under win32. + +------------------------------------------------------------------------ +r127 | massiot | 2003-06-22 20:59:45 +0000 (Sun, 22 Jun 2003) | 2 lines +Changed paths: + M /trunk/src/Makefile.am + +* Updated library version. + +------------------------------------------------------------------------ +r126 | sam | 2003-06-18 17:23:55 +0000 (Wed, 18 Jun 2003) | 2 lines +Changed paths: + M /trunk/src/libdvdcss.c + + * ./src/libdvdcss.c: if DVDCSS_VERBOSE is greater than 2, do as if it was 2. + +------------------------------------------------------------------------ +r125 | sam | 2003-06-13 00:41:35 +0000 (Fri, 13 Jun 2003) | 12 lines +Changed paths: + M /trunk/ChangeLog + M /trunk/NEWS + M /trunk/configure.ac + M /trunk/debian/changelog + M /trunk/debian/control + M /trunk/debian/rules + M /trunk/libdvdcss.spec + + * Everything is ready for a 1.2.7 release. + + * debian/control: + + Set policy to 3.5.10. + + Removed the leading "a" in the package description. + + Set the source section to libs. + + Set the -dev package section to libdevel. + + Changed the debhelper build dependency to (>=3.0). + * debian/rules: + + Added magic to avoid autotools timestamp skews on autobuilders (as if + libdvdcss was ever going to hit the Debian autobuilders anyway). + +------------------------------------------------------------------------ +r124 | sam | 2003-06-12 23:22:34 +0000 (Thu, 12 Jun 2003) | 6 lines +Changed paths: + M /trunk/src/libdvdcss.c + + * ./src/libdvdcss.c: if DVDCSS_CACHE is not set, we force a default value. + - under Win32: C:\Documents and Settings\$USER\Application Data\dvdcss\ + - under Unix and everything else: ${HOME}/.dvdcss/ + - the special value DVDCSS_CACHE=off disables caching. + * ./src/libdvdcss.c: updated doxygen documentation accordingly. + +------------------------------------------------------------------------ +r123 | sam | 2003-06-12 23:15:18 +0000 (Thu, 12 Jun 2003) | 3 lines +Changed paths: + M /trunk/Makefile.am + M /trunk/configure.ac + + * ./Makefile.am: put autotools/ in DIST_SUBDIRS instead of SUBDIRS. + * ./configure.ac: forgot to generate autotools/Makefile. + +------------------------------------------------------------------------ +r122 | sam | 2003-06-10 22:50:31 +0000 (Tue, 10 Jun 2003) | 4 lines +Changed paths: + M /trunk/Makefile.am + A /trunk/autotools + A /trunk/autotools/.cvsignore + A /trunk/autotools/Makefile.am + M /trunk/bootstrap + M /trunk/configure.ac + + * ./configure.ac: make use of the autotools/ directory. + * ./bootstrap: libfool is a tool. Worked around its blatant ignorance of + the AC_CONFIG_AUX_DIR directive. + +------------------------------------------------------------------------ +r121 | sam | 2003-05-27 17:12:33 +0000 (Tue, 27 May 2003) | 4 lines +Changed paths: + M /trunk/debian/changelog + M /trunk/debian/control + + * ./debian/control: removed libc6-dev from libdvdcss2-dev's dependencies + because it is part of build-essential and it isn't even called libc6-dev + on all architectures. + +------------------------------------------------------------------------ +r120 | sam | 2003-05-16 22:12:48 +0000 (Fri, 16 May 2003) | 2 lines +Changed paths: + M /trunk/src/css.c + + * ./src/css.c: typos in comments. + +------------------------------------------------------------------------ +r119 | gbazin | 2003-04-11 10:00:29 +0000 (Fri, 11 Apr 2003) | 3 lines +Changed paths: + M /trunk/configure.ac + M /trunk/src/common.h + + +* configure.ac, src/common.h: fixes for the cygwin build using the mno-cygwin flag. + +------------------------------------------------------------------------ +r118 | yves | 2003-04-06 20:36:07 +0000 (Sun, 06 Apr 2003) | 2 lines +Changed paths: + M /trunk/libdvdcss.spec + +better RH part thx Kipp Cannon <kipp@sgl.crestech.ca> + +------------------------------------------------------------------------ +r117 | gbazin | 2003-03-27 18:57:12 +0000 (Thu, 27 Mar 2003) | 3 lines +Changed paths: + M /trunk/src/libdvdcss.c + + +* src/libdvdcss.c: CSS key cache collisions patch, courtesy of Michael Roitzsch. + +------------------------------------------------------------------------ +r116 | gbazin | 2003-03-22 16:37:37 +0000 (Sat, 22 Mar 2003) | 3 lines +Changed paths: + M /trunk/src/libdvdcss.c + + +* src/libdvdcss.c: fix for NetBSD's mkdir that doesn't like trailing "/" on its argument. (courtesy of Christopher Richards) + +------------------------------------------------------------------------ +r115 | sam | 2003-03-10 18:01:40 +0000 (Mon, 10 Mar 2003) | 3 lines +Changed paths: + M /trunk/debian/changelog + M /trunk/src/Makefile.am + + * ./debian/changelog: updated Debian changelog. + * ./src/Makefile.am: bumped version information. + +------------------------------------------------------------------------ +r114 | alexis | 2003-03-10 17:41:31 +0000 (Mon, 10 Mar 2003) | 2 lines +Changed paths: + M /trunk/ChangeLog + M /trunk/libdvdcss.spec + +- preparing the 1.2.6 release... + +------------------------------------------------------------------------ +r113 | massiot | 2003-03-09 23:50:42 +0000 (Sun, 09 Mar 2003) | 2 lines +Changed paths: + M /trunk/NEWS + M /trunk/configure.ac + +Bumped up to 1.2.6. + +------------------------------------------------------------------------ +r112 | gbazin | 2003-03-09 23:34:18 +0000 (Sun, 09 Mar 2003) | 3 lines +Changed paths: + M /trunk/src/common.h + M /trunk/src/error.c + + +* src/common.h, src/error.c: fixed the PATH_MAX breakage on win32. + +------------------------------------------------------------------------ +r111 | massiot | 2003-02-04 11:54:36 +0000 (Tue, 04 Feb 2003) | 2 lines +Changed paths: + M /trunk/src/css.c + M /trunk/src/device.c + M /trunk/src/error.c + +Fixed compilation problems with PATH_MAX. + +------------------------------------------------------------------------ +r110 | massiot | 2003-01-29 22:59:35 +0000 (Wed, 29 Jan 2003) | 2 lines +Changed paths: + M /trunk/configure.ac + M /trunk/src/libdvdcss.c + +Fixed MAX_PATH on Darwin. + +------------------------------------------------------------------------ +r109 | yves | 2003-01-28 07:58:22 +0000 (Tue, 28 Jan 2003) | 3 lines +Changed paths: + M /trunk/libdvdcss.spec + +- release number is 1. do not forget to update it too, aka sam sux. +- fix a redhat "macro". + +------------------------------------------------------------------------ +r108 | sam | 2003-01-28 01:17:02 +0000 (Tue, 28 Jan 2003) | 6 lines +Changed paths: + M /trunk/ChangeLog + A /trunk/NEWS + M /trunk/configure.ac + M /trunk/debian/changelog + M /trunk/debian/rules + M /trunk/doc/doxygen.cfg + M /trunk/libdvdcss.spec + M /trunk/src/Makefile.am + M /trunk/test/Makefile.am + + * updated ChangeLog. + * updated version numbers and timestamps everywhere. + * created NEWS file. + * ./configure.ac: BSD/OS compilation fix when a local copy of libdvd is + found on the system, thanks to Steven M. Schultz. + +------------------------------------------------------------------------ +r107 | sam | 2003-01-28 00:41:10 +0000 (Tue, 28 Jan 2003) | 3 lines +Changed paths: + M /trunk/src/libdvdcss.c + M /trunk/test/csstest.c + + * ./test/csstest.c: we align our read buffer in case of raw device access. + * ./src/libdvdcss.c: updated documentation about raw devices. + +------------------------------------------------------------------------ +r106 | sam | 2003-01-27 16:57:19 +0000 (Mon, 27 Jan 2003) | 2 lines +Changed paths: + M /trunk/src/libdvdcss.c + + * ./src/libdvdcss.c: disabled key cache when reading VOBs. + +------------------------------------------------------------------------ +r105 | sam | 2003-01-16 22:58:29 +0000 (Thu, 16 Jan 2003) | 2 lines +Changed paths: + M /trunk/src/ioctl.c + M /trunk/src/ioctl.h + + * ./src/ioctl.c, ./src/ioctl.h: removed minor gcc-isms. + +------------------------------------------------------------------------ +r104 | yves | 2003-01-16 14:45:14 +0000 (Thu, 16 Jan 2003) | 3 lines +Changed paths: + M /trunk/libdvdcss.spec + +* macros to fix build on redhat system. put %define redhat80 to 1. +* few fixes. + +------------------------------------------------------------------------ +r103 | sam | 2002-12-19 16:50:50 +0000 (Thu, 19 Dec 2002) | 4 lines +Changed paths: + M /trunk/src/device.c + + * ./src/device.c: seek() calls don't do anything if we're already at the + right position. + * ./src/device.c: we now handle partial reads. + +------------------------------------------------------------------------ +r102 | sam | 2002-12-19 15:44:30 +0000 (Thu, 19 Dec 2002) | 2 lines +Changed paths: + M /trunk/configure.ac + M /trunk/src/css.c + M /trunk/src/libdvdcss.c + + * ./configure.ac: added warning flags whenever possible. + +------------------------------------------------------------------------ +r101 | sam | 2002-12-19 15:36:04 +0000 (Thu, 19 Dec 2002) | 3 lines +Changed paths: + M /trunk/configure.ac + M /trunk/src/device.c + M /trunk/src/libdvdcss.h + + * ./src/device.c: dvdcss->i_pos now gets updated on each seek and each + read. Partial reads are not handled yet, but it's a step. + +------------------------------------------------------------------------ +r100 | sam | 2002-12-19 15:29:53 +0000 (Thu, 19 Dec 2002) | 3 lines +Changed paths: + M /trunk/src/bsdi_dvd.h + M /trunk/src/bsdi_ioctl.c + + * ./src/bsdi_ioctl.c, ./src/bsdi_dvd.h: updated the bsdi libdvd with + Steven M. Schultz's latest changes. + +------------------------------------------------------------------------ +r99 | sam | 2002-12-19 12:37:30 +0000 (Thu, 19 Dec 2002) | 2 lines +Changed paths: + M /trunk/configure.ac + M /trunk/msvc/config.h + M /trunk/src/device.c + M /trunk/src/device.h + M /trunk/src/libdvdcss.c + M /trunk/src/libdvdcss.h + + * Ported the library build to Cygwin. + +------------------------------------------------------------------------ +r98 | sam | 2002-12-11 13:12:10 +0000 (Wed, 11 Dec 2002) | 2 lines +Changed paths: + M /trunk/src/bsdi_dvd.h + M /trunk/src/bsdi_ioctl.c + M /trunk/src/device.c + M /trunk/src/dvdcss/dvdcss.h + M /trunk/src/libdvdcss.c + + * minor coding style fixes. + +------------------------------------------------------------------------ +r97 | sam | 2002-12-10 10:43:25 +0000 (Tue, 10 Dec 2002) | 2 lines +Changed paths: + M /trunk/msvc/csstest.dsp + M /trunk/msvc/libdvdcss.dsp + M /trunk/msvc/workspace.dsw + + * ./msvc/*: grmbl, for some reason the project files were empty. + +------------------------------------------------------------------------ +r96 | sam | 2002-12-10 10:38:12 +0000 (Tue, 10 Dec 2002) | 2 lines +Changed paths: + M /trunk/configure.ac + A /trunk/msvc + A /trunk/msvc/.cvsignore + A /trunk/msvc/config.h + A /trunk/msvc/csstest.dsp + A /trunk/msvc/libdvdcss.dsp + A /trunk/msvc/workspace.dsw + M /trunk/src/device.c + M /trunk/src/libdvdcss.c + M /trunk/test/csstest.c + + * ./msvc/*: MS VC++ project files. + +------------------------------------------------------------------------ +r95 | babal | 2002-12-06 00:16:57 +0000 (Fri, 06 Dec 2002) | 3 lines +Changed paths: + M /trunk/src/css.c + M /trunk/src/device.c + M /trunk/src/error.c + M /trunk/src/libdvdcss.c + +- Early versions of Mingw32 (at least until 1.2) do not include + <limits.h> automatically, so PATH_MAX was undefined. + +------------------------------------------------------------------------ +r94 | sam | 2002-12-05 10:24:42 +0000 (Thu, 05 Dec 2002) | 4 lines +Changed paths: + M /trunk/configure.ac + M /trunk/src/common.h + M /trunk/src/css.c + M /trunk/src/css.h + M /trunk/src/csstables.h + M /trunk/src/device.c + M /trunk/src/device.h + M /trunk/src/error.c + M /trunk/src/ioctl.c + M /trunk/src/ioctl.h + M /trunk/src/libdvdcss.c + M /trunk/src/libdvdcss.h + + * ./src/libdvdcss.c: fixed Win32 mkdir() call. + * ALL: removed trailing spaces in files. + * ALL: moved everything to C99 integer types. + +------------------------------------------------------------------------ +r93 | sam | 2002-12-02 12:58:23 +0000 (Mon, 02 Dec 2002) | 2 lines +Changed paths: + M /trunk/bootstrap + + * ./bootstrap: we also look for glibtoolize (Closes: #37). + +------------------------------------------------------------------------ +r92 | jlj | 2002-12-02 07:38:21 +0000 (Mon, 02 Dec 2002) | 2 lines +Changed paths: + M /trunk/src/device.h + + ./src/device.h: Applied FreeBSD compile fix from Steven M. Schultz. + +------------------------------------------------------------------------ +r91 | jlj | 2002-11-25 18:44:31 +0000 (Mon, 25 Nov 2002) | 3 lines +Changed paths: + M /trunk/ChangeLog + M /trunk/src/ioctl.c + M /trunk/src/ioctl.h + M /trunk/test/dvd_region.c + + * ./src/ioctl.[ch]: Implemented ioctl_SendRPC. + * ./test/dvd_region.c: enabled set_region. + +------------------------------------------------------------------------ +r90 | sam | 2002-11-24 17:34:23 +0000 (Sun, 24 Nov 2002) | 3 lines +Changed paths: + M /trunk/src/css.c + M /trunk/src/device.c + M /trunk/src/error.c + M /trunk/src/libdvdcss.c + M /trunk/src/libdvdcss.h + + * ./src/css.c, ./src/libdvdcss.c: applied a patch from the MPlayer folks + to cache title keys on disk. + +------------------------------------------------------------------------ +r89 | sam | 2002-11-21 12:13:20 +0000 (Thu, 21 Nov 2002) | 3 lines +Changed paths: + M /trunk/debian/control + + * ./debian/control: set the package sections to libs and devel instead of + graphics. + +------------------------------------------------------------------------ +r88 | alexis | 2002-11-17 23:46:44 +0000 (Sun, 17 Nov 2002) | 6 lines +Changed paths: + M /trunk/libdvdcss.spec + +Changes in order to support RedHat and RPM 4.1 (courtesy of Ryurick +Hristev and Kenton Groombridge). + +I have already uploaded new RPM packages on the FTP site (1.2.4-2) and +updated the download page. Please test and give feedback. + +------------------------------------------------------------------------ +r87 | jlj | 2002-11-15 18:39:08 +0000 (Fri, 15 Nov 2002) | 2 lines +Changed paths: + M /trunk/src/ioctl.c + M /trunk/src/ioctl.h + + * ./src/ioctl.[ch]: ReportRPC win32 changes. Needs testing. + +------------------------------------------------------------------------ +r86 | gbazin | 2002-11-14 15:12:34 +0000 (Thu, 14 Nov 2002) | 3 lines +Changed paths: + M /trunk/ChangeLog + M /trunk/debian/changelog + M /trunk/libdvdcss.spec + + +* updated the changelogs for the 1.2.4 release. + +------------------------------------------------------------------------ +r85 | sam | 2002-11-14 12:41:47 +0000 (Thu, 14 Nov 2002) | 6 lines +Changed paths: + M /trunk/bootstrap + M /trunk/configure.ac + M /trunk/libdvdcss.spec + + * ./configure.ac: explicitly set AC_CONFIG_AUX_DIR(.) so that people who + do bootstrap without paying attention to error messages don't screw up + packages :-) + * ./libdvdcss.spec: removed bootstrap from the build phase. + * ./bootstrap: we accept automake 1.7. + +------------------------------------------------------------------------ +r84 | gbazin | 2002-11-14 12:38:57 +0000 (Thu, 14 Nov 2002) | 9 lines +Changed paths: + M /trunk/src/css.c + M /trunk/src/ioctl.c + + +* src/css.c src/ioctl.c, src/libdvdcss.c: changed the work-around to detect + if the dvd is encrypted on Win2K in non-administrator mode. + Because we cannot use an ioctl to get the copyright status of the DVD, + we try to get the disc key and if this succeed, we assume the DVD is + encrypted, otherwise we assume it to be unencrypted. + I hope this logic is not too much flawed... at least it seems to be working + with the few DVDs I've got. + +------------------------------------------------------------------------ +r83 | jlj | 2002-11-14 01:32:37 +0000 (Thu, 14 Nov 2002) | 2 lines +Changed paths: + M /trunk/src/ioctl.c + + * ./src/ioctl.c: Broke OpenBSD port with my previous commit. Fixed. + +------------------------------------------------------------------------ +r82 | alexis | 2002-11-13 23:43:01 +0000 (Wed, 13 Nov 2002) | 3 lines +Changed paths: + M /trunk/libdvdcss.spec + + +Added ./bootstrap for the build target + +------------------------------------------------------------------------ +r81 | gbazin | 2002-11-13 23:08:11 +0000 (Wed, 13 Nov 2002) | 3 lines +Changed paths: + M /trunk/ChangeLog + M /trunk/debian/changelog + M /trunk/libdvdcss.spec + + +* update changelogs. + +------------------------------------------------------------------------ +r80 | jlj | 2002-11-13 22:45:05 +0000 (Wed, 13 Nov 2002) | 3 lines +Changed paths: + M /trunk/AUTHORS + M /trunk/src/ioctl.c + + * ./src/ioctl.c: cosmetic fixes. + * ./AUTHORS: updated my entry. + +------------------------------------------------------------------------ +r79 | alexis | 2002-11-13 22:24:41 +0000 (Wed, 13 Nov 2002) | 3 lines +Changed paths: + M /trunk/configure.ac + + +Update version number to 1.2.4 + +------------------------------------------------------------------------ +r78 | alexis | 2002-11-13 22:14:28 +0000 (Wed, 13 Nov 2002) | 2 lines +Changed paths: + M /trunk/libdvdcss.spec + +Update for 1.2.4 release. + +------------------------------------------------------------------------ +r77 | sam | 2002-11-13 22:11:38 +0000 (Wed, 13 Nov 2002) | 3 lines +Changed paths: + M /trunk/debian/changelog + + Updated Debian changelog (though there are no changes in this version + apart from Win32, so what's the point of building new packages :p) + +------------------------------------------------------------------------ +r76 | gbazin | 2002-11-13 21:23:08 +0000 (Wed, 13 Nov 2002) | 3 lines +Changed paths: + M /trunk/ChangeLog + + +* ChangeLog: updated changelog. + +------------------------------------------------------------------------ +r75 | gbazin | 2002-10-29 18:51:37 +0000 (Tue, 29 Oct 2002) | 4 lines +Changed paths: + M /trunk/src/ioctl.c + + +* src/ioctl.c: fixed typo that prevented unencrypted DVDs to work in + non-administrator mode. + +------------------------------------------------------------------------ +r74 | gbazin | 2002-10-19 09:53:33 +0000 (Sat, 19 Oct 2002) | 4 lines +Changed paths: + M /trunk/src/device.c + M /trunk/src/ioctl.h + + +* src/device.c, src/ioctl.h: on win9x, when using ASPI, make sure the drive + we are trying to open is actually a cdrom/dvdrom drive. + +------------------------------------------------------------------------ +r73 | sam | 2002-10-18 18:48:59 +0000 (Fri, 18 Oct 2002) | 5 lines +Changed paths: + M /trunk/src/css.c + M /trunk/src/device.c + M /trunk/src/device.h + M /trunk/src/libdvdcss.c + M /trunk/src/libdvdcss.h + + * ./src/device.c: split the open, read and seek functions so that we can + use function pointers instead of doing the if(WIN2K) test. + * ./src/device.c: if the target is not a drive name such as F:, we open + it with the standard libc functions, even under Win32. + +------------------------------------------------------------------------ +r72 | massiot | 2002-10-12 23:02:49 +0000 (Sat, 12 Oct 2002) | 2 lines +Changed paths: + M /trunk/ChangeLog + M /trunk/debian/changelog + M /trunk/libdvdcss.spec + +Updated changelog and release tag. + +------------------------------------------------------------------------ +r71 | gbazin | 2002-10-12 12:41:24 +0000 (Sat, 12 Oct 2002) | 4 lines +Changed paths: + M /trunk/src/ioctl.c + M /trunk/src/ioctl.h + + +* src/ioctl.c, src/ioctl.h: fix in ioctl_ReadCopyright to try to work around + the buggy IOCTL_DVD_READ_STRUCTURE on WinNT/2k/XP. + +------------------------------------------------------------------------ +r70 | sam | 2002-10-11 10:09:56 +0000 (Fri, 11 Oct 2002) | 2 lines +Changed paths: + M /trunk/ChangeLog + M /trunk/debian/changelog + M /trunk/libdvdcss.spec + + * Updated changelog and package files. + +------------------------------------------------------------------------ +r69 | sam | 2002-10-11 10:03:48 +0000 (Fri, 11 Oct 2002) | 6 lines +Changed paths: + M /trunk/.cvsignore + M /trunk/Makefile.am + D /trunk/NEWS + M /trunk/bootstrap + A /trunk/configure.ac + D /trunk/configure.in + M /trunk/src/.cvsignore + M /trunk/src/Makefile.am + D /trunk/src/config.h.in + + * ./configure.ac, ./bootstrap: used libdvbpsi's bootstrap, moved config.h + to ., renamed configure.in into configure.ac, removed useless files that + are autogenerated. + * ./src/Makefile.am: instead of using -no-undefined "only under BeOS" we + use it "never with MSVC". + +------------------------------------------------------------------------ +r68 | massiot | 2002-10-10 22:29:31 +0000 (Thu, 10 Oct 2002) | 2 lines +Changed paths: + M /trunk/bootstrap + +Exit cleanly in case of error. + +------------------------------------------------------------------------ +r67 | massiot | 2002-10-10 21:40:41 +0000 (Thu, 10 Oct 2002) | 4 lines +Changed paths: + M /trunk/ChangeLog + M /trunk/configure.in + M /trunk/src/config.h.in + M /trunk/src/css.c + +* Bumped up version number to 1.2.3 (soleil !). +* Updated Changelog. +* Merged in hh's patch for broken DVD drives/kernel/whatever. + +------------------------------------------------------------------------ +r66 | gbazin | 2002-10-10 12:44:28 +0000 (Thu, 10 Oct 2002) | 7 lines +Changed paths: + M /trunk/AUTHORS + M /trunk/src/css.c + M /trunk/src/device.c + M /trunk/src/ioctl.c + M /trunk/src/ioctl.h + + +* src/css.c, src/device.c, src/ioctl.[ch]: We don't need to be in administrator mode +anymore to authenticate the drive on Windows NT/2k/XP. As a result any user can now +play a DVD on these OSs :) +* src/ioctl.c: fixed ioctl_ReadTitleKey which wasn't working on Windows NT/2k/XP. +Because of this bug, the disc and key methods for key decryption where not working. + +------------------------------------------------------------------------ +r65 | sam | 2002-10-07 16:37:15 +0000 (Mon, 07 Oct 2002) | 5 lines +Changed paths: + M /trunk/configure.in + M /trunk/src/Makefile.am + M /trunk/src/config.h.in + + * ./src/Makefile.am: -no-undefined is now only used under BeOS because it + causes the Win32 compilation to fail. + * ./configure.in, src/Makefile.am: used AM_CONDITIONAL to conditionally + build the BSDi stuff. + +------------------------------------------------------------------------ +r64 | sam | 2002-08-10 21:27:42 +0000 (Sat, 10 Aug 2002) | 2 lines +Changed paths: + M /trunk/src/Makefile.am + + * Bumped the revision number... thanks Hï¿œkan :-) + +------------------------------------------------------------------------ +r63 | sam | 2002-08-10 21:19:55 +0000 (Sat, 10 Aug 2002) | 2 lines +Changed paths: + M /trunk/src/css.c + + * ./src/css.c: removed useless debug messages on Hï¿œkan's advice. + +------------------------------------------------------------------------ +r62 | sam | 2002-08-10 20:21:54 +0000 (Sat, 10 Aug 2002) | 2 lines +Changed paths: + M /trunk/AUTHORS + M /trunk/ChangeLog + M /trunk/debian/changelog + M /trunk/libdvdcss.spec + M /trunk/src/libdvdcss.c + + * Updated release-related files. + +------------------------------------------------------------------------ +r61 | sam | 2002-08-10 17:42:09 +0000 (Sat, 10 Aug 2002) | 3 lines +Changed paths: + M /trunk/src/device.c + M /trunk/src/device.h + M /trunk/src/ioctl.c + M /trunk/src/ioctl.h + + * ./src/ioctl.c: fixed ReportRPC for Win32. + * ./src/device.h: removed unneeded exported symbols. + +------------------------------------------------------------------------ +r60 | sam | 2002-08-10 14:27:26 +0000 (Sat, 10 Aug 2002) | 4 lines +Changed paths: + M /trunk/src/css.c + M /trunk/src/css.h + M /trunk/src/device.c + M /trunk/src/device.h + M /trunk/src/dvdcss/dvdcss.h + M /trunk/src/error.c + M /trunk/src/libdvdcss.c + M /trunk/src/libdvdcss.h + M /trunk/test/csstest.c + + * ./src/dvdcss/dvdcss.h: marked deprecated stuff. + * ./test/csstest.c: more documentation. + see http://www.videolan.org/libdvdcss/doc/ + +------------------------------------------------------------------------ +r59 | sam | 2002-08-10 12:56:04 +0000 (Sat, 10 Aug 2002) | 3 lines +Changed paths: + M /trunk/.cvsignore + M /trunk/Makefile.am + D /trunk/Makefile.in + D /trunk/aclocal.m4 + D /trunk/config.guess + D /trunk/config.sub + D /trunk/configure + M /trunk/configure.in + M /trunk/debian/.cvsignore + D /trunk/debian/Makefile.in + A /trunk/doc + A /trunk/doc/.cvsignore + A /trunk/doc/Makefile.am + A /trunk/doc/doxygen.cfg + A /trunk/doc/footer.html + A /trunk/doc/header.html + D /trunk/install-sh + D /trunk/ltmain.sh + D /trunk/missing + D /trunk/mkinstalldirs + M /trunk/src/.cvsignore + D /trunk/src/Makefile.in + M /trunk/src/dvdcss/.cvsignore + D /trunk/src/dvdcss/Makefile.in + M /trunk/src/libdvdcss.c + M /trunk/test/.cvsignore + D /trunk/test/Makefile.in + + * ALL: removed autotools files. + * ./doc/*: added doxygen files. + +------------------------------------------------------------------------ +r58 | sam | 2002-08-10 12:21:28 +0000 (Sat, 10 Aug 2002) | 2 lines +Changed paths: + M /trunk/src/dvdcss/dvdcss.h + M /trunk/src/libdvdcss.c + + * ./src/libdvdcss.c, ./src/dvdcss/dvdcss.h: documented the API. + +------------------------------------------------------------------------ +r57 | sam | 2002-08-09 22:03:34 +0000 (Fri, 09 Aug 2002) | 4 lines +Changed paths: + M /trunk/src/css.c + + * ./src/css.c: in case of a region mismatch and when the drive needs to + be reset, we read the first sector of the disc instead of closing and + reopening it. + +------------------------------------------------------------------------ +r56 | sam | 2002-08-09 14:19:46 +0000 (Fri, 09 Aug 2002) | 3 lines +Changed paths: + M /trunk/src/Makefile.am + M /trunk/src/Makefile.in + + * ./src/Makefile.am: tell libtool that libdvdcss does not have undefined + symbols. Fix for BeOS courtesy of Andrew Bachmann. + +------------------------------------------------------------------------ +r55 | sam | 2002-08-09 14:10:43 +0000 (Fri, 09 Aug 2002) | 23 lines +Changed paths: + M /trunk/Makefile.in + M /trunk/aclocal.m4 + M /trunk/configure + M /trunk/configure.in + M /trunk/debian/Makefile.in + M /trunk/src/Makefile.am + M /trunk/src/Makefile.in + M /trunk/src/bsdi_ioctl.c + M /trunk/src/common.h + M /trunk/src/config.h.in + M /trunk/src/css.c + M /trunk/src/css.h + A /trunk/src/device.c + A /trunk/src/device.h + M /trunk/src/dvdcss/Makefile.in + A /trunk/src/error.c + M /trunk/src/libdvdcss.c + M /trunk/src/libdvdcss.h + M /trunk/test/Makefile.in + M /trunk/test/csstest.c + + * ./src/css.c: when the ReadTitleKey ioctl failed, reopen the device before + falling back to the title method. + + Note: on my drive, this fixes the "ioctl_ReadTitleKey failed" error + many users have been reporting. Please test! + + Note 2: I could not find any other way to reset the drive after a failed + ReadTitleKey ioctl than closing and opening the device again. If + I don't do that, read() fails with an Input/output error after a + while (but not immediately). + + * ALL: libdvdcss builds with -ansi -pedantic. Yeah I like that :-) + * ./src/css.c: renamed a few functions so that they make more sense, added + debug messages here and there, fixed typos and speling. + * ./src/error.c: moved _dvdcss_error and _dvdcss_debug here. + * ./src/device.c: moved device reading functions from libdvdcss.c to here. + * ./src/device.c: errors from dvdcss_read are now properly handled; partial + reads still aren't though. + * ./src/libdvdcss.c: default verbosity is now 0, a library should not be + intrusive by default. + * ./test/csstest.c: additional error check. + * ./configure.in: removed the crap boolean_t detection. + +------------------------------------------------------------------------ +r54 | massiot | 2002-07-23 11:43:58 +0000 (Tue, 23 Jul 2002) | 2 lines +Changed paths: + M /trunk/README + +Default method is now "key" :p. + +------------------------------------------------------------------------ +r53 | sam | 2002-07-16 22:47:40 +0000 (Tue, 16 Jul 2002) | 4 lines +Changed paths: + M /trunk/ChangeLog + M /trunk/Makefile.in + M /trunk/aclocal.m4 + M /trunk/config.guess + M /trunk/config.sub + M /trunk/configure + M /trunk/configure.in + M /trunk/debian/Makefile.in + M /trunk/debian/changelog + M /trunk/libdvdcss.spec + M /trunk/ltmain.sh + M /trunk/src/Makefile.in + M /trunk/src/css.c + M /trunk/src/css.h + M /trunk/src/dvdcss/Makefile.in + M /trunk/src/libdvdcss.c + M /trunk/test/Makefile.am + M /trunk/test/Makefile.in + + * ./test/Makefile.am: disabled dvd_region. + * ./src/css.c: speling fixes. + * ALL: re-ran bootstrap with more recent autotools. + +------------------------------------------------------------------------ +r52 | hjort | 2002-07-14 11:44:57 +0000 (Sun, 14 Jul 2002) | 3 lines +Changed paths: + A /trunk/test/dvd_region.c + +New utility for querying (and eventualy setting) the region of a DVD drive +using the ioctl wrappers in libdvdcss. + +------------------------------------------------------------------------ +r51 | hjort | 2002-07-12 23:28:42 +0000 (Fri, 12 Jul 2002) | 3 lines +Changed paths: + M /trunk/configure.in + M /trunk/src/bsdi_ioctl.c + +Include config.h before testing defines in the BSDi ioctl code. Add a bug +fix from the author. Remove the now unused parts from configure.in. + +------------------------------------------------------------------------ +r50 | hjort | 2002-07-12 21:06:41 +0000 (Fri, 12 Jul 2002) | 3 lines +Changed paths: + M /trunk/src/Makefile.am + M /trunk/src/bsdi_ioctl.c + M /trunk/test/Makefile.am + +Fix so that the bsdi_*.[hc] files make it into the dist tar-ball. +Correct the include path for the programs in test/. + +------------------------------------------------------------------------ +r49 | hjort | 2002-07-01 13:40:33 +0000 (Mon, 01 Jul 2002) | 3 lines +Changed paths: + M /trunk/src/libdvdcss.c + +Typo fix and fix the linked list code to not drop the list when instering +at the head, from Adam Jones. + +------------------------------------------------------------------------ +r48 | hjort | 2002-07-01 10:36:37 +0000 (Mon, 01 Jul 2002) | 2 lines +Changed paths: + M /trunk/src/ioctl.c + M /trunk/src/ioctl.h + +Patch for OS/2 from Alex Strelnikov. + +------------------------------------------------------------------------ +r47 | hjort | 2002-07-01 09:59:09 +0000 (Mon, 01 Jul 2002) | 2 lines +Changed paths: + M /trunk/src/css.c + +Typo fix from Adam Jones. + +------------------------------------------------------------------------ +r46 | hjort | 2002-07-01 09:02:25 +0000 (Mon, 01 Jul 2002) | 2 lines +Changed paths: + M /trunk/src/ioctl.c + M /trunk/src/ioctl.h + +Getting ReportRPC for WIN32 a bit closer to working. + +------------------------------------------------------------------------ +r45 | sam | 2002-06-04 07:10:07 +0000 (Tue, 04 Jun 2002) | 2 lines +Changed paths: + M /trunk/ChangeLog + M /trunk/src/ioctl.c + + * ./src/ioctl.c: implemented ioctl_ReportKey1 for HP-UX. + +------------------------------------------------------------------------ +r44 | sam | 2002-06-04 07:02:57 +0000 (Tue, 04 Jun 2002) | 2 lines +Changed paths: + M /trunk/ChangeLog + M /trunk/src/libdvdcss.c + + * ./src/libdvdcss.c: Win32 compilation fix. + +------------------------------------------------------------------------ +r43 | sam | 2002-06-02 16:18:45 +0000 (Sun, 02 Jun 2002) | 2 lines +Changed paths: + M /trunk/ChangeLog + M /trunk/configure + M /trunk/configure.in + M /trunk/debian/changelog + M /trunk/libdvdcss.spec + + * ALL: changed version number to 1.2.1. + +------------------------------------------------------------------------ +r42 | sam | 2002-06-02 16:14:48 +0000 (Sun, 02 Jun 2002) | 2 lines +Changed paths: + M /trunk/AUTHORS + M /trunk/ChangeLog + M /trunk/src/ioctl.c + M /trunk/src/ioctl.h + + * ./src/ioctl.c, ./src/ioctl.h: QNX port, courtesy of Pascal Levesque. + +------------------------------------------------------------------------ +r41 | sam | 2002-06-02 16:05:34 +0000 (Sun, 02 Jun 2002) | 2 lines +Changed paths: + M /trunk/ChangeLog + M /trunk/src/css.c + + * ./src/css.c: applied Hï¿œkan's fix for the failure on region mismatch. + +------------------------------------------------------------------------ +r40 | sam | 2002-06-02 15:54:10 +0000 (Sun, 02 Jun 2002) | 3 lines +Changed paths: + M /trunk/.cvsignore + M /trunk/ChangeLog + M /trunk/aclocal.m4 + M /trunk/configure + M /trunk/libdvdcss.spec + M /trunk/ltmain.sh + M /trunk/src/libdvdcss.c + + * ALL: switched to libtool 1.4.2a. + * ./src/libdvdcss.c: fixed an uninitialized variable. + +------------------------------------------------------------------------ +r39 | sam | 2002-05-26 14:22:23 +0000 (Sun, 26 May 2002) | 2 lines +Changed paths: + M /trunk/src/dvdcss/dvdcss.h + + * ./src/dvdcss/dvdcss.h: C++ compliant public header. + +------------------------------------------------------------------------ +r38 | sam | 2002-05-20 17:58:20 +0000 (Mon, 20 May 2002) | 4 lines +Changed paths: + M /trunk/ChangeLog + M /trunk/configure + M /trunk/configure.in + M /trunk/debian/changelog + M /trunk/libdvdcss.spec + D /trunk/libtool + + * Everything should be ready for 1.2.0. + * Updated ChangeLog. + * Removed libtool. It seems to be created automatically anyway. + +------------------------------------------------------------------------ +r37 | hjort | 2002-05-16 20:40:54 +0000 (Thu, 16 May 2002) | 4 lines +Changed paths: + M /trunk/src/libdvdcss.c + +New function _dvdcss_use_ioctls. Avoid using the ioctl calls when +they have no chans or working, this in turn avoids a spurious warning +when they fail. + +------------------------------------------------------------------------ +r36 | hjort | 2002-05-16 20:12:04 +0000 (Thu, 16 May 2002) | 2 lines +Changed paths: + M /trunk/src/css.c + +Update error message. + +------------------------------------------------------------------------ +r35 | hjort | 2002-05-16 12:10:29 +0000 (Thu, 16 May 2002) | 2 lines +Changed paths: + M /trunk/src/libdvdcss.c + +Default to 'key', rather than 'title', method. + +------------------------------------------------------------------------ +r34 | sam | 2002-05-15 20:27:04 +0000 (Wed, 15 May 2002) | 2 lines +Changed paths: + M /trunk/libdvdcss.spec + + * ./libdvdcss.spec: enhancements by Mandrakesoft. + +------------------------------------------------------------------------ +r33 | hjort | 2002-05-13 21:22:22 +0000 (Mon, 13 May 2002) | 3 lines +Changed paths: + M /trunk/src/libdvdcss.c + +Correct serious bug in dvdcss_read for titles with all zero key (a unencrypted +title on a CSS protected disc). + +------------------------------------------------------------------------ +r32 | jlj | 2002-05-05 22:21:51 +0000 (Sun, 05 May 2002) | 3 lines +Changed paths: + M /trunk/src/ioctl.c + M /trunk/src/ioctl.h + + * ./src/ioctl.[ch]: Darwin changes: Cleaned up the code, fixed + ReadTitleKey, and implemented ReportRPC. + +------------------------------------------------------------------------ +r31 | gbazin | 2002-04-26 20:47:08 +0000 (Fri, 26 Apr 2002) | 4 lines +Changed paths: + M /trunk/INSTALL + + + +* updated win32 compilation instructions. + +------------------------------------------------------------------------ +r30 | sam | 2002-04-06 01:27:43 +0000 (Sat, 06 Apr 2002) | 3 lines +Changed paths: + M /trunk/ChangeLog + M /trunk/configure + M /trunk/configure.in + M /trunk/debian/changelog + M /trunk/libdvdcss.spec + + + * libdvdcss-1.1.1 release. + +------------------------------------------------------------------------ +r29 | sam | 2002-04-06 01:11:05 +0000 (Sat, 06 Apr 2002) | 3 lines +Changed paths: + M /trunk/ChangeLog + M /trunk/src/ioctl.c + + + * ./src/ioctl.c: OpenBSD compile fix. Thanks to ex0dus on #videolan. + +------------------------------------------------------------------------ +r28 | gbazin | 2002-04-05 00:26:25 +0000 (Fri, 05 Apr 2002) | 5 lines +Changed paths: + M /trunk/INSTALL + M /trunk/src/css.c + + + +* updated INSTALL doc for the win32 build. +* added small win32 specific error message that was also in the vlc tree. + +------------------------------------------------------------------------ +r27 | gbazin | 2002-04-04 23:44:20 +0000 (Thu, 04 Apr 2002) | 10 lines +Changed paths: + M /trunk/src/ioctl.c + M /trunk/src/libdvdcss.c + + + +* added two patches that have been forgot from the vlc tree. + + 1- Under NT/2K/XP try to open the dvd device in read only mode if we don't + have right access. With only read access we can't use ioctls but if the + disc has already been authenticated, then we can decrypt it with the + TITLE method. + 2- Small compilation fix for msvc. + +------------------------------------------------------------------------ +r26 | sam | 2002-04-04 14:21:25 +0000 (Thu, 04 Apr 2002) | 3 lines +Changed paths: + M /trunk/ChangeLog + M /trunk/src/libdvdcss.h + + + * ./src/libdvdcss.h: IRIX compile fix by Michael Pruett <michael@68k.org>. + +------------------------------------------------------------------------ +r25 | sam | 2002-04-04 01:26:54 +0000 (Thu, 04 Apr 2002) | 4 lines +Changed paths: + M /trunk/ChangeLog + M /trunk/configure + M /trunk/configure.in + M /trunk/src/config.h.in + M /trunk/src/ioctl.c + + + * ./configure.in: BeOS bug fix. I'm so lame. + * ./src/ioctl.c: refuse to build if DVD ioctls weren't found. + +------------------------------------------------------------------------ +r24 | sam | 2002-04-03 23:34:30 +0000 (Wed, 03 Apr 2002) | 3 lines +Changed paths: + M /trunk/test/.cvsignore + + + * Forgot to change test/.cvsignore ... + +------------------------------------------------------------------------ +r23 | sam | 2002-04-03 23:33:57 +0000 (Wed, 03 Apr 2002) | 6 lines +Changed paths: + M /trunk/ChangeLog + M /trunk/test/Makefile.am + M /trunk/test/Makefile.in + A /trunk/test/csstest.c + D /trunk/test/test.c + + + * ./test/csstest.c: renamed test.c to csstest.c. + + I hereby declare libdvdcss 1.1.0 ready to ship; it was successfully tested + on Linux, FreeBSD, MacOS X and BeOS, and compiles on Solaris. + +------------------------------------------------------------------------ +r22 | jlj | 2002-04-03 23:02:20 +0000 (Wed, 03 Apr 2002) | 3 lines +Changed paths: + M /trunk/src/ioctl.c + + + * ./src/ioctl.c: Fixed a Darwin typo I recently introduced. + +------------------------------------------------------------------------ +r21 | sam | 2002-04-03 22:31:42 +0000 (Wed, 03 Apr 2002) | 3 lines +Changed paths: + M /trunk/ChangeLog + M /trunk/Makefile.in + M /trunk/configure + M /trunk/debian/Makefile.in + M /trunk/src/Makefile.in + M /trunk/src/dvdcss/Makefile.in + M /trunk/test/Makefile.in + + + * Run ./bootstrap. + +------------------------------------------------------------------------ +r20 | jlj | 2002-04-03 22:17:00 +0000 (Wed, 03 Apr 2002) | 3 lines +Changed paths: + M /trunk/configure.in + + + * ./configure.in: Darwin compile fix (added -no-cpp-precomp) + +------------------------------------------------------------------------ +r19 | sam | 2002-04-03 21:31:52 +0000 (Wed, 03 Apr 2002) | 5 lines +Changed paths: + M /trunk/ChangeLog + M /trunk/configure + M /trunk/debian/changelog + M /trunk/libdvdcss.spec + M /trunk/missing + + + * ./ChangeLog: everything should be ready for the 1.1.0 release. + * ./libdvdcss.spec: updated specfile for RPM generation. + * ./missing: commited libtool's latest version of this file. + +------------------------------------------------------------------------ +r18 | jlj | 2002-04-03 21:25:13 +0000 (Wed, 03 Apr 2002) | 3 lines +Changed paths: + M /trunk/configure.in + M /trunk/src/config.h.in + M /trunk/src/ioctl.c + + + * Fixed a Darwin define problem. + +------------------------------------------------------------------------ +r17 | sam | 2002-04-03 15:19:22 +0000 (Wed, 03 Apr 2002) | 5 lines +Changed paths: + M /trunk/ChangeLog + M /trunk/Makefile.am + M /trunk/config.guess + M /trunk/config.sub + M /trunk/configure + M /trunk/configure.in + M /trunk/src/Makefile.am + M /trunk/src/Makefile.in + M /trunk/src/css.c + A /trunk/src/dvdcss + A /trunk/src/dvdcss/.cvsignore + A /trunk/src/dvdcss/Makefile.am + A /trunk/src/dvdcss/Makefile.in + A /trunk/src/dvdcss/dvdcss.h + D /trunk/src/dvdcss.h + M /trunk/src/libdvdcss.c + M /trunk/test/Makefile.am + M /trunk/test/Makefile.in + M /trunk/test/test.c + + + * ./src/dvdcss/dvdcss.h: moved dvdcss.h in a subdirectory so that we can + include <dvdcss/dvdcss.h> without having to make install. + * ./test/test.c: removed #ifdef DVDCSS_DIST. + +------------------------------------------------------------------------ +r16 | sam | 2002-04-03 06:12:50 +0000 (Wed, 03 Apr 2002) | 9 lines +Changed paths: + M /trunk/AUTHORS + M /trunk/ChangeLog + M /trunk/Makefile.am + M /trunk/Makefile.in + M /trunk/configure + M /trunk/configure.in + M /trunk/debian/.cvsignore + A /trunk/debian/Makefile.am + A /trunk/debian/Makefile.in + M /trunk/debian/changelog + M /trunk/debian/rules + M /trunk/libtool + M /trunk/src/Makefile.am + M /trunk/src/Makefile.in + M /trunk/src/config.h.in + M /trunk/src/css.c + M /trunk/src/dvdcss.h + M /trunk/src/libdvdcss.c + M /trunk/test/Makefile.in + M /trunk/test/test.c + + + * ./ChangeLog: updated changelog. + * ./Makefile.am: added the debian dir to the targets. + * ./configure.in: switched to a more conventional versioning scheme. + * ./src/css.c: removed a useless #ifdef. + * ./src/dvdcss.h: added a versioned symbol to the API. + * ./src/Makefile.am: use <dvdcss/dvdcss.h> instead of <videolan/dvdcss.h>. + * ./test/test.c: test program is now up to date. + +------------------------------------------------------------------------ +r15 | hjort | 2002-03-09 17:57:53 +0000 (Sat, 09 Mar 2002) | 7 lines +Changed paths: + M /trunk/src/css.c + M /trunk/src/css.h + M /trunk/src/libdvdcss.c + +Split the code into more functions. The disc and title decryption / +cracking code is now each in it's own function. Also moved the code that +looks for a weak block in the VOB to crack the title key from out from +the loop that reads them. Added another crack method, it's disabled for +now though. Lowered some limits on the current 'weak' test. Added more +comments. + +------------------------------------------------------------------------ +r14 | hjort | 2002-03-09 17:35:49 +0000 (Sat, 09 Mar 2002) | 3 lines +Changed paths: + M /trunk/configure.in + +Add -D_FILE_OFFSET_BITS=64 to the compile line to make off_t / lseek and +other file access functions used in dvdcss be 64bit. + +------------------------------------------------------------------------ +r13 | hjort | 2002-03-09 17:24:28 +0000 (Sat, 09 Mar 2002) | 2 lines +Changed paths: + M /trunk/test/test.c + +Tell libdvdcss to get the key for the block before we decrypt it. + +------------------------------------------------------------------------ +r12 | hjort | 2002-03-09 17:23:05 +0000 (Sat, 09 Mar 2002) | 2 lines +Changed paths: + M /trunk/test/Makefile.am + +Don't link to libdl. + +------------------------------------------------------------------------ +r11 | sam | 2002-03-09 17:16:44 +0000 (Sat, 09 Mar 2002) | 3 lines +Changed paths: + M /trunk/configure + M /trunk/configure.in + M /trunk/test/test.c + + + * Fixed compilation of test/test.c. + +------------------------------------------------------------------------ +r10 | sam | 2002-03-06 00:06:17 +0000 (Wed, 06 Mar 2002) | 3 lines +Changed paths: + M /trunk/test/.cvsignore + A /trunk/test/test.c + + + * Updated misc control files and added the sample program. + +------------------------------------------------------------------------ +r9 | sam | 2002-03-06 00:04:41 +0000 (Wed, 06 Mar 2002) | 2 lines +Changed paths: + M /trunk/Makefile.am + M /trunk/Makefile.in + M /trunk/aclocal.m4 + M /trunk/config.guess + M /trunk/config.sub + M /trunk/configure + M /trunk/configure.in + M /trunk/debian/changelog + D /trunk/debian/libdvdcss2.shlibs + M /trunk/libtool + M /trunk/src/Makefile.am + M /trunk/src/Makefile.in + M /trunk/src/config.h.in + M /trunk/test/Makefile.am + M /trunk/test/Makefile.in + +*** empty log message *** + +------------------------------------------------------------------------ +r8 | hjort | 2002-02-25 18:21:57 +0000 (Mon, 25 Feb 2002) | 2 lines +Changed paths: + M /trunk/src/css.c + M /trunk/src/css.h + +Cleanup some formating, indentation and types and add a small comment. + +------------------------------------------------------------------------ +r7 | hjort | 2002-02-03 14:54:53 +0000 (Sun, 03 Feb 2002) | 2 lines +Changed paths: + M /trunk/src/ioctl.c + M /trunk/src/ioctl.h + +Add the WIN32 fix to GetTitleKey from the vlc/extra branch. + +------------------------------------------------------------------------ +r6 | hjort | 2002-02-03 14:53:10 +0000 (Sun, 03 Feb 2002) | 2 lines +Changed paths: + M /trunk/configure.in + +Do check for the unistd.h header file. + +------------------------------------------------------------------------ +r5 | hjort | 2002-01-20 17:04:54 +0000 (Sun, 20 Jan 2002) | 7 lines +Changed paths: + M /trunk/src/css.c + M /trunk/src/css.h + +Make CSSAuth more rubust, should now also work with drives that are not 100% +compliant to the SFF-8090 standard. AGID invalidation should now work, +allowing us to recover from hung / failed authentications. Corrected +CSSGetASF, it does not take an AGID argument. Move several data structures +from the dvdcss handle to local variables in CSSAuth. Remove CSSAuth as a +externaly visible function in css.c. + +------------------------------------------------------------------------ +r4 | sam | 2001-12-22 00:52:46 +0000 (Sat, 22 Dec 2001) | 3 lines +Changed paths: + M /trunk/configure + M /trunk/configure.in + M /trunk/libtool + A /trunk/src/.cvsignore + M /trunk/src/config.h.in + M /trunk/src/libdvdcss.c + + + * Win32 compilation fix. + +------------------------------------------------------------------------ +r3 | sam | 2001-12-22 00:26:17 +0000 (Sat, 22 Dec 2001) | 3 lines +Changed paths: + M /trunk/configure + M /trunk/configure.in + M /trunk/src/config.h.in + + + * Attempt at fixing the Solaris port. + +------------------------------------------------------------------------ +r2 | sam | 2001-12-22 00:10:31 +0000 (Sat, 22 Dec 2001) | 3 lines +Changed paths: + M /trunk/.cvsignore + A /trunk/Makefile.in + M /trunk/configure + M /trunk/configure.in + A /trunk/src/Makefile.in + M /trunk/test/.cvsignore + A /trunk/test/Makefile.in + + + * Forgot Makefile.in files. + +------------------------------------------------------------------------ +r1 | sam | 2001-12-22 00:08:13 +0000 (Sat, 22 Dec 2001) | 3 lines +Changed paths: + A /trunk + A /trunk/.cvsignore + A /trunk/AUTHORS + A /trunk/COPYING + A /trunk/ChangeLog + A /trunk/INSTALL + A /trunk/Makefile.am + A /trunk/NEWS + A /trunk/README + A /trunk/aclocal.m4 + A /trunk/bootstrap + A /trunk/config.guess + A /trunk/config.sub + A /trunk/configure + A /trunk/configure.in + A /trunk/debian + A /trunk/debian/.cvsignore + A /trunk/debian/changelog + A /trunk/debian/control + A /trunk/debian/libdvdcss2-dev.dirs + A /trunk/debian/libdvdcss2.copyright + A /trunk/debian/libdvdcss2.dirs + A /trunk/debian/libdvdcss2.shlibs + A /trunk/debian/rules + A /trunk/install-sh + A /trunk/libdvdcss.spec + A /trunk/libtool + A /trunk/ltmain.sh + A /trunk/missing + A /trunk/mkinstalldirs + A /trunk/src + A /trunk/src/Makefile.am + A /trunk/src/bsdi_dvd.h + A /trunk/src/bsdi_ioctl.c + A /trunk/src/common.h + A /trunk/src/config.h.in + A /trunk/src/css.c + A /trunk/src/css.h + A /trunk/src/csstables.h + A /trunk/src/dvdcss.h + A /trunk/src/ioctl.c + A /trunk/src/ioctl.h + A /trunk/src/libdvdcss.c + A /trunk/src/libdvdcss.h + A /trunk/test + A /trunk/test/.cvsignore + A /trunk/test/Makefile.am + + + * Initial commit. Hope it'll work. + +------------------------------------------------------------------------ diff --git a/lib/libdvd/libdvdcss/INSTALL b/lib/libdvd/libdvdcss/INSTALL new file mode 100644 index 0000000000..254758f753 --- /dev/null +++ b/lib/libdvd/libdvdcss/INSTALL @@ -0,0 +1,77 @@ +INSTALL file for libdvdcss, a DVD access library + + +Configuring libdvdcss +===================== + +A typical way to configure libdvdcss is: + + ./configure --prefix=/usr + +See `./configure --help' for more information. + +Building libdvdcss +================== + +Once configured, run `make' to build libdvdcss. + +If you have player keys, you need to put them in the file csskeys.h, before +configuring libdvdcss to enable the "key" method (the one from libcss). + + +Installing libdvdcss +==================== + +You can install libdvdcss by typing: + + make install + + +Building libdvdcss for Win32 +============================ + +You have two alternatives to build libdvdcss for Win32: + +- natively on Windows, using MSYS + MINGW (www.mingw.org): + + (MSYS is a minimal build environnement to compile unixish projects under + windoze. It provides all the common unix tools like sh, gmake...) + + You will need to download and install the latest MSYS (version 1.0.7 as + of now) and MINGW. + The installation is really easy. Begin with the MSYS auto-installer and once + this is done, extract MINGW into c:\msys\1.0\mingw. You also have to remember + to remove the make utility included with MINGW as it conflicts with the one + from MSYS (just rename or remove c:\msys\1.0\mingw\bin\make.exe). + + http://www.mingw.org/download.shtml + http://prdownloads.sourceforge.net/mingw/MSYS-1.0.7-i686-2002.04.24-1.exe + http://prdownloads.sourceforge.net/mingw/MinGW-1.1.tar.gz + + To build libdvdcss you just have to run the following commands: + ./configure + make + +- or on Linux, using the mingw32 cross-compiler: + + You can find a mingw32 cross-compiler on the videolan web site: + http://www.videolan.org/vlc/windows.html + Or if you are running Debian, there is a mingw32 package you can use. + + If you are cross-compiling from the Debian package, you can use the following + commands: + + ./configure --host=i586-mingw32msvc --target=i586-mingw32msvc \ + --build=i386-linux + + make + + If you are cross-compiling using the mingw32 package provided by + www.videolan.org, you have to use something along those lines: + + CC=/usr/local/cross-tools/bin/i586-mingw32msvc-gcc \ + PATH=/usr/local/cross-tools/bin:$PATH \ + ./configure --host=i586-mingw32msvc --target=i586-mingw32msvc \ + --build=i386-linux + + PATH=/usr/local/cross-tools/bin:$PATH make diff --git a/lib/libdvd/libdvdcss/Makefile.am b/lib/libdvd/libdvdcss/Makefile.am new file mode 100644 index 0000000000..bc8b81d6d9 --- /dev/null +++ b/lib/libdvd/libdvdcss/Makefile.am @@ -0,0 +1,12 @@ +SUBDIRS = src test doc +DIST_SUBDIRS = $(SUBDIRS) + +EXTRA_DIST = libdvdcss.spec bootstrap + +AUTOMAKE_OPTIONS = foreign dist-bzip2 subdir-objects + +doc-dummy: + +doc: doc-dummy + $(MAKE) -C doc doc + diff --git a/lib/libdvd/libdvdcss/NEWS b/lib/libdvd/libdvdcss/NEWS new file mode 100644 index 0000000000..87df99944e --- /dev/null +++ b/lib/libdvd/libdvdcss/NEWS @@ -0,0 +1,112 @@ +$Id$ + +Changes between 1.2.9 and 1.2.10: +--------------------------------- + + * DVD drive autodetection. + * new dvdcss_is_scrambled() function. + * various failure recovery improvements. + * accept "X:\" as a device name, as well as "X:". + * various bug fixes. + +Changes between 1.2.8 and 1.2.9: +-------------------------------- + + * more robust key caching + * support for cache directory tags + * improved seeking on win32 + * support for Solaris libsmedia library + +Changes between 1.2.7 and 1.2.8: +-------------------------------- + + * win32 fix for encrypted DVDs. + * workaround for strange discs that report read errors seemingly at random. + +Changes between 1.2.6 and 1.2.7: +-------------------------------- + + * activated key caching by default. + * fix for collisions between cached keys. + * packaging improvements for Debian. + * packaging improvements for RPM-based distributions. + +Changes between 1.2.5 and 1.2.6: +-------------------------------- + + * compilation fix for most UNIXes + +Changes between 1.2.4 and 1.2.5: +-------------------------------- + + * key cache support + * improved robustness in case of read errors + * now builds under Cygwin + * now builds under Microsoft Visual C++ + +Changes between 1.2.3 and 1.2.4: +-------------------------------- + + * administrator rights are no longer required under Windows NT/2000/XP + +Changes between 1.2.2 and 1.2.3: +-------------------------------- + + * many Windows bugfixes + * workaround for drives which prevent key decryption + +Changes between 1.2.1 and 1.2.2: +-------------------------------- + + * fix for the "ioctl_ReadTitleKey failed" bug on RPC2 drives + * better error checking + * improved documentation + * OS/2 port + +Changes between 1.2.0 and 1.2.1: +-------------------------------- + + * fix for discs with a mismatched region + * QNX port + +Changes between 1.1.1 and 1.2.0: +-------------------------------- + + * fix for a crash when an unencrypted sector is found on a scrambled disc + * stability enhancements + +Changes between 1.1.0 and 1.1.1: +-------------------------------- + + * compilation fixes for BeOS, IRIX, OpenBSD + +Changes between 1.0.0 and 1.1.0: +-------------------------------- + + * merged all patches from the Ogle group + * lots of bugfixes + * HP-UX port + * better error recovery + * third descrambling implementation + +Changes between 0.0.3 and 1.0.0: +-------------------------------- + + * stable API + * OpenBSD port + * NetBSD port + * Mac OS X port + +Changes between 0.0.2 and 0.0.3: +-------------------------------- + + * fix to access the whole device under Win32 + * BSD/OS port + * Solaris port + +Changes between 0.0.1 and 0.0.2: +-------------------------------- + + * internal key cache mechanism + * stability fixes + diff --git a/lib/libdvd/libdvdcss/README b/lib/libdvd/libdvdcss/README new file mode 100644 index 0000000000..5b63385e7b --- /dev/null +++ b/lib/libdvd/libdvdcss/README @@ -0,0 +1,71 @@ +README for libdvdcss, a portable abstraction library for DVD decryption +$Id$ + + +Introduction +============ + +libdvdcss is part of the VideoLAN project, a full MPEG2 client/server +solution. The VideoLAN Client can also be used as a standalone program +to play MPEG2 streams from a hard disk or a DVD. + + +Building and Installing libdvdcss +================================= + +See the INSTALL or INSTALL.libdvdcss file for this. + +Running lidvdcss +================ + +The behaviourof the library can be affected by changing two environment +variables: + DVDCSS_METHOD={title|disc|key}: method for key decryption + title: decrypted title key is guessed from the encrypted sectors of + the stream. Thus it should work with a file as well as the + DVD device. But it sometimes takes much time to decrypt a title + key and may even fail. With this method, the key is only checked + at the beginning of each title, so it won't work if the key + changes in the middle of a title. + disc: the disc key is first cracked ; then all title keys can be + decrypted instantly, which allows us to check them often, + key: the same as "disc" if you don't have a file with player keys at + compilation time. If you do, the decryption of the disc key + will be faster with this method. It is the one that was used by + libcss. + This is the default method, + DVDCSS_VERBOSE={0|1|2}: libdvdcss verbosity + 0: no error messages, no debug messages (this is the default) + 1: only error messages + 2: error and debug messages + + +Troubleshooting +=============== + +A mailing-list has been set up for support and discussion about +libdvdcss. Its address is : + + <libdvdcss@videolan.org> + +To subscribe, send a mail to <listar@videolan.org> with the following +words in the mail body : + + subscribe libdvdcss + +To unsubscribe, do the same with the words : + + unsubscribe libdvdcss + + +When reporting bugs, try to be as precise as possible (which OS, which +distribution, what plugins you were trying, and so on). + + +Resources +========= + +The VideoLAN web site at http://www.videolan.org/ is a good start for +information about MPEG and DVD playing. Have a look at the documentation +section, as well as the bookmarks. + diff --git a/lib/libdvd/libdvdcss/bootstrap b/lib/libdvd/libdvdcss/bootstrap new file mode 100755 index 0000000000..434d6e3fca --- /dev/null +++ b/lib/libdvd/libdvdcss/bootstrap @@ -0,0 +1,132 @@ +#! /bin/sh +# $Id: bootstrap 2005 2008-07-16 20:51:50Z sam $ + +# bootstrap: generic bootstrap/autogen.sh script for autotools projects +# +# Copyright (c) 2002-2008 Sam Hocevar <sam@zoy.org> +# +# This program is free software. It comes without any warranty, to +# the extent permitted by applicable law. You can redistribute it +# and/or modify it under the terms of the Do What The Fuck You Want +# To Public License, Version 2, as published by Sam Hocevar. See +# http://sam.zoy.org/wtfpl/COPYING for more details. +# +# The latest version of this script can be found at the following place: +# http://sam.zoy.org/autotools/ + +# Die if an error occurs +set -e + +# Guess whether we are using configure.ac or configure.in +if test -f configure.ac; then + conffile="configure.ac" +elif test -f configure.in; then + conffile="configure.in" +else + echo "$0: could not find configure.ac or configure.in" + exit 1 +fi + +# Check for needed features +auxdir="`sed -ne 's/^[ \t]*A._CONFIG_AUX_DIR *([[ ]*\([^] )]*\).*/\1/p' $conffile`" +libtool="`grep '^[ \t]*A._PROG_LIBTOOL' $conffile >/dev/null 2>&1 && echo yes || echo no`" +header="`grep '^[ \t]*A._CONFIG_HEADER' $conffile >/dev/null 2>&1 && echo yes || echo no`" +makefile="`[ -f Makefile.am ] && echo yes || echo no`" +aclocalflags="`sed -ne 's/^[ \t]*ACLOCAL_AMFLAGS[ \t]*=//p' Makefile.am 2>/dev/null || :`" + +# Check for automake +amvers="no" +for v in 11 10 9 8 7 6 5; do + if automake-1.${v} --version >/dev/null 2>&1; then + amvers="-1.${v}" + break + elif automake1.${v} --version >/dev/null 2>&1; then + amvers="1.${v}" + break + fi +done + +if test "${amvers}" = "no" && automake --version > /dev/null 2>&1; then + amvers="`automake --version | sed -e '1s/[^0-9]*//' -e q`" + if expr "$amvers" "<" "1.5" > /dev/null 2>&1; then + amvers="no" + else + amvers="" + fi +fi + +if test "$amvers" = "no"; then + echo "$0: you need automake version 1.5 or later" + exit 1 +fi + +# Check for autoconf +acvers="no" +for v in "" "259" "253"; do + if autoconf${v} --version >/dev/null 2>&1; then + acvers="${v}" + break + fi +done + +if test "$acvers" = "no"; then + echo "$0: you need autoconf" + exit 1 +fi + +# Check for libtool +if test "$libtool" = "yes"; then + libtoolize="no" + if glibtoolize --version >/dev/null 2>&1; then + libtoolize="glibtoolize" + else + for v in "16" "15" "" "14"; do + if libtoolize${v} --version >/dev/null 2>&1; then + libtoolize="libtoolize${v}" + break + fi + done + fi + + if test "$libtoolize" = "no"; then + echo "$0: you need libtool" + exit 1 + fi +fi + +# Remove old cruft +for x in aclocal.m4 configure config.guess config.log config.sub config.cache config.h.in config.h compile libtool.m4 ltoptions.m4 ltsugar.m4 ltversion.m4 ltmain.sh libtool ltconfig missing mkinstalldirs depcomp install-sh; do rm -f $x autotools/$x; if test -n "$auxdir"; then rm -f "$auxdir/$x"; fi; done +rm -Rf autom4te.cache +if test -n "$auxdir"; then + if test ! -d "$auxdir"; then + mkdir "$auxdir" + fi + aclocalflags="${aclocalflags} -I $auxdir -I ." +fi + +# Explain what we are doing from now +set -x + +# Bootstrap package +if test "$libtool" = "yes"; then + ${libtoolize} --copy --force + if test -n "$auxdir" -a ! "$auxdir" = "." -a -f "ltmain.sh"; then + echo "$0: working around a minor libtool issue" + mv ltmain.sh "$auxdir/" + fi +fi + +aclocal${amvers} ${aclocalflags} +autoconf${acvers} +if test "$header" = "yes"; then + autoheader${acvers} +fi +if test "$makefile" = "yes"; then + #add --include-deps if you want to bootstrap with any other compiler than gcc + #automake${amvers} --add-missing --copy --include-deps + automake${amvers} --foreign --add-missing --copy +fi + +# Remove cruft that we no longer want +rm -Rf autom4te.cache + diff --git a/lib/libdvd/libdvdcss/configure.ac b/lib/libdvd/libdvdcss/configure.ac new file mode 100644 index 0000000000..1b9ff8b7b7 --- /dev/null +++ b/lib/libdvd/libdvdcss/configure.ac @@ -0,0 +1,215 @@ +AC_INIT(src/libdvdcss.c) + +AC_PREREQ(2.50) +AC_CONFIG_AUX_DIR(.auto) +AC_CANONICAL_SYSTEM + +AM_INIT_AUTOMAKE(libdvdcss, 1.2.10) +AM_CONFIG_HEADER(config.h) + +AC_PROG_CC +AC_STDC_HEADERS + +AC_LIBTOOL_WIN32_DLL +AM_PROG_LIBTOOL + +AC_C_CONST +AC_C_INLINE +AC_TYPE_SIZE_T + +AC_CHECK_HEADERS(unistd.h sys/param.h limits.h pwd.h errno.h) + +dnl +dnl Check the operating system +dnl +case x"${target_os}" in + xdarwin*) + CFLAGS="${CFLAGS} -no-cpp-precomp" + ;; + x*cygwin*) + dnl Check if we are using the mno-cygwin mode in which case we are + dnl actually dealing with a mingw32 compiler. + AC_EGREP_CPP(yes, [#ifndef WIN32 + yes + #endif], + AC_DEFINE(SYS_CYGWIN, 1, Have a Cygwin system.)) + AC_DEFINE(WIN32, 1, Using Win32.) + ;; + xbeos*) + AC_DEFINE(SYS_BEOS, 1, Have a BeOS system.) + ;; + x*msvc*) + SYS_MSVC=1 + ;; + x*) + ;; +esac + +dnl +dnl libdvdcss: check for DVD ioctls +dnl + +dnl default is no +CAN_BUILD_LIBDVDCSS=0 + +dnl for windoze +AC_CHECK_HEADERS(windows.h,[ + AC_CHECK_HEADERS(direct.h,,,[ + #include <windows.h> + ]) + AC_CHECK_HEADERS(winioctl.h,[ + CAN_BUILD_LIBDVDCSS=1 + ],,[ + #include <windows.h> + ]) +]) + +dnl for Un*x and BeOS +AC_CHECK_HEADERS(sys/ioctl.h,[ + CAN_BUILD_LIBDVDCSS=1 + AC_CHECK_HEADERS(sys/cdio.h sys/dvdio.h linux/cdrom.h dvd.h) + BSD_DVD_STRUCT=0 + LINUX_DVD_STRUCT=0 + OPENBSD_DVD_STRUCT=0 + dnl + dnl Old FreeBSD: sys/cdio.h + dnl + AC_EGREP_HEADER(dvd_struct,sys/cdio.h,[ + AC_DEFINE(DVD_STRUCT_IN_SYS_CDIO_H, 1, + Define if <sys/cdio.h> defines dvd_struct.) + AC_EGREP_HEADER(struct dvd_struct,sys/cdio.h,[ + BSD_DVD_STRUCT=1],[LINUX_DVD_STRUCT=1; OPENBSD_DVD_STRUCT=1]) + ]) + dnl + dnl Newer FreeBSD: sys/dvdio.h + dnl + AC_EGREP_HEADER(dvd_struct,sys/dvdio.h,[ + AC_DEFINE(DVD_STRUCT_IN_SYS_DVDIO_H, 1, + Define if <sys/dvdio.h> defines dvd_struct.) + AC_EGREP_HEADER(struct dvd_struct,sys/dvdio.h,[ + BSD_DVD_STRUCT=1],[LINUX_DVD_STRUCT=1]) + ]) + dnl + dnl Linux: linux/cdrom.h + dnl + AC_EGREP_HEADER(dvd_struct,linux/cdrom.h,[ + AC_DEFINE(DVD_STRUCT_IN_LINUX_CDROM_H, 1, + Define if <linux/cdrom.h> defines DVD_STRUCT.) + LINUX_DVD_STRUCT=1 + ]) + dnl + dnl BSDI: dvd.h - may require -ldvd IF a local copy of libdvd is installed + dnl + AC_EGREP_HEADER(dvd_struct,dvd.h,[ + AC_DEFINE(DVD_STRUCT_IN_DVD_H, 1, + Define if <dvd.h> defines DVD_STRUCT.) + SYS_BSDI_LIBDVD=1 + LINUX_DVD_STRUCT=1 + ],[ + dnl + dnl BSDI: /sys/dev/scsi/scsi_ioctl.h, using our own libdvd + dnl + AC_CHECK_HEADERS(/sys/dev/scsi/scsi_ioctl.h,[ + AC_DEFINE(DVD_STRUCT_IN_BSDI_DVDIOCTL_DVD_H, 1, + Define if <extras/BSDI_dvdioctl/dvd.h> defines DVD_STRUCT.) + SYS_BSDI=1 + LINUX_DVD_STRUCT=1 + ]) + ]) + dnl + dnl Solaris: sys/scsi/scsi_types.h, sys/scsi/impl/uscsi.h + dnl + AC_CHECK_HEADER(sys/scsi/scsi_types.h,[ + AC_CHECK_HEADER(sys/scsi/impl/uscsi.h,[ + AC_DEFINE(SOLARIS_USCSI, 1, Have userspace SCSI headers.) + ]) + ]) + dnl + dnl HP-UX: sys/scsi.h + dnl + AC_CHECK_HEADER(sys/scsi.h,[ + AC_EGREP_HEADER(sctl_io,sys/scsi.h,[ + AC_DEFINE(HPUX_SCTL_IO, 1, Define if <sys/scsi.h> defines sctl_io.) + ]) + ]) + dnl + dnl Darwin + dnl + AC_CHECK_HEADER(IOKit/storage/IODVDMediaBSDClient.h,[ + AC_DEFINE(DARWIN_DVD_IOCTL, 1, Have IOKit DVD IOCTL headers) + DVDCSS_LDFLAGS="-Wl,-framework -Wl,CoreFoundation -Wl,-framework -Wl,IOKit" + ]) + dnl + dnl Final tests to check what was detected + dnl + if test x$LINUX_DVD_STRUCT = x1; then + AC_DEFINE(HAVE_LINUX_DVD_STRUCT, 1, + Define if Linux-like dvd_struct is defined.) + if test x$OPENBSD_DVD_STRUCT = x1; then + AC_DEFINE(HAVE_OPENBSD_DVD_STRUCT, 1, + Define if OpenBSD-like dvd_struct is defined.) + fi + else + if test x$BSD_DVD_STRUCT = x1; then + AC_DEFINE(HAVE_BSD_DVD_STRUCT, 1, + Define if FreeBSD-like dvd_struct is defined.) + fi + fi +]) + +dnl +dnl Check for available warning flags +dnl +CFLAGS_save="${CFLAGS}" + +AC_CACHE_CHECK([if \$CC accepts -Wall], + [ac_cv_c_Wall], + [CFLAGS="-Wall ${CFLAGS_save}" + AC_TRY_COMPILE([],,ac_cv_c_Wall=yes, ac_cv_c_Wall=no)]) +if test "${ac_cv_c_Wall}" != "no"; then + CFLAGS_save="-Wall ${CFLAGS_save}" +fi + +AC_CACHE_CHECK([if \$CC accepts -Wsign-compare], + [ac_cv_c_Wsign_compare], + [CFLAGS="-Wsign-compare ${CFLAGS_save}" + AC_TRY_COMPILE([],,ac_cv_c_Wsign_compare=yes, ac_cv_c_Wsign_compare=no)]) +if test "${ac_cv_c_Wsign_compare}" != "no"; then + CFLAGS_save="-Wsign-compare ${CFLAGS_save}" +fi + +CFLAGS="${CFLAGS_save}" + +dnl +dnl Use 64 bits offsets +dnl +CFLAGS="-D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -DDVDCSS_DIST ${CFLAGS}" + +AM_CONDITIONAL(SYS_BSDI, test "${SYS_BSDI}" = "1") +AM_CONDITIONAL(SYS_BSDI_LIBDVD, test "${SYS_BSDI_LIBDVD}" = "1") +AM_CONDITIONAL(SYS_MSVC, test "${SYS_MSVC}" = "1") + +dnl +dnl Shall we build documentation? +dnl +AC_ARG_ENABLE([doc], AC_HELP_STRING([--disable-doc], [do not build API documentation with Doxygen])) +if test "$enable_doc" != "no"; then + AC_PATH_PROG(DOXYGEN, doxygen, no) + AC_PATH_PROG(LATEX, latex, no) +else + DOXYGEN="no" + LATEX="no" +fi +AM_CONDITIONAL(DOXYGEN, test "${DOXYGEN}" != "no") +AM_CONDITIONAL(LATEX, test "${LATEX}" != "no") + +AC_SUBST(DVDCSS_LDFLAGS) +AC_OUTPUT([ + Makefile + doc/Makefile + src/Makefile + src/dvdcss/Makefile + test/Makefile + src/libdvdcss.pc +]) + diff --git a/lib/libdvd/libdvdcss/doc/Makefile.am b/lib/libdvd/libdvdcss/doc/Makefile.am new file mode 100644 index 0000000000..2e269b028a --- /dev/null +++ b/lib/libdvd/libdvdcss/doc/Makefile.am @@ -0,0 +1,28 @@ +EXTRA_DIST = doxygen.cfg.in footer.html header.html +DISTCLEANFILES = doxygen.cfg + +all: stamp-doxygen stamp-latex + +doxygen.cfg: $(srcdir)/doxygen.cfg.in + -rm -f $@ + sed 's|@SRCDIR@|$(srcdir)|g; s|@TOP_SRCDIR@|$(top_srcdir)|g' $< > $@ + +stamp-doxygen: doxygen.cfg +if DOXYGEN + doxygen doxygen.cfg + touch stamp-doxygen +endif + +stamp-latex: stamp-doxygen +if DOXYGEN +if LATEX + cd latex && $(MAKE) $(AM_CFLAGS) ps + touch stamp-latex +endif +endif + +clean: clean-local +clean-local: + -rm -f stamp-latex stamp-doxygen + -rm -Rf html latex + diff --git a/lib/libdvd/libdvdcss/doc/doxygen.cfg.in b/lib/libdvd/libdvdcss/doc/doxygen.cfg.in new file mode 100644 index 0000000000..c27228a17c --- /dev/null +++ b/lib/libdvd/libdvdcss/doc/doxygen.cfg.in @@ -0,0 +1,1419 @@ +# 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 = libdvdcss + +# 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 = 1.2.5 + +# 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 = . + +# 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 DETAILS_AT_TOP tag is set to YES then Doxygen +# will output the detailed description near the top, like JavaDoc. +# If set to NO, the detailed description appears after the member +# documentation. + +DETAILS_AT_TOP = 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 + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = NO + +# 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 <command> <input-file>, where <command> is the value of +# the FILE_VERSION_FILTER tag, and <input-file> 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 = NO + +# 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/dvdcss/dvdcss.h \ + @TOP_SRCDIR@/src/libdvdcss.c + +# 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 <filter> <input-file>, where <filter> +# is the value of the INPUT_FILTER tag, and <input-file> 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 = @SRCDIR@/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 = @SRCDIR@/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 HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# 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 = YES + +# The LATEX_OUTPUT tag is used to specify where the LaTeX 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 `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = 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/lib/libdvd/libdvdcss/doc/footer.html b/lib/libdvd/libdvdcss/doc/footer.html new file mode 100644 index 0000000000..b1f50f56cc --- /dev/null +++ b/lib/libdvd/libdvdcss/doc/footer.html @@ -0,0 +1,3 @@ +<!-- $Id$ --> + </body> +</html> diff --git a/lib/libdvd/libdvdcss/doc/header.html b/lib/libdvd/libdvdcss/doc/header.html new file mode 100644 index 0000000000..b6c70da037 --- /dev/null +++ b/lib/libdvd/libdvdcss/doc/header.html @@ -0,0 +1,10 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<html> + <head> + <meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1"> + <title>libdvdcss documentation</title> + <link href="/main.css" rel="stylesheet" type="text/css"> + <link href="/doxygen.css" rel="stylesheet" type="text/css"> + </head> + <body> +<!-- $Id$ --> diff --git a/lib/libdvd/libdvdcss/libdvdcss.spec b/lib/libdvd/libdvdcss/libdvdcss.spec new file mode 100644 index 0000000000..4276333846 --- /dev/null +++ b/lib/libdvd/libdvdcss/libdvdcss.spec @@ -0,0 +1,181 @@ +%define name libdvdcss +%define version 1.2.9 +%define release 1 + +%define major 2 +%define libname %{name}%{major} + +%define buildfor_rh9 %([[ -e /etc/mandrake-release ]] && echo 0 || echo 1) + +%if %buildfor_rh9 +# some mdk macros that do not exist in rh +%define configure2_5x %configure +%define make %__make +%define makeinstall_std %makeinstall +# adjust define for Redhat. +%endif + + +Name: %{name} +Version: %{version} +Release: %{release} +Summary: Library for accessing DVDs like block devices with transparent decryption +Source: %{name}-%{version}.tar.bz2 +License: GPL +Group: System/Libraries +URL: http://www.videolan.org/libdvdcss/ +Packager: Yves Duret <yves@zarb.org> +BuildRoot: %_tmppath/%name-%version-%release-root +Conflicts: libdvdcss0.0.1, libdvdcss0.0.2 + +%description +libdvdcss is a simple library designed for accessing DVDs like a block device +without having to bother about the decryption. The important features are: + * Portability: currently supported platforms are GNU/Linux, FreeBSD, NetBSD, + OpenBSD, BSD/OS, BeOS, Windows 95/98/ME, Windows NT/2000/XP, MacOS X, + Solaris, HP-UX and OS/2. + * Adaptability: unlike most similar projects, libdvdcss doesn't require the + region of your drive to be set and will try its best to read from the disc + even in the case of a region mismatch. + * Simplicity: a DVD player can be built around the libdvdcss API using no + more than 6 library calls. + +%package -n %{libname} +Summary: Library for accessing DVDs like block devices with transparent decryption +Group: System/Libraries +Provides: %name = %version-%release + +%description -n %{libname} +libdvdcss is a simple library designed for accessing DVDs like a block device +without having to bother about the decryption. The important features are: + * Portability: currently supported platforms are GNU/Linux, FreeBSD, NetBSD, + OpenBSD, BSD/OS, BeOS, Windows 95/98/ME, Windows NT/2000/XP, MacOS X, + Solaris, HP-UX and OS/2. + * Adaptability: unlike most similar projects, libdvdcss doesn't require the + region of your drive to be set and will try its best to read from the disc + even in the case of a region mismatch. + * Simplicity: a DVD player can be built around the libdvdcss API using no + more than 6 library calls. + +%package -n %{libname}-devel +Summary: Development tools for programs which will use the %{name} library +Group: Development/C +Requires: %{libname} = %version-%release +Provides: %{name}-devel = %version-%release + +%description -n %{libname}-devel +The %{name}-devel package includes the header files and static libraries +necessary for developing programs which will manipulate DVDs files using +the %{name} library. + +If you are going to develop programs which will manipulate DVDs, you +should install %{name}-devel. You'll also need to have the %{name} +package installed. + +%prep +%setup -q + +%build +%configure2_5x +%make + +%install +%makeinstall_std + +%clean +[ %buildroot != "/" ] && rm -Rf %buildroot + +%post -n %{libname} -p /sbin/ldconfig + +%postun -n %{libname} -p /sbin/ldconfig + +%files -n %{libname} +%defattr(-,root,root) +%doc AUTHORS COPYING NEWS +%{_libdir}/*.so.* + +%files -n %{libname}-devel +%defattr(-,root,root) +%doc ChangeLog COPYING +%{_libdir}/*.a +%{_libdir}/*.so +%{_libdir}/*.la +%{_includedir}/* + +%changelog +* Mon Jul 11 2005 Sam Hocevar <sam@zoy.org> 1.2.9-1 +- new upstream release + +* Tue Jul 29 2003 Sam Hocevar <sam@zoy.org> 1.2.8-1 +- new upstream release + +* Fri Jun 13 2003 Sam Hocevar <sam@zoy.org> 1.2.7-1 +- new upstream release +- key cache activated by default + +* Mon Mar 10 2003 Alexis de Lattre <alexis@videolan.org> 1.2.6-1 +- new upstream release +- small bug fixes + +* Tue Jan 28 2003 Sam Hocevar <sam@zoy.org> 1.2.5-1 +- new upstream release +- improved robustness in case of read errors +- key cache support +- added more macros to fix RedHat build + +* Mon Nov 18 2002 Alexis de Lattre <alexis@videolan.org> 1.2.4-2 +- Changes in .spec file for RedHat and RPM 4.1 + +* Thu Nov 14 2002 Alexis de Lattre <alexis@videolan.org> 1.2.4-1 +- new upstream release +- fixes for Win32 + +* Sun Oct 13 2002 Sam Hocevar <sam@zoy.org> 1.2.3-1 +- new upstream release +- fix for drives not allowing to read their disc key + +* Sat Aug 10 2002 Sam Hocevar <sam@zoy.org> 1.2.2-1 +- new upstream release +- even more fixes for the disc/drive region mismatch problem + +* Sun Jun 02 2002 Sam Hocevar <sam@zoy.org> 1.2.1-1 +- new upstream release +- fix for a crash on disc/drive region mismatch + +* Mon May 20 2002 Sam Hocevar <sam@zoy.org> 1.2.0-1 +- new upstream release +- weird libxalf dependency is gone + +* Sun Apr 07 2002 Yves Duret <yduret@mandrakesoft.com> 1.1.1-2plf +- major version is 2 (aka guillaume sux). +- spec clean up: do not rm in %%prep, %%buildroot, %%makeinstall_std, %%provides %%version-%%release +- added doc in devel +- sync with cvs's one (%%description,%%files, conflicts). +- fix url + +* Sat Apr 06 2002 Guillaume Rousse <rousse@ccr.jussieu.fr> 1.1.1-1plf +- 1.1.1 + +* Wed Jan 30 2002 Guillaume Rousse <rousse@ccr.jussieu.fr> 1.0.0-3plf +- new plf extension + +* Wed Dec 05 2001 Guillaume Rousse <g.rousse@linux-mandrake.com> 1.0.0-3mdk +- removed conflict + +* Tue Dec 04 2001 Guillaume Rousse <g.rousse@linux-mandrake.com> 1.0.0-2mdk +- contributed to PLF by Yves Duret <yduret@mandrakesoft.com> +- Conflicts: libdvdcss-ogle +- more doc files +- no doc file for devel package + +* Fri Nov 30 2001 Yves Duret <yduret@mandrakesoft.com> 1.0.0-1mdk +- version 1.0.0 + +* Thu Aug 23 2001 Yves Duret <yduret@mandrakesoft.com> 0.0.3-1mdk +- version 0.0.3 + +* Mon Aug 13 2001 Yves Duret <yduret@mandrakesoft.com> 0.0.2-1mdk +- version 0.0.2 + +* Tue Jun 19 2001 Yves Duret <yduret@mandrakesoft.com> 0.0.1-1mdk +- first release and first mdk release diff --git a/lib/libdvd/libdvdcss/src/Makefile.am b/lib/libdvd/libdvdcss/src/Makefile.am new file mode 100644 index 0000000000..3823b501d8 --- /dev/null +++ b/lib/libdvd/libdvdcss/src/Makefile.am @@ -0,0 +1,37 @@ +SUBDIRS = dvdcss + +lib_LTLIBRARIES = libdvdcss.la + +libdvdcss_la_SOURCES = \ + libdvdcss.c libdvdcss.h \ + device.c device.h \ + css.c css.h csstables.h \ + ioctl.c ioctl.h \ + error.c \ + common.h \ + $(bsdi_sources) + +EXTRA_libdvdcss_la_SOURCES = \ + $(bsdi_extras) + +libdvdcss_la_LIBADD = $(bsdi_libadd) +libdvdcss_la_LDFLAGS = -version-info 3:0:1 $(libtool_flags) @DVDCSS_LDFLAGS@ + +bsdi_extras = bsdi_ioctl.c bsdi_dvd.h + +if SYS_BSDI +bsdi_sources = $(bsdi_extras) +endif + +if SYS_BSDI_LIBDVD +bsdi_libadd = -ldvd +endif + +if SYS_MSVC +else +libtool_flags = -no-undefined +endif + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = libdvdcss.pc + diff --git a/lib/libdvd/libdvdcss/src/bsdi_dvd.h b/lib/libdvd/libdvdcss/src/bsdi_dvd.h new file mode 100644 index 0000000000..f4c8b89f6d --- /dev/null +++ b/lib/libdvd/libdvdcss/src/bsdi_dvd.h @@ -0,0 +1,344 @@ +/* + * $Id$ +*/ + +#ifndef DVDCSS_DVD_H +#define DVDCSS_DVD_H + +#include <sys/cdefs.h> +#include <machine/endian.h> +#include <sys/ioctl.h> + +__BEGIN_DECLS +int dvd_cdrom_ioctl(int, unsigned long, void *); +int cdrom_blocksize(int, int); +void dvd_cdrom_debug(int); +__END_DECLS + +#define ioctl(a,b,c) dvd_cdrom_ioctl((a),(b),(c)) + +typedef unsigned char __u8; +typedef unsigned short __u16; +typedef unsigned int __u32; + +#define DVD_READ_STRUCT 0x5390 /* Read structure */ +#define DVD_WRITE_STRUCT 0x5391 /* Write structure */ +#define DVD_AUTH 0x5392 /* Authentication */ + +#define DVD_STRUCT_PHYSICAL 0x00 +#define DVD_STRUCT_COPYRIGHT 0x01 +#define DVD_STRUCT_DISCKEY 0x02 +#define DVD_STRUCT_BCA 0x03 +#define DVD_STRUCT_MANUFACT 0x04 + +struct dvd_layer { + __u8 book_version : 4; + __u8 book_type : 4; + __u8 min_rate : 4; + __u8 disc_size : 4; + __u8 layer_type : 4; + __u8 track_path : 1; + __u8 nlayers : 2; + __u8 track_density : 4; + __u8 linear_density : 4; + __u8 bca : 1; + __u32 start_sector; + __u32 end_sector; + __u32 end_sector_l0; +}; + +struct dvd_physical { + __u8 type; + __u8 layer_num; + struct dvd_layer layer[4]; +}; + +struct dvd_copyright { + __u8 type; + + __u8 layer_num; + __u8 cpst; + __u8 rmi; +}; + +struct dvd_disckey { + __u8 type; + + unsigned agid : 2; + __u8 value[2048]; +}; + +struct dvd_bca { + __u8 type; + + int len; + __u8 value[188]; +}; + +struct dvd_manufact { + __u8 type; + + __u8 layer_num; + int len; + __u8 value[2048]; +}; + +typedef union { + __u8 type; + + struct dvd_physical physical; + struct dvd_copyright copyright; + struct dvd_disckey disckey; + struct dvd_bca bca; + struct dvd_manufact manufact; +} dvd_struct; + +/* + * DVD authentication ioctl + */ + +/* Authentication states */ +#define DVD_LU_SEND_AGID 0 +#define DVD_HOST_SEND_CHALLENGE 1 +#define DVD_LU_SEND_KEY1 2 +#define DVD_LU_SEND_CHALLENGE 3 +#define DVD_HOST_SEND_KEY2 4 + +/* Termination states */ +#define DVD_AUTH_ESTABLISHED 5 +#define DVD_AUTH_FAILURE 6 + +/* Other functions */ +#define DVD_LU_SEND_TITLE_KEY 7 +#define DVD_LU_SEND_ASF 8 +#define DVD_INVALIDATE_AGID 9 +#define DVD_LU_SEND_RPC_STATE 10 +#define DVD_HOST_SEND_RPC_STATE 11 + +/* State data */ +typedef __u8 dvd_key[5]; /* 40-bit value, MSB is first elem. */ +typedef __u8 dvd_challenge[10]; /* 80-bit value, MSB is first elem. */ + +struct dvd_lu_send_agid { + __u8 type; + unsigned agid : 2; +}; + +struct dvd_host_send_challenge { + __u8 type; + unsigned agid : 2; + + dvd_challenge chal; +}; + +struct dvd_send_key { + __u8 type; + unsigned agid : 2; + + dvd_key key; +}; + +struct dvd_lu_send_challenge { + __u8 type; + unsigned agid : 2; + + dvd_challenge chal; +}; + +#define DVD_CPM_NO_COPYRIGHT 0 +#define DVD_CPM_COPYRIGHTED 1 + +#define DVD_CP_SEC_NONE 0 +#define DVD_CP_SEC_EXIST 1 + +#define DVD_CGMS_UNRESTRICTED 0 +#define DVD_CGMS_SINGLE 2 +#define DVD_CGMS_RESTRICTED 3 + +struct dvd_lu_send_title_key { + __u8 type; + unsigned agid : 2; + + dvd_key title_key; + int lba; + unsigned cpm : 1; + unsigned cp_sec : 1; + unsigned cgms : 2; +}; + +struct dvd_lu_send_asf { + __u8 type; + unsigned agid : 2; + + unsigned asf : 1; +}; + +struct dvd_host_send_rpcstate { + __u8 type; + __u8 pdrc; +}; + +struct dvd_lu_send_rpcstate { + __u8 type : 2; + __u8 vra : 3; + __u8 ucca : 3; + __u8 region_mask; + __u8 rpc_scheme; +}; + +typedef union { + __u8 type; + + struct dvd_lu_send_agid lsa; + struct dvd_host_send_challenge hsc; + struct dvd_send_key lsk; + struct dvd_lu_send_challenge lsc; + struct dvd_send_key hsk; + struct dvd_lu_send_title_key lstk; + struct dvd_lu_send_asf lsasf; + struct dvd_host_send_rpcstate hrpcs; + struct dvd_lu_send_rpcstate lrpcs; +} dvd_authinfo; + + +typedef struct { + __u16 report_key_length; + __u8 reserved1; + __u8 reserved2; +#if BYTE_ORDER == BIG_ENDIAN + __u8 type_code : 2; + __u8 vra : 3; + __u8 ucca : 3; +#elif BYTE_ORDER == LITTLE_ENDIAN + __u8 ucca : 3; + __u8 vra : 3; + __u8 type_code : 2; +#endif + __u8 region_mask; + __u8 rpc_scheme; + __u8 reserved3; +} rpc_state_t; + +/* + * Stuff for the CDROM ioctls +*/ + +#define CDROMREADTOCHDR 0x5305 /* Read TOC header (cdrom_tochdr) */ +#define CDROMREADTOCENTRY 0x5306 /* Read TOC entry (cdrom_tocentry) */ +#define CDROMEJECT 0x5309 /* Ejects the cdrom media */ +#define CDROMCLOSETRAY 0x5319 /* Reverse of CDROMEJECT */ +#define CDROM_DRIVE_STATUS 0x5326 /* Get tray position, etc. */ +#define CDROM_DISC_STATUS 0x5327 /* Get disc type, etc. */ +#define CDROMREADMODE2 0x530c /* Read CDROM mode 2 data (2336 Bytes) */ +#define CDROMREADMODE1 0x530d /* Read CDROM mode 1 data (2048 Bytes) */ +#define CDROMREADRAW 0x5314 /* read data in raw mode (2352 bytes) */ + +#define CD_MINS 74 /* max. minutes per CD, not really a limit */ +#define CD_SECS 60 /* seconds per minute */ +#define CD_FRAMES 75 /* frames per second */ +#define CD_MSF_OFFSET 150 /* MSF numbering offset of first frame */ + +#define CD_HEAD_SIZE 4 /* header (address) bytes per raw data frame */ +#define CD_SYNC_SIZE 12 /* 12 sync bytes per raw data frame */ +#define CD_FRAMESIZE 2048 /* bytes per frame, "cooked" mode */ +#define CD_FRAMESIZE_RAW 2352 /* bytes per frame, "raw" mode */ +#define CD_FRAMESIZE_RAW0 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE-CD_HEAD_SIZE) /*2336*/ +#define CD_FRAMESIZE_RAW1 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE) /*2340*/ + +/* CD-ROM address types (cdrom_tocentry.cdte_format) */ +#define CDROM_LBA 0x01 /* logical block: first frame is #0 */ +#define CDROM_MSF 0x02 /* minute-second-frame: binary. not bcd here!*/ + +/* bit to tell whether track is data or audio (cdrom_tocentry.cdte_ctrl) */ +#define CDROM_DATA_TRACK 0x04 + +/* The leadout track is always 0xAA, regardless of # of tracks on disc */ +#define CDROM_LEADOUT 0xAA + +/* drive status returned by CDROM_DRIVE_STATUS ioctl */ +#define CDS_NO_INFO 0 /* if not implemented */ +#define CDS_NO_DISC 1 +#define CDS_TRAY_OPEN 2 +#define CDS_DRIVE_NOT_READY 3 +#define CDS_DISC_OK 4 + +/* + * Return values for CDROM_DISC_STATUS ioctl. + * Can also return CDS_NO_INFO and CDS_NO_DISC from above +*/ +#define CDS_AUDIO 100 +#define CDS_DATA_1 101 +#define CDS_DATA_2 102 +#define CDS_XA_2_1 103 +#define CDS_XA_2_2 104 +#define CDS_MIXED 105 + +/* For compile compatibility only - we don't support changers */ +#define CDSL_NONE ((int) (~0U>>1)-1) +#define CDSL_CURRENT ((int) (~0U>>1)) + +struct cdrom_msf +{ + __u8 cdmsf_min0; /* start minute */ + __u8 cdmsf_sec0; /* start second */ + __u8 cdmsf_frame0; /* start frame */ + __u8 cdmsf_min1; /* end minute */ + __u8 cdmsf_sec1; /* end second */ + __u8 cdmsf_frame1; /* end frame */ +}; + +struct cdrom_tochdr + { + __u8 cdth_trk0; /* start track */ + __u8 cdth_trk1; /* end track */ + }; + +struct cdrom_msf0 +{ + __u8 minute; + __u8 second; + __u8 frame; +}; + +union cdrom_addr +{ + struct cdrom_msf0 msf; + int lba; +}; + +struct cdrom_tocentry +{ + __u8 cdte_track; + __u8 cdte_adr :4; + __u8 cdte_ctrl :4; + __u8 cdte_format; + union cdrom_addr cdte_addr; + __u8 cdte_datamode; +}; + +struct modesel_head +{ + __u8 reserved1; + __u8 medium; + __u8 reserved2; + __u8 block_desc_length; + __u8 density; + __u8 number_of_blocks_hi; + __u8 number_of_blocks_med; + __u8 number_of_blocks_lo; + __u8 reserved3; + __u8 block_length_hi; + __u8 block_length_med; + __u8 block_length_lo; +}; + +typedef struct +{ + int data; + int audio; + int cdi; + int xa; + int error; +} tracktype; + +#endif /* DVDCSS_DVD_H */ diff --git a/lib/libdvd/libdvdcss/src/bsdi_ioctl.c b/lib/libdvd/libdvdcss/src/bsdi_ioctl.c new file mode 100644 index 0000000000..ef4c56c30e --- /dev/null +++ b/lib/libdvd/libdvdcss/src/bsdi_ioctl.c @@ -0,0 +1,770 @@ +#include "config.h" + +/* + * Hacked version of the linux cdrom.c kernel module - everything except the + * DVD handling ripped out and the rest rewritten to use raw SCSI commands + * on BSD/OS 4.2 (but should work with earlier versions as well). +*/ + +#include <sys/types.h> +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include </sys/dev/scsi/scsi.h> +#include </sys/dev/scsi/scsi_ioctl.h> + +#include "bsdi_dvd.h" + +/* + * Now get rid of the override/intercept macro so we can call the real ioctl() + * routine! +*/ +#undef ioctl + +#define CMD_READ_10 0x28 +#define CMD_READ_TOC_PMA_ATIP 0x43 +#define CMD_READ_CD 0xbe +#define CMD_START_STOP_UNIT 0x1b + +#define CMD_SEND_KEY 0xa3 +#define CMD_REPORT_KEY 0xa4 +#define CMD_READ_DVD_STRUCTURE 0xad + +#define copy_key(dest,src) memcpy((dest), (src), sizeof(dvd_key)) +#define copy_chal(dest,src) memcpy((dest), (src), sizeof(dvd_challenge)) + +/* Define the Cdrom Generic Command structure */ +typedef struct cgc + { + u_char cdb[12]; + u_char *buf; + int buflen; + int rw; + int timeout; + scsi_user_sense_t *sus; + } cgc_t; + +static int scsi_cmd(int, cgc_t *); +static int cdrom_ioctl(int, u_long, void *); +static int cdrom_tray_move(int, int); +static void cdrom_count_tracks(int, tracktype *); +static int dvd_ioctl(int, u_long, void *); +static int debug = 0; + +void dvd_cdrom_debug(int flag) + { + debug = flag; + } + +/* + * This is the published entry point. Actually applications should simply + * include <dvd.h> and not refer to this at all. +*/ +int dvd_cdrom_ioctl(int fd, unsigned long cmd, void *arg) + { + switch (cmd) + { + case DVD_AUTH: + case DVD_READ_STRUCT: + return(dvd_ioctl(fd, cmd, arg)); + case CDROMREADTOCHDR: + case CDROMREADTOCENTRY: + case CDROMEJECT: + case CDROMREADRAW: + case CDROMREADMODE1: + case CDROMREADMODE2: + case CDROMCLOSETRAY: + case CDROM_DRIVE_STATUS: + case CDROM_DISC_STATUS: + return(cdrom_ioctl(fd, cmd, arg)); + default: + return(ioctl(fd, cmd, arg)); + } + } + +static void setup_report_key(cgc_t *cgc, u_int agid, u_int type) + { + + cgc->cdb[0] = CMD_REPORT_KEY; + cgc->cdb[10] = type | (agid << 6); + switch (type) + { + case 0: + case 5: + case 8: + cgc->buflen = 8; + break; + case 1: + cgc->buflen = 16; + break; + case 2: + case 4: + cgc->buflen = 12; + break; + } + cgc->cdb[9] = cgc->buflen; + cgc->rw = SUC_READ;; + } + +static void setup_send_key(cgc_t *cgc, u_int agid, u_int type) + { + + cgc->cdb[0] = CMD_SEND_KEY; + cgc->cdb[10] = type | (agid << 6); + switch (type) + { + case 1: + cgc->buflen = 16; + break; + case 3: + cgc->buflen = 12; + break; + case 6: + cgc->buflen = 8; + break; + } + cgc->cdb[9] = cgc->buflen; + cgc->rw = SUC_WRITE; + } + +static void cgc_init(cgc_t *cgc, void *buf, int len, int type) + { + + memset(cgc, 0, sizeof (*cgc)); + if (buf) + memset(buf, 0, len); + cgc->buf = (u_char *)buf; + cgc->buflen = len; + cgc->rw = type; + cgc->timeout = 5; /* 5 second timeout */ + } + +static int dvd_do_auth(int fd, dvd_authinfo *ai) + { + int ret; + u_char buf[20]; + cgc_t cgc; + rpc_state_t rpc_state; + + memset(buf, 0, sizeof(buf)); + cgc_init(&cgc, buf, 0, SUC_READ); + + switch (ai->type) + { + case DVD_LU_SEND_AGID: /* LU data send */ + setup_report_key(&cgc, ai->lsa.agid, 0); + if (ret = scsi_cmd(fd, &cgc)) + return ret; + ai->lsa.agid = buf[7] >> 6; + break; + case DVD_LU_SEND_KEY1: + setup_report_key(&cgc, ai->lsk.agid, 2); + if (ret = scsi_cmd(fd, &cgc)) + return ret; + copy_key(ai->lsk.key, &buf[4]); + break; + case DVD_LU_SEND_CHALLENGE: + setup_report_key(&cgc, ai->lsc.agid, 1); + if (ret = scsi_cmd(fd, &cgc)) + return ret; + copy_chal(ai->lsc.chal, &buf[4]); + break; + case DVD_LU_SEND_TITLE_KEY: /* Post-auth key */ + setup_report_key(&cgc, ai->lstk.agid, 4); + cgc.cdb[5] = ai->lstk.lba; + cgc.cdb[4] = ai->lstk.lba >> 8; + cgc.cdb[3] = ai->lstk.lba >> 16; + cgc.cdb[2] = ai->lstk.lba >> 24; + if (ret = scsi_cmd(fd, &cgc)) + return ret; + ai->lstk.cpm = (buf[4] >> 7) & 1; + ai->lstk.cp_sec = (buf[4] >> 6) & 1; + ai->lstk.cgms = (buf[4] >> 4) & 3; + copy_key(ai->lstk.title_key, &buf[5]); + break; + case DVD_LU_SEND_ASF: + setup_report_key(&cgc, ai->lsasf.agid, 5); + if (ret = scsi_cmd(fd, &cgc)) + return ret; + ai->lsasf.asf = buf[7] & 1; + break; + case DVD_HOST_SEND_CHALLENGE: /* LU data receive (LU changes state) */ + setup_send_key(&cgc, ai->hsc.agid, 1); + buf[1] = 0xe; + copy_chal(&buf[4], ai->hsc.chal); + if (ret = scsi_cmd(fd, &cgc)) + return ret; + ai->type = DVD_LU_SEND_KEY1; + break; + case DVD_HOST_SEND_KEY2: + setup_send_key(&cgc, ai->hsk.agid, 3); + buf[1] = 0xa; + copy_key(&buf[4], ai->hsk.key); + if (ret = scsi_cmd(fd, &cgc)) + { + ai->type = DVD_AUTH_FAILURE; + return ret; + } + ai->type = DVD_AUTH_ESTABLISHED; + break; + case DVD_INVALIDATE_AGID: + setup_report_key(&cgc, ai->lsa.agid, 0x3f); + if (ret = scsi_cmd(fd, &cgc)) + return ret; + break; + case DVD_LU_SEND_RPC_STATE: /* Get region settings */ + setup_report_key(&cgc, 0, 8); + memset(&rpc_state, 0, sizeof(rpc_state_t)); + cgc.buf = (char *) &rpc_state; + if (ret = scsi_cmd(fd, &cgc)) + { + ai->lrpcs.type = 0; + ai->lrpcs.rpc_scheme = 0; + } + else + { + ai->lrpcs.type = rpc_state.type_code; + ai->lrpcs.vra = rpc_state.vra; + ai->lrpcs.ucca = rpc_state.ucca; + ai->lrpcs.region_mask = rpc_state.region_mask; + ai->lrpcs.rpc_scheme = rpc_state.rpc_scheme; + } + break; + case DVD_HOST_SEND_RPC_STATE: /* Set region settings */ + setup_send_key(&cgc, 0, 6); + buf[1] = 6; + buf[4] = ai->hrpcs.pdrc; + if (ret = scsi_cmd(fd, &cgc)) + return ret; + break; + default: + return EINVAL; + } + return 0; + } + +static int dvd_read_physical(int fd, dvd_struct *s) + { + int ret, i; + u_char buf[4 + 4 * 20], *base; + struct dvd_layer *layer; + cgc_t cgc; + + cgc_init(&cgc, buf, sizeof(buf), SUC_READ); + cgc.cdb[0] = CMD_READ_DVD_STRUCTURE; + cgc.cdb[6] = s->physical.layer_num; + cgc.cdb[7] = s->type; + cgc.cdb[9] = cgc.buflen & 0xff; + + if (ret = scsi_cmd(fd, &cgc)) + return ret; + + base = &buf[4]; + layer = &s->physical.layer[0]; + + /* place the data... really ugly, but at least we won't have to + worry about endianess in userspace or here. */ + for (i = 0; i < 4; ++i, base += 20, ++layer) + { + memset(layer, 0, sizeof(*layer)); + layer->book_version = base[0] & 0xf; + layer->book_type = base[0] >> 4; + layer->min_rate = base[1] & 0xf; + layer->disc_size = base[1] >> 4; + layer->layer_type = base[2] & 0xf; + layer->track_path = (base[2] >> 4) & 1; + layer->nlayers = (base[2] >> 5) & 3; + layer->track_density = base[3] & 0xf; + layer->linear_density = base[3] >> 4; + layer->start_sector = base[5] << 16 | base[6] << 8 | base[7]; + layer->end_sector = base[9] << 16 | base[10] << 8 | base[11]; + layer->end_sector_l0 = base[13] << 16 | base[14] << 8 | base[15]; + layer->bca = base[16] >> 7; + } + return 0; + } + +static int dvd_read_copyright(int fd, dvd_struct *s) + { + int ret; + u_char buf[8]; + cgc_t cgc; + + cgc_init(&cgc, buf, sizeof(buf), SUC_READ); + cgc.cdb[0] = CMD_READ_DVD_STRUCTURE; + cgc.cdb[6] = s->copyright.layer_num; + cgc.cdb[7] = s->type; + cgc.cdb[8] = cgc.buflen >> 8; + cgc.cdb[9] = cgc.buflen & 0xff; + + if (ret = scsi_cmd(fd, &cgc)) + return ret; + s->copyright.cpst = buf[4]; + s->copyright.rmi = buf[5]; + return 0; + } + +static int dvd_read_disckey(int fd, dvd_struct *s) + { + int ret, size; + u_char *buf; + cgc_t cgc; + + size = sizeof(s->disckey.value) + 4; + + if ((buf = (u_char *) malloc(size)) == NULL) + return ENOMEM; + + cgc_init(&cgc, buf, size, SUC_READ); + cgc.cdb[0] = CMD_READ_DVD_STRUCTURE; + cgc.cdb[7] = s->type; + cgc.cdb[8] = size >> 8; + cgc.cdb[9] = size & 0xff; + cgc.cdb[10] = s->disckey.agid << 6; + + if (!(ret = scsi_cmd(fd, &cgc))) + memcpy(s->disckey.value, &buf[4], sizeof(s->disckey.value)); + free(buf); + return ret; + } + +static int dvd_read_bca(int fd, dvd_struct *s) + { + int ret; + u_char buf[4 + 188]; + cgc_t cgc; + + cgc_init(&cgc, buf, sizeof(buf), SUC_READ); + cgc.cdb[0] = CMD_READ_DVD_STRUCTURE; + cgc.cdb[7] = s->type; + cgc.cdb[9] = cgc.buflen = 0xff; + + if (ret = scsi_cmd(fd, &cgc)) + return ret; + s->bca.len = buf[0] << 8 | buf[1]; + if (s->bca.len < 12 || s->bca.len > 188) + return EIO; + memcpy(s->bca.value, &buf[4], s->bca.len); + return 0; + } + +static int dvd_read_manufact(int fd, dvd_struct *s) + { + int ret = 0, size; + u_char *buf; + cgc_t cgc; + + size = sizeof(s->manufact.value) + 4; + + if ((buf = (u_char *) malloc(size)) == NULL) + return ENOMEM; + + cgc_init(&cgc, buf, size, SUC_READ); + cgc.cdb[0] = CMD_READ_DVD_STRUCTURE; + cgc.cdb[7] = s->type; + cgc.cdb[8] = size >> 8; + cgc.cdb[9] = size & 0xff; + + if (ret = scsi_cmd(fd, &cgc)) + { + free(buf); + return ret; + } + s->manufact.len = buf[0] << 8 | buf[1]; + if (s->manufact.len < 0 || s->manufact.len > 2048) + ret = -EIO; + else + memcpy(s->manufact.value, &buf[4], s->manufact.len); + free(buf); + return ret; + } + +static int dvd_read_struct(int fd, dvd_struct *s) + { + switch (s->type) + { + case DVD_STRUCT_PHYSICAL: + return dvd_read_physical(fd, s); + case DVD_STRUCT_COPYRIGHT: + return dvd_read_copyright(fd, s); + case DVD_STRUCT_DISCKEY: + return dvd_read_disckey(fd, s); + case DVD_STRUCT_BCA: + return dvd_read_bca(fd, s); + case DVD_STRUCT_MANUFACT: + return dvd_read_manufact(fd, s); + default: + return EINVAL; + } + } + +static u_char scsi_cdblen[8] = {6, 10, 10, 12, 12, 12, 10, 10}; + +static int scsi_cmd(int fd, cgc_t *cgc) + { + int i, scsistatus, cdblen; + unsigned char *cp; + struct scsi_user_cdb suc; + + /* safety checks */ + if (cgc->rw != SUC_READ && cgc->rw != SUC_WRITE) + return(EINVAL); + + suc.suc_flags = cgc->rw; + cdblen = scsi_cdblen[(cgc->cdb[0] >> 5) & 7]; + suc.suc_cdblen = cdblen; + bcopy(cgc->cdb, suc.suc_cdb, cdblen); + suc.suc_data = cgc->buf; + suc.suc_datalen = cgc->buflen; + suc.suc_timeout = cgc->timeout; + if (ioctl(fd, SCSIRAWCDB, &suc) == -1) + return(errno); + scsistatus = suc.suc_sus.sus_status; + +/* + * If the device returns a scsi sense error and debugging is enabled print + * some hopefully useful information on stderr. +*/ + if (scsistatus && debug) + { + cp = suc.suc_sus.sus_sense; + fprintf(stderr,"scsistatus = %x cdb =", + scsistatus); + for (i = 0; i < cdblen; i++) + fprintf(stderr, " %x", cgc->cdb[i]); + fprintf(stderr, "\nsense ="); + for (i = 0; i < 16; i++) + fprintf(stderr, " %x", cp[i]); + fprintf(stderr, "\n"); + } + if (cgc->sus) + bcopy(&suc.suc_sus, cgc->sus, sizeof (struct scsi_user_sense)); + if (scsistatus) + return(EIO); /* generic i/o error for unsuccessful status */ + return(0); + } + +/* + * The entry point for the DVDioctls for BSD/OS. +*/ +static int dvd_ioctl(int fd, u_long cmd, void *arg) + { + int ret; + + switch (cmd) + { + case DVD_READ_STRUCT: + ret = dvd_read_struct(fd, (dvd_struct *)arg); + if (ret) + errno = ret; + return(ret ? -1 : 0); + case DVD_AUTH: + ret = dvd_do_auth(fd, (dvd_authinfo *)arg); + if (ret) + errno = ret; + return(ret ? -1 : 0); + default: + errno = EINVAL; + return(-1); + } + } + +/* + * The entry point for the CDROMioctls for BSD/OS +*/ +static int cdrom_read_block(int, cgc_t *, int, int, int, int); +static int cdrom_read_cd(int, cgc_t *, int, int, int ); + int cdrom_blocksize(int, int ); + +static inline +int msf_to_lba(char m, char s, char f) +{ + return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_MSF_OFFSET; +} + +cdrom_ioctl(int fd, u_long cmd, void *arg) + { + int ret; + cgc_t cgc; + + switch (cmd) + { + case CDROMREADRAW: + case CDROMREADMODE1: + case CDROMREADMODE2: + { + struct cdrom_msf *msf; + int blocksize = 0, format = 0, lba; + + switch (cmd) + { + case CDROMREADRAW: + blocksize = CD_FRAMESIZE_RAW; + break; + case CDROMREADMODE1: + blocksize = CD_FRAMESIZE; + format = 2; + break; + case CDROMREADMODE2: + blocksize = CD_FRAMESIZE_RAW0; + break; + } + msf = (struct cdrom_msf *)arg; + lba = msf_to_lba(msf->cdmsf_min0,msf->cdmsf_sec0, + msf->cdmsf_frame0); + ret = EINVAL; + if (lba < 0) + break; + + cgc_init(&cgc, arg, blocksize, SUC_READ); + ret = cdrom_read_block(fd, &cgc, lba, 1, format, blocksize); + if (ret) + { +/* + * SCSI-II devices are not required to support CMD_READ_CD (which specifies + * the blocksize to read) so try switching the block size with a mode select, + * doing the normal read sector command and then changing the sector size back + * to 2048. + * + * If the program dies before changing the blocksize back sdopen() + * in the kernel will fail opens with a message that looks something like: + * + * "sr1: blksize 2336 not multiple of 512: cannot use" + * + * At that point the drive has to be power cycled (or reset in some other way). +*/ + if (ret = cdrom_blocksize(fd, blocksize)) + break; + ret = cdrom_read_cd(fd, &cgc, lba, blocksize, 1); + ret |= cdrom_blocksize(fd, 2048); + } + break; + } + case CDROMREADTOCHDR: + { + struct cdrom_tochdr *tochdr = (struct cdrom_tochdr *) arg; + u_char buffer[12]; + + cgc_init(&cgc, buffer, sizeof (buffer), SUC_READ); + cgc.cdb[0] = CMD_READ_TOC_PMA_ATIP; + cgc.cdb[1] = 0x2; /* MSF */ + cgc.cdb[8] = 12; /* LSB of length */ + + ret = scsi_cmd(fd, &cgc); + if (!ret) + { + tochdr->cdth_trk0 = buffer[2]; + tochdr->cdth_trk1 = buffer[3]; + } + break; + } + case CDROMREADTOCENTRY: + { + struct cdrom_tocentry *tocentry = (struct cdrom_tocentry *) arg; + u_char buffer[12]; + + cgc_init(&cgc, buffer, sizeof (buffer), SUC_READ); + cgc.cdb[0] = CMD_READ_TOC_PMA_ATIP; + cgc.cdb[1] = (tocentry->cdte_format == CDROM_MSF) ? 0x02 : 0; + cgc.cdb[6] = tocentry->cdte_track; + cgc.cdb[8] = 12; /* LSB of length */ + + ret = scsi_cmd(fd, &cgc); + if (ret) + break; + + tocentry->cdte_ctrl = buffer[5] & 0xf; + tocentry->cdte_adr = buffer[5] >> 4; + tocentry->cdte_datamode = (tocentry->cdte_ctrl & 0x04) ? 1 : 0; + if (tocentry->cdte_format == CDROM_MSF) + { + tocentry->cdte_addr.msf.minute = buffer[9]; + tocentry->cdte_addr.msf.second = buffer[10]; + tocentry->cdte_addr.msf.frame = buffer[11]; + } + else + tocentry->cdte_addr.lba = (((((buffer[8] << 8) + + buffer[9]) << 8) + + buffer[10]) << 8) + + buffer[11]; + break; + } + case CDROMEJECT: /* NO-OP for now */ + ret = cdrom_tray_move(fd, 1); + break; + case CDROMCLOSETRAY: + ret = cdrom_tray_move(fd, 0); + break; +/* + * This sucks but emulates the expected behaviour. Instead of the return + * value being the actual status a success/fail indicator should have been + * returned and the 3rd arg to the ioctl should have been an 'int *' to update + * with the actual status. Both the drive and disc status ioctl calls are + * similarily braindamaged. +*/ + case CDROM_DRIVE_STATUS: + return(CDS_NO_INFO); /* XXX */ + case CDROM_DISC_STATUS: + { + tracktype tracks; + int cnt; + + cdrom_count_tracks(fd, &tracks); + if (tracks.error) + return(tracks.error); + if (tracks.audio > 0) + { + cnt = tracks.data + tracks.cdi + tracks.xa; + if (cnt == 0) + return(CDS_AUDIO); + else + return(CDS_MIXED); + } + if (tracks.cdi) + return(CDS_XA_2_2); + if (tracks.xa) + return(CDS_XA_2_1); + if (tracks.data) + return(CDS_DATA_1); + return(CDS_NO_INFO); + } + } + errno = ret; + return(ret ? -1 : 0); + } + +static int cdrom_read_cd(int fd, cgc_t *cgc, int lba, int blocksize, int nblocks) + { + + memset(&cgc->cdb, 0, sizeof(cgc->cdb)); + cgc->cdb[0] = CMD_READ_10; + cgc->cdb[2] = (lba >> 24) & 0xff; + cgc->cdb[3] = (lba >> 16) & 0xff; + cgc->cdb[4] = (lba >> 8) & 0xff; + cgc->cdb[5] = lba & 0xff; + cgc->cdb[6] = (nblocks >> 16) & 0xff; + cgc->cdb[7] = (nblocks >> 8) & 0xff; + cgc->cdb[8] = nblocks & 0xff; + cgc->buflen = blocksize * nblocks; + return(scsi_cmd(fd, cgc)); + } + +static int cdrom_read_block(int fd, cgc_t *cgc, + int lba, int nblocks, int format, int blksize) + { + + memset(&cgc->cdb, 0, sizeof(cgc->cdb)); + cgc->cdb[0] = CMD_READ_CD; + /* expected sector size - cdda,mode1,etc. */ + cgc->cdb[1] = format << 2; + /* starting address */ + cgc->cdb[2] = (lba >> 24) & 0xff; + cgc->cdb[3] = (lba >> 16) & 0xff; + cgc->cdb[4] = (lba >> 8) & 0xff; + cgc->cdb[5] = lba & 0xff; + /* number of blocks */ + cgc->cdb[6] = (nblocks >> 16) & 0xff; + cgc->cdb[7] = (nblocks >> 8) & 0xff; + cgc->cdb[8] = nblocks & 0xff; + cgc->buflen = blksize * nblocks; + + /* set the header info returned */ + switch (blksize) + { + case CD_FRAMESIZE_RAW0: + cgc->cdb[9] = 0x58; + break; + case CD_FRAMESIZE_RAW1: + cgc->cdb[9] = 0x78; + break; + case CD_FRAMESIZE_RAW: + cgc->cdb[9] = 0xf8; + break; + default: + cgc->cdb[9] = 0x10; + } + return(scsi_cmd(fd, cgc)); + } + +static void cdrom_count_tracks(int fd, tracktype *tracks) + { + struct cdrom_tochdr header; + struct cdrom_tocentry entry; + int ret, i; + + memset(tracks, 0, sizeof (*tracks)); + ret = cdrom_ioctl(fd, CDROMREADTOCHDR, &header); +/* + * This whole business is a crock anyhow so we don't bother distinguishing + * between no media, drive not ready, etc and on any error just say we have + * no info. +*/ + if (ret) + { + tracks->error = CDS_NO_INFO; + return; + } + + entry.cdte_format = CDROM_MSF; + for (i = header.cdth_trk0; i <= header.cdth_trk1; i++) + { + entry.cdte_track = i; + if (cdrom_ioctl(fd, CDROMREADTOCENTRY, &entry)) + { + tracks->error = CDS_NO_INFO; + return; + } + if (entry.cdte_ctrl & CDROM_DATA_TRACK) + { + if (entry.cdte_format == 0x10) + tracks->cdi++; + else if (entry.cdte_format == 0x20) + tracks->xa++; + else + tracks->data++; + } + else + tracks->audio++; + } + return; + } + +static int cdrom_tray_move(int fd, int flag) + { + cgc_t cgc; + + cgc_init(&cgc, NULL, 0, SUC_READ); + cgc.cdb[0] = CMD_START_STOP_UNIT; + cgc.cdb[1] = 1; /* immediate */ + cgc.cdb[4] = flag ? 0x2 : 0x3; /* eject : close */ + return(scsi_cmd(fd, &cgc)); + } + +/* + * Required when we need to use READ_10 to issue other than 2048 block + * reads + */ +int cdrom_blocksize(int fd, int size) + { + cgc_t cgc; + struct modesel_head mh; + + memset(&mh, 0, sizeof(mh)); + mh.block_desc_length = 0x08; + mh.block_length_med = (size >> 8) & 0xff; + mh.block_length_lo = size & 0xff; + + memset(&cgc, 0, sizeof(cgc)); + cgc.cdb[0] = 0x15; + cgc.cdb[1] = 1 << 4; + cgc.cdb[4] = 12; + cgc.buflen = sizeof(mh); + cgc.buf = (u_char *) &mh; + cgc.rw = SUC_WRITE; + mh.block_desc_length = 0x08; + mh.block_length_med = (size >> 8) & 0xff; + mh.block_length_lo = size & 0xff; + return(scsi_cmd(fd, &cgc)); + } diff --git a/lib/libdvd/libdvdcss/src/common.h b/lib/libdvd/libdvdcss/src/common.h new file mode 100644 index 0000000000..aff5ccbaa7 --- /dev/null +++ b/lib/libdvd/libdvdcss/src/common.h @@ -0,0 +1,81 @@ +/***************************************************************************** + * common.h: common definitions + * Collection of useful common types and macros definitions + ***************************************************************************** + * Copyright (C) 1998, 1999, 2000 VideoLAN + * $Id$ + * + * Authors: Sam Hocevar <sam@via.ecp.fr> + * Vincent Seguin <seguin@via.ecp.fr> + * Gildas Bazin <gbazin@netcourrier.com> + * + * 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, USA. + *****************************************************************************/ + +/***************************************************************************** + * Basic types definitions + *****************************************************************************/ +#if defined( HAVE_STDINT_H ) +# include <stdint.h> +#elif defined( HAVE_INTTYPES_H ) +# include <inttypes.h> +#elif defined( SYS_CYGWIN ) +# include <sys/types.h> + /* Cygwin only defines half of these... */ + typedef u_int8_t uint8_t; + typedef u_int32_t uint32_t; +#else + /* Fallback types (very x86-centric, sorry) */ + typedef unsigned char uint8_t; + typedef signed char int8_t; + typedef unsigned int uint32_t; + typedef signed int int32_t; +#endif + +#if defined( WIN32 ) + +# ifndef PATH_MAX +# define PATH_MAX MAX_PATH +# endif + +/* several type definitions */ +# if defined( __MINGW32__ ) +# define lseek _lseeki64 +# if !defined( _OFF_T_ ) +typedef long long _off_t; +typedef _off_t off_t; +# define _OFF_T_ +# else +# define off_t long long +# endif +# endif + +# if defined( _MSC_VER ) +# define lseek _lseeki64 +# if !defined( _OFF_T_DEFINED ) +typedef __int64 off_t; +# define _OFF_T_DEFINED +# else +# define off_t __int64 +# endif +# define stat _stati64 +# endif + +# ifndef snprintf +# define snprintf _snprintf /* snprintf not defined in mingw32 (bug?) */ +# endif + +#endif + diff --git a/lib/libdvd/libdvdcss/src/css.c b/lib/libdvd/libdvdcss/src/css.c new file mode 100644 index 0000000000..4e24bbf68f --- /dev/null +++ b/lib/libdvd/libdvdcss/src/css.c @@ -0,0 +1,1696 @@ +/***************************************************************************** + * css.c: Functions for DVD authentication and descrambling + ***************************************************************************** + * Copyright (C) 1999-2008 VideoLAN + * $Id$ + * + * Authors: Stéphane Borel <stef@via.ecp.fr> + * HÃ¥kan Hjort <d95hjort@dtek.chalmers.se> + * + * based on: + * - css-auth by Derek Fawcus <derek@spider.com> + * - DVD CSS ioctls example program by Andrew T. Veliath <andrewtv@usa.net> + * - The Divide and conquer attack by Frank A. Stevenson <frank@funcom.com> + * (see http://www-2.cs.cmu.edu/~dst/DeCSS/FrankStevenson/index.html) + * - DeCSSPlus by Ethan Hawke + * - DecVOB + * see http://www.lemuria.org/DeCSS/ by Tom Vogt for more information. + * + * 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, USA. + *****************************************************************************/ + +/***************************************************************************** + * Preamble + *****************************************************************************/ +#include "config.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#ifdef HAVE_SYS_PARAM_H +# include <sys/param.h> +#endif +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif +#include <fcntl.h> + +#ifdef HAVE_LIMITS_H +# include <limits.h> +#endif + +#include "dvdcss/dvdcss.h" + +#include "common.h" +#include "css.h" +#include "libdvdcss.h" +#include "csstables.h" +#include "ioctl.h" +#include "device.h" + +/***************************************************************************** + * Local prototypes + *****************************************************************************/ +static void PrintKey ( dvdcss_t, char *, uint8_t const * ); + +static int GetBusKey ( dvdcss_t ); +static int GetASF ( dvdcss_t ); + +static void CryptKey ( int, int, uint8_t const *, uint8_t * ); +static void DecryptKey ( uint8_t, + uint8_t const *, uint8_t const *, uint8_t * ); + +static int DecryptDiscKey ( dvdcss_t, uint8_t const *, dvd_key_t ); +static int CrackDiscKey ( dvdcss_t, uint8_t * ); + +static void DecryptTitleKey ( dvd_key_t, dvd_key_t ); +static int RecoverTitleKey ( int, uint8_t const *, + uint8_t const *, uint8_t const *, uint8_t * ); +static int CrackTitleKey ( dvdcss_t, int, int, dvd_key_t ); + +static int AttackPattern ( uint8_t const[], int, uint8_t * ); +#if 0 +static int AttackPadding ( uint8_t const[], int, uint8_t * ); +#endif + +/***************************************************************************** + * _dvdcss_test: check if the disc is encrypted or not + *****************************************************************************/ +int _dvdcss_test( dvdcss_t dvdcss ) +{ + int i_ret, i_copyright; + + i_ret = ioctl_ReadCopyright( dvdcss->i_fd, 0 /* i_layer */, &i_copyright ); + +#ifdef WIN32 + if( i_ret < 0 ) + { + /* Maybe we didn't have enough privileges to read the copyright + * (see ioctl_ReadCopyright comments). + * Apparently, on unencrypted DVDs _dvdcss_disckey() always fails, so + * we can check this as a workaround. */ + i_ret = 0; + i_copyright = 1; + if( _dvdcss_disckey( dvdcss ) < 0 ) + { + i_copyright = 0; + } + } +#endif + + if( i_ret < 0 ) + { + /* Since it's the first ioctl we try to issue, we add a notice */ + print_error( dvdcss, "css error: ioctl_ReadCopyright failed, " + "make sure there is a DVD in the drive, and that " + "you have used the correct device node." ); + + return i_ret; + } + + return i_copyright; +} + +/***************************************************************************** + * _dvdcss_title: crack or decrypt the current title key if needed + ***************************************************************************** + * This function should only be called by dvdcss->pf_seek and should eventually + * not be external if possible. + *****************************************************************************/ +int _dvdcss_title ( dvdcss_t dvdcss, int i_block ) +{ + dvd_title_t *p_title; + dvd_title_t *p_newtitle; + dvd_key_t p_title_key; + int i_fd, i_ret = -1, b_cache = 0; + + if( ! dvdcss->b_scrambled ) + { + return 0; + } + + /* Check if we've already cracked this key */ + p_title = dvdcss->p_titles; + while( p_title != NULL + && p_title->p_next != NULL + && p_title->p_next->i_startlb <= i_block ) + { + p_title = p_title->p_next; + } + + if( p_title != NULL + && p_title->i_startlb == i_block ) + { + /* We've already cracked this key, nothing to do */ + memcpy( dvdcss->css.p_title_key, p_title->p_key, sizeof(dvd_key_t) ); + return 0; + } + + /* Check whether the key is in our disk cache */ + if( dvdcss->psz_cachefile[0] ) + { + /* XXX: be careful, we use sprintf and not snprintf */ + sprintf( dvdcss->psz_block, "%.10x", i_block ); + i_fd = open( dvdcss->psz_cachefile, O_RDONLY ); + b_cache = 1; + + if( i_fd >= 0 ) + { + char psz_key[KEY_SIZE * 3]; + unsigned int k0, k1, k2, k3, k4; + + psz_key[KEY_SIZE * 3 - 1] = '\0'; + + if( read( i_fd, psz_key, KEY_SIZE * 3 - 1 ) == KEY_SIZE * 3 - 1 + && sscanf( psz_key, "%x:%x:%x:%x:%x", + &k0, &k1, &k2, &k3, &k4 ) == 5 ) + { + p_title_key[0] = k0; + p_title_key[1] = k1; + p_title_key[2] = k2; + p_title_key[3] = k3; + p_title_key[4] = k4; + PrintKey( dvdcss, "title key found in cache ", p_title_key ); + + /* Don't try to save it again */ + b_cache = 0; + i_ret = 1; + } + + close( i_fd ); + } + } + + /* Crack or decrypt CSS title key for current VTS */ + if( i_ret < 0 ) + { + i_ret = _dvdcss_titlekey( dvdcss, i_block, p_title_key ); + + if( i_ret < 0 ) + { + print_error( dvdcss, "fatal error in vts css key" ); + return i_ret; + } + + if( i_ret == 0 ) + { + print_debug( dvdcss, "unencrypted title" ); + /* We cache this anyway, so we don't need to check again. */ + } + } + + /* Key is valid, we store it on disk. */ + if( dvdcss->psz_cachefile[0] && b_cache ) + { + i_fd = open( dvdcss->psz_cachefile, O_RDWR|O_CREAT, 0644 ); + if( i_fd >= 0 ) + { + char psz_key[KEY_SIZE * 3 + 2]; + + sprintf( psz_key, "%02x:%02x:%02x:%02x:%02x\r\n", + p_title_key[0], p_title_key[1], p_title_key[2], + p_title_key[3], p_title_key[4] ); + + write( i_fd, psz_key, KEY_SIZE * 3 + 1 ); + close( i_fd ); + } + } + + /* Find our spot in the list */ + p_newtitle = NULL; + p_title = dvdcss->p_titles; + while( ( p_title != NULL ) && ( p_title->i_startlb < i_block ) ) + { + p_newtitle = p_title; + p_title = p_title->p_next; + } + + /* Save the found title */ + p_title = p_newtitle; + + /* Write in the new title and its key */ + p_newtitle = malloc( sizeof( dvd_title_t ) ); + p_newtitle->i_startlb = i_block; + memcpy( p_newtitle->p_key, p_title_key, KEY_SIZE ); + + /* Link it at the head of the (possibly empty) list */ + if( p_title == NULL ) + { + p_newtitle->p_next = dvdcss->p_titles; + dvdcss->p_titles = p_newtitle; + } + /* Link the new title inside the list */ + else + { + p_newtitle->p_next = p_title->p_next; + p_title->p_next = p_newtitle; + } + + memcpy( dvdcss->css.p_title_key, p_title_key, KEY_SIZE ); + return 0; +} + +/***************************************************************************** + * _dvdcss_disckey: get disc key. + ***************************************************************************** + * This function should only be called if DVD ioctls are present. + * It will set dvdcss->i_method = DVDCSS_METHOD_TITLE if it fails to find + * a valid disc key. + * Two decryption methods are offered: + * -disc key hash crack, + * -decryption with player keys if they are available. + *****************************************************************************/ +int _dvdcss_disckey( dvdcss_t dvdcss ) +{ + unsigned char p_buffer[ DVD_DISCKEY_SIZE ]; + dvd_key_t p_disc_key; + int i; + + if( GetBusKey( dvdcss ) < 0 ) + { + return -1; + } + + /* Get encrypted disc key */ + if( ioctl_ReadDiscKey( dvdcss->i_fd, &dvdcss->css.i_agid, p_buffer ) < 0 ) + { + print_error( dvdcss, "ioctl ReadDiscKey failed" ); + return -1; + } + + /* This should have invaidated the AGID and got us ASF=1. */ + if( GetASF( dvdcss ) != 1 ) + { + /* Region mismatch (or region not set) is the most likely source. */ + print_error( dvdcss, + "ASF not 1 after reading disc key (region mismatch?)" ); + ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); + return -1; + } + + /* Shuffle disc key using bus key */ + for( i = 0 ; i < DVD_DISCKEY_SIZE ; i++ ) + { + p_buffer[ i ] ^= dvdcss->css.p_bus_key[ 4 - (i % KEY_SIZE) ]; + } + + /* Decrypt disc key */ + switch( dvdcss->i_method ) + { + case DVDCSS_METHOD_KEY: + + /* Decrypt disc key with player key. */ + PrintKey( dvdcss, "decrypting disc key ", p_buffer ); + if( ! DecryptDiscKey( dvdcss, p_buffer, p_disc_key ) ) + { + PrintKey( dvdcss, "decrypted disc key is ", p_disc_key ); + break; + } + print_debug( dvdcss, "failed to decrypt the disc key, " + "faulty drive/kernel? " + "cracking title keys instead" ); + + /* Fallback, but not to DISC as the disc key might be faulty */ + memset( p_disc_key, 0, KEY_SIZE ); + dvdcss->i_method = DVDCSS_METHOD_TITLE; + break; + + case DVDCSS_METHOD_DISC: + + /* Crack Disc key to be able to use it */ + memcpy( p_disc_key, p_buffer, KEY_SIZE ); + PrintKey( dvdcss, "cracking disc key ", p_disc_key ); + if( ! CrackDiscKey( dvdcss, p_disc_key ) ) + { + PrintKey( dvdcss, "cracked disc key is ", p_disc_key ); + break; + } + print_debug( dvdcss, "failed to crack the disc key" ); + memset( p_disc_key, 0, KEY_SIZE ); + dvdcss->i_method = DVDCSS_METHOD_TITLE; + break; + + default: + + print_debug( dvdcss, "disc key needs not be decrypted" ); + memset( p_disc_key, 0, KEY_SIZE ); + break; + } + + memcpy( dvdcss->css.p_disc_key, p_disc_key, KEY_SIZE ); + + return 0; +} + + +/***************************************************************************** + * _dvdcss_titlekey: get title key. + *****************************************************************************/ +int _dvdcss_titlekey( dvdcss_t dvdcss, int i_pos, dvd_key_t p_title_key ) +{ + static uint8_t p_garbage[ DVDCSS_BLOCK_SIZE ]; /* we never read it back */ + uint8_t p_key[ KEY_SIZE ]; + int i, i_ret = 0; + + if( dvdcss->b_ioctls && ( dvdcss->i_method == DVDCSS_METHOD_KEY || + dvdcss->i_method == DVDCSS_METHOD_DISC ) ) + { + /* We have a decrypted Disc key and the ioctls are available, + * read the title key and decrypt it. + */ + + print_debug( dvdcss, "getting title key at block %i the classic way", + i_pos ); + + /* We need to authenticate again every time to get a new session key */ + if( GetBusKey( dvdcss ) < 0 ) + { + return -1; + } + + /* Get encrypted title key */ + if( ioctl_ReadTitleKey( dvdcss->i_fd, &dvdcss->css.i_agid, + i_pos, p_key ) < 0 ) + { + print_debug( dvdcss, + "ioctl ReadTitleKey failed (region mismatch?)" ); + i_ret = -1; + } + + /* Test ASF, it will be reset to 0 if we got a Region error */ + switch( GetASF( dvdcss ) ) + { + case -1: + /* An error getting the ASF status, something must be wrong. */ + print_debug( dvdcss, "lost ASF requesting title key" ); + ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); + i_ret = -1; + break; + + case 0: + /* This might either be a title that has no key, + * or we encountered a region error. */ + print_debug( dvdcss, "lost ASF requesting title key" ); + break; + + case 1: + /* Drive status is ok. */ + /* If the title key request failed, but we did not loose ASF, + * we might stil have the AGID. Other code assume that we + * will not after this so invalidate it(?). */ + if( i_ret < 0 ) + { + ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); + } + break; + } + + if( !( i_ret < 0 ) ) + { + /* Decrypt title key using the bus key */ + for( i = 0 ; i < KEY_SIZE ; i++ ) + { + p_key[ i ] ^= dvdcss->css.p_bus_key[ 4 - (i % KEY_SIZE) ]; + } + + /* If p_key is all zero then there really wasn't any key present + * even though we got to read it without an error. */ + if( !( p_key[0] | p_key[1] | p_key[2] | p_key[3] | p_key[4] ) ) + { + i_ret = 0; + } + else + { + PrintKey( dvdcss, "initial disc key ", dvdcss->css.p_disc_key ); + DecryptTitleKey( dvdcss->css.p_disc_key, p_key ); + PrintKey( dvdcss, "decrypted title key ", p_key ); + i_ret = 1; + } + + /* All went well either there wasn't a key or we have it now. */ + memcpy( p_title_key, p_key, KEY_SIZE ); + PrintKey( dvdcss, "title key is ", p_title_key ); + + return i_ret; + } + + /* The title key request failed */ + print_debug( dvdcss, "resetting drive and cracking title key" ); + + /* Read an unscrambled sector and reset the drive */ + dvdcss->pf_seek( dvdcss, 0 ); + dvdcss->pf_read( dvdcss, p_garbage, 1 ); + dvdcss->pf_seek( dvdcss, 0 ); + _dvdcss_disckey( dvdcss ); + + /* Fallback */ + } + + /* METHOD is TITLE, we can't use the ioctls or requesting the title key + * failed above. For these cases we try to crack the key instead. */ + + /* For now, the read limit is 9Gb / 2048 = 4718592 sectors. */ + i_ret = CrackTitleKey( dvdcss, i_pos, 4718592, p_key ); + + memcpy( p_title_key, p_key, KEY_SIZE ); + PrintKey( dvdcss, "title key is ", p_title_key ); + + return i_ret; +} + +/***************************************************************************** + * _dvdcss_unscramble: does the actual descrambling of data + ***************************************************************************** + * sec : sector to unscramble + * key : title key for this sector + *****************************************************************************/ +int _dvdcss_unscramble( dvd_key_t p_key, uint8_t *p_sec ) +{ + unsigned int i_t1, i_t2, i_t3, i_t4, i_t5, i_t6; + uint8_t *p_end = p_sec + DVDCSS_BLOCK_SIZE; + + /* PES_scrambling_control */ + if( !(p_sec[0x14] & 0x30) ) + { + return 0; + } + + i_t1 = (p_key[0] ^ p_sec[0x54]) | 0x100; + i_t2 = p_key[1] ^ p_sec[0x55]; + i_t3 = (p_key[2] | (p_key[3] << 8) | + (p_key[4] << 16)) ^ (p_sec[0x56] | + (p_sec[0x57] << 8) | (p_sec[0x58] << 16)); + i_t4 = i_t3 & 7; + i_t3 = i_t3 * 2 + 8 - i_t4; + p_sec += 0x80; + i_t5 = 0; + + while( p_sec != p_end ) + { + i_t4 = p_css_tab2[i_t2] ^ p_css_tab3[i_t1]; + i_t2 = i_t1>>1; + i_t1 = ( ( i_t1 & 1 ) << 8 ) ^ i_t4; + i_t4 = p_css_tab5[i_t4]; + i_t6 = ((((((( i_t3 >> 3 ) ^ i_t3 ) >> 1 ) ^ + i_t3 ) >> 8 ) ^ i_t3 ) >> 5 ) & 0xff; + i_t3 = (i_t3 << 8 ) | i_t6; + i_t6 = p_css_tab4[i_t6]; + i_t5 += i_t6 + i_t4; + *p_sec = p_css_tab1[*p_sec] ^ ( i_t5 & 0xff ); + p_sec++; + i_t5 >>= 8; + } + + return 0; +} + +/* Following functions are local */ + +/***************************************************************************** + * GetBusKey : Go through the CSS Authentication process + ***************************************************************************** + * It simulates the mutual authentication between logical unit and host, + * and stops when a session key (called bus key) has been established. + * Always do the full auth sequence. Some drives seem to lie and always + * respond with ASF=1. For instance the old DVD roms on Compaq Armada says + * that ASF=1 from the start and then later fail with a 'read of scrambled + * block without authentication' error. + *****************************************************************************/ +static int GetBusKey( dvdcss_t dvdcss ) +{ + uint8_t p_buffer[10]; + uint8_t p_challenge[2*KEY_SIZE]; + dvd_key_t p_key1; + dvd_key_t p_key2; + dvd_key_t p_key_check; + uint8_t i_variant = 0; + int i_ret = -1; + int i; + + print_debug( dvdcss, "requesting AGID" ); + i_ret = ioctl_ReportAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); + + /* We might have to reset hung authentication processes in the drive + * by invalidating the corresponding AGID'. As long as we haven't got + * an AGID, invalidate one (in sequence) and try again. */ + for( i = 0; i_ret == -1 && i < 4 ; ++i ) + { + print_debug( dvdcss, "ioctl ReportAgid failed, " + "invalidating AGID %d", i ); + + /* This is really _not good_, should be handled by the OS. + * Invalidating an AGID could make another process fail somewhere + * in its authentication process. */ + dvdcss->css.i_agid = i; + ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); + + print_debug( dvdcss, "requesting AGID" ); + i_ret = ioctl_ReportAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); + } + + /* Unable to authenticate without AGID */ + if( i_ret == -1 ) + { + print_error( dvdcss, "ioctl ReportAgid failed, fatal" ); + return -1; + } + + /* Setup a challenge, any values should work */ + for( i = 0 ; i < 10; ++i ) + { + p_challenge[i] = i; + } + + /* Get challenge from host */ + for( i = 0 ; i < 10 ; ++i ) + { + p_buffer[9-i] = p_challenge[i]; + } + + /* Send challenge to LU */ + if( ioctl_SendChallenge( dvdcss->i_fd, + &dvdcss->css.i_agid, p_buffer ) < 0 ) + { + print_error( dvdcss, "ioctl SendChallenge failed" ); + ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); + return -1; + } + + /* Get key1 from LU */ + if( ioctl_ReportKey1( dvdcss->i_fd, &dvdcss->css.i_agid, p_buffer ) < 0) + { + print_error( dvdcss, "ioctl ReportKey1 failed" ); + ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); + return -1; + } + + /* Send key1 to host */ + for( i = 0 ; i < KEY_SIZE ; i++ ) + { + p_key1[i] = p_buffer[4-i]; + } + + for( i = 0 ; i < 32 ; ++i ) + { + CryptKey( 0, i, p_challenge, p_key_check ); + + if( memcmp( p_key_check, p_key1, KEY_SIZE ) == 0 ) + { + print_debug( dvdcss, "drive authenticated, using variant %d", i ); + i_variant = i; + break; + } + } + + if( i == 32 ) + { + print_error( dvdcss, "drive would not authenticate" ); + ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); + return -1; + } + + /* Get challenge from LU */ + if( ioctl_ReportChallenge( dvdcss->i_fd, + &dvdcss->css.i_agid, p_buffer ) < 0 ) + { + print_error( dvdcss, "ioctl ReportKeyChallenge failed" ); + ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); + return -1; + } + + /* Send challenge to host */ + for( i = 0 ; i < 10 ; ++i ) + { + p_challenge[i] = p_buffer[9-i]; + } + + CryptKey( 1, i_variant, p_challenge, p_key2 ); + + /* Get key2 from host */ + for( i = 0 ; i < KEY_SIZE ; ++i ) + { + p_buffer[4-i] = p_key2[i]; + } + + /* Send key2 to LU */ + if( ioctl_SendKey2( dvdcss->i_fd, &dvdcss->css.i_agid, p_buffer ) < 0 ) + { + print_error( dvdcss, "ioctl SendKey2 failed" ); + ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); + return -1; + } + + /* The drive has accepted us as authentic. */ + print_debug( dvdcss, "authentication established" ); + + memcpy( p_challenge, p_key1, KEY_SIZE ); + memcpy( p_challenge + KEY_SIZE, p_key2, KEY_SIZE ); + + CryptKey( 2, i_variant, p_challenge, dvdcss->css.p_bus_key ); + + return 0; +} + +/***************************************************************************** + * PrintKey : debug function that dumps a key value + *****************************************************************************/ +static void PrintKey( dvdcss_t dvdcss, char *prefix, uint8_t const *data ) +{ + print_debug( dvdcss, "%s%02x:%02x:%02x:%02x:%02x", prefix, + data[0], data[1], data[2], data[3], data[4] ); +} + +/***************************************************************************** + * GetASF : Get Authentication success flag + ***************************************************************************** + * Returns : + * -1 on ioctl error, + * 0 if the device needs to be authenticated, + * 1 either. + *****************************************************************************/ +static int GetASF( dvdcss_t dvdcss ) +{ + int i_asf = 0; + + if( ioctl_ReportASF( dvdcss->i_fd, NULL, &i_asf ) != 0 ) + { + /* The ioctl process has failed */ + print_error( dvdcss, "GetASF fatal error" ); + return -1; + } + + if( i_asf ) + { + print_debug( dvdcss, "GetASF authenticated, ASF=1" ); + } + else + { + print_debug( dvdcss, "GetASF not authenticated, ASF=0" ); + } + + return i_asf; +} + +/***************************************************************************** + * CryptKey : shuffles bits and unencrypt keys. + ***************************************************************************** + * Used during authentication and disc key negociation in GetBusKey. + * i_key_type : 0->key1, 1->key2, 2->buskey. + * i_variant : between 0 and 31. + *****************************************************************************/ +static void CryptKey( int i_key_type, int i_variant, + uint8_t const *p_challenge, uint8_t *p_key ) +{ + /* Permutation table for challenge */ + uint8_t pp_perm_challenge[3][10] = + { { 1, 3, 0, 7, 5, 2, 9, 6, 4, 8 }, + { 6, 1, 9, 3, 8, 5, 7, 4, 0, 2 }, + { 4, 0, 3, 5, 7, 2, 8, 6, 1, 9 } }; + + /* Permutation table for variant table for key2 and buskey */ + uint8_t pp_perm_variant[2][32] = + { { 0x0a, 0x08, 0x0e, 0x0c, 0x0b, 0x09, 0x0f, 0x0d, + 0x1a, 0x18, 0x1e, 0x1c, 0x1b, 0x19, 0x1f, 0x1d, + 0x02, 0x00, 0x06, 0x04, 0x03, 0x01, 0x07, 0x05, + 0x12, 0x10, 0x16, 0x14, 0x13, 0x11, 0x17, 0x15 }, + { 0x12, 0x1a, 0x16, 0x1e, 0x02, 0x0a, 0x06, 0x0e, + 0x10, 0x18, 0x14, 0x1c, 0x00, 0x08, 0x04, 0x0c, + 0x13, 0x1b, 0x17, 0x1f, 0x03, 0x0b, 0x07, 0x0f, + 0x11, 0x19, 0x15, 0x1d, 0x01, 0x09, 0x05, 0x0d } }; + + uint8_t p_variants[32] = + { 0xB7, 0x74, 0x85, 0xD0, 0xCC, 0xDB, 0xCA, 0x73, + 0x03, 0xFE, 0x31, 0x03, 0x52, 0xE0, 0xB7, 0x42, + 0x63, 0x16, 0xF2, 0x2A, 0x79, 0x52, 0xFF, 0x1B, + 0x7A, 0x11, 0xCA, 0x1A, 0x9B, 0x40, 0xAD, 0x01 }; + + /* The "secret" key */ + uint8_t p_secret[5] = { 0x55, 0xD6, 0xC4, 0xC5, 0x28 }; + + uint8_t p_bits[30], p_scratch[10], p_tmp1[5], p_tmp2[5]; + uint8_t i_lfsr0_o; /* 1 bit used */ + uint8_t i_lfsr1_o; /* 1 bit used */ + uint8_t i_css_variant, i_cse, i_index, i_combined, i_carry; + uint8_t i_val = 0; + uint32_t i_lfsr0, i_lfsr1; + int i_term = 0; + int i_bit; + int i; + + for (i = 9; i >= 0; --i) + p_scratch[i] = p_challenge[pp_perm_challenge[i_key_type][i]]; + + i_css_variant = ( i_key_type == 0 ) ? i_variant : + pp_perm_variant[i_key_type-1][i_variant]; + + /* + * This encryption engine implements one of 32 variations + * one the same theme depending upon the choice in the + * variant parameter (0 - 31). + * + * The algorithm itself manipulates a 40 bit input into + * a 40 bit output. + * The parameter 'input' is 80 bits. It consists of + * the 40 bit input value that is to be encrypted followed + * by a 40 bit seed value for the pseudo random number + * generators. + */ + + /* Feed the secret into the input values such that + * we alter the seed to the LFSR's used above, then + * generate the bits to play with. + */ + for( i = 5 ; --i >= 0 ; ) + { + p_tmp1[i] = p_scratch[5 + i] ^ p_secret[i] ^ p_crypt_tab2[i]; + } + + /* + * We use two LFSR's (seeded from some of the input data bytes) to + * generate two streams of pseudo-random bits. These two bit streams + * are then combined by simply adding with carry to generate a final + * sequence of pseudo-random bits which is stored in the buffer that + * 'output' points to the end of - len is the size of this buffer. + * + * The first LFSR is of degree 25, and has a polynomial of: + * x^13 + x^5 + x^4 + x^1 + 1 + * + * The second LSFR is of degree 17, and has a (primitive) polynomial of: + * x^15 + x^1 + 1 + * + * I don't know if these polynomials are primitive modulo 2, and thus + * represent maximal-period LFSR's. + * + * + * Note that we take the output of each LFSR from the new shifted in + * bit, not the old shifted out bit. Thus for ease of use the LFSR's + * are implemented in bit reversed order. + * + */ + + /* In order to ensure that the LFSR works we need to ensure that the + * initial values are non-zero. Thus when we initialise them from + * the seed, we ensure that a bit is set. + */ + i_lfsr0 = ( p_tmp1[0] << 17 ) | ( p_tmp1[1] << 9 ) | + (( p_tmp1[2] & ~7 ) << 1 ) | 8 | ( p_tmp1[2] & 7 ); + i_lfsr1 = ( p_tmp1[3] << 9 ) | 0x100 | p_tmp1[4]; + + i_index = sizeof(p_bits); + i_carry = 0; + + do + { + for( i_bit = 0, i_val = 0 ; i_bit < 8 ; ++i_bit ) + { + + i_lfsr0_o = ( ( i_lfsr0 >> 24 ) ^ ( i_lfsr0 >> 21 ) ^ + ( i_lfsr0 >> 20 ) ^ ( i_lfsr0 >> 12 ) ) & 1; + i_lfsr0 = ( i_lfsr0 << 1 ) | i_lfsr0_o; + + i_lfsr1_o = ( ( i_lfsr1 >> 16 ) ^ ( i_lfsr1 >> 2 ) ) & 1; + i_lfsr1 = ( i_lfsr1 << 1 ) | i_lfsr1_o; + + i_combined = !i_lfsr1_o + i_carry + !i_lfsr0_o; + /* taking bit 1 */ + i_carry = ( i_combined >> 1 ) & 1; + i_val |= ( i_combined & 1 ) << i_bit; + } + + p_bits[--i_index] = i_val; + } while( i_index > 0 ); + + /* This term is used throughout the following to + * select one of 32 different variations on the + * algorithm. + */ + i_cse = p_variants[i_css_variant] ^ p_crypt_tab2[i_css_variant]; + + /* Now the actual blocks doing the encryption. Each + * of these works on 40 bits at a time and are quite + * similar. + */ + i_index = 0; + for( i = 5, i_term = 0 ; --i >= 0 ; i_term = p_scratch[i] ) + { + i_index = p_bits[25 + i] ^ p_scratch[i]; + i_index = p_crypt_tab1[i_index] ^ ~p_crypt_tab2[i_index] ^ i_cse; + + p_tmp1[i] = p_crypt_tab2[i_index] ^ p_crypt_tab3[i_index] ^ i_term; + } + p_tmp1[4] ^= p_tmp1[0]; + + for( i = 5, i_term = 0 ; --i >= 0 ; i_term = p_tmp1[i] ) + { + i_index = p_bits[20 + i] ^ p_tmp1[i]; + i_index = p_crypt_tab1[i_index] ^ ~p_crypt_tab2[i_index] ^ i_cse; + + p_tmp2[i] = p_crypt_tab2[i_index] ^ p_crypt_tab3[i_index] ^ i_term; + } + p_tmp2[4] ^= p_tmp2[0]; + + for( i = 5, i_term = 0 ; --i >= 0 ; i_term = p_tmp2[i] ) + { + i_index = p_bits[15 + i] ^ p_tmp2[i]; + i_index = p_crypt_tab1[i_index] ^ ~p_crypt_tab2[i_index] ^ i_cse; + i_index = p_crypt_tab2[i_index] ^ p_crypt_tab3[i_index] ^ i_term; + + p_tmp1[i] = p_crypt_tab0[i_index] ^ p_crypt_tab2[i_index]; + } + p_tmp1[4] ^= p_tmp1[0]; + + for( i = 5, i_term = 0 ; --i >= 0 ; i_term = p_tmp1[i] ) + { + i_index = p_bits[10 + i] ^ p_tmp1[i]; + i_index = p_crypt_tab1[i_index] ^ ~p_crypt_tab2[i_index] ^ i_cse; + + i_index = p_crypt_tab2[i_index] ^ p_crypt_tab3[i_index] ^ i_term; + + p_tmp2[i] = p_crypt_tab0[i_index] ^ p_crypt_tab2[i_index]; + } + p_tmp2[4] ^= p_tmp2[0]; + + for( i = 5, i_term = 0 ; --i >= 0 ; i_term = p_tmp2[i] ) + { + i_index = p_bits[5 + i] ^ p_tmp2[i]; + i_index = p_crypt_tab1[i_index] ^ ~p_crypt_tab2[i_index] ^ i_cse; + + p_tmp1[i] = p_crypt_tab2[i_index] ^ p_crypt_tab3[i_index] ^ i_term; + } + p_tmp1[4] ^= p_tmp1[0]; + + for(i = 5, i_term = 0 ; --i >= 0 ; i_term = p_tmp1[i] ) + { + i_index = p_bits[i] ^ p_tmp1[i]; + i_index = p_crypt_tab1[i_index] ^ ~p_crypt_tab2[i_index] ^ i_cse; + + p_key[i] = p_crypt_tab2[i_index] ^ p_crypt_tab3[i_index] ^ i_term; + } + + return; +} + +/***************************************************************************** + * DecryptKey: decrypt p_crypted with p_key. + ***************************************************************************** + * Used to decrypt the disc key, with a player key, after requesting it + * in _dvdcss_disckey and to decrypt title keys, with a disc key, requested + * in _dvdcss_titlekey. + * The player keys and the resulting disc key are only used as KEKs + * (key encryption keys). + * Decryption is slightly dependant on the type of key: + * -for disc key, invert is 0x00, + * -for title key, invert if 0xff. + *****************************************************************************/ +static void DecryptKey( uint8_t invert, uint8_t const *p_key, + uint8_t const *p_crypted, uint8_t *p_result ) +{ + unsigned int i_lfsr1_lo; + unsigned int i_lfsr1_hi; + unsigned int i_lfsr0; + unsigned int i_combined; + uint8_t o_lfsr0; + uint8_t o_lfsr1; + uint8_t k[5]; + int i; + + i_lfsr1_lo = p_key[0] | 0x100; + i_lfsr1_hi = p_key[1]; + + i_lfsr0 = ( ( p_key[4] << 17 ) + | ( p_key[3] << 9 ) + | ( p_key[2] << 1 ) ) + + 8 - ( p_key[2] & 7 ); + i_lfsr0 = ( p_css_tab4[i_lfsr0 & 0xff] << 24 ) | + ( p_css_tab4[( i_lfsr0 >> 8 ) & 0xff] << 16 ) | + ( p_css_tab4[( i_lfsr0 >> 16 ) & 0xff] << 8 ) | + p_css_tab4[( i_lfsr0 >> 24 ) & 0xff]; + + i_combined = 0; + for( i = 0 ; i < KEY_SIZE ; ++i ) + { + o_lfsr1 = p_css_tab2[i_lfsr1_hi] ^ p_css_tab3[i_lfsr1_lo]; + i_lfsr1_hi = i_lfsr1_lo >> 1; + i_lfsr1_lo = ( ( i_lfsr1_lo & 1 ) << 8 ) ^ o_lfsr1; + o_lfsr1 = p_css_tab4[o_lfsr1]; + + o_lfsr0 = ((((((( i_lfsr0 >> 8 ) ^ i_lfsr0 ) >> 1 ) + ^ i_lfsr0 ) >> 3 ) ^ i_lfsr0 ) >> 7 ); + i_lfsr0 = ( i_lfsr0 >> 8 ) | ( o_lfsr0 << 24 ); + + i_combined += ( o_lfsr0 ^ invert ) + o_lfsr1; + k[i] = i_combined & 0xff; + i_combined >>= 8; + } + + p_result[4] = k[4] ^ p_css_tab1[p_crypted[4]] ^ p_crypted[3]; + p_result[3] = k[3] ^ p_css_tab1[p_crypted[3]] ^ p_crypted[2]; + p_result[2] = k[2] ^ p_css_tab1[p_crypted[2]] ^ p_crypted[1]; + p_result[1] = k[1] ^ p_css_tab1[p_crypted[1]] ^ p_crypted[0]; + p_result[0] = k[0] ^ p_css_tab1[p_crypted[0]] ^ p_result[4]; + + p_result[4] = k[4] ^ p_css_tab1[p_result[4]] ^ p_result[3]; + p_result[3] = k[3] ^ p_css_tab1[p_result[3]] ^ p_result[2]; + p_result[2] = k[2] ^ p_css_tab1[p_result[2]] ^ p_result[1]; + p_result[1] = k[1] ^ p_css_tab1[p_result[1]] ^ p_result[0]; + p_result[0] = k[0] ^ p_css_tab1[p_result[0]]; + + return; +} + +/***************************************************************************** + * player_keys: alternate DVD player keys + ***************************************************************************** + * These player keys were generated using Frank A. Stevenson's PlayerKey + * cracker. A copy of his article can be found here: + * http://www-2.cs.cmu.edu/~dst/DeCSS/FrankStevenson/mail2.txt + *****************************************************************************/ +static const dvd_key_t player_keys[] = +{ + { 0x01, 0xaf, 0xe3, 0x12, 0x80 }, + { 0x12, 0x11, 0xca, 0x04, 0x3b }, + { 0x14, 0x0c, 0x9e, 0xd0, 0x09 }, + { 0x14, 0x71, 0x35, 0xba, 0xe2 }, + { 0x1a, 0xa4, 0x33, 0x21, 0xa6 }, + { 0x26, 0xec, 0xc4, 0xa7, 0x4e }, + { 0x2c, 0xb2, 0xc1, 0x09, 0xee }, + { 0x2f, 0x25, 0x9e, 0x96, 0xdd }, + { 0x33, 0x2f, 0x49, 0x6c, 0xe0 }, + { 0x35, 0x5b, 0xc1, 0x31, 0x0f }, + { 0x36, 0x67, 0xb2, 0xe3, 0x85 }, + { 0x39, 0x3d, 0xf1, 0xf1, 0xbd }, + { 0x3b, 0x31, 0x34, 0x0d, 0x91 }, + { 0x45, 0xed, 0x28, 0xeb, 0xd3 }, + { 0x48, 0xb7, 0x6c, 0xce, 0x69 }, + { 0x4b, 0x65, 0x0d, 0xc1, 0xee }, + { 0x4c, 0xbb, 0xf5, 0x5b, 0x23 }, + { 0x51, 0x67, 0x67, 0xc5, 0xe0 }, + { 0x53, 0x94, 0xe1, 0x75, 0xbf }, + { 0x57, 0x2c, 0x8b, 0x31, 0xae }, + { 0x63, 0xdb, 0x4c, 0x5b, 0x4a }, + { 0x7b, 0x1e, 0x5e, 0x2b, 0x57 }, + { 0x85, 0xf3, 0x85, 0xa0, 0xe0 }, + { 0xab, 0x1e, 0xe7, 0x7b, 0x72 }, + { 0xab, 0x36, 0xe3, 0xeb, 0x76 }, + { 0xb1, 0xb8, 0xf9, 0x38, 0x03 }, + { 0xb8, 0x5d, 0xd8, 0x53, 0xbd }, + { 0xbf, 0x92, 0xc3, 0xb0, 0xe2 }, + { 0xcf, 0x1a, 0xb2, 0xf8, 0x0a }, + { 0xec, 0xa0, 0xcf, 0xb3, 0xff }, + { 0xfc, 0x95, 0xa9, 0x87, 0x35 } +}; + +/***************************************************************************** + * DecryptDiscKey + ***************************************************************************** + * Decryption of the disc key with player keys: try to decrypt the disc key + * from every position with every player key. + * p_struct_disckey: the 2048 byte DVD_STRUCT_DISCKEY data + * p_disc_key: result, the 5 byte disc key + *****************************************************************************/ +static int DecryptDiscKey( dvdcss_t dvdcss, uint8_t const *p_struct_disckey, + dvd_key_t p_disc_key ) +{ + uint8_t p_verify[KEY_SIZE]; + unsigned int i, n = 0; + + /* Decrypt disc key with the above player keys */ + for( n = 0; n < sizeof(player_keys) / sizeof(dvd_key_t); n++ ) + { + PrintKey( dvdcss, "trying player key ", player_keys[n] ); + + for( i = 1; i < 409; i++ ) + { + /* Check if player key n is the right key for position i. */ + DecryptKey( 0, player_keys[n], p_struct_disckey + 5 * i, + p_disc_key ); + + /* The first part in the struct_disckey block is the + * 'disc key' encrypted with itself. Using this we + * can check if we decrypted the correct key. */ + DecryptKey( 0, p_disc_key, p_struct_disckey, p_verify ); + + /* If the position / player key pair worked then return. */ + if( memcmp( p_disc_key, p_verify, KEY_SIZE ) == 0 ) + { + return 0; + } + } + } + + /* Have tried all combinations of positions and keys, + * and we still didn't succeed. */ + memset( p_disc_key, 0, KEY_SIZE ); + return -1; +} + +/***************************************************************************** + * DecryptTitleKey + ***************************************************************************** + * Decrypt the title key using the disc key. + * p_disc_key: result, the 5 byte disc key + * p_titlekey: the encrypted title key, gets overwritten by the decrypted key + *****************************************************************************/ +static void DecryptTitleKey( dvd_key_t p_disc_key, dvd_key_t p_titlekey ) +{ + DecryptKey( 0xff, p_disc_key, p_titlekey, p_titlekey ); +} + +/***************************************************************************** + * CrackDiscKey: brute force disc key + * CSS hash reversal function designed by Frank Stevenson + ***************************************************************************** + * This function uses a big amount of memory to crack the disc key from the + * disc key hash, if player keys are not available. + *****************************************************************************/ +#define K1TABLEWIDTH 10 + +/* + * Simple function to test if a candidate key produces the given hash + */ +static int investigate( unsigned char *hash, unsigned char *ckey ) +{ + unsigned char key[KEY_SIZE]; + + DecryptKey( 0, ckey, hash, key ); + + return memcmp( key, ckey, KEY_SIZE ); +} + +static int CrackDiscKey( dvdcss_t dvdcss, uint8_t *p_disc_key ) +{ + unsigned char B[5] = { 0,0,0,0,0 }; /* Second Stage of mangle cipher */ + unsigned char C[5] = { 0,0,0,0,0 }; /* Output Stage of mangle cipher + * IntermediateKey */ + unsigned char k[5] = { 0,0,0,0,0 }; /* Mangling cipher key + * Also output from CSS( C ) */ + unsigned char out1[5]; /* five first output bytes of LFSR1 */ + unsigned char out2[5]; /* five first output bytes of LFSR2 */ + unsigned int lfsr1a; /* upper 9 bits of LFSR1 */ + unsigned int lfsr1b; /* lower 8 bits of LFSR1 */ + unsigned int tmp, tmp2, tmp3, tmp4,tmp5; + int i,j; + unsigned int nStepA; /* iterator for LFSR1 start state */ + unsigned int nStepB; /* iterator for possible B[0] */ + unsigned int nTry; /* iterator for K[1] possibilities */ + unsigned int nPossibleK1; /* #of possible K[1] values */ + unsigned char* K1table; /* Lookup table for possible K[1] */ + unsigned int* BigTable; /* LFSR2 startstate indexed by + * 1,2,5 output byte */ + + /* + * Prepare tables for hash reversal + */ + + /* initialize lookup tables for k[1] */ + K1table = malloc( 65536 * K1TABLEWIDTH ); + memset( K1table, 0 , 65536 * K1TABLEWIDTH ); + if( K1table == NULL ) + { + return -1; + } + + tmp = p_disc_key[0] ^ p_css_tab1[ p_disc_key[1] ]; + for( i = 0 ; i < 256 ; i++ ) /* k[1] */ + { + tmp2 = p_css_tab1[ tmp ^ i ]; /* p_css_tab1[ B[1] ]*/ + + for( j = 0 ; j < 256 ; j++ ) /* B[0] */ + { + tmp3 = j ^ tmp2 ^ i; /* C[1] */ + tmp4 = K1table[ K1TABLEWIDTH * ( 256 * j + tmp3 ) ]; /* count of entries here */ + tmp4++; +/* + if( tmp4 == K1TABLEWIDTH ) + { + print_debug( dvdcss, "Table disaster %d", tmp4 ); + } +*/ + if( tmp4 < K1TABLEWIDTH ) + { + K1table[ K1TABLEWIDTH * ( 256 * j + tmp3 ) + tmp4 ] = i; + } + K1table[ K1TABLEWIDTH * ( 256 * j + tmp3 ) ] = tmp4; + } + } + + /* Initing our Really big table */ + BigTable = malloc( 16777216 * sizeof(int) ); + memset( BigTable, 0 , 16777216 * sizeof(int) ); + if( BigTable == NULL ) + { + return -1; + } + + tmp3 = 0; + + print_debug( dvdcss, "initializing the big table" ); + + for( i = 0 ; i < 16777216 ; i++ ) + { + tmp = (( i + i ) & 0x1fffff0 ) | 0x8 | ( i & 0x7 ); + + for( j = 0 ; j < 5 ; j++ ) + { + tmp2=((((((( tmp >> 3 ) ^ tmp ) >> 1 ) ^ tmp ) >> 8 ) + ^ tmp ) >> 5 ) & 0xff; + tmp = ( tmp << 8) | tmp2; + out2[j] = p_css_tab4[ tmp2 ]; + } + + j = ( out2[0] << 16 ) | ( out2[1] << 8 ) | out2[4]; + BigTable[j] = i; + } + + /* + * We are done initing, now reverse hash + */ + tmp5 = p_disc_key[0] ^ p_css_tab1[ p_disc_key[1] ]; + + for( nStepA = 0 ; nStepA < 65536 ; nStepA ++ ) + { + lfsr1a = 0x100 | ( nStepA >> 8 ); + lfsr1b = nStepA & 0xff; + + /* Generate 5 first output bytes from lfsr1 */ + for( i = 0 ; i < 5 ; i++ ) + { + tmp = p_css_tab2[ lfsr1b ] ^ p_css_tab3[ lfsr1a ]; + lfsr1b = lfsr1a >> 1; + lfsr1a = ((lfsr1a&1)<<8) ^ tmp; + out1[ i ] = p_css_tab4[ tmp ]; + } + + /* cumpute and cache some variables */ + C[0] = nStepA >> 8; + C[1] = nStepA & 0xff; + tmp = p_disc_key[3] ^ p_css_tab1[ p_disc_key[4] ]; + tmp2 = p_css_tab1[ p_disc_key[0] ]; + + /* Search through all possible B[0] */ + for( nStepB = 0 ; nStepB < 256 ; nStepB++ ) + { + /* reverse parts of the mangling cipher */ + B[0] = nStepB; + k[0] = p_css_tab1[ B[0] ] ^ C[0]; + B[4] = B[0] ^ k[0] ^ tmp2; + k[4] = B[4] ^ tmp; + nPossibleK1 = K1table[ K1TABLEWIDTH * (256 * B[0] + C[1]) ]; + + /* Try out all possible values for k[1] */ + for( nTry = 0 ; nTry < nPossibleK1 ; nTry++ ) + { + k[1] = K1table[ K1TABLEWIDTH * (256 * B[0] + C[1]) + nTry + 1 ]; + B[1] = tmp5 ^ k[1]; + + /* reconstruct output from LFSR2 */ + tmp3 = ( 0x100 + k[0] - out1[0] ); + out2[0] = tmp3 & 0xff; + tmp3 = tmp3 & 0x100 ? 0x100 : 0xff; + tmp3 = ( tmp3 + k[1] - out1[1] ); + out2[1] = tmp3 & 0xff; + tmp3 = ( 0x100 + k[4] - out1[4] ); + out2[4] = tmp3 & 0xff; /* Can be 1 off */ + + /* test first possible out2[4] */ + tmp4 = ( out2[0] << 16 ) | ( out2[1] << 8 ) | out2[4]; + tmp4 = BigTable[ tmp4 ]; + C[2] = tmp4 & 0xff; + C[3] = ( tmp4 >> 8 ) & 0xff; + C[4] = ( tmp4 >> 16 ) & 0xff; + B[3] = p_css_tab1[ B[4] ] ^ k[4] ^ C[4]; + k[3] = p_disc_key[2] ^ p_css_tab1[ p_disc_key[3] ] ^ B[3]; + B[2] = p_css_tab1[ B[3] ] ^ k[3] ^ C[3]; + k[2] = p_disc_key[1] ^ p_css_tab1[ p_disc_key[2] ] ^ B[2]; + + if( ( B[1] ^ p_css_tab1[ B[2] ] ^ k[ 2 ] ) == C[ 2 ] ) + { + if( ! investigate( &p_disc_key[0] , &C[0] ) ) + { + goto end; + } + } + + /* Test second possible out2[4] */ + out2[4] = ( out2[4] + 0xff ) & 0xff; + tmp4 = ( out2[0] << 16 ) | ( out2[1] << 8 ) | out2[4]; + tmp4 = BigTable[ tmp4 ]; + C[2] = tmp4 & 0xff; + C[3] = ( tmp4 >> 8 ) & 0xff; + C[4] = ( tmp4 >> 16 ) & 0xff; + B[3] = p_css_tab1[ B[4] ] ^ k[4] ^ C[4]; + k[3] = p_disc_key[2] ^ p_css_tab1[ p_disc_key[3] ] ^ B[3]; + B[2] = p_css_tab1[ B[3] ] ^ k[3] ^ C[3]; + k[2] = p_disc_key[1] ^ p_css_tab1[ p_disc_key[2] ] ^ B[2]; + + if( ( B[1] ^ p_css_tab1[ B[2] ] ^ k[ 2 ] ) == C[ 2 ] ) + { + if( ! investigate( &p_disc_key[0] , &C[0] ) ) + { + goto end; + } + } + } + } + } + +end: + + memcpy( p_disc_key, &C[0], KEY_SIZE ); + + free( K1table ); + free( BigTable ); + + return 0; +} + +/***************************************************************************** + * RecoverTitleKey: (title) key recovery from cipher and plain text + * Function designed by Frank Stevenson + ***************************************************************************** + * Called from Attack* which are in turn called by CrackTitleKey. Given + * a guessed(?) plain text and the cipher text. Returns -1 on failure. + *****************************************************************************/ +static int RecoverTitleKey( int i_start, uint8_t const *p_crypted, + uint8_t const *p_decrypted, + uint8_t const *p_sector_seed, uint8_t *p_key ) +{ + uint8_t p_buffer[10]; + unsigned int i_t1, i_t2, i_t3, i_t4, i_t5, i_t6; + unsigned int i_try; + unsigned int i_candidate; + unsigned int i, j; + int i_exit = -1; + + for( i = 0 ; i < 10 ; i++ ) + { + p_buffer[i] = p_css_tab1[p_crypted[i]] ^ p_decrypted[i]; + } + + for( i_try = i_start ; i_try < 0x10000 ; i_try++ ) + { + i_t1 = i_try >> 8 | 0x100; + i_t2 = i_try & 0xff; + i_t3 = 0; /* not needed */ + i_t5 = 0; + + /* iterate cipher 4 times to reconstruct LFSR2 */ + for( i = 0 ; i < 4 ; i++ ) + { + /* advance LFSR1 normaly */ + i_t4 = p_css_tab2[i_t2] ^ p_css_tab3[i_t1]; + i_t2 = i_t1 >> 1; + i_t1 = ( ( i_t1 & 1 ) << 8 ) ^ i_t4; + i_t4 = p_css_tab5[i_t4]; + /* deduce i_t6 & i_t5 */ + i_t6 = p_buffer[i]; + if( i_t5 ) + { + i_t6 = ( i_t6 + 0xff ) & 0x0ff; + } + if( i_t6 < i_t4 ) + { + i_t6 += 0x100; + } + i_t6 -= i_t4; + i_t5 += i_t6 + i_t4; + i_t6 = p_css_tab4[ i_t6 ]; + /* feed / advance i_t3 / i_t5 */ + i_t3 = ( i_t3 << 8 ) | i_t6; + i_t5 >>= 8; + } + + i_candidate = i_t3; + + /* iterate 6 more times to validate candidate key */ + for( ; i < 10 ; i++ ) + { + i_t4 = p_css_tab2[i_t2] ^ p_css_tab3[i_t1]; + i_t2 = i_t1 >> 1; + i_t1 = ( ( i_t1 & 1 ) << 8 ) ^ i_t4; + i_t4 = p_css_tab5[i_t4]; + i_t6 = ((((((( i_t3 >> 3 ) ^ i_t3 ) >> 1 ) ^ + i_t3 ) >> 8 ) ^ i_t3 ) >> 5 ) & 0xff; + i_t3 = ( i_t3 << 8 ) | i_t6; + i_t6 = p_css_tab4[i_t6]; + i_t5 += i_t6 + i_t4; + if( ( i_t5 & 0xff ) != p_buffer[i] ) + { + break; + } + + i_t5 >>= 8; + } + + if( i == 10 ) + { + /* Do 4 backwards steps of iterating t3 to deduce initial state */ + i_t3 = i_candidate; + for( i = 0 ; i < 4 ; i++ ) + { + i_t1 = i_t3 & 0xff; + i_t3 = ( i_t3 >> 8 ); + /* easy to code, and fast enough bruteforce + * search for byte shifted in */ + for( j = 0 ; j < 256 ; j++ ) + { + i_t3 = ( i_t3 & 0x1ffff ) | ( j << 17 ); + i_t6 = ((((((( i_t3 >> 3 ) ^ i_t3 ) >> 1 ) ^ + i_t3 ) >> 8 ) ^ i_t3 ) >> 5 ) & 0xff; + if( i_t6 == i_t1 ) + { + break; + } + } + } + + i_t4 = ( i_t3 >> 1 ) - 4; + for( i_t5 = 0 ; i_t5 < 8; i_t5++ ) + { + if( ( ( i_t4 + i_t5 ) * 2 + 8 - ( (i_t4 + i_t5 ) & 7 ) ) + == i_t3 ) + { + p_key[0] = i_try>>8; + p_key[1] = i_try & 0xFF; + p_key[2] = ( ( i_t4 + i_t5 ) >> 0 ) & 0xFF; + p_key[3] = ( ( i_t4 + i_t5 ) >> 8 ) & 0xFF; + p_key[4] = ( ( i_t4 + i_t5 ) >> 16 ) & 0xFF; + i_exit = i_try + 1; + } + } + } + } + + if( i_exit >= 0 ) + { + p_key[0] ^= p_sector_seed[0]; + p_key[1] ^= p_sector_seed[1]; + p_key[2] ^= p_sector_seed[2]; + p_key[3] ^= p_sector_seed[3]; + p_key[4] ^= p_sector_seed[4]; + } + + return i_exit; +} + + +/****************************************************************************** + * Various pieces for the title crack engine. + ****************************************************************************** + * The length of the PES packet is located at 0x12-0x13. + * The the copyrigth protection bits are located at 0x14 (bits 0x20 and 0x10). + * The data of the PES packet begins at 0x15 (if there isn't any PTS/DTS) + * or at 0x?? if there are both PTS and DTS's. + * The seed value used with the unscrambling key is the 5 bytes at 0x54-0x58. + * The scrabled part of a sector begins at 0x80. + *****************************************************************************/ + +/* Statistics */ +static int i_tries = 0, i_success = 0; + +/***************************************************************************** + * CrackTitleKey: try to crack title key from the contents of a VOB. + ***************************************************************************** + * This function is called by _dvdcss_titlekey to find a title key, if we've + * chosen to crack title key instead of decrypting it with the disc key. + * The DVD should have been opened and be in an authenticated state. + * i_pos is the starting sector, i_len is the maximum number of sectors to read + *****************************************************************************/ +static int CrackTitleKey( dvdcss_t dvdcss, int i_pos, int i_len, + dvd_key_t p_titlekey ) +{ + uint8_t p_buf[ DVDCSS_BLOCK_SIZE ]; + const uint8_t p_packstart[4] = { 0x00, 0x00, 0x01, 0xba }; + int i_reads = 0; + int i_encrypted = 0; + int b_stop_scanning = 0; + int b_read_error = 0; + int i_ret; + + print_debug( dvdcss, "cracking title key at block %i", i_pos ); + + i_tries = 0; + i_success = 0; + + do + { + i_ret = dvdcss->pf_seek( dvdcss, i_pos ); + + if( i_ret != i_pos ) + { + print_error( dvdcss, "seek failed" ); + } + + i_ret = dvdcss_read( dvdcss, p_buf, 1, DVDCSS_NOFLAGS ); + + /* Either we are at the end of the physical device or the auth + * have failed / were not done and we got a read error. */ + if( i_ret <= 0 ) + { + if( i_ret == 0 ) + { + print_debug( dvdcss, "read returned 0 (end of device?)" ); + } + else if( !b_read_error ) + { + print_debug( dvdcss, "read error at block %i, resorting to " + "secret arcanes to recover", i_pos ); + + /* Reset the drive before trying to continue */ + _dvdcss_close( dvdcss ); + _dvdcss_open( dvdcss ); + + b_read_error = 1; + continue; + } + break; + } + + /* Stop when we find a non MPEG stream block. + * (We must have reached the end of the stream). + * For now, allow all blocks that begin with a start code. */ + if( memcmp( p_buf, p_packstart, 3 ) ) + { + print_debug( dvdcss, "non MPEG block found at block %i " + "(end of title)", i_pos ); + break; + } + + if( p_buf[0x0d] & 0x07 ) + print_debug( dvdcss, "stuffing in pack header" ); + + /* PES_scrambling_control does not exist in a system_header, + * a padding_stream or a private_stream2 (and others?). */ + if( p_buf[0x14] & 0x30 && ! ( p_buf[0x11] == 0xbb + || p_buf[0x11] == 0xbe + || p_buf[0x11] == 0xbf ) ) + { + i_encrypted++; + + if( AttackPattern(p_buf, i_reads, p_titlekey) > 0 ) + { + b_stop_scanning = 1; + } +#if 0 + if( AttackPadding(p_buf, i_reads, p_titlekey) > 0 ) + { + b_stop_scanning = 1; + } +#endif + } + + i_pos++; + i_len--; + i_reads++; + + /* Emit a progress indication now and then. */ + if( !( i_reads & 0xfff ) ) + { + print_debug( dvdcss, "at block %i, still cracking...", i_pos ); + } + + /* Stop after 2000 blocks if we haven't seen any encrypted blocks. */ + if( i_reads >= 2000 && i_encrypted == 0 ) break; + + } while( !b_stop_scanning && i_len > 0); + + if( !b_stop_scanning ) + { + print_debug( dvdcss, "end of title reached" ); + } + + /* Print some statistics. */ + print_debug( dvdcss, "successful attempts %d/%d, scrambled blocks %d/%d", + i_success, i_tries, i_encrypted, i_reads ); + + if( i_success > 0 /* b_stop_scanning */ ) + { + print_debug( dvdcss, "vts key initialized" ); + return 1; + } + + if( i_encrypted == 0 && i_reads > 0 ) + { + memset( p_titlekey, 0, KEY_SIZE ); + print_debug( dvdcss, "no scrambled sectors found" ); + return 0; + } + + memset( p_titlekey, 0, KEY_SIZE ); + return -1; +} + + +/****************************************************************************** + * The original Ethan Hawke (DeCSSPlus) attack (modified). + ****************************************************************************** + * Tries to find a repeating pattern just before the encrypted part starts. + * Then it guesses that the plain text for first encrypted bytes are + * a contiuation of that pattern. + *****************************************************************************/ +static int AttackPattern( uint8_t const p_sec[ DVDCSS_BLOCK_SIZE ], + int i_pos, uint8_t *p_key ) +{ + unsigned int i_best_plen = 0; + unsigned int i_best_p = 0; + unsigned int i, j; + + /* For all cycle length from 2 to 48 */ + for( i = 2 ; i < 0x30 ; i++ ) + { + /* Find the number of bytes that repeats in cycles. */ + for( j = i + 1; + j < 0x80 && ( p_sec[0x7F - (j%i)] == p_sec[0x7F - j] ); + j++ ) + { + /* We have found j repeating bytes with a cycle length i. */ + if( j > i_best_plen ) + { + i_best_plen = j; + i_best_p = i; + } + } + } + + /* We need at most 10 plain text bytes?, so a make sure that we + * have at least 20 repeated bytes and that they have cycled at + * least one time. */ + if( ( i_best_plen > 3 ) && ( i_best_plen / i_best_p >= 2) ) + { + int res; + + i_tries++; + memset( p_key, 0, KEY_SIZE ); + res = RecoverTitleKey( 0, &p_sec[0x80], + &p_sec[ 0x80 - (i_best_plen / i_best_p) * i_best_p ], + &p_sec[0x54] /* key_seed */, p_key ); + i_success += ( res >= 0 ); +#if 0 + if( res >= 0 ) + { + fprintf( stderr, "key is %02x:%02x:%02x:%02x:%02x ", + p_key[0], p_key[1], p_key[2], p_key[3], p_key[4] ); + fprintf( stderr, "at block %5d pattern len %3d period %3d %s\n", + i_pos, i_best_plen, i_best_p, (res>=0?"y":"n") ); + } +#endif + return ( res >= 0 ); + } + + return 0; +} + + +#if 0 +/****************************************************************************** + * Encrypted Padding_stream attack. + ****************************************************************************** + * DVD specifies that there must only be one type of data in every sector. + * Every sector is one pack and so must obviously be 2048 bytes long. + * For the last pice of video data before a VOBU boundary there might not + * be exactly the right amount of data to fill a sector. Then one has to + * pad the pack to 2048 bytes. For just a few bytes this is done in the + * header but for any large amount you insert a PES packet from the + * Padding stream. This looks like 0x00 00 01 be xx xx ff ff ... + * where xx xx is the length of the padding stream. + *****************************************************************************/ +static int AttackPadding( uint8_t const p_sec[ DVDCSS_BLOCK_SIZE ], + int i_pos, uint8_t *p_key ) +{ + unsigned int i_pes_length; + /*static int i_tries = 0, i_success = 0;*/ + + i_pes_length = (p_sec[0x12]<<8) | p_sec[0x13]; + + /* Coverd by the test below but usfull for debuging. */ + if( i_pes_length == DVDCSS_BLOCK_SIZE - 0x14 ) return 0; + + /* There must be room for at least 4? bytes of padding stream, + * and it must be encrypted. + * sector size - pack/pes header - padding startcode - padding length */ + if( ( DVDCSS_BLOCK_SIZE - 0x14 - 4 - 2 - i_pes_length < 4 ) || + ( p_sec[0x14 + i_pes_length + 0] == 0x00 && + p_sec[0x14 + i_pes_length + 1] == 0x00 && + p_sec[0x14 + i_pes_length + 2] == 0x01 ) ) + { + fprintf( stderr, "plain %d %02x:%02x:%02x:%02x (type %02x sub %02x)\n", + DVDCSS_BLOCK_SIZE - 0x14 - 4 - 2 - i_pes_length, + p_sec[0x14 + i_pes_length + 0], + p_sec[0x14 + i_pes_length + 1], + p_sec[0x14 + i_pes_length + 2], + p_sec[0x14 + i_pes_length + 3], + p_sec[0x11], p_sec[0x17 + p_sec[0x16]]); + return 0; + } + + /* If we are here we know that there is a where in the pack a + encrypted PES header is (startcode + length). It's never more + than two packets in the pack, so we 'know' the length. The + plaintext at offset (0x14 + i_pes_length) will then be + 00 00 01 e0/bd/be xx xx, in the case of be the following bytes + are also known. */ + + /* An encrypted SPU PES packet with another encrypted PES packet following. + Normaly if the following was a padding stream that would be in plain + text. So it will be another SPU PES packet. */ + if( p_sec[0x11] == 0xbd && + p_sec[0x17 + p_sec[0x16]] >= 0x20 && + p_sec[0x17 + p_sec[0x16]] <= 0x3f ) + { + i_tries++; + } + + /* A Video PES packet with another encrypted PES packet following. + * No reason execpt for time stamps to break the data into two packets. + * So it's likely that the following PES packet is a padding stream. */ + if( p_sec[0x11] == 0xe0 ) + { + i_tries++; + } + + if( 1 ) + { + /*fprintf( stderr, "key is %02x:%02x:%02x:%02x:%02x ", + p_key[0], p_key[1], p_key[2], p_key[3], p_key[4] );*/ + fprintf( stderr, "at block %5d padding len %4d " + "type %02x sub %02x\n", i_pos, i_pes_length, + p_sec[0x11], p_sec[0x17 + p_sec[0x16]]); + } + + return 0; +} +#endif diff --git a/lib/libdvd/libdvdcss/src/css.h b/lib/libdvd/libdvdcss/src/css.h new file mode 100644 index 0000000000..03becda17c --- /dev/null +++ b/lib/libdvd/libdvdcss/src/css.h @@ -0,0 +1,56 @@ +/***************************************************************************** + * css.h: Structures for DVD authentication and unscrambling + ***************************************************************************** + * Copyright (C) 1999-2001 VideoLAN + * $Id$ + * + * Author: Stéphane Borel <stef@via.ecp.fr> + * + * based on: + * - css-auth by Derek Fawcus <derek@spider.com> + * - DVD CSS ioctls example program by Andrew T. Veliath <andrewtv@usa.net> + * - DeCSSPlus by Ethan Hawke + * - The Divide and conquer attack by Frank A. Stevenson <frank@funcom.com> + * + * 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, USA. + *****************************************************************************/ +#define KEY_SIZE 5 + +typedef uint8_t dvd_key_t[KEY_SIZE]; + +typedef struct dvd_title_s +{ + int i_startlb; + dvd_key_t p_key; + struct dvd_title_s *p_next; +} dvd_title_t; + +typedef struct css_s +{ + int i_agid; /* Current Authenication Grant ID. */ + dvd_key_t p_bus_key; /* Current session key. */ + dvd_key_t p_disc_key; /* This DVD disc's key. */ + dvd_key_t p_title_key; /* Current title key. */ +} css_t; + +/***************************************************************************** + * Prototypes in css.c + *****************************************************************************/ +int _dvdcss_test ( dvdcss_t ); +int _dvdcss_title ( dvdcss_t, int ); +int _dvdcss_disckey ( dvdcss_t ); +int _dvdcss_titlekey ( dvdcss_t, int , dvd_key_t ); +int _dvdcss_unscramble ( uint8_t *, uint8_t * ); + diff --git a/lib/libdvd/libdvdcss/src/csstables.h b/lib/libdvd/libdvdcss/src/csstables.h new file mode 100644 index 0000000000..bd0fc3a706 --- /dev/null +++ b/lib/libdvd/libdvdcss/src/csstables.h @@ -0,0 +1,392 @@ +/***************************************************************************** + * csstables.h: CSS Tables for DVD unscrambling + ***************************************************************************** + * Copyright (C) 1999-2001 VideoLAN + * $Id$ + * + * Author: Stéphane Borel <stef@via.ecp.fr> + * + * based on: + * - css-auth by Derek Fawcus <derek@spider.com> + * - DVD CSS ioctls example program by Andrew T. Veliath <andrewtv@usa.net> + * - The Divide and conquer attack by Frank A. Stevenson <frank@funcom.com> + * - DeCSSPlus by Ethan Hawke + * - DecVOB + * see http://www.lemuria.org/DeCSS/ by Tom Vogt for more information. + * + * 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, USA. + *****************************************************************************/ + + +static uint8_t p_css_tab1[ 256 ] = +{ + 0x33, 0x73, 0x3b, 0x26, 0x63, 0x23, 0x6b, 0x76, + 0x3e, 0x7e, 0x36, 0x2b, 0x6e, 0x2e, 0x66, 0x7b, + 0xd3, 0x93, 0xdb, 0x06, 0x43, 0x03, 0x4b, 0x96, + 0xde, 0x9e, 0xd6, 0x0b, 0x4e, 0x0e, 0x46, 0x9b, + 0x57, 0x17, 0x5f, 0x82, 0xc7, 0x87, 0xcf, 0x12, + 0x5a, 0x1a, 0x52, 0x8f, 0xca, 0x8a, 0xc2, 0x1f, + 0xd9, 0x99, 0xd1, 0x00, 0x49, 0x09, 0x41, 0x90, + 0xd8, 0x98, 0xd0, 0x01, 0x48, 0x08, 0x40, 0x91, + 0x3d, 0x7d, 0x35, 0x24, 0x6d, 0x2d, 0x65, 0x74, + 0x3c, 0x7c, 0x34, 0x25, 0x6c, 0x2c, 0x64, 0x75, + 0xdd, 0x9d, 0xd5, 0x04, 0x4d, 0x0d, 0x45, 0x94, + 0xdc, 0x9c, 0xd4, 0x05, 0x4c, 0x0c, 0x44, 0x95, + 0x59, 0x19, 0x51, 0x80, 0xc9, 0x89, 0xc1, 0x10, + 0x58, 0x18, 0x50, 0x81, 0xc8, 0x88, 0xc0, 0x11, + 0xd7, 0x97, 0xdf, 0x02, 0x47, 0x07, 0x4f, 0x92, + 0xda, 0x9a, 0xd2, 0x0f, 0x4a, 0x0a, 0x42, 0x9f, + 0x53, 0x13, 0x5b, 0x86, 0xc3, 0x83, 0xcb, 0x16, + 0x5e, 0x1e, 0x56, 0x8b, 0xce, 0x8e, 0xc6, 0x1b, + 0xb3, 0xf3, 0xbb, 0xa6, 0xe3, 0xa3, 0xeb, 0xf6, + 0xbe, 0xfe, 0xb6, 0xab, 0xee, 0xae, 0xe6, 0xfb, + 0x37, 0x77, 0x3f, 0x22, 0x67, 0x27, 0x6f, 0x72, + 0x3a, 0x7a, 0x32, 0x2f, 0x6a, 0x2a, 0x62, 0x7f, + 0xb9, 0xf9, 0xb1, 0xa0, 0xe9, 0xa9, 0xe1, 0xf0, + 0xb8, 0xf8, 0xb0, 0xa1, 0xe8, 0xa8, 0xe0, 0xf1, + 0x5d, 0x1d, 0x55, 0x84, 0xcd, 0x8d, 0xc5, 0x14, + 0x5c, 0x1c, 0x54, 0x85, 0xcc, 0x8c, 0xc4, 0x15, + 0xbd, 0xfd, 0xb5, 0xa4, 0xed, 0xad, 0xe5, 0xf4, + 0xbc, 0xfc, 0xb4, 0xa5, 0xec, 0xac, 0xe4, 0xf5, + 0x39, 0x79, 0x31, 0x20, 0x69, 0x29, 0x61, 0x70, + 0x38, 0x78, 0x30, 0x21, 0x68, 0x28, 0x60, 0x71, + 0xb7, 0xf7, 0xbf, 0xa2, 0xe7, 0xa7, 0xef, 0xf2, + 0xba, 0xfa, 0xb2, 0xaf, 0xea, 0xaa, 0xe2, 0xff +}; + +static uint8_t p_css_tab2[ 256 ] = +{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x09, 0x08, 0x0b, 0x0a, 0x0d, 0x0c, 0x0f, 0x0e, + 0x12, 0x13, 0x10, 0x11, 0x16, 0x17, 0x14, 0x15, + 0x1b, 0x1a, 0x19, 0x18, 0x1f, 0x1e, 0x1d, 0x1c, + 0x24, 0x25, 0x26, 0x27, 0x20, 0x21, 0x22, 0x23, + 0x2d, 0x2c, 0x2f, 0x2e, 0x29, 0x28, 0x2b, 0x2a, + 0x36, 0x37, 0x34, 0x35, 0x32, 0x33, 0x30, 0x31, + 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, + 0x49, 0x48, 0x4b, 0x4a, 0x4d, 0x4c, 0x4f, 0x4e, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x5b, 0x5a, 0x59, 0x58, 0x5f, 0x5e, 0x5d, 0x5c, + 0x52, 0x53, 0x50, 0x51, 0x56, 0x57, 0x54, 0x55, + 0x6d, 0x6c, 0x6f, 0x6e, 0x69, 0x68, 0x6b, 0x6a, + 0x64, 0x65, 0x66, 0x67, 0x60, 0x61, 0x62, 0x63, + 0x7f, 0x7e, 0x7d, 0x7c, 0x7b, 0x7a, 0x79, 0x78, + 0x76, 0x77, 0x74, 0x75, 0x72, 0x73, 0x70, 0x71, + 0x92, 0x93, 0x90, 0x91, 0x96, 0x97, 0x94, 0x95, + 0x9b, 0x9a, 0x99, 0x98, 0x9f, 0x9e, 0x9d, 0x9c, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x89, 0x88, 0x8b, 0x8a, 0x8d, 0x8c, 0x8f, 0x8e, + 0xb6, 0xb7, 0xb4, 0xb5, 0xb2, 0xb3, 0xb0, 0xb1, + 0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, 0xb8, + 0xa4, 0xa5, 0xa6, 0xa7, 0xa0, 0xa1, 0xa2, 0xa3, + 0xad, 0xac, 0xaf, 0xae, 0xa9, 0xa8, 0xab, 0xaa, + 0xdb, 0xda, 0xd9, 0xd8, 0xdf, 0xde, 0xdd, 0xdc, + 0xd2, 0xd3, 0xd0, 0xd1, 0xd6, 0xd7, 0xd4, 0xd5, + 0xc9, 0xc8, 0xcb, 0xca, 0xcd, 0xcc, 0xcf, 0xce, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, + 0xf6, 0xf7, 0xf4, 0xf5, 0xf2, 0xf3, 0xf0, 0xf1, + 0xed, 0xec, 0xef, 0xee, 0xe9, 0xe8, 0xeb, 0xea, + 0xe4, 0xe5, 0xe6, 0xe7, 0xe0, 0xe1, 0xe2, 0xe3 +}; + +static uint8_t p_css_tab3[ 512 ] = +{ + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff +}; + +static uint8_t p_css_tab4[ 256 ] = +{ + 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, + 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, + 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, + 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, + 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, + 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, + 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, + 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, + 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, + 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, + 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, + 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, + 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, + 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, + 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, + 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, + 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, + 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, + 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, + 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, + 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, + 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, + 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, + 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, + 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, + 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, + 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, + 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, + 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, + 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, + 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, + 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff +}; + +static uint8_t p_css_tab5[ 256 ] = +{ + 0xff, 0x7f, 0xbf, 0x3f, 0xdf, 0x5f, 0x9f, 0x1f, + 0xef, 0x6f, 0xaf, 0x2f, 0xcf, 0x4f, 0x8f, 0x0f, + 0xf7, 0x77, 0xb7, 0x37, 0xd7, 0x57, 0x97, 0x17, + 0xe7, 0x67, 0xa7, 0x27, 0xc7, 0x47, 0x87, 0x07, + 0xfb, 0x7b, 0xbb, 0x3b, 0xdb, 0x5b, 0x9b, 0x1b, + 0xeb, 0x6b, 0xab, 0x2b, 0xcb, 0x4b, 0x8b, 0x0b, + 0xf3, 0x73, 0xb3, 0x33, 0xd3, 0x53, 0x93, 0x13, + 0xe3, 0x63, 0xa3, 0x23, 0xc3, 0x43, 0x83, 0x03, + 0xfd, 0x7d, 0xbd, 0x3d, 0xdd, 0x5d, 0x9d, 0x1d, + 0xed, 0x6d, 0xad, 0x2d, 0xcd, 0x4d, 0x8d, 0x0d, + 0xf5, 0x75, 0xb5, 0x35, 0xd5, 0x55, 0x95, 0x15, + 0xe5, 0x65, 0xa5, 0x25, 0xc5, 0x45, 0x85, 0x05, + 0xf9, 0x79, 0xb9, 0x39, 0xd9, 0x59, 0x99, 0x19, + 0xe9, 0x69, 0xa9, 0x29, 0xc9, 0x49, 0x89, 0x09, + 0xf1, 0x71, 0xb1, 0x31, 0xd1, 0x51, 0x91, 0x11, + 0xe1, 0x61, 0xa1, 0x21, 0xc1, 0x41, 0x81, 0x01, + 0xfe, 0x7e, 0xbe, 0x3e, 0xde, 0x5e, 0x9e, 0x1e, + 0xee, 0x6e, 0xae, 0x2e, 0xce, 0x4e, 0x8e, 0x0e, + 0xf6, 0x76, 0xb6, 0x36, 0xd6, 0x56, 0x96, 0x16, + 0xe6, 0x66, 0xa6, 0x26, 0xc6, 0x46, 0x86, 0x06, + 0xfa, 0x7a, 0xba, 0x3a, 0xda, 0x5a, 0x9a, 0x1a, + 0xea, 0x6a, 0xaa, 0x2a, 0xca, 0x4a, 0x8a, 0x0a, + 0xf2, 0x72, 0xb2, 0x32, 0xd2, 0x52, 0x92, 0x12, + 0xe2, 0x62, 0xa2, 0x22, 0xc2, 0x42, 0x82, 0x02, + 0xfc, 0x7c, 0xbc, 0x3c, 0xdc, 0x5c, 0x9c, 0x1c, + 0xec, 0x6c, 0xac, 0x2c, 0xcc, 0x4c, 0x8c, 0x0c, + 0xf4, 0x74, 0xb4, 0x34, 0xd4, 0x54, 0x94, 0x14, + 0xe4, 0x64, 0xa4, 0x24, 0xc4, 0x44, 0x84, 0x04, + 0xf8, 0x78, 0xb8, 0x38, 0xd8, 0x58, 0x98, 0x18, + 0xe8, 0x68, 0xa8, 0x28, 0xc8, 0x48, 0x88, 0x08, + 0xf0, 0x70, 0xb0, 0x30, 0xd0, 0x50, 0x90, 0x10, + 0xe0, 0x60, 0xa0, 0x20, 0xc0, 0x40, 0x80, 0x00 +}; + +static uint8_t p_crypt_tab0[ 256 ] = +{ + 0xB7, 0xF4, 0x82, 0x57, 0xDA, 0x4D, 0xDB, 0xE2, + 0x2F, 0x52, 0x1A, 0xA8, 0x68, 0x5A, 0x8A, 0xFF, + 0xFB, 0x0E, 0x6D, 0x35, 0xF7, 0x5C, 0x76, 0x12, + 0xCE, 0x25, 0x79, 0x29, 0x39, 0x62, 0x08, 0x24, + 0xA5, 0x85, 0x7B, 0x56, 0x01, 0x23, 0x68, 0xCF, + 0x0A, 0xE2, 0x5A, 0xED, 0x3D, 0x59, 0xB0, 0xA9, + 0xB0, 0x2C, 0xF2, 0xB8, 0xEF, 0x32, 0xA9, 0x40, + 0x80, 0x71, 0xAF, 0x1E, 0xDE, 0x8F, 0x58, 0x88, + 0xB8, 0x3A, 0xD0, 0xFC, 0xC4, 0x1E, 0xB5, 0xA0, + 0xBB, 0x3B, 0x0F, 0x01, 0x7E, 0x1F, 0x9F, 0xD9, + 0xAA, 0xB8, 0x3D, 0x9D, 0x74, 0x1E, 0x25, 0xDB, + 0x37, 0x56, 0x8F, 0x16, 0xBA, 0x49, 0x2B, 0xAC, + 0xD0, 0xBD, 0x95, 0x20, 0xBE, 0x7A, 0x28, 0xD0, + 0x51, 0x64, 0x63, 0x1C, 0x7F, 0x66, 0x10, 0xBB, + 0xC4, 0x56, 0x1A, 0x04, 0x6E, 0x0A, 0xEC, 0x9C, + 0xD6, 0xE8, 0x9A, 0x7A, 0xCF, 0x8C, 0xDB, 0xB1, + 0xEF, 0x71, 0xDE, 0x31, 0xFF, 0x54, 0x3E, 0x5E, + 0x07, 0x69, 0x96, 0xB0, 0xCF, 0xDD, 0x9E, 0x47, + 0xC7, 0x96, 0x8F, 0xE4, 0x2B, 0x59, 0xC6, 0xEE, + 0xB9, 0x86, 0x9A, 0x64, 0x84, 0x72, 0xE2, 0x5B, + 0xA2, 0x96, 0x58, 0x99, 0x50, 0x03, 0xF5, 0x38, + 0x4D, 0x02, 0x7D, 0xE7, 0x7D, 0x75, 0xA7, 0xB8, + 0x67, 0x87, 0x84, 0x3F, 0x1D, 0x11, 0xE5, 0xFC, + 0x1E, 0xD3, 0x83, 0x16, 0xA5, 0x29, 0xF6, 0xC7, + 0x15, 0x61, 0x29, 0x1A, 0x43, 0x4F, 0x9B, 0xAF, + 0xC5, 0x87, 0x34, 0x6C, 0x0F, 0x3B, 0xA8, 0x1D, + 0x45, 0x58, 0x25, 0xDC, 0xA8, 0xA3, 0x3B, 0xD1, + 0x79, 0x1B, 0x48, 0xF2, 0xE9, 0x93, 0x1F, 0xFC, + 0xDB, 0x2A, 0x90, 0xA9, 0x8A, 0x3D, 0x39, 0x18, + 0xA3, 0x8E, 0x58, 0x6C, 0xE0, 0x12, 0xBB, 0x25, + 0xCD, 0x71, 0x22, 0xA2, 0x64, 0xC6, 0xE7, 0xFB, + 0xAD, 0x94, 0x77, 0x04, 0x9A, 0x39, 0xCF, 0x7C +}; + +static uint8_t p_crypt_tab1[ 256 ] = +{ + 0x8C, 0x47, 0xB0, 0xE1, 0xEB, 0xFC, 0xEB, 0x56, + 0x10, 0xE5, 0x2C, 0x1A, 0x5D, 0xEF, 0xBE, 0x4F, + 0x08, 0x75, 0x97, 0x4B, 0x0E, 0x25, 0x8E, 0x6E, + 0x39, 0x5A, 0x87, 0x53, 0xC4, 0x1F, 0xF4, 0x5C, + 0x4E, 0xE6, 0x99, 0x30, 0xE0, 0x42, 0x88, 0xAB, + 0xE5, 0x85, 0xBC, 0x8F, 0xD8, 0x3C, 0x54, 0xC9, + 0x53, 0x47, 0x18, 0xD6, 0x06, 0x5B, 0x41, 0x2C, + 0x67, 0x1E, 0x41, 0x74, 0x33, 0xE2, 0xB4, 0xE0, + 0x23, 0x29, 0x42, 0xEA, 0x55, 0x0F, 0x25, 0xB4, + 0x24, 0x2C, 0x99, 0x13, 0xEB, 0x0A, 0x0B, 0xC9, + 0xF9, 0x63, 0x67, 0x43, 0x2D, 0xC7, 0x7D, 0x07, + 0x60, 0x89, 0xD1, 0xCC, 0xE7, 0x94, 0x77, 0x74, + 0x9B, 0x7E, 0xD7, 0xE6, 0xFF, 0xBB, 0x68, 0x14, + 0x1E, 0xA3, 0x25, 0xDE, 0x3A, 0xA3, 0x54, 0x7B, + 0x87, 0x9D, 0x50, 0xCA, 0x27, 0xC3, 0xA4, 0x50, + 0x91, 0x27, 0xD4, 0xB0, 0x82, 0x41, 0x97, 0x79, + 0x94, 0x82, 0xAC, 0xC7, 0x8E, 0xA5, 0x4E, 0xAA, + 0x78, 0x9E, 0xE0, 0x42, 0xBA, 0x28, 0xEA, 0xB7, + 0x74, 0xAD, 0x35, 0xDA, 0x92, 0x60, 0x7E, 0xD2, + 0x0E, 0xB9, 0x24, 0x5E, 0x39, 0x4F, 0x5E, 0x63, + 0x09, 0xB5, 0xFA, 0xBF, 0xF1, 0x22, 0x55, 0x1C, + 0xE2, 0x25, 0xDB, 0xC5, 0xD8, 0x50, 0x03, 0x98, + 0xC4, 0xAC, 0x2E, 0x11, 0xB4, 0x38, 0x4D, 0xD0, + 0xB9, 0xFC, 0x2D, 0x3C, 0x08, 0x04, 0x5A, 0xEF, + 0xCE, 0x32, 0xFB, 0x4C, 0x92, 0x1E, 0x4B, 0xFB, + 0x1A, 0xD0, 0xE2, 0x3E, 0xDA, 0x6E, 0x7C, 0x4D, + 0x56, 0xC3, 0x3F, 0x42, 0xB1, 0x3A, 0x23, 0x4D, + 0x6E, 0x84, 0x56, 0x68, 0xF4, 0x0E, 0x03, 0x64, + 0xD0, 0xA9, 0x92, 0x2F, 0x8B, 0xBC, 0x39, 0x9C, + 0xAC, 0x09, 0x5E, 0xEE, 0xE5, 0x97, 0xBF, 0xA5, + 0xCE, 0xFA, 0x28, 0x2C, 0x6D, 0x4F, 0xEF, 0x77, + 0xAA, 0x1B, 0x79, 0x8E, 0x97, 0xB4, 0xC3, 0xF4 +}; + +static uint8_t p_crypt_tab2[ 256 ] = +{ + 0xB7, 0x75, 0x81, 0xD5, 0xDC, 0xCA, 0xDE, 0x66, + 0x23, 0xDF, 0x15, 0x26, 0x62, 0xD1, 0x83, 0x77, + 0xE3, 0x97, 0x76, 0xAF, 0xE9, 0xC3, 0x6B, 0x8E, + 0xDA, 0xB0, 0x6E, 0xBF, 0x2B, 0xF1, 0x19, 0xB4, + 0x95, 0x34, 0x48, 0xE4, 0x37, 0x94, 0x5D, 0x7B, + 0x36, 0x5F, 0x65, 0x53, 0x07, 0xE2, 0x89, 0x11, + 0x98, 0x85, 0xD9, 0x12, 0xC1, 0x9D, 0x84, 0xEC, + 0xA4, 0xD4, 0x88, 0xB8, 0xFC, 0x2C, 0x79, 0x28, + 0xD8, 0xDB, 0xB3, 0x1E, 0xA2, 0xF9, 0xD0, 0x44, + 0xD7, 0xD6, 0x60, 0xEF, 0x14, 0xF4, 0xF6, 0x31, + 0xD2, 0x41, 0x46, 0x67, 0x0A, 0xE1, 0x58, 0x27, + 0x43, 0xA3, 0xF8, 0xE0, 0xC8, 0xBA, 0x5A, 0x5C, + 0x80, 0x6C, 0xC6, 0xF2, 0xE8, 0xAD, 0x7D, 0x04, + 0x0D, 0xB9, 0x3C, 0xC2, 0x25, 0xBD, 0x49, 0x63, + 0x8C, 0x9F, 0x51, 0xCE, 0x20, 0xC5, 0xA1, 0x50, + 0x92, 0x2D, 0xDD, 0xBC, 0x8D, 0x4F, 0x9A, 0x71, + 0x2F, 0x30, 0x1D, 0x73, 0x39, 0x13, 0xFB, 0x1A, + 0xCB, 0x24, 0x59, 0xFE, 0x05, 0x96, 0x57, 0x0F, + 0x1F, 0xCF, 0x54, 0xBE, 0xF5, 0x06, 0x1B, 0xB2, + 0x6D, 0xD3, 0x4D, 0x32, 0x56, 0x21, 0x33, 0x0B, + 0x52, 0xE7, 0xAB, 0xEB, 0xA6, 0x74, 0x00, 0x4C, + 0xB1, 0x7F, 0x82, 0x99, 0x87, 0x0E, 0x5E, 0xC0, + 0x8F, 0xEE, 0x6F, 0x55, 0xF3, 0x7E, 0x08, 0x90, + 0xFA, 0xB6, 0x64, 0x70, 0x47, 0x4A, 0x17, 0xA7, + 0xB5, 0x40, 0x8A, 0x38, 0xE5, 0x68, 0x3E, 0x8B, + 0x69, 0xAA, 0x9B, 0x42, 0xA5, 0x10, 0x01, 0x35, + 0xFD, 0x61, 0x9E, 0xE6, 0x16, 0x9C, 0x86, 0xED, + 0xCD, 0x2E, 0xFF, 0xC4, 0x5B, 0xA0, 0xAE, 0xCC, + 0x4B, 0x3B, 0x03, 0xBB, 0x1C, 0x2A, 0xAC, 0x0C, + 0x3F, 0x93, 0xC7, 0x72, 0x7A, 0x09, 0x22, 0x3D, + 0x45, 0x78, 0xA9, 0xA8, 0xEA, 0xC9, 0x6A, 0xF7, + 0x29, 0x91, 0xF0, 0x02, 0x18, 0x3A, 0x4E, 0x7C +}; + +static uint8_t p_crypt_tab3[ 288 ] = +{ + 0x73, 0x51, 0x95, 0xE1, 0x12, 0xE4, 0xC0, 0x58, + 0xEE, 0xF2, 0x08, 0x1B, 0xA9, 0xFA, 0x98, 0x4C, + 0xA7, 0x33, 0xE2, 0x1B, 0xA7, 0x6D, 0xF5, 0x30, + 0x97, 0x1D, 0xF3, 0x02, 0x60, 0x5A, 0x82, 0x0F, + 0x91, 0xD0, 0x9C, 0x10, 0x39, 0x7A, 0x83, 0x85, + 0x3B, 0xB2, 0xB8, 0xAE, 0x0C, 0x09, 0x52, 0xEA, + 0x1C, 0xE1, 0x8D, 0x66, 0x4F, 0xF3, 0xDA, 0x92, + 0x29, 0xB9, 0xD5, 0xC5, 0x77, 0x47, 0x22, 0x53, + 0x14, 0xF7, 0xAF, 0x22, 0x64, 0xDF, 0xC6, 0x72, + 0x12, 0xF3, 0x75, 0xDA, 0xD7, 0xD7, 0xE5, 0x02, + 0x9E, 0xED, 0xDA, 0xDB, 0x4C, 0x47, 0xCE, 0x91, + 0x06, 0x06, 0x6D, 0x55, 0x8B, 0x19, 0xC9, 0xEF, + 0x8C, 0x80, 0x1A, 0x0E, 0xEE, 0x4B, 0xAB, 0xF2, + 0x08, 0x5C, 0xE9, 0x37, 0x26, 0x5E, 0x9A, 0x90, + 0x00, 0xF3, 0x0D, 0xB2, 0xA6, 0xA3, 0xF7, 0x26, + 0x17, 0x48, 0x88, 0xC9, 0x0E, 0x2C, 0xC9, 0x02, + 0xE7, 0x18, 0x05, 0x4B, 0xF3, 0x39, 0xE1, 0x20, + 0x02, 0x0D, 0x40, 0xC7, 0xCA, 0xB9, 0x48, 0x30, + 0x57, 0x67, 0xCC, 0x06, 0xBF, 0xAC, 0x81, 0x08, + 0x24, 0x7A, 0xD4, 0x8B, 0x19, 0x8E, 0xAC, 0xB4, + 0x5A, 0x0F, 0x73, 0x13, 0xAC, 0x9E, 0xDA, 0xB6, + 0xB8, 0x96, 0x5B, 0x60, 0x88, 0xE1, 0x81, 0x3F, + 0x07, 0x86, 0x37, 0x2D, 0x79, 0x14, 0x52, 0xEA, + 0x73, 0xDF, 0x3D, 0x09, 0xC8, 0x25, 0x48, 0xD8, + 0x75, 0x60, 0x9A, 0x08, 0x27, 0x4A, 0x2C, 0xB9, + 0xA8, 0x8B, 0x8A, 0x73, 0x62, 0x37, 0x16, 0x02, + 0xBD, 0xC1, 0x0E, 0x56, 0x54, 0x3E, 0x14, 0x5F, + 0x8C, 0x8F, 0x6E, 0x75, 0x1C, 0x07, 0x39, 0x7B, + 0x4B, 0xDB, 0xD3, 0x4B, 0x1E, 0xC8, 0x7E, 0xFE, + 0x3E, 0x72, 0x16, 0x83, 0x7D, 0xEE, 0xF5, 0xCA, + 0xC5, 0x18, 0xF9, 0xD8, 0x68, 0xAB, 0x38, 0x85, + 0xA8, 0xF0, 0xA1, 0x73, 0x9F, 0x5D, 0x19, 0x0B, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x33, 0x72, 0x39, 0x25, 0x67, 0x26, 0x6D, 0x71, + 0x36, 0x77, 0x3C, 0x20, 0x62, 0x23, 0x68, 0x74, + 0xC3, 0x82, 0xC9, 0x15, 0x57, 0x16, 0x5D, 0x81 +}; + diff --git a/lib/libdvd/libdvdcss/src/device.c b/lib/libdvd/libdvdcss/src/device.c new file mode 100644 index 0000000000..45d6f0d3d2 --- /dev/null +++ b/lib/libdvd/libdvdcss/src/device.c @@ -0,0 +1,1086 @@ +/***************************************************************************** + * device.h: DVD device access + ***************************************************************************** + * Copyright (C) 1998-2006 VideoLAN + * $Id$ + * + * Authors: Stéphane Borel <stef@via.ecp.fr> + * Sam Hocevar <sam@zoy.org> + * HÃ¥kan Hjort <d95hjort@dtek.chalmers.se> + * + * 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, USA. + *****************************************************************************/ + +/* + Modifications for XBMC are all contained within _XBOX (real xbox hardware) or WITH_CACHE +*/ + +/***************************************************************************** + * Preamble + *****************************************************************************/ +#include "config.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#ifdef HAVE_ERRNO_H +# include <errno.h> +#endif +#include <sys/types.h> +#include <sys/stat.h> +#ifdef HAVE_SYS_PARAM_H +# include <sys/param.h> +#endif +#include <fcntl.h> + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif + +#ifdef HAVE_LIMITS_H +# include <limits.h> +#endif + +#if defined( WIN32 ) && !defined( SYS_CYGWIN ) +# include <io.h> /* read() */ +#else +# include <sys/uio.h> /* struct iovec */ +#endif + +#ifdef DARWIN_DVD_IOCTL +# include <paths.h> +# include <CoreFoundation/CoreFoundation.h> +# include <IOKit/IOKitLib.h> +# include <IOKit/IOBSD.h> +# include <IOKit/storage/IOMedia.h> +# include <IOKit/storage/IOCDMedia.h> +# include <IOKit/storage/IODVDMedia.h> +#endif + +#include "dvdcss/dvdcss.h" + +#include "common.h" +#include "css.h" +#include "libdvdcss.h" +#include "ioctl.h" +#include "device.h" + +/***************************************************************************** + * Device reading prototypes + *****************************************************************************/ +static int libc_open ( dvdcss_t, char const * ); +static int libc_seek ( dvdcss_t, int ); +static int libc_read ( dvdcss_t, void *, int ); +static int libc_readv ( dvdcss_t, struct iovec *, int ); + +#ifdef WIN32 +static int win2k_open ( dvdcss_t, char const * ); +static int aspi_open ( dvdcss_t, char const * ); +static int win2k_seek ( dvdcss_t, int ); +static int aspi_seek ( dvdcss_t, int ); +static int win2k_read ( dvdcss_t, void *, int ); +static int aspi_read ( dvdcss_t, void *, int ); +static int win_readv ( dvdcss_t, struct iovec *, int ); + +static int aspi_read_internal ( int, void *, int ); +#endif + +int _dvdcss_use_ioctls( dvdcss_t dvdcss ) +{ +#if defined( WIN32 ) + if( dvdcss->b_file ) + { + return 0; + } + + /* FIXME: implement this for Windows */ + if( WIN2K ) + { + return 1; + } + else + { + return 1; + } +#else + struct stat fileinfo; + int ret; + + ret = fstat( dvdcss->i_fd, &fileinfo ); + if( ret < 0 ) + { + return 1; /* What to do? Be conservative and try to use the ioctls */ + } + + /* Complete this list and check that we test for the right things + * (I've assumed for all OSs that 'r', (raw) device, are char devices + * and those that don't contain/use an 'r' in the name are block devices) + * + * Linux needs a block device + * Solaris needs a char device + * Darwin needs a char device + * OpenBSD needs a char device + * NetBSD needs a char device + * FreeBSD can use either the block or the char device + * BSD/OS can use either the block or the char device + */ + + /* Check if this is a block/char device */ + if( S_ISBLK( fileinfo.st_mode ) || + S_ISCHR( fileinfo.st_mode ) ) + { + return 1; + } + else + { + return 0; + } +#endif +} + +void _dvdcss_check ( dvdcss_t dvdcss ) +{ +#if defined( WIN32 ) + DWORD drives; + int i; +#elif defined( DARWIN_DVD_IOCTL ) + io_object_t next_media; + mach_port_t master_port; + kern_return_t kern_result; + io_iterator_t media_iterator; + CFMutableDictionaryRef classes_to_match; +#else + char *ppsz_devices[] = { "/dev/dvd", "/dev/cdrom", "/dev/hdc", NULL }; + int i, i_fd; +#endif + + /* If the device name is non-null, return */ + if( dvdcss->psz_device[0] ) + { + return; + } + +#if defined( WIN32 ) + drives = GetLogicalDrives(); + + for( i = 0; drives; i++ ) + { + char psz_device[5]; + DWORD cur = 1 << i; + UINT i_ret; + + if( (drives & cur) == 0 ) + { + continue; + } + drives &= ~cur; + + sprintf( psz_device, "%c:\\", 'A' + i ); + i_ret = GetDriveType( psz_device ); + if( i_ret != DRIVE_CDROM ) + { + continue; + } + + /* Remove trailing backslash */ + psz_device[2] = '\0'; + + /* FIXME: we want to differenciate between CD and DVD drives + * using DeviceIoControl() */ + print_debug( dvdcss, "defaulting to drive `%s'", psz_device ); + free( dvdcss->psz_device ); + dvdcss->psz_device = strdup( psz_device ); + return; + } +#elif defined( DARWIN_DVD_IOCTL ) + + kern_result = IOMasterPort( MACH_PORT_NULL, &master_port ); + if( kern_result != KERN_SUCCESS ) + { + return; + } + + classes_to_match = IOServiceMatching( kIODVDMediaClass ); + if( classes_to_match == NULL ) + { + return; + } + + CFDictionarySetValue( classes_to_match, CFSTR( kIOMediaEjectableKey ), + kCFBooleanTrue ); + + kern_result = IOServiceGetMatchingServices( master_port, classes_to_match, + &media_iterator ); + if( kern_result != KERN_SUCCESS ) + { + return; + } + + next_media = IOIteratorNext( media_iterator ); + for( ; ; ) + { + char psz_buf[0x32]; + size_t i_pathlen; + CFTypeRef psz_path; + + next_media = IOIteratorNext( media_iterator ); + if( next_media == 0 ) + { + break; + } + + psz_path = IORegistryEntryCreateCFProperty( next_media, + CFSTR( kIOBSDNameKey ), + kCFAllocatorDefault, + 0 ); + if( psz_path == NULL ) + { + IOObjectRelease( next_media ); + continue; + } + + snprintf( psz_buf, sizeof(psz_buf), "%s%c", _PATH_DEV, 'r' ); + i_pathlen = strlen( psz_buf ); + + if( CFStringGetCString( psz_path, + (char*)&psz_buf + i_pathlen, + sizeof(psz_buf) - i_pathlen, + kCFStringEncodingASCII ) ) + { + print_debug( dvdcss, "defaulting to drive `%s'", psz_buf ); + CFRelease( psz_path ); + IOObjectRelease( next_media ); + IOObjectRelease( media_iterator ); + free( dvdcss->psz_device ); + dvdcss->psz_device = strdup( psz_buf ); + return; + } + + CFRelease( psz_path ); + + IOObjectRelease( next_media ); + } + + IOObjectRelease( media_iterator ); +#else + for( i = 0; ppsz_devices[i]; i++ ) + { + i_fd = open( ppsz_devices[i], 0 ); + if( i_fd != -1 ) + { + print_debug( dvdcss, "defaulting to drive `%s'", ppsz_devices[i] ); + close( i_fd ); + free( dvdcss->psz_device ); + dvdcss->psz_device = strdup( ppsz_devices[i] ); + return; + } + } +#endif + + print_error( dvdcss, "could not find a suitable default drive" ); +} + +int _dvdcss_open ( dvdcss_t dvdcss ) +{ + char const *psz_device = dvdcss->psz_device; + + print_debug( dvdcss, "opening target `%s'", psz_device ); + +#if defined( WIN32 ) + dvdcss->b_file = 1; +#if defined( _XBOX ) + // If we've passed over the device string make sure we don't try + // to use file based handling (libc) - we want Win2k routines ... + if (!stricmp(psz_device, "\\Device\\Cdrom0")) + dvdcss->b_file = 0; + else + dvdcss->b_file = stricmp(psz_device, "D:"); +#else + /* If device is "X:" or "X:\", we are not actually opening a file. */ + if (psz_device[0] && psz_device[1] == ':' && + (!psz_device[2] || (psz_device[2] == '\\' && !psz_device[3]))) + dvdcss->b_file = 0; + +#endif // _XBOX + /* Initialize readv temporary buffer */ + dvdcss->p_readv_buffer = NULL; + dvdcss->i_readv_buf_size = 0; + + if( !dvdcss->b_file && WIN2K ) + { + print_debug( dvdcss, "using Win2K API for access" ); + dvdcss->pf_seek = win2k_seek; + dvdcss->pf_read = win2k_read; + dvdcss->pf_readv = win_readv; + return win2k_open( dvdcss, psz_device ); + } + else if( !dvdcss->b_file ) + { + print_debug( dvdcss, "using ASPI for access" ); + dvdcss->pf_seek = aspi_seek; + dvdcss->pf_read = aspi_read; + dvdcss->pf_readv = win_readv; + return aspi_open( dvdcss, psz_device ); + } + else +#endif + { + print_debug( dvdcss, "using libc for access" ); + dvdcss->pf_seek = libc_seek; + dvdcss->pf_read = libc_read; + dvdcss->pf_readv = libc_readv; + return libc_open( dvdcss, psz_device ); + } +} + +#ifndef WIN32 +int _dvdcss_raw_open ( dvdcss_t dvdcss, char const *psz_device ) +{ + dvdcss->i_raw_fd = open( psz_device, 0 ); + + if( dvdcss->i_raw_fd == -1 ) + { + print_debug( dvdcss, "cannot open %s (%s)", + psz_device, strerror(errno) ); + print_error( dvdcss, "failed to open raw device, but continuing" ); + return -1; + } + else + { + dvdcss->i_read_fd = dvdcss->i_raw_fd; + } + + return 0; +} +#endif + +int _dvdcss_close ( dvdcss_t dvdcss ) +{ +#if defined( WIN32 ) + if( dvdcss->b_file ) + { + close( dvdcss->i_fd ); + } + else if( WIN2K ) + { + CloseHandle( (HANDLE) dvdcss->i_fd ); + } + else /* ASPI */ + { +#if !defined(_XBOX) + struct w32_aspidev *fd = (struct w32_aspidev *) dvdcss->i_fd; + + /* Unload aspi and free w32_aspidev structure */ + FreeLibrary( (HMODULE) fd->hASPI ); + free( (void*) dvdcss->i_fd ); +#endif // !_XBOX + } + + /* Free readv temporary buffer */ + if( dvdcss->p_readv_buffer ) + { + free( dvdcss->p_readv_buffer ); + dvdcss->p_readv_buffer = NULL; + dvdcss->i_readv_buf_size = 0; + } + + return 0; +#else + close( dvdcss->i_fd ); + + if( dvdcss->i_raw_fd >= 0 ) + { + close( dvdcss->i_raw_fd ); + dvdcss->i_raw_fd = -1; + } + + return 0; +#endif +} + +/* Following functions are local */ + +/***************************************************************************** + * Open commands. + *****************************************************************************/ +static int libc_open ( dvdcss_t dvdcss, char const *psz_device ) +{ +#if !defined( WIN32 ) + dvdcss->i_fd = dvdcss->i_read_fd = open( psz_device, 0 ); +#else + dvdcss->i_fd = dvdcss->i_read_fd = open( psz_device, O_BINARY ); +#endif + + if( dvdcss->i_fd == -1 ) + { + print_debug( dvdcss, "cannot open %s (%s)", + psz_device, strerror(errno) ); + print_error( dvdcss, "failed to open device" ); + return -1; + } + + dvdcss->i_pos = 0; + + return 0; +} + +#if defined( WIN32 ) +static int win2k_open ( dvdcss_t dvdcss, char const *psz_device ) +{ +#ifdef _XBOX + char psz_dvd[70]; + strcpy(psz_dvd, "cdrom0:"); +#else + char psz_dvd[7]; + _snprintf( psz_dvd, 7, "\\\\.\\%c:", psz_device[0] ); + +#endif + /* To work around an M$ bug in IOCTL_DVD_READ_STRUCTURE, we need read + * _and_ write access to the device (so we can make SCSI Pass Through + * Requests). Unfortunately this is only allowed if you have + * administrator priviledges so we allow for a fallback method with + * only read access to the device (in this case ioctl_ReadCopyright() + * won't send back the right result). + * (See Microsoft Q241374: Read and Write Access Required for SCSI + * Pass Through Requests) */ + +#ifdef WITH_CACHE + DWORD flags = FILE_FLAG_NO_BUFFERING; /* we handle buffering ourself */ +#else + DWORD flags = FILE_FLAG_RANDOM_ACCESS; +#endif //!_XBOX + + dvdcss->i_fd = (int) + CreateFile( psz_dvd, GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, + flags, NULL ); + + if( (HANDLE) dvdcss->i_fd == INVALID_HANDLE_VALUE ) + dvdcss->i_fd = (int) + CreateFile( psz_dvd, GENERIC_READ, FILE_SHARE_READ, + NULL, OPEN_EXISTING, + flags, NULL ); + + if( (HANDLE) dvdcss->i_fd == INVALID_HANDLE_VALUE ) + { + print_error( dvdcss, "failed opening device" ); + return -1; + } + + dvdcss->i_pos = 0; + + return 0; +} + +static int aspi_open( dvdcss_t dvdcss, char const * psz_device ) +{ + HMODULE hASPI; + DWORD dwSupportInfo; + struct w32_aspidev *fd; + int i, j, i_hostadapters; + GETASPI32SUPPORTINFO lpGetSupport; + SENDASPI32COMMAND lpSendCommand; + char c_drive = psz_device[0]; + + /* load aspi and init w32_aspidev structure */ + hASPI = LoadLibrary( "wnaspi32.dll" ); + if( hASPI == NULL ) + { + print_error( dvdcss, "unable to load wnaspi32.dll" ); + return -1; + } + + lpGetSupport = (GETASPI32SUPPORTINFO) GetProcAddress( hASPI, "GetASPI32SupportInfo" ); + lpSendCommand = (SENDASPI32COMMAND) GetProcAddress( hASPI, "SendASPI32Command" ); + + if(lpGetSupport == NULL || lpSendCommand == NULL ) + { + print_error( dvdcss, "unable to get aspi function pointers" ); + FreeLibrary( hASPI ); + return -1; + } + + dwSupportInfo = lpGetSupport(); + + if( HIBYTE( LOWORD ( dwSupportInfo ) ) == SS_NO_ADAPTERS ) + { + print_error( dvdcss, "no ASPI adapters found" ); + FreeLibrary( hASPI ); + return -1; + } + + if( HIBYTE( LOWORD ( dwSupportInfo ) ) != SS_COMP ) + { + print_error( dvdcss, "unable to initalize aspi layer" ); + FreeLibrary( hASPI ); + return -1; + } + + i_hostadapters = LOBYTE( LOWORD( dwSupportInfo ) ); + if( i_hostadapters == 0 ) + { + print_error( dvdcss, "no ASPI adapters ready" ); + FreeLibrary( hASPI ); + return -1; + } + + fd = malloc( sizeof( struct w32_aspidev ) ); + if( fd == NULL ) + { + print_error( dvdcss, "not enough memory" ); + FreeLibrary( hASPI ); + return -1; + } + + fd->i_blocks = 0; + fd->hASPI = (long) hASPI; + fd->lpSendCommand = lpSendCommand; + + c_drive = c_drive > 'Z' ? c_drive - 'a' : c_drive - 'A'; + + for( i = 0; i < i_hostadapters; i++ ) + { + for( j = 0; j < 15; j++ ) + { + struct SRB_GetDiskInfo srbDiskInfo; + + srbDiskInfo.SRB_Cmd = SC_GET_DISK_INFO; + srbDiskInfo.SRB_HaId = i; + srbDiskInfo.SRB_Flags = 0; + srbDiskInfo.SRB_Hdr_Rsvd = 0; + srbDiskInfo.SRB_Target = j; + srbDiskInfo.SRB_Lun = 0; + + lpSendCommand( (void*) &srbDiskInfo ); + + if( (srbDiskInfo.SRB_Status == SS_COMP) && + (srbDiskInfo.SRB_Int13HDriveInfo == c_drive) ) + { + /* Make sure this is a cdrom device */ + struct SRB_GDEVBlock srbGDEVBlock; + + memset( &srbGDEVBlock, 0, sizeof(struct SRB_GDEVBlock) ); + srbGDEVBlock.SRB_Cmd = SC_GET_DEV_TYPE; + srbGDEVBlock.SRB_HaId = i; + srbGDEVBlock.SRB_Target = j; + + lpSendCommand( (void*) &srbGDEVBlock ); + + if( ( srbGDEVBlock.SRB_Status == SS_COMP ) && + ( srbGDEVBlock.SRB_DeviceType == DTYPE_CDROM ) ) + { + fd->i_sid = MAKEWORD( i, j ); + dvdcss->i_fd = (int) fd; + dvdcss->i_pos = 0; + return 0; + } + else + { + free( (void*) fd ); + FreeLibrary( hASPI ); + print_error( dvdcss,"this is not a cdrom drive" ); + return -1; + } + } + } + } + + free( (void*) fd ); + FreeLibrary( hASPI ); + print_error( dvdcss, "unable to get haid and target (aspi)" ); + return -1; +} +#endif + +/***************************************************************************** + * Seek commands. + *****************************************************************************/ +static int libc_seek( dvdcss_t dvdcss, int i_blocks ) +{ + off_t i_seek; + + if( dvdcss->i_pos == i_blocks ) + { + /* We are already in position */ + return i_blocks; + } + + i_seek = (off_t)i_blocks * (off_t)DVDCSS_BLOCK_SIZE; + i_seek = lseek( dvdcss->i_read_fd, i_seek, SEEK_SET ); + + if( i_seek < 0 ) + { + print_error( dvdcss, "seek error" ); + dvdcss->i_pos = -1; + return i_seek; + } + + dvdcss->i_pos = i_seek / DVDCSS_BLOCK_SIZE; + + return dvdcss->i_pos; +} + +#if defined( WIN32 ) +static int win2k_seek( dvdcss_t dvdcss, int i_blocks ) +{ + LARGE_INTEGER li_seek; +#ifdef WITH_CACHE + int iBytesToSkip; +#endif + +#ifndef INVALID_SET_FILE_POINTER +# define INVALID_SET_FILE_POINTER ((DWORD)-1) +#endif + + if( dvdcss->i_pos == i_blocks ) + { + /* We are already in position */ + return i_blocks; + } + +#ifdef WITH_CACHE + + // if our buffer contains the position which we want to seek too, we can + // just decrease dwCacheBufferSize + iBytesToSkip = (i_blocks - dvdcss->i_pos) * DVDCSS_BLOCK_SIZE; + if (iBytesToSkip > 0 && iBytesToSkip < dvdcss->buffer_size) + { + dvdcss->buffer_size -= iBytesToSkip; + dvdcss->i_pos = i_blocks; + return dvdcss->i_pos; + } + else if (iBytesToSkip < 0 && (DISC_CACHE_SIZE - dvdcss->buffer_size) >= -iBytesToSkip) + { + // we want to seek backwards, and we have enough old data in our buffer + dvdcss->buffer_size -= iBytesToSkip; // since iBytesToSkip is negative, dwCacheBufferSize will get bigger + dvdcss->i_pos = i_blocks; + return dvdcss->i_pos; + } + else dvdcss->buffer_size = 0; + +#endif + + li_seek.QuadPart = (LONGLONG)i_blocks * DVDCSS_BLOCK_SIZE; + + li_seek.LowPart = SetFilePointer( (HANDLE) dvdcss->i_fd, + li_seek.LowPart, + &li_seek.HighPart, FILE_BEGIN ); + if( (li_seek.LowPart == INVALID_SET_FILE_POINTER) + && GetLastError() != NO_ERROR) + { + dvdcss->i_pos = -1; + return -1; + } + + dvdcss->i_pos = li_seek.QuadPart / DVDCSS_BLOCK_SIZE; + + return dvdcss->i_pos; +} + +static int aspi_seek( dvdcss_t dvdcss, int i_blocks ) +{ + int i_old_blocks; + char sz_buf[ DVDCSS_BLOCK_SIZE ]; + struct w32_aspidev *fd = (struct w32_aspidev *) dvdcss->i_fd; + + if( dvdcss->i_pos == i_blocks ) + { + /* We are already in position */ + return i_blocks; + } + + i_old_blocks = fd->i_blocks; + fd->i_blocks = i_blocks; + + if( aspi_read_internal( dvdcss->i_fd, sz_buf, 1 ) == -1 ) + { + fd->i_blocks = i_old_blocks; + dvdcss->i_pos = -1; + return -1; + } + + (fd->i_blocks)--; + + dvdcss->i_pos = fd->i_blocks; + + return dvdcss->i_pos; +} +#endif + +/***************************************************************************** + * Read commands. + *****************************************************************************/ +static int libc_read ( dvdcss_t dvdcss, void *p_buffer, int i_blocks ) +{ + off_t i_size, i_ret; + + i_size = (off_t)i_blocks * (off_t)DVDCSS_BLOCK_SIZE; + i_ret = read( dvdcss->i_read_fd, p_buffer, i_size ); + + if( i_ret < 0 ) + { + print_error( dvdcss, "read error" ); + dvdcss->i_pos = -1; + return i_ret; + } + + /* Handle partial reads */ + if( i_ret != i_size ) + { + int i_seek; + + dvdcss->i_pos = -1; + i_seek = libc_seek( dvdcss, i_ret / DVDCSS_BLOCK_SIZE ); + if( i_seek < 0 ) + { + return i_seek; + } + + /* We have to return now so that i_pos isn't clobbered */ + return i_ret / DVDCSS_BLOCK_SIZE; + } + + dvdcss->i_pos += i_ret / DVDCSS_BLOCK_SIZE; + return i_ret / DVDCSS_BLOCK_SIZE; +} + +#if defined( WIN32 ) +static int win2k_read ( dvdcss_t dvdcss, void *p_buffer, int i_blocks ) +{ + int i_bytes; + +#ifdef WITH_CACHE + + if (dvdcss->buffer_size < i_blocks * DVDCSS_BLOCK_SIZE) + { + // we don't have enough data in our buffer + int iRemaining = i_blocks * DVDCSS_BLOCK_SIZE; + int iCopied = 0; + // copy data we already have and read again into the cache + if (dvdcss->buffer_size > 0) memcpy(p_buffer, dvdcss->buffer + (DISC_CACHE_SIZE - dvdcss->buffer_size), dvdcss->buffer_size); + iCopied = dvdcss->buffer_size; + iRemaining -= dvdcss->buffer_size; + (BYTE*)p_buffer += iCopied; + dvdcss->buffer_size = 0; + + // if remaining size is bigger >= DISC_CACHE_SIZE, don't cache it. Just read + if (iRemaining >= DISC_CACHE_SIZE) + { + if (!ReadFile((HANDLE)dvdcss->i_fd, p_buffer, iRemaining, (LPDWORD)&i_bytes, NULL)) + { + dvdcss->i_pos = -1; + return -1; + } + dvdcss->i_pos += (i_bytes + iCopied) / DVDCSS_BLOCK_SIZE; + return (i_bytes + iCopied) / DVDCSS_BLOCK_SIZE; + } + else + { + // read a chunk into the cache and copy the needed bytes into p_buffer + if (!ReadFile((HANDLE)dvdcss->i_fd, dvdcss->buffer, DISC_CACHE_SIZE, &dvdcss->buffer_size, NULL)) + { + // read error, maybe we tried to read to much. Try again but now without cache + if (!ReadFile((HANDLE)dvdcss->i_fd, p_buffer, iRemaining, (LPDWORD)&i_bytes, NULL)) + { + dvdcss->i_pos = -1; + return -1; + } + dvdcss->i_pos += (i_bytes + iCopied) / DVDCSS_BLOCK_SIZE; + return (i_bytes + iCopied) / DVDCSS_BLOCK_SIZE; + } + // copy bytes into the buffer + memcpy(p_buffer, dvdcss->buffer, iRemaining); + dvdcss->buffer_size -= iRemaining; + dvdcss->i_pos += (iRemaining + iCopied) / DVDCSS_BLOCK_SIZE; + return (iRemaining + iCopied) / DVDCSS_BLOCK_SIZE; + } + } + else + { + // we have enough data in our cache, just copy it + memcpy(p_buffer, dvdcss->buffer + (DISC_CACHE_SIZE - dvdcss->buffer_size), i_blocks * DVDCSS_BLOCK_SIZE); + dvdcss->buffer_size -= i_blocks * DVDCSS_BLOCK_SIZE; + dvdcss->i_pos += i_blocks; + return i_blocks; + } + + dvdcss->i_pos = -1; + return -1; + +#else // WITH_CACHE + + if( !ReadFile( (HANDLE) dvdcss->i_fd, p_buffer, + i_blocks * DVDCSS_BLOCK_SIZE, + (LPDWORD)&i_bytes, NULL ) ) + { + dvdcss->i_pos = -1; + return -1; + } + + dvdcss->i_pos += i_bytes / DVDCSS_BLOCK_SIZE; + return i_bytes / DVDCSS_BLOCK_SIZE; +#endif // WITH_CACHE +} + +static int aspi_read ( dvdcss_t dvdcss, void *p_buffer, int i_blocks ) +{ + int i_read = aspi_read_internal( dvdcss->i_fd, p_buffer, i_blocks ); + + if( i_read < 0 ) + { + dvdcss->i_pos = -1; + return i_read; + } + + dvdcss->i_pos += i_read; + return i_read; +} +#endif + +/***************************************************************************** + * Readv commands. + *****************************************************************************/ +static int libc_readv ( dvdcss_t dvdcss, struct iovec *p_iovec, int i_blocks ) +{ +#if defined( WIN32 ) + int i_index, i_len, i_total = 0; + unsigned char *p_base; + int i_bytes; + + for( i_index = i_blocks; + i_index; + i_index--, p_iovec++ ) + { + i_len = p_iovec->iov_len; + p_base = p_iovec->iov_base; + + if( i_len <= 0 ) + { + continue; + } + + i_bytes = read( dvdcss->i_fd, p_base, i_len ); + + if( i_bytes < 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 postition is left + * unspecified after a failure */ + dvdcss->i_pos = -1; + return -1; + } + + i_total += i_bytes; + + if( i_bytes != i_len ) + { + /* We reached the end of the file or a signal interrupted + * the read. Return a partial read. */ + int i_seek; + + dvdcss->i_pos = -1; + i_seek = libc_seek( dvdcss, i_total / DVDCSS_BLOCK_SIZE ); + if( i_seek < 0 ) + { + return i_seek; + } + + /* We have to return now so that i_pos isn't clobbered */ + return i_total / DVDCSS_BLOCK_SIZE; + } + } + + dvdcss->i_pos += i_total / DVDCSS_BLOCK_SIZE; + return i_total / DVDCSS_BLOCK_SIZE; +#else + int i_read = readv( dvdcss->i_read_fd, p_iovec, i_blocks ); + + if( i_read < 0 ) + { + dvdcss->i_pos = -1; + return i_read; + } + + dvdcss->i_pos += i_read / DVDCSS_BLOCK_SIZE; + return i_read / DVDCSS_BLOCK_SIZE; +#endif +} + +#if defined( WIN32 ) +/***************************************************************************** + * win_readv: vectored read using ReadFile for Win2K and ASPI for win9x + *****************************************************************************/ +static int win_readv ( dvdcss_t dvdcss, struct iovec *p_iovec, int i_blocks ) +{ + int i_index; + int i_blocks_read, i_blocks_total = 0; + + /* Check the size of the readv temp buffer, just in case we need to + * realloc something bigger */ + if( dvdcss->i_readv_buf_size < i_blocks * DVDCSS_BLOCK_SIZE ) + { + dvdcss->i_readv_buf_size = i_blocks * DVDCSS_BLOCK_SIZE; + + if( dvdcss->p_readv_buffer ) free( dvdcss->p_readv_buffer ); + + /* Allocate a buffer which will be used as a temporary storage + * for readv */ + dvdcss->p_readv_buffer = malloc( dvdcss->i_readv_buf_size ); + if( !dvdcss->p_readv_buffer ) + { + print_error( dvdcss, " failed (readv)" ); + dvdcss->i_pos = -1; + return -1; + } + } + + for( i_index = i_blocks; i_index; i_index-- ) + { + i_blocks_total += p_iovec[i_index-1].iov_len; + } + + if( i_blocks_total <= 0 ) return 0; + + i_blocks_total /= DVDCSS_BLOCK_SIZE; + + if( WIN2K ) + { + unsigned long int i_bytes; + if( !ReadFile( (HANDLE)dvdcss->i_fd, dvdcss->p_readv_buffer, + i_blocks_total * DVDCSS_BLOCK_SIZE, &i_bytes, NULL ) ) + { + /* The read failed... too bad. + * As in the posix spec the file postition is left + * unspecified after a failure */ + dvdcss->i_pos = -1; + return -1; + } + i_blocks_read = i_bytes / DVDCSS_BLOCK_SIZE; + } + else /* Win9x */ + { + i_blocks_read = aspi_read_internal( dvdcss->i_fd, + dvdcss->p_readv_buffer, + i_blocks_total ); + if( i_blocks_read < 0 ) + { + /* See above */ + dvdcss->i_pos = -1; + return -1; + } + } + + /* We just have to copy the content of the temp buffer into the iovecs */ + for( i_index = 0, i_blocks_total = i_blocks_read; + i_blocks_total > 0; + i_index++ ) + { + memcpy( p_iovec[i_index].iov_base, + dvdcss->p_readv_buffer + (i_blocks_read - i_blocks_total) + * DVDCSS_BLOCK_SIZE, + p_iovec[i_index].iov_len ); + /* if we read less blocks than asked, we'll just end up copying + * garbage, this isn't an issue as we return the number of + * blocks actually read */ + i_blocks_total -= ( p_iovec[i_index].iov_len / DVDCSS_BLOCK_SIZE ); + } + + dvdcss->i_pos += i_blocks_read; + return i_blocks_read; +} + +static int aspi_read_internal( int i_fd, void *p_data, int i_blocks ) +{ + HANDLE hEvent; + struct SRB_ExecSCSICmd ssc; + struct w32_aspidev *fd = (struct w32_aspidev *) i_fd; + + /* Create the transfer completion event */ + hEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); + if( hEvent == NULL ) + { + return -1; + } + + memset( &ssc, 0, sizeof( ssc ) ); + + ssc.SRB_Cmd = SC_EXEC_SCSI_CMD; + ssc.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; + ssc.SRB_HaId = LOBYTE( fd->i_sid ); + ssc.SRB_Target = HIBYTE( fd->i_sid ); + ssc.SRB_SenseLen = SENSE_LEN; + + ssc.SRB_PostProc = (LPVOID) hEvent; + ssc.SRB_BufPointer = p_data; + ssc.SRB_CDBLen = 12; + + ssc.CDBByte[0] = 0xA8; /* RAW */ + ssc.CDBByte[2] = (UCHAR) (fd->i_blocks >> 24); + ssc.CDBByte[3] = (UCHAR) (fd->i_blocks >> 16) & 0xff; + ssc.CDBByte[4] = (UCHAR) (fd->i_blocks >> 8) & 0xff; + ssc.CDBByte[5] = (UCHAR) (fd->i_blocks) & 0xff; + + /* We have to break down the reads into 64kb pieces (ASPI restriction) */ + if( i_blocks > 32 ) + { + ssc.SRB_BufLen = 32 * DVDCSS_BLOCK_SIZE; + ssc.CDBByte[9] = 32; + fd->i_blocks += 32; + + /* Initiate transfer */ + ResetEvent( hEvent ); + fd->lpSendCommand( (void*) &ssc ); + + /* transfer the next 64kb (aspi_read_internal is called recursively) + * We need to check the status of the read on return */ + if( aspi_read_internal( i_fd, + (uint8_t*) p_data + 32 * DVDCSS_BLOCK_SIZE, + i_blocks - 32) < 0 ) + { + return -1; + } + } + else + { + /* This is the last transfer */ + ssc.SRB_BufLen = i_blocks * DVDCSS_BLOCK_SIZE; + ssc.CDBByte[9] = (UCHAR) i_blocks; + fd->i_blocks += i_blocks; + + /* Initiate transfer */ + ResetEvent( hEvent ); + fd->lpSendCommand( (void*) &ssc ); + + } + + /* If the command has still not been processed, wait until it's finished */ + if( ssc.SRB_Status == SS_PENDING ) + { + WaitForSingleObject( hEvent, INFINITE ); + } + CloseHandle( hEvent ); + + /* check that the transfer went as planned */ + if( ssc.SRB_Status != SS_COMP ) + { + return -1; + } + + return i_blocks; +} +#endif + diff --git a/lib/libdvd/libdvdcss/src/device.h b/lib/libdvd/libdvdcss/src/device.h new file mode 100644 index 0000000000..d8a73f0d4e --- /dev/null +++ b/lib/libdvd/libdvdcss/src/device.h @@ -0,0 +1,58 @@ +/***************************************************************************** + * device.h: DVD device access + ***************************************************************************** + * Copyright (C) 1998-2002 VideoLAN + * $Id$ + * + * Authors: Stéphane Borel <stef@via.ecp.fr> + * Sam Hocevar <sam@zoy.org> + * HÃ¥kan Hjort <d95hjort@dtek.chalmers.se> + * + * 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, USA. + *****************************************************************************/ + +/***************************************************************************** + * iovec structure: vectored data entry + *****************************************************************************/ +#if defined( WIN32 ) && !defined( SYS_CYGWIN ) +# include <io.h> /* read() */ +#else +# include <sys/types.h> +# include <sys/uio.h> /* struct iovec */ +#endif + +#if defined( WIN32 ) && !defined( SYS_CYGWIN ) +struct iovec +{ + void *iov_base; /* Pointer to data. */ + size_t iov_len; /* Length of data. */ +}; +#endif + +/***************************************************************************** + * Device reading prototypes + *****************************************************************************/ +int _dvdcss_use_ioctls ( dvdcss_t ); +void _dvdcss_check ( dvdcss_t ); +int _dvdcss_open ( dvdcss_t ); +int _dvdcss_close ( dvdcss_t ); + +/***************************************************************************** + * Device reading prototypes, raw-device specific + *****************************************************************************/ +#ifndef WIN32 +int _dvdcss_raw_open ( dvdcss_t, char const * ); +#endif + diff --git a/lib/libdvd/libdvdcss/src/dvdcss/Makefile.am b/lib/libdvd/libdvdcss/src/dvdcss/Makefile.am new file mode 100644 index 0000000000..46746964cb --- /dev/null +++ b/lib/libdvd/libdvdcss/src/dvdcss/Makefile.am @@ -0,0 +1,3 @@ +pkgincludedir = $(includedir)/dvdcss + +pkginclude_HEADERS = dvdcss.h diff --git a/lib/libdvd/libdvdcss/src/dvdcss/dvdcss.h b/lib/libdvd/libdvdcss/src/dvdcss/dvdcss.h new file mode 100644 index 0000000000..c97f996824 --- /dev/null +++ b/lib/libdvd/libdvdcss/src/dvdcss/dvdcss.h @@ -0,0 +1,107 @@ +/** + * \file dvdcss.h + * \author Stéphane Borel <stef@via.ecp.fr> + * \author Sam Hocevar <sam@zoy.org> + * \brief The \e libdvdcss public header. + * + * This header contains the public types and functions that applications + * using \e libdvdcss may use. + */ + +/* + * Copyright (C) 1998-2008 VideoLAN + * $Id$ + * + * 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, USA. + */ + +#ifndef DVDCSS_DVDCSS_H +#ifndef _DOXYGEN_SKIP_ME +#define DVDCSS_DVDCSS_H 1 +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** Library instance handle, to be used for each library call. */ +typedef struct dvdcss_s* dvdcss_t; + + +/** The block size of a DVD. */ +#define DVDCSS_BLOCK_SIZE 2048 + +/** The default flag to be used by \e libdvdcss functions. */ +#define DVDCSS_NOFLAGS 0 + +/** Flag to ask dvdcss_read() to decrypt the data it reads. */ +#define DVDCSS_READ_DECRYPT (1 << 0) + +/** Flag to tell dvdcss_seek() it is seeking in MPEG data. */ +#define DVDCSS_SEEK_MPEG (1 << 0) + +/** Flag to ask dvdcss_seek() to check the current title key. */ +#define DVDCSS_SEEK_KEY (1 << 1) + + +#if defined(LIBDVDCSS_EXPORTS) +#define LIBDVDCSS_EXPORT __declspec(dllexport) extern +#elif defined(LIBDVDCSS_IMPORTS) +#define LIBDVDCSS_EXPORT __declspec(dllimport) extern +#else +#define LIBDVDCSS_EXPORT extern +#endif + +/* + * Our version number. The variable name contains the interface version. + */ +LIBDVDCSS_EXPORT char * dvdcss_interface_2; + + +/* + * Exported prototypes. + */ +LIBDVDCSS_EXPORT dvdcss_t dvdcss_open ( char *psz_target ); +LIBDVDCSS_EXPORT int dvdcss_close ( dvdcss_t ); +LIBDVDCSS_EXPORT int dvdcss_seek ( dvdcss_t, + int i_blocks, + int i_flags ); +LIBDVDCSS_EXPORT int dvdcss_read ( dvdcss_t, + void *p_buffer, + int i_blocks, + int i_flags ); +LIBDVDCSS_EXPORT int dvdcss_readv ( dvdcss_t, + void *p_iovec, + int i_blocks, + int i_flags ); +LIBDVDCSS_EXPORT char * dvdcss_error ( dvdcss_t ); + +LIBDVDCSS_EXPORT int dvdcss_is_scrambled ( dvdcss_t ); + + +/* + * Deprecated stuff. + */ +#ifndef _DOXYGEN_SKIP_ME +#define dvdcss_title(a,b) dvdcss_seek(a,b,DVDCSS_SEEK_KEY) +#define dvdcss_handle dvdcss_t +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* DVDCSS_DVDCSS_H */ diff --git a/lib/libdvd/libdvdcss/src/error.c b/lib/libdvd/libdvdcss/src/error.c new file mode 100644 index 0000000000..66d2b67ad4 --- /dev/null +++ b/lib/libdvd/libdvdcss/src/error.c @@ -0,0 +1,68 @@ +/***************************************************************************** + * error.c: error management functions + ***************************************************************************** + * Copyright (C) 1998-2002 VideoLAN + * $Id$ + * + * Author: Sam Hocevar <sam@zoy.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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, USA. + *****************************************************************************/ + +#include "config.h" + +#include <stdio.h> +#include <stdlib.h> + +#ifdef HAVE_SYS_PARAM_H +# include <sys/param.h> +#endif + +#ifdef HAVE_LIMITS_H +# include <limits.h> +#endif + +#include "dvdcss/dvdcss.h" + +#include "common.h" +#include "css.h" +#include "libdvdcss.h" + +/***************************************************************************** + * Error messages + *****************************************************************************/ +void _print_error( dvdcss_t dvdcss, char *psz_string ) +{ + if( dvdcss->b_errors ) + { + fprintf( stderr, "libdvdcss error: %s\n", psz_string ); + } + + dvdcss->psz_error = psz_string; +} + +/***************************************************************************** + * Debug messages + *****************************************************************************/ +#if 0 +void _print_debug( dvdcss_t dvdcss, char *psz_string ) +{ + if( dvdcss->b_debug ) + { + fprintf( stderr, "libdvdcss debug: %s\n", psz_string ); + } +} +#endif + diff --git a/lib/libdvd/libdvdcss/src/ioctl.c b/lib/libdvd/libdvdcss/src/ioctl.c new file mode 100644 index 0000000000..1e5ebead8f --- /dev/null +++ b/lib/libdvd/libdvdcss/src/ioctl.c @@ -0,0 +1,2183 @@ +/***************************************************************************** + * ioctl.c: DVD ioctl replacement function + ***************************************************************************** + * Copyright (C) 1999-2001 VideoLAN + * $Id$ + * + * Authors: Markus Kuespert <ltlBeBoy@beosmail.com> + * Sam Hocevar <sam@zoy.org> + * Jon Lech Johansen <jon-vl@nanocrew.net> + * HÃ¥kan Hjort <d95hjort@dtek.chalmers.se> + * Eugenio Jarosiewicz <ej0@cise.ufl.edu> + * David Siebörger <drs-videolan@rucus.ru.ac.za> + * Alex Strelnikov <lelik@os2.ru> + * Gildas Bazin <gbazin@netcourrier.com> + * + * 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, USA. + *****************************************************************************/ + +/***************************************************************************** + * Preamble + *****************************************************************************/ +#include "config.h" + +#include <stdio.h> + +#include <string.h> /* memcpy(), memset() */ +#include <sys/types.h> + +#if defined( WIN32 ) +# include <windows.h> +# include <winioctl.h> +#elif defined ( SYS_OS2 ) +# define INCL_DOSFILEMGR +# define INCL_DOSDEVICES +# define INCL_DOSDEVIOCTL +# define INCL_DOSERRORS +# include <os2.h> +# include <sys/ioctl.h> +#else +# include <netinet/in.h> +# include <sys/ioctl.h> +#endif + +#ifdef DVD_STRUCT_IN_SYS_CDIO_H +# include <sys/cdio.h> +#endif +#ifdef DVD_STRUCT_IN_SYS_DVDIO_H +# include <sys/dvdio.h> +#endif +#ifdef DVD_STRUCT_IN_LINUX_CDROM_H +# include <linux/cdrom.h> +#endif +#ifdef DVD_STRUCT_IN_DVD_H +# include <dvd.h> +#endif +#ifdef DVD_STRUCT_IN_BSDI_DVDIOCTL_DVD_H +# include "bsdi_dvd.h" +#endif +#ifdef SYS_BEOS +# include <malloc.h> +# include <scsi.h> +#endif +#ifdef HPUX_SCTL_IO +# include <sys/scsi.h> +#endif +#ifdef SOLARIS_USCSI +# include <dlfcn.h> +# include <unistd.h> +# include <stropts.h> +# include <sys/scsi/scsi_types.h> +# include <sys/scsi/impl/uscsi.h> +#endif +#ifdef DARWIN_DVD_IOCTL +# include <IOKit/storage/IODVDMediaBSDClient.h> +#endif +#ifdef __QNXNTO__ +# include <sys/mman.h> +# include <sys/dcmd_cam.h> +#endif + +#include "common.h" + +#include "ioctl.h" + +/***************************************************************************** + * Local prototypes, BeOS specific + *****************************************************************************/ +#if defined( SYS_BEOS ) +static void BeInitRDC ( raw_device_command *, int ); +#endif + +/***************************************************************************** + * Local prototypes, HP-UX specific + *****************************************************************************/ +#if defined( HPUX_SCTL_IO ) +static void HPUXInitSCTL ( struct sctl_io *sctl_io, int i_type ); +#endif + +/***************************************************************************** + * Local prototypes, Solaris specific + *****************************************************************************/ +#if defined( SOLARIS_USCSI ) +static void SolarisInitUSCSI( struct uscsi_cmd *p_sc, int i_type ); +static int SolarisSendUSCSI( int fd, struct uscsi_cmd *p_sc ); +#endif + +/***************************************************************************** + * Local prototypes, win32 (aspi) specific + *****************************************************************************/ +#if defined( WIN32 ) +static void WinInitSPTD ( SCSI_PASS_THROUGH_DIRECT *, int ); +static void WinInitSSC ( struct SRB_ExecSCSICmd *, int ); +static int WinSendSSC ( int, struct SRB_ExecSCSICmd * ); +#endif + +/***************************************************************************** + * Local prototypes, QNX specific + *****************************************************************************/ +#if defined( __QNXNTO__ ) +static void QNXInitCPT ( CAM_PASS_THRU *, int ); +#endif + +/***************************************************************************** + * Local prototypes, OS2 specific + *****************************************************************************/ +#if defined( SYS_OS2 ) +static void OS2InitSDC( struct OS2_ExecSCSICmd *, int ); +#endif + +/***************************************************************************** + * ioctl_ReadCopyright: check whether the disc is encrypted or not + *****************************************************************************/ +int ioctl_ReadCopyright( int i_fd, int i_layer, int *pi_copyright ) +{ + int i_ret; + +#if defined( HAVE_LINUX_DVD_STRUCT ) + dvd_struct dvd; + + memset( &dvd, 0, sizeof( dvd ) ); + dvd.type = DVD_STRUCT_COPYRIGHT; + dvd.copyright.layer_num = i_layer; + + i_ret = ioctl( i_fd, DVD_READ_STRUCT, &dvd ); + + *pi_copyright = dvd.copyright.cpst; + +#elif defined( HAVE_BSD_DVD_STRUCT ) + struct dvd_struct dvd; + + memset( &dvd, 0, sizeof( dvd ) ); + dvd.format = DVD_STRUCT_COPYRIGHT; + dvd.layer_num = i_layer; + + i_ret = ioctl( i_fd, DVDIOCREADSTRUCTURE, &dvd ); + + *pi_copyright = dvd.cpst; + +#elif defined( SYS_BEOS ) + INIT_RDC( GPCMD_READ_DVD_STRUCTURE, 8 ); + + rdc.command[ 6 ] = i_layer; + rdc.command[ 7 ] = DVD_STRUCT_COPYRIGHT; + + i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) ); + + *pi_copyright = p_buffer[ 4 ]; + +#elif defined( HPUX_SCTL_IO ) + INIT_SCTL_IO( GPCMD_READ_DVD_STRUCTURE, 8 ); + + sctl_io.cdb[ 6 ] = i_layer; + sctl_io.cdb[ 7 ] = DVD_STRUCT_COPYRIGHT; + + i_ret = ioctl( i_fd, SIOC_IO, &sctl_io ); + + *pi_copyright = p_buffer[ 4 ]; + +#elif defined( SOLARIS_USCSI ) + INIT_USCSI( GPCMD_READ_DVD_STRUCTURE, 8 ); + + rs_cdb.cdb_opaque[ 6 ] = i_layer; + rs_cdb.cdb_opaque[ 7 ] = DVD_STRUCT_COPYRIGHT; + + i_ret = SolarisSendUSCSI(i_fd, &sc); + + if( i_ret < 0 || sc.uscsi_status ) { + i_ret = -1; + } + + *pi_copyright = p_buffer[ 4 ]; + /* s->copyright.rmi = p_buffer[ 5 ]; */ + +#elif defined( DARWIN_DVD_IOCTL ) + INIT_DVDIOCTL( dk_dvd_read_structure_t, DVDCopyrightInfo, + kDVDStructureFormatCopyrightInfo ); + + dvd.layer = i_layer; + + i_ret = ioctl( i_fd, DKIOCDVDREADSTRUCTURE, &dvd ); + + *pi_copyright = dvdbs.copyrightProtectionSystemType; + +#elif defined( WIN32 ) + if( WIN2K ) /* NT/2k/XP */ + { + INIT_SPTD( GPCMD_READ_DVD_STRUCTURE, 8 ); + + /* When using IOCTL_DVD_READ_STRUCTURE and + DVD_COPYRIGHT_DESCRIPTOR, CopyrightProtectionType + seems to be always 6 ??? + To work around this MS bug we try to send a raw scsi command + instead (if we've got enough privileges to do so). */ + + sptd.Cdb[ 6 ] = i_layer; + sptd.Cdb[ 7 ] = DVD_STRUCT_COPYRIGHT; + + i_ret = SEND_SPTD( i_fd, &sptd, &tmp ); + + if( i_ret == 0 ) + { + *pi_copyright = p_buffer[ 4 ]; + } + } + else + { + INIT_SSC( GPCMD_READ_DVD_STRUCTURE, 8 ); + + ssc.CDBByte[ 6 ] = i_layer; + ssc.CDBByte[ 7 ] = DVD_STRUCT_COPYRIGHT; + + i_ret = WinSendSSC( i_fd, &ssc ); + + *pi_copyright = p_buffer[ 4 ]; + } + +#elif defined( __QNXNTO__ ) + + INIT_CPT( GPCMD_READ_DVD_STRUCTURE, 8 ); + + p_cpt->cam_cdb[ 6 ] = i_layer; + p_cpt->cam_cdb[ 7 ] = DVD_STRUCT_COPYRIGHT; + + i_ret = devctl(i_fd, DCMD_CAM_PASS_THRU, p_cpt, structSize, NULL); + + *pi_copyright = p_buffer[4]; + +#elif defined( SYS_OS2 ) + INIT_SSC( GPCMD_READ_DVD_STRUCTURE, 8 ); + + sdc.command[ 6 ] = i_layer; + sdc.command[ 7 ] = DVD_STRUCT_COPYRIGHT; + + i_ret = DosDevIOCtl(i_fd, IOCTL_CDROMDISK, CDROMDISK_EXECMD, + &sdc, sizeof(sdc), &ulParamLen, + p_buffer, sizeof(p_buffer), &ulDataLen); + + *pi_copyright = p_buffer[ 4 ]; + +#else +# error "DVD ioctls are unavailable on this system" + +#endif + return i_ret; +} + +/***************************************************************************** + * ioctl_ReadDiscKey: get the disc key + *****************************************************************************/ +int ioctl_ReadDiscKey( int i_fd, int *pi_agid, uint8_t *p_key ) +{ + int i_ret; + +#if defined( HAVE_LINUX_DVD_STRUCT ) + dvd_struct dvd; + + memset( &dvd, 0, sizeof( dvd ) ); + dvd.type = DVD_STRUCT_DISCKEY; + dvd.disckey.agid = *pi_agid; + memset( dvd.disckey.value, 0, DVD_DISCKEY_SIZE ); + + i_ret = ioctl( i_fd, DVD_READ_STRUCT, &dvd ); + + if( i_ret < 0 ) + { + return i_ret; + } + + memcpy( p_key, dvd.disckey.value, DVD_DISCKEY_SIZE ); + +#elif defined( HAVE_BSD_DVD_STRUCT ) + struct dvd_struct dvd; + + memset( &dvd, 0, sizeof( dvd ) ); + dvd.format = DVD_STRUCT_DISCKEY; + dvd.agid = *pi_agid; + memset( dvd.data, 0, DVD_DISCKEY_SIZE ); + + i_ret = ioctl( i_fd, DVDIOCREADSTRUCTURE, &dvd ); + + if( i_ret < 0 ) + { + return i_ret; + } + + memcpy( p_key, dvd.data, DVD_DISCKEY_SIZE ); + +#elif defined( SYS_BEOS ) + INIT_RDC( GPCMD_READ_DVD_STRUCTURE, DVD_DISCKEY_SIZE + 4 ); + + rdc.command[ 7 ] = DVD_STRUCT_DISCKEY; + rdc.command[ 10 ] = *pi_agid << 6; + + i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) ); + + if( i_ret < 0 ) + { + return i_ret; + } + + memcpy( p_key, p_buffer + 4, DVD_DISCKEY_SIZE ); + +#elif defined( HPUX_SCTL_IO ) + INIT_SCTL_IO( GPCMD_READ_DVD_STRUCTURE, DVD_DISCKEY_SIZE + 4 ); + + sctl_io.cdb[ 7 ] = DVD_STRUCT_DISCKEY; + sctl_io.cdb[ 10 ] = *pi_agid << 6; + + i_ret = ioctl( i_fd, SIOC_IO, &sctl_io ); + + if( i_ret < 0 ) + { + return i_ret; + } + + memcpy( p_key, p_buffer + 4, DVD_DISCKEY_SIZE ); + +#elif defined( SOLARIS_USCSI ) + INIT_USCSI( GPCMD_READ_DVD_STRUCTURE, DVD_DISCKEY_SIZE + 4 ); + + rs_cdb.cdb_opaque[ 7 ] = DVD_STRUCT_DISCKEY; + rs_cdb.cdb_opaque[ 10 ] = *pi_agid << 6; + + i_ret = SolarisSendUSCSI( i_fd, &sc ); + + if( i_ret < 0 || sc.uscsi_status ) + { + i_ret = -1; + return i_ret; + } + + memcpy( p_key, p_buffer + 4, DVD_DISCKEY_SIZE ); + +#elif defined( DARWIN_DVD_IOCTL ) + INIT_DVDIOCTL( dk_dvd_read_structure_t, DVDDiscKeyInfo, + kDVDStructureFormatDiscKeyInfo ); + + dvd.grantID = *pi_agid; + + i_ret = ioctl( i_fd, DKIOCDVDREADSTRUCTURE, &dvd ); + + memcpy( p_key, dvdbs.discKeyStructures, DVD_DISCKEY_SIZE ); + +#elif defined( _XBOX ) + // the next piece of code will read the disc key on the xbox for all drives (samsung included) + // but for some reason it takes 15 - 20 seconds longer to load a dvd if mplayer has the dvd key + // so we let this part fail and will only use the modified ioctl_ReadTitleKey code. + // don't get this delay, and i'm surprised it worked as the ReadTitleKey function didn't work. + + DWORD dwBytesRead; + DVD_READ_STRUCTURE st; + char buffer[DVD_DISCKEY_SIZE]; + + memset( &buffer, 0, sizeof( buffer ) ); + memset( &st, 0, sizeof( st ) ); + + st.BlockByteOffset.QuadPart = 0; + st.SessionId = *pi_agid; + st.Format = DvdDiskKeyDescriptor; + + i_ret = DeviceIoControl((HANDLE) i_fd, IOCTL_DVD_READ_STRUCTURE, &st, + sizeof(st), buffer, DVD_DISCKEY_SIZE, &dwBytesRead, NULL ) ? 0 : -1; + + if (i_ret < 0) // didn't work + { + printf("Failed to read disc key\n"); + return i_ret; + } + + // copy the returned key into our key buffer + int i; + for (i = 0; i < DVD_DISCKEY_SIZE; i++) + p_key[i] = buffer[i+4]; + +#elif defined( WIN32 ) + if( WIN2K ) /* NT/2k/XP */ + { + DWORD tmp; + uint8_t buffer[DVD_DISK_KEY_LENGTH]; + PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer; + + memset( &buffer, 0, sizeof( buffer ) ); + + key->KeyLength = DVD_DISK_KEY_LENGTH; + key->SessionId = *pi_agid; + key->KeyType = DvdDiskKey; + key->KeyFlags = 0; + + i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key, + key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1; + + if( i_ret < 0 ) + { + return i_ret; + } + + memcpy( p_key, key->KeyData, DVD_DISCKEY_SIZE ); + } + else + { + INIT_SSC( GPCMD_READ_DVD_STRUCTURE, DVD_DISCKEY_SIZE + 4 ); + + ssc.CDBByte[ 7 ] = DVD_STRUCT_DISCKEY; + ssc.CDBByte[ 10 ] = *pi_agid << 6; + + i_ret = WinSendSSC( i_fd, &ssc ); + + if( i_ret < 0 ) + { + return i_ret; + } + + memcpy( p_key, p_buffer + 4, DVD_DISCKEY_SIZE ); + } + +#elif defined( __QNXNTO__ ) + + INIT_CPT( GPCMD_READ_DVD_STRUCTURE, DVD_DISCKEY_SIZE + 4 ); + + p_cpt->cam_cdb[ 7 ] = DVD_STRUCT_DISCKEY; + p_cpt->cam_cdb[ 10 ] = *pi_agid << 6; + + i_ret = devctl(i_fd, DCMD_CAM_PASS_THRU, p_cpt, structSize, NULL); + + memcpy( p_key, p_buffer + 4, DVD_DISCKEY_SIZE ); + +#elif defined ( SYS_OS2 ) + INIT_SSC( GPCMD_READ_DVD_STRUCTURE, DVD_DISCKEY_SIZE + 4 ); + + sdc.command[ 7 ] = DVD_STRUCT_DISCKEY; + sdc.command[ 10 ] = *pi_agid << 6; + + i_ret = DosDevIOCtl(i_fd, IOCTL_CDROMDISK, CDROMDISK_EXECMD, + &sdc, sizeof(sdc), &ulParamLen, + p_buffer, sizeof(p_buffer), &ulDataLen); + + if( i_ret < 0 ) + { + return i_ret; + } + + memcpy( p_key, p_buffer + 4, DVD_DISCKEY_SIZE ); + +#else +# error "DVD ioctls are unavailable on this system" + +#endif + return i_ret; +} + +/***************************************************************************** + * ioctl_ReadTitleKey: get the title key + *****************************************************************************/ +int ioctl_ReadTitleKey( int i_fd, int *pi_agid, int i_pos, uint8_t *p_key ) +{ + int i_ret; + +#if defined( HAVE_LINUX_DVD_STRUCT ) + dvd_authinfo auth_info; + + memset( &auth_info, 0, sizeof( auth_info ) ); + auth_info.type = DVD_LU_SEND_TITLE_KEY; + auth_info.lstk.agid = *pi_agid; + auth_info.lstk.lba = i_pos; + + i_ret = ioctl( i_fd, DVD_AUTH, &auth_info ); + + memcpy( p_key, auth_info.lstk.title_key, DVD_KEY_SIZE ); + +#elif defined( HAVE_BSD_DVD_STRUCT ) + struct dvd_authinfo auth_info; + + memset( &auth_info, 0, sizeof( auth_info ) ); + auth_info.format = DVD_REPORT_TITLE_KEY; + auth_info.agid = *pi_agid; + auth_info.lba = i_pos; + + i_ret = ioctl( i_fd, DVDIOCREPORTKEY, &auth_info ); + + memcpy( p_key, auth_info.keychal, DVD_KEY_SIZE ); + +#elif defined( SYS_BEOS ) + INIT_RDC( GPCMD_REPORT_KEY, 12 ); + + rdc.command[ 2 ] = ( i_pos >> 24 ) & 0xff; + rdc.command[ 3 ] = ( i_pos >> 16 ) & 0xff; + rdc.command[ 4 ] = ( i_pos >> 8 ) & 0xff; + rdc.command[ 5 ] = ( i_pos ) & 0xff; + rdc.command[ 10 ] = DVD_REPORT_TITLE_KEY | (*pi_agid << 6); + + i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) ); + + memcpy( p_key, p_buffer + 5, DVD_KEY_SIZE ); + +#elif defined( HPUX_SCTL_IO ) + INIT_SCTL_IO( GPCMD_REPORT_KEY, 12 ); + + sctl_io.cdb[ 2 ] = ( i_pos >> 24 ) & 0xff; + sctl_io.cdb[ 3 ] = ( i_pos >> 16 ) & 0xff; + sctl_io.cdb[ 4 ] = ( i_pos >> 8 ) & 0xff; + sctl_io.cdb[ 5 ] = ( i_pos ) & 0xff; + sctl_io.cdb[ 10 ] = DVD_REPORT_TITLE_KEY | (*pi_agid << 6); + + i_ret = ioctl( i_fd, SIOC_IO, &sctl_io ); + + memcpy( p_key, p_buffer + 5, DVD_KEY_SIZE ); + +#elif defined( SOLARIS_USCSI ) + INIT_USCSI( GPCMD_REPORT_KEY, 12 ); + + rs_cdb.cdb_opaque[ 2 ] = ( i_pos >> 24 ) & 0xff; + rs_cdb.cdb_opaque[ 3 ] = ( i_pos >> 16 ) & 0xff; + rs_cdb.cdb_opaque[ 4 ] = ( i_pos >> 8 ) & 0xff; + rs_cdb.cdb_opaque[ 5 ] = ( i_pos ) & 0xff; + rs_cdb.cdb_opaque[ 10 ] = DVD_REPORT_TITLE_KEY | (*pi_agid << 6); + + i_ret = SolarisSendUSCSI( i_fd, &sc ); + + if( i_ret < 0 || sc.uscsi_status ) + { + i_ret = -1; + } + + /* Do we want to return the cp_sec flag perhaps? */ + /* a->lstk.cpm = (buf[ 4 ] >> 7) & 1; */ + /* a->lstk.cp_sec = (buf[ 4 ] >> 6) & 1; */ + /* a->lstk.cgms = (buf[ 4 ] >> 4) & 3; */ + + memcpy( p_key, p_buffer + 5, DVD_KEY_SIZE ); + +#elif defined( DARWIN_DVD_IOCTL ) + INIT_DVDIOCTL( dk_dvd_report_key_t, DVDTitleKeyInfo, + kDVDKeyFormatTitleKey ); + + dvd.address = i_pos; + dvd.grantID = *pi_agid; + dvd.keyClass = kDVDKeyClassCSS_CPPM_CPRM; + + i_ret = ioctl( i_fd, DKIOCDVDREPORTKEY, &dvd ); + + memcpy( p_key, dvdbs.titleKeyValue, DVD_KEY_SIZE ); + +#elif defined( _XBOX ) && 0 //Faulty wrong key returned, original for WIN32 works thou so use it instead + DWORD dwBytesRead; + DVD_READ_STRUCTURE st; + char buffer[2048+4]; + + memset( &buffer, 0, sizeof( buffer ) ); + + st.BlockByteOffset.QuadPart = (LONGLONG) i_pos * 2048 /*DVDCSS_BLOCK_SIZE*/; + st.SessionId = *pi_agid; + st.Format = DvdDiskKeyDescriptor; + + i_ret = DeviceIoControl((HANDLE) i_fd, IOCTL_DVD_READ_STRUCTURE, &st, sizeof(st), buffer, 2048+4, &dwBytesRead, NULL ) ? 0 : -1; + if( i_ret < 0 ) + { + return i_ret; + } + + memcpy( p_key, &(buffer[4]), 2048); + +#elif defined( WIN32 ) + if( WIN2K ) /* NT/2k/XP */ + { + DWORD tmp; + uint8_t buffer[DVD_TITLE_KEY_LENGTH]; + PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer; + + memset( &buffer, 0, sizeof( buffer ) ); + + key->KeyLength = DVD_TITLE_KEY_LENGTH; + key->SessionId = *pi_agid; + key->KeyType = DvdTitleKey; + key->KeyFlags = 0; + key->Parameters.TitleOffset.QuadPart = (LONGLONG) i_pos * + 2048 /*DVDCSS_BLOCK_SIZE*/; + + i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key, + key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1; + + memcpy( p_key, key->KeyData, DVD_KEY_SIZE ); + } + else + { + INIT_SSC( GPCMD_REPORT_KEY, 12 ); + + ssc.CDBByte[ 2 ] = ( i_pos >> 24 ) & 0xff; + ssc.CDBByte[ 3 ] = ( i_pos >> 16 ) & 0xff; + ssc.CDBByte[ 4 ] = ( i_pos >> 8 ) & 0xff; + ssc.CDBByte[ 5 ] = ( i_pos ) & 0xff; + ssc.CDBByte[ 10 ] = DVD_REPORT_TITLE_KEY | (*pi_agid << 6); + + i_ret = WinSendSSC( i_fd, &ssc ); + + memcpy( p_key, p_buffer + 5, DVD_KEY_SIZE ); + } + +#elif defined( __QNXNTO__ ) + + INIT_CPT( GPCMD_REPORT_KEY, 12 ); + + p_cpt->cam_cdb[ 2 ] = ( i_pos >> 24 ) & 0xff; + p_cpt->cam_cdb[ 3 ] = ( i_pos >> 16 ) & 0xff; + p_cpt->cam_cdb[ 4 ] = ( i_pos >> 8 ) & 0xff; + p_cpt->cam_cdb[ 5 ] = ( i_pos ) & 0xff; + p_cpt->cam_cdb[ 10 ] = DVD_REPORT_TITLE_KEY | (*pi_agid << 6); + + i_ret = devctl(i_fd, DCMD_CAM_PASS_THRU, p_cpt, structSize, NULL); + + memcpy( p_key, p_buffer + 5, DVD_KEY_SIZE ); + +#elif defined( SYS_OS2 ) + INIT_SSC( GPCMD_REPORT_KEY, 12 ); + + sdc.command[ 2 ] = ( i_pos >> 24 ) & 0xff; + sdc.command[ 3 ] = ( i_pos >> 16 ) & 0xff; + sdc.command[ 4 ] = ( i_pos >> 8 ) & 0xff; + sdc.command[ 5 ] = ( i_pos ) & 0xff; + sdc.command[ 10 ] = DVD_REPORT_TITLE_KEY | (*pi_agid << 6); + + i_ret = DosDevIOCtl(i_fd, IOCTL_CDROMDISK, CDROMDISK_EXECMD, + &sdc, sizeof(sdc), &ulParamLen, + p_buffer, sizeof(p_buffer), &ulDataLen); + + memcpy( p_key, p_buffer + 5, DVD_KEY_SIZE ); + +#else +# error "DVD ioctls are unavailable on this system" + +#endif + + return i_ret; +} + + +/***************************************************************************** + * ioctl_ReportAgid: get AGID from the drive + *****************************************************************************/ +int ioctl_ReportAgid( int i_fd, int *pi_agid ) +{ + int i_ret; + +#if defined( HAVE_LINUX_DVD_STRUCT ) + dvd_authinfo auth_info; + + memset( &auth_info, 0, sizeof( auth_info ) ); + auth_info.type = DVD_LU_SEND_AGID; + auth_info.lsa.agid = *pi_agid; + + i_ret = ioctl( i_fd, DVD_AUTH, &auth_info ); + + *pi_agid = auth_info.lsa.agid; + +#elif defined( HAVE_BSD_DVD_STRUCT ) + struct dvd_authinfo auth_info; + + memset( &auth_info, 0, sizeof( auth_info ) ); + auth_info.format = DVD_REPORT_AGID; + auth_info.agid = *pi_agid; + + i_ret = ioctl( i_fd, DVDIOCREPORTKEY, &auth_info ); + + *pi_agid = auth_info.agid; + +#elif defined( SYS_BEOS ) + INIT_RDC( GPCMD_REPORT_KEY, 8 ); + + rdc.command[ 10 ] = DVD_REPORT_AGID | (*pi_agid << 6); + + i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) ); + + *pi_agid = p_buffer[ 7 ] >> 6; + +#elif defined( HPUX_SCTL_IO ) + INIT_SCTL_IO( GPCMD_REPORT_KEY, 8 ); + + sctl_io.cdb[ 10 ] = DVD_REPORT_AGID | (*pi_agid << 6); + + i_ret = ioctl( i_fd, SIOC_IO, &sctl_io ); + + *pi_agid = p_buffer[ 7 ] >> 6; + +#elif defined( SOLARIS_USCSI ) + INIT_USCSI( GPCMD_REPORT_KEY, 8 ); + + rs_cdb.cdb_opaque[ 10 ] = DVD_REPORT_AGID | (*pi_agid << 6); + + i_ret = SolarisSendUSCSI( i_fd, &sc ); + + if( i_ret < 0 || sc.uscsi_status ) + { + i_ret = -1; + } + + *pi_agid = p_buffer[ 7 ] >> 6; + +#elif defined( DARWIN_DVD_IOCTL ) + INIT_DVDIOCTL( dk_dvd_report_key_t, DVDAuthenticationGrantIDInfo, + kDVDKeyFormatAGID_CSS ); + + dvd.grantID = *pi_agid; + dvd.keyClass = kDVDKeyClassCSS_CPPM_CPRM; + + i_ret = ioctl( i_fd, DKIOCDVDREPORTKEY, &dvd ); + + *pi_agid = dvdbs.grantID; + +#elif defined( WIN32 ) + if( WIN2K ) /* NT/2k/XP */ + { + ULONG id; + DWORD tmp; + +#if defined( _XBOX) + i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_START_SESSION, + NULL, 0, &id, sizeof(id), &tmp, NULL ) ? 0 : -1; +#else + i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_START_SESSION, + &tmp, 4, &id, sizeof( id ), &tmp, NULL ) ? 0 : -1; +#endif + + *pi_agid = id; + } + else + { + INIT_SSC( GPCMD_REPORT_KEY, 8 ); + + ssc.CDBByte[ 10 ] = DVD_REPORT_AGID | (*pi_agid << 6); + + i_ret = WinSendSSC( i_fd, &ssc ); + + *pi_agid = p_buffer[ 7 ] >> 6; + } + +#elif defined( __QNXNTO__ ) + + INIT_CPT( GPCMD_REPORT_KEY, 8 ); + + p_cpt->cam_cdb[ 10 ] = DVD_REPORT_AGID | (*pi_agid << 6); + + i_ret = devctl(i_fd, DCMD_CAM_PASS_THRU, p_cpt, structSize, NULL); + + *pi_agid = p_buffer[ 7 ] >> 6; + +#elif defined( SYS_OS2 ) + INIT_SSC( GPCMD_REPORT_KEY, 8 ); + + sdc.command[ 10 ] = DVD_REPORT_AGID | (*pi_agid << 6); + + i_ret = DosDevIOCtl(i_fd, IOCTL_CDROMDISK, CDROMDISK_EXECMD, + &sdc, sizeof(sdc), &ulParamLen, + p_buffer, sizeof(p_buffer), &ulDataLen); + + *pi_agid = p_buffer[ 7 ] >> 6; + +#else +# error "DVD ioctls are unavailable on this system" + +#endif + return i_ret; +} + +/***************************************************************************** + * ioctl_ReportChallenge: get challenge from the drive + *****************************************************************************/ +int ioctl_ReportChallenge( int i_fd, int *pi_agid, uint8_t *p_challenge ) +{ + int i_ret; + +#if defined( HAVE_LINUX_DVD_STRUCT ) + dvd_authinfo auth_info; + + memset( &auth_info, 0, sizeof( auth_info ) ); + auth_info.type = DVD_LU_SEND_CHALLENGE; + auth_info.lsc.agid = *pi_agid; + + i_ret = ioctl( i_fd, DVD_AUTH, &auth_info ); + + memcpy( p_challenge, auth_info.lsc.chal, DVD_CHALLENGE_SIZE ); + +#elif defined( HAVE_BSD_DVD_STRUCT ) + struct dvd_authinfo auth_info; + + memset( &auth_info, 0, sizeof( auth_info ) ); + auth_info.format = DVD_REPORT_CHALLENGE; + auth_info.agid = *pi_agid; + + i_ret = ioctl( i_fd, DVDIOCREPORTKEY, &auth_info ); + + memcpy( p_challenge, auth_info.keychal, DVD_CHALLENGE_SIZE ); + +#elif defined( SYS_BEOS ) + INIT_RDC( GPCMD_REPORT_KEY, 16 ); + + rdc.command[ 10 ] = DVD_REPORT_CHALLENGE | (*pi_agid << 6); + + i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) ); + + memcpy( p_challenge, p_buffer + 4, DVD_CHALLENGE_SIZE ); + +#elif defined( HPUX_SCTL_IO ) + INIT_SCTL_IO( GPCMD_REPORT_KEY, 16 ); + + sctl_io.cdb[ 10 ] = DVD_REPORT_CHALLENGE | (*pi_agid << 6); + + i_ret = ioctl( i_fd, SIOC_IO, &sctl_io ); + + memcpy( p_challenge, p_buffer + 4, DVD_CHALLENGE_SIZE ); + +#elif defined( SOLARIS_USCSI ) + INIT_USCSI( GPCMD_REPORT_KEY, 16 ); + + rs_cdb.cdb_opaque[ 10 ] = DVD_REPORT_CHALLENGE | (*pi_agid << 6); + + i_ret = SolarisSendUSCSI( i_fd, &sc ); + + if( i_ret < 0 || sc.uscsi_status ) + { + i_ret = -1; + } + + memcpy( p_challenge, p_buffer + 4, DVD_CHALLENGE_SIZE ); + +#elif defined( DARWIN_DVD_IOCTL ) + INIT_DVDIOCTL( dk_dvd_report_key_t, DVDChallengeKeyInfo, + kDVDKeyFormatChallengeKey ); + + dvd.grantID = *pi_agid; + + i_ret = ioctl( i_fd, DKIOCDVDREPORTKEY, &dvd ); + + memcpy( p_challenge, dvdbs.challengeKeyValue, DVD_CHALLENGE_SIZE ); + +#elif defined( WIN32 ) + if( WIN2K ) /* NT/2k/XP */ + { + DWORD tmp; + uint8_t buffer[DVD_CHALLENGE_KEY_LENGTH]; + PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer; + + memset( &buffer, 0, sizeof( buffer ) ); + + key->KeyLength = DVD_CHALLENGE_KEY_LENGTH; + key->SessionId = *pi_agid; + key->KeyType = DvdChallengeKey; + key->KeyFlags = 0; + + i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key, + key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1; + + if( i_ret < 0 ) + { + return i_ret; + } + + memcpy( p_challenge, key->KeyData, DVD_CHALLENGE_SIZE ); + } + else + { + INIT_SSC( GPCMD_REPORT_KEY, 16 ); + + ssc.CDBByte[ 10 ] = DVD_REPORT_CHALLENGE | (*pi_agid << 6); + + i_ret = WinSendSSC( i_fd, &ssc ); + + memcpy( p_challenge, p_buffer + 4, DVD_CHALLENGE_SIZE ); + } + +#elif defined( __QNXNTO__ ) + + INIT_CPT( GPCMD_REPORT_KEY, 16 ); + + p_cpt->cam_cdb[ 10 ] = DVD_REPORT_CHALLENGE | (*pi_agid << 6); + + i_ret = devctl(i_fd, DCMD_CAM_PASS_THRU, p_cpt, structSize, NULL); + + memcpy( p_challenge, p_buffer + 4, DVD_CHALLENGE_SIZE ); + +#elif defined( SYS_OS2 ) + INIT_SSC( GPCMD_REPORT_KEY, 16 ); + + sdc.command[ 10 ] = DVD_REPORT_CHALLENGE | (*pi_agid << 6); + + i_ret = DosDevIOCtl(i_fd, IOCTL_CDROMDISK, CDROMDISK_EXECMD, + &sdc, sizeof(sdc), &ulParamLen, + p_buffer, sizeof(p_buffer), &ulDataLen); + + memcpy( p_challenge, p_buffer + 4, DVD_CHALLENGE_SIZE ); + +#else +# error "DVD ioctls are unavailable on this system" + +#endif + return i_ret; +} + +/***************************************************************************** + * ioctl_ReportASF: get ASF from the drive + *****************************************************************************/ +int ioctl_ReportASF( int i_fd, int *pi_remove_me, int *pi_asf ) +{ + int i_ret; + +#if defined( HAVE_LINUX_DVD_STRUCT ) + dvd_authinfo auth_info; + + memset( &auth_info, 0, sizeof( auth_info ) ); + auth_info.type = DVD_LU_SEND_ASF; + auth_info.lsasf.asf = *pi_asf; + + i_ret = ioctl( i_fd, DVD_AUTH, &auth_info ); + + *pi_asf = auth_info.lsasf.asf; + +#elif defined( HAVE_BSD_DVD_STRUCT ) + struct dvd_authinfo auth_info; + + memset( &auth_info, 0, sizeof( auth_info ) ); + auth_info.format = DVD_REPORT_ASF; + auth_info.asf = *pi_asf; + + i_ret = ioctl( i_fd, DVDIOCREPORTKEY, &auth_info ); + + *pi_asf = auth_info.asf; + +#elif defined( SYS_BEOS ) + INIT_RDC( GPCMD_REPORT_KEY, 8 ); + + rdc.command[ 10 ] = DVD_REPORT_ASF; + + i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) ); + + *pi_asf = p_buffer[ 7 ] & 1; + +#elif defined( HPUX_SCTL_IO ) + INIT_SCTL_IO( GPCMD_REPORT_KEY, 8 ); + + sctl_io.cdb[ 10 ] = DVD_REPORT_ASF; + + i_ret = ioctl( i_fd, SIOC_IO, &sctl_io ); + + *pi_asf = p_buffer[ 7 ] & 1; + +#elif defined( SOLARIS_USCSI ) + INIT_USCSI( GPCMD_REPORT_KEY, 8 ); + + rs_cdb.cdb_opaque[ 10 ] = DVD_REPORT_ASF; + + i_ret = SolarisSendUSCSI( i_fd, &sc ); + + if( i_ret < 0 || sc.uscsi_status ) + { + i_ret = -1; + } + + *pi_asf = p_buffer[ 7 ] & 1; + +#elif defined( DARWIN_DVD_IOCTL ) + INIT_DVDIOCTL( dk_dvd_report_key_t, DVDAuthenticationSuccessFlagInfo, + kDVDKeyFormatASF ); + + i_ret = ioctl( i_fd, DKIOCDVDREPORTKEY, &dvd ); + + *pi_asf = dvdbs.successFlag; + +#elif defined( WIN32 ) + if( WIN2K ) /* NT/2k/XP */ + { + DWORD tmp; + uint8_t buffer[DVD_ASF_LENGTH]; + PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer; + + memset( &buffer, 0, sizeof( buffer ) ); + + key->KeyLength = DVD_ASF_LENGTH; + key->KeyType = DvdAsf; + key->KeyFlags = 0; + + ((PDVD_ASF)key->KeyData)->SuccessFlag = *pi_asf; + + i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key, + key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1; + + if( i_ret < 0 ) + { + return i_ret; + } + + *pi_asf = ((PDVD_ASF)key->KeyData)->SuccessFlag; + } + else + { + INIT_SSC( GPCMD_REPORT_KEY, 8 ); + + ssc.CDBByte[ 10 ] = DVD_REPORT_ASF; + + i_ret = WinSendSSC( i_fd, &ssc ); + + *pi_asf = p_buffer[ 7 ] & 1; + } + +#elif defined( __QNXNTO__ ) + + INIT_CPT( GPCMD_REPORT_KEY, 8 ); + + p_cpt->cam_cdb[ 10 ] = DVD_REPORT_ASF; + + i_ret = devctl(i_fd, DCMD_CAM_PASS_THRU, p_cpt, structSize, NULL); + + *pi_asf = p_buffer[ 7 ] & 1; + +#elif defined( SYS_OS2 ) + INIT_SSC( GPCMD_REPORT_KEY, 8 ); + + sdc.command[ 10 ] = DVD_REPORT_ASF; + + i_ret = DosDevIOCtl(i_fd, IOCTL_CDROMDISK, CDROMDISK_EXECMD, + &sdc, sizeof(sdc), &ulParamLen, + p_buffer, sizeof(p_buffer), &ulDataLen); + + *pi_asf = p_buffer[ 7 ] & 1; + +#else +# error "DVD ioctls are unavailable on this system" + +#endif + return i_ret; +} + +/***************************************************************************** + * ioctl_ReportKey1: get the first key from the drive + *****************************************************************************/ +int ioctl_ReportKey1( int i_fd, int *pi_agid, uint8_t *p_key ) +{ + int i_ret; + +#if defined( HAVE_LINUX_DVD_STRUCT ) + dvd_authinfo auth_info; + + memset( &auth_info, 0, sizeof( auth_info ) ); + auth_info.type = DVD_LU_SEND_KEY1; + auth_info.lsk.agid = *pi_agid; + + i_ret = ioctl( i_fd, DVD_AUTH, &auth_info ); + + memcpy( p_key, auth_info.lsk.key, DVD_KEY_SIZE ); + +#elif defined( HAVE_BSD_DVD_STRUCT ) + struct dvd_authinfo auth_info; + + memset( &auth_info, 0, sizeof( auth_info ) ); + auth_info.format = DVD_REPORT_KEY1; + auth_info.agid = *pi_agid; + + i_ret = ioctl( i_fd, DVDIOCREPORTKEY, &auth_info ); + + memcpy( p_key, auth_info.keychal, DVD_KEY_SIZE ); + +#elif defined( SYS_BEOS ) + INIT_RDC( GPCMD_REPORT_KEY, 12 ); + + rdc.command[ 10 ] = DVD_REPORT_KEY1 | (*pi_agid << 6); + + i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) ); + + memcpy( p_key, p_buffer + 4, DVD_KEY_SIZE ); + +#elif defined( HPUX_SCTL_IO ) + INIT_SCTL_IO( GPCMD_REPORT_KEY, 12 ); + + sctl_io.cdb[ 10 ] = DVD_REPORT_KEY1 | (*pi_agid << 6); + + i_ret = ioctl( i_fd, SIOC_IO, &sctl_io ); + + memcpy( p_key, p_buffer + 4, DVD_KEY_SIZE ); + +#elif defined( SOLARIS_USCSI ) + INIT_USCSI( GPCMD_REPORT_KEY, 12 ); + + rs_cdb.cdb_opaque[ 10 ] = DVD_REPORT_KEY1 | (*pi_agid << 6); + + i_ret = SolarisSendUSCSI( i_fd, &sc ); + + if( i_ret < 0 || sc.uscsi_status ) + { + i_ret = -1; + } + + memcpy( p_key, p_buffer + 4, DVD_KEY_SIZE ); + +#elif defined( DARWIN_DVD_IOCTL ) + INIT_DVDIOCTL( dk_dvd_report_key_t, DVDKey1Info, + kDVDKeyFormatKey1 ); + + dvd.grantID = *pi_agid; + + i_ret = ioctl( i_fd, DKIOCDVDREPORTKEY, &dvd ); + + memcpy( p_key, dvdbs.key1Value, DVD_KEY_SIZE ); + +#elif defined( WIN32 ) + if( WIN2K ) /* NT/2k/XP */ + { + DWORD tmp; + uint8_t buffer[DVD_BUS_KEY_LENGTH]; + PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer; + + memset( &buffer, 0, sizeof( buffer ) ); + + key->KeyLength = DVD_BUS_KEY_LENGTH; + key->SessionId = *pi_agid; + key->KeyType = DvdBusKey1; + key->KeyFlags = 0; + + i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key, + key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1; + + memcpy( p_key, key->KeyData, DVD_KEY_SIZE ); + } + else + { + INIT_SSC( GPCMD_REPORT_KEY, 12 ); + + ssc.CDBByte[ 10 ] = DVD_REPORT_KEY1 | (*pi_agid << 6); + + i_ret = WinSendSSC( i_fd, &ssc ); + + memcpy( p_key, p_buffer + 4, DVD_KEY_SIZE ); + } + +#elif defined( __QNXNTO__ ) + + INIT_CPT( GPCMD_REPORT_KEY, 12 ); + + p_cpt->cam_cdb[ 10 ] = DVD_REPORT_KEY1 | (*pi_agid << 6); + + i_ret = devctl(i_fd, DCMD_CAM_PASS_THRU, p_cpt, structSize, NULL); + + memcpy( p_key, p_buffer + 4, DVD_KEY_SIZE ); + +#elif defined( SYS_OS2 ) + INIT_SSC( GPCMD_REPORT_KEY, 12 ); + + sdc.command[ 10 ] = DVD_REPORT_KEY1 | (*pi_agid << 6); + + i_ret = DosDevIOCtl(i_fd, IOCTL_CDROMDISK, CDROMDISK_EXECMD, + &sdc, sizeof(sdc), &ulParamLen, + p_buffer, sizeof(p_buffer), &ulDataLen); + + memcpy( p_key, p_buffer + 4, DVD_KEY_SIZE ); + +#else +# error "DVD ioctls are unavailable on this system" + +#endif + return i_ret; +} + +/***************************************************************************** + * ioctl_InvalidateAgid: invalidate the current AGID + *****************************************************************************/ +int ioctl_InvalidateAgid( int i_fd, int *pi_agid ) +{ + int i_ret; + +#if defined( HAVE_LINUX_DVD_STRUCT ) + dvd_authinfo auth_info; + + memset( &auth_info, 0, sizeof( auth_info ) ); + auth_info.type = DVD_INVALIDATE_AGID; + auth_info.lsa.agid = *pi_agid; + + i_ret = ioctl( i_fd, DVD_AUTH, &auth_info ); + +#elif defined( HAVE_BSD_DVD_STRUCT ) + struct dvd_authinfo auth_info; + + memset( &auth_info, 0, sizeof( auth_info ) ); + auth_info.format = DVD_INVALIDATE_AGID; + auth_info.agid = *pi_agid; + + i_ret = ioctl( i_fd, DVDIOCREPORTKEY, &auth_info ); + +#elif defined( SYS_BEOS ) + INIT_RDC( GPCMD_REPORT_KEY, 0 ); + + rdc.command[ 10 ] = DVD_INVALIDATE_AGID | (*pi_agid << 6); + + i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) ); + +#elif defined( HPUX_SCTL_IO ) + INIT_SCTL_IO( GPCMD_REPORT_KEY, 0 ); + + sctl_io.cdb[ 10 ] = DVD_INVALIDATE_AGID | (*pi_agid << 6); + + i_ret = ioctl( i_fd, SIOC_IO, &sctl_io ); + +#elif defined( SOLARIS_USCSI ) + INIT_USCSI( GPCMD_REPORT_KEY, 0 ); + + rs_cdb.cdb_opaque[ 10 ] = DVD_INVALIDATE_AGID | (*pi_agid << 6); + + i_ret = SolarisSendUSCSI( i_fd, &sc ); + + if( i_ret < 0 || sc.uscsi_status ) + { + i_ret = -1; + } + +#elif defined( DARWIN_DVD_IOCTL ) + INIT_DVDIOCTL( dk_dvd_send_key_t, DVDAuthenticationGrantIDInfo, + kDVDKeyFormatAGID_Invalidate ); + + dvd.grantID = *pi_agid; + + i_ret = ioctl( i_fd, DKIOCDVDSENDKEY, &dvd ); + +#elif defined( WIN32 ) + if( WIN2K ) /* NT/2k/XP */ + { + DWORD tmp; + + i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_END_SESSION, + pi_agid, sizeof( *pi_agid ), NULL, 0, &tmp, NULL ) ? 0 : -1; + } + else + { +#if defined( __MINGW32__ ) + INIT_SSC( GPCMD_REPORT_KEY, 0 ); +#else + INIT_SSC( GPCMD_REPORT_KEY, 1 ); + + ssc.SRB_BufLen = 0; + ssc.CDBByte[ 8 ] = 0; + ssc.CDBByte[ 9 ] = 0; +#endif + + ssc.CDBByte[ 10 ] = DVD_INVALIDATE_AGID | (*pi_agid << 6); + + i_ret = WinSendSSC( i_fd, &ssc ); + } + +#elif defined( __QNXNTO__ ) + + INIT_CPT( GPCMD_REPORT_KEY, 0 ); + + p_cpt->cam_cdb[ 10 ] = DVD_INVALIDATE_AGID | (*pi_agid << 6); + + i_ret = devctl(i_fd, DCMD_CAM_PASS_THRU, p_cpt, structSize, NULL); + +#elif defined( SYS_OS2 ) + INIT_SSC( GPCMD_REPORT_KEY, 1 ); + + sdc.data_length = 0; + sdc.command[ 8 ] = 0; + sdc.command[ 9 ] = 0; + + sdc.command[ 10 ] = DVD_INVALIDATE_AGID | (*pi_agid << 6); + + i_ret = DosDevIOCtl(i_fd, IOCTL_CDROMDISK, CDROMDISK_EXECMD, + &sdc, sizeof(sdc), &ulParamLen, + NULL, 0, &ulDataLen); +#else +# error "DVD ioctls are unavailable on this system" + +#endif + return i_ret; +} + +/***************************************************************************** + * ioctl_SendChallenge: send challenge to the drive + *****************************************************************************/ +int ioctl_SendChallenge( int i_fd, int *pi_agid, uint8_t *p_challenge ) +{ + int i_ret; + +#if defined( HAVE_LINUX_DVD_STRUCT ) + dvd_authinfo auth_info; + + memset( &auth_info, 0, sizeof( auth_info ) ); + auth_info.type = DVD_HOST_SEND_CHALLENGE; + auth_info.hsc.agid = *pi_agid; + + memcpy( auth_info.hsc.chal, p_challenge, DVD_CHALLENGE_SIZE ); + + i_ret = ioctl( i_fd, DVD_AUTH, &auth_info ); + +#elif defined( HAVE_BSD_DVD_STRUCT ) + struct dvd_authinfo auth_info; + + memset( &auth_info, 0, sizeof( auth_info ) ); + auth_info.format = DVD_SEND_CHALLENGE; + auth_info.agid = *pi_agid; + + memcpy( auth_info.keychal, p_challenge, DVD_CHALLENGE_SIZE ); + + i_ret = ioctl( i_fd, DVDIOCSENDKEY, &auth_info ); + +#elif defined( SYS_BEOS ) + INIT_RDC( GPCMD_SEND_KEY, 16 ); + + rdc.command[ 10 ] = DVD_SEND_CHALLENGE | (*pi_agid << 6); + + p_buffer[ 1 ] = 0xe; + memcpy( p_buffer + 4, p_challenge, DVD_CHALLENGE_SIZE ); + + i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) ); + +#elif defined( HPUX_SCTL_IO ) + INIT_SCTL_IO( GPCMD_SEND_KEY, 16 ); + + sctl_io.cdb[ 10 ] = DVD_SEND_CHALLENGE | (*pi_agid << 6); + + p_buffer[ 1 ] = 0xe; + memcpy( p_buffer + 4, p_challenge, DVD_CHALLENGE_SIZE ); + + i_ret = ioctl( i_fd, SIOC_IO, &sctl_io ); + +#elif defined( SOLARIS_USCSI ) + INIT_USCSI( GPCMD_SEND_KEY, 16 ); + + rs_cdb.cdb_opaque[ 10 ] = DVD_SEND_CHALLENGE | (*pi_agid << 6); + + p_buffer[ 1 ] = 0xe; + memcpy( p_buffer + 4, p_challenge, DVD_CHALLENGE_SIZE ); + + if( SolarisSendUSCSI( i_fd, &sc ) < 0 || sc.uscsi_status ) + { + return -1; + } + + i_ret = 0; + +#elif defined( DARWIN_DVD_IOCTL ) + INIT_DVDIOCTL( dk_dvd_send_key_t, DVDChallengeKeyInfo, + kDVDKeyFormatChallengeKey ); + + dvd.grantID = *pi_agid; + dvd.keyClass = kDVDKeyClassCSS_CPPM_CPRM; + + dvdbs.dataLength[ 1 ] = 0xe; + memcpy( dvdbs.challengeKeyValue, p_challenge, DVD_CHALLENGE_SIZE ); + + i_ret = ioctl( i_fd, DKIOCDVDSENDKEY, &dvd ); + +#elif defined( WIN32 ) + if( WIN2K ) /* NT/2k/XP */ + { + DWORD tmp; + uint8_t buffer[DVD_CHALLENGE_KEY_LENGTH]; + PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer; + + memset( &buffer, 0, sizeof( buffer ) ); + + key->KeyLength = DVD_CHALLENGE_KEY_LENGTH; + key->SessionId = *pi_agid; + key->KeyType = DvdChallengeKey; + key->KeyFlags = 0; + + memcpy( key->KeyData, p_challenge, DVD_CHALLENGE_SIZE ); + +#if defined(_XBOX) + i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_SEND_KEY, key, + key->KeyLength, NULL, 0, &tmp, NULL ) ? 0 : -1; +#else + i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_SEND_KEY, key, + key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1; +#endif + } + else + { + INIT_SSC( GPCMD_SEND_KEY, 16 ); + + ssc.CDBByte[ 10 ] = DVD_SEND_CHALLENGE | (*pi_agid << 6); + + p_buffer[ 1 ] = 0xe; + memcpy( p_buffer + 4, p_challenge, DVD_CHALLENGE_SIZE ); + + i_ret = WinSendSSC( i_fd, &ssc ); + } + +#elif defined( __QNXNTO__ ) + + INIT_CPT( GPCMD_SEND_KEY, 16 ); + + p_cpt->cam_cdb[ 10 ] = DVD_SEND_CHALLENGE | (*pi_agid << 6); + + p_buffer[ 1 ] = 0xe; + memcpy( p_buffer + 4, p_challenge, DVD_CHALLENGE_SIZE ); + + i_ret = devctl(i_fd, DCMD_CAM_PASS_THRU, p_cpt, structSize, NULL); + +#elif defined( SYS_OS2 ) + INIT_SSC( GPCMD_SEND_KEY, 16 ); + + sdc.command[ 10 ] = DVD_SEND_CHALLENGE | (*pi_agid << 6); + + p_buffer[ 1 ] = 0xe; + memcpy( p_buffer + 4, p_challenge, DVD_CHALLENGE_SIZE ); + + i_ret = DosDevIOCtl( i_fd, IOCTL_CDROMDISK, CDROMDISK_EXECMD, + &sdc, sizeof(sdc), &ulParamLen, + p_buffer, sizeof(p_buffer), &ulDataLen ); + +#else +# error "DVD ioctls are unavailable on this system" + +#endif + return i_ret; +} + +/***************************************************************************** + * ioctl_SendKey2: send the second key to the drive + *****************************************************************************/ +int ioctl_SendKey2( int i_fd, int *pi_agid, uint8_t *p_key ) +{ + int i_ret; + +#if defined( HAVE_LINUX_DVD_STRUCT ) + dvd_authinfo auth_info; + + memset( &auth_info, 0, sizeof( auth_info ) ); + auth_info.type = DVD_HOST_SEND_KEY2; + auth_info.hsk.agid = *pi_agid; + + memcpy( auth_info.hsk.key, p_key, DVD_KEY_SIZE ); + + i_ret = ioctl( i_fd, DVD_AUTH, &auth_info ); + +#elif defined( HAVE_BSD_DVD_STRUCT ) + struct dvd_authinfo auth_info; + + memset( &auth_info, 0, sizeof( auth_info ) ); + auth_info.format = DVD_SEND_KEY2; + auth_info.agid = *pi_agid; + + memcpy( auth_info.keychal, p_key, DVD_KEY_SIZE ); + + i_ret = ioctl( i_fd, DVDIOCSENDKEY, &auth_info ); + +#elif defined( SYS_BEOS ) + INIT_RDC( GPCMD_SEND_KEY, 12 ); + + rdc.command[ 10 ] = DVD_SEND_KEY2 | (*pi_agid << 6); + + p_buffer[ 1 ] = 0xa; + memcpy( p_buffer + 4, p_key, DVD_KEY_SIZE ); + + i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) ); + +#elif defined( HPUX_SCTL_IO ) + INIT_SCTL_IO( GPCMD_SEND_KEY, 12 ); + + sctl_io.cdb[ 10 ] = DVD_SEND_KEY2 | (*pi_agid << 6); + + p_buffer[ 1 ] = 0xa; + memcpy( p_buffer + 4, p_key, DVD_KEY_SIZE ); + + i_ret = ioctl( i_fd, SIOC_IO, &sctl_io ); + +#elif defined( SOLARIS_USCSI ) + INIT_USCSI( GPCMD_SEND_KEY, 12 ); + + rs_cdb.cdb_opaque[ 10 ] = DVD_SEND_KEY2 | (*pi_agid << 6); + + p_buffer[ 1 ] = 0xa; + memcpy( p_buffer + 4, p_key, DVD_KEY_SIZE ); + + if( SolarisSendUSCSI( i_fd, &sc ) < 0 || sc.uscsi_status ) + { + return -1; + } + + i_ret = 0; + +#elif defined( DARWIN_DVD_IOCTL ) + INIT_DVDIOCTL( dk_dvd_send_key_t, DVDKey2Info, + kDVDKeyFormatKey2 ); + + dvd.grantID = *pi_agid; + dvd.keyClass = kDVDKeyClassCSS_CPPM_CPRM; + + dvdbs.dataLength[ 1 ] = 0xa; + memcpy( dvdbs.key2Value, p_key, DVD_KEY_SIZE ); + + i_ret = ioctl( i_fd, DKIOCDVDSENDKEY, &dvd ); + +#elif defined( WIN32 ) + if( WIN2K ) /* NT/2k/XP */ + { + DWORD tmp; + uint8_t buffer[DVD_BUS_KEY_LENGTH]; + PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer; + + memset( &buffer, 0, sizeof( buffer ) ); + + key->KeyLength = DVD_BUS_KEY_LENGTH; + key->SessionId = *pi_agid; + key->KeyType = DvdBusKey2; + key->KeyFlags = 0; + + memcpy( key->KeyData, p_key, DVD_KEY_SIZE ); + + i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_SEND_KEY, key, + key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1; + } + else + { + INIT_SSC( GPCMD_SEND_KEY, 12 ); + + ssc.CDBByte[ 10 ] = DVD_SEND_KEY2 | (*pi_agid << 6); + + p_buffer[ 1 ] = 0xa; + memcpy( p_buffer + 4, p_key, DVD_KEY_SIZE ); + + i_ret = WinSendSSC( i_fd, &ssc ); + } + +#elif defined( __QNXNTO__ ) + + INIT_CPT( GPCMD_SEND_KEY, 12 ); + + p_cpt->cam_cdb[ 10 ] = DVD_SEND_KEY2 | (*pi_agid << 6); + + p_buffer[ 1 ] = 0xa; + memcpy( p_buffer + 4, p_key, DVD_KEY_SIZE ); + + i_ret = devctl(i_fd, DCMD_CAM_PASS_THRU, p_cpt, structSize, NULL); + +#elif defined( SYS_OS2 ) + INIT_SSC( GPCMD_SEND_KEY, 12 ); + + sdc.command[ 10 ] = DVD_SEND_KEY2 | (*pi_agid << 6); + + p_buffer[ 1 ] = 0xa; + memcpy( p_buffer + 4, p_key, DVD_KEY_SIZE ); + + i_ret = DosDevIOCtl( i_fd, IOCTL_CDROMDISK, CDROMDISK_EXECMD, + &sdc, sizeof(sdc), &ulParamLen, + p_buffer, sizeof(p_buffer), &ulDataLen ); + +#else +# error "DVD ioctls are unavailable on this system" + +#endif + return i_ret; +} + +/***************************************************************************** + * ioctl_ReportRPC: get RPC status for the drive + *****************************************************************************/ +int ioctl_ReportRPC( int i_fd, int *p_type, int *p_mask, int *p_scheme ) +{ + int i_ret; + +#if defined( HAVE_LINUX_DVD_STRUCT ) && defined( DVD_LU_SEND_RPC_STATE ) + dvd_authinfo auth_info; + + memset( &auth_info, 0, sizeof( auth_info ) ); + auth_info.type = DVD_LU_SEND_RPC_STATE; + + i_ret = ioctl( i_fd, DVD_AUTH, &auth_info ); + + *p_type = auth_info.lrpcs.type; + *p_mask = auth_info.lrpcs.region_mask; + *p_scheme = auth_info.lrpcs.rpc_scheme; + +#elif defined( HAVE_LINUX_DVD_STRUCT ) + /* FIXME: OpenBSD doesn't know this */ + i_ret = -1; + +#elif defined( HAVE_BSD_DVD_STRUCT ) + struct dvd_authinfo auth_info; + + memset( &auth_info, 0, sizeof( auth_info ) ); + auth_info.format = DVD_REPORT_RPC; + + i_ret = ioctl( i_fd, DVDIOCREPORTKEY, &auth_info ); + + *p_type = auth_info.reg_type; + *p_mask = auth_info.region; // ?? + *p_scheme = auth_info.rpc_scheme; + +#elif defined( SYS_BEOS ) + INIT_RDC( GPCMD_REPORT_KEY, 8 ); + + rdc.command[ 10 ] = DVD_REPORT_RPC; + + i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) ); + + *p_type = p_buffer[ 4 ] >> 6; + *p_mask = p_buffer[ 5 ]; + *p_scheme = p_buffer[ 6 ]; + +#elif defined( HPUX_SCTL_IO ) + INIT_SCTL_IO( GPCMD_REPORT_KEY, 8 ); + + sctl_io.cdb[ 10 ] = DVD_REPORT_RPC; + + i_ret = ioctl( i_fd, SIOC_IO, &sctl_io ); + + *p_type = p_buffer[ 4 ] >> 6; + *p_mask = p_buffer[ 5 ]; + *p_scheme = p_buffer[ 6 ]; + +#elif defined( SOLARIS_USCSI ) + INIT_USCSI( GPCMD_REPORT_KEY, 8 ); + + rs_cdb.cdb_opaque[ 10 ] = DVD_REPORT_RPC; + + i_ret = SolarisSendUSCSI( i_fd, &sc ); + + if( i_ret < 0 || sc.uscsi_status ) + { + i_ret = -1; + } + + *p_type = p_buffer[ 4 ] >> 6; + *p_mask = p_buffer[ 5 ]; + *p_scheme = p_buffer[ 6 ]; + +#elif defined( DARWIN_DVD_IOCTL ) + INIT_DVDIOCTL( dk_dvd_report_key_t, DVDRegionPlaybackControlInfo, + kDVDKeyFormatRegionState ); + + dvd.keyClass = kDVDKeyClassCSS_CPPM_CPRM; + + i_ret = ioctl( i_fd, DKIOCDVDREPORTKEY, &dvd ); + + *p_type = dvdbs.typeCode; + *p_mask = dvdbs.driveRegion; + *p_scheme = dvdbs.rpcScheme; + +#elif defined( WIN32 ) + if( WIN2K ) /* NT/2k/XP */ + { + DWORD tmp; + uint8_t buffer[DVD_RPC_KEY_LENGTH]; + PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer; + + memset( &buffer, 0, sizeof( buffer ) ); + + key->KeyLength = DVD_RPC_KEY_LENGTH; + key->KeyType = DvdGetRpcKey; + key->KeyFlags = 0; + + i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key, + key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1; + + if( i_ret < 0 ) + { + return i_ret; + } + + *p_type = ((PDVD_RPC_KEY)key->KeyData)->TypeCode; + *p_mask = ((PDVD_RPC_KEY)key->KeyData)->RegionMask; + *p_scheme = ((PDVD_RPC_KEY)key->KeyData)->RpcScheme; + } + else + { + INIT_SSC( GPCMD_REPORT_KEY, 8 ); + + ssc.CDBByte[ 10 ] = DVD_REPORT_RPC; + + i_ret = WinSendSSC( i_fd, &ssc ); + + *p_type = p_buffer[ 4 ] >> 6; + *p_mask = p_buffer[ 5 ]; + *p_scheme = p_buffer[ 6 ]; + } + +#elif defined( __QNXNTO__ ) + + INIT_CPT( GPCMD_REPORT_KEY, 8 ); + + p_cpt->cam_cdb[ 10 ] = DVD_REPORT_RPC; + + i_ret = devctl(i_fd, DCMD_CAM_PASS_THRU, p_cpt, structSize, NULL); + + *p_type = p_buffer[ 4 ] >> 6; + *p_mask = p_buffer[ 5 ]; + *p_scheme = p_buffer[ 6 ]; + +#elif defined( SYS_OS2 ) + INIT_SSC( GPCMD_REPORT_KEY, 8 ); + + sdc.command[ 10 ] = DVD_REPORT_RPC; + + i_ret = DosDevIOCtl(i_fd, IOCTL_CDROMDISK, CDROMDISK_EXECMD, + &sdc, sizeof(sdc), &ulParamLen, + p_buffer, sizeof(p_buffer), &ulDataLen); + + *p_type = p_buffer[ 4 ] >> 6; + *p_mask = p_buffer[ 5 ]; + *p_scheme = p_buffer[ 6 ]; + +#else +# error "DVD ioctls are unavailable on this system" + +#endif + return i_ret; +} + +/***************************************************************************** + * ioctl_SendRPC: set RPC status for the drive + *****************************************************************************/ +int ioctl_SendRPC( int i_fd, int i_pdrc ) +{ + int i_ret; + +#if defined( HAVE_LINUX_DVD_STRUCT ) && defined( DVD_HOST_SEND_RPC_STATE ) + dvd_authinfo auth_info; + + memset( &auth_info, 0, sizeof( auth_info ) ); + auth_info.type = DVD_HOST_SEND_RPC_STATE; + auth_info.hrpcs.pdrc = i_pdrc; + + i_ret = ioctl( i_fd, DVD_AUTH, &auth_info ); + +#elif defined( HAVE_LINUX_DVD_STRUCT ) + /* FIXME: OpenBSD doesn't know this */ + i_ret = -1; + +#elif defined( HAVE_BSD_DVD_STRUCT ) + struct dvd_authinfo auth_info; + + memset( &auth_info, 0, sizeof( auth_info ) ); + auth_info.format = DVD_SEND_RPC; + auth_info.region = i_pdrc; + + i_ret = ioctl( i_fd, DVDIOCSENDKEY, &auth_info ); + +#elif defined( SYS_BEOS ) + INIT_RDC( GPCMD_SEND_KEY, 8 ); + + rdc.command[ 10 ] = DVD_SEND_RPC; + + p_buffer[ 1 ] = 6; + p_buffer[ 4 ] = i_pdrc; + + i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) ); + +#elif defined( HPUX_SCTL_IO ) + INIT_SCTL_IO( GPCMD_SEND_KEY, 8 ); + + sctl_io.cdb[ 10 ] = DVD_SEND_RPC; + + p_buffer[ 1 ] = 6; + p_buffer[ 4 ] = i_pdrc; + + i_ret = ioctl( i_fd, SIOC_IO, &sctl_io ); + +#elif defined( SOLARIS_USCSI ) + INIT_USCSI( GPCMD_SEND_KEY, 8 ); + + rs_cdb.cdb_opaque[ 10 ] = DVD_SEND_RPC; + + p_buffer[ 1 ] = 6; + p_buffer[ 4 ] = i_pdrc; + + i_ret = SolarisSendUSCSI( i_fd, &sc ); + + if( i_ret < 0 || sc.uscsi_status ) + { + i_ret = -1; + } + +#elif defined( DARWIN_DVD_IOCTL ) + INIT_DVDIOCTL( dk_dvd_send_key_t, DVDRegionPlaybackControlInfo, + kDVDKeyFormatSetRegion ); + + dvd.keyClass = kDVDKeyClassCSS_CPPM_CPRM; + dvdbs.driveRegion = i_pdrc; + + i_ret = ioctl( i_fd, DKIOCDVDSENDKEY, &dvd ); + +#elif defined( WIN32 ) + if( WIN2K ) /* NT/2k/XP */ + { + INIT_SPTD( GPCMD_SEND_KEY, 8 ); + + sptd.Cdb[ 10 ] = DVD_SEND_RPC; + + p_buffer[ 1 ] = 6; + p_buffer[ 4 ] = i_pdrc; + + i_ret = SEND_SPTD( i_fd, &sptd, &tmp ); + } + else + { + INIT_SSC( GPCMD_SEND_KEY, 8 ); + + ssc.CDBByte[ 10 ] = DVD_SEND_RPC; + + p_buffer[ 1 ] = 6; + p_buffer[ 4 ] = i_pdrc; + + i_ret = WinSendSSC( i_fd, &ssc ); + } + +#elif defined( __QNXNTO__ ) + + INIT_CPT( GPCMD_SEND_KEY, 8 ); + + p_cpt->cam_cdb[ 10 ] = DVD_SEND_RPC; + + p_buffer[ 1 ] = 6; + p_buffer[ 4 ] = i_pdrc; + + i_ret = devctl(i_fd, DCMD_CAM_PASS_THRU, p_cpt, structSize, NULL); + +#elif defined( SYS_OS2 ) + INIT_SSC( GPCMD_SEND_KEY, 8 ); + + sdc.command[ 10 ] = DVD_SEND_RPC; + + p_buffer[ 1 ] = 6; + p_buffer[ 4 ] = i_pdrc; + + i_ret = DosDevIOCtl( i_fd, IOCTL_CDROMDISK, CDROMDISK_EXECMD, + &sdc, sizeof(sdc), &ulParamLen, + p_buffer, sizeof(p_buffer), &ulDataLen ); + +#else +# error "DVD ioctls are unavailable on this system" + +#endif + return i_ret; +} + +/* Local prototypes */ + +#if defined( SYS_BEOS ) +/***************************************************************************** + * BeInitRDC: initialize a RDC structure for the BeOS kernel + ***************************************************************************** + * This function initializes a BeOS raw device command structure for future + * use, either a read command or a write command. + *****************************************************************************/ +static void BeInitRDC( raw_device_command *p_rdc, int i_type ) +{ + memset( p_rdc->data, 0, p_rdc->data_length ); + + switch( i_type ) + { + case GPCMD_SEND_KEY: + /* leave the flags to 0 */ + break; + + case GPCMD_READ_DVD_STRUCTURE: case GPCMD_REPORT_KEY: + p_rdc->flags = B_RAW_DEVICE_DATA_IN; break; } + + p_rdc->command[ 0 ] = i_type; + + p_rdc->command[ 8 ] = (p_rdc->data_length >> 8) & 0xff; + p_rdc->command[ 9 ] = p_rdc->data_length & 0xff; + p_rdc->command_length = 12; + + p_rdc->sense_data = NULL; + p_rdc->sense_data_length = 0; + + p_rdc->timeout = 1000000; +} +#endif + +#if defined( HPUX_SCTL_IO ) +/***************************************************************************** + * HPUXInitSCTL: initialize a sctl_io structure for the HP-UX kernel + ***************************************************************************** + * This function initializes a HP-UX command structure for future + * use, either a read command or a write command. + *****************************************************************************/ +static void HPUXInitSCTL( struct sctl_io *sctl_io, int i_type ) +{ + memset( sctl_io->data, 0, sctl_io->data_length ); + + switch( i_type ) + { + case GPCMD_SEND_KEY: + /* leave the flags to 0 */ + break; + + case GPCMD_READ_DVD_STRUCTURE: + case GPCMD_REPORT_KEY: + sctl_io->flags = SCTL_READ; + break; + } + + sctl_io->cdb[ 0 ] = i_type; + + sctl_io->cdb[ 8 ] = (sctl_io->data_length >> 8) & 0xff; + sctl_io->cdb[ 9 ] = sctl_io->data_length & 0xff; + sctl_io->cdb_length = 12; + + sctl_io->max_msecs = 1000000; +} +#endif + +#if defined( SOLARIS_USCSI ) +/***************************************************************************** + * SolarisInitUSCSI: initialize a USCSICMD structure for the Solaris kernel + ***************************************************************************** + * This function initializes a Solaris userspace scsi command structure for + * future use, either a read command or a write command. + *****************************************************************************/ +static void SolarisInitUSCSI( struct uscsi_cmd *p_sc, int i_type ) +{ + union scsi_cdb *rs_cdb; + memset( p_sc->uscsi_cdb, 0, sizeof( union scsi_cdb ) ); + memset( p_sc->uscsi_bufaddr, 0, p_sc->uscsi_buflen ); + + switch( i_type ) + { + case GPCMD_SEND_KEY: + p_sc->uscsi_flags = USCSI_ISOLATE | USCSI_WRITE; + break; + + case GPCMD_READ_DVD_STRUCTURE: + case GPCMD_REPORT_KEY: + p_sc->uscsi_flags = USCSI_ISOLATE | USCSI_READ; + break; + } + + rs_cdb = (union scsi_cdb *)p_sc->uscsi_cdb; + + rs_cdb->scc_cmd = i_type; + + rs_cdb->cdb_opaque[ 8 ] = (p_sc->uscsi_buflen >> 8) & 0xff; + rs_cdb->cdb_opaque[ 9 ] = p_sc->uscsi_buflen & 0xff; + p_sc->uscsi_cdblen = 12; + + USCSI_TIMEOUT( p_sc, 15 ); +} + +/***************************************************************************** + * SolarisSendUSCSI: send a USCSICMD structure to the Solaris kernel + * for execution + ***************************************************************************** + * When available, this function uses the function smedia_uscsi_cmd() + * from Solaris' libsmedia library (Solaris 9 or newer) to execute the + * USCSI command. smedia_uscsi_cmd() allows USCSI commands for + * non-root users on removable media devices on Solaris 9; sending the + * USCSI command directly to the device using the USCSICMD ioctl fails + * with an EPERM error on Solaris 9. + * + * The code will fall back to the USCSICMD ioctl method, when + * libsmedia.so is not available or does not export the + * smedia_uscsi_cmd() function (on Solaris releases upto and including + * Solaris 8). Fortunatelly, on these old releases non-root users are + * allowed to perform USCSICMD ioctls on removable media devices. + *****************************************************************************/ +static int SolarisSendUSCSI( int i_fd, struct uscsi_cmd *p_sc ) +{ + void *p_handle; + + /* We use static variables to keep track of the libsmedia symbols, which + * is harmless even in a multithreaded program because the library and + * its symbols will always be mapped at the same address. */ + static int b_tried = 0; + static int b_have_sm = 0; + static void * (*p_get_handle) ( int32_t ); + static int (*p_uscsi_cmd) ( void *, struct uscsi_cmd * ); + static int (*p_release_handle) ( void * ); + + if( !b_tried ) + { + void *p_lib; + + p_lib = dlopen( "libsmedia.so", RTLD_NOW ); + if( p_lib ) + { + p_get_handle = dlsym( p_lib, "smedia_get_handle" ); + p_uscsi_cmd = dlsym( p_lib, "smedia_uscsi_cmd" ); + p_release_handle = dlsym( p_lib, "smedia_release_handle" ); + + if( p_get_handle && p_uscsi_cmd && p_release_handle ) + { + b_have_sm = 1; + } + else + { + dlclose( p_lib ); + } + } + + b_tried = 1; + } + + if( b_have_sm && (p_handle = p_get_handle(i_fd)) ) + { + int i_ret = p_uscsi_cmd( p_handle, p_sc ); + p_release_handle( p_handle ); + return i_ret; + } + + return ioctl( i_fd, USCSICMD, p_sc ); +} +#endif + +#if defined( WIN32 ) +/***************************************************************************** + * WinInitSPTD: initialize a sptd structure + ***************************************************************************** + * This function initializes a SCSI pass through command structure for future + * use, either a read command or a write command. + *****************************************************************************/ +static void WinInitSPTD( SCSI_PASS_THROUGH_DIRECT *p_sptd, int i_type ) +{ + memset( p_sptd->DataBuffer, 0, p_sptd->DataTransferLength ); + + switch( i_type ) + { + case GPCMD_SEND_KEY: + p_sptd->DataIn = SCSI_IOCTL_DATA_OUT; + break; + + case GPCMD_READ_DVD_STRUCTURE: + case GPCMD_REPORT_KEY: + p_sptd->DataIn = SCSI_IOCTL_DATA_IN; + break; + } + + p_sptd->Cdb[ 0 ] = i_type; + p_sptd->Cdb[ 8 ] = (uint8_t)(p_sptd->DataTransferLength >> 8) & 0xff; + p_sptd->Cdb[ 9 ] = (uint8_t) p_sptd->DataTransferLength & 0xff; + p_sptd->CdbLength = 12; + + p_sptd->TimeOutValue = 2; +} + +/***************************************************************************** + * WinInitSSC: initialize a ssc structure for the win32 aspi layer + ***************************************************************************** + * This function initializes a ssc raw device command structure for future + * use, either a read command or a write command. + *****************************************************************************/ +static void WinInitSSC( struct SRB_ExecSCSICmd *p_ssc, int i_type ) +{ + memset( p_ssc->SRB_BufPointer, 0, p_ssc->SRB_BufLen ); + + switch( i_type ) + { + case GPCMD_SEND_KEY: + p_ssc->SRB_Flags = SRB_DIR_OUT; + break; + + case GPCMD_READ_DVD_STRUCTURE: + case GPCMD_REPORT_KEY: + p_ssc->SRB_Flags = SRB_DIR_IN; + break; + } + + p_ssc->SRB_Cmd = SC_EXEC_SCSI_CMD; + p_ssc->SRB_Flags |= SRB_EVENT_NOTIFY; + + p_ssc->CDBByte[ 0 ] = i_type; + + p_ssc->CDBByte[ 8 ] = (uint8_t)(p_ssc->SRB_BufLen >> 8) & 0xff; + p_ssc->CDBByte[ 9 ] = (uint8_t) p_ssc->SRB_BufLen & 0xff; + p_ssc->SRB_CDBLen = 12; + + p_ssc->SRB_SenseLen = SENSE_LEN; +} + +/***************************************************************************** + * WinSendSSC: send a ssc structure to the aspi layer + *****************************************************************************/ +static int WinSendSSC( int i_fd, struct SRB_ExecSCSICmd *p_ssc ) +{ + HANDLE hEvent = NULL; + struct w32_aspidev *fd = (struct w32_aspidev *) i_fd; + + hEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); + if( hEvent == NULL ) + { + return -1; + } + + p_ssc->SRB_PostProc = hEvent; + p_ssc->SRB_HaId = LOBYTE( fd->i_sid ); + p_ssc->SRB_Target = HIBYTE( fd->i_sid ); + + ResetEvent( hEvent ); + if( fd->lpSendCommand( (void*) p_ssc ) == SS_PENDING ) + WaitForSingleObject( hEvent, INFINITE ); + + CloseHandle( hEvent ); + + return p_ssc->SRB_Status == SS_COMP ? 0 : -1; +} +#endif + +#if defined( __QNXNTO__ ) +/***************************************************************************** + * QNXInitCPT: initialize a CPT structure for QNX Neutrino + ***************************************************************************** + * This function initializes a cpt command structure for future use, + * either a read command or a write command. + *****************************************************************************/ +static void QNXInitCPT( CAM_PASS_THRU * p_cpt, int i_type ) +{ + switch( i_type ) + { + case GPCMD_SEND_KEY: + p_cpt->cam_flags = CAM_DIR_OUT; + break; + + case GPCMD_READ_DVD_STRUCTURE: + case GPCMD_REPORT_KEY: + p_cpt->cam_flags = CAM_DIR_IN; + break; + } + + p_cpt->cam_cdb[0] = i_type; + + p_cpt->cam_cdb[ 8 ] = (p_cpt->cam_dxfer_len >> 8) & 0xff; + p_cpt->cam_cdb[ 9 ] = p_cpt->cam_dxfer_len & 0xff; + p_cpt->cam_cdb_len = 12; + + p_cpt->cam_timeout = CAM_TIME_DEFAULT; +} +#endif + +#if defined( SYS_OS2 ) +/***************************************************************************** + * OS2InitSDC: initialize a SDC structure for the Execute SCSI-command + ***************************************************************************** + * This function initializes a OS2 'execute SCSI command' structure for + * future use, either a read command or a write command. + *****************************************************************************/ +static void OS2InitSDC( struct OS2_ExecSCSICmd *p_sdc, int i_type ) +{ + switch( i_type ) + { + case GPCMD_SEND_KEY: + p_sdc->flags = 0; + break; + + case GPCMD_READ_DVD_STRUCTURE: + case GPCMD_REPORT_KEY: + p_sdc->flags = EX_DIRECTION_IN; + break; + } + + p_sdc->command[ 0 ] = i_type; + p_sdc->command[ 8 ] = (p_sdc->data_length >> 8) & 0xff; + p_sdc->command[ 9 ] = p_sdc->data_length & 0xff; + p_sdc->id_code = 0x31304443; // 'CD01' + p_sdc->cmd_length = 12; +} +#endif diff --git a/lib/libdvd/libdvdcss/src/ioctl.h b/lib/libdvd/libdvdcss/src/ioctl.h new file mode 100644 index 0000000000..b1ea287b0a --- /dev/null +++ b/lib/libdvd/libdvdcss/src/ioctl.h @@ -0,0 +1,433 @@ +/***************************************************************************** + * ioctl.h: DVD ioctl replacement function + ***************************************************************************** + * Copyright (C) 1999-2001 VideoLAN + * $Id$ + * + * Authors: Sam Hocevar <sam@zoy.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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, USA. + *****************************************************************************/ + +int ioctl_ReadCopyright ( int, int, int * ); +int ioctl_ReadDiscKey ( int, int *, uint8_t * ); +int ioctl_ReadTitleKey ( int, int *, int, uint8_t * ); +int ioctl_ReportAgid ( int, int * ); +int ioctl_ReportChallenge ( int, int *, uint8_t * ); +int ioctl_ReportKey1 ( int, int *, uint8_t * ); +int ioctl_ReportASF ( int, int *, int * ); +int ioctl_InvalidateAgid ( int, int * ); +int ioctl_SendChallenge ( int, int *, uint8_t * ); +int ioctl_SendKey2 ( int, int *, uint8_t * ); +int ioctl_ReportRPC ( int, int *, int *, int * ); +int ioctl_SendRPC ( int, int ); + +#define DVD_KEY_SIZE 5 +#define DVD_CHALLENGE_SIZE 10 +#define DVD_DISCKEY_SIZE 2048 + +/***************************************************************************** + * Common macro, BeOS specific + *****************************************************************************/ +#if defined( SYS_BEOS ) +#define INIT_RDC( TYPE, SIZE ) \ + raw_device_command rdc; \ + uint8_t p_buffer[ (SIZE)+1 ]; \ + memset( &rdc, 0, sizeof( raw_device_command ) ); \ + rdc.data = (char *)p_buffer; \ + rdc.data_length = (SIZE); \ + BeInitRDC( &rdc, (TYPE) ); +#endif + +/***************************************************************************** + * Common macro, HP-UX specific + *****************************************************************************/ +#if defined( HPUX_SCTL_IO ) +#define INIT_SCTL_IO( TYPE, SIZE ) \ + struct sctl_io sctl_io; \ + uint8_t p_buffer[ (SIZE)+1 ]; \ + memset( &sctl_io, 0, sizeof( sctl_io ) ); \ + sctl_io.data = (void *)p_buffer; \ + sctl_io.data_length = (SIZE); \ + HPUXInitSCTL( &sctl_io, (TYPE) ); +#endif + +/***************************************************************************** + * Common macro, Solaris specific + *****************************************************************************/ +#if defined( SOLARIS_USCSI ) +#define USCSI_TIMEOUT( SC, TO ) ( (SC)->uscsi_timeout = (TO) ) +#define USCSI_RESID( SC ) ( (SC)->uscsi_resid ) +#define INIT_USCSI( TYPE, SIZE ) \ + struct uscsi_cmd sc; \ + union scsi_cdb rs_cdb; \ + uint8_t p_buffer[ (SIZE)+1 ]; \ + memset( &sc, 0, sizeof( struct uscsi_cmd ) ); \ + sc.uscsi_cdb = (caddr_t)&rs_cdb; \ + sc.uscsi_bufaddr = (caddr_t)p_buffer; \ + sc.uscsi_buflen = (SIZE); \ + SolarisInitUSCSI( &sc, (TYPE) ); +#endif + +/***************************************************************************** + * Common macro, Darwin specific + *****************************************************************************/ +#if defined( DARWIN_DVD_IOCTL ) +#define INIT_DVDIOCTL( DKDVD_TYPE, BUFFER_TYPE, FORMAT ) \ + DKDVD_TYPE dvd; \ + BUFFER_TYPE dvdbs; \ + memset( &dvd, 0, sizeof(dvd) ); \ + memset( &dvdbs, 0, sizeof(dvdbs) ); \ + dvd.format = FORMAT; \ + dvd.buffer = &dvdbs; \ + dvd.bufferLength = sizeof(dvdbs); +#endif + +/***************************************************************************** + * Common macro, win32 specific + *****************************************************************************/ +#if defined( WIN32 ) +#define INIT_SPTD( TYPE, SIZE ) \ + DWORD tmp; \ + SCSI_PASS_THROUGH_DIRECT sptd; \ + uint8_t p_buffer[ (SIZE) ]; \ + memset( &sptd, 0, sizeof( SCSI_PASS_THROUGH_DIRECT ) ); \ + sptd.Length = sizeof( SCSI_PASS_THROUGH_DIRECT ); \ + sptd.DataBuffer = p_buffer; \ + sptd.DataTransferLength = (SIZE); \ + WinInitSPTD( &sptd, (TYPE) ); +#define SEND_SPTD( DEV, SPTD, TMP ) \ + (DeviceIoControl( (HANDLE)(DEV), IOCTL_SCSI_PASS_THROUGH_DIRECT, \ + (SPTD), sizeof( SCSI_PASS_THROUGH_DIRECT ), \ + (SPTD), sizeof( SCSI_PASS_THROUGH_DIRECT ), \ + (TMP), NULL ) ? 0 : -1) +#define INIT_SSC( TYPE, SIZE ) \ + struct SRB_ExecSCSICmd ssc; \ + uint8_t p_buffer[ (SIZE)+1 ]; \ + memset( &ssc, 0, sizeof( struct SRB_ExecSCSICmd ) ); \ + ssc.SRB_BufPointer = (char *)p_buffer; \ + ssc.SRB_BufLen = (SIZE); \ + WinInitSSC( &ssc, (TYPE) ); +#endif + +/***************************************************************************** + * Common macro, QNX specific + *****************************************************************************/ +#if defined( __QNXNTO__ ) +#define INIT_CPT( TYPE, SIZE ) \ + CAM_PASS_THRU * p_cpt; \ + uint8_t * p_buffer; \ + int structSize = sizeof( CAM_PASS_THRU ) + (SIZE); \ + p_cpt = (CAM_PASS_THRU *) malloc ( structSize ); \ + p_buffer = (uint8_t *) p_cpt + sizeof( CAM_PASS_THRU ); \ + memset( p_cpt, 0, structSize ); \ + p_cpt->cam_data_ptr = sizeof( CAM_PASS_THRU ); \ + p_cpt->cam_dxfer_len = (SIZE); \ + QNXInitCPT( p_cpt, (TYPE) ); +#endif + +/***************************************************************************** + * Common macro, OS2 specific + *****************************************************************************/ +#if defined( SYS_OS2 ) +#define INIT_SSC( TYPE, SIZE ) \ + struct OS2_ExecSCSICmd sdc; \ + uint8_t p_buffer[ (SIZE)+1 ]; \ + unsigned long ulParamLen; \ + unsigned long ulDataLen; \ + memset( &sdc, 0, sizeof( OS2_ExecSCSICmd ) ); \ + memset( &p_buffer, 0, SIZE ); \ + sdc.data_length = (SIZE); \ + ulParamLen = sizeof(sdc); \ + OS2InitSDC( &sdc, (TYPE) ) +#endif + +/***************************************************************************** + * Additional types, OpenBSD specific + *****************************************************************************/ +#if defined( HAVE_OPENBSD_DVD_STRUCT ) +typedef union dvd_struct dvd_struct; +typedef union dvd_authinfo dvd_authinfo; +#endif + +/***************************************************************************** + * Various DVD I/O tables + *****************************************************************************/ +#if defined( SYS_BEOS ) || defined( WIN32 ) || defined ( SOLARIS_USCSI ) || defined ( HPUX_SCTL_IO ) || defined ( __QNXNTO__ ) || defined ( SYS_OS2 ) + /* The generic packet command opcodes for CD/DVD Logical Units, + * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ +# define GPCMD_READ_DVD_STRUCTURE 0xad +# define GPCMD_REPORT_KEY 0xa4 +# define GPCMD_SEND_KEY 0xa3 + /* DVD struct types */ +# define DVD_STRUCT_PHYSICAL 0x00 +# define DVD_STRUCT_COPYRIGHT 0x01 +# define DVD_STRUCT_DISCKEY 0x02 +# define DVD_STRUCT_BCA 0x03 +# define DVD_STRUCT_MANUFACT 0x04 + /* Key formats */ +# define DVD_REPORT_AGID 0x00 +# define DVD_REPORT_CHALLENGE 0x01 +# define DVD_SEND_CHALLENGE 0x01 +# define DVD_REPORT_KEY1 0x02 +# define DVD_SEND_KEY2 0x03 +# define DVD_REPORT_TITLE_KEY 0x04 +# define DVD_REPORT_ASF 0x05 +# define DVD_SEND_RPC 0x06 +# define DVD_REPORT_RPC 0x08 +# define DVD_INVALIDATE_AGID 0x3f +#endif + +/***************************************************************************** + * win32 ioctl specific + *****************************************************************************/ +#if defined( WIN32 ) + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +#define IOCTL_DVD_START_SESSION CTL_CODE(FILE_DEVICE_DVD, 0x0400, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_DVD_READ_KEY CTL_CODE(FILE_DEVICE_DVD, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_DVD_SEND_KEY CTL_CODE(FILE_DEVICE_DVD, 0x0402, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_DVD_END_SESSION CTL_CODE(FILE_DEVICE_DVD, 0x0403, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_DVD_GET_REGION CTL_CODE(FILE_DEVICE_DVD, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_DVD_SEND_KEY2 CTL_CODE(FILE_DEVICE_DVD, 0x0406, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define IOCTL_DVD_READ_STRUCTURE CTL_CODE(FILE_DEVICE_DVD, 0x0450, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_SCSI_PASS_THROUGH_DIRECT CTL_CODE(FILE_DEVICE_CONTROLLER, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) + +#define DVD_CHALLENGE_KEY_LENGTH (12 + sizeof(DVD_COPY_PROTECT_KEY)) +#define DVD_BUS_KEY_LENGTH (8 + sizeof(DVD_COPY_PROTECT_KEY)) +#define DVD_TITLE_KEY_LENGTH (8 + sizeof(DVD_COPY_PROTECT_KEY)) +#define DVD_DISK_KEY_LENGTH (2048 + sizeof(DVD_COPY_PROTECT_KEY)) +#define DVD_RPC_KEY_LENGTH (sizeof(DVD_RPC_KEY) + sizeof(DVD_COPY_PROTECT_KEY)) +#define DVD_ASF_LENGTH (sizeof(DVD_ASF) + sizeof(DVD_COPY_PROTECT_KEY)) + +#define DVD_COPYRIGHT_MASK 0x00000040 +#define DVD_NOT_COPYRIGHTED 0x00000000 +#define DVD_COPYRIGHTED 0x00000040 + +#define DVD_SECTOR_PROTECT_MASK 0x00000020 +#define DVD_SECTOR_NOT_PROTECTED 0x00000000 +#define DVD_SECTOR_PROTECTED 0x00000020 + +#define SCSI_IOCTL_DATA_OUT 0 +#define SCSI_IOCTL_DATA_IN 1 + +typedef ULONG DVD_SESSION_ID, *PDVD_SESSION_ID; + +typedef enum DVD_STRUCTURE_FORMAT { + DvdPhysicalDescriptor, + DvdCopyrightDescriptor, + DvdDiskKeyDescriptor, + DvdBCADescriptor, + DvdManufacturerDescriptor, + DvdMaxDescriptor +} DVD_STRUCTURE_FORMAT, *PDVD_STRUCTURE_FORMAT; + +typedef struct DVD_READ_STRUCTURE { + LARGE_INTEGER BlockByteOffset; + DVD_STRUCTURE_FORMAT Format; + DVD_SESSION_ID SessionId; + UCHAR LayerNumber; +} DVD_READ_STRUCTURE, *PDVD_READ_STRUCTURE; + +typedef struct DVD_COPYRIGHT_DESCRIPTOR { + UCHAR CopyrightProtectionType; + UCHAR RegionManagementInformation; + USHORT Reserved; +} DVD_COPYRIGHT_DESCRIPTOR, *PDVD_COPYRIGHT_DESCRIPTOR; + +typedef enum +{ + DvdChallengeKey = 0x01, + DvdBusKey1, + DvdBusKey2, + DvdTitleKey, + DvdAsf, + DvdSetRpcKey = 0x6, + DvdGetRpcKey = 0x8, + DvdDiskKey = 0x80, + DvdInvalidateAGID = 0x3f +} DVD_KEY_TYPE; + +typedef struct DVD_COPY_PROTECT_KEY +{ + ULONG KeyLength; + DVD_SESSION_ID SessionId; + DVD_KEY_TYPE KeyType; + ULONG KeyFlags; + union + { + struct + { + ULONG FileHandle; + ULONG Reserved; // used for NT alignment + }; + LARGE_INTEGER TitleOffset; + } Parameters; + UCHAR KeyData[0]; +} DVD_COPY_PROTECT_KEY, *PDVD_COPY_PROTECT_KEY; + +typedef struct DVD_ASF +{ + UCHAR Reserved0[3]; + UCHAR SuccessFlag:1; + UCHAR Reserved1:7; +} DVD_ASF, * PDVD_ASF; + +typedef struct DVD_RPC_KEY +{ + UCHAR UserResetsAvailable:3; + UCHAR ManufacturerResetsAvailable:3; + UCHAR TypeCode:2; + UCHAR RegionMask; + UCHAR RpcScheme; + UCHAR Reserved2[1]; +} DVD_RPC_KEY, * PDVD_RPC_KEY; + +typedef struct SCSI_PASS_THROUGH_DIRECT +{ + USHORT Length; + UCHAR ScsiStatus; + UCHAR PathId; + UCHAR TargetId; + UCHAR Lun; + UCHAR CdbLength; + UCHAR SenseInfoLength; + UCHAR DataIn; + ULONG DataTransferLength; + ULONG TimeOutValue; + PVOID DataBuffer; + ULONG SenseInfoOffset; + UCHAR Cdb[16]; +} SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT; + +/***************************************************************************** + * win32 aspi specific + *****************************************************************************/ + +typedef DWORD (CALLBACK *GETASPI32SUPPORTINFO)(VOID); +typedef DWORD (CALLBACK *SENDASPI32COMMAND)(LPVOID); + +#if defined(_XBOX) || defined(WIN32) +#define WIN2K 1 +#else +#define WIN2K ( GetVersion() < 0x80000000 ) +#endif // _XBOX +#define ASPI_HAID 0 +#define ASPI_TARGET 0 +#define DTYPE_CDROM 0x05 + +#define SENSE_LEN 0x0E +#define SC_GET_DEV_TYPE 0x01 +#define SC_EXEC_SCSI_CMD 0x02 +#define SC_GET_DISK_INFO 0x06 +#define SS_COMP 0x01 +#define SS_PENDING 0x00 +#define SS_NO_ADAPTERS 0xE8 +#define SRB_DIR_IN 0x08 +#define SRB_DIR_OUT 0x10 +#define SRB_EVENT_NOTIFY 0x40 + +struct w32_aspidev +{ + long hASPI; + short i_sid; + int i_blocks; + SENDASPI32COMMAND lpSendCommand; +}; + +#pragma pack(1) + +struct SRB_GetDiskInfo +{ + unsigned char SRB_Cmd; + unsigned char SRB_Status; + unsigned char SRB_HaId; + unsigned char SRB_Flags; + unsigned long SRB_Hdr_Rsvd; + unsigned char SRB_Target; + unsigned char SRB_Lun; + unsigned char SRB_DriveFlags; + unsigned char SRB_Int13HDriveInfo; + unsigned char SRB_Heads; + unsigned char SRB_Sectors; + unsigned char SRB_Rsvd1[22]; +}; + +struct SRB_GDEVBlock +{ + unsigned char SRB_Cmd; + unsigned char SRB_Status; + unsigned char SRB_HaId; + unsigned char SRB_Flags; + unsigned long SRB_Hdr_Rsvd; + unsigned char SRB_Target; + unsigned char SRB_Lun; + unsigned char SRB_DeviceType; + unsigned char SRB_Rsvd1; +}; + +struct SRB_ExecSCSICmd +{ + unsigned char SRB_Cmd; + unsigned char SRB_Status; + unsigned char SRB_HaId; + unsigned char SRB_Flags; + unsigned long SRB_Hdr_Rsvd; + unsigned char SRB_Target; + unsigned char SRB_Lun; + unsigned short SRB_Rsvd1; + unsigned long SRB_BufLen; + unsigned char *SRB_BufPointer; + unsigned char SRB_SenseLen; + unsigned char SRB_CDBLen; + unsigned char SRB_HaStat; + unsigned char SRB_TargStat; + unsigned long *SRB_PostProc; + unsigned char SRB_Rsvd2[20]; + unsigned char CDBByte[16]; + unsigned char SenseArea[SENSE_LEN+2]; +}; + +#pragma pack() + +#endif + +/***************************************************************************** + * OS2 ioctl specific + *****************************************************************************/ +#if defined( SYS_OS2 ) + +#define CDROMDISK_EXECMD 0x7A + +#define EX_DIRECTION_IN 0x01 +#define EX_PLAYING_CHK 0x02 + +#pragma pack(1) + +struct OS2_ExecSCSICmd +{ + unsigned long id_code; // 'CD01' + unsigned short data_length; // length of the Data Packet + unsigned short cmd_length; // length of the Command Buffer + unsigned short flags; // flags + unsigned char command[16]; // Command Buffer for SCSI command + +} OS2_ExecSCSICmd; + +#pragma pack() + +#endif diff --git a/lib/libdvd/libdvdcss/src/libdvdcss.c b/lib/libdvd/libdvdcss/src/libdvdcss.c new file mode 100644 index 0000000000..0f6524176d --- /dev/null +++ b/lib/libdvd/libdvdcss/src/libdvdcss.c @@ -0,0 +1,835 @@ +/* libdvdcss.c: DVD reading library. + * + * Authors: Stéphane Borel <stef@via.ecp.fr> + * Sam Hocevar <sam@zoy.org> + * HÃ¥kan Hjort <d95hjort@dtek.chalmers.se> + * + * Copyright (C) 1998-2008 VideoLAN + * $Id$ + * + * 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, USA. + */ + +/** + * \mainpage libdvdcss developer documentation + * + * \section intro Introduction + * + * \e libdvdcss is a simple library designed for accessing DVDs like a block + * device without having to bother about the decryption. The important features + * are: + * \li portability: currently supported platforms are GNU/Linux, FreeBSD, + * NetBSD, OpenBSD, BSD/OS, BeOS, Windows 95/98, Windows NT/2000, MacOS X, + * Solaris, HP-UX and OS/2. + * \li adaptability: unlike most similar projects, libdvdcss doesn't require + * the region of your drive to be set and will try its best to read from + * the disc even in the case of a region mismatch. + * \li simplicity: a DVD player can be built around the \e libdvdcss API using + * no more than 4 or 5 library calls. + * + * \e libdvdcss is free software, released under the General Public License. + * This ensures that \e libdvdcss remains free and used only with free + * software. + * + * \section api The libdvdcss API + * + * The complete \e libdvdcss programming interface is documented in the + * dvdcss.h file. + * + * \section env Environment variables + * + * Some environment variables can be used to change the behaviour of + * \e libdvdcss without having to modify the program which uses it. These + * variables are: + * + * \li \b DVDCSS_VERBOSE: sets the verbosity level. + * - \c 0 outputs no messages at all. + * - \c 1 outputs error messages to stderr. + * - \c 2 outputs error messages and debug messages to stderr. + * + * \li \b DVDCSS_METHOD: sets the authentication and decryption method + * that \e libdvdcss will use to read scrambled discs. Can be one + * of \c title, \c key or \c disc. + * - \c key is the default method. \e libdvdcss will use a set of + * calculated player keys to try and get the disc key. This can fail + * if the drive does not recognize any of the player keys. + * - \c disc is a fallback method when \c key has failed. Instead of + * using player keys, \e libdvdcss will crack the disc key using + * a brute force algorithm. This process is CPU intensive and requires + * 64 MB of memory to store temporary data. + * - \c title is the fallback when all other methods have failed. It does + * not rely on a key exchange with the DVD drive, but rather uses a + * crypto attack to guess the title key. On rare cases this may fail + * because there is not enough encrypted data on the disc to perform + * a statistical attack, but in the other hand it is the only way to + * decrypt a DVD stored on a hard disc, or a DVD with the wrong region + * on an RPC2 drive. + * + * \li \b DVDCSS_RAW_DEVICE: specify the raw device to use. Exact usage will + * depend on your operating system, the Linux utility to set up raw devices + * is \c raw(8) for instance. Please note that on most operating systems, + * using a raw device requires highly aligned buffers: Linux requires a + * 2048 bytes alignment (which is the size of a DVD sector). + * + * \li \b DVDCSS_CACHE: specify a directory in which to store title key + * values. This will speed up descrambling of DVDs which are in the + * cache. The DVDCSS_CACHE directory is created if it does not exist, + * and a subdirectory is created named after the DVD's title or + * manufacturing date. If DVDCSS_CACHE is not set or is empty, \e libdvdcss + * will use the default value which is "${HOME}/.dvdcss/" under Unix and + * "C:\Documents and Settings\$USER\Application Data\dvdcss\" under Win32. + * The special value "off" disables caching. + */ + +/* + * Preamble + */ +#include "config.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#ifdef HAVE_SYS_PARAM_H +# include <sys/param.h> +#endif +#ifdef HAVE_PWD_H +# include <pwd.h> +#endif +#include <fcntl.h> +#include <errno.h> + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif + +#ifdef HAVE_LIMITS_H +# include <limits.h> +#endif + +#ifdef HAVE_DIRECT_H +# include <direct.h> +#endif + +#include "dvdcss/dvdcss.h" + +#include "common.h" +#include "css.h" +#include "libdvdcss.h" +#include "ioctl.h" +#include "device.h" + +/** + * \brief Symbol for version checks. + * + * The name of this symbol contains the library major number, which makes it + * easy to check which \e libdvdcss development headers are installed on the + * system with tools such as autoconf. + * + * The variable itself contains the exact version number of the library, + * which can be useful for specific feature needs. + */ +char * dvdcss_interface_2 = VERSION; + +/** + * \brief Open a DVD device or directory and return a dvdcss instance. + * + * \param psz_target a string containing the target name, for instance + * "/dev/hdc" or "E:". + * \return a handle to a dvdcss instance or NULL on error. + * + * Initialize the \e libdvdcss library and open the requested DVD device or + * directory. \e libdvdcss checks whether ioctls can be performed on the disc, + * and when possible, the disc key is retrieved. + * + * dvdcss_open() returns a handle to be used for all subsequent \e libdvdcss + * calls. If an error occurred, NULL is returned. + */ +LIBDVDCSS_EXPORT dvdcss_t dvdcss_open ( char *psz_target ) +{ + char psz_buffer[PATH_MAX]; + int i_ret; + + char *psz_method = getenv( "DVDCSS_METHOD" ); + char *psz_verbose = getenv( "DVDCSS_VERBOSE" ); + char *psz_cache = getenv( "DVDCSS_CACHE" ); +#ifndef WIN32 + char *psz_raw_device = getenv( "DVDCSS_RAW_DEVICE" ); +#endif + + dvdcss_t dvdcss; + + /* + * Allocate the library structure + */ + dvdcss = malloc( sizeof( struct dvdcss_s ) ); + if( dvdcss == NULL ) + { + return NULL; + } + + /* + * Initialize structure with default values + */ +#ifndef WIN32 + dvdcss->i_raw_fd = -1; +#endif + dvdcss->p_titles = NULL; + dvdcss->psz_device = (char *)strdup( psz_target ); + dvdcss->psz_error = "no error"; + dvdcss->i_method = DVDCSS_METHOD_KEY; + dvdcss->psz_cachefile[0] = '\0'; + dvdcss->b_debug = 0; + dvdcss->b_errors = 0; + +#ifdef WITH_CACHE + dvdcss->buffer_size = 0; +#endif + + /* + * Find verbosity from DVDCSS_VERBOSE environment variable + */ + if( psz_verbose != NULL ) + { + int i = atoi( psz_verbose ); + + if( i >= 2 ) dvdcss->b_debug = i; + if( i >= 1 ) dvdcss->b_errors = 1; + } + + /* + * Find method from DVDCSS_METHOD environment variable + */ + if( psz_method != NULL ) + { + if( !strncmp( psz_method, "key", 4 ) ) + { + dvdcss->i_method = DVDCSS_METHOD_KEY; + } + else if( !strncmp( psz_method, "disc", 5 ) ) + { + dvdcss->i_method = DVDCSS_METHOD_DISC; + } + else if( !strncmp( psz_method, "title", 5 ) ) + { + dvdcss->i_method = DVDCSS_METHOD_TITLE; + } + else + { + print_error( dvdcss, "unknown decrypt method, please choose " + "from 'title', 'key' or 'disc'" ); + free( dvdcss->psz_device ); + free( dvdcss ); + return NULL; + } + } + + /* + * If DVDCSS_CACHE was not set, try to guess a default value + */ + if( psz_cache == NULL || psz_cache[0] == '\0' ) + { +#ifdef HAVE_DIRECT_H + typedef HRESULT( WINAPI *SHGETFOLDERPATH ) + ( HWND, int, HANDLE, DWORD, LPTSTR ); + +# define CSIDL_FLAG_CREATE 0x8000 +# define CSIDL_APPDATA 0x1A +# define SHGFP_TYPE_CURRENT 0 + + char psz_home[MAX_PATH]; + HINSTANCE p_dll; + SHGETFOLDERPATH p_getpath; + + *psz_home = '\0'; + + /* Load the shfolder dll to retrieve SHGetFolderPath */ + p_dll = LoadLibrary( "shfolder.dll" ); + if( p_dll ) + { + p_getpath = (void*)GetProcAddress( p_dll, "SHGetFolderPathA" ); + if( p_getpath ) + { + /* Get the "Application Data" folder for the current user */ + if( p_getpath( NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, + NULL, SHGFP_TYPE_CURRENT, psz_home ) == S_OK ) + { + FreeLibrary( p_dll ); + } + else + { + *psz_home = '\0'; + } + } + FreeLibrary( p_dll ); + } + + /* Cache our keys in + * C:\Documents and Settings\$USER\Application Data\dvdcss\ */ + if( *psz_home ) + { + snprintf( psz_buffer, PATH_MAX, "%s/dvdcss", psz_home ); + psz_buffer[PATH_MAX-1] = '\0'; + psz_cache = psz_buffer; + } +#else + char *psz_home = NULL; +# ifdef HAVE_PWD_H + struct passwd *p_pwd; + + /* Try looking in password file for home dir. */ + p_pwd = getpwuid(getuid()); + if( p_pwd ) + { + psz_home = p_pwd->pw_dir; + } +# endif + + if( psz_home == NULL ) + { + psz_home = getenv( "HOME" ); + } + if( psz_home == NULL ) + { + psz_home = getenv( "USERPROFILE" ); + } + + /* Cache our keys in ${HOME}/.dvdcss/ */ + if( psz_home ) + { + snprintf( psz_buffer, PATH_MAX, "%s/.dvdcss", psz_home ); + psz_buffer[PATH_MAX-1] = '\0'; + psz_cache = psz_buffer; + } +#endif + } + + /* + * Find cache dir from the DVDCSS_CACHE environment variable + */ + if( psz_cache != NULL ) + { + if( psz_cache[0] == '\0' || !strcmp( psz_cache, "off" ) ) + { + psz_cache = NULL; + } + /* Check that we can add the ID directory and the block filename */ + else if( strlen( psz_cache ) + 1 + 32 + 1 + (KEY_SIZE * 2) + 10 + 1 + > PATH_MAX ) + { + print_error( dvdcss, "cache directory name is too long" ); + psz_cache = NULL; + } + } + + /* + * Open device + */ + _dvdcss_check( dvdcss ); + i_ret = _dvdcss_open( dvdcss ); + if( i_ret < 0 ) + { + free( dvdcss->psz_device ); + free( dvdcss ); + return NULL; + } + + dvdcss->b_scrambled = 1; /* Assume the worst */ + dvdcss->b_ioctls = _dvdcss_use_ioctls( dvdcss ); + + if( dvdcss->b_ioctls ) + { + i_ret = _dvdcss_test( dvdcss ); + if( i_ret < 0 ) + { + /* Disable the CSS ioctls and hope that it works? */ + print_debug( dvdcss, + "could not check whether the disc was scrambled" ); + dvdcss->b_ioctls = 0; + } + else + { + print_debug( dvdcss, i_ret ? "disc is scrambled" + : "disc is unscrambled" ); + dvdcss->b_scrambled = i_ret; + } + } + /* if wo don't have b_ioctls, we don't have a disk key, make sure area is nulled */ + memset( dvdcss->css.p_disc_key, 0, KEY_SIZE ); + + /* If disc is CSS protected and the ioctls work, authenticate the drive */ + if( dvdcss->b_scrambled && dvdcss->b_ioctls ) + { + i_ret = _dvdcss_disckey( dvdcss ); + + if( i_ret < 0 ) + { + print_debug( dvdcss, "could not get disc key" ); + } + } + else + { + memset( dvdcss->css.p_disc_key, 0, KEY_SIZE ); + } + + /* If the cache is enabled, write the cache directory tag */ + if( psz_cache ) + { + char *psz_tag = "Signature: 8a477f597d28d172789f06886806bc55\r\n" + "# This file is a cache directory tag created by libdvdcss.\r\n" + "# For information about cache directory tags, see:\r\n" + "# http://www.brynosaurus.com/cachedir/\r\n"; + char psz_tagfile[PATH_MAX + 1 + 12 + 1]; + int i_fd; + + sprintf( psz_tagfile, "%s/CACHEDIR.TAG", psz_cache ); + i_fd = open( psz_tagfile, O_RDWR|O_CREAT, 0644 ); + if( i_fd >= 0 ) + { + write( i_fd, psz_tag, strlen(psz_tag) ); + close( i_fd ); + } + } + + /* If the cache is enabled, extract a unique disc ID */ + if( psz_cache ) + { + uint8_t p_sector[DVDCSS_BLOCK_SIZE]; + char psz_debug[PATH_MAX + 30]; + char psz_key[1 + KEY_SIZE * 2 + 1]; + char *psz_title; + uint8_t *psz_serial; + int i; + + /* We read sector 0. If it starts with 0x000001ba (BE), we are + * reading a VOB file, and we should not cache anything. */ + + i_ret = dvdcss->pf_seek( dvdcss, 0 ); + if( i_ret != 0 ) + { + goto nocache; + } + + i_ret = dvdcss->pf_read( dvdcss, p_sector, 1 ); + if( i_ret != 1 ) + { + goto nocache; + } + + if( p_sector[0] == 0x00 && p_sector[1] == 0x00 + && p_sector[2] == 0x01 && p_sector[3] == 0xba ) + { + goto nocache; + } + + /* The data we are looking for is at sector 16 (32768 bytes): + * - offset 40: disc title (32 uppercase chars) + * - offset 813: manufacturing date + serial no (16 digits) */ + + i_ret = dvdcss->pf_seek( dvdcss, 16 ); + if( i_ret != 16 ) + { + goto nocache; + } + + i_ret = dvdcss->pf_read( dvdcss, p_sector, 1 ); + if( i_ret != 1 ) + { + goto nocache; + } + + /* Get the disc title */ + psz_title = (char *)p_sector + 40; + psz_title[32] = '\0'; + + for( i = 0 ; i < 32 ; i++ ) + { + if( psz_title[i] <= ' ' ) + { + psz_title[i] = '\0'; + break; + } + else if( psz_title[i] == '/' || psz_title[i] == '\\' ) + { + psz_title[i] = '-'; + } + } + + /* Get the date + serial */ + psz_serial = p_sector + 813; + psz_serial[16] = '\0'; + + /* Check that all characters are digits, otherwise convert. */ + for( i = 0 ; i < 16 ; i++ ) + { + if( psz_serial[i] < '0' || psz_serial[i] > '9' ) + { + char psz_tmp[16 + 1]; + sprintf( psz_tmp, + "%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", + psz_serial[0], psz_serial[1], psz_serial[2], + psz_serial[3], psz_serial[4], psz_serial[5], + psz_serial[6], psz_serial[7] ); + memcpy( psz_serial, psz_tmp, 16 ); + break; + } + } + + /* Get disk key, since some discs have got same title, manufacturing + * date and serial number, but different keys */ + if( dvdcss->b_scrambled ) + { + psz_key[0] = '-'; + for( i = 0; i < KEY_SIZE; i++ ) + { + sprintf( &psz_key[1+i*2], "%.2x", dvdcss->css.p_disc_key[i] ); + } + psz_key[1 + KEY_SIZE * 2] = '\0'; + } + else + { + psz_key[0] = 0; + } + + /* We have a disc name or ID, we can create the cache dir */ + i = sprintf( dvdcss->psz_cachefile, "%s", psz_cache ); +#if !defined( WIN32 ) || defined( SYS_CYGWIN ) + i_ret = mkdir( dvdcss->psz_cachefile, 0755 ); +#else + i_ret = mkdir( dvdcss->psz_cachefile ); +#endif + if( i_ret < 0 && errno != EEXIST ) + { + print_error( dvdcss, "failed creating cache directory" ); + dvdcss->psz_cachefile[0] = '\0'; + goto nocache; + } + +#ifdef _XBOX + //due to xbox file system having a limited length on folders/files, + //make separate folder for disk name first + if(psz_title[0] == '\0') + strcat(psz_title, "NONAME"); + + i += sprintf( dvdcss->psz_cachefile + i, "/%s", psz_title); + + i_ret = mkdir( dvdcss->psz_cachefile ); + if( i_ret < 0 && errno != EEXIST ) + { + print_error( dvdcss, "failed creating cache titledirectory" ); + dvdcss->psz_cachefile[0] = '\0'; + goto nocache; + } + i += sprintf( dvdcss->psz_cachefile + i, "/%s%s", psz_serial, psz_key ); +#else + i += sprintf( dvdcss->psz_cachefile + i, "/%s-%s%s", psz_title, + psz_serial, psz_key ); +#endif +#if !defined( WIN32 ) || defined( SYS_CYGWIN ) + i_ret = mkdir( dvdcss->psz_cachefile, 0755 ); +#else + i_ret = mkdir( dvdcss->psz_cachefile ); +#endif + if( i_ret < 0 && errno != EEXIST ) + { + print_error( dvdcss, "failed creating cache subdirectory" ); + dvdcss->psz_cachefile[0] = '\0'; + goto nocache; + } + i += sprintf( dvdcss->psz_cachefile + i, "/"); + + /* Pointer to the filename we will use. */ + dvdcss->psz_block = dvdcss->psz_cachefile + i; + + sprintf( psz_debug, "using CSS key cache dir: %s", + dvdcss->psz_cachefile ); + print_debug( dvdcss, psz_debug ); + } + nocache: + +#ifndef WIN32 + if( psz_raw_device != NULL ) + { + _dvdcss_raw_open( dvdcss, psz_raw_device ); + } +#endif + + /* Seek at the beginning, just for safety. */ + dvdcss->pf_seek( dvdcss, 0 ); + + return dvdcss; +} + +/** + * \brief Return a string containing the latest error that occurred in the + * given \e libdvdcss instance. + * + * \param dvdcss a \e libdvdcss instance. + * \return a null-terminated string containing the latest error message. + * + * This function returns a constant string containing the latest error that + * occurred in \e libdvdcss. It can be used to format error messages at your + * convenience in your application. + */ +LIBDVDCSS_EXPORT char * dvdcss_error ( dvdcss_t dvdcss ) +{ + return dvdcss->psz_error; +} + +/** + * \brief Seek in the disc and change the current key if requested. + * + * \param dvdcss a \e libdvdcss instance. + * \param i_blocks an absolute block offset to seek to. + * \param i_flags #DVDCSS_NOFLAGS, optionally ored with one of #DVDCSS_SEEK_KEY + * or #DVDCSS_SEEK_MPEG. + * \return the new position in blocks, or a negative value in case an error + * happened. + * + * This function seeks to the requested position, in logical blocks. + * + * You typically set \p i_flags to #DVDCSS_NOFLAGS when seeking in a .IFO. + * + * If #DVDCSS_SEEK_MPEG is specified in \p i_flags and if \e libdvdcss finds it + * reasonable to do so (ie, if the dvdcss method is not "title"), the current + * title key will be checked and a new one will be calculated if necessary. + * This flag is typically used when reading data from a VOB. + * + * If #DVDCSS_SEEK_KEY is specified, the title key will be always checked, + * even with the "title" method. This is equivalent to using the now + * deprecated dvdcss_title() call. This flag is typically used when seeking + * in a new title. + */ +LIBDVDCSS_EXPORT int dvdcss_seek ( dvdcss_t dvdcss, int i_blocks, int i_flags ) +{ + /* title cracking method is too slow to be used at each seek */ + if( ( ( i_flags & DVDCSS_SEEK_MPEG ) + && ( dvdcss->i_method != DVDCSS_METHOD_TITLE ) ) + || ( i_flags & DVDCSS_SEEK_KEY ) ) + { + /* check the title key */ + if( _dvdcss_title( dvdcss, i_blocks ) ) + { + return -1; + } + } + + return dvdcss->pf_seek( dvdcss, i_blocks ); +} + +/** + * \brief Read from the disc and decrypt data if requested. + * + * \param dvdcss a \e libdvdcss instance. + * \param p_buffer a buffer that will contain the data read from the disc. + * \param i_blocks the amount of blocks to read. + * \param i_flags #DVDCSS_NOFLAGS, optionally ored with #DVDCSS_READ_DECRYPT. + * \return the amount of blocks read, or a negative value in case an + * error happened. + * + * This function reads \p i_blocks logical blocks from the DVD. + * + * You typically set \p i_flags to #DVDCSS_NOFLAGS when reading data from a + * .IFO file on the DVD. + * + * If #DVDCSS_READ_DECRYPT is specified in \p i_flags, dvdcss_read() will + * automatically decrypt scrambled sectors. This flag is typically used when + * reading data from a .VOB file on the DVD. It has no effect on unscrambled + * discs or unscrambled sectors, and can be safely used on those. + * + * \warning dvdcss_read() expects to be able to write \p i_blocks * + * #DVDCSS_BLOCK_SIZE bytes in \p p_buffer. + */ +LIBDVDCSS_EXPORT int dvdcss_read ( dvdcss_t dvdcss, void *p_buffer, + int i_blocks, + int i_flags ) +{ + int i_ret, i_index; + + i_ret = dvdcss->pf_read( dvdcss, p_buffer, i_blocks ); + + if( i_ret <= 0 + || !dvdcss->b_scrambled + || !(i_flags & DVDCSS_READ_DECRYPT) ) + { + return i_ret; + } + + if( ! memcmp( dvdcss->css.p_title_key, "\0\0\0\0\0", 5 ) ) + { + /* For what we believe is an unencrypted title, + * check that there are no encrypted blocks */ + for( i_index = i_ret; i_index; i_index-- ) + { + if( ((uint8_t*)p_buffer)[0x14] & 0x30 ) + { + print_error( dvdcss, "no key but found encrypted block" ); + /* Only return the initial range of unscrambled blocks? */ + /* or fail completely? return 0; */ + break; + } + p_buffer = (void *) ((uint8_t *)p_buffer + DVDCSS_BLOCK_SIZE); + } + } + else + { + /* Decrypt the blocks we managed to read */ + for( i_index = i_ret; i_index; i_index-- ) + { + _dvdcss_unscramble( dvdcss->css.p_title_key, p_buffer ); + ((uint8_t*)p_buffer)[0x14] &= 0x8f; + p_buffer = (void *) ((uint8_t *)p_buffer + DVDCSS_BLOCK_SIZE); + } + } + + return i_ret; +} + +/** + * \brief Read from the disc into multiple buffers and decrypt data if + * requested. + * + * \param dvdcss a \e libdvdcss instance. + * \param p_iovec a pointer to an array of iovec structures that will contain + * the data read from the disc. + * \param i_blocks the amount of blocks to read. + * \param i_flags #DVDCSS_NOFLAGS, optionally ored with #DVDCSS_READ_DECRYPT. + * \return the amount of blocks read, or a negative value in case an + * error happened. + * + * This function reads \p i_blocks logical blocks from the DVD and writes them + * to an array of iovec structures. + * + * You typically set \p i_flags to #DVDCSS_NOFLAGS when reading data from a + * .IFO file on the DVD. + * + * If #DVDCSS_READ_DECRYPT is specified in \p i_flags, dvdcss_readv() will + * automatically decrypt scrambled sectors. This flag is typically used when + * reading data from a .VOB file on the DVD. It has no effect on unscrambled + * discs or unscrambled sectors, and can be safely used on those. + * + * \warning dvdcss_readv() expects to be able to write \p i_blocks * + * #DVDCSS_BLOCK_SIZE bytes in the buffers pointed by \p p_iovec. + * Moreover, all iov_len members of the iovec structures should be + * multiples of #DVDCSS_BLOCK_SIZE. + */ +LIBDVDCSS_EXPORT int dvdcss_readv ( dvdcss_t dvdcss, void *p_iovec, + int i_blocks, + int i_flags ) +{ + struct iovec *_p_iovec = (struct iovec *)p_iovec; + int i_ret, i_index; + void *iov_base; + size_t iov_len; + + i_ret = dvdcss->pf_readv( dvdcss, _p_iovec, i_blocks ); + + if( i_ret <= 0 + || !dvdcss->b_scrambled + || !(i_flags & DVDCSS_READ_DECRYPT) ) + { + return i_ret; + } + + /* Initialize loop for decryption */ + iov_base = _p_iovec->iov_base; + iov_len = _p_iovec->iov_len; + + /* Decrypt the blocks we managed to read */ + for( i_index = i_ret; i_index; i_index-- ) + { + /* Check that iov_len is a multiple of 2048 */ + if( iov_len & 0x7ff ) + { + return -1; + } + + while( iov_len == 0 ) + { + _p_iovec++; + iov_base = _p_iovec->iov_base; + iov_len = _p_iovec->iov_len; + } + + _dvdcss_unscramble( dvdcss->css.p_title_key, iov_base ); + ((uint8_t*)iov_base)[0x14] &= 0x8f; + + iov_base = (void *) ((uint8_t*)iov_base + DVDCSS_BLOCK_SIZE); + iov_len -= DVDCSS_BLOCK_SIZE; + } + + return i_ret; +} + +/** + * \brief Close the DVD and clean up the library. + * + * \param dvdcss a \e libdvdcss instance. + * \return zero in case of success, a negative value otherwise. + * + * This function closes the DVD device and frees all the memory allocated + * by \e libdvdcss. On return, the #dvdcss_t is invalidated and may not be + * used again. + */ +LIBDVDCSS_EXPORT int dvdcss_close ( dvdcss_t dvdcss ) +{ + dvd_title_t *p_title; + int i_ret; + + /* Free our list of keys */ + p_title = dvdcss->p_titles; + while( p_title ) + { + dvd_title_t *p_tmptitle = p_title->p_next; + free( p_title ); + p_title = p_tmptitle; + } + + i_ret = _dvdcss_close( dvdcss ); + + if( i_ret < 0 ) + { + return i_ret; + } + + free( dvdcss->psz_device ); + free( dvdcss ); + + return 0; +} + +/* + * Deprecated. See dvdcss_seek(). + */ +#undef dvdcss_title +LIBDVDCSS_EXPORT int dvdcss_title ( dvdcss_t dvdcss, int i_block ) +{ + return _dvdcss_title( dvdcss, i_block ); +} + +/** + * \brief Return 1 if the DVD is scrambled, 0 otherwise. + * + * \param dvdcss a \e libdvdcss instance. + * \return 1 if the DVD is scrambled, 0 otherwise. + * + * This function returns whether the DVD is scrambled. + */ +LIBDVDCSS_EXPORT int dvdcss_is_scrambled ( dvdcss_t dvdcss ) +{ + return dvdcss->b_scrambled; +} + diff --git a/lib/libdvd/libdvdcss/src/libdvdcss.h b/lib/libdvd/libdvdcss/src/libdvdcss.h new file mode 100644 index 0000000000..80f78c3062 --- /dev/null +++ b/lib/libdvd/libdvdcss/src/libdvdcss.h @@ -0,0 +1,104 @@ +/***************************************************************************** + * libdvdcss.h: private DVD reading library data + ***************************************************************************** + * Copyright (C) 1998-2001 VideoLAN + * $Id$ + * + * Authors: Stéphane Borel <stef@via.ecp.fr> + * Sam Hocevar <sam@zoy.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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, USA. + *****************************************************************************/ + +struct iovec; + +/***************************************************************************** + * The libdvdcss structure + *****************************************************************************/ +struct dvdcss_s +{ + /* File descriptor */ + char * psz_device; + int i_fd; + int i_read_fd; + int i_pos; + + /* File handling */ + int ( * pf_seek ) ( dvdcss_t, int ); + int ( * pf_read ) ( dvdcss_t, void *, int ); + int ( * pf_readv ) ( dvdcss_t, struct iovec *, int ); + + /* Decryption stuff */ + int i_method; + css_t css; + int b_ioctls; + int b_scrambled; + dvd_title_t *p_titles; + + /* Key cache directory and pointer to the filename */ + char psz_cachefile[PATH_MAX]; + char * psz_block; + + /* Error management */ + char * psz_error; + int b_errors; + int b_debug; + +#ifdef WIN32 + int b_file; + char * p_readv_buffer; + int i_readv_buf_size; +#endif + +#ifndef WIN32 + int i_raw_fd; +#endif +}; + +/***************************************************************************** + * libdvdcss method: used like init flags + *****************************************************************************/ +#define DVDCSS_METHOD_KEY 0 +#define DVDCSS_METHOD_DISC 1 +#define DVDCSS_METHOD_TITLE 2 + +/***************************************************************************** + * Functions used across the library + *****************************************************************************/ +#define print_error(dvdcss,msg) _print_error(dvdcss,msg) +#if defined( _MSC_VER ) +#include <stdarg.h> +__forceinline void print_debug(dvdcss_t dvdcss, const char *msg,...) +{ + va_list args; + + fprintf( stderr, "libdvdcss debug: " ); + va_start( args, msg ); + vfprintf( stderr, msg, args ); + va_end( args ); + fprintf( stderr, "\n" ); +} +#else +#define print_debug(dvdcss,msg,args...) \ + if( dvdcss->b_debug ) \ + { \ + fprintf( stderr, "libdvdcss debug: " ); \ + fprintf( stderr, msg, ##args ); \ + fprintf( stderr, "\n" ); \ + } +#endif + +void _print_error ( dvdcss_t, char * ); + diff --git a/lib/libdvd/libdvdcss/src/libdvdcss.pc.in b/lib/libdvd/libdvdcss/src/libdvdcss.pc.in new file mode 100644 index 0000000000..9d2516787f --- /dev/null +++ b/lib/libdvd/libdvdcss/src/libdvdcss.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libdvdcss +Description: DVD access and decryption library. +Version: @VERSION@ +Libs: -L${libdir} -ldvdcss +Cflags: -I{includedir} -I${includedir}/@PACKAGE@ diff --git a/lib/libdvd/libdvdcss/test/Makefile.am b/lib/libdvd/libdvdcss/test/Makefile.am new file mode 100644 index 0000000000..f1c5a631e0 --- /dev/null +++ b/lib/libdvd/libdvdcss/test/Makefile.am @@ -0,0 +1,15 @@ + +noinst_PROGRAMS = csstest #dvd_region + +csstest_SOURCES = csstest.c +csstest_LDADD = $(top_builddir)/src/libdvdcss.la $(bsdi_libadd) +csstest_CFLAGS = -I$(top_srcdir)/src + +#dvd_region_SOURCES = dvd_region.c +#dvd_region_LDADD = $(top_builddir)/src/libdvdcss.la +#dvd_region_CFLAGS = -I$(top_srcdir)/src + +if SYS_BSDI_LIBDVD +bsdi_libadd = -ldvd +endif + diff --git a/lib/libdvd/libdvdcss/test/csstest.c b/lib/libdvd/libdvdcss/test/csstest.c new file mode 100644 index 0000000000..70f3b4d8f9 --- /dev/null +++ b/lib/libdvd/libdvdcss/test/csstest.c @@ -0,0 +1,130 @@ +/* csstest.c - test program for libdvdcss + * + * Sam Hocevar <sam@zoy.org> - June 2001 + * Updated on Nov 13th 2001 for libdvdcss version 1.0.0 + * Additional error checks on Aug 9th 2002 + * Aligned data reads on Jan 28th 2003 + * + * This piece of code is public domain */ + +#include <stdio.h> +#include <stdlib.h> + +#include <dvdcss/dvdcss.h> + +static int isscrambled( unsigned char * ); +static void dumpsector ( unsigned char * ); + +int main( int i_argc, char *ppsz_argv[] ) +{ + dvdcss_t dvdcss; + unsigned char p_data[ DVDCSS_BLOCK_SIZE * 2 ]; + unsigned char *p_buffer; + unsigned int i_sector; + int i_ret; + + /* Print version number */ + printf( "cool, I found libdvdcss version %s\n", dvdcss_interface_2 ); + + /* Check for 2 arguments */ + if( i_argc != 3 ) + { + printf( "usage: %s <target> <sector>\n", ppsz_argv[0] ); + printf( "examples:\n" ); + printf( " %s /dev/hdc 1024\n", ppsz_argv[0] ); + printf( " %s D: 1024\n", ppsz_argv[0] ); + printf( " %s scrambledfile.vob 1024\n", ppsz_argv[0] ); + return -1; + } + + /* Save the requested sector */ + i_sector = atoi( ppsz_argv[2] ); + + /* Initialize libdvdcss */ + dvdcss = dvdcss_open( ppsz_argv[1] ); + if( dvdcss == NULL ) + { + printf( "argh ! couldn't open DVD (%s)\n", ppsz_argv[1] ); + return -1; + } + + /* Align our read buffer */ + p_buffer = p_data + DVDCSS_BLOCK_SIZE + - ((long int)p_data & (DVDCSS_BLOCK_SIZE-1)); + + /* Set the file descriptor at sector i_sector and read one sector */ + i_ret = dvdcss_seek( dvdcss, i_sector, DVDCSS_NOFLAGS ); + if( i_ret != (int)i_sector ) + { + printf( "seek failed (%s)\n", dvdcss_error( dvdcss ) ); + dvdcss_close( dvdcss ); + return i_ret; + } + + i_ret = dvdcss_read( dvdcss, p_buffer, 1, DVDCSS_NOFLAGS ); + if( i_ret != 1 ) + { + printf( "read failed (%s)\n", dvdcss_error( dvdcss ) ); + dvdcss_close( dvdcss ); + return i_ret; + } + + /* Print the sector */ + printf( "requested sector: " ); + dumpsector( p_buffer ); + + /* Check if sector was encrypted */ + if( isscrambled( p_buffer ) ) + { + /* Set the file descriptor position to the previous location */ + /* ... and get the appropriate key for this sector */ + i_ret = dvdcss_seek( dvdcss, i_sector, DVDCSS_SEEK_KEY ); + if( i_ret != (int)i_sector ) + { + printf( "seek failed (%s)\n", dvdcss_error( dvdcss ) ); + dvdcss_close( dvdcss ); + return i_ret; + } + + /* Read sector again, and decrypt it on the fly */ + i_ret = dvdcss_read( dvdcss, p_buffer, 1, DVDCSS_READ_DECRYPT ); + if( i_ret != 1 ) + { + printf( "read failed (%s)\n", dvdcss_error( dvdcss ) ); + dvdcss_close( dvdcss ); + return i_ret; + } + + /* Print the decrypted sector */ + printf( "unscrambled sector: " ); + dumpsector( p_buffer ); + } + else + { + printf( "sector is not scrambled\n" ); + } + + /* Close the device */ + i_ret = dvdcss_close( dvdcss ); + + return i_ret; +} + +/* Check if a sector is scrambled */ +static int isscrambled( unsigned char *p_buffer ) +{ + return p_buffer[ 0x14 ] & 0x30; +} + +/* Print parts of a 2048 bytes buffer */ +static void dumpsector( unsigned char *p_buffer ) +{ + int i_amount = 4; + for( ; i_amount ; i_amount--, p_buffer++ ) printf( "%.2x", *p_buffer ); + printf( "..." ); + i_amount = 22; + p_buffer += 200; + for( ; i_amount ; i_amount--, p_buffer++ ) printf( "%.2x", *p_buffer ); + printf( "...\n" ); +} + diff --git a/lib/libdvd/libdvdnav/.relignore b/lib/libdvd/libdvdnav/.relignore new file mode 100644 index 0000000000..2f2f41fa9c --- /dev/null +++ b/lib/libdvd/libdvdnav/.relignore @@ -0,0 +1,2 @@ +autom4te.cache +config.status diff --git a/lib/libdvd/libdvdnav/AUTHORS b/lib/libdvd/libdvdnav/AUTHORS new file mode 100644 index 0000000000..cb528af0dd --- /dev/null +++ b/lib/libdvd/libdvdnav/AUTHORS @@ -0,0 +1,6 @@ +Daniel Caujolle-Bert <segfault@club-internet.fr> +Thomas Vander Stichele <thomas@apestaart.org> +Rich Wareham <richwareham@users.sourceforge.net> +Kees Cook <kees@outflux.net> +Michael Roitzsch <mroi@users.sourceforge.net> +Frantisek Dvorak <valtri@users.sourceforge.net> diff --git a/lib/libdvd/libdvdnav/COPYING b/lib/libdvd/libdvdnav/COPYING new file mode 100644 index 0000000000..d60c31a97a --- /dev/null +++ b/lib/libdvd/libdvdnav/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. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + 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. + + <signature of Ty Coon>, 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/lib/libdvd/libdvdnav/ChangeLog b/lib/libdvd/libdvdnav/ChangeLog new file mode 100644 index 0000000000..46b43d0fa7 --- /dev/null +++ b/lib/libdvd/libdvdnav/ChangeLog @@ -0,0 +1,134 @@ +libdvdnav (4.1.3) + * an embarassing amount of fixes regarding potential memory and resource leaks + (patches contributed by Erik Hovland) + * added dvdread-config (dvdnav-config's younger brother) + * added pkg-config support + * split dvdread to a separate tree; now you need to check it out + and install it before building libdvdnav. + In order to configure libdvdnav We need the executable dvdread-config + somewhere in the PATH or explicitly specified to configure[2] with + --with-dvdread-config=~/bin/dvdread-config + +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." occuring 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 layed 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 <richwareham@users.sourceforge.net> 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 <jcdutton@users.sourceforge.net> 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 <pmhahn@titan.lahn.de> 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 <pmhahn@titan.lahn.de> 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 <siggi@debian.org> Mon, 20 May 2002 15:57:40 +0200 + +libdvdnav (0.0.1-1) unstable; urgency=low + + * Repackaged using dh-make. + + -- Philipp Matthias Hahn <pmhahn@titan.lahn.de> Sun, 7 Apr 2002 16:29:35 +0200 + +libdvdnav (0.0.1) unstable; urgency=low + + * Initial release. + * Split from xine-dvdnav + + -- rjw57 <rjw57@hermes.cam.ac.uk> Tue, 12 Mar 2002 19:41:13 +0000 + diff --git a/lib/libdvd/libdvdnav/DEVELOPMENT-POLICY.txt b/lib/libdvd/libdvdnav/DEVELOPMENT-POLICY.txt new file mode 100644 index 0000000000..20c73e5005 --- /dev/null +++ b/lib/libdvd/libdvdnav/DEVELOPMENT-POLICY.txt @@ -0,0 +1,25 @@ +This fork of dvdnav was created to overcome the lack of responsiveness +of the official development channel, not to bastardize this library in +something for specific usage by mplayer, so these are the rules to follow +when developing code: +- don't remove pre-existing code that mplayer doesn't need +- don't add code to expose the internals of dvdnav +- don't add code that binds applications to side-effects of the library +- don't alter the API in an incompatible manner + + +When committing code to the repository always follow these rules: +- don't break the compilability of the library - always keep svn checkouts usable +- never mix cosmetical and functional changes +- don't commit unrelated changes as a single transaction +- don't split strictly related changes over multiple commits +- never alter the indentation / bracing / prototyping style of existing files +- if you break something by accident fix it as soon as possible using the appropriate + svn tools to revert your commit(s). If in doubt ask explanations to the + mailing list +- trivial patches such as spell fixes, prototype mismatch, missing includes, + more proper variable typization and similar should be committed without asking + prior authorization + + +If in reiterated violation of these rules your account will be deleted. diff --git a/lib/libdvd/libdvdnav/Makefile b/lib/libdvd/libdvdnav/Makefile new file mode 100644 index 0000000000..85245b7a4d --- /dev/null +++ b/lib/libdvd/libdvdnav/Makefile @@ -0,0 +1,166 @@ +include config.mak + +.SUFFIXES: .so + +AR=ar +LD=ld +RANLIB=ranlib + +VPATH+= $(SRC_PATH_BARE)/src +SRCS = dvdnav.c highlight.c navigation.c read_cache.c remap.c searching.c settings.c + +VPATH+= $(SRC_PATH_BARE)/src/vm +SRCS+= decoder.c vm.c vmcmd.c + +HEADERS = src/dvd_types.h src/dvdnav.h src/dvdnav_events.h + +CFLAGS += $(USEDEBUG) -Wall -funsigned-char +CFLAGS += -I$(CURDIR) -I$(SRC_PATH)/src -I$(SRC_PATH)/src/vm +CFLAGS += -DDVDNAV_COMPILE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE +CFLAGS += -DHAVE_CONFIG_H -DHAVE_DLFCN_H + +L=libdvdnav +MINI_L=libdvdnavmini +CFLAGS += $(DVDREAD_CFLAGS) + +LIB = $(L).a +SHLIB = $(L).so +MINI_SHLIB = $(MINI_L).so + +.OBJDIR= obj +DEPFLAG = -M + +OBJS = $(patsubst %.c,%.o, $(SRCS)) +SHOBJS = $(patsubst %.c,%.so, $(SRCS)) +DEPS= ${OBJS:%.o=%.d} + +BUILDDEPS = Makefile config.mak + +ifeq ($(BUILD_SHARED),yes) +all: $(SHLIB) $(MINI_SHLIB) dvdnav-config pkgconfig +install: $(SHLIB) install-shared install-dvdnav-config install-pkgconfig +endif + +ifeq ($(BUILD_STATIC),yes) +all: $(LIB) dvdnav-config pkgconfig +install: $(LIB) install-static install-dvdnav-config install-pkgconfig +endif + +install: install-headers + +# Let version.sh create version.h + +SVN_ENTRIES = $(SRC_PATH_BARE)/.svn/entries +ifeq ($(wildcard $(SVN_ENTRIES)),$(SVN_ENTRIES)) +version.h: $(SVN_ENTRIES) +endif + +version.h: + sh $(SRC_PATH)/version.sh $(SRC_PATH) "$(SHLIB_VERSION)" + +$(SRCS): version.h + + +# General targets + +${LIB}: version.h $(OBJS) $(BUILDDEPS) + cd $(.OBJDIR) && $(AR) rc $@ $(OBJS) + cd $(.OBJDIR) && $(RANLIB) $@ + +${SHLIB}: version.h $(SHOBJS) $(BUILDDEPS) + cd $(.OBJDIR) && $(CC) $(SHLDFLAGS) -Wl,-soname=$(SHLIB).$(SHLIB_MAJOR) -o $@ $(SHOBJS) $(DVDREAD_LIBS) $(THREADLIB) +${MINI_SHLIB}: version.h $(.OBJDIR) $(SHOBJS) $(BUILDDEPS) + cd $(.OBJDIR) && $(CC) $(SHLDFLAGS) -Wl,-soname=$(MINI_SHLIB).$(SHLIB_MAJOR) -o $@ $(SHOBJS) $(THREADLIB) + +.c.so: $(BUILDDEPS) + cd $(.OBJDIR) && $(CC) -fPIC -DPIC -MD $(CFLAGS) -c -o $@ $< + +.c.o: $(BUILDDEPS) + cd $(.OBJDIR) && $(CC) -MD $(CFLAGS) -c -o $@ $< + + +# Install targets + +install-headers: + install -d $(DESTDIR)$(incdir) + install -m 644 $(HEADERS) $(DESTDIR)$(incdir) + +install-shared: $(SHLIB) + install -d $(DESTDIR)$(shlibdir) + + install $(INSTALLSTRIP) -m 755 $(.OBJDIR)/$(SHLIB) \ + $(DESTDIR)$(shlibdir)/$(SHLIB).$(SHLIB_VERSION) + install $(INSTALLSTRIP) -m 755 $(.OBJDIR)/$(MINI_SHLIB) \ + $(DESTDIR)$(shlibdir)/$(MINI_SHLIB).$(SHLIB_VERSION) + + cd $(DESTDIR)$(shlibdir) && \ + ln -sf $(SHLIB).$(SHLIB_VERSION) $(SHLIB).$(SHLIB_MAJOR) + cd $(DESTDIR)$(shlibdir) && \ + ln -sf $(MINI_SHLIB).$(SHLIB_VERSION) $(MINI_SHLIB).$(SHLIB_MAJOR) + cd $(DESTDIR)$(shlibdir) && \ + ln -sf $(SHLIB).$(SHLIB_MAJOR) $(SHLIB) + cd $(DESTDIR)$(shlibdir) && \ + ln -sf $(MINI_SHLIB).$(SHLIB_MAJOR) $(MINI_SHLIB) + + +install-static: $(LIB) + install -d $(DESTDIR)$(libdir) + + install $(INSTALLSTRIP) -m 755 $(.OBJDIR)/$(LIB) $(DESTDIR)$(libdir)/$(LIB) + + +# Clean targets + +clean: + rm -rf *~ $(.OBJDIR)/* + +pcedit = sed \ + -e 's,@prefix@,$(PREFIX),' \ + -e 's,@exec_prefix@,$(PREFIX),' \ + -e 's,@libdir@,$(shlibdir),' \ + -e 's,@includedir@,$(PREFIX)/include,' \ + -e 's,@VERSION@,$(SHLIB_VERSION),' \ + -e 's,@THREAD_CFLAGS@,,' \ + -e 's,@THREAD_LIBS@,$(THREADLIB),' \ + -e 's,@DVDREAD_CFLAGS@,$(DVDREAD_CFLAGS),' + +pkgconfig: $(.OBJDIR)/dvdnav.pc $(.OBJDIR)/dvdnavmini.pc +$(.OBJDIR)/dvdnav.pc: misc/dvdnav.pc.in $(BUILDDEPS) + $(pcedit) $< > $@ +$(.OBJDIR)/dvdnavmini.pc: misc/dvdnavmini.pc.in $(BUILDDEPS) + $(pcedit) $< > $@ + +install-pkgconfig: $(.OBJDIR)/dvdnav.pc $(.OBJDIR)/dvdnavmini.pc + install -d $(DESTDIR)$(libdir)/pkgconfig + install -m 0644 $(.OBJDIR)/dvdnav.pc $(DESTDIR)$(libdir)/pkgconfig + install -m 0644 $(.OBJDIR)/dvdnavmini.pc \ + $(DESTDIR)$(libdir)/pkgconfig + +distclean: clean + find . -name "*~" | xargs rm -rf + rm -rf config.mak $(.OBJDIR) + +dvdnav-config: $(.OBJDIR)/dvdnav-config +$(.OBJDIR)/dvdnav-config: $(BUILDDEPS) + @echo '#!/bin/sh' > $(.OBJDIR)/dvdnav-config + @echo 'prefix='$(PREFIX) >> $(.OBJDIR)/dvdnav-config + @echo 'libdir='$(shlibdir) >> $(.OBJDIR)/dvdnav-config + @echo 'version='$(SHLIB_VERSION) >> $(.OBJDIR)/dvdnav-config + @echo 'dvdread_cflags="'$(DVDREAD_CFLAGS)'"' >> $(.OBJDIR)/dvdnav-config + @echo 'dvdread_libs="'$(DVDREAD_LIBS)'"' >> $(.OBJDIR)/dvdnav-config + @echo 'threadlib='$(THREADLIB) >> $(.OBJDIR)/dvdnav-config + @echo >> $(.OBJDIR)/dvdnav-config + cat $(SRC_PATH_BARE)/misc/dvdnav-config2.sh >> $(.OBJDIR)/dvdnav-config + chmod 0755 $(.OBJDIR)/dvdnav-config + +install-dvdnav-config: dvdnav-config + install -d $(DESTDIR)$(PREFIX)/bin + install -m 0755 $(.OBJDIR)/dvdnav-config $(DESTDIR)$(PREFIX)/bin/dvdnav-config + +vpath %.so ${.OBJDIR} +vpath %.o ${.OBJDIR} +vpath ${LIB} ${.OBJDIR} + +# include dependency files if they exist +$(addprefix ${.OBJDIR}/, ${DEPS}): ; +-include $(addprefix ${.OBJDIR}/, ${DEPS}) diff --git a/lib/libdvd/libdvdnav/Makefile.am b/lib/libdvd/libdvdnav/Makefile.am new file mode 100644 index 0000000000..f03ecaaeff --- /dev/null +++ b/lib/libdvd/libdvdnav/Makefile.am @@ -0,0 +1,42 @@ +include $(top_srcdir)/misc/Makefile.common + + +SUBDIRS = src examples doc misc m4 + +EXTRA_DIST = autogen.sh \ + AUTHORS \ + ChangeLog \ + configure \ + config.guess \ + config.sub \ + COPYING \ + INSTALL \ + install-sh \ + libtool \ + ltmain.sh \ + missing \ + mkinstalldirs \ + README \ + TODO + +MOSTLYCLEANFILES += $(PACKAGE)_$(VERSION).tar.gz \ + $(distdir).tar.gz $(PACKAGE).tgz package_descriptions + +MAINTAINERCLEANFILES += configure $(ACLOCAL_M4) config.h.in \ + ltmain.sh config.guess config.sub install-sh missing \ + mkinstalldirs + +world: + @$(MAKE) clean all install 2> warnings.log + test -s warnings.log || rm warnings.log + +prune-cache: + -rm -f config.cache + +release-check: + @./config.status misc/relchk.sh + @./autogen.sh noconfig && $(SHELL) misc/relchk.sh + +dist-hook: + cp -r $(srcdir)/msvc $(distdir)/msvc + rm -rf `find $(distdir)/msvc -name CVS` diff --git a/lib/libdvd/libdvdnav/NEWS b/lib/libdvd/libdvdnav/NEWS new file mode 100644 index 0000000000..7aa22b1545 --- /dev/null +++ b/lib/libdvd/libdvdnav/NEWS @@ -0,0 +1,2 @@ +This file is unused. +The ChangeLog file lists changes for new versions. diff --git a/lib/libdvd/libdvdnav/README b/lib/libdvd/libdvdnav/README new file mode 100644 index 0000000000..d7f78d48a2 --- /dev/null +++ b/lib/libdvd/libdvdnav/README @@ -0,0 +1,57 @@ +What is this all about? +----------------------- + +libdvdnav is a library that allows easy use of sophisticated DVD navigation +features such as DVD menus, multiangle playback and even interactive DVD games. +All this functionality is provided through a simple API which provides the +DVD playback as a single logical stream of blocks, intermitted by special +dvdnav events to report certain conditions. The main usage of libdvdnav is a +loop regularly calling a function to get the next block, surrounded by +additional calls to tell the library of user interaction. +The whole DVD virtual machine and internal playback states are completely +encapsulated. + +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 +libdvdnav 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. + +Where is it now? +---------------- + +libdvdnav is hosted on http://www.mplayerhq.hu/MPlayer/releases/dvdnav/ . +Please report bugs to the developers mailinglist at +mailto:dvdnav-discuss@mplayerhq.hu . + +We are still in beta stage, but libdvdnav is already quite usable. With +regular DVD playback, there should not be any serious issues. The library +also makes some limited effort to handle error situations gracefully, but +there are still assertions in the code that may trigger on some DVDs. Please +send a report to the developer mailinglist, if you encounter such problems. + +How can I use it? +----------------- + +libdvdnav is completely licensed under GPL. You may use it at wish within the +bounds of this license. See the file "COPYING" for a copy of the GPL. + +Sources for documentation on libdvdnav are: +* the examples directory contains a simple program using libdvdnav + this one is well-commented and therefore a good starting point +* the public header dvdnav.h documents the API +* the public header dvdnav_events.h documents the dvdnav events +* doc/library_layout contains some info on the internal working of libdvdnav + +Sources for documentation on DVD terminology, structure and surrounding concepts: +* doc/dvd_structures briefly explains DVD terms and organization +* a more detailed description of DVD structures is available at + http://www.mpucoder.com/dvd/ +* the ifo_types.h and nav_types.h headers are also interesting if you + are already used to the sometimes cryptical abbreviations diff --git a/lib/libdvd/libdvdnav/TODO b/lib/libdvd/libdvdnav/TODO new file mode 100644 index 0000000000..3fe2eed5af --- /dev/null +++ b/lib/libdvd/libdvdnav/TODO @@ -0,0 +1,12 @@ +* Support DVDs with errors on them. So we can recover from corrupt sectors in the .VOB. Also, handle corrupt .IFO files by using the backup .BUP files. +* Support Random and Shuffle Titles. Only sequencial 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 +* RELEASE! (maybe it's time for libdvdnav 0.5?) +* Replace the auto* build system with a custom and clean one based on ffmpeg's (partly done) diff --git a/lib/libdvd/libdvdnav/autogen.sh b/lib/libdvd/libdvdnav/autogen.sh new file mode 100755 index 0000000000..6ffc84e710 --- /dev/null +++ b/lib/libdvd/libdvdnav/autogen.sh @@ -0,0 +1,29 @@ +#!/bin/sh +# +# $Id: autogen.sh 1091 2008-06-08 06:37:22Z nicodvb $ +# +# run this to generate all the initial makefiles, etc. + +srcdir=`dirname "$0"` +test -z "$srcdir" && srcdir=. + +ORIGDIR=`pwd` +cd "$srcdir" + +AUTORECONF=${AUTORECONF-autoreconf} + +if ! type $AUTORECONF >/dev/null 2>&1; then + echo "**Error**: Missing \`autoreconf' program." >&2 + echo "You will need the autoconf and automake packages." >&2 + echo "You can download them from ftp://ftp.gnu.org/pub/gnu/." >&2 + exit 1 +fi + +$AUTORECONF -v --install || exit $? +cd "$ORIGDIR" || exit $? + +test "$1" = noconfig && NOCONFIGURE=1 + +if test -z "$NOCONFIGURE"; then + "$srcdir"/configure "$@" +fi diff --git a/lib/libdvd/libdvdnav/configure.ac b/lib/libdvd/libdvdnav/configure.ac new file mode 100644 index 0000000000..e76fa25b8f --- /dev/null +++ b/lib/libdvd/libdvdnav/configure.ac @@ -0,0 +1,253 @@ +dnl -------------------------------------------------------------- +dnl Configure.ac for libdvdnav +dnl -------------------------------------------------------------- + +dnl -------------------------------------------------------------- +dnl Require autoconf version 2.53 +dnl -------------------------------------------------------------- +AC_PREREQ([2.53]) + +dnl -------------------------------------------------------------- +dnl Making releases: dvdnav_sub += 1; change DVDNAV_LT_* accordingly +dnl +dnl These are defined in m4 so they can be passed to AC_INIT +dnl -------------------------------------------------------------- +m4_define([dvdnav_major], [4]) +m4_define([dvdnav_minor], [1]) +m4_define([dvdnav_sub], [3]) +m4_define([dvdnav_pre], []) + +AC_INIT([libdvdnav], [dvdnav_major.dvdnav_minor.dvdnav_sub[]dvdnav_pre]) +AC_CONFIG_SRCDIR([src/dvdnav.c]) +AM_INIT_AUTOMAKE([1.6]) + +dnl create a config.h file (Automake will add -DHAVE_CONFIG_H) +AC_CONFIG_HEADERS([config.h]) +AC_CANONICAL_HOST + +DVDNAV_MAJOR="dvdnav_major" +DVDNAV_MINOR="dvdnav_minor" +DVDNAV_SUB="dvdnav_sub" +DVDNAV_PRE="dvdnav_pre" + +AC_SUBST(DVDNAV_MAJOR) +AC_SUBST(DVDNAV_MINOR) +AC_SUBST(DVDNAV_SUB) + +dnl The libtool version numbers (DVDNAV_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 DVDNAV_LT_REVISION ++; +dnl else { /* interfaces have been added, removed or changed */ +dnl DVDNAV_LT_REVISION = 0; +dnl DVDNAV_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 * DVDNAV_LT_CURRENT is the current API version +dnl * DVDNAV_LT_REVISION is an internal revision number which is increased when the API +dnl itself did not change +dnl * DVDNAV_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.(DVDNAV_LT_CURRENT - DVDNAV_LT_AGE).DVDNAV_LT_AGE.DVDNAV_LT_REVISION + +DVDNAV_LT_CURRENT=5 +DVDNAV_LT_AGE=1 +DVDNAV_LT_REVISION=2 + +AC_SUBST(DVDNAV_LT_CURRENT) +AC_SUBST(DVDNAV_LT_AGE) +AC_SUBST(DVDNAV_LT_REVISION) + +dnl -------------------------------------------------------------- +dnl Make possible to build for another arch. +dnl -------------------------------------------------------------- +if test x$DVDNAV_BUILD != "x"; then + AC_MSG_RESULT(*** build forced to $DVDNAV_BUILD ***) + build=$DVDNAV_BUILD + host=$DVDNAV_BUILD +else + check_athlon=yes +fi + +dnl -------------------------------------------------------------- +dnl Checks for programs. +dnl -------------------------------------------------------------- +dnl Save CFLAGS, AC_ISC_POSIX set some unwanted default CFLAGS +saved_CFLAGS="$CFLAGS" +AC_ISC_POSIX +CFLAGS="$saved_CFLAGS" +AC_PROG_CC +AC_PROG_MAKE_SET +AC_PROG_INSTALL +AC_PROG_LN_S + +dnl -------------------------------------------------------------- +dnl Libtool +dnl -------------------------------------------------------------- +dnl LT_PREREQ only available in libtool-2.2+ +dnl LT_PREREQ([1.4.0]) +AC_LIBTOOL_DLOPEN +AC_DISABLE_STATIC +AC_PROG_LIBTOOL +AC_SUBST(LIBTOOL_DEPS) +if ${CONFIG_SHELL} ./libtool --features | grep "enable static" >/dev/null; then + STATIC="-static" +else + STATIC= +fi +AC_SUBST(STATIC) + +dnl -------------------------------------------------------------- +dnl Checks for header files. +dnl -------------------------------------------------------------- +AC_HEADER_STDC +AC_CHECK_HEADER(unistd.h) +AC_CHECK_HEADER(string.h) + +dnl -------------------------------------------------------------- +dnl Checks for typedefs, structures, and compiler characteristics. +dnl -------------------------------------------------------------- +AC_C_CONST +AC_C_INLINE +AC_TYPE_OFF_T +AC_TYPE_SIZE_T +dnl AC_CHECK_TYPES([ptrdiff_t]) +AC_C_BIGENDIAN + +dnl ------------------------------------------------------------- +dnl Check for basic *nix fonction that we may emulate on windows. +dnl ------------------------------------------------------------- +case $host in + *mingw32* | *cygwin*) + AC_CHECK_FUNCS(gettimeofday) + ;; + *) + ;; +esac + +dnl --------------------------------------------- +dnl threads +dnl --------------------------------------------- +case $host in + *-*-freebsd*) + THREAD_LIBS="-L/usr/local/lib -pthread" + THREAD_CFLAGS="-I/usr/local/include -D_THREAD_SAFE" + CFLAGS="$THREAD_CFLAGS $CFLAGS" + ;; + *mingw32* | *cygwin*) + ;; + *) + AC_CHECK_LIB(pthread, pthread_create, + [THREAD_LIBS="-lpthread"], + AC_MSG_ERROR(pthread needed)) + ;; +esac +AC_SUBST(THREAD_LIBS) +AC_SUBST(THREAD_CFLAGS) + +dnl --------------------------------------------- +dnl dynamic linker +dnl --------------------------------------------- +case $host in + *mingw32*) + CFLAGS="-idirafter \$(top_srcdir)/msvc/include $CFLAGS" + LDFLAGS="-no-undefined $LDFLAGS" + ;; + *cygwin*) + LDFLAGS="-no-undefined $LDFLAGS" + ;; + *) + AC_CHECK_LIB(c, dlopen, + DYNAMIC_LD_LIBS="", + AC_CHECK_LIB(dl, dlopen, + DYNAMIC_LD_LIBS="-ldl", + AC_MSG_ERROR(dynamic linker needed))) + AC_SUBST(DYNAMIC_LD_LIBS) + ;; +esac + +dnl --------------------------------------------- +dnl libdvdread +dnl --------------------------------------------- +AC_ARG_WITH([dvdread-config], + [AS_HELP_STRING([--with-dvdread-config=PROG], + [dvdread-config program to use @<:@default=from PATH@:>@])], + [DVDREAD_CONFIG="$withval"], + [dnl User didn't specify program, search PATH + AC_PATH_PROG([DVDREAD_CONFIG], [dvdread-config], [no]) + test "x$DVDREAD_CONFIG" = xno && \ + AC_MSG_ERROR([dvdread-config required to link with libdvdread]) + ]) +DVDREAD_CFLAGS=`$DVDREAD_CONFIG --cflags` || \ + AC_MSG_ERROR([Could not get libdvdread CFLAGS from $DVDREAD_CONFIG]) +DVDREAD_LIBS=`$DVDREAD_CONFIG --libs` || \ + AC_MSG_ERROR([Could not get libdvdread LIBS from $DVDREAD_CONFIG]) +AC_SUBST([DVDREAD_CFLAGS]) +AC_SUBST([DVDREAD_LIBS]) + +dnl --------------------------------------------- +dnl cflags +dnl --------------------------------------------- +dnl Common cflags for all platforms +CFLAGS="-O3 -Wall -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE $CFLAGS" +DEBUG_CFLAGS="-g -DDEBUG $CFLAGS" + +AC_SUBST(DEBUG_CFLAGS) + +dnl --------------------------------------------- +dnl Get where .m4 should be installed. +dnl --------------------------------------------- +case "`id`" in + uid=0\(* ) + AC_MSG_CHECKING(for aclocal directory) + if (aclocal --version) < /dev/null > /dev/null 2>&1; then + ACLOCAL_DIR="`eval $ACLOCAL --print-ac-dir`" + AC_MSG_RESULT($ACLOCAL_DIR) + else + ACLOCAL_DIR="/usr/local/share/aclocal" + AC_MSG_RESULT(none - will be installed in $ACLOCAL_DIR) + fi + escapedprefix="`echo $prefix | sed -e 's/\\//\\\\\//g'`" + ACLOCAL_DIR="`echo $ACLOCAL_DIR|sed -e 's/^'$escapedprefix/'\${prefix}'/`" + AC_SUBST(ACLOCAL_DIR) + ;; +esac +AM_CONDITIONAL(INSTALL_M4, test x"$ACLOCAL_DIR" != "x") + +dnl --------------------------------------------- +dnl Check for doxygen (dynamic documentation generator) +dnl --------------------------------------------- +AC_CHECK_PROG(DOXYGEN, doxygen, doxygen, no) + +dnl --------------------------------------------- +dnl Some include paths ( !!! DO NOT REMOVE !!! ) +dnl --------------------------------------------- +INCLUDES='-I$(top_srcdir) $(DVDNAV_CFLAGS)' +AC_SUBST(INCLUDES) + +dnl --------------------------------------------- +dnl Output configuration files +dnl --------------------------------------------- +AC_OUTPUT([ +Makefile +src/Makefile +src/vm/Makefile +misc/Makefile +misc/dvdnav-config +misc/dvdnav.pc +misc/dvdnavmini.pc +misc/libdvdnav.spec +misc/relchk.sh +m4/Makefile +doc/Makefile +examples/Makefile +]) diff --git a/lib/libdvd/libdvdnav/configure2 b/lib/libdvd/libdvdnav/configure2 new file mode 100755 index 0000000000..5767a5ab94 --- /dev/null +++ b/lib/libdvd/libdvdnav/configure2 @@ -0,0 +1,172 @@ +#!/bin/sh + +dvdnav_sh_version=4.1.3 +dvdnav_sh_major=`echo $dvdnav_sh_version | awk -F. '{print $1}'` + +cc=gcc +make=make + +# find source path +source_path="`dirname \"$0\"`" +source_path_used="yes" +if test -z "$source_path" -o "$source_path" = "." ; then + source_path="`pwd`" + source_path_used="no" +else + source_path="`cd \"$source_path\" && pwd`" + echo "$source_path" | grep -q '[[:blank:]]' && + die "Out of tree builds are impossible with whitespace in source path." +fi + +show_help(){ + echo "Usage: configure [options]" + echo "Options: [defaults in brackets after descriptions]" + echo + echo "Standard options:" + echo " --help print this message" + echo " --prefix=PREFIX install in PREFIX [$PREFIX]" + echo " --libdir=DIR install libs in DIR [PREFIX/lib]" + echo " --shlibdir=DIR install shared libs in DIR [PREFIX/lib]" + echo " --incdir=DIR install includes in DIR [PREFIX/include/dvdnav]" + echo " --enable-static build static libraries [default=yes]" + echo " --disable-static do not build static libraries [default=no]" + echo " --enable-shared build shared libraries [default=no]" + echo " --disable-shared do not build shared libraries [default=yes]" + echo " --enable-debug compile with debug symbols [default=yes]" + echo " --disable-debug compile without debug symbols [default=no]" + echo " --with-dvdread=PATH compile libdvdnav with an external libdvdread" + echo "Advanced options (experts only):" + echo " --cc=CC use C compiler CC [$cc]" + echo " --make=MAKE use specified make [$make]" + echo " --extra-cflags=ECFLAGS add ECFLAGS to CFLAGS" + echo " --extra-ldflags=ELDFLAGS add ELDFLAGS to LDFLAGS" + echo "Developer options:" + echo " --disable-strip disable stripping of executables and shared libraries" + echo " --disable-opts disable compiler optimizations" + exit 1 +} + +SHARED=yes +STATIC=yes +DVDREAD_CONFIG=dvdread-config +PREFIX=/usr/local/ +INSTALLSTRIP=-s +USEDEBUG=-g +optimizations="-O3" +threadlib="-lpthread" + +for opt do + optval=`echo $opt | cut -d '=' -f 2-` + case "$opt" in + --enable-shared) SHARED=yes + ;; + --disable-shared) SHARED=no + ;; + --enable-static) STATIC=yes + ;; + --disable-static) STATIC=no + ;; + --with-dvdread-config=*) DVDREAD_CONFIG="$optval" + ;; + --prefix=*) PREFIX="$optval" + ;; + --libdir=*) libdir="$optval" + ;; + --shlibdir=*) shlibdir="$optval" + ;; + --incdir=*) incdir="$optval" + ;; + --cc=*) cc="$optval" + ;; + --make=*) make="$optval" + ;; + --extra-cflags=*) cflags="$cflags $optval" + ;; + --extra-ldflags=*) ldflags="$ldflags $optval" + ;; + --disable-strip) INSTALLSTRIP= + ;; + --disable-opts) optimizations="" + ;; + --disable-debug) USEDEBUG="" + ;; + --enable-debug) USEDEBUG="-g" + ;; + --help) show_help + ;; + esac +done + +PREFIX=`cd $PREFIX && pwd` + +test -z "$libdir" && libdir=$PREFIX/lib +test -z "$shlibdir" && shlibdir=$PREFIX/lib +test -z "$incdir" && incdir=$PREFIX/include/dvdnav + +dvdread=no +$DVDREAD_CONFIG --prefix >> /dev/null 2>&1 && dvdread=yes +test "$dvdread" != "yes" && $DVDREAD_CONFIG --exists >> /dev/null 2>&1 && dvdread=yes +if test "$dvdread" != "yes" ; then + echo "$DVDREAD_CONFIG returned an error. Can't proceed" + exit 1 +fi +dvdread_cflags=`$DVDREAD_CONFIG --cflags` +dvdread_libs=`$DVDREAD_CONFIG --libs` + +targetos=`uname -s` +case $targetos in + Darwin) + SHLDFLAGS="-dynamiclib -Wl,-single_module -Wl,-read_only_relocs,suppress" + ;; + *) + SHLDFLAGS="-shared" + ;; +esac + +cat > config.mak << EOF +# Automatically generated by configure, do not edit +PREFIX=$PREFIX +libdir=$libdir +shlibdir=$shlibdir +incdir=$incdir +THREADLIB=$threadlib +BUILD_SHARED=$SHARED +BUILD_STATIC=$STATIC +SHLIB_VERSION=$dvdnav_sh_version +SHLIB_MAJOR=$dvdnav_sh_major +CC=$cc +MAKE=$make +CFLAGS=$optimizations $cflags +LDFLAGS=$ldflags +SHLDFLAGS=$SHLDFLAGS +INSTALLSTRIP=$INSTALLSTRIP +USEDEBUG=$USEDEBUG +DVDREAD_CFLAGS=$dvdread_cflags +DVDREAD_LIBS=$dvdread_libs + +SRC_PATH="$source_path" +SRC_PATH_BARE=$source_path + +EOF + +cat > config.h << EOF +/* Automatically generated by configure, do not edit */ +#include "version.h" +EOF + +# build tree in object directory if source path is different from current one +if test "$source_path_used" != "no"; then + FILES="\ + Makefile \ + misc \ + " + for f in $FILES ; do + ln -sf "$source_path/$f" $f + done +fi + +[ -d obj ] || mkdir -p obj + +echo +echo "Done, type 'make install' to build and install" + diff --git a/lib/libdvd/libdvdnav/doc/Makefile.am b/lib/libdvd/libdvdnav/doc/Makefile.am new file mode 100644 index 0000000000..205f055b1a --- /dev/null +++ b/lib/libdvd/libdvdnav/doc/Makefile.am @@ -0,0 +1,8 @@ +include $(top_srcdir)/misc/Makefile.common + +EXTRA_DIST = doxy.conf mainpage.cpp tutorial.cpp dvd_structures library_layout + +docs: doxy.conf + @if test x"$(DOXYGEN)" != "xno"; then \ + $(DOXYGEN) doxy.conf > /dev/null 2> /dev/null; \ + fi diff --git a/lib/libdvd/libdvdnav/doc/doxy.conf b/lib/libdvd/libdvdnav/doc/doxy.conf new file mode 100644 index 0000000000..a55f262943 --- /dev/null +++ b/lib/libdvd/libdvdnav/doc/doxy.conf @@ -0,0 +1,947 @@ +# Doxyfile 1.2.16 + +# 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 (" ") + +#--------------------------------------------------------------------------- +# General configuration options +#--------------------------------------------------------------------------- + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = libdvdnav + +# 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 = + +# 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 = + +# 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: +# Brazilian, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, +# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Korean, +# Norwegian, Polish, Portuguese, Romanian, Russian, Slovak, Slovene, +# Spanish, Swedish and Ukrainian. + +OUTPUT_LANGUAGE = English + +# 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 + +# 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 class will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# 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 + +# 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. It is allowed to use relative paths in the argument list. + +STRIP_FROM_PATH = + +# 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 + +# 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 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 +# users are adviced to set this option to NO. + +CASE_SENSE_NAMES = YES + +# 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 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 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 + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# 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 the Qt-style comments (thus requiring an +# explict @brief command for a brief description. + +JAVADOC_AUTOBRIEF = YES + +# If the DETAILS_AT_TOP tag is set to YES then Doxygen +# will output the detailed description near the top, like JavaDoc. +# If set to NO, the detailed description appears after the member +# documentation. + +DETAILS_AT_TOP = 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 +# reimplements. + +INHERIT_DOCS = YES + +# 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 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 + +# 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 + +# 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 + +# 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 = + +# 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 consist 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 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 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 + +#--------------------------------------------------------------------------- +# 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 = NO + +# 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 + +# 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. + +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 = . + +# 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 + +FILE_PATTERNS = + +# 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 = NO + +# 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 = + +# 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. + +EXCLUDE_PATTERNS = + +# 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 = examples + + +# 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 <filter> <input-file>, where <filter> +# is the value of the INPUT_FILTER tag, and <input-file> is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. + +INPUT_FILTER = + +# 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. + +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. + +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 + +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# 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 (the default) +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = 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 = + +# 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 = + +# 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 + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# 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 compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# 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 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 = NO + +# 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 + +# If the GENERATE_TREEVIEW tag is set to YES, 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 and frames is required (for instance Mozilla, Netscape 4.0+, +# or Internet explorer 4.0+). Note that for large projects the tree generation +# can take a very long time. In such cases it is better to disable this feature. +# Windows users are probably better off using the HTML help feature. + +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 + +#--------------------------------------------------------------------------- +# 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 = YES + +# The LATEX_OUTPUT tag is used to specify where the LaTeX 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 `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = 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 optimised 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 assigments. 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. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_XML = NO + +#--------------------------------------------------------------------------- +# 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 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_PREDEFINED 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. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_PREDEF_ONLY 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 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::addtions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES tag can be used to specify one or more tagfiles. + +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 superceded by the HAVE_DOT option below. This is only a fallback. It is +# recommended to install and use dot, since it yield more powerful graphs. + +CLASS_DIAGRAMS = YES + +# 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 + +# 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 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 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 + +# 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 on 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 MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_WIDTH = 1024 + +# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_HEIGHT = 1024 + +# 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 intermedate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::addtions 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 + +# The CGI_NAME tag should be the name of the CGI script that +# starts the search engine (doxysearch) with the correct parameters. +# A script with this name will be generated by doxygen. + +CGI_NAME = search.cgi + +# The CGI_URL tag should be the absolute URL to the directory where the +# cgi binaries are located. See the documentation of your http daemon for +# details. + +CGI_URL = + +# The DOC_URL tag should be the absolute URL to the directory where the +# documentation is located. If left blank the absolute path to the +# documentation, with file:// prepended to it, will be used. + +DOC_URL = + +# The DOC_ABSPATH tag should be the absolute path to the directory where the +# documentation is located. If left blank the directory on the local machine +# will be used. + +DOC_ABSPATH = + +# The BIN_ABSPATH tag must point to the directory where the doxysearch binary +# is installed. + +BIN_ABSPATH = /usr/local/bin/ + +# The EXT_DOC_PATHS tag can be used to specify one or more paths to +# documentation generated for other projects. This allows doxysearch to search +# the documentation for these projects as well. + +EXT_DOC_PATHS = diff --git a/lib/libdvd/libdvdnav/doc/dvd_structures b/lib/libdvd/libdvdnav/doc/dvd_structures new file mode 100644 index 0000000000..9d8569bab7 --- /dev/null +++ b/lib/libdvd/libdvdnav/doc/dvd_structures @@ -0,0 +1,107 @@ +This is some rather basic information on the organizational structures of +a DVD. I collected this info over time from various sources, the most +valuable being an article in the German c't computer magazine. +Some of the info might be wrong according to the DVD standard (which I do +not know), but they are practically proven in libdvdnav. + + Michael Roitzsch + + +0. storage structure + - sector + * smallest addressable unit on disc + * data is stored on disc with a Reed-Solomon error correction + - file + * the storage entity in the underlying filesystem (usually UDF) + * on DVD-Video, files are stored consecutively +1. MPEG stream structure + - blocks + * a file system driver (usually UDF) is needed to map the VOBS-local + block numbers to global disc sectors + - GOP (group of pictures) + * contains multiple sectors + * smallest self-contained MPEG unit + - VOBU (video object unit) + * contains multiple GOPs + audio and SPU blocks + NAV packet + * smallest unit in seek and resume operations, always starts with a + NAV packet used for menu button highlight and command information + and to detect PTS discontinuities + - ILVU (interleaved video unit) + * contains multiple VOBUs (ususally only one) + * blocking multiple VOBUs of multiple interleaved MPEG streams for + multiangle features + - VOB (video object) + * contains multiple ILVUs (usually quite a lot) + * each NAV packet has a CellID, so VOBs are divided into stream Cells + which do not necessarily correspond to the navigation Cells below + - VOBS (video object set) + * contains multiple VOBs (addressed by VOB_ID) + * a VOBS is the storage analogy to the playback domains below, + therefore, a VMGM_VOBS, a VTSM_VOBS and a VTS_VOBS exist + * all block addressing is done within the scope of the VOBS +2. navigational structure - logical playback control + - Cell + * smallest unit which is layed out in sequence + * points to a first and last VOBU (by sector) + * also points to the corresponding CellID and VOB_ID + * smallest unit to execute VM commands (cell_post commands) + * smallest unit accesible by VM commands (apart from LinkRSM) + - PG (program) + * points to a Cell + * usually the mapping between PG and Cells is 1:1, but not always + (multiple Cells inside one PG can occur when special VM commands + have to be executed in the middle of a PG, for example to switch + SPU channels or to provide a branching target for special + features that need access to parts of the movie) + * unit for user skip operations + * libdvdnav's default unit for seeking + - PGC (program chain) + * contains multiple programs and cells + * logical playback chain + * VM commands at start and stop (PGC_pre and PGC_post commands) + * might be used for seeking (see dvdnav_set_PGC_positioning()) +3. title structure - high level navigation + - PTT (part of title track) + * points to a PG in a PGC + * usually what you select in a "chapter menu" are parts + * usually the mapping between PTT and PG is 1:1, but not always + (this is similar to the distinction between track and index marks + on audio CDs: PTT = track mark, PG = index mark) + - TT (title track) + * contains multiple PTTs + * logical partitioning of the content + (multiple episodes of a TV series on one DVD: one TT per episode) + * the display of DVD players show title and part number + - VTS (video title set) + * contains multiple TTs with a local numbering (to emphasize the + local scope of the number, these are also called VTS_TT) + * high level partitioning of the content (movie / bonus material) + * video, audio and spu attributes are common inside a whole VTS +4. domain structure - bringing it all together + - FP (first play) + * one special PGC in the VMGM domain run on start of the disc + - VMGM (video manager menu) - files video_ts.{vob,ifo,bup} + * the menu which allows you to select between title sets + * corresponds to the VMGM_VOBS (video_ts.vob) and + the VMGI (video_ts.ifo) + * contains sets of PGCs, differentiated by language + * contains a global table of TTs each pointing to a VTS and a local VTS_TT + * contains parental management information + * contains attribute lists for the VTS'es + * contains text data (?) + * contains a Cell and a VOBU lists with local sector info (for seeking) + - VTSM (video title set menu) - files vts_<vtsN>_0.{vob,ifo,bup} + * the menu which allows you to select between the TTs of a VTS + * corresponds to the VTSM_VOBS (vts_<vtsN>_0.vob) and + the VTSI (vts_<vtsN>_0.ifo) + * contains sets of PGCs, differentiated by language + * contains a Cell and a VOBU lists with local sector info (for seeking) + - VTS (video title set) - files vts_<vtsN>_[1-x].vob, vts_<vtsN>_0.{ifo,bup} + * regular playback domain + * corresponds to the VTS_VOBS (vts_<vtsN>_[1-x].vob) and + the VTSI (vts_<vtsN>_0.ifo) + * contains one VTS with its VTS_TTs and PGCs + * contains a time map (for time-based seeking) + * contains a Cell and a VOBU lists with local sector info (for seeking) + - STOP + * 'nuff said diff --git a/lib/libdvd/libdvdnav/doc/library_layout b/lib/libdvd/libdvdnav/doc/library_layout new file mode 100644 index 0000000000..74116a9682 --- /dev/null +++ b/lib/libdvd/libdvdnav/doc/library_layout @@ -0,0 +1,53 @@ +This is information on what the various files in libdvdnav/src are for: + +public API +---------- + +dvdnav.h main public header +dvdnav_events.h events returned by get_next_block() +dvd_types.h some additional convenience types, mostly unused yet + +dvd_reader.h libdvdread API +ifo_types.h IFO structures translated into C +ifo_read.h reading and parsing of IFO structures +nav_types.h NAV structures translated into C +nav_read.h reading and parsing of NAV structures +nav_print.h print NAV structures in a human readable form + +client interaction +------------------ + +dvdnav.c the big get_next_block() function and some basic housekeeping +dvdnav_internal.h internal structure of libdvdnav library handle +navigation.c basic Title/Part navigation +searching.c PGC/PG navigation and seeking, position reporting +highlight.c DVD menu highlight handling +settings.c libdvdnav customizing +remap.[ch] user defined reorganization of VOBU playback order + +DVD virtual machine (subdirectory vm) +------------------- + +vm.[ch] the logic surrounding the DVD VM +decoder.[ch] decodes and executes DVD VM commands + +DVD reading (subdirectory dvdread, a modified copy of libdvdread) +----------- + +dvd_reader.c reading data from DVD sources +dvd_udf.[ch] handles the UDF filesystem +dvd_input.[ch] lowlevel input abstraction, libdvdcss glue code +md5.[ch] md5 hashing to provide unique disc IDs + +ifo_read.c reading and parsing of IFO structures +nav_read.c reading and parsing of NAV structures +nav_print.c output NAV structures in a human readable form + +read_cache.[ch] caching + +debugging and utilities +----------------------- + +bswap.h endianness helper macros +dvdread_internal.h CHECK_VALUE() helper macro +vmcmd.[ch] print DVD VM commands and registers in a human readable form diff --git a/lib/libdvd/libdvdnav/doc/mainpage.cpp b/lib/libdvd/libdvdnav/doc/mainpage.cpp new file mode 100644 index 0000000000..3f5e88c5bc --- /dev/null +++ b/lib/libdvd/libdvdnav/doc/mainpage.cpp @@ -0,0 +1,51 @@ +/*! + +\mainpage The libdvdnav Reference Documentation + +\section intro Introduction + +This reference is not maintained. See the README file for pointers on +current documentation. + +This reference documentation is intended to both provide a comprehensive reference to +the <tt>libdvdnav</tt> DVD navigation library and a brief introduction to the library +for new users. + +This documentation is automatically generated from the <tt>libdvdnav</tt> code so +should remain somewhat relevant but as always be wary that <tt>libdvdnav</tt> +is currently in heavy development and the API is not yet frozen. + +\subsection feedback Feedback + +All comments, error reports, additional information and criticism of all sorts +should be directed to <tt>dvd-devel@lists.sf.net</tt>. + +\subsection disclaimer Disclaimer + +No liability for the contents of this documents can be accepted. Use the concepts, +examples and other content at your own risk. Additionally, this is an early version, +with many possibilities for inaccuracies and errors. + +As far as I know, all of the programmes mentioned here and example code quoted are +released under the GNU General Public License or the Lesser GNU Public License. + +\subsection copyright Copyright information + +This document is copyrighted ©2002 by Richard Wareham and the <tt>libdvdnav</tt> +project. It is distributed under the following terms: + + - This document may be reproduced and distributed in whole or in part, in any medium + physical or electronic, as long as this copyright notice is retained on all copies. + Commercial redistribution is allowed and encouraged; however, the author would like + to be notified of any such distributions. + - All translations, derivative works, or aggregate works incorporating any parts of + this document must be covered under this copyright notice. That is, you may not produce + a derivative work from this manual and impose additional restrictions on its distribution. + +\section sections Section + + - A tutorial is in section \ref tutorial . + - A complete reference may be found in the <A HREF="modules.html">modules</a> section. + +*/ + diff --git a/lib/libdvd/libdvdnav/doc/tutorial.cpp b/lib/libdvd/libdvdnav/doc/tutorial.cpp new file mode 100644 index 0000000000..5306eb8749 --- /dev/null +++ b/lib/libdvd/libdvdnav/doc/tutorial.cpp @@ -0,0 +1,253 @@ +/*! \page tutorial A libdvdnav Tutorial + +The <tt>libdvdnav</tt> library provides a powerful API allowing your +programs to take advantage of the sophisticated navigation features +on DVDs. + +\subsection wherenow Tutorial sections + + - For an introduction to the navigation features of DVDs look in section + \ref dvdnavissues . This also provides an overview of the concepts + required to understand DVD navigation. + - For a step-by step walkthrough of a simple program look in + section \ref firstprog . + - FIXME: More sections :) + +*/ + +/*! \page dvdnavissues An introduction to DVD navigation + +The DVD format represents a radical departure from the traditional +form of video home-entertainment. Instead of just being a linear +programme which is watched from beginning to end like a novel +DVD allows the user to jump about at will (much like those +'Choose your own adventure' or 'Which Way' books which were +popular a while back). + +Such features are usually referred to under the moniker +'interactive' by marketting people but you aren't in marketting +since you are reading the <tt>libdvdnav</tt> tutorial. We'll +assume you actually want to know precisely what DVD can do. + +\subsection layout DVD logical layout + +A DVD is logically structured into titles, chapters (also +known as 'parts'), cells and VOBUS, much like the +filesystem on your hard disc. The structure is heirachical. +A typical DVD might have the following structure: + +\verbatim + . + |-- Title 1 + | |-- Chapter 1 + | | |-- Cell 1 + | | | |-- VOBU 1 + | | | |-- ... + | | | `-- VOBU n + | | |-- ... + | | `-- Cell n + | |-- ... + | `-- Chapter 2 + | |-- Cell 1 + | | |-- VOBU 1 + | | |-- ... + | | `-- VOBU n + | |-- ... + | `-- Cell n + |-- ... + `-- Title m + |-- Chapter 1 + | |-- Cell 1 + | | |-- VOBU 1 + | | |-- ... + | | `-- VOBU n + | |-- ... + | `-- Cell n + |-- ... + `-- Chapter 2 + |-- Cell 1 + | |-- VOBU 1 + | |-- ... + | `-- VOBU n + |-- ... + `-- Cell n +\endverbatim + +A DVD 'Title' is generally a logically distinct section of video. For example the main +feature film on a DVD might be Title 1, a behind-the-scenes documentary might be Title 2 +and a selection of cast interviews might be Title 3. There can be up to 99 Titles on +any DVD. + +A DVD 'Chapter' (somewhat confusingly referred to as a 'Part' in the parlence of +DVD authors) is generally a logical segment of a Title such as a scene in a film +or one interview in a set of cast interviews. There can be up to 999 Parts in +one Title. + +A 'Cell' is a small segment of a Part. It is the smallest resolution at which +DVD navigation commands can act (e.g. 'Jump to Cell 3 of Part 4 of Title 2'). +Typically one Part contains one Cell but on complex DVDs it may be useful to have +multiple Cells per Part. + +A VOBU (<I>V</I>ideo <I>OB</I>ject <I>U</I>nit) is a small (typically a few +seconds) of video. It must be a self contained 'Group of Pictures' which +can be understood by the MPEG decoder. All seeking, jumping, etc is guaranteed +to occurr at a VOBU boundary so that the decoder need not be restarted and that +the location jumped to is always the start of a valid MPEG stream. For multiple-angle +DVDs VOBUs for each angle can be interleaved into one Interleaved Video Unit (ILVU). +In this case when the player get to the end of the VOBU for angle <i>n</i> instead of +jumping to the next VOBU the player will move forward to the VOBU for angle <i>n</i> +in the next ILVU. + +This is summarised in the following diagram showing how the VOBUs are actually +laid out on disc. + +\verbatim + ,---------------------------. ,---------------------------. + | ILVU 1 | | ILVU m | + | ,--------. ,--------. | | ,--------. ,--------. | + | | VOBU 1 | ... | VOBU 1 | | ... | | VOBU m | ... | VOBU m | | + | |Angle 1 | |Angle n | | | |Angle 1 | |Angle n | | + | `--------' `--------' | | `--------' `--------' | + `---------------------------' `---------------------------' +\endverbatim + +\subsection vm The DVD Virtual Machine + +If the layout of the DVD were the only feature of the format the DVD +would only have a limited amount of interactivity, you could jump +around between Titles, Parts and Cells but not much else. + +The feature most people associate with DVDs is its ability to +present the user with full-motion interactive menus. To provide +these features the DVD format includes a specification for a +DVD 'virtual machine'. + +To a first order approximation x86 programs can only be run on +x86-based machines, PowerPC programs on PowerPC-based machines and so on. +Java, however, is an exception in that programs are compiled into +a special code which is designed for a 'Java Virtual Machine'. +Programmes exist which take this code and convert it into code which +can run on real processors. + +Similarly the DVD virtual machine is a hypothetical processor +which has commands useful for DVD navigation (e.g. Jump to Title +4 or Jump to Cell 2) along with the ability to perform +simple arithmetic and save values in a number of special +variables (in processor speak, they are known as 'registers'). + +When a button is pressed on a DVD menu, a specified machine instruction +can be executed (e.g. to jump to a particular Title). Similarly +commands can be executed at the beginning and end of Cells and +Parts to, for example, return to the menu at the end of a film. + +Return to the \ref tutorial. + +*/ + +/*! \page firstprog A first libdvdnav program + +\section compiling Compiling a libdvdnav program + +Below is a simple <tt>libdvdnav</tt> program. Type/copy it and save it +into the file 'dvdtest.c'. + +\verbatim +#include <stdio.h> +#include <dvdnav/dvdnav.h> +#include <dvdnav/dvdnav_events.h> +#include <sys/types.h> + +int main(int argc, char **argv) { + dvdnav_t *dvdnav; + int finished, len, event; + uint8_t buf[2050]; + + /* Open the DVD */ + dvdnav_open(&dvdnav, "/dev/dvd"); + + fprintf(stderr, "Reading...\n"); + finished = 0; + while(!finished) { + int result = dvdnav_get_next_block(dvdnav, buf, + &event, &len); + + if(result == DVDNAV_STATUS_ERR) { + fprintf(stderr, "Error getting next block (%s)\n", + dvdnav_err_to_string(dvdnav)); + exit(1); + } + + switch(event) { + case DVDNAV_BLOCK_OK: + /* Write output to stdout */ + fwrite(buf, len, 1, stdout); + break; + case DVDNAV_STILL_FRAME: + { + fprintf(stderr, "Skipping still frame\n"); + dvdnav_still_skip(dvdnav); + } + break; + case DVDNAV_STOP: + { + finished = 1; + } + default: + fprintf(stderr, "Unhandled event (%i)\n", event); + finished = 1; + break; + } + } + + dvdnav_close(dvdnav); + + return 0; +} +\endverbatim + +If you have correctly installled <tt>libdvdnav</tt>, you should have the +command 'dvdnav-config' in your path. If so you can compile this program +with +\verbatim + gcc -o dvdtest dvdtest.c `dvdnav-config --cflags --libs` +\endverbatim + +If all goes well, this should generate the 'dvdtest' program in your current working +directory. You can now start saving a MPEG 2 stream directly off your DVD +with +\verbatim + ./dvdtest 2>error.log >out.mpeg +\endverbatim + +If the command fails, check the error.log file for details. + +\section walkthrorugh Line-by-line walk through + +\verbatim + include <stdio.h> + include <dvdnav/dvdnav.h> + include <dvdnav/dvdnav_events.h> + include <sys/types.h> +\endverbatim + +These lines include the necessary headers. Almost all <tt>libdvdnav</tt> programs +will only need to include the dvdnav.h and dvdnav_events.h header files from +the dvdnav directory. + +\verbatim + dvdnav_open(&dvdnav, "/dev/dvd"); +\endverbatim + +The <tt>libdvdnav</tt> uses <tt>libdvdread</tt> for its DVD I/O. <tt>libdvdread</tt> +accesses the DVD-device directly so dvdnav_open() needs to be passed the location +of the DVD device. <tt>libdvdread</tt> can also open DVD images/mounted DVDs. Read +the <tt>libdvdread</tt> documentation for more information. + +\verbatim + int result = dvdnav_get_next_block(dvdnav, buf, + &event, &len); +\endverbatim + +Return to \ref tutorial. + +*/ diff --git a/lib/libdvd/libdvdnav/examples/Makefile.am b/lib/libdvd/libdvdnav/examples/Makefile.am new file mode 100644 index 0000000000..c4540f51e0 --- /dev/null +++ b/lib/libdvd/libdvdnav/examples/Makefile.am @@ -0,0 +1,13 @@ +include $(top_srcdir)/misc/Makefile.common + +AM_CPPFLAGS = -DDVDNAV_COMPILE $(DVDREAD_CFLAGS) -I$(top_srcdir)/src + +DVDNAV_LIB = $(top_builddir)/src/libdvdnav.la + +noinst_PROGRAMS = menus + +menus_SOURCES = menus.c +menus_LDADD = $(DVDNAV_LIB) $(DVDREAD_LIBS) + +$(DVDNAV_LIB): + @cd $(top_builddir)/src/ && $(MAKE) libdvdnav.la diff --git a/lib/libdvd/libdvdnav/examples/menus.c b/lib/libdvd/libdvdnav/examples/menus.c new file mode 100644 index 0000000000..5f83005576 --- /dev/null +++ b/lib/libdvd/libdvdnav/examples/menus.c @@ -0,0 +1,281 @@ +/* + * Copyright (C) 2003 by the libdvdnav project + * + * This file is part of libdvdnav, a DVD navigation library. + * + * libdvdnav 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. + * + * libdvdnav 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 + * + * $Id: menus.c 1135 2008-09-06 21:55:51Z rathann $ + * + */ + +#include <stdio.h> +#include <unistd.h> +#include <inttypes.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include "dvd_types.h" +#include <dvdread/dvd_reader.h> +#include <dvdread/nav_types.h> +#include <dvdread/ifo_types.h> /* For vm_cmd_t */ +#include "dvdnav.h" +#include "dvdnav_events.h" + +/* shall we use libdvdnav's read ahead cache? */ +#define DVD_READ_CACHE 1 + +/* which is the default language for menus/audio/subpictures? */ +#define DVD_LANGUAGE "en" + +#ifdef WIN32 +#define S_IRWXG 0 +#endif + +int main(int argc, char **argv) { + dvdnav_t *dvdnav; + uint8_t mem[DVD_VIDEO_LB_LEN]; + int finished = 0; + int output_fd = 0; + int dump = 0, tt_dump = 0; + + /* open dvdnav handle */ + printf("Opening DVD...\n"); + if (dvdnav_open(&dvdnav, "/dev/dvd") != DVDNAV_STATUS_OK) { + printf("Error on dvdnav_open\n"); + return 1; + } + + /* set read ahead cache usage */ + if (dvdnav_set_readahead_flag(dvdnav, DVD_READ_CACHE) != DVDNAV_STATUS_OK) { + printf("Error on dvdnav_set_readahead_flag: %s\n", dvdnav_err_to_string(dvdnav)); + return 2; + } + + /* set the language */ + if (dvdnav_menu_language_select(dvdnav, DVD_LANGUAGE) != DVDNAV_STATUS_OK || + dvdnav_audio_language_select(dvdnav, DVD_LANGUAGE) != DVDNAV_STATUS_OK || + dvdnav_spu_language_select(dvdnav, DVD_LANGUAGE) != DVDNAV_STATUS_OK) { + printf("Error on setting languages: %s\n", dvdnav_err_to_string(dvdnav)); + return 2; + } + + /* set the PGC positioning flag to have position information relatively to the + * whole feature instead of just relatively to the current chapter */ + if (dvdnav_set_PGC_positioning_flag(dvdnav, 1) != DVDNAV_STATUS_OK) { + printf("Error on dvdnav_set_PGC_positioning_flag: %s\n", dvdnav_err_to_string(dvdnav)); + return 2; + } + + + /* the read loop which regularly calls dvdnav_get_next_block + * and handles the returned events */ + printf("Reading...\n"); + while (!finished) { + int result, event, len; + uint8_t *buf = mem; + + /* the main reading function */ +#if DVD_READ_CACHE + result = dvdnav_get_next_cache_block(dvdnav, &buf, &event, &len); +#else + result = dvdnav_get_next_block(dvdnav, buf, &event, &len); +#endif + + if (result == DVDNAV_STATUS_ERR) { + printf("Error getting next block: %s\n", dvdnav_err_to_string(dvdnav)); + return 3; + } + + switch (event) { + case DVDNAV_BLOCK_OK: + /* We have received a regular block of the currently playing MPEG stream. + * A real player application would now pass this block through demuxing + * and decoding. We simply write it to disc here. */ + + if (!output_fd) { + printf("Opening output...\n"); + output_fd = open("libdvdnav.mpg", O_CREAT | O_WRONLY, S_IRWXU | S_IRWXG); + if (output_fd == -1) { + printf("Error opening output\n"); + return 4; + } + } + + if (dump || tt_dump) + write(output_fd, buf, len); + + break; + case DVDNAV_NOP: + /* Nothing to do here. */ + break; + case DVDNAV_STILL_FRAME: + /* We have reached a still frame. A real player application would wait + * the amount of time specified by the still's length while still handling + * user input to make menus and other interactive stills work. + * A length of 0xff means an indefinite still which has to be skipped + * indirectly by some user interaction. */ + { + dvdnav_still_event_t *still_event = (dvdnav_still_event_t *)buf; + if (still_event->length < 0xff) + printf("Skipping %d seconds of still frame\n", still_event->length); + else + printf("Skipping indefinite length still frame\n"); + dvdnav_still_skip(dvdnav); + } + break; + case DVDNAV_WAIT: + /* We have reached a point in DVD playback, where timing is critical. + * Player application with internal fifos can introduce state + * inconsistencies, because libdvdnav is always the fifo's length + * ahead in the stream compared to what the application sees. + * Such applications should wait until their fifos are empty + * when they receive this type of event. */ + printf("Skipping wait condition\n"); + dvdnav_wait_skip(dvdnav); + break; + case DVDNAV_SPU_CLUT_CHANGE: + /* Player applications should pass the new colour lookup table to their + * SPU decoder */ + break; + case DVDNAV_SPU_STREAM_CHANGE: + /* Player applications should inform their SPU decoder to switch channels */ + break; + case DVDNAV_AUDIO_STREAM_CHANGE: + /* Player applications should inform their audio decoder to switch channels */ + break; + case DVDNAV_HIGHLIGHT: + /* Player applications should inform their overlay engine to highlight the + * given button */ + { + dvdnav_highlight_event_t *highlight_event = (dvdnav_highlight_event_t *)buf; + printf("Selected button %d\n", highlight_event->buttonN); + } + break; + case DVDNAV_VTS_CHANGE: + /* Some status information like video aspect and video scale permissions do + * not change inside a VTS. Therefore this event can be used to query such + * information only when necessary and update the decoding/displaying + * accordingly. */ + break; + case DVDNAV_CELL_CHANGE: + /* Some status information like the current Title and Part numbers do not + * change inside a cell. Therefore this event can be used to query such + * information only when necessary and update the decoding/displaying + * accordingly. */ + { + int32_t tt = 0, ptt = 0; + uint32_t pos, len; + char input = '\0'; + + dvdnav_current_title_info(dvdnav, &tt, &ptt); + dvdnav_get_position(dvdnav, &pos, &len); + printf("Cell change: Title %d, Chapter %d\n", tt, ptt); + printf("At position %.0f%% inside the feature\n", 100 * (double)pos / (double)len); + + dump = 0; + if (tt_dump && tt != tt_dump) + tt_dump = 0; + + if (!dump && !tt_dump) { + fflush(stdin); + while ((input != 'a') && (input != 's') && (input != 'q') && (input != 't')) { + printf("(a)ppend cell to output\n(s)kip cell\nappend until end of (t)itle\n(q)uit\n"); + scanf("%c", &input); + } + + switch (input) { + case 'a': + dump = 1; + break; + case 't': + tt_dump = tt; + break; + case 'q': + finished = 1; + } + } + } + break; + case DVDNAV_NAV_PACKET: + /* A NAV packet provides PTS discontinuity information, angle linking information and + * button definitions for DVD menus. Angles are handled completely inside libdvdnav. + * For the menus to work, the NAV packet information has to be passed to the overlay + * engine of the player so that it knows the dimensions of the button areas. */ + { + pci_t *pci; + + /* Applications with fifos should not use these functions to retrieve NAV packets, + * they should implement their own NAV handling, because the packet you get from these + * functions will already be ahead in the stream which can cause state inconsistencies. + * Applications with fifos should therefore pass the NAV packet through the fifo + * and decoding pipeline just like any other data. */ + pci = dvdnav_get_current_nav_pci(dvdnav); + dvdnav_get_current_nav_dsi(dvdnav); + + if(pci->hli.hl_gi.btn_ns > 0) { + int button; + + printf("Found %i DVD menu buttons...\n", pci->hli.hl_gi.btn_ns); + + for (button = 0; button < pci->hli.hl_gi.btn_ns; button++) { + btni_t *btni = &(pci->hli.btnit[button]); + printf("Button %i top-left @ (%i,%i), bottom-right @ (%i,%i)\n", + button + 1, btni->x_start, btni->y_start, + btni->x_end, btni->y_end); + } + + button = 0; + while ((button <= 0) || (button > pci->hli.hl_gi.btn_ns)) { + printf("Which button (1 to %i): ", pci->hli.hl_gi.btn_ns); + scanf("%i", &button); + } + + printf("Selecting button %i...\n", button); + /* This is the point where applications with fifos have to hand in a NAV packet + * which has traveled through the fifos. See the notes above. */ + dvdnav_button_select_and_activate(dvdnav, pci, button); + } + } + break; + case DVDNAV_HOP_CHANNEL: + /* This event is issued whenever a non-seamless operation has been executed. + * Applications with fifos should drop the fifos content to speed up responsiveness. */ + break; + case DVDNAV_STOP: + /* Playback should end here. */ + { + finished = 1; + } + break; + default: + printf("Unknown event (%i)\n", event); + finished = 1; + break; + } +#if DVD_READ_CACHE + dvdnav_free_cache_block(dvdnav, buf); +#endif + } + + /* destroy dvdnav handle */ + if (dvdnav_close(dvdnav) != DVDNAV_STATUS_OK) { + printf("Error on dvdnav_close: %s\n", dvdnav_err_to_string(dvdnav)); + return 5; + } + close(output_fd); + + return 0; +} diff --git a/lib/libdvd/libdvdnav/m4/Makefile.am b/lib/libdvd/libdvdnav/m4/Makefile.am new file mode 100644 index 0000000000..fdcb9410e4 --- /dev/null +++ b/lib/libdvd/libdvdnav/m4/Makefile.am @@ -0,0 +1,11 @@ +include $(top_srcdir)/misc/Makefile.common + +EXTRA_DIST = dvdnav.m4 + +if INSTALL_M4 +m4datadir = @ACLOCAL_DIR@ +else +m4datadir = $(datadir)/aclocal +endif + +m4data_DATA = dvdnav.m4 diff --git a/lib/libdvd/libdvdnav/m4/dvdnav.m4 b/lib/libdvd/libdvdnav/m4/dvdnav.m4 new file mode 100644 index 0000000000..aa4a2b0f96 --- /dev/null +++ b/lib/libdvd/libdvdnav/m4/dvdnav.m4 @@ -0,0 +1,181 @@ +dnl Configure paths for DVDNAV +dnl +dnl Copyright (C) 2001 Daniel Caujolle-Bert <segfault@club-internet.fr> +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 of the License, or +dnl (at your option) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +dnl +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a configuration +dnl script generated by Autoconf, you may include it under the same +dnl distribution terms that you use for the rest of that program. +dnl + +dnl AM_PATH_DVDNAV([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) +dnl Test for DVDNAV, and define DVDNAV_CFLAGS and DVDNAV_LIBS +dnl +AC_DEFUN([AM_PATH_DVDNAV], +[dnl +dnl Get the cflags and libraries from the dvdnav-config script +dnl +AC_ARG_WITH(dvdnav-prefix, + AC_HELP_STRING([--with-dvdnav-prefix=DIR], [prefix where DVDNAV is installed (optional)]), + dvdnav_config_prefix="$withval", dvdnav_config_prefix="") +AC_ARG_WITH(dvdnav-exec-prefix, + AC_HELP_STRING([--with-dvdnav-exec-prefix=DIR], [exec prefix where DVDNAV is installed (optional)]), + dvdnav_config_exec_prefix="$withval", dvdnav_config_exec_prefix="") +AC_ARG_ENABLE(dvdnavtest, + AC_HELP_STRING([--disable-dvdnavtest], [do not try to compile and run a test DVDNAV program]), + enable_dvdnavtest=$enableval, enable_dvdnavtest=yes) + + if test x$dvdnav_config_exec_prefix != x ; then + dvdnav_config_args="$dvdnav_config_args --exec-prefix=$dvdnav_config_exec_prefix" + if test x${DVDNAV_CONFIG+set} != xset ; then + DVDNAV_CONFIG=$dvdnav_config_exec_prefix/bin/dvdnav-config + fi + fi + if test x$dvdnav_config_prefix != x ; then + dvdnav_config_args="$dvdnav_config_args --prefix=$dvdnav_config_prefix" + if test x${DVDNAV_CONFIG+set} != xset ; then + DVDNAV_CONFIG=$dvdnav_config_prefix/bin/dvdnav-config + fi + fi + + min_dvdnav_version=ifelse([$1], ,0.0.0,$1) + if test "x$enable_dvdnavtest" != "xyes" ; then + AC_MSG_CHECKING([for DVDNAV-LIB version >= $min_dvdnav_version]) + else + AC_PATH_PROG(DVDNAV_CONFIG, dvdnav-config, no) + AC_MSG_CHECKING([for DVDNAV-LIB version >= $min_dvdnav_version]) + no_dvdnav="" + if test "$DVDNAV_CONFIG" = "no" ; then + no_dvdnav=yes + else + DVDNAV_CFLAGS=`$DVDNAV_CONFIG $dvdnav_config_args --cflags` + DVDNAV_LIBS=`$DVDNAV_CONFIG $dvdnav_config_args --libs` + dvdnav_config_major_version=`$DVDNAV_CONFIG $dvdnav_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + dvdnav_config_minor_version=`$DVDNAV_CONFIG $dvdnav_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + dvdnav_config_sub_version=`$DVDNAV_CONFIG $dvdnav_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + dnl if test "x$enable_dvdnavtest" = "xyes" ; then + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $DVDNAV_CFLAGS" + LIBS="$DVDNAV_LIBS $LIBS" +dnl +dnl Now check if the installed DVDNAV is sufficiently new. (Also sanity +dnl checks the results of dvdnav-config to some extent +dnl + AC_LANG_SAVE() + AC_LANG_C() + rm -f conf.dvdnavtest + AC_TRY_RUN([ +#include <dvdnav.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +int +main () +{ + int major, minor, sub; + char *tmp_version; + + system ("touch conf.dvdnavtest"); + + /* HP/UX 9 (%@#!) writes to sscanf strings */ + tmp_version = (char *) strdup("$min_dvdnav_version"); + if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &sub) != 3) { + printf("%s, bad version string\n", "$min_dvdnav_version"); + exit(1); + } + + if (($dvdnav_config_major_version > major) || + (($dvdnav_config_major_version == major) && ($dvdnav_config_minor_version > minor)) || + (($dvdnav_config_major_version == major) && ($dvdnav_config_minor_version == minor) && ($dvdnav_config_sub_version >= sub))) { + return 0; + } else { + printf("\n*** An old version of libdvdnav (%d.%d.%d) was found.\n", + $dvdnav_config_major_version, $dvdnav_config_minor_version, $dvdnav_config_sub_version); + printf("*** You need a version of libdvdnav newer than %d.%d.%d. The latest version of\n", + major, minor, sub); + printf("*** libdvdnav is always available from:\n"); + printf("*** http://dvd.sourceforge.net\n"); + printf("***\n"); + printf("*** If you have already installed a sufficiently new version, this error\n"); + printf("*** probably means that the wrong copy of the dvdnav-config shell script is\n"); + printf("*** being found. The easiest way to fix this is to remove the old version\n"); + printf("*** of libdvdnav, but you can also set the DVDNAV_CONFIG environment to point to the\n"); + printf("*** correct copy of dvdnav-config. (In this case, you will have to\n"); + printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n"); + printf("*** so that the correct libraries are found at run-time))\n"); + } + return 1; +} +],, no_dvdnav=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + if test "x$no_dvdnav" = x ; then + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) + else + AC_MSG_RESULT(no) + if test "$DVDNAV_CONFIG" = "no" ; then + echo "*** The dvdnav-config script installed by DVDNAV could not be found" + echo "*** If DVDNAV was installed in PREFIX, make sure PREFIX/bin is in" + echo "*** your path, or set the DVDNAV_CONFIG environment variable to the" + echo "*** full path to dvdnav-config." + else + if test -f conf.dvdnavtest ; then + : + else + echo "*** Could not run DVDNAV test program, checking why..." + CFLAGS="$CFLAGS $DVDNAV_CFLAGS" + LIBS="$LIBS $DVDNAV_LIBS" + AC_TRY_LINK([ +#include <dvdnav.h> +#include <stdio.h> +], [ return 0; ], + [ echo "*** The test program compiled, but did not run. This usually means" + echo "*** that the run-time linker is not finding DVDNAV or finding the wrong" + echo "*** version of DVDNAV. If it is not finding DVDNAV, you'll need to set your" + echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" + echo "*** to the installed location Also, make sure you have run ldconfig if that" + echo "*** is required on your system" + echo "***" + echo "*** If you have an old version installed, it is best to remove it, although" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" + echo "***"], + [ echo "*** The test program failed to compile or link. See the file config.log for the" + echo "*** exact error that occured. This usually means DVDNAV was incorrectly installed" + echo "*** or that you have moved DVDNAV since it was installed. In the latter case, you" + echo "*** may want to edit the dvdnav-config script: $DVDNAV_CONFIG" ]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + DVDNAV_CFLAGS="" + DVDNAV_LIBS="" + ifelse([$3], , :, [$3]) + fi + AC_SUBST(DVDNAV_CFLAGS) + AC_SUBST(DVDNAV_LIBS) + AC_LANG_RESTORE() + rm -f conf.dvdnavtest +]) diff --git a/lib/libdvd/libdvdnav/misc/Makefile.am b/lib/libdvd/libdvdnav/misc/Makefile.am new file mode 100644 index 0000000000..86726307c5 --- /dev/null +++ b/lib/libdvd/libdvdnav/misc/Makefile.am @@ -0,0 +1,8 @@ +include $(top_srcdir)/misc/Makefile.common + +EXTRA_DIST = dvdnav-config.in libdvdnav.spec.in libdvdnav.spec Makefile.common relchk.sh relchk.sh.in + +bin_SCRIPTS = dvdnav-config + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = dvdnav.pc dvdnavmini.pc diff --git a/lib/libdvd/libdvdnav/misc/Makefile.common b/lib/libdvd/libdvdnav/misc/Makefile.common new file mode 100644 index 0000000000..6faa23f2c7 --- /dev/null +++ b/lib/libdvd/libdvdnav/misc/Makefile.common @@ -0,0 +1,10 @@ +MOSTLYCLEANFILES = *~ \\\#* .*~ .\\\#* +MAINTAINERCLEANFILES = Makefile.in + +debug: + @$(MAKE) CFLAGS="$(DEBUG_CFLAGS)" + +debug-install: install-debug + +install-debug: + @$(MAKE) CFLAGS="$(DEBUG_CFLAGS)" install diff --git a/lib/libdvd/libdvdnav/misc/dvdnav-config.in b/lib/libdvd/libdvdnav/misc/dvdnav-config.in new file mode 100644 index 0000000000..4e65cc1c65 --- /dev/null +++ b/lib/libdvd/libdvdnav/misc/dvdnav-config.in @@ -0,0 +1,88 @@ +#!/bin/sh +# +# + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +exec_prefix_set=no + +usage() +{ + cat <<EOF +Usage: dvdnav-config [OPTIONS] [LIBRARIES] +Options: + [--prefix[=DIR]] + [--exec-prefix[=DIR]] + [--version] + [--libs] + [--minilibs] + [--cflags] +EOF + exit $1 +} + +if test $# -eq 0; then + usage 1 1>&2 +fi + +while test $# -gt 0; do + case "$1" in + -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) optarg= ;; + esac + + case $1 in + --prefix=*) + prefix=$optarg + if test $exec_prefix_set = no ; then + exec_prefix=$optarg + fi + ;; + --prefix) + echo_prefix=yes + ;; + --exec-prefix=*) + exec_prefix=$optarg + exec_prefix_set=yes + ;; + --exec-prefix) + echo_exec_prefix=yes + ;; + --version) + echo @DVDNAV_MAJOR@.@DVDNAV_MINOR@.@DVDNAV_SUB@ + ;; + --cflags) + echo_cflags=yes + ;; + --libs) + echo_libs=yes + ;; + --minilibs) + echo_minilibs=yes + ;; + *) + usage 1 1>&2 + ;; + esac + shift +done + +if test "$echo_prefix" = "yes"; then + echo $prefix +fi + +if test "$echo_exec_prefix" = "yes"; then + echo $exec_prefix +fi + +if test "$echo_cflags" = "yes"; then + echo -I@includedir@ -I@includedir@/libdvdread @THREAD_CFLAGS@ +fi + +if test "$echo_libs" = "yes"; then + echo -L@libdir@ -ldvdnav -ldvdread @THREAD_LIBS@ +fi + +if test "$echo_minilibs" = "yes"; then + echo -L@libdir@ -ldvdnavmini @THREAD_LIBS@ +fi diff --git a/lib/libdvd/libdvdnav/misc/dvdnav-config2.sh b/lib/libdvd/libdvdnav/misc/dvdnav-config2.sh new file mode 100644 index 0000000000..c8cdd05391 --- /dev/null +++ b/lib/libdvd/libdvdnav/misc/dvdnav-config2.sh @@ -0,0 +1,72 @@ + extracflags="-DDVDNAV_USES_EXTERNAL_DVDREAD" + +usage() +{ + cat <<EOF +Usage: dvdnav-config [OPTIONS] [LIBRARIES] +Options: + [--prefix[=DIR]] + [--version] + [--libs] + [--cflags] + [--minilibs] + [--minicflags] +EOF + exit $1 +} + +if test $# -eq 0; then + usage 1 1>&2 +fi + +while test $# -gt 0; do + case "$1" in + -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) optarg= ;; + esac + + case $1 in + --prefix) + echo_prefix=yes + ;; + --version) + echo $version + ;; + --cflags) + echo_cflags=yes + ;; + --minicflags) + echo_minicflags=yes + ;; + --libs) + echo_libs=yes + ;; + --minilibs) + echo_minilibs=yes + ;; + *) + usage 1 1>&2 + ;; + esac + shift +done + +if test "$echo_prefix" = "yes"; then + echo $prefix +fi + +if test "$echo_cflags" = "yes"; then + echo -I$prefix/include $dvdread_cflags $extracflags $threadcflags +fi + +if test "$echo_minicflags" = "yes"; then + echo -I$prefix/include -I$prefix/include/dvdnav $extracflags $threadcflags +fi + +if test "$echo_libs" = "yes"; then + echo -L$libdir -ldvdnav $dvdread_libs $threadlib +fi + +if test "$echo_minilibs" = "yes"; then + echo -L$libdir -ldvdnavmini $threadlib +fi diff --git a/lib/libdvd/libdvdnav/misc/dvdnav.pc.in b/lib/libdvd/libdvdnav/misc/dvdnav.pc.in new file mode 100644 index 0000000000..7ed56d3752 --- /dev/null +++ b/lib/libdvd/libdvdnav/misc/dvdnav.pc.in @@ -0,0 +1,12 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libdvdnav +Description: DVD Navigation library +Version: @VERSION@ + +Requires.private: dvdread >= 4.1.2 +Cflags: -I${includedir} @THREAD_CFLAGS@ +Libs: -L${libdir} -ldvdnav @THREAD_LIBS@ diff --git a/lib/libdvd/libdvdnav/misc/dvdnavmini.pc.in b/lib/libdvd/libdvdnav/misc/dvdnavmini.pc.in new file mode 100644 index 0000000000..52945b3b93 --- /dev/null +++ b/lib/libdvd/libdvdnav/misc/dvdnavmini.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libdvdnavmini +Description: DVD Navigation mini library +Version: @VERSION@ + +Cflags: -I${includedir} @DVDREAD_CFLAGS@ @THREAD_CFLAGS@ +Libs: -L${libdir} -ldvdnav @THREAD_LIBS@ diff --git a/lib/libdvd/libdvdnav/misc/libdvdnav.spec.in b/lib/libdvd/libdvdnav/misc/libdvdnav.spec.in new file mode 100644 index 0000000000..43b2c3932b --- /dev/null +++ b/lib/libdvd/libdvdnav/misc/libdvdnav.spec.in @@ -0,0 +1,50 @@ +%define prefix @prefix@ +%define name @PACKAGE_NAME@ +%define ver @PACKAGE_VERSION@ +%define rel 0 + +Name: %{name} +Summary: DVD Navigation library +Version: %{ver} +Release: %{rel} +Group: Development/Libraries +Copyright: GPL +Url: http://dvd.sourceforge.net/ +Source: %{name}-%{version}.tar.gz +Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root + +%description +libdvdnav provides support to applications wishing to make use of advanced +DVD navigation features. + +%prep +%setup + +%build +CFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=%{prefix} +make + +%install +rm -rf $RPM_BUILD_ROOT +make install-strip DESTDIR=$RPM_BUILD_ROOT + +%clean +rm -r $RPM_BUILD_ROOT + +%files +%defattr(-,root,root) +%doc AUTHORS ChangeLog COPYING INSTALL README +%{prefix}/bin/dvdnav-config +%{prefix}/lib/libdvdnav*.la +%{prefix}/lib/libdvdnav*.so.* +%{prefix}/lib/libdvdnav*.so +%{prefix}/include/dvdnav/* +@INSTALL_M4_TRUE@@ACLOCAL_DIR@/dvdnav.m4 + +%changelog +* Sun Mar 18 2002 Daniel Caujolle-Bert <f1rmb@users.sourceforge.net> +- Add missing files. Fix rpm generation. +* Tue Mar 12 2002 Rich Wareham <richwareham@users.sourceforge.net> +- Canabalisation to form libdvdnav spec file. +* Sun Sep 09 2001 Thomas Vander Stichele <thomas@apestaart.org> +- first spec file diff --git a/lib/libdvd/libdvdnav/misc/relchk.sh.in b/lib/libdvd/libdvdnav/misc/relchk.sh.in new file mode 100755 index 0000000000..8251874692 --- /dev/null +++ b/lib/libdvd/libdvdnav/misc/relchk.sh.in @@ -0,0 +1,66 @@ +#!/bin/sh +## +## A simple compare directory content utility. +## + +topdir="`pwd`" +distdir="@PACKAGE_NAME@-@PACKAGE_VERSION@" +log="$topdir/dist-log" +logerror="$topdir/dist-errors" + +getdir() { + if test -r .relignore; then + filelist=`ls | grep -Fxvf .relignore` + else + filelist=`ls` + fi + + for file in $filelist; do + + if test -d $file -a $file != "CVS" -a $file != $distdir; then + (cd $file && getdir) || (cd ..) + else + if test ! -d $file -a \ + $file != $log -a \ + $file != $logerror -a \ + $file != "$distdir.tar.gz"; then + + orifile=`pwd`/$file + + distfile=$topdir/$distdir${orifile##*$topdir} + + echo -e "check:\t$orifile\nand\t$distfile" >> $log + + if test ! -e $distfile; then + missingfile=${orifile##$topdir} + echo "${missingfile#/} is missing in tarball" >> $logerror + fi + + fi + fi + + done +} + +main() { + rm -f $log $logerror + + make config.status && make dist && mv $distdir.tar.gz $distdir.tmp.tar.gz && \ + cp config.status config.tmp.status && make clean && make distclean && \ + mv $distdir.tmp.tar.gz $distdir.tar.gz && mv config.tmp.status config.status && \ + tar -xzf $distdir.tar.gz + + echo "Check is running, be patient..." + getdir + + rm -rf $distdir + rm -f $distdir.tar.gz + ./config.status --recheck + ./config.status + + echo " * Log is ${log##*/}" + echo " * Error log is ${logerror##*/}" + +} + +main diff --git a/lib/libdvd/libdvdnav/msvc/config.h b/lib/libdvd/libdvdnav/msvc/config.h new file mode 100755 index 0000000000..c6c6f94dc3 --- /dev/null +++ b/lib/libdvd/libdvdnav/msvc/config.h @@ -0,0 +1,51 @@ +/* config.h. Generated by hand. */ + +#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; diff --git a/lib/libdvd/libdvdnav/msvc/contrib/bcopy.c b/lib/libdvd/libdvdnav/msvc/contrib/bcopy.c new file mode 100755 index 0000000000..21be364aef --- /dev/null +++ b/lib/libdvd/libdvdnav/msvc/contrib/bcopy.c @@ -0,0 +1,8 @@ +#include <string.h> + +void bcopy(const void *IN, void *OUT, size_t N); + +void bcopy(const void *IN, void *OUT, size_t N) +{ + memcpy(OUT, IN, N); +} diff --git a/lib/libdvd/libdvdnav/msvc/contrib/dirent/dirent.c b/lib/libdvd/libdvdnav/msvc/contrib/dirent/dirent.c new file mode 100755 index 0000000000..00289ed57f --- /dev/null +++ b/lib/libdvd/libdvdnav/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 <dirent.h> +#include <errno.h> +#include <io.h> +#include <stdlib.h> +#include <string.h> + +#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 = (DIR *) malloc(sizeof *dir)) != 0 && + (dir->name = (char *) 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/lib/libdvd/libdvdnav/msvc/contrib/dirent/dirent.h b/lib/libdvd/libdvdnav/msvc/contrib/dirent/dirent.h new file mode 100755 index 0000000000..28a17731ab --- /dev/null +++ b/lib/libdvd/libdvdnav/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/lib/libdvd/libdvdnav/msvc/contrib/dlfcn.c b/lib/libdvd/libdvdnav/msvc/contrib/dlfcn.c new file mode 100755 index 0000000000..3eb996bd13 --- /dev/null +++ b/lib/libdvd/libdvdnav/msvc/contrib/dlfcn.c @@ -0,0 +1,97 @@ +/* + * $Id: dlfcn.c 1135 2008-09-06 21:55:51Z rathann $ + * $Name$ + * + * Adopted from Apache DSO code. + * Portions copyright Apache Software Foundation + * + * Structures and types used to implement dlopen, dlsym, etc. + * on Windows 95/NT. + */ +#include <windows.h> +#include <string.h> +#include <stdio.h> + +#include "dlfcn.h" +#include "os_types.h" + +void *dlopen(const char *module_name, int mode) +{ + UINT em; + HINSTANCE dsoh; + char path[MAX_PATH], *p; + /* 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); + 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/lib/libdvd/libdvdnav/msvc/contrib/getopt.c b/lib/libdvd/libdvdnav/msvc/contrib/getopt.c new file mode 100755 index 0000000000..4b3ce3db40 --- /dev/null +++ b/lib/libdvd/libdvdnav/msvc/contrib/getopt.c @@ -0,0 +1,1009 @@ +/* Getopt for GNU. + NOTE: getopt is now part of the C library, so if you don't know what + "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu + before changing it! + + Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97 + Free Software Foundation, Inc. + + This file is part of the GNU C Library. Its master source is NOT part of + the C library, however. The master source lives in /gd/gnu/lib. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>. + Ditto for AIX 3.2 and <stdlib.h>. */ +#ifndef _NO_PROTO +#define _NO_PROTO +#endif + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#if !defined (__STDC__) || !__STDC__ +/* This is a separate conditional since some stdc systems + reject `defined (const)'. */ +#ifndef const +#define const +#endif +#endif + +#include <stdio.h> + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#define GETOPT_INTERFACE_VERSION 2 +#if !defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2 +#include <gnu-versions.h> +#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION +#define ELIDE_CODE +#endif +#endif + +#ifndef ELIDE_CODE + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +/* Don't include stdlib.h for non-GNU C libraries because some of them + contain conflicting prototypes for getopt. */ +#include <stdlib.h> +#include <unistd.h> +#endif /* GNU C library. */ + +#ifdef VMS +#include <unixlib.h> +#if HAVE_STRING_H - 0 +#include <string.h> +#ifdef STRNCASECMP_IN_STRINGS_H +# include <strings.h> +#endif +#endif +#endif + +#if defined (WIN32) && !defined (__CYGWIN32__) || defined(UNDER_CE) +/* It's not Unix, really. See? Capital letters. */ +#include <windows.h> +#define getpid() GetCurrentProcessId() +#endif + +#ifndef _ +/* This is for other GNU distributions with internationalized messages. + When compiling libc, the _ macro is predefined. */ +#ifdef HAVE_LIBINTL_H +#include <libintl.h> +#define _(msgid) gettext (msgid) +#else +#define _(msgid) (msgid) +#endif +#endif + +/* This version of `getopt' appears to the caller like standard Unix `getopt' + but it behaves differently for the user, since it allows the user + to intersperse the options with the other arguments. + + As `getopt' works, it permutes the elements of ARGV so that, + when it is done, all the options precede everything else. Thus + all application programs are extended to handle flexible argument order. + + Setting the environment variable POSIXLY_CORRECT disables permutation. + Then the behavior is completely standard. + + GNU application programs can use a third alternative mode in which + they can distinguish the relative order of options and other arguments. */ + +#include "getopt.h" + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +char *optarg = NULL; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +/* 1003.2 says this must be 1 before any call. */ +int optind = 1; + +/* Formerly, initialization of getopt depended on optind==0, which + causes problems with re-calling getopt as programs generally don't + know that. */ + +int __getopt_initialized = 0; + +/* The next char to be scanned in the option-element + in which the last option character we returned was found. + This allows us to pick up the scan where we left off. + + If this is zero, or a null string, it means resume the scan + by advancing to the next ARGV-element. */ + +static char *nextchar; + +/* Callers store zero here to inhibit the error message + for unrecognized options. */ + +int opterr = 1; + +/* Set to an option character which was unrecognized. + This must be initialized on some systems to avoid linking in the + system's own getopt implementation. */ + +int optopt = '?'; + +/* Describe how to deal with options that follow non-option ARGV-elements. + + If the caller did not specify anything, + the default is REQUIRE_ORDER if the environment variable + POSIXLY_CORRECT is defined, PERMUTE otherwise. + + REQUIRE_ORDER means don't recognize them as options; + stop option processing when the first non-option is seen. + This is what Unix does. + This mode of operation is selected by either setting the environment + variable POSIXLY_CORRECT, or using `+' as the first character + of the list of option characters. + + PERMUTE is the default. We permute the contents of ARGV as we scan, + so that eventually all the non-options are at the end. This allows options + to be given in any order, even with programs that were not written to + expect this. + + RETURN_IN_ORDER is an option available to programs that were written + to expect options and other ARGV-elements in any order and that care about + the ordering of the two. We describe each non-option ARGV-element + as if it were the argument of an option with character code 1. + Using `-' as the first character of the list of option characters + selects this mode of operation. + + The special argument `--' forces an end of option-scanning regardless + of the value of `ordering'. In the case of RETURN_IN_ORDER, only + `--' can cause `getopt' to return -1 with `optind' != ARGC. */ + +static enum +{ + REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER +} +ordering; + +/* Value of POSIXLY_CORRECT environment variable. */ +static char *posixly_correct; + +#ifdef __GNU_LIBRARY__ +/* We want to avoid inclusion of string.h with non-GNU libraries + because there are many ways it can cause trouble. + On some systems, it contains special magic macros that don't work + in GCC. */ +#include <string.h> +#define my_index strchr +#else + +/* Avoid depending on library functions or files + whose names are inconsistent. */ + +char *getenv(); + +static char * + my_index(str, chr) + const char *str; + int chr; +{ + while (*str) + { + if (*str == chr) + return (char *) str; + str++; + } + return 0; +} + +/* If using GCC, we can safely declare strlen this way. + If not using GCC, it is ok not to declare it. */ +#ifdef __GNUC__ +/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. + That was relevant to code that was here before. */ +#if !defined (__STDC__) || !__STDC__ +/* gcc with -traditional declares the built-in strlen to return int, + and has done so at least since version 2.4.5. -- rms. */ +extern int strlen(const char *); + +#endif /* not __STDC__ */ +#endif /* __GNUC__ */ + +#endif /* not __GNU_LIBRARY__ */ + +/* Handle permutation of arguments. */ + +/* Describe the part of ARGV that contains non-options that have + been skipped. `first_nonopt' is the index in ARGV of the first of them; + `last_nonopt' is the index after the last of them. */ + +static int first_nonopt; +static int last_nonopt; + +#ifdef _LIBC +/* Bash 2.0 gives us an environment variable containing flags + indicating ARGV elements that should not be considered arguments. */ + +static const char *nonoption_flags; +static int nonoption_flags_len; + +static int original_argc; +static char *const *original_argv; + +/* Make sure the environment variable bash 2.0 puts in the environment + is valid for the getopt call we must make sure that the ARGV passed + to getopt is that one passed to the process. */ +static void store_args(int argc, char *const *argv) __attribute__((unused)); + static void + store_args(int argc, char *const *argv) +{ + /* XXX This is no good solution. We should rather copy the args so + that we can compare them later. But we must not use malloc(3). */ + original_argc = argc; + original_argv = argv; +} +text_set_element(__libc_subinit, store_args); +#endif + +/* Exchange two adjacent subsequences of ARGV. + One subsequence is elements [first_nonopt,last_nonopt) + which contains all the non-options that have been skipped so far. + The other is elements [last_nonopt,optind), which contains all + the options processed since those non-options were skipped. + + `first_nonopt' and `last_nonopt' are relocated so that they describe + the new indices of the non-options in ARGV after they are moved. */ + +#if defined (__STDC__) && __STDC__ +static void exchange(char **); + +#endif + +static void + exchange(argv) + char **argv; +{ + int bottom = first_nonopt; + int middle = last_nonopt; + int top = optind; + char *tem; + + /* Exchange the shorter segment with the far end of the longer segment. + That puts the shorter segment into the right place. + It leaves the longer segment in the right place overall, + but it consists of two parts that need to be swapped next. */ + + while (top > middle && middle > bottom) + { + if (top - middle > middle - bottom) + { + /* Bottom segment is the short one. */ + int len = middle - bottom; + register int i; + + /* Swap it with the top part of the top segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[top - (middle - bottom) + i]; + argv[top - (middle - bottom) + i] = tem; + } + /* Exclude the moved bottom segment from further swapping. */ + top -= len; + } + else + { + /* Top segment is the short one. */ + int len = top - middle; + register int i; + + /* Swap it with the bottom part of the bottom segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[middle + i]; + argv[middle + i] = tem; + } + /* Exclude the moved top segment from further swapping. */ + bottom += len; + } + } + + /* Update records for the slots the non-options now occupy. */ + + first_nonopt += (optind - last_nonopt); + last_nonopt = optind; +} + +/* Initialize the internal data when the first call is made. */ + +#if defined (__STDC__) && __STDC__ +static const char *_getopt_initialize(int, char *const *, const char *); + +#endif +static const char * + _getopt_initialize(argc, argv, optstring) + int argc; + char *const *argv; + const char *optstring; +{ + /* Start processing options with ARGV-element 1 (since ARGV-element 0 + is the program name); the sequence of previously skipped + non-option ARGV-elements is empty. */ + + first_nonopt = last_nonopt = optind = 1; + + nextchar = NULL; + + posixly_correct = getenv("POSIXLY_CORRECT"); + + /* Determine how to handle the ordering of options and nonoptions. */ + + if (optstring[0] == '-') + { + ordering = RETURN_IN_ORDER; + ++optstring; + } + else if (optstring[0] == '+') + { + ordering = REQUIRE_ORDER; + ++optstring; + } + else if (posixly_correct != NULL) + ordering = REQUIRE_ORDER; + else + ordering = PERMUTE; + +#ifdef _LIBC + if (posixly_correct == NULL + && argc == original_argc && argv == original_argv) + { + /* Bash 2.0 puts a special variable in the environment for each + command it runs, specifying which ARGV elements are the results of + file name wildcard expansion and therefore should not be + considered as options. */ + char var[100]; + + sprintf(var, "_%d_GNU_nonoption_argv_flags_", getpid()); + nonoption_flags = getenv(var); + if (nonoption_flags == NULL) + nonoption_flags_len = 0; + else + nonoption_flags_len = strlen(nonoption_flags); + } + else + nonoption_flags_len = 0; +#endif + + return optstring; +} + +/* Scan elements of ARGV (whose length is ARGC) for option characters + given in OPTSTRING. + + If an element of ARGV starts with '-', and is not exactly "-" or "--", + then it is an option element. The characters of this element + (aside from the initial '-') are option characters. If `getopt' + is called repeatedly, it returns successively each of the option characters + from each of the option elements. + + If `getopt' finds another option character, it returns that character, + updating `optind' and `nextchar' so that the next call to `getopt' can + resume the scan with the following option character or ARGV-element. + + If there are no more option characters, `getopt' returns -1. + Then `optind' is the index in ARGV of the first ARGV-element + that is not an option. (The ARGV-elements have been permuted + so that those that are not options now come last.) + + OPTSTRING is a string containing the legitimate option characters. + If an option character is seen that is not listed in OPTSTRING, + return '?' after printing an error message. If you set `opterr' to + zero, the error message is suppressed but we still return '?'. + + If a char in OPTSTRING is followed by a colon, that means it wants an arg, + so the following text in the same ARGV-element, or the text of the following + ARGV-element, is returned in `optarg'. Two colons mean an option that + wants an optional arg; if there is text in the current ARGV-element, + it is returned in `optarg', otherwise `optarg' is set to zero. + + If OPTSTRING starts with `-' or `+', it requests different methods of + handling the non-option ARGV-elements. + See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. + + Long-named options begin with `--' instead of `-'. + Their names may be abbreviated as long as the abbreviation is unique + or is an exact match for some defined option. If they have an + argument, it follows the option name in the same ARGV-element, separated + from the option name by a `=', or else the in next ARGV-element. + When `getopt' finds a long-named option, it returns 0 if that option's + `flag' field is nonzero, the value of the option's `val' field + if the `flag' field is zero. + + The elements of ARGV aren't really const, because we permute them. + But we pretend they're const in the prototype to be compatible + with other systems. + + LONGOPTS is a vector of `struct option' terminated by an + element containing a name which is zero. + + LONGIND returns the index in LONGOPT of the long-named option found. + It is only valid when a long-named option has been found by the most + recent call. + + If LONG_ONLY is nonzero, '-' as well as '--' can introduce + long-named options. */ + +int + _getopt_internal(argc, argv, optstring, longopts, longind, long_only) + int argc; + char *const *argv; + const char *optstring; + const struct option *longopts; + int *longind; + int long_only; +{ + optarg = NULL; + + if (!__getopt_initialized || optind == 0) + { + optstring = _getopt_initialize(argc, argv, optstring); + optind = 1; /* Don't scan ARGV[0], the program name. */ + __getopt_initialized = 1; + } + + /* Test whether ARGV[optind] points to a non-option argument. + Either it does not have option syntax, or there is an environment flag + from the shell indicating it is not an option. The later information + is only used when the used in the GNU libc. */ +#ifdef _LIBC +#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ + || (optind < nonoption_flags_len \ + && nonoption_flags[optind] == '1')) +#else +#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') +#endif + + if (nextchar == NULL || *nextchar == '\0') + { + /* Advance to the next ARGV-element. */ + + /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been + moved back by the user (who may also have changed the arguments). */ + if (last_nonopt > optind) + last_nonopt = optind; + if (first_nonopt > optind) + first_nonopt = optind; + + if (ordering == PERMUTE) + { + /* If we have just processed some options following some non-options, + exchange them so that the options come first. */ + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange((char **) argv); + else if (last_nonopt != optind) + first_nonopt = optind; + + /* Skip any additional non-options + and extend the range of non-options previously skipped. */ + + while (optind < argc && NONOPTION_P) + optind++; + last_nonopt = optind; + } + + /* The special ARGV-element `--' means premature end of options. + Skip it like a null option, + then exchange with previous non-options as if it were an option, + then skip everything else like a non-option. */ + + if (optind != argc && !strcmp(argv[optind], "--")) + { + optind++; + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange((char **) argv); + else if (first_nonopt == last_nonopt) + first_nonopt = optind; + last_nonopt = argc; + + optind = argc; + } + + /* If we have done all the ARGV-elements, stop the scan + and back over any non-options that we skipped and permuted. */ + + if (optind == argc) + { + /* Set the next-arg-index to point at the non-options + that we previously skipped, so the caller will digest them. */ + if (first_nonopt != last_nonopt) + optind = first_nonopt; + return -1; + } + + /* If we have come to a non-option and did not permute it, + either stop the scan or describe it to the caller and pass it by. */ + + if (NONOPTION_P) + { + if (ordering == REQUIRE_ORDER) + return -1; + optarg = argv[optind++]; + return 1; + } + + /* We have found another option-ARGV-element. + Skip the initial punctuation. */ + + nextchar = (argv[optind] + 1 + + (longopts != NULL && argv[optind][1] == '-')); + } + + /* Decode the current option-ARGV-element. */ + + /* Check whether the ARGV-element is a long option. + + If long_only and the ARGV-element has the form "-f", where f is + a valid short option, don't consider it an abbreviated form of + a long option that starts with f. Otherwise there would be no + way to give the -f short option. + + On the other hand, if there's a long option "fubar" and + the ARGV-element is "-fu", do consider that an abbreviation of + the long option, just like "--fu", and not "-f" with arg "u". + + This distinction seems to be the most useful approach. */ + + if (longopts != NULL + && (argv[optind][1] == '-' + || (long_only && (argv[optind][2] || !my_index(optstring, argv[optind][1]))))) + { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = -1; + int option_index; + + for (nameend = nextchar; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp(p->name, nextchar, nameend - nextchar)) + { + if ((unsigned int) (nameend - nextchar) + == (unsigned int) strlen(p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else + /* Second or later nonexact match found. */ + ambig = 1; + } + + if (ambig && !exact) + { + if (opterr) + fprintf(stderr, _("%s: option `%s' is ambiguous\n"), + argv[0], argv[optind]); + nextchar += strlen(nextchar); + optind++; + optopt = 0; + return '?'; + } + + if (pfound != NULL) + { + option_index = indfound; + optind++; + if (*nameend) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + optarg = nameend + 1; + else + { + if (opterr) + { + if (argv[optind - 1][1] == '-') + /* --option */ + fprintf(stderr, + _("%s: option `--%s' doesn't allow an argument\n"), + argv[0], pfound->name); + else + /* +option or -option */ + fprintf(stderr, + _("%s: option `%c%s' doesn't allow an argument\n"), + argv[0], argv[optind - 1][0], pfound->name); + } + + nextchar += strlen(nextchar); + + optopt = pfound->val; + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (optind < argc) + optarg = argv[optind++]; + else + { + if (opterr) + fprintf(stderr, + _("%s: option `%s' requires an argument\n"), + argv[0], argv[optind - 1]); + nextchar += strlen(nextchar); + optopt = pfound->val; + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen(nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + + /* Can't find it as a long option. If this is not getopt_long_only, + or the option starts with '--' or is not a valid short + option, then it's an error. + Otherwise interpret it as a short option. */ + if (!long_only || argv[optind][1] == '-' + || my_index(optstring, *nextchar) == NULL) + { + if (opterr) + { + if (argv[optind][1] == '-') + /* --option */ + fprintf(stderr, _("%s: unrecognized option `--%s'\n"), + argv[0], nextchar); + else + /* +option or -option */ + fprintf(stderr, _("%s: unrecognized option `%c%s'\n"), + argv[0], argv[optind][0], nextchar); + } + nextchar = (char *) ""; + optind++; + optopt = 0; + return '?'; + } + } + + /* Look at and handle the next short option-character. */ + + { + char c = *nextchar++; + char *temp = my_index(optstring, c); + + /* Increment `optind' when we start to process its last character. */ + if (*nextchar == '\0') + ++optind; + + if (temp == NULL || c == ':') + { + if (opterr) + { + if (posixly_correct) + /* 1003.2 specifies the format of this message. */ + fprintf(stderr, _("%s: illegal option -- %c\n"), + argv[0], c); + else + fprintf(stderr, _("%s: invalid option -- %c\n"), + argv[0], c); + } + optopt = c; + return '?'; + } + /* Convenience. Treat POSIX -W foo same as long option --foo */ + if (temp[0] == 'W' && temp[1] == ';') + { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = 0; + int option_index; + + /* This is an option that requires an argument. */ + if (*nextchar != '\0') + { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } + else if (optind == argc) + { + if (opterr) + { + /* 1003.2 specifies the format of this message. */ + fprintf(stderr, _("%s: option requires an argument -- %c\n"), + argv[0], c); + } + optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + return c; + } + else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + optarg = argv[optind++]; + + /* optarg is now the argument, see if it's in the + table of longopts. */ + + for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp(p->name, nextchar, nameend - nextchar)) + { + if ((unsigned int) (nameend - nextchar) == strlen(p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else + /* Second or later nonexact match found. */ + ambig = 1; + } + if (ambig && !exact) + { + if (opterr) + fprintf(stderr, _("%s: option `-W %s' is ambiguous\n"), + argv[0], argv[optind]); + nextchar += strlen(nextchar); + optind++; + return '?'; + } + if (pfound != NULL) + { + option_index = indfound; + if (*nameend) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + optarg = nameend + 1; + else + { + if (opterr) + fprintf(stderr, _("\ +%s: option `-W %s' doesn't allow an argument\n"), + argv[0], pfound->name); + + nextchar += strlen(nextchar); + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (optind < argc) + optarg = argv[optind++]; + else + { + if (opterr) + fprintf(stderr, + _("%s: option `%s' requires an argument\n"), + argv[0], argv[optind - 1]); + nextchar += strlen(nextchar); + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen(nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + nextchar = NULL; + return 'W'; /* Let the application handle it. */ + } + if (temp[1] == ':') + { + if (temp[2] == ':') + { + /* This is an option that accepts an argument optionally. */ + if (*nextchar != '\0') + { + optarg = nextchar; + optind++; + } + else + optarg = NULL; + nextchar = NULL; + } + else + { + /* This is an option that requires an argument. */ + if (*nextchar != '\0') + { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } + else if (optind == argc) + { + if (opterr) + { + /* 1003.2 specifies the format of this message. */ + fprintf(stderr, + _("%s: option requires an argument -- %c\n"), + argv[0], c); + } + optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + } + else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + optarg = argv[optind++]; + nextchar = NULL; + } + } + return c; + } +} + +int + getopt(argc, argv, optstring) + int argc; + char *const *argv; + const char *optstring; +{ + return _getopt_internal(argc, argv, optstring, + (const struct option *) 0, + (int *) 0, + 0); +} + +#endif /* Not ELIDE_CODE. */ + +#ifdef TEST + +/* Compile with -DTEST to make an executable for use in testing + the above definition of `getopt'. */ + +int + main(argc, argv) + int argc; + char **argv; +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + + c = getopt(argc, argv, "abc:d:0123456789"); + if (c == -1) + break; + + switch (c) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf("option %c\n", c); + break; + + case 'a': + printf("option a\n"); + break; + + case 'b': + printf("option b\n"); + break; + + case 'c': + printf("option c with value `%s'\n", optarg); + break; + + case '?': + break; + + default: + printf("?? getopt returned character code 0%o ??\n", c); + } + } + + if (optind < argc) + { + printf("non-option ARGV-elements: "); + while (optind < argc) + printf("%s ", argv[optind++]); + printf("\n"); + } + + exit(0); +} + +#endif /* TEST */ diff --git a/lib/libdvd/libdvdnav/msvc/contrib/timer/timer.c b/lib/libdvd/libdvdnav/msvc/contrib/timer/timer.c new file mode 100755 index 0000000000..60efe86db9 --- /dev/null +++ b/lib/libdvd/libdvdnav/msvc/contrib/timer/timer.c @@ -0,0 +1,102 @@ +/* + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * WIN32 PORT, + * by Matthew Grooms <elon@altavista.com> + * + * timer.c - Missing unix timer functions + * + */ + +#include "stdio.h" +#include "timer.h" + +/* + this function returns somewhat + accurate unix time with the data + accurate to the first call to get + of day and the resolution accurate + to ~ miliseconds. +*/ + +static time_t startseconds = 0; + +int gettimeofday( struct timeval *tp, struct timezone *tzp ) +{ + MMTIME mmtime; + + // clock() returns time in miliseconds + + if( !startseconds ) + startseconds = time( 0 ); + + timeGetSystemTime( &mmtime, sizeof( mmtime ) ); + + tp->tv_sec = ( mmtime.u.ms / 1000 ) + startseconds; + tp->tv_usec = ( mmtime.u.ms % 1000 ) * 1000; + + return 0; +}; + +/* + These functions are designed to mimick + a subset of itimer for use with the + alarm signal on win32. This is just + enough for xine to work. +*/ + +static HANDLE sigalarm = 0; + +int setitimer( int which, struct itimerval * value, struct itimerval *ovalue ) +{ + long int miliseconds; + + if( !sigalarm ) + sigalarm = CreateEvent( 0, FALSE, TRUE, "SIGALARM" ); + + miliseconds = value->it_value.tv_usec / 1000; + + timeSetEvent( miliseconds, 0, ( LPTIMECALLBACK ) sigalarm, 0, TIME_PERIODIC | TIME_CALLBACK_EVENT_PULSE ); + + return 0; +} + +/* + Wait for sigalarm to wake the thread +*/ + +int pause( void ) +{ + WaitForSingleObject( sigalarm, INFINITE ); + + return 0; +} + +int nanosleep( const struct timespec * rqtp, struct timespec * rmtp ) +{ + Sleep( rqtp->tv_nsec / 1000000 ); + + return 0; +} + +unsigned int sleep( unsigned int seconds ) +{ + Sleep( seconds * 1000 ); + return 0; +}
\ No newline at end of file diff --git a/lib/libdvd/libdvdnav/msvc/contrib/timer/timer.h b/lib/libdvd/libdvdnav/msvc/contrib/timer/timer.h new file mode 100755 index 0000000000..efab6f4e18 --- /dev/null +++ b/lib/libdvd/libdvdnav/msvc/contrib/timer/timer.h @@ -0,0 +1,39 @@ +#include <time.h> +#include <winsock.h> +#include "pthread.h" + +#ifndef _ITIMER_ +#define _ITIMER_ + +#define ITIMER_REAL 0 +#define ITIMER_VIRTUAL 1 + +// time reference +// ---------------------------------- +// +// 1,000 milliseconds / sec +// 1,000,000 microseconds / sec +// 1,000,000,000 nanoseconds / sec +// +// timeval.time_sec = seconds +// timeval.time_usec = microseconds + +struct itimerval +{ + struct timeval it_interval; /* timer interval */ + struct timeval it_value; /* current value */ +}; + +struct timezone { + int tz_minuteswest; /* minutes west of Greenwich */ + int tz_dsttime; /* type of dst correction */ +}; + +int gettimeofday( struct timeval *tp, struct timezone *tzp ); +int setitimer( int which, struct itimerval * value, struct itimerval *ovalue ); +int pause( void ); + +unsigned int sleep( unsigned int seconds ); +int nanosleep( const struct timespec *rqtp, struct timespec *rmtp ); + +#endif
\ No newline at end of file diff --git a/lib/libdvd/libdvdnav/msvc/ifo_dump.dsp b/lib/libdvd/libdvdnav/msvc/ifo_dump.dsp new file mode 100755 index 0000000000..fc39837296 --- /dev/null +++ b/lib/libdvd/libdvdnav/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 "include/pthreads" /I "install/include" /I ".." /I "../src" /I "contrib/timer" /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/lib/libdvd/libdvdnav/msvc/include/dlfcn.h b/lib/libdvd/libdvdnav/msvc/include/dlfcn.h new file mode 100755 index 0000000000..7a2416c843 --- /dev/null +++ b/lib/libdvd/libdvdnav/msvc/include/dlfcn.h @@ -0,0 +1,23 @@ +#ifndef __DLFCN_H__ +# define __DLFCN_H__ +/* + * $Id: dlfcn.h 1135 2008-09-06 21:55:51Z rathann $ + * $Name$ + * + * + */ +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/lib/libdvd/libdvdnav/msvc/include/dvdnav_internal.h b/lib/libdvd/libdvdnav/msvc/include/dvdnav_internal.h new file mode 100644 index 0000000000..cee785472e --- /dev/null +++ b/lib/libdvd/libdvdnav/msvc/include/dvdnav_internal.h @@ -0,0 +1,185 @@ +/* !! DO NO EDIT THIS FILE, it is automatically generated */ +/* + * Copyright (C) 2001 Rich Wareham <richwareham@users.sourceforge.net> + * + * This file is part of libdvdnav, a DVD navigation library. + * + * libdvdnav 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. + * + * libdvdnav 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 + * + * $Id: dvdnav_internal.h 1135 2008-09-06 21:55:51Z rathann $ + * + */ + +#ifndef DVDNAV_INTERNAL_H_INCLUDED +#define DVDNAV_INTERNAL_H_INCLUDED + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <limits.h> +#include <string.h> +#include <pthread.h> + +#undef WORDS_BIGENDIAN + +#include "dvd_reader.h" +#include "ifo_read.h" +#include "ifo_types.h" + +/* Uncomment for VM command tracing */ +/* #define TRACE */ + +#include "decoder.h" +#include "dvdnav.h" +#include "vm.h" +#include "vmcmd.h" + +/* where should libdvdnav write its messages (stdout/stderr) */ +#define MSG_OUT stdout + +/* Maximum length of an error string */ +#define MAX_ERR_LEN 255 + +/* Use the POSIX PATH_MAX if available */ +#ifdef PATH_MAX +#define MAX_PATH_LEN PATH_MAX +#else +#define MAX_PATH_LEN 255 /* Arbitrary */ +#endif + +#ifndef DVD_VIDEO_LB_LEN +#define DVD_VIDEO_LB_LEN 2048 +#endif + +typedef struct read_cache_s read_cache_t; + +/* + * These are defined here because they are + * not in ifo_types.h, they maybe one day + */ + +#ifndef audio_status_t +typedef struct { +#ifdef WORDS_BIGENDIAN + unsigned int available : 1; + unsigned int zero1 : 4; + unsigned int stream_number : 3; + uint8_t zero2; +#else + uint8_t zero2; + unsigned int stream_number : 3; + unsigned int zero1 : 4; + unsigned int available : 1; +#endif +} ATTRIBUTE_PACKED audio_status_t; +#endif + +#ifndef spu_status_t +typedef struct { +#ifdef WORDS_BIGENDIAN + unsigned int available : 1; + unsigned int zero1 : 2; + unsigned int stream_number_4_3 : 5; + unsigned int zero2 : 3; + unsigned int stream_number_wide : 5; + unsigned int zero3 : 3; + unsigned int stream_number_letterbox : 5; + unsigned int zero4 : 3; + unsigned int stream_number_pan_scan : 5; +#else + unsigned int stream_number_pan_scan : 5; + unsigned int zero4 : 3; + unsigned int stream_number_letterbox : 5; + unsigned int zero3 : 3; + unsigned int stream_number_wide : 5; + unsigned int zero2 : 3; + unsigned int stream_number_4_3 : 5; + unsigned int zero1 : 2; + unsigned int available : 1; +#endif +} ATTRIBUTE_PACKED spu_status_t; +#endif + +typedef struct dvdnav_vobu_s { + int32_t vobu_start; /* Logical Absolute. MAX needed is 0x300000 */ + int32_t vobu_length; + int32_t blockN; /* Relative offset */ + int32_t vobu_next; /* Relative offset */ +} dvdnav_vobu_t; + +/** The main DVDNAV type **/ + +struct dvdnav_s { + /* General data */ + char path[MAX_PATH_LEN]; /* Path to DVD device/dir */ + dvd_file_t *file; /* Currently opened file */ + int open_vtsN; /* The domain and number of the... */ + int open_domain; /* ..currently opened VOB */ + + /* Position data */ + vm_position_t position_next; + vm_position_t position_current; + dvdnav_vobu_t vobu; + + /* NAV data */ + pci_t pci; + dsi_t dsi; + uint32_t last_cmd_nav_lbn; /* detects when a command is issued on an already left NAV */ + + /* Flags */ + int skip_still; /* Set when skipping a still */ + int sync_wait; /* applications should wait till they are in sync with us */ + int sync_wait_skip; /* Set when skipping wait state */ + int spu_clut_changed; /* The SPU CLUT changed */ + int started; /* vm_start has been called? */ + int use_read_ahead; /* 1 - use read-ahead cache, 0 - don't */ + int pgc_based; /* positioning works PGC based instead of PG based */ + + /* VM */ + vm_t *vm; + pthread_mutex_t vm_lock; + + /* Read-ahead cache */ + read_cache_t *cache; + + /* Errors */ + char err_str[MAX_ERR_LEN]; +}; + +/** USEFUL MACROS **/ + +#ifdef __GNUC__ +#define printerrf(format, args...) snprintf(this->err_str, MAX_ERR_LEN, format, ## args); +#else +#ifdef _MSC_VER +#define printerrf(str) snprintf(this->err_str, MAX_ERR_LEN, str); +#else +#define printerrf(...) snprintf(this->err_str, MAX_ERR_LEN, __VA_ARGS__); +#endif /* WIN32 */ +#endif +#define printerr(str) strncpy(this->err_str, str, MAX_ERR_LEN); + +/* Save my typing */ +#define S_ERR DVDNAV_STATUS_ERR + +#ifndef _MSC_VER +#define S_OK DVDNAV_STATUS_OK +#endif /* MSC_VER */ + +#endif /* DVDNAV_INTERNAL_H_INCLUDED */ diff --git a/lib/libdvd/libdvdnav/msvc/include/getopt.h b/lib/libdvd/libdvdnav/msvc/include/getopt.h new file mode 100755 index 0000000000..2fa12f7baf --- /dev/null +++ b/lib/libdvd/libdvdnav/msvc/include/getopt.h @@ -0,0 +1,134 @@ +/* Declarations for getopt. + Copyright (C) 1989,90,91,92,93,94,96,97 Free Software Foundation, Inc. + + This file is part of the GNU C Library. Its master source is NOT part of + the C library, however. The master source lives in /gd/gnu/lib. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _GETOPT_H +#define _GETOPT_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + + extern char *optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + + extern int optind; + +/* Callers store zero here to inhibit the error message `getopt' prints + for unrecognized options. */ + + extern int opterr; + +/* Set to an option character which was unrecognized. */ + + extern int optopt; + +/* Describe the long-named options requested by the application. + The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector + of `struct option' terminated by an element containing a name which is + zero. + + The field `has_arg' is: + no_argument (or 0) if the option does not take an argument, + required_argument (or 1) if the option requires an argument, + optional_argument (or 2) if the option takes an optional argument. + + If the field `flag' is not NULL, it points to a variable that is set + to the value given in the field `val' when the option is found, but + left unchanged if the option is not found. + + To have a long-named option do something other than set an `int' to + a compiled-in constant, such as set a value from `optarg', set the + option's `flag' field to zero and its `val' field to a nonzero + value (the equivalent single-letter option character, if there is + one). For long options that have a zero `flag' field, `getopt' + returns the contents of the `val' field. */ + + struct option + { +#if defined (__STDC__) && __STDC__ + const char *name; +#else + char *name; +#endif + /* has_arg can't be an enum because some compilers complain about + type mismatches in all the code that assumes it is an int. */ + int has_arg; + int *flag; + int val; + }; + +/* Names for the values of the `has_arg' field of `struct option'. */ + +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +#if defined (__STDC__) && __STDC__ +#ifdef __GNU_LIBRARY__ +/* Many other libraries have conflicting prototypes for getopt, with + differences in the consts, in stdlib.h. To avoid compilation + errors, only prototype getopt for the GNU C library. */ + extern int getopt(int argc, char *const *argv, const char *shortopts); +#else /* not __GNU_LIBRARY__ */ + extern int getopt(); +#endif /* __GNU_LIBRARY__ */ + extern int getopt_long(int argc, char *const *argv, const char *shortopts, + const struct option *longopts, int *longind); + extern int getopt_long_only(int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind); + +/* Internal only. Users should not call this directly. */ + extern int _getopt_internal(int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind, + int long_only); +#else /* not __STDC__ */ + extern int getopt(); + extern int getopt_long(); + extern int getopt_long_only(); + + extern int _getopt_internal(); +#endif /* __STDC__ */ + +#ifdef __cplusplus +} +#endif + +#endif /* _GETOPT_H */ diff --git a/lib/libdvd/libdvdnav/msvc/include/inttypes.h b/lib/libdvd/libdvdnav/msvc/include/inttypes.h new file mode 100755 index 0000000000..55fd6a33e0 --- /dev/null +++ b/lib/libdvd/libdvdnav/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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * WIN32 PORT, + * by Matthew Grooms <elon@altavista.com> + * + * inttypes.h - Standard integer definitions. + * + */ + +#ifndef _SYS_INTTYPES_H_ +#define _SYS_INTTYPES_H_ + +#include <config.h> + +#endif diff --git a/lib/libdvd/libdvdnav/msvc/include/os_types.h b/lib/libdvd/libdvdnav/msvc/include/os_types.h new file mode 100755 index 0000000000..69f05a8d93 --- /dev/null +++ b/lib/libdvd/libdvdnav/msvc/include/os_types.h @@ -0,0 +1,27 @@ +#ifndef __OS_TYPES_H__ +#define __OS_TYPES_H__ +/* + * $Id: os_types.h 1135 2008-09-06 21:55:51Z rathann $ + * $Name$ + * + * 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/lib/libdvd/libdvdnav/msvc/include/pthreads/pthread.h b/lib/libdvd/libdvdnav/msvc/include/pthreads/pthread.h new file mode 100755 index 0000000000..7b89ca8401 --- /dev/null +++ b/lib/libdvd/libdvdnav/msvc/include/pthreads/pthread.h @@ -0,0 +1,1077 @@ +/* This is the POSIX thread API (POSIX 1003). + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright (C) 1998 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA + */ + +#if !defined( PTHREAD_H ) +#define PTHREAD_H + +#ifdef _UWIN +# define HAVE_STRUCT_TIMESPEC 1 +# define HAVE_SIGNAL_H 1 +# undef HAVE_CONFIG_H +# pragma comment(lib, "pthread") +#endif + +/* + * ------------------------------------------------------------- + * + * + * Module: pthread.h + * + * Purpose: + * Provides an implementation of PThreads based upon the + * standard: + * + * POSIX 1003.1c-1995 (POSIX.1c) + * + * Parts of the implementation also comply with the + * Open Group Unix 98 specification in order to enhance + * code portability between Windows, various commercial + * Unix implementations, and Linux. + * + * Authors: + * There have been many contributors to this library. + * The initial implementation was contributed by + * John Bossom, and several others have provided major + * sections or revisions of parts of the implementation. + * Often significant effort has been contributed to + * find and fix important bugs and other problems to + * improve the reliability of the library, which sometimes + * is not reflected in the amount of code which changed as + * result. + * As much as possible, the contributors are acknowledged + * in the ChangeLog file in the source code distribution + * where their changes are noted in detail. + * + * Contributors are listed in the MAINTAINERS file. + * + * As usual, all bouquets go to the contributors, and all + * brickbats go to the project maintainer. + * + * Maintainer: + * The code base for this project is coordinated and + * eventually pre-tested, packaged, and made available by + * + * Ross Johnson <rpj@ise.canberra.edu.au> + * + * QA Testers: + * Ultimately, the library is tested in the real world by + * a host of competent and demanding scientists and + * engineers who report bugs and/or provide solutions + * which are then fixed or incorporated into subsequent + * versions of the library. Each time a bug is fixed, a + * test case is written to prove the fix and ensure + * that later changes to the code don't reintroduce the + * same error. The number of test cases is slowly growing + * and therefore so is the code reliability. + * + * Compliance: + * See the file ANNOUNCE for the list of implemented + * and not-implemented routines and defined options. + * Of course, these are all defined is this file as well. + * + * Web site: + * The source code and other information about this library + * are available from + * + * http://sources.redhat.com/pthreads-win32/ + * + * ------------------------------------------------------------- + */ + +/* + * ----------------- + * autoconf switches + * ----------------- + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include <windows.h> + +#ifndef NEED_FTIME +#include <time.h> +#else /* NEED_FTIME */ +/* use native WIN32 time API */ +#endif /* NEED_FTIME */ + +#if HAVE_SIGNAL_H +#include <signal.h> +#endif /* HAVE_SIGNAL_H */ + +#include <setjmp.h> + +#ifndef HAVE_STRUCT_TIMESPEC +struct timespec { + long tv_sec; + long tv_nsec; +}; +#endif /* HAVE_STRUCT_TIMESPEC */ + +#ifndef SIG_BLOCK +#define SIG_BLOCK 0 +#endif /* SIG_BLOCK */ + +#ifndef SIG_UNBLOCK +#define SIG_UNBLOCK 1 +#endif /* SIG_UNBLOCK */ + +#ifndef SIG_SETMASK +#define SIG_SETMASK 2 +#endif /* SIG_SETMASK */ + +/* + * note: ETIMEDOUT is correctly defined in winsock.h + */ +#include <winsock.h> + +#ifdef NEED_ERRNO +# include "need_errno.h" +#else +# include <errno.h> +#endif + +#include <sched.h> + +/* + * In case ETIMEDOUT hasn't been defined above somehow. + */ +#ifndef ETIMEDOUT +# define ETIMEDOUT 10060 /* This is the value in winsock.h. */ +#endif + +/* + * Several systems don't define ENOTSUP. If not, we use + * the same value as Solaris. + */ +#ifndef ENOTSUP +# define ENOTSUP 48 +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* + * ------------------------------------------------------------- + * + * POSIX 1003.1c-1995 Options + * =========================== + * + * _POSIX_THREADS (set) + * If set, you can use threads + * + * _POSIX_THREAD_ATTR_STACKSIZE (set) + * If set, you can control the size of a thread's + * stack + * pthread_attr_getstacksize + * pthread_attr_setstacksize + * + * _POSIX_THREAD_ATTR_STACKADDR (not set) + * If set, you can allocate and control a thread's + * stack. If not supported, the following functions + * will return ENOSYS, indicating they are not + * supported: + * pthread_attr_getstackaddr + * pthread_attr_setstackaddr + * + * _POSIX_THREAD_PRIORITY_SCHEDULING (set) + * If set, you can use realtime scheduling. + * Indicates the availability of: + * pthread_attr_getinheritsched + * pthread_attr_getschedparam + * pthread_attr_getschedpolicy + * pthread_attr_getscope + * pthread_attr_setinheritsched + * pthread_attr_setschedparam + * pthread_attr_setschedpolicy + * pthread_attr_setscope + * pthread_getschedparam + * pthread_setschedparam + * sched_get_priority_max + * sched_get_priority_min + * sched_rr_set_interval + * + * _POSIX_THREAD_PRIO_INHERIT (not set) + * If set, you can create priority inheritance + * mutexes. + * pthread_mutexattr_getprotocol + + * pthread_mutexattr_setprotocol + + * + * _POSIX_THREAD_PRIO_PROTECT (not set) + * If set, you can create priority ceiling mutexes + * Indicates the availability of: + * pthread_mutex_getprioceiling + * pthread_mutex_setprioceiling + * pthread_mutexattr_getprioceiling + * pthread_mutexattr_getprotocol + + * pthread_mutexattr_setprioceiling + * pthread_mutexattr_setprotocol + + * + * _POSIX_THREAD_PROCESS_SHARED (not set) + * If set, you can create mutexes and condition + * variables that can be shared with another + * process.If set, indicates the availability + * of: + * pthread_mutexattr_getpshared + * pthread_mutexattr_setpshared + * pthread_condattr_getpshared + * pthread_condattr_setpshared + * + * _POSIX_THREAD_SAFE_FUNCTIONS (set) + * If set you can use the special *_r library + * functions that provide thread-safe behaviour + * + * + These functions provide both 'inherit' and/or + * 'protect' protocol, based upon these macro + * settings. + * + * POSIX 1003.1c-1995 Limits + * =========================== + * + * PTHREAD_DESTRUCTOR_ITERATIONS + * Maximum number of attempts to destroy + * a thread's thread-specific data on + * termination (must be at least 4) + * + * PTHREAD_KEYS_MAX + * Maximum number of thread-specific data keys + * available per process (must be at least 128) + * + * PTHREAD_STACK_MIN + * Minimum supported stack size for a thread + * + * PTHREAD_THREADS_MAX + * Maximum number of threads supported per + * process (must be at least 64). + * + * + * POSIX 1003.1j/D10-1999 Options + * ============================== + * + * _POSIX_READER_WRITER_LOCKS (set) + * If set, you can use read/write locks + * + * _POSIX_SPIN_LOCKS (set) + * If set, you can use spin locks + * + * _POSIX_BARRIERS (set) + * If set, you can use barriers + * + * ------------------------------------------------------------- + */ + +/* + * POSIX Options + */ +#ifndef _POSIX_THREADS +#define _POSIX_THREADS +#endif + +#ifndef _POSIX_READER_WRITER_LOCKS +#define _POSIX_READER_WRITER_LOCKS +#endif + +#ifndef _POSIX_SPIN_LOCKS +#define _POSIX_SPIN_LOCKS +#endif + +#ifndef _POSIX_BARRIERS +#define _POSIX_BARRIERS +#endif + +#define _POSIX_THREAD_SAFE_FUNCTIONS +#define _POSIX_THREAD_ATTR_STACKSIZE +#define _POSIX_THREAD_PRIORITY_SCHEDULING + +#if defined( KLUDGE ) +/* + * The following are not supported + */ +#define _POSIX_THREAD_ATTR_STACKADDR +#define _POSIX_THREAD_PRIO_INHERIT +#define _POSIX_THREAD_PRIO_PROTECT +#define _POSIX_THREAD_PROCESS_SHARED + +#endif /* KLUDGE */ + +/* + * POSIX Limits + * + * PTHREAD_DESTRUCTOR_ITERATIONS + * Standard states this must be at least + * 4. + * + * PTHREAD_KEYS_MAX + * WIN32 permits only 64 TLS keys per process. + * This limitation could be worked around by + * simply simulating keys. + * + * PTHREADS_STACK_MIN + * POSIX specifies 0 which is also the value WIN32 + * interprets as allowing the system to + * set the size to that of the main thread. The + * maximum stack size in Win32 is 1Meg. WIN32 + * allocates more stack as required up to the 1Meg + * limit. + * + * PTHREAD_THREADS_MAX + * Not documented by WIN32. Wrote a test program + * that kept creating threads until it failed + * revealed this approximate number. + * + */ +#define PTHREAD_DESTRUCTOR_ITERATIONS 4 +#define PTHREAD_KEYS_MAX 64 +#define PTHREAD_STACK_MIN 0 +#define PTHREAD_THREADS_MAX 2019 + + +#ifdef _UWIN +# include <sys/types.h> +#else +typedef struct pthread_t_ *pthread_t; +typedef struct pthread_attr_t_ *pthread_attr_t; +typedef struct pthread_once_t_ pthread_once_t; +typedef struct pthread_key_t_ *pthread_key_t; +typedef struct pthread_mutex_t_ *pthread_mutex_t; +typedef struct pthread_mutexattr_t_ *pthread_mutexattr_t; +typedef struct pthread_cond_t_ *pthread_cond_t; +typedef struct pthread_condattr_t_ *pthread_condattr_t; +#endif +typedef struct pthread_rwlock_t_ *pthread_rwlock_t; +typedef struct pthread_rwlockattr_t_ *pthread_rwlockattr_t; +typedef struct pthread_spinlock_t_ *pthread_spinlock_t; +typedef struct pthread_barrier_t_ *pthread_barrier_t; +typedef struct pthread_barrierattr_t_ *pthread_barrierattr_t; + +/* + * ==================== + * ==================== + * POSIX Threads + * ==================== + * ==================== + */ + +enum { +/* + * pthread_attr_{get,set}detachstate + */ + PTHREAD_CREATE_JOINABLE = 0, /* Default */ + PTHREAD_CREATE_DETACHED = 1, + +/* + * pthread_attr_{get,set}inheritsched + */ + PTHREAD_INHERIT_SCHED = 0, + PTHREAD_EXPLICIT_SCHED = 1, /* Default */ + +/* + * pthread_{get,set}scope + */ + PTHREAD_SCOPE_PROCESS = 0, + PTHREAD_SCOPE_SYSTEM = 1, /* Default */ + +/* + * pthread_setcancelstate paramters + */ + PTHREAD_CANCEL_ENABLE = 0, /* Default */ + PTHREAD_CANCEL_DISABLE = 1, + +/* + * pthread_setcanceltype parameters + */ + PTHREAD_CANCEL_ASYNCHRONOUS = 0, + PTHREAD_CANCEL_DEFERRED = 1, /* Default */ + +/* + * pthread_mutexattr_{get,set}pshared + * pthread_condattr_{get,set}pshared + */ + PTHREAD_PROCESS_PRIVATE = 0, + PTHREAD_PROCESS_SHARED = 1, + +/* + * pthread_barrier_wait + */ + PTHREAD_BARRIER_SERIAL_THREAD = -1 +}; + +/* + * ==================== + * ==================== + * Cancelation + * ==================== + * ==================== + */ +#define PTHREAD_CANCELED ((void *) -1) + + +/* + * ==================== + * ==================== + * Once Key + * ==================== + * ==================== + */ +#define PTHREAD_ONCE_INIT { FALSE, -1 } + +struct pthread_once_t_ +{ + int done; /* indicates if user function executed */ + long started; /* First thread to increment this value */ + /* to zero executes the user function */ +}; + + +/* + * ==================== + * ==================== + * Object initialisers + * ==================== + * ==================== + */ +#define PTHREAD_MUTEX_INITIALIZER ((pthread_mutex_t) -1) + +#define PTHREAD_COND_INITIALIZER ((pthread_cond_t) -1) + +#define PTHREAD_RWLOCK_INITIALIZER ((pthread_rwlock_t) -1) + +#define PTHREAD_SPINLOCK_INITIALIZER ((pthread_spinlock_t) -1) + +enum +{ + PTHREAD_MUTEX_FAST_NP, + PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_FAST_NP, + PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL +}; + + +/* There are three implementations of cancel cleanup. + * Note that pthread.h is included in both application + * compilation units and also internally for the library. + * The code here and within the library aims to work + * for all reasonable combinations of environments. + * + * The three implementations are: + * + * WIN32 SEH + * C + * C++ + * + * Please note that exiting a push/pop block via + * "return", "exit", "break", or "continue" will + * lead to different behaviour amongst applications + * depending upon whether the library was built + * using SEH, C++, or C. For example, a library built + * with SEH will call the cleanup routine, while both + * C++ and C built versions will not. + */ + +/* + * define defaults for cleanup code + */ +#if !defined( __CLEANUP_SEH ) && !defined( __CLEANUP_CXX ) && !defined( __CLEANUP_C ) + +#if defined(_MSC_VER) +#define __CLEANUP_SEH +#elif defined(__cplusplus) +#define __CLEANUP_CXX +#else +#define __CLEANUP_C +#endif + +#endif + +#if defined( __CLEANUP_SEH ) && defined(__GNUC__) +#error ERROR [__FILE__, line __LINE__]: GNUC does not support SEH. +#endif + +typedef struct ptw32_cleanup_t ptw32_cleanup_t; +typedef void (__cdecl *ptw32_cleanup_callback_t)(void *); + +struct ptw32_cleanup_t +{ + ptw32_cleanup_callback_t routine; + void *arg; + struct ptw32_cleanup_t *prev; +}; + +#ifdef __CLEANUP_SEH + /* + * WIN32 SEH version of cancel cleanup. + */ + +#define pthread_cleanup_push( _rout, _arg ) \ + { \ + ptw32_cleanup_t _cleanup; \ + \ + _cleanup.routine = (ptw32_cleanup_callback_t)(_rout); \ + _cleanup.arg = (_arg); \ + __try \ + { \ + +#define pthread_cleanup_pop( _execute ) \ + } \ + __finally \ + { \ + if( _execute || AbnormalTermination()) \ + { \ + (*(_cleanup.routine))( _cleanup.arg ); \ + } \ + } \ + } + +#else /* __CLEANUP_SEH */ + +#ifdef __CLEANUP_C + + /* + * C implementation of PThreads cancel cleanup + */ + +#define pthread_cleanup_push( _rout, _arg ) \ + { \ + ptw32_cleanup_t _cleanup; \ + \ + ptw32_push_cleanup( &_cleanup, (ptw32_cleanup_callback_t) (_rout), (_arg) ); \ + +#define pthread_cleanup_pop( _execute ) \ + (void) ptw32_pop_cleanup( _execute ); \ + } + +#else /* __CLEANUP_C */ + +#ifdef __CLEANUP_CXX + + /* + * C++ version of cancel cleanup. + * - John E. Bossom. + */ + + class PThreadCleanup { + /* + * PThreadCleanup + * + * Purpose + * This class is a C++ helper class that is + * used to implement pthread_cleanup_push/ + * pthread_cleanup_pop. + * The destructor of this class automatically + * pops the pushed cleanup routine regardless + * of how the code exits the scope + * (i.e. such as by an exception) + */ + ptw32_cleanup_callback_t cleanUpRout; + void * obj; + int executeIt; + + public: + PThreadCleanup() : + cleanUpRout( NULL ), + obj( NULL ), + executeIt( 0 ) + /* + * No cleanup performed + */ + { + } + + PThreadCleanup( + ptw32_cleanup_callback_t routine, + void * arg ) : + cleanUpRout( routine ), + obj( arg ), + executeIt( 1 ) + /* + * Registers a cleanup routine for 'arg' + */ + { + } + + ~PThreadCleanup() + { + if ( executeIt && ((void *) cleanUpRout != NULL) ) + { + (void) (*cleanUpRout)( obj ); + } + } + + void execute( int exec ) + { + executeIt = exec; + } + }; + + /* + * C++ implementation of PThreads cancel cleanup; + * This implementation takes advantage of a helper + * class who's destructor automatically calls the + * cleanup routine if we exit our scope weirdly + */ +#define pthread_cleanup_push( _rout, _arg ) \ + { \ + PThreadCleanup cleanup((ptw32_cleanup_callback_t)(_rout), \ + (void *) (_arg) ); + +#define pthread_cleanup_pop( _execute ) \ + cleanup.execute( _execute ); \ + } + +#else + +#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined. + +#endif /* __CLEANUP_CXX */ + +#endif /* __CLEANUP_C */ + +#endif /* __CLEANUP_SEH */ + +/* + * =============== + * =============== + * Methods + * =============== + * =============== + */ + +/* + * PThread Attribute Functions + */ +int pthread_attr_init (pthread_attr_t * attr); + +int pthread_attr_destroy (pthread_attr_t * attr); + +int pthread_attr_getdetachstate (const pthread_attr_t * attr, + int *detachstate); + +int pthread_attr_getstackaddr (const pthread_attr_t * attr, + void **stackaddr); + +int pthread_attr_getstacksize (const pthread_attr_t * attr, + size_t * stacksize); + +int pthread_attr_setdetachstate (pthread_attr_t * attr, + int detachstate); + +int pthread_attr_setstackaddr (pthread_attr_t * attr, + void *stackaddr); + +int pthread_attr_setstacksize (pthread_attr_t * attr, + size_t stacksize); + +int pthread_attr_getschedparam (const pthread_attr_t *attr, + struct sched_param *param); + +int pthread_attr_setschedparam (pthread_attr_t *attr, + const struct sched_param *param); + +int pthread_attr_setschedpolicy (pthread_attr_t *, + int); + +int pthread_attr_getschedpolicy (pthread_attr_t *, + int *); + +int pthread_attr_setinheritsched(pthread_attr_t * attr, + int inheritsched); + +int pthread_attr_getinheritsched(pthread_attr_t * attr, + int * inheritsched); + +int pthread_attr_setscope (pthread_attr_t *, + int); + +int pthread_attr_getscope (const pthread_attr_t *, + int *); + +/* + * PThread Functions + */ +int pthread_create (pthread_t * tid, + const pthread_attr_t * attr, + void *(*start) (void *), + void *arg); + +int pthread_detach (pthread_t tid); + +int pthread_equal (pthread_t t1, + pthread_t t2); + +void pthread_exit (void *value_ptr); + +int pthread_join (pthread_t thread, + void **value_ptr); + +pthread_t pthread_self (void); + +int pthread_cancel (pthread_t thread); + +int pthread_setcancelstate (int state, + int *oldstate); + +int pthread_setcanceltype (int type, + int *oldtype); + +void pthread_testcancel (void); + +int pthread_once (pthread_once_t * once_control, + void (*init_routine) (void)); + +ptw32_cleanup_t *ptw32_pop_cleanup (int execute); + +void ptw32_push_cleanup (ptw32_cleanup_t * cleanup, + void (*routine) (void *), + void *arg); + +/* + * Thread Specific Data Functions + */ +int pthread_key_create (pthread_key_t * key, + void (*destructor) (void *)); + +int pthread_key_delete (pthread_key_t key); + +int pthread_setspecific (pthread_key_t key, + const void *value); + +void *pthread_getspecific (pthread_key_t key); + + +/* + * Mutex Attribute Functions + */ +int pthread_mutexattr_init (pthread_mutexattr_t * attr); + +int pthread_mutexattr_destroy (pthread_mutexattr_t * attr); + +int pthread_mutexattr_getpshared (const pthread_mutexattr_t + * attr, + int *pshared); + +int pthread_mutexattr_setpshared (pthread_mutexattr_t * attr, + int pshared); + +int pthread_mutexattr_settype (pthread_mutexattr_t * attr, int kind); +int pthread_mutexattr_gettype (pthread_mutexattr_t * attr, int *kind); + +/* + * Barrier Attribute Functions + */ +int pthread_barrierattr_init (pthread_barrierattr_t * attr); + +int pthread_barrierattr_destroy (pthread_barrierattr_t * attr); + +int pthread_barrierattr_getpshared (const pthread_barrierattr_t + * attr, + int *pshared); + +int pthread_barrierattr_setpshared (pthread_barrierattr_t * attr, + int pshared); + +/* + * Mutex Functions + */ +int pthread_mutex_init (pthread_mutex_t * mutex, + const pthread_mutexattr_t * attr); + +int pthread_mutex_destroy (pthread_mutex_t * mutex); + +int pthread_mutex_lock (pthread_mutex_t * mutex); + +int pthread_mutex_trylock (pthread_mutex_t * mutex); + +int pthread_mutex_unlock (pthread_mutex_t * mutex); + +/* + * Spinlock Functions + */ +int pthread_spin_init (pthread_spinlock_t * lock, int pshared); + +int pthread_spin_destroy (pthread_spinlock_t * lock); + +int pthread_spin_lock (pthread_spinlock_t * lock); + +int pthread_spin_trylock (pthread_spinlock_t * lock); + +int pthread_spin_unlock (pthread_spinlock_t * lock); + +/* + * Barrier Functions + */ +int pthread_barrier_init (pthread_barrier_t * barrier, + const pthread_barrierattr_t * attr, + unsigned int count); + +int pthread_barrier_destroy (pthread_barrier_t * barrier); + +int pthread_barrier_wait (pthread_barrier_t * barrier); + +/* + * Condition Variable Attribute Functions + */ +int pthread_condattr_init (pthread_condattr_t * attr); + +int pthread_condattr_destroy (pthread_condattr_t * attr); + +int pthread_condattr_getpshared (const pthread_condattr_t * attr, + int *pshared); + +int pthread_condattr_setpshared (pthread_condattr_t * attr, + int pshared); + +/* + * Condition Variable Functions + */ +int pthread_cond_init (pthread_cond_t * cond, + const pthread_condattr_t * attr); + +int pthread_cond_destroy (pthread_cond_t * cond); + +int pthread_cond_wait (pthread_cond_t * cond, + pthread_mutex_t * mutex); + +int pthread_cond_timedwait (pthread_cond_t * cond, + pthread_mutex_t * mutex, + const struct timespec *abstime); + +int pthread_cond_signal (pthread_cond_t * cond); + +int pthread_cond_broadcast (pthread_cond_t * cond); + +/* + * Scheduling + */ +int pthread_setschedparam (pthread_t thread, + int policy, + const struct sched_param *param); + +int pthread_getschedparam (pthread_t thread, + int *policy, + struct sched_param *param); + +int pthread_setconcurrency (int); + +int pthread_getconcurrency (void); + +/* + * Read-Write Lock Functions + */ +int pthread_rwlock_init(pthread_rwlock_t *lock, + const pthread_rwlockattr_t *attr); + +int pthread_rwlock_destroy(pthread_rwlock_t *lock); + +int pthread_rwlock_tryrdlock(pthread_rwlock_t *); + +int pthread_rwlock_trywrlock(pthread_rwlock_t *); + +int pthread_rwlock_rdlock(pthread_rwlock_t *lock); + +int pthread_rwlock_wrlock(pthread_rwlock_t *lock); + +int pthread_rwlock_unlock(pthread_rwlock_t *lock); + + +/* + * Non-portable functions + */ + +/* + * Compatibility with Linux. + */ +int pthread_mutexattr_setkind_np(pthread_mutexattr_t * attr, int kind); +int pthread_mutexattr_getkind_np(pthread_mutexattr_t * attr, int *kind); + +/* + * Possibly supported by other POSIX threads implementations + */ +int pthread_delay_np (struct timespec * interval); + +/* + * Returns the Win32 HANDLE for the POSIX thread. + */ +HANDLE pthread_getw32threadhandle_np(pthread_t thread); + +/* + * Returns the number of CPUs available to the process. + */ +int pthread_getprocessors_np(int * count); + +/* + * Useful if an application wants to statically link + * the lib rather than load the DLL at run-time. + */ +int pthread_win32_process_attach_np(void); +int pthread_win32_process_detach_np(void); +int pthread_win32_thread_attach_np(void); +int pthread_win32_thread_detach_np(void); + + +/* + * Protected Methods + * + * This function blocks until the given WIN32 handle + * is signaled or pthread_cancel had been called. + * This function allows the caller to hook into the + * PThreads cancel mechanism. It is implemented using + * + * WaitForMultipleObjects + * + * on 'waitHandle' and a manually reset WIN32 Event + * used to implement pthread_cancel. The 'timeout' + * argument to TimedWait is simply passed to + * WaitForMultipleObjects. + */ +int pthreadCancelableWait (HANDLE waitHandle); +int pthreadCancelableTimedWait (HANDLE waitHandle, DWORD timeout); + +/* + * Thread-Safe C Runtime Library Mappings. + */ +#ifndef _UWIN +#if 1 +#if (! defined(HAVE_ERRNO)) && (! defined(_REENTRANT)) && (! defined(_MT)) +int * _errno( void ); +#endif +#else +#if (! defined(NEED_ERRNO)) || (! defined( _REENTRANT ) && (! defined( _MT ) || ! defined( _MD ))) +#if defined(PTW32_BUILD) +__declspec( dllexport ) int * _errno( void ); +#else +int * _errno( void ); +#endif +#endif +#endif +#endif + +/* + * WIN32 C runtime library had been made thread-safe + * without affecting the user interface. Provide + * mappings from the UNIX thread-safe versions to + * the standard C runtime library calls. + * Only provide function mappings for functions that + * actually exist on WIN32. + */ + +#if !defined(__MINGW32__) +#define strtok_r( _s, _sep, _lasts ) \ + ( *(_lasts) = strtok( (_s), (_sep) ) ) +#endif /* !__MINGW32__ */ + +#define asctime_r( _tm, _buf ) \ + ( strcpy( (_buf), asctime( (_tm) ) ), \ + (_buf) ) + +#define ctime_r( _clock, _buf ) \ + ( strcpy( (_buf), ctime( (_clock) ) ), \ + (_buf) ) + +#define gmtime_r( _clock, _result ) \ + ( *(_result) = *gmtime( (_clock) ), \ + (_result) ) + +#define localtime_r( _clock, _result ) \ + ( *(_result) = *localtime( (_clock) ), \ + (_result) ) + +#define rand_r( _seed ) \ + ( _seed == _seed? rand() : rand() ) + + +#ifdef __cplusplus + +/* + * Internal exceptions + */ +class ptw32_exception {}; +class ptw32_exception_cancel : public ptw32_exception {}; +class ptw32_exception_exit : public ptw32_exception {}; + +#endif + +/* FIXME: This is only required if the library was built using SEH */ +/* + * Get internal SEH tag + */ +DWORD ptw32_get_exception_services_code(void); + +#ifndef PTW32_BUILD + +#ifdef __CLEANUP_SEH + +/* + * Redefine the SEH __except keyword to ensure that applications + * propagate our internal exceptions up to the library's internal handlers. + */ +#define __except( E ) \ + __except( ( GetExceptionCode() == ptw32_get_exception_services_code() ) \ + ? EXCEPTION_CONTINUE_SEARCH : ( E ) ) + +#endif /* __CLEANUP_SEH */ + +#ifdef __cplusplus + +/* + * Redefine the C++ catch keyword to ensure that applications + * propagate our internal exceptions up to the library's internal handlers. + */ +#ifdef _MSC_VER + /* + * WARNING: Replace any 'catch( ... )' with 'PtW32CatchAll' + * if you want Pthread-Win32 cancelation and pthread_exit to work. + */ + +#ifndef PtW32NoCatchWarn + +#pragma message("When compiling applications with MSVC++ and C++ exception handling:") +#pragma message(" Replace any 'catch( ... )' with 'PtW32CatchAll' in POSIX threads") +#pragma message(" if you want POSIX thread cancelation and pthread_exit to work.") + +#endif + +#define PtW32CatchAll \ + catch( ptw32_exception & ) { throw; } \ + catch( ... ) + +#else /* _MSC_VER */ + +#define catch( E ) \ + catch( ptw32_exception & ) { throw; } \ + catch( E ) + +#endif /* _MSC_VER */ + +#endif /* __cplusplus */ + +#endif /* ! PTW32_BUILD */ + +#ifdef __cplusplus +} /* End of extern "C" */ +#endif /* __cplusplus */ + +#endif /* PTHREAD_H */ diff --git a/lib/libdvd/libdvdnav/msvc/include/pthreads/sched.h b/lib/libdvd/libdvdnav/msvc/include/pthreads/sched.h new file mode 100755 index 0000000000..ab277920e0 --- /dev/null +++ b/lib/libdvd/libdvdnav/msvc/include/pthreads/sched.h @@ -0,0 +1,89 @@ +/* + * Module: sched.h + * + * Purpose: + * Provides an implementation of POSIX realtime extensions + * as defined in + * + * POSIX 1003.1b-1993 (POSIX.1b) + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright (C) 1998 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA + */ +#ifndef _SCHED_H +#define _SCHED_H + +#if defined(__MINGW32__) || defined(_UWIN) +/* For pid_t */ +# include <sys/types.h> +/* Required by Unix 98 */ +# include <time.h> +#else +typedef int pid_t; +#endif + +/* Thread scheduling policies */ + +enum { + SCHED_OTHER = 0, + SCHED_FIFO, + SCHED_RR, + SCHED_MIN = SCHED_OTHER, + SCHED_MAX = SCHED_RR +}; + +struct sched_param { + int sched_priority; +}; + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +int sched_yield (void); + +int sched_get_priority_min (int policy); + +int sched_get_priority_max (int policy); + +int sched_setscheduler (pid_t pid, int policy); + +int sched_getscheduler (pid_t pid); + +/* + * Note that this macro returns ENOTSUP rather than + * ENOSYS as might be expected. However, returning ENOSYS + * should mean that sched_get_priority_{min,max} are + * not implemented as well as sched_rr_get_interval. + * This is not the case, since we just don't support + * round-robin scheduling. Therefore I have chosen to + * return the same value as sched_setscheduler when + * SCHED_RR is passed to it. + */ +#define sched_rr_get_interval(_pid, _interval) \ + ( errno = ENOTSUP, (int) -1 ) + + +#ifdef __cplusplus +} /* End of extern "C" */ +#endif /* __cplusplus */ + + +#endif /* !_SCHED_H */ + diff --git a/lib/libdvd/libdvdnav/msvc/include/sys/time.h b/lib/libdvd/libdvdnav/msvc/include/sys/time.h new file mode 100755 index 0000000000..f874fa655f --- /dev/null +++ b/lib/libdvd/libdvdnav/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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * WIN32 PORT, + * by Matthew Grooms <elon@altavista.com> + * + * sys/time.h - There is no seperate sys/time.h for win32 so we simply + * include the standard time header as well as our xine + * timer functions. + */ + +#include <time.h> diff --git a/lib/libdvd/libdvdnav/msvc/include/timer.h b/lib/libdvd/libdvdnav/msvc/include/timer.h new file mode 100755 index 0000000000..efab6f4e18 --- /dev/null +++ b/lib/libdvd/libdvdnav/msvc/include/timer.h @@ -0,0 +1,39 @@ +#include <time.h> +#include <winsock.h> +#include "pthread.h" + +#ifndef _ITIMER_ +#define _ITIMER_ + +#define ITIMER_REAL 0 +#define ITIMER_VIRTUAL 1 + +// time reference +// ---------------------------------- +// +// 1,000 milliseconds / sec +// 1,000,000 microseconds / sec +// 1,000,000,000 nanoseconds / sec +// +// timeval.time_sec = seconds +// timeval.time_usec = microseconds + +struct itimerval +{ + struct timeval it_interval; /* timer interval */ + struct timeval it_value; /* current value */ +}; + +struct timezone { + int tz_minuteswest; /* minutes west of Greenwich */ + int tz_dsttime; /* type of dst correction */ +}; + +int gettimeofday( struct timeval *tp, struct timezone *tzp ); +int setitimer( int which, struct itimerval * value, struct itimerval *ovalue ); +int pause( void ); + +unsigned int sleep( unsigned int seconds ); +int nanosleep( const struct timespec *rqtp, struct timespec *rmtp ); + +#endif
\ No newline at end of file diff --git a/lib/libdvd/libdvdnav/msvc/include/unistd.h b/lib/libdvd/libdvdnav/msvc/include/unistd.h new file mode 100755 index 0000000000..7e4c63f3a5 --- /dev/null +++ b/lib/libdvd/libdvdnav/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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * WIN32 PORT, + * by Matthew Grooms <elon@altavista.com> + * + * unistd.h - This is mostly a catch all header that maps standard unix + * libc calls to the equivelent win32 functions. + * + */ + +#include <windows.h> +#include <malloc.h> +#include <errno.h> +#include <direct.h> + +#include <config.h> + +#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 dont remember why this is here +#define readlink + +#endif diff --git a/lib/libdvd/libdvdnav/msvc/install/README b/lib/libdvd/libdvdnav/msvc/install/README new file mode 100755 index 0000000000..5e6ba4ae9f --- /dev/null +++ b/lib/libdvd/libdvdnav/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/lib/libdvd/libdvdnav/msvc/libdvdcss.def b/lib/libdvd/libdvdnav/msvc/libdvdcss.def new file mode 100755 index 0000000000..0a6e2fd997 --- /dev/null +++ b/lib/libdvd/libdvdnav/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/lib/libdvd/libdvdnav/msvc/libdvdcss.dsp b/lib/libdvd/libdvdnav/msvc/libdvdcss.dsp new file mode 100755 index 0000000000..bb91b6a3eb --- /dev/null +++ b/lib/libdvd/libdvdnav/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/lib/libdvd/libdvdnav/msvc/libdvdnav.def b/lib/libdvd/libdvdnav/msvc/libdvdnav.def new file mode 100755 index 0000000000..7f633d18d2 --- /dev/null +++ b/lib/libdvd/libdvdnav/msvc/libdvdnav.def @@ -0,0 +1,82 @@ +;------------------------------------------------------------ +; 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 + +;------------------------------------------------------------ +; timer exports + +gettimeofday +setitimer +pause +sleep +nanosleep diff --git a/lib/libdvd/libdvdnav/msvc/libdvdnav.dsp b/lib/libdvd/libdvdnav/msvc/libdvdnav.dsp new file mode 100755 index 0000000000..c1dd747df1 --- /dev/null +++ b/lib/libdvd/libdvdnav/msvc/libdvdnav.dsp @@ -0,0 +1,156 @@ +# 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 "include/pthreads" /I "../../libdvdcss" /I ".." /I "../src" /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 "include/pthreads" /I "../../libdvdcss" /I "../src" /I "." /I ".." /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\dvdnav.c +# End Source File +# Begin Source File + +SOURCE=..\src\highlight.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/lib/libdvd/libdvdnav/msvc/libdvdnav.dsw b/lib/libdvd/libdvdnav/msvc/libdvdnav.dsw new file mode 100755 index 0000000000..8974efbee6 --- /dev/null +++ b/lib/libdvd/libdvdnav/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/lib/libdvd/libdvdnav/msvc/libwin32utils.def b/lib/libdvd/libdvdnav/msvc/libwin32utils.def new file mode 100755 index 0000000000..1277cc8b7b --- /dev/null +++ b/lib/libdvd/libdvdnav/msvc/libwin32utils.def @@ -0,0 +1,229 @@ +;------------------------------------------------------------ +; LIBWIN32UTILS DLL DEFINITIONS FILE + +EXPORTS + +;------------------------------------------------------------ +; dirent exports + +opendir +closedir +readdir +rewinddir + +;------------------------------------------------------------ +; pthread exports + +;pthread_atfork +pthread_attr_destroy +pthread_attr_getdetachstate +pthread_attr_getinheritsched +pthread_attr_getschedparam +pthread_attr_getschedpolicy +pthread_attr_getscope +pthread_attr_getstackaddr +pthread_attr_getstacksize +pthread_attr_init +pthread_attr_setdetachstate +pthread_attr_setinheritsched +pthread_attr_setschedparam +pthread_attr_setschedpolicy +pthread_attr_setscope +pthread_attr_setstackaddr +pthread_attr_setstacksize +pthread_cancel +; +; These two are implemented as macros in pthread.h +; +;pthread_cleanup_pop +;pthread_cleanup_push +; +pthread_condattr_destroy +pthread_condattr_getpshared +pthread_condattr_init +pthread_condattr_setpshared +pthread_cond_broadcast +pthread_cond_destroy +pthread_cond_init +pthread_cond_signal +pthread_cond_timedwait +pthread_cond_wait +pthread_create +pthread_detach +pthread_equal +pthread_exit +pthread_getconcurrency +pthread_getschedparam +pthread_getspecific +pthread_join +pthread_key_create +pthread_key_delete +;pthread_kill +pthread_mutexattr_destroy +;pthread_mutexattr_getprioceiling +;pthread_mutexattr_getprotocol +pthread_mutexattr_getpshared +pthread_mutexattr_gettype +pthread_mutexattr_init +;pthread_mutexattr_setprioceiling +;pthread_mutexattr_setprotocol +pthread_mutexattr_setpshared +pthread_mutexattr_settype +pthread_mutexattr_destroy +pthread_mutex_init +pthread_mutex_destroy +pthread_mutex_lock +pthread_mutex_trylock +pthread_mutex_unlock +pthread_once +pthread_self +pthread_setcancelstate +pthread_setcanceltype +pthread_setconcurrency +pthread_setschedparam +pthread_setspecific +;pthread_sigmask +pthread_testcancel +; +; POSIX 1.b +; +sched_get_priority_min +sched_get_priority_max +sched_getscheduler +sched_setscheduler +sched_yield +sem_init +sem_destroy +sem_trywait +sem_wait +sem_post +sem_open +sem_close +sem_unlink +sem_getvalue +; +; This next one is a macro +;sched_rr_get_interval +; +; +; Read/Write Locks +; +pthread_rwlock_init +pthread_rwlock_destroy +pthread_rwlock_tryrdlock +pthread_rwlock_trywrlock +pthread_rwlock_rdlock +pthread_rwlock_wrlock +pthread_rwlock_unlock +; +; Spin locks +; +pthread_spin_init +pthread_spin_destroy +pthread_spin_lock +pthread_spin_unlock +pthread_spin_trylock +; +; Barriers +; +pthread_barrier_init +pthread_barrier_destroy +pthread_barrier_wait +pthread_barrierattr_init +pthread_barrierattr_destroy +pthread_barrierattr_getpshared +pthread_barrierattr_setpshared +; +; Non-portable/compatibility with other implementations +; +pthread_delay_np +pthread_mutexattr_getkind_np +pthread_mutexattr_setkind_np +; +; Non-portable local implementation only +; +pthread_getw32threadhandle_np +pthread_getprocessors_np +pthreadCancelableWait +pthreadCancelableTimedWait +; +; For use when linking statically +; +pthread_win32_process_attach_np +pthread_win32_process_detach_np +pthread_win32_thread_attach_np +pthread_win32_thread_detach_np +; +; 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 + +;------------------------------------------------------------ +; timer exports + +gettimeofday +setitimer +pause +sleep +nanosleep + +;------------------------------------------------------------ +; other exports +bcopy +dlclose +dlsym +dlopen +dlerror + +optind
\ No newline at end of file diff --git a/lib/libdvd/libdvdnav/msvc/libwin32utils.dsp b/lib/libdvd/libdvdnav/msvc/libwin32utils.dsp new file mode 100755 index 0000000000..f94af8f493 --- /dev/null +++ b/lib/libdvd/libdvdnav/msvc/libwin32utils.dsp @@ -0,0 +1,136 @@ +# 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" /I "include/pthreads" /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/pthreads" /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 "Source Files ( timer )" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\contrib\timer\timer.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\bcopy.c +# End Source File +# Begin Source File + +SOURCE=.\contrib\dlfcn.c +# End Source File +# Begin Source File + +SOURCE=.\contrib\getopt.c +# End Source File +# End Group +# End Target +# End Project diff --git a/lib/libdvd/libdvdnav/msvc/play_title.dsp b/lib/libdvd/libdvdnav/msvc/play_title.dsp new file mode 100755 index 0000000000..8a3efdf587 --- /dev/null +++ b/lib/libdvd/libdvdnav/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/lib/libdvd/libdvdnav/msvc/scripts/libdvdcss_install.bat b/lib/libdvd/libdvdnav/msvc/scripts/libdvdcss_install.bat new file mode 100755 index 0000000000..84712b122b --- /dev/null +++ b/lib/libdvd/libdvdnav/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/lib/libdvd/libdvdnav/msvc/scripts/libdvdnav_install.bat b/lib/libdvd/libdvdnav/msvc/scripts/libdvdnav_install.bat new file mode 100755 index 0000000000..f49f2f2294 --- /dev/null +++ b/lib/libdvd/libdvdnav/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/lib/libdvd/libdvdnav/msvc/title_info.dsp b/lib/libdvd/libdvdnav/msvc/title_info.dsp new file mode 100755 index 0000000000..39d3768d56 --- /dev/null +++ b/lib/libdvd/libdvdnav/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/lib/libdvd/libdvdnav/src/FELLOWSHIP.map b/lib/libdvd/libdvdnav/src/FELLOWSHIP.map new file mode 100644 index 0000000000..2d0a3f03cf --- /dev/null +++ b/lib/libdvd/libdvdnav/src/FELLOWSHIP.map @@ -0,0 +1,163 @@ +# The Lord of the Rings: Fellowship of the Ring (Widescreen Theatrical Release) +domain 8, title 1, program 1, start 0x0000, end 0x1f0a # Introduction + +# history of middle earth +#domain 2, title 1, program 1, start 0x9cba, end 0xcea4 # violence/war +#domain 2, title 1, program 1, start 0xf018, end 0x1272c # violence/war +domain 2, title 1, program 1, start 0x11ff3, end 0x1272c # gore +#domain 2, title 1, program 1, start 0x173f1, end 0x185d6 # violence/death + +# hobbiton +domain 2, title 1, program 2, start 0x30373, end 0x31946 # vices/smoking +domain 2, title 1, program 2, start 0x32942, end 0x34426 # vices/smoking +domain 2, title 1, program 2, start 0x34895, end 0x34ad1 # vices/smoking +domain 2, title 1, program 2, start 0x3965c, end 0x39d7c # vices/smoking + +# bag end +domain 2, title 1, program 3, start 0x40288, end 0x412de # vices/drinking/talk +domain 2, title 1, program 3, start 0x4cfbe, end 0x4f955 # vices/smoking + +# party +domain 2, title 1, program 4, start 0x53ee0, end 0x54396 # vices/drinking +domain 2, title 1, program 4, start 0x58851, end 0x5ae3d # imitative/theft +domain 2, title 1, program 4, start 0x5cd0a, end 0x5e216 # jump + +# gandalf departs +domain 2, title 1, program 6, start 0x7f05d, end 0x7f1b3 # jump +domain 2, title 1, program 6, start 0x7f51a, end 0x834a7 # vices/smoking + +# research +domain 2, title 1, program 7, start 0x8e6e8, end 0x8e9d7 # vices/smoking + +# hobbiton +domain 2, title 1, program 8, start 0x98f49, end 0x990ba # jump +domain 2, title 1, program 8, start 0xa0ad1, end 0xa17ac # jump +domain 2, title 1, program 8, start 0xa9e32, end 0xaaa70 # violence/torture +domain 2, title 1, program 8, start 0xabc6c, end 0xabd92 # violence + +# orthanc +domain 2, title 1, program 9, start 0xd50b7, end 0xd87f9 # violence +domain 2, title 1, program 9, start 0xd8e49, end 0xda611 # violence + +# farmer maggot +domain 2, title 1, program 10, start 0xde856, end 0xdeb07 # jump +domain 2, title 1, program 10, start 0xe4cfe, end 0xe50b3 # gore/excrement +domain 2, title 1, program 10, start 0xebba3, end 0xebf93 # gore/blood +domain 2, title 1, program 10, start 0xed222, end 0xeda7e # gore/insects + +# buckleberry ferry +domain 2, title 1, program 11, start 0xf6d77, end 0xf83f8 # jump + +# prancing pony in bree +domain 2, title 1, program 12, start 0x10945e, end 0x10a2f2 # vices/drinking/rolemodel +domain 2, title 1, program 12, start 0x10c103, end 0x10c417 # vices/smoking +domain 2, title 1, program 12, start 0x10c934, end 0x10cb44 # vices/smoking +# 10c934 +# 10c9b4 +# 10ca3c +# 10cad6 +# 10cb44 +# 10cbb4 +domain 2, title 1, program 12, start 0x10ddab, end 0x10e0f2 # vices/smoking +domain 2, title 1, program 12, start 0x10e1df, end 0x10e411 # vices/drinking + +# ring wraiths in bree +domain 2, title 1, program 13, start 0x117853, end 0x117f6e # violence +domain 2, title 1, program 13, start 0x117853, end 0x117f6e # gore/crushing +domain 2, title 1, program 13, start 0x11b2b3, end 0x11bffc # violence + +# weathertop +#domain 2, title 1, program 15, start 0x13b85b, end 0x141b38 # violence +domain 2, title 1, program 15, start 0x14093a, end 0x141063 # gore/stabbing +domain 2, title 1, program 15, start 0x142555, end 0x1466e9 # violence + +# isengard +domain 2, title 1, program 16, start 0x152a28, end 0x1549fb # violence +domain 2, title 1, program 16, start 0x152a28, end 0x1549fb # gore + +# the ford +domain 2, title 1, program 17, start 0x173dbe, end 0x1748a6 # violence + +# rivendell +domain 2, title 1, program 18, start 0x179793, end 0x17a667 # vices/smoking +domain 2, title 1, program 18, start 0x17c452, end 0x17eab6 # violence + +# rivendell +domain 2, title 1, program 20, start 0x19caaf, end 0x19db12 # violence + +# tomb of isildur +domain 2, title 1, program 21, start 0x1a69ae, end 0x1a6a3d # gore/blood + +# rivendell +domain 2, title 1, program 22, start 0x1b298b, end 0x1b2bae # kiss + +# rivendell +domain 2, title 1, program 24, start 0x1d8253, end 0x1d8f5d # horror/posession + +# on the road south +domain 2, title 1, program 25, start 0x1e2fc2, end 0x1e31b8 # vices/smoking + +# at the entrance to moria +domain 2, title 1, program 27, start 0x214bdd, end 0x214fcc # gore/skeletons +domain 2, title 1, program 27, start 0x2157d9, end 0x216731 # gore/skeletons +domain 2, title 1, program 27, start 0x217ba6, end 0x21cdb4 # violence + +# moria +#domain 2, title 1, program 28, start 0x22173d, end 0x221e58 # gore/skeletons +#domain 2, title 1, program 28, start 0x222e0b, end 0x223345 # gore/skeletons +domain 2, title 1, program 28, start 0x22173d, end 0x223345 # gore/skeletons +domain 2, title 1, program 28, start 0x2239e2, end 0x223e8c # gore/skeletons +domain 2, title 1, program 28, start 0x22589f, end 0x2259bf # vices/smoking + +# balin's tomb +domain 2, title 1, program 29, start 0x234abb, end 0x234dd0 # gore/skeletons +domain 2, title 1, program 29, start 0x2352ed, end 0x2361d7 # gore/skeletons +domain 2, title 1, program 29, start 0x23898b, end 0x23955c # gore/skeletons +domain 2, title 1, program 29, start 0x23b467, end 0x23db2b # gore/skeletons +#domain 2, title 1, program 29, start 0x247360, end 0x25e24b # violence +domain 2, title 1, program 29, start 0x2483b6, end 0x248b62 # gore/impalement +domain 2, title 1, program 29, start 0x24a606, end 0x24a9f3 # gore/headshot +domain 2, title 1, program 29, start 0x24acd8, end 0x24ae7e # gore/decapitation +domain 2, title 1, program 29, start 0x24d708, end 0x24d88f # gore/bashing +domain 2, title 1, program 29, start 0x25013a, end 0x250501 # gore/impalement +domain 2, title 1, program 29, start 0x2540a0, end 0x254507 # jump +domain 2, title 1, program 29, start 0x2560b3, end 0x256423 # gore/impalement +domain 2, title 1, program 29, start 0x258152, end 0x258459 # gore/impalement +domain 2, title 1, program 29, start 0x258152, end 0x258459 # gore/impalement + +# the bridge +#domain 2, title 1, program 30, start 0x274235, end 0x275e59 # violence +domain 2, title 1, program 30, start 0x2744c6, end 0x274a5e # gore/headshot +domain 2, title 1, program 30, start 0x275661, end 0x275e59 # violence/death +domain 2, title 1, program 30, start 0x289d2a, end 0x28a066 # gore/falling + +# lothlorien +domain 2, title 1, program 32, start 0x2be304, end 0x2beb1d # violence +domain 2, title 1, program 32, start 0x2c5d59, end 0x2c9a40 # horror/posession +#domain 2, title 1, program 32, start 0x2c5d59, end 0x2c9e41 # horror/posession + +# parth galen +domain 2, title 1, program 36, start 0x2fa317, end 0x2fb0b0 # violence + +# parth galen w/ orcs +domain 2, title 1, program 37, start 0x30c8cb, end 0x313054 # violence +domain 2, title 1, program 37, start 0x310428, end 0x313054 # gore/impalement +#domain 2, title 1, program 37, start 0x317f45, end 0x332a52 # violence +domain 2, title 1, program 37, start 0x322d8b, end 0x328f4d # gore/impalement +domain 2, title 1, program 37, start 0x32f2a4, end 0x330731 # gore/impalement +domain 2, title 1, program 37, start 0x330b3b, end 0x330c4d # gore/blood +domain 2, title 1, program 37, start 0x331c4e, end 0x332a52 # gore/dismemberment +domain 2, title 1, program 37, start 0x331c4e, end 0x332a52 # gore/decapitation + +# death of boromir +domain 2, title 1, program 38, start 0x33322f, end 0x33c10c # gore/bodies +domain 2, title 1, program 38, start 0x33b558, end 0x33c10c # horror/death + +# to the eastern shore +domain 2, title 1, program 39, start 0x34a25b, end 0x34c1e3 # horror/drowning + + + + + + diff --git a/lib/libdvd/libdvdnav/src/Makefile.am b/lib/libdvd/libdvdnav/src/Makefile.am new file mode 100644 index 0000000000..c39b2e7bec --- /dev/null +++ b/lib/libdvd/libdvdnav/src/Makefile.am @@ -0,0 +1,34 @@ +include $(top_srcdir)/misc/Makefile.common + +SUBDIRS = vm + +includedir = ${prefix}/include/dvdnav + +AM_CPPFLAGS = -DDVDNAV_COMPILE $(THREAD_CFLAGS) $(DVDREAD_CFLAGS) \ + -I$(top_srcdir)/src/vm + +EXTRA_DIST = README.MAP FELLOWSHIP.map + +lib_LTLIBRARIES = libdvdnav.la libdvdnavmini.la + +libdvdnav_la_SOURCES = dvdnav.c \ + read_cache.c navigation.c highlight.c \ + searching.c settings.c remap.c \ + dvdnav_internal.h read_cache.h remap.h + +libdvdnav_la_LIBADD = $(THREAD_LIBS) $(DVDREAD_LIBS) \ + $(top_builddir)/src/vm/libdvdvm.la + +libdvdnav_la_LDFLAGS = \ + -version-info $(DVDNAV_LT_CURRENT):$(DVDNAV_LT_REVISION):$(DVDNAV_LT_AGE) \ + -export-symbols-regex "(^dvdnav.*|^nav.*|^ifo.*|^DVD.*)" +# -release $(DVDNAV_MAJOR).$(DVDNAV_MINOR).$(DVDNAV_SUB) + +libdvdnavmini_la_SOURCES = $(libdvdnav_la_SOURCES) + +libdvdnavmini_la_LIBADD = $(THREAD_LIBS) \ + $(top_builddir)/src/vm/libdvdvm.la + +libdvdnavmini_la_LDFLAGS = $(libdvdnav_la_LDFLAGS) + +include_HEADERS = dvdnav.h dvdnav_events.h dvd_types.h diff --git a/lib/libdvd/libdvdnav/src/README.MAP b/lib/libdvd/libdvdnav/src/README.MAP new file mode 100644 index 0000000000..2181a03d65 --- /dev/null +++ b/lib/libdvd/libdvdnav/src/README.MAP @@ -0,0 +1,105 @@ +Contents + +WHAT ARE MAP FILES +HOWTO +FINDING MAP FILES +WHOM TO BLAME + +WHAT ARE MAP FILES +================== + +Map files are an experimental feature that lets you customize the way +you watch DVDs. If you are opposed to violence, are sickened by gore, +or would rather your two year old didn't ask you just yet why that +woman in the movie was naked, you might want to create a map file. + +Map files identify sections of the movie that will be skipped during +playback. You can skip any section you like with the only restriction +(right now) that the movie player must play at least the last VOBU +(about a fifth of a second) of each chapter in the movie in order +to detect chapter changes correctly. + +Included with this patch is an example map file that describes most +of the potentially objectionable content in the new "The Lord of the +Rings" DVD. I've added a comment after each block that identifies +what content it contains so that you can customize the file to your +preferences. The map file looks something like this: + + # The Lord of the Rings: Fellowship of the Ring + # (Widescreen Theatrical Release) + debug + domain 8, title 1, program 1, start 0x0000, end 0x1f0a # Introduction + + # history of middle earth + #domain 2, title 1, program 1, start 0x9cba, end 0xcea4 # violence/war + #domain 2, title 1, program 1, start 0xf018, end 0x1272c # violence/war + domain 2, title 1, program 1, start 0x11ff3, end 0x1272c # gore + #domain 2, title 1, program 1, start 0x173f1, end 0x185d6 # violence/death + +Place the map file in your .xine directory to enable the selected +cuts as follows: + + cp FELLOWSHIP.map ~/.xine + +The debug command tells the map code that you would like to see the +VOBU numbers as the movie is playing. Comment out this line to hide +this output. The remaining lines are all either comments or blocks. +Each block has a start and an end, and whenever Xine tries to load +a VOBU between the start and end, it will be redirected to the end +block instead. + + +HOWTO +===== + +To create your own map files you would create a new map file using the +title of the disk as the filename, and add the debug line to it. The +map file should be placed in your '.xine' directory and have a '.map' +extension added. For example "The Lord Of The Rings" map must be stored +in the file ~/.xine/FELLOWSHIP.map + +After you create the file with the DEBUG line you will see output that +looks like this in window where you started Xine: + + FELLOWSHIP: domain 8, title 1, program 1, start 2205, next 22a8 + FELLOWSHIP: domain 8, title 1, program 1, start 22a8, next 234b + FELLOWSHIP: domain 8, title 1, program 1, start 234b, next 23eb + FELLOWSHIP: domain 8, title 1, program 1, start 23eb, next 248a + +Each line represents one VOBU, and the start and end addresses match +the start and end addresses that you should place in the map file +if you want to skip that block. If you want to skip multiple blocks +you would just add one line with the start address of the first block +to skip, and the end address of the last block to skip. For example +to skip these four blocks you would add the following line to your +map file: + + domain 8, title 1, program 1, start 0x2205, end 0x248a # 4 blocks + +Xine uses a buffered input chain so that if you pause the viewer you +won't find the same VOBU being displayed on the terminal as is +currently on the screen. In my testing the correct VOBU to use if +you pause exactly on the section you want to cut will be about five +or six lines above the last one printed to the screen. Replay the +scene with the deletion to see if you caught the correct blocks. + + +WHERE TO FIND MAP FILES +======================= + +If you create a map file for a new movie, please send it to me. If +there is widespread interest I'll put up a site where map files can +be located and downloaded. + + +WHOM TO BLAME +============= + +If the patch doesn't work for you (and you want it to) you can contact +me at 'kevin_smathers@hp.com'. + +If the patch works for you and you don't want it to, remember that +not everyone in the world has the same needs. The freedom to censor +movies in our own homes is quite different from the government +interfering into libraries and other public forums to censor movies +for us. diff --git a/lib/libdvd/libdvdnav/src/dvd_types.h b/lib/libdvd/libdvdnav/src/dvd_types.h new file mode 100644 index 0000000000..43c21c9674 --- /dev/null +++ b/lib/libdvd/libdvdnav/src/dvd_types.h @@ -0,0 +1,278 @@ +/* + * Copyright (C) 2000, 2001 Björn Englund, Håkan Hjort + * + * This file is part of libdvdnav, a DVD navigation library. It is a modified + * file originally part of the Ogle DVD player project. + * + * libdvdnav 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. + * + * libdvdnav 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 + * + * $Id: dvd_types.h 1135 2008-09-06 21:55:51Z rathann $ + * + */ + +/* + * Various useful structs and enums for DVDs. + */ + +#ifndef DVD_H_INCLUDED +#define DVD_H_INCLUDED + +/* + * DVD Menu ID + * (see dvdnav_menu_call()) + */ +typedef enum { + /* When used in VTS domain, DVD_MENU_Escape behaves like DVD_MENU_Root, + * but from within a menu domain, DVD_MENU_Escape resumes playback. */ + DVD_MENU_Escape = 0, + DVD_MENU_Title = 2, + DVD_MENU_Root = 3, + DVD_MENU_Subpicture = 4, + DVD_MENU_Audio = 5, + DVD_MENU_Angle = 6, + DVD_MENU_Part = 7 +} DVDMenuID_t; + + +/* + * Structure containing info on highlight areas + * (see dvdnav_get_highlight_area()) + */ +typedef struct { + uint32_t palette; /* The CLUT entries for the highlight palette + (4-bits per entry -> 4 entries) */ + uint16_t sx,sy,ex,ey; /* The start/end x,y positions */ + uint32_t pts; /* Highlight PTS to match with SPU */ + + /* button number for the SPU decoder/overlaying engine */ + uint32_t buttonN; +} dvdnav_highlight_area_t; + + +/* the following types are currently unused */ + +#if 0 + +/* Domain */ +typedef enum { + DVD_DOMAIN_FirstPlay, /* First Play Domain */ + DVD_DOMAIN_VMG, /* Video Manager Domain */ + DVD_DOMAIN_VTSMenu, /* Video Title Set Menu Domain */ + DVD_DOMAIN_VTSTitle, /* Video Title Set Domain */ + DVD_DOMAIN_Stop /* Stop Domain */ +} DVDDomain_t; + +/* User operation permissions */ +typedef enum { + UOP_FLAG_TitleOrTimePlay = 0x00000001, + UOP_FLAG_ChapterSearchOrPlay = 0x00000002, + UOP_FLAG_TitlePlay = 0x00000004, + UOP_FLAG_Stop = 0x00000008, + UOP_FLAG_GoUp = 0x00000010, + UOP_FLAG_TimeOrChapterSearch = 0x00000020, + UOP_FLAG_PrevOrTopPGSearch = 0x00000040, + UOP_FLAG_NextPGSearch = 0x00000080, + UOP_FLAG_ForwardScan = 0x00000100, + UOP_FLAG_BackwardScan = 0x00000200, + UOP_FLAG_TitleMenuCall = 0x00000400, + UOP_FLAG_RootMenuCall = 0x00000800, + UOP_FLAG_SubPicMenuCall = 0x00001000, + UOP_FLAG_AudioMenuCall = 0x00002000, + UOP_FLAG_AngleMenuCall = 0x00004000, + UOP_FLAG_ChapterMenuCall = 0x00008000, + UOP_FLAG_Resume = 0x00010000, + UOP_FLAG_ButtonSelectOrActivate = 0x00020000, + UOP_FLAG_StillOff = 0x00040000, + UOP_FLAG_PauseOn = 0x00080000, + UOP_FLAG_AudioStreamChange = 0x00100000, + UOP_FLAG_SubPicStreamChange = 0x00200000, + UOP_FLAG_AngleChange = 0x00400000, + UOP_FLAG_KaraokeAudioPresModeChange = 0x00800000, + UOP_FLAG_VideoPresModeChange = 0x01000000 +} DVDUOP_t; + +/* Parental Level */ +typedef enum { + DVD_PARENTAL_LEVEL_1 = 1, + DVD_PARENTAL_LEVEL_2 = 2, + DVD_PARENTAL_LEVEL_3 = 3, + DVD_PARENTAL_LEVEL_4 = 4, + DVD_PARENTAL_LEVEL_5 = 5, + DVD_PARENTAL_LEVEL_6 = 6, + DVD_PARENTAL_LEVEL_7 = 7, + DVD_PARENTAL_LEVEL_8 = 8, + DVD_PARENTAL_LEVEL_None = 15 +} DVDParentalLevel_t; + +/* Language ID (ISO-639 language code) */ +typedef uint16_t DVDLangID_t; + +/* Country ID (ISO-3166 country code) */ +typedef uint16_t DVDCountryID_t; + +/* Register */ +typedef uint16_t DVDRegister_t; +typedef enum { + DVDFalse = 0, + DVDTrue = 1 +} DVDBool_t; +typedef DVDRegister_t DVDGPRMArray_t[16]; +typedef DVDRegister_t DVDSPRMArray_t[24]; + +/* Navigation */ +typedef int DVDStream_t; +typedef int DVDPTT_t; +typedef int DVDTitle_t; + +/* Angle number (1-9 or default?) */ +typedef int DVDAngle_t; + +/* Timecode */ +typedef struct { + uint8_t Hours; + uint8_t Minutes; + uint8_t Seconds; + uint8_t Frames; +} DVDTimecode_t; + +/* Subpicture stream number (0-31,62,63) */ +typedef int DVDSubpictureStream_t; + +/* Audio stream number (0-7, 15(none)) */ +typedef int DVDAudioStream_t; + +/* The audio application mode */ +typedef enum { + DVD_AUDIO_APP_MODE_None = 0, + DVD_AUDIO_APP_MODE_Karaoke = 1, + DVD_AUDIO_APP_MODE_Surround = 2, + DVD_AUDIO_APP_MODE_Other = 3 +} DVDAudioAppMode_t; + +/* The audio format */ +typedef enum { + DVD_AUDIO_FORMAT_AC3 = 0, + DVD_AUDIO_FORMAT_MPEG1 = 1, + DVD_AUDIO_FORMAT_MPEG1_DRC = 2, + DVD_AUDIO_FORMAT_MPEG2 = 3, + DVD_AUDIO_FORMAT_MPEG2_DRC = 4, + DVD_AUDIO_FORMAT_LPCM = 5, + DVD_AUDIO_FORMAT_DTS = 6, + DVD_AUDIO_FORMAT_SDDS = 7, + DVD_AUDIO_FORMAT_Other = 8 +} DVDAudioFormat_t; + +/* Audio language extension */ +typedef enum { + DVD_AUDIO_LANG_EXT_NotSpecified = 0, + DVD_AUDIO_LANG_EXT_NormalCaptions = 1, + DVD_AUDIO_LANG_EXT_VisuallyImpaired = 2, + DVD_AUDIO_LANG_EXT_DirectorsComments1 = 3, + DVD_AUDIO_LANG_EXT_DirectorsComments2 = 4 +} DVDAudioLangExt_t; + +/* Subpicture language extension */ +typedef enum { + DVD_SUBPICTURE_LANG_EXT_NotSpecified = 0, + DVD_SUBPICTURE_LANG_EXT_NormalCaptions = 1, + DVD_SUBPICTURE_LANG_EXT_BigCaptions = 2, + DVD_SUBPICTURE_LANG_EXT_ChildrensCaptions = 3, + DVD_SUBPICTURE_LANG_EXT_NormalCC = 5, + DVD_SUBPICTURE_LANG_EXT_BigCC = 6, + DVD_SUBPICTURE_LANG_EXT_ChildrensCC = 7, + DVD_SUBPICTURE_LANG_EXT_Forced = 9, + DVD_SUBPICTURE_LANG_EXT_NormalDirectorsComments = 13, + DVD_SUBPICTURE_LANG_EXT_BigDirectorsComments = 14, + DVD_SUBPICTURE_LANG_EXT_ChildrensDirectorsComments = 15, +} DVDSubpictureLangExt_t; + +/* Karaoke Downmix mode */ +typedef enum { + DVD_KARAOKE_DOWNMIX_0to0 = 0x0001, + DVD_KARAOKE_DOWNMIX_1to0 = 0x0002, + DVD_KARAOKE_DOWNMIX_2to0 = 0x0004, + DVD_KARAOKE_DOWNMIX_3to0 = 0x0008, + DVD_KARAOKE_DOWNMIX_4to0 = 0x0010, + DVD_KARAOKE_DOWNMIX_Lto0 = 0x0020, + DVD_KARAOKE_DOWNMIX_Rto0 = 0x0040, + DVD_KARAOKE_DOWNMIX_0to1 = 0x0100, + DVD_KARAOKE_DOWNMIX_1to1 = 0x0200, + DVD_KARAOKE_DOWNMIX_2to1 = 0x0400, + DVD_KARAOKE_DOWNMIX_3to1 = 0x0800, + DVD_KARAOKE_DOWNMIX_4to1 = 0x1000, + DVD_KARAOKE_DOWNMIX_Lto1 = 0x2000, + DVD_KARAOKE_DOWNMIX_Rto1 = 0x4000 +} DVDKaraokeDownmix_t; +typedef int DVDKaraokeDownmixMask_t; + +/* Display mode */ +typedef enum { + DVD_DISPLAY_MODE_ContentDefault = 0, + DVD_DISPLAY_MODE_16x9 = 1, + DVD_DISPLAY_MODE_4x3PanScan = 2, + DVD_DISPLAY_MODE_4x3Letterboxed = 3 +} DVDDisplayMode_t; + +/* Audio attributes */ +typedef struct { + DVDAudioAppMode_t AppMode; + DVDAudioFormat_t AudioFormat; + DVDLangID_t Language; + DVDAudioLangExt_t LanguageExtension; + DVDBool_t HasMultichannelInfo; + DVDAudioSampleFreq_t SampleFrequency; + DVDAudioSampleQuant_t SampleQuantization; + DVDChannelNumber_t NumberOfChannels; +} DVDAudioAttributes_t; +typedef int DVDAudioSampleFreq_t; +typedef int DVDAudioSampleQuant_t; +typedef int DVDChannelNumber_t; + +/* Subpicture attributes */ +typedef enum { + DVD_SUBPICTURE_TYPE_NotSpecified = 0, + DVD_SUBPICTURE_TYPE_Language = 1, + DVD_SUBPICTURE_TYPE_Other = 2 +} DVDSubpictureType_t; +typedef enum { + DVD_SUBPICTURE_CODING_RunLength = 0, + DVD_SUBPICTURE_CODING_Extended = 1, + DVD_SUBPICTURE_CODING_Other = 2 +} DVDSubpictureCoding_t; +typedef struct { + DVDSubpictureType_t Type; + DVDSubpictureCoding_t CodingMode; + DVDLangID_t Language; + DVDSubpictureLangExt_t LanguageExtension; +} DVDSubpictureAttributes_t; + +/* Video attributes */ +typedef struct { + DVDBool_t PanscanPermitted; + DVDBool_t LetterboxPermitted; + int AspectX; + int AspectY; + int FrameRate; + int FrameHeight; + DVDVideoCompression_t Compression; + DVDBool_t Line21Field1InGop; + DVDBool_t Line21Field2InGop; + int more_to_come; +} DVDVideoAttributes_t; +typedef int DVDVideoCompression_t; + +#endif + +#endif /* DVD_H_INCLUDED */ diff --git a/lib/libdvd/libdvdnav/src/dvdnav.c b/lib/libdvd/libdvdnav/src/dvdnav.c new file mode 100644 index 0000000000..5af111ca06 --- /dev/null +++ b/lib/libdvd/libdvdnav/src/dvdnav.c @@ -0,0 +1,1451 @@ +/* + * Copyright (C) 2000 Rich Wareham <richwareham@users.sourceforge.net> + * + * This file is part of libdvdnav, a DVD navigation library. + * + * libdvdnav 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. + * + * libdvdnav 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 + * + * $Id: dvdnav.c 1135 2008-09-06 21:55:51Z rathann $ + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* +#define LOG_DEBUG +*/ + +#include <inttypes.h> +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <limits.h> +#include <string.h> +#include <sys/time.h> +#include "dvd_types.h" +#include <dvdread/dvd_reader.h> +#include <dvdread/nav_types.h> +#include <dvdread/ifo_types.h> /* For vm_cmd_t */ +#include "remap.h" +#include "vm/decoder.h" +#include "vm/vm.h" +#include "dvdnav.h" +#include "dvdnav_events.h" +#include "dvdnav_internal.h" +#include "read_cache.h" +#include <dvdread/nav_read.h> +#include "remap.h" + +static dvdnav_status_t dvdnav_clear(dvdnav_t * this) { + /* clear everything except file, vm, mutex, readahead */ + + pthread_mutex_lock(&this->vm_lock); + if (this->file) DVDCloseFile(this->file); + this->file = NULL; + + memset(&this->pci,0,sizeof(this->pci)); + memset(&this->dsi,0,sizeof(this->dsi)); + this->last_cmd_nav_lbn = SRI_END_OF_CELL; + + /* Set initial values of flags */ + this->position_current.still = 0; + this->skip_still = 0; + this->sync_wait = 0; + this->sync_wait_skip = 0; + this->spu_clut_changed = 0; + this->started = 0; + this->cur_cell_time = 0; + + dvdnav_read_cache_clear(this->cache); + pthread_mutex_unlock(&this->vm_lock); + + return DVDNAV_STATUS_OK; +} + +dvdnav_status_t dvdnav_open(dvdnav_t** dest, const char *path) { + dvdnav_t *this; + struct timeval time; + + /* Create a new structure */ + fprintf(MSG_OUT, "libdvdnav: Using dvdnav version %s\n", VERSION); + + (*dest) = NULL; + this = (dvdnav_t*)malloc(sizeof(dvdnav_t)); + if(!this) + return DVDNAV_STATUS_ERR; + memset(this, 0, (sizeof(dvdnav_t) ) ); /* Make sure this structure is clean */ + + pthread_mutex_init(&this->vm_lock, NULL); + /* Initialise the error string */ + printerr(""); + + /* Initialise the VM */ + this->vm = vm_new_vm(); + if(!this->vm) { + printerr("Error initialising the DVD VM."); + pthread_mutex_destroy(&this->vm_lock); + free(this); + return DVDNAV_STATUS_ERR; + } + if(!vm_reset(this->vm, path)) { + printerr("Error starting the VM / opening the DVD device."); + pthread_mutex_destroy(&this->vm_lock); + vm_free_vm(this->vm); + free(this); + return DVDNAV_STATUS_ERR; + } + + /* Set the path. FIXME: Is a deep copy 'right' */ + strncpy(this->path, path, MAX_PATH_LEN - 1); + this->path[MAX_PATH_LEN - 1] = '\0'; + + /* Pre-open and close a file so that the CSS-keys are cached. */ + this->file = DVDOpenFile(vm_get_dvd_reader(this->vm), 0, DVD_READ_MENU_VOBS); + + /* Start the read-ahead cache. */ + this->cache = dvdnav_read_cache_new(this); + + /* Seed the random numbers. So that the DVD VM Command rand() + * gives a different start value each time a DVD is played. */ + gettimeofday(&time, NULL); + srand(time.tv_usec); + + dvdnav_clear(this); + + (*dest) = this; + return DVDNAV_STATUS_OK; +} + +dvdnav_status_t dvdnav_close(dvdnav_t *this) { + +#ifdef LOG_DEBUG + fprintf(MSG_OUT, "libdvdnav: close:called\n"); +#endif + + if (this->file) { + pthread_mutex_lock(&this->vm_lock); + DVDCloseFile(this->file); +#ifdef LOG_DEBUG + fprintf(MSG_OUT, "libdvdnav: close:file closing\n"); +#endif + this->file = NULL; + pthread_mutex_unlock(&this->vm_lock); + } + + /* Free the VM */ + if(this->vm) + vm_free_vm(this->vm); + + pthread_mutex_destroy(&this->vm_lock); + + /* We leave the final freeing of the entire structure to the cache, + * because we don't know, if there are still buffers out in the wild, + * that must return first. */ + if(this->cache) + dvdnav_read_cache_free(this->cache); + else + free(this); + + return DVDNAV_STATUS_OK; +} + +dvdnav_status_t dvdnav_reset(dvdnav_t *this) { + dvdnav_status_t result; + +#ifdef LOG_DEBUG + fprintf(MSG_OUT, "libdvdnav: reset:called\n"); +#endif + + pthread_mutex_lock(&this->vm_lock); + +#ifdef LOG_DEBUG + fprintf(MSG_OUT, "libdvdnav: reseting vm\n"); +#endif + if(!vm_reset(this->vm, NULL)) { + printerr("Error restarting the VM."); + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_ERR; + } +#ifdef LOG_DEBUG + fprintf(MSG_OUT, "libdvdnav: clearing dvdnav\n"); +#endif + result = dvdnav_clear(this); + + pthread_mutex_unlock(&this->vm_lock); + return result; +} + +dvdnav_status_t dvdnav_path(dvdnav_t *this, const char** path) { + (*path) = this->path; + + return DVDNAV_STATUS_OK; +} + +const char* dvdnav_err_to_string(dvdnav_t *this) { + + if(!this) + return "Hey! You gave me a NULL pointer you naughty person!"; + + return this->err_str; +} + +/* converts a dvd_time_t to PTS ticks */ +int64_t dvdnav_convert_time(dvd_time_t *time) { + int64_t result; + int64_t frames; + + result = (time->hour >> 4 ) * 10 * 60 * 60 * 90000; + result += (time->hour & 0x0f) * 60 * 60 * 90000; + result += (time->minute >> 4 ) * 10 * 60 * 90000; + result += (time->minute & 0x0f) * 60 * 90000; + result += (time->second >> 4 ) * 10 * 90000; + result += (time->second & 0x0f) * 90000; + + frames = ((time->frame_u & 0x30) >> 4) * 10; + frames += ((time->frame_u & 0x0f) ) ; + + if (time->frame_u & 0x80) + result += frames * 3000; + else + result += frames * 3600; + + return result; +} + +/* + * Returns 1 if block contains NAV packet, 0 otherwise. + * Processes said NAV packet if present. + * + * Most of the code in here is copied from xine's MPEG demuxer + * so any bugs which are found in that should be corrected here also. + */ +static int32_t dvdnav_decode_packet(dvdnav_t *this, uint8_t *p, dsi_t *nav_dsi, pci_t *nav_pci) { + int32_t bMpeg1 = 0; + uint32_t nHeaderLen; + uint32_t nPacketLen; + uint32_t nStreamID; + + if (p[3] == 0xBA) { /* program stream pack header */ + int32_t nStuffingBytes; + + bMpeg1 = (p[4] & 0x40) == 0; + + if (bMpeg1) { + p += 12; + } else { /* mpeg2 */ + nStuffingBytes = p[0xD] & 0x07; + p += 14 + nStuffingBytes; + } + } + + if (p[3] == 0xbb) { /* program stream system header */ + nHeaderLen = (p[4] << 8) | p[5]; + p += 6 + nHeaderLen; + } + + /* we should now have a PES packet here */ + if (p[0] || p[1] || (p[2] != 1)) { + fprintf(MSG_OUT, "libdvdnav: demux error! %02x %02x %02x (should be 0x000001) \n",p[0],p[1],p[2]); + return 0; + } + + nPacketLen = p[4] << 8 | p[5]; + nStreamID = p[3]; + + nHeaderLen = 6; + p += nHeaderLen; + + if (nStreamID == 0xbf) { /* Private stream 2 */ +#if 0 + int32_t i; + fprintf(MSG_OUT, "libdvdnav: nav packet=%u\n",p-p_start-6); + for(i=0;i<80;i++) + fprintf(MSG_OUT, "%02x ",p[i-6]); + fprintf(MSG_OUT, "\n"); +#endif + + if(p[0] == 0x00) { + navRead_PCI(nav_pci, p+1); + } + + p += nPacketLen; + + /* We should now have a DSI packet. */ + if(p[6] == 0x01) { + nPacketLen = p[4] << 8 | p[5]; + p += 6; + navRead_DSI(nav_dsi, p+1); + } + return 1; + } + return 0; +} + +/* DSI is used for most angle stuff. + * PCI is used for only non-seemless angle stuff + */ +static int32_t dvdnav_get_vobu(dvdnav_t *this, dsi_t *nav_dsi, pci_t *nav_pci, dvdnav_vobu_t *vobu) { + uint32_t next; + int32_t angle, num_angle; + + vobu->vobu_start = nav_dsi->dsi_gi.nv_pck_lbn; /* Absolute offset from start of disk */ + vobu->vobu_length = nav_dsi->dsi_gi.vobu_ea; /* Relative offset from vobu_start */ + + /* + * If we're not at the end of this cell, we can determine the next + * VOBU to display using the VOBU_SRI information section of the + * DSI. Using this value correctly follows the current angle, + * avoiding the doubled scenes in The Matrix, and makes our life + * really happy. + * + * vobu_next is an offset value, 0x3fffffff = SRI_END_OF_CELL + * DVDs are about 6 Gigs, which is only up to 0x300000 blocks + * Should really assert if bit 31 != 1 + */ + +#if 0 + /* Old code -- may still be useful one day */ + if(nav_dsi->vobu_sri.next_vobu != SRI_END_OF_CELL ) { + vobu->vobu_next = ( nav_dsi->vobu_sri.next_vobu & 0x3fffffff ); + } else { + vobu->vobu_next = vobu->vobu_length; + } +#else + /* Relative offset from vobu_start */ + vobu->vobu_next = ( nav_dsi->vobu_sri.next_vobu & 0x3fffffff ); +#endif + + vm_get_angle_info(this->vm, &angle, &num_angle); + + /* FIMXE: The angle reset doesn't work for some reason for the moment */ +#if 0 + if((num_angle < angle) && (angle != 1)) { + fprintf(MSG_OUT, "libdvdnav: angle ends!\n"); + + /* This is to switch back to angle one when we + * finish with angles. */ + dvdnav_angle_change(this, 1); + } +#endif + + /* only use ILVU information if we are at the last vobunit in ILVU */ + /* otherwise we will miss nav packets from vobunits inbetween */ + if(num_angle != 0 && (nav_dsi->sml_pbi.category & 0x5000) == 0x5000 ) { + + if((next = nav_pci->nsml_agli.nsml_agl_dsta[angle-1]) != 0) { + if((next & 0x3fffffff) != 0) { + if(next & 0x80000000) + vobu->vobu_next = - (int32_t)(next & 0x3fffffff); + else + vobu->vobu_next = + (int32_t)(next & 0x3fffffff); + } + } else if((next = nav_dsi->sml_agli.data[angle-1].address) != 0) { + vobu->vobu_length = nav_dsi->sml_pbi.ilvu_ea; + + if((next & 0x80000000) && (next != 0x7fffffff)) + vobu->vobu_next = - (int32_t)(next & 0x3fffffff); + else + vobu->vobu_next = + (int32_t)(next & 0x3fffffff); + } + } + + return 1; +} + +/* + * These are the main get_next_block function which actually get the media stream video and audio etc. + * + * There are two versions: The second one is using the zero-copy read ahead cache and therefore + * hands out pointers targetting directly into the cache. + * The first one uses a memcopy to fill this cache block into the application provided memory. + * The benefit of this first one is that no special memory management is needed. The application is + * the only one responsible of allocating and freeing the memory associated with the pointer. + * The drawback is the additional memcopy. + */ + +dvdnav_status_t dvdnav_get_next_block(dvdnav_t *this, uint8_t *buf, + int32_t *event, int32_t *len) { + unsigned char *block; + dvdnav_status_t status; + + block = buf; + status = dvdnav_get_next_cache_block(this, &block, event, len); + if (status == DVDNAV_STATUS_OK && block != buf) { + /* we received a block from the cache, copy it, so we can give it back */ + memcpy(buf, block, DVD_VIDEO_LB_LEN); + dvdnav_free_cache_block(this, block); + } + return status; +} + +int64_t dvdnav_get_current_time(dvdnav_t *this) { + int i; + int64_t tm=0; + dvd_state_t *state = &this->vm->state; + + for(i=0; i<state->cellN-1; i++) { + if(! + (state->pgc->cell_playback[i].block_type == BLOCK_TYPE_ANGLE_BLOCK && + state->pgc->cell_playback[i].block_mode != BLOCK_MODE_FIRST_CELL) + ) + tm += dvdnav_convert_time(&state->pgc->cell_playback[i].playback_time); + } + tm += this->cur_cell_time; + + return tm; +} + +dvdnav_status_t dvdnav_get_next_cache_block(dvdnav_t *this, uint8_t **buf, + int32_t *event, int32_t *len) { + dvd_state_t *state; + int32_t result; + + pthread_mutex_lock(&this->vm_lock); + + if(!this->started) { + /* Start the VM */ + if (!vm_start(this->vm)) { + printerr("Encrypted or faulty DVD"); + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_ERR; + } + this->started = 1; + } + + state = &(this->vm->state); + (*event) = DVDNAV_NOP; + (*len) = 0; + + /* Check the STOP flag */ + if(this->vm->stopped) { + vm_stop(this->vm); + (*event) = DVDNAV_STOP; + this->started = 0; + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_OK; + } + + vm_position_get(this->vm, &this->position_next); + +#ifdef LOG_DEBUG + fprintf(MSG_OUT, "libdvdnav: POS-NEXT "); + vm_position_print(this->vm, &this->position_next); + fprintf(MSG_OUT, "libdvdnav: POS-CUR "); + vm_position_print(this->vm, &this->position_current); +#endif + + /* did we hop? */ + if(this->position_current.hop_channel != this->position_next.hop_channel) { + (*event) = DVDNAV_HOP_CHANNEL; +#ifdef LOG_DEBUG + fprintf(MSG_OUT, "libdvdnav: HOP_CHANNEL\n"); +#endif + if (this->position_next.hop_channel - this->position_current.hop_channel >= HOP_SEEK) { + int32_t num_angles = 0, current; + + /* we seeked -> check for multiple angles */ + vm_get_angle_info(this->vm, ¤t, &num_angles); + if (num_angles > 1) { + int32_t result, block; + /* we have to skip the first VOBU when seeking in a multiangle feature, + * because it might belong to the wrong angle */ + block = this->position_next.cell_start + this->position_next.block; + result = dvdnav_read_cache_block(this->cache, block, 1, buf); + if(result <= 0) { + printerr("Error reading NAV packet."); + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_ERR; + } + /* Decode nav into pci and dsi. Then get next VOBU info. */ + if(!dvdnav_decode_packet(this, *buf, &this->dsi, &this->pci)) { + printerr("Expected NAV packet but none found."); +#ifdef _XBMC + /* skip this cell as we won't recover from this*/ + vm_get_next_cell(this->vm); +#endif + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_ERR; + } + dvdnav_get_vobu(this, &this->dsi, &this->pci, &this->vobu); + /* skip to next, if there is a next */ + if (this->vobu.vobu_next != SRI_END_OF_CELL) { + this->vobu.vobu_start += this->vobu.vobu_next; + this->vobu.vobu_next = 0; + } + /* update VM state */ + this->vm->state.blockN = this->vobu.vobu_start - this->position_next.cell_start; + } + } + this->position_current.hop_channel = this->position_next.hop_channel; + /* update VOBU info */ + this->vobu.vobu_start = this->position_next.cell_start + this->position_next.block; + this->vobu.vobu_next = 0; + /* Make blockN == vobu_length to do expected_nav */ + this->vobu.vobu_length = 0; + this->vobu.blockN = 0; + this->sync_wait = 0; + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_OK; + } + + /* Check the HIGHLIGHT flag */ + if(this->position_current.button != this->position_next.button) { + dvdnav_highlight_event_t *hevent = (dvdnav_highlight_event_t *)*buf; + + (*event) = DVDNAV_HIGHLIGHT; +#ifdef LOG_DEBUG + fprintf(MSG_OUT, "libdvdnav: HIGHLIGHT\n"); +#endif + (*len) = sizeof(dvdnav_highlight_event_t); + hevent->display = 1; + hevent->buttonN = this->position_next.button; + this->position_current.button = this->position_next.button; + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_OK; + } + + /* Check the WAIT flag */ + if(this->sync_wait) { + (*event) = DVDNAV_WAIT; +#ifdef LOG_DEBUG + fprintf(MSG_OUT, "libdvdnav: WAIT\n"); +#endif + (*len) = 0; + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_OK; + } + + /* Check to see if we need to change the currently opened VOB */ + if((this->position_current.vts != this->position_next.vts) || + (this->position_current.domain != this->position_next.domain)) { + dvd_read_domain_t domain; + int32_t vtsN; + dvdnav_vts_change_event_t *vts_event = (dvdnav_vts_change_event_t *)*buf; + + if(this->file) { + DVDCloseFile(this->file); + this->file = NULL; + } + + vts_event->old_vtsN = this->position_current.vts; + vts_event->old_domain = this->position_current.domain; + + /* Use the DOMAIN to find whether to open menu or title VOBs */ + switch(this->position_next.domain) { + case FP_DOMAIN: + case VMGM_DOMAIN: + domain = DVD_READ_MENU_VOBS; + vtsN = 0; + break; + case VTSM_DOMAIN: + domain = DVD_READ_MENU_VOBS; + vtsN = this->position_next.vts; + break; + case VTS_DOMAIN: + domain = DVD_READ_TITLE_VOBS; + vtsN = this->position_next.vts; + break; + default: + printerr("Unknown domain when changing VTS."); + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_ERR; + } + + this->position_current.vts = this->position_next.vts; + this->position_current.domain = this->position_next.domain; + dvdnav_read_cache_clear(this->cache); + this->file = DVDOpenFile(vm_get_dvd_reader(this->vm), vtsN, domain); + vts_event->new_vtsN = this->position_next.vts; + vts_event->new_domain = this->position_next.domain; + + /* If couldn't open the file for some reason, moan */ + if(this->file == NULL) { + printerrf("Error opening vtsN=%i, domain=%i.", vtsN, domain); + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_ERR; + } + + /* File opened successfully so return a VTS change event */ + (*event) = DVDNAV_VTS_CHANGE; +#ifdef LOG_DEBUG + fprintf(MSG_OUT, "libdvdnav: VTS_CHANGE\n"); +#endif + (*len) = sizeof(dvdnav_vts_change_event_t); + + this->spu_clut_changed = 1; + this->position_current.cell = -1; /* Force an update */ + this->position_current.spu_channel = -1; /* Force an update */ + this->position_current.audio_channel = -1; /* Force an update */; + + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_OK; + } + + /* Check if the cell changed */ + if( (this->position_current.cell != this->position_next.cell) || + (this->position_current.cell_restart != this->position_next.cell_restart) || + (this->position_current.cell_start != this->position_next.cell_start) ) { + dvdnav_cell_change_event_t *cell_event = (dvdnav_cell_change_event_t *)*buf; + int32_t first_cell_nr, last_cell_nr, i; + dvd_state_t *state = &this->vm->state; + + this->cur_cell_time = 0; + (*event) = DVDNAV_CELL_CHANGE; +#ifdef LOG_DEBUG + fprintf(MSG_OUT, "libdvdnav: CELL_CHANGE\n"); +#endif + (*len) = sizeof(dvdnav_cell_change_event_t); + + cell_event->cellN = state->cellN; + cell_event->pgN = state->pgN; + cell_event->cell_length = + dvdnav_convert_time(&state->pgc->cell_playback[state->cellN-1].playback_time); + + cell_event->pg_length = 0; + /* Find start cell of program. */ + first_cell_nr = state->pgc->program_map[state->pgN-1]; + /* Find end cell of program */ + if(state->pgN < state->pgc->nr_of_programs) + last_cell_nr = state->pgc->program_map[state->pgN] - 1; + else + last_cell_nr = state->pgc->nr_of_cells; + for (i = first_cell_nr; i <= last_cell_nr; i++) + cell_event->pg_length += + dvdnav_convert_time(&state->pgc->cell_playback[i - 1].playback_time); + cell_event->pgc_length = dvdnav_convert_time(&state->pgc->playback_time); + + cell_event->cell_start = 0; + for (i = 0; i < state->cellN; i++) + { + /* only count the first angle cell */ + if( state->pgc->cell_playback[i].block_type == BLOCK_TYPE_ANGLE_BLOCK + && state->pgc->cell_playback[i].block_mode != BLOCK_MODE_FIRST_CELL ) + continue; + + cell_event->cell_start += + dvdnav_convert_time(&state->pgc->cell_playback[i].playback_time); + } + cell_event->cell_start-= dvdnav_convert_time(&state->pgc->cell_playback[state->cellN-1].playback_time); + + cell_event->pg_start = 0; + for (i = 1; i < state->pgc->program_map[state->pgN-1]; i++) + cell_event->pg_start += + dvdnav_convert_time(&state->pgc->cell_playback[i - 1].playback_time); + + this->position_current.cell = this->position_next.cell; + this->position_current.cell_restart = this->position_next.cell_restart; + this->position_current.cell_start = this->position_next.cell_start; + this->position_current.block = this->position_next.block; + + /* vobu info is used for mid cell resumes */ + this->vobu.vobu_start = this->position_next.cell_start + this->position_next.block; + this->vobu.vobu_next = 0; + /* Make blockN == vobu_length to do expected_nav */ + this->vobu.vobu_length = 0; + this->vobu.blockN = 0; + + /* update the spu palette at least on PGC changes */ + this->spu_clut_changed = 1; + this->position_current.spu_channel = -1; /* Force an update */ + this->position_current.audio_channel = -1; /* Force an update */ + + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_OK; + } + + /* has the CLUT changed? */ + if(this->spu_clut_changed) { + (*event) = DVDNAV_SPU_CLUT_CHANGE; +#ifdef LOG_DEBUG + fprintf(MSG_OUT, "libdvdnav: SPU_CLUT_CHANGE\n"); +#endif + (*len) = 16 * sizeof(uint32_t); + memcpy(*buf, state->pgc->palette, 16 * sizeof(uint32_t)); + this->spu_clut_changed = 0; + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_OK; + } + + /* has the SPU channel changed? */ + if(this->position_current.spu_channel != this->position_next.spu_channel) { + dvdnav_spu_stream_change_event_t *stream_change = (dvdnav_spu_stream_change_event_t *)*buf; + + (*event) = DVDNAV_SPU_STREAM_CHANGE; +#ifdef LOG_DEBUG + fprintf(MSG_OUT, "libdvdnav: SPU_STREAM_CHANGE\n"); +#endif + (*len) = sizeof(dvdnav_spu_stream_change_event_t); + stream_change->physical_wide = vm_get_subp_active_stream(this->vm, 0); + stream_change->physical_letterbox = vm_get_subp_active_stream(this->vm, 1); + stream_change->physical_pan_scan = vm_get_subp_active_stream(this->vm, 2); + this->position_current.spu_channel = this->position_next.spu_channel; +#ifdef LOG_DEBUG + fprintf(MSG_OUT, "libdvdnav: SPU_STREAM_CHANGE stream_id_wide=%d\n",stream_change->physical_wide); + fprintf(MSG_OUT, "libdvdnav: SPU_STREAM_CHANGE stream_id_letterbox=%d\n",stream_change->physical_letterbox); + fprintf(MSG_OUT, "libdvdnav: SPU_STREAM_CHANGE stream_id_pan_scan=%d\n",stream_change->physical_pan_scan); + fprintf(MSG_OUT, "libdvdnav: SPU_STREAM_CHANGE returning DVDNAV_STATUS_OK\n"); +#endif + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_OK; + } + + /* has the audio channel changed? */ + if(this->position_current.audio_channel != this->position_next.audio_channel) { + dvdnav_audio_stream_change_event_t *stream_change = (dvdnav_audio_stream_change_event_t *)*buf; + + (*event) = DVDNAV_AUDIO_STREAM_CHANGE; +#ifdef LOG_DEBUG + fprintf(MSG_OUT, "libdvdnav: AUDIO_STREAM_CHANGE\n"); +#endif + (*len) = sizeof(dvdnav_audio_stream_change_event_t); + stream_change->physical = vm_get_audio_active_stream( this->vm ); + stream_change->logical = this->position_next.audio_channel; + this->position_current.audio_channel = this->position_next.audio_channel; +#ifdef LOG_DEBUG + fprintf(MSG_OUT, "libdvdnav: AUDIO_STREAM_CHANGE stream_id=%d returning DVDNAV_STATUS_OK\n",stream_change->physical); +#endif + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_OK; + } + + /* Check the STILLFRAME flag */ + if(this->position_current.still != 0) { + dvdnav_still_event_t *still_event = (dvdnav_still_event_t *)*buf; + + (*event) = DVDNAV_STILL_FRAME; +#ifdef LOG_DEBUG + fprintf(MSG_OUT, "libdvdnav: STILL_FRAME\n"); +#endif + (*len) = sizeof(dvdnav_still_event_t); + still_event->length = this->position_current.still; + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_OK; + } + + /* Have we reached the end of a VOBU? */ + if (this->vobu.blockN >= this->vobu.vobu_length) { + + /* Have we reached the end of a cell? */ + if(this->vobu.vobu_next == SRI_END_OF_CELL) { + /* End of Cell from NAV DSI info */ +#ifdef LOG_DEBUG + fprintf(MSG_OUT, "libdvdnav: Still set to %x\n", this->position_next.still); +#endif + this->position_current.still = this->position_next.still; + + /* we are about to leave a cell, so a lot of state changes could occur; + * under certain conditions, the application should get in sync with us before this, + * otherwise it might show stills or menus too shortly */ + if ((this->position_current.still || this->pci.hli.hl_gi.hli_ss) && !this->sync_wait_skip) { + this->sync_wait = 1; + } else { + if( this->position_current.still == 0 || this->skip_still ) { + /* no active cell still -> get us to the next cell */ + vm_get_next_cell(this->vm); + this->position_current.still = 0; /* still gets activated at end of cell */ + this->skip_still = 0; + this->sync_wait_skip = 0; + } + } + /* handle related state changes in next iteration */ + (*event) = DVDNAV_NOP; + (*len) = 0; + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_OK; + } + + /* Perform remapping jump if necessary (this is always a + * VOBU boundary). */ + if (this->vm->map) { + this->vobu.vobu_next = remap_block( this->vm->map, + this->vm->state.domain, this->vm->state.TTN_REG, + this->vm->state.pgN, + this->vobu.vobu_start, this->vobu.vobu_next); + } + + /* at the start of the next VOBU -> expecting NAV packet */ + result = dvdnav_read_cache_block(this->cache, this->vobu.vobu_start + this->vobu.vobu_next, 1, buf); + + if(result <= 0) { + printerr("Error reading NAV packet."); + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_ERR; + } + /* Decode nav into pci and dsi. Then get next VOBU info. */ + if(!dvdnav_decode_packet(this, *buf, &this->dsi, &this->pci)) { + printerr("Expected NAV packet but none found."); +#ifdef _XBMC + /* skip this cell as we won't recover from this */ + vm_get_next_cell(this->vm); +#endif + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_ERR; + } + /* We need to update the vm state->blockN with which VOBU we are in. + * This is so RSM resumes to the VOBU level and not just the CELL level. + */ + this->vm->state.blockN = this->vobu.vobu_start - this->position_current.cell_start; + + dvdnav_get_vobu(this, &this->dsi, &this->pci, &this->vobu); + this->vobu.blockN = 0; + /* Give the cache a hint about the size of next VOBU. + * This improves pre-caching, because the VOBU will almost certainly be read entirely. + */ + dvdnav_pre_cache_blocks(this->cache, this->vobu.vobu_start+1, this->vobu.vobu_length+1); + + /* release NAV menu filter, when we reach the same NAV packet again */ + if (this->last_cmd_nav_lbn == this->pci.pci_gi.nv_pck_lbn) + this->last_cmd_nav_lbn = SRI_END_OF_CELL; + + /* Successfully got a NAV packet */ + (*event) = DVDNAV_NAV_PACKET; +#ifdef LOG_DEBUG + fprintf(MSG_OUT, "libdvdnav: NAV_PACKET\n"); +#endif + (*len) = 2048; + this->cur_cell_time = dvdnav_convert_time(&this->dsi.dsi_gi.c_eltm); + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_OK; + } + + /* If we've got here, it must just be a normal block. */ + if(!this->file) { + printerr("Attempting to read without opening file."); + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_ERR; + } + + this->vobu.blockN++; + result = dvdnav_read_cache_block(this->cache, this->vobu.vobu_start + this->vobu.blockN, 1, buf); + if(result <= 0) { + printerr("Error reading from DVD."); + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_ERR; + } + (*event) = DVDNAV_BLOCK_OK; + (*len) = 2048; + + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_OK; +} + +dvdnav_status_t dvdnav_get_title_string(dvdnav_t *this, const char **title_str) { + (*title_str) = this->vm->dvd_name; + return DVDNAV_STATUS_OK; +} + +uint8_t dvdnav_get_video_aspect(dvdnav_t *this) { + uint8_t retval; + + if(!this->started) { + printerr("Virtual DVD machine not started."); + return -1; + } + + pthread_mutex_lock(&this->vm_lock); + retval = (uint8_t)vm_get_video_aspect(this->vm); + pthread_mutex_unlock(&this->vm_lock); + + return retval; +} + +uint8_t dvdnav_get_video_scale_permission(dvdnav_t *this) { + uint8_t retval; + + if(!this->started) { + printerr("Virtual DVD machine not started."); + return -1; + } + + pthread_mutex_lock(&this->vm_lock); + retval = (uint8_t)vm_get_video_scale_permission(this->vm); + pthread_mutex_unlock(&this->vm_lock); + + return retval; +} + +uint16_t dvdnav_audio_stream_to_lang(dvdnav_t *this, uint8_t stream) { + audio_attr_t attr; + + if(!this->started) { + printerr("Virtual DVD machine not started."); + return -1; + } + + pthread_mutex_lock(&this->vm_lock); + attr = vm_get_audio_attr(this->vm, stream); + pthread_mutex_unlock(&this->vm_lock); + + if(attr.lang_type != 1) + return 0xffff; + + return attr.lang_code; +} + +uint16_t dvdnav_audio_stream_format(dvdnav_t *this, uint8_t stream) { + audio_attr_t attr; + uint16_t format; + + if(!this->started) { + printerr("Virtual DVD machine not started."); + return -1; /* 0xffff */ + } + + pthread_mutex_lock(&this->vm_lock); + attr = vm_get_audio_attr(this->vm, stream); + pthread_mutex_unlock(&this->vm_lock); + + switch(attr.audio_format) { + case 0: + format = DVDNAV_FORMAT_AC3; + break; + case 2: /* MPEG-1 or MPEG-2 without extension bitstream. */ + case 3: /* MPEG-2 with extension bitstream. */ + format = DVDNAV_FORMAT_MPEGAUDIO; + break; + case 4: + format = DVDNAV_FORMAT_LPCM; + break; + case 6: + format = DVDNAV_FORMAT_DTS; + break; + case 7: + format = DVDNAV_FORMAT_SDDS; + break; + default: + format = 0xffff; + break; + } + + return format; +} + +uint16_t dvdnav_audio_stream_channels(dvdnav_t *this, uint8_t stream) { + audio_attr_t attr; + + if(!this->started) { + printerr("Virtual DVD machine not started."); + return -1; /* 0xffff */ + } + + pthread_mutex_lock(&this->vm_lock); + attr = vm_get_audio_attr(this->vm, stream); + pthread_mutex_unlock(&this->vm_lock); + + return attr.channels + 1; +} + +uint16_t dvdnav_spu_stream_to_lang(dvdnav_t *this, uint8_t stream) { + subp_attr_t attr; + + if(!this->started) { + printerr("Virtual DVD machine not started."); + return -1; + } + + pthread_mutex_lock(&this->vm_lock); + attr = vm_get_subp_attr(this->vm, stream); + pthread_mutex_unlock(&this->vm_lock); + + if(attr.type != 1) + return 0xffff; + + return attr.lang_code; +} + +int8_t dvdnav_get_audio_logical_stream(dvdnav_t *this, uint8_t audio_num) { + int8_t retval; + + if(!this->started) { + printerr("Virtual DVD machine not started."); + return -1; + } + + pthread_mutex_lock(&this->vm_lock); + if (!this->vm->state.pgc) { + printerr("No current PGC."); + pthread_mutex_unlock(&this->vm_lock); + return -1; + } + retval = vm_get_audio_stream(this->vm, audio_num); + pthread_mutex_unlock(&this->vm_lock); + + return retval; +} + +dvdnav_status_t dvdnav_get_audio_attr(dvdnav_t *this, uint8_t audio_num, audio_attr_t *audio_attr) { + if(!this->started) { + printerr("Virtual DVD machine not started."); + return -1; + } + pthread_mutex_lock(&this->vm_lock); + if (!this->vm->state.pgc) { + printerr("No current PGC."); + pthread_mutex_unlock(&this->vm_lock); + return -1; + } + *audio_attr=vm_get_audio_attr(this->vm, audio_num); + pthread_mutex_unlock(&this->vm_lock); + + return DVDNAV_STATUS_OK; +} + +int8_t dvdnav_get_spu_logical_stream(dvdnav_t *this, uint8_t subp_num) { + int8_t retval; + + if(!this->started) { + printerr("Virtual DVD machine not started."); + return -1; + } + + pthread_mutex_lock(&this->vm_lock); + if (!this->vm->state.pgc) { + printerr("No current PGC."); + pthread_mutex_unlock(&this->vm_lock); + return -1; + } + retval = vm_get_subp_stream(this->vm, subp_num, 0); + pthread_mutex_unlock(&this->vm_lock); + + return retval; +} + +dvdnav_status_t dvdnav_get_spu_attr(dvdnav_t *this, uint8_t audio_num, subp_attr_t *subp_attr) { + if(!this->started) { + printerr("Virtual DVD machine not started."); + return -1; + } + pthread_mutex_lock(&this->vm_lock); + if (!this->vm->state.pgc) { + printerr("No current PGC."); + pthread_mutex_unlock(&this->vm_lock); + return -1; + } + *subp_attr=vm_get_subp_attr(this->vm, audio_num); + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_OK; +} + +int8_t dvdnav_get_active_audio_stream(dvdnav_t *this) { + int8_t retval; + + if(!this->started) { + printerr("Virtual DVD machine not started."); + return -1; + } + + pthread_mutex_lock(&this->vm_lock); + if (!this->vm->state.pgc) { + printerr("No current PGC."); + pthread_mutex_unlock(&this->vm_lock); + return -1; + } + retval = vm_get_audio_active_stream(this->vm); + pthread_mutex_unlock(&this->vm_lock); + + return retval; +} + +int8_t dvdnav_get_active_spu_stream(dvdnav_t *this) { + int8_t retval; + + if(!this->started) { + printerr("Virtual DVD machine not started."); + return -1; + } + + pthread_mutex_lock(&this->vm_lock); + if (!this->vm->state.pgc) { + printerr("No current PGC."); + pthread_mutex_unlock(&this->vm_lock); + return -1; + } + retval = vm_get_subp_active_stream(this->vm, 0); + pthread_mutex_unlock(&this->vm_lock); + + return retval; +} + +static int8_t dvdnav_is_domain(dvdnav_t *this, domain_t domain) { + int8_t retval; + + if(!this->started) { + printerr("Virtual DVD machine not started."); + return -1; + } + + pthread_mutex_lock(&this->vm_lock); + retval = (this->vm->state.domain == domain); + pthread_mutex_unlock(&this->vm_lock); + + return retval; +} + +/* First Play domain. (Menu) */ +int8_t dvdnav_is_domain_fp(dvdnav_t *this) { + return dvdnav_is_domain(this, FP_DOMAIN); +} +/* Video management Menu domain. (Menu) */ +int8_t dvdnav_is_domain_vmgm(dvdnav_t *this) { + return dvdnav_is_domain(this, VMGM_DOMAIN); +} +/* Video Title Menu domain (Menu) */ +int8_t dvdnav_is_domain_vtsm(dvdnav_t *this) { + return dvdnav_is_domain(this, VTSM_DOMAIN); +} +/* Video Title domain (playing movie). */ +int8_t dvdnav_is_domain_vts(dvdnav_t *this) { + return dvdnav_is_domain(this, VTS_DOMAIN); +} + +/* Generally delegate angle information handling to VM */ +dvdnav_status_t dvdnav_angle_change(dvdnav_t *this, int32_t angle) { + int32_t num, current; + + pthread_mutex_lock(&this->vm_lock); + vm_get_angle_info(this->vm, ¤t, &num); + /* Set angle SPRM if valid */ + if((angle > 0) && (angle <= num)) { + this->vm->state.AGL_REG = angle; + } else { + printerr("Passed an invalid angle number."); + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_ERR; + } + pthread_mutex_unlock(&this->vm_lock); + + return DVDNAV_STATUS_OK; +} + +dvdnav_status_t dvdnav_get_angle_info(dvdnav_t *this, int32_t *current_angle, + int32_t *number_of_angles) { + pthread_mutex_lock(&this->vm_lock); + vm_get_angle_info(this->vm, current_angle, number_of_angles); + pthread_mutex_unlock(&this->vm_lock); + + return DVDNAV_STATUS_OK; +} + +pci_t* dvdnav_get_current_nav_pci(dvdnav_t *this) { + if(!this) return 0; + return &this->pci; +} + +dsi_t* dvdnav_get_current_nav_dsi(dvdnav_t *this) { + if(!this) return 0; + return &this->dsi; +} + +uint32_t dvdnav_get_next_still_flag(dvdnav_t *this) { + if(!this) return -1; + return this->position_next.still; +} + +user_ops_t dvdnav_get_restrictions(dvdnav_t* this) { + /* + * user_ops_t is a structure of 32 bits. We want to compute + * the union of two of those bitfields so to make this quicker + * than performing 32 ORs, we will access them as 32bits words. + */ + union { + user_ops_t ops_struct; + uint32_t ops_int; + } ops, tmp; + + ops.ops_int = 0; + + if(!this) { + printerr("Passed a NULL pointer."); + return ops.ops_struct; + } + if(!this->started) { + printerr("Virtual DVD machine not started."); + return ops.ops_struct; + } + + pthread_mutex_lock(&this->vm_lock); + tmp.ops_struct = this->pci.pci_gi.vobu_uop_ctl; + ops.ops_int |= tmp.ops_int; + + if(this->vm && this->vm->state.pgc) { + tmp.ops_struct = this->vm->state.pgc->prohibited_ops; + ops.ops_int |= tmp.ops_int; + } + pthread_mutex_unlock(&this->vm_lock); + + return ops.ops_struct; +} + +#ifdef _XBMC + +vm_t* dvdnav_get_vm(dvdnav_t *this) { + if(!this) return 0; + return this->vm; +} + +int dvdnav_get_nr_of_subtitle_streams(dvdnav_t *this) +{ + int i; + int count = 0; + + if (this && this->vm && this->vm->state.pgc) + { + for (i = 0; i < 32; i++) + { + if (this->vm->state.pgc->subp_control[i] & (1<<31)) count++; + } + } + return count; + + /* old code + if(!this || !this->vm || !this->vm->vtsi || !this->vm->vtsi->vtsi_mat) return 0; + + switch ((this->vm->state).domain) { + case VTS_DOMAIN: + return this->vm->vtsi->vtsi_mat->nr_of_vts_subp_streams; + case VTSM_DOMAIN: + return this->vm->vtsi->vtsi_mat->nr_of_vtsm_subp_streams; // 1 + case VMGM_DOMAIN: + case FP_DOMAIN: + return this->vm->vmgi->vmgi_mat->nr_of_vmgm_subp_streams; // 1 + } + + return 0; + */ +} + +int dvdnav_get_nr_of_audio_streams(dvdnav_t *this) +{ + int i; + int count = 0; + + if (this && this->vm && this->vm->state.pgc) + { + for (i = 0; i < 8; i++) + { + if (this->vm->state.pgc->audio_control[i] & (1<<15)) count++; + } + } + return count; + + /* old code + if(!this || !this->vm || !this->vm->vtsi || !this->vm->vtsi->vtsi_mat) return 0; + + switch ((this->vm->state).domain) { + case VTS_DOMAIN: + return this->vm->vtsi->vtsi_mat->nr_of_vts_audio_streams; + case VTSM_DOMAIN: + return this->vm->vtsi->vtsi_mat->nr_of_vtsm_audio_streams; // 1 + case VMGM_DOMAIN: + case FP_DOMAIN: + return this->vm->vmgi->vmgi_mat->nr_of_vmgm_audio_streams; // 1 + } + + return 0; + */ +} + +/* return the alpha and color for the current active button + * color, alpha [0][] = selection + * color, alpha = color + * + * argsize = [2][4] + */ +int dvdnav_get_button_info(dvdnav_t* this, int alpha[2][4], int color[2][4]) +{ + int current_button, current_button_color, i; + pci_t* pci; + + if (!this) return -1; + + pci = dvdnav_get_current_nav_pci(this); + if (!pci) return -1; + + dvdnav_get_current_highlight(this, ¤t_button); + current_button_color = pci->hli.btnit[current_button - 1].btn_coln; + + for (i = 0; i < 2; i++) + { + alpha[i][0] = pci->hli.btn_colit.btn_coli[current_button_color - 1][i] >> 0 & 0xf; + alpha[i][1] = pci->hli.btn_colit.btn_coli[current_button_color - 1][i] >> 4 & 0xf; + alpha[i][2] = pci->hli.btn_colit.btn_coli[current_button_color - 1][i] >> 8 & 0xf; + alpha[i][3] = pci->hli.btn_colit.btn_coli[current_button_color - 1][i] >> 12 & 0xf; + + color[i][0] = pci->hli.btn_colit.btn_coli[current_button_color - 1][i] >> 16 & 0xf; + color[i][1] = pci->hli.btn_colit.btn_coli[current_button_color - 1][i] >> 20 & 0xf; + color[i][2] = pci->hli.btn_colit.btn_coli[current_button_color - 1][i] >> 24 & 0xf; + color[i][3] = pci->hli.btn_colit.btn_coli[current_button_color - 1][i] >> 28 & 0xf; + } + + return 0; +} + +/* + * the next stuff is taken from ratdvd + */ + +#undef printerr +#define printerr(str) strncpy(self->err_str, str, MAX_ERR_LEN); + +dvdnav_status_t dvdnav_get_audio_info(dvdnav_t * self, int32_t streamid, audio_attr_t* audio_attributes) +{ + if(!self) { + printerr("Passed a NULL pointer."); + return -1; + } + if(!self->started) { + printerr("Virtual DVD machine not started."); + return -1; + } + + pthread_mutex_lock(&self->vm_lock); + audio_attr_t attributes = vm_get_audio_attr(self->vm,streamid); + pthread_mutex_unlock(&self->vm_lock); + audio_attributes->audio_format = attributes.audio_format; + audio_attributes->multichannel_extension = attributes.multichannel_extension; + audio_attributes->lang_type = attributes.lang_type; + audio_attributes->application_mode = attributes.application_mode; + audio_attributes->quantization = attributes.quantization; + audio_attributes->sample_frequency = attributes.sample_frequency; + audio_attributes->channels = attributes.channels; + audio_attributes->lang_code = attributes.lang_code; + audio_attributes->lang_extension = attributes.lang_extension; + audio_attributes->code_extension = attributes.code_extension; + audio_attributes->unknown3 = attributes.unknown3; + audio_attributes->app_info = attributes.app_info; + return DVDNAV_STATUS_OK; +} + +dvdnav_status_t dvdnav_get_stitle_info(dvdnav_t * self + , int32_t streamid, subp_attr_t* stitle_attributes) +{ + if(!self) { + printerr("Passed a NULL pointer."); + return -1; + } + if(!self->started) { + printerr("Virtual DVD machine not started."); + return -1; + } + + pthread_mutex_lock(&self->vm_lock); + subp_attr_t attributes = vm_get_subp_attr(self->vm,streamid); + pthread_mutex_unlock(&self->vm_lock); + stitle_attributes->code_mode = attributes.code_mode; + stitle_attributes->zero1 = attributes.zero1; + stitle_attributes->type = attributes.type; + stitle_attributes->zero2 = attributes.zero2; + stitle_attributes->lang_code = attributes.lang_code; + stitle_attributes->lang_extension = attributes.lang_extension; + stitle_attributes->code_extension = attributes.code_extension; + return DVDNAV_STATUS_OK; +} + +dvdnav_status_t dvdnav_get_video_info(dvdnav_t * self, video_attr_t* video_attributes) +{ + if(!self) { + printerr("Passed a NULL pointer."); + return -1; + } + if(!self->started) { + printerr("Virtual DVD machine not started."); + return -1; + } + + pthread_mutex_lock(&self->vm_lock); + video_attr_t attributes = vm_get_video_attr(self->vm); + pthread_mutex_unlock(&self->vm_lock); + + video_attributes->video_format = attributes.video_format; + video_attributes->permitted_df = attributes.permitted_df; + video_attributes->display_aspect_ratio = attributes.display_aspect_ratio; + video_attributes->mpeg_version = attributes.mpeg_version; + video_attributes->film_mode = attributes.film_mode; + video_attributes->letterboxed = attributes.letterboxed; + video_attributes->picture_size = attributes.picture_size; + video_attributes->bit_rate = attributes.bit_rate; + video_attributes->unknown1 = attributes.unknown1; + video_attributes->line21_cc_2 = attributes.line21_cc_2; + video_attributes->line21_cc_1 = attributes.line21_cc_1; + return DVDNAV_STATUS_OK; +} + +dvdnav_status_t dvdnav_audio_change(dvdnav_t *self, int32_t audio) +{ + int32_t num; + + if(!self) { + printerr("Passed a NULL pointer."); + return DVDNAV_STATUS_ERR; + } + + num = dvdnav_get_nr_of_audio_streams(self); + pthread_mutex_lock(&self->vm_lock); + /* Set subp AUDIO if valid */ + if((audio >= 0) && (audio <= num)) { + self->vm->state.AST_REG = audio; + } else { + //printerr("Passed an invalid audio number."); + pthread_mutex_unlock(&self->vm_lock); + return DVDNAV_STATUS_ERR; + } + pthread_mutex_unlock(&self->vm_lock); + + return DVDNAV_STATUS_OK; +} + +dvdnav_status_t dvdnav_subpicture_change(dvdnav_t *self, int32_t subpicture) +{ + int32_t num; + + if(!self) { + printerr("Passed a NULL pointer."); + return DVDNAV_STATUS_ERR; + } + + num = dvdnav_get_nr_of_subtitle_streams(self); + pthread_mutex_lock(&self->vm_lock); + /* Set subp SPRM if valid */ + if((subpicture >= 0) && (subpicture <= num)) { + self->vm->state.SPST_REG = subpicture | 0x40; + } else if (subpicture & 0x80) { + self->vm->state.SPST_REG = subpicture & ~0x80; + } else { + self->vm->state.SPST_REG = subpicture; + //printerr("Passed an invalid subpicture number."); + //pthread_mutex_unlock(&self->vm_lock); + //return DVDNAV_STATUS_ERR; + } + pthread_mutex_unlock(&self->vm_lock); + + return DVDNAV_STATUS_OK; +} + +void dvdnav_lock(dvdnav_t *self) +{ + // we do not check for null pointer problems + pthread_mutex_lock(&self->vm_lock); +} + +void dvdnav_unlock(dvdnav_t *self) +{ + // we do not check for null pointer problems + pthread_mutex_unlock(&self->vm_lock); +} + +#endif // _XBMC + diff --git a/lib/libdvd/libdvdnav/src/dvdnav.h b/lib/libdvd/libdvdnav/src/dvdnav.h new file mode 100644 index 0000000000..0a6d5db2cc --- /dev/null +++ b/lib/libdvd/libdvdnav/src/dvdnav.h @@ -0,0 +1,720 @@ +/* + * Copyright (C) 2001 Rich Wareham <richwareham@users.sourceforge.net> + * + * This file is part of libdvdnav, a DVD navigation library. + * + * libdvdnav 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. + * + * libdvdnav 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 + * + * $Id: dvdnav.h 1135 2008-09-06 21:55:51Z rathann $ + * + */ + +/* + * This is the main header file applications should include if they want + * to access dvdnav functionality. + */ + +#ifndef DVDNAV_H_INCLUDED +#define DVDNAV_H_INCLUDED + +#define MP_DVDNAV 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef DVDNAV_COMPILE +# include <dvdnav/dvd_types.h> +# include <dvdread/dvd_reader.h> +# include <dvdread/nav_types.h> +# include <dvdread/ifo_types.h> /* For vm_cmd_t */ +# include <dvdnav/dvdnav_events.h> +#endif + + + +/********************************************************************* + * dvdnav data types * + *********************************************************************/ + +/* + * Opaque data-type can be viewed as a 'DVD handle'. You should get + * a pointer to a dvdnav_t from the dvdnav_open() function. + * Never call free() on the pointer, you have to give it back with + * dvdnav_close(). + */ +typedef struct dvdnav_s dvdnav_t; + +/* Status as reported by most of libdvdnav's functions */ +typedef int32_t dvdnav_status_t; + +/* + * Unless otherwise stated, all functions return DVDNAV_STATUS_OK if + * they succeeded, otherwise DVDNAV_STATUS_ERR is returned and the error may + * be obtained by calling dvdnav_err_to_string(). + */ +#define DVDNAV_STATUS_ERR 0 +#define DVDNAV_STATUS_OK 1 + +#define DVDNAV_FORMAT_AC3 0 +#define DVDNAV_FORMAT_MPEGAUDIO 3 +#define DVDNAV_FORMAT_LPCM 4 +#define DVDNAV_FORMAT_DTS 5 +#define DVDNAV_FORMAT_SDDS 6 + +/********************************************************************* + * initialisation & housekeeping functions * + *********************************************************************/ + +/* + * These functions allow you to open a DVD device and associate it + * with a dvdnav_t. + */ + +/* + * Attempts to open the DVD drive at the specified path and pre-cache + * the CSS-keys. libdvdread is used to access the DVD, so any source + * supported by libdvdread can be given with "path". Currently, + * libdvdread can access: DVD drives, DVD image files, DVD file-by-file + * copies. + * + * The resulting dvdnav_t handle will be written to *dest. + */ +dvdnav_status_t dvdnav_open(dvdnav_t **dest, const char *path); + +/* + * Closes a dvdnav_t previously opened with dvdnav_open(), freeing any + * memory associated with it. + */ +dvdnav_status_t dvdnav_close(dvdnav_t *self); + +/* + * Resets the DVD virtual machine and cache buffers. + */ +dvdnav_status_t dvdnav_reset(dvdnav_t *self); + +/* + * Fills a pointer with a value pointing to a string describing + * the path associated with an open dvdnav_t. It assigns *path to NULL + * on error. + */ +dvdnav_status_t dvdnav_path(dvdnav_t *self, const char **path); + +/* + * Returns a human-readable string describing the last error. + */ +const char* dvdnav_err_to_string(dvdnav_t *self); + + +/********************************************************************* + * changing and reading DVD player characteristics * + *********************************************************************/ + +/* + * These functions allow you to manipulate the various global characteristics + * of the DVD playback engine. + */ + +/* + * Sets the region mask (bit 0 set implies region 1, bit 1 set implies + * region 2, etc) of the virtual machine. Generally you will only need to set + * this if you are playing RCE discs which query the virtual machine as to its + * region setting. + * + * This has _nothing_ to do with the region setting of the DVD drive. + */ +dvdnav_status_t dvdnav_set_region_mask(dvdnav_t *self, int32_t region_mask); + +/* + * Returns the region mask (bit 0 set implies region 1, bit 1 set implies + * region 2, etc) of the virtual machine. + * + * This has _nothing_ to do with the region setting of the DVD drive. + */ +dvdnav_status_t dvdnav_get_region_mask(dvdnav_t *self, int32_t *region_mask); + +/* + * Specify whether read-ahead caching should be used. You may not want this if your + * decoding engine does its own buffering. + * + * The default read-ahead cache does not use an additional thread for the reading + * (see read_cache.c for a threaded cache, but note that this code is currently + * unmaintained). It prebuffers on VOBU level by reading ahead several buffers + * on every read request. The speed of this prebuffering has been optimized to + * also work on slow DVD drives. + * + * If in addition you want to prevent memcpy's to improve performance, have a look + * at dvdnav_get_next_cache_block(). + */ +dvdnav_status_t dvdnav_set_readahead_flag(dvdnav_t *self, int32_t read_ahead_flag); + +/* + * Query whether read-ahead caching/buffering will be used. + */ +dvdnav_status_t dvdnav_get_readahead_flag(dvdnav_t *self, int32_t *read_ahead_flag); + +/* + * Specify whether the positioning works PGC or PG based. + * Programs (PGs) on DVDs are similar to Chapters and a program chain (PGC) + * usually covers a whole feature. This affects the behaviour of the + * functions dvdnav_get_position() and dvdnav_sector_search(). See there. + * Default is PG based positioning. + */ +dvdnav_status_t dvdnav_set_PGC_positioning_flag(dvdnav_t *self, int32_t pgc_based_flag); + +/* + * Query whether positioning is PG or PGC based. + */ +dvdnav_status_t dvdnav_get_PGC_positioning_flag(dvdnav_t *self, int32_t *pgc_based_flag); + + +/********************************************************************* + * reading data * + *********************************************************************/ + +/* + * These functions are used to poll the playback enginge and actually get data + * off the DVD. + */ + +/* + * Attempts to get the next block off the DVD and copies it into the buffer 'buf'. + * If there is any special actions that may need to be performed, the value + * pointed to by 'event' gets set accordingly. + * + * If 'event' is DVDNAV_BLOCK_OK then 'buf' is filled with the next block + * (note that means it has to be at /least/ 2048 bytes big). 'len' is + * then set to 2048. + * + * Otherwise, buf is filled with an appropriate event structure and + * len is set to the length of that structure. + * + * See the dvdnav_events.h header for information on the various events. + */ +dvdnav_status_t dvdnav_get_next_block(dvdnav_t *self, uint8_t *buf, + int32_t *event, int32_t *len); + +/* + * This basically does the same as dvdnav_get_next_block. The only difference is + * that it avoids a memcopy, when the requested block was found in the cache. + * I such a case (cache hit) this function will return a different pointer than + * the one handed in, pointing directly into the relevant block in the cache. + * Those pointers must _never_ be freed but instead returned to the library via + * dvdnav_free_cache_block(). + */ +dvdnav_status_t dvdnav_get_next_cache_block(dvdnav_t *self, uint8_t **buf, + int32_t *event, int32_t *len); + +/* + * All buffers which came from the internal cache (when dvdnav_get_next_cache_block() + * returned a buffer different from the one handed in) have to be freed with this + * function. Although handing in other buffers not from the cache doesn't cause any harm. + */ +dvdnav_status_t dvdnav_free_cache_block(dvdnav_t *self, unsigned char *buf); + +/* + * If we are currently in a still-frame this function skips it. + * + * See also the DVDNAV_STILL_FRAME event. + */ +dvdnav_status_t dvdnav_still_skip(dvdnav_t *self); + +/* + * If we are currently in WAIT state, that is: the application is required to + * wait for its fifos to become empty, calling this signals libdvdnav that this + * is achieved and that it can continue. + * + * See also the DVDNAV_WAIT event. + */ +dvdnav_status_t dvdnav_wait_skip(dvdnav_t *self); + +/* + * Returns the still time from the currently playing cell. + * The still time is given in seconds with 0xff meaning an indefinite still. + * + * This function can be used to detect still frames before they are reached. + * Some players might need this to prepare for a frame to be shown for a + * longer time than usual. + */ +uint32_t dvdnav_get_next_still_flag(dvdnav_t *self); + +/* + * Stops playback. The next event obtained with one of the get_next_block + * functions will be a DVDNAV_STOP event. + * + * It is not required to call this before dvdnav_close(). + */ +dvdnav_status_t dvdnav_stop(dvdnav_t *self); + + +/********************************************************************* + * title/part navigation * + *********************************************************************/ + +/* + * Returns the number of titles on the disk. + */ +dvdnav_status_t dvdnav_get_number_of_titles(dvdnav_t *self, int32_t *titles); + +/* + * Returns the number of parts within the given title. + */ +dvdnav_status_t dvdnav_get_number_of_parts(dvdnav_t *self, int32_t title, int32_t *parts); + +/* + * Plays the specified title of the DVD from its beginning (that is: part 1). + */ +dvdnav_status_t dvdnav_title_play(dvdnav_t *self, int32_t title); + +/* + * Plays the specified title, starting from the specified part. + */ +dvdnav_status_t dvdnav_part_play(dvdnav_t *self, int32_t title, int32_t part); + +/* + * Stores in *times an array (that the application *must* free) of + * dvdtimes corresponding to the chapter times for the chosen title. + * *duration will have the duration of the title + * The number of entries in *times is the result of the function. + * On error *times is NULL and the output is 0 + */ +uint32_t dvdnav_describe_title_chapters(dvdnav_t *self, int32_t title, uint64_t **times, uint64_t *duration); + +/* + * Play the specified amount of parts of the specified title of + * the DVD then STOP. + * + * Currently unimplemented! + */ +dvdnav_status_t dvdnav_part_play_auto_stop(dvdnav_t *self, int32_t title, + int32_t part, int32_t parts_to_play); + +/* + * Play the specified title starting from the specified time. + * + * Currently unimplemented! + */ +dvdnav_status_t dvdnav_time_play(dvdnav_t *self, int32_t title, + uint64_t time); + +/* + * Stop playing the current position and jump to the specified menu. + * + * See also DVDMenuID_t from libdvdread + */ +dvdnav_status_t dvdnav_menu_call(dvdnav_t *self, DVDMenuID_t menu); + +/* + * Return the title number and part currently being played. + * A title of 0 indicates, we are in a menu. In this case, part + * is set to the current menu's ID. + */ +dvdnav_status_t dvdnav_current_title_info(dvdnav_t *self, int32_t *title, + int32_t *part); + +/* + * Return the current position (in blocks) within the current + * title and the length (in blocks) of said title. + * + * Current implementation is wrong and likely to behave unpredictably! + * Use is discouraged! + */ +dvdnav_status_t dvdnav_get_position_in_title(dvdnav_t *self, + uint32_t *pos, + uint32_t *len); + +/* + * This function is only available for compatibility reasons. + * + * Stop playing the current position and start playback of the current title + * from the specified part. + */ +dvdnav_status_t dvdnav_part_search(dvdnav_t *self, int32_t part); + + +/********************************************************************* + * program chain/program navigation * + *********************************************************************/ + +/* + * Stop playing the current position and start playback from the last + * VOBU boundary before the given sector. The sector number is not + * meant to be an absolute physical DVD sector, but a relative sector + * in the current program. This function cannot leave the current + * program and will fail, if asked to do so. + * + * If program chain based positioning is enabled + * (see dvdnav_set_PGC_positioning_flag()), this will seek to the relative + * sector inside the current program chain. + * + * 'origin' can be one of SEEK_SET, SEEK_CUR, SEEK_END as defined in + * fcntl.h. + */ +dvdnav_status_t dvdnav_sector_search(dvdnav_t *self, + uint64_t offset, int32_t origin); + +/* + returns the current stream time in PTS ticks as reported by the IFO structures + divide it by 90000 to get the current play time in seconds + */ +int64_t dvdnav_get_current_time(dvdnav_t *self); + +/* + * Stop playing the current position and start playback of the title + * from the specified timecode. + * + * Currently unimplemented! + */ +dvdnav_status_t dvdnav_time_search(dvdnav_t *self, + uint64_t time); + +/* + * Stop playing current position and play the "GoUp"-program chain. + * (which generally leads to the title menu or a higer-level menu). + */ +dvdnav_status_t dvdnav_go_up(dvdnav_t *self); + +/* + * Stop playing the current position and start playback at the + * previous program (if it exists). + */ +dvdnav_status_t dvdnav_prev_pg_search(dvdnav_t *self); + +/* + * Stop playing the current position and start playback at the + * first program. + */ +dvdnav_status_t dvdnav_top_pg_search(dvdnav_t *self); + +/* + * Stop playing the current position and start playback at the + * next program (if it exists). + */ +dvdnav_status_t dvdnav_next_pg_search(dvdnav_t *self); + +/* + * Return the current position (in blocks) within the current + * program and the length (in blocks) of current program. + * + * If program chain based positioning is enabled + * (see dvdnav_set_PGC_positioning_flag()), this will return the + * relative position in and the length of the current program chain. + */ +dvdnav_status_t dvdnav_get_position(dvdnav_t *self, uint32_t *pos, + uint32_t *len); + + +/********************************************************************* + * menu highlights * + *********************************************************************/ + +/* + * Most functions related to highlights take a NAV PCI packet as a parameter. + * While you can get the such a packet from libdvdnav, for players with internal + * FIFOs, this will result in errors, because due to the FIFO length, libdvdnav will + * be ahead in the stream compared to what the user is seeing on screen. + * Therefore, player applications who have a NAV packet available, which is + * better in sync with the actual playback should always pass this one to these + * functions. + */ + +/* + * Get the currently highlighted button + * number (1..36) or 0 if no button is highlighted. + */ +dvdnav_status_t dvdnav_get_current_highlight(dvdnav_t *self, int32_t *button); + +/* + * Returns the Presentation Control Information (PCI) structure associated + * with the current position. + * + * Read the general notes above. + * See also libdvdreads nav_types.h for definition of pci_t. + */ +pci_t* dvdnav_get_current_nav_pci(dvdnav_t *self); + +/* + * Returns the DSI (data search information) structure associated + * with the current position. + * + * Read the general notes above. + * See also libdvdreads nav_types.h for definition of dsi_t. + */ +dsi_t* dvdnav_get_current_nav_dsi(dvdnav_t *self); + +/* + * Get the area associated with a certain button. + */ +dvdnav_status_t dvdnav_get_highlight_area(pci_t *nav_pci , int32_t button, int32_t mode, + dvdnav_highlight_area_t *highlight); + +/* + * Move button highlight around as suggested by function name (e.g. with arrow keys). + */ +dvdnav_status_t dvdnav_upper_button_select(dvdnav_t *self, pci_t *pci); +dvdnav_status_t dvdnav_lower_button_select(dvdnav_t *self, pci_t *pci); +dvdnav_status_t dvdnav_right_button_select(dvdnav_t *self, pci_t *pci); +dvdnav_status_t dvdnav_left_button_select(dvdnav_t *self, pci_t *pci); + +/* + * Activate ("press") the currently highlighted button. + */ +dvdnav_status_t dvdnav_button_activate(dvdnav_t *self, pci_t *pci); + +/* + * Highlight a specific button. + */ +dvdnav_status_t dvdnav_button_select(dvdnav_t *self, pci_t *pci, int32_t button); + +/* + * Activate ("press") specified button. + */ +dvdnav_status_t dvdnav_button_select_and_activate(dvdnav_t *self, pci_t *pci, int32_t button); + +/* + * Activate (press) a button and execute specified command. + */ +dvdnav_status_t dvdnav_button_activate_cmd(dvdnav_t *self, int32_t button, vm_cmd_t *cmd); + +/* + * Select button at specified video frame coordinates. + */ +dvdnav_status_t dvdnav_mouse_select(dvdnav_t *self, pci_t *pci, int32_t x, int32_t y); + +/* + * Activate ("press") button at specified video frame coordinates. + */ +dvdnav_status_t dvdnav_mouse_activate(dvdnav_t *self, pci_t *pci, int32_t x, int32_t y); + + +/********************************************************************* + * languages * + *********************************************************************/ + +/* + * The language codes expected by these functions are two character + * codes as defined in ISO639. + */ + +/* + * Set which menu language we should use per default. + */ +dvdnav_status_t dvdnav_menu_language_select(dvdnav_t *self, + char *code); + +/* + * Set which audio language we should use per default. + */ +dvdnav_status_t dvdnav_audio_language_select(dvdnav_t *self, + char *code); + +/* + * Set which spu language we should use per default. + */ +dvdnav_status_t dvdnav_spu_language_select(dvdnav_t *self, + char *code); + + +/********************************************************************* + * obtaining stream attributes * + *********************************************************************/ + +/* + * Return a string describing the title of the DVD. + * This is an ID string encoded on the disc by the author. In many cases + * this is a descriptive string such as `THE_MATRIX' but sometimes is sigularly + * uninformative such as `PDVD-011421'. Some DVD authors even forget to set this, + * so you may also read the default of the authoring software they used, like + * `DVDVolume'. + */ +dvdnav_status_t dvdnav_get_title_string(dvdnav_t *self, const char **title_str); + +/* + * Get video aspect code. + * The aspect code does only change on VTS boundaries. + * See the DVDNAV_VTS_CHANGE event. + * + * 0 -- 4:3, 2 -- 16:9 + */ +uint8_t dvdnav_get_video_aspect(dvdnav_t *self); + +/* + * Get video scaling permissions. + * The scaling permission does only change on VTS boundaries. + * See the DVDNAV_VTS_CHANGE event. + * + * bit0 set = deny letterboxing, bit1 set = deny pan&scan + */ +uint8_t dvdnav_get_video_scale_permission(dvdnav_t *self); + +/* + * Converts a *logical* audio stream id into language code + * (returns 0xffff if no such stream). + */ +uint16_t dvdnav_audio_stream_to_lang(dvdnav_t *self, uint8_t stream); + +/* + * Returns the format of *logical* audio stream 'stream' + * (returns 0xffff if no such stream). + */ +uint16_t dvdnav_audio_stream_format(dvdnav_t *self, uint8_t stream); + +/* + * Returns number of channelsn in *logical* audio stream 'stream' + * (returns 0xffff if no such stream). + */ +uint16_t dvdnav_audio_stream_channels(dvdnav_t *self, uint8_t stream); + +/* + * Converts a *logical* subpicture stream id into country code + * (returns 0xffff if no such stream). + */ +uint16_t dvdnav_spu_stream_to_lang(dvdnav_t *self, uint8_t stream); + +/* + * Converts a *physical* (MPEG) audio stream id into a logical stream number. + */ +int8_t dvdnav_get_audio_logical_stream(dvdnav_t *self, uint8_t audio_num); + +#define HAVE_GET_AUDIO_ATTR +/* + * Get audio attr + */ +dvdnav_status_t dvdnav_get_audio_attr(dvdnav_t *self, uint8_t audio_mum, audio_attr_t *audio_attr); + +/* + * Converts a *physical* (MPEG) subpicture stream id into a logical stream number. + */ +int8_t dvdnav_get_spu_logical_stream(dvdnav_t *self, uint8_t subp_num); + +#define HAVE_GET_SPU_ATTR +/* + * Get spu attr + */ +dvdnav_status_t dvdnav_get_spu_attr(dvdnav_t *self, uint8_t audio_mum, subp_attr_t *subp_attr); + +/* + * Get active audio stream. + */ +int8_t dvdnav_get_active_audio_stream(dvdnav_t *self); + +/* + * Get active spu stream. + */ +int8_t dvdnav_get_active_spu_stream(dvdnav_t *self); + +/* + * Get the set of user operations that are currently prohibited. + * There are potentially new restrictions right after + * DVDNAV_CHANNEL_HOP and DVDNAV_NAV_PACKET. + */ +user_ops_t dvdnav_get_restrictions(dvdnav_t *self); + + +/********************************************************************* + * multiple angles * + *********************************************************************/ + +/* + * The libdvdnav library abstracts away the difference between seamless and + * non-seamless angles. From the point of view of the programmer you just set the + * angle number and all is well in the world. You will always see only the + * selected angle coming from the get_next_block functions. + * + * Note: + * It is quite possible that some tremendously strange DVD feature might change the + * angle number from under you. Generally you should always view the results from + * dvdnav_get_angle_info() as definitive only up to the next time you call + * dvdnav_get_next_block(). + */ + +/* + * Sets the current angle. If you try to follow a non existant angle + * the call fails. + */ +dvdnav_status_t dvdnav_angle_change(dvdnav_t *self, int32_t angle); + +/* + * Returns the current angle and number of angles present. + */ +dvdnav_status_t dvdnav_get_angle_info(dvdnav_t *self, int32_t *current_angle, + int32_t *number_of_angles); + +/********************************************************************* + * domain queries * + *********************************************************************/ + +/* + * Are we in the First Play domain? + */ +int8_t dvdnav_is_domain_fp(dvdnav_t *self); + +/* + * Are we in the Video management Menu domain? + */ +int8_t dvdnav_is_domain_vmgm(dvdnav_t *self); + +/* + * Are we in the Video Title Menu domain? + */ +int8_t dvdnav_is_domain_vtsm(dvdnav_t *self); + +/* + * Are we in the Video Title Set domain? + */ +int8_t dvdnav_is_domain_vts(dvdnav_t *self); + +////////// RATDVD stuff /////////////// + +/* + * Get the number of audio streams. + */ +int32_t dvdnav_get_audio_stream_count(dvdnav_t * self); + +/* + * Get the number of subpicture streams. + */ +int32_t dvdnav_get_subpicture_stream_count(dvdnav_t * self); + +/* + * Get attributes of the current audio stream. + */ +dvdnav_status_t dvdnav_get_audio_info(dvdnav_t * self, int32_t streamid, audio_attr_t* audio_attributes); + +/* + * Get attributes of the current subpicture stream. + */ +dvdnav_status_t dvdnav_get_stitle_info(dvdnav_t * self, int32_t streamid, subp_attr_t* stitle_attributes); + +/* + * Get information about the current video stream + */ +dvdnav_status_t dvdnav_get_video_info(dvdnav_t * self, video_attr_t* video_attributes); + +/* + * Select the audio stream to be played + */ +dvdnav_status_t dvdnav_audio_change(dvdnav_t *self, int32_t audio); + +/* + * Select the spu stream to be displayed + */ +dvdnav_status_t dvdnav_subpicture_change(dvdnav_t *self, int32_t subpicture); + +#ifdef __cplusplus +} +#endif + +#endif /* DVDNAV_H_INCLUDED */ diff --git a/lib/libdvd/libdvdnav/src/dvdnav_events.h b/lib/libdvd/libdvdnav/src/dvdnav_events.h new file mode 100644 index 0000000000..a4d460eeca --- /dev/null +++ b/lib/libdvd/libdvdnav/src/dvdnav_events.h @@ -0,0 +1,239 @@ +/* + * Copyright (C) 2001 Rich Wareham <richwareham@users.sourceforge.net> + * + * This file is part of libdvdnav, a DVD navigation library. + * + * libdvdnav 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. + * + * libdvdnav 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 + * + * $Id: dvdnav_events.h 1135 2008-09-06 21:55:51Z rathann $ + * + */ + +/* + * This header defines events and event types + */ + +#ifndef DVDNAV_EVENTS_H_INCLUDED +#define DVDNAV_EVENTS_H_INCLUDED + +/* + * DVDNAV_BLOCK_OK + * + * A regular data block from the DVD has been returned. + * This one should be demuxed and decoded for playback. + */ +#define DVDNAV_BLOCK_OK 0 + + +/* + * DVDNAV_NOP + * + * Just ignore this. + */ +#define DVDNAV_NOP 1 + + +/* + * DVDNAV_STILL_FRAME + * + * We have reached a still frame. The player application should wait + * the amount of time specified by the still's length while still handling + * user input to make menus and other interactive stills work. + * The last delivered frame should be kept showing. + * Once the still has timed out, call dvdnav_skip_still(). + * A length of 0xff means an infinite still which has to be skipped + * indirectly by some user interaction. + */ +#define DVDNAV_STILL_FRAME 2 + +typedef struct { + /* The length (in seconds) the still frame should be displayed for, + * or 0xff if infinite. */ + int length; +} dvdnav_still_event_t; + + +/* + * DVDNAV_SPU_STREAM_CHANGE + * + * Inform the SPU decoding/overlaying engine to switch SPU channels. + */ +#define DVDNAV_SPU_STREAM_CHANGE 3 + +typedef struct { + /* The physical (MPEG) stream number for widescreen SPU display. + * Use this, if you blend the SPU on an anamorphic image before + * unsqueezing it. */ + int physical_wide; + + /* The physical (MPEG) stream number for letterboxed display. + * Use this, if you blend the SPU on an anamorphic image after + * unsqueezing it. */ + int physical_letterbox; + + /* The physical (MPEG) stream number for pan&scan display. + * Use this, if you blend the SPU on an anamorphic image after + * unsqueezing it the pan&scan way. */ + int physical_pan_scan; + + /* The logical (DVD) stream number. */ + int logical; +} dvdnav_spu_stream_change_event_t; + + +/* + * DVDNAV_AUDIO_STREAM_CHANGE + * + * Inform the audio decoder to switch channels. + */ +#define DVDNAV_AUDIO_STREAM_CHANGE 4 + +typedef struct { + /* The physical (MPEG) stream number. */ + int physical; + + /* The logical (DVD) stream number. */ + int logical; +} dvdnav_audio_stream_change_event_t; + + +/* + * DVDNAV_VTS_CHANGE + * + * Some status information like video aspect and video scale permissions do + * not change inside a VTS. Therefore this event can be used to query such + * information only when necessary and update the decoding/displaying + * accordingly. + */ +#define DVDNAV_VTS_CHANGE 5 + +typedef struct { + int old_vtsN; /* the old VTS number */ + dvd_read_domain_t old_domain; /* the old domain */ + int new_vtsN; /* the new VTS number */ + dvd_read_domain_t new_domain; /* the new domain */ +} dvdnav_vts_change_event_t; + + +/* + * DVDNAV_CELL_CHANGE + * + * Some status information like the current Title and Part numbers do not + * change inside a cell. Therefore this event can be used to query such + * information only when necessary and update the decoding/displaying + * accordingly. + * Some useful information for accurate time display is also reported + * together with this event. + */ +#define DVDNAV_CELL_CHANGE 6 + +typedef struct { + int cellN; /* the new cell number */ + int pgN; /* the current program number */ + int64_t cell_length; /* the length of the current cell in PTS ticks */ + int64_t pg_length; /* the length of the current program in PTS ticks */ + int64_t pgc_length; /* the length of the current program chain in PTS ticks */ + int64_t cell_start; /* the start time of the current cell relatively to the PGC in PTS ticks */ + int64_t pg_start; /* the start time of the current PG relatively to the PGC in PTS ticks */ +} dvdnav_cell_change_event_t; + + +/* + * DVDNAV_NAV_PACKET + * + * NAV packets are useful for various purposes. They define the button + * highlight areas and VM commands of DVD menus, so they should in any + * case be sent to the SPU decoder/overlaying engine for the menus to work. + * NAV packets also provide a way to detect PTS discontinuities, because + * they carry the start and end PTS values for the current VOBU. + * (pci.vobu_s_ptm and pci.vobu_e_ptm) Whenever the start PTS of the + * current NAV does not match the end PTS of the previous NAV, a PTS + * discontinuity has occured. + * NAV packets can also be used for time display, because they are + * timestamped relatively to the current Cell. + */ +#define DVDNAV_NAV_PACKET 7 + + +/* + * DVDNAV_STOP + * + * Applications should end playback here. A subsequent dvdnav_get_next_block() + * call will restart the VM from the beginning of the DVD. + */ +#define DVDNAV_STOP 8 + + +/* + * DVDNAV_HIGHLIGHT + * + * The current button highlight changed. Inform the overlaying engine to + * highlight a different button. Please note, that at the moment only mode 1 + * highlights are reported this way. That means, when the button highlight + * has been moved around by some function call, you will receive an event + * telling you the new button. But when a button gets activated, you have + * to handle the mode 2 highlighting (that is some different colour the + * button turns to on activation) in your application. + */ +#define DVDNAV_HIGHLIGHT 9 + +typedef struct { + /* highlight mode: 0 - hide, 1 - show, 2 - activate, currently always 1 */ + int display; + + /* FIXME: these fields are currently not set */ + uint32_t palette; /* The CLUT entries for the highlight palette + (4-bits per entry -> 4 entries) */ + uint16_t sx,sy,ex,ey; /* The start/end x,y positions */ + uint32_t pts; /* Highlight PTS to match with SPU */ + + /* button number for the SPU decoder/overlaying engine */ + uint32_t buttonN; +} dvdnav_highlight_event_t; + + +/* + * DVDNAV_SPU_CLUT_CHANGE + * + * Inform the SPU decoder/overlaying engine to update its colour lookup table. + * The CLUT is given as 16 uint32_t's in the buffer. + */ +#define DVDNAV_SPU_CLUT_CHANGE 10 + + +/* + * DVDNAV_HOP_CHANNEL + * + * A non-seamless operation has been performed. Applications can drop all + * their internal fifo's content, which will speed up the response. + */ +#define DVDNAV_HOP_CHANNEL 12 + + +/* + * DVDNAV_WAIT + * + * We have reached a point in DVD playback, where timing is critical. + * Player application with internal fifos can introduce state + * inconsistencies, because libdvdnav is always the fifo's length + * ahead in the stream compared to what the application sees. + * Such applications should wait until their fifos are empty + * when they receive this type of event. + * Once this is achieved, call dvdnav_skip_wait(). + */ +#define DVDNAV_WAIT 13 + + +#endif /* DVDNAV_EVENTS_H_INCLUDED */ diff --git a/lib/libdvd/libdvdnav/src/dvdnav_internal.h b/lib/libdvd/libdvdnav/src/dvdnav_internal.h new file mode 100644 index 0000000000..996723ea7e --- /dev/null +++ b/lib/libdvd/libdvdnav/src/dvdnav_internal.h @@ -0,0 +1,218 @@ +/* + * Copyright (C) 2001-2004 Rich Wareham <richwareham@users.sourceforge.net> + * + * This file is part of libdvdnav, a DVD navigation library. + * + * libdvdnav 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. + * + * libdvdnav 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 + * + * $Id: dvdnav_internal.h 1135 2008-09-06 21:55:51Z rathann $ + * + */ + +#ifndef DVDNAV_INTERNAL_H_INCLUDED +#define DVDNAV_INTERNAL_H_INCLUDED + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* Uncomment for VM command tracing */ +/* #define TRACE */ + +#include "decoder.h" +#include "dvdnav.h" +#include "vm.h" +#include "vmcmd.h" + +#ifdef WIN32 + +/* pthread_mutex_* wrapper for win32 */ +#include <windows.h> +#include <process.h> +typedef CRITICAL_SECTION pthread_mutex_t; +#define pthread_mutex_init(a, b) InitializeCriticalSection(a) +#define pthread_mutex_lock(a) EnterCriticalSection(a) +#define pthread_mutex_unlock(a) LeaveCriticalSection(a) +#define pthread_mutex_destroy(a) + +#ifndef HAVE_GETTIMEOFDAY +/* replacement gettimeofday implementation */ +#include <sys/timeb.h> +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 + +#include <io.h> /* read() */ +#define lseek64 _lseeki64 + +#else + +#include <pthread.h> + +#endif /* WIN32 */ + +/* where should libdvdnav write its messages (stdout/stderr) */ +#define MSG_OUT stdout + +/* Maximum length of an error string */ +#define MAX_ERR_LEN 255 + +/* Use the POSIX PATH_MAX if available */ +#ifdef PATH_MAX +#define MAX_PATH_LEN PATH_MAX +#else +#define MAX_PATH_LEN 255 /* Arbitrary */ +#endif + +#ifndef DVD_VIDEO_LB_LEN +#define DVD_VIDEO_LB_LEN 2048 +#endif + +typedef struct read_cache_s read_cache_t; + +/* + * These are defined here because they are + * not in ifo_types.h, they maybe one day + */ + +#ifndef audio_status_t +typedef struct { +#ifdef WORDS_BIGENDIAN + unsigned int available : 1; + unsigned int zero1 : 4; + unsigned int stream_number : 3; + uint8_t zero2; +#else + uint8_t zero2; + unsigned int stream_number : 3; + unsigned int zero1 : 4; + unsigned int available : 1; +#endif +} ATTRIBUTE_PACKED audio_status_t; +#endif + +#ifndef spu_status_t +typedef struct { +#ifdef WORDS_BIGENDIAN + unsigned int available : 1; + unsigned int zero1 : 2; + unsigned int stream_number_4_3 : 5; + unsigned int zero2 : 3; + unsigned int stream_number_wide : 5; + unsigned int zero3 : 3; + unsigned int stream_number_letterbox : 5; + unsigned int zero4 : 3; + unsigned int stream_number_pan_scan : 5; +#else + unsigned int stream_number_pan_scan : 5; + unsigned int zero4 : 3; + unsigned int stream_number_letterbox : 5; + unsigned int zero3 : 3; + unsigned int stream_number_wide : 5; + unsigned int zero2 : 3; + unsigned int stream_number_4_3 : 5; + unsigned int zero1 : 2; + unsigned int available : 1; +#endif +} ATTRIBUTE_PACKED spu_status_t; +#endif + +typedef struct dvdnav_vobu_s { + int32_t vobu_start; /* Logical Absolute. MAX needed is 0x300000 */ + int32_t vobu_length; + int32_t blockN; /* Relative offset */ + int32_t vobu_next; /* Relative offset */ +} dvdnav_vobu_t; + +/** The main DVDNAV type **/ + +struct dvdnav_s { + /* General data */ + char path[MAX_PATH_LEN]; /* Path to DVD device/dir */ + dvd_file_t *file; /* Currently opened file */ + + /* Position data */ + vm_position_t position_next; + vm_position_t position_current; + dvdnav_vobu_t vobu; + + /* NAV data */ + pci_t pci; + dsi_t dsi; + uint32_t last_cmd_nav_lbn; /* detects when a command is issued on an already left NAV */ + + /* Flags */ + int skip_still; /* Set when skipping a still */ + int sync_wait; /* applications should wait till they are in sync with us */ + int sync_wait_skip; /* Set when skipping wait state */ + int spu_clut_changed; /* The SPU CLUT changed */ + int started; /* vm_start has been called? */ + int use_read_ahead; /* 1 - use read-ahead cache, 0 - don't */ + int pgc_based; /* positioning works PGC based instead of PG based */ + int cur_cell_time; /* time expired since the beginning of the current cell, read from the dsi */ + + /* VM */ + vm_t *vm; + pthread_mutex_t vm_lock; + + /* Read-ahead cache */ + read_cache_t *cache; + + /* Errors */ + char err_str[MAX_ERR_LEN]; +}; + +/** HELPER FUNCTIONS **/ + +/* converts a dvd_time_t to PTS ticks */ +int64_t dvdnav_convert_time(dvd_time_t *time); + +/* + * Get current playback state + */ +dvdnav_status_t dvdnav_get_state(dvdnav_t *this, dvd_state_t *save_state); + +/* + * Resume playback state + */ +dvdnav_status_t dvdnav_set_state(dvdnav_t *this, dvd_state_t *save_state); + + + +/** USEFUL MACROS **/ + +#ifdef __GNUC__ +#define printerrf(format, args...) \ + do { if (this) snprintf(this->err_str, MAX_ERR_LEN, format, ## args); } while (0) +#else +#ifdef _MSC_VER +#define printerrf(str) \ + do { if (this) snprintf(this->err_str, MAX_ERR_LEN, str); } while (0) +#else +#define printerrf(...) \ + do { if (this) snprintf(this->err_str, MAX_ERR_LEN, __VA_ARGS__); } while (0) +#endif /* WIN32 */ +#endif +#define printerr(str) \ + do { if (this) strncpy(this->err_str, str, MAX_ERR_LEN - 1); } while (0) + +#endif /* DVDNAV_INTERNAL_H_INCLUDED */ diff --git a/lib/libdvd/libdvdnav/src/highlight.c b/lib/libdvd/libdvdnav/src/highlight.c new file mode 100644 index 0000000000..bdf652a5b2 --- /dev/null +++ b/lib/libdvd/libdvdnav/src/highlight.c @@ -0,0 +1,497 @@ +/* + * Copyright (C) 2000 Rich Wareham <richwareham@users.sourceforge.net> + * + * This file is part of libdvdnav, a DVD navigation library. + * + * libdvdnav 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. + * + * libdvdnav 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 + * + * $Id: highlight.c 1135 2008-09-06 21:55:51Z rathann $ + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <assert.h> +#include <inttypes.h> +#include <stdlib.h> +#include <stdio.h> +#include <limits.h> +#include <string.h> +#include <sys/time.h> +#include <dvdread/nav_types.h> +#include "dvd_types.h" +#include "remap.h" +#include "vm/decoder.h" +#include "vm/vm.h" +#include "vm/vmcmd.h" +#include "dvdnav_internal.h" +#include "dvdnav.h" + +/* +#define BUTTON_TESTING +*/ + +#ifdef BUTTON_TESTING + +#include "nav_print.h" + +static void 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); + + fprintf(MSG_OUT,"%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: + rate = "(please send a bug report)"; + break; + } + fprintf(MSG_OUT," @ %s fps", rate); +} + +static void nav_print_PCI_GI(pci_gi_t *pci_gi) { + int32_t i; + + fprintf(MSG_OUT,"libdvdnav: pci_gi:\n"); + fprintf(MSG_OUT,"libdvdnav: nv_pck_lbn 0x%08x\n", pci_gi->nv_pck_lbn); + fprintf(MSG_OUT,"libdvdnav: vobu_cat 0x%04x\n", pci_gi->vobu_cat); + fprintf(MSG_OUT,"libdvdnav: vobu_uop_ctl 0x%08x\n", *(uint32_t*)&pci_gi->vobu_uop_ctl); + fprintf(MSG_OUT,"libdvdnav: vobu_s_ptm 0x%08x\n", pci_gi->vobu_s_ptm); + fprintf(MSG_OUT,"libdvdnav: vobu_e_ptm 0x%08x\n", pci_gi->vobu_e_ptm); + fprintf(MSG_OUT,"libdvdnav: vobu_se_e_ptm 0x%08x\n", pci_gi->vobu_se_e_ptm); + fprintf(MSG_OUT,"libdvdnav: e_eltm "); + print_time(&pci_gi->e_eltm); + fprintf(MSG_OUT,"\n"); + + fprintf(MSG_OUT,"libdvdnav: vobu_isrc \""); + for(i = 0; i < 32; i++) { + char c = pci_gi->vobu_isrc[i]; + if((c >= ' ') && (c <= '~')) + fprintf(MSG_OUT,"%c", c); + else + fprintf(MSG_OUT,"."); + } + fprintf(MSG_OUT,"\"\n"); +} + +static void nav_print_NSML_AGLI(nsml_agli_t *nsml_agli) { + int32_t i, j = 0; + + for(i = 0; i < 9; i++) + j |= nsml_agli->nsml_agl_dsta[i]; + if(j == 0) + return; + + fprintf(MSG_OUT,"libdvdnav: nsml_agli:\n"); + for(i = 0; i < 9; i++) + if(nsml_agli->nsml_agl_dsta[i]) + fprintf(MSG_OUT,"libdvdnav: nsml_agl_c%d_dsta 0x%08x\n", i + 1, + nsml_agli->nsml_agl_dsta[i]); +} + +static void nav_print_HL_GI(hl_gi_t *hl_gi, int32_t *btngr_ns, int32_t *btn_ns) { + + if((hl_gi->hli_ss & 0x03) == 0) + return; + + fprintf(MSG_OUT,"libdvdnav: hl_gi:\n"); + fprintf(MSG_OUT,"libdvdnav: hli_ss 0x%01x\n", hl_gi->hli_ss & 0x03); + fprintf(MSG_OUT,"libdvdnav: hli_s_ptm 0x%08x\n", hl_gi->hli_s_ptm); + fprintf(MSG_OUT,"libdvdnav: hli_e_ptm 0x%08x\n", hl_gi->hli_e_ptm); + fprintf(MSG_OUT,"libdvdnav: btn_se_e_ptm 0x%08x\n", hl_gi->btn_se_e_ptm); + + *btngr_ns = hl_gi->btngr_ns; + fprintf(MSG_OUT,"libdvdnav: btngr_ns %d\n", hl_gi->btngr_ns); + fprintf(MSG_OUT,"libdvdnav: btngr%d_dsp_ty 0x%02x\n", 1, hl_gi->btngr1_dsp_ty); + fprintf(MSG_OUT,"libdvdnav: btngr%d_dsp_ty 0x%02x\n", 2, hl_gi->btngr2_dsp_ty); + fprintf(MSG_OUT,"libdvdnav: btngr%d_dsp_ty 0x%02x\n", 3, hl_gi->btngr3_dsp_ty); + + fprintf(MSG_OUT,"libdvdnav: btn_ofn %d\n", hl_gi->btn_ofn); + *btn_ns = hl_gi->btn_ns; + fprintf(MSG_OUT,"libdvdnav: btn_ns %d\n", hl_gi->btn_ns); + fprintf(MSG_OUT,"libdvdnav: nsl_btn_ns %d\n", hl_gi->nsl_btn_ns); + fprintf(MSG_OUT,"libdvdnav: fosl_btnn %d\n", hl_gi->fosl_btnn); + fprintf(MSG_OUT,"libdvdnav: foac_btnn %d\n", hl_gi->foac_btnn); +} + +static void nav_print_BTN_COLIT(btn_colit_t *btn_colit) { + int32_t i, j; + + j = 0; + for(i = 0; i < 6; i++) + j |= btn_colit->btn_coli[i/2][i&1]; + if(j == 0) + return; + + fprintf(MSG_OUT,"libdvdnav: btn_colit:\n"); + for(i = 0; i < 3; i++) + for(j = 0; j < 2; j++) + fprintf(MSG_OUT,"libdvdnav: btn_cqoli %d %s_coli: %08x\n", + i, (j == 0) ? "sl" : "ac", + btn_colit->btn_coli[i][j]); +} + +static void nav_print_BTNIT(btni_t *btni_table, int32_t btngr_ns, int32_t btn_ns) { + int32_t i, j, k; + + fprintf(MSG_OUT,"libdvdnav: btnit:\n"); + fprintf(MSG_OUT,"libdvdnav: btngr_ns: %i\n", btngr_ns); + fprintf(MSG_OUT,"libdvdnav: 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]; + + fprintf(MSG_OUT,"libdvdnav: group %d btni %d: ", i+1, j+1); + fprintf(MSG_OUT,"btn_coln %d, auto_action_mode %d\n", + btni->btn_coln, btni->auto_action_mode); + fprintf(MSG_OUT,"libdvdnav: coords (%d, %d) .. (%d, %d)\n", + btni->x_start, btni->y_start, btni->x_end, btni->y_end); + + fprintf(MSG_OUT,"libdvdnav: up %d, ", btni->up); + fprintf(MSG_OUT,"down %d, ", btni->down); + fprintf(MSG_OUT,"left %d, ", btni->left); + fprintf(MSG_OUT,"right %d\n", btni->right); + for(k = 0; k < 8; k++) { + fprintf(MSG_OUT, "libdvdnav: %02x ", btni->cmd.bytes[k]); + } + fprintf(MSG_OUT, "| "); +#ifdef TRACE + vm_print_mnemonic(&btni->cmd); +#endif + fprintf(MSG_OUT, "\n"); + } + } + } +} + +static void nav_print_HLI(hli_t *hli) { + int32_t btngr_ns = 0, btn_ns = 0; + + fprintf(MSG_OUT,"libdvdnav: hli:\n"); + nav_print_HL_GI(&hli->hl_gi, & btngr_ns, & btn_ns); + nav_print_BTN_COLIT(&hli->btn_colit); + nav_print_BTNIT(hli->btnit, btngr_ns, btn_ns); +} + +void nav_print_PCI(pci_t *pci) { + fprintf(MSG_OUT,"libdvdnav: pci packet:\n"); + nav_print_PCI_GI(&pci->pci_gi); + nav_print_NSML_AGLI(&pci->nsml_agli); + nav_print_HLI(&pci->hli); +} + +#endif + + +/* Highlighting API calls */ + +dvdnav_status_t dvdnav_get_current_highlight(dvdnav_t *this, int32_t *button) { + /* Simply return the appropriate value based on the SPRM */ + if(((*button) = this->position_current.button) == -1) + (*button) = this->vm->state.HL_BTNN_REG >> 10; + + return DVDNAV_STATUS_OK; +} + +static btni_t *get_current_button(dvdnav_t *this, pci_t *pci) { + int32_t button = 0; + + if(!pci->hli.hl_gi.hli_ss) { + printerr("Not in a menu."); + return NULL; + } + if(this->last_cmd_nav_lbn == pci->pci_gi.nv_pck_lbn) { + printerr("This NAV has already been left."); + return NULL; + } + + button = this->vm->state.HL_BTNN_REG >> 10; +#ifdef BUTTON_TESTING + nav_print_PCI(pci); +#endif + + return &(pci->hli.btnit[button-1]); +} + +static dvdnav_status_t button_auto_action(dvdnav_t *this, pci_t *pci) { + if (get_current_button(this, pci)->auto_action_mode) + return dvdnav_button_activate(this, pci); + return DVDNAV_STATUS_OK; +} + +dvdnav_status_t dvdnav_upper_button_select(dvdnav_t *this, pci_t *pci) { + btni_t *button_ptr; + + if(!(button_ptr = get_current_button(this, pci))) + return DVDNAV_STATUS_ERR; + + dvdnav_button_select(this, pci, button_ptr->up); + return button_auto_action(this, pci); +} + +dvdnav_status_t dvdnav_lower_button_select(dvdnav_t *this, pci_t *pci) { + btni_t *button_ptr; + + if(!(button_ptr = get_current_button(this, pci))) + return DVDNAV_STATUS_ERR; + + dvdnav_button_select(this, pci, button_ptr->down); + return button_auto_action(this, pci); +} + +dvdnav_status_t dvdnav_right_button_select(dvdnav_t *this, pci_t *pci) { + btni_t *button_ptr; + + if(!(button_ptr = get_current_button(this, pci))) + return DVDNAV_STATUS_ERR; + + dvdnav_button_select(this, pci, button_ptr->right); + return button_auto_action(this, pci); +} + +dvdnav_status_t dvdnav_left_button_select(dvdnav_t *this, pci_t *pci) { + btni_t *button_ptr; + + if(!(button_ptr = get_current_button(this, pci))) + return DVDNAV_STATUS_ERR; + + dvdnav_button_select(this, pci, button_ptr->left); + return button_auto_action(this, pci); +} + +dvdnav_status_t dvdnav_get_highlight_area(pci_t *nav_pci , int32_t button, int32_t mode, + dvdnav_highlight_area_t *highlight) { + btni_t *button_ptr; + +#ifdef BUTTON_TESTING + fprintf(MSG_OUT, "libdvdnav: Button get_highlight_area %i\n", button); +#endif + + if(!nav_pci->hli.hl_gi.hli_ss) + return DVDNAV_STATUS_ERR; + if((button <= 0) || (button > nav_pci->hli.hl_gi.btn_ns)) + return DVDNAV_STATUS_ERR; + + + button_ptr = &nav_pci->hli.btnit[button-1]; + + highlight->sx = button_ptr->x_start; + highlight->sy = button_ptr->y_start; + highlight->ex = button_ptr->x_end; + highlight->ey = button_ptr->y_end; + if(button_ptr->btn_coln != 0) { + highlight->palette = nav_pci->hli.btn_colit.btn_coli[button_ptr->btn_coln-1][mode]; + } else { + highlight->palette = 0; + } + highlight->pts = nav_pci->hli.hl_gi.hli_s_ptm; + highlight->buttonN = button; +#ifdef BUTTON_TESTING + fprintf(MSG_OUT, "libdvdnav: highlight: Highlight area is (%u,%u)-(%u,%u), display = %i, button = %u\n", + button_ptr->x_start, button_ptr->y_start, + button_ptr->x_end, button_ptr->y_end, + 1, + button); +#endif + + return DVDNAV_STATUS_OK; +} + +dvdnav_status_t dvdnav_button_activate(dvdnav_t *this, pci_t *pci) { + int32_t button; + btni_t *button_ptr = NULL; + + if(!pci->hli.hl_gi.hli_ss) { + printerr("Not in a menu."); + return DVDNAV_STATUS_ERR; + } + if(this->last_cmd_nav_lbn == pci->pci_gi.nv_pck_lbn) { + printerr("This NAV has already been left."); + return DVDNAV_STATUS_ERR; + } + pthread_mutex_lock(&this->vm_lock); + + button = this->vm->state.HL_BTNN_REG >> 10; + + if((button <= 0) || (button > pci->hli.hl_gi.btn_ns)) { + /* Special code to handle still menus with no buttons. + * The navigation is expected to report to the application that a STILL is + * underway. In turn, the application is supposed to report to the user + * that the playback is paused. The user is then expected to undo the pause, + * ie: hit play. At that point, the navigation should release the still and + * go to the next Cell. + * Explanation by Mathieu Lacage <mathieu_lacage@realmagic.fr> + * Code added by jcdutton. + */ + if (this->position_current.still != 0) { + /* In still, but no buttons. */ + vm_get_next_cell(this->vm); + this->position_current.still = 0; + this->sync_wait = 0; + this->last_cmd_nav_lbn = pci->pci_gi.nv_pck_lbn; + pthread_mutex_unlock(&this->vm_lock); + /* clear error message */ + printerr(""); + return DVDNAV_STATUS_OK; + } + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_ERR; + } + + button_ptr = get_current_button(this, pci); + /* Finally, make the VM execute the appropriate code and probably + * scedule a jump */ +#ifdef BUTTON_TESTING + fprintf(MSG_OUT, "libdvdnav: Evaluating Button Activation commands.\n"); +#endif + if(vm_exec_cmd(this->vm, &(button_ptr->cmd)) == 1) { + /* Command caused a jump */ + this->vm->hop_channel++; + this->position_current.still = 0; + this->last_cmd_nav_lbn = pci->pci_gi.nv_pck_lbn; + } + + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_OK; +} + +dvdnav_status_t dvdnav_button_activate_cmd(dvdnav_t *this, int32_t button, vm_cmd_t *cmd) +{ + pthread_mutex_lock(&this->vm_lock); + /* make the VM execute the appropriate code and probably + * schedule a jump */ +#ifdef BUTTON_TESTING + fprintf(MSG_OUT, "libdvdnav: dvdnav_button_activate_cmd: Evaluating Button Activation commands.\n"); +#endif + if(button > 0) { + this->vm->state.HL_BTNN_REG = (button << 10); + if(vm_exec_cmd(this->vm, cmd) == 1) { + /* Command caused a jump */ + this->vm->hop_channel++; + } + } + /* Always remove still, because some still menus have no buttons. */ + this->position_current.still = 0; + this->sync_wait = 0; + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_OK; +} + +dvdnav_status_t dvdnav_button_select(dvdnav_t *this, pci_t *pci, int32_t button) { + if(!pci->hli.hl_gi.hli_ss) { + printerr("Not in a menu."); + return DVDNAV_STATUS_ERR; + } + if(this->last_cmd_nav_lbn == pci->pci_gi.nv_pck_lbn) { + printerr("This NAV has already been left."); + return DVDNAV_STATUS_ERR; + } + +#ifdef BUTTON_TESTING + fprintf(MSG_OUT, "libdvdnav: Button select %i\n", button); +#endif + + if((button <= 0) || (button > pci->hli.hl_gi.btn_ns)) { + printerr("Button does not exist."); + return DVDNAV_STATUS_ERR; + } + + this->vm->state.HL_BTNN_REG = (button << 10); + this->position_current.button = -1; /* Force Highligh change */ + + return DVDNAV_STATUS_OK; +} + +dvdnav_status_t dvdnav_button_select_and_activate(dvdnav_t *this, pci_t *pci, + int32_t button) { + /* A trivial function */ + if(dvdnav_button_select(this, pci, button) != DVDNAV_STATUS_ERR) + return dvdnav_button_activate(this, pci); + return DVDNAV_STATUS_ERR; +} + +dvdnav_status_t dvdnav_mouse_select(dvdnav_t *this, pci_t *pci, int32_t x, int32_t y) { + int32_t button, cur_button; + int32_t best,dist,d; + int32_t mx,my,dx,dy; + + if(!pci->hli.hl_gi.hli_ss) { + printerr("Not in a menu."); + return DVDNAV_STATUS_ERR; + } + if(this->last_cmd_nav_lbn == pci->pci_gi.nv_pck_lbn) { + printerr("This NAV has already been left."); + return DVDNAV_STATUS_ERR; + } + + cur_button = this->vm->state.HL_BTNN_REG >> 10; + + best = 0; + dist = 0x08000000; /* >> than (720*720)+(567*567); */ + + /* Loop through all buttons */ + for(button = 1; button <= pci->hli.hl_gi.btn_ns; button++) { + btni_t *button_ptr = &(pci->hli.btnit[button-1]); + + if((x >= button_ptr->x_start) && (x <= button_ptr->x_end) && + (y >= button_ptr->y_start) && (y <= button_ptr->y_end)) { + mx = (button_ptr->x_start + button_ptr->x_end)/2; + my = (button_ptr->y_start + button_ptr->y_end)/2; + dx = mx - x; + dy = my - y; + d = (dx*dx) + (dy*dy); + /* If the mouse is within the button and the mouse is closer + * to the center of this button then it is the best choice. */ + if(d < dist) { + dist = d; + best = button; + } + } + } + /* As an efficiency measure, only re-select the button + * if it is different to the previously selected one. */ + if (best != 0 && best != cur_button) + dvdnav_button_select(this, pci, best); + + /* return DVDNAV_STATUS_OK only if we actually found a matching button */ + return best ? DVDNAV_STATUS_OK : DVDNAV_STATUS_ERR; +} + +dvdnav_status_t dvdnav_mouse_activate(dvdnav_t *this, pci_t *pci, int32_t x, int32_t y) { + /* A trivial function */ + if(dvdnav_mouse_select(this, pci, x,y) != DVDNAV_STATUS_ERR) + return dvdnav_button_activate(this, pci); + return DVDNAV_STATUS_ERR; +} diff --git a/lib/libdvd/libdvdnav/src/navigation.c b/lib/libdvd/libdvdnav/src/navigation.c new file mode 100644 index 0000000000..e28cb640bb --- /dev/null +++ b/lib/libdvd/libdvdnav/src/navigation.c @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2000 Rich Wareham <richwareham@users.sourceforge.net> + * + * This file is part of libdvdnav, a DVD navigation library. + * + * libdvdnav 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. + * + * libdvdnav 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 + * + * $Id: navigation.c 1135 2008-09-06 21:55:51Z rathann $ + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <inttypes.h> +#include <limits.h> +#include <string.h> +#include <sys/time.h> +#include "dvd_types.h" +#include <dvdread/nav_types.h> +#include <dvdread/ifo_types.h> +#include "remap.h" +#include "vm/decoder.h" +#include "vm/vm.h" +#include "dvdnav.h" +#include "dvdnav_internal.h" + +/* Navigation API calls */ + +dvdnav_status_t dvdnav_still_skip(dvdnav_t *this) { + pthread_mutex_lock(&this->vm_lock); + this->position_current.still = 0; + pthread_mutex_unlock(&this->vm_lock); + this->skip_still = 1; + this->sync_wait = 0; + this->sync_wait_skip = 1; + + return DVDNAV_STATUS_OK; +} + +dvdnav_status_t dvdnav_wait_skip(dvdnav_t *this) { + this->sync_wait = 0; + this->sync_wait_skip = 1; + + return DVDNAV_STATUS_OK; +} + +dvdnav_status_t dvdnav_get_number_of_titles(dvdnav_t *this, int32_t *titles) { + if (!this->vm->vmgi) { + printerr("Bad VM state."); + return DVDNAV_STATUS_ERR; + } + + (*titles) = vm_get_vmgi(this->vm)->tt_srpt->nr_of_srpts; + + return DVDNAV_STATUS_OK; +} + +dvdnav_status_t dvdnav_get_number_of_parts(dvdnav_t *this, int32_t title, int32_t *parts) { + if (!this->vm->vmgi) { + printerr("Bad VM state."); + return DVDNAV_STATUS_ERR; + } + if ((title < 1) || (title > vm_get_vmgi(this->vm)->tt_srpt->nr_of_srpts) ) { + printerr("Passed a title number out of range."); + return DVDNAV_STATUS_ERR; + } + + (*parts) = vm_get_vmgi(this->vm)->tt_srpt->title[title-1].nr_of_ptts; + + return DVDNAV_STATUS_OK; +} + +dvdnav_status_t dvdnav_current_title_info(dvdnav_t *this, int32_t *title, int32_t *part) { + int32_t retval; + + pthread_mutex_lock(&this->vm_lock); + if (!this->vm->vtsi || !this->vm->vmgi) { + printerr("Bad VM state."); + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_ERR; + } + if (!this->started) { + printerr("Virtual DVD machine not started."); + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_ERR; + } + if (!this->vm->state.pgc) { + printerr("No current PGC."); + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_ERR; + } + if ( (this->vm->state.domain == VTSM_DOMAIN) + || (this->vm->state.domain == VMGM_DOMAIN) ) { + /* Get current Menu ID: into *part. */ + if(! vm_get_current_menu(this->vm, part)) { + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_ERR; + } + if (*part > -1) { + *title = 0; + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_OK; + } + } + if (this->vm->state.domain == VTS_DOMAIN) { + retval = vm_get_current_title_part(this->vm, title, part); + pthread_mutex_unlock(&this->vm_lock); + return retval ? DVDNAV_STATUS_OK : DVDNAV_STATUS_ERR; + } + printerr("Not in a title or menu."); + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_ERR; +} + +dvdnav_status_t dvdnav_title_play(dvdnav_t *this, int32_t title) { + return dvdnav_part_play(this, title, 1); +} + +dvdnav_status_t dvdnav_part_play(dvdnav_t *this, int32_t title, int32_t part) { + int32_t retval; + + pthread_mutex_lock(&this->vm_lock); + if (!this->vm->vmgi) { + printerr("Bad VM state."); + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_ERR; + } + if (!this->started) { + /* don't report an error but be nice */ + vm_start(this->vm); + this->started = 1; + } + if (!this->vm->state.pgc) { + printerr("No current PGC."); + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_ERR; + } + if((title < 1) || (title > this->vm->vmgi->tt_srpt->nr_of_srpts)) { + printerr("Title out of range."); + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_ERR; + } + if((part < 1) || (part > this->vm->vmgi->tt_srpt->title[title-1].nr_of_ptts)) { + printerr("Part out of range."); + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_ERR; + } + + retval = vm_jump_title_part(this->vm, title, part); + if (retval) + this->vm->hop_channel++; + pthread_mutex_unlock(&this->vm_lock); + + return retval ? DVDNAV_STATUS_OK : DVDNAV_STATUS_ERR; +} + +dvdnav_status_t dvdnav_part_play_auto_stop(dvdnav_t *this, int32_t title, + int32_t part, int32_t parts_to_play) { + /* FIXME: Implement auto-stop */ + if (dvdnav_part_play(this, title, part) == DVDNAV_STATUS_OK) + printerr("Not implemented yet."); + return DVDNAV_STATUS_ERR; +} + +dvdnav_status_t dvdnav_time_play(dvdnav_t *this, int32_t title, + uint64_t time) { + /* FIXME: Implement */ + printerr("Not implemented yet."); + return DVDNAV_STATUS_ERR; +} + +dvdnav_status_t dvdnav_stop(dvdnav_t *this) { + pthread_mutex_lock(&this->vm_lock); + this->vm->stopped = 1; + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_OK; +} + +dvdnav_status_t dvdnav_go_up(dvdnav_t *this) { + /* A nice easy function... delegate to the VM */ + pthread_mutex_lock(&this->vm_lock); + vm_jump_up(this->vm); + pthread_mutex_unlock(&this->vm_lock); + + return DVDNAV_STATUS_OK; +} diff --git a/lib/libdvd/libdvdnav/src/read_cache.c b/lib/libdvd/libdvdnav/src/read_cache.c new file mode 100644 index 0000000000..b5e16f0784 --- /dev/null +++ b/lib/libdvd/libdvdnav/src/read_cache.c @@ -0,0 +1,356 @@ +/* + * Copyright (C) 2000 Rich Wareham <richwareham@users.sourceforge.net> + * 2001-2004 the dvdnav project + * + * This file is part of libdvdnav, a DVD navigation library. + * + * libdvdnav 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. + * + * libdvdnav 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 + * + * $Id: read_cache.c 1135 2008-09-06 21:55:51Z rathann $ + * + */ +/* + * There was a multithreaded read ahead cache in here for some time, but + * it had only been used for a short time. If you want to have a look at it, + * search the CVS attic. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <inttypes.h> +#include <stdlib.h> +#include <limits.h> +#include <sys/time.h> +#include <time.h> +#include "dvd_types.h" +#include <dvdread/nav_types.h> +#include <dvdread/ifo_types.h> +#include "remap.h" +#include "vm/decoder.h" +#include "vm/vm.h" +#include "dvdnav.h" +#include "dvdnav_internal.h" +#include "read_cache.h" + +#define READ_CACHE_CHUNKS 10 + +/* all cache chunks must be memory aligned to allow use of raw devices */ +#define ALIGNMENT 2048 + +#define READ_AHEAD_SIZE_MIN 4 +#define READ_AHEAD_SIZE_MAX 512 + +typedef struct read_cache_chunk_s { + uint8_t *cache_buffer; + uint8_t *cache_buffer_base; /* used in malloc and free for alignment */ + int32_t cache_start_sector; /* -1 means cache invalid */ + int32_t cache_read_count; /* this many sectors are already read */ + size_t cache_block_count; /* this many sectors will go in this chunk */ + size_t cache_malloc_size; + int cache_valid; + int usage_count; /* counts how many buffers where issued from this chunk */ +} read_cache_chunk_t; + +struct read_cache_s { + read_cache_chunk_t chunk[READ_CACHE_CHUNKS]; + int current; + int freeing; /* is set to one when we are about to dispose the cache */ + uint32_t read_ahead_size; + int read_ahead_incr; + int last_sector; + pthread_mutex_t lock; + + /* Bit of strange cross-linking going on here :) -- Gotta love C :) */ + dvdnav_t *dvd_self; +}; + +/* +#define READ_CACHE_TRACE 0 +*/ + +#ifdef __GNUC__ +# if READ_CACHE_TRACE +# define dprintf(fmt, args...) fprintf(MSG_OUT, "libdvdnav: %s: "fmt, __func__ , ## args) +# else +# define dprintf(fmt, args...) /* Nowt */ +# endif +#else +# if READ_CACHE_TRACE +# define dprintf(fmt, ...) fprintf(MSG_OUT, "libdvdnav: %s: "fmt, __func__ , __VA_ARGS__) +# else +#ifdef _MSC_VER +# define dprintf(fmt, str) /* Nowt */ +#else +# define dprintf(fmt, ...) /* Nowt */ +#endif /* _MSC_VER */ +# endif +#endif + + +read_cache_t *dvdnav_read_cache_new(dvdnav_t* dvd_self) { + read_cache_t *self; + int i; + + self = (read_cache_t *)malloc(sizeof(read_cache_t)); + + if(self) { + self->current = 0; + self->freeing = 0; + self->dvd_self = dvd_self; + self->last_sector = 0; + self->read_ahead_size = READ_AHEAD_SIZE_MIN; + self->read_ahead_incr = 0; + pthread_mutex_init(&self->lock, NULL); + dvdnav_read_cache_clear(self); + for (i = 0; i < READ_CACHE_CHUNKS; i++) { + self->chunk[i].cache_buffer = NULL; + self->chunk[i].usage_count = 0; + } + } + + return self; +} + +void dvdnav_read_cache_free(read_cache_t* self) { + dvdnav_t *tmp; + int i; + + pthread_mutex_lock(&self->lock); + self->freeing = 1; + for (i = 0; i < READ_CACHE_CHUNKS; i++) + if (self->chunk[i].cache_buffer && self->chunk[i].usage_count == 0) { + free(self->chunk[i].cache_buffer_base); + self->chunk[i].cache_buffer = NULL; + } + pthread_mutex_unlock(&self->lock); + + for (i = 0; i < READ_CACHE_CHUNKS; i++) + if (self->chunk[i].cache_buffer) return; + + /* all buffers returned, free everything */ + tmp = self->dvd_self; + pthread_mutex_destroy(&self->lock); + free(self); + free(tmp); +} + +/* This function MUST be called whenever self->file changes. */ +void dvdnav_read_cache_clear(read_cache_t *self) { + int i; + + if(!self) + return; + + pthread_mutex_lock(&self->lock); + for (i = 0; i < READ_CACHE_CHUNKS; i++) + self->chunk[i].cache_valid = 0; + pthread_mutex_unlock(&self->lock); +} + +/* This function is called just after reading the NAV packet. */ +void dvdnav_pre_cache_blocks(read_cache_t *self, int sector, size_t block_count) { + int i, use; + + if(!self) + return; + + if(!self->dvd_self->use_read_ahead) + return; + + pthread_mutex_lock(&self->lock); + + /* find a free cache chunk that best fits the required size */ + use = -1; + for (i = 0; i < READ_CACHE_CHUNKS; i++) + if (self->chunk[i].usage_count == 0 && self->chunk[i].cache_buffer && + self->chunk[i].cache_malloc_size >= block_count && + (use == -1 || self->chunk[use].cache_malloc_size > self->chunk[i].cache_malloc_size)) + use = i; + + if (use == -1) { + /* we haven't found a cache chunk, so we try to reallocate an existing one */ + for (i = 0; i < READ_CACHE_CHUNKS; i++) + if (self->chunk[i].usage_count == 0 && self->chunk[i].cache_buffer && + (use == -1 || self->chunk[use].cache_malloc_size < self->chunk[i].cache_malloc_size)) + use = i; + if (use >= 0) { + self->chunk[use].cache_buffer_base = realloc(self->chunk[use].cache_buffer_base, + block_count * DVD_VIDEO_LB_LEN + ALIGNMENT); + self->chunk[use].cache_buffer = + (uint8_t *)(((uintptr_t)self->chunk[use].cache_buffer_base & ~((uintptr_t)(ALIGNMENT - 1))) + ALIGNMENT); + dprintf("pre_cache DVD read realloc happened\n"); + self->chunk[use].cache_malloc_size = block_count; + } else { + /* we still haven't found a cache chunk, let's allocate a new one */ + for (i = 0; i < READ_CACHE_CHUNKS; i++) + if (!self->chunk[i].cache_buffer) { + use = i; + break; + } + if (use >= 0) { + /* We start with a sensible figure for the first malloc of 500 blocks. + * Some DVDs I have seen venture to 450 blocks. + * This is so that fewer realloc's happen if at all. + */ + self->chunk[i].cache_buffer_base = + malloc((block_count > 500 ? block_count : 500) * DVD_VIDEO_LB_LEN + ALIGNMENT); + self->chunk[i].cache_buffer = + (uint8_t *)(((uintptr_t)self->chunk[i].cache_buffer_base & ~((uintptr_t)(ALIGNMENT - 1))) + ALIGNMENT); + self->chunk[i].cache_malloc_size = block_count > 500 ? block_count : 500; + dprintf("pre_cache DVD read malloc %d blocks\n", + (block_count > 500 ? block_count : 500 )); + } + } + } + + if (use >= 0) { + self->chunk[use].cache_start_sector = sector; + self->chunk[use].cache_block_count = block_count; + self->chunk[use].cache_read_count = 0; + self->chunk[use].cache_valid = 1; + self->current = use; + } else { + dprintf("pre_caching was impossible, no cache chunk available\n"); + } + pthread_mutex_unlock(&self->lock); +} + +int dvdnav_read_cache_block(read_cache_t *self, int sector, size_t block_count, uint8_t **buf) { + int i, use; + int start; + int size; + int incr; + uint8_t *read_ahead_buf; + int32_t res; + + if(!self) + return 0; + + use = -1; + + if(self->dvd_self->use_read_ahead) { + /* first check, if sector is in current chunk */ + read_cache_chunk_t cur = self->chunk[self->current]; + if (cur.cache_valid && sector >= cur.cache_start_sector && + sector <= (cur.cache_start_sector + cur.cache_read_count) && + sector + block_count <= cur.cache_start_sector + cur.cache_block_count) + use = self->current; + else + for (i = 0; i < READ_CACHE_CHUNKS; i++) + if (self->chunk[i].cache_valid && + sector >= self->chunk[i].cache_start_sector && + sector <= (self->chunk[i].cache_start_sector + self->chunk[i].cache_read_count) && + sector + block_count <= self->chunk[i].cache_start_sector + self->chunk[i].cache_block_count) + use = i; + } + + if (use >= 0) { + read_cache_chunk_t *chunk; + + /* Increment read-ahead size if sector follows the last sector */ + if (sector == (self->last_sector + 1)) { + if (self->read_ahead_incr < READ_AHEAD_SIZE_MAX) + self->read_ahead_incr++; + } else { + self->read_ahead_size = READ_AHEAD_SIZE_MIN; + self->read_ahead_incr = 0; + } + self->last_sector = sector; + + /* The following resources need to be protected by a mutex : + * self->chunk[*].cache_buffer + * self->chunk[*].cache_malloc_size + * self->chunk[*].usage_count + */ + pthread_mutex_lock(&self->lock); + chunk = &self->chunk[use]; + read_ahead_buf = chunk->cache_buffer + chunk->cache_read_count * DVD_VIDEO_LB_LEN; + *buf = chunk->cache_buffer + (sector - chunk->cache_start_sector) * DVD_VIDEO_LB_LEN; + chunk->usage_count++; + pthread_mutex_unlock(&self->lock); + + dprintf("libdvdnav: sector=%d, start_sector=%d, last_sector=%d\n", sector, chunk->cache_start_sector, chunk->cache_start_sector + chunk->cache_block_count); + + /* read_ahead_size */ + incr = self->read_ahead_incr >> 1; + if ((self->read_ahead_size + incr) > READ_AHEAD_SIZE_MAX) { + self->read_ahead_size = READ_AHEAD_SIZE_MAX; + } else { + self->read_ahead_size += incr; + } + + /* real read size */ + start = chunk->cache_start_sector + chunk->cache_read_count; + if (chunk->cache_read_count + self->read_ahead_size > chunk->cache_block_count) { + size = chunk->cache_block_count - chunk->cache_read_count; + } else { + size = self->read_ahead_size; + /* ensure that the sector we want will be read */ + if (sector >= chunk->cache_start_sector + chunk->cache_read_count + size) + size = sector - chunk->cache_start_sector - chunk->cache_read_count; + } + dprintf("libdvdnav: read_ahead_size=%d, size=%d\n", self->read_ahead_size, size); + + if (size) + chunk->cache_read_count += DVDReadBlocks(self->dvd_self->file, + start, + size, + read_ahead_buf); + + res = DVD_VIDEO_LB_LEN * block_count; + + } else { + + if (self->dvd_self->use_read_ahead) + dprintf("cache miss on sector %d\n", sector); + + res = DVDReadBlocks(self->dvd_self->file, + sector, + block_count, + *buf) * DVD_VIDEO_LB_LEN; + } + + return res; + +} + +dvdnav_status_t dvdnav_free_cache_block(dvdnav_t *self, unsigned char *buf) { + read_cache_t *cache; + int i; + + if (!self) + return DVDNAV_STATUS_ERR; + + cache = self->cache; + if (!cache) + return DVDNAV_STATUS_ERR; + + pthread_mutex_lock(&cache->lock); + for (i = 0; i < READ_CACHE_CHUNKS; i++) { + if (cache->chunk[i].cache_buffer && buf >= cache->chunk[i].cache_buffer && + buf < cache->chunk[i].cache_buffer + cache->chunk[i].cache_malloc_size * DVD_VIDEO_LB_LEN && cache->chunk[i].usage_count > 0) { + cache->chunk[i].usage_count--; + } + } + pthread_mutex_unlock(&cache->lock); + + if (cache->freeing) + /* when we want to dispose the cache, try freeing it now */ + dvdnav_read_cache_free(cache); + + return DVDNAV_STATUS_OK; +} diff --git a/lib/libdvd/libdvdnav/src/read_cache.h b/lib/libdvd/libdvdnav/src/read_cache.h new file mode 100644 index 0000000000..92f9c5caba --- /dev/null +++ b/lib/libdvd/libdvdnav/src/read_cache.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2000 Rich Wareham <richwareham@users.sourceforge.net> + * + * This file is part of libdvdnav, a DVD navigation library. + * + * libdvdnav 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. + * + * libdvdnav 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 + * + * $Id: read_cache.h 1135 2008-09-06 21:55:51Z rathann $ + * + */ + +#ifndef __DVDNAV_READ_CACHE_H +#define __DVDNAV_READ_CACHE_H + +/* Opaque cache type -- defined in dvdnav_internal.h */ +/* typedef struct read_cache_s read_cache_t; */ + +/* EXPERIMENTAL: Setting the following to 1 will use an experimental multi-threaded + * read-ahead cache. + */ +#define _MULTITHREAD_ 0 + +/* Constructor/destructors */ +read_cache_t *dvdnav_read_cache_new(dvdnav_t* dvd_self); +void dvdnav_read_cache_free(read_cache_t* self); + +/* This function MUST be called whenever self->file changes. */ +void dvdnav_read_cache_clear(read_cache_t *self); +/* This function is called just after reading the NAV packet. */ +void dvdnav_pre_cache_blocks(read_cache_t *self, int sector, size_t block_count); +/* This function will do the cache read. + * The buffer handed in must be malloced to take one dvd block. + * On a cache hit, a different buffer will be returned though. + * Those buffers must _never_ be freed. */ +int dvdnav_read_cache_block(read_cache_t *self, int sector, size_t block_count, uint8_t **buf); + +#endif /* __DVDNAV_READ_CACHE_H */ diff --git a/lib/libdvd/libdvdnav/src/remap.c b/lib/libdvd/libdvdnav/src/remap.c new file mode 100644 index 0000000000..5601605dba --- /dev/null +++ b/lib/libdvd/libdvdnav/src/remap.c @@ -0,0 +1,269 @@ +/* + * This file is part of libdvdnav, a DVD navigation library. + * + * libdvdnav 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. + * + * libdvdnav 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 + * + * $Id: remap.c 1135 2008-09-06 21:55:51Z rathann $ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + +#ifndef _MSC_VER +#include <sys/param.h> +#include <sys/fcntl.h> +#else +#ifndef MAXPATHLEN +#define MAXPATHLEN 255 +#endif +#endif /* _MSC_VER */ + +#include <inttypes.h> +#include <limits.h> +#include <sys/time.h> +#include "dvd_types.h" +#include <dvdread/nav_types.h> +#include <dvdread/ifo_types.h> +#include "remap.h" +#include "vm/decoder.h" +#include "vm/vm.h" +#include "dvdnav.h" +#include "dvdnav_internal.h" + +struct block_s { + int domain; + int title; + int program; + unsigned long start_block; + unsigned long end_block; +}; + +struct remap_s { + char *title; + int maxblocks; + int nblocks; + int debug; + struct block_s *blocks; +}; + +static remap_t* remap_new( char *title) { + remap_t *map = malloc( sizeof(remap_t)); + map->title = strdup(title); + map->maxblocks = 0; + map->nblocks = 0; + map->blocks = NULL; + map->debug = 0; + return map; +} + +static int compare_block( block_t *a, block_t *b) { + /* returns -1 if a precedes b, 1 if a follows b, and 0 if a and b overlap */ + if (a->domain < b->domain) { + return -1; + } else if (a->domain > b->domain) { + return 1; + } + + if (a->title < b->title) { + return -1; + } else if (a->title > b->title) { + return 1; + } + + if (a->program < b->program) { + return -1; + } else if (a->program > b->program) { + return 1; + } + + if (a->end_block < b->start_block) { + return -1; + } else if (a->start_block > b->end_block) { + /* + * if a->start_block == b->end_block then the two regions + * aren't strictly overlapping, but they should be merged + * anyway since there are zero blocks between them + */ + return 1; + } + + return 0; +} + +static block_t *findblock( remap_t *map, block_t *key) { + int lb = 0; + int ub = map->nblocks - 1; + int mid; + int res; + + while (lb <= ub) { + mid = lb + (ub - lb)/2; + res = compare_block( key, &map->blocks[mid]); + if (res < 0) { + ub = mid-1; + } else if (res > 0) { + lb = mid+1; + } else { + return &map->blocks[mid]; + } + } + return NULL; +} + +static void mergeblock( block_t *b, block_t tmp) { + if (tmp.start_block < b->start_block) b->start_block = tmp.start_block; + if (tmp.end_block > b->end_block) b->end_block = tmp.end_block; +} + +static void remap_add_node( remap_t *map, block_t block) { + block_t *b; + int n; + b = findblock( map, &block); + if (b) { + /* overlaps an existing block */ + mergeblock( b, block); + } else { + /* new block */ + if (map->nblocks >= map->maxblocks) { + map->maxblocks += 20; + map->blocks = realloc( map->blocks, sizeof( block_t)*map->maxblocks); + } + n = map->nblocks++; + while (n > 0 && compare_block( &block, &map->blocks[ n-1]) < 0) { + map->blocks[ n] = map->blocks[ n-1]; + n--; + } + map->blocks[ n] = block; + } +} + +static int parseblock(char *buf, int *dom, int *tt, int *pg, + unsigned long *start, unsigned long *end) { + long tmp; + char *tok; + char *epos; + char *marker[]={"domain", "title", "program", "start", "end"}; + int st = 0; + tok = strtok( buf, " "); + while (st < 5) { + if (strcmp(tok, marker[st])) return -st-1000; + tok = strtok( NULL, " "); + if (!tok) return -st-2000; + tmp = strtol( tok, &epos, 0); + if (*epos != 0 && *epos != ',') return -st-3000; + switch (st) { + case 0: + *dom = (int)tmp; + break; + case 1: + *tt = (int)tmp; + break; + case 2: + *pg = (int)tmp; + break; + case 3: + *start = tmp; + break; + case 4: + *end = tmp; + break; + } + st++; + tok = strtok( NULL, " "); + } + return st; +} + +remap_t* remap_loadmap( char *title) { + char buf[160]; + char fname[MAXPATHLEN]; + char *home; + int res; + FILE *fp; + block_t tmp; + remap_t *map; + + memset(&tmp, 0, sizeof(tmp)); + /* Build the map filename */ + home = getenv("HOME"); + if(!home) { + fprintf(MSG_OUT, "libdvdnav: Unable to find home directory" ); + return NULL; + } + snprintf(fname, sizeof(fname), "%s/.dvdnav/%s.map", home, title); + + /* Open the map file */ + fp = fopen( fname, "r"); + if (!fp) { + fprintf(MSG_OUT, "libdvdnav: Unable to find map file '%s'\n", fname); + return NULL; + } + + /* Load the map file */ + map = remap_new( title); + while (fgets( buf, sizeof(buf), fp) != NULL) { + if (buf[0] == '\n' || buf[0] == '#' || buf[0] == 0) continue; + if (strncasecmp( buf, "debug", 5) == 0) { + map->debug = 1; + } else { + res = parseblock( buf, + &tmp.domain, &tmp.title, &tmp.program, &tmp.start_block, &tmp.end_block); + if (res != 5) { + fprintf(MSG_OUT, "libdvdnav: Ignoring map line (%d): %s\n", res, buf); + continue; + } + remap_add_node( map, tmp); + } + } + fclose(fp); + + if (map->nblocks == 0 && map->debug == 0) { + free(map); + return NULL; + } + return map; +} + +unsigned long remap_block( + remap_t *map, int domain, int title, int program, + unsigned long cblock, unsigned long offset) +{ + block_t key; + block_t *b; + + if (map->debug) { + fprintf(MSG_OUT, "libdvdnav: %s: domain %d, title %d, program %d, start %lx, next %lx\n", + map->title, domain, title, program, cblock, cblock+offset); + } + + key.domain = domain; + key.title = title; + key.program = program; + key.start_block = key.end_block = cblock + offset; + b = findblock( map, &key); + + if (b) { + if (map->debug) { + fprintf(MSG_OUT, "libdvdnav: Redirected to %lx\n", b->end_block); + } + return b->end_block - cblock; + } + return offset; +} diff --git a/lib/libdvd/libdvdnav/src/remap.h b/lib/libdvd/libdvdnav/src/remap.h new file mode 100644 index 0000000000..0a8a81636b --- /dev/null +++ b/lib/libdvd/libdvdnav/src/remap.h @@ -0,0 +1,33 @@ +/* + * This file is part of libdvdnav, a DVD navigation library. + * + * libdvdnav 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. + * + * libdvdnav 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 + * + * $Id: remap.h 1135 2008-09-06 21:55:51Z rathann $ + */ + +#ifndef __REMAP__H +#define __REMAP__H +typedef struct block_s block_t; + +typedef struct remap_s remap_t; + +remap_t* remap_loadmap( char *title); + +unsigned long remap_block( + remap_t *map, int domain, int title, int program, + unsigned long cblock, unsigned long offset); + +#endif diff --git a/lib/libdvd/libdvdnav/src/searching.c b/lib/libdvd/libdvdnav/src/searching.c new file mode 100644 index 0000000000..0d3475ed1c --- /dev/null +++ b/lib/libdvd/libdvdnav/src/searching.c @@ -0,0 +1,782 @@ +/* + * Copyright (C) 2000 Rich Wareham <richwareham@users.sourceforge.net> + * + * This file is part of libdvdnav, a DVD navigation library. + * + * libdvdnav 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. + * + * libdvdnav 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 + * + * $Id: searching.c 1135 2008-09-06 21:55:51Z rathann $ + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <assert.h> +#include <inttypes.h> +#include <limits.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <sys/time.h> +#include "dvd_types.h" +#include <dvdread/nav_types.h> +#include <dvdread/ifo_types.h> +#include "remap.h" +#include "vm/decoder.h" +#include "vm/vm.h" +#include "dvdnav.h" +#include "dvdnav_internal.h" + +/* +#define LOG_DEBUG +*/ + +/* Searching API calls */ + +/* Scan the ADMAP for a particular block number. */ +/* Return placed in vobu. */ +/* Returns error status */ +/* FIXME: Maybe need to handle seeking outside current cell. */ +static dvdnav_status_t dvdnav_scan_admap(dvdnav_t *this, int32_t domain, uint32_t seekto_block, uint32_t *vobu) { + vobu_admap_t *admap = NULL; + +#ifdef LOG_DEBUG + fprintf(MSG_OUT, "libdvdnav: Seeking to target %u ...\n", seekto_block); +#endif + *vobu = -1; + + /* Search through the VOBU_ADMAP for the nearest VOBU + * to the target block */ + switch(domain) { + case FP_DOMAIN: + case VMGM_DOMAIN: + admap = this->vm->vmgi->menu_vobu_admap; + break; + case VTSM_DOMAIN: + admap = this->vm->vtsi->menu_vobu_admap; + break; + case VTS_DOMAIN: + admap = this->vm->vtsi->vts_vobu_admap; + break; + default: + fprintf(MSG_OUT, "libdvdnav: Error: Unknown domain for seeking.\n"); + } + if(admap) { + uint32_t address = 0; + uint32_t vobu_start, next_vobu; + int admap_entries = (admap->last_byte + 1 - VOBU_ADMAP_SIZE)/VOBU_ADMAP_SIZE; + + /* Search through ADMAP for best sector */ + vobu_start = SRI_END_OF_CELL; + /* FIXME: Implement a faster search algorithm */ + while(address < admap_entries) { + next_vobu = admap->vobu_start_sectors[address]; + + /* fprintf(MSG_OUT, "libdvdnav: Found block %u\n", next_vobu); */ + + if(vobu_start <= seekto_block && next_vobu > seekto_block) + break; + vobu_start = next_vobu; + address++; + } + *vobu = vobu_start; + return DVDNAV_STATUS_OK; + } + fprintf(MSG_OUT, "libdvdnav: admap not located\n"); + return DVDNAV_STATUS_ERR; +} + +dvdnav_status_t dvdnav_time_search(dvdnav_t *this, + uint64_t time) { + + uint32_t target; + uint64_t length = 0; + uint32_t first_cell_nr, last_cell_nr, cell_nr; + int32_t found = 0; + cell_playback_t *cell; + dvd_state_t *state; + + if(this->position_current.still != 0) { + printerr("Cannot seek in a still frame."); + return DVDNAV_STATUS_ERR; + } + + pthread_mutex_lock(&this->vm_lock); + state = &(this->vm->state); + if(!state->pgc) { + printerr("No current PGC."); + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_ERR; + } + + if((state->pgc->prohibited_ops.title_or_time_play == 1) || + (this->pci.pci_gi.vobu_uop_ctl.title_or_time_play == 1 )){ + printerr("operation forbidden."); + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_ERR; + } + + /* setup what cells we should be working within */ + if (this->pgc_based) { + first_cell_nr = 1; + last_cell_nr = state->pgc->nr_of_cells; + } else { + /* Find start cell of program. */ + first_cell_nr = state->pgc->program_map[state->pgN-1]; + /* Find end cell of program */ + if(state->pgN < state->pgc->nr_of_programs) + last_cell_nr = state->pgc->program_map[state->pgN] - 1; + else + last_cell_nr = state->pgc->nr_of_cells; + } + + /* FIXME: using time map is not going to work unless we are pgc_based */ + /* we'd need to recalculate the time to be relative to full pgc first*/ + if(!this->pgc_based) + { +#ifdef LOG_DEBUG + fprintf(MSG_OUT, "libdvdnav: time_search - not pgc based\n"); +#endif + goto timemapdone; + } + + if(!this->vm->vtsi->vts_tmapt){ + /* no time map for this program chain */ +#ifdef LOG_DEBUG + fprintf(MSG_OUT, "libdvdnav: time_search - no time map for this program chain\n"); +#endif + goto timemapdone; + } + + if(this->vm->vtsi->vts_tmapt->nr_of_tmaps < state->pgcN){ + /* to few time maps for this program chain */ +#ifdef LOG_DEBUG + fprintf(MSG_OUT, "libdvdnav: time_search - to few time maps for this program chain\n"); +#endif + goto timemapdone; + } + + /* get the tmpat corresponding to the pgc */ + vts_tmap_t *tmap = &(this->vm->vtsi->vts_tmapt->tmap[state->pgcN-1]); + + if(tmap->tmu == 0){ + /* no time unit for this time map */ +#ifdef LOG_DEBUG + fprintf(MSG_OUT, "libdvdnav: time_search - no time unit for this time map\n"); +#endif + goto timemapdone; + } + + /* time is in pts (90khz clock), get the number of tmu's that represent */ + /* first entry defines at time tmu not time zero */ + int entry = time / tmap->tmu / 90000 - 1; + if(entry > tmap->nr_of_entries) + entry = tmap->nr_of_entries -1; + + if(entry > 0) + { + /* get the table entry, disregarding marking of discontinuity */ + target = tmap->map_ent[entry] & 0x7fffffff; + } + else + { + /* start from first vobunit */ + target = state->pgc->cell_playback[first_cell_nr-1].first_sector;; + } + + /* if we have an additional entry we can interpolate next position */ + /* allowed only if next entry isn't discontinious */ + + if( entry < tmap->nr_of_entries - 1) + { + const uint32_t target2 = tmap->map_ent[entry+1]; + const uint64_t timeunit = tmap->tmu*90000; + if( !( target2 & 0x80000000) ) + { + length = target2 - target; + target += (uint32_t) (length * ( time - (entry+1)*timeunit ) / timeunit); + } + } + found = 1; + +timemapdone: + + + for(cell_nr = first_cell_nr; cell_nr <= last_cell_nr; cell_nr ++) { + cell = &(state->pgc->cell_playback[cell_nr-1]); + + if(cell->block_type == BLOCK_TYPE_ANGLE_BLOCK && cell->block_mode != BLOCK_MODE_FIRST_CELL) + continue; + + if(found) { + + length = cell->last_sector - cell->first_sector + 1; + if (target >= length) { + target -= length; + } else { + /* convert the target sector from Cell-relative to absolute physical sector */ + target += cell->first_sector; + break; + } + + } else { + + length = dvdnav_convert_time(&cell->playback_time); + if (time >= length) { + time -= length; + } else { + /* FIXME: there must be a better way than interpolation */ + target = time * (cell->last_sector - cell->first_sector + 1) / length; + target += cell->first_sector; + + #ifdef LOG_DEBUG + if( cell->first_sector > target || target > cell->last_sector ) + fprintf(MSG_OUT, "libdvdnav: time_search - sector is not within cell min:%u, max:%u, cur:%u\n", cell->first_sector, cell->last_sector, target); + #endif + + found = 1; + break; + } + } + } + + if(found) { + uint32_t vobu; +#ifdef LOG_DEBUG + fprintf(MSG_OUT, "libdvdnav: Seeking to cell %i from choice of %i to %i\n", + cell_nr, first_cell_nr, last_cell_nr); +#endif + if (dvdnav_scan_admap(this, state->domain, target, &vobu) == DVDNAV_STATUS_OK) { + uint32_t start = state->pgc->cell_playback[cell_nr-1].first_sector; + + if (vm_jump_cell_block(this->vm, cell_nr, vobu - start)) { +#ifdef LOG_DEBUG + fprintf(MSG_OUT, "libdvdnav: After cellN=%u blockN=%u target=%x vobu=%x start=%x\n" , + state->cellN, state->blockN, target, vobu, start); +#endif + this->vm->hop_channel += HOP_SEEK; + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_OK; + } + } + } + + fprintf(MSG_OUT, "libdvdnav: Error when seeking\n"); + printerr("Error when seeking."); + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_ERR; +} + +dvdnav_status_t dvdnav_sector_search(dvdnav_t *this, + uint64_t offset, int32_t origin) { + uint32_t target = 0; + uint32_t length = 0; + uint32_t first_cell_nr, last_cell_nr, cell_nr; + int32_t found; + cell_playback_t *cell; + dvd_state_t *state; + dvdnav_status_t result; + + if(this->position_current.still != 0) { + printerr("Cannot seek in a still frame."); + return DVDNAV_STATUS_ERR; + } + + result = dvdnav_get_position(this, &target, &length); + if(!result) { + printerr("Cannot get current position"); + return DVDNAV_STATUS_ERR; + } + + pthread_mutex_lock(&this->vm_lock); + state = &(this->vm->state); + if(!state->pgc) { + printerr("No current PGC."); + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_ERR; + } +#ifdef LOG_DEBUG + fprintf(MSG_OUT, "libdvdnav: seeking to offset=%llu pos=%u length=%u\n", offset, target, length); + fprintf(MSG_OUT, "libdvdnav: Before cellN=%u blockN=%u\n", state->cellN, state->blockN); +#endif + + switch(origin) { + case SEEK_SET: + if(offset >= length) { + printerr("Request to seek behind end."); + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_ERR; + } + target = offset; + break; + case SEEK_CUR: + if(target + offset >= length) { + printerr("Request to seek behind end."); + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_ERR; + } + target += offset; + break; + case SEEK_END: + if(length < offset) { + printerr("Request to seek before start."); + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_ERR; + } + target = length - offset; + break; + default: + /* Error occured */ + printerr("Illegal seek mode."); + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_ERR; + } + + this->cur_cell_time = 0; + if (this->pgc_based) { + first_cell_nr = 1; + last_cell_nr = state->pgc->nr_of_cells; + } else { + /* Find start cell of program. */ + first_cell_nr = state->pgc->program_map[state->pgN-1]; + /* Find end cell of program */ + if(state->pgN < state->pgc->nr_of_programs) + last_cell_nr = state->pgc->program_map[state->pgN] - 1; + else + last_cell_nr = state->pgc->nr_of_cells; + } + + found = 0; + for(cell_nr = first_cell_nr; (cell_nr <= last_cell_nr) && !found; cell_nr ++) { + cell = &(state->pgc->cell_playback[cell_nr-1]); + if(cell->block_type == BLOCK_TYPE_ANGLE_BLOCK && cell->block_mode != BLOCK_MODE_FIRST_CELL) + continue; + length = cell->last_sector - cell->first_sector + 1; + if (target >= length) { + target -= length; + } else { + /* convert the target sector from Cell-relative to absolute physical sector */ + target += cell->first_sector; + found = 1; + break; + } + } + + if(found) { + uint32_t vobu; +#ifdef LOG_DEBUG + fprintf(MSG_OUT, "libdvdnav: Seeking to cell %i from choice of %i to %i\n", + cell_nr, first_cell_nr, last_cell_nr); +#endif + if (dvdnav_scan_admap(this, state->domain, target, &vobu) == DVDNAV_STATUS_OK) { + int32_t start = state->pgc->cell_playback[cell_nr-1].first_sector; + + if (vm_jump_cell_block(this->vm, cell_nr, vobu - start)) { +#ifdef LOG_DEBUG + fprintf(MSG_OUT, "libdvdnav: After cellN=%u blockN=%u target=%x vobu=%x start=%x\n" , + state->cellN, state->blockN, target, vobu, start); +#endif + this->vm->hop_channel += HOP_SEEK; + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_OK; + } + } + } + + fprintf(MSG_OUT, "libdvdnav: Error when seeking\n"); + fprintf(MSG_OUT, "libdvdnav: FIXME: Implement seeking to location %u\n", target); + printerr("Error when seeking."); + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_ERR; +} + +dvdnav_status_t dvdnav_part_search(dvdnav_t *this, int32_t part) { + int32_t title, old_part; + + if (dvdnav_current_title_info(this, &title, &old_part) == DVDNAV_STATUS_OK) + return dvdnav_part_play(this, title, part); + return DVDNAV_STATUS_ERR; +} + +dvdnav_status_t dvdnav_prev_pg_search(dvdnav_t *this) { + pthread_mutex_lock(&this->vm_lock); + if(!this->vm->state.pgc) { + printerr("No current PGC."); + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_ERR; + } + +#ifdef LOG_DEBUG + fprintf(MSG_OUT, "libdvdnav: previous chapter\n"); +#endif + if (!vm_jump_prev_pg(this->vm)) { + fprintf(MSG_OUT, "libdvdnav: previous chapter failed.\n"); + printerr("Skip to previous chapter failed."); + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_ERR; + } + this->cur_cell_time = 0; + this->position_current.still = 0; + this->vm->hop_channel++; +#ifdef LOG_DEBUG + fprintf(MSG_OUT, "libdvdnav: previous chapter done\n"); +#endif + pthread_mutex_unlock(&this->vm_lock); + + return DVDNAV_STATUS_OK; +} + +dvdnav_status_t dvdnav_top_pg_search(dvdnav_t *this) { + pthread_mutex_lock(&this->vm_lock); + if(!this->vm->state.pgc) { + printerr("No current PGC."); + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_ERR; + } + +#ifdef LOG_DEBUG + fprintf(MSG_OUT, "libdvdnav: top chapter\n"); +#endif + if (!vm_jump_top_pg(this->vm)) { + fprintf(MSG_OUT, "libdvdnav: top chapter failed.\n"); + printerr("Skip to top chapter failed."); + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_ERR; + } + this->cur_cell_time = 0; + this->position_current.still = 0; + this->vm->hop_channel++; +#ifdef LOG_DEBUG + fprintf(MSG_OUT, "libdvdnav: top chapter done\n"); +#endif + pthread_mutex_unlock(&this->vm_lock); + + return DVDNAV_STATUS_OK; +} + +dvdnav_status_t dvdnav_next_pg_search(dvdnav_t *this) { + vm_t *try_vm; + + pthread_mutex_lock(&this->vm_lock); + if(!this->vm->state.pgc) { + printerr("No current PGC."); + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_ERR; + } + +#ifdef LOG_DEBUG + fprintf(MSG_OUT, "libdvdnav: next chapter\n"); +#endif + /* make a copy of current VM and try to navigate the copy to the next PG */ + try_vm = vm_new_copy(this->vm); + if (!vm_jump_next_pg(try_vm) || try_vm->stopped) { + vm_free_copy(try_vm); + /* next_pg failed, try to jump at least to the next cell */ + try_vm = vm_new_copy(this->vm); + vm_get_next_cell(try_vm); + if (try_vm->stopped) { + vm_free_copy(try_vm); + fprintf(MSG_OUT, "libdvdnav: next chapter failed.\n"); + printerr("Skip to next chapter failed."); + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_ERR; + } + } + this->cur_cell_time = 0; + /* merge changes on success */ + vm_merge(this->vm, try_vm); + vm_free_copy(try_vm); + this->position_current.still = 0; + this->vm->hop_channel++; +#ifdef LOG_DEBUG + fprintf(MSG_OUT, "libdvdnav: next chapter done\n"); +#endif + pthread_mutex_unlock(&this->vm_lock); + + return DVDNAV_STATUS_OK; +} + +dvdnav_status_t dvdnav_menu_call(dvdnav_t *this, DVDMenuID_t menu) { + vm_t *try_vm; + + pthread_mutex_lock(&this->vm_lock); + if(!this->vm->state.pgc) { + printerr("No current PGC."); + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_ERR; + } + + this->cur_cell_time = 0; + /* make a copy of current VM and try to navigate the copy to the menu */ + try_vm = vm_new_copy(this->vm); + if ( (menu == DVD_MENU_Escape) && (this->vm->state.domain != VTS_DOMAIN)) { + /* Try resume */ + if (vm_jump_resume(try_vm) && !try_vm->stopped) { + /* merge changes on success */ + vm_merge(this->vm, try_vm); + vm_free_copy(try_vm); + this->position_current.still = 0; + this->vm->hop_channel++; + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_OK; + } + } + if (menu == DVD_MENU_Escape) menu = DVD_MENU_Root; + + if (vm_jump_menu(try_vm, menu) && !try_vm->stopped) { + /* merge changes on success */ + vm_merge(this->vm, try_vm); + vm_free_copy(try_vm); + this->position_current.still = 0; + this->vm->hop_channel++; + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_OK; + } else { + vm_free_copy(try_vm); + printerr("No such menu or menu not reachable."); + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_ERR; + } +} + +dvdnav_status_t dvdnav_get_position(dvdnav_t *this, uint32_t *pos, + uint32_t *len) { + uint32_t cur_sector; + int32_t cell_nr, first_cell_nr, last_cell_nr; + cell_playback_t *cell; + dvd_state_t *state; + + if(!this->started) { + printerr("Virtual DVD machine not started."); + return DVDNAV_STATUS_ERR; + } + + pthread_mutex_lock(&this->vm_lock); + state = &(this->vm->state); + if(!state->pgc || this->vm->stopped) { + printerr("No current PGC."); + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_ERR; + } + if (this->position_current.hop_channel != this->vm->hop_channel || + this->position_current.domain != state->domain || + this->position_current.vts != state->vtsN || + this->position_current.cell_restart != state->cell_restart) { + printerr("New position not yet determined."); + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_ERR; + } + + /* Get current sector */ + cur_sector = this->vobu.vobu_start + this->vobu.blockN; + + if (this->pgc_based) { + first_cell_nr = 1; + last_cell_nr = state->pgc->nr_of_cells; + } else { + /* Find start cell of program. */ + first_cell_nr = state->pgc->program_map[state->pgN-1]; + /* Find end cell of program */ + if(state->pgN < state->pgc->nr_of_programs) + last_cell_nr = state->pgc->program_map[state->pgN] - 1; + else + last_cell_nr = state->pgc->nr_of_cells; + } + + *pos = -1; + *len = 0; + for (cell_nr = first_cell_nr; cell_nr <= last_cell_nr; cell_nr++) { + cell = &(state->pgc->cell_playback[cell_nr-1]); + if (cell_nr == state->cellN) { + /* the current sector is in this cell, + * pos is length of PG up to here + sector's offset in this cell */ + *pos = *len + cur_sector - cell->first_sector; + } + *len += cell->last_sector - cell->first_sector + 1; + } + + assert((signed)*pos != -1); + + pthread_mutex_unlock(&this->vm_lock); + + return DVDNAV_STATUS_OK; +} + +dvdnav_status_t dvdnav_get_position_in_title(dvdnav_t *this, + uint32_t *pos, + uint32_t *len) { + uint32_t cur_sector; + uint32_t first_cell_nr; + uint32_t last_cell_nr; + cell_playback_t *first_cell; + cell_playback_t *last_cell; + dvd_state_t *state; + + state = &(this->vm->state); + if(!state->pgc) { + printerr("No current PGC."); + return DVDNAV_STATUS_ERR; + } + + /* Get current sector */ + cur_sector = this->vobu.vobu_start + this->vobu.blockN; + + /* Now find first and last cells in title. */ + first_cell_nr = state->pgc->program_map[0]; + first_cell = &(state->pgc->cell_playback[first_cell_nr-1]); + last_cell_nr = state->pgc->nr_of_cells; + last_cell = &(state->pgc->cell_playback[last_cell_nr-1]); + + *pos = cur_sector - first_cell->first_sector; + *len = last_cell->last_sector - first_cell->first_sector; + + return DVDNAV_STATUS_OK; +} + +uint32_t dvdnav_describe_title_chapters(dvdnav_t *this, int32_t title, uint64_t **times, uint64_t *duration) { + int32_t retval=0; + uint16_t parts, i; + title_info_t *ptitle = NULL; + ptt_info_t *ptt = NULL; + ifo_handle_t *ifo; + pgc_t *pgc; + cell_playback_t *cell; + uint64_t length, *tmp=NULL; + + *times = NULL; + *duration = 0; + pthread_mutex_lock(&this->vm_lock); + if(!this->vm->vmgi) { + printerr("Bad VM state or missing VTSI."); + goto fail; + } + if(!this->started) { + /* don't report an error but be nice */ + vm_start(this->vm); + this->started = 1; + } + ifo = vm_get_title_ifo(this->vm, title); + if(!ifo || !ifo->vts_pgcit) { + printerr("Couldn't open IFO for chosen title, exit."); + goto fail; + } + + ptitle = &this->vm->vmgi->tt_srpt->title[title-1]; + parts = ptitle->nr_of_ptts; + ptt = ifo->vts_ptt_srpt->title[ptitle->vts_ttn-1].ptt; + + tmp = calloc(1, sizeof(uint64_t)*parts); + if(!tmp) + goto fail; + + length = 0; + for(i=0; i<parts; i++) { + uint32_t cellnr, endcellnr; + pgc = ifo->vts_pgcit->pgci_srp[ptt[i].pgcn-1].pgc; + if(ptt[i].pgn > pgc->nr_of_programs) { + printerr("WRONG part number."); + goto fail; + } + + cellnr = pgc->program_map[ptt[i].pgn-1]; + if(ptt[i].pgn < pgc->nr_of_programs) + endcellnr = pgc->program_map[ptt[i].pgn]; + else + endcellnr = 0; + + do { + cell = &pgc->cell_playback[cellnr-1]; + if(!(cell->block_type == BLOCK_TYPE_ANGLE_BLOCK && + cell->block_mode != BLOCK_MODE_FIRST_CELL + )) + { + tmp[i] = length + dvdnav_convert_time(&cell->playback_time); + length = tmp[i]; + } + cellnr++; + } while(cellnr < endcellnr); + } + *duration = length; + vm_ifo_close(ifo); + retval = parts; + *times = tmp; + +fail: + pthread_mutex_unlock(&this->vm_lock); + if(!retval && tmp) + free(tmp); + return retval; +} + +dvdnav_status_t dvdnav_get_state(dvdnav_t *this, dvd_state_t *save_state) +{ + if(!this || !this->vm) return DVDNAV_STATUS_ERR; + + pthread_mutex_lock(&this->vm_lock); + + if( !vm_get_state(this->vm, save_state) ) + { + printerr("Failed to get vm state."); + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_ERR; + } + + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_OK; +} + +dvdnav_status_t dvdnav_set_state(dvdnav_t *this, dvd_state_t *save_state) +{ + if(!this || !this->vm) + { + printerr("Passed a NULL pointer."); + return DVDNAV_STATUS_ERR; + } + + if(!this->started) { + printerr("Virtual DVD machine not started."); + return DVDNAV_STATUS_ERR; + } + + pthread_mutex_lock(&this->vm_lock); + + /* reset the dvdnav state */ + memset(&this->pci,0,sizeof(this->pci)); + memset(&this->dsi,0,sizeof(this->dsi)); + this->last_cmd_nav_lbn = SRI_END_OF_CELL; + + /* Set initial values of flags */ + this->position_current.still = 0; + this->skip_still = 0; + this->sync_wait = 0; + this->sync_wait_skip = 0; + this->spu_clut_changed = 0; + + + /* set the state. this will also start the vm on that state */ + /* means the next read block should be comming from that new */ + /* state */ + if( !vm_set_state(this->vm, save_state) ) + { + printerr("Failed to set vm state."); + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_ERR; + } + + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_OK; +} diff --git a/lib/libdvd/libdvdnav/src/settings.c b/lib/libdvd/libdvdnav/src/settings.c new file mode 100644 index 0000000000..7261f1d502 --- /dev/null +++ b/lib/libdvd/libdvdnav/src/settings.c @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2000 Rich Wareham <richwareham@users.sourceforge.net> + * + * This file is part of libdvdnav, a DVD navigation library. + * + * libdvdnav 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. + * + * libdvdnav 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 + * + * $Id: settings.c 1135 2008-09-06 21:55:51Z rathann $ + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <inttypes.h> +#include <limits.h> +#include <string.h> +#include <sys/time.h> +#include "dvd_types.h" +#include <dvdread/nav_types.h> +#include <dvdread/ifo_types.h> +#include "remap.h" +#include "vm/decoder.h" +#include "vm/vm.h" +#include "dvdnav.h" +#include "dvdnav_internal.h" + +/* Characteristics/setting API calls */ + +dvdnav_status_t dvdnav_get_region_mask(dvdnav_t *this, int32_t *region) { + (*region) = this->vm->state.registers.SPRM[20]; + return DVDNAV_STATUS_OK; +} + +dvdnav_status_t dvdnav_set_region_mask(dvdnav_t *this, int32_t mask) { + pthread_mutex_lock(&this->vm_lock); + this->vm->state.registers.SPRM[20] = (mask & 0xff); + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_OK; +} + +dvdnav_status_t dvdnav_set_readahead_flag(dvdnav_t *this, int32_t use_readahead) { + this->use_read_ahead = use_readahead; + return DVDNAV_STATUS_OK; +} + +dvdnav_status_t dvdnav_get_readahead_flag(dvdnav_t *this, int32_t *flag) { + (*flag) = this->use_read_ahead; + return DVDNAV_STATUS_OK; +} + +static dvdnav_status_t set_language_register(dvdnav_t *this, char *code, int reg) { + if(!code[0] || !code[1]) { + printerr("Passed illegal language code."); + return DVDNAV_STATUS_ERR; + } + + pthread_mutex_lock(&this->vm_lock); + this->vm->state.registers.SPRM[reg] = (code[0] << 8) | code[1]; + pthread_mutex_unlock(&this->vm_lock); + return DVDNAV_STATUS_OK; +} + +dvdnav_status_t dvdnav_menu_language_select(dvdnav_t *this, char *code) { + return set_language_register(this, code, 0); +} + +dvdnav_status_t dvdnav_audio_language_select(dvdnav_t *this, char *code) { + return set_language_register(this, code, 16); +} + +dvdnav_status_t dvdnav_spu_language_select(dvdnav_t *this, char *code) { + return set_language_register(this, code, 18); +} + +dvdnav_status_t dvdnav_set_PGC_positioning_flag(dvdnav_t *this, int32_t pgc) { + this->pgc_based = pgc; + return DVDNAV_STATUS_OK; +} + +dvdnav_status_t dvdnav_get_PGC_positioning_flag(dvdnav_t *this, int32_t *flag) { + (*flag) = this->pgc_based; + return DVDNAV_STATUS_OK; +} diff --git a/lib/libdvd/libdvdnav/src/vm/Makefile.am b/lib/libdvd/libdvdnav/src/vm/Makefile.am new file mode 100644 index 0000000000..67a4811aed --- /dev/null +++ b/lib/libdvd/libdvdnav/src/vm/Makefile.am @@ -0,0 +1,16 @@ +include $(top_srcdir)/misc/Makefile.common + +includedir = ${prefix}/include/dvdnav + +AM_CPPFLAGS = -DDVDNAV_COMPILE $(THREAD_CFLAGS) $(DVDREAD_CFLAGS) \ + -I$(top_srcdir)/src + +noinst_LTLIBRARIES = libdvdvm.la + +libdvdvm_la_SOURCES = decoder.c vm.c vmcmd.c + +libdvdvm_la_LDFLAGS = $(THREAD_LIBS) + +include_HEADERS = + +noinst_HEADERS = decoder.h vm.h vmcmd.h diff --git a/lib/libdvd/libdvdnav/src/vm/decoder.c b/lib/libdvd/libdvdnav/src/vm/decoder.c new file mode 100644 index 0000000000..8a26c1d558 --- /dev/null +++ b/lib/libdvd/libdvdnav/src/vm/decoder.c @@ -0,0 +1,788 @@ +/* + * Copyright (C) 2000, 2001 Martin Norbäck, Håkan Hjort + * 2002-2004 the dvdnav project + * + * This file is part of libdvdnav, a DVD navigation library. It is modified + * from a file originally part of the Ogle DVD player. + * + * libdvdnav 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. + * + * libdvdnav 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 + * + * $Id: decoder.c 1135 2008-09-06 21:55:51Z rathann $ + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <inttypes.h> +#include <limits.h> +#include <string.h> /* For memset */ +#include <sys/time.h> +#include <dvdread/nav_types.h> +#include <dvdread/ifo_types.h> /* vm_cmd_t */ + +#include "dvd_types.h" +#include "remap.h" +#include "decoder.h" +#include "vm.h" +#include "vmcmd.h" +#include "dvdnav.h" +#include "dvdnav_internal.h" + +uint32_t vm_getbits(command_t *command, int32_t start, int32_t count) { + uint64_t result = 0; + uint64_t bit_mask = 0; + uint64_t examining = 0; + int32_t bits; + + if (count == 0) return 0; + + if ( ((start - count) < -1) || + (count > 32) || + (start > 63) || + (count < 0) || + (start < 0) ) { + fprintf(MSG_OUT, "libdvdnav: Bad call to vm_getbits. Parameter out of range\n"); + abort(); + } + /* all ones, please */ + bit_mask = ~bit_mask; + bit_mask >>= 63 - start; + bits = start + 1 - count; + examining = ((bit_mask >> bits) << bits ); + command->examined |= examining; + result = (command->instruction & bit_mask) >> bits; + return (uint32_t) result; +} + +static uint16_t get_GPRM(registers_t* registers, uint8_t reg) { + if (registers->GPRM_mode[reg] & 0x01) { + struct timeval current_time, time_offset; + uint16_t result; + /* Counter mode */ + /* fprintf(MSG_OUT, "libdvdnav: Getting counter %d\n",reg);*/ + gettimeofday(¤t_time, NULL); + time_offset.tv_sec = current_time.tv_sec - registers->GPRM_time[reg].tv_sec; + time_offset.tv_usec = current_time.tv_usec - registers->GPRM_time[reg].tv_usec; + if (time_offset.tv_usec < 0) { + time_offset.tv_sec--; + time_offset.tv_usec += 1000000; + } + result = (uint16_t) (time_offset.tv_sec & 0xffff); + registers->GPRM[reg]=result; + return result; + + } else { + /* Register mode */ + return registers->GPRM[reg]; + } + +} + +static void set_GPRM(registers_t* registers, uint8_t reg, uint16_t value) { + if (registers->GPRM_mode[reg] & 0x01) { + struct timeval current_time; + /* Counter mode */ + /* fprintf(MSG_OUT, "libdvdnav: Setting counter %d\n",reg); */ + gettimeofday(¤t_time, NULL); + registers->GPRM_time[reg] = current_time; + registers->GPRM_time[reg].tv_sec -= value; + } + registers->GPRM[reg] = value; +} + +/* Eval register code, can either be system or general register. + SXXX_XXXX, where S is 1 if it is system register. */ +static uint16_t eval_reg(command_t* command, uint8_t reg) { + if(reg & 0x80) { + if ((reg & 0x1f) == 20) { + fprintf(MSG_OUT, "libdvdnav: Suspected RCE Region Protection!!!\n"); + } + return command->registers->SPRM[reg & 0x1f]; /* FIXME max 24 not 32 */ + } else { + return get_GPRM(command->registers, reg & 0x0f) ; + } +} + +/* Eval register or immediate data. + AAAA_AAAA BBBB_BBBB, if immediate use all 16 bits for data else use + lower eight bits for the system or general purpose register. */ +static uint16_t eval_reg_or_data(command_t* command, int32_t imm, int32_t start) { + if(imm) { /* immediate */ + return vm_getbits(command, start, 16); + } else { + return eval_reg(command, vm_getbits(command, (start - 8), 8)); + } +} + +/* Eval register or immediate data. + xBBB_BBBB, if immediate use all 7 bits for data else use + lower four bits for the general purpose register number. */ +/* Evaluates gprm or data depending on bit, data is in byte n */ +static uint16_t eval_reg_or_data_2(command_t* command, + int32_t imm, int32_t start) { + if(imm) /* immediate */ + return vm_getbits(command, (start - 1), 7); + else + return get_GPRM(command->registers, (vm_getbits(command, (start - 4), 4)) ); +} + + +/* Compare data using operation, return result from comparison. + Helper function for the different if functions. */ +static int32_t eval_compare(uint8_t operation, uint16_t data1, uint16_t data2) { + switch(operation) { + case 1: + return data1 & data2; + case 2: + return data1 == data2; + case 3: + return data1 != data2; + case 4: + return data1 >= data2; + case 5: + return data1 > data2; + case 6: + return data1 <= data2; + case 7: + return data1 < data2; + } + fprintf(MSG_OUT, "libdvdnav: eval_compare: Invalid comparison code\n"); + return 0; +} + + +/* Evaluate if version 1. + Has comparison data in byte 3 and 4-5 (immediate or register) */ +static int32_t eval_if_version_1(command_t* command) { + uint8_t op = vm_getbits(command, 54, 3); + if(op) { + return eval_compare(op, eval_reg(command, vm_getbits(command, 39, 8)), + eval_reg_or_data(command, vm_getbits(command, 55, 1), 31)); + } + return 1; +} + +/* Evaluate if version 2. + This version only compares register which are in byte 6 and 7 */ +static int32_t eval_if_version_2(command_t* command) { + uint8_t op = vm_getbits(command, 54, 3); + if(op) { + return eval_compare(op, eval_reg(command, vm_getbits(command, 15, 8)), + eval_reg(command, vm_getbits(command, 7, 8))); + } + return 1; +} + +/* Evaluate if version 3. + Has comparison data in byte 2 and 6-7 (immediate or register) */ +static int32_t eval_if_version_3(command_t* command) { + uint8_t op = vm_getbits(command, 54, 3); + if(op) { + return eval_compare(op, eval_reg(command, vm_getbits(command, 47, 8)), + eval_reg_or_data(command, vm_getbits(command, 55, 1), 15)); + } + return 1; +} + +/* Evaluate if version 4. + Has comparison data in byte 1 and 4-5 (immediate or register) + The register in byte 1 is only the lowe nibble (4 bits) */ +static int32_t eval_if_version_4(command_t* command) { + uint8_t op = vm_getbits(command, 54, 3); + if(op) { + return eval_compare(op, eval_reg(command, vm_getbits(command, 51, 4)), + eval_reg_or_data(command, vm_getbits(command, 55, 1), 31)); + } + return 1; +} + +/* Evaluate special instruction.... returns the new row/line number, + 0 if no new row and 256 if Break. */ +static int32_t eval_special_instruction(command_t* command, int32_t cond) { + int32_t line, level; + + switch(vm_getbits(command, 51, 4)) { + case 0: /* NOP */ + line = 0; + return cond ? line : 0; + case 1: /* Goto line */ + line = vm_getbits(command, 7, 8); + return cond ? line : 0; + case 2: /* Break */ + /* max number of rows < 256, so we will end this set */ + line = 256; + return cond ? 256 : 0; + case 3: /* Set temporary parental level and goto */ + line = vm_getbits(command, 7, 8); + level = vm_getbits(command, 11, 4); + if(cond) { + /* This always succeeds now, if we want real parental protection */ + /* we need to ask the user and have passwords and stuff. */ + command->registers->SPRM[13] = level; + } + return cond ? line : 0; + } + return 0; +} + +/* Evaluate link by subinstruction. + Return 1 if link, or 0 if no link + Actual link instruction is in return_values parameter */ +static int32_t eval_link_subins(command_t* command, int32_t cond, link_t *return_values) { + uint16_t button = vm_getbits(command, 15, 6); + uint8_t linkop = vm_getbits(command, 4, 5); + + if(linkop > 0x10) + return 0; /* Unknown Link by Sub-Instruction command */ + + /* Assumes that the link_cmd_t enum has the same values as the LinkSIns codes */ + return_values->command = linkop; + return_values->data1 = button; + return cond; +} + + +/* Evaluate link instruction. + Return 1 if link, or 0 if no link + Actual link instruction is in return_values parameter */ +static int32_t eval_link_instruction(command_t* command, int32_t cond, link_t *return_values) { + uint8_t op = vm_getbits(command, 51, 4); + + switch(op) { + case 1: + return eval_link_subins(command, cond, return_values); + case 4: + return_values->command = LinkPGCN; + return_values->data1 = vm_getbits(command, 14, 15); + return cond; + case 5: + return_values->command = LinkPTTN; + return_values->data1 = vm_getbits(command, 9, 10); + return_values->data2 = vm_getbits(command, 15, 6); + return cond; + case 6: + return_values->command = LinkPGN; + return_values->data1 = vm_getbits(command, 6, 7); + return_values->data2 = vm_getbits(command, 15, 6); + return cond; + case 7: + return_values->command = LinkCN; + return_values->data1 = vm_getbits(command, 7, 8); + return_values->data2 = vm_getbits(command, 15, 6); + return cond; + } + return 0; +} + + +/* Evaluate a jump instruction. + returns 1 if jump or 0 if no jump + actual jump instruction is in return_values parameter */ +static int32_t eval_jump_instruction(command_t* command, int32_t cond, link_t *return_values) { + + switch(vm_getbits(command, 51, 4)) { + case 1: + return_values->command = Exit; + return cond; + case 2: + return_values->command = JumpTT; + return_values->data1 = vm_getbits(command, 22, 7); + return cond; + case 3: + return_values->command = JumpVTS_TT; + return_values->data1 = vm_getbits(command, 22, 7); + return cond; + case 5: + return_values->command = JumpVTS_PTT; + return_values->data1 = vm_getbits(command, 22, 7); + return_values->data2 = vm_getbits(command, 41, 10); + return cond; + case 6: + switch(vm_getbits(command, 23, 2)) { + case 0: + return_values->command = JumpSS_FP; + return cond; + case 1: + return_values->command = JumpSS_VMGM_MENU; + return_values->data1 = vm_getbits(command, 19, 4); + return cond; + case 2: + return_values->command = JumpSS_VTSM; + return_values->data1 = vm_getbits(command, 31, 8); + return_values->data2 = vm_getbits(command, 39, 8); + return_values->data3 = vm_getbits(command, 19, 4); + return cond; + case 3: + return_values->command = JumpSS_VMGM_PGC; + return_values->data1 = vm_getbits(command, 46, 15); + return cond; + } + break; + case 8: + switch(vm_getbits(command, 23, 2)) { + case 0: + return_values->command = CallSS_FP; + return_values->data1 = vm_getbits(command, 31, 8); + return cond; + case 1: + return_values->command = CallSS_VMGM_MENU; + return_values->data1 = vm_getbits(command, 19, 4); + return_values->data2 = vm_getbits(command, 31, 8); + return cond; + case 2: + return_values->command = CallSS_VTSM; + return_values->data1 = vm_getbits(command, 19, 4); + return_values->data2 = vm_getbits(command, 31, 8); + return cond; + case 3: + return_values->command = CallSS_VMGM_PGC; + return_values->data1 = vm_getbits(command, 46, 15); + return_values->data2 = vm_getbits(command, 31, 8); + return cond; + } + break; + } + return 0; +} + +/* Evaluate a set sytem register instruction + May contain a link so return the same as eval_link */ +static int32_t eval_system_set(command_t* command, int32_t cond, link_t *return_values) { + int32_t i; + uint16_t data, data2; + + switch(vm_getbits(command, 59, 4)) { + case 1: /* Set system reg 1 &| 2 &| 3 (Audio, Subp. Angle) */ + for(i = 1; i <= 3; i++) { + if(vm_getbits(command, 63 - ((2 + i)*8), 1)) { + data = eval_reg_or_data_2(command, vm_getbits(command, 60, 1), (47 - (i*8))); + if(cond) { + command->registers->SPRM[i] = data; + } + } + } + break; + case 2: /* Set system reg 9 & 10 (Navigation timer, Title PGC number) */ + data = eval_reg_or_data(command, vm_getbits(command, 60, 1), 47); + data2 = vm_getbits(command, 23, 8); /* ?? size */ + if(cond) { + command->registers->SPRM[9] = data; /* time */ + command->registers->SPRM[10] = data2; /* pgcN */ + } + break; + case 3: /* Mode: Counter / Register + Set */ + data = eval_reg_or_data(command, vm_getbits(command, 60, 1), 47); + data2 = vm_getbits(command, 19, 4); + if(vm_getbits(command, 23, 1)) { + command->registers->GPRM_mode[data2] |= 1; /* Set bit 0 */ + } else { + command->registers->GPRM_mode[data2] &= ~ 0x01; /* Reset bit 0 */ + } + if(cond) { + set_GPRM(command->registers, data2, data); + } + break; + case 6: /* Set system reg 8 (Highlighted button) */ + data = eval_reg_or_data(command, vm_getbits(command, 60, 1), 31); /* Not system reg!! */ + if(cond) { + command->registers->SPRM[8] = data; + } + break; + } + if(vm_getbits(command, 51, 4)) { + return eval_link_instruction(command, cond, return_values); + } + return 0; +} + + +/* Evaluate set operation + Sets the register given to the value indicated by op and data. + For the swap case the contents of reg is stored in reg2. +*/ +static void eval_set_op(command_t* command, int32_t op, int32_t reg, int32_t reg2, int32_t data) { + static const int32_t shortmax = 0xffff; + int32_t tmp; + switch(op) { + case 1: + set_GPRM(command->registers, reg, data); + break; + case 2: /* SPECIAL CASE - SWAP! */ + set_GPRM(command->registers, reg2, get_GPRM(command->registers, reg)); + set_GPRM(command->registers, reg, data); + break; + case 3: + tmp = get_GPRM(command->registers, reg) + data; + if(tmp > shortmax) tmp = shortmax; + set_GPRM(command->registers, reg, (uint16_t)tmp); + break; + case 4: + tmp = get_GPRM(command->registers, reg) - data; + if(tmp < 0) tmp = 0; + set_GPRM(command->registers, reg, (uint16_t)tmp); + break; + case 5: + tmp = get_GPRM(command->registers, reg) * data; + if(tmp > shortmax) tmp = shortmax; + set_GPRM(command->registers, reg, (uint16_t)tmp); + break; + case 6: + if (data != 0) { + set_GPRM(command->registers, reg, (get_GPRM(command->registers, reg) / data) ); + } else { + set_GPRM(command->registers, reg, 0xffff); /* Avoid that divide by zero! */ + } + break; + case 7: + if (data != 0) { + set_GPRM(command->registers, reg, (get_GPRM(command->registers, reg) % data) ); + } else { + set_GPRM(command->registers, reg, 0xffff); /* Avoid that divide by zero! */ + } + break; + case 8: /* SPECIAL CASE - RND! Return numbers between 1 and data. */ + set_GPRM(command->registers, reg, 1 + ((uint16_t) ((float) data * rand()/(RAND_MAX+1.0))) ); + break; + case 9: + set_GPRM(command->registers, reg, (get_GPRM(command->registers, reg) & data) ); + break; + case 10: + set_GPRM(command->registers, reg, (get_GPRM(command->registers, reg) | data) ); + break; + case 11: + set_GPRM(command->registers, reg, (get_GPRM(command->registers, reg) ^ data) ); + break; + } +} + +/* Evaluate set instruction, combined with either Link or Compare. */ +static void eval_set_version_1(command_t* command, int32_t cond) { + uint8_t op = vm_getbits(command, 59, 4); + uint8_t reg = vm_getbits(command, 35, 4); /* FIXME: This is different from vmcmd.c!!! */ + uint8_t reg2 = vm_getbits(command, 19, 4); + uint16_t data = eval_reg_or_data(command, vm_getbits(command, 60, 1), 31); + + if(cond) { + eval_set_op(command, op, reg, reg2, data); + } +} + + +/* Evaluate set instruction, combined with both Link and Compare. */ +static void eval_set_version_2(command_t* command, int32_t cond) { + uint8_t op = vm_getbits(command, 59, 4); + uint8_t reg = vm_getbits(command, 51, 4); + uint8_t reg2 = vm_getbits(command, 35, 4); /* FIXME: This is different from vmcmd.c!!! */ + uint16_t data = eval_reg_or_data(command, vm_getbits(command, 60, 1), 47); + + if(cond) { + eval_set_op(command, op, reg, reg2, data); + } +} + + +/* Evaluate a command + returns row number of goto, 0 if no goto, -1 if link. + Link command in return_values */ +static int32_t eval_command(uint8_t *bytes, registers_t* registers, link_t *return_values) { + int32_t cond, res = 0; + command_t command; + command.instruction =( (uint64_t) bytes[0] << 56 ) | + ( (uint64_t) bytes[1] << 48 ) | + ( (uint64_t) bytes[2] << 40 ) | + ( (uint64_t) bytes[3] << 32 ) | + ( (uint64_t) bytes[4] << 24 ) | + ( (uint64_t) bytes[5] << 16 ) | + ( (uint64_t) bytes[6] << 8 ) | + (uint64_t) bytes[7] ; + command.examined = 0; + command.registers = registers; + memset(return_values, 0, sizeof(link_t)); + + switch(vm_getbits(&command, 63, 3)) { /* three first old_bits */ + case 0: /* Special instructions */ + cond = eval_if_version_1(&command); + res = eval_special_instruction(&command, cond); + if(res == -1) { + fprintf(MSG_OUT, "libdvdnav: Unknown Instruction!\n"); + abort(); + } + break; + case 1: /* Link/jump instructions */ + if(vm_getbits(&command, 60, 1)) { + cond = eval_if_version_2(&command); + res = eval_jump_instruction(&command, cond, return_values); + } else { + cond = eval_if_version_1(&command); + res = eval_link_instruction(&command, cond, return_values); + } + if(res) + res = -1; + break; + case 2: /* System set instructions */ + cond = eval_if_version_2(&command); + res = eval_system_set(&command, cond, return_values); + if(res) + res = -1; + break; + case 3: /* Set instructions, either Compare or Link may be used */ + cond = eval_if_version_3(&command); + eval_set_version_1(&command, cond); + if(vm_getbits(&command, 51, 4)) { + res = eval_link_instruction(&command, cond, return_values); + } + if(res) + res = -1; + break; + case 4: /* Set, Compare -> Link Sub-Instruction */ + eval_set_version_2(&command, /*True*/ 1); + cond = eval_if_version_4(&command); + res = eval_link_subins(&command, cond, return_values); + if(res) + res = -1; + break; + case 5: /* Compare -> (Set and Link Sub-Instruction) */ + /* FIXME: These are wrong. Need to be updated from vmcmd.c */ + cond = eval_if_version_4(&command); + eval_set_version_2(&command, cond); + res = eval_link_subins(&command, cond, return_values); + if(res) + res = -1; + break; + case 6: /* Compare -> Set, allways Link Sub-Instruction */ + /* FIXME: These are wrong. Need to be updated from vmcmd.c */ + cond = eval_if_version_4(&command); + eval_set_version_2(&command, cond); + res = eval_link_subins(&command, /*True*/ 1, return_values); + if(res) + res = -1; + break; + default: /* Unknown command */ + fprintf(MSG_OUT, "libdvdnav: WARNING: Unknown Command=%x\n", vm_getbits(&command, 63, 3)); + abort(); + } + /* Check if there are bits not yet examined */ + + if(command.instruction & ~ command.examined) { + fprintf(MSG_OUT, "libdvdnav: decoder.c: [WARNING, unknown bits:"); + fprintf(MSG_OUT, " %08"PRIx64, (command.instruction & ~ command.examined) ); + fprintf(MSG_OUT, "]\n"); + } + + return res; +} + +/* Evaluate a set of commands in the given register set (which is modified) */ +int32_t vmEval_CMD(vm_cmd_t commands[], int32_t num_commands, + registers_t *registers, link_t *return_values) { + int32_t i = 0; + int32_t total = 0; + +#ifdef TRACE + /* DEBUG */ + fprintf(MSG_OUT, "libdvdnav: Registers before transaction\n"); + vm_print_registers( registers ); + fprintf(MSG_OUT, "libdvdnav: Full list of commands to execute\n"); + for(i = 0; i < num_commands; i++) + vm_print_cmd(i, &commands[i]); + fprintf(MSG_OUT, "libdvdnav: --------------------------------------------\n"); + fprintf(MSG_OUT, "libdvdnav: Single stepping commands\n"); +#endif + + i = 0; + while(i < num_commands && total < 100000) { + int32_t line; + +#ifdef TRACE + vm_print_cmd(i, &commands[i]); +#endif + + line = eval_command(&commands[i].bytes[0], registers, return_values); + + if (line < 0) { /* Link command */ +#ifdef TRACE + fprintf(MSG_OUT, "libdvdnav: Registers after transaction\n"); + vm_print_registers( registers ); + fprintf(MSG_OUT, "libdvdnav: eval: Doing Link/Jump/Call\n"); +#endif + return 1; + } + + if (line > 0) /* Goto command */ + i = line - 1; + else /* Just continue on the next line */ + i++; + + total++; + } + + memset(return_values, 0, sizeof(link_t)); +#ifdef TRACE + fprintf(MSG_OUT, "libdvdnav: Registers after transaction\n"); + vm_print_registers( registers ); +#endif + return 0; +} + +#ifdef TRACE + +static char *linkcmd2str(link_cmd_t cmd) { + switch(cmd) { + case LinkNoLink: + return "LinkNoLink"; + case LinkTopC: + return "LinkTopC"; + case LinkNextC: + return "LinkNextC"; + case LinkPrevC: + return "LinkPrevC"; + case LinkTopPG: + return "LinkTopPG"; + case LinkNextPG: + return "LinkNextPG"; + case LinkPrevPG: + return "LinkPrevPG"; + case LinkTopPGC: + return "LinkTopPGC"; + case LinkNextPGC: + return "LinkNextPGC"; + case LinkPrevPGC: + return "LinkPrevPGC"; + case LinkGoUpPGC: + return "LinkGoUpPGC"; + case LinkTailPGC: + return "LinkTailPGC"; + case LinkRSM: + return "LinkRSM"; + case LinkPGCN: + return "LinkPGCN"; + case LinkPTTN: + return "LinkPTTN"; + case LinkPGN: + return "LinkPGN"; + case LinkCN: + return "LinkCN"; + case Exit: + return "Exit"; + case JumpTT: + return "JumpTT"; + case JumpVTS_TT: + return "JumpVTS_TT"; + case JumpVTS_PTT: + return "JumpVTS_PTT"; + case JumpSS_FP: + return "JumpSS_FP"; + case JumpSS_VMGM_MENU: + return "JumpSS_VMGM_MENU"; + case JumpSS_VTSM: + return "JumpSS_VTSM"; + case JumpSS_VMGM_PGC: + return "JumpSS_VMGM_PGC"; + case CallSS_FP: + return "CallSS_FP"; + case CallSS_VMGM_MENU: + return "CallSS_VMGM_MENU"; + case CallSS_VTSM: + return "CallSS_VTSM"; + case CallSS_VMGM_PGC: + return "CallSS_VMGM_PGC"; + case PlayThis: + return "PlayThis"; + } + return "*** (bug)"; +} + +void vm_print_link(link_t value) { + char *cmd = linkcmd2str(value.command); + + switch(value.command) { + case LinkNoLink: + case LinkTopC: + case LinkNextC: + case LinkPrevC: + case LinkTopPG: + case LinkNextPG: + case LinkPrevPG: + case LinkTopPGC: + case LinkNextPGC: + case LinkPrevPGC: + case LinkGoUpPGC: + case LinkTailPGC: + case LinkRSM: + fprintf(MSG_OUT, "libdvdnav: %s (button %d)\n", cmd, value.data1); + break; + case LinkPGCN: + case JumpTT: + case JumpVTS_TT: + case JumpSS_VMGM_MENU: /* == 2 -> Title Menu */ + case JumpSS_VMGM_PGC: + fprintf(MSG_OUT, "libdvdnav: %s %d\n", cmd, value.data1); + break; + case LinkPTTN: + case LinkPGN: + case LinkCN: + fprintf(MSG_OUT, "libdvdnav: %s %d (button %d)\n", cmd, value.data1, value.data2); + break; + case Exit: + case JumpSS_FP: + case PlayThis: /* Humm.. should we have this at all.. */ + fprintf(MSG_OUT, "libdvdnav: %s\n", cmd); + break; + case JumpVTS_PTT: + fprintf(MSG_OUT, "libdvdnav: %s %d:%d\n", cmd, value.data1, value.data2); + break; + case JumpSS_VTSM: + fprintf(MSG_OUT, "libdvdnav: %s vts %d title %d menu %d\n", + cmd, value.data1, value.data2, value.data3); + break; + case CallSS_FP: + fprintf(MSG_OUT, "libdvdnav: %s resume cell %d\n", cmd, value.data1); + break; + case CallSS_VMGM_MENU: /* == 2 -> Title Menu */ + case CallSS_VTSM: + fprintf(MSG_OUT, "libdvdnav: %s %d resume cell %d\n", cmd, value.data1, value.data2); + break; + case CallSS_VMGM_PGC: + fprintf(MSG_OUT, "libdvdnav: %s %d resume cell %d\n", cmd, value.data1, value.data2); + break; + } + } + +void vm_print_registers( registers_t *registers ) { + int32_t i; + fprintf(MSG_OUT, "libdvdnav: # "); + for(i = 0; i < 24; i++) + fprintf(MSG_OUT, " %2d |", i); + fprintf(MSG_OUT, "\nlibdvdnav: SRPMS: "); + for(i = 0; i < 24; i++) + fprintf(MSG_OUT, "%04x|", registers->SPRM[i]); + fprintf(MSG_OUT, "\nlibdvdnav: GRPMS: "); + for(i = 0; i < 16; i++) + fprintf(MSG_OUT, "%04x|", get_GPRM(registers, i) ); + fprintf(MSG_OUT, "\nlibdvdnav: Gmode: "); + for(i = 0; i < 16; i++) + fprintf(MSG_OUT, "%04x|", registers->GPRM_mode[i]); + fprintf(MSG_OUT, "\nlibdvdnav: Gtime: "); + for(i = 0; i < 16; i++) + fprintf(MSG_OUT, "%04lx|", registers->GPRM_time[i].tv_sec & 0xffff); + fprintf(MSG_OUT, "\n"); +} + +#endif + diff --git a/lib/libdvd/libdvdnav/src/vm/decoder.h b/lib/libdvd/libdvdnav/src/vm/decoder.h new file mode 100644 index 0000000000..1e834a786d --- /dev/null +++ b/lib/libdvd/libdvdnav/src/vm/decoder.h @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2000, 2001 Martin Norbäck, Håkan Hjort + * + * This file is part of libdvdnav, a DVD navigation library. It is modified + * from a file originally part of the Ogle DVD player. + * + * libdvdnav 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. + * + * libdvdnav 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 + * + * $Id: decoder.h 1135 2008-09-06 21:55:51Z rathann $ + * + */ + +#ifndef DECODER_H_INCLUDED +#define DECODER_H_INCLUDED + +/* link command types */ +typedef enum { + LinkNoLink = 0, + + LinkTopC = 1, + LinkNextC = 2, + LinkPrevC = 3, + + LinkTopPG = 5, + LinkNextPG = 6, + LinkPrevPG = 7, + + LinkTopPGC = 9, + LinkNextPGC = 10, + LinkPrevPGC = 11, + LinkGoUpPGC = 12, + LinkTailPGC = 13, + + LinkRSM = 16, + + LinkPGCN, + LinkPTTN, + LinkPGN, + LinkCN, + + Exit, + + JumpTT, /* 22 */ + JumpVTS_TT, + JumpVTS_PTT, + + JumpSS_FP, + JumpSS_VMGM_MENU, + JumpSS_VTSM, + JumpSS_VMGM_PGC, + + CallSS_FP, /* 29 */ + CallSS_VMGM_MENU, + CallSS_VTSM, + CallSS_VMGM_PGC, + + PlayThis +} link_cmd_t; + +/* a link's data set */ +typedef struct { + link_cmd_t command; + uint16_t data1; + uint16_t data2; + uint16_t data3; +} link_t; + +/* the VM registers */ +typedef struct { + uint16_t SPRM[24]; + uint16_t GPRM[16]; + uint8_t GPRM_mode[16]; /* Need to have some thing to indicate normal/counter mode for every GPRM */ + struct timeval GPRM_time[16]; /* For counter mode */ +} registers_t; + +/* a VM command data set */ +typedef struct { + uint64_t instruction; + uint64_t examined; + registers_t *registers; +} command_t; + +/* the big VM function, executing the given commands and writing + * the link where to continue, the return value indicates if a jump + * has been performed */ +int32_t vmEval_CMD(vm_cmd_t commands[], int32_t num_commands, + registers_t *registers, link_t *return_values); + +/* extracts some bits from the command */ +uint32_t vm_getbits(command_t* command, int32_t start, int32_t count); + +#ifdef TRACE +/* for debugging: prints a link in readable form */ +void vm_print_link(link_t value); + +/* for debugging: dumps VM registers */ +void vm_print_registers( registers_t *registers ); +#endif + +#endif /* DECODER_H_INCLUDED */ diff --git a/lib/libdvd/libdvdnav/src/vm/vm.c b/lib/libdvd/libdvdnav/src/vm/vm.c new file mode 100644 index 0000000000..9c9a5c4d2a --- /dev/null +++ b/lib/libdvd/libdvdnav/src/vm/vm.c @@ -0,0 +1,1947 @@ +/* + * Copyright (C) 2000, 2001 Håkan Hjort + * Copyright (C) 2001 Rich Wareham <richwareham@users.sourceforge.net> + * 2002-2004 the dvdnav project + * + * This file is part of libdvdnav, a DVD navigation library. It is modified + * from a file originally part of the Ogle DVD player. + * + * libdvdnav 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. + * + * libdvdnav 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 + * + * $Id: vm.c 1135 2008-09-06 21:55:51Z rathann $ + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <inttypes.h> +#include <limits.h> +#include <assert.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <fcntl.h> + +#include <dvdread/nav_types.h> +#include <dvdread/ifo_types.h> +#include <dvdread/ifo_read.h> +#include "dvd_types.h" + +#include "decoder.h" +#include "remap.h" +#include "vm.h" +#include "dvdnav.h" +#include "dvdnav_internal.h" + +#ifdef _MSC_VER +#include <io.h> /* read() */ +#endif /* _MSC_VER */ + +/* +#define STRICT +*/ + +/* Local prototypes */ + +/* get_XYZ returns a value. + * set_XYZ sets state using passed parameters. + * returns success/failure. + */ + +/* Play */ +static link_t play_PGC(vm_t *vm); +static link_t play_PGC_PG(vm_t *vm, int pgN); +static link_t play_PGC_post(vm_t *vm); +static link_t play_PG(vm_t *vm); +static link_t play_Cell(vm_t *vm); +static link_t play_Cell_post(vm_t *vm); + +/* Process link - returns 1 if a hop has been performed */ +static int process_command(vm_t *vm,link_t link_values); + +/* Set */ +static int set_TT(vm_t *vm, int tt); +static int set_PTT(vm_t *vm, int tt, int ptt); +static int set_VTS_TT(vm_t *vm, int vtsN, int vts_ttn); +static int set_VTS_PTT(vm_t *vm, int vtsN, int vts_ttn, int part); +static int set_FP_PGC(vm_t *vm); +static int set_MENU(vm_t *vm, int menu); +static int set_PGCN(vm_t *vm, int pgcN); +static int set_PGN(vm_t *vm); /* Set PGN based on (vm->state).CellN */ +static void set_RSMinfo(vm_t *vm, int cellN, int blockN); + +/* Get */ +static int get_TT(vm_t *vm, int vtsN, int vts_ttn); +static int get_ID(vm_t *vm, int id); +static int get_PGCN(vm_t *vm); + +static pgcit_t* get_MENU_PGCIT(vm_t *vm, ifo_handle_t *h, uint16_t lang); +static pgcit_t* get_PGCIT(vm_t *vm); + + +/* Helper functions */ + +#ifdef TRACE +static void vm_print_current_domain_state(vm_t *vm) { + switch((vm->state).domain) { + case VTS_DOMAIN: + fprintf(MSG_OUT, "libdvdnav: Video Title Domain: -\n"); + break; + + case VTSM_DOMAIN: + fprintf(MSG_OUT, "libdvdnav: Video Title Menu Domain: -\n"); + break; + + case VMGM_DOMAIN: + fprintf(MSG_OUT, "libdvdnav: Video Manager Menu Domain: -\n"); + break; + + case FP_DOMAIN: + fprintf(MSG_OUT, "libdvdnav: First Play Domain: -\n"); + break; + + default: + fprintf(MSG_OUT, "libdvdnav: Unknown Domain: -\n"); + break; + } + fprintf(MSG_OUT, "libdvdnav: VTS:%d PGC:%d PG:%u CELL:%u BLOCK:%u VTS_TTN:%u TTN:%u TT_PGCN:%u\n", + (vm->state).vtsN, + get_PGCN(vm), + (vm->state).pgN, + (vm->state).cellN, + (vm->state).blockN, + (vm->state).VTS_TTN_REG, + (vm->state).TTN_REG, + (vm->state).TT_PGCN_REG); +} +#endif + +static void dvd_read_name(char *name, const char *device) { + /* Because we are compiling with _FILE_OFFSET_BITS=64 + * all off_t are 64bit. + */ + off_t off; + int fd, i; + uint8_t data[DVD_VIDEO_LB_LEN]; + + /* Read DVD name */ + fd = open(device, O_RDONLY); + if (fd > 0) { + off = lseek( fd, 32 * (off_t) DVD_VIDEO_LB_LEN, SEEK_SET ); + if( off == ( 32 * (off_t) DVD_VIDEO_LB_LEN ) ) { + off = read( fd, data, DVD_VIDEO_LB_LEN ); + close(fd); + if (off == ( (off_t) DVD_VIDEO_LB_LEN )) { + fprintf(MSG_OUT, "libdvdnav: DVD Title: "); + for(i=25; i < 73; i++ ) { + if((data[i] == 0)) break; + if((data[i] > 32) && (data[i] < 127)) { + fprintf(MSG_OUT, "%c", data[i]); + } else { + fprintf(MSG_OUT, " "); + } + } + strncpy(name, (char*) &data[25], 48); + name[48] = 0; + fprintf(MSG_OUT, "\nlibdvdnav: DVD Serial Number: "); + for(i=73; i < 89; i++ ) { + if((data[i] == 0)) break; + if((data[i] > 32) && (data[i] < 127)) { + fprintf(MSG_OUT, "%c", data[i]); + } else { + fprintf(MSG_OUT, " "); + } + } + fprintf(MSG_OUT, "\nlibdvdnav: DVD Title (Alternative): "); + for(i=89; i < 128; i++ ) { + if((data[i] == 0)) break; + if((data[i] > 32) && (data[i] < 127)) { + fprintf(MSG_OUT, "%c", data[i]); + } else { + fprintf(MSG_OUT, " "); + } + } + fprintf(MSG_OUT, "\n"); + } else { + fprintf(MSG_OUT, "libdvdnav: Can't read name block. Probably not a DVD-ROM device.\n"); + } + } else { + fprintf(MSG_OUT, "libdvdnav: Can't seek to block %u\n", 32 ); + } + close(fd); + } else { + fprintf(MSG_OUT, "NAME OPEN FAILED\n"); + } +} + +static int ifoOpenNewVTSI(vm_t *vm, dvd_reader_t *dvd, int vtsN) { + if((vm->state).vtsN == vtsN) { + return 1; /* We alread have it */ + } + + if(vm->vtsi != NULL) + ifoClose(vm->vtsi); + + vm->vtsi = ifoOpenVTSI(dvd, vtsN); + if(vm->vtsi == NULL) { + fprintf(MSG_OUT, "libdvdnav: ifoOpenVTSI failed\n"); + return 0; + } + if(!ifoRead_VTS_PTT_SRPT(vm->vtsi)) { + fprintf(MSG_OUT, "libdvdnav: ifoRead_VTS_PTT_SRPT failed\n"); + return 0; + } + if(!ifoRead_PGCIT(vm->vtsi)) { + fprintf(MSG_OUT, "libdvdnav: ifoRead_PGCIT failed\n"); + return 0; + } + if(!ifoRead_PGCI_UT(vm->vtsi)) { + fprintf(MSG_OUT, "libdvdnav: ifoRead_PGCI_UT failed\n"); + return 0; + } + if(!ifoRead_VOBU_ADMAP(vm->vtsi)) { + fprintf(MSG_OUT, "libdvdnav: ifoRead_VOBU_ADMAP vtsi failed\n"); + return 0; + } + if(!ifoRead_TITLE_VOBU_ADMAP(vm->vtsi)) { + fprintf(MSG_OUT, "libdvdnav: ifoRead_TITLE_VOBU_ADMAP vtsi failed\n"); + return 0; + } + if(!ifoRead_VTS_TMAPT(vm->vtsi)) { + fprintf(MSG_OUT, "libdvdnav: ifoRead_VTS_TMAPT vtsi failed\n"); + return 0; + } + if(!ifoRead_TITLE_C_ADT(vm->vtsi)) { + fprintf(MSG_OUT, "libdvdnav: ifoRead_TITLE_C_ADT vtsi failed\n"); + return 0; + } + + (vm->state).vtsN = vtsN; + + return 1; +} + + +/* Initialisation & Destruction */ + +vm_t* vm_new_vm() { + return (vm_t*)calloc(sizeof(vm_t), sizeof(char)); +} + +void vm_free_vm(vm_t *vm) { + vm_stop(vm); + free(vm); +} + + +/* IFO Access */ + +ifo_handle_t *vm_get_vmgi(vm_t *vm) { + return vm->vmgi; +} + +ifo_handle_t *vm_get_vtsi(vm_t *vm) { + return vm->vtsi; +} + + +/* Reader Access */ + +dvd_reader_t *vm_get_dvd_reader(vm_t *vm) { + return vm->dvd; +} + + +/* Basic Handling */ + +int vm_start(vm_t *vm) { + /* Set pgc to FP (First Play) pgc */ + set_FP_PGC(vm); + process_command(vm, play_PGC(vm)); + return !vm->stopped; +} + +void vm_stop(vm_t *vm) { + if(vm->vmgi) { + ifoClose(vm->vmgi); + vm->vmgi=NULL; + } + if(vm->vtsi) { + ifoClose(vm->vtsi); + vm->vtsi=NULL; + } + if(vm->dvd) { + DVDClose(vm->dvd); + vm->dvd=NULL; + } + vm->stopped = 1; +} + +int vm_reset(vm_t *vm, const char *dvdroot) { + /* Setup State */ + memset((vm->state).registers.SPRM, 0, sizeof((vm->state).registers.SPRM)); + memset((vm->state).registers.GPRM, 0, sizeof((vm->state).registers.GPRM)); + memset((vm->state).registers.GPRM_mode, 0, sizeof((vm->state).registers.GPRM_mode)); + memset((vm->state).registers.GPRM_mode, 0, sizeof((vm->state).registers.GPRM_mode)); + memset((vm->state).registers.GPRM_time, 0, sizeof((vm->state).registers.GPRM_time)); + (vm->state).registers.SPRM[0] = ('e'<<8)|'n'; /* Player Menu Languange code */ + (vm->state).AST_REG = 15; /* 15 why? */ + (vm->state).SPST_REG = 62; /* 62 why? */ + (vm->state).AGL_REG = 1; + (vm->state).TTN_REG = 1; + (vm->state).VTS_TTN_REG = 1; + /* (vm->state).TT_PGCN_REG = 0 */ + (vm->state).PTTN_REG = 1; + (vm->state).HL_BTNN_REG = 1 << 10; + (vm->state).PTL_REG = 15; /* Parental Level */ + (vm->state).registers.SPRM[12] = ('U'<<8)|'S'; /* Parental Management Country Code */ + (vm->state).registers.SPRM[16] = ('e'<<8)|'n'; /* Initial Language Code for Audio */ + (vm->state).registers.SPRM[18] = ('e'<<8)|'n'; /* Initial Language Code for Spu */ + (vm->state).registers.SPRM[20] = 0x1; /* Player Regional Code Mask. Region free! */ + (vm->state).registers.SPRM[14] = 0x100; /* Try Pan&Scan */ + + (vm->state).pgN = 0; + (vm->state).cellN = 0; + (vm->state).cell_restart = 0; + + (vm->state).domain = FP_DOMAIN; + (vm->state).rsm_vtsN = 0; + (vm->state).rsm_cellN = 0; + (vm->state).rsm_blockN = 0; + + (vm->state).vtsN = -1; + + if (vm->dvd && dvdroot) { + /* a new dvd device has been requested */ + vm_stop(vm); + } + if (!vm->dvd) { + vm->dvd = DVDOpen(dvdroot); + if(!vm->dvd) { + fprintf(MSG_OUT, "libdvdnav: vm: failed to open/read the DVD\n"); + return 0; + } +#ifdef _XBMC + if(DVDUDFVolumeInfo(vm->dvd, vm->dvd_name, sizeof(vm->dvd_name), NULL, 0)) + if(DVDISOVolumeInfo(vm->dvd, vm->dvd_name, sizeof(vm->dvd_name), NULL, 0)) + strcpy(vm->dvd_name, ""); + + fprintf(MSG_OUT, "libdvdnav: vm: DVD Title: %s\n", vm->dvd_name); +#else + dvd_read_name(vm->dvd_name, dvdroot); +#endif + vm->map = remap_loadmap(vm->dvd_name); + vm->vmgi = ifoOpenVMGI(vm->dvd); + if(!vm->vmgi) { + fprintf(MSG_OUT, "libdvdnav: vm: failed to read VIDEO_TS.IFO\n"); + return 0; + } + if(!ifoRead_FP_PGC(vm->vmgi)) { + fprintf(MSG_OUT, "libdvdnav: vm: ifoRead_FP_PGC failed\n"); + return 0; + } + if(!ifoRead_TT_SRPT(vm->vmgi)) { + fprintf(MSG_OUT, "libdvdnav: vm: ifoRead_TT_SRPT failed\n"); + return 0; + } + if(!ifoRead_PGCI_UT(vm->vmgi)) { + fprintf(MSG_OUT, "libdvdnav: vm: ifoRead_PGCI_UT failed\n"); + return 0; + } + if(!ifoRead_PTL_MAIT(vm->vmgi)) { + fprintf(MSG_OUT, "libdvdnav: vm: ifoRead_PTL_MAIT failed\n"); + /* return 0; Not really used for now.. */ + } + if(!ifoRead_VTS_ATRT(vm->vmgi)) { + fprintf(MSG_OUT, "libdvdnav: vm: ifoRead_VTS_ATRT failed\n"); + /* return 0; Not really used for now.. */ + } + if(!ifoRead_VOBU_ADMAP(vm->vmgi)) { + fprintf(MSG_OUT, "libdvdnav: vm: ifoRead_VOBU_ADMAP vgmi failed\n"); + /* return 0; Not really used for now.. */ + } + /* ifoRead_TXTDT_MGI(vmgi); Not implemented yet */ + } + if (vm->vmgi) { + int i, mask; + fprintf(MSG_OUT, "libdvdnav: DVD disk reports itself with Region mask 0x%08x. Regions:", + vm->vmgi->vmgi_mat->vmg_category); + for (i = 1, mask = 1; i <= 8; i++, mask <<= 1) + if (((vm->vmgi->vmgi_mat->vmg_category >> 16) & mask) == 0) + fprintf(MSG_OUT, " %d", i); + fprintf(MSG_OUT, "\n"); + } + return 1; +} + + +/* copying and merging */ + +vm_t *vm_new_copy(vm_t *source) { + vm_t *target = vm_new_vm(); + int vtsN; + int pgcN = get_PGCN(source); + int pgN = (source->state).pgN; + + assert(pgcN); + + memcpy(target, source, sizeof(vm_t)); + + /* open a new vtsi handle, because the copy might switch to another VTS */ + target->vtsi = NULL; + vtsN = (target->state).vtsN; + if (vtsN > 0) { + (target->state).vtsN = 0; + if (!ifoOpenNewVTSI(target, target->dvd, vtsN)) + assert(0); + + /* restore pgc pointer into the new vtsi */ + if (!set_PGCN(target, pgcN)) + assert(0); + (target->state).pgN = pgN; + } + + return target; +} + +void vm_merge(vm_t *target, vm_t *source) { + if(target->vtsi) + ifoClose(target->vtsi); + memcpy(target, source, sizeof(vm_t)); + memset(source, 0, sizeof(vm_t)); +} + +void vm_free_copy(vm_t *vm) { + if(vm->vtsi) + ifoClose(vm->vtsi); + free(vm); +} + + +/* regular playback */ + +void vm_position_get(vm_t *vm, vm_position_t *position) { + position->button = (vm->state).HL_BTNN_REG >> 10; + position->vts = (vm->state).vtsN; + position->domain = (vm->state).domain; + position->spu_channel = (vm->state).SPST_REG; + position->audio_channel = (vm->state).AST_REG; + position->angle_channel = (vm->state).AGL_REG; + position->hop_channel = vm->hop_channel; /* Increases by one on each hop */ + position->cell = (vm->state).cellN; + position->cell_restart = (vm->state).cell_restart; + position->cell_start = (vm->state).pgc->cell_playback[(vm->state).cellN - 1].first_sector; + position->still = (vm->state).pgc->cell_playback[(vm->state).cellN - 1].still_time; + position->block = (vm->state).blockN; + + /* handle PGC stills at PGC end */ + if ((vm->state).cellN == (vm->state).pgc->nr_of_cells) + position->still += (vm->state).pgc->still_time; + /* still already determined */ + if (position->still) + return; + /* This is a rough fix for some strange still situations on some strange DVDs. + * There are discs (like the German "Back to the Future" RC2) where the only + * indication of a still is a cell playback time higher than the time the frames + * in this cell actually take to play (like 1 frame with 1 minute playback time). + * On the said BTTF disc, for these cells last_sector and last_vobu_start_sector + * are equal and the cells are very short, so we abuse these conditions to + * detect such discs. I consider these discs broken, so the fix is somewhat + * broken, too. */ + if (((vm->state).pgc->cell_playback[(vm->state).cellN - 1].last_sector == + (vm->state).pgc->cell_playback[(vm->state).cellN - 1].last_vobu_start_sector) && + ((vm->state).pgc->cell_playback[(vm->state).cellN - 1].last_sector - + (vm->state).pgc->cell_playback[(vm->state).cellN - 1].first_sector < 1024)) { + int time; + int size = (vm->state).pgc->cell_playback[(vm->state).cellN - 1].last_sector - + (vm->state).pgc->cell_playback[(vm->state).cellN - 1].first_sector; + time = ((vm->state).pgc->cell_playback[(vm->state).cellN - 1].playback_time.hour >> 4 ) * 36000; + time += ((vm->state).pgc->cell_playback[(vm->state).cellN - 1].playback_time.hour & 0x0f) * 3600; + time += ((vm->state).pgc->cell_playback[(vm->state).cellN - 1].playback_time.minute >> 4 ) * 600; + time += ((vm->state).pgc->cell_playback[(vm->state).cellN - 1].playback_time.minute & 0x0f) * 60; + time += ((vm->state).pgc->cell_playback[(vm->state).cellN - 1].playback_time.second >> 4 ) * 10; + time += ((vm->state).pgc->cell_playback[(vm->state).cellN - 1].playback_time.second & 0x0f) * 1; + if (!time || size / time > 30) + /* datarate is too high, it might be a very short, but regular cell */ + return; + if (time > 0xff) time = 0xff; + position->still = time; + } +} + +void vm_get_next_cell(vm_t *vm) { + process_command(vm, play_Cell_post(vm)); +} + + +/* Jumping */ + +int vm_jump_pg(vm_t *vm, int pg) { + (vm->state).pgN = pg; + process_command(vm, play_PG(vm)); + return 1; +} + +int vm_jump_cell_block(vm_t *vm, int cell, int block) { + (vm->state).cellN = cell; + process_command(vm, play_Cell(vm)); + /* play_Cell can jump to a different cell in case of angles */ + if ((vm->state).cellN == cell) + (vm->state).blockN = block; + return 1; +} + +int vm_jump_title_part(vm_t *vm, int title, int part) { + link_t link; + + if(!set_PTT(vm, title, part)) + return 0; + /* Some DVDs do not want us to jump directly into a title and have + * PGC pre commands taking us back to some menu. Since we do not like that, + * we do not execute PGC pre commands that would do a jump. */ + /* process_command(vm, play_PGC_PG(vm, (vm->state).pgN)); */ + link = play_PGC_PG(vm, (vm->state).pgN); + if (link.command != PlayThis) + /* jump occured -> ignore it and play the PG anyway */ + process_command(vm, play_PG(vm)); + else + process_command(vm, link); + return 1; +} + +int vm_jump_top_pg(vm_t *vm) { + process_command(vm, play_PG(vm)); + return 1; +} + +int vm_jump_next_pg(vm_t *vm) { + if((vm->state).pgN >= (vm->state).pgc->nr_of_programs) { + /* last program -> move to TailPGC */ + process_command(vm, play_PGC_post(vm)); + return 1; + } else { + vm_jump_pg(vm, (vm->state).pgN + 1); + return 1; + } +} + +int vm_jump_prev_pg(vm_t *vm) { + if ((vm->state).pgN <= 1) { + /* first program -> move to last program of previous PGC */ + if ((vm->state).pgc->prev_pgc_nr && set_PGCN(vm, (vm->state).pgc->prev_pgc_nr)) { + process_command(vm, play_PGC(vm)); + vm_jump_pg(vm, (vm->state).pgc->nr_of_programs); + return 1; + } + return 0; + } else { + vm_jump_pg(vm, (vm->state).pgN - 1); + return 1; + } +} + +int vm_jump_up(vm_t *vm) { + if((vm->state).pgc->goup_pgc_nr && set_PGCN(vm, (vm->state).pgc->goup_pgc_nr)) { + process_command(vm, play_PGC(vm)); + return 1; + } + return 0; +} + +int vm_jump_menu(vm_t *vm, DVDMenuID_t menuid) { + domain_t old_domain = (vm->state).domain; + + switch ((vm->state).domain) { + case VTS_DOMAIN: + set_RSMinfo(vm, 0, (vm->state).blockN); + /* FALL THROUGH */ + case VTSM_DOMAIN: + case VMGM_DOMAIN: + switch(menuid) { + case DVD_MENU_Title: + case DVD_MENU_Escape: + (vm->state).domain = VMGM_DOMAIN; + break; + case DVD_MENU_Root: + case DVD_MENU_Subpicture: + case DVD_MENU_Audio: + case DVD_MENU_Angle: + case DVD_MENU_Part: + (vm->state).domain = VTSM_DOMAIN; + break; + } + if(get_PGCIT(vm) && set_MENU(vm, menuid)) { + process_command(vm, play_PGC(vm)); + return 1; /* Jump */ + } else { + (vm->state).domain = old_domain; + } + break; + case FP_DOMAIN: /* FIXME XXX $$$ What should we do here? */ + break; + } + + return 0; +} + +int vm_jump_resume(vm_t *vm) { + link_t link_values = { LinkRSM, 0, 0, 0 }; + + if (!(vm->state).rsm_vtsN) /* Do we have resume info? */ + return 0; + if (!process_command(vm, link_values)) + return 0; + return 1; +} + +int vm_exec_cmd(vm_t *vm, vm_cmd_t *cmd) { + link_t link_values; + + if(vmEval_CMD(cmd, 1, &(vm->state).registers, &link_values)) + return process_command(vm, link_values); + else + return 0; /* It updated some state thats all... */ +} + + +/* getting information */ + +int vm_get_current_menu(vm_t *vm, int *menuid) { + pgcit_t* pgcit; + int pgcn; + pgcn = (vm->state).pgcN; + pgcit = get_PGCIT(vm); + if(pgcit==NULL) return 0; + *menuid = pgcit->pgci_srp[pgcn - 1].entry_id & 0xf ; + return 1; +} + +int vm_get_current_title_part(vm_t *vm, int *title_result, int *part_result) { + vts_ptt_srpt_t *vts_ptt_srpt; + int title, part = 0, vts_ttn; + int found; + int16_t pgcN, pgN; + + vts_ptt_srpt = vm->vtsi->vts_ptt_srpt; + pgcN = get_PGCN(vm); + pgN = vm->state.pgN; + + found = 0; + for (vts_ttn = 0; (vts_ttn < vts_ptt_srpt->nr_of_srpts) && !found; vts_ttn++) { + for (part = 0; (part < vts_ptt_srpt->title[vts_ttn].nr_of_ptts) && !found; part++) { + if (vts_ptt_srpt->title[vts_ttn].ptt[part].pgcn == pgcN) { + if (vts_ptt_srpt->title[vts_ttn].ptt[part].pgn == pgN) { + found = 1; + break; + } + if (part > 0 && vts_ptt_srpt->title[vts_ttn].ptt[part].pgn > pgN && + vts_ptt_srpt->title[vts_ttn].ptt[part - 1].pgn < pgN) { + part--; + found = 1; + break; + } + } + } + if (found) break; + } + vts_ttn++; + part++; + + if (!found) { + fprintf(MSG_OUT, "libdvdnav: chapter NOT FOUND!\n"); + return 0; + } + + title = get_TT(vm, vm->state.vtsN, vts_ttn); + +#ifdef TRACE + if (title) { + fprintf(MSG_OUT, "libdvdnav: ************ this chapter FOUND!\n"); + fprintf(MSG_OUT, "libdvdnav: VTS_PTT_SRPT - Title %3i part %3i: PGC: %3i PG: %3i\n", + title, part, + vts_ptt_srpt->title[vts_ttn-1].ptt[part-1].pgcn , + vts_ptt_srpt->title[vts_ttn-1].ptt[part-1].pgn ); + } +#endif + *title_result = title; + *part_result = part; + return 1; +} + +/* Return the substream id for 'logical' audio stream audioN. + * 0 <= audioN < 8 + */ +int vm_get_audio_stream(vm_t *vm, int audioN) { + int streamN = -1; + + if((vm->state).domain != VTS_DOMAIN) + audioN = 0; + + if(audioN < 8) { + /* Is there any control info for this logical stream */ + if((vm->state).pgc->audio_control[audioN] & (1<<15)) { + streamN = ((vm->state).pgc->audio_control[audioN] >> 8) & 0x07; + } + } + + if((vm->state).domain != VTS_DOMAIN && streamN == -1) + streamN = 0; + + /* FIXME: Should also check in vtsi/vmgi status what kind of stream + * it is (ac3/lpcm/dts/sdds...) to find the right (sub)stream id */ + return streamN; +} + +/* Return the substream id for 'logical' subpicture stream subpN and given mode. + * 0 <= subpN < 32 + * mode == 0 - widescreen + * mode == 1 - letterbox + * mode == 2 - pan&scan + */ +int vm_get_subp_stream(vm_t *vm, int subpN, int mode) { + int streamN = -1; + int source_aspect = vm_get_video_aspect(vm); + + if((vm->state).domain != VTS_DOMAIN) + subpN = 0; + + if(subpN < 32) { /* a valid logical stream */ + /* Is this logical stream present */ + if((vm->state).pgc->subp_control[subpN] & (1<<31)) { + if(source_aspect == 0) /* 4:3 */ + streamN = ((vm->state).pgc->subp_control[subpN] >> 24) & 0x1f; + if(source_aspect == 3) /* 16:9 */ + switch (mode) { + case 0: + streamN = ((vm->state).pgc->subp_control[subpN] >> 16) & 0x1f; + break; + case 1: + streamN = ((vm->state).pgc->subp_control[subpN] >> 8) & 0x1f; + break; + case 2: + streamN = (vm->state).pgc->subp_control[subpN] & 0x1f; + } + } + } + + if((vm->state).domain != VTS_DOMAIN && streamN == -1) + streamN = 0; + + /* FIXME: Should also check in vtsi/vmgi status what kind of stream it is. */ + return streamN; +} + +int vm_get_audio_active_stream(vm_t *vm) { + int audioN; + int streamN; + audioN = (vm->state).AST_REG ; + streamN = vm_get_audio_stream(vm, audioN); + + /* If no such stream, then select the first one that exists. */ + if(streamN == -1) { + for(audioN = 0; audioN < 8; audioN++) { + if((vm->state).pgc->audio_control[audioN] & (1<<15)) { + if ((streamN = vm_get_audio_stream(vm, audioN)) >= 0) + break; + } + } + } + + return streamN; +} + +int vm_get_subp_active_stream(vm_t *vm, int mode) { + int subpN; + int streamN; + subpN = (vm->state).SPST_REG & ~0x40; + streamN = vm_get_subp_stream(vm, subpN, mode); + + /* If no such stream, then select the first one that exists. */ + if(streamN == -1) { + for(subpN = 0; subpN < 32; subpN++) { + if((vm->state).pgc->subp_control[subpN] & (1<<31)) { + if ((streamN = vm_get_subp_stream(vm, subpN, mode)) >= 0) + break; + } + } + } + + if((vm->state).domain == VTS_DOMAIN && !((vm->state).SPST_REG & 0x40)) + /* Bit 7 set means hide, and only let Forced display show */ + return (streamN | 0x80); + else + return streamN; +} + +void vm_get_angle_info(vm_t *vm, int *current, int *num_avail) { + *num_avail = 1; + *current = 1; + + if((vm->state).domain == VTS_DOMAIN) { + title_info_t *title; + /* TTN_REG does not allways point to the correct title.. */ + if((vm->state).TTN_REG > vm->vmgi->tt_srpt->nr_of_srpts) + return; + title = &vm->vmgi->tt_srpt->title[(vm->state).TTN_REG - 1]; + if(title->title_set_nr != (vm->state).vtsN || + title->vts_ttn != (vm->state).VTS_TTN_REG) + return; + *num_avail = title->nr_of_angles; + *current = (vm->state).AGL_REG; + } +} + +// XBMC #if 0 +/* currently unused */ +void vm_get_audio_info(vm_t *vm, int *current, int *num_avail) { + switch ((vm->state).domain) { + case VTS_DOMAIN: + *num_avail = vm->vtsi->vtsi_mat->nr_of_vts_audio_streams; + *current = (vm->state).AST_REG; + break; + case VTSM_DOMAIN: + *num_avail = vm->vtsi->vtsi_mat->nr_of_vtsm_audio_streams; /* 1 */ + *current = 1; + break; + case VMGM_DOMAIN: + case FP_DOMAIN: + *num_avail = vm->vmgi->vmgi_mat->nr_of_vmgm_audio_streams; /* 1 */ + *current = 1; + break; + } +} + +/* currently unused */ +void vm_get_subp_info(vm_t *vm, int *current, int *num_avail) { + switch ((vm->state).domain) { + case VTS_DOMAIN: + *num_avail = vm->vtsi->vtsi_mat->nr_of_vts_subp_streams; + *current = (vm->state).SPST_REG; + break; + case VTSM_DOMAIN: + *num_avail = vm->vtsi->vtsi_mat->nr_of_vtsm_subp_streams; /* 1 */ + *current = 0x41; + break; + case VMGM_DOMAIN: + case FP_DOMAIN: + *num_avail = vm->vmgi->vmgi_mat->nr_of_vmgm_subp_streams; /* 1 */ + *current = 0x41; + break; + } +} + +/* currently unused */ +void vm_get_video_res(vm_t *vm, int *width, int *height) { + video_attr_t attr = vm_get_video_attr(vm); + + if(attr.video_format != 0) + *height = 576; + else + *height = 480; + switch(attr.picture_size) { + case 0: + *width = 720; + break; + case 1: + *width = 704; + break; + case 2: + *width = 352; + break; + case 3: + *width = 352; + *height /= 2; + break; + } +} +// XBMC #endif + +int vm_get_video_aspect(vm_t *vm) { + int aspect = vm_get_video_attr(vm).display_aspect_ratio; + + assert(aspect == 0 || aspect == 3); + (vm->state).registers.SPRM[14] &= ~(0x3 << 10); + (vm->state).registers.SPRM[14] |= aspect << 10; + + return aspect; +} + +int vm_get_video_scale_permission(vm_t *vm) { + return vm_get_video_attr(vm).permitted_df; +} + +video_attr_t vm_get_video_attr(vm_t *vm) { + switch ((vm->state).domain) { + case VTS_DOMAIN: + return vm->vtsi->vtsi_mat->vts_video_attr; + case VTSM_DOMAIN: + return vm->vtsi->vtsi_mat->vtsm_video_attr; + case VMGM_DOMAIN: + case FP_DOMAIN: + return vm->vmgi->vmgi_mat->vmgm_video_attr; + default: + abort(); + } +} + +audio_attr_t vm_get_audio_attr(vm_t *vm, int streamN) { + switch ((vm->state).domain) { + case VTS_DOMAIN: + return vm->vtsi->vtsi_mat->vts_audio_attr[streamN]; + case VTSM_DOMAIN: + return vm->vtsi->vtsi_mat->vtsm_audio_attr; + case VMGM_DOMAIN: + case FP_DOMAIN: + return vm->vmgi->vmgi_mat->vmgm_audio_attr; + default: + abort(); + } +} + +subp_attr_t vm_get_subp_attr(vm_t *vm, int streamN) { + switch ((vm->state).domain) { + case VTS_DOMAIN: + return vm->vtsi->vtsi_mat->vts_subp_attr[streamN]; + case VTSM_DOMAIN: + return vm->vtsi->vtsi_mat->vtsm_subp_attr; + case VMGM_DOMAIN: + case FP_DOMAIN: + return vm->vmgi->vmgi_mat->vmgm_subp_attr; + default: + abort(); + } +} + + +/* Playback control */ + +static link_t play_PGC(vm_t *vm) { + link_t link_values; + +#ifdef TRACE + fprintf(MSG_OUT, "libdvdnav: play_PGC:"); + if((vm->state).domain != FP_DOMAIN) { + fprintf(MSG_OUT, " (vm->state).pgcN (%i)\n", get_PGCN(vm)); + } else { + fprintf(MSG_OUT, " first_play_pgc\n"); + } +#endif + + /* This must be set before the pre-commands are executed because they + * might contain a CallSS that will save resume state */ + + /* FIXME: This may be only a temporary fix for something... */ + (vm->state).pgN = 1; + (vm->state).cellN = 0; + (vm->state).blockN = 0; + + /* eval -> updates the state and returns either + - some kind of jump (Jump(TT/SS/VTS_TTN/CallSS/link C/PG/PGC/PTTN) + - just play video i.e first PG + (This is what happens if you fall of the end of the pre_cmds) + - or an error (are there more cases?) */ + if((vm->state).pgc->command_tbl && (vm->state).pgc->command_tbl->nr_of_pre) { + if(vmEval_CMD((vm->state).pgc->command_tbl->pre_cmds, + (vm->state).pgc->command_tbl->nr_of_pre, + &(vm->state).registers, &link_values)) { + /* link_values contains the 'jump' return value */ + return link_values; + } else { +#ifdef TRACE + fprintf(MSG_OUT, "libdvdnav: PGC pre commands didn't do a Jump, Link or Call\n"); +#endif + } + } + return play_PG(vm); +} + +static link_t play_PGC_PG(vm_t *vm, int pgN) { + link_t link_values; + +#ifdef TRACE + fprintf(MSG_OUT, "libdvdnav: play_PGC_PG:"); + if((vm->state).domain != FP_DOMAIN) { + fprintf(MSG_OUT, " (vm->state).pgcN (%i)\n", get_PGCN(vm)); + } else { + fprintf(MSG_OUT, " first_play_pgc\n"); + } +#endif + + /* This must be set before the pre-commands are executed because they + * might contain a CallSS that will save resume state */ + + /* FIXME: This may be only a temporary fix for something... */ + (vm->state).pgN = pgN; + (vm->state).cellN = 0; + (vm->state).blockN = 0; + + /* eval -> updates the state and returns either + - some kind of jump (Jump(TT/SS/VTS_TTN/CallSS/link C/PG/PGC/PTTN) + - just play video i.e first PG + (This is what happens if you fall of the end of the pre_cmds) + - or an error (are there more cases?) */ + if((vm->state).pgc->command_tbl && (vm->state).pgc->command_tbl->nr_of_pre) { + if(vmEval_CMD((vm->state).pgc->command_tbl->pre_cmds, + (vm->state).pgc->command_tbl->nr_of_pre, + &(vm->state).registers, &link_values)) { + /* link_values contains the 'jump' return value */ + return link_values; + } else { +#ifdef TRACE + fprintf(MSG_OUT, "libdvdnav: PGC pre commands didn't do a Jump, Link or Call\n"); +#endif + } + } + return play_PG(vm); +} + +static link_t play_PGC_post(vm_t *vm) { + link_t link_values; + +#ifdef TRACE + fprintf(MSG_OUT, "libdvdnav: play_PGC_post:\n"); +#endif + + /* eval -> updates the state and returns either + - some kind of jump (Jump(TT/SS/VTS_TTN/CallSS/link C/PG/PGC/PTTN) + - just go to next PGC + (This is what happens if you fall of the end of the post_cmds) + - or an error (are there more cases?) */ + if((vm->state).pgc->command_tbl && (vm->state).pgc->command_tbl->nr_of_post && + vmEval_CMD((vm->state).pgc->command_tbl->post_cmds, + (vm->state).pgc->command_tbl->nr_of_post, + &(vm->state).registers, &link_values)) { + return link_values; + } + +#ifdef TRACE + fprintf(MSG_OUT, "libdvdnav: ** Fell of the end of the pgc, continuing in NextPGC\n"); +#endif + /* Should end up in the STOP_DOMAIN if next_pgc is 0. */ + if(!set_PGCN(vm, (vm->state).pgc->next_pgc_nr)) { + link_values.command = Exit; + return link_values; + } + return play_PGC(vm); +} + +static link_t play_PG(vm_t *vm) { +#ifdef TRACE + fprintf(MSG_OUT, "libdvdnav: play_PG: (vm->state).pgN (%i)\n", (vm->state).pgN); +#endif + + assert((vm->state).pgN > 0); + if((vm->state).pgN > (vm->state).pgc->nr_of_programs) { +#ifdef TRACE + fprintf(MSG_OUT, "libdvdnav: play_PG: (vm->state).pgN (%i) > pgc->nr_of_programs (%i)\n", + (vm->state).pgN, (vm->state).pgc->nr_of_programs ); +#endif + assert((vm->state).pgN == (vm->state).pgc->nr_of_programs + 1); + return play_PGC_post(vm); + } + + (vm->state).cellN = (vm->state).pgc->program_map[(vm->state).pgN - 1]; + + return play_Cell(vm); +} + +static link_t play_Cell(vm_t *vm) { + static const link_t play_this = {PlayThis, /* Block in Cell */ 0, 0, 0}; + +#ifdef TRACE + fprintf(MSG_OUT, "libdvdnav: play_Cell: (vm->state).cellN (%i)\n", (vm->state).cellN); +#endif + + assert((vm->state).cellN > 0); + if((vm->state).cellN > (vm->state).pgc->nr_of_cells) { +#ifdef TRACE + fprintf(MSG_OUT, "libdvdnav: (vm->state).cellN (%i) > pgc->nr_of_cells (%i)\n", + (vm->state).cellN, (vm->state).pgc->nr_of_cells ); +#endif + assert((vm->state).cellN == (vm->state).pgc->nr_of_cells + 1); + return play_PGC_post(vm); + } + + /* Multi angle/Interleaved */ + switch((vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_mode) { + case 0: /* Normal */ + assert((vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_type == 0); + break; + case 1: /* The first cell in the block */ + switch((vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_type) { + case 0: /* Not part of a block */ + assert(0); + break; + case 1: /* Angle block */ + /* Loop and check each cell instead? So we don't get outside the block? */ + (vm->state).cellN += (vm->state).AGL_REG - 1; +#ifdef STRICT + assert((vm->state).cellN <= (vm->state).pgc->nr_of_cells); + assert((vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_mode != 0); + assert((vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_type == 1); +#else + if (!((vm->state).cellN <= (vm->state).pgc->nr_of_cells) || + !((vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_mode != 0) || + !((vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_type == 1)) { + fprintf(MSG_OUT, "libdvdnav: Invalid angle block\n"); + (vm->state).cellN -= (vm->state).AGL_REG - 1; + } +#endif + break; + case 2: /* ?? */ + case 3: /* ?? */ + default: + fprintf(MSG_OUT, "libdvdnav: Invalid? Cell block_mode (%d), block_type (%d)\n", + (vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_mode, + (vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_type); + assert(0); + } + break; + case 2: /* Cell in the block */ + case 3: /* Last cell in the block */ + /* These might perhaps happen for RSM or LinkC commands? */ + default: + fprintf(MSG_OUT, "libdvdnav: Cell is in block but did not enter at first cell!\n"); + } + + /* Updates (vm->state).pgN and PTTN_REG */ + if(!set_PGN(vm)) { + /* Should not happen */ + assert(0); + return play_PGC_post(vm); + } + (vm->state).cell_restart++; + (vm->state).blockN = 0; +#ifdef TRACE + fprintf(MSG_OUT, "libdvdnav: Cell should restart here\n"); +#endif + return play_this; +} + +static link_t play_Cell_post(vm_t *vm) { + cell_playback_t *cell; + +#ifdef TRACE + fprintf(MSG_OUT, "libdvdnav: play_Cell_post: (vm->state).cellN (%i)\n", (vm->state).cellN); +#endif + + cell = &(vm->state).pgc->cell_playback[(vm->state).cellN - 1]; + + /* Still time is already taken care of before we get called. */ + + /* Deal with a Cell command, if any */ + if(cell->cell_cmd_nr != 0) { + link_t link_values; + +/* These asserts are now not needed. + * Some DVDs have no cell commands listed in the PGC, + * but the Cell itself points to a cell command that does not exist. + * For this situation, just ignore the cell command and continue. + * + * assert((vm->state).pgc->command_tbl != NULL); + * assert((vm->state).pgc->command_tbl->nr_of_cell >= cell->cell_cmd_nr); + */ + + if ((vm->state).pgc->command_tbl != NULL && + (vm->state).pgc->command_tbl->nr_of_cell >= cell->cell_cmd_nr) { +#ifdef TRACE + fprintf(MSG_OUT, "libdvdnav: Cell command present, executing\n"); +#endif + if(vmEval_CMD(&(vm->state).pgc->command_tbl->cell_cmds[cell->cell_cmd_nr - 1], 1, + &(vm->state).registers, &link_values)) { + return link_values; + } else { +#ifdef TRACE + fprintf(MSG_OUT, "libdvdnav: Cell command didn't do a Jump, Link or Call\n"); +#endif + } + } else { +#ifdef TRACE + fprintf(MSG_OUT, "libdvdnav: Invalid Cell command\n"); +#endif + } + } + + /* Where to continue after playing the cell... */ + /* Multi angle/Interleaved */ + switch((vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_mode) { + case 0: /* Normal */ + assert((vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_type == 0); + (vm->state).cellN++; + break; + case 1: /* The first cell in the block */ + case 2: /* A cell in the block */ + case 3: /* The last cell in the block */ + default: + switch((vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_type) { + case 0: /* Not part of a block */ + assert(0); + break; + case 1: /* Angle block */ + /* Skip the 'other' angles */ + (vm->state).cellN++; + while((vm->state).cellN <= (vm->state).pgc->nr_of_cells && + (vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_mode >= 2) { + (vm->state).cellN++; + } + break; + case 2: /* ?? */ + case 3: /* ?? */ + default: + fprintf(MSG_OUT, "libdvdnav: Invalid? Cell block_mode (%d), block_type (%d)\n", + (vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_mode, + (vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_type); + assert(0); + } + break; + } + + /* Figure out the correct pgN for the new cell */ + if(!set_PGN(vm)) { +#ifdef TRACE + fprintf(MSG_OUT, "libdvdnav: last cell in this PGC\n"); +#endif + return play_PGC_post(vm); + } + return play_Cell(vm); +} + + +/* link processing */ + +static int process_command(vm_t *vm, link_t link_values) { + + while(link_values.command != PlayThis) { + +#ifdef TRACE + fprintf(MSG_OUT, "libdvdnav: Before printout starts:\n"); + vm_print_link(link_values); + fprintf(MSG_OUT, "libdvdnav: Link values %i %i %i %i\n", link_values.command, + link_values.data1, link_values.data2, link_values.data3); + vm_print_current_domain_state(vm); + fprintf(MSG_OUT, "libdvdnav: Before printout ends.\n"); +#endif + + switch(link_values.command) { + case LinkNoLink: + /* BUTTON number:data1 */ + if(link_values.data1 != 0) + (vm->state).HL_BTNN_REG = link_values.data1 << 10; + return 0; /* no actual jump */ + + case LinkTopC: + /* Restart playing from the beginning of the current Cell. */ + /* BUTTON number:data1 */ + if(link_values.data1 != 0) + (vm->state).HL_BTNN_REG = link_values.data1 << 10; + link_values = play_Cell(vm); + break; + case LinkNextC: + /* Link to Next Cell */ + /* BUTTON number:data1 */ + if(link_values.data1 != 0) + (vm->state).HL_BTNN_REG = link_values.data1 << 10; + (vm->state).cellN += 1; + link_values = play_Cell(vm); + break; + case LinkPrevC: + /* Link to Previous Cell */ + /* BUTTON number:data1 */ + if(link_values.data1 != 0) + (vm->state).HL_BTNN_REG = link_values.data1 << 10; + assert((vm->state).cellN > 1); + (vm->state).cellN -= 1; + link_values = play_Cell(vm); + break; + + case LinkTopPG: + /* Link to Top of current Program */ + /* BUTTON number:data1 */ + if(link_values.data1 != 0) + (vm->state).HL_BTNN_REG = link_values.data1 << 10; + link_values = play_PG(vm); + break; + case LinkNextPG: + /* Link to Next Program */ + /* BUTTON number:data1 */ + if(link_values.data1 != 0) + (vm->state).HL_BTNN_REG = link_values.data1 << 10; + (vm->state).pgN += 1; + link_values = play_PG(vm); + break; + case LinkPrevPG: + /* Link to Previous Program */ + /* BUTTON number:data1 */ + if(link_values.data1 != 0) + (vm->state).HL_BTNN_REG = link_values.data1 << 10; + assert((vm->state).pgN > 1); + (vm->state).pgN -= 1; + link_values = play_PG(vm); + break; + + case LinkTopPGC: + /* Restart playing from beginning of current Program Chain */ + /* BUTTON number:data1 */ + if(link_values.data1 != 0) + (vm->state).HL_BTNN_REG = link_values.data1 << 10; + link_values = play_PGC(vm); + break; + case LinkNextPGC: + /* Link to Next Program Chain */ + /* BUTTON number:data1 */ + if(link_values.data1 != 0) + (vm->state).HL_BTNN_REG = link_values.data1 << 10; + assert((vm->state).pgc->next_pgc_nr != 0); + if(set_PGCN(vm, (vm->state).pgc->next_pgc_nr)) + link_values = play_PGC(vm); + else + link_values.command = Exit; + break; + case LinkPrevPGC: + /* Link to Previous Program Chain */ + /* BUTTON number:data1 */ + if(link_values.data1 != 0) + (vm->state).HL_BTNN_REG = link_values.data1 << 10; + assert((vm->state).pgc->prev_pgc_nr != 0); + if(set_PGCN(vm, (vm->state).pgc->prev_pgc_nr)) + link_values = play_PGC(vm); + else + link_values.command = Exit; + break; + case LinkGoUpPGC: + /* Link to GoUp Program Chain */ + /* BUTTON number:data1 */ + if(link_values.data1 != 0) + (vm->state).HL_BTNN_REG = link_values.data1 << 10; + assert((vm->state).pgc->goup_pgc_nr != 0); + if(set_PGCN(vm, (vm->state).pgc->goup_pgc_nr)) + link_values = play_PGC(vm); + else + link_values.command = Exit; + break; + case LinkTailPGC: + /* Link to Tail of Program Chain */ + /* BUTTON number:data1 */ + if(link_values.data1 != 0) + (vm->state).HL_BTNN_REG = link_values.data1 << 10; + link_values = play_PGC_post(vm); + break; + + case LinkRSM: + { + /* Link to Resume point */ + int i; + + /* Check and see if there is any rsm info!! */ + if (!(vm->state).rsm_vtsN) { + fprintf(MSG_OUT, "libdvdnav: trying to resume without any resume info set\n"); + link_values.command = Exit; + break; + } + + (vm->state).domain = VTS_DOMAIN; + if (!ifoOpenNewVTSI(vm, vm->dvd, (vm->state).rsm_vtsN)) + assert(0); + set_PGCN(vm, (vm->state).rsm_pgcN); + + /* These should never be set in SystemSpace and/or MenuSpace */ + /* (vm->state).TTN_REG = rsm_tt; ?? */ + /* (vm->state).TT_PGCN_REG = (vm->state).rsm_pgcN; ?? */ + for(i = 0; i < 5; i++) { + (vm->state).registers.SPRM[4 + i] = (vm->state).rsm_regs[i]; + } + + if(link_values.data1 != 0) + (vm->state).HL_BTNN_REG = link_values.data1 << 10; + + if((vm->state).rsm_cellN == 0) { + assert((vm->state).cellN); /* Checking if this ever happens */ + (vm->state).pgN = 1; + link_values = play_PG(vm); + } else { + /* (vm->state).pgN = ?? this gets the right value in set_PGN() below */ + (vm->state).cellN = (vm->state).rsm_cellN; + link_values.command = PlayThis; + link_values.data1 = (vm->state).rsm_blockN & 0xffff; + link_values.data2 = (vm->state).rsm_blockN >> 16; + if(!set_PGN(vm)) { + /* Were at the end of the PGC, should not happen for a RSM */ + assert(0); + link_values.command = LinkTailPGC; + link_values.data1 = 0; /* No button */ + } + } + } + break; + case LinkPGCN: + /* Link to Program Chain Number:data1 */ + if(!set_PGCN(vm, link_values.data1)) + assert(0); + link_values = play_PGC(vm); + break; + case LinkPTTN: + /* Link to Part of current Title Number:data1 */ + /* BUTTON number:data2 */ + /* PGC Pre-Commands are not executed */ + assert((vm->state).domain == VTS_DOMAIN); + if(link_values.data2 != 0) + (vm->state).HL_BTNN_REG = link_values.data2 << 10; + if(!set_VTS_PTT(vm, (vm->state).vtsN, (vm->state).VTS_TTN_REG, link_values.data1)) + assert(0); + link_values = play_PG(vm); + break; + case LinkPGN: + /* Link to Program Number:data1 */ + /* BUTTON number:data2 */ + if(link_values.data2 != 0) + (vm->state).HL_BTNN_REG = link_values.data2 << 10; + /* Update any other state, PTTN perhaps? */ + (vm->state).pgN = link_values.data1; + link_values = play_PG(vm); + break; + case LinkCN: + /* Link to Cell Number:data1 */ + /* BUTTON number:data2 */ + if(link_values.data2 != 0) + (vm->state).HL_BTNN_REG = link_values.data2 << 10; + /* Update any other state, pgN, PTTN perhaps? */ + (vm->state).cellN = link_values.data1; + link_values = play_Cell(vm); + break; + + case Exit: + vm->stopped = 1; + return 0; + + case JumpTT: + /* Jump to VTS Title Domain */ + /* Only allowed from the First Play domain(PGC) */ + /* or the Video Manager domain (VMG) */ + /* Stop SPRM9 Timer */ + /* Set SPRM1 and SPRM2 */ + assert((vm->state).domain == VMGM_DOMAIN || (vm->state).domain == FP_DOMAIN); /* ?? */ + if(set_TT(vm, link_values.data1)) + link_values = play_PGC(vm); + else + link_values.command = Exit; + break; + case JumpVTS_TT: + /* Jump to Title:data1 in same VTS Title Domain */ + /* Only allowed from the VTS Menu Domain(VTSM) */ + /* or the Video Title Set Domain(VTS) */ + /* Stop SPRM9 Timer */ + /* Set SPRM1 and SPRM2 */ + assert((vm->state).domain == VTSM_DOMAIN || (vm->state).domain == VTS_DOMAIN); /* ?? */ + if(!set_VTS_TT(vm, (vm->state).vtsN, link_values.data1)) + assert(0); + link_values = play_PGC(vm); + break; + case JumpVTS_PTT: + /* Jump to Part:data2 of Title:data1 in same VTS Title Domain */ + /* Only allowed from the VTS Menu Domain(VTSM) */ + /* or the Video Title Set Domain(VTS) */ + /* Stop SPRM9 Timer */ + /* Set SPRM1 and SPRM2 */ + assert((vm->state).domain == VTSM_DOMAIN || (vm->state).domain == VTS_DOMAIN); /* ?? */ + if(!set_VTS_PTT(vm, (vm->state).vtsN, link_values.data1, link_values.data2)) + assert(0); + link_values = play_PGC_PG(vm, (vm->state).pgN); + break; + + case JumpSS_FP: + /* Jump to First Play Domain */ + /* Only allowed from the VTS Menu Domain(VTSM) */ + /* or the Video Manager domain (VMG) */ + /* Stop SPRM9 Timer and any GPRM counters */ + assert((vm->state).domain == VMGM_DOMAIN || (vm->state).domain == VTSM_DOMAIN); /* ?? */ + if (!set_FP_PGC(vm)) + assert(0); + link_values = play_PGC(vm); + break; + case JumpSS_VMGM_MENU: + /* Jump to Video Manger domain - Title Menu:data1 or any PGC in VMG */ + /* Allowed from anywhere except the VTS Title domain */ + /* Stop SPRM9 Timer and any GPRM counters */ + assert((vm->state).domain != VTS_DOMAIN); /* ?? */ + (vm->state).domain = VMGM_DOMAIN; + if(!set_MENU(vm, link_values.data1)) + assert(0); + link_values = play_PGC(vm); + break; + case JumpSS_VTSM: + /* Jump to a menu in Video Title domain, */ + /* or to a Menu is the current VTS */ + /* Stop SPRM9 Timer and any GPRM counters */ + /* ifoOpenNewVTSI:data1 */ + /* VTS_TTN_REG:data2 */ + /* get_MENU:data3 */ + if(link_values.data1 != 0) { + if (link_values.data1 != (vm->state).vtsN) { + /* the normal case */ + assert((vm->state).domain == VMGM_DOMAIN || (vm->state).domain == FP_DOMAIN); /* ?? */ + (vm->state).domain = VTSM_DOMAIN; + if (!ifoOpenNewVTSI(vm, vm->dvd, link_values.data1)) /* Also sets (vm->state).vtsN */ + assert(0); + } else { + /* This happens on some discs like "Captain Scarlet & the Mysterons" or + * the German RC2 of "Anatomie" in VTSM. */ + assert((vm->state).domain == VTSM_DOMAIN || + (vm->state).domain == VMGM_DOMAIN || (vm->state).domain == FP_DOMAIN); /* ?? */ + (vm->state).domain = VTSM_DOMAIN; + } + } else { + /* This happens on 'The Fifth Element' region 2. */ + assert((vm->state).domain == VTSM_DOMAIN); + } + /* I don't know what title is supposed to be used for. */ + /* Alien or Aliens has this != 1, I think. */ + /* assert(link_values.data2 == 1); */ + (vm->state).VTS_TTN_REG = link_values.data2; + /* TTN_REG (SPRM4), VTS_TTN_REG (SPRM5), TT_PGCN_REG (SPRM6) are linked, */ + /* so if one changes, the others must change to match it. */ + (vm->state).TTN_REG = get_TT(vm, (vm->state).vtsN, (vm->state).VTS_TTN_REG); + if(!set_MENU(vm, link_values.data3)) + assert(0); + link_values = play_PGC(vm); + break; + case JumpSS_VMGM_PGC: + /* set_PGCN:data1 */ + /* Stop SPRM9 Timer and any GPRM counters */ + assert((vm->state).domain != VTS_DOMAIN); /* ?? */ + (vm->state).domain = VMGM_DOMAIN; + if(!set_PGCN(vm, link_values.data1)) + assert(0); + link_values = play_PGC(vm); + break; + + case CallSS_FP: + /* set_RSMinfo:data1 */ + assert((vm->state).domain == VTS_DOMAIN); /* ?? */ + /* Must be called before domain is changed */ + set_RSMinfo(vm, link_values.data1, /* We dont have block info */ 0); + set_FP_PGC(vm); + link_values = play_PGC(vm); + break; + case CallSS_VMGM_MENU: + /* set_MENU:data1 */ + /* set_RSMinfo:data2 */ + assert((vm->state).domain == VTS_DOMAIN); /* ?? */ + /* Must be called before domain is changed */ + set_RSMinfo(vm, link_values.data2, /* We dont have block info */ 0); + (vm->state).domain = VMGM_DOMAIN; + if(!set_MENU(vm, link_values.data1)) + assert(0); + link_values = play_PGC(vm); + break; + case CallSS_VTSM: + /* set_MENU:data1 */ + /* set_RSMinfo:data2 */ + assert((vm->state).domain == VTS_DOMAIN); /* ?? */ + /* Must be called before domain is changed */ + set_RSMinfo(vm, link_values.data2, /* We dont have block info */ 0); + (vm->state).domain = VTSM_DOMAIN; + if(!set_MENU(vm, link_values.data1)) + assert(0); + link_values = play_PGC(vm); + break; + case CallSS_VMGM_PGC: + /* set_PGC:data1 */ + /* set_RSMinfo:data2 */ + assert((vm->state).domain == VTS_DOMAIN); /* ?? */ + /* Must be called before domain is changed */ + set_RSMinfo(vm, link_values.data2, /* We dont have block info */ 0); + (vm->state).domain = VMGM_DOMAIN; + if(!set_PGCN(vm, link_values.data1)) + assert(0); + link_values = play_PGC(vm); + break; + case PlayThis: + /* Should never happen. */ + assert(0); + break; + } + +#ifdef TRACE + fprintf(MSG_OUT, "libdvdnav: After printout starts:\n"); + vm_print_current_domain_state(vm); + fprintf(MSG_OUT, "libdvdnav: After printout ends.\n"); +#endif + + } + (vm->state).blockN = link_values.data1 | (link_values.data2 << 16); + return 1; +} + + +/* Set functions */ + +static int set_TT(vm_t *vm, int tt) { + return set_PTT(vm, tt, 1); +} + +static int set_PTT(vm_t *vm, int tt, int ptt) { + assert(tt <= vm->vmgi->tt_srpt->nr_of_srpts); + return set_VTS_PTT(vm, vm->vmgi->tt_srpt->title[tt - 1].title_set_nr, + vm->vmgi->tt_srpt->title[tt - 1].vts_ttn, ptt); +} + +static int set_VTS_TT(vm_t *vm, int vtsN, int vts_ttn) { + return set_VTS_PTT(vm, vtsN, vts_ttn, 1); +} + +static int set_VTS_PTT(vm_t *vm, int vtsN, int vts_ttn, int part) { + int pgcN, pgN, res; + + (vm->state).domain = VTS_DOMAIN; + + if (vtsN != (vm->state).vtsN) + if (!ifoOpenNewVTSI(vm, vm->dvd, vtsN)) /* Also sets (vm->state).vtsN */ + return 0; + + if ((vts_ttn < 1) || (vts_ttn > vm->vtsi->vts_ptt_srpt->nr_of_srpts) || + (part < 1) || (part > vm->vtsi->vts_ptt_srpt->title[vts_ttn - 1].nr_of_ptts) ) { + return 0; + } + + pgcN = vm->vtsi->vts_ptt_srpt->title[vts_ttn - 1].ptt[part - 1].pgcn; + pgN = vm->vtsi->vts_ptt_srpt->title[vts_ttn - 1].ptt[part - 1].pgn; + + (vm->state).TT_PGCN_REG = pgcN; + (vm->state).PTTN_REG = part; + (vm->state).TTN_REG = get_TT(vm, vtsN, vts_ttn); + assert( (vm->state.TTN_REG) != 0 ); + (vm->state).VTS_TTN_REG = vts_ttn; + (vm->state).vtsN = vtsN; /* Not sure about this one. We can get to it easily from TTN_REG */ + /* Any other registers? */ + + res = set_PGCN(vm, pgcN); /* This clobber's state.pgN (sets it to 1), but we don't want clobbering here. */ + (vm->state).pgN = pgN; + return res; +} + +static int set_FP_PGC(vm_t *vm) { + (vm->state).domain = FP_DOMAIN; + if (!vm->vmgi->first_play_pgc) { + return set_PGCN(vm, 1); + } + (vm->state).pgc = vm->vmgi->first_play_pgc; + (vm->state).pgcN = vm->vmgi->vmgi_mat->first_play_pgc; + return 1; +} + + +static int set_MENU(vm_t *vm, int menu) { + assert((vm->state).domain == VMGM_DOMAIN || (vm->state).domain == VTSM_DOMAIN); + return set_PGCN(vm, get_ID(vm, menu)); +} + +static int set_PGCN(vm_t *vm, int pgcN) { + pgcit_t *pgcit; + + pgcit = get_PGCIT(vm); + assert(pgcit != NULL); /* ?? Make this return -1 instead */ + + if(pgcN < 1 || pgcN > pgcit->nr_of_pgci_srp) { +#ifdef TRACE + fprintf(MSG_OUT, "libdvdnav: ** No such pgcN = %d\n", pgcN); +#endif + return 0; + } + + (vm->state).pgc = pgcit->pgci_srp[pgcN - 1].pgc; + (vm->state).pgcN = pgcN; + (vm->state).pgN = 1; + + if((vm->state).domain == VTS_DOMAIN) + (vm->state).TT_PGCN_REG = pgcN; + + return 1; +} + +/* Figure out the correct pgN from the cell and update (vm->state). */ +static int set_PGN(vm_t *vm) { + int new_pgN = 0; + + while(new_pgN < (vm->state).pgc->nr_of_programs + && (vm->state).cellN >= (vm->state).pgc->program_map[new_pgN]) + new_pgN++; + + if(new_pgN == (vm->state).pgc->nr_of_programs) /* We are at the last program */ + if((vm->state).cellN > (vm->state).pgc->nr_of_cells) + return 0; /* We are past the last cell */ + + (vm->state).pgN = new_pgN; + + if((vm->state).domain == VTS_DOMAIN) { + playback_type_t *pb_ty; + if((vm->state).TTN_REG > vm->vmgi->tt_srpt->nr_of_srpts) + return 0; /* ?? */ + pb_ty = &vm->vmgi->tt_srpt->title[(vm->state).TTN_REG - 1].pb_ty; + if(pb_ty->multi_or_random_pgc_title == /* One_Sequential_PGC_Title */ 0) { + int dummy, part; + vm_get_current_title_part(vm, &dummy, &part); + (vm->state).PTTN_REG = part; + } else { + /* FIXME: Handle RANDOM or SHUFFLE titles. */ + fprintf(MSG_OUT, "libdvdnav: RANDOM or SHUFFLE titles are NOT handled yet.\n"); + } + } + return 1; +} + +/* Must be called before domain is changed (set_PGCN()) */ +static void set_RSMinfo(vm_t *vm, int cellN, int blockN) { + int i; + + if(cellN) { + (vm->state).rsm_cellN = cellN; + (vm->state).rsm_blockN = blockN; + } else { + (vm->state).rsm_cellN = (vm->state).cellN; + (vm->state).rsm_blockN = blockN; + } + (vm->state).rsm_vtsN = (vm->state).vtsN; + (vm->state).rsm_pgcN = get_PGCN(vm); + + /* assert((vm->state).rsm_pgcN == (vm->state).TT_PGCN_REG); for VTS_DOMAIN */ + + for(i = 0; i < 5; i++) { + (vm->state).rsm_regs[i] = (vm->state).registers.SPRM[4 + i]; + } +} + + +/* Get functions */ + +/* Searches the TT tables, to find the current TT. + * returns the current TT. + * returns 0 if not found. + */ +static int get_TT(vm_t *vm, int vtsN, int vts_ttn) { + int i; + int tt=0; + + for(i = 1; i <= vm->vmgi->tt_srpt->nr_of_srpts; i++) { + if( vm->vmgi->tt_srpt->title[i - 1].title_set_nr == vtsN && + vm->vmgi->tt_srpt->title[i - 1].vts_ttn == vts_ttn) { + tt=i; + break; + } + } + return tt; +} + +/* Search for entry_id match of the PGC Category in the current VTS PGCIT table. + * Return pgcN based on entry_id match. + */ +static int get_ID(vm_t *vm, int id) { + int pgcN, i; + pgcit_t *pgcit; + + /* Relies on state to get the correct pgcit. */ + pgcit = get_PGCIT(vm); + assert(pgcit != NULL); +#ifdef TRACE + fprintf(MSG_OUT, "libdvdnav: ** Searching for menu (0x%x) entry PGC\n", id); +#endif + + /* Force high bit set. */ + id |=0x80; + + /* Get menu/title */ + for(i = 0; i < pgcit->nr_of_pgci_srp; i++) { + if( (pgcit->pgci_srp[i].entry_id) == id) { + pgcN = i + 1; +#ifdef TRACE + fprintf(MSG_OUT, "libdvdnav: Found menu.\n"); +#endif + return pgcN; + } + } +#ifdef TRACE + fprintf(MSG_OUT, "libdvdnav: ** No such id/menu (0x%02x) entry PGC\n", id & 0x7f); + for(i = 0; i < pgcit->nr_of_pgci_srp; i++) { + if ( (pgcit->pgci_srp[i].entry_id & 0x80) == 0x80) { + fprintf(MSG_OUT, "libdvdnav: Available menus: 0x%x\n", + pgcit->pgci_srp[i].entry_id & 0x7f); + } + } +#endif + return 0; /* error */ +} + +/* FIXME: we have a pgcN member in the vm's state now, so this should be obsolete */ +static int get_PGCN(vm_t *vm) { + pgcit_t *pgcit; + int pgcN = 1; + + pgcit = get_PGCIT(vm); + + if (pgcit) { + while(pgcN <= pgcit->nr_of_pgci_srp) { + if(pgcit->pgci_srp[pgcN - 1].pgc == (vm->state).pgc) { + assert((vm->state).pgcN == pgcN); + return pgcN; + } + pgcN++; + } + } + fprintf(MSG_OUT, "libdvdnav: get_PGCN failed. Was trying to find pgcN in domain %d\n", + (vm->state).domain); + return 0; /* error */ +} + +static pgcit_t* get_MENU_PGCIT(vm_t *vm, ifo_handle_t *h, uint16_t lang) { + int i; + + if(h == NULL || h->pgci_ut == NULL) { + fprintf(MSG_OUT, "libdvdnav: *** pgci_ut handle is NULL ***\n"); + return NULL; /* error? */ + } + + i = 0; + while(i < h->pgci_ut->nr_of_lus + && h->pgci_ut->lu[i].lang_code != lang) + i++; + if(i == h->pgci_ut->nr_of_lus) { + fprintf(MSG_OUT, "libdvdnav: Language '%c%c' not found, using '%c%c' instead\n", + (char)(lang >> 8), (char)(lang & 0xff), + (char)(h->pgci_ut->lu[0].lang_code >> 8), + (char)(h->pgci_ut->lu[0].lang_code & 0xff)); + fprintf(MSG_OUT, "libdvdnav: Menu Languages available: "); + for(i = 0; i < h->pgci_ut->nr_of_lus; i++) { + fprintf(MSG_OUT, "%c%c ", + (char)(h->pgci_ut->lu[i].lang_code >> 8), + (char)(h->pgci_ut->lu[i].lang_code & 0xff)); + } + fprintf(MSG_OUT, "\n"); + i = 0; /* error? */ + } + + return h->pgci_ut->lu[i].pgcit; +} + +/* Uses state to decide what to return */ +static pgcit_t* get_PGCIT(vm_t *vm) { + pgcit_t *pgcit = NULL; + + switch ((vm->state).domain) { + case VTS_DOMAIN: + if(!vm->vtsi) return NULL; + pgcit = vm->vtsi->vts_pgcit; + break; + case VTSM_DOMAIN: + if(!vm->vtsi) return NULL; + pgcit = get_MENU_PGCIT(vm, vm->vtsi, (vm->state).registers.SPRM[0]); + break; + case VMGM_DOMAIN: + case FP_DOMAIN: + pgcit = get_MENU_PGCIT(vm, vm->vmgi, (vm->state).registers.SPRM[0]); + break; + default: + abort(); + } + + return pgcit; +} + +//return the ifo_handle_t describing required title, used to +//identify chapters +ifo_handle_t *vm_get_title_ifo(vm_t *vm, uint32_t title) +{ + ifo_handle_t *ifo = NULL; + uint8_t titleset_nr; + if((title < 1) || (title > vm->vmgi->tt_srpt->nr_of_srpts)) + return NULL; + titleset_nr = vm->vmgi->tt_srpt->title[title-1].title_set_nr; + ifo = ifoOpen(vm->dvd, titleset_nr); + return ifo; +} + +void vm_ifo_close(ifo_handle_t *ifo) +{ + ifoClose(ifo); +} + +int vm_get_state(vm_t *vm, dvd_state_t *save_state) { + *save_state = vm->state; + + /* remove the pgc pointer as it might not be valid later*/ + save_state->pgc = NULL; + + return 1; +} + +int vm_set_state(vm_t *vm, dvd_state_t *save_state) { + + /* restore state from save_state as taken from ogle */ + + /* open the needed vts */ + if( !ifoOpenNewVTSI(vm, vm->dvd, save_state->vtsN) ) return 0; + // sets state.vtsN + + vm->state = *save_state; + /* set state.domain before calling */ + //calls get_pgcit() + // needs state.domain and sprm[0] set + // sets pgcit depending on state.domain + //writes: state.pgc + // state.pgN + // state.TT_PGCN_REG + + if( !set_PGCN(vm, save_state->pgcN) ) return 0; + save_state->pgc = vm->state.pgc; + + /* set the rest of state after the call */ + vm->state = *save_state; + + /* if we are not in standard playback, we must get all data */ + /* otherwise we risk loosing stillframes, and overlays */ + if(vm->state.domain != VTS_DOMAIN) + vm->state.blockN = 0; + + /* force a flush of data here */ + /* we don't need a hop seek here as it's a complete state*/ + vm->hop_channel++; + + return 1; +} + +/* Debug functions */ + +#ifdef TRACE +void vm_position_print(vm_t *vm, vm_position_t *position) { + fprintf(MSG_OUT, "libdvdnav: But=%x Spu=%x Aud=%x Ang=%x Hop=%x vts=%x dom=%x cell=%x cell_restart=%x cell_start=%x still=%x block=%x\n", + position->button, + position->spu_channel, + position->audio_channel, + position->angle_channel, + position->hop_channel, + position->vts, + position->domain, + position->cell, + position->cell_restart, + position->cell_start, + position->still, + position->block); +} +#endif + diff --git a/lib/libdvd/libdvdnav/src/vm/vm.h b/lib/libdvd/libdvdnav/src/vm/vm.h new file mode 100644 index 0000000000..fff9a7d9b1 --- /dev/null +++ b/lib/libdvd/libdvdnav/src/vm/vm.h @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2000, 2001 Håkan Hjort + * Copyright (C) 2001 Rich Wareham <richwareham@users.sourceforge.net> + * + * This file is part of libdvdnav, a DVD navigation library. It is modified + * from a file originally part of the Ogle DVD player. + * + * libdvdnav 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. + * + * libdvdnav 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 + * + * $Id: vm.h 1135 2008-09-06 21:55:51Z rathann $ + * + */ + +#ifndef VM_H_INCLUDED +#define VM_H_INCLUDED + +/* DOMAIN enum */ + +typedef enum { + FP_DOMAIN = 1, + VTS_DOMAIN = 2, + VMGM_DOMAIN = 4, + VTSM_DOMAIN = 8 +} domain_t; + +/** + * State: SPRM, GPRM, Domain, pgc, pgN, cellN, ? + */ +typedef struct { + registers_t registers; + + domain_t domain; + int vtsN; /* 0 is vmgm? */ + pgc_t *pgc; /* either this or 'int pgcN' is enough? */ + int pgcN; /* but provide pgcN for quick lookup */ + int pgN; /* is this needed? can allways fid pgN from cellN? */ + int cellN; + int32_t cell_restart; /* get cell to restart */ + int blockN; + + /* Resume info */ + int rsm_vtsN; + int rsm_blockN; /* of nav_packet */ + uint16_t rsm_regs[5]; /* system registers 4-8 */ + int rsm_pgcN; + int rsm_cellN; +} dvd_state_t; + +typedef struct vm_position_s { + int16_t button; /* Button highlighted */ + int32_t vts; /* vts number to use */ + domain_t domain; /* domain to use */ + int32_t spu_channel; /* spu channel to use */ + int32_t angle_channel; /* angle channel to use */ + int32_t audio_channel; /* audio channel to use */ + int32_t hop_channel; /* channel hopping. E.g menu button pressed */ +#if 0 + /* currently unused */ + int32_t title; /* title number */ + int32_t chapter; /* chapter number */ +#endif + int32_t cell; /* cell number */ + int32_t cell_restart; /* get cell to restart */ + int32_t cell_start; /* sector number of start of current cell in use */ + int32_t still; /* is cell still */ + int32_t block; /* block number within cell in use */ +} vm_position_t; + +typedef struct { + dvd_reader_t *dvd; + ifo_handle_t *vmgi; + ifo_handle_t *vtsi; + dvd_state_t state; + int32_t hop_channel; + char dvd_name[50]; + remap_t *map; + int stopped; +} vm_t; + +/* magic number for seeking hops */ +#define HOP_SEEK 0x1000 + + +/* Audio stream number */ +#define AST_REG registers.SPRM[1] +/* Subpicture stream number */ +#define SPST_REG registers.SPRM[2] +/* Angle number */ +#define AGL_REG registers.SPRM[3] +/* Title Track Number */ +#define TTN_REG registers.SPRM[4] +/* VTS Title Track Number */ +#define VTS_TTN_REG registers.SPRM[5] +/* PGC Number for this Title Track */ +#define TT_PGCN_REG registers.SPRM[6] +/* Current Part of Title (PTT) number for (One_Sequential_PGC_Title) */ +#define PTTN_REG registers.SPRM[7] +/* Highlighted Button Number (btn nr 1 == value 1024) */ +#define HL_BTNN_REG registers.SPRM[8] +/* Parental Level */ +#define PTL_REG registers.SPRM[13] + +/* Initialisation & destruction */ +vm_t *vm_new_vm(void); +void vm_free_vm(vm_t *vm); + +/* IFO access */ +ifo_handle_t *vm_get_vmgi(vm_t *vm); +ifo_handle_t *vm_get_vtsi(vm_t *vm); + +/* Reader Access */ +dvd_reader_t *vm_get_dvd_reader(vm_t *vm); + +/* Basic Handling */ +int vm_start(vm_t *vm); +void vm_stop(vm_t *vm); +int vm_reset(vm_t *vm, const char *dvdroot); + +/* copying and merging - useful for try-running an operation */ +vm_t *vm_new_copy(vm_t *vm); +void vm_merge(vm_t *target, vm_t *source); +void vm_free_copy(vm_t *vm); + +/* regular playback */ +void vm_position_get(vm_t *vm, vm_position_t *position); +void vm_get_next_cell(vm_t *vm); + +/* Jumping - all these return 1, if a hop has been performed */ +int vm_jump_pg(vm_t *vm, int pg); +int vm_jump_cell_block(vm_t *vm, int cell, int block); +int vm_jump_title_part(vm_t *vm, int title, int part); +int vm_jump_top_pg(vm_t *vm); +int vm_jump_next_pg(vm_t *vm); +int vm_jump_prev_pg(vm_t *vm); +int vm_jump_up(vm_t *vm); +int vm_jump_menu(vm_t *vm, DVDMenuID_t menuid); +int vm_jump_resume(vm_t *vm); +int vm_exec_cmd(vm_t *vm, vm_cmd_t *cmd); + +/* getting information */ +int vm_get_current_menu(vm_t *vm, int *menuid); +int vm_get_current_title_part(vm_t *vm, int *title_result, int *part_result); +int vm_get_audio_stream(vm_t *vm, int audioN); +int vm_get_subp_stream(vm_t *vm, int subpN, int mode); +int vm_get_audio_active_stream(vm_t *vm); +int vm_get_subp_active_stream(vm_t *vm, int mode); +void vm_get_angle_info(vm_t *vm, int *current, int *num_avail); +// _XBMC #if 0 +/* currently unused */ +void vm_get_audio_info(vm_t *vm, int *current, int *num_avail); +void vm_get_subp_info(vm_t *vm, int *current, int *num_avail); +void vm_get_video_res(vm_t *vm, int *width, int *height); +// _XBMC #endif +int vm_get_video_aspect(vm_t *vm); +int vm_get_video_scale_permission(vm_t *vm); +video_attr_t vm_get_video_attr(vm_t *vm); +audio_attr_t vm_get_audio_attr(vm_t *vm, int streamN); +subp_attr_t vm_get_subp_attr(vm_t *vm, int streamN); +ifo_handle_t *vm_get_title_ifo(vm_t *vm, uint32_t title); +void vm_ifo_close(ifo_handle_t *ifo); + +int vm_get_state(vm_t *vm, dvd_state_t *save_state); +int vm_set_state(vm_t *vm, dvd_state_t *save_state); + +/* Uncomment for VM command tracing */ +/* #define TRACE */ +#ifdef TRACE +/* Debug */ +void vm_position_print(vm_t *vm, vm_position_t *position); +#endif + + +#endif /* VM_HV_INCLUDED */ diff --git a/lib/libdvd/libdvdnav/src/vm/vmcmd.c b/lib/libdvd/libdvdnav/src/vm/vmcmd.c new file mode 100644 index 0000000000..9f68dbd399 --- /dev/null +++ b/lib/libdvd/libdvdnav/src/vm/vmcmd.c @@ -0,0 +1,549 @@ +/* + * Copyright (C) 2000, 2001 Martin Norbäck, Håkan Hjort + * 2002-2004 the dvdnav project + * + * This file is part of libdvdnav, a DVD navigation library. It is modified + * from a file originally part of the Ogle DVD player. + * + * libdvdnav 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. + * + * libdvdnav 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 + * + * $Id: vmcmd.c 1135 2008-09-06 21:55:51Z rathann $ + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <ctype.h> +#include <inttypes.h> +#include <limits.h> +#include <sys/time.h> + +#include "dvd_types.h" +#include <dvdread/nav_types.h> +#include <dvdread/ifo_types.h> +#include "decoder.h" +#include "remap.h" +#include "vm.h" +#include "vmcmd.h" +#include "dvdnav.h" +#include "dvdnav_internal.h" + +/* freebsd compatibility */ +#ifndef PRIu8 +#define PRIu8 "d" +#endif + +/* freebsd compatibility */ +#ifndef PRIu16 +#define PRIu16 "d" +#endif + +static const char cmp_op_table[][4] = { + "", "&", "==", "!=", ">=", ">", "<=", "<" +}; +static const char set_op_table[][4] = { + "", "=", "<->", "+=", "-=", "*=", "/=", "%=", "rnd", "&=", "|=", "^=" +}; + +static const char link_table[][16] = { + "LinkNoLink", "LinkTopC", "LinkNextC", "LinkPrevC", + "", "LinkTopPG", "LinkNextPG", "LinkPrevPG", + "", "LinkTopPGC", "LinkNextPGC", "LinkPrevPGC", + "LinkGoUpPGC", "LinkTailPGC", "", "", + "RSM" +}; + +static const char *const system_reg_table[] = { + "Menu Description Language Code", + "Audio Stream Number", + "Sub-picture Stream Number", + "Angle Number", + "Title Track Number", + "VTS Title Track Number", + "VTS PGC Number", + "PTT Number for One_Sequential_PGC_Title", + "Highlighted Button Number", + "Navigation Timer", + "Title PGC Number for Navigation Timer", + "Audio Mixing Mode for Karaoke", + "Country Code for Parental Management", + "Parental Level", + "Player Configurations for Video", + "Player Configurations for Audio", + "Initial Language Code for Audio", + "Initial Language Code Extension for Audio", + "Initial Language Code for Sub-picture", + "Initial Language Code Extension for Sub-picture", + "Player Regional Code", + "Reserved 21", + "Reserved 22", + "Reserved 23" +}; + +static const char system_reg_abbr_table[][8] = { + "", + "ASTN", + "SPSTN", + "AGLN", + "TTN", + "VTS_TTN", + "TT_PGCN", + "PTTN", + "HL_BTNN", + "NVTMR", + "NV_PGCN", + "", + "CC_PLT", + "PLT", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", +}; + +static void print_system_reg(uint16_t reg) { + if(reg < sizeof(system_reg_abbr_table) / sizeof(system_reg_abbr_table[0])) + fprintf(MSG_OUT, "%s (SRPM:%d)", system_reg_table[reg], reg); + else + fprintf(MSG_OUT, " WARNING: Unknown system register ( reg=%d ) ", reg); +} + +static void print_g_reg(uint8_t reg) { + if(reg < 16) + fprintf(MSG_OUT, "g[%" PRIu8 "]", reg); + else + fprintf(MSG_OUT, " WARNING: Unknown general register "); +} + +static void print_reg(uint8_t reg) { + if(reg & 0x80) + print_system_reg(reg & 0x7f); + else + print_g_reg(reg & 0x7f); +} + +static void print_cmp_op(uint8_t op) { + if(op < sizeof(cmp_op_table) / sizeof(cmp_op_table[0])) + fprintf(MSG_OUT, " %s ", cmp_op_table[op]); + else + fprintf(MSG_OUT, " WARNING: Unknown compare op "); +} + +static void print_set_op(uint8_t op) { + if(op < sizeof(set_op_table) / sizeof(cmp_op_table[0])) + fprintf(MSG_OUT, " %s ", set_op_table[op]); + else + fprintf(MSG_OUT, " WARNING: Unknown set op "); +} + +static void print_reg_or_data(command_t* command, int immediate, int start) { + if(immediate) { + uint32_t i = vm_getbits(command, start, 16); + + fprintf(MSG_OUT, "0x%x", i); + if(isprint(i & 0xff) && isprint((i>>8) & 0xff)) + fprintf(MSG_OUT, " (\"%c%c\")", (char)((i>>8) & 0xff), (char)(i & 0xff)); + } else { + print_reg(vm_getbits(command, start - 8, 8)); + } +} + +static void print_reg_or_data_2(command_t* command, int immediate, int start) { + if(immediate) + fprintf(MSG_OUT, "0x%x", vm_getbits(command, start - 1, 7)); + else + fprintf(MSG_OUT, "g[%" PRIu8 "]", vm_getbits(command, start - 4, 4)); +} + +static void print_reg_or_data_3(command_t* command, int immediate, int start) { + if(immediate) { + uint32_t i = vm_getbits(command, start, 16); + + fprintf(MSG_OUT, "0x%x", i); + if(isprint(i & 0xff) && isprint((i>>8) & 0xff)) + fprintf(MSG_OUT, " (\"%c%c\")", (char)((i>>8) & 0xff), (char)(i & 0xff)); + } else { + print_reg(vm_getbits(command, start, 8)); + } +} + + +static void print_if_version_1(command_t* command) { + uint8_t op = vm_getbits(command, 54, 3); + + if(op) { + fprintf(MSG_OUT, "if ("); + print_g_reg(vm_getbits(command,39,8)); + print_cmp_op(op); + print_reg_or_data(command, vm_getbits(command, 55,1), 31); + fprintf(MSG_OUT, ") "); + } +} + +static void print_if_version_2(command_t* command) { + uint8_t op = vm_getbits(command, 54, 3); + + if(op) { + fprintf(MSG_OUT, "if ("); + print_reg(vm_getbits(command, 15, 8)); + print_cmp_op(op); + print_reg(vm_getbits(command, 7, 8)); + fprintf(MSG_OUT, ") "); + } +} + +static void print_if_version_3(command_t* command) { + uint8_t op = vm_getbits(command, 54, 3); + + if(op) { + fprintf(MSG_OUT, "if ("); + print_g_reg(vm_getbits(command, 43, 4)); + print_cmp_op(op); + print_reg_or_data(command, vm_getbits(command, 55, 1), 15); + fprintf(MSG_OUT, ") "); + } +} + +static void print_if_version_4(command_t* command) { + uint8_t op = vm_getbits(command, 54, 3); + + if(op) { + fprintf(MSG_OUT, "if ("); + print_g_reg(vm_getbits(command, 51, 4)); + print_cmp_op(op); + print_reg_or_data(command, vm_getbits(command, 55, 1), 31); + fprintf(MSG_OUT, ") "); + } +} + +static void print_if_version_5(command_t* command) { + uint8_t op = vm_getbits(command, 54, 3); + int set_immediate = vm_getbits(command, 60, 1); + + if(op) { + if (set_immediate) { + fprintf(MSG_OUT, "if ("); + print_g_reg(vm_getbits(command, 31, 8)); + print_cmp_op(op); + print_reg(vm_getbits(command, 23, 8)); + fprintf(MSG_OUT, ") "); + } else { + fprintf(MSG_OUT, "if ("); + print_g_reg(vm_getbits(command, 39, 8)); + print_cmp_op(op); + print_reg_or_data(command, vm_getbits(command, 55, 1), 31); + fprintf(MSG_OUT, ") "); + } + } +} + +static void print_special_instruction(command_t* command) { + uint8_t op = vm_getbits(command, 51, 4); + + switch(op) { + case 0: /* NOP */ + fprintf(MSG_OUT, "Nop"); + break; + case 1: /* Goto line */ + fprintf(MSG_OUT, "Goto %" PRIu8, vm_getbits(command, 7, 8)); + break; + case 2: /* Break */ + fprintf(MSG_OUT, "Break"); + break; + case 3: /* Parental level */ + fprintf(MSG_OUT, "SetTmpPML %" PRIu8 ", Goto %" PRIu8, + vm_getbits(command, 11, 4), vm_getbits(command, 7, 8)); + break; + default: + fprintf(MSG_OUT, "WARNING: Unknown special instruction (%i)", + vm_getbits(command, 51, 4)); + } +} + +static void print_linksub_instruction(command_t* command) { + uint32_t linkop = vm_getbits(command, 7, 8); + uint32_t button = vm_getbits(command, 15, 6); + + if(linkop < sizeof(link_table)/sizeof(link_table[0])) + fprintf(MSG_OUT, "%s (button %" PRIu8 ")", link_table[linkop], button); + else + fprintf(MSG_OUT, "WARNING: Unknown linksub instruction (%i)", linkop); +} + +static void print_link_instruction(command_t* command, int optional) { + uint8_t op = vm_getbits(command, 51, 4); + + if(optional && op) + fprintf(MSG_OUT, ", "); + + switch(op) { + case 0: + if(!optional) + fprintf(MSG_OUT, "WARNING: NOP (link)!"); + break; + case 1: + print_linksub_instruction(command); + break; + case 4: + fprintf(MSG_OUT, "LinkPGCN %" PRIu16, vm_getbits(command, 14, 15)); + break; + case 5: + fprintf(MSG_OUT, "LinkPTT %" PRIu16 " (button %" PRIu8 ")", + vm_getbits(command, 9, 10), vm_getbits(command, 15, 6)); + break; + case 6: + fprintf(MSG_OUT, "LinkPGN %" PRIu8 " (button %" PRIu8 ")", + vm_getbits(command, 6, 7), vm_getbits(command, 15, 6)); + break; + case 7: + fprintf(MSG_OUT, "LinkCN %" PRIu8 " (button %" PRIu8 ")", + vm_getbits(command, 7, 8), vm_getbits(command, 15, 6)); + break; + default: + fprintf(MSG_OUT, "WARNING: Unknown link instruction"); + } +} + +static void print_jump_instruction(command_t* command) { + switch(vm_getbits(command, 51, 4)) { + case 1: + fprintf(MSG_OUT, "Exit"); + break; + case 2: + fprintf(MSG_OUT, "JumpTT %" PRIu8, vm_getbits(command, 22, 7)); + break; + case 3: + fprintf(MSG_OUT, "JumpVTS_TT %" PRIu8, vm_getbits(command, 22, 7)); + break; + case 5: + fprintf(MSG_OUT, "JumpVTS_PTT %" PRIu8 ":%" PRIu16, + vm_getbits(command, 22, 7), vm_getbits(command, 41, 10)); + break; + case 6: + switch(vm_getbits(command, 23, 2)) { + case 0: + fprintf(MSG_OUT, "JumpSS FP"); + break; + case 1: + fprintf(MSG_OUT, "JumpSS VMGM (menu %" PRIu8 ")", vm_getbits(command, 19, 4)); + break; + case 2: + fprintf(MSG_OUT, "JumpSS VTSM (vts %" PRIu8 ", title %" PRIu8 + ", menu %" PRIu8 ")", vm_getbits(command, 30, 7), vm_getbits(command, 38, 7), vm_getbits(command, 19, 4)); + break; + case 3: + fprintf(MSG_OUT, "JumpSS VMGM (pgc %" PRIu8 ")", vm_getbits(command, 46, 15)); + break; + } + break; + case 8: + switch(vm_getbits(command, 23, 2)) { + case 0: + fprintf(MSG_OUT, "CallSS FP (rsm_cell %" PRIu8 ")", + vm_getbits(command, 31, 8)); + break; + case 1: + fprintf(MSG_OUT, "CallSS VMGM (menu %" PRIu8 + ", rsm_cell %" PRIu8 ")", vm_getbits(command, 19, 4), vm_getbits(command, 31, 8)); + break; + case 2: + fprintf(MSG_OUT, "CallSS VTSM (menu %" PRIu8 + ", rsm_cell %" PRIu8 ")", vm_getbits(command, 19, 4), vm_getbits(command, 31, 8)); + break; + case 3: + fprintf(MSG_OUT, "CallSS VMGM (pgc %" PRIu8 ", rsm_cell %" PRIu8 ")", + vm_getbits(command, 46, 15), vm_getbits(command, 31, 8)); + break; + } + break; + default: + fprintf(MSG_OUT, "WARNING: Unknown Jump/Call instruction"); + } +} + +static void print_system_set(command_t* command) { + int i; +/* FIXME: What about SPRM11 ? Karaoke */ +/* Surely there must be some system set command for that ? */ + + switch(vm_getbits(command, 59, 4)) { + case 1: /* Set system reg 1 &| 2 &| 3 (Audio, Subp. Angle) */ + for(i = 1; i <= 3; i++) { + if(vm_getbits(command, 47 - (i*8), 1)) { + print_system_reg(i); + fprintf(MSG_OUT, " = "); + print_reg_or_data_2(command, vm_getbits(command, 60, 1), 47 - (i*8) ); + fprintf(MSG_OUT, " "); + } + } + break; + case 2: /* Set system reg 9 & 10 (Navigation timer, Title PGC number) */ + print_system_reg(9); + fprintf(MSG_OUT, " = "); + print_reg_or_data(command, vm_getbits(command, 60, 1), 47); + fprintf(MSG_OUT, " "); + print_system_reg(10); + fprintf(MSG_OUT, " = %" PRIu16, vm_getbits(command, 30, 15)); /* ?? */ + break; + case 3: /* Mode: Counter / Register + Set */ + fprintf(MSG_OUT, "SetMode "); + if(vm_getbits(command, 23, 1)) + fprintf(MSG_OUT, "Counter "); + else + fprintf(MSG_OUT, "Register "); + print_g_reg(vm_getbits(command, 19, 4)); + print_set_op(0x1); /* '=' */ + print_reg_or_data(command, vm_getbits(command, 60, 1), 47); + break; + case 6: /* Set system reg 8 (Highlighted button) */ + print_system_reg(8); + if(vm_getbits(command, 60, 1)) /* immediate */ + fprintf(MSG_OUT, " = 0x%x (button no %d)", vm_getbits(command, 31, 16), vm_getbits(command, 31, 6)); + else + fprintf(MSG_OUT, " = g[%" PRIu8 "]", vm_getbits(command, 19, 4)); + break; + default: + fprintf(MSG_OUT, "WARNING: Unknown system set instruction (%i)", + vm_getbits(command, 59, 4)); + } +} + +static void print_set_version_1(command_t* command) { + uint8_t set_op = vm_getbits(command, 59, 4); + + if(set_op) { + print_g_reg(vm_getbits(command, 35, 4)); + print_set_op(set_op); + print_reg_or_data(command, vm_getbits(command, 60, 1), 31); + } else { + fprintf(MSG_OUT, "NOP"); + } +} + +static void print_set_version_2(command_t* command) { + uint8_t set_op = vm_getbits(command, 59, 4); + + if(set_op) { + print_g_reg(vm_getbits(command, 51, 4)); + print_set_op(set_op); + print_reg_or_data(command, vm_getbits(command, 60, 1), 47); + } else { + fprintf(MSG_OUT, "NOP"); + } +} + +static void print_set_version_3(command_t* command) { + uint8_t set_op = vm_getbits(command, 59, 4); + + if(set_op) { + print_g_reg(vm_getbits(command, 51, 4)); + print_set_op(set_op); + print_reg_or_data_3(command, vm_getbits(command, 60, 1), 47); + } else { + fprintf(MSG_OUT, "NOP"); + } +} + + +void vm_print_mnemonic(vm_cmd_t *vm_command) { + command_t command; + command.instruction =( (uint64_t) vm_command->bytes[0] << 56 ) | + ( (uint64_t) vm_command->bytes[1] << 48 ) | + ( (uint64_t) vm_command->bytes[2] << 40 ) | + ( (uint64_t) vm_command->bytes[3] << 32 ) | + ( (uint64_t) vm_command->bytes[4] << 24 ) | + ( (uint64_t) vm_command->bytes[5] << 16 ) | + ( (uint64_t) vm_command->bytes[6] << 8 ) | + (uint64_t) vm_command->bytes[7] ; + command.examined = 0; + + switch(vm_getbits(&command,63,3)) { /* three first bits */ + case 0: /* Special instructions */ + print_if_version_1(&command); + print_special_instruction(&command); + break; + case 1: /* Jump/Call or Link instructions */ + if(vm_getbits(&command,60,1)) { + print_if_version_2(&command); + print_jump_instruction(&command); + } else { + print_if_version_1(&command); + print_link_instruction(&command, 0); /* must be pressent */ + } + break; + case 2: /* Set System Parameters instructions */ + print_if_version_2(&command); + print_system_set(&command); + print_link_instruction(&command, 1); /* either 'if' or 'link' */ + break; + case 3: /* Set General Parameters instructions */ + print_if_version_3(&command); + print_set_version_1(&command); + print_link_instruction(&command, 1); /* either 'if' or 'link' */ + break; + case 4: /* Set, Compare -> LinkSub instructions */ + print_set_version_2(&command); + fprintf(MSG_OUT, ", "); + print_if_version_4(&command); + print_linksub_instruction(&command); + break; + case 5: /* Compare -> (Set and LinkSub) instructions */ + print_if_version_5(&command); + fprintf(MSG_OUT, "{ "); + print_set_version_3(&command); + fprintf(MSG_OUT, ", "); + print_linksub_instruction(&command); + fprintf(MSG_OUT, " }"); + break; + case 6: /* Compare -> Set, always LinkSub instructions */ + print_if_version_5(&command); + fprintf(MSG_OUT, "{ "); + print_set_version_3(&command); + fprintf(MSG_OUT, " } "); + print_linksub_instruction(&command); + break; + default: + fprintf(MSG_OUT, "WARNING: Unknown instruction type (%i)", vm_getbits(&command, 63, 3)); + } + /* Check if there still are bits set that were not examined */ + + if(command.instruction & ~ command.examined) { + fprintf(MSG_OUT, " libdvdnav: vmcmd.c: [WARNING, unknown bits:"); + fprintf(MSG_OUT, " %08"PRIx64, (command.instruction & ~ command.examined) ); + fprintf(MSG_OUT, "]"); + } +} + +void vm_print_cmd(int row, vm_cmd_t *vm_command) { + int i; + + fprintf(MSG_OUT, "(%03d) ", row + 1); + for(i = 0; i < 8; i++) + fprintf(MSG_OUT, "%02x ", vm_command->bytes[i]); + fprintf(MSG_OUT, "| "); + + vm_print_mnemonic(vm_command); + fprintf(MSG_OUT, "\n"); +} + diff --git a/lib/libdvd/libdvdnav/src/vm/vmcmd.h b/lib/libdvd/libdvdnav/src/vm/vmcmd.h new file mode 100644 index 0000000000..4340b5df76 --- /dev/null +++ b/lib/libdvd/libdvdnav/src/vm/vmcmd.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2000, 2001 Martin Norbäck, Håkan Hjort + * + * This file is part of libdvdnav, a DVD navigation library. It is modified + * from a file originally part of the Ogle DVD player. + * + * libdvdnav 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. + * + * libdvdnav 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 + * + * $Id: vmcmd.h 1135 2008-09-06 21:55:51Z rathann $ + * + */ + +#ifndef VMCMD_H_INCLUDED +#define VMCMD_H_INCLUDED + +void vm_print_mnemonic(vm_cmd_t *command); +void vm_print_cmd(int row, vm_cmd_t *command); + +#endif /* VMCMD_H_INCLUDED */ diff --git a/lib/libdvd/libdvdnav/version.h b/lib/libdvd/libdvdnav/version.h new file mode 100644 index 0000000000..fd4fb3ab13 --- /dev/null +++ b/lib/libdvd/libdvdnav/version.h @@ -0,0 +1 @@ +#define VERSION "4.1.3" diff --git a/lib/libdvd/libdvdnav/version.sh b/lib/libdvd/libdvdnav/version.sh new file mode 100755 index 0000000000..230da4a8af --- /dev/null +++ b/lib/libdvd/libdvdnav/version.sh @@ -0,0 +1,18 @@ +##!/bin/sh +# +#svn_revision=`cd "$1" && LC_ALL=C svn info 2> /dev/null | grep Revision | cut -d' ' -f2` +#test $svn_revision || svn_revision=`cd "$1" && grep revision .svn/entries 2>/dev/null | \ +# cut -d '"' -f2 2> /dev/null` +#test $svn_revision || svn_revision=UNKNOWN +# +#if test "$svn_revision" = UNKNOWN && test -n "$2"; then +# NEW_REVISION="#define VERSION \"$2\"" +#else +# NEW_REVISION="#define VERSION \"SVN-r$svn_revision\"" +#fi +#OLD_REVISION=`cat version.h 2> /dev/null` +# +## Update version.h only on revision changes to avoid spurious rebuilds +#if test "$NEW_REVISION" != "$OLD_REVISION"; then +# echo "$NEW_REVISION" > version.h +#fi diff --git a/lib/libdvd/libdvdread/.relignore b/lib/libdvd/libdvdread/.relignore new file mode 100644 index 0000000000..2f2f41fa9c --- /dev/null +++ b/lib/libdvd/libdvdread/.relignore @@ -0,0 +1,2 @@ +autom4te.cache +config.status diff --git a/lib/libdvd/libdvdread/AUTHORS b/lib/libdvd/libdvdread/AUTHORS new file mode 100644 index 0000000000..cb528af0dd --- /dev/null +++ b/lib/libdvd/libdvdread/AUTHORS @@ -0,0 +1,6 @@ +Daniel Caujolle-Bert <segfault@club-internet.fr> +Thomas Vander Stichele <thomas@apestaart.org> +Rich Wareham <richwareham@users.sourceforge.net> +Kees Cook <kees@outflux.net> +Michael Roitzsch <mroi@users.sourceforge.net> +Frantisek Dvorak <valtri@users.sourceforge.net> diff --git a/lib/libdvd/libdvdread/COPYING b/lib/libdvd/libdvdread/COPYING new file mode 100644 index 0000000000..d60c31a97a --- /dev/null +++ b/lib/libdvd/libdvdread/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. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + 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. + + <signature of Ty Coon>, 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/lib/libdvd/libdvdread/ChangeLog b/lib/libdvd/libdvdread/ChangeLog new file mode 100644 index 0000000000..3bd83761ae --- /dev/null +++ b/lib/libdvd/libdvdread/ChangeLog @@ -0,0 +1,130 @@ +libdvdread (4.1.3) + * an embarassing 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." occuring 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 layed 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 <richwareham@users.sourceforge.net> 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 <jcdutton@users.sourceforge.net> 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 <pmhahn@titan.lahn.de> 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 <pmhahn@titan.lahn.de> 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 <siggi@debian.org> Mon, 20 May 2002 15:57:40 +0200 + +libdvdnav (0.0.1-1) unstable; urgency=low + + * Repackaged using dh-make. + + -- Philipp Matthias Hahn <pmhahn@titan.lahn.de> Sun, 7 Apr 2002 16:29:35 +0200 + +libdvdnav (0.0.1) unstable; urgency=low + + * Initial release. + * Split from xine-dvdnav + + -- rjw57 <rjw57@hermes.cam.ac.uk> Tue, 12 Mar 2002 19:41:13 +0000 + diff --git a/lib/libdvd/libdvdread/DEVELOPMENT-POLICY.txt b/lib/libdvd/libdvdread/DEVELOPMENT-POLICY.txt new file mode 100644 index 0000000000..20c73e5005 --- /dev/null +++ b/lib/libdvd/libdvdread/DEVELOPMENT-POLICY.txt @@ -0,0 +1,25 @@ +This fork of dvdnav was created to overcome the lack of responsiveness +of the official development channel, not to bastardize this library in +something for specific usage by mplayer, so these are the rules to follow +when developing code: +- don't remove pre-existing code that mplayer doesn't need +- don't add code to expose the internals of dvdnav +- don't add code that binds applications to side-effects of the library +- don't alter the API in an incompatible manner + + +When committing code to the repository always follow these rules: +- don't break the compilability of the library - always keep svn checkouts usable +- never mix cosmetical and functional changes +- don't commit unrelated changes as a single transaction +- don't split strictly related changes over multiple commits +- never alter the indentation / bracing / prototyping style of existing files +- if you break something by accident fix it as soon as possible using the appropriate + svn tools to revert your commit(s). If in doubt ask explanations to the + mailing list +- trivial patches such as spell fixes, prototype mismatch, missing includes, + more proper variable typization and similar should be committed without asking + prior authorization + + +If in reiterated violation of these rules your account will be deleted. diff --git a/lib/libdvd/libdvdread/Makefile b/lib/libdvd/libdvdread/Makefile new file mode 100644 index 0000000000..dc2c906c4f --- /dev/null +++ b/lib/libdvd/libdvdread/Makefile @@ -0,0 +1,166 @@ +include config.mak + +.SUFFIXES: .so + +AR=ar +LD=ld +RANLIB=ranlib + +VPATH+= $(SRC_PATH_BARE)/src + +CFLAGS += $(USEDEBUG) -Wall -funsigned-char +CFLAGS += -I$(CURDIR) -I$(SRC_PATH)/src +CFLAGS += -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE +CFLAGS += -DHAVE_CONFIG_H -DHAVE_DLFCN_H + +L=libdvdread +DVDREAD_L=libdvdread +DVDREAD_LIB = $(DVDREAD_L).a +DVDREAD_SHLIB = $(DVDREAD_L).so +VPATH+= $(SRC_PATH_BARE)/src +DVDREAD_HEADERS = src/dvd_reader.h \ + src/ifo_print.h \ + src/ifo_read.h \ + src/ifo_types.h \ + src/nav_print.h \ + src/nav_read.h \ + src/dvd_udf.h \ + src/nav_types.h \ + src/bitreader.h +DVDREAD_SRCS = dvd_input.c dvd_reader.c dvd_udf.c ifo_print.c ifo_read.c \ + md5.c nav_print.c nav_read.c bitreader.c +CFLAGS += -I$(SRC_PATH)/src + +LIB = $(L).a +SHLIB = $(L).so + +.OBJDIR= obj +DEPFLAG = -M + +OBJS = $(patsubst %.c,%.o, $(SRCS)) +DVDREAD_OBJS = $(patsubst %.c,%.o, $(DVDREAD_SRCS)) +SHOBJS = $(patsubst %.c,%.so, $(SRCS)) +DVDREAD_SHOBJS = $(patsubst %.c,%.so, $(DVDREAD_SRCS)) +DEPS= ${OBJS:%.o=%.d} +DVDREAD_DEPS= ${DVDREAD_OBJS:%.o=%.d} + +BUILDDEPS = Makefile config.mak + +ifeq ($(BUILD_SHARED),yes) +all: $(SHLIB) $(DVDREAD_SHLIB) dvdread-config pkgconfig +install: $(SHLIB) $(DVDREAD_SHLIB) install-shared install-dvdread-config install-pkgconfig +endif + +ifeq ($(BUILD_STATIC),yes) +all: $(LIB) $(DVDREAD_LIB) dvdread-config pkgconfig +install: $(LIB) $(DVDREAD_LIB) install-static install-dvdread-config install-pkgconfig +endif + +install: install-headers + +# Let version.sh create version.h + +SVN_ENTRIES = $(SRC_PATH_BARE)/.svn/entries +ifeq ($(wildcard $(SVN_ENTRIES)),$(SVN_ENTRIES)) +version.h: $(SVN_ENTRIES) +endif + +version.h: + sh $(SRC_PATH)/version.sh $(SRC_PATH) "$(SHLIB_VERSION)" + +$(SRCS) $(DVDREAD_SRCS): version.h + + +# General targets + +${DVDREAD_LIB}: version.h $(DVDREAD_OBJS) $(BUILDDEPS) + cd $(.OBJDIR) && $(AR) rc $@ $(DVDREAD_OBJS) + cd $(.OBJDIR) && $(RANLIB) $@ + +${DVDREAD_SHLIB}: version.h $(DVDREAD_SHOBJS) $(BUILDDEPS) + cd $(.OBJDIR) && $(CC) $(SHLDFLAGS) $(LDFLAGS) -ldl -Wl,-soname=$(DVDREAD_SHLIB).$(SHLIB_MAJOR) -o $@ $(DVDREAD_SHOBJS) + +.c.so: $(BUILDDEPS) + cd $(.OBJDIR) && $(CC) -fPIC -DPIC -MD $(CFLAGS) -c -o $@ $< + +.c.o: $(BUILDDEPS) + cd $(.OBJDIR) && $(CC) -MD $(CFLAGS) -c -o $@ $< + + +# Install targets + +install-headers: + install -d $(DESTDIR)$(dvdread_incdir) + install -m 644 $(DVDREAD_HEADERS) $(DESTDIR)$(dvdread_incdir) + +install-shared: $(SHLIB) + install -d $(DESTDIR)$(shlibdir) + + install $(INSTALLSTRIP) -m 755 $(.OBJDIR)/$(SHLIB) \ + $(DESTDIR)$(shlibdir)/$(SHLIB).$(SHLIB_VERSION) + + cd $(DESTDIR)$(shlibdir) && \ + ln -sf $(SHLIB).$(SHLIB_VERSION) $(SHLIB).$(SHLIB_MAJOR) + cd $(DESTDIR)$(shlibdir) && \ + ln -sf $(SHLIB).$(SHLIB_MAJOR) $(SHLIB) + + install $(INSTALLSTRIP) -m 755 $(.OBJDIR)/$(DVDREAD_SHLIB) \ + $(DESTDIR)$(shlibdir)/$(DVDREAD_SHLIB).$(SHLIB_VERSION) + cd $(DESTDIR)$(shlibdir) && \ + ln -sf $(DVDREAD_SHLIB).$(SHLIB_VERSION) $(DVDREAD_SHLIB).$(SHLIB_MAJOR) + cd $(DESTDIR)$(shlibdir) && \ + ln -sf $(DVDREAD_SHLIB).$(SHLIB_MAJOR) $(DVDREAD_SHLIB) + +install-static: $(LIB) + install -d $(DESTDIR)$(libdir) + + install $(INSTALLSTRIP) -m 755 $(.OBJDIR)/$(LIB) $(DESTDIR)$(libdir)/$(LIB) + install $(INSTALLSTRIP) -m 755 $(.OBJDIR)/$(DVDREAD_LIB) $(DESTDIR)$(libdir)/$(DVDREAD_LIB) + + +# Clean targets + +clean: + rm -rf *~ $(.OBJDIR)/* + + +distclean: clean + find . -name "*~" | xargs rm -rf + rm -rf config.mak $(.OBJDIR) + +dvdread-config: $(.OBJDIR)/dvdread-config +$(.OBJDIR)/dvdread-config: $(BUILDDEPS) + @echo '#!/bin/sh' > $(.OBJDIR)/dvdread-config + @echo 'prefix='$(PREFIX) >> $(.OBJDIR)/dvdread-config + @echo 'libdir='$(shlibdir) >> $(.OBJDIR)/dvdread-config + @echo 'version='$(SHLIB_VERSION) >> $(.OBJDIR)/dvdread-config + @echo >> $(.OBJDIR)/dvdread-config + cat $(SRC_PATH_BARE)/misc/dvdread-config.sh >> $(.OBJDIR)/dvdread-config + chmod 0755 $(.OBJDIR)/dvdread-config + +install-dvdread-config: dvdread-config + install -d $(DESTDIR)$(PREFIX)/bin + install -m 0755 $(.OBJDIR)/dvdread-config $(DESTDIR)$(PREFIX)/bin/dvdread-config + +pcedit = sed \ + -e 's,@prefix@,$(PREFIX),' \ + -e 's,@exec_prefix@,$(PREFIX),' \ + -e 's,@libdir@,$(shlibdir),' \ + -e 's,@includedir@,$(PREFIX)/include,' \ + -e 's,@VERSION@,$(SHLIB_VERSION),' + +pkgconfig: $(.OBJDIR)/dvdread.pc +$(.OBJDIR)/dvdread.pc: misc/dvdread.pc.in $(BUILDDEPS) + $(pcedit) $< > $@ + +install-pkgconfig: $(.OBJDIR)/dvdread.pc + install -d $(DESTDIR)$(libdir)/pkgconfig + install -m 0644 $(.OBJDIR)/dvdread.pc $(DESTDIR)$(libdir)/pkgconfig + +vpath %.so ${.OBJDIR} +vpath %.o ${.OBJDIR} +vpath ${LIB} ${.OBJDIR} + +# include dependency files if they exist +$(addprefix ${.OBJDIR}/, ${DEPS}): ; +-include $(addprefix ${.OBJDIR}/, ${DEPS}) diff --git a/lib/libdvd/libdvdread/Makefile.am b/lib/libdvd/libdvdread/Makefile.am new file mode 100644 index 0000000000..84adceed94 --- /dev/null +++ b/lib/libdvd/libdvdread/Makefile.am @@ -0,0 +1,42 @@ +include $(top_srcdir)/misc/Makefile.common + + +SUBDIRS = src misc m4 + +EXTRA_DIST = autogen.sh \ + AUTHORS \ + ChangeLog \ + configure \ + config.guess \ + config.sub \ + COPYING \ + INSTALL \ + install-sh \ + libtool \ + ltmain.sh \ + missing \ + mkinstalldirs \ + README \ + TODO + +MOSTLYCLEANFILES += $(PACKAGE)_$(VERSION).tar.gz \ + $(distdir).tar.gz $(PACKAGE).tgz package_descriptions + +MAINTAINERCLEANFILES += configure $(ACLOCAL_M4) config.h.in \ + ltmain.sh config.guess config.sub install-sh missing \ + mkinstalldirs + +world: + @$(MAKE) clean all install 2> warnings.log + test -s warnings.log || rm warnings.log + +prune-cache: + -rm -f config.cache + +release-check: + @./config.status misc/relchk.sh + @./autogen.sh noconfig && $(SHELL) misc/relchk.sh + +dist-hook: + cp -r $(srcdir)/msvc $(distdir)/msvc + rm -rf `find $(distdir)/msvc -name CVS` diff --git a/lib/libdvd/libdvdread/NEWS b/lib/libdvd/libdvdread/NEWS new file mode 100644 index 0000000000..7aa22b1545 --- /dev/null +++ b/lib/libdvd/libdvdread/NEWS @@ -0,0 +1,2 @@ +This file is unused. +The ChangeLog file lists changes for new versions. diff --git a/lib/libdvd/libdvdread/README b/lib/libdvd/libdvdread/README new file mode 100644 index 0000000000..d7f78d48a2 --- /dev/null +++ b/lib/libdvd/libdvdread/README @@ -0,0 +1,57 @@ +What is this all about? +----------------------- + +libdvdnav is a library that allows easy use of sophisticated DVD navigation +features such as DVD menus, multiangle playback and even interactive DVD games. +All this functionality is provided through a simple API which provides the +DVD playback as a single logical stream of blocks, intermitted by special +dvdnav events to report certain conditions. The main usage of libdvdnav is a +loop regularly calling a function to get the next block, surrounded by +additional calls to tell the library of user interaction. +The whole DVD virtual machine and internal playback states are completely +encapsulated. + +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 +libdvdnav 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. + +Where is it now? +---------------- + +libdvdnav is hosted on http://www.mplayerhq.hu/MPlayer/releases/dvdnav/ . +Please report bugs to the developers mailinglist at +mailto:dvdnav-discuss@mplayerhq.hu . + +We are still in beta stage, but libdvdnav is already quite usable. With +regular DVD playback, there should not be any serious issues. The library +also makes some limited effort to handle error situations gracefully, but +there are still assertions in the code that may trigger on some DVDs. Please +send a report to the developer mailinglist, if you encounter such problems. + +How can I use it? +----------------- + +libdvdnav is completely licensed under GPL. You may use it at wish within the +bounds of this license. See the file "COPYING" for a copy of the GPL. + +Sources for documentation on libdvdnav are: +* the examples directory contains a simple program using libdvdnav + this one is well-commented and therefore a good starting point +* the public header dvdnav.h documents the API +* the public header dvdnav_events.h documents the dvdnav events +* doc/library_layout contains some info on the internal working of libdvdnav + +Sources for documentation on DVD terminology, structure and surrounding concepts: +* doc/dvd_structures briefly explains DVD terms and organization +* a more detailed description of DVD structures is available at + http://www.mpucoder.com/dvd/ +* the ifo_types.h and nav_types.h headers are also interesting if you + are already used to the sometimes cryptical abbreviations diff --git a/lib/libdvd/libdvdread/TODO b/lib/libdvd/libdvdread/TODO new file mode 100644 index 0000000000..3fe2eed5af --- /dev/null +++ b/lib/libdvd/libdvdread/TODO @@ -0,0 +1,12 @@ +* Support DVDs with errors on them. So we can recover from corrupt sectors in the .VOB. Also, handle corrupt .IFO files by using the backup .BUP files. +* Support Random and Shuffle Titles. Only sequencial 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 +* RELEASE! (maybe it's time for libdvdnav 0.5?) +* Replace the auto* build system with a custom and clean one based on ffmpeg's (partly done) diff --git a/lib/libdvd/libdvdread/autogen.sh b/lib/libdvd/libdvdread/autogen.sh new file mode 100755 index 0000000000..72f2ac80ee --- /dev/null +++ b/lib/libdvd/libdvdread/autogen.sh @@ -0,0 +1,29 @@ +#!/bin/sh +# +# $Id: autogen.sh 1128 2008-08-30 22:32:00Z rathann $ +# +# run this to generate all the initial makefiles, etc. + +srcdir=`dirname "$0"` +test -z "$srcdir" && srcdir=. + +ORIGDIR=`pwd` +cd "$srcdir" + +AUTORECONF=${AUTORECONF-autoreconf} + +if ! type $AUTORECONF >/dev/null 2>&1; then + echo "**Error**: Missing \`autoreconf' program." >&2 + echo "You will need the autoconf and automake packages." >&2 + echo "You can download them from ftp://ftp.gnu.org/pub/gnu/." >&2 + exit 1 +fi + +$AUTORECONF -v --install || exit $? +cd "$ORIGDIR" || exit $? + +test "$1" = noconfig && NOCONFIGURE=1 + +if test -z "$NOCONFIGURE"; then + "$srcdir"/configure "$@" +fi diff --git a/lib/libdvd/libdvdread/configure.ac b/lib/libdvd/libdvdread/configure.ac new file mode 100644 index 0000000000..1425c371ac --- /dev/null +++ b/lib/libdvd/libdvdread/configure.ac @@ -0,0 +1,210 @@ +dnl -------------------------------------------------------------- +dnl Configure.ac for libdvdread +dnl -------------------------------------------------------------- + +dnl -------------------------------------------------------------- +dnl Require autoconf version 2.53 +dnl -------------------------------------------------------------- +AC_PREREQ([2.53]) + +dnl -------------------------------------------------------------- +dnl Making releases: dvdread_sub += 1; change DVDREAD_LT_* accordingly +dnl +dnl These are defined in m4 so they can be passed to AC_INIT +dnl -------------------------------------------------------------- +m4_define([dvdread_major], [4]) +m4_define([dvdread_minor], [1]) +m4_define([dvdread_sub], [3]) +m4_define([dvdread_pre], []) + +AC_INIT([libdvdread], [dvdread_major.dvdread_minor.dvdread_sub[]dvdread_pre]) +AC_CONFIG_SRCDIR([src/dvd_reader.h]) +AM_INIT_AUTOMAKE([1.6]) + +dnl create a config.h file (Automake will add -DHAVE_CONFIG_H) +AC_CONFIG_HEADERS([config.h]) +AC_CANONICAL_HOST + +DVDREAD_MAJOR="dvdread_major" +DVDREAD_MINOR="dvdread_minor" +DVDREAD_SUB="dvdread_sub" +DVDREAD_PRE="dvdread_pre" + +AC_SUBST(DVDREAD_MAJOR) +AC_SUBST(DVDREAD_MINOR) +AC_SUBST(DVDREAD_SUB) + +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_AGE.DVDREAD_LT_REVISION + +DVDREAD_LT_CURRENT=5 +DVDREAD_LT_AGE=1 +DVDREAD_LT_REVISION=2 + +AC_SUBST(DVDREAD_LT_CURRENT) +AC_SUBST(DVDREAD_LT_AGE) +AC_SUBST(DVDREAD_LT_REVISION) + +dnl -------------------------------------------------------------- +dnl Make possible to build for another arch. +dnl -------------------------------------------------------------- +if test x$DVDREAD_BUILD != "x"; then + AC_MSG_RESULT(*** build forced to $DVDREAD_BUILD ***) + build=$DVDREAD_BUILD + host=$DVDREAD_BUILD +else + check_athlon=yes +fi + +dnl -------------------------------------------------------------- +dnl Checks for programs. +dnl -------------------------------------------------------------- +dnl Save CFLAGS, AC_ISC_POSIX set some unwanted default CFLAGS +saved_CFLAGS="$CFLAGS" +AC_ISC_POSIX +CFLAGS="$saved_CFLAGS" +AC_PROG_CC +AC_PROG_MAKE_SET +AC_PROG_INSTALL +AC_PROG_LN_S + +dnl -------------------------------------------------------------- +dnl Libtool +dnl -------------------------------------------------------------- +dnl LT_PREREQ only available in libtool-2.2+ +dnl LT_PREREQ([1.4.0]) +AC_LIBTOOL_DLOPEN +AC_DISABLE_STATIC +AC_PROG_LIBTOOL +AC_SUBST(LIBTOOL_DEPS) +if ${CONFIG_SHELL} ./libtool --features | grep "enable static" >/dev/null; then + STATIC="-static" +else + STATIC= +fi +AC_SUBST(STATIC) + +dnl -------------------------------------------------------------- +dnl Checks for header files. +dnl -------------------------------------------------------------- +AC_HEADER_STDC +AC_CHECK_HEADER(unistd.h) +AC_CHECK_HEADER(string.h) + +dnl -------------------------------------------------------------- +dnl Checks for typedefs, structures, and compiler characteristics. +dnl -------------------------------------------------------------- +AC_C_CONST +AC_C_INLINE +AC_TYPE_OFF_T +AC_TYPE_SIZE_T +dnl AC_CHECK_TYPES([ptrdiff_t]) +AC_C_BIGENDIAN + +dnl ------------------------------------------------------------- +dnl Check for basic *nix fonction that we may emulate on windows. +dnl ------------------------------------------------------------- +case $host in + *mingw32* | *cygwin*) + AC_CHECK_FUNCS(gettimeofday) + ;; + *) + ;; +esac + +dnl --------------------------------------------- +dnl dynamic linker +dnl --------------------------------------------- +case $host in + *mingw32*) + CFLAGS="-idirafter \$(top_srcdir)/msvc/include $CFLAGS" + LDFLAGS="-no-undefined $LDFLAGS" + ;; + *cygwin*) + LDFLAGS="-no-undefined $LDFLAGS" + ;; + *) + AC_CHECK_LIB(c, dlopen, + DYNAMIC_LD_LIBS="", + AC_CHECK_LIB(dl, dlopen, + DYNAMIC_LD_LIBS="-ldl", + AC_MSG_ERROR(dynamic linker needed))) + AC_SUBST(DYNAMIC_LD_LIBS) + ;; +esac + +dnl --------------------------------------------- +dnl cflags +dnl --------------------------------------------- +dnl Common cflags for all platforms +CFLAGS="-O3 -Wall -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE $CFLAGS" +DEBUG_CFLAGS="-g -DDEBUG $CFLAGS" + +AC_SUBST(DEBUG_CFLAGS) + +dnl --------------------------------------------- +dnl Get where .m4 should be installed. +dnl --------------------------------------------- +case "`id`" in + uid=0\(* ) + AC_MSG_CHECKING(for aclocal directory) + if (aclocal --version) < /dev/null > /dev/null 2>&1; then + ACLOCAL_DIR="`eval $ACLOCAL --print-ac-dir`" + AC_MSG_RESULT($ACLOCAL_DIR) + else + ACLOCAL_DIR="/usr/local/share/aclocal" + AC_MSG_RESULT(none - will be installed in $ACLOCAL_DIR) + fi + escapedprefix="`echo $prefix | sed -e 's/\\//\\\\\//g'`" + ACLOCAL_DIR="`echo $ACLOCAL_DIR|sed -e 's/^'$escapedprefix/'\${prefix}'/`" + AC_SUBST(ACLOCAL_DIR) + ;; +esac +AM_CONDITIONAL(INSTALL_M4, test x"$ACLOCAL_DIR" != "x") + +dnl --------------------------------------------- +dnl Check for doxygen (dynamic documentation generator) +dnl --------------------------------------------- +AC_CHECK_PROG(DOXYGEN, doxygen, doxygen, no) + +dnl --------------------------------------------- +dnl Some include paths ( !!! DO NOT REMOVE !!! ) +dnl --------------------------------------------- +INCLUDES='-I$(top_srcdir) $(DVDREAD_CFLAGS)' +AC_SUBST(INCLUDES) + +dnl --------------------------------------------- +dnl Output configuration files +dnl --------------------------------------------- +AC_OUTPUT([ +Makefile +src/Makefile +misc/Makefile +misc/dvdread-config +misc/dvdread.pc +misc/libdvdread.spec +misc/relchk.sh +m4/Makefile +]) diff --git a/lib/libdvd/libdvdread/configure2 b/lib/libdvd/libdvdread/configure2 new file mode 100755 index 0000000000..08c0c40e15 --- /dev/null +++ b/lib/libdvd/libdvdread/configure2 @@ -0,0 +1,155 @@ +#!/bin/sh + +dvdread_sh_version=4.1.3 +dvdread_sh_major=`echo $dvdread_sh_version | awk -F. '{print $1}'` + +cc=gcc +make=make + +# find source path +source_path="`dirname \"$0\"`" +source_path_used="yes" +if test -z "$source_path" -o "$source_path" = "." ; then + source_path="`pwd`" + source_path_used="no" +else + source_path="`cd \"$source_path\" && pwd`" + echo "$source_path" | grep -q '[[:blank:]]' && + die "Out of tree builds are impossible with whitespace in source path." +fi + +show_help(){ + echo "Usage: configure [options]" + echo "Options: [defaults in brackets after descriptions]" + echo + echo "Standard options:" + echo " --help print this message" + echo " --prefix=PREFIX install in PREFIX [$PREFIX]" + echo " --libdir=DIR install libs in DIR [PREFIX/lib]" + echo " --shlibdir=DIR install shared libs in DIR [PREFIX/lib]" + echo " --incdir=DIR install includes in DIR [PREFIX/include/libdvdread]" + echo " --enable-static build static libraries [default=yes]" + echo " --disable-static do not build static libraries [default=no]" + echo " --enable-shared build shared libraries [default=no]" + echo " --disable-shared do not build shared libraries [default=yes]" + echo " --enable-debug compile with debug symbols [default=yes]" + echo " --disable-debug compile without debug symbols [default=no]" + echo "Advanced options (experts only):" + echo " --cc=CC use C compiler CC [$cc]" + echo " --make=MAKE use specified make [$make]" + echo " --extra-cflags=ECFLAGS add ECFLAGS to CFLAGS" + echo " --extra-ldflags=ELDFLAGS add ELDFLAGS to LDFLAGS" + echo "Developer options:" + echo " --disable-strip disable stripping of executables and shared libraries" + echo " --disable-opts disable compiler optimizations" + exit 1 +} + +SHARED=yes +STATIC=yes +PREFIX=/usr/local/ +INSTALLSTRIP=-s +USEDEBUG=-g +optimizations="-O3" + +for opt do + optval=`echo $opt | cut -d '=' -f 2-` + case "$opt" in + --enable-shared) SHARED=yes + ;; + --disable-shared) SHARED=no + ;; + --enable-static) STATIC=yes + ;; + --disable-static) STATIC=no + ;; + --prefix=*) PREFIX="$optval" + ;; + --libdir=*) libdir="$optval" + ;; + --shlibdir=*) shlibdir="$optval" + ;; + --incdir=*) incdir="$optval" + ;; + --cc=*) cc="$optval" + ;; + --make=*) make="$optval" + ;; + --extra-cflags=*) cflags="$cflags $optval" + ;; + --extra-ldflags=*) ldflags="$ldflags $optval" + ;; + --disable-strip) INSTALLSTRIP= + ;; + --disable-opts) optimizations="" + ;; + --disable-debug) USEDEBUG="" + ;; + --enable-debug) USEDEBUG="-g" + ;; + --help) show_help + ;; + esac +done + +PREFIX=`cd $PREFIX && pwd` + +test -z "$libdir" && libdir=$PREFIX/lib +test -z "$shlibdir" && shlibdir=$PREFIX/lib +test -z "$incdir" && dvdread_incdir=$PREFIX/include/dvdread + +targetos=`uname -s` +case $targetos in + Darwin) + SHLDFLAGS="-dynamiclib -Wl,-single_module -Wl,-read_only_relocs,suppress" + ;; + *) + SHLDFLAGS="-shared" + ;; +esac + +cat > config.mak << EOF +# Automatically generated by configure, do not edit +PREFIX=$PREFIX +libdir=$libdir +shlibdir=$shlibdir +incdir=$incdir +dvdread_incdir=$dvdread_incdir +BUILD_SHARED=$SHARED +BUILD_STATIC=$STATIC +SHLIB_VERSION=$dvdread_sh_version +SHLIB_MAJOR=$dvdread_sh_major +CC=$cc +MAKE=$make +CFLAGS=$optimizations $cflags +LDFLAGS=$ldflags +SHLDFLAGS=$SHLDFLAGS +INSTALLSTRIP=$INSTALLSTRIP +USEDEBUG=$USEDEBUG + +SRC_PATH="$source_path" +SRC_PATH_BARE=$source_path + +EOF + +cat > config.h << EOF +/* Automatically generated by configure, do not edit */ +#include "version.h" +EOF + +# build tree in object directory if source path is different from current one +if test "$source_path_used" != "no"; then + FILES="\ + Makefile \ + misc \ + " + for f in $FILES ; do + ln -sf "$source_path/$f" $f + done +fi + +[ -d obj ] || mkdir -p obj + +echo +echo "Done, type 'make install' to build and install" + diff --git a/lib/libdvd/libdvdread/m4/Makefile.am b/lib/libdvd/libdvdread/m4/Makefile.am new file mode 100644 index 0000000000..a29b467bb7 --- /dev/null +++ b/lib/libdvd/libdvdread/m4/Makefile.am @@ -0,0 +1,11 @@ +include $(top_srcdir)/misc/Makefile.common + +EXTRA_DIST = dvdread.m4 + +if INSTALL_M4 +m4datadir = @ACLOCAL_DIR@ +else +m4datadir = $(datadir)/aclocal +endif + +m4data_DATA = dvdread.m4 diff --git a/lib/libdvd/libdvdread/m4/dvdread.m4 b/lib/libdvd/libdvdread/m4/dvdread.m4 new file mode 100644 index 0000000000..e11b35c046 --- /dev/null +++ b/lib/libdvd/libdvdread/m4/dvdread.m4 @@ -0,0 +1,181 @@ +dnl Configure paths for DVDREAD +dnl +dnl Copyright (C) 2001 Daniel Caujolle-Bert <segfault@club-internet.fr> +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 of the License, or +dnl (at your option) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +dnl +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a configuration +dnl script generated by Autoconf, you may include it under the same +dnl distribution terms that you use for the rest of that program. +dnl + +dnl AM_PATH_DVDREAD([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) +dnl Test for DVDREAD, and define DVDREAD_CFLAGS and DVDREAD_LIBS +dnl +AC_DEFUN([AM_PATH_DVDREAD], +[dnl +dnl Get the cflags and libraries from the dvdread-config script +dnl +AC_ARG_WITH(dvdread-prefix, + AC_HELP_STRING([--with-dvdread-prefix=DIR], [prefix where DVDREAD is installed (optional)]), + dvdread_config_prefix="$withval", dvdread_config_prefix="") +AC_ARG_WITH(dvdread-exec-prefix, + AC_HELP_STRING([--with-dvdread-exec-prefix=DIR], [exec prefix where DVDREAD is installed (optional)]), + dvdread_config_exec_prefix="$withval", dvdread_config_exec_prefix="") +AC_ARG_ENABLE(dvdreadtest, + AC_HELP_STRING([--disable-dvdreadtest], [do not try to compile and run a test DVDREAD program]), + enable_dvdreadtest=$enableval, enable_dvdreadtest=yes) + + if test x$dvdread_config_exec_prefix != x ; then + dvdread_config_args="$dvdread_config_args --exec-prefix=$dvdread_config_exec_prefix" + if test x${DVDREAD_CONFIG+set} != xset ; then + DVDREAD_CONFIG=$dvdread_config_exec_prefix/bin/dvdread-config + fi + fi + if test x$dvdread_config_prefix != x ; then + dvdread_config_args="$dvdread_config_args --prefix=$dvdread_config_prefix" + if test x${DVDREAD_CONFIG+set} != xset ; then + DVDREAD_CONFIG=$dvdread_config_prefix/bin/dvdread-config + fi + fi + + min_dvdread_version=ifelse([$1], ,0.0.0,$1) + if test "x$enable_dvdreadtest" != "xyes" ; then + AC_MSG_CHECKING([for DVDREAD-LIB version >= $min_dvdread_version]) + else + AC_PATH_PROG(DVDREAD_CONFIG, dvdread-config, no) + AC_MSG_CHECKING([for DVDREAD-LIB version >= $min_dvdread_version]) + no_dvdread="" + if test "$DVDREAD_CONFIG" = "no" ; then + no_dvdread=yes + else + DVDREAD_CFLAGS=`$DVDREAD_CONFIG $dvdread_config_args --cflags` + DVDREAD_LIBS=`$DVDREAD_CONFIG $dvdread_config_args --libs` + dvdread_config_major_version=`$DVDREAD_CONFIG $dvdread_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + dvdread_config_minor_version=`$DVDREAD_CONFIG $dvdread_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + dvdread_config_sub_version=`$DVDREAD_CONFIG $dvdread_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + dnl if test "x$enable_dvdreadtest" = "xyes" ; then + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $DVDREAD_CFLAGS" + LIBS="$DVDREAD_LIBS $LIBS" +dnl +dnl Now check if the installed DVDREAD is sufficiently new. (Also sanity +dnl checks the results of dvdread-config to some extent +dnl + AC_LANG_SAVE() + AC_LANG_C() + rm -f conf.dvdreadtest + AC_TRY_RUN([ +#include <dvdread.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +int +main () +{ + int major, minor, sub; + char *tmp_version; + + system ("touch conf.dvdreadtest"); + + /* HP/UX 9 (%@#!) writes to sscanf strings */ + tmp_version = (char *) strdup("$min_dvdread_version"); + if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &sub) != 3) { + printf("%s, bad version string\n", "$min_dvdread_version"); + exit(1); + } + + if (($dvdread_config_major_version > major) || + (($dvdread_config_major_version == major) && ($dvdread_config_minor_version > minor)) || + (($dvdread_config_major_version == major) && ($dvdread_config_minor_version == minor) && ($dvdread_config_sub_version >= sub))) { + return 0; + } else { + printf("\n*** An old version of libdvdread (%d.%d.%d) was found.\n", + $dvdread_config_major_version, $dvdread_config_minor_version, $dvdread_config_sub_version); + printf("*** You need a version of libdvdread newer than %d.%d.%d. The latest version of\n", + major, minor, sub); + printf("*** libdvdread is always available from:\n"); + printf("*** http://dvd.sourceforge.net\n"); + printf("***\n"); + printf("*** If you have already installed a sufficiently new version, this error\n"); + printf("*** probably means that the wrong copy of the dvdread-config shell script is\n"); + printf("*** being found. The easiest way to fix this is to remove the old version\n"); + printf("*** of libdvdread, but you can also set the DVDREAD_CONFIG environment to point to the\n"); + printf("*** correct copy of dvdread-config. (In this case, you will have to\n"); + printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n"); + printf("*** so that the correct libraries are found at run-time))\n"); + } + return 1; +} +],, no_dvdread=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + if test "x$no_dvdread" = x ; then + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) + else + AC_MSG_RESULT(no) + if test "$DVDREAD_CONFIG" = "no" ; then + echo "*** The dvdread-config script installed by DVDREAD could not be found" + echo "*** If DVDREAD was installed in PREFIX, make sure PREFIX/bin is in" + echo "*** your path, or set the DVDREAD_CONFIG environment variable to the" + echo "*** full path to dvdread-config." + else + if test -f conf.dvdreadtest ; then + : + else + echo "*** Could not run DVDREAD test program, checking why..." + CFLAGS="$CFLAGS $DVDREAD_CFLAGS" + LIBS="$LIBS $DVDREAD_LIBS" + AC_TRY_LINK([ +#include <dvdread.h> +#include <stdio.h> +], [ return 0; ], + [ echo "*** The test program compiled, but did not run. This usually means" + echo "*** that the run-time linker is not finding DVDREAD or finding the wrong" + echo "*** version of DVDREAD. If it is not finding DVDREAD, you'll need to set your" + echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" + echo "*** to the installed location Also, make sure you have run ldconfig if that" + echo "*** is required on your system" + echo "***" + echo "*** If you have an old version installed, it is best to remove it, although" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" + echo "***"], + [ echo "*** The test program failed to compile or link. See the file config.log for the" + echo "*** exact error that occured. This usually means DVDREAD was incorrectly installed" + echo "*** or that you have moved DVDREAD since it was installed. In the latter case, you" + echo "*** may want to edit the dvdread-config script: $DVDREAD_CONFIG" ]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + DVDREAD_CFLAGS="" + DVDREAD_LIBS="" + ifelse([$3], , :, [$3]) + fi + AC_SUBST(DVDREAD_CFLAGS) + AC_SUBST(DVDREAD_LIBS) + AC_LANG_RESTORE() + rm -f conf.dvdreadtest +]) diff --git a/lib/libdvd/libdvdread/misc/Makefile.am b/lib/libdvd/libdvdread/misc/Makefile.am new file mode 100644 index 0000000000..efe65034c3 --- /dev/null +++ b/lib/libdvd/libdvdread/misc/Makefile.am @@ -0,0 +1,8 @@ +include $(top_srcdir)/misc/Makefile.common + +EXTRA_DIST = libdvdread.spec.in libdvdread.spec Makefile.common relchk.sh relchk.sh.in + +bin_SCRIPTS = dvdread-config + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = dvdread.pc diff --git a/lib/libdvd/libdvdread/misc/Makefile.common b/lib/libdvd/libdvdread/misc/Makefile.common new file mode 100644 index 0000000000..6faa23f2c7 --- /dev/null +++ b/lib/libdvd/libdvdread/misc/Makefile.common @@ -0,0 +1,10 @@ +MOSTLYCLEANFILES = *~ \\\#* .*~ .\\\#* +MAINTAINERCLEANFILES = Makefile.in + +debug: + @$(MAKE) CFLAGS="$(DEBUG_CFLAGS)" + +debug-install: install-debug + +install-debug: + @$(MAKE) CFLAGS="$(DEBUG_CFLAGS)" install diff --git a/lib/libdvd/libdvdread/misc/dvdread-config.in b/lib/libdvd/libdvdread/misc/dvdread-config.in new file mode 100644 index 0000000000..cf38462e24 --- /dev/null +++ b/lib/libdvd/libdvdread/misc/dvdread-config.in @@ -0,0 +1,80 @@ +#!/bin/sh +# +# + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +exec_prefix_set=no + +usage() +{ + cat <<EOF +Usage: dvdnav-config [OPTIONS] [LIBRARIES] +Options: + [--prefix[=DIR]] + [--exec-prefix[=DIR]] + [--version] + [--libs] + [--cflags] +EOF + exit $1 +} + +if test $# -eq 0; then + usage 1 1>&2 +fi + +while test $# -gt 0; do + case "$1" in + -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) optarg= ;; + esac + + case $1 in + --prefix=*) + prefix=$optarg + if test $exec_prefix_set = no ; then + exec_prefix=$optarg + fi + ;; + --prefix) + echo_prefix=yes + ;; + --exec-prefix=*) + exec_prefix=$optarg + exec_prefix_set=yes + ;; + --exec-prefix) + echo_exec_prefix=yes + ;; + --version) + echo @DVDREAD_MAJOR@.@DVDREAD_MINOR@.@DVDREAD_SUB@ + ;; + --cflags) + echo_cflags=yes + ;; + --libs) + echo_libs=yes + ;; + *) + usage 1 1>&2 + ;; + esac + shift +done + +if test "$echo_prefix" = "yes"; then + echo $prefix +fi + +if test "$echo_exec_prefix" = "yes"; then + echo $exec_prefix +fi + +if test "$echo_cflags" = "yes"; then + echo -I@includedir@ +fi + +if test "$echo_libs" = "yes"; then + echo -L@libdir@ -ldvdread +fi diff --git a/lib/libdvd/libdvdread/misc/dvdread-config.sh b/lib/libdvd/libdvdread/misc/dvdread-config.sh new file mode 100644 index 0000000000..e170c7ee1b --- /dev/null +++ b/lib/libdvd/libdvdread/misc/dvdread-config.sh @@ -0,0 +1,56 @@ +dvdreadlib="-ldvdread" + +usage() +{ + cat <<EOF +Usage: dvdread-config [OPTIONS] [LIBRARIES] +Options: + [--prefix[=DIR]] + [--version] + [--libs] + [--cflags] +EOF + exit $1 +} + +if test $# -eq 0; then + usage 1 1>&2 +fi + +while test $# -gt 0; do + case "$1" in + -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) optarg= ;; + esac + + case $1 in + --prefix) + echo_prefix=yes + ;; + --version) + echo $version + ;; + --cflags) + echo_cflags=yes + ;; + --libs) + echo_libs=yes + ;; + *) + usage 1 1>&2 + ;; + esac + shift +done + +if test "$echo_prefix" = "yes"; then + echo $prefix +fi + +if test "$echo_cflags" = "yes"; then + echo -I$prefix/include $extracflags +fi + +if test "$echo_libs" = "yes"; then + echo -L$libdir $dvdreadlib +fi diff --git a/lib/libdvd/libdvdread/misc/dvdread.pc.in b/lib/libdvd/libdvdread/misc/dvdread.pc.in new file mode 100644 index 0000000000..917d0e665a --- /dev/null +++ b/lib/libdvd/libdvdread/misc/dvdread.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libdvdread +Description: Low level DVD access library +Version: @VERSION@ + +Cflags: -I${includedir} +Libs: -L${libdir} -ldvdread diff --git a/lib/libdvd/libdvdread/misc/libdvdread.spec.in b/lib/libdvd/libdvdread/misc/libdvdread.spec.in new file mode 100644 index 0000000000..44168576c1 --- /dev/null +++ b/lib/libdvd/libdvdread/misc/libdvdread.spec.in @@ -0,0 +1,50 @@ +%define prefix @prefix@ +%define name @PACKAGE_NAME@ +%define ver @PACKAGE_VERSION@ +%define rel 0 + +Name: %{name} +Summary: Low level DVD access library +Version: %{ver} +Release: %{rel} +Group: Development/Libraries +Copyright: GPL +Url: http://dvd.sourceforge.net/ +Source: %{name}-%{version}.tar.gz +Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root + +%description +libdvdread provides support to applications wishing to make use of basic +DVD reading features. + +%prep +%setup + +%build +CFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=%{prefix} +make + +%install +rm -rf $RPM_BUILD_ROOT +make install-strip DESTDIR=$RPM_BUILD_ROOT + +%clean +rm -r $RPM_BUILD_ROOT + +%files +%defattr(-,root,root) +%doc AUTHORS ChangeLog COPYING INSTALL README +%{prefix}/bin/dvdread-config +%{prefix}/lib/libdvdread*.la +%{prefix}/lib/libdvdread*.so.* +%{prefix}/lib/libdvdread*.so +%{prefix}/include/libdvdread/* +@INSTALL_M4_TRUE@@ACLOCAL_DIR@/dvdread.m4 + +%changelog +* Sun Mar 18 2002 Daniel Caujolle-Bert <f1rmb@users.sourceforge.net> +- Add missing files. Fix rpm generation. +* Tue Mar 12 2002 Rich Wareham <richwareham@users.sourceforge.net> +- Canabalisation to form libdvdnav spec file. +* Sun Sep 09 2001 Thomas Vander Stichele <thomas@apestaart.org> +- first spec file diff --git a/lib/libdvd/libdvdread/misc/relchk.sh.in b/lib/libdvd/libdvdread/misc/relchk.sh.in new file mode 100755 index 0000000000..8251874692 --- /dev/null +++ b/lib/libdvd/libdvdread/misc/relchk.sh.in @@ -0,0 +1,66 @@ +#!/bin/sh +## +## A simple compare directory content utility. +## + +topdir="`pwd`" +distdir="@PACKAGE_NAME@-@PACKAGE_VERSION@" +log="$topdir/dist-log" +logerror="$topdir/dist-errors" + +getdir() { + if test -r .relignore; then + filelist=`ls | grep -Fxvf .relignore` + else + filelist=`ls` + fi + + for file in $filelist; do + + if test -d $file -a $file != "CVS" -a $file != $distdir; then + (cd $file && getdir) || (cd ..) + else + if test ! -d $file -a \ + $file != $log -a \ + $file != $logerror -a \ + $file != "$distdir.tar.gz"; then + + orifile=`pwd`/$file + + distfile=$topdir/$distdir${orifile##*$topdir} + + echo -e "check:\t$orifile\nand\t$distfile" >> $log + + if test ! -e $distfile; then + missingfile=${orifile##$topdir} + echo "${missingfile#/} is missing in tarball" >> $logerror + fi + + fi + fi + + done +} + +main() { + rm -f $log $logerror + + make config.status && make dist && mv $distdir.tar.gz $distdir.tmp.tar.gz && \ + cp config.status config.tmp.status && make clean && make distclean && \ + mv $distdir.tmp.tar.gz $distdir.tar.gz && mv config.tmp.status config.status && \ + tar -xzf $distdir.tar.gz + + echo "Check is running, be patient..." + getdir + + rm -rf $distdir + rm -f $distdir.tar.gz + ./config.status --recheck + ./config.status + + echo " * Log is ${log##*/}" + echo " * Error log is ${logerror##*/}" + +} + +main diff --git a/lib/libdvd/libdvdread/msvc/config.h b/lib/libdvd/libdvdread/msvc/config.h new file mode 100755 index 0000000000..c6c6f94dc3 --- /dev/null +++ b/lib/libdvd/libdvdread/msvc/config.h @@ -0,0 +1,51 @@ +/* config.h. Generated by hand. */ + +#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; diff --git a/lib/libdvd/libdvdread/msvc/contrib/bcopy.c b/lib/libdvd/libdvdread/msvc/contrib/bcopy.c new file mode 100755 index 0000000000..21be364aef --- /dev/null +++ b/lib/libdvd/libdvdread/msvc/contrib/bcopy.c @@ -0,0 +1,8 @@ +#include <string.h> + +void bcopy(const void *IN, void *OUT, size_t N); + +void bcopy(const void *IN, void *OUT, size_t N) +{ + memcpy(OUT, IN, N); +} diff --git a/lib/libdvd/libdvdread/msvc/contrib/dirent/dirent.c b/lib/libdvd/libdvdread/msvc/contrib/dirent/dirent.c new file mode 100755 index 0000000000..00289ed57f --- /dev/null +++ b/lib/libdvd/libdvdread/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 <dirent.h> +#include <errno.h> +#include <io.h> +#include <stdlib.h> +#include <string.h> + +#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 = (DIR *) malloc(sizeof *dir)) != 0 && + (dir->name = (char *) 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/lib/libdvd/libdvdread/msvc/contrib/dirent/dirent.h b/lib/libdvd/libdvdread/msvc/contrib/dirent/dirent.h new file mode 100755 index 0000000000..28a17731ab --- /dev/null +++ b/lib/libdvd/libdvdread/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/lib/libdvd/libdvdread/msvc/contrib/dlfcn.c b/lib/libdvd/libdvdread/msvc/contrib/dlfcn.c new file mode 100755 index 0000000000..3eb996bd13 --- /dev/null +++ b/lib/libdvd/libdvdread/msvc/contrib/dlfcn.c @@ -0,0 +1,97 @@ +/* + * $Id: dlfcn.c 1135 2008-09-06 21:55:51Z rathann $ + * $Name$ + * + * Adopted from Apache DSO code. + * Portions copyright Apache Software Foundation + * + * Structures and types used to implement dlopen, dlsym, etc. + * on Windows 95/NT. + */ +#include <windows.h> +#include <string.h> +#include <stdio.h> + +#include "dlfcn.h" +#include "os_types.h" + +void *dlopen(const char *module_name, int mode) +{ + UINT em; + HINSTANCE dsoh; + char path[MAX_PATH], *p; + /* 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); + 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/lib/libdvd/libdvdread/msvc/contrib/getopt.c b/lib/libdvd/libdvdread/msvc/contrib/getopt.c new file mode 100755 index 0000000000..4b3ce3db40 --- /dev/null +++ b/lib/libdvd/libdvdread/msvc/contrib/getopt.c @@ -0,0 +1,1009 @@ +/* Getopt for GNU. + NOTE: getopt is now part of the C library, so if you don't know what + "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu + before changing it! + + Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97 + Free Software Foundation, Inc. + + This file is part of the GNU C Library. Its master source is NOT part of + the C library, however. The master source lives in /gd/gnu/lib. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>. + Ditto for AIX 3.2 and <stdlib.h>. */ +#ifndef _NO_PROTO +#define _NO_PROTO +#endif + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#if !defined (__STDC__) || !__STDC__ +/* This is a separate conditional since some stdc systems + reject `defined (const)'. */ +#ifndef const +#define const +#endif +#endif + +#include <stdio.h> + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#define GETOPT_INTERFACE_VERSION 2 +#if !defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2 +#include <gnu-versions.h> +#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION +#define ELIDE_CODE +#endif +#endif + +#ifndef ELIDE_CODE + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +/* Don't include stdlib.h for non-GNU C libraries because some of them + contain conflicting prototypes for getopt. */ +#include <stdlib.h> +#include <unistd.h> +#endif /* GNU C library. */ + +#ifdef VMS +#include <unixlib.h> +#if HAVE_STRING_H - 0 +#include <string.h> +#ifdef STRNCASECMP_IN_STRINGS_H +# include <strings.h> +#endif +#endif +#endif + +#if defined (WIN32) && !defined (__CYGWIN32__) || defined(UNDER_CE) +/* It's not Unix, really. See? Capital letters. */ +#include <windows.h> +#define getpid() GetCurrentProcessId() +#endif + +#ifndef _ +/* This is for other GNU distributions with internationalized messages. + When compiling libc, the _ macro is predefined. */ +#ifdef HAVE_LIBINTL_H +#include <libintl.h> +#define _(msgid) gettext (msgid) +#else +#define _(msgid) (msgid) +#endif +#endif + +/* This version of `getopt' appears to the caller like standard Unix `getopt' + but it behaves differently for the user, since it allows the user + to intersperse the options with the other arguments. + + As `getopt' works, it permutes the elements of ARGV so that, + when it is done, all the options precede everything else. Thus + all application programs are extended to handle flexible argument order. + + Setting the environment variable POSIXLY_CORRECT disables permutation. + Then the behavior is completely standard. + + GNU application programs can use a third alternative mode in which + they can distinguish the relative order of options and other arguments. */ + +#include "getopt.h" + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +char *optarg = NULL; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +/* 1003.2 says this must be 1 before any call. */ +int optind = 1; + +/* Formerly, initialization of getopt depended on optind==0, which + causes problems with re-calling getopt as programs generally don't + know that. */ + +int __getopt_initialized = 0; + +/* The next char to be scanned in the option-element + in which the last option character we returned was found. + This allows us to pick up the scan where we left off. + + If this is zero, or a null string, it means resume the scan + by advancing to the next ARGV-element. */ + +static char *nextchar; + +/* Callers store zero here to inhibit the error message + for unrecognized options. */ + +int opterr = 1; + +/* Set to an option character which was unrecognized. + This must be initialized on some systems to avoid linking in the + system's own getopt implementation. */ + +int optopt = '?'; + +/* Describe how to deal with options that follow non-option ARGV-elements. + + If the caller did not specify anything, + the default is REQUIRE_ORDER if the environment variable + POSIXLY_CORRECT is defined, PERMUTE otherwise. + + REQUIRE_ORDER means don't recognize them as options; + stop option processing when the first non-option is seen. + This is what Unix does. + This mode of operation is selected by either setting the environment + variable POSIXLY_CORRECT, or using `+' as the first character + of the list of option characters. + + PERMUTE is the default. We permute the contents of ARGV as we scan, + so that eventually all the non-options are at the end. This allows options + to be given in any order, even with programs that were not written to + expect this. + + RETURN_IN_ORDER is an option available to programs that were written + to expect options and other ARGV-elements in any order and that care about + the ordering of the two. We describe each non-option ARGV-element + as if it were the argument of an option with character code 1. + Using `-' as the first character of the list of option characters + selects this mode of operation. + + The special argument `--' forces an end of option-scanning regardless + of the value of `ordering'. In the case of RETURN_IN_ORDER, only + `--' can cause `getopt' to return -1 with `optind' != ARGC. */ + +static enum +{ + REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER +} +ordering; + +/* Value of POSIXLY_CORRECT environment variable. */ +static char *posixly_correct; + +#ifdef __GNU_LIBRARY__ +/* We want to avoid inclusion of string.h with non-GNU libraries + because there are many ways it can cause trouble. + On some systems, it contains special magic macros that don't work + in GCC. */ +#include <string.h> +#define my_index strchr +#else + +/* Avoid depending on library functions or files + whose names are inconsistent. */ + +char *getenv(); + +static char * + my_index(str, chr) + const char *str; + int chr; +{ + while (*str) + { + if (*str == chr) + return (char *) str; + str++; + } + return 0; +} + +/* If using GCC, we can safely declare strlen this way. + If not using GCC, it is ok not to declare it. */ +#ifdef __GNUC__ +/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. + That was relevant to code that was here before. */ +#if !defined (__STDC__) || !__STDC__ +/* gcc with -traditional declares the built-in strlen to return int, + and has done so at least since version 2.4.5. -- rms. */ +extern int strlen(const char *); + +#endif /* not __STDC__ */ +#endif /* __GNUC__ */ + +#endif /* not __GNU_LIBRARY__ */ + +/* Handle permutation of arguments. */ + +/* Describe the part of ARGV that contains non-options that have + been skipped. `first_nonopt' is the index in ARGV of the first of them; + `last_nonopt' is the index after the last of them. */ + +static int first_nonopt; +static int last_nonopt; + +#ifdef _LIBC +/* Bash 2.0 gives us an environment variable containing flags + indicating ARGV elements that should not be considered arguments. */ + +static const char *nonoption_flags; +static int nonoption_flags_len; + +static int original_argc; +static char *const *original_argv; + +/* Make sure the environment variable bash 2.0 puts in the environment + is valid for the getopt call we must make sure that the ARGV passed + to getopt is that one passed to the process. */ +static void store_args(int argc, char *const *argv) __attribute__((unused)); + static void + store_args(int argc, char *const *argv) +{ + /* XXX This is no good solution. We should rather copy the args so + that we can compare them later. But we must not use malloc(3). */ + original_argc = argc; + original_argv = argv; +} +text_set_element(__libc_subinit, store_args); +#endif + +/* Exchange two adjacent subsequences of ARGV. + One subsequence is elements [first_nonopt,last_nonopt) + which contains all the non-options that have been skipped so far. + The other is elements [last_nonopt,optind), which contains all + the options processed since those non-options were skipped. + + `first_nonopt' and `last_nonopt' are relocated so that they describe + the new indices of the non-options in ARGV after they are moved. */ + +#if defined (__STDC__) && __STDC__ +static void exchange(char **); + +#endif + +static void + exchange(argv) + char **argv; +{ + int bottom = first_nonopt; + int middle = last_nonopt; + int top = optind; + char *tem; + + /* Exchange the shorter segment with the far end of the longer segment. + That puts the shorter segment into the right place. + It leaves the longer segment in the right place overall, + but it consists of two parts that need to be swapped next. */ + + while (top > middle && middle > bottom) + { + if (top - middle > middle - bottom) + { + /* Bottom segment is the short one. */ + int len = middle - bottom; + register int i; + + /* Swap it with the top part of the top segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[top - (middle - bottom) + i]; + argv[top - (middle - bottom) + i] = tem; + } + /* Exclude the moved bottom segment from further swapping. */ + top -= len; + } + else + { + /* Top segment is the short one. */ + int len = top - middle; + register int i; + + /* Swap it with the bottom part of the bottom segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[middle + i]; + argv[middle + i] = tem; + } + /* Exclude the moved top segment from further swapping. */ + bottom += len; + } + } + + /* Update records for the slots the non-options now occupy. */ + + first_nonopt += (optind - last_nonopt); + last_nonopt = optind; +} + +/* Initialize the internal data when the first call is made. */ + +#if defined (__STDC__) && __STDC__ +static const char *_getopt_initialize(int, char *const *, const char *); + +#endif +static const char * + _getopt_initialize(argc, argv, optstring) + int argc; + char *const *argv; + const char *optstring; +{ + /* Start processing options with ARGV-element 1 (since ARGV-element 0 + is the program name); the sequence of previously skipped + non-option ARGV-elements is empty. */ + + first_nonopt = last_nonopt = optind = 1; + + nextchar = NULL; + + posixly_correct = getenv("POSIXLY_CORRECT"); + + /* Determine how to handle the ordering of options and nonoptions. */ + + if (optstring[0] == '-') + { + ordering = RETURN_IN_ORDER; + ++optstring; + } + else if (optstring[0] == '+') + { + ordering = REQUIRE_ORDER; + ++optstring; + } + else if (posixly_correct != NULL) + ordering = REQUIRE_ORDER; + else + ordering = PERMUTE; + +#ifdef _LIBC + if (posixly_correct == NULL + && argc == original_argc && argv == original_argv) + { + /* Bash 2.0 puts a special variable in the environment for each + command it runs, specifying which ARGV elements are the results of + file name wildcard expansion and therefore should not be + considered as options. */ + char var[100]; + + sprintf(var, "_%d_GNU_nonoption_argv_flags_", getpid()); + nonoption_flags = getenv(var); + if (nonoption_flags == NULL) + nonoption_flags_len = 0; + else + nonoption_flags_len = strlen(nonoption_flags); + } + else + nonoption_flags_len = 0; +#endif + + return optstring; +} + +/* Scan elements of ARGV (whose length is ARGC) for option characters + given in OPTSTRING. + + If an element of ARGV starts with '-', and is not exactly "-" or "--", + then it is an option element. The characters of this element + (aside from the initial '-') are option characters. If `getopt' + is called repeatedly, it returns successively each of the option characters + from each of the option elements. + + If `getopt' finds another option character, it returns that character, + updating `optind' and `nextchar' so that the next call to `getopt' can + resume the scan with the following option character or ARGV-element. + + If there are no more option characters, `getopt' returns -1. + Then `optind' is the index in ARGV of the first ARGV-element + that is not an option. (The ARGV-elements have been permuted + so that those that are not options now come last.) + + OPTSTRING is a string containing the legitimate option characters. + If an option character is seen that is not listed in OPTSTRING, + return '?' after printing an error message. If you set `opterr' to + zero, the error message is suppressed but we still return '?'. + + If a char in OPTSTRING is followed by a colon, that means it wants an arg, + so the following text in the same ARGV-element, or the text of the following + ARGV-element, is returned in `optarg'. Two colons mean an option that + wants an optional arg; if there is text in the current ARGV-element, + it is returned in `optarg', otherwise `optarg' is set to zero. + + If OPTSTRING starts with `-' or `+', it requests different methods of + handling the non-option ARGV-elements. + See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. + + Long-named options begin with `--' instead of `-'. + Their names may be abbreviated as long as the abbreviation is unique + or is an exact match for some defined option. If they have an + argument, it follows the option name in the same ARGV-element, separated + from the option name by a `=', or else the in next ARGV-element. + When `getopt' finds a long-named option, it returns 0 if that option's + `flag' field is nonzero, the value of the option's `val' field + if the `flag' field is zero. + + The elements of ARGV aren't really const, because we permute them. + But we pretend they're const in the prototype to be compatible + with other systems. + + LONGOPTS is a vector of `struct option' terminated by an + element containing a name which is zero. + + LONGIND returns the index in LONGOPT of the long-named option found. + It is only valid when a long-named option has been found by the most + recent call. + + If LONG_ONLY is nonzero, '-' as well as '--' can introduce + long-named options. */ + +int + _getopt_internal(argc, argv, optstring, longopts, longind, long_only) + int argc; + char *const *argv; + const char *optstring; + const struct option *longopts; + int *longind; + int long_only; +{ + optarg = NULL; + + if (!__getopt_initialized || optind == 0) + { + optstring = _getopt_initialize(argc, argv, optstring); + optind = 1; /* Don't scan ARGV[0], the program name. */ + __getopt_initialized = 1; + } + + /* Test whether ARGV[optind] points to a non-option argument. + Either it does not have option syntax, or there is an environment flag + from the shell indicating it is not an option. The later information + is only used when the used in the GNU libc. */ +#ifdef _LIBC +#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ + || (optind < nonoption_flags_len \ + && nonoption_flags[optind] == '1')) +#else +#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') +#endif + + if (nextchar == NULL || *nextchar == '\0') + { + /* Advance to the next ARGV-element. */ + + /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been + moved back by the user (who may also have changed the arguments). */ + if (last_nonopt > optind) + last_nonopt = optind; + if (first_nonopt > optind) + first_nonopt = optind; + + if (ordering == PERMUTE) + { + /* If we have just processed some options following some non-options, + exchange them so that the options come first. */ + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange((char **) argv); + else if (last_nonopt != optind) + first_nonopt = optind; + + /* Skip any additional non-options + and extend the range of non-options previously skipped. */ + + while (optind < argc && NONOPTION_P) + optind++; + last_nonopt = optind; + } + + /* The special ARGV-element `--' means premature end of options. + Skip it like a null option, + then exchange with previous non-options as if it were an option, + then skip everything else like a non-option. */ + + if (optind != argc && !strcmp(argv[optind], "--")) + { + optind++; + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange((char **) argv); + else if (first_nonopt == last_nonopt) + first_nonopt = optind; + last_nonopt = argc; + + optind = argc; + } + + /* If we have done all the ARGV-elements, stop the scan + and back over any non-options that we skipped and permuted. */ + + if (optind == argc) + { + /* Set the next-arg-index to point at the non-options + that we previously skipped, so the caller will digest them. */ + if (first_nonopt != last_nonopt) + optind = first_nonopt; + return -1; + } + + /* If we have come to a non-option and did not permute it, + either stop the scan or describe it to the caller and pass it by. */ + + if (NONOPTION_P) + { + if (ordering == REQUIRE_ORDER) + return -1; + optarg = argv[optind++]; + return 1; + } + + /* We have found another option-ARGV-element. + Skip the initial punctuation. */ + + nextchar = (argv[optind] + 1 + + (longopts != NULL && argv[optind][1] == '-')); + } + + /* Decode the current option-ARGV-element. */ + + /* Check whether the ARGV-element is a long option. + + If long_only and the ARGV-element has the form "-f", where f is + a valid short option, don't consider it an abbreviated form of + a long option that starts with f. Otherwise there would be no + way to give the -f short option. + + On the other hand, if there's a long option "fubar" and + the ARGV-element is "-fu", do consider that an abbreviation of + the long option, just like "--fu", and not "-f" with arg "u". + + This distinction seems to be the most useful approach. */ + + if (longopts != NULL + && (argv[optind][1] == '-' + || (long_only && (argv[optind][2] || !my_index(optstring, argv[optind][1]))))) + { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = -1; + int option_index; + + for (nameend = nextchar; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp(p->name, nextchar, nameend - nextchar)) + { + if ((unsigned int) (nameend - nextchar) + == (unsigned int) strlen(p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else + /* Second or later nonexact match found. */ + ambig = 1; + } + + if (ambig && !exact) + { + if (opterr) + fprintf(stderr, _("%s: option `%s' is ambiguous\n"), + argv[0], argv[optind]); + nextchar += strlen(nextchar); + optind++; + optopt = 0; + return '?'; + } + + if (pfound != NULL) + { + option_index = indfound; + optind++; + if (*nameend) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + optarg = nameend + 1; + else + { + if (opterr) + { + if (argv[optind - 1][1] == '-') + /* --option */ + fprintf(stderr, + _("%s: option `--%s' doesn't allow an argument\n"), + argv[0], pfound->name); + else + /* +option or -option */ + fprintf(stderr, + _("%s: option `%c%s' doesn't allow an argument\n"), + argv[0], argv[optind - 1][0], pfound->name); + } + + nextchar += strlen(nextchar); + + optopt = pfound->val; + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (optind < argc) + optarg = argv[optind++]; + else + { + if (opterr) + fprintf(stderr, + _("%s: option `%s' requires an argument\n"), + argv[0], argv[optind - 1]); + nextchar += strlen(nextchar); + optopt = pfound->val; + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen(nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + + /* Can't find it as a long option. If this is not getopt_long_only, + or the option starts with '--' or is not a valid short + option, then it's an error. + Otherwise interpret it as a short option. */ + if (!long_only || argv[optind][1] == '-' + || my_index(optstring, *nextchar) == NULL) + { + if (opterr) + { + if (argv[optind][1] == '-') + /* --option */ + fprintf(stderr, _("%s: unrecognized option `--%s'\n"), + argv[0], nextchar); + else + /* +option or -option */ + fprintf(stderr, _("%s: unrecognized option `%c%s'\n"), + argv[0], argv[optind][0], nextchar); + } + nextchar = (char *) ""; + optind++; + optopt = 0; + return '?'; + } + } + + /* Look at and handle the next short option-character. */ + + { + char c = *nextchar++; + char *temp = my_index(optstring, c); + + /* Increment `optind' when we start to process its last character. */ + if (*nextchar == '\0') + ++optind; + + if (temp == NULL || c == ':') + { + if (opterr) + { + if (posixly_correct) + /* 1003.2 specifies the format of this message. */ + fprintf(stderr, _("%s: illegal option -- %c\n"), + argv[0], c); + else + fprintf(stderr, _("%s: invalid option -- %c\n"), + argv[0], c); + } + optopt = c; + return '?'; + } + /* Convenience. Treat POSIX -W foo same as long option --foo */ + if (temp[0] == 'W' && temp[1] == ';') + { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = 0; + int option_index; + + /* This is an option that requires an argument. */ + if (*nextchar != '\0') + { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } + else if (optind == argc) + { + if (opterr) + { + /* 1003.2 specifies the format of this message. */ + fprintf(stderr, _("%s: option requires an argument -- %c\n"), + argv[0], c); + } + optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + return c; + } + else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + optarg = argv[optind++]; + + /* optarg is now the argument, see if it's in the + table of longopts. */ + + for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp(p->name, nextchar, nameend - nextchar)) + { + if ((unsigned int) (nameend - nextchar) == strlen(p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else + /* Second or later nonexact match found. */ + ambig = 1; + } + if (ambig && !exact) + { + if (opterr) + fprintf(stderr, _("%s: option `-W %s' is ambiguous\n"), + argv[0], argv[optind]); + nextchar += strlen(nextchar); + optind++; + return '?'; + } + if (pfound != NULL) + { + option_index = indfound; + if (*nameend) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + optarg = nameend + 1; + else + { + if (opterr) + fprintf(stderr, _("\ +%s: option `-W %s' doesn't allow an argument\n"), + argv[0], pfound->name); + + nextchar += strlen(nextchar); + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (optind < argc) + optarg = argv[optind++]; + else + { + if (opterr) + fprintf(stderr, + _("%s: option `%s' requires an argument\n"), + argv[0], argv[optind - 1]); + nextchar += strlen(nextchar); + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen(nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + nextchar = NULL; + return 'W'; /* Let the application handle it. */ + } + if (temp[1] == ':') + { + if (temp[2] == ':') + { + /* This is an option that accepts an argument optionally. */ + if (*nextchar != '\0') + { + optarg = nextchar; + optind++; + } + else + optarg = NULL; + nextchar = NULL; + } + else + { + /* This is an option that requires an argument. */ + if (*nextchar != '\0') + { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } + else if (optind == argc) + { + if (opterr) + { + /* 1003.2 specifies the format of this message. */ + fprintf(stderr, + _("%s: option requires an argument -- %c\n"), + argv[0], c); + } + optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + } + else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + optarg = argv[optind++]; + nextchar = NULL; + } + } + return c; + } +} + +int + getopt(argc, argv, optstring) + int argc; + char *const *argv; + const char *optstring; +{ + return _getopt_internal(argc, argv, optstring, + (const struct option *) 0, + (int *) 0, + 0); +} + +#endif /* Not ELIDE_CODE. */ + +#ifdef TEST + +/* Compile with -DTEST to make an executable for use in testing + the above definition of `getopt'. */ + +int + main(argc, argv) + int argc; + char **argv; +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + + c = getopt(argc, argv, "abc:d:0123456789"); + if (c == -1) + break; + + switch (c) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf("option %c\n", c); + break; + + case 'a': + printf("option a\n"); + break; + + case 'b': + printf("option b\n"); + break; + + case 'c': + printf("option c with value `%s'\n", optarg); + break; + + case '?': + break; + + default: + printf("?? getopt returned character code 0%o ??\n", c); + } + } + + if (optind < argc) + { + printf("non-option ARGV-elements: "); + while (optind < argc) + printf("%s ", argv[optind++]); + printf("\n"); + } + + exit(0); +} + +#endif /* TEST */ diff --git a/lib/libdvd/libdvdread/msvc/contrib/timer/timer.c b/lib/libdvd/libdvdread/msvc/contrib/timer/timer.c new file mode 100755 index 0000000000..60efe86db9 --- /dev/null +++ b/lib/libdvd/libdvdread/msvc/contrib/timer/timer.c @@ -0,0 +1,102 @@ +/* + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * WIN32 PORT, + * by Matthew Grooms <elon@altavista.com> + * + * timer.c - Missing unix timer functions + * + */ + +#include "stdio.h" +#include "timer.h" + +/* + this function returns somewhat + accurate unix time with the data + accurate to the first call to get + of day and the resolution accurate + to ~ miliseconds. +*/ + +static time_t startseconds = 0; + +int gettimeofday( struct timeval *tp, struct timezone *tzp ) +{ + MMTIME mmtime; + + // clock() returns time in miliseconds + + if( !startseconds ) + startseconds = time( 0 ); + + timeGetSystemTime( &mmtime, sizeof( mmtime ) ); + + tp->tv_sec = ( mmtime.u.ms / 1000 ) + startseconds; + tp->tv_usec = ( mmtime.u.ms % 1000 ) * 1000; + + return 0; +}; + +/* + These functions are designed to mimick + a subset of itimer for use with the + alarm signal on win32. This is just + enough for xine to work. +*/ + +static HANDLE sigalarm = 0; + +int setitimer( int which, struct itimerval * value, struct itimerval *ovalue ) +{ + long int miliseconds; + + if( !sigalarm ) + sigalarm = CreateEvent( 0, FALSE, TRUE, "SIGALARM" ); + + miliseconds = value->it_value.tv_usec / 1000; + + timeSetEvent( miliseconds, 0, ( LPTIMECALLBACK ) sigalarm, 0, TIME_PERIODIC | TIME_CALLBACK_EVENT_PULSE ); + + return 0; +} + +/* + Wait for sigalarm to wake the thread +*/ + +int pause( void ) +{ + WaitForSingleObject( sigalarm, INFINITE ); + + return 0; +} + +int nanosleep( const struct timespec * rqtp, struct timespec * rmtp ) +{ + Sleep( rqtp->tv_nsec / 1000000 ); + + return 0; +} + +unsigned int sleep( unsigned int seconds ) +{ + Sleep( seconds * 1000 ); + return 0; +}
\ No newline at end of file diff --git a/lib/libdvd/libdvdread/msvc/contrib/timer/timer.h b/lib/libdvd/libdvdread/msvc/contrib/timer/timer.h new file mode 100755 index 0000000000..efab6f4e18 --- /dev/null +++ b/lib/libdvd/libdvdread/msvc/contrib/timer/timer.h @@ -0,0 +1,39 @@ +#include <time.h> +#include <winsock.h> +#include "pthread.h" + +#ifndef _ITIMER_ +#define _ITIMER_ + +#define ITIMER_REAL 0 +#define ITIMER_VIRTUAL 1 + +// time reference +// ---------------------------------- +// +// 1,000 milliseconds / sec +// 1,000,000 microseconds / sec +// 1,000,000,000 nanoseconds / sec +// +// timeval.time_sec = seconds +// timeval.time_usec = microseconds + +struct itimerval +{ + struct timeval it_interval; /* timer interval */ + struct timeval it_value; /* current value */ +}; + +struct timezone { + int tz_minuteswest; /* minutes west of Greenwich */ + int tz_dsttime; /* type of dst correction */ +}; + +int gettimeofday( struct timeval *tp, struct timezone *tzp ); +int setitimer( int which, struct itimerval * value, struct itimerval *ovalue ); +int pause( void ); + +unsigned int sleep( unsigned int seconds ); +int nanosleep( const struct timespec *rqtp, struct timespec *rmtp ); + +#endif
\ No newline at end of file diff --git a/lib/libdvd/libdvdread/msvc/ifo_dump.dsp b/lib/libdvd/libdvdread/msvc/ifo_dump.dsp new file mode 100755 index 0000000000..fc39837296 --- /dev/null +++ b/lib/libdvd/libdvdread/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 "include/pthreads" /I "install/include" /I ".." /I "../src" /I "contrib/timer" /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/lib/libdvd/libdvdread/msvc/include/dlfcn.h b/lib/libdvd/libdvdread/msvc/include/dlfcn.h new file mode 100755 index 0000000000..7a2416c843 --- /dev/null +++ b/lib/libdvd/libdvdread/msvc/include/dlfcn.h @@ -0,0 +1,23 @@ +#ifndef __DLFCN_H__ +# define __DLFCN_H__ +/* + * $Id: dlfcn.h 1135 2008-09-06 21:55:51Z rathann $ + * $Name$ + * + * + */ +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/lib/libdvd/libdvdread/msvc/include/dvdnav_internal.h b/lib/libdvd/libdvdread/msvc/include/dvdnav_internal.h new file mode 100644 index 0000000000..cee785472e --- /dev/null +++ b/lib/libdvd/libdvdread/msvc/include/dvdnav_internal.h @@ -0,0 +1,185 @@ +/* !! DO NO EDIT THIS FILE, it is automatically generated */ +/* + * Copyright (C) 2001 Rich Wareham <richwareham@users.sourceforge.net> + * + * This file is part of libdvdnav, a DVD navigation library. + * + * libdvdnav 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. + * + * libdvdnav 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 + * + * $Id: dvdnav_internal.h 1135 2008-09-06 21:55:51Z rathann $ + * + */ + +#ifndef DVDNAV_INTERNAL_H_INCLUDED +#define DVDNAV_INTERNAL_H_INCLUDED + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <limits.h> +#include <string.h> +#include <pthread.h> + +#undef WORDS_BIGENDIAN + +#include "dvd_reader.h" +#include "ifo_read.h" +#include "ifo_types.h" + +/* Uncomment for VM command tracing */ +/* #define TRACE */ + +#include "decoder.h" +#include "dvdnav.h" +#include "vm.h" +#include "vmcmd.h" + +/* where should libdvdnav write its messages (stdout/stderr) */ +#define MSG_OUT stdout + +/* Maximum length of an error string */ +#define MAX_ERR_LEN 255 + +/* Use the POSIX PATH_MAX if available */ +#ifdef PATH_MAX +#define MAX_PATH_LEN PATH_MAX +#else +#define MAX_PATH_LEN 255 /* Arbitrary */ +#endif + +#ifndef DVD_VIDEO_LB_LEN +#define DVD_VIDEO_LB_LEN 2048 +#endif + +typedef struct read_cache_s read_cache_t; + +/* + * These are defined here because they are + * not in ifo_types.h, they maybe one day + */ + +#ifndef audio_status_t +typedef struct { +#ifdef WORDS_BIGENDIAN + unsigned int available : 1; + unsigned int zero1 : 4; + unsigned int stream_number : 3; + uint8_t zero2; +#else + uint8_t zero2; + unsigned int stream_number : 3; + unsigned int zero1 : 4; + unsigned int available : 1; +#endif +} ATTRIBUTE_PACKED audio_status_t; +#endif + +#ifndef spu_status_t +typedef struct { +#ifdef WORDS_BIGENDIAN + unsigned int available : 1; + unsigned int zero1 : 2; + unsigned int stream_number_4_3 : 5; + unsigned int zero2 : 3; + unsigned int stream_number_wide : 5; + unsigned int zero3 : 3; + unsigned int stream_number_letterbox : 5; + unsigned int zero4 : 3; + unsigned int stream_number_pan_scan : 5; +#else + unsigned int stream_number_pan_scan : 5; + unsigned int zero4 : 3; + unsigned int stream_number_letterbox : 5; + unsigned int zero3 : 3; + unsigned int stream_number_wide : 5; + unsigned int zero2 : 3; + unsigned int stream_number_4_3 : 5; + unsigned int zero1 : 2; + unsigned int available : 1; +#endif +} ATTRIBUTE_PACKED spu_status_t; +#endif + +typedef struct dvdnav_vobu_s { + int32_t vobu_start; /* Logical Absolute. MAX needed is 0x300000 */ + int32_t vobu_length; + int32_t blockN; /* Relative offset */ + int32_t vobu_next; /* Relative offset */ +} dvdnav_vobu_t; + +/** The main DVDNAV type **/ + +struct dvdnav_s { + /* General data */ + char path[MAX_PATH_LEN]; /* Path to DVD device/dir */ + dvd_file_t *file; /* Currently opened file */ + int open_vtsN; /* The domain and number of the... */ + int open_domain; /* ..currently opened VOB */ + + /* Position data */ + vm_position_t position_next; + vm_position_t position_current; + dvdnav_vobu_t vobu; + + /* NAV data */ + pci_t pci; + dsi_t dsi; + uint32_t last_cmd_nav_lbn; /* detects when a command is issued on an already left NAV */ + + /* Flags */ + int skip_still; /* Set when skipping a still */ + int sync_wait; /* applications should wait till they are in sync with us */ + int sync_wait_skip; /* Set when skipping wait state */ + int spu_clut_changed; /* The SPU CLUT changed */ + int started; /* vm_start has been called? */ + int use_read_ahead; /* 1 - use read-ahead cache, 0 - don't */ + int pgc_based; /* positioning works PGC based instead of PG based */ + + /* VM */ + vm_t *vm; + pthread_mutex_t vm_lock; + + /* Read-ahead cache */ + read_cache_t *cache; + + /* Errors */ + char err_str[MAX_ERR_LEN]; +}; + +/** USEFUL MACROS **/ + +#ifdef __GNUC__ +#define printerrf(format, args...) snprintf(this->err_str, MAX_ERR_LEN, format, ## args); +#else +#ifdef _MSC_VER +#define printerrf(str) snprintf(this->err_str, MAX_ERR_LEN, str); +#else +#define printerrf(...) snprintf(this->err_str, MAX_ERR_LEN, __VA_ARGS__); +#endif /* WIN32 */ +#endif +#define printerr(str) strncpy(this->err_str, str, MAX_ERR_LEN); + +/* Save my typing */ +#define S_ERR DVDNAV_STATUS_ERR + +#ifndef _MSC_VER +#define S_OK DVDNAV_STATUS_OK +#endif /* MSC_VER */ + +#endif /* DVDNAV_INTERNAL_H_INCLUDED */ diff --git a/lib/libdvd/libdvdread/msvc/include/getopt.h b/lib/libdvd/libdvdread/msvc/include/getopt.h new file mode 100755 index 0000000000..2fa12f7baf --- /dev/null +++ b/lib/libdvd/libdvdread/msvc/include/getopt.h @@ -0,0 +1,134 @@ +/* Declarations for getopt. + Copyright (C) 1989,90,91,92,93,94,96,97 Free Software Foundation, Inc. + + This file is part of the GNU C Library. Its master source is NOT part of + the C library, however. The master source lives in /gd/gnu/lib. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _GETOPT_H +#define _GETOPT_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + + extern char *optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + + extern int optind; + +/* Callers store zero here to inhibit the error message `getopt' prints + for unrecognized options. */ + + extern int opterr; + +/* Set to an option character which was unrecognized. */ + + extern int optopt; + +/* Describe the long-named options requested by the application. + The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector + of `struct option' terminated by an element containing a name which is + zero. + + The field `has_arg' is: + no_argument (or 0) if the option does not take an argument, + required_argument (or 1) if the option requires an argument, + optional_argument (or 2) if the option takes an optional argument. + + If the field `flag' is not NULL, it points to a variable that is set + to the value given in the field `val' when the option is found, but + left unchanged if the option is not found. + + To have a long-named option do something other than set an `int' to + a compiled-in constant, such as set a value from `optarg', set the + option's `flag' field to zero and its `val' field to a nonzero + value (the equivalent single-letter option character, if there is + one). For long options that have a zero `flag' field, `getopt' + returns the contents of the `val' field. */ + + struct option + { +#if defined (__STDC__) && __STDC__ + const char *name; +#else + char *name; +#endif + /* has_arg can't be an enum because some compilers complain about + type mismatches in all the code that assumes it is an int. */ + int has_arg; + int *flag; + int val; + }; + +/* Names for the values of the `has_arg' field of `struct option'. */ + +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +#if defined (__STDC__) && __STDC__ +#ifdef __GNU_LIBRARY__ +/* Many other libraries have conflicting prototypes for getopt, with + differences in the consts, in stdlib.h. To avoid compilation + errors, only prototype getopt for the GNU C library. */ + extern int getopt(int argc, char *const *argv, const char *shortopts); +#else /* not __GNU_LIBRARY__ */ + extern int getopt(); +#endif /* __GNU_LIBRARY__ */ + extern int getopt_long(int argc, char *const *argv, const char *shortopts, + const struct option *longopts, int *longind); + extern int getopt_long_only(int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind); + +/* Internal only. Users should not call this directly. */ + extern int _getopt_internal(int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind, + int long_only); +#else /* not __STDC__ */ + extern int getopt(); + extern int getopt_long(); + extern int getopt_long_only(); + + extern int _getopt_internal(); +#endif /* __STDC__ */ + +#ifdef __cplusplus +} +#endif + +#endif /* _GETOPT_H */ diff --git a/lib/libdvd/libdvdread/msvc/include/inttypes.h b/lib/libdvd/libdvdread/msvc/include/inttypes.h new file mode 100755 index 0000000000..55fd6a33e0 --- /dev/null +++ b/lib/libdvd/libdvdread/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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * WIN32 PORT, + * by Matthew Grooms <elon@altavista.com> + * + * inttypes.h - Standard integer definitions. + * + */ + +#ifndef _SYS_INTTYPES_H_ +#define _SYS_INTTYPES_H_ + +#include <config.h> + +#endif diff --git a/lib/libdvd/libdvdread/msvc/include/os_types.h b/lib/libdvd/libdvdread/msvc/include/os_types.h new file mode 100755 index 0000000000..69f05a8d93 --- /dev/null +++ b/lib/libdvd/libdvdread/msvc/include/os_types.h @@ -0,0 +1,27 @@ +#ifndef __OS_TYPES_H__ +#define __OS_TYPES_H__ +/* + * $Id: os_types.h 1135 2008-09-06 21:55:51Z rathann $ + * $Name$ + * + * 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/lib/libdvd/libdvdread/msvc/include/pthreads/pthread.h b/lib/libdvd/libdvdread/msvc/include/pthreads/pthread.h new file mode 100755 index 0000000000..7b89ca8401 --- /dev/null +++ b/lib/libdvd/libdvdread/msvc/include/pthreads/pthread.h @@ -0,0 +1,1077 @@ +/* This is the POSIX thread API (POSIX 1003). + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright (C) 1998 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA + */ + +#if !defined( PTHREAD_H ) +#define PTHREAD_H + +#ifdef _UWIN +# define HAVE_STRUCT_TIMESPEC 1 +# define HAVE_SIGNAL_H 1 +# undef HAVE_CONFIG_H +# pragma comment(lib, "pthread") +#endif + +/* + * ------------------------------------------------------------- + * + * + * Module: pthread.h + * + * Purpose: + * Provides an implementation of PThreads based upon the + * standard: + * + * POSIX 1003.1c-1995 (POSIX.1c) + * + * Parts of the implementation also comply with the + * Open Group Unix 98 specification in order to enhance + * code portability between Windows, various commercial + * Unix implementations, and Linux. + * + * Authors: + * There have been many contributors to this library. + * The initial implementation was contributed by + * John Bossom, and several others have provided major + * sections or revisions of parts of the implementation. + * Often significant effort has been contributed to + * find and fix important bugs and other problems to + * improve the reliability of the library, which sometimes + * is not reflected in the amount of code which changed as + * result. + * As much as possible, the contributors are acknowledged + * in the ChangeLog file in the source code distribution + * where their changes are noted in detail. + * + * Contributors are listed in the MAINTAINERS file. + * + * As usual, all bouquets go to the contributors, and all + * brickbats go to the project maintainer. + * + * Maintainer: + * The code base for this project is coordinated and + * eventually pre-tested, packaged, and made available by + * + * Ross Johnson <rpj@ise.canberra.edu.au> + * + * QA Testers: + * Ultimately, the library is tested in the real world by + * a host of competent and demanding scientists and + * engineers who report bugs and/or provide solutions + * which are then fixed or incorporated into subsequent + * versions of the library. Each time a bug is fixed, a + * test case is written to prove the fix and ensure + * that later changes to the code don't reintroduce the + * same error. The number of test cases is slowly growing + * and therefore so is the code reliability. + * + * Compliance: + * See the file ANNOUNCE for the list of implemented + * and not-implemented routines and defined options. + * Of course, these are all defined is this file as well. + * + * Web site: + * The source code and other information about this library + * are available from + * + * http://sources.redhat.com/pthreads-win32/ + * + * ------------------------------------------------------------- + */ + +/* + * ----------------- + * autoconf switches + * ----------------- + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include <windows.h> + +#ifndef NEED_FTIME +#include <time.h> +#else /* NEED_FTIME */ +/* use native WIN32 time API */ +#endif /* NEED_FTIME */ + +#if HAVE_SIGNAL_H +#include <signal.h> +#endif /* HAVE_SIGNAL_H */ + +#include <setjmp.h> + +#ifndef HAVE_STRUCT_TIMESPEC +struct timespec { + long tv_sec; + long tv_nsec; +}; +#endif /* HAVE_STRUCT_TIMESPEC */ + +#ifndef SIG_BLOCK +#define SIG_BLOCK 0 +#endif /* SIG_BLOCK */ + +#ifndef SIG_UNBLOCK +#define SIG_UNBLOCK 1 +#endif /* SIG_UNBLOCK */ + +#ifndef SIG_SETMASK +#define SIG_SETMASK 2 +#endif /* SIG_SETMASK */ + +/* + * note: ETIMEDOUT is correctly defined in winsock.h + */ +#include <winsock.h> + +#ifdef NEED_ERRNO +# include "need_errno.h" +#else +# include <errno.h> +#endif + +#include <sched.h> + +/* + * In case ETIMEDOUT hasn't been defined above somehow. + */ +#ifndef ETIMEDOUT +# define ETIMEDOUT 10060 /* This is the value in winsock.h. */ +#endif + +/* + * Several systems don't define ENOTSUP. If not, we use + * the same value as Solaris. + */ +#ifndef ENOTSUP +# define ENOTSUP 48 +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* + * ------------------------------------------------------------- + * + * POSIX 1003.1c-1995 Options + * =========================== + * + * _POSIX_THREADS (set) + * If set, you can use threads + * + * _POSIX_THREAD_ATTR_STACKSIZE (set) + * If set, you can control the size of a thread's + * stack + * pthread_attr_getstacksize + * pthread_attr_setstacksize + * + * _POSIX_THREAD_ATTR_STACKADDR (not set) + * If set, you can allocate and control a thread's + * stack. If not supported, the following functions + * will return ENOSYS, indicating they are not + * supported: + * pthread_attr_getstackaddr + * pthread_attr_setstackaddr + * + * _POSIX_THREAD_PRIORITY_SCHEDULING (set) + * If set, you can use realtime scheduling. + * Indicates the availability of: + * pthread_attr_getinheritsched + * pthread_attr_getschedparam + * pthread_attr_getschedpolicy + * pthread_attr_getscope + * pthread_attr_setinheritsched + * pthread_attr_setschedparam + * pthread_attr_setschedpolicy + * pthread_attr_setscope + * pthread_getschedparam + * pthread_setschedparam + * sched_get_priority_max + * sched_get_priority_min + * sched_rr_set_interval + * + * _POSIX_THREAD_PRIO_INHERIT (not set) + * If set, you can create priority inheritance + * mutexes. + * pthread_mutexattr_getprotocol + + * pthread_mutexattr_setprotocol + + * + * _POSIX_THREAD_PRIO_PROTECT (not set) + * If set, you can create priority ceiling mutexes + * Indicates the availability of: + * pthread_mutex_getprioceiling + * pthread_mutex_setprioceiling + * pthread_mutexattr_getprioceiling + * pthread_mutexattr_getprotocol + + * pthread_mutexattr_setprioceiling + * pthread_mutexattr_setprotocol + + * + * _POSIX_THREAD_PROCESS_SHARED (not set) + * If set, you can create mutexes and condition + * variables that can be shared with another + * process.If set, indicates the availability + * of: + * pthread_mutexattr_getpshared + * pthread_mutexattr_setpshared + * pthread_condattr_getpshared + * pthread_condattr_setpshared + * + * _POSIX_THREAD_SAFE_FUNCTIONS (set) + * If set you can use the special *_r library + * functions that provide thread-safe behaviour + * + * + These functions provide both 'inherit' and/or + * 'protect' protocol, based upon these macro + * settings. + * + * POSIX 1003.1c-1995 Limits + * =========================== + * + * PTHREAD_DESTRUCTOR_ITERATIONS + * Maximum number of attempts to destroy + * a thread's thread-specific data on + * termination (must be at least 4) + * + * PTHREAD_KEYS_MAX + * Maximum number of thread-specific data keys + * available per process (must be at least 128) + * + * PTHREAD_STACK_MIN + * Minimum supported stack size for a thread + * + * PTHREAD_THREADS_MAX + * Maximum number of threads supported per + * process (must be at least 64). + * + * + * POSIX 1003.1j/D10-1999 Options + * ============================== + * + * _POSIX_READER_WRITER_LOCKS (set) + * If set, you can use read/write locks + * + * _POSIX_SPIN_LOCKS (set) + * If set, you can use spin locks + * + * _POSIX_BARRIERS (set) + * If set, you can use barriers + * + * ------------------------------------------------------------- + */ + +/* + * POSIX Options + */ +#ifndef _POSIX_THREADS +#define _POSIX_THREADS +#endif + +#ifndef _POSIX_READER_WRITER_LOCKS +#define _POSIX_READER_WRITER_LOCKS +#endif + +#ifndef _POSIX_SPIN_LOCKS +#define _POSIX_SPIN_LOCKS +#endif + +#ifndef _POSIX_BARRIERS +#define _POSIX_BARRIERS +#endif + +#define _POSIX_THREAD_SAFE_FUNCTIONS +#define _POSIX_THREAD_ATTR_STACKSIZE +#define _POSIX_THREAD_PRIORITY_SCHEDULING + +#if defined( KLUDGE ) +/* + * The following are not supported + */ +#define _POSIX_THREAD_ATTR_STACKADDR +#define _POSIX_THREAD_PRIO_INHERIT +#define _POSIX_THREAD_PRIO_PROTECT +#define _POSIX_THREAD_PROCESS_SHARED + +#endif /* KLUDGE */ + +/* + * POSIX Limits + * + * PTHREAD_DESTRUCTOR_ITERATIONS + * Standard states this must be at least + * 4. + * + * PTHREAD_KEYS_MAX + * WIN32 permits only 64 TLS keys per process. + * This limitation could be worked around by + * simply simulating keys. + * + * PTHREADS_STACK_MIN + * POSIX specifies 0 which is also the value WIN32 + * interprets as allowing the system to + * set the size to that of the main thread. The + * maximum stack size in Win32 is 1Meg. WIN32 + * allocates more stack as required up to the 1Meg + * limit. + * + * PTHREAD_THREADS_MAX + * Not documented by WIN32. Wrote a test program + * that kept creating threads until it failed + * revealed this approximate number. + * + */ +#define PTHREAD_DESTRUCTOR_ITERATIONS 4 +#define PTHREAD_KEYS_MAX 64 +#define PTHREAD_STACK_MIN 0 +#define PTHREAD_THREADS_MAX 2019 + + +#ifdef _UWIN +# include <sys/types.h> +#else +typedef struct pthread_t_ *pthread_t; +typedef struct pthread_attr_t_ *pthread_attr_t; +typedef struct pthread_once_t_ pthread_once_t; +typedef struct pthread_key_t_ *pthread_key_t; +typedef struct pthread_mutex_t_ *pthread_mutex_t; +typedef struct pthread_mutexattr_t_ *pthread_mutexattr_t; +typedef struct pthread_cond_t_ *pthread_cond_t; +typedef struct pthread_condattr_t_ *pthread_condattr_t; +#endif +typedef struct pthread_rwlock_t_ *pthread_rwlock_t; +typedef struct pthread_rwlockattr_t_ *pthread_rwlockattr_t; +typedef struct pthread_spinlock_t_ *pthread_spinlock_t; +typedef struct pthread_barrier_t_ *pthread_barrier_t; +typedef struct pthread_barrierattr_t_ *pthread_barrierattr_t; + +/* + * ==================== + * ==================== + * POSIX Threads + * ==================== + * ==================== + */ + +enum { +/* + * pthread_attr_{get,set}detachstate + */ + PTHREAD_CREATE_JOINABLE = 0, /* Default */ + PTHREAD_CREATE_DETACHED = 1, + +/* + * pthread_attr_{get,set}inheritsched + */ + PTHREAD_INHERIT_SCHED = 0, + PTHREAD_EXPLICIT_SCHED = 1, /* Default */ + +/* + * pthread_{get,set}scope + */ + PTHREAD_SCOPE_PROCESS = 0, + PTHREAD_SCOPE_SYSTEM = 1, /* Default */ + +/* + * pthread_setcancelstate paramters + */ + PTHREAD_CANCEL_ENABLE = 0, /* Default */ + PTHREAD_CANCEL_DISABLE = 1, + +/* + * pthread_setcanceltype parameters + */ + PTHREAD_CANCEL_ASYNCHRONOUS = 0, + PTHREAD_CANCEL_DEFERRED = 1, /* Default */ + +/* + * pthread_mutexattr_{get,set}pshared + * pthread_condattr_{get,set}pshared + */ + PTHREAD_PROCESS_PRIVATE = 0, + PTHREAD_PROCESS_SHARED = 1, + +/* + * pthread_barrier_wait + */ + PTHREAD_BARRIER_SERIAL_THREAD = -1 +}; + +/* + * ==================== + * ==================== + * Cancelation + * ==================== + * ==================== + */ +#define PTHREAD_CANCELED ((void *) -1) + + +/* + * ==================== + * ==================== + * Once Key + * ==================== + * ==================== + */ +#define PTHREAD_ONCE_INIT { FALSE, -1 } + +struct pthread_once_t_ +{ + int done; /* indicates if user function executed */ + long started; /* First thread to increment this value */ + /* to zero executes the user function */ +}; + + +/* + * ==================== + * ==================== + * Object initialisers + * ==================== + * ==================== + */ +#define PTHREAD_MUTEX_INITIALIZER ((pthread_mutex_t) -1) + +#define PTHREAD_COND_INITIALIZER ((pthread_cond_t) -1) + +#define PTHREAD_RWLOCK_INITIALIZER ((pthread_rwlock_t) -1) + +#define PTHREAD_SPINLOCK_INITIALIZER ((pthread_spinlock_t) -1) + +enum +{ + PTHREAD_MUTEX_FAST_NP, + PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_FAST_NP, + PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL +}; + + +/* There are three implementations of cancel cleanup. + * Note that pthread.h is included in both application + * compilation units and also internally for the library. + * The code here and within the library aims to work + * for all reasonable combinations of environments. + * + * The three implementations are: + * + * WIN32 SEH + * C + * C++ + * + * Please note that exiting a push/pop block via + * "return", "exit", "break", or "continue" will + * lead to different behaviour amongst applications + * depending upon whether the library was built + * using SEH, C++, or C. For example, a library built + * with SEH will call the cleanup routine, while both + * C++ and C built versions will not. + */ + +/* + * define defaults for cleanup code + */ +#if !defined( __CLEANUP_SEH ) && !defined( __CLEANUP_CXX ) && !defined( __CLEANUP_C ) + +#if defined(_MSC_VER) +#define __CLEANUP_SEH +#elif defined(__cplusplus) +#define __CLEANUP_CXX +#else +#define __CLEANUP_C +#endif + +#endif + +#if defined( __CLEANUP_SEH ) && defined(__GNUC__) +#error ERROR [__FILE__, line __LINE__]: GNUC does not support SEH. +#endif + +typedef struct ptw32_cleanup_t ptw32_cleanup_t; +typedef void (__cdecl *ptw32_cleanup_callback_t)(void *); + +struct ptw32_cleanup_t +{ + ptw32_cleanup_callback_t routine; + void *arg; + struct ptw32_cleanup_t *prev; +}; + +#ifdef __CLEANUP_SEH + /* + * WIN32 SEH version of cancel cleanup. + */ + +#define pthread_cleanup_push( _rout, _arg ) \ + { \ + ptw32_cleanup_t _cleanup; \ + \ + _cleanup.routine = (ptw32_cleanup_callback_t)(_rout); \ + _cleanup.arg = (_arg); \ + __try \ + { \ + +#define pthread_cleanup_pop( _execute ) \ + } \ + __finally \ + { \ + if( _execute || AbnormalTermination()) \ + { \ + (*(_cleanup.routine))( _cleanup.arg ); \ + } \ + } \ + } + +#else /* __CLEANUP_SEH */ + +#ifdef __CLEANUP_C + + /* + * C implementation of PThreads cancel cleanup + */ + +#define pthread_cleanup_push( _rout, _arg ) \ + { \ + ptw32_cleanup_t _cleanup; \ + \ + ptw32_push_cleanup( &_cleanup, (ptw32_cleanup_callback_t) (_rout), (_arg) ); \ + +#define pthread_cleanup_pop( _execute ) \ + (void) ptw32_pop_cleanup( _execute ); \ + } + +#else /* __CLEANUP_C */ + +#ifdef __CLEANUP_CXX + + /* + * C++ version of cancel cleanup. + * - John E. Bossom. + */ + + class PThreadCleanup { + /* + * PThreadCleanup + * + * Purpose + * This class is a C++ helper class that is + * used to implement pthread_cleanup_push/ + * pthread_cleanup_pop. + * The destructor of this class automatically + * pops the pushed cleanup routine regardless + * of how the code exits the scope + * (i.e. such as by an exception) + */ + ptw32_cleanup_callback_t cleanUpRout; + void * obj; + int executeIt; + + public: + PThreadCleanup() : + cleanUpRout( NULL ), + obj( NULL ), + executeIt( 0 ) + /* + * No cleanup performed + */ + { + } + + PThreadCleanup( + ptw32_cleanup_callback_t routine, + void * arg ) : + cleanUpRout( routine ), + obj( arg ), + executeIt( 1 ) + /* + * Registers a cleanup routine for 'arg' + */ + { + } + + ~PThreadCleanup() + { + if ( executeIt && ((void *) cleanUpRout != NULL) ) + { + (void) (*cleanUpRout)( obj ); + } + } + + void execute( int exec ) + { + executeIt = exec; + } + }; + + /* + * C++ implementation of PThreads cancel cleanup; + * This implementation takes advantage of a helper + * class who's destructor automatically calls the + * cleanup routine if we exit our scope weirdly + */ +#define pthread_cleanup_push( _rout, _arg ) \ + { \ + PThreadCleanup cleanup((ptw32_cleanup_callback_t)(_rout), \ + (void *) (_arg) ); + +#define pthread_cleanup_pop( _execute ) \ + cleanup.execute( _execute ); \ + } + +#else + +#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined. + +#endif /* __CLEANUP_CXX */ + +#endif /* __CLEANUP_C */ + +#endif /* __CLEANUP_SEH */ + +/* + * =============== + * =============== + * Methods + * =============== + * =============== + */ + +/* + * PThread Attribute Functions + */ +int pthread_attr_init (pthread_attr_t * attr); + +int pthread_attr_destroy (pthread_attr_t * attr); + +int pthread_attr_getdetachstate (const pthread_attr_t * attr, + int *detachstate); + +int pthread_attr_getstackaddr (const pthread_attr_t * attr, + void **stackaddr); + +int pthread_attr_getstacksize (const pthread_attr_t * attr, + size_t * stacksize); + +int pthread_attr_setdetachstate (pthread_attr_t * attr, + int detachstate); + +int pthread_attr_setstackaddr (pthread_attr_t * attr, + void *stackaddr); + +int pthread_attr_setstacksize (pthread_attr_t * attr, + size_t stacksize); + +int pthread_attr_getschedparam (const pthread_attr_t *attr, + struct sched_param *param); + +int pthread_attr_setschedparam (pthread_attr_t *attr, + const struct sched_param *param); + +int pthread_attr_setschedpolicy (pthread_attr_t *, + int); + +int pthread_attr_getschedpolicy (pthread_attr_t *, + int *); + +int pthread_attr_setinheritsched(pthread_attr_t * attr, + int inheritsched); + +int pthread_attr_getinheritsched(pthread_attr_t * attr, + int * inheritsched); + +int pthread_attr_setscope (pthread_attr_t *, + int); + +int pthread_attr_getscope (const pthread_attr_t *, + int *); + +/* + * PThread Functions + */ +int pthread_create (pthread_t * tid, + const pthread_attr_t * attr, + void *(*start) (void *), + void *arg); + +int pthread_detach (pthread_t tid); + +int pthread_equal (pthread_t t1, + pthread_t t2); + +void pthread_exit (void *value_ptr); + +int pthread_join (pthread_t thread, + void **value_ptr); + +pthread_t pthread_self (void); + +int pthread_cancel (pthread_t thread); + +int pthread_setcancelstate (int state, + int *oldstate); + +int pthread_setcanceltype (int type, + int *oldtype); + +void pthread_testcancel (void); + +int pthread_once (pthread_once_t * once_control, + void (*init_routine) (void)); + +ptw32_cleanup_t *ptw32_pop_cleanup (int execute); + +void ptw32_push_cleanup (ptw32_cleanup_t * cleanup, + void (*routine) (void *), + void *arg); + +/* + * Thread Specific Data Functions + */ +int pthread_key_create (pthread_key_t * key, + void (*destructor) (void *)); + +int pthread_key_delete (pthread_key_t key); + +int pthread_setspecific (pthread_key_t key, + const void *value); + +void *pthread_getspecific (pthread_key_t key); + + +/* + * Mutex Attribute Functions + */ +int pthread_mutexattr_init (pthread_mutexattr_t * attr); + +int pthread_mutexattr_destroy (pthread_mutexattr_t * attr); + +int pthread_mutexattr_getpshared (const pthread_mutexattr_t + * attr, + int *pshared); + +int pthread_mutexattr_setpshared (pthread_mutexattr_t * attr, + int pshared); + +int pthread_mutexattr_settype (pthread_mutexattr_t * attr, int kind); +int pthread_mutexattr_gettype (pthread_mutexattr_t * attr, int *kind); + +/* + * Barrier Attribute Functions + */ +int pthread_barrierattr_init (pthread_barrierattr_t * attr); + +int pthread_barrierattr_destroy (pthread_barrierattr_t * attr); + +int pthread_barrierattr_getpshared (const pthread_barrierattr_t + * attr, + int *pshared); + +int pthread_barrierattr_setpshared (pthread_barrierattr_t * attr, + int pshared); + +/* + * Mutex Functions + */ +int pthread_mutex_init (pthread_mutex_t * mutex, + const pthread_mutexattr_t * attr); + +int pthread_mutex_destroy (pthread_mutex_t * mutex); + +int pthread_mutex_lock (pthread_mutex_t * mutex); + +int pthread_mutex_trylock (pthread_mutex_t * mutex); + +int pthread_mutex_unlock (pthread_mutex_t * mutex); + +/* + * Spinlock Functions + */ +int pthread_spin_init (pthread_spinlock_t * lock, int pshared); + +int pthread_spin_destroy (pthread_spinlock_t * lock); + +int pthread_spin_lock (pthread_spinlock_t * lock); + +int pthread_spin_trylock (pthread_spinlock_t * lock); + +int pthread_spin_unlock (pthread_spinlock_t * lock); + +/* + * Barrier Functions + */ +int pthread_barrier_init (pthread_barrier_t * barrier, + const pthread_barrierattr_t * attr, + unsigned int count); + +int pthread_barrier_destroy (pthread_barrier_t * barrier); + +int pthread_barrier_wait (pthread_barrier_t * barrier); + +/* + * Condition Variable Attribute Functions + */ +int pthread_condattr_init (pthread_condattr_t * attr); + +int pthread_condattr_destroy (pthread_condattr_t * attr); + +int pthread_condattr_getpshared (const pthread_condattr_t * attr, + int *pshared); + +int pthread_condattr_setpshared (pthread_condattr_t * attr, + int pshared); + +/* + * Condition Variable Functions + */ +int pthread_cond_init (pthread_cond_t * cond, + const pthread_condattr_t * attr); + +int pthread_cond_destroy (pthread_cond_t * cond); + +int pthread_cond_wait (pthread_cond_t * cond, + pthread_mutex_t * mutex); + +int pthread_cond_timedwait (pthread_cond_t * cond, + pthread_mutex_t * mutex, + const struct timespec *abstime); + +int pthread_cond_signal (pthread_cond_t * cond); + +int pthread_cond_broadcast (pthread_cond_t * cond); + +/* + * Scheduling + */ +int pthread_setschedparam (pthread_t thread, + int policy, + const struct sched_param *param); + +int pthread_getschedparam (pthread_t thread, + int *policy, + struct sched_param *param); + +int pthread_setconcurrency (int); + +int pthread_getconcurrency (void); + +/* + * Read-Write Lock Functions + */ +int pthread_rwlock_init(pthread_rwlock_t *lock, + const pthread_rwlockattr_t *attr); + +int pthread_rwlock_destroy(pthread_rwlock_t *lock); + +int pthread_rwlock_tryrdlock(pthread_rwlock_t *); + +int pthread_rwlock_trywrlock(pthread_rwlock_t *); + +int pthread_rwlock_rdlock(pthread_rwlock_t *lock); + +int pthread_rwlock_wrlock(pthread_rwlock_t *lock); + +int pthread_rwlock_unlock(pthread_rwlock_t *lock); + + +/* + * Non-portable functions + */ + +/* + * Compatibility with Linux. + */ +int pthread_mutexattr_setkind_np(pthread_mutexattr_t * attr, int kind); +int pthread_mutexattr_getkind_np(pthread_mutexattr_t * attr, int *kind); + +/* + * Possibly supported by other POSIX threads implementations + */ +int pthread_delay_np (struct timespec * interval); + +/* + * Returns the Win32 HANDLE for the POSIX thread. + */ +HANDLE pthread_getw32threadhandle_np(pthread_t thread); + +/* + * Returns the number of CPUs available to the process. + */ +int pthread_getprocessors_np(int * count); + +/* + * Useful if an application wants to statically link + * the lib rather than load the DLL at run-time. + */ +int pthread_win32_process_attach_np(void); +int pthread_win32_process_detach_np(void); +int pthread_win32_thread_attach_np(void); +int pthread_win32_thread_detach_np(void); + + +/* + * Protected Methods + * + * This function blocks until the given WIN32 handle + * is signaled or pthread_cancel had been called. + * This function allows the caller to hook into the + * PThreads cancel mechanism. It is implemented using + * + * WaitForMultipleObjects + * + * on 'waitHandle' and a manually reset WIN32 Event + * used to implement pthread_cancel. The 'timeout' + * argument to TimedWait is simply passed to + * WaitForMultipleObjects. + */ +int pthreadCancelableWait (HANDLE waitHandle); +int pthreadCancelableTimedWait (HANDLE waitHandle, DWORD timeout); + +/* + * Thread-Safe C Runtime Library Mappings. + */ +#ifndef _UWIN +#if 1 +#if (! defined(HAVE_ERRNO)) && (! defined(_REENTRANT)) && (! defined(_MT)) +int * _errno( void ); +#endif +#else +#if (! defined(NEED_ERRNO)) || (! defined( _REENTRANT ) && (! defined( _MT ) || ! defined( _MD ))) +#if defined(PTW32_BUILD) +__declspec( dllexport ) int * _errno( void ); +#else +int * _errno( void ); +#endif +#endif +#endif +#endif + +/* + * WIN32 C runtime library had been made thread-safe + * without affecting the user interface. Provide + * mappings from the UNIX thread-safe versions to + * the standard C runtime library calls. + * Only provide function mappings for functions that + * actually exist on WIN32. + */ + +#if !defined(__MINGW32__) +#define strtok_r( _s, _sep, _lasts ) \ + ( *(_lasts) = strtok( (_s), (_sep) ) ) +#endif /* !__MINGW32__ */ + +#define asctime_r( _tm, _buf ) \ + ( strcpy( (_buf), asctime( (_tm) ) ), \ + (_buf) ) + +#define ctime_r( _clock, _buf ) \ + ( strcpy( (_buf), ctime( (_clock) ) ), \ + (_buf) ) + +#define gmtime_r( _clock, _result ) \ + ( *(_result) = *gmtime( (_clock) ), \ + (_result) ) + +#define localtime_r( _clock, _result ) \ + ( *(_result) = *localtime( (_clock) ), \ + (_result) ) + +#define rand_r( _seed ) \ + ( _seed == _seed? rand() : rand() ) + + +#ifdef __cplusplus + +/* + * Internal exceptions + */ +class ptw32_exception {}; +class ptw32_exception_cancel : public ptw32_exception {}; +class ptw32_exception_exit : public ptw32_exception {}; + +#endif + +/* FIXME: This is only required if the library was built using SEH */ +/* + * Get internal SEH tag + */ +DWORD ptw32_get_exception_services_code(void); + +#ifndef PTW32_BUILD + +#ifdef __CLEANUP_SEH + +/* + * Redefine the SEH __except keyword to ensure that applications + * propagate our internal exceptions up to the library's internal handlers. + */ +#define __except( E ) \ + __except( ( GetExceptionCode() == ptw32_get_exception_services_code() ) \ + ? EXCEPTION_CONTINUE_SEARCH : ( E ) ) + +#endif /* __CLEANUP_SEH */ + +#ifdef __cplusplus + +/* + * Redefine the C++ catch keyword to ensure that applications + * propagate our internal exceptions up to the library's internal handlers. + */ +#ifdef _MSC_VER + /* + * WARNING: Replace any 'catch( ... )' with 'PtW32CatchAll' + * if you want Pthread-Win32 cancelation and pthread_exit to work. + */ + +#ifndef PtW32NoCatchWarn + +#pragma message("When compiling applications with MSVC++ and C++ exception handling:") +#pragma message(" Replace any 'catch( ... )' with 'PtW32CatchAll' in POSIX threads") +#pragma message(" if you want POSIX thread cancelation and pthread_exit to work.") + +#endif + +#define PtW32CatchAll \ + catch( ptw32_exception & ) { throw; } \ + catch( ... ) + +#else /* _MSC_VER */ + +#define catch( E ) \ + catch( ptw32_exception & ) { throw; } \ + catch( E ) + +#endif /* _MSC_VER */ + +#endif /* __cplusplus */ + +#endif /* ! PTW32_BUILD */ + +#ifdef __cplusplus +} /* End of extern "C" */ +#endif /* __cplusplus */ + +#endif /* PTHREAD_H */ diff --git a/lib/libdvd/libdvdread/msvc/include/pthreads/sched.h b/lib/libdvd/libdvdread/msvc/include/pthreads/sched.h new file mode 100755 index 0000000000..ab277920e0 --- /dev/null +++ b/lib/libdvd/libdvdread/msvc/include/pthreads/sched.h @@ -0,0 +1,89 @@ +/* + * Module: sched.h + * + * Purpose: + * Provides an implementation of POSIX realtime extensions + * as defined in + * + * POSIX 1003.1b-1993 (POSIX.1b) + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright (C) 1998 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA + */ +#ifndef _SCHED_H +#define _SCHED_H + +#if defined(__MINGW32__) || defined(_UWIN) +/* For pid_t */ +# include <sys/types.h> +/* Required by Unix 98 */ +# include <time.h> +#else +typedef int pid_t; +#endif + +/* Thread scheduling policies */ + +enum { + SCHED_OTHER = 0, + SCHED_FIFO, + SCHED_RR, + SCHED_MIN = SCHED_OTHER, + SCHED_MAX = SCHED_RR +}; + +struct sched_param { + int sched_priority; +}; + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +int sched_yield (void); + +int sched_get_priority_min (int policy); + +int sched_get_priority_max (int policy); + +int sched_setscheduler (pid_t pid, int policy); + +int sched_getscheduler (pid_t pid); + +/* + * Note that this macro returns ENOTSUP rather than + * ENOSYS as might be expected. However, returning ENOSYS + * should mean that sched_get_priority_{min,max} are + * not implemented as well as sched_rr_get_interval. + * This is not the case, since we just don't support + * round-robin scheduling. Therefore I have chosen to + * return the same value as sched_setscheduler when + * SCHED_RR is passed to it. + */ +#define sched_rr_get_interval(_pid, _interval) \ + ( errno = ENOTSUP, (int) -1 ) + + +#ifdef __cplusplus +} /* End of extern "C" */ +#endif /* __cplusplus */ + + +#endif /* !_SCHED_H */ + diff --git a/lib/libdvd/libdvdread/msvc/include/sys/time.h b/lib/libdvd/libdvdread/msvc/include/sys/time.h new file mode 100755 index 0000000000..f874fa655f --- /dev/null +++ b/lib/libdvd/libdvdread/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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * WIN32 PORT, + * by Matthew Grooms <elon@altavista.com> + * + * sys/time.h - There is no seperate sys/time.h for win32 so we simply + * include the standard time header as well as our xine + * timer functions. + */ + +#include <time.h> diff --git a/lib/libdvd/libdvdread/msvc/include/timer.h b/lib/libdvd/libdvdread/msvc/include/timer.h new file mode 100755 index 0000000000..efab6f4e18 --- /dev/null +++ b/lib/libdvd/libdvdread/msvc/include/timer.h @@ -0,0 +1,39 @@ +#include <time.h> +#include <winsock.h> +#include "pthread.h" + +#ifndef _ITIMER_ +#define _ITIMER_ + +#define ITIMER_REAL 0 +#define ITIMER_VIRTUAL 1 + +// time reference +// ---------------------------------- +// +// 1,000 milliseconds / sec +// 1,000,000 microseconds / sec +// 1,000,000,000 nanoseconds / sec +// +// timeval.time_sec = seconds +// timeval.time_usec = microseconds + +struct itimerval +{ + struct timeval it_interval; /* timer interval */ + struct timeval it_value; /* current value */ +}; + +struct timezone { + int tz_minuteswest; /* minutes west of Greenwich */ + int tz_dsttime; /* type of dst correction */ +}; + +int gettimeofday( struct timeval *tp, struct timezone *tzp ); +int setitimer( int which, struct itimerval * value, struct itimerval *ovalue ); +int pause( void ); + +unsigned int sleep( unsigned int seconds ); +int nanosleep( const struct timespec *rqtp, struct timespec *rmtp ); + +#endif
\ No newline at end of file diff --git a/lib/libdvd/libdvdread/msvc/include/unistd.h b/lib/libdvd/libdvdread/msvc/include/unistd.h new file mode 100755 index 0000000000..7e4c63f3a5 --- /dev/null +++ b/lib/libdvd/libdvdread/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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * WIN32 PORT, + * by Matthew Grooms <elon@altavista.com> + * + * unistd.h - This is mostly a catch all header that maps standard unix + * libc calls to the equivelent win32 functions. + * + */ + +#include <windows.h> +#include <malloc.h> +#include <errno.h> +#include <direct.h> + +#include <config.h> + +#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 dont remember why this is here +#define readlink + +#endif diff --git a/lib/libdvd/libdvdread/msvc/install/README b/lib/libdvd/libdvdread/msvc/install/README new file mode 100755 index 0000000000..5e6ba4ae9f --- /dev/null +++ b/lib/libdvd/libdvdread/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/lib/libdvd/libdvdread/msvc/libdvdcss.def b/lib/libdvd/libdvdread/msvc/libdvdcss.def new file mode 100755 index 0000000000..0a6e2fd997 --- /dev/null +++ b/lib/libdvd/libdvdread/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/lib/libdvd/libdvdread/msvc/libdvdcss.dsp b/lib/libdvd/libdvdread/msvc/libdvdcss.dsp new file mode 100755 index 0000000000..bb91b6a3eb --- /dev/null +++ b/lib/libdvd/libdvdread/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/lib/libdvd/libdvdread/msvc/libdvdnav.def b/lib/libdvd/libdvdread/msvc/libdvdnav.def new file mode 100755 index 0000000000..7f633d18d2 --- /dev/null +++ b/lib/libdvd/libdvdread/msvc/libdvdnav.def @@ -0,0 +1,82 @@ +;------------------------------------------------------------ +; 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 + +;------------------------------------------------------------ +; timer exports + +gettimeofday +setitimer +pause +sleep +nanosleep diff --git a/lib/libdvd/libdvdread/msvc/libdvdnav.dsp b/lib/libdvd/libdvdread/msvc/libdvdnav.dsp new file mode 100755 index 0000000000..d301b234ee --- /dev/null +++ b/lib/libdvd/libdvdread/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 "include/pthreads" /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 "include/pthreads" /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/lib/libdvd/libdvdread/msvc/libdvdnav.dsw b/lib/libdvd/libdvdread/msvc/libdvdnav.dsw new file mode 100755 index 0000000000..8974efbee6 --- /dev/null +++ b/lib/libdvd/libdvdread/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/lib/libdvd/libdvdread/msvc/libwin32utils.def b/lib/libdvd/libdvdread/msvc/libwin32utils.def new file mode 100755 index 0000000000..1277cc8b7b --- /dev/null +++ b/lib/libdvd/libdvdread/msvc/libwin32utils.def @@ -0,0 +1,229 @@ +;------------------------------------------------------------ +; LIBWIN32UTILS DLL DEFINITIONS FILE + +EXPORTS + +;------------------------------------------------------------ +; dirent exports + +opendir +closedir +readdir +rewinddir + +;------------------------------------------------------------ +; pthread exports + +;pthread_atfork +pthread_attr_destroy +pthread_attr_getdetachstate +pthread_attr_getinheritsched +pthread_attr_getschedparam +pthread_attr_getschedpolicy +pthread_attr_getscope +pthread_attr_getstackaddr +pthread_attr_getstacksize +pthread_attr_init +pthread_attr_setdetachstate +pthread_attr_setinheritsched +pthread_attr_setschedparam +pthread_attr_setschedpolicy +pthread_attr_setscope +pthread_attr_setstackaddr +pthread_attr_setstacksize +pthread_cancel +; +; These two are implemented as macros in pthread.h +; +;pthread_cleanup_pop +;pthread_cleanup_push +; +pthread_condattr_destroy +pthread_condattr_getpshared +pthread_condattr_init +pthread_condattr_setpshared +pthread_cond_broadcast +pthread_cond_destroy +pthread_cond_init +pthread_cond_signal +pthread_cond_timedwait +pthread_cond_wait +pthread_create +pthread_detach +pthread_equal +pthread_exit +pthread_getconcurrency +pthread_getschedparam +pthread_getspecific +pthread_join +pthread_key_create +pthread_key_delete +;pthread_kill +pthread_mutexattr_destroy +;pthread_mutexattr_getprioceiling +;pthread_mutexattr_getprotocol +pthread_mutexattr_getpshared +pthread_mutexattr_gettype +pthread_mutexattr_init +;pthread_mutexattr_setprioceiling +;pthread_mutexattr_setprotocol +pthread_mutexattr_setpshared +pthread_mutexattr_settype +pthread_mutexattr_destroy +pthread_mutex_init +pthread_mutex_destroy +pthread_mutex_lock +pthread_mutex_trylock +pthread_mutex_unlock +pthread_once +pthread_self +pthread_setcancelstate +pthread_setcanceltype +pthread_setconcurrency +pthread_setschedparam +pthread_setspecific +;pthread_sigmask +pthread_testcancel +; +; POSIX 1.b +; +sched_get_priority_min +sched_get_priority_max +sched_getscheduler +sched_setscheduler +sched_yield +sem_init +sem_destroy +sem_trywait +sem_wait +sem_post +sem_open +sem_close +sem_unlink +sem_getvalue +; +; This next one is a macro +;sched_rr_get_interval +; +; +; Read/Write Locks +; +pthread_rwlock_init +pthread_rwlock_destroy +pthread_rwlock_tryrdlock +pthread_rwlock_trywrlock +pthread_rwlock_rdlock +pthread_rwlock_wrlock +pthread_rwlock_unlock +; +; Spin locks +; +pthread_spin_init +pthread_spin_destroy +pthread_spin_lock +pthread_spin_unlock +pthread_spin_trylock +; +; Barriers +; +pthread_barrier_init +pthread_barrier_destroy +pthread_barrier_wait +pthread_barrierattr_init +pthread_barrierattr_destroy +pthread_barrierattr_getpshared +pthread_barrierattr_setpshared +; +; Non-portable/compatibility with other implementations +; +pthread_delay_np +pthread_mutexattr_getkind_np +pthread_mutexattr_setkind_np +; +; Non-portable local implementation only +; +pthread_getw32threadhandle_np +pthread_getprocessors_np +pthreadCancelableWait +pthreadCancelableTimedWait +; +; For use when linking statically +; +pthread_win32_process_attach_np +pthread_win32_process_detach_np +pthread_win32_thread_attach_np +pthread_win32_thread_detach_np +; +; 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 + +;------------------------------------------------------------ +; timer exports + +gettimeofday +setitimer +pause +sleep +nanosleep + +;------------------------------------------------------------ +; other exports +bcopy +dlclose +dlsym +dlopen +dlerror + +optind
\ No newline at end of file diff --git a/lib/libdvd/libdvdread/msvc/libwin32utils.dsp b/lib/libdvd/libdvdread/msvc/libwin32utils.dsp new file mode 100755 index 0000000000..f94af8f493 --- /dev/null +++ b/lib/libdvd/libdvdread/msvc/libwin32utils.dsp @@ -0,0 +1,136 @@ +# 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" /I "include/pthreads" /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/pthreads" /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 "Source Files ( timer )" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\contrib\timer\timer.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\bcopy.c +# End Source File +# Begin Source File + +SOURCE=.\contrib\dlfcn.c +# End Source File +# Begin Source File + +SOURCE=.\contrib\getopt.c +# End Source File +# End Group +# End Target +# End Project diff --git a/lib/libdvd/libdvdread/msvc/play_title.dsp b/lib/libdvd/libdvdread/msvc/play_title.dsp new file mode 100755 index 0000000000..8a3efdf587 --- /dev/null +++ b/lib/libdvd/libdvdread/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/lib/libdvd/libdvdread/msvc/scripts/libdvdcss_install.bat b/lib/libdvd/libdvdread/msvc/scripts/libdvdcss_install.bat new file mode 100755 index 0000000000..84712b122b --- /dev/null +++ b/lib/libdvd/libdvdread/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/lib/libdvd/libdvdread/msvc/scripts/libdvdnav_install.bat b/lib/libdvd/libdvdread/msvc/scripts/libdvdnav_install.bat new file mode 100755 index 0000000000..f49f2f2294 --- /dev/null +++ b/lib/libdvd/libdvdread/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/lib/libdvd/libdvdread/msvc/title_info.dsp b/lib/libdvd/libdvdread/msvc/title_info.dsp new file mode 100755 index 0000000000..39d3768d56 --- /dev/null +++ b/lib/libdvd/libdvdread/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/lib/libdvd/libdvdread/src/Makefile.am b/lib/libdvd/libdvdread/src/Makefile.am new file mode 100644 index 0000000000..f79280cfbb --- /dev/null +++ b/lib/libdvd/libdvdread/src/Makefile.am @@ -0,0 +1,19 @@ +include $(top_srcdir)/misc/Makefile.common + +includedir = ${prefix}/include/dvdread + +AM_CPPFLAGS = -I$(top_srcdir)/src + +lib_LTLIBRARIES = libdvdread.la + +libdvdread_la_SOURCES = dvd_reader.c nav_read.c ifo_read.c \ + dvd_input.c dvd_udf.c md5.c nav_print.c ifo_print.c bitreader.c \ + bswap.h dvd_input.h dvdread_internal.h dvd_udf.h md5.h bitreader.h + +libdvdread_la_LIBADD = $(DYNAMIC_LD_LIBS) + +libdvdread_la_LDFLAGS = -version-info $(DVDREAD_LT_CURRENT):$(DVDREAD_LT_REVISION):$(DVDREAD_LT_AGE) \ + -export-symbols-regex "(^dvd.*|^nav.*|^ifo.*|^DVD.*|^UDF.*)" + +include_HEADERS = dvd_reader.h nav_read.h ifo_read.h \ + nav_print.h ifo_print.h ifo_types.h nav_types.h dvd_udf.h bitreader.h diff --git a/lib/libdvd/libdvdread/src/bitreader.c b/lib/libdvd/libdvdread/src/bitreader.c new file mode 100644 index 0000000000..441659f721 --- /dev/null +++ b/lib/libdvd/libdvdread/src/bitreader.c @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2000, 2001, 2002, 2003 Håkan Hjort <d95hjort@dtek.chalmers.se> + * + * 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 + */ + +#include "config.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <inttypes.h> + +#include "bitreader.h" + +int dvdread_getbits_init(getbits_state_t *state, uint8_t *start) { + if ((state == NULL) || (start == NULL)) return 0; + state->start = start; + state->bit_position = 0; + state->byte_position = 0; + state->byte = start[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->byte; + byte = byte >> (state->bit_position); + result = byte; + number_of_bits -= (8-state->bit_position); + state->bit_position = 0; + state->byte_position++; + state->byte = state->start[state->byte_position]; + } else { + byte=state->byte; + state->byte = state->byte << number_of_bits; + 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++; + state->byte = state->start[state->byte_position]; + } + number_of_bits = 0; + } + } + if ((state->bit_position) == 0) { + while (number_of_bits > 7) { + result = (result << 8) + state->byte; + state->byte_position++; + state->byte = state->start[state->byte_position]; + number_of_bits -= 8; + } + if (number_of_bits > 0) { /* number_of_bits < 8 */ + byte = state->byte; + state->byte = state->byte << number_of_bits; + 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 diff --git a/lib/libdvd/libdvdread/src/bitreader.h b/lib/libdvd/libdvdread/src/bitreader.h new file mode 100644 index 0000000000..54d421507d --- /dev/null +++ b/lib/libdvd/libdvdread/src/bitreader.h @@ -0,0 +1,40 @@ +#ifndef BITREADER_H_INCLUDED +#define BITREADER_H_INCLUDED + +/* + * Copyright (C) 2000, 2001, 2002 Håkan Hjort <d95hjort@dtek.chalmers.se>. + * + * 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 + */ + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + uint8_t *start; + uint32_t byte_position; + uint32_t bit_position; + uint8_t byte; +} getbits_state_t; + +int dvdread_getbits_init(getbits_state_t *state, uint8_t *start); +uint32_t dvdread_getbits(getbits_state_t *state, uint32_t number_of_bits); + +#ifdef __cplusplus +}; +#endif +#endif /* BITREADER_H_INCLUDED */ diff --git a/lib/libdvd/libdvdread/src/bswap.h b/lib/libdvd/libdvdread/src/bswap.h new file mode 100644 index 0000000000..45286db0e5 --- /dev/null +++ b/lib/libdvd/libdvdread/src/bswap.h @@ -0,0 +1,104 @@ +#ifndef BSWAP_H_INCLUDED +#define BSWAP_H_INCLUDED + +/* + * Copyright (C) 2000, 2001 Billy Biggs <vektor@dumbterm.net>, + * Håkan Hjort <d95hjort@dtek.chalmers.se> + * + * 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 + */ + +#include <config.h> + +#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 <sys/param.h> +#endif + +#if defined(__linux__) || defined(__GLIBC__) +#include <byteswap.h> +#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 <libkern/OSByteOrder.h> +#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 <sys/endian.h> +#define B2N_16(x) BE16TOH(x) +#define B2N_32(x) BE32TOH(x) +#define B2N_64(x) BE64TOH(x) + +#elif defined(__OpenBSD__) +#include <sys/endian.h> +#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 <sys/endian.h> +#define B2N_16(x) x = be16toh(x) +#define B2N_32(x) x = be32toh(x) +#define B2N_64(x) x = be64toh(x) + +/* This is a slow but portable implementation, it has multiple evaluation + * problems so beware. + * Old FreeBSD's and Solaris don't have <byteswap.h> or any other such + * functionality! + */ + +#elif defined(__FreeBSD__) || defined(__sun) || defined(__bsdi__) || defined(WIN32) || defined(__CYGWIN__) || defined(__BEOS__) +#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 you're system" + +#endif + +#endif /* WORDS_BIGENDIAN */ + +#endif /* BSWAP_H_INCLUDED */ diff --git a/lib/libdvd/libdvdread/src/dvd_input.c b/lib/libdvd/libdvdread/src/dvd_input.c new file mode 100644 index 0000000000..3fbc2ae2f7 --- /dev/null +++ b/lib/libdvd/libdvdread/src/dvd_input.c @@ -0,0 +1,362 @@ +/* + * Copyright (C) 2002 Samuel Hocevar <sam@zoy.org>, + * Håkan Hjort <d95hjort@dtek.chalmers.se> + * + * 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, USA. + */ + +#include "config.h" + +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <unistd.h> + +#include "dvd_reader.h" +#include "dvd_input.h" + + +/* The function pointers that is the exported interface of this file. */ +dvd_input_t (*dvdinput_open) (const char *); +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); +char * (*dvdinput_error) (dvd_input_t); + +#ifdef HAVE_DVDCSS_DVDCSS_H +/* linking to libdvdcss */ +#include "dvdcss/dvdcss.h" +#define DVDcss_open(a) dvdcss_open((char*)(a)) +#define DVDcss_close dvdcss_close +#define DVDcss_seek dvdcss_seek +#define DVDcss_title dvdcss_title +#define DVDcss_read dvdcss_read +#define DVDcss_error dvdcss_error +#else + +/* dlopening libdvdcss */ +#ifdef HAVE_DLFCN_H +#include <dlfcn.h> +#else +/* Only needed on MINGW at the moment */ +#include "../../msvc/contrib/dlfcn.c" +#endif + +typedef struct dvdcss_s *dvdcss_handle; +static dvdcss_handle (*DVDcss_open) (const char *); +static int (*DVDcss_close) (dvdcss_handle); +static int (*DVDcss_seek) (dvdcss_handle, int, int); +static int (*DVDcss_title) (dvdcss_handle, int); +static int (*DVDcss_read) (dvdcss_handle, void *, int, int); +static char * (*DVDcss_error) (dvdcss_handle); +#endif + +/* The DVDinput handle, add stuff here for new input methods. */ +struct dvd_input_s { + /* libdvdcss handle */ + dvdcss_handle dvdcss; + + /* dummy file input */ + int fd; +}; + + +/** + * initialize and open a DVD device or file. + */ +static dvd_input_t css_open(const char *target) +{ + dvd_input_t dev; + + /* Allocate the handle structure */ + dev = (dvd_input_t) malloc(sizeof(*dev)); + if(dev == NULL) { + fprintf(stderr, "libdvdread: Could not allocate memory.\n"); + return NULL; + } + + /* Really open it with libdvdcss */ + dev->dvdcss = DVDcss_open(target); + if(dev->dvdcss == 0) { + fprintf(stderr, "libdvdread: Could not open %s with libdvdcss.\n", target); + free(dev); + return NULL; + } + + return dev; +} + +/** + * return the last error message + */ +static char *css_error(dvd_input_t dev) +{ + return DVDcss_error(dev->dvdcss); +} + +/** + * 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_title(dev->dvdcss, block); +} + +/** + * 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); + + if(ret < 0) + return ret; + + free(dev); + + return 0; +} + +/** + * initialize and open a DVD device or file. + */ +static dvd_input_t file_open(const char *target) +{ + dvd_input_t dev; + + /* Allocate the library structure */ + dev = (dvd_input_t) malloc(sizeof(*dev)); + if(dev == NULL) { + fprintf(stderr, "libdvdread: Could not allocate memory.\n"); + return NULL; + } + + /* Open the device */ +#ifndef WIN32 + dev->fd = open(target, O_RDONLY); +#else + dev->fd = open(target, O_RDONLY | O_BINARY); +#endif + if(dev->fd < 0) { + perror("libdvdread: Could not open input"); + free(dev); + return NULL; + } + + return dev; +} + +/** + * return the last error message + */ +static char *file_error(dvd_input_t dev) +{ + /* use strerror(errno)? */ + return (char *)"unknown error"; +} + +/** + * seek into the device. + */ +static int file_seek(dvd_input_t dev, int blocks) +{ + off_t pos; + + pos = lseek(dev->fd, (off_t)blocks * (off_t)DVD_VIDEO_LB_LEN, SEEK_SET); + if(pos < 0) { + return pos; + } + /* assert pos % DVD_VIDEO_LB_LEN == 0 */ + return (int) (pos / DVD_VIDEO_LB_LEN); +} + +/** + * set the block for the beginning of a new title (key). + */ +static int file_title(dvd_input_t dev, int block) +{ + return -1; +} + +/** + * read data from the device. + */ +static int file_read(dvd_input_t dev, void *buffer, int blocks, int flags) +{ + size_t len; + ssize_t ret; + + len = (size_t)blocks * DVD_VIDEO_LB_LEN; + + while(len > 0) { + + ret = read(dev->fd, buffer, 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. */ + 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. */ + size_t bytes = (size_t)blocks * DVD_VIDEO_LB_LEN - len; + off_t over_read = -(bytes % DVD_VIDEO_LB_LEN); + /*off_t pos =*/ lseek(dev->fd, over_read, SEEK_CUR); + /* should have pos % 2048 == 0 */ + return (int) (bytes / DVD_VIDEO_LB_LEN); + } + + len -= ret; + } + + return blocks; +} + +/** + * close the DVD device and clean up. + */ +static int file_close(dvd_input_t dev) +{ + int ret; + + ret = close(dev->fd); + + if(ret < 0) + return ret; + + free(dev); + + return 0; +} + + +/** + * Setup read functions with either libdvdcss or minimal DVD access. + */ +int dvdinput_setup(void) +{ + void *dvdcss_library = NULL; + char **dvdcss_version = NULL; + +#ifdef HAVE_DVDCSS_DVDCSS_H + /* linking to libdvdcss */ + dvdcss_library = &dvdcss_library; /* Give it some value != NULL */ + /* the DVDcss_* functions have been #defined at the top */ + dvdcss_version = &dvdcss_interface_2; + +#else + /* dlopening libdvdcss */ + +#ifdef __APPLE__ + #define CSS_LIB "libdvdcss.2.dylib" +#elif defined(WIN32) + #define CSS_LIB "libdvdcss.dll" +#else + #define CSS_LIB "libdvdcss.so.2" +#endif + dvdcss_library = dlopen(CSS_LIB, RTLD_LAZY); + + if(dvdcss_library != NULL) { +#if defined(__OpenBSD__) && !defined(__ELF__) +#define U_S "_" +#else +#define U_S +#endif + DVDcss_open = (dvdcss_handle (*)(const char*)) + dlsym(dvdcss_library, U_S "dvdcss_open"); + DVDcss_close = (int (*)(dvdcss_handle)) + dlsym(dvdcss_library, U_S "dvdcss_close"); + DVDcss_title = (int (*)(dvdcss_handle, int)) + dlsym(dvdcss_library, U_S "dvdcss_title"); + DVDcss_seek = (int (*)(dvdcss_handle, int, int)) + dlsym(dvdcss_library, U_S "dvdcss_seek"); + DVDcss_read = (int (*)(dvdcss_handle, void*, int, int)) + dlsym(dvdcss_library, U_S "dvdcss_read"); + DVDcss_error = (char* (*)(dvdcss_handle)) + dlsym(dvdcss_library, U_S "dvdcss_error"); + + dvdcss_version = (char **)dlsym(dvdcss_library, U_S "dvdcss_interface_2"); + + if(dlsym(dvdcss_library, U_S "dvdcss_crack")) { + fprintf(stderr, + "libdvdread: Old (pre-0.0.2) version of libdvdcss found.\n" + "libdvdread: You should get the latest version from " + "http://www.videolan.org/\n" ); + dlclose(dvdcss_library); + dvdcss_library = NULL; + } else if(!DVDcss_open || !DVDcss_close || !DVDcss_title || !DVDcss_seek + || !DVDcss_read || !DVDcss_error || !dvdcss_version) { + fprintf(stderr, "libdvdread: Missing symbols in %s, " + "this shouldn't happen !\n", CSS_LIB); + dlclose(dvdcss_library); + } + } +#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); + */ + fprintf(stderr, "libdvdread: Using libdvdcss version %s for DVD access\n", + dvdcss_version ? *dvdcss_version : ""); + + /* libdvdcss wrapper functions */ + dvdinput_open = css_open; + dvdinput_close = css_close; + dvdinput_seek = css_seek; + dvdinput_title = css_title; + dvdinput_read = css_read; + dvdinput_error = css_error; + return 1; + + } else { + fprintf(stderr, "libdvdread: Encrypted DVD support unavailable.\n"); + + /* libdvdcss replacement functions */ + dvdinput_open = file_open; + dvdinput_close = file_close; + dvdinput_seek = file_seek; + dvdinput_title = file_title; + dvdinput_read = file_read; + dvdinput_error = file_error; + return 0; + } +} diff --git a/lib/libdvd/libdvdread/src/dvd_input.h b/lib/libdvd/libdvdread/src/dvd_input.h new file mode 100644 index 0000000000..ccd2e74fe1 --- /dev/null +++ b/lib/libdvd/libdvdread/src/dvd_input.h @@ -0,0 +1,67 @@ +#ifndef DVD_INPUT_H_INCLUDED +#define DVD_INPUT_H_INCLUDED + +/* + * Copyright (C) 2001, 2002 Samuel Hocevar <sam@zoy.org>, + * Håkan Hjort <d95hjort@dtek.chalmers.se> + * + * 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, USA. + */ + +/** + * Defines and flags. Make sure they fit the libdvdcss API! + */ +#define DVDINPUT_NOFLAGS 0 + +#define DVDINPUT_READ_DECRYPT (1 << 0) + +#if defined( __MINGW32__ ) +# undef lseek +# define lseek _lseeki64 +# undef fseeko +# define fseeko fseeko64 +# undef ftello +# define ftello ftello64 +# define flockfile(...) +# define funlockfile(...) +# define getc_unlocked getc +# undef off_t +# define off_t off64_t +# undef stat +# define stat _stati64 +# define fstat _fstati64 +# define wstat _wstati64 +#endif + + +typedef struct dvd_input_s *dvd_input_t; + +/** + * Function pointers that will be filled in by the input implementation. + * These functions provide the main API. + */ +extern dvd_input_t (*dvdinput_open) (const char *); +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); +extern char * (*dvdinput_error) (dvd_input_t); + +/** + * Setup function accessed by dvd_reader.c. Returns 1 if there is CSS support. + */ +int dvdinput_setup(void); + +#endif /* DVD_INPUT_H_INCLUDED */ diff --git a/lib/libdvd/libdvdread/src/dvd_reader.c b/lib/libdvd/libdvdread/src/dvd_reader.c new file mode 100644 index 0000000000..e865b41ef5 --- /dev/null +++ b/lib/libdvd/libdvdread/src/dvd_reader.c @@ -0,0 +1,1395 @@ +/* + * Copyright (C) 2001-2004 Billy Biggs <vektor@dumbterm.net>, + * HÃkan Hjort <d95hjort@dtek.chalmers.se>, + * BjËrn Englund <d4bjorn@dtek.chalmers.se> + * + * 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, USA. + */ + +#include "config.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/time.h> /* For the timing of dvdcss_title crack. */ +#include <fcntl.h> +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <unistd.h> +#include <limits.h> +#include <dirent.h> + +#define WITH_CACHE + +/* misc win32 helpers */ +#ifdef WIN32 +#ifndef HAVE_GETTIMEOFDAY +/* replacement gettimeofday implementation */ +#include <sys/timeb.h> +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 +#include <io.h> /* read() */ +#define lseek64 _lseeki64 +#endif + +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__bsdi__)|| defined(__DARWIN__) +#define SYS_BSD 1 +#endif + +#if defined(__sun) +#include <sys/mnttab.h> +#elif defined(SYS_BSD) +#include <fstab.h> +#elif defined(__linux__) +#include <mntent.h> +#endif + +#include "dvd_udf.h" +#include "dvd_input.h" +#include "dvd_reader.h" +#include "md5.h" + +#define DEFAULT_UDF_CACHE_LEVEL 1 + +struct dvd_reader_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 *dvd; + + /* Hack for selecting the right css title. */ + int css_title; + + /* Information required for an image file. */ + uint32_t lb_start; + uint32_t seek_pos; + +#ifdef WITH_CACHE + char cache[DVD_VIDEO_LB_LEN]; + uint32_t lb_cache; +#endif + /* 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; +}; + +int UDFReadBlocksRaw( dvd_reader_t *device, uint32_t lb_number, + size_t block_count, unsigned char *data, + int encrypted ); + +/** + * Set the level of caching on udf + * level = 0 (no caching) + * level = 1 (caching filesystem info) + */ +int DVDUDFCacheLevel(dvd_reader_t *device, int level) +{ + struct dvd_reader_s *dev = (struct dvd_reader_s *)device; + + if(level > 0) { + level = 1; + } else if(level < 0) { + return dev->udfcache_level; + } + + dev->udfcache_level = level; + + return level; +} + +void *GetUDFCacheHandle(dvd_reader_t *device) +{ + struct dvd_reader_s *dev = (struct dvd_reader_s *)device; + + return dev->udfcache; +} + +void SetUDFCacheHandle(dvd_reader_t *device, void *cache) +{ + struct dvd_reader_s *dev = (struct dvd_reader_s *)device; + + dev->udfcache = cache; +} + + + +/* Loop over all titles and call dvdcss_title to crack the keys. */ +static int initAllCSSKeys( dvd_reader_t *dvd ) +{ + 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; + + char *nokeys_str = getenv("DVDREAD_NOKEYS"); + if(nokeys_str != NULL) + return 0; + + fprintf( stderr, "\n" ); + fprintf( stderr, "libdvdread: Attempting to retrieve all CSS keys\n" ); + fprintf( stderr, "libdvdread: This can take a _long_ time, " + "please be patient\n\n" ); + + gettimeofday(&all_s, NULL); + + for( title = 0; title < 100; title++ ) { + gettimeofday( &t_s, NULL ); + if( title == 0 ) { + sprintf( filename, "/VIDEO_TS/VIDEO_TS.VOB" ); + } else { + sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, 0 ); + } + start = UDFFindFile( dvd, filename, &len ); + if( start != 0 && len != 0 ) { + /* Perform CSS key cracking for this title. */ + fprintf( stderr, "libdvdread: Get key for %s at 0x%08x\n", + filename, start ); + if( dvdinput_title( dvd->dev, (int)start ) < 0 ) { + fprintf( stderr, "libdvdread: Error cracking CSS key for %s (0x%08x)\n", filename, start); + } + gettimeofday( &t_e, NULL ); + fprintf( stderr, "libdvdread: Elapsed time %ld\n", + (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( dvd, filename, &len ); + if( start == 0 || len == 0 ) break; + + /* Perform CSS key cracking for this title. */ + fprintf( stderr, "libdvdread: Get key for %s at 0x%08x\n", + filename, start ); + if( dvdinput_title( dvd->dev, (int)start ) < 0 ) { + fprintf( stderr, "libdvdread: Error cracking CSS key for %s (0x%08x)!!\n", filename, start); + } + gettimeofday( &t_e, NULL ); + fprintf( stderr, "libdvdread: Elapsed time %ld\n", + (long int) t_e.tv_sec - t_s.tv_sec ); + } + title--; + + fprintf( stderr, "libdvdread: Found %d VTS's\n", title ); + gettimeofday(&all_e, NULL); + fprintf( stderr, "libdvdread: Elapsed time %ld\n", + (long int) all_e.tv_sec - all_s.tv_sec ); + + return 0; +} + + + +/** + * Open a DVD image or block device file. + */ +static dvd_reader_t *DVDOpenImageFile( const char *location, int have_css ) +{ + dvd_reader_t *dvd; + dvd_input_t dev; + + dev = dvdinput_open( location ); + if( !dev ) { + fprintf( stderr, "libdvdread: Can't open %s for reading\n", location ); + return NULL; + } + + dvd = (dvd_reader_t *) malloc( sizeof( dvd_reader_t ) ); + if( !dvd ) { + dvdinput_close(dev); + return NULL; + } + dvd->isImageFile = 1; + dvd->dev = dev; + dvd->path_root = NULL; + + dvd->udfcache_level = DEFAULT_UDF_CACHE_LEVEL; + dvd->udfcache = NULL; + + if( have_css ) { + /* Only if DVDCSS_METHOD = title, a bit if it's disc or if + * DVDCSS_METHOD = key but region missmatch. Unfortunaly we + * don't have that information. */ + + dvd->css_state = 1; /* Need key init. */ + } + dvd->css_title = 0; + + return dvd; +} + +static dvd_reader_t *DVDOpenPath( const char *path_root ) +{ + dvd_reader_t *dvd; + + dvd = (dvd_reader_t *) malloc( sizeof( dvd_reader_t ) ); + if( !dvd ) return NULL; + dvd->isImageFile = 0; + dvd->dev = 0; + dvd->path_root = strdup( path_root ); + if(!dvd->path_root) { + free(dvd); + return 0; + } + + dvd->udfcache_level = DEFAULT_UDF_CACHE_LEVEL; + dvd->udfcache = NULL; + + dvd->css_state = 0; /* Only used in the UDF path */ + dvd->css_title = 0; /* Only matters in the UDF path */ + + return dvd; +} + +#if defined(__sun) +/* /dev/rdsk/c0t6d0s0 (link to /devices/...) + /vol/dev/rdsk/c0t6d0/?? + /vol/rdsk/<name> */ +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 ); + 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), recomended to _not_ use r + 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) */ +static char *bsd_block2char( const char *path ) +{ + 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 ); + strcpy( new_path, "/dev/r" ); + strcat( new_path, path + strlen( "/dev/" ) ); + + return new_path; +} +#endif + +dvd_reader_t *DVDOpen( const char *ppath ) +{ + struct stat fileinfo; + int ret; + int have_css; + dvd_reader_t *ret_val = NULL; + char *dev_name = NULL; + char *path; + +#ifdef _MSC_VER + int len; +#endif + + if( ppath == NULL ) + return 0; + + path = strdup(ppath); + if( path == NULL ) + return 0; + + /* Try to open libdvdcss or fall back to standard functions */ + have_css = dvdinput_setup(); + +#ifdef _MSC_VER + /* 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 = stat( path, &fileinfo ); + + if( ret < 0 ) { + /* maybe "host:port" url? try opening it with acCeSS library */ + if( strchr(path,':') ) { + ret_val = DVDOpenImageFile( path, have_css ); + free(path); + return ret_val; + } + /* If we can't stat the file, give up */ + fprintf( stderr, "libdvdread: Can't stat %s\n", path ); + perror(""); + free(path); + return NULL; + } + + /* 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) + ret_val = DVDOpenImageFile( sun_block2char( path ), have_css ); +#elif defined(SYS_BSD) + ret_val = DVDOpenImageFile( bsd_block2char( path ), have_css ); +#else + ret_val = DVDOpenImageFile( path, have_css ); +#endif + + free(path); + return ret_val; + + } else if( S_ISDIR( fileinfo.st_mode ) ) { + dvd_reader_t *auth_drive = 0; + char *path_copy; +#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 ) ) ) { + free(path); + return NULL; + } + +#ifndef WIN32 /* don't have fchdir, and getcwd( NULL, ... ) is strange */ + /* Also WIN32 does not have symlinks, so we don't need this bit of code. */ + + /* Resolve any symlinks and get the absolut dir name. */ + { + char *new_path; + int cdir = open( ".", O_RDONLY ); + + if( cdir >= 0 ) { + chdir( path_copy ); + new_path = malloc(PATH_MAX+1); + if(!new_path) { + free(path); + return NULL; + } + getcwd(new_path, PATH_MAX ); + fchdir( cdir ); + close( cdir ); + free( path_copy ); + path_copy = new_path; + } + } +#endif + /** + * If we're being asked to open a directory, check if that directory + * is the mountpoint 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( strlen( path_copy ) > TITLES_MAX ) { + if( !strcasecmp( &(path_copy[ strlen( path_copy ) - TITLES_MAX ]), + "/video_ts" ) ) { + path_copy[ strlen( path_copy ) - TITLES_MAX ] = '\0'; + } + } + + if(path_copy[0] == '\0') { + path_copy[0] = '/'; + path_copy[1] = '\0'; + } + +#if defined(SYS_BSD) + if( ( fe = getfsfile( path_copy ) ) ) { + dev_name = bsd_block2char( fe->fs_spec ); + fprintf( stderr, + "libdvdread: Attempting to use device %s" + " mounted on %s for CSS authentication\n", + dev_name, + fe->fs_file ); + auth_drive = DVDOpenImageFile( dev_name, 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 ); + fprintf( stderr, + "libdvdread: Attempting to use device %s" + " mounted on %s for CSS authentication\n", + dev_name, + mp.mnt_mountp ); + auth_drive = DVDOpenImageFile( dev_name, have_css ); + break; + } + } + fclose( mntfile ); + } +#elif defined(__linux__) + mntfile = fopen( MOUNTED, "r" ); + if( mntfile ) { + struct mntent *me; + + while( ( me = getmntent( mntfile ) ) ) { + if( !strcmp( me->mnt_dir, path_copy ) ) { + fprintf( stderr, + "libdvdread: Attempting to use device %s" + " mounted on %s for CSS authentication\n", + me->mnt_fsname, + me->mnt_dir ); + auth_drive = DVDOpenImageFile( me->mnt_fsname, have_css ); + dev_name = strdup(me->mnt_fsname); + break; + } + } + fclose( mntfile ); + } +#elif defined(_MSC_VER) + auth_drive = DVDOpenImageFile( path, have_css ); +#endif + +#ifndef _MSC_VER + if( !dev_name ) { + fprintf( stderr, "libdvdread: Couldn't find device name.\n" ); + } else if( !auth_drive ) { + fprintf( stderr, "libdvdread: Device %s inaccessible, " + "CSS authentication not available.\n", dev_name ); + } +#else + if( !auth_drive ) { + fprintf( stderr, "libdvdread: Device %s inaccessible, " + "CSS authentication not available.\n", dev_name ); + } +#endif + + free( dev_name ); + free( path_copy ); + + /** + * If we've opened a drive, just use that. + */ + if( auth_drive ) { + free(path); + return auth_drive; + } + + /** + * Otherwise, we now try to open the directory tree instead. + */ + ret_val = DVDOpenPath( path ); + free( path ); + return ret_val; + } + + /* If it's none of the above, screw it. */ + fprintf( stderr, "libdvdread: Could not open %s\n", path ); + free( path ); + return NULL; +} + +void DVDClose( dvd_reader_t *dvd ) +{ + if( dvd ) { + if( dvd->dev ) dvdinput_close( dvd->dev ); + if( dvd->path_root ) free( dvd->path_root ); + if( dvd->udfcache ) FreeUDFCache( dvd->udfcache ); + free( dvd ); + } +} + +/** + * Open an unencrypted file on a DVD image file. + */ +static dvd_file_t *DVDOpenFileUDF( dvd_reader_t *dvd, char *filename ) +{ + uint32_t start, len; + dvd_file_t *dvd_file; + + start = UDFFindFile( dvd, filename, &len ); + if( !start ) { + fprintf( stderr, "libdvdnav:DVDOpenFileUDF:UDFFindFile %s failed\n", filename ); + return NULL; + } + + dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) ); + if( !dvd_file ) { + fprintf( stderr, "libdvdnav:DVDOpenFileUDF:malloc failed\n" ); + return NULL; + } + dvd_file->dvd = dvd; + dvd_file->lb_start = start; + dvd_file->seek_pos = 0; + memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) ); + memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) ); + dvd_file->filesize = len / DVD_VIDEO_LB_LEN; + +#ifdef WITH_CACHE + dvd_file->lb_cache = -1; +#endif + + return dvd_file; +} + +/** + * Searches for <file> in directory <path>, ignoring case. + * Returns 0 and full filename in <filename>. + * or -1 on file not found. + * or -2 on path not found. + */ +static int findDirFile( const char *path, const char *file, char *filename ) +{ +#if defined(_XBMC) + struct stat fileinfo; + + // no emulated opendir function in xbmc, so we'll + // check if the file exists by stat'ing it ... + sprintf(filename, "%s%s%s", path, + ( ( path[ strlen( path ) - 1 ] == '/' ) ? "" : "/" ), + file ); + + if (stat(filename, &fileinfo) == 0) return 0; + +#else + 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 ); +#endif // _XBMC + return -1; +} + +static int findDVDFile( dvd_reader_t *dvd, const char *file, char *filename ) +{ + char video_path[ PATH_MAX + 1 ]; + 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->path_root, nodirfile, filename ); + if( ret < 0 ) { + /* Try also with adding the path, just in case. */ + sprintf( video_path, "%s/VIDEO_TS/", dvd->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->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 *dvd, char *filename ) +{ + char full_path[ PATH_MAX + 1 ]; + dvd_file_t *dvd_file; + struct stat fileinfo; + dvd_input_t dev; + + /* Get the full path of the file. */ + if( !findDVDFile( dvd, filename, full_path ) ) { + fprintf( stderr, "libdvdnav:DVDOpenFilePath:findDVDFile %s failed\n", filename ); + return NULL; + } + + dev = dvdinput_open( full_path ); + if( !dev ) { + fprintf( stderr, "libdvdnav:DVDOpenFilePath:dvdinput_open %s failed\n", full_path ); + return NULL; + } + + dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) ); + if( !dvd_file ) { + fprintf( stderr, "libdvdnav:DVDOpenFilePath:dvd_file malloc failed\n" ); + dvdinput_close(dev); + return NULL; + } + dvd_file->dvd = dvd; + dvd_file->lb_start = 0; + dvd_file->seek_pos = 0; + memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) ); + memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) ); + dvd_file->filesize = 0; + + if( stat( full_path, &fileinfo ) < 0 ) { + fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename ); + free( dvd_file ); + 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 ]; + +#ifdef WITH_CACHE + dvd_file->lb_cache = -1; +#endif + return dvd_file; +} + +static dvd_file_t *DVDOpenVOBUDF( dvd_reader_t *dvd, int title, int menu ) +{ + char filename[ MAX_UDF_FILE_NAME_LEN ]; + uint32_t start, len; + dvd_file_t *dvd_file; + + if( title == 0 ) { + sprintf( filename, "/VIDEO_TS/VIDEO_TS.VOB" ); + } else { + sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, menu ? 0 : 1 ); + } + start = UDFFindFile( dvd, filename, &len ); + if( start == 0 ) return NULL; + + dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) ); + if( !dvd_file ) return NULL; + dvd_file->dvd = dvd; + /*Hack*/ dvd_file->css_title = title << 1 | menu; + dvd_file->lb_start = start; + dvd_file->seek_pos = 0; + memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) ); + memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) ); + dvd_file->filesize = len / DVD_VIDEO_LB_LEN; + +#ifdef WITH_CACHE + dvd_file->lb_cache = -1; +#endif + /* 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( dvd, filename, &len ) ) break; + dvd_file->filesize += len / DVD_VIDEO_LB_LEN; + } + } + + if( dvd->css_state == 1 /* Need key init */ ) { + initAllCSSKeys( dvd ); + dvd->css_state = 2; + } + /* + if( dvdinput_title( dvd_file->dvd->dev, (int)start ) < 0 ) { + fprintf( stderr, "libdvdread: Error cracking CSS key for %s\n", + filename ); + } + */ + + return dvd_file; +} + +static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *dvd, int title, int menu ) +{ + char filename[ MAX_UDF_FILE_NAME_LEN ]; + char full_path[ PATH_MAX + 1 ]; + struct stat fileinfo; + dvd_file_t *dvd_file; + int i; + + dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) ); + if( !dvd_file ) return NULL; + dvd_file->dvd = dvd; + /*Hack*/ dvd_file->css_title = title << 1 | menu; + dvd_file->lb_start = 0; + dvd_file->seek_pos = 0; + memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) ); + memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) ); + dvd_file->filesize = 0; + +#ifdef WITH_CACHE + dvd_file->lb_cache = -1; +#endif + + if( menu ) { + dvd_input_t dev; + + if( title == 0 ) { + sprintf( filename, "VIDEO_TS.VOB" ); + } else { + sprintf( filename, "VTS_%02i_0.VOB", title ); + } + if( !findDVDFile( dvd, filename, full_path ) ) { + free( dvd_file ); + return NULL; + } + + dev = dvdinput_open( full_path ); + if( dev == NULL ) { + free( dvd_file ); + return NULL; + } + + if( stat( full_path, &fileinfo ) < 0 ) { + fprintf( stderr, "libdvdread: Can't stat() %s.\n", 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 { + for( i = 0; i < TITLES_MAX; ++i ) { + + sprintf( filename, "VTS_%02i_%i.VOB", title, i + 1 ); + if( !findDVDFile( dvd, filename, full_path ) ) { + break; + } + + if( stat( full_path, &fileinfo ) < 0 ) { + fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename ); + break; + } + + dvd_file->title_sizes[ i ] = fileinfo.st_size / DVD_VIDEO_LB_LEN; + dvd_file->title_devs[ i ] = dvdinput_open( full_path ); + 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 *dvd, int titlenum, + dvd_read_domain_t domain ) +{ + char filename[ MAX_UDF_FILE_NAME_LEN ]; + + /* Check arguments. */ + if( dvd == NULL || titlenum < 0 ) + return NULL; + + switch( domain ) { + case DVD_READ_INFO_FILE: + if( titlenum == 0 ) { + sprintf( 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 ) { + sprintf( 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 DVDOpenVOBUDF( dvd, titlenum, 1 ); + } else { + return DVDOpenVOBPath( dvd, titlenum, 1 ); + } + break; + case DVD_READ_TITLE_VOBS: + if( titlenum == 0 ) return 0; + if( dvd->isImageFile ) { + return DVDOpenVOBUDF( dvd, titlenum, 0 ); + } else { + return DVDOpenVOBPath( dvd, titlenum, 0 ); + } + break; + default: + fprintf( stderr, "libdvdread: Invalid domain for file open.\n" ); + return NULL; + } + + if( dvd->isImageFile ) { + return DVDOpenFileUDF( dvd, filename ); + } else { + return DVDOpenFilePath( dvd, filename ); + } +} + +void DVDCloseFile( dvd_file_t *dvd_file ) +{ + int i; + + if( dvd_file ) { + if( dvd_file->dvd->isImageFile ) { + ; + } else { + for( i = 0; i < TITLES_MAX; ++i ) { + if( dvd_file->title_devs[ i ] ) { + dvdinput_close( dvd_file->title_devs[i] ); + } + } + } + + free( dvd_file ); + dvd_file = 0; + } +} + +/* Internal, but used from dvd_udf.c */ +int UDFReadBlocksRaw( dvd_reader_t *device, uint32_t lb_number, + size_t block_count, unsigned char *data, + int encrypted ) +{ + int ret; + if( !device->dev ) { + fprintf( stderr, "libdvdread: Fatal error in block read.\n" ); + return 0; + } + + ret = dvdinput_seek( device->dev, (int) lb_number ); + if( ret != (int) lb_number ) { + fprintf( stderr, "libdvdread: Can't seek to block %u\n", lb_number ); + return 0; + } + + ret = dvdinput_read( device->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( dvd_file_t *dvd_file, uint32_t offset, + size_t block_count, unsigned char *data, + int encrypted ) +{ + return UDFReadBlocksRaw( dvd_file->dvd, 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( dvd_file_t *dvd_file, unsigned int offset, + size_t block_count, unsigned char *data, + int encrypted ) +{ + 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 ) { + fprintf( stderr, "libdvdread: Can't seek to block %d\n", + 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 ) { + fprintf( stderr, "libdvdread: Can't seek to block %d\n", + 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 ) { + fprintf( stderr, "libdvdread: Can't seek to block %d\n", + 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; +} + +#ifdef WITH_CACHE + +/* returns true aslong as the sector isn't all zeros */ +inline int DVDCheckSector(unsigned char *data, int offset) +{ + int i = 0; + int32_t *p = (int32_t*)data + (DVD_VIDEO_LB_LEN>>2)*offset; + for(;i<(DVD_VIDEO_LB_LEN<<2);i++) { + if(*(p+i) != 0) + break; + } + return (i!=(DVD_VIDEO_LB_LEN>>2)); +} + +int DVDReadBlocksCached( dvd_file_t *dvd_file, int offset, + size_t block_count, unsigned char *data, int encrypted ) +{ + int ret=0; + /* Check arguments. */ + if( dvd_file == NULL || offset < 0 || data == NULL ) + return -1; + + if(encrypted & DVDINPUT_READ_DECRYPT) { + /* Hack, and it will still fail for multiple opens in a threaded app ! */ + if( dvd_file->dvd->css_title != dvd_file->css_title ) { + dvd_file->dvd->css_title = dvd_file->css_title; + if( dvd_file->dvd->isImageFile ) { + dvdinput_title( dvd_file->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 ); + }*/ + } + } + + /* check if first sector is in cache */ + int cachehit = 0; + if( offset == dvd_file->lb_cache ) { + memcpy( data, dvd_file->cache, DVD_VIDEO_LB_LEN ); + block_count--; + offset++; + data+=DVD_VIDEO_LB_LEN; + cachehit = 1; + } + + + if( block_count > 0 ) + { + if( dvd_file->dvd->isImageFile ) + ret = DVDReadBlocksUDF( dvd_file, (uint32_t)offset, + block_count, data, encrypted ); + else + ret = DVDReadBlocksPath( dvd_file, (unsigned int)offset, + block_count, data, encrypted ); + + if(ret<0) + return ret; + + /* here is a hack for drive wich don't handle layerchange properly */ + /* they start returning zero data while laser is shifting position */ + /* normally just doing a reread will get the correct data */ + if( dvd_file->dvd->isImageFile ) + { + /* check sectors from the back */ + int count = ret; /* previous call could have returned fewer than requested */ + int i = count-1; + for(;i>=0;i--) + if(!DVDCheckSector(data, i)) break; + + if(i>=0) { + fprintf( stderr, "libdvdread: potential layer change. %d zero sectors detected starting at %d!\n", i+1, offset); + + /* reread the invalid sectors */ + count = DVDReadBlocksUDF( dvd_file, (uint32_t)offset+i, + count-i, data+DVD_VIDEO_LB_LEN*i, encrypted ); + + if(count<0) + return count; + } + } + + } + + if(ret>0) + { /* store last sector read into cache */ + dvd_file->lb_cache = offset+ret-1; + memcpy( dvd_file->cache, data+(DVD_VIDEO_LB_LEN*(ret-1)), DVD_VIDEO_LB_LEN ); + } + + return (ssize_t)(ret+cachehit); +} +#endif + +/* 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 ) +{ + int ret; + /* Check arguments. */ + if( dvd_file == NULL || offset < 0 || data == NULL ) + return -1; + +#ifdef WITH_CACHE + return (ssize_t)DVDReadBlocksCached( dvd_file, offset, block_count, data, DVDINPUT_READ_DECRYPT ); +#endif + + /* Hack, and it will still fail for multiple opens in a threaded app ! */ + if( dvd_file->dvd->css_title != dvd_file->css_title ) { + dvd_file->dvd->css_title = dvd_file->css_title; + if( dvd_file->dvd->isImageFile ) { + dvdinput_title( dvd_file->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_file->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) +{ + /* Check arguments. */ + if( dvd_file == NULL || offset <= 0 ) + return -1; + + if( dvd_file->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; + fprintf(stderr, "libdvdread: Ignored size of file indicated in UDF.\n"); + } + } + + 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 ) +{ + unsigned char *secbuf_base, *secbuf; + unsigned int numsec, seek_sector, seek_byte; + int ret; + + /* Check arguments. */ + if( dvd_file == NULL || data == NULL ) + 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 = (unsigned char *) malloc( numsec * DVD_VIDEO_LB_LEN + 2048 ); + secbuf = (unsigned char *)(((uintptr_t)secbuf_base & ~((uintptr_t)2047)) + 2048); + if( !secbuf_base ) { + fprintf( stderr, "libdvdread: Can't allocate memory " + "for file read!\n" ); + return 0; + } + +#ifdef WITH_CACHE + ret = DVDReadBlocksCached( dvd_file, (uint32_t) seek_sector, + (size_t) numsec, secbuf, DVDINPUT_NOFLAGS ); +#else + if( dvd_file->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 ); + } +#endif + + 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_ctx ctx; + int title; + int nr_of_files = 0; + + /* Check arguments. */ + if( dvd == NULL || discid == NULL ) + return 0; + + /* Go through the first 10 IFO:s, in order, + * and md5sum them, i.e VIDEO_TS.IFO and VTS_0?_0.IFO */ + md5_init_ctx( &ctx ); + for( title = 0; title < 10; title++ ) { + dvd_file_t *dvd_file = DVDOpenFile( dvd, title, DVD_READ_INFO_FILE ); + if( dvd_file != NULL ) { + ssize_t bytes_read; + size_t file_size = dvd_file->filesize * DVD_VIDEO_LB_LEN; + char *buffer_base = malloc( file_size + 2048 ); + char *buffer = (char *)(((uintptr_t)buffer_base & ~((uintptr_t)2047)) + 2048); + + if( buffer_base == NULL ) { + DVDCloseFile( dvd_file ); + fprintf( stderr, "libdvdread: DVDDiscId, failed to " + "allocate memory for file read!\n" ); + return -1; + } + bytes_read = DVDReadBytes( dvd_file, buffer, file_size ); + if( bytes_read != file_size ) { + fprintf( stderr, "libdvdread: DVDDiscId read returned %zd bytes" + ", wanted %zd\n", bytes_read, file_size ); + DVDCloseFile( dvd_file ); + free( buffer_base ); + return -1; + } + + md5_process_bytes( buffer, file_size, &ctx ); + + DVDCloseFile( dvd_file ); + free( buffer_base ); + nr_of_files++; + } + } + md5_finish_ctx( &ctx, discid ); + if(!nr_of_files) + return -1; + + return 0; +} + + +int DVDISOVolumeInfo( dvd_reader_t *dvd, + char *volid, unsigned int volid_size, + unsigned char *volsetid, unsigned int volsetid_size ) +{ + 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 ); + buffer = (unsigned char *)(((uintptr_t)buffer_base & ~((uintptr_t)2047)) + 2048); + + if( buffer_base == NULL ) { + fprintf( stderr, "libdvdread: DVDISOVolumeInfo, failed to " + "allocate memory for file read!\n" ); + return -1; + } + + ret = UDFReadBlocksRaw( dvd, 16, 1, buffer, 0 ); + if( ret != 1 ) { + fprintf( stderr, "libdvdread: DVDISOVolumeInfo, failed to " + "read ISO9660 Primary Volume Descriptor!\n" ); + 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 *dvd, + char *volid, unsigned int volid_size, + unsigned char *volsetid, unsigned int volsetid_size ) +{ + int ret; + /* Check arguments. */ + if( dvd == NULL ) + return -1; + + if( dvd->dev == NULL ) { + /* No block access, so no UDF VolumeSet Identifier */ + return -1; + } + + if( (volid != NULL) && (volid_size > 0) ) { + ret = UDFGetVolumeIdentifier(dvd, volid, volid_size); + if(!ret) { + return -1; + } + } + if( (volsetid != NULL) && (volsetid_size > 0) ) { + ret = UDFGetVolumeSetIdentifier(dvd, volsetid, volsetid_size); + if(!ret) { + return -1; + } + } + + return 0; +} diff --git a/lib/libdvd/libdvdread/src/dvd_reader.h b/lib/libdvd/libdvdread/src/dvd_reader.h new file mode 100644 index 0000000000..8c91242c98 --- /dev/null +++ b/lib/libdvd/libdvdread/src/dvd_reader.h @@ -0,0 +1,275 @@ +#ifndef DVD_READER_H_INCLUDED +#define DVD_READER_H_INCLUDED + +/* + * Copyright (C) 2001, 2002 Billy Biggs <vektor@dumbterm.net>, + * Håkan Hjort <d95hjort@dtek.chalmers.se>, + * Björn Englund <d4bjorn@dtek.chalmers.se> + * + * 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 + */ + +#ifdef _MSC_VER +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#endif + +#include <sys/types.h> +#include <inttypes.h> + +/** + * The DVD access interface. + * + * This file contains the functions that form the interface to to + * reading files located on a DVD. + */ + +/** + * The current version. + */ +#define DVDREAD_VERSION 904 + +/** + * 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; + +/** + * Opaque type for a file read handle, much like a normal fd or FILE *. + */ +typedef struct dvd_file_s dvd_file_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. + * + * 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 the device, file or directory to be used. + * @return If successful a a read handle is returned. Otherwise 0 is returned. + * + * dvd = DVDOpen(path); + */ +dvd_reader_t *DVDOpen( const char * ); + +/** + * 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; + +/** + * 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 currrent 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 0 * + * * 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 /* DVD_READER_H_INCLUDED */ diff --git a/lib/libdvd/libdvdread/src/dvd_udf.c b/lib/libdvd/libdvdread/src/dvd_udf.c new file mode 100644 index 0000000000..26a663a1c9 --- /dev/null +++ b/lib/libdvd/libdvdread/src/dvd_udf.c @@ -0,0 +1,968 @@ +/* + * This code is based on dvdudf by: + * Christian Wolff <scarabaeus@convergence.de>. + * + * Modifications by: + * Billy Biggs <vektor@dumbterm.net>. + * Björn Englund <d4bjorn@dtek.chalmers.se>. + * + * 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 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. Or, point your browser to + * http://www.gnu.org/copyleft/gpl.html + */ + +#include "config.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <inttypes.h> + +#include "dvd_reader.h" +#include "dvd_udf.h" + +/* Private but located in/shared with dvd_reader.c */ +extern int UDFReadBlocksRaw( dvd_reader_t *device, uint32_t lb_number, + size_t block_count, unsigned char *data, + int encrypted ); + +/* It's required to either fail or deliver all the blocks asked for. */ +static int DVDReadLBUDF( dvd_reader_t *device, uint32_t lb_number, + size_t block_count, unsigned char *data, + int encrypted ) +{ + int ret; + size_t count = block_count; + + while(count > 0) { + ret = UDFReadBlocksRaw(device, lb_number, count, data, 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; + char VolumeDesc[128]; + 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 *device, UDFCacheType type, + uint32_t nr, void *data) +{ + int n; + struct udf_cache *c; + + if(DVDUDFCacheLevel(device, -1) <= 0) + return 0; + + c = (struct udf_cache *)GetUDFCacheHandle(device); + + 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 *device, UDFCacheType type, + uint32_t nr, void *data) +{ + int n; + struct udf_cache *c; + void *tmp; + + if(DVDUDFCacheLevel(device, -1) <= 0) + return 0; + + c = (struct udf_cache *)GetUDFCacheHandle(device); + + if(c == NULL) { + c = calloc(1, sizeof(struct udf_cache)); + /* fprintf(stderr, "calloc: %d\n", sizeof(struct udf_cache)); */ + if(c == NULL) + return 0; + SetUDFCacheHandle(device, 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)); + /* + fprintf(stderr, "realloc lb: %d * %d = %d\n", + 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)); + /* + fprintf(stderr, "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 endianess */ +#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; + + if( ( data[ 0 ] == 8 ) || ( data[ 0 ] == 16 ) ) do { + if( data[ 0 ] == 16 ) p++; /* Ignore MSB of unicode16 */ + if( p < len ) { + target[ i++ ] = data[ p++ ]; + } + } while( p < len ); + + target[ i ] = '\0'; + return 0; +} + +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, char *VolumeDescriptor ) +{ + uint32_t lbsize, MT_L, N_PM; + Unicodedecode(&data[84], 128, VolumeDescriptor); + 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; + + 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 ); + p = 176 + L_EA; + while( p < 176 + L_EA + L_AD ) { + switch( flags & 0x0007 ) { + case 0: UDFShortAD( &data[ p ], ad, partition ); p += 8; break; + case 1: 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) Unicodedecode(&data[38 + L_IU], L_FI, FileName); + 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 *device, 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; + + lbnum = partition->Start + ICB.Location; + tmpmap.lbn = lbnum; + if(GetUDFCache(device, MapCache, lbnum, &tmpmap)) { + *FileType = tmpmap.filetype; + memcpy(File, &tmpmap.file, sizeof(tmpmap.file)); + return 1; + } + + do { + if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <= 0 ) + TagID = 0; + else + UDFDescriptor( LogBlock, &TagID ); + + if( TagID == 261 ) { + UDFFileEntry( LogBlock, FileType, partition, File ); + memcpy(&tmpmap.file, File, sizeof(tmpmap.file)); + tmpmap.filetype = *FileType; + SetUDFCache(device, MapCache, tmpmap.lbn, &tmpmap); + return 1; + }; + } while( ( lbnum <= partition->Start + ICB.Location + ( ICB.Length - 1 ) + / DVD_VIDEO_LB_LEN ) && ( TagID != 261 ) ); + + 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 *device, 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 found = 0; + int in_cache = 0; + + /* Scan dir for ICB of file */ + lbnum = partition->Start + Dir.Location; + + if(DVDUDFCacheLevel(device, -1) > 0) { + /* caching */ + + if(!GetUDFCache(device, 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); + if( DVDReadLBUDF( device, lbnum, dir_lba, cached_dir, 0) <= 0 ) { + free(cached_dir_base); + cached_dir_base = NULL; + cached_dir = NULL; + } + /* + if(cached_dir) { + fprintf(stderr, "malloc dir: %d\n", dir_lba * DVD_VIDEO_LB_LEN); + } + */ + { + uint8_t *data[2]; + data[0] = cached_dir_base; + data[1] = cached_dir; + SetUDFCache(device, LBUDFCache, lbnum, data); + } + } else + in_cache = 1; + + if(cached_dir == NULL) + return 0; + + p = 0; + + while( p < Dir.Length ) { + UDFDescriptor( &cached_dir[ p ], &TagID ); + if( TagID == 257 ) { + 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; + } + UDFMapICB(device, tmpICB, &tmpFiletype, partition, &tmpFile); + } 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( device, 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( device, lbnum, 2, directory, 0 ) <= 0 ) { + return 0; + } + } + UDFDescriptor( &directory[ p ], &TagID ); + if( TagID == 257 ) { + p += UDFFileIdentifier( &directory[ p ], &filechar, + filename, FileICB ); + if( !strcasecmp( FileName, filename ) ) { + return 1; + } + } else + return 0; + } + + return 0; +} + + +static int UDFGetAVDP( dvd_reader_t *device, + 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; + + if(GetUDFCache(device, AVDPCache, 0, avdp)) + return 1; + + /* Find Anchor */ + lastsector = 0; + lbnum = 256; /* Try #1, prime anchor */ + terminate = 0; + + for(;;) { + if( DVDReadLBUDF( device, lbnum, 1, Anchor, 0 ) > 0 ) { + UDFDescriptor( Anchor, &TagID ); + } else { + TagID = 0; + } + if (TagID != 2) { + /* 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(device, 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 *device, 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; + struct avdp_t avdp; + + if(!UDFGetAVDP(device, &avdp)) + return 0; + + /* Main volume descriptor */ + MVDS_location = avdp.mvds.location; + MVDS_length = avdp.mvds.length; + + part->valid = 0; + volvalid = 0; + part->VolumeDesc[ 0 ] = '\0'; + i = 1; + do { + /* Find Volume Descriptor */ + lbnum = MVDS_location; + do { + + if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <= 0 ) + TagID = 0; + else + UDFDescriptor( LogBlock, &TagID ); + + if( ( TagID == 5 ) && ( !part->valid ) ) { + /* Partition Descriptor */ + UDFPartition( LogBlock, &part->Flags, &part->Number, + part->Contents, &part->Start, &part->Length ); + part->valid = ( partnum == part->Number ); + } else if( ( TagID == 6 ) && ( !volvalid ) ) { + /* Logical Volume Descriptor */ + if( UDFLogVolume( LogBlock, part->VolumeDesc ) ) { + /* TODO: sector size wrong! */ + } else + volvalid = 1; + } + + } while( ( lbnum <= MVDS_location + ( MVDS_length - 1 ) + / DVD_VIDEO_LB_LEN ) && ( TagID != 8 ) + && ( ( !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 *device, 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 ]; + char *token; + uint8_t filetype; + + *filesize = 0; + tokenline[0] = '\0'; + strncat(tokenline, filename, MAX_UDF_FILE_NAME_LEN - 1); + memset(&ICB, 0, sizeof(ICB)); + + if(!(GetUDFCache(device, PartitionCache, 0, &partition) && + GetUDFCache(device, RootICBCache, 0, &RootICB))) { + /* Find partition, 0 is the standard location for DVD Video.*/ + if( !UDFFindPartition( device, 0, &partition ) ) return 0; + SetUDFCache(device, PartitionCache, 0, &partition); + + /* Find root dir ICB */ + lbnum = partition.Start; + do { + if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <= 0 ) + TagID = 0; + else + UDFDescriptor( LogBlock, &TagID ); + + /* File Set Descriptor */ + if( TagID == 256 ) /* File Set Descriptor */ + UDFLongAD( &LogBlock[ 400 ], &RootICB ); + } while( ( lbnum < partition.Start + partition.Length ) + && ( TagID != 8 ) && ( TagID != 256 ) ); + + /* Sanity checks. */ + if( TagID != 256 ) return 0; + if( RootICB.Partition != 0 ) return 0; + SetUDFCache(device, RootICBCache, 0, &RootICB); + } + + /* Find root dir */ + if( !UDFMapICB( device, RootICB, &filetype, &partition, &File ) ) return 0; + if( filetype != 4 ) return 0; /* Root dir should be dir */ + + { + int cache_file_info = 0; + /* Tokenize filepath */ + token = strtok(tokenline, "/"); + while( token != NULL ) { + if( !UDFScanDir( device, File, token, &partition, &ICB, + cache_file_info)) + return 0; + if( !UDFMapICB( device, 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 *device, int id, + uint8_t *descriptor, int bufsize) +{ + uint32_t lbnum, MVDS_location, MVDS_length; + struct avdp_t avdp; + uint16_t TagID; + uint32_t lastsector; + int i, terminate; + int desc_found = 0; + /* Find Anchor */ + lastsector = 0; + lbnum = 256; /* Try #1, prime anchor */ + terminate = 0; + if(bufsize < DVD_VIDEO_LB_LEN) + return 0; + + if(!UDFGetAVDP(device, &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 { + if( DVDReadLBUDF( device, lbnum++, 1, descriptor, 0 ) <= 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 != 8 ) + && ( !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 *device, 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(device, PVDCache, 0, pvd)) + return 1; + + if(!UDFGetDescriptor( device, 1, pvd_buf, sizeof(pvd_buf))) + return 0; + + memcpy(pvd->VolumeIdentifier, &pvd_buf[24], 32); + memcpy(pvd->VolumeSetIdentifier, &pvd_buf[72], 128); + SetUDFCache(device, 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 *device, char *volid, + unsigned int volid_size) +{ + struct pvd_t pvd; + unsigned int volid_len; + + /* get primary volume descriptor */ + if(!UDFGetPVD(device, &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 *device, uint8_t *volsetid, + unsigned int volsetid_size) +{ + struct pvd_t pvd; + + /* get primary volume descriptor */ + if(!UDFGetPVD(device, &pvd)) + return 0; + + + if(volsetid_size > 128) + volsetid_size = 128; + + memcpy(volsetid, pvd.VolumeSetIdentifier, volsetid_size); + return 128; +} diff --git a/lib/libdvd/libdvdread/src/dvd_udf.h b/lib/libdvd/libdvdread/src/dvd_udf.h new file mode 100644 index 0000000000..3f38e8070c --- /dev/null +++ b/lib/libdvd/libdvdread/src/dvd_udf.h @@ -0,0 +1,62 @@ +#ifndef DVD_UDF_H_INCLUDED +#define DVD_UDF_H_INCLUDED + +/* + * This code is based on dvdudf by: + * Christian Wolff <scarabaeus@convergence.de>. + * + * Modifications by: + * Billy Biggs <vektor@dumbterm.net>. + * Björn Englund <d4bjorn@dtek.chalmers.se>. + * + * 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 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. Or, point your browser to + * http://www.gnu.org/copyleft/gpl.html + */ + +#include <inttypes.h> + +#include "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 *device, char *filename, uint32_t *size ); + +void FreeUDFCache(void *cache); +int UDFGetVolumeIdentifier(dvd_reader_t *device, + char *volid, unsigned int volid_size); +int UDFGetVolumeSetIdentifier(dvd_reader_t *device, + uint8_t *volsetid, unsigned int volsetid_size); +void *GetUDFCacheHandle(dvd_reader_t *device); +void SetUDFCacheHandle(dvd_reader_t *device, void *cache); + +#ifdef __cplusplus +}; +#endif +#endif /* DVD_UDF_H_INCLUDED */ diff --git a/lib/libdvd/libdvdread/src/dvdread_internal.h b/lib/libdvd/libdvdread/src/dvdread_internal.h new file mode 100644 index 0000000000..ed9fd0f7a9 --- /dev/null +++ b/lib/libdvd/libdvdread/src/dvdread_internal.h @@ -0,0 +1,15 @@ +#ifndef DVDREAD_INTERNAL_H +#define DVDREAD_INTERNAL_H + +#ifdef _MSC_VER +#include <unistd.h> +#endif /* _MSC_VER */ + +#define CHECK_VALUE(arg) \ + if(!(arg)) { \ + fprintf(stderr, "\n*** libdvdread: CHECK_VALUE failed in %s:%i ***" \ + "\n*** for %s ***\n\n", \ + __FILE__, __LINE__, # arg ); \ + } + +#endif /* DVDREAD_INTERNAL_H */ diff --git a/lib/libdvd/libdvdread/src/ifo_print.c b/lib/libdvd/libdvdread/src/ifo_print.c new file mode 100644 index 0000000000..fd1e7edb1d --- /dev/null +++ b/lib/libdvd/libdvdread/src/ifo_print.c @@ -0,0 +1,1251 @@ +/* + * 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 + * + * $Id: ifo_print.c 1135 2008-09-06 21:55:51Z rathann $ + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <inttypes.h> +#include <string.h> +#include <ctype.h> +#include <assert.h> + +#include "ifo_types.h" +#include "ifo_read.h" +#include "ifo_print.h" + +/* Put this in some other file / package? It's used in nav_print too. */ +static void ifo_print_time(int level, 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(5, 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(int level, 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->unknown1 == 0 + && attr->line21_cc_1 == 0 + && attr->line21_cc_2 == 0 + && attr->video_format == 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 allways 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), "); + } + + printf("U%x, ", attr->unknown1); + assert(!attr->unknown1); + + 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 + } +} + +static void ifo_print_audio_attributes(int level, 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->channels == 0 + && attr->lang_extension == 0 + && attr->unknown1 == 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 "); + 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 + assert(attr->lang_code == 0 || attr->lang_code == 0xffff); + 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 imparied + 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("%d ", attr->unknown1); + printf("%d ", attr->unknown3); +} + +static void ifo_print_subp_attributes(int level, subp_attr_t *attr) { + + if(attr->type == 0 + && attr->lang_code == 0 + && attr->zero1 == 0 + && attr->zero2 == 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 ifo_print_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"); + } +} + + +void ifo_print_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(5, &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(5, &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(5, &vmgi_mat->vmgm_subp_attr); + printf("\n"); + } +} + + +void ifo_print_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(5, &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(5, &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(5, &vtsi_mat->vtsm_subp_attr); + printf("\n"); + } + + printf("Video attributes of VTS_VOBS: "); + ifo_print_video_attributes(5, &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(5, &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(5, &vtsi_mat->vts_subp_attr[i]); + printf("\n"); + } +} + + +static void ifo_print_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 ifo_print_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 ifo_print_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;i<nr;i++) { + printf("Cell: %3i ", i + 1); + + dvdread_print_time(&cell_playback[i].playback_time); + printf("\t"); + + if(cell_playback[i].block_mode || cell_playback[i].block_type) { + const char *s; + switch(cell_playback[i].block_mode) { + case 0: + s = "not a"; break; + case 1: + s = "the first"; break; + case 2: + default: + s = ""; break; + case 3: + s = "last"; break; + } + printf("%s cell in the block ", s); + + switch(cell_playback[i].block_type) { + case 0: + printf("not part of the block "); + break; + case 1: + printf("angle block "); + break; + case 2: + case 3: + printf("(send bug repport) "); + break; + } + } + if(cell_playback[i].seamless_play) + printf("presented seamlessly "); + if(cell_playback[i].interleaved) + printf("cell is interleaved "); + if(cell_playback[i].stc_discontinuity) + printf("STC_discontinuty "); + if(cell_playback[i].seamless_angle) + printf("only seamless angle "); + if(cell_playback[i].playback_mode) + printf("only still VOBUs "); + if(cell_playback[i].restricted) + printf("restricted cell "); + if(cell_playback[i].unknown2) + printf("Unknown 0x%x ", cell_playback[i].unknown2); + if(cell_playback[i].still_time) + printf("still time %d ", cell_playback[i].still_time); + if(cell_playback[i].cell_cmd_nr) + printf("cell command %d", cell_playback[i].cell_cmd_nr); + + printf("\n\tStart sector: %08x\tFirst ILVU end sector: %08x\n", + cell_playback[i].first_sector, + cell_playback[i].first_ilvu_end_sector); + printf("\tEnd sector: %08x\tLast VOBU start sector: %08x\n", + cell_playback[i].last_sector, + cell_playback[i].last_vobu_start_sector); + } +} + +static void ifo_print_CELL_POSITION(cell_position_t *cell_position, int nr) { + int i; + + if(cell_position == NULL) { + printf("No Cell Position info present\n"); + return; + } + + for(i=0;i<nr;i++) { + printf("Cell: %3i has VOB ID: %3i, Cell ID: %3i\n", i + 1, + cell_position[i].vob_id_nr, cell_position[i].cell_nr); + } +} + + +void ifo_print_PGC(pgc_t *pgc) { + int i; + + if (!pgc) { + printf("None\n"); + return; + } + printf("Number of Programs: %i\n", pgc->nr_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: "); + ifo_print_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]); + } + } + + /* Memmory offsets to div. tables. */ + ifo_print_PGC_COMMAND_TBL(pgc->command_tbl); + ifo_print_PGC_PROGRAM_MAP(pgc->program_map, pgc->nr_of_programs); + ifo_print_CELL_PLAYBACK(pgc->cell_playback, pgc->nr_of_cells); + ifo_print_CELL_POSITION(pgc->cell_position, pgc->nr_of_cells); +} + + +void ifo_print_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;i<tt_srpt->nr_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" : "Sequencial"); + 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:%d\n", tt_srpt->title[i].pb_ty.title_or_time_play); + printf("\t\tChapter search or play:%d\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); + } +} + + +void ifo_print_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;i<vts_ptt_srpt->nr_of_srpts;i++) { + for(j=0;j<vts_ptt_srpt->title[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++); +} + +void ifo_print_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"); + } + } +} + +void ifo_print_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" : ""); + } + } +} + +void ifo_print_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); + } +} + + +void ifo_print_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]); + } +} + +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. */ +void ifo_print_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); + ifo_print_PGC(pgcit->pgci_srp[i].pgc); + } +} + + +void ifo_print_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"); + ifo_print_PGCIT(pgci_ut->lu[i].pgcit, 1); + } +} + + +static void ifo_print_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(5, &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(5, &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(5, &vts_attributes->vtsm_subp_attr); + printf("\n"); + } + + printf("Video attributes of VTSTT_VOBS: "); + ifo_print_video_attributes(5, &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(5, &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(5, &vts_attributes->vtstt_subp_attr[i]); + printf("\n"); + } +} + + +void ifo_print_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); + ifo_print_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) { + fprintf(stderr, "Can't open info file for title %d\n", title); + return; + } + + + if(ifohandle->vmgi_mat) { + + printf("VMG top level\n-------------\n"); + ifo_print_VMGI_MAT(ifohandle->vmgi_mat); + + printf("\nFirst Play PGC\n--------------\n"); + if(ifohandle->first_play_pgc) + ifo_print_PGC(ifohandle->first_play_pgc); + else + printf("No First Play PGC present\n"); + + printf("\nTitle Track search pointer table\n"); + printf( "------------------------------------------------\n"); + ifo_print_TT_SRPT(ifohandle->tt_srpt); + + printf("\nMenu PGCI Unit table\n"); + printf( "--------------------\n"); + if(ifohandle->pgci_ut) { + ifo_print_PGCI_UT(ifohandle->pgci_ut); + } else { + printf("No PGCI Unit table present\n"); + } + + printf("\nParental Manegment Information table\n"); + printf( "------------------------------------\n"); + if(ifohandle->ptl_mait) { + ifo_print_PTL_MAIT(ifohandle->ptl_mait); + } else { + printf("No Parental Management Information present\n"); + } + + printf("\nVideo Title Set Attribute Table\n"); + printf( "-------------------------------\n"); + ifo_print_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 Adress table\n"); + printf( "-----------------\n"); + if(ifohandle->menu_c_adt) { + ifo_print_C_ADT(ifohandle->menu_c_adt); + } else { + printf("No Menu Cell Adress table present\n"); + } + + printf("\nVideo Manager Menu VOBU address map\n"); + printf( "-----------------\n"); + if(ifohandle->menu_vobu_admap) { + ifo_print_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"); + ifo_print_VTSI_MAT(ifohandle->vtsi_mat); + + printf("\nPart of Title Track search pointer table\n"); + printf( "----------------------------------------------\n"); + ifo_print_VTS_PTT_SRPT(ifohandle->vts_ptt_srpt); + + printf("\nPGCI Unit table\n"); + printf( "--------------------\n"); + ifo_print_PGCIT(ifohandle->vts_pgcit, 0); + + printf("\nMenu PGCI Unit table\n"); + printf( "--------------------\n"); + if(ifohandle->pgci_ut) { + ifo_print_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) { + ifo_print_VTS_TMAPT(ifohandle->vts_tmapt); + } else { + printf("No VTS Time Map table present\n"); + } + + printf("\nMenu Cell Adress table\n"); + printf( "-----------------\n"); + if(ifohandle->menu_c_adt) { + ifo_print_C_ADT(ifohandle->menu_c_adt); + } else { + printf("No Cell Adress table present\n"); + } + + printf("\nVideo Title Set Menu VOBU address map\n"); + printf( "-----------------\n"); + if(ifohandle->menu_vobu_admap) { + ifo_print_VOBU_ADMAP(ifohandle->menu_vobu_admap); + } else { + printf("No Menu VOBU address map present\n"); + } + + printf("\nCell Adress table\n"); + printf( "-----------------\n"); + ifo_print_C_ADT(ifohandle->vts_c_adt); + + printf("\nVideo Title Set VOBU address map\n"); + printf( "-----------------\n"); + ifo_print_VOBU_ADMAP(ifohandle->vts_vobu_admap); + } + + ifoClose(ifohandle); +} + +/* + * $Log$ + * Revision 1.3 2004/10/22 11:36:19 jcdutton + * Stop seg fault when using ifo_dump. + * + * Revision 1.2 2004/09/27 12:24:01 jcdutton + * Add extra info to printout when using ifo_dump. + * + * Revision 1.1 2004/01/11 21:43:13 mroi + * big build system changes + * * cleaned up all Makefiles and added a Makefile.common + * * added relchk script + * * moved libdvdread files to a dvdread subdir + * * moved DVD VM to a vm subdir + * * removed unused code in read_cache.c + * + * Revision 1.4 2004/01/01 15:13:13 jcdutton + * Put ifo_print.c and .h back in. + * + * Revision 1.7 2003/04/28 15:17:17 jcdutton + * Update ifodump to work with new libdvdnav cvs, instead of needing libdvdread. + * + * Revision 1.6 2003/04/05 22:49:04 jcdutton + * Update with more info from the latest libdvdread. + * + * Revision 1.5 2003/04/05 13:03:49 jcdutton + * Small updates. + * + * Revision 1.4 2003/04/01 08:01:03 jcdutton + * Add VTS Time map display. Requires libdvdread 0.9.4. The same version that comes with xine. + * + * Revision 1.3 2003/03/14 15:49:18 mroi + * adjust to new libdvdread version + * + * Revision 1.2 2002/08/30 05:12:33 jcdutton + * Minor update now that I know what PGC Entry IDs are for. + * + * Revision 1.1.1.1 2002/08/28 09:48:35 jcdutton + * Initial import into CVS. + * + * + * + */ + diff --git a/lib/libdvd/libdvdread/src/ifo_print.h b/lib/libdvd/libdvdread/src/ifo_print.h new file mode 100644 index 0000000000..4c958f1c12 --- /dev/null +++ b/lib/libdvd/libdvdread/src/ifo_print.h @@ -0,0 +1,53 @@ +/* + * 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 + * + * $Id: ifo_print.h 1135 2008-09-06 21:55:51Z rathann $ + * + */ + +#ifndef IFO_PRINT_H_INCLUDED +#define IFO_PRINT_H_INCLUDED + +#include <inttypes.h> +#include "ifo_types.h" + +void ifo_print(dvd_reader_t *dvd, int title); +void dvdread_print_time(dvd_time_t *dtime); + +#endif /* IFO_PRINT_H_INCLUDED */ + +/* + * $Log$ + * Revision 1.1 2004/01/11 21:43:13 mroi + * big build system changes + * * cleaned up all Makefiles and added a Makefile.common + * * added relchk script + * * moved libdvdread files to a dvdread subdir + * * moved DVD VM to a vm subdir + * * removed unused code in read_cache.c + * + * Revision 1.4 2004/01/01 15:13:13 jcdutton + * Put ifo_print.c and .h back in. + * + * Revision 1.2 2003/04/28 15:17:17 jcdutton + * Update ifodump to work with new libdvdnav cvs, instead of needing libdvdread. + * + * Revision 1.1.1.1 2002/08/28 09:48:35 jcdutton + * Initial import into CVS. + * + * + * + */ + diff --git a/lib/libdvd/libdvdread/src/ifo_read.c b/lib/libdvd/libdvdread/src/ifo_read.c new file mode 100644 index 0000000000..a89d7f2273 --- /dev/null +++ b/lib/libdvd/libdvdread/src/ifo_read.c @@ -0,0 +1,2212 @@ +/* + * Copyright (C) 2000, 2001, 2002, 2003 + * Björn Englund <d4bjorn@dtek.chalmers.se>, + * Håkan Hjort <d95hjort@dtek.chalmers.se> + * + * 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 + */ + +#include "config.h" + +#include <stdio.h> +#include <stdlib.h> +#include <inttypes.h> +#include <string.h> + +#include "bswap.h" +#include "ifo_types.h" +#include "ifo_read.h" +#include "dvd_reader.h" +#include "dvdread_internal.h" +#include "bitreader.h" + +#ifndef DVD_BLOCK_LEN +#define DVD_BLOCK_LEN 2048 +#endif + +#ifndef NDEBUG +#define CHECK_ZERO0(arg) \ + if(arg != 0) { \ + fprintf(stderr, "*** Zero check failed in %s:%i\n for %s = 0x%x\n", \ + __FILE__, __LINE__, # arg, arg); \ + } +#define CHECK_ZERO(arg) \ + if(memcmp(my_friendly_zeros, &arg, sizeof(arg))) { \ + unsigned int i_CZ; \ + fprintf(stderr, "*** Zero check failed in %s:%i\n for %s = 0x", \ + __FILE__, __LINE__, # arg ); \ + for(i_CZ = 0; i_CZ < sizeof(arg); i_CZ++) \ + fprintf(stderr, "%02x", *((uint8_t *)&arg + i_CZ)); \ + fprintf(stderr, "\n"); \ + } +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->unknown1 = 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->playback_mode = dvdread_getbits(&state, 1); + cp->restricted = dvdread_getbits(&state, 1); + cp->unknown2 = dvdread_getbits(&state, 6); + 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); +} + +ifo_handle_t *ifoOpen(dvd_reader_t *dvd, int title) { + ifo_handle_t *ifofile; + + ifofile = (ifo_handle_t *)malloc(sizeof(ifo_handle_t)); + if(!ifofile) + return NULL; + + memset(ifofile, 0, sizeof(ifo_handle_t)); + + ifofile->file = DVDOpenFile(dvd, title, DVD_READ_INFO_FILE); + if(!ifofile->file) /* Should really catch any error and try to fallback */ + ifofile->file = DVDOpenFile(dvd, title, DVD_READ_INFO_BACKUP_FILE); + if(!ifofile->file) { + if(title) { + fprintf(stderr, "libdvdread: Can't open file VTS_%02d_0.IFO.\n", title); + } else { + fprintf(stderr, "libdvdread: Can't open file VIDEO_TS.IFO.\n"); + } + free(ifofile); + return NULL; + } + + /* 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)) { + fprintf(stderr, "libdvdread: Invalid main menu IFO (VIDEO_TS.IFO), ifoRead_FP_PGC() failed.\n"); + ifoClose(ifofile); + return NULL; + } + + ifoRead_PGCI_UT(ifofile); + ifoRead_PTL_MAIT(ifofile); + + /* This is also mandatory. */ + if(!ifoRead_VTS_ATRT(ifofile)) { + fprintf(stderr, "libdvdread: Invalid main menu IFO (VIDEO_TS.IFO), ifoRead_VTS_ATRT() failed.\n"); + ifoClose(ifofile); + return NULL; + } + + 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)) { + fprintf(stderr, "libdvdread: Invalid title IFO (VTS_%02d_0.IFO).\n", + title); + ifoClose(ifofile); + return NULL; + } + + + 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)) { + fprintf(stderr, "libdvdread: Invalid title IFO (VTS_%02d_0.IFO).\n", + title); + ifoClose(ifofile); + return NULL; + } + + return ifofile; + } + + if(title) { + fprintf(stderr, "libdvdread: Invalid IFO for title %d (VTS_%02d_0.IFO).\n", + title, title); + } else { + fprintf(stderr, "libdvdread: Invalid IFO for VMGM (VIDEO_TS.IFO).\n"); + } + ifoClose(ifofile); + return NULL; +} + + +ifo_handle_t *ifoOpenVMGI(dvd_reader_t *dvd) { + ifo_handle_t *ifofile; + + ifofile = (ifo_handle_t *)malloc(sizeof(ifo_handle_t)); + if(!ifofile) + return NULL; + + memset(ifofile, 0, sizeof(ifo_handle_t)); + + ifofile->file = DVDOpenFile(dvd, 0, DVD_READ_INFO_FILE); + if(!ifofile->file) /* Should really catch any error and try to fallback */ + ifofile->file = DVDOpenFile(dvd, 0, DVD_READ_INFO_BACKUP_FILE); + if(!ifofile->file) { + fprintf(stderr, "libdvdread: Can't open file VIDEO_TS.IFO.\n"); + free(ifofile); + return NULL; + } + + if(ifoRead_VMG(ifofile)) + return ifofile; + + fprintf(stderr, "libdvdread,ifoOpenVMGI(): Invalid main menu IFO (VIDEO_TS.IFO).\n"); + ifoClose(ifofile); + return NULL; +} + + +ifo_handle_t *ifoOpenVTSI(dvd_reader_t *dvd, int title) { + ifo_handle_t *ifofile; + + ifofile = (ifo_handle_t *)malloc(sizeof(ifo_handle_t)); + if(!ifofile) + return NULL; + + memset(ifofile, 0, sizeof(ifo_handle_t)); + + if(title <= 0 || title > 99) { + fprintf(stderr, "libdvdread: ifoOpenVTSI invalid title (%d).\n", title); + free(ifofile); + return NULL; + } + + ifofile->file = DVDOpenFile(dvd, title, DVD_READ_INFO_FILE); + if(!ifofile->file) /* Should really catch any error and try to fallback */ + ifofile->file = DVDOpenFile(dvd, title, DVD_READ_INFO_BACKUP_FILE); + if(!ifofile->file) { + fprintf(stderr, "libdvdread: Can't open file VTS_%02d_0.IFO.\n", title); + free(ifofile); + return NULL; + } + + ifoRead_VTS(ifofile); + if(ifofile->vtsi_mat) + return ifofile; + + fprintf(stderr, "libdvdread: Invalid IFO for title %d (VTS_%02d_0.IFO).\n", + title, title); + ifoClose(ifofile); + 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); + + DVDCloseFile(ifofile->file); + ifofile->file = 0; + free(ifofile); + ifofile = 0; +} + + +static int ifoRead_VMG(ifo_handle_t *ifofile) { + vmgi_mat_t *vmgi_mat; + + vmgi_mat = (vmgi_mat_t *)malloc(sizeof(vmgi_mat_t)); + if(!vmgi_mat) + return 0; + + ifofile->vmgi_mat = vmgi_mat; + + if(!DVDFileSeek_(ifofile->file, 0)) { + free(ifofile->vmgi_mat); + ifofile->vmgi_mat = 0; + return 0; + } + + if(!DVDReadBytes(ifofile->file, vmgi_mat, sizeof(vmgi_mat_t))) { + free(ifofile->vmgi_mat); + ifofile->vmgi_mat = 0; + return 0; + } + + if(strncmp("DVDVIDEO-VMG", vmgi_mat->vmg_identifier, 12) != 0) { + free(ifofile->vmgi_mat); + ifofile->vmgi_mat = 0; + 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); + 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) { + vtsi_mat_t *vtsi_mat; + int i; + + vtsi_mat = (vtsi_mat_t *)malloc(sizeof(vtsi_mat_t)); + if(!vtsi_mat) + return 0; + + ifofile->vtsi_mat = vtsi_mat; + + if(!DVDFileSeek_(ifofile->file, 0)) { + free(ifofile->vtsi_mat); + ifofile->vtsi_mat = 0; + return 0; + } + + if(!(DVDReadBytes(ifofile->file, vtsi_mat, sizeof(vtsi_mat_t)))) { + free(ifofile->vtsi_mat); + ifofile->vtsi_mat = 0; + return 0; + } + + if(strncmp("DVDVIDEO-VTS", vtsi_mat->vts_identifier, 12) != 0) { + free(ifofile->vtsi_mat); + ifofile->vtsi_mat = 0; + 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) { + + memset(cmd_tbl, 0, sizeof(pgc_command_tbl_t)); + + if(!DVDFileSeek_(ifofile->file, offset)) + return 0; + + if(!(DVDReadBytes(ifofile->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); + + CHECK_VALUE(cmd_tbl->nr_of_pre + cmd_tbl->nr_of_post + cmd_tbl->nr_of_cell<= 255); + + if(cmd_tbl->nr_of_pre != 0) { + unsigned int pre_cmds_size = cmd_tbl->nr_of_pre * COMMAND_DATA_SIZE; + cmd_tbl->pre_cmds = (vm_cmd_t *)malloc(pre_cmds_size); + if(!cmd_tbl->pre_cmds) + return 0; + + if(!(DVDReadBytes(ifofile->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 = (vm_cmd_t *)malloc(post_cmds_size); + if(!cmd_tbl->post_cmds) { + if(cmd_tbl->pre_cmds) + free(cmd_tbl->pre_cmds); + return 0; + } + if(!(DVDReadBytes(ifofile->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 = (vm_cmd_t *)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(ifofile->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) { + unsigned int size = nr * sizeof(pgc_program_map_t); + + if(!DVDFileSeek_(ifofile->file, offset)) + return 0; + + if(!(DVDReadBytes(ifofile->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) { + unsigned int i; + unsigned int size = nr * sizeof(cell_playback_t); + + if(!DVDFileSeek_(ifofile->file, offset)) + return 0; + + if(!(DVDReadBytes(ifofile->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) { + unsigned int i; + unsigned int size = nr * sizeof(cell_position_t); + + if(!DVDFileSeek_(ifofile->file, offset)) + return 0; + + if(!(DVDReadBytes(ifofile->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) { + unsigned int i; + + if(!DVDFileSeek_(ifofile->file, offset)) + return 0; + + if(!(DVDReadBytes(ifofile->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 = malloc(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)) { + free(pgc->command_tbl); + return 0; + } + } else { + pgc->command_tbl = NULL; + } + + if(pgc->program_map_offset != 0 && pgc->nr_of_programs>0) { + pgc->program_map = malloc(pgc->nr_of_programs * sizeof(pgc_program_map_t)); + if(!pgc->program_map) { + ifoFree_PGC_COMMAND_TBL(pgc->command_tbl); + return 0; + } + if(!ifoRead_PGC_PROGRAM_MAP(ifofile, pgc->program_map,pgc->nr_of_programs, + offset + pgc->program_map_offset)) { + ifoFree_PGC_COMMAND_TBL(pgc->command_tbl); + free(pgc->program_map); + return 0; + } + } else { + pgc->program_map = NULL; + } + + if(pgc->cell_playback_offset != 0 && pgc->nr_of_cells>0) { + pgc->cell_playback = malloc(pgc->nr_of_cells * sizeof(cell_playback_t)); + if(!pgc->cell_playback) { + ifoFree_PGC_COMMAND_TBL(pgc->command_tbl); + if(pgc->program_map) + free(pgc->program_map); + return 0; + } + if(!ifoRead_CELL_PLAYBACK_TBL(ifofile, pgc->cell_playback, + pgc->nr_of_cells, + offset + pgc->cell_playback_offset)) { + ifoFree_PGC_COMMAND_TBL(pgc->command_tbl); + if(pgc->program_map) + free(pgc->program_map); + free(pgc->cell_playback); + return 0; + } + } else { + pgc->cell_playback = NULL; + } + + if(pgc->cell_position_offset != 0 && pgc->nr_of_cells>0) { + pgc->cell_position = malloc(pgc->nr_of_cells * sizeof(cell_position_t)); + if(!pgc->cell_position) { + ifoFree_PGC(pgc); + return 0; + } + if(!ifoRead_CELL_POSITION_TBL(ifofile, pgc->cell_position, + pgc->nr_of_cells, + offset + pgc->cell_position_offset)) { + ifoFree_PGC(pgc); + 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 = 0; + if(ifofile->vmgi_mat->first_play_pgc == 0) + return 1; + + ifofile->first_play_pgc = (pgc_t *)malloc(sizeof(pgc_t)); + if(!ifofile->first_play_pgc) + return 0; + + if(!ifoRead_PGC(ifofile, ifofile->first_play_pgc, + ifofile->vmgi_mat->first_play_pgc)) { + free(ifofile->first_play_pgc); + ifofile->first_play_pgc = 0; + return 0; + } + + return 1; +} + +static void ifoFree_PGC(pgc_t *pgc) { + if(pgc) { + 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); + } +} + +void ifoFree_FP_PGC(ifo_handle_t *ifofile) { + if(!ifofile) + return; + + if(ifofile->first_play_pgc) { + ifoFree_PGC(ifofile->first_play_pgc); + free(ifofile->first_play_pgc); + ifofile->first_play_pgc = 0; + } +} + + +int ifoRead_TT_SRPT(ifo_handle_t *ifofile) { + tt_srpt_t *tt_srpt; + int i, info_length; + + if(!ifofile) + return 0; + + if(!ifofile->vmgi_mat) + return 0; + + if(ifofile->vmgi_mat->tt_srpt == 0) /* mandatory */ + return 0; + + if(!DVDFileSeek_(ifofile->file, ifofile->vmgi_mat->tt_srpt * DVD_BLOCK_LEN)) + return 0; + + tt_srpt = (tt_srpt_t *)malloc(sizeof(tt_srpt_t)); + if(!tt_srpt) + return 0; + + ifofile->tt_srpt = tt_srpt; + + if(!(DVDReadBytes(ifofile->file, tt_srpt, TT_SRPT_SIZE))) { + fprintf(stderr, "libdvdread: Unable to read read TT_SRPT.\n"); + free(tt_srpt); + return 0; + } + + B2N_16(tt_srpt->nr_of_srpts); + B2N_32(tt_srpt->last_byte); + + info_length = tt_srpt->last_byte + 1 - TT_SRPT_SIZE; + + tt_srpt->title = (title_info_t *)malloc(info_length); + if(!tt_srpt->title) { + free(tt_srpt); + ifofile->tt_srpt = 0; + return 0; + } + if(!(DVDReadBytes(ifofile->file, tt_srpt->title, info_length))) { + fprintf(stderr, "libdvdread: Unable to read read TT_SRPT.\n"); + ifoFree_TT_SRPT(ifofile); + return 0; + } + + 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((int)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))) { + fprintf(stderr, "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); + free(ifofile->tt_srpt); + ifofile->tt_srpt = 0; + } +} + + +int ifoRead_VTS_PTT_SRPT(ifo_handle_t *ifofile) { + vts_ptt_srpt_t *vts_ptt_srpt; + int info_length, i, j; + uint32_t *data; + + if(!ifofile) + return 0; + + if(!ifofile->vtsi_mat) + return 0; + + if(ifofile->vtsi_mat->vts_ptt_srpt == 0) /* mandatory */ + return 0; + + if(!DVDFileSeek_(ifofile->file, + ifofile->vtsi_mat->vts_ptt_srpt * DVD_BLOCK_LEN)) + return 0; + + vts_ptt_srpt = (vts_ptt_srpt_t *)malloc(sizeof(vts_ptt_srpt_t)); + if(!vts_ptt_srpt) + return 0; + + ifofile->vts_ptt_srpt = vts_ptt_srpt; + + if(!(DVDReadBytes(ifofile->file, vts_ptt_srpt, VTS_PTT_SRPT_SIZE))) { + fprintf(stderr, "libdvdread: Unable to read PTT search table.\n"); + free(vts_ptt_srpt); + return 0; + } + + 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); /* ?? */ + + info_length = vts_ptt_srpt->last_byte + 1 - VTS_PTT_SRPT_SIZE; + + data = (uint32_t *)malloc(info_length); + if(!data) { + free(vts_ptt_srpt); + ifofile->vts_ptt_srpt = 0; + return 0; + } + if(!(DVDReadBytes(ifofile->file, data, info_length))) { + fprintf(stderr, "libdvdread: Unable to read PTT search table.\n"); + free(vts_ptt_srpt); + free(data); + ifofile->vts_ptt_srpt = 0; + return 0; + } + + for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) { + B2N_32(data[i]); + /* 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 = malloc(vts_ptt_srpt->nr_of_srpts * sizeof(ttu_t)); + if(!vts_ptt_srpt->title) { + free(vts_ptt_srpt); + free(data); + ifofile->vts_ptt_srpt = 0; + return 0; + } + 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; + CHECK_VALUE(n % 4 == 0); + + vts_ptt_srpt->title[i].nr_of_ptts = n / 4; + vts_ptt_srpt->title[i].ptt = malloc(n * sizeof(ptt_info_t)); + if(!vts_ptt_srpt->title[i].ptt) { + for(n = 0; n < i; n++) + free(vts_ptt_srpt->title[n].ptt); + free(vts_ptt_srpt); + free(data); + ifofile->vts_ptt_srpt = 0; + return 0; + } + 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); /* ?? */ + } + } + + return 1; +} + + +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) { + 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 == 0) + return 1; + + if(!DVDFileSeek_(ifofile->file, ifofile->vmgi_mat->ptl_mait * DVD_BLOCK_LEN)) + return 0; + + ptl_mait = (ptl_mait_t *)malloc(sizeof(ptl_mait_t)); + if(!ptl_mait) + return 0; + + ifofile->ptl_mait = ptl_mait; + + if(!(DVDReadBytes(ifofile->file, ptl_mait, PTL_MAIT_SIZE))) { + free(ptl_mait); + ifofile->ptl_mait = 0; + 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 = (ptl_mait_country_t *)malloc(info_length); + if(!ptl_mait->countries) { + free(ptl_mait); + ifofile->ptl_mait = 0; + return 0; + } + + for(i = 0; i < ptl_mait->nr_of_countries; i++) { + if(!(DVDReadBytes(ifofile->file, &ptl_mait->countries[i], PTL_MAIT_COUNTRY_SIZE))) { + fprintf(stderr, "libdvdread: Unable to read PTL_MAIT.\n"); + free(ptl_mait->countries); + free(ptl_mait); + ifofile->ptl_mait = 0; + 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 + + 8*2 * (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_(ifofile->file, + ifofile->vmgi_mat->ptl_mait * DVD_BLOCK_LEN + + ptl_mait->countries[i].pf_ptl_mai_start_byte)) { + fprintf(stderr, "libdvdread: Unable to seak PTL_MAIT table.\n"); + free(ptl_mait->countries); + free(ptl_mait); + return 0; + } + info_length = (ptl_mait->nr_of_vtss + 1) * sizeof(pf_level_t); + pf_temp = (uint16_t *)malloc(info_length); + if(!pf_temp) { + free_ptl_mait(ptl_mait, i); + return 0; + } + if(!(DVDReadBytes(ifofile->file, pf_temp, info_length))) { + fprintf(stderr, "libdvdread: Unable to read PTL_MAIT table.\n"); + free(pf_temp); + free_ptl_mait(ptl_mait, i); + return 0; + } + for (j = 0; j < ((ptl_mait->nr_of_vtss + 1) * 8); j++) { + B2N_16(pf_temp[j]); + } + ptl_mait->countries[i].pf_ptl_mai = (pf_level_t *)malloc(info_length); + if(!ptl_mait->countries[i].pf_ptl_mai) { + free(pf_temp); + free_ptl_mait(ptl_mait, i); + return 0; + } + { /* Transpose the array so we can use C indexing. */ + int level, vts; + for(level = 0; level < 8; 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) { + unsigned int i; + + if(!ifofile) + return; + + if(ifofile->ptl_mait) { + 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 = 0; + } +} + +int ifoRead_VTS_TMAPT(ifo_handle_t *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) { /* optional(?) */ + ifofile->vts_tmapt = NULL; + fprintf(stderr,"Please send bug report - no VTS_TMAPT ?? \n"); + return 1; + } + + offset = ifofile->vtsi_mat->vts_tmapt * DVD_BLOCK_LEN; + + if(!DVDFileSeek_(ifofile->file, offset)) + return 0; + + vts_tmapt = (vts_tmapt_t *)malloc(sizeof(vts_tmapt_t)); + if(!vts_tmapt) + return 0; + + ifofile->vts_tmapt = vts_tmapt; + + if(!(DVDReadBytes(ifofile->file, vts_tmapt, VTS_TMAPT_SIZE))) { + fprintf(stderr, "libdvdread: Unable to read VTS_TMAPT.\n"); + 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 = (uint32_t *)malloc(info_length); + if(!vts_tmap_srp) { + free(vts_tmapt); + ifofile->vts_tmapt = NULL; + return 0; + } + + vts_tmapt->tmap_offset = vts_tmap_srp; + + if(!(DVDReadBytes(ifofile->file, vts_tmap_srp, info_length))) { + fprintf(stderr, "libdvdread: Unable to read VTS_TMAPT.\n"); + 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 = (vts_tmap_t *)malloc(info_length); + if(!vts_tmapt->tmap) { + free(vts_tmap_srp); + free(vts_tmapt); + ifofile->vts_tmapt = NULL; + return 0; + } + + memset(vts_tmapt->tmap, 0, info_length); /* So ifoFree_VTS_TMAPT works. */ + + for(i = 0; i < vts_tmapt->nr_of_tmaps; i++) { + if(!DVDFileSeek_(ifofile->file, offset + vts_tmap_srp[i])) { + ifoFree_VTS_TMAPT(ifofile); + return 0; + } + + if(!(DVDReadBytes(ifofile->file, &vts_tmapt->tmap[i], VTS_TMAP_SIZE))) { + fprintf(stderr, "libdvdread: Unable to read VTS_TMAP.\n"); + 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 = (map_ent_t *)malloc(info_length); + if(!vts_tmapt->tmap[i].map_ent) { + ifoFree_VTS_TMAPT(ifofile); + return 0; + } + + if(!(DVDReadBytes(ifofile->file, vts_tmapt->tmap[i].map_ent, info_length))) { + fprintf(stderr, "libdvdread: Unable to read VTS_TMAP_ENT.\n"); + 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) { + unsigned int i; + + if(!ifofile) + return; + + if(ifofile->vts_tmapt) { + 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 = (c_adt_t *)malloc(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 = 0; + 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 = (c_adt_t *)malloc(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 = 0; + return 0; + } + + return 1; +} + +static int ifoRead_C_ADT_internal(ifo_handle_t *ifofile, + c_adt_t *c_adt, unsigned int sector) { + int i, info_length; + + if(!DVDFileSeek_(ifofile->file, sector * DVD_BLOCK_LEN)) + return 0; + + if(!(DVDReadBytes(ifofile->file, c_adt, C_ADT_SIZE))) + return 0; + + B2N_16(c_adt->nr_of_vobs); + B2N_32(c_adt->last_byte); + + 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) { + fprintf(stderr, "libdvdread: *C_ADT nr_of_vobs > avaiable info entries\n"); + c_adt->nr_of_vobs = info_length / sizeof(cell_adr_t); + } + + c_adt->cell_adr_table = (cell_adr_t *)malloc(info_length); + if(!c_adt->cell_adr_table) + return 0; + + if(info_length && + !(DVDReadBytes(ifofile->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 = 0; +} + +void ifoFree_TITLE_C_ADT(ifo_handle_t *ifofile) { + if(!ifofile) + return; + + ifoFree_C_ADT_internal(ifofile->vts_c_adt); + ifofile->vts_c_adt = 0; +} + +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 = (vobu_admap_t *)malloc(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 = 0; + 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 = (vobu_admap_t *)malloc(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 = 0; + return 0; + } + + return 1; +} + +static int ifoRead_VOBU_ADMAP_internal(ifo_handle_t *ifofile, + vobu_admap_t *vobu_admap, + unsigned int sector) { + unsigned int i; + int info_length; + + if(!DVDFileSeekForce_(ifofile->file, sector * DVD_BLOCK_LEN, sector)) + return 0; + + if(!(DVDReadBytes(ifofile->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 = (uint32_t *)malloc(info_length); + if(!vobu_admap->vobu_start_sectors) { + return 0; + } + if(info_length && + !(DVDReadBytes(ifofile->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 = 0; +} + +void ifoFree_TITLE_VOBU_ADMAP(ifo_handle_t *ifofile) { + if(!ifofile) + return; + + ifoFree_VOBU_ADMAP_internal(ifofile->vts_vobu_admap); + ifofile->vts_vobu_admap = 0; +} + +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 = (pgcit_t *)malloc(sizeof(pgcit_t)); + if(!ifofile->vts_pgcit) + return 0; + + if(!ifoRead_PGCIT_internal(ifofile, ifofile->vts_pgcit, + ifofile->vtsi_mat->vts_pgcit * DVD_BLOCK_LEN)) { + free(ifofile->vts_pgcit); + ifofile->vts_pgcit = 0; + return 0; + } + + return 1; +} + +static int ifoRead_PGCIT_internal(ifo_handle_t *ifofile, pgcit_t *pgcit, + unsigned int offset) { + int i, info_length; + uint8_t *data, *ptr; + + if(!DVDFileSeek_(ifofile->file, offset)) + return 0; + + if(!(DVDReadBytes(ifofile->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 */ + + info_length = pgcit->nr_of_pgci_srp * PGCI_SRP_SIZE; + data = malloc(info_length); + if(!data) + return 0; + + if(info_length && !(DVDReadBytes(ifofile->file, data, info_length))) { + free(data); + return 0; + } + + pgcit->pgci_srp = malloc(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].unknown1 == 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++) { + pgcit->pgci_srp[i].pgc = malloc(sizeof(pgc_t)); + if(!pgcit->pgci_srp[i].pgc) { + int j; + for(j = 0; j < i; j++) { + ifoFree_PGC(pgcit->pgci_srp[j].pgc); + free(pgcit->pgci_srp[j].pgc); + } + goto fail; + } + if(!ifoRead_PGC(ifofile, pgcit->pgci_srp[i].pgc, + offset + pgcit->pgci_srp[i].pgc_start_byte)) { + int j; + for(j = 0; j < i; j++) { + ifoFree_PGC(pgcit->pgci_srp[j].pgc); + free(pgcit->pgci_srp[j].pgc); + } + goto fail; + } + } + + return 1; +fail: + free(pgcit->pgci_srp); + pgcit->pgci_srp = NULL; + return 0; +} + +static void ifoFree_PGCIT_internal(pgcit_t *pgcit) { + if(pgcit) { + int i; + for(i = 0; i < pgcit->nr_of_pgci_srp; i++) { + ifoFree_PGC(pgcit->pgci_srp[i].pgc); + free(pgcit->pgci_srp[i].pgc); + } + free(pgcit->pgci_srp); + } +} + +void ifoFree_PGCIT(ifo_handle_t *ifofile) { + if(!ifofile) + return; + + if(ifofile->vts_pgcit) { + ifoFree_PGCIT_internal(ifofile->vts_pgcit); + free(ifofile->vts_pgcit); + ifofile->vts_pgcit = 0; + } +} + + +int ifoRead_PGCI_UT(ifo_handle_t *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 = (pgci_ut_t *)malloc(sizeof(pgci_ut_t)); + if(!ifofile->pgci_ut) + return 0; + + if(!DVDFileSeek_(ifofile->file, sector * DVD_BLOCK_LEN)) { + free(ifofile->pgci_ut); + ifofile->pgci_ut = 0; + return 0; + } + + if(!(DVDReadBytes(ifofile->file, ifofile->pgci_ut, PGCI_UT_SIZE))) { + free(ifofile->pgci_ut); + ifofile->pgci_ut = 0; + 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 = malloc(info_length); + if(!data) { + free(pgci_ut); + ifofile->pgci_ut = 0; + return 0; + } + if(!(DVDReadBytes(ifofile->file, data, info_length))) { + free(data); + free(pgci_ut); + ifofile->pgci_ut = 0; + return 0; + } + + pgci_ut->lu = malloc(pgci_ut->nr_of_lus * sizeof(pgci_lu_t)); + if(!pgci_ut->lu) { + free(data); + free(pgci_ut); + ifofile->pgci_ut = 0; + 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++) { + pgci_ut->lu[i].pgcit = malloc(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[j].pgcit); + } + free(pgci_ut->lu); + free(pgci_ut); + ifofile->pgci_ut = 0; + return 0; + } + 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[j].pgcit); + } + free(pgci_ut->lu[i].pgcit); + free(pgci_ut->lu); + free(pgci_ut); + ifofile->pgci_ut = 0; + 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) { + unsigned int i; + + if(!ifofile) + return; + + if(ifofile->pgci_ut) { + 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[i].pgcit); + } + free(ifofile->pgci_ut->lu); + free(ifofile->pgci_ut); + ifofile->pgci_ut = 0; + } +} + +static int ifoRead_VTS_ATTRIBUTES(ifo_handle_t *ifofile, + vts_attributes_t *vts_attributes, + unsigned int offset) { + unsigned int i; + + if(!DVDFileSeek_(ifofile->file, offset)) + return 0; + + if(!(DVDReadBytes(ifofile->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) { + 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_(ifofile->file, sector * DVD_BLOCK_LEN)) + return 0; + + vts_atrt = (vts_atrt_t *)malloc(sizeof(vts_atrt_t)); + if(!vts_atrt) + return 0; + + ifofile->vts_atrt = vts_atrt; + + if(!(DVDReadBytes(ifofile->file, vts_atrt, VTS_ATRT_SIZE))) { + free(vts_atrt); + ifofile->vts_atrt = 0; + 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 = (uint32_t *)malloc(info_length); + if(!data) { + free(vts_atrt); + ifofile->vts_atrt = 0; + return 0; + } + + vts_atrt->vts_atrt_offsets = data; + + if(!(DVDReadBytes(ifofile->file, data, info_length))) { + free(data); + free(vts_atrt); + ifofile->vts_atrt = 0; + 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 = (vts_attributes_t *)malloc(info_length); + if(!vts_atrt->vts) { + free(data); + free(vts_atrt); + ifofile->vts_atrt = 0; + 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 = 0; + return 0; + } + + /* This assert cant 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 = 0; + } +} + + +int ifoRead_TXTDT_MGI(ifo_handle_t *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_(ifofile->file, + ifofile->vmgi_mat->txtdt_mgi * DVD_BLOCK_LEN)) + return 0; + + txtdt_mgi = (txtdt_mgi_t *)malloc(sizeof(txtdt_mgi_t)); + if(!txtdt_mgi) { + return 0; + } + ifofile->txtdt_mgi = txtdt_mgi; + + if(!(DVDReadBytes(ifofile->file, txtdt_mgi, TXTDT_MGI_SIZE))) { + fprintf(stderr, "libdvdread: Unable to read TXTDT_MGI.\n"); + free(txtdt_mgi); + ifofile->txtdt_mgi = 0; + return 0; + } + + /* fprintf(stderr, "-- 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 = 0; + } +} + diff --git a/lib/libdvd/libdvdread/src/ifo_read.h b/lib/libdvd/libdvdread/src/ifo_read.h new file mode 100644 index 0000000000..3f4ea24ec2 --- /dev/null +++ b/lib/libdvd/libdvdread/src/ifo_read.h @@ -0,0 +1,227 @@ +#ifndef IFO_READ_H_INCLUDED +#define IFO_READ_H_INCLUDED + +/* + * Copyright (C) 2000, 2001, 2002 Björn Englund <d4bjorn@dtek.chalmers.se>, + * Håkan Hjort <d95hjort@dtek.chalmers.se> + * + * 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 + */ + +#include "ifo_types.h" +#include "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 pressent 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 /* IFO_READ_H_INCLUDED */ diff --git a/lib/libdvd/libdvdread/src/ifo_types.h b/lib/libdvd/libdvdread/src/ifo_types.h new file mode 100644 index 0000000000..44e95da1f9 --- /dev/null +++ b/lib/libdvd/libdvdread/src/ifo_types.h @@ -0,0 +1,747 @@ +#ifndef IFO_TYPES_H_INCLUDED +#define IFO_TYPES_H_INCLUDED + +/* + * Copyright (C) 2000, 2001 Björn Englund <d4bjorn@dtek.chalmers.se>, + * Håkan Hjort <d95hjort@dtek.chalmers.se> + * + * 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 + */ + +#include <inttypes.h> +#include "dvd_reader.h" + + +#undef ATTRIBUTE_PACKED +#undef PRAGMA_PACK_BEGIN +#undef PRAGMA_PACK_END + +#if defined(__GNUC__) +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95) +#define ATTRIBUTE_PACKED __attribute__ ((packed)) +#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; + } app_info; +} ATTRIBUTE_PACKED audio_attr_t; + + +/** + * MultiChannel Extension + */ +typedef struct { + unsigned int zero1 : 7; + unsigned int ach0_gme : 1; + + unsigned int zero2 : 7; + unsigned int ach1_gme : 1; + + unsigned int zero3 : 4; + unsigned int ach2_gv1e : 1; + unsigned int ach2_gv2e : 1; + unsigned int ach2_gm1e : 1; + unsigned int ach2_gm2e : 1; + + unsigned int zero4 : 4; + unsigned int ach3_gv1e : 1; + unsigned int ach3_gv2e : 1; + unsigned int ach3_gmAe : 1; + unsigned int ach3_se2e : 1; + + unsigned int zero5 : 4; + unsigned int ach4_gv1e : 1; + unsigned int ach4_gv2e : 1; + unsigned int ach4_gmBe : 1; + unsigned int 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 zero_1; + 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 int block_mode : 2; + unsigned int block_type : 2; + unsigned int seamless_play : 1; + unsigned int interleaved : 1; + unsigned int stc_discontinuity: 1; + unsigned int seamless_angle : 1; + unsigned int playback_mode : 1; /**< When set, enter StillMode after each VOBU */ + unsigned int restricted : 1; /**< ?? drop out of fastforward? */ + unsigned int unknown2 : 6; + 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 int zero : 7; /* 25-31 */ + unsigned int video_pres_mode_change : 1; /* 24 */ + + unsigned int karaoke_audio_pres_mode_change : 1; /* 23 */ + unsigned int angle_change : 1; + unsigned int subpic_stream_change : 1; + unsigned int audio_stream_change : 1; + unsigned int pause_on : 1; + unsigned int still_off : 1; + unsigned int button_select_or_activate : 1; + unsigned int resume : 1; /* 16 */ + + unsigned int chapter_menu_call : 1; /* 15 */ + unsigned int angle_menu_call : 1; + unsigned int audio_menu_call : 1; + unsigned int subpic_menu_call : 1; + unsigned int root_menu_call : 1; + unsigned int title_menu_call : 1; + unsigned int backward_scan : 1; + unsigned int forward_scan : 1; /* 8 */ + + unsigned int next_pg_search : 1; /* 7 */ + unsigned int prev_or_top_pg_search : 1; + unsigned int time_or_chapter_search : 1; + unsigned int go_up : 1; + unsigned int stop : 1; + unsigned int title_play : 1; + unsigned int chapter_search_or_play : 1; + unsigned int 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 still_time; + uint8_t pg_playback_mode; + 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; +} ATTRIBUTE_PACKED pgc_t; +#define PGC_SIZE 236U + +/** + * Program Chain Information Search Pointer. + */ +typedef struct { + uint8_t entry_id; + unsigned int block_mode : 2; + unsigned int block_type : 2; + unsigned int unknown1 : 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; +} 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 int zero_1 : 1; + unsigned int multi_or_random_pgc_title : 1; /* 0: one sequential pgc title */ + unsigned int jlc_exists_in_cell_cmd : 1; + unsigned int jlc_exists_in_prepost_cmd : 1; + unsigned int jlc_exists_in_button_cmd : 1; + unsigned int jlc_exists_in_tt_dom : 1; + unsigned int chapter_search_or_play : 1; /* UOP 1 */ + unsigned int 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 + */ +typedef uint16_t pf_level_t[8]; + +/** + * 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; /* ?? allways 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; + uint16_t unknown; /* 0x0001, title 1? disc 1? side 1? */ + 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[14]; /* how many bytes?? */ + uint16_t nr_of_language_units; /* 32bit?? */ + 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 { + dvd_file_t *file; + + /* 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 /* IFO_TYPES_H_INCLUDED */ diff --git a/lib/libdvd/libdvdread/src/md5.c b/lib/libdvd/libdvdread/src/md5.c new file mode 100644 index 0000000000..2bfdddee44 --- /dev/null +++ b/lib/libdvd/libdvdread/src/md5.c @@ -0,0 +1,411 @@ +/* md5.c - Functions to compute MD5 message digest of files or memory blocks + according to the definition of MD5 in RFC 1321 from April 1992. + Copyright (C) 1995, 1996, 2001 Free Software Foundation, Inc. + NOTE: The canonical source of this file is maintained with the GNU C + Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu. + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <sys/types.h> + +#include <stdlib.h> +#include <string.h> + +#include "md5.h" +/* #include "unlocked-io.h" */ + +#ifdef _LIBC +# include <endian.h> +# if __BYTE_ORDER == __BIG_ENDIAN +# define WORDS_BIGENDIAN 1 +# endif +#endif + +#ifdef WORDS_BIGENDIAN +# define SWAP(n) \ + (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24)) +#else +# define SWAP(n) (n) +#endif + + +/* This array contains the bytes used to pad the buffer to the next + 64-byte boundary. (RFC 1321, 3.1: Step 1) */ +static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ }; + + +/* Initialize structure containing state of computation. + (RFC 1321, 3.3: Step 3) */ +void +md5_init_ctx (ctx) + struct md5_ctx *ctx; +{ + ctx->A = 0x67452301; + ctx->B = 0xefcdab89; + ctx->C = 0x98badcfe; + ctx->D = 0x10325476; + + ctx->total[0] = ctx->total[1] = 0; + ctx->buflen = 0; +} + +/* Put result from CTX in first 16 bytes following RESBUF. The result + must be in little endian byte order. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 32 bits value. */ +void * +md5_read_ctx (ctx, resbuf) + const struct md5_ctx *ctx; + void *resbuf; +{ + ((md5_uint32 *) resbuf)[0] = SWAP (ctx->A); + ((md5_uint32 *) resbuf)[1] = SWAP (ctx->B); + ((md5_uint32 *) resbuf)[2] = SWAP (ctx->C); + ((md5_uint32 *) resbuf)[3] = SWAP (ctx->D); + + return resbuf; +} + +/* Process the remaining bytes in the internal buffer and the usual + prolog according to the standard and write the result to RESBUF. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 32 bits value. */ +void * +md5_finish_ctx (ctx, resbuf) + struct md5_ctx *ctx; + void *resbuf; +{ + /* Take yet unprocessed bytes into account. */ + md5_uint32 bytes = ctx->buflen; + size_t pad; + + /* Now count remaining bytes. */ + ctx->total[0] += bytes; + if (ctx->total[0] < bytes) + ++ctx->total[1]; + + pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes; + memcpy (&ctx->buffer[bytes], fillbuf, pad); + + /* Put the 64-bit file length in *bits* at the end of the buffer. */ + *(md5_uint32 *) &ctx->buffer[bytes + pad] = SWAP (ctx->total[0] << 3); + *(md5_uint32 *) &ctx->buffer[bytes + pad + 4] = SWAP ((ctx->total[1] << 3) | + (ctx->total[0] >> 29)); + + /* Process last bytes. */ + md5_process_block (ctx->buffer, bytes + pad + 8, ctx); + + return md5_read_ctx (ctx, resbuf); +} + +/* Compute MD5 message digest for bytes read from STREAM. The + resulting message digest number will be written into the 16 bytes + beginning at RESBLOCK. */ +int +md5_stream (stream, resblock) + FILE *stream; + void *resblock; +{ + /* Important: BLOCKSIZE must be a multiple of 64. */ +#define BLOCKSIZE 4096 + struct md5_ctx ctx; + char buffer[BLOCKSIZE + 72]; + size_t sum; + + /* Initialize the computation context. */ + md5_init_ctx (&ctx); + + /* Iterate over full file contents. */ + while (1) + { + /* We read the file in blocks of BLOCKSIZE bytes. One call of the + computation function processes the whole buffer so that with the + next round of the loop another block can be read. */ + size_t n; + sum = 0; + + /* Read block. Take care for partial reads. */ + do + { + n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream); + + sum += n; + } + while (sum < BLOCKSIZE && n != 0); + if (n == 0 && ferror (stream)) + return 1; + + /* If end of file is reached, end the loop. */ + if (n == 0) + break; + + /* Process buffer with BLOCKSIZE bytes. Note that + BLOCKSIZE % 64 == 0 + */ + md5_process_block (buffer, BLOCKSIZE, &ctx); + } + + /* Add the last bytes if necessary. */ + if (sum > 0) + md5_process_bytes (buffer, sum, &ctx); + + /* Construct result in desired memory. */ + md5_finish_ctx (&ctx, resblock); + return 0; +} + +/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The + result is always in little endian byte order, so that a byte-wise + output yields to the wanted ASCII representation of the message + digest. */ +void * +md5_buffer (buffer, len, resblock) + const char *buffer; + size_t len; + void *resblock; +{ + struct md5_ctx ctx; + + /* Initialize the computation context. */ + md5_init_ctx (&ctx); + + /* Process whole buffer but last len % 64 bytes. */ + md5_process_bytes (buffer, len, &ctx); + + /* Put result in desired memory area. */ + return md5_finish_ctx (&ctx, resblock); +} + + +void +md5_process_bytes (buffer, len, ctx) + const void *buffer; + size_t len; + struct md5_ctx *ctx; +{ + /* When we already have some bits in our internal buffer concatenate + both inputs first. */ + if (ctx->buflen != 0) + { + size_t left_over = ctx->buflen; + size_t add = 128 - left_over > len ? len : 128 - left_over; + + memcpy (&ctx->buffer[left_over], buffer, add); + ctx->buflen += add; + + if (left_over + add > 64) + { + md5_process_block (ctx->buffer, (left_over + add) & ~63, ctx); + /* The regions in the following copy operation cannot overlap. */ + memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63], + (left_over + add) & 63); + ctx->buflen = (left_over + add) & 63; + } + + buffer = (const char *) buffer + add; + len -= add; + } + + /* Process available complete blocks. */ + if (len > 64) + { + md5_process_block (buffer, len & ~63, ctx); + buffer = (const char *) buffer + (len & ~63); + len &= 63; + } + + /* Move remaining bytes in internal buffer. */ + if (len > 0) + { + memcpy (ctx->buffer, buffer, len); + ctx->buflen = len; + } +} + + +/* 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)) + +/* Process LEN bytes of BUFFER, accumulating context into CTX. + It is assumed that LEN % 64 == 0. */ + +void +md5_process_block (buffer, len, ctx) + const void *buffer; + size_t len; + struct md5_ctx *ctx; +{ + md5_uint32 correct_words[16]; + const md5_uint32 *words = buffer; + size_t nwords = len / sizeof (md5_uint32); + const md5_uint32 *endp = words + nwords; + md5_uint32 A = ctx->A; + md5_uint32 B = ctx->B; + md5_uint32 C = ctx->C; + md5_uint32 D = ctx->D; + + /* First increment the byte count. RFC 1321 specifies the possible + length of the file up to 2^64 bits. Here we only compute the + number of bytes. Do a double word increment. */ + ctx->total[0] += len; + if (ctx->total[0] < len) + ++ctx->total[1]; + + /* Process all bytes in the buffer with 64 bytes in each round of + the loop. */ + while (words < endp) + { + md5_uint32 *cwp = correct_words; + md5_uint32 A_save = A; + md5_uint32 B_save = B; + md5_uint32 C_save = C; + md5_uint32 D_save = D; + + /* First round: using the given function, the context and a constant + the next context is computed. Because the algorithms processing + unit is a 32-bit word and it is determined to work on words in + little endian byte order we perhaps have to change the byte order + before the computation. To reduce the work for the next steps + we store the swapped words in the array CORRECT_WORDS. */ + +#define OP(a, b, c, d, s, T) \ + do \ + { \ + a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T; \ + ++words; \ + a = rol (a, s); \ + a += b; \ + } \ + while (0) + + /* Before we start, one word to the strange constants. + They are defined in RFC 1321 as + + T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64, or + perl -e 'foreach(1..64){printf "0x%08x\n", int (4294967296 * abs (sin $_))}' + */ + + /* 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); + + /* For the second to fourth round we have the possibly swapped words + in CORRECT_WORDS. Redefine the macro to take an additional first + argument specifying the function to use. */ +#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); + + /* Add the starting values of the context. */ + A += A_save; + B += B_save; + C += C_save; + D += D_save; + } + + /* Put checksum in context given as argument. */ + ctx->A = A; + ctx->B = B; + ctx->C = C; + ctx->D = D; +} diff --git a/lib/libdvd/libdvdread/src/md5.h b/lib/libdvd/libdvdread/src/md5.h new file mode 100644 index 0000000000..3b7dea1699 --- /dev/null +++ b/lib/libdvd/libdvdread/src/md5.h @@ -0,0 +1,161 @@ +/* md5.h - Declaration of functions and data types used for MD5 sum + computing library functions. + Copyright (C) 1995, 1996, 1999 Free Software Foundation, Inc. + NOTE: The canonical source of this file is maintained with the GNU C + Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu. + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef _MD5_H +#define _MD5_H 1 + +#include <stdio.h> + +#if defined HAVE_LIMITS_H || _LIBC +# include <limits.h> +#endif + +/* The following contortions are an attempt to use the C preprocessor + to determine an unsigned integral type that is 32 bits wide. An + alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but + doing that would require that the configure script compile and *run* + the resulting executable. Locally running cross-compiled executables + is usually not possible. */ + +#ifdef _LIBC +# include <sys/types.h> +typedef u_int32_t md5_uint32; +#else +# if defined __STDC__ && __STDC__ +# define UINT_MAX_32_BITS 4294967295U +# else +# define UINT_MAX_32_BITS 0xFFFFFFFF +# endif + +/* If UINT_MAX isn't defined, assume it's a 32-bit type. + This should be valid for all systems GNU cares about because + that doesn't include 16-bit systems, and only modern systems + (that certainly have <limits.h>) have 64+-bit integral types. */ + +# ifndef UINT_MAX +# define UINT_MAX UINT_MAX_32_BITS +# endif + +# if UINT_MAX == UINT_MAX_32_BITS + typedef unsigned int md5_uint32; +# else +# if USHRT_MAX == UINT_MAX_32_BITS + typedef unsigned short md5_uint32; +# else +# if ULONG_MAX == UINT_MAX_32_BITS + typedef unsigned long md5_uint32; +# else + /* The following line is intended to evoke an error. + Using #error is not portable enough. */ + "Cannot determine unsigned 32-bit data type." +# endif +# endif +# endif +#endif + +#undef __P +#if defined (__STDC__) && __STDC__ +#define __P(x) x +#else +#define __P(x) () +#endif + +/* Structure to save state of computation between the single steps. */ +struct md5_ctx +{ + md5_uint32 A; + md5_uint32 B; + md5_uint32 C; + md5_uint32 D; + + md5_uint32 total[2]; + md5_uint32 buflen; + char buffer[128]; +}; + +/* + * The following three functions are build up the low level used in + * the functions `md5_stream' and `md5_buffer'. + */ + +/* Initialize structure containing state of computation. + (RFC 1321, 3.3: Step 3) */ +extern void md5_init_ctx __P ((struct md5_ctx *ctx)); + +/* Starting with the result of former calls of this function (or the + initialization function update the context for the next LEN bytes + starting at BUFFER. + It is necessary that LEN is a multiple of 64!!! */ +extern void md5_process_block __P ((const void *buffer, size_t len, + struct md5_ctx *ctx)); + +/* Starting with the result of former calls of this function (or the + initialization function update the context for the next LEN bytes + starting at BUFFER. + It is NOT required that LEN is a multiple of 64. */ +extern void md5_process_bytes __P ((const void *buffer, size_t len, + struct md5_ctx *ctx)); + +/* Process the remaining bytes in the buffer and put result from CTX + in first 16 bytes following RESBUF. The result is always in little + endian byte order, so that a byte-wise output yields to the wanted + ASCII representation of the message digest. + + IMPORTANT: On some systems it is required that RESBUF be correctly + aligned for a 32 bits value. */ +extern void *md5_finish_ctx __P ((struct md5_ctx *ctx, void *resbuf)); + + +/* Put result from CTX in first 16 bytes following RESBUF. The result is + always in little endian byte order, so that a byte-wise output yields + to the wanted ASCII representation of the message digest. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 32 bits value. */ +extern void *md5_read_ctx __P ((const struct md5_ctx *ctx, void *resbuf)); + + +/* Compute MD5 message digest for bytes read from STREAM. The + resulting message digest number will be written into the 16 bytes + beginning at RESBLOCK. */ +extern int md5_stream __P ((FILE *stream, void *resblock)); + +/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The + result is always in little endian byte order, so that a byte-wise + output yields to the wanted ASCII representation of the message + digest. */ +extern void *md5_buffer __P ((const char *buffer, size_t len, void *resblock)); + +/* The following is from gnupg-1.0.2's cipher/bithelp.h. */ +/* Rotate a 32 bit integer by n bytes */ +#if defined __GNUC__ && defined __i386__ +static inline md5_uint32 +rol(md5_uint32 x, int n) +{ + __asm__("roll %%cl,%0" + :"=r" (x) + :"0" (x),"c" (n)); + return x; +} +#else +# define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) ) +#endif + +#endif diff --git a/lib/libdvd/libdvdread/src/nav_print.c b/lib/libdvd/libdvdread/src/nav_print.c new file mode 100644 index 0000000000..a4370c16e6 --- /dev/null +++ b/lib/libdvd/libdvdread/src/nav_print.c @@ -0,0 +1,252 @@ +/* + * Copyright (C) 2000, 2001, 2002, 2003 Håkan Hjort <d95hjort@dtek.chalmers.se> + * + * Much of the contents in this file is based on VOBDUMP. + * + * VOBDUMP: a program for examining DVD .VOB filse + * + * Copyright 1998, 1999 Eric Smith <eric@brouhaha.com> + * + * VOBDUMP is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include <stdio.h> +#include <inttypes.h> + +#include "nav_types.h" +#include "nav_print.h" +#include "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_uop_ctl 0x%08x\n", *(uint32_t*)&pci_gi->vobu_uop_ctl); + 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 %d\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 %d, auto_action_mode %d\n", + btni->btn_coln, btni->auto_action_mode); + printf("coords (%d, %d) .. (%d, %d)\n", + btni->x_start, btni->y_start, btni->x_end, btni->y_end); + + printf("up %d, ", btni->up); + printf("down %d, ", btni->down); + printf("left %d, ", btni->left); + printf("right %d\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/lib/libdvd/libdvdread/src/nav_print.h b/lib/libdvd/libdvdread/src/nav_print.h new file mode 100644 index 0000000000..bc79ab641f --- /dev/null +++ b/lib/libdvd/libdvdread/src/nav_print.h @@ -0,0 +1,50 @@ +#ifndef NAV_PRINT_H_INCLUDED +#define NAV_PRINT_H_INCLUDED + +/* + * Copyright (C) 2001, 2002 Billy Biggs <vektor@dumbterm.net>, + * Håkan Hjort <d95hjort@dtek.chalmers.se> + * + * 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 + */ + +#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 /* NAV_PRINT_H_INCLUDED */ diff --git a/lib/libdvd/libdvdread/src/nav_read.c b/lib/libdvd/libdvdread/src/nav_read.c new file mode 100644 index 0000000000..8ee6033a25 --- /dev/null +++ b/lib/libdvd/libdvdread/src/nav_read.c @@ -0,0 +1,265 @@ +/* + * Copyright (C) 2000, 2001, 2002, 2003 Håkan Hjort <d95hjort@dtek.chalmers.se> + * + * 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 + */ + +#include "config.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <inttypes.h> + +#include "bswap.h" +#include "nav_types.h" +#include "nav_read.h" +#include "dvdread_internal.h" +#include "bitreader.h" + +#define getbits_init dvdread_getbits_init +#define getbits dvdread_getbits + +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); +} + diff --git a/lib/libdvd/libdvdread/src/nav_read.h b/lib/libdvd/libdvdread/src/nav_read.h new file mode 100644 index 0000000000..48fe2c8524 --- /dev/null +++ b/lib/libdvd/libdvdread/src/nav_read.h @@ -0,0 +1,51 @@ +#ifndef NAV_READ_H_INCLUDED +#define NAV_READ_H_INCLUDED + +/* + * Copyright (C) 2000, 2001, 2002 Håkan Hjort <d95hjort@dtek.chalmers.se>. + * + * 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 + */ + +#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 bufffer 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 bufffer Pointer to the buffer of the on disc DSI data. + */ +void navRead_DSI(dsi_t *, unsigned char *); + +#ifdef __cplusplus +}; +#endif +#endif /* NAV_READ_H_INCLUDED */ diff --git a/lib/libdvd/libdvdread/src/nav_types.h b/lib/libdvd/libdvdread/src/nav_types.h new file mode 100644 index 0000000000..e0bbe2f57b --- /dev/null +++ b/lib/libdvd/libdvdread/src/nav_types.h @@ -0,0 +1,249 @@ +#ifndef NAV_TYPES_H_INCLUDED +#define NAV_TYPES_H_INCLUDED + +/* + * Copyright (C) 2000, 2001, 2002 Håkan Hjort <d95hjort@dtek.chalmers.se> + * + * 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 <eric@brouhaha.com> + * + * VOBDUMP is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#include <inttypes.h> +#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 int zero1 : 2; /**< reserved */ + unsigned int btngr_ns : 2; /**< number of button groups 1, 2 or 3 with 36/18/12 buttons */ + unsigned int zero2 : 1; /**< reserved */ + unsigned int btngr1_dsp_ty : 3; /**< display type of subpic stream for button group 1 */ + unsigned int zero3 : 1; /**< reserved */ + unsigned int btngr2_dsp_ty : 3; /**< display type of subpic stream for button group 2 */ + unsigned int zero4 : 1; /**< reserved */ + unsigned int 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 beeing a 32bit word that contains the color indexs 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 Infromation 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 Infromation + */ +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 /* NAV_TYPES_H_INCLUDED */ diff --git a/lib/libdvd/libdvdread/version.h b/lib/libdvd/libdvdread/version.h new file mode 100644 index 0000000000..fd4fb3ab13 --- /dev/null +++ b/lib/libdvd/libdvdread/version.h @@ -0,0 +1 @@ +#define VERSION "4.1.3" diff --git a/lib/libdvd/libdvdread/version.sh b/lib/libdvd/libdvdread/version.sh new file mode 100755 index 0000000000..230da4a8af --- /dev/null +++ b/lib/libdvd/libdvdread/version.sh @@ -0,0 +1,18 @@ +##!/bin/sh +# +#svn_revision=`cd "$1" && LC_ALL=C svn info 2> /dev/null | grep Revision | cut -d' ' -f2` +#test $svn_revision || svn_revision=`cd "$1" && grep revision .svn/entries 2>/dev/null | \ +# cut -d '"' -f2 2> /dev/null` +#test $svn_revision || svn_revision=UNKNOWN +# +#if test "$svn_revision" = UNKNOWN && test -n "$2"; then +# NEW_REVISION="#define VERSION \"$2\"" +#else +# NEW_REVISION="#define VERSION \"SVN-r$svn_revision\"" +#fi +#OLD_REVISION=`cat version.h 2> /dev/null` +# +## Update version.h only on revision changes to avoid spurious rebuilds +#if test "$NEW_REVISION" != "$OLD_REVISION"; then +# echo "$NEW_REVISION" > version.h +#fi |