pax_global_header00006660000000000000000000000064141571173660014525gustar00rootroot0000000000000052 comment=a83a0ccc4b05711f544420b9b62fc5664e216d44 vdr-plugin-dvd-0.3.7/000077500000000000000000000000001415711736600143765ustar00rootroot00000000000000vdr-plugin-dvd-0.3.7/CONTRIBUTORS000066400000000000000000000022311415711736600162540ustar00rootroot00000000000000Thanks to: Major ====== * FIXME: add all contributors .. Marco Schluessler - cvs team Miko Wohlgemuth - cvs team Sven Goethel - cvs team - successor dev. Andreas Schultz - Original Author Minor ====== Martin Hammerschmid - lcdproc hint Sascha Volkenandt - for the HideMainMenu patch Andr Weidemann - for the vaspect patch Angelo Lambiasi - buffer overflow in A52Decoder Rolf Ahrenberg - for the finnish translation Stefan Lucke - for fix segfault Vyacheslav Dikonov - for the russian translation Jaroslaw Swierczynski - for the polish translation Mogens Elneff - for the Danish translation Jesus Bravo Alvarez - for updating the Spanish OSD texts Maarten Wisse - for updating the Dutch OSD texts Arthur Konovalov - for the Estonian translation Vladimr Brta - for the Czech translation Dimitrios Dimitrakos - for the Greek translation Matjaz Thaler - for the Slovenian translation Oktay Yolgeen - for the Turkish translation Ioannis Petroglou - for fix possible segfault's ... and all the many testers and test case contributors .. vdr-plugin-dvd-0.3.7/COPYING000066400000000000000000000431311415711736600154330ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. vdr-plugin-dvd-0.3.7/HISTORY000066400000000000000000000350601415711736600154660ustar00rootroot00000000000000VDR Plugin 'dvd' Revision History --------------------------------- 2021-12-17 Version 0.3.7 - change i18n to gettext - fix GetIndex return value, remove lcdproc workaround - fix possible segfault's (thanks to Ioannis Petroglou) - add Turkish translation (thanks to Oktay Yolgeen) - add kNext and kPrev keys - changes for vdr-1.5.0 - changes for vdr-1.3.47 - fix pcm audiotrackhandling in audiomenu - add Slovenian translation (thanks to Matjaz Thaler) - add Greek translation (thanks to Dimitrios Dimitrakos) - add Czech translation (thanks to Vladimr Brta) - add Estonian translation (thanks to Arthur Konovalov) - updated the Dutch OSD texts (thanks to Maarten Wisse). - updated Spanish OSD texts (thanks to Jesus Bravo Alvarez) - add Danish translation (thanks to Mogens Elneff) - add polish translation (thanks to Jaroslaw Swierczynski) - changes for vdr-1.3.42 - add russian language (thanks to Vyacheslav Dikonov) - changes for vdr-1.3.38 - fix memleak in SetAspectString - add workaround for lcdproc-crashing (thanks to Joachim Wilke) - change SetVideoDisplayFormat to DeviceSetVideoDisplayFormat - fix error in i18.c (thanks to Ville Skytt) 2005-04-16 Version 0.3.6-b03 - add finnish translation (thanks to Ville Skytt) - fix error in picturetype detection to save still iframes - fix highlight in letterbox and pan&scan mode (need patch vdr-1.3.23-dvbspu.c.diff works also on vdr-1.3.22) - fix highlight button when button == 0 - change menu detection (test) - use DeviceClrAvailableTracks/DeviceSetCurrentAudioTrack from vdr - only set possible subtitles - fix subtitlehandling in replay display - fix aspectratio in pan and scan mode - fix stillpicture in menu - fix allways showed subtitles - fix audiotrackcount and audiolanguage in progress display - add mpeg2 audio language 2005-01-24 Version 0.3.6-b02 - added respect to vdr 1.3.19 multiple ac3 audioid's, as well as converting ac3->lpcm with the same audio id's - use this only with vdr >= 1.3.19 2005-01-23 Version 0.3.6-b01 - fix vdr >= 1.3.18 audio selection - AUDIO and DOLBY type works fine now - this needs a little fix, since klaus has added support for multiple ac3 audio id's .. - backward trick and very-fast fwd trick is fixed ! - change audio switch from '1' to 'Audio' - changes for vdr-1.3.18 (is not ready yet) - add gain in setup for analog output - fixed backward play - add fields for Danish language texts - add fields for Estonian language texts - deactivate "new a/v sync code" it produced high CPU load - fixed PTS sync - fixed error in the replay display - add finnish translation (thanks to Rolf Ahrenberg) - add 'data alignment indicator' Bit for AC3 loop through Firmware - add virtual plugin methods - move RegisterI18n(...) from Start() to Initialize() - fixed hightlight in menu - correct subtitle position (test) - fix audiostream selection - move 'forced subs' to VDR SpuDecoder - fix stop playing if message displayed 2004-06-24: Version 0.3.5-b06 - fixed segfault at plugin exit - fixed segfault in ac3 softdecoder - fixed AC3/DTS audiostream selection - remove 'forced subs' from setup - fixed video glitches at startup - remove code < vdr-1.3.7 it does not work - change stop to speedup exit 2004-06-17: Version 0.3.5-b05... - div by zero .. - dvd aspect .. - ReadAHead is boolean again - fetching dvd infos, only if necessary (new): bool UpdateBlockInfo(void); void UpdateVTSInfo(void); else, data is cached within player. - Try to use ReadAHead := true, and check dvd drive access/performance !! 2004-06-17: Version 0.3.5-b04 - many merges/fixes .. - highlight - QNX support - still/audio dvd's (hybrid dvd-audio) - dvd-v part only .. - pcm support started .. /** * the funny thing here is, that: * - it plays well within vdr-xine * - it plays broken with vdr/dvb itself (PlayVideo) * - it plays broken with bitstreamout (PlayAudio) */ 2004-06-10: Version 0.3.5-b02 - SPU AUTO PROBLEM: * #define FORCED_SUBS_ONLY_SEMANTICS * this was "weak"'s solution of a forced * SPU only stream choice, * which does _not_ work .. * * Problem: * - forcedDisplay | menu ctrseq within the SPU, * means kinda "just do it" * * - special SPU channels, which only shows up * e.g. if a klingon speaks klingon, * are handled by a special SPU channel id, * which dvdnav will choose for you automatic, * and if your appropriate language is set * as the default language ! * FIXME ?? * - correct pre-parse of SPU to check for forcedDisplay ctrl-seq - take forceDisplay into account, if outta menu space - take care of all SPU channel id's [0x00 .. 0x1F] - take care of all Audio channel id's [0x00 .. 0x1F] - all SPU and Audio channels are looked up at VTS_CHANGE, and are therefore available if start a new title ! - take very good care ;-), of who owns the OSD, this one is needed to use softdevices, alike vdr-xine ! *** be aware that we do need the very little patch patches/vdr-1.3.10_spu_01.diff *** to enable access to - cSpuDecoder::Hide,Draw,IsVisible - cDvbSpuDecoder::Hide,Draw,IsVisible now you can switch to dvd-osd, vdr-menu and spu, without seg fault, or else with a softdevice .. - minimized dvdnav access for title string data .. - many stuff learned about SPU control, and channel hopping ;-) - please apply the mandatory patches to the regarding vanilla version: - vdr-1.3.10_spu_01.diff (see above, spu stuff) - vdr-xine-0.3.4-withSpu_02.diff (add dvbspu to the xineDevice) 2004-06-08: - merge with inofficial fork @ dvdplugin.pimps.at ..: - fixed some display errors during navigation - ringbuffer implemented - fixed buffer overflow in sound handling - fixed language selection bug in plugin setup - added 'forced subs only' mode - added support for vdr >= 1.3.7, and < 1.3.7 ! 2004-05-26: Version 0.3.5-b01 - ported to vdr 1.3.8, no more support for vdr pre 1.3.8 - added DevicePoll timeout > MAX_POLL_TOs -> DeviceClear - good for softdevices, like vdr-xine - added some patches for vdr 1.3.8 support .. 2003-11-18: Version 0.3.4-rc11 .. sven at jausoft.com - cleaned up termination (as well as UC: no disc inserted ..) - fixed case where device->GetSTC returns < 0 (dxr3 users) 2003-11-11: Version 0.3.4-rc10 .. sven at jausoft.com - fixed setting correct 16:9 / 4:3 bits in mpeg stream - fixed usage of DeviceClear .. - fixed variable osd position, regarding to video height - needs vdr >= 1.2.6pre6 - no more extra STC patch ! 2003-11-03: Version 0.3.4-rc9 .. sven at jausoft.com - bugfix: error introduced in rc8 are removed (new threading errors) - menue navi is stable again. 2003-11-02: Version 0.3.4-rc8 .. sven at jausoft.com - bugfix: AudioSwitch had a bad thread deadlock, while using an audio plugin, e.g. bitstreamout. After switching, audio was no more played. 2003-11-02: Version 0.3.4-rc7 .. sven at jausoft.com All Menue's with all sounds within Menue's should work now ! Also any missed sync (Audio/Video/SPU) should being fixed ! - using new sync code, with the new getSTC function therefore _you_have_to_ apply the patch: vdr-1.2.6-device-getSTC-v2.diff if not allready done (-> latest bitstreamout ) !! - the new a/v sync code does (simplified): delay_ticks ( (pktptsAudio-pktptsLastAudio)-(stcPTSAudio-stcPTSLastAudio ) ) where pktpts is PTS of the stream and stcPTS is PTS seen by the dvb device ! therefore, we do usleep for this diff ticks we should had being passed. - cleaned up transition back to case where a DevicePlay/DeviceClear is needed (-> within Empty now ) 2003-10-22: Version 0.3.4-rc6 .. sven at jausoft.com - added cPlayer default functions as well (AudioTrack..) - BITSTREAM - uses bitstreamout >= 0.48pre3 2003-10-14: Version 0.3.4-rc5 .. sven at jausoft.com - removed workarounds for vdr version < 1.2.6pre2 ! - BITSTREAM - uses bitstreamout >= 0.47c - const int cDvdPlayer::MaxSubpStreams = 16; - so hopefully 16 subtitles can be detected .. 2003-10-11: Version 0.3.4-rc4 .. sven at jausoft.com - BITSTREAM well, i got it to work well so the tee can be hot - no problem ;-) - made a stabilize bitstreamout-0.46g-jau01.patch, read ths incl. ChangeLog ! since this patch is not incl. within bitstreamout, this patch is a MUST HAVE ! - understanding how bitstreamout works, therefore simplifying the usage to a simple PlayAudio ;-) the only difference to just PlayAudio is that we do not feed the packet to another decoder .. - added an extra DeviceClear() at VTS_CHANGE, so (especially AudioPlugins) can re-sync .. DeviceClear is called at any place it won't disturb .. (manually switch track, audio, ..) 2003-10-11: Version 0.3.4-rc3 .. sven at jausoft.com - cleaned up Stop, no more hurting your ears on stopping plugin ;-) - still no audio after leaveing the plugin, any ideas ? - cleaned up usage of clearSeenSubpStream(), clearSeenAudioTrack(); - they do really clean up the lists, - they are called only if really intended ;-) - SPU fix: - cleared highlight button at startup (dvbspu.c) bug workaround. cDvbSpuDecoder::clearHighlight should set hlpsize members to -1 ! - fixed issue about: TV 4:3 DVD 16:9 Menu 4:3 -> cSpuDecoder::eSpuPanAndScan the 16:9 flag is cleared out in this case - propper button pos. ! - Tested with StarTrek - TheDirectorsCut - widescreeen Edition - BITSTREAM - bitstreamout plugin used only if avaiable and active - fixed the usage of PlayAudio -> bitstreamout, as seen in dvbplayer.c (StripAudioPackets) - index i was not used within "search" loop .. - BITSTREAM PROBLEM: - using the latest of all ;-) - bitstream out works sometimes, and sometimes not ! - in the latter case, i have to restart vdr :-( - the not case: - other recordings running - previous menu struggle arround .. - the tee was a very hot one ;-) - Force DvdNavigation (-> or HowTo play DVD games ..) - Key 5 DvdNavigationForce ON (not if progess display on) - Key Red Leave DvdNavigationForce - Assume you have a typical DVD game, so now you can navigate it - see Keys above (-> README) ! - Tested with DVD Die Monster AG, BonusMaterial.BoosDoorGame, Track #15 2003-10-09: Version 0.3.4-rc2 sven at jausoft.com This is the 2nd release candidate for 0.3.4 ! - cleaned up SPU usage .. - OSD keeps alive while subtitles -> it hides subtitles - .. 2003-10-09: Version 0.3.3-jau-p9 sven at jausoft.com This is a release candidate for 0.3.4 ! So please check and report ! - finish translations ( Lauri Tischler ) - "beauty" status progress line (title, chapters, ..) - ReadAHead defaults := 0 (recommended -> no memcpy) - cStatus usage e.g. for lcdproc (Martin Hammerschmid) - control/player GetIndex returns frame values now, like all vdr players/controllers ! therefore the lcd problem should being fixed ... - fixed slow motion backward - fixed send no more audio packets in slomo-fwd, pause 2003-10-07: Version 0.3.3-jau-p8 sven at jausoft.com BugFixes: - DVDActiveAndRunning checks active && running && nav ! - All public methods does check DVDActiveAndRunning now, therefore no seg.faults should happen. - Typos: 'prefered' -> 'Preferred' - 1st Jumper fast backward .. - cleaned up threading .. compared with dvbplayer .. - SPU ... - Enhanced fast forward/backward - incl. half a secound jumps (fwd>3, bwd>3) - slow backward works now with good pics - allows speeds 1-9 now - Added subtitle SPU handling alike the audio handling - Enhanced dvd-player's SPU and controller/interface locking/hide - Exits in plain mode (no more to recordings dir) - integrated patched dvd-bitstreamout-0.3.3.dif - changed key usage -> README 2003-10-06: Version 0.3.3-jau-p7 sven at jausoft.com - BugFixed TrickMode (-> FastBackward, SlowBackward ok with picture) - We have to go as many loops and blocks forward as long the I_Frame is being sliced ... Then we jump back IFrameBlocks * factor ! - Removed notes about a special libdvdnav version ;-) - Added ReadAHead setup value (defaults to 1) 2003-10-06: Version 0.3.3-jau-p6 sven at jausoft.com - bugfix: lock current audio, if set manually, so DVDNAV_AUDIO_STREAM_CHANGE won't affect, as well as the seen audio streams won't be cleaned ... the lock will be released if switching to a menu, or changing the title ! 2003-10-06: Version 0.3.3-jau-p5 sven at jausoft.com - Blue Goto title (enter title number) so you can seek manually to a specific title, you might want to look at "hidden" ones ;-) 2003-10-06: Version 0.3.3-jau-p4 sven at jausoft.com - Add to TitleString: TitleNo/ChapterNo + Angle if avaiable (outta xine ..), AudioType - Add new direct (keyboard/rc) navigation: - audio id - title - chapter - angle SEE README ! 2003-10-02: Version 0.3.3-jau-p3 sven at jausoft.com Keyboard (added, changed,fixed): - Left/Right fast forward/rewind - Red Goto position - Green 1 min. backward - Yellow 1 min. forward - 2 skip to next/previous chapter - 5 skip to next/previous chapter - OK ShowProgress Bar - 6/9 Move the ProgressBar in this mode .. .. see README ! now the behavior is like normal recording-playback, plus the mplayer-feature of moving the menu bar. - Impl./Enabled TimeSearch, ShowProgress, Goto, SkipSeconds, SkipFrames - using new: - PTSTicksToHMSm - BlocksToPGCTicks - PGCTicksToBlocks - GetIndex - GetTitleString - GetAspectString - NextPG, PreviousPG - BugFixed TrickMode (-> FastForward ok, any backward ok, but no picture) - REMOVED: #if defined(dvdnav_set_trick_speed) - introduced define CTRLDEBUG to enable DEBUG_CONTROL 2003-09-30: Version 0.3.3-jau-p2 sven at jausoft.com - audio track change to MP2 id's nor works properly - the former audioTrack member, ain'T initialized, but was used to determine the asked aid ! this never worked for MP2 aid's C1, C2, .. - now using currentNavAudioTrack = dvdnav_get_active_audio_stream(nav); - introduced define AUDIOIDDEBUG to enable DEBUG_AUDIO_ID - disabled all three debug def's as default DVDDEBUG, PTSDEBUG, AUDIOIDDEBUG 2002-05-12: Version 0.0.1 - Initial revision. vdr-plugin-dvd-0.3.7/Makefile000066400000000000000000000070171415711736600160430ustar00rootroot00000000000000# # Makefile for a Video Disk Recorder plugin # # $Id: Makefile,v 1.6 2008/12/23 16:49:04 lordzodiac Exp $ # The official name of this plugin. # This name will be used in the '-P...' option of VDR to load the plugin. # By default the main source file also carries this name. # PLUGIN = dvd ### The version number of this plugin (taken from the main source file): VERSION = $(shell grep 'static const char \*VERSION *=' $(PLUGIN).c | awk '{ print $$6 }' | sed -e 's/[";]//g') ### The directory environment: PKG_CONFIG ?= pkg-config PKGCFG = $(if $(VDRDIR),$(shell $(PKG_CONFIG) --variable=$(1) $(VDRDIR)/vdr.pc),$(shell $(PKG_CONFIG) --variable=$(1) vdr || $(PKG_CONFIG) --variable=$(1) ../../../vdr.pc)) LIBDIR = $(DESTDIR)$(call PKGCFG,libdir) LOCDIR = $(DESTDIR)$(call PKGCFG,locdir) TMPDIR ?= /tmp ### Allow user defined options to overwrite defaults: export CFLAGS = $(call PKGCFG,cflags) export CXXFLAGS = $(call PKGCFG,cxxflags) ### The version number of VDR's plugin API (taken from VDR's "config.h"): APIVERSION = $(call PKGCFG,apiversion) ### The name of the distribution archive: ARCHIVE = $(PLUGIN)-$(VERSION) PACKAGE = vdr-$(ARCHIVE) ### The name of the shared object file: SOFILE = libvdr-$(PLUGIN).so ### Includes and Defines (add further entries here): INCLUDES += DEFINES += -DPLUGIN_NAME_I18N='"$(PLUGIN)"' # to use xine videoout: ifdef POLLTIMEOUTS_BEFORE_DEVICECLEAR DEFINES += -DPOLLTIMEOUTS_BEFORE_DEVICECLEAR=$(POLLTIMEOUTS_BEFORE_DEVICECLEAR) endif LIBS = -ldvdnav -la52 ifdef DJBFFT LIBS += -L/usr/lib/djbfft/lib -ldjbfft endif ifdef DBG CXXFLAGS += -g -ggdb -O0 LDFLAGS += -g -ggdb -O0 else CXXFLAGS += -O3 LDFLAGS += -O3 -Wl,--retain-symbols-file,retain-sym endif ifdef RESUMEDIR DEFINES += -DRESUMEDIR=\"$(RESUMEDIR)\" endif ### The object files (add further files here): OBJS = $(PLUGIN).o dvddev.o player-dvd.o control-dvd.o dvdspu.o \ ca52.o i18n.o setup-dvd.o ### The main target: all: $(SOFILE) i18n ### Implicit rules: %.o: %.c $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) $< # Dependencies: MAKEDEP = g++ -MM -MG DEPFILE = .dependencies $(DEPFILE): Makefile @$(MAKEDEP) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.c) > $@ -include $(DEPFILE) ### Internationalization (I18N): PODIR = po I18Npo = $(wildcard $(PODIR)/*.po) I18Nmo = $(addsuffix .mo, $(foreach file, $(I18Npo), $(basename $(file)))) I18Nmsgs = $(addprefix $(LOCDIR)/, $(addsuffix /LC_MESSAGES/vdr-$(PLUGIN).mo, $(notdir $(foreach file, $(I18Npo), $(basename $(file)))))) I18Npot = $(PODIR)/$(PLUGIN).pot %.mo: %.po msgfmt -c -o $@ $< $(I18Npot): $(wildcard *.c) xgettext -C -cTRANSLATORS --no-wrap --no-location -k -ktr -ktrNOOP --msgid-bugs-address='' -o $@ `ls $^` %.po: $(I18Npot) msgmerge -U --no-wrap --no-location --backup=none -q -N $@ $< @touch $@ $(I18Nmsgs): $(LOCDIR)/%/LC_MESSAGES/vdr-$(PLUGIN).mo: $(PODIR)/%.mo install -D -m644 $< $@ .PHONY: i18n i18n: $(I18Nmo) $(I18Npot) install-i18n: $(I18Nmsgs) ### Targets: $(SOFILE): $(OBJS) retain-sym $(CXX) $(LDFLAGS) -shared $(OBJS) $(LIBS) -o $@ install-lib: $(SOFILE) install -D $^ $(LIBDIR)/$^.$(APIVERSION) install: install-lib install-i18n dist: clean @-rm -rf $(TMPDIR)/$(ARCHIVE) @mkdir $(TMPDIR)/$(ARCHIVE) @cp -a * $(TMPDIR)/$(ARCHIVE) @tar czf $(PACKAGE).tgz -C $(TMPDIR) --exclude SCCS $(ARCHIVE) @-rm -rf $(TMPDIR)/$(ARCHIVE) @echo Distribution package created as $(PACKAGE).tgz retain-sym: echo "VDRPluginCreator" > retain-sym clean: @-rm -f $(PODIR)/*.mo $(PODIR)/*.pot @-rm -f $(OBJS) $(DEPFILE) *.so *.tgz core* *~ vdr-plugin-dvd-0.3.7/README000066400000000000000000000101341415711736600152550ustar00rootroot00000000000000This is the DVD plugin for the Video Disk Recorder (VDR). +++ Project's homepage: http://www.jausoft.com/Files/vdr/vdr-dvd/ sf.net's CVS Archive: http://sourceforge.net/projects/dvdplugin/ Written by: Andreas Schultz Original Author http://www.cs.uni-magdeburg.de/~aschultz/dvd/ Sven Goethel New Maintainer http://www.jausoft.com/Files/vdr/ Marco Schluessler - cvs team Miko Wohlgemuth - cvs team +++ See the file COPYING for license information. Requirements: ------------- vdr >= 1.6.0 http://cadsoft.de/vdr/, ftp://ftp.cadsoft.de/vdr/Developer/ libdvdcss >= 20030724 http://www.videolan.org/libdvdcss/download.html libdvdnav >= 4.1.2 http://www.mplayerhq.hu/MPlayer/releases/dvdnav/ a52dec >= 0.7.4 http://liba52.sourceforge.net/ The plugin has been tested with the following versions: libdvdcss: 20030724 (cvs) libdvdnav: 4.1.2 liba52: 0.7.4 +++ libdvdcss is optional, but required for playing CSS protected DVDs. The libraries should be installed into /usr/lib, e.g.: # ./configure --prefix=/usr # make # make install But be aware to check your countries law, for example, nowadays it is prohibited in europe to workaround a _copy_protection_ - so just don't copy ;-) Accessing the DVD drive: ------------------------ The plugin uses libdvdcss to access CSS protected DVDs. Older version on the library worked best with DVDCSS_METHODE set. Newer versions no longer require. Note that the user id under which VDR runs needs to have write access to the DVD device in order to replay CSS protected DVDs. By default VDR expects the DVD drive to be located at /dev/dvd (which typically is a symbolic link to the actual device, for instance /dev/hdc). You can use the '-C' option to overwrite this, as in vdr -P"dvd -C/media/dvd" Navigation in DVD mode: ----------------------- The following navigation keys are available in DVD mode: Key Function ------------------------------------------------------------- Red Goto position (enter time) Green 1 min. backward Yellow 1 min. forward Blue Goto title (enter title number) Back Stop Replay - Exit Ok toggle progess display (this will mess up any subtitles) Up, kPlay playback Down, kPause pauses playback Left/Right rewind/forward (fast if play mode, slow if pause mode) kFastRew/kFastFwd kAudio select audio track 2 skip to next subtitle ( if "no subtitle" is reached, progress display on, if subtitle language code is prefixed with "forced-" (eg. 'forced-en') only forced subs will be shown ) 3 skip to next angle (skip copyright notice) 4, kPrev skip to previous chapter 6, kNext skip to next chapter 7, kChanDn skip to previous title 9, kChanUp skip to next title 5 DvdNavigationForce ON / go to DVD Root menu (if progess display on) 8 go to DVD Title menu 0 go to DVD Audio menu (only avaiable if progess display off) In DVD-Menu: 2/8/4/6,5 DVD menu Up/Down/Left/Right, OK control's Left/Right/Up/Down OK also work when in menuspace Red Leave DvdNavigationForce Green skip to previous title Yellow skip to next title Goto title (enter title number) Notes: ======= if you use next/prev title, and you are e.g. jumping from title 3 to title 13, then this is not a bug, but a feature of the author of the current DVD ! so you can use Goto title, to manually check a specific one .. this way enables you to look at "hidden" titles ;-) HowTo play DVD games .. ------------------------ Assume you have a typical DVD game, so you need to enter/force DVD Navigation mode ! - Key 5 DvdNavigationForce ON (not if progess display on) - Key Red Leave DvdNavigationForce BUG: ==== if you have subtitles enabled by setup, or by key, the osd / progress display, may disappear, but believes it is still visible .. so just press OK one more time to make it hide for real. vdr-plugin-dvd-0.3.7/ca52.c000066400000000000000000000330111415711736600152720ustar00rootroot00000000000000/* * DVD Player plugin for VDR * * Copyright (C) 2001.2002 Andreas Schultz * * This code is distributed under the terms and conditions of the * GNU GENERAL PUBLIC LICENSE. See the file COPYING for details. * */ #include #include #ifndef __QNXNTO__ #include #elif defined(__QNXNTO__) #include #include #include #ifdef WORDS_BIGENDIAN #define bswap_16(x) ENDIAN_LE16(x) #define bswap_32(x) ENDIAN_LE32(x) #define bswap_64(x) ENDIAN_LE64(x) #else #define bswap_16(x) ENDIAN_BE16(x) #define bswap_32(x) ENDIAN_BE32(x) #define bswap_64(x) ENDIAN_BE64(x) #endif #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "dvddev.h" #include "setup-dvd.h" #include "tools-dvd.h" #include "player-dvd.h" #include "ca52.h" // #define A52DEBUG #ifdef A52DEBUG #warning A52DEBUG is defined #define DEBUG_A52(format, args...) fprintf (stderr, format, ## args) #else #define DEBUG_A52(format, args...) #endif static const uint8_t burstHeader[4] = { 0xf8, 0x72, 0x4e, 0x1f }; A52decoder::A52decoder(cDvdPlayer &ThePlayer): player(ThePlayer) { syncMode = ptsCopy; apts = 0; state = a52_init (MM_ACCEL_DJBFFT); // state = a52_init(MM_ACCEL_X86_MMXEXT); blk_buf = (uchar *)malloc(25*1024); blk_ptr = blk_buf; blk_size = 0; setup(); } A52decoder::~A52decoder() { if (blk_buf) free(blk_buf); blk_buf=NULL; } void A52decoder::setup(void) { flags = A52_DOLBY; level = DVDSetup.Gain; bias = 384; } #define convert(x) x>0x43c07fff ? bswap_16(0x7fff) : x < 0x43bf8000 ? bswap_16(0x8000) : bswap_16(x - 0x43c00000); #if 0 static inline int16_t bswap(int16_t i) { return bswap_16(i); } inline int16_t A52decoder::convert (int32_t i) { if (i > 0x43c07fff) return bswap(32767); else if (i < 0x43bf8000) return bswap(-32768); else return bswap(i - 0x43c00000); } #endif inline void A52decoder::float_to_int (float * _f, int16_t * s16, int flags) { int i; int32_t * f = (int32_t *) _f; switch (flags) { case A52_MONO: { int ic=0; for (i = 0; i < 256; i++) { s16[ic] = s16[ic+1] = s16[ic+2] = s16[ic+3] = 0; s16[ic+4] = convert (f[i]); ic+=5; } break; } case A52_CHANNEL: case A52_STEREO: case A52_DOLBY: { int ic=0; for (i = 0; i < 256; i++) { s16[ic] = convert (f[i]); s16[ic+1] = convert (f[i+256]); ic +=2; } break; } case A52_3F: { int ic=0; for (i = 0; i < 256; i++) { s16[ic] = convert (f[i]); s16[ic+1] = convert (f[i+512]); s16[ic+2] = s16[ic+3] = 0; s16[ic+4] = convert (f[i+256]); ic +=5; } break; } case A52_2F2R: { int ic=0; for (i = 0; i < 256; i++) { s16[ic] = convert (f[i]); s16[ic+1] = convert (f[i+256]); s16[ic+2] = convert (f[i+512]); s16[ic+3] = convert (f[i+768]); ic +=4; } break; } case A52_3F2R: { int ic=0; for (i = 0; i < 256; i++) { s16[ic] = convert (f[i]); s16[ic+1] = convert (f[i+256]); s16[ic+2] = convert (f[i+512]); s16[ic+3] = convert (f[i+768]); s16[ic+4] = convert (f[i+1024]); ic +=5; } break; } case A52_MONO | A52_LFE: { int ic=0; for (i = 0; i < 256; i++) { s16[ic] = s16[ic+1] = s16[ic+2] = s16[ic+3] = 0; s16[ic+4] = convert (f[i+256]); s16[ic+5] = convert (f[i]); ic +=6; } break; } case A52_CHANNEL | A52_LFE: case A52_STEREO | A52_LFE: case A52_DOLBY | A52_LFE: { int ic=0; for (i = 0; i < 256; i++) { s16[ic] = convert (f[i+256]); s16[ic+1] = convert (f[i+512]); s16[ic+2] = s16[ic+3] = s16[ic+4] = 0; s16[ic+5] = convert (f[i]); ic +=6; } break; } case A52_3F | A52_LFE: { int ic=0; for (i = 0; i < 256; i++) { s16[ic] = convert (f[i+256]); s16[ic+1] = convert (f[i+768]); s16[ic+2] = s16[ic+3] = 0; s16[ic+4] = convert (f[i+512]); s16[ic+5] = convert (f[i]); ic +=6; } break; } case A52_2F2R | A52_LFE: { int ic=0; for (i = 0; i < 256; i++) { s16[ic] = convert (f[i+256]); s16[ic+1] = convert (f[i+512]); s16[ic+2] = convert (f[i+768]); s16[ic+3] = convert (f[i+1024]); s16[ic+4] = 0; s16[ic+5] = convert (f[i]); ic +=6; } break; } case A52_3F2R | A52_LFE: { int ic=0; for (i = 0; i < 256; i++) { s16[ic] = convert (f[i+256]); s16[ic+1] = convert (f[i+768]); s16[ic+2] = convert (f[i+1024]); s16[ic+3] = convert (f[i+1280]); s16[ic+4] = convert (f[i+512]); s16[ic+5] = convert (f[i]); ic +=6; } break; } } } // data=PCM samples, 16 bit, LSB first, 48kHz, stereo void A52decoder::init_ipack(int p_size, uint32_t pktpts, uint8_t SubStreamId) { int header = pktpts ? 5 :0; int length = 10 + header + p_size; blk_ptr[0] = 0x00; blk_ptr[1] = 0x00; blk_ptr[2] = 0x01; blk_ptr[3] = PRIVATE_STREAM1; blk_ptr[4] = (length >> 8) & 0xff; blk_ptr[5] = length & 0xff; blk_ptr[6] = 0x84; blk_ptr[7] = pktpts ? 0x80 : 0; blk_ptr[8] = header; blk_ptr += 9; if (header) { cPStream::toPTS(blk_ptr, pktpts); } blk_ptr += header; /** * struct LPCMHeader { int id:8; // id int frame_count:8; // number of frames int access_ptr:16; // first acces unit pointer, i.e. start of audio frame bool emphasis:1; // audio emphasis on-off bool mute:1; // audio mute on-off bool reserved:1; // reserved int frame_number:5; // audio frame number int quant_wlen:2; // quantization word length int sample_freq:2; // audio sampling frequency (48khz=0, 96khz=1, 44,1khz=2, 32khz=3) bool reserved2:1; // reserved int chan_count:3; // number of audio channels - 1 (e.g. stereo = 1) int dyn_range_ctrl:8; // dynamic range control (0x80 if off) }; * */ blk_ptr[0] = aLPCM | SubStreamId; // substream ID // other stuff (see DVB specs), may be ignored by driver // but try to set it up correctly .. blk_ptr[1] = 0x07; // number of frames blk_ptr[2] = 0x00; // start of audio frame blk_ptr[3] = 0x04; // start of audio frame blk_ptr[4] = 0x0C; // emph, mute, res, frame_num blk_ptr[5] = 0x01; // quantwlen, samplefreq, channels (48kHz, stereo) blk_ptr[6] = 0x80; // dynam. range ctrl (off) blk_ptr += 7; blk_size += 16 + header; } int A52decoder::convertSample(int flags, a52_state_t * _state, uint32_t pktpts, uint8_t SubStreamId) { int chans = -1; sample_t * _samples = a52_samples(_state); #ifdef LIBA52_DOUBLE float samples[256 * 6]; int i; for (i = 0; i < 256 * 6; i++) samples[i] = _samples[i]; #else float * samples = _samples; #endif flags &= A52_CHANNEL_MASK | A52_LFE; if (flags & A52_LFE) chans = 6; else if (flags & 1) /* center channel */ chans = 5; else switch (flags) { case A52_2F2R: chans = 4; break; case A52_CHANNEL: case A52_STEREO: case A52_DOLBY: chans = 2; break; default: return 1; } init_ipack((int) 256 * sizeof (int16_t) * chans, pktpts, SubStreamId); float_to_int (samples, (int16_t *)blk_ptr, flags); // push data to driver blk_ptr += (int) 256 * sizeof (int16_t) * chans; blk_size += (int) 256 * sizeof (int16_t) * chans; return 0; } void A52decoder::clear() { DEBUG_A52("A52decoder::clear()\n"); blk_ptr = blk_buf; blk_size = 0; apts = 0; a52asm.clear(); } /* from a52a.pdf: * * The AC-3 audio access unit (AU) or presentation unit (PU) * is an AC-3 sync frame. The AC-3 sync frame contains 1 536 audio * samples. The duration of an AC-3 access (or presentation) unit * is 32 ms for audio sampled at 48 kHz, approximately 34.83 ms for * audio sampled at 44.1 kHz, and 48 ms for audio sampled at 32 kHz. * * in 90kHz pts cycles: * 48kHz = 2880 * 44.1kHz = 3134.69 * 32kHz = 4320 * * for now, lets assume we always have 48kHz!! */ void A52decoder::decode(uint8_t * start, int size, uint32_t pktpts, uint8_t SubStreamId) { int bit_rate; //do we enter with an empty buffer bool sendPTS = a52asm.used() < 40; DEBUG_A52("pts: %d %8d %8d, %8d\n", sendPTS, apts, pktpts, apts - pktpts); if (a52asm.used() == 0 || apts == 0 || apts > (pktpts + 2880) || (apts + 5760) < pktpts) { DEBUG_A52("reseting Audio PTS\n"); apts = pktpts; } blk_ptr = blk_buf; blk_size = 0; while (size) { int res = a52asm.put(start, size, pktpts); start += res; size -= res; if ( res==0 ) { clear(); break; } if (a52asm.ready()) { int length; A52frame *frm = a52asm.get(); if (!frm) goto error; length = a52_syncinfo (frm->frame, &flags, &sample_rate, &bit_rate); if (!length) { delete frm; continue; } if (syncMode == ptsGenerate) { pktpts = apts; sendPTS = true; } int i; setup(); flags |= A52_ADJUST_LEVEL; if (a52_frame (state, frm->frame, &flags, &level, bias)) goto error; if (!DVDSetup.AC3dynrng) a52_dynrng (state, NULL, NULL); for (i = 0; i < 6; i++) { if (a52_block (state)) goto error; if (sendPTS) { player.seenAPTS(pktpts); DEBUG_A52("sending PTS\n"); } if (convertSample(flags, state, sendPTS ? pktpts : 0, SubStreamId)) goto error; pktpts = 0; sendPTS = false; } apts += 2880; delete frm; continue; error: DEBUG_A52("error\n"); sendPTS = false; apts = 0; if (frm) delete frm; } } if (blk_size > 0) player.cbPlayAudio(blk_buf, blk_size); } A52frame::A52frame(int datasize, int frmsize, uint32_t apts) { frame = new uint8_t[datasize+2]; frame[0] = 0x0b; frame[1] = 0x77; size = frmsize; pos = 2; pts = apts; } A52frame::~A52frame() { delete[] frame; } A52assembler::A52assembler() { curfrm = NULL; syncword = 0xffff; } A52assembler::~A52assembler() { if (curfrm) delete curfrm; } void A52assembler::clear(void) { if (curfrm) delete curfrm; curfrm = NULL; syncword = 0xffff; } A52frame *A52assembler::get(void) { A52frame *frm = curfrm; curfrm = NULL; syncword = 0xffff; return frm; } int A52assembler::used(void) { if (curfrm) return curfrm->pos; return 0; } bool A52assembler::ready(void) { return curfrm && curfrm->pos == curfrm->size; }; #ifndef WORDS_BIGENDIAN # define char2short(a,b) ((((b) << 8) & 0xffff) ^ ((a) & 0xffff)) # define shorts(a) (a) #else # define char2short(a,b) ((((a) << 8) & 0xffff) ^ ((b) & 0xffff)) # define shorts(a) char2short(((a) & 0xff),(((a) >> 8) & 0xff)); #endif int A52assembler::put(uint8_t *buf, int len, uint32_t pts) { if (ready()) return 0; uint8_t *data = buf; uint8_t *end = data + len; while(syncword != char2short(0x77, 0x0b)) { if (data >= end) { DEBUG_A52("skipping %d bytes without finding anything\n", data - buf); return data - buf; } syncword = (syncword << 8) | *data++; } int frmsize = 0; if (!curfrm) { int datasize = 1920; if (end - data > 3) datasize = frmsize = parse_syncinfo(data); curfrm = new A52frame(datasize, frmsize, pts); } if (curfrm->size == 0) { if (curfrm->pos < 6) { frmsize = 6 - curfrm->pos; } else { curfrm->size = parse_syncinfo(curfrm->frame+2); frmsize = curfrm->size - curfrm->pos; } } else frmsize = curfrm->size - curfrm->pos; if (frmsize > end - data) frmsize = end - data; if (frmsize<0) return 0; memcpy(curfrm->frame + curfrm->pos, data, frmsize); curfrm->pos += frmsize; return data + frmsize - buf; } // Parse a syncinfo structure, minus the sync word int A52assembler::parse_syncinfo(uint8_t *data) { static int rate[] = { 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 448, 512, 576, 640}; int frmsizecod; int bitrate; if (data[3] >= 0x60) /* bsid >= 12 */ return 0; frmsizecod = data[2] & 63; if (frmsizecod >= 38) return 0; bitrate = rate [frmsizecod >> 1]; switch (data[2] & 0xc0) { case 0: return 4 * bitrate; case 0x40: return 2 * (320 * bitrate / 147 + (frmsizecod & 1)); case 0x80: return 6 * bitrate; default: return 0; } } vdr-plugin-dvd-0.3.7/ca52.h000066400000000000000000000034071415711736600153050ustar00rootroot00000000000000/* * DVD Player plugin for VDR * * Copyright (C) 2001.2002 Andreas Schultz * * This code is distributed under the terms and conditions of the * GNU GENERAL PUBLIC LICENSE. See the file COPYING for details. * */ #ifndef __VDR_cA52_H #define __VDR_cA52_H #include extern "C" { #include #include } #include #include "tools-dvd.h" #include "player-dvd.h" class A52frame { public: uint32_t pts; int size; uint8_t *frame; int pos; public: A52frame(int datasize, int frmsize, uint32_t apts); ~A52frame(); }; class A52assembler { private: A52frame *curfrm; uint16_t syncword; int parse_syncinfo(uint8_t *data); public: A52assembler(); ~A52assembler(); int put(uint8_t *buf, int len, uint32_t pts); A52frame *get(void); void clear(void); int used(void); bool ready(void); }; class A52decoder { public: enum eSyncMode { ptsCopy, ptsGenerate }; private: cDvdPlayer &player; A52assembler a52asm; a52_state_t * state; uint8_t burst[6144]; int sample_rate; int flags; sample_t level, bias; eSyncMode syncMode; uint32_t apts; uchar *blk_buf; uchar *blk_ptr; int blk_size; void setup(void); void float_to_int (float * _f, int16_t * s16, int flags); void init_ipack(int p_size, uint32_t pktpts, uint8_t SubStreamId); int convertSample (int flags, a52_state_t * _state, uint32_t pktpts, uint8_t SubStreamId); public: A52decoder(cDvdPlayer &ThePlayer); ~A52decoder(); void setSyncMode(eSyncMode mode) { syncMode = mode; }; eSyncMode getSyncMode(void) { return syncMode; } void decode(uint8_t * start, int size, uint32_t pktpts, uint8_t SubStreamId); void clear(); }; #endif //__VDR_cA52_H vdr-plugin-dvd-0.3.7/common-dvd.h000066400000000000000000000045021415711736600166130ustar00rootroot00000000000000/* * DVD Player plugin for VDR * * Copyright (C) 2001.2002 Andreas Schultz * * This code is distributed under the terms and conditions of the * GNU GENERAL PUBLIC LICENSE. See the file COPYING for details. * */ #ifndef __COMMON_DVD_H #define __COMMON_DVD_H //#define CTRLDEBUG //#define DVDDEBUG //#define PTSDEBUG //#define AUDIOIDDEBUG //#define AUDIOPLAYDEBUG //#define NAVDEBUG //#define SUBPDEBUG //#define IFRAMEDEBUG //#define IFRAMEDEBUG2 #ifdef DVDDEBUG #define DEBUGDVD(format, args...) printf (format, ## args) #else #define DEBUGDVD(format, args...) #endif #ifdef PTSDEBUG #define DEBUGPTS(format, args...) printf (format, ## args) #else #define DEBUGPTS(format, args...) #endif #ifdef AUDIOIDDEBUG #define DEBUG_AUDIO_ID(format, args...) printf (format, ## args) #else #define DEBUG_AUDIO_ID(format, args...) #endif #ifdef CTRLDEBUG #define DEBUG_CONTROL(format, args...) printf (format, ## args) #else #define DEBUG_CONTROL(format, args...) #endif #ifdef AUDIOPLAYDEBUG #define DEBUG_AUDIO_PLAY(format, args...) printf (format, ## args) #else #define DEBUG_AUDIO_PLAY(format, args...) #endif #ifdef AUDIOPLAYDEBUG2 #define DEBUG_AUDIO_PLAY2(format, args...) printf (format, ## args) #else #define DEBUG_AUDIO_PLAY2(format, args...) #endif #ifdef NAVDEBUG #define DEBUG_NAV(format, args...) printf (format, ## args) #else #define DEBUG_NAV(format, args...) #endif #ifdef NAV0DEBUG #define DEBUG_NAV0(format, args...) printf (format, ## args); fflush(NULL) #else #define DEBUG_NAV0(format, args...) #endif #ifdef SUBPDEBUG #define DEBUG_SUBP_ID(format, args...) printf (format, ## args) #else #define DEBUG_SUBP_ID(format, args...) #endif #ifdef SUBPDECDEBUG #define DEBUG_SUBP_DEC(format, args...) printf (format, ## args) #else #define DEBUG_SUBP_DEC(format, args...) #endif #ifdef IFRAMEDEBUG #define DEBUG_IFRAME(format, args...) printf (format, ## args) #else #define DEBUG_IFRAME(format, args...) #endif #ifdef IFRAMEDEBUG2 #define DEBUG_IFRAME2(format, args...) printf (format, ## args) #else #define DEBUG_IFRAME2(format, args...) #endif #ifdef PTSDEBUG #define DEBUG_PTS(format, args...) printf (format, ## args) #else #define DEBUG_PTS(format, args...) #endif #ifdef PTSDEBUG2 #define DEBUG_PTS2(format, args...) printf (format, ## args) #else #define DEBUG_PTS2(format, args...) #endif #endif // __COMMON_DVD_H vdr-plugin-dvd-0.3.7/control-dvd.c000066400000000000000000000521671415711736600170100ustar00rootroot00000000000000/* * DVD Player plugin for VDR * * Copyright (C) 2001.2002 Andreas Schultz * * This code is distributed under the terms and conditions of the * GNU GENERAL PUBLIC LICENSE. See the file COPYING for details. * */ #include #include #include #include #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "tools-dvd.h" #include "player-dvd.h" #include "control-dvd.h" #define MENUTIMEOUT 120 // seconds #define MAXWAIT4EPGINFO 10 // seconds #define MODETIMEOUT 3 // seconds bool cDvdPlayerControl::dvd_active = false; #define DVDDEBUG #define DEBUG_KEY(format, args...) #define DEBUG_SHOW(format, args...) #define DEBUG_OSDCTRL(format, args...) //#define DEBUG_KEY(format, args...) printf (format, ## args); fflush(NULL) //#define DEBUG_SHOW(format, args...) printf (format, ## args); fflush(NULL) //#define DEBUG_OSDCTRL(format, args...) printf (format, ## args); fflush(NULL) // --- cDvdPlayerControl ----------------------------------------------------- cDvdPlayerControl::cDvdPlayerControl(void) : cControl(player = new cDvdPlayer()) { assert(dvd_active == false); dvd_active = true; visible = modeOnly = shown = displayFrames = false; osdTaker = NULL; lastCurrent = lastTotal = -1; lastPlay = lastForward = false; lastSpeed = -1; displayReplay = NULL; timeoutShow = 0; inputActive = NoneInput; inputHide = true; forceDvdNavigation = false; player->setController(this); cStatus::MsgReplaying(this, "DVD", NULL, true); } cDvdPlayerControl::~cDvdPlayerControl() { Hide(); cStatus::MsgReplaying(this, NULL, NULL, false); Stop(); assert(dvd_active == true); dvd_active = false; delete player; } bool cDvdPlayerControl::Active(void) { return player && player->Active(); } void cDvdPlayerControl::Stop(void) { if (player) player->Stop(); } void cDvdPlayerControl::Pause(void) { if (player) player->Pause(); } void cDvdPlayerControl::Play(void) { if (player) player->Play(); } void cDvdPlayerControl::Forward(void) { if (player) player->Forward(); } void cDvdPlayerControl::Backward(void) { if (player) player->Backward(); } void cDvdPlayerControl::SkipSeconds(int Seconds) { if (player) player->SkipSeconds(Seconds); } int cDvdPlayerControl::SkipFrames(int Frames) { return player ? player->SkipFrames(Frames) : -1; } bool cDvdPlayerControl::GetIndex(int &Current, int &Total, bool SnapToIFrame) { return player ? player->GetIndex(Current, Total, SnapToIFrame) : false; } bool cDvdPlayerControl::GetReplayMode(bool &Play, bool &Forward, int &Speed) { return player && player->GetReplayMode(Play, Forward, Speed); } void cDvdPlayerControl::Goto(int Seconds, bool Still) { if (player) player->Goto(Seconds, Still); } void cDvdPlayerControl::OsdClose() { DELETENULL(displayReplay); } void cDvdPlayerControl::OsdOpen(void) { if (visible) { DEBUG_OSDCTRL("DVD-Ctrl: OsdOpen: allready visible\n"); return; } if (OsdTaken((void*)this)) { if (player) { DEBUG_OSDCTRL("DVD-Ctrl: OsdOpen: AllreadyOpen -> HideSPU ... \n"); player->HideSPU(); } } if (!TakeOsd((void *)this)) { DEBUG_OSDCTRL("DVD-Ctrl: OsdOpen: AllreadyOpen -> !visible, osdTaken\n"); visible = false; } else { DEBUG_OSDCTRL("DVD-Ctrl: OsdOpen: visible\n"); visible = true; displayReplay = Skins.Current()->DisplayReplay(modeOnly); } } void cDvdPlayerControl::ShowTimed(int Seconds) { if (modeOnly) Hide(); if (!visible) { shown = ShowProgress(true); timeoutShow = (shown && Seconds > 0) ? time(NULL) + Seconds : 0; } } void cDvdPlayerControl::Show(void) { ShowTimed(); } void cDvdPlayerControl::Hide(void) { DEBUG_SHOW("DVD-Ctrl: Hide\n"); TakeOsd((void *)(-1)); // somebody else (external) might take the osd .. if (player) player->HideSPU(); HideOwnOsd(); } void cDvdPlayerControl::HideOwnOsd(void) { DEBUG_SHOW("DVD-Ctrl: HideOwnOsd: visible=%d\n", visible); if (visible) { OsdClose(); #if VDRVERSNUM >= 10500 SetNeedsFastResponse(false); #else needsFastResponse = false; #endif visible = modeOnly = false; lastPlay = lastForward = false; lastSpeed = -1; } } bool cDvdPlayerControl::TakeOsd(void * owner) { if (owner == (void *)-1 || !OsdTaken(owner) || osdTaker == (void *)-1) { DEBUG_OSDCTRL("DVD-Ctrl: TakeOsd(%p) new owner!\n", owner); osdTaker = owner; // not taken by other: new owner return true; } else { DEBUG_OSDCTRL("DVD-Ctrl: TakeOsd(%p) not taken! %p \n", owner,osdTaker); } return false; } bool cDvdPlayerControl::OsdTaken(void *me) { if (osdTaker && !cOsd::IsOpen()) { DEBUG_OSDCTRL("DVD-Ctrl: OsdTaken(%p) !IsOpen->taker:=NULL\n", me); osdTaker = NULL; // update info .. } DEBUG_OSDCTRL("DVD-Ctrl: OsdTaken(%p) != %p := %d \n", me, osdTaker, osdTaker!=me); return osdTaker != NULL && osdTaker != me; } bool cDvdPlayerControl::OsdVisible(void *me) { return visible || OsdTaken(me) ; } void cDvdPlayerControl::ShowMode(void) { if (Setup.ShowReplayMode && inputActive == NoneInput) { bool Play, Forward; int Speed; if (GetReplayMode(Play, Forward, Speed) && (!visible || Play != lastPlay || Forward != lastForward || Speed != lastSpeed)) { bool NormalPlay = (Play && Speed == -1); if (!visible) { if (NormalPlay) return; // no need to do indicate ">" unless there was a different mode displayed before modeOnly = true; // open small display OsdOpen(); } if (!visible) return; if (modeOnly && !timeoutShow && NormalPlay) timeoutShow = time(NULL) + MODETIMEOUT; displayReplay->SetMode(Play, Forward, Speed); lastPlay = Play; lastForward = Forward; lastSpeed = Speed; } } } const char *cDvdPlayerControl::GetDisplayHeaderLine() { char *titleinfo_str = NULL; char *title_str = NULL; char *aspect_str = NULL; const char *audiolang_str = NULL; const char *spulang_str = NULL; static char title_buffer[256]; title_buffer[0] = 0; if (!player) return title_buffer; titleinfo_str = player->GetTitleInfoString(); title_str = player->GetTitleString(); aspect_str = player->GetAspectString(); player->GetAudioLanguageStr(&audiolang_str); player->GetSubtitleLanguageStr(&spulang_str); snprintf(title_buffer, sizeof(title_buffer), "%s, %s, %s, %s, %s ", titleinfo_str, audiolang_str, spulang_str, aspect_str, title_str); free(titleinfo_str); free(title_str); free(aspect_str); return title_buffer; } bool cDvdPlayerControl::ShowProgress(bool Initial) { int Current, Total; const char *title_buffer = NULL; static char last_title_buffer[256]; if (GetIndex(Current, Total) && Total > 0) { DEBUG_SHOW("DVD-Ctrl: ShowProgress: ... \n"); if (!visible) { #if VDRVERSNUM >= 10500 SetNeedsFastResponse(true); #else needsFastResponse = true; #endif OsdOpen(); } if (!visible) return false; if (Initial) { lastCurrent = lastTotal = -1; last_title_buffer[0] = 0; displayReplay->SetTitle("unknown title"); cStatus::MsgReplaying(this, "unknown title", NULL, true); } if (player) { title_buffer = GetDisplayHeaderLine(); if (strcmp(title_buffer, last_title_buffer)) { displayReplay->SetTitle(title_buffer); if (!Initial) displayReplay->Flush(); cStatus::MsgReplaying(this, title_buffer, NULL, true); strcpy(last_title_buffer, title_buffer); } } if (Current != lastCurrent || Total != lastTotal) { displayReplay->SetProgress(Current, Total); displayReplay->SetTotal(IndexToHMSF(Total)); displayReplay->SetCurrent(IndexToHMSF(Current, displayFrames)); lastCurrent = Current; if (!Initial) displayReplay->Flush(); } lastTotal = Total; ShowMode(); return true; } else { DEBUG_SHOW("DVD-Ctrl: ShowProgress: nope \n"); } return false; } void cDvdPlayerControl::InputIntDisplay(const char *msg, int val) { char buf[120]; snprintf(buf, sizeof(buf), "%s %d", msg, val); displayReplay->SetJump(buf); } void cDvdPlayerControl::InputIntProcess(eKeys Key, const char *msg, int &val) { switch (Key) { case k0 ... k9: val = val * 10 + Key - k0; InputIntDisplay(msg, val); break; case kOk: case kLeft: case kRight: case kUp: case kDown: switch (inputActive) { case TimeSearchInput: break; case TrackSearchInput: if (player) player->GotoTitle(val); break; default: break; } inputActive = NoneInput; break; default: inputActive = NoneInput; break; } if (inputActive == NoneInput) { if (inputHide) Hide(); else displayReplay->SetJump(NULL); ShowMode(); } } void cDvdPlayerControl::TrackSearch(void) { inputIntVal = 0; inputIntMsg = "Track: "; inputHide = false; Show(); if (visible) inputHide = true; else return; timeoutShow = 0; InputIntDisplay(inputIntMsg, inputIntVal); inputActive = TrackSearchInput; } void cDvdPlayerControl::TimeSearchDisplay(void) { char buf[64]; strcpy(buf, trVDR("Jump: ")); int len = strlen(buf); char h10 = '0' + (timeSearchTime >> 24); char h1 = '0' + ((timeSearchTime & 0x00FF0000) >> 16); char m10 = '0' + ((timeSearchTime & 0x0000FF00) >> 8); char m1 = '0' + (timeSearchTime & 0x000000FF); char ch10 = timeSearchPos > 3 ? h10 : '-'; char ch1 = timeSearchPos > 2 ? h1 : '-'; char cm10 = timeSearchPos > 1 ? m10 : '-'; char cm1 = timeSearchPos > 0 ? m1 : '-'; sprintf(buf + len, "%c%c:%c%c", ch10, ch1, cm10, cm1); displayReplay->SetJump(buf); } void cDvdPlayerControl::TimeSearchProcess(eKeys Key) { #define STAY_SECONDS_OFF_END 10 int Seconds = (timeSearchTime >> 24) * 36000 + ((timeSearchTime & 0x00FF0000) >> 16) * 3600 + ((timeSearchTime & 0x0000FF00) >> 8) * 600 + (timeSearchTime & 0x000000FF) * 60; #if VDRVERSNUM >= 10703 int Current = int(lastCurrent / FramesPerSecond()); int Total = int(lastTotal / FramesPerSecond()); #else int Current = (lastCurrent / FRAMESPERSEC); int Total = (lastTotal / FRAMESPERSEC); #endif switch (Key) { case k0 ... k9: if (timeSearchPos < 4) { timeSearchTime <<= 8; timeSearchTime |= Key - k0; timeSearchPos++; TimeSearchDisplay(); } break; case kLeft: case kRight: { int dir = (Key == kRight ? 1 : -1); if (dir > 0) Seconds = min(Total - Current - STAY_SECONDS_OFF_END, Seconds); switch ( inputActive ) { case TimeSearchInput: SkipSeconds(Seconds * dir); break; case TrackSearchInput: break; default: break; } inputActive = NoneInput; break; } case kPlay: case kUp: case kPause: case kDown: case kOk: Seconds = min(Total - STAY_SECONDS_OFF_END, Seconds); switch (inputActive) { case TimeSearchInput: Goto(Seconds, Key == kDown); break; case TrackSearchInput: break; default: break; } inputActive = NoneInput; break; default: inputActive = NoneInput; break; } if (inputActive == NoneInput) { if (inputHide) Hide(); else displayReplay->SetJump(NULL); ShowMode(); } } void cDvdPlayerControl::TimeSearch(void) { timeSearchTime = timeSearchPos = 0; inputHide = false; Show(); if (visible) inputHide = true; else return; timeoutShow = 0; TimeSearchDisplay(); inputActive = TimeSearchInput; } bool cDvdPlayerControl::DvdNavigation(eKeys Key) { if (!player) return false; HideOwnOsd(); if(player) player->DrawSPU(); switch (Key) { case kUp: case k2: player->selectUpButton(); break; case kDown: case k8: player->selectDownButton(); break; case kLeft: case k4: player->selectLeftButton(); break; case kRight: case k6: player->selectRightButton(); break; case kOk: case k5: player->activateButton(); break; case k1: player->callRootMenu(); break; case k3: player->callTitleMenu(); break; case k7: player->callSubpMenu(); break; case k9: player->callAudioMenu(); break; default: return false; } return true; } void cDvdPlayerControl::UpdateShow(bool force) { DEBUG_SHOW("DVD-Ctrl: updateShow: force=%d, visible=%d, modeOnly=%d\n", force, visible, modeOnly); if (visible || force) { if (timeoutShow && time(NULL) > timeoutShow) { Hide(); ShowMode(); timeoutShow = 0; return; } if (modeOnly) ShowMode(); else shown = ShowProgress(!shown) || shown; } else { const char *title_buffer = NULL; static char last_title_buffer[256]; if (player) { title_buffer = GetDisplayHeaderLine(); if (strcmp(title_buffer, last_title_buffer)) { strcpy(last_title_buffer, title_buffer); cStatus::MsgReplaying(this, title_buffer, NULL, true); } } } } eOSState cDvdPlayerControl::ProcessKey(eKeys Key) { DEBUG_KEY("DVD-Ctrl: ProcessKey BEGIN\n"); eOSState state = cOsdObject::ProcessKey(Key); if (state != osUnknown) { Hide(); DEBUG_KEY("cDvdPlayerControl::ProcessKey key: %d 0x%X, state=%d 0x%X FIN!\n", Key, Key, state, state); DEBUG_KEY("DVD-Ctrl: ProcessKey END\n"); return state; } DEBUG_KEY("cDvdPlayerControl::ProcessKey key: %d 0x%X, state=unknown\n", Key, Key); if (player && player->DVDRemoveable()) { DEBUG_KEY("cDvdPlayerControl::ProcessKey DVDRemoveable -> Stop\n"); Hide(); DEBUG_KEY("DVD-Ctrl: ProcessKey END\n"); return osEnd; } if (!Active()) { DEBUG_KEY("cDvdPlayerControl::ProcessKey !Active -> Stop\n"); Hide(); Stop(); DEBUG_KEY("DVD-Ctrl: ProcessKey END\n"); return osEnd; } UpdateShow(); bool DisplayedFrames = displayFrames; displayFrames = false; if (inputActive != NoneInput && Key != kNone) { switch (inputActive) { case TimeSearchInput: TimeSearchProcess(Key); break; case TrackSearchInput: InputIntProcess(Key, inputIntMsg, inputIntVal); break; default: break; } DEBUG_KEY("DVD-Ctrl: ProcessKey END\n"); return osContinue; } bool DoShowMode = true; state = osContinue; if ((player && player->IsInMenuDomain()) || forceDvdNavigation) { switch (Key) { case kRed: forceDvdNavigation = false; break; case kGreen|k_Repeat: case kGreen: player->PreviousTitle(); break; case kYellow|k_Repeat: case kYellow: player->NextTitle(); break; case kUp: case kDown: case kLeft: case kRight: case kOk: case k0 ... k9: DoShowMode = false; displayFrames = DisplayedFrames; if (DvdNavigation(Key)) break; default: state = osUnknown; break; } } else { switch (Key) { // Positioning: case kPlay: case kUp: Play(); break; case kPause: case kDown: Pause(); break; case kFastRew|k_Release: case kLeft|k_Release: if (Setup.MultiSpeedMode) break; case kFastRew: case kLeft: Backward(); break; case kFastFwd|k_Release: case kRight|k_Release: if (Setup.MultiSpeedMode) break; case kFastFwd: case kRight: Forward(); break; default: state = osUnknown; break; } } if (state == osUnknown) { state = osContinue; switch (Key) { // Positioning: case kRed: TimeSearch(); break; case kGreen | k_Repeat: case kGreen: SkipSeconds(-60); break; case kYellow | k_Repeat: case kYellow: SkipSeconds(60); break; case kBlue: TrackSearch(); break; default: { DoShowMode = false; displayFrames = DisplayedFrames; switch (Key) { // Menu control: case kOk: if (visible && !modeOnly) { Hide(); DoShowMode = true; } else Show(); break; case kStop: case kBack: Hide(); Stop(); state = osEnd; break; case k2: if (player) { if (player->NextSubpStream() == -1) Skins.QueueMessage(mtError, tr("Error.DVD$Current subp stream not seen!")); if (player->GetCurrentNavSubpStream() == -1) { Hide(); Show(); } } break; case k3: if (player) player->NextAngle(); break; case kPrev: case k4: if (player) player->PreviousPart(); break; case kNext: case k6: if (player) player->NextPart(); break; case kChanDn: case k7: if (player) player->PreviousTitle(); break; case kChanUp: case k9: if (player) player->NextTitle(); break; case k5: if (visible && !modeOnly) { Hide(); player->callRootMenu(); } else { Hide(); forceDvdNavigation = true; } break; case k8: if (player) { Hide(); player->callTitleMenu(); } break; case k0: if (player) { Hide(); player->callAudioMenu(); } break; default: state = osUnknown; } } } } if (DoShowMode && state != osEnd) { DEBUG_SHOW("cDvdPlayerControl::ProcessKey ShowMode\n"); ShowMode(); } DEBUG_KEY("DVD-Ctrl: ProcessKey END\n"); return state; } vdr-plugin-dvd-0.3.7/control-dvd.h000066400000000000000000000071441415711736600170100ustar00rootroot00000000000000/* * DVD Player plugin for VDR * * Copyright (C) 2001.2002 Andreas Schultz * * This code is distributed under the terms and conditions of the * GNU GENERAL PUBLIC LICENSE. See the file COPYING for details. * */ #ifndef __CONTROL_DVD_H #define __CONTROL_DVD_H #include #include #include enum InputProcessType { NoneInput, TimeSearchInput, TrackSearchInput }; class cDvdPlayerControl : public cControl { friend class cDvdPlayer; private: static bool dvd_active; bool displayFrames; bool forceDvdNavigation; bool inputHide; bool lastForward; bool lastPlay; bool modeOnly; bool shown; bool visible; void *osdTaker; int inputIntVal; int lastCurrent; int lastTotal; int lastSpeed; int timeSearchPos; int timeSearchTime; InputProcessType inputActive; time_t timeoutShow; const char *inputIntMsg; void InputIntDisplay(const char *msg, int val); void InputIntProcess(eKeys Key, const char *msg, int &val); bool IsDvdNavigationForced(void) { return forceDvdNavigation; } void OsdOpen(void); void OsdClose(); void ShowTimed(int Seconds = 0); void ShowMode(void); bool ShowProgress(bool Initial); void TimeSearchDisplay(void); void TimeSearchProcess(eKeys Key); void TimeSearch(void); void TrackSearch(void); void UpdateShow(bool force = false); public: cDvdPlayerControl(void); virtual ~cDvdPlayerControl(); virtual void Hide(void); virtual eOSState ProcessKey(eKeys Key); virtual void Show(void); static bool DVDActive() { return dvd_active; }; bool DvdNavigation(eKeys Key); const char *GetDisplayHeaderLine(); bool OsdVisible(void *me); bool OsdTaken(void *me); bool TakeOsd(void *obj); protected: void HideOwnOsd(void); private: cDvdPlayer *player; cSkinDisplayReplay *displayReplay; public: bool Active(void); bool Start(const char *FileName); // Starts replaying the given file. void Stop(void); // Stops the current replay session (if any). void Pause(void); // Pauses the current replay session, or resumes a paused session. void Play(void); // Resumes normal replay mode. void Forward(void); // Runs the current replay session forward at a higher speed. void Backward(void); // Runs the current replay session backwards at a higher speed. int SkipFrames(int Frames); // Returns the new index into the current replay session after skipping // the given number of frames (no actual repositioning is done!). // The sign of 'Frames' determines the direction in which to skip. void SkipSeconds(int Seconds); // Skips the given number of seconds in the current replay session. // The sign of 'Seconds' determines the direction in which to skip. // Use a very large negative value to go all the way back to the // beginning of the recording. bool GetIndex(int &Current, int &Total, bool SnapToIFrame = false); // Returns the current and total frame index, optionally snapped to the // nearest I-frame. bool GetReplayMode(bool &Play, bool &Forward, int &Speed); // Returns the current replay mode (if applicable). // 'Play' tells whether we are playing or pausing, 'Forward' tells whether // we are going forward or backward and 'Speed' is -1 if this is normal // play/pause mode, 0 if it is single speed fast/slow forward/back mode // and >0 if this is multi speed mode. void Goto(int Index, bool Still = false); // Positions to the given index and displays that frame as a still picture // if Still is true. }; #endif // __CONTROL_DVD_H vdr-plugin-dvd-0.3.7/dvd.c000066400000000000000000000071321415711736600153220ustar00rootroot00000000000000/* * DVD Player plugin for VDR * * Copyright (C) 2001.2002 Andreas Schultz * * This code is distributed under the terms and conditions of the * GNU GENERAL PUBLIC LICENSE. See the file COPYING for details. * */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "dvd.h" static const char *VERSION = "0.3.7"; #if VDRVERSNUM >= 10507 static const char *DESCRIPTION = trNOOP("Plugin.DVD$turn VDR into an (almost) full featured DVD player"); static const char *MAINMENUENTRY = trNOOP("Plugin.DVD$DVD"); #else static const char *DESCRIPTION = "Plugin.DVD$turn VDR into an (almost) full featured DVD player"; static const char *MAINMENUENTRY = "Plugin.DVD$DVD"; #endif // --- cPluginDvd ------------------------------------------------------------ cPluginDvd::cPluginDvd(void) { // Initialize any member varaiables here. // DON'T DO ANYTHING ELSE THAT MAY HAVE SIDE EFFECTS, REQUIRE GLOBAL // VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT! } cPluginDvd::~cPluginDvd() { // Clean up after yourself! } const char *cPluginDvd::Description(void) { return tr(DESCRIPTION); } const char *cPluginDvd::MainMenuEntry(void) { return DVDSetup.HideMainMenu ? NULL : tr(MAINMENUENTRY); } const char *cPluginDvd::Version(void) { return VERSION; } const char *cPluginDvd::CommandLineHelp(void) { // Return a string that describes all known command line options. return " -C DEV, --dvd=DEV use DEV as the DVD device (default: /dev/dvd)\n"; } bool cPluginDvd::ProcessArgs(int argc, char *argv[]) { // Implement command line argument processing here if applicable. #ifndef __QNXNTO__ static struct option long_options[] = { { "dvd", required_argument, NULL, 'C' }, { NULL } }; #endif int c; #ifndef __QNXNTO__ while ((c = getopt_long(argc, argv, "C:", long_options, NULL)) != -1) { #else optind = 1; while ((c = getopt(argc, argv, "C:")) != -1) { #endif switch (c) { case 'C': // fprintf(stderr, "arg: %s\n", optarg); cDVD::SetDeviceName(optarg); if (!cDVD::DriveExists()) { esyslog("vdr: DVD drive not found: %s", optarg); return false; } break; default: fprintf(stderr, "arg char: %c\n", c); return false; } } return true; } bool cPluginDvd::Initialize(void) { // Initialize any background activities the plugin shall perform. #if VDRVERSNUM < 10507 RegisterI18n(DvdPhrases); #endif return true; } bool cPluginDvd::Start(void) { // Start any background activities the plugin shall perform. return true; } void cPluginDvd::Housekeeping(void) { // Perform any cleanup or other regular tasks. } cOsdMenu *cPluginDvd::MainMenuAction(void) { if (!cDvdPlayerControl::DVDActive()) cControl::Launch(new cDvdPlayerControl); return NULL; } cMenuSetupPage *cPluginDvd::SetupMenu(void) { // Return a setup menu in case the plugin supports one. return new cMenuSetupDVD; } bool cPluginDvd::SetupParse(const char *Name, const char *Value) { return DVDSetup.SetupParse(Name, Value); } cSetupLine *cPluginDvd::GetSetupLine(const char *Name, const char *Plugin) { for (cSetupLine *l = Setup.First(); l; l = Setup.Next(l)) { if ((l->Plugin() == NULL) == (Plugin == NULL)) { if ((!Plugin || strcasecmp(l->Plugin(), Plugin) == 0) && strcasecmp(l->Name(), Name) == 0) return l; } } return NULL; } VDRPLUGINCREATOR(cPluginDvd); // Don't touch this! vdr-plugin-dvd-0.3.7/dvd.h000066400000000000000000000024671415711736600153350ustar00rootroot00000000000000/* * DVD Player plugin for VDR * * Copyright (C) 2001.2002 Andreas Schultz * * This code is distributed under the terms and conditions of the * GNU GENERAL PUBLIC LICENSE. See the file COPYING for details. * */ #include #include #ifndef __QNXNTO__ #include #else #include #endif #include "dvddev.h" #include "tools-dvd.h" #include "player-dvd.h" #include "control-dvd.h" #include "setup-dvd.h" #include "i18n.h" // --- cPluginDvd ------------------------------------------------------------ class cPluginDvd : public cPlugin { friend class cDvdPlayer; friend class cDvdPlayerControl; static cSetupLine *GetSetupLine(const char *Name, const char *Plugin); private: // Add any member variables or functions you may need here. public: cPluginDvd(void); virtual ~cPluginDvd(); virtual const char *Version(void); virtual const char *Description(void); virtual const char *CommandLineHelp(void); virtual bool ProcessArgs(int argc, char *argv[]); virtual bool Initialize(void); virtual bool Start(void); virtual void Housekeeping(void); virtual const char *MainMenuEntry(void); virtual cOsdMenu *MainMenuAction(void); virtual cMenuSetupPage *SetupMenu(void); virtual bool SetupParse(const char *Name, const char *Value); }; vdr-plugin-dvd-0.3.7/dvddev.c000066400000000000000000000047231415711736600160240ustar00rootroot00000000000000/* * DVD Player plugin for VDR * * Copyright (C) 2001.2002 Andreas Schultz * * This code is distributed under the terms and conditions of the * GNU GENERAL PUBLIC LICENSE. See the file COPYING for details. * */ //#define DVDDEBUG #include #include #include #include #include #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "dvddev.h" #ifndef __QNXNTO__ #include #endif #ifdef DEBUG #define DVDDEBUG #undef DEBUG #else #ifndef NDEBUG #define NDEBUG #endif #endif #ifdef DVDDEBUG #define DEBUG(format, args...) fprintf (stderr, format, ## args) #else #define DEBUG(format, args...) #endif // --- cDVD ------------------------------------------------------------------ const char *cDVD::deviceName = "/dev/dvd"; cDVD *cDVD::dvdInstance = NULL; cDVD *cDVD::getDVD(void) { if (!dvdInstance) new cDVD; return dvdInstance; } cDVD::cDVD(void) { dvdInstance = this; } int cDVD::Command(int Cmd) { int result = -1; int f; if ((f = open(deviceName, O_RDONLY | O_NONBLOCK)) > 0) { result = ioctl(f, Cmd, 0); close(f); } return result; } void cDVD::SetDeviceName(const char *DeviceName) { deviceName = strdup(DeviceName); } const char *cDVD::DeviceName(void) { return deviceName; } bool cDVD::DriveExists(void) { return access(deviceName, F_OK) == 0; } bool cDVD::DiscOk(void) { #ifndef __QNXNTO__ return Command(CDROM_DRIVE_STATUS) == CDS_DISC_OK; #else return 1; // fake ok for QNX #endif } void cDVD::Eject(void) { // vm_destroy(); #ifndef __QNXNTO__ Command(CDROMEJECT); #endif } #if 0 #define _lang2int( x ) ((x[0] << 8) | x[1]); int cDVD::vm_reset(void) { int ret = ::vm_init(const_cast(deviceName)); if (ret ==0) { ::vm_reset(); state.registers.SPRM[14] &= ~(0x0f << 8); state.registers.SPRM[14] |= (Setup.VideoFormat ? 0x03 : 0) << 10; state.registers.SPRM[14] |= 0x02 << 8; // letterbox is default for dvb/vdr state.registers.SPRM[0] = _lang2int( LangCodes()[Setup.DVDMenuLanguage] ); // Player Menu Languange code state.registers.SPRM[16] = _lang2int( LangCodes()[Setup.DVDAudioLanguage] ); // Initial Language Code for Audio state.registers.SPRM[18] = _lang2int( LangCodes()[Setup.DVDSpuLanguage] ); // Initial Language Code for Spu state.registers.SPRM[20] = _lang2int( LangCodes()[Setup.DVDPlayerRCE] ); // Player Regional Code (bit mask?) } return ret; } #endif vdr-plugin-dvd-0.3.7/dvddev.h000066400000000000000000000012451415711736600160250ustar00rootroot00000000000000/* * DVD Player plugin for VDR * * Copyright (C) 2001.2002 Andreas Schultz * * This code is distributed under the terms and conditions of the * GNU GENERAL PUBLIC LICENSE. See the file COPYING for details. * */ #ifndef __VDR_DVDDEV_H #define __VDR_DVDDEV_H class cDVD { private: static cDVD *dvdInstance; static const char *deviceName; static int Command(int Cmd); public: cDVD(void); ~cDVD(); static void SetDeviceName(const char *DeviceName); static const char *DeviceName(void); static bool DriveExists(void); static bool DiscOk(void); static void Eject(void); static cDVD *getDVD(void); }; #endif //__VDR_DVDDEV_H vdr-plugin-dvd-0.3.7/dvdspu.c000066400000000000000000000120111415711736600160420ustar00rootroot00000000000000/* * DVD Player plugin for VDR * * Copyright (C) 2001.2002 Andreas Schultz * * This code is distributed under the terms and conditions of the * GNU GENERAL PUBLIC LICENSE. See the file COPYING for details. * * parts of this file are derived from the OMS program. * */ /***** * * This file is part of the VDR program. * This file was part of the OMS program. * * 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; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * *****/ #if 0 #define CTRLDEBUG #undef DEBUG_CONTROL #define DEBUG_CONTROL(format, args...) printf (format, ## args); fflush(NULL) #else #ifdef CTRLDEBUG #undef CTRLDEBUG #endif #ifndef DEBUG_CONTROL #define DEBUG_CONTROL(format, args...) #endif #endif /* * subpic_decode.c - converts DVD subtitles to an XPM image * * Mostly based on hard work by: * * Copyright (C) 2000 Samuel Hocevar * and Michel Lespinasse * * Lots of rearranging by: * Aaron Holtzman * Thomas Mirlacher * implemented reassembling * cleaner implementation of SPU are saving * overlaying (proof of concept for now) * ... and yes, it works now with oms * added tranparency (provided by the SPU hdr) * changed structures for easy porting to MGAs DVD mode * * addapted for VDR by Andreas Schultz * * 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 * */ /* * added some functions to extract some informations of the SPU command * sequence (cSPUassembler::checkSPUHeader and related). * needed for 'forced subtitles only' mode * * weak@pimps.at * * Code of checkSPUHeader and related functions are based on SPUClass.cpp from the NMM - Network-Integrated Multimedia Environment (www.networkmultimedia.org) * */ /** * fixed and willing to merge with xine's solution .. * * sven goethel sgoethel@jausoft.com */ #include #include #include #include #include #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "dvdspu.h" //----------- cSPUdata ----------------------------------- simpleFIFO::simpleFIFO(int Size) { size = Size; head = tail = 0; buffer = (uint8_t *)malloc(2*size); } simpleFIFO::~simpleFIFO() { free(buffer); } int simpleFIFO::Put(const uint8_t *Data, int Count) { if (Count > 0) { int rest = size - head; int free = Free(); if (free <= 0) return 0; if (free < Count) Count = free; if (Count >= rest) { memcpy(buffer + head, Data, rest); if (Count - rest) memcpy(buffer, Data + rest, Count - rest); head = Count - rest; } else { memcpy(buffer + head, Data, Count); head += Count; } } return Count; } int simpleFIFO::Get(uint8_t *Data, int Count) { if (Count > 0) { int rest = size - tail; int cont = Available(); if (rest <= 0) return 0; if (cont < Count) Count = cont; if (Count >= rest) { memcpy(Data, buffer + tail, rest); if (Count - rest) memcpy(Data + rest, buffer, Count - rest); tail = Count - rest; } else { memcpy(Data, buffer + tail, Count); tail += Count; } } return Count; } int simpleFIFO::Release(int Count) { if (Count > 0) { int rest = size - tail; int cont = Available(); if (rest <= 0) return 0; if (cont < Count) Count = cont; if (Count >= rest) tail = Count - rest; else tail += Count; } return Count; } // ---------- cSPUassembler ----------------------------------- cSPUassembler::cSPUassembler(): simpleFIFO(SPU_BUFFER_SIZE) { }; int cSPUassembler::Put(const uint8_t *Data, int Count, uint64_t Pts) { if (Pts > 0) pts = Pts; return simpleFIFO::Put(Data, Count); } vdr-plugin-dvd-0.3.7/dvdspu.h000066400000000000000000000024541415711736600160610ustar00rootroot00000000000000/* * DVD Player plugin for VDR * * Copyright (C) 2001.2002 Andreas Schultz * * This code is distributed under the terms and conditions of the * GNU GENERAL PUBLIC LICENSE. See the file COPYING for details. * * parts of this file are derived from the OMS program. * */ #ifndef __DVDSPU_H__ #define __DVDSPU_H__ #include #define SPU_BUFFER_SIZE (128*1024) class simpleFIFO { private: uint8_t *buffer; int head; int tail; int size; public: simpleFIFO(int Size); ~simpleFIFO(); int Put(const uint8_t *Data, int Count); int Get(uint8_t *Data, int Count); int Release(int Count); int Size(void) const { return size; }; int Free(void) const { return ((size + tail) - head - 1) % size; }; int Available(void) const { return ((head + size) - tail) % size; }; uint8_t const &operator[] (int i) const { return buffer[(tail + i) % size]; }; }; class cSPUassembler: public simpleFIFO { private: uint64_t pts; public: cSPUassembler(); bool ready(void) { return ((Available() > 2) && (Available() >= getSize())); }; int getSize(void) { return ((operator[](0)) << 8) | operator[](1); }; uint64_t getPts(void) { return pts; }; int Put(const uint8_t *Data, int Count, uint64_t Pts); }; #endif vdr-plugin-dvd-0.3.7/i18n.c000066400000000000000000000574331415711736600153350ustar00rootroot00000000000000/* * DVD Player plugin for VDR * * Copyright (C) 2001.2002 Andreas Schultz * * This code is distributed under the terms and conditions of the * GNU GENERAL PUBLIC LICENSE. See the file COPYING for details. * */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "i18n.h" const char *ISO639code[] = { // Language ISO 639 codes for DVD "en", "de", "sl", "it", "nl", "pt", "fr", "no", "fi", "pl", "es", "el", "se", "ro", "hu", "ca", "ru", "hr", "et", "da", "cs", #if VDRVERSNUM >= 10502 "tr", #endif }; const char *DvdLanguageCode[][2] = { // Language ISO 639 codes for DVD {"en", "English"}, {"de", "Deutsch"}, {"sl", "Slovenski"}, {"it", "Italiano"}, {"nl", "Nederlands"}, {"pt", "Portugus"}, {"fr", "Franais"}, {"no", "Norsk"}, {"fi", "suomi"}, {"pl", "Polski"}, {"es", "Espaol"}, {"el", ""}, {"se", "Svenska"}, {"ro", "Romaneste"}, {"hu", "Magyar"}, {"ca", "Catal"}, {"ru", "Русский"}, {"hr", "Hrvatski"}, {"et", "Eesti"}, {"da", "Dansk"}, {"cs", "Czech"}, {"tr", "Trke"} }; #if VDRVERSNUM < 10507 const tI18nPhrase DvdPhrases[] = { { "Plugin.DVD$DVD", // English "DVD", // Deutsch "DVD", // Slovenski "DVD", // Italiano "DVD", // Nederlands "DVD", // Portugus "DVD", // Franais "DVD", // Norsk "DVD", // suomi "DVD", // Polski "DVD", // Espaol "DVD", // (Greek) "DVD", // Svenska "DVD", // Romaneste "DVD", // Magyar "DVD", // Catal " DVD", // (Russian) "DVD", // Hrvatski (Croatian) "DVD", // Eesti "DVD", // Dansk "DVD", // Czech #if VDRVERSNUM >= 10502 "DVD", // Trke #endif }, { "Plugin.DVD$turn VDR into an (almost) full featured DVD player", // English "verwandelt VDR in einen (fast) vollstndigen DVD Spieler", // Deutsch "spremeni VDR v (skoraj) popolen DVD predvajalnik", // Slovenski "", // Italiano "Verander VDR in een (bijna) complete DVD-speler", // Nederlands "", // Portugus "", // Franais "", // Norsk "DVD-soitin", // suomi "Zmienia VDR w odtwarzacz DVD", // Polski "Convierte VDR en un reproductor DVD (casi) completo", // Espaol "Metatropi tou VDR se ena (sxedon) olokliromeno DVD", // (Greek) "", // Svenska "", // Romaneste "", // Magyar "", // Catal " DVD", // (Russian) "", // Hrvatski (Croatian) "DVD-mngija", // Eesti "forvandler VDR til en (nsten) normal DVD afspiller", // Dansk "Pemn VDR v plnohodnotn DVD pehrva", // Czech #if VDRVERSNUM >= 10502 "VDR'i (nerdeyse) tam DVD oynatcsna evirir" // Trke #endif }, { "Setup.DVD$Preferred menu language", // English "Bevorzugte Sprache fr Mens", // Deutsch "Prednostni jezik za menije", // Slovenski "menu - linguaggio preferito", // Italiano "Taalkeuze voor menu", // Nederlands "", // Portugus "Langage prfr pour les menus", // Franais "", // Norsk "Haluttu valikkokieli", // suomi "Preferowany jzyk menu", // Polski "Idioma preferido para los mens", // Espaol "Protinomeni glossa gia menou", // (Greek) "", // Svenska "", // Romaneste "", // Magyar "", // Catal " ", // (Russian) "", // Hrvatski (Croatian) "Eelistatud menkeel", // Eesti "Foretrukket sprog for menuer", // Dansk "Preferovan jazyk menu", // Czech #if VDRVERSNUM >= 10502 "Menlerin dil tercihi" // Trke #endif }, { "Setup.DVD$Preferred audio language", // English "Bevorzugte Sprache fr Dialog", // Deutsch "Prednostni jezik za zvok", // Slovenski "audio - linguaggio preferito", // Italiano "Taalkeuze voor geluid", // Nederlands "", // Portugus "Langage prfr pour le son", // Franais "", // Norsk "Haluttu niraita", // suomi "Preferowany jzyk dwiku", // Polski "Idioma preferido para el sonido", // Espaol "Protinomeni glossa gia ton dialogo", // (Greek) "", // Svenska "", // Romaneste "", // Magyar "", // Catal " ", // (Russian) "", // Hrvatski (Croatian) "Eelistatud audiokeel", // Eesti "Foretrukket sprog for lyd", // Dansk "Preferovan jazyk zvuku", // Czech #if VDRVERSNUM >= 10502 "Diyaloglarn dil tercihi" // Trke #endif }, { "Setup.DVD$Preferred subtitle language", // English "Bevorzugte Sprache fr Untertitel", // Deutsch "Prednostni jezik za podnapise", // Slovenski "sottotitoli - linguaggio preferito", // Italiano "Taalkeuze voor ondertitels", // Nederlands "", // Portugus "Langage prfr pour les sous-titres", // Franais "", // Norsk "Haluttu tekstityskieli", // suomi "Preferowany jzyk napisw", // Polski "Idioma preferido para los subttulos", // Espaol "Protinomeni glossa ipotitlon", // (Greek) "", // Svenska "", // Romaneste "", // Magyar "", // Catal " ", // (Russian) "", // Hrvatski (Croatian) "Eelistatud subtiitritekeel", // Eesti "Foretrukket sprog for undertekster", // Dansk "Preferovan jazyk titulk", // Czech #if VDRVERSNUM >= 10502 "Altyazlarn dil tercihi" // Trke #endif }, { "Setup.DVD$Player region code", // English "Regionalkode fr DVD Spieler", // Deutsch "Regionalna koda za predvajalnik", // Slovenski "region code del DVD player", // Italiano "Regiocode van Speler", // Nederlands "", // Portugus "Code rgion du lecteur", // Franais "", // Norsk "Soittimen aluekoodi", // suomi "Kod regionu odtwarzacza", // Polski "Cdigo de zona del lector", // Espaol "Kodikos Zonis DVD", // (Greek) "", // Svenska "", // Romaneste "", // Magyar "", // Catal " ", // (Russian) "", // Hrvatski (Croatian) "Mngija regioonikood", // Eesti "Afspillerens regions kode", // Dansk "Regionln kd pehrvae", // Czech #if VDRVERSNUM >= 10502 "DVD oynatcnn blge kodu" // Trke #endif }, { "Setup.DVD$Display subtitles", // English "Untertitel anzeigen", // Deutsch "Prikai podnapise", // Slovenski "Visualizza sottotitoli", // Italiano "Toon ondertitels", // Nederlands "", // Portugus "Affiche les sous-titres", // Franais "", // Norsk "Nyt tekstitys", // suomi "Wywietlaj napisy", // Polski "Mostrar subttulos", // Espaol "Endiksi ipotitlon", // (Greek) "", // Svenska "", // Romaneste "", // Magyar "", // Catal " ", // (Russian) "", // Hrvatski (Croatian) "Subtiitrite kuvamine", // Eesti "Vis undertekster", // Dansk "Zobrazovat titulky", // Czech #if VDRVERSNUM >= 10502 "Altyazlar gster" // Trke #endif }, { "Setup.DVD$Hide Mainmenu Entry", "Hauptmeneintrag verstecken", // Deutsch "Skrij galvni meni", // Slovenski "Nascondi voce men", // Italiano "Verberg vermelding in het hoofdmenu", // Nederlands "", // Portugus "", // Franais "", // Norsk "Piilota valinta pvalikosta", // suomi "Ukryj pozycj w gwnym menu", // Polski "Ocultar entrada en el men principal", // Espaol "Apokripsi sto vasiko menou", // (Greek) "", // Svenska "", // Romaneste "", // Magyar "", // Catal " ", // (Russian) "", // Hrvatski (Croatian) "Peita peamen valikust", // Eesti "Skjul DVD i hovedmenuen", // Dansk "Skrt poloku v hlavnm menu", // Czech #if VDRVERSNUM >= 10502 "Ana mende sakla" // Trke #endif }, { "Setup.DVD$ReadAHead", "ReadAHead", // Deutsch "Beri vnaprej", // Slovenski "ReadAHead", // Italiano "Vooruit lezen", // Nederlands "ReadAHead", // Portugus "ReadAHead", // Franais "ReadAHead", // Norsk "ReadAHead-toiminto", // suomi "ReadAHead", // Polski "Lectura anticipada", // Espaol "ReadAHead", // (Greek) "ReadAHead", // Svenska "ReadAHead", // Romaneste "ReadAHead", // Magyar "ReadAHead", // Catal " ", // (Russian) "ReadAHead", // Hrvatski (Croatian) "ReadAHead", // Eesti "Ls forud", // Dansk "Dopedn ten", // Czech #if VDRVERSNUM >= 10502 "leri oku" // Trke #endif }, { "Setup.DVD$Gain (analog)", "Verstrkung (analog)", // Deutsch "Ojaanje (analogno)", // Slovenski "Gain (analog)", // Italiano "Versterking (analoog)", // Nederlands "Gain (analog)", // Portugus "Gain (analog)", // Franais "Gain (analog)", // Norsk "nen vahvistus (analoginen)", // suomi "Zysk (analogowo)", // Polski "Ganancia (analgico)", // Espaol "Gain (analogika)", // (Greek) "Gain (analog)", // Svenska "Gain (analog)", // Romaneste "Gain (analog)", // Magyar "Gain (analog)", // Catal " (.)", // (Russian) "Gain (analog)", // Hrvatski (Croatian) "Helivimendamine (analoog)", // Eesti "Forstrkning (analog)", // Dansk "Zeslen (analog)", // Czech #if VDRVERSNUM >= 10502 "Kuvvetlendirmek (analog)" // Trke #endif }, { "Error.DVD$Error opening DVD!", // English "Fehler beim ffnen der DVD!", // Deutsch "Napaka pri odpiranju DVD-ja!", // Slovenski "", // Italiano "Fout bij het openen van de DVD!", // Nederlands "", // Portugus "", // Franais "", // Norsk "DVD:n avaaminen eponnistui!", // suomi "Bd otwierania DVD!", // Polski "Error abriendo el DVD!", // Espaol "Lathos sto anigma tou DVD", // (Greek) "", // Svenska "", // Romaneste "", // Magyar "", // Catal " DVD!", // (Russian) "", // Hrvatski (Croatian) "DVD avamine ebannestus!", // Eesti "Fejl ved bning af DVD!", // Dansk "Chyba pi otevrn DVD!", // Czech #if VDRVERSNUM >= 10502 "DVD al hatas!" // Trke #endif }, { "Error.DVD$Error fetching data from DVD!", // English "Fehler beim Lesen von der DVD!", // Deutsch "Napaka pri branju podatkov iz DVD-ja!", // Slovenski "", // Italiano "Error bij het verkrijgen van data van de DVD!", // Nederlands "", // Portugus "", // Franais "", // Norsk "DVD:n lukeminen eponnistui", // suomi "Bd pobierania danych z DVD!", // Polski "Error obteniendo datos del DVD!", // Espaol "Lathos sto diavasma tou DVD", // (Greek) "", // Svenska "", // Romaneste "", // Magyar "", // Catal " DVD!", // (Russian) "", // Hrvatski (Croatian) "Lugemine DVD-lt ebannestus!", // Eesti "Fejl ved hentning af data fra DVD!", // Dansk "Chyba pi natn dat z DVD!", // Czech #if VDRVERSNUM >= 10502 "DVD okuma hatas!" // Trke #endif }, { "Error.DVD$Current subtitle stream not seen!", // English "Der ausgewhlte Untertitel ist nicht vorhanden!", // Deutsch "Izbrani podnapisi niso prisotni!", // Slovenski "", // Italiano "De gekozen ondertiteling is niet beschikbaar!", // Nederlands "", // Portugus "", // Franais "", // Norsk "Tekstitysraitaa ei havaita!", // suomi "Wybrane napisy nie istniej!", // Polski "Subttulos actuales no encontrados!", // Espaol "O epilegmenos ipotitlos den iparxi", // (Greek) "", // Svenska "", // Romaneste "", // Magyar "", // Catal " !", // (Russian) "", // Hrvatski (Croatian) "Subtiitriterada pole avastatud!", // Eesti "Valgte undertekst findes ikke!", // Dansk "Vybran titulky nejsou k dispozici!", // Czech #if VDRVERSNUM >= 10502 "Seilen altyaz bulunamad!" // Trke #endif }, { "Error.DVD$Current audio track not seen!", // English "Die ausgewhlte Audiospur ist nicht vorhanden!", // Deutsch "Izbrani zvoni zapis ni prisoten!", // Slovenski "", // Italiano "Het gekozen audiospoort is niet beschikbaar", // Nederlands "", // Portugus "", // Franais "", // Norsk "niraitaa ei havaita!", // suomi "Wybrana cieka dwikowa nie istnieje!", // Polski "Pista de audio actual no encontrada!", // Espaol "I Epilegmeni desmi ixou den mpori na wrethi", // (Greek) "", // Svenska "", // Romaneste "", // Magyar "", // Catal " !", // (Russian) "", // Hrvatski (Croatian) "Audiorada pole avastatud!", // Eesti "Valgte lyd-spor findes ikke!", // Dansk "Vybran zvukov stopa nen k dispozici!", // Czech #if VDRVERSNUM >= 10502 "Seilen audio ses bulunamad!" // Trke #endif }, { NULL } }; #endif vdr-plugin-dvd-0.3.7/i18n.h000066400000000000000000000007341415711736600153320ustar00rootroot00000000000000/* * DVD Player plugin for VDR * * Copyright (C) 2001.2002 Andreas Schultz * * This code is distributed under the terms and conditions of the * GNU GENERAL PUBLIC LICENSE. See the file COPYING for details. * */ #ifndef __DVD_I18N_H #define __DVD_I18N_H #include extern const char *ISO639code[]; extern const char *DvdLanguageCode[][2]; #if VDRVERSNUM < 10507 extern const tI18nPhrase DvdPhrases[]; #endif #endif // __DVD_I18N_H vdr-plugin-dvd-0.3.7/mpegtypes.h000066400000000000000000000046021415711736600165660ustar00rootroot00000000000000 #ifndef _MPEGTYPES_H #define _MPEGTYPES_H #define NO_PICTURE 0 #define SC_PICTURE 0x00 #define SYSTEM_HEADER 0xBB #define PROG_STREAM_MAP 0xBC #define PRIVATE_STREAM1 0xBD #define PADDING_STREAM 0xBE #define PRIVATE_STREAM2 0xBF #define AUDIO_STREAM_S 0xC0 #define AUDIO_STREAM_E 0xDF #define VIDEO_STREAM_S 0xE0 #define VIDEO_STREAM_E 0xEF #define ECM_STREAM 0xF0 #define EMM_STREAM 0xF1 #define DSM_CC_STREAM 0xF2 #define ISO13522_STREAM 0xF3 #define PROG_STREAM_DIR 0xFF #define PICTURE_START 0x00 #define USER_START 0xb2 #define SEQUENCE_HEADER 0xb3 #define SEQUENCE_ERROR 0xb4 #define EXTENSION_START 0xb5 #define SEQUENCE_END 0xb7 #define GOP_START 0xb8 #define EXCEPT_SLICE 0xb0 #define SEQUENCE_EXTENSION 0x01 #define SEQUENCE_DISPLAY_EXTENSION 0x02 #define PICTURE_CODING_EXTENSION 0x08 #define QUANT_MATRIX_EXTENSION 0x03 #define PICTURE_DISPLAY_EXTENSION 0x07 #if VDRVERSNUM < 10701 || VDRVERSNUM >= 10703 #define I_FRAME 0x01 #define P_FRAME 0x02 #define B_FRAME 0x03 #endif #define aAC3 0x80 #define aDTS 0x88 #define aLPCM 0xA0 #define aLPCM_Min 0xA0 #define aLPCM_Max 0xA7 #define aMPEG 0xC0 /* Initialize sequence_data */ #define INIT_HORIZONTAL_SIZE 720 #define INIT_VERTICAL_SIZE 576 #define INIT_ASPECT_RATIO 0x02 #define INIT_FRAME_RATE 0x03 #define INIT_DISP_HORIZONTAL_SIZE 540 #define INIT_DISP_VERTICAL_SIZE 576 //flags2 #define PTS_DTS_FLAGS 0xC0 #define ESCR_FLAG 0x20 #define ES_RATE_FLAG 0x10 #define DSM_TRICK_FLAG 0x08 #define ADD_CPY_FLAG 0x04 #define PES_CRC_FLAG 0x02 #define PES_EXT_FLAG 0x01 //pts_dts flags #define PTS_ONLY 0x80 #define PTS_DTS 0xC0 #define TS_SIZE 188 #define TRANS_ERROR 0x80 #define PAY_START 0x40 #define TRANS_PRIO 0x20 #define PID_MASK_HI 0x1F //flags #define TRANS_SCRMBL1 0x80 #define TRANS_SCRMBL2 0x40 #define ADAPT_FIELD 0x20 #define PAYLOAD 0x10 #define COUNT_MASK 0x0F // adaptation flags #define DISCON_IND 0x80 #define RAND_ACC_IND 0x40 #define ES_PRI_IND 0x20 #define PCR_FLAG 0x10 #define OPCR_FLAG 0x08 #define SPLICE_FLAG 0x04 #define TRANS_PRIV 0x02 #define ADAP_EXT_FLAG 0x01 // adaptation extension flags #define LTW_FLAG 0x80 #define PIECE_RATE 0x40 #define SEAM_SPLICE 0x20 #endif vdr-plugin-dvd-0.3.7/patches/000077500000000000000000000000001415711736600160255ustar00rootroot00000000000000vdr-plugin-dvd-0.3.7/patches/mp3-0.9.0_vdr138_01.diff000066400000000000000000000510251415711736600214320ustar00rootroot00000000000000diff -Nur mp3-0.9.0/common.h mp3-0.9.0jau01/common.h --- mp3-0.9.0/common.h 2002-08-04 12:26:54.000000000 +0200 +++ mp3-0.9.0jau01/common.h 2004-05-28 05:14:56.021809616 +0200 @@ -30,4 +30,8 @@ #define d(x) ; #endif +#define MSG_ERROR(x) Skins.Message(mtError,x) +#define MSG_INFO(x) Skins.Message(mtInfo,x) +#define MSG_STATUS(x) Skins.Message(mtStatus,x) + #endif //___COMMON_H diff -Nur mp3-0.9.0/config.h mp3-0.9.0jau01/config.h --- mp3-0.9.0/config.h 2002-08-11 22:12:50.000000000 +0200 +++ mp3-0.9.0jau01/config.h 2004-05-28 05:29:46.478439632 +0200 @@ -110,7 +110,9 @@ // Uncomment to enable generic debugging messages to the console. This may slow // down operation in some cases. -#define DEBUG +#ifndef DEBUG +// #define DEBUG +#endif // Uncomment to disable audio output to the dvb driver. The audio data is // simply discarded. diff -Nur mp3-0.9.0/decoder-snd.c mp3-0.9.0jau01/decoder-snd.c --- mp3-0.9.0/decoder-snd.c 2004-05-01 15:58:58.000000000 +0200 +++ mp3-0.9.0jau01/decoder-snd.c 2004-05-28 05:18:08.895488360 +0200 @@ -648,9 +648,7 @@ bool res=false; if(Interface) { - Interface->Open(0,-1); - Interface->Status(tr("Remote CDDB lookup...")); - Interface->Flush(); + MSG_STATUS(tr("Remote CDDB lookup...")); } delete net; net=new cNet(16*1024,CDDB_TOUT,CDDB_TOUT); @@ -709,10 +707,6 @@ delete net; net=0; - if(Interface) { - Interface->Close(); - } - return res; } diff -Nur mp3-0.9.0/menu-mplayer.c mp3-0.9.0jau01/menu-mplayer.c --- mp3-0.9.0/menu-mplayer.c 2004-05-01 16:05:51.000000000 +0200 +++ mp3-0.9.0jau01/menu-mplayer.c 2004-05-28 05:19:35.270357384 +0200 @@ -62,6 +62,7 @@ bool visible, modeOnly, haveBeauty; time_t timeoutShow; int lastCurrent, lastTotal, osdPos; + cSkinDisplayReplay *displayReplay; // bool jumpactive, jumphide, jumpmode; int jumpval; @@ -107,12 +108,17 @@ if(symD != osdD) haveBeauty=true; d(printf("mplayer: beauty patch %sdetected\n",haveBeauty?"":"NOT ")) #endif + displayReplay = NULL; } cMPlayerControl::~cMPlayerControl() { Stop(); cStatus::MsgReplaying(this, NULL); + if(displayReplay) { + delete displayReplay; + displayReplay = NULL; + } } void cMPlayerControl::SetFilename(const char *FileName) @@ -138,21 +144,17 @@ void cMPlayerControl::Hide(void) { if(visible) { - Interface->Close(); + if(displayReplay) { + delete displayReplay; + displayReplay = NULL; + } needsFastResponse=visible=modeOnly=false; } } void cMPlayerControl::DisplayAtBottom(const char *s) { - const int p=modeOnly ? 0 : 2; - if(s) { - const int d=max(Width()-cOsd::WidthInCells(s),0) / 2; - if(modeOnly) Interface->Fill(0, p, Interface->Width(), 1, clrTransparent); - Interface->Write(d, p, s); - } - else - Interface->Fill(12, p, Width() - 22, 1, clrBackground); + displayReplay->SetJump(s); } void cMPlayerControl::ShowProgress(void) @@ -162,32 +164,21 @@ if(GetIndex(Current,Total) && Total>0) { bool flush=false; if(!visible) { - Interface->Open(Setup.OSDwidth,osdPos-3); - Interface->Clear(); - if(osdPos<0) Interface->Fill(0,3,Interface->Width(),-osdPos,clrTransparent); + displayReplay = Skins.Current()->DisplayReplay(false); needsFastResponse=visible=true; if(fileName) { - int n=strlen(fileName); - if(n>Width()) { - n=n-Width()+4; if(n<0) n=0; - char str[72]; - snprintf(str,sizeof(str),"... %s",fileName+n); - Interface->Write(0,0,str); - } - else Interface->Write(0,0,fileName); + displayReplay->SetTitle(fileName); } lastCurrent=lastTotal=-1; flush=true; } if(Current!=lastCurrent) { - cProgressBar ProgressBar(Width() * cOsd::CellWidth(), cOsd::LineHeight(), Current, Total); - Interface->SetBitmap(0, cOsd::LineHeight(), ProgressBar); - Interface->Write(0,2,IndexToHMSF(Current)); - flush=true; + displayReplay->SetTotal(IndexToHMSF(Total)); + displayReplay->SetProgress(Current, Total); + displayReplay->SetCurrent(IndexToHMSF(Current)); lastCurrent=Current; lastTotal=Total; } - if(flush) Interface->Flush(); ShowMode(); } } @@ -207,14 +198,13 @@ if(!visible) { if(NormalPlay) return; - Interface->Open(0,osdPos-1); + displayReplay = Skins.Current()->DisplayReplay(true); visible=modeOnly=true; } if(modeOnly && !timeoutShow && NormalPlay) timeoutShow=time(0)+SELECTHIDE_TIMEOUT; char buf[16]; - eDvbFont OldFont; #ifdef HAVE_BEAUTYPATCH if(haveBeauty) { int i=0; @@ -226,23 +216,13 @@ i++; if(!(Width()&1)) buf[i++]=' '; buf[i]=0; - OldFont = Interface->SetFont(fontSym); } else { #endif - const char *Mode; - if (Speed == -1) Mode = Play ? " > " : " || "; - else if (Play) Mode = Forward ? " X>> " : " < " : " <|X "; - strn0cpy(buf, Mode, sizeof(buf)); - char *p = strchr(buf, 'X'); - if(p) *p = Speed > 0 ? '1' + Speed - 1 : ' '; - OldFont = Interface->SetFont(fontFix); + displayReplay->SetMode(Play, Forward, Speed); #ifdef HAVE_BEAUTYPATCH } #endif - DisplayAtBottom(buf); - Interface->SetFont(OldFont); } } } diff -Nur mp3-0.9.0/menu.c mp3-0.9.0jau01/menu.c --- mp3-0.9.0/menu.c 2004-05-01 18:44:30.000000000 +0200 +++ mp3-0.9.0jau01/menu.c 2004-05-28 05:17:35.725530960 +0200 @@ -107,8 +107,7 @@ bool cMenuBrowse::LoadDir(const char *dir) { Clear(); - Interface->Status(tr("Scanning directory...")); - Interface->Flush(); + MSG_STATUS(tr("Scanning directory...")); if(!list->Load(source,dir)) return false; cFileObj *item=list->First(); @@ -132,7 +131,7 @@ return true; } free(ncur); - Interface->Error(tr("Error scanning directory!")); + MSG_ERROR(tr("Error scanning directory!")); return false; } @@ -265,7 +264,7 @@ { cFileSource *src=selected ? selected:current; if(src->NeedsMount() && !src->Status()) { - Interface->Error(tr("Selected source is not mounted!")); + MSG_ERROR(tr("Selected source is not mounted!")); return false; } return true; @@ -277,7 +276,7 @@ cFileSource *src = ((cMenuSourceItem *)Get(Current()))->Source(); if(src->NeedsMount() && !src->Status()) { - if(!DoMount(src)) Interface->Info(tr("Mount failed!")); + if(!DoMount(src)) MSG_ERROR(tr("Mount failed!")); } if(!src->NeedsMount() || src->Status()) { selected=src; @@ -292,8 +291,8 @@ cFileSource *src = ((cMenuSourceItem *)Get(Current()))->Source(); if(src->NeedsMount() && !src->Status()) { - if(DoMount(src)) Interface->Info(tr("Mount succeeded")); - else Interface->Error(tr("Mount failed!")); + if(DoMount(src)) MSG_INFO(tr("Mount succeeded")); + else MSG_ERROR(tr("Mount failed!")); } return osContinue; } @@ -307,8 +306,8 @@ bool res=src->Unmount(); RefreshCurrent(); DisplayCurrent(true); - if(res) Interface->Info(tr("Unmount succeeded")); - else Interface->Error(tr("Unmount failed!")); + if(res) MSG_INFO(tr("Unmount succeeded")); + else MSG_ERROR(tr("Unmount failed!")); } return osContinue; } @@ -322,7 +321,7 @@ bool res=src->Eject(); RefreshCurrent(); DisplayCurrent(true); - if(!res) Interface->Error(tr("Eject failed!")); + if(!res) MSG_ERROR(tr("Eject failed!")); } return osContinue; } @@ -346,15 +345,4 @@ return state; } -// --- cProgressBar ------------------------------------------------------------ - -cProgressBar::cProgressBar(int Width, int Height, int Current, int Total) -:cBitmap(Width, Height, 2) -{ - if(Total > 0) { - int p = Current * width / Total;; - Fill(0, 0, p, Height - 1, clrGreen); - Fill(p + 1, 0, Width - 1, Height - 1, clrWhite); - } -} diff -Nur mp3-0.9.0/menu.h mp3-0.9.0jau01/menu.h --- mp3-0.9.0/menu.h 2004-05-01 16:04:22.000000000 +0200 +++ mp3-0.9.0jau01/menu.h 2004-05-28 05:04:34.996219856 +0200 @@ -23,6 +23,8 @@ #define ___MENU_H #include +#include +#include // ---------------------------------------------------------------- @@ -77,11 +79,4 @@ static cFileSource *GetSelected(void) { return selected; } }; -// ---------------------------------------------------------------- - -class cProgressBar : public cBitmap { -public: - cProgressBar(int Width, int Height, int Current, int Total); - }; - #endif //___MENU_H diff -Nur mp3-0.9.0/mp3.c mp3-0.9.0jau01/mp3.c --- mp3-0.9.0/mp3.c 2004-05-01 17:33:50.000000000 +0200 +++ mp3-0.9.0jau01/mp3.c 2004-05-28 05:45:24.798793256 +0200 @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include "common.h" #include "setup.h" @@ -131,6 +133,11 @@ int flip, flipint, top; int lastIndex, lastTotal, lastTop; int framesPerSecond; + + cSkinDisplayReplay *displayReplay; + cOsd *displayBig; + const cFont *fontList; + // bool jumpactive, jumphide, jumpsecs; int jumpmm; @@ -164,6 +171,9 @@ lastMode=0; framesPerSecond=SecondsToFrames(1); plist=0; // the player is responsible to delete playlist + displayReplay = NULL; + displayBig = NULL; + fontList = cFont::GetFont(fontOsd); } cMP3Control::~cMP3Control() @@ -172,6 +182,14 @@ Hide(); Stop(); cStatus::MsgReplaying(this, NULL); + if(displayReplay) { + delete displayReplay; + displayReplay = NULL; + } + if(displayBig) { + delete displayBig; + displayBig = NULL; + } } void cMP3Control::Stop(void) @@ -209,7 +227,14 @@ void cMP3Control::Hide(void) { if(visible) { - Interface->Close(); + if(displayReplay) { + delete displayReplay; + displayReplay = NULL; + } + if(displayBig) { + delete displayBig; + displayBig = NULL; + } needsFastResponse=visible=bigwin=false; } } @@ -217,7 +242,7 @@ #define CTAB 11 // some tabbing values for the progress display #define CTAB2 5 -#define PL_ROWS (Setup.OSDheight-3) +#define PL_ROWS (Setup.OSDHeight-fontList->Height()) void cMP3Control::ShowProgress(bool open, bool bigWin) { @@ -226,12 +251,12 @@ if(player->GetIndex(index,total) && total>=0) { index/=framesPerSecond; total/=framesPerSecond; if(!visible && open) { - static int cols[] = { 5,0 }; - Interface->Open(Setup.OSDwidth, bigWin?0:-2); - Interface->SetCols(cols); bigwin=bigWin; + if(bigwin) { + displayBig = cOsdProvider::NewOsd(0,0); + } + displayReplay = Skins.Current()->DisplayReplay(false); needsFastResponse=visible=true; - Interface->Clear(); fliptime=listtime=0; flipint=0; flip=-1; top=lastTop=-1; lastIndex=lastTotal=-1; delete lastMode; lastMode=0; } @@ -256,33 +281,27 @@ if(!selecting && changed) { char *buf=0; - asprintf(&buf,"(%d/%d)",mode->Num,mode->MaxNum); - Interface->Fill(0,-2,CTAB,1,clrBackground); - Interface->Write(0,-2,buf); + char buf2[10]; + buf2[0]=0; + if(mode->Loop) strncat(buf2, "L ", 10); + if(mode->Shuffle) strncat(buf2, "S ", 10); + if(mode->Artist[0]) + asprintf(&buf,"%s - %s (%d/%d) %s", + mode->Title, mode->Artist, mode->Num,mode->MaxNum, buf2); + else + asprintf(&buf,"%s (%d/%d) %s", + mode->Title, mode->Num,mode->MaxNum, buf2); + displayReplay->SetTitle(buf); free(buf); flush=true; } - if(!lastMode || mode->Loop!=lastMode->Loop) { - if(mode->Loop) Interface->Write(-4,-1,"L",clrBlack,clrYellow); - else Interface->Fill(-4,-1,2,1,clrBackground); - flush=true; - } - if(!lastMode || mode->Shuffle!=lastMode->Shuffle) { - if(mode->Shuffle) Interface->Write(-2,-1,"S",clrWhite,clrRed); - else Interface->Fill(-2,-1,2,1,clrBackground); - flush=true; - } - if(index!=lastIndex || total!=lastTotal) { if(total>0) { - cProgressBar ProgressBar((Width()-CTAB-CTAB2)*cOsd::CellWidth(), cOsd::LineHeight(), index, total); - Interface->SetBitmap(CTAB*cOsd::CellWidth(), (abs(Height())-1)*cOsd::LineHeight(), ProgressBar); + displayReplay->SetTotal(IndexToHMSF(total)); + displayReplay->SetProgress(index, total); } - char *buf; - asprintf(&buf,total?"%02d:%02d/%02d:%02d":"%02d:%02d",index/60,index%60,total/60,total%60); - Interface->Write(0,-1,buf); - free(buf); + displayReplay->SetCurrent(IndexToHMSF(index)); flush=true; } @@ -306,17 +325,13 @@ flip=0; // fall through case 0: - asprintf(&buf,mode->Artist[0]?"%s - %s":"%s",mode->Title,mode->Artist); - flipint=6; - break; - case 1: if(mode->Album[0]) { asprintf(&buf,mode->Year>0?"from: %s (%d)":"from: %s",mode->Album,mode->Year); flipint=4; } else fliptime=0; break; - case 2: + case 1: if(mode->MaxBitrate>0) asprintf(&buf,"%.1f kHz, %d-%d kbps, %s",mode->SampleFreq/1000.0,mode->Bitrate/1000,mode->MaxBitrate/1000,mode->SMode); else @@ -328,7 +343,7 @@ } } - if(bigwin && mode->PlayList) { + if(bigwin && displayBig && mode->PlayList) { bool all=(top!=lastTop || changed); if(all || time(0)>listtime+2) { int num=(top>0 && mode->Num==lastMode->Num) ? top : mode->Num - PL_ROWS/2; @@ -343,12 +358,12 @@ asprintf(&buf,si->Artist?"%d.\t%s - %s":"%d.\t%s",num,si->Title,si->Artist); else asprintf(&buf,"%d.\t%s",num,song->Name()); - eDvbColor fg=clrWhite, bg=clrBackground; + int fg=clrWhite, bg=clrTransparent; int hash=MakeHash(buf); if(num==mode->Num) { fg=clrBlack; bg=clrCyan; hash=(hash^77) + 23; } if(all || hash!=hashlist[i]) { - Interface->Fill(0,i,Setup.OSDwidth,1,clrBackground); - Interface->WriteText(0,i,buf,fg,bg); + displayBig->DrawRectangle(0,i,Setup.OSDWidth,i+1,clrTransparent); + displayBig->DrawText(0,i,buf,fg,bg,fontList); flush=true; hashlist[i]=hash; } @@ -359,8 +374,7 @@ } } } - - if(flush) Interface->Flush(); + if(flush && displayBig) displayBig->Flush(); } lastIndex=index; lastTotal=total; @@ -370,8 +384,7 @@ void cMP3Control::DisplayInfo(const char *s) { - Interface->Fill(CTAB,-2,Width()-CTAB,1,clrBackground); - if(s) Interface->Write(CTAB,-2,s); + displayReplay->SetJump(s); } void cMP3Control::JumpDisplay(void) @@ -496,9 +509,7 @@ selecting=true; lastkeytime=time_ms(); char *buf=0; asprintf(&buf,"(%d-/%d)",number,lastMode->MaxNum); - Interface->Fill(0,-2,CTAB,1,clrBackground); - Interface->Write(0,-2,buf); - Interface->Flush(); + displayReplay->SetTitle(buf); free(buf); break; } @@ -593,7 +604,7 @@ char *buf=0; asprintf(&buf,"%s:\t%s",name,text?text:""); cOsdItem *item = new cOsdItem(buf,osBack); - item->SetColor(clrWhite, clrBackground); + //item->SetColor(clrWhite, clrTransparent); free(buf); Add(item); return item; } @@ -756,8 +767,7 @@ { cFileObj *item=cMenuInstantBrowse::GetSelected(); if(item) { - Interface->Status(tr("Scanning directory...")); - Interface->Flush(); + MSG_STATUS(tr("Scanning directory...")); cInstantPlayList *newpl=new cInstantPlayList(item); if(newpl->Load()) { if(newpl->Count()) { @@ -780,9 +790,9 @@ Refresh(); Display(); } } - else Interface->Error(tr("Empty directory!")); + else MSG_ERROR(tr("Empty directory!")); } - else Interface->Error(tr("Error scanning directory!")); + else MSG_ERROR(tr("Error scanning directory!")); delete newpl; } } @@ -869,7 +879,7 @@ char *buf=NULL; asprintf(&buf,"%s\t%s",tr("Old name:"),oldname); cOsdItem *old = new cOsdItem(buf,osContinue); - old->SetColor(clrWhite, clrBackground); + // old->SetColor(clrWhite, clrTransparent); Add(old); free(buf); @@ -972,8 +982,7 @@ void cMenuMP3::ScanLists(void) { Clear(); - Interface->Status(tr("Scanning playlists...")); - Interface->Flush(); + MSG_STATUS(tr("Scanning playlists...")); if(lists->Load(MP3Sources.GetSource())) { cPlayList *plist=lists->First(); while(plist) { @@ -981,7 +990,7 @@ plist=lists->Next(plist); } } - else Interface->Error(tr("Error scanning playlists!")); + else MSG_ERROR(tr("Error scanning playlists!")); } eOSState cMenuMP3::Delete(void) @@ -995,7 +1004,7 @@ cOsdMenu::Del(Current()); Display(); } - else Interface->Error(tr("Error deleting playlist!")); + else MSG_ERROR(tr("Error deleting playlist!")); } } return osContinue; @@ -1018,7 +1027,7 @@ isyslog("MP3: playlist %s added", plist->Name()); return AddSubMenu(new cMenuPlayList(plist)); } - Interface->Error(tr("Error creating playlist!")); + MSG_ERROR(tr("Error creating playlist!")); delete plist; return osContinue; } @@ -1039,7 +1048,7 @@ RefreshCurrent(); DisplayCurrent(true); } - else Interface->Error(tr("Error renaming playlist!")); + else MSG_ERROR(tr("Error renaming playlist!")); } return osContinue; } @@ -1049,12 +1058,12 @@ if(HasSubMenu() || Count() == 0) return osContinue; cPlayList *plist = ((cMenuMP3Item *)Get(Current()))->List(); - if(!plist->Load()) Interface->Error(tr("Error loading playlist!")); + if(!plist->Load()) MSG_ERROR(tr("Error loading playlist!")); else if(!plist->IsWinAmp()) { isyslog("MP3: editing playlist %s", plist->Name()); return AddSubMenu(new cMenuPlayList(plist)); } - else Interface->Error(tr("Can't edit a WinAmp playlist!")); + else MSG_ERROR(tr("Can't edit a WinAmp playlist!")); return osContinue; } @@ -1062,8 +1071,7 @@ { if(HasSubMenu() || Count() == 0) return osContinue; - Interface->Status(tr("Loading playlist...")); - Interface->Flush(); + MSG_STATUS(tr("Loading playlist...")); cPlayList *newpl=new cPlayList(((cMenuMP3Item *)Get(Current()))->List()); if(newpl->Load() && newpl->Count()) { isyslog("mp3: playback started with playlist %s", newpl->Name()); @@ -1071,7 +1079,7 @@ return osEnd; } delete newpl; - Interface->Error(tr("Error loading playlist!")); + MSG_ERROR(tr("Error loading playlist!")); return osContinue; } @@ -1104,8 +1112,7 @@ instanting=false; cFileObj *item=cMenuInstantBrowse::GetSelected(); if(item) { - Interface->Status(tr("Building playlist...")); - Interface->Flush(); + MSG_STATUS(tr("Building playlist...")); cInstantPlayList *newpl = new cInstantPlayList(item); if(newpl->Load() && newpl->Count()) { isyslog("mp3: playback started with instant playlist %s", newpl->Name()); @@ -1113,7 +1120,7 @@ return osEnd; } delete newpl; - Interface->Error(tr("Error building playlist!")); + MSG_ERROR(tr("Error building playlist!")); } return osContinue; } diff -Nur mp3-0.9.0/player-mp3.c mp3-0.9.0jau01/player-mp3.c --- mp3-0.9.0/player-mp3.c 2004-05-01 17:30:12.000000000 +0200 +++ mp3-0.9.0jau01/player-mp3.c 2004-05-28 06:03:01.518147496 +0200 @@ -1218,7 +1218,9 @@ playing=0; if(decoder) { decoder->Stop(); decoder=0; } levelgood=false; +#ifdef DEBUG out->Stats(); if(haslevel) norm.Stats(); +#endif if(state==msStop) SetPlayMode(pmStopped); break; case msWait: diff -Nur mp3-0.9.0/stream.c mp3-0.9.0jau01/stream.c --- mp3-0.9.0/stream.c 2004-05-01 22:01:14.000000000 +0200 +++ mp3-0.9.0jau01/stream.c 2004-05-28 05:15:32.439273320 +0200 @@ -370,10 +370,8 @@ free(p); free(h); cc++; - if(cc==1 && Interface) { - Interface->Open(0,-1); - Interface->Status(tr("Connecting to stream server ...")); - Interface->Flush(); + if(cc==1) { + MSG_STATUS(tr("Connecting to stream server ...")); } if(net->Connect(MP3Setup.UseProxy ? MP3Setup.ProxyHost:host , MP3Setup.UseProxy ? MP3Setup.ProxyPort:port)) { @@ -381,9 +379,6 @@ if(net->Puts(buff)>0) res=GetHTTPResponse(); } - if(cc==1 && Interface) { - Interface->Close(); - } cc--; return res; } vdr-plugin-dvd-0.3.7/patches/vdr-1.3.10_spu_01.diff000066400000000000000000000151311415711736600213600ustar00rootroot00000000000000--- ../vdr-1.3.10/spu.h 2002-09-08 16:17:51.000000000 +0200 +++ src/spu.h 2004-06-08 21:48:02.761556408 +0200 @@ -32,6 +32,9 @@ uint32_t palette) = 0; virtual void clearHighlight(void) = 0; virtual void Empty(void) = 0; + virtual void Hide(void) = 0; + virtual void Draw(void) = 0; + virtual bool IsVisible(void) = 0; virtual void processSPU(uint32_t pts, uint8_t * buf) = 0; }; --- ../vdr-1.3.10/dvbspu.h 2004-05-31 10:49:20.000000000 +0200 +++ src/dvbspu.h 2004-06-08 21:51:33.025591416 +0200 @@ -132,9 +132,6 @@ int ScaleYres(int value); void DrawBmp(sDvbSpuRect & size, cBitmap * bmp); - void Draw(); - void Hide(); - public: cDvbSpuDecoder(); ~cDvbSpuDecoder(); @@ -146,8 +143,14 @@ void setHighlight(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint32_t palette); void clearHighlight(void); - void Empty(void); void processSPU(uint32_t pts, uint8_t * buf); + + cOsd * getOsd() { return osd; } // fixme: not necessary ? yet ! + + void Empty(void); + void Hide(void); + void Draw(void); + bool IsVisible(void) { return osd!=NULL; } }; // --- cDvbSpuPalette ------------------------------------------- --- ../vdr-1.3.10/dvbspu.c 2004-05-22 16:02:32.000000000 +0200 +++ src/dvbspu.c 2004-06-10 04:27:45.037899744 +0200 @@ -35,11 +35,15 @@ * transparencies */ -// #define SPUDEBUG +#if 0 + #define SPUDEBUG + #undef DEBUG +#endif #ifdef SPUDEBUG #define DEBUG(format, args...) printf (format, ## args) #else +#undef DEBUG #define DEBUG(format, args...) #endif @@ -240,7 +244,7 @@ { setTime(pts); - DEBUG("SPU pushData: pts: %d\n", pts); + DEBUG("DVB_SPU pushData: pts: %d\n", pts); delete spubmp; spubmp = NULL; @@ -261,6 +265,7 @@ void cDvbSpuDecoder::setPalette(uint32_t * pal) { + DEBUG("DVB_SPU setPalette\n"); palette.setPalette(pal); } @@ -280,7 +285,7 @@ pld[2] != hlpDescr[2] || pld[3] != hlpDescr[3]; if (ne) { - DEBUG("setHighlight: %d,%d x %d,%d\n", sx, sy, ex, ey); + DEBUG("DVB_SPU setHighlight: %d,%d x %d,%d\n", sx, sy, ex, ey); hlpsize.x1 = sx; hlpsize.y1 = sy; hlpsize.x2 = ex; @@ -288,11 +293,14 @@ memcpy(hlpDescr, pld, sizeof(aDvbSpuPalDescr)); highlight = true; clean = false; + } else { + DEBUG("DVB_SPU setHighlight dropped ..\n"); } } void cDvbSpuDecoder::clearHighlight(void) { + DEBUG("DVB_SPU clearHighlight\n"); clean &= !highlight; highlight = false; hlpsize.x1 = -1; @@ -334,11 +342,14 @@ void cDvbSpuDecoder::Draw(void) { + DEBUG("DVB_SPU Draw ..\n"); Hide(); if (!spubmp) return; + DEBUG("DVB_SPU Draw with spubmp\n"); + cBitmap *fg = NULL; cBitmap *bg = NULL; sDvbSpuRect bgsize; @@ -363,11 +374,13 @@ } if (bg || fg) { - if (osd == NULL) + if (osd == NULL) { if ((osd = cOsdProvider::NewOsd(0, 0)) == NULL) { dsyslog("NewOsd failed\n"); return; } + DEBUG("DVB_SPU new Osd\n"); + } if (fg) DrawBmp(hlsize, fg); @@ -383,12 +396,14 @@ void cDvbSpuDecoder::Hide(void) { + DEBUG("DVB_SPU Hide\n"); delete osd; osd = NULL; } void cDvbSpuDecoder::Empty(void) { + DEBUG("DVB_SPU Empty\n"); Hide(); delete spubmp; @@ -403,20 +418,26 @@ int cDvbSpuDecoder::setTime(uint32_t pts) { + //DEBUG("DVB_SPU setTime .\n"); if (!spu) return 0; + //DEBUG("DVB_SPU setTime .. spu=%p, clean=%d\n", spu, clean); if (spu && !clean) Draw(); + //DEBUG("DVB_SPU setTime ...\n"); + while (DCSQ_offset != prev_DCSQ_offset) { /* Display Control Sequences */ int i = DCSQ_offset; state = spNONE; uint32_t exec_time = spupts + spuU32(i) * 1024; - if ((pts != 0) && (exec_time > pts)) + + if ((pts != 0) && (exec_time > pts)) { return 0; - DEBUG("offs = %d, rel = %d, time = %d, pts = %d, diff = %d\n", + } + DEBUG("DVB_SPU setTime offs = %d, rel = %d, time = %d, pts = %d, diff = %d\n", i, spuU32(i) * 1024, exec_time, pts, exec_time - pts); if (pts != 0) { @@ -432,6 +453,7 @@ i += 2; while (spu[i] != CMD_SPU_EOF) { // Command Sequence + DEBUG("\t@ %d: 0x%X (%d), ", i, spu[i], spu[i]); switch (spu[i]) { case CMD_SPU_SHOW: // show subpicture DEBUG("\tshow subpicture\n"); @@ -446,6 +468,7 @@ break; case CMD_SPU_SET_PALETTE: // CLUT + DEBUG("\tset palette\n"); palDescr[0].index = spu[i + 2] & 0xf; palDescr[1].index = spu[i + 2] >> 4; palDescr[2].index = spu[i + 1] & 0xf; @@ -454,6 +477,7 @@ break; case CMD_SPU_SET_ALPHA: // transparency palette + DEBUG("\tset alpha\n"); palDescr[0].trans = spu[i + 2] & 0xf; palDescr[1].trans = spu[i + 2] >> 4; palDescr[2].trans = spu[i + 1] & 0xf; @@ -462,6 +486,7 @@ break; case CMD_SPU_SET_SIZE: // image coordinates + DEBUG("\tset size "); size.x1 = (spu[i + 1] << 4) | (spu[i + 2] >> 4); size.x2 = ((spu[i + 2] & 0x0f) << 8) | spu[i + 3]; @@ -474,6 +499,7 @@ break; case CMD_SPU_SET_PXD_OFFSET: // image 1 / image 2 offsets + DEBUG("\tset pxd off "); fodd = spuU32(i + 1); feven = spuU32(i + 3); DEBUG("\todd = %d even = %d\n", fodd, feven); @@ -488,8 +514,8 @@ break; default: - esyslog("invalid sequence in control header (%.2x)\n", - spu[i]); + DEBUG("invalid sequence in control header (%.2x)\n", spu[i]); + esyslog("invalid sequence in control header (%.2x)\n", spu[i]); assert(0); i++; break; @@ -499,6 +525,7 @@ delete spubmp; spubmp = new cDvbSpuBitmap(size, spu + fodd, spu + feven, spu + feven, spu + cmdOffs()); + DEBUG("DVB_SPU new spubmp\n"); } } else if (!clean) state = spSHOW; vdr-plugin-dvd-0.3.7/patches/vdr-1.3.11_spu_02.diff000066400000000000000000000051351415711736600213650ustar00rootroot00000000000000diff -ur vdr-1.3.11_orig/dvbosd.c vdr-1.3.11/dvbosd.c --- vdr-1.3.11_orig/dvbosd.c Tue Jul 20 17:51:59 2004 +++ vdr-1.3.11/dvbosd.c Tue Jul 20 17:52:30 2004 @@ -39,6 +39,10 @@ shown = false; if (osdDev < 0) esyslog("ERROR: illegal OSD device handle (%d)!", osdDev); + for (int i = 1 ;i <= MAXNUMWINDOWS; i++) { + Cmd(OSD_SetWindow, 0, i); + Cmd(OSD_Clear); + } } cDvbOsd::~cDvbOsd() diff -ur vdr-1.3.11_orig/dvbspu.c vdr-1.3.11/dvbspu.c --- vdr-1.3.11_orig/dvbspu.c Tue Jul 20 17:51:59 2004 +++ vdr-1.3.11/dvbspu.c Tue Jul 20 17:54:39 2004 @@ -227,6 +227,7 @@ spu = NULL; osd = NULL; spubmp = NULL; + allowedShow = false; } cDvbSpuDecoder::~cDvbSpuDecoder() @@ -236,7 +237,7 @@ delete osd; } -void cDvbSpuDecoder::processSPU(uint32_t pts, uint8_t * buf) +void cDvbSpuDecoder::processSPU(uint32_t pts, uint8_t * buf, bool AllowedShow) { setTime(pts); @@ -252,6 +253,7 @@ prev_DCSQ_offset = 0; clean = true; + allowedShow = AllowedShow; } void cDvbSpuDecoder::setScaleMode(cSpuDecoder::eScaleMode ScaleMode) @@ -503,7 +505,7 @@ } else if (!clean) state = spSHOW; - if (state == spSHOW || state == spMENU) + if ((state == spSHOW && allowedShow) || state == spMENU) Draw(); if (state == spHIDE) diff -ur vdr-1.3.11_orig/dvbspu.h vdr-1.3.11/dvbspu.h --- vdr-1.3.11_orig/dvbspu.h Tue Jul 20 17:51:59 2004 +++ vdr-1.3.11/dvbspu.h Tue Jul 20 17:54:50 2004 @@ -120,6 +120,7 @@ uint16_t prev_DCSQ_offset; cDvbSpuBitmap *spubmp; + bool allowedShow; private: int cmdOffs(void) { return ((spu[2] << 8) | spu[3]); @@ -131,7 +132,6 @@ int ScaleYcoord(int value); int ScaleYres(int value); void DrawBmp(sDvbSpuRect & size, cBitmap * bmp); - public: cDvbSpuDecoder(); ~cDvbSpuDecoder(); @@ -147,7 +147,7 @@ void Hide(void); void Draw(void); bool IsVisible(void) { return osd != NULL; } - void processSPU(uint32_t pts, uint8_t * buf); + void processSPU(uint32_t pts, uint8_t * buf, bool AllowedShow); }; // --- cDvbSpuPalette ------------------------------------------- diff -ur vdr-1.3.11_orig/spu.h vdr-1.3.11/spu.h --- vdr-1.3.11_orig/spu.h Tue Jul 20 17:51:59 2004 +++ vdr-1.3.11/spu.h Tue Jul 20 17:54:58 2004 @@ -35,7 +35,7 @@ virtual void Hide(void) = 0; virtual void Draw(void) = 0; virtual bool IsVisible(void) = 0; - virtual void processSPU(uint32_t pts, uint8_t * buf) = 0; + virtual void processSPU(uint32_t pts, uint8_t * buf, bool AllowedShow) = 0; }; #endif // __SPU_VDR_H vdr-plugin-dvd-0.3.7/patches/vdr-1.3.12_spu_02.diff000066400000000000000000000037731415711736600213740ustar00rootroot00000000000000diff -ur vdr-1.3.12_orig/dvbspu.c vdr-1.3.12/dvbspu.c --- vdr-1.3.12_orig/dvbspu.c Sun Jul 18 17:27:50 2004 +++ vdr-1.3.12/dvbspu.c Tue Jul 20 17:47:43 2004 @@ -227,6 +227,7 @@ spu = NULL; osd = NULL; spubmp = NULL; + allowedShow = false; } cDvbSpuDecoder::~cDvbSpuDecoder() @@ -236,7 +237,7 @@ delete osd; } -void cDvbSpuDecoder::processSPU(uint32_t pts, uint8_t * buf) +void cDvbSpuDecoder::processSPU(uint32_t pts, uint8_t * buf, bool AllowedShow) { setTime(pts); @@ -252,6 +253,7 @@ prev_DCSQ_offset = 0; clean = true; + allowedShow = AllowedShow; } void cDvbSpuDecoder::setScaleMode(cSpuDecoder::eScaleMode ScaleMode) @@ -503,7 +505,7 @@ } else if (!clean) state = spSHOW; - if (state == spSHOW || state == spMENU) + if ((state == spSHOW && allowedShow) || state == spMENU) Draw(); if (state == spHIDE) diff -ur vdr-1.3.12_orig/dvbspu.h vdr-1.3.12/dvbspu.h --- vdr-1.3.12_orig/dvbspu.h Sun Jul 18 17:27:50 2004 +++ vdr-1.3.12/dvbspu.h Tue Jul 20 17:48:03 2004 @@ -120,6 +120,7 @@ uint16_t prev_DCSQ_offset; cDvbSpuBitmap *spubmp; + bool allowedShow; private: int cmdOffs(void) { return ((spu[2] << 8) | spu[3]); @@ -147,7 +148,7 @@ void Hide(void); void Draw(void); bool IsVisible(void) { return osd != NULL; } - void processSPU(uint32_t pts, uint8_t * buf); + void processSPU(uint32_t pts, uint8_t * buf, bool AllowedShow); }; // --- cDvbSpuPalette ------------------------------------------- diff -ur vdr-1.3.12_orig/spu.h vdr-1.3.12/spu.h --- vdr-1.3.12_orig/spu.h Sun Jul 18 17:27:50 2004 +++ vdr-1.3.12/spu.h Tue Jul 20 17:48:15 2004 @@ -35,7 +35,7 @@ virtual void Hide(void) = 0; virtual void Draw(void) = 0; virtual bool IsVisible(void) = 0; - virtual void processSPU(uint32_t pts, uint8_t * buf) = 0; + virtual void processSPU(uint32_t pts, uint8_t * buf, bool AllowedShow) = 0; }; #endif // __SPU_VDR_H vdr-plugin-dvd-0.3.7/patches/vdr-1.3.13_spu_02_menu.diff000066400000000000000000000112741415711736600224140ustar00rootroot00000000000000diff -ur vdr-1.3.13_orig/dvbspu.c vdr-1.3.13/dvbspu.c --- vdr-1.3.13_orig/dvbspu.c Sun Oct 17 18:39:51 2004 +++ vdr-1.3.13/dvbspu.c Thu Oct 21 22:06:05 2004 @@ -227,6 +227,7 @@ spu = NULL; osd = NULL; spubmp = NULL; + allowedShow = false; } cDvbSpuDecoder::~cDvbSpuDecoder() @@ -236,7 +237,7 @@ delete osd; } -void cDvbSpuDecoder::processSPU(uint32_t pts, uint8_t * buf) +void cDvbSpuDecoder::processSPU(uint32_t pts, uint8_t * buf, bool AllowedShow) { setTime(pts); @@ -252,6 +253,7 @@ prev_DCSQ_offset = 0; clean = true; + allowedShow = AllowedShow; } void cDvbSpuDecoder::setScaleMode(cSpuDecoder::eScaleMode ScaleMode) @@ -319,25 +321,43 @@ return value; } -void cDvbSpuDecoder::DrawBmp(sDvbSpuRect & size, cBitmap * bmp) -{ - int x2 = size.x2; - while ((x2 - size.x1 + 1) & 0x03) - x2++; - tArea Area = { size.x1, size.y1, x2, size.y2, 2 }; - osd->SetAreas(&Area, 1); - if (x2 > size.x2) - osd->DrawRectangle(size.x2 + 1, size.y1, x2, size.y2, clrTransparent); - osd->DrawBitmap(size.x1, size.y1, *bmp); - delete bmp; +sDvbSpuRect cDvbSpuDecoder::CalcAreaSize(sDvbSpuRect fgsize, cBitmap *fgbmp, sDvbSpuRect bgsize, cBitmap *bgbmp) { + sDvbSpuRect size; + if (fgbmp && bgbmp) { + size.x1 = min(fgsize.x1, bgsize.x1); + size.y1 = min(fgsize.y1, bgsize.y1); + size.x2 = max(fgsize.x2, bgsize.x2); + size.y2 = max(fgsize.y2, bgsize.y2); + } + else if (fgbmp) { + size.x1 = fgsize.x1; + size.y1 = fgsize.y1; + size.x2 = fgsize.x2; + size.y2 = fgsize.y2; + } + else if (bgbmp) { + size.x1 = bgsize.x1; + size.y1 = bgsize.y1; + size.x2 = bgsize.x2; + size.y2 = bgsize.y2; + } + else { + size.x1 = 0; + size.y1 = 0; + size.x2 = 0; + size.y2 = 0; + } + return size; } void cDvbSpuDecoder::Draw(void) { - Hide(); +// Hide(); - if (!spubmp) + if (!spubmp) { + Hide(); return; + } cBitmap *fg = NULL; cBitmap *bg = NULL; @@ -362,22 +382,33 @@ } } + sDvbSpuRect areaSize = CalcAreaSize(hlsize, fg, bgsize, bg); + + if(!fg || !bg || !osd) { + Hide(); + } + if (bg || fg) { - if (osd == NULL) + if (osd == NULL) { if ((osd = cOsdProvider::NewOsd(0, 0)) == NULL) { + delete fg; + delete bg; dsyslog("NewOsd failed\n"); return; } + int x2 = areaSize.x2; + while ((x2 - areaSize.x1 + 1) & 0x03) + x2++; + tArea Area = { areaSize.x1, areaSize.y1, x2, areaSize.y2, (fg && bg) ? 4 : 2 }; + osd->SetAreas(&Area, 1); + } - if (fg) - DrawBmp(hlsize, fg); - - if (bg) - DrawBmp(bgsize, bg); - + if (bg) osd->DrawBitmap(bgsize.x1, bgsize.y1, *bg); + if (fg) osd->DrawBitmap(hlsize.x1, hlsize.y1, *fg); + delete fg; + delete bg; osd->Flush(); } - clean = true; } @@ -503,7 +534,7 @@ } else if (!clean) state = spSHOW; - if (state == spSHOW || state == spMENU) + if ((state == spSHOW && allowedShow) || state == spMENU) Draw(); if (state == spHIDE) diff -ur vdr-1.3.13_orig/dvbspu.h vdr-1.3.13/dvbspu.h --- vdr-1.3.13_orig/dvbspu.h Sun Oct 17 18:39:51 2004 +++ vdr-1.3.13/dvbspu.h Thu Oct 21 22:06:17 2004 @@ -120,6 +120,7 @@ uint16_t prev_DCSQ_offset; cDvbSpuBitmap *spubmp; + bool allowedShow; private: int cmdOffs(void) { return ((spu[2] << 8) | spu[3]); @@ -130,8 +131,7 @@ int ScaleYcoord(int value); int ScaleYres(int value); - void DrawBmp(sDvbSpuRect & size, cBitmap * bmp); - + sDvbSpuRect CalcAreaSize(sDvbSpuRect fgsize, cBitmap *fgbmp, sDvbSpuRect bgsize, cBitmap *bgbmp); public: cDvbSpuDecoder(); ~cDvbSpuDecoder(); @@ -147,7 +147,7 @@ void Hide(void); void Draw(void); bool IsVisible(void) { return osd != NULL; } - void processSPU(uint32_t pts, uint8_t * buf); + void processSPU(uint32_t pts, uint8_t * buf, bool AllowedShow); }; // --- cDvbSpuPalette ------------------------------------------- diff -ur vdr-1.3.13_orig/spu.h vdr-1.3.13/spu.h --- vdr-1.3.13_orig/spu.h Sun Oct 17 18:39:51 2004 +++ vdr-1.3.13/spu.h Thu Oct 21 22:06:27 2004 @@ -35,7 +35,7 @@ virtual void Hide(void) = 0; virtual void Draw(void) = 0; virtual bool IsVisible(void) = 0; - virtual void processSPU(uint32_t pts, uint8_t * buf) = 0; + virtual void processSPU(uint32_t pts, uint8_t * buf, bool AllowedShow) = 0; }; #endif // __SPU_VDR_H vdr-plugin-dvd-0.3.7/patches/vdr-1.3.16-spu-02.diff000066400000000000000000000040751415711736600212300ustar00rootroot00000000000000diff -ur vdr-1.3.16_orig/dvbspu.c vdr-1.3.16/dvbspu.c --- vdr-1.3.16_orig/dvbspu.c 2004-11-14 19:07:50.000000000 +0100 +++ vdr-1.3.16/dvbspu.c 2004-11-14 19:08:32.000000000 +0100 @@ -227,6 +227,7 @@ spu = NULL; osd = NULL; spubmp = NULL; + allowedShow = false; } cDvbSpuDecoder::~cDvbSpuDecoder() @@ -236,7 +237,7 @@ delete osd; } -void cDvbSpuDecoder::processSPU(uint32_t pts, uint8_t * buf) +void cDvbSpuDecoder::processSPU(uint32_t pts, uint8_t * buf, bool AllowedShow) { setTime(pts); @@ -252,6 +253,7 @@ prev_DCSQ_offset = 0; clean = true; + allowedShow = AllowedShow; } void cDvbSpuDecoder::setScaleMode(cSpuDecoder::eScaleMode ScaleMode) @@ -530,7 +532,7 @@ } else if (!clean) state = spSHOW; - if (state == spSHOW || state == spMENU) + if ((state == spSHOW && allowedShow) || state == spMENU) Draw(); if (state == spHIDE) diff -ur vdr-1.3.16_orig/dvbspu.h vdr-1.3.16/dvbspu.h --- vdr-1.3.16_orig/dvbspu.h 2004-11-14 19:07:50.000000000 +0100 +++ vdr-1.3.16/dvbspu.h 2004-11-14 19:08:44.000000000 +0100 @@ -120,6 +120,7 @@ uint16_t prev_DCSQ_offset; cDvbSpuBitmap *spubmp; + bool allowedShow; private: int cmdOffs(void) { return ((spu[2] << 8) | spu[3]); @@ -147,7 +148,7 @@ void Hide(void); void Draw(void); bool IsVisible(void) { return osd != NULL; } - void processSPU(uint32_t pts, uint8_t * buf); + void processSPU(uint32_t pts, uint8_t * buf, bool AllowedShow); }; // --- cDvbSpuPalette ------------------------------------------- diff -ur vdr-1.3.16_orig/spu.h vdr-1.3.16/spu.h --- vdr-1.3.16_orig/spu.h 2004-11-14 19:07:50.000000000 +0100 +++ vdr-1.3.16/spu.h 2004-11-14 19:08:55.000000000 +0100 @@ -35,7 +35,7 @@ virtual void Hide(void) = 0; virtual void Draw(void) = 0; virtual bool IsVisible(void) = 0; - virtual void processSPU(uint32_t pts, uint8_t * buf) = 0; + virtual void processSPU(uint32_t pts, uint8_t * buf, bool AllowedShow) = 0; }; #endif // __SPU_VDR_H vdr-plugin-dvd-0.3.7/patches/vdr-1.3.20_aspectratio.diff000066400000000000000000000124401415711736600225700ustar00rootroot00000000000000diff -bur vdr-1.3.20_orig/device.c vdr-1.3.20/device.c --- vdr-1.3.20_orig/device.c 2005-02-06 21:16:58.000000000 +0100 +++ vdr-1.3.20/device.c 2005-02-06 22:43:29.000000000 +0100 @@ -235,6 +235,7 @@ primaryDevice->MakePrimaryDevice(false); primaryDevice = device[n]; primaryDevice->MakePrimaryDevice(true); + primaryDevice->SetVideoFormat(Setup.VideoFormat); return true; } esyslog("ERROR: invalid primary device number: %d", n + 1); @@ -327,6 +328,28 @@ return false; } +void cDevice::SetVideoDisplayFormat(eVideoDisplayFormat VideoDisplayFormat) +{ + cSpuDecoder *spuDecoder = GetSpuDecoder(); + if (spuDecoder) { + if (Setup.VideoFormat) + spuDecoder->setScaleMode(cSpuDecoder::eSpuNormal); + else { + switch (VideoDisplayFormat) { + case vdfPanAndScan: + spuDecoder->setScaleMode(cSpuDecoder::eSpuPanAndScan); + break; + case vdfLetterBox: + spuDecoder->setScaleMode(cSpuDecoder::eSpuLetterBox); + break; + case vdfCenterCutOut: + spuDecoder->setScaleMode(cSpuDecoder::eSpuNormal); + break; + } + } + } +} + void cDevice::SetVideoFormat(bool VideoFormat16_9) { } @@ -833,6 +856,7 @@ player->device = NULL; player = NULL; SetPlayMode(pmNone); + SetVideoDisplayFormat(vdfLetterBox); Audios.ClearAudio(); } } diff -bur vdr-1.3.20_orig/device.h vdr-1.3.20/device.h --- vdr-1.3.20_orig/device.h 2005-02-06 21:16:58.000000000 +0100 +++ vdr-1.3.20/device.h 2005-02-06 22:43:47.000000000 +0100 @@ -17,6 +17,7 @@ #include "pat.h" #include "ringbuffer.h" #include "sdt.h" +#include "spu.h" #include "sections.h" #include "thread.h" #include "tools.h" @@ -56,6 +57,11 @@ vsNTSC }; +enum eVideoDisplayFormat { vdfPanAndScan, + vdfLetterBox, + vdfCenterCutOut + }; + enum eTrackType { ttNone, ttAudio, ttAudioFirst = ttAudio, @@ -83,7 +89,6 @@ class cChannel; class cPlayer; class cReceiver; -class cSpuDecoder; class cPesAssembler; /// The cDevice class is the base from which actual devices can be derived. @@ -301,6 +306,7 @@ // Video format facilities public: + virtual void SetVideoDisplayFormat(eVideoDisplayFormat VideoDisplayFormat); virtual void SetVideoFormat(bool VideoFormat16_9); ///< Sets the output video format to either 16:9 or 4:3 (only useful ///< if this device has an MPEG decoder). diff -bur vdr-1.3.20_orig/dvbdevice.c vdr-1.3.20/dvbdevice.c --- vdr-1.3.20_orig/dvbdevice.c 2005-02-06 21:16:58.000000000 +0100 +++ vdr-1.3.20/dvbdevice.c 2005-02-06 22:44:27.000000000 +0100 @@ -598,10 +598,35 @@ return false; } +void cDvbDevice::SetVideoDisplayFormat(eVideoDisplayFormat VideoDisplayFormat) +{ + cDevice::SetVideoDisplayFormat(VideoDisplayFormat); + if (HasDecoder()) { + if (Setup.VideoFormat) { + CHECK(ioctl(fd_video, VIDEO_SET_DISPLAY_FORMAT, VIDEO_CENTER_CUT_OUT)); + } + else { + switch (VideoDisplayFormat) { + case vdfPanAndScan: + CHECK(ioctl(fd_video, VIDEO_SET_DISPLAY_FORMAT, VIDEO_PAN_SCAN)); + break; + case vdfLetterBox: + CHECK(ioctl(fd_video, VIDEO_SET_DISPLAY_FORMAT, VIDEO_LETTER_BOX)); + break; + case vdfCenterCutOut: + CHECK(ioctl(fd_video, VIDEO_SET_DISPLAY_FORMAT, VIDEO_CENTER_CUT_OUT)); + break; + } + } + } +} + void cDvbDevice::SetVideoFormat(bool VideoFormat16_9) { - if (HasDecoder()) + if (HasDecoder()) { CHECK(ioctl(fd_video, VIDEO_SET_FORMAT, VideoFormat16_9 ? VIDEO_FORMAT_16_9 : VIDEO_FORMAT_4_3)); + SetVideoDisplayFormat(vdfLetterBox); + } } eVideoSystem cDvbDevice::GetVideoSystem(void) diff -bur vdr-1.3.20_orig/dvbdevice.h vdr-1.3.20/dvbdevice.h --- vdr-1.3.20_orig/dvbdevice.h 2005-02-06 21:16:58.000000000 +0100 +++ vdr-1.3.20/dvbdevice.h 2005-02-06 21:21:06.000000000 +0100 @@ -87,6 +87,7 @@ // Video format facilities public: + virtual void SetVideoDisplayFormat(eVideoDisplayFormat VideoDisplayFormat); virtual void SetVideoFormat(bool VideoFormat16_9); virtual eVideoSystem GetVideoSystem(void); diff -bur vdr-1.3.20_orig/dvbspu.h vdr-1.3.20/dvbspu.h --- vdr-1.3.20_orig/dvbspu.h 2005-02-06 21:16:58.000000000 +0100 +++ vdr-1.3.20/dvbspu.h 2005-02-06 21:29:51.000000000 +0100 @@ -139,6 +139,7 @@ int setTime(uint32_t pts); + cSpuDecoder::eScaleMode getScaleMode(void) {return scaleMode;}; void setScaleMode(cSpuDecoder::eScaleMode ScaleMode); void setPalette(uint32_t * pal); void setHighlight(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, diff -bur vdr-1.3.20_orig/spu.h vdr-1.3.20/spu.h --- vdr-1.3.20_orig/spu.h 2005-02-06 21:16:58.000000000 +0100 +++ vdr-1.3.20/spu.h 2005-02-06 22:18:09.000000000 +0100 @@ -25,6 +25,7 @@ virtual int setTime(uint32_t pts) = 0; + virtual cSpuDecoder::eScaleMode getScaleMode(void) = 0; virtual void setScaleMode(cSpuDecoder::eScaleMode ScaleMode) = 0; virtual void setPalette(uint32_t * pal) = 0; virtual void setHighlight(uint16_t sx, uint16_t sy, vdr-plugin-dvd-0.3.7/patches/vdr-1.3.23-dvbspu.c.diff000066400000000000000000000043021415711736600217150ustar00rootroot00000000000000diff -bur vdr-1.3.23_orig/dvbspu.c vdr-1.3.23/dvbspu.c --- vdr-1.3.23_orig/dvbspu.c 2005-04-03 18:19:40.000000000 +0200 +++ vdr-1.3.23/dvbspu.c 2005-04-09 01:27:24.000000000 +0200 @@ -143,6 +143,8 @@ if (ret) DEBUG("MinSize: (%d, %d) x (%d, %d)\n", size.x1, size.y1, size.x2, size.y2); + if (size.x1 > size.x2 || size.y1 > size.y2) + return false; return ret; } @@ -304,24 +306,6 @@ hlpsize.y2 = -1; } -int cDvbSpuDecoder::ScaleYcoord(int value) -{ - if (scaleMode == eSpuLetterBox) { - int offset = cDevice::PrimaryDevice()->GetVideoSystem() == vsPAL ? 72 : 60; - return lround((value * 3.0) / 4.0) + offset; - } - else - return value; -} - -int cDvbSpuDecoder::ScaleYres(int value) -{ - if (scaleMode == eSpuLetterBox) - return lround((value * 3.0) / 4.0); - else - return value; -} - sDvbSpuRect cDvbSpuDecoder::CalcAreaSize(sDvbSpuRect fgsize, cBitmap *fgbmp, sDvbSpuRect bgsize, cBitmap *bgbmp) { sDvbSpuRect size; @@ -365,21 +349,15 @@ sDvbSpuRect hlsize; hlsize.x1 = hlpsize.x1; - hlsize.y1 = ScaleYcoord(hlpsize.y1); + hlsize.y1 = hlpsize.y1; hlsize.x2 = hlpsize.x2; - hlsize.y2 = ScaleYcoord(hlpsize.y2); + hlsize.y2 = hlpsize.y2; if (highlight) fg = spubmp->getBitmap(hlpDescr, palette, hlsize); if (spubmp->getMinSize(palDescr, bgsize)) { bg = spubmp->getBitmap(palDescr, palette, bgsize); - if (scaleMode == eSpuLetterBox) { - // the coordinates have to be modified for letterbox - int y1 = ScaleYres(bgsize.y1) + bgsize.height(); - bgsize.y2 = y1 + bgsize.height(); - bgsize.y1 = y1; - } } sDvbSpuRect areaSize = CalcAreaSize(hlsize, fg, bgsize, bg); diff -bur vdr-1.3.23_orig/dvbspu.h vdr-1.3.23/dvbspu.h --- vdr-1.3.23_orig/dvbspu.h 2005-04-03 18:19:40.000000000 +0200 +++ vdr-1.3.23/dvbspu.h 2005-04-09 01:27:33.000000000 +0200 @@ -129,8 +129,6 @@ return ((spu[0] << 8) | spu[1]); }; - int ScaleYcoord(int value); - int ScaleYres(int value); sDvbSpuRect CalcAreaSize(sDvbSpuRect fgsize, cBitmap *fgbmp, sDvbSpuRect bgsize, cBitmap *bgbmp); public: vdr-plugin-dvd-0.3.7/patches/vdr-xine-0.3.4-withSpu_02.diff000066400000000000000000000051241415711736600230170ustar00rootroot00000000000000diff -Nur nope/xine-0.3.4/Makefile xine-0.3.4jau02/Makefile --- nope/xine-0.3.4/Makefile 2004-05-28 00:06:43.000000000 +0200 +++ xine-0.3.4jau02/Makefile 2004-05-28 03:05:17.867268840 +0200 @@ -33,8 +33,9 @@ FIFO_DIR = /tmp/vdr-xine #DATA_DIR = /usr/local/share/vdr-xine -DATA_DIR = ./PLUGINS/src/xine/data +#DATA_DIR = ./PLUGINS/src/xine/data #DATA_DIR = /soft/vdr-1.3.8/share/vdr/xine +DATA_DIR = /video/plugins/xine/data ### The version number of VDR (taken from VDR's "config.h"): diff -Nur nope/xine-0.3.4/xineDevice.c xine-0.3.4jau02/xineDevice.c --- nope/xine-0.3.4/xineDevice.c 2004-05-27 23:27:49.000000000 +0200 +++ xine-0.3.4jau02/xineDevice.c 2004-06-08 18:33:40.961419504 +0200 @@ -17,6 +17,15 @@ return true; } + cSpuDecoder *cXineDevice::GetSpuDecoder(void) + { + if (!spuDecoder && IsPrimaryDevice()) + spuDecoder = new cDvbSpuDecoder(); + //::fprintf(stderr, "XineDevice::GetSpuDecoder: 0x%X prim:=%d\n", + // spuDecoder, IsPrimaryDevice()); + return spuDecoder; + } + bool cXineDevice::CanReplay(void) const { return true; @@ -214,7 +223,10 @@ muted = true; } +/** #define VERBOSE_RETURN(x) do{ fprintf(stderr, "FIXME: %s:%d\n", __FILE__, __LINE__); return x; } while (0) + */ +#define VERBOSE_RETURN(x) do{ return x; } while (0) static bool getPTS(const unsigned char *buf0, int len0, int64_t &pts) { @@ -787,6 +799,13 @@ cOsd *cXineDevice::NewOsd(int x, int y) #endif { + if(cOsd::IsOpen()) + { + // who owns the OSD ??? + ::fprintf(stderr, "cXineDevice::NewOsd will fail, allready opened .. (m_currentOsd=%d)\n", + m_currentOsd!=NULL); + } + m_currentOsd = new cXineOsd(*this, x, y); return m_currentOsd; @@ -846,6 +865,7 @@ , m_xineLib(settings, remote) { m_xineLib.SetEventSink(this); + spuDecoder = NULL; } cXineDevice::~cXineDevice() diff -Nur nope/xine-0.3.4/xineDevice.h xine-0.3.4jau02/xineDevice.h --- nope/xine-0.3.4/xineDevice.h 2004-05-20 19:53:17.000000000 +0200 +++ xine-0.3.4jau02/xineDevice.h 2004-05-28 03:03:16.613702184 +0200 @@ -5,6 +5,7 @@ #include +#include #include "xineLib.h" @@ -20,10 +21,12 @@ const cXineSettings &m_settings; cXineOsd *m_currentOsd; + cDvbSpuDecoder *spuDecoder; void playTrickVideo(const uchar *Data, int Length); virtual bool HasDecoder(void) const; + virtual cSpuDecoder *GetSpuDecoder(void); virtual bool CanReplay(void) const; virtual bool SetPlayMode(ePlayMode PlayMode); virtual void TrickSpeed(int Speed); vdr-plugin-dvd-0.3.7/player-dvd.c000066400000000000000000003062021415711736600166140ustar00rootroot00000000000000/* * DVD Player plugin for VDR * * Copyright (C) 2001.2002 Andreas Schultz * * This code is distributed under the terms and conditions of the * GNU GENERAL PUBLIC LICENSE. See the file COPYING for details. * */ // #define IFRAMEWRITE #ifndef DEBUG #ifndef NDEBUG #define NDEBUG #endif #endif #include #include #include #include #include // for VideoDirectory variable #include #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "common-dvd.h" #include "i18n.h" #include "dvddev.h" #include "setup-dvd.h" #include "tools-dvd.h" #include "player-dvd.h" #include "control-dvd.h" #include "dvd.h" /** * this was "weak"'s solution of a forced * SPU only stream choice, * which does _not_ work .. * * Problem: * - forcedDisplay | menu ctrseq within the SPU, * means kinda "just do it" * - special SPU channels, which only shows up * e.g. if a klingon speaks klingon, * are handled by a special SPU channel id, * which dvdnav will choose for you automatic, * and if your appropriate language is set * as the default language ! #define FORCED_SUBS_ONLY_SEMANTICS * * - we handle the forcedDisplay (outta a menu space) * - we take care now of all SPU channels [0x00 .. 0x1F] * - ... */ // #define NO_USLEEP #ifdef NO_USLEEP #define USLEEP(a) #else #define USLEEP(a) usleep((a)) #endif #if defined( DEBUG ) #warning using verbose DEBUG mode /** #define DVDDEBUG #undef DEBUGDVD #define DEBUGDVD(format, args...) printf (format, ## args) #define CTRLDEBUG #undef DEBUG_CONTROL #define DEBUG_CONTROL(format, args...) printf (format, ## args); fflush(NULL) #define NAVDEBUG #undef DEBUG_NAV #define DEBUG_NAV(format, args...) printf (format, ## args); fflush(NULL) ** ** #define NAV0DEBUG #undef DEBUG_NAV0 #define DEBUG_NAV0(format, args...) printf (format, ## args); fflush(NULL) ** ** ** #define SUBPDECDEBUG #undef DEBUG_SUBP_DEC #define DEBUG_SUBP_DEC(format, args...) printf (format, ## args); fflush(NULL) ** #define SUBPDEBUG #undef DEBUG_SUBP_ID #define DEBUG_SUBP_ID(format, args...) printf (format, ## args); fflush(NULL) #define IFRAMEDEBUG #undef DEBUG_IFRAME #define DEBUG_IFRAME(format, args...) printf (format, ## args); fflush(NULL) #define IFRAMEDEBUG2 #undef DEBUG_IFRAME2 #define DEBUG_IFRAME2(format, args...) printf (format, ## args); fflush(NULL) #define PTSDEBUG #undef DEBUG_PTS #define DEBUG_PTS(format, args...) printf (format, ## args); fflush(NULL) #define AUDIOIDDEBUG #undef DEBUG_AUDIO_ID #define DEBUG_AUDIO_ID(format, args...) printf (format, ## args); fflush(NULL) #define AUDIOPLAYDEBUG #undef DEBUG_AUDIO_PLAY #define DEBUG_AUDIO_PLAY(format, args...) printf (format, ## args); fflush(NULL) #define AUDIOPLAYDEBUG2 #undef DEBUG_AUDIO_PLAY2 #define DEBUG_AUDIO_PLAY2(format, args...) printf (format, ## args); fflush(NULL) */ #endif // --- static stuff ------------------------------------------------------ #if 1 #ifdef POLLTIMEOUTS_BEFORE_DEVICECLEAR // polltimeout of 3 seems to be enough for a softdevice .. #undef POLLTIMEOUTS_BEFORE_DEVICECLEAR #endif #endif #ifndef POLLTIMEOUTS_BEFORE_DEVICECLEAR #define POLLTIMEOUTS_BEFORE_DEVICECLEAR 6 #else #warning using patched POLLTIMEOUTS_BEFORE_DEVICECLEAR #endif #define OsdInUse() ((controller!=NULL)?controller->OsdVisible(this):false) #define TakeOsd() ((controller!=NULL)?controller->TakeOsd((void *)this):false) #ifdef CTRLDEBUG static void printCellInfo( dvdnav_cell_change_event_t & lastCellEventInfo, int64_t pgcTotalTicks, int64_t pgcTicksPerBlock ) { int cell_length_s = (int)(lastCellEventInfo.cell_length / 90000L) ; int pg_length_s = (int)(lastCellEventInfo.pg_length / 90000L) ; int pgc_length_s = (int)(lastCellEventInfo.pgc_length / 90000L) ; int cell_start_s = (int)(lastCellEventInfo.cell_start / 90000L) ; int pg_start_s = (int)(lastCellEventInfo.pg_start / 90000L) ; printf("cellN %ld, pgN=%d, cell_length=%ld %d, pg_length=%ld %d, pgc_length=%ld %d, cell_start %ld %d, pg_start %ld %d, ticksPerBlock=%ld, secPerBlock=%ld\n", (long)lastCellEventInfo.cellN , lastCellEventInfo.pgN , (long)lastCellEventInfo.cell_length , cell_length_s, (long)lastCellEventInfo.pg_length , pg_length_s, (long)lastCellEventInfo.pgc_length , pgc_length_s, (long)lastCellEventInfo.cell_start , cell_start_s, (long)lastCellEventInfo.pg_start , pg_start_s, (long)pgcTicksPerBlock, (long)(pgcTicksPerBlock/90000L) ); } #endif const char *cDvdPlayer::PTSTicksToHMSm(int64_t ticks, bool WithMS) { static char buffer[200]; int ms = (int)(ticks / 90L) % 100; int s = (int)(ticks / 90000L); int m = s / 60 % 60; int h = s / 3600; s %= 60; snprintf(buffer, sizeof(buffer), WithMS ? "%d:%02d:%02d.%02d" : "%d:%02d:%02d", h, m, s, ms); return buffer; } // --- cIframeAssembler ------------------------------------------------------ class cIframeAssembler { private: int head; int size; unsigned char *buf; cMutex mutex; void Lock(void) { mutex.Lock(); } void Unlock(void) { mutex.Unlock(); } public: cIframeAssembler(int Size); virtual ~cIframeAssembler(void); int Available(void) {return head;} void Clear(void); unsigned char *Get(int &Lenth); void Put(unsigned char *Data, int Length); }; cIframeAssembler::cIframeAssembler(int Size) { size = Size; head = 0; buf = MALLOC(unsigned char, Size); } cIframeAssembler::~cIframeAssembler(void) { free(buf); } void cIframeAssembler::Clear(void) { Lock(); head = 0; Unlock(); } unsigned char *cIframeAssembler::Get(int &Length) { Length = head; return buf; } void cIframeAssembler::Put(unsigned char *Data, int Length) { Lock(); if (head + Length < size) { memcpy(buf + head, Data, Length); head += Length; } else esyslog("ERROR: dvd-plugin iframeassembler full %d", head + Length); Unlock(); } // --- cResumeEntry ------------------------------------------------------------ // borrowed from the mplayer plugin code and adapted to the dvd resume requirements class cResumeEntry : public cListObject { public: char *key; int title; int chapter; int64_t second; // cResumeEntry(void); ~cResumeEntry(); }; cResumeEntry::cResumeEntry(void) { key=0; } cResumeEntry::~cResumeEntry() { free(key); } // --- cDVDPlayerResume ---------------------------------------------------------- // store resume database to this file ... #define RESUME_FILE "dvdplayer.resume" // ... in this directory (default: /video) #ifndef RESUMEDIR #if APIVERSNUM > 20101 #define RESUMEDIR cVideoDirectory::Name() #else #define RESUMEDIR VideoDirectory #endif #endif // borrowed from the mplayer plugin code and adapted to the dvd resume requirements class cDVDPlayerResume : public cList { private: char* resfile; // the full pathname of resume file bool modified; // flag to indicate that memory database was modified and needs to be saved /** * LoadResume(): * reads in the resume database file from resfile. */ void LoadResume(); /** * SaveResume(): * saves the resume database to the file resfile. * returns true on successful save. */ bool SaveResume(void); /** * search the (loaded) resume database for the given key. * returns the cResumeEntry* if the key was found * or NULL if no resume entry was found for the given key. */ cResumeEntry *FindResume(const char* key); public: cDVDPlayerResume(void); ~cDVDPlayerResume(); /** * SetResume(): * set the given resume values for the given key into the resume database. * the resume database is loaded from file if not yet loaded. */ void SetResume(const char* key, int title, int chapter, int64_t second); /** * GetResume(): * tries looking up the given key into the resume database. * the resume database is loaded from file if not yet loaded. * returns true if resume data could be found. In this case * the givven arguments are filled with the resume data. Otherwise * the arguments are not modified! */ bool GetResume(const char* key, int& title, int& chapter, int64_t& second); }; cDVDPlayerResume::cDVDPlayerResume(void) { // initialize the resume filename string. asprintf(&resfile, "%s/%s", RESUMEDIR, RESUME_FILE); } cDVDPlayerResume::~cDVDPlayerResume() { // save resume data to disc before self-destruction. SaveResume(); // free the resume filename string, allocated in C'tor by asprintf free(resfile); } void cDVDPlayerResume::SetResume(const char* key, int title, int chapter, int64_t second) { // (re)load resume data from file to be actual LoadResume(); cResumeEntry* re = FindResume(key); if (re) { // found a resume entry, so we can update it. DEBUGDVD("resume: setting resume %d:%d:%lld (update)", title, chapter, second); } else { // no resume entry found yet, creating a new one re = new cResumeEntry; re->key = strdup(key); Add(re); DEBUGDVD("resume: setting resume %d:%d:%lld (new)", title, chapter, second); } // set the new resume data for the found/created entry re->title = title; re->chapter = chapter; re->second = second; // and mark memory database as modified to be saved. modified = true; // save it now (sync!) SaveResume(); } bool cDVDPlayerResume::GetResume(const char* key, int& title, int& chapter, int64_t& second) { // (re)load the resume file to have actual values LoadResume(); cResumeEntry* re = FindResume(key); if (re) { // found a resume entry, copy values title = re->title; chapter = re->chapter; second = re->second; // indicate successful search return true; } // no resume entry found in database return false; } void cDVDPlayerResume::LoadResume() { // we will load the file for sure and add all entries, clear all old entries. Clear(); // no entries == no modifications modified = false; DEBUGDVD("resume: resume file is \"%s\"\n",resfile); FILE *f = fopen(resfile,"r"); if (f) { DEBUGDVD("resume: successfully opened resume file\n"); char line[768]; // read file line by line while(fgets(line,sizeof(line),f)) { char key[512]; int t, c; int64_t s; // parse line as "title:chapter:second:key" if(sscanf(line,"%d:%d:%lld:%511[^\n]",&t,&c,&s,key) == 4) { // successful parse, save in resume entry cResumeEntry *re = new cResumeEntry; re->key = strdup(key); re->title = t; re->chapter = c; re->second = s; // and add it to memory database Add(re); } } // don't forget to close what you have opened! fclose(f); } // unsuccessful open leads to empty database as the file does not exists } bool cDVDPlayerResume::SaveResume(void) { if(modified) { // modification indicated, save the database to the resume file DEBUGDVD("resume: saving resume file\n"); cSafeFile f(resfile); if(f.Open()) { // forall resume entries in the memory database for (cResumeEntry *re=First(); re; re=Next(re)) { // save the as one line in the format "title:chapter:second:key" fprintf(f, "%d:%d:%lld:%s\n", re->title, re->chapter, re->second, re->key); } // don't forget to close what you have opened! f.Close(); // signal successful save return true; } else { DEBUGDVD("resume: failed to save resume file\n"); // saving did not succeed!!!! return false; } } else { // no modifications -> successful "save" :-) return true; } } cResumeEntry *cDVDPlayerResume::FindResume(const char* key) { DEBUGDVD("resume: searching resume position for \"%s\"\n", key); // iterate over all entries in the memory database for(cResumeEntry *re=First(); re; re=Next(re)) { if (!strcasecmp(re->key, key)) { // return the entry iff the keys match DEBUGDVD("resume: found resume position %d:%d:%lld\n",re->title, re->chapter, re->second); return re; } } DEBUGDVD("resume: no resume position found\n"); return NULL; } // --- cDvdPlayer ------------------------------------------------------------ //XXX+ also used in recorder.c - find a better place??? // The size of the array used to buffer video data: // (must be larger than MINVIDEODATA - see remux.h) #define VIDEOBUFSIZE MEGABYTE(1) // The number of frames to back up when resuming an interrupted replay session: #define RESUMEBACKUP (10 * FRAMESPERSEC) #define MAX_VIDEO_SLOWMOTION 63 // max. arg to pass to VIDEO_SLOWMOTION // TODO is this value correct? #define NORMAL_SPEED 10 // the index of the '1' entry in the following array #define MAX_SPEEDS 3 // the offset of the maximum speed from normal speed in either direction, // for the dvbplayer #define MAX_MAX_SPEEDS MAX_SPEEDS*MAX_SPEEDS // the super speed maximum #define SPEED_MULT 12 // the speed multiplier int cDvdPlayer::Speeds[] = { 0, 0, 0, 0, 0, 0, 0, -2, -4, -8, 1, 2, 4, 12, 0, 0, 0, 0, 0, 0, 0 }; bool cDvdPlayer::BitStreamOutActive = false; bool cDvdPlayer::HasBitStreamOut = false; bool cDvdPlayer::HasSoftDeviceOut = false; bool cDvdPlayer::SoftDeviceOutActive = false; bool cDvdPlayer::HasReelbox = false; const int cDvdPlayer::MaxAudioTracks = 0x20; const int cDvdPlayer::AudioTrackMask = 0x1F; const int cDvdPlayer::AC3AudioTrackMask = 0x07; const int cDvdPlayer::MaxSubpStreams = 0x20; const int cDvdPlayer::SubpStreamMask = 0x1F; const char * cDvdPlayer::dummy_title = "DVD Title"; const char * cDvdPlayer::dummy_n_a = "n.a."; cDvdPlayer::cDvdPlayer(void): cThread("dvd-plugin"), a52dec(*this) { DEBUGDVD("cDvdPlayer::cDvdPlayer(void)\n"); ringBuffer=new cRingBufferFrame(VIDEOBUFSIZE); rframe=NULL; pframe=NULL; controller = NULL; active = true; running = false; playMode = pmPlay; playDir = pdForward; trickSpeed = NORMAL_SPEED; stillTimer = 0; currButtonN = -1; nav = 0; iframeAssembler = new cIframeAssembler(KILOBYTE(CIF_MAXSIZE)); IframeCnt = 0; event_buf = new uint8_t[4096]; current_pci = 0; prev_e_ptm = 0; ptm_offs = 0; DEBUG_SUBP_ID("SPU showSubs=%d\n", DVDSetup.ShowSubtitles); skipPlayVideo=false; fastWindFactor=1; // resume resume = new cDVDPlayerResume; clearSeenSubpStream(); clearSeenAudioTrack(); currentNavSubpStream = -1; currentNavAudioTrackType = -1; lastNavAudioTrackType = -1; pgcCurrentBlockNum=1; pgcTotalBlockNum=1; pgcTotalTicks=1; pgcTicksPerBlock=1; isInMenuDomain = false; isInFeature = false; dvd_aspect=0; dvd_scaleperm=0; SPUdecoder = NULL; a52dec.setSyncMode(A52decoder::ptsGenerate); titleinfo_str=0; title_str=0; aspect_str = NULL; SetTitleInfoString(); SetTitleString(); SetAspectString(); memset(&lastCellEventInfo, 0, sizeof(dvdnav_cell_change_event_t)); } cDvdPlayer::~cDvdPlayer() { DEBUGDVD("destructor cDvdPlayer::~cDvdPlayer()\n"); Detach(); Save(); delete []event_buf; delete iframeAssembler; delete ringBuffer; if(titleinfo_str) free(titleinfo_str); if(title_str) free(title_str); if(aspect_str) free(aspect_str); delete resume; } void cDvdPlayer::setController (cDvdPlayerControl *ctrl ) { controller = ctrl; } bool cDvdPlayer::IsDvdNavigationForced() const { return (controller?controller->IsDvdNavigationForced():false); } void cDvdPlayer::TrickSpeed(int Increment) { int nts = trickSpeed + Increment; cntVidBlocksPlayed=0; cntAudBlocksPlayed=0; if (nts>0 && nts-NORMAL_SPEED <= MAX_SPEEDS && Speeds[nts] == 1) { fastWindFactor = 1; trickSpeed = nts; if (playMode == pmFast) Play(); else Pause(); } else if (nts>0 && nts-NORMAL_SPEED <= MAX_SPEEDS && Speeds[nts]) { fastWindFactor = 1; if (playDir == pdBackward && DVDSetup.ReadAHead>0) dvdnav_set_readahead_flag(nav, 0); trickSpeed = nts; int Mult = ( playMode == pmSlow ) ? 1 : SPEED_MULT; int sp = (Speeds[nts] > 0) ? Mult / Speeds[nts] : -Speeds[nts] * Mult; if (sp > MAX_VIDEO_SLOWMOTION) sp = MAX_VIDEO_SLOWMOTION; if (playDir == pdBackward) { fastWindFactor = ( playMode == pmSlow ) ? trickSpeed - NORMAL_SPEED : trickSpeed - NORMAL_SPEED + 1 ; if (playMode == pmSlow) sp=2; } #if VDRVERSNUM < 20103 DeviceTrickSpeed(sp); #else DeviceTrickSpeed(sp,playDir == pdForward); #endif } else if ( nts>0 && nts-NORMAL_SPEED <= MAX_MAX_SPEEDS ) { fastWindFactor = 1; trickSpeed = nts; if ( playDir == pdBackward ) if ( playMode == pmSlow ) fastWindFactor = trickSpeed - NORMAL_SPEED ; else fastWindFactor = ( trickSpeed - NORMAL_SPEED - MAX_SPEEDS + 1 ) * 2 ; else if ( playDir == pdForward && playMode == pmFast ) fastWindFactor = ( trickSpeed - NORMAL_SPEED - MAX_SPEEDS + 1 ) * 2 ; } DEBUG_CONTROL("dvd TRICKSPEED: %d (%d), fastWindFactor=%d fwd=%d, slow=%d, fast=%d\n", trickSpeed, Increment, fastWindFactor, playDir == pdForward, playMode == pmSlow, playMode == pmFast); } void cDvdPlayer::DeviceReset(void) { DEBUG_CONTROL("DeviceReset: Clear & Play\n"); cntVidBlocksPlayed=0; cntAudBlocksPlayed=0; cPlayer::DeviceClear(); cPlayer::DevicePlay(); } void cDvdPlayer::DeviceClear(void) { DEBUG_CONTROL("DeviceClear\n"); if (IsAttached()) PlayPes(NULL, 0); cPlayer::DeviceClear(); } void cDvdPlayer::DevicePlay(void) { DEBUG_CONTROL("DevicePlay\n"); cPlayer::DevicePlay(); } void cDvdPlayer::DrawSPU() { if (SPUdecoder && !SPUdecoder->IsVisible() && TakeOsd()) { SPUdecoder->Draw(); } } void cDvdPlayer::HideSPU() { if (SPUdecoder) { SPUdecoder->Hide(); } } void cDvdPlayer::EmptySPU() { if (SPUdecoder) { ClearButtonHighlight(); SPUdecoder->Empty(); } } void cDvdPlayer::Empty(bool emptyDeviceToo) { DEBUG_CONTROL("dvd .. Empty ...\n"); LOCK_THREAD; if( IframeCnt < 0 && cntVidBlocksPlayed > 0 ) { DEBUG_IFRAME("I-Frame: Empty: Iframe used, VidBlocksPlayed -> emptyDevice\n"); emptyDeviceToo=true; } DEBUG_CONTROL("dvd .. Empty IframeCnt=%d, emptyDeviceToo=%d!\n", IframeCnt, emptyDeviceToo); if (SPUdecoder) { DEBUG_NAV("DVD NAV SPU clear & empty %s:%d\n", __FILE__, __LINE__); EmptySPU(); } currButtonN = -1; a52dec.clear(); lastFrameType = 0xff; VideoPts = 0xFFFFFFFF; stcPTS = 0xFFFFFFFF; stcPTSAudio = 0xFFFFFFFF; stcPTSLastAudio = 0xFFFFFFFF; pktpts = 0xFFFFFFFF; pktptsAudio = 0xFFFFFFFF; pktptsLastAudio = 0xFFFFFFFF; prev_e_ptm = 0; ptm_offs = 0; DELETENULL(rframe); pframe=NULL; ringBuffer->Clear(); cntVidBlocksPlayed=0; cntAudBlocksPlayed=0; stillTimer = 0; stillFrame = 0; IframeCnt = 0; iframeAssembler->Clear(); pictureNumber=0; pictureFlip=false; skipPlayVideo=false; if(emptyDeviceToo) { DeviceClear(); } } void cDvdPlayer::StillSkip() { DEBUGDVD("cDvdPlayer::StillSkip()\n"); if(stillTimer!=0) { stillTimer = 0; if(nav!=NULL) { dvdnav_still_skip(nav); } } } #ifdef DVDDEBUG static char *dvd_ev[] = { "BLOCK_OK", "NOP", "STILL_FRAME", "SPU_STREAM_CHANGE", "AUDIO_STREAM_CHANGE", "VTS_CHANGE", "CELL_CHANGE", "NAV_PACKET", "STOP", "HIGHLIGHT", "SPU_CLUT_CHANGE", "SEEK_DONE", // remove in newer lib versions "HOP_CHANNEL", "WAIT", // since 0.1.7 "TRICK_MODE_CHANGE" }; #endif #define CELL_STILL 0x02 #define NAV_STILL 0x04 /** * timer funktions with ticks as its base * * 90000 ticks are 1 second, acording to MPEG ! * * just to make things clear ;-) * * 1000 ms / s, 1000000 us / s * * 90000/1 t/s = 90/1 t/ms = 9/100 t/us * * 1/90000 s/t = 1/90 ms/t = 100/9 us/t */ uint64_t cDvdPlayer::time_ticks(void) { static time_t t0 = 0; struct timeval t; if (gettimeofday(&t, NULL) == 0) { if (t0 == 0) t0 = t.tv_sec; // this avoids an overflow (we only work with deltas) return (uint64_t)(t.tv_sec - t0) * 90000U + (uint64_t)( t.tv_usec * 9U ) / 100U ; } return 0; } uint64_t cDvdPlayer::delay_ticks(uint64_t ticks) { #ifndef NO_USLEEP uint64_t t0 = time_ticks(); USLEEP(1000); // at least one guaranteed sleep of 1ms !! uint64_t done = time_ticks() - t0 ; while ( ticks > done ) { // USLEEP resol. is about 19 ms if(ticks-done>19U*90U) USLEEP( (ticks-done)*100U/9U - 19000U ); done = time_ticks() - t0 ; } return time_ticks() - t0 ; #else return ticks; #endif } char* cDvdPlayer::GetDVDResumeKey() const { // first we fetch the total number of titles of the current dvd int totalTitles; if (dvdnav_get_number_of_titles(nav, &totalTitles)) { // then we sum up the numbers of chapters for each title int totalChapters = 0; for (int t = 1; t <= totalTitles; t++) { int curChapters; dvdnav_get_number_of_parts(nav, t, &curChapters); totalChapters += curChapters; DEBUGDVD("resume: cDvdPlayer::Action() Title %d has %d chapters.\n", t, curChapters); } DEBUGDVD("resume: cDvdPlayer::Action() Titles: %d with %d chapters all together, Title: \"%s\"\n", totalTitles, totalChapters, title_str); // finally the key is build as "DVDName_TotalTitles_OverallChapters" char* key; asprintf(&key, "%s_%d_%d", title_str, totalTitles, totalChapters); // note: this is not completly unique. Maybe some other informations are more suitable, like: // - the "serial number" of the dvd as displayed in the libdvdnav debug output, but: // it is not available through the current libdvdnav api // - the total bytes of the dvd (quiet unique!!!), but: // also not available through the libdvdnav api and no idea how to get it for a media not mounted. // - any other ideas??? return key; } else { // if we cannot fetch the total number of titles of the current disc, there must be something wrong! // Who needs a key for resuming then? return NULL; } } void cDvdPlayer::SaveResume() { // make sure resume database is allocated (might be a possibility to completly disable resuming!) if (resume) { // fetch the current title and chapter number via libdvdnav api int currentTitle, currentChapter; if (dvdnav_current_title_info(nav, ¤tTitle, ¤tChapter) && (0 != currentTitle)) { // fetch current time position through own class api int64_t currentSec, totalSec; GetPositionInSec(currentSec, totalSec); // compute the resume key for the current dvd char* key = GetDVDResumeKey(); if (key) { // store computed/fetched resume data in database DEBUGDVD("resume->SetResume(\"%s\", %d, %d, %lld)\n", key, currentTitle, currentChapter, currentSec); resume->SetResume(key, currentTitle, currentChapter, currentSec); // free the key string memory allocated by GetDVDResumeKey() free(key); } else { DEBUGDVD("resume: ERROR computing resume key for this dvd!\n"); } } else { // in a menu title and chapter seams to be always 0 -> no way to resume there! DEBUGDVD("resume: ERROR fetching current title and chapter (maybe in menus?).\n"); } } } bool cDvdPlayer::LoadResume(int& title, int& chapter, int64_t& second) { // helper variable for the return value bool retval = false; // make sure resume database is allocated (might be a possibility to completly disable resuming!) if(resume) { // compute the resume key for the current dvd char* key = GetDVDResumeKey(); if (key) { DEBUGDVD("resume->GetResume(\"%s\", ...): ", key); // try loading the resume data for the computed key into the given arguments if (resume->GetResume(key, title, chapter, second)) { DEBUGDVD("%d:%d:%lld\n", title, chapter, second); // continuing at the very same position might be inappropriate (vdr's recordings also rewind some seconds) int ResumeRewind = 30; // rewind 30s if possible // note: I used a variable here to show up, that this value might be made // possible to configure (in the setup dialog). Doing so myself was // not yet nesseccary and is so left to the plugin maintainers. // make sure we do not rewind before the beginning if (second > ResumeRewind) { second -= ResumeRewind; } retval = true; } else { DEBUGDVD("\n"); retval = false; } // free the key string memory allocated by GetDVDResumeKey() free(key); } else { DEBUGDVD("resume: ERROR computing resume key for this dvd.\n"); } } return retval; } void cDvdPlayer::Action(void) { memset(event_buf, 0, sizeof(uint8_t)*4096); unsigned char *write_blk = NULL; int blk_size = 0; BitStreamOutActive = false; HasBitStreamOut = (cPluginManager::GetPlugin("bitstreamout") != NULL); HasReelbox = (cPluginManager::GetPlugin("reelbox") != NULL); SoftDeviceOutActive = false; HasSoftDeviceOut = (cPluginManager::GetPlugin("xine") != NULL); cSetupLine *slBitStreamOutActive = NULL; if(HasBitStreamOut) { slBitStreamOutActive = cPluginDvd::GetSetupLine("active", "bitstreamout"); if(slBitStreamOutActive!=NULL) BitStreamOutActive = atoi ( slBitStreamOutActive->Value() ) ? true: false ; } dsyslog("dvd-plugin: BitStreamOutActive=%d, HasBitStreamOut=%d (%d)", BitStreamOutActive, HasBitStreamOut, slBitStreamOutActive!=NULL); if(HasSoftDeviceOut) { SoftDeviceOutActive = true; } dsyslog("dvd-plugin: SoftDeviceOutActive=%d, HasSoftDeviceOut=%d", SoftDeviceOutActive, HasSoftDeviceOut); if (dvdnav_open(&nav, const_cast(cDVD::getDVD()->DeviceName())) != DVDNAV_STATUS_OK) { Skins.QueueMessage(mtError, tr("Error.DVD$Error opening DVD!")); esyslog("ERROR: dvd-plugin cannot open dvdnav device %s -> input thread ended (pid=%d) !", const_cast(cDVD::getDVD()->DeviceName()), getpid()); active = running = false; nav=NULL; fflush(NULL); return; } dvdnav_set_readahead_flag(nav, DVDSetup.ReadAHead); if (DVDSetup.PlayerRCE != 0) dvdnav_set_region_mask(nav, 1 << (DVDSetup.PlayerRCE - 1)); else dvdnav_set_region_mask(nav, 0xffff); dvdnav_menu_language_select(nav, const_cast(ISO639code[DVDSetup.MenuLanguage])); dvdnav_audio_language_select(nav, const_cast(ISO639code[DVDSetup.AudioLanguage])); dvdnav_spu_language_select(nav, const_cast(ISO639code[DVDSetup.SpuLanguage])); DEBUGDVD("Default-Langs: menu=%s, audio=%s, spu=%s\n", const_cast(ISO639code[DVDSetup.MenuLanguage]), const_cast(ISO639code[DVDSetup.AudioLanguage]), const_cast(ISO639code[DVDSetup.SpuLanguage])); if (IsAttached()) { SPUdecoder = cDevice::PrimaryDevice()->GetSpuDecoder(); DEBUG_NAV("DVD NAV SPU clear & empty %s:%d\n", __FILE__, __LINE__); EmptySPU(); } int slomoloop=0; uint64_t sleept = 0; // in ticks ! uint64_t sleept_done = 0; // in ticks ! bool trickMode = false; bool noAudio = false; int PollTimeouts = 0; int playedPacket = pktNone; uint32_t cntVidBlocksSkipped = 0; Empty(false); // IframeCnt = -1; // mark that we have to reset the device, before 1st PlayVideo .. running = true; eFrameType frameType = ftUnknown; bool firstClear = true; // we need to know the very first VTS change to hook inthe resume call bool first_vts_change = true; // we cannot directly resume to the exact time, so we hook on the next cell change when resuming bool next_cell_change = false; // and seek the the exact time stored here int64_t resSecond = 0; while(running && nav) { if (!pframe) { pframe = ringBuffer->Get(); if (pframe) { write_blk=pframe->Data(); blk_size=pframe->Count(); frameType=pframe->Type(); } } /* // clip PTS values .. if ( pktptsAudio= stcPTSAudio-stcPTSLastAudio+90 ) { sleept_trial = (pktptsAudio-pktptsLastAudio) - (stcPTSAudio-stcPTSLastAudio) ; if(sleept_trial>sleept) sleept=sleept_trial; } } */ /** DEBUG_CONTROL("dvd: menu=%d, v:%u, a:%u, p:%d, stc:%8ums, blk_size=%3d, skipPlayV=%d, IframeCnt=%d, stillTimer=%8ums\n", IsInMenuDomain(), cntVidBlocksPlayed, cntAudBlocksPlayed, playedPacket, (unsigned int)(stcPTS/90U), blk_size, skipPlayVideo, IframeCnt, stillTimer/90U); */ sleept_done = 0; if (sleept) { if ( sleept/90U > 1000 ) DEBUG_PTS("\n***** WARNING >=1000ms sleep %llums\n", sleept/90U); sleept_done = delay_ticks(sleept); DEBUG_PTS2("dvd loop sleep=%5ut(%3ums)/%5ut(%3ums), blk_size=%3d, skipPlayV=%d, AudioBlock=%d IframeCnt=%d stillTimer=%u\n", (unsigned int)sleept, (unsigned int)sleept/90U, (unsigned int)sleept_done, (unsigned int)sleept_done/90U, blk_size, skipPlayVideo, playedPacket==pktAudio, IframeCnt, stillTimer/90U); } sleept = 0; if (playMode == pmPause || playMode == pmStill) { cCondWait::SleepMs(10); continue; } cPoller Poller; if (!DevicePoll(Poller, 100)) { PollTimeouts++; if (PollTimeouts == POLLTIMEOUTS_BEFORE_DEVICECLEAR) { dsyslog("dvd-plugin: clearing device because of consecutive poll timeouts %d", POLLTIMEOUTS_BEFORE_DEVICECLEAR); DEBUG_CONTROL("clearing device because of consecutive poll timeouts %d\n", POLLTIMEOUTS_BEFORE_DEVICECLEAR); DeviceReset(); PollTimeouts = 0; } continue; } PollTimeouts = 0; LOCK_THREAD; trickMode = playMode == pmFast || (playMode == pmSlow && playDir == pdBackward) ; if (pframe) { int res = blk_size; if( !skipPlayVideo ) { if (firstClear && (frameType == ftDolby || frameType == ftAudio) && IframeCnt == 0) { DeviceReset(); firstClear = false; } if (IframeCnt < 0 && frameType == ftVideo) { // we played an IFrame with DeviceStillPicture, or else -> reset ! DEBUG_CONTROL("clearing device because of IframeCnt < 0 && VideoFrame\n"); IframeCnt = 0; while (!DeviceFlush(100)); if (!firstClear) DeviceReset(); } /** !! Skip Stillpicture **/ res = (IframeCnt > 0 && frameType == ftVideo) ? blk_size : PlayPes(write_blk, blk_size); if (trickMode) { DEBUG_CONTROL("PLAYED : todo=%d, written=%d\n", blk_size, res); } } #ifdef CTRLDEBUG else if (trickMode) printf("SKIPPED : todo=%d\n", blk_size); #endif if (res < 0) { if (errno != EAGAIN && errno != EINTR) { esyslog("ERROR: dvd-plugin PlayVideo, %s (workaround activ)", strerror(errno)); DEBUG_CONTROL("PlayVideo, %s (workaround activ)\n", strerror(errno)); } DEBUG_CONTROL("PLAYED zero -> Clear/Play\n"); DeviceReset(); continue; } if (res > 0) { blk_size -= res; write_blk += res; } if (blk_size > 0) { // sleept = 5*90U; // 5ms*90t/ms } else { if ( frameType==ftVideo ) { if(!skipPlayVideo) { cntVidBlocksPlayed++; } else { cntVidBlocksSkipped++; } } else if ( frameType==ftAudio || frameType==ftDolby ) { cntAudBlocksPlayed++; } playedPacket = pktNone; frameType = ftUnknown; ringBuffer->Drop(pframe); pframe = NULL; } continue; } else { if ( playedPacket==pktAudio ) { cntAudBlocksPlayed++; } playedPacket = pktNone; frameType = ftUnknown; } if (IframeCnt > 0) { /** * reset device only if video was played, * else it would distrub audio playback in an * menu&audio only environment */ if (cntVidBlocksPlayed > 0) { DEBUG_CONTROL("clearing device because of IframeCnt > 0, vid %d, aud %d\n", cntVidBlocksPlayed, cntAudBlocksPlayed); while (!DeviceFlush(100)); DeviceReset(); } int iframeSize; unsigned char *iframe=iframeAssembler->Get(iframeSize); DEBUG_IFRAME("I-Frame: DeviceStillPicture: IframeCnt=%d->-1, iframe=%d, used=%d;\n", IframeCnt, iframe!=NULL, iframeSize); if ( iframe && iframeSize>0 ) { #ifdef IFRAMEWRITE static int ifnum = 0; static char ifname[255]; snprintf(ifname, 255, "/tmp/dvd.iframe.%3.3d.asm.pes", ifnum++); FILE *f = fopen(ifname, "wb"); fwrite(iframe, 1, iframeSize, f); fclose(f); #endif DeviceStillPicture(iframe, iframeSize); DEBUG_IFRAME("SEND; "); while (!DeviceFlush(100)); DEBUG_IFRAME("FLUSH!\n"); } iframeAssembler->Clear(); IframeCnt = -1; // mark that we played an IFrame if (blk_size <= 0 && !skipPlayVideo) sleept = 1*90U; // 1ms*90t/ms DEBUG_IFRAME("I-Frame: DeviceStillPicture: stc=%8ums vpts=%8ums sleept=%llums\n", (unsigned int)(stcPTS/90U), (unsigned int)(VideoPts/90U), sleept/90U); continue; } /** * check if we should use the very fast forward mode */ if (playDir == pdForward && playMode == pmFast && skipPlayVideo && cntVidBlocksPlayed>0 && fastWindFactor>1) { uint32_t pos, len; int64_t pgcPosTicks = 0, pgcPosTicksIncr=0; /** * skip blocks .. if pos is not at the end */ dvdnav_set_PGC_positioning_flag ( nav, 1); dvdnav_get_position ( nav, &pos, &len); pgcPosTicks = (int64_t)pos * pgcTicksPerBlock; /** * increment about fastWindFactor * 0.5 s */ pgcPosTicksIncr = (int64_t) ((fastWindFactor * 90000L)/2L) ; if( pgcPosTicks+pgcPosTicksIncr < pgcTotalTicks ) { DEBUG_CONTROL("dvd %d %4.4u/%4.4u fwd get block: %4.4ldb %10.10ldt %lds\n", playDir == pdBackward, cntVidBlocksPlayed, cntVidBlocksSkipped, (long)pos, (long)pgcPosTicks, (long)(pgcPosTicks/90000L)); DEBUG_CONTROL("dvd fwd set block: ts=%d, factor=%ds, %ldms+%ldms=%ldms, %4.4ldb+%4.4ldb=%4.4ldb, %10.10ldt+%10.10ldt=%10.10ldt\n", trickSpeed, fastWindFactor/2, (long)(pgcPosTicks/90L), (long)(pgcPosTicksIncr/90L), (long)((pgcPosTicks+pgcPosTicksIncr)/90L), (long)pos, (long)(pgcPosTicksIncr/pgcTicksPerBlock), (long)((pgcPosTicks+pgcPosTicksIncr)/pgcTicksPerBlock), (long)pgcPosTicks, (long)pgcPosTicksIncr, (long)pgcPosTicks+(long)pgcPosTicksIncr); pos = (pgcPosTicks+pgcPosTicksIncr)/pgcTicksPerBlock; if (dvdnav_sector_search( nav, pos, SEEK_SET) != DVDNAV_STATUS_OK) esyslog("ERROR: dvd-plugin dvd error dvdnav_sector_search: %s", dvdnav_err_to_string(nav)); } cntVidBlocksPlayed=0; cntVidBlocksSkipped=0; } /** * check is we should use any backward mode */ else if (playDir == pdBackward && skipPlayVideo && cntVidBlocksPlayed>0 && fastWindFactor!=1) { uint32_t pos=0, posdiff=0, len=0; int64_t pgcPosTicks = 0; if(fastWindFactor<0) { /** * special slomo handling */ if(slomoloop==0) { slomoloop= abs(fastWindFactor); cntVidBlocksPlayed++; // one more block back .. posdiff = (uint32_t)(cntVidBlocksPlayed*2) ; DEBUG_CONTROL("dvd slomo jump: d%ldb %dsl (%df)\n", (long)posdiff, slomoloop, fastWindFactor); } else { posdiff = (uint32_t)(cntVidBlocksPlayed) ; DEBUG_CONTROL("dvd slomo loop: d%ldb %dsl (%df)\n", (long)posdiff, slomoloop, fastWindFactor); slomoloop--; } } else { /** * simple rewind: * trickspeed-NORMAL_SPEED <= MAX_SPEEDS * else fast rewind * half a secound * fastWindFactor */ if ( trickSpeed-NORMAL_SPEED <= MAX_SPEEDS ) { cntVidBlocksPlayed++; // one more block back .. posdiff = cntVidBlocksPlayed*fastWindFactor ; } else { int64_t pgcPosTicksDecr=0; /** * increment about fastWindFactor * 0.5 s */ pgcPosTicksDecr = (int64_t) ((fastWindFactor * 90000L)/2L) ; posdiff = (uint32_t) (pgcPosTicksDecr / pgcTicksPerBlock); } } /** * jump back, if pos is not at the beginning */ dvdnav_set_PGC_positioning_flag ( nav, 1); if( dvdnav_get_position ( nav, &pos, &len) == DVDNAV_STATUS_OK && pos>posdiff ) { pgcPosTicks = (int64_t)pos * pgcTicksPerBlock; uint32_t forcedBlockPosition = pos-posdiff; DEBUG_CONTROL("dvd %d %4.4u/%4.4u bwd get block: %4.4ldb %10.10ldt %lds\n", playDir == pdBackward, cntVidBlocksPlayed, cntVidBlocksSkipped, (long)pos, (long)pgcPosTicks, (long)(pgcPosTicks/90000L)); DEBUG_CONTROL("dvd bwd set block: ts=%d, factor=%d, %ld-%ld=%ld, slo=%d\n", trickSpeed, fastWindFactor, (long)pos, (long)posdiff, (long)forcedBlockPosition, slomoloop); if (dvdnav_sector_search( nav, forcedBlockPosition, SEEK_SET) != DVDNAV_STATUS_OK) esyslog("ERROR: dvd-plugin dvd error dvdnav_sector_search: %s", dvdnav_err_to_string(nav)); } else { DEBUG_CONTROL("dvd %d %4.4u/%4.4u bwd get block: %4.4ldb d%4.4ldb, slo=%d\n", playDir == pdBackward, cntVidBlocksPlayed, cntVidBlocksSkipped, (long)pos, (long)posdiff, slomoloop); } cntVidBlocksPlayed=0; cntVidBlocksSkipped=0; } else if ( playMode == pmFast || playMode == pmSlow ) { uint32_t pos, len; int64_t pgcPosTicks = 0; dvdnav_set_PGC_positioning_flag ( nav, 1); dvdnav_get_position ( nav, &pos, &len); pgcPosTicks = (int64_t)pos * pgcTicksPerBlock; DEBUG_CONTROL("dvd %d %4.4u/%4.4u any get block: %4.4ldb %10.10ldt %lds, sec=%d\n", playDir == pdBackward, cntVidBlocksPlayed, cntVidBlocksSkipped, (long)pos, (long)pgcPosTicks, (long)(pgcPosTicks/90000L), (int)(pgcPosTicks/90000L)); /** * dont jump over the end .. 10s tolerance .. */ if (playDir == pdForward && pos+1 == len && pgcPosTicks>90000L*10L && pgcTicksPerBlock>0) { pgcPosTicks-=90000L*10L; if (dvdnav_sector_search( nav, pgcPosTicks/pgcTicksPerBlock, SEEK_SET) != DVDNAV_STATUS_OK ) esyslog("ERROR: dvd-plugin dvd error dvdnav_sector_search: %s", dvdnav_err_to_string(nav)); } } uint8_t *cache_ptr = event_buf; int32_t event; int32_t len; // from here on, continue is not allowed, // as it would bypass dvdnav_free_cache_block if (dvdnav_get_next_cache_block(nav, &cache_ptr, &event, &len) != DVDNAV_STATUS_OK) { Skins.QueueMessage(mtError, tr("Error.DVD$Error fetching data from DVD!")); dvdnav_reset(nav); // running = false; // break; continue; } noAudio = playMode != pmPlay ; switch (event) { case DVDNAV_BLOCK_OK: // DEBUG_NAV("%s:%d:NAV BLOCK OK\n", __FILE__, __LINE__); #if 0 //FIXME: if ( cntVidBlocksPlayed==0 && cntAudBlocksPlayed==0 ) { DEBUG_CONTROL("play device because of zero played blocks v:%u, a:%u..\n", cntVidBlocksPlayed, cntAudBlocksPlayed); DevicePlay(); } #endif UpdateBlockInfo(); // TEST playedPacket = playPacket(cache_ptr, trickMode, noAudio); break; case DVDNAV_NOP: DEBUG_NAV("%s:%d:NAV NOP\n", __FILE__, __LINE__); break; case DVDNAV_STILL_FRAME: { uint64_t currentTicks = time_ticks(); DEBUG_PTS2("%s:%d:NAV STILL FRAME (menu=%d), rem. stillTimer=%ut(%ums), currTicks=%llut(%llums)\n", __FILE__, __LINE__, IsInMenuDomain(), stillTimer, stillTimer/90, currentTicks, currentTicks/90); dvdnav_still_event_t *still = (dvdnav_still_event_t *)cache_ptr; if (stillTimer != 0) { seenVPTS(0); if (stillTimer > currentTicks) { sleept = 40*90U; // 40ms*90t/ms } else { StillSkip(); sleept = 0; DEBUG_PTS("Still time clear\n"); } DEBUG_PTS2("StillTimer->Sleep: %llut(%llums)\n", sleept, sleept/90); } else { if(still->length == 0xff) { stillTimer = INT_MAX; DEBUG_PTS("Still time (max): %ut(%ums)\n", stillTimer, stillTimer/90); } else { stillTimer = currentTicks + (uint64_t)(still->length) * 90000U; DEBUG_PTS("Still time (set): %ut(%ums)\n", stillTimer, stillTimer/90); } SendIframe( true ); } break; } case DVDNAV_WAIT: DEBUG_NAV("%s:%d:NAV WAIT\n", __FILE__, __LINE__); prev_e_ptm = 0; ptm_offs = 0; dvdnav_wait_skip(nav); break; case DVDNAV_SPU_STREAM_CHANGE: { DEBUG_NAV("%s:%d:NAV SPU STREAM CHANGE\n", __FILE__, __LINE__); dvdnav_spu_stream_change_event_t *ev = (dvdnav_spu_stream_change_event_t *)cache_ptr; DEBUG_SUBP_ID("SPU Streams: w:0x%X (%d), l:0x%X (%d), p:0x%X (%d), L:0x%X (%d), locked=%d/%d\n", ev->physical_wide, ev->physical_wide, ev->physical_letterbox, ev->physical_letterbox, ev->physical_pan_scan, ev->physical_pan_scan, ev->logical, ev->logical, currentNavSubpStreamUsrLocked, !changeNavSubpStreamOnceInSameCell); if( IsInMenuDomain() || IsDvdNavigationForced() || !currentNavSubpStreamUsrLocked || changeNavSubpStreamOnceInSameCell ) { cSpuDecoder::eScaleMode mode = SPUdecoder ? SPUdecoder->getScaleMode() : cSpuDecoder::eSpuNormal; /* !!! Bit 7 set means hide, and only let Forced display show (see vm.c from libdvdnav) */ if (mode == cSpuDecoder::eSpuLetterBox ) { // TV 4:3, DVD 16:9 currentNavSubpStream = ev->physical_letterbox & (0x80 | SubpStreamMask); DEBUG_SUBP_ID("dvd choosing letterbox SPU stream: curNavSpu=%d 0x%X\n", currentNavSubpStream, currentNavSubpStream); } else if (mode == cSpuDecoder::eSpuPanAndScan ) { // TV 4:3, DVD 16:9 currentNavSubpStream = ev->physical_pan_scan & (0x80 | SubpStreamMask); DEBUG_SUBP_ID("dvd choosing pan_scan SPU stream: curNavSpu=%d 0x%X\n", currentNavSubpStream, currentNavSubpStream); } else { currentNavSubpStream = ev->physical_wide & (0x80 | SubpStreamMask); DEBUG_SUBP_ID("dvd choosing wide SPU stream: curNavSpu=%d 0x%X\n", currentNavSubpStream, currentNavSubpStream); } changeNavSubpStreamOnceInSameCell=false; } else { DEBUG_SUBP_ID("DVDNAV_SPU_STREAM_CHANGE: ignore (locked=%d/%d|not enabled=%d), menu=%d, feature=%d \n", currentNavSubpStreamUsrLocked, !changeNavSubpStreamOnceInSameCell, DVDSetup.ShowSubtitles, IsInMenuDomain(), isInFeature); } break; } case DVDNAV_AUDIO_STREAM_CHANGE: { DEBUG_NAV("%s:%d:NAV AUDIO STREAM CHANGE\n", __FILE__, __LINE__); dvdnav_audio_stream_change_event_t *ev; ev = (dvdnav_audio_stream_change_event_t *)cache_ptr; if(!currentNavAudioTrackUsrLocked) { int id = dvdnav_get_active_audio_stream(nav); DEBUG_AUDIO_ID("dvd->SetCurrentAudioTrack DOLBY %02X\n", ttDolby + id); if (Setup.UseDolbyDigital) DeviceSetCurrentAudioTrack(eTrackType(ttDolby + id)); else DeviceSetCurrentAudioTrack(eTrackType(ttAudio + id)); currentNavAudioTrack = id; DEBUG_AUDIO_ID("DVDNAV_AUDIO_STREAM_CHANGE: curNavAu=%d 0x%02X, phys=%d, 0x%X\n", id, id, ev->physical, ev->physical); SetCurrentNavAudioTrackUsrLocked(false); } else { DEBUG_AUDIO_ID("DVDNAV_AUDIO_STREAM_CHANGE: ignore (locked) phys=%d, 0x%X\n", ev->physical, ev->physical); } // firstClear=true; break; } case DVDNAV_VTS_CHANGE: DEBUG_NAV("%s:%d:NAV VTS CHANGE -> Empty, setAll-spu&audio \n", __FILE__, __LINE__); Empty(true); UpdateBlockInfo(); // TEST UpdateVTSInfo(); // TEST setAllSubpStreams(); setAllAudioTracks(); SetTitleInfoString(); SetTitleString(); SetAspectString(); if (first_vts_change) { first_vts_change = false; // now all data for computing the resume key is available, so trying to resume int resTitle, resChapter; if (LoadResume(resTitle, resChapter, resSecond)) { // if resume data could be found seek to the found title and chapter NOW GotoTitle(resTitle, resChapter); // and wait for the next cell change (= title and chapter reached) // to seek to the exact time next_cell_change = true; // note: seeking to the exact time HERE leads to an error on the libdvdnav console: // "dvd error dvdnav_sector_search: New position not yet determined." and is // slightly ignored :-( . } } break; case DVDNAV_CELL_CHANGE: { DEBUG_NAV("%s:%d:NAV CELL CHANGE\n", __FILE__, __LINE__); /** * update information */ memcpy(&lastCellEventInfo, cache_ptr, sizeof(dvdnav_cell_change_event_t)); UpdateBlockInfo(); // TEST UpdateVTSInfo(); // TEST BlocksToPGCTicks( 1, pgcTicksPerBlock, pgcTotalTicks); #ifdef CTRLDEBUG printCellInfo(lastCellEventInfo, pgcTicksPerBlock, pgcTotalTicks); #endif //did the old cell end in a still frame? SendIframe( stillFrame & CELL_STILL ); stillFrame = (dvdnav_get_next_still_flag(nav) != 0) ? CELL_STILL : 0; // cell change .. game over .. changeNavSubpStreamOnceInSameCell=false; SetTitleInfoString(); if (next_cell_change) { next_cell_change = false; // we are resuming the current dvd. NOW its time to seek to the correct second. Goto(resSecond); } break; } case DVDNAV_NAV_PACKET: { DEBUG_NAV0("%s:%d:NAV PACKET\n", __FILE__, __LINE__); dsi_t *dsi; current_pci = dvdnav_get_current_nav_pci(nav); DEBUG_NAV0("NAV: %x, prev_e_ptm: %8d, s_ptm: %8d, ", stillFrame, prev_e_ptm, current_pci->pci_gi.vobu_s_ptm); if (prev_e_ptm) ptm_offs += (prev_e_ptm - current_pci->pci_gi.vobu_s_ptm); DEBUG_NAV0("ptm_offs: %8d\n", ptm_offs); prev_e_ptm = current_pci->pci_gi.vobu_e_ptm; if (current_pci && (current_pci->hli.hl_gi.hli_ss & 0x03) == 1) UpdateButtonHighlight(NULL); dsi = dvdnav_get_current_nav_dsi(nav); SendIframe( stillFrame & NAV_STILL ); if (dsi->vobu_sri.next_video == 0xbfffffff) stillFrame |= NAV_STILL; else stillFrame &= ~NAV_STILL; break; } case DVDNAV_STOP: DEBUG_NAV("%s:%d:NAV STOP\n", __FILE__, __LINE__); running = false; break; case DVDNAV_HIGHLIGHT: { DEBUG_NAV("%s:%d:NAV HIGHLIGHT\n", __FILE__, __LINE__); dvdnav_highlight_event_t *hlevt = (dvdnav_highlight_event_t *)cache_ptr; UpdateButtonHighlight(hlevt); break; } case DVDNAV_SPU_CLUT_CHANGE: DEBUG_NAV("%s:%d:NAV SPU CLUT CHANGE SPUdecoder=%d\n", __FILE__, __LINE__, SPUdecoder!=NULL); if (SPUdecoder) { ClearButtonHighlight(); SPUdecoder->setPalette((uint32_t *)cache_ptr); } break; case DVDNAV_HOP_CHANNEL: DEBUG_NAV("%s:%d:NAV HOP CHANNEL -> Empty\n", __FILE__, __LINE__); //Empty reset backward play!!! if ( !trickMode ) { //if (playDir != pdBackward) Empty(true); } UpdateBlockInfo(); // TEST UpdateVTSInfo(); // TEST break; default: DEBUG_NAV("%s:%d:NAV ???\n", __FILE__, __LINE__); break; } #ifdef DVDDEBUG if ((event != DVDNAV_BLOCK_OK) && (event != DVDNAV_NAV_PACKET) && (event != DVDNAV_STILL_FRAME)) DEBUGDVD("got event (%d)%s, len %d\n", event, dvd_ev[event], len); #endif if (cache_ptr != 0 && cache_ptr != event_buf) dvdnav_free_cache_block(nav, cache_ptr); } DEBUG_NAV("%s:%d: empty\n", __FILE__, __LINE__); Empty(); fflush(NULL); running = false; SPUdecoder=NULL; dvdnav_close(nav); nav=NULL; DEBUGDVD("%s:%d: input thread ended (pid=%d)\n", __FILE__, __LINE__, getpid()); fflush(NULL); } void cDvdPlayer::ClearButtonHighlight(void) { LOCK_THREAD; if (SPUdecoder) { SPUdecoder->clearHighlight(); DEBUG_NAV("DVD NAV SPU clear button %d\n", currButtonN); } } void cDvdPlayer::activateButton(void) { DEBUGDVD("activateButton (former: %d)\n", currButtonN); if (nav && current_pci) { LOCK_THREAD; //StillSkip(); int buttonN; dvdnav_highlight_area_t hl; dvdnav_get_current_highlight(nav, &buttonN); if (dvdnav_get_highlight_area(current_pci, buttonN, 0, &hl) == DVDNAV_STATUS_OK) { ClearButtonHighlight(); DEBUG_NAV("DVD NAV SPU activate hl button: %d: %d/%d %d/%d (%dx%d)\n", buttonN, hl.sx, hl.sy, hl.ex, hl.ey, hl.ex-hl.sx+1, hl.ey-hl.sy+1); } dvdnav_button_select_and_activate(nav, current_pci, buttonN); } } void cDvdPlayer::UpdateButtonHighlight(dvdnav_highlight_event_t *hlevt) { LOCK_THREAD; if (hlevt) { DEBUG_NAV("DVD NAV SPU highlight evt: %d: %d/%d %d/%d (%dx%d)\n", hlevt->buttonN, hlevt->sx, hlevt->sy, hlevt->ex, hlevt->ey, hlevt->ex-hlevt->sx+1, hlevt->ey-hlevt->sy+1); } else { DEBUG_NAV("DVD NAV SPU highlight evt: NULL\n"); } int buttonN = -1; dvdnav_get_current_highlight(nav, &buttonN); ClearButtonHighlight(); if (SPUdecoder && current_pci && TakeOsd()) { dvdnav_highlight_area_t hl; //libdvdnav does not support button groups //but letterbox and pan&scan need it for correct highlight information bool libdvd_workaround = false; if (current_pci->hli.hl_gi.btngr_ns) { int btns_per_group = 36 / current_pci->hli.hl_gi.btngr_ns; btni_t *button_ptr = NULL; int modeMask = 1 << SPUdecoder->getScaleMode(); if (!button_ptr && current_pci->hli.hl_gi.btngr_ns >= 1 && (current_pci->hli.hl_gi.btngr1_dsp_ty & modeMask)) button_ptr = ¤t_pci->hli.btnit[0 * btns_per_group + buttonN - 1]; if (!button_ptr && current_pci->hli.hl_gi.btngr_ns >= 2 && (current_pci->hli.hl_gi.btngr2_dsp_ty & modeMask)) button_ptr = ¤t_pci->hli.btnit[1 * btns_per_group + buttonN - 1]; if (!button_ptr && current_pci->hli.hl_gi.btngr_ns >= 3 && (current_pci->hli.hl_gi.btngr3_dsp_ty & modeMask)) button_ptr = ¤t_pci->hli.btnit[2 * btns_per_group + buttonN - 1]; if (button_ptr && button_ptr->btn_coln != 0) { int sx = button_ptr->x_start; int ex = button_ptr->x_end; if ((ex - sx + 1) & 0x03) ex += 4 - ((ex - sx + 1) & 0x03); SPUdecoder->setHighlight(sx, button_ptr->y_start, ex, button_ptr->y_end, current_pci->hli.btn_colit.btn_coli[button_ptr->btn_coln-1][0]); libdvd_workaround = true; } } if (!libdvd_workaround && dvdnav_get_highlight_area(current_pci, buttonN, 0, &hl) == DVDNAV_STATUS_OK) { DEBUG_NAV("DVD NAV SPU highlight button: %d: %d/%d %d/%d (%dx%d)\n", buttonN, hl.sx, hl.sy, hl.ex, hl.ey, hl.ex-hl.sx+1, hl.ey-hl.sy+1); if ((hl.ex - hl.sx + 1) & 0x03) { hl.ex += 4 - ((hl.ex - hl.sx + 1) & 0x03); } DEBUG_NAV("\t\t-> %d/%d %d/%d (%dx%d)\n", hl.sx, hl.sy, hl.ex, hl.ey, hl.ex-hl.sx+1, hl.ey-hl.sy+1); SPUdecoder->setHighlight(hl.sx, hl.sy, hl.ex, hl.ey, hl.palette); if(pktpts != 0xFFFFFFFF) seenVPTS(pktpts); } else { // this should never happen anyway if (buttonN == 0) { DEBUG_NAV("DVD NAV SPU select button 1 %s:%d\n", __FILE__, __LINE__); dvdnav_button_select(nav, current_pci, 1); } else buttonN = -1; } } else { DEBUG_NAV("not current pci button: %d, SPUdecoder=%d, current_pci=0x%p\n", buttonN, SPUdecoder!=NULL, current_pci); } currButtonN = buttonN; } /* * current video parameter have been set by ScanVideoPacket, * update the state struct now appropriatly * aspect: 0001xxxx == 1:1 (square pixel) 0010xxxx == 4:3 0011xxxx == 16:9 0100xxxx == 2,21:1 */ void cDvdPlayer::DoScaleMode(int &vaspect) { // nothing has to be done, if // TV 16:9 // DVD 4:3 if (!Setup.VideoFormat && dvd_aspect != 0) { // // if we are here, then // TV==4:3 && DVD==16:9 // if (vaspect != 2) { // //and the actual material on the DVD is not 4:3 // if (!(dvd_scaleperm & 1)) // letterbox is allowed, keep 16:9 and wxh vaspect = 0x03; else if (!(dvd_scaleperm & 2)) { // pan& scan allowed .. vaspect = 0x02; // 4:3 } } if (vaspect == 2 && dvd_aspect == 3) // use letterbox (honor dvd_aspect) vaspect = 0x03; // 16:9 } } void cDvdPlayer::seenVPTS(uint64_t pts) { seenSpuPts(pts); } void cDvdPlayer::seenAPTS(uint64_t pts) { seenSpuPts(pts); } void cDvdPlayer::seenSpuPts(uint64_t pts) { LOCK_THREAD; if (SPUdecoder && TakeOsd()) { SPUdecoder->setTime(pts); } } void cDvdPlayer::SendIframe(bool doSend) { if (IframeCnt == 0 && iframeAssembler->Available() && doSend ) { DEBUG_IFRAME("I-Frame: Doing StillFrame: IframeCnt=%d->1, used=%d, doSend=%d, stillFrame=0x%X\n", IframeCnt, iframeAssembler->Available(), doSend, stillFrame); IframeCnt = 1; } } void cDvdPlayer::playSPU(int spuId, unsigned char *data, int datalen) { int spuSize = SPUassembler.getSize(); uint8_t *buffer = new uint8_t[spuSize]; SPUassembler.Get(buffer, SPUassembler.getSize()); /** * !(spuId & 0x80) controls subpictures from dvd-menu */ bool allowedShow = currentNavSubpStreamUsrLocked || IsDvdNavigationForced() || (DVDSetup.ShowSubtitles && !(spuId & 0x80)); DEBUG_SUBP_ID("playSPU: SPU proc, spu_size:%d, menuDomain=%d, pts: %12lld\n", spuSize, IsInMenuDomain(), SPUassembler.getPts()); SPUdecoder->processSPU(SPUassembler.getPts(), buffer, allowedShow); if(IsInMenuDomain()) seenVPTS(pktpts); // else should be seen later .. } int cDvdPlayer::playPacket(unsigned char *&cache_buf, bool trickMode, bool noAudio) { int playedPacket = pktNone; uint64_t scr; uint32_t mux; unsigned char *sector = cache_buf; static uint64_t lapts, lvpts; static int adiff; char ptype = '-'; //make sure we got a PS packet header if (!cPStream::packetStart(sector, DVD_VIDEO_LB_LEN) && cPStream::packetType(sector) != 0xBA) { esyslog("ERROR: dvd-plugin got unexpected packet: %x %x %x %x", sector[0], sector[1], sector[2], sector[3]); return playedPacket; } scr = cPStream::fromSCR(sector+4) * 300 + cPStream::fromSCRext(sector+9); mux = cPStream::fromMUXrate(sector+11); int offset = 14 + cPStream::stuffingLength(sector); sector += offset; int r = DVD_VIDEO_LB_LEN - offset; sector[6] &= 0x8f; int64_t rawSTC = -1; if ( !SoftDeviceOutActive ) { // if ( (rawSTC=cDevice::PrimaryDevice()->GetSTC())>=0 ) // stcPTS=(uint64_t)rawSTC; } uchar *data = sector; int datalen = r; pictureFlip=false; switch (cPStream::packetType(sector)) { case VIDEO_STREAM_S ... VIDEO_STREAM_E: { bool ptsFlag = ((sector[7] & 0x80) && sector[8]>=5); if (ptsFlag) { pktpts = cPStream::fromPTS(sector + 9) + (uint64_t)ptm_offs; } datalen = cPStream::packetLength(sector); //skip optional Header bytes datalen -= cPStream::PESHeaderLength(sector); data += cPStream::PESHeaderLength(sector); //skip mandatory header bytes data += 3; uint8_t currentFrameType = 0; bool do_copy = (lastFrameType == I_FRAME) && !(data[0] == 0 && data[1] == 0 && data[2] == 1); bool havePictureHeader = false; bool haveSequenceHeader = false; bool haveSliceBeforePicture = false; while (datalen > 6) { if (data[0] == 0 && data[1] == 0 && data[2] == 1) { int ptype2 = cPStream::packetType(data); if (ptype2 == SC_PICTURE) { uchar foundFrameType = (uchar)(data[5] >> 3) & 0x07; if (foundFrameType < I_FRAME || B_FRAME < foundFrameType) { data++; datalen--; continue; } havePictureHeader = true; VideoPts += 3600; lastFrameType = foundFrameType; if (!currentFrameType) currentFrameType = lastFrameType; // // in trickMode, only play assembled .. I-Frames .. skipPlayVideo= lastFrameType > I_FRAME && trickMode; data += 5; datalen -= 5; } else if (ptype2 == SEQUENCE_HEADER && datalen >= 8) { /** get the last IFRAME */ iframeAssembler->Clear(); haveSequenceHeader = true; data += 4; //skip the header // check the aspect ratio and correct it // // data stream seen as 4-bit nibbles: // 0 1 2 3 // ww|wh|hh|ax // // w width // h height // a aspect // x any hsize = (int) ( data[0] & 0xff ) << 4 ; // bits 04..11 hsize |= (int) ( data[1] & 0xf0 ) >> 4 ; // bits 00..03 vsize = (int) ( data[1] & 0x0f ) << 8 ; // bits 08..11 vsize |= (int) ( data[2] & 0xff ) ; // bits 00..07 vaspect = (int) ( data[3] & 0xf0 ) >> 4 ; DoScaleMode(vaspect); data[3] &= 0x0f; data[3] |= (uchar) ( ( vaspect & 0x0f ) << 4); data += 3; datalen -=7; } else if (ptype2 == PADDING_STREAM) { DEBUGDVD("PADDING_STREAM @ %d\n", data - sector); #if 0 DEBUGDVD("PADDING_STREAM (strip) r: %d -> %d\n", r, data - sector); r = data - sector; #endif break; } else if( 0x01 <= ptype2 && ptype2 <= 0xaf) { if( !havePictureHeader && iframeAssembler->Available()==0 ) haveSliceBeforePicture = true; int mb_y= ptype2 * 16; if ( mb_y == vsize) { pictureNumber++; pictureFlip=true; DEBUGDVD("pic flip - num: %llu\n", pictureNumber); } /** else { DEBUGDVD("pic vsize %d, mb_y*16: %d ; pn: %llu\n", vsize, mb_y, pictureNumber); } */ } } data++; datalen--; } if (stillFrame && (currentFrameType <= I_FRAME || do_copy)) { if (haveSliceBeforePicture) { DEBUG_IFRAME2("I-Frame: clr (%d,%d,c:%d,p:%d,s:%d,x:%d,v:%u,p:%llu) !\n", currentFrameType, lastFrameType, (int)do_copy, (int)havePictureHeader, (int)haveSequenceHeader, (int)haveSliceBeforePicture, cntVidBlocksPlayed, pictureNumber); currentFrameType = 0; lastFrameType = 0xff; do_copy = false; } else { DEBUG_IFRAME2("I-Frame: Put MB .. %d+%d=", r, iframeAssembler->Available()); iframeAssembler->Put(sector, r); DEBUG_IFRAME2("%d (%d,%d,c:%d,p:%d,s:%d,x:%d,v:%d,p:%llu)\n", iframeAssembler->Available(), currentFrameType, lastFrameType, do_copy, havePictureHeader, haveSequenceHeader, haveSliceBeforePicture, cntVidBlocksPlayed, pictureNumber); } } if (ptsFlag) { VideoPts = lvpts = pktpts; cPStream::toPTS(sector + 9, pktpts); } rframe = new cFrame(sector, r, ftVideo); playedPacket |= pktVideo; if ( !IsInMenuDomain() ) seenVPTS(VideoPts); ptype = 'V'; break; } case AUDIO_STREAM_S ... AUDIO_STREAM_E: { lastFrameType = AUDIO_STREAM_S; int audioVal = cPStream::packetType(sector); int audioId = audioVal & AudioTrackMask; int audioTrackIndex = notifySeenAudioTrack(audioId); uint16_t audioLanguageCode = GetAudioTrackLanguageCode(audioId); const char *audioLanguageStr = NULL; for (int i = 0; i < 22; i++) { if (!memcmp(&audioLanguageCode, DvdLanguageCode[i][0], 2)) { audioLanguageStr = DvdLanguageCode[i][1]; break; } } DeviceSetAvailableTrack(ttAudio, audioId, audioVal, audioLanguageStr); (void) audioTrackIndex; // no sound in trick mode if (noAudio) return playedPacket; if ( currentNavAudioTrack != audioId ) { /* DEBUG_AUDIO_ID("packet unasked audio stream: got=%d 0x%X (0x%X), curNavAu=%d 0x%X\n", cPStream::packetType(sector), cPStream::packetType(sector), cPStream::packetType(sector) & AudioTrackMask, currentNavAudioTrack, currentNavAudioTrack); */ return playedPacket; } bool ptsFlag = ((sector[7] & 0xC0)==0x80) && sector[8]>=5; if (ptsFlag) { pktpts = cPStream::fromPTS(sector + 9) + (uint64_t)ptm_offs; } playedPacket |= pktAudio; SetCurrentNavAudioTrackType(aMPEG); if (ptsFlag) { adiff = pktpts - lapts; lapts = pktpts; cPStream::toPTS(sector + 9, pktpts); } if(rawSTC>=0) { pktptsLastAudio = pktptsAudio ; stcPTSLastAudio = stcPTSAudio ; pktptsAudio = pktpts; stcPTSAudio = stcPTS; } rframe = new cFrame(sector, r, ftAudio); if (ptsFlag) seenAPTS(pktpts); ptype = 'M'; break; } case PRIVATE_STREAM1: { datalen = cPStream::packetLength(sector); //skip optional Header bytes datalen -= cPStream::PESHeaderLength(sector); data += cPStream::PESHeaderLength(sector); //skip mandatory header bytes data += 3; //fallthrough is intended } case PRIVATE_STREAM2: { lastFrameType = PRIVATE_STREAM2; //FIXME: Stream1 + Stream2 is ok, but is Stream2 alone also? // no sound, no spu in trick mode if (noAudio) return playedPacket; // skip PS header bytes data += 6; bool ptsFlag = (sector[7] & 0xC0) && sector[8]>=5; if (ptsFlag) { pktpts = cPStream::fromPTS(sector + 9) + (uint64_t)ptm_offs; } // data now points to the beginning of the payload int subStreamId = ((int)*data); int audioType = subStreamId & 0xF8; if (audioType == aAC3 || audioType == aDTS || audioType == aLPCM) { int audioId = subStreamId & AC3AudioTrackMask; ptype = 'A'; int audioTrackIndex = notifySeenAudioTrack(audioId); uint16_t audioLanguageCode = GetAudioTrackLanguageCode(audioId); const char *audioLanguageStr = NULL; for (int i = 0; i < 22; i++) { if (!memcmp(&audioLanguageCode, DvdLanguageCode[i][0], 2)) { audioLanguageStr = DvdLanguageCode[i][1]; break; } } if ((!Setup.UseDolbyDigital && audioType == aAC3) || audioType == aLPCM) DeviceSetAvailableTrack(ttAudio, audioId, aLPCM | audioId, audioLanguageStr); else DeviceSetAvailableTrack(ttDolby, audioId, subStreamId, audioLanguageStr); (void)audioTrackIndex; if (ptsFlag) { adiff = pktpts - lapts; lapts = pktpts; } if (currentNavAudioTrack == audioId) { playedPacket |= pktAudio; SetCurrentNavAudioTrackType(audioType); if (ptsFlag) { cPStream::toPTS(sector + 9, pktpts); } if(rawSTC>=0) { pktptsLastAudio = pktptsAudio ; stcPTSLastAudio = stcPTSAudio ; pktptsAudio = pktpts; stcPTSAudio = stcPTS; } #ifdef AUDIOPLAYDEBUG2 /** * the funny thing here is, that: * - it plays well within vdr-xine * - it plays broken with vdr/dvb itself (PlayVideo) * - it plays broken with bitstreamout (PlayAudio) */ if ( audioType == aLPCM ) { int numFrame = (int)(data[1]); int offset = (uint16_t)(data[2]) << 8 | (uint16_t)(data[3]) ; bool emph = ((uint8_t)(data[4]) & 0x80 ) >> 7; bool mute = ((uint8_t)(data[4]) & 0x40 ) >> 6; bool res1 = ((uint8_t)(data[4]) & 0x20 ) >> 5; int numFrameA = ((uint8_t)(data[4]) & 0x1F ) ; int qwl = ((uint8_t)(data[5]) & 0xC0 ) >> 6; int bits = 0; switch ( audioin_fmt.bits ) { case 0: bits=16; break; case 1: bits=20; break; case 2: bits=24; break; case 3: bits=32; break; default: bits=16; break; } int sfr = ((uint8_t)(data[5]) & 0x30 ) >> 4; switch (sfr) { case 0: sfr=48000; break; case 1: sfr=96000; break; case 2: sfr=44100; break; case 3: sfr=32000; break; } bool res2 = ((uint8_t)(data[5]) & 0x08 ) >> 3; int channels = ((uint8_t)(data[5]) & 0x07 ) +1 ; int dyn_range = ((uint8_t)(data[6]) & 0xff ) ; DEBUG_AUDIO_PLAY2("dvd pcm: nf:%d, of:%d, e:%d, mu:%d, r1:%d, nfa:%d, bits=%d(qwl:%d), sfr:%d, r2:%d, ch:%d, dr:%d\n", numFrame, offset, emph, mute, res1, numFrameA, bits, qwl, sfr, res2, channels, dyn_range); } #endif if (HasReelbox && ptype == 'A'){ rframe = new cFrame(sector, r, ftDolby); if (ptsFlag) seenAPTS(pktpts); } else if (Setup.UseDolbyDigital || (audioType == aLPCM && !SoftDeviceOutActive)) { // else 2 pcm's -> 1 device rframe = new cFrame(sector, r, ftDolby); DEBUG_AUDIO_PLAY2("dvd pcm/fake menu=%d, stc=%8ums apts=%8ums vpts=%8ums len=%d\n", IsInMenuDomain(), (unsigned int)(stcPTS/90U), (unsigned int)(ptsFlag?pktpts/90U:0), (unsigned int)(VideoPts/90U), r); if (ptsFlag) seenAPTS(pktpts); } else if ( audioType == aAC3 && !BitStreamOutActive ) { data += 4; // header: 3 (mandatory) + 6 (PS) + 4 (AC3) datalen -= 13; DEBUG_AUDIO_PLAY2("dvd a52dec menu=%d, stc=%8ums apts=%8ums vpts=%8ums len=%d\n", IsInMenuDomain(), (unsigned int)(stcPTS/90U), (unsigned int)(ptsFlag?pktpts/90U:0), (unsigned int)(VideoPts/90U), datalen); if (ptsFlag && a52dec.getSyncMode()==A52decoder::ptsCopy) seenAPTS(pktpts); a52dec.decode(data, datalen, pktpts, audioId); } else if (audioType == aDTS && !BitStreamOutActive ) { // todo DTS ;-) DEBUG_AUDIO_PLAY2("dvd aDTS n.a. menu=%d\n", IsInMenuDomain()); if (ptsFlag) seenAPTS(pktpts); } } } else if ((subStreamId & 0xE0) == 0x20) { int subtitleIndex = subStreamId & SubpStreamMask; notifySeenSubpStream(subtitleIndex); ptype = 'S'; if (OsdInUse()) { /** * somebody uses the osd .. DEBUG_SUBP_ID("SPU in vts ignored -> OsdInUse() !\n"); */ break; } data++; datalen -= 10; // 3 (mandatory header) + 6 (PS header) /** * !!! currentNavSubpStream is used for Bit 7 from libdvdnav, it controls 'forced subs' */ if (currentNavSubpStream != -1 && subtitleIndex == (currentNavSubpStream & SubpStreamMask)) { SPUassembler.Put(data, datalen, pktpts); if (SPUdecoder && SPUassembler.ready()) playSPU(currentNavSubpStream, data, datalen); } } else { DEBUGDVD("PRIVATE_STREAM2 unhandled (a)id: %d 0x%X\n", (int)(*data), (int)(*data)); } break; } /* PRIVATE_STREAM2 */ case PADDING_STREAM: DEBUGDVD("PADDING_STREAM ...\n"); lastFrameType = PADDING_STREAM; break; case SYSTEM_HEADER: case PROG_STREAM_MAP: default: { lastFrameType = 0xff; esyslog("ERROR: dvd-plugin don't know what to do - packetType: %x", cPStream::packetType(sector)); DEBUGDVD("don't know what to do - packetType: %x", cPStream::packetType(sector)); return playedPacket; } } if(rframe && !ringBuffer->Put(rframe)) delete rframe; rframe = NULL; #ifdef PTSDEBUG if (playMode != pmPlay) DEBUGPTS("SCR: %8Lx,%8Ld, %8d, %c %1d, %8d (%8d) - %8d (%8d)\n", scr / 300, scr % 300, mux, ptype, ptsFlag, VideoPts, lvpts, lapts, adiff); #endif return playedPacket; } int cDvdPlayer::Resume(void) { return -1; } bool cDvdPlayer::Save(void) { return false; } void cDvdPlayer::Activate(bool On) { DEBUGDVD("cDvdPlayer::Activate %d->%d\n", active, On); if (On) { Start(); } else if (active) { if(nav) dvdnav_stop(nav); else running = false; Cancel(3); running = false; active = false; } } void cDvdPlayer::Pause(void) { if (!DVDActiveAndRunning()) return; if (playMode == pmPause || playMode == pmStill) Play(); else { LOCK_THREAD; if (playMode == pmFast || (playMode == pmSlow && playDir == pdBackward)) { DEBUG_NAV("%s:%d: empty\n", __FILE__, __LINE__); Empty(); } DeviceFreeze(); // DeviceClear(); playMode = pmPause; } } void cDvdPlayer::Stop(void) { if (!DVDActiveAndRunning()) return; if (running && nav) { // we will stop replay now. Its time to save the current possition // for later resuming. SaveResume(); dvdnav_stop(nav); // don't know why Stop() is called twice, but this prevents from // twice save resume data and calling dvdnav_stop() twice. // Comments from maintainers are welcome. running = false; } } void cDvdPlayer::Play(void) { if (!DVDActiveAndRunning()) return; if (playMode != pmPlay) { LOCK_THREAD; if (playMode == pmStill || playMode == pmFast || (playMode == pmSlow && playDir == pdBackward)) { if (DVDSetup.ReadAHead > 0) dvdnav_set_readahead_flag(nav, DVDSetup.ReadAHead); DEBUG_NAV("DVD NAV SPU clear & empty %s:%d\n", __FILE__, __LINE__); Empty(); } DevicePlay(); playMode = pmPlay; playDir = pdForward; } } void cDvdPlayer::Forward(void) { if (!DVDActiveAndRunning()) return; LOCK_THREAD; switch (playMode) { case pmFast: if (Setup.MultiSpeedMode) { TrickSpeed(playDir == pdForward ? 1 : -1); break; } else if (playDir == pdForward) { Play(); break; } // run into pmPlay case pmPlay: DEBUG_NAV("DVD NAV SPU clear & empty %s:%d\n", __FILE__, __LINE__); Empty(); DeviceMute(); playMode = pmFast; playDir = pdForward; trickSpeed = NORMAL_SPEED; TrickSpeed(Setup.MultiSpeedMode ? 1 : MAX_SPEEDS); break; case pmSlow: if (Setup.MultiSpeedMode) { TrickSpeed(playDir == pdForward ? -1 : 1); break; } else if (playDir == pdForward) { Pause(); break; } // run into pmPause case pmStill: case pmPause: DeviceMute(); playMode = pmSlow; playDir = pdForward; trickSpeed = NORMAL_SPEED; TrickSpeed(Setup.MultiSpeedMode ? -1 : -MAX_SPEEDS); break; } } void cDvdPlayer::Backward(void) { if (!DVDActiveAndRunning()) return; LOCK_THREAD; switch (playMode) { case pmFast: if (Setup.MultiSpeedMode) { TrickSpeed(playDir == pdBackward ? 1 : -1); break; } else if (playDir == pdBackward) { Play(); break; } // run into pmPlay case pmPlay: DEBUG_NAV("DVD NAV SPU clear & empty %s:%d\n", __FILE__, __LINE__); Empty(); DeviceMute(); playMode = pmFast; playDir = pdBackward; trickSpeed = NORMAL_SPEED; TrickSpeed(Setup.MultiSpeedMode ? 1 : MAX_SPEEDS); break; case pmSlow: if (Setup.MultiSpeedMode) { TrickSpeed(playDir == pdBackward ? -1 : 1); break; } else if (playDir == pdBackward) { Pause(); break; } // run into pmPause case pmStill: case pmPause: DEBUG_NAV("DVD NAV SPU clear & empty %s:%d\n", __FILE__, __LINE__); Empty(); DeviceMute(); playMode = pmSlow; playDir = pdBackward; trickSpeed = NORMAL_SPEED; TrickSpeed(Setup.MultiSpeedMode ? -1 : -MAX_SPEEDS); break; } } inline int cDvdPlayer::GetProgramNumber(void) const { return lastCellEventInfo.pgN; } inline int cDvdPlayer::GetCellNumber(void) const { return lastCellEventInfo.cellN; } inline int64_t cDvdPlayer::GetPGLengthInTicks(void) { return lastCellEventInfo.pg_length; } inline int64_t cDvdPlayer::GetPGCLengthInTicks(void) { return lastCellEventInfo.pgc_length; } void cDvdPlayer::BlocksToPGCTicks(uint32_t BlockNum, int64_t &Ticks, int64_t &TotalTicks) { TotalTicks = GetPGCLengthInTicks(); if (pgcTotalBlockNum > 0) Ticks = BlockNum * (TotalTicks / pgcTotalBlockNum) ; else Ticks = 0; } void cDvdPlayer::PGCTicksToBlocks( int64_t Ticks, uint32_t &BlockNum, uint32_t &TotalBlockNum) { int64_t totalTicks = GetPGCLengthInTicks(); TotalBlockNum = pgcTotalBlockNum; BlockNum = totalTicks > 0 ? (Ticks * TotalBlockNum / totalTicks) : 0; } bool cDvdPlayer::GetIndex(int &CurrentFrame, int &TotalFrame, bool SnapToIFrame) { if (nav) { uint32_t currentBlock; uint32_t totalBlock; dvdnav_set_PGC_positioning_flag(nav, 1); if (dvdnav_get_position(nav, ¤tBlock, &totalBlock) == DVDNAV_STATUS_OK) { #if VDRVERSNUM >= 10703 CurrentFrame = (int)(currentBlock * GetPGCLengthInTicks() / totalBlock / 90000L * FramesPerSecond()); TotalFrame = (int)(GetPGCLengthInTicks() / 90000L * FramesPerSecond()); #else CurrentFrame = (int)(currentBlock * GetPGCLengthInTicks() / totalBlock / 90000L) * FRAMESPERSEC; TotalFrame = (int)(GetPGCLengthInTicks() / 90000L) * FRAMESPERSEC; #endif return true; } } return false; } bool cDvdPlayer::UpdateBlockInfo() { if (nav) { dvdnav_set_PGC_positioning_flag (nav, 1); if(dvdnav_get_position (nav, &pgcCurrentBlockNum, &pgcTotalBlockNum) != DVDNAV_STATUS_OK) { DEBUG_CONTROL("dvd get pos in title failed (no pos) ..\n"); return false; } } else { DEBUG_CONTROL("dvd get pos in title failed (no nav) ..\n"); return false; } return true; } void cDvdPlayer::UpdateVTSInfo() { if(nav) { dvd_aspect = dvdnav_get_video_aspect(nav); dvd_scaleperm = dvdnav_get_video_scale_permission(nav); isInMenuDomain = dvdnav_is_domain_vmgm(nav) || dvdnav_is_domain_vtsm(nav); isInFeature = dvdnav_is_domain_vts(nav); eVideoDisplayFormat videoDisplayformat = vdfCenterCutOut; if (!(dvd_scaleperm & 1)) videoDisplayformat = vdfLetterBox; else if (!(dvd_scaleperm & 2)) videoDisplayformat = vdfPanAndScan; DeviceSetVideoDisplayFormat(videoDisplayformat); } } int cDvdPlayer::SkipFrames(int Frames) { if (!DVDActiveAndRunning()) return -1; #if VDRVERSNUM >= 10703 SkipSeconds(int(Frames * FramesPerSecond())); #else SkipSeconds(Frames*FRAMESPERSEC); #endif return Frames; } void cDvdPlayer::SkipSeconds(int Seconds) { if (!DVDActiveAndRunning()) return; if (Seconds) { int64_t diffTicks = Seconds * 90000; uint32_t diffBlockNum; uint32_t currentBlockNumber = pgcCurrentBlockNum; PGCTicksToBlocks(diffTicks, diffBlockNum, pgcTotalBlockNum); currentBlockNumber += diffBlockNum; LOCK_THREAD; DEBUG_NAV("DVD NAV SPU clear & empty %s:%d\n", __FILE__, __LINE__); Empty(); if (dvdnav_sector_search(nav, currentBlockNumber, SEEK_SET) != DVDNAV_STATUS_OK) printf("dvd error dvdnav_sector_search: %s\n", dvdnav_err_to_string(nav)); Play(); } } bool cDvdPlayer::GetPositionInSec(int64_t &CurrentSec, int64_t &TotalSec) { int64_t currentTicks = 0; int64_t totalTicks = 0; if (!DVDActiveAndRunning()) { CurrentSec = -1; TotalSec = -1; return false; } if (!GetPositionInTicks(currentTicks, totalTicks)) return false; CurrentSec = PTSTicksToSec(currentTicks); TotalSec = PTSTicksToSec(totalTicks); return true; } bool cDvdPlayer::GetPositionInTicks(int64_t &CurrentTicks, int64_t &TotalTicks) { BlocksToPGCTicks(pgcCurrentBlockNum, CurrentTicks, TotalTicks ); return true; } void cDvdPlayer::Goto(int Seconds, bool Still) { int64_t currentTicks = Seconds * 90000; uint32_t currentBlockNumber; uint32_t totalBlockNumber; if (!DVDActiveAndRunning()) return; PGCTicksToBlocks(currentTicks, currentBlockNumber, totalBlockNumber); LOCK_THREAD; DEBUG_NAV("DVD NAV SPU clear & empty %s:%d\n", __FILE__, __LINE__); Empty(); if (dvdnav_sector_search(nav, currentBlockNumber, SEEK_SET) != DVDNAV_STATUS_OK) printf("dvd error dvdnav_sector_search: %s\n", dvdnav_err_to_string(nav)); Play(); } int cDvdPlayer::GotoAngle(int Angle) { int angleNumber = -1; int angleNumbers = -1; if (!DVDActiveAndRunning()) return -1; LOCK_THREAD; DEBUG_NAV("DVD NAV SPU clear & empty %s:%d\n", __FILE__, __LINE__); Empty(); dvdnav_get_angle_info(nav, &angleNumber, &angleNumbers); if (Angle > angleNumbers) Angle = 1; if (Angle <= 0) Angle = angleNumbers; if (stillTimer == 0) dvdnav_angle_change(nav, Angle); Play(); return Angle; } void cDvdPlayer::NextAngle(void) { int angleNumber = -1; int angleNumbers = -1; if (!DVDActiveAndRunning()) return; dvdnav_get_angle_info(nav, &angleNumber, &angleNumbers); GotoAngle(++angleNumber); } // GotoTitle now optionally takes a chapter to seek to in the given title. int cDvdPlayer::GotoTitle(int Title, int Chapter /*= 1*/) { int titleNumbers; int targetTitle = Title; int chapterNumber; if (!DVDActiveAndRunning()) return -1; LOCK_THREAD; DEBUG_NAV("DVD NAV SPU clear & empty %s:%d\n", __FILE__, __LINE__); Empty(); // check if the given title is in the title range of this dvd dvdnav_get_number_of_titles(nav, &titleNumbers); if (Title > titleNumbers) targetTitle = 1; if (Title <= 0) targetTitle = titleNumbers; // if given title is in the bounds of this dvd's title range if (Title == targetTitle) { // check if the chapter is in the title's chapter range dvdnav_get_number_of_parts(nav, Title, &chapterNumber); if (Chapter > chapterNumber) Chapter = 1; if (Chapter <= 0) Chapter = chapterNumber; } else { // otherwise reset it to the first chapter. Chapter = 1; } if (stillTimer == 0) { dvdnav_part_play(nav, Title, Chapter); // dvdnav_title_play(nav, Title); } Play(); return Title; } void cDvdPlayer::NextTitle(void) { int titleNumber, chapterNumber; if (!DVDActiveAndRunning()) return; dvdnav_current_title_info(nav, &titleNumber, &chapterNumber); GotoTitle(++titleNumber); } void cDvdPlayer::PreviousTitle() { int titleNumber, chapterNumber; if (!DVDActiveAndRunning()) return; dvdnav_current_title_info(nav, &titleNumber, &chapterNumber); GotoTitle(--titleNumber); } int cDvdPlayer::GotoPart(int Part) { int titleNumber; int chapterNumber; int chapterNumbers; if (!DVDActiveAndRunning()) return -1; LOCK_THREAD; DEBUG_NAV("DVD NAV SPU clear & empty %s:%d\n", __FILE__, __LINE__); Empty(); dvdnav_current_title_info(nav, &titleNumber, &chapterNumber); dvdnav_get_number_of_parts(nav, titleNumber, &chapterNumbers); if (Part > chapterNumbers) Part = 1; if (Part <= 0) Part = chapterNumbers; if (stillTimer == 0) dvdnav_part_play(nav, titleNumber, Part); Play(); return Part; } void cDvdPlayer::NextPart(void) { int titleNumber, chapterNumber; if (!DVDActiveAndRunning()) return; dvdnav_current_title_info(nav, &titleNumber, &chapterNumber); GotoPart(++chapterNumber); } void cDvdPlayer::PreviousPart(void) { int titleNumber, chapterNumber; if (!DVDActiveAndRunning()) return; dvdnav_current_title_info(nav, &titleNumber, &chapterNumber); GotoPart(--chapterNumber); } void cDvdPlayer::NextPG(void) { if (!DVDActiveAndRunning()) return; LOCK_THREAD; DEBUG_NAV("DVD NAV SPU clear & empty %s:%d\n", __FILE__, __LINE__); Empty(); if (stillTimer == 0) dvdnav_next_pg_search(nav); Play(); } void cDvdPlayer::PreviousPG(void) { if (!DVDActiveAndRunning()) return; LOCK_THREAD; DEBUG_NAV("DVD NAV SPU clear & empty %s:%d\n", __FILE__, __LINE__); Empty(); dvdnav_prev_pg_search(nav); Play(); } void cDvdPlayer::clearSeenSubpStream( ) { LOCK_THREAD; navSubpStreamSeen.Clear(); currentNavSubpStream = -1; notifySeenSubpStream(-1); // no subp .. DEBUG_SUBP_ID("cDvdPlayer::cDvdPlayer: seen subp cleared\n"); SetCurrentNavSubpStreamUsrLocked(false); } void cDvdPlayer::setAllSubpStreams(void) { clearSeenSubpStream(); for (int i = 0; nav != NULL && i < MaxSubpStreams; i++) { if (GetSubtitleLanguageCode(i) != 0xFFFF) notifySeenSubpStream(i); } } /** !!! Save Bit7 for 'forced subs' !!! * */ int cDvdPlayer::SearchSubpStream(int SubpStreamId) const { if (SubpStreamId != -1) SubpStreamId &= SubpStreamMask; int i = navSubpStreamSeen.Count() - 1; while (i >= 0) { int streamId = ((IntegerListObject *)navSubpStreamSeen.Get(i))->getValue(); if (streamId != -1) streamId &= SubpStreamMask; if (SubpStreamId == ((IntegerListObject *)navSubpStreamSeen.Get(i))->getValue()) break; // found i--; } return i; } void cDvdPlayer::notifySeenSubpStream(int navSubpStream) { int i = SearchSubpStream(navSubpStream); if (i < 0) { /*#ifdef SUBPDEBUG int channel, channel_active=0; uint16_t subpStreamLanguageCode = 0; channel = navSubpStream; if(nav != NULL) { subpStreamLanguageCode = GetNavSubpStreamLangCode(channel); channel_active = dvdnav_get_active_spu_stream(nav); } printf("cDvdPlayer::cDvdPlayer: seen new subp id: 0x%X (%d), <%s>; 0x%X (%d)\n", channel, channel, (char *)&subpStreamLanguageCode, channel_active, channel_active); #endif*/ // only set possible subpstreams if ((nav && dvdnav_get_spu_logical_stream(nav, navSubpStream) >= 0) || navSubpStream == -1) navSubpStreamSeen.Add(new IntegerListObject(navSubpStream)); } } bool cDvdPlayer::GetCurrentNavSubpStreamUsrLocked(void) const { return currentNavSubpStreamUsrLocked; } void cDvdPlayer::SetCurrentNavSubpStreamUsrLocked(bool lock) { currentNavSubpStreamUsrLocked = lock; DEBUG_SUBP_ID("cDvdPlayer::cDvdPlayer: currentNavSubpStreamUsrLocked=%s\n", currentNavSubpStreamUsrLocked ? "true" : "false"); } int cDvdPlayer::GetCurrentNavSubpStream(void) const { return currentNavSubpStream; } int cDvdPlayer::GetCurrentNavSubpStreamIdx(void) const { return SearchSubpStream(currentNavSubpStream); } int cDvdPlayer::GetSubtitleStreamNumbers(void) const { return navSubpStreamSeen.Count(); } int cDvdPlayer::SetSubpStream(int id) { LOCK_THREAD; int i = SearchSubpStream(id); if (i < 0) id = ((IntegerListObject *)navSubpStreamSeen.Get(0))->getValue(); currentNavSubpStream = id; SetCurrentNavSubpStreamUsrLocked(true); uint16_t subtileLanguageCode = GetSubtitleLanguageCode(currentNavSubpStream); if (subtileLanguageCode != 0xFFFF && nav) dvdnav_spu_language_select(nav, (char *)&subtileLanguageCode); DEBUG_SUBP_ID("cDvdPlayer::cDvdPlayer: curNavSpu next to 0x%X, idx=%d, %s, locked=%d/%d\n", currentNavSubpStream, i, (char *)&subtileLanguageCode, currentNavSubpStreamUsrLocked, !changeNavSubpStreamOnceInSameCell); return id; } int cDvdPlayer::NextSubpStream() { if (navSubpStreamSeen.Count() == 0) return 0; LOCK_THREAD; int i = SearchSubpStream(currentNavSubpStream); i = ( i + 1 ) % navSubpStreamSeen.Count(); DEBUG_SUBP_ID("cDvdPlayer::cDvdPlayer: found curNavSubp(0x%X) at idx = %d\n", currentNavSubpStream, i); currentNavSubpStream = ((IntegerListObject *)navSubpStreamSeen.Get(i))->getValue(); uint16_t subtileLanguageCode = GetSubtitleLanguageCode(currentNavSubpStream); if (subtileLanguageCode != 0xFFFF && nav) dvdnav_spu_language_select(nav, (char *)&subtileLanguageCode); SetCurrentNavSubpStreamUsrLocked(true); // DEBUG_SUBP_ID("cDvdPlayer::cDvdPlayer: curNavSpu next to 0x%X, idx=%d, %s, locked=%d/%d\n", // currentNavSubpStream, i, (char *)¤tNavSubpStreamLangCode, // currentNavSubpStreamUsrLocked, !changeNavSubpStreamOnceInSameCell); return 0; } void cDvdPlayer::clearSeenAudioTrack( ) { navAudioTracksSeen.Clear(); DEBUG_AUDIO_ID("cDvdPlayer::cDvdPlayer: seen audio cleared\n"); SetCurrentNavAudioTrackUsrLocked(false); DeviceClrAvailableTracks(); } void cDvdPlayer::setAllAudioTracks(void) { clearSeenAudioTrack(); for (int i = 0; nav != NULL && i < MaxAudioTracks; i++) { if (GetAudioTrackLanguageCode(i) != 0xFFFF) { notifySeenAudioTrack(dvdnav_get_audio_logical_stream(nav, i)); } } } int cDvdPlayer::SearchAudioStream(int AudioStreamId) const { int i = navAudioTracksSeen.Count() - 1; while (i >= 0) { if (AudioStreamId == ((IntegerListObject *)navAudioTracksSeen.Get(i))->getValue()) break; // found i--; } return i; } int cDvdPlayer::notifySeenAudioTrack(int navAudioTrack) { int i = SearchAudioStream(navAudioTrack); if (i < 0) { #ifdef AUDIOIDDEBUG uint16_t audioLanguageCode = 0xFFFF; int channel, channel_active=0; channel = navAudioTrack; if (nav != NULL) { audioLanguageCode = GetAudioTrackLanguageCode(channel); channel_active = dvdnav_get_active_audio_stream(nav); } printf("cDvdPlayer::cDvdPlayer: seen new audio id: 0x%X (%d), <%s>; 0x%X (%d)\n", channel, channel, (char *)&audioLanguageCode, channel_active, channel_active); fflush(NULL); #endif navAudioTracksSeen.Add(new IntegerListObject(navAudioTrack)); return navAudioTracksSeen.Count() - 1; } else return i; } bool cDvdPlayer::GetCurrentNavAudioTrackUsrLocked(void) const { return currentNavAudioTrackUsrLocked; } void cDvdPlayer::SetCurrentNavAudioTrackUsrLocked(bool lock) { currentNavAudioTrackUsrLocked = lock; DEBUG_AUDIO_ID("cDvdPlayer::cDvdPlayer: currentNavAudioTrackUsrLocked=%s\n", currentNavAudioTrackUsrLocked ? "true" : "false"); } int cDvdPlayer::GetCurrentNavAudioTrack(void) const { return currentNavAudioTrack; } int cDvdPlayer::GetCurrentNavAudioTrackIdx(void) const { return SearchAudioStream(currentNavAudioTrack); } bool cDvdPlayer::SetCurrentNavAudioTrackType(int atype) { lastNavAudioTrackType = currentNavAudioTrackType; currentNavAudioTrackType = atype; bool ch = lastNavAudioTrackType!=currentNavAudioTrackType; if(ch) { DEBUG_AUDIO_ID("cDvdPlayer::cDvdPlayer: atype 0x%X -> 0x%X := %d\n", lastNavAudioTrackType, currentNavAudioTrackType, ch); } return ch; } int cDvdPlayer::GetCurrentNavAudioTrackType(void) const { return currentNavAudioTrackType; // aAC3, aDTS, aLPCM, aMPEG } int cDvdPlayer::GetAudioStreamNumbers(void) const { return navAudioTracksSeen.Count(); } void cDvdPlayer::SetAudioTrack(eTrackType Type, const tTrackId *TrackId) { if(!DVDActiveAndRunning() || !TrackId) return; LOCK_THREAD; int id = TrackId->id & (IS_DOLBY_TRACK(Type) ? AC3AudioTrackMask : AudioTrackMask); DEBUG_AUDIO_ID("cDvdPlayer::SetAudioTrack: dd=%d, index=%d, id=0x%2X\n", IS_DOLBY_TRACK(Type), Type, id); int i = SearchAudioStream(id); if(i < 0 && navAudioTracksSeen.Count() > 0) { id = ((IntegerListObject *)navAudioTracksSeen.Get(0))->getValue(); DEBUG_AUDIO_ID("cDvdPlayer::SetAudioTrack: .. not found !\n"); } else { currentNavAudioTrack = -1; DEBUG_AUDIO_ID("cDvdPlayer::SetAudioTrack: .. found !\n"); } SetCurrentNavAudioTrackUsrLocked(true); //!!! soundglitches on titlejump if (currentNavAudioTrack != id) { currentNavAudioTrack = id; uint16_t audioTrackLangCode = GetAudioTrackLanguageCode(currentNavAudioTrack); if (audioTrackLangCode != 0xFFFF) { dvdnav_audio_language_select(nav, (char *)&audioTrackLangCode); } // Empty(); DEBUG_AUDIO_ID("cDvdPlayer::SetAudioTrack: SWITCHED !\n"); } } uint16_t cDvdPlayer::GetAudioTrackLanguageCode(int Channel) const { uint16_t audioStreamLanguageCode = 0xFFFF; if (nav) { int logchan = dvdnav_get_audio_logical_stream(nav, Channel); audioStreamLanguageCode = dvdnav_audio_stream_to_lang(nav, logchan >= 0 ? logchan : Channel); audioStreamLanguageCode = audioStreamLanguageCode >> 8 | (audioStreamLanguageCode & 0xFF) << 8; } return audioStreamLanguageCode; } uint16_t cDvdPlayer::GetSubtitleLanguageCode(int Channel) const { uint16_t subtitleStreamLanguageCode = 0xFFFF; if (nav) { int logchan = dvdnav_get_spu_logical_stream(nav, Channel); subtitleStreamLanguageCode = dvdnav_spu_stream_to_lang(nav, (logchan >= 0 ? logchan : Channel) & SubpStreamMask); subtitleStreamLanguageCode = subtitleStreamLanguageCode >> 8 | (subtitleStreamLanguageCode & 0xFF) << 8; } return subtitleStreamLanguageCode; } char *cDvdPlayer::GetTitleString() const { return strdup(title_str); } void cDvdPlayer::SetTitleString() { static const char *title_holder = NULL; if (title_str) { free(title_str); title_str = NULL; } if (!DVDActiveAndRunning()) { title_str = strdup(dummy_title); return; } if (dvdnav_get_title_string(nav, &title_holder) == DVDNAV_STATUS_OK) title_str = strdup(title_holder); else title_str = strdup(dummy_title); } char *cDvdPlayer::GetTitleInfoString() const { return strdup(titleinfo_str); } void cDvdPlayer::SetTitleInfoString() { if (titleinfo_str) { free(titleinfo_str); titleinfo_str = NULL; } if (!DVDActiveAndRunning()) { titleinfo_str = strdup(dummy_title); return; } int angleNumber = -1; int angleNumbers = -1; int chapterNumber = -1; int chapterNumbers = -1; int titleNumber = -1; int titleNumbers = -1; dvdnav_get_number_of_titles(nav, &titleNumbers); dvdnav_current_title_info(nav, &titleNumber, &chapterNumber); dvdnav_get_number_of_parts(nav, titleNumber, &chapterNumbers); if (titleNumber >= 1) { /* no menu here */ /* Reflect angle info if appropriate */ dvdnav_get_angle_info(nav, &angleNumber, &angleNumbers); } //Menu's has no titleNumbers and chapterNumbers (see dvdnav.h) if (titleNumber == 0) asprintf(&titleinfo_str, "%d/%d %d", titleNumber, titleNumbers, chapterNumber); else if (angleNumbers > 1) asprintf(&titleinfo_str, "%d/%d %d/%d %d/%d", titleNumber, titleNumbers, chapterNumber, chapterNumbers, angleNumber, angleNumbers); else asprintf(&titleinfo_str, "%d/%d %d/%d", titleNumber, titleNumbers, chapterNumber, chapterNumbers); return; } void cDvdPlayer::GetAudioLanguageStr(const char **AudioLanguageStr) const { static char buffer[100]; char *audioTypeDescr = NULL; if (!DVDActiveAndRunning()) { *AudioLanguageStr = "n.a."; return; } switch (currentNavAudioTrackType) { case aAC3: audioTypeDescr = "ac3"; break; case aDTS: audioTypeDescr = "dts"; break; case aLPCM: audioTypeDescr = "pcm"; break; case aMPEG: audioTypeDescr = "mp2"; break; default: audioTypeDescr = "non"; break; } uint16_t audioStreamLanguageCode = GetAudioTrackLanguageCode(currentNavAudioTrack); char audioLanguageStr[3] = {audioStreamLanguageCode, audioStreamLanguageCode >> 8, 0}; if (GetAudioStreamNumbers() > 1) sprintf(buffer,"%s %d/%d %s", audioStreamLanguageCode != 0xFFFF ? audioLanguageStr : "", GetCurrentNavAudioTrackIdx() + 1, GetAudioStreamNumbers() - 1, audioTypeDescr); else sprintf(buffer,"%s %s", audioStreamLanguageCode != 0xFFFF ? audioLanguageStr : "", audioTypeDescr); *AudioLanguageStr = buffer; } void cDvdPlayer::GetSubtitleLanguageStr(const char **SubtitleLanguageStr) const { static char buffer[100]; if (!DVDActiveAndRunning() || GetSubtitleStreamNumbers() == 0) { *SubtitleLanguageStr = "n.a."; return; } int subtitleStreamLanguageCode = GetSubtitleLanguageCode(currentNavSubpStream); char subtitleLanguageStr[3] = {subtitleStreamLanguageCode, subtitleStreamLanguageCode >> 8, 0}; if(GetSubtitleStreamNumbers() > 2) sprintf(buffer,"%s %d/%d", subtitleStreamLanguageCode !=0xFFFF ? subtitleLanguageStr : "", GetCurrentNavSubpStreamIdx(), GetSubtitleStreamNumbers() - 1); else if(GetSubtitleStreamNumbers() > 1) sprintf(buffer,"%s", subtitleStreamLanguageCode != 0xFFFF ? subtitleLanguageStr : "n.a."); *SubtitleLanguageStr = buffer; } char *cDvdPlayer::GetAspectString() const { return strdup(aspect_str); } void cDvdPlayer::SetAspectString() { if (aspect_str) { free(aspect_str); aspect_str = NULL; } if (!DVDActiveAndRunning()) { aspect_str = strdup(dummy_n_a); return; } switch (dvdnav_get_video_aspect(nav)) { case 0: asprintf(&aspect_str, " 4:3"); break; case 2: asprintf(&aspect_str, "16:9_"); break; case 3: asprintf(&aspect_str, "16:9"); break; default: aspect_str = strdup(dummy_n_a); } } bool cDvdPlayer::GetReplayMode(bool &Play, bool &Forward, int &Speed) { Play = (playMode == pmPlay || playMode == pmFast); Forward = (playDir == pdForward); if (playMode == pmFast || playMode == pmSlow) Speed = Setup.MultiSpeedMode ? abs(trickSpeed - NORMAL_SPEED) : 0; else Speed = -1; return true; } int cDvdPlayer::callRootMenu(void) { DEBUGDVD("cDvdPlayer::callRootMenu()\n"); LOCK_THREAD; StillSkip(); SetCurrentNavAudioTrackUsrLocked(false); return nav ? dvdnav_menu_call(nav, DVD_MENU_Root) : 0; } int cDvdPlayer::callTitleMenu(void) { DEBUGDVD("cDvdPlayer::callTitleMenu()\n"); LOCK_THREAD; StillSkip(); SetCurrentNavAudioTrackUsrLocked(false); return nav ? dvdnav_menu_call(nav, DVD_MENU_Title) : 0; } int cDvdPlayer::callSubpMenu(void) { DEBUGDVD("cDvdPlayer::callSubpMenu()\n"); LOCK_THREAD; StillSkip(); return nav ? dvdnav_menu_call(nav, DVD_MENU_Subpicture) : 0; } int cDvdPlayer::callAudioMenu(void) { DEBUGDVD("cDvdPlayer::callAudioMenu()\n"); LOCK_THREAD; StillSkip(); SetCurrentNavAudioTrackUsrLocked(false); return nav ? dvdnav_menu_call(nav, DVD_MENU_Audio) : 0; } vdr-plugin-dvd-0.3.7/player-dvd.h000066400000000000000000000324611415711736600166240ustar00rootroot00000000000000/* * DVD Player plugin for VDR * * Copyright (C) 2001.2002 Andreas Schultz * * This code is distributed under the terms and conditions of the * GNU GENERAL PUBLIC LICENSE. See the file COPYING for details. * */ #ifndef __PLAYER_DVD_H #define __PLAYER_DVD_H #define this _this #include #include #undef this #include #include #include #include #include #include "common-dvd.h" class cDvdPlayer; #include "dvdspu.h" #include "ca52.h" class IntegerListObject : public cListObject { private: int value; public: IntegerListObject() { value=0; } IntegerListObject( const IntegerListObject & v ) { value=v.value; } IntegerListObject( int i ) { value=i; } int getValue() const { return value; } void setValue(int v) { value=v; } virtual bool operator==(const cListObject & ListObject ) const { return value == ((IntegerListObject *)&ListObject)->value; } virtual bool operator<(const cListObject & ListObject ) /* const */ { return value < ((IntegerListObject *)&ListObject)->value; } virtual bool operator>(const cListObject & ListObject ) const { return value > ((IntegerListObject *)&ListObject)->value; } operator int () const { return value; } }; class cDvdPlayerControl ; class cIframeAssembler; class cDVDPlayerResume; class cDvdPlayer : public cPlayer, cThread { private: enum ePlayModes { pmPlay, pmPause, pmSlow, pmFast, pmStill }; enum ePlayDirs { pdForward, pdBackward }; enum ePacketType { pktNone=0, pktVideo=1, pktAudio=2, pktIFrame=4, pktSpu=8 }; cDvdPlayerControl *controller; cSPUassembler SPUassembler; cSpuDecoder *SPUdecoder; A52decoder a52dec; #ifdef NOT_YET cDTSdecoder dtsdec; #endif int hsize; int vsize; int vaspect; cIframeAssembler *iframeAssembler; int IframeCnt; uint8_t * event_buf; cRingBufferFrame *ringBuffer; cFrame *rframe, *pframe; dvdnav_cell_change_event_t lastCellEventInfo ; uint32_t pgcCurrentBlockNum, pgcTotalBlockNum; int64_t pgcTotalTicks; int64_t pgcTicksPerBlock; bool UpdateBlockInfo(void); bool isInMenuDomain; bool isInFeature; int dvd_aspect; int dvd_scaleperm; void UpdateVTSInfo(void); bool skipPlayVideo; int fastWindFactor; uint32_t cntVidBlocksPlayed; uint32_t cntAudBlocksPlayed; int currentNavSubpStream; bool currentNavSubpStreamUsrLocked; bool changeNavSubpStreamOnceInSameCell; cList navSubpStreamSeen; void clearSeenSubpStream(void); void setAllSubpStreams(void); int SearchSubpStream(int SubpStreamId) const; void notifySeenSubpStream( int navSubpStream ); int SetSubpStream(int id); bool GetCurrentNavSubpStreamUsrLocked(void) const ; void SetCurrentNavSubpStreamUsrLocked(bool lock) ; uint32_t stillTimer; dvdnav_t *nav; pci_t *current_pci; int prev_e_ptm; int ptm_offs; uint8_t stillFrame; uint8_t lastFrameType; uint64_t VideoPts; uint64_t stcPTS; uint64_t pktpts; uint64_t stcPTSAudio; uint64_t stcPTSLastAudio; uint64_t pktptsAudio; uint64_t pktptsLastAudio; uint64_t pictureNumber; bool pictureFlip; int currentNavAudioTrack; uint16_t currentNavAudioTrackLangCode; int currentNavAudioTrackType; // aAC3, aDTS, aLPCM, aMPEG int lastNavAudioTrackType; // aAC3, aDTS, aLPCM, aMPEG bool currentNavAudioTrackUsrLocked; cList navAudioTracksSeen; void clearSeenAudioTrack(void); void setAllAudioTracks(void); int notifySeenAudioTrack(int navAudioTrack); int SearchAudioStream(int AudioStreamId) const; bool SetCurrentNavAudioTrackType(int atype); static int Speeds[]; bool running; bool active; ePlayModes playMode; ePlayDirs playDir; int trickSpeed; static const char * dummy_title; static const char * dummy_n_a; char * title_str; char * titleinfo_str; char * aspect_str; void SetTitleString( void ) ; void SetTitleInfoString( void ); void SetAspectString( void ); //player stuff void StillSkip(void); void TrickSpeed(int Increment); void Empty(bool emptyDeviceToo=true); void StripAudioPackets(uchar *b, int Length, uchar Except = 0x00); int Resume(void); bool Save(void); static bool BitStreamOutActive; static bool HasBitStreamOut; static bool SoftDeviceOutActive; // currently used to switch for xine static bool HasSoftDeviceOut; // currently used to switch for xine static bool HasReelbox; //dvd stuff int currButtonN; void ClearButtonHighlight(void); void UpdateButtonHighlight(dvdnav_highlight_event_t *hlevt); void DoScaleMode(int &vaspect); cSpuDecoder::eScaleMode getSPUScaleMode(); void SendIframe(bool doSend); int playPacket(unsigned char *&cache_buf, bool trickMode, bool noAudio); void playSPU(int spuId, unsigned char *data, int datalen); uint16_t GetAudioTrackLanguageCode(int channel) const; int GetAudioStreamNumbers(void) const ; uint16_t GetSubtitleLanguageCode(int Channel) const; int GetSubtitleStreamNumbers(void) const ; //resuming /** * the resume database */ cDVDPlayerResume* resume; /** * GetDVDResumeKey(): * computes a (hopefully) unique id for storing the resume data of the current disc. * * this get returns a new allocated memory area .. * must be freed by callee .. */ char* GetDVDResumeKey() const; /** * SaveResume(): * handles everything to save the current position on the disc for later resuming. */ void SaveResume(); /** * LoadResume(): * loads the resume data for the current disc and stores it in the given arguments. * returns false if no resume data for the disc can be found or and error occured while loading. */ bool LoadResume(int& title, int& chapter, int64_t& second); protected: //Player virtual void Activate(bool On); virtual void Action(void); void DeviceReset(void); void DeviceClear(void); void DevicePlay(void); public: /** * returns the CurrentFrame and TotalFrame of the actual PGC ! * the timebase is accurate (BlockNumber/Ticks), but the resulting * "frame" number is calculated using the magic number FRAMESPERSEC ;-) * * optional snap to the next IFrame (not functional now) */ bool GetIndex(int &CurrentFrame, int &TotalFrame, bool SnapToIFrame); bool GetReplayMode(bool &Play, bool &Forward, int &Speed) ; void SetAudioTrack(eTrackType Type, const tTrackId *TrackId); protected: void seenSpuPts(uint64_t pts); uint64_t time_ticks(void); uint64_t delay_ticks(uint64_t ticks); public: static const int MaxAudioTracks; static const int AudioTrackMask; static const int AC3AudioTrackMask; static const int MaxSubpStreams; static const int SubpStreamMask; cDvdPlayer(void); virtual ~cDvdPlayer(); bool Active(void) const { return active ; } bool DVDActiveAndRunning(void) const { return active && nav != NULL && running; } bool DVDRemoveable(void) const { return !active && !running; } void GetAudioLanguageStr(const char **AudioLanguageStr) const ; void GetSubtitleLanguageStr( const char **SubtitleLanguageStr ) const ; // -- control stuff -- void setController (cDvdPlayerControl *ctrl ); bool IsDvdNavigationForced() const ; void DrawSPU(); void HideSPU(); void EmptySPU(); void Pause(void); void Play(void); void Stop(void); void Forward(void); void Backward(void); /** * these getter returns a new allocated memory area .. * must be freed by callee .. */ char *GetTitleString(void) const ; char *GetTitleInfoString(void) const ; char *GetAspectString(void) const ; int GetProgramNumber(void) const ; int GetCellNumber(void) const ; /** * returns the PG (e.g. chapter) lenght in ticks * * 90000 ticks are 1 second, acording to MPEG ! */ int64_t GetPGLengthInTicks(void) ; /** * returns the PGC (e.g. whole title) lenght in ticks * * 90000 ticks are 1 second, acording to MPEG ! */ int64_t GetPGCLengthInTicks(void) ; /** * returns the Ticks and TotalTicks according to the given * BlockNum, TotalBlockNum of the actual PGC ! * * the TotalBlockNum of the actual PGC is fetched ! * * 90000 ticks are 1 second, acording to MPEG ! */ void BlocksToPGCTicks(uint32_t BlockNum, int64_t &Ticks, int64_t &TotalTicks) ; /** * returns the CurrentBlockNum and TotalBlockNum according to the given * Ticks, TotalTicks of the actual PGC ! * * the TotalTicks of the actual PGC is fetched ! * * 90000 ticks are 1 second, acording to MPEG ! */ void PGCTicksToBlocks(int64_t Ticks, uint32_t &BlockNum, uint32_t &TotalBlockNum) ; bool GetPositionInSec(int64_t &CurrentSec, int64_t &TotalSec) ; bool GetPositionInTicks(int64_t &CurrentTicks, int64_t &TotalTicks) ; int getWidth() const { return hsize; } int getHeight() const { return vsize; } int getAspect() const { return vaspect; } /** * we assume FRAMESPERSEC ! */ int SkipFrames(int Frames); void SkipSeconds(int Seconds); /** * set the position of the actual PGC to the given Seconds */ void Goto(int Seconds, bool Still = false); int GotoAngle(int Angle); /** * jump to the next Angle (rotate) */ void NextAngle(void); /** * jump to the next Title (rotate) */ void NextTitle(void); /** * goto to the Title * * return set title .. */ // GotoTitle now optionally takes a chapter to seek to in the given title int GotoTitle(int Title, int Chapter = 1); /** * jump to the previous Title (rotate) */ void PreviousTitle(void); /** * goto to the Part * * return set Part .. */ int GotoPart(int Part); /** * jump to the next Part (rotate) */ void NextPart(void); /** * jump to the previous Part (rotate) */ void PreviousPart(void); /** * jump to the next PG */ void NextPG(void); /** * jump to the previous PG */ void PreviousPG(void); int GetCurrentNavSubpStream(void) const ; int GetCurrentNavSubpStreamIdx(void) const ; int NextSubpStream(); bool GetCurrentNavAudioTrackUsrLocked(void) const ; void SetCurrentNavAudioTrackUsrLocked(bool lock); int GetCurrentNavAudioTrack(void) const ; int GetCurrentNavAudioTrackIdx(void) const ; int GetCurrentNavAudioTrackType(void) const ; // aAC3, aDTS, aLPCM, aMPEG void selectUpButton(void); void selectDownButton(void); void selectLeftButton(void); void selectRightButton(void); void activateButton(void); int callRootMenu(void); int callTitleMenu(void); int callSubpMenu(void); int callAudioMenu(void); bool IsInMenuDomain() const; bool IsInStillFrame() const ; bool IsInMenuDomainOrStillFrame() const ; // -- callbacks -- void seenAPTS(uint64_t pts); void seenVPTS(uint64_t pts); int cbPlayVideo(uchar *Data, int Length); int cbPlayAudio(uchar *Data, int Length); /** * 90000 ticks are 1 second, acording to MPEG ! */ static const char *PTSTicksToHMSm(int64_t ticks, bool WithMS=false); static int64_t PTSTicksToMilliSec(int64_t ticks) { return ticks / 90L; } static int64_t PTSTicksToSec(int64_t ticks) { return ticks / 90000L; } }; #define CIF_MAXSIZE 512 // --- cDvdPlayer --------------------------------------------------- inline bool cDvdPlayer::IsInMenuDomain() const { // return isInMenuDomain; return (current_pci && current_pci->hli.hl_gi.hli_ss); } inline bool cDvdPlayer::IsInStillFrame() const { return stillFrame!=0; } inline bool cDvdPlayer::IsInMenuDomainOrStillFrame() const { return IsInStillFrame()||IsInMenuDomain(); } inline int cDvdPlayer::cbPlayVideo(uchar *Data, int Length) { if (ringBuffer) { cFrame *cbFrame = new cFrame(Data, Length, ftVideo); if(cbFrame && !ringBuffer->Put(cbFrame)) DELETENULL(cbFrame); } return Length; } inline int cDvdPlayer::cbPlayAudio(uchar *Data, int Length) { if (ringBuffer) { cFrame *cbFrame = new cFrame(Data, Length, ftDolby); if(cbFrame && !ringBuffer->Put(cbFrame)) DELETENULL(cbFrame); } return Length; } // --- navigation stuff --- inline void cDvdPlayer::selectUpButton(void) { DEBUGDVD("selectUpButton\n"); if (nav && current_pci) { dvdnav_upper_button_select(nav, current_pci); } } inline void cDvdPlayer::selectDownButton(void) { DEBUGDVD("selectDownButton\n"); if (nav && current_pci) { dvdnav_lower_button_select(nav, current_pci); } } inline void cDvdPlayer::selectLeftButton(void) { DEBUGDVD("selectLeftButton\n"); if (nav && current_pci) { dvdnav_left_button_select(nav, current_pci); } } inline void cDvdPlayer::selectRightButton(void) { DEBUGDVD("selectRightButton\n"); if (nav && current_pci) { dvdnav_right_button_select(nav, current_pci); } } #endif //__PLAYER_DVD_H vdr-plugin-dvd-0.3.7/po/000077500000000000000000000000001415711736600150145ustar00rootroot00000000000000vdr-plugin-dvd-0.3.7/po/de_DE.po000066400000000000000000000031321415711736600163130ustar00rootroot00000000000000# VDR plugin language source file. # Copyright (C) 2007 # This file is distributed under the same license as the dvd-plugin package. # Marco Schluessler , 2007 # msgid "" msgstr "" "Project-Id-Version: VDR dvd-plugin 0.3.6b03\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-01-02 05:14+1100\n" "PO-Revision-Date: 2007-08-12 23:15+0200\n" "Last-Translator: Marco Schluessler \n" "Language-Team: German\n" "Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=ISO-8859-15\n" "Content-Transfer-Encoding: 8bit\n" msgid "Error.DVD$Current subp stream not seen!" msgstr "Der ausgewhlte Untertitel ist nicht vorhanden!" msgid "Plugin.DVD$turn VDR into an (almost) full featured DVD player" msgstr "verwandelt VDR in einen (fast) vollstndigen DVD Spieler" msgid "Plugin.DVD$DVD" msgstr "DVD" msgid "Error.DVD$Error opening DVD!" msgstr "Fehler beim ffnen der DVD!" msgid "Error.DVD$Error fetching data from DVD!" msgstr "Fehler beim Lesen von der DVD!" msgid "Setup.DVD$Preferred menu language" msgstr "Bevorzugte Sprache fr Mens" msgid "Setup.DVD$Preferred audio language" msgstr "Bevorzugte Sprache fr Dialog" msgid "Setup.DVD$Preferred subtitle language" msgstr "Bevorzugte Sprache fr Untertitel" msgid "Setup.DVD$Player region code" msgstr "Regionalkode fr DVD Spieler" msgid "Setup.DVD$Display subtitles" msgstr "Untertitel anzeigen" msgid "Setup.DVD$Hide Mainmenu Entry" msgstr "Hauptmeneintrag verstecken" msgid "Setup.DVD$ReadAHead" msgstr "ReadAHead" msgid "Setup.DVD$Gain (analog)" msgstr "Verstrkung (analog)" vdr-plugin-dvd-0.3.7/po/ru_RU.po000066400000000000000000000032571415711736600164170ustar00rootroot00000000000000# VDR plugin language source file. # Copyright (C) 2007 # This file is distributed under the same license as the dvd-plugin package. # Marco Schluessler , 2007 # msgid "" msgstr "" "Project-Id-Version: VDR dvd-plugin 0.3.6b03\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-01-02 05:14+1100\n" "PO-Revision-Date: 2007-08-12 23:15+0200\n" "Last-Translator: Marco Schluessler \n" "Language-Team: Russian\n" "Language: ru\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "Error.DVD$Current subp stream not seen!" msgstr "Поток не найден!" msgid "Plugin.DVD$turn VDR into an (almost) full featured DVD player" msgstr "Проигрыватель DVD" msgid "Plugin.DVD$DVD" msgstr "DVD" msgid "Error.DVD$Error opening DVD!" msgstr "Ошибка открытия DVD!" msgid "Error.DVD$Error fetching data from DVD!" msgstr "Ошибка получения данных с DVD!" msgid "Setup.DVD$Preferred menu language" msgstr "Предпочтительный язык меню" msgid "Setup.DVD$Preferred audio language" msgstr "Предпочтительный язык звука" msgid "Setup.DVD$Preferred subtitle language" msgstr "Предпочтииельный язык субтитров" msgid "Setup.DVD$Player region code" msgstr "Код региона" msgid "Setup.DVD$Display subtitles" msgstr "Показывать субтитры" msgid "Setup.DVD$Hide Mainmenu Entry" msgstr "Скрыть основное меню" msgid "Setup.DVD$ReadAHead" msgstr "ReadAHead" msgid "Setup.DVD$Gain (analog)" msgstr "Усиление (аналог)" vdr-plugin-dvd-0.3.7/setup-dvd.c000066400000000000000000000066421415711736600164650ustar00rootroot00000000000000/* * DVD Player plugin for VDR * * Copyright (C) 2001.2002 Andreas Schultz * * This code is distributed under the terms and conditions of the * GNU GENERAL PUBLIC LICENSE. Read the file COPYING for details. */ #include #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "setup-dvd.h" #include "i18n.h" #ifdef __QNXNTO__ #include #endif cDVDSetup DVDSetup; // --- cDVDSetup ----------------------------------------------------------- cDVDSetup::cDVDSetup(void) { MenuLanguage = 0; AudioLanguage = 0; SpuLanguage = 0; PlayerRCE = 2; ShowSubtitles = 0; HideMainMenu = 0; ReadAHead = 0; Gain = 4; AC3dynrng = 0; } bool cDVDSetup::SetupParse(const char *Name, const char *Value) { // Parse your own setup parameters and store their values. if (!strcasecmp(Name, "MenuLanguage")) MenuLanguage = atoi(Value); else if (!strcasecmp(Name, "AudioLanguage")) AudioLanguage = atoi(Value); else if (!strcasecmp(Name, "SpuLanguage")) SpuLanguage = atoi(Value); else if (!strcasecmp(Name, "PlayerRCE")) PlayerRCE = atoi(Value); else if (!strcasecmp(Name, "ShowSubtitles")) ShowSubtitles = atoi(Value); else if (!strcasecmp(Name, "HideMainMenu")) HideMainMenu = atoi(Value); else if (!strcasecmp(Name, "ReadAHead")) ReadAHead = atoi(Value); else if (!strcasecmp(Name, "Gain")) Gain = atoi(Value); else return false; return true; } // --- cMenuSetupDVD -------------------------------------------------------- cMenuSetupDVD::cMenuSetupDVD(void) { data = DVDSetup; SetSection(tr("Plugin.DVD$DVD")); #if VDRVERSNUM >= 10507 Add(new cMenuEditStraItem(tr("Setup.DVD$Preferred menu language"), &data.MenuLanguage, 22, ISO639code)); Add(new cMenuEditStraItem(tr("Setup.DVD$Preferred audio language"), &data.AudioLanguage, 22, ISO639code)); Add(new cMenuEditStraItem(tr("Setup.DVD$Preferred subtitle language"), &data.SpuLanguage, 22, ISO639code)); #else Add(new cMenuEditStraItem(tr("Setup.DVD$Preferred menu language"), &data.MenuLanguage, I18nNumLanguages, I18nLanguages())); Add(new cMenuEditStraItem(tr("Setup.DVD$Preferred audio language"), &data.AudioLanguage, I18nNumLanguages, I18nLanguages())); Add(new cMenuEditStraItem(tr("Setup.DVD$Preferred subtitle language"), &data.SpuLanguage, I18nNumLanguages, I18nLanguages())); #endif Add(new cMenuEditIntItem( tr("Setup.DVD$Player region code"), &data.PlayerRCE)); Add(new cMenuEditBoolItem(tr("Setup.DVD$Display subtitles"), &data.ShowSubtitles)); Add(new cMenuEditBoolItem(tr("Setup.DVD$Hide Mainmenu Entry"), &data.HideMainMenu)); Add(new cMenuEditBoolItem(tr("Setup.DVD$ReadAHead"), &data.ReadAHead)); Add(new cMenuEditIntItem( tr("Setup.DVD$Gain (analog)"), &data.Gain, 0, 10)); } void cMenuSetupDVD::Store(void) { DVDSetup = data; SetupStore("MenuLanguage", DVDSetup.MenuLanguage ); SetupStore("AudioLanguage", DVDSetup.AudioLanguage ); SetupStore("SpuLanguage", DVDSetup.SpuLanguage ); SetupStore("PlayerRCE", DVDSetup.PlayerRCE ); SetupStore("ShowSubtitles", DVDSetup.ShowSubtitles ); SetupStore("HideMainMenu", DVDSetup.HideMainMenu ); SetupStore("ReadAHead", DVDSetup.ReadAHead ); SetupStore("Gain", DVDSetup.Gain ); } vdr-plugin-dvd-0.3.7/setup-dvd.h000066400000000000000000000015151415711736600164640ustar00rootroot00000000000000/* * DVD Player plugin for VDR * * Copyright (C) 2001.2002 Andreas Schultz * * This code is distributed under the terms and conditions of the * GNU GENERAL PUBLIC LICENSE. See the file COPYING for details. * */ #ifndef __SETUP_DVD_H #define __SETUP_DVD_H #include class cDVDSetup { public: int MenuLanguage; int AudioLanguage; int SpuLanguage; int PlayerRCE; int ShowSubtitles; int HideMainMenu; int ReadAHead; int Gain; // AC3 stuff int AC3dynrng; public: cDVDSetup(void); bool SetupParse(const char *Name, const char *Value); }; class cMenuSetupDVD : public cMenuSetupPage { private: cDVDSetup data; protected: virtual void Store(void); public: cMenuSetupDVD(void); }; extern cDVDSetup DVDSetup; #endif // __SETUP_DVD_H vdr-plugin-dvd-0.3.7/tools-dvd.h000066400000000000000000000053031415711736600164630ustar00rootroot00000000000000/* * DVD Player plugin for VDR * * Copyright (C) 2001.2002 Andreas Schultz * * This code is distributed under the terms and conditions of the * GNU GENERAL PUBLIC LICENSE. See the file COPYING for details. * */ #ifndef __TOOLS_DVD_H #define __TOOLS_DVD_H #include #include #include #ifdef __QNXNTO__ #include #endif #include "mpegtypes.h" #ifndef AARONS_TYPES #define AARONS_TYPES typedef unsigned long long uint_64; #endif class cPStream { public: static bool packetStart(uint8_t * &data, int len) { while (len > 6 && !(data[0] == 0x00 && data[1] == 0x00 && data[2] == 0x01)) { data++; len--; } return (data[0] == 0x00 && data[1] == 0x00 && data[2] == 0x01); } static int packetType (const uint8_t *data) { return data[3]; } static int stuffingLength (const uint8_t *data) { return data[13] & 0x07; } static int packetLength (const uint8_t *data) { return (data[4] << 8) + data[5] + 6; } static int PESHeaderLength(const uint8_t *data) { return (data[8]); } static uint64_t fromPTS(const uint8_t *p) { uint64_t lpts = 0; lpts = (((uint64_t)p[0]) & 0x0e) << 29; lpts |= ( (uint64_t)p[1]) << 22; lpts |= (((uint64_t)p[2]) & 0xfe) << 14; lpts |= ( (uint64_t)p[3]) << 7; lpts |= (((uint64_t)p[4]) & 0xfe) >> 1; return lpts; } static void toPTS(uint8_t *p, uint64_t lpts) { p[0] = ((uint8_t)(lpts >> 29) & 0x0e) | 0x21; p[1] = (uint8_t)(lpts >> 22); p[2] = 0x01 | (uint8_t)(lpts >> 14); p[3] = (uint8_t)(lpts >> 7); p[4] = 0x01 | (uint8_t)(lpts << 1); } /* * 28 20 13 5 * 7654 3210 7654 3210 7654 3210 7654 3210 7654 3210 7654 3210 * 01xx x1xx xxxx xxxx xxxx x1xx xxxx xxxx xxxx x1ee eeee eee1 */ static uint32_t fromSCR(const uint8_t *data) { uint32_t ret; ret = (((data[0] & 0x38) >> 1) | (data[0] & 0x03)) << 28; ret |= data[1] << 20; ret |= (((data[2] & 0xF8) >> 1) | (data[2] & 0x03)) << 13; ret |= data[3] << 5; ret |= data[4] >> 3; return ret; } static uint8_t fromSCRext(const uint8_t *data) { uint8_t ret; ret = (data[0] & 0x03) << 7; ret |= data[1] >> 1; return ret; } static uint16_t fromMUXrate(const uint8_t *data) { uint16_t ret; ret = data[0] << 14; ret |= data[1] << 6; ret |= data[2] >> 2; return ret; } }; #endif // __TOOLS_DVD_H