From 49de4abb667134bc79b87562793106136b14a985 Mon Sep 17 00:00:00 2001 From: cvs2svn Date: Mon, 28 Apr 2008 20:53:08 +0000 Subject: This commit was manufactured by cvs2svn to create branch 'unlabeled-1.34.2'. --- COPYING | 340 -- HISTORY | 392 -- Makefile | 555 --- README | 643 --- black_720x576.mpg | Bin 8815 -> 0 bytes config.c | 806 ---- config.h | 393 -- device.c | 1696 ------- device.h | 280 -- dummy_player.c | 102 - dummy_player.h | 39 - equalizer.c | 149 - equalizer.h | 36 - examples/Live Radio/BBC Radio 4 Live.m3u | 4 - examples/Live Radio/BBC World Service.ram | 1 - examples/remote.conf.example | 60 - frontend.c | 898 ---- frontend.h | 159 - frontend_local.c | 463 -- frontend_local.h | 74 - frontend_svr.c | 1870 -------- frontend_svr.h | 134 - i18n.c | 4331 ------------------ i18n.h | 30 - logdefs.h | 187 - media_player.c | 1319 ------ media_player.h | 125 - menu.c | 1089 ----- menu.h | 53 - menuitems.c | 215 - menuitems.h | 104 - mpg2c.c | 50 - nosignal_720x576.mpg | Bin 13195 -> 0 bytes osd.c | 504 --- osd.h | 36 - patches/vdr-1.4.6-Smooth_FastForward.patch | 79 - po/cs_CZ.po | 615 --- po/de_DE.po | 614 --- po/fi_FI.po | 616 --- po/it_IT.po | 613 --- po/ru_RU.po | 615 --- setup_menu.c | 1957 --------- setup_menu.h | 27 - tools.c | 23 - tools/backgroundwriter.c | 486 --- tools/backgroundwriter.h | 161 - tools/bitstream.h | 177 - tools/cxsocket.c | 430 -- tools/cxsocket.h | 195 - tools/debug_mutex.h | 206 - tools/display_message.h | 73 - tools/functor.h | 47 - tools/functorimpl.h | 150 - tools/future.h | 87 - tools/general_remote.h | 27 - tools/h264.c | 188 - tools/h264.h | 49 - tools/http.c | 434 -- tools/http.h | 147 - tools/iconv.h | 100 - tools/iso639.h | 171 - tools/listiter.h | 83 - tools/mpeg.c | 51 - tools/mpeg.h | 55 - tools/pes.c | 152 - tools/pes.h | 101 - tools/playlist.c | 1000 ----- tools/playlist.h | 132 - tools/rtcp.h | 134 - tools/rtp.h | 100 - tools/sap.h | 207 - tools/sdp.h | 95 - tools/time_pts.c | 172 - tools/time_pts.h | 43 - tools/timer.c | 288 -- tools/timer.h | 296 -- tools/udp_buffer.h | 136 - tools/udp_pes_scheduler.h | 108 - tools/vdrdiscovery.c | 280 -- tools/vdrdiscovery.h | 38 - vdrlogo_32x32.c | 220 - vdrlogo_720x576.mpg | Bin 22739 -> 0 bytes xine/post.c | 906 ---- xine/post.h | 99 - xine/post_util.h | 144 - xine_fbfe_frontend.c | 321 -- xine_frontend.c | 1668 ------- xine_frontend.h | 102 - xine_frontend_lirc.c | 265 -- xine_frontend_main.c | 723 --- xine_input_vdr.c | 6542 ---------------------------- xine_input_vdr.h | 54 - xine_input_vdr_net.h | 167 - xine_osd_command.h | 155 - xine_post_audiochannel.c | 323 -- xine_post_autocrop.c | 1623 ------- xine_post_swscale.c | 1730 -------- xine_sxfe_frontend.c | 1495 ------- xineliboutput.c | 277 -- 99 files changed, 45709 deletions(-) delete mode 100644 COPYING delete mode 100644 HISTORY delete mode 100644 Makefile delete mode 100644 README delete mode 100644 black_720x576.mpg delete mode 100644 config.c delete mode 100644 config.h delete mode 100644 device.c delete mode 100644 device.h delete mode 100644 dummy_player.c delete mode 100644 dummy_player.h delete mode 100644 equalizer.c delete mode 100644 equalizer.h delete mode 100755 examples/Live Radio/BBC Radio 4 Live.m3u delete mode 100644 examples/Live Radio/BBC World Service.ram delete mode 100644 examples/remote.conf.example delete mode 100644 frontend.c delete mode 100644 frontend.h delete mode 100644 frontend_local.c delete mode 100644 frontend_local.h delete mode 100644 frontend_svr.c delete mode 100644 frontend_svr.h delete mode 100644 i18n.c delete mode 100644 i18n.h delete mode 100644 logdefs.h delete mode 100644 media_player.c delete mode 100644 media_player.h delete mode 100644 menu.c delete mode 100644 menu.h delete mode 100644 menuitems.c delete mode 100644 menuitems.h delete mode 100644 mpg2c.c delete mode 100644 nosignal_720x576.mpg delete mode 100644 osd.c delete mode 100644 osd.h delete mode 100644 patches/vdr-1.4.6-Smooth_FastForward.patch delete mode 100644 po/cs_CZ.po delete mode 100644 po/de_DE.po delete mode 100644 po/fi_FI.po delete mode 100644 po/it_IT.po delete mode 100644 po/ru_RU.po delete mode 100644 setup_menu.c delete mode 100644 setup_menu.h delete mode 100644 tools.c delete mode 100644 tools/backgroundwriter.c delete mode 100644 tools/backgroundwriter.h delete mode 100644 tools/bitstream.h delete mode 100644 tools/cxsocket.c delete mode 100644 tools/cxsocket.h delete mode 100644 tools/debug_mutex.h delete mode 100644 tools/display_message.h delete mode 100644 tools/functor.h delete mode 100644 tools/functorimpl.h delete mode 100644 tools/future.h delete mode 100644 tools/general_remote.h delete mode 100644 tools/h264.c delete mode 100644 tools/h264.h delete mode 100644 tools/http.c delete mode 100644 tools/http.h delete mode 100644 tools/iconv.h delete mode 100644 tools/iso639.h delete mode 100644 tools/listiter.h delete mode 100644 tools/mpeg.c delete mode 100644 tools/mpeg.h delete mode 100644 tools/pes.c delete mode 100644 tools/pes.h delete mode 100644 tools/playlist.c delete mode 100644 tools/playlist.h delete mode 100644 tools/rtcp.h delete mode 100644 tools/rtp.h delete mode 100644 tools/sap.h delete mode 100644 tools/sdp.h delete mode 100644 tools/time_pts.c delete mode 100644 tools/time_pts.h delete mode 100644 tools/timer.c delete mode 100644 tools/timer.h delete mode 100644 tools/udp_buffer.h delete mode 100644 tools/udp_pes_scheduler.h delete mode 100644 tools/vdrdiscovery.c delete mode 100644 tools/vdrdiscovery.h delete mode 100644 vdrlogo_32x32.c delete mode 100644 vdrlogo_720x576.mpg delete mode 100644 xine/post.c delete mode 100644 xine/post.h delete mode 100644 xine/post_util.h delete mode 100644 xine_fbfe_frontend.c delete mode 100644 xine_frontend.c delete mode 100644 xine_frontend.h delete mode 100644 xine_frontend_lirc.c delete mode 100644 xine_frontend_main.c delete mode 100644 xine_input_vdr.c delete mode 100644 xine_input_vdr.h delete mode 100644 xine_input_vdr_net.h delete mode 100644 xine_osd_command.h delete mode 100644 xine_post_audiochannel.c delete mode 100644 xine_post_autocrop.c delete mode 100644 xine_post_swscale.c delete mode 100644 xine_sxfe_frontend.c delete mode 100644 xineliboutput.c diff --git a/COPYING b/COPYING deleted file mode 100644 index f90922ee..00000000 --- a/COPYING +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 Lesser 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 Lesser General -Public License instead of this License. diff --git a/HISTORY b/HISTORY deleted file mode 100644 index 11d97149..00000000 --- a/HISTORY +++ /dev/null @@ -1,392 +0,0 @@ -VDR Plugin 'xineliboutput' Revision History -------------------------------------------- - -????-??-??: Version 1.0.1 -- - -2008-04-14: Version 1.0.0 -- Added Italian translations (Thanks to Gringo) -- Added Czech translations (Thanks to Maya) -- Added HUD OSD (Blend OSD using graphics hardware) and --hud command-line option. - (Thanks to Antti Seppälä and Rolf Ahrenberg) -- Added support for libextractor metadata parsing library (Petri Helin) -- Added service interface for launching media player (Suggested by Tobias Grimm) -- Added configuration options for unsharp and denoise3d post plugins (Petri Helin) -- Fixed the case when watching image files and the first one just flashes and - gets replaced by black image (Petri Helin) -- Added support for VDR 1.5.x and 1.6.0 -- Dropped legacy code for vdr-1.3.x -- Added support for xine-lib up to 1.1.11.1 -- Added support for xine-lib 1.2 hg branch -- Changed mrl syntax from xvdr[:proto]:// to xvdr[+proto]:// -- Added video softwarwe scaling support -- Added non-linear 4:3 -> 16:9 "smart" scaling -- Added configure option for video aspect ratio (Petri Helin) -- Added media player options for enabling or disabling metainfo types, metainfo - scanner and metainfo caching (Petri Helin) -- Added support for smooth fast forward (Thanks to Timo Eskola) -- Added setup option to limit trick speed -- Removed support for arts audio output -- Added setup option to change external subtitle (.sub/.srt) font size -- Added command-line option for binding to specific local interface address -- Initial support for H.264 video -- Support for HD-resolution OSD (Petri Helin). Requires patched vdr. -- Increased local frontend initialization timeout (Thanks to Mikko Vartiainen) -- Removed configuration option to disable OSD downscaling -- Improved media player playlist handling and menu (Petri Helin) -- Fixed DVD menu domain detection (Petri Helin) -- Fixed DVD title and chapter information shown on the OSD (Petri Helin) -- Improved key mappings for audio player (Petri Helin) -- Allow users to add single files to playlist as well as whole directories (Petri Helin) -- Fixed "TCP fifo full" problem -- Added hotkeys for audio delay (Thanks to Timo Eskola) -- Enabled streaming of external subtitle files for remote frontends -- Added support for multithreaded video decoding. Auto-detect number of CPUs. -- Show address of current VDR server in X title bar -- Added support to control HW aspect ratio with external script -- Added support to output video and OSD to existing X11 window -- Allow fine-tuning of SCR (should reduce frame drops/duplications and make video smoother) -- Support using ffmpeg mpeg2 video decoder instead of libmpeg2 decoder -- Improved PTS warp detection -- Restore DPMS state at exit -- Fixed sxfe window position when returning from fullscreen mode (Thanks to Timo Eskola) - -2007-05-17: Version 1.0.0rc2 - -- Workaround for xine-lib demux_mpeg_block PTS wrap issue - (this should fix daily picture freezes) -- Support for denoise3d and unsharp post plugins (Thanks to Petri Helin) -- Fixed media player random play kNext (next file) handling (Thanks to Petri Helin) -- Fixed media player MsgReplaying status messages (Thanks to Petri Helin) -- Fixed closing DVD player with Back key (Thanks to Petri Helin) -- Improved media player resume file creation -- Fixed UDP segfault -- Mac OS X build fixes (Thanks to Tero Siironen) -- Updated remote.conf example -- Added support for xine-lib software volume control - (useful with digital audio output) -- Removed (unused) decoder priority setting -- Fixed yuy2 frame grabbing -- Adapted for xine-lib 1.1.5 -- Added vdr-sxfe fullscreen and de-interlace toggling with lirc keys - "Fullscreen" and "Deinterlace" - -2007-03-17: Version 1.0.0rc1 - -- PLUGIN HOMEPAGE CHANGED - -- Fixed audio CD replay (cdda:/) -- Adapted for xine-lib 1.1.4 -- Adapted for vdr-1.5.1 (Thanks to Rolf Ahrenberg) -- Mac OS X compability fixes (Thanks to Tero Siironen) -- DXR3 added to list of output devices (experimental; Thanks to Ville Skyttä) -- Subtitle selection menu updated to use VDR audio menu skin -- New subtitle macro key handling (identical to VDR kAudio) -- Added preferred subtitle language selection for media player -- Updated trick speed modes and still image handling -- Remote mode can now survive longer network delays -- Fixed tvtime options (Thanks to Petri Helin) -- Fixed using video driver "none" -- Simple "slave mode" for remote frontends -- Added automatic re-connection to remote frontends (--reconnect option) -- Slow down DVD drive speed -- Initialize video size from stream info when playing slave streams, - (Thanks to Antti Seppälä) -- Makefile shell scripts modified to run in dash (Ubuntu). - (Thanks to realKano@directbox.com) -- Increased frame-based buffering time after channel changes -- Use iconv to translate id3 tags from utf8 to VDR charset -- Use /dev/dsp as OSS default device (Thanks to Ville Skyttä) -- Lot of small fixes and enhancements, complete log in CVS - -2007-01-07: Version 1.0.0pre7 - -- Added possibility to add files to playlist -- Added playlist menu to media player -- Added "Play Audio CD" / "Play remote Audio CD" entry to plugin menu -- Makefile modified to allow overriding default directory environment. - Using "install" to install files. (Thanks to Timo Weingärtner) -- Added metainfo caching to media player. Cached metainfo is stored to - ".xineliboutput-playlist.m3u" files by default. -- Added support for playlists inside playlists - (ex. http://.../?.pls entries in playlists) -- Added playlist HTTP download support to playlists (curl required) -- lirc forwarding updated (synced with vdr-1.4.3-2): added re-connecting to lircd. -- Lirc forwarding key repeat fixed (Thanks to Timo Ruottinen). -- Display metainfo (ID3 etc) instead of file name in (audio)player -- Fixed deadlock in audio post plugin loading and wiring - (in some cases plugins were loaded multiple times) -- Fixed buffer overflow problems in xineliboutput device polling -- Fixed buffer overflow problems in UDP packet scheduler queue -- Several new media file types added to media player -- Subtitle type .ssa added -- Parsing for .pls, .asx and .ram playlists added -- Eliminated some warnings when compiling to 64bit (Thanks to Anssi Hannula) -- Vidix(fb) added to supported video drivers (Thanks to Antti Seppälä) -- Media player/audio file browser does not anymore show video files -- When replaying music files, replay moves to next file automatically -- Decoder setup menu moved to Local setup menu - (decoder settings have effect on local frontend only) -- Implemented simple RTSP streaming support (rtsp://vdr-host:xineliboutput-port/) -- Implemented simple HTTP streaming support (http://vdr-host:xineliboutput-port/) -- Fixed control channel disconnection detection in frontend_svr.c -- Media player: Try to detect when navigating in DVD menus and change - functions of Up/Down/Left/Right/Ok/Back keys when in menus -- Added RFC2974 SAP (Session Announcement Protocol) implementation -- Now using RFC3550 RTP headers when multicasting - -2006-10-20: Version 1.0.0pre6 - -- Display Audio track languages when replaying DVDs -- Display DVD SPU track language names instead track numbers -- Improved shortcut key support -- Fixed garbage in bottom of image when using autocrop -- Fixed SCR tunning when only one TCP/PIPE client -- Fixed unscaled OSD scaling to display size when low-resolution video or - different aspect ratio -- Allow overriding default startup image -- German translations (Thanks to Udo Richter) -- Setup menu re-arranged -- Command-line given post plugin parameters are never changed at runtime -- Added string length checks to several places -- Added missing frame buffer device selection -- Support for ffmpeg post processing -- Easier configuration for tvtime post plugin in menu -- Autoplay list support for xine (patch from sf feature request #1561688) -- Removed busy loop from vdr-fbfe/vdr-sxfe when console was unavailable - -2006-09-17: Version 1.0.0pre5 - -- Allow overriding default no signal image -- Several fixes to post plugin handling -- Fixed --audio=driver:port parsing in vdr plugin -- Fixed overscan when image does not fill whole output window - (bug #1556912) -- Implemented simple MMX/SSE and YUY2 detection routines - to autocrop -- Main menu re-arranged (Thanks to Petri Helin) -- Fixed display blanking aspect ratio (bug #1554070) -- Lirc receiver accepts shorter LIRC commands (bug #1540896) -- Fixed immediate re-configuration when setup entries are - changed with repeated keys (Thanks to Petri Helin) -- Implemented audio channel selection as xine post plugin - (to select only left or right channel from stereo) -- Several minor fixes / enhancements to autocrop plugin - -2006-09-06: Version 1.0.0pre4 - -- WARNING: updated command-line options ! -- Support for HD (larger buffers with HD content) -- Simple playlist support to media player -- Fixed starting replay of new file while old file is still playing -- Fixed segfault in OSD downscaling -- Added SPU track selection for DVDs without menu -- Forcing order and location of video filter post plugins - autocrop and tvtime in post plugin chain -- Fixed replaying some older VDR recordings (video PID != 0xE0) - (Reported by Petri Helin) -- Fixed deadlock when closing xine input plugin and threads - in TCP mode (reported by Tobias Grimm) -- Fixed wrong XKeySym remote learning trigger when using fbfe - (reported by Voitto Tuomainen) -- Minor updates to playlists and file replay OSD handling -- Added trick speed modes (forward only) to DVD player -- Improved X11 fullscreen <-> window mode switching -- Improved display blanking: blank image is now generated using - last seen video frame size and aspect ratio. This should reduce - OSD resizings and re-positioning when switching channels. - -2006-08-25: Version 1.0.0pre3 - -- Fixed segfault when grabbing with remote-only frontends -- Configurable speaker configuration and spdif passthru -- Support for playlists (.m3u or whole directory) in media player -- Separate menu item for playing music -- Configuration options for letterbox cropping -- Added audio visualization support for media files - (originally supported only with DVB radio) -- Implemented image grabbing for remote frontends -- Fixed restoring primary device when using tcp transport -- Executing primary device switching in main thread context -- Added configurable overscan option (%) to crop frame borders - when using displays without overscan - -2006-08-16: Version 1.0.0pre2 - -- Xine plugins and frontends are not installed automatically. - (Suggested by Udo Richter). -- Added support for AC3 passthrough (thanks to Petri Helin) -- Automatic 4:3 letterbox to 16:9 cropping pre-version -- Added daemon mode to stand-alone frontends -- Removed possible busy loop from lirc receiver thread -- New localized texts -- Fixed local media player when remote server is active and there are no clients -- Option for audio-only playback (discards video) -- Fixed DVD navigation in local mode (Thanks to Petri Helin) -- Completed simple playlist support - (play all media files in folder ; play .m3u playlist) - -2006-07-23: Verson 1.0.0pre1 - -- Added DVD playback and navigation support to media player -- Added support for DVD subtitles in VDR recordings -- Fixed audio surround mode (Thanks to Petri Helin) -- Added option to disable keyboard input in vdr-fbfe and vdr-sxfe - (required when running as daemon) -- Fixed OSD updating, closing and re-scaling under high system load - -2006-07-05: Version 0.99 - -- Finished implementing audio stream switching -- Improved VDR server detection and refused connection handling -- Added option to close VDR when local frontend window is closed -- Added always-on-top mode, window title and icon to vdr-sxfe - -2006-06-12: Version 0.99rc5 -- OSD endian problems fixed -- More x64 fixes (Thanks to Anssi Hannula) -- Better TCP and PIPE disconnection detection -- Fixed possible race conditions in xine input plugin -- Fixed image player (reported by Petri Helin) -- Improved (?) X11 fullscreen mode -- X11 fullscreen mode can be toggled by double-clicking window - -2006-06-03: Version 0.99rc4 - -- Fixed missing audio after trick speed modes (thanks to Tero Saarni) -- Fixed fullscreen size detection with frame buffer / DirectFB -- Added unscaled OSD capability check for framebuffer / DirectFB - -2006-06-02: Version 0.99rc3 - -- OSD is scaled to display resolution instead of video resolution - when using unscaled OSD -- OSD is re-centered when resolution is slighty different from 720x576 -- Added configuration options for multicast parameters (address, port, TTL) -- Added option to set multicast transmission always on for third-party - clients (vlc, ...) -- Some new x64 fixes -- Several configuration menu fixes -- Fixed compilation problem with xine-lib < 1.1.2 -- Fixed missing audio after trick speed modes (thanks to Tero Saarni) - -2006-05-18: Version 0.99rc2 - -- Fixed control input deadlock when using xine-ui -- Experimental automatic primary device mode included -- Fixed remote frontend keyboard handling for escape sequences -- Added several new command-line options to stand-alone frontends -- Adapted for vdr 1.4.0 -- Fixed automatic server discovery -- Fixed fullscreen mode when screen resolution != 720x576 -- Fixed --local=none option (reported by Ulf Betlehem) -- Faster channel switching -- Fixed --post option -- Fixed several endian problems and byte ordering in network modes - (reported by Carsten Rietzschel) -- Fixed segmentation fault when frontend was executed from path - (reported by Carsten Rietzschel) -- Fixed amd64 compilation problems (reported by Voitto Tuomainen) -- Many finnish menu texts updated (patch provided by Rolf Ahrenberg) -- Socket option SO_REUSEADDR added to several places to speed - up VDR restart - -2006-04-08: Version 0.99rc - -- Fixed compilation problems with gcc 3.4.5 (timer.h, osd.c). - (reported by Gavin Hamill and Voitto Tuomainen) -- Suspend mode removed (it is now implemented only as separate plugin) -- Fixed X11 keyboard input handling -- Faster seeks and channel switches in udp and rtp streaming modes -- Fixed disconnection when playing to end of avi file -- Fixed multi-speed modes (reported by Vladimir Monchenko) -- Updated russian translations (thanks to Vladimir Monchenko) -- Pipe transport fixed - -2006-03-28: Version 0.99pre - -- Russian translations (thanks to Vladimir Monchenko) -- New de-interlacing methods and options -- Updated for vdr 1.3.43 -- Support for xine post-processing plugins -- Stand-alone frontends can now automatically find - vdr (xineliboutput) server from network. -- Makefile modified to auto-detect vdr. - If vdr is not installed, only stand-alone frontends and - xine plugin are compiled. - (use "make frontends" in plugin source directory) -- Xine plugin is automatically copied to xine's plugin directory - instead of statically linking it to frontends. - -> any xine frontend can be used. -- All logging goes to syslog and honors vdr's logging level - -2005-11-22: Version 0.4 - -- Updated for xine-lib 1.1.0 and 1.1.1 -- Framebuffer and DirectFB frontend is now tested and working. -- Remote frontends tested and working (TCP/UDP/RTP). -- README updated. -- Frontend is now loaded dynamically if needed. - VDR part of plugin is not anymore linked against xine-lib and X11. - -> plugin itself can be compiled and used without installing xine - and/or X11 to VDR machine. - Frontends still need X11 and/or xine-lib. -- Makefile modified to auto-detect xine-lib and X11. - If X11 is not installed, only framebuffer frontend is compiled. - If xine-lib is not installed, frontends are not compiled (-> only - remote frontends can be used). -- Updated for vdr 1.3.34 -- Stand-alone frontends (sxfe and fbfe) can now forward lirc keys to VDR. -- New command-line parameters: frontend type, video driver and audio driver. -- Command-line parameters now override saved configuration parameters. - -- Updated for xine-lib 1.0.1 - -2005-02-17: Version 0.3 - -- Updated for vdr 1.3.19 and xine-lib 1.0 -- Direct playback of all xine-supported media types - (+ automatic loading of external .srt/.sub subtitles) -- Support for http/rtsp network streams -- Image viewer -- New configuration options -- Improved OSD support for low-resolution video -- OSD performance optimizations -- Improved X server detection -- Support for xxmc output driver -- Support for DVB radio streams -- Support for audio visualization plugins - -2004-08-19: Version 0.2 - -- Tested with VDR versions 1.2.6, 1.3.7 and 1.3.12 -- Modified to compile with xine-lib 1.0.0 (rc4) -- New configuration options -- Decoder can be stopped manually or using inactivity timer -- Support for image grabbing -- Support for localization (i18n) - -2003-12-20: Version 0.1 - -- Modified to compile with xine-lib 1.0.0 (rc2) -- Support for Xshm, Xv and XvMC. -- Audio driver and port can be selected (alsa,oss,...) -- X11 display location configurable (in setup.conf, - OSD menu or usind DISPLAY environment variable) -- Support for unscaled OSD (requires XShape X server extension) -- Support for deinterlacing -- Multiple bug fixes -- Many new configuration options -- Support for DVD plugin (GetSTC) -- Support for VDR Make.config - -2003-09-10 - -- C Compilation problems fixed -- OSD scaling fixed - -2003-05-23: Version 0.0.0 - -- Initial revision. - - diff --git a/Makefile b/Makefile deleted file mode 100644 index 0be21b4a..00000000 --- a/Makefile +++ /dev/null @@ -1,555 +0,0 @@ -# -# Makefile for a Video Disk Recorder plugin -# -# See the main source file 'xineliboutput.c' for copyright information and -# how to reach the author. -# -# $Id: Makefile,v 1.37 2008-04-23 07:11:20 phintuka 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 = xineliboutput - -_default: all - -### -### check for xine-lib and X11 -### - -XINELIBOUTPUT_FB = 0 -XINELIBOUTPUT_X11 = 0 -HAVE_XRENDER = 0 -HAVE_XDPMS = 0 -HAVE_XINERAMA = 0 -HAVE_EXTRACTOR_H = 0 -APPLE_DARWIN = 0 -XINELIBOUTPUT_XINEPLUGIN = 0 - -# check for xine-lib -ifeq ($(shell (pkg-config libxine && echo 1 || echo 0)), 1) - XINELIBOUTPUT_XINEPLUGIN = 1 -else - ifeq ($(shell (xine-config --cflags >/dev/null 2>&1 && echo "1") || echo "0"), 1) - XINELIBOUTPUT_XINEPLUGIN = 1 - endif -endif - -# check for X11 and Xrender extension -ifeq ($(XINELIBOUTPUT_XINEPLUGIN), 1) - XINELIBOUTPUT_FB = $(XINELIBOUTPUT_XINEPLUGIN) - ifeq ($(shell (((echo "\#include ";echo "int main(int c,char* v[]) {return 0;}") > testx.c && gcc -c testx.c -o testx.o >/dev/null 2>&1) && echo "1") || echo "0" ; rm -f testx.* >/dev/null), 1) - XINELIBOUTPUT_X11 = 1 - ifeq ($(shell (((echo "\#include ";echo "int main(int c,char* v[]) {return 0;}") > testx.c && gcc -c testx.c -o testx.o >/dev/null 2>&1) && echo "1") || echo "0" ; rm -f testx.* >/dev/null), 1) - HAVE_XRENDER = 1 - else - $(warning ********************************************************) - $(warning XRender extension not detected ! HUD OSD disabled. ) - $(warning ********************************************************) - endif - ifeq ($(shell (((echo "\#include ";echo "\#include ";echo "int main(int c,char* v[]) {return 0;}") > testx.c && gcc -c testx.c -o testx.o >/dev/null 2>&1) && echo "1") || echo "0" ; rm -f testx.* >/dev/null), 1) - HAVE_XDPMS = 1 - else - $(warning XDPMS extension not detected. ) - endif - ifeq ($(shell (((echo "\#include ";echo "int main(int c,char* v[]) {return 0;}") > testx.c && gcc -c testx.c -o testx.o >/dev/null 2>&1) && echo "1") || echo "0" ; rm -f testx.* >/dev/null), 1) - HAVE_XINERAMA = 1 - else - $(warning Xinerama extension not detected. ) - endif - else - $(warning ********************************************************) - $(warning X11 not detected ! X11 frontends will not be compiled. ) - $(warning ********************************************************) - endif -else - $(warning ********************************************************) - $(warning xine-lib not detected ! frontends will not be compiled. ) - $(warning ********************************************************) -endif - -# check for Apple Darwin -ifeq ($(shell gcc -dumpmachine | grep -q 'apple-darwin' && echo "1" || echo "0"), 1) - APPLE_DARWIN = 1 -endif - -# -# Override configuration here or in ../../../Make.config -# - -USE_ICONV = 1 -#XINELIBOUTPUT_X11 = 1 -#HAVE_XRENDER = 1 -#HAVE_XDPMS = 1 -#HAVE_XINERAMA = 1 -#HAVE_EXTRACTOR_H = 1 -#XINELIBOUTPUT_FB = 1 -#XINELIBOUTPUT_XINEPLUGIN = 1 -#XINELIBOUTPUT_VDRPLUGIN = 1 -#ENABLE_TEST_POSTPLUGINS = 1 -#NOSIGNAL_IMAGE_FILE=/usr/share/vdr/xineliboutput/nosignal.mpv -#STARTUP_IMAGE_FILE=/usr/share/vdr/xineliboutput/logodisplay.mpv - - -### -### The version number of this plugin (taken from the main source file): -### - -VERSION = $(shell grep 'static const char \*VERSION *=' $(PLUGIN).c | cut -d'"' -f2) - - -### -### The C++ compiler and options: -### - -CXX ?= g++ -CC ?= gcc -OPTFLAGS ?= - -ifeq ($(APPLE_DARWIN), 1) - CXXFLAGS ?= -O3 -pipe -Wall -Woverloaded-virtual -fPIC -g -fno-common -bundle -flat_namespace -undefined suppress - CFLAGS ?= -O3 -pipe -Wall -fPIC -g -fno-common -bundle -flat_namespace -undefined suppress - LDFLAGS_SO ?= -fvisibility=hidden -else - CXXFLAGS ?= -O3 -pipe -Wall -Woverloaded-virtual -fPIC -g - CFLAGS ?= -O3 -pipe -Wall -fPIC -g - LDFLAGS_SO ?= -shared -fvisibility=hidden -endif -LIBS_VDR ?= - -### -### The directory environment: -### - -VDRDIR ?= ../../.. -LIBDIR ?= ../../lib -TMPDIR ?= /tmp -BINDIR ?= /usr/bin -DESTDIR ?= / - -INSTALL ?= install - -VDRINCDIR ?= $(VDRDIR)/include - -### -### Allow user defined options to overwrite defaults: -### - --include $(VDRDIR)/Make.config --include Make.config - - -### -### check for VDR -### - -ifeq ($(APPLE_DARWIN), 1) - VDRVERSION = $(shell sed -ne '/define VDRVERSION/s/^.*"\(.*\)".*$$/\1/p' $(VDRDIR)/config.h) - APIVERSION = $(shell sed -ne '/define APIVERSION/s/^.*"\(.*\)".*$$/\1/p' $(VDRDIR)/config.h) -else - VDRVERSION = $(shell sed -ne '/define VDRVERSION/ { s/^.*"\(.*\)".*$$/\1/; p }' $(VDRDIR)/config.h) - APIVERSION = $(shell sed -ne '/define APIVERSION/ { s/^.*"\(.*\)".*$$/\1/; p }' $(VDRDIR)/config.h) -endif - -ifeq ($(strip $(VDRVERSION)),) - $(warning ********************************************************) - $(warning VDR not detected ! VDR plugin will not be compiled. ) - $(warning ********************************************************) - XINELIBOUTPUT_VDRPLUGIN = 0 -else - ifeq ($(strip $(APIVERSION)),) - $(warning VDR APIVERSION missing, using VDRVERSION $(VDRVERSION) ) - APIVERSION = $(VDRVERSION) - endif - XINELIBOUTPUT_VDRPLUGIN = 1 - ifeq ($(shell pkg-config libextractor && echo "1"), 1) - HAVE_EXTRACTOR_H = 1 - else - $(warning libextractor not found.) - endif -endif - - -### -### The name of the distribution archive: -### - -ARCHIVE = $(PLUGIN)-$(VERSION) -PACKAGE = vdr-$(ARCHIVE) - - -### -### The name of executable and libraries -### - -VDRSXFE = vdr-sxfe -VDRFBFE = vdr-fbfe -XINEINPUTVDR = xineplug_inp_xvdr.so -XINEPOSTAUTOCROP = xineplug_post_autocrop.so -XINEPOSTSWSCALE = xineplug_post_swscale.so -XINEPOSTAUDIOCHANNEL = xineplug_post_audiochannel.so -XINEPOSTHEADPHONE = xineplug_post_headphone.so - -### -### which programs and libs to build -### - -VDRSXFE_EXEC = -VDRPLUGIN_SXFE_SO = -VDRFBFE_EXEC = -VDRPLUGIN_FBFE_SO = -XINEPOSTHEADPHONE_SO = -XINEINPUTVDR_SO = -XINEPLUGINDIR = ./ -XINEPOSTAUTOCROP_SO = -XINEPOSTSWSCALE_SO = -XINEPOSTAUDIOCHANNEL_SO = -XINEPOSTHEADPHONE_SO = -VDRPLUGIN_SO = - -ifeq ($(XINELIBOUTPUT_X11), 1) - VDRSXFE_EXEC = $(VDRSXFE) - ifeq ($(XINELIBOUTPUT_VDRPLUGIN), 1) - VDRPLUGIN_SXFE_SO = lib$(PLUGIN)-sxfe.so - endif -endif -ifeq ($(XINELIBOUTPUT_FB), 1) - VDRFBFE_EXEC = $(VDRFBFE) - ifeq ($(XINELIBOUTPUT_VDRPLUGIN), 1) - VDRPLUGIN_FBFE_SO = lib$(PLUGIN)-fbfe.so - endif -endif -ifeq ($(XINELIBOUTPUT_XINEPLUGIN), 1) - XINEINPUTVDR_SO = $(XINEINPUTVDR) - XINEPLUGINDIR = $(shell (pkg-config libxine --atleast-version=1.1.90 && pkg-config libxine --variable=plugindir) || xine-config --plugindir) - XINEPOSTAUTOCROP_SO = $(XINEPOSTAUTOCROP) - XINEPOSTSWSCALE_SO = $(XINEPOSTSWSCALE) - XINEPOSTAUDIOCHANNEL_SO = $(XINEPOSTAUDIOCHANNEL) - ifeq ($(ENABLE_TEST_POSTPLUGINS), 1) - XINEPOSTHEADPHONE_SO = $(XINEPOSTHEADPHONE) - endif -endif -ifeq ($(XINELIBOUTPUT_VDRPLUGIN), 1) - VDRPLUGIN_SO = libvdr-$(PLUGIN).so -endif - - -### -### Includes and Defines (add further entries here): -### - -INCLUDES += -I$(VDRINCDIR) -LIBS_XINE += $(shell (pkg-config libxine --atleast-version=1.1.90 && pkg-config libxine --libs) || xine-config --libs) -LIBS_X11 += -L/usr/X11R6/lib -lX11 -lXv -lXext -ifeq ($(HAVE_XRENDER), 1) - LIBS_X11 += -lXrender -endif - -ifeq ($(APPLE_DARWIN), 1) - INCLUDES += -I/sw/include - LIBDIRS += -L/sw/lib - LIBS += $(LIBDIRS) -ljpeg -liconv -else - LIBS += -lrt -endif - -DEFINES += -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"' \ - -D_REENTRANT -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 \ - -DXINELIBOUTPUT_VERSION='"$(VERSION)"' -ifeq ($(HAVE_XRENDER), 1) - DEFINES += -DHAVE_XRENDER=1 -endif -ifeq ($(HAVE_XDPMS), 1) - DEFINES += -DHAVE_XDPMS=1 -endif -ifeq ($(HAVE_XINERAMA), 1) - DEFINES += -DHAVE_XINERAMA=1 -endif -ifeq ($(HAVE_EXTRACTOR_H), 1) - DEFINES += -DHAVE_EXTRACTOR_H=1 - INCLUDES += $(shell pkg-config libextractor --cflags-only-I) - LIBS_VDR += $(shell pkg-config libextractor --libs-only-L) - LIBS_VDR += $(shell pkg-config libextractor --libs-only-l) -endif - -# check for yaegp patch -#YAEPG = $(shell grep -q 'vidWin' \$(VDRINCDIR)/vdr/osd.h && echo "1") -#ifeq ($(YAEPG), 1) -# DEFINES += -DYAEGP_PATCH -#endif -#DEFINES += $(shell grep -q 'vidWin' \$(VDRINCDIR)/vdr/osd.h && echo "-DYAEGP_PATCH") - -ifeq ($(XINELIBOUTPUT_XINEPLUGIN), 1) - CFLAGS += $(shell (pkg-config libxine --atleast-version=1.1.90 && pkg-config libxine --cflags) || xine-config --cflags) -endif - -ifeq ($(ENABLE_TEST_POSTPLUGINS), 1) - DEFINES += -DENABLE_TEST_POSTPLUGINS -endif - -ifdef USE_ICONV - DEFINES += -DUSE_ICONV=$(USE_ICONV) -endif -ifdef NOSIGNAL_IMAGE_FILE - DEFINES += -DNOSIGNAL_IMAGE_FILE='"$(NOSIGNAL_IMAGE_FILE)"' -endif -ifdef STARTUP_IMAGE_FILE - DEFINES += -DSTARTUP_IMAGE_FILE='"$(STARTUP_IMAGE_FILE)"' -endif - - -### -### configuration -### - -#DEFINES += -DHAVE_XV_FIELD_ORDER - - -### -### The object files (add further files here): -### - -ifeq ($(XINELIBOUTPUT_VDRPLUGIN), 1) - OBJS = $(PLUGIN).o device.o frontend.o osd.o config.o menu.o setup_menu.o \ - i18n.o menuitems.o media_player.o equalizer.o \ - frontend_local.o frontend_svr.o \ - tools/cxsocket.o tools/udp_pes_scheduler.o \ - tools/backgroundwriter.o tools/playlist.o tools/http.o \ - tools/vdrdiscovery.o tools/time_pts.o tools.o - OBJS_MPG = black_720x576.o nosignal_720x576.o vdrlogo_720x576.o -else - OBJS = - OBJS_MPG = -endif - -ifeq ($(XINELIBOUTPUT_X11), 1) - OBJS_SXFE_SO = xine_sxfe_frontend.o xine/post.o - OBJS_SXFE = xine_sxfe_frontend_standalone.o xine/post.o tools/vdrdiscovery_standalone.o -else - OBJS_SXFE_SO = - OBJS_SXFE = -endif - -ifeq ($(XINELIBOUTPUT_FB), 1) - OBJS_FBFE_SO = xine_fbfe_frontend.o xine/post.o - OBJS_FBFE = xine_fbfe_frontend_standalone.o xine/post.o tools/vdrdiscovery_standalone.o -else - OBJS_FBFE_SO = - OBJS_FBFE = -endif - - -### -### Implicit rules: -### - -%.o: %.c - $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) -o $@ $< - - -### -### Dependencies: -### - -MAKEDEP = g++ -MM -MG -DEPFILE = .dependencies -$(DEPFILE): Makefile - @$(MAKEDEP) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.c) $(OBJS_SXFE_SO:%.o=%.c) $(OBJS_FBFE_SO:%.o=%.c) > $@ - --include $(DEPFILE) - -DEFINES += -Wall - - -### -### Rules: -### - -mpg2c: mpg2c.c - $(CC) mpg2c.c -o $@ - -black_720x576.c: mpg2c black_720x576.mpg - @./mpg2c black black_720x576.mpg black_720x576.c -nosignal_720x576.c: mpg2c nosignal_720x576.mpg - @./mpg2c nosignal nosignal_720x576.mpg nosignal_720x576.c -vdrlogo_720x576.c: mpg2c vdrlogo_720x576.mpg - @./mpg2c vdrlogo vdrlogo_720x576.mpg vdrlogo_720x576.c - -xine_input_vdr.o: xine_input_vdr.c xine_input_vdr.h xine_osd_command.h nosignal_720x576.c logdefs.h - $(CC) $(CFLAGS) -c $(DEFINES) $(INCLUDES) $(OPTFLAGS) xine_input_vdr.c -xine_input_http.o: xine_input_http.c - $(CC) $(CFLAGS) -c $(DEFINES) $(INCLUDES) $(OPTFLAGS) xine_input_http.c -xine/post.o: xine/post.c xine/post.h - $(CC) $(CFLAGS) -c $(DEFINES) $(INCLUDES) $(OPTFLAGS) xine/post.c -o $@ -tools/vdrdiscovery.o: tools/vdrdiscovery.c tools/vdrdiscovery.h - $(CC) $(CFLAGS) -c $(DEFINES) $(INCLUDES) $(OPTFLAGS) tools/vdrdiscovery.c -o $@ -tools/vdrdiscovery_standalone.o: tools/vdrdiscovery.c tools/vdrdiscovery.h - $(CC) $(CFLAGS) -c $(DEFINES) -DFE_STANDALONE $(INCLUDES) $(OPTFLAGS) tools/vdrdiscovery.c -o $@ -xine_post_autocrop.o: xine_post_autocrop.c - $(CC) $(CFLAGS) -c $(DEFINES) $(INCLUDES) $(OPTFLAGS) xine_post_autocrop.c -xine_post_swscale.o: xine_post_swscale.c - $(CC) $(CFLAGS) -c $(DEFINES) $(INCLUDES) $(OPTFLAGS) xine_post_swscale.c -xine_post_audiochannel.o: xine_post_audiochannel.c - $(CC) $(CFLAGS) -c $(DEFINES) $(INCLUDES) $(OPTFLAGS) xine_post_audiochannel.c -xine_post_headphone.o: xine_post_headphone.c - $(CC) $(CFLAGS) -c $(DEFINES) $(INCLUDES) $(OPTFLAGS) xine_post_headphone.c - -xine_sxfe_frontend.o: xine_sxfe_frontend.c xine_frontend.c xine_frontend.h \ - xine_input_vdr.h xine_osd_command.h xine/post.h logdefs.h \ - xineliboutput.c - $(CC) $(CFLAGS) -c $(DEFINES) $(INCLUDES) $(OPTFLAGS) xine_sxfe_frontend.c -xine_fbfe_frontend.o: xine_fbfe_frontend.c xine_frontend.c xine_frontend.h \ - xine_input_vdr.h xine_osd_command.h xine/post.h logdefs.h \ - xineliboutput.c - $(CC) $(CFLAGS) -c $(DEFINES) $(INCLUDES) $(OPTFLAGS) xine_fbfe_frontend.c -xine_sxfe_frontend_standalone.o: xine_sxfe_frontend.c xine_frontend.c \ - xine_frontend.h xine_input_vdr.h xine_osd_command.h \ - xine/post.h logdefs.h xine_frontend_main.c xine_frontend_lirc.c \ - xineliboutput.c tools/vdrdiscovery.h - $(CC) $(CFLAGS) -c $(DEFINES) -DFE_STANDALONE $(INCLUDES) $(OPTFLAGS) xine_sxfe_frontend.c -o $@ -xine_fbfe_frontend_standalone.o: xine_fbfe_frontend.c xine_frontend.c \ - xine_frontend.h xine_input_vdr.h xine_osd_command.h \ - xine/post.h logdefs.h xine_frontend_main.c xine_frontend_lirc.c \ - xineliboutput.c tools/vdrdiscovery.h - $(CC) $(CFLAGS) -c $(DEFINES) -DFE_STANDALONE $(INCLUDES) $(OPTFLAGS) xine_fbfe_frontend.c -o $@ - -### Internationalization (I18N): - -PODIR = po -LOCALEDIR ?= $(VDRDIR)/locale -I18Npo = $(wildcard $(PODIR)/*.po) -I18Nmsgs = $(addprefix $(LOCALEDIR)/, $(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 $@ $^ - -%.po: $(I18Npot) - msgmerge -U --no-wrap --no-location --backup=none -q $@ $< - @touch $@ - -$(I18Nmsgs): $(LOCALEDIR)/%/LC_MESSAGES/vdr-$(PLUGIN).mo: $(PODIR)/%.mo - @mkdir -p $(dir $@) - cp $< $@ - -.PHONY: i18n -i18n: $(I18Nmsgs) - -### -### targets -### - -XINELIBOUTPUT_INSTALL_MSG = \ - $(warning *********************** xineliboutput ***************************) \ - $(warning Xine plugins and frontends will not be installed automatically. ) \ - $(warning To install files execute "make install" in ) \ - $(warning $(shell echo `pwd`)) \ - $(warning *****************************************************************) \ - -install : XINELIBOUTPUT_INSTALL_MSG = - -all: $(VDRPLUGIN_SO) $(VDRPLUGIN_SXFE_SO) $(VDRPLUGIN_FBFE_SO) \ - $(VDRSXFE_EXEC) $(VDRFBFE_EXEC) $(XINEINPUTVDR_SO) \ - $(XINEPOSTAUTOCROP_SO) $(XINEPOSTSWSCALE_SO) $(XINEPOSTHEADPHONE_SO) \ - $(XINEPOSTAUDIOCHANNEL_SO) i18n - $(XINELIBOUTPUT_INSTALL_MSG) - -frontends: $(VDRSXFE_EXEC) $(VDRFBFE_EXEC) $(XINEINPUTVDR_SO) \ - $(XINEPOSTAUTOCROP_SO) $(XINEPOSTSWSCALE_SO) $(XINEPOSTHEADPHONE_SO) \ - $(XINEPOSTAUDIOCHANNEL_SO) - -.PHONY: all - - -ifeq ($(XINELIBOUTPUT_VDRPLUGIN), 1) -$(VDRPLUGIN_SO): $(OBJS) $(OBJS_MPG) - $(CXX) $(CXXFLAGS) $(LDFLAGS_SO) $(OBJS) $(OBJS_MPG) $(LIBS) $(LIBS_VDR) -o $@ - @-rm -rf $(LIBDIR)/$@.$(APIVERSION) - @cp $@ $(LIBDIR)/$@.$(APIVERSION) -endif - -ifeq ($(XINELIBOUTPUT_X11), 1) -$(VDRPLUGIN_SXFE_SO): $(OBJS_SXFE_SO) - $(CC) $(CFLAGS) $(LDFLAGS_SO) $(OBJS_SXFE_SO) $(LIBS_X11) $(LIBS_XINE) -o $@ - @-rm -rf $(LIBDIR)/$(VDRPLUGIN_SXFE_SO).$(VERSION) - @cp $@ $(LIBDIR)/$(VDRPLUGIN_SXFE_SO).$(VERSION) -$(VDRSXFE): $(OBJS_SXFE) - $(CC) -g $(OBJS_SXFE) $(LIBS_X11) -ljpeg $(LIBS_XINE) -o $@ -endif - -ifeq ($(XINELIBOUTPUT_FB), 1) -$(VDRPLUGIN_FBFE_SO): $(OBJS_FBFE_SO) - $(CC) $(CFLAGS) $(LDFLAGS_SO) $(OBJS_FBFE_SO) $(LIBS_XINE) -o $@ - @-rm -rf $(LIBDIR)/$(VDRPLUGIN_FBFE_SO).$(VERSION) - @cp $@ $(LIBDIR)/$(VDRPLUGIN_FBFE_SO).$(VERSION) -$(VDRFBFE): $(OBJS_FBFE) - $(CC) -g $(OBJS_FBFE) $(LIBS_XINE) -ljpeg -o $@ -endif - -ifeq ($(XINELIBOUTPUT_XINEPLUGIN), 1) -$(XINEINPUTVDR_SO): xine_input_vdr.o - $(CC) $(CFLAGS) $(LDFLAGS_SO) xine_input_vdr.o $(LIBS_XINE) -o $@ -$(XINEPOSTAUTOCROP_SO): xine_post_autocrop.o - $(CC) $(CFLAGS) $(LDFLAGS_SO) xine_post_autocrop.o $(LIBS_XINE) -o $@ -$(XINEPOSTSWSCALE_SO): xine_post_swscale.o - $(CC) $(CFLAGS) $(LDFLAGS_SO) xine_post_swscale.o $(LIBS_XINE) -o $@ -$(XINEPOSTAUDIOCHANNEL_SO): xine_post_audiochannel.o - $(CC) $(CFLAGS) $(LDFLAGS_SO) xine_post_audiochannel.o $(LIBS_XINE) -o $@ -endif -ifeq ($(ENABLE_TEST_POSTPLUGINS), 1) -$(XINEPOSTHEADPHONE_SO): xine_post_headphone.o - $(CC) $(CFLAGS) $(LDFLAGS_SO) xine_post_headphone.o $(LIBS_XINE) -o $@ -endif - -install: all -ifeq ($(XINELIBOUTPUT_XINEPLUGIN), 1) - @echo Installing $(DESTDIR)/$(XINEPLUGINDIR)/$(XINEINPUTVDR) - @-rm -rf $(DESTDIR)/$(XINEPLUGINDIR)/$(XINEINPUTVDR) - @$(INSTALL) $(XINEINPUTVDR) $(DESTDIR)/$(XINEPLUGINDIR)/$(XINEINPUTVDR) - @echo Installing $(DESTDIR)/$(XINEPLUGINDIR)/post/$(XINEPOSTAUTOCROP) - @-rm -rf $(DESTDIR)/$(XINEPLUGINDIR)/post/$(XINEPOSTAUTOCROP) - @$(INSTALL) -D -m 0644 $(XINEPOSTAUTOCROP) $(DESTDIR)/$(XINEPLUGINDIR)/post/$(XINEPOSTAUTOCROP) - @echo Installing $(DESTDIR)/$(XINEPLUGINDIR)/post/$(XINEPOSTSWSCALE) - @-rm -rf $(DESTDIR)/$(XINEPLUGINDIR)/post/$(XINEPOSTSWSCALE) - @$(INSTALL) -D -m 0644 $(XINEPOSTSWSCALE) $(DESTDIR)/$(XINEPLUGINDIR)/post/$(XINEPOSTSWSCALE) - @echo Installing $(DESTDIR)/$(XINEPLUGINDIR)/post/$(XINEPOSTAUDIOCHANNEL) - @-rm -rf $(DESTDIR)/$(XINEPLUGINDIR)/post/$(XINEPOSTAUDIOCHANNEL) - @$(INSTALL) -D -m 0644 $(XINEPOSTAUDIOCHANNEL) $(DESTDIR)/$(XINEPLUGINDIR)/post/$(XINEPOSTAUDIOCHANNEL) -endif -ifeq ($(ENABLE_TEST_POSTPLUGINS), 1) - @echo Installing $(DESTDIR)/$(XINEPLUGINDIR)/post/$(XINEPOSTHEADPHONE) - @-rm -rf $(DESTDIR)/$(XINEPLUGINDIR)/post/$(XINEPOSTHEADPHONE) - @$(INSTALL) -D -m 0644 $(XINEPOSTHEADPHONE) $(DESTDIR)/$(XINEPLUGINDIR)/post/$(XINEPOSTHEADPHONE) -endif -ifeq ($(XINELIBOUTPUT_FB), 1) - @echo Installing $(DESTDIR)/$(BINDIR)/vdr-fbfe - @-rm -rf $(DESTDIR)/$(BINDIR)/vdr-fbfe - @$(INSTALL) -D -m 0755 vdr-fbfe $(DESTDIR)/$(BINDIR)/vdr-fbfe -endif -ifeq ($(XINELIBOUTPUT_X11), 1) - @echo Installing $(DESTDIR)/$(BINDIR)/vdr-sxfe - @-rm -rf $(DESTDIR)/$(BINDIR)/vdr-sxfe - @$(INSTALL) -D -m 0755 vdr-sxfe $(DESTDIR)/$(BINDIR)/vdr-sxfe -endif - -dist: clean - @-rm -rf $(TMPDIR)/$(ARCHIVE) - @mkdir $(TMPDIR)/$(ARCHIVE) - @cp -a * $(TMPDIR)/$(ARCHIVE) - @tar czf $(PACKAGE).tgz --exclude=CVS -C $(TMPDIR) $(ARCHIVE) - @-rm -rf $(TMPDIR)/$(ARCHIVE) - @echo Distribution package created as $(PACKAGE).tgz - - -clean: - @-rm -f $(DEPFILE) *.so* *.o *.tgz core* *~ *.flc *.bak \ - tools/*.o tools/*~ tools/*.flc xine/*.o xine/*~ \ - xine/*.flc $(VDR_FBFE) $(VDR_SXFE) mpg2c black_720x576.c \ - nosignal_720x576.c vdrlogo_720x576.c vdr-sxfe vdr-fbfe \ - $(PODIR)/*.mo $(PODIR)/*.pot - diff --git a/README b/README deleted file mode 100644 index b5969cd4..00000000 --- a/README +++ /dev/null @@ -1,643 +0,0 @@ -This is a "plugin" for the Video Disk Recorder (VDR). - -Written by: Petri Hintukainen - -Project's homepage: http://www.sourceforge.net/projects/xineliboutput - -Latest version available at: http://prdownloads.sourceforge.net/xineliboutput/ - - -See the file COPYING for license information. - - -Description - - X11 and Linux framebuffer front-end for VDR. - Plugin displays video and OSD in X/Xv/XvMC window, - Linux framebuffer/DirectFB/vidixfb or DXR3 card. - - Support for local and remote frontends. - - Built-in image and media player supports playback of most known - media files (avi/mp3/divx/jpeg/...), DVDs and radio/video streams - (http, rtsp, ...) directly from VDR. - - -Requirements - - - vdr-1.4.0 or later - (vdr is required only at server side) - - xine-lib 1.1.1 or later - (xine-lib is not required for server in network-only usage) - - Enough CPU power and memory to decode streams - (PII 400Mhz + 64M should be enough with Xv or DirectFB) - - Optional: - - - X server with Composite and Xrender extensions, - compositing window manager or composite manager (xcompmgr). - (Required for HUD OSD to blend high-quality OSD using graphics hardware) - - libextractor 0.5.20 or later (http://libextractor.sourceforge.net). - (used for media file metadata extraction in media player) - -WARNING - - Remote (network) mode should be used only in firewalled - environment; it gives anyone full control to VDR ! - - Full access is allowed to all hosts listed in svdrphosts.conf. - - Multicast streaming can flood your internet connection and/or - wireless LAN. If there is no router (or intelligent switch ?) - all multicast packets will be broadcasted to all network links. - This will flood slow network links: - - Internet connection if outgoing bandwith is < 10 Mbit/s - - Wireless LAN (11 or 54 Mbit/s). - By default multicast TTL is set to 1 so multicast packets should - be stopped to first router regardless of network configuration. - - -Public CVS - - Latest fixes are available from sourceforge.net public CVS - (http://sourceforge.net/cvs/?group_id=160063). - - CVS checkout command: - cvs -d:pserver:anonymous@xineliboutput.cvs.sourceforge.net:/cvsroot/xineliboutput co vdr-xineliboutput - - -Buildtime options - - X11 and xine-lib are detected by Makefile. - It is possible to override auto-detection by adding - following definitions to VDR's Make.config: - - enable/disable building of X11 frontends: - XINELIBOUTPUT_X11 = 1 - XINELIBOUTPUT_X11 = 0 - - enable/disable framebuffer frontends: - XINELIBOUTPUT_FB = 1 - XINELIBOUTPUT_FB = 0 - - enable/disable xine (input)plugin: - XINELIBOUTPUT_XINEPLUGIN = 1 - XINELIBOUTPUT_XINEPLUGIN = 0 - - or changing corresponding lines in plugin's Makefile. - - It is possible to compile only remote frontends with command - "make frontends". Building frontends is possible without VDR. - Only xine-lib (and corresponding development package or headers) - are required. - - -Installing - IMPORTANT - - XINE'S DYNAMIC LIBRARIES AND FRONTEND EXECUTABLES ARE NOT - INSTALLED AUTOMATICALLY. - - It is important to copy required libraries to right place - either by hand or by executing "make install" in plugin's - source directory. - Installing binaries and libraries usually requires root - permissions. - - PLUGIN WILL NOT WORK UNLESS ALL FILES HAVE BEEN INSTALLED ! - - To be able to use remote frontends each client's IP address - must be defined in VDR's svdrphosts.conf. - Full access is allowed to all hosts listed in svdrphosts.conf. - Connections from any other hosts are rejected. - - -Usage examples (VDR plugin) - - If no arguments are given, both X11 and framebuffer frontends are tried. - First working frontend is used with best available video driver. - Complete list of available command-line arguments can be obtained - with "vdr --help". - - Only local frontend, X11/Xv video, alsa audio: - vdr -P"xineliboutput --local=sxfe --video=xv --audio=alsa --remote=none" - - Only local frontend, (slow) X11 video, oss audio: - vdr -P"xineliboutput --local=sxfe --video=xshm --audio=oss --remote=none" - - Only local frontend, DirectFB: - vdr -P"xineliboutput --local=fbfe --video=DirectFB --remote=none" - - Only remote frontend(s): - vdr -P"xineliboutput --local=none --remote=37890" - - Local and remote frontends: - vdr -P"xineliboutput --local=sxfe --remote=37890" - or - vdr -P"xineliboutput --local=fbfe --remote=37890" - - -Using remote frontends - - Two remote frontends are included, vdr-fbfe for framebuffer and - vdr-sxfe for X11. - Complete list of available command-line arguments can be obtained - with "vdr-??fe --help". - - Frontend should find server automatically (from local subnet) - and negoate best available transport. If frontend does not - find server (or specific transport should be used), mrl must - be given on command line. - - Examples: - - Search for VDR (xineliboutput) server, connect to it and - negoatite best available transport. Use best available audio - and video driver. - vdr-fbfe - or - vdr-sxfe - - Connect to 192.168.1.3 default port and negoate best available transport - vdr-fbfe xvdr://192.168.1.3 - - Connect to 192.168.2.100, port 12550 and use TCP transport - vdr-fbfe xvdr+tcp://192.168.2.100:12550 - - Automatically search for VDR server and use UDP transport - vdr-fbfe xvdr+udp: - or - vdr-fbfe --udp - - Available transports for video/audio - pipe Use local pipe; server and front-end must be running in - same machine - rtp Use RTP/UDP multicast for data and TCP for control. - Multiple frontends can receive same stream. - udp Use UDP unicast for data and TCP for control. - tcp Use TCP protocol for control and data. Both channels - use same server port and are opened by client. - - Forwarding lirc keys to server - Use option --lirc with optional lircd socket name to - forward LIRC commands from client to server. - - Audio driver - Use alsa: - vdr-fbfe --audio alsa - Use alsa (and specific card/sub-device): - vdr-fbfe --audio alsa:plughw:1,1 - - Video driver (and display / device): - With X11 frontend (vdr-sxfe): - vdr-sxfe --video [xshm | xv | xvmc | xxmc | vidix | - XDirectFB | opengl | sdl | none [:display]] - Examples: - --video xv - --video xvmc:127.0.0.1:1.0 - - With framebuffer frontend (vdr-fbfe): - --video [fb | DirectFB | sdl | vidixfb | dxr3 | aadxr3 | none [:fb_device]] - Examples: - --video DirectFB - --video fb:/dev/fb/1 - --video vidixfb - --video aadxr3 - - De-interlacing - If deinterlacing post plugin options are not given at command line, - deinterlacing is controlled by VDR plugin configuration menu settings. - - De-interlacing can also be forced on or off with command-line option --post tvtime. - Examples: - vdr-sxfe --post tvtime:method=Linear,cheap_mode=1,pulldown=0,use_progressive_frame_flag=1 - vdr -P"xineliboutput --post=tvtime:method=Linear,cheap_mode=1,pulldown=0,use_progressive_frame_flag=1" - Disable deinterlacing: - vdr-sxfe --post tvtime:enable=0 - - -HUD OSD - - HUD OSD implements high-quality OSD using modern graphics hardware. - OSD is scaled and blended using hardware, so it adds no extra CPU - overhead. OSD is always blended to output (display) resolution, - so it remains sharp and detailed even with low-resolution video. - - HUD OSD must be enabled with command-line option (--hud). Scaling - options can be configured in xineliboutput plugin setup menu, - OSD settings page. - - Requirements: - - X server with Composite and Xrender extensions. - Composite extension must be enabled in Xorg config. - - Composite window manager (compiz, beryl, or properly configured xfce4, metacity, ...) - or separate composite manager (xcompmgr). - - Compatible graphics hardware and drivers. - HUD OSD has been tested with: - nVidia GF FX5700LE (driver version 169.09) - Intel G965 (GMA-X3000) (driver version 2.2.1, textured XVideo) - - metacity 2.23.2 - xcompmgr 1.1.3 - - NOTE: - - Drawing video (even without OSD) may be slower when composite - extension is enabled. - - - For true HD-resolution OSD VDR needs to be patched. - - HUD OSD was contributed by Antti Seppälä and Rolf Ahrenberg. - - -Using with xine-ui (xine, fbxine, gxine, ...) - - Examples: - xine "xvdr://127.0.0.1#nocache;demux:mpeg_block" - xine "xvdr+tcp://127.0.0.1:37890#nocache;demux:mpeg_block" - xine "xvdr+udp://127.0.0.1:37890#nocache;demux:mpeg_block" - - "#nocache;demux:mpeg_block" should always be appended to end of mrl. - - Remote mode must be enabled in VDR plugin. - - Some configuration options are not available when using - third-party frontends. - - -Using with other media players (mplayer, vlc, ...) - - Primary device video and audio (without OSD or subtitles) - can be streamed from plugin control port to almost any media - player using http or rtsp. - - Session Announcement Protocol (SAP) compatible players - should detect stream automatically and add it to playlist - or bookmarks when RTP transmission is active (tested with vlc). - - Tested players: - - Linux: mplayer, vlc, xine - Windows: vlc - - Examples: - - mplayer http://192.168.1.3:37890 - vlc http://192.168.1.3:37890 - vlc rtsp://192.168.1.3:37890 - vlc rtp://@224.0.1.9:37890 - - -Controlling VDR - - With local frontend, vdr-sxfe and vdr-fbfe: - - Keyboard input from console is mapped to VDR keyboard input. - If VDR was compiled or configured without keyboard support, - console keyboard input does not work. - - Keyboard input from X11 window is mapped to XKeySym remote. - Keys are mapped to VDR keys in remote.conf file. Simple example - of X11 key mappings is included in examples directory. - - It should be possible to use VDR's remote controller learning - mode by pressing some key just after VDR has been started. - Learning mode does not work with remote frontends. - - Keyboard input can be disabled in configuration menu. There - are separate entries for local and remote frontends. - - With xine-ui: - - Keyboard shortcuts and remote events from xine menus are - automatically forwarded to VDR and translated to VDR keys. - Translation to VDR keys is static and defined in xine_input_vdr.c. - - -Frontend key bindings - - Esc Close frontend (vdr-fbfe / fdr-sxfe) - - Mouse left button double-click - Toggle between fullscreen / window mode (vdr-sxfe only) - - Mouse right button click - Toggle between normal window / always on top / - borderless window (vdr-sxfe only) - - Close Window - Close frontend (fdr-sxfe only) - - -Image viewer key bindings - - Left/Prev Previous image - Right/Next Next image - Up/Down Jump 5 images forward/backward - Yellow Delete current image - Back Return to image list - Stop/Blue Exit image viewer - Play Start slide show - Pause Stop slide show - FastFwd/FastRew Start slide show; Increase/decrease slide show speed; - Change slideshow direction - Ok Toggle replay display mode - -Media player key bindings for video files - - Back Return to file list - Red Open playlist if more than one file in the playlist, - otherwise jump to beginning of file - Green Jump 1 min back - Yellow Jump 1 min forward - Stop/Blue Stop replay - User7 Random play / normal play - 1, User8 Jump 20 s back - 3, User9 Jump 20 s forward - 2 Move subtitles up - 5 Move subtitles down - Down/Pause Pause replay - Up/Play Play - Ok Toggle replay display mode - Next Skip to next file when replaying playlist - Prev Skip to previous file when replaying playlist - FastRew/Left Play slower - FastFwd/Right Play faster - -Media player key bindings for audio files - - Back Return to file list - Red Open playlist - Green Jump 1 min back - Yellow Jump 1 min forward - Stop/Blue Stop replay - 0...9 Use to select a file from the playlist - according to its position on the playlist - Down/Pause Pause replay - Up/Play Play - Ok Toggle replay display mode - Next/Right Skip to next file - Prev/Left Skip to previous file or restart the currently playing file - if more than three seconds has been played back already - FastRew/FastFwd Play faster/slower - User7 Random play / normal play - - with VDR < 1.5.15: - If media file includes multiple subtitles (DVD, .mkv file, ...), - subtitle language can be selected from xineliboutput plugin menu, - "Select subtitle track" key macro or from DVD subtitle menu. - Preferred subtitle languages can be selected from plugin setup menu. - - with VDR >= 1.5.15: - If media file includes multiple subtitles (DVD, .mkv file, ...), - subtitle language can be selected with VDR Subtitle key or from - DVD subtitle menu. - Plugin uses VDR's preferred subtitle language settings. - -DVD player key bindings - - Up/Down/Left/Right/Ok/Back DVD menu navigation when DVD menu is active - Red Access DVD menu(s) - Green Jump 1 min back - Yellow Jump 1 min forward - Stop/Blue/Back Stop replay - Ok / Info Toggle replay display mode - 1 / User8 Jump 20 s back - 3 / User9 Jump 20 s forward - Pause / Down Pause replay - Play / Up Play - 6 / Next, Next chapter - 4 / Prev Previous chapter - 9 Next title - 7 Previous title - Info Show progress display - 2 Next subtitle track (with VDR < 1.5.15) - 5 Previous subtitle track (with VDR < 1.5.15) - FastRew/FastFwd, - Left/Right Play faster/slower - - -DVD playback - - DVD images - - Media player supports playing DVDs directly from hard disk. - Found DVD folders are marked with 'D' in media player - file list. - Plugin detects folders as DVDs if there is file - Name_Of_DVD/VIDEO_TS/VIDEO_TS.IFO. - - It is also possible to replay DVD as VDR recording by - creating empty recording directory and renaming or - symlinking .VOBs of selected title to 00?.vdr files. - DVD menus (VTS_??_0.VOB) should _not_ be copied. - Audio can be selected from main menu just as with normal - VDR recordings. - For seeking it is necessarily to create index.vdr file - with genindex or similar tool. - - DVD discs - - "Real" DVD discs (accessible from /dev/dvd) can be played - from xineliboutput plugin menu. - - In case of remote frontend (vdr-sxfe/vdr-fbfe) DVD drive - of _remote client_ is used. - - Audio track can be selected from VDR audio track menu - (keys "Menu" + "Green" or "Audio") or from DVD menu. - - with VDR < 1.5.15: - DVD subtitle language can be selected from xineliboutput plugin - menu, from DVD menu, with keys "2" and "5" or from subtitle - menu (using "Select subtitle track" key macro). - Preferred subtitle languages can be selected from plugin setup menu. - - with VDR >= 1.5.15: - DVD subtitle language can be selected with VDR Subtitle key or - from DVD subtitle menu. - Plugin uses VDR's preferred subtitle language settings. - - -Aspect ratio setting - - default Aspect ratio is calculated from display resolution. - - 4:3 4:3 video is scaled to fill whole window; - 16:9 video has black bars at top and bottom - - 16:9 16:9 video is scaled to fill whole window; - 4:3 video has black bars at left and right. - - 16:10 - - auto 4:3 and 16:9 are scaled to fill whole window. - (useful if TV can "smart scale" 4:3 video to 16:9) - - -Shortcut key macros - - It is possible to change some settings and execute actions with - user-defined key macros and VDR User? keys. - - Supported settings and corresponding key sequences in VDR - keymacros.conf format are: - - Start replaying DVD (User? @xineliboutput Red 0) - Start replaying Title 1 from DVD (User? @xineliboutput Red 1) - Select subtitle track (VDR <1.5.15) (User? @xineliboutput Red 2) - Toggle aspect ratio (User? @xineliboutput Red 3) - Toggle letterbox -> 16:9 cropping (User? @xineliboutput Red 4) - Toggle stereo -> 5.1 upmix (User? @xineliboutput Red 5) - Toggle 5.1 -> surround downmix (User? @xineliboutput Red 6) - Toggle de-interlacing (User? @xineliboutput Red 7) - Toggle local frontend on/off (User? @xineliboutput Red 8) - Start replaying default playlist or file pointed by symlink - $(CONFDIR)/plugins/xineliboutput/default_playlist - (User? @xineliboutput Red 9) - Increase audio delay (User? @xineliboutput Red Up) - Decrease audio delay (User? @xineliboutput Red Down) - Toggle the video aspect ratio (User? @xineliboutput Red Right) - - with VDR < 1.5.15: - Defining "Select subtitle track" macro key enables VDR-style - subtitle track menu for media player (identical to audio track - selection with VDR "Audio" key). - - -Special LIRC keys - - If plugin is compiled with macro INTERPRET_LIRC_KEYS defined, following - LIRC keys are interpreted by vdr-sxfe/vdr-fbfe: - - Fullscreen Toggle fullscreen state - Deinterlace Toggle deinterlacing - Quit Close program - - -Xine-specific settings - - All xine-specific settings can be changed by editing file - $(HOME)/.xine/config_xineliboutput. - - Default mpeg2 decoder (libmpeg2) can be switched to ffmpeg mpeg2 decoder - by increasing ffmpeg decoder priority: - - engine.decoder_priorities.ffmpegvideo:1 - - (ffmpeg decoder is slower but handles errors better). - - -Slave mode - - vdr-sxfe and vdr-fbfe implement simple slave mode. Slave mode is - activated with command-line option --slave. In slave mode program reads - CRLF-terminated commands from standard input instead of using keyboard - as VDR remote controller. Supported commands are: - - HITK Send key press event to VDR - FULLSCREEN Toggle fullscreen state - DEINTERLACE Toggle deinterlacing - QUIT Close program - - Video can be drawn to existing X11 window with vdr-sxfe - option --wid= - - -Distributed set-up - multiple clients and/or servers - - Simple multi-head setup - - When there is no need to watch different recordings / channels at - different clients at the same time, just running vdr-[sx/fb]fe at - each client is enough. In this case the same video + OSD is mirrored - to all clients and all clients control the same (shared) VDR. - - Real multi-user setup - - When there is a need to have multiple independently controlled - clients (each with separate video and OSD), running multiple - instances of VDR is required. - It doesn't matter if all VDR instances run at server or at each - client. However, there are some benefits when running all - instances of VDR on the same server: - - less maintenance: only one installation of VDR and plugins is required - - posibility to use simpler, diskless clients with less memory - - Faster cutting / DVD burning / ... as there is no - network between VDR and disks - - no need to export and mount /video to every client - - overall resource usage is lower - - ... - - It is preferred to allow recording only at the "master" vdr. - Recording the same timer on two VDR instances will most likely - corrupt the recording. Besides that, doing all recordings directly - from DVB card (no streamdev in middle) makes things simpler and less - error prone. It is probably even impossible to do several recordings - from different transponders using single streamdev instance. - - Timersync plugin disables recording on client VDRs. All timers - are still visible at each client and timers can be created/modified - at any client just as with the single VDR setup. - Timersync plugin synchronizes all timer modifications between VDR instances - and takes care that all recordings are made by the "master" vdr. - Still, all kind of autotimer plugins etc. that generate timers - should be activated only at server vdr (there shouldn't - be any reasons to run multiple instances of such plugins). - - Simplified example: - (xinelibout and streamdev plugins required) - - Start 3 VDRs at server: - - "Master" VDR: controls all DVB cards, does all recordings, - server for client 1 - - vdr -c /etc/vdr \ - -P"xineliboutput --local=none --remote=37890" \ - -Pstreamdev-server - - VDR server for client 2: - - vdr -c /etc/vdr2 \ - -D 10 -p 2102 \ - -P"xineliboutput --local=none --remote=37892" \ - -Pstreamdev-client - - VDR server for client 3 - - vdr -c /etc/vdr3 \ - -D 10 -p 2103 \ - -P"xineliboutput --local=none --remote=37894" \ - -Pstreamdev-client - - + all possible other options and plugins. - - - Using -D 10 option for client VDR instances "forces" all DVB - cards for master VDR. - - Each VDR instance must have its own configuration directory (-c option). - - Each xineliboutput server uses different port - - Streamdev plugin is used to provide live view for client - VDR's. It is not required to just watch recordings. - To correctly configure vdr-streamdev plugin, see - streamdev plugin's README. - - Using suspendoutput plugin with some proper timeout value - in VDR instances might be good idea - it releases - streamdev VTP connection and server-side DVB devices - for other use when the client is not in use. - - Starting clients: - - Client 1: vdr-sxfe - - Client 2: vdr-sxfe xvdr://:37892 - - Client 3: vdr-sxfe xvdr://:37894 - - - If RTP is used between vdr and vdr-sxfe, using separate - RTP address or port for each xineliboutput server - instance might be good idea. - - -VDR Logo - - The VDR logo was designed by Jan Grell. - diff --git a/black_720x576.mpg b/black_720x576.mpg deleted file mode 100644 index 1d466be0..00000000 Binary files a/black_720x576.mpg and /dev/null differ diff --git a/config.c b/config.c deleted file mode 100644 index 97a48ef8..00000000 --- a/config.c +++ /dev/null @@ -1,806 +0,0 @@ -/* - * config.c: User settings - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: config.c,v 1.61 2008-04-14 13:19:45 phintuka Exp $ - * - */ - -#include -#include -#include -#include - -#include -#include -#include - -#include "logdefs.h" -#include "config.h" -#include "i18n.h" - -#define STRN0CPY(dst, src) \ - do { \ - strn0cpy(dst, src, sizeof(dst)); \ - if(strlen(src) >= sizeof(dst)) \ - LOGMSG("WARNING: Setting %s truncated to %s !", Name, dst); \ - } while(0) - - -#define DEFAULT_DEINTERLACE_OPTS "method=Linear,cheap_mode=1,pulldown=0,use_progressive_frame_flag=1" - -const int config_t::i_pesBufferSize[ PES_BUFFERS_count+1 ] = { - 0, 50, 250, 500, 1000, 2000, 500 -}; - -const char * const config_t::s_bufferSize[ PES_BUFFERS_count+1 ] = { - trNOOP("custom"), - trNOOP("tiny"), - trNOOP("small"), - trNOOP("medium"), - trNOOP("large"), - trNOOP("huge"), - NULL -}; - -const char * const config_t::s_aspects[ ASPECT_count+1 ] = { - trNOOP("automatic"), - trNOOP("default"), - "4:3", - "16:9", - "16:10", - trNOOP("Pan&Scan"), - trNOOP("CenterCutOut"), - NULL -}; - -const char * const config_t::s_vo_aspects[ VO_ASPECT_count+1 ] = { - trNOOP("automatic"), - trNOOP("square"), - "4:3", - trNOOP("anamorphic"), - trNOOP("DVB"), - NULL -}; - - -const char * const config_t::s_deinterlaceMethods[ DEINTERLACE_count+1 ] = { - "none", - "bob", - "weave", - "greedy", - "onefield", - "onefield_xv", - "linearblend", - "tvtime", - NULL -}; - -const char * const config_t::s_deinterlaceMethodNames[ DEINTERLACE_count+1 ] = { - trNOOP("off"), - "Bob", - "Weave", - "Greedy", - "One Field", - "One Field XV", - "Linear Blend", - "TvTime", - NULL -}; - -const char * const config_t::s_fieldOrder[ FIELD_ORDER_count+1 ] = { - trNOOP("normal"), - trNOOP("inverted"), - NULL -}; - -const char * const config_t::s_audioDrivers[ AUDIO_DRIVER_count+1 ] = { - "auto", "alsa", "oss", "none", "esd", "jack", - NULL -}; - -const char * const config_t::s_audioDriverNames[ AUDIO_DRIVER_count+1 ] = { - trNOOP("automatic"), - "Alsa", - "OSS", - trNOOP("no audio"), - "ESD", - "Jack", - NULL -}; - -const char * const config_t::s_videoDriversX11[ X11_DRIVER_count+1 ] = { - "auto", "xshm", "xv", "xvmc", "xxmc", "vidix", "XDirectFB", "opengl", "sdl", "none", - NULL -}; - -const char * const config_t::s_videoDriverNamesX11[ X11_DRIVER_count+1 ] = { - trNOOP("automatic"), - "XShm", - "Xv", - "XvMC", - "XvMC+VLD", - "Vidix", - "XDirectFB", - "OpenGL", - "SDL", - trNOOP("no video"), - NULL -}; - -const char * const config_t::s_videoDriversFB[ FB_DRIVER_count+1 ] = { - "auto", "fb", "DirectFB", "sdl", "vidixfb", "aadxr3", "none", - NULL -}; - -const char * const config_t::s_videoDriverNamesFB [ FB_DRIVER_count+1 ] = { - trNOOP("automatic"), - "Framebuffer", - "DirectFB", - "SDL", - "VidixFB", - "DXR3", - trNOOP("no video"), - NULL -}; - -const char * const config_t::s_frontends[ FRONTEND_count+1 ] = { - "sxfe", "fbfe", "none", - NULL -}; - -const char * const config_t::s_frontendNames[ FRONTEND_count+1 ] = { - "X11 (sxfe)", - "Framebuffer (fbfe)", - trNOOP("Off"), - NULL -}; - -const char * const config_t::s_frontend_files[ FRONTEND_count+1 ] = { - "lib" PLUGIN_NAME_I18N "-sxfe.so." XINELIBOUTPUT_VERSION, - "lib" PLUGIN_NAME_I18N "-fbfe.so." XINELIBOUTPUT_VERSION, - // example: libxineliboutput-sxfe.so.0.4.0 - "", - NULL -}; - -const char * const config_t::s_audioEqNames[ AUDIO_EQ_count+1 ] = { - "30 Hz", "60 Hz", "125 Hz", "250 Hz", "500 Hz", - "1 kHz", "2 kHz", "4 kHz", "8 kHz", "16 kHz", - NULL -}; - -const char * const config_t::s_audioVisualizations[ AUDIO_VIS_count+1 ] = { - "none", "goom", "oscope", "fftscope", "fftgraph", - NULL -}; - -const char * const config_t::s_audioVisualizationNames[ AUDIO_VIS_count+1 ] = { - trNOOP("Off"), - trNOOP("Goom"), - trNOOP("Oscilloscope"), - trNOOP("FFT Scope"), - trNOOP("FFT Graph"), - NULL -}; - -/* xine, audio_alsa_out.c */ -const char * const config_t::s_speakerArrangements[ SPEAKERS_count+1 ] = { - trNOOP("Mono 1.0"), trNOOP("Stereo 2.0"), trNOOP("Headphones 2.0"), trNOOP("Stereo 2.1"), - trNOOP("Surround 3.0"), trNOOP("Surround 4.0"), trNOOP("Surround 4.1"), - trNOOP("Surround 5.0"), trNOOP("Surround 5.1"), trNOOP("Surround 6.0"), - trNOOP("Surround 6.1"), trNOOP("Surround 7.1"), trNOOP("Pass Through"), - NULL -}; - -const char * const config_t::s_subtitleSizes[ SUBTITLESIZE_count+1 ] = { - trNOOP("default"), - trNOOP("tiny"), - trNOOP("small"), - trNOOP("medium"), - trNOOP("large"), - trNOOP("very large"), - trNOOP("huge"), - NULL -}; - -const char * const config_t::s_subExts[] = { - ".sub", ".srt", ".txt", ".ssa", - ".SUB", ".SRT", ".TXT", ".SSA", - NULL -}; - -const char * const config_t::s_osdMixers[] = { - trNOOP("no"), - trNOOP("grayscale"), // item [1] - trNOOP("transparent"), // item [2] - trNOOP("transparent grayscale"), // item [3] ([1 | 2]) - trNOOP("yes"), - NULL -}; - -const char * const config_t::s_osdScalings[] = { - trNOOP("no"), - trNOOP("nearest"), // item [1] - trNOOP("bilinear"), // item [2] - NULL -}; - -static char *strcatrealloc(char *dest, const char *src) -{ - if (!src || !*src) - return dest; - - int l = (dest ? strlen(dest) : 0) + strlen(src) + 1; - if(dest) { - dest = (char *)realloc(dest, l); - strcat(dest, src); - } else { - dest = (char*)malloc(l); - strcpy(dest, src); - } - return dest; -} - -bool config_t::IsPlaylistFile(const char *fname) -{ - if(fname) { - char *pos = strrchr(fname,'.'); - if(pos) { - pos++; - if(!strcasecmp(pos, "pls") || - !strcasecmp(pos, "m3u") || - !strcasecmp(pos, "ram") || - !strcasecmp(pos, "asx")) - return true; - } - } - return false; -} - -bool config_t::IsAudioFile(const char *fname) -{ - if(fname) { - char *pos = strrchr(fname,'.'); - if(pos) { - pos++; - if(!strcasecmp(pos, "mpa") || - !strcasecmp(pos, "mp2") || - !strcasecmp(pos, "mp3") || - !strcasecmp(pos, "m4a") || - !strcasecmp(pos, "mpega") || - !strcasecmp(pos, "flac") || - !strcasecmp(pos, "ac3") || - !strcasecmp(pos, "ogg") || - !strcasecmp(pos, "ogm") || - !strcasecmp(pos, "au") || - !strcasecmp(pos, "aud") || - !strcasecmp(pos, "wma") || - !strcasecmp(pos, "asf") || - !strcasecmp(pos, "wav") || - !strcasecmp(pos, "spx") || - !strcasecmp(pos, "ra")) - return true; - return IsPlaylistFile(fname); - } - } - return false; -} - -bool config_t::IsVideoFile(const char *fname) -{ - if(fname) { - char *pos = strrchr(fname,'.'); - if(pos) { - pos++; - if(!strcasecmp(pos, "avi") || - !strcasecmp(pos, "mpv") || - !strcasecmp(pos, "m2v") || - !strcasecmp(pos, "m4v") || - !strcasecmp(pos, "vob") || - !strcasecmp(pos, "vdr") || - !strcasecmp(pos, "mpg") || - !strcasecmp(pos, "mpeg")|| - !strcasecmp(pos, "mp4") || - !strcasecmp(pos, "asf") || - !strcasecmp(pos, "wmv") || - !strcasecmp(pos, "mov") || - !strcasecmp(pos, "ts") || - !strcasecmp(pos, "pes") || - !strcasecmp(pos, "xvid") || - !strcasecmp(pos, "divx") || - !strcasecmp(pos, "fli") || - !strcasecmp(pos, "flv") || - !strcasecmp(pos, "dv") || - !strcasecmp(pos, "dat") || - !strcasecmp(pos, "mkv") || - !strcasecmp(pos, "rm") || - !strcasecmp(pos, "iso")) /* maybe dvd */ - return true; - return IsAudioFile(fname); - } - } - return false; -} - -bool config_t::IsImageFile(const char *fname) -{ - if(fname) { - char *pos = strrchr(fname,'.'); - if(pos) { - pos++; - if(!strcasecmp(pos, "jpg") || - !strcasecmp(pos, "jpeg") || - !strcasecmp(pos, "gif") || - !strcasecmp(pos, "tiff") || - !strcasecmp(pos, "bmp") || - !strcasecmp(pos, "mng") || - !strcasecmp(pos, "png")) - return true; - } - } - return false; -} - -cString config_t::AutocropOptions(void) -{ - if (!autocrop) - return NULL; - - return cString::sprintf("enable_autodetect=%d,soft_start=%d,stabilize=%d,enable_subs_detect=%d", - autocrop_autodetect, autocrop_soft, autocrop_fixedsize, autocrop_subs); -} - -cString config_t::SwScaleOptions(void) -{ - if (!swscale) - return NULL; - - return cString::sprintf("output_aspect=%s,output_width=%d,output_height=%d,no_downscaling=%d", - swscale_change_aspect ? "auto" : "0.0", - swscale_resize ? swscale_width : 0, - swscale_resize ? swscale_height : 0, - swscale_downscale ? 0 : 1 ); -} - -cString config_t::FfmpegPpOptions(void) -{ - if (!ffmpeg_pp) - return NULL; - - if(*ffmpeg_pp_mode) - return cString::sprintf("quality=%d,mode=%s", ffmpeg_pp_quality, ffmpeg_pp_mode); - - return cString::sprintf("quality=%d", ffmpeg_pp_quality); -} - -cString config_t::UnsharpOptions(void) -{ - if (!unsharp) - return NULL; - - return cString::sprintf("luma_matrix_width=%d,luma_matrix_height=%d,luma_amount=%1.1f," - "chroma_matrix_width=%d,chroma_matrix_height=%d,chroma_amount=%1.1f", - unsharp_luma_matrix_width, unsharp_luma_matrix_height, - ((float)unsharp_luma_amount)/10.0, - unsharp_chroma_matrix_width, unsharp_chroma_matrix_height, - ((float)unsharp_chroma_amount)/10.0); -} - -cString config_t::Denoise3dOptions(void) -{ - if (!denoise3d) - return NULL; - - return cString::sprintf("luma=%1.1f,chroma=%1.1f,time=%1.1f", - ((float)denoise3d_luma)/10.0, - ((float)denoise3d_chroma)/10.0, - ((float)denoise3d_time)/10.0); -} - -config_t::config_t() { - memset(this, 0, sizeof(config_t)); - - strn0cpy(local_frontend, s_frontends[FRONTEND_X11], sizeof(local_frontend)); - strn0cpy(video_driver , s_videoDriversX11[X11_DRIVER_XV], sizeof(video_driver)); - strn0cpy(video_port , "0.0", sizeof(video_port)); - strn0cpy(modeline , "", sizeof(modeline)); - - strn0cpy(audio_driver , s_audioDrivers[AUDIO_DRIVER_ALSA], sizeof(audio_driver)); - strn0cpy(audio_port , "default", sizeof(audio_port)); - speaker_type = SPEAKERS_STEREO; - - post_plugins = NULL; - - audio_delay = 0; - audio_compression = 0; - memset(audio_equalizer,0,sizeof(audio_equalizer)); - strn0cpy(audio_visualization, "goom", sizeof(audio_visualization)); - strn0cpy(audio_vis_goom_opts, "fps:25,width:720,height:576", sizeof(audio_vis_goom_opts)); - - headphone = 0; - audio_upmix = 0; - audio_surround = 0; - sw_volume_control = 0; - - pes_buffers = i_pesBufferSize[PES_BUFFERS_SMALL_250]; - strn0cpy(deinterlace_method, s_deinterlaceMethods[DEINTERLACE_NONE], sizeof(deinterlace_method)); - strn0cpy(deinterlace_opts, DEFAULT_DEINTERLACE_OPTS, sizeof(deinterlace_opts)); - ffmpeg_pp = 0; - ffmpeg_pp_quality = 3; - strn0cpy(ffmpeg_pp_mode, "de", sizeof(ffmpeg_pp_mode)); - subtitle_vpos = 0; - - unsharp = 0; - unsharp_luma_matrix_width = 5; - unsharp_luma_matrix_height = 5; - unsharp_luma_amount = 0; - unsharp_chroma_matrix_width = 3; - unsharp_chroma_matrix_height = 3; - unsharp_chroma_amount = 0; - - denoise3d = 0; - denoise3d_luma = 40; - denoise3d_chroma = 30; - denoise3d_time = 60; - - display_aspect = 0; /* auto */ - - hide_main_menu = 0; - osd_mixer = OSD_MIXER_FULL; - osd_scaling = OSD_SCALING_NEAREST; - hud_osd = 0; - - unscaled_osd = 0; - unscaled_osd_lowresvideo = 1; - -#if VDRVERSNUM < 10515 - spu_autoshow = 0; - memset(spu_lang, 0, sizeof(spu_lang)); - strn0cpy(spu_lang[0], "eng", sizeof(spu_lang[0])); - strn0cpy(spu_lang[1], "deu", sizeof(spu_lang[1])); - strn0cpy(spu_lang[2], "fin", sizeof(spu_lang[2])); - strn0cpy(spu_lang[3], "" , sizeof(spu_lang[3])); -#endif - extsub_size = -1; - - alpha_correction = 0; - alpha_correction_abs = 0; - - fullscreen = 0; - modeswitch = 1; - width = 720; - height = 576; - scale_video = 0; - field_order = 0; - autocrop = 0; - autocrop_autodetect = 1; - autocrop_soft = 1; - autocrop_fixedsize = 1; - autocrop_subs = 1; - - swscale = 0; // enable/disable - swscale_change_aspect = 0; // change video aspect ratio - swscale_resize = 0; // change video size - swscale_width = 720; // output video width - swscale_height = 576; // output video height - swscale_downscale = 0; // allow downscaling - - remote_mode = 0; - listen_port = LISTEN_PORT; - remote_keyboard = 1; - remote_usetcp = 1; - remote_useudp = 1; - remote_usertp = 1; - remote_usepipe = 1; - remote_usebcast = 1; - remote_http_files = 1; /* allow http streaming of media files to xineliboutput clients - * (currently replayed media file from xineliboutput media player) - * - will be used if client can't access file directly (nfs etc.) */ - - strn0cpy(remote_rtp_addr, "224.0.1.9", sizeof(remote_rtp_addr)); - remote_rtp_port = (LISTEN_PORT) & (0xfffe); /* even ports only */ - remote_rtp_ttl = 1; - remote_rtp_always_on = 0; - remote_rtp_sap = 1; - - remote_use_rtsp = 1; // allow generic rtsp for primary device. needs enabled udp or rtp - remote_use_rtsp_ctrl = 0; // allow rtsp to control primary device (play/pause/seek...) - remote_use_http = 1; // allow generic http streaming (primary device output) - remote_use_http_ctrl = 0; // allow http to control primary device (play/pause/seek...) - - remote_local_if[0] = 0; // use only this interface - undefined -> any/all - remote_local_ip[0] = 0; // bind locally to this IP - undefined -> any/all - - use_x_keyboard = 1; - - // video settings -#ifdef DEVICE_SUPPORTS_IBP_TRICKSPEED - ibp_trickspeed = 1; -#else - ibp_trickspeed = 0; -#endif - max_trickspeed = 12; - overscan = 0; - hue = -1; - saturation = -1; - contrast = -1; - brightness = -1; - vo_aspect_ratio = 0; - - live_mode_sync = 1; // Sync SCR to transponder clock in live mode - scr_tunning = 0; // Fine-tune xine egine SCR (to sync video to graphics output) - scr_hz = 90000; // Current SCR speed (Hz), default is 90000 - - strn0cpy(browse_files_dir, VideoDirectory, sizeof(browse_files_dir)); - strn0cpy(browse_music_dir, VideoDirectory, sizeof(browse_music_dir)); - strn0cpy(browse_images_dir, VideoDirectory, sizeof(browse_images_dir)); - cache_implicit_playlists = 1; - enable_id3_scanner = 1; - - main_menu_mode = ShowMenu; - force_primary_device = 0; -}; - -static uint8_t g_hidden_options[sizeof(config_t)] = {0}; -static uint8_t g_readonly_options[sizeof(config_t)] = {0}; -uint8_t *config_t::hidden_options = &g_hidden_options[0]; -uint8_t *config_t::readonly_options = &g_readonly_options[0]; - -cString config_t::m_ProcessedArgs; -bool config_t::ProcessArg(const char *Name, const char *Value) -{ - if(SetupParse(Name, Value)) { - m_ProcessedArgs = cString::sprintf("%s%s ", *m_ProcessedArgs ? *m_ProcessedArgs : " ", Name); - return true; - } - return false; -} - -bool config_t::ProcessArgs(int argc, char *argv[]) -{ - static const char short_options[] = "fDw:h:l:r:A:V:d:P:pc"; - - static const struct option long_options[] = { - { "fullscreen", no_argument, NULL, 'f' }, - { "hud", no_argument, NULL, 'D' }, - { "width", required_argument, NULL, 'w' }, - { "height", required_argument, NULL, 'h' }, - //{ "xkeyboard", no_argument, NULL, 'k' }, - //{ "noxkeyboard", no_argument, NULL, 'K' }, - { "local", required_argument, NULL, 'l' }, - //{ "modeline", required_argument, NULL, 'm' }, - { "remote", required_argument, NULL, 'r' }, - { "audio", required_argument, NULL, 'A' }, - { "video", required_argument, NULL, 'V' }, - { "display", required_argument, NULL, 'd' }, - { "post", required_argument, NULL, 'P' }, - { "primary", no_argument, NULL, 'p' }, - { "exit-on-close",no_argument, NULL, 'c' }, - { NULL } - }; - - int c; - while ((c = getopt_long(argc, argv, short_options, long_options, NULL)) != -1) { - switch (c) { - case 'd': ProcessArg("Video.Port", optarg); - break; - case 'f': ProcessArg("Fullscreen", "1"); - break; - case 'D': ProcessArg("X11.HUDOSD", "1"); - break; - case 'w': ProcessArg("Fullscreen", "0"); - ProcessArg("X11.WindowWidth", optarg); - break; - case 'h': ProcessArg("Fullscreen", "0"); - ProcessArg("X11.WindowHeight", optarg); - break; - //case 'k': ProcessArg("X11.UseKeyboard", "1"); - // break; - //case 'K': ProcessArg("X11.UseKeyboard", "0"); - // break; - case 'l': ProcessArg("Frontend", optarg); - break; - //case 'm': ProcessArg("Modeline", optarg); - // break; - case 'r': if(strcmp(optarg, "none")) { - if(strchr(optarg, ':')) { - char *tmp = strdup(optarg); - char *pt = strchr(tmp,':'); - *pt++ = 0; - ProcessArg("Remote.ListenPort", pt); - ProcessArg("RemoteMode", listen_port>0 ? "1" : "0"); - ProcessArg("Remote.LocalIP", tmp); - free(tmp); - LOGMSG("Listening on address \'%s\' port %d", remote_local_ip, listen_port); - } else { - ProcessArg("Remote.ListenPort", optarg); - ProcessArg("RemoteMode", listen_port>0 ? "1" : "0"); - } - } else - ProcessArg("RemoteMode", "0"); - break; - case 'V': ProcessArg("Video.Driver", optarg); - break; - case 'A': if(strchr(optarg,':')) { - char *tmp = strdup(optarg); - char *pt = strchr(tmp,':'); - *pt = 0; - ProcessArg("Audio.Driver", tmp); - ProcessArg("Audio.Port", pt+1); - free(tmp); - } else - ProcessArg("Audio.Driver", optarg); - break; - case 'P': if(post_plugins) - post_plugins = strcatrealloc(post_plugins, ";"); - post_plugins = strcatrealloc(post_plugins, optarg); - break; - case 'p': ProcessArg("ForcePrimaryDevice", "1"); - break; - case 'c': exit_on_close = 1; - break; - - default: return false; - } - } - return true; -} - -bool config_t::SetupParse(const char *Name, const char *Value) -{ - char *pt; - if(*m_ProcessedArgs && NULL != (pt=strstr(m_ProcessedArgs+1, Name)) && - *(pt-1) == ' ' && *(pt+strlen(Name)) == ' ') { - LOGDBG("Skipping configuration entry %s=%s (overridden in command line)", Name, Value); - return true; - } - - if (!strcasecmp(Name, "Frontend")) STRN0CPY(local_frontend, Value); - else if (!strcasecmp(Name, "Modeline")) STRN0CPY(modeline, Value); - else if (!strcasecmp(Name, "VideoModeSwitching")) modeswitch = atoi(Value); - else if (!strcasecmp(Name, "Fullscreen")) fullscreen = atoi(Value); - else if (!strcasecmp(Name, "DisplayAspect")) display_aspect = strstra(Value, s_aspects, 0); - else if (!strcasecmp(Name, "ForcePrimaryDevice")) force_primary_device = atoi(Value); - - else if (!strcasecmp(Name, "X11.WindowWidth")) width = atoi(Value); - else if (!strcasecmp(Name, "X11.WindowHeight")) height = atoi(Value); - else if (!strcasecmp(Name, "X11.UseKeyboard")) use_x_keyboard = atoi(Value); - else if (!strcasecmp(Name, "X11.HUDOSD")) hud_osd = atoi(Value); - - else if (!strcasecmp(Name, "Audio.Driver")) STRN0CPY(audio_driver, Value); - else if (!strcasecmp(Name, "Audio.Port")) STRN0CPY(audio_port, Value); - else if (!strcasecmp(Name, "Audio.Speakers")) speaker_type = strstra(Value, s_speakerArrangements, - SPEAKERS_STEREO); - else if (!strcasecmp(Name, "Audio.Delay")) audio_delay = atoi(Value); - else if (!strcasecmp(Name, "Audio.Compression")) audio_compression = atoi(Value); - else if (!strcasecmp(Name, "Audio.Visualization.GoomOpts")) STRN0CPY(audio_vis_goom_opts, Value); - else if (!strcasecmp(Name, "Audio.Visualization")) STRN0CPY(audio_visualization, Value); - else if (!strcasecmp(Name, "Audio.Surround")) audio_surround = atoi(Value); - else if (!strcasecmp(Name, "Audio.Upmix")) audio_upmix = atoi(Value); - else if (!strcasecmp(Name, "Audio.Headphone")) headphone = atoi(Value); - else if (!strcasecmp(Name, "Audio.SoftwareVolumeControl")) sw_volume_control = atoi(Value); - - else if (!strcasecmp(Name, "OSD.HideMainMenu")) hide_main_menu = atoi(Value); - else if (!strcasecmp(Name, "OSD.LayersVisible")) osd_mixer = atoi(Value); - else if (!strcasecmp(Name, "OSD.Scaling")) osd_scaling = atoi(Value); - else if (!strcasecmp(Name, "OSD.UnscaledAlways")) unscaled_osd = atoi(Value); - else if (!strcasecmp(Name, "OSD.UnscaledLowRes")) unscaled_osd_lowresvideo = atoi(Value); - - else if (!strcasecmp(Name, "OSD.AlphaCorrection")) alpha_correction = atoi(Value); - else if (!strcasecmp(Name, "OSD.AlphaCorrectionAbs")) alpha_correction_abs = atoi(Value); - -#if VDRVERSNUM < 10515 - else if (!strcasecmp(Name, "OSD.SpuAutoSelect")) spu_autoshow = atoi(Value); - else if (!strcasecmp(Name, "OSD.SpuLang0")) STRN0CPY(spu_lang[0], Value); - else if (!strcasecmp(Name, "OSD.SpuLang1")) STRN0CPY(spu_lang[1], Value); - else if (!strcasecmp(Name, "OSD.SpuLang2")) STRN0CPY(spu_lang[2], Value); - else if (!strcasecmp(Name, "OSD.SpuLang3")) STRN0CPY(spu_lang[3], Value); -#endif - else if (!strcasecmp(Name, "OSD.ExtSubSize")) extsub_size = atoi(Value); - - else if (!strcasecmp(Name, "RemoteMode")) remote_mode = atoi(Value); - else if (!strcasecmp(Name, "Remote.ListenPort")) listen_port = atoi(Value); - else if (!strcasecmp(Name, "Remote.Keyboard")) remote_keyboard = atoi(Value); - else if (!strcasecmp(Name, "Remote.UseTcp")) remote_usetcp = atoi(Value); - else if (!strcasecmp(Name, "Remote.UseUdp")) remote_useudp = atoi(Value); - else if (!strcasecmp(Name, "Remote.UseRtp")) remote_usertp = atoi(Value); - else if (!strcasecmp(Name, "Remote.UsePipe")) remote_usepipe= atoi(Value); - else if (!strcasecmp(Name, "Remote.UseHttp")) remote_http_files = atoi(Value); - else if (!strcasecmp(Name, "Remote.UseBroadcast")) remote_usebcast = atoi(Value); - - else if (!strcasecmp(Name, "Remote.Rtp.Address")) STRN0CPY(remote_rtp_addr, Value); - else if (!strcasecmp(Name, "Remote.Rtp.Port")) remote_rtp_port = (atoi(Value)) & (0xfffe); - else if (!strcasecmp(Name, "Remote.Rtp.TTL")) remote_rtp_ttl = atoi(Value); - else if (!strcasecmp(Name, "Remote.Rtp.AlwaysOn")) remote_rtp_always_on = atoi(Value); - else if (!strcasecmp(Name, "Remote.Rtp.SapAnnouncements")) remote_rtp_sap = atoi(Value); - - else if (!strcasecmp(Name, "Remote.AllowRtsp")) remote_use_rtsp = atoi(Value); - else if (!strcasecmp(Name, "Remote.AllowRtspCtrl")) remote_use_rtsp_ctrl = atoi(Value); - else if (!strcasecmp(Name, "Remote.AllowHttp")) remote_use_http = atoi(Value); - else if (!strcasecmp(Name, "Remote.AllowHttpCtrl")) remote_use_http_ctrl = atoi(Value); - - else if (!strcasecmp(Name, "Remote.Iface")) STRN0CPY(remote_local_if, Value); - else if (!strcasecmp(Name, "Remote.LocalIP")) STRN0CPY(remote_local_ip, Value); - - else if (!strcasecmp(Name, "Decoder.PesBuffers")) pes_buffers=atoi(Value); - - else if (!strcasecmp(Name, "Video.Driver")) STRN0CPY(video_driver, Value); - else if (!strcasecmp(Name, "Video.Port")) STRN0CPY(video_port, Value); - else if (!strcasecmp(Name, "Video.Scale")) scale_video = atoi(Value); - else if (!strcasecmp(Name, "Video.DeinterlaceOptions")) STRN0CPY(deinterlace_opts, Value); - else if (!strcasecmp(Name, "Video.Deinterlace")) STRN0CPY(deinterlace_method, Value); - else if (!strcasecmp(Name, "Video.FieldOrder")) field_order=atoi(Value)?1:0; - else if (!strcasecmp(Name, "Video.AutoCrop")) autocrop = atoi(Value); - else if (!strcasecmp(Name, "Video.AutoCrop.AutoDetect")) autocrop_autodetect = atoi(Value); - else if (!strcasecmp(Name, "Video.AutoCrop.SoftStart")) autocrop_soft = atoi(Value); - else if (!strcasecmp(Name, "Video.AutoCrop.FixedSize")) autocrop_fixedsize = atoi(Value); - else if (!strcasecmp(Name, "Video.AutoCrop.DetectSubs")) autocrop_subs = atoi(Value); - - else if (!strcasecmp(Name, "Video.SwScale")) swscale = atoi(Value); - else if (!strcasecmp(Name, "Video.SwScale.Aspect")) swscale_change_aspect = atoi(Value); - else if (!strcasecmp(Name, "Video.SwScale.Resize")) swscale_resize = atoi(Value); - else if (!strcasecmp(Name, "Video.SwScale.Downscale")) swscale_downscale = atoi(Value); - else if (!strcasecmp(Name, "Video.SwScale.Width")) swscale_width = atoi(Value); - else if (!strcasecmp(Name, "Video.SwScale.Height")) swscale_height = atoi(Value); - - else if (!strcasecmp(Name, "Video.HUE")) hue = atoi(Value); - else if (!strcasecmp(Name, "Video.Saturation")) saturation = atoi(Value); - else if (!strcasecmp(Name, "Video.Contrast")) contrast = atoi(Value); - else if (!strcasecmp(Name, "Video.Brightness")) brightness = atoi(Value); - else if (!strcasecmp(Name, "Video.Overscan")) overscan = atoi(Value); - else if (!strcasecmp(Name, "Video.IBPTrickSpeed")) ibp_trickspeed = atoi(Value); - else if (!strcasecmp(Name, "Video.MaxTrickSpeed")) max_trickspeed = atoi(Value); - else if (!strcasecmp(Name, "Video.AspectRatio")) vo_aspect_ratio = atoi(Value); - - else if (!strcasecmp(Name, "Post.pp.Enable")) ffmpeg_pp = atoi(Value); - else if (!strcasecmp(Name, "Post.pp.Quality")) ffmpeg_pp_quality = atoi(Value); - else if (!strcasecmp(Name, "Post.pp.Mode")) STRN0CPY(ffmpeg_pp_mode, Value); - else if (!strcasecmp(Name, "Post.unsharp.Enable")) unsharp = atoi(Value); - else if (!strcasecmp(Name, "Post.unsharp.luma_matrix_width")) unsharp_luma_matrix_width = atoi(Value); - else if (!strcasecmp(Name, "Post.unsharp.luma_matrix_height")) unsharp_luma_matrix_height = atoi(Value); - else if (!strcasecmp(Name, "Post.unsharp.luma_amount")) unsharp_luma_amount = atoi(Value); - else if (!strcasecmp(Name, "Post.unsharp.chroma_matrix_width")) unsharp_chroma_matrix_width = atoi(Value); - else if (!strcasecmp(Name, "Post.unsharp.chroma_matrix_height")) unsharp_chroma_matrix_height = atoi(Value); - else if (!strcasecmp(Name, "Post.unsharp.chroma_amount")) unsharp_chroma_amount = atoi(Value); - else if (!strcasecmp(Name, "Post.denoise3d.Enable")) denoise3d = atoi(Value); - else if (!strcasecmp(Name, "Post.denoise3d.luma")) denoise3d_luma = atoi(Value); - else if (!strcasecmp(Name, "Post.denoise3d.chroma")) denoise3d_chroma = atoi(Value); - else if (!strcasecmp(Name, "Post.denoise3d.time")) denoise3d_time = atoi(Value); -#if 1 // 1.0.0pre6 - else if (!strcasecmp(Name, "BrowseFilesDir")) STRN0CPY(browse_files_dir, Value); - else if (!strcasecmp(Name, "BrowseMusicDir")) STRN0CPY(browse_music_dir, Value); - else if (!strcasecmp(Name, "BrowseImagesDir")) STRN0CPY(browse_images_dir, Value); -#endif - else if (!strcasecmp(Name, "Media.BrowseFilesDir")) STRN0CPY(browse_files_dir, Value); - else if (!strcasecmp(Name, "Media.BrowseMusicDir")) STRN0CPY(browse_music_dir, Value); - else if (!strcasecmp(Name, "Media.BrowseImagesDir")) STRN0CPY(browse_images_dir, Value); - else if (!strcasecmp(Name, "Media.CacheImplicitPlaylists")) cache_implicit_playlists = atoi(Value); - else if (!strcasecmp(Name, "Media.EnableID3Scanner")) enable_id3_scanner = atoi(Value); - else if (!strcasecmp(Name, "Playlist.Tracknumber")) playlist_tracknumber = atoi(Value); - else if (!strcasecmp(Name, "Playlist.Artist")) playlist_artist = atoi(Value); - else if (!strcasecmp(Name, "Playlist.Album")) playlist_album = atoi(Value); - - else if (!strcasecmp(Name, "Advanced.LiveModeSync")) xc.live_mode_sync = atoi(Value); - else if (!strcasecmp(Name, "Advanced.AdjustSCR")) xc.scr_tunning = atoi(Value); - else if (!strcasecmp(Name, "Advanced.SCRSpeed")) xc.scr_hz = atoi(Value); - - else if (!strcasecmp(Name, "Audio.Equalizer")) - sscanf(Value,"%d %d %d %d %d %d %d %d %d %d", - audio_equalizer ,audio_equalizer+1, - audio_equalizer+2,audio_equalizer+3, - audio_equalizer+4,audio_equalizer+5, - audio_equalizer+6,audio_equalizer+7, - audio_equalizer+8,audio_equalizer+9); - - else return false; - - return true; -} - -/* Global instance */ -config_t xc; - - diff --git a/config.h b/config.h deleted file mode 100644 index 88f31a7a..00000000 --- a/config.h +++ /dev/null @@ -1,393 +0,0 @@ -/* - * config.h: Global configuration and user settings - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: config.h,v 1.45 2008-04-14 14:13:15 phintuka Exp $ - * - */ - -#ifndef _XINELIB_CONFIG_H_ -#define _XINELIB_CONFIG_H_ - -#include -#include - -#include - -// Decoder buffer size -#define PES_BUFFERS_CUSTOM 0 -#define PES_BUFFERS_TINY_50 1 -#define PES_BUFFERS_SMALL_250 2 -#define PES_BUFFERS_MEDIUM_500 3 -#define PES_BUFFERS_LARGE_1000 4 -#define PES_BUFFERS_HUGE_2000 5 -#define PES_BUFFERS_count 6 - -// Output window aspect ratio -#define ASPECT_AUTO 0 -#define ASPECT_DEFAULT 1 -#define ASPECT_4_3 2 -#define ASPECT_16_9 3 -#define ASPECT_16_10 4 -#define ASPECT_PAN_SCAN 5 -#define ASPECT_CENTER_CUT_OUT 6 -#define ASPECT_count 7 - -// VIDEO OUTPUT ASPECT RATIO -#define VO_ASPECT_AUTO 0 -#define VO_ASPECT_SQUARE 1 /* 1:1 */ -#define VO_ASPECT_4_3 2 /* 4:3 */ -#define VO_ASPECT_ANAMORPHIC 3 /* 16:9 */ -#define VO_ASPECT_DVB 4 /* 2.11:1 */ -#define VO_ASPECT_count 5 - -// De-interlace method -#define DEINTERLACE_NONE 0 -#define DEINTERLACE_BOB 1 -#define DEINTERLACE_WEAVE 2 -#define DEINTERLACE_GREEDY 3 -#define DEINTERLACE_ONEFIELD 4 -#define DEINTERLACE_ONEFIELD_XV 5 -#define DEINTERLACE_LINEARLEND 6 -#define DEINTERLACE_TVTIME 7 -#define DEINTERLACE_count 8 - -#define FIELD_ORDER_NORMAL 0 -#define FIELD_ORDER_INVERTED 1 -#define FIELD_ORDER_count 2 - -// Audio driver -#define AUDIO_DRIVER_AUTO 0 -#define AUDIO_DRIVER_ALSA 1 -#define AUDIO_DRIVER_OSS 2 -#define AUDIO_DRIVER_NONE 3 -#define AUDIO_DRIVER_ESD 4 -#define AUDIO_DRIVER_JACK 5 -#define AUDIO_DRIVER_count 6 - -// Video driver -#define X11_DRIVER_AUTO 0 -#define X11_DRIVER_XSHM 1 -#define X11_DRIVER_XV 2 -#define X11_DRIVER_XVMC 3 -#define X11_DRIVER_XXMC 4 -#define X11_DRIVER_VIDIX 5 -#define X11_DRIVER_DIRECTFB 6 -#define X11_DRIVER_OPENGL 7 -#define X11_DRIVER_SDL 8 -#define X11_DRIVER_NONE 9 -#define X11_DRIVER_count 10 - -#define FB_DRIVER_AUTO 0 -#define FB_DRIVER_FB 1 -#define FB_DRIVER_DIRECTFB 2 -#define FB_DRIVER_SDL 3 -#define FB_DRIVER_VIDIXFB 4 -#define FB_DRIVER_DXR3 5 -#define FB_DRIVER_NONE 6 -#define FB_DRIVER_count 7 - -// Local frontend -#define FRONTEND_X11 0 -#define FRONTEND_FB 1 -#define FRONTEND_NONE 2 -#define FRONTEND_count 3 -#define DEFAULT_FRONTEND "sxfe" - -#define LISTEN_PORT 37890 -#define LISTEN_PORT_S "37890" -#define DISCOVERY_PORT 37890 - -#define AUDIO_EQ_30HZ 0 -#define AUDIO_EQ_60HZ 1 -#define AUDIO_EQ_125HZ 2 -#define AUDIO_EQ_250HZ 3 -#define AUDIO_EQ_500HZ 4 -#define AUDIO_EQ_1000HZ 5 -#define AUDIO_EQ_2000HZ 6 -#define AUDIO_EQ_4000HZ 7 -#define AUDIO_EQ_8000HZ 8 -#define AUDIO_EQ_16000HZ 9 -#define AUDIO_EQ_count 10 - -#define AUDIO_VIS_NONE 0 -#define AUDIO_VIS_GOOM 1 -#define AUDIO_VIS_count 5 - -/* speaker arrangements: xine, audio_out_alsa.c */ -#define SPEAKERS_MONO 0 -#define SPEAKERS_STEREO 1 -#define SPEAKERS_HEADPHONES 2 -#define SPEAKERS_SURROUND21 3 -#define SPEAKERS_SURROUND3 4 -#define SPEAKERS_SURROUND4 5 -#define SPEAKERS_SURROUND41 6 -#define SPEAKERS_SURROUND5 7 -#define SPEAKERS_SURROUND51 8 -#define SPEAKERS_SURROUND6 9 -#define SPEAKERS_SURROUND61 10 -#define SPEAKERS_SURROUND71 11 -#define SPEAKERS_A52_PASSTHRU 12 -#define SPEAKERS_count 13 - -// OSD layers mixing -#define OSD_MIXER_NONE 0 -#define OSD_MIXER_GRAY 1 -#define OSD_MIXER_ALPHA 2 -#define OSD_MIXER_GRAYALPHA 3 // OSD_MIXER_GRAY | OSD_MIXER_ALPHA -#define OSD_MIXER_FULL 4 -#define OSD_MIXER_count 5 - -// OSD scaling modes -#define OSD_SCALING_NONE 0 -#define OSD_SCALING_NEAREST 1 -#define OSD_SCALING_BILINEAR 2 -#define OSD_SCALING_count 3 - -#define SUBTITLESIZE_count 7 - -#define HIDDEN_OPTION(opt) \ - (xc.IsOptionHidden(xc.opt)) -#define READONLY_OPTION(opt) \ - (xc.IsOptionReadOnly(xc.opt)) - -#define DEFAULT_POLL_SIZE 16 - -typedef enum { - ShowMenu = 0, - ShowEq = 1, - ShowFiles = 2, - ShowMusic = 3, - ShowImages = 4, - CloseOsd = 5 -} eMainMenuMode; - -class config_t { - public: - static const char * const s_bufferSize[]; - static const int i_pesBufferSize[]; - static const char * const s_aspects[]; - static const char * const s_deinterlaceMethods[]; - static const char * const s_deinterlaceMethodNames[]; - static const char * const s_fieldOrder[]; - static const char * const s_audioDriverNames[]; - static const char * const s_audioDrivers[]; - static const char * const s_videoDriverNamesX11[]; - static const char * const s_videoDriversX11[]; - static const char * const s_videoDriverNamesFB[]; - static const char * const s_videoDriversFB[]; - static const char * const s_frontendNames[]; - static const char * const s_frontends[]; - static const char * const s_frontend_files[]; - static const char * const s_audioEqNames[]; - static const char * const s_audioVisualizations[]; - static const char * const s_audioVisualizationNames[]; - static const char * const s_speakerArrangements[]; - static const char * const s_subtitleSizes[]; - static const char * const s_subExts[]; - static const char * const s_osdMixers[]; - static const char * const s_osdScalings[]; - static const char * const s_vo_aspects[]; - - public: - - // Force xineliboutput to be the primary device - int force_primary_device; - - // local frontend settings - char local_frontend[64]; - char video_driver[32]; - char video_port[32]; // X11: DISPLAY=... - char audio_driver[32]; - char audio_port[64]; - char *post_plugins; // static post plugins from command line options - int pes_buffers; - - char modeline[64]; - int fullscreen; - int modeswitch; - int width; - int height; - int display_aspect; - int scale_video; - int field_order; - int exit_on_close; // Terminate VDR when local frontend is closed - int use_x_keyboard; // Use X11 keyboard to control VDR (console kbd is handled by VDR) - - // Audio settings - int speaker_type; - int audio_delay; // in ms - int audio_compression; // 100%(=off)...500% - int audio_equalizer[AUDIO_EQ_count]; - int audio_surround; // downmix multichannel audio to stereo surround - int headphone; // mix audio for headphones - int audio_upmix; // upmix stereo to 5.1 - int sw_volume_control; // software (xine-lib) or hardware (alsa) volume control and muting - - // Video settings - int ibp_trickspeed; - int max_trickspeed; - int overscan; // % - int hue; // 0...0xffff, -1 == off - int saturation; // 0...0xffff, -1 == off - int contrast; // 0...0xffff, -1 == off - int brightness; // 0...0xffff, -1 == off - int vo_aspect_ratio; - - // OSD settings - eMainMenuMode main_menu_mode; // used internally to open right sub-menu - int hide_main_menu; - int osd_mixer; // show multiple OSD layers - int osd_scaling; // OSD scaling mode: off, nearest, bilinear - int hud_osd; // head up display OSD - int unscaled_osd; - int unscaled_osd_lowresvideo; - int alpha_correction; - int alpha_correction_abs; - int extsub_size; /* size of separate subtitles ( -1 = xine default ; 0...6 = { tiny small normal large very large huge } */ - - // Media player -#if VDRVERSNUM < 10515 - int spu_autoshow; // Preferred SPU language(s) for media player - char spu_lang[4][4]; -#endif - char browse_files_dir[4096]; - char browse_music_dir[4096]; - char browse_images_dir[4096]; - int cache_implicit_playlists; // used in playlist.c - int enable_id3_scanner; // used in playlist.c - int subtitle_vpos; // used in media player. Not saved ! - int playlist_tracknumber; - int playlist_artist; - int playlist_album; - - // Audio visualization - char audio_visualization[64]; - char audio_vis_goom_opts[256]; - - // deinterlacing post plugin - char deinterlace_method[32]; - char deinterlace_opts[256]; - - // ffmpeg post processing - int ffmpeg_pp; // enable / disable - int ffmpeg_pp_quality; // 0...6 - char ffmpeg_pp_mode[256]; - - // automatic 4:3 letterbox -> 16:9 cropping post plugin - int autocrop; // enable / disable - int autocrop_autodetect; - int autocrop_soft; - int autocrop_fixedsize; - int autocrop_subs; - - // (video) software scaling - int swscale; // enable/disable - int swscale_change_aspect; // change video aspect ratio - int swscale_resize; // change video size - int swscale_width; // output video width - int swscale_height; // output video height - int swscale_downscale; // allow downscaling - - // sharpen / soften post plugin - int unsharp; // enable / disable - int unsharp_luma_matrix_width; // 3..11, should be an odd number - int unsharp_luma_matrix_height; // 3..11, should be an odd number - int unsharp_luma_amount; // Actually a double between -2.0 and 2.0, but handled as a int between -20 and 20 - int unsharp_chroma_matrix_width; // 3..11, should be an odd number - int unsharp_chroma_matrix_height; // 3..11, should be an odd number - int unsharp_chroma_amount; // Actually a double between -2.0 and 2.0, but handled as a int between -20 and 20 - - // 3D noise reduction post plugin - int denoise3d; // enable / disable - int denoise3d_luma; // Actually a double between 0.0 and 10.0, but handled as a int between 0 and 100 - int denoise3d_chroma; // Actually a double between 0.0 and 10.0, but handled as a int between 0 and 100 - int denoise3d_time; // Actually a double between 0.0 and 10.0, but handled as a int between 0 and 100 - - int volnorm; // enable/disable volnorm post plugin (normalize audio volume) - - // Remote server settings - int remote_mode; // Allow remote clients (vdr-sxfe, vdr-fbfe, ...) - int listen_port; // Port of remote server - char remote_local_if[32]; // Listen only on this interface - char remote_local_ip[32]; // Bind locally to this IP - int remote_keyboard; // Allow remote client to control VDR with keyboard, LIRC, etc. - - int remote_usebcast; // Use proadcasts to find servers automatically - int remote_usepipe; // enable local pipes for video transport - int remote_usertp; // enable RTP multicast for video transport - int remote_useudp; // enable UDP unicast for video transport - int remote_usetcp; // enable TCP streams for video transport - int remote_http_files; // allow http streaming of media files to xineliboutput clients - // (=currently replayed media file from xineliboutput media player) - // streaming is used only if client can't access file directly (nfs etc.) - int remote_use_rtsp; // allow generic rtsp for primary device. needs enabled udp or rtp - int remote_use_rtsp_ctrl;// allow rtsp to control primary device (play/pause/seek...) - int remote_use_http; // allow generic http streaming (primary device output) - int remote_use_http_ctrl;// allow http to control primary device (play/pause/seek...) - - // RTP parameters - char remote_rtp_addr[32]; //xxx.xxx.xxx.xxx\0 - int remote_rtp_port; - int remote_rtp_ttl; - int remote_rtp_always_on; - int remote_rtp_sap; - - // Advanced settings - int live_mode_sync; /* Sync SCR to transponder clock in live mode */ - int scr_tunning; /* Fine-tune xine egine SCR (to sync video to graphics output) */ - int scr_hz; /* Current SCR speed (Hz), default is 90000 */ - - config_t(); - - bool SetupParse(const char *Name, const char *Value); - bool ProcessArgs(int argc, char *argv[]); - - bool IsImageFile(const char *); - bool IsAudioFile(const char *); - bool IsVideoFile(const char *); - bool IsPlaylistFile(const char *); - - cString AutocropOptions(void); - cString SwScaleOptions(void); - cString FfmpegPpOptions(void); - cString UnsharpOptions(void); - cString Denoise3dOptions(void); - - template bool IsOptionHidden(T & option) - { return hidden_options[(int)((long int)&option - (long int)this)];}; - template bool IsOptionReadOnly(T & option) - { return readonly_options[(int)((long int)&option - (long int)this)];}; - - protected: - bool ProcessArg(const char *Name, const char *Value); - static cString m_ProcessedArgs; - - static uint8_t *hidden_options; - static uint8_t *readonly_options; - - template void HideOption(T & option) - { hidden_options[(int)((long int)&option - (long int)this)] = 1;}; - template void ReadOnlyOption(T & option) - { readonly_options[(int)((long int)&option - (long int)this)] = 1;}; -}; - -// Global instance -extern config_t xc; - -// Find index of string in array of strings -static inline int strstra(const char * const str, const char * const stra[], int def_index) -{ - if(str && stra) { - int i; - for(i=0; stra[i]; i++) - if(!strcmp(str,stra[i])) - return i; - } - return def_index; -} - -#endif //_XINELIB_CONFIG_H_ - diff --git a/device.c b/device.c deleted file mode 100644 index d2a881c0..00000000 --- a/device.c +++ /dev/null @@ -1,1696 +0,0 @@ -/* - * device.c: xine-lib output device for the Video Disk Recorder - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: device.c,v 1.57 2008-04-14 19:58:50 phintuka Exp $ - * - */ - -#define __STDC_FORMAT_MACROS -#define __STDC_CONSTANT_MACROS -#include - -#include -#include -#include -#include -#include -#include -#include - -//#define XINELIBOUTPUT_DEBUG -//#define XINELIBOUTPUT_DEBUG_STDERR -//#define TRACK_EXEC_TIME -//#define FORWARD_DVD_SPUS -//#define DEBUG_SWITCHING_TIME -//#define LOG_TRICKSPEED -#if VDRVERSNUM >= 10510 -# define DEVICE_SUPPORTS_IBP_TRICKSPEED -#endif - -#include "logdefs.h" -#include "config.h" -#include "osd.h" - -#include "tools/listiter.h" -#include "tools/pes.h" -#include "tools/functor.h" - -#include "frontend_local.h" -#include "frontend_svr.h" - -#include "device.h" - -#define STILLPICTURE_REPEAT_COUNT 3 -#define LOCAL_INIT_TIMEOUT 20 // seconds -#define SERVER_INIT_TIMEOUT 5 // seconds - -#ifdef LOG_TRICKSPEED -# define LOGTRICKSPEED(x...) LOGMSG("trs: " x) -#else -# define LOGTRICKSPEED(x...) -#endif - -//---------------------------- status monitor ------------------------------- - -class cXinelibStatusMonitor : public cStatus -{ - private: - cXinelibStatusMonitor(); - cXinelibStatusMonitor(cXinelibStatusMonitor&); - - public: - cXinelibStatusMonitor(cXinelibDevice& device, int cardIndex) : - m_Device(device), m_cardIndex(cardIndex) - { -#ifdef DEBUG_SWITCHING_TIME - switchtimeOff = 0LL; - switchtimeOn = 0LL; - switchingIframe = false; -#endif - }; - - protected: - virtual void ChannelSwitch(const cDevice *Device, int ChannelNumber); - virtual void Replaying(const cControl *Control, const char *Name, - const char *FileName, bool On); - - cXinelibDevice& m_Device; - int m_cardIndex; - -#ifdef DEBUG_SWITCHING_TIME - public: - int64_t switchtimeOff; - int64_t switchtimeOn; - bool switchingIframe; - - void IFrame(void) - { - if(!switchingIframe) { - int64_t now = cTimeMs::Now(); - switchingIframe = true; - LOGMSG("Channel switch: off -> on %" PRId64 " ms, " - "on -> 1. I-frame %" PRId64 " ms", - switchtimeOn-switchtimeOff, now-switchtimeOn); - } else { - int64_t now = cTimeMs::Now(); - LOGMSG("Channel switch: on -> 2. I-frame %" PRId64 " ms, " - "Total %" PRId64 " ms", - now-switchtimeOn, now-switchtimeOff); - switchtimeOff = 0LL; - switchtimeOn = 0LL; - switchingIframe = false; - } - } -#endif -}; - -void cXinelibStatusMonitor::ChannelSwitch(const cDevice *Device, - int ChannelNumber) -{ - TRACEF("cXinelibStatusMonitor::ChannelSwitch"); - TRACK_TIME(200); - - if (ChannelNumber) { - if (Device->CardIndex() == m_cardIndex) { -#ifdef DEBUG_SWITCHING_TIME - switchtimeOn = cTimeMs::Now(); -#endif - m_Device.SetTvMode(Channels.GetByNumber(ChannelNumber)); - TRACE("cXinelibStatusMonitor: Set to TvMode"); - } - } else { - if (Device->CardIndex() == m_cardIndex) { -#ifdef DEBUG_SWITCHING_TIME - switchtimeOff = cTimeMs::Now(); -#endif - m_Device.StopOutput(); - TRACE("cXinelibStatusMonitor: received stop"); - } - } -} - -void cXinelibStatusMonitor::Replaying(const cControl *Control, - const char *Name, - const char *FileName, bool On) -{ - TRACEF("cXinelibStatusMonitor::Replaying"); - - if (On /*&& Name != NULL*/) { - TRACE("cXinelibStatusMonitor: Replaying " << Name << "(" << FileName << ")"); - m_Device.SetReplayMode(); - } -} - -//----------------------------- device ---------------------------------------- - -// -// Singleton -// - -cXinelibDevice* cXinelibDevice::m_pInstance = NULL; - -cXinelibDevice& cXinelibDevice::Instance(void) -{ - TRACEF("cXinelibDevice::Instance"); - if (!m_pInstance) { - m_pInstance = new cXinelibDevice(); - TRACE("cXinelibDevice::Instance(): create, cardindex = " - << m_pInstance->CardIndex()); - } - - return *m_pInstance; -} - -void cXinelibDevice::Dispose(void) -{ - TRACEF("cXinelibDevice::Dispose"); - delete m_pInstance; - m_pInstance = NULL; -} - -// -// init and shutdown -// - -cXinelibDevice::cXinelibDevice() -{ - TRACEF("cXinelibDevice::cXinelibDevice"); - - m_statusMonitor = NULL; - m_spuDecoder = NULL; - - m_local = NULL; - m_server = NULL; - - m_OriginalPrimaryDevice = 0; - m_ForcePrimaryDeviceCnt = 0; - - if(*xc.local_frontend && strncmp(xc.local_frontend, "none", 4)) - m_clients.Add(m_local = new cXinelibLocal(xc.local_frontend)); - if(xc.remote_mode && xc.listen_port>0) - m_clients.Add(m_server = new cXinelibServer(xc.listen_port)); - - m_ac3Present = false; - m_spuPresent = false; - -#if VDRVERSNUM < 10515 - m_CurrentDvdSpuTrack = ttXSubtitleNone; - m_ForcedDvdSpuTrack = false; - ClrAvailableDvdSpuTracks(); -#endif - - memset(m_MetaInfo, 0, sizeof(m_MetaInfo)); - - m_PlayMode = pmNone; - m_AudioChannel = 0; - - m_liveMode = true; - m_TrickSpeed = -1; - m_TrickSpeedPts = 0; - m_TrickSpeedMode = 0; - m_TrickSpeedDelay = 0; - m_VDR_TrickSpeedIBP = 0; - m_SkipAudio = false; - m_PlayingFile = pmNone; - m_StreamStart = true; - m_RadioStream = false; - m_AudioCount = 0; - m_FreeBufs = 0; - m_Cleared = true; - m_h264 = false; -} - -cXinelibDevice::~cXinelibDevice() -{ - TRACEF("cXinelibDevice::~cXinelibDevice"); - - StopDevice(); - - m_pInstance = NULL; -} - -bool cXinelibDevice::StartDevice() -{ - TRACEF("cXinelibDevice::StartDevice"); - - if(m_local) - m_local->Start(); - if(m_server) - m_server->Start(); - - // if(dynamic_cast(it)) - if(m_local) { - int timer = 0; - while(!m_local->IsReady()) { - cCondWait::SleepMs(100); - if(m_local->IsFinished()) { - LOGMSG("cXinelibDevice::Start(): Local frontend init failed"); - return false; - } - if(++timer >= LOCAL_INIT_TIMEOUT*10) { - LOGMSG("cXinelibDevice::Start(): Local frontend init timeout"); - return false; - } - } - if(xc.force_primary_device) - ForcePrimaryDevice(true); - } - - if(m_server) { - int timer = 0; - while(!m_server->IsReady()) { - cCondWait::SleepMs(100); - if(m_server->IsFinished()) { - LOGMSG("cXinelibDevice::Start(): Server init failed"); - return false; - } - if(++timer >= SERVER_INIT_TIMEOUT*10) { - LOGMSG("cXinelibDevice::Start(): Server init timeout"); - return false; - } - } - } - - ASSERT(m_statusMonitor == NULL, false); - m_statusMonitor = new cXinelibStatusMonitor(*this, CardIndex()); - - LOGDBG("cXinelibDevice::StartDevice(): Device started"); - return true; -} - -void cXinelibDevice::StopDevice(void) -{ - TRACEF("cXinelibDevice::StopDevice"); - LOGDBG("cXinelibDevice::StopDevice(): Stopping device ..."); - - if(m_statusMonitor) { - delete m_statusMonitor; - m_statusMonitor = NULL; - } - if (m_spuDecoder) { - delete m_spuDecoder; - m_spuDecoder = NULL; - } - - cXinelibThread *server = m_server; - cXinelibThread *local = m_local; - m_local = m_server = NULL; - - cControl::Shutdown(); - ForEach(m_clients, &cXinelibThread::SetLiveMode, false); - TrickSpeed(-1); - - if(local) m_clients.Del(local, false); - if(server) m_clients.Del(server, false); - - if(server) { - server->Stop(); - delete server; - } - if(local) { - local->Stop(); - delete local; - } - - m_clients.Clear(); -} - -// -// Primary device switching -// - -void cXinelibDevice::MakePrimaryDevice(bool On) -{ - TRACEF("cXinelibDevice::MakePrimaryDevice"); - - if(On) - new cXinelibOsdProvider(this); -} - -void cXinelibDevice::ForcePrimaryDevice(bool On) -{ - TRACEF("cXinelibDevice::ForcePrimaryDevice"); - - m_MainThreadLock.Lock(); - m_MainThreadFunctors.Add(CreateFunctor(this, &cXinelibDevice::ForcePrimaryDeviceImpl, On)); - m_MainThreadLock.Unlock(); -} - -void cXinelibDevice::ForcePrimaryDeviceImpl(bool On) -{ - TRACEF("cXinelibDevice::ForcePrimaryDeviceImpl"); - ASSERT(cThread::IsMainThread(), false); - - if(On) { - m_ForcePrimaryDeviceCnt++; - - if(xc.force_primary_device) { - if(cDevice::PrimaryDevice() && this != cDevice::PrimaryDevice()) { - m_OriginalPrimaryDevice = cDevice::PrimaryDevice()->DeviceNumber() + 1; - cControl::Shutdown(); - LOGMSG("Forcing primary device, original index = %d", m_OriginalPrimaryDevice); - if(cOsd::IsOpen()) { - LOGMSG("Forcing primary device, old OSD still open !"); - xc.main_menu_mode = CloseOsd; - cRemote::CallPlugin("xineliboutput"); - } - SetPrimaryDevice(DeviceNumber() + 1); - } - } - - } else /* Off */ { - m_ForcePrimaryDeviceCnt--; - - if(m_ForcePrimaryDeviceCnt < 0) - LOGMSG("ForcePrimaryDevice: Internal error (ForcePrimaryDevice < 0)"); - else if(m_ForcePrimaryDeviceCnt == 0) { - if(m_OriginalPrimaryDevice) { - LOGMSG("Restoring original primary device %d", m_OriginalPrimaryDevice); - cControl::Shutdown(); - if(cOsd::IsOpen()) { - LOGMSG("Restoring primary device, xineliboutput OSD still open !"); - xc.main_menu_mode = CloseOsd; /* will be executed in future by vdr main thread */ - cRemote::CallPlugin("xineliboutput"); - } - cChannel *channel = Channels.GetByNumber(CurrentChannel()); - cDevice::SetPrimaryDevice(m_OriginalPrimaryDevice); - PrimaryDevice()->SwitchChannel(channel, true); - m_OriginalPrimaryDevice = 0; - } - } - } -} - -// -// Execute functors in main thread context -// - -void cXinelibDevice::MainThreadHook(void) -{ - TRACEF("cXinelibDevice::MainThreadHook"); - - if(m_MainThreadFunctors.First()) { - cFunctor *f = NULL; - do { - m_MainThreadLock.Lock(); - if(f) - m_MainThreadFunctors.Del(f); - f = m_MainThreadFunctors.First(); - m_MainThreadLock.Unlock(); - - if(f) { - /*LOGDBG("cXinelibDevice::MainThreadHook: executing functor 0x%lx",(long)f);*/ - f->Execute(); - } - - } while(f); - } -} - -// -// Configuration -// - -void cXinelibDevice::ConfigurePostprocessing(const char *deinterlace_method, - int audio_delay, - int audio_compression, - const int *audio_equalizer, - int audio_surround, - int speaker_type) -{ - TRACEF("cXinelibDevice::ConfigurePostprocessing"); - - if(m_local) - m_local->ConfigurePostprocessing(deinterlace_method, audio_delay, - audio_compression, audio_equalizer, - audio_surround, speaker_type); - if(m_server) - m_server->ConfigurePostprocessing(deinterlace_method, audio_delay, - audio_compression, audio_equalizer, - audio_surround, speaker_type); -} - -void cXinelibDevice::ConfigurePostprocessing(const char *name, bool on, - const char *args) -{ - TRACEF("cXinelibDevice::ConfigurePostprocessing"); - - if(m_local) - m_local->ConfigurePostprocessing(name, on, args); - if(m_server) - m_server->ConfigurePostprocessing(name, on, args); -} - -void cXinelibDevice::ConfigureVideo(int hue, int saturation, int brightness, int contrast, - int overscan, int vo_aspect_ratio) -{ - TRACEF("cXinelibDevice::ConfigureVideo"); - - if(m_local) - m_local->ConfigureVideo(hue, saturation, brightness, contrast, overscan, vo_aspect_ratio); - if(m_server) - m_server->ConfigureVideo(hue, saturation, brightness, contrast, overscan, vo_aspect_ratio); -} - -void cXinelibDevice::ConfigureDecoder(int pes_buffers) -{ - TRACEF("cXinelibDevice::ConfigureDecoder"); - - if(m_local) - m_local->ConfigureDecoder(pes_buffers); - //if(m_server) - // m_server->ConfigureDecoder(pes_buffers); - - cXinelibOsdProvider::RefreshOsd(); -} - -void cXinelibDevice::ConfigureWindow(int fullscreen, int width, int height, - int modeswitch, const char *modeline, - int aspect, int scale_video, - int field_order) -{ - TRACEF("cXinelibDevice::ConfigureWindow"); - - if((!*xc.local_frontend || !strncmp(xc.local_frontend, "none", 4)) && m_local) { - cXinelibThread *tmp = m_local; - m_clients.Del(tmp, false); - m_local = NULL; - cCondWait::SleepMs(5); - tmp->Stop(); - cCondWait::SleepMs(5); - delete tmp; - if(xc.force_primary_device) - ForcePrimaryDevice(false); - } - - if(m_local) - m_local->ConfigureWindow(fullscreen, width, height, modeswitch, modeline, - aspect, scale_video, field_order); - - else if(*xc.local_frontend && strncmp(xc.local_frontend, "none", 4)) { - cXinelibThread *tmp = new cXinelibLocal(xc.local_frontend); - tmp->Start(); - m_clients.Add(m_local = tmp); - - cCondWait::SleepMs(25); - while(!m_local->IsReady() && !m_local->IsFinished()) - cCondWait::SleepMs(25); - - if(m_local->IsFinished()) { - m_local = NULL; - m_clients.Del(tmp, true); - Skins.QueueMessage(mtError, tr("Frontend initialization failed"), 10); - } else { - if(xc.force_primary_device) - ForcePrimaryDevice(true); - - m_local->ConfigureWindow(fullscreen, width, height, modeswitch, modeline, - aspect, scale_video, field_order); - } - } -} - -void cXinelibDevice::Listen(bool activate, int port) -{ - TRACEF("cXinelibDevice::Listen"); - - if(activate && port>0) { - if(!m_server) { - cXinelibThread *tmp = new cXinelibServer(port); - tmp->Start(); - m_clients.Add(m_server = tmp); - - cCondWait::SleepMs(10); - while(!m_server->IsReady() && !m_server->IsFinished()) - cCondWait::SleepMs(10); - - if(m_server->IsFinished()) { - Skins.QueueMessage(mtError, tr("Server initialization failed"), 10); - m_server = NULL; - m_clients.Del(tmp, true); - } - - } else { - if(! m_server->Listen(port)) - Skins.QueueMessage(mtError, tr("Server initialization failed"), 10); - } - } else if( /*((!activate) || port<=0) && */ m_server) { - cXinelibThread *tmp = m_server; - m_clients.Del(tmp, false); - m_server = NULL; - cCondWait::SleepMs(5); - tmp->Stop(); - cCondWait::SleepMs(5); - delete tmp; - } -} - -// -// OSD -// - -void cXinelibDevice::OsdCmd(void *cmd) -{ - TRACEF("cXinelibDevice::OsdCmd"); - TRACK_TIME(250); - - if(m_server) // call first server, local frontend modifies contents of the message ... - m_server->OsdCmd(cmd); - if(m_local) - m_local->OsdCmd(cmd); -} - -// -// Play mode control -// -void cXinelibDevice::StopOutput(void) -{ - TRACEF("cXinelibDevice::StopOutput"); - TRACK_TIME(250); - - m_RadioStream = false; - m_AudioCount = 0; - ForEach(m_clients, &cXinelibThread::SetLiveMode, false); - Clear(); - ForEach(m_clients, &cXinelibThread::QueueBlankDisplay); - ForEach(m_clients, &cXinelibThread::SetNoVideo, false); -#if VDRVERSNUM < 10515 - ClrAvailableDvdSpuTracks(); - m_ForcedDvdSpuTrack = false; -#endif -} - -void cXinelibDevice::SetTvMode(cChannel *Channel) -{ - TRACEF("cXinelibDevice::SetTvMode"); - TRACK_TIME(250); - - m_RadioStream = false; - if (Channel && !Channel->Vpid() && (Channel->Apid(0) || Channel->Apid(1))) - m_RadioStream = true; - if(m_PlayMode == pmAudioOnlyBlack) - m_RadioStream = true; - TRACE("cXinelibDevice::SetTvMode - isRadio = "< BlankDisplay, NoVideo"); - ForEach(m_clients, &cXinelibThread::BlankDisplay); - ForEach(m_clients, &cXinelibThread::SetNoVideo, true); - } else { - if(m_liveMode) - ForEach(m_clients, &cXinelibThread::SetNoVideo, m_RadioStream); - else - ForEach(m_clients, &cXinelibThread::SetNoVideo, - m_RadioStream && (m_AudioCount<1)); - Clear(); - } - - return true; -} - -// -// Playback control -// - -// m_TrickSpeedMode flags -#define trs_IPB_frames 0x01 // stream has all frame types -#define trs_I_frames 0x02 // stream has only I-frames -#define trs_PTS_recalc 0x04 // PTS must be re-calculated -#define trs_NoAudio 0x08 // no audio in trick speed mode -#define trs_PTS_check 0x80 // detect in PlayVideo if PTS must be recalculated - -bool cXinelibDevice::HasIBPTrickSpeed(void) -{ - TRACEF("cXinelibDevice::HasIBPTrickSpeed"); - -#ifndef DEVICE_SUPPORTS_IBP_TRICKSPEED -#warning VDR has not been patched for smooth fast forward. Disabling smooth fast forward. - return false; -#else - m_VDR_TrickSpeedIBP = true; - - return xc.ibp_trickspeed; -#endif -} - -bool cXinelibDevice::UseIBPTrickSpeed(void) -{ - return m_VDR_TrickSpeedIBP && xc.ibp_trickspeed; -} - -void cXinelibDevice::TrickSpeed(int Speed) -{ - TRACEF("cXinelibDevice::TrickSpeed"); - - if(m_TrickSpeed != Speed) { - int RealSpeed = abs(Speed); - LOGTRICKSPEED("TrickSpeed changed from %d to %d [%d]", m_TrickSpeed, Speed, RealSpeed); - - m_TrickSpeedPts = 0; - m_TrickSpeed = Speed; - m_TrickSpeedDelay = 0; - - // Possible transitions: - // fast <-> play - // play <-> pause - // pause <-> slow - // _and_ from any mode to normal play and pause - - if(Speed == 8 || Speed == 4 || Speed == 2) { - LOGTRICKSPEED(" Slow forward (1/%d speed), IPB-frames", Speed); - - // do nothing - slow forward is just slow playback of complete stream - m_TrickSpeedMode = trs_IPB_frames; - - // previous state was slow forward or pause --> no need for clear - - // change decoder and UDP/RTP scheduler clock rates - ForEach(m_clients, &cXinelibThread::TrickSpeed, RealSpeed); - } - - else if(Speed == 63 || Speed == 48 || Speed == 24) { - RealSpeed = (Speed+11)/12; - LOGTRICKSPEED(" Slow backward (1/%d speed), I-frames only", RealSpeed); - - // previous state was slow backwards or pause --> clear if it was pause - // - //if(PrevSpeed == 0 && !(m_TrickSpeedMode & trs_PTS_recalc)) { - // LOGMSG(" -> Clear"); - // ForEach(m_clients, &cXinelibThread::Clear); - //} - - // only I-frames, backwards, pts must be re-generated - m_TrickSpeedMode = trs_I_frames | trs_PTS_recalc | trs_NoAudio; - - // change decoder and UDP/RTP scheduler clock rates - ForEach(m_clients, &cXinelibThread::TrickSpeed, RealSpeed); - } - - else if(Speed == 6 || Speed == 3 || Speed == 1) { - RealSpeed = 12/Speed; - LOGTRICKSPEED(" Fast (%dx speed), direction unknown", RealSpeed); - - if(RealSpeed > xc.max_trickspeed) { - RealSpeed = xc.max_trickspeed; - LOGTRICKSPEED(" Trick speed limited to %dx speed", RealSpeed); - } - - /* only I-frames, backwards, pts must be re-generated if playing backwards */ - m_TrickSpeedMode |= trs_PTS_check; - - /* backward/forward state is unknown until first PTS is seen - so, clear() must be done in PlayVideo. */ - /* previous trick speed state is not overwritten yet ... ! */ - - // change decoder and UDP/RTP scheduler clock rates - ForEach(m_clients, &cXinelibThread::TrickSpeed, -RealSpeed); - } - - else if(Speed==-1 || Speed == 0) { - LOGTRICKSPEED(" Play/Pause"); - - // change decoder and UDP/RTP scheduler clock rates - ForEach(m_clients, &cXinelibThread::TrickSpeed, RealSpeed); - - // returning from backward mode needs Clear - // - //if(Speed==-1 && (m_TrickSpeedMode & trs_PTS_recalc)) { - // LOGMSG(" -> Clear"); - // ForEach(m_clients, &cXinelibThread::Clear); - // m_TrickSpeedMode = 0; - //} - // returning from fast forward mode needs Clear - // because of DvbPlayer jumps few seconds back at mode change ... - // - //if(Speed==-1 && (m_TrickSpeedMode & trs_I_frames)) { - // LOGMSG(" -> Clear"); - // ForEach(m_clients, &cXinelibThread::Clear); - //} - m_TrickSpeedMode = 0; - } - - else { - LOGTRICKSPEED(" Unknown trickspeed %d !", Speed); - m_TrickSpeedMode = 0; - m_TrickSpeed = -1; - ForEach(m_clients, &cXinelibThread::TrickSpeed, -1); - } - } -} - -void cXinelibDevice::Clear(void) -{ - TRACEF("cXinelibDevice::Clear"); - TRACK_TIME(100); - - if(m_Cleared && m_StreamStart && m_TrickSpeed == -1) { - //LOGMSG("************ Double Clear ***************"); - } else { - //LOGMSG("************ FIRST Clear ***************"); - m_Cleared = true; - m_StreamStart = true; - m_h264 = false; - m_FreeBufs = 0; - TrickSpeed(-1); - ForEach(m_clients, &cXinelibThread::Clear); - ForEach(m_clients, &cXinelibThread::SetStillMode, false); - } -} - -void cXinelibDevice::Play(void) -{ - TRACEF("cXinelibDevice::Play"); - - m_SkipAudio = false; - - ForEach(m_clients, &cXinelibThread::SetLiveMode, false); - TrickSpeed(-1); -} - -void cXinelibDevice::Freeze(void) -{ - TRACEF("cXinelibDevice::Freeze"); - - TrickSpeed(0); -} - -int64_t cXinelibDevice::GetSTC(void) -{ - TRACEF("cXinelibDevice::GetSTC"); - - if(m_local) - return m_local->GetSTC(); - if(m_server) - return m_server->GetSTC(); - return cDevice::GetSTC(); -} - -bool cXinelibDevice::Flush(int TimeoutMs) -{ - TRACEF("cXinelibDevice::Flush"); - TRACK_TIME(500); - - if(m_TrickSpeed == 0) { - ForEach(m_clients, &cXinelibThread::SetLiveMode, false); - TrickSpeed(-1); - } - - bool r = ForEach(m_clients, &cXinelibThread::Flush, TimeoutMs, - &mand, true); - - return r; -} - - -// -// Playback of files and images -// - -int cXinelibDevice::PlayFileCtrl(const char *Cmd) -{ - TRACEF("cXinelibDevice::PlayFile"); - int result = -1; - - if(m_PlayingFile != pmNone) { - if(m_server) - result = m_server->PlayFileCtrl(Cmd); - if(m_local) - result = m_local->PlayFileCtrl(Cmd); - } - return result; -} - -bool cXinelibDevice::EndOfStreamReached(void) -{ - if(m_local && !m_local->EndOfStreamReached()) - return false; - if(m_server && !m_server->EndOfStreamReached()) - return false; - return true; -} - -bool cXinelibDevice::PlayFile(const char *FileName, int Position, - bool LoopPlay, ePlayMode PlayMode) -{ - TRACEF("cXinelibDevice::PlayFile"); - TRACE("cXinelibDevice::PlayFile(\"" << FileName << "\")"); - - bool result = true; - - if(FileName) { - if(m_PlayingFile == pmNone) { - m_PlayingFile = PlayMode; - if (!xc.IsImageFile(FileName)) - StopOutput(); - } - for(int i = 0; i < mi_Count; i++) - m_MetaInfo[i][0] = 0; - if(m_server) - result = m_server->PlayFile(FileName, Position, LoopPlay, PlayMode); - if(m_local) - result = m_local->PlayFile(FileName, Position, LoopPlay, PlayMode); - } else if(/*!FileName &&*/m_PlayingFile != pmNone) { - if(m_server) - result = m_server->PlayFile(NULL, 0); - if(m_local) - result = m_local->PlayFile(NULL, 0); - if(!m_liveMode) - SetReplayMode(); - else - SetTvMode(Channels.GetByNumber(cDevice::CurrentChannel())); - m_PlayingFile = pmNone; - } - - return result; -} - -// -// Data stream handling -// - -int cXinelibDevice::PlayTrickSpeed(const uchar *buf, int length) -{ - if(abs(m_TrickSpeed) > 1 && (m_TrickSpeedMode & trs_I_frames)) { - uint8_t PictureType = pes_get_picture_type(buf, length); -#ifdef LOG_TRICKSPEED - if(PictureType != NO_PICTURE && PES_HAS_PTS(buf)) { - int64_t pts = pes_get_pts(buf, length); - LOGMSG(" TrickSpeed: frame %s pts %"PRId64, picture_type_str[PictureType], pts); - } -#endif - -#if 1 - // limit I-frame rate - if(PictureType == I_FRAME) { - static int64_t t0 = 0; - int64_t t1 = cTimeMs::Now(); - if((t1 - t0) < 1000) { - int fdelay = 40*12; // = 480 ms, time of one GOP in normal speed - switch(m_TrickSpeed) { - case 6: /* 2x ff */ fdelay /= min( 2, xc.max_trickspeed); break; - case 3: /* 4x ff */ fdelay /= min( 4, xc.max_trickspeed); break; - case 1: /* 12x ff */ fdelay /= min(12, xc.max_trickspeed); break; - case 63: /* 1/6x rew */ fdelay *= 6; break; - case 48: /* 1/4x rew */ fdelay *= 4; break; - case 24: /* 1/2x rew */ fdelay *= 2; break; - default: break; - } - /* wait if data is coming in too fast */ - if(fdelay - (t1-t0) >= 40) { - m_TrickSpeedDelay = 40; - return -1; - } - - t0 += fdelay; - - pes_change_pts((uchar*)buf, length, INT64_C(0)); - } else { - t0 = t1; - } - } -#endif - } - - // - // detecting trick speed mode ? - // - if( m_TrickSpeed > 0 && (m_TrickSpeedMode & trs_PTS_check) && IS_VIDEO_PACKET(buf)) { - int64_t pts; - if (PES_HAS_PTS(buf) && (pts = pes_get_pts(buf, length)) > 0) { - uint8_t PictureType = pes_get_picture_type(buf, length); - if(PictureType != I_FRAME && PictureType != NO_PICTURE) { - // --> must be fast worward with IBP frames. - // --> PTS check does not work (frames are sent in decoder order) ! */ - m_TrickSpeedPts = pts - 1; - LOGTRICKSPEED(" Detected fast forward mode, using IBP frames"); - } - if(m_TrickSpeedPts == 0) { - m_TrickSpeedMode |= trs_NoAudio; - m_TrickSpeedPts = pts; - LOGTRICKSPEED(" Seen video pts = %"PRId64, pts); - } else { - if(pts < m_TrickSpeedPts) { - /* -> playing fast backwards */ - LOGTRICKSPEED(" Detected fast backward mode. last %"PRId64" now %"PRId64, - m_TrickSpeedPts, pts); - //if(!(m_TrickSpeedMode & trs_PTS_recalc)) - // ForEach(m_clients, &cXinelibThread::Clear); - m_TrickSpeedMode = trs_I_frames | trs_PTS_recalc | trs_NoAudio; - } else { - LOGTRICKSPEED(" Detected fast forward mode"); - if(UseIBPTrickSpeed()) - m_TrickSpeedMode = trs_IPB_frames; - else - m_TrickSpeedMode = trs_I_frames; - } - } - } - } - - // - // Trick speed mode with PTS re-calc - // - if( m_TrickSpeed > 0 && (m_TrickSpeedMode & trs_PTS_recalc) && - IS_VIDEO_PACKET(buf) && PES_HAS_PTS(buf)) { - int64_t pts = pes_get_pts(buf, length); - if (pts > 0) { - - /* m_TrickSpeedPts could be 0 in case of slow backwards */ - if(m_TrickSpeedPts == 0) - m_TrickSpeedPts = pts; - - LOGTRICKSPEED(" pts %"PRId64" -> %"PRId64" (diff %"PRId64") %"PRId64"", pts, - m_TrickSpeedPts + 40*12*90, m_TrickSpeedPts + 40*12*90 - pts, - (m_TrickSpeedPts + 40*12*90)^0x80000000); - pts = m_TrickSpeedPts = m_TrickSpeedPts + 40*12*90; /* 12 frames * 40ms -> pts units */ - pts ^= 0x80000000; /* discontinuity (when mode changes) forces re-syncing of all clocks */ - pes_change_pts((uchar*)buf, length, pts); - } - } - -#if 1 - else if (m_TrickSpeedMode & trs_I_frames) { - if (IS_VIDEO_PACKET(buf) && PES_HAS_PTS(buf)) { - int64_t pts = pes_get_pts(buf, length); - if (pts > 0) { - pts ^= 0x80000000; /* discontinuity (when mode changes) forces re-syncing of all clocks */ - pes_change_pts((uchar*)buf, length, pts); - } - } - } -#endif - - return 0; -} - -int cXinelibDevice::PlayAny(const uchar *buf, int length) -{ - TRACEF("cXinelibDevice::PlayAny"); - TRACK_TIME(100); - -#if 0 - if(m_PlayingFile) - return length; -#endif - - // - // Need to be sure Poll has been called for every frame: - // - cDevice can feed multiple frames after each poll from player/transfer. - // - If only part of frames are consumed, rest are fed again after next Poll. - // - If there are multiple clients it is possible first client(s) - // can queue more frames than last client(s). - // -> frame(s) are either lost immediately (last client(s)) - // or duplicated after next poll (first client(s)) - // - if(m_FreeBufs < 1) { - cPoller Poller; - if(!Poll(Poller,0)) { - errno = EAGAIN; - return 0; - } - } - - int isMpeg1 = pes_is_mpeg1(buf); - int len = pes_packet_len(buf, length); - if(len>0 && len != length) - LOGMSG("cXinelibDevice::PlayAny: invalid data !"); - - if(m_TrickSpeed > 0) { - if(PlayTrickSpeed(buf, length) < 0) - return 0; /* wait if data is coming in too fast */ - } else if(m_SkipAudio) { - /* needed for still images when moving cutting marks */ - pes_change_pts((uchar*)buf, length, INT64_C(0)); - } - m_Cleared = false; - m_FreeBufs --; - - if(m_local) { - length = (isMpeg1 ? m_local->Play_Mpeg1_PES(buf,length) : - m_local->Play_PES(buf,length)); - } - if(m_server && length > 0) { - int length2 = isMpeg1 ? m_server->Play_Mpeg1_PES(buf, length) : - m_server->Play_PES(buf, length); - if(!m_local) - return length2; - } - - return length; -} - -int cXinelibDevice::PlayVideo(const uchar *buf, int length) -{ - TRACEF("cXinelibDevice::PlayVideo"); - TRACK_TIME(100); - - if(m_PlayMode == pmAudioOnlyBlack) - return length; - - if(m_RadioStream) { - m_RadioStream = false; - m_AudioCount = 0; - ForEach(m_clients, &cXinelibThread::SetNoVideo, m_RadioStream); - } - - if(m_StreamStart) { - -#ifdef START_IFRAME - // Start with I-frame if stream has video - // wait for first I-frame - if (pes_get_picture_type(buf, length) == I_FRAME) { - m_StreamStart = false; - } else { - return length; - } -#endif - - if (!m_h264 && pes_is_frame_h264(buf, length)) { - LOGMSG("cXinelibDevice::PlayVideo: Detected H.264 video"); - m_h264 = true; - } - - video_size_t Size; - if (pes_get_video_size(buf, length, &Size, m_h264 ? 1:0)) { - m_StreamStart = false; - /*if (m_h264)*/ LOGMSG("Detected video size %dx%d", Size.width, Size.height); - //LOGDBG("Detected video size %dx%d", Width, Height); - ForEach(m_clients, &cXinelibThread::SetHDMode, (Size.width > 800)); - } - } - -#ifdef DEBUG_SWITCHING_TIME - if(m_statusMonitor->switchtimeOff && m_statusMonitor->switchtimeOn) { - if (pes_get_picture_type(buf, length) == I_FRAME) - m_statusMonitor->IFrame(); - } -#endif - - if(m_PlayingFile && (m_PlayingFile == pmAudioVideo || m_PlayingFile == pmVideoOnly)) - return length; - - return PlayAny(buf, length); -} - -void cXinelibDevice::StillPicture(const uchar *Data, int Length) -{ - TRACEF("cXinelibDevice::StillPicture"); - - // skip still images coming in too fast (ex. when moving cutting marks) - if(cRemote::HasKeys()) { - static int skipped = 0; - static uint64_t lastshow = 0; - uint64_t now = cTimeMs::Now(); - if(now - lastshow < 500) { - skipped++; - //LOGMSG("Skipping still image (coming in too fast)"); - return; - } - LOGDBG("Forcing still image - skipped %d images", skipped); - lastshow = now; - skipped = 0; - } - - bool isPes = (!Data[0] && !Data[1] && Data[2] == 0x01 && - (Data[3] & 0xF0) == 0xE0); - bool isMpeg1 = isPes && ((Data[6] & 0xC0) != 0x80); - int i; - - if(m_PlayingFile && (m_PlayingFile == pmAudioVideo || m_PlayingFile == pmVideoOnly)) - return; - - TRACE("cXinelibDevice::StillPicture: isPes = "< 0*/) - return length; - if(m_TrickSpeedMode & trs_NoAudio) - return length; - - if(m_RadioStream) { - if(m_AudioCount) { - m_AudioCount--; - if(!m_AudioCount) { - LOGDBG("PlayAudio detected radio stream"); - ForEach(m_clients, &cXinelibThread::SetNoVideo, m_RadioStream); - } - } - } - - if(m_PlayingFile && (m_PlayingFile == pmAudioVideo || m_PlayingFile == pmAudioOnly)) - return length; - - return PlayAny(buf, length); -} - -#if VDRVERSNUM < 10510 -int cXinelibDevice::PlaySpu(const uchar *buf, int length, uchar Id) -{ - TRACEF("cXinelibDevice::PlaySpu"); - - if(!buf || length < 6) - return length; - - if(((unsigned char *)buf)[3] == PRIVATE_STREAM1) { - - if(!m_spuPresent) { - TRACE("cXinelibDevice::PlaySpu first DVD SPU frame"); - Skins.QueueMessage(mtInfo,"DVD Subtitles"); - m_spuPresent = true; - - ForEach(m_clients, &cXinelibThread::SpuStreamChanged, (int)Id); - } - - // Strip all but selected SPU track - if(Id != m_CurrentDvdSpuTrack) - return length; - } - - return PlayAny(buf, length); -} -#endif - -bool cXinelibDevice::Poll(cPoller &Poller, int TimeoutMs) -{ - TRACEF("cXinelibDevice::Poll"); - TRACK_TIME(400); - - if(m_PlayingFile == pmAudioVideo) - return true; - - if(m_TrickSpeed == 0) { - cCondWait::SleepMs(min(TimeoutMs, 20)); - return Poller.Poll(0); - } - - if(!m_local && !m_server) { - /* nothing to do... why do I exist ... ? */ - //cCondWait::SleepMs(TimeoutMs); - //return Poller.Poll(0); - return true; - } - - if(m_TrickSpeed > 1 && m_TrickSpeedDelay > 20) { - LOGTRICKSPEED(" Poll: m_TrickSpeedDelay=%d.", m_TrickSpeedDelay); - cCondWait::SleepMs(20); - m_TrickSpeedDelay -= 20; - return false; - } - - if(m_FreeBufs < 1) { - int result = DEFAULT_POLL_SIZE; - - if(m_local) - result = min(result, m_local->Poll(Poller, TimeoutMs)); - if(m_server) - result = min(result, m_server->Poll(Poller, TimeoutMs)); - - m_FreeBufs = max(result, 0); - } - - return m_FreeBufs > 0 /*|| Poller.Poll(0)*/; -} - -// -// Audio facilities -// - -void cXinelibDevice::SetVolumeDevice(int Volume) -{ - TRACEF("cXinelibDevice::SetVolumeDevice"); - - ForEach(m_clients, &cXinelibThread::SetVolume, Volume); -} - -void cXinelibDevice::SetAudioTrackDevice(eTrackType Type) -{ - TRACEF("cXinelibDevice::SetAudioTrackDevice"); - - // track changes are autodetected at xine side -} - -void cXinelibDevice::SetAudioChannelDevice(int AudioChannel) -{ - TRACEF("cXinelibDevice::SetAudioChannelDevice"); - - if(m_AudioChannel != AudioChannel) { - m_AudioChannel = AudioChannel; - //LOGDBG("cXinelibDevice::SetAudioChannelDevice --> %d", AudioChannel); -#if 0 - switch(AudioChannel) { - default: - //case 0: ConfigurePostprocessing("upmix_mono", false, NULL); - case 0: ConfigurePostprocessing("upmix_mono", true, "channel=-1"); - break; - case 1: ConfigurePostprocessing("upmix_mono", true, "channel=0"); - break; - case 2: ConfigurePostprocessing("upmix_mono", true, "channel=1"); - break; - } -#else - switch(AudioChannel) { - default: - case 0: ConfigurePostprocessing("audiochannel", false, NULL); - break; - case 1: ConfigurePostprocessing("audiochannel", true, "channel=0"); - break; - case 2: ConfigurePostprocessing("audiochannel", true, "channel=1"); - break; - } -#endif - } -} - -void cXinelibDevice::SetDigitalAudioDevice(bool On) -{ - TRACEF("cXinelibDevice::SetDigitalAudioDevice"); - - // track changes are autodetected at xine side -} - -// -// Video format facilities -// - -void cXinelibDevice::SetVideoFormat(bool VideoFormat16_9) -{ - TRACEF("cXinelibDevice::SetVideoFormat"); - cDevice::SetVideoFormat(VideoFormat16_9); - -#if 0 - // - // TODO - // - if(xc.aspect != ASPECT_AUTO && - xc.aspect != ASPECT_DEFAULT) { - if(VideoFormat16_9) - xc.aspect = ASPECT_16_9; - else if(xc.aspect == ASPECT_16_9) - xc.aspect = ASPECT_4_3; - ConfigureDecoder(,,,xc.aspect,,,); - } -#endif -} - -void cXinelibDevice::SetVideoDisplayFormat(eVideoDisplayFormat VideoDisplayFormat) -{ - TRACEF("cXinelibDevice::SetVideoDisplayFormat"); - cDevice::SetVideoDisplayFormat(VideoDisplayFormat); - -#if 0 - // - // TODO - // - // - set normal, pan&scan, letterbox (only for 4:3?) - // - if(xc.aspect != ASPECT_AUTO && - xc.aspect != ASPECT_DEFAULT) { - switch(VideoDisplayFormat) { - case vdfPanAndScan: - xc.aspect = ASPECT_PAN_SCAN; - break; - case vdfLetterBox: - xc.aspect = ASPECT_4_3; /* borders are added automatically if needed */ - break; - case vdfCenterCutOut: - xc.aspect = ASPECT_CENTER_CUT_OUT; - break; - } - ConfigureDecoder(,,,xc.aspect,,,); - } -#endif -} - -eVideoSystem cXinelibDevice::GetVideoSystem(void) -{ - TRACEF("cXinelibDevice::GetVideoSystem"); - return cDevice::GetVideoSystem(); -} - - -// -// SPU decoder -// - -#ifdef FORWARD_DVD_SPUS -# include "spu_decoder.h" -#endif - -cSpuDecoder *cXinelibDevice::GetSpuDecoder(void) -{ - TRACEF("cXinelibDevice::GetSpuDecoder"); - if (!m_spuDecoder && IsPrimaryDevice()) { - // - // TODO - // - // - use own derived SpuDecoder with special cXinelibOsd - // -> always visible - // - -#ifdef FORWARD_DVD_SPUS - // forward DVD SPUs to xine without decoding - m_spuDecoder = new cFwdSpuDecoder(this); -#else - m_spuDecoder = new cDvbSpuDecoder(); -#endif - } - return m_spuDecoder; -} - -// -// Image Grabbing -// - -uchar *cXinelibDevice::GrabImage(int &Size, bool Jpeg, - int Quality, int SizeX, int SizeY) -{ - TRACEF("cXinelibDevice::GrabImage"); - - if(m_local) - return m_local->GrabImage(Size, Jpeg, Quality, SizeX, SizeY); - if(m_server) - return m_server->GrabImage(Size, Jpeg, Quality, SizeX, SizeY); - - return NULL; -} - - -// -// DVD SPU support in VDR recordings -// -// - override cDevice::PlayPesPacket to get DVD SPUs -// - -#if VDRVERSNUM < 10510 -int cXinelibDevice::PlayPesPacket(const uchar *Data, int Length, - bool VideoOnly) -{ - switch (Data[3]) { - case 0xBD: { // private stream 1 - int PayloadOffset = Data[8] + 9; - uchar SubStreamId = Data[PayloadOffset]; - uchar SubStreamType = SubStreamId & 0xF0; - uchar SubStreamIndex = SubStreamId & 0x1F; - switch (SubStreamType) { - case 0x20: // SPU - case 0x30: // SPU - SetAvailableDvdSpuTrack(SubStreamIndex); - return PlaySpu(Data, Length, SubStreamIndex); - break; - default: - ; - } - } - default: - ; - } - return cDevice::PlayPesPacket(Data, Length, VideoOnly); -} -#endif - -// -// Available DVD SPU tracks -// - -#if VDRVERSNUM < 10515 -bool cXinelibDevice::SetCurrentDvdSpuTrack(int Type, bool Force) -{ - if(Type == ttXSubtitleNone || - ( Type >= 0 && - Type < 64 && - m_DvdSpuTrack[Type].id != 0xffff)) { - m_CurrentDvdSpuTrack = Type; - ForEach(m_clients, &cXinelibThread::SpuStreamChanged, Type); - if(Force) - m_ForcedDvdSpuTrack = true; - return true; - } - return false; -} -#endif - -#if VDRVERSNUM >= 10515 -void cXinelibDevice::SetSubtitleTrackDevice(eTrackType Type) -{ - if (m_PlayingFile == pmAudioVideo || m_PlayingFile == pmVideoOnly) - ForEach(m_clients, &cXinelibThread::SetSubtitleTrack, Type); -} -#endif - -#if VDRVERSNUM < 10515 -void cXinelibDevice::ClrAvailableDvdSpuTracks(bool NotifyFrontend) -{ - for(int i=0; i<64; i++) - m_DvdSpuTrack[i].id = 0xffff; - if(m_CurrentDvdSpuTrack >= 0 ) { - m_CurrentDvdSpuTrack = ttXSubtitleNone; - if(NotifyFrontend) - ForEach(m_clients, &cXinelibThread::SpuStreamChanged, m_CurrentDvdSpuTrack); - } -} -#endif - -#if VDRVERSNUM < 10515 -int cXinelibDevice::NumDvdSpuTracks(void) const -{ - int DvdSpuTracks = 0; - for(int i=0; i<64; i++) - if(m_DvdSpuTrack[i].id != 0xffff) - DvdSpuTracks++; - return DvdSpuTracks; -} -#endif - -#if VDRVERSNUM < 10515 -const tTrackId *cXinelibDevice::GetDvdSpuTrack(int Type) const -{ - if(Type >= 0 && Type < 64 && - m_DvdSpuTrack[Type].id != 0xffff) - return &m_DvdSpuTrack[Type]; - return NULL; -} -#endif - -#if VDRVERSNUM < 10515 -const char *cXinelibDevice::GetDvdSpuLang(int Type) const -{ - const tTrackId *track = GetDvdSpuTrack(Type); - if(track) - return track->language[0] ? track->language : NULL; - return NULL; -} -#endif - -#if VDRVERSNUM < 10515 -bool cXinelibDevice::SetAvailableDvdSpuTrack(int Type, const char *lang, bool Current) -{ - if(Type >= 0 && Type < 64) { - - m_DvdSpuTrack[Type].id = Type; - m_DvdSpuTrack[Type].language[0] = '\0'; - if(lang) - strn0cpy(m_DvdSpuTrack[Type].language, lang, MAXLANGCODE2); - if(Current) - m_CurrentDvdSpuTrack = Type; - - return true; - } - return false; -} -#endif - -#if VDRVERSNUM < 10515 -void cXinelibDevice::EnsureDvdSpuTrack(void) -{ - if(!m_ForcedDvdSpuTrack && - NumDvdSpuTracks() > 0 && - (m_DvdSpuTrack[0].id == 0xffff || - strcmp(m_DvdSpuTrack[0].language, "menu"))) { - - if(xc.spu_autoshow) { - int pref, len, track; - for(pref = 0; pref < 4; pref++) - for(track = 0; track < 64; track++) - if(m_DvdSpuTrack[track].id != 0xffff) - if((len=strlen(xc.spu_lang[pref])) > 0) - //if(!strncmp(m_DvdSpuTrack[track].language, - // xc.spu_lang[pref], len)) { - if(!strcmp(m_DvdSpuTrack[track].language, - xc.spu_lang[pref])) { - if(m_CurrentDvdSpuTrack != track) { - LOGMSG("Auto-selecting %d. SPU track \'%s\' (%d. preferred language is \'%s\')", - track, m_DvdSpuTrack[track].language, pref+1, xc.spu_lang[pref]); - cXinelibDevice::SetCurrentDvdSpuTrack(track); - cString msg = cString::sprintf("Subtitles: %s", m_DvdSpuTrack[track].language); - Skins.QueueMessage(mtInfo, msg); - } - m_spuPresent = true; - track = 64; - pref = 99; - } - if(pref < 99) { - for(track = 0; track < 64; track++) - if(m_DvdSpuTrack[track].id != 0xffff) - if(m_CurrentDvdSpuTrack != track) { - LOGMSG("Auto-selecting (non-matching) %d. SPU track \'%s\'", - track, m_DvdSpuTrack[track].language); - cXinelibDevice::SetCurrentDvdSpuTrack(track); - } - } - } - - if(!m_spuPresent) { - Skins.QueueMessage(mtInfo, "Subtitles present"); - m_spuPresent = true; - } - } -} -#endif - -// -// Metainfo -// - -const char *cXinelibDevice::GetMetaInfo(eMetainfoType Type) -{ - if(Type >= 0 && Type < mi_Count) { - if ((Type == miTitle) || - (Type == miTracknumber && xc.playlist_tracknumber == 1) || - (Type == miArtist && xc.playlist_artist == 1) || - (Type == miAlbum && xc.playlist_album == 1) || - (Type > miAlbum)) { - return m_MetaInfo[Type]; - } - return ""; - } - - LOGMSG("cXinelibDevice::GetMetaInfo: unknown metainfo type"); - return ""; -} - -void cXinelibDevice::SetMetaInfo(eMetainfoType Type, const char *Value) -{ - if(Type >= 0 && Type < mi_Count) { - /* set to 0 first, so if player is accessing string in middle of - copying it will always be 0-terminated (but truncated) */ - memset(m_MetaInfo[Type], 0, sizeof(m_MetaInfo[Type])); - strn0cpy(m_MetaInfo[Type], Value, MAX_METAINFO_LEN); - } else { - LOGMSG("cXinelibDevice::SetMetaInfo: unknown metainfo type"); - } -} - diff --git a/device.h b/device.h deleted file mode 100644 index 41391eb1..00000000 --- a/device.h +++ /dev/null @@ -1,280 +0,0 @@ -/* - * device.h: - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: device.h,v 1.34 2008-04-14 19:58:50 phintuka Exp $ - * - */ - -#ifndef __XINELIB_DEVICE_H -#define __XINELIB_DEVICE_H - -#include -#include -#include - -class cXinelibStatusMonitor; -class cXinelibThread; -class cChannel; -class cFunctor; - -typedef enum { - miTitle = 0, - miTracknumber = 1, - miArtist = 2, - miAlbum = 3, - miDvdTitleNo = 4, - mi_Count = 5 -} eMetainfoType; - -# define ttXSubtitleNone (-2) -# define ttXSubtitleAuto (-1) - -#define MAX_METAINFO_LEN 63 - -class cXinelibDevice : public cDevice -{ - - // Singleton - - private: - static cXinelibDevice* m_pInstance; // singleton - cXinelibDevice(); // - cXinelibDevice(cXinelibDevice&); // no copy constructor - - public: - static cXinelibDevice& Instance(void); // singleton - static void Dispose(void); - - virtual ~cXinelibDevice(); - - - // device start/stop (from cPlugin) - - public: - bool StartDevice(void); - void StopDevice(void); - - - // function calls waiting to be executed in VDR main thread context - - private: - cList m_MainThreadFunctors; - cMutex m_MainThreadLock; - - public: - void MainThreadHook(void); - - - // Primary device switching - - private: - int m_OriginalPrimaryDevice; - int m_ForcePrimaryDeviceCnt; - - void ForcePrimaryDeviceImpl(bool On); - - public: - virtual void MakePrimaryDevice(bool On); - void ForcePrimaryDevice(bool On); - - - // Device capabilities - private: - bool m_VDR_TrickSpeedIBP; - - public: - - virtual bool HasDecoder(void) const { return true; }; - virtual bool CanReplay(void) const { return true; }; - - virtual bool HasIBPTrickSpeed(void); - - // Playback control - - private: - ePlayMode m_PlayMode; - int m_TrickSpeed; - int64_t m_TrickSpeedPts; - int m_TrickSpeedMode; - int m_TrickSpeedDelay; - - public: - virtual bool SetPlayMode(ePlayMode PlayMode); - ePlayMode GetPlayMode(void) const { return m_PlayMode; }; - - protected: - virtual void Clear(void); - virtual void Play(void); - virtual void TrickSpeed(int Speed); - virtual void Freeze(void); - virtual bool Flush(int TimeoutMs = 0); - virtual int64_t GetSTC(void); - - bool UseIBPTrickSpeed(void); - - // Video format facilities - - public: - virtual void SetVideoDisplayFormat(eVideoDisplayFormat VideoDisplayFormat); - virtual void SetVideoFormat(bool VideoFormat16_9); - virtual eVideoSystem GetVideoSystem(void); - - // Track facilities - - protected: - virtual void SetAudioTrackDevice(eTrackType Type); - - private: -#if VDRVERSNUM < 10515 - // (DVD) SPU tracks - tTrackId m_DvdSpuTrack[64]; - int m_CurrentDvdSpuTrack; - bool m_ForcedDvdSpuTrack; -#endif - char m_MetaInfo[mi_Count][MAX_METAINFO_LEN+1]; - - public: -#if VDRVERSNUM < 10515 - void ClrAvailableDvdSpuTracks(bool NotifyFrontend = true); - bool SetAvailableDvdSpuTrack(int Type, const char *lang = NULL, bool Current = false); - - int NumDvdSpuTracks(void) const; - const tTrackId *GetDvdSpuTrack(int Type) const; - const char *GetDvdSpuLang(int Type) const; - - int GetCurrentDvdSpuTrack(void) const { return m_CurrentDvdSpuTrack; } - bool SetCurrentDvdSpuTrack(int Type, bool Force=false); - void EnsureDvdSpuTrack(void); -#else - virtual void SetSubtitleTrackDevice(eTrackType Type); -#endif - - const char *GetMetaInfo(eMetainfoType Type); - void SetMetaInfo(eMetainfoType Type, const char *Value); - - // Audio facilities - - private: - int m_AudioChannel; - - protected: - virtual int GetAudioChannelDevice(void) { return m_AudioChannel; } - virtual void SetAudioChannelDevice(int AudioChannel); - virtual void SetVolumeDevice(int Volume); - virtual void SetDigitalAudioDevice(bool On); - - - // Image grabbing - - public: - virtual uchar *GrabImage(int &Size, bool Jpeg = true, - int Quality = -1, int SizeX = -1, int SizeY = -1); - - - // SPU decoder - - private: - cSpuDecoder *m_spuDecoder; - - friend class cXineSpuDecoder; - - public: - virtual cSpuDecoder *GetSpuDecoder(void); - - - // Messages from StatusMonitor: - - private: - cXinelibStatusMonitor *m_statusMonitor; - bool m_liveMode; - - public: - void SetTvMode(cChannel *Channel); - void SetReplayMode(void); - void StopOutput(void); - - - // Osd Commands (from cXinelibOsd) - - public: - void OsdCmd(void *cmd); - - - // Configuration - - private: - cList m_clients; - cXinelibThread *m_server; - cXinelibThread *m_local; - - public: - void ConfigurePostprocessing(const char *deinterlace_method, - int audio_delay, - int audio_compression, - const int *audio_equalizer, - int audio_surround, - int speaker_type); - void ConfigurePostprocessing(const char *name, bool on=true, - const char *args=NULL); - void ConfigureVideo(int hue, int saturation, int brightness, int contrast, - int overscan, int vo_aspect_ratio); - // local mode: - void ConfigureWindow(int fullscreen, int width, int height, - int modeswitch, const char *modeline, - int aspect, int scale_video, int field_order); - void ConfigureDecoder(int pes_buffers); - // remote mode: - void Listen(bool activate, int port); - - - // File playback - - private: - ePlayMode m_PlayingFile; - - public: - bool PlayFile(const char *Filename, int Position=0, - bool LoopPlay=false, ePlayMode PlayMode=pmAudioVideo); - int PlayFileCtrl(const char *Cmd); - bool EndOfStreamReached(void); - - - // Stream data - - private: - bool m_ac3Present; - bool m_spuPresent; - bool m_RadioStream; - int m_AudioCount; - bool m_SkipAudio; - bool m_StreamStart; - int m_FreeBufs; - bool m_Cleared; - bool m_h264; - - int PlayAny(const uchar *Data, int Length); - int PlayTrickSpeed(const uchar *buf, int length); - - protected: - - virtual bool Poll(cPoller &Poller, int TimeoutMs = 0); - - virtual void StillPicture(const uchar *Data, int Length); - - virtual int PlayVideo(const uchar *Data, int Length); - virtual int PlayAudio(const uchar *Data, int Length, uchar Id); - -#if VDRVERSNUM < 10510 - virtual int PlaySpu(const uchar *Data, int Length, uchar Id); - - // conflicts with vdr-1.5.10+ DVB subtitle handling - // override cDevice to get DVD SPUs - virtual int PlayPesPacket(const uchar *Data, int Length, - bool VideoOnly = false); -#endif -}; - -#endif // __XINELIB_DEVICE_H diff --git a/dummy_player.c b/dummy_player.c deleted file mode 100644 index 8980e656..00000000 --- a/dummy_player.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - * dummy_player.c: Player that does nothing (saves CPU time) - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: dummy_player.c,v 1.3 2007-10-15 00:15:07 phintuka Exp $ - * - */ - -#include - -#include "dummy_player.h" -#include "tools/timer.h" - -#define STILLPICTURE_INTERVAL (5*1000) // 5 sec - -// -// cDummyPlayerControl -// - -extern const unsigned char v_mpg_vdrlogo[]; // vdrlogo_720x576.mpg.c -extern const int v_mpg_vdrlogo_length; // vdrlogo_720x576.mpg.c -//extern const unsigned char v_mpg_nosignal[];// nosignal_720x576.mpg.c -//extern const int v_mpg_nosignal_length; // nosignal_720x576.mpg.c -//extern const unsigned char v_mpg_black[]; // black_720x576.mpg.c -//extern const int v_mpg_black_length; // black_720x576.mpg.c - -class cDummyPlayer : public cPlayer { - protected: - virtual void Activate(bool On) - { - if(On) { - TimerHandler(); - CreateTimerEvent(this, &cDummyPlayer::TimerHandler, STILLPICTURE_INTERVAL); - } else { - CancelTimerEvents(this); - } - } - bool TimerHandler(void) - { - DeviceStillPicture(v_mpg_vdrlogo, v_mpg_vdrlogo_length); - //DeviceStillPicture(v_mpg_nosignal, v_mpg_nosignal_length); - //DeviceStillPicture(v_mpg_black, v_mpg_black_length); - return true; - } - - public: - cDummyPlayer(void) {}; - virtual ~cDummyPlayer() - { - Activate(false); - Detach(); - } -}; - -// -// cDummyPlayerControl -// - -cDummyPlayer *cDummyPlayerControl::m_Player = NULL; -cMutex cDummyPlayerControl::m_Lock; - -cDummyPlayerControl::cDummyPlayerControl(void) : - cControl(OpenPlayer()) -{ - cStatus::MsgReplaying(this, "none", NULL, true); -} - -cDummyPlayerControl::~cDummyPlayerControl() -{ - cStatus::MsgReplaying(this, NULL, NULL, false); - Close(); -} - -cDummyPlayer *cDummyPlayerControl::OpenPlayer(void) -{ - m_Lock.Lock(); - if(!m_Player) - m_Player = new cDummyPlayer; - m_Lock.Unlock(); - return m_Player; -} - -void cDummyPlayerControl::Close(void) -{ - m_Lock.Lock(); - if(m_Player) - delete m_Player; - m_Player = NULL; - m_Lock.Unlock(); -} - -eOSState cDummyPlayerControl::ProcessKey(eKeys Key) -{ - if(!ISMODELESSKEY(Key) || Key == kBack || Key == kStop) { - Close(); - return osEnd; - } - return osContinue; -} - diff --git a/dummy_player.h b/dummy_player.h deleted file mode 100644 index 9af28ba7..00000000 --- a/dummy_player.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * dummy_player.h: Player that does nothing (saves CPU time) - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: dummy_player.h,v 1.1 2006-06-03 09:50:54 phintuka Exp $ - * - */ - -#ifndef __DUMMY_PLAYER_H -#define __DUMMY_PLAYER_H - -#include - -class cDummyPlayer; - -class cDummyPlayerControl : public cControl -{ - private: - static cDummyPlayer *m_Player; - static cMutex m_Lock; - - static cDummyPlayer *OpenPlayer(void); - - public: - cDummyPlayerControl(void); - virtual ~cDummyPlayerControl(); - - virtual void Show(void) {}; - virtual void Hide(void) {}; - virtual eOSState ProcessKey(eKeys Key); - - static void Close(void); - static bool IsOpen(void) {return m_Player != NULL;}; -}; - -#endif //__DUMMY_PLAYER_H - diff --git a/equalizer.c b/equalizer.c deleted file mode 100644 index 98b81a00..00000000 --- a/equalizer.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * equalizer.c: audio equalizer OSD control - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: equalizer.c,v 1.4 2007-10-15 00:15:07 phintuka Exp $ - * - */ - -#include - -#include "config.h" -#include "device.h" -#include "equalizer.h" - -cEqualizer::cEqualizer() : cOsdObject() -{ - m_Values = new int[AUDIO_EQ_count]; - memcpy(m_Values, xc.audio_equalizer, sizeof(xc.audio_equalizer)); - m_Osd = NULL; - m_Current = 0; -} - -cEqualizer::~cEqualizer() -{ - delete m_Osd; - delete m_Values; -} - -#define OSD_W (220) -#define OSD_H (220) -#define OSD_X (720-50-OSD_W) -#define OSD_Y (576-50-OSD_H) -/* dvbdevice requires bpp*width to be n*8 */ - -#define ADJUST_MIN (-100) -#define ADJUST_MAX (100) -#define ADJUST_STEP (5) - -void cEqualizer::Show() -{ - tArea areas [] = { {0, 0, OSD_W - 1, OSD_H - 1, 4} }; - -#if VDRVERSNUM >= 10509 - m_Osd = cOsdProvider::NewOsd(OSD_X, OSD_Y, 0); -#else - m_Osd = cOsdProvider::NewOsd(OSD_X, OSD_Y); -#endif - - if(m_Osd) { - if (m_Osd->CanHandleAreas(areas, sizeof(areas) / sizeof(tArea) ) == oeOk) { - m_Osd->SetAreas(areas, sizeof(areas) / sizeof(tArea)); - m_Osd->Flush(); - DrawBackground(); - DrawBar(0,true); - for(int i=1; i ADJUST_MAX) - m_Values[m_Current] = ADJUST_MAX; - DrawBar(m_Current,true); - cXinelibDevice::Instance().ConfigurePostprocessing(xc.deinterlace_method, xc.audio_delay, xc.audio_compression, m_Values, xc.audio_surround, xc.speaker_type); - break; - case kLeft: - if(m_Current>0) { - DrawBar(m_Current); - m_Current--; - DrawBar(m_Current, true); - } - break; - case kRight: - if(m_Current+1 < AUDIO_EQ_count) { - DrawBar(m_Current); - m_Current++; - DrawBar(m_Current, true); - } - break; - case kBack: - cXinelibDevice::Instance().ConfigurePostprocessing(xc.deinterlace_method, xc.audio_delay, xc.audio_compression, xc.audio_equalizer, xc.audio_surround, xc.speaker_type); - return osEnd; - case kOk: - memcpy(xc.audio_equalizer, m_Values, sizeof(xc.audio_equalizer)); - return osEnd; - } - } - - return state; -} - -#define COL_BORDER 0xffb0b0b0 -#define COL_BG 0x7f7f7f7f -#define COL_BAR 0xff000000 -#define COL_BAR_SEL 0xffff0000 -#define COL_BAR_ON 0xff00FF00 -#define COL_BAR_OFF 0xff000000 -#define COL_BAR_BORDER 0xff7f7f7f - -void cEqualizer::DrawBackground() -{ - // border - m_Osd->DrawRectangle(0, 0, OSD_W - 1, OSD_H - 1, COL_BORDER); - m_Osd->DrawRectangle(1, 1, OSD_W - 2, OSD_H - 2, COL_BORDER); - // background - m_Osd->DrawRectangle(2, 2, OSD_W - 3, OSD_H - 3, COL_BG); - // line - m_Osd->DrawRectangle(5, 10+100-1, OSD_W-6, 10+100, COL_BAR); - // commit - m_Osd->Flush(); -} - -void cEqualizer::DrawBar(int Index, bool Selected) -{ - // bar - if(Selected) - m_Osd->DrawRectangle(10+20*Index, 10, 10+20*Index+7, OSD_H - 10, COL_BAR_SEL); - else - m_Osd->DrawRectangle(10+20*Index, 10, 10+20*Index+7, OSD_H - 10, COL_BAR); - // off - m_Osd->DrawRectangle(12+20*Index, 10, 10+20*Index+5, OSD_H - 10, COL_BAR_OFF); - // on - if(m_Values[Index]>0) - m_Osd->DrawRectangle(12+20*Index, 10+100-m_Values[Index], 10+20*Index+5, 10+100, COL_BAR_ON); - else - m_Osd->DrawRectangle(12+20*Index, 10+100, 10+20*Index+5, 10+100-m_Values[Index], COL_BAR_ON); - // line - m_Osd->DrawRectangle(12+20*Index, 10+100-1, 10+20*Index+5, 10+100, COL_BAR_ON); - - m_Osd->Flush(); -} - - diff --git a/equalizer.h b/equalizer.h deleted file mode 100644 index e2c7a9fa..00000000 --- a/equalizer.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * equalizer.h: audio equalizer OSD control - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: equalizer.h,v 1.1 2006-06-03 09:50:54 phintuka Exp $ - * - */ - -#ifndef __EQUALIZER_H -#define __EQUALIZER_H - -#include -#include - -class cEqualizer : public cOsdObject -{ - private: - int *m_Values; - int m_Current; - - cOsd *m_Osd; - - public: - cEqualizer(); - virtual ~cEqualizer(); - - virtual void Show(); - virtual eOSState ProcessKey(eKeys Key); - - void DrawBackground(void); - void DrawBar(int Index, bool Selected = false); -}; - -#endif // __EQUALIZER_H_ diff --git a/examples/Live Radio/BBC Radio 4 Live.m3u b/examples/Live Radio/BBC Radio 4 Live.m3u deleted file mode 100755 index daebab2f..00000000 --- a/examples/Live Radio/BBC Radio 4 Live.m3u +++ /dev/null @@ -1,4 +0,0 @@ -#EXTM3U -#EXTINF:111,BBC Radio 4 Live -rtsp://rmlivev8bb.bbc.net.uk/farm/*/ev7/live24/radio4/live/r4_dsat_g2.ra - diff --git a/examples/Live Radio/BBC World Service.ram b/examples/Live Radio/BBC World Service.ram deleted file mode 100644 index 0a706198..00000000 --- a/examples/Live Radio/BBC World Service.ram +++ /dev/null @@ -1 +0,0 @@ -rtsp://rmlivev8.bbc.net.uk/farm/*/ev7/live24/worldservice/liveinfent.ra diff --git a/examples/remote.conf.example b/examples/remote.conf.example deleted file mode 100644 index 681c2760..00000000 --- a/examples/remote.conf.example +++ /dev/null @@ -1,60 +0,0 @@ -LIRC.Up up -LIRC.Down down -LIRC.Left left -LIRC.Right right -LIRC.Menu menu -LIRC.Ok ok -LIRC.Back exit -KBD.Up 00000000001B5B41 -KBD.Down 00000000001B5B42 -KBD.Menu 000000000000006D -KBD.Ok 000000000000000D -KBD.Back 0000000000000062 -KBD.Left 00000000001B5B44 -KBD.Right 00000000001B5B43 -XKeySym.Up Up -XKeySym.Down Down -XKeySym.Left Left -XKeySym.Right Right -XKeySym.Menu F1 -XKeySym.Ok Return -XKeySym.Back BackSpace -XKeySym.Red F2 -XKeySym.Green F3 -XKeySym.Yellow F4 -XKeySym.Blue F5 -XKeySym.0 0 -XKeySym.1 1 -XKeySym.2 2 -XKeySym.3 3 -XKeySym.4 4 -XKeySym.5 5 -XKeySym.6 6 -XKeySym.7 7 -XKeySym.8 8 -XKeySym.9 9 -XKeySym.Play p -XKeySym.Pause space -XKeySym.Stop s -XKeySym.FastFwd f -XKeySym.FastRew b -XKeySym.Channel+ Prior -XKeySym.Channel- Next -XKeySym.Volume+ KP_Add -XKeySym.Volume- KP_Subtract -XKeySym.Mute m -XKeySym.Schedule F6 -XKeySym.Channels F7 -XKeySym.Timers F8 -XKeySym.Recordings F9 -XKeySym.Setup F10 -XKeySym.Commands F11 -XKeySym.User1 q -XKeySym.User2 w -XKeySym.User3 e -XKeySym.User4 r -XKeySym.User5 t -XKeySym.User6 y -XKeySym.User7 u -XKeySym.User8 i -XKeySym.User9 o diff --git a/frontend.c b/frontend.c deleted file mode 100644 index 51133266..00000000 --- a/frontend.c +++ /dev/null @@ -1,898 +0,0 @@ -/* - * frontend.c: - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: frontend.c,v 1.59 2008-04-14 19:58:54 phintuka Exp $ - * - */ - -#define __STDC_FORMAT_MACROS -#define __STDC_CONSTANT_MACROS -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "logdefs.h" -#include "config.h" -#include "frontend.h" -#include "device.h" - -#include "tools/pes.h" -#include "tools/general_remote.h" -#include "tools/iso639.h" - -//#define LOG_CONTROL_MESSAGES -//#define XINELIBOUTPUT_LOG_KEYS - -#ifndef STARTUP_IMAGE_FILE -# define STARTUP_IMAGE_FILE "/usr/share/vdr/xineliboutput/logo.mpv" -#endif -#ifndef STARTUP_MAX_SIZE -# define STARTUP_MAX_SIZE (256*1024) -#endif - -//----------------------------- cXinelibThread -------------------------------- - -// -// keyboard control handler -// - -/*static*/ -void cXinelibThread::KeypressHandler(const char *keymap, const char *key, - bool repeat, bool release) -{ -#ifdef XINELIBOUTPUT_LOG_KEYS - static FILE *flog = fopen("/video/keys.log","w"); - if (flog) { - fprintf(flog,"KEY %s %s %d %d\n",keymap,key,repeat,release); fflush(flog); - } -#endif - - TRACE("keypress_handler: " << (keymap?keymap:"") << " " << key); - - if(!key) - return; - - if(keymap) { - cRemote *item = Remotes.First(); - while(item) { - if(!strcmp(item->Name(), keymap)) { - // dirty... but only way to support learning ... - ((cGeneralRemote*)item)->Put(key, repeat, release); - return; - } - item = Remotes.Next(item); - } - cGeneralRemote *r = new cGeneralRemote(keymap); - if(*key) - r->Put(key, repeat, release); - } else { - cRemote::Put(cKey::FromString(key)); - } -} - -#include -class cFrontendStatusMonitor : public cStatus { - private: - bool& m_SpuLangAuto; - public: - cFrontendStatusMonitor(bool& SpuLangAuto) : m_SpuLangAuto(SpuLangAuto) {}; - virtual void SetSubtitleTrack(int /*Index*/, const char * const */*Tracks*/) { m_SpuLangAuto = false; } -}; - -void cXinelibThread::InfoHandler(const char *info) -{ - char *pmap = strdup(info), *map = pmap, *pt; - - if(NULL != (pt=strchr(map, '\r'))) - *pt = 0; - - if(!strncmp(info, "TRACKMAP SPU", 12)) { - int CurrentTrack = ttXSubtitleAuto; - map += 12; -#if VDRVERSNUM < 10515 && !defined(VDRSPUPATCH) - cXinelibDevice::Instance().ClrAvailableDvdSpuTracks(false); -#endif - while(*map) { - bool Current = false; - while(*map == ' ') map++; - if(*map == '*') { - Current = true; - map++; - if (*map == '-') { - CurrentTrack = atoi(map); - while (*map && *map != ' ') map++; - continue; - } - } - if(*map >= '0' && *map <= '9') { - int id = atoi(map); - while(*map && *map != ':') map++; - if(*map == ':') map++; - char *lang = map; - while(*map && *map != ' ') map++; - if(*map == ' ') { *map = 0; map++; }; -#if VDRVERSNUM < 10515 && !defined(VDRSPUPATCH) - cXinelibDevice::Instance().SetAvailableDvdSpuTrack(id, iso639_2_to_iso639_1(lang), Current); -#else - cXinelibDevice::Instance().SetAvailableTrack(ttSubtitle, id, id+1, iso639_2_to_iso639_1(lang)); - if (Current) - CurrentTrack = id; -#endif - } - } -#if VDRVERSNUM < 10515 && !defined(VDRSPUPATCH) - cXinelibDevice::Instance().EnsureDvdSpuTrack(); -#else - if (CurrentTrack == ttXSubtitleAuto) - cXinelibDevice::Instance().EnsureSubtitleTrack(); - else if (CurrentTrack == ttXSubtitleNone) - cXinelibDevice::Instance().SetCurrentSubtitleTrack(ttNone, true); - else - cXinelibDevice::Instance().SetCurrentSubtitleTrack(eTrackType(CurrentTrack+ttSubtitleFirst), true); -#endif - } - - else if(!strncmp(info, "TRACKMAP AUDIO", 14)) { - map += 14; - cXinelibDevice::Instance().ClrAvailableTracks(); - while(*map) { - bool Current = false; - while(*map == ' ') map++; - if(*map == '*') { - Current = true; - map++; - } - int id = atoi(map); - while(*map && *map != ':') map++; - if(*map == ':') map++; - char *lang = map; - while(*map && *map != ' ') map++; - if(*map == ' ') { *map = 0; map++; }; - cXinelibDevice::Instance().SetAvailableTrack(ttDolby, id, ttDolby+id, iso639_2_to_iso639_1(lang)); - if(Current) - cXinelibDevice::Instance().SetCurrentAudioTrack((eTrackType)(ttDolby+id)); - } - } - - else if(!strncmp(info, "METAINFO", 8)) { - map += 8; - while(*map) { - while(*map == ' ') map++; - char *next = strstr(map, "=@"); - if(!next) - break; - *next = 0; - next += 2; - char *end = strstr(next, "@"); - if(!end) - break; - *end = 0; - - if(!strcmp(map, "title")) - cXinelibDevice::Instance().SetMetaInfo(miTitle, next); - if(!strcmp(map, "tracknumber")) - cXinelibDevice::Instance().SetMetaInfo(miTracknumber, next); - if(!strcmp(map, "album")) - cXinelibDevice::Instance().SetMetaInfo(miAlbum, next); - if(!strcmp(map, "artist")) - cXinelibDevice::Instance().SetMetaInfo(miArtist, next); - map = end+1; - } - } - - else if(!strncmp(info, "TITLE ", 6)) { - map += 6; - while(*map == ' ') map++; - cXinelibDevice::Instance().SetMetaInfo(miTitle, map); - } - - else if(!strncmp(info, "DVDTITLE ", 9)) { - LOGMSG("DVDTITLE %s", info); - map += 9; - while(*map == ' ') map++; - cXinelibDevice::Instance().SetMetaInfo(miDvdTitleNo, map); -#if VDRVERSNUM < 10515 && !defined(VDRSPUPATCH) - if (*map == '0') // DVD Menu, set spu track to 0 - cXinelibDevice::Instance().SetCurrentDvdSpuTrack(0); -#else - if (*map == '0') // DVD Menu, set spu track to 0 - cXinelibDevice::Instance().SetCurrentSubtitleTrack(ttSubtitleFirst); -#endif - } - - free(pmap); -} - -cXinelibThread::cXinelibThread(const char *Description) : cThread(Description) -{ - TRACEF("cXinelibThread::cXinelibThread"); - - m_Volume = 255; - m_bStopThread = false; - m_bReady = false; - m_bIsFinished = false; - m_bNoVideo = true; - m_bLiveMode = true; /* can't be replaying when there is no output device */ - m_StreamPos = 0; - m_Frames = 0; - m_bEndOfStreamReached = false; - m_bPlayingFile = false; - m_StatusMonitor = NULL; -} - -cXinelibThread::~cXinelibThread() -{ - TRACEF("cXinelibThread::~cXinelibThread"); - - m_bStopThread = true; - if(Active()) - Cancel(); - if(m_StatusMonitor) - delete m_StatusMonitor; -} - -// -// Thread control -// - -void cXinelibThread::Start(void) -{ - TRACEF("cXinelibThread::Start"); - - cThread::Start(); -} - -void cXinelibThread::Stop(void) -{ - TRACEF("cXinelibThread::Stop"); - - SetStopSignal(); - - //if(Active()) - Cancel(5); -} - -void cXinelibThread::SetStopSignal(void) -{ - TRACEF("cXinelibThread::SetStopSignal"); - - LOCK_THREAD; - m_bStopThread = true; -} - -bool cXinelibThread::GetStopSignal(void) -{ - TRACEF("cXinelibThread::GetStopSignal"); - - LOCK_THREAD; - return m_bStopThread; -} - -bool cXinelibThread::IsReady(void) -{ - LOCK_THREAD; - return m_bReady; -} - -bool cXinelibThread::IsFinished(void) -{ - LOCK_THREAD; - return m_bIsFinished; -} - -// -// Playback control -// - -void cXinelibThread::SetVolume(int NewVolume) -{ - m_Volume = NewVolume; - cString str = cString::sprintf("VOLUME %d%s", NewVolume * 100 / 255, - xc.sw_volume_control ? " SW" : ""); - Xine_Control(str); -} - -void cXinelibThread::TrickSpeed(int Speed) -{ - TRACEF("cXinelibThread::TrickSpeed"); - - Xine_Control("TRICKSPEED", Speed); -} - -void cXinelibThread::SetLiveMode(bool LiveModeOn) -{ - TRACEF("cXinelibThread::SetLiveMode"); - - Lock(); - if(m_bLiveMode == LiveModeOn) { - Unlock(); - return; - } - m_bLiveMode = LiveModeOn; - Unlock(); - - Xine_Control("LIVE", m_bLiveMode ? 1 : 0); -} - -void cXinelibThread::SetStillMode(bool StillModeOn) -{ - TRACEF("cXinelibThread::SetStillMode"); - Xine_Control("STILL", StillModeOn ? 1 : 0); -} - -void cXinelibThread::SetNoVideo(bool bVal) -{ - TRACEF("cXinelibThread::SetNoVideo"); - - Lock(); - if(m_bNoVideo == bVal) { - Unlock(); - return; - } - m_bNoVideo = bVal; - Unlock(); - - Xine_Control("NOVIDEO", m_bNoVideo ? 1 : 0); - - char *opts = NULL; - if(xc.audio_vis_goom_opts[0] && !strcmp(xc.audio_visualization, "goom")) - opts = xc.audio_vis_goom_opts; - - if(m_bNoVideo && strcmp(xc.audio_visualization, "none")) { - ConfigurePostprocessing(xc.audio_visualization, true, opts); - } else { - ConfigurePostprocessing("AudioVisualization", false, NULL); - } -} - -void cXinelibThread::AudioStreamChanged(bool ac3, int StreamId) -{ - TRACEF("cXinelibThread::AudioStreamChanged"); - if(ac3) - Xine_Control("AUDIOSTREAM AC3", StreamId); - else - Xine_Control("AUDIOSTREAM", StreamId); -} - -#if VDRVERSNUM < 10515 -void cXinelibThread::SpuStreamChanged(int StreamId) -{ - TRACEF("cXinelibThread::SpuStreamChanged"); - Xine_Control("SPUSTREAM", StreamId); -} -#else -void cXinelibThread::SetSubtitleTrack(eTrackType Track) -{ - TRACEF("cXinelibThread::SetSubtitleTrack"); - cString buf = cString::sprintf("SPUSTREAM %d%s", - Track==ttNone ? ttXSubtitleNone : (Track - ttSubtitleFirst), - m_SpuLangAuto ? " auto" : ""); - Xine_Control(buf); -} -#endif - -void cXinelibThread::Clear(void) -{ - TRACEF("cXinelibThread::Clear"); - - Lock(); - int64_t tmp1 = m_StreamPos; - uint32_t tmp2 = m_Frames; - Unlock(); - - char buf[128]; - snprintf(buf, sizeof(buf), "DISCARD %" PRId64 " %d", tmp1, tmp2); - /* Send to control stream and data stream. If message is sent only to - * control stream, and it is delayed, engine flush will be skipped. - */ - Xine_Control(buf); - Xine_Control_Sync(buf); -} - -bool cXinelibThread::Flush(int TimeoutMs) -{ - TRACEF("cXinelibThread::Flush"); - - return Xine_Control("FLUSH", TimeoutMs) <= 0; -} - -int cXinelibThread::Poll(cPoller& Poller, int TimeoutMs) -{ - TRACEF("cXinelibThread::Poll"); - - if(!m_bReady) { - if(TimeoutMs>0) - cCondWait::SleepMs(TimeoutMs); - if(!m_bReady) - return 0; - } - - int n = Xine_Control("POLL", TimeoutMs); - - return max(n, 0); -} - -// -// Data transfer -// - -int cXinelibThread::Play_PES(const uchar *data, int len) -{ - Lock(); - m_StreamPos += len; - m_Frames++; - /*m_bEndOfStreamReached = false;*/ - Unlock(); - return len; -} - -// -// Stream conversions -// - -// Convert MPEG1 PES headers to MPEG2 PES headers - -int cXinelibThread::Play_Mpeg1_PES(const uchar *data1, int len) -{ - if(!data1[0] && !data1[1] && data1[2] == 0x01 && len>7 && /* header sync bytes */ - ( IS_VIDEO_PACKET(data1) || IS_AUDIO_PACKET(data1)) && /* video / audio / ps1 stream */ - ((data1[6] & 0xC0) != 0x80) && /* really mpeg1 pes */ - (len == ((data1[4]<<8) | data1[5]) + 6)) { /* whole PES packet and nothing else */ - uchar *data2 = new uchar[len+64]; - int i1=0, i2=0, r=0; - - data2[i2++]=data1[i1++]; // 00 (sync) - data2[i2++]=data1[i1++]; // 00 (sync) - data2[i2++]=data1[i1++]; // 01 (sync) - data2[i2++]=data1[i1++]; // stream ID - data2[i2++]=data1[i1++]; // len hi - data2[i2++]=data1[i1++]; // len lo - - // skip stuffing - while ((data1[i1] & 0x80) == 0x80) - i1++; - - if ((data1[i1] & 0xc0) == 0x40) { - // skip STD_buffer_scale, STD_buffer_size - i1 += 2; - } - - if(len>8; - data2[5] = ((newlen)&0xff); - if(len-i1 > 0) { - memcpy(data2+i2, data1+i1, len-i1); - cPoller p; - while(!Poll(p,100) && loops++ < 10) { - LOGDBG("Play_Mpeg1_PES: poll failed"); - } - r = Play_PES(data2,newlen+6); - } - - delete data2; - return r==newlen+6 ? ((data1[4]<<8)|data1[5])+6 : 0; - } - return len; // nothing useful found ... -} - -// Pack elementary MPEG stream to PES - -bool cXinelibThread::Play_Mpeg2_ES(const uchar *data, int len, int streamID) -{ - static uchar hdr_vid[] = {0x00,0x00,0x01,0xe0, 0x00,0x00,0x80,0x00,0x00}; /* mpeg2 */ - static uchar hdr_pts[] = {0x00,0x00,0x01,0xe0, 0x00,0x08,0x80,0x80, - 0x05,0x00,0x00,0x00, 0x00,0x00}; /* mpeg2 */ - static uchar seq_end[] = {0x00,0x00,0x01,0xe0, 0x00,0x07,0x80,0x00, - 0x00, - 0x00,0x00,0x01,0xB7}; /* mpeg2 */ - int todo = len, done = 0, hdrlen = 9/*sizeof(hdr)*/; - uchar *frame = new uchar[PES_CHUNK_SIZE+32]; - cPoller p; - - - hdr_pts[3] = (uchar)streamID; - Poll(p, 100); - Play_PES(hdr_pts, sizeof(hdr_pts)); - - hdr_vid[3] = (uchar)streamID; - while(todo) { - int blocklen = todo; - if(blocklen > ((PES_CHUNK_SIZE - hdrlen) & 0xfffc)) - blocklen = (PES_CHUNK_SIZE - hdrlen) & 0xfffc; - hdr_vid[4] = ((blocklen+3)&0xff00)>>8; - hdr_vid[5] = ((blocklen+3)&0xff); - - memcpy(frame, hdr_vid, hdrlen); - memcpy(frame+hdrlen, data+done, blocklen); - - done += blocklen; - todo -= blocklen; - - Poll(p, 100); - - if(blocklen+hdrlen != Play_PES(frame,blocklen+hdrlen)) { - delete frame; - return false; - } - } - - // append sequence end code to video - if((streamID & 0xF0) == 0xE0) { - seq_end[3] = (uchar)streamID; - Poll(p, 100); - Play_PES(seq_end, sizeof(seq_end)); - } - - delete[] frame; - return true; -} - -// -// Built-in still images -// - -bool cXinelibThread::QueueBlankDisplay(void) -{ - TRACEF("cXinelibThread::BlankDisplay"); -#if 0 - extern const unsigned char v_mpg_black[]; // black_720x576.c - extern const int v_mpg_black_length; - - Play_Mpeg2_ES(v_mpg_black, v_mpg_black_length, VIDEO_STREAM); -#endif - Xine_Control_Sync("BLANK"); - return true; -} - -bool cXinelibThread::BlankDisplay(void) -{ - TRACEF("cXinelibThread::BlankDisplay"); - - bool r = QueueBlankDisplay(); - for(int i=0; i<5 && !Flush(100); i++) - ; - return r; -} - -bool cXinelibThread::LogoDisplay(void) -{ - TRACEF("cXinelibThread::LogoDisplay"); - - cString Path; - int fd = -1; - - if(Setup.FileName()) { - cString SetupPath = Setup.FileName(); - char *end = strrchr(SetupPath, '/'); - if(end) { - *end = 0; - fd = open(Path=cString::sprintf("%s/plugins/xineliboutput/logo.mpv", *SetupPath), O_RDONLY); - } - } - - if(fd<0) - fd = open(Path=STARTUP_IMAGE_FILE, O_RDONLY); - - if(fd >= 0) { - uint8_t *data = (uint8_t*)malloc(STARTUP_MAX_SIZE); - int datalen = read(fd, data, STARTUP_MAX_SIZE); - if(datalen == STARTUP_MAX_SIZE) { - LOGMSG("WARNING: custom startup image %s too large", *Path); - } else if(datalen<=0) { - LOGERR("error reading custom startup image %s", *Path); - } else { - LOGMSG("using custom startup image %s", *Path); - bool r = Play_Mpeg2_ES(data, datalen, VIDEO_STREAM); - free(data); - for(int i=0; i<5 && !Flush(100); i++) - ; - return r; - } - free(data); - close(fd); - } - - /* use default image */ - extern const unsigned char v_mpg_vdrlogo[]; // vdrlogo_720x576.c - extern const int v_mpg_vdrlogo_length; - - bool r = Play_Mpeg2_ES(v_mpg_vdrlogo, v_mpg_vdrlogo_length, VIDEO_STREAM); - for(int i=0; i<5 && !Flush(100); i++) - ; - return r; -} - -bool cXinelibThread::NoSignalDisplay(void) -{ - TRACEF("cXinelibThread::NoSignalDisplay"); - - extern const unsigned char v_mpg_nosignal[]; // nosignal_720x576.c - extern const int v_mpg_nosignal_length; - - bool r = Play_Mpeg2_ES(v_mpg_nosignal, v_mpg_nosignal_length, VIDEO_STREAM); - for(int i=0; i<5 && !Flush(100); i++) - ; - return r; -} - -// -// Xine Control -// - -int cXinelibThread::Xine_Control(const char *cmd, int p1) -{ - char buf[128]; - if(snprintf(buf, sizeof(buf), "%s %d", cmd, p1) >= (int)sizeof(buf)) { - LOGMSG("Xine_Control %s: message too long !", cmd); - return 0; - } - //buf[sizeof(buf)-1] = 0; - return Xine_Control(buf); -} - -int cXinelibThread::Xine_Control(const char *cmd, int64_t p1) -{ - char buf[128]; - if(snprintf(buf, sizeof(buf), "%s %" PRId64, cmd, p1) >= (int)sizeof(buf)) { - LOGMSG("Xine_Control %s: message too long !", cmd); - return 0; - } - //buf[sizeof(buf)-1] = 0; - return Xine_Control(buf); -} - -int cXinelibThread::Xine_Control(const char *cmd, const char *p1) -{ - char buf[1024]; - if(snprintf(buf, sizeof(buf), "%s %s", cmd, p1) >= (int)sizeof(buf)) { - LOGMSG("Xine_Control %s: message too long !", cmd); - return 0; - } - //buf[sizeof(buf)-1] = 0; - return Xine_Control(buf); -} - -bool cXinelibThread::PlayFile(const char *FileName, int Position, - bool LoopPlay, ePlayMode PlayMode) -{ - TRACEF("cXinelibThread::PlayFile"); - - char vis[256]; - - switch(PlayMode) { - case pmVideoOnly: - LOGDBG("cXinelibThread::PlayFile: Video from file, audio from VDR"); - strcpy(vis, "Video"); - break; - case pmAudioOnly: - LOGDBG("cXinelibThread::PlayFile: Audio from file, video from VDR"); - strcpy(vis, "Audio"); - break; - case pmAudioOnlyBlack: - //LOGDBG("cXinelibThread::PlayFile: Audio from file, no video"); - strcpy(vis, "none"); - break; - case pmAudioVideo: - default: - if(xc.audio_vis_goom_opts[0] && !strcmp(xc.audio_visualization, "goom")) - snprintf(vis, sizeof(vis), "%s:%s", xc.audio_visualization, xc.audio_vis_goom_opts); - else - strn0cpy(vis, xc.audio_visualization, sizeof(vis)); - vis[sizeof(vis)-1] = 0; - break; - } - - char buf[4096]; - m_bEndOfStreamReached = false; - if(snprintf(buf, sizeof(buf), "PLAYFILE %s %d %s %s", - LoopPlay ? "Loop" : "", Position, vis, FileName ? FileName : "") - >= 4096) { - LOGMSG("PlayFile: message too long !"); - return 0; - } - - if(FileName) { - Lock(); - m_FileName = FileName; - m_bPlayingFile = true; - m_SpuLangAuto = true; -#if VDRVERSNUM >= 10515 - if (m_StatusMonitor) - DELETENULL(m_StatusMonitor); - m_StatusMonitor = new cFrontendStatusMonitor(m_SpuLangAuto); -#endif - Unlock(); - } - - int result = PlayFileCtrl(buf); - - if(!FileName || result != 0) { - Lock(); - m_bPlayingFile = false; - m_FileName = NULL; - if (m_StatusMonitor) - DELETENULL(m_StatusMonitor); - Unlock(); - } else { - if(xc.extsub_size >= 0) - Xine_Control("EXTSUBSIZE", xc.extsub_size); - } - - return (!GetStopSignal()) && (result==0); -} - - -// -// Configuration -// - -void cXinelibThread::Configure(void) -{ - ConfigurePostprocessing(xc.deinterlace_method, xc.audio_delay, - xc.audio_compression, xc.audio_equalizer, - xc.audio_surround, xc.speaker_type); - ConfigureVideo(xc.hue, xc.saturation, xc.brightness, xc.contrast, xc.overscan, xc.vo_aspect_ratio); - ConfigurePostprocessing("upmix", xc.audio_upmix ? true : false, NULL); - ConfigurePostprocessing("autocrop", xc.autocrop ? true : false, - xc.AutocropOptions()); - ConfigurePostprocessing("swscale", xc.swscale ? true : false, - xc.SwScaleOptions()); - ConfigurePostprocessing("pp", xc.ffmpeg_pp ? true : false, - xc.FfmpegPpOptions()); - ConfigurePostprocessing("unsharp",xc.unsharp ? true : false, - xc.UnsharpOptions()); - ConfigurePostprocessing("denoise3d",xc.denoise3d ? true : false, - xc.Denoise3dOptions()); - -#ifdef ENABLE_TEST_POSTPLUGINS - ConfigurePostprocessing("headphone", xc.headphone ? true : false, NULL); -#endif - - Xine_Control(cString::sprintf("SCR %s %d", - xc.live_mode_sync ? "Sync" : "NoSync", - xc.scr_tunning ? xc.scr_hz : 90000)); -} - -int cXinelibThread::ConfigurePostprocessing(const char *deinterlace_method, - int audio_delay, - int audio_compression, - const int *audio_equalizer, - int audio_surround, - int speaker_type) -{ - char buf[1024]; - int r = true; - - if(strcmp(deinterlace_method, "tvtime")) - r = ConfigurePostprocessing("tvtime", false, NULL) && r; - - r = Xine_Control("DEINTERLACE", deinterlace_method) && r; - r = Xine_Control("AUDIODELAY", audio_delay) && r; - r = Xine_Control("AUDIOCOMPRESSION", audio_compression) && r; - r = Xine_Control("AUDIOSURROUND", audio_surround) && r; - r = Xine_Control("SPEAKERS", speaker_type) && r; - sprintf(buf,"EQUALIZER %d %d %d %d %d %d %d %d %d %d", - audio_equalizer[0],audio_equalizer[1], - audio_equalizer[2],audio_equalizer[3], - audio_equalizer[4],audio_equalizer[5], - audio_equalizer[6],audio_equalizer[7], - audio_equalizer[8],audio_equalizer[9]); - r = Xine_Control(buf) && r; - - if(m_bNoVideo && strcmp(xc.audio_visualization, "none")) { - char *opts = NULL; - if(xc.audio_vis_goom_opts[0] && !strcmp(xc.audio_visualization, "goom")) - opts = xc.audio_vis_goom_opts; - //fe->post_open(fe, xc.audio_visualization, NULL); - r = ConfigurePostprocessing(xc.audio_visualization, true, opts) && r; - } else { - //fe->post_close(fe, NULL, 0); - r = ConfigurePostprocessing("AudioVisualization", false, NULL) && r; - } - - if(!strcmp(deinterlace_method, "tvtime")) - r = ConfigurePostprocessing("tvtime", true, xc.deinterlace_opts) && r; - - return r; -} - -int cXinelibThread::ConfigurePostprocessing(const char *name, bool on, const char *args) -{ - char buf[1024]; - int l; - - if(on) - l = snprintf(buf, sizeof(buf), "POST %s On %s", (name&&*name)?name:"0", args?args:""); - else - // 0 - audio vis. - // 1 - audio post - // 2 - video post - //return fe->post_close(fe, name, -1); - l = snprintf(buf, sizeof(buf), "POST %s Off", (name&&*name)?name:"0"); - - if(l >= (int)sizeof(buf)) { - LOGMSG("ConfigurePostprocessing %s: message too long !", name); - return 0; - } - //buf[sizeof(buf)-1] = 0; - - return Xine_Control(buf); -} - -int cXinelibThread::ConfigureVideo(int hue, int saturation, - int brightness, int contrast, - int overscan, int vo_aspect_ratio) -{ - char cmd[128]; - Xine_Control("OVERSCAN", overscan); - snprintf(cmd, sizeof(cmd), - "VIDEO_PROPERTIES %d %d %d %d %d", - hue, saturation, brightness, contrast, vo_aspect_ratio); - return Xine_Control(cmd); -} - -// -// Playback files -// - -bool cXinelibThread::EndOfStreamReached(void) -{ - LOCK_THREAD; - bool r = m_bEndOfStreamReached; - return r; -} - - diff --git a/frontend.h b/frontend.h deleted file mode 100644 index 70c29e12..00000000 --- a/frontend.h +++ /dev/null @@ -1,159 +0,0 @@ -/* - * frontend.h: - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: frontend.h,v 1.22 2008-04-14 19:58:50 phintuka Exp $ - * - */ - -#ifndef __XINELIB_FRONTEND_H -#define __XINELIB_FRONTEND_H - -#include -#include -#include // ePlayMode - -class cStatus; - -//----------------------------- cXinelibThread -------------------------------- - -class cXinelibThread : public cThread, public cListObject -{ - private: - cXinelibThread(cXinelibThread&); // no copy contructor - - public: - cXinelibThread(const char *Description = NULL); - virtual ~cXinelibThread(); - - // - // Thread control - // - - public: - virtual void Start(void); - virtual void Stop(void); - bool IsReady(void); - bool IsFinished(void); - - protected: - void SetStopSignal(void); - bool GetStopSignal(void); - - virtual void Action(void) = 0; - - // - // Playback control - // - - public: - void PauseOutput(void) { TrickSpeed(0); } - void ResumeOutput(void) { TrickSpeed(1); } - virtual void TrickSpeed(int Speed); - void SetVolume(int NewVolume); - void SetLiveMode(bool); - void SetStillMode(bool); - void SetNoVideo(bool bVal); - void AudioStreamChanged(bool ac3, int StreamId); -#if VDRVERSNUM < 10515 - void SpuStreamChanged(int StreamId); -#else - void SetSubtitleTrack(eTrackType Track); -#endif - - protected: - int Xine_Control(const char *cmd, const char *p1); - int Xine_Control(const char *cmd, int p1); - int Xine_Control(const char *cmd, int64_t p1); - virtual int Xine_Control(const char *cmd) = 0; - virtual int Xine_Control_Sync(const char *cmd) { return Xine_Control(cmd); } - - void Configure(void); - - // - // Data transfer - // - - public: - virtual int Poll(cPoller &Poller, int TimeoutMs); - virtual bool Flush(int TimeoutMs); - virtual void Clear(void); - virtual int Play_PES(const uchar *buf, int len); - virtual void OsdCmd(void *cmd) = 0; - virtual int64_t GetSTC(void) { return -1; } - virtual void SetHDMode(bool On) { (void)Xine_Control("HDMODE",On?1:0); }; - - // Stream type conversions - int Play_Mpeg1_PES(const uchar *data, int len); - bool Play_Mpeg2_ES(const uchar *data, int len, int streamID); - - // Built-in still images - bool BlankDisplay(void); - bool QueueBlankDisplay(void); - bool LogoDisplay(void); - bool NoSignalDisplay(void); - - // Playback files - virtual bool PlayFile(const char *FileName, int Position, - bool LoopPlay = false, ePlayMode PlayMode = pmAudioVideo); - virtual int PlayFileCtrl(const char *Cmd) { return Xine_Control(Cmd); } - virtual bool EndOfStreamReached(void); - - // Image grabbing - virtual uchar *GrabImage(int &Size, bool Jpeg, int Quality, - int SizeX, int SizeY) { return NULL; } - - // Control from frontend - static void KeypressHandler(const char *keymap, const char *key, - bool repeat, bool release); - static void InfoHandler(const char *info); - - // - // Configuration - // - - public: - virtual int ConfigurePostprocessing(const char *deinterlace_method, - int audio_delay, - int audio_compression, - const int *audio_equalizer, - int audio_surround, - int speaker_type); - virtual int ConfigurePostprocessing(const char *name, bool on, const char *args); - virtual int ConfigureVideo(int hue, int saturation, - int brightness, int contrast, - int overscan, int vo_aspect_ratio); - // Local frontend: - virtual void ConfigureWindow(int fullscreen, int width, int height, - int modeswitch, const char *modeline, - int aspect, int scale_video, - int field_order) {}; - virtual void ConfigureDecoder(int pes_buffers) {}; - // Remote frontend server: - virtual bool Listen(int port) { return false; } - - // - // Data - // - - protected: - bool m_bStopThread; - bool m_bReady; - bool m_bIsFinished; - bool m_bNoVideo; - bool m_bLiveMode; - bool m_bEndOfStreamReached; - bool m_bPlayingFile; - int m_Volume; - cString m_FileName; - uint64_t m_StreamPos; - uint32_t m_Frames; - - cStatus *m_StatusMonitor; - bool m_SpuLangAuto; -}; - - -#endif // __XINELIB_FRONTEND_H diff --git a/frontend_local.c b/frontend_local.c deleted file mode 100644 index 780520a4..00000000 --- a/frontend_local.c +++ /dev/null @@ -1,463 +0,0 @@ -/* - * frontend_local.c: - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: frontend_local.c,v 1.31 2008-04-03 08:08:27 phintuka Exp $ - * - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#if VDRVERSNUM >= 10501 || (defined(PATCH_SHUTDOWN_REWRITE) && PATCH_SHUTDOWN_REWRITE >= 100) -#include -#endif - -#include "logdefs.h" -#include "config.h" - -#include "xine_frontend.h" - -#include "frontend_local.h" - -//------------------------------ cRwLockBlock --------------------------------- - -class cRwLockBlock -{ - private: - cRwLock& m_Lock; - - public: - cRwLockBlock(cRwLock& lock, bool write) : m_Lock(lock) - { m_Lock.Lock(write);} - - ~cRwLockBlock() - { m_Lock.Unlock(); } -}; - -#define LOCK_FE cRwLockBlock(m_feLock, false) -#define LOCK_FE_WR cRwLockBlock(m_feLock, true) - -//----------------- keyboard control handler (C callback) -------------------- - -extern "C" { - static void keypress_handler(const char *keymap, const char *key) - { - if(!strncmp("INFO ", keymap, 5)) { - - cXinelibThread::InfoHandler(keymap+5); - - } else if(!xc.use_x_keyboard || !key) { - - /* Only X11 key events came this way in local mode. - Keyboard is handled by vdr. */ - LOGMSG("keypress_handler(%s): X11 Keyboard disabled in config", key); - - } else { - - cXinelibThread::KeypressHandler(keymap, key, false, false); - - } - } -}; - -//----------------------------- cXinelibLocal -------------------------------- - -cXinelibLocal::cXinelibLocal(const char *frontend_name) : - cXinelibThread("Local decoder/display (cXinelibThread)"), m_feLock(true) -{ - fe = NULL; - h_fe_lib = NULL; - m_bReconfigRequest = true; -} - -cXinelibLocal::~cXinelibLocal() -{ - TRACEF("cXinelibLocal::~cXinelibLocal"); - - m_bReady = false; - - Stop(); - if(fe) { - fe->fe_free(fe); - fe = NULL; - } - if(h_fe_lib) { - dlclose(h_fe_lib); - } -} - -void cXinelibLocal::Stop(void) -{ - TRACEF("cXinelibLocal::Stop"); - - SetStopSignal(); - - { - LOCK_FE; - m_bReady = false; - if(fe) - fe->fe_interrupt(fe); - } - - cXinelibThread::Stop(); -} - -// -// Data transfer -// - -int cXinelibLocal::Play_PES(const uchar *data, int len) -{ - TRACEF("cXinelibLocal::Play_PES"); - - { - LOCK_FE; - if(fe && !m_bStopThread) { - int done = fe->xine_queue_pes_packet(fe, (char*)data, len); - if(done>0) { - Lock(); - m_StreamPos += done; - Unlock(); - return done; - } - } - } - - //cCondWait::SleepMs(5); - return len; -} - -void cXinelibLocal::OsdCmd(void *cmd) -{ - TRACEF("cXinelibLocal::OsdCmd"); - LOCK_FE; - if(cmd && fe && m_bReady) - fe->xine_osd_command(fe, (struct osd_command_s*)cmd); -} - -uchar *cXinelibLocal::GrabImage(int &Size, bool Jpeg, - int Quality, int SizeX, - int SizeY) -{ - uchar *data; - LOCK_FE; - if(fe && fe->grab && m_bReady) - if((data = (uchar*)fe->grab(fe, &Size, Jpeg, Quality, SizeX, SizeY))) - return data; - return NULL; -} - -int64_t cXinelibLocal::GetSTC() -{ - TRACEF("cXinelibLocal::GetSTC"); - - int64_t pts = -1; - char buf[32] = {0}; - strcpy(buf, "GETSTC\r\n"); - - LOCK_FE; - if(fe && m_bReady) - if(0 == fe->xine_control(fe, (char*)buf)) - //if(*((int64_t *)buf) < MAX_SCR) - // if(*((int64_t *)buf) >= 0LL) - pts = *((int64_t *)buf); - return pts; -} - -// -// Playback files -// - -bool cXinelibLocal::EndOfStreamReached(void) -{ - LOCK_THREAD; - if(fe && fe->xine_is_finished(fe, 1)) - return true; - return cXinelibThread::EndOfStreamReached(); -} - -// -// Configuration -// - -void cXinelibLocal::ConfigureWindow(int fullscreen, int width, int height, - int modeswitch, const char *modeline, - int aspect, int scale_video, - int field_order) -{ - LOCK_FE; - if(fe) - fe->fe_display_config(fe, width, height, fullscreen, modeswitch, modeline, - aspect, scale_video, field_order); -} - -void cXinelibLocal::ConfigureDecoder(int pes_buffers) -{ - // needs xine restart - { - LOCK_FE; - xc.pes_buffers = pes_buffers; - if(!fe) - return; - m_bReady = false; - m_bReconfigRequest = true; - fe->fe_interrupt(fe); - } - - while(!m_bReady && !GetStopSignal()) - cCondWait::SleepMs(100); - - cCondWait::SleepMs(100); -} - -// -// Xine control -// - -int cXinelibLocal::Xine_Control(const char *cmd) -{ - TRACEF("cXinelibLocal::Xine_Control"); - if(cmd && *cmd && !GetStopSignal()) { - char buf[4096]; - if(snprintf(buf, sizeof(buf), "%s\r\n", cmd) >= (int)sizeof(buf)) { - buf[sizeof(buf)-1] = 0; - LOGMSG("Xine_Control: message too long ! (%s)", buf); - return 0; - } - LOCK_FE; - if(fe) - return fe->xine_control(fe, (char*)buf); - } - return 0; -} - -// -// Frontend loader -// - -frontend_t *cXinelibLocal::load_frontend(const char *fe_name) -{ - Dl_info info; - struct stat statbuffer; - char libname[4096]=""; - void *lib = NULL; - fe_creator_f *fe_creator = NULL; - static int my_marker = 0; - - if(!dladdr((void *)&my_marker, &info)) { - LOGERR("Error searching plugin: dladdr() returned false (%s)",dlerror()); - return NULL; - } - LOGDBG("xineliboutput: plugin file is %s", info.dli_fname); - - int fe_ind = strstra(fe_name, xc.s_frontends, FRONTEND_NONE); - bool fe_try = false; - if(fe_ind == FRONTEND_NONE) { - LOGMSG("Front-end %s unknown!", fe_name); - fe_ind = 0; - fe_try = true; - } - - strn0cpy(libname, info.dli_fname, sizeof(libname) - 128); - if(strrchr(libname, '/')) - *(strrchr(libname, '/')+1) = 0; - - LOGDBG("Searching frontend %s from %s", xc.s_frontends[fe_ind], libname); - - do { - strncat(libname, xc.s_frontend_files[fe_ind], 64); - LOGDBG("Probing %s", libname); - - if (stat(libname, &statbuffer)) { - LOGERR("load_frontend: can't stat %s",libname); - } else if((statbuffer.st_mode & S_IFMT) != S_IFREG) { - LOGMSG("load_frontend: %s not regular file ! trying to load anyway ...", - libname); - } - - if( !(lib = dlopen (libname, RTLD_LAZY | RTLD_GLOBAL))) { - char *dl_error_msg = dlerror(); - LOGERR("load_frontend: cannot dlopen file %s: %s", - libname, dl_error_msg); - } else if ( (fe_creator = (fe_creator_f*)dlsym(lib, "fe_creator"))) { - LOGDBG("load_frontend: entry at %p", fe_creator); - frontend_t *fe = (**fe_creator)(); - - if(fe) { - if(h_fe_lib) - dlclose(h_fe_lib); - h_fe_lib = lib; - - LOGDBG("Using frontend %s (%s) from %s", - xc.s_frontends[fe_ind], xc.s_frontendNames[fe_ind], - xc.s_frontend_files[fe_ind]); - - return fe; - } else { - LOGMSG("Frontend %s (%s) creation failed", - xc.s_frontends[fe_ind], xc.s_frontendNames[fe_ind]); - } - } else { - LOGERR("Frontend entry point not found"); - dlclose(lib); - } - - fe_ind++; // try next frontend ... - - } while(fe_try && fe_ind < FRONTEND_count); - - LOGMSG("No usable frontends found, giving up !"); - return NULL; -} - -// -// Thread main loop -// - -void cXinelibLocal::Action(void) -{ - frontend_t *curr_fe = NULL; - - TRACEF("cXinelibLocal::Action"); - - SetPriority(2); /* lower priority */ - - // init frontend - if(!curr_fe) { - curr_fe = load_frontend(xc.local_frontend); - if(!curr_fe) { - LOGMSG("cXinelibLocal: Error initializing frontend"); - SetStopSignal(); - } else { - LOGDBG("cXinelibLocal::Action - fe created"); - if(!curr_fe->fe_display_open(curr_fe, xc.width, xc.height, xc.fullscreen, xc.hud_osd, - xc.modeswitch, xc.modeline, - xc.display_aspect, keypress_handler, - xc.video_port, - xc.scale_video, - xc.field_order)) { - LOGMSG("cXinelibLocal: Error initializing display"); - SetStopSignal(); - } else { - LOGDBG("cXinelibLocal::Action - fe->fe_display_open ok"); - } - } - } - - // main loop - while (!GetStopSignal()) { - - { - // init and start xine engine - LOCK_FE_WR; - LOGDBG("cXinelibLocal::Action - xine_init"); - - fe = curr_fe; - if(m_bReconfigRequest) { - if(!fe->xine_init(fe, xc.audio_driver, xc.audio_port, - xc.video_driver, - xc.pes_buffers, - xc.post_plugins)) { - LOGMSG("cXinelibLocal: Error initializing frontend"); - break; - } - LOGDBG("cXinelibLocal::Action - fe->xine_init ok"); - m_bReconfigRequest = false; - } - - // open (xine) stream - LOGDBG("cXinelibLocal::Action - xine_open"); - if(!fe->xine_open(fe, NULL)) { - LOGMSG("cXinelibLocal: Error opening xvdr://"); - break; - } - LOGDBG("cXinelibLocal::Action - fe->xine_open ok"); - - // start playing (xine) stream - if(!fe->xine_play(fe)) { - LOGMSG("cXinelibLocal: Error playing xvdr://"); - break; - } - LOGDBG("cXinelibLocal::Action - fe->xine_play ok"); - - m_StreamPos = 0; - Xine_Control("STREAMPOS 0"); - Xine_Control("VERSION " XINELIBOUTPUT_VERSION " " "\r\n"); - } - - // configure frontend and xine - m_bNoVideo = false; - Configure(); - LOGDBG("cXinelibLocal::Action - fe config OK"); - - LogoDisplay(); - LOGDBG("cXinelibLocal::Action - logo sent"); - - { - LOCK_THREAD; - Xine_Control("NOVIDEO 0"); - Xine_Control("LIVE 1"); - Xine_Control("CLEAR"); - m_bNoVideo = false; - m_bLiveMode = true; - m_bReady = true; - } - - // main event loop - LOGDBG("cXinelibLocal:Action - Starting event loop"); - { - LOCK_FE; - while(!GetStopSignal() && m_bReady && - (/*m_bLoopPlay ||*/ !fe->xine_is_finished(fe, 0)) && - fe->fe_run(fe)) - /*cCondWait::SleepMs(50)*/ ; - } - - LOGDBG("cXinelibLocal::Action - event loop terminated, " - "xine_is_finished=%d", fe->xine_is_finished(fe, 0)); - - { - LOCK_THREAD; - m_bReady = false; - m_bEndOfStreamReached = true; - } - - { - LOCK_FE_WR; - if(fe) - fe->xine_close(fe); - fe = NULL; - } - - LOGMSG("cXinelibLocal::Action: Xine closed"); - - if(!m_bReconfigRequest && xc.exit_on_close) { - LOGMSG("Shutting down VDR"); -#if VDRVERSNUM >= 10501 || (defined(PATCH_SHUTDOWN_REWRITE) && PATCH_SHUTDOWN_REWRITE >= 100) - ShutdownHandler.RequestEmergencyExit(); -#else - cThread::EmergencyExit(true); -#endif - break; - } - } - - if(curr_fe) { - curr_fe->xine_exit(fe); - curr_fe->fe_display_close(curr_fe); - curr_fe->fe_free(curr_fe); - } - - m_bIsFinished = true; - LOGMSG("cXinelibLocal::Action: thread finished"); -} - diff --git a/frontend_local.h b/frontend_local.h deleted file mode 100644 index 84dd2ad4..00000000 --- a/frontend_local.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * frontend_local.h: - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: frontend_local.h,v 1.5 2007-04-12 22:53:36 phintuka Exp $ - * - */ - -#ifndef __XINELIB_FRONTEND_LOCAL_H -#define __XINELIB_FRONTEND_LOCAL_H - -#include "frontend.h" - -//----------------------------- cXinelibLocal -------------------------------- - -extern "C" { - typedef struct frontend_s frontend_t; -} - -class cXinelibLocal : public cXinelibThread -{ - - public: - cXinelibLocal(const char *frontend_name); - virtual ~cXinelibLocal(); - - // Thread control - virtual void Stop(void); - - protected: - virtual void Action(void); - - - public: - - // Data transfer - virtual int Play_PES(const uchar *buf, int len); - virtual void OsdCmd(void *cmd); - virtual int64_t GetSTC(); - - // Playback files - virtual bool EndOfStreamReached(void); - - // Image grabbing - virtual uchar *GrabImage(int &Size, bool Jpeg, int Quality, - int SizeX, int SizeY); - - // Configuration - virtual void ConfigureWindow(int fullscreen, int width, int height, - int modeswitch, const char *modeline, - int aspect, int scale_video, int field_order); - virtual void ConfigureDecoder(int pes_buffers); - - protected: - - // Playback control - virtual int Xine_Control(const char *cmd); - - protected: - - // Frontend access - frontend_t *load_frontend(const char *fe_name); - - // Data - void *h_fe_lib; - frontend_t *fe; - cRwLock m_feLock; - bool m_bReconfigRequest; -}; - - -#endif // __XINELIB_FRONTEND_LOCAL_H diff --git a/frontend_svr.c b/frontend_svr.c deleted file mode 100644 index 720106f8..00000000 --- a/frontend_svr.c +++ /dev/null @@ -1,1870 +0,0 @@ -/* - * frontend_svr.c: server for remote frontends - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: frontend_svr.c,v 1.56 2008-04-10 20:21:45 phintuka Exp $ - * - */ - -#define __STDC_FORMAT_MACROS -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "logdefs.h" -#include "config.h" - -#include "xine_input_vdr_net.h" // stream header(s) -#include "xine_osd_command.h" // osd commands - -#include "tools/cxsocket.h" -#include "tools/future.h" -#include "tools/backgroundwriter.h" -#include "tools/udp_pes_scheduler.h" -#include "tools/http.h" -#include "tools/vdrdiscovery.h" -#include "tools/sdp.h" - -#include "frontend_svr.h" -#include "device.h" -#include "osd.h" - -//#define HTTP_OSD - -#define MAX_OSD_TIMEOUTS (25*5) /* max. rate 25 updates/s -> at least 5 seconds */ -#define LOG_OSD_BANDWIDTH (128*1024) /* log messages if OSD bandwidth > 1 Mbit/s */ - -#define PLAYFILE_CTRL_TIMEOUT 300 /* ms */ -#define PLAYFILE_TIMEOUT 5000 /* ms */ - -typedef struct { - int Size; - uchar *Data; -} grab_result_t; - -class cStcFuture : public cFuture {}; -class cReplyFuture : public cFuture, public cListObject {}; -class cGrabReplyFuture : public cFuture, public cListObject {}; -class cCmdFutures : public cHash {}; - - -//----------------------------- cXinelibServer -------------------------------- - -// (control) connection types -enum { - ctDetecting = 0x00, - ctControl = 0x01, - ctHttp = 0x02, - ctRtsp = 0x04, // TCP/RTSP + UDP/RTP - ctRtspMux = 0x08 // TCP: multiplexed RTSP control + RTP/RTCP data/control -}; - -// (data) connection types -enum { - dtPipe = 0x01, - dtTcp = 0x02, - dtUdp = 0x04, - dtRtp = 0x08, - dtHttp = 0x10, - dtRtspMux = 0x20, -}; - -// (data) connection properties -#define DATA_STREAM(dt) ((dt) & (dtPipe | dtTcp | dtHttp | dtRtspMux)) -#define DATA_DATAGRAM(dt) ((dt) & (dtUdp | dtRtp)) -#define DATA_NOPOLL(dt) ((dt) & (dtHttp | dtRtspMux)) -#define DATA_NOCONTROL(dt) ((dt) & (dtHttp | dtRtspMux)) - -cXinelibServer::cXinelibServer(int listen_port) : - cXinelibThread("Remote decoder/display server (cXinelibServer)") -{ - int i; - for(i=0; iClear(); - - if(m_Scheduler) - m_Scheduler->Clear(); - - cXinelibThread::Clear(); -} - -void cXinelibServer::CloseDataConnection(int cli) -{ - if(m_bUdp[cli] && fd_data[cli]>=0) - m_Scheduler->RemoveHandle(fd_data[cli]); - - CLOSESOCKET(fd_data[cli]); - - if(m_Writer[cli]) { - delete m_Writer[cli]; - m_Writer[cli] = NULL; - } - - m_bUdp[cli] = false; - m_bMulticast[cli] = false; - m_bConfigOk[cli] = false; - - m_iUdpFlowMask &= ~(1<RemoveRtp(); -} - -void cXinelibServer::CloseConnection(int cli) -{ - CloseDataConnection(cli); - if(fd_control[cli].open()) { - LOGMSG("Closing connection %d", cli); - fd_control[cli].close(); - if(m_State[cli]) { - delete m_State[cli]; - m_State[cli] = NULL; - } - cXinelibDevice::Instance().ForcePrimaryDevice(false); - } -} - -static int recompress_osd_net(uint8_t *raw, xine_rle_elem_t *data, int elems) -{ - uint8_t *raw0 = raw; - for(int i=0; i= 0x80) { - *(raw++) = (len>>8) | 0x80; - *(raw++) = (len & 0xff); - } else { - *(raw++) = (len & 0x7f); - } - *(raw++) = color; - } - return (raw-raw0); -} - -static int write_osd_command(cxSocket& s, osd_command_t *cmd) -{ - cxPoller p(s, true); - if(!p.Poll(100)) { - LOGMSG("write_osd_command: poll failed, OSD send skipped"); - return 0; - } - - ssize_t max = s.tx_buffer_free(); - ssize_t size = (ssize_t)8 + - (ssize_t)(sizeof(osd_command_t)) + - (ssize_t)(sizeof(xine_clut_t) * ntohl(cmd->colors)) + - (ssize_t)(ntohl(cmd->datalen)); - - if(max > 0 && max < size) { -/* #warning TODO: buffer latest failed OSD and retry - -> skipped OSDs can be left out but - latest will be always delivered */ - LOGMSG("write_osd_command: socket buffer full, OSD send skipped (got %d ; need %d", - (int)max, (int)size); - return 0; - } - - if(8 != s.write("OSDCMD\r\n", 8, 100)) { - LOGDBG("write_osd_command: write (command) failed"); - return -1; - } - if((ssize_t)sizeof(osd_command_t) != - s.write(cmd, sizeof(osd_command_t), 100)) { - LOGDBG("write_osd_command: write (data) failed"); - return -1; - } - if(cmd->palette && cmd->colors && - (ssize_t)(sizeof(xine_clut_t)*ntohl(cmd->colors)) != - s.write(cmd->palette, sizeof(xine_clut_t)*ntohl(cmd->colors), 100)) { - LOGDBG("write_osd_command: write (palette) failed"); - return -1; - } - if(cmd->data && cmd->datalen && - (ssize_t)ntohl(cmd->datalen) != s.write(cmd->data, ntohl(cmd->datalen), 300)) { - LOGDBG("write_osd_command: write (bitmap) failed"); - return -1; - } - return 1; -} - -#ifdef HTTP_OSD -#include "dvdauthor/rgb.h" -#include "dvdauthor/subgen-encode.c" -#include "dvdauthor/subgen.c" -#include "dvdauthor/subgen-image.c" -//subgen-image: palette generation, image divided to buttons --> 16-col palette -static uint8_t *dvdspu_encode(osd_command_t *cmd, int *spulen) -{ -#if 0 - stinfo st; - st.x0 = cmd->x; - st.y0 = cmd->y; - st.xd = cmd->w; - st.yd = cmd->h; - - st.spts = 0; /* start pts */ - st.sd = 0; /* duration */ - st.forced = 0; - st.numbuttons = 0; - st.numpal = 0; - - st.autooutline = 0; /* -> 1 -> imgfix calls detectbuttons(s); */ - st.outlinewidth = 0; - st.autoorder = 0; - - st.img =; /* img */ - st.hlt =; /* img */ - st.sel =; /* img */ - st.fimg = NULL; - - st.pal[4] = ; /* palt */ - st.masterpal[16] = ; /* palt */ - st.transparentc = ; /* palt */ - - st.numgroups = ; - st.groupmap[3][4] = ; - st.buttons = ; /* button * */ - - if(imgfix(&st)) - dvd_encode(&st); -#endif - return NULL; - -} -#endif - -void cXinelibServer::OsdCmd(void *cmd_gen) -{ - TRACEF("cXinelibServer::OsdCmd"); - int i; - - LOCK_THREAD; - - // check if there are any clients - if(!HasClients()) - return; - - if(cmd_gen) { - osd_command_t *cmd = (osd_command_t*)cmd_gen; - osd_command_t cmdnet; - memcpy(&cmdnet, cmd, sizeof(osd_command_t)); - if (cmd->data) { - cmdnet.raw_data = (uint8_t *)malloc(cmd->datalen); - cmdnet.datalen = recompress_osd_net(cmdnet.raw_data, cmd->data, cmd->num_rle); - } - // -> network byte order - hton_osdcmd(cmdnet); - -#ifdef HTTP_OSD - uint8_t *spudata = NULL; - int spulen = 0; -#endif - - for(i = 0; i < MAXCLIENTS; i++) { - if(fd_control[i].open()) { - int r = write_osd_command(fd_control[i], &cmdnet); - if(r < 0) { - LOGMSG("Send OSD command failed, closing connection"); - CloseConnection(i); - } else if(r == 0) { - if(m_OsdTimeouts[i]++ > MAX_OSD_TIMEOUTS) { - LOGMSG("Too many OSD timeouts, dropping client"); - CloseConnection(i); - } - } else { - m_OsdTimeouts[i] = 0; - } - } -#ifdef HTTP_OSD - if(m_ConnType[i] == ctHttp) { - if(m_Writer[i]) { - if(!spudata) - spudata = dvdspu_encode(cmd, &spulen); - if(spudata) - m_Writer[i]->Put(-1, spudata, spulen); - } - } -#endif - } - -#ifdef HTTP_OSD - free(spudata); -#endif - - free(cmdnet.data); - -#ifdef LOG_OSD_BANDWIDTH - { - static int64_t timer = 0LL; - static int bytes = 0; - int64_t now = cTimeMs::Now(); - - if(timer + 5000LL < now) { - timer = now; - bytes = 0; - } else if(timer + 1000LL < now) { - bytes = bytes / (((int)(now - timer)) / 1000); - if(bytes > LOG_OSD_BANDWIDTH) - LOGMSG("OSD bandwidth: %d bytes/s (%d kbit/s)", bytes, bytes*8/1024); - timer = now; - bytes = 0; - } - bytes += sizeof(osd_command_t) + ntohl(cmdnet.datalen); - } -#endif - } -} - -int64_t cXinelibServer::GetSTC(void) -{ - Lock(); - - // check if there are any clients - if(!HasClients()) { - Unlock(); - return -1ULL; - } - - // Query client(s) - m_StcFuture->Reset(); - Xine_Control("GETSTC"); - - Unlock(); - - if(! m_StcFuture->Wait(200)) { - LOGMSG("cXinelibServer::GetSTC timeout (200ms)"); - return -1ULL; - } - - //if(delay.Elapsed() > 0 && !is_Paused) - // LOGMSG("GetSTC: compensating network delay by %s ticks (ms)\n", - // delay.Elapsed()*90000/2, delay.Elapsed()/2); - - return m_StcFuture->Value() /*+ (delay.Elapsed()*90000/2*/; -} - -int cXinelibServer::Play_PES(const uchar *data, int len) -{ - int TcpClients = 0, UdpClients = 0, RtpClients = 0; - - LOCK_THREAD; // Lock control thread out - - for(int i=0; i= 0) || - m_ConnType[i] & (ctHttp|ctRtsp)) { - - if(m_bUdp[i]) { - - UdpClients++; - - } else if(m_Writer[i]) { - - int result = m_Writer[i]->Put(m_StreamPos, data, len); - if(!result) { - LOGMSG("cXinelibServer::Play_PES Write/Queue error (TCP/PIPE)"); - CloseConnection(i); - } else if(result<0) { - LOGMSG("cXinelibServer::Play_PES Buffer overflow (TCP/PIPE)"); - if(m_ConnType[i] == ctHttp) - m_Writer[i]->Clear(); - } - - TcpClients++; - } - } - } - } - - RtpClients = (m_iMulticastMask || xc.remote_rtp_always_on); - - if(UdpClients || RtpClients) - if(! m_Scheduler->Queue(m_StreamPos, data, len)) - LOGMSG("cXinelibServer::Play_PES Buffer overflow (UDP/RTP)"); - - if(TcpClients || UdpClients || RtpClients) - cXinelibThread::Play_PES(data, len); - - return len; -} - -void cXinelibServer::SetHDMode(bool On) -{ - cXinelibThread::SetHDMode(On); -#if 0 - /*#warning TODO*/ - LOCK_THREAD; - - int i; - for(i=0; iSetBuffer(On ? 2048 : 512); - m_Scheduler->SetWindow(On ? 512 : 128); -#endif -} - -int cXinelibServer::Poll(cPoller &Poller, int TimeoutMs) -{ - // in live mode transponder clock is the master ... - // in replay mode local frontend (if present) is master - if(m_bLiveMode || (*xc.local_frontend && strncmp(xc.local_frontend, "none", 4))) { - if(m_Scheduler->Clients()) - return m_Scheduler->Poll(TimeoutMs, m_Master = false); - return DEFAULT_POLL_SIZE; - } - - // replay mode: - do { - Lock(); - m_Master = true; - int Free = 0xfffff, FreeHttp = 0xfffff, FreeUdp = 0; - int Clients = 0, Http = 0, Udp = 0; - for(int i=0; iFree()); - else if(m_bUdp[i]) - Udp++; - Clients++; - } else if(m_ConnType[i] & (ctHttp|ctRtspMux)) { - if(m_Writer[i]) { - FreeHttp = min(FreeHttp, m_Writer[i]->Free()); - Http++; - } - } - } - } - if(m_iMulticastMask) { - Clients++; - Udp++; - } - - /* select master timing source for replay mode */ - int master = -1; - if(Clients && !Udp) { - for(int i=0; i= 0) - Xine_Control("MASTER 0"); - if(master >= 0) - fd_control[master].write_cmd("MASTER 1\r\n"); - m_MasterCli = master; - } - - Unlock(); - - if(!Clients && !Http) { - // live mode runs even if there are no clients - if(m_bLiveMode) - return DEFAULT_POLL_SIZE; - // replay is paused when no clients - if(TimeoutMs>0) - cCondWait::SleepMs(TimeoutMs); - return 0; - } - - // in replay mode cUdpScheduler is master timing source - if( Free < 8128 || - ((FreeUdp = m_Scheduler->Poll(TimeoutMs, true)) < 1) || - (!Clients && FreeHttp < 8128)) { - - if(TimeoutMs > 0) - cCondWait::SleepMs(min(TimeoutMs, 5)); - TimeoutMs -= 5; - - } else { - Free = min(Free, FreeHttp) / 2070; - Free = min(Free, FreeUdp); - return max(0, Free); - } - - } while(TimeoutMs > 0); - - return 0; -} - -bool cXinelibServer::Flush(int TimeoutMs) -{ - int result = true; - - if(m_Scheduler) - result = m_Scheduler->Flush(TimeoutMs) && result; - - for(int i=0; i=0 && m_Writer[i]) - result = m_Writer[i]->Flush(TimeoutMs) && result; - - if(TimeoutMs > 50) - TimeoutMs = 50; - - if(result) { - cString tmp = cString::sprintf("FLUSH %d %" PRIu64 " %d", - TimeoutMs, m_StreamPos, m_Frames); - result = (PlayFileCtrl(tmp)) <= 0 && result; - } - - return result; -} - -int cXinelibServer::Xine_Control(const char *cmd) -{ - TRACEF("cXinelibServer::Xine_Control"); - - if(cmd && *cmd) { - char buf[4096]; - int len = snprintf(buf, sizeof(buf), "%s\r\n", cmd); - if(len >= (int)sizeof(buf)) { - LOGMSG("Xine_Control: command truncated !"); - //len = sizeof(buf); - return 0; - } - - LOCK_THREAD; - - for(int i=0; i=0 || m_bMulticast[i]) && m_bConfigOk[i]) - if(len != fd_control[i].write(buf, len, 100)) { - LOGMSG("Control send failed (%s), dropping client", cmd); - CloseConnection(i); - } - } - - return 1; -} - -int cXinelibServer::Xine_Control_Sync(const char *cmd) -{ - TRACEF("cXinelibServer::Xine_Control_Sync"); - - if(cmd && *cmd) { - int i, len, UdpClients = 0, RtpClients = 0; - char buf[256]; - - len = snprintf(buf, sizeof(buf), "%s\r\n", cmd) + 1; - if(len >= (int)sizeof(buf)) { - LOGMSG("Xine_Control_Sync: command truncated ! (%s)", cmd); - len = sizeof(buf); - } - - LOCK_THREAD; - - for(i=0; i= 0) { - if(m_bUdp[i]) - UdpClients++; - else if(m_Writer[i]) - m_Writer[i]->Put((uint64_t)(-1ULL), (const uchar*)buf, len); - } - } - - RtpClients = (m_iMulticastMask || xc.remote_rtp_always_on); - - if(UdpClients || RtpClients) - if(! m_Scheduler->Queue((uint64_t)(-1ULL), (const uchar*)buf, len)) - LOGMSG("cXinelibServer::Xine_Control_Sync overflow (UDP/RTP)"); - } - - return 1; -} - -void cXinelibServer::TrickSpeed(int Speed) -{ - if(Speed == 0) { - m_Scheduler->Pause(true); - } else { - m_Scheduler->Pause(false); - m_Scheduler->TrickSpeed(Speed == -1 ? 1 : Speed); - } - - cXinelibThread::TrickSpeed(Speed); -} - -bool cXinelibServer::EndOfStreamReached(void) -{ - LOCK_THREAD; - - /* Check if there are any clients */ - if(!HasClients()) - return true; - - return cXinelibThread::EndOfStreamReached(); -} - -int cXinelibServer::AllocToken(void) -{ - LOCK_THREAD; - - m_Token = (m_Token+1) & 0xffff; - - cXinelibThread::Xine_Control((const char *)"TOKEN", m_Token); - - return m_Token; -} - -bool cXinelibServer::HasClients(void) -{ - LOCK_THREAD; - - int i; - for(i=0; iAdd(&future, token); - - /* Send actual command */ - cXinelibThread::PlayFileCtrl(Cmd); - - Unlock(); - - /* When server thread get REPLY %d %d (first %d == token, second returned value) - * it sets corresponding future (by token; if found) in list - * and removes it from list. - */ - -#ifdef XINELIBOUTPUT_DEBUG - int64_t t = cTimeMs::Now(); -#endif - - int timeout = bPlayfile ? PLAYFILE_TIMEOUT : PLAYFILE_CTRL_TIMEOUT; - - future.Wait(timeout); - - Lock(); - m_Futures->Del(&future, token); - Unlock(); - - if(!future.IsReady()) { - LOGMSG("cXinelibServer::PlayFileCtrl: Timeout (%s , %d ms) %d", Cmd, timeout, token); - return -1; - } - - TRACE("cXinelibServer::PlayFileCtrl("< 0xffff) { - CLOSESOCKET(fd_listen); - CLOSESOCKET(fd_discovery); - if(m_Scheduler) - m_Scheduler->RemoveRtp(); - cHttpStreamer::CloseAll(); - LOGMSG("Not listening for remote connections"); - return false; - } - - if(fd_listen<0 || listen_port != m_Port) { - m_Port = listen_port; - CLOSESOCKET(fd_listen); - - int iReuse = 1; - struct sockaddr_in name; - name.sin_family = AF_INET; - name.sin_addr.s_addr = htonl(INADDR_ANY); - name.sin_port = htons(m_Port); - - if(xc.remote_local_ip[0]) { - uint32_t ip = inet_addr(xc.remote_local_ip); - if(ip != INADDR_NONE) { - char txt[128]; - name.sin_addr.s_addr = ip; - LOGDBG("Binding server to %s", cxSocket::ip2txt(name.sin_addr.s_addr, htons(m_Port), txt)); - } else { - LOGERR("Local interface address %s is invalid !", xc.remote_local_ip); - } - } - fd_listen = socket(PF_INET,SOCK_STREAM,0); - setsockopt(fd_listen, SOL_SOCKET, SO_REUSEADDR, &iReuse, sizeof(int)); - - if (bind(fd_listen, (struct sockaddr *)&name, sizeof(name)) < 0) { - LOGERR("cXinelibServer: bind error %s port %d: %s", - xc.remote_local_ip[0] ? xc.remote_local_ip : "", - m_Port, strerror(errno)); - CLOSESOCKET(fd_listen); - } else if(listen(fd_listen, MAXCLIENTS)) { - LOGERR("cXinelibServer: listen error (port %d): %s", - m_Port, strerror(errno)); - CLOSESOCKET(fd_listen); - } else { - LOGMSG("Listening on port %d", m_Port); - result = true; - } - } else { - result = true; - } - - // set listen for discovery messages - CLOSESOCKET(fd_discovery); - if(xc.remote_usebcast) { - fd_discovery = udp_discovery_init(); - if(udp_discovery_broadcast(fd_discovery, m_Port, xc.remote_local_ip) < 0) - CLOSESOCKET(fd_discovery); - else - LOGMSG("Listening for UDP broadcasts on port %d", m_Port); - } - - // set up multicast sockets - - if(m_Scheduler) - m_Scheduler->RemoveRtp(); - - if(xc.remote_usertp) { - if(xc.remote_rtp_always_on) - LOGMSG("WARNING: RTP Configuration: transmission is always on !"); - if(xc.remote_rtp_always_on || m_iMulticastMask) - m_Scheduler->AddRtp(); - } - - return result; -} - -uchar *cXinelibServer::GrabImage(int &Size, bool Jpeg, - int Quality, int SizeX, int SizeY) -{ - cGrabReplyFuture future; - uchar *result = NULL; - cString cmd; - - cmd = cString::sprintf("GRAB %s %d %d %d\r\n", - Jpeg ? "JPEG" : "PNM", - Quality, SizeX, SizeY); - - Lock(); - - /* Check if there are any clients */ - if(!HasClients()) { - Unlock(); - return NULL; - } - - int token = AllocToken(); - m_Futures->Add(&future, token); - - // might be better to request iamge from one client only (?) - Xine_Control(cmd); - - Unlock(); - - if(future.Wait(5000)) { - grab_result_t r = future.Value(); - if((Size = r.Size) > 0) { - LOGDBG("cXinelibServer::GrabImage: image size is %d bytes", Size); - result = r.Data; - } else { - LOGMSG("cXinelibServer::Grab: Grab failed (%d)", Size); - } - } else { - LOGMSG("cXinelibServer::Grab: Timeout (5000 ms)"); - } - - Lock(); - m_Futures->Del(&future, token); - Unlock(); - - return result; -} - -// -// (Client) Control message handling -// - -#define CREATE_NEW_WRITER \ - if(m_Writer[cli]) \ - delete m_Writer[cli]; \ - m_Writer[cli] = new cTcpWriter(fd); - -void cXinelibServer::Handle_Control_PIPE(int cli, const char *arg) -{ - LOGDBG("Trying PIPE connection ..."); - - CloseDataConnection(cli); - - // - // TODO: client should create pipe; waiting here is not good thing ... - // - - if(!xc.remote_usepipe) { - LOGMSG("PIPE transport disabled in configuration"); - fd_control[cli].write_cmd("PIPE: Pipe transport disabled in config.\r\n"); - return; - } - - MakeDirs(m_PipesDir, true); - - int i; - cString pipeName; - for(i=0; i<10; i++) { - pipeName = cString::sprintf("%s/pipe.%d", *m_PipesDir, i); - if(mknod(pipeName, 0644|S_IFIFO, 0) < 0) { - unlink(pipeName); - continue; - } - else - break; - } - if(i>=10) { - LOGERR("Pipe creation failed (%s)", *pipeName); - RemoveFileOrDir(m_PipesDir, false); - fd_control[cli].write_cmd("PIPE: Pipe creation failed.\r\n"); - return; - } - - fd_control[cli].printf("PIPE %s\r\n", *pipeName); - - cxPoller poller(fd_control[cli]); - poller.Poll(500); /* quite short time ... */ - - int fd; - if((fd = open(pipeName, O_WRONLY|O_NONBLOCK)) < 0) { - LOGDBG("Pipe not opened by client"); - /*write_cmd(fd_control[cli], "PIPE NONE\r\n");*/ - unlink(pipeName); - RemoveFileOrDir(m_PipesDir, false); - return; - } - - fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)|O_NONBLOCK); - - //LOGDBG("cXinelibServer::Handle_Control: pipe %s open", pipeName); - - unlink(pipeName); /* safe to remove now, both ends are open or closed. */ - RemoveFileOrDir(m_PipesDir, false); - fd_control[cli].write_cmd("PIPE OK\r\n"); - - CREATE_NEW_WRITER; - - fd_data[cli] = fd; -} - - -void cXinelibServer::Handle_Control_DATA(int cli, const char *arg) -{ - int clientId = -1; - unsigned int ipc, portc; - - LOGDBG("Data connection (TCP) requested"); - - CloseDataConnection(cli); - - if(!xc.remote_usetcp) { - LOGMSG("TCP transports disabled in configuration"); - fd_control[cli].write_cmd("TCP: TCP transport disabled in config.\r\n"); - CloseConnection(cli); /* actually closes the new data connection */ - return; - } - - /* validate client ID */ - if(3 != sscanf(arg, "%d 0x%x:%d", &clientId, &ipc, &portc) || - clientId < 0 || - clientId >= MAXCLIENTS || - !fd_control[clientId].open()) { - fd_control[cli].write_cmd("TCP: Error in request (ClientId).\r\n"); - LOGDBG("Invalid data connection (TCP) request"); - /* close only new data connection, no control connection */ - CloseConnection(cli); - return; - } - - /* check client IP's */ - struct sockaddr_in sinc, sind; - socklen_t len = sizeof(sinc); - sinc.sin_addr.s_addr = 0; - sind.sin_addr.s_addr = ~0; - fd_control[cli].getpeername((struct sockaddr *)&sind, &len); - fd_control[clientId].getpeername((struct sockaddr *)&sinc, &len); - if(sinc.sin_addr.s_addr != sind.sin_addr.s_addr) { - fd_control[cli].write_cmd("TCP: Error in request (IP does not match).\r\n"); - LOGMSG("Invalid data connection (TCP) request: IP does not match: ctrl %x, data %x", - (unsigned int)sinc.sin_addr.s_addr, (unsigned int)sind.sin_addr.s_addr); - CloseConnection(cli); - return; - } - if(htonl(ipc) != sinc.sin_addr.s_addr || htons(portc) != sinc.sin_port) { - fd_control[cli].write_cmd("TCP: Error in request (invalid IP:port).\r\n"); - LOGMSG("Invalid data connection (TCP) request: control IP:port does not match" - "control: %x:%d client: %x:%d", - (unsigned int)sinc.sin_addr.s_addr, (unsigned int)sinc.sin_port, - (unsigned int)htonl(ipc), (unsigned int)htons(portc)); - CloseConnection(cli); - return; - } - - /* close old data connection */ - CloseDataConnection(clientId); - - /* change connection type */ - - fd_control[cli].write_cmd("DATA\r\n"); - fd_data[clientId] = fd_control[cli].handle(true); - - cli = clientId; - - if(m_Writer[cli]) - delete m_Writer[cli]; - m_Writer[cli] = new cTcpWriter(fd_data[cli]); - - /* not anymore control connection, so dec primary device reference counter */ - cXinelibDevice::Instance().ForcePrimaryDevice(false); -} - -void cXinelibServer::Handle_Control_RTP(int cli, const char *arg) -{ - LOGDBG("Trying RTP connection ..."); - - CloseDataConnection(cli); - - if(!xc.remote_usertp) { - fd_control[cli].write_cmd("RTP: RTP transport disabled in configuration.\r\n"); - LOGMSG("RTP transports disabled"); - return; - } - - fd_control[cli].printf("RTP %s:%d\r\n", xc.remote_rtp_addr, xc.remote_rtp_port); - - if(!m_iMulticastMask && !xc.remote_rtp_always_on) - m_Scheduler->AddRtp(); - - m_bMulticast[cli] = true; - m_iMulticastMask |= (1<AddHandle(fd); -} - -void cXinelibServer::Handle_Control_KEY(int cli, const char *arg) -{ - TRACE("cXinelibServer received KEY " << buf); - - if(!xc.remote_keyboard) { - LOGMSG("Handle_Control_KEY(%s): Remote keyboard disabled in config", arg); - return; - } - - char buf[256], *pt, *key; - bool repeat = false, release = false; - strn0cpy(buf, arg, sizeof(buf)); - - int n = strlen(buf)-1; - while(n && buf[n]==' ') buf[n--]=0; /* trailing spaces */ - if(NULL != (key=strchr(buf, ' '))) { - while(*key == ' ') - *(key++) = 0; - if(NULL != (pt = strchr(key, ' '))) { - *(pt++) = 0; - if(strstr(pt, "Repeat")) - repeat = true; - if(strstr(pt, "Release")) - release = true; - } - cXinelibThread::KeypressHandler(buf, key, repeat, release); - } else { - cXinelibThread::KeypressHandler(NULL, buf, repeat, release); - } -} - -void cXinelibServer::Handle_Control_CONFIG(int cli) -{ - m_bConfigOk[cli] = true; - - fd_control[cli].set_nodelay(true); - - fd_control[cli].printf("NOVIDEO %d\r\nLIVE %d\r\n", - m_bNoVideo?1:0, m_bLiveMode?1:0); - - SetVolume(m_Volume); - - Configure(); - - fd_control[cli].write_cmd("CLEAR\r\n"); - - if(m_bPlayingFile && *m_FileName) { - Unlock(); - int pos = cXinelibDevice::Instance().PlayFileCtrl("GETPOS"); - Lock(); - if(m_bPlayingFile && *m_FileName) { - fd_control[cli].printf("PLAYFILE %d %s %s\r\n", - (pos>0?pos/1000:0), xc.audio_visualization, *m_FileName); - } - } - - cXinelibOsdProvider::RefreshOsd(); -} - -void cXinelibServer::Handle_Control_UDP_RESEND(int cli, const char *arg) -{ - unsigned int seq1, seq2; - uint64_t pos; - - if( (!fd_data[cli] || !m_bUdp[cli]) && - (!m_bMulticast[cli])) { - LOGMSG("Got invalid re-send request: no udp/rtp in use"); - return; - } - - if(3 == sscanf(arg, "%d-%d %" PRIu64, &seq1, &seq2, &pos)) { - - if(seq1 <= UDP_SEQ_MASK && seq2 <= UDP_SEQ_MASK && pos <= m_StreamPos) { - - if(fd_data[cli] >= 0) - m_Scheduler->ReSend(fd_data[cli], pos, seq1, seq2); - else - m_Scheduler->ReSend(-1, pos, seq1, seq2); - } else { - LOGMSG("Invalid re-send request: %s (send pos=%" PRIu64 ")", - arg, m_StreamPos); - } - } else { - LOGMSG("Invalid re-send request: %s (send pos=%" PRIu64 ")", - arg, m_StreamPos); - } -} - -void cXinelibServer::Handle_Control_GRAB(int cli, const char *arg) -{ - cGrabReplyFuture *f; - int token = -1, size = 0; - if(2 == sscanf(arg, "%d %d", &token, &size)) { - if(size > 0) { - uchar *result = (uchar*)malloc(size); - Unlock(); /* may take a while ... */ - ssize_t n = fd_control[cli].read(result, size, 1000); - Lock(); - if(n == size) { - if(NULL != (f = (cGrabReplyFuture*)m_Futures->Get(token))) { - grab_result_t r; - r.Size = size; - r.Data = result; - m_Futures->Del(f, token); - f->Set(r); - result = NULL; - } else { - LOGMSG("cXinelibServer: Grab image discarded"); - } - } else { - LOGMSG("cXinelibServer: Grab result read() failed"); - CloseConnection(cli); - } - free(result); - } else if(NULL != (f = (cGrabReplyFuture*)m_Futures->Get(token))) { - grab_result_t r; - r.Size = 0; - r.Data = NULL; - m_Futures->Del(f, token); - f->Set(r); - } - } -} - -void cXinelibServer::Handle_Control_CONTROL(int cli, const char *arg) -{ - fd_control[cli].printf("VDR-" VDRVERSION " " - "xineliboutput-" XINELIBOUTPUT_VERSION " " - "READY\r\nCLIENT-ID %d\r\n", cli); - m_ConnType[cli] = ctControl; -} - -static int strcmp_escaped(const char *s1, const char *s2) -{ - if(!strncmp(s1, "file:", 5)) - s1 += 5; - - while(*s1 && *s2) { - int c1 = *s1; - int c2 = *s2; - if(c1 == '%' && s1[1] && s1[2] && 1 == sscanf(s1+1, "%02x", &c1)) s1 += 2; - if(c2 == '%' && s2[1] && s2[2] && 1 == sscanf(s2+1, "%02x", &c2)) s2 += 2; - if(c1 < c2) return -1; - if(c1 > c2) return 1; - s1++; s2++; - } - return *s1 ? -1 : *s2 ? 1 : 0; -} - -void cXinelibServer::Handle_Control_HTTP(int cli, const char *arg) -{ - // Parse request - if(m_ConnType[cli] == ctDetecting || !m_State[cli]) { - LOGDBG("HTTP request: %s", arg); - - DELETENULL(m_Writer[cli]); - DELETENULL(m_State[cli]); - - m_State[cli] = new cConnState; - if( !m_State[cli]->SetCommand(arg) || - strncmp(m_State[cli]->Version(), "HTTP/1.", 7) || - strcmp(m_State[cli]->Name(), "GET")) { - LOGMSG("invalid HTTP request: %s", arg); - CloseConnection(cli); - return; - } - m_ConnType[cli] = ctHttp; - return; - } - - // Handle request - else if(m_ConnType[cli] == ctHttp) { - LOGDBG("HTTP(%d): %s", cli, arg); - - // Collect headers - if(*arg) { - m_State[cli]->AddHeader(arg); - return; - } - - LOGMSG("HTTP Request complete"); - - // - // primary device output (PES) - // - if(!strcmp(m_State[cli]->Uri(), "/")) { - LOGMSG("HTTP streaming primary device feed"); - fd_control[cli].write_cmd(HTTP_REPLY_200_PRIMARY); -#if 0 - // pack header (scr 0, mux rate 0x6270) - fd_control[cli].write( - "\x00\x00\x01\xba" - "\x44\x00\x04\x00" "\x04\x01\x01\x89" "\xc3\xf8", 14); - // system header (streams C0, E0, BD, BF) - fd_control[cli].write( - "\x00\x00\x01\xbb" "\x00\x12" - "\x80\xc4\xe1" "\x00\xe1" "\x7f" - "\xb9\xe0\xe8" "\xb8\xc0\x20" "\xbd\xe0\x3a" "\xbf\xe0\x02", 24); -#endif - m_Writer[cli] = new cRawWriter(fd_control[cli].handle(), KILOBYTE(1024)); - - DELETENULL(m_State[cli]); - return; - } - -#if 0 - // - // primary device output (TS) - // - if(!strcmp(m_State[cli]->Uri(), "/TS")) { - LOGMSG("HTTP streaming primary device feed (TS)"); - fd_control[cli].write_cmd(HTTP_REPLY_200_PRIMARY_TS); - m_Writer[cli] = new cTsWriter(fd_control[cli].handle(), KILOBYTE(1024)); - DELETENULL(m_State[cli]); - return; - } -#endif - -#if 0 /* for testing */ - else if(!strcmp(m_State[cli]->Uri(), "/test.avi")) { - LOGMSG("HTTP streaming test file"); - - // detach socket - new cHttpStreamer(fd_control[cli].handle(true), "/tmp/test.avi", m_State[cli]); - m_State[cli] = NULL; - CloseConnection(cli); - return; - } -#endif - - // - // currently playing media file - // - else if(!strncmp(m_State[cli]->Uri(), "/PLAYFILE", 9)) { - - if( *m_FileName && m_bPlayingFile) { - char *pos = strstr(m_FileName, "#subtitle:"); - if(pos) *pos = 0; - bool Allow = ( !strcmp_escaped(m_FileName, m_State[cli]->Uri() + 9) - || (pos && !strcmp_escaped(pos + 10, m_State[cli]->Uri() + 9))); - if(pos) *pos = '#'; - if(Allow) { - LOGMSG("HTTP streaming media file"); - - // detach socket - new cHttpStreamer(fd_control[cli].handle(true), m_State[cli]->Uri() + 9, m_State[cli]); - m_State[cli] = NULL; - CloseConnection(cli); - return; - } - LOGDBG("HTTP Unauthorized request: %s", *m_State[cli]->Uri()); - } - else - LOGDBG("No currently playing file"); - } - - // - // nothing else will be served ... - // - LOGMSG("Rejected HTTP request for \'%s\'", *m_State[cli]->Uri()); - fd_control[cli].write_cmd(HTTP_REPLY_404); - LOGDBG("HTTP Reply: HTTP/1.1 404 Not Found"); - CloseConnection(cli); - } -} - -#define RTSP_200_OK "RTSP/1.0 200 OK\r\n" \ - "CSeq: %d\r\n" -#define RTSP_415 "RTSP/1.0 415 Unsupported media type\r\n" \ - "CSeq: %d\r\n" RTSP_FIN -#define RTSP_461 "RTSP/1.0 461 Unsupported transport\r\n" \ - "CSeq: %d\r\n" RTSP_FIN -#define RTSP_501 "RTSP/1.0 501 Not implemented\r\n" \ - "CSeq: %d\r\n" RTSP_FIN -#define RTSP_FIN "\r\n", CSeq - -#define RTSPOUT(x...) do { fd_control[cli].printf(x); LOGMSG("RTSP TX:" x); } while(0) -//#define RTSPOUT(x...) fd_control[cli].printf_cmd(x) - -void cXinelibServer::Handle_Control_RTSP(int cli, const char *arg) -{ - // - // Minimal RTSP (RFC 2326) server implementation - // - - - // - // collect request and headers - // - if(m_ConnType[cli] == ctDetecting || !m_State[cli]) { - LOGDBG("RTSP request: %s", arg); - - DELETENULL(m_State[cli]); - m_State[cli] = new cConnState; - - if( !m_State[cli]->SetCommand(arg) || - strcmp(m_State[cli]->Version(), "RTSP/1.0")) { - LOGMSG("invalid RTSP request: %s", arg); - CloseConnection(cli); - return; - } - m_ConnType[cli] = ctRtsp; - return; - } - - // - // Process complete request - // - else if(m_ConnType[cli] == ctRtsp) { - LOGDBG("RTSP(%d): %s", cli, arg); - - if(*arg) { - m_State[cli]->AddHeader(arg); - return; - } - - cHeader *cseq = m_State[cli]->Header("CSeq"); - int CSeq = cseq ? cseq->IntValue() : -1; - LOGMSG("RTSP Request complete (cseq %d)", CSeq); - - // - // OPTIONS rtsp://127.0.0.1:37890 RTSP/1.0 - // CSeq: 1 - // - if(!strcmp(m_State[cli]->Name(), "OPTIONS")) { - RTSPOUT(RTSP_200_OK - "Public: DESCRIBE, SETUP, TEARDOWN, PLAY\r\n" - RTSP_FIN); - } // OPTIONS - - // - // DESCRIBE rtsp://127.0.0.1:37890 RTSP/1.0 - // CSeq: 2 - // Accept: application/sdp - // - else if(!strcmp(m_State[cli]->Name(), "DESCRIBE")) { - cHeader *accept = m_State[cli]->Header("Accept"); - if(accept && strstr(accept->Value(), "application/sdp")) { - struct sockaddr_in sin; - socklen_t len = sizeof(sin); - char buf[64]; - fd_control[cli].getsockname((struct sockaddr *)&sin, &len); - const char *sdp_descr = vdr_sdp_description(cxSocket::ip2txt(sin.sin_addr.s_addr, - sin.sin_port, buf), - 2001, - xc.listen_port, - xc.remote_rtp_addr, - /*m_ssrc*/0x4df73452, - xc.remote_rtp_port, - xc.remote_rtp_ttl); - int sdplen = sdp_descr ? strlen(sdp_descr) : 0; - RTSPOUT(RTSP_200_OK - "Content-Type: application/sdp\r\n" - "Content-Length: %d\r\n" - "\r\n", - CSeq, sdplen); - fd_control[cli].write_cmd(sdp_descr, sdplen); - } else { - RTSPOUT(RTSP_415 /*UNSUPPORTED_MEDIATYPE*/); - } - } // DESCRIBE - - // - // SETUP rtsp://127.0.0.1:37890/ RTSP/1.0 - // CSeq: 15 - // Transport: RTP/AVP;unicast;client_port=37890-37891 - // User-Agent: VLC media player (LIVE555 Streaming Media v2005.11.10) - // - else if(!strcmp(m_State[cli]->Name(), "SETUP")) { - cHeader *transport = m_State[cli]->Header("Transport"); - int urtp=0, mrtp=0, tcp=0; - if(transport && - ( (strstr(transport->Value(), "RTP/AVP;multicast") && (mrtp=1)) || - (strstr(transport->Value(), "RTP/AVP;unicast") && (urtp=1)) || - (strstr(transport->Value(), "RTP/AVP;interleaved") && (tcp=1)))) { - //if(!mrtp) - // sprintf(buf, "RTSP/1.0 461 Unsupported transport\r\n" RTSP_H_CSEQ RTSP_OK_FIN); - //else - RTSPOUT(RTSP_200_OK - "Session: %u\r\n" - "Transport: RTP/AVP;multicast;destination=224.8.4.9;server_port=37890-37891\r\n" - RTSP_FIN, - cli); - } else { - RTSPOUT(RTSP_461 /*UNSUPPORTED_TRANSPORT*/ ); - } - } // SETUP - - // - // PLAY rtsp://127.0.0.1:37890 RTSP/1.0 - // CSeq: 13 - // Session: 0 - // Range: npt=0.000- - // User-Agent: VLC media player (LIVE555 Streaming Media v2005.11.10) - // - else if(!strcmp(m_State[cli]->Name(), "PLAY")) { - RTSPOUT(RTSP_200_OK - RTSP_FIN); - - if(!m_iMulticastMask && !xc.remote_rtp_always_on) - m_Scheduler->AddRtp(); - - m_bMulticast[cli] = true; - m_iMulticastMask |= (1<AddHandle(fd); -#endif - } // PLAY - - // - // TEARDOWN rtsp://127.0.0.1:37890 RTSP/1.0 - // CSeq: 39 - // Session: 1 - // User-Agent: VLC media player (LIVE555 Streaming Media v2005.11.10) - // - else if(!strcmp(m_State[cli]->Name(), "TEARDOWN")) { - RTSPOUT(RTSP_200_OK - RTSP_FIN); - CloseConnection(cli); - } // TEARDOWN - - // - // unknown/unsupported request - // - else { - LOGMSG("Unsupported RTSP request: %s", *m_State[cli]->Name()); - RTSPOUT(RTSP_501 /*NOT_IMPLEMENTED*/); - } // unsupported request - - - // dispose buffer - DELETENULL(m_State[cli]); - - } // ConnectionType == ctRtsp -} - -void cXinelibServer::Handle_Control(int cli, const char *cmd) -{ - TRACEF("cXinelibServer::Handle_Control"); - -#ifdef LOG_CONTROL_MESSAGES - static FILE *flog = fopen("/video/control.log","w"); - if (flog) { - fprintf(flog,"CTRL (%d): %s\n",cli,cmd); fflush(flog); - } -#endif - - //LOGDBG("Server received %s", cmd); - TRACE("Server received " << cmd); - - /* Order of tests is significant !!! - (example: UDP 2\r\n or UDP FULL 1\r\n) */ - - if(!strncasecmp(cmd, "OPTIONS ", 8) || - !strncasecmp(cmd, "SETUP ", 6) || - !strncasecmp(cmd, "DESCRIBE ", 9) || - m_ConnType[cli] == ctRtsp) { - - Handle_Control_RTSP(cli, cmd); - - } else if(!strncasecmp(cmd, "GET ", 4) || - m_ConnType[cli] == ctHttp) { - - Handle_Control_HTTP(cli, cmd); - - } else if(!strncasecmp(cmd, "PIPE OPEN", 9)) { - LOGDBG("Pipe open"); - - } else if(!strncasecmp(cmd, "PIPE", 4)) { - Handle_Control_PIPE(cli, cmd+4); - - } else if(!strncasecmp(cmd, "RTP", 3)) { - Handle_Control_RTP(cli, cmd+4); - - } else if(!strncasecmp(cmd, "UDP FULL 1", 10)) { - m_iUdpFlowMask |= (1<Set(pts); - - } else if(!strncasecmp(cmd, "ENDOFSTREAM", 11)) { - m_bEndOfStreamReached = true; - - } else if(!strncasecmp(cmd, "RESULT ", 7)) { - int token = -1, result = -1; - if(2 == sscanf(cmd, "RESULT %d %d", &token, &result)) { - cReplyFuture *f = m_Futures->Get(token); - if(f) { - m_Futures->Del(f, token); - f->Set(result); - } - } - - } else if(!strncmp(cmd, "INFO ", 5)) { - if(!*xc.local_frontend || !strncmp(xc.local_frontend, "none", 4)) - cXinelibThread::InfoHandler(cmd+5); - - } else if(!strncasecmp(cmd, "GRAB ", 5)) { - Handle_Control_GRAB(cli, cmd+5); - - } else if(!strncasecmp(cmd, "CLOSE", 5)) { - CloseConnection(cli); - - } else if(!strncasecmp(cmd, "CONTROL", 7)) { - Handle_Control_CONTROL(cli, cmd); - - } -} - -void cXinelibServer::Read_Control(int cli) -{ - int n; - while((n = fd_control[cli].recv(&m_CtrlBuf[ cli ][ m_CtrlBufPos[cli] ], 1)) == 1) { - - ++m_CtrlBufPos[cli]; - - if( m_CtrlBufPos[cli] > 512) { - LOGMSG("Received too long control message from client %d (%d bytes)", - cli, m_CtrlBufPos[cli]); - LOGMSG("%81s",m_CtrlBuf[cli]); - CloseConnection(cli); - return; - } - - if( m_CtrlBufPos[cli] > 1 && - m_CtrlBuf[ cli ][ m_CtrlBufPos[cli] - 2 ] == '\r' && - m_CtrlBuf[ cli ][ m_CtrlBufPos[cli] - 1 ] == '\n') { - - m_CtrlBufPos[cli] -= 2; - m_CtrlBuf[ cli ][ m_CtrlBufPos[cli] ] = 0; - - Handle_Control(cli, m_CtrlBuf[cli]); - - m_CtrlBufPos[cli] = 0; - } - } - if (n == 0) { - LOGMSG("Client connection %d closed", cli); - CloseConnection(cli); - } -} - -void cXinelibServer::Handle_ClientConnected(int fd) -{ - char buf[64]; - struct sockaddr_in sin; - socklen_t len = sizeof(sin); - int cli; - - for(cli=0; cli=MAXCLIENTS) { - // too many clients - LOGMSG("Too mant clients, connection refused"); - CLOSESOCKET(fd); - return; - } - - if (fcntl (fd, F_SETFL, fcntl (fd, F_GETFL) | O_NONBLOCK) == -1) { - LOGERR("Error setting control socket to nonblocking mode"); - CLOSESOCKET(fd); - } - - CloseDataConnection(cli); - - m_OsdTimeouts[cli] = 0; - m_CtrlBufPos[cli] = 0; - m_CtrlBuf[cli][0] = 0; - m_ConnType[cli] = ctDetecting; - fd_control[cli].set_handle(fd); - fd_control[cli].set_buffers(KILOBYTE(128), KILOBYTE(128)); - cXinelibDevice::Instance().ForcePrimaryDevice(true); -} - -void cXinelibServer::Handle_Discovery_Broadcast(void) -{ - if(!xc.remote_usebcast) { - LOGDBG("BROADCASTS disabled in configuration"); - CLOSESOCKET(fd_discovery); - return; - } - - char buf[DISCOVERY_MSG_MAXSIZE] = {0}; - struct sockaddr_in from; - - if(udp_discovery_recv(fd_discovery, buf, 0, &from) > 0) - if(udp_discovery_is_valid_search(buf)) - udp_discovery_broadcast(fd_discovery, m_Port, xc.remote_local_ip); -} - -void cXinelibServer::Action(void) -{ - TRACEF("cXinelibServer::Action"); - - int i, fds=0; - pollfd pfd[MAXCLIENTS]; - - /* higher priority */ - SetPriority(-1); - - sched_param temp; - temp.sched_priority = 2; - - /* request real-time scheduling */ - if (!pthread_setschedparam(pthread_self(), SCHED_RR, &temp)) { - LOGDBG("cXinelibServer priority set successful SCHED_RR %d [%d,%d]", - temp.sched_priority, - sched_get_priority_min(SCHED_RR), - sched_get_priority_max(SCHED_RR)); - } else { - LOGDBG("cXinelibServer: Can't set priority to SCHED_RR %d [%d,%d]", - temp.sched_priority, - sched_get_priority_min(SCHED_RR), - sched_get_priority_max(SCHED_RR)); - } - errno = 0; - - Lock(); - Listen(m_Port); - m_bReady=true; - - if(fd_listen>=0) - while (!GetStopSignal() && fds>=0) { - - fds = 0; - if(fd_listen>=0) { - pfd[fds].fd = fd_listen; - pfd[fds++].events = POLLIN; - } - if(fd_discovery >= 0) { - pfd[fds].fd = fd_discovery; - pfd[fds++].events = POLLIN; - } - - for(i=0; i=0) { - pfd[fds].fd = fd_data[i]; - pfd[fds++].events = 0; /* check for errors only */ - } - } - Unlock(); - - int err = poll(pfd,fds,1000); - - if(err < 0) { - LOGERR("cXinelibServer: poll failed"); - if(!GetStopSignal()) - cCondWait::SleepMs(100); - - } else if(err == 0) { - // poll timeout - - } else { - Lock(); - for(int f=0; f=0) - Handle_ClientConnected(fd); - } /* fd_listen */ - - // VDR Discovery - else if(pfd[f].fd == fd_discovery) { - Handle_Discovery_Broadcast(); - } /* fd_discovery */ - - // Control data - else { - for(i=0; i -#include "i18n.h" - -#if VDRVERSNUM < 10507 - -const tI18nPhrase Phrases[] = { - { "X11/xine-lib output plugin", // English - "X11/xine-lib Ausgabe-Plugin", // Deutsch - "", // Slovenski - "Plugin uscita X11/xine-lib", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "X11/xine-lib näyttölaite", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "X11/xine-lib ÒØÔÕÞ ÜÞÔãÛì", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Media Player", // English - "Medien...", // Deutsch - "", // Slovenski - "Lettore multimediale", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "Mediasoitin", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "Xine-lib", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "normal", // English - "Normal", // Deutsch - "", // Slovenski - "normale", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "normaali", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "½ÞàÜÐÛìÝëÙ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "inverted", // English - "Invertiert", // Deutsch - "", // Slovenski - "invertito", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "käänteinen", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "¸ÝÒÕàâØàÞÒÐÝÞ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Interlaced Field Order", // English - "Interlaced Halbbild-Reihenfolge", // Deutsch - "", // Slovenski - "Ordine campo interlacciato", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "Lomitettujen kenttien järjestys", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "ÇÕàÕ×áâàÞçÝëÙ ßÞàïÔÞÚ ßÞÛÕÙ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Brightness", // English - "Helligkeit", // Deutsch - "", // Slovenski - "Luminosità", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "Kirkkaus", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "ÏàÚÞáâì", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Decoder", // English - "Dekoder", // Deutsch - "", // Slovenski - "Decoder", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "Dekooderi", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "´ÕÚÞÔÕà", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Audio", // English - "Audio", // Deutsch - "", // Slovenski - "Audio", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "Ääni", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "°ãÔØÞ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "On-Screen Display", // English - "On-Screen Display", // Deutsch - "", // Slovenski - "Messaggi in sovraimpressione (OSD)", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "Kuvaruutunäyttö", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "ÍÚàÐÝÝÞÕ ÜÕÝî", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Hide main menu", // English - "Verstecke Hauptmenü", // Deutsch - "", // Slovenski - "Nascondi voce nel menu principale", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "Piilota valinta päävalikossa", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "ÁÚàëâì ÞáÝÞÒÝÞÕ ÜÕÝî", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Window aspect", // English - "Fenster-Seitenverhältnis", // Deutsch - "", // Slovenski - "Aspetto finestra", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "Ikkunan kuvasuhde", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "ÁÞÞâÝÞèÕÝØÕ áâÞàÞÝ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Scale to window size", // English - "Skaliere auf Fenster-Größe", // Deutsch - "", // Slovenski - "Scala a dimensione finestra", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "Skaalaa ikkunan kokoiseksi", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "¼ÐáèâÐÑØàÞÒÐâì Ò àÐ×ÜÕà ÞÚÝÐ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Dynamic transparency correction", // English - "Dynamische Transparenz-Korrektur", // Deutsch - "", // Slovenski - "Correzione trasparenza dinamica", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "Dynaaminen läpinäkyvyyden korjaus", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "´ØÝÐÜØçÕáÚÐï ÚÞààÕÚæØï ßàÞ×àÐçÝÞáâØ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Static transparency correction", // English - "Statische Transparenz-Korrektur", // Deutsch - "", // Slovenski - "Correzione trasparenza statica", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "Läpinäkyvyyden korjaus", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "ÁâÐâØçÕáÚÐï ÚÞààÕÚæØï ßàÞ×àÐçÝÞáâØ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Video", // English - "Video", // Deutsch - "", // Slovenski - "Video", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "Kuva", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "²ØÔÕÞ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Deinterlacing", // English - "Deinterlacing", // Deutsch - "", // Slovenski - "Deinterlacciamento", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "Lomituksen poisto", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "´ÕØÝâÕàÛÕÙáØÝÓ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Remote Clients", // English - "Entfernte Clients", // Deutsch - "", // Slovenski - "Client remoti", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "Etäkäyttö", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "ÃÔÐÛÕÝÝëÕ ÚÛØÕÝâë", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Allow remote clients", // English - "Erlaube entfernte Clients", // Deutsch - "", // Slovenski - "Permetti client remoti", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "Salli etäkäyttö", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "ÀÐ×àÕèØâì ãÔÐÛÕÝÝëå ÚÛØÕÝâÞÒ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Listen port (TCP and broadcast)", // English - " Empfangender Port (TCP und Broadcast)", // Deutsch - "", // Slovenski - " Porta in ascolto (TCP e broadcast)", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - " Kuuntele TCP-porttia", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - " ¿Þàâ (TCP Ø èØàÞÚÞÒÕèÐâÕÛìÝëÙ)", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Listen address", // English - "", // Deutsch - "", // Slovenski - " Indirizzo in ascolto", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - " Kuuntele osoitteessa", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Remote keyboard", // English - " Tastaturfernsteuerung", // Deutsch - "", // Slovenski - " Tastiera remota", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - " Käytä etänäppäimistöä", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - " ÃÔÐÛÕÝÝÐï ÚÛÐÒØÐâãàÐ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Buffer size", // English - "Puffergröße", // Deutsch - "", // Slovenski - "Dimensione buffer", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "Puskurin koko", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "ÀÐ×ÜÕà ÑãäÕàÐ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Number of PES packets", // English - " Anzahl PES-Pakete", // Deutsch - "", // Slovenski - " Numero di pacchetti PES", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - " PES-pakettien lukumäärä", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - " PES ßÐÚÕâÞÒ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "custom", // English - "Benutzerdefiniert", // Deutsch - "", // Slovenski - "personalizza", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "oma", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "¿ÞÛì×ÞÒÐâÕÛì", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "tiny", // English - "Winzig", // Deutsch - "", // Slovenski - "molto piccolo", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "olematon", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "¾çÕÝì ÜÐÛÕÝìÚØÙ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "small", // English - "Klein", // Deutsch - "", // Slovenski - "piccolo", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "pieni", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "¼ÐÛÕÝìÚØÙ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "medium", // English - "Mittel", // Deutsch - "", // Slovenski - "medio", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "keskikokoinen", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "ÁàÕÔÝØÙ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "large", // English - "Groß", // Deutsch - "", // Slovenski - "grande", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "suuri", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "±ÞÛìèÞÙ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "very large", // English - "", // Deutsch - "", // Slovenski - "molto grande", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "erittäin suuri", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "huge", // English - "Riesig", // Deutsch - "", // Slovenski - "enorme", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "valtava", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "¾çÕÝì ÑÞÛìÝÞÙ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Display address", // English - "Bildschirm-Adresse", // Deutsch - "", // Slovenski - "Mostra indirizzo", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "Näytön osoite", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "°ÔàÕá ÔØáßÛÕï", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Use keyboard", // English - "Tastatur benutzen", // Deutsch - "", // Slovenski - "Utilizza tastiera", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "Käytä näppäimistöä", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "¸áßÞÛì×ÞÒÐâì ÚÛÐÒØÐâãàã", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Driver", // English - "Treiber", // Deutsch - "", // Slovenski - "Driver", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "Ohjain", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "´àÐÙÒÕà", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Port", // English - "Port", // Deutsch - "", // Slovenski - "Porta", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "Portti", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "¿Þàâ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Delay", // English - "Verzögerung", // Deutsch - "", // Slovenski - "Ritardo", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "Viive", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "·ÐÔÕàÖÚÐ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - // ms -- milliseconds - { "ms", // English - "ms", // Deutsch - "", // Slovenski - "ms", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "ms", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "ms", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - // px - pixels - { "px", // English - "px", // Deutsch - "", // Slovenski - "px", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "px", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "ߨÚáÕÛÕÙ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Window width", // English - " Fensterbreite", // Deutsch - "", // Slovenski - " Larghezza finestra", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - " Ikkunan leveys", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - " ÈØàØÝÐ ÞÚÝÐ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Window height", // English - " Fensterhöhe", // Deutsch - "", // Slovenski - " Altezza finestra", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - " Ikkunan korkeus", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - " ²ëáÞâÐ ÞÚÝÐ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "automatic", // English - "Automatik", // Deutsch - "", // Slovenski - "automatica", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "automaattinen", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "°ÒâÞÜÐâØçÕáÚØ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "default", // English - "Standard", // Deutsch - "", // Slovenski - "predefinita", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "oletus", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "¿Þ ãÜÞÛçÐÝØî", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "4:3", // English - "4:3", // Deutsch - "4:3", // Slovenski - "4:3", // Italiano - "4:3", // Nederlands - "4:3", // Português - "4:3", // Français - "4:3", // Norsk - "4:3", // Suomi - "4:3", // Polski - "4:3", // Español - "4:3", // Ellinika - "4:3", // Svenska - "4:3", // Romaneste - "4:3", // Magyar - "4:3", // Catala - "4:3", // Russian - "4:3", // Croatian - "4:3", // Eesti - "4:3", // Dansk - "4:3", // Czech - }, - { "16:9", // English - "16:9", // Deutsch - "16:9", // Slovenski - "16:9", // Italiano - "16:9", // Nederlands - "16:9", // Português - "16:9", // Français - "16:9", // Norsk - "16:9", // Suomi - "16:9", // Polski - "16:9", // Español - "16:9", // Ellinika - "16:9", // Svenska - "16:9", // Romaneste - "16:9", // Magyar - "16:9", // Catala - "16:9", // Russian - "16:9", // Croatian - "16:9", // Eesti - "16:9", // Dansk - "16:9", // Czech - }, - { "Pan&Scan", // English - "Pan&Scan", // Deutsch - "Pan&Scan", // Slovenski - "Pan&Scan", // Italiano - "Pan&Scan", // Nederlands - "Pan&Scan", // Português - "Pan&Scan", // Français - "Pan&Scan", // Norsk - "Pan&Scan", // Suomi - "Pan&Scan", // Polski - "Pan&Scan", // Español - "Pan&Scan", // Ellinika - "Pan&Scan", // Svenska - "Pan&Scan", // Romaneste - "Pan&Scan", // Magyar - "Pan&Scan", // Catala - "Pan&Scan", // Russian - "Pan&Scan", // Croatian - "Pan&Scan", // Eesti - "Pan&Scan", // Dansk - "Pan&Scan", // Czech - }, - { "HUE", // English - "Farbton", // Deutsch - "", // Slovenski - "Tonalità", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "Värisävy", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "HUE", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Saturation", // English - "Sättigung", // Deutsch - "", // Slovenski - "Saturazione", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "Saturaatio", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "½ÐáëéÕÝÝÞáâì", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Contrast", // English - "Kontrast", // Deutsch - "", // Slovenski - "Contrasto", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "Kontrasti", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "ºÞÝâàÐáâÝÞáâì", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "off", // English - "Aus", // Deutsch - "", // Slovenski - "disattivo", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "ei käytössä", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "²ëÚÛ.", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "no audio", // English - "Kein Audio", // Deutsch - "", // Slovenski - "niente audio", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "ei ääntä", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "½Õâ ÐãÔØÞ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "no video", // English - "Kein Video", // Deutsch - "", // Slovenski - "niente video", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "ei kuvaa", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "½Õâ ÒØÔÕÞ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Fullscreen mode", // English - "Vollbild-Modus", // Deutsch - "", // Slovenski - "Mod. schermo intero", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "Kokoruututila", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "¿ÞÛÝÞíÚàÐÝÝëÙ àÕÖØÜ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Local Frontend", // English - "Lokale Anzeige", // Deutsch - "", // Slovenski - "Frontend locale", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "Paikallinen näyttö", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "»ÞÚÐÛìÝëÙ äàÞÝâÕÝÔ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Local Display Frontend", // English - "Lokale Bildschirmanzeige", // Deutsch - "", // Slovenski - "Frontend visualizzazione locale", // Italiano - "", // Nederlands - "", // Português - "", // Français - "", // Norsk - "Paikallinen näyttö", // Suomi - "", // Polski - "", // Español - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "ÄàÞÝâÕÝÔ ÛÞÚÐÛìÝÞÓÞ íÚàÐÝÐ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Delete image ?", // English - "Bild löschen?", // Deutsch - "", // Slovenski - "Cancellare immagine ?", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Poistetaanko kuva ?", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "ÃÔÐÛØâì ÚÐàâØÝÚã ?", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " TCP transport", // English - " TCP-Übertragung", // Deutsch - "", // Slovenski - " Protocollo TCP", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - " TCP-siirto", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "TCP âàÐÝáßÞàâ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " UDP transport", // English - " UDP-Übertragung", // Deutsch - "", // Slovenski - " Protocollo UDP", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - " UDP-siirto", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "UDP âàÐÝáßÞàâ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " RTP (multicast) transport", // English - " RTP (multicast) Übertragung", // Deutsch - "", // Slovenski - " Protocollo RTP (multicast)", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - " RTP (multicast) -siirto", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - " RTP (èØàÞÚÞÒÕéÐâÕÛìÝëÙ) âàÐÝáßÞàâ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " PIPE transport", // English - " Pipe-Übertragung", // Deutsch - "", // Slovenski - " Protocollo PIPE", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - " PIPE-siirto", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - " PIPE âàÐÝáßÞàâ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Server announce broadcasts", // English - " Server-Bekanntmachung Broadcast", // Deutsch - "", // Slovenski - " Annuncio trasmissioni dal server", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - " Palvelimen broadcast-ilmoitukset", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - " ÁÕàÒÕà ØáßÞÛì×ãÕâ èØàÞÚÞÒÕéÐÝØÕ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Audio equalizer >>", // English - "Audio-Equalizer >>", // Deutsch - "", // Slovenski - "Equalizzatore audio >>", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Taajuuskorjain >>", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "°ãÔØÞ íÚÒÐÛÐÙ×Õà >>", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Audio Equalizer", // English - "Audio Equalizer", // Deutsch - "", // Slovenski - "Equalizzatore audio", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Taajuuskorjain", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "°ãÔØÞ íÚÒÐÛÐÙ×Õà", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Grayscale", // English - "Graustufen", // Deutsch - "", // Slovenski - "Scala di grigi", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Harmaasävy", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "¾ââÕÝÚØ áÕàÞÓÞ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Bitmap", // English - "Bitmap", // Deutsch - "", // Slovenski - "Bitmap", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Bittikartta", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "±ØâÞÒÐï ÚÐàâÐ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Button$Info", // English - "Info", // Deutsch - "", // Slovenski - "Info", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Tiedot", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Audio Compression", // English - "Audio-Komprimierung", // Deutsch - "", // Slovenski - "Compressione audio", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Voimista hiljaisia ääniä", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "°ãÔØÞ ÚÞÜßàÕááØï", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Play file >>", // English - "Datei abspielen >>", // Deutsch - "", // Slovenski - "Riproduci file >>", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Toista tiedosto >>", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "¿àÞØÓàÐâì äÐÙÛ >>", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Play music >>", // English - "Musik abspielen >>", // Deutsch - "", // Slovenski - "Riproduci musica >>", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Toista musiikkia >>", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "¿àÞØÓàÐâì äÐÙÛ >>", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "View images >>", // English - "Bilder ansehen >>", // Deutsch - "", // Slovenski - "Visualizza immagini >>", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Katsele kuvia >>", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "¿àÞáÜÞâàÕâì Ø×ÞÑàÐÖÕÝØï >>", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Play file", // English - "Datei abspielen", // Deutsch - "", // Slovenski - "Riproduci file", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Toista tiedosto", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "¿àÞØÓàÐâì äÐÙÛ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Images", // English - "Bilder", // Deutsch - "", // Slovenski - "Immagini", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Kuvat", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "¸×ÞÑàÐÖÕÝØï", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "CenterCutOut", // English - "CenterCutOut", // Deutsch - "", // Slovenski - "CenterCutOut", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "CenterCutOut", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Test Images", // English - "Testbilder", // Deutsch - "", // Slovenski - "Prova immagini", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Testikuvat", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "ÂÕáâÞÒëÕ Ø×ÞÑàÐÖÕÝØï", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Visualization", // English - "Visualisierung", // Deutsch - "", // Slovenski - "Visualizzazione", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Visualisointi", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "²Ø×ãÐÛØ×ÐæØï", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Upmix stereo to 5.1", // English - "Stereo zu 5.1 hoch mischen", // Deutsch - "", // Slovenski - "Suono da Stereo a 5.1", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Miksaa stereoääni 5.1-kanavaiseksi", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "¿àÕÞÑàÐ×ÞÒÐâì áâÕàÕÞ Ò 5.1", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Downmix AC3 to surround", // English - "AC3 zu Surround herunter mischen", // Deutsch - "", // Slovenski - "Suono da AC3 a surround", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Miksaa AC3-ääni surroundiksi", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Framebuffer device", // English - "Framebuffer-Device", // Deutsch - "", // Slovenski - "Periferica framebuffer", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Framebuffer-laite", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "Framebuffer ãáâàÞÙáâÒÞ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Use hardware for low-res video", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - " Laitteisto matalaresoluutioisella videolla", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - - // 1.0.0pre2: - { "Play remote DVD >>", // English - "Entfernte DVD abspielen >>", // Deutsch - "", // Slovenski - "Riproduci DVD remoto >>", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Toista DVD-levy etäkoneesta >>", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Play DVD disc >>", // English - "DVD abspielen", // Deutsch - "", // Slovenski - "Riproduci disco DVD >>", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Toista DVD-levy >>", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Crop letterbox 4:3 to 16:9", // English - "Schneide letterbox 4:3 zu 16:9", // Deutsch - "", // Slovenski - "Ritaglia letterbox 4:3 a 16:9", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Leikkaa 4:3-letterbox 16:9:ksi", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Play only audio", // English - "Nur Audio spielen", // Deutsch - "", // Slovenski - "Riproduci solo audio", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Toista pelkkä ääni", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Off", // English - "Aus", // Deutsch - "", // Slovenski - "Disattivo", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "ei käytössä", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "OSS", // English - "OSS", // Deutsch - "", // Slovenski - "OSS", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "OSS", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Alsa", // English - "Alsa", // Deutsch - "", // Slovenski - "Alsa", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Alsa", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Goom", // English - "Goom", // Deutsch - "", // Slovenski - "Goom", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Goom", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Oscilloscope", // English - "Oszilloskop", // Deutsch - "", // Slovenski - "Oscilloscopio", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Oskilloskooppi", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "FFT Scope", // English - "FFT Spektrum", // Deutsch - "", // Slovenski - "Spettro FFT", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Spektri", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "FFT Graph", // English - "FFT Graph", // Deutsch - "", // Slovenski - "Grafico FFT", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Spektrogrammi", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "X11 (sxfe)", // English - "X11 (sxfe)", // Deutsch - "", // Slovenski - "X11 (sxfe)", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "X11 (sxfe)", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Framebuffer (fbfe)", // English - "Framebuffer (fbfe)", // Deutsch - "", // Slovenski - "Framebuffer (fbfe)", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Framebuffer (fbfe)", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Xv", // English - "Xv", // Deutsch - "", // Slovenski - "Xv", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Xv", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "XShm", // English - "XShm", // Deutsch - "", // Slovenski - "XShm", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "XShm", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Bob", // English - "Bob", // Deutsch - "", // Slovenski - "Bob", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Bob", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Weave", // English - "Weave", // Deutsch - "", // Slovenski - "Weave", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Weave", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Greedy", // English - "Greedy", // Deutsch - "", // Slovenski - "Greedy", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Greedy", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "One Field", // English - "Ein Halbbild", // Deutsch - "", // Slovenski - "Un campo", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "One Field", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "One Field XV", // English - "Ein Halbbild XV", // Deutsch - "", // Slovenski - "Un campo XV", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "One Field XV", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Linear Blend", // English - "Linear mischen", // Deutsch - "", // Slovenski - "Trasparenza lineare", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Linear Blend", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "TvTime", // English - "TvTime", // Deutsch - "", // Slovenski - "TvTime", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "TvTime", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Address", // English - " Multicast-Adresse", // Deutsch - "", // Slovenski - " Indirizzo", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - " Osoite", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Port", // English - " Multicast-Port", // Deutsch - "", // Slovenski - " Porta", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - " Portti", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " TTL", // English - " Multicast-TTL", // Deutsch - "", // Slovenski - " TTL", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - " TTL-aika", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Transmit always on", // English - " Immer senden", // Deutsch - "", // Slovenski - " Trasmetti sempre", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - " Pidä lähetys aina päällä", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Speakers", // English - "Lautsprecher", // Deutsch - "", // Slovenski - "Altoparlanti", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Kaiuttimet", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Headphones 2.0", // English - "Kopfhöhrer 2.0", // Deutsch - "", // Slovenski - "Cuffie 2.0", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Kuulokkeet 2.0", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Autodetect letterbox", // English - " Letterbox automatisch erkennen", // Deutsch - "", // Slovenski - " Rileva letterbox in automatico", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - " Tunnista letterbox automaattisesti", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Soft start", // English - " Weich starten", // Deutsch - "", // Slovenski - " Avvio leggero", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - " Portaittainen aloitus", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Crop to", // English - " Schneide auf", // Deutsch - "", // Slovenski - " Ritaglia a", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - " Leikkaa kokoon", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Detect subtitles", // English - " Erkenne Untertitel", // Deutsch - "", // Slovenski - " Rileva sottotitoli", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - " Huomioi tekstitys", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - - // 1.0.0pre4: - { "Media", // English - "Medien", // Deutsch - "", // Slovenski - "Media", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Media", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Video settings", // English - "Video-Einstellungen", // Deutsch - "", // Slovenski - "Impostazioni video", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Videoasetukset", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Audio settings", // English - "Audio-Einstellungen", // Deutsch - "", // Slovenski - "Impostazioni audio", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Ääniasetukset", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Overscan (crop image borders)", // English - "Overscan (Bildränder abschneiden)", // Deutsch - "", // Slovenski - "Overscan (ritaglia bordi immagine)", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Leikkaa kuvan reunoja (overscan)", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Smooth fast forward", // English - "", // Deutsch - "", // Slovenski - "Avanzamento veloce leggero", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Tasainen kuvakelaus", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - // Missing texts 2006-09-20 - { "Post processing (ffmpeg)", // English - "Nachbearbeitung (ffmpeg)", // Deutsch - "", // Slovenski - "Codifica (ffmpeg)", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Käytä jälkikäsittelyä (ffmpeg)", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - // ffmpeg post processing - { " Quality", // English - " Qualität", // Deutsch - "", // Slovenski - " Qualità", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - " Laatu", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Mode", // English - " Modus", // Deutsch - "", // Slovenski - " Modalità", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - " Moodi", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - // tvtime de-interlacing - { " Method", // English - " Methode", // Deutsch - "", // Slovenski - " Metodo", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - " Menetelmä", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Cheap mode", // English - " einfacher Modus", // Deutsch - "", // Slovenski - " Modo economico", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - " Käytä Cheap-moodia", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Pulldown", // English - " Pulldown", // Deutsch - "", // Slovenski - " Pulldown", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - " Pulldown-moodi", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Frame rate", // English - " Bildrate", // Deutsch - "", // Slovenski - " Frame rate", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - " Ruudunpäivitys", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Judder Correction", // English - " Ruckel-Korrektur", // Deutsch - "", // Slovenski - " Correzione gamma", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - " Käytä tärinänkorjausta", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Use progressive frame flag", // English - " Nutze progressive frame flag", // Deutsch - "", // Slovenski - " Utilizza flag frame progressivo", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - " Tunnista progressiivinen kuva", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Chroma Filter", // English - " Chrominanz-Filter", // Deutsch - "", // Slovenski - " Filtro Chroma", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - " Käytä Chroma-suodinta", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Select subtitle track", // English - "Wähle Untertitel", // Deutsch - "", // Slovenski - "Seleziona traccia sottotitoli", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Valitse tekstityskieli", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Select subtitle track >>", // English - "Wähle Untertitel >>", // Deutsch - "", // Slovenski - "Seleziona traccia sottotitoli >>", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Valitse tekstityskieli >>", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Subtitles", // English - "Untertitel", // Deutsch - "", // Slovenski - "Sottotitoli", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Tekstitys", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "External subtitle size", // English - "Untertitel größe", // Deutsch - "", // Slovenski - "Dimensione sottotitoli esterni", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Erillisen tekstityksen koko", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Aspect ratio", // English - "Seitenverhältnis", // Deutsch - "", // Slovenski - "Proporzioni", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Kuvasuhde", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Play music", // English - "Musik abspielen", // Deutsch - "", // Slovenski - "Riproduci musica", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Toista musiikkia", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Random play", // English - "Zufallswiedergabe", // Deutsch - "", // Slovenski - "Riproduzione casuale", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Satunnaistoisto", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Normal play", // English - "Normale Wiedergabe", // Deutsch - "", // Slovenski - "Riproduzione normale", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Normaali toisto", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Frontend initialization failed", // English - "Initialisierung des Frontends fehlgeschlagen", // Deutsch - "", // Slovenski - "Inizializzazione frontend fallita", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Näyttölaitteen alustus epäonnistui", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Server initialization failed", // English - "Initialisierung des Servers fehlgeschlagen", // Deutsch - "", // Slovenski - "Inizializzazione server fallita", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Palvelimen käynnistys epäonnistui", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - // Goom options - { " Width", // English - " Breite", // Deutsch - "", // Slovenski - " Larghezza", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - " Leveys", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Height", // English - " Höhe", // Deutsch - "", // Slovenski - " Altezza", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - " Korkeus", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Speed", // English - " Bildrate", // Deutsch - "", // Slovenski - " Velocità", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - " Nopeus", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " SAP announcements", // English - " SAP-Ankündigungen", // Deutsch - "", // Slovenski - " Annunci SAP", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - " SAP-ilmoitukset", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Play remote CD >>", // English - "Entfernte CD abspielen >>", // Deutsch - "", // Slovenski - "Riproduci CD remoto >>", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Toista CD-levy etäkoneesta >>", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Play audio CD >>", // English - "Musik-CD abspielen >>", // Deutsch - "", // Slovenski - "Riproduci CD audio >>", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Toista CD-levy >>", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " HTTP transport for media files", // English - " HTTP-Verbindung für Medien-Dateien", // Deutsch - "", // Slovenski - " Protocollo HTTP per file multimediali", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - " HTTP -siirto mediatiedostoille", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Additional network services", // English - "Zusätzliche Netzwerk-Services", // Deutsch - "", // Slovenski - "Ulteriori servizi di rete", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Muut verkkopalvelut", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "HTTP server", // English - "HTTP-Server", // Deutsch - "", // Slovenski - "Server HTTP", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "HTTP-palvelin", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "RTSP server", // English - "RTSP-Server", // Deutsch - "", // Slovenski - "Server RTSP", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "RTSP-palvelin", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "HTTP clients can control VDR", // English - "HTTP-Clients können VDR kontrollieren", // Deutsch - "", // Slovenski - "I client HTTP possono controllare VDR", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Anna HTTP-asiakkaiden ohjata VDR:ää", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "RTSP clients can control VDR", // English - "RTSP-Clients können VDR kontrollieren", // Deutsch - "", // Slovenski - "I client RTSP possono controllare VDR", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Anna RTSP-asiakkaiden ohjata VDR:ää", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Button$Queue", // English - "Warteschlange", // Deutsch - "", // Slovenski - "Coda", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Soittolistalle", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Button$Sort", // English - "Sortiere", // Deutsch - "", // Slovenski - "Ordina", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Järjestä", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Button$Remove", // English - "Entferne", // Deutsch - "", // Slovenski - "Rimuovi", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Poista", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Button$Add files", // English - "Füge Dateien hinzu", // Deutsch - "", // Slovenski - "Aggiungi files", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Lisää", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Button$Random", // English - "Zufall", // Deutsch - "", // Slovenski - "Casuale", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Satunnaistoisto", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Button$Normal", // English - "Normal", // Deutsch - "", // Slovenski - "Normale", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Normaali toisto", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "No subtitles available!", // English - "Keine Untertitel verfügbar!", // Deutsch - "", // Slovenski - "Nessun sottotitolo disponibile!", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Ei tekstitystä", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Playlist", // English - "Wiedergabeliste", // Deutsch - "", // Slovenski - "Lista esecuzione", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Soittolista", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Add to playlist", // English - "Füge zur Wiedergabeliste hinzu", // Deutsch - "", // Slovenski - "Aggiungi alla lista esecuzione", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Lisää soittolistalle", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Queued to playlist", // English - "Hänge an Wiedergabeliste an", // Deutsch - "", // Slovenski - "Accoda alla lista esecuzione", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Lisätty soittolistalle", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Volume control", // English - "", // Deutsch - "", // Slovenski - "Controllo volume", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Äänenvoimakkuuden säätö", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Hardware", // English - "", // Deutsch - "", // Slovenski - "Hardware", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Laitteistolla", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Software", // English - "", // Deutsch - "", // Slovenski - "Software", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Ohjelmallisesti", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "3D Denoiser", // English - "", // Deutsch - "", // Slovenski - "3D Denoiser", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "3D kohinanpoisto", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - // 3D Denoiser - { " Spatial luma strength", // English - "", // Deutsch - "", // Slovenski - " Resistenza luma spaziale", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - " Luman tilavoimakkuus", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Spatial chroma strength", // English - "", // Deutsch - "", // Slovenski - " Resistenza chroma spaziale", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - " Chroman tilavoimakkuus", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Temporal strength", // English - "", // Deutsch - "", // Slovenski - " Resistenza temporale", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - " Ajallinen voimakkuus", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Sharpen / Blur", // English - "", // Deutsch - "", // Slovenski - "Nitido / Blur", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Terävöinti / Sumennus", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - // Unsharp mask - { " Width of the luma matrix", // English - "", // Deutsch - "", // Slovenski - " Larghezza della matrice luma", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - " Luma-matriisin leveys", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Height of the luma matrix", // English - "", // Deutsch - "", // Slovenski - " Altezza della matrice luma", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - " Luma-matriisin korkeus", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Amount of luma sharpness/blur", // English - "", // Deutsch - "", // Slovenski - " Valore di nitidezza/blur luma", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - " Luma-terävöinti/-sumennus", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Width of the chroma matrix", // English - "", // Deutsch - "", // Slovenski - " Larghezza della matrice chroma", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - " Chroma-matriisin leveys", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Height of the chroma matrix", // English - "", // Deutsch - "", // Slovenski - " Altezza della matrice chroma", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - " Chroma-matriisin korkeus", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Amount of chroma sharpness/blur", // English - "", // Deutsch - "", // Slovenski - " Valore di nitidezza/blur chroma", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - " Chroma-terävöinti/-sumennus", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Headphones 2.0", // English - "", // Deutsch - "", // Slovenski - "Cuffie 2.0", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Kuulokkeet 2.0", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Pass Through", // English - "", // Deutsch - "", // Slovenski - "Passa attraverso", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Läpivienti", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Show the track number", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Näytä raidan numero", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Show the name of the artist", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Näytä esittäjän nimi", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Show the name of the album", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Näytä levyn nimi", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Cache metainfo", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Tallenna metatieto", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Scan for metainfo", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Tutki kappaleiden metatiedot", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Playlist settings", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Soittolistan asetukset", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Video aspect ratio", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Videon kuvasuhde", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "square", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "neliö", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "anamorphic", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "anamorfinen", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Software scaling", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Skaalaus ohjelmistolla", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Change aspect ratio", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - " Muuta kuvasuhdetta", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Change video size", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - " Muuta videokuvan kokoa", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Fastest trick speed", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Suurin kelausnopeus", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Blending method", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Piirtotapa", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Scaling method", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Skaalaus", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Show all layers", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Näytä kaikki kerrokset", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Advanced", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Advanced settings", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " * Following settings won't work with UDP/RTP *", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - " * Seuraavat asetukset eivät toimi UDP/RTP:n kanssa *", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Sync to transponder in live mode", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Tahdistu lähetteeseen live-tilassa", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Adjust SCR", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - "Säädä SCR:ää", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Clock speed (Hz)", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - " Kellon nopeus (Hz)", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Clock Adjustment (%)", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugus - "", // Franais - "", // Norsk - " Kellon säätö (%)", // Suomi - "", // Polski - "", // Espaol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - - { NULL } -}; - -#endif // VDRVERSNUM < 10507 - diff --git a/i18n.h b/i18n.h deleted file mode 100644 index 41faaeee..00000000 --- a/i18n.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * i18n.h: Internationalization - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: i18n.h,v 1.3 2007-09-18 13:52:52 phintuka Exp $ - * - */ - -#ifndef __XINELIBOUTPUT_I18N_H -#define __XINELIBOUTPUT_I18N_H - -#include - -#if VDRVERSNUM < 10507 - -extern const tI18nPhrase Phrases[]; - -#ifndef trNOOP -# define trNOOP(s) (s) -#endif - -#ifndef trVDR -# define trVDR(s) tr(s) -#endif - -#endif // VDRVERSNUM < 10507 - -#endif //__XINELIBOUTPUT_I18N_H diff --git a/logdefs.h b/logdefs.h deleted file mode 100644 index df186697..00000000 --- a/logdefs.h +++ /dev/null @@ -1,187 +0,0 @@ -/* - * logdefs.h: Logging and debug output - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: logdefs.h,v 1.8 2008-02-05 01:18:17 phintuka Exp $ - * - */ - -#ifndef _LOGDEFS_H_ - -/* - * Default module name (goes to every log line) - */ - -#ifndef LOG_MODULENAME -# define LOG_MODULENAME "[xine..put] " -#endif - -/* - * Logging functions, should not be used directly - */ - -#if defined(esyslog) || (defined(VDRVERSNUM) && VDRVERSNUM >= 10343) -# define x_syslog(l,x...) syslog_with_tid(l, LOG_MODULENAME x) -#else - -# ifndef __APPLE__ -# include /* syscall(__NR_gettid) */ -# endif - - /* from xine_frontend.c or vdr tools.c: */ - extern int SysLogLevel; /* errors, info, debug */ - -# ifndef LogToSysLog - extern int LogToSysLog; /* xine_frontend_c, log to syslog instead of console */ -# endif - -# if defined(NEED_x_syslog) -# include -# include -# include - static void x_syslog(int level, const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); - static void x_syslog(int level, const char *fmt, ...) - { - va_list argp; - char buf[512]; - va_start(argp, fmt); - vsnprintf(buf, 512, fmt, argp); - buf[sizeof(buf)-1] = 0; -# ifndef __APPLE__ - if(!LogToSysLog) { - fprintf(stderr,"[%ld] " LOG_MODULENAME "%s\n", (long int)syscall(__NR_gettid), buf); - } else { - syslog(level, "[%ld] " LOG_MODULENAME "%s", (long int)syscall(__NR_gettid), buf); - } -# else - if(!LogToSysLog) { - fprintf(stderr, LOG_MODULENAME "%s\n", buf); - } else { - syslog(level, LOG_MODULENAME "%s", buf); - } -# endif - va_end(argp); - } -# endif /* NEED_x_syslog */ -#endif /* VDR */ - - -/* - * Macros used for logging - */ - -#include - -#define LOG_ERRNO x_syslog(LOG_ERR, " (ERROR (%s,%d): %s)", \ - __FILE__, __LINE__, strerror(errno)) - -#define LOGERR(x...) do { \ - if(SysLogLevel > 0) { \ - x_syslog(LOG_ERR, x); \ - if(errno) \ - LOG_ERRNO; \ - } \ - } while(0) -#define LOGMSG(x...) do{ if(SysLogLevel > 1) x_syslog(LOG_INFO, x); } while(0) -#define LOGDBG(x...) do{ if(SysLogLevel > 2) x_syslog(LOG_DEBUG, x); } while(0) - -#define TRACELINE LOGDBG("at %s:%d %s", __FILE__, __LINE__, __FUNCTION__) - - - -/* - * ASSERT - */ - -#ifdef NDEBUG -# define ASSERT(expr) -#else -# define ASSERT(expr,fatal) \ - do { \ - if(!(expr)) { \ - LOGERR("Asseretion failed: %s at %s:%d (%s)", \ - #expr, __FILE__, __LINE__, __FUNCTION__); \ - if(fatal) \ - abort(); \ - } \ - } while(0) -#endif - - -/* - * Plugin (call)trace - */ - -#ifdef XINELIBOUTPUT_DEBUG -# ifdef __cplusplus -# -# include -# include -# include -# -# ifndef TRACE_IDENT -# define TRACE_IDENT "" -# endif -# if defined(XINELIBOUTPUT_DEBUG_STDOUT) -# define TRACE(x) do {std::cout << TRACE_IDENT << x << "\n"; fflush(stdout);}while(0) -# elif defined(XINELIBOUTPUT_DEBUG_STDERR) -# define TRACE(x) do {std::cerr << TRACE_IDENT << x << "\n"; fflush(stderr);}while(0) -# else -# error No trace target ! -# endif -# define TRACEF(x) cTraceFunctionCall _x_cTraceFunctionCall(x); - class cTraceFunctionCall { - public: - const char *m_name; - cTraceFunctionCall(const char *name) : m_name(name) - { TRACE(m_name << " - Enter"); } - ~cTraceFunctionCall() - { TRACE(m_name << " - Leave "); } - }; -# endif -#else -# define TRACE(x) -# define TRACEF(x) -#endif - - -/* - * Execution time tracker: - * log a message when function execution takes longer than expected - */ - -#ifdef __cplusplus -# ifdef TRACK_EXEC_TIME - class cTimeTracker - { - private: - const char *m_Message; - const char *m_Where; - uint64_t m_Start; - uint64_t m_Trigger; - public: - cTimeTracker(const char *Message, int TriggerMs, const char *Where) { - m_Message = Message; - m_Where = Where; - m_Trigger = TriggerMs; - m_Start = cTimeMs::Now(); - } - ~cTimeTracker() { - if(cTimeMs::Now() - m_Start > m_Trigger) - LOGMSG("********** TimeTracker hit in %s: %d ms %s", - m_Where, (int)(cTimeMs::Now() - m_Start), - m_Message?m_Message:""); - } - }; -# define TRACK_TIME(limit) cTimeTracker _timetracker(NULL,limit,__PRETTY_FUNCTION__) -# define TRACK_TIME_EXT(limit,msg) cTrimeTracker __timetracker(msg,limit,__PRETTY_FUNCTION__) -# else -# define TRACK_TIME(limit) -# define TRACK_TIME_EXT(limit,msg) -# endif -# endif - - -#endif /* _LOGDEFS_H_ */ diff --git a/media_player.c b/media_player.c deleted file mode 100644 index 0392714c..00000000 --- a/media_player.c +++ /dev/null @@ -1,1319 +0,0 @@ -/* - * media_player.c: - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: media_player.c,v 1.51 2008-04-03 15:32:07 phelin Exp $ - * - */ - -#include - -#include -#include -#include -#include - -#include "config.h" -#include "media_player.h" -#include "device.h" -#include "tools/playlist.h" -#include "menu.h" - -#include "logdefs.h" - -#include "tools/iconv.h" - -static void BackToMenu(void) -{ - cRemote::CallPlugin("xineliboutput"); -} - - -// -// cXinelibPlayer -// - -class cXinelibPlayer : public cPlayer -{ - private: - cString m_File; - cString m_ResumeFile; - cString m_SubFile; - - cPlaylist m_Playlist; - - bool m_Replaying; - int m_Speed; - - protected: - virtual void Activate(bool On); - - public: - cXinelibPlayer(const char *File, bool Queue = false, const char *SubFile = NULL); - virtual ~cXinelibPlayer(); - - // cPlayer - virtual void SetAudioTrack(eTrackType Type, const tTrackId *TrackId); - virtual void SetSubtitleTrack(eTrackType Type, const tTrackId *TrackId); - virtual bool GetIndex(int &Current, int &Total, bool SnapToIFrame = false); - virtual bool GetReplayMode(bool &Play, bool &Forward, int &Speed); - - // cXinelibPlayer - void Control(const char *s) { (void)cXinelibDevice::Instance().PlayFileCtrl(s); } - void Control(const char *s, int i) { - cString cmd = cString::sprintf(s, i); - Control(cmd); - } - void SetSpeed(int Speed); - int Speed(void) { return m_Speed; }; - - bool NextFile(int step); - bool Replaying(void) { return m_Replaying; } - - bool m_UseResume; - - /* Playlist access */ - cPlaylist& Playlist(void) { return m_Playlist; } - const cString& File(void) { return m_File; } - int CurrentFile(void) { return m_Playlist.Current()->Index(); } - int Files(void) { return m_Playlist.Count(); } -}; - -cXinelibPlayer::cXinelibPlayer(const char *File, bool Queue, const char *SubFile) -{ - m_ResumeFile = NULL; - m_UseResume = true; - m_Replaying = false; - m_Speed = 1; - - if(File) { - int len = strlen(File); - if(len && File[len-1] == '/') { - // whole directory, create temporary playlist - m_Playlist.Read(File, true); - m_Playlist.Sort(); - } else if(xc.IsPlaylistFile(File)) { - m_Playlist.Read(File); - } else { - // a single file but not a playlist file, create playlist with only one item - m_Playlist.Read(File); - } - - if(m_Playlist.Count() < 1) - LOGMSG("cXinelibPlayer: nothing to play !"); - - if(m_Playlist.Count() > 0) - m_Playlist.StartScanner(); - - m_File = m_Playlist.Current()->Filename; - m_SubFile = SubFile; - } -} - -cXinelibPlayer::~cXinelibPlayer() -{ - Activate(false); - Detach(); -} - -void cXinelibPlayer::SetAudioTrack(eTrackType Type, const tTrackId *TrackId) -{ - if(IS_DOLBY_TRACK(Type)) - Control("AUDIOSTREAM AC3 %d", (int)(Type - ttDolbyFirst)); - if(IS_AUDIO_TRACK(Type)) - Control("AUDIOSTREAM AC3 %d", (int)(Type - ttAudioFirst)); -} - -void cXinelibPlayer::SetSubtitleTrack(eTrackType Type, const tTrackId *TrackId) -{ -#if VDRVERSNUM >= 10515 - cXinelibDevice::Instance().SetSubtitleTrackDevice(Type); -#endif -} - -bool cXinelibPlayer::GetIndex(int &Current, int &Total, bool SnapToIFrame) -{ - // Returns the current and total frame index, optionally snapped to the - // nearest I-frame. - int msCurrent = cXinelibDevice::Instance().PlayFileCtrl("GETPOS"); - int msTotal = cXinelibDevice::Instance().PlayFileCtrl("GETLENGTH"); - if(msCurrent>=0 && msTotal>=0) { - Current = msCurrent * 25 / 1000; - Total = msTotal * 25 / 1000; - return true; - } - return false; -} - -bool cXinelibPlayer::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. - Play = (m_Speed>0); - Forward = true; - Speed = abs(m_Speed) - 2; - if(Speed<-1) Speed=-1; - - return true; -} - -void cXinelibPlayer::SetSpeed(int Speed) -{ - m_Speed = Speed; - switch(Speed) { - case -4: Control("TRICKSPEED 8"); break; - case -3: Control("TRICKSPEED 4"); break; - case -2: Control("TRICKSPEED 2"); break; - case 0: Control("TRICKSPEED 0"); break; - default: m_Speed = 1; - case 1: Control("TRICKSPEED 1"); break; - case 2: Control("TRICKSPEED -2"); break; - case 3: Control("TRICKSPEED -4"); break; - case 4: Control("TRICKSPEED -12"); break; - } -} - -bool cXinelibPlayer::NextFile(int step) -{ - if(m_Playlist.Count()>0) { - for(;step < 0; step++) - m_Playlist.Prev(); - for(;step > 0; step--) - m_Playlist.Next(); - - if(!m_Playlist.Current()) - LOGERR("!m_Playlist.Get(m_CurrInd)"); - m_File = *m_Playlist.Current()->Filename; - m_ResumeFile = NULL; - m_SubFile = NULL; - - Activate(true); - if(!m_Replaying) - return false; - return true; - } - - return false; -} - -void cXinelibPlayer::Activate(bool On) -{ - int pos = 0, len = 0, fd = -1; - if(On) { - if(m_UseResume && !*m_ResumeFile) - m_ResumeFile = cString::sprintf("%s.resume", *m_File); - if(m_UseResume && 0 <= (fd = open(m_ResumeFile, O_RDONLY))) { - if(read(fd, &pos, sizeof(int)) != sizeof(int)) - pos = 0; - close(fd); - } - // escape file name and join subtitle file - // Maybe mrls from playlist files should not be escaped ? - // (those may contain #subtitle, #volnorm etc. directives) - cString mrl; - if(*m_SubFile) - mrl = cString::sprintf("%s%s#subtitle:%s", - m_File[0] == '/' ? "file:" : "", - *cPlaylist::EscapeMrl(m_File), - *cPlaylist::EscapeMrl(m_SubFile)); - else if((*m_File)[0] == '/') - mrl = cString::sprintf("%s%s", - m_File[0] == '/' ? "file:" : "", - *cPlaylist::EscapeMrl(m_File)); - else - mrl = cPlaylist::EscapeMrl(m_File); - m_Replaying = cXinelibDevice::Instance().PlayFile(mrl, pos); - LOGDBG("cXinelibPlayer playing %s (%s)", *m_File, m_Replaying?"OK":"FAIL"); - - if(m_Replaying) { - // update playlist metainfo - const char *ti = cXinelibDevice::Instance().GetMetaInfo(miTitle); - const char *tr = cXinelibDevice::Instance().GetMetaInfo(miTracknumber); - const char *al = cXinelibDevice::Instance().GetMetaInfo(miAlbum); - const char *ar = cXinelibDevice::Instance().GetMetaInfo(miArtist); - if(ti && ti[0] && (!*m_Playlist.Current()->Title || !strstr(m_Playlist.Current()->Title, ti))) - m_Playlist.Current()->Title = ti; - if(tr && tr[0]) - m_Playlist.Current()->Tracknumber = tr; - if(al && al[0]) - m_Playlist.Current()->Album = al; - if(ar && ar[0]) - m_Playlist.Current()->Artist = ar; - - // cdda tracks - if(m_Playlist.Count() == 1 && !strcmp("cdda:/", m_Playlist.First()->Filename)) { - int count = cXinelibDevice::Instance().PlayFileCtrl("GETAUTOPLAYSIZE"); - if(count>1) { - for(int i=0; i10000 && pos < (len-10000)) { - pos = (pos/1000) - 10; // skip back 10 seconds ("VDR style") - if(0 <= (fd = open(m_ResumeFile, O_WRONLY | O_CREAT, - S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) { - if(write(fd, &pos, sizeof(int)) != sizeof(int)) { - Skins.QueueMessage(mtInfo, "Error writing resume position !", 5, 30); - } - close(fd); - } else { - Skins.QueueMessage(mtInfo, "Error creating resume file !", 5, 30); - } - } else { - unlink(m_ResumeFile); - } - m_ResumeFile = NULL; - } - cXinelibDevice::Instance().PlayFile(NULL,0); - m_Replaying = false; - } -} - -// -// cPlaylistMenu -// - - -class cPlaylistMenu : public cOsdMenu, cPlaylistChangeNotify -{ - protected: - - cPlaylist& m_Playlist; - bool m_NeedsUpdate; - bool& m_RandomPlay; - cIConv ic; - - public: - - cPlaylistMenu(cPlaylist &Playlist, bool& RandomPlay); - virtual ~cPlaylistMenu(); - - void Set(bool setCurrentPlaying = false); - void SetCurrentExt(int i); - void SetHelpButtons(void); - - // cOsdMenu - virtual eOSState ProcessKey(eKeys Key); - - // cPlaylistChangeNotify - virtual void PlaylistChanged(const cPlaylistItem *item); -}; - -cPlaylistMenu::cPlaylistMenu(cPlaylist &Playlist, bool& RandomPlay) : - cOsdMenu(tr("Playlist")), - m_Playlist(Playlist), - m_RandomPlay(RandomPlay), - ic() -{ - SetTitle(cString::sprintf("%s: %s", tr("Playlist"), *ic.Translate(Playlist.Name()))); - Playlist.Listen(this); - Set(true); -} - -cPlaylistMenu::~cPlaylistMenu() -{ - m_Playlist.Listen(NULL); -} - -void cPlaylistMenu::PlaylistChanged(const cPlaylistItem *item) -{ - m_NeedsUpdate = true; -} - -eOSState cPlaylistMenu::ProcessKey(eKeys Key) -{ - bool hadSubMenu = HasSubMenu(); - - if(m_NeedsUpdate) - Set(); - - eOSState state = cOsdMenu::ProcessKey(Key); - - if(state == osUnknown) { - switch(Key) { - case kBack: - return osEnd; - case kRed: - m_RandomPlay = !m_RandomPlay; - SetHelpButtons(); - return osContinue; - case kGreen: - return AddSubMenu(cMenuXinelib::CreateMenuBrowseFiles(ShowMusic)); - case kYellow: if(m_Playlist.Count() > 1) { - eOSState result = osContinue; - cPlaylistItem *i = m_Playlist.Current(); - if(i->Index() == Current()) { - if(i->Next()) - result = (eOSState)(os_User + i->Index()); /* forces jump to next item */ - else - result = (eOSState)(os_User + i->Index() - 1);/* forces jump to last item */ - } - for(i = m_Playlist.First(); i && i->Index() != Current(); i = m_Playlist.Next(i)); - if(i) - m_Playlist.Del(i); - if(Current() == Count()-1) - SetCurrent(Get(Current()-1)); - Set(); - return result; - } - case kBlue: - m_Playlist.Sort(); - Set(); - return osContinue; - default: break; - } - } - - if(hadSubMenu && !HasSubMenu()) - Set(); - - return state; -} - -void cPlaylistMenu::SetCurrentExt(int i) -{ - SetCurrent(Get(i)); - Set(); -} - -void cPlaylistMenu::SetHelpButtons(void) -{ - SetHelp(!m_RandomPlay ? tr("Button$Random") : tr("Button$Normal"), - tr("Button$Add files"), - m_Playlist.Count()>1 ? tr("Button$Remove") : NULL, - tr("Button$Sort")); - Display(); -} - -void cPlaylistMenu::Set(bool setCurrentPlaying) -{ - m_NeedsUpdate = false; - - int currentItem = Current(); - Clear(); - SetHasHotkeys(); - SetCols(2, 30); - SetHelpButtons(); - - int currentPlaying = m_Playlist.Current()->Index(); - int j = 0; - - for(cPlaylistItem *i = m_Playlist.First(); i; i = m_Playlist.Next(i), j++) { - cString Title = cPlaylist::GetEntry(i, true, j==currentPlaying); - Add(new cOsdItem( ic.Translate(Title), (eOSState)(os_User + j))); - } - - if(setCurrentPlaying) - SetCurrent(Get(currentPlaying)); - else - SetCurrent(Get(currentItem)); - - Display(); -} - - -// -// cXinelibPlayerControl -// - -#include - -cXinelibPlayer *cXinelibPlayerControl::m_Player = NULL; -cMutex cXinelibPlayerControl::m_Lock; - -cXinelibPlayerControl::cXinelibPlayerControl(eMainMenuMode Mode, const char *File, const char *SubFile) : - cControl(OpenPlayer(File, false, SubFile)) -{ - m_DisplayReplay = NULL; - m_PlaylistMenu = NULL; - m_ShowModeOnly = true; - m_Mode = Mode; - m_RandomPlay = false; - m_AutoShowStart = time(NULL); - m_BlinkState = true; - - number = 0; - lastTime.Set(); - - m_Player->m_UseResume = (Mode==ShowFiles); - - MsgReplaying(*m_Player->Playlist().Current()->Title, *m_Player->File()); -} - -cXinelibPlayerControl::~cXinelibPlayerControl() -{ - if(m_PlaylistMenu) { - delete m_PlaylistMenu; - m_PlaylistMenu = NULL; - } - if(m_DisplayReplay) { - delete m_DisplayReplay; - m_DisplayReplay = NULL; - } - - MsgReplaying(NULL, NULL); - Close(); -} - -void cXinelibPlayerControl::MsgReplaying(const char *Title, const char *File) -{ - cStatus::MsgReplaying(this, NULL, NULL, false); - if(Title || File) - cStatus::MsgReplaying(this, Title, File, true); -} - -void cXinelibPlayerControl::Queue(const char *File) -{ - if(!File) - return; - - m_Lock.Lock(); - - LOGMSG("cXinelibPlayerControl::Queue(%s)", File); - - if(!m_Player) { - OpenPlayer(File, true); - cControl::Launch(new cXinelibPlayerControl(ShowMusic, NULL)); - } else { - int len = strlen(File); - if(len && File[len-1] == '/') - m_Player->Playlist().Read(File, true); - else - m_Player->Playlist().Read(File); - } - - Skins.Message(mtInfo, tr("Queued to playlist")); - - m_Lock.Unlock(); - - if(m_Player->Playlist().Count() > 0) - m_Player->Playlist().StartScanner(); - -} - -cXinelibPlayer *cXinelibPlayerControl::OpenPlayer(const char *File, bool Queue, const char *SubFile) -{ - m_Lock.Lock(); - if(!m_Player) - m_Player = new cXinelibPlayer(File, Queue, SubFile); - m_Lock.Unlock(); - return m_Player; -} - -void cXinelibPlayerControl::Close(void) -{ - m_Lock.Lock(); - if(m_Player) - delete m_Player; - m_Player = NULL; - m_Lock.Unlock(); -} - -void cXinelibPlayerControl::Show() -{ - bool Play = (m_Player->Speed() > 0); - bool Forward = true; - int Speed = abs(m_Player->Speed()) - 2; - if(Speed<-1) Speed=-1; - - if(!m_DisplayReplay) { - if(cOsd::IsOpen()) - return; - m_DisplayReplay = Skins.Current()->DisplayReplay(m_ShowModeOnly); - } - - if(!m_ShowModeOnly) { - char t[128] = ""; - int Current = cXinelibDevice::Instance().PlayFileCtrl("GETPOS"); - int Total = cXinelibDevice::Instance().PlayFileCtrl("GETLENGTH"); - if(Current>=0) m_CurrentPos = Current; - if(Total>=0) m_CurrentLen = Total; - - if(m_CurrentLen >= 0 /*&& Total >= 0*/) { - Total = (m_CurrentLen + 500) / 1000; // ms --> s - Current = (m_CurrentPos + 500) / 1000; - - cString Title = cPlaylist::GetEntry(m_Player->Playlist().Current()); - cIConv ic; - m_DisplayReplay->SetTitle(ic.Translate(Title)); - - m_DisplayReplay->SetProgress(Current, Total); - sprintf(t, "%d:%02d:%02d", Total/3600, (Total%3600)/60, Total%60); - m_DisplayReplay->SetTotal( t ); - sprintf(t, "%d:%02d:%02d", Current/3600, (Current%3600)/60, Current%60); - m_BlinkState = (m_Player->Speed() != 0) || (!m_BlinkState); - m_DisplayReplay->SetCurrent( m_BlinkState ? t : ""); - } - } - - m_DisplayReplay->SetMode(Play, Forward, Speed); - - m_DisplayReplay->Flush(); -} - -void cXinelibPlayerControl::Hide() -{ - if(m_PlaylistMenu) { - delete m_PlaylistMenu; - m_PlaylistMenu = NULL; - } - if(m_DisplayReplay) { - delete m_DisplayReplay; - m_DisplayReplay = NULL; - } -} - -cOsdObject *cXinelibPlayerControl::GetInfo(void) -{ - /* ??? */ - return NULL; -} - -eOSState cXinelibPlayerControl::ProcessKey(eKeys Key) -{ - if (cXinelibDevice::Instance().EndOfStreamReached() || - !m_Player->Replaying() ) { - LOGDBG("cXinelibPlayerControl: EndOfStreamReached"); - LOGDBG("cXinelibPlayerControl: Replaying = %d", m_Player->Replaying()); - if (m_Mode == ShowMusic && m_Player->Files() == 1) { - m_Player->NextFile(0); - return osContinue; - } - int Jump = 1; - if(m_RandomPlay) { - srand((unsigned int)time(NULL)); - Jump = (random() % m_Player->Files()) - m_Player->CurrentFile(); - } - if(m_Player->Files() < 2 || !m_Player->NextFile(Jump)) { - Hide(); - return osEnd; - } - if(m_PlaylistMenu) { - m_PlaylistMenu->PlaylistChanged(m_Player->Playlist().Current()); - m_PlaylistMenu->SetCurrentExt(m_Player->CurrentFile()); - } - - if(!m_DisplayReplay) - m_AutoShowStart = time(NULL); - - MsgReplaying(*m_Player->Playlist().Current()->Title, *m_Player->File()); - } - - else { - // metainfo may change during playback (DVD titles, CDDA tracks) - const char *ti = cXinelibDevice::Instance().GetMetaInfo(miTitle); - if(ti && ti[0] && (!*m_Player->Playlist().Current()->Title || - !strstr(m_Player->Playlist().Current()->Title, ti))) { - const char *tr = cXinelibDevice::Instance().GetMetaInfo(miTracknumber); - const char *al = cXinelibDevice::Instance().GetMetaInfo(miAlbum); - const char *ar = cXinelibDevice::Instance().GetMetaInfo(miArtist); - LOGDBG("metainfo changed: %s->%s %s->%s %s->%s %s->%s", - *m_Player->Playlist().Current()->Artist?:"-", ar?:"-", - *m_Player->Playlist().Current()->Album ?:"-", al?:"-", - *m_Player->Playlist().Current()->Tracknumber ?:"-", tr?:"-", - *m_Player->Playlist().Current()->Title ?:"-", ti?:"-"); - m_Player->Playlist().Current()->Title = ti; - if(tr && tr[0]) - m_Player->Playlist().Current()->Tracknumber = tr; - if(al && al[0]) - m_Player->Playlist().Current()->Album = al; - if(ar && ar[0]) - m_Player->Playlist().Current()->Artist = ar; - MsgReplaying(*m_Player->Playlist().Current()->Title, *m_Player->File()); - } - } - - if(m_PlaylistMenu) { - m_AutoShowStart = 0; - - eOSState state = osUnknown; - - switch(state=m_PlaylistMenu->ProcessKey(Key)) { - case osBack: - case osEnd: Hide(); break; - default: if(state >= os_User) { - m_Player->NextFile( (int)state - (int)os_User - m_Player->CurrentFile()); - m_PlaylistMenu->SetCurrentExt(m_Player->CurrentFile()); - MsgReplaying(*m_Player->Playlist().Current()->Title, *m_Player->File()); - } - break; - } - - if(state != osUnknown) - return osContinue; - } - - if (m_DisplayReplay) - Show(); - - if ( m_Mode == ShowFiles ) { - switch(Key) { - case kRed: if(m_Player->Playlist().Count() > 1) { - Hide(); - m_PlaylistMenu = new cPlaylistMenu(m_Player->Playlist(), m_RandomPlay); - m_AutoShowStart = 0; - } else { - m_Player->Control("SEEK 0"); break; - } - break; - case kUser8: - case k1: m_Player->Control("SEEK -20"); break; - case kUser9: - case k3: m_Player->Control("SEEK +20"); break; - case k2: xc.subtitle_vpos -= 10; - case k5: xc.subtitle_vpos += 5; - m_Player->Control("SUBTITLES %d", xc.subtitle_vpos); - break; - case kRight: - { - static const int speeds[] = { -3, -2, 1, 2, -4, 2, 3, 4, 4 }; - m_Player->SetSpeed(speeds[m_Player->Speed() + 4]); - if(m_Player->Speed() != 1) - Show(); - else - Hide(); - break; - } - case kLeft: - { - static const int speeds[] = { 0, -4, -3, -2, 0, -2, 1, 2, 3 }; - m_Player->SetSpeed(speeds[m_Player->Speed() + 4]); - if(m_Player->Speed() != 1 || !m_ShowModeOnly) - Show(); - else - Hide(); - break; - } - default: break; - } - } - if ( m_Mode == ShowMusic ) { - switch(Key) { - case kRed: Hide(); - m_PlaylistMenu = new cPlaylistMenu(m_Player->Playlist(), m_RandomPlay); - m_AutoShowStart = 0; - break; - case kNext: - case kRight: if(m_RandomPlay) { - srand((unsigned int)time(NULL)); - m_Player->NextFile((random() % m_Player->Files()) - m_Player->CurrentFile()); - } - else { - m_Player->NextFile(1); - } - if(!m_DisplayReplay) - m_AutoShowStart = time(NULL); - MsgReplaying(*m_Player->Playlist().Current()->Title, *m_Player->File()); - break; - case kPrev: - case kLeft: if(cXinelibDevice::Instance().PlayFileCtrl("GETPOS") < 3000) { - m_Player->NextFile(-1); - if(!m_DisplayReplay) - m_AutoShowStart = time(NULL); - MsgReplaying(*m_Player->Playlist().Current()->Title, *m_Player->File()); - } - else { - m_Player->NextFile(0); - if(!m_DisplayReplay) - m_AutoShowStart = time(NULL); - } - break; - case k0 ... k9: - if (number >= 0) { - if (number * 10 + Key - k0 > m_Player->Files()) - number = m_Player->Files(); - else - number = number * 10 + Key - k0; - } - break; - case kNone: - if (number > 0 && int(lastTime.Elapsed()) > 3000) { - m_Player->NextFile( number - (m_Player->CurrentFile() + 1) ); - if (!m_DisplayReplay) - m_AutoShowStart = time(NULL); - MsgReplaying(*m_Player->Playlist().Current()->Title, *m_Player->File()); - number = 0; - lastTime.Set(); - } - break; - default: break; - } - } - switch(Key) { // key bindings common for both players - case kBack: xc.main_menu_mode = m_Mode; - Hide(); - BackToMenu(); - break; - case kStop: - case kBlue: Hide(); - Close(); - return osEnd; - case kUser7: if(m_Player->Playlist().Count()>1) { - m_RandomPlay = !m_RandomPlay; - if(m_RandomPlay) - Skins.Message(mtInfo, tr("Random play")); - else - Skins.Message(mtInfo, tr("Normal play")); - } - break; - case kGreen: m_Player->Control("SEEK -60"); break; - case kYellow: m_Player->Control("SEEK +60"); break; - case kUser8: m_Player->Control("SEEK -20"); break; - case kUser9: m_Player->Control("SEEK +20"); break; - case kDown: - case kPause: if(m_Player->Speed()) { - m_Player->SetSpeed(0); - if(!m_DisplayReplay) - m_ShowModeOnly = true; - Show(); - break; - } - // fall thru - case kUp: - case kPlay: m_Player->SetSpeed(1); - if(m_ShowModeOnly && m_DisplayReplay) - Hide(); - else if(m_DisplayReplay) - Show(); - m_ShowModeOnly = false; - break; - case kFastFwd: - { - static const int speeds[] = { -3, -2, 1, 2, -4, 2, 3, 4, 4 }; - m_Player->SetSpeed(speeds[m_Player->Speed() + 4]); - if(m_Player->Speed() != 1) - Show(); - else - Hide(); - break; - } - case kFastRew: - { - static const int speeds[] = { 0, -4, -3, -2, 0, -2, 1, 2, 3 }; - m_Player->SetSpeed(speeds[m_Player->Speed() + 4]); - if(m_Player->Speed() != 1 || !m_ShowModeOnly) - Show(); - else - Hide(); - break; - } - case kOk: - m_AutoShowStart = 0; - if(m_Player->Speed() != 1) { - Hide(); - m_ShowModeOnly = !m_ShowModeOnly; - Show(); - } else { - if(m_DisplayReplay) { - m_ShowModeOnly = true; - Hide(); - } else { - Hide(); - m_ShowModeOnly = false; - Show(); - } - } - break; - default: break; - } - - if(m_DisplayReplay && - m_AutoShowStart && - time(NULL) - m_AutoShowStart > 5) { - m_AutoShowStart = 0; - Hide(); - } - - if(!m_DisplayReplay && - m_AutoShowStart) { - m_ShowModeOnly = false; - Show(); - } - - return osContinue; -} - -// -// cDvdMenu -// - -class cDvdMenu : public cOsdMenu { - public: - cDvdMenu(void) : cOsdMenu("DVD Menu") - { - Add(new cOsdItem("Exit DVD menu", osUser1)); - Add(new cOsdItem("DVD Root menu", osUser2)); - Add(new cOsdItem("DVD Title menu", osUser3)); - Add(new cOsdItem("DVD SPU menu", osUser4)); - Add(new cOsdItem("DVD Audio menu", osUser5)); - Add(new cOsdItem("Close menu", osEnd)); - Display(); - } -}; - - -// -// cXinelibDvdPlayerControl -// - -cXinelibDvdPlayerControl::~cXinelibDvdPlayerControl() -{ - if(Menu) { - delete Menu; - Menu = NULL; - } -} - -void cXinelibDvdPlayerControl::Hide(void) -{ - if(Menu) { - delete Menu; - Menu = NULL; - } - cXinelibPlayerControl::Hide(); -} - -void cXinelibDvdPlayerControl::Show(void) -{ - if(!Menu) - cXinelibPlayerControl::Show(); - else - cXinelibPlayerControl::Hide(); -} - -eOSState cXinelibDvdPlayerControl::ProcessKey(eKeys Key) -{ - if (cXinelibDevice::Instance().EndOfStreamReached()) { - Hide(); - return osEnd; - } - else { - const char *ti = cXinelibDevice::Instance().GetMetaInfo(miTitle); - if (ti && ti[0] && (!m_CurrentDVDTitle || !strstr(m_CurrentDVDTitle, ti))) { - memset(m_CurrentDVDTitle, 0, 63); - strn0cpy(m_CurrentDVDTitle, ti, 63); - m_Player->Playlist().Current()->Title = m_CurrentDVDTitle; - MsgReplaying(m_CurrentDVDTitle, NULL); - } - } - - if(Menu) { - if(Key == kRed) - Hide(); - else switch(Menu->ProcessKey(Key)) { - case osUser1: Hide(); m_Player->Control("EVENT XINE_EVENT_INPUT_MENU1"); break; - case osUser2: Hide(); m_Player->Control("EVENT XINE_EVENT_INPUT_MENU2"); break; - case osUser3: Hide(); m_Player->Control("EVENT XINE_EVENT_INPUT_MENU3"); break; - case osUser4: Hide(); m_Player->Control("EVENT XINE_EVENT_INPUT_MENU4"); break; - case osUser5: Hide(); m_Player->Control("EVENT XINE_EVENT_INPUT_MENU5"); break; - case osBack: - case osEnd: Hide(); break; - default: break; - } - return osContinue; - } - - if (m_DisplayReplay) - Show(); - - bool MenuDomain = false; - if(Key != kNone || m_DisplayReplay) { - const char *dt = cXinelibDevice::Instance().GetMetaInfo(miDvdTitleNo); - if(dt && !strcmp("0", dt)) - MenuDomain = true; - } - - if(MenuDomain) { - if(m_DisplayReplay) - Hide(); - - switch(Key) { - // DVD navigation - case kUp: m_Player->Control("EVENT XINE_EVENT_INPUT_UP"); return osContinue; - case kDown: m_Player->Control("EVENT XINE_EVENT_INPUT_DOWN"); return osContinue; - case kLeft: m_Player->Control("EVENT XINE_EVENT_INPUT_LEFT"); return osContinue; - case kRight: m_Player->Control("EVENT XINE_EVENT_INPUT_RIGHT"); return osContinue; - case kOk: m_Player->Control("EVENT XINE_EVENT_INPUT_SELECT"); return osContinue; - case kBack: m_Player->Control("EVENT XINE_EVENT_INPUT_MENU1"); return osContinue; - default: break; - } - } - - if(!MenuDomain) { - switch(Key) { - // Replay control - case kUp: Key = kPlay; break; - case kDown: Key = kPause; break; - case kLeft: Key = kFastRew; break; - case kRight: Key = kFastFwd; break; - case kOk: - if(m_Player->Speed() != 1) { - Hide(); - m_ShowModeOnly = !m_ShowModeOnly; - Show(); - break; - } - if(m_DisplayReplay) { - Hide(); - m_ShowModeOnly = true; - } else { - Hide(); - m_ShowModeOnly = false; - Show(); - } - break; - case kInfo: Hide(); - if(m_DisplayReplay && !m_ShowModeOnly) { - m_ShowModeOnly = true; - } else { - m_ShowModeOnly = false; - Show(); - } - break; - case kBack: xc.main_menu_mode = m_Mode; - Hide(); - Close(); - return osEnd; - default: break; - } - } - - switch(Key) { - // DVD menus - case kRed: Hide(); - Menu = new cDvdMenu(); - break; -#if VDRVERSNUM < 10515 - // SPU channel - case k5: cXinelibDevice::Instance().SetCurrentDvdSpuTrack( - cXinelibDevice::Instance().GetCurrentDvdSpuTrack() - 2); - case k2: cRemote::CallPlugin("xineliboutput"); - cRemote::Put(kRed); /* shortcut key */ - cRemote::Put(k2); - break; -#endif - // Playback control - case kGreen: m_Player->Control("SEEK -60"); break; - case kYellow: m_Player->Control("SEEK +60"); break; - case kUser8: - case k1: m_Player->Control("SEEK -20"); break; - case kUser9: - case k3: m_Player->Control("SEEK +20"); break; - - case kStop: - case kBlue: Hide(); - Close(); - return osEnd; - - case k9: m_Player->Control("EVENT XINE_EVENT_INPUT_NEXT TITLE"); break; - case k7: m_Player->Control("EVENT XINE_EVENT_INPUT_PREVIOUS TITLE"); break; - case k6: - case kNext: m_Player->Control("EVENT XINE_EVENT_INPUT_NEXT CHAPTER"); break; - case k4: - case kPrev: m_Player->Control("EVENT XINE_EVENT_INPUT_PREVIOUS CHAPTER"); break; - - case kFastFwd: - { - static const int speeds[] = { -3, -2, 1, 2, -4, 2, 3, 4, 4 }; - m_Player->SetSpeed(speeds[m_Player->Speed() + 4]); - if(m_Player->Speed() != 1) - Show(); - else - Hide(); - break; - } - case kFastRew: - { - static const int speeds[] = { 0, -4, -3, -2, 0, -2, 1, 2, 3 }; - m_Player->SetSpeed(speeds[m_Player->Speed() + 4]); - if(m_Player->Speed() != 1 || !m_ShowModeOnly) - Show(); - else - Hide(); - break; - } - case kInfo: if(m_DisplayReplay) { - Hide(); - } else { - m_ShowModeOnly = false; - Show(); - } - break; - case kPause: if(m_Player->Speed()) { - m_Player->SetSpeed(0); - m_ShowModeOnly = false; - Show(); - break; - } - // fall thru - case kPlay: m_Player->SetSpeed(1); - m_ShowModeOnly = true; - Hide(); - break; - default: break; - } - - return osContinue; -} - -// -// cXinelibImagePlayer -// - -class cXinelibImagePlayer : public cPlayer { - private: - cString m_File; - bool m_Active; - - protected: - virtual void Activate(bool On); - - public: - cXinelibImagePlayer(const char *File); - virtual ~cXinelibImagePlayer(); - - bool ShowImage(const char *File); -}; - -cXinelibImagePlayer::cXinelibImagePlayer(const char *File) -{ - m_File = File; - m_Active = false; -} - -cXinelibImagePlayer::~cXinelibImagePlayer() -{ - Activate(false); - Detach(); -} - -void cXinelibImagePlayer::Activate(bool On) -{ - if(On) { - m_Active = true; - cXinelibDevice::Instance().PlayFile(*cString::sprintf("file:%s", *cPlaylist::EscapeMrl(m_File)), 0, true); - } else { - m_Active = false; - cXinelibDevice::Instance().PlayFile(NULL, 0); - } -} - -bool cXinelibImagePlayer::ShowImage(const char *File) -{ - m_File = File; - if(m_Active) - return cXinelibDevice::Instance().PlayFile(*cString::sprintf("file:%s", *cPlaylist::EscapeMrl(m_File)), 0, true); - return true; -} - - -// -// cXinelibImagesControl -// - -cXinelibImagePlayer *cXinelibImagesControl::m_Player = NULL; -cMutex cXinelibImagesControl::m_Lock; - -cXinelibImagesControl::cXinelibImagesControl(char **Files, int Index, int Count) : - cControl(OpenPlayer(Files[Index])) -{ - m_DisplayReplay = NULL; - m_Files = Files; - m_File = NULL; - m_Index = Index; - m_Count = Count; - m_Speed = 0; - m_ShowModeOnly = false; - - Seek(0); -} - -cXinelibImagesControl::~cXinelibImagesControl() -{ - if(m_DisplayReplay) - delete m_DisplayReplay; - m_DisplayReplay = NULL; - - cStatus::MsgReplaying(this, NULL, NULL, false); - Close(); - - if(m_Files) { - int i=0; - while(m_Files[i]) { - free(m_Files[i]); - m_Files[i] = NULL; - i++; - } - delete [] m_Files; - m_Files = NULL; - } -} - -cXinelibImagePlayer *cXinelibImagesControl::OpenPlayer(const char *File) -{ - m_Lock.Lock(); - if(!m_Player) - m_Player = new cXinelibImagePlayer(File); - m_Lock.Unlock(); - return m_Player; -} - -void cXinelibImagesControl::Close(void) -{ - m_Lock.Lock(); - if(m_Player) - delete m_Player; - m_Player = NULL; - m_Lock.Unlock(); -} - -void cXinelibImagesControl::Delete(void) -{ - if(Interface->Confirm(tr("Delete image ?"))) { - if(!unlink(m_Files[m_Index])) { - free(m_Files[m_Index]); - for(int i=m_Index; i0) - m_Index = 0; - else if(m_Index == 0 && Rel<0) - m_Index = m_Count-1; - else - m_Index += Rel; - - if(m_Index < 0) - m_Index = 0; - else if(m_Index >= m_Count) - m_Index = m_Count; - - char *pt; - free(m_File); - m_File = strdup(m_Files[m_Index]); - if(NULL != (pt=strrchr(m_File, '/'))) - strcpy(m_File, pt+1); - if(NULL != (pt=strrchr(m_File, '.'))) - *pt = 0; - - cStatus::MsgReplaying(this, m_File, m_Files[m_Index], true); - - m_Player->ShowImage(m_Files[m_Index]); - m_LastShowTime = time(NULL); - strn0cpy(xc.browse_images_dir, m_Files[m_Index], sizeof(xc.browse_images_dir)); -} - -void cXinelibImagesControl::Show(void) -{ - bool Play = (m_Speed!=0), Forward = m_Speed>=0; - int Speed = abs(m_Speed); - - if(!m_DisplayReplay) { - m_DisplayReplay = Skins.Current()->DisplayReplay(m_ShowModeOnly); - } - - if(!m_ShowModeOnly) { - char t[128] = ""; - m_DisplayReplay->SetTitle(m_File); - m_DisplayReplay->SetProgress(m_Index, m_Count); - sprintf(t, "%d", m_Count); - m_DisplayReplay->SetTotal( t ); - sprintf(t, "%d", m_Index+1); - m_DisplayReplay->SetCurrent( t ); - } - - m_DisplayReplay->SetMode(Play, Forward, Speed); - m_DisplayReplay->Flush(); -} - -void cXinelibImagesControl::Hide(void) -{ - if(m_DisplayReplay) { - delete m_DisplayReplay; - m_DisplayReplay = NULL; - } -} - -eOSState cXinelibImagesControl::ProcessKey(eKeys Key) -{ - switch(Key) { - case kBack: xc.main_menu_mode = ShowImages; - Hide(); - Close(); - BackToMenu(); - //return osPlugin; - return osEnd; - case kYellow: Delete(); - break; - case kStop: - case kBlue: Hide(); - Close(); - return osEnd; - case kPrev: - case kLeft: Seek(-1); - break; - case kNext: - case kRight: Seek(1); - break; - case kUp: Seek(5); - break; - case kDown: Seek(-5); - break; - case kPause: m_Speed = 0; - break; - case kPlay: m_Speed = 2; - break; - case kFastFwd: m_Speed++; - break; - case kFastRew: m_Speed--; - break; - case kOk: if(m_DisplayReplay) { - if(m_ShowModeOnly) { - Hide(); - m_ShowModeOnly = false; - Show(); - } else { - Hide(); - } - } else { - m_ShowModeOnly = true; - Show(); - } - break; - default: break; - } - - static const int Speed2Time[] = { 0, 5, 3, 1 }; - if(m_Speed > 3) - m_Speed = 3; - if(m_Speed < -3) - m_Speed = -3; - - if(Key == kNone && m_Speed != 0) { - if(m_LastShowTime + Speed2Time[m_Speed<0 ? -m_Speed : m_Speed] <= time(NULL)) - Seek(sgn(m_Speed)); - } - - if (m_DisplayReplay) - Show(); - - return osContinue; -} diff --git a/media_player.h b/media_player.h deleted file mode 100644 index 1ae6ed83..00000000 --- a/media_player.h +++ /dev/null @@ -1,125 +0,0 @@ -/* - * media_player.h: Media and image players - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: media_player.h,v 1.15 2008-01-10 23:41:24 phelin Exp $ - * - */ - -#ifndef __XINELIB_PLAYER_H -#define __XINELIB_PLAYER_H - -#include - -#include "config.h" - -// --- Media player --------------------------------------------------------- - -class cXinelibPlayer; -class cSkinDisplayReplay; -class cPlaylistMenu; - -class cXinelibPlayerControl : public cControl -{ - private: - static cMutex m_Lock; - - static cXinelibPlayer *OpenPlayer(const char *File, bool Queue = false, const char *SubFile = NULL); - - protected: - static cXinelibPlayer *m_Player; - - cSkinDisplayReplay *m_DisplayReplay; - cPlaylistMenu *m_PlaylistMenu; - - eMainMenuMode m_Mode; - bool m_ShowModeOnly; - bool m_RandomPlay; - time_t m_AutoShowStart; - int m_CurrentPos; - int m_CurrentLen; - bool m_BlinkState; - - cTimeMs lastTime; - int number; - - void MsgReplaying(const char *Title, const char *File); - - public: - cXinelibPlayerControl(eMainMenuMode Mode, const char *File, const char *SubFile = NULL); - virtual ~cXinelibPlayerControl(); - - virtual void Show(void); - virtual void Hide(void); - virtual eOSState ProcessKey(eKeys Key); - - virtual cOsdObject *GetInfo(void); - - static void Close(void); - static bool IsOpen(void) { return m_Player != NULL; }; - static void Queue(const char *File); -}; - - -// --- DVD player ----------------------------------------------------------- - -class cDvdMenu; -class cXinelibDvdPlayerControl : public cXinelibPlayerControl -{ - private: - cDvdMenu *Menu; - char m_CurrentDVDTitle[63]; - - public: - cXinelibDvdPlayerControl(const char *File) : - cXinelibPlayerControl(ShowFiles, File), Menu(NULL) - {} - virtual ~cXinelibDvdPlayerControl(); - - virtual void Show(void); - virtual void Hide(void); - virtual eOSState ProcessKey(eKeys Key); -}; - -// --- Image player --------------------------------------------------------- - -class cXinelibImagePlayer; - -class cXinelibImagesControl : public cControl -{ - private: - static cXinelibImagePlayer *m_Player; - static cMutex m_Lock; - - cSkinDisplayReplay *m_DisplayReplay; - - char **m_Files; - char *m_File; - int m_Index; - int m_Count; - int m_Speed; - int m_LastShowTime; - bool m_ShowModeOnly; - - static cXinelibImagePlayer *OpenPlayer(const char *File); - - protected: - void Seek(int Rel); - void Delete(void); - - public: - cXinelibImagesControl(char **Files, int Index, int Count); - virtual ~cXinelibImagesControl(); - - virtual void Show(void); - virtual void Hide(void); - virtual eOSState ProcessKey(eKeys Key); - - static void Close(void); - static bool IsOpen(void) { return m_Player != NULL; } -}; - -#endif // __XINELIB_PLAYER_H - diff --git a/menu.c b/menu.c deleted file mode 100644 index 0a379823..00000000 --- a/menu.c +++ /dev/null @@ -1,1089 +0,0 @@ -/* - * menu.c: Main Menu - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: menu.c,v 1.54 2008-04-13 23:07:25 phintuka Exp $ - * - */ - -#include - -#ifdef HAVE_EXTRACTOR_H -# include -#endif - -#include -#include -#include -#include -#include - -#include "logdefs.h" -#include "config.h" -#include "menu.h" -#include "menuitems.h" -#include "device.h" -#include "media_player.h" -#include "equalizer.h" -#include "i18n.h" // trVDR for VDR-1.4.x - -#ifndef HOTKEY_START -# define HOTKEY_START kRed - -# define HOTKEY_DVD k0 /* */ -# define HOTKEY_DVD_TRACK1 k1 /* */ -# define HOTKEY_DVD_SPU k2 /* */ - -# define HOTKEY_NEXT_ASPECT k3 /* auto, 4:3, 16:9 */ -# define HOTKEY_TOGGLE_CROP k4 /* off, force, auto */ -# define HOTKEY_UPMIX k5 /* off, on */ -# define HOTKEY_DOWNMIX k6 /* off, on */ -# define HOTKEY_DEINTERLACE k7 /* off, on */ -# define HOTKEY_LOCAL_FE k8 /* off, on */ - -# define HOTKEY_PLAYLIST k9 /* Start replaying playlist or file pointed by - symlink $(CONFDIR)/plugins/xineliboutput/default_playlist */ -# define HOTKEY_ADELAY_UP kUp /* audio delay up */ -# define HOTKEY_ADELAY_DOWN kDown /* audio delay down */ -# define HOTKEY_TOGGLE_VO_ASPECT kRight -#endif - -//#define OLD_TOGGLE_FE - -#define ISNUMBERKEY(k) (RAWKEY(k) >= k0 && RAWKEY(k) <= k9) - -//--------------------------- cMenuBrowseFiles ------------------------------- - -class cMenuBrowseFiles : public cOsdMenu -{ - protected: - const eMainMenuMode m_Mode; - bool m_OnlyQueue; - char *m_CurrentDir; - char *m_ConfigLastDir; - - virtual bool ScanDir(const char *DirName); - virtual eOSState Open(bool ForceOpen = false, bool Parent = false, bool Queue = false); - virtual eOSState Delete(void); - virtual eOSState Info(void); - virtual void Set(void); - virtual void SetHelpButtons(void); - cFileListItem *GetCurrent() { return (cFileListItem *)Get(Current()); } - void StoreConfig(void); - char *GetLastDir(void); - - public: - cMenuBrowseFiles(eMainMenuMode mode = ShowFiles, bool OnlyQueue=false); - ~cMenuBrowseFiles(); - - virtual eOSState ProcessKey(eKeys Key); -}; - -static char *ParentDir(const char *dir) -{ - char *result = strdup(dir); - char *pt = strrchr(result, '/'); - if(pt) { - *(pt+1)=0; - if(pt != result) - *pt = 0; - } - return result; -} - -static char *LastDir(const char *dir) -{ - char *pt = strrchr(dir, '/'); - if(pt && pt[0] && pt[1]) - return strdup(pt+1); - return NULL; -} - -cMenuBrowseFiles::cMenuBrowseFiles(eMainMenuMode mode, bool OnlyQueue) : - cOsdMenu( ( mode==ShowImages ? tr("Images") : - mode==ShowMusic ? (!OnlyQueue ? tr("Play music") : tr("Add to playlist")) : - /*mode==ShowFiles ?*/ tr("Play file")), - 2, 4), - m_Mode(mode) -{ - m_CurrentDir = NULL; - m_OnlyQueue = OnlyQueue; - - m_ConfigLastDir = GetLastDir(); - Set(); -} - -cMenuBrowseFiles::~cMenuBrowseFiles() -{ - Setup.Save(); - free(m_CurrentDir); -} - -char *cMenuBrowseFiles::GetLastDir(void) -{ - switch(m_Mode) { - case ShowMusic: return xc.browse_music_dir; - case ShowImages: return xc.browse_images_dir; - default: - case ShowFiles: return xc.browse_files_dir; - } - return xc.browse_files_dir; -} - -void cMenuBrowseFiles::Set(void) -{ - Clear(); - - if(!m_CurrentDir) - m_CurrentDir = strdup(m_ConfigLastDir); - - if(m_CurrentDir[0] != '/') { - free(m_CurrentDir); - m_CurrentDir = strdup(VideoDirectory); - } - - // find deepest accessible directory from path - while(!ScanDir(m_CurrentDir) && strlen(m_CurrentDir) > 1) { - char *n = ParentDir(m_CurrentDir); - free(m_CurrentDir); - m_CurrentDir = n; - } - - // add link to parent folder - if(strlen(m_CurrentDir) > 1) - Add(new cFileListItem("..",true)); - - Sort(); - - SetCurrent(Get(Count()>1 && strlen(m_CurrentDir)>1 ? 1 : 0)); - - // select last selected item - - char *lastParent = ParentDir(m_ConfigLastDir); - if(!strncmp(m_CurrentDir,lastParent,strlen(m_CurrentDir))) { - char *item = LastDir(m_ConfigLastDir); - if(item) { - for(cFileListItem *it = (cFileListItem*)First(); it; it = (cFileListItem*)Next(it)) - if(!strcmp(it->Name(),item)) - SetCurrent(it); - free(item); - } - } - free(lastParent); - - strn0cpy(m_ConfigLastDir, m_CurrentDir, sizeof(xc.browse_files_dir)); - StoreConfig(); - - SetHelpButtons(); -} - -void cMenuBrowseFiles::StoreConfig(void) -{ - cPluginManager::GetPlugin(PLUGIN_NAME_I18N)->SetupStore("Media.BrowseMusicDir", - xc.browse_music_dir); - cPluginManager::GetPlugin(PLUGIN_NAME_I18N)->SetupStore("Media.BrowseFilesDir", - xc.browse_files_dir); - cPluginManager::GetPlugin(PLUGIN_NAME_I18N)->SetupStore("Media.BrowseImagesDir", - xc.browse_images_dir); -#if 1 - cPluginManager::GetPlugin(PLUGIN_NAME_I18N)->SetupStore("Media.CacheImplicitPlaylists", - xc.cache_implicit_playlists); - cPluginManager::GetPlugin(PLUGIN_NAME_I18N)->SetupStore("Media.EnableID3Scanner", - xc.enable_id3_scanner); -#endif -} - -void cMenuBrowseFiles::SetHelpButtons(void) -{ - bool isDir = !GetCurrent() || GetCurrent()->IsDir(); - bool isDvd = GetCurrent() && GetCurrent()->IsDvd(); - SetHelp((isDir && isDvd) ? trVDR("Button$Open") : !m_OnlyQueue ? trVDR("Button$Play"): NULL, - (m_Mode == ShowMusic) ? tr("Button$Queue") : - strlen(m_CurrentDir)>1 ? "[..]" : NULL, - (isDir && !isDvd) ? NULL : trVDR("Button$Delete"), - isDir ? NULL : trVDR("Button$Info")); - Display(); -} - -eOSState cMenuBrowseFiles::Delete(void) -{ - cFileListItem *it = GetCurrent(); - if(!it->IsDir()) { - if (Interface->Confirm(trVDR("Delete recording?"))) { - cString name = cString::sprintf("%s/%s", m_CurrentDir, it->Name()); - if(!unlink(name)) { - isyslog("file %s deleted", *name); - if(m_Mode != ShowImages) { - name = cString::sprintf("%s.resume", *name); - unlink(name); - } - cOsdMenu::Del(Current()); - SetHelpButtons(); - Display(); - } else { - Skins.Message(mtError, trVDR("Error while deleting recording!")); - isyslog("Error deleting file %s", *name); - } - } - } - return osContinue; -} - -eOSState cMenuBrowseFiles::Open(bool ForceOpen, bool Parent, bool Queue) -{ - if(!GetCurrent()) { - return osContinue; - } - - /* parent directory */ - if(Parent || !strcmp("..", GetCurrent()->Name())) { - char *n = ParentDir(m_CurrentDir); - free(m_CurrentDir); - m_CurrentDir = n; - Set(); - return osContinue; - - /* directory */ - } else if (GetCurrent()->IsDir()) { - - if(!ForceOpen && GetCurrent()->IsDvd()) { - /* play dvd */ - cString f = cString::sprintf("dvd:%s/%s", m_CurrentDir, GetCurrent()->Name()); - cControl::Shutdown(); - cControl::Launch(new cXinelibDvdPlayerControl(f)); - return osEnd; - } - if(ForceOpen && GetCurrent()->IsDir() && !GetCurrent()->IsDvd()) { - /* play all files */ - if(m_Mode != ShowImages) { - - if(m_OnlyQueue && !Queue) - return osContinue; - - cString f = cString::sprintf("%s/%s/", m_CurrentDir, GetCurrent()->Name()); - - if(!Queue || !cXinelibPlayerControl::IsOpen()) - cControl::Shutdown(); - if(Queue) - cXinelibPlayerControl::Queue(f); - else - cControl::Launch(new cXinelibPlayerControl(m_Mode, f)); - return Queue ? osContinue : osEnd; - - } else { - // TODO: show all images - } - } - const char *d = GetCurrent()->Name(); - char *buffer = NULL; - asprintf(&buffer, "%s/%s", m_CurrentDir, d); - while(buffer[0] == '/' && buffer[1] == '/') - strcpy(buffer, buffer+1); - free(m_CurrentDir); - m_CurrentDir = buffer; - Set(); - return osContinue; - - /* regular file */ - } else { - cString f = cString::sprintf("%s%s/%s", - GetCurrent()->IsDvd() ? "dvd:" : "", - m_CurrentDir, GetCurrent()->Name()); - if (GetCurrent()->IsDvd()) - strn0cpy(m_ConfigLastDir, m_CurrentDir, sizeof(xc.browse_files_dir)); - else - strn0cpy(m_ConfigLastDir, f, sizeof(xc.browse_files_dir)); - StoreConfig(); - - if(m_Mode != ShowImages) { - /* video/audio */ - if(m_OnlyQueue && !Queue) - return osContinue; - if(!Queue || !cXinelibPlayerControl::IsOpen()) - cControl::Shutdown(); - if(Queue) - cXinelibPlayerControl::Queue(f); - if(!cXinelibPlayerControl::IsOpen()) - cControl::Launch(GetCurrent()->IsDvd() - ? new cXinelibDvdPlayerControl(f) - : new cXinelibPlayerControl(m_Mode, f, GetCurrent()->SubFile())); - if(Queue) - return osContinue; - } else { - /* image */ - char **files = new char*[Count()+1]; - int i = 0, index = 0; - memset(files, 0, sizeof(char*)*(Count()+1)); - for(cFileListItem *it = (cFileListItem*)First(); it; it=(cFileListItem*)Next(it)) { - if(it==Get(Current())) - index = i; - if(!it->IsDir()) - asprintf(&files[i++], "%s/%s", m_CurrentDir, it->Name()); - } - cControl::Shutdown(); - cControl::Launch(new cXinelibImagesControl(files, index, i)); - } - return osEnd; - } - return osContinue; -} - -eOSState cMenuBrowseFiles::Info(void) -{ - if(GetCurrent() && !GetCurrent()->IsDir()) { -#ifdef HAVE_EXTRACTOR_H - cString filename = cString::sprintf("%s/%s", m_CurrentDir, GetCurrent()->Name()); - EXTRACTOR_ExtractorList * plugins; - EXTRACTOR_KeywordList * md_list; - plugins = EXTRACTOR_loadDefaultLibraries(); - md_list = EXTRACTOR_getKeywords(plugins, *filename); - const char *key; - char * buf; - char metadata[4096]; - strcpy(metadata, ""); - while(md_list) { - if((key=EXTRACTOR_getKeywordTypeAsString(md_list->keywordType))) { - buf = strdup(md_list->keyword); - sprintf(metadata, "%s%s: %s\n", metadata, key, buf); - free(buf); - } - md_list=md_list->next; - } - EXTRACTOR_freeKeywords(md_list); - EXTRACTOR_removeAll(plugins); /* unload plugins */ - return AddSubMenu(new cMenuText(GetCurrent()->Name(), metadata)); -#else - cString cmd = cString::sprintf("'%s/%s'", m_CurrentDir, GetCurrent()->Name()); - if(xc.IsPlaylistFile(GetCurrent()->Name())) - cmd = cString::sprintf("file -b %s; cat %s", *cmd, *cmd); - else if(xc.IsAudioFile(GetCurrent()->Name())) - cmd = cString::sprintf("mp3info -x %s ; file -b %s", *cmd, *cmd); - else if(xc.IsVideoFile(GetCurrent()->Name())) - cmd = cString::sprintf("file -b %s; midentify %s", *cmd, *cmd); - else if(xc.IsImageFile(GetCurrent()->Name())) - cmd = cString::sprintf("file -b %s; identify %s", *cmd, *cmd); - else - cmd = cString::sprintf("file -b %s", *cmd); - - cPipe p; - if(p.Open(*cmd, "r")) { - char buf[4096]; - int n = fread(buf, 1, sizeof(buf)-1, p); - if(n>0) { - buf[n] = 0; - strreplace(buf, ',', '\n'); - return AddSubMenu(new cMenuText(GetCurrent()->Name(), buf)); - } - } -#endif - } - - return osContinue; -} - -bool cMenuBrowseFiles::ScanDir(const char *DirName) -{ - DIR *d = opendir(DirName); - if (d) { - struct dirent *e; - while ((e = readdir(d)) != NULL) { - if (strcmp(e->d_name, ".") && strcmp(e->d_name, "..")) { - cString buffer = cString::sprintf("%s/%s", DirName, e->d_name); - struct stat st; - if (stat(buffer, &st) == 0) { - - // check symlink destination - if (S_ISLNK(st.st_mode)) { - buffer = ReadLink(buffer); - if (!*buffer || stat(buffer, &st)) - continue; - } - - // folders - if (S_ISDIR(st.st_mode)) { - - if(m_Mode == ShowImages || m_Mode == ShowMusic) - Add(new cFileListItem(e->d_name, true)); - else { - // check if DVD - bool dvd = false; - buffer = cString::sprintf("%s/%s/VIDEO_TS/VIDEO_TS.IFO", DirName, e->d_name); - if (stat(buffer, &st) == 0) - dvd = true; - else { - buffer = cString::sprintf("%s/%s/video_ts/video_ts.ifo", DirName, e->d_name); - if (stat(buffer, &st) == 0) - dvd = true; - } - Add(new cFileListItem(e->d_name, true, false, false, dvd)); - } - - // regular files - } else if(e->d_name[0] != '.') { - - // audio - if (m_Mode == ShowMusic && xc.IsAudioFile(buffer)) { - Add(new cFileListItem(e->d_name, false)); - - // images - } else if(m_Mode == ShowImages && xc.IsImageFile(buffer)) { - Add(new cFileListItem(e->d_name, false)); - - // video - } else if (m_Mode == ShowFiles && xc.IsVideoFile(buffer)) { - bool resume = false, subs = false, dvd = false; - char *pos = strrchr(e->d_name, '.'); - cString subfile; - - if(pos) { - // .iso image -> dvd - if(pos && !strcasecmp(pos, ".iso")) - dvd = true; - - // separate subtitles ? - subfile = cString::sprintf("%s/%s____", DirName, e->d_name); - char *p = strrchr(subfile, '.'); - if( p ) { - int i; - for(i=0; xc.s_subExts[i] && !subs; i++) { - strcpy(p, xc.s_subExts[i]); - if (stat(subfile, &st) == 0) - subs = true; - } - } - } - - // resume file ? - buffer = cString::sprintf("%s/%s.resume", DirName, e->d_name); - if (stat(buffer, &st) == 0) - resume = true; - - Add(new cFileListItem(e->d_name, false, resume, subs?*subfile:NULL, dvd)); - } - } - } - } - } - closedir(d); - return true; - } - return false; -} - -eOSState cMenuBrowseFiles::ProcessKey(eKeys Key) -{ - eOSState state = cOsdMenu::ProcessKey(Key); - - if (state == osUnknown) { - switch (Key) { - case kPlay: - case kOk: return Open(false, false, m_OnlyQueue); - case kRed: return Open(true); - case kGreen: return Open(true, m_Mode != ShowMusic, - m_Mode==ShowMusic ? m_OnlyQueue=true : false); - case kYellow: return Delete(); - case kBlue: return Info(); - default: break; - } - } - - if (state == osUnknown) - state = osContinue; - - if(!HasSubMenu()) - SetHelpButtons(); - - return state; -} - - -#if VDRVERSNUM < 10515 - -//-------------------------- cDisplaySpuTracks ------------------------------ -// -// cDisplaySpuTracks : almost identical copy of VDR 1.4.5 cDisplayTracks -// - -#define TRACKTIMEOUT 5000 //ms - -class cDisplaySpuTracks : public cOsdObject { -private: - cSkinDisplayTracks *displayTracks; - cTimeMs timeout; - eTrackType types[64+2]; - char *descriptions[64+2]; - int numTracks, track; - static cDisplaySpuTracks *currentDisplayTracks; - virtual void Show(void); - cDisplaySpuTracks(void); -public: - virtual ~cDisplaySpuTracks(); - static bool IsOpen(void) { return currentDisplayTracks != NULL; } - static cDisplaySpuTracks *Create(void); - static void Process(eKeys Key); - eOSState ProcessKey(eKeys Key); - }; - -cDisplaySpuTracks *cDisplaySpuTracks::currentDisplayTracks = NULL; - -cDisplaySpuTracks::cDisplaySpuTracks(void) : cOsdObject(true) -{ - currentDisplayTracks = this; - numTracks = track = 0; - int CurrentTrack = cXinelibDevice::Instance().GetCurrentDvdSpuTrack(); - - track = numTracks; - types[numTracks] = eTrackType(ttXSubtitleNone); - descriptions[numTracks] = strdup("(none)"); - numTracks++; - - for (int i = 0; i <= 63; i++) { - const tTrackId *TrackId = cXinelibDevice::Instance().GetDvdSpuTrack(i); - if (TrackId) { - types[numTracks] = eTrackType(i); - descriptions[numTracks] = strdup(*TrackId->description ? TrackId->description : *TrackId->language ? TrackId->language : *itoa(i)); - if (i == CurrentTrack) - track = numTracks; - numTracks++; - } - } - timeout.Set(TRACKTIMEOUT); - displayTracks = NULL; -} - -cDisplaySpuTracks::~cDisplaySpuTracks() -{ - delete displayTracks; - currentDisplayTracks = NULL; - for (int i = 0; i < numTracks; i++) - free(descriptions[i]); -} - -void cDisplaySpuTracks::Show(void) -{ - if(!displayTracks) - displayTracks = Skins.Current()->DisplayTracks(tr("Subtitles"), numTracks, descriptions); - - displayTracks->SetTrack(track, descriptions); - displayTracks->SetAudioChannel(-1); - displayTracks->Flush(); -} - -cDisplaySpuTracks *cDisplaySpuTracks::Create(void) -{ - if (cXinelibDevice::Instance().NumDvdSpuTracks() > 0) { - if (!currentDisplayTracks) - new cDisplaySpuTracks; - return currentDisplayTracks; - } - return NULL; -} - -void cDisplaySpuTracks::Process(eKeys Key) -{ - if (currentDisplayTracks) - currentDisplayTracks->ProcessKey(Key); -} - -eOSState cDisplaySpuTracks::ProcessKey(eKeys Key) -{ - if(!displayTracks) { - Show(); - } - - int oldTrack = track; - switch (Key) { - case kUp|k_Repeat: - case kUp: - case kDown|k_Repeat: - case kDown: - if (NORMALKEY(Key) == kUp && track > 0) - track--; - else if (NORMALKEY(Key) == kDown && track < numTracks - 1) - track++; - timeout.Set(TRACKTIMEOUT); - break; - case kNext: - //case kSubtitle|k_Repeat: - //case kSubtitle: - if (++track >= numTracks) - track = 0; - timeout.Set(TRACKTIMEOUT); - break; - case kOk: - if (track != cXinelibDevice::Instance().GetCurrentDvdSpuTrack()) - oldTrack = -1; // make sure we explicitly switch to that track - timeout.Set(); - break; - case kNone: break; - default: if ((Key & k_Release) == 0) - return osEnd; - } - if (track != oldTrack) - Show(); - if (track != oldTrack) { - cXinelibDevice::Instance().SetCurrentDvdSpuTrack(types[track], true); - } - return timeout.TimedOut() ? osEnd : osContinue; -} -#endif // VDRVERSNUM < 10515 - -//----------------------------- cMenuXinelib --------------------------------- - -#include "tools/display_message.h" - -static cOsdItem *NewTitle(const char *s) -{ - cString str = cString::sprintf("----- %s -----", s); - cOsdItem *tmp = new cOsdItem(str); - tmp->SetSelectable(false); - return tmp; -} - - -extern cOsdObject *g_PendingMenuAction; - -time_t cMenuXinelib::g_LastHotkeyTime = 0; -eKeys cMenuXinelib::g_LastHotkey = kNone; - -cMenuXinelib::cMenuXinelib() -{ - field_order = xc.field_order; - compression = xc.audio_compression; - headphone = xc.headphone; - autocrop = xc.autocrop; - overscan = xc.overscan; - - hotkey_state = hkInit; - - novideo = cXinelibDevice::Instance().GetPlayMode() == pmAudioOnlyBlack ? 1 : 0; - - Add(NewTitle(tr("Media"))); - Add(new cOsdItem(tr("Play file >>"), osUser1)); - Add(new cOsdItem(tr("Play music >>"), osUser2)); - Add(new cOsdItem(tr("View images >>"), osUser3)); - if(xc.remote_mode) - Add(new cOsdItem(tr("Play remote DVD >>"), osUser4)); - else - Add(new cOsdItem(tr("Play DVD disc >>"), osUser4)); - if(xc.remote_mode) - Add(new cOsdItem(tr("Play remote CD >>"), osUser6)); - else - Add(new cOsdItem(tr("Play audio CD >>"), osUser6)); -#if VDRVERSNUM < 10515 - if(cXinelibDevice::Instance().NumDvdSpuTracks() > 0) - Add(new cOsdItem(tr("Select subtitle track >>"), osUser5)); -#endif - Add(NewTitle(tr("Video settings"))); - Add(ctrl_novideo = new cMenuEditBoolItem(tr("Play only audio"), - &novideo)); - Add(ctrl_autocrop = new cMenuEditBoolItem(tr("Crop letterbox 4:3 to 16:9"), - &autocrop)); - Add(ctrl_overscan = new cMenuEditTypedIntItem(tr("Overscan (crop image borders)"), "%", - &overscan, 0, 10, - tr("Off"))); -#ifdef HAVE_XV_FIELD_ORDER - Add(video_ctrl_interlace_order = new cMenuEditStraI18nItem(tr("Interlaced Field Order"), - &field_order, 2, xc.s_fieldOrder)); -#endif - - Add(NewTitle(tr("Audio settings"))); -#ifdef ENABLE_TEST_POSTPLUGINS - Add(ctrl_headphone = new cMenuEditBoolItem(tr("Headphone audio mode"), - &headphone)); -#else - ctrl_headphone = NULL; -#endif - - Add(audio_ctrl_compress = new cMenuEditTypedIntItem(tr("Audio Compression"),"%", - &compression, 100, 500, NULL, tr("Off"))); - - Add(new cOsdItem(tr("Audio equalizer >>"), osUser7)); - - switch(xc.main_menu_mode) { - case ShowFiles: AddSubMenu(new cMenuBrowseFiles(ShowFiles)); break; - case ShowMusic: AddSubMenu(new cMenuBrowseFiles(ShowMusic)); break; - case ShowImages: AddSubMenu(new cMenuBrowseFiles(ShowImages)); break; - default: break; - } - - xc.main_menu_mode = ShowMenu; -} - -cMenuXinelib::~cMenuXinelib() -{ -#ifdef HAVE_XV_FIELD_ORDER - if(xc.field_order != field_order ) - cXinelibDevice::Instance().ConfigureWindow(xc.fullscreen, xc.width, xc.height, - xc.modeswitch, xc.modeline, xc.display_aspect, - xc.scale_video, xc.field_order); -#endif - - if(xc.audio_compression != compression) - cXinelibDevice::Instance().ConfigurePostprocessing(xc.deinterlace_method, xc.audio_delay, - xc.audio_compression, xc.audio_equalizer, - xc.audio_surround, xc.speaker_type); - - if(xc.overscan != overscan) - cXinelibDevice::Instance().ConfigureVideo(xc.hue, xc.saturation, xc.brightness, - xc.contrast, xc.overscan, xc.vo_aspect_ratio); - - if(xc.headphone != headphone) - cXinelibDevice::Instance().ConfigurePostprocessing("headphone", - xc.headphone ? true : false); - - if(xc.autocrop != autocrop) - cXinelibDevice::Instance().ConfigurePostprocessing("autocrop", - xc.autocrop ? true : false, - xc.AutocropOptions()); - - int dev_novideo = cXinelibDevice::Instance().GetPlayMode() == pmAudioOnlyBlack ? 1 : 0; - if(dev_novideo != novideo) - cXinelibDevice::Instance().SetPlayMode(novideo ? pmAudioOnlyBlack : pmNone); -} - -cOsdMenu *cMenuXinelib::CreateMenuBrowseFiles(eMainMenuMode mode, bool Queue) -{ - return new cMenuBrowseFiles(mode, true); -} - -eOSState cMenuXinelib::ProcessKey(eKeys Key) -{ - /* Hot key support */ - if(hotkey_state == hkInit && Key == kNone) - return osContinue; - if(hotkey_state == hkInit && Key == HOTKEY_START) { - hotkey_state = hkSeen; - return osContinue; - } else if(hotkey_state == hkSeen && Key != kNone) { - hotkey_state = hkNone; - return ProcessHotkey(Key); - } - hotkey_state = hkNone; - - cOsdItem *item = Get(Current()); - - eOSState state = cMenuSetupPage::ProcessKey(Key); - - if(HasSubMenu()) - return state; - - switch(state) { - case osUser1: - AddSubMenu(new cMenuBrowseFiles(ShowFiles)); - return osUnknown; - case osUser2: - AddSubMenu(new cMenuBrowseFiles(ShowMusic)); - return osUnknown; - case osUser3: - AddSubMenu(new cMenuBrowseFiles(ShowImages)); - return osContinue; - case osUser4: - cControl::Shutdown(); - cControl::Launch(new cXinelibDvdPlayerControl("dvd:/")); - return osEnd; - case osUser6: - cControl::Shutdown(); - cControl::Launch(new cXinelibPlayerControl(ShowMusic, "cdda:/")); - return osEnd; -#if VDRVERSNUM < 10515 - case osUser5: - if(!g_PendingMenuAction) { - g_PendingMenuAction = cDisplaySpuTracks::Create(); - return osPlugin; - } - return osContinue; -#endif - case osUser7: - if(!g_PendingMenuAction) { - g_PendingMenuAction = new cEqualizer(); - return osPlugin; - } - return osContinue; - default: ; - } - - Key = NORMALKEY(Key); - - if(Key==kLeft || Key==kRight || ISNUMBERKEY(Key)) { - if(item == audio_ctrl_compress) - cXinelibDevice::Instance().ConfigurePostprocessing(xc.deinterlace_method, xc.audio_delay, - compression, xc.audio_equalizer, - xc.audio_surround, xc.speaker_type); - else if(item == ctrl_overscan) - cXinelibDevice::Instance().ConfigureVideo(xc.hue, xc.saturation, xc.brightness, - xc.contrast, overscan, xc.vo_aspect_ratio); - } - if(Key==kLeft || Key==kRight) { - if(item == ctrl_headphone) - cXinelibDevice::Instance().ConfigurePostprocessing("headphone", headphone?true:false); - else if(item == ctrl_autocrop) - cXinelibDevice::Instance().ConfigurePostprocessing("autocrop", autocrop?true:false, - xc.AutocropOptions()); - else if(item == ctrl_novideo) - cXinelibDevice::Instance().SetPlayMode(novideo ? pmAudioOnlyBlack : pmNone); -#ifdef HAVE_XV_FIELD_ORDER - else if(video_ctrl_interlace_order && item == video_ctrl_interlace_order) - cXinelibDevice::Instance().ConfigureWindow(xc.fullscreen, xc.width, xc.height, - xc.modeswitch, xc.modeline, - xc.display_aspect, xc.scale_video, - field_order); -#endif - } - - return state; -} - -void cMenuXinelib::Store(void) -{ -#ifdef HAVE_XV_FIELD_ORDER - xc.field_order = field_order; -#endif - xc.audio_compression = compression; - xc.autocrop = autocrop; - xc.overscan = overscan; - xc.headphone = headphone; -} - -#if APIVERSNUM < 10404 -# warning Using hotkeys may segfault with VDR version < 1.4.3-2 -#endif - -eOSState cMenuXinelib::ProcessHotkey(eKeys Key) -{ - eOSState NewState = osEnd; - cString Message; - time_t now = time(NULL); - bool OnlyInfo = ((g_LastHotkeyTime < now-3) || g_LastHotkey != Key); - - switch(Key) { - case HOTKEY_DVD: - cControl::Shutdown(); - cControl::Launch(new cXinelibDvdPlayerControl("dvd:/")); - break; - - case HOTKEY_DVD_TRACK1: - cControl::Shutdown(); - cControl::Launch(new cXinelibDvdPlayerControl("dvd:/1")); - break; - -#if VDRVERSNUM < 10515 - case HOTKEY_DVD_SPU: - /* use audio track display menu */ - if(!g_PendingMenuAction) { - bool WasOpen = cDisplaySpuTracks::IsOpen(); - g_PendingMenuAction = cDisplaySpuTracks::Create(); - if(g_PendingMenuAction) { - cRemote::CallPlugin("xineliboutput"); - if(WasOpen || !OnlyInfo) cRemote::Put(kNext); - } else { - Message = tr("No subtitles available!"); - } - } - break; -#endif - case HOTKEY_LOCAL_FE: - /* off, on */ - { - int local_frontend = strstra(xc.local_frontend, xc.s_frontends, 0); - -#ifndef OLD_TOGGLE_FE - if(local_frontend==FRONTEND_NONE) - // no need to show current frontend if there is no output device ... - OnlyInfo = false; -#endif - if(!OnlyInfo) { -#ifndef OLD_TOGGLE_FE - static int orig_frontend = -1; - if(orig_frontend < 0) - orig_frontend = local_frontend; - - if(orig_frontend == FRONTEND_NONE) { - // no frontends were loaded at startup -> loop thru all frontends - local_frontend++; - } else { - // frontend was loaded at startup -> toggle it on/off - if(local_frontend == FRONTEND_NONE) - local_frontend = orig_frontend; - else - local_frontend = FRONTEND_NONE; - } -#else - local_frontend++; -#endif - if(local_frontend >= FRONTEND_count) - local_frontend = 0; - strn0cpy(xc.local_frontend, xc.s_frontends[local_frontend], sizeof(xc.local_frontend)); - cXinelibDevice::Instance().ConfigureWindow( - xc.fullscreen, xc.width, xc.height, xc.modeswitch, xc.modeline, - xc.display_aspect, xc.scale_video, xc.field_order); - } - Message = cString::sprintf("%s %s %s", tr("Local Frontend"), - OnlyInfo ? ":" : "->", - xc.s_frontendNames[local_frontend]); - } - break; - - case HOTKEY_NEXT_ASPECT: - /* auto, 4:3, 16:9, ... */ - if(!OnlyInfo) { - xc.display_aspect = (xc.display_aspect < ASPECT_count-1) ? xc.display_aspect+1 : 0; - cXinelibDevice::Instance().ConfigureWindow(xc.fullscreen, xc.width, xc.height, - xc.modeswitch, xc.modeline, xc.display_aspect, - xc.scale_video, xc.field_order); - } - Message = cString::sprintf("%s %s %s", tr("Aspect ratio"), - OnlyInfo ? ":" : "->", - tr(xc.s_aspects[xc.display_aspect])); - break; - - case HOTKEY_TOGGLE_VO_ASPECT: - /* auto, square, 4:3, anamorphic or DVB */ - if(!OnlyInfo) { - xc.vo_aspect_ratio = (xc.vo_aspect_ratio < VO_ASPECT_count-1) ? xc.vo_aspect_ratio + 1 : 0; - cXinelibDevice::Instance().ConfigureVideo(xc.hue, xc.saturation, xc.brightness, - xc.contrast, xc.overscan, xc.vo_aspect_ratio); - } - Message = cString::sprintf("%s %s %s", tr("Video aspect ratio"), - OnlyInfo ? ":" : "->", - tr(xc.s_vo_aspects[xc.vo_aspect_ratio])); - break; - - case HOTKEY_TOGGLE_CROP: - /* off, force, auto */ - if(!OnlyInfo) { - if(!xc.autocrop) { - xc.autocrop = 1; - xc.autocrop_autodetect = 1; - } else if(xc.autocrop_autodetect) { - xc.autocrop_autodetect = 0; - } else { - xc.autocrop = 0; - } - cXinelibDevice::Instance().ConfigurePostprocessing("autocrop", - xc.autocrop ? true : false, - xc.AutocropOptions()); - } - - Message = cString::sprintf("%s %s %s", tr("Crop letterbox 4:3 to 16:9"), - OnlyInfo ? ":" : "->", - !xc.autocrop ? tr("Off") : xc.autocrop_autodetect ? tr("automatic") : tr("On")); - break; - - case HOTKEY_DEINTERLACE: - { - /* off, on */ - int off = !strcmp(xc.deinterlace_method, "none"); - if(!OnlyInfo) { - off = !off; - if(off) - strcpy(xc.deinterlace_method, "none"); - else - strcpy(xc.deinterlace_method, "tvtime"); - cXinelibDevice::Instance().ConfigurePostprocessing(xc.deinterlace_method, xc.audio_delay, - compression, xc.audio_equalizer, - xc.audio_surround, xc.speaker_type); - } - Message = cString::sprintf("%s %s %s", tr("Deinterlacing"), - OnlyInfo ? ":" : "->", - tr(off ? "Off":"On")); - } - break; - - case HOTKEY_UPMIX: - /* off, on */ - if(!OnlyInfo) { - xc.audio_upmix = xc.audio_upmix ? 0 : 1; - cXinelibDevice::Instance().ConfigurePostprocessing( - "upmix", xc.audio_upmix ? true : false, NULL); - } - Message = cString::sprintf("%s %s %s", - tr("Upmix stereo to 5.1"), - OnlyInfo ? ":" : "->", - tr(xc.audio_upmix ? "On" : "Off")); - break; - - case HOTKEY_DOWNMIX: - /* off, on */ - if(!OnlyInfo) { - xc.audio_surround = xc.audio_surround ? 0 : 1; - cXinelibDevice::Instance().ConfigurePostprocessing( - xc.deinterlace_method, xc.audio_delay, xc.audio_compression, - xc.audio_equalizer, xc.audio_surround, xc.speaker_type); - } - Message = cString::sprintf("%s %s %s", - tr("Downmix AC3 to surround"), - OnlyInfo ? ":" : "->", - tr(xc.audio_surround ? "On":"Off")); - break; - - case HOTKEY_PLAYLIST: - /* Start replaying playlist or file pointed by - symlink $(CONFDIR)/plugins/xineliboutput/default_playlist */ - { - struct stat st; - cString file = cString::sprintf("%s%s", cPlugin::ConfigDirectory("xineliboutput"), "/default_playlist"); - if (lstat(file, &st) == 0) { - if (S_ISLNK(st.st_mode)) { - cString buffer(ReadLink(file), true); - if (!*buffer || stat(buffer, &st)) { - Message = tr("Default playlist not found"); - } else { - LOGDBG("Replaying default playlist: %s", *file); - cControl::Shutdown(); - cControl::Launch(new cXinelibPlayerControl(CloseOsd, buffer)); - } - } else { - Message = tr("Default playlist is not symlink"); - } - } else { - Message = tr("Default playlist not defined"); - } - } - break; - - case HOTKEY_ADELAY_UP: - /* audio delay up */ - if(!OnlyInfo) { - xc.audio_delay++; - cXinelibDevice::Instance().ConfigurePostprocessing(xc.deinterlace_method, xc.audio_delay, - xc.audio_compression, xc.audio_equalizer, - xc.audio_surround, xc.speaker_type); - } - Message = cString::sprintf("%s %s %d %s", tr("Delay"), - OnlyInfo ? ":" : "->", - xc.audio_delay, tr("ms")); - break; - - case HOTKEY_ADELAY_DOWN: - /* audio delay up */ - if(!OnlyInfo) { - xc.audio_delay--; - cXinelibDevice::Instance().ConfigurePostprocessing(xc.deinterlace_method, xc.audio_delay, - xc.audio_compression, xc.audio_equalizer, - xc.audio_surround, xc.speaker_type); - } - Message = cString::sprintf("%s %s %d %s", tr("Delay"), - OnlyInfo ? ":" : "->", - xc.audio_delay, tr("ms")); - break; - - default: - Message = cString::sprintf(tr("xineliboutput: hotkey %s not binded"), cKey::ToString(Key)); - break; - } - - if(*Message) { - if(!g_PendingMenuAction && - !cRemote::HasKeys() && - cRemote::CallPlugin("xineliboutput")) - g_PendingMenuAction = new cDisplayMessage(Message); - } - - g_LastHotkeyTime = now; - g_LastHotkey = Key; - - return NewState; -} diff --git a/menu.h b/menu.h deleted file mode 100644 index 6551d971..00000000 --- a/menu.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * menu.h: Main Menu - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: menu.h,v 1.6 2007-01-04 08:42:47 phintuka Exp $ - * - */ - -#ifndef __XINELIB_MENU_H -#define __XINELIB_MENU_H - -#include - -class cMenuXinelib : public cMenuSetupPage -{ - private: - int field_order; - int compression; - int headphone; - int autocrop; - int overscan; - int novideo; - - // Hotkeys - enum {hkInit, hkSeen, hkNone} hotkey_state; - static time_t g_LastHotkeyTime; - static eKeys g_LastHotkey; - virtual eOSState ProcessHotkey(eKeys Key); - -#ifdef HAVE_XV_FIELD_ORDER - cOsdItem *video_ctrl_interlace_order; -#endif - cOsdItem *audio_ctrl_compress; - - cOsdItem *ctrl_autocrop; - cOsdItem *ctrl_overscan; - cOsdItem *ctrl_headphone; - cOsdItem *ctrl_novideo; - - protected: - virtual void Store(void); - - public: - cMenuXinelib(void); - virtual ~cMenuXinelib(); - virtual eOSState ProcessKey(eKeys Key); - - static cOsdMenu *CreateMenuBrowseFiles(eMainMenuMode mode, bool Queue=true); -}; - -#endif //__XINELIB_SETUP_MENU_H diff --git a/menuitems.c b/menuitems.c deleted file mode 100644 index 719f221d..00000000 --- a/menuitems.c +++ /dev/null @@ -1,215 +0,0 @@ -/* - * menuitems.c: New menu item types - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: menuitems.c,v 1.11 2008-03-13 21:29:00 phintuka Exp $ - * - */ - -#include - -#include "i18n.h" - -#include "menuitems.h" - -// --- cMenuEditTypedIntItem ------------------------------------------------- - -cMenuEditTypedIntItem::cMenuEditTypedIntItem(const char *Name, const char *Type, int *Value, - int Min, int Max, const char *ZeroString, - const char *MinString, const char *MaxString) -:cMenuEditIntItem(Name,Value,Min,Max,MinString,MaxString) -{ - type = Type ? Type : ""; - zeroString = ZeroString ? ZeroString : NULL; - Set(); -} - -void cMenuEditTypedIntItem::Set(void) -{ - if(*value == 0 && *zeroString) - SetValue(zeroString); - else if (minString && *value == min) - SetValue(minString); - else if (maxString && *value == max) - SetValue(maxString); - else - SetValue(cString::sprintf("%d %s", *value, *type)); -} - -// --- cMenuEditOddIntItem ------------------------------------------------------ - -cMenuEditOddIntItem::cMenuEditOddIntItem(const char *Name, int *Value, int Min, int Max, const char *MinString, const char *MaxString) -:cMenuEditIntItem(Name,Value,Min,Max,MinString,MaxString) -{ - value = Value; - min = Min; - max = Max; - minString = MinString; - maxString = MaxString; - if (*value < min) - *value = min; - else if (*value > max) - *value = max; - Set(); -} - -eOSState cMenuEditOddIntItem::ProcessKey(eKeys Key) -{ - eOSState state = cMenuEditItem::ProcessKey(Key); - - if (state == osUnknown) { - int newValue = *value; - bool IsRepeat = Key & k_Repeat; - Key = NORMALKEY(Key); - switch (Key) { - case kNone: break; - case kLeft: - newValue = *value - 2; - fresh = true; - if (!IsRepeat && newValue < min && max != INT_MAX) - newValue = max; - break; - case kRight: - newValue = *value + 2; - fresh = true; - if (!IsRepeat && newValue > max && min != INT_MIN) - newValue = min; - break; - default: - if (*value < min) { *value = min; Set(); } - if (*value > max) { *value = max; Set(); } - return state; - } - if (newValue != *value && (!fresh || min <= newValue) && newValue <= max) { - *value = newValue; - Set(); - } - state = osContinue; - } - return state; -} - -// --- cMenuEditFpIntItem ---------------------------------------------------- - -cMenuEditFpIntItem::cMenuEditFpIntItem(const char *Name, int *Value, int Min, int Max, - int Decimals, const char *ZeroString, - const char *MinString, const char *MaxString) -:cMenuEditIntItem(Name,Value,Min,Max,MinString,MaxString) -{ - decimals = Decimals; - zeroString = ZeroString ? ZeroString : NULL; - Set(); -} - -void cMenuEditFpIntItem::Set(void) -{ - if(*value == 0 && *zeroString) - SetValue(zeroString); - else if (minString && *value == min) - SetValue(minString); - else if (maxString && *value == max) - SetValue(maxString); - else - SetValue(cString::sprintf("%1.1f", ((float)(*value)) / exp10f(decimals))); -} - -// --- cMenuEditStraI18nItem ------------------------------------------------- - -cMenuEditStraI18nItem::cMenuEditStraI18nItem(const char *Name, int *Value, int NumStrings, const char * const *Strings) -:cMenuEditIntItem(Name, Value, 0, NumStrings - 1) -{ - strings = Strings; - Set(); -} - -void cMenuEditStraI18nItem::Set(void) -{ - SetValue(tr(strings[*value])); -} - -// --- cFileListItem ------------------------------------------------- - -cFileListItem::cFileListItem(const char *name, bool isDir) -{ - m_Name = name; - m_IsDir = isDir; - m_IsDvd = false; - m_HasResume = false; - m_SubFile = NULL; - m_ShowFlags = false; - m_Up = m_IsDir && !strcmp(m_Name, ".."); - Set(); -} - -cFileListItem::cFileListItem(const char *name, bool IsDir, - bool HasResume, const char *subfile, - bool IsDvd) -{ - m_Name = name; - m_IsDir = IsDir; - m_IsDvd = IsDvd; - m_HasResume = HasResume; - m_SubFile = subfile; - m_ShowFlags = true; - m_Up = m_IsDir && !strcmp(m_Name, ".."); - Set(); -} - -void cFileListItem::Set(void) -{ - cString txt; - char *pt; - if(m_ShowFlags) { - if(m_IsDir) { - if(m_IsDvd) - txt = cString::sprintf("\tD\t[%s] ", *m_Name); // text2skin requires space at end of string to display item correctly ... - else - txt = cString::sprintf("\t\t[%s] ", *m_Name); // text2skin requires space at end of string to display item correctly ... - } else { - txt = cString::sprintf("%c\t%c\t%s", m_HasResume ? ' ' : '*', *m_SubFile ? 'S' : m_IsDvd ? 'D' : ' ', *m_Name); - if(NULL != (pt = strrchr(txt,'.'))) - *pt = 0; - } - } else { - if(m_IsDir) { - txt = cString::sprintf("[%s] ", *m_Name); // text2skin requires space at end of string to display item correctly ... - } else { - txt = m_Name; - if(NULL != (pt = strrchr(txt,'.'))) - *pt = 0; - } - } - SetText(txt); -} - -int cFileListItem::Compare(const cListObject &ListObject) const -{ - cFileListItem *other = (cFileListItem *)&ListObject; - - if(m_IsDir && !other->m_IsDir) - return -1; - if(!m_IsDir && other->m_IsDir) - return 1; - if(m_Up && !other->m_Up) - return -1; - if(!m_Up && other->m_Up) - return 1; - return strcmp(m_Name, other->m_Name); -} - -bool cFileListItem::operator< (const cListObject &ListObject) -{ - cFileListItem *other = (cFileListItem *)&ListObject; - - if(m_IsDir && !other->m_IsDir) - return true; - if(!m_IsDir && other->m_IsDir) - return false; - if(m_Up && !other->m_Up) - return true; - if(!m_Up && other->m_Up) - return false; - return strcmp(m_Name, other->m_Name) < 0; -} diff --git a/menuitems.h b/menuitems.h deleted file mode 100644 index cb158881..00000000 --- a/menuitems.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * menuitems.h: New menu item types - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: menuitems.h,v 1.7 2007-06-21 10:00:29 phintuka Exp $ - * - */ - -#ifndef __XINELIB_MENUITEMS_H_ -#define __XINELIB_MENUITEMS_H_ - -#include - -// --- cMenuEditTypedIntItem ------------------------------------------------- - -class cMenuEditTypedIntItem : public cMenuEditIntItem -{ - protected: - cString type; - cString zeroString; - - virtual void Set(void); - - public: - cMenuEditTypedIntItem(const char *Name, const char *Type, int *Value, - int Min = 0, int Max = INT_MAX, const char *ZeroString = NULL, - const char *MinString = NULL, const char *MaxString = NULL); -}; - -// --- cMenuEditOddIntItem ------------------------------------------------- - -class cMenuEditOddIntItem : public cMenuEditIntItem -{ - public: - cMenuEditOddIntItem(const char *Name, int *Value, int Min = 1, int Max = INT_MAX, const char *MinString = NULL, const char *MaxString = NULL); - eOSState ProcessKey(eKeys Key); -}; - - -// --- cMenuEditFpIntItem ------------------------------------------------- - -// Fixed-point decimal number - -class cMenuEditFpIntItem : public cMenuEditIntItem -{ - protected: - int decimals; - cString zeroString; - - virtual void Set(void); - - public: - cMenuEditFpIntItem(const char *Name, int *Value, int Min = 1, int Max = INT_MAX, - int Decimals = 1, const char *ZeroString = NULL, - const char *MinString = NULL, const char *MaxString = NULL); -}; - - -// --- cMenuEditStraI18nItem ------------------------------------------------- - -class cMenuEditStraI18nItem : public cMenuEditIntItem -{ - private: - const char * const *strings; - - protected: - virtual void Set(void); - - public: - cMenuEditStraI18nItem(const char *Name, int *Value, - int NumStrings, const char * const *Strings); -}; - -// --- cFileListItem --------------------------------------------------------- - -class cFileListItem : public cOsdItem -{ - private: - cString m_Name; - cString m_SubFile; - bool m_IsDir, m_HasResume, m_ShowFlags, m_Up; - bool m_IsDvd; - - protected: - virtual void Set(void); - - public: - cFileListItem(const char *name, bool isDir, - bool HasResume, const char *subfile, - bool IsDvd = false); - cFileListItem(const char *name, bool isDir); - - const char *Name(void) { return m_Name; } - const char *SubFile(void) { return m_SubFile; } - bool IsDir(void) { return m_IsDir; } - bool IsDvd(void) { return m_IsDvd; } - - virtual bool operator< (const cListObject &ListObject); - virtual int Compare(const cListObject &ListObject) const; -}; - -#endif //__XINELIB_MENUITEMS_H_ diff --git a/mpg2c.c b/mpg2c.c deleted file mode 100644 index 50c1e25a..00000000 --- a/mpg2c.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2003-2006 Petri Hintukainen - * - * This code is distributed under the terms and conditions of the - * GNU GENERAL PUBLIC LICENSE. See the file COPYING for details. - * - * mpg2.c: - * - * $Id: mpg2c.c,v 1.3 2006-06-04 11:00:04 phintuka Exp $ - * - */ - -#include - -#define LINELEN 20 - -int main(int argc, char *argv[]) -{ - int ch; - int pos=1; - - if(argc != 4) { - printf("%s - convert binary file to C code\n\n" - "usage: %s variable inputfile outputfile\n", - argv[0],argv[0]); - return -1; - } - - FILE *fi = fopen(argv[2],"rb"); - FILE *fo = fopen(argv[3],"wt"); - if(!fi ||!fo) { - printf("Error opening files\n"); - return -1; - } - fprintf(fo, "extern const unsigned char v_mpg_%s[] = \n \"", argv[1]); - while(EOF != (ch = fgetc(fi))) { - fprintf(fo, "\\x%02x", ch); - if(pos++ > LINELEN) { - fprintf(fo, "\"\n \""); - pos=1; - } - } - fprintf(fo, "\";\n\nextern const int v_mpg_%s_length = sizeof(v_mpg_%s);\n\n", - argv[1], argv[1]); - - fclose(fi); - fclose(fo); - - return 0; -} diff --git a/nosignal_720x576.mpg b/nosignal_720x576.mpg deleted file mode 100644 index cff01b4c..00000000 Binary files a/nosignal_720x576.mpg and /dev/null differ diff --git a/osd.c b/osd.c deleted file mode 100644 index 690682ae..00000000 --- a/osd.c +++ /dev/null @@ -1,504 +0,0 @@ -/* - * osd.c: Xinelib On Screen Display control - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: osd.c,v 1.23 2008-04-14 19:58:54 phintuka Exp $ - * - */ - -#include -#include -#include - -#include "logdefs.h" -#include "device.h" -#include "config.h" -#include "xine_osd_command.h" - -#include "osd.h" - -//#define LIMIT_OSD_REFRESH_RATE - -#define LOGOSD(x...) - -// -// tools -// - -static inline int saturate(int x, int min, int max) -{ - return x < min ? min : (x > max ? max : x); -} - -static inline void prepare_palette(xine_clut_t *clut, const unsigned int *palette, int colors, bool top, bool rgb) -{ - if (colors) { - int c; - - // Apply alpha layer correction and convert ARGB -> AYCrCb - - for(c=0; c> 24; - int R = (palette[c] & 0x00ff0000) >> 16; - int G = (palette[c] & 0x0000ff00) >> 8; - int B = (palette[c] & 0x000000ff); - A = A + xc.alpha_correction*A/100 + xc.alpha_correction_abs; - if(rgb) { - clut[c].r = R; - clut[c].g = G; - clut[c].b = B; - clut[c].alpha = saturate( A, 0, 255); - } else { - int Y = (( + 66*R + 129*G + 25*B + 0x80) >> 8) + 16; - int CR = (( + 112*R - 94*G - 18*B + 0x80) >> 8) + 128; - int CB = (( - 38*R - 74*G + 112*B + 0x80) >> 8) + 128; - clut[c].y = saturate( Y, 16, 235); - clut[c].cb = saturate(CB, 16, 240); - clut[c].cr = saturate(CR, 16, 240); - clut[c].alpha = saturate( A, 0, 255); - } - } - - // Apply OSD mixer settings - - if(!top) { - if(xc.osd_mixer & OSD_MIXER_ALPHA) - for(c=0; c> 1) | 0x80; - if(xc.osd_mixer & OSD_MIXER_GRAY) - for(c=0; c rle_size ) { - rle_size *= 2; - rle_base = (xine_rle_elem_t*)realloc( rle_base, 4*rle_size ); - rle_p = rle_base + num_rle; - } - *rle_p++ = rle; - num_rle++; - } - rle.color = *c; - rle.len = 1; - } else { - rle.len++; - } - } - *rle_p++ = rle; - num_rle++; - } - - TRACE("xinelib_osd.c:CmdRle uncompressed="<< (w*h) <<", compressed=" << (4*num_rle)); - - *rle_data = rle_base; - return num_rle; -} - -// -// cXinelibOsd -// - -class cXinelibOsd : public cOsd, public cListObject -{ - private: - cXinelibOsd(); - cXinelibOsd(cXinelibOsd&); // no copy - - cXinelibDevice *m_Device; - - void CloseWindows(void); - void CmdSize(int Width, int Height); - void CmdRle(int Wnd, int X0, int Y0, - int W, int H, unsigned char *Data, - int Colors, unsigned int *Palette, - osd_rect_t *DirtyArea); - void CmdClose(int Wnd); - - protected: - static cMutex m_Lock; - static cList m_OsdStack; - - bool m_IsVisible; - bool m_Refresh; - uint m_Layer; - - virtual eOsdError CanHandleAreas(const tArea *Areas, int NumAreas); - virtual eOsdError SetAreas(const tArea *Areas, int NumAreas); - virtual void Flush(void); - - // Messages from cXinelibOsdProvider - void Show(void); - void Hide(void); - void Refresh(void); - void Detach(void); - - friend class cXinelibOsdProvider; - - public: - cXinelibOsd(cXinelibDevice *Device, int x, int y, uint Level = 0); - virtual ~cXinelibOsd(); -}; - -cList cXinelibOsd::m_OsdStack; -cMutex cXinelibOsd::m_Lock; - - -void cXinelibOsd::CmdSize(int Width, int Height) -{ - TRACEF("cXinelibOsd::CmdSize"); - - if(m_Device) { - osd_command_t osdcmd; - memset(&osdcmd,0,sizeof(osdcmd)); - - osdcmd.cmd = OSD_Size; - osdcmd.w = Width; - osdcmd.h = Height; - - m_Device->OsdCmd((void*)&osdcmd); - } -} - -void cXinelibOsd::CmdClose(int Wnd) -{ - TRACEF("cXinelibOsd::CmdClose"); - - if(m_Device) { - osd_command_t osdcmd; - memset(&osdcmd,0,sizeof(osdcmd)); - - osdcmd.cmd = OSD_Close; - osdcmd.wnd = Wnd; - - if(m_Refresh) - osdcmd.flags |= OSDFLAG_REFRESH; - - m_Device->OsdCmd((void*)&osdcmd); - } -} - -void cXinelibOsd::CmdRle(int Wnd, int X0, int Y0, - int W, int H, unsigned char *Data, - int Colors, unsigned int *Palette, - osd_rect_t *DirtyArea) -{ - TRACEF("cXinelibOsd::CmdRle"); - - if(m_Device) { - - osd_command_t osdcmd; - xine_clut_t clut[256]; - - memset(&osdcmd, 0, sizeof(osdcmd)); - osdcmd.cmd = OSD_Set_RLE; - osdcmd.wnd = Wnd; - osdcmd.x = X0; - osdcmd.y = Y0; - osdcmd.w = W; - osdcmd.h = H; - if(DirtyArea) - memcpy(&osdcmd.dirty_area, DirtyArea, sizeof(osd_rect_t)); - if(m_Refresh) - osdcmd.flags |= OSDFLAG_REFRESH; - if(xc.unscaled_osd) - osdcmd.flags |= OSDFLAG_UNSCALED; - else if(xc.unscaled_osd_lowresvideo) - osdcmd.flags |= OSDFLAG_UNSCALED_LOWRES; - - prepare_palette(&clut[0], Palette, Colors, /*Top*/(Prev() == NULL), true); - osdcmd.colors = Colors; - osdcmd.palette = clut; - - osdcmd.num_rle = rle_compress(&osdcmd.data, Data, W, H); - osdcmd.datalen = 4 * osdcmd.num_rle; - - osdcmd.scaling = xc.osd_scaling; - - m_Device->OsdCmd((void*)&osdcmd); - - if(osdcmd.data) - free(osdcmd.data); - } -} - -cXinelibOsd::cXinelibOsd(cXinelibDevice *Device, int x, int y, uint Level) -#if VDRVERSNUM >= 10509 - : cOsd(x, y, Level) -#else - : cOsd(x, y) -#endif -{ - TRACEF("cXinelibOsd::cXinelibOsd"); - - m_Device = Device; - m_Refresh = false; - m_IsVisible = true; - m_Layer = Level; -} - -cXinelibOsd::~cXinelibOsd() -{ - TRACEF("cXinelibOsd::~cXinelibOsd"); - - cMutexLock ml(&m_Lock); - - CloseWindows(); - - m_OsdStack.Del(this,false); - - if(m_OsdStack.First()) - m_OsdStack.First()->Show(); -} - -eOsdError cXinelibOsd::SetAreas(const tArea *Areas, int NumAreas) -{ - TRACEF("cXinelibOsd::SetAreas"); - cMutexLock ml(&m_Lock); - - LOGOSD("cXinelibOsd::SetAreas"); - - CloseWindows(); - - eOsdError Result = cOsd::SetAreas(Areas, NumAreas); - - if(Left() + Width() > 720 || Top() + Height() > 576) { - LOGDBG("Detected HD OSD, size > %dx%d, using setup values %dx%d", - 2*Left() + Width(), 2*Top() + Height(), - Setup.OSDWidth + (2*Setup.OSDLeft), Setup.OSDHeight + (2*Setup.OSDTop)); - CmdSize(Setup.OSDWidth + (2*Setup.OSDLeft), Setup.OSDHeight + (2*Setup.OSDTop)); - } else { - CmdSize(720, 576); - } - - return Result; -} - -eOsdError cXinelibOsd::CanHandleAreas(const tArea *Areas, int NumAreas) -{ - TRACEF("cXinelibOsd::CanHandleAreas"); - - eOsdError Result = cOsd::CanHandleAreas(Areas, NumAreas); - if (Result == oeOk) { - if (NumAreas > MAX_OSD_OBJECT) - return oeTooManyAreas; - for (int i = 0; i < NumAreas; i++) { - if (Areas[i].bpp != 1 && Areas[i].bpp != 2 && - Areas[i].bpp != 4 && Areas[i].bpp != 8) - return oeBppNotSupported; - } - } - return Result; -} - -void cXinelibOsd::Flush(void) -{ - TRACEF("cXinelibOsd::Flush"); - - cMutexLock ml(&m_Lock); - - cBitmap *Bitmap; - - if(!m_IsVisible) - return; - - int SendDone = 0; - for (int i = 0; (Bitmap = GetBitmap(i)) != NULL; i++) { - int x1 = 0, y1 = 0, x2 = Bitmap->Width()-1, y2 = Bitmap->Height()-1; - if (m_Refresh || Bitmap->Dirty(x1, y1, x2, y2)) { - - /* XXX what if only palette has been changed ? */ - int NumColors; - const tColor *Colors = Bitmap->Colors(NumColors); - osd_rect_t DirtyArea = {x1:x1, y1:y1, x2:x2, y2:y2}; - CmdRle(i, - Left() + Bitmap->X0(), Top() + Bitmap->Y0(), - Bitmap->Width(), Bitmap->Height(), - (unsigned char *)Bitmap->Data(0,0), - NumColors, (unsigned int *)Colors, - &DirtyArea); - SendDone++; - } - Bitmap->Clean(); - } - -#ifdef LIMIT_OSD_REFRESH_RATE - if(SendDone) { - static int64_t last_refresh = 0LL; - int64_t now = cTimeMs::Now(); - if(now - last_refresh < 100) { - /* too fast refresh rate, delay ... */ - cCondWait::SleepMs(40); /* Can't update faster anyway ... */ -# if 0 - LOGDBG("cXinelibOsd::Flush: OSD refreshing too fast ! (>10Hz) -> Sleeping 50ms"); -# endif - } - last_refresh = now; - } -#endif -} - -void cXinelibOsd::Refresh(void) -{ - TRACEF("cXinelibOsd::Refresh"); - - cMutexLock ml(&m_Lock); - - m_Refresh = true; - CloseWindows(); - Flush(); - m_Refresh = false; -} - -void cXinelibOsd::Show(void) -{ - TRACEF("cXinelibOsd::Show"); - - cMutexLock ml(&m_Lock); - - m_IsVisible = true; - Refresh(); -} - -void cXinelibOsd::CloseWindows(void) -{ - TRACEF("cXinelibOsd::CloseWindows"); - - if(m_IsVisible) { - cBitmap *Bitmap; - for (int i = 0; (Bitmap = GetBitmap(i)) != NULL; i++) { - LOGOSD("Close OSD %d.%d", Index(), i); - CmdClose(i); - } - } -} - -void cXinelibOsd::Hide(void) -{ - TRACEF("cXinelibOsd::Hide"); - - cMutexLock ml(&m_Lock); - - CloseWindows(); - m_IsVisible = false; -} - -void cXinelibOsd::Detach(void) -{ - TRACEF("cXinelibOsd::Detach"); - - cMutexLock ml(&m_Lock); - - Hide(); - m_Device = NULL; -} - -// -// cXinelibOsdProvider -// - -cXinelibOsdProvider::cXinelibOsdProvider(cXinelibDevice *Device) -{ - m_Device = Device; -} - -cXinelibOsdProvider::~cXinelibOsdProvider() -{ - LOGMSG("cXinelibOsdProvider: shutting down !"); - - cMutexLock ml(&cXinelibOsd::m_Lock); - - m_Device = NULL; - - if(cXinelibOsd::m_OsdStack.First()) { - LOGMSG("cXinelibOsdProvider: OSD open while OSD provider shutting down !"); - - // Detach all OSD instances from device - cXinelibOsd *osd; - while(NULL != (osd = cXinelibOsd::m_OsdStack.First())) { - osd->Detach(); - cXinelibOsd::m_OsdStack.Del(osd, false); - } - } -} - -cOsd *cXinelibOsdProvider::CreateOsd(int Left, int Top, uint Level) -{ - TRACEF("cXinelibOsdProvider::CreateOsd"); - - cMutexLock ml(&cXinelibOsd::m_Lock); - -#if VDRVERSNUM < 10509 - if(cXinelibOsd::m_OsdStack.First()) - LOGMSG("cXinelibOsdProvider::CreateOsd - OSD already open !"); -#endif - - cXinelibOsd *m_OsdInstance = new cXinelibOsd(m_Device, Left, Top, Level); - - // sorted insert - cXinelibOsd *it = cXinelibOsd::m_OsdStack.First(); - while(it) { - if(it->m_Layer >= Level) { - cXinelibOsd::m_OsdStack.Ins(m_OsdInstance, it); - break; - } - it = cXinelibOsd::m_OsdStack.Next(it); - } - if(!it) - cXinelibOsd::m_OsdStack.Add(m_OsdInstance); - - LOGOSD("New OSD: index %d, layer %d [now %d OSDs]", m_OsdInstance->Index(), Level, cXinelibOsd::m_OsdStack.Count()); - if(xc.osd_mixer == OSD_MIXER_NONE) - LOGOSD(" OSD mixer off"); - - // hide all but top-most OSD - it = cXinelibOsd::m_OsdStack.Last(); - while(cXinelibOsd::m_OsdStack.Prev(it)) { - LOGOSD(" -> hide OSD %d", it->Index()); - it->Hide(); - it = cXinelibOsd::m_OsdStack.Prev(it); - } - it->Show(); - - return m_OsdInstance; -} - -void cXinelibOsdProvider::RefreshOsd(void) -{ - TRACEF("cXinelibOsdProvider::RefreshOsd"); - - cMutexLock ml(&cXinelibOsd::m_Lock); - - // bottom --> top (draw lower layer OSDs first) - cXinelibOsd *it = cXinelibOsd::m_OsdStack.Last(); - while(it) { - it->Refresh(); - it = cXinelibOsd::m_OsdStack.Prev(it); - } -} - - - diff --git a/osd.h b/osd.h deleted file mode 100644 index 74baf804..00000000 --- a/osd.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * osd.h: Xinelib On Screen Display control - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: osd.h,v 1.5 2007-10-15 00:31:39 phintuka Exp $ - * - */ - -#ifndef __XINELIB_OSD_H -#define __XINELIB_OSD_H - -#include - -class cXinelibDevice; - -class cXinelibOsdProvider : public cOsdProvider -{ - protected: - cXinelibDevice *m_Device; - - public: - cXinelibOsdProvider(cXinelibDevice *Device); - virtual ~cXinelibOsdProvider(); - - virtual cOsd *CreateOsd(int Left, int Top, uint Level); - - static void RefreshOsd(void); - - // VDR < 1.5.9 compability - virtual cOsd *CreateOsd(int Left, int Top) { return CreateOsd(Left, Top, 0); } -}; - -#endif //__XINELIB_OSD_H - diff --git a/patches/vdr-1.4.6-Smooth_FastForward.patch b/patches/vdr-1.4.6-Smooth_FastForward.patch deleted file mode 100644 index fc1383f6..00000000 --- a/patches/vdr-1.4.6-Smooth_FastForward.patch +++ /dev/null @@ -1,79 +0,0 @@ -Common subdirectories: vdr-1.4.6-orig/PLUGINS and vdr-1.4.6/PLUGINS -diff -u vdr-1.4.6-orig/device.h vdr-1.4.6/device.h ---- vdr-1.4.6-orig/device.h 2007-06-19 10:42:07.000000000 +0300 -+++ vdr-1.4.6/device.h 2007-06-19 10:43:33.000000000 +0300 -@@ -452,6 +452,9 @@ - ///< which is necessary for trick modes like 'fast forward'. - ///< Data must point to one single, complete PES packet. - public: -+#define DEVICE_SUPPORTS_IBP_TRICKSPEED -+ virtual bool HasIBPTrickSpeed(void) { return false; } -+ ///< Returns true if this device can all frames in fast fwd trick speeds. - virtual int64_t GetSTC(void); - ///< Gets the current System Time Counter, which can be used to - ///< synchronize audio and video. If this device is unable to -Only in vdr-1.4.6: device.h.flc -Only in vdr-1.4.6: device.h~ -diff -u vdr-1.4.6-orig/dvbplayer.c vdr-1.4.6/dvbplayer.c ---- vdr-1.4.6-orig/dvbplayer.c 2007-06-19 10:42:07.000000000 +0300 -+++ vdr-1.4.6/dvbplayer.c 2007-06-19 10:51:19.000000000 +0300 -@@ -400,7 +400,13 @@ - uchar FileNumber; - int FileOffset; - bool TimeShiftMode = index->IsStillRecording(); -- int Index = index->GetNextIFrame(readIndex, playDir == pdForward, &FileNumber, &FileOffset, &Length, TimeShiftMode); -+ int Index = -1; -+ if (DeviceHasIBPTrickSpeed() && playDir == pdForward) { -+ if (index->Get(readIndex+1, &FileNumber, &FileOffset, NULL, &Length)) -+ Index = readIndex+1; -+ } -+ else -+ Index = index->GetNextIFrame(readIndex, playDir == pdForward, &FileNumber, &FileOffset, &Length, TimeShiftMode); - if (Index >= 0) { - if (!NextFile(FileNumber, FileOffset)) - continue; -@@ -530,7 +536,8 @@ - else { - LOCK_THREAD; - if (playMode == pmFast || (playMode == pmSlow && playDir == pdBackward)) -- Empty(); -+ if (!(DeviceHasIBPTrickSpeed() && playDir == pdForward)) -+ Empty(); - DeviceFreeze(); - playMode = pmPause; - } -@@ -541,7 +548,8 @@ - if (playMode != pmPlay) { - LOCK_THREAD; - if (playMode == pmStill || playMode == pmFast || (playMode == pmSlow && playDir == pdBackward)) -- Empty(); -+ if (!(DeviceHasIBPTrickSpeed() && playDir == pdForward)) -+ Empty(); - DevicePlay(); - playMode = pmPlay; - playDir = pdForward; -@@ -564,7 +572,8 @@ - // run into pmPlay - case pmPlay: { - LOCK_THREAD; -- Empty(); -+ if (! DeviceHasIBPTrickSpeed()) -+ Empty(); - DeviceMute(); - playMode = pmFast; - playDir = pdForward; -Only in vdr-1.4.6: dvbplayer.c.orig -Only in vdr-1.4.6: dvbplayer.c~ -Common subdirectories: vdr-1.4.6-orig/libsi and vdr-1.4.6/libsi -diff -u vdr-1.4.6-orig/player.h vdr-1.4.6/player.h ---- vdr-1.4.6-orig/player.h 2007-06-19 10:42:07.000000000 +0300 -+++ vdr-1.4.6/player.h 2007-06-19 10:42:20.000000000 +0300 -@@ -24,6 +24,7 @@ - bool DeviceSetCurrentAudioTrack(eTrackType Type) { return device ? device->SetCurrentAudioTrack(Type) : false; } - bool DevicePoll(cPoller &Poller, int TimeoutMs = 0) { return device ? device->Poll(Poller, TimeoutMs) : false; } - bool DeviceFlush(int TimeoutMs = 0) { return device ? device->Flush(TimeoutMs) : true; } -+ bool DeviceHasIBPTrickSpeed(void) { return device ? device->HasIBPTrickSpeed() : false; } - void DeviceTrickSpeed(int Speed) { if (device) device->TrickSpeed(Speed); } - void DeviceClear(void) { if (device) device->Clear(); } - void DevicePlay(void) { if (device) device->Play(); } -Common subdirectories: vdr-1.4.6-orig/symbols and vdr-1.4.6/symbols diff --git a/po/cs_CZ.po b/po/cs_CZ.po deleted file mode 100644 index db7a254f..00000000 --- a/po/cs_CZ.po +++ /dev/null @@ -1,615 +0,0 @@ -# VDR plugin language source file. -# Copyright (C) 2007 Klaus Schmidinger -# This file is distributed under the same license as the VDR package. -# -msgid "" -msgstr "" -"Project-Id-Version: VDR 1.5.7\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2008-04-15 00:22+0300\n" -"PO-Revision-Date: 2008-03-20 23:57+0100\n" -"Last-Translator: Maya \n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=iso-8859-2\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Poedit-Language: Czech\n" -"X-Poedit-Country: CZECH REPUBLIC\n" - -msgid "custom" -msgstr "u¾ivatelský" - -msgid "tiny" -msgstr "nejmen¹í" - -msgid "small" -msgstr "malý" - -msgid "medium" -msgstr "støední" - -msgid "large" -msgstr "velký" - -msgid "huge" -msgstr "nejvìt¹í" - -msgid "automatic" -msgstr "automaticky" - -msgid "default" -msgstr "výchozí" - -msgid "Pan&Scan" -msgstr "Pan&Scan" - -msgid "CenterCutOut" -msgstr "" - -msgid "square" -msgstr "ètvercový" - -msgid "anamorphic" -msgstr "anamorfní" - -msgid "DVB" -msgstr "DVB" - -msgid "off" -msgstr "vypnuto" - -msgid "normal" -msgstr "normální" - -msgid "inverted" -msgstr "inverzní" - -msgid "no audio" -msgstr "bez zvuku" - -msgid "no video" -msgstr "bez obrazu" - -msgid "Off" -msgstr "vypnuto" - -msgid "Goom" -msgstr "Soutìska" - -msgid "Oscilloscope" -msgstr "Osciloskop" - -msgid "FFT Scope" -msgstr "FFT spektrum" - -msgid "FFT Graph" -msgstr "FFT graf" - -msgid "Mono 1.0" -msgstr "Mono 1.0" - -msgid "Stereo 2.0" -msgstr "Stereo 2.0" - -msgid "Headphones 2.0" -msgstr "Sluchátka 2.0" - -msgid "Stereo 2.1" -msgstr "Stereo 2.1" - -msgid "Surround 3.0" -msgstr "Surround 3.0" - -msgid "Surround 4.0" -msgstr "Surround 4.0" - -msgid "Surround 4.1" -msgstr "Surround 4.1" - -msgid "Surround 5.0" -msgstr "Surround 5.0" - -msgid "Surround 5.1" -msgstr "Surround 5.1" - -msgid "Surround 6.0" -msgstr "Surround 6.0" - -msgid "Surround 6.1" -msgstr "Surround 6.1" - -msgid "Surround 7.1" -msgstr "Surround 7.1" - -msgid "Pass Through" -msgstr "Prùchozí" - -msgid "very large" -msgstr "velmi velký" - -msgid "no" -msgstr "ne" - -msgid "grayscale" -msgstr "odstíny ¹edi" - -msgid "transparent" -msgstr "prùhledný" - -msgid "transparent grayscale" -msgstr "" - -msgid "yes" -msgstr "ano" - -msgid "nearest" -msgstr "" - -msgid "bilinear" -msgstr "" - -msgid "Frontend initialization failed" -msgstr "Inicializace rozhraní selhala" - -msgid "Server initialization failed" -msgstr "Inicializace serveru selhala" - -msgid "Playlist" -msgstr "Seznam stop" - -msgid "Button$Random" -msgstr "Náhodné" - -msgid "Button$Normal" -msgstr "Normální" - -msgid "Button$Add files" -msgstr "Pøidat soubory" - -msgid "Button$Remove" -msgstr "Odstranit" - -msgid "Button$Sort" -msgstr "Tøídìní" - -msgid "Queued to playlist" -msgstr "Pøidáno do seznamu stop" - -msgid "Random play" -msgstr "Náhodné pøehrávání" - -msgid "Normal play" -msgstr "Normální pøehrávání" - -msgid "Delete image ?" -msgstr "Smazat obrázek ?" - -msgid "Images" -msgstr "Obrázky" - -msgid "Play music" -msgstr "Pøehrát hudbu" - -msgid "Add to playlist" -msgstr "Pøidat do seznamu stop" - -msgid "Play file" -msgstr "Pøehrát soubor" - -msgid "Button$Queue" -msgstr "Fronta" - -msgid "Subtitles" -msgstr "Titulky" - -msgid "Media" -msgstr "Média" - -msgid "Play file >>" -msgstr "Pøehrát soubor >>" - -msgid "Play music >>" -msgstr "Pøehrát hudbu >>" - -msgid "View images >>" -msgstr "Prohlí¾et obrázky >>" - -msgid "Play remote DVD >>" -msgstr "Pøehrát vzdálené DVD >>" - -msgid "Play DVD disc >>" -msgstr "Pøehrát DVD >>" - -msgid "Play remote CD >>" -msgstr "Pøehrát vzdálené CD >>" - -msgid "Play audio CD >>" -msgstr "Pøehrát zvukové CD >>" - -msgid "Select subtitle track >>" -msgstr "Výbìr titulkù >>" - -msgid "Video settings" -msgstr "Nastavení obrazu" - -msgid "Play only audio" -msgstr "Pøehrávat pouze zvuk" - -msgid "Crop letterbox 4:3 to 16:9" -msgstr "Oøíznout letterbox 4:3 na 16:9" - -msgid "Overscan (crop image borders)" -msgstr "Overscan (oøez okrajù obrazu)" - -msgid "Interlaced Field Order" -msgstr "Poøadí pùlsnímkù" - -msgid "Audio settings" -msgstr "Nastavení zvuku" - -msgid "Headphone audio mode" -msgstr "" - -msgid "Audio Compression" -msgstr "" - -msgid "Audio equalizer >>" -msgstr "Korekce zvuku (ekvalizér) >>" - -msgid "No subtitles available!" -msgstr "Titulky nejsou k dispozici!" - -msgid "Local Frontend" -msgstr "Lokální rozhraní" - -msgid "Aspect ratio" -msgstr "Pomìr stran" - -msgid "Video aspect ratio" -msgstr "Pomìr stran obrazu" - -msgid "On" -msgstr "zapnuto" - -msgid "Deinterlacing" -msgstr "Odstranìní prokládání" - -msgid "Upmix stereo to 5.1" -msgstr "Pøevzorkovat stereo na 5.1" - -msgid "Downmix AC3 to surround" -msgstr "Pøevzorkovat AC3 na surround" - -msgid "Default playlist not found" -msgstr "Výchozí seznam stop nenalezen" - -msgid "Default playlist is not symlink" -msgstr "Výchozí seznam stop není symbolický odkaz" - -msgid "Default playlist not defined" -msgstr "Výchozí seznam stop není definován" - -msgid "Delay" -msgstr "Zpo¾dìní" - -msgid "ms" -msgstr "ms" - -#, c-format -msgid "xineliboutput: hotkey %s not binded" -msgstr "xineliboutput: horká klávesa %s není pøiøazena" - -msgid "Audio" -msgstr "Zvuk" - -msgid "Speakers" -msgstr "Reproduktory" - -msgid "Volume control" -msgstr "Ovládání hlasitosti" - -msgid "Hardware" -msgstr "hardwarové" - -msgid "Software" -msgstr "softwarové" - -msgid "Mix to headphones" -msgstr "" - -msgid "Visualization" -msgstr "Vizualizace" - -msgid " Width" -msgstr " ©íøka" - -msgid "px" -msgstr "bodù" - -msgid " Height" -msgstr " Vý¹ka" - -msgid " Speed" -msgstr " Rychlost" - -msgid "fps" -msgstr "snímkù/sek." - -msgid "Audio Equalizer" -msgstr "Korekce zvuku" - -msgid "Video" -msgstr "Obraz" - -msgid " Autodetect letterbox" -msgstr " Automaticky detekovat letterbox" - -msgid " Soft start" -msgstr " Postupné zvìt¹ení" - -msgid " Crop to" -msgstr " Oøíznout na" - -msgid " Detect subtitles" -msgstr " Detekovat titulky" - -msgid "Software scaling" -msgstr "Softwarové ¹kálování" - -msgid " Change aspect ratio" -msgstr " Zmìna pomìru stran obrazu" - -msgid " Change video size" -msgstr " Zmìnit velikost obrazu" - -msgid " Allow downscaling" -msgstr " Povolit zmen¹ení" - -msgid "Post processing (ffmpeg)" -msgstr "Post processing (ffmpeg)" - -msgid " Quality" -msgstr " Kvalita" - -msgid " Mode" -msgstr " Mód" - -msgid " Method" -msgstr " Metoda" - -msgid " Cheap mode" -msgstr " Zjednodu¹ený mód" - -msgid " Pulldown" -msgstr "" - -msgid " Frame rate" -msgstr " Snímková rychlost" - -msgid " Judder Correction" -msgstr " Korekce chvìní" - -msgid " Use progressive frame flag" -msgstr "" - -msgid " Chroma Filter" -msgstr "" - -msgid "Sharpen / Blur" -msgstr "Zaostøení / rozmazání" - -msgid " Width of the luma matrix" -msgstr "" - -msgid " Height of the luma matrix" -msgstr "" - -msgid " Amount of luma sharpness/blur" -msgstr "" - -msgid " Width of the chroma matrix" -msgstr "" - -msgid " Height of the chroma matrix" -msgstr "" - -msgid " Amount of chroma sharpness/blur" -msgstr "" - -msgid "3D Denoiser" -msgstr "3D odstranìní ¹umu" - -msgid " Spatial luma strength" -msgstr "" - -msgid " Spatial chroma strength" -msgstr "" - -msgid " Temporal strength" -msgstr "" - -msgid "HUE" -msgstr "" - -msgid "Saturation" -msgstr "" - -msgid "Contrast" -msgstr "Kontrast" - -msgid "Brightness" -msgstr "Jas" - -msgid "Smooth fast forward" -msgstr "Plynulé pøetáèení" - -msgid "Fastest trick speed" -msgstr "" - -msgid "On-Screen Display" -msgstr "Obrazovkové menu" - -msgid "Hide main menu" -msgstr "Nezobrazovat v hlavním menu" - -msgid "Blending method" -msgstr "" - -msgid " Use hardware for low-res video" -msgstr "" - -msgid "Scaling method" -msgstr "" - -msgid "Show all layers" -msgstr "Zobrazit v¹echny vrstvy" - -msgid "Dynamic transparency correction" -msgstr "Úprava dynamické prùhlednosti" - -msgid "Static transparency correction" -msgstr "Úprava statické prùhlednosti" - -msgid "External subtitle size" -msgstr "Velikost externích titulkù" - -msgid "Decoder" -msgstr "Dekodér" - -msgid "Buffer size" -msgstr "Velikost vyrovnávací pamìti" - -msgid " Number of PES packets" -msgstr " Poèet PES paketù" - -msgid "Local Display Frontend" -msgstr "Lokální zobrazovací rozhraní" - -msgid "Use keyboard" -msgstr "Pou¾ívat klávesnici" - -msgid "Driver" -msgstr "Ovladaè" - -msgid "Display address" -msgstr "" - -msgid "Framebuffer device" -msgstr "" - -msgid "Fullscreen mode" -msgstr "Celoobrazovkový re¾im" - -msgid " Window width" -msgstr " ©íøka okna" - -msgid " Window height" -msgstr " Vý¹ka okna" - -msgid "Window aspect" -msgstr "Pomìr stran okna" - -msgid "Scale to window size" -msgstr "©kálovat do velikosti okna" - -msgid "Port" -msgstr "Port" - -msgid "Remote Clients" -msgstr "Vzdálení klienti" - -msgid "Allow remote clients" -msgstr "Povolit vzdálené klienty" - -msgid " Listen port (TCP and broadcast)" -msgstr "" - -msgid " Listen address" -msgstr "" - -msgid " Remote keyboard" -msgstr "" - -msgid " PIPE transport" -msgstr " PIPE transport" - -msgid " TCP transport" -msgstr " TCP transport" - -msgid " UDP transport" -msgstr " UDP transport" - -msgid " RTP (multicast) transport" -msgstr " RTP (multicast) transport" - -msgid " Address" -msgstr " Adresa" - -msgid " Port" -msgstr " Port" - -msgid " TTL" -msgstr "" - -msgid " Transmit always on" -msgstr " Pøenos stále zapnut" - -msgid " SAP announcements" -msgstr "" - -msgid " Server announce broadcasts" -msgstr "" - -msgid " HTTP transport for media files" -msgstr " HTTP transport pro média" - -msgid "Additional network services" -msgstr "Dal¹í sí»ové slu¾by" - -msgid "HTTP server" -msgstr "HTTP server" - -msgid "HTTP clients can control VDR" -msgstr "HTTP klienti mohou ovládat VDR" - -msgid "RTSP server" -msgstr "RTSP server" - -msgid "RTSP clients can control VDR" -msgstr "RTSP klienti mohou ovládat VDR" - -msgid "Playlist settings" -msgstr "Nastavení seznamu stop" - -msgid "Show the track number" -msgstr "Zobrazovat èíslo stopy" - -msgid "Show the name of the artist" -msgstr "Zobrazovat jméno autora" - -msgid "Show the name of the album" -msgstr "Zobrazovat název alba" - -msgid "Scan for metainfo" -msgstr "Vyhledávat metainfo" - -msgid "Cache metainfo" -msgstr "Uchovávat metainfo" - -msgid "Grayscale" -msgstr "Odstíny ¹edi" - -msgid "Bitmap" -msgstr "Rastr" - -msgid "OSD" -msgstr "OSD" - -msgid "Media Player" -msgstr "Pøehrávaè médií" - -msgid "Test Images" -msgstr "Zku¹ební obrazce" - -msgid "X11/xine-lib output plugin" -msgstr "X11/xine-lib výstupní plugin" diff --git a/po/de_DE.po b/po/de_DE.po deleted file mode 100644 index 687e8488..00000000 --- a/po/de_DE.po +++ /dev/null @@ -1,614 +0,0 @@ -# VDR plugin language source file. -# Copyright (C) 2007 Klaus Schmidinger -# This file is distributed under the same license as the VDR package. -# Udo Richter -# -msgid "" -msgstr "" -"Project-Id-Version: VDR 1.5.7\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2008-04-15 00:22+0300\n" -"PO-Revision-Date: 2007-11-23 10:17+0200\n" -"Last-Translator: Udo Richter\n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=ISO-8859-15\n" -"Content-Transfer-Encoding: 8bit\n" - -msgid "custom" -msgstr "Benutzerdefiniert" - -msgid "tiny" -msgstr "Winzig" - -msgid "small" -msgstr "Klein" - -msgid "medium" -msgstr "Mittel" - -msgid "large" -msgstr "Groß" - -msgid "huge" -msgstr "Riesig" - -msgid "automatic" -msgstr "Automatik" - -msgid "default" -msgstr "Standard" - -msgid "Pan&Scan" -msgstr "Pan&Scan" - -msgid "CenterCutOut" -msgstr "CenterCutOut" - -msgid "square" -msgstr "" - -msgid "anamorphic" -msgstr "" - -msgid "DVB" -msgstr "" - -msgid "off" -msgstr "Aus" - -msgid "normal" -msgstr "Normal" - -msgid "inverted" -msgstr "Invertiert" - -msgid "no audio" -msgstr "Kein Audio" - -msgid "no video" -msgstr "Kein Video" - -msgid "Off" -msgstr "Aus" - -msgid "Goom" -msgstr "Goom" - -msgid "Oscilloscope" -msgstr "Oszilloskop" - -msgid "FFT Scope" -msgstr "FFT Spektrum" - -msgid "FFT Graph" -msgstr "FFT Graph" - -msgid "Mono 1.0" -msgstr "" - -msgid "Stereo 2.0" -msgstr "" - -msgid "Headphones 2.0" -msgstr "" - -msgid "Stereo 2.1" -msgstr "" - -msgid "Surround 3.0" -msgstr "" - -msgid "Surround 4.0" -msgstr "" - -msgid "Surround 4.1" -msgstr "" - -msgid "Surround 5.0" -msgstr "" - -msgid "Surround 5.1" -msgstr "" - -msgid "Surround 6.0" -msgstr "" - -msgid "Surround 6.1" -msgstr "" - -msgid "Surround 7.1" -msgstr "" - -msgid "Pass Through" -msgstr "" - -msgid "very large" -msgstr "" - -msgid "no" -msgstr "" - -msgid "grayscale" -msgstr "" - -msgid "transparent" -msgstr "" - -msgid "transparent grayscale" -msgstr "" - -msgid "yes" -msgstr "" - -msgid "nearest" -msgstr "" - -msgid "bilinear" -msgstr "" - -msgid "Frontend initialization failed" -msgstr "Initialisierung des Frontends fehlgeschlagen" - -msgid "Server initialization failed" -msgstr "Initialisierung des Servers fehlgeschlagen" - -msgid "Playlist" -msgstr "Wiedergabeliste" - -msgid "Button$Random" -msgstr "Zufall" - -msgid "Button$Normal" -msgstr "Normal" - -msgid "Button$Add files" -msgstr "Füge Dateien hinzu" - -msgid "Button$Remove" -msgstr "Entferne" - -msgid "Button$Sort" -msgstr "Sortiere" - -msgid "Queued to playlist" -msgstr "Hänge an Wiedergabeliste an" - -msgid "Random play" -msgstr "Zufallswiedergabe" - -msgid "Normal play" -msgstr "Normale Wiedergabe" - -msgid "Delete image ?" -msgstr "Bild löschen?" - -msgid "Images" -msgstr "Bilder" - -msgid "Play music" -msgstr "Musik abspielen" - -msgid "Add to playlist" -msgstr "Füge zur Wiedergabeliste hinzu" - -msgid "Play file" -msgstr "Datei abspielen" - -msgid "Button$Queue" -msgstr "Warteschlange" - -msgid "Subtitles" -msgstr "Untertitel" - -msgid "Media" -msgstr "Medien" - -msgid "Play file >>" -msgstr "Datei abspielen >>" - -msgid "Play music >>" -msgstr "Musik abspielen >>" - -msgid "View images >>" -msgstr "Bilder ansehen >>" - -msgid "Play remote DVD >>" -msgstr "Entfernte DVD abspielen >>" - -msgid "Play DVD disc >>" -msgstr "DVD abspielen" - -msgid "Play remote CD >>" -msgstr "Entfernte CD abspielen >>" - -msgid "Play audio CD >>" -msgstr "Musik-CD abspielen >>" - -msgid "Select subtitle track >>" -msgstr "Wähle Untertitel >>" - -msgid "Video settings" -msgstr "Video-Einstellungen" - -msgid "Play only audio" -msgstr "Nur Audio spielen" - -msgid "Crop letterbox 4:3 to 16:9" -msgstr "Schneide letterbox 4:3 zu 16:9" - -msgid "Overscan (crop image borders)" -msgstr "Overscan (Bildränder abschneiden)" - -msgid "Interlaced Field Order" -msgstr "Interlaced Halbbild-Reihenfolge" - -msgid "Audio settings" -msgstr "Audio-Einstellungen" - -msgid "Headphone audio mode" -msgstr "" - -msgid "Audio Compression" -msgstr "Audio-Komprimierung" - -msgid "Audio equalizer >>" -msgstr "Audio-Equalizer >>" - -msgid "No subtitles available!" -msgstr "Keine Untertitel verfügbar!" - -msgid "Local Frontend" -msgstr "Lokale Anzeige" - -msgid "Aspect ratio" -msgstr "Seitenverhältnis" - -msgid "Video aspect ratio" -msgstr "" - -msgid "On" -msgstr "" - -msgid "Deinterlacing" -msgstr "Deinterlacing" - -msgid "Upmix stereo to 5.1" -msgstr "Stereo zu 5.1 hoch mischen" - -msgid "Downmix AC3 to surround" -msgstr "AC3 zu Surround herunter mischen" - -msgid "Default playlist not found" -msgstr "" - -msgid "Default playlist is not symlink" -msgstr "" - -msgid "Default playlist not defined" -msgstr "" - -msgid "Delay" -msgstr "Verzögerung" - -msgid "ms" -msgstr "ms" - -#, c-format -msgid "xineliboutput: hotkey %s not binded" -msgstr "" - -msgid "Audio" -msgstr "Audio" - -msgid "Speakers" -msgstr "Lautsprecher" - -msgid "Volume control" -msgstr "" - -msgid "Hardware" -msgstr "" - -msgid "Software" -msgstr "" - -msgid "Mix to headphones" -msgstr "" - -msgid "Visualization" -msgstr "Visualisierung" - -msgid " Width" -msgstr " Breite" - -msgid "px" -msgstr "px" - -msgid " Height" -msgstr " Höhe" - -msgid " Speed" -msgstr " Bildrate" - -msgid "fps" -msgstr "" - -msgid "Audio Equalizer" -msgstr "Audio Equalizer" - -msgid "Video" -msgstr "Video" - -msgid " Autodetect letterbox" -msgstr " Letterbox automatisch erkennen" - -msgid " Soft start" -msgstr " Weich starten" - -msgid " Crop to" -msgstr " Schneide auf" - -msgid " Detect subtitles" -msgstr " Erkenne Untertitel" - -msgid "Software scaling" -msgstr "" - -msgid " Change aspect ratio" -msgstr "" - -msgid " Change video size" -msgstr "" - -msgid " Allow downscaling" -msgstr " Verkleinern zulassen" - -msgid "Post processing (ffmpeg)" -msgstr "Nachbearbeitung (ffmpeg)" - -msgid " Quality" -msgstr " Qualität" - -msgid " Mode" -msgstr " Modus" - -msgid " Method" -msgstr " Methode" - -msgid " Cheap mode" -msgstr " einfacher Modus" - -msgid " Pulldown" -msgstr " Pulldown" - -msgid " Frame rate" -msgstr " Bildrate" - -msgid " Judder Correction" -msgstr " Ruckel-Korrektur" - -msgid " Use progressive frame flag" -msgstr " Nutze progressive frame flag" - -msgid " Chroma Filter" -msgstr " Chrominanz-Filter" - -msgid "Sharpen / Blur" -msgstr "" - -msgid " Width of the luma matrix" -msgstr "" - -msgid " Height of the luma matrix" -msgstr "" - -msgid " Amount of luma sharpness/blur" -msgstr "" - -msgid " Width of the chroma matrix" -msgstr "" - -msgid " Height of the chroma matrix" -msgstr "" - -msgid " Amount of chroma sharpness/blur" -msgstr "" - -msgid "3D Denoiser" -msgstr "" - -msgid " Spatial luma strength" -msgstr "" - -msgid " Spatial chroma strength" -msgstr "" - -msgid " Temporal strength" -msgstr "" - -msgid "HUE" -msgstr "Farbton" - -msgid "Saturation" -msgstr "Sättigung" - -msgid "Contrast" -msgstr "Kontrast" - -msgid "Brightness" -msgstr "Helligkeit" - -msgid "Smooth fast forward" -msgstr "" - -msgid "Fastest trick speed" -msgstr "" - -msgid "On-Screen Display" -msgstr "On-Screen Display" - -msgid "Hide main menu" -msgstr "Verstecke Hauptmenü" - -msgid "Blending method" -msgstr "" - -msgid " Use hardware for low-res video" -msgstr "" - -msgid "Scaling method" -msgstr "" - -msgid "Show all layers" -msgstr "" - -msgid "Dynamic transparency correction" -msgstr "Dynamische Transparenz-Korrektur" - -msgid "Static transparency correction" -msgstr "Statische Transparenz-Korrektur" - -msgid "External subtitle size" -msgstr "Untertitel größe" - -msgid "Decoder" -msgstr "Dekoder" - -msgid "Buffer size" -msgstr "Puffergröße" - -msgid " Number of PES packets" -msgstr " Anzahl PES-Pakete" - -msgid "Local Display Frontend" -msgstr "Lokale Bildschirmanzeige" - -msgid "Use keyboard" -msgstr "Tastatur benutzen" - -msgid "Driver" -msgstr "Treiber" - -msgid "Display address" -msgstr "Bildschirm-Adresse" - -msgid "Framebuffer device" -msgstr "Framebuffer-Device" - -msgid "Fullscreen mode" -msgstr "Vollbild-Modus" - -msgid " Window width" -msgstr " Fensterbreite" - -msgid " Window height" -msgstr " Fensterhöhe" - -msgid "Window aspect" -msgstr "Fenster-Seitenverhältnis" - -msgid "Scale to window size" -msgstr "Skaliere auf Fenster-Größe" - -msgid "Port" -msgstr "Port" - -msgid "Remote Clients" -msgstr "Entfernte Clients" - -msgid "Allow remote clients" -msgstr "Erlaube entfernte Clients" - -msgid " Listen port (TCP and broadcast)" -msgstr " Empfangender Port (TCP und Broadcast)" - -msgid " Listen address" -msgstr "" - -msgid " Remote keyboard" -msgstr " Tastaturfernsteuerung" - -msgid " PIPE transport" -msgstr " Pipe-Übertragung" - -msgid " TCP transport" -msgstr " TCP-Übertragung" - -msgid " UDP transport" -msgstr " UDP-Übertragung" - -msgid " RTP (multicast) transport" -msgstr " RTP (multicast) Übertragung" - -msgid " Address" -msgstr " Multicast-Adresse" - -msgid " Port" -msgstr " Multicast-Port" - -msgid " TTL" -msgstr " Multicast-TTL" - -msgid " Transmit always on" -msgstr " Immer senden" - -msgid " SAP announcements" -msgstr " SAP-Ankündigungen" - -msgid " Server announce broadcasts" -msgstr " Server-Bekanntmachung Broadcast" - -msgid " HTTP transport for media files" -msgstr " HTTP-Verbindung für Medien-Dateien" - -msgid "Additional network services" -msgstr "Zusätzliche Netzwerk-Services" - -msgid "HTTP server" -msgstr "HTTP-Server" - -msgid "HTTP clients can control VDR" -msgstr "HTTP-Clients können VDR kontrollieren" - -msgid "RTSP server" -msgstr "RTSP-Server" - -msgid "RTSP clients can control VDR" -msgstr "RTSP-Clients können VDR kontrollieren" - -msgid "Playlist settings" -msgstr "" - -msgid "Show the track number" -msgstr "" - -msgid "Show the name of the artist" -msgstr "" - -msgid "Show the name of the album" -msgstr "" - -msgid "Scan for metainfo" -msgstr "" - -msgid "Cache metainfo" -msgstr "" - -msgid "Grayscale" -msgstr "Graustufen" - -msgid "Bitmap" -msgstr "Bitmap" - -msgid "OSD" -msgstr "" - -msgid "Media Player" -msgstr "Medien..." - -msgid "Test Images" -msgstr "Testbilder" - -msgid "X11/xine-lib output plugin" -msgstr "X11/xine-lib Ausgabe-Plugin" diff --git a/po/fi_FI.po b/po/fi_FI.po deleted file mode 100644 index 4043bf98..00000000 --- a/po/fi_FI.po +++ /dev/null @@ -1,616 +0,0 @@ -# VDR plugin language source file. -# Copyright (C) 2007 Klaus Schmidinger -# This file is distributed under the same license as the VDR package. -# Petri Hintukainen -# Rolf Ahrenberg -# -msgid "" -msgstr "" -"Project-Id-Version: VDR 1.5.7\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2008-04-15 00:22+0300\n" -"PO-Revision-Date: 2007-11-23 10:17+0200\n" -"Last-Translator: Petri Hintukainen\n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=ISO-8859-15\n" -"Content-Transfer-Encoding: 8bit\n" - -msgid "custom" -msgstr "oma" - -msgid "tiny" -msgstr "olematon" - -msgid "small" -msgstr "pieni" - -msgid "medium" -msgstr "keskikokoinen" - -msgid "large" -msgstr "suuri" - -msgid "huge" -msgstr "valtava" - -msgid "automatic" -msgstr "automaattinen" - -msgid "default" -msgstr "oletus" - -msgid "Pan&Scan" -msgstr "Pan&Scan" - -msgid "CenterCutOut" -msgstr "CenterCutOut" - -msgid "square" -msgstr "neliö" - -msgid "anamorphic" -msgstr "anamorfinen" - -msgid "DVB" -msgstr "" - -msgid "off" -msgstr "ei käytössä" - -msgid "normal" -msgstr "normaali" - -msgid "inverted" -msgstr "käänteinen" - -msgid "no audio" -msgstr "ei ääntä" - -msgid "no video" -msgstr "ei kuvaa" - -msgid "Off" -msgstr "ei käytössä" - -msgid "Goom" -msgstr "Goom" - -msgid "Oscilloscope" -msgstr "Oskilloskooppi" - -msgid "FFT Scope" -msgstr "Spektri" - -msgid "FFT Graph" -msgstr "Spektrogrammi" - -msgid "Mono 1.0" -msgstr "" - -msgid "Stereo 2.0" -msgstr "" - -msgid "Headphones 2.0" -msgstr "Kuulokkeet 2.0" - -msgid "Stereo 2.1" -msgstr "" - -msgid "Surround 3.0" -msgstr "" - -msgid "Surround 4.0" -msgstr "" - -msgid "Surround 4.1" -msgstr "" - -msgid "Surround 5.0" -msgstr "" - -msgid "Surround 5.1" -msgstr "" - -msgid "Surround 6.0" -msgstr "" - -msgid "Surround 6.1" -msgstr "" - -msgid "Surround 7.1" -msgstr "" - -msgid "Pass Through" -msgstr "Läpivienti" - -msgid "very large" -msgstr "erittäin suuri" - -msgid "no" -msgstr "" - -msgid "grayscale" -msgstr "" - -msgid "transparent" -msgstr "" - -msgid "transparent grayscale" -msgstr "" - -msgid "yes" -msgstr "" - -msgid "nearest" -msgstr "" - -msgid "bilinear" -msgstr "" - -msgid "Frontend initialization failed" -msgstr "Näyttölaitteen alustus epäonnistui" - -msgid "Server initialization failed" -msgstr "Palvelimen käynnistys epäonnistui" - -msgid "Playlist" -msgstr "Soittolista" - -msgid "Button$Random" -msgstr "Satunnaistoisto" - -msgid "Button$Normal" -msgstr "Normaali toisto" - -msgid "Button$Add files" -msgstr "Lisää" - -msgid "Button$Remove" -msgstr "Poista" - -msgid "Button$Sort" -msgstr "Järjestä" - -msgid "Queued to playlist" -msgstr "Lisätty soittolistalle" - -msgid "Random play" -msgstr "Satunnaistoisto" - -msgid "Normal play" -msgstr "Normaali toisto" - -msgid "Delete image ?" -msgstr "Poistetaanko kuva ?" - -msgid "Images" -msgstr "Kuvat" - -msgid "Play music" -msgstr "Toista musiikkia" - -msgid "Add to playlist" -msgstr "Lisää soittolistalle" - -msgid "Play file" -msgstr "Toista tiedosto" - -msgid "Button$Queue" -msgstr "Soittolistalle" - -msgid "Subtitles" -msgstr "Tekstitys" - -msgid "Media" -msgstr "Media" - -msgid "Play file >>" -msgstr "Toista tiedosto >>" - -msgid "Play music >>" -msgstr "Toista musiikkia >>" - -msgid "View images >>" -msgstr "Katsele kuvia >>" - -msgid "Play remote DVD >>" -msgstr "Toista DVD-levy etäkoneesta >>" - -msgid "Play DVD disc >>" -msgstr "Toista DVD-levy >>" - -msgid "Play remote CD >>" -msgstr "Toista CD-levy etäkoneesta >>" - -msgid "Play audio CD >>" -msgstr "Toista CD-levy >>" - -msgid "Select subtitle track >>" -msgstr "Valitse tekstityskieli >>" - -msgid "Video settings" -msgstr "Videoasetukset" - -msgid "Play only audio" -msgstr "Toista pelkkä ääni" - -msgid "Crop letterbox 4:3 to 16:9" -msgstr "Leikkaa 4:3-letterbox 16:9:ksi" - -msgid "Overscan (crop image borders)" -msgstr "Leikkaa kuvan reunoja (overscan)" - -msgid "Interlaced Field Order" -msgstr "Lomitettujen kenttien järjestys" - -msgid "Audio settings" -msgstr "Ääniasetukset" - -msgid "Headphone audio mode" -msgstr "" - -msgid "Audio Compression" -msgstr "Voimista hiljaisia ääniä" - -msgid "Audio equalizer >>" -msgstr "Taajuuskorjain >>" - -msgid "No subtitles available!" -msgstr "Ei tekstitystä" - -msgid "Local Frontend" -msgstr "Paikallinen näyttö" - -msgid "Aspect ratio" -msgstr "Kuvasuhde" - -msgid "Video aspect ratio" -msgstr "Videon kuvasuhde" - -msgid "On" -msgstr "" - -msgid "Deinterlacing" -msgstr "Lomituksen poisto" - -msgid "Upmix stereo to 5.1" -msgstr "Miksaa stereoääni 5.1-kanavaiseksi" - -msgid "Downmix AC3 to surround" -msgstr "Miksaa AC3-ääni surroundiksi" - -msgid "Default playlist not found" -msgstr "" - -msgid "Default playlist is not symlink" -msgstr "" - -msgid "Default playlist not defined" -msgstr "" - -msgid "Delay" -msgstr "Viive" - -msgid "ms" -msgstr "ms" - -#, c-format -msgid "xineliboutput: hotkey %s not binded" -msgstr "" - -msgid "Audio" -msgstr "Ääni" - -msgid "Speakers" -msgstr "Kaiuttimet" - -msgid "Volume control" -msgstr "Äänenvoimakkuuden säätö" - -msgid "Hardware" -msgstr "Laitteistolla" - -msgid "Software" -msgstr "Ohjelmallisesti" - -msgid "Mix to headphones" -msgstr "" - -msgid "Visualization" -msgstr "Visualisointi" - -msgid " Width" -msgstr " Leveys" - -msgid "px" -msgstr "px" - -msgid " Height" -msgstr " Korkeus" - -msgid " Speed" -msgstr " Nopeus" - -msgid "fps" -msgstr "" - -msgid "Audio Equalizer" -msgstr "Taajuuskorjain" - -msgid "Video" -msgstr "Kuva" - -msgid " Autodetect letterbox" -msgstr " Tunnista letterbox automaattisesti" - -msgid " Soft start" -msgstr " Portaittainen aloitus" - -msgid " Crop to" -msgstr " Leikkaa kokoon" - -msgid " Detect subtitles" -msgstr " Huomioi tekstitys" - -msgid "Software scaling" -msgstr "Skaalaa ohjelmistolla" - -msgid " Change aspect ratio" -msgstr " Muuta kuvasuhdetta" - -msgid " Change video size" -msgstr " Muuta videokuvan kokoa" - -msgid " Allow downscaling" -msgstr " Salli skaalaus pienemmäksi" - -msgid "Post processing (ffmpeg)" -msgstr "Käytä jälkikäsittelyä (ffmpeg)" - -msgid " Quality" -msgstr " Laatu" - -msgid " Mode" -msgstr " Moodi" - -msgid " Method" -msgstr " Menetelmä" - -msgid " Cheap mode" -msgstr " Käytä Cheap-moodia" - -msgid " Pulldown" -msgstr " Pulldown-moodi" - -msgid " Frame rate" -msgstr " Ruudunpäivitys" - -msgid " Judder Correction" -msgstr " Käytä tärinänkorjausta" - -msgid " Use progressive frame flag" -msgstr " Tunnista progressiivinen kuva" - -msgid " Chroma Filter" -msgstr " Käytä Chroma-suodinta" - -msgid "Sharpen / Blur" -msgstr "Terävöinti / Sumennus" - -msgid " Width of the luma matrix" -msgstr " Luma-matriisin leveys" - -msgid " Height of the luma matrix" -msgstr " Luma-matriisin korkeus" - -msgid " Amount of luma sharpness/blur" -msgstr " Luma-terävöinti/-sumennus" - -msgid " Width of the chroma matrix" -msgstr " Chroma-matriisin leveys" - -msgid " Height of the chroma matrix" -msgstr " Chroma-matriisin korkeus" - -msgid " Amount of chroma sharpness/blur" -msgstr " Chroma-terävöinti/-sumennus" - -msgid "3D Denoiser" -msgstr "3D kohinanpoisto" - -msgid " Spatial luma strength" -msgstr " Luman tilavoimakkuus" - -msgid " Spatial chroma strength" -msgstr " Chroman tilavoimakkuus" - -msgid " Temporal strength" -msgstr " Ajallinen voimakkuus" - -msgid "HUE" -msgstr "Värisävy" - -msgid "Saturation" -msgstr "Saturaatio" - -msgid "Contrast" -msgstr "Kontrasti" - -msgid "Brightness" -msgstr "Kirkkaus" - -msgid "Smooth fast forward" -msgstr "Tasainen kuvakelaus" - -msgid "Fastest trick speed" -msgstr "Suurin kelausnopeus" - -msgid "On-Screen Display" -msgstr "Kuvaruutunäyttö" - -msgid "Hide main menu" -msgstr "Piilota valinta päävalikossa" - -msgid "Blending method" -msgstr "Piirtotapa" - -msgid " Use hardware for low-res video" -msgstr " Laitteisto matalaresoluutioisella videolla" - -msgid "Scaling method" -msgstr "Skaalaustapa" - -msgid "Show all layers" -msgstr "Näytä kaikki kerrokset" - -msgid "Dynamic transparency correction" -msgstr "Dynaaminen läpinäkyvyyden korjaus" - -msgid "Static transparency correction" -msgstr "Läpinäkyvyyden korjaus" - -msgid "External subtitle size" -msgstr "Erillisen tekstityksen koko" - -msgid "Decoder" -msgstr "Dekooderi" - -msgid "Buffer size" -msgstr "Puskurin koko" - -msgid " Number of PES packets" -msgstr " PES-pakettien lukumäärä" - -msgid "Local Display Frontend" -msgstr "Paikallinen näyttö" - -msgid "Use keyboard" -msgstr "Käytä näppäimistöä" - -msgid "Driver" -msgstr "Ohjain" - -msgid "Display address" -msgstr "Näytön osoite" - -msgid "Framebuffer device" -msgstr "Framebuffer-laite" - -msgid "Fullscreen mode" -msgstr "Kokoruututila" - -msgid " Window width" -msgstr " Ikkunan leveys" - -msgid " Window height" -msgstr " Ikkunan korkeus" - -msgid "Window aspect" -msgstr "Ikkunan kuvasuhde" - -msgid "Scale to window size" -msgstr "Skaalaa ikkunan kokoiseksi" - -msgid "Port" -msgstr "Portti" - -msgid "Remote Clients" -msgstr "Etäkäyttö" - -msgid "Allow remote clients" -msgstr "Salli etäkäyttö" - -msgid " Listen port (TCP and broadcast)" -msgstr " Kuuntele TCP-porttia" - -msgid " Listen address" -msgstr " Kuuntele osoitteessa" - -msgid " Remote keyboard" -msgstr " Käytä etänäppäimistöä" - -msgid " PIPE transport" -msgstr " PIPE-siirto" - -msgid " TCP transport" -msgstr " TCP-siirto" - -msgid " UDP transport" -msgstr " UDP-siirto" - -msgid " RTP (multicast) transport" -msgstr " RTP (multicast) -siirto" - -msgid " Address" -msgstr " Osoite" - -msgid " Port" -msgstr " Portti" - -msgid " TTL" -msgstr " TTL-aika" - -msgid " Transmit always on" -msgstr " Pidä lähetys aina päällä" - -msgid " SAP announcements" -msgstr " SAP-ilmoitukset" - -msgid " Server announce broadcasts" -msgstr " Palvelimen broadcast-ilmoitukset" - -msgid " HTTP transport for media files" -msgstr " HTTP -siirto mediatiedostoille" - -msgid "Additional network services" -msgstr "Muut verkkopalvelut" - -msgid "HTTP server" -msgstr "HTTP-palvelin" - -msgid "HTTP clients can control VDR" -msgstr "Anna HTTP-asiakkaiden ohjata VDR:ää" - -msgid "RTSP server" -msgstr "RTSP-palvelin" - -msgid "RTSP clients can control VDR" -msgstr "Anna RTSP-asiakkaiden ohjata VDR:ää" - -msgid "Playlist settings" -msgstr "Soittolistan asetukset" - -msgid "Show the track number" -msgstr "Näytä raidan numero" - -msgid "Show the name of the artist" -msgstr "Näytä esittäjän nimi" - -msgid "Show the name of the album" -msgstr "Näytä levyn nimi" - -msgid "Scan for metainfo" -msgstr "Tutki kappaleiden metatiedot" - -msgid "Cache metainfo" -msgstr "Tallenna metatieto" - -msgid "Grayscale" -msgstr "Harmaasävy" - -msgid "Bitmap" -msgstr "Bittikartta" - -msgid "OSD" -msgstr "" - -msgid "Media Player" -msgstr "Mediasoitin" - -msgid "Test Images" -msgstr "Testikuvat" - -msgid "X11/xine-lib output plugin" -msgstr "X11/xine-lib näyttölaite" - diff --git a/po/it_IT.po b/po/it_IT.po deleted file mode 100644 index 426fc7f1..00000000 --- a/po/it_IT.po +++ /dev/null @@ -1,613 +0,0 @@ -# VDR plugin language source file. -# Copyright (C) 2007 Klaus Schmidinger -# This file is distributed under the same license as the VDR package. -# -msgid "" -msgstr "" -"Project-Id-Version: VDR 1.5.7\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2008-04-15 00:22+0300\n" -"PO-Revision-Date: 2008-01-16 00:27+0100\n" -"Last-Translator: Gringo \n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=ISO-8859-15\n" -"Content-Transfer-Encoding: 8bit\n" - -msgid "custom" -msgstr "personalizza" - -msgid "tiny" -msgstr "molto piccolo" - -msgid "small" -msgstr "piccolo" - -msgid "medium" -msgstr "medio" - -msgid "large" -msgstr "grande" - -msgid "huge" -msgstr "enorme" - -msgid "automatic" -msgstr "automatica" - -msgid "default" -msgstr "predefinita" - -msgid "Pan&Scan" -msgstr "Pan&Scan" - -msgid "CenterCutOut" -msgstr "CenterCutOut" - -msgid "square" -msgstr "" - -msgid "anamorphic" -msgstr "" - -msgid "DVB" -msgstr "" - -msgid "off" -msgstr "spento" - -msgid "normal" -msgstr "normale" - -msgid "inverted" -msgstr "invertito" - -msgid "no audio" -msgstr "niente audio" - -msgid "no video" -msgstr "niente video" - -msgid "Off" -msgstr "Spento" - -msgid "Goom" -msgstr "Goom" - -msgid "Oscilloscope" -msgstr "Oscilloscopio" - -msgid "FFT Scope" -msgstr "Spettro FFT" - -msgid "FFT Graph" -msgstr "Grafico FFT" - -msgid "Mono 1.0" -msgstr "Mono 1.0" - -msgid "Stereo 2.0" -msgstr "Stereo 2.0" - -msgid "Headphones 2.0" -msgstr "Cuffie 2.0" - -msgid "Stereo 2.1" -msgstr "Stereo 2.1" - -msgid "Surround 3.0" -msgstr "Surround 3.0" - -msgid "Surround 4.0" -msgstr "Surround 4.0" - -msgid "Surround 4.1" -msgstr "Surround 4.1" - -msgid "Surround 5.0" -msgstr "Surround 5.0" - -msgid "Surround 5.1" -msgstr "Surround 5.1" - -msgid "Surround 6.0" -msgstr "Surround 6.0" - -msgid "Surround 6.1" -msgstr "Surround 6.1" - -msgid "Surround 7.1" -msgstr "Surround 7.1" - -msgid "Pass Through" -msgstr "Passa attraverso" - -msgid "very large" -msgstr "molto grande" - -msgid "no" -msgstr "no" - -msgid "grayscale" -msgstr "scala di grigi" - -msgid "transparent" -msgstr "trasparente" - -msgid "transparent grayscale" -msgstr "scala di grigi trasparente" - -msgid "yes" -msgstr "sì" - -msgid "nearest" -msgstr "" - -msgid "bilinear" -msgstr "" - -msgid "Frontend initialization failed" -msgstr "Inizializzazione frontend fallita" - -msgid "Server initialization failed" -msgstr "Inizializzazione server fallita" - -msgid "Playlist" -msgstr "Lista esecuzione" - -msgid "Button$Random" -msgstr "Casuale" - -msgid "Button$Normal" -msgstr "Normale" - -msgid "Button$Add files" -msgstr "Aggiungi files" - -msgid "Button$Remove" -msgstr "Rimuovi" - -msgid "Button$Sort" -msgstr "Ordina" - -msgid "Queued to playlist" -msgstr "Accoda alla lista esecuzione" - -msgid "Random play" -msgstr "Riproduzione casuale" - -msgid "Normal play" -msgstr "Riproduzione normale" - -msgid "Delete image ?" -msgstr "Cancellare immagine ?" - -msgid "Images" -msgstr "Immagini" - -msgid "Play music" -msgstr "Riproduci musica" - -msgid "Add to playlist" -msgstr "Aggiungi alla lista esecuzione" - -msgid "Play file" -msgstr "Riproduci file" - -msgid "Button$Queue" -msgstr "Coda" - -msgid "Subtitles" -msgstr "Sottotitoli" - -msgid "Media" -msgstr "Media" - -msgid "Play file >>" -msgstr "Riproduci file >>" - -msgid "Play music >>" -msgstr "Riproduci musica >>" - -msgid "View images >>" -msgstr "Visualizza immagini >>" - -msgid "Play remote DVD >>" -msgstr "Riproduci DVD remoto >>" - -msgid "Play DVD disc >>" -msgstr "Riproduci disco DVD >>" - -msgid "Play remote CD >>" -msgstr "Riproduci CD remoto >>" - -msgid "Play audio CD >>" -msgstr "Riproduci CD audio >>" - -msgid "Select subtitle track >>" -msgstr "Seleziona traccia sottotitoli >>" - -msgid "Video settings" -msgstr "Impostazioni video" - -msgid "Play only audio" -msgstr "Riproduci solo audio" - -msgid "Crop letterbox 4:3 to 16:9" -msgstr "Ritaglia letterbox 4:3 a 16:9" - -msgid "Overscan (crop image borders)" -msgstr "Overscan (ritaglia bordi immagine)" - -msgid "Interlaced Field Order" -msgstr "Ordine campo interlacciato" - -msgid "Audio settings" -msgstr "Impostazioni audio" - -msgid "Headphone audio mode" -msgstr "Modalità cuffie audio" - -msgid "Audio Compression" -msgstr "Compressione audio" - -msgid "Audio equalizer >>" -msgstr "Equalizzatore audio >>" - -msgid "No subtitles available!" -msgstr "Nessun sottotitolo disponibile!" - -msgid "Local Frontend" -msgstr "Frontend locale" - -msgid "Aspect ratio" -msgstr "Proporzioni" - -msgid "Video aspect ratio" -msgstr "" - -msgid "On" -msgstr "Attivo" - -msgid "Deinterlacing" -msgstr "Deinterlacciamento" - -msgid "Upmix stereo to 5.1" -msgstr "Suono da Stereo a 5.1" - -msgid "Downmix AC3 to surround" -msgstr "Suono da AC3 a surround" - -msgid "Default playlist not found" -msgstr "Lista esec. predefinita non trovata" - -msgid "Default playlist is not symlink" -msgstr "La lista esec. predefinita non è un link simbolico" - -msgid "Default playlist not defined" -msgstr "Lista esec. predefinita non definita" - -msgid "Delay" -msgstr "Ritardo" - -msgid "ms" -msgstr "ms" - -#, c-format -msgid "xineliboutput: hotkey %s not binded" -msgstr "xineliboutput: tasto %s non associato" - -msgid "Audio" -msgstr "Audio" - -msgid "Speakers" -msgstr "Altoparlanti" - -msgid "Volume control" -msgstr "Controllo volume" - -msgid "Hardware" -msgstr "Hardware" - -msgid "Software" -msgstr "Software" - -msgid "Mix to headphones" -msgstr "Suono a cuffie" - -msgid "Visualization" -msgstr "Visualizzazione" - -msgid " Width" -msgstr " Larghezza" - -msgid "px" -msgstr "px" - -msgid " Height" -msgstr " Altezza" - -msgid " Speed" -msgstr " Velocità" - -msgid "fps" -msgstr "fps" - -msgid "Audio Equalizer" -msgstr "Equalizzatore audio" - -msgid "Video" -msgstr "Video" - -msgid " Autodetect letterbox" -msgstr " Rileva letterbox in automatico" - -msgid " Soft start" -msgstr " Avvio leggero" - -msgid " Crop to" -msgstr " Ritaglia a" - -msgid " Detect subtitles" -msgstr " Rileva sottotitoli" - -msgid "Software scaling" -msgstr "" - -msgid " Change aspect ratio" -msgstr "" - -msgid " Change video size" -msgstr "" - -msgid " Allow downscaling" -msgstr " Permetti ridimensionamento" - -msgid "Post processing (ffmpeg)" -msgstr "Codifica (ffmpeg)" - -msgid " Quality" -msgstr " Qualità" - -msgid " Mode" -msgstr " Modalità" - -msgid " Method" -msgstr " Metodo" - -msgid " Cheap mode" -msgstr " Modo economico" - -msgid " Pulldown" -msgstr " Pulldown" - -msgid " Frame rate" -msgstr " Frame rate" - -msgid " Judder Correction" -msgstr " Correzione gamma" - -msgid " Use progressive frame flag" -msgstr " Utilizza flag frame progressivo" - -msgid " Chroma Filter" -msgstr " Filtro Chroma" - -msgid "Sharpen / Blur" -msgstr "Nitido / Blur" - -msgid " Width of the luma matrix" -msgstr " Larghezza della matrice luma" - -msgid " Height of the luma matrix" -msgstr " Altezza della matrice luma" - -msgid " Amount of luma sharpness/blur" -msgstr " Valore di nitidezza/blur luma" - -msgid " Width of the chroma matrix" -msgstr " Larghezza della matrice chroma" - -msgid " Height of the chroma matrix" -msgstr " Altezza della matrice chroma" - -msgid " Amount of chroma sharpness/blur" -msgstr " Valore di nitidezza/blur chroma" - -msgid "3D Denoiser" -msgstr "3D Denoiser" - -msgid " Spatial luma strength" -msgstr " Resistenza luma spaziale" - -msgid " Spatial chroma strength" -msgstr " Resistenza chroma spaziale" - -msgid " Temporal strength" -msgstr " Resistenza temporale" - -msgid "HUE" -msgstr "Tonalità" - -msgid "Saturation" -msgstr "Saturazione" - -msgid "Contrast" -msgstr "Contrasto" - -msgid "Brightness" -msgstr "Luminosità" - -msgid "Smooth fast forward" -msgstr "Avanzamento veloce leggero" - -msgid "Fastest trick speed" -msgstr "Velocità trucco più veloce" - -msgid "On-Screen Display" -msgstr "Messaggi in sovraimpressione (OSD)" - -msgid "Hide main menu" -msgstr "Nascondi voce nel menu principale" - -msgid "Blending method" -msgstr "" - -msgid " Use hardware for low-res video" -msgstr "" - -msgid "Scaling method" -msgstr "" - -msgid "Show all layers" -msgstr "Mostra tutti i livelli" - -msgid "Dynamic transparency correction" -msgstr "Correzione trasparenza dinamica" - -msgid "Static transparency correction" -msgstr "Correzione trasparenza statica" - -msgid "External subtitle size" -msgstr "Dimensione sottotitoli esterni" - -msgid "Decoder" -msgstr "Decoder" - -msgid "Buffer size" -msgstr "Dimensione buffer" - -msgid " Number of PES packets" -msgstr " Numero di pacchetti PES" - -msgid "Local Display Frontend" -msgstr "Frontend visualizzazione locale" - -msgid "Use keyboard" -msgstr "Utilizza tastiera" - -msgid "Driver" -msgstr "Driver" - -msgid "Display address" -msgstr "Mostra indirizzo" - -msgid "Framebuffer device" -msgstr "Periferica framebuffer" - -msgid "Fullscreen mode" -msgstr "Mod. schermo intero" - -msgid " Window width" -msgstr " Larghezza finestra" - -msgid " Window height" -msgstr " Altezza finestra" - -msgid "Window aspect" -msgstr "Aspetto finestra" - -msgid "Scale to window size" -msgstr "Scala a dimensione finestra" - -msgid "Port" -msgstr "Porta" - -msgid "Remote Clients" -msgstr "Client remoti" - -msgid "Allow remote clients" -msgstr "Permetti client remoti" - -msgid " Listen port (TCP and broadcast)" -msgstr " Porta in ascolto (TCP e broadcast)" - -msgid " Listen address" -msgstr " Indirizzo in ascolto" - -msgid " Remote keyboard" -msgstr " Tastiera remota" - -msgid " PIPE transport" -msgstr " Protocollo PIPE" - -msgid " TCP transport" -msgstr " Protocollo TCP" - -msgid " UDP transport" -msgstr " Protocollo UDP" - -msgid " RTP (multicast) transport" -msgstr " Protocollo RTP (multicast)" - -msgid " Address" -msgstr " Indirizzo" - -msgid " Port" -msgstr " Porta" - -msgid " TTL" -msgstr " TTL" - -msgid " Transmit always on" -msgstr " Trasmetti sempre" - -msgid " SAP announcements" -msgstr " Annunci SAP" - -msgid " Server announce broadcasts" -msgstr " Annuncio trasmissioni dal server" - -msgid " HTTP transport for media files" -msgstr " Protocollo HTTP per file multimediali" - -msgid "Additional network services" -msgstr "Ulteriori servizi di rete" - -msgid "HTTP server" -msgstr "Server HTTP" - -msgid "HTTP clients can control VDR" -msgstr "I client HTTP possono controllare VDR" - -msgid "RTSP server" -msgstr "Server RTSP" - -msgid "RTSP clients can control VDR" -msgstr "I client RTSP possono controllare VDR" - -msgid "Playlist settings" -msgstr "" - -msgid "Show the track number" -msgstr "" - -msgid "Show the name of the artist" -msgstr "" - -msgid "Show the name of the album" -msgstr "" - -msgid "Scan for metainfo" -msgstr "" - -msgid "Cache metainfo" -msgstr "" - -msgid "Grayscale" -msgstr "Scala di grigi" - -msgid "Bitmap" -msgstr "Bitmap" - -msgid "OSD" -msgstr "OSD" - -msgid "Media Player" -msgstr "Lettore multimediale" - -msgid "Test Images" -msgstr "Prova immagini" - -msgid "X11/xine-lib output plugin" -msgstr "Plugin uscita X11/xine-lib" diff --git a/po/ru_RU.po b/po/ru_RU.po deleted file mode 100644 index b9e7342a..00000000 --- a/po/ru_RU.po +++ /dev/null @@ -1,615 +0,0 @@ -# VDR plugin language source file. -# Copyright (C) 2007 Klaus Schmidinger -# This file is distributed under the same license as the VDR package. -# Vladimir Monchenko -# -msgid "" -msgstr "" -"Project-Id-Version: VDR 1.5.7\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2008-04-15 00:22+0300\n" -"PO-Revision-Date: 2007-11-23 10:17+0200\n" -"Last-Translator: Vladimir Monchenko\n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=ISO-8859-5\n" -"Content-Transfer-Encoding: 8bit\n" - -msgid "custom" -msgstr "¿ÞÛì×ÞÒÐâÕÛì" - -msgid "tiny" -msgstr "¾çÕÝì ÜÐÛÕÝìÚØÙ" - -msgid "small" -msgstr "¼ÐÛÕÝìÚØÙ" - -msgid "medium" -msgstr "ÁàÕÔÝØÙ" - -msgid "large" -msgstr "±ÞÛìèÞÙ" - -msgid "huge" -msgstr "¾çÕÝì ÑÞÛìÝÞÙ" - -msgid "automatic" -msgstr "°ÒâÞÜÐâØçÕáÚØ" - -msgid "default" -msgstr "¿Þ ãÜÞÛçÐÝØî" - -msgid "Pan&Scan" -msgstr "Pan&Scan" - -msgid "CenterCutOut" -msgstr "" - -msgid "square" -msgstr "" - -msgid "anamorphic" -msgstr "" - -msgid "DVB" -msgstr "" - -msgid "off" -msgstr "²ëÚÛ." - -msgid "normal" -msgstr "½ÞàÜÐÛìÝëÙ" - -msgid "inverted" -msgstr "¸ÝÒÕàâØàÞÒÐÝÞ" - -msgid "no audio" -msgstr "½Õâ ÐãÔØÞ" - -msgid "no video" -msgstr "½Õâ ÒØÔÕÞ" - -msgid "Off" -msgstr "" - -msgid "Goom" -msgstr "" - -msgid "Oscilloscope" -msgstr "" - -msgid "FFT Scope" -msgstr "" - -msgid "FFT Graph" -msgstr "" - -msgid "Mono 1.0" -msgstr "" - -msgid "Stereo 2.0" -msgstr "" - -msgid "Headphones 2.0" -msgstr "" - -msgid "Stereo 2.1" -msgstr "" - -msgid "Surround 3.0" -msgstr "" - -msgid "Surround 4.0" -msgstr "" - -msgid "Surround 4.1" -msgstr "" - -msgid "Surround 5.0" -msgstr "" - -msgid "Surround 5.1" -msgstr "" - -msgid "Surround 6.0" -msgstr "" - -msgid "Surround 6.1" -msgstr "" - -msgid "Surround 7.1" -msgstr "" - -msgid "Pass Through" -msgstr "" - -msgid "very large" -msgstr "" - -msgid "no" -msgstr "" - -msgid "grayscale" -msgstr "" - -msgid "transparent" -msgstr "" - -msgid "transparent grayscale" -msgstr "" - -msgid "yes" -msgstr "" - -msgid "nearest" -msgstr "" - -msgid "bilinear" -msgstr "" - -msgid "Frontend initialization failed" -msgstr "" - -msgid "Server initialization failed" -msgstr "" - -msgid "Playlist" -msgstr "" - -msgid "Button$Random" -msgstr "" - -msgid "Button$Normal" -msgstr "" - -msgid "Button$Add files" -msgstr "" - -msgid "Button$Remove" -msgstr "" - -msgid "Button$Sort" -msgstr "" - -msgid "Queued to playlist" -msgstr "" - -msgid "Random play" -msgstr "" - -msgid "Normal play" -msgstr "" - -msgid "Delete image ?" -msgstr "ÃÔÐÛØâì ÚÐàâØÝÚã ?" - -msgid "Images" -msgstr "¸×ÞÑàÐÖÕÝØï" - -msgid "Play music" -msgstr "" - -msgid "Add to playlist" -msgstr "" - -msgid "Play file" -msgstr "¿àÞØÓàÐâì äÐÙÛ" - -msgid "Button$Queue" -msgstr "" - -msgid "Subtitles" -msgstr "" - -msgid "Media" -msgstr "" - -msgid "Play file >>" -msgstr "¿àÞØÓàÐâì äÐÙÛ >>" - -msgid "Play music >>" -msgstr "¿àÞØÓàÐâì äÐÙÛ >>" - -msgid "View images >>" -msgstr "¿àÞáÜÞâàÕâì Ø×ÞÑàÐÖÕÝØï >>" - -msgid "Play remote DVD >>" -msgstr "" - -msgid "Play DVD disc >>" -msgstr "" - -msgid "Play remote CD >>" -msgstr "" - -msgid "Play audio CD >>" -msgstr "" - -msgid "Select subtitle track >>" -msgstr "" - -msgid "Video settings" -msgstr "" - -msgid "Play only audio" -msgstr "" - -msgid "Crop letterbox 4:3 to 16:9" -msgstr "" - -msgid "Overscan (crop image borders)" -msgstr "" - -msgid "Interlaced Field Order" -msgstr "ÇÕàÕ×áâàÞçÝëÙ ßÞàïÔÞÚ ßÞÛÕÙ" - -msgid "Audio settings" -msgstr "" - -msgid "Headphone audio mode" -msgstr "" - -msgid "Audio Compression" -msgstr "°ãÔØÞ ÚÞÜßàÕááØï" - -msgid "Audio equalizer >>" -msgstr "°ãÔØÞ íÚÒÐÛÐÙ×Õà >>" - -msgid "No subtitles available!" -msgstr "" - -msgid "Local Frontend" -msgstr "»ÞÚÐÛìÝëÙ äàÞÝâÕÝÔ" - -msgid "Aspect ratio" -msgstr "" - -msgid "Video aspect ratio" -msgstr "" - -msgid "On" -msgstr "" - -msgid "Deinterlacing" -msgstr "´ÕØÝâÕàÛÕÙáØÝÓ" - -msgid "Upmix stereo to 5.1" -msgstr "¿àÕÞÑàÐ×ÞÒÐâì áâÕàÕÞ Ò 5.1" - -msgid "Downmix AC3 to surround" -msgstr "" - -msgid "Default playlist not found" -msgstr "" - -msgid "Default playlist is not symlink" -msgstr "" - -msgid "Default playlist not defined" -msgstr "" - -msgid "Delay" -msgstr "·ÐÔÕàÖÚÐ" - -msgid "ms" -msgstr "ms" - -#, c-format -msgid "xineliboutput: hotkey %s not binded" -msgstr "" - -msgid "Audio" -msgstr "°ãÔØÞ" - -msgid "Speakers" -msgstr "" - -msgid "Volume control" -msgstr "" - -msgid "Hardware" -msgstr "" - -msgid "Software" -msgstr "" - -msgid "Mix to headphones" -msgstr "" - -msgid "Visualization" -msgstr "²Ø×ãÐÛØ×ÐæØï" - -msgid " Width" -msgstr "" - -msgid "px" -msgstr "ߨÚáÕÛÕÙ" - -msgid " Height" -msgstr "" - -msgid " Speed" -msgstr "" - -msgid "fps" -msgstr "" - -msgid "Audio Equalizer" -msgstr "°ãÔØÞ íÚÒÐÛÐÙ×Õà" - -msgid "Video" -msgstr "²ØÔÕÞ" - -msgid " Autodetect letterbox" -msgstr "" - -msgid " Soft start" -msgstr "" - -msgid " Crop to" -msgstr "" - -msgid " Detect subtitles" -msgstr "" - -msgid "Software scaling" -msgstr "" - -msgid " Change aspect ratio" -msgstr "" - -msgid " Change video size" -msgstr "" - -msgid " Allow downscaling" -msgstr " ¼ÐáèâÐÑØàÞÒÐâì á ßÐÔÕÝØÕÜ ÚÐçÕáâÒÐ" - -msgid "Post processing (ffmpeg)" -msgstr "" - -msgid " Quality" -msgstr "" - -msgid " Mode" -msgstr "" - -msgid " Method" -msgstr "" - -msgid " Cheap mode" -msgstr "" - -msgid " Pulldown" -msgstr "" - -msgid " Frame rate" -msgstr "" - -msgid " Judder Correction" -msgstr "" - -msgid " Use progressive frame flag" -msgstr "" - -msgid " Chroma Filter" -msgstr "" - -msgid "Sharpen / Blur" -msgstr "" - -msgid " Width of the luma matrix" -msgstr "" - -msgid " Height of the luma matrix" -msgstr "" - -msgid " Amount of luma sharpness/blur" -msgstr "" - -msgid " Width of the chroma matrix" -msgstr "" - -msgid " Height of the chroma matrix" -msgstr "" - -msgid " Amount of chroma sharpness/blur" -msgstr "" - -msgid "3D Denoiser" -msgstr "" - -msgid " Spatial luma strength" -msgstr "" - -msgid " Spatial chroma strength" -msgstr "" - -msgid " Temporal strength" -msgstr "" - -msgid "HUE" -msgstr "HUE" - -msgid "Saturation" -msgstr "½ÐáëéÕÝÝÞáâì" - -msgid "Contrast" -msgstr "ºÞÝâàÐáâÝÞáâì" - -msgid "Brightness" -msgstr "ÏàÚÞáâì" - -msgid "Smooth fast forward" -msgstr "" - -msgid "Fastest trick speed" -msgstr "" - -msgid "On-Screen Display" -msgstr "ÍÚàÐÝÝÞÕ ÜÕÝî" - -msgid "Hide main menu" -msgstr "ÁÚàëâì ÞáÝÞÒÝÞÕ ÜÕÝî" - -msgid "Blending method" -msgstr "" - -msgid " Use hardware for low-res video" -msgstr "" - -msgid "Scaling method" -msgstr "" - -msgid "Show all layers" -msgstr "" - -msgid "Dynamic transparency correction" -msgstr "´ØÝÐÜØçÕáÚÐï ÚÞààÕÚæØï ßàÞ×àÐçÝÞáâØ" - -msgid "Static transparency correction" -msgstr "ÁâÐâØçÕáÚÐï ÚÞààÕÚæØï ßàÞ×àÐçÝÞáâØ" - -msgid "External subtitle size" -msgstr "" - -msgid "Decoder" -msgstr "´ÕÚÞÔÕà" - -msgid "Buffer size" -msgstr "ÀÐ×ÜÕà ÑãäÕàÐ" - -msgid " Number of PES packets" -msgstr " PES ßÐÚÕâÞÒ" - -msgid "Local Display Frontend" -msgstr "ÄàÞÝâÕÝÔ ÛÞÚÐÛìÝÞÓÞ íÚàÐÝÐ" - -msgid "Use keyboard" -msgstr "¸áßÞÛì×ÞÒÐâì ÚÛÐÒØÐâãàã" - -msgid "Driver" -msgstr "´àÐÙÒÕà" - -msgid "Display address" -msgstr "°ÔàÕá ÔØáßÛÕï" - -msgid "Framebuffer device" -msgstr "Framebuffer ãáâàÞÙáâÒÞ" - -msgid "Fullscreen mode" -msgstr "¿ÞÛÝÞíÚàÐÝÝëÙ àÕÖØÜ" - -msgid " Window width" -msgstr " ÈØàØÝÐ ÞÚÝÐ" - -msgid " Window height" -msgstr " ²ëáÞâÐ ÞÚÝÐ" - -msgid "Window aspect" -msgstr "ÁÞÞâÝÞèÕÝØÕ áâÞàÞÝ" - -msgid "Scale to window size" -msgstr "¼ÐáèâÐÑØàÞÒÐâì Ò àÐ×ÜÕà ÞÚÝÐ" - -msgid "Port" -msgstr "¿Þàâ" - -msgid "Remote Clients" -msgstr "ÃÔÐÛÕÝÝëÕ ÚÛØÕÝâë" - -msgid "Allow remote clients" -msgstr "ÀÐ×àÕèØâì ãÔÐÛÕÝÝëå ÚÛØÕÝâÞÒ" - -msgid " Listen port (TCP and broadcast)" -msgstr " ¿Þàâ (TCP Ø èØàÞÚÞÒÕèÐâÕÛìÝëÙ)" - -msgid " Listen address" -msgstr "" - -msgid " Remote keyboard" -msgstr " ÃÔÐÛÕÝÝÐï ÚÛÐÒØÐâãàÐ" - -msgid " PIPE transport" -msgstr " PIPE âàÐÝáßÞàâ" - -msgid " TCP transport" -msgstr "TCP âàÐÝáßÞàâ" - -msgid " UDP transport" -msgstr "UDP âàÐÝáßÞàâ" - -msgid " RTP (multicast) transport" -msgstr " RTP (èØàÞÚÞÒÕéÐâÕÛìÝëÙ) âàÐÝáßÞàâ" - -msgid " Address" -msgstr "" - -msgid " Port" -msgstr "" - -msgid " TTL" -msgstr "" - -msgid " Transmit always on" -msgstr "" - -msgid " SAP announcements" -msgstr "" - -msgid " Server announce broadcasts" -msgstr " ÁÕàÒÕà ØáßÞÛì×ãÕâ èØàÞÚÞÒÕéÐÝØÕ" - -msgid " HTTP transport for media files" -msgstr "" - -msgid "Additional network services" -msgstr "" - -msgid "HTTP server" -msgstr "" - -msgid "HTTP clients can control VDR" -msgstr "" - -msgid "RTSP server" -msgstr "" - -msgid "RTSP clients can control VDR" -msgstr "" - -msgid "Playlist settings" -msgstr "" - -msgid "Show the track number" -msgstr "" - -msgid "Show the name of the artist" -msgstr "" - -msgid "Show the name of the album" -msgstr "" - -msgid "Scan for metainfo" -msgstr "" - -msgid "Cache metainfo" -msgstr "" - -msgid "Grayscale" -msgstr "¾ââÕÝÚØ áÕàÞÓÞ" - -msgid "Bitmap" -msgstr "±ØâÞÒÐï ÚÐàâÐ" - -msgid "OSD" -msgstr "" - -msgid "Media Player" -msgstr "Xine-lib" - -msgid "Test Images" -msgstr "ÂÕáâÞÒëÕ Ø×ÞÑàÐÖÕÝØï" - -msgid "X11/xine-lib output plugin" -msgstr "X11/xine-lib ÒØÔÕÞ ÜÞÔãÛì" - diff --git a/setup_menu.c b/setup_menu.c deleted file mode 100644 index 311096ac..00000000 --- a/setup_menu.c +++ /dev/null @@ -1,1957 +0,0 @@ -/* - * setup_menu.c: Setup Menu - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: setup_menu.c,v 1.56 2008-04-14 21:15:42 phintuka Exp $ - * - */ - -#include -#include -#include - -#include "setup_menu.h" -#include "device.h" -#include "menuitems.h" -#include "config.h" -#include "i18n.h" // trVDR for vdr-1.4.x -#include "osd.h" // cXinelibOsdProvider::RefreshOsd() - - -namespace XinelibOutputSetupMenu { - -//#define INTEGER_CONFIG_VIDEO_CONTROLS -//#define LINEAR_VIDEO_CONTROLS - -#define ISNUMBERKEY(k) (RAWKEY(k) >= k0 && RAWKEY(k) <= k9) - -//--- Setup Menu ------------------------------------------------------------- - -const char *ModeLineChars = - " 0123456789+-hvsync."; -const char *DriverNameChars = - " abcdefghijklmnopqrstuvwxyz0123456789-.,#~:;"; -const char *OptionsChars = - "=.,abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; -const char *LangNameChars = - "abcdefghijklmnopqrstuvwxyz"; - -const char *controls[] = - { "Off", - "[|---------------]","[|---------------]", - "[-|--------------]","[-|--------------]", - "[--|-------------]","[--|-------------]", - "[---|------------]","[---|------------]", - "[----|-----------]","[----|-----------]", - "[-----|----------]","[-----|----------]", - "[------|---------]","[------|---------]", - "[-------|--------]","[-------|--------]", - "[--------|-------]","[--------|-------]", - "[---------|------]","[---------|------]", - "[----------|-----]","[----------|-----]", - "[-----------|----]","[-----------|----]", - "[------------|---]","[------------|---]", - "[-------------|--]","[-------------|--]", - "[--------------|-]","[--------------|-]", - "[---------------|]","[---------------|]", - NULL - }; - -#ifdef LINEAR_VIDEO_CONTROLS -# define CONTROL_TO_INDEX(val) ((val)>=0 ? ((val)>>11)+1 : 0) -# define INDEX_TO_CONTROL(ind) ((ind)==0 ? -1 : ((ind)-1)<<11) -#else -const int ind2ctrl_tbl[33] = { - -1, 0, 0x0001, 0x0002, 0x0003, 0x0004, 0x0007, 0x000a, - 0x000f, 0x0014, 0x001f, 42, 0x003f, 80, 0x007f, 170, - 0x00ff, 336, 0x01ff, 682, 0x03ff, 1630, 0x07ff, 2730, - 0x0fff, 5726, 0x1fff, 10858, 0x3fff, 22110, 0x7fff, 43224, - 0xffff }; -static int CONTROL_TO_INDEX(int val) -{ - for(int i=0; i<33;i++) - if(val<=ind2ctrl_tbl[i]) - return i; - return 32; -} -static int INDEX_TO_CONTROL(int ind) -{ - if(ind<0) ind=0; - if(ind>32) ind=32; - return ind2ctrl_tbl[ind]; -} -#endif - -static cOsdItem *NewTitle(const char *s) -{ - char str[128]; - cOsdItem *tmp; - snprintf(str, sizeof(str), "----- %s -----", s); - str[sizeof(str)-1] = 0; - tmp = new cOsdItem(str); - tmp->SetSelectable(false); - return tmp; -} - -//--- cMenuSetupAudio -------------------------------------------------------- - -class cMenuSetupAudio : public cMenuSetupPage -{ - private: - config_t newconfig; - int visualization; - int goom_width, goom_height, goom_fps; - - cOsdItem *audio_ctrl_speakers; - cOsdItem *audio_ctrl_volume; - cOsdItem *audio_ctrl_delay; - cOsdItem *audio_ctrl_compression; - cOsdItem *audio_ctrl_upmix; - cOsdItem *audio_ctrl_surround; - cOsdItem *audio_ctrl_headphone; - cOsdItem *audio_ctrl_vis; - - protected: - virtual void Store(void); - void Set(void); - - public: - cMenuSetupAudio(void); - ~cMenuSetupAudio(void); - - virtual eOSState ProcessKey(eKeys Key); -}; - -cMenuSetupAudio::cMenuSetupAudio(void) -{ - memcpy(&newconfig, &xc, sizeof(config_t)); - - visualization = strstra(xc.audio_visualization, - xc.s_audioVisualizations, - 0); - goom_width = 720; - goom_height = 576; - goom_fps = 25; - - char *pt; - if(NULL != (pt=strstr(xc.audio_vis_goom_opts, "width="))) - goom_width = max(320, min(1920, atoi(pt+6))); - if(NULL != (pt=strstr(xc.audio_vis_goom_opts, "height="))) - goom_height = max(240, min(1280, atoi(pt+7))); - if(NULL != (pt=strstr(xc.audio_vis_goom_opts, "fps="))) - goom_fps = max(1, min(100, atoi(pt+4))); - - Set(); -} - -cMenuSetupAudio::~cMenuSetupAudio(void) -{ - cXinelibDevice::Instance().ConfigurePostprocessing( - xc.deinterlace_method, xc.audio_delay, xc.audio_compression, - xc.audio_equalizer, xc.audio_surround, xc.speaker_type); - cXinelibDevice::Instance().ConfigurePostprocessing( - "upmix", xc.audio_upmix ? true : false, NULL); -#ifdef ENABLE_TEST_POSTPLUGINS - cXinelibDevice::Instance().ConfigurePostprocessing( - "headphone", xc.headphone ? true : false, NULL); -#endif -} - -void cMenuSetupAudio::Set(void) -{ - SetPlugin(cPluginManager::GetPlugin(PLUGIN_NAME_I18N)); - int current = Current(); - Clear(); - - Add(NewTitle(tr("Audio"))); - - Add(audio_ctrl_speakers = - new cMenuEditStraI18nItem(tr("Speakers"), &newconfig.speaker_type, - SPEAKERS_count, xc.s_speakerArrangements)); - - Add(audio_ctrl_volume = - new cMenuEditBoolItem(tr("Volume control"), - &newconfig.sw_volume_control, - tr("Hardware"), tr("Software"))); - - Add(audio_ctrl_delay = - new cMenuEditTypedIntItem(tr("Delay"), tr("ms"), &newconfig.audio_delay, - -3000, 3000, tr("Off"))); - Add(audio_ctrl_compression = - new cMenuEditTypedIntItem(tr("Audio Compression"), "%", - &newconfig.audio_compression, - 100, 500, NULL, tr("Off"))); - Add(audio_ctrl_upmix = - new cMenuEditBoolItem(tr("Upmix stereo to 5.1"), - &newconfig.audio_upmix)); - Add(audio_ctrl_surround = - new cMenuEditBoolItem(tr("Downmix AC3 to surround"), - &newconfig.audio_surround)); -#ifdef ENABLE_TEST_POSTPLUGINS - Add(audio_ctrl_headphone = - new cMenuEditBoolItem(tr("Mix to headphones"), - &newconfig.headphone)); -#else - audio_ctrl_headphone = NULL; -#endif - Add(audio_ctrl_vis = - new cMenuEditStraI18nItem(tr("Visualization"), &visualization, - AUDIO_VIS_count, - xc.s_audioVisualizationNames)); - if(visualization == AUDIO_VIS_GOOM) { - Add(new cMenuEditTypedIntItem(tr(" Width"), tr("px"), &goom_width, - 320, 1920)); - Add(new cMenuEditTypedIntItem(tr(" Height"),tr("px"), &goom_height, - 240, 1280)); - Add(new cMenuEditTypedIntItem(tr(" Speed"), tr("fps"), &goom_fps, - 1, 100)); - } - - if(current<1) current=1; /* first item is not selectable */ - SetCurrent(Get(current)); - Display(); -} - -eOSState cMenuSetupAudio::ProcessKey(eKeys Key) -{ - cOsdItem *item = Get(Current()); - - eOSState state = cMenuSetupPage::ProcessKey(Key); - - Key = NORMALKEY(Key); - - if(Key!=kLeft && Key!=kRight) - return state; - - if(item == audio_ctrl_delay || item == audio_ctrl_compression) { - cXinelibDevice::Instance().ConfigurePostprocessing( - xc.deinterlace_method, newconfig.audio_delay, - newconfig.audio_compression, newconfig.audio_equalizer, - newconfig.audio_surround, newconfig.speaker_type); - } - else if(item == audio_ctrl_vis) { - Set(); - } - else if(item == audio_ctrl_speakers) { - cXinelibDevice::Instance().ConfigurePostprocessing( - xc.deinterlace_method, newconfig.audio_delay, - newconfig.audio_compression, newconfig.audio_equalizer, - newconfig.audio_surround, newconfig.speaker_type); - if(newconfig.speaker_type <= SPEAKERS_STEREO && - newconfig.audio_upmix) { - newconfig.audio_upmix = false; - Set(); - } - } - else if(item == audio_ctrl_surround) { - cXinelibDevice::Instance().ConfigurePostprocessing( - xc.deinterlace_method, newconfig.audio_delay, - newconfig.audio_compression, newconfig.audio_equalizer, - newconfig.audio_surround, newconfig.speaker_type); - if(newconfig.audio_surround && newconfig.audio_upmix) { - newconfig.audio_upmix = 0; - Set(); - } - } - else if(item == audio_ctrl_volume) { - // trigger volume control message by toggling mute - cRemote::Put(kMute); - cRemote::Put(kMute); - } - else if(item == audio_ctrl_upmix) { - cXinelibDevice::Instance().ConfigurePostprocessing( - "upmix", newconfig.audio_upmix ? true : false, NULL); - if(newconfig.audio_upmix && newconfig.audio_surround) { - newconfig.audio_surround = 0; - Set(); - } - } -#ifdef ENABLE_TEST_POSTPLUGINS - else if(item == audio_ctrl_headphone) { - cXinelibDevice::Instance().ConfigurePostprocessing( - "headphone", newconfig.headphone ? true : false, NULL); - } -#endif - - return state; -} - - -void cMenuSetupAudio::Store(void) -{ - memcpy(&xc, &newconfig, sizeof(config_t)); - - strn0cpy(xc.audio_visualization, xc.s_audioVisualizations[visualization], - sizeof(xc.audio_visualization)); - snprintf(xc.audio_vis_goom_opts, sizeof(xc.audio_vis_goom_opts), - "width=%d,height=%d,fps=%d", - goom_width, goom_height, goom_fps); - xc.audio_vis_goom_opts[sizeof(xc.audio_vis_goom_opts)-1] = 0; - - SetupStore("Audio.Speakers", xc.s_speakerArrangements[xc.speaker_type]); - SetupStore("Audio.Delay", xc.audio_delay); - SetupStore("Audio.Compression", xc.audio_compression); - SetupStore("Audio.Surround", xc.audio_surround); - SetupStore("Audio.Upmix", xc.audio_upmix); - SetupStore("Audio.Headphone", xc.headphone); - SetupStore("Audio.Visualization",xc.audio_visualization); - SetupStore("Audio.Visualization.GoomOpts",xc.audio_vis_goom_opts); - SetupStore("Audio.SoftwareVolumeControl", xc.sw_volume_control); - Setup.Save(); -} - -//--- cMenuSetupAudioEq ------------------------------------------------------ - -class cMenuSetupAudioEq : public cMenuSetupPage -{ - private: - config_t newconfig; - - protected: - virtual void Store(void); - void Set(void); - - public: - cMenuSetupAudioEq(void); - ~cMenuSetupAudioEq(void); - - virtual eOSState ProcessKey(eKeys Key); -}; - -cMenuSetupAudioEq::cMenuSetupAudioEq(void) -{ - memcpy(&newconfig, &xc, sizeof(config_t)); - Set(); -} - -cMenuSetupAudioEq::~cMenuSetupAudioEq(void) -{ - cXinelibDevice::Instance().ConfigurePostprocessing( - xc.deinterlace_method, xc.audio_delay, xc.audio_compression, - xc.audio_equalizer, xc.audio_surround, xc.speaker_type); -} - -void cMenuSetupAudioEq::Set(void) -{ - SetPlugin(cPluginManager::GetPlugin(PLUGIN_NAME_I18N)); - int current = Current(); - Clear(); - - Add(NewTitle(tr("Audio Equalizer"))); - for(int i=0; i= 10509 -# if 0 - Add(new cMenuEditStraI18nItem(tr("Show all layers"), &newconfig.osd_mixer, - OSD_MIXER_count, xc.s_osdMixers)); -# endif -#endif - - Add(ctrl_alpha = - new cMenuEditTypedIntItem(tr("Dynamic transparency correction"), "%", - &newconfig.alpha_correction, -200, 200, - tr("Off"))); - Add(ctrl_alpha_abs = - new cMenuEditTypedIntItem(tr("Static transparency correction"), "", - &newconfig.alpha_correction_abs, -0xff, 0xff, - tr("Off"))); - -#if VDRVERSNUM < 10515 - Add(NewTitle(tr("Subtitles"))); - Add(new cMenuEditBoolItem(trVDR("Setup.EPG$Preferred languages"), - &newconfig.spu_autoshow)); - if(newconfig.spu_autoshow) { - Add(ctrl_spulang0 = - new cMenuEditStrItem(trVDR("Setup.EPG$Preferred language"), - newconfig.spu_lang[0], 4, LangNameChars)); - Add(new cMenuEditStrItem(trVDR("Setup.EPG$Preferred language"), - newconfig.spu_lang[1], 4, LangNameChars)); - Add(new cMenuEditStrItem(trVDR("Setup.EPG$Preferred language"), - newconfig.spu_lang[2], 4, LangNameChars)); - Add(new cMenuEditStrItem(trVDR("Setup.EPG$Preferred language"), - newconfig.spu_lang[3], 4, LangNameChars)); - } -#endif - - Add(new cMenuEditStraI18nItem(tr("External subtitle size"), - &newconfig.extsub_size, SUBTITLESIZE_count, xc.s_subtitleSizes)); - - if(current<1) current=1; /* first item is not selectable */ - SetCurrent(Get(current)); - //SetCurrent(Get(1)); - Display(); -} - -eOSState cMenuSetupOSD::ProcessKey(eKeys Key) -{ - cOsdItem *item = Get(Current()); - - eOSState state = cMenuSetupPage::ProcessKey(Key); - - Key = NORMALKEY(Key); - - if(Key!=kLeft && Key!=kRight) - return state; - - if(item == ctrl_scaling) - cXinelibOsdProvider::RefreshOsd(); - else if(item == ctrl_alpha) - xc.alpha_correction = newconfig.alpha_correction; - else if(item == ctrl_alpha_abs) - xc.alpha_correction_abs = newconfig.alpha_correction_abs; - - if(!newconfig.unscaled_osd && !ctrl_lowres) - Set(); - if(newconfig.unscaled_osd && ctrl_lowres) - Set(); -#if VDRVERSNUM < 10515 - if(newconfig.spu_autoshow && !ctrl_spulang0) - Set(); - if(!newconfig.spu_autoshow && ctrl_spulang0) - Set(); -#endif - return state; -} - -void cMenuSetupOSD::Store(void) -{ - newconfig.extsub_size --; - if(newconfig.extsub_size != xc.extsub_size) { - cString tmp = cString::sprintf("EXTSUBSIZE %d", newconfig.extsub_size); - cXinelibDevice::Instance().PlayFileCtrl(tmp); - } - - memcpy(&xc, &newconfig, sizeof(config_t)); - orig_alpha_correction = xc.alpha_correction; - orig_alpha_correction_abs = xc.alpha_correction_abs; - - SetupStore("OSD.Scaling", xc.osd_scaling); - SetupStore("OSD.HideMainMenu", xc.hide_main_menu); - SetupStore("OSD.LayersVisible", xc.osd_mixer); - SetupStore("OSD.UnscaledAlways", xc.unscaled_osd); - SetupStore("OSD.UnscaledLowRes", xc.unscaled_osd_lowresvideo); - SetupStore("OSD.AlphaCorrection", xc.alpha_correction); - SetupStore("OSD.AlphaCorrectionAbs", xc.alpha_correction_abs); - - SetupStore("OSD.ExtSubSize", xc.extsub_size); -#if VDRVERSNUM < 10515 - SetupStore("OSD.SpuAutoSelect", xc.spu_autoshow); - SetupStore("OSD.SpuLang0", xc.spu_lang[0]); - SetupStore("OSD.SpuLang1", xc.spu_lang[1]); - SetupStore("OSD.SpuLang2", xc.spu_lang[2]); - SetupStore("OSD.SpuLang3", xc.spu_lang[3]); -#endif - Setup.Save(); -} - - -//--- cMenuSetupDecoder ------------------------------------------------------ - -class cMenuSetupDecoder : public cMenuSetupPage -{ - private: - config_t newconfig; - - int pes_buffers_ind; - - cOsdItem *ctrl_pes_buffers_ind; - cOsdItem *ctrl_pes_buffers; - - protected: - virtual void Store(void); - void Set(void); - - public: - cMenuSetupDecoder(void); - - virtual eOSState ProcessKey(eKeys Key); -}; - -cMenuSetupDecoder::cMenuSetupDecoder(void) -{ - int i; - memcpy(&newconfig, &xc, sizeof(config_t)); - - pes_buffers_ind = PES_BUFFERS_CUSTOM; - for(i=0;xc.s_bufferSize[i];i++) - if(xc.pes_buffers == xc.i_pesBufferSize[i]) - pes_buffers_ind = i; - - Set(); -} - -void cMenuSetupDecoder::Set(void) -{ - SetPlugin(cPluginManager::GetPlugin(PLUGIN_NAME_I18N)); - int current = Current(); - Clear(); - - Add(NewTitle(tr("Decoder"))); - Add(ctrl_pes_buffers_ind = - new cMenuEditStraI18nItem(tr("Buffer size"), &pes_buffers_ind, - PES_BUFFERS_count, xc.s_bufferSize)); - if(pes_buffers_ind == PES_BUFFERS_CUSTOM) - Add(ctrl_pes_buffers = - new cMenuEditIntItem(tr(" Number of PES packets"), &newconfig.pes_buffers, - 10, 10000)); - else - ctrl_pes_buffers = NULL; - - if(current<1) current=1; /* first item is not selectable */ - SetCurrent(Get(current)); - Display(); -} - -eOSState cMenuSetupDecoder::ProcessKey(eKeys Key) -{ - cOsdItem *item = Get(Current()); - - eOSState state = cMenuSetupPage::ProcessKey(Key); - - Key = NORMALKEY(Key); - - if(Key!=kLeft && Key!=kRight) - return state; - - if(item == ctrl_pes_buffers_ind) { - if(pes_buffers_ind == PES_BUFFERS_CUSTOM && !ctrl_pes_buffers) { - Set(); - } else if(pes_buffers_ind != PES_BUFFERS_CUSTOM && ctrl_pes_buffers) { - Set(); - } - } - - return state; -} - -void cMenuSetupDecoder::Store(void) -{ - int old_buffers = xc.pes_buffers; - - //memcpy(&xc, &newconfig, sizeof(config_t)); - xc.pes_buffers = newconfig.pes_buffers; - - if(pes_buffers_ind != PES_BUFFERS_CUSTOM) - xc.pes_buffers = xc.i_pesBufferSize[pes_buffers_ind]; - - SetupStore("Decoder.PesBuffers", xc.pes_buffers); - - if(xc.pes_buffers != old_buffers) - cXinelibDevice::Instance().ConfigureDecoder(xc.pes_buffers); - Setup.Save(); -} - - -//--- cMenuSetupLocal -------------------------------------------------------- - -class cMenuSetupLocal : public cMenuSetupPage -{ - private: - config_t newconfig; - - int local_frontend; - int local_frontend_orig; - int audio_driver; - int audio_driver_orig; - int video_driver; - int video_driver_orig; - - cOsdItem *ctrl_scale; - cOsdItem *ctrl_local_fe; - cOsdItem *ctrl_driver; - cOsdItem *ctrl_fullscreen; - cOsdItem *ctrl_window_width; - cOsdItem *ctrl_window_height; - cOsdItem *ctrl_interlace_order; - cOsdItem *ctrl_aspect; - cOsdItem *ctrl_audio_driver; - cOsdItem *ctrl_audio_port; - - protected: - virtual void Store(void); - void Set(void); - - public: - cMenuSetupLocal(void); - ~cMenuSetupLocal(void); - - virtual eOSState ProcessKey(eKeys Key); -}; - -cMenuSetupLocal::cMenuSetupLocal(void) -{ - SetPlugin(cPluginManager::GetPlugin(PLUGIN_NAME_I18N)); - - memcpy(&newconfig, &xc, sizeof(config_t)); - - local_frontend_orig = local_frontend = strstra(xc.local_frontend, xc.s_frontends, 0); - audio_driver_orig = audio_driver = strstra(xc.audio_driver, xc.s_audioDrivers, 0); - - video_driver = 0; - if(local_frontend == FRONTEND_X11) - video_driver = strstra(xc.video_driver, xc.s_videoDriversX11, 0); - if(local_frontend == FRONTEND_FB) - video_driver = strstra(xc.video_driver, xc.s_videoDriversFB, 0); - video_driver_orig = video_driver; - - Set(); -} - -cMenuSetupLocal::~cMenuSetupLocal(void) -{ - cXinelibDevice::Instance().ConfigureWindow( - xc.fullscreen, xc.width, xc.height, xc.modeswitch, xc.modeline, - xc.display_aspect, xc.scale_video, xc.field_order); - cXinelibDevice::Instance().ConfigurePostprocessing( - xc.deinterlace_method, xc.audio_delay, xc.audio_compression, - xc.audio_equalizer, xc.audio_surround, xc.speaker_type); -} - -void cMenuSetupLocal::Set(void) -{ - int current = Current(); - Clear(); - - ctrl_interlace_order = NULL; - ctrl_fullscreen = NULL; - ctrl_window_width = NULL; - ctrl_window_height = NULL; - ctrl_driver = NULL; - ctrl_aspect = NULL; - ctrl_scale = NULL; - ctrl_audio_driver = NULL; - ctrl_audio_port = NULL; - - Add(NewTitle(tr("Local Frontend"))); - - Add(ctrl_local_fe = - new cMenuEditStraI18nItem(tr("Local Display Frontend"), &local_frontend, - FRONTEND_count, xc.s_frontendNames)); - - if(local_frontend == FRONTEND_X11) { - Add(new cMenuEditBoolItem(tr("Use keyboard"), - &newconfig.use_x_keyboard)); - } - - if(local_frontend != FRONTEND_NONE) { - cString tmp = cString::sprintf("%s >>", tr("Decoder")); - Add(new cOsdItem(tmp, osUser1)); - Add(NewTitle(tr("Video"))); - } - - if(local_frontend == FRONTEND_X11) { - Add(ctrl_driver = - new cMenuEditStraI18nItem(tr("Driver"), &video_driver, - X11_DRIVER_count, - xc.s_videoDriverNamesX11)); - Add(new cMenuEditStrItem(tr("Display address"), newconfig.video_port, - 31, DriverNameChars)); - - } else if(local_frontend == FRONTEND_FB) { - Add(ctrl_driver = - new cMenuEditStraI18nItem(tr("Driver"), &video_driver, - FB_DRIVER_count, - xc.s_videoDriverNamesFB)); - Add(new cMenuEditStrItem(tr("Framebuffer device"), newconfig.video_port, 31, - DriverNameChars)); - } -#if 0 - if(local_frontend == FRONTEND_FB || !newconfig.fullscreen) { - Add(new cMenuEditStrItem( "Modeline", newconfig.modeline, 31, - ModeLineChars)); - Add(new cMenuEditBoolItem("Videomode switching", &xc.modeswitch)); - } -#endif - - if(local_frontend == FRONTEND_X11) { - Add(ctrl_fullscreen = new cMenuEditBoolItem(tr("Fullscreen mode"), - &newconfig.fullscreen)); - if(!newconfig.fullscreen) { - Add(ctrl_window_width = - new cMenuEditTypedIntItem( tr(" Window width"), tr("px"), - &newconfig.width, 1, 2048)); - Add(ctrl_window_height = - new cMenuEditTypedIntItem( tr(" Window height"), tr("px"), - &newconfig.height, 1, 2048)); - } - } - - if(local_frontend != FRONTEND_NONE) { - Add(ctrl_aspect = - new cMenuEditStraI18nItem(tr("Window aspect"), &newconfig.display_aspect, - ASPECT_count, xc.s_aspects)); - Add(ctrl_scale = - new cMenuEditBoolItem(tr("Scale to window size"), &newconfig.scale_video)); - -#ifdef HAVE_XV_FIELD_ORDER - Add(ctrl_interlace_order = - new cMenuEditStraI18nItem(tr("Interlaced Field Order"), - &newconfig.field_order, FIELD_ORDER_count, - xc.s_fieldOrder)); -#endif - - Add(NewTitle(tr("Audio"))); - - Add(ctrl_audio_driver = - new cMenuEditStraI18nItem(tr("Driver"), &audio_driver, - AUDIO_DRIVER_count, xc.s_audioDriverNames)); - if(audio_driver != AUDIO_DRIVER_AUTO && audio_driver != AUDIO_DRIVER_NONE) - Add(ctrl_audio_port = - new cMenuEditStrItem(tr("Port"), newconfig.audio_port, 31, - DriverNameChars)); - } - - if(current<1) current=1; /* first item is not selectable */ - SetCurrent(Get(current)); - Display(); -} - -eOSState cMenuSetupLocal::ProcessKey(eKeys Key) -{ - int prev_frontend = local_frontend; - int prev_audio_driver = audio_driver; - - cOsdItem *item = Get(Current()); - - eOSState state = cMenuSetupPage::ProcessKey(Key); - - if(state == osUser1) - return AddSubMenu(new XinelibOutputSetupMenu::cMenuSetupDecoder); - - Key = NORMALKEY(Key); - - if((Key!=kLeft && Key!=kRight) || !item) - return state; - - if(item == ctrl_audio_driver) { - if(prev_audio_driver != audio_driver) { - - if(audio_driver == audio_driver_orig) - strcpy(newconfig.audio_port, xc.audio_port); - else if(audio_driver == AUDIO_DRIVER_ALSA) - strcpy(newconfig.audio_port, "default"); - else if(audio_driver == AUDIO_DRIVER_OSS) - strcpy(newconfig.audio_port, "/dev/dsp"); - else - strcpy(newconfig.audio_port, ""); - Set(); - } - else if((audio_driver != AUDIO_DRIVER_AUTO && - audio_driver != AUDIO_DRIVER_NONE) && - !ctrl_audio_port) - Set(); - else if((audio_driver == AUDIO_DRIVER_AUTO || - audio_driver == AUDIO_DRIVER_NONE) && - ctrl_audio_port) - Set(); - } - else if(item == ctrl_aspect || item == ctrl_scale || item == ctrl_interlace_order) - cXinelibDevice::Instance().ConfigureWindow( - xc.fullscreen, xc.width, xc.height, xc.modeswitch, xc.modeline, - newconfig.display_aspect, newconfig.scale_video, - newconfig.field_order); - else if(item == ctrl_local_fe && local_frontend != prev_frontend) { - - if(local_frontend == local_frontend_orig) { - video_driver = video_driver_orig; - strcpy(newconfig.video_port, xc.video_port); - } - else if(local_frontend == FRONTEND_FB) - strcpy(newconfig.video_port, "/dev/fb/0"); - else if(local_frontend == FRONTEND_X11) - strcpy(newconfig.video_port, "0.0"); - - Set(); - } - else if(item == ctrl_fullscreen) { - if(!newconfig.fullscreen && !ctrl_window_width) { - Set(); - } else if(newconfig.fullscreen && ctrl_window_width) { - Set(); - } - } - - return state; -} - -void cMenuSetupLocal::Store(void) -{ - int old_buffers = xc.pes_buffers; - - memcpy(&xc, &newconfig, sizeof(config_t)); - - xc.pes_buffers = old_buffers; - - strn0cpy(xc.audio_driver, xc.s_audioDrivers[audio_driver], sizeof(xc.audio_driver)); - strn0cpy(xc.local_frontend, xc.s_frontends[local_frontend], sizeof(xc.local_frontend)); - if(local_frontend == FRONTEND_X11) - strn0cpy(xc.video_driver, xc.s_videoDriversX11[video_driver], sizeof(xc.video_driver)); - if(local_frontend == FRONTEND_FB) - strn0cpy(xc.video_driver, xc.s_videoDriversFB[video_driver], sizeof(xc.video_driver)); - - SetupStore("Frontend", xc.local_frontend); - SetupStore("Audio.Driver", xc.audio_driver); - SetupStore("Audio.Port", xc.audio_port); - SetupStore("Video.Driver", xc.video_driver); - SetupStore("Video.Port", xc.video_port); -#if 0 - SetupStore("Video.Port", NULL); /* should delete entry ? */ - SetupStore("Video.Port.X11",xc.video_port_x11); - SetupStore("Video.Port.FB", xc.video_port_fb); -#endif - SetupStore("Video.Scale", xc.scale_video); - SetupStore("Video.FieldOrder", xc.field_order); - SetupStore("Modeline", xc.modeline); - SetupStore("VideoModeSwitching", xc.modeswitch); - SetupStore("Fullscreen", xc.fullscreen); - SetupStore("DisplayAspect", xc.s_aspects[xc.display_aspect]); - SetupStore("X11.WindowWidth", xc.width); - SetupStore("X11.WindowHeight", xc.height); - SetupStore("X11.UseKeyboard", xc.use_x_keyboard); - Setup.Save(); -} - -//--- cMenuSetupRemote ------------------------------------------------------- - -class cMenuSetupRemote : public cMenuSetupPage -{ - private: - config_t newconfig; - - cOsdItem *ctrl_remote_mode; - cOsdItem *ctrl_usertp; - cOsdItem *ctrl_rtp_addr; - cOsdItem *ctrl_use_http; - cOsdItem *ctrl_http_ctrl; - cOsdItem *ctrl_use_rtsp; - cOsdItem *ctrl_rtsp_ctrl; - - protected: - virtual void Store(void); - void Set(void); - - public: - cMenuSetupRemote(void); - - virtual eOSState ProcessKey(eKeys Key); -}; - -cMenuSetupRemote::cMenuSetupRemote(void) -{ - memcpy(&newconfig, &xc, sizeof(config_t)); - Set(); -} - -void cMenuSetupRemote::Set(void) -{ - int current = Current(); - SetPlugin(cPluginManager::GetPlugin(PLUGIN_NAME_I18N)); - Clear(); - - Add(NewTitle(tr("Remote Clients"))); - Add(ctrl_remote_mode = new cMenuEditBoolItem(tr("Allow remote clients"), - &newconfig.remote_mode)); - ctrl_usertp = NULL; - ctrl_rtp_addr = NULL; - ctrl_use_http = NULL; - ctrl_use_rtsp = NULL; - ctrl_http_ctrl = NULL; - ctrl_rtsp_ctrl = NULL; - if(newconfig.remote_mode) { - Add(new cMenuEditIntItem( tr(" Listen port (TCP and broadcast)"), - &newconfig.listen_port, - 0, 0xffff)); - Add(new cMenuEditStrItem( tr(" Listen address"), - &newconfig.remote_local_ip[0], 16, "0123456789.")); - Add(new cMenuEditBoolItem(tr(" Remote keyboard"), - &newconfig.remote_keyboard)); - - Add(new cMenuEditBoolItem(tr(" PIPE transport"), - &newconfig.remote_usepipe)); - Add(new cMenuEditBoolItem(tr(" TCP transport"), - &newconfig.remote_usetcp)); - Add(new cMenuEditBoolItem(tr(" UDP transport"), - &newconfig.remote_useudp)); - Add(ctrl_usertp = - new cMenuEditBoolItem(tr(" RTP (multicast) transport"), - &newconfig.remote_usertp)); - if(newconfig.remote_usertp) { - Add(ctrl_rtp_addr = - new cMenuEditStrItem( tr(" Address"), - &newconfig.remote_rtp_addr[0], 16, "0123456789.")); - Add(new cMenuEditOddIntItem( tr(" Port"), - &newconfig.remote_rtp_port, 1000, 0xfffe)); - Add(new cMenuEditIntItem( tr(" TTL"), - &newconfig.remote_rtp_ttl, 1, 10)); - Add(new cMenuEditBoolItem(tr(" Transmit always on"), - &newconfig.remote_rtp_always_on)); - Add(new cMenuEditBoolItem(tr(" SAP announcements"), - &newconfig.remote_rtp_sap)); - } - Add(new cMenuEditBoolItem(tr(" Server announce broadcasts"), - &newconfig.remote_usebcast)); - - Add(new cMenuEditBoolItem(tr(" HTTP transport for media files"), - &newconfig.remote_http_files)); - - Add(NewTitle(tr("Additional network services"))); - Add(ctrl_use_http = - new cMenuEditBoolItem(tr("HTTP server"), - &newconfig.remote_use_http)); - if(newconfig.remote_use_http) - Add(ctrl_http_ctrl = - new cMenuEditBoolItem(tr("HTTP clients can control VDR"), - &newconfig.remote_use_http_ctrl)); - Add(ctrl_use_rtsp = - new cMenuEditBoolItem(tr("RTSP server"), - &newconfig.remote_use_rtsp)); - if(newconfig.remote_use_rtsp) - Add(ctrl_rtsp_ctrl = - new cMenuEditBoolItem(tr("RTSP clients can control VDR"), - &newconfig.remote_use_rtsp_ctrl)); - } - - if(current<1) current=1; /* first item is not selectable */ - SetCurrent(Get(current)); - Display(); -} - -eOSState cMenuSetupRemote::ProcessKey(eKeys Key) -{ - cOsdItem *item = Get(Current()); - - eOSState state = cMenuSetupPage::ProcessKey(Key); - - Key = NORMALKEY(Key); - - if(Key!=kLeft && Key!=kRight) - return state; - - if(item == ctrl_remote_mode) { - if(newconfig.remote_mode && !ctrl_usertp) { - Set(); - } else if(!newconfig.remote_mode && ctrl_usertp) { - Set(); - } - } - if(item == ctrl_usertp) { - if(newconfig.remote_usertp && !ctrl_rtp_addr) { - Set(); - } else if(!newconfig.remote_usertp && ctrl_rtp_addr) { - Set(); - } - } - if(item == ctrl_use_http) { - if(newconfig.remote_use_http && !ctrl_http_ctrl) { - Set(); - } else if(!newconfig.remote_use_http && ctrl_http_ctrl) { - Set(); - } - } - if(item == ctrl_use_rtsp) { - if(newconfig.remote_use_rtsp && !ctrl_rtsp_ctrl) { - Set(); - } else if(!newconfig.remote_use_rtsp && ctrl_rtsp_ctrl) { - Set(); - } - } - - return state; -} - -void cMenuSetupRemote::Store(void) -{ - memcpy(&xc, &newconfig, sizeof(config_t)); - - SetupStore("RemoteMode", xc.remote_mode); - SetupStore("Remote.ListenPort", xc.listen_port); - SetupStore("Remote.Iface", xc.remote_local_if); - SetupStore("Remote.LocalIP", xc.remote_local_ip); - SetupStore("Remote.Keyboard", xc.remote_keyboard); - - SetupStore("Remote.UsePipe",xc.remote_usepipe); - SetupStore("Remote.UseTcp", xc.remote_usetcp); - SetupStore("Remote.UseUdp", xc.remote_useudp); - SetupStore("Remote.UseRtp", xc.remote_usertp); - SetupStore("Remote.UseBroadcast", xc.remote_usebcast); - - SetupStore("Remote.UseHttp", xc.remote_http_files); - - SetupStore("Remote.Rtp.Address", xc.remote_rtp_addr); - SetupStore("Remote.Rtp.Port", xc.remote_rtp_port); - SetupStore("Remote.Rtp.TTL", xc.remote_rtp_ttl); - SetupStore("Remote.Rtp.AlwaysOn", xc.remote_rtp_always_on); - SetupStore("Remote.Rtp.SapAnnouncements", xc.remote_rtp_sap); - - SetupStore("Remote.AllowRtsp", xc.remote_use_rtsp); - SetupStore("Remote.AllowRtspCtrl", xc.remote_use_rtsp_ctrl); - SetupStore("Remote.AllowHttp", xc.remote_use_http); - SetupStore("Remote.AllowHttpCtrl", xc.remote_use_http_ctrl); - - cXinelibDevice::Instance().Listen(xc.remote_mode, xc.listen_port); - Setup.Save(); -} - -//--- cMenuSetupMediaPlayer -------------------------------------------------------- - -class cMenuSetupMediaPlayer : public cMenuSetupPage -{ - private: - config_t newconfig; - - cOsdItem *media_ctrl_playlist_tracknumber; - cOsdItem *media_ctrl_playlist_artist; - cOsdItem *media_ctrl_playlist_album; - cOsdItem *media_ctrl_playlist_cache; - cOsdItem *media_ctrl_playlist_id3scanner; - - protected: - virtual void Store(void); - void Set(void); - - public: - cMenuSetupMediaPlayer(void); - - virtual eOSState ProcessKey(eKeys Key); -}; - -cMenuSetupMediaPlayer::cMenuSetupMediaPlayer(void) -{ - memcpy(&newconfig, &xc, sizeof(config_t)); - Set(); -} - -void cMenuSetupMediaPlayer::Set(void) -{ - SetPlugin(cPluginManager::GetPlugin(PLUGIN_NAME_I18N)); - int current = Current(); - Clear(); - - Add(NewTitle(tr("Playlist settings"))); - - Add(media_ctrl_playlist_tracknumber = - new cMenuEditBoolItem(tr("Show the track number"), - &newconfig.playlist_tracknumber)); - - Add(media_ctrl_playlist_artist = - new cMenuEditBoolItem(tr("Show the name of the artist"), - &newconfig.playlist_artist)); - - Add(media_ctrl_playlist_album = - new cMenuEditBoolItem(tr("Show the name of the album"), - &newconfig.playlist_album)); - - Add(media_ctrl_playlist_id3scanner = - new cMenuEditBoolItem(tr("Scan for metainfo"), - &newconfig.enable_id3_scanner)); - - Add(media_ctrl_playlist_cache = - new cMenuEditBoolItem(tr("Cache metainfo"), - &newconfig.cache_implicit_playlists)); - - - if(current<1) current=1; /* first item is not selectable */ - SetCurrent(Get(current)); - Display(); -} - -eOSState cMenuSetupMediaPlayer::ProcessKey(eKeys Key) -{ - eOSState state = cMenuSetupPage::ProcessKey(Key); - return state; -} - -void cMenuSetupMediaPlayer::Store(void) -{ - memcpy(&xc, &newconfig, sizeof(config_t)); - - SetupStore("Playlist.Tracknumber", xc.playlist_tracknumber); - SetupStore("Playlist.Album", xc.playlist_album); - SetupStore("Playlist.Artist", xc.playlist_artist); - SetupStore("Media.CacheImplicitPlaylists", xc.cache_implicit_playlists); - SetupStore("Media.EnableID3Scanner", xc.enable_id3_scanner); - Setup.Save(); -} - -} // namespace - - -//--- cMenuTestImages ------------------------------------------------------ - -#include - -#define OSD_W (720-2) -#define OSD_H (576-2) -#define OSD_X (1) -#define OSD_Y (1) - -// -// cTestGrayscale -// - -class cTestGrayscale : public cOsdObject -{ - private: - cOsd *m_Osd; - - public: - cTestGrayscale() { m_Osd = NULL; } - virtual ~cTestGrayscale() { delete m_Osd; } - - virtual void Show(); - virtual eOSState ProcessKey(eKeys Key); -}; - -void cTestGrayscale::Show() -{ - tArea areas [] = { { 0, 0, OSD_W/2 - 1, OSD_H - 1, 8}, - {OSD_W/2, 0, OSD_W - 1, OSD_H - 1, 8}}; - int i; - - if(!m_Osd) -#if VDRVERSNUM >= 10509 - m_Osd = cOsdProvider::NewOsd(OSD_X, OSD_Y, 0); -#else - m_Osd = cOsdProvider::NewOsd(OSD_X, OSD_Y); -#endif - - if(m_Osd) { - if (m_Osd->CanHandleAreas(areas, sizeof(areas) / sizeof(tArea) ) == oeOk) { - m_Osd->SetAreas(areas, sizeof(areas) / sizeof(tArea)); - m_Osd->Flush(); - - // border - m_Osd->DrawRectangle(0, 0, OSD_W - 1, OSD_H - 1, 0xff000000); - m_Osd->DrawRectangle(1, 1, OSD_W - 2, OSD_H - 2, 0xff000000); - - // background - m_Osd->DrawRectangle(2, 2, 2+103, OSD_H - 3, 0xffffffff); - m_Osd->DrawRectangle(OSD_W-2-103, 2, OSD_W-2, OSD_H - 3, 0xff000000); - - for(i=0; i<0xff; i++) - m_Osd->DrawRectangle(2+103+2*i, 2, 2+103+2*(i+1), OSD_H - 3, - 0xff000000|(i*0x00010101)/*=(i<<16)|(i<<8)|(i)*/); - // line - m_Osd->DrawRectangle(1, OSD_H/2-20, OSD_W - 2, OSD_H/2, 0xffffffff); - m_Osd->DrawRectangle(1, OSD_H/2+1, OSD_W - 2, OSD_H/2+21, 0xff000000); - - // Cross - for(int x=0; xDrawPixel(x, x*OSD_H/OSD_W, 0x00000000); - m_Osd->DrawPixel(x, OSD_H - 1 - x*OSD_H/OSD_W, 0x00000000); - } - - // commit - m_Osd->Flush(); - } - - } -} - -eOSState cTestGrayscale::ProcessKey(eKeys key) -{ - char s[32]; - static int br = xc.brightness; - static int co = xc.contrast; - eOSState state = cOsdObject::ProcessKey(key); - if (state == osUnknown) { - switch (key & ~k_Repeat) { - case kOk: - case kBack: - return osEnd; - case kRight: - br += 0xffff/1024*2; - case kLeft: - br -= 0xffff/1024; - sprintf(s, "b %d", br); - m_Osd->DrawText(400, 100, s, 0xff000000, 0xffffffff, cFont::GetFont(fontSml)); - cXinelibDevice::Instance().ConfigureVideo(xc.hue, xc.saturation, br, co, xc.overscan, xc.vo_aspect_ratio); - m_Osd->Flush(); - return osContinue; - case kUp: - co += 0xffff/1024*2; - case kDown: - co -= 0xffff/1024; - sprintf(s, "c %d", co); - m_Osd->DrawText(400, 130, s, 0xff000000, 0xffffffff, cFont::GetFont(fontSml)); - cXinelibDevice::Instance().ConfigureVideo(xc.hue, xc.saturation, br, co, xc.overscan, xc.vo_aspect_ratio); - m_Osd->Flush(); - return osContinue; - } - } - return state; -} - - -// -// cTestBitmap -// - -class cTestBitmap : public cOsdObject -{ - private: - cOsd *m_Osd; - int bpp; - - public: - cTestBitmap(int _bpp = 1) { - m_Osd = NULL; - if(_bpp<1) _bpp = 1; - if(_bpp>6) _bpp = 6; - bpp = 1<<_bpp; - } - virtual ~cTestBitmap() { delete m_Osd; } - - virtual void Show(); - virtual eOSState ProcessKey(eKeys Key); -}; - -void cTestBitmap::Show() -{ - tArea areas [] = {{ 0, 0, OSD_W - 1, OSD_H - 1, 8}}; - int x, y, bit = 0; - - if(!m_Osd) { -#if VDRVERSNUM >= 10509 - m_Osd = cOsdProvider::NewOsd(OSD_X, OSD_Y, 0); -#else - m_Osd = cOsdProvider::NewOsd(OSD_X, OSD_Y); -#endif - - if(m_Osd) { - if (m_Osd->CanHandleAreas(areas, sizeof(areas) / sizeof(tArea) ) == oeOk) { - m_Osd->SetAreas(areas, sizeof(areas) / sizeof(tArea)); - m_Osd->Flush(); - } - } - } - - if(m_Osd) { - for(x=0; xDrawRectangle(x, y, x+bpp, y+bpp, bit?0xffffffff:0xff000000); - bit = !bit; - } - } - // commit - m_Osd->Flush(); - } -} - -eOSState cTestBitmap::ProcessKey(eKeys key) -{ - eOSState state = cOsdObject::ProcessKey(key); - - if (state == osUnknown) { - switch (key & ~k_Repeat) { - case kOk: - case kBack: - return osEnd; - case kRight: - bpp = (bpp<64) ? (bpp<<1) : 1; - Show(); - return osContinue; - case kLeft: - bpp = (bpp>1) ? (bpp>>1) : 64; - Show(); - return osContinue; - default: - break; - } - } - return state; -} - -// -// cMenuTestImages -// - -#include // CallPlugin - -extern cOsdObject *g_PendingMenuAction; - -class cMenuTestImages : public cMenuSetupPage { - - protected: - void Set(void); - virtual void Store(void) {}; - - public: - cMenuTestImages(); - - virtual eOSState ProcessKey(eKeys Key); -}; - -cMenuTestImages::cMenuTestImages() -{ - Set(); -} - -void cMenuTestImages::Set(void) -{ - char buf[128]; - Clear(); - - SetHasHotkeys(); - Add(new cOsdItem(tr("Grayscale"), osUser1)); - - snprintf(buf, sizeof(buf), "%s 1bit", tr("Bitmap")); - buf[sizeof(buf)-1] = 0; - Add(new cOsdItem(buf, osUser2)); - - snprintf(buf, sizeof(buf), "%s 4bit", tr("Bitmap")); - buf[sizeof(buf)-1] = 0; - Add(new cOsdItem(buf, osUser3)); - - Display(); -} - -eOSState cMenuTestImages::ProcessKey(eKeys Key) -{ - eOSState state = cMenuSetupPage::ProcessKey(Key); - - switch (state) { - case osUser1: - if(cRemote::CallPlugin("xineliboutput")) - g_PendingMenuAction = new cTestGrayscale(); - return osEnd; - case osUser2: - if(cRemote::CallPlugin("xineliboutput")) - g_PendingMenuAction = new cTestBitmap(1); - return osEnd; - case osUser3: - if(cRemote::CallPlugin("xineliboutput")) - g_PendingMenuAction = new cTestBitmap(4); - return osEnd; - default: ; - } - - return state; -} - -//--- cMenuSetupXinelib ------------------------------------------------------ - -cMenuSetupXinelib::cMenuSetupXinelib(void) -{ - XinelibOutputSetupMenu::controls[0] = tr("Off"); - Set(); -} - -void cMenuSetupXinelib::Set(void) -{ - Clear(); - - SetHasHotkeys(); - Add(new cOsdItem(hk(tr("Audio")), osUser1)); - Add(new cOsdItem(hk(tr("Audio Equalizer")),osUser2)); - Add(new cOsdItem(hk(tr("Video")), osUser3)); - Add(new cOsdItem(hk(tr("OSD")), osUser4)); - //Add(new cOsdItem(hk(tr("Decoder")), osUser5)); - Add(new cOsdItem(hk(tr("Media Player")), osUser5)); - Add(new cOsdItem(hk(tr("Local Frontend")), osUser6)); - Add(new cOsdItem(hk(tr("Remote Clients")), osUser7)); - Add(new cOsdItem(hk(tr("Test Images")), osUser8)); - - Display(); -} - -eOSState cMenuSetupXinelib::ProcessKey(eKeys Key) -{ - eOSState state = cMenuSetupPage::ProcessKey(Key); - - switch (state) { - case osUser1: - return AddSubMenu(new XinelibOutputSetupMenu::cMenuSetupAudio); - case osUser2: - return AddSubMenu(new XinelibOutputSetupMenu::cMenuSetupAudioEq); - case osUser3: - return AddSubMenu(new XinelibOutputSetupMenu::cMenuSetupVideo); - case osUser4: - return AddSubMenu(new XinelibOutputSetupMenu::cMenuSetupOSD); - case osUser5: - return AddSubMenu(new XinelibOutputSetupMenu::cMenuSetupMediaPlayer); - case osUser6: - return AddSubMenu(new XinelibOutputSetupMenu::cMenuSetupLocal); - case osUser7: - return AddSubMenu(new XinelibOutputSetupMenu::cMenuSetupRemote); - case osUser8: - return AddSubMenu(new cMenuTestImages); - - default: ; - } - - return state; -} - - diff --git a/setup_menu.h b/setup_menu.h deleted file mode 100644 index d77cc797..00000000 --- a/setup_menu.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * setup_menu.h: Setup Menu - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: setup_menu.h,v 1.1 2006-06-03 09:50:54 phintuka Exp $ - * - */ - -#ifndef __XINELIB_SETUP_MENU_H -#define __XINELIB_SETUP_MENU_H - -#include - -class cMenuSetupXinelib : public cMenuSetupPage { - - protected: - void Set(void); - virtual void Store(void) {}; - - public: - cMenuSetupXinelib(void); - virtual eOSState ProcessKey(eKeys Key); -}; - -#endif //__XINELIB_SETUP_MENU_H diff --git a/tools.c b/tools.c deleted file mode 100644 index dcca8d1c..00000000 --- a/tools.c +++ /dev/null @@ -1,23 +0,0 @@ -/* - * tools.c: VDR/C++ wrapper for common tools - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: tools.c,v 1.1 2008-02-04 23:05:34 phintuka Exp $ - * - */ - -#define __STDC_CONSTANT_MACROS -#include -#define __STDC_FORMAT_MACROS -#include - -#include -#include "logdefs.h" - - -#include "tools/pes.c" -#include "tools/mpeg.c" -#include "tools/h264.c" - diff --git a/tools/backgroundwriter.c b/tools/backgroundwriter.c deleted file mode 100644 index f13a52a7..00000000 --- a/tools/backgroundwriter.c +++ /dev/null @@ -1,486 +0,0 @@ -/* - * backgroundwriter.h: Buffered socket/file writing thread - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: backgroundwriter.c,v 1.6 2008-02-04 23:54:06 phintuka Exp $ - * - */ - -#define __STDC_FORMAT_MACROS -#define __STDC_CONSTANT_MACROS -#include - -#include -#include -#include // CORK, NODELAY - -#include - -#include "../logdefs.h" -#include "../xine_input_vdr_net.h" // stream_tcp_header_t - -#include "backgroundwriter.h" - -//#define DISABLE_DISCARD -//#define LOG_DISCARDS - -#define MAX_OVERFLOWS_BEFORE_DISCONNECT 1000 // ~ 1 second - - -// -// cBackgroundWriterI -// - -cBackgroundWriterI::cBackgroundWriterI(int fd, int Size, int Margin) - : m_RingBuffer(Size, Margin) -{ - m_fd = fd; - m_RingBuffer.SetTimeouts(0, 100); - m_Active = true; - - m_PutPos = 0; - m_DiscardStart = 0; - m_DiscardEnd = 0; - - m_BufferOverflows = 0; - -#if defined(TCP_CORK) - int iCork = 1; - if(setsockopt(m_fd, IPPROTO_TCP, TCP_CORK, &iCork, sizeof(int))) { - if(errno != ENOTSOCK) - LOGERR("cBackgroundWriter: setsockopt(TCP_CORK) failed"); - m_IsSocket = false; - errno = 0; - } else { - m_IsSocket = true; - } -#elif defined(TCP_NOPUSH) - int iCork = 1; - if(setsockopt(m_fd, IPPROTO_TCP, TCP_NOPUSH, &iCork, sizeof(int))) { - if(errno != ENOTSOCK) - LOGERR("cBackgroundWriter: setsockopt(TCP_NOPUSH) failed"); - m_IsSocket = false; - errno = 0; - } else { - m_IsSocket = true; - } -#endif - - LOGDBG("cBackgroundWriterI initialized (buffer %d kb)", Size/1024); -} - -cBackgroundWriterI::~cBackgroundWriterI() -{ - m_Active = false; - Cancel(3); -} - -int cBackgroundWriterI::Free(void) -{ - return m_RingBuffer.Free(); -} - -void cBackgroundWriterI::Clear(void) -{ - // Can't just drop buffer contents or PES frames will be broken. - // Serialize with Put - LOCK_THREAD; - m_DiscardEnd = m_PutPos; -} - -bool cBackgroundWriterI::Flush(int TimeoutMs) -{ - uint64_t WaitEnd = cTimeMs::Now(); - - // wait for ring buffer to drain - if(TimeoutMs > 0) { - WaitEnd += (uint64_t)TimeoutMs; - - while(cTimeMs::Now() < WaitEnd && - m_Active && - m_RingBuffer.Available() > 0) - cCondWait::SleepMs(3); - } - - if(m_IsSocket && m_RingBuffer.Available() <= 0) { - // flush corked data too -#if defined(TCP_CORK) - int i = 1; - if(setsockopt(m_fd, IPPROTO_TCP, TCP_NODELAY, &i, sizeof(int))) { - LOGERR("cBackgroundWriter: setsockopt(TCP_NODELAY) failed"); - errno = 0; - } -#elif defined(TCP_NOPUSH) - int On = 1, Off = 0; - if(setsockopt(m_fd, IPPROTO_TCP, TCP_NOPUSH, &Off, sizeof(int)) || - setsockopt(m_fd, IPPROTO_TCP, TCP_NOPUSH, &On, sizeof(int))) { - LOGERR("cBackgroundWriter: setsockopt(TCP_NOPUSH) failed"); - errno = 0; - } -#endif - } - - return m_RingBuffer.Available() <= 0; -} - - -// -// cTcpWriter -// - -cTcpWriter::cTcpWriter(int fd, int Size) : - cBackgroundWriterI(fd, Size, sizeof(stream_tcp_header_t)) -{ - LOGDBG("cTcpWriter initialized (buffer %d kb)", Size/1024); - Start(); -} - -void cTcpWriter::Action(void) -{ - uint64_t NextHeaderPos = 0ULL; - uint64_t GetPos = 0ULL; - cPoller Poller(m_fd, true); - - while(m_Active) { - - if(Poller.Poll(100)) { - - int Count = 0, n; - uchar *Data = m_RingBuffer.Get(Count); - - if(Data && Count > 0) { - -#ifndef DISABLE_DISCARD - Lock(); // uint64_t m_DiscardStart can not be read atomically (IA32) - if(m_DiscardEnd > GetPos) { - -# ifdef LOG_DISCARDS - LOGMSG("TCP: queue: discard request: queue %d bytes, " - "next point %d bytes forward (Count=%d)", - m_RingBuffer.Available(), - NextHeaderPos - GetPos, - Count); -# endif - if(NextHeaderPos == GetPos) { - // we're at frame boundary -# ifdef LOG_DISCARDS - uint8_t *pkt = TCP_PAYLOAD(Data); - if(pkt[0] || pkt[1] || pkt[2] != 1 || hdr->len > 2100) { - LOGMSG(" -> %x %x %x %x", pkt[0], pkt[1], pkt[2], pkt[3]); - } -# endif - Count = min(Count, (int)(m_DiscardEnd - GetPos)); -# ifdef LOG_DISCARDS - LOGMSG("Flushing %d bytes", Count); -#endif - Unlock(); - - m_RingBuffer.Del(Count); - GetPos += Count; - NextHeaderPos = GetPos; -# ifdef LOG_DISCARDS - LOGMSG("Queue now %d bytes", m_RingBuffer.Available()); - pkt = TCP_PAYLOAD(Data); - if(pkt[0] || pkt[1] || pkt[2] != 1 || hdr->len > 2100) { - LOGMSG(" -> %x %x %x %x", pkt[0], pkt[1], pkt[2], pkt[3]); -# endif - continue; - } - } - Unlock(); -#endif - -#ifndef DISABLE_DISCARD - if(GetPos == NextHeaderPos) { - if(Count < (int)sizeof(stream_tcp_header_t)) - LOGMSG("cBackgroundWriter @NextHeaderPos: Count < header size !"); - - stream_tcp_header_t *header = (stream_tcp_header_t*)Data; - if(Count < (int)(ntohl(header->len) + sizeof(stream_tcp_header_t))) - ;//LOGMSG("Count = %d < %d", Count, - // header->len + sizeof(stream_tcp_header_t)); - else - Count = ntohl(header->len) + sizeof(stream_tcp_header_t); - NextHeaderPos = GetPos + ntohl(header->len) + sizeof(stream_tcp_header_t); - } else { - Count = min(Count, (int)(NextHeaderPos-GetPos)); - } -#endif - - errno = 0; - n = write(m_fd, Data, Count); - - if(n == 0) { - LOGERR("cBackgroundWriter: Client disconnected data stream ?"); - break; - - } else if(n < 0) { - - if (errno == EINTR || errno == EWOULDBLOCK) { - TRACE("cBackgroundWriter: EINTR while writing to file handle " - < MAX_OVERFLOWS_BEFORE_DISCONNECT) { - LOGMSG("cXinelibServer: Too many TCP buffer overflows, dropping client"); - m_RingBuffer.Clear(); - m_Active = false; - return 0; - } - return -HeaderCount-DataCount; - } - int n = m_RingBuffer.Put(Header, HeaderCount) + - m_RingBuffer.Put(Data, DataCount); - if(n == HeaderCount+DataCount) { - m_BufferOverflows = 0; - m_PutPos += n; - return n; - } - - LOGMSG("cXinelibServer: TCP buffer internal error ?!?"); - m_RingBuffer.Clear(); - m_Active = false; - } - - return 0; -} - - -// -// cRawWriter -// - -#include "pes.h" - -cRawWriter::cRawWriter(int fd, int Size) : - cBackgroundWriterI(fd, Size, 6) -{ - LOGDBG("cRawWriter initialized (buffer %d kb)", Size/1024); - Start(); -} - -void cRawWriter::Action(void) -{ - uint64_t NextHeaderPos = 0ULL; - uint64_t GetPos = 0ULL; - cPoller Poller(m_fd, true); - - while(m_Active) { - - if(Poller.Poll(100)) { - - int Count = 0, n; - uchar *Data = m_RingBuffer.Get(Count); - - if(Data && Count > 0) { - -#ifndef DISABLE_DISCARD - Lock(); // uint64_t m_DiscardStart can not be read atomically (IA32) - if(m_DiscardEnd > GetPos) { - - if(NextHeaderPos == GetPos) { - // we're at frame boundary - Count = min(Count, (int)(m_DiscardEnd - GetPos)); - Unlock(); - - m_RingBuffer.Del(Count); - GetPos += Count; - NextHeaderPos = GetPos; - continue; - } - } - Unlock(); -#endif - -#ifndef DISABLE_DISCARD - if(GetPos == NextHeaderPos) { - if(Count < 6) - LOGMSG("cBackgroundWriter @NextHeaderPos: Count < header size !"); - int packlen = pes_packet_len(Data, Count); - if(Count < packlen) - ;//LOGMSG("Count = %d < %d", Count, - // header->len + sizeof(stream_tcp_header_t)); - else - Count = packlen; - NextHeaderPos = GetPos + packlen; - } else { - Count = min(Count, (int)(NextHeaderPos-GetPos)); - } -#endif - - errno = 0; - n = write(m_fd, Data, Count); - - if(n == 0) { - LOGERR("cBackgroundWriter: Client disconnected data stream ?"); - break; - - } else if(n < 0) { - - if (errno == EINTR || errno == EWOULDBLOCK) { - TRACE("cBackgroundWriter: EINTR while writing to file handle " - < MAX_OVERFLOWS_BEFORE_DISCONNECT) { - LOGMSG("cXinelibServer: Too many TCP buffer overflows, dropping client"); - m_RingBuffer.Clear(); - m_Active = false; - return 0; - } - return -DataCount; - } - int n = m_RingBuffer.Put(Data, DataCount); - if(n == DataCount) { - m_BufferOverflows = 0; - m_PutPos += n; - return n; - } - - LOGMSG("cXinelibServer: TCP buffer internal error ?!?"); - m_RingBuffer.Clear(); - m_Active = false; - } - - return 0; -} - - -// -// cTsWriter -// - Demux PES stream to PS -// - -cTsWriter::cTsWriter(int fd, int Size) : - cBackgroundWriterI(fd, Size, 6) -{ - LOGDBG("cTsWriter initialized (buffer %d kb)", Size/1024); - Start(); -} - - -void cTsWriter::Action(void) -{ -} - -int cTsWriter::Put(uint64_t StreamPos, const uchar *Data, int DataCount) -{ - return 0; -} - - -// -// cRtspMuxWriter -// - RTSP multiplexed control+data -// - Each encapsulated PES frame is written atomically to socket buffer -// - Atomic control data can be written directly to socket -// from another thread to bypass buffer -// - -cRtspMuxWriter::cRtspMuxWriter(int fd, int Size) : - cBackgroundWriterI(fd, Size, 6) -{ - LOGDBG("cRtspMuxWriter initialized (buffer %d kb)", Size/1024); - Start(); -} - -void cRtspMuxWriter::Action(void) -{ -} - -int cRtspMuxWriter::Put(uint64_t StreamPos, const uchar *Data, int DataCount) -{ - return 0; -} - - -// -// cRtspRemuxWriter -// - RTSP multiplexed control+data -// - Demux PES stream to independent ES streams -// - encapsulate ES to RTP/AVP compatible frames -// - Mux RTP/AVP ES streams to pipelined RTCP control connection -// - Each encapsulated frame is written atomically to socket buffer -// - Atomic control data can be written directly to socket -// from another thread to bypass buffer -// - -cRtspRemuxWriter::cRtspRemuxWriter(int fd, int Size) : - cBackgroundWriterI(fd, Size, 6) -{ - LOGDBG("cRtspRemuxWriter initialized (buffer %d kb)", Size/1024); - Start(); -} - -void cRtspRemuxWriter::Action(void) -{ -} - -int cRtspRemuxWriter::Put(uint64_t StreamPos, const uchar *Data, int DataCount) -{ - return 0; -} - - diff --git a/tools/backgroundwriter.h b/tools/backgroundwriter.h deleted file mode 100644 index 7119047e..00000000 --- a/tools/backgroundwriter.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - * backgroundwriter.h: Buffered socket/file writing thread - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: backgroundwriter.h,v 1.4 2007-01-07 05:36:30 phintuka Exp $ - * - */ - -#ifndef __BACKGROUNDWRITER_H -#define __BACKGROUNDWRITER_H - -#include - -#include -#include - -// -// cBackgroundWriterI -// - generic interface for buffered output -// -class cBackgroundWriterI : public cThread -{ - protected: - cRingBufferLinear m_RingBuffer; - - volatile bool m_Active; - int m_fd; - bool m_IsSocket; - - uint64_t m_PutPos; - uint64_t m_DiscardStart; - uint64_t m_DiscardEnd; - - int m_BufferOverflows; - - protected: - virtual void Action(void) = 0; - - public: - cBackgroundWriterI(int fd, int Size = KILOBYTE(512), int Margin = 0); - virtual ~cBackgroundWriterI(); - - // Add PES frame to buffer - // - // Return value: - // Success: Count (all bytes pushed to queue) - // Error: 0 (write error ; socket disconnected) - // Buffer full: -Count (no bytes will be pushed to queue) - // - virtual int Put(uint64_t StreamPos, const uchar *Data, int DataCount) = 0; - - int Free(void); // Return largest possible Put size - void Clear(void); // Drop all data (only complete frames) from buffer - bool Flush(int TimeoutMs); // Flush buffer (wait for data to be sent) -}; - - -// -// cTcpWriter -// - xineliboutput TCP data steam -// - stream_tcp_header_t encapsulated PES frames -// -class cTcpWriter : public cBackgroundWriterI -{ - protected: - virtual void Action(void); - - int Put(const uchar *Header, int HeaderCount, - const uchar *Data, int DataCount); - - public: - cTcpWriter(int fd, int Size = KILOBYTE(512)); - virtual ~cTcpWriter() {}; - - virtual int Put(uint64_t StreamPos, const uchar *Data, int DataCount); -}; - - -// -// cRawWriter -// - Raw PES stream -// - Used with HTTP -// -class cRawWriter : public cBackgroundWriterI -{ - protected: - virtual void Action(void); - - public: - cRawWriter(int fd, int Size = KILOBYTE(512)); - virtual ~cRawWriter() {}; - - virtual int Put(uint64_t StreamPos, const uchar *Data, int DataCount); -}; - - -// -// cTsWriter -// - Demux PES stream to PS -// -class cTsWriter : public cBackgroundWriterI -{ - protected: - virtual void Action(void); - - public: - cTsWriter(int fd, int Size = KILOBYTE(512)); - virtual ~cTsWriter() {}; - - virtual int Put(uint64_t StreamPos, const uchar *Data, int DataCount); -}; - - -// -// cRtspMuxWriter -// - RTSP multiplexed control+data -// - Each encapsulated PES frame is written atomically to socket buffer -// - Atomic control data can be written directly to socket -// from another thread to bypass buffer -// - -class cRtspMuxWriter : public cBackgroundWriterI -{ - protected: - virtual void Action(void); - - public: - cRtspMuxWriter(int fd, int Size = KILOBYTE(512)); - virtual ~cRtspMuxWriter() {}; - - virtual int Put(uint64_t StreamPos, const uchar *Data, int DataCount); -}; - - -// -// cRtspRemuxWriter -// - RTSP multiplexed control+data -// - Demux PES stream to independent ES streams -// - encapsulate ES to RTP/AVP compatible frames -// - Mux RTP/AVP ES streams to pipelined RTCP control connection -// - Each encapsulated frame is written atomically to socket buffer -// - Atomic control data can be written directly to socket -// from another thread to bypass buffer -// - -class cRtspRemuxWriter : public cBackgroundWriterI -{ - protected: - virtual void Action(void); - - public: - cRtspRemuxWriter(int fd, int Size = KILOBYTE(512)); - virtual ~cRtspRemuxWriter() {}; - - virtual int Put(uint64_t StreamPos, const uchar *Data, int DataCount); -}; - - -#endif diff --git a/tools/bitstream.h b/tools/bitstream.h deleted file mode 100644 index 066fb2fe..00000000 --- a/tools/bitstream.h +++ /dev/null @@ -1,177 +0,0 @@ -/* - * bitstream.h: generic bitstream parsing - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: bitstream.h,v 1.2 2008-02-04 22:41:14 phintuka Exp $ - * - */ - -#ifndef _XINELIBOUTPUT_BITSTREAM_H_ -#define _XINELIBOUTPUT_BITSTREAM_H_ - -#include - - -# ifdef NOCACHE - -typedef struct { - const uint8_t *data; - int count; /* in bits */ - int index; /* in bits */ -} br_state; - -#define BR_INIT(data,bytes) { (data), 8*(bytes), 0 } - -#define BR_EOF(br) ((br)->index >= (br)->count) - -static inline void br_init(br_state *br, const uint8_t *data, int bytes) -{ - br->data = data; - br->count = 8*bytes; - br->index = 0; -} - -static inline int br_get_bit(br_state *br) -{ - if(br->index >= br->count) - return 1; /* -> no infinite colomb's ... */ - - int r = (br->data[br->index>>3] >> (7 - (br->index&7))) & 1; - br->index++; - return r; -} - -static inline uint32_t br_get_bits(br_state *br, uint32_t n) -{ - uint32_t r = 0; - while(n--) - r = r | (br_get_bit(br) << n); - return r; -} - -#define br_skip_bit(br) br_skip_bits(br,1) - -static inline void br_skip_bits(br_state *br, int n) -{ - br->index += n; -} - - -# else /* NOCACHE */ - - -typedef struct { - uint8_t *data; - uint8_t *data_end; - uint32_t cache; - uint32_t cache_bits; -} br_state; - -#define BR_INIT(data,bytes) { (data), (data)+(bytes), 0, 0 } - -static inline void br_init(br_state *br, const uint8_t *data, int bytes) -{ - br->data = data; - br->data_end = data + bytes; - br->cache = 0; - br->cache_bits = 0; -} - -#define BR_GET_BYTE(br) \ - (br->data < br->data_end ? *br->data++ : 0xff) - -#define BR_EOF(br) ((br)->data >= (br)->data_end) - -static inline uint32_t br_get_bits(br_state *br, uint32_t n) -{ - if(n > 24) - return (br_get_bits(br, 16) << 16) | br_get_bits(br, n-16); - - while (br->cache_bits < 24) { - br->cache = (br->cache<<8) | BR_GET_BYTE(br); - br->cache_bits += 8; - } - - br->cache_bits -= n; - return (br->cache >> br->cache_bits) & ((1<cache_bits) { - br->cache = BR_GET_BYTE(br); - br->cache_bits = 7; - } else { - br->cache_bits--; - } - return (br->cache >> br->cache_bits) & 1; -} - -static inline void br_skip_bit(br_state *br) -{ - if(!br->cache_bits) { - br->cache = BR_GET_BYTE(br); - br->cache_bits = 7; - } else { - br->cache_bits--; - } -} - -static inline void br_skip_bits(br_state *br, int n) -{ - if(br->cache_bits >= n) { - br->cache_bits -= n; - } else { - /* drop cached bits */ - n -= br->cache_bits; - - /* drop full bytes */ - br->data += (n >> 3); - n &= 7; - - /* update cache */ - if(n) { - br->cache = BR_GET_BYTE(br); - br->cache_bits = 8 - n; - } else { - br->cache_bits = 0; - } - } -} - - -# endif /* NOCACHE */ - - -#define br_get_u8(br) br_get_bits(br, 8) -#define br_get_u16(br) ((br_get_bits(br, 8)<<8) | br_get_bits(br, 8)) - -static inline uint32_t br_get_ue_golomb(br_state *br) -{ - int n = 0; - while (!br_get_bit(br) && n < 32) - n++; - return n ? ((1<>1) : (r>>1); -} - -static inline void br_skip_golomb(br_state *br) -{ - int n = 0; - while (!br_get_bit(br) && n < 32) - n++; - br_skip_bits(br, n); -} - -#define br_skip_ue_golomb(br) br_skip_golomb(br) -#define br_skip_se_golomb(br) br_skip_golomb(br) - - -#endif /* _XINELIBOUTPUT_BITSTREAM_H_ */ diff --git a/tools/cxsocket.c b/tools/cxsocket.c deleted file mode 100644 index e6a95a72..00000000 --- a/tools/cxsocket.c +++ /dev/null @@ -1,430 +0,0 @@ -/* - * cxsocket.c: Socket wrapper classes - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: cxsocket.c,v 1.11 2007-03-27 02:45:48 phintuka Exp $ - * - */ - -#define __STDC_FORMAT_MACROS -#include - -#include -#include -#include -#include -#include -#include -#ifndef __APPLE__ -# include -#endif -#include - -#include -#include - -#include "../logdefs.h" - -#include "cxsocket.h" - -bool cxSocket::connect(struct sockaddr *addr, socklen_t len) -{ - return ::connect(m_fd, addr, len) == 0; -} - -bool cxSocket::connect(const char *ip, int port) -{ - struct sockaddr_in sin; - sin.sin_family = AF_INET; - sin.sin_port = htons(port); - sin.sin_addr.s_addr = inet_addr(ip); - return connect((struct sockaddr *)&sin, sizeof(sin)); -} - -bool cxSocket::set_blocking(bool state) -{ - int flags = fcntl (m_fd, F_GETFL); - - if(flags == -1) { - LOGERR("cxSocket::SetBlocking: fcntl(F_GETFL) failed"); - return false; - } - - flags = state ? (flags&(~O_NONBLOCK)) : (flags|O_NONBLOCK); - - if(fcntl (m_fd, F_SETFL, flags) == -1) { - LOGERR("cxSocket::SetBlocking: fcntl(F_SETFL) failed"); - return false; - } - - return true; -} - -bool cxSocket::set_buffers(int Tx, int Rx) -{ - int max_buf = Tx; - /*while(max_buf) {*/ - errno = 0; - if(setsockopt(m_fd, SOL_SOCKET, SO_SNDBUF, &max_buf, sizeof(int))) { - LOGERR("cxSocket: setsockopt(SO_SNDBUF,%d) failed", max_buf); - /*max_buf >>= 1;*/ - } - /*else {*/ - int tmp = 0; - int len = sizeof(int); - errno = 0; - if(getsockopt(m_fd, SOL_SOCKET, SO_SNDBUF, &tmp, (socklen_t*)&len)) { - LOGERR("cxSocket: getsockopt(SO_SNDBUF,%d) failed", max_buf); - /*break;*/ - } else if(tmp != max_buf) { - LOGDBG("cxSocket: setsockopt(SO_SNDBUF): got %d bytes", tmp); - /*max_buf >>= 1;*/ - /*continue;*/ - } - /*}*/ - /*}*/ - - max_buf = Rx; - setsockopt(m_fd, SOL_SOCKET, SO_RCVBUF, &max_buf, sizeof(int)); - - return true; -} - -bool cxSocket::set_multicast(int ttl) -{ - int iReuse = 1, iLoop = 1, iTtl = ttl; - - errno = 0; - - if(setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, &iReuse, sizeof(int)) < 0) { - LOGERR("cxSocket: setsockopt(SO_REUSEADDR) failed"); - return false; - } - - if(setsockopt(m_fd, IPPROTO_IP, IP_MULTICAST_TTL, &iTtl, sizeof(int))) { - LOGERR("cxSocket: setsockopt(IP_MULTICAST_TTL, %d) failed", iTtl); - return false; - } - - if(setsockopt(m_fd, IPPROTO_IP, IP_MULTICAST_LOOP, &iLoop, sizeof(int))) { - LOGERR("cxSocket: setsockopt(IP_MULTICAST_LOOP) failed"); - return false; - } - - return true; -} - -ssize_t cxSocket::sendfile(int fd_file, off_t *offset, size_t count) -{ - int r; -#ifndef __APPLE__ - r = ::sendfile(m_fd, fd_file, offset, count); - if(r<0 && (errno == ENOSYS || errno == EINVAL)) { - // fall back to read/write - LOGERR("sendfile failed - using simple read/write"); -#endif - cxPoller p(*this, true); - char buf[0x10000]; - int todor = count, todow, done = 0; - if(offset) - if((r=::lseek(fd_file, *offset, SEEK_SET)) < 0) - return r; - todow = ::read(fd_file, buf, count>sizeof(buf) ? sizeof(buf) : count); - if(todow <= 0) - return todow; - todor -= todow; - while(todow > 0) { - if(p.Poll(100)) { - r = write(buf+done, todow); - if(r <= 0) - return r; - todow -= r; - done += r; - } - } - return done; -#ifndef __APPLE__ - } - return r; -#endif -} - -bool cxSocket::set_cork(bool state) -{ -#ifdef __APPLE__ - return false; -#else - int iCork = state ? 1 : 0; - if(setsockopt(m_fd, IPPROTO_TCP, TCP_CORK, &iCork, sizeof(int))) { - LOGERR("cxSocket: setsockopt(TCP_CORK) failed"); - return false; - } - return true; -#endif -} - -bool cxSocket::set_nodelay(bool state) -{ - int i = state ? 1 : 0; - if(setsockopt(m_fd, IPPROTO_TCP, TCP_NODELAY, &i, sizeof(int))) { - LOGERR("cxSocket: setsockopt(TCP_NODELAY) failed"); - return false; - } - return true; -} - -ssize_t cxSocket::tx_buffer_size(void) -{ - socklen_t l = sizeof(int); - int wmem = -1; - if(getsockopt(m_fd, SOL_SOCKET, SO_SNDBUF, &wmem, &l)) { - LOGERR("getsockopt(SO_SNDBUF) failed"); - return (ssize_t)-1; - } - return (ssize_t)wmem; -} - -ssize_t cxSocket::tx_buffer_free(void) -{ - int wmem = tx_buffer_size(); - int size = -1; - if(ioctl(m_fd, TIOCOUTQ, &size)) { - LOGERR("ioctl(TIOCOUTQ) failed"); - return (ssize_t)-1; - } - - return (ssize_t)(wmem - size); -} - -int cxSocket::getsockname(struct sockaddr *name, socklen_t *namelen) -{ - return ::getsockname(m_fd, name, namelen); -} - -int cxSocket::getpeername(struct sockaddr *name, socklen_t *namelen) -{ - return ::getpeername(m_fd, name, namelen); -} - -ssize_t cxSocket::send(const void *buf, size_t size, int flags, - const struct sockaddr *to, socklen_t tolen) -{ - return ::sendto(m_fd, buf, size, flags, to, tolen); -} - -ssize_t cxSocket::recv(void *buf, size_t size, int flags, - struct sockaddr *from, socklen_t *fromlen) -{ - return ::recvfrom(m_fd, buf, size, flags, from, fromlen); -} - -ssize_t cxSocket::write(const void *buffer, size_t size, - int timeout_ms) -{ - ssize_t written = (ssize_t)size; - const unsigned char *ptr = (const unsigned char *)buffer; - cPoller poller(m_fd, true); - - while (size > 0) { - errno = 0; - if(!poller.Poll(timeout_ms)) { - LOGERR("cxSocket::write: poll() failed"); - return written-size; - } - - errno = 0; - ssize_t p = ::write(m_fd, ptr, size); - - if (p <= 0) { - if (errno == EINTR || errno == EAGAIN) { - LOGDBG("cxSocket::write: EINTR during write(), retrying"); - continue; - } - LOGERR("cxSocket::write: write() error"); - return p; - } - - ptr += p; - size -= p; - } - - return written; -} - -ssize_t cxSocket::read(void *buffer, size_t size, int timeout_ms) -{ - ssize_t missing = (ssize_t)size; - unsigned char *ptr = (unsigned char *)buffer; - cPoller poller(m_fd); - - while (missing > 0) { - - if(!poller.Poll(timeout_ms)) { - LOGERR("cxSocket::read: poll() failed at %d/%d", (int)(size-missing), (int)size); - return size-missing; - } - - errno = 0; - ssize_t p = ::read(m_fd, ptr, missing); - - if (p <= 0) { - if (errno == EINTR || errno == EAGAIN) { - LOGDBG("cxSocket::read: EINTR/EAGAIN during read(), retrying"); - continue; - } - LOGERR("cxSocket::read: read() error at %d/%d", (int)(size-missing), (int)size); - return size-missing; - } - - ptr += p; - missing -= p; - } - - return size; -} - -ssize_t cxSocket::printf(const char *fmt, ...) -{ - va_list argp; - char buf[1024]; - int r; - - va_start(argp, fmt); - r = vsnprintf(buf, sizeof(buf), fmt, argp); - if(r<0) - LOGERR("cxSocket::printf: vsnprintf failed"); - else if(r >= (int)sizeof(buf)) - LOGMSG("cxSocket::printf: vsnprintf overflow (%20s)", buf); - else - return write(buf, r); - - return (ssize_t)-1; -} - -/* readline return value: - * <0 : failed - * >=maxsize : buffer overflow - * >=0 : if errno = EAGAIN -> line is not complete (there was timeout) - * if errno = 0 -> succeed - * (return value 0 indicates empty line "\r\n") - */ -ssize_t cxSocket::readline(char *buf, int bufsize, int timeout, int bufpos) -{ - int n = -1, cnt = bufpos; - cPoller p(m_fd); - - do { - if(timeout>0 && !p.Poll(timeout)) { - errno = EAGAIN; - return cnt; - } - - while((n = ::read(m_fd, buf+cnt, 1)) == 1) { - buf[++cnt] = 0; - - if( cnt > 1 && buf[cnt - 2] == '\r' && buf[cnt - 1] == '\n') { - cnt -= 2; - buf[cnt] = 0; - errno = 0; - return cnt; - } - - if( cnt >= bufsize) { - LOGMSG("cxSocket::readline: too long control message (%d bytes): %20s", cnt, buf); - errno = 0; - return bufsize; - } - } - - /* connection closed ? */ - if (n == 0) { - LOGMSG("cxSocket::readline: disconnected"); - if(errno == EAGAIN) - errno = ENOTCONN; - return -1; - } - - } while (timeout>0 && n<0 && errno == EAGAIN); - - if(errno == EAGAIN) - return cnt; - - LOGERR("cxSocket::readline: read failed"); - return n; -} - -#include -#include - -uint32_t cxSocket::get_local_address(char *ip_address) -{ - uint32_t local_addr = 0; - struct ifconf conf; - struct ifreq buf[3]; - unsigned int n; - - struct sockaddr_in sin; - socklen_t len = sizeof(sin); - - if(!getsockname((struct sockaddr *)&sin, &len)) { - local_addr = sin.sin_addr.s_addr; - - } else { - //LOGERR("getsockname failed"); - - // scan network interfaces - - conf.ifc_len = sizeof(buf); - conf.ifc_req = buf; - memset(buf, 0, sizeof(buf)); - - errno = 0; - if(ioctl(m_fd, SIOCGIFCONF, &conf) < 0) - LOGERR("cxSocket: can't obtain socket local address"); - else { - for(n=0; nsin_addr.s_addr); - LOGMSG("Local address %6s %d.%d.%d.%d", - conf.ifc_req[n].ifr_name, - ((tmp>>24)&0xff), ((tmp>>16)&0xff), - ((tmp>>8)&0xff), ((tmp)&0xff)); -# endif - if(n==0 || local_addr == htonl(INADDR_LOOPBACK)) - local_addr = in->sin_addr.s_addr; - else - break; - } - } - } - - if(!local_addr) - LOGERR("No local address found"); - - if(ip_address) - cxSocket::ip2txt(local_addr, 0, ip_address); - - return local_addr; -} - -char *cxSocket::ip2txt(uint32_t ip, unsigned int port, char *str) -{ - // inet_ntoa is not thread-safe (?) - if(str) { - unsigned int iph =(unsigned int)ntohl(ip); - unsigned int porth =(unsigned int)ntohs(port); - if(!porth) - sprintf(str, "%d.%d.%d.%d", - ((iph>>24)&0xff), ((iph>>16)&0xff), - ((iph>>8)&0xff), ((iph)&0xff)); - else - sprintf(str, "%u.%u.%u.%u:%u", - ((iph>>24)&0xff), ((iph>>16)&0xff), - ((iph>>8)&0xff), ((iph)&0xff), - porth); - } - return str; -} diff --git a/tools/cxsocket.h b/tools/cxsocket.h deleted file mode 100644 index 92954f3c..00000000 --- a/tools/cxsocket.h +++ /dev/null @@ -1,195 +0,0 @@ -/* - * cxsocket.h: Socket wrapper classes - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: cxsocket.h,v 1.20 2007-01-20 17:24:40 phintuka Exp $ - * - */ - -#ifndef __CXSOCKET_H -#define __CXSOCKET_H - -#include -#include -#include - -#define CLOSESOCKET(fd) do { if(fd>=0) { ::close(fd); fd=-1; } } while(0) - -class cxSocket { - private: - int m_fd; - - cxSocket(const cxSocket& s) ;//{ m_fd = s.m_fd>=0 ? dup(s.m_fd) : -1; } - cxSocket &operator=(const cxSocket &S) - ;// { close(); m_fd = S.m_fd >= 0 ? dup(S.m_fd) : -1; return *this; }; - - public: - - typedef enum { - estSTREAM = SOCK_STREAM, - estDGRAM = SOCK_DGRAM - } eSockType; - - cxSocket() : m_fd(-1) {} - cxSocket(eSockType type) : m_fd(::socket(PF_INET, (int)type, 0)) {} - - ~cxSocket() { CLOSESOCKET(m_fd); } - - //operator int () const { return Handle(); } - //operator bool () const { return open(); } - //bool operator==(const cxSocket &s) { return m_fd == s.m_fd; } - - int handle(bool take_ownership=false) - { int r=m_fd; if(take_ownership) m_fd=-1; return r; } - void set_handle(int h) { if(h != m_fd) {close(); m_fd = h;} } - bool create(eSockType type) { close(); return (m_fd=::socket(PF_INET, (int)type, 0)) >= 0; } - bool open(void) const { return m_fd>0; } - void close(void) { CLOSESOCKET(m_fd); } - - ssize_t send(const void *buf, size_t size, int flags=0, - const struct sockaddr *to = NULL, socklen_t tolen = 0); - ssize_t recv(void *buf, size_t size, int flags = 0, - struct sockaddr *from = NULL, socklen_t *fromlen = NULL); - ssize_t sendfile(int fd_file, off_t *offset, size_t count); - - ssize_t read(void *buffer, size_t size, int timeout_ms = -1); - ssize_t write(const void *buffer, size_t size, int timeout_ms = -1); - - ssize_t printf(const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); - ssize_t write_str(const char *str, int timeout_ms=-1, int len=0) - { return write(str, len ?: strlen(str), timeout_ms); } - ssize_t write_cmd(const char *str, int len=0) - { return write(str, len ?: strlen(str), 10); } - -/* readline return value: - * <0 : failed - * >=maxsize : buffer overflow - * >=0 : if errno = EAGAIN -> line is not complete (there was timeout) - * if errno = 0 -> succeed - * (return value 0 indicates empty line "\r\n") - */ - ssize_t readline(char *buf, int bufsize, int timeout=0, int bufpos=0); - - bool set_buffers(int Tx, int Rx); - bool set_multicast(int ttl); - bool set_blocking(bool state); - bool set_cork(bool state); - bool flush_cork(void) { return set_nodelay(true); }; - bool set_nodelay(bool state); - ssize_t tx_buffer_size(void); - ssize_t tx_buffer_free(void); - int getsockname(struct sockaddr *name, socklen_t *namelen); - int getpeername(struct sockaddr *name, socklen_t *namelen); - - - bool connect(struct sockaddr *addr, socklen_t len); - bool connect(const char *ip, int port); - - uint32_t get_local_address(char *ip_address); - - static char *ip2txt(uint32_t ip, unsigned int port, char *str); -}; - - -#include - -class cxPoller : public cPoller { - public: - cxPoller(cxSocket& Sock, bool Out=false) : cPoller(Sock.handle(), Out) {}; - - cxPoller(cxSocket* Socks, int count, bool Out=false) - { - for(int i=0; i>= 1;*/ - } - /*else {*/ - int tmp = 0; - int len = sizeof(int); - errno = 0; - if(getsockopt(s, SOL_SOCKET, SO_SNDBUF, &tmp, (socklen_t*)&len)) { - LOGERR("getsockopt(SO_SNDBUF,%d) failed", max_buf); - /*break;*/ - } else if(tmp != max_buf) { - LOGDBG("setsockopt(SO_SNDBUF): got %d bytes", tmp); - /*max_buf >>= 1;*/ - /*continue;*/ - } - /*}*/ - /*}*/ - - max_buf = rxbuf; - setsockopt(s, SOL_SOCKET, SO_RCVBUF, &max_buf, sizeof(int)); -} - -// -// Connect data socket to client (take address from fd_control) -// -static inline int sock_connect(int fd_control, int port, int type) -{ - struct sockaddr_in sin; - socklen_t len = sizeof(sin); - int s, one = 1; - - if(getpeername(fd_control, (struct sockaddr *)&sin, &len)) { - LOGERR("sock_connect: getpeername failed"); - return -1; - } - - uint32_t tmp = ntohl(sin.sin_addr.s_addr); - LOGMSG("Client address: %d.%d.%d.%d", - ((tmp>>24)&0xff), ((tmp>>16)&0xff), - ((tmp>>8)&0xff), ((tmp)&0xff)); - -#if 0 - if ((h = gethostbyname(tmp)) == NULL) { - LOGDBG("sock_connect: unable to resolve host name", tmp); - } -#endif - - if ((s = socket(PF_INET, type, - type==SOCK_DGRAM?IPPROTO_UDP:IPPROTO_TCP)) < 0) { - LOGERR("sock_connect: failed to create socket"); - return -1; - } - - // Set socket buffers: large send buffer, small receive buffer - set_socket_buffers(s, KILOBYTE(256), 2048); - - if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(int)) < 0) - LOGERR("sock_connect: setsockopt(SO_REUSEADDR) failed"); - - sin.sin_family = AF_INET; - sin.sin_port = htons(port); - - if (connect(s, (struct sockaddr *)&sin, sizeof(sin))==-1 && - errno != EINPROGRESS) { - LOGERR("connect() failed"); - CLOSESOCKET(s); - } - - if (fcntl (s, F_SETFL, fcntl (s, F_GETFL) | O_NONBLOCK) == -1) { - LOGERR("can't put socket in non-blocking mode"); - CLOSESOCKET(s); - return -1; - } - - return s; -} - -#endif // __CXSOCKET_H diff --git a/tools/debug_mutex.h b/tools/debug_mutex.h deleted file mode 100644 index 0802c7cc..00000000 --- a/tools/debug_mutex.h +++ /dev/null @@ -1,206 +0,0 @@ -/* - * debug_mutex.h: debugging wrappers for pthread_mutex_ functions - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: debug_mutex.h,v 1.3 2007-03-14 11:50:08 phintuka Exp $ - * - */ - -#ifndef DEBUG_MUTEX_H -#define DEBUG_MUTEX_H - -#ifndef _PTHREAD_H -# error pthread.h must be included before debug_mutex.h -#endif - -/* - * Override pthread_mutex_ calls: - * - * Change type of each mutex to PTHREAD_MUTEX_ERRORCHECK_NP - * - * Store line number of last succeed pthread_mutex_lock call - * for each initialized mutex - * - * Check every pthread_mutex_ call for errors and log all errors - * - * To help detecting deadlocks and minimize logging: - * - Try locking first in pthread_mutex_lock - * - If pthread_mutex_trylock fails, log a message and retry. - * - When trylock failed, log another message when lock is acquired. - * - * - * NOTE: debugging itself is not thread-safe and may indicate wrong line numbers ! - * - */ - -#define MAX_DBG_MUTEX 64 -static struct { - pthread_mutex_t *lock; - int line; - int tid; -} dbgdata[MAX_DBG_MUTEX+1] = {{NULL,0}}; - -static void dbg_setdata(pthread_mutex_t *mutex, int line) -{ - int i; - for(i=0; i -#include - -class cDisplayMessage : public cOsdObject -{ - cSkinDisplayMessage *displayMessage; - char *Message; - int Timer; - int Timeout; - - public: - - cDisplayMessage(const char *message, int timeout = 3) - { - displayMessage = NULL; - Message = strdup(message); - Timer = 0; - Timeout = timeout; - } - - virtual ~cDisplayMessage() - { - delete displayMessage; - free(Message); - } - - void Update(const char *message) - { - Timer = 0; - free(Message); - Message = strdup(message); - Show(); - } - - virtual eOSState ProcessKey(eKeys Key) - { - if(Key == kNone && Timer++ > Timeout) - return osEnd; - - if(Key != kNone) { - // put back and close - cRemote::Put(Key, true); - return osEnd; - } - - return osContinue; - } - - virtual void Show(void) - { - if(!displayMessage) - displayMessage = Skins.Current()->DisplayMessage(); - - displayMessage->SetMessage(mtInfo, Message); - displayMessage->Flush(); - } - -}; - -#endif diff --git a/tools/functor.h b/tools/functor.h deleted file mode 100644 index 0dadf1fc..00000000 --- a/tools/functor.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * functor.h: - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: functor.h,v 1.1 2006-08-24 23:25:07 phintuka Exp $ - * - */ - -#ifndef __XINELIB_FUNCTOR_H -#define __XINELIB_FUNCTOR_H - -#include - - -class cFunctor : public cListObject -{ - public: - cFunctor() : cListObject() {} - virtual ~cFunctor() {} - virtual void Execute(void) = 0; -}; - -#if 1 /* gcc 3.3.x (?) does not accept class TRESULT=void */ -template -cFunctor *CreateFunctor(TCLASS *c, - void (TCLASS::*fp)(void)); - -template -cFunctor *CreateFunctor(TCLASS *c, - void (TCLASS::*fp)(TARG1), - TARG1 arg1); -#endif - -template -cFunctor *CreateFunctor(TCLASS *c, - TRESULT (TCLASS::*fp)(void)); - -template -cFunctor *CreateFunctor(TCLASS *c, - TRESULT (TCLASS::*fp)(TARG1), - TARG1 arg1); - -#include "functorimpl.h" - -#endif diff --git a/tools/functorimpl.h b/tools/functorimpl.h deleted file mode 100644 index 2d3504e6..00000000 --- a/tools/functorimpl.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - * functorimpl.h: - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: functorimpl.h,v 1.1 2006-08-24 23:25:07 phintuka Exp $ - * - */ - -#ifndef __XINELIB_FUNCTORIMPL_H - -#ifndef __XINELIB_FUNCTOR_H -# error functorimpl.h should not be included, use functor.h instead -#endif - -#if 1 /* gcc 3.3.x (?) does not accept class TRESULT=void */ -template -class cFunctor0 : public cFunctor { - - public: - protected: - - typedef void (TCLASS::*TFUNC)(void); - - cFunctor0(TCLASS *obj, TFUNC f) : m_obj(obj), m_f(f) {} - virtual ~cFunctor0() {}; - - virtual void Execute(void) - { - (*m_obj.*m_f)(); - } - - private: - TCLASS *m_obj; - TFUNC m_f; - - friend cFunctor *CreateFunctor(TCLASS*,TFUNC); -}; - -template -class cFunctor1 : public cFunctor { - - public: - - protected: - typedef void (TCLASS::*TFUNC)(TARG1); - - cFunctor1(TCLASS *obj, TFUNC f, TARG1 arg1) : - m_obj(obj), m_f(f), m_arg1(arg1) {} - virtual ~cFunctor1() {}; - - virtual void Execute(void) - { - (*m_obj.*m_f)(m_arg1); - } - - private: - TCLASS *m_obj; - TFUNC m_f; - TARG1 m_arg1; - - friend cFunctor *CreateFunctor(TCLASS*,TFUNC,TARG1); -}; -#endif - -template -class cFunctorR0 : public cFunctor { - - public: - protected: - - typedef TRESULT (TCLASS::*TFUNC)(void); - - cFunctorR0(TCLASS *obj, TFUNC f) : m_obj(obj), m_f(f) {} - virtual ~cFunctorR0() {}; - - virtual void Execute(void) - { - // TODO: use future to pass back value - (void) (*m_obj.*m_f)(); - } - - private: - TCLASS *m_obj; - TFUNC m_f; - - friend cFunctor *CreateFunctor(TCLASS*,TFUNC); -}; - -template -class cFunctorR1 : public cFunctor { - - public: - protected: - - typedef TRESULT (TCLASS::*TFUNC)(TARG1); - - cFunctorR1(TCLASS *obj, TFUNC f, TARG1 arg1) : - m_obj(obj), m_f(f), m_arg1(arg1) {} - virtual ~cFunctorR1() {}; - - virtual void Execute(void) - { - // TODO: use future to pass back value - (void) (*m_obj.*m_f)(m_arg1); - } - - private: - TCLASS *m_obj; - TFUNC m_f; - TARG1 m_arg1; - - friend cFunctor *CreateFunctor(TCLASS*,TFUNC,TARG1); -}; - -#if 1 /* gcc 3.3.x (?) does not accept class TRESULT=void */ -template -cFunctor *CreateFunctor(TCLASS *c, - void (TCLASS::*fp)(void)) -{ - return new cFunctor0(c, fp); -} - -template -cFunctor *CreateFunctor(TCLASS *c, - void (TCLASS::*fp)(TARG1), - TARG1 arg1) -{ - return new cFunctor1(c, fp, arg1); -} -#endif - -template -cFunctor *CreateFunctor(TCLASS *c, - TRESULT (TCLASS::*fp)(void)) -{ - return new cFunctorR0(c, fp); -} - -template -cFunctor *CreateFunctor(TCLASS *c, - TRESULT (TCLASS::*fp)(TARG1), - TARG1 arg1) -{ - return new cFunctorR1(c, fp, arg1); -} - - -#endif diff --git a/tools/future.h b/tools/future.h deleted file mode 100644 index bdd0498c..00000000 --- a/tools/future.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * future.h: A variable that gets its value in future. - * Used to convert asynchronous IPCs to synchronous. - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: future.h,v 1.2 2006-08-19 23:44:07 phintuka Exp $ - * - */ - -#ifndef __FUTURE_H -#define __FUTURE_H - -#include - -template -class cFuture { - - private: - cMutex mutex; - cCondVar cond; - bool m_Ready; - T m_Value; - - public: - - cFuture() - { - m_Ready = false; - } - - void Reset(void) - { - cMutexLock l(&mutex); - m_Ready = false; - } - - // - // Producer interface - // - - void Set(T& Value) - { - cMutexLock l(&mutex); - m_Value = Value; - m_Ready = true; - cond.Broadcast(); - } - - // - // Consumer interface - // - - bool Wait(int Timeout = -1) - { - cMutexLock l(&mutex); - - if(Timeout==0 || m_Ready) - return m_Ready; - - if(Timeout >= 0) - return cond.TimedWait(mutex, Timeout) && m_Ready; - - while(!m_Ready) - cond.Wait(mutex); - - return m_Ready; - } - - bool IsReady(void) - { - cMutexLock l(&mutex); - return m_Ready; - } - - T Value(void) - { - cMutexLock l(&mutex); - while(!m_Ready) - cond.Wait(mutex); - return m_Value; - } -}; - - -#endif // __FUTURE_H diff --git a/tools/general_remote.h b/tools/general_remote.h deleted file mode 100644 index aed60463..00000000 --- a/tools/general_remote.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * general_remote.h: - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: general_remote.h,v 1.1 2006-06-03 10:04:27 phintuka Exp $ - * - */ - -#ifndef __GENERAL_REMOTE_H -#define __GENERAL_REMOTE_H - - -//----------------------------- cGeneralRemote -------------------------------- - -#include - -class cGeneralRemote : public cRemote { - public: - cGeneralRemote(const char *Name) : cRemote(Name) {}; - bool Put(const char *Code, bool Repeat=false, bool Release=false) - { return cRemote::Put(Code, Repeat, Release); }; -}; - - -#endif diff --git a/tools/h264.c b/tools/h264.c deleted file mode 100644 index 65be1180..00000000 --- a/tools/h264.c +++ /dev/null @@ -1,188 +0,0 @@ -/* - * h264.c: H.264 bitstream decoding - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: h264.c,v 1.1 2008-02-04 22:43:27 phintuka Exp $ - * - */ - - -#ifndef LOGDBG -# include -# include "../logdefs.h" -#endif - -#define NOCACHE 1 -#include "bitstream.h" - -#include "mpeg.h" -#include "h264.h" - - -int h264_parse_sps(const uint8_t *buf, int len, h264_sps_data_t *sps) -{ - br_state br = BR_INIT(buf, len); - int profile_idc, pic_order_cnt_type; - int frame_mbs_only; - int i, j; - - profile_idc = br_get_u8(&br); - LOGDBG("H.264 SPS: profile_idc %d", profile_idc); - /* constraint_set0_flag = br_get_bit(br); */ - /* constraint_set1_flag = br_get_bit(br); */ - /* constraint_set2_flag = br_get_bit(br); */ - /* constraint_set3_flag = br_get_bit(br); */ - /* reserved = br_get_bits(br,4); */ - /* level_idc = br_get_u8(br); */ - br_skip_bits(&br, 16); - br_skip_ue_golomb(&br); /* seq_parameter_set_id */ - if (profile_idc >= 100) { - if (br_get_ue_golomb(&br) == 3) /* chroma_format_idc */ - br_skip_bit(&br); /* residual_colour_transform_flag */ - br_skip_ue_golomb(&br); /* bit_depth_luma - 8 */ - br_skip_ue_golomb(&br); /* bit_depth_chroma - 8 */ - br_skip_bit(&br); /* transform_bypass */ - if (br_get_bit(&br)) /* seq_scaling_matrix_present */ - for (i = 0; i < 8; i++) - if (br_get_bit(&br)) { /* seq_scaling_list_present */ - int last = 8, next = 8, size = (i<6) ? 16 : 64; - for (j = 0; j < size; j++) { - if (next) - next = (last + br_get_se_golomb(&br)) & 0xff; - last = next ?: last; - } - } - } - - br_skip_ue_golomb(&br); /* log2_max_frame_num - 4 */ - pic_order_cnt_type = br_get_ue_golomb(&br); - if (pic_order_cnt_type == 0) - br_skip_ue_golomb(&br); /* log2_max_poc_lsb - 4 */ - else if (pic_order_cnt_type == 1) { - br_skip_bit(&br); /* delta_pic_order_always_zero */ - br_skip_se_golomb(&br); /* offset_for_non_ref_pic */ - br_skip_se_golomb(&br); /* offset_for_top_to_bottom_field */ - j = br_get_ue_golomb(&br); /* num_ref_frames_in_pic_order_cnt_cycle */ - for (i = 0; i < j; i++) - br_skip_se_golomb(&br); /* offset_for_ref_frame[i] */ - } - br_skip_ue_golomb(&br); /* ref_frames */ - br_skip_bit(&br); /* gaps_in_frame_num_allowed */ - sps->width /* mbs */ = br_get_ue_golomb(&br) + 1; - sps->height /* mbs */ = br_get_ue_golomb(&br) + 1; - frame_mbs_only = br_get_bit(&br); - LOGDBG("H.264 SPS: pic_width: %u mbs", (unsigned) sps->width); - LOGDBG("H.264 SPS: pic_height: %u mbs", (unsigned) sps->height); - LOGDBG("H.264 SPS: frame only flag: %d", frame_mbs_only); - - sps->width *= 16; - sps->height *= 16 * (2-frame_mbs_only); - - if (!frame_mbs_only) - if (br_get_bit(&br)) /* mb_adaptive_frame_field_flag */ - LOGDBG("H.264 SPS: MBAFF"); - br_skip_bit(&br); /* direct_8x8_inference_flag */ - if (br_get_bit(&br)) { /* frame_cropping_flag */ - uint32_t crop_left = br_get_ue_golomb(&br); - uint32_t crop_right = br_get_ue_golomb(&br); - uint32_t crop_top = br_get_ue_golomb(&br); - uint32_t crop_bottom = br_get_ue_golomb(&br); - LOGDBG("H.264 SPS: cropping %d %d %d %d", - crop_left, crop_top, crop_right, crop_bottom); - - sps->width -= 2*(crop_left + crop_right); - if (frame_mbs_only) - sps->height -= 2*(crop_top + crop_bottom); - else - sps->height -= 4*(crop_top + crop_bottom); - } - /* skip VUI parameters */ - - LOGDBG("H.264 SPS: -> video size %dx%d ", sps->width, sps->height); - - if(BR_EOF(&br)) { - LOGDBG("H.264 SPS: not enough data ?"); - return 0; - } - return 1; -} - -static int h264_nal_unescape(uint8_t *dst, const uint8_t *src, int len) -{ - int s = 0, d = 0; - while (s < len) { - if (!src[s] && !src[s+1]) { - /* hit 00 00 xx */ - dst[d] = dst[d+1] = 0; - s += 2; - d += 2; - if (src[s] == 3) { - s++; /* 00 00 03 xx --> 00 00 xx */ - /*LOGDBG("h264_nal_unescape: hit 00 00 03 %02x", src[s]);*/ - if (s >= len) - return d; - } /* else if (src[s] == 0 || src[s] == 1) { - LOGDBG("h264_nal_unescape: invalid NAL sequence 00 00 %02x %02x", src[s], src[s+1]); - return -1; - }*/ - } - dst[d++] = src[s++]; - } - return d; -} - -int h264_get_picture_type(const uint8_t *buf, int len) -{ - int i; - for (i = 0; i < len-5; i++) { - if (buf[i] == 0 && buf[i + 1] == 0 && buf[i + 2] == 1 && buf[i + 3] == 9) { - uint8_t type = (buf[i + 4] >> 5); - switch (type) { - case 0: case 3: case 5: return I_FRAME; - case 1: case 4: case 6: return P_FRAME; - case 2: case 7: return B_FRAME; - default:; - } - } - } - return NO_PICTURE; -} - -int h264_get_video_size(const uint8_t *buf, int len, video_size_t *size) -{ - int i; - - /* H.264 detection, search for NAL AUD */ - if (!(buf[0] == 0 && buf[1] == 0 && buf[2] == 1 && buf[3] == 0x09)) - return 0; - - /* if I-frame, search for NAL SPS */ - if (h264_get_picture_type(buf, len) != I_FRAME) - return 0; - - /* scan video packet for sequence parameter set */ - for (i = 5; i < len-4; i++) - if (buf[i] == 0 && buf[i + 1] == 0 && buf[i + 2] == 1 && (buf[i + 3] & 0x1f) == 0x07) { - - h264_sps_data_t sps = {0}; - uint8_t nal_data[len]; - int nal_len; - - LOGDBG("H.264: Found NAL SPS at offset %d/%d", i, len); - - if (0 < (nal_len = h264_nal_unescape(nal_data, buf+i+4, len-i-4))) { - - if (h264_parse_sps(nal_data, nal_len, &sps)) { - size->width = sps.width; - size->height = sps.height; - return 1; - } - LOGMSG("h264_get_video_size: not enough data ?"); - } - } - - return 0; -} - diff --git a/tools/h264.h b/tools/h264.h deleted file mode 100644 index 34e11b81..00000000 --- a/tools/h264.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * h264.h: H.264 bitstream decoding - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: h264.h,v 1.2 2008-03-16 22:12:56 phintuka Exp $ - * - */ - -#ifndef _XINELIBOUTPUT_H264_H_ -#define _XINELIBOUTPUT_H264_H_ - - -#ifdef __cplusplus -extern "C" { -#endif - -#include "mpeg.h" - -typedef struct { - int width; - int height; - double pixel_aspect; - /* ... */ -} h264_sps_data_t; - -/* - * input: start of NAL SPS (without 00 00 01 07) - */ -int h264_parse_sps(const uint8_t *buf, int len, h264_sps_data_t *sps); - -/* - * input: start of H.264 video data (not PES) - */ -int h264_get_picture_type(const uint8_t *buf, int len); - -/* - * input: start of H.264 video data (not PES) - */ -int h264_get_video_size(const uint8_t *buf, int len, video_size_t *size); - - -#ifdef __cplusplus -} /* extern "C" { */ -#endif - - -#endif /* _XINELIBOUTPUT_H264_H_ */ diff --git a/tools/http.c b/tools/http.c deleted file mode 100644 index 4a529550..00000000 --- a/tools/http.c +++ /dev/null @@ -1,434 +0,0 @@ -/* - * http.c: HTTP (/RTSP) helper classes - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: http.c,v 1.6 2007-06-21 09:12:52 phintuka Exp $ - * - */ - -#define __STDC_FORMAT_MACROS -#include - -#include - -#include -#include - -#include "../logdefs.h" - -#include "http.h" - -// -// cHttpReq -// - -bool cHttpReq::SetCommand(const char *Command) -{ - char *tmp = strdup(Command); - char *pt = strchr(tmp, ' '), *uri; - - m_Valid = false; - if(pt) { - *pt++ = 0; - m_Name = tmp; - - while(*pt && *pt == ' ') pt++; - - uri = pt; - pt = strrchr(uri, ' '); - if(pt) { - m_Version = pt+1; - while(*pt && *pt == ' ') *pt-- = 0; - m_Uri = uri; - m_Valid = true; - } - } - - free(tmp); - return m_Valid; -} - -cHeader *cHttpReq::Header(const char *Name) -{ - for(cHeader *i = m_Headers.First(); i; i = m_Headers.Next(i)) - if(!strcmp(Name, i->Name())) - return i; - return NULL; -} - -void cHttpReq::AddHeader(const char *Header, bool Duplicate) -{ - if(strlen(Header) < 4096) { - char *name = strdup(Header); - char *val = strchr(name, ':'); - if(val) { - *val++ = 0; - while(*val == ' ') val++; - AddHeader(name, val, Duplicate); - } - free(name); - } else { - LOGMSG("cConnState::AddHeader: header length exceeds 4096 !"); - } -} - -void cHttpReq::AddHeader(const char *Name, const char *Value, bool Duplicate) -{ - if(strlen(Name) > 64 || strlen(Value) > 4096) { - LOGMSG("cConnState::AddHeader: header length exceeds limit !"); - } else { - cHeader *h = Header(Name); - if(!Duplicate && h) - h->SetValue(Value); - else { - if(m_Headers.Count() < 50) - m_Headers.Add(new cHeader(Name, Value)); - else - LOGMSG("cConnState::AddHeader: header count exceeds 50 !"); - } - } -} - -void cHttpReq::Reset(void) -{ - m_Name = NULL; - m_Uri = NULL; - m_Version = NULL; - m_Valid = false; - m_Headers.Clear(); -} - -// -// Map file extensions to mime types -// - -static const char *mimetype(const char *ext) -{ - static const struct { - const char *ext; - const char *mime; - } ext2mime[] = { - {"avi", "video/avi"}, - {"vob", "video/mpeg"}, - {"mpg", "video/mpeg"}, - {"mpeg", "video/mpeg"}, - {"vdr", "video/mp2p"}, - - {"mp3", "audio/mp3"}, - {"flac", "audio/flac"}, - - {"jpg", "image/jpeg"}, - {"jpeg", "image/jpeg"}, - {"gif", "image/gif"}, - - {NULL, NULL} - }; - - int i = -1; - while(ext2mime[++i].ext) - if(!strcmp(ext, ext2mime[i].ext)) - return ext2mime[i].mime; - return NULL; -} - -static char *unescape_uri(const char *uri) -{ - char *d = strdup(uri), *s = d, *result = d; - while(*s) { - if(s[0] == '%' && s[1] && s[2]) { - unsigned int c; - if (sscanf(s+1, "%02x", &c) == 1) { - *d++ = (char)c; - s += 3; - continue; - } - } - *d++ = *s++; - } - *d = 0; - return result; -} - -// -// cHttpStreamer -// - -cList cHttpStreamer::m_Streamers; - -void cHttpStreamer::CloseAll(bool OnlyFinished) -{ - if(!OnlyFinished) { - while(m_Streamers.First()) - m_Streamers.Del(m_Streamers.First()); - - } else { - /* purge finished streamers from list */ - cHttpStreamer *it = m_Streamers.First(); - while(it) { - if(it->Active()) { - it = (cHttpStreamer*)it->Next(); - } else { - m_Streamers.Del(it); - it = m_Streamers.First(); - } - } - } -} - -cHttpStreamer::cHttpStreamer(int fd_http, const char *filename, - cConnState *Request) : - m_Filename(unescape_uri(filename), true) -{ - m_fds.set_handle(fd_http); - m_fds.set_cork(true); - m_fdf = -1; - - //m_Filename = filename; - m_FileSize = -1; - m_Start = 0; - m_End = -1; - m_KeepOpen = true; - - m_ConnState = Request; - - m_Finished = false; - - CloseAll(true); - - m_Streamers.Add(this); - - if(m_Streamers.Count() > 5) { - LOGMSG("WARNING: There are %d running HTTP streamers !", m_Streamers.Count()); - if(m_Streamers.Count() > 20) { - errno = 0; - LOGERR("ERROR: There are %d running HTTP streamers, cancelling first", - m_Streamers.Count()); - m_Streamers.Del(m_Streamers.First()); - } - } - - Start(); -} - -cHttpStreamer::~cHttpStreamer() -{ - Cancel(3); - if(m_ConnState) - delete m_ConnState; - if(m_fdf >= 0) - close(m_fdf); - m_fdf = -1; -} - -void cHttpStreamer::ParseRange(const char *Range) -{ - m_Start = 0; - m_End = -1; - if(Range) { - LOGDBG("cHttpStreamer: Request range is \'%s\'", Range); - switch(sscanf(Range, "bytes=%" PRId64 "-%" PRId64, &m_Start, &m_End)) { - case 2: LOGMSG(" Range: %s (%" PRId64 " - %" PRId64 ")", Range, m_Start, m_End); - break; - case 1: m_End = -1; - LOGMSG(" Range start: %s (%" PRId64 " - )", Range, m_Start); - break; - default: - case 0: m_Start = 0; - m_End = -1; - break; - } - } -} - -bool cHttpStreamer::ParseRequest(void) -{ - cHeader *h; - - if((h = m_ConnState->Header("Range")) != NULL) - ParseRange(h->Value()); - - m_KeepOpen = false; - if((h = m_ConnState->Header("Connection")) != NULL) { - m_KeepOpen = !strcasecmp(h->Value(), "keep-alive"); - if(m_KeepOpen) - LOGDBG("cHttpStreamer: client wants to keep connection open"); - } - - return true; -} - -bool cHttpStreamer::Seek(void) -{ - if(m_fdf < 0) { - m_fdf = open(m_Filename, O_RDONLY); - if(m_fdf < 0) { - LOGERR("cHttpStreamer: error opening %s", *m_Filename); - m_fds.write_cmd(HTTP_REPLY_401); // 401 Not Found - return false; - } - - m_FileSize = lseek(m_fdf, 0, SEEK_END); - if(m_FileSize <= 0) { - LOGERR("cHttpStreamer: error seeking %s to end", *m_Filename); - m_fds.write_cmd(HTTP_REPLY_401); // 401 Not Found - return false; - } - } - - if(m_Start >= m_FileSize) { - LOGERR("cHttpStreamer: Requested range not available " - "(%s:%" PRId64 "-%" PRId64 " ; len=%" PRIu64 ")", - *m_Filename, m_Start, m_End, (uint64_t)m_FileSize); - m_fds.write_cmd(HTTP_REPLY_416); // 416 Requested Range Not Satisfiable - return false; - } - - if(m_Start > 0) { - if(m_End >= m_FileSize || m_End < 0) - m_End = m_FileSize-1; - - m_fds.write_cmd("HTTP/1.1 206 Partial Content\r\n"); - m_fds.printf("Content-Range: bytes %" PRId64 "-%" PRId64 "/%" PRIu64 "\r\n", - m_Start, m_End, (uint64_t)m_FileSize); - } else { - m_fds.write_cmd("HTTP/1.1 200 OK\r\n"); - } - - /* content type */ - char *ext = strrchr(m_Filename, '.'); - if(ext) { - const char *mime = mimetype(ext+1); - if(mime) - m_fds.printf("Content-Type: %s\r\n", mime); - } - - /* Content-Length */ - if(m_FileSize >= 0) { - int64_t len = m_FileSize; - if(m_End >= 0) - len = m_End + 1; - if(m_Start >= 0) - len -= m_Start; - m_fds.printf("Content-Length: %" PRId64 "\r\n", len); - } - - /* Connection and end of reply */ - if(m_KeepOpen) - m_fds.write_cmd("Connection: Keep-Alive\r\n" - "\r\n"); - else - m_fds.write_cmd("Connection: Close\r\n" - "\r\n"); - - if(m_Start) - lseek(m_fdf, (off_t)m_Start, SEEK_SET); - else - lseek(m_fdf, 0, SEEK_SET); - - return true; -} - -bool cHttpStreamer::ReadPipelined(void) -{ - char buf[2048]; - int r; - - if(m_ConnState) - delete m_ConnState; - m_ConnState = new cConnState; - - do { - r = m_fds.readline(buf, sizeof(buf), 1000); - if(r < 0 || errno == EAGAIN || r >= (int)sizeof(buf)) { - LOGMSG("cHttpStreamer: disconnected"); - return false; - } - - LOGMSG("cHttpStreamer: pipelined request: %s", buf); - - if(!*m_ConnState->Name()) { - if(!m_ConnState->SetCommand(buf) || - strcmp(m_ConnState->Name(), "GET") || - strncmp(m_ConnState->Uri(), "/PLAYFILE", 9) || - strncmp(m_ConnState->Version(), "HTTP/1.", 7)) { - LOGMSG("Incorrect HTTP request: %s", buf); - return false; - } - } - else if(r > 0) - m_ConnState->AddHeader(buf); - } while(r>0); - - return true; -} - -void cHttpStreamer::Action(void) -{ - int n = 0; - cxPoller p(m_fds); - bool Disc = !(ParseRequest() && Seek()); - uint64_t pos = m_Start; - off_t start = (off_t)m_Start; - - while(Running() && !Disc) { - - n = m_End>0 ? (m_End-start+1) : m_FileSize - start; - if(n > 0) { - errno = 0; - pthread_testcancel(); - n = m_fds.sendfile(m_fdf, &start, n); - pthread_testcancel(); - if(n <= 0) { - if(errno == EAGAIN || errno == EINTR) { - p.Poll(100); - pthread_testcancel(); - } else { - LOGERR("cHttpStreamer: sendfile() failed"); - Disc=true; - } - } else if(n == 0) { - LOGMSG("cHttpStreamer: disconnected at %" PRId64, (int64_t)start); - Disc = true; - } - continue; - } - - LOGDBG("cHttpStreamer: Hit to EOF or end of requested range"); - - m_fds.flush_cork(); - - if(!m_KeepOpen) { - LOGMSG("cHttpStreamer: disconnecting (request complete)"); - Disc = true; - continue; - } - - // keep connection open for new range for max. 30 sec - n = 30; - do { - pthread_testcancel(); - //cxPoller p(m_fds); - LOGDBG("cHttpStreamer: Request complete, waiting..."); - if(p.Poll(1000)) { - LOGDBG("cHttpStreamer: Reading pipelined request"); - pthread_testcancel(); - Disc = !(ReadPipelined() && ParseRequest() && Seek()); - pos = m_Start; - } - } while(--n && Running() && !Disc); - - if(n <= 0) { - LOGMSG("cHttpStreamer: Disconnecting (timeout)"); - Disc = true; - } - } - - close(m_fdf); - m_fdf = -1; - - m_fds.close(); - - m_Finished = true; -} diff --git a/tools/http.h b/tools/http.h deleted file mode 100644 index 2adcf8e3..00000000 --- a/tools/http.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - * http.h: HTTP (/RTSP) helper classes - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: http.h,v 1.5 2007-01-07 09:45:48 phintuka Exp $ - * - */ - -#ifndef XINELIBOUTPUT_HTTP_H_ -#define XINELIBOUTPUT_HTTP_H_ - -#include - - -#define HTTP_REPLY_401 \ - "HTTP/1.1 401 Unauthorized\r\n" \ - "Connection: Close\r\n" \ - "\r\n" - -#define HTTP_REPLY_404 \ - "HTTP/1.1 404 Not Found\r\n" \ - "Connection: Close\r\n" \ - "\r\n" - -#define HTTP_REPLY_416 \ - "HTTP/1.1 416 Requested Range Not Satisfiable\r\n" \ - "Connection: Close\r\n" \ - "\r\n" - -#define HTTP_REPLY_200_PRIMARY \ - "HTTP/1.1 200 OK\r\n" \ - "Content-Type: video/mpeg\r\n" \ - "Connection: Close\r\n" \ - "\r\n" -//"Content-Type: video/mp2p\r\n" - - -// -// cHeader -// - -class cHeader : public cListObject -{ - protected: - cString m_Name; - cString m_Value; - - private: - cHeader(); - - public: - cHeader(const char *Name, const char *Value) : - m_Name(Name), m_Value(Value) {}; - - const cString& Name(void) { return m_Name; } - const cString& Value(void) { return m_Value; } - int IntValue(void) { return *m_Value?atoi(m_Value):-1; } - void SetValue(const char *Value) { m_Value = Value; } -}; - - -// -// cHttpReq -// - -class cHttpReq -{ - private: - cString m_Name; - cString m_Uri; - cString m_Version; - cList m_Headers; - - bool m_Valid; - - public: - cHttpReq() : m_Valid(false) {} - - bool SetCommand(const char *Command); - const cString& Name(void) { return m_Name; } - const cString& Uri(void) { return m_Uri; } - const cString& Version(void) { return m_Version; } - bool Valid(void) { return m_Valid; } - - void AddHeader(const char *Header, bool Duplicate=false); - void AddHeader(const char *Name, const char *Value, bool Duplicate=false); - cHeader *Header(const char *Name); - - void Reset(void); -}; - - -// -// cConnState -// - -class cConnState : public cHttpReq -{ - public: -}; - - -// -// cHttpStreamer -// - -#include -#include - -#include "cxsocket.h" - -class cHttpStreamer : protected cListObject, cThread -{ - public: - cHttpStreamer(int fd_http, const char *filename, cConnState *Request); - virtual ~cHttpStreamer(); - - static void CloseAll(bool OnlyFinished = false); - - private: - static cList m_Streamers; - - cxSocket m_fds; - int m_fdf; - - cString m_Filename; - int64_t m_FileSize; - int64_t m_Start; - int64_t m_End; - bool m_KeepOpen; - - cConnState *m_ConnState; - - bool m_Finished; - - virtual void Action(void); - - bool ParseRequest(void); - void ParseRange(const char *Range); - bool ReadPipelined(void); - bool Seek(void); -}; - -#endif // XINELIBOUTPUT_HTTP_H_ - diff --git a/tools/iconv.h b/tools/iconv.h deleted file mode 100644 index 3ce0fb28..00000000 --- a/tools/iconv.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * iconv.h: iconv library wrapper - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: iconv.h,v 1.5 2007-09-18 09:13:13 phintuka Exp $ - * - */ - -#ifndef _XINELIBOUTPUT_ICONV_H_ -#define _XINELIBOUTPUT_ICONV_H_ - -#if defined(USE_ICONV) && USE_ICONV == 0 -# undef USE_ICONV -# warning iconv disabled -#endif - -#ifdef USE_ICONV -# include -#endif - -class cIConv -{ -#ifdef USE_ICONV - private: - iconv_t m_ic; -#endif - - public: - cIConv(const char *SrcCharset = NULL, const char * DstCharset = NULL); - virtual ~cIConv(); - - cString Translate(const char *Text) const; -}; - -cIConv::cIConv(const char *SrcCharset, const char * DstCharset) -{ -#ifdef USE_ICONV - if(!SrcCharset) - SrcCharset = "UTF-8"; - if(!DstCharset) { -#if APIVERSNUM >= 10503 - DstCharset = cCharSetConv::SystemCharacterTable(); -#else - DstCharset = I18nCharSets()[Setup.OSDLanguage]; -#endif - } - m_ic = (iconv_t)-1; - - if(DstCharset) { - m_ic = iconv_open(DstCharset, SrcCharset); - - if(m_ic == (iconv_t)-1) - LOGERR("cIConv: iconv_open(\"%s\",\"%s\") failed", - SrcCharset, DstCharset); - } -#endif -} - -cIConv::~cIConv() -{ -#ifdef USE_ICONV - if(m_ic != (iconv_t)-1) - iconv_close(m_ic); -#endif -} - -cString cIConv::Translate(const char *Text) const -{ -#ifdef USE_ICONV - if(m_ic == (iconv_t)-1) - return cString(Text); - - size_t inc = strlen(Text); - size_t outc = inc<2048 ? 2048 : inc+1; -#ifdef __APPLE__ - const char *in = Text; -#else - char *in = (char*)Text; -#endif - char *buf = (char*)malloc(outc+1); - char *out = buf; - - size_t n = iconv(m_ic, &in, &inc, &out, &outc); - - if(n != (size_t)-1) { - *out = 0; - return cString(buf, true); - } - - LOGERR("cIConv: iconv(%s) failed at %d", Text, (int)(in - Text)); - free(buf); -#endif - - return cString(Text); -} - - -#endif // _XINELIBOUTPUT_ICONV_H_ diff --git a/tools/iso639.h b/tools/iso639.h deleted file mode 100644 index 66438f13..00000000 --- a/tools/iso639.h +++ /dev/null @@ -1,171 +0,0 @@ -/* - * iso639.h: iso-639-1 <-> iso-639-2 language code translations - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: iso639.h,v 1.1 2008-02-20 03:55:11 phintuka Exp $ - * - */ - -#ifndef __ISO_639_H -#define __ISO_639_H - -static const struct { - const char iso639_2[4]; - const char iso639_1[4]; -} ISO639_map[] = -{ - {"???", "??"}, - {"abk", "ab"}, - {"aar", "aa"}, - {"afr", "af"}, - {"alb", "sq"}, - {"amh", "am"}, - {"ara", "ar"}, - {"arm", "hy"}, - {"ast", "as"}, - {"aym", "ay"}, - {"aze", "az"}, - {"bak", "ba"}, - {"baq", "eu"}, - {"bel", "be"}, - {"ben", "bn"}, - {"bih", "bh"}, - {"bis", "bi"}, - {"bre", "br"}, - {"bul", "bg"}, - {"bur", "my"}, - {"cat", "ca"}, - {"chi", "zh"}, - {"cos", "co"}, - {"scr", "hr"}, - {"cze", "cs"}, - {"dan", "da"}, - {"dut", "nl"}, - {"dzo", "dz"}, - {"eng", "en"}, - {"epo", "eo"}, - {"est", "et"}, - {"fao", "fo"}, - {"fij", "fj"}, - {"fin", "fi"}, - {"fre", "fr"}, - {"fry", "fy"}, - {"glg", "gl"}, - {"geo", "ka"}, - {"ger", "de"}, - {"gre", "el"}, - {"grn", "gn"}, - {"guj", "gu"}, - {"hau", "ha"}, - {"heb", "he"}, - {"hin", "hi"}, - {"hun", "hu"}, - {"ice", "is"}, - {"ind", "id"}, - {"ina", "ia"}, - {"iku", "iu"}, - {"ipk", "ik"}, - {"gle", "ga"}, - {"ita", "it"}, - {"jpn", "ja"}, - {"jav", "jv"}, - {"kal", "kl"}, - {"kan", "kn"}, - {"kas", "ks"}, - {"kaz", "kk"}, - {"khm", "km"}, - {"kin", "rw"}, - {"kir", "ky"}, - {"kor", "ko"}, - {"kur", "ku"}, - {"lao", "lo"}, - {"lat", "la"}, - {"lav", "lv"}, - {"lin", "ln"}, - {"lit", "lt"}, - {"mac", "mk"}, - {"mlg", "mg"}, - {"may", "ms"}, - {"mlt", "ml"}, - {"mao", "mi"}, - {"mar", "mr"}, - {"mol", "mo"}, - {"mon", "mn"}, - {"nau", "na"}, - {"nep", "ne"}, - {"nor", "no"}, - {"oci", "oc"}, - {"ori", "or"}, - {"orm", "om"}, - {"per", "fa"}, - {"pol", "pl"}, - {"por", "pt"}, - {"pus", "ps"}, - {"que", "qu"}, - {"roh", "rm"}, - {"rum", "ro"}, - {"run", "rn"}, - {"rus", "ru"}, - {"smo", "sm"}, - {"sag", "sg"}, - {"san", "sa"}, - {"srp", "sr"}, - {"scr", "sh"}, - {"sna", "sn"}, - {"snd", "sd"}, - {"sin", "si"}, - {"slo", "sk"}, - {"slv", "sl"}, - {"som", "so"}, - {"sot", "st"}, - {"spa", "es"}, - {"sun", "su"}, - {"swa", "sw"}, - {"ssw", "ss"}, - {"swe", "sv"}, - {"tgl", "tl"}, - {"tgk", "tg"}, - {"tam", "ta"}, - {"tat", "tt"}, - {"tel", "te"}, - {"tha", "th"}, - {"tib", "bo"}, - {"tir", "ti"}, - {"tog", "to"}, - {"tso", "ts"}, - {"tsn", "tn"}, - {"tur", "tr"}, - {"tuk", "tk"}, - {"twi", "tw"}, - {"uig", "ug"}, - {"ukr", "uk"}, - {"urd", "ur"}, - {"uzb", "uz"}, - {"vie", "vi"}, - {"vol", "vo"}, - {"wel", "cy"}, - {"wol", "wo"}, - {"xho", "xh"}, - {"yid", "yi"}, - {"yor", "yo"}, - {"zha", "za"}, - {"zul", "zu"}, -}; - -static const char *iso639_2_to_iso639_1(const char *lang) -{ - if (lang && lang[0]) { - if(lang[1] && !lang[2]) { - for (unsigned int i = 0 ; i < sizeof(ISO639_map) / sizeof(ISO639_map[0]); i++) - if (((uint16_t*)ISO639_map[i].iso639_1)[0] == ((uint16_t*)lang)[0]) - return ISO639_map[i].iso639_2; - LOGMSG("Unknown iso639-2 code: %s", lang); - } - return lang; - } - return NULL; -} - -#endif diff --git a/tools/listiter.h b/tools/listiter.h deleted file mode 100644 index 9c88940e..00000000 --- a/tools/listiter.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * listiter.h: - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: listiter.h,v 1.1 2006-06-03 10:04:27 phintuka Exp $ - * - */ - - -#ifndef _LISTITER_H_ -#define _LISTITER_H_ - -//------------------------------ list ---------------------------------------- - -template -void ForEach(LIST& List, RESULT (ITEM::*f)()) -{ - for(ITEM *it = List.First(); it; it = List.Next(it)) - (*it.*f)(); -} - -template -void ForEach(LIST& List, RESULT (ITEM::*f)(ARG1), ARG1 arg1) -{ - for(ITEM *it = List.First(); it; it = List.Next(it)) - (*it.*f)(arg1); -} - -template -void ForEach(LIST& List, void (ITEM::*f)(ARG1,ARG2), ARG1 arg1, ARG2 arg2) -{ - for(ITEM *it = List.First(); it; it = List.Next(it)) - (*it.*f)(arg1,arg2); -} - -template -RESULT ForEach(LIST& List, RESULT (ITEM::*f)(ARG1), ARG1 arg1, - RESULT (*combiner)(RESULT,RESULT), RESULT def) -{ - RESULT result = def; - for(ITEM *it = List.First(); it; it = List.Next(it)) - result = (*combiner)((*it.*f)(arg1),result); - return result; -} - -template -RESULT ForEach(LIST& List, RESULT (ITEM::*f)(ARG1,ARG2), - ARG1 arg1, ARG2 arg2, - RESULT (*combiner)(RESULT,RESULT), RESULT def) -{ - RESULT result = def; - for(ITEM *it = List.First(); it; it = List.Next(it)) - result = (*combiner)((*it.*f)(arg1,arg2),result); - return result; -} - -template -RESULT ForEach(LIST& List, RESULT (ITEM::*f)(ARG1,ARG2,ARG3), - ARG1 arg1, ARG2 arg2, ARG3 arg3, - RESULT (*combiner)(RESULT,RESULT), RESULT def) -{ - RESULT result = def; - for(ITEM *it = List.First(); it; it = List.Next(it)) - result = (*combiner)((*it.*f)(arg1,arg2,arg3),result); - return result; -} - -template -T mmin(T a, T b) {return a -T mmax(T a, T b) {return a>b ? a : b;} - -template -T mand(T a, T b) {return a&&b;} - -template -T mor(T a, T b) {return a||b;} - -#endif diff --git a/tools/mpeg.c b/tools/mpeg.c deleted file mode 100644 index 35e95da3..00000000 --- a/tools/mpeg.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * mpeg.c: - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: mpeg.c,v 1.1 2008-02-04 22:42:13 phintuka Exp $ - * - */ - -#include "mpeg.h" - - -const char * const picture_type_str[] = { - "(none)", - "I-Frame", - "B-Frame", - "P-Frame" -}; - - -int mpeg2_get_picture_type(const uint8_t *buf, int len) -{ - int i; - for (i = 0; i < len-5; i++) { - if (buf[i] == 0 && buf[i + 1] == 0 && buf[i + 2] == 1) { - switch (buf[i + 3]) { - case SC_PICTURE: - return (buf[i + 5] >> 3) & 0x07; - } - } - } - return NO_PICTURE; -} - -int mpeg2_get_video_size(const uint8_t *buf, int len, video_size_t *size) -{ - int i; - for (i = 0; i < len-6; i++) { - if (buf[i] == 0 && buf[i + 1] == 0 && buf[i + 2] == 1) { - if (buf[i + 3] == SC_SEQUENCE) { - int d = (buf[i+4] << 16) | (buf[i+5] << 8) | buf[i+6]; - size->width = (d >> 12); - size->height = (d & 0xfff); - return 1; - } - } - } - return 0; -} - diff --git a/tools/mpeg.h b/tools/mpeg.h deleted file mode 100644 index c17ee0ec..00000000 --- a/tools/mpeg.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * mpeg.h: MPEG definitions - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: mpeg.h,v 1.2 2008-03-16 22:12:56 phintuka Exp $ - * - */ - -#ifndef XINELIBOUTPUT_MPEG_H_ -#define XINELIBOUTPUT_MPEG_H_ - - -#ifdef __cplusplus -extern "C" { -#endif - - -#define SC_PICTURE 0x00 /* picture atart code */ -#define SC_SEQUENCE 0xb3 /* sequence header */ - -/* Picture types */ -#define NO_PICTURE 0 -#define I_FRAME 1 -#define P_FRAME 2 -#define B_FRAME 3 - - -typedef struct { - int width; - int height; - double pixel_aspect; -} video_size_t; - - -extern const char * const picture_type_str[]; - -/* - * input: start of MPEG video data (not PES) - */ -int mpeg2_get_picture_type(const uint8_t *buf, int len); - -/* - * input: start of MPEG video data (not PES) - */ -int mpeg2_get_video_size(const uint8_t *buf, int len, video_size_t *size); - - -#ifdef __cplusplus -} /* extern "C" { */ -#endif - - -#endif diff --git a/tools/pes.c b/tools/pes.c deleted file mode 100644 index 2845bf07..00000000 --- a/tools/pes.c +++ /dev/null @@ -1,152 +0,0 @@ -/* - * pes.h: PES header definitions - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: pes.c,v 1.2 2008-02-04 23:49:50 phintuka Exp $ - * - */ - -#include "mpeg.h" -#include "h264.h" - -#include "pes.h" - - -int64_t pes_get_pts(const uint8_t *buf, int len) -{ - /* assume mpeg2 pes header ... */ - if (IS_VIDEO_PACKET(buf) || IS_AUDIO_PACKET(buf)) { - - if ((buf[6] & 0xC0) != 0x80) - return INT64_C(-1); - if ((buf[6] & 0x30) != 0) - return INT64_C(-1); - - if ((len > 14) && (buf[7] & 0x80)) { /* pts avail */ - int64_t pts; - pts = ((int64_t)(buf[ 9] & 0x0E)) << 29 ; - pts |= ((int64_t) buf[10]) << 22 ; - pts |= ((int64_t)(buf[11] & 0xFE)) << 14 ; - pts |= ((int64_t) buf[12]) << 7 ; - pts |= ((int64_t)(buf[13] & 0xFE)) >> 1 ; - return pts; - } - } - return INT64_C(-1); -} - -int64_t pes_get_dts(const uint8_t *buf, int len) -{ - if (IS_VIDEO_PACKET(buf) || IS_AUDIO_PACKET(buf)) { - - if ((buf[6] & 0xC0) != 0x80) - return INT64_C(-1); - if ((buf[6] & 0x30) != 0) - return INT64_C(-1); - - if (len > 18 && (buf[7] & 0x40)) { /* dts avail */ - int64_t dts; - dts = ((int64_t)( buf[14] & 0x0E)) << 29 ; - dts |= (int64_t)( buf[15] << 22 ); - dts |= (int64_t)((buf[16] & 0xFE) << 14 ); - dts |= (int64_t)( buf[17] << 7 ); - dts |= (int64_t)((buf[18] & 0xFE) >> 1 ); - return dts; - } - } - return INT64_C(-1); -} - -void pes_change_pts(uint8_t *buf, int len, int64_t new_pts) -{ - /* assume mpeg2 pes header ... Assume header already HAS pts */ - if (IS_VIDEO_PACKET(buf) || IS_AUDIO_PACKET(buf)) { - - if ((buf[6] & 0xC0) != 0x80) - return; - if ((buf[6] & 0x30) != 0) - return; - - if ((len > 14) && (buf[7] & 0x80)) { /* pts avail */ - buf[ 9] = ((new_pts >> 29) & 0x0E) | (buf[ 9] & 0xf1); - buf[10] = ((new_pts >> 22) & 0xFF); - buf[11] = ((new_pts >> 14) & 0xFE) | (buf[11] & 0x01); - buf[12] = ((new_pts >> 7 ) & 0xFF); - buf[13] = ((new_pts << 1 ) & 0xFE) | (buf[13] & 0x01); - } - } -} - -int pes_strip_pts_dts(uint8_t *buf, int size) -{ - if(size > 13 && buf[7] & 0x80) { /* pts avail */ - int n = 5; - int pes_len = (buf[4] << 8) | buf[5]; - if ((buf[6] & 0xC0) != 0x80) - return size; - if ((buf[6] & 0x30) != 0) /* scrambling control */ - return size; - /* dts too ? */ - if(size > 18 && buf[7] & 0x40) - n += 5; - pes_len -= n; /* update packet len */ - buf[4] = pes_len >> 8; /* packet len (hi) */ - buf[5] = pes_len & 0xff; /* packet len (lo) */ - buf[7] &= 0x7f; /* clear pts flag */ - buf[8] -= 5; /* update header len */ - memmove(buf+4+n, buf+9+n, size-9-n); - return size - n; - } - return size; -} - -int pes_is_frame_h264(const uint8_t *buf, int len) -{ - if (len < 9 || len < 9 + buf[8]) - return 0; - if ( (buf[6] & 0xC0) != 0x80) /* MPEG 2 PES */ - return 0; - - buf += 9 + buf[8]; - - if (!buf[0] && !buf[1] && buf[2] == 0x01 && buf[3] == 0x09) - return 1; - return 0; -} - -uint8_t pes_get_picture_type(const uint8_t *buf, int len) -{ - int i = 8; /* the minimum length of the video packet header */ - i += buf[i] + 1; /* possible additional header bytes */ - - buf += i; - len -= i; - - if (!buf[0] && !buf[1] && buf[2]) { - if (buf[3] == 0x09) - return h264_get_picture_type(buf, len); - else - return mpeg2_get_picture_type(buf, len); - } - return NO_PICTURE; -} - -int pes_get_video_size(const uint8_t *buf, int len, video_size_t *size, int h264) -{ - int i = 8; - - i += buf[i] + 1; /* possible additional header bytes */ - - buf += i; - len -= i; - - if (h264 || (!buf[0] && !buf[1] && buf[2] == 0x01 && buf[3] == 0x09)) - return h264_get_video_size(buf, len, size); - else - return mpeg2_get_video_size(buf, len, size); - - return 0; -} - diff --git a/tools/pes.h b/tools/pes.h deleted file mode 100644 index c55a4ed5..00000000 --- a/tools/pes.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * pes.h: PES header definitions - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: pes.h,v 1.6 2008-02-04 23:59:30 phintuka Exp $ - * - */ - -#ifndef _PES_H_ -#define _PES_H_ - -#include "mpeg.h" - - -/* - * Constants - */ - -#define PES_CHUNK_SIZE 2048 - -#define MAX_SCR ((int64_t)0x1ffffffffLL) - -/* PES PIDs */ -#define PRIVATE_STREAM1 0xBD -#define PADDING_STREAM 0xBE -#define PRIVATE_STREAM2 0xBF -#define AUDIO_STREAM_S 0xC0 /* 1100 0000 */ -#define AUDIO_STREAM_E 0xDF /* 1101 1111 */ -#define VIDEO_STREAM_S 0xE0 /* 1110 0000 */ -#define VIDEO_STREAM_E 0xEF /* 1110 1111 */ - -#define AUDIO_STREAM_MASK 0x1F /* 0001 1111 */ -#define VIDEO_STREAM_MASK 0x0F /* 0000 1111 */ -#define AUDIO_STREAM 0xC0 /* 1100 0000 */ -#define VIDEO_STREAM 0xE0 /* 1110 0000 */ - -#define ECM_STREAM 0xF0 -#define EMM_STREAM 0xF1 -#define DSM_CC_STREAM 0xF2 -#define ISO13522_STREAM 0xF3 -#define PROG_STREAM_DIR 0xFF - -#define IS_VIDEO_PACKET(data) (VIDEO_STREAM == ((data)[3] & ~VIDEO_STREAM_MASK)) -#define IS_AUDIO_PACKET(data) ((AUDIO_STREAM == ((data)[3] & ~AUDIO_STREAM_MASK)) || \ - (PRIVATE_STREAM1 == (data)[3])) - -#define PES_HAS_PTS(data) ((data)[7] & 0x80) -#define PES_HAS_DTS(data) ((data)[7] & 0x40) - -/* - * timestamps - */ - - -int64_t pes_get_pts(const uint8_t *buf, int len); -int64_t pes_get_dts(const uint8_t *buf, int len); -void pes_change_pts(uint8_t *buf, int len, int64_t new_pts); -int pes_strip_pts_dts(uint8_t *buf, int len); - -/* - * payload - */ - -int pes_is_frame_h264(const uint8_t *buf, int len); -uint8_t pes_get_picture_type(const uint8_t *buf, int len); -int pes_get_video_size(const uint8_t *buf, int len, video_size_t *size, int h264); - -static inline int pes_is_mpeg1(const uint8_t *header) -{ - if (IS_VIDEO_PACKET(header) || IS_AUDIO_PACKET(header)) - return ((header[6] & 0xC0) != 0x80); - if (header[3] == 0xBA) - return ((header[4] & 0x40) == 0); /* mpeg1 */ - return 0; -} - -/* - * Extract PES packet length - */ - -static inline int pes_packet_len(const uint8_t *data, const int len) -{ - if (IS_VIDEO_PACKET(data) || IS_AUDIO_PACKET(data)) { - return 6 + (data[4] << 8 | data[5]); - } else if (data[3] == PADDING_STREAM) { - return 6 + (data[4] << 8 | data[5]); - } else if (data[3] == 0xBA) { - if ((data[4] & 0x40) == 0) /* mpeg1 */ - return 12; - else /* mpeg 2 */ - return 14 + (data[0xD] & 0x07); - } else if (data[3] <= 0xB9) { - return -3; - } - return -(6 + (data[4] << 8 | data[5])); -} - - -#endif /* _PES_H_ */ diff --git a/tools/playlist.c b/tools/playlist.c deleted file mode 100644 index 9f4c85c3..00000000 --- a/tools/playlist.c +++ /dev/null @@ -1,1000 +0,0 @@ -/* - * playlist.c: Media player playlist - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: playlist.c,v 1.17 2008-04-03 15:11:26 phelin Exp $ - * - */ - -#include - -#ifdef HAVE_EXTRACTOR_H -# include - // libextractor 0.5.20 (2008-03-20) adds support for track numbers -# if EXTRACTOR_VERSION < 0x00052000 -# warning libextractor version too old (0.5.20 required for track numbers) -# undef HAVE_EXTRACTOR_H -# endif -#endif - -#include -#include -#include - -#include "../config.h" - -#include "playlist.h" - -#include "../logdefs.h" - - -#ifndef PLAYLIST_CACHE -# define PLAYLIST_CACHE ".xineliboutput-playlist.pls" -#endif - -#define MAX_PLAYLIST_FILES 1024 - - -// -// cPlaylistItem -// - -cPlaylistItem::cPlaylistItem(const char *filename) -{ - char *pt; - - Filename = filename; - Position = -1; - - if(NULL != (pt = strrchr(filename, '/'))) - Title = pt + 1; - else - Title = filename; - - if(NULL != (pt = strrchr(Title, '.'))) - *pt = 0; -} - -cPlaylistItem::cPlaylistItem(const char *filename, - const char *path, - const char *title, - int position) -{ - char *pt; - - if(path[strlen(path)-1] != '/') - Filename = cString::sprintf("%s/%s", path, filename); - else - Filename = cString::sprintf("%s%s", path, filename); - Position = position; - Title = title ?: filename; - - if(!title && (pt = strrchr(Title, '.'))) - *pt = 0; -} - -int cPlaylistItem::Compare(const cListObject &ListObject) const -{ - ///< Must return 0 if this object is equal to ListObject, a positive value - ///< if it is "greater", and a negative value if it is "smaller". - - const cPlaylistItem *o = (cPlaylistItem *)&ListObject; - - // Use Position (if defined in playlist file) - // compare as unsigned --> -1 goes to last position - if(Position != o->Position) - return ((unsigned int)Position) > ((unsigned int)o->Position) ? 1 : -1; - - // same position (or no positions definend) -> alphabetical order -#if 0 - return strcmp(Title, o->Title); -#else - // use filename, because: - // - implicit playlist has no track names available when sorting - // (track names are read during playback), so track name is - // just file name without path. - // using full path allows sorting of each album and tracks inside albums... - // - "normal" playlist is ordered using Position, - // so track names are never compared anyway ... - return strcmp(Filename, o->Filename); -#endif -} - - -// -// cID3Scanner -// - -#ifndef HAVE_EXTRACTOR_H -static const char *shell_escape(char *buf, int buflen, const cString& src, char ch) -{ - const char *pt = *src; - int n = 0; - - if(pt) { - while(*pt && n < buflen-2) { - if(*pt == ch || *pt == '\\' /*|| *pt == '\"' || *pt == '\''*/) { - buf[n++] = '\\'; - } - buf[n++] = *pt++; - } - buf[n] = 0; - return buf; - } - return ""; -} -#endif - -class cID3Scanner : public cThread -{ - public: - cPlaylist& m_List; - cID3Scanner(cPlaylist& List) : cThread("Metadata scanner"), m_List(List), m_Done(false) {}; - - void CancelScanner(void) { Cancel(3); } - - private: - bool m_Done; - - virtual void Action(void) - { - cPlaylistItem *Item = NULL; - unsigned int Version = 0; - - (void)nice(10); - - LOGDBG("ID3Scanner Started"); - while(Running()) { - - cMutexLock ml(&m_List.m_Lock); - - if(Version < m_List.m_Version) { - // restart after sort, add, del - Item = NULL; - Version = m_List.m_Version; - } - - if(!(Item = m_List.Next(Item))) - break; - - if(xc.IsAudioFile(Item->Filename)) { - LOGDBG("Scanning metainfo for file %s", *Item->Filename); -#ifdef HAVE_EXTRACTOR_H - EXTRACTOR_ExtractorList * plugins; - EXTRACTOR_KeywordList * md_list; - plugins = EXTRACTOR_loadDefaultLibraries(); - md_list = EXTRACTOR_getKeywords(plugins, *Item->Filename); - const char *key; - while(md_list) { - if ((key=EXTRACTOR_getKeywordTypeAsString(md_list->keywordType))) { - if (!strcasecmp(key,"title")) - Item->Title = strdup(md_list->keyword); - else if (!strcasecmp(key,"artist")) - Item->Artist = strdup(md_list->keyword); - else if (!strcasecmp(key,"album")) - Item->Album = strdup(md_list->keyword); - else if (!strcasecmp(key,"track number")) - Item->Tracknumber = cString::sprintf("%s%s", strlen(md_list->keyword) == 1 ? "0" : "", md_list->keyword); - md_list=md_list->next; - } - } - EXTRACTOR_freeKeywords(md_list); - EXTRACTOR_removeAll(plugins); /* unload plugins */ -#else - char buf[4096]; - cString Cmd = ""; - if(!strcasecmp((Item->Filename) + strlen(Item->Filename) - 5, ".flac")) - Cmd = cString::sprintf("metaflac " - " --show-tag=TITLE " - " --show-tag=ALBUM " - " --show-tag=ARTIST " - " --show-tag=TRACKNUMBER " - " \"%s\"", - shell_escape(buf, sizeof(buf)-1, Item->Filename, '\"')); - else - Cmd = cString::sprintf("mp3info -p \"" - "ARTIST=%%a\\r\\n" - "ALBUM=%%l\\r\\n" - "TITLE=%%t\\r\\n" - "TRACKNUMBER=%%n\\r\\n\"" - " \"%s\"", - shell_escape(buf, sizeof(buf)-1, Item->Filename, '\"')); - - cPipe p; - if(p.Open(*Cmd, "r")) { - cReadLine r; - char *pt; - while(NULL != (pt = r.Read(p))) { - if(!strncasecmp(pt, "ARTIST=", 7) && strlen(pt) > 8) - Item->Artist = (pt+7); - else if(!strncasecmp(pt, "ALBUM=", 6) && strlen(pt) > 7) - Item->Album = (pt+6); - else if(!strncasecmp(pt, "TITLE=", 6) && strlen(pt) > 7) - Item->Title = (pt+6); - else if(!strncasecmp(pt, "TRACKNUMBER=", 12) && strlen(pt) > 12) - Item->Tracknumber = cString::sprintf("%s%s", strlen(pt) == 13 ? "0" : "", (pt+12)); - } - } -#endif - } - } - LOGDBG("ID3Scanner Done."); - - m_List.PlaylistChanged(Item); - m_Done = true; - } -}; - -// -// cPlaylistReader -// - -class cPlaylistReader -{ - private: - cPlaylist& m_Playlist; - - protected: - cString m_Title; - int m_Position; - - cPlaylistItem *Prev(void) { return m_Playlist.Last(); } - - public: - cPlaylistReader(cPlaylist& Playlist) : m_Playlist(Playlist) {} - virtual ~cPlaylistReader() {} - - virtual char *Parse(char *line) = 0; - - void ResetCache(void) { m_Title = NULL; m_Position = -1; } - const char *Title(void) { return m_Title; } - int Position(void) { return m_Position; } -}; - -class cM3uReader : public cPlaylistReader -{ - public: - cM3uReader(cPlaylist& Playlist) : cPlaylistReader(Playlist), m_Next(1) {} - - protected: - int m_Next; - virtual char *Parse(char *line) { - if(!*line) - return NULL; - if(*line == '#') { - if(!strncmp(line, "#EXTINF:", 8)) { - int len = -1; - sscanf(line+8,"%d", &len); - while(*line && *line != ',') - line++; - m_Title = *line ? (line+1) : NULL; - m_Position = m_Next++; - } - return NULL; - } - return *line ? line : NULL; - } -}; - -class cPlsReader : public cPlaylistReader -{ - public: - cPlsReader(cPlaylist& Playlist) : cPlaylistReader(Playlist), m_Current(0) {} - - protected: - int m_Current; - virtual char *Parse(char *line) { - char *t = strchr(line, '='); - if(t) { - int n; - if(!strncasecmp(line, "file", 4) && - 1 == sscanf(line + 4, "%d=", &n)) { - m_Current = n; - m_Position = n; - if(*(t+1)) - return t+1; - } - else if(!strncasecmp(line, "title", 5) && - 1 == sscanf(line + 5, "%d=", &n)) { - if(*(t+1)) { - if(n == m_Current) - Prev()->Title = t; - else - m_Title = t; - } - } - //else if(!strncasecmp(line, "length", 6) && - // 1 == sscanf(line + 4, "%d=", &n)) { - //} - } - return NULL; - } -}; - -class cAsxReader : public cPlaylistReader -{ - public: - cAsxReader(cPlaylist& Playlist) : cPlaylistReader(Playlist) {} - - protected: - virtual char *Parse(char *line) { - char *pt = strstr(line, ""); - if(!pt) - pt = strstr(line, ""); - if(pt) { - pt += 7; - if(strstr(line, "</")) - *strstr(line, "</") = 0; - m_Title = pt; - } - - if(*m_Title) { - pt = strstr(line, "<ENTRY>"); - if(!pt) - pt = strstr(line, "<entry>"); - if(pt) { - if(*m_Title && Prev()) { - Prev()->Title = m_Title; - m_Title = NULL; - } - } - } - return NULL; - } -}; - - -// -// cPlaylist -// - -cPlaylist::cPlaylist() -{ - m_Origin = eImplicit; - m_Menu = NULL; - m_Scanner = NULL; - m_Current = NULL; - m_Version = 1; -} - -cPlaylist::~cPlaylist() -{ - if(m_Scanner) { - m_Scanner->CancelScanner(); - delete m_Scanner; - } - - if(m_Origin == eImplicit) - StoreCache(); -} - -void cPlaylist::Listen(cPlaylistChangeNotify *Menu) -{ - cMutexLock ml(&m_Lock); - m_Menu = Menu; -} - -void cPlaylist::PlaylistChanged(const cPlaylistItem *Item) -{ - cMutexLock ml(&m_Lock); - /*if(m_Origin == eImplicit)*/ - Sort(); - if(m_Menu) - m_Menu->PlaylistChanged(Item); -} - -void cPlaylist::Sort(void) -{ - cMutexLock ml(&m_Lock); - cListBase::Sort(); - m_Version++; -} - -int cPlaylist::Count(void) const -{ - return cListBase::Count(); -} - -cPlaylistItem *cPlaylist::Next(const cPlaylistItem *i) -{ - cMutexLock ml(&m_Lock); - return i ? cList<cPlaylistItem>::Next(i) : cList<cPlaylistItem>::First(); -} - -cPlaylistItem *cPlaylist::Current(void) -{ - cMutexLock ml(&m_Lock); - return m_Current ?: First(); -} - -void cPlaylist::Del(cPlaylistItem *it) -{ - cMutexLock ml(&m_Lock); - - if(!it || Count() < 2) - return; - - if(m_Current == it) - m_Current = cList<cPlaylistItem>::Next(Current()) ?: - cList<cPlaylistItem>::Prev(Current()); - - cListBase::Del(it); - m_Version++; -} - -void cPlaylist::SetCurrent(cPlaylistItem *current) -{ - cMutexLock ml(&m_Lock); - m_Current = current; -} - -cPlaylistItem *cPlaylist::Next(void) -{ - cMutexLock ml(&m_Lock); - if(Current()) - return m_Current = (cList<cPlaylistItem>::Next(Current()) ?: First()); - return NULL; -} - -cPlaylistItem *cPlaylist::Prev(void) -{ - cMutexLock ml(&m_Lock); - if(Current()) - return m_Current = (cList<cPlaylistItem>::Prev(Current()) ?: Last()); - return NULL; -} - -bool cPlaylist::StoreCache(void) -{ - if(!xc.cache_implicit_playlists || - m_Origin != eImplicit || - !*m_Folder) - return false; - - cString Name = cString::sprintf("%s%s", *m_Folder, PLAYLIST_CACHE); - int len = strlen(m_Folder), entries = 0; - FILE *f = NULL; - - for(cPlaylistItem *i = First(); i; i=Next(i)) { - // store only items in "current" root folder - if(!strncmp(i->Filename, m_Folder, len)) { - if(/**i->Title ||*/ *i->Artist || *i->Album) { - cString Filename = ((*i->Filename) + len); // relative - if(entries < 1) { - f = fopen(Name, "w"); - if(!f) { - LOGERR("creation of metadata cache %s%s failed", - *m_Folder, PLAYLIST_CACHE); - return false; - } - fprintf(f, "[playlist]\r\n"); - } - entries++; - fprintf(f, "File%d=%s\r\n", entries, *Filename); - if(*i->Title && (*i->Title)[0]) - fprintf(f, "Title%d=%s\r\n", entries, *i->Title); - if(*i->Tracknumber && (*i->Tracknumber)[0]) - fprintf(f, "Tracknumber%d=%s\r\n", entries, *i->Tracknumber); - if(*i->Artist && (*i->Artist)[0]) - fprintf(f, "Artist%d=%s\r\n", entries, *i->Artist); - if(*i->Album && (*i->Album)[0]) - fprintf(f, "Album%d=%s\r\n", entries, *i->Album); - } - } - } - - if(entries > 0) { - fprintf(f, "NumberOfEntries=%d\r\nVersion=2\r\n", entries); - fclose(f); - return true; - } - - return false; -} - -static const char *strchrnext(const char *s, char c) -{ - return (s = strchr(s, c)) ? ((*(s+1))?(s+1):NULL) : NULL; -} - -bool cPlaylist::ReadCache(void) -{ - if(xc.cache_implicit_playlists && m_Origin == eImplicit && *m_Folder) { - - cString Name = cString::sprintf("%s%s", *m_Folder, PLAYLIST_CACHE); - FILE *f = fopen(Name, "r"); - if(f) { - int len = strlen(m_Folder); - cPlaylistItem *it = NULL; - cReadLine r; - char *pt; - while(NULL != (pt = r.Read(f))) { - if(!strncmp(pt, "File", 4)) { - it = NULL; - const char *Filename = strchrnext(pt+4, '='); - if(Filename && *Filename) { - for(cPlaylistItem *i = First(); i; i=Next(i)) { - if(!strncmp(i->Filename, m_Folder, len)) { - if(!strcmp(*i->Filename + len, Filename)) { - it = i; - break; - } - } - } - } - } else if(it && !strncmp(pt, "Title", 5)) { - it->Title = strchrnext(pt, '='); - } else if(it && !strncmp(pt, "Tracknumber", 11)) { - it->Tracknumber = strchrnext(pt, '='); - } else if(it && !strncmp(pt, "Artist", 6)) { - it->Artist = strchrnext(pt, '='); - } else if(it && !strncmp(pt, "Album", 5)) { - it->Album = strchrnext(pt, '='); - } else { - /*it = NULL;*/ - } - } - fclose(f); - return true; - } - } - - return false; -} - -#if 0 -static FILE *open_http(const char *PlaylistFile) -{ - char file[1024] = "", host[128] = "", pt; - int fd, port = 80; - - strn0cpy(host, PlaylistFile+strlen("http://"), sizeof(host)-1); - pt = strchr(host, '/'); - if(pt) { - strn0cpy(file, pt, sizeof(file)-1); - *pt = 0; - } - pt = strchr(host, ':'); - if(pt) { - *pt++ = 0; - port = atoi(pt); - } - - fd = tcp_connect(host, port); - if(fd < 0) { - LOGERR("TCP connect failed"); - return NULL; - } - - int len = asprintf(&pt, - "GET %s HTTP/1.1" "\r\n" - "Host: %s" "\r\n" - "\r\n", - file, host); - if(len != write(fd, pt, len)) { - LOGERR("HTTP request write failed"); - free(pt); - close(fd); - return NULL; - } - free(pt); - - int state = 0; - FILE *f = fdopen(fd, "r"); - cReadLine r; - while(state >= 0 && NULL != (pt = r.Read(f))) { - switch(state) { - case 0: if(!strncmp(pt, "HTTP/1", 6) || !strstr(pt, " 200 ")) { - LOGERR("HTTP error: %s", pt); - fclose(f); - return NULL; - } - state = 1; - break; - case 1: if(strcmp(pt, "\r\n")) - break; - return f; - default: break; - } - } - - fclose(f); - return NULL; -} -#endif - -int cPlaylist::ScanFolder(const char *FolderName, - bool Recursive, - bool (config_t::*Filter)(const char *)) -{ - cMutexLock ml(&m_Lock); - static int depth = 0; - - DIR *d = opendir(FolderName); - - if (d) { - LOGDBG("ScanFolder(%s)", FolderName); - struct dirent *e; - int n = 0, warn = -1; - while ((e = readdir(d)) != NULL) { - cString Buffer = cString::sprintf("%s%s", FolderName, e->d_name); - struct stat st; - if (stat(Buffer, &st) == 0) { - if(S_ISDIR(st.st_mode)) { - if (Recursive && !S_ISLNK(st.st_mode)) { /* don't want to loop ... */ - if(depth > 4) { - LOGMSG("ScanFolder: Too deep directory tree"); - } else if(e->d_name[0]=='.') { - } else { - if(n<MAX_PLAYLIST_FILES) { - depth++; /* limit depth */ - Buffer = cString::sprintf("%s/", *Buffer); - n += ScanFolder(Buffer, Recursive, Filter); - depth--; - } else { - if(!++warn) - LOGMSG("ScanFolder: Found over %d matching files, list truncated!", n); - break; - } - } - } - } else /* == if(!S_ISDIR(st.st_mode))*/ { - // check symlink destination - if (S_ISLNK(st.st_mode)) { - Buffer = ReadLink(Buffer); - if (!*Buffer) - continue; - if (stat(Buffer, &st) != 0) - continue; - } - if((xc.*Filter)(Buffer)) { - /* TODO: Should ScanDir add contents of playlist files ... ? */ - if(Filter == &config_t::IsPlaylistFile || !xc.IsPlaylistFile(Buffer)) { - n++; - if(n<MAX_PLAYLIST_FILES) { - Add(new cPlaylistItem(e->d_name, FolderName)); - //LOGDBG("ScanFolder: %s", e->d_name); - } else { - if(!++warn) - LOGMSG("ScanFolder: Found over %d matching files, list truncated!", n); - break; - } - } - } - } - } - } - LOGDBG("ScanFolder: Found %d matching files from %s", n, FolderName); - closedir(d); - - return n; - } - - LOGERR("ScanFolder: Error opening %s", FolderName); - return 0; -} - -void cPlaylist::StartScanner(void) -{ - cMutexLock ml(&m_Lock); - - if(m_Scanner) { - if(m_Scanner->Active()) - return; - delete m_Scanner; - m_Scanner = NULL; - } - - /* check if cache is already up-to-date */ - cString CacheName = cString::sprintf("%s%s", *m_Folder, PLAYLIST_CACHE); - struct stat stf, stc; - if(!stat(m_Folder, &stf)) { - if(!stat(CacheName, &stc)) { - //LOGDBG("ID3 Cache modified %d, folder modified %d, diff %d", - // (unsigned int)stc.st_mtime, (unsigned int)stf.st_mtime, - // (unsigned int)(stc.st_mtime - stf.st_mtime)); - if(stc.st_mtime >= stf.st_mtime) { - if(ReadCache()) { - LOGDBG("cPlaylist: using up-to-date ID3 cache"); - //LOGMSG(" Cache read OK."); - return; - } - LOGMSG("cPlaylist: ID3 cache read FAILED"); - } else { - LOGDBG("cPlaylist: ID3 cache not up-to-date, using old cache and scanning for changes"); - ReadCache(); - } - } - //else LOGERR("cPlaylist: stat(%s) failed"); - } - //else LOGERR("cPlaylist: stat(%s) failed"); - - if(xc.enable_id3_scanner) { - m_Scanner = new cID3Scanner(*this); - m_Scanner->Start(); - } -} - -int cPlaylist::ReadPlaylist(const char *file) -{ - static int depth = 0; /* limit recursion */ - cPipe p; - cPlaylistReader *parser = NULL; - FILE *f; - - if(strncmp(file, "http:", 5) && strncmp(file, "https:", 6)) { - f = fopen(file, "r"); - } else { - // fetch playlist from server using curl - LOGDBG("cPlaylist: fetching remote playlist from %s", file); - cString Cmd = cString::sprintf("curl %s", file); - if(!p.Open(Cmd, "r")) { - LOGERR("cPlaylist: CURL command (%s) failed", *Cmd); - return false; - } - // process as normal file - f = p; - } - - if(f) { - LOGDBG("cPlaylist: parsing %s", file); - char *pt = strrchr(file, '.'); - if(!strcasecmp(pt, ".pls")) - parser = new cPlsReader(*this); - else if(!strcasecmp(pt, ".asx")) - parser = new cAsxReader(*this); - else /*if(!strcasecmp(pt, ".m3u"))*/ - parser = new cM3uReader(*this); /* parses plain lists (.ram, ...) too ...*/ - - cString Base(file); - if(NULL != (pt=strrchr(Base,'/'))) - pt[1]=0; - - int n = 0; - cReadLine r; - while(NULL != (pt = r.Read(f)) && n < MAX_PLAYLIST_FILES) { - if(NULL != (pt = parser->Parse(pt))) { - - if(depth && n==0) { - // TODO - // - add "separator" item - // Add(new cPlaylistItem(NULL, Base, "---"); - } - - if(xc.IsPlaylistFile(pt)) { - parser->ResetCache(); - LOGDBG("cPlaylist: found playlist inside playlist"); - if(depth > 4) - LOGMSG("cPlaylist: recursion too deep, skipped %s", pt); - else { - depth++; - if(*pt == '/' || - (strstr(pt,"://")+1 == strchr(pt,'/') && - strchr(pt,'/') - pt < 8)) - n += ReadPlaylist(pt); - else - n += ReadPlaylist(cString::sprintf("%s%s", *Base, pt)); - depth--; - } - - } else { - if(*pt == '/' || - (strstr(pt,"://")+1 == strchr(pt,'/') && - strchr(pt,'/') - pt < 8)) { - // absolute path - Add(new cPlaylistItem(pt)); - if(parser->Title()) - Last()->Title = parser->Title(); - } else { - // relative path - Add(new cPlaylistItem(pt, Base, parser->Title())); - } - Last()->Position = parser->Position(); - parser->ResetCache(); - //LOGDBG("read_playlist: %s", pt); - n++; - } - } - } - - if(! (FILE*) p) - fclose(f); - - if(n >= MAX_PLAYLIST_FILES) - LOGMSG("cPlaylist: Found over %d matching files, list truncated!", n); - LOGDBG("cPlaylist: Found %d matching files", n); - return n; - } - - LOGERR("cPlaylist: Error opening %s", file); - return 0; -} - -static cString LastDir(cString& path) -{ - cString tmp = strdup(path); - char *pt = strrchr(tmp, '/'); - if(pt && pt > *tmp) { - *pt = 0; - pt = strrchr(tmp, '/'); - if(pt) - return cString(pt+1); - } - return cString(NULL); -} - -bool cPlaylist::Read(const char *PlaylistFile, bool Recursive) -{ - cMutexLock ml(&m_Lock); - bool Result = true; - - // extract playlist root folder - if(!*m_Folder) { - m_Folder = PlaylistFile; - if(strrchr(m_Folder, '/')) - *(strrchr(m_Folder, '/') + 1) = 0; - } - - if(xc.IsPlaylistFile(PlaylistFile)) { - // Read playlist file - Result = ReadPlaylist(PlaylistFile); - m_Origin = ePlaylist; - - cString dir = LastDir(m_Folder); - char *name = strrchr(PlaylistFile, '/'); - name = name ? name+1 : NULL; - if(*dir && name) - m_Name = cString::sprintf("%s - %s", *dir, name); - else - m_Name = name ?: ""; - - if(strrchr(m_Name, '.')) - *(strrchr(m_Name, '.')) = 0; - - } else if(PlaylistFile[strlen(PlaylistFile)-1] == '/') { - // Scan folder - Result = ScanFolder(PlaylistFile, Recursive) > 0; - m_Origin = eImplicit; - Sort(); - - if(!*m_Name) { - m_Name = PlaylistFile; - *(strrchr(m_Name, '/')) = 0; - if(strrchr(m_Name, '/')) { - cString dir = LastDir(m_Name); - if(*dir) - m_Name = cString::sprintf("%s - %s", *dir, strrchr(m_Name, '/')+1); - else - m_Name = strrchr(m_Name, '/')+1; - } - } - - } else { - // Single file - Add(new cPlaylistItem(PlaylistFile)); - m_Origin = eImplicit; - - if(!*m_Name) { - m_Name = LastDir(m_Folder); - if(!*m_Name) - m_Name = ""; - } - } - - if(Count() < 1) { - LOGMSG("Empty playlist %s !", PlaylistFile); - Add(new cPlaylistItem(PlaylistFile)); - } - - m_Version++; - return Result; -} - -cString cPlaylist::EscapeMrl(const char *mrl) -{ - static const uint8_t hex[16] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; - const uint8_t *fn = (const uint8_t*)mrl; - int size = strlen(mrl) + 16; - uint8_t *buf = (uint8_t*)malloc(size); - int i = 0, found = 0; - LOGDBG("cPlaylist::EscapeMrl('%s')", fn); - - // Wait for first '/' (do not escape mrl start dvd:/, http://a@b/, ...) - if (*fn == '/') - found = 3; - - while (*fn) { - if(size-7 < i) - buf = (uint8_t *)realloc(buf, (size=size+16)); - switch (*fn) { - case 1 ... ' ': - case 127 ... 255: - case '#': - case '%': - case ':': - case ';': - case '\'': - case '\"': - case '(': - case ')': - if (found > 2) { - buf[i++] = '%'; - buf[i++] = hex[(*fn & 0xf0)>>4]; - buf[i++] = hex[(*fn & 0x0f)]; - break; - } - default: - // file:/... -> only one '/' before escaping - // http://.../ --> three '/' before escaping - if(!found && (fn[0] == ':' && fn[1] == '/')) { - if(fn[2] == '/') { - // ex. http://user:pass@host/... --> wait for third '/' - buf[i++] = *fn++; - buf[i++] = *fn++; - found += 2; - } else { - // ex. file:/local_file - buf[i++] = *fn++; - found += 3; - } - } else if(*fn == '/') { - found++; - } - buf[i++] = *fn; - break; - } - fn++; - } - - buf[i] = 0; - LOGDBG(" --> '%s'", buf); - return cString((const char*)buf, true); -} - -cString cPlaylist::GetEntry(cPlaylistItem *i, bool isPlaylist, bool isCurrent) -{ - - cString Entry = ""; - if ((*i->Artist && xc.playlist_artist) || (*i->Album && xc.playlist_album)) { - Entry = cString::sprintf("%s%s%s%s%s%s(%s%s%s)", - isPlaylist ? (isCurrent ? "*" : " ") : "", - isPlaylist ? "\t" : " ", - xc.playlist_tracknumber ? (*i->Tracknumber ?: "") : "", - xc.playlist_tracknumber ? (*i->Tracknumber ? " - " : "") : "", - *i->Title, - isPlaylist ? "\t" : " ", - xc.playlist_artist ? (*i->Artist ?: "") : "", - xc.playlist_artist && xc.playlist_album ? (*i->Artist && *i->Album ? ":" : "") : "", - xc.playlist_album ? (*i->Album ?: "") : ""); - } else { - Entry = cString::sprintf("%s%s%s%s%s", - isPlaylist ? (isCurrent ? "*" : " ") : "", - isPlaylist ? "\t" : " ", - xc.playlist_tracknumber ? (*i->Tracknumber ?: "") : "", - xc.playlist_tracknumber ? (*i->Tracknumber ? " - " : "") : "", - *i->Title); - } - return Entry; -} diff --git a/tools/playlist.h b/tools/playlist.h deleted file mode 100644 index 50c3d97a..00000000 --- a/tools/playlist.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * playlist.h: Media player playlist - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: playlist.h,v 1.8 2008-02-19 04:24:34 phintuka Exp $ - * - */ - -#ifndef __XINELIBOUTPUT_PLAYLIST_H -#define __XINELIBOUTPUT_PLAYLIST_H - -#include <vdr/tools.h> // cString, cListObject, cList<> -#include <vdr/thread.h> // cMutex - - -// -// cPlaylistItem -// - -class cPlaylistItem : public cListObject -{ - private: - cPlaylistItem(); - - virtual int Compare(const cListObject &ListObject) const; - - public: - cPlaylistItem(const char *filename); /* file name with full path */ - cPlaylistItem(const char *filename, /* file name without path */ - const char *path, - const char *title = NULL, - int position = -1); - - cString Filename; /* file name and full path */ - - // Metainfo (ID3 etc.) - cString Title; - cString Tracknumber; - cString Artist; - cString Album; - - // position in playlist (if given in playlist file) - int Position; -}; - - -// -// cPlaylistChangeNotify interface -// - -class cPlaylistChangeNotify -{ - public: - virtual void PlaylistChanged(const cPlaylistItem *Item) = 0; - - virtual ~cPlaylistChangeNotify() {} -}; - - -// -// cPlaylist -// - - -class cID3Scanner; - -class cPlaylist : protected cList<cPlaylistItem> -{ - private: - - cMutex m_Lock; - cString m_Name; // playlist (or folder) name - cString m_Folder; // path to "root" of playlist - cPlaylistItem *m_Current; // now playing - unsigned int m_Version; - - enum { ePlaylist, eImplicit } m_Origin; - - cPlaylistChangeNotify *m_Menu; - cID3Scanner *m_Scanner; - - protected: - - bool StoreCache(void); - bool ReadCache(void); - - int ReadPlaylist(const char *PlaylistFile); - int ScanFolder(const char *FolderName, - bool Recursive = false, - bool (config_t::*Filter)(const char *) = &config_t::IsAudioFile); - - friend class cID3Scanner; - friend class cPlaylistReader; - void PlaylistChanged(const cPlaylistItem *Item); - cPlaylistItem *Last(void) { return cList<cPlaylistItem>::Last(); } - - public: - - cPlaylist(); - virtual ~cPlaylist(); - - const cString& Name(void) const { return m_Name; } - - // listen for changes in playlist - void Listen(cPlaylistChangeNotify *Menu = NULL); - - // read playlist from file or create playlist from directory tree - bool Read(const char *PlaylistFile, bool Recursive = false); - void StartScanner(void); - void Del(cPlaylistItem *it); - - void Sort(void); - int Count(void) const; - - // access/iterate playlist items - cPlaylistItem *First(void) { return Next(NULL); } - cPlaylistItem *Next(const cPlaylistItem *i); - - // get/set current (now playing) item - cPlaylistItem *Current(void); - void SetCurrent(cPlaylistItem *current); - cPlaylistItem *Next(void); - cPlaylistItem *Prev(void); - - static cString EscapeMrl(const char *name); - static cString GetEntry(cPlaylistItem *i, bool isPlaylist = false, bool isCurrent = false); -}; - - -#endif // __XINELIBOUTPUT_PLAYLIST_H diff --git a/tools/rtcp.h b/tools/rtcp.h deleted file mode 100644 index 608f2daf..00000000 --- a/tools/rtcp.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * rtcp.h: RFC1889: RTCP - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: rtcp.h,v 1.3 2007-03-29 14:22:31 phintuka Exp $ - * - */ - -#ifndef XINELIBOUTPUT_RTCP_H_ -#define XINELIBOUTPUT_RTCP_H_ - -#ifdef __APPLE__ -# include <machine/endian.h> -#else -# include <endian.h> -#endif - - -#ifndef PACKED -# define PACKED __attribute__((packed)) -#endif - -#if __BYTE_ORDER == __BIG_ENDIAN -#elif __BYTE_ORDER == __LITTLE_ENDIAN -#else -# error __BYTE_ORDER not defined -#endif - -#if defined __cplusplus -extern "C" { -#endif - - -/* RTCP packet types */ -typedef enum { - RTCP_SR = 200, - RTCP_RR = 201, - RTCP_SDES = 202, - RTCP_BYE = 203, - RTCP_APP = 204 -} rtcp_type_t; - -/* RTCP SDES types */ -typedef enum { - RTCP_SDES_END = 0, - RTCP_SDES_CNAME = 1, - - RTCP_SDES_NAME = 2, - RTCP_SDES_EMAIL = 3, - RTCP_SDES_PHONE = 4, - RTCP_SDES_LOC = 5, - RTCP_SDES_TOOL = 6, - RTCP_SDES_NOTE = 7, - RTCP_SDES_PRIV = 8 -} rtcp_sdes_type_t; - -/* RTCP common header word */ -typedef struct { - union { - uint8_t raw[4]; - struct { -#if __BYTE_ORDER == __BIG_ENDIAN - unsigned int version:2; /* protocol version */ - unsigned int padding:1; /* padding flag */ - unsigned int count:5; /* varies by packet type */ -#else - unsigned int count:5; /* varies by packet type */ - unsigned int padding:1; /* padding flag */ - unsigned int version:2; /* protocol version */ -#endif - unsigned int ptype:8; /* RTCP packet type */ - - uint16_t length; /* pkt len in words, w/o this word */ - } PACKED; - } PACKED; -} PACKED rtcp_common_t; - -/* RTCP RR (Reception report) */ -typedef struct { - uint32_t ssrc; /* data source being reported */ - unsigned int fraction:8; /* fraction lost since last SR/RR */ - int lost:24; /* cumul. no. pkts lost (signed!) */ - uint32_t last_seq; /* extended last seq. no. received */ - uint32_t jitter; /* interarrival jitter */ - uint32_t lsr; /* last SR packet from this source */ - uint32_t dlsr; /* delay since last SR packet */ -} PACKED rtcp_rr_t; - -/* RTCP SR (Sender report) */ -typedef struct { - uint32_t ssrc; - uint32_t ntp_sec; /* NTP timestamp, most significant word / seconds */ - uint32_t ntp_frac; - uint32_t rtp_ts; - uint32_t psent; /* packets sent */ - uint32_t osent; /* octets sent */ - rtcp_rr_t rr[0]; /* variable-length list */ -} PACKED rtcp_sr_t; - -/* RTCP SDES item */ -typedef struct { - uint8_t type; /* type of item (rtcp_sdes_type_t) */ - uint8_t length; /* length of item (in octets) */ - char data[0]; /* text, not null-terminated */ -} PACKED rtcp_sdes_item_t; - -/* RTCP packet */ -typedef struct { - rtcp_common_t hdr; - union { - rtcp_sr_t sr; - struct { - uint32_t ssrc; - rtcp_rr_t rr[0]; - } PACKED rr; - struct { - uint32_t ssrc; /* first SSRC/CSRC */ - rtcp_sdes_item_t item[0]; /* list of SDES items */ - } PACKED sdes; - struct { - uint32_t src[0]; /* list of sources */ - /* can't express trailing text for reason */ - } PACKED bye; - } PACKED; -} PACKED rtcp_packet_t; - - -#if defined __cplusplus -}; -#endif - -#endif /* XINELIBOUTPUT_RTCP_H_ */ diff --git a/tools/rtp.h b/tools/rtp.h deleted file mode 100644 index fa2ccf63..00000000 --- a/tools/rtp.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * rtp.h: RFC1889: RTP - A Transport Protocol for Real-Time Applications - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: rtp.h,v 1.3 2007-03-29 14:22:31 phintuka Exp $ - * - */ - -#ifndef XINELIBOUTPUT_RTP_H_ -#define XINELIBOUTPUT_RTP_H_ - -#ifdef __APPLE__ -# include <machine/endian.h> -#else -# include <endian.h> -#endif - - -#ifndef PACKED -# define PACKED __attribute__((packed)) -#endif - -#if __BYTE_ORDER == __BIG_ENDIAN -#elif __BYTE_ORDER == __LITTLE_ENDIAN -#else -# error __BYTE_ORDER not defined -#endif - -#if defined __cplusplus -extern "C" { -#endif - - -/* Generic RTP header extension */ -typedef struct stream_rtp_header_ext { - - union { - uint8_t raw[4]; - uint32_t rawd; - - struct { - uint16_t type; - uint16_t size; /* Size of ext_data field in DWORDS */ - } PACKED; - } PACKED; - - uint8_t ext_data[0]; - -} PACKED stream_rtp_header_ext_t; - - -/* Common RTP data header */ -typedef struct stream_rtp_header { - - union { - uint8_t raw[12]; - - struct { -#if __BYTE_ORDER == __BIG_ENDIAN - unsigned int version:2; /* protocol version */ - unsigned int padding:1; /* padding flag */ - unsigned int ext:1; /* header extension flag */ - unsigned int cc:4; /* CSRC count */ - - unsigned int marker:1; /* marker bit */ - unsigned int paytype:7; /* payload type */ -#else - unsigned int cc:4; /* CSRC count */ - unsigned int ext:1; /* header extension flag */ - unsigned int padding:1; /* padding flag */ - unsigned int version:2; /* protocol version */ - - unsigned int paytype:7; /* payload type */ - unsigned int marker:1; /* marker bit */ -#endif - uint16_t seq; /* sequence number */ - uint32_t ts; /* timestamp */ - uint32_t ssrc; /* synchronization source */ - - /*uint32_t csrc[0];*/ /* optional CSRC list */ - } PACKED; - } PACKED; - - - union { - stream_rtp_header_ext_t hdr_ext[0]; - uint8_t payload[0]; - } PACKED; - - -} PACKED stream_rtp_header_t; - -#if defined __cplusplus -}; -#endif - -#endif /* XINELIBOUTPUT_RTP_H_ */ - diff --git a/tools/sap.h b/tools/sap.h deleted file mode 100644 index 6b341efc..00000000 --- a/tools/sap.h +++ /dev/null @@ -1,207 +0,0 @@ -/* - * sap.h: RFC2974 Session Announcement Protocol (SAP) version 2 - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: sap.h,v 1.8 2007-03-29 14:22:30 phintuka Exp $ - * - */ - -#ifndef XINELIBOUTPUT_SAP_H_ -#define XINELIBOUTPUT_SAP_H_ - -#include <arpa/inet.h> -#ifdef __APPLE__ -# include <machine/endian.h> -#else -# include <endian.h> -#endif - - -#ifndef PACKED -# define PACKED __attribute__((packed)) -#endif - -/*#define LOG_SAP*/ - -/* SAP IPv4 multicast addresses */ -#define SAP_IP_ADDRESS_GLOBAL "224.2.127.254" /* SAPv1 IP4 global scope multicast address */ -#define SAP_IP_ADDRESS_ORG "239.195.255.255" /* organization-local */ -#define SAP_IP_ADDRESS_LOCAL "239.255.255.255" /* local */ -#define SAP_IP_ADDRESS_LINK "224.0.0.255" /* link-local */ - -#define SAP_IP_TTL 255 -#define SAP_UDP_PORT 9875 - - -typedef struct { - - /* RFC2974: SAP (Session Announcement Protocol) version 2 PDU */ - - union { - uint8_t raw0; - struct { -#if __BYTE_ORDER == __BIG_ENDIAN - uint8_t version : 3; - uint8_t addr_type : 1; - uint8_t reserved : 1; - uint8_t msg_type : 1; - uint8_t encrypted : 1; - uint8_t compressed : 1; -#else - uint8_t compressed : 1; - uint8_t encrypted : 1; - uint8_t msg_type : 1; - uint8_t reserved : 1; - uint8_t addr_type : 1; - uint8_t version : 3; -#endif - } PACKED; - } PACKED; - - uint8_t auth_len; - uint16_t msgid_hash; - - union { - uint8_t u8[4]; - uint32_t u32; - } PACKED ip4_source; - - char payload[0]; - -} PACKED sap_pdu_t; - - -static inline sap_pdu_t *sap_create_pdu(uint32_t src_ip, - uint16_t msgid, - int announce, - const char *payload_type, - const char *payload) -{ - sap_pdu_t *pdu; - int length = sizeof(sap_pdu_t) + strlen(payload) + 3; - - if(payload_type) - length += strlen(payload_type); - - if(! (pdu = (sap_pdu_t*)malloc(length))) - return NULL; - - memset(pdu, 0, sizeof(sap_pdu_t)); - pdu->version = 1; /* SAP v1 / v2 */ - pdu->msg_type = announce ? 0 : 1; - pdu->msgid_hash = msgid; - pdu->ip4_source.u32 = src_ip; - - if(payload_type) { - char *tmp = &pdu->payload[0]; - strcpy(tmp, payload_type); - tmp += strlen(tmp) + 1; - strcpy(tmp, payload); - } else { - /* payload type defaults to application/sdp */ - sprintf(&pdu->payload[0], "%s%c%c", payload, 0, 0); - } - - return pdu; -} - -static inline int sap_compress_pdu(sap_pdu_t *pdu) -{ -#ifdef HAVE_ZLIB_H - - /* zlib compression */ - - Compress(); - - /*pdu->compressed = 1;*/ - -#endif - - /* not implemented */ - - pdu->compressed = 0; - return -1; -} - -static inline int sap_send_pdu(int *pfd, sap_pdu_t *pdu, uint32_t dst_ip) -{ - int len = 0, r; - int iReuse = 1, iLoop = 1, iTtl = SAP_IP_TTL; - int fd; - - if(!pfd || *pfd < 0) { - fd = socket(AF_INET, SOCK_DGRAM, 0); - - if(fd < 0) { - LOGERR("socket() failed (UDP/SAP multicast)"); - return -1; - } - - setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &iReuse, sizeof(int)); - setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, &iTtl, sizeof(int)); - setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &iLoop, sizeof(int)); - - // Connect to multicast address - struct sockaddr_in sin; - sin.sin_family = AF_INET; - sin.sin_port = htons(SAP_UDP_PORT); - sin.sin_addr.s_addr = dst_ip ? dst_ip : inet_addr(SAP_IP_ADDRESS_GLOBAL); - - if(connect(fd, (struct sockaddr *)&sin, sizeof(sin))==-1) - LOGERR("UDP/SAP multicast connect() failed."); - - // Set to non-blocking mode - fcntl (fd, F_SETFL, fcntl (fd, F_GETFL) | O_NONBLOCK); - - if(pfd) - *pfd = fd; - - } else { - fd = *pfd; - } - - // size of PDU - len += strlen(&pdu->payload[0]); - if(!strstr(&pdu->payload[0], "\r\n")) { - /* assume mime content type is present */ - len += 1; - len += strlen(&pdu->payload[len]); - len += sizeof(sap_pdu_t); - } - - // network order - pdu->msgid_hash = htons(pdu->msgid_hash); - - // send - r = send(fd, pdu, len, 0); - if(r < 0) - LOGERR("UDP/SAP multicast send() failed."); - - if(!pfd) - close(fd); - -#ifdef LOG_SAP - /* log PDU */ - for(int i=0; i<len;) { - char x[4096]="", a[4096]=""; - for(int j=0; j<16 && i<len; i++, j++) { - char t[8], ch = ((char*)pdu)[i]; - sprintf(t, "%02X ", ((unsigned int)ch)&0xff); - strcat(x, t); - sprintf(t, "%c", (ch>=32 && ch<127) ? ch : '.'); - strcat(a, t); - } - LOGMSG("SAP: 0x%02x: %-50s%-18s", i/16-1, x, a); - } -#endif - - // back to host order - pdu->msgid_hash = ntohs(pdu->msgid_hash); - - return r == len ? len : -1; -} - - -#endif /* XINELIBOUTPUT_SAP_H_ */ diff --git a/tools/sdp.h b/tools/sdp.h deleted file mode 100644 index 47a3a409..00000000 --- a/tools/sdp.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * sdp.h: RFC2974 Session Description Protocol (SDP) - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: sdp.h,v 1.2 2006-12-14 12:52:49 phintuka Exp $ - * - */ - -#ifndef XINELIBOUTPUT_SDP_H_ -#define XINELIBOUTPUT_SDP_H_ - - -#define SDP_MIME_TYPE "application/sdp" - - -static char *vdr_sdp_description(const char *vdr_ip, - int vdr_svdrp_port, - int vdr_xineliboutput_port, - const char *rtp_ip, - uint32_t rtp_ssrc, - int rtp_port, - int rtp_ttl) -{ - static uint8_t s_serial = 0; - static char *s_data = NULL; - static char s_hostname[257] = {0}; - - uint64_t serial = (time(NULL) << 2) + ((s_serial++) & 0x03); - - if(!s_hostname[0]) - gethostname(s_hostname, 256); - - free(s_data); - - asprintf(&s_data, - /*** session ***/ - /* version */ "v=0" - /* origin */ "\r\n" "o=%s %u %"PRIu64" IN IP4 %s" - /* name */ "\r\n" "s=%s@%s (multicast %s:%d)" - /* opt:info */ /*"\r\n" "i=vdr-xineliboutput primary device output"*/ - /* time */ "\r\n" "t=0 0" - - /*** data stream(s) ***/ - /* connection */ "\r\n" "c=IN IP4 %s/%d" - /* */ "\r\n" "a=recvonly" - /* */ "\r\n" "a=type:broadcast" - /* */ "\r\n" "a=x-plgroup:vdr" - /* media */ "\r\n" "m=video %d RTP/AVP 96" - /* */ "\r\n" "a=rtpmap:96 MP2P/90000" - /* media */ /*"\r\n" "m=video %d udp MP2P"*/ - /* */ /*"\r\n" "a=mux:ps"*/ - /* */ /*"\r\n" "a=packetformat:RAW"*/ -#if 0 - /*** rtsp control port ***/ - /* connection */ "\r\n" "c=IN IP4 %s" - /* media */ "\r\n" "m=control %d tcp/http rtsp" -#endif - /*** xineliboutput control port ***/ - /* connection */ "\r\n" "c=IN IP4 %s" - /* media */ "\r\n" "m=control %d tcp x-vdr-xineliboutput" - - /*** SVDRP control port ***/ - /* connection */ "\r\n" "c=IN IP4 %s" - /* media */ "\r\n" "m=control %d tcp x-svdrp" - - /* origin */ - , "vdr", rtp_ssrc, serial, vdr_ip - - /* name */ - , "vdr", s_hostname, rtp_ip, rtp_port - - /* video/mp2p udp/rtp */ - , rtp_ip, rtp_ttl - , rtp_port -#if 0 - /* tcp/http control/rtsp */ - , vdr_ip - , vdr_xineliboutput_port -#endif - /* tcp control/x-vdr-xineliboutput */ - , vdr_ip - , vdr_xineliboutput_port - - /* tcp control/x-svdrp */ - , vdr_ip - , vdr_svdrp_port - ); - - return s_data; -} - - -#endif /* XINELIBOUTPUT_SDP_H_ */ diff --git a/tools/time_pts.c b/tools/time_pts.c deleted file mode 100644 index 81ee7c73..00000000 --- a/tools/time_pts.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - * time_pts.c: Adjustable clock in PTS units - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: time_pts.c,v 1.4 2008-04-28 20:48:05 phintuka Exp $ - * - */ - -#define __STDC_FORMAT_MACROS -#define __STDC_CONSTANT_MACROS -#include <inttypes.h> -#include <time.h> - -#include <vdr/config.h> - -#include "../logdefs.h" // logging - -#include "time_pts.h" - - -#define MAX_SCR ((int64_t)0x1ffffffffLL) - -#if _POSIX_TIMERS > 0 && defined(_POSIX_MONOTONIC_CLOCK) -#else -# warning Posix monotonic clock not available -#endif - -int cTimePts::m_Monotonic = -1; - -void cTimePts::Init(void) -{ -#if _POSIX_TIMERS > 0 && defined(_POSIX_MONOTONIC_CLOCK) - if(m_Monotonic >= 0) - return; - - m_Monotonic = 0; - - struct timespec resolution; - if(clock_getres(CLOCK_MONOTONIC, &resolution)) { - LOGERR("cTimePts: clock_getres(CLOCK_MONOTONIC) failed"); - return; - } - - LOGDBG("cTimePts: clock_gettime(CLOCK_MONOTONIC): clock resolution %d us", - ((int)resolution.tv_nsec) / 1000); - - if( resolution.tv_sec == 0 && resolution.tv_nsec <= 1000000 ) { - struct timespec tp; - if(clock_gettime(CLOCK_MONOTONIC, &tp)) { - LOGERR("cTimePts: clock_gettime(CLOCK_MONOTONIC) failed"); - } else { - LOGDBG("cTimePts: using monotonic clock"); - m_Monotonic = 1; - } - } -#endif -} - -cTimePts::cTimePts(void) -{ - m_Paused = false; - m_ScrSpeed = 90000; - m_Multiplier = 90000; - - Init(); - - Set(); -} - -int64_t cTimePts::Now(void) const -{ - if(m_Paused) - return begin; - - struct timeval t; - -#if _POSIX_TIMERS > 0 && defined(_POSIX_MONOTONIC_CLOCK) - if(m_Monotonic) { - struct timespec tp; - - if(clock_gettime(CLOCK_MONOTONIC, &tp)) { - LOGERR("cTimePts: clock_gettime(CLOCK_MONOTONIC) failed"); - return -1; - } - - t.tv_sec = tp.tv_sec; - t.tv_usec = tp.tv_nsec/1000; - - } else if (gettimeofday(&t, NULL)) { - LOGERR("cTimePts: gettimeofday() failed"); - return -1; - } -#else - if (gettimeofday(&t, NULL)) { - LOGERR("cTimePts: gettimeofday() failed"); - return -1; - } -#endif - - t.tv_sec -= tbegin.tv_sec; - if(t.tv_usec < tbegin.tv_usec) { - t.tv_sec--; - t.tv_usec += 1000000; - } - t.tv_usec -= tbegin.tv_usec; - - int64_t pts = 0; - pts += (int64_t)t.tv_sec * (int64_t)m_ScrSpeed; - pts += (int64_t)t.tv_usec * (int64_t)m_ScrSpeed / INT64_C(1000000); - - if(m_Multiplier != 90000) - pts = pts * m_Multiplier / INT64_C(90000); - - return ( pts + begin ) & MAX_SCR; -} - -void cTimePts::Set(int64_t Pts) -{ - begin = Pts; - -#if _POSIX_TIMERS > 0 && defined(_POSIX_MONOTONIC_CLOCK) - if(m_Monotonic) { - struct timespec tp; - - if(!clock_gettime(CLOCK_MONOTONIC, &tp)) { - tbegin.tv_sec = tp.tv_sec; - tbegin.tv_usec = tp.tv_nsec/1000; - return; - } - - LOGERR("cTimePts: clock_gettime(CLOCL_MONOTONIC) failed"); - m_Monotonic = 0; - } -#endif - - gettimeofday(&tbegin, NULL); -} - -void cTimePts::Pause(void) -{ - Set(Now()); - m_Paused = true; -} - -void cTimePts::Resume(void) -{ - if(m_Paused) { - Set(begin); - m_Paused = false; - } -} - -void cTimePts::TrickSpeed(const int Multiplier) -{ - Set(Now()); - - if(Multiplier < 0) - m_Multiplier = 90000 * (-Multiplier); - else if(Multiplier > 0) - m_Multiplier = 90000 / Multiplier; - else - LOGERR("cTimePts::SetSpeed: Multiplier=%d", Multiplier); -} - -void cTimePts::SetScrSpeed(const int ScrSpeed) -{ - Set(Now()); - - m_ScrSpeed = ScrSpeed; -} diff --git a/tools/time_pts.h b/tools/time_pts.h deleted file mode 100644 index fafc7199..00000000 --- a/tools/time_pts.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * time_pts.h: Adjustable clock in PTS units - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: time_pts.h,v 1.4 2008-04-28 20:48:05 phintuka Exp $ - * - */ - -#ifndef __TIME_PTS_H -#define __TIME_PTS_H - -#include <stdint.h> // int64_t -#include <sys/time.h> // struct timeval - - -class cTimePts -{ - private: - int64_t begin; /* Start time (PTS) */ - struct timeval tbegin; /* Start time (real time) */ - bool m_Paused; - int m_Multiplier; - int m_ScrSpeed; - - static int m_Monotonic; - static void Init(void); - - public: - cTimePts(void); - - int64_t Now(void) const; - void Set(int64_t Pts = 0LL); - - void Pause(void); - void Resume(void); - void TrickSpeed(const int Multiplier); - - void SetScrSpeed(const int ScrSpeed = 90000); -}; - -#endif // __TIME_PTS_H diff --git a/tools/timer.c b/tools/timer.c deleted file mode 100644 index f24e925a..00000000 --- a/tools/timer.c +++ /dev/null @@ -1,288 +0,0 @@ -/* - * timer.c: Threaded timer class - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: timer.c,v 1.2 2007-10-15 00:15:07 phintuka Exp $ - * - */ - -#include <sys/time.h> - -#include <vdr/config.h> -#include <vdr/tools.h> -#include <vdr/thread.h> - -#include "timer.h" - -//#define XINELIBOUTPUT_DEBUG -//#define XINELIBOUTPUT_DEBUG_STDOUT -#ifdef XINELIBOUTPUT_DEBUG -# include "logdefs.h" -#else -# define TRACE(x) -# define TRACEF(x) -#endif - -// ---------------------------- cTimerThreadEvent ---------------------------- - -class cTimerThreadEvent : public cListObject { - public: - cTimerThreadEvent(cTimerCallback *Handler, unsigned int TimeoutMs, - bool DeleteOnCancel = false) : - m_Handler(Handler), - m_DeleteOnCancel(DeleteOnCancel), - m_TimeoutMs(TimeoutMs) - { - m_NextEventTime = cTimeMs::Now(); - UpdateEventTime(); - } - - ~cTimerThreadEvent() - { - if(m_DeleteOnCancel && m_Handler) - delete m_Handler; - } - - void UpdateEventTime() - { - m_NextEventTime += m_TimeoutMs; - } - - int TimeToNextEvent(void) - { - return m_NextEventTime - cTimeMs::Now(); - } - - virtual bool operator< (const cListObject &ListObject) - { - const cTimerThreadEvent *o = (cTimerThreadEvent *)&ListObject; - return m_NextEventTime<o->m_NextEventTime; - } - - virtual int Compare(const cListObject &ListObject) const - { - const cTimerThreadEvent *o = (cTimerThreadEvent *)&ListObject; - if(m_NextEventTime<o->m_NextEventTime) - return -1; - else if(m_NextEventTime>o->m_NextEventTime) - return 1; - return 0; - } - - cTimerCallback *m_Handler; - - protected: - bool m_DeleteOnCancel; - unsigned int m_TimeoutMs; - int64_t m_NextEventTime; -}; - -// ------------------------------- cTimerThread ------------------------------ - -class cTimerThread : public cThread { - private: - cTimerThread(cTimerThread&); // copy not allowed - - static cMutex m_InstanceLock; - static cTimerThread *m_Instance; // singleton - - cMutex m_Lock; - cCondVar m_Signal; - cList<cTimerThreadEvent> m_Events; - cTimerThreadEvent *m_RunningEvent; - bool m_Finished; - bool m_HandlerRunning; - - cTimerThread() : - m_RunningEvent(NULL), - m_Finished(false), - m_HandlerRunning(false) - { - } - - virtual ~cTimerThread() - { - m_Lock.Lock(); - cTimerThreadEvent *ev; - while(NULL != (ev = m_Events.First())) { - m_Events.Del(ev,true); - } - m_Lock.Unlock(); - m_Signal.Broadcast(); - Cancel(1); - } - - protected: - - virtual void Action() - { - TRACEF("cTimerThread::Action"); - m_Lock.Lock(); - while(m_Events.First()) { - m_Signal.TimedWait(m_Lock, - max(1, m_Events.First()->TimeToNextEvent())); - TRACE("cTimerThread::Action waked up"); - while(NULL != (m_RunningEvent = m_Events.First()) && - m_RunningEvent->TimeToNextEvent() <= 0) { - TRACE("cTimerThread::Action calling handler"); - m_HandlerRunning=true; -// m_Lock.Unlock(); -// - can't unlock or running timer handler may be deleted while -// executing (or thread may be killed by Delete) - bool result = m_RunningEvent->m_Handler->TimerEvent(); -// m_Lock.Lock(); - m_HandlerRunning=false; - if(!result) { - if(m_RunningEvent) { // check if event was cancelled in handler... - TRACE("cTimerThread::Action handler cancelled timer"); - m_Events.Del(m_RunningEvent, true); - } - } else { - if(m_RunningEvent) { - TRACE("cTimerThread::Action timer re-scheduled"); - m_RunningEvent->UpdateEventTime(); - m_Events.Sort(); - } - } - m_RunningEvent = NULL; - } - } - m_Finished = true; - m_Lock.Unlock(); - } - - void Add(cTimerThreadEvent *Event) - { - TRACEF("cTimerThread::Add"); - //m_Events.Del(Event, false); - Event->Unlink(); - Del(Event->m_Handler); - m_Events.Add(Event); - m_Events.Sort(); - } - - bool Del(cTimerCallback *Handler, void *TargetId=NULL, - bool inDestructor=false) - { - TRACEF("cTimerThread::Del"); - cTimerThreadEvent *ev = m_Events.First(); - while(ev) { - if(ev->m_Handler == Handler || - (TargetId && ev->m_Handler->TargetId() == TargetId) || - (Handler && ev->m_Handler->is(Handler,Handler->size()))) { - cTimerThreadEvent *nev = m_Events.Next(ev); - if(inDestructor) ev->m_Handler=NULL; - m_Events.Del(ev, true); - ev = nev; - } else - ev = m_Events.Next(ev); - } - if(m_RunningEvent && - (m_RunningEvent->m_Handler == Handler || - m_RunningEvent->m_Handler->TargetId() == TargetId)) - m_RunningEvent = NULL; - return !m_HandlerRunning && !m_RunningEvent && !m_Events.First(); - } - - public: - - static void AddEvent(cTimerCallback *Handler, unsigned int TimeoutMs, - bool DeleteOnCancel=false) - { - TRACEF("cTimerThread::AddEvent"); - m_InstanceLock.Lock(); - if(m_Instance && m_Instance->m_Finished) { - delete m_Instance; - m_Instance = NULL; - } - if(!m_Instance) { - m_Instance = new cTimerThread; - m_Instance->m_Lock.Lock(); - m_Instance->Start(); - } else { - m_Instance->m_Lock.Lock(); - m_Instance->m_Signal.Broadcast(); - } - m_Instance->Add(new cTimerThreadEvent(Handler, max(1U,TimeoutMs), - DeleteOnCancel)); - m_Instance->m_Lock.Unlock(); - m_InstanceLock.Unlock(); - } - - static void CancelEvent(cTimerCallback *Handler, void *TargetId = NULL, - bool inDestructor=false) - { - TRACEF("cTimerThread::CancelEvent"); - m_InstanceLock.Lock(); - if(m_Instance && !m_Instance->m_Finished) { - m_Instance->m_Lock.Lock(); - if(m_Instance->Del(Handler, TargetId, inDestructor) && !inDestructor) { - m_Instance->m_Lock.Unlock(); - delete m_Instance; - m_Instance = NULL; - } else - m_Instance->m_Lock.Unlock(); - } - m_InstanceLock.Unlock(); - } - -}; - -cMutex cTimerThread::m_InstanceLock; -cTimerThread *cTimerThread::m_Instance = NULL; - -// ------------------------------ cTimerCallback ----------------------------- - -cTimerCallback::~cTimerCallback() -{ - TRACEF("cTimerCallback::~cTimerCallback"); - cTimerThread::CancelEvent(this, NULL, true); -} - -void cTimerCallback::Set(cTimerCallback *handler, unsigned int TimeoutMs) -{ - TRACEF("cTimerCallback::Set"); - cTimerThread::AddEvent(handler, TimeoutMs); -} - -void cTimerCallback::Cancel(cTimerCallback *handler) -{ - TRACEF("cTimerCallback::Cancel"); - cTimerThread::CancelEvent(handler); -} - -// ------------------------------- cTimerEvent ------------------------------- - -//cTimerEvent::cTimerEvent(unsigned int TimeoutMs) -//{ -// TRACEF("cTimerEvent::cTimerEvent"); -//// cTimerThread::AddEvent(this, TimeoutMs, true); -//} - -void cTimerEvent::AddEvent(unsigned int TimeoutMs) -{ - TRACEF("cTimerEvent::AddEvent"); - cTimerThread::AddEvent(this, TimeoutMs, true); -} - -void cTimerEvent::Cancel(cTimerEvent *&event) -{ - TRACEF("cTimerEvent::Cancel"); - cTimerThread::CancelEvent(event); - event = NULL; -} - -void cTimerEvent::CancelAll(void *Target) -{ - TRACEF("cTimerEvent::CancelAll"); - cTimerThread::CancelEvent(NULL, Target); -} - - - - - - - diff --git a/tools/timer.h b/tools/timer.h deleted file mode 100644 index 2ee8724b..00000000 --- a/tools/timer.h +++ /dev/null @@ -1,296 +0,0 @@ -/* - * timer.h: Threaded timer class - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: timer.h,v 1.1 2006-06-03 10:04:28 phintuka Exp $ - * - */ - -#ifndef __XINELIBOUTPUT_TIMER_H -#define __XINELIBOUTPUT_TIMER_H - -// -// cTimerCallback : timer callback handler interface -// -class cTimerCallback { - protected: - virtual bool TimerEvent() = 0; // return false to cancel timer - - virtual void *TargetId() { return (void*)this; } - virtual int size() { return sizeof(*this); } - virtual bool is(void *data, int len) - { - return len==sizeof(*this) && TargetId()==data; - } - - friend class cTimerThread; - - public: - static void Set(cTimerCallback *, unsigned int TimeoutMs); - static void Cancel(cTimerCallback *); - - virtual ~cTimerCallback(); -}; - -// -// cTimerEvent : base class for timer events -// -class cTimerEvent : protected cTimerCallback { - private: - cTimerEvent(cTimerEvent&); - - protected: - cTimerEvent() {}; - - virtual void AddEvent(unsigned int TimeoutMs); - - static void CancelAll(void *Target); - - template<class TCLASS> friend void CancelTimerEvents(TCLASS*); - friend class cTimerThread; - - public: - static void Cancel(cTimerEvent *&); -}; - -// -// make gcc 3.4.5 happy -// -template<class TCLASS, class TRESULT> -cTimerEvent *CreateTimerEvent(TCLASS *c, TRESULT (TCLASS::*fp)(void), - unsigned int TimeoutMs); -template<class TCLASS, class TRESULT, class TARG1> -cTimerEvent *CreateTimerEvent(TCLASS *c, TRESULT (TCLASS::*fp)(TARG1), - TARG1 arg1, - unsigned int TimeoutMs); -template<class TCLASS> -cTimerEvent *CreateTimerEvent(TCLASS *c, void (TCLASS::*fp)(void), - unsigned int TimeoutMs, bool runOnce = true); -template<class TCLASS, class TARG1> -cTimerEvent *CreateTimerEvent(TCLASS *c, void (TCLASS::*fp)(TARG1), - TARG1 arg1, - unsigned int TimeoutMs, bool runOnce = true); - -// -// Timer event templates -// - -template <class TCLASS, class TRESULT> -class cTimerFunctorR0 : public cTimerEvent { - - public: - - protected: - typedef TRESULT (TCLASS::*TFUNC)(void); - - cTimerFunctorR0(TCLASS *obj, TFUNC f, unsigned int TimeoutMs) : - m_obj(obj), m_f(f) - { - AddEvent(TimeoutMs); - } - - virtual ~cTimerFunctorR0() {}; - - virtual bool TimerEvent(void) - { - return (*m_obj.*m_f)(); - } - - virtual void *TargetId() { return (void*)m_obj; } - virtual int size() { return sizeof(*this); } - virtual bool is(void *data, int len) - { - return sizeof(*this)==len && !memcmp(this,data,len); - } - - private: - TCLASS *m_obj; - TFUNC m_f; - - friend cTimerEvent *CreateTimerEvent<TCLASS,TRESULT>(TCLASS*,TFUNC,unsigned int); -}; - -template <class TCLASS, class TRESULT, class TARG1> -class cTimerFunctorR1 : public cTimerEvent { - - public: - - protected: - typedef TRESULT (TCLASS::*TFUNC)(TARG1); - - cTimerFunctorR1(TCLASS *obj, TFUNC f, TARG1 arg1, unsigned int TimeoutMs) : - m_obj(obj), m_f(f), m_arg1(arg1) - { - AddEvent(TimeoutMs); - } - - virtual ~cTimerFunctorR1() {}; - - virtual bool TimerEvent(void) - { - return (*m_obj.*m_f)(m_arg1); - } - - virtual void *TargetId() { return (void*)m_obj; } - virtual int size() { return sizeof(*this); } - virtual bool is(void *data, int len) - { - return sizeof(*this)==len && !memcmp(this,data,len); - } - - private: - TCLASS *m_obj; - TFUNC m_f; - TARG1 m_arg1; - - friend cTimerEvent *CreateTimerEvent<TCLASS,TRESULT,TARG1>(TCLASS*,TFUNC,TARG1,unsigned int); -}; - -template <class TCLASS> -class cTimerFunctor0 : public cTimerEvent { - - public: - - protected: - typedef void (TCLASS::*TFUNC)(void); - - cTimerFunctor0(TCLASS *obj, TFUNC f, - unsigned int TimeoutMs, bool runOnce) : - m_obj(obj), m_f(f), m_runAgain(!runOnce) - { - AddEvent(TimeoutMs); - } - - virtual ~cTimerFunctor0() {}; - - virtual bool TimerEvent(void) - { - (*m_obj.*m_f)(); - return m_runAgain; - } - - virtual void *TargetId() { return (void*)m_obj; } - virtual int size() { return sizeof(*this); } - virtual bool is(void *data, int len) - { - return sizeof(*this)==len && !memcmp(this,data,len); - } - - private: - TCLASS *m_obj; - TFUNC m_f; - bool m_runAgain; - - friend cTimerEvent *CreateTimerEvent<TCLASS>(TCLASS*,TFUNC,unsigned int,bool); -}; - -template <class TCLASS, class TARG1> -class cTimerFunctor1 : public cTimerEvent { - - public: - - protected: - typedef void (TCLASS::*TFUNC)(TARG1); - - cTimerFunctor1(TCLASS *obj, TFUNC f, TARG1 arg1, - unsigned int TimeoutMs, bool runOnce) : - m_obj(obj), m_f(f), m_arg1(arg1), m_runAgain(!runOnce) - { - AddEvent(TimeoutMs); - } - - virtual ~cTimerFunctor1() {}; - - virtual bool TimerEvent(void) - { - (*m_obj.*m_f)(m_arg1); - return m_runAgain; - } - - virtual void *TargetId() { return (void*)m_obj; } - virtual int size() { return sizeof(*this); } - virtual bool is(void *data, int len) - { - return sizeof(*this)==len && !memcmp(this,data,len); - } - - private: - TCLASS *m_obj; - TFUNC m_f; - TARG1 m_arg1; - bool m_runAgain; - - friend cTimerEvent *CreateTimerEvent<TCLASS,TARG1>(TCLASS*,TFUNC,TARG1,unsigned int,bool); -}; - -// -// Function templates for timer event creation and cancellation -// - -template<class TCLASS, class TRESULT> -cTimerEvent *CreateTimerEvent(TCLASS *c, TRESULT (TCLASS::*fp)(void), - unsigned int TimeoutMs) -{ - return new cTimerFunctorR0<TCLASS,TRESULT>(c,fp,TimeoutMs); -} - -template<class TCLASS, class TRESULT, class TARG1> -cTimerEvent *CreateTimerEvent(TCLASS *c, TRESULT (TCLASS::*fp)(TARG1), - TARG1 arg1, - unsigned int TimeoutMs) -{ - return new cTimerFunctorR1<TCLASS,TRESULT,TARG1>(c,fp,arg1,TimeoutMs); -} - -template<class TCLASS> -cTimerEvent *CreateTimerEvent(TCLASS *c, void (TCLASS::*fp)(void), - unsigned int TimeoutMs, bool runOnce = true) -{ - return new cTimerFunctor0<TCLASS>(c,fp,TimeoutMs,runOnce); -} - -template<class TCLASS, class TARG1> -cTimerEvent *CreateTimerEvent(TCLASS *c, void (TCLASS::*fp)(TARG1), - TARG1 arg1, - unsigned int TimeoutMs, bool runOnce = true) -{ - return new cTimerFunctor1<TCLASS,TARG1>(c,fp,arg1,TimeoutMs,runOnce); -} - -template<class TCLASS> -void CancelTimerEvents(TCLASS *c) -{ - cTimerEvent::CancelAll((void*)c); -} - - -// usage: -// -// 'this' derived from cTimerHandler: -// Set timer: -// cTimerCallback::Set(this, TimeoutMs); -// Cancel timer: -// - return false from handler or -// - call cTimerCallback::Cancel(this); or -// - delete 'this' object -// -// any function of any class: -// Set timer: -// - cTimerEvent *event = CreateTimerEvent(...); -// example: -// CreateTimerEvent(this, &cXinelibDevice::TimerEvent, 1, 1000); -// -> calls this->cXinelibDevice::TimerEvent(1) every second until stopped. -// Cancel timer: -// - if handler returns bool: return false from handler -// - handler is type of void: timer runs only once -// - call cTimerEvent::Cancel(event) -// Cancel all timers for object: -// - Call CancelTimerEvents(object) -// - Call CancelTimerEvents(this) - - -#endif // __XINELIBOUTPUT_TIMER_H - - diff --git a/tools/udp_buffer.h b/tools/udp_buffer.h deleted file mode 100644 index 6284349a..00000000 --- a/tools/udp_buffer.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - * udp_buffer.h: Ring buffer for UDP/RTP streams - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: udp_buffer.h,v 1.3 2006-12-14 12:30:25 phintuka Exp $ - * - */ - -#ifndef __UDP_BUFFER_H -#define __UDP_BUFFER_H - -#include <stdint.h> - -#include "../xine_input_vdr_net.h" // frame headers - - -#define UDP_BUFFER_SIZE 0x100 // 2^n -#define UDP_BUFFER_MASK 0xff // 2^n - 1 - -#if UDP_BUFFER_MASK != UDP_SEQ_MASK -# error Buffer handling error !!! -#endif - - -class cUdpBackLog -{ - friend class cUdpScheduler; - - private: - - cUdpBackLog(cUdpBackLog&); - - stream_rtp_header_impl_t *m_UdpBuffer[UDP_BUFFER_SIZE]; - int m_UdpBufLen[UDP_BUFFER_SIZE]; /* size of allocated memory, not frame */ - int m_PayloadSize[UDP_BUFFER_SIZE]; /* size of frame */ - unsigned int m_SeqNo; /* next (outgoing) sequence number */ - unsigned int m_RtpSeqNo; /* next (outgoing) RTP sequence number */ - - protected: - - cUdpBackLog() - { - memset(m_UdpBuffer, 0, sizeof(stream_rtp_header_impl_t *)*UDP_BUFFER_SIZE); - memset(m_UdpBufLen, 0, sizeof(int) * UDP_BUFFER_SIZE); - memset(m_PayloadSize, 0, sizeof(int) * UDP_BUFFER_SIZE); - m_SeqNo = 0; - m_RtpSeqNo = random(); - } - - void Clear(int HowManyFrames) - { - // Clear n last frames from buffer. - // (called to adjust sequence numbering when some - // already allocated frames won't be sent) - // - // Note: Nothing is freed. - // To completely reset buffer it must be deleted and re-created. - // - m_SeqNo = (m_SeqNo + UDP_BUFFER_SIZE - HowManyFrames) & UDP_BUFFER_MASK; - } - - virtual ~cUdpBackLog() - { - for(int i=0; i<UDP_BUFFER_SIZE; i++) - if(m_UdpBuffer[i]) { - //m_UdpBufLen[i] = 0; - delete[] m_UdpBuffer[i]; - m_UdpBuffer[i] = NULL; - } - } - - stream_rtp_header_impl_t *Get(int UdpSeqNo) - { - int BufIndex = UdpSeqNo & UDP_BUFFER_MASK; - return m_UdpBuffer[BufIndex]; - } - - int PayloadSize(int UdpSeqNo) - { - int BufIndex = UdpSeqNo & UDP_BUFFER_MASK; - return m_UdpBuffer[BufIndex] ? m_PayloadSize[BufIndex] : 0; - } - - stream_rtp_header_impl_t *MakeFrame(uint64_t StreamPos, - const uchar *Data, int DataLen) - { - int UdpPacketLen = DataLen + sizeof(stream_rtp_header_impl_t); - int BufIndex = m_SeqNo & UDP_BUFFER_MASK; - - // old buffer too small ? free it - if(m_UdpBuffer[BufIndex] && m_UdpBufLen[BufIndex] < UdpPacketLen) { - delete[] m_UdpBuffer[BufIndex]; - m_UdpBuffer[BufIndex] = NULL; - } - - // no buffer ? alloc it - if(!m_UdpBuffer[BufIndex]) { - m_UdpBuffer[BufIndex] = (stream_rtp_header_impl_t*)new uchar[UdpPacketLen]; - m_UdpBufLen[BufIndex] = UdpPacketLen; - } - m_PayloadSize[BufIndex] = DataLen; - - // Fill frame to buffer - stream_rtp_header_impl_t *header = m_UdpBuffer[BufIndex]; - - memcpy(header->payload, Data, DataLen); - - // RTP header - header->rtp_hdr.raw[0] = RTP_VERSION_BYTE | RTP_HDREXT_BIT; - header->rtp_hdr.raw[1] = RTP_PAYLOAD_TYPE; - header->rtp_hdr.seq = htons(m_RtpSeqNo & 0xFFFF); - /*header->rtp_hdr.ts = htonl((uint32_t)(RtpScr.Now() & 0xffffffff));*/ - /*header->rtp_hdr.ssrc = htonl(m_ssrc);*/ - - // RTP header extension - header->hdr_ext.hdr.size = htons(RTP_HEADER_EXT_X_SIZE); - header->hdr_ext.hdr.type = htons(RTP_HEADER_EXT_X_TYPE); - - // UDP header - header->hdr_ext.pos = htonull(StreamPos); - header->hdr_ext.seq = htons(m_SeqNo); - - header->hdr_ext.padding1[0] = 0; - header->hdr_ext.padding1[1] = 0; - - m_RtpSeqNo = (m_RtpSeqNo + 1) & 0xFFFF; - m_SeqNo = (m_SeqNo + 1) & UDP_SEQ_MASK; - - return header; - } -}; - - -#endif diff --git a/tools/udp_pes_scheduler.h b/tools/udp_pes_scheduler.h deleted file mode 100644 index fd24f57a..00000000 --- a/tools/udp_pes_scheduler.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * udp_pes_scheduler.h: PES scheduler for UDP/RTP streams - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: udp_pes_scheduler.h,v 1.13 2008-04-28 20:53:07 phintuka Exp $ - * - */ - -#ifndef __UDP_PES_SCHEDULER_H -#define __UDP_PES_SCHEDULER_H - -#include <stdint.h> - -#include <vdr/tools.h> // uchar -#include <vdr/thread.h> - -#include "cxsocket.h" -#include "time_pts.h" - -#define MAX_UDP_HANDLES 16 - -class cUdpBackLog; - -class cUdpScheduler : public cThread -{ - public: - - cUdpScheduler(); - virtual ~cUdpScheduler(); - - // fd should be binded & connected to IP:PORT (local+remote) pair ! - bool AddHandle(int fd); /* UDP unicast */ - void RemoveHandle(int fd); /* UDP unicast */ - bool AddRtp(void); /* UDP/RTP multicast */ - void RemoveRtp(void); /* UDP/RTP multicast */ - bool AddHandle(cxSocket& s) { return AddHandle(s.handle()); } - void RemoveHandle(cxSocket& s) { RemoveHandle(s.handle()); } - - bool Clients(void) { return m_Handles[0] >= 0; } - int Poll(int TimeoutMs, bool Master); - bool Queue(uint64_t StreamPos, const uchar *Data, int Length); - void ReSend(int fd, uint64_t Pos, int Seq1, int Seq2); - - void Clear(void); - bool Flush(int TimeoutMs); - - void Pause(bool On); - void TrickSpeed(const int Multiplier); - void SetScrSpeed(const int Speed = 90000); - - protected: - - // Data for payload handling & buffering - - // Signalling - cCondVar m_Cond; - cMutex m_Lock; - - // Clients - int m_Handles[MAX_UDP_HANDLES]; - int m_wmem[MAX_UDP_HANDLES]; /* kernel buffer size */ - - cxSocket m_fd_rtp; - cxSocket m_fd_rtcp; - - // Queue - int m_QueueNextSeq; /* next outgoing */ - int m_QueuePending; /* outgoing queue size */ - cUdpBackLog *m_BackLog; /* queue for incoming data (not yet send) and retransmissions */ - cMutex m_BackLogDeleteMutex; - - // Data for scheduling algorithm - cTimePts MasterClock; /* Current MPEG PTS (synchronized to current stream) */ - cCondWait CondWait; - - int64_t current_audio_vtime; - int64_t current_video_vtime; - - // RTP - uint32_t m_ssrc; /* RTP synchronization source id */ - cTimePts RtpScr; /* 90 kHz monotonic time source for RTP timestamps */ - - // RTCP - uint64_t m_LastRtcpTime; - uint32_t m_Frames; - uint32_t m_Octets; - - // Scheduling - - bool m_TrickSpeed; - bool m_Master; /* if true, we are master metronom for playback */ - - int calc_elapsed_vtime(int64_t pts, bool Audio); - void Schedule(const uchar *Data, int Length); - - bool m_Running; - virtual void Action(void); - - void Send_RTCP(void); - - int m_fd_sap; - - void Send_SAP(bool Announce = true); -}; - -#endif diff --git a/tools/vdrdiscovery.c b/tools/vdrdiscovery.c deleted file mode 100644 index 82a9a109..00000000 --- a/tools/vdrdiscovery.c +++ /dev/null @@ -1,280 +0,0 @@ -/* - * vdrdiscovery.c - * - * Simple broadcast protocol to search VDR with xineliboutput server - * from (local) network. - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: vdrdiscovery.c,v 1.5 2008-04-03 13:59:37 phintuka Exp $ - * - */ - -#include <stdlib.h> -#include <stdio.h> -#include <poll.h> -#include <unistd.h> -#include <netinet/in.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <arpa/inet.h> - -#ifdef FE_STANDALONE -# define LOG_MODULENAME "[discovery] " -#else -# define LogToSysLog 1 -#endif - -#define NEED_x_syslog -#include "../logdefs.h" - -#include "vdrdiscovery.h" - -/* - * - */ - -#ifndef DISCOVERY_PORT -# define DISCOVERY_PORT 37890 -#endif - -/* discovery protocol strings (v1.0) */ -#define DISCOVERY_1_0_HDR "VDR xineliboutput DISCOVERY 1.0" "\r\n" -#define DISCOVERY_1_0_CLI "Client: %s:%d" "\r\n" -#define DISCOVERY_1_0_SVR "Server port: %d" "\r\n" -#define DISCOVERY_1_0_ADDR "Server address: %s" "\r\n" -#define DISCOVERY_1_0_VERSION "Server version: " /*vdr-" VDRVERSION "\r\n\t"*/ \ - "xineliboutput-" XINELIBOUTPUT_VERSION "\r\n" - -/* - * - */ - -static inline int discovery_init(int port) -{ - int fd_discovery = -1; - struct sockaddr_in sin; - - if ((fd_discovery = socket(PF_INET, SOCK_DGRAM, 0/*IPPROTO_TCP*/)) < 0) { - LOGERR("socket() failed (UDP discovery)"); - } else { - int iBroadcast = 1, iReuse = 1; - if(setsockopt(fd_discovery, SOL_SOCKET, SO_BROADCAST, &iBroadcast, sizeof(int)) < 0) - LOGERR("setsockopt(SO_BROADCAST) failed"); - if(setsockopt(fd_discovery, SOL_SOCKET, SO_REUSEADDR, &iReuse, sizeof(int)) < 0) - LOGERR("setsockopt(SO_REUSEADDR) failed"); - sin.sin_family = AF_INET; - sin.sin_port = htons(port); - sin.sin_addr.s_addr = htonl(INADDR_BROADCAST); - - if (bind(fd_discovery, (struct sockaddr *)&sin, sizeof(sin)) < 0) { - LOGERR("bind() failed (UDP discovery)"); - } else { - return fd_discovery; - } - } - - close(fd_discovery); - return -1; -} - -#ifndef FE_STANDALONE -int udp_discovery_init(void) -{ - return discovery_init(DISCOVERY_PORT); -} -#endif - -static inline int udp_discovery_send(int fd_discovery, int port, char *msg) -{ - struct sockaddr_in sin; - int len = strlen(msg); - - sin.sin_family = AF_INET; - sin.sin_port = htons(port); - sin.sin_addr.s_addr = INADDR_BROADCAST; - - if(len != sendto(fd_discovery, msg, len, 0, - (struct sockaddr *)&sin, sizeof(sin))) { - LOGERR("UDP broadcast send failed (discovery)"); - return -1; - } - - //LOGDBG("UDP broadcast send succeed (discovery)"); - return 0; -} - -#ifndef FE_STANDALONE -int udp_discovery_broadcast(int fd_discovery, int server_port, const char *server_address) -{ - char *msg = NULL; - int result; - - if(server_address && *server_address) - asprintf(&msg, - DISCOVERY_1_0_HDR //"VDR xineliboutput DISCOVERY 1.0" "\r\n" - DISCOVERY_1_0_SVR //"Server port: %d" "\r\n" - DISCOVERY_1_0_ADDR //"Server Address: %d.%d.%d.%d \r\n" - DISCOVERY_1_0_VERSION //"Server version: xineliboutput-" XINELIBOUTPUT_VERSION "\r\n" - "\r\n", - server_port, server_address); - else - asprintf(&msg, - DISCOVERY_1_0_HDR //"VDR xineliboutput DISCOVERY 1.0" "\r\n" - DISCOVERY_1_0_SVR //"Server port: %d" "\r\n" - DISCOVERY_1_0_VERSION //"Server version: xineliboutput-" XINELIBOUTPUT_VERSION "\r\n" - "\r\n", - server_port); - - result = udp_discovery_send(fd_discovery, DISCOVERY_PORT, msg); - - free(msg); - return result; -} -#else -static inline int udp_discovery_search(int fd_discovery, int port) -{ - char *msg = NULL; - int result; - - asprintf(&msg, - DISCOVERY_1_0_HDR /* "VDR xineliboutput DISCOVERY 1.0" "\r\n" */ - DISCOVERY_1_0_CLI /* "Client: %s:%d" "\r\n" */ - "\r\n", - "255.255.255.255", - port); - - result = udp_discovery_send(fd_discovery, port, msg); - - free(msg); - return result; -} -#endif - -#ifdef FE_STANDALONE -static -#endif -int udp_discovery_recv(int fd_discovery, char *buf, int timeout, - struct sockaddr_in *source) -{ - socklen_t sourcelen = sizeof(struct sockaddr_in); - struct pollfd pfd; - int err; - - pfd.fd = fd_discovery; - pfd.events = POLLIN; - - errno = 0; - err = poll(&pfd, 1, timeout); - if(err < 1) { - if(err < 0) - LOGERR("broadcast poll error"); - return err; - } - - memset(source, 0, sourcelen); - memset(buf, 0, DISCOVERY_MSG_MAXSIZE); - - err = recvfrom(fd_discovery, buf, DISCOVERY_MSG_MAXSIZE-1, 0, - (struct sockaddr *)source, &sourcelen); - - if(err <= 0) - LOGDBG("fd_discovery recvfrom() error"); - - return err; -} - -#ifndef FE_STANDALONE -int udp_discovery_is_valid_search(const char *buf) -{ - const char *id_string = DISCOVERY_1_0_HDR "Client:"; - - if(!strncmp(id_string, buf, strlen(id_string))) { - LOGMSG("Received valid discovery message %s", buf); - return 1; - } - - LOGDBG("BROADCAST: %s", buf); - return 0; -} -#else -int udp_discovery_find_server(int *port, char *address) -{ - static const char mystring[] = DISCOVERY_1_0_HDR "Server port: "; - struct sockaddr_in from; - char buf[DISCOVERY_MSG_MAXSIZE]; - int fd_discovery = -1; - int trycount = 0; - int err = 0; - - *port = DISCOVERY_PORT; - strcpy(address, "vdr"); - - if((fd_discovery = discovery_init(DISCOVERY_PORT)) < 0) - return 0; - - while(err >= 0 && ++trycount < 4) { - - if((err = udp_discovery_search(fd_discovery, DISCOVERY_PORT) >= 0)) { - - errno = 0; - while( (err = udp_discovery_recv(fd_discovery, buf, 500, &from)) > 0) { - - uint32_t tmp = ntohl(from.sin_addr.s_addr); - - buf[err] = 0; - LOGDBG("Reveived broadcast: %d bytes from %d.%d.%d.%d \n%s", - err, - ((tmp>>24)&0xff), ((tmp>>16)&0xff), - ((tmp>>8)&0xff), ((tmp)&0xff), - buf); - if(!strncmp(mystring, buf, strlen(mystring))) { - char *iploc; - LOGDBG("Valid discovery message"); - close(fd_discovery); - - // default: use broadcast source address - sprintf(address, "%d.%d.%d.%d", - ((tmp>>24)&0xff), ((tmp>>16)&0xff), - ((tmp>>8)&0xff), ((tmp)&0xff)); - - // Check if announce message includes alternative server address - iploc = strstr(buf + strlen(mystring), "Server address: "); - if(iploc) { - uint32_t svraddr; - iploc += strlen("Server address: "); - svraddr = inet_addr(iploc); - if(svraddr == INADDR_NONE) { - LOGMSG("Server provided invalid address !"); - } else { - svraddr = ntohl(svraddr); - sprintf(address, "%d.%d.%d.%d", - ((svraddr>>24)&0xff), ((svraddr>>16)&0xff), - ((svraddr>>8)&0xff), ((svraddr)&0xff)); - LOGMSG("Replacing broadcast source address %d.%d.%d.%d " - "with server-given address %s", - ((tmp>>24)&0xff), ((tmp>>16)&0xff), - ((tmp>>8)&0xff), ((tmp)&0xff), - address); - } - } - - *port = -1; - if(1 == sscanf(buf + strlen(mystring), "%d", port) && - *port >= 1000 && *port <= 0xffff) - return 1; - LOGMSG("Server-given port is invalid !"); - } else { - LOGDBG("NOT valid discovery message"); - } - } - } - } - - /* failed */ - close(fd_discovery); - return 0; -} -#endif - diff --git a/tools/vdrdiscovery.h b/tools/vdrdiscovery.h deleted file mode 100644 index 7c4d18ae..00000000 --- a/tools/vdrdiscovery.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * vdrdiscovery.h - * - * Simple broadcast protocol to search VDR with xineliboutput server - * from (local) network. - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: vdrdiscovery.h,v 1.3 2007-06-11 19:39:06 phintuka Exp $ - * - */ - -#ifndef _VDRDISCOVERY_H_ -#define _VDRDISCOVERY_H_ - -#define DISCOVERY_MSG_MAXSIZE 1024 - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef FE_STANDALONE -int udp_discovery_find_server(int *port, char *address); -#else -int udp_discovery_init(void); -int udp_discovery_broadcast(int fd_discovery, int server_port, const char *server_address); -int udp_discovery_recv(int fd_discovery, char *buf, int timeout, - struct sockaddr_in *source); -int udp_discovery_is_valid_search(const char *buf); -#endif - -#ifdef __cplusplus -}; -#endif - - -#endif // _VDRDISCOVERY_H_ diff --git a/vdrlogo_32x32.c b/vdrlogo_32x32.c deleted file mode 100644 index b5abd5dc..00000000 --- a/vdrlogo_32x32.c +++ /dev/null @@ -1,220 +0,0 @@ -/* - * vdrlogo_32x32.c: 32x32 logo icon - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: vdrlogo_32x32.c,v 1.2 2006-12-19 17:27:49 phintuka Exp $ - * - */ - -/* GIMP RGBA C-Source image dump (vdrlogo_32x32.c) */ - -static const struct { - unsigned int width; - unsigned int height; - /*unsigned int bytes_per_pixel; / * 3:RGB, 4:RGBA */ - unsigned char pixel_data[32 * 32 * 4 + 1]; -} vdrlogo_32x32 = { - 32, 32, /*4,*/ - "\375\375\374\377\375\375\375\377\375\375\375\377\375\375\375\377\375\375" - "\375\377\375\375\375\377\375\375\375\377\375\375\375\377\375\375\375\377" - "\375\375\375\377\375\375\375\377\375\375\375\377\375\375\375\377\375\375" - "\375\377\375\375\375\377\375\375\375\377\375\375\375\377\375\375\375\377" - "\375\375\375\377\375\375\375\377\375\375\375\377\375\375\375\377\375\375" - "\375\377\375\375\375\377\375\375\375\377\375\375\375\377\375\375\375\377" - "\375\375\375\377\375\375\375\377\375\375\375\377\375\375\375\377\375\375" - "\375\377\375\375\374\377\375\375\375\377\375\375\374\377\375\375\375\377" - "\375\375\375\377\375\375\375\377\375\375\375\377\375\375\375\377\375\375" - "\375\377\375\375\375\377\375\375\375\377\375\375\375\377\375\375\375\377" - "\375\375\375\377\375\375\375\377\375\375\375\377\375\375\375\377\375\375" - "\375\377\375\375\375\377\375\375\375\377\375\375\375\377\375\375\375\377" - "\375\375\375\377\375\375\375\377\375\375\375\377\375\375\375\377\375\375" - "\375\377\375\375\375\377\375\375\375\377\375\375\375\377\375\375\375\377" - "\375\375\375\377\366\363\370\377\365\362\367\377\374\374\373\377\375\375" - "\374\377\375\375\375\377\375\375\375\377\375\375\375\377\375\375\375\377" - "\375\375\375\377\375\375\375\377\375\375\373\377\374\374\375\377\366\362" - "\371\377\365\361\367\377\365\361\370\377\365\361\367\377\367\363\372\377" - "\374\372\375\377\370\367\370\377\364\361\370\377\364\361\367\377\365\361" - "\367\377\365\361\367\377\365\361\367\377\365\361\367\377\365\361\367\377" - "\366\362\370\377\373\371\374\377\374\375\375\377\375\375\375\377\375\375" - "\375\377\375\375\375\377\210s\245\377Q0\177\377\336\326\346\377\376\374\374" - "\377\375\375\375\377\375\375\375\377\375\375\375\377\375\375\375\377\375" - "\375\375\377\375\375\374\377\370\365\371\377\233\207\265\377T3\204\377O." - "\201\377O.\201\377O.\201\377T4\205\377nQ\224\377\245\221\276\377eN\207\377" - "O.\202\377O-\201\377O-\201\377O.\201\377O.\201\377O-\201\377Q1\203\377iK" - "\221\377\270\247\311\377\372\371\374\377\375\375\375\377\375\375\375\377" - "\241\216\271\377:\17x\377\256\235\303\377\375\375\374\377\375\375\375\377" - "\375\375\375\377\375\375\375\377\375\375\375\377\375\375\375\377\375\374" - "\373\377\236\214\270\377;\21x\377:\17w\377:\17w\377;\16w\377:\17y\377:\17" - "z\377:\17z\377<\23w\377kQ\221\377C\37x\377:\17x\377:\17x\377:\17x\377:\17" - "x\377:\17x\377:\17w\377:\17w\377;\24v\377\264\245\311\377\374\374\375\377" - "\375\375\374\377\316\303\332\377:\20x\377\205k\246\377\375\375\375\377\375" - "\375\375\377\375\375\375\377\375\375\375\377\375\375\375\377\375\375\375" - "\377\352\345\360\377C\35{\377:\20u\377<\33j\377>\"c\377<\"c\377<\"e\377:" - "\40e\3779\26n\377;\17x\377>\27w\377v_\230\377A*c\377B,d\377C-e\377D.e\377" - "E/f\377D-g\377;\31k\377:\17z\377R2\204\377\367\364\371\377\375\375\375\377" - "\363\356\367\377A\32z\377\\;\213\377\373\372\374\377\375\375\375\377\375" - "\375\375\377\375\375\375\377\375\375\375\377\375\375\375\377\264\244\310" - "\377:\20w\377@\"i\377K1o\377\306\303\312\377\313\311\315\377\312\311\315" - "\377\304\302\306\377\237\230\252\377K-u\377;\17x\377pT\231\377\332\327\333" - "\377\334\333\334\377\336\336\335\377\340\337\337\377\342\340\340\377\336" - "\336\337\377\256\246\270\377B\40u\3779\20x\377\313\302\331\377\375\375\375" - "\377\375\373\375\377dD\221\377?\31w\377\355\351\362\377\375\375\375\377\375" - "\375\375\377\375\375\375\377\375\375\375\377\375\375\373\377\211o\252\377" - ";\24q\377C&n\377>\31s\377\354\351\356\377\375\375\374\377\375\375\375\377" - "\375\375\375\377\375\375\375\377\310\301\323\377>\27v\377?\32y\377\352\344" - "\357\377\375\376\374\377\375\375\374\377\375\375\374\377\375\375\374\377" - "\375\375\374\377\374\374\374\377\223}\261\377:\16y\377\236\214\265\377\375" - "\375\374\377\375\375\375\377\220y\257\377:\20v\377\312\300\327\377\375\375" - "\375\377\375\375\375\377\375\375\375\377\375\375\374\377\374\374\375\377" - "\\:\214\377G)p\377P/\204\377=\30t\377\353\351\355\377\375\375\375\377\375" - "\375\374\377\374\374\374\377\374\374\373\377\374\373\374\377w^\234\3778\20" - "z\377\266\251\312\377\375\375\374\377\375\375\375\377\375\375\375\377\375" - "\375\375\377\375\375\375\377\375\375\374\377\304\267\323\377;\17x\377\201" - "m\236\377\375\375\374\377\375\375\375\377\274\257\316\377:\17y\377\240\217" - "\271\377\375\375\372\377\375\375\375\377\375\375\375\377\375\375\375\377" - "\361\354\366\377<\25t\377jV\207\377];\216\377<\31s\377\353\351\355\377\375" - "\375\375\377\373\373\373\377yyy\377\220\221\220\377\374\374\374\377\273\255" - "\315\3779\20x\377\211u\253\377\375\375\374\377\375\375\375\377\375\375\375" - "\377\375\375\375\377\375\375\375\377\375\375\374\377\306\271\325\377;\17" - "x\377xb\226\377\375\375\375\377\375\375\374\377\346\340\354\377;\24w\377" - "v\\\236\377\375\375\373\377\375\375\375\377\375\375\375\377\375\375\374\377" - "\310\275\325\3779\21v\377\227\214\250\377_;\216\377<\31s\377\353\351\355" - "\377\375\375\375\377\331\331\331\377\5\5\5\377\24\24\24\377\340\340\340\377" - "\343\335\354\377:\21w\377gL\222\377\374\374\374\377\375\375\375\377\375\375" - "\375\377\375\375\375\377\375\375\375\377\376\374\374\377\242\217\273\377" - ";\17z\377\177m\230\377\375\375\375\377\375\375\376\377\372\371\373\377T2" - "\205\377O.\203\377\372\371\373\377\375\375\375\377\375\375\375\377\375\375" - "\374\377\232\206\267\377:\23s\377\304\277\312\377_<\217\377<\31r\377\353" - "\351\355\377\375\375\375\377\320\320\320\377HE?\377QPM\377\253\253\253\377" - "\363\360\367\377B\32{\377R2\201\377\372\371\373\377\375\375\374\377\375\375" - "\374\377\375\375\374\377\375\375\375\377\364\355\366\377W6\210\377:\20v\377" - "\232\220\247\377\375\375\375\377\375\375\375\377\375\375\376\377~d\244\377" - ";\23u\377\345\340\355\377\375\375\375\377\375\375\375\377\375\374\375\377" - "oP\231\377@\40p\377\351\350\352\377_<\216\377<\31r\377\353\351\355\377\375" - "\375\375\377\333\330\325\377\237\2076\377k_0\377\232\232\232\377\370\366" - "\373\377I$\177\377G#y\377\276\261\315\377\273\255\314\377\273\255\314\377" - "\272\254\313\377\252\227\301\377`A\212\377;\17y\377<\33k\377\315\312\320" - "\377\375\375\375\377\375\375\375\377\375\375\375\377\254\232\302\3779\20" - "z\377\275\261\316\377\375\375\375\377\375\375\375\377\370\364\372\377G\"" - "}\377[B|\377\373\372\373\377_<\216\377<\31r\377\353\351\355\377\375\375\375" - "\377\340\334\327\377\267\2266\377\220|D\377\213\214\213\377\373\371\375\377" - "M(\204\377D\34x\377J'\201\377:\20x\377;\20x\377:\20y\377;\17y\377:\17w\377" - "9\23r\377i]{\377\367\370\370\377\375\375\374\377\375\375\375\377\375\375" - "\374\377\327\316\342\377;\21x\377\224\177\262\377\375\375\375\377\375\375" - "\375\377\327\316\342\377:\21w\377\203t\231\377\375\375\375\377_<\216\377" - "<\31r\377\353\351\355\377\375\375\375\377\263\263\262\377\325\315\275\377" - "\334\331\323\377<<<\377\370\366\373\377L'\202\377A\34v\377H'y\3778\23r\377" - "9\21t\377:\17y\3778\20v\377;\36h\377]Rr\377\334\333\336\377\374\375\373\377" - "\375\375\375\377\375\375\375\377\375\375\375\377\367\364\370\377H!~\377k" - "M\225\377\375\374\375\377\375\375\374\377\255\233\303\3778\21t\377\257\250" - "\272\377\375\375\375\377_<\216\377<\31r\377\353\351\355\377\372\372\372\377" - "\177\177\177\377\363\363\363\377\351\352\351\377*+*\377\302\276\304\377G" - "!~\377B\37v\377\211}\227\377la}\377gZ|\377D'p\377:\20w\377hQ\212\377\354" - "\353\355\377\375\375\375\377\375\375\376\377\375\375\375\377\375\375\375" - "\377\375\375\375\377\375\374\373\377nO\230\377F!|\377\370\366\372\377\375" - "\375\374\377\201f\246\377:\27o\377\331\327\334\377\375\375\375\377_<\216" - "\377<\31r\377\353\351\355\377\347\347\347\377\233\233\233\377\365\366\365" - "\377\366\366\365\377lmm\377nis\377>\27x\377H(v\377\364\364\365\377\371\372" - "\372\377\371\370\370\377\311\302\323\377B\37u\377<\25x\377\317\304\335\377" - "\375\375\375\377\375\375\375\377\375\375\375\377\375\375\375\377\375\375" - "\375\377\375\375\373\377\231\205\267\377:\21u\377\332\324\342\377\373\372" - "\375\377V4\210\377H-r\377\366\366\366\377\375\375\375\377_<\216\377<\31r" - "\377\353\351\354\377\257\257\257\377\304\305\307\377\362\364\364\377\366" - "\366\366\377\201\201\202\377,$8\3779\20u\377U:{\377\372\372\372\377\375\375" - "\375\377\375\375\375\377\374\374\375\377\217|\253\3779\17y\377mO\227\377" - "\375\373\374\377\375\375\375\377\375\375\375\377\375\375\375\377\375\375" - "\375\377\375\375\375\377\306\273\324\3779\20u\377\262\243\305\377\350\344" - "\357\377>\25w\377nZ\211\377\375\375\373\377\375\375\375\377_<\216\377<\31" - "r\377\353\351\354\377\270\253\211\377\322\316\275\377\363\363\364\377\366" - "\366\365\377\204\200l\377\36\21\40\377:\20v\377lY\210\377\375\374\374\377" - "\375\375\375\377\375\375\375\377\375\375\375\377\345\337\353\377?\31v\377" - ";\24w\377\326\315\341\377\375\375\375\377\375\375\375\377\375\375\375\377" - "\375\375\374\377\375\375\374\377\357\352\364\377=\27x\377\210q\252\377\302" - "\265\321\377;\20v\377\231\216\250\377\375\375\375\377\375\374\375\377^;\216" - "\377=\30s\377\343\333\306\377\344\2738\377\241\213L\377\360\357\361\377\365" - "\364\360\377\237\2016\377\214i,\377:\21n\377\221\205\242\377\375\375\375" - "\377\375\375\375\377\375\375\375\377\375\375\375\377\375\374\376\377z_\237" - "\3779\20y\377\214u\253\377\374\374\374\377\375\375\375\377\375\375\375\377" - "\375\375\375\377\375\375\375\377\375\373\375\377\\;\214\377`A\215\377\232" - "\202\264\377:\23p\377\304\300\310\377\375\375\375\377\375\374\375\377`<\216" - "\377=\30r\377\335\312\227\377\356\274\22\377\300\234\36\377\342\337\333\377" - "\337\336\331\377\315\236\36\377\350\267\37\377b<X\377\300\274\304\377\374" - "\376\375\377\375\375\375\377\375\375\375\377\375\375\375\377\375\375\375" - "\377\305\272\324\3779\20w\377J'\200\377\365\361\367\377\375\375\374\377\375" - "\375\375\377\375\375\375\377\375\375\375\377\375\374\375\377\211q\251\377" - "E\36|\377lJ\227\377@!n\377\352\350\353\377\375\375\374\377\375\375\375\377" - "`=\217\377>\30t\377\327\300\236\377\335\254\37\377\336\255'\377vkc\3770+" - "2\377\311\232\32\377\263\212\40\377H7B\377\356\356\357\377\375\375\375\377" - "\375\375\375\377\375\375\375\377\375\375\375\377\375\375\375\377\370\366" - "\372\377P.\203\377:\20x\377\274\256\316\377\375\375\375\377\375\375\375\377" - "\375\375\375\377\375\375\375\377\375\375\376\377\266\247\311\377:\21x\377" - "?\26z\377ZC{\377\373\372\373\377\375\375\375\377\375\374\375\377];\215\377" - "<\22v\377^<\202\377P%N\377X+R\3775\23]\3770\22^\377fC\36\3770\30*\377\214" - "\210\225\377\375\375\375\377\375\375\375\377\375\375\375\377\375\375\375" - "\377\375\375\375\377\375\375\375\377\375\375\375\377\226\201\263\377;\17" - "y\377pV\231\377\374\374\374\377\375\375\375\377\375\375\375\377\375\375\375" - "\377\376\375\375\377\342\333\351\3779\22v\377:\17y\377\204u\227\377\375\375" - "\374\377\375\375\375\377\375\374\375\377]9\214\377;\17z\377;\17y\3779\20" - "y\377;\17x\377;\17z\377;\20v\377/\21S\377RDc\377\350\347\346\377\375\375" - "\375\377\375\375\375\377\375\375\375\377\375\375\375\377\375\375\375\377" - "\375\375\375\377\375\375\376\377\334\325\347\377=\25w\377>\27w\377\345\337" - "\355\377\375\375\374\377\375\375\374\377\376\375\374\377\375\375\375\377" - "\374\371\374\377K.{\3778\26l\377\257\247\271\377\375\375\375\377\376\375" - "\375\377\375\374\374\377_@\206\377:\25q\3779\25q\377:\24p\3779\25n\3778\26" - "n\377?#d\377bWr\377\325\323\325\377\375\375\373\377\375\375\374\377\376\375" - "\374\377\375\375\374\377\375\375\374\377\375\375\374\377\375\375\375\377" - "\375\375\374\377\374\372\374\377gK\217\3779\24o\377\240\223\264\377\374\374" - "\373\377\374\374\373\377\374\374\373\377\374\372\373\377\375\374\374\377" - "\255\245\265\377\211\202\222\377\336\335\343\377\375\375\375\377\374\374" - "\375\377\374\372\375\377\260\252\267\377\210\203\224\377\212\200\223\377" - "\212\202\225\377\212\202\221\377\223\217\232\377\277\274\303\377\360\360" - "\361\377\374\372\373\377\375\374\375\377\373\373\375\377\373\374\374\377" - "\373\372\373\377\375\374\372\377\374\371\372\377\374\374\372\377\373\373" - "\374\377\374\372\372\377\305\300\313\377\211\200\225\377\253\250\261\377" - "\326\323\337\377\325\322\333\377\331\323\335\377\247\233\265\377\340\333" - "\344\377\240\224\261\377\342\335\346\377\244\231\257\377\367\365\370\377" - "\350\346\354\377\241\226\260\377\336\332\343\377\332\326\341\377\261\250" - "\276\377\326\321\335\377\313\305\322\377\375\374\373\377\274\263\312\377" - "\310\300\323\377\260\244\275\377\337\333\344\377\246\237\263\377\345\342" - "\351\377\241\227\256\377\342\334\350\377\235\217\257\377\327\321\335\377" - "\252\240\271\377\321\312\332\377\275\266\311\377\300\266\314\377\305\273" - "\317\377\301\270\314\377\301\272\306\377\275\265\304\377\261\250\277\377" - "\271\263\301\377\203u\225\377\316\311\324\377\261\250\273\377\333\327\335" - "\377\343\337\346\377\241\226\256\377\276\267\307\377\314\304\322\377\210" - "}\232\377\257\246\276\377\263\252\276\377\375\375\374\377\237\222\257\377" - "\244\232\263\377\225\210\245\377\324\320\331\377\262\251\274\377\316\310" - "\322\377\264\252\277\377\271\262\303\377n^\205\377\300\271\307\377\244\231" - "\263\377\267\256\302\377\256\246\271\377\244\230\264\377\236\225\257\377" - "\325\321\331\377\331\326\333\377\313\307\321\377\240\230\255\377\313\307" - "\320\377\217\206\240\377\341\336\345\377\231\220\244\377\342\341\344\377" - "\356\352\356\377\220\207\234\377\320\315\323\377\322\316\326\377\217\210" - "\236\377\311\305\320\377\301\272\307\377\376\375\374\377\307\302\315\377" - "\304\277\313\377\243\233\257\377\326\323\332\377\242\230\256\377\335\331" - "\337\377\233\220\246\377\320\314\324\377\254\246\267\377\317\312\324\377" - "\222\213\237\377\307\303\316\377\246\241\263\377\311\303\314\377\302\275" - "\306\377\372\372\372\377\371\371\370\377\370\370\371\377\360\357\357\377" - "\370\370\370\377\354\354\355\377\367\367\366\377\355\355\355\377\374\374" - "\373\377\374\374\373\377\353\353\353\377\372\372\371\377\371\371\371\377" - "\354\354\354\377\371\370\370\377\366\366\366\377\375\375\375\377\370\370" - "\371\377\366\367\367\377\361\360\361\377\364\363\362\377\360\357\360\377" - "\371\371\371\377\356\356\356\377\372\372\372\377\367\367\370\377\367\367" - "\366\377\353\353\353\377\371\371\370\377\352\353\353\377\371\367\370\377" - "\367\366\366\377\375\375\375\377\375\375\375\377\375\375\375\377\375\375" - "\375\377\375\375\375\377\375\375\375\377\375\375\375\377\375\375\375\377" - "\375\375\375\377\375\375\375\377\375\375\375\377\375\375\375\377\375\375" - "\375\377\375\375\375\377\375\375\375\377\375\375\375\377\375\375\375\377" - "\375\375\375\377\375\375\375\377\375\375\375\377\375\375\375\377\375\375" - "\375\377\375\375\375\377\375\375\375\377\375\375\375\377\375\375\375\377" - "\375\375\375\377\375\375\375\377\375\375\375\377\375\375\375\377\375\375" - "\375\377\375\375\375\377\375\375\375\377\375\375\375\377\375\375\375\377" - "\375\375\375\377\375\375\375\377\375\375\375\377\375\375\375\377\375\375" - "\375\377\375\375\375\377\375\375\375\377\375\375\375\377\375\375\375\377" - "\375\375\375\377\375\375\375\377\375\375\375\377\375\375\375\377\375\375" - "\375\377\375\375\375\377\375\375\375\377\375\375\375\377\375\375\375\377" - "\375\375\375\377\375\375\375\377\375\375\375\377\375\375\375\377\375\375" - "\375\377\375\375\375\377\375\375\375\377\375\375\375\377\375\375\375\377" - "\375\375\375\377\375\375\375\377", -}; - diff --git a/vdrlogo_720x576.mpg b/vdrlogo_720x576.mpg deleted file mode 100644 index 2ef0f3f4..00000000 Binary files a/vdrlogo_720x576.mpg and /dev/null differ diff --git a/xine/post.c b/xine/post.c deleted file mode 100644 index 51ba3188..00000000 --- a/xine/post.c +++ /dev/null @@ -1,906 +0,0 @@ -/* - * Copyright (C) 2003 by Dirk Meyer - * - * This file is part of xine, a unix video player. - * - * xine is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * xine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - * - * The code is taken from xine-ui/src/xitk/post.c at changed to work with fbxine - * - * Modified for VDR xineliboutput plugin by Petri Hintukainen, 2006 - * - runtime re-configuration (load/unload, enable/disable) - * - support for multiple streams - * - support for mosaico post plugin (picture-in-picture) - * - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "post.h" - -#include <sys/types.h> -#include <sys/syscall.h> -#include <unistd.h> -#include <errno.h> -#include <syslog.h> - -#define NEED_x_syslog -#define LOG_MODULENAME "[xine-post] " -#include "../logdefs.h" - -#define fe_t post_plugins_t - -typedef struct { - xine_post_t *post; - xine_post_api_t *api; - xine_post_api_descr_t *descr; - xine_post_api_parameter_t *param; - char *param_data; - - int x; - int y; - - int readonly; - - char **properties_names; -} post_object_t; - - -static int __pplugin_retrieve_parameters(post_object_t *pobj) -{ - xine_post_in_t *input_api; - - if((input_api = (xine_post_in_t *) xine_post_input(pobj->post, - "parameters"))) { - xine_post_api_t *post_api; - xine_post_api_descr_t *api_descr; - xine_post_api_parameter_t *parm; - int pnum = 0; - - post_api = (xine_post_api_t *) input_api->data; - - api_descr = post_api->get_param_descr(); - - parm = api_descr->parameter; - pobj->param_data = malloc(api_descr->struct_size); - - while(parm->type != POST_PARAM_TYPE_LAST) { - - post_api->get_parameters(pobj->post, pobj->param_data); - - if(!pnum) - pobj->properties_names = (char **) xine_xmalloc(sizeof(char *) * 2); - else - pobj->properties_names = (char **) - realloc(pobj->properties_names, sizeof(char *) * (pnum + 2)); - - pobj->properties_names[pnum] = strdup(parm->name); - pobj->properties_names[pnum + 1] = NULL; - pnum++; - parm++; - } - - pobj->api = post_api; - pobj->descr = api_descr; - pobj->param = api_descr->parameter; - - return 1; - } - - return 0; -} - -static void _pplugin_update_parameter(post_object_t *pobj) -{ - pobj->api->set_parameters(pobj->post, pobj->param_data); - pobj->api->get_parameters(pobj->post, pobj->param_data); -} - -static void __pplugin_update_parameters(xine_post_t *post, char *args) -{ - post_object_t pobj; - char *p; - - memset(&pobj, 0, sizeof(post_object_t)); - pobj.post = post; - - if(__pplugin_retrieve_parameters(&pobj)) { - int i; - - if(pobj.properties_names && args && *args) { - char *param; - - while((param = xine_strsep(&args, ",")) != NULL) { - - p = param; - - while((*p != '\0') && (*p != '=')) - p++; - - if(p && strlen(p)) { - int param_num = 0; - - *p++ = '\0'; - - while(pobj.properties_names[param_num] - && strcasecmp(pobj.properties_names[param_num], param)) - param_num++; - - if(pobj.properties_names[param_num]) { - - pobj.param = pobj.descr->parameter; - pobj.param += param_num; - pobj.readonly = pobj.param->readonly; - - switch(pobj.param->type) { - case POST_PARAM_TYPE_INT: - if(!pobj.readonly) { - if(pobj.param->enum_values) { - char **values = pobj.param->enum_values; - int i = 0; - - while(values[i]) { - if(!strcasecmp(values[i], p)) { - *(int *)(pobj.param_data + pobj.param->offset) = i; - break; - } - i++; - } - - if( !values[i] ) - *(int *)(pobj.param_data + pobj.param->offset) = (int) strtol(p, &p, 10); - } else { - *(int *)(pobj.param_data + pobj.param->offset) = (int) strtol(p, &p, 10); - } - _pplugin_update_parameter(&pobj); - } - break; - - case POST_PARAM_TYPE_DOUBLE: - if(!pobj.readonly) { - *(double *)(pobj.param_data + pobj.param->offset) = strtod(p, &p); - _pplugin_update_parameter(&pobj); - } - break; - - case POST_PARAM_TYPE_CHAR: - case POST_PARAM_TYPE_STRING: - if(!pobj.readonly) { - if(pobj.param->type == POST_PARAM_TYPE_CHAR) { - int maxlen = pobj.param->size / sizeof(char); - - snprintf((char *)(pobj.param_data + pobj.param->offset), maxlen, "%s", p); - _pplugin_update_parameter(&pobj); - } - else - fprintf(stderr, "parameter type POST_PARAM_TYPE_STRING not supported yet.\n"); - } - break; - - case POST_PARAM_TYPE_STRINGLIST: /* unsupported */ - if(!pobj.readonly) - fprintf(stderr, "parameter type POST_PARAM_TYPE_STRINGLIST not supported yet.\n"); - break; - - case POST_PARAM_TYPE_BOOL: - if(!pobj.readonly) { - *(int *)(pobj.param_data + pobj.param->offset) = ((int) strtol(p, &p, 10)) ? 1 : 0; - _pplugin_update_parameter(&pobj); - } - break; - } - } else { - LOGMSG("Unknown post plugin parameter %s !", param); - } - } - } - - i = 0; - - while(pobj.properties_names[i]) { - free(pobj.properties_names[i]); - i++; - } - - free(pobj.properties_names); - } - - free(pobj.param_data); - } -} - -/* -post <name>:option1=value1,option2=value2... */ -static post_element_t **pplugin_parse_and_load(fe_t *fe, - int plugin_type, - const char *pchain, - int *post_elements_num) -{ - post_element_t **post_elements = NULL; - - *post_elements_num = 0; - - if(pchain && strlen(pchain)) { - char *post_chain, *freeme, *p; - - freeme = post_chain = strdup(pchain); - - while((p = xine_strsep(&post_chain, ";"))) { - - if(p && strlen(p)) { - char *plugin, *args = NULL; - xine_post_t *post; - - while(*p == ' ') - p++; - - plugin = strdup(p); - - if((p = strchr(plugin, ':'))) - *p++ = '\0'; - - if(p && (strlen(p) > 1)) - args = p; -#if 0 - post = xine_post_init(fe->xine, plugin, 0, - &fe->audio_port, &fe->video_port); -#else - if(plugin_type == XINE_POST_TYPE_VIDEO_COMPOSE) { - post = xine_post_init(fe->xine, plugin, 2, - &fe->audio_port, &fe->video_port); - } else - post = xine_post_init(fe->xine, plugin, 0, - &fe->audio_port, &fe->video_port); -#endif - - if (post && plugin_type) { - if (post->type != plugin_type) { - xine_post_dispose(fe->xine, post); - post = NULL; - } - } - - if(post) { - - if(!(*post_elements_num)) - post_elements = (post_element_t **) xine_xmalloc(sizeof(post_element_t *) * 2); - else - post_elements = (post_element_t **) - realloc(post_elements, sizeof(post_element_t *) * ((*post_elements_num) + 2)); - - post_elements[(*post_elements_num)] = (post_element_t *) - xine_xmalloc(sizeof(post_element_t)); - post_elements[(*post_elements_num)]->post = post; - post_elements[(*post_elements_num)]->name = strdup(plugin); -#if 1 - post_elements[(*post_elements_num)]->args = args ? strdup(args) : NULL; - post_elements[(*post_elements_num)]->enable = 0; -#endif - (*post_elements_num)++; - post_elements[(*post_elements_num)] = NULL; - - __pplugin_update_parameters(post, args); - } - - free(plugin); - } - } - free(freeme); - } - - return post_elements; -} - -void pplugin_parse_and_store_post(fe_t *fe, int plugin_type, - const char *post_chain) -{ - post_element_t ***_post_elements; - int *_post_elements_num; - post_element_t **posts = NULL; - int num; - - switch(plugin_type) { - case XINE_POST_TYPE_VIDEO_FILTER: - _post_elements = &fe->post_video_elements; - _post_elements_num = &fe->post_video_elements_num; - break; - case XINE_POST_TYPE_VIDEO_COMPOSE: - _post_elements = &fe->post_pip_elements; - _post_elements_num = &fe->post_pip_elements_num; - break; - case XINE_POST_TYPE_AUDIO_VISUALIZATION: - _post_elements = &fe->post_vis_elements; - _post_elements_num = &fe->post_vis_elements_num; - break; - default: - _post_elements = &fe->post_audio_elements; - _post_elements_num = &fe->post_audio_elements_num; - break; - } - - if((posts = pplugin_parse_and_load(fe, plugin_type, post_chain, &num))) { - if(*_post_elements_num) { - int i; - int ptot = *_post_elements_num + num; - - *_post_elements = (post_element_t **) realloc(*_post_elements, - sizeof(post_element_t *) * (ptot + 1)); - for(i = *_post_elements_num; i < ptot; i++) - (*_post_elements)[i] = posts[i - *_post_elements_num]; - - (*_post_elements)[i] = NULL; - (*_post_elements_num) += num; - } - else { - *_post_elements = posts; - *_post_elements_num = num; - } -#if 1 - if(SysLogLevel > 2) { - /* dump list of all loaded plugins */ - int ptot = *_post_elements_num; - int i; - char s[4096]=""; - for(i=0; i<ptot; i++) - if((*_post_elements)[i]) - if(((*_post_elements)[i])->post) { - if(((*_post_elements)[i])->enable) - strcat(s, "*"); - if(((*_post_elements)[i])->name) - strcat(s, ((*_post_elements)[i])->name); - else - strcat(s, "<no name!>"); - strcat(s, " "); - } - LOGDBG(" loaded plugins (type %d.%d): %s", - (plugin_type>>16), (plugin_type&0xffff), s); - } -#endif - } -} - - -void vpplugin_parse_and_store_post(fe_t *fe, const char *post_chain) -{ - pplugin_parse_and_store_post(fe, XINE_POST_TYPE_VIDEO_FILTER, post_chain); - pplugin_parse_and_store_post(fe, XINE_POST_TYPE_VIDEO_COMPOSE, post_chain); -} - - -void applugin_parse_and_store_post(fe_t *fe, const char *post_chain) -{ - pplugin_parse_and_store_post(fe, XINE_POST_TYPE_AUDIO_FILTER, post_chain); - pplugin_parse_and_store_post(fe, XINE_POST_TYPE_AUDIO_VISUALIZATION, post_chain); -} - - -static void _vpplugin_unwire(fe_t *fe) -{ - xine_post_out_t *vo_source; - vo_source = xine_get_video_source(fe->video_source); - (void) xine_post_wire_video_port(vo_source, fe->video_port); -} - - -static void _applugin_unwire(fe_t *fe) -{ - xine_post_out_t *ao_source; - ao_source = xine_get_audio_source(fe->audio_source); - (void) xine_post_wire_audio_port(ao_source, fe->audio_port); -} - - -static void _vpplugin_rewire_from_post_elements(fe_t *fe, post_element_t **post_elements, int post_elements_num) -{ - if(post_elements_num) { - xine_post_out_t *vo_source; - int i = 0; - - for(i = (post_elements_num - 1); i >= 0; i--) { - const char *const *outs = xine_post_list_outputs(post_elements[i]->post); - const xine_post_out_t *vo_out = xine_post_output(post_elements[i]->post, (char *) *outs); - if(i == (post_elements_num - 1)) { - LOGDBG(" wiring %10s[out] -> [in]video_out", post_elements[i]->name); - xine_post_wire_video_port((xine_post_out_t *) vo_out, fe->video_port); - } - else { - const xine_post_in_t *vo_in; - int err; - - /* look for standard input names */ - vo_in = xine_post_input(post_elements[i + 1]->post, "video"); - if( !vo_in ) - vo_in = xine_post_input(post_elements[i + 1]->post, "video in"); - - LOGDBG(" wiring %10s[out] -> [in]%-10s ", - post_elements[i]->name, post_elements[i+1]->name); - err = xine_post_wire((xine_post_out_t *) vo_out, - (xine_post_in_t *) vo_in); - } - } - - if(fe->post_pip_enable && - !strcmp(post_elements[0]->name, "mosaico") && - fe->pip_stream) { - vo_source = xine_get_video_source(fe->pip_stream); - LOGDBG(" wiring %10s[out] -> [in1]%-10s ", "pip stream", post_elements[0]->name); - xine_post_wire_video_port(vo_source, - post_elements[0]->post->video_input[1]); - } - - vo_source = xine_get_video_source(fe->video_source); - LOGDBG(" wiring %10s[out] -> [in]%-10s", "stream", post_elements[0]->name); - xine_post_wire_video_port(vo_source, - post_elements[0]->post->video_input[0]); - } -} - - -static void _applugin_rewire_from_post_elements(fe_t *fe, post_element_t **post_elements, int post_elements_num) -{ - if(post_elements_num) { - xine_post_out_t *ao_source; - int i = 0; - - for(i = (post_elements_num - 1); i >= 0; i--) { - const char *const *outs = xine_post_list_outputs(post_elements[i]->post); - const xine_post_out_t *ao_out = xine_post_output(post_elements[i]->post, (char *) *outs); - - if(i == (post_elements_num - 1)) { - LOGDBG(" wiring %10s[out] -> [in]audio_out", post_elements[i]->name); - xine_post_wire_audio_port((xine_post_out_t *) ao_out, fe->audio_port); - } - else { - const xine_post_in_t *ao_in; - int err; - - /* look for standard input names */ - ao_in = xine_post_input(post_elements[i + 1]->post, "audio"); - if( !ao_in ) - ao_in = xine_post_input(post_elements[i + 1]->post, "audio in"); - - LOGDBG(" wiring %10s[out] -> [in]%-10s ", - post_elements[i]->name, post_elements[i+1]->name); - err = xine_post_wire((xine_post_out_t *) ao_out, (xine_post_in_t *) ao_in); - } - } - - ao_source = xine_get_audio_source(fe->audio_source); - LOGDBG(" wiring %10s[out] -> [in]%-10s", "stream", post_elements[0]->name); - xine_post_wire_audio_port(ao_source, post_elements[0]->post->audio_input[0]); - } -} - -static post_element_t **_pplugin_join_deinterlace_and_post_elements(fe_t *fe, int *post_elements_num) -{ - post_element_t **post_elements; - int i = 0, j = 0, n = 0, p = 0; - static const char *order[] = {"autocrop", "thread", "tvtime", "swscale", NULL}; - - *post_elements_num = 0; - if( fe->post_video_enable ) - *post_elements_num += fe->post_video_elements_num; - - if( fe->post_pip_enable ) - *post_elements_num += fe->post_pip_elements_num; - - if( *post_elements_num == 0 ) - return NULL; - - post_elements = (post_element_t **) - xine_xmalloc(sizeof(post_element_t *) * (*post_elements_num)); - - if(fe->post_pip_enable) - for( i = 0; i < fe->post_pip_elements_num; i++ ) { - if(fe->post_pip_elements[i]->enable) - post_elements[i+j-n] = fe->post_pip_elements[i]; - else - n++; - } - - if(fe->post_video_enable) - for( j = 0; j < fe->post_video_elements_num; j++ ) { - if(fe->post_video_elements[j]->enable) { - post_elements[i+j-n] = fe->post_video_elements[j]; - } else - n++; - } - - *post_elements_num -= n; - if( *post_elements_num == 0 ) { - free(post_elements); - return NULL; - } - - /* in some special cases order is important. By default plugin order - * in post plugin chain is post plugin loading order. - * But, we want: - * - * 1. autocrop - less data to process for other plugins - * - accepts only YV12 - * 2. deinterlace - blur etc. makes deinterlacing difficult. - * - upscales chroma (YV12->YUY2) in some modes. - * 3. anything else - * - * So let's move those two to beginning ... - */ - n = 0; - while(order[p]) { - for(i = 0; i<*post_elements_num; i++) - if(!strcmp(post_elements[i]->name, order[p])) { - if(i != n) { - post_element_t *tmp = post_elements[i]; - for(j=i; j>n; j--) - post_elements[j] = post_elements[j-1]; - post_elements[n] = tmp; - LOGDBG(" moved %s to post slot %d", order[p], n); - } - n++; - break; - } - p++; - } - - return post_elements; -} - -static post_element_t **_pplugin_join_visualization_and_post_elements(fe_t *fe, int *post_elements_num) -{ - post_element_t **post_elements; - int i = 0, j = 0, n = 0; - - *post_elements_num = 0; - if( fe->post_audio_enable ) - *post_elements_num += fe->post_audio_elements_num; - - if( fe->post_vis_enable ) - *post_elements_num += fe->post_vis_elements_num; - - if( *post_elements_num == 0 ) - return NULL; - - post_elements = (post_element_t **) - xine_xmalloc(sizeof(post_element_t *) * (*post_elements_num)); - - if(fe->post_audio_enable) - for( j = 0; j < fe->post_audio_elements_num; j++ ) { - if(fe->post_audio_elements[j]->enable) - post_elements[i+j-n] = fe->post_audio_elements[j]; - else - n++; - } - - if(fe->post_vis_enable) - for( i = 0; i < fe->post_vis_elements_num; i++ ) { - if(fe->post_vis_elements[i]->enable) - post_elements[i+j-n] = fe->post_vis_elements[i]; - else - n++; - } - - *post_elements_num -= n; - if( *post_elements_num == 0 ) { - free(post_elements); - return NULL; - } - - return post_elements; -} - -static void _vpplugin_rewire(fe_t *fe) -{ - static post_element_t **post_elements; - int post_elements_num; - - post_elements = _pplugin_join_deinterlace_and_post_elements(fe, &post_elements_num); - - if( post_elements ) { - _vpplugin_rewire_from_post_elements(fe, post_elements, post_elements_num); - - free(post_elements); - } -} - -static void _applugin_rewire(fe_t *fe) -{ - static post_element_t **post_elements; - int post_elements_num; - - post_elements = _pplugin_join_visualization_and_post_elements(fe, &post_elements_num); - - if( post_elements ) { - _applugin_rewire_from_post_elements(fe, post_elements, post_elements_num); - - free(post_elements); - } -} - -void vpplugin_rewire_posts(fe_t *fe) -{ - /*TRACELINE;*/ - _vpplugin_unwire(fe); - _vpplugin_rewire(fe); -} - -void applugin_rewire_posts(fe_t *fe) -{ - /*TRACELINE;*/ - _applugin_unwire(fe); - _applugin_rewire(fe); -} - -static int _pplugin_enable_post(post_plugins_t *fe, const char *name, - const char *args, - post_element_t **post_elements, - int post_elements_num, - int *found) -{ - int i, result = 0; - - for(i=0; i<post_elements_num; i++) - if(post_elements[i]) - if(!strcmp(post_elements[i]->name, name)) { - if(post_elements[i]->enable == 0) { - post_elements[i]->enable = 1; - result = 1; - } - - *found = 1; - - if(args && *args) { - if(post_elements[i]->enable != 2) { - char *tmp = strdup(args); - __pplugin_update_parameters(post_elements[i]->post, tmp); - free(tmp); - if(post_elements[i]->args) - free(post_elements[i]->args); - post_elements[i]->args = strdup(args); - } else { - LOGDBG(" * enable post %s, parameters fixed in command line.", name); - LOGDBG(" requested: %s", args ? : "none"); - LOGDBG(" using : %s", post_elements[i]->args ? : "none"); - } - } - } - - return result; -} - -static int _vpplugin_enable_post(post_plugins_t *fe, const char *name, - const char *args, int *found) -{ - int result = 0; - if(!*found) - result = _pplugin_enable_post(fe, name, args, fe->post_video_elements, - fe->post_video_elements_num, found); - if(!*found) - result = _pplugin_enable_post(fe, name, args, fe->post_pip_elements, - fe->post_pip_elements_num, found); - return result; -} - -static int _applugin_enable_post(post_plugins_t *fe, const char *name, - const char *args, int *found) -{ - int result = 0; - if(!*found) - result = _pplugin_enable_post(fe, name, args, fe->post_audio_elements, - fe->post_audio_elements_num, found); - if(!*found) - result = _pplugin_enable_post(fe, name, args, fe->post_vis_elements, - fe->post_vis_elements_num, found); - return result; -} - -static char * _pp_name_strdup(const char *initstr) -{ - char *name = strdup(initstr), *pt; - - if(NULL != (pt = strchr(name, ':'))) - *pt = 0; - - return name; -} - -static const char * _pp_args(const char *initstr) -{ - char *pt = strchr(initstr, ':'); - if(pt && *(pt+1)) - return pt+1; - return NULL; -} - -int vpplugin_enable_post(post_plugins_t *fe, const char *initstr, - int *found) -{ - char *name = _pp_name_strdup(initstr); - const char *args = _pp_args(initstr); - - int result = _vpplugin_enable_post(fe, name, args, found); - - LOGDBG(" * enable post %s --> %s, %s", name, - *found ? "found" : "not found", - result ? "enabled" : "no action"); - - if(!*found) { - LOGDBG(" * loading post %s", initstr); - vpplugin_parse_and_store_post(fe, initstr); - result = _vpplugin_enable_post(fe, name, NULL, found); - LOGDBG(" * enable post %s --> %s, %s", name, - *found ? "found" : "not found", - result ? "enabled" : "no action"); - } - - if(result) - _vpplugin_unwire(fe); - - free(name); - return result; -} - -int applugin_enable_post(post_plugins_t *fe, const char *initstr, - int *found) -{ - const char * args = _pp_args(initstr); - char *name = _pp_name_strdup(initstr); - - int result = _applugin_enable_post(fe, name, args, found); - - LOGDBG(" * enable post %s --> %s, %s", name, - *found ? "found" : "not found", - result ? "enabled" : "no action"); - - if(!*found) { - LOGDBG(" * loading post %s", initstr); - applugin_parse_and_store_post(fe, initstr); - result = _applugin_enable_post(fe, name, NULL, found); - LOGDBG(" * enable post %s --> %s, %s", name, - *found ? "found" : "not found", - result ? "enabled" : "no action"); - } - - if(result) - _applugin_unwire(fe); - - free(name); - return result; -} - -static int _pplugin_disable_post(post_plugins_t *fe, const char *name, - post_element_t **post_elements, - int post_elements_num) -{ - int i, result = 0; - /*TRACELINE;*/ - if(post_elements) - for(i = 0; i < post_elements_num; i++) - if(post_elements[i]) - if(!name || !strcmp(post_elements[i]->name, name)) - if(post_elements[i]->enable == 1) { - post_elements[i]->enable = 0; - result = 1; - } - return result; -} - -int vpplugin_disable_post(post_plugins_t *fe, const char *name) -{ - /*TRACELINE;*/ - if(_pplugin_disable_post(fe, name, fe->post_video_elements, - fe->post_video_elements_num) || - _pplugin_disable_post(fe, name, fe->post_pip_elements, - fe->post_pip_elements_num)) { - _vpplugin_unwire(fe); - return 1; - } - return 0; -} - -int applugin_disable_post(post_plugins_t *fe, const char *name) -{ - /*TRACELINE;*/ - if(_pplugin_disable_post(fe, name, fe->post_audio_elements, - fe->post_audio_elements_num) || - _pplugin_disable_post(fe, name, fe->post_vis_elements, - fe->post_vis_elements_num)) { - _applugin_unwire(fe); - return 1; - } - return 0; -} - -static int _pplugin_unload_post(post_plugins_t *fe, const char *name, - post_element_t ***post_elements, - int *post_elements_num) -{ - /* does not unwrire plugins ! */ - int i, j, result = 0; - /*TRACELINE;*/ - - if(!*post_elements || !*post_elements_num) - return 0; - - for(i=0; i < *post_elements_num; i++) { - if((*post_elements)[i]) { - if(!name || !strcmp((*post_elements)[i]->name, name)) { - - if((*post_elements)[i]->enable == 0 || !name) { - xine_post_dispose(fe->xine, (*post_elements)[i]->post); - - free((*post_elements)[i]->name); - - if((*post_elements)[i]->args) - free((*post_elements)[i]->args); - - free((*post_elements)[i]); - - for(j=i; j < *post_elements_num - 1; j++) - (*post_elements)[j] = (*post_elements)[j+1]; - - (*post_elements_num) --; - (*post_elements)[(*post_elements_num)] = 0; - - result = 1; - i--; - - } else { - LOGDBG("Unload %s failed: plugin enabled and in use", - (*post_elements)[i]->name); - } - } - } - } - - if(*post_elements_num <= 0) { - if(*post_elements) - free(*post_elements); - *post_elements = NULL; - } - - return result; -} - -int vpplugin_unload_post(post_plugins_t *fe, const char *name) -{ - int result = vpplugin_disable_post(fe, name); - - /* unload already disabled plugins too (result=0) */ - _pplugin_unload_post(fe, name, &fe->post_video_elements, - &fe->post_video_elements_num); - _pplugin_unload_post(fe, name, &fe->post_pip_elements, - &fe->post_pip_elements_num); - - /* result indicates only unwiring condition, not unload result */ - return result; -} - -int applugin_unload_post(post_plugins_t *fe, const char *name) -{ - int result = applugin_disable_post(fe, name); - - /* unload already disabled plugins too (result=0) */ - _pplugin_unload_post(fe, name, &fe->post_audio_elements, - &fe->post_audio_elements_num); - _pplugin_unload_post(fe, name, &fe->post_vis_elements, - &fe->post_vis_elements_num); - - /* result indicates only unwiring condition, not unload result */ - return result; -} - - -/* end of post.c */ - diff --git a/xine/post.h b/xine/post.h deleted file mode 100644 index 88f3916e..00000000 --- a/xine/post.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 2003 by Dirk Meyer - * - * This file is part of xine, a unix video player. - * - * xine is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * xine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - * - * Modified for xineliboutput by Petri Hintukainen, 2006 - * - */ - -#ifndef POST_HH -#define POST_HH - -#include <xine.h> -#include <xine/xine_internal.h> -#include <xine/xineutils.h> -#include <xine/plugin_catalog.h> - -typedef struct { - xine_post_t *post; - char *name; - char *args; - int enable; /* 0 - disabled, 1 - enabled, 2 - can't disable */ -} post_element_t; - - -typedef struct post_plugins_s post_plugins_t; - -struct post_plugins_s { - - /* frontend data */ - char *static_post_plugins; /* post plugins from command line; always on */ - xine_stream_t *video_source; /* stream to take video from */ - xine_stream_t *audio_source; /* stream to take audio from */ - xine_stream_t *pip_stream; /* pip stream */ - - /* xine */ - xine_t *xine; - xine_video_port_t *video_port; - xine_audio_port_t *audio_port; - - /* post.c internal use */ - int post_audio_elements_num; - int post_video_elements_num; - int post_vis_elements_num; - int post_pip_elements_num; - - post_element_t **post_audio_elements; - post_element_t **post_video_elements; - post_element_t **post_vis_elements; /* supports only one */ - post_element_t **post_pip_elements; /* supports only one and two input */ - - int post_audio_enable; - int post_video_enable; - int post_vis_enable; - int post_pip_enable; -}; - - -void vpplugin_rewire_posts(post_plugins_t *fe); -void applugin_rewire_posts(post_plugins_t *fe); - -/* load and config post plugin(s) */ -/* post == "plugin:arg1=val1,arg2=val2;plugin2..." */ -void vpplugin_parse_and_store_post(post_plugins_t *fe, const char *post); -void applugin_parse_and_store_post(post_plugins_t *fe, const char *post); - -/* enable (and load if not loaded), but don't rewire */ -/* result indicates only unwiring condition, not enable result */ -/* -> if result <> 0, something was enabled and post chain is unwired */ -int vpplugin_enable_post(post_plugins_t *fe, const char *name, int *found); -int applugin_enable_post(post_plugins_t *fe, const char *name, int *found); - -/* disable (and unwire if found), but don't unload */ -/* result indicates only unwiring condition, not disable result */ -int vpplugin_disable_post(post_plugins_t *fe, const char *name); -int applugin_disable_post(post_plugins_t *fe, const char *name); - -/* unload (and unwire) plugin(s) */ -/* result indicates only unwiring condition, not unload result */ -int vpplugin_unload_post(post_plugins_t *fe, const char *name); -int applugin_unload_post(post_plugins_t *fe, const char *name); - -#endif - -/* end of post.h */ diff --git a/xine/post_util.h b/xine/post_util.h deleted file mode 100644 index 06154ed7..00000000 --- a/xine/post_util.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * post_util.h: post plugin utility functions - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: post_util.h,v 1.3 2008-02-28 06:10:54 phintuka Exp $ - * - */ - -#if POST_PLUGIN_IFACE_VERSION < 9 -# warning POST_PLUGIN_IFACE_VERSION < 9 not supported ! -#endif -#if POST_PLUGIN_IFACE_VERSION > 10 -# warning POST_PLUGIN_IFACE_VERSION > 10 not supported ! -#endif - -/* - * class util prototypes - */ - -static void *init_plugin(xine_t *xine, void *data); -#if POST_PLUGIN_IFACE_VERSION < 10 -static char *get_identifier(post_class_t *class_gen); -static char *get_description(post_class_t *class_gen); -static void class_dispose(post_class_t *class_gen); -#endif - -/* required from plugin: */ -static post_plugin_t *open_plugin(post_class_t *class_gen, int inputs, - xine_audio_port_t **audio_target, - xine_video_port_t **video_target); - -/* - * plugin util prototypes - */ - -static int dispatch_draw(vo_frame_t *frame, xine_stream_t *stream); -static int intercept_frame_yuy(post_video_port_t *port, vo_frame_t *frame); -static int post_draw(vo_frame_t *frame, xine_stream_t *stream); -#ifdef ENABLE_SLICED -static void dispatch_slice(vo_frame_t *vo_img, uint8_t **src); -#endif - -/* required from plugin: */ -static vo_frame_t *got_frame(vo_frame_t *frame); -static void draw_internal(vo_frame_t *frame, vo_frame_t *new_frame); - - -/* - * class utils - */ - -static void *init_plugin(xine_t *xine, void *data) -{ - post_class_t *class = (post_class_t *)malloc(sizeof(post_class_t)); - - if (!class) - return NULL; - - class->open_plugin = open_plugin; -#if POST_PLUGIN_IFACE_VERSION < 10 - class->get_identifier = get_identifier; - class->get_description = get_description; - class->dispose = class_dispose; -#else - class->identifier = PLUGIN_ID; - class->description = PLUGIN_DESCR; - class->dispose = default_post_class_dispose; -#endif - - return class; -} - -#if POST_PLUGIN_IFACE_VERSION < 10 -static char *get_identifier(post_class_t *class_gen) -{ - return PLUGIN_ID; -} - -static char *get_description(post_class_t *class_gen) -{ - return PLUGIN_DESCR; -} - -static void class_dispose(post_class_t *class_gen) -{ - free(class_gen); -} -#endif - -/* - * plugin utils - */ - -#ifdef ENABLE_SLICED -static void dispatch_slice(vo_frame_t *vo_img, uint8_t **src) -{ - if (vo_img->next->proc_slice) { - _x_post_frame_copy_down(vo_img, vo_img->next); - vo_img->next->proc_slice(vo_img->next, src); - _x_post_frame_copy_up(vo_img, vo_img->next); - } -} -#endif - -static int dispatch_draw(vo_frame_t *frame, xine_stream_t *stream) -{ - int skip; - _x_post_frame_copy_down(frame, frame->next); - skip = frame->next->draw(frame->next, stream); - _x_post_frame_copy_up(frame, frame->next); - return skip; -} - -static int intercept_frame_yuy(post_video_port_t *port, vo_frame_t *frame) -{ - return (frame->format == XINE_IMGFMT_YV12 || frame->format == XINE_IMGFMT_YUY2); -} - -static int post_draw(vo_frame_t *frame, xine_stream_t *stream) -{ - vo_frame_t *new_frame; - int skip; - - if (frame->bad_frame) - return dispatch_draw(frame, stream); - - new_frame = got_frame(frame); - - if (!new_frame) - return dispatch_draw(frame, stream); - - _x_post_frame_copy_down(frame, new_frame); - - draw_internal(frame, new_frame); - - skip = new_frame->draw(new_frame, stream); - _x_post_frame_copy_up(frame, new_frame); - new_frame->free(new_frame); - - return skip; -} - diff --git a/xine_fbfe_frontend.c b/xine_fbfe_frontend.c deleted file mode 100644 index 13d3f542..00000000 --- a/xine_fbfe_frontend.c +++ /dev/null @@ -1,321 +0,0 @@ -/* - * xine_fbfe_frontend.c: Simple front-end, framebuffer functions - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: xine_fbfe_frontend.c,v 1.19 2008-03-28 22:17:17 phintuka Exp $ - * - */ - -#include <errno.h> -#include <inttypes.h> -#include <poll.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/ioctl.h> -#include <fcntl.h> -#include <dlfcn.h> -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <sys/types.h> -#include <unistd.h> -#include <time.h> -#include <pthread.h> -#include <sched.h> - -#if defined(__linux__) -# include <linux/kd.h> -#endif - -#ifdef boolean -# define HAVE_BOOLEAN -#endif -#include <jpeglib.h> -#undef boolean - -/* framegrab ports */ -#define XINE_ENABLE_EXPERIMENTAL_FEATURES - -#include <xine.h> -#ifndef XINE_ENGINE_INTERNAL -# define XINE_ENGINE_INTERNAL -# include <xine/xine_internal.h> -# undef XINE_ENGINE_INTERNAL -#else -# include <xine/xine_internal.h> -#endif -#include <xine/xineutils.h> -#include <xine/input_plugin.h> -#include <xine/plugin_catalog.h> - -#include "xine_input_vdr.h" - -#include "xine_frontend.h" -#include "xine/post.h" - - -/* - * data - */ - -typedef struct fbfe_t { - - /* function pointers */ - frontend_t fe; - void (*update_display_size)(frontend_t*); - - /* vdr */ - fe_keypress_f keypress; - - /* xine stuff */ - xine_t *xine; - xine_stream_t *stream; - xine_stream_t *slave_stream; - input_plugin_t *input; - xine_video_port_t *video_port; - xine_video_port_t *video_port_none; - xine_audio_port_t *audio_port; - xine_audio_port_t *audio_port_none; - xine_event_queue_t *event_queue; - - post_plugins_t *postplugins; - char *fb_dev; - char *aspect_controller; - - int xine_visual_type; - fb_visual_t vis; - - uint16_t pes_buffers; - - /* display */ - int fd_tty; - - /* frontend */ - double display_ratio; - double video_aspect; - uint16_t xpos, ypos; - uint16_t width, height; - uint16_t video_width, video_height; - uint8_t overscan; - uint8_t playback_finished; - uint8_t slave_playback_finished; - uint8_t aspect; - uint8_t cropping; - uint8_t scale_video; - uint8_t fullscreen; - uint8_t vmode_switch; - uint8_t field_order; - - /* strings */ - char configfile[256]; - char modeline[256]; - -} fe_t; - -#define IS_FBFE - -/* Common (non-X11/FB) frontend functions */ -#include "xine_frontend.c" - -static void fbfe_update_display_size(frontend_t *this_gen) -{ - fe_t *this = (fe_t*)this_gen; - if(this->fullscreen) { - this->width = this->video_port->get_property(this->video_port, - VO_PROP_WINDOW_WIDTH); - this->height = this->video_port->get_property(this->video_port, - VO_PROP_WINDOW_HEIGHT); - LOGDBG("Framebuffer size after initialization: %dx%d", - this->width, this->height); - } -} - -/* - * fbfe_display_open - */ -static int fbfe_display_open(frontend_t *this_gen, int width, int height, int fullscreen, int hud, - int modeswitch, const char *modeline, int aspect, - fe_keypress_f keyfunc, const char *video_port, - int scale_video, int field_order) -{ - fe_t *this = (fe_t*)this_gen; - - if(!this) - return 0; - - if(this->fd_tty >= 0) - this->fe.fe_display_close(this_gen); - - if(keyfunc) { - this->keypress = keyfunc; - this->keypress("KBD", ""); - } - - LOGDBG("fbfe_display_open(width=%d, height=%d, fullscreen=%d, display=%s)", - width, height, fullscreen, video_port); - - this->xpos = 0; - this->ypos = 0; - this->width = width; - this->height = height; - this->fullscreen = fullscreen; - this->vmode_switch = 0/*modeswitch*/; - this->aspect = aspect; - this->cropping = 0; - this->field_order = 0/*field_order ? 1 : 0*/; - this->scale_video = scale_video; - this->overscan = 0; - strn0cpy(this->modeline, modeline, sizeof(this->modeline)); - this->display_ratio = 1.0; - - this->xine_visual_type = XINE_VISUAL_TYPE_FB; - this->vis.frame_output_cb = fe_frame_output_cb; - this->vis.user_data = this; - - this->update_display_size = fbfe_update_display_size; - - if(video_port && !strncmp(video_port, "/dev/", 5)) - this->fb_dev = strdup(video_port); - else - this->fb_dev = NULL; - -#if defined(KDSETMODE) && defined(KD_GRAPHICS) - if (isatty(STDIN_FILENO)) - this->fd_tty = dup(STDIN_FILENO); - else - this->fd_tty = open("/dev/tty", O_RDWR); - - if(this->fd_tty < 0) - LOGERR("fbfe_display_open: error opening /dev/tty"); - else if (ioctl(this->fd_tty, KDSETMODE, KD_GRAPHICS) == -1) - LOGERR("fbfe_display_open: failed to set /dev/tty to graphics mode"); -#else -# warning No support for console graphics mode - this->fd_tty = -1; -#endif - - return 1; -} - -/* - * fbfe_display_config - * - * configure windows - */ -static int fbfe_display_config(frontend_t *this_gen, int width, int height, int fullscreen, - int modeswitch, const char *modeline, int aspect, - int scale_video, int field_order) -{ - fe_t *this = (fe_t*)this_gen; - - if(!this) - return 0; - - if(this->width != width || this->height != height) { - this->width = width; - this->height = height; - } - - if(fullscreen != this->fullscreen) { - this->fullscreen = fullscreen; - } - - if(!modeswitch && strcmp(modeline, this->modeline)) { - strn0cpy(this->modeline, modeline, sizeof(this->modeline)); - /* XXX TODO - switch vmode */ -#ifdef LOG - LOGDBG("fbfe_display_config: TODO: switch vmode\n");fflush(stdout); -#endif - } - - this->vmode_switch = modeswitch; - this->aspect = aspect; - this->scale_video = scale_video; - this->field_order = field_order ? 1 : 0; - return 1; -} - -static void fbfe_interrupt(frontend_t *this_gen) -{ - /* stop fbfe_run() */ -} - -static int fbfe_run(frontend_t *this_gen) -{ - struct timeval tv; - fe_t *this = (fe_t*)this_gen; - - if(this && this->playback_finished) - return !this->playback_finished; - - tv.tv_sec = 0; - tv.tv_usec = 500*1000; - select(0, NULL, NULL, NULL, &tv); /* just sleep 500ms */ - - return !(!this || this->playback_finished); -} - -static void fbfe_display_close(frontend_t *this_gen) -{ - fe_t *this = (fe_t*)this_gen; - - if(this) { - if(this->fb_dev) { - free(this->fb_dev); - this->fb_dev = NULL; - } - if(this->xine) - this->fe.xine_exit(this_gen); - - if (this->fd_tty >= 0) { -#if defined(KDSETMODE) && defined(KD_TEXT) - if(ioctl(this->fd_tty, KDSETMODE, KD_TEXT) == -1) - LOGERR("fbfe_display_close: failed to set /dev/tty to text mode"); -#endif - close(this->fd_tty); - this->fd_tty = -1; - } - } -} - -static frontend_t *fbfe_get_frontend(void) -{ - fe_t *this = malloc(sizeof(fe_t)); - memset(this, 0, sizeof(fe_t)); - - this->fd_tty = -1; - - this->fe.fe_display_open = fbfe_display_open; - this->fe.fe_display_config = fbfe_display_config; - this->fe.fe_display_close = fbfe_display_close; - - this->fe.xine_init = fe_xine_init; - this->fe.xine_open = fe_xine_open; - this->fe.xine_play = fe_xine_play; - this->fe.xine_stop = fe_xine_stop; - this->fe.xine_close = fe_xine_close; - this->fe.xine_exit = fe_xine_exit; - this->fe.xine_is_finished = fe_is_finished; - - this->fe.fe_run = fbfe_run; - this->fe.fe_interrupt = fbfe_interrupt; - - this->fe.fe_free = fe_free; - - this->fe.grab = fe_grab; -#ifndef FE_STANDALONE - this->fe.xine_osd_command = xine_osd_command; - this->fe.xine_control = xine_control; - - this->fe.xine_queue_pes_packet = xine_queue_pes_packet; -#endif /*#ifndef FE_STANDALONE */ - - return (frontend_t*)this; -} - -/* ENTRY POINT */ -const fe_creator_f fe_creator __attribute__((visibility("default"))) = fbfe_get_frontend; - - diff --git a/xine_frontend.c b/xine_frontend.c deleted file mode 100644 index 11034235..00000000 --- a/xine_frontend.c +++ /dev/null @@ -1,1668 +0,0 @@ -/* - * xine_frontend.c: - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: xine_frontend.c,v 1.53 2008-04-13 23:11:51 phintuka Exp $ - * - */ - -#ifndef XINE_VERSION_CODE -# define XINE_VERSION_CODE (XINE_MAJOR_VERSION*10000 + \ - XINE_MINOR_VERSION*100 + \ - XINE_SUB_VERSION) -#endif - -#define NEED_x_syslog -#define LOG_MODULENAME "[vdr-fe] " -#include "logdefs.h" - -#include "xine/post.h" - -#ifdef FE_STANDALONE - /* next two symbols are dynamically linked from input plugin */ - int SysLogLevel __attribute__((visibility("default"))) = 2; /* errors and info, no debug */ - int LogToSysLog __attribute__((visibility("default"))) = 0; /* log to syslog instead of console */ - - static int verbose_xine_log = 0; -#else - int LogToSysLog __attribute__((visibility("default"))) = 1; /* dynamically linked from input plugin */ -#endif - -/* from vdr_input_plugin: */ -typedef struct { - input_plugin_t input_plugin; - vdr_input_plugin_funcs_t f; - /* ... */ -} vdr_input_plugin_t; - - -static inline char *strn0cpy(char *dest, const char *src, int n) -{ - char *s = dest; - for ( ; --n && (*dest = *src) != 0; dest++, src++) ; - *dest = 0; - return s; -} - -static int guess_cpu_count(void) -{ - static int cores = -1; - FILE *f; - - if(cores >= 0) - return cores; - - cores = 0; - if(NULL != (f = fopen("/proc/cpuinfo", "r"))) { - char buf[256]; - while (NULL != fgets(buf, 255, f)) - sscanf(buf, "processor : %d", &cores); - fclose(f); - } - cores++; - - if(cores > 1) - LOGMSG("Detected %d CPUs", cores); - else - LOGDBG("Detected single CPU. Multithreaded decoding and post processing disabled."); - - return cores; -} - -/* - * detect input plugin - */ - -static int find_input(fe_t *this) -{ - if(!this->input) { - if(!this->stream || !this->stream->input_plugin || - !this->stream->input_plugin->input_class || this->playback_finished) { - LOGMSG("find_input: stream not initialized or playback finished !"); - usleep(100*1000); - return 0; - } -#if XINE_VERSION_CODE < 10190 - if(strcmp(this->stream->input_plugin->input_class->get_identifier( - this->stream->input_plugin->input_class), - "xvdr")) { -#else - if(strcmp(this->stream->input_plugin->input_class->identifier, - "xvdr")) { -#endif - LOGMSG("find_input: current xine input plugin is not xvdr !"); - return 0; - } - this->input = this->stream->input_plugin; - } - return 1; -} - -static void *fe_control(frontend_t *this_gen, const char *cmd); - -/* - * xine callbacks - */ - -static double fe_dest_pixel_aspect(const fe_t *this, double video_pixel_aspect, - int video_width, int video_height) -{ - /*int new_cropping = 0;*/ - double result = 1.0; - - if(!this->scale_video) { - - /*#warning what to do if scaling disabled ???*/ - - /*return video_pixel_aspect;*/ - } - - switch(this->aspect) { - /* Auto */ - default: { - double correction = - ((double)video_width/(double)video_height) / - ((double)this->width/(double)this->height); - - result = video_pixel_aspect * correction; - if(result > (16.9/9.0 * (double)this->height/ - (double)this->width)) - result = (16.0/9.0 * (double)this->height/ - (double)this->width); - break; - } - /* Default */ - case 1: result = this->display_ratio; break; - - /* 4:3 */ - case 2: result = (4.0/3.0 * (double)this->height/(double)this->width); break; - /* 16:9 */ - case 3: result = (16.0/9.0 * (double)this->height/(double)this->width); break; - /* 16:10 */ - case 4: result = (16.0/10.0 * (double)this->height/(double)this->width); break; - /* Pan&Scan */ - case 5: { - double aspect_diff /*= video_pixel_aspect - 1.0*/; - /* TODO */ - /* does not work (?) */ -aspect_diff=(video_pixel_aspect*(double)video_width/(double)video_height) - 4.0 / 3.0; - if ((aspect_diff < 0.05) && (aspect_diff > -0.05)) { - result = (4.0/3.0 * (double)this->height/(double)this->width); - /*LOGDBG("diff: %f", aspect_diff);*/ - /*new_cropping = 1;*/ - } else { - result = (16.0/9.0 * (double)this->height/(double)this->width); - } - /*result = (4.0/3.0 * (double)this->height/(double)this->width);*/ - break; - } - /* center cut-out */ - case 6: { -/*#warning center cut-out mode not implemented*/ - break; - } - - } -#if 0 - if(this->cropping && !new_cropping) { - LOGDBG("pan&scan CROP OFF"); - xine_set_param(this->stream, XINE_PARAM_VO_CROP_LEFT, 0); - xine_set_param(this->stream, XINE_PARAM_VO_CROP_TOP, 72); - xine_set_param(this->stream, XINE_PARAM_VO_CROP_RIGHT, 0); - xine_set_param(this->stream, XINE_PARAM_VO_CROP_BOTTOM, 72); - this->cropping = 0; - } - if(!this->cropping && new_cropping) { - LOGDBG("pan&scan CROP ON"); - /*** Should set unscaled osd (or top & bottom will be cropped off) */ - xine_set_param(this->stream, XINE_PARAM_VO_CROP_LEFT, 0); - xine_set_param(this->stream, XINE_PARAM_VO_CROP_TOP, 0); - xine_set_param(this->stream, XINE_PARAM_VO_CROP_RIGHT, 0); - xine_set_param(this->stream, XINE_PARAM_VO_CROP_BOTTOM, 0); - this->cropping = 1; - } -#endif - - return result; -} - -static void fe_frame_output_cb (void *data, - int video_width, int video_height, - double video_pixel_aspect, - int *dest_x, int *dest_y, - int *dest_width, int *dest_height, - double *dest_pixel_aspect, - int *win_x, int *win_y) -{ - fe_t *this = (fe_t *)data; - - if (!this) - return; - - *dest_width = this->width; - *dest_height = this->height; - *dest_x = 0; -#ifndef HAVE_XV_FIELD_ORDER - *dest_y = 0 + this->field_order; -#else - *dest_y = 0; -#endif - -#if 1 - if(!this->scale_video) { - if(video_height < this->height) { - *dest_height = video_height; - *dest_y = (this->height - video_height) / 2; - } - if(video_width < this->width) { - *dest_width = video_width; - *dest_x = (this->width - video_width) / 2; - } - } -#endif - - *win_x = this->xpos; - *win_y = this->ypos; - - *dest_pixel_aspect = fe_dest_pixel_aspect(this, video_pixel_aspect, - video_width, video_height); - -#if 0 - if(this->cropping) { - *dest_pixel_aspect = *dest_pixel_aspect * (16.0/9.0)/(4.0/3.0); - *dest_y = *dest_y - 72; - *dest_height = *dest_height + 144; - } -#endif - -#if 0 - /* video_out cropping works better */ - if(this->overscan) { - int crop_x = this->overscan * this->width / 100 / 2; - int crop_y = this->overscan * this->height / 100 / 2; - *dest_x -= crop_x; - *dest_y -= crop_y; - *dest_width += crop_x; - *dest_height += crop_y; - } -#endif - - if(!this->stream) - return; - - _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_RATIO, - (int)(10000.0*video_pixel_aspect * - ((double)video_width)/((double)video_height))); - if(this->video_width != video_width || - this->video_height != video_height) { - xine_event_t event; - xine_format_change_data_t framedata; - event.type = XINE_EVENT_FRAME_FORMAT_CHANGE; - event.stream = this->stream; - event.data = &framedata; - event.data_length = sizeof(framedata); - framedata.width = video_width; - framedata.height = video_height; - framedata.aspect = 0; /* TODO */ - framedata.pan_scan = 0; - xine_event_send(this->stream, &event); - this->video_width = video_width; - this->video_height = video_height; - - /* trigger forced redraw to make cropping changes effective */ - if(this->cropping) - xine_set_param(this->stream, XINE_PARAM_VO_ZOOM_X, 100); - } - - if(this->aspect_controller) { - double video_aspect = (video_pixel_aspect * (double)video_width / (double)video_height); - double aspect_diff = video_aspect - this->video_aspect; - if ((aspect_diff > 0.05) || (aspect_diff < -0.05)) { - char cmd[4096]; - if(snprintf(cmd, sizeof(cmd), "%s %d", - this->aspect_controller, (int)(video_aspect * 10000.0)) - < sizeof(cmd)) { - LOGDBG("Aspect ratio changed, executing %s", cmd); - system(cmd); - this->video_aspect = video_aspect; - } - } - } -} - -static void xine_event_cb (void *user_data, const xine_event_t *event) -{ - fe_t *this = (fe_t *)user_data; - - switch (event->type) { - /* in local mode: vdr stream / slave stream ; in remote mode: vdr stream only */ - case XINE_EVENT_UI_PLAYBACK_FINISHED: - LOGMSG("xine_event_cb: XINE_EVENT_UI_PLAYBACK_FINISHED"); - if(this) { - if(event->stream == this->stream) - this->playback_finished = 1; - } else { - LOGMSG("xine_event_cb: NO USER DATA !"); - } - break; - default: break; - } -} - -/* - * fe_xine_init - * - * initialize xine engine, initialize audio and video ports, setup stream - */ - -#define MONO 0 -#define STEREO 1 -#define HEADPHONES 2 -#define SURROUND21 3 -#define SURROUND3 4 -#define SURROUND4 5 -#define SURROUND41 6 -#define SURROUND5 7 -#define SURROUND51 8 -#define SURROUND6 9 -#define SURROUND61 10 -#define SURROUND71 11 -#define A52_PASSTHRU 12 - -#define x_reg_num(x...) xine_config_register_num(this->xine, x) -#define x_reg_str(x...) xine_config_register_string(this->xine, x) -#define x_reg_enum(x...) xine_config_register_enum(this->xine, x) -#define x_reg_bool(x...) xine_config_register_bool(this->xine, x) - -#define x_upd_num(x...) this->xine->config->update_num(this->xine->config, x) -#define x_upd_str(x...) this->xine->config->update_string(this->xine->config, x) - -static void configure_audio_out(const fe_t *this, const char *audio_driver, const char *audio_port) -{ - /* - * alsa - */ - if(audio_driver && audio_port && !strcmp("alsa", audio_driver) && strlen(audio_port) > 0) { - - /* define possible speaker arrangements */ - /* From xine audio_alsa_out.c ; must be synchronized ! */ - static char *speaker_arrangement[] = - {"Mono 1.0", "Stereo 2.0", "Headphones 2.0", "Stereo 2.1", - "Surround 3.0", "Surround 4.0", "Surround 4.1", - "Surround 5.0", "Surround 5.1", "Surround 6.0", - "Surround 6.1", "Surround 7.1", "Pass Through", NULL}; - - x_reg_enum("audio.output.speaker_arrangement", - STEREO, - speaker_arrangement, - _("speaker arrangement"), - _("Select how your speakers are arranged, " - "this determines which speakers xine uses for sound output. " - "The individual values are:\n\n" - "Mono 1.0: You have only one speaker.\n" - "Stereo 2.0: You have two speakers for left and right channel.\n" - "Headphones 2.0: You use headphones.\n" - "Stereo 2.1: You have two speakers for left and right channel, and one " - "subwoofer for the low frequencies.\n" - "Surround 3.0: You have three speakers for left, right and rear channel.\n" - "Surround 4.0: You have four speakers for front left and right and rear " - "left and right channels.\n" - "Surround 4.1: You have four speakers for front left and right and rear " - "left and right channels, and one subwoofer for the low frequencies.\n" - "Surround 5.0: You have five speakers for front left, center and right and " - "rear left and right channels.\n" - "Surround 5.1: You have five speakers for front left, center and right and " - "rear left and right channels, and one subwoofer for the low frequencies.\n" - "Surround 6.0: You have six speakers for front left, center and right and " - "rear left, center and right channels.\n" - "Surround 6.1: You have six speakers for front left, center and right and " - "rear left, center and right channels, and one subwoofer for the low frequencies.\n" - "Surround 7.1: You have seven speakers for front left, center and right, " - "left and right and rear left and right channels, and one subwoofer for the " - "low frequencies.\n" - "Pass Through: Your sound system will receive undecoded digital sound from xine. " - "You need to connect a digital surround decoder capable of decoding the " - "formats you want to play to your sound card's digital output."), - 10, NULL, NULL); - - x_reg_str("audio.device.alsa_default_device", - "default", - _("device used for mono output"), - _("xine will use this alsa device " - "to output mono sound.\n" - "See the alsa documentation " - "for information on alsa devices."), - 10, NULL, NULL); - x_reg_str("audio.device.alsa_front_device", - "plug:front:default", - _("device used for stereo output"), - _("xine will use this alsa device " - "to output stereo sound.\n" - "See the alsa documentation " - "for information on alsa devices."), - 10, NULL, NULL); - x_reg_str("audio.device.alsa_surround51_device", - "plug:surround51:0", - _("device used for 5.1-channel output"), - _("xine will use this alsa device to output " - "5 channel plus LFE (5.1) surround sound.\n" - "See the alsa documentation for information " - "on alsa devices."), - 10, NULL, NULL); - x_reg_str("audio.device.alsa_passthrough_device", - "iec958:AES0=0x6,AES1=0x82,AES2=0x0,AES3=0x2", - _("device used for 5.1-channel output"), - _("xine will use this alsa device to output " - "undecoded digital surround sound. This can " - "be used be external surround decoders.\nSee the " - "alsa documentation for information on alsa " - "devices."), - 10, NULL, NULL); - - x_upd_str("audio.device.alsa_front_device", audio_port); - x_upd_str("audio.device.alsa_default_device", audio_port); - x_upd_str("audio.device.alsa_surround51_device", audio_port); - if(strstr(audio_port, "iec") || - strstr(audio_port, "spdif")) { - x_upd_str("audio.device.alsa_passthrough_device", audio_port); - x_upd_num("audio.output.speaker_arrangement", A52_PASSTHRU); - } else { - x_upd_num("audio.output.speaker_arrangement", - strstr(audio_port, "surround") ? SURROUND51 : STEREO); - } - } - - - /* - * OSS - */ - if(audio_driver && !strcmp("oss", audio_driver) && audio_port) { - int devnum = -2; - if(!strcmp("default", audio_port)) - devnum = -1; - if(!strncmp("/dev/dsp", audio_port, 8) && - sscanf(audio_port+8, "%d", &devnum) < 1) - devnum = -1; - if(!strncmp("/dev/sound/dsp", audio_port, 14) && - sscanf(audio_port+14, "%d", &devnum) < 1) - devnum = -1; - if(devnum > -2) { - x_reg_num("audio.device.oss_device_number", -1, - _("OSS audio device number, -1 for none"), - _("The full audio device name is created by concatenating the " - "OSS device name and the audio device number.\n" - "If you do not need a number because you are happy with " - "your system's default audio device, set this to -1.\n" - "The range of this value is -1 or 0-15. This setting is " - "ignored, when the OSS audio device name is set to \"auto\"."), - 10, NULL, NULL); - x_upd_num("audio.device.oss_device_num", devnum); - } - } -} - -static int fe_xine_init(frontend_t *this_gen, const char *audio_driver, - const char *audio_port, - const char *video_driver, - int pes_buffers, - const char *static_post_plugins) -{ - fe_t *this = (fe_t*)this_gen; - post_plugins_t *posts = NULL; - - if(!this) - return 0; - - /* - * init xine engine - */ - - if(this->xine) - this->fe.xine_exit(this_gen); - - this->stream = NULL; - this->video_port = NULL; - this->audio_port = NULL; - this->input = NULL; - - /* create a new xine and load config file */ - this->xine = xine_new(); - if(!this->xine) - return 0; - -#ifdef FE_STANDALONE - this->xine->verbosity = verbose_xine_log; -#else - this->xine->verbosity = (SysLogLevel>2); -#endif - - /*xine_register_log_cb(this->xine, xine_log_cb, this);*/ - - /* TODO: use different config file ? (vdr conf.dir/xine/config_vdr ?) */ - snprintf(this->configfile, sizeof(this->configfile), - "%s%s", xine_get_homedir(), - "/.xine/config_xineliboutput"); - this->configfile[sizeof(this->configfile)-1] = 0; - xine_config_load (this->xine, this->configfile); - - x_reg_num ("engine.buffers.video_num_buffers", - 500, - _("number of video buffers"), - _("The number of video buffers " - "(each is 8k in size) " - "xine uses in its internal queue. " - "Higher values " - "mean smoother playback for unreliable " - "inputs, but " - "also increased latency and memory " - "consumption."), - 20, NULL, NULL); - x_reg_bool("gui.osd_use_unscaled", - 0, - _("Use unscaled OSD"), - _("Use unscaled (full screen resolution) OSD if possible"), - 10, NULL, NULL); - - xine_init (this->xine); - - x_upd_num("video.device.xv_double_buffer", 1); - x_upd_num("engine.buffers.video_num_buffers", pes_buffers); - -#ifdef IS_FBFE - if(this->fb_dev) { - if(video_driver && !strcmp(video_driver, "fb")) - x_upd_str("video.device.fb_device", this->fb_dev); - else if(video_driver && !strcmp(video_driver, "DirectFB")) { - /* DirectFBInit (NULL, NULL); */ - /* DirectFBSetOption ("fbdev", video_port); */ - char *orig = getenv("DFBARGS"), *head = NULL, *tail = NULL, *tmp = NULL; - if(orig) { - orig = strdup(orig); - if(NULL != (head = strstr(orig,"fbdev="))) { - tail = strchr(head, ','); - if(head == orig) - head = NULL; - else - *head = 0; - asprintf(&tmp, "%sfbdev=%s%s", - head ? orig : "", this->fb_dev, tail ? tail : ""); - } else { - asprintf(&tmp, "fbdev=%s%s%s", this->fb_dev, orig?",":"", orig?orig:""); - } - LOGMSG("replacing environment variable DFBARGS with %s (original was %s)", - tmp, getenv("DFBARGS")); - free(orig); - } else { - asprintf(&tmp, "fbdev=%s", this->fb_dev); - LOGMSG("setting environment variable DFBARGS to %s", tmp); - } - setenv("DFBARGS", tmp, 1); - free(tmp); - /*free(orig);*/ - } - } -#endif - - this->playback_finished = 0; - - /* create video port */ - if(video_driver && !strcmp(video_driver, "none")) - this->video_port = xine_open_video_driver(this->xine, - video_driver, - XINE_VISUAL_TYPE_NONE, - NULL); - else if(video_driver && !strcmp(video_driver, "dxr3")) - this->video_port = xine_open_video_driver(this->xine, - video_driver, - XINE_VISUAL_TYPE_X11, - NULL); - else if(video_driver && !strcmp(video_driver, "aadxr3")) - this->video_port = xine_open_video_driver(this->xine, - video_driver, - XINE_VISUAL_TYPE_AA, - NULL); - else - this->video_port = xine_open_video_driver(this->xine, - video_driver, - this->xine_visual_type, - (void *) &(this->vis)); - if(!this->video_port) { - LOGMSG("fe_xine_init: xine_open_video_driver(\"%s\") failed", - video_driver?video_driver:"(NULL)"); - xine_exit(this->xine); - this->xine = NULL; - return 0; - } - - this->video_port_none = NULL; - - /* re-configure display size (DirectFB driver changes display mode in init) */ - if(this->update_display_size) - this->update_display_size(this_gen); - - /* create audio port */ - - if(audio_driver && audio_port) - configure_audio_out(this, audio_driver, audio_port); - - if(audio_driver && !strcmp(audio_driver, "auto")) { - this->audio_port = xine_open_audio_driver (this->xine, NULL, NULL); -#if XINE_VERSION_CODE < 10190 - } else if(audio_driver && !strcmp(audio_driver, "none")) { - this->audio_port = _x_ao_new_port (this->xine, NULL, 1); - this->audio_port->set_property(this->audio_port, AO_PROP_DISCARD_BUFFERS, 1); -#endif - } else { - this->audio_port = xine_open_audio_driver (this->xine, audio_driver, NULL); - } - - if(!this->audio_port && (audio_driver && !!strcmp(audio_driver, "none"))) { - LOGMSG("fe_xine_init: xine_open_audio_driver(\"%s%s%s\") failed", - audio_driver?audio_driver:"(NULL)", - audio_port?":":"", audio_port?audio_port:""); - } - - this->audio_port_none = NULL; - - /* create stream */ - - this->stream = xine_stream_new(this->xine, this->audio_port, this->video_port); - this->slave_stream = NULL; - - if(!this->stream) { - LOGMSG("fe_xine_init: xine_stream_new failed"); - - if(this->audio_port) - xine_close_audio_driver(this->xine, this->audio_port); - this->audio_port = NULL; - xine_close_video_driver(this->xine, this->video_port); - this->video_port = NULL; - xine_exit(this->xine); - this->xine = NULL; - - return 0; - } - - /* event handling */ - - this->event_queue = xine_event_new_queue (this->stream); - xine_event_create_listener_thread (this->event_queue, xine_event_cb, this); - - if(!this->event_queue) - LOGMSG("fe_xine_init: xine_event_new_queue failed"); - - /* misc. config */ - - this->pes_buffers = pes_buffers; - - posts = this->postplugins = malloc(sizeof(post_plugins_t)); - memset(posts, 0, sizeof(post_plugins_t)); - posts->xine = this->xine; - posts->audio_port = this->audio_port; - posts->video_port = this->video_port; - posts->video_source = posts->audio_source = this->stream; - - /* multithreaded decoding / post processing */ - - if(guess_cpu_count() > 1) { - int xmajor, xminor, xsub; - xine_get_version(&xmajor, &xminor, &xsub); - if(xmajor*10000 + xminor*100 + xsub < 10109) - LOGMSG("Multithreaded video decoding is not supported in xine-lib %d.%d.%d", - xmajor, xminor, xsub); - else - LOGMSG("Enabling multithreaded video decoding"); - - /* try to enable anyway, maybe someone is using patched 1.1.8 ... */ - x_upd_num("video.processing.ffmpeg_thread_count", guess_cpu_count()); -#if 0 - LOGMSG("Enabling multithreaded post processing"); - vpplugin_parse_and_store_post(posts, "thread"); -#endif - } - - /* static post plugins from command-line */ - - if(static_post_plugins && *static_post_plugins) { - int i; - LOGDBG("static post plugins (from command line): %s", static_post_plugins); - posts->static_post_plugins = strdup(static_post_plugins); - vpplugin_parse_and_store_post(posts, posts->static_post_plugins); - applugin_parse_and_store_post(posts, posts->static_post_plugins); - - for(i=0; i<posts->post_audio_elements_num; i++) - if(posts->post_audio_elements[i]) - posts->post_audio_elements[i]->enable = 2; - for(i=0; i<posts->post_video_elements_num; i++) - if(posts->post_video_elements[i]) - posts->post_video_elements[i]->enable = 2; - posts->post_video_enable = 1; - posts->post_audio_enable = 1; - } - - this->video_width = this->video_height = 0; - - return 1; -} - -/* - * fe_xine_open - * - * open xine stream - */ - -static int fe_xine_open(frontend_t *this_gen, const char *mrl) -{ - fe_t *this = (fe_t*)this_gen; - int result = 0; - char *url = NULL; - - if(!this) - return 0; - - this->input = NULL; - this->playback_finished = 1; - - asprintf(&url, "%s#nocache;demux:mpeg_block", mrl ? : "xvdr://"); - - result = xine_open(this->stream, url); - - if(!result) { - LOGMSG("fe_xine_open: xine_open(\"%s\") failed", url); - free(url); - return 0; - } - free(url); - -#if 0 - this->xine->config->update_num(this->xine->config, - "video.output.xv_double_buffer", - 1); -#endif - x_upd_num("engine.buffers.video_num_buffers", this->pes_buffers); - -#if !defined(IS_FBFE) && defined(FE_STANDALONE) - if(!strncmp(mrl, "xvdr:", 5) && strstr(mrl, "//")) { - char *name = NULL, *end; - asprintf(&name, "VDR - %s", strstr(mrl, "//")+2); - if(NULL != (end = strstr(name, ":37890"))) *end = 0; /* hide only default port */ - XStoreName(this->display, this->window[0], name); - XStoreName(this->display, this->window[1], name); - free(name); - } -#endif - - return result; -} - -/* - * post plugin handling - * - */ - -#define POST_AUDIO_VIS 0 -#define POST_AUDIO 1 -#define POST_VIDEO 2 -#define POST_VIDEO_PIP 3 - - -static void init_dummy_ports(fe_t *this, int on) -{ - if(!on) { - if(this->slave_stream) - LOGMSG("ERROR: init_dummy_ports(false) called while port is still in use !"); - - if(this->audio_port_none) - xine_close_audio_driver(this->xine, this->audio_port_none); - this->audio_port_none = NULL; - if(this->video_port_none) - xine_close_video_driver(this->xine, this->video_port_none); - this->video_port_none = NULL; - } else { - if(! this->audio_port_none) -#if XINE_VERSION_CODE < 10190 - this->audio_port_none = _x_ao_new_port (this->xine, NULL, 1); -#else - this->audio_port_none = NULL;/*xine_new_framegrab_audio_port(this->xine);*/ -#endif - if(this->audio_port_none) - this->audio_port_none->set_property(this->audio_port_none, AO_PROP_DISCARD_BUFFERS, 1); - /*LOGMSG("initialized dummy audio port %x", this->audio_port_none);*/ -#if 0 - if(! this->video_port_none) - this->video_port_none = - _x_vo_new_port(this->xine, - _x_load_video_output_plugin(this->xine, "none", - XINE_VISUAL_TYPE_NONE, NULL), - 1); - this->video_port_none->set_property(this->video_port_none, VO_PROP_DISCARD_FRAMES, 1); -#endif - } -} - -static void fe_post_unwire(fe_t *this) -{ - xine_post_out_t *vo_source = xine_get_video_source(this->stream); - xine_post_out_t *ao_source = xine_get_audio_source(this->stream); - - if(this->slave_stream && - this->slave_stream == this->postplugins->audio_source) { - LOGDBG("unwiring slave stream audio post plugins"); - init_dummy_ports(this, 1); - - if(ao_source && this->audio_port_none) - (void) xine_post_wire_audio_port(ao_source, this->audio_port_none); - - ao_source = xine_get_audio_source(this->slave_stream); - if(ao_source && this->audio_port) - (void) xine_post_wire_audio_port(ao_source, this->audio_port); - - } else { - LOGDBG("unwiring audio post plugins"); - init_dummy_ports(this, 0); - if(ao_source && this->audio_port) - (void) xine_post_wire_audio_port(ao_source, this->audio_port); - } - - if(this->slave_stream && - this->slave_stream == this->postplugins->video_source) { - LOGDBG("unwiring slave stream video post plugins"); - /*init_dummy_ports(this, 1);*/ - /*(void) xine_post_wire_video_port(vo_source, this->video_port_none);*/ - - vo_source = xine_get_video_source(this->slave_stream); - if(vo_source && this->video_port) - (void) xine_post_wire_video_port(vo_source, this->video_port); - - } else { - LOGDBG("unwiring video post plugins"); - /*init_dummy_ports(this, 0);*/ - if(vo_source && this->video_port) - (void) xine_post_wire_video_port(vo_source, this->video_port); - } -} - -static void fe_post_rewire(const fe_t *this) -{ - LOGDBG("re-wiring post plugins"); - vpplugin_rewire_posts(this->postplugins); - applugin_rewire_posts(this->postplugins); -} - -static void fe_post_unload(const fe_t *this) -{ - LOGDBG("unloading post plugins"); - vpplugin_unload_post(this->postplugins, NULL); - applugin_unload_post(this->postplugins, NULL); -} - -static void fe_post_close(const fe_t *this, const char *name, int which) -{ - post_plugins_t *posts = this->postplugins; - - if(!this) - return; - - if(name && !strcmp(name, "AudioVisualization")) { - name = NULL; - which = POST_AUDIO_VIS; - } - if(name && !strcmp(name, "Pip")) { - name = NULL; - which = POST_VIDEO_PIP; - } - - /* by name */ - if(name) { - LOGDBG("closing post plugin: %s", name); - if(applugin_unload_post(posts, name)) { - /*LOGDBG(" * rewiring audio");*/ - applugin_rewire_posts(posts); - return; - } - if(vpplugin_unload_post(posts, name)) { - /*LOGDBG(" * rewiring video");*/ - vpplugin_rewire_posts(posts); - return; - } - return; - } - - /* by type */ - if(which == POST_AUDIO_VIS || which < 0) { /* audio visualization */ - if(posts->post_vis_elements_num && - posts->post_vis_elements && - posts->post_vis_elements[0]) { - LOGDBG("Closing audio visualization post plugins"); - if(applugin_unload_post(posts, posts->post_vis_elements[0]->name)) { - /*LOGDBG(" * rewiring audio");*/ - applugin_rewire_posts(posts); - } - } - } - - if(which == POST_AUDIO || which < 0) { /* audio effect(s) */ - LOGDBG("Closing audio post plugins"); - if(applugin_disable_post(posts, NULL)) { - /*LOGDBG(" * rewiring audio");*/ - applugin_rewire_posts(posts); - } - } - if(which == POST_VIDEO || which < 0) { /* video effect(s) */ - LOGDBG("Closing video post plugins"); - if(vpplugin_unload_post(posts, NULL)) { - /*LOGDBG(" * rewiring video");*/ - vpplugin_rewire_posts(posts); - } - } - - if(which == POST_VIDEO_PIP || which < 0) { /* Picture-In-Picture */ - if(posts->post_pip_elements_num && - posts->post_pip_elements && - posts->post_pip_elements[0]) { - LOGDBG("Closing PIP (mosaico) post plugins"); - if(vpplugin_unload_post(posts, "mosaico")) { - /*LOGDBG(" * rewiring video");*/ - vpplugin_rewire_posts(posts); - } - } - } -} - -static int get_opt_val(const char *s, const char *opt) -{ - int val = -1; - const char *pt = strstr(s, opt); - if(pt) - if(1 == sscanf(pt+strlen(opt)+1, "%d", &val)) - return val; - return -1; -} - -static void fe_post_open(const fe_t *this, const char *name, const char *args) -{ - post_plugins_t *posts = this->postplugins; - char initstr[1024]; - int found = 0; - - if(!this || !this->xine || !this->stream || !name) - return; - - /* pip */ - if(!strcmp(name, "Pip")) { - posts->post_pip_enable = 1; - name = "mosaico"; - if(!posts->post_pip_elements || - !posts->post_vis_elements[0] || - !posts->post_vis_elements[0]->enable) - LOGMSG("enabling picture-in-picture (\"%s\") post plugin", initstr); - } - - if(args) { - snprintf(initstr, sizeof(initstr), "%s:%s", name, args); - initstr[sizeof(initstr)-1] = 0; - } else - strn0cpy(initstr, name, sizeof(initstr)); - - /* swscale aspect ratio */ - if (!strcmp(name, "swscale")) { - char *pt = strstr(initstr, "output_aspect=auto"); - if (pt) { - char tmp[16]; - double r = 0.0; - pt += 14; - switch(this->aspect) { - case 0: - case 1: /* */ r = this->display_ratio * (double)this->width / (double)this->height; break; - case 2: /* 4:3 */ r = 4.0/3.0; break; - case 3: /* 16:9 */ r = 16.0/9.0; break; - case 4: /* 16:10 */ r = 16.0/10.0; break; - } - /* in finnish locale decimal separator is "," - same as post plugin parameter separator :( */ - sprintf(tmp, "%04d", (int)(r*1000.0)); - strncpy(pt, tmp, 4); - } - } - - LOGDBG("opening post plugin: %s", initstr); - - /* close old audio visualization plugin */ - if(!strcmp(name,"goom") || - !strcmp(name,"oscope") || - !strcmp(name,"fftscope") || - !strcmp(name,"fftgraph") || - !strcmp(name,"fooviz")) { - - /* close if changed */ - if(posts->post_vis_elements_num && - posts->post_vis_elements && - posts->post_vis_elements[0] && - strcmp(name, posts->post_vis_elements[0]->name)) { - - fe_post_close(this, NULL, POST_AUDIO_VIS); - } - - if(!found && applugin_enable_post(posts, initstr, &found)) { - posts->post_vis_enable = 1; - applugin_rewire_posts(posts); - - // goom wants options thru config ... - if(args && !strcmp(name,"goom")) { - int val; - if((val = get_opt_val(initstr, "fps")) > 0) - x_upd_num ("effects.goom.fps", val ); - if((val = get_opt_val(initstr, "width")) > 0) - x_upd_num ("effects.goom.width", val); - if((val = get_opt_val(initstr, "height")) > 0) - x_upd_num ("effects.goom.height", val); - //if((val = get_opt_val(initstr, "csc_method"))>0) - // this->xine->config->update_enum (this->xine->config, "effects.goom.csc_method", val); - } - } - - } else { - - /* video filters */ - if(strcmp(name, "audiochannel") && - strcmp(name, "volnorm") && - strcmp(name, "stretch") && - strcmp(name, "upmix_mono") && - strcmp(name, "upmix") && - vpplugin_enable_post(posts, initstr, &found)) { - - posts->post_video_enable = 1; - vpplugin_rewire_posts(posts); - } - - /* audio filters */ - if(!found && applugin_enable_post(posts, initstr, &found)) { - posts->post_audio_enable = 1; - applugin_rewire_posts(posts); - } - } - - if(!found) - LOGMSG("Can't load post plugin %s", name); - else - LOGDBG("Post plugin %s loaded and wired", name); -} - -static int fe_xine_play(frontend_t *this_gen) -{ - fe_t *this = (fe_t*)this_gen; - vdr_input_plugin_t *input_vdr; - - if(!this) - return 0; - - fe_post_rewire(this); - - this->input = NULL; - this->playback_finished = xine_play(this->stream, 0, 0) ? 0 : 1; - - if(!this->input && !find_input(this)) - return -1; - - input_vdr = (vdr_input_plugin_t *)this->input; - input_vdr->f.xine_input_event = this->keypress; - input_vdr->f.fe_control = fe_control; - input_vdr->f.fe_handle = this_gen; - - if(this->playback_finished) - LOGMSG("Error playing xvdr:// !"); - - return !this->playback_finished; -} - -static int fe_xine_stop(frontend_t *this_gen) -{ - fe_t *this = (fe_t*)this_gen; - - if(!this) - return 0; - - this->input = NULL; - this->playback_finished = 1; - - xine_stop(this->stream); - - fe_post_unwire(this); - - return 1; -} - -static void fe_xine_close(frontend_t *this_gen) -{ - fe_t *this = (fe_t*)this_gen; - - if(!this) - return; - - if (this && this->xine) { -#ifndef FE_STANDALONE - if(this->input) { - vdr_input_plugin_t *input_vdr; - input_vdr = (vdr_input_plugin_t *)this->input; - input_vdr->f.xine_input_event = NULL; - } -#endif - - fe_xine_stop(this_gen); - - fe_post_unload(this); - - xine_close(this->stream); - if(this->postplugins->pip_stream) - xine_close(this->postplugins->pip_stream); - } -} - -static void fe_xine_exit(frontend_t *this_gen) -{ - fe_t *this = (fe_t*)this_gen; - - if (this && this->xine) { - - if(this->input || !this->playback_finished) - fe_xine_close(this_gen); - fe_post_unload(this); - - xine_config_save (this->xine, this->configfile); - if(this->event_queue) - xine_event_dispose_queue(this->event_queue); - this->event_queue = NULL; - - if(this->stream) - xine_dispose(this->stream); - this->stream = NULL; - - if(this->postplugins->pip_stream) - xine_dispose(this->postplugins->pip_stream); - this->postplugins->pip_stream = NULL; - - if(this->slave_stream) - xine_dispose(this->slave_stream); - this->slave_stream = NULL; - - if(this->audio_port) - xine_close_audio_driver(this->xine, this->audio_port); - this->audio_port = NULL; - - init_dummy_ports(this, 0); - - if(this->video_port) - xine_close_video_driver(this->xine, this->video_port); - this->video_port = NULL; - - if(this->postplugins->static_post_plugins) - free(this->postplugins->static_post_plugins); - free(this->postplugins); - this->postplugins = NULL; - - xine_exit(this->xine); - this->xine = NULL; - } -} - -static void fe_free(frontend_t *this_gen) -{ - if (this_gen) { - fe_t *this = (fe_t*)this_gen; - this->fe.fe_display_close(this_gen); - free(this); - } -} - -static int fe_is_finished(frontend_t *this_gen, int slave_stream) -{ - fe_t *this = (fe_t*)this_gen; - - if(!this || this->playback_finished) - return 1; - - if(slave_stream) { - if(!this->slave_stream || this->slave_playback_finished) - return 1; - } - - return 0; -} - -/************************** hooks to input plugin ****************************/ - -#ifndef FE_STANDALONE - -static int xine_control(frontend_t *this_gen, const char *cmd) -{ - fe_t *this = (fe_t*)this_gen; - vdr_input_plugin_t *input_vdr; - - if(!this->input && !find_input(this)) - return -1; - - input_vdr = (vdr_input_plugin_t *)this->input; - return input_vdr->f.push_input_control(this->input, cmd); -} - -static int xine_osd_command(frontend_t *this_gen, struct osd_command_s *cmd) { - fe_t *this = (fe_t*)this_gen; - vdr_input_plugin_t *input_vdr; - - if(!this->input && !find_input(this)) - return -1; - - input_vdr = (vdr_input_plugin_t *)this->input; - return input_vdr->f.push_input_osd(this->input, cmd); -} - -static int xine_queue_pes_packet(frontend_t *this_gen, const char *data, int len) -{ - fe_t *this = (fe_t*)this_gen; - vdr_input_plugin_t *input_vdr; - - if(!this->input && !find_input(this)) - return 0/*-1*/; - -#if 0 - if(len<6) { - LOGMSG("xine_queue_pes_packet: len == %d, too short!", len); - abort(); - } - /* must contain single pes packet and nothing else */ - if(data[0] || data[1] || (data[2] != 1)) { - static int counter=0; - counter++; - LOGMSG("xine_queue_pes_packet: packet not starting with 00 00 01 \n" - " packet #%d, size=%d : %02x %02x %02x %02x %02x %02x\n", - counter, len, - data[0], data[1], data[2], data[3], data[4], data[5]); - abort(); - } -#endif - - input_vdr = (vdr_input_plugin_t *)this->input; - return input_vdr->f.push_input_write(this->input, data, len); -} - -#else /* #ifndef FE_STANDALONE */ - -static void process_xine_keypress(input_plugin_t *input, - const char *map, const char *key, - int repeat, int release) -{ - /* from UI --> input plugin --> vdr */ - LOGDBG("Keypress: %s %s %s %s", - map, key, repeat?"Repeat":"", release?"Release":""); - if(input) { - vdr_input_plugin_t *input_vdr = (vdr_input_plugin_t *)input; - if(input_vdr->f.input_control) { - input_vdr->f.input_control(input, map, key, repeat, release); - } else { - LOGMSG("Keypress --- NO HANDLER SET"); - } - } else { - LOGMSG("Keypress --- NO PLUGIN FOUND"); - } -} - -#endif /* #ifndef FE_STANDALONE */ - -/* - * Control messages from input plugin - */ -static void *fe_control(frontend_t *this_gen, const char *cmd) -{ - fe_t *this = (fe_t*)this_gen; - post_plugins_t *posts; - - /*LOGDBG("fe_control(\"%s\")", cmd);*/ - - if(!cmd || !this) { - LOGMSG("fe_control(0x%lx,0x%lx) : invalid argument", - (unsigned long int)this_gen, (unsigned long int)cmd); - return NULL; - } - - posts = this->postplugins; - - if(!posts) { - LOGMSG("fe_control : this->posts == NULL"); - return NULL; - } - - if(!strncmp(cmd, "SLAVE CLOSED", 16)) { - /*LOGMSG("fe_control : slave closed");*/ - if(this->slave_stream) - fe_control(this_gen, "SLAVE 0x0\r\n"); - init_dummy_ports(this, 0); - - } else if(!strncmp(cmd, "SLAVE 0x", 8)) { - unsigned long pt; - if(1 == sscanf(cmd, "SLAVE 0x%lx", &pt)) { - xine_stream_t *slave_stream = (xine_stream_t*)pt; - if(this->slave_stream != slave_stream) { - - fe_post_unwire(this); - - if(this->slave_stream) { - /*xine_post_out_t *vo_source = xine_get_video_source(posts->slave_stream);*/ - if(this->slave_stream == this->postplugins->audio_source) { - xine_post_out_t *ao_source = xine_get_audio_source(this->slave_stream); - LOGMSG("unwiring slave stream from output"); - /*(void) xine_post_wire_video_port(vo_source, this->video_port_none);*/ - (void) xine_post_wire_audio_port(ao_source, this->audio_port_none); - } - } - - this->slave_stream = slave_stream; - - this->postplugins->video_source = this->postplugins->audio_source = - this->slave_stream ?: this->stream; - if(strstr(cmd, "Video")) /* video only, audio from VDR */ - this->postplugins->audio_source = this->stream; - if(strstr(cmd, "Audio")) /* audio only, video from VDR */ - this->postplugins->video_source = this->stream; - - if(this->slave_stream) - fe_post_unwire(this); - - fe_post_rewire(this); - } - this->slave_playback_finished = !slave_stream; - } - - } else if(!strncmp(cmd, "ENDOFSTREAM", 11)) { - if(this->slave_stream) - this->slave_playback_finished = 1; - - } else if(!strncmp(cmd, "SUBSTREAM ", 10)) { - unsigned int pid; - int x, y, w, h; - if(5 == sscanf(cmd, "SUBSTREAM 0x%x %d %d %d %d", &pid, &x, &y, &w, &h)) { - char mrl[256]; - if(!posts->pip_stream) - posts->pip_stream = xine_stream_new(this->xine, - this->audio_port, - this->video_port); - LOGMSG(" PIP %d: %dx%d @ (%d,%d)", pid & 0x0f, w, h, x, y); - LOGMSG("create pip stream done"); - sprintf(mrl, "xvdr+slave://0x%lx#nocache;demux:mpeg_block", - (unsigned long int)this); - if(!xine_open(posts->pip_stream, mrl) || - !xine_play(posts->pip_stream, 0, 0)) { - LOGERR(" pip stream open/play failed"); - } else { - char params[64]; - sprintf(params, "pip_num=1,x=%d,y=%d,w=%d,h=%d", x,y,w,h); - fe_post_open(this, "Pip", params); - return posts->pip_stream; - } - } - fe_post_close(this, NULL, POST_VIDEO_PIP); - if(posts->pip_stream) { - xine_close(posts->pip_stream); - xine_dispose(posts->pip_stream); - posts->pip_stream = NULL; - } - return NULL; - - } else if(!strncmp(cmd, "POST ", 5)) { - char *name = strdup(cmd+5), *args = name, *pt; - - if(NULL != (pt=strchr(name, '\r'))) - *pt = 0; - if(NULL != (pt=strchr(name, '\n'))) - *pt = 0; - - while(*args && *args != ' ') /* skip name */ - args++; - if(*args /*== ' '*/) - *args++ = 0; - - while(*args && *args == ' ') /* skip whitespace between name and args */ - args++; - - /*this->stream->xine->port_ticket->acquire(this->stream->xine->port_ticket, 0);*/ - /* - locks local frontend at startup */ - if(!strncmp(args, "On", 2)) { - args += 2; - while(*args == ' ') - args++; - /*LOGDBG(" POST: %s On \"%s\"", name, args);*/ - fe_post_open(this, name, args); - } else if(!strncmp(args, "Off", 3)) { - /*LOGDBG(" POST: %s Off (name len=%d), name => int = %d", name, strlen(name), atoi(name));*/ - if(strlen(name) == 1) - fe_post_close(this, NULL, atoi(name)); - else - fe_post_close(this, name, -1); - } else { - LOGMSG("fe_control: POST: unknown command %s", cmd); - } - /*this->stream->xine->port_ticket->release(this->stream->xine->port_ticket, 0);*/ - /* - locks local frontend at startup */ - free(name); - return NULL; - - } else if(!strncmp(cmd, "GRAB ", 5)) { - int quality, width, height, jpeg, size=0; - jpeg = !strncmp(cmd+5,"JPEG",4); - if(3 == sscanf(cmd+5+4, "%d %d %d", &quality, &width, &height)) { - grab_data_t *result = (grab_data_t*)malloc(sizeof(grab_data_t)); - result->data = this->fe.grab((frontend_t*)this, &size, - jpeg, quality, width, height); - if(result->data && (result->size=size)>0) - return result; - free(result->data); - free(result); - } - - } else if(!strncmp(cmd, "OVERSCAN ", 9)) { - int overscan; - if(1 == sscanf(cmd+9, "%d", &overscan)) { - int crop_x = overscan * this->width / 100 / 2; - int crop_y = overscan * this->height / 100 / 2; - this->overscan = overscan; - xine_set_param(this->stream, XINE_PARAM_VO_CROP_LEFT, crop_x); - xine_set_param(this->stream, XINE_PARAM_VO_CROP_TOP, crop_y); - xine_set_param(this->stream, XINE_PARAM_VO_CROP_RIGHT, crop_x); - xine_set_param(this->stream, XINE_PARAM_VO_CROP_BOTTOM, crop_y); - /* trigger forced redraw to make changes effective */ - xine_set_param(this->stream, XINE_PARAM_VO_ZOOM_X, 100); - } - } else if(!strncmp(cmd, "VO_ASPECT ", 10)) { - int vo_aspect_ratio; - if(1 == sscanf(cmd+10, "%d", &vo_aspect_ratio)) { - xine_set_param(this->stream, XINE_PARAM_VO_ASPECT_RATIO, vo_aspect_ratio); - } - } - - - return NULL; -} - -/* - * --- RgbToJpeg ------------------------------------------------------------- - * - * source: vdr-1.3.42, tools.c - * modified to accept YUV data - * - * TODO: remote version: send to ctrl stream - * - move to xine_input_vdr ? - */ - -#define JPEGCOMPRESSMEM 500000 - -typedef struct tJpegCompressData_s { - int size; - unsigned char *mem; -} tJpegCompressData; - -static void JpegCompressInitDestination(const j_compress_ptr cinfo) -{ - tJpegCompressData *jcd = (tJpegCompressData *)cinfo->client_data; - if (jcd) { - cinfo->dest->free_in_buffer = jcd->size = JPEGCOMPRESSMEM; - cinfo->dest->next_output_byte = jcd->mem = - (unsigned char *)malloc(jcd->size); - } -} - -static boolean JpegCompressEmptyOutputBuffer(const j_compress_ptr cinfo) -{ - tJpegCompressData *jcd = (tJpegCompressData *)cinfo->client_data; - if (jcd) { - int Used = jcd->size; - jcd->size += JPEGCOMPRESSMEM; - jcd->mem = (unsigned char *)realloc(jcd->mem, jcd->size); - if (jcd->mem) { - cinfo->dest->next_output_byte = jcd->mem + Used; - cinfo->dest->free_in_buffer = jcd->size - Used; - return TRUE; - } - } - return FALSE; -} - -static void JpegCompressTermDestination(const j_compress_ptr cinfo) -{ - tJpegCompressData *jcd = (tJpegCompressData *)cinfo->client_data; - if (jcd) { - int Used = cinfo->dest->next_output_byte - jcd->mem; - if (Used < jcd->size) { - jcd->size = Used; - jcd->mem = (unsigned char *)realloc(jcd->mem, jcd->size); - } - } -} - -static char *fe_grab(frontend_t *this_gen, int *size, int jpeg, - int quality, int width, int height) -{ - struct jpeg_destination_mgr jdm; - struct jpeg_compress_struct cinfo; - struct jpeg_error_mgr jerr; - tJpegCompressData jcd; - - fe_t *this = (fe_t*)this_gen; - vo_frame_t *frame, *img; - -#ifndef PPM_SUPPORTED - if(!jpeg) { - LOGMSG("fe_grab: PPM grab not implemented"); - return 0; - } -#else - /* #warning TODO: convert to RGB PPM */ -#endif - - if(!this->input && !find_input(this)) - return 0; - - LOGDBG("fe_grab: grabbing %s %d %dx%d", - jpeg ? "JPEG" : "PNM", quality, width, height); - - if (quality < 0) - quality = 0; - else if(quality > 100) - quality = 100; - - this->stream->xine->port_ticket->acquire(this->stream->xine->port_ticket, 0); - frame = this->stream->video_out->get_last_frame (this->stream->video_out); - if(frame) - frame->lock(frame); - this->stream->xine->port_ticket->release(this->stream->xine->port_ticket, 0); - - if(!frame) - return NULL; - - // convert yuy2 frames to yv12 - if (frame->format == XINE_IMGFMT_YUY2) { - this->stream->xine->port_ticket->acquire(this->stream->xine->port_ticket, 0); - img = this->stream->video_out->get_frame (this->stream->video_out, - frame->width, frame->height, - frame->ratio, XINE_IMGFMT_YV12, - VO_BOTH_FIELDS); - this->stream->xine->port_ticket->release(this->stream->xine->port_ticket, 0); - - if(!img) { - LOGMSG("fe_grab: get_frame failed"); - frame->free(frame); - return NULL; - } - - init_yuv_conversion(); - yuy2_to_yv12(frame->base[0], frame->pitches[0], - img->base[0], img->pitches[0], - img->base[1], img->pitches[1], - img->base[2], img->pitches[2], - frame->width, frame->height); - - frame->free(frame); - frame = img; - } - - /* #warning TODO: no scaling implemented */ - if(width != frame->width) - width = frame->width; - if(height != frame->height) - height = frame->height; - - /* Compress JPEG */ - - jdm.init_destination = JpegCompressInitDestination; - jdm.empty_output_buffer = JpegCompressEmptyOutputBuffer; - jdm.term_destination = JpegCompressTermDestination; - - cinfo.err = jpeg_std_error(&jerr); - jpeg_create_compress(&cinfo); - cinfo.dest = &jdm; - - cinfo.client_data = &jcd; - cinfo.image_width = width; - cinfo.image_height = height; - - cinfo.input_components = 3; - cinfo.in_color_space = JCS_YCbCr; - - switch (frame->format) { - case XINE_IMGFMT_YV12: { - JSAMPARRAY pp[3]; - JSAMPROW *rpY = (JSAMPROW*)malloc(sizeof(JSAMPROW) * height); - JSAMPROW *rpU = (JSAMPROW*)malloc(sizeof(JSAMPROW) * height); - JSAMPROW *rpV = (JSAMPROW*)malloc(sizeof(JSAMPROW) * height); - int k; - - jpeg_set_defaults(&cinfo); - jpeg_set_quality(&cinfo, quality, TRUE); - cinfo.raw_data_in = TRUE; - - jpeg_set_colorspace(&cinfo, JCS_YCbCr); - cinfo.comp_info[0].h_samp_factor = - cinfo.comp_info[0].v_samp_factor = 2; - cinfo.comp_info[1].h_samp_factor = - cinfo.comp_info[1].v_samp_factor = - cinfo.comp_info[2].h_samp_factor = - cinfo.comp_info[2].v_samp_factor = 1; - jpeg_start_compress(&cinfo, TRUE); - - for (k = 0; k < height; k+=2) { - rpY[k] = frame->base[0] + k*frame->pitches[0]; - rpY[k+1] = frame->base[0] + (k+1)*frame->pitches[0]; - rpU[k/2] = frame->base[1] + (k/2)*frame->pitches[1]; - rpV[k/2] = frame->base[2] + (k/2)*frame->pitches[2]; - } - for (k = 0; k < height; k+=2*DCTSIZE) { - pp[0] = &rpY[k]; - pp[1] = &rpU[k/2]; - pp[2] = &rpV[k/2]; - jpeg_write_raw_data(&cinfo, pp, 2*DCTSIZE); - } - free(rpY); - free(rpU); - free(rpV); - break; - } -#if 0 - case XINE_IMGFMT_RGB: { - JSAMPROW rp[height]; - int rs, k; - - cinfo.in_color_space = JCS_RGB; - - jpeg_set_defaults(&cinfo); - jpeg_set_quality(&cinfo, quality, TRUE); - jpeg_start_compress(&cinfo, TRUE); - - rs = frame->pitches[0]; - for (k = 0; k < height; k++) - rp[k] = frame->base[0] + k*rs; - jpeg_write_scanlines(&cinfo, rp, height); - break; - } -#endif - default: - LOGMSG("fe_grab: grabbing failed (unsupported image format %d)", - frame->format); - break; - } - - jpeg_finish_compress(&cinfo); - jpeg_destroy_compress(&cinfo); - frame->free(frame); - - *size = jcd.size; - return (char*) jcd.mem; -} - - -#ifdef FE_STANDALONE - -/* frontend main() */ - -#include "xine_frontend_main.c" - -#endif /* #ifdef FE_STANDALONE */ - diff --git a/xine_frontend.h b/xine_frontend.h deleted file mode 100644 index 09660b89..00000000 --- a/xine_frontend.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * xine_frontend.h: - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: xine_frontend.h,v 1.7 2008-03-28 22:17:17 phintuka Exp $ - * - */ - -#ifndef _XINE_FRONTEND_H -#define _XINE_FRONTEND_H - -#ifdef __cplusplus -extern "C" { -#endif - -#define FE_VERSION_STR XINELIBOUTPUT_VERSION /*"1.0.0pre1"*/ - -typedef void (*fe_keypress_f)(const char *keymap, const char *name); - -typedef struct frontend_config_s frontend_config_t; -typedef struct frontend_s frontend_t; - -#if 0 -struct frontend_config_s { - /* Display */ - int width; - int height; - int fullscreen; - int modeswitch; - char *modeline; - int aspect; - - char *video_port; - - int scale_video; - int field_order; - - fe_keypress_f keypresshandler; - - /* Xine engine */ - char *audio_driver; - char *audio_port; - char *video_driver; - int pes_buffers; - int priority; -}; -#endif - -struct frontend_s { - /* Display */ - int (*fe_display_open)(frontend_t*, int winwidth, int winheight, - int fullscreen, int hud, int modeswitch, const char *modeline, - int aspect, fe_keypress_f keypresshandler, - const char *video_port, - int scale_video, int field_order); - int (*fe_display_config)(frontend_t *, int width, int height, - int fullscreen, - int modeswitch, const char *modeline, - int aspect, int scale_video, int field_order); - void (*fe_display_close)(frontend_t*); - - /* Xine engine */ - int (*xine_init)(frontend_t*, - const char *audio_driver, - const char *audio_port, - const char *video_driver, - int pes_buffers, - const char *static_post); - int (*xine_open)(frontend_t*, const char *mrl); - int (*xine_play)(frontend_t*); - int (*xine_stop)(frontend_t*); - void (*xine_close)(frontend_t*); - void (*xine_exit)(frontend_t*); - - /* Execution control */ - int (*fe_run)(frontend_t*); - void (*fe_interrupt)(frontend_t*); - void (*fe_free)(frontend_t*); - - /* Data transfer */ - int (*xine_is_finished)(frontend_t*, int slave_stream); - int (*xine_osd_command)(frontend_t*, struct osd_command_s *cmd); - int (*xine_control)(frontend_t*, const char *cmd); - int (*xine_queue_pes_packet)(frontend_t*, const char *data, int len); - - char *(*grab)(frontend_t*, int *size, int jpeg, int quality, - int width, int height); -#if 0 - frontend_config_t config; -#endif -}; - -typedef frontend_t *(*fe_creator_f)(void); - -#ifdef __cplusplus -} /* extern "C" { */ -#endif - -#endif /* _XINE_FRONTEND_H */ - diff --git a/xine_frontend_lirc.c b/xine_frontend_lirc.c deleted file mode 100644 index a9c4e251..00000000 --- a/xine_frontend_lirc.c +++ /dev/null @@ -1,265 +0,0 @@ -/* - * xine_frontend_lirc.c: Forward (local) lirc keys to VDR (server) - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: xine_frontend_lirc.c,v 1.10 2008-02-05 00:56:43 phintuka Exp $ - * - */ -/* - * - * Almost directly copied from vdr-1.4.3-2 (lirc.c : cLircRemote) - * - */ -/* - * lirc.c: LIRC remote control - * - * See the main source file 'vdr.c' for copyright information and - * how to reach the author. - * - * LIRC support added by Carsten Koch <Carsten.Koch@icem.de> 2000-06-16. - * - * $Id: xine_frontend_lirc.c,v 1.10 2008-02-05 00:56:43 phintuka Exp $ - */ - - -#include <stdint.h> -#include <netinet/in.h> -#include <sys/socket.h> -#include <sys/un.h> - -#define REPEATDELAY 350 /* ms */ -#define REPEATFREQ 100 /* ms */ -#define REPEATTIMEOUT 500 /* ms */ -#define RECONNECTDELAY 3000 /* ms */ - -#define LIRC_KEY_BUF 30 -#define LIRC_BUFFER_SIZE 128 -#define MIN_LIRCD_CMD_LEN 5 - -/* static data */ -static pthread_t lirc_thread; -static volatile char *lirc_device_name = NULL; -static volatile int fd_lirc = -1; -static int lirc_repeat_emu = 0; - -#ifndef IS_FBFE -static void sxfe_toggle_fullscreen(sxfe_t *this); -#endif - -static uint64_t time_ms() -{ - struct timeval t; - if (gettimeofday(&t, NULL) == 0) - return ((uint64_t)t.tv_sec) * 1000ULL + t.tv_usec / 1000ULL; - return 0; -} - -static uint64_t elapsed(uint64_t t) -{ - return time_ms() - t; -} - -static void lircd_connect(void) -{ - struct sockaddr_un addr; - - if(fd_lirc >= 0) { - close(fd_lirc); - fd_lirc = -1; - } - - if(!lirc_device_name) { - LOGDBG("no lirc device given"); - return; - } - - addr.sun_family = AF_UNIX; - strn0cpy(addr.sun_path, (char*)lirc_device_name, sizeof(addr.sun_path)); - - if ((fd_lirc = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { - LOGERR("lirc error: socket() < 0"); - return; - } - - if (connect(fd_lirc, (struct sockaddr *)&addr, sizeof(addr))) { - LOGERR("lirc error: connect(%s) < 0", lirc_device_name); - close(fd_lirc); - fd_lirc = -1; - return; - } -} - -static void *lirc_receiver_thread(void *fe) -{ - int timeout = -1; - uint64_t FirstTime = time_ms(); - uint64_t LastTime = time_ms(); - char buf[LIRC_BUFFER_SIZE]; - char LastKeyName[LIRC_KEY_BUF] = ""; - int repeat = 0; - - LOGMSG("lirc forwarding started"); - - nice(-1); - lircd_connect(); - - while(lirc_device_name && fd_lirc >= 0) { - fd_set set; - int ready, ret = -1; - FD_ZERO(&set); - FD_SET(fd_lirc, &set); - - if (timeout >= 0) { - struct timeval tv; - tv.tv_sec = timeout / 1000; - tv.tv_usec = (timeout % 1000) * 1000; - ready = select(FD_SETSIZE, &set, NULL, NULL, &tv) > 0 && FD_ISSET(fd_lirc, &set); - } else { - ready = select(FD_SETSIZE, &set, NULL, NULL, NULL) > 0 && FD_ISSET(fd_lirc, &set); - } - - if(ready < 0) { - LOGMSG("LIRC connection lost ?"); - break; - } - - if(ready) { - - do { - errno = 0; - ret = read(fd_lirc, buf, sizeof(buf)); - } while(ret < 0 && errno == EINTR); - - if (ret <= 0 ) { - /* try reconnecting */ - LOGERR("LIRC connection lost"); - lircd_connect(); - while(lirc_device_name && fd_lirc < 0) { - sleep(RECONNECTDELAY/1000); - lircd_connect(); - } - if(fd_lirc >= 0) - LOGMSG("LIRC reconnected"); - continue; - } - - if (ret >= MIN_LIRCD_CMD_LEN) { - unsigned int count; - char KeyName[LIRC_KEY_BUF]; - LOGDBG("LIRC: %s", buf); - - if (sscanf(buf, "%*x %x %29s", &count, KeyName) != 2) { - /* '29' in '%29s' is LIRC_KEY_BUF-1! */ - LOGMSG("unparseable lirc command: %s", buf); - continue; - } - - if(lirc_repeat_emu) - if (strcmp(KeyName, LastKeyName) == 0 && elapsed(LastTime) < REPEATDELAY) - count = repeat + 1; - - if (count == 0) { - if (strcmp(KeyName, LastKeyName) == 0 && elapsed(FirstTime) < REPEATDELAY) - continue; /* skip keys coming in too fast */ - if (repeat) { - alarm(3); - if(find_input((fe_t*)fe)) - process_xine_keypress(((fe_t*)fe)->input, "LIRC", LastKeyName, 0, 1); - alarm(0); - } - - strcpy(LastKeyName, KeyName); - repeat = 0; - FirstTime = time_ms(); - timeout = -1; - } - else { - if (elapsed(LastTime) < REPEATFREQ) - continue; /* repeat function kicks in after a short delay */ - - if (elapsed(FirstTime) < REPEATDELAY) { - if(lirc_repeat_emu) - LastTime = time_ms(); - continue; /* skip keys coming in too fast */ - } - repeat = 1; - timeout = REPEATDELAY; - } - LastTime = time_ms(); - -#if defined(XINELIBOUTPUT_FE_TOGGLE_FULLSCREEN) || defined(INTERPRET_LIRC_KEYS) - if(!strcmp(KeyName, "Quit")) { - terminate_key_pressed = 1; - break; -# ifndef IS_FBFE - } else if(!strcmp(KeyName, "Fullscreen")) { - if(!repeat) - sxfe_toggle_fullscreen((sxfe_t*)fe); -# endif - } else if(!strcmp(KeyName, "Deinterlace")) { - fe_t *this = (fe_t*)fe; - xine_set_param(this->stream, XINE_PARAM_VO_DEINTERLACE, - xine_get_param(this->stream, XINE_PARAM_VO_DEINTERLACE) ? 0 : 1); - } else -#endif - { - alarm(3); - if(find_input((fe_t*)fe)) - process_xine_keypress(((fe_t*)fe)->input, "LIRC", KeyName, repeat, 0); - alarm(0); - } - - } - else if (repeat) { /* the last one was a repeat, so let's generate a release */ - if (elapsed(LastTime) >= REPEATTIMEOUT) { - alarm(3); - if(find_input((fe_t*)fe)) - process_xine_keypress(((fe_t*)fe)->input, "LIRC", LastKeyName, 0, 1); - alarm(0); - repeat = 0; - *LastKeyName = 0; - timeout = -1; - } - } - - } - } - - - if(fd_lirc >= 0) - close(fd_lirc); - fd_lirc = -1; - pthread_exit(NULL); - return NULL; /* never reached */ -} - -void lirc_start(fe_t *fe, char *lirc_dev, int repeat_emu) -{ - if(lirc_dev) { - int err; - lirc_device_name = lirc_dev; - lirc_repeat_emu = repeat_emu; - if ((err = pthread_create (&lirc_thread, - NULL, lirc_receiver_thread, - (void*)fe)) != 0) { - fprintf(stderr, "can't create new thread for lirc (%s)\n", - strerror(err)); - } - } -} - -void lirc_stop(void) -{ - if(lirc_device_name) { - void *p; - /*free(lirc_device_name);*/ - lirc_device_name = NULL; - if(fd_lirc >= 0) - close(fd_lirc); - fd_lirc = -1; - pthread_cancel (lirc_thread); - pthread_join (lirc_thread, &p); - } -} diff --git a/xine_frontend_main.c b/xine_frontend_main.c deleted file mode 100644 index 7c8a3171..00000000 --- a/xine_frontend_main.c +++ /dev/null @@ -1,723 +0,0 @@ -/* - * Simple main() routine for stand-alone frontends. - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: xine_frontend_main.c,v 1.40 2008-04-28 20:03:52 phintuka Exp $ - * - */ - -#include <termios.h> -#include <unistd.h> -#include <syslog.h> -#include <getopt.h> -#include <signal.h> - -#include "tools/vdrdiscovery.h" - - -#if 0 -static void xine_log_cb(void *data, int section) -{ - fprintf(stderr, "xine: log section %d\n",section); -} - -static void print_xine_log(xine_t *xine) -{ - int i, j; - int logs = xine_get_log_section_count(xine); - const char * const * names = xine_get_log_names(xine); - for(i=0; i<logs; i++) { - const char * const * lines = xine_get_log(xine, i); - if(lines[0]) { - printf("\nLOG: %s\n",names[i]); - j=-1; - while(lines[++j] && *lines[++j] ) - printf(" %2d: %s", j, lines[j]); - } - } -} -#endif - -static void list_plugins_type(xine_t *xine, const char *msg, typeof (xine_list_audio_output_plugins) list_func) -{ - static xine_t *tmp_xine = NULL; - if(!xine) { - if(!tmp_xine) - xine_init(tmp_xine = xine_new()); - xine = tmp_xine; - } - const char *const *list = list_func(xine); - - printf("%s", msg); - while(list && *list) - printf(" %s", *list++); - printf("\n"); -} - -static void list_plugins(xine_t *xine, int verbose) -{ - list_plugins_type (xine, "Available video drivers:", xine_list_video_output_plugins); - list_plugins_type (xine, "Available audio drivers:", xine_list_audio_output_plugins); - if(verbose) { - list_plugins_type (xine, "Available post plugins: ", xine_list_post_plugins); - list_plugins_type (xine, "Available input plugins:", xine_list_input_plugins); - list_plugins_type (xine, "Available demux plugins:", xine_list_demuxer_plugins); - list_plugins_type (xine, "Available audio decoder plugins:", xine_list_audio_decoder_plugins); - list_plugins_type (xine, "Available video decoder plugins:", xine_list_video_decoder_plugins); - list_plugins_type (xine, "Available SPU decoder plugins: ", xine_list_spu_plugins); - } -} - -/* static data */ -pthread_t kbd_thread; -struct termios tm, saved_tm; -volatile int terminate_key_pressed = 0; - -/* include LIRC forwarding code */ -#include "xine_frontend_lirc.c" - -static int read_key(void) -{ - unsigned char ch; - int err; - struct pollfd pfd; - pfd.fd = STDIN_FILENO; - pfd.events = POLLIN; - - errno = 0; - if(1 == (err=poll(&pfd, 1, 50))) { - - if (1 == (err = read(STDIN_FILENO, &ch, 1))) - return (int)ch; - - if (err < 0) - LOGERR("read_key: read(stdin) failed"); - else - LOGERR("read_key: read(stdin) failed: no stdin"); - return -2; - - } else if(err < 0 && errno != EINTR) { - LOGERR("read_key: poll(stdin) failed"); - return -2; - } - - return -1; -} - -static uint64_t read_key_seq(void) -{ - /* from vdr, remote.c */ - uint64_t k = 0; - int key1; - - if ((key1 = read_key()) >= 0) { - k = key1; - if (key1 == 0x1B) { - // Start of escape sequence - if ((key1 = read_key()) >= 0) { - k <<= 8; - k |= key1 & 0xFF; - switch (key1) { - case 0x4F: // 3-byte sequence - if ((key1 = read_key()) >= 0) { - k <<= 8; - k |= key1 & 0xFF; - } - break; - case 0x5B: // 3- or more-byte sequence - if ((key1 = read_key()) >= 0) { - k <<= 8; - k |= key1 & 0xFF; - switch (key1) { - case 0x31 ... 0x3F: // more-byte sequence - case 0x5B: // strange, may apparently occur - do { - if ((key1 = read_key()) < 0) - break; // Sequence ends here - k <<= 8; - k |= key1 & 0xFF; - } while (key1 != 0x7E); - break; - } - } - break; - } - } - } - } - if(key1==-2) - return 0xffff; - return k; -} - -#ifndef IS_FBFE -static void sxfe_toggle_fullscreen(sxfe_t *this); -#endif - -static void *kbd_receiver_thread(void *fe) -{ - uint64_t code = 0; - char str[64]; - - terminate_key_pressed = 0; - - system("setterm -cursor off"); - system("setterm -blank off"); - - /* Set stdin to deliver keypresses without buffering whole lines */ - tcgetattr(STDIN_FILENO, &saved_tm); - if (tcgetattr(STDIN_FILENO, &tm) == 0) { - tm.c_iflag = 0; - tm.c_lflag &= ~(ICANON | ECHO); - tm.c_cc[VMIN] = 0; - tm.c_cc[VTIME] = 0; - tcsetattr(STDIN_FILENO, TCSANOW, &tm); - } - - do { - alarm(0); - errno = 0; - code = read_key_seq(); - alarm(3); /* watchdog */ - if(code == 0) - continue; - if(code == 27) { - terminate_key_pressed = 1; - break; - } -#if defined(XINELIBOUTPUT_FE_TOGGLE_FULLSCREEN) || defined(INTERPRET_LIRC_KEYS) -# ifndef IS_FBFE - if(code == 'f' || code == 'F') { - sxfe_toggle_fullscreen((sxfe_t*)fe); - continue; - } else -# endif - if(code == 'd' || code == 'D') { - fe_t *this = (fe_t*)fe; - xine_set_param(this->stream, XINE_PARAM_VO_DEINTERLACE, - xine_get_param(this->stream, XINE_PARAM_VO_DEINTERLACE) ? 0 : 1); - continue; - } else -#endif - if(code == 0xffff) - break; - - snprintf(str, sizeof(str), "%016" PRIX64, code); - if(find_input((fe_t*)fe)) - process_xine_keypress(((fe_t*)fe)->input, "KBD", str, 0, 0); - - } while(!terminate_key_pressed && code != 0xffff); - - alarm(0); - LOGDBG("Keyboard thread terminated"); - tcsetattr(STDIN_FILENO, TCSANOW, &saved_tm); - system("setterm -cursor on"); - - pthread_exit(NULL); - return NULL; /* never reached */ -} - -static void *slave_receiver_thread(void *fe) -{ - char str[128], *pt; - - terminate_key_pressed = 0; - tcgetattr(STDIN_FILENO, &saved_tm); - - do { - - errno = 0; - str[0] = 0; - - if(!fgets(str, sizeof(str), stdin)) - break; - - if(NULL != (pt = strchr(str, '\r'))) - *pt = 0; - if(NULL != (pt = strchr(str, '\n'))) - *pt = 0; - - if(!strncasecmp(str, "QUIT", 4)) { - break; - -#ifndef IS_FBFE - } else if(!strncasecmp(str, "FULLSCREEN", 10)) { - sxfe_toggle_fullscreen((sxfe_t*)fe); -#endif - - } else if(!strncasecmp(str, "DEINTERLACE ", 12)) { - fe_t *this = (fe_t*)fe; - int val = atoi(str+12); - xine_set_param(this->stream, XINE_PARAM_VO_DEINTERLACE, val ? 1 : 0); - - } else if(!strncasecmp(str, "HITK ", 5)) { - if(find_input((fe_t*)fe)) - process_xine_keypress(((fe_t*)fe)->input, NULL, str+5, 0, 0); - - } else { - LOGMSG("Unknown slave mode command: %s", str); - } - - } while(!terminate_key_pressed); - - LOGDBG("Slave mode receiver terminated"); - tcsetattr(STDIN_FILENO, TCSANOW, &saved_tm); - terminate_key_pressed = 1; - - pthread_exit(NULL); - return NULL; /* never reached */ -} - -static void kbd_stop(void) -{ - void *p; - - pthread_cancel (kbd_thread); - pthread_join (kbd_thread, &p); - - tcsetattr(STDIN_FILENO, TCSANOW, &saved_tm); - system("setterm -cursor on"); -} - -static void SignalHandler(int signum) -{ - if (signum != SIGPIPE) - terminate_key_pressed = 1; - - signal(signum, SignalHandler); -} - -static char *strcatrealloc(char *dest, const char *src) -{ - int l; - - if (!src || !*src) - return dest; - - l = (dest ? strlen(dest) : 0) + strlen(src) + 1; - if(dest) { - dest = (char *)realloc(dest, l); - strcat(dest, src); - } else { - dest = (char*)malloc(l); - strcpy(dest, src); - } - return dest; -} - -static const char help_str[] = -"When server address is not given, server is searched from local network.\n" -"If server is not found, localhost (127.0.0.1) is used as default.\n\n" - " --help Show (this) help message\n" - " --audio=audiodriver[:device] Select audio driver and optional port\n" - " --video=videodriver[:device] Select video driver and optional port\n" -#ifndef IS_FBFE - " --display=displayaddress X11 display address\n" - " --wid=id Use existing X11 window\n" -#endif - " --aspect=[auto|4:3|16:9|16:10|default]\n" - " Display aspect ratio\n" - " Use script to control HW aspect ratio:\n" - " --aspect=auto:path_to_script\n" - " --fullscreen Fullscreen mode\n" - " --hud Head Up Display OSD mode\n" - " --width=x Video window width\n" - " --height=x Video window height\n" - " --noscaling Disable all video scaling\n" - " --post=name[:arg=val[,arg=val]] Load and use xine post plugin(s)\n" - " examples:\n" - " --post=upmix\n" - " --post=upmix;tvtime:enabled=1,cheap_mode=1\n" - " --lirc[=devicename] Use lirc input device\n" - " Optional lirc socket name can be given\n" - " --verbose Verbose debug output\n" - " --silent Silent mode (report only errors)\n" - " --syslog Write all output to system log\n" - " --nokbd Disable keyboard input\n" - " --daemon Run as daemon (disable keyboard,\n" - " log to syslog and fork to background)\n" - " --slave Enable slave mode (read commands from stdin)\r\n" - " --reconnect Automatically reconnect when connection has been lost" - " --tcp Use TCP transport\n" - " --udp Use UDP transport\n" - " --rtp Use RTP transport\n\n" - " If no transport options are given, transports\n" - " are tried in following order:\n" - " local pipe, rtp, udp, tcp\n\n"; - -static const char short_options[] = "HL:A:V:d:a:fDw:h:P:vslkbtur"; - -static const struct option long_options[] = { - { "help", no_argument, NULL, 'H' }, - { "audio", required_argument, NULL, 'A' }, - { "video", required_argument, NULL, 'V' }, - { "display", required_argument, NULL, 'd' }, - { "wid", required_argument, NULL, 'W' }, - { "aspect", required_argument, NULL, 'a' }, - { "fullscreen", no_argument, NULL, 'f' }, - { "hud", no_argument, NULL, 'D' }, - { "width", required_argument, NULL, 'w' }, - { "height", required_argument, NULL, 'h' }, - { "noscaling", no_argument, NULL, 'n' }, - { "post", required_argument, NULL, 'P' }, - { "lirc", optional_argument, NULL, 'L' }, - - { "verbose", no_argument, NULL, 'v' }, - { "silent", no_argument, NULL, 's' }, - { "syslog", no_argument, NULL, 'l' }, - { "nokbd", no_argument, NULL, 'k' }, - { "daemon", no_argument, NULL, 'b' }, - { "slave", no_argument, NULL, 'S' }, - - { "reconnect", no_argument, NULL, 'R' }, - { "tcp", no_argument, NULL, 't' }, - { "udp", no_argument, NULL, 'u' }, - { "rtp", no_argument, NULL, 'r' }, - { NULL } -}; - -#define PRINTF(x...) do { if(SysLogLevel>1) printf(x); } while(0) - -int main(int argc, char *argv[]) -{ - char *mrl = NULL, *gdrv = NULL, *adrv = NULL, *adev = NULL; - int ftcp = 0, fudp = 0, frtp = 0, reconnect = 0, firsttry = 1; - int fullscreen = 0, hud = 0, width = 720, height = 576; - int scale_video = 1, aspect = 1; - int daemon_mode = 0, nokbd = 0, slave_mode = 0; - char *video_port = NULL; -#ifndef IS_FBFE - int window_id = -1; -#endif - int xmajor, xminor, xsub; - int err, c; - frontend_t *fe = NULL; - extern const fe_creator_f fe_creator; - char *static_post_plugins = NULL; - char *lirc_dev = NULL; - char *aspect_controller = NULL; - int repeat_emu = 0; - char *exec_name = argv[0]; - - if(strrchr(argv[0],'/')) - exec_name = strrchr(argv[0],'/')+1; - - xine_get_version(&xmajor, &xminor, &xsub); - printf("%s %s (build with xine-lib %d.%d.%d, using xine-lib %d.%d.%d)\n\n", - exec_name, - FE_VERSION_STR, - XINE_MAJOR_VERSION, XINE_MINOR_VERSION, XINE_SUB_VERSION, - xmajor, xminor, xsub); - - /* Parse arguments */ - while ((c = getopt_long(argc, argv, short_options, long_options, NULL)) != -1) { - switch (c) { - default: - case 'H': printf("\nUsage: %s [options] [xvdr[+udp|+tcp|+rtp]:[//host[:port]]] \n" - "\nAvailable options:\n", exec_name); - printf("%s", help_str); - list_plugins(NULL, verbose_xine_log); - exit(0); - case 'A': adrv = strdup(optarg); - adev = strchr(adrv, ':'); - if(adev) - *(adev++) = 0; - PRINTF("Audio driver: %s\n",adrv); - if(adev) - PRINTF("Audio device: %s\n",adev); - break; - case 'V': gdrv = strdup(optarg); - if(strchr(gdrv, ':')) { - video_port = strchr(gdrv, ':'); - *video_port = 0; - video_port++; - PRINTF("Video port: %s\n",video_port); - } - PRINTF("Video driver: %s\n",gdrv); - break; -#ifndef IS_FBFE - case 'W': window_id = atoi(optarg); - break; - case 'd': video_port = strdup(optarg); - break; -#endif - case 'a': if(!strncmp(optarg, "auto", 4)) - aspect = 0; - if(!strncmp(optarg, "4:3", 3)) - aspect = 2; - if(!strncmp(optarg, "16:9", 4)) - aspect = 3; - if(!strncmp(optarg, "16:10", 5)) - aspect = 4; - if(aspect == 0 && optarg[5] == ':') - aspect_controller = strdup(optarg+5); - PRINTF("Aspect ratio: %s\n", - aspect==0?"Auto":aspect==2?"4:3":aspect==3?"16:9": - aspect==4?"16:10":"Default"); - if(aspect_controller) - PRINTF("Using %s to switch aspect ratio\n", - aspect_controller); - break; - case 'f': fullscreen=1; - PRINTF("Fullscreen mode\n"); - break; - case 'D': hud=1; - PRINTF("HUD OSD mode\n"); - break; - case 'w': width = atoi(optarg); - PRINTF("Width: %d\n", width); - break; - case 'h': height = atoi(optarg); - PRINTF("Height: %d\n", height); - break; - case 'n': scale_video = 0; - PRINTF("Video scaling disabled\n"); - break; - case 'P': if(static_post_plugins) - strcatrealloc(static_post_plugins, ";"); - static_post_plugins = strcatrealloc(static_post_plugins, optarg); - PRINTF("Post plugins: %s\n", static_post_plugins); - break; - case 'L': lirc_dev = optarg ? : strdup("/dev/lircd"); - if(strstr((char*)lirc_dev, ",repeatemu")) { - *strstr((char*)lirc_dev, ",repeatemu") = 0; - repeat_emu = 1; - } - PRINTF("LIRC device: %s%s\n", lirc_dev, - repeat_emu?", emulating key repeat":""); - break; - case 'v': verbose_xine_log = 1; - SysLogLevel = 3; - PRINTF("Verbose mode\n"); - break; - case 's': verbose_xine_log = 0; - SysLogLevel = 1; - PRINTF("Silent mode\n"); - break; - case 'S': slave_mode = 1; - PRINTF("Slave mode\n"); - break; - case 'l': LogToSysLog = 1; - openlog(exec_name, LOG_PID|LOG_CONS, LOG_USER); - break; - case 'k': nokbd = 1; - PRINTF("Keyboard input disabled\n"); - break; - case 'b': nokbd = daemon_mode = 1; - PRINTF("Keyboard input disabled\n"); - break; - case 'R': reconnect = 1; - PRINTF("Automatic reconnection enabled\n"); - break; - case 't': ftcp = 1; - PRINTF("Protocol: TCP\n"); - break; - case 'u': fudp = 1; - PRINTF("Protocol: UDP\n"); - break; - case 'r': frtp = 1; - PRINTF("Protocol: RTP\n"); - break; - case 1: printf("arg 1 (%s)\n", long_options[optind].name); exit(0); - } - } - - if (optind < argc) { - mrl = strdup(argv[optind]); - PRINTF("VDR Server: %s\n", mrl); - while (++optind < argc) - printf("Unknown argument: %s\n", argv[optind]); - } - - PRINTF("\n"); - - /* check xine-lib version */ - if(!xine_check_version(1, 1, 0)) { - fprintf(stderr,"ERROR: xine-lib is too old, require at least " - "xine library version 1.1.0\n"); - return -1; - } - -#if 1 - /* backward compability */ - if(mrl && ( !strncmp(mrl, "xvdr:tcp:", 9) || - !strncmp(mrl, "xvdr:udp:", 9) || - !strncmp(mrl, "xvdr:rtp:", 9) || - !strncmp(mrl, "xvdr:pipe:", 10))) - mrl[5] = '+'; -#endif - - /* If server address not given, try to find server automatically */ - if(!mrl || - !strcmp(mrl, "xvdr:") || - !strcmp(mrl, "xvdr+tcp:") || - !strcmp(mrl, "xvdr+udp:") || - !strcmp(mrl, "xvdr+rtp:") || - !strcmp(mrl, "xvdr+pipe:")) { - char address[1024] = ""; - int port = -1; - PRINTF("VDR server not given, searching ...\n"); - if(udp_discovery_find_server(&port, &address[0])) { - PRINTF("Found VDR server: host %s, port %d\n", address, port); - if(mrl) { - char *tmp = mrl; - mrl = NULL; - asprintf(&mrl, "%s//%s:%d", tmp, address, port); - free(tmp); - } else - asprintf(&mrl, "xvdr://%s:%d", address, port); - } else { - PRINTF("---------------------------------------------------------------\n" - "WARNING: MRL not given and server not found from local network.\n" - " Trying to connect to default port on local host.\n" - "---------------------------------------------------------------\n"); - mrl = strdup("xvdr://127.0.0.1"); - } - } - - if(mrl && strncmp(mrl, "xvdr:", 5) && strncmp(mrl, "xvdr+", 5)) { - char *mrl2 = mrl; - PRINTF("WARNING: MRL does not start with \'xvdr:\' (%s)", mrl); - asprintf(&mrl, "xvdr://%s", mrl); - free(mrl2); - } - - { - char *tmp = NULL, *mrl2 = mrl; - if(frtp && !strstr(mrl, "rtp:")) - tmp = strdup("xvdr+rtp:"); - else if(fudp && !strstr(mrl, "udp:")) - tmp = strdup("xvdr+udp:"); - else if(ftcp && !strstr(mrl, "tcp:")) - tmp = strdup("xvdr+tcp:"); - if(tmp) { - mrl = strcatrealloc(tmp, strchr(mrl, '/')); - free(mrl2); - } - } - - if(daemon_mode) { - PRINTF("Entering daemon mode\n\n"); - if (daemon(1, 0) == -1) { - fprintf(stderr, "%s: %m\n", exec_name); - LOGERR("daemon() failed"); - return -2; - } - } - - /* Create front-end */ - fe = (*fe_creator)(); - if(!fe) { - fprintf(stderr, "Error initializing frontend\n"); - return -3; - } -#ifndef IS_FBFE - ((fe_t*)fe)->window_id = window_id; -#endif - ((fe_t*)fe)->aspect_controller = aspect_controller; - - /* Initialize display */ - if(!fe->fe_display_open(fe, width, height, fullscreen, hud, 0, - "", aspect, NULL, video_port, scale_video, 0)) { - fprintf(stderr, "Error opening display\n"); - fe->fe_free(fe); - return -4; - } - - /* Initialize xine */ - if(!fe->xine_init(fe, adrv, adev, gdrv, 250, static_post_plugins)) { - fprintf(stderr, "Error initializing xine\n"); - fe->fe_free(fe); - list_plugins(NULL, verbose_xine_log); - return -5; - } - if(SysLogLevel>2) - list_plugins(((fe_t*)fe)->xine, verbose_xine_log); - - /* signal handlers */ - - if (signal(SIGHUP, SignalHandler) == SIG_IGN) signal(SIGHUP, SIG_IGN); - if (signal(SIGINT, SignalHandler) == SIG_IGN) signal(SIGINT, SIG_IGN); - if (signal(SIGTERM, SignalHandler) == SIG_IGN) signal(SIGTERM, SIG_IGN); - if (signal(SIGPIPE, SignalHandler) == SIG_IGN) signal(SIGPIPE, SIG_IGN); - - /* Start LIRC forwarding */ - lirc_start((fe_t*)fe, lirc_dev, repeat_emu); - - PRINTF("\n\nPress Esc to exit\n\n"); - - /* Start keyboard listener thread */ - if(!nokbd) { - if ((err = pthread_create (&kbd_thread, - NULL, - slave_mode ? slave_receiver_thread : kbd_receiver_thread, - (void*)fe)) != 0) { - fprintf(stderr, "Can't create new thread for keyboard (%s)\n", - strerror(err)); - } - sleep(1); - } - - do { - - if(!firsttry) { - PRINTF("Connection to server lost. Reconnecting after two seconds...\n"); - sleep(2); - PRINTF("Reconnecting...\n"); - } - - /* Connect to VDR xineliboutput server */ - if(!fe_xine_open(fe, mrl)) { - /*print_xine_log(((fe_t *)fe)->xine);*/ - if(!firsttry) { - PRINTF("Error opening %s\n", mrl); - continue; - } - fprintf(stderr, "Error opening %s\n", mrl); - lirc_stop(); - if(!nokbd) kbd_stop(); - fe->fe_free(fe); - return -6; - } - - if(!fe->xine_play(fe)) { - /*print_xine_log(((fe_t *)fe)->xine);*/ - /*printf("Error playing %s//%s:%s\n", argv[1], host, port);*/ - if(!firsttry) { - PRINTF("Error playing %s\n", argv[1]); - continue; - } - fprintf(stderr, "Error playing %s\n", argv[1]); - lirc_stop(); - if(!nokbd) kbd_stop(); - fe->fe_free(fe); - return -7; - } - - /* Main loop */ - - sleep(2); /* give input_vdr some time to establish connection */ - - fflush(stdout); - fflush(stderr); - - while(fe->fe_run(fe) && !fe->xine_is_finished(fe,0) && !terminate_key_pressed) - ; - - fe->xine_close(fe); - firsttry = 0; - - } while(!terminate_key_pressed && reconnect); - - /* Clean up */ - - PRINTF("Terminating...\n"); - - lirc_stop(); - if(!nokbd) kbd_stop(); - - fe->fe_free(fe); - return terminate_key_pressed ? 0 : 1; -} diff --git a/xine_input_vdr.c b/xine_input_vdr.c deleted file mode 100644 index b83bdeb3..00000000 --- a/xine_input_vdr.c +++ /dev/null @@ -1,6542 +0,0 @@ -/* - * xine_input_vdr.c: xine VDR input plugin - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: xine_input_vdr.c,v 1.137 2008-04-14 19:58:54 phintuka Exp $ - * - */ - - -#define XINE_ENGINE_INTERNAL -#define METRONOM_CLOCK_INTERNAL - -#include <sys/types.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <fcntl.h> -#include <string.h> -#include <poll.h> -#include <arpa/inet.h> -#include <netinet/in.h> -#include <netinet/tcp.h> -#include <sys/ioctl.h> -#include <sys/socket.h> -#include <errno.h> -#include <sys/time.h> -#include <dlfcn.h> -#include <sys/resource.h> /* setpriority() */ -#include <sys/stat.h> -#include <syslog.h> - -#ifndef __APPLE__ -# define DVD_STREAMING_SPEED -#endif - -#ifdef DVD_STREAMING_SPEED -# include <linux/cdrom.h> -# include <scsi/sg.h> -#endif - -#include <xine/xine_internal.h> -#include <xine/xineutils.h> -#include <xine/input_plugin.h> -#include <xine/plugin_catalog.h> -#include <xine/io_helper.h> -#include <xine/buffer.h> -#include <xine/post.h> - -#include "xine_input_vdr.h" -#include "xine_input_vdr_net.h" -#include "xine_osd_command.h" - -/***************************** DEFINES *********************************/ - -/* Support for ffmpeg mpeg2 decoder. - Priority must be increased in $HOME/.xine/config_xineliboutput: - engine.decoder_priorities.ffmpegvideo:1 -*/ -#define FFMPEG_DEC - -/*#define LOG_UDP*/ -/*#define LOG_OSD*/ -/*#define LOG_CMD*/ -/*#define LOG_SCR*/ -/*#define LOG_TRACE*/ - -#define ADJUST_SCR_SPEED 1 -#define METRONOM_PREBUFFER_VAL (4 * 90000 / 25 ) -#define HD_BUF_NUM_BUFS (2048) /* 2k payload * 2048 = 4Mb , ~ 1 second */ -#define HD_BUF_ELEM_SIZE (2048+64) -#define TEST_H264 1 - -#define RADIO_MAX_BUFFERS 10 - -#ifndef NOSIGNAL_IMAGE_FILE -# define NOSIGNAL_IMAGE_FILE "/usr/share/vdr/xineliboutput/nosignal.mpv" -#endif -#ifndef NOSIGNAL_MAX_SIZE -# define NOSIGNAL_MAX_SIZE 0x10000 /* 64k */ -#endif - -/* - Note: - I tried to set speed to something very small instead of full pause - when pausing SCR but it didn't work in all systems. - TEST_SCR_PAUSE replaces this by adding delay before stream - is paused (pause is triggered by first received PES containing PTS). - This should allow immediate processing of still frames and let video_out - run in paused_loop when there is gap in feed (ex. channel can't be decrypted). - Not running video_out in paused_loop caused very long delays in - OSD updating in some setups. -*/ -#define TEST_SCR_PAUSE - -/* picture-in-picture support */ -/*#define TEST_PIP 1*/ - - -#define CONTROL_BUF (0x0f000000) /* 0x0f000000 */ -#define CONTROL_BUF_BLANK (CONTROL_BUF|0x00010000) /* 0x0f010000 */ -#define CONTROL_BUF_CLEAR (CONTROL_BUF|0x00020000) /* 0x0f020000 */ - -#define SPU_CHANNEL_NONE (-2) -#define SPU_CHANNEL_AUTO (-1) - -/******************************* LOG ***********************************/ - -#define LOG_MODULENAME "[input_vdr] " -#define SysLogLevel iSysLogLevel - -#include "logdefs.h" - -#undef x_syslog -#define x_syslog syslog_with_tid - -int iSysLogLevel = 1; /* 0:none, 1:errors, 2:info, 3:debug */ -int bLogToSysLog = 0; -int bSymbolsFound = 0; - -static void syslog_with_tid(int level, const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); -static void syslog_with_tid(int level, const char *fmt, ...) -{ - va_list argp; - char buf[512]; - va_start(argp, fmt); - vsnprintf(buf, sizeof(buf), fmt, argp); - buf[sizeof(buf)-1] = 0; -#ifdef __APPLE__ - if(!bLogToSysLog) { - fprintf(stderr, LOG_MODULENAME "%s\n", buf); - } else { - syslog(level, LOG_MODULENAME "%s", buf); - } -#else - if(!bLogToSysLog) { - fprintf(stderr,"[%ld] " LOG_MODULENAME "%s\n", syscall(__NR_gettid), buf); - } else { - syslog(level, "[%ld] " LOG_MODULENAME "%s", syscall(__NR_gettid), buf); - } -#endif - va_end(argp); -} - -static void SetupLogLevel(void) -{ - void *lib = NULL; - if( !(lib = dlopen (NULL, RTLD_LAZY | RTLD_GLOBAL))) { - LOGERR("Can't dlopen self: %s", dlerror()); - } else { - int *pLogToSyslog = (int*)dlsym(lib, "LogToSysLog"); - int *pSysLogLevel = (int*)dlsym(lib, "SysLogLevel"); - bLogToSysLog = pLogToSyslog && *pLogToSyslog; - iSysLogLevel = pSysLogLevel ? (*pSysLogLevel) : iSysLogLevel; - LOGDBG("Symbol SysLogLevel %s : value %d", - pSysLogLevel ? "found" : "not found", iSysLogLevel); - LOGDBG("Symbol LogToSysLog %s : value %s", - pLogToSyslog ? "found" : "not found", bLogToSysLog ? "yes" : "no"); - bSymbolsFound = pSysLogLevel && pLogToSyslog; - dlclose(lib); - } -} - -#define LOG_UDP - -#ifdef LOG_SCR -# define LOGSCR(x...) LOGMSG("SCR: " x) -#else -# define LOGSCR(x...) -#endif -# -#ifdef LOG_OSD -# define LOGOSD(x...) LOGMSG("OSD: " x) -#else -# define LOGOSD(x...) -#endif -# -#ifdef LOG_UDP -# define LOGUDP(x...) LOGMSG("UDP:" x) -#else -# define LOGUDP(x...) -#endif -#ifdef LOG_CMD -# define LOGCMD(x...) LOGMSG("CMD:" x) -#else -# define LOGCMD(x...) -#endif -#ifdef LOG_TRACE -# undef TRACE -# define TRACE(x...) printf(x) -#else -# undef TRACE -# define TRACE(x...) -#endif - - -/*#define DEBUG_LOCKING*/ -#ifdef DEBUG_LOCKING -# include "tools/debug_mutex.h" -#endif - -/******************************* DATA ***********************************/ - -#define KILOBYTE(x) (1024 * (x)) - -typedef struct pvrscr_s pvrscr_t; -typedef struct udp_data_s udp_data_t; - -/* plugin class */ -typedef struct vdr_input_class_s { - input_class_t input_class; - xine_t *xine; - char *mrls[ 2 ]; - int fast_osd_scaling; -} vdr_input_class_t; - -/* input plugin */ -typedef struct vdr_input_plugin_s { - input_plugin_t input_plugin; - - /* VDR */ - vdr_input_plugin_funcs_t funcs; - - /* plugin */ - vdr_input_class_t *class; - xine_stream_t *stream; - xine_event_queue_t *event_queue; - - char *mrl; - - xine_stream_t *pip_stream; - xine_stream_t *slave_stream; - xine_event_queue_t *slave_event_queue; - int autoplay_size; - - /* Sync */ - pthread_mutex_t lock; - pthread_mutex_t vdr_entry_lock; - pthread_cond_t engine_flushed; - - /* Playback */ - int no_video; - int live_mode; - int still_mode; - int stream_start; - int send_pts; - int padding_cnt; - int loop_play; - int hd_stream; /* true if current stream is HD */ - int h264; /* -1: unknown, 0: no, 1: yes */ - - int audio_stream_id; /* ((PES PID) << 8) | (SUBSTREAM ID) */ - int prev_audio_stream_id; - int sw_volume_control; - int ffmpeg_video_decoder; - - /* SCR */ - pvrscr_t *scr; - int scr_tunning; - int fixed_scr; - int scr_live_sync; - int speed_before_pause; - int is_paused; - int is_trickspeed; - - int I_frames; /* amount of I-frames passed to demux */ - int B_frames; - int P_frames; - - /* Network */ - pthread_t control_thread; - pthread_t data_thread; - pthread_mutex_t fd_control_lock; - int threads_initialized; - volatile int control_running; - volatile int fd_data; - volatile int fd_control; - int tcp, udp, rtp; - udp_data_t *udp_data; - int client_id; - int token; - - /* buffer */ - fifo_buffer_t *block_buffer; /* blocks to be demuxed */ - fifo_buffer_t *buffer_pool; /* stream's video fifo */ - fifo_buffer_t *big_buffer; /* for jumbo PES */ - fifo_buffer_t *hd_buffer; /* more buffer for HD streams */ - fifo_buffer_t *iframe_buffer; /* buffer for cached I-frame */ - int saving_iframe; - uint64_t discard_index; /* index of next byte to feed to demux; - all data before this offset will - be discarded */ - int discard_frame; - uint64_t guard_index; /* data before this offset will not be discarded */ - int guard_frame; - uint64_t curpos; /* current position (demux side) */ - int curframe; - int max_buffers; /* max no. of non-demuxed buffers */ - int64_t last_delivered_vid_pts; /* detect PTS wraps */ - - /* saved video properties */ - int video_properties_saved; - int orig_hue; - int orig_brightness; - int orig_saturation; - int orig_contrast; - int orig_vo_aspect_ratio; - - /* OSD */ - pthread_mutex_t osd_lock; - int vdr_osd_width, vdr_osd_height; - int video_width, video_height; - int video_changed; - int osdhandle[MAX_OSD_OBJECT]; - int64_t last_changed_vpts[MAX_OSD_OBJECT]; - osd_command_t osddata[MAX_OSD_OBJECT]; - -} vdr_input_plugin_t; - - -/***************************** UDP DATA *********************************/ - -struct udp_data_s { - - /* Server address (used to validate incoming packets) */ - struct sockaddr_in server_address; - uint32_t ssrc; - - /* receiving queue for re-ordering and re-transmissions */ - buf_element_t *queue[UDP_SEQ_MASK+1]; - uint64_t queue_input_pos; /* stream position of next incoming byte */ - uint16_t queued; /* count of frames in queue */ - uint16_t next_seq; /* expected sequence number of next incoming packet */ - - /* missing frames ratio statistics */ - int16_t missed_frames; - int16_t received_frames; - - /* SCR adjust */ - uint8_t scr_jump_done; - - int resend_requested : 1; -}; - -/* UDP sequence number handling */ -#define NEXTSEQ(x) ((x + 1) & UDP_SEQ_MASK) -#define PREVSEQ(x) ((x + UDP_SEQ_MASK) & UDP_SEQ_MASK) -#define INCSEQ(x) (x = NEXTSEQ(x)) -#define ADDSEQ(x,n) ((x + UDP_SEQ_MASK + 1 + n) & UDP_SEQ_MASK) - -#define UDP_SIGNAL_FULL_TRESHOLD 50 /* ~100ms with DVB mpeg2 - (2k-blocks @ 8 Mbps) */ -#define UDP_SIGNAL_NOT_FULL_TRESHOLD 100 /* ~200ms with DVB mpeg2 - (2k-blocks @ 8 Mbps) */ - -static udp_data_t *init_udp_data(void) -{ - udp_data_t *data = (udp_data_t *)xine_xmalloc(sizeof(udp_data_t)); - - data->received_frames = -1; - - return data; -} - -static void free_udp_data(udp_data_t *data) -{ - int i; - - for(i=0; i<=UDP_SEQ_MASK; i++) - if(data->queue[i]) { - data->queue[i]->free_buffer(data->queue[i]); - data->queue[i] = NULL; - } - free(data); -} - -#if 0 -static void flush_udp_data(udp_data_t *data) -{ - /* flush all data immediately even if there are gaps */ -} -#endif - -#ifdef ADJUST_SCR_SPEED -/******************************* SCR ************************************* - * - * unix System Clock Reference + fine tunning - * - * pvrscr code is mostly copied from xine, input_pvr.c - * - * fine tunning is used to change playback speed in live mode - * to keep in sync with mpeg source - *************************************************************************/ - -struct pvrscr_s { - scr_plugin_t scr; - - struct timeval cur_time; - int64_t cur_pts; - int xine_speed; - int scr_speed_base; - double speed_factor; - double speed_tunning; - - pthread_mutex_t lock; - - struct timeval last_time; -}; - -static int pvrscr_get_priority (scr_plugin_t *scr) -{ - return 50; /* high priority */ -} - -/* Only call pvrscr_set_pivot when already mutex locked ! */ -static void pvrscr_set_pivot (pvrscr_t *this) -{ - struct timeval tv; - int64_t pts; - double pts_calc; - - xine_monotonic_clock(&tv,NULL); - - pts_calc = (tv.tv_sec - this->cur_time.tv_sec) * this->speed_factor; - pts_calc += (tv.tv_usec - this->cur_time.tv_usec) * this->speed_factor / 1e6; - pts = this->cur_pts + pts_calc; - - /* This next part introduces a one off inaccuracy - * to the scr due to rounding tv to pts. - */ - this->cur_time.tv_sec=tv.tv_sec; - this->cur_time.tv_usec=tv.tv_usec; - this->cur_pts=pts; - - this->last_time.tv_sec = tv.tv_sec; - this->last_time.tv_usec = tv.tv_usec; - - return ; -} - -static int pvrscr_set_fine_speed (scr_plugin_t *scr, int speed) -{ - pvrscr_t *this = (pvrscr_t*) scr; - - pthread_mutex_lock (&this->lock); - - pvrscr_set_pivot( this ); - this->xine_speed = speed; - this->speed_factor = (double) speed * (double)this->scr_speed_base /*90000.0*/ / - (1.0*XINE_FINE_SPEED_NORMAL) * - this->speed_tunning; - - pthread_mutex_unlock (&this->lock); - - return speed; -} - -static void pvrscr_speed_tunning (pvrscr_t *this, double factor) -{ - pthread_mutex_lock (&this->lock); - - pvrscr_set_pivot( this ); - this->speed_tunning = factor; - this->speed_factor = (double) this->xine_speed * (double)this->scr_speed_base /*90000.0*/ / - (1.0*XINE_FINE_SPEED_NORMAL) * - this->speed_tunning; - - pthread_mutex_unlock (&this->lock); -} - -static void pvrscr_speed_base (pvrscr_t *this, int hz) -{ - pthread_mutex_lock (&this->lock); - - pvrscr_set_pivot( this ); - this->scr_speed_base = hz; - this->speed_factor = (double) this->xine_speed * (double)this->scr_speed_base /*90000.0*/ / - (1.0*XINE_FINE_SPEED_NORMAL) * - this->speed_tunning; - - pthread_mutex_unlock (&this->lock); -} - -static void pvrscr_skip_frame (pvrscr_t *this) -{ - pthread_mutex_lock (&this->lock); - - pvrscr_set_pivot( this ); - this->cur_pts += (90000/25)*1ULL; - - pthread_mutex_unlock (&this->lock); -} - -static void pvrscr_adjust (scr_plugin_t *scr, int64_t vpts) -{ - pvrscr_t *this = (pvrscr_t*) scr; - struct timeval tv; - - pthread_mutex_lock (&this->lock); - - xine_monotonic_clock(&tv,NULL); - this->cur_time.tv_sec=tv.tv_sec; - this->cur_time.tv_usec=tv.tv_usec; - this->cur_pts = vpts; - - this->last_time.tv_sec = tv.tv_sec; - this->last_time.tv_usec = tv.tv_usec; - - pthread_mutex_unlock (&this->lock); -} - -static void pvrscr_start (scr_plugin_t *scr, int64_t start_vpts) -{ - pvrscr_t *this = (pvrscr_t*) scr; - - pthread_mutex_lock (&this->lock); - - xine_monotonic_clock(&this->cur_time, NULL); - this->cur_pts = start_vpts; - - this->last_time.tv_sec = this->cur_time.tv_sec; - this->last_time.tv_usec = this->cur_time.tv_usec; - - pthread_mutex_unlock (&this->lock); - - pvrscr_set_fine_speed (&this->scr, XINE_FINE_SPEED_NORMAL); -} - -static int64_t pvrscr_get_current (scr_plugin_t *scr) -{ - pvrscr_t *this = (pvrscr_t*) scr; - - struct timeval tv; - int64_t pts; - double pts_calc; - pthread_mutex_lock (&this->lock); - - xine_monotonic_clock(&tv,NULL); - -#ifdef LOG_SCR - if(this->last_time.tv_sec+3 < tv.tv_sec && this->last_time.tv_sec) { - LOGMSG("ERROR - CLOCK JUMPED FORWARDS ? " - "(pvrscr_get_current diff %d.%06d sec)\n", - (int)(tv.tv_sec - this->last_time.tv_sec), - (int)(tv.tv_usec - this->last_time.tv_usec)); - pthread_mutex_unlock (&this->lock); - pvrscr_adjust(scr,this->cur_pts); - pthread_mutex_lock (&this->lock); - } - else if(this->last_time.tv_sec > tv.tv_sec) { - LOGMSG("ERROR - CLOCK JUMPED BACKWARDS ! " - "(pvrscr_get_current diff %d.%06d sec)\n", - (int)(tv.tv_sec - this->last_time.tv_sec), - (int)(tv.tv_usec - this->last_time.tv_usec)); - pthread_mutex_unlock (&this->lock); - pvrscr_adjust(scr,this->cur_pts); - pthread_mutex_lock (&this->lock); - } -#endif - - pts_calc = (tv.tv_sec - this->cur_time.tv_sec) * this->speed_factor; - pts_calc += (tv.tv_usec - this->cur_time.tv_usec) * this->speed_factor / 1e6; - - pts = this->cur_pts + pts_calc; - - this->last_time.tv_sec = tv.tv_sec; - this->last_time.tv_usec = tv.tv_usec; - - pthread_mutex_unlock (&this->lock); - - return pts; -} - -static void pvrscr_exit (scr_plugin_t *scr) -{ - pvrscr_t *this = (pvrscr_t*) scr; - - pthread_mutex_destroy (&this->lock); - free(this); -} - -static pvrscr_t* pvrscr_init (void) -{ - pvrscr_t *this; - - this = malloc(sizeof(*this)); - memset(this, 0, sizeof(*this)); - - this->scr.interface_version = 3; - this->scr.set_fine_speed = pvrscr_set_fine_speed; - this->scr.get_priority = pvrscr_get_priority; - this->scr.adjust = pvrscr_adjust; - this->scr.start = pvrscr_start; - this->scr.get_current = pvrscr_get_current; - this->scr.exit = pvrscr_exit; - - pthread_mutex_init (&this->lock, NULL); - - this->scr_speed_base = 90000; - - pvrscr_speed_tunning(this, 1.0 ); - pvrscr_set_fine_speed (&this->scr, XINE_SPEED_PAUSE); - - LOGSCR("SCR init complete"); - - return this; -} - -/* - * SCR tunning - */ - -#define SCR_TUNNING_PAUSED -3 -#define SCR_TUNNING_OFF 0 - -#ifdef LOG_SCR -static inline const char *scr_tunning_str(int value) -{ - switch(value) { - case 2: return "SCR +1.0%"; - case 1: return "SCR +0.5%"; - case SCR_TUNNING_OFF: return "SCR +0.0%"; - case -1: return "SCR -0.5%"; - case -2: return "SCR -1.0%"; - case SCR_TUNNING_PAUSED: return "SCR PAUSED"; - default: break; - } - return "ERROR"; -} -#endif - -static int64_t monotonic_time_ms (void) -{ - static struct timeval tv_0; - static int init_done = 0; - struct timeval tv; - int64_t ms; - - if(!init_done) { - init_done = 1; - xine_monotonic_clock(&tv_0, NULL); - } - xine_monotonic_clock(&tv, NULL); - - ms = 1000LL * (tv.tv_sec - tv_0.tv_sec); - ms += tv.tv_usec / 1000; - return ms; -} - -static void scr_tunning_set_paused(vdr_input_plugin_t *this) -{ - if(this->scr_tunning != SCR_TUNNING_PAUSED && - !this->slave_stream && - !this->is_trickspeed) { - - this->scr_tunning = SCR_TUNNING_PAUSED; /* marked as paused */ - if(this->scr) - pvrscr_speed_tunning(this->scr, 1.0); - - this->speed_before_pause = _x_get_fine_speed(this->stream); - -#ifdef TEST_SCR_PAUSE - if(_x_get_fine_speed(this->stream) != XINE_SPEED_PAUSE) - _x_set_fine_speed(this->stream, XINE_SPEED_PAUSE); -#else - _x_set_fine_speed(this->stream, 1000000 / 1000); /* -> speed to 0.1% */ -#endif - this->I_frames = this->P_frames = this->B_frames = 0; - } -} - -static void reset_scr_tunning(vdr_input_plugin_t *this, int new_speed) -{ - if(this->scr_tunning != SCR_TUNNING_OFF) { - this->scr_tunning = SCR_TUNNING_OFF; /* marked as normal */ - if(this->scr) - pvrscr_speed_tunning(this->scr, 1.0); - - if(new_speed >= 0) { - if(_x_get_fine_speed(this->stream) != new_speed) { - _x_set_fine_speed(this->stream, XINE_FINE_SPEED_NORMAL); - } - pvrscr_set_fine_speed((scr_plugin_t*)this->scr, XINE_FINE_SPEED_NORMAL); - } - } -} - -static void vdr_adjust_realtime_speed(vdr_input_plugin_t *this) -{ - /* - * Grab current buffer usage - */ - int num_used = this->buffer_pool->size(this->buffer_pool) + - this->block_buffer->size(this->block_buffer); - int num_free = this->buffer_pool->num_free(this->buffer_pool); - int scr_tunning = this->scr_tunning; - /*int num_vbufs = 0;*/ - - if(this->hd_stream && this->hd_buffer) { - num_free += this->hd_buffer->num_free(this->hd_buffer); - } - - if(this->stream->audio_fifo) - num_used += this->stream->audio_fifo->size(this->stream->audio_fifo); - num_free -= (this->buffer_pool->buffer_pool_capacity - this->max_buffers); - -#ifdef LOG_SCR - /* - * Trace current buffer and tunning status - */ - { - static int fcnt=0; - if(!((fcnt++)%2500) || - (this->scr_tunning==SCR_TUNNING_PAUSED && !(fcnt%10)) || - (this->no_video && !(fcnt%50))) { - LOGSCR("Buffer %2d%% (%3d/%3d) %s", - 100*num_used/(num_used+num_free), - num_used, num_used+num_free, - scr_tunning_str(this->scr_tunning)); - } - } - - if(this->scr_tunning==SCR_TUNNING_PAUSED) { - if(_x_get_fine_speed(this->stream) != XINE_SPEED_PAUSE) { - LOGMSG("ERROR: SCR PAUSED ; speed=%d bool=%d", - _x_get_fine_speed(this->stream), - (int)_x_get_fine_speed(this->stream) == XINE_SPEED_PAUSE); - _x_set_fine_speed(this->stream, XINE_SPEED_PAUSE); - } - } -#endif - - /* - * SCR -> PAUSE - * - If buffer is empty, pause SCR (playback) for a while - */ - if( num_used < 1 && - scr_tunning != SCR_TUNNING_PAUSED && - !this->no_video && !this->still_mode && !this->is_trickspeed) { -/* - #warning TODO: - - First I-frame can be delivered as soon as it is decoded - -> illusion of faster channel switches - - Clock must still be paused, but stream can be in PLAYING state - (if clock is not paused we will got a lot of discarded frames - as those are decoded too late according to running SCR) -*/ -#if 0 - this->class->xine->port_ticket->acquire(this->class->xine->port_ticket, 0); - num_vbufs = this->stream->video_out->get_property(this->stream->video_out, - VO_PROP_BUFS_IN_FIFO); - this->class->xine->port_ticket->release(this->class->xine->port_ticket, 0); - if(num_vbufs < 3) { - LOGSCR("SCR paused by adjust_speed (vbufs=%d)", num_vbufs); -#endif - scr_tunning_set_paused(this); -#if 0 - } else { - LOGSCR("adjust_speed: no pause, enough vbufs queued (%d)", num_vbufs); - } -#endif - - - /* SCR -> RESUME - * - If SCR (playback) is currently paused due to previous buffer underflow, - * revert to normal if buffer fill is > 66% - */ - } else if( scr_tunning == SCR_TUNNING_PAUSED) { -/* - #warning TODO: - - Using amount of buffers is not good trigger as it depends on channel bitrate - - Wait time is not not good trigger as it depends on tuner lock time - -> maybe keep track of PTSes or wait until decoder has complete IBBBP frame sequence ? - - First I-frame can be delivered as soon as it is decoded - -> illusion of faster channel switches -*/ -#if 0 - /* causes random freezes with some post plugins */ - this->class->xine->port_ticket->acquire(this->class->xine->port_ticket, 0); - num_vbufs = this->stream->video_out->get_property(this->stream->video_out, - VO_PROP_BUFS_IN_FIFO); - this->class->xine->port_ticket->release(this->class->xine->port_ticket, 0); -#endif - - if( num_used/2 > num_free - || (this->no_video && num_used > 5) - || this->still_mode - || this->is_trickspeed - || ( this->I_frames > 0 - && (this->I_frames > 2 || this->P_frames > 6 )) - ) { - LOGSCR("SCR tunning resetted by adjust_speed, " - "I %d B %d P %d", this->I_frames, this->B_frames, this->P_frames); - - this->I_frames = 0; - reset_scr_tunning(this, this->speed_before_pause); - } - - /* - * Adjust SCR rate - * - Live data is coming in at rate defined by sending transponder, - * there is no way to change it -> we must adapt to it - * - when playing realtime (live) stream, adjust our SCR to keep - * xine buffers half full. This efficiently synchronizes our SCR - * to transponder SCR and prevents buffer under/overruns caused by - * minor differences in clock speeds. - * - if buffer is getting empty, slow don SCR by 0.5...1% - * - if buffer is getting full, speed up SCR by 0.5...1% - * - * TODO: collect simple statistics and try to calculate more exact - * clock rate difference to minimize SCR speed changes - */ - } else if( _x_get_fine_speed(this->stream) == XINE_FINE_SPEED_NORMAL) { - - if(!this->scr_live_sync) { - scr_tunning = SCR_TUNNING_OFF; - - } else if(this->no_video) { /* radio stream ? */ - if( num_used >= (RADIO_MAX_BUFFERS-1)) - scr_tunning = +1; /* play faster */ - else if( num_used <= (RADIO_MAX_BUFFERS/3)) - scr_tunning = -1; /* play slower */ - else - scr_tunning = SCR_TUNNING_OFF; - } else { - if( num_used > 4*num_free ) - scr_tunning = +2; /* play 1% faster */ - else if( num_used > 2*num_free ) - scr_tunning = +1; /* play .5% faster */ - else if( num_free > 4*num_used ) /* <20% */ - scr_tunning = -2; /* play 1% slower */ - else if( num_free > 2*num_used ) /* <33% */ - scr_tunning = -1; /* play .5% slower */ - else if( (scr_tunning > 0 && num_free > num_used) || - (scr_tunning < 0 && num_used > num_free) ) - scr_tunning = SCR_TUNNING_OFF; - } - - if( scr_tunning != this->scr_tunning ) { - LOGSCR("scr_tunning: %s -> %s (buffer %d/%d)", - scr_tunning_str(this->scr_tunning), - scr_tunning_str(scr_tunning), num_used, num_free ); - this->scr_tunning = scr_tunning; - - /* make it play .5% / 1% faster or slower */ - if(this->scr) - pvrscr_speed_tunning(this->scr, 1.0 + (0.005 * scr_tunning) ); - } - - /* - * SCR -> NORMAL - * - If we are in replay (or trick speed) mode, switch SCR tunning off - * as we can always have complete control on incoming data rate - */ - } else if( this->scr_tunning ) { - reset_scr_tunning(this, -1); - } -} - -#else /* ADJUST_SCR_SPEED */ - -struct pvrscr_s { - int dummy; -}; - -static void vdr_adjust_realtime_speed(vdr_input_plugin_t *this, - fifo_buffer_t *fifo1, - fifo_buffer_t *fifo2, - int speed ) -{ -} - -static void reset_scr_tunning(vdr_input_plugin_t *this, int new_speed) -{ -} - -static void scr_tunning_set_paused(vdr_input_plugin_t *this, - int speed_before_pause) -{ -} - -#endif /* ADJUST_SCR_SPEED */ - -/******************************* TOOLS ***********************************/ - -#ifndef __APPLE__ -# define MIN(a,b) ((a)<(b)?(a):(b)) -# define MAX(a,b) ((a)>(b)?(a):(b)) -#endif - -static char *strn0cpy(char *dest, const char *src, int n) -{ - char *s = dest; - for ( ; --n && (*dest = *src) != 0; dest++, src++) ; - *dest = 0; - return s; -} - -static char *unescape_filename(const char *fn) -{ - char *d = strdup(fn), *s = d, *result = d; - while(*s && *s != '#') { - if(s[0] == '%' && s[1] && s[2]) { - unsigned int c; - if (sscanf(s+1, "%02x", &c) == 1) { - *d++ = (char)c; - s += 3; - continue; - } - } - *d++ = *s++; - } - *d = 0; - return result; -} - -static int64_t pts_from_pes(const uint8_t *buf, int size) -{ - int64_t pts = INT64_C(-1); - if(size > 13 && (buf[7] & 0x80)) { /* pts avail */ - pts = ((int64_t)( buf[ 9] & 0x0E)) << 29; - pts |= (int64_t)( buf[10] << 22 ); - pts |= (int64_t)((buf[11] & 0xFE) << 14 ); - pts |= (int64_t)( buf[12] << 7 ); - pts |= (int64_t)((buf[13] & 0xFE) >> 1 ); - } - return pts; -} - -static int64_t dts_from_pes(const uint8_t *buf, int size) -{ - int64_t dts = INT64_C(-1); - if(size > 18 && (buf[7] & 0x40)) { /* dts avail */ - dts = ((int64_t)( buf[14] & 0x0E)) << 29 ; - dts |= (int64_t)( buf[15] << 22 ); - dts |= (int64_t)((buf[16] & 0xFE) << 14 ); - dts |= (int64_t)( buf[17] << 7 ); - dts |= (int64_t)((buf[18] & 0xFE) >> 1 ); - } - return dts; -} - -static void pes_strip_pts(uint8_t *buf, int size) -{ - if(size > 13 && buf[7] & 0x80) { /* pts avail */ - int pes_len = (buf[4] << 8) | buf[5]; - if ((buf[6] & 0xC0) != 0x80) - return; - if ((buf[6] & 0x30) != 0) - return; - pes_len -= 5; /* update packet len */ - buf[4] = pes_len >> 8; /* packet len (hi) */ - buf[5] = pes_len & 0xff; /* packet len (lo) */ - buf[7] &= 0x7f; /* clear pts flag */ - buf[8] -= 5; /* update header len */ - memmove(buf+9, buf+14, size-14); - } -} - -static void create_timeout_time(struct timespec *abstime, int timeout_ms) -{ - struct timeval now; - gettimeofday(&now, NULL); - now.tv_usec += timeout_ms * 1000; - while (now.tv_usec >= 1000000) { /* take care of an overflow */ - now.tv_sec++; - now.tv_usec -= 1000000; - } - abstime->tv_sec = now.tv_sec; - abstime->tv_nsec = now.tv_usec * 1000; -} - -static int io_select_rd (int fd) -{ - fd_set fdset, eset; - int ret; - struct timeval select_timeout; - - if(fd < 0) - return XIO_ERROR; - - FD_ZERO (&fdset); - FD_ZERO (&eset); - FD_SET (fd, &fdset); - FD_SET (fd, &eset); - - select_timeout.tv_sec = 0; - select_timeout.tv_usec = 500*1000; /* 500 ms */ - errno = 0; - ret = select (fd + 1, &fdset, NULL, &eset, &select_timeout); - - if (ret == 0) - return XIO_TIMEOUT; - if (ret < 0) { - if(errno == EINTR || errno == EAGAIN) - return XIO_TIMEOUT; - return XIO_ERROR; - } - if(FD_ISSET(fd,&eset)) - return XIO_ERROR; - if(FD_ISSET(fd,&fdset)) - return XIO_READY; - - return XIO_TIMEOUT; -} - -static void write_control_data(vdr_input_plugin_t *this, const char *str, size_t len) -{ - size_t ret; - while(len>0) { - - if(!this->control_running) { - LOGERR("write_control aborted"); - return; - } - -#if 1 - fd_set fdset, eset; - struct timeval select_timeout; - FD_ZERO (&fdset); - FD_ZERO (&eset); - FD_SET (this->fd_control, &fdset); - FD_SET (this->fd_control, &eset); - select_timeout.tv_sec = 0; - select_timeout.tv_usec = 500*1000; /* 500 ms */ - errno = 0; - if(1 != select (this->fd_control + 1, NULL, &fdset, &eset, &select_timeout) || - !FD_ISSET(this->fd_control, &fdset) || - FD_ISSET(this->fd_control, &eset)) { - LOGERR("write_control failed (poll timeout or error)"); - this->control_running = 0; - return; - } -#endif - - if(!this->control_running) { - LOGERR("write_control aborted"); - return; - } - - errno = 0; - ret = write(this->fd_control, str, len); - - if(ret <= 0) { - if(ret == 0) { - LOGMSG("write_control: disconnected"); - } else if(errno == EAGAIN) { - LOGERR("write_control failed: EAGAIN"); - continue; - } else if(errno == EINTR) { - LOGERR("write_control failed: EINTR"); - pthread_testcancel(); - continue; - } else { - LOGERR("write_control failed"); - } - this->control_running = 0; - return; - } - len -= ret; - str += ret; - } -} - -static void write_control(vdr_input_plugin_t *this, const char *str) -{ - size_t len = (size_t)strlen(str); - pthread_mutex_lock (&this->fd_control_lock); - write_control_data(this, str, len); - pthread_mutex_unlock (&this->fd_control_lock); -} - -static void printf_control(vdr_input_plugin_t *this, const char *fmt, ...) -{ - va_list argp; - char buf[512]; - - va_start(argp, fmt); - vsnprintf(buf, sizeof(buf), fmt, argp); - buf[sizeof(buf)-1] = 0; - - write_control(this, buf); - va_end(argp); -} - -static int readline_control(vdr_input_plugin_t *this, char *buf, int maxlen, - int timeout) -{ - int num_bytes = 0, total_bytes = 0, err; - - *buf = 0; - while(total_bytes < maxlen-1 ) { - - if(!this->control_running && timeout<0) - return -1; - - pthread_testcancel(); - err = io_select_rd(this->fd_control); - pthread_testcancel(); - - if(!this->control_running && timeout<0) - return -1; - - if(err == XIO_TIMEOUT) { - if(timeout==0) - return 0; - if(timeout>0) - timeout--; - continue; - } - if(err == XIO_ABORTED) { - LOGERR("readline_control: XIO_ABORTED at [%d]", num_bytes); - continue; - } - if(err != XIO_READY /* == XIO_ERROR */) { - LOGERR("readline_control: poll error at [%d]", num_bytes); - return -1; - } - - errno = 0; - num_bytes = read (this->fd_control, buf + total_bytes, 1); - pthread_testcancel(); - - if(!this->control_running && timeout<0) - return -1; - - if (num_bytes <= 0) { - if(num_bytes==0) - LOGERR("Control stream disconnected"); - else - LOGERR("readline_control: read error at [%d]", num_bytes); - if(num_bytes < 0 && (errno == EINTR || errno==EAGAIN)) - continue; - return -1; - } - - if(buf[total_bytes]) { - if(buf[total_bytes] == '\r') { - buf[total_bytes] = 0; - } else if(buf[total_bytes] == '\n') { - buf[total_bytes] = 0; - break; - } else { - total_bytes ++; - buf[total_bytes] = 0; - } - } - TRACE("readline_control: %d bytes ... %s\n", - total_bytes, buf); - } - - TRACE("readline_control: %d bytes (max %d)\n", total_bytes, maxlen); - - return total_bytes; -} - - -static int read_control(vdr_input_plugin_t *this, uint8_t *buf, int len) -{ - int num_bytes, total_bytes = 0, err; - - while(total_bytes < len) { - pthread_testcancel(); - err = io_select_rd(this->fd_control); - pthread_testcancel(); - - if(!this->control_running) - return -1; - - if(err == XIO_TIMEOUT) { - continue; - } - if(err == XIO_ABORTED) { - LOGERR("read_control: XIO_ABORTED"); - continue; - } - if(err == XIO_ERROR) { - LOGERR("read_control: poll error"); - return -1; - } - - errno = 0; - num_bytes = read (this->fd_control, buf + total_bytes, len - total_bytes); - pthread_testcancel(); - - if (num_bytes <= 0) { - if(this->control_running && num_bytes<0) - LOGERR("read_control read() error"); - return -1; - } - total_bytes += num_bytes; - } - - return total_bytes; -} - -static void queue_nosignal(vdr_input_plugin_t *this) -{ -#define extern static -#include "nosignal_720x576.c" -#undef extern - char *data = NULL, *tmp = NULL; - int datalen = 0, pos = 0; - buf_element_t *buf = NULL; - char *path, *home; - - if(this->stream->video_fifo->num_free(this->stream->video_fifo) < 10) { - LOGMSG("queue_nosignal: not enough free buffers (%d) !", - this->stream->video_fifo->num_free(this->stream->video_fifo)); - return; - } - - asprintf(&home,"%s/.xine/nosignal.mpg", xine_get_homedir()); - int fd = open(path=home, O_RDONLY); - if(fd<0) fd = open(path="/etc/vdr/plugins/xineliboutput/nosignal.mpg", O_RDONLY); - if(fd<0) fd = open(path="/etc/vdr/plugins/xine/noSignal.mpg", O_RDONLY); - if(fd<0) fd = open(path="/video/plugins/xineliboutput/nosignal.mpg", O_RDONLY); - if(fd<0) fd = open(path="/video/plugins/xine/noSignal.mpg", O_RDONLY); - if(fd<0) fd = open(path=NOSIGNAL_IMAGE_FILE, O_RDONLY); - if(fd>=0) { - tmp = data = malloc(NOSIGNAL_MAX_SIZE); - datalen = read(fd, data, NOSIGNAL_MAX_SIZE); - if(datalen==NOSIGNAL_MAX_SIZE) { - LOGMSG("WARNING: custom \"no signal\" image %s too large", path); - } else if(datalen<=0) { - LOGERR("error reading %s", path); - } else { - LOGMSG("using custom \"no signal\" image %s", path); - } - close(fd); - } - free(home); - - if(datalen<=0) { - data = (char*)&v_mpg_nosignal[0]; - datalen = v_mpg_nosignal_length; - } - - /* need to reset decoder if video format is not the same */ - _x_demux_control_start(this->stream); - - while(pos < datalen) { - buf = this->stream->video_fifo->buffer_pool_try_alloc(this->stream->video_fifo); - if(buf) { - buf->content = buf->mem; - buf->size = MIN(datalen - pos, buf->max_size); - buf->type = BUF_VIDEO_MPEG; - xine_fast_memcpy(buf->content, &data[pos], buf->size); - pos += buf->size; - this->stream->video_fifo->put(this->stream->video_fifo, buf); - } else { - LOGMSG("Error: queue_nosignal: no buffers !"); - break; - } - } - - free(tmp); -} - -/************************** BUFFER HANDLING ******************************/ - -static void buffer_pool_free (buf_element_t *element) -{ - fifo_buffer_t *this = (fifo_buffer_t *) element->source; - - pthread_mutex_lock (&this->buffer_pool_mutex); - - element->next = this->buffer_pool_top; - this->buffer_pool_top = element; - - this->buffer_pool_num_free++; - if (this->buffer_pool_num_free > this->buffer_pool_capacity) { - LOGERR("xine-lib:buffer: There has been a fatal error: TOO MANY FREE's"); - _x_abort(); - } - - if(this->buffer_pool_num_free > 20) - pthread_cond_signal (&this->buffer_pool_cond_not_empty); - - pthread_mutex_unlock (&this->buffer_pool_mutex); -} - -#if 0 -static buf_element_t *buffer_pool_timed_alloc(fifo_buffer_t *fifo, int timeoutMs, int buffer_limit) -{ - struct timespec abstime; - create_timeout_time(&abstime, timeoutMs); - - pthread_mutex_lock(&fifo->buffer_pool_mutex); - - while(fifo->buffer_pool_num_free <= buffer_limit) { - if(pthread_cond_timedwait (&fifo->buffer_pool_cond_not_empty, &fifo->buffer_pool_mutex, &abstime) == ETIMEDOUT) - break; - } - - pthread_mutex_unlock(&fifo->buffer_pool_mutex); - - return fifo->buffer_pool_try_alloc(fifo); -} -#endif - -#if 0 -static buf_element_t *fifo_buffer_timed_get(fifo_buffer_t *fifo, int timeoutMs) -{ - struct timespec abstime; - create_timeout_time(&abstime, timeoutMs); - - return NULL; -} -#endif - -static buf_element_t *fifo_buffer_try_get(fifo_buffer_t *fifo) -{ - int i; - buf_element_t *buf; - - pthread_mutex_lock (&fifo->mutex); - - if (fifo->first==NULL) { - pthread_mutex_unlock (&fifo->mutex); - return NULL; - } - - buf = fifo->first; - - fifo->first = fifo->first->next; - if (fifo->first==NULL) - fifo->last = NULL; - - fifo->fifo_size--; - fifo->fifo_data_size -= buf->size; - - for(i = 0; fifo->get_cb[i]; i++) - fifo->get_cb[i](fifo, buf, fifo->get_cb_data[i]); - - pthread_mutex_unlock (&fifo->mutex); - - return buf; -} - -#if 0 -static int fifo_buffer_clear(fifo_buffer_t *fifo) -{ - int bytes = 0; - buf_element_t *buf, *next, *prev=NULL; - pthread_mutex_lock (&fifo->mutex); - buf = fifo->first; - while (buf != NULL) { - next = buf->next; - if ((buf->type & BUF_MAJOR_MASK) != BUF_CONTROL_BASE) { - /* remove this buffer */ - if (prev) - prev->next = next; - else - fifo->first = next; - - if (!next) - fifo->last = prev; - - fifo->fifo_size--; - bytes += buf->size; - fifo->fifo_data_size -= buf->size; - - buf->free_buffer(buf); - } else { - prev = buf; - } - buf = next; - } - pthread_mutex_unlock (&fifo->mutex); - - return bytes; -} -#endif - -static void signal_buffer_pool_not_empty(vdr_input_plugin_t *this) -{ - if(this->buffer_pool) { - pthread_mutex_lock(&this->buffer_pool->buffer_pool_mutex); - pthread_cond_broadcast(&this->buffer_pool->buffer_pool_cond_not_empty); - pthread_mutex_unlock(&this->buffer_pool->buffer_pool_mutex); - } -} - -static void signal_buffer_not_empty(vdr_input_plugin_t *this) -{ - if(this->block_buffer) { - pthread_mutex_lock(&this->block_buffer->mutex); - pthread_cond_broadcast(&this->block_buffer->not_empty); - pthread_mutex_unlock(&this->block_buffer->mutex); - } -} - -#if XINE_VERSION_CODE < 10190 -# define fifo_buffer_new(stream, n, s) _x_fifo_buffer_new(n, s) -#else -static fifo_buffer_t *fifo_buffer_new (xine_stream_t *stream, int num_buffers, uint32_t buf_size) -{ - fifo_buffer_t *ref = stream->video_fifo; - fifo_buffer_t *this; - int i; - int alignment = 2048; - unsigned char *multi_buffer = NULL; - - LOGDBG("fifo_buffer_new..."); - this = xine_xmalloc (sizeof (fifo_buffer_t)); - - this->first = NULL; - this->last = NULL; - this->fifo_size = 0; - this->put = ref->put; - this->insert = ref->insert; - this->get = ref->get; - this->clear = ref->clear; - this->size = ref->size; - this->num_free = ref->num_free; - this->data_size = ref->data_size; - this->dispose = ref->dispose; - this->register_alloc_cb = ref->register_alloc_cb; - this->register_get_cb = ref->register_get_cb; - this->register_put_cb = ref->register_put_cb; - this->unregister_alloc_cb = ref->unregister_alloc_cb; - this->unregister_get_cb = ref->unregister_get_cb; - this->unregister_put_cb = ref->unregister_put_cb; - pthread_mutex_init (&this->mutex, NULL); - pthread_cond_init (&this->not_empty, NULL); - - /* - * init buffer pool, allocate nNumBuffers of buf_size bytes each - */ - - if (buf_size % alignment != 0) - buf_size += alignment - (buf_size % alignment); - - multi_buffer = xine_xmalloc_aligned (alignment, num_buffers * buf_size, - &this->buffer_pool_base); - - this->buffer_pool_top = NULL; - - pthread_mutex_init (&this->buffer_pool_mutex, NULL); - pthread_cond_init (&this->buffer_pool_cond_not_empty, NULL); - - this->buffer_pool_num_free = 0; - this->buffer_pool_capacity = num_buffers; - this->buffer_pool_buf_size = buf_size; - this->buffer_pool_alloc = ref->buffer_pool_alloc; - this->buffer_pool_try_alloc = ref->buffer_pool_try_alloc; - - for (i = 0; i<num_buffers; i++) { - buf_element_t *buf; - - buf = xine_xmalloc (sizeof (buf_element_t)); - - buf->mem = multi_buffer; - multi_buffer += buf_size; - - buf->max_size = buf_size; - buf->free_buffer = buffer_pool_free; - buf->source = this; - buf->extra_info = malloc(sizeof(extra_info_t)); - - buffer_pool_free (buf); - } - this->alloc_cb[0] = NULL; - this->get_cb[0] = NULL; - this->put_cb[0] = NULL; - this->alloc_cb_data[0] = NULL; - this->get_cb_data[0] = NULL; - this->put_cb_data[0] = NULL; - - LOGDBG("fifo_buffer_new done."); - return this; -} -#endif - -static buf_element_t *get_buf_element(vdr_input_plugin_t *this, int size, int force) -{ - buf_element_t *buf = NULL; - - /* HD buffer */ - if(this->hd_stream) { - if(!this->hd_buffer) - this->hd_buffer = fifo_buffer_new(this->stream, HD_BUF_NUM_BUFS, HD_BUF_ELEM_SIZE); - - if(size <= HD_BUF_ELEM_SIZE && this->hd_buffer && this->hd_stream) - buf = this->hd_buffer->buffer_pool_try_alloc(this->hd_buffer); - } else { - if(this->hd_buffer) { - LOGMSG("hd_buffer still exists ..."); - if(this->hd_buffer->num_free(this->hd_buffer) == this->hd_buffer->buffer_pool_capacity) { - LOGMSG("disposing hd_buffer ..."); - this->hd_buffer->dispose(this->hd_buffer); - this->hd_buffer = NULL; - } - } - } - - /* limit max. buffered data */ - if(!force && !buf) { - int buffer_limit = this->buffer_pool->buffer_pool_capacity - this->max_buffers; - if(this->buffer_pool->buffer_pool_num_free < buffer_limit) - return NULL; - } - - /* get smallest possible buffer */ - if(!buf) { - if(size < 8000) - buf = this->buffer_pool->buffer_pool_try_alloc(this->buffer_pool); - else if(size < 0xffff) { - buf = this->block_buffer->buffer_pool_try_alloc(this->block_buffer); - LOGDBG("get_buf_element: big PES (%d bytes) !", size); - } - else { /* len>64k */ - if(!this->big_buffer) - this->big_buffer = fifo_buffer_new(this->stream, 4, 512*1024); - buf = this->big_buffer->buffer_pool_try_alloc(this->big_buffer); - LOGDBG("get_buf_element: jumbo PES (%d bytes) !", size); - } - } - - /* final try from audio fifo */ - if(!buf) - buf = this->stream->audio_fifo->buffer_pool_try_alloc(this->stream->audio_fifo); - - if(buf) { - buf->content = buf->mem; - buf->size = 0; - buf->type = BUF_DEMUX_BLOCK; - buf->pts = 0; - - buf->free_buffer = buffer_pool_free; - } - - return buf; -} - -static void strip_network_headers(vdr_input_plugin_t *this, buf_element_t *buf) -{ - if(buf->type == BUF_MAJOR_MASK) { - if(this->udp||this->rtp) { - stream_udp_header_t *header = (stream_udp_header_t *)buf->content; - this->curpos = header->pos; - buf->content += sizeof(stream_udp_header_t); - buf->size -= sizeof(stream_udp_header_t); - } else { - stream_tcp_header_t *header = (stream_tcp_header_t *)buf->content; - this->curpos = header->pos; - buf->content += sizeof(stream_tcp_header_t); - buf->size -= sizeof(stream_tcp_header_t); - } - buf->type = BUF_DEMUX_BLOCK; - } -} - -static buf_element_t *make_padding_frame(vdr_input_plugin_t *this) -{ - static const uint8_t padding[] = {0x00,0x00,0x01,0xBE,0x00,0x02,0xff,0xff}; - buf_element_t *buf; - - buf = get_buf_element(this, 8, 1); - - if(!buf && this->stream->audio_fifo) - buf = this->stream->audio_fifo->buffer_pool_try_alloc(this->stream->audio_fifo); - - if(buf) { - buf->size = 8; - buf->content = buf->mem; - buf->type = BUF_DEMUX_BLOCK; - memcpy(buf->content, padding, 8); - } - - return buf; -} - -void put_control_buf(fifo_buffer_t *buffer, fifo_buffer_t *pool, int cmd) -{ - buf_element_t *buf = pool->buffer_pool_try_alloc(pool); - if(buf) { - buf->type = cmd; - buffer->put(buffer, buf); - } -} - -static void queue_blank_yv12(vdr_input_plugin_t *this) -{ - int ratio = _x_stream_info_get(this->stream, XINE_STREAM_INFO_VIDEO_RATIO); - double dratio; - - if(!this || !this->stream) - return; - - if(ratio > 13300 && ratio < 13400) dratio = 4.0/3.0; - else if(ratio > 17700 && ratio < 17800) dratio = 16.0/9.0; - else if(ratio > 21000 && ratio < 22000) dratio = 2.11/1.0; - else dratio = ((double)ratio)/10000.0; - - if(this->stream && this->stream->video_out) { - /* our video size is size _after_ cropping, so generate - larger image if cropping is active. This will result - in right sized image after cropping ...*/ - int width = this->video_width; - int height = this->video_height; - vo_frame_t *img = NULL; - - width += xine_get_param(this->stream, XINE_PARAM_VO_CROP_LEFT); - width += xine_get_param(this->stream, XINE_PARAM_VO_CROP_RIGHT); - height += xine_get_param(this->stream, XINE_PARAM_VO_CROP_TOP); - height += xine_get_param(this->stream, XINE_PARAM_VO_CROP_BOTTOM); - - if(width >= 360 && height >= 288 && width <= 1920 && height <= 1024) { - this->class->xine->port_ticket->acquire(this->class->xine->port_ticket, 1); - img = this->stream->video_out->get_frame (this->stream->video_out, - width, height, - dratio, XINE_IMGFMT_YV12, - VO_BOTH_FIELDS); - this->class->xine->port_ticket->release(this->class->xine->port_ticket, 1); - } - - if(img) { - if(img->format == XINE_IMGFMT_YV12 && img->base[0] && img->base[1] && img->base[2]) { - if(img->pitches[0] < width) - width = img->pitches[0]; - if(img->width < width) - width = img->width; - if(img->height < height) - height = img->height; - memset( img->base[0], 0x00, width * height); - memset( img->base[1], 0x80, width * height / 4 ); - memset( img->base[2], 0x80, width * height / 4 ); - img->duration = 3600; - img->pts = 3600; - img->bad_frame = 0; - img->draw(img, this->stream); - } - img->free(img); - } - } - - this->still_mode = 0; - _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_HAS_STILL, this->still_mode); -} - - -/*************************** slave input (PIP stream) ********************/ - -typedef struct fifo_input_plugin_s { - input_plugin_t i; - vdr_input_plugin_t *master; - xine_stream_t *stream; - fifo_buffer_t *buffer; - fifo_buffer_t *buffer_pool; - off_t pos; -} fifo_input_plugin_t; - -static int fifo_open(input_plugin_t *this_gen) -{ return 1; } -static uint32_t fifo_get_capabilities (input_plugin_t *this_gen) -{ return INPUT_CAP_BLOCK; } -static uint32_t fifo_get_blocksize (input_plugin_t *this_gen) -{ return 2 * 2048; } -static off_t fifo_get_current_pos (input_plugin_t *this_gen) -{ return -1; } -static off_t fifo_get_length (input_plugin_t *this_gen) -{ return -1; } -static off_t fifo_seek (input_plugin_t *this_gen, off_t offset, int origin) -{ return offset; } -static int fifo_get_optional_data (input_plugin_t *this_gen, void *data, int data_type) -{ return INPUT_OPTIONAL_UNSUPPORTED; } -#if XINE_VERSION_CODE > 10103 -static const char* fifo_get_mrl (input_plugin_t *this_gen) -#else -static char* fifo_get_mrl (input_plugin_t *this_gen) -#endif -{ return "xvdr+slave:"; } - -#if XINE_VERSION_CODE < 10190 -static off_t fifo_read (input_plugin_t *this_gen, char *buf, off_t len) -#else -static off_t fifo_read (input_plugin_t *this_gen, void *buf, off_t len) -#endif -{ - int got = 0; - LOGERR("fifo_input_plugin::fifo_read() not implemented !"); - exit(-1); /* assert(false); */ - return got; -} - -static buf_element_t *fifo_read_block (input_plugin_t *this_gen, - fifo_buffer_t *fifo, off_t todo) -{ - fifo_input_plugin_t *this = (fifo_input_plugin_t *) this_gen; - /*LOGDBG("fifo_read_block");*/ - - while(!this->stream->demux_action_pending) { - buf_element_t *buf = fifo_buffer_try_get(this->buffer); - if(buf) { - /* LOGDBG("fifo_read_block: got, return"); */ - return buf; - } - /* LOGDBG("fifo_read_block: no buf, poll..."); */ - /* poll(NULL, 0, 10); */ - xine_usec_sleep(5*1000); - /* LOGDBG("fifo_read_block: poll timeout"); */ - } - - LOGDBG("fifo_read_block: return NULL !"); - return NULL; -} - -static void fifo_dispose (input_plugin_t *this_gen) -{ - fifo_input_plugin_t *this = (fifo_input_plugin_t *) this_gen; - LOGDBG("fifo_dispose"); - - if(this) { - if(this->buffer) - this->buffer->dispose(this->buffer); - free(this); - } -} - -static input_plugin_t *fifo_class_get_instance (input_class_t *class_gen, - xine_stream_t *stream, - const char *data) -{ - fifo_input_plugin_t *slave = (fifo_input_plugin_t *) xine_xmalloc (sizeof(fifo_input_plugin_t)); - unsigned long int imaster; - vdr_input_plugin_t *master; - LOGDBG("fifo_class_get_instance"); - - sscanf(data+15, "%lx", &imaster); - master = (vdr_input_plugin_t*)imaster; - - slave->master = (vdr_input_plugin_t*)master; - slave->stream = stream; - slave->buffer_pool = stream->video_fifo; - slave->buffer = fifo_buffer_new(stream, 4, 4096); - slave->i.open = fifo_open; - slave->i.get_mrl = fifo_get_mrl; - slave->i.dispose = fifo_dispose; - slave->i.input_class = class_gen; - slave->i.get_capabilities = fifo_get_capabilities; - slave->i.read = fifo_read; - slave->i.read_block = fifo_read_block; - slave->i.seek = fifo_seek; - slave->i.get_current_pos = fifo_get_current_pos; - slave->i.get_length = fifo_get_length; - slave->i.get_blocksize = fifo_get_blocksize; - slave->i.get_optional_data = fifo_get_optional_data; - - return (input_plugin_t*)slave; -} - - -/******************************** OSD ************************************/ - -static int update_video_size(vdr_input_plugin_t *this) -{ -#if 0 - int w = 0, h = 0; - int64_t duration; - - this->class->xine->port_ticket->acquire(this->class->xine->port_ticket, 1); - this->stream->video_out->status(this->stream->video_out, - this->stream, &w, &h, &duration); - this->class->xine->port_ticket->release(this->class->xine->port_ticket, 1); - - if(w>0 && h>0) { - if(this->video_width != w || - this->video_height != h) { - - LOGOSD("update_video_size: new video size (%dx%d->%dx%d)", - this->video_width, this->video_height, w, h); - this->video_width = w; - this->video_height = h; - this->video_changed = 1; - return 1; - } - } -#endif - return 0; -} - -#define saturate(x,min,max) ( (x)<(min) ? (min) : (x)>(max) ? (max) : (x)) - -static void palette_rgb_to_yuy(xine_clut_t *clut, int colors) -{ - if (clut && colors>0) { - int c; - for (c=0; c<colors; c++) { - int R = clut[c].r; - int G = clut[c].g; - int B = clut[c].b; - int Y = (( + 66*R + 129*G + 25*B + 0x80) >> 8) + 16; - int CR = (( + 112*R - 94*G - 18*B + 0x80) >> 8) + 128; - int CB = (( - 38*R - 74*G + 112*B + 0x80) >> 8) + 128; - clut[c].y = saturate( Y, 16, 235); - clut[c].cb = saturate(CB, 16, 240); - clut[c].cr = saturate(CR, 16, 240); - } - } -} - -static xine_rle_elem_t *uncompress_osd_net(uint8_t *raw, int elems, int datalen) -{ - xine_rle_elem_t *data = (xine_rle_elem_t*)malloc(elems*sizeof(xine_rle_elem_t)); - int i; - - /* - * xine-lib rle format: - * - palette index and length are uint16_t - * - * network format: - * - palette entry is uint8_t - * - length is uint8_t for lengths <=0x7f and uint16_t for lengths >0x7f - * - high-order bit of first byte is used to signal size of length field: - * bit=0 -> 7-bit, bit=1 -> 15-bit - */ - - for(i=0; i<elems; i++) { - if((*raw) & 0x80) { - data[i].len = ((*(raw++)) & 0x7f) << 8; - data[i].len |= *(raw++); - } else - data[i].len = *(raw++); - data[i].color = *(raw++); - } - - return data; -} - - -/*#define NEW_SCALING*/ -#ifdef NEW_SCALING -#include "tools/rle.h" -#else -typedef enum { - scale_fast = 0, /* simple pixel doubling/dropping */ - scale_good_BW = 1, /* linear interpolation, palette re-generation */ -} scale_mode_t; -#endif - -/* re-scale compressed RLE image */ -static xine_rle_elem_t *scale_rle_image(osd_command_t *osdcmd, - int new_w, int new_h, - scale_mode_t mode) -{ - #define FACTORBASE 0x100 - #define FACTOR2PIXEL(f) ((f)>>8) - #define SCALEX(x) FACTOR2PIXEL(factor_x*(x)) - #define SCALEY(y) FACTOR2PIXEL(factor_y*(y)) - - xine_rle_elem_t *old_rle = osdcmd->data; - int old_w = osdcmd->w, old_h = osdcmd->h; - int old_y = 0, new_y = 0; - int factor_x = FACTORBASE*new_w/old_w; - int factor_y = FACTORBASE*new_h/old_h; - - xine_rle_elem_t *new_rle_start, *new_rle, *tmp; - int rle_size = 8128; - int num_rle = 0; - -#ifdef NEW_SCALING - /* try better quality grayscale 100%...200% */ - if(mode != scale_fast && - old_w <= new_w && old_w*2 >= new_w && - old_h <= new_h && old_h*2 >= new_h) { - tmp = upscale_grayscale_rle_image(osdcmd, new_w, new_h); - if(tmp) - return tmp; - } -#endif - - new_rle_start = new_rle = (xine_rle_elem_t*)malloc(4*rle_size); - - /* we assume rle elements are breaked at end of line */ - while(old_y < old_h) { - int elems_current_line = 0; - int old_x = 0, new_x = 0; - - while(old_x < old_w) { - int new_x_end = SCALEX(old_x + old_rle->len); - - if(new_x_end > new_w) { - new_x_end = new_w; - } - - new_rle->len = new_x_end - new_x; - new_rle->color = old_rle->color; - - old_x += old_rle->len; - old_rle++; /* may be incremented to last element + 1 (element is not accessed anymore) */ - - if(new_rle->len > 0) { - new_x += new_rle->len; - new_rle++; - - num_rle++; - elems_current_line++; - - if( (num_rle + 1) >= rle_size ) { - rle_size *= 2; - new_rle_start = (xine_rle_elem_t*)realloc( new_rle_start, 4*rle_size); - new_rle = new_rle_start + num_rle; - } - } - } - if(new_x < new_w) - (new_rle-1)->len += new_w - new_x; - old_y++; - new_y++; - - if(factor_y > FACTORBASE) { - /* scale up -- duplicate current line ? */ - int dup = SCALEY(old_y) - new_y; - - /* if no lines left in (old) rle, copy all lines still missing from new */ - if(old_y == old_h) - dup = new_h - new_y - 1; - - while(dup-- && (new_y+1<new_h)) { - xine_rle_elem_t *prevline; - int n; - if( (num_rle + elems_current_line + 1) >= rle_size ) { - rle_size *= 2; - new_rle_start = (xine_rle_elem_t*)realloc( new_rle_start, 4*rle_size); - new_rle = new_rle_start + num_rle; - } - - /* duplicate previous line */ - prevline = new_rle - elems_current_line; - for(n = 0; n < elems_current_line; n++) { - *new_rle++ = *prevline++; - num_rle++; - } - new_y++; - } - - } else if(factor_y < FACTORBASE) { - /* scale down -- drop next line ? */ - int skip = new_y - SCALEY(old_y); - if(old_y == old_h-1) { - /* one (old) line left ; don't skip it if new rle is not complete */ - if(new_y < new_h) - skip = 0; - } - while(skip-- && - old_y<old_h /* rounding error may add one line, filter it out */) { - for(old_x = 0; old_x < old_w;) { - old_x += old_rle->len; - old_rle++; - } - old_y++; - } - } - } - - tmp = osdcmd->data; - - osdcmd->data = new_rle_start; - osdcmd->datalen = num_rle*4; - - if(old_w != new_w) { - osdcmd->x = (0x100*osdcmd->x * new_w/old_w)>>8; - osdcmd->w = new_w; - } - if(old_h != new_h) { - osdcmd->y = (0x100*osdcmd->y * new_h/old_h)>>8; - osdcmd->h = new_h; - } - - return tmp; -} - -static int exec_osd_command(vdr_input_plugin_t *this, osd_command_t *cmd) -{ - video_overlay_event_t ov_event; - vo_overlay_t ov_overlay; - video_overlay_manager_t *ovl_manager; - int handle = -1, i; - - /* Caller must have locked this->osd_lock ! */ - - LOGOSD("exec_osd_command %d", cmd ? cmd->cmd : -1); - - /* Check parameters */ - - if(!cmd || !this || !this->stream) { - LOGMSG("exec_osd_command: Stream not initialized !"); - return CONTROL_DISCONNECTED; - } - - if(cmd->wnd < 0 || cmd->wnd >= MAX_OSD_OBJECT) { - LOGMSG("exec_osd_command: OSD window handle %d out of range !", cmd->wnd); - return CONTROL_PARAM_ERROR; - } - - handle = this->osdhandle[cmd->wnd]; - - if(handle < 0 && cmd->cmd == OSD_Close) { - LOGMSG("exec_osd_command: Attempt to close non-existing OSD (%d) !", cmd->wnd); - return CONTROL_PARAM_ERROR; - } - - /* we already have port ticket */ - ovl_manager = - this->stream->video_out->get_overlay_manager(this->stream->video_out); - - if(!ovl_manager) { - LOGMSG("exec_osd_command: Stream has no overlay manager !"); - return CONTROL_DISCONNECTED; - } - - memset(&ov_event, 0, sizeof(ov_event)); - - /* calculate exec time */ - if(cmd->pts || cmd->delay_ms) { - int64_t vpts = xine_get_current_vpts(this->stream); - if(cmd->pts) { - ov_event.vpts = cmd->pts + - this->stream->metronom->get_option(this->stream->metronom, - METRONOM_VPTS_OFFSET); - } else { - if(this->last_changed_vpts[cmd->wnd]) - ov_event.vpts = this->last_changed_vpts[cmd->wnd] + cmd->delay_ms*90; - } - /* execution time must be in future */ - if(ov_event.vpts < vpts) - ov_event.vpts = 0; - /* limit delay to 5 seconds (because of seeks and channel switches ...) */ - if(ov_event.vpts > vpts + 5*90000) - ov_event.vpts = vpts + 5*90000; - } - - /* Execute command */ - - if(cmd->cmd == OSD_Size) { - this->vdr_osd_width = cmd->w; - this->vdr_osd_height = cmd->h; - - } else if(cmd->cmd == OSD_Nop) { - this->last_changed_vpts[cmd->wnd] = xine_get_current_vpts(this->stream); - - } else if(cmd->cmd == OSD_SetPalette) { - /* TODO */ - } else if(cmd->cmd == OSD_Move) { - /* TODO */ - } else if(cmd->cmd == OSD_Set_YUV) { - /* TODO */ - } else if(cmd->cmd == OSD_Close) { - ov_event.event_type = OVERLAY_EVENT_FREE_HANDLE; - ov_event.object.handle = handle; - this->osdhandle[cmd->wnd] = -1; - free(this->osddata[cmd->wnd].data); - this->osddata[cmd->wnd].data = NULL; - free(this->osddata[cmd->wnd].palette); - this->osddata[cmd->wnd].palette = NULL; - - do { - int r = ovl_manager->add_event(ovl_manager, (void *)&ov_event); - if(r<0) { - LOGDBG("OSD_Close(%d): overlay manager queue full !", cmd->wnd); - ovl_manager->flush_events(ovl_manager); - continue; - } - break; - } while(1); - - this->last_changed_vpts[cmd->wnd] = 0; - - if((cmd->wnd==0 || this->osdhandle[cmd->wnd-1]<0) && - (cmd->wnd==MAX_OSD_OBJECT || this->osdhandle[cmd->wnd+1]<0)) { - /*LOGMSG("OSD_Close(%d): last, flush ovl manager");*/ - ovl_manager->flush_events(ovl_manager); - } - - } else if(cmd->cmd == OSD_Set_RLE) { - - int use_unscaled = 0; - int rle_scaled = 0; - int xmove = 0, ymove = 0; - int unscaled_supported = 1; - - if(handle < 0) - handle = this->osdhandle[cmd->wnd] = - ovl_manager->get_handle(ovl_manager,0); - - ov_event.event_type = OVERLAY_EVENT_SHOW; - ov_event.object.handle = handle; - ov_event.object.overlay = &ov_overlay; - ov_event.object.object_type = 1; /* menu */ - memset( ov_event.object.overlay, 0, sizeof(*ov_event.object.overlay) ); - -#if XINE_VERSION_CODE < 10101 - ov_event.object.overlay->clip_top = -1; - ov_event.object.overlay->clip_bottom = 0; - ov_event.object.overlay->clip_left = 0; - ov_event.object.overlay->clip_right = 0; -#else - ov_event.object.overlay->hili_top = -1; - ov_event.object.overlay->hili_bottom = 0; - ov_event.object.overlay->hili_left = 0; - ov_event.object.overlay->hili_right = 0; -#endif - - /* palette must contain YUV values for each color index */ - for(i=0; i<cmd->colors; i++) { - uint32_t *tmp = (uint32_t*)(cmd->palette + i); - ov_event.object.overlay->color[i] = *tmp & 0xffffff; - ov_event.object.overlay->trans[i] = (cmd->palette[i].alpha + 0x7)/0xf; - } - - if(!(this->stream->video_out->get_capabilities(this->stream->video_out) & - VO_CAP_UNSCALED_OVERLAY)) - unscaled_supported = 0; - else if(cmd->flags & OSDFLAG_UNSCALED) - use_unscaled = 1; - - /* store osd for later rescaling (done if video size changes) */ - free(this->osddata[cmd->wnd].data); - this->osddata[cmd->wnd].data = NULL; - free(this->osddata[cmd->wnd].palette); - this->osddata[cmd->wnd].palette = NULL; - - memcpy(&this->osddata[cmd->wnd], cmd, sizeof(osd_command_t)); - this->osddata[cmd->wnd].data = NULL; - if(cmd->palette) { - this->osddata[cmd->wnd].palette = malloc(sizeof(xine_clut_t)*cmd->colors); - memcpy(this->osddata[cmd->wnd].palette, cmd->palette, 4*cmd->colors); - } - - /* if video size differs from expected (VDR osd is designed for 720x576), - scale osd to video size or use unscaled (display resolution) - blending */ - if(!use_unscaled) { - int w_hi = this->vdr_osd_width * 1100 / 1000; - int w_lo = this->vdr_osd_width * 950 / 1000; - int h_hi = this->vdr_osd_height * 1100 / 1000; - int h_lo = this->vdr_osd_height * 950 / 1000; - int width_diff = 0, height_diff = 0; -#if 0 - int video_changed = update_video_size(this); - LOGOSD("video size %dx%d, margins %d..%dx%d..%d (changed: %s)", - this->video_width, this->video_height, w_lo, w_hi, h_lo, h_hi - video_changed ? "yes" : "no"); -#endif - if(this->video_width < w_lo) width_diff = -1; - else if(this->video_width > w_hi) width_diff = 1; - if(this->video_height < h_lo) height_diff = -1; - else if(this->video_height > h_hi) height_diff = 1; - - if(width_diff || height_diff) { - int new_w = (0x100*cmd->w * this->video_width - / this->vdr_osd_width)>>8; - int new_h = (0x100*cmd->h * this->video_height - / this->vdr_osd_height)>>8; - LOGOSD("Size out of margins, rescaling rle image"); - if(width_diff < 0 || height_diff < 0) - if(unscaled_supported && (cmd->flags & OSDFLAG_UNSCALED_LOWRES)) - use_unscaled = 1; - - if(!use_unscaled && cmd->scaling > 0) { - - if(height_diff || width_diff) { - this->osddata[cmd->wnd].data = cmd->data; - this->osddata[cmd->wnd].datalen = cmd->datalen; - - rle_scaled = 1; - scale_rle_image(cmd, new_w, new_h, this->class->fast_osd_scaling ? 0 : 1); - } else { - LOGOSD("osd_command: size out of margins, using UNSCALED"); - use_unscaled = unscaled_supported; - } - } - } - if(!use_unscaled && !rle_scaled) { - /* no scaling required, but may still need to re-center OSD */ - if(this->video_width != this->vdr_osd_width) - xmove = (this->video_width - this->vdr_osd_width)/2; - if(this->video_height != this->vdr_osd_height) - ymove = (this->video_height - this->vdr_osd_height)/2; - } - } - - if(use_unscaled) { - int win_width = this->stream->video_out->get_property(this->stream->video_out, - VO_PROP_WINDOW_WIDTH); - int win_height = this->stream->video_out->get_property(this->stream->video_out, - VO_PROP_WINDOW_HEIGHT); - if(cmd->scaling > 0) { - /* it is not nice to have subs in _middle_ of display when using 1440x900 etc... */ - - if(win_width > 240 && win_height > 196) { - if(cmd->scaling > 0) { - /*LOGMSG("Scaling unscaled OSD to %dx%d", win_width, win_height);*/ - if(win_width != this->vdr_osd_width || win_height != this->vdr_osd_height) { - int new_w = (0x100*cmd->w * win_width - / this->vdr_osd_width)>>8; - int new_h = (0x100*cmd->h * win_height - / this->vdr_osd_height)>>8; - - this->osddata[cmd->wnd].data = cmd->data; - this->osddata[cmd->wnd].datalen = cmd->datalen; - - rle_scaled = 1; - scale_rle_image(cmd, new_w, new_h, this->class->fast_osd_scaling ? 0 : 1); - } - } - } - } - if(!rle_scaled) { - /* no scaling required, but may still need to re-center OSD */ - if(win_width != this->vdr_osd_width) - xmove = (win_width - this->vdr_osd_width)/2; - if(win_height != this->vdr_osd_height) - ymove = (win_height - this->vdr_osd_height)/2; - } - } - - /* set position and size for this overlay */ - ov_event.object.overlay->x = cmd->x + xmove; - ov_event.object.overlay->y = cmd->y + ymove; - ov_event.object.overlay->width = cmd->w; - ov_event.object.overlay->height = cmd->h; - - /* RLE image */ - ov_event.object.overlay->unscaled = use_unscaled; - ov_event.object.overlay->rle = (rle_elem_t*)cmd->data; - ov_event.object.overlay->num_rle = cmd->datalen/4; /* two uint_16's in one element */ - ov_event.object.overlay->data_size = cmd->datalen; - - /* store rle for later scaling (done if video size changes) */ - if(/*!use_unscaled &&*/ - /*!this->osddata[cmd->wnd].data && */ - !rle_scaled /*if scaled, we already have a copy (original data)*/ ) { - this->osddata[cmd->wnd].data = malloc(cmd->datalen); - memcpy(this->osddata[cmd->wnd].data, cmd->data, cmd->datalen); - } - cmd->data = NULL;/* we 'consume' data (ownership goes for osd manager) */ - - /* send event to overlay manager */ - do { - int r = ovl_manager->add_event(ovl_manager, (void *)&ov_event); - if(r<0) { - LOGDBG("OSD_Set_RLE(%d): overlay manager queue full !", cmd->wnd); - ovl_manager->flush_events(ovl_manager); - continue; - } - break; - } while(1); - - this->last_changed_vpts[cmd->wnd] = xine_get_current_vpts(this->stream); - - } else { - LOGMSG("Unknown OSD command %d", cmd->cmd); - return CONTROL_PARAM_ERROR; - } - - LOGOSD("OSD command %d done", cmd->cmd); - return CONTROL_OK; -} - -static void vdr_scale_osds(vdr_input_plugin_t *this, - int video_width, int video_height) -{ - if(! pthread_mutex_lock(&this->osd_lock)) { - - if((this->video_width != video_width || - this->video_height != video_height || - this->video_changed) && - video_width > 0 && video_height > 0) { - int i, ticket = 0; - - LOGOSD("New video size (%dx%d->%dx%d)", - this->video_width, this->video_height, - video_width, video_height); - - this->video_width = video_width; - this->video_height = video_height; - this->video_changed = 0; - - /* just call exec_osd_command for all stored osd's. - scaling is done automatically if required. */ - for(i=0; i<MAX_OSD_OBJECT; i++) - if(this->osdhandle[i] >= 0 && - this->osddata[i].data && - this->osddata[i].scaling > 0) { - osd_command_t tmp; - memcpy(&tmp, &this->osddata[i], sizeof(osd_command_t)); - memset(&this->osddata[i], 0, sizeof(osd_command_t)); - - if(!ticket) { - this->class->xine->port_ticket->acquire(this->class->xine->port_ticket, 1); - ticket++; - } - exec_osd_command(this, &tmp); - - free(tmp.palette); - free(tmp.data); - } - if(ticket) - this->class->xine->port_ticket->release(this->class->xine->port_ticket, 1); - } - pthread_mutex_unlock(&this->osd_lock); - - } else { - LOGERR("vdr_scale_osds: pthread_mutex_lock failed"); - } -} - -static int vdr_plugin_exec_osd_command(input_plugin_t *this_gen, - osd_command_t *cmd) -{ - vdr_input_plugin_t *this = (vdr_input_plugin_t *) this_gen; - int result = CONTROL_DISCONNECTED; - int video_changed = 0; - - if (this->fd_control >= 0 && /* remote mode */ - this->funcs.intercept_osd /* frontend handles OSD */ ) { - return this->funcs.intercept_osd(this->funcs.fe_handle, cmd) ? CONTROL_OK : CONTROL_DISCONNECTED; - } - - if(!pthread_mutex_lock (&this->osd_lock)) { - if(!(cmd->flags & OSDFLAG_YUV_CLUT)) - palette_rgb_to_yuy(cmd->palette, cmd->colors); - cmd->flags &= ~OSDFLAG_YUV_CLUT; - - video_changed = update_video_size(this); - this->class->xine->port_ticket->acquire(this->class->xine->port_ticket, 1); - result = exec_osd_command(this, cmd); - this->class->xine->port_ticket->release(this->class->xine->port_ticket, 1); - pthread_mutex_unlock (&this->osd_lock); - } else { - LOGERR("vdr_plugin_exec_osd_command: pthread_mutex_lock failed"); - } - - if(video_changed) - vdr_scale_osds(this, this->video_width, this->video_height); - - return result; -} - - -/******************************* Control *********************************/ - -#if XINE_VERSION_CODE < 10111 -# define DEMUX_MUTEX_LOCK -# define DEMUX_MUTEX_UNLOCK -# define DEMUX_RESUME_SIGNAL -#else -# define DEMUX_MUTEX_LOCK pthread_mutex_lock(&stream->demux_mutex) -# define DEMUX_MUTEX_UNLOCK pthread_mutex_unlock(&stream->demux_mutex) -# define DEMUX_RESUME_SIGNAL pthread_cond_signal(&this->stream->demux_resume) -#endif - -static void suspend_demuxer(vdr_input_plugin_t *this) -{ - this->stream->demux_action_pending = 1; - signal_buffer_not_empty(this); - if(this->is_paused) - LOGMSG("WARNING: called suspend_demuxer in paused mode !"); - pthread_mutex_lock( &this->stream->demux_lock ); - this->stream->demux_action_pending = 0; - /* must be paired with resume_demuxer !!! */ -} - -static void resume_demuxer(vdr_input_plugin_t *this) -{ - /* must be paired with suspend_demuxer !!! */ - DEMUX_RESUME_SIGNAL; - pthread_mutex_unlock( &this->stream->demux_lock ); -} - -#if 0 -static void vdr_x_demux_flush_engine (xine_stream_t *stream, vdr_input_plugin_t *this) -{ - buf_element_t *buf; - - if(this->curpos > this->discard_index) { -#if 0 - LOGMSG("Possibly flushing too much !!! (diff=%"PRIu64" bytes, " - "guard @%" PRIu64 ")", - this->curpos - this->discard_index, this->guard_index); -#endif - if(this->curpos < this->guard_index) { - LOGMSG("Guard > current position, decoder flush skipped"); - return; - } - } - - stream->xine->port_ticket->acquire(stream->xine->port_ticket, 1); - - if (stream->video_out) - stream->video_out->set_property(stream->video_out, VO_PROP_DISCARD_FRAMES, 1); - if (stream->audio_out) - stream->audio_out->set_property(stream->audio_out, AO_PROP_DISCARD_BUFFERS, 1); - - fifo_buffer_clear(stream->video_fifo); - fifo_buffer_clear(stream->audio_fifo); - - DEMUX_MUTEX_LOCK; - - buf = stream->video_fifo->buffer_pool_alloc (stream->video_fifo); - buf->type = BUF_CONTROL_RESET_DECODER; - stream->video_fifo->put (stream->video_fifo, buf); - - buf = stream->audio_fifo->buffer_pool_alloc (stream->audio_fifo); - buf->type = BUF_CONTROL_RESET_DECODER; - stream->audio_fifo->put (stream->audio_fifo, buf); - - DEMUX_MUTEX_UNLOCK; - - this->prev_audio_stream_id = 0; - - /* on seeking we must wait decoder fifos to process before doing flush. - * otherwise we flush too early (before the old data has left decoders) - */ - _x_demux_control_headers_done (stream); - - if (stream->video_out) { - stream->video_out->flush(stream->video_out); - stream->video_out->set_property(stream->video_out, - VO_PROP_DISCARD_FRAMES, 0); - } - - if (stream->audio_out) { - stream->audio_out->flush(stream->audio_out); - stream->audio_out->set_property(stream->audio_out, - AO_PROP_DISCARD_BUFFERS, 0); - } - - stream->xine->port_ticket->release(stream->xine->port_ticket, 1); -} -#endif - -static void vdr_x_demux_control_newpts( xine_stream_t *stream, int64_t pts, - uint32_t flags ) -{ - buf_element_t *buf; - - DEMUX_MUTEX_LOCK; - - buf = stream->video_fifo ? stream->video_fifo->buffer_pool_try_alloc (stream->video_fifo) : NULL; - if(buf) { - buf->type = BUF_CONTROL_NEWPTS; - buf->decoder_flags = flags; - buf->disc_off = pts; - stream->video_fifo->put (stream->video_fifo, buf); - } else { - LOGMSG("vdr_x_demux_control_newpts: video fifo full !"); - } - - buf = stream->audio_fifo ? stream->audio_fifo->buffer_pool_try_alloc (stream->audio_fifo) : NULL; - if (buf) { - buf->type = BUF_CONTROL_NEWPTS; - buf->decoder_flags = flags; - buf->disc_off = pts; - stream->audio_fifo->put (stream->audio_fifo, buf); - } else { - LOGMSG("vdr_x_demux_control_newpts: audio fifo full !"); - } - - DEMUX_MUTEX_UNLOCK; -} - -static void vdr_flush_engine(vdr_input_plugin_t *this, uint64_t discard_index) -{ - int speed; - - if(this->stream_start) { - LOGMSG("vdr_flush_engine: stream_start, flush skipped"); - return; - } - - if(this->curpos > discard_index) { - if(this->curpos < this->guard_index) { - LOGMSG("vdr_flush_engine: guard > curpos, flush skipped"); - return; - } - LOGMSG("vdr_flush_engine: %"PRIu64" < current position, flush skipped", - discard_index); - return; - } - - speed = xine_get_param(this->stream, XINE_PARAM_FINE_SPEED); - if(speed <= 0) { - LOGMSG("vdr_flush_engine: speed = %d", speed); - xine_set_param(this->stream, XINE_PARAM_FINE_SPEED, XINE_FINE_SPEED_NORMAL); - } - - /* suspend demuxer */ - this->stream->demux_action_pending = 1; - if(pthread_mutex_unlock( &this->lock )) /* to let demuxer return from vdr_plugin_read_* */ - LOGERR("pthread_mutex_unlock failed !"); - suspend_demuxer(this); - pthread_mutex_lock( &this->lock ); - - reset_scr_tunning(this, this->speed_before_pause); - - /* reset speed again (adjust_realtime_speed might have set pause) */ - if(xine_get_param(this->stream, XINE_PARAM_FINE_SPEED) <= 0) { - speed = xine_get_param(this->stream, XINE_PARAM_FINE_SPEED); - LOGMSG("vdr_flush_engine: speed = %d", speed); - xine_set_param(this->stream, XINE_PARAM_FINE_SPEED, XINE_FINE_SPEED_NORMAL); - } - -#if 0 - _x_demux_flush_engine (this->stream); - /* warning: after clearing decoders fifos an absolute discontinuity - * indication must be sent. relative discontinuities are likely - * to cause "jumps" on metronom. - */ -#else - this->stream->demux_plugin->seek (this->stream->demux_plugin, - 0, 0, this->stream->demux_thread_running); -#endif - -#if XINE_VERSION_CODE < 10104 - /* disabled _x_demux_control_start as it causes alsa output driver to exit now and then ... */ -#else - _x_demux_control_start(this->stream); -#endif - this->prev_audio_stream_id = 0; - this->stream_start = 1; - this->I_frames = this->B_frames = this->P_frames = 0; - this->discard_index = discard_index; - - if(speed <= 0) - xine_set_param(this->stream, XINE_PARAM_FINE_SPEED, speed); - - resume_demuxer(this); -} - -static int set_deinterlace_method(vdr_input_plugin_t *this, const char *method_name) -{ - int method = 0; - if(!strncasecmp(method_name,"bob",3)) { method = 1; - } else if(!strncasecmp(method_name,"weave",5)) { method = 2; - } else if(!strncasecmp(method_name,"greedy",6)) { method = 3; - } else if(!strncasecmp(method_name,"onefield",8)) { method = 4; - } else if(!strncasecmp(method_name,"onefield_xv",11)) { method = 5; - } else if(!strncasecmp(method_name,"linearblend",11)) { method = 6; - } else if(!strncasecmp(method_name,"none",4)) { method = 0; - } else if(!*method_name) { method = 0; - } else if(!strncasecmp(method_name,"tvtime",6)) { method = -1; - /* old deinterlacing system must be switched off. - tvtime will be configured as all other post plugins with - "POST tvtime ..." control message */ - } else return -2; - - this->class->xine->config->update_num(this->class->xine->config, - "video.output.xv_deinterlace_method", - method >= 0 ? method : 0); - xine_set_param(this->stream, XINE_PARAM_VO_DEINTERLACE, method ? 1 : 0); - - return 0; -} - -static int set_video_properties(vdr_input_plugin_t *this, - int hue, int saturation, - int brightness, int contrast, - int vo_aspect_ratio) -{ - pthread_mutex_lock(&this->lock); - - /* when changed first time, save original/default values */ - if(!this->video_properties_saved && - (hue>=0 || saturation>=0 || contrast>=0 || brightness>=0 || - vo_aspect_ratio>=0)) { - this->video_properties_saved = 1; - this->orig_hue = xine_get_param(this->stream, - XINE_PARAM_VO_HUE ); - this->orig_saturation = xine_get_param(this->stream, - XINE_PARAM_VO_SATURATION ); - this->orig_brightness = xine_get_param(this->stream, - XINE_PARAM_VO_BRIGHTNESS ); - this->orig_contrast = xine_get_param(this->stream, - XINE_PARAM_VO_CONTRAST ); - this->orig_vo_aspect_ratio = xine_get_param(this->stream, - XINE_PARAM_VO_ASPECT_RATIO ); - } - - /* set new values, or restore default/original values */ - if(hue>=0 || this->video_properties_saved) - xine_set_param(this->stream, XINE_PARAM_VO_HUE, - hue>=0 ? hue : this->orig_hue ); - if(saturation>=0 || this->video_properties_saved) - xine_set_param(this->stream, XINE_PARAM_VO_SATURATION, - saturation>0 ? saturation : this->orig_saturation ); - if(brightness>=0 || this->video_properties_saved) - xine_set_param(this->stream, XINE_PARAM_VO_BRIGHTNESS, - brightness>=0 ? brightness : this->orig_brightness ); - if(contrast>=0 || this->video_properties_saved) - xine_set_param(this->stream, XINE_PARAM_VO_CONTRAST, - contrast>=0 ? contrast : this->orig_contrast ); - if(vo_aspect_ratio>=0 || this->video_properties_saved) - xine_set_param(this->stream, XINE_PARAM_VO_ASPECT_RATIO, - vo_aspect_ratio>=0 ? vo_aspect_ratio : this->orig_vo_aspect_ratio ); - - if(hue<0 && saturation<0 && contrast<0 && brightness<0 && vo_aspect_ratio<0) - this->video_properties_saved = 0; - - pthread_mutex_unlock(&this->lock); - return 0; -} - -static int set_live_mode(vdr_input_plugin_t *this, int onoff) -{ - pthread_mutex_lock(&this->lock); - - if(this->live_mode != onoff) { - config_values_t *config = this->class->xine->config; - this->live_mode = onoff; - - this->stream->metronom->set_option(this->stream->metronom, - METRONOM_PREBUFFER, METRONOM_PREBUFFER_VAL); - - if(this->live_mode || (this->fd_control >= 0 && !this->slave_stream)) - config->update_num(config, "audio.synchronization.av_sync_method", 1); -#if 0 - /* does not work after playing music files (?) */ - else - config->update_num(config, "audio.synchronization.av_sync_method", 0); -#endif - - } - - /* set buffer usage limits */ - this->max_buffers = this->buffer_pool->buffer_pool_capacity; - if(this->live_mode && this->fd_control < 0) - this->max_buffers >>= 1; - this->max_buffers -= 10; - - if(this->no_video) - this->max_buffers = RADIO_MAX_BUFFERS; - - /* SCR tunning */ - if(this->live_mode) { -#ifndef TEST_SCR_PAUSE - LOGSCR("pause scr tunning by set_live_mode"); - scr_tunning_set_paused(this); -#endif - } else { - LOGSCR("reset scr tunning by set_live_mode"); - reset_scr_tunning(this, this->speed_before_pause=XINE_FINE_SPEED_NORMAL); - } - - this->still_mode = 0; - _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_HAS_STILL, this->still_mode); - - pthread_mutex_unlock(&this->lock); - - signal_buffer_pool_not_empty(this); - return 0; -} - -static int set_playback_speed(vdr_input_plugin_t *this, int speed) -{ -/* speed: - <0 - show each abs(n)'th frame (drop other frames) - * no audio - 0 - paused - * audio back if mute != 0 - >0 - show each frame n times - * no audio - 1 - normal -*/ - pthread_mutex_lock(&this->lock); - this->is_paused = 0; - if(speed == 0) { - this->is_paused = 1; - } else if(speed>64 || speed<-64) { - pthread_mutex_unlock(&this->lock); - return -2; - } - - if(speed > 1 || speed < -1) { - reset_scr_tunning(this, -1); - this->is_trickspeed = 1; - } else { - this->is_trickspeed = 0; - } - - _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_HAS_STILL, this->still_mode || speed==0); - - if(speed>0) - speed = this->speed_before_pause = XINE_FINE_SPEED_NORMAL/speed; - else - speed = this->speed_before_pause = XINE_FINE_SPEED_NORMAL*(-speed); - - if(this->scr_tunning != SCR_TUNNING_PAUSED && - _x_get_fine_speed(this->stream) != speed) { - _x_set_fine_speed (this->stream, speed); - } - - if(this->slave_stream) - _x_set_fine_speed (this->slave_stream, speed); - - pthread_mutex_unlock(&this->lock); - return 0; -} - -static void send_meta_info(vdr_input_plugin_t *this) -{ - if(this->slave_stream) { - - /* send stream meta info */ - char *meta = NULL; - char *title = (char *)xine_get_meta_info(this->slave_stream, XINE_META_INFO_TITLE); - char *artist = (char *)xine_get_meta_info(this->slave_stream, XINE_META_INFO_ARTIST); - char *album = (char *)xine_get_meta_info(this->slave_stream, XINE_META_INFO_ALBUM); - char *tracknumber = (char *)xine_get_meta_info(this->slave_stream, XINE_META_INFO_TRACK_NUMBER); - - asprintf(&meta, - "INFO METAINFO title=@%s@ artist=@%s@ album=@%s@ tracknumber=@%s@\r\n", - title?:"", artist?:"", album?:"", tracknumber?:""); - - if(this->fd_control < 0) - this->funcs.xine_input_event(meta, NULL); - else - write_control(this, meta); - - free(meta); - } -} - -static void send_cd_info(vdr_input_plugin_t *this) -{ -#if 0 - // get_autoplay_list stops replay ... - int count = 0; - input_class_t *c = this->slave_stream->input_plugin->input_class; - char **list = c->get_autoplay_list(c, &count); - if(list) { - int i; - LOGMSG("cdda: %d entries", count); - for(i=0; i<count && list[i]; i++) - LOGMSG("cdda: %d: %s", i, list[i]); - } - this->autoplay_size = count; -#endif -} - -#ifdef DVD_STREAMING_SPEED -static void dvd_set_speed(const char *device, int speed) -{ - /* - * Original idea & code from mplayer-dev-eng mailing list: - * Date: Sun, 17 Dec 2006 09:15:30 +0100 - * From: Tobias Diedrich <ranma@xxxxxxxxxxxx> - * Subject: [MPlayer-dev-eng] Re: [PATCH] Add "-dvd-speed", use SET_STREAMING command to quieten DVD drives - * (http://lists-archives.org/mplayer-dev-eng/14383-add-dvd-speed-use-set_streaming-command-to-quieten-dvd-drives.html) - */ -#if defined(__linux__) && defined(SG_IO) && defined(GPCMD_SET_STREAMING) - unsigned char buffer[28], cmd[16], sense[16]; - struct sg_io_hdr sghdr; - struct stat st; - int fd; - - memset(&sghdr, 0, sizeof(sghdr)); - memset(buffer, 0, sizeof(buffer)); - memset(sense, 0, sizeof(sense)); - memset(cmd, 0, sizeof(cmd)); - memset(&st, 0, sizeof(st)); - - /* remember previous device so we can restore default speed */ - static int dvd_speed = 0; - static const char *dvd_dev = NULL; - if (speed < 0 && dvd_speed == 0) return; /* we haven't touched the speed setting */ - if (!device) device = dvd_dev; /* use previous device */ - if (!device) return; - if (!speed) return; - - if (stat(device, &st) == -1) return; - - if (!S_ISBLK(st.st_mode)) return; /* not a block device */ - - if ((fd = open(device, O_RDWR | O_NONBLOCK)) == -1) { - LOGMSG("set_dvd_speed: error opening DVD device %s for read/write", device); - return; - } - - if(speed < 0) { - /* restore default value */ - speed = 0; - buffer[0] = 4; /* restore default */ - LOGMSG("Setting DVD streaming speed to <default>"); - } else { - /* limit to <speed> KB/s */ - LOGMSG("Setting DVD streaming speed to %d", speed); - } - - sghdr.interface_id = 'S'; - sghdr.timeout = 5000; - sghdr.dxfer_direction = SG_DXFER_TO_DEV; - sghdr.mx_sb_len = sizeof(sense); - sghdr.dxfer_len = sizeof(buffer); - sghdr.cmd_len = sizeof(cmd); - sghdr.sbp = sense; - sghdr.dxferp = buffer; - sghdr.cmdp = cmd; - - cmd[0] = GPCMD_SET_STREAMING; - cmd[10] = 28; - - buffer[8] = 0xff; - buffer[9] = 0xff; - buffer[10] = 0xff; - buffer[11] = 0xff; - - buffer[12] = buffer[20] = (speed >> 24) & 0xff; /* <speed> kilobyte */ - buffer[13] = buffer[21] = (speed >> 16) & 0xff; - buffer[14] = buffer[22] = (speed >> 8) & 0xff; - buffer[15] = buffer[23] = speed & 0xff; - - buffer[18] = buffer[26] = 0x03; /* 1 second */ - buffer[19] = buffer[27] = 0xe8; - - if (ioctl(fd, SG_IO, &sghdr) < 0) - LOGERR("Failed setting DVD streaming speed to %d", speed); - else if(speed > 0) - LOGMSG("DVD streaming speed set to %d", speed); - else - LOGMSG("DVD streaming speed set to <default>"); - - dvd_speed = speed; - dvd_dev = device; - close(fd); -#else -# warning Changing DVD streaming speed not supported -#endif -} -#endif - -static void vdr_event_cb (void *user_data, const xine_event_t *event); - -static void select_spu_channel(xine_stream_t *stream, int channel) -{ - _x_select_spu_channel(stream, channel); - if (channel == SPU_CHANNEL_NONE) { - /* re-enable overlay for VDR OSD ... */ - if (stream->video_out) { - pthread_mutex_lock (&stream->frontend_lock); - stream->xine->port_ticket->acquire (stream->xine->port_ticket, 0); - - stream->video_out->enable_ovl (stream->video_out, 1); - - stream->xine->port_ticket->release (stream->xine->port_ticket, 0); - pthread_mutex_unlock (&stream->frontend_lock); - } - } -} - -static int handle_control_playfile(vdr_input_plugin_t *this, const char *cmd) -{ - const char *pt = cmd + 9; - char filename[4096], av[256], *pav = av; - int loop = 0, pos = 0, err = 0, avsize = sizeof(av)-2, mix_streams = 0; - - while(*pt==' ') pt++; - - if(!strncmp(pt, "Loop ", 5)) { - loop = 1; - pt += 5; - while(*pt==' ') pt++; - } - - pos = atoi(pt); - - while(*pt && *pt != ' ') pt++; - while(*pt == ' ') pt++; - - /* audio visualization / audio/video mixing */ - while(*pt && *pt != ' ' && --avsize) - *pav++ = *pt++; - *pav = 0; - while(*pt == ' ') pt++; - mix_streams = (!strcmp(av, "Audio")) || (!strcmp(av, "Video")); - - strn0cpy(filename, pt, sizeof(filename)); - - this->autoplay_size = -1; - - if(*filename) { - int is_file_mrl = !strncmp(filename, "file:/", 6) ? 5 : 0; - this->loop_play = 0; - - if(this->slave_stream) - handle_control_playfile(this, "PLAYFILE 0"); - - LOGMSG("PLAYFILE (Loop: %d, Offset: %ds, File: %s %s)", - loop, pos, av, filename); - - /* check if it is really a file (not mrl) and try to access it */ - if(is_file_mrl || filename[0] == '/') { - struct stat st; - char *f = unescape_filename(filename); - errno = 0; - if(stat(f+is_file_mrl, &st)) { - if(errno == EACCES || errno == ELOOP) - LOGERR("Can't access file !"); - if(errno == ENOENT || errno == ENOTDIR) - LOGERR("File not found !"); - if(this->fd_control >= 0) { - char mrl[sizeof(filename)+256], mrlbase[256]; - char *host = strdup(strstr(this->mrl, "//")+2); - char *port = strchr(host, ':'); - char *sub = strstr(filename, "#subtitle:"); - int iport = port ? atoi(port+1) : DEFAULT_VDR_PORT; - if(port) *port = 0; - if(sub) *sub = 0; - snprintf(mrlbase, sizeof(mrlbase), "http://%s:%d/PLAYFILE", - host?:"127.0.0.1", iport); - sprintf(mrl, "%s%s", mrlbase, filename + is_file_mrl); - if(sub) { - sub += 10; /*strlen("#subtitle:");*/ - strcat(mrl, "#subtitle:"); - strcat(mrl, mrlbase); - strcat(mrl, sub); - } - free(host); - LOGMSG(" -> trying to stream from server (%s) ...", mrl); - strn0cpy(filename, mrl, sizeof(filename)); - } - } - free(f); - } - - if(!strcmp(filename,"dvd:/")) { -#if 0 - /* input/media_helper.c */ - eject_media(0); /* DVD tray in */ -#endif -#ifdef DVD_STREAMING_SPEED - xine_cfg_entry_t device; - if (xine_config_lookup_entry(this->class->xine, - "media.dvd.device", &device)) - dvd_set_speed(device.str_value, 2700); -#endif - } -#if XINE_VERSION_CODE < 10109 - else if(!strncmp(filename,"dvd:/", 5)) { - /* DVD plugin 'bug': unescaping is not implemented ... */ - char *mrl = unescape_filename(filename); - strn0cpy(filename, mrl, sizeof(filename)); - free(mrl); - } -#endif - - if(!this->slave_stream) { - this->slave_stream = xine_stream_new(this->class->xine, - this->stream->audio_out, - this->stream->video_out); - } - - if(!this->slave_event_queue) { - this->slave_event_queue = xine_event_new_queue (this->slave_stream); - xine_event_create_listener_thread (this->slave_event_queue, - vdr_event_cb, this); - } - select_spu_channel(this->slave_stream, SPU_CHANNEL_AUTO); - - errno = 0; - err = !xine_open(this->slave_stream, filename); - if(err) { - LOGERR("Error opening file ! (File not found ? Unknown format ?)"); - *filename = 0; /* this triggers stop */ - } else { -#if 1 - if(this->stream->video_fifo->size(this->stream->video_fifo)) - LOGMSG("playfile: main stream video_fifo not empty ! (%d)", - this->stream->video_fifo->size(this->stream->video_fifo)); - - /* flush decoders and output fifos, close decoders and free frames. */ - _x_demux_control_start(this->stream); - xine_usec_sleep(50*1000); - - /* keep our own demux happy while playing another stream */ - set_playback_speed(this, 1); - this->live_mode = 1; - set_live_mode(this, 0); - set_playback_speed(this, 1); - reset_scr_tunning(this, this->speed_before_pause = XINE_FINE_SPEED_NORMAL); - this->slave_stream->metronom->set_option(this->slave_stream->metronom, - METRONOM_PREBUFFER, 90000); -#endif - if(!strncmp(filename, "cdda:", 5)) - send_cd_info(this); - - this->loop_play = loop; - err = !xine_play(this->slave_stream, 0, 1000 * pos); - if(err) { - LOGMSG("Error playing file"); - *filename = 0; /* this triggers stop */ - } else { - send_meta_info(this); - - if(this->funcs.fe_control) { - char tmp[128]; - int has_video; - sprintf(tmp, "SLAVE 0x%lx %s\r\n", - (unsigned long int)this->slave_stream, - mix_streams ? av : ""); - this->funcs.fe_control(this->funcs.fe_handle, tmp); - has_video = _x_stream_info_get(this->slave_stream, XINE_STREAM_INFO_HAS_VIDEO); - - if(has_video) { - int stream_width, stream_height; - stream_width = _x_stream_info_get(this->slave_stream, XINE_STREAM_INFO_VIDEO_WIDTH); - stream_height = _x_stream_info_get(this->slave_stream, XINE_STREAM_INFO_VIDEO_HEIGHT); - - if(stream_width != this->video_width || stream_height != this->video_height) { - this->video_width = stream_width; - this->video_height = stream_height; - this->video_changed = 1; - } - } - this->funcs.fe_control(this->funcs.fe_handle, - has_video ? "NOVIDEO 1\r\n" : "NOVIDEO 0\r\n"); - if(!has_video && !mix_streams && *av && strcmp(av, "none")) { - char str[128], *avopts; - if(NULL != (avopts = strchr(av, ':'))) - *avopts++ = 0; - else - avopts = ""; - snprintf(str, sizeof(str), "POST %s On %s\r\n", av, avopts); - str[sizeof(str)-1] = 0; - this->funcs.fe_control(this->funcs.fe_handle, str); - } else { - this->funcs.fe_control(this->funcs.fe_handle, "POST 0 Off\r\n"); - } - } - } - } - } - - /* next code is also executed after failed open, so no "} else { " */ - if(!*filename) { - LOGMSG("PLAYFILE <STOP>: Closing slave stream"); - this->loop_play = 0; - if(this->slave_stream) { - int stream_width, stream_height; - xine_stop(this->slave_stream); - - if (this->slave_event_queue) { - xine_event_dispose_queue (this->slave_event_queue); - this->slave_event_queue = NULL; - } - - if(this->funcs.fe_control) { - this->funcs.fe_control(this->funcs.fe_handle, "POST 0 Off\r\n"); - this->funcs.fe_control(this->funcs.fe_handle, "SLAVE 0x0\r\n"); - } - xine_close(this->slave_stream); - xine_dispose(this->slave_stream); - this->slave_stream = NULL; - - if(this->funcs.fe_control) - this->funcs.fe_control(this->funcs.fe_handle, "SLAVE CLOSED\r\n"); - - stream_width = _x_stream_info_get(this->stream, XINE_STREAM_INFO_VIDEO_WIDTH); - stream_height = _x_stream_info_get(this->stream, XINE_STREAM_INFO_VIDEO_HEIGHT); - - if(stream_width != this->video_width || stream_height != this->video_height) { - this->video_width = stream_width; - this->video_height = stream_height; - this->video_changed = 1; - } - - _x_demux_control_start(this->stream); - -#ifdef DVD_STREAMING_SPEED - dvd_set_speed(NULL, -1); -#endif - } - } - - return err ? CONTROL_PARAM_ERROR : CONTROL_OK; -} - -static int handle_control_grab(vdr_input_plugin_t *this, const char *cmd) -{ - int quality, width, height, jpeg; - jpeg = !strcmp(cmd+5,"JPEG"); - - if(3 == sscanf(cmd+5+4, "%d %d %d", &quality, &width, &height)) { - - if(this->fd_control >= 0) { - - grab_data_t *data = NULL; - uint64_t t = monotonic_time_ms(); - LOGDBG("GRAB: jpeg=%d quality=%d w=%d h=%d", jpeg, quality, width, height); - - /* grab takes long time and we don't want to lose data connection - or interrupt video ... */ - if(pthread_mutex_unlock(&this->vdr_entry_lock)) - LOGERR("pthread_mutex_unlock failed"); - - if(this->funcs.fe_control) - data = (grab_data_t*)(this->funcs.fe_control(this->funcs.fe_handle, cmd)); - - if(data && data->size>0 && data->data) { - char s[128]; - sprintf(s, "GRAB %d %d\r\n", this->token, data->size); - pthread_mutex_lock (&this->fd_control_lock); - write_control_data(this, s, strlen(s)); - write_control_data(this, data->data, data->size); - if(pthread_mutex_unlock (&this->fd_control_lock)) - LOGERR("pthread_mutex_unlock failed"); - } else { - /* failed */ - printf_control(this, "GRAB %d 0\r\n", this->token); - } - - pthread_mutex_lock(&this->vdr_entry_lock); - - if(data) - free(data->data); - free(data); - - LOGDBG("grab took %d ms", (int)(monotonic_time_ms() - t)); - return CONTROL_OK; - } - } - - return CONTROL_PARAM_ERROR; -} - -static int handle_control_substream(vdr_input_plugin_t *this, const char *cmd) -{ - unsigned int pid; - if(1 == sscanf(cmd, "SUBSTREAM 0x%x", &pid)) { - pthread_mutex_lock(&this->lock); - - if(!this->funcs.fe_control) - LOGERR("ERROR - no fe_control set !"); - - if((pid & 0xf0) == 0xe0 && this->funcs.fe_control) { /* video 0...15 */ - if(!this->pip_stream) { -LOGMSG("create pip stream %s", cmd); - this->pip_stream = - this->funcs.fe_control(this->funcs.fe_handle, cmd); -LOGMSG(" pip stream created"); - } - } else { - /*} else if(audio) {*/ - if(this->pip_stream && this->funcs.fe_control) { - LOGMSG("close pip stream"); - - this->pip_stream = NULL; - this->funcs.fe_control(this->funcs.fe_handle, cmd); - /* xine_stop(this->pip_stream); */ - /* xine_close(this->pip_stream); */ - /* xine_dispose(this->pip_stream); */ - } - } - pthread_mutex_unlock(&this->lock); - return CONTROL_OK; - } - return CONTROL_PARAM_ERROR; -} - -static int handle_control_osdcmd(vdr_input_plugin_t *this) -{ - osd_command_t osdcmd; - int err = CONTROL_OK; - - if(!this->control_running) - return CONTROL_DISCONNECTED; - - if(read_control(this, (unsigned char*)&osdcmd, sizeof(osd_command_t)) - != sizeof(osd_command_t)) { - LOGMSG("control: error reading OSDCMD data"); - return CONTROL_DISCONNECTED; - } - - ntoh_osdcmd(osdcmd); - - if(osdcmd.palette && osdcmd.colors>0) { - int bytes = sizeof(xine_clut_t)*(osdcmd.colors); - osdcmd.palette = malloc(bytes); - if(read_control(this, (unsigned char *)osdcmd.palette, bytes) - != bytes) { - LOGMSG("control: error reading OSDCMD palette"); - err = CONTROL_DISCONNECTED; - } - } else { - osdcmd.palette = NULL; - } - - if(err == CONTROL_OK && osdcmd.data && osdcmd.datalen>0) { - osdcmd.data = (xine_rle_elem_t*)malloc(osdcmd.datalen); - if(read_control(this, (unsigned char *)osdcmd.data, osdcmd.datalen) - != osdcmd.datalen) { - LOGMSG("control: error reading OSDCMD bitmap"); - err = CONTROL_DISCONNECTED; - } else { - uint8_t *raw = osdcmd.raw_data; - osdcmd.data = uncompress_osd_net(raw, osdcmd.num_rle, osdcmd.datalen); - osdcmd.datalen = osdcmd.num_rle*4; - free(raw); - } - } else { - osdcmd.data = NULL; - } - - if(err == CONTROL_OK) - err = vdr_plugin_exec_osd_command((input_plugin_t*)this, &osdcmd); - - free(osdcmd.data); - free(osdcmd.palette); - - return err; -} - -/************************** Control from VDR ******************************/ - -#define VDR_ENTRY_LOCK(ret...) \ - do { \ - if(pthread_mutex_lock(&this->vdr_entry_lock)) { \ - LOGERR("%s:%d: pthread_mutex_lock failed", __PRETTY_FUNCTION__, __LINE__); \ - return ret ; \ - } \ - } while(0) - -#define VDR_ENTRY_UNLOCK() \ - do { \ - if(pthread_mutex_unlock(&this->vdr_entry_lock)) { \ - LOGERR("%s:%d: pthread_mutex_unlock failed", __PRETTY_FUNCTION__, __LINE__); \ - } \ - } while(0) - -static const struct { - const uint32_t type; - const char name[28]; -} eventmap[] = { - {XINE_EVENT_INPUT_UP, "XINE_EVENT_INPUT_UP"}, - {XINE_EVENT_INPUT_DOWN, "XINE_EVENT_INPUT_DOWN"}, - {XINE_EVENT_INPUT_LEFT, "XINE_EVENT_INPUT_LEFT"}, - {XINE_EVENT_INPUT_RIGHT, "XINE_EVENT_INPUT_RIGHT"}, - {XINE_EVENT_INPUT_SELECT, "XINE_EVENT_INPUT_SELECT"}, - {XINE_EVENT_INPUT_MENU1, "XINE_EVENT_INPUT_MENU1"}, - {XINE_EVENT_INPUT_MENU2, "XINE_EVENT_INPUT_MENU2"}, - {XINE_EVENT_INPUT_MENU3, "XINE_EVENT_INPUT_MENU3"}, - {XINE_EVENT_INPUT_MENU4, "XINE_EVENT_INPUT_MENU4"}, - {XINE_EVENT_INPUT_MENU5, "XINE_EVENT_INPUT_MENU5"}, - {XINE_EVENT_INPUT_NEXT, "XINE_EVENT_INPUT_NEXT"}, - {XINE_EVENT_INPUT_PREVIOUS,"XINE_EVENT_INPUT_PREVIOUS"}, -}; - -static int vdr_plugin_poll(vdr_input_plugin_t *this, int timeout_ms) -{ - struct timespec abstime; - int result = 0; - - /* Caller must have locked this->vdr_entry_lock ! */ - - if(this->slave_stream) { - LOGMSG("vdr_plugin_poll: called while playing slave stream !"); - return 1; - } - - TRACE("vdr_plugin_poll (%d ms), buffer_pool: blocks=%d, bytes=%d", - timeout_ms, this->buffer_pool->size(this->buffer_pool), - this->buffer_pool->data_size(this->buffer_pool)); -#if 0 - if(this->is_paused) { - VDR_ENTRY_UNLOCK(); - - create_timeout_time(&abstime, timeout_ms); - pthread_mutex_lock (&this->buffer_pool->buffer_pool_mutex); - while(pthread_cond_timedwait (&this->buffer_pool->buffer_pool_cond_not_empty, - &this->buffer_pool->buffer_pool_mutex, - &abstime) != ETIMEDOUT) - ; - pthread_mutex_unlock (&this->buffer_pool->buffer_pool_mutex); - timeout_ms = 0; - - VDR_ENTRY_LOCK(0); - } -#endif - pthread_mutex_lock (&this->buffer_pool->buffer_pool_mutex); - result = this->buffer_pool->buffer_pool_num_free - - (this->buffer_pool->buffer_pool_capacity - this->max_buffers); - pthread_mutex_unlock (&this->buffer_pool->buffer_pool_mutex); - - if(timeout_ms > 0 && result <= 0) { - if(timeout_ms > 250) { - LOGMSG("vdr_plugin_poll: timeout too large (%d ms), forced to 250ms", timeout_ms); - timeout_ms = 250; - } - create_timeout_time(&abstime, timeout_ms); - pthread_mutex_lock(&this->lock); - if(this->scr_tunning == SCR_TUNNING_PAUSED) { - LOGSCR("scr tunning reset by POLL"); - reset_scr_tunning(this,this->speed_before_pause); - } - pthread_mutex_unlock(&this->lock); - - signal_buffer_not_empty(this); - - VDR_ENTRY_UNLOCK(); - - pthread_mutex_lock (&this->buffer_pool->buffer_pool_mutex); - while(result <= 5) { - if(pthread_cond_timedwait (&this->buffer_pool->buffer_pool_cond_not_empty, - &this->buffer_pool->buffer_pool_mutex, - &abstime) == ETIMEDOUT) - break; - result = this->buffer_pool->buffer_pool_num_free - - (this->buffer_pool->buffer_pool_capacity - this->max_buffers); - } - pthread_mutex_unlock (&this->buffer_pool->buffer_pool_mutex); - VDR_ENTRY_LOCK(0); - } - - TRACE("vdr_plugin_poll returns, %d free (%d used, %d bytes)\n", result, - this->buffer_pool->size(this->buffer_pool), - this->buffer_pool->data_size(this->buffer_pool)); - - /* handle priority problem in paused mode when - data source has higher priority than control source */ - if(result <= 0) { - result = 0; - xine_usec_sleep(3*1000); - } - - return result; -} - -/* - * Flush returns 0 if there is no data or frames in stream buffers - */ -static int vdr_plugin_flush(vdr_input_plugin_t *this, int timeout_ms) -{ - struct timespec abstime; - fifo_buffer_t *pool = this->buffer_pool; - fifo_buffer_t *buffer = this->block_buffer; - int result = 0, waitresult=0; - - /* Caller must have locked this->vdr_entry_lock ! */ - - if(this->slave_stream) { - LOGDBG("vdr_plugin_flush: called while playing slave stream !"); - return 0; - } - - TRACE("vdr_plugin_flush (%d ms) blocks=%d+%d, frames=%d", timeout_ms, - buffer->size(buffer), pool->size(pool), - this->stream->video_out->get_property(this->stream->video_out, - VO_PROP_BUFS_IN_FIFO)); - - if(this->live_mode /*&& this->fd_control < 0*/) { - /* No flush in live mode */ - return 1; - } - - this->class->xine->port_ticket->acquire(this->class->xine->port_ticket, 1); - result = MAX(0, pool->size(pool)) + - MAX(0, buffer->size(buffer)) + - this->stream->video_out->get_property(this->stream->video_out, - VO_PROP_BUFS_IN_FIFO); - this->class->xine->port_ticket->release(this->class->xine->port_ticket, 1); - - if(result>0) { - put_control_buf(buffer, pool, BUF_CONTROL_FLUSH_DECODER); - put_control_buf(buffer, pool, BUF_CONTROL_NOP); - } - - create_timeout_time(&abstime, timeout_ms); - - while(result > 0 && waitresult != ETIMEDOUT) { - TRACE("vdr_plugin_flush waiting (max %d ms), %d+%d buffers used, " - "%d frames (rd pos=%" PRIu64 ")\n", timeout_ms, - pool->size(pool), buffer->size(buffer), - (int)this->stream->video_out->get_property(this->stream->video_out, - VO_PROP_BUFS_IN_FIFO), - this->curpos); - - pthread_mutex_lock(&pool->buffer_pool_mutex); - waitresult = pthread_cond_timedwait (&pool->buffer_pool_cond_not_empty, - &pool->buffer_pool_mutex, &abstime); - pthread_mutex_unlock(&pool->buffer_pool_mutex); - - this->class->xine->port_ticket->acquire(this->class->xine->port_ticket, 1); - result = MAX(0, pool->size(pool)) + - MAX(0, buffer->size(buffer)) + - this->stream->video_out->get_property(this->stream->video_out, - VO_PROP_BUFS_IN_FIFO); - this->class->xine->port_ticket->release(this->class->xine->port_ticket, 1); - } - - TRACE("vdr_plugin_flush returns %d (%d+%d used, %d frames)\n", result, - pool->size(pool), buffer->size(buffer), - (int)this->stream->video_out->get_property(this->stream->video_out, - VO_PROP_BUFS_IN_FIFO)); - - return result; -} - -static int vdr_plugin_flush_remote(vdr_input_plugin_t *this, int timeout_ms, - uint64_t offset, int frame) -{ - int r, live_mode; - - pthread_mutex_lock(&this->lock); - - live_mode = this->live_mode; - this->live_mode = 0; /* --> 1 again when data arrives ... */ - - LOGSCR("reset scr tunning by flush_remote"); - reset_scr_tunning(this, this->speed_before_pause); - - /* wait until all data has been received */ - while(this->curpos < offset && timeout_ms > 0) { - TRACE("FLUSH: wait position (%" PRIu64 " ; need %" PRIu64 ")", - this->curpos, offset); - pthread_mutex_unlock(&this->lock); - xine_usec_sleep(3*1000); - pthread_mutex_lock(&this->lock); - timeout_ms -= 3; - } - - LOGSCR("reset scr tunning by flush_remote"); - reset_scr_tunning(this, this->speed_before_pause); - - pthread_mutex_unlock(&this->lock); - - r = vdr_plugin_flush(this, MAX(5, timeout_ms)); - printf_control(this, "RESULT %d %d\r\n", this->token, r); - - pthread_mutex_lock(&this->lock); - - this->live_mode = live_mode; - this->stream->metronom->set_option(this->stream->metronom, - METRONOM_PREBUFFER, - METRONOM_PREBUFFER_VAL); - this->guard_index = offset; - - pthread_mutex_unlock(&this->lock); - - return CONTROL_OK; -} - -static int vdr_plugin_parse_control(input_plugin_t *this_gen, const char *cmd) -{ - vdr_input_plugin_t *this = (vdr_input_plugin_t *) this_gen; - int err = CONTROL_OK, i, j; - int /*int32_t*/ tmp32 = 0; - uint64_t tmp64 = 0ULL; - xine_stream_t *stream = this->stream; - static const char str_poll[] = "POLL"; - char *pt; - - VDR_ENTRY_LOCK(CONTROL_DISCONNECTED); - - LOGCMD("vdr_plugin_parse_control: %s", cmd); - - if( *((uint32_t*)cmd) == *((uint32_t*)str_poll) || - !strncasecmp(cmd, "POLL ", 5)) { - tmp32 = atoi(cmd+5); - if(tmp32 >= 0 && tmp32 < 1000) { - if(this->fd_control >= 0) { - printf_control(this, "POLL %d\r\n", vdr_plugin_poll(this, tmp32)); - } else { - err = vdr_plugin_poll(this, tmp32); - } - } else { - err = CONTROL_PARAM_ERROR; - } - VDR_ENTRY_UNLOCK(); - return err; - } - - if(this->slave_stream) - stream = this->slave_stream; - - if(NULL != (pt = strstr(cmd, "\r\n"))) - *((char*)pt) = 0; /* auts */ - - if(!strncasecmp(cmd, "OSDCMD", 6)) { - err = handle_control_osdcmd(this); - - } else if(!strncasecmp(cmd, "VIDEO_PROPERTIES ", 17)) { - int hue, saturation, brightness, contrast, vo_aspect_ratio; - if(5 == sscanf(cmd, "VIDEO_PROPERTIES %d %d %d %d %d", - &hue, &saturation, &brightness, &contrast, &vo_aspect_ratio)) - err = set_video_properties(this, hue, saturation, brightness, contrast, vo_aspect_ratio); - else - err = CONTROL_PARAM_ERROR; - - } else if(!strncasecmp(cmd, "OVERSCAN ", 9)) { - if(!this->funcs.fe_control) - LOGMSG("No fe_control function! %s failed.", cmd); - else - this->funcs.fe_control(this->funcs.fe_handle, cmd); - - } else if(!strncasecmp(cmd, "VO_ASPECT ", 10)) { - if(1 == sscanf(cmd, "VO_ASPECT %d", &tmp32)) { - xine_set_param(stream, XINE_PARAM_VO_ASPECT_RATIO, tmp32); - } else - err = CONTROL_PARAM_ERROR; - - } else if(!strncasecmp(cmd, "DEINTERLACE ", 12)) { - if(this->fd_control < 0) - err = set_deinterlace_method(this, cmd+12); - - } else if(!strncasecmp(cmd, "EVENT ", 6)) { - int i; - char *pt = strchr(cmd, '\n'); - if(pt) *pt=0; - pt = strstr(cmd+6, " CHAPTER"); - if(pt) { - *pt = 0; - this->class->xine->config->update_num(this->class->xine->config, - "media.dvd.skip_behaviour", 1); - } - pt = strstr(cmd+6, " TITLE"); - if(pt) { - *pt = 0; - this->class->xine->config->update_num(this->class->xine->config, - "media.dvd.skip_behaviour", 2); - } - for(i=0; i<sizeof(eventmap)/sizeof(eventmap[0]); i++) - if(!strcmp(cmd+6, eventmap[i].name)) { - xine_event_t ev; - ev.type = eventmap[i].type; - ev.stream = this->slave_stream ? this->slave_stream : this->stream; - /* tag event to prevent circular input events - (vdr -> here -> event_listener -> vdr -> ...) */ - ev.data = "VDR"; - ev.data_length = 4; - xine_event_send(ev.stream, &ev); - break; - } - - } else if(!strncasecmp(cmd, "VERSION ", 7)) { - if(strncmp(XINELIBOUTPUT_VERSION " ", cmd+8, - strlen(XINELIBOUTPUT_VERSION)+1)) { - if(this->fd_control < 0) { - /* Check should use protocol version. - * In remote mode check is done in connect */ - LOGMSG("WARNING! xineplug_inp_xvdr.so and libvdr-xineliboutput.so " - "are from different version (%s and %s)", XINELIBOUTPUT_VERSION, cmd+8); - LOGMSG("Re-install plugin !"); - /*abort();*/ - } - } - - } else if(!strncasecmp(cmd, "HDMODE ", 7)) { - if(1 == sscanf(cmd, "HDMODE %d", &tmp32)) { - pthread_mutex_lock(&this->lock); - this->hd_stream = tmp32 ? 1 : 0; - pthread_mutex_unlock(&this->lock); - } - - } else if(!strncasecmp(cmd, "NOVIDEO ", 8)) { - if(1 == sscanf(cmd, "NOVIDEO %d", &tmp32)) { - pthread_mutex_lock(&this->lock); - this->no_video = tmp32; - if(this->no_video) { - this->max_buffers = RADIO_MAX_BUFFERS; - } else { - this->max_buffers = this->buffer_pool->buffer_pool_capacity; - if(!this->live_mode && this->fd_control < 0) - this->max_buffers >>= 1; - this->max_buffers -= 10; - } - pthread_mutex_unlock(&this->lock); - } else - err = CONTROL_PARAM_ERROR; - - signal_buffer_pool_not_empty(this); - - } else if(!strncasecmp(cmd, "DISCARD ", 8)) { - if(2 == sscanf(cmd, "DISCARD %" PRIu64 " %d", &tmp64, &tmp32)) { - pthread_mutex_lock(&this->lock); - if(this->discard_index < tmp64) { - this->discard_frame = tmp32; - vdr_flush_engine(this, tmp64); - this->discard_index = tmp64; - } else if(this->discard_index != tmp64) { - LOGMSG("Ignoring delayed control message %s", cmd); - } - pthread_cond_broadcast(&this->engine_flushed); - pthread_mutex_unlock(&this->lock); - } else - err = CONTROL_PARAM_ERROR; - - } else if(!strncasecmp(cmd, "STREAMPOS ", 10)) { - if(1 == sscanf(cmd, "STREAMPOS %" PRIu64, &tmp64)) { - pthread_mutex_lock(&this->lock); - vdr_flush_engine(this, tmp64); - this->curpos = tmp64; - this->discard_index = this->curpos; - this->guard_index = 0; - pthread_mutex_unlock(&this->lock); - } else - err = CONTROL_PARAM_ERROR; - - } else if(!strncasecmp(cmd, "TRICKSPEED ", 11)) { - err = (1 == sscanf(cmd, "TRICKSPEED %d", &tmp32)) ? - set_playback_speed(this, tmp32) : - CONTROL_PARAM_ERROR; - - } else if(!strncasecmp(cmd, "STILL ", 6)) { - pthread_mutex_lock(&this->lock); - /*if(this->fd_control >= 0) {*/ - if(1 == sscanf(cmd, "STILL %d", &tmp32)) { - this->still_mode = tmp32; - if(this->still_mode) - reset_scr_tunning(this, this->speed_before_pause); - _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_HAS_STILL, this->still_mode); - this->stream_start = 1; - } else - err = CONTROL_PARAM_ERROR; - /*}*/ - pthread_mutex_unlock(&this->lock); - - } else if(!strncasecmp(cmd, "SCR ", 4)) { - pthread_mutex_lock(&this->lock); - if(1 == sscanf(cmd, "SCR Sync %d", &tmp32)) { - this->scr_live_sync = 1; - pvrscr_speed_base(this->scr, tmp32); - } - else if(1 == sscanf(cmd, "SCR NoSync %d", &tmp32)) { - this->scr_live_sync = 0; - pvrscr_speed_base(this->scr, tmp32); - reset_scr_tunning(this, -1); - } - pthread_mutex_unlock(&this->lock); - - } else if(!strncasecmp(cmd, "LIVE ", 5)) { - this->still_mode = 0; - _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_HAS_STILL, this->still_mode); - err = (1 == sscanf(cmd, "LIVE %d", &tmp32)) ? - set_live_mode(this, tmp32) : -2 ; - - } else if(!strncasecmp(cmd, "MASTER ", 7)) { - if(1 == sscanf(cmd, "MASTER %d", &tmp32)) - this->fixed_scr = tmp32 ? 1 : 0; - else - err = CONTROL_PARAM_ERROR; - - } else if(!strncasecmp(cmd, "VOLUME ", 7)) { - if(1 == sscanf(cmd, "VOLUME %d", &tmp32)) { - int sw = strstr(cmd, "SW") ? 1 : 0; - if(!sw) { - xine_set_param(stream, XINE_PARAM_AUDIO_VOLUME, tmp32); - xine_set_param(stream, XINE_PARAM_AUDIO_MUTE, tmp32<=0 ? 1 : 0); - } else { - xine_set_param(stream, XINE_PARAM_AUDIO_AMP_LEVEL, tmp32); - xine_set_param(stream, XINE_PARAM_AUDIO_AMP_MUTE, tmp32<=0 ? 1 : 0); - } - if(sw != this->sw_volume_control) { - this->sw_volume_control = sw; - if(sw) { - xine_set_param(stream, XINE_PARAM_AUDIO_MUTE, 0); - } else { - xine_set_param(stream, XINE_PARAM_AUDIO_AMP_LEVEL, 100); - xine_set_param(stream, XINE_PARAM_AUDIO_AMP_MUTE, 0); - } - } - } else - err = CONTROL_PARAM_ERROR; - - } else if(!strncasecmp(cmd, "AUDIOCOMPRESSION ",17)) { - if(1 == sscanf(cmd, "AUDIOCOMPRESSION %d", &tmp32)) { - xine_set_param(stream, XINE_PARAM_AUDIO_COMPR_LEVEL, tmp32); - } else - err = CONTROL_PARAM_ERROR; - - } else if(!strncasecmp(cmd, "AUDIOSURROUND ",14)) { - if(1 == sscanf(cmd, "AUDIOSURROUND %d", &tmp32)) { - this->class->xine->config->update_num(this->class->xine->config, - "audio.a52.surround_downmix", tmp32?1:0); - } else - err = CONTROL_PARAM_ERROR; - - } else if(!strncasecmp(cmd, "SPEAKERS ",9)) { - if(1 == sscanf(cmd, "SPEAKERS %d", &tmp32)) { - this->class->xine->config->update_num(this->class->xine->config, - "audio.output.speaker_arrangement", tmp32); - } else - err = CONTROL_PARAM_ERROR; - - } else if(!strncasecmp(cmd, "EQUALIZER ", 10)) { - int eqs[XINE_PARAM_EQ_16000HZ - XINE_PARAM_EQ_30HZ + 2] = {0}; - sscanf(cmd,"EQUALIZER %d %d %d %d %d %d %d %d %d %d", - eqs,eqs+1,eqs+2,eqs+3,eqs+4,eqs+5,eqs+6,eqs+7,eqs+8,eqs+9); - for(i=XINE_PARAM_EQ_30HZ,j=0; i<=XINE_PARAM_EQ_16000HZ; i++,j++) - xine_set_param(stream, i, eqs[j]); - - } else if(!strncasecmp(cmd, "AUDIOSTREAM ", 12)) { - if(!this->slave_stream) { - int ac3 = strncmp(cmd+12, "AC3", 3) ? 0 : 1; - if(1 == sscanf(cmd+12 + 4*ac3, "%d", &tmp32)) { - pthread_mutex_lock(&this->lock); - this->audio_stream_id = tmp32; - pthread_mutex_unlock(&this->lock); - } else { - err = CONTROL_PARAM_ERROR; - } - } else { - if(1 == sscanf(cmd, "AUDIOSTREAM AC3 %d", &tmp32)) { - tmp32 &= 0xff; - LOGDBG("Audio channel -> [%d]", tmp32); - xine_set_param(stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL, tmp32); - } - LOGDBG("Audio channel selected: [%d]", _x_get_audio_channel (stream)); - } - - } else if(!strncasecmp(cmd, "SPUSTREAM ", 10)) { - int old_ch = _x_get_spu_channel (stream); - int max_ch = xine_get_stream_info(stream, XINE_STREAM_INFO_MAX_SPU_CHANNEL); - int ch = old_ch; - if(strstr(cmd, "NEXT")) - ch = ch < max_ch ? ch+1 : -2; - else if(strstr(cmd, "PREV")) - ch = ch > -2 ? ch-1 : max_ch-1; - else if(1 == sscanf(cmd, "SPUSTREAM %d", &tmp32)) { - ch = tmp32; - } else - err = CONTROL_PARAM_ERROR; - if(ch != old_ch) { - select_spu_channel(stream, ch); - LOGDBG("SPU channel selected: [%d]", _x_get_spu_channel (stream)); - } - - } else if(!strncasecmp(cmd, "AUDIODELAY ", 11)) { - if(1 == sscanf(cmd, "AUDIODELAY %d", &tmp32)) - xine_set_param(stream, XINE_PARAM_AV_OFFSET, tmp32*90000/1000); - else - err = CONTROL_PARAM_ERROR; - - } else if(!strncasecmp(cmd, "SYNC ", 5)) { - if(this->fd_control >= 0) - write_control(this, cmd); - - } else if(!strncasecmp(cmd, "GETSTC", 6)) { - int64_t pts = xine_get_current_vpts(stream) - - stream->metronom->get_option(stream->metronom, - METRONOM_VPTS_OFFSET); - if(this->fd_control >= 0) { - printf_control(this, "STC %" PRId64 "\r\n", pts); - } else { - *((int64_t *)cmd) = pts; - } - - } else if(!strncasecmp(cmd, "FLUSH ", 6)) { - if(1 == sscanf(cmd, "FLUSH %d", &tmp32)) { - if(this->fd_control >= 0) { - uint32_t frame = 0; - tmp64 = 0ULL; - tmp32 = 0; - sscanf(cmd, "FLUSH %d %" PRIu64 " %d", &tmp32, &tmp64, &frame); - err = vdr_plugin_flush_remote(this, tmp32, tmp64, frame); - } else { - err = vdr_plugin_flush(this, tmp32); - } - } else - err = CONTROL_PARAM_ERROR; - - } else if(!strncasecmp(cmd, "TOKEN ", 6)) { - this->token = atoi(cmd+6); - - } else if(!strncasecmp(cmd, "SUBSTREAM ", 9)) { - err = handle_control_substream(this, cmd); - - } else if(!strncasecmp(cmd, "POST ", 5)) { - /* lock demuxer thread out of adjust_realtime_speed */ - pthread_mutex_lock(&this->lock); - if(!this->funcs.fe_control) - LOGMSG("No fe_control function! %s failed.", cmd); - else - this->funcs.fe_control(this->funcs.fe_handle, cmd); - pthread_mutex_unlock(&this->lock); - - } else if(!strncasecmp(cmd, "PLAYFILE ", 9)) { - err = handle_control_playfile(this, cmd); - if(this->fd_control >= 0) { - printf_control(this, "RESULT %d %d\r\n", this->token, err); - err = CONTROL_OK; - } - - } else if(!strncasecmp(cmd, "SEEK ", 5)) { - if(this->slave_stream) { - int pos_stream=0, pos_time=0, length_time=0; - xine_get_pos_length(this->slave_stream, - &pos_stream, &pos_time, &length_time); - if(cmd[5]=='+') - pos_time += atoi(cmd+6) * 1000; - else if(cmd[5]=='-') - pos_time -= atoi(cmd+6) * 1000; - else - pos_time = atoi(cmd+5) * 1000; - err = xine_play (this->slave_stream, 0, pos_time); - if(this->fd_control >= 0) - err = CONTROL_OK; - } - - } else if(!strncasecmp(cmd, "GETLENGTH", 9)) { - int pos_stream=0, pos_time=0, length_time=0; - xine_get_pos_length(stream, &pos_stream, &pos_time, &length_time); - err = length_time/*/1000*/; - if(this->fd_control >= 0) { - printf_control(this, "RESULT %d %d\r\n", this->token, err); - err = CONTROL_OK; - } - - } else if(!strncasecmp(cmd, "GETAUTOPLAYSIZE", 15)) { - if(this->autoplay_size < 0) { - char **list; - if(this->slave_stream && - this->slave_stream->input_plugin && - this->slave_stream->input_plugin->input_class) - list = this->slave_stream->input_plugin->input_class-> - get_autoplay_list(this->slave_stream->input_plugin->input_class, &this->autoplay_size); - } - err = this->autoplay_size; - if(this->fd_control >= 0) { - printf_control(this, "RESULT %d %d\r\n", this->token, err); - err = CONTROL_OK; - } - - } else if(!strncasecmp(cmd, "GETPOS", 6)) { - int pos_stream=0, pos_time=0, length_time=0; - xine_get_pos_length(stream, &pos_stream, &pos_time, &length_time); - err = pos_time/*/1000*/; - if(this->fd_control >= 0) { - printf_control(this, "RESULT %d %d\r\n", this->token, err); - err = CONTROL_OK; - } - - } else if(!strncasecmp(cmd, "SUBTITLES ", 10)) { - if(this->slave_stream) { - int vpos = 0; - if(1 == sscanf(cmd, "SUBTITLES %d", &vpos)) - this->class->xine->config->update_num(this->class->xine->config, - "subtitles.separate.vertical_offset", vpos); - else - err = CONTROL_PARAM_ERROR; - } - - } else if(!strncasecmp(cmd, "EXTSUBSIZE ", 11)) { - int size = 0; - if(1 == sscanf(cmd, "EXTSUBSIZE %d", &size)) - /* size of separate subtitles : - -1 = xine default - 0...6 = { tiny small normal large very large huge } */ - this->class->xine->config->update_num(this->class->xine->config, - "subtitles.separate.subtitle_size", size); - else - err = CONTROL_PARAM_ERROR; - - } else if(!strncasecmp(cmd, "GRAB ", 5)) { - handle_control_grab(this, cmd); - - /* next ones need to be synchronized to data stream */ - } else if(!strncasecmp(cmd, "BLANK", 5)) { - put_control_buf(this->block_buffer, this->buffer_pool, CONTROL_BUF_BLANK); - - } else if(!strncasecmp(cmd, "CLEAR", 5)) { - /* #warning should be delayed and executed in read_block */ - - } else { - LOGMSG("unknown control %s", cmd); - err = CONTROL_UNKNOWN; - } - - LOGCMD("vdr_plugin_parse_control: DONE (%d): %s", err, cmd); - - VDR_ENTRY_UNLOCK(); - - return err; -} - -static void *vdr_control_thread(void *this_gen) -{ - vdr_input_plugin_t *this = (vdr_input_plugin_t *) this_gen; - char line[8128]; - int err; - int counter = 100; - - LOGDBG("Control thread started"); - - /*(void)nice(-1);*/ - - /* wait until state changes from open to play */ - while(bSymbolsFound && counter>0 && ! this->funcs.fe_control) { - xine_usec_sleep(50*1000); - counter--; - } - - write_control(this, "CONFIG\r\n"); - - while(this->control_running) { - - /* read next command */ - line[0] = 0; - pthread_testcancel(); - if((err=readline_control(this, line, sizeof(line)-1, -1)) <= 0) { - if(err < 0) - break; - continue; - } - LOGCMD("Received command %s",line); - pthread_testcancel(); - - if(!this->control_running) - break; - - /* parse */ - switch(err = vdr_plugin_parse_control(this_gen, line)) { - case CONTROL_OK: - break; - case CONTROL_UNKNOWN: - LOGMSG("unknown control message %s", line); - break; - case CONTROL_PARAM_ERROR: - LOGMSG("invalid parameter in control message %s", line); - break; - case CONTROL_DISCONNECTED: - LOGMSG("control stream read error - disconnected ?"); - this->control_running = 0; - break; - default: - LOGMSG("parse_control failed with result: %d", err); - break; - } - } - - if(this->control_running) - write_control(this, "CLOSE\r\n"); - this->control_running = 0; - - if(this->slave_stream) - xine_stop(this->slave_stream); - - LOGDBG("Control thread terminated"); - pthread_exit(NULL); -} - -/**************************** Control to VDR ********************************/ - -static void slave_track_maps_changed(vdr_input_plugin_t *this) -{ - char tracks[1024], lang[128]; - int i, current, n = 0, cnt; - - /* Audio tracks */ - - strcpy(tracks, "INFO TRACKMAP AUDIO "); - cnt = strlen(tracks); - current = xine_get_param(this->slave_stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL); - for(i=0; i<32 && cnt<sizeof(tracks)-32; i++) - if(xine_get_audio_lang(this->slave_stream, i, lang)) { - while(lang[0]==' ') strcpy(lang, lang+1); - cnt += snprintf(tracks+cnt, sizeof(tracks)-cnt-32, - "%s%d:%s ", i==current?"*":"", i, lang); - n++; - } - tracks[sizeof(tracks)-1] = 0; - if(n>1) - LOGDBG("%s", tracks); - - if(this->funcs.xine_input_event) { - /* local mode: -> VDR */ - this->funcs.xine_input_event(tracks, NULL); - } else { - /* remote mode: -> connection -> VDR */ - strcpy(tracks+cnt, "\r\n"); - write_control(this, tracks); - } - - /* DVD SPU tracks */ - - n = 0; - strcpy(tracks, "INFO TRACKMAP SPU "); - cnt = strlen(tracks); - current = _x_get_spu_channel (this->slave_stream); - if(current < 0) { - /* -2 == none, -1 == auto */ - cnt += snprintf(tracks+cnt, sizeof(tracks)-cnt-32, - "*%d:%s ", current, - current==SPU_CHANNEL_NONE ? "none" : "auto"); - n++; - } - for(i=0; i<32 && cnt<sizeof(tracks)-32; i++) - if(xine_get_spu_lang(this->slave_stream, i, lang)) { - while(lang[0]==' ') strcpy(lang, lang+1); - cnt += snprintf(tracks+cnt, sizeof(tracks)-cnt-32, - "%s%d:%s ", i==current?"*":"", i, lang); - n++; - } - tracks[sizeof(tracks)-1] = 0; - if(n>1) - LOGDBG("%s", tracks); - - if(this->funcs.xine_input_event) { - this->funcs.xine_input_event(tracks, NULL); - } else { - strcpy(tracks+cnt, "\r\n"); - write_control(this, tracks); - } - -#ifdef XINE_STREAM_INFO_DVD_TITLE_NUMBER - i = _x_stream_info_get(this->slave_stream,XINE_STREAM_INFO_DVD_TITLE_NUMBER); - if(i >= 0) { - sprintf(tracks, "INFO DVDTITLE %d\r\n", i); - if(this->funcs.xine_input_event) - this->funcs.xine_input_event(tracks, NULL); - else - write_control(this, tracks); - LOGDBG(tracks); - } -#endif -} - -/* Map some xine input events to vdr input (remote key names) */ -static const struct { - const uint32_t event; - const char name[12]; -} vdr_keymap[] = { - {XINE_EVENT_INPUT_NEXT, "Next"}, - {XINE_EVENT_INPUT_PREVIOUS, "Previous"}, - - {XINE_EVENT_INPUT_DOWN, "Down"}, - {XINE_EVENT_INPUT_UP, "Up"}, - {XINE_EVENT_INPUT_LEFT, "Left"}, - {XINE_EVENT_INPUT_RIGHT, "Right"}, - {XINE_EVENT_INPUT_SELECT, "Ok"}, - - {XINE_EVENT_INPUT_MENU1, "Menu"}, - {XINE_EVENT_INPUT_MENU2, "Red"}, - {XINE_EVENT_INPUT_MENU3, "Green"}, - {XINE_EVENT_INPUT_MENU4, "Yellow"}, - {XINE_EVENT_INPUT_MENU5, "Blue"}, - {XINE_EVENT_INPUT_NUMBER_0, "0"}, - {XINE_EVENT_INPUT_NUMBER_1, "1"}, - {XINE_EVENT_INPUT_NUMBER_2, "2"}, - {XINE_EVENT_INPUT_NUMBER_3, "3"}, - {XINE_EVENT_INPUT_NUMBER_4, "4"}, - {XINE_EVENT_INPUT_NUMBER_5, "5"}, - {XINE_EVENT_INPUT_NUMBER_6, "6"}, - {XINE_EVENT_INPUT_NUMBER_7, "7"}, - {XINE_EVENT_INPUT_NUMBER_8, "8"}, - {XINE_EVENT_INPUT_NUMBER_9, "9"}, - -#if defined(XINE_EVENT_VDR_RED) - {XINE_EVENT_VDR_BACK, "Back"}, - {XINE_EVENT_VDR_CHANNELPLUS, "Channel+"}, - {XINE_EVENT_VDR_CHANNELMINUS, "Channel-"}, - {XINE_EVENT_VDR_RED, "Red"}, - {XINE_EVENT_VDR_GREEN, "Green"}, - {XINE_EVENT_VDR_YELLOW, "Yellow"}, - {XINE_EVENT_VDR_BLUE, "Blue"}, - {XINE_EVENT_VDR_PLAY, "Play"}, - {XINE_EVENT_VDR_PAUSE, "Pause"}, - {XINE_EVENT_VDR_STOP, "Stop"}, - {XINE_EVENT_VDR_RECORD, "Record"}, - {XINE_EVENT_VDR_FASTFWD, "FastFwd"}, - {XINE_EVENT_VDR_FASTREW, "FastRew"}, - {XINE_EVENT_VDR_POWER, "Power"}, - {XINE_EVENT_VDR_SCHEDULE, "Schedule"}, - {XINE_EVENT_VDR_CHANNELS, "Channels"}, - {XINE_EVENT_VDR_TIMERS, "Timers"}, - {XINE_EVENT_VDR_RECORDINGS, "Recordings"}, - {XINE_EVENT_VDR_SETUP, "Setup"}, - {XINE_EVENT_VDR_COMMANDS, "Commands"}, - {XINE_EVENT_VDR_USER1, "User1"}, - {XINE_EVENT_VDR_USER2, "User2"}, - {XINE_EVENT_VDR_USER3, "User3"}, - {XINE_EVENT_VDR_USER4, "User4"}, - {XINE_EVENT_VDR_USER5, "User5"}, - {XINE_EVENT_VDR_USER6, "User6"}, - {XINE_EVENT_VDR_USER7, "User7"}, - {XINE_EVENT_VDR_USER8, "User8"}, - {XINE_EVENT_VDR_USER9, "User9"}, - {XINE_EVENT_VDR_VOLPLUS, "Volume+"}, - {XINE_EVENT_VDR_VOLMINUS, "Volume-"}, - {XINE_EVENT_VDR_MUTE, "Mute"}, - {XINE_EVENT_VDR_AUDIO, "Audio"}, -#endif -#if defined(XINE_EVENT_VDR_INFO) - {XINE_EVENT_VDR_INFO, "Info"}, -#endif -#if defined(XINE_EVENT_VDR_SUBTITLES) - {XINE_EVENT_VDR_SUBTITLES, "Subtitles"}, -#endif -}; - -static void vdr_event_cb (void *user_data, const xine_event_t *event) -{ - vdr_input_plugin_t *this = (vdr_input_plugin_t *)user_data; - int i; - - for(i=0; i < sizeof(vdr_keymap)/sizeof(vdr_keymap[0]); i++) { - if(event->type == vdr_keymap[i].event) { - if(event->data && event->data_length == 4 && - !strncmp(event->data, "VDR", 4)) { - /*LOGMSG("Input event created by self, ignoring");*/ - return; - } - LOGDBG("XINE_EVENT (input) %d --> %s", - event->type, vdr_keymap[i].name); - - if(this->funcs.input_control) { - /* remote mode: -> input_plugin -> connection -> VDR */ - this->funcs.input_control((input_plugin_t *)this, - NULL, vdr_keymap[i].name, 0, 0); - } - if(this->funcs.xine_input_event) { - /* local mode: -> VDR */ - this->funcs.xine_input_event(NULL, vdr_keymap[i].name); - } - return; - } - } - - switch (event->type) { - case XINE_EVENT_UI_SET_TITLE: - if(event->stream==this->slave_stream) { - char msg[256], titlen[64] = ""; - xine_ui_data_t *data = (xine_ui_data_t *)event->data; - LOGMSG("XINE_EVENT_UI_SET_TITLE: %s", data->str); - -#ifdef XINE_STREAM_INFO_DVD_TITLE_NUMBER - int tt = _x_stream_info_get(this->slave_stream,XINE_STREAM_INFO_DVD_TITLE_NUMBER); - snprintf(titlen, sizeof(titlen), "INFO DVDTITLE %d\r\n", tt); -#endif - snprintf(msg, sizeof(msg), "INFO TITLE %s\r\n%s", data->str, titlen); - msg[sizeof(msg)-1] = 0; - if(this->funcs.xine_input_event) - this->funcs.xine_input_event(msg, NULL); - else - write_control(this, msg); - break; - } - - case XINE_EVENT_UI_CHANNELS_CHANGED: - if(event->stream==this->slave_stream) - slave_track_maps_changed(this); - break; - - case XINE_EVENT_FRAME_FORMAT_CHANGE: - { - xine_format_change_data_t *frame_change = - (xine_format_change_data_t *)event->data; - LOGOSD("XINE_EVENT_FRAME_FORMAT_CHANGE (%dx%d, aspect=%d)", - frame_change->width, frame_change->height, - frame_change->aspect); - if(!frame_change->aspect) /* from frontend */ - vdr_scale_osds(this, frame_change->width, frame_change->height); -#if 0 - if(frame_change->aspect) - queue_blank_yv12(this); -#endif - } - break; - - case XINE_EVENT_UI_PLAYBACK_FINISHED: - if(event->stream == this->stream) { - LOGMSG("XINE_EVENT_UI_PLAYBACK_FINISHED"); - this->control_running = 0; -#if 1 - if(iSysLogLevel > 2) { - /* dump whole xine log as we should not be here ... */ - xine_t *xine = this->class->xine; - int i, j; - int logs = xine_get_log_section_count(xine); - const char * const * names = xine_get_log_names(xine); - for(i=0; i<logs; i++) { -#if XINE_VERSION_CODE < 10105 - const char * const * lines = xine_get_log(xine, i); -#else - char * const * lines = xine_get_log(xine, i); -#endif - if(lines[0]) { - printf("\nLOG: %s\n",names[i]); - for(j=0; lines[j] && *lines[j]; j++) - printf(" %2d: %s", j, lines[j]); - } - } - } -#endif - } else if(event->stream == this->slave_stream) { - LOGMSG("XINE_EVENT_UI_PLAYBACK_FINISHED (slave stream)"); - if(this->fd_control >= 0) { - write_control(this, "ENDOFSTREAM\r\n"); - } else { - if(this->funcs.fe_control) - this->funcs.fe_control(this->funcs.fe_handle, "ENDOFSTREAM\r\n"); -#if 0 - if(!this->loop_play) { - /* forward to vdr-fe (listening only VDR stream events) */ - xine_event_t event; - event.data_length = 0; - event.type = XINE_EVENT_UI_PLAYBACK_FINISHED; - xine_event_send (this->stream, &event); - } else { -# if 0 - xine_usec_sleep(500*1000); - xine_play(this->slave_stream, 0, 0); -# endif - } -#endif - } - } - break; - - default: - LOGCMD("Got an xine event, type 0x%08x", event->type); - break; - } -} - -/**************************** Data Stream *********************************/ - -static void data_stream_parse_control(vdr_input_plugin_t *this, char *cmd) -{ - char *tmp; - - cmd[64] = 0; - if(NULL != (tmp=strchr(cmd, '\r'))) - *tmp = '\0'; - if(NULL != (tmp=strchr(cmd, '\n'))) - *tmp = '\0'; - - if(!strncasecmp(cmd, "DISCARD ", 8)) { - uint64_t index; - if(1 == sscanf(cmd, "DISCARD %" PRIu64, &index)) { - struct timespec abstime; - create_timeout_time(&abstime, 100); - - this->block_buffer->clear(this->block_buffer); - - pthread_mutex_lock(&this->lock); - while(this->control_running && - this->discard_index < index) { - LOGDBG("data_stream_parse_control: waiting for engine_flushed condition %"PRIu64"<%"PRIu64, - this->discard_index, index); - pthread_cond_timedwait(&this->engine_flushed, &this->lock, &abstime); - } - pthread_mutex_unlock(&this->lock); - LOGDBG("data_stream_parse_control: streams synced at %"PRIu64"/%"PRIu64, - index, this->discard_index); - } - return; - } - - vdr_plugin_parse_control((input_plugin_t*)this, cmd); -} - -static int vdr_plugin_read_net_tcp(vdr_input_plugin_t *this) -{ - buf_element_t *read_buffer = NULL; - int cnt = 0, todo = 0, n, result, retries = 0; - - retry: - while(XIO_READY == (result = io_select_rd(this->fd_data))) { - - if(!this->control_running) - break; - - /* Allocate buffer */ - if(!read_buffer) { - - /* can't cancel if read_buffer != NULL (disposing fifos would freeze) */ - pthread_testcancel(); - - read_buffer = get_buf_element(this, 0, 0); - if(!read_buffer) { - VDR_ENTRY_LOCK(XIO_ERROR); - vdr_plugin_poll(this, 100); - VDR_ENTRY_UNLOCK(); - - if(!this->control_running) - break; - - read_buffer = get_buf_element(this, 0, 0); - if(!read_buffer) { - /* do not drop any data here ; dropping is done only at server side. */ - if(!this->is_paused) - LOGDBG("TCP: fifo buffer full"); - xine_usec_sleep(3*1000); - continue; /* must call select to check fd for errors / closing */ - } - } - - todo = sizeof(stream_tcp_header_t); - cnt = 0; - } - - /* Read data */ - errno = 0; - n = read(this->fd_data, &read_buffer->mem[cnt], todo-cnt); - if(n <= 0) { - if(!n || (errno != EINTR && errno != EAGAIN)) { - if(n<0 && this->fd_data>=0) - LOGERR("TCP read error (data stream %d : %d)", this->fd_data, n); - if(n==0) - LOGMSG("Data stream disconnected"); - result = XIO_ERROR; - break; - } - continue; - } - - cnt += n; - - if(cnt == sizeof(stream_tcp_header_t)) { - /* Header complete */ - stream_tcp_header_t *hdr = ((stream_tcp_header_t *)read_buffer->content); - hdr->len = ntohl(hdr->len); - hdr->pos = ntohull(hdr->pos); - - todo = cnt + hdr->len; - if(todo+cnt >= read_buffer->max_size) { - LOGMSG("TCP: Buffer too small (%d ; incoming frame %d bytes)", - read_buffer->max_size, todo + cnt); - todo = read_buffer->max_size - cnt - 1; - } - } - - if(cnt >= todo) { - /* Buffer complete */ - stream_tcp_header_t *hdr = ((stream_tcp_header_t *)read_buffer->content); - if(hdr->pos == (uint64_t)(-1ULL) /*0xffffffff ffffffff*/) { - /* control data */ - uint8_t *pkt_data = read_buffer->content + sizeof(stream_tcp_header_t); - if(pkt_data[0]) { /* -> can't be pes frame */ - data_stream_parse_control(this, (char*)pkt_data); - - /* read next block */ - todo = sizeof(stream_tcp_header_t); - cnt = 0; - continue; - } - } - - /* frame ready */ - read_buffer->size = cnt; - read_buffer->type = BUF_MAJOR_MASK; - this->block_buffer->put(this->block_buffer, read_buffer); - read_buffer = NULL; - } - } - - if(read_buffer) { - if(cnt && this->control_running && result == XIO_TIMEOUT && (++retries < 10)) { - LOGMSG("TCP: Warning: long delay (>500ms) !"); - goto retry; - } - - read_buffer->free_buffer(read_buffer); - read_buffer = NULL; - if(cnt && this->fd_data >= 0 && result == XIO_TIMEOUT) { - LOGMSG("TCP: Delay too long, disconnecting"); - this->control_running = 0; - return XIO_ERROR; - } - } - - return result; -} - -static int vdr_plugin_read_net_udp(vdr_input_plugin_t *this) -{ - struct sockaddr_in server_address; - socklen_t address_len = sizeof(server_address); - udp_data_t *udp = this->udp_data; - stream_udp_header_t *pkt; - stream_rtp_header_impl_t *rtp_pkt; - uint8_t *pkt_data; - int result = XIO_ERROR, n, current_seq, timeouts = 0; - buf_element_t *read_buffer = NULL; - - while(this->control_running && this->fd_data >= 0) { - - result = _x_io_select(this->stream, this->fd_data, - XIO_READ_READY, 20); - - if(result != XIO_READY) { - if(result == XIO_TIMEOUT) { - if(timeouts++ > 25) - return XIO_TIMEOUT; - continue; - } - return result; - } - timeouts = 0; - - if(!this->control_running) - break; - - /* - * allocate buffer and read incoming UDP packet from socket - */ - - if(!read_buffer) { - - pthread_testcancel(); - - read_buffer = get_buf_element(this, 0, 0); - if(!read_buffer) { - /* if queue is full, skip (video) frame. - Waiting longer for free buffers just makes things worse ... */ - if(!this->is_paused) { - LOGDBG("UDP Fifo buffer full !"); - if(this->scr && !udp->scr_jump_done) { - pvrscr_skip_frame (this->scr); - LOGMSG("SCR jump: +40 ms (live=%d, tunning=%d) time %ds", - this->live_mode, this->scr_tunning, - (int)(monotonic_time_ms()/1000)); - udp->scr_jump_done = 50; - xine_usec_sleep(5*1000); - } - } - - VDR_ENTRY_LOCK(XIO_ERROR); - vdr_plugin_poll(this, 100); - VDR_ENTRY_UNLOCK(); - - if(!this->control_running) - break; - - read_buffer = get_buf_element(this, 0, 0); - if(!read_buffer) { - if(!this->is_paused) - LOGMSG("Fifo buffer still full after poll !"); - xine_usec_sleep(5*1000); - return result; - } - } - - if(udp->scr_jump_done) - udp->scr_jump_done --; - } - - /* Receive frame from socket and check for errors */ - n = recvfrom(this->fd_data, read_buffer->mem, - read_buffer->max_size, MSG_TRUNC, - &server_address, &address_len); - if(n <= 0) { - if(n<0 && this->control_running && errno != EINTR) - LOGERR("read_net_udp recv() error"); - if(!n || errno != EINTR) - result = XIO_ERROR; - break; - } - - /* check source address */ - if((server_address.sin_addr.s_addr != - udp->server_address.sin_addr.s_addr) || - server_address.sin_port != udp->server_address.sin_port) { -#ifdef LOG_UDP - uint32_t tmp_ip = ntohl(server_address.sin_addr.s_addr); - LOGUDP("Received data from unknown sender: %d.%d.%d.%d:%d", - ((tmp_ip>>24)&0xff), ((tmp_ip>>16)&0xff), - ((tmp_ip>>8)&0xff), ((tmp_ip)&0xff), - server_address.sin_port); -#endif - continue; - } - - /* Check if frame size is valid */ - if(n < sizeof(stream_udp_header_t)) { - LOGMSG("received invalid UDP packet (too short)"); - continue; - } - if(n > read_buffer->max_size) { - LOGMSG("received too large UDP packet ; part of data was discarded"); - n = read_buffer->max_size; - } - - read_buffer->size = n; - read_buffer->type = BUF_MAJOR_MASK; - - pkt = (stream_udp_header_t*)read_buffer->mem; - pkt_data = read_buffer->mem + sizeof(stream_udp_header_t); - - if(this->rtp) { - if(n < sizeof(stream_rtp_header_impl_t)) { - LOGMSG("received invalid RTP packet (too short)"); - continue; - } - - /* check if RTP header is valid. If not, assume UDP without RTP. */ - rtp_pkt = (stream_rtp_header_impl_t*)read_buffer->mem; - if(rtp_pkt->rtp_hdr.raw[0] == (RTP_VERSION_BYTE | RTP_HDREXT_BIT) && - rtp_pkt->rtp_hdr.raw[1] == RTP_PAYLOAD_TYPE && - rtp_pkt->hdr_ext.hdr.size == htons(RTP_HEADER_EXT_X_SIZE) && - rtp_pkt->hdr_ext.hdr.type == htons(RTP_HEADER_EXT_X_TYPE)) { - - /* strip RTP header but leave UDP header (carried inside RTP header extension) */ - pkt = (stream_udp_header_t*)(read_buffer->mem + - sizeof(stream_rtp_header_impl_t) - - sizeof(stream_udp_header_t)); - pkt_data = read_buffer->mem + sizeof(stream_rtp_header_impl_t); - - read_buffer->content += sizeof(stream_rtp_header_impl_t) - sizeof(stream_udp_header_t); - read_buffer->size -= sizeof(stream_rtp_header_impl_t) - sizeof(stream_udp_header_t); - } - } - - pkt->seq = ntohs(pkt->seq); - pkt->pos = ntohull(pkt->pos); - - /* Check for control messages */ - if(/*pkt->seq == (uint16_t)(-1) &&*/ /*0xffff*/ - pkt->pos == (uint64_t)(-1ULL) && /*0xffffffff ffffffff*/ - pkt_data[0]) { /* -> can't be PES frame */ - pkt_data[64] = 0; - if(!strncmp((char*)pkt_data, "UDP MISSING", 11)) { - /* Re-send failed */ - int seq1 = 0, seq2 = 0; - uint64_t rpos = 0ULL; - sscanf((char*)pkt_data, "UDP MISSING %d-%d %" PRIu64, - &seq1, &seq2, &rpos); - read_buffer->size = sizeof(stream_udp_header_t); - read_buffer->type = BUF_MAJOR_MASK; - pkt->pos = rpos; - LOGUDP("Got UDP MISSING %d-%d (currseq=%d)", seq1, seq2, udp->next_seq); - if(seq1 == udp->next_seq) { - /* this is the one we are expecting ... */ - int n = ADDSEQ(seq2 + 1, -seq1); - udp->missed_frames += n; - seq2 &= UDP_SEQ_MASK; - pkt->seq = seq2; - udp->next_seq = seq2; - LOGUDP(" accepted: now currseq %d", udp->next_seq); - /* -> drop frame thru as empty ; it will trigger queue to continue */ - } else { - LOGUDP(" rejected: not expected seq ???"); - continue; - } - } else { - data_stream_parse_control(this, (char*)pkt_data); - continue; - } - } else { - /* Check for PES header */ - if(pkt_data[0] || pkt_data[1] || pkt_data[2] != 1) { - LOGMSG("received invalid UDP packet (PES header 0x000001 missing)"); - continue; - } - } - - /* Check if header is valid */ - if(pkt->seq > UDP_SEQ_MASK) { - LOGMSG("received invalid UDP packet (sequence number too big)"); - continue; - } - - /* - * handle re-ordering and retransmissios - */ - - current_seq = pkt->seq & UDP_SEQ_MASK; - /* first received frame initializes sequence counter */ - if(udp->received_frames == -1) { - udp->next_seq = current_seq; - udp->received_frames = 0; - } - - /* check if received sequence number is inside allowed window - (half of whole range) */ - if(ADDSEQ(current_seq, -udp->next_seq) > ((UDP_SEQ_MASK+1) >> 1)/*0x80*/) { - struct sockaddr_in sin; - LOGUDP("Received SeqNo out of window (%d ; [%d..%d])", - current_seq, udp->next_seq, - (udp->next_seq+((UDP_SEQ_MASK+1) >> 1)/*0x80*/) & UDP_SEQ_MASK); - /* reset link */ - LOGDBG("UDP: resetting link"); - memcpy(&sin, &udp->server_address, sizeof(sin)); - free_udp_data(udp); - udp = this->udp_data = init_udp_data(); - memcpy(&udp->server_address, &sin, sizeof(sin)); - continue; - } - - /* Add received frame to incoming queue */ - if(udp->queue[current_seq]) { - /* Duplicate packet or lot of dropped packets */ - LOGUDP("Got duplicate or window exceeded ? (queue slot %d in use) !", - current_seq); - udp->queue[current_seq]->free_buffer(udp->queue[current_seq]); - udp->queue[current_seq] = NULL; - if(!udp->queued) - LOGERR("UDP queue corrupt !!!"); - else - udp->queued--; - } - udp->queue[current_seq] = read_buffer; - read_buffer = NULL; - udp->queued ++; - - /* stay inside receiving window: - If window exceeded, skip missing frames */ - if(udp->queued > ((UDP_SEQ_MASK+1)>>2)) { -#ifdef LOG_UDP - int start = udp->next_seq; -#endif - while(!udp->queue[udp->next_seq]) { - INCSEQ(udp->next_seq); - udp->missed_frames++; - } - udp->resend_requested = 0; - LOGUDP("Re-ordering window exceeded, skipped missed frames %d-%d", - start, udp->next_seq-1); - } - - /* flush continous part of queue to demuxer queue */ - while(udp->queued > 0 && udp->queue[udp->next_seq]) { - pkt = (stream_udp_header_t*)udp->queue[udp->next_seq]->content; - udp->queue_input_pos = pkt->pos + udp->queue[udp->next_seq]->size - - sizeof(stream_udp_header_t); - if(udp->queue[udp->next_seq]->size > sizeof(stream_udp_header_t)) - this->block_buffer->put(this->block_buffer, udp->queue[udp->next_seq]); - else - udp->queue[udp->next_seq]->free_buffer(udp->queue[udp->next_seq]); - - udp->queue[udp->next_seq] = NULL; - udp->queued --; - INCSEQ(udp->next_seq); - if(udp->resend_requested) - udp->resend_requested --; - } - - /* no new resend requests until previous has been completed or failed */ - if(udp->resend_requested) - continue; - - /* If frames are missing, request re-send */ - if(NEXTSEQ(current_seq) != udp->next_seq && udp->queued) { - - if(!udp->resend_requested) { - int max_req = 20; - - while(!udp->queue[current_seq] && --max_req > 0) - INCSEQ(current_seq); - - printf_control(this, "UDP RESEND %d-%d %" PRIu64 "\r\n", - udp->next_seq, PREVSEQ(current_seq), - udp->queue_input_pos); - udp->resend_requested = - (current_seq + (UDP_SEQ_MASK+1) - udp->next_seq) & UDP_SEQ_MASK; - - LOGUDP("%d-%d missing, requested re-send for %d frames", - udp->next_seq, PREVSEQ(current_seq), udp->resend_requested); - } - } - -#ifdef LOG_UDP - /* Link quality statistics */ - udp->received_frames++; - if(udp->received_frames >= 1000) { - if(udp->missed_frames) - LOGUDP("packet loss %d.%d%% (%4d/%4d)", - udp->missed_frames*100/udp->received_frames, - (udp->missed_frames*1000/udp->received_frames)%10, - udp->missed_frames, udp->received_frames); - udp->missed_frames = udp->received_frames = 0; - } -#endif - } - - if(read_buffer) - read_buffer->free_buffer(read_buffer); - - return result; -} - - -static void *vdr_data_thread(void *this_gen) -{ - vdr_input_plugin_t *this = (vdr_input_plugin_t *) this_gen; - - LOGDBG("Data thread started"); - - (void)nice(-1); - - if(this->udp || this->rtp) { - while(this->control_running) { - if(vdr_plugin_read_net_udp(this) == XIO_ERROR) - break; - pthread_testcancel(); - } - } else { - while(this->control_running) { - if(vdr_plugin_read_net_tcp(this) == XIO_ERROR) - break; - pthread_testcancel(); - } - } - - this->control_running = 0; - LOGDBG("Data thread terminated"); - pthread_exit(NULL); -} - -#ifdef TEST_PIP -static int write_slave_stream(vdr_input_plugin_t *this, const char *data, int len) -{ - fifo_input_plugin_t *slave; - buf_element_t *buf; - - TRACE("write_slave_stream (%d bytes)", len); - - if(!this->pip_stream) { - LOGMSG("Detected new video stream 0x%X", (unsigned int)data[3]); - LOGMSG(" no xine stream yet, trying to create ..."); - vdr_plugin_parse_control((input_plugin_t*)this, "SUBSTREAM 0xE1 50 50 288 196"); - } - if(!this->pip_stream) { - LOGMSG(" pip substream: no stream !"); - return -1; - } - /*LOGMSG(" pip substream open, queuing data");*/ - - slave = (fifo_input_plugin_t*)this->pip_stream->input_plugin; - if(!slave) { - LOGMSG(" pip substream: no input plugin !"); - return len; - } - - if(slave->buffer_pool->num_free(slave->buffer_pool) < 20) { - /*LOGMSG(" pip substream: fifo almost full !");*/ - xine_usec_sleep(3000); - return 0; - } - buf = slave->buffer_pool->buffer_pool_try_alloc(slave->buffer_pool); - if(!buf) { - LOGMSG(" pip substream: fifo full !"); - return 0; - } - if(len > buf->max_size) { - LOGMSG(" pip substream: buf too small"); - buf->free_buffer(buf); - return len; - } - - buf->content = buf->mem; - buf->size = len; - buf->type = BUF_DEMUX_BLOCK; - xine_fast_memcpy(buf->content, data, len); - slave->buffer->put(slave->buffer, buf); - return len; -} -#endif - -static int vdr_plugin_write(input_plugin_t *this_gen, const char *data, int len) -{ - vdr_input_plugin_t *this = (vdr_input_plugin_t *) this_gen; - buf_element_t *buf = NULL; - static int overflows = 0; - - if(this->slave_stream) - return len; - -#ifdef TEST_PIP - /* some (older?) VDR recordings have video PID != 0xE0 ... */ - - /* slave */ - if(((uint8_t*)data)[3] > 0xe0 && ((uint8_t*)data)[3] <= 0xef) - return write_slave_stream(this, data, len); -#endif - - TRACE("vdr_plugin_write (%d bytes)", len); - - VDR_ENTRY_LOCK(0); - - buf = get_buf_element(this, len, 0); - if(!buf) { - /* need counter to filter non-fatal overflows - (VDR is not polling for every PES packet) */ - if(overflows++ > 1) - LOGMSG("vdr_plugin_write: buffer overflow ! (%d bytes)", len); - VDR_ENTRY_UNLOCK(); - xine_usec_sleep(5*1000); - return 0; /* EAGAIN */ - } - overflows = 0; - - if(len > buf->max_size) { - LOGMSG("vdr_plugin_write: PES too long (%d bytes, max size " - "%d bytes), data ignored !", len, buf->max_size); - buf->free_buffer(buf); -/* curr_pos will be invalid when this point is reached ! */ - VDR_ENTRY_UNLOCK(); - return len; - } - - buf->size = len; - xine_fast_memcpy(buf->content, data, len); - this->block_buffer->put(this->block_buffer, buf); - - VDR_ENTRY_UNLOCK(); - - TRACE("vdr_plugin_write returns %d", len); - - return len; -} - -static int vdr_plugin_keypress(input_plugin_t *this_gen, - const char *map, const char *key, - int repeat, int release) -{ - vdr_input_plugin_t *this = (vdr_input_plugin_t *) this_gen; - if(pthread_mutex_lock(&this->lock)) { - LOGERR("vdr_plugin_keypress: pthread_mutex_lock failed"); - return -1; - } - - if(key && this->fd_control >= 0) { - if(map) - printf_control(this, "KEY %s %s %s %s\r\n", map, key, - repeat?"Repeat":"", release?"Release":""); - else - printf_control(this, "KEY %s\r\n", key); - } - - pthread_mutex_unlock(&this->lock); - return 0; -} - - -/******************************* Plugin **********************************/ - -static void track_audio_stream_change(vdr_input_plugin_t *this, buf_element_t *buf) -{ - /* track audio stream changes */ - int audio_changed = 0; - if(buf->content[3] >= 0xc0 && buf->content[3] < 0xe0) { - /* audio */ - if(this->prev_audio_stream_id != (buf->content[3] << 8)) { - /*LOGDBG("Audio changed -> %d (%02X)", buf->content[3] - 0xc0, buf->content[3]);*/ - this->prev_audio_stream_id = buf->content[3] << 8; - audio_changed = 1; - } - } - else if(buf->content[3] == 0xbd) { - /* PS1 */ - int PayloadOffset = buf->content[8] + 9; - int SubStreamId = buf->content[PayloadOffset]; - int SubStreamType = SubStreamId & 0xF0; - int SubStreamIndex = SubStreamId & 0x1F; - switch (SubStreamType) { - case 0x20: /* SPU */ - case 0x30: /* SPU */ - /*LOGMSG("SPU %d", SubStreamId);*/ - break; - case 0x80: /* AC3 & DTS */ - if(this->prev_audio_stream_id != ((0xbd<<8) | SubStreamId)) { - LOGDBG("Audio changed -> AC3 %d (BD:%02X)", SubStreamIndex, SubStreamId); - this->prev_audio_stream_id = ((0xbd<<8) | SubStreamId); - audio_changed = 1; - } - break; - case 0xA0: /* LPCM */ - if(this->prev_audio_stream_id != ((0xbd<<8) | SubStreamId)) { - LOGDBG("Audio changed -> LPCM %d (BD:%02X)", SubStreamIndex, SubStreamId); - this->prev_audio_stream_id = ((0xbd<<8) | SubStreamId); - audio_changed = 1; - } - break; - default: - /*LOGMSG("Unknown PS1 substream %d", SubStreamId);*/ - break; - } - } else { - /* no audio */ - return; - } - - if(audio_changed) { -#if !defined(BUF_CONTROL_RESET_TRACK_MAP) -# warning xine-lib is older than 1.1.2. Multiple audio streams are not supported. -#else - put_control_buf(this->stream->audio_fifo, - this->stream->audio_fifo, - BUF_CONTROL_RESET_TRACK_MAP); -#endif -#if 0 - put_control_buf(this->stream->audio_fifo, - this->stream->audio_fifo, - BUF_CONTROL_RESET_DECODER); - put_control_buf(this->stream->audio_fifo, - this->stream->audio_fifo, - BUF_CONTROL_START); -#endif -#if 0 - LOGMSG("VDR-Given stream: %04x", this->audio_stream_id); -#endif - } -} - -#if XINE_VERSION_CODE < 10190 -static off_t vdr_plugin_read (input_plugin_t *this_gen, char *buf_gen, off_t len) -#else -static off_t vdr_plugin_read (input_plugin_t *this_gen, void *buf_gen, off_t len) -#endif -{ - /* from xine_input_dvd.c: */ - /* FIXME: Tricking the demux_mpeg_block plugin */ - if(len > 3) { - uint8_t *buf = (uint8_t*)buf_gen; - buf[0] = 0; - buf[1] = 0; - buf[2] = 0x01; - buf[3] = 0xba; - return 4; - } - return 0; -} - -/*#define CACHE_FIRST_IFRAME*/ -#ifdef CACHE_FIRST_IFRAME -# include "cache_iframe.c" -#endif - -static void pts_wrap_workaround(vdr_input_plugin_t *this, buf_element_t *buf) -{ -#if 1 - /* PTS wrap workaround for mpeg_block demuxer */ - int64_t pts = pts_from_pes(buf->content, buf->size); - if(pts >= 0) { - int video = ((buf->content[3] & 0xf0) == 0xe0); - if(video) - this->last_delivered_vid_pts = pts; - if(!video) { - if(pts > 0x40400000 && - this->last_delivered_vid_pts < 0x40000000 && - this->last_delivered_vid_pts > 0) { - LOGMSG("VIDEO pts wrap before AUDIO, ignoring audio pts %" PRId64, pts); - pes_strip_pts(buf->content, buf->size); - } - } - } -#endif -} - -static void post_frame_end(vdr_input_plugin_t *this, int type) -{ - /* signal FRAME_END to video decoder */ - buf_element_t *cbuf = get_buf_element (this, 0, 1); - if (!cbuf) { - LOGMSG("get_buf_element() for BUF_FLAG_FRAME_END failed - retrying"); - xine_usec_sleep (10*1000); - cbuf = get_buf_element (this, 0, 1); - } - if (cbuf) { - cbuf->type = type; - cbuf->decoder_flags = BUF_FLAG_FRAME_END; - this->stream->video_fifo->put (this->stream->video_fifo, cbuf); - } else if (type == BUF_VIDEO_H264) { - /* Should not be here ... - Failing to send BUF_FLAG_FRAME_END 's freezes the decoder */ - LOGERR("get_buf_element() for H.264 BUF_FLAG_FRAME_END failed - aborting"); - abort(); - } -} - -static int update_frames(vdr_input_plugin_t *this, uint8_t *data, int len) -{ - int i = 8; - - if (!this->I_frames) - this->P_frames = this->B_frames = 0; - i += data[i] + 1; /* possible additional header bytes */ - for (; i < len-5; i++) { - if (data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 1 && data[i + 3] == 0) { - uint8_t type = ((data[i + 5] >> 3) & 0x07); - switch (type) { - case 1: this->I_frames++; LOGSCR("I"); break; - case 2: this->P_frames++; LOGSCR("P"); break; - case 3: this->B_frames++; LOGSCR("B"); break; - default: return 0; - } - return type; - } - } - return 0; -} - -#ifdef TEST_H264 -static int update_frames_h264(vdr_input_plugin_t *this, uint8_t *data, int len) -{ - int i = 8; - if (!this->I_frames) - this->P_frames = this->B_frames = 0; - i += data[i] + 1; /* possible additional header bytes */ - for (; i < len-5; i++) { - if (data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 1 && data[i + 3] == 9) { - uint8_t type = (data[i + 4] >> 5); - switch (type) { - case 0: case 3: case 5: this->I_frames++; LOGSCR("I %d", type); break; - case 1: case 4: case 6: this->P_frames++; LOGSCR("P %d", type); break; - case 2: case 7: this->B_frames++; LOGSCR("B %d", type); break; - default: return 0; - } - return type; - } - } - return 0; -} -#endif - -#ifdef TEST_H264 -static int detect_h264(vdr_input_plugin_t *this, uint8_t *data, int len) -{ - int i = 8; - i += data[i] + 1; /* possible additional header bytes */ - - /* H.264 detection */ - if (data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 1) { - if (data[i + 3] == 0x09) { - LOGMSG("H.264 scanner: Possible H.264 NAL AUD"); - return 1; - } - if (data[i + 3] == 0) { - LOGDBG("H.264 scanner: Possible MPEG2 start code PICTURE (0x00)"); - return 0; - } - if (data[i + 3] >= 0x80) { - LOGDBG("H.264 scanner: Possible MPEG2 start code (0x%02x)", data[i + 3]); - return 0; - } - LOGMSG("H.264 scanner: Unregonized header 00 00 01 %02x", data[i + 3]); - } - -#if 0 - if (this->h264 < 0) - LOGDBG("H.264 scanner: unregonized video packet"); -#endif - - return this->h264; -} -#endif /* TEST_H264 */ - -#ifdef TEST_H264 -buf_element_t *post_frame_h264(vdr_input_plugin_t *this, buf_element_t *buf) -{ - int64_t pts = pts_from_pes (buf->content, buf->size); - uint8_t *data = buf->content; - int i = 8; - - /* Detect video frame boundaries */ - - i += data[i] + 1; /* possible additional header bytes */ - - if (data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 1 ) { - - /* Access Unit Delimiter */ - if (data[i + 3] == 0x09) - post_frame_end (this, BUF_VIDEO_H264); - - if (data[i + 3] >= 0x80) { - LOGMSG("H.264: Possible MPEG2 start code (0x%02x)", data[i + 3]); - /* Should do something ... ? */ - } - - if(this->live_mode && this->I_frames < 4) - /*if((buf->content[3] & 0xf0) == 0xe0 && buf->size > 32)*/ - update_frames_h264(this, buf->content, buf->size); - } - - /* Handle PTS and DTS */ - - buf->decoder_info[0] = 0; - if (pts >= INT64_C(0)) { - int64_t dts = dts_from_pes (buf->content, buf->size); -#if 0 - if (dts < INT64_C(0)) { - buf->decoder_info[0] = pts; - } else { - buf->decoder_info[0] = (pts - dts); - buf->decoder_flags |= BUF_FLAG_FRAMERATE; - } - LOGMSG("H.264: dts %"PRId64" DIFF %d [stream video step %d]", - dts, (int)(pts-dts), - _x_stream_info_get(this->stream, XINE_STREAM_INFO_FRAME_DURATION)); -#endif - if (this->send_pts) { - LOGMSG("H.264: post pts %"PRId64, pts); - vdr_x_demux_control_newpts (this->stream, pts, BUF_FLAG_SEEK); - this->send_pts = 0; - } else if (this->last_delivered_vid_pts > 0 && - abs(pts - this->last_delivered_vid_pts) > 270000 /* 3 sec */) { - LOGMSG("H.264: post pts %"PRId64" diff %d", pts, (int)(pts-this->last_delivered_vid_pts)); - vdr_x_demux_control_newpts (this->stream, pts, BUF_FLAG_SEEK); - } - - /* xine ffmpeg decoder does not handle pts <-> dts difference very well if P/B frames have pts */ - if (abs(pts - this->last_delivered_vid_pts) < 90000 && pts < this->last_delivered_vid_pts) { - LOGDBG("H.264: -> pts %"PRId64" <- 0", pts); - /*buf->pts = 0;*/ - } else if (dts>0) { - LOGDBG("H.264: -> pts %"PRId64" <- 0 (DTS %"PRId64")", pts, dts); - /*buf->pts = 0;*/ - } else { - LOGDBG("H.264: -> pts %"PRId64, pts); - buf->pts = pts; - } - - this->last_delivered_vid_pts = pts; - } - - /* bypass demuxer ... */ - - buf->type = BUF_VIDEO_H264; - buf->content += i; - buf->size -= i; - - this->stream->video_fifo->put (this->stream->video_fifo, buf); - - return NULL; -} -#endif /* TEST_H264 */ - -static buf_element_t *vdr_plugin_read_block (input_plugin_t *this_gen, - fifo_buffer_t *fifo, off_t todo) -{ - vdr_input_plugin_t *this = (vdr_input_plugin_t *) this_gen; - buf_element_t *buf = NULL; -#ifdef TEST_SCR_PAUSE - int need_pause = 0; -#endif - - TRACE("vdr_plugin_read_block"); - - /* check for disconnection/termination */ - if(!this->funcs.push_input_write /* reading from socket */ && - !this->control_running) { - LOGMSG("read_block: no data source, returning NULL"); - if(this->block_buffer) - this->block_buffer->clear(this->block_buffer); - if(this->big_buffer) - this->big_buffer->clear(this->big_buffer); - if(this->hd_buffer) - this->hd_buffer->clear(this->hd_buffer); - set_playback_speed(this, 1); - this->live_mode = 0; - reset_scr_tunning(this, XINE_FINE_SPEED_NORMAL); - this->stream->emergency_brake = 1; - return NULL; /* disconnected ? */ - } - - /* Return immediately if demux_action_pending flag is set */ - if(this->stream->demux_action_pending) { - if(NULL != (buf = make_padding_frame(this))) - return buf; - LOGMSG("vdr_plugin_read_block: demux_action_pending, make_padding_frame failed"); - } - -#ifdef CACHE_FIRST_IFRAME - if(NULL != (buf = get_cached_iframe(this))) - return buf; -#endif - - /* adjust SCR speed */ -#ifdef ADJUST_SCR_SPEED - if(pthread_mutex_lock(&this->lock)) { - LOGERR("read_block: pthread_mutex_lock failed"); - return NULL; - } - - if( (!this->live_mode && (this->fd_control < 0 || - this->fixed_scr)) || - this->slave_stream) { - if(this->scr_tunning) - reset_scr_tunning(this, this->speed_before_pause); - } else { -# ifdef TEST_SCR_PAUSE - if(this->stream_start || this->send_pts) { - reset_scr_tunning(this, this->speed_before_pause); - need_pause = 1; - } else { -# endif - vdr_adjust_realtime_speed(this); -# ifdef TEST_SCR_PAUSE - } -# endif - } - pthread_mutex_unlock(&this->lock); -#endif - - do { - buf = fifo_buffer_try_get(this->block_buffer); - if(!buf) { - struct timespec abstime; - create_timeout_time(&abstime, 500); - pthread_mutex_lock(&this->block_buffer->mutex); - if(this->block_buffer->fifo_size <= 0) - pthread_cond_timedwait (&this->block_buffer->not_empty, - &this->block_buffer->mutex, &abstime); - pthread_mutex_unlock(&this->block_buffer->mutex); -#if 1 - if(!this->is_paused && - !this->still_mode && - !this->is_trickspeed && - !this->slave_stream && - this->stream->video_fifo->fifo_size <= 0) { - this->padding_cnt++; - - if(this->padding_cnt > 16) { - LOGMSG("No data in 8 seconds, queuing no signal image"); - queue_nosignal(this); - this->padding_cnt = 0; - } - } else { - this->padding_cnt = 0; - } -#endif - if(NULL != (buf = make_padding_frame(this))) - return buf; - LOGMSG("make_padding_frame FAILED"); - continue; - } - this->padding_cnt = 0; - - /* internal control bufs */ - if(buf->type == CONTROL_BUF_BLANK) { - buf->free_buffer(buf); - buf = NULL; - - pthread_mutex_lock(&this->lock); - if(!this->stream_start) { - LOGMSG("BLANK in middle of stream! bufs queue %d , video_fifo %d", - this->block_buffer->fifo_size, - this->stream->video_fifo->fifo_size); - } else { - vdr_x_demux_control_newpts(this->stream, 0, BUF_FLAG_SEEK); - queue_blank_yv12(this); - } - pthread_mutex_unlock(&this->lock); - - continue; - } - - /* control buffers go always to demuxer */ - if ((buf->type & BUF_MAJOR_MASK) == BUF_CONTROL_BASE) - return buf; - - pthread_mutex_lock(&this->lock); - - /* Update stream position and remove network headers */ - strip_network_headers(this, buf); - - /* Update stream position */ - this->curpos += buf->size; - this->curframe ++; - - /* Handle discard */ - if(this->discard_index > this->curpos && this->guard_index < this->curpos) { - this->last_delivered_vid_pts = INT64_C(-1); - pthread_mutex_unlock(&this->lock); - buf->free_buffer(buf); - buf = NULL; - continue; - } - - /* ignore UDP/RTP "idle" padding */ - if(buf->content[3] == 0xbe) { - pthread_mutex_unlock(&this->lock); - return buf; - } - - /* Send current PTS ? */ - if(this->stream_start) { - this->last_delivered_vid_pts = INT64_C(-1); - this->send_pts = 1; - this->stream_start = 0; - this->h264 = -1; - pthread_mutex_lock (&this->stream->first_frame_lock); - this->stream->first_frame_flag = 2; - pthread_mutex_unlock (&this->stream->first_frame_lock); - } - - pthread_mutex_unlock(&this->lock); - -#ifdef TEST_H264 - /* H.264 */ - if(this->h264 && (buf->content[3] & 0xf0) == 0xe0) { - if(this->h264 < 0) - this->h264 = detect_h264(this, buf->content, buf->size); - - if(this->h264 > 0) { - buf = post_frame_h264(this, buf); - if(!buf) - continue; - } - } -#endif - - } while(!buf); - -#ifdef CACHE_FIRST_IFRAME - cache_iframe(this, buf); -#endif - - track_audio_stream_change(this, buf); - - pts_wrap_workaround(this, buf); - - /* Send current PTS ? */ - if(this->send_pts) { - int64_t pts = pts_from_pes(buf->content, buf->size); - if(pts > 0) { -#ifdef TEST_SCR_PAUSE - if(need_pause) - scr_tunning_set_paused(this); -#endif - vdr_x_demux_control_newpts(this->stream, pts, BUF_FLAG_SEEK); - this->send_pts = 0; - } else if(pts == 0) { - /* Still image? do nothing, leave send_pts ON */ - } - } - -#ifdef LOG_FIRSTFRAME_FLAG - { - /* trace flag changes */ - static uint64_t timer = 0; - static int tfd = 0; - pthread_mutex_lock (&this->stream->first_frame_lock); - if(tfd != this->stream->first_frame_flag) { - uint64_t now = monotonic_time_ms(); - if(tfd) - LOGMSG("FIRST FRAME FLAG %d -> %d (%d ms)", - tfd, this->stream->first_frame_flag, (int)(now-timer)); - timer = now; - tfd = this->stream->first_frame_flag; - } - pthread_mutex_unlock (&this->stream->first_frame_lock); - } -#endif - - if(this->still_mode && buf->size == 14) { - /* generated still images start with empty video PES, PTS = 0. - Reset metronom pts so images will be displayed */ - int64_t pts = pts_from_pes(buf->content, buf->size); - if(pts==0) { - vdr_x_demux_control_newpts(this->stream, pts, BUF_FLAG_SEEK); - /* delay frame 10ms (9000 ticks) */ - /*buf->content[12] = (uint8_t)((10*90) >> 7);*/ - } - } - -#ifndef FFMPEG_DEC - if(this->live_mode && this->I_frames < 4) - if((buf->content[3] & 0xf0) == 0xe0 && buf->size > 32) - update_frames(this, buf->content, buf->size); -#else /* FFMPEG_DEC */ - if(this->ffmpeg_video_decoder || (this->live_mode && this->I_frames < 4)) - if((buf->content[3] & 0xf0) == 0xe0 && buf->size > 32) { - int type = update_frames(this, buf->content, buf->size); - if(type && this->ffmpeg_video_decoder) { - /* signal FRAME_END to decoder */ - post_frame_end(this, BUF_VIDEO_MPEG); - /* for some reason ffmpeg mpeg2 decoder does not understand pts'es in B frames ? - * (B-frame pts's are smaller than in previous P-frame) - * Anyway, without this block of code B frames with pts are dropped. */ - if(type == 3 && pts_from_pes(buf->content, buf->size) > INT64_C(0)) - pes_strip_pts(buf->content, buf->size); - } - } -#endif - - TRACE("vdr_plugin_read_block: return data, pos end = %" PRIu64, this->curpos); - return buf; -} - -static off_t vdr_plugin_seek (input_plugin_t *this_gen, off_t offset, - int origin) -{ - return -1; -} - -static off_t vdr_plugin_get_length (input_plugin_t *this_gen) -{ - return -1; -} - -static uint32_t vdr_plugin_get_capabilities (input_plugin_t *this_gen) -{ - vdr_input_plugin_t *this = (vdr_input_plugin_t *) this_gen; - - if(!this->stream->demux_plugin) { - return - INPUT_CAP_PREVIEW | -#ifdef INPUT_CAP_NOCACHE - INPUT_CAP_NOCACHE | -#endif - INPUT_CAP_SEEKABLE | /* help demux detection */ - INPUT_CAP_BLOCK; - } - - return - INPUT_CAP_PREVIEW | -#ifdef INPUT_CAP_NOCACHE - INPUT_CAP_NOCACHE | -#endif - INPUT_CAP_BLOCK; -} - -static uint32_t vdr_plugin_get_blocksize (input_plugin_t *this_gen) -{ - vdr_input_plugin_t *this = (vdr_input_plugin_t *) this_gen; - int ret = 2048; - - if(this->block_buffer) { - pthread_mutex_lock(&this->block_buffer->buffer_pool_mutex); - if(this->block_buffer->first && this->block_buffer->first->size > 0) - ret = this->block_buffer->first->size; - pthread_mutex_unlock(&this->block_buffer->buffer_pool_mutex); - } - - return ret; -} - -static off_t vdr_plugin_get_current_pos (input_plugin_t *this_gen) -{ - vdr_input_plugin_t *this = (vdr_input_plugin_t *) this_gen; - return this->discard_index > this->curpos ? this->discard_index : this->curpos; -} - -static void vdr_plugin_dispose (input_plugin_t *this_gen) -{ - vdr_input_plugin_t *this = (vdr_input_plugin_t *) this_gen; - int i, local; - int fd = -1, fc = -1; - - if(!this_gen) - return; - - LOGDBG("vdr_plugin_dispose"); - - /* stop slave stream */ - if (this->slave_stream) { - LOGMSG("dispose: Closing slave stream"); - if (this->slave_event_queue) - xine_event_dispose_queue (this->slave_event_queue); - this->slave_event_queue = NULL; - if(this->funcs.fe_control) { - this->funcs.fe_control(this->funcs.fe_handle, "POST 0 Off\r\n"); - this->funcs.fe_control(this->funcs.fe_handle, "SLAVE 0x0\r\n"); - } - xine_stop(this->slave_stream); - xine_close(this->slave_stream); - xine_dispose(this->slave_stream); - this->slave_stream = NULL; - } - - if(this->fd_control>=0) - write_control(this, "CLOSE\r\n"); - - this->control_running = 0; - - local = this->funcs.push_input_write ? 1 : 0; - memset(&this->funcs, 0, sizeof(this->funcs)); - - /* shutdown sockets */ - if(!local) { - struct linger { - int l_onoff; /* linger active */ - int l_linger; /* how many seconds to linger for */ - } l = {0,0}; - - fd = this->fd_data; - fc = this->fd_control; - - if(fc >= 0) { - LOGDBG("Shutdown control"); - setsockopt(fc, SOL_SOCKET, SO_LINGER, &l, sizeof(struct linger)); - shutdown(fc, SHUT_RDWR); - } - - if(fd >= 0 && this->tcp) { - LOGDBG("Shutdown data"); - setsockopt(fc, SOL_SOCKET, SO_LINGER, &l, sizeof(struct linger)); - shutdown(fd, SHUT_RDWR); - } - } - - /* threads */ - if(!local && this->threads_initialized) { - void *p; - LOGDBG("Cancel control thread ..."); - /*pthread_cancel(this->control_thread);*/ - pthread_join (this->control_thread, &p); - LOGDBG("Cancel data thread ..."); - /*pthread_cancel(this->data_thread);*/ - pthread_join (this->data_thread, &p); - LOGDBG("Threads joined"); - } - - /* event queue(s) and listener threads */ - LOGDBG("Disposing event queues"); - if (this->event_queue) - xine_event_dispose_queue (this->event_queue); - this->event_queue = NULL; - - pthread_cond_broadcast(&this->engine_flushed); - while(pthread_cond_destroy(&this->engine_flushed) == EBUSY) { - LOGMSG("discard_signal busy !"); - pthread_cond_broadcast(&this->engine_flushed); - xine_usec_sleep(10); - } - - /* destroy mutexes (keep VDR out) */ - LOGDBG("Destroying mutexes"); - while(pthread_mutex_destroy(&this->vdr_entry_lock) == EBUSY) { - LOGMSG("vdr_entry_lock busy ..."); - pthread_mutex_lock(&this->vdr_entry_lock); - pthread_mutex_unlock(&this->vdr_entry_lock); - } - while(pthread_mutex_destroy(&this->osd_lock) == EBUSY) { - LOGMSG("osd_lock busy ..."); - pthread_mutex_lock(&this->osd_lock); - pthread_mutex_unlock(&this->osd_lock); - } - while(pthread_mutex_destroy(&this->lock) == EBUSY) { - LOGMSG("lock busy ..."); - pthread_mutex_lock(&this->lock); - pthread_mutex_unlock(&this->lock); - } - while(pthread_mutex_destroy(&this->fd_control_lock) == EBUSY) { - LOGMSG("fd_control_lock busy ..."); - pthread_mutex_lock(&this->fd_control_lock); - pthread_mutex_unlock(&this->fd_control_lock); - } - - signal_buffer_pool_not_empty(this); - signal_buffer_not_empty(this); - - /* close sockets */ - if(!local) { - LOGDBG("Closing data connection"); - if(fd >= 0) - if(close(fd)) - LOGERR("close(fd_data) failed"); - LOGDBG("Closing control connection"); - if(fc >= 0) - if(close(fc)) - LOGERR("close(fd_control) failed"); - this->fd_data = this->fd_control = -1; - LOGMSG("Connections closed."); - } - - /* OSD */ - for(i=0; i<MAX_OSD_OBJECT; i++) { - if(this->osdhandle[i] != -1) { - osd_command_t cmd; - LOGDBG("Closing osd %d", i); - memset(&cmd,0,sizeof(cmd)); - cmd.cmd = OSD_Close; - cmd.wnd = i; - exec_osd_command(this, &cmd); - } - } - - /* restore video properties */ - if(this->video_properties_saved) - set_video_properties(this, -1,-1,-1,-1,-1); /* restore defaults */ - - signal_buffer_pool_not_empty(this); - signal_buffer_not_empty(this); - - /* SCR */ - if (this->scr) { - this->class->xine->clock->unregister_scr(this->class->xine->clock, - &this->scr->scr); - this->scr->scr.exit(&this->scr->scr); - } - - free (this->mrl); - - if(this->udp_data) - free_udp_data(this->udp_data); - - /* fifos */ - - /* need to get all buffer elements back before disposing own buffers ... */ - LOGDBG("Disposing fifos"); - if(this->stream && this->stream->audio_fifo) - this->stream->audio_fifo->clear(this->stream->audio_fifo); - if(this->stream && this->stream->video_fifo) - this->stream->video_fifo->clear(this->stream->video_fifo); - - if(this->iframe_buffer) - this->iframe_buffer->clear(this->iframe_buffer); - if(this->block_buffer) - this->block_buffer->clear(this->block_buffer); - if(this->big_buffer) - this->big_buffer->clear(this->big_buffer); - if(this->hd_buffer) - this->hd_buffer->clear(this->hd_buffer); - - if(this->iframe_buffer) - this->iframe_buffer->dispose(this->iframe_buffer); - if(this->big_buffer) - this->big_buffer->dispose(this->big_buffer); - if(this->block_buffer) - this->block_buffer->dispose(this->block_buffer); - if(this->hd_buffer) - this->hd_buffer->dispose(this->hd_buffer); - - memset(this, 0, sizeof(this)); - - free (this); - LOGDBG("dispose done."); -} - -#if XINE_VERSION_CODE > 10103 -static const char* vdr_plugin_get_mrl (input_plugin_t *this_gen) -#else -static char* vdr_plugin_get_mrl (input_plugin_t *this_gen) -#endif -{ - vdr_input_plugin_t *this = (vdr_input_plugin_t *) this_gen; - - if(!this->stream->demux_plugin) { - /* help in demuxer selection */ - static char fake[128] = {0}; - snprintf(fake, sizeof(fake)-1, "%s/.vob", this->mrl); - fake[sizeof(fake)-1] = 0; - return fake; - } - - return this->mrl; -} - -static int vdr_plugin_get_optional_data (input_plugin_t *this_gen, - void *data, int data_type) -{ - if(data_type == INPUT_OPTIONAL_DATA_PREVIEW) { - - static const uint8_t preview_data[] = {0x00,0x00,0x01,0xBA, /* sequence start */ - 0x00,0x00,0x01,0xBE, /* padding */ - 0x00,0x02,0xff,0xff}; -#if MAX_PREVIEW_SIZE < 12 -# warning MAX_PREVIEW_SIZE < 12 ! - memcpy(data, preview_data, MAX_PREVIEW_SIZE); - return MAX_PREVIEW_SIZE; -#else - memcpy(data, preview_data, sizeof(preview_data)); - return sizeof(preview_data); -#endif - } - - return INPUT_OPTIONAL_UNSUPPORTED; -} - -static int vdr_plugin_open(input_plugin_t *this_gen) -{ - vdr_input_plugin_t *this = (vdr_input_plugin_t *) this_gen; - xine_t *xine = this->class->xine; - - this->event_queue = xine_event_new_queue (this->stream); - xine_event_create_listener_thread (this->event_queue, vdr_event_cb, this); - - this->buffer_pool = this->stream->video_fifo; - -#ifdef ADJUST_SCR_SPEED - /* enable resample method */ - xine->config->update_num(xine->config, - "audio.synchronization.av_sync_method",1); - - /* register our own scr provider */ - { - uint64_t time; - time = xine->clock->get_current_time(xine->clock); - this->scr = pvrscr_init(); - this->scr->scr.start(&this->scr->scr, time); - if(xine->clock->register_scr(this->class->xine->clock, &this->scr->scr)) - LOGMSG("xine->clock->register_scr FAILED !"); - this->scr_live_sync = 1; - } -#endif - this->scr_tunning = SCR_TUNNING_OFF; - this->curpos = 0; - return 1; -} - -static int vdr_plugin_open_local (input_plugin_t *this_gen) -{ - LOGDBG("vdr_plugin_open_local"); - return vdr_plugin_open(this_gen); -} - -static void set_recv_buffer_size(int fd, int max_buf) -{ - /* try to have larger receiving buffer */ - - /*while(max_buf) {*/ - if(setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &max_buf, sizeof(int)) < 0) { - LOGERR("setsockopt(SO_RCVBUF,%d) failed", max_buf); - /*max_buf >>= 1;*/ - } else { - unsigned int tmp = 0, len = sizeof(int);; - if(getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &tmp, &len) < 0) { - LOGERR("getsockopt(SO_RCVBUF,%d) failed", max_buf); - /*max_buf >>= 1;*/ - } else if(tmp != 2*max_buf) { - LOGDBG("setsockopt(SO_RCVBUF): got %d bytes", tmp); - /*max_buf >>= 1;*/ - } - } - /*}*/ - max_buf = 256; - /* not going to send anything, so shrink send buffer ... */ - setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &max_buf, sizeof(int)); -} - -static int alloc_udp_data_socket(int firstport, int trycount, int *port) -{ - int fd, one = 1; - struct sockaddr_in name; - - name.sin_family = AF_INET; - name.sin_port = htons(firstport); - name.sin_addr.s_addr = htonl(INADDR_ANY); - - fd = socket(PF_INET, SOCK_DGRAM, 0/*IPPROTO_UDP*/); - - set_recv_buffer_size(fd, KILOBYTE(512)); - - if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(int)) < 0) - LOGERR("UDP data stream: setsockopt(SO_REUSEADDR) failed"); - - while(bind(fd, (struct sockaddr *)&name, sizeof(name)) < 0) { - if(!--trycount) { - LOGMSG("UDP Data stream: bind error, no free port found"); - close(fd); - return -1; - } - LOGERR("UDP Data stream: bind error, port %d: %s", - name.sin_port, strerror(errno)); - name.sin_port = htons(++firstport); - } - - *port = ntohs(name.sin_port); - return fd; -} - -static int connect_control_stream(vdr_input_plugin_t *this, const char *host, - int port, int *client_id) -{ - char tmpbuf[256]; - int fd_control; - int saved_fd = this->fd_control, one = 1; - - /* Connect to server */ - this->fd_control = fd_control = _x_io_tcp_connect(this->stream, host, port); - - if(fd_control < 0 || - XIO_READY != _x_io_tcp_connect_finish(this->stream, this->fd_control, - 3000)) { - LOGERR("Can't connect to tcp://%s:%d", host, port); - close(fd_control); - this->fd_control = saved_fd; - return -1; - } - - set_recv_buffer_size(fd_control, KILOBYTE(128)); - - /* request control connection */ - if(_x_io_tcp_write(this->stream, fd_control, "CONTROL\r\n", 9) < 0) { - LOGERR("Control stream write error"); - return -1; - } - - /* Check server greeting */ - if(readline_control(this, tmpbuf, sizeof(tmpbuf)-1, 4) <= 0) { - LOGMSG("Server not replying"); - close(fd_control); - this->fd_control = saved_fd; - return -1; - } - LOGMSG("Server greeting: %s", tmpbuf); - if(!strncmp(tmpbuf, "Access denied", 13)) { - LOGMSG("Maybe host address is missing from server-side svdrphosts.conf ?"); - close(fd_control); - this->fd_control = saved_fd; - return -1; - } - if(!strstr(tmpbuf, "VDR-") || !strstr(tmpbuf, "xineliboutput-") || !strstr(tmpbuf, "READY")) { - LOGMSG("Unregonized greeting !"); - close(fd_control); - this->fd_control = saved_fd; - return -1; - } - /* Check server xineliboutput version */ - if(!strstr(tmpbuf, "xineliboutput-" XINELIBOUTPUT_VERSION " ")) { - LOGMSG("-----------------------------------------------------------------"); - LOGMSG("WARNING: Client and server versions of xinelibout are different !"); - LOGMSG(" Client version (xine_input_vdr.so) is " XINELIBOUTPUT_VERSION); - LOGMSG("-----------------------------------------------------------------"); - } - - /* Store our client-id */ - if(readline_control(this, tmpbuf, sizeof(tmpbuf)-1, 4) > 0 && - !strncmp(tmpbuf, "CLIENT-ID ", 10)) { - LOGDBG("Got Client-ID: %s", tmpbuf+10); - if(client_id) - if(1 != sscanf(tmpbuf+10, "%d", client_id)) - *client_id = -1; - } else { - LOGMSG("Warning: No Client-ID !"); - if(*client_id) - *client_id = -1; - } - - /* set socket to non-blocking mode */ - fcntl (fd_control, F_SETFL, fcntl (fd_control, F_GETFL) | O_NONBLOCK); - - /* set control socket to deliver data immediately - instead of waiting for full TCP segments */ - setsockopt(fd_control, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(int)); - - this->fd_control = saved_fd; - return fd_control; -} - - -static int connect_rtp_data_stream(vdr_input_plugin_t *this) -{ - char cmd[256]; - unsigned int ip0, ip1, ip2, ip3, port; - int fd=-1, one = 1, retries = 0, n; - struct sockaddr_in multicastAddress; - struct ip_mreq mreq; - struct sockaddr_in server_address, sin; - socklen_t len = sizeof(sin); - stream_rtp_header_impl_t tmp_rtp; - - /* get server IP address */ - if(getpeername(this->fd_control, (struct sockaddr *)&server_address, &len)) { - LOGERR("getpeername(fd_control) failed"); - /* close(fd); */ - return -1; - } - - /* request RTP data transport from server */ - - LOGDBG("Requesting RTP transport"); - if(_x_io_tcp_write(this->stream, this->fd_control, "RTP\r\n", 5) < 0) { - LOGERR("Control stream write error"); - return -1; - } - - cmd[0] = 0; - if(readline_control(this, cmd, sizeof(cmd)-1, 4) < 8 || - strncmp(cmd, "RTP ", 4)) { - LOGMSG("Server does not support RTP ? (%s)", cmd); - return -1; - } - - LOGDBG("Got: %s", cmd); - if(5 != sscanf(cmd, "RTP %u.%u.%u.%u:%u", &ip0, &ip1, &ip2, &ip3, &port) || - ip0>0xff || ip1>0xff || ip2>0xff || ip3>0xff || port>0xffff) { - LOGMSG("Server does not support RTP ? (%s)", cmd); - return -1; - } - - LOGMSG("Connecting (data) to rtp://@%u.%u.%u.%u:%u ...", - ip0, ip1, ip2, ip3, port); - multicastAddress.sin_family = AF_INET; - multicastAddress.sin_port = htons(port); - multicastAddress.sin_addr.s_addr = htonl((ip0<<24)|(ip1<<16)|(ip2<<8)|ip3); -#if 0 - LOGDBG("got address: %s int=0x%x net=0x%x translated=0x%x port=%d", - cmd+4, (ip0<<24)|(ip1<<16)|(ip2<<8)|ip3, - htonl((ip0<<24)|(ip1<<16)|(ip2<<8)|ip3), - inet_addr("224.0.1.9"), port); -#endif - - if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - LOGERR("socket() failed"); - return -1; - } - set_recv_buffer_size(fd, KILOBYTE(512)); - - if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(int)) < 0) { - LOGERR("setsockopt(SO_REUSEADDR) failed"); - close(fd); - return -1; - } - - if(bind(fd, (struct sockaddr *)&multicastAddress, - sizeof(multicastAddress)) < 0) { - LOGERR("bind() to multicast address failed"); - close(fd); - return -1; - } - - /* Join to multicast group */ - - memset(&mreq, 0, sizeof(mreq)); - mreq.imr_multiaddr.s_addr = multicastAddress.sin_addr.s_addr; - mreq.imr_interface.s_addr = htonl(INADDR_ANY); - /*mreq.imr_ifindex = 0;*/ - if(setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq))) { - LOGERR("setsockopt(IP_ADD_MEMBERSHIP) failed. No multicast in kernel?"); - close(fd); - return -1; - } - -retry_select: - - /* wait until server sends first RTP packet */ - - if( XIO_READY != io_select_rd(fd)) { - LOGDBG("Requesting RTP transport: RTP poll timeout"); - if(++retries < 10) { - LOGDBG("Requesting RTP transport"); - if(_x_io_tcp_write(this->stream, this->fd_control, "RTP\r\n", 5) < 0) { - LOGERR("Control stream write error"); - close(fd); - return -1; - } - goto retry_select; - } - LOGMSG("Data stream connection timed out (RTP)"); - close(fd); - return -1; - } - -retry_recvfrom: - - /* check sender address */ - - n = recvfrom(fd, &tmp_rtp, sizeof(tmp_rtp), 0, &sin, &len); - if(sin.sin_addr.s_addr != server_address.sin_addr.s_addr) { - uint32_t tmp_ip = ntohl(sin.sin_addr.s_addr); - LOGMSG("Received UDP/RTP multicast from unknown sender: %d.%d.%d.%d:%d", - ((tmp_ip>>24)&0xff), ((tmp_ip>>16)&0xff), - ((tmp_ip>>8)&0xff), ((tmp_ip)&0xff), - sin.sin_port); - - if(XIO_READY == _x_io_select(this->stream, fd, XIO_READ_READY, 0)) - goto retry_recvfrom; - if(++retries < 4) - goto retry_select; - close(fd); - return -1; - } - - /* Succeed */ - - this->udp_data = init_udp_data(); - - /* store server address */ - memcpy(&this->udp_data->server_address, &sin, sizeof(sin)); - this->udp_data->ssrc = tmp_rtp.rtp_hdr.ssrc; - - return fd; -} - - -static int connect_udp_data_stream(vdr_input_plugin_t *this) -{ - char cmd[256]; - struct sockaddr_in server_address, sin; - socklen_t len = sizeof(sin); - uint32_t tmp_ip; - stream_udp_header_t tmp_udp; - int n, retries = 0, port = -1, fd = -1; - - /* get server IP address */ - if(getpeername(this->fd_control, (struct sockaddr *)&server_address, &len)) { - LOGERR("getpeername(fd_control) failed"); - /* close(fd); */ - return -1; - } - tmp_ip = ntohl(server_address.sin_addr.s_addr); - - LOGDBG("VDR server address: %d.%d.%d.%d", - ((tmp_ip>>24)&0xff), ((tmp_ip>>16)&0xff), - ((tmp_ip>>8)&0xff), ((tmp_ip)&0xff)); - - /* allocate UDP socket */ - if((fd = alloc_udp_data_socket(DEFAULT_VDR_PORT, 20, &port)) < 0) - return -1; - /*LOGDBG("my UDP port is: %d", port);*/ - -retry_request: - - /* request UDP data transport from server */ - - LOGDBG("Requesting UDP transport"); - sprintf(cmd, "UDP %d\r\n", port); - if(_x_io_tcp_write(this->stream, this->fd_control, cmd, strlen(cmd)) < 0) { - LOGERR("Control stream write error"); - close(fd); - return -1; - } - - cmd[0] = 0; - if(readline_control(this, cmd, sizeof(cmd)-1, 4) < 6 || - strncmp(cmd, "UDP OK", 6)) { - LOGMSG("Server does not support UDP ? (%s)", cmd); - return -1; - } - -retry_select: - - /* wait until server sends first UDP packet */ - - if( XIO_READY != io_select_rd(fd)) { - LOGDBG("Requesting UDP transport: UDP poll timeout"); - if(++retries < 4) - goto retry_request; - LOGMSG("Data stream connection timed out (UDP)"); - close(fd); - return -1; - } - -retry_recvfrom: - - /* check sender address */ - - n = recvfrom(fd, &tmp_udp, sizeof(tmp_udp), 0, &sin, &len); - if(sin.sin_addr.s_addr != server_address.sin_addr.s_addr) { - tmp_ip = ntohl(sin.sin_addr.s_addr); - LOGMSG("Received UDP packet from unknown sender: %d.%d.%d.%d:%d", - ((tmp_ip>>24)&0xff), ((tmp_ip>>16)&0xff), - ((tmp_ip>>8)&0xff), ((tmp_ip)&0xff), - sin.sin_port); - - if(XIO_READY == _x_io_select(this->stream, fd, XIO_READ_READY, 0)) - goto retry_recvfrom; - if(++retries < 4) - goto retry_select; - close(fd); - return -1; - } - - /* Succeed */ - - this->udp_data = init_udp_data(); - - /* store server address */ - memcpy(&this->udp_data->server_address, &sin, sizeof(sin)); - - return fd; -} - -static int connect_tcp_data_stream(vdr_input_plugin_t *this, const char *host, - int port) -{ - struct sockaddr_in sinc; - socklen_t len = sizeof(sinc); - uint32_t ipc; - char tmpbuf[256]; - int fd_data, n; - - /* Connect to server */ - fd_data = _x_io_tcp_connect(this->stream, host, port); - - if(fd_data < 0 || - XIO_READY != _x_io_tcp_connect_finish(this->stream, fd_data, 3000)) { - LOGERR("Can't connect to tcp://%s:%d", host, port); - close(fd_data); - return -1; - } - - set_recv_buffer_size(fd_data, KILOBYTE(128)); - - /* request data connection */ - - getsockname(this->fd_control, (struct sockaddr *)&sinc, &len); - ipc = ntohl(sinc.sin_addr.s_addr); - sprintf(tmpbuf, - "DATA %d 0x%x:%u %d.%d.%d.%d\r\n", - this->client_id, - (unsigned int)ipc, - (unsigned int)ntohs(sinc.sin_port), - ((ipc>>24)&0xff), ((ipc>>16)&0xff), ((ipc>>8)&0xff), ((ipc)&0xff) - ); - if(_x_io_tcp_write(this->stream, fd_data, tmpbuf, strlen(tmpbuf)) < 0) { - LOGERR("Data stream write error (TCP)"); - } else if( XIO_READY != io_select_rd(fd_data)) { - LOGERR("Data stream poll failed (TCP)"); - } else if((n=read(fd_data, tmpbuf, sizeof(tmpbuf))) <= 0) { - LOGERR("Data stream read failed (TCP)"); - } else if(n<6 || strncmp(tmpbuf, "DATA\r\n", 6)) { - tmpbuf[n] = 0; - LOGMSG("Server does not support TCP ? (%s)", tmpbuf); - } else { - /* succeed */ - /* set socket to non-blocking mode */ - fcntl (fd_data, F_SETFL, fcntl (fd_data, F_GETFL) | O_NONBLOCK); - return fd_data; - } - - close(fd_data); - return -1; -} - -static int connect_pipe_data_stream(vdr_input_plugin_t *this) -{ - char tmpbuf[256]; - int fd_data = -1; - - /* check if IP address matches */ - if(!strstr(this->mrl, "127.0.0.1")) { - struct sockaddr_in sinc; - struct sockaddr_in sins; - socklen_t len = sizeof(sinc); - getsockname(this->fd_control, &sinc, &len); - getpeername(this->fd_control, &sins, &len); - if(sinc.sin_addr.s_addr != sins.sin_addr.s_addr) { - LOGMSG("connect_pipe_data_stream: client ip=0x%x != server ip=0x%x !", - (unsigned int)sinc.sin_addr.s_addr, (unsigned int)sins.sin_addr.s_addr); -#if 0 - LOGMSG(" different host, pipe won't work"); - return -1; -#endif - } - } - - _x_io_tcp_write(this->stream, this->fd_control, "PIPE\r\n", 6); - - if(readline_control(this, tmpbuf, sizeof(tmpbuf), 4) <= 0) { - LOGMSG("Pipe request failed"); - } else if(strncmp(tmpbuf, "PIPE /", 6)) { - LOGMSG("Server does not support pipes ? (%s)", tmpbuf); - } else { - - LOGMSG("Connecting (data) to pipe://%s", tmpbuf+5); - if((fd_data = open(tmpbuf+5, O_RDONLY|O_NONBLOCK)) < 0) { - if(errno == ENOENT) - LOGMSG("Pipe not found"); - else - LOGERR("Pipe opening failed"); - } else { - _x_io_tcp_write(this->stream, this->fd_control, "PIPE OPEN\r\n", 11); - if(readline_control(this, tmpbuf, sizeof(tmpbuf)-1, 4) >6 && - !strncmp(tmpbuf, "PIPE OK", 7)) { - fcntl (fd_data, F_SETFL, fcntl (fd_data, F_GETFL) | O_NONBLOCK); - return fd_data; - } - LOGMSG("Data stream connection failed (PIPE)"); - } - } - - close(fd_data); - return -1; -} - -static int vdr_plugin_open_net (input_plugin_t *this_gen) -{ - vdr_input_plugin_t *this = (vdr_input_plugin_t *) this_gen; - char tmpbuf[256]; - int err; - - LOGDBG("vdr_plugin_open_net %s", this->mrl); - - if(strchr(this->mrl, '#')) - *strchr(this->mrl, '#') = 0; - if((!strncasecmp(this->mrl, "xvdr+tcp://", 11) && (this->tcp=1)) || - (!strncasecmp(this->mrl, "xvdr+udp://", 11) && (this->udp=1)) || - (!strncasecmp(this->mrl, "xvdr+rtp://", 11) && (this->rtp=1)) || - (!strncasecmp(this->mrl, "xvdr+pipe://", 12)) || - (!strncasecmp(this->mrl, "xvdr:tcp://", 11) && (this->tcp=1)) || - (!strncasecmp(this->mrl, "xvdr:udp://", 11) && (this->udp=1)) || - (!strncasecmp(this->mrl, "xvdr:rtp://", 11) && (this->rtp=1)) || - (!strncasecmp(this->mrl, "xvdr:pipe://", 12)) || - (!strncasecmp(this->mrl, "xvdr://", 7))) { - - char *phost = strdup(strstr(this->mrl, "//") + 2); - char host[256]; - char *port = strchr(phost, ':'); - int iport; - int one = 1; - if(port) *port++ = 0; - iport = port ? atoi(port) : DEFAULT_VDR_PORT; - strn0cpy(host, phost, 254); - /*host[sizeof(host)-1] = 0;*/ - free(phost); - /* TODO: use multiple input plugins - tcp/udp/file */ - - /* connect control stream */ - - LOGMSG("Connecting (control) to tcp://%s:%d ...", host, iport); - this->fd_control = connect_control_stream(this, host, iport, - &this->client_id); - if (this->fd_control < 0) { - LOGERR("Can't connect to tcp://%s:%d", host, iport); - return 0; - } - setsockopt(this->fd_control, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(int)); - - LOGMSG("Connected (control) to tcp://%s:%d", host, iport); - - /* connect data stream */ - - /* try pipe ? */ - - if(!this->tcp && !this->udp && !this->rtp) { - if((this->fd_data = connect_pipe_data_stream(this)) < 0) { - LOGMSG("Data stream connection failed (PIPE)"); - } else { - this->tcp = this->udp = this->tcp = 0; - LOGMSG("Data stream connected (PIPE)"); - } - } - - /* try RTP ? */ - - if(this->fd_data < 0 && !this->udp && !this->tcp) { - /* flush control buffer (if PIPE was tried first) */ - while(0 < read(this->fd_control, tmpbuf, 255)) ; - if((this->fd_data = connect_rtp_data_stream(this)) < 0) { - LOGMSG("Data stream connection failed (RTP)"); - this->rtp = 0; - } else { - this->rtp = 1; - this->tcp = this->udp = 0; - LOGMSG("Data stream connected (RTP)"); - } - } - - /* try UDP ? */ - - if(this->fd_data < 0 && !this->tcp) { - LOGMSG("Connecting (data) to udp://%s ...", host); - /* flush control buffer (if RTP was tried first) */ - while(0 < read(this->fd_control, tmpbuf, 255)) ; - if((this->fd_data = connect_udp_data_stream(this)) < 0) { - LOGMSG("Data stream connection failed (UDP)"); - this->udp = 0; - } else { - this->udp = 1; - this->tcp = this->rtp = 0; - LOGMSG("Data stream connected (UDP)"); - } - } - - /* fall back to TCP ? */ - - if(this->fd_data < 0) { - LOGMSG("Connecting (data) to tcp://%s:%d ...", host, iport); - this->tcp = 0; - if((this->fd_data = connect_tcp_data_stream(this, host, iport)) < 0) { - LOGMSG("Data stream connection failed (TCP)"); - this->tcp = 0; - } else { - this->tcp = 1; - } - if(this->tcp) { - /* succeed */ - this->rtp = this->udp = 0; - LOGMSG("Data stream connected (TCP)"); - } else { - /* failed */ - close(this->fd_data); - close(this->fd_control); - this->fd_control = this->fd_data = -1; - return 0; - } - } - - } else { - LOGMSG("Unknown mrl (%s)", this->mrl); - return 0; - } - - if(!vdr_plugin_open(this_gen)) - return 0; - - queue_nosignal(this); - - this->control_running = 1; - if ((err = pthread_create (&this->control_thread, - NULL, vdr_control_thread, (void*)this)) != 0) { - LOGERR("Can't create new thread"); - return 0; - } - if ((err = pthread_create (&this->data_thread, - NULL, vdr_data_thread, (void*)this)) != 0) { - LOGERR("Can't create new thread"); - return 0; - } - - this->class->xine->port_ticket->acquire(this->class->xine->port_ticket, 1); - if(!(this->stream->video_out->get_capabilities(this->stream->video_out) & - VO_CAP_UNSCALED_OVERLAY)) - LOGMSG("WARNING: Video output driver reports it does not support unscaled overlays !"); - this->class->xine->port_ticket->release(this->class->xine->port_ticket, 1); - - this->threads_initialized = 1; - return 1; -} - -/**************************** Plugin class *******************************/ -/* Callback on default mrl change */ -static void vdr_class_default_mrl_change_cb(void *data, xine_cfg_entry_t *cfg) -{ - vdr_input_class_t *class = (vdr_input_class_t *) data; - - class->mrls[0] = cfg->str_value; -} - -/* callback on OSD scaling mode change */ -static void vdr_class_fast_osd_scaling_cb(void *data, xine_cfg_entry_t *cfg) -{ - vdr_input_class_t *class = (vdr_input_class_t *) data; - - class->fast_osd_scaling = cfg->num_value; -} - -static input_plugin_t *vdr_class_get_instance (input_class_t *class_gen, - xine_stream_t *stream, - const char *data) -{ - vdr_input_class_t *class = (vdr_input_class_t *) class_gen; - vdr_input_plugin_t *this; - char *mrl = (char *) data; - int local_mode, i; - - LOGDBG("vdr_class_get_instance"); - - if (strncasecmp (mrl, "xvdr:",5) && strncasecmp (mrl, "xvdr+",5)) - return NULL; - - if(!strncasecmp(mrl, "xvdr+slave://0x", 15)) { - LOGMSG("vdr_class_get_instance: slave stream requested"); - return fifo_class_get_instance(class_gen, stream, data); - } - - this = (vdr_input_plugin_t *) xine_xmalloc (sizeof(vdr_input_plugin_t)); - - this->stream = stream; - this->mrl = strdup(mrl); - this->class = class; - - this->fd_data = -1; - this->fd_control = -1; - - this->stream_start = 1; - this->max_buffers = 10; - this->ffmpeg_video_decoder = -1; - this->last_delivered_vid_pts = INT64_C(-1); - this->autoplay_size = -1; - - for(i=0; i<MAX_OSD_OBJECT; i++) - this->osdhandle[i] = -1; - this->video_width = this->vdr_osd_width = 720; - this->video_height = this->vdr_osd_height = 576; - - local_mode = ( (!strncasecmp(mrl, "xvdr://", 7)) && - (strlen(mrl)==7)) - || (!strncasecmp(mrl, "xvdr:///", 8)); - - if(!bSymbolsFound) { - /* not running under VDR or vdr-sxfe/vdr-fbfe */ - if(local_mode) { - LOGDBG("vdr or vdr-??fe not detected, forcing remote mode"); - local_mode = 0; - } - if(!strcasecmp(mrl, "xvdr:") || - !strcasecmp(mrl, "xvdr:/") || - !strcasecmp(mrl, "xvdr://") || - !strcasecmp(mrl, "xvdr:///")) { - /* default to local host */ - free(this->mrl); - this->mrl = strdup("xvdr://127.0.0.1"); - LOGMSG("Changed mrl from %s to %s", mrl, this->mrl); - } - } - - this->input_plugin.open = local_mode ? vdr_plugin_open_local - : vdr_plugin_open_net; - this->input_plugin.get_mrl = vdr_plugin_get_mrl; - this->input_plugin.dispose = vdr_plugin_dispose; - this->input_plugin.input_class = class_gen; - - this->input_plugin.get_capabilities = vdr_plugin_get_capabilities; - this->input_plugin.read = vdr_plugin_read; - this->input_plugin.read_block = vdr_plugin_read_block; - this->input_plugin.seek = vdr_plugin_seek; - this->input_plugin.get_current_pos = vdr_plugin_get_current_pos; - this->input_plugin.get_length = vdr_plugin_get_length; - this->input_plugin.get_blocksize = vdr_plugin_get_blocksize; - this->input_plugin.get_optional_data = vdr_plugin_get_optional_data; - - if(local_mode) { - this->funcs.push_input_write = vdr_plugin_write; - this->funcs.push_input_control= vdr_plugin_parse_control; - this->funcs.push_input_osd = vdr_plugin_exec_osd_command; - /*this->funcs.xine_input_event= NULL; -- frontend sets this */ - } else { - this->funcs.input_control = vdr_plugin_keypress; - } - - /* buffer */ - this->block_buffer = fifo_buffer_new(this->stream, 4, 0x10000+64); /* dummy buf to be used before first read and for big PES frames */ - - /* sync */ - pthread_mutex_init (&this->lock, NULL); - pthread_mutex_init (&this->osd_lock, NULL); - pthread_mutex_init (&this->vdr_entry_lock, NULL); - pthread_mutex_init (&this->fd_control_lock, NULL); - pthread_cond_init (&this->engine_flushed, NULL); - -#ifdef FFMPEG_DEC - if(this->ffmpeg_video_decoder < 0) { - xine_cfg_entry_t ffmpegprio, mpeg2prio; - this->ffmpeg_video_decoder = 0; - if (xine_config_lookup_entry(this->class->xine, "engine.decoder_priorities.ffmpegvideo", &ffmpegprio) && - ffmpegprio.num_value > 0) { - LOGMSG("ffmpeg video decoder priority: %d", ffmpegprio.num_value); - this->ffmpeg_video_decoder = 1; - if (xine_config_lookup_entry(this->class->xine, "engine.decoder_priorities.mpeg2", &mpeg2prio)) { - LOGMSG("libmpeg2 video decoder priority: %d", mpeg2prio.num_value); - if (mpeg2prio.num_value >= ffmpegprio.num_value) - this->ffmpeg_video_decoder = 0; - } - LOGMSG(" --> using %s mpeg2 video decoder", this->ffmpeg_video_decoder?"ffmpeg":"libmpeg2"); - } - } -#endif - - LOGDBG("vdr_class_get_instance done."); - return &this->input_plugin; -} - -/* - * vdr input plugin class stuff - */ - -#if INPUT_PLUGIN_IFACE_VERSION < 18 -#if XINE_VERSION_CODE > 10103 -static const char *vdr_class_get_description (input_class_t *this_gen) -#else -static char *vdr_class_get_description (input_class_t *this_gen) -#endif -{ - return _("VDR (Video Disk Recorder) input plugin"); -} - -static const char *vdr_class_get_identifier (input_class_t *this_gen) -{ - return "xvdr"; -} -#endif - -static char **vdr_plugin_get_autoplay_list(input_class_t *this_gen, int *num_files) -{ - vdr_input_class_t *this = (vdr_input_class_t *)this_gen; - *num_files = 1; - - return this->mrls; -} - -static void vdr_class_dispose (input_class_t *this_gen) -{ - vdr_input_class_t *this = (vdr_input_class_t *) this_gen; - - this->xine->config->unregister_callback(this->xine->config, - "media.xvdr.default_mrl"); - this->xine->config->unregister_callback(this->xine->config, - "xvdr.osd.fast_scaling"); - - free (this); -} - -static void *init_class (xine_t *xine, void *data) -{ - vdr_input_class_t *this; - config_values_t *config = xine->config; - - SetupLogLevel(); - - if(!bSymbolsFound) { - if(xine->verbosity > 0) { - iSysLogLevel = xine->verbosity + 1; - LOGMSG("detected verbose logging xine->verbosity=%d, setting log level to %d:%s", - xine->verbosity, iSysLogLevel, - iSysLogLevel==2?"INFO":"DEBUG"); - } - } - - this = (vdr_input_class_t *) xine_xmalloc (sizeof (vdr_input_class_t)); - - this->xine = xine; - - this->mrls[ 0 ] = config->register_string(config, - "media.xvdr.default_mrl", - "xvdr://127.0.0.1#nocache;demux:mpeg_block", - _("default VDR host"), - _("The default VDR host"), - 10, vdr_class_default_mrl_change_cb, (void *)this); - this->mrls[ 1 ] = 0; - - this->fast_osd_scaling = config->register_bool(config, - "input.xvdr.fast_osd_scaling", 0, - _("Fast (low-quality) OSD scaling"), - _("Enable fast (lower quality) OSD scaling.\n" - "Default is to use (slow) linear interpolation " - "to calculate pixels and full palette re-allocation " - "to optimize color palette.\n" - "Fast method only duplicates/removes rows and columns " - "and does not modify palette."), - 10, vdr_class_fast_osd_scaling_cb, - (void *)this); - - this->input_class.get_instance = vdr_class_get_instance; -#if INPUT_PLUGIN_IFACE_VERSION < 18 - this->input_class.get_identifier = vdr_class_get_identifier; - this->input_class.get_description = vdr_class_get_description; -#else - this->input_class.identifier = "xvdr"; - this->input_class.description = N_("VDR (Video Disk Recorder) input plugin"); -#endif - this->input_class.get_autoplay_list = vdr_plugin_get_autoplay_list; - this->input_class.dispose = vdr_class_dispose; - - LOGDBG("init class succeeded"); - - return this; -} - - -/* - * exported plugin catalog entry - */ - -const plugin_info_t xine_plugin_info[] __attribute__((visibility("default"))) = { - /* type, API, "name", version, special_info, init_function */ - { PLUGIN_INPUT, INPUT_PLUGIN_IFACE_VERSION, "XVDR", XINE_VERSION_CODE, NULL, init_class }, - { PLUGIN_NONE, 0, "", 0, NULL, NULL } -}; - -const plugin_info_t *xine_plugin_info_xvdr = xine_plugin_info; - - diff --git a/xine_input_vdr.h b/xine_input_vdr.h deleted file mode 100644 index fa9c29fc..00000000 --- a/xine_input_vdr.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * xine_input_vdr.h: - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: xine_input_vdr.h,v 1.5 2008-03-31 20:36:03 phintuka Exp $ - * - */ - -#ifndef __XINE_INPUT_VDR_H_ -#define __XINE_INPUT_VDR_H_ - -#if defined __cplusplus -extern "C" { -#endif - -struct input_plugin_s; -struct osd_command_s; -struct frontend_s; - -typedef struct vdr_input_plugin_funcs_s { - /* VDR --> input plugin (only local mode) */ - int (*push_input_write)(struct input_plugin_s *, const char *, int); - int (*push_input_control)(struct input_plugin_s *, const char *); - int (*push_input_osd)(struct input_plugin_s *, struct osd_command_s *); - /* input plugin --> frontend (only local mode) */ - void (*xine_input_event)(const char *, const char *); - /* input plugin --> frontend (remote mode) */ - int (*intercept_osd)(struct frontend_s *, struct osd_command_s *); - /* input plugin --> frontend */ - void *(*fe_control)(struct frontend_s *, const char *); - struct frontend_s *fe_handle; - /* frontend --> input plugin (remote mode) */ - int (*input_control)(struct input_plugin_s *, const char *, const char *, int, int); -} vdr_input_plugin_funcs_t; - -#define CONTROL_OK 0 -#define CONTROL_UNKNOWN -1 -#define CONTROL_PARAM_ERROR -2 -#define CONTROL_DISCONNECTED -3 - -typedef struct grab_data_s { - int size; - char *data; -} grab_data_t; - -#if defined __cplusplus -} -#endif - - -#endif /*__XINE_INPUT_VDR_H_*/ - diff --git a/xine_input_vdr_net.h b/xine_input_vdr_net.h deleted file mode 100644 index da93476d..00000000 --- a/xine_input_vdr_net.h +++ /dev/null @@ -1,167 +0,0 @@ -/* - * xine_input_vdr_net.h: - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: xine_input_vdr_net.h,v 1.9 2007-03-29 14:22:27 phintuka Exp $ - * - */ - -#ifndef __XINE_INPUT_VDR_NET_H_ -#define __XINE_INPUT_VDR_NET_H_ - -#include <arpa/inet.h> -#ifdef __APPLE__ -# include <machine/endian.h> -#else -# include <endian.h> -#endif - -#ifndef PACKED -# define PACKED __attribute__((packed)) -#endif - -#include "tools/rtp.h" /* generic RTP headers */ - - -/* - * Default port(s) - */ - -#ifndef DEFAULT_VDR_PORT -# define DEFAULT_VDR_PORT 37890 -#endif - -/* - * Byte-order conversions - */ - -#if __BYTE_ORDER == __BIG_ENDIAN -#elif __BYTE_ORDER == __LITTLE_ENDIAN -#else -# error __BYTE_ORDER not defined ! -#endif - -#if __BYTE_ORDER == __BIG_ENDIAN -# define ntohll(val) (val) -# define htonll(val) (val) -# define ntohull(val) (val) -# define htonull(val) (val) -#else -# define ntohll(val) ((int64_t)ntohull((uint64_t)val)) -# define htonll(val) ((int64_t)htonull((uint64_t)val)) -# define ntohull(val) \ - ((uint64_t) ntohl((uint32_t)((val) >> 32)) | \ - (uint64_t) ntohl((uint32_t)(val)) << 32) -# define htonull(val) \ - ((uint64_t) htonl((uint32_t)((val) >> 32)) | \ - (uint64_t) htonl((uint32_t)(val)) << 32) -#endif - - -/* - * Network packet headers - */ - -#if defined __cplusplus -extern "C" { -#endif - - -/* - * TCP / PIPE - */ - -typedef struct stream_tcp_header { - uint64_t pos; /* stream position of first byte */ - uint32_t len; /* length of following PES packet */ - - uint8_t payload[0]; - -} PACKED stream_tcp_header_t; - - -/* - * UDP - */ - -typedef struct stream_udp_header { - uint64_t pos; /* stream position of first byte */ - /* -1ULL and first bytes of frame != 00 00 01 */ - /* --> embedded control stream data */ - uint16_t seq; /* packet sequence number - (for re-ordering and detecting missing packets) */ - - uint8_t payload[0]; - -} PACKED stream_udp_header_t; - -#define UDP_SEQ_MASK 0xff - - -/* - * RTP - */ - -/* xineliboutput RTP header extension */ -typedef struct stream_rtp_header_ext_x { - - stream_rtp_header_ext_t hdr; - - union { - uint8_t raw[12]; /* 3 DWORDs */ - uint32_t rawd[3]; - - union { - - struct { - uint8_t padding0[2]; /* must be padded to full DWORDs */ - stream_udp_header_t udphdr; - } PACKED; - - struct { - uint8_t padding1[2]; /* must be padded to full DWORDs */ - - uint64_t pos; - uint16_t seq; - } PACKED; - - } PACKED; - } PACKED; - - uint8_t payload[0]; - -} PACKED stream_rtp_header_ext_x_t; - - -/* xineliboutput RTP header */ -typedef struct stream_rtp_header_impl { - - stream_rtp_header_t rtp_hdr; - stream_rtp_header_ext_x_t hdr_ext; - - uint8_t payload[0]; - -} PACKED stream_rtp_header_impl_t; - - -#define RTP_VERSION 2 -#define RTP_MARKER_BIT 0x80 -#define RTP_HDREXT_BIT 0x10 -#define RTP_PAYLOAD_TYPE 96 /* application */ - -#define RTP_VERSION_BYTE (RTP_VERSION<<6) -#define RTP_PAYLOAD_TYPE_M (RTP_PAYLOAD_TYPE|RTP_MARKER_BIT) - -#define RTP_HEADER_EXT_X_SIZE 3 /* dwords, not counting stream_rtp_header_ext_t */ -#define RTP_HEADER_EXT_X_TYPE 0x54d3 - - -#if defined __cplusplus -} -#endif - - -#endif /*__XINE_INPUT_VDR_NET_H_*/ - diff --git a/xine_osd_command.h b/xine_osd_command.h deleted file mode 100644 index 5d24bd8b..00000000 --- a/xine_osd_command.h +++ /dev/null @@ -1,155 +0,0 @@ -/* - * xine_osd_command.h: - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: xine_osd_command.h,v 1.12 2008-04-14 19:58:50 phintuka Exp $ - * - */ - -#ifndef __XINE_OSD_COMMAND_H_ -#define __XINE_OSD_COMMAND_H_ - -#ifndef PACKED -# define PACKED __attribute__((packed)) -#endif - - -#define MAX_OSD_OBJECT 50 - -#if defined __cplusplus -extern "C" { -#endif - -typedef enum { - OSD_Nop = 0, /* Do nothing ; used to initialize delay_ms counter */ - OSD_Size = 1, /* Set size of VDR OSD area (usually 720x576) */ - OSD_Set_RLE = 2, /* Create/update OSD window. Data is rle-compressed. */ - OSD_SetPalette = 3, /* Modify palette of already created OSD window */ - OSD_Move = 4, /* Change x/y position of already created OSD window */ - OSD_Close = 5, /* Close OSD window */ - OSD_Set_YUV = 6, /* Create/update OSD window. Data is in YUV420 format. */ - OSD_Commit = 7 /* All OSD areas have been updated, commit changes to display */ -} osd_command_id_t; - -#define OSDFLAG_YUV_CLUT 0x01 /* palette is in YUV format */ -#define OSDFLAG_REFRESH 0x02 /* OSD data refresh for new config, clients, etc. - no changes in bitmap */ -#define OSDFLAG_UNSCALED 0x04 /* xine-lib unscaled (hardware) blending */ -#define OSDFLAG_UNSCALED_LOWRES 0x08 /* unscaled blending when video resolution < .95 * 720x576 */ - -typedef struct xine_clut_s { - union { - uint8_t cb /*: 8*/; - uint8_t g; - }; - union { - uint8_t cr /*: 8*/; - uint8_t b; - }; - union { - uint8_t y /*: 8*/; - uint8_t r; - }; - uint8_t alpha /*: 8*/; -} PACKED xine_clut_t; /* from xine, alphablend.h */ - -typedef struct xine_rle_elem_s { - uint16_t len; - uint16_t color; -} PACKED xine_rle_elem_t; /* from xine */ - -typedef struct osd_rect_s { - uint16_t x1; - uint16_t y1; - uint16_t x2; - uint16_t y2; -} osd_rect_t; - -typedef struct osd_command_s { - uint32_t cmd; /* osd_command_id_t */ - - uint32_t wnd; /* OSD window handle */ - - int64_t pts; /* execute at given pts */ - uint32_t delay_ms; /* execute 'delay_ms' ms after previous command (for same window). */ - - uint16_t x; /* window position, x */ - uint16_t y; /* window position, y */ - uint16_t w; /* window width */ - uint16_t h; /* window height */ - - uint32_t datalen; /* size of image data, in bytes */ - uint32_t num_rle; - union { - xine_rle_elem_t *data; /* RLE compressed image */ - uint8_t *raw_data; - uint64_t dummy01; - }; - uint32_t colors; /* palette size */ - union { - xine_clut_t *palette; /* palette (YCrCb) */ - uint64_t dummy02; - }; - - osd_rect_t dirty_area; - uint8_t flags; - uint8_t scaling; - -} PACKED osd_command_t; - - -#if __BYTE_ORDER == __LITTLE_ENDIAN -# define hton_osdcmd(cmdP) \ - do { \ - cmdP.cmd = htonl (cmdP.cmd); \ - cmdP.wnd = htonl (cmdP.wnd); \ - cmdP.pts = htonll(cmdP.pts); \ - cmdP.delay_ms = htonl (cmdP.delay_ms); \ - cmdP.x = htons (cmdP.x); \ - cmdP.y = htons (cmdP.y); \ - cmdP.w = htons (cmdP.w); \ - cmdP.h = htons (cmdP.h); \ - cmdP.datalen = htonl (cmdP.datalen); \ - cmdP.num_rle = htonl (cmdP.num_rle); \ - cmdP.colors = htonl (cmdP.colors); \ - cmdP.dirty_area.x1 = htons(cmdP.dirty_area.x1); \ - cmdP.dirty_area.y1 = htons(cmdP.dirty_area.y1); \ - cmdP.dirty_area.x2 = htons(cmdP.dirty_area.x2); \ - cmdP.dirty_area.y2 = htons(cmdP.dirty_area.y2); \ - } while(0) - -# define ntoh_osdcmd(cmdP) \ - do { \ - cmdP.cmd = ntohl (cmdP.cmd); \ - cmdP.wnd = ntohl (cmdP.wnd); \ - cmdP.pts = ntohll(cmdP.pts); \ - cmdP.delay_ms = ntohl (cmdP.delay_ms); \ - cmdP.x = ntohs (cmdP.x); \ - cmdP.y = ntohs (cmdP.y); \ - cmdP.w = ntohs (cmdP.w); \ - cmdP.h = ntohs (cmdP.h); \ - cmdP.datalen = ntohl (cmdP.datalen); \ - cmdP.num_rle = ntohl (cmdP.num_rle); \ - cmdP.colors = ntohl (cmdP.colors); \ - cmdP.dirty_area.x1 = ntohs(cmdP.dirty_area.x1); \ - cmdP.dirty_area.y1 = ntohs(cmdP.dirty_area.y1); \ - cmdP.dirty_area.x2 = ntohs(cmdP.dirty_area.x2); \ - cmdP.dirty_area.y2 = ntohs(cmdP.dirty_area.y2); \ - } while(0) - -#elif __BYTE_ORDER == __BIG_ENDIAN - -# define hton_osdcmd(cmd) do {} while(0) -# define ntoh_osdcmd(cmd) do {} while(0) - -#else -# error __BYTE_ORDER undefined ! -#endif - - -#if defined __cplusplus -} -#endif - -#endif /*__XINE_OSD_COMMAND_H_*/ diff --git a/xine_post_audiochannel.c b/xine_post_audiochannel.c deleted file mode 100644 index 3d1ad609..00000000 --- a/xine_post_audiochannel.c +++ /dev/null @@ -1,323 +0,0 @@ -/* - * xine_post_audiochannel.c: xine post plugin - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: xine_post_audiochannel.c,v 1.5 2008-01-02 01:55:19 phintuka Exp $ - * - */ - -/* - * Copyright (C) 2006 the xine project - * - * This file is part of xine, a free video player. - * - * xine is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * xine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - * - * $Id: - * - * audio channel selection post plugin by Petri Hintukainen 01/09/2006 - * based on upmix.c - * - * Removes left or right channel from stereo audio track - * and fills both channels with same data. - * This is useful with some bi-lingual DVB transmissions where - * two different languages are sent on same (stereo) audio track. - * - */ - -#include <xine/xine_internal.h> -#include <xine/post.h> - - -typedef struct audioch_parameters_s { - int channel; -} audioch_parameters_t; - -START_PARAM_DESCR(audioch_parameters_t) -PARAM_ITEM(POST_PARAM_TYPE_BOOL, channel, NULL, 0, 1, 0, - "select channel (0=left, 1=right)") -END_PARAM_DESCR(audioch_param_descr) - - -typedef struct audioch_post_plugin_s -{ - post_plugin_t post_plugin; - xine_post_in_t parameter_input; - - /* Config */ - int channel; /* 0 - left, 1 - right */ - - /* Data */ - int channels; - -} audioch_post_plugin_t; - - -/* - * Port functions - */ -#if XINE_VERSION_CODE < 10200 -static int audioch_port_open(xine_audio_port_t *port_gen, xine_stream_t *stream, - uint32_t bits, uint32_t rate, int mode) -#else -static int audioch_port_open(xine_audio_port_t *port_gen, xine_stream_t *stream, - ao_format_t format) -#endif -{ - post_audio_port_t *port = (post_audio_port_t *)port_gen; - audioch_post_plugin_t *this = (audioch_post_plugin_t *)port->post; - - _x_post_rewire(&this->post_plugin); - _x_post_inc_usage(port); - - port->stream = stream; -#if XINE_VERSION_CODE < 10200 - port->bits = bits; - port->rate = rate; - port->mode = mode; - - this->channels = _x_ao_mode2channels(mode); - - return port->original_port->open(port->original_port, stream, bits, rate, mode ); -#else - port->format = format; - - this->num_channels = _x_ao_mode2channels(format.mode); - - return port->original_port->open(port->original_port, stream, format); -#endif - - -} - -static void audioch_port_put_buffer (xine_audio_port_t *port_gen, - audio_buffer_t *buf, xine_stream_t *stream) -{ - post_audio_port_t *port = (post_audio_port_t *)port_gen; - audioch_post_plugin_t *this = (audioch_post_plugin_t *)port->post; - int i; - - if(this->channels == 2) { -#if XINE_VERSION_CODE < 10200 - int step = buf->format.bits / 8; -#else - int step = sample_bytes_table[buf->format.sample_format]; -#endif - audio_buffer_t *newbuf = port->original_port->get_buffer(port->original_port); - newbuf->num_frames = buf->num_frames; - newbuf->vpts = buf->vpts; - newbuf->frame_header_count = buf->frame_header_count; - newbuf->first_access_unit = buf->first_access_unit; -#if XINE_VERSION_CODE < 10200 - newbuf->format.bits = buf->format.bits; - newbuf->format.rate = buf->format.rate; - newbuf->format.mode = buf->format.mode; -#else - newbuf->format = buf->format; -#endif - _x_extra_info_merge( newbuf->extra_info, buf->extra_info); - - switch(step) { - case 1: - for(i=0; i<buf->num_frames; i++) - newbuf->mem[i*2+1] = newbuf->mem[i*2] = buf->mem[i*2+this->channel]; - break; - case 2: - for(i=0; i<buf->num_frames; i++) - ((uint16_t*)newbuf->mem)[i*2+1] = - ((uint16_t*)newbuf->mem)[i*2] = ((uint16_t*)buf->mem)[i*2+this->channel]; - break; - case 3: - for(i=0; i<buf->num_frames*3; i+=3) { - newbuf->mem[i*2+0] = newbuf->mem[i*2+3] = buf->mem[i*2+0+3*this->channel]; - newbuf->mem[i*2+1] = newbuf->mem[i*2+4] = buf->mem[i*2+1+3*this->channel]; - newbuf->mem[i*2+2] = newbuf->mem[i*2+5] = buf->mem[i*2+2+3*this->channel]; - } - break; - case 4: - for(i=0; i<buf->num_frames; i++) - ((uint32_t*)newbuf->mem)[i*2+1] = - ((uint32_t*)newbuf->mem)[i*2] = ((uint32_t*)buf->mem)[i*2+this->channel]; - break; - default: /* ??? */ - memcpy(newbuf->mem, buf->mem, buf->num_frames*2*buf->format.bits); - break; - } - - /* pass data to original port */ - port->original_port->put_buffer(port->original_port, newbuf, stream ); - - /* free data from origial buffer */ - buf->num_frames=0; /* UNDOCUMENTED, but hey, it works! Force old audio_out buffer free. */ - } - - port->original_port->put_buffer(port->original_port, buf, stream ); -} - -/* - * Parameter functions - */ - -static xine_post_api_descr_t *audioch_get_param_descr(void) -{ - return &audioch_param_descr; -} - -static int audioch_set_parameters(xine_post_t *this_gen, void *param_gen) -{ - audioch_post_plugin_t *this = (audioch_post_plugin_t *)this_gen; - audioch_parameters_t *param = (audioch_parameters_t *)param_gen; - - this->channel = param->channel; - return 1; -} - -static int audioch_get_parameters(xine_post_t *this_gen, void *param_gen) -{ - audioch_post_plugin_t *this = (audioch_post_plugin_t *)this_gen; - audioch_parameters_t *param = (audioch_parameters_t *)param_gen; - - param->channel = this->channel; - return 1; -} - -static char *audioch_get_help(void) { - return _("The audiochannel plugin is meant to take stereo audio and \n" - "remove left or right channel by replacing both channels \n" - "with the same data. \n" - "\n" - "Parameters \n" - " channel: Select channel (left=0, right=1) \n" - "\n" - ); -} - - -/* - * Open / Close - */ - -static void audioch_dispose(post_plugin_t *this_gen) -{ - if (_x_post_dispose(this_gen)) - free(this_gen); -} - -static post_plugin_t *audioch_open_plugin(post_class_t *class_gen, - int inputs, - xine_audio_port_t **audio_target, - xine_video_port_t **video_target) -{ - audioch_post_plugin_t *this = (audioch_post_plugin_t*)xine_xmalloc(sizeof(audioch_post_plugin_t)); - post_in_t *input; - post_out_t *output; - post_audio_port_t *port; - xine_post_in_t *input_param; - - static xine_post_api_t post_api = - { audioch_set_parameters, audioch_get_parameters, - audioch_get_param_descr, audioch_get_help }; - - if (!this || !audio_target || !audio_target[0] ) { - free(this); - return NULL; - } - - _x_post_init(&this->post_plugin, 1, 0); - - port = _x_post_intercept_audio_port(&this->post_plugin, - audio_target[ 0 ], - &input, &output); - - port->new_port.open = audioch_port_open; - port->new_port.put_buffer = audioch_port_put_buffer; - - input->xine_in.name = "audio in"; - output->xine_out.name = "audio out"; - - this->post_plugin.xine_post.audio_input[ 0 ] = &port->new_port; - this->post_plugin.dispose = audioch_dispose; - - input_param = &this->parameter_input; - input_param->name = "parameters"; - input_param->type = XINE_POST_DATA_PARAMETERS; - input_param->data = &post_api; -#if XINE_VERSION_CODE >= 10102 - xine_list_push_back(this->post_plugin.input, input_param); -#else - xine_list_append_content(this->post_plugin.input, input_param); -#endif - - this->channel = 0; - - this->channels = 0; - - return &this->post_plugin; -} - -/* - * Plugin class - */ - -#if POST_PLUGIN_IFACE_VERSION < 10 -static char *audioch_get_identifier(post_class_t *class_gen) -{ - return "audiochannel"; -} - -static char *audioch_get_description(post_class_t *class_gen) -{ - return "Select audio channel"; -} - -static void audioch_class_dispose(post_class_t *class_gen) -{ - free(class_gen); -} -#endif - -static void *audioch_init_plugin(xine_t *xine, void *data) -{ - post_class_t *class = (post_class_t*)malloc(sizeof(post_class_t)); - - if(!class) - return NULL; - - class->open_plugin = audioch_open_plugin; -#if POST_PLUGIN_IFACE_VERSION < 10 - class->get_identifier = audioch_get_identifier; - class->get_description = audioch_get_description; - class->dispose = audioch_class_dispose; -#else - class->identifier = "audiochannel"; - class->description = N_("Select audio channel"); - class->dispose = default_post_class_dispose; -#endif - - return class; -} - -static post_info_t audioch_info = { XINE_POST_TYPE_AUDIO_FILTER }; - -#ifndef NO_INFO_EXPORT -plugin_info_t xine_plugin_info[] __attribute__((visibility("default"))) = -{ - /* type, API, "name", version, special_info, init_function */ - { PLUGIN_POST, POST_PLUGIN_IFACE_VERSION, "audiochannel", XINE_VERSION_CODE, &audioch_info, &audioch_init_plugin }, - { PLUGIN_NONE, 0, "", 0, NULL, NULL } -}; -#endif diff --git a/xine_post_autocrop.c b/xine_post_autocrop.c deleted file mode 100644 index 26edcaf6..00000000 --- a/xine_post_autocrop.c +++ /dev/null @@ -1,1623 +0,0 @@ -/* - * xine_post_autocrop.c: xine post plugin - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: xine_post_autocrop.c,v 1.12 2008-01-02 01:55:19 phintuka Exp $ - * - */ - -/* - * Copyright (C) 2006 the xine project - * - * This file is part of xine, a free video player. - * - * xine is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * xine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - * - * $Id: xine_post_autocrop.c,v 1.12 2008-01-02 01:55:19 phintuka Exp $ - * - * autocrop video filter by Petri Hintukainen 25/03/2006 - * - * Automatically crop 4:3 letterbox frames to 16:9 - * - * based on expand.c - * - * - * TODO: - * - more reliable border detection, including channel logo detection - * - OSD re-positioning (?) - * - */ - - -#ifdef HAVE_CONFIG_H -#include "config.h" /* ARCH_X86 */ -#endif - -#include <stdint.h> - -#include <xine/xine_internal.h> -#include <xine/post.h> - -/* - * Configuration - */ - -/*#define USE_CROP / * Crop frame in video_out instead of copying */ -/*#define MARK_FRAME Draw markers on detected boundaries */ -/*#define ENABLE_64BIT 1 Force using of 64-bit routines */ -/*#undef __MMX__ Disable MMX */ -/*#undef __SSE__ Disable SSE */ -/*#define FILTER2 Tighter Y-filter */ - -# if defined(__SSE__) -# warning Compiling with SSE support -# include <xmmintrin.h> -# elif defined(__MMX__) -# warning Compiling with MMX support -# include <mmintrin.h> -# endif - -#if defined(__WORDSIZE) -# if __WORDSIZE == 64 -# warning Compiling with 64-bit integer support -# define ENABLE_64BIT (sizeof(int) > 32) -# endif -#endif - -/*#define TRACE printf*/ -#define TRACE(x...) do {} while(0) -#define INFO printf - - -/* - * Constants - */ - -#define YNOISEFILTER (0xE0U) -#define YSHIFTUP (0x05U) -#define UVBLACK (0x80U) -#define UVSHIFTUP (0x03U) -#define UVNOISEFILTER (0xF8U) - -/* YV12 */ -#define YNOISEFILTER32 (YNOISEFILTER * 0x01010101U) -#define YSHIFTUP32 (YSHIFTUP * 0x01010101U) -#define UVBLACK32 (UVBLACK * 0x01010101U) -#define UVSHIFTUP32 (UVSHIFTUP * 0x01010101U) -#define UVNOISEFILTER32 (UVNOISEFILTER * 0x01010101U) - -#define YNOISEFILTER64 (YNOISEFILTER * UINT64_C(0x0101010101010101)) -#define YSHIFTUP64 (YSHIFTUP * UINT64_C(0x0101010101010101)) -#define UVBLACK64 (UVBLACK * UINT64_C(0x0101010101010101)) -#define UVSHIFTUP64 (UVSHIFTUP * UINT64_C(0x0101010101010101)) -#define UVNOISEFILTER64 (UVNOISEFILTER * UINT64_C(0x0101010101010101)) - -/* YUY2 */ -/* TODO: should use normal/inverse order based on endianess */ -#if 0 -#define YUY2BLACK32 (UVBLACK * 0x00010001U) -#define YUY2SHIFTUP32 (UVSHIFTUP * 0x00010001U) -#define YUY2NOISEFILTER32 ((YNOISEFILTER * 0x01000100U)|(UVNOISEFILTER * 0x00010001U)) -#else -#define YUY2BLACK32 (UVBLACK * 0x01000100U) -#define YUY2SHIFTUP32 (UVSHIFTUP * 0x01000100U) -#define YUY2NOISEFILTER32 ((YNOISEFILTER * 0x00010001U)|(UVNOISEFILTER * 0x01000100U)) -#endif - -#define YUY2BLACK64 (YUY2BLACK32 * UINT64_C(0x0000000100000001)) -#define YUY2SHIFTUP64 (YUY2SHIFTUP32 * UINT64_C(0x0000000100000001)) -#define YUY2NOISEFILTER64 (YUY2NOISEFILTER32 * UINT64_C(0x0000000100000001)) - -#ifdef FILTER2 -/* tighter Y-filter: original black threshold is 0x1f ; here it is 0x1f - 0x0b = 0x14 */ -# define YUY2SHIFTUP32 ((UVSHIFTUP * 0x00010001U)|(YSHIFTUP * 0x01000100U)) -# undef __SSE__ -#endif - - -#define START_TIMER_INIT (25) /* 1 second, unit: frames */ -#define HEIGHT_LIMIT_LIFETIME (60*25) /* 1 minute, unit: frames */ - -#define LOGOSKIP (frame->width/4) /* skip logo (Y, top-left or top-right quarter) */ - -/* - * Plugin - */ - -typedef struct autocrop_parameters_s { - int enable_autodetect; - int enable_subs_detect; - int soft_start; - int stabilize; -} autocrop_parameters_t; - -START_PARAM_DESCR(autocrop_parameters_t) -PARAM_ITEM(POST_PARAM_TYPE_BOOL, enable_autodetect, NULL, 0, 1, 0, - "enable automatic border detecton") -PARAM_ITEM(POST_PARAM_TYPE_BOOL, enable_subs_detect, NULL, 0, 1, 0, - "enable automatic subtitle detecton") -PARAM_ITEM(POST_PARAM_TYPE_BOOL, soft_start, NULL, 0, 1, 0, - "enable soft start of cropping") -PARAM_ITEM(POST_PARAM_TYPE_BOOL, stabilize, NULL, 0, 1, 0, - "stabilize cropping to 14:9, 16:9, (16:9+subs), 20:9, (20:9+subs)") -END_PARAM_DESCR(autocrop_param_descr) - - -typedef struct autocrop_post_plugin_s -{ - post_plugin_t post_plugin; - - xine_post_in_t parameter_input; - - /* setup */ - int autodetect; - int subs_detect; - int soft_start; - int stabilize; - - /* Current cropping status */ - int cropping_active; - - /* Detected bars */ - int start_line; - int end_line; - int crop_total; - - /* Previously detected bars - - eliminate jumping if there is some noise at bar boundaries: - don't change cropped area unless it has been stable for - some time */ - int prev_start_line; - int prev_end_line; - - /* Delayed start for cropping */ - int start_timer; - int stabilize_timer; - - /* Last seen frame */ - int prev_height; - int prev_width; - int64_t prev_pts; - - /* eliminate jumping when when there are subtitles inside bottom bar: - - when cropping is active and one frame has larger end_line - than previous, we enlarge frame. - - after this, cropping is not resetted to previous value unless - bottom bar has been empty for certain time */ - int height_limit_active; /* true if detected possible subtitles in bottom area */ - int height_limit; /* do not crop bottom above this value (bottom of subtitles) */ - int height_limit_timer; /* counter how many following frames must have black - bottom bar until returning to full cropping - (used to reset height_limit when there are no subtitles) */ -} autocrop_post_plugin_t; - - -/* - * Black bar detection - * - * Detect black lines with simple noise filtering. - * Line is "black" if Y-valus are less than 0x20 and - * U/V values inside range 0x7d...0x84. - * ~ 32 first and last pixels are not checked. - * - */ - -static int blank_line_Y_C(uint8_t *data, int length); -static int blank_line_UV_C(uint8_t *data, int length); -static int blank_line_YUY2_C(uint8_t *data, int length); -#if defined(ENABLE_64BIT) -static int blank_line_Y_C64(uint8_t *data, int length); -static int blank_line_UV_C64(uint8_t *data, int length); -static int blank_line_YUY2_C64(uint8_t *data, int length); -#endif -#if defined(__MMX__) -static int blank_line_Y_mmx(uint8_t *data, int length); -static int blank_line_UV_mmx(uint8_t *data, int length); -static int blank_line_YUY2_mmx(uint8_t *data, int length); -#endif -#if defined(__SSE__) -static int blank_line_Y_sse(uint8_t *data, int length); -static int blank_line_UV_sse(uint8_t *data, int length); -static int blank_line_YUY2_sse(uint8_t *data, int length); -#endif - -static int blank_line_Y_INIT(uint8_t *data, int length); -static int blank_line_UV_INIT(uint8_t *data, int length); -static int blank_line_YUY2_INIT(uint8_t *data, int length); - -static void autocrop_init_mm_accel(void); - -int (*blank_line_Y)(uint8_t *data, int length) = blank_line_Y_INIT; -int (*blank_line_UV)(uint8_t *data, int length) = blank_line_UV_INIT; -int (*blank_line_YUY2)(uint8_t *data, int length) = blank_line_YUY2_INIT; - -static int blank_line_Y_C(uint8_t *data, int length) -{ - uint32_t *data32 = (uint32_t*)((((long int)data) + 32 + 3) & (~3)), r = 0; - - length -= 64; /* skip borders (2 x 32 pixels) */ - length /= 4; /* 4 bytes / loop */ - -#ifdef FILTER2 - while(length) { - /* shiftdown needs saturated unsigned element-wise substraction, available only in MMX ...*/ - /* -> use shiftup and looser noise filter for same result. */ - /* this needs special handling for large values */ - r = r | data32[--length]; /* this catches large values (0xf9 : 0xf9+0x7=0x100 === black) */ - r = r | (data32[length] + YSHIFTUP32); /* this catches small walues (0x1d...0x1f) */ - } -#else - while(length) - r = r | data32[--length]; -#endif - - return !(r & YNOISEFILTER32); -} - -static int blank_line_UV_C(uint8_t *data, int length) -{ - uint32_t *data32 = (uint32_t*)((((long int)data) + 16 + 3) & (~3)); - uint32_t r1 = 0, r2 = 0; - - length -= 32; /* skip borders (2 x 32 pixels, 2 pix/byte) */ - length /= 4; /* 2 x 4 bytes / loop */ - - while(length>0) { - r1 = r1 | ((data32[--length] + UVSHIFTUP32) ^ UVBLACK32); - r2 = r2 | ((data32[--length] + UVSHIFTUP32) ^ UVBLACK32); - } - return !((r1|r2) & (UVNOISEFILTER32)); -} - -#if defined(ENABLE_64BIT) -static int blank_line_Y_C64(uint8_t *data, int length) -{ - uint64_t *data64 = (uint64_t*)((((long int)data) + 32 + 7) & (~7)), r = 0; - - length -= 64; /* skip borders (2 x 32 pixels) */ - length /= 8; /* 8 bytes / loop */ - -#ifdef FILTER2 - while(length) { - r = r | data64[--length]; - r = r | (data64[length] + YSHIFTUP64); - } -#else - while(length) - r = r | data64[--length]; -#endif - - return !(r & YNOISEFILTER64); -} -#endif - -#if defined(ENABLE_64BIT) -static int blank_line_UV_C64(uint8_t *data, int length) -{ - uint64_t *data64 = (uint64_t*)((((long int)data) + 16 + 7) & (~7)); - uint64_t r1 = UINT64_C(0), r2 = UINT64_C(0); - - length -= 32; /* skip borders (2x32 pixels, 2 pix/byte) */ - length /= 8; /* 2 x 8 bytes / loop */ - - while(length>0) { - r1 = r1 | ((data64[--length] + UVSHIFTUP64) ^ UVBLACK64); - r2 = r2 | ((data64[--length] + UVSHIFTUP64) ^ UVBLACK64); - } - return !((r1|r2) & (UVNOISEFILTER64)); -} -#endif - - -#if defined(__MMX__) -typedef union { - uint32_t u32[2]; - __m64 m64; -} __attribute__((__aligned__ (8))) __m64_wrapper; -#endif - -#if defined(__MMX__) - int blank_line_Y_mmx(uint8_t *data, int length) -{ -#ifdef FILTER2 - static const __m64_wrapper mask = {{YNOISEFILTER32, YNOISEFILTER32}}; - static const __m64_wrapper gshift = {{YSHIFTUP32, YSHIFTUP32}}; - register __m64 sum, sum2, shift = gshift.m64, val; -#else - static const __m64_wrapper mask = {{YNOISEFILTER32, YNOISEFILTER32}}; - register __m64 sum; -#endif - __m64 *data64 = (__m64*)(((long int)(data + 32 + 7)) & (~7)); - - /*sum = _m_pxor(sum,sum);*/ - __asm__("pxor %0,%0" : "=y"(sum)); - - length -= 64; /* skip borders (2 x 32 pixels) */ - length /= 8; /* 8 bytes / loop */ - -#ifdef FILTER2 - __asm__("pxor %0,%0" : "=y"(sum2)); - while(length) { - val = data64[--length]; - sum = _m_por(sum, val); - sum2 = _m_por(sum2, _m_paddb(val, shift)); - } - sum = _m_por(sum, sum2); -#else - while(length) - sum = _m_por(sum, data64[--length]); -#endif - - sum = _m_pand(sum, mask.m64); - return 0 == _m_to_int(_m_packsswb(sum, sum)); -} -#endif - -#if defined(__MMX__) -static int blank_line_UV_mmx(uint8_t *data, int length) -{ - static const __m64_wrapper gm_03 = {{UVSHIFTUP32, UVSHIFTUP32}}; - static const __m64_wrapper gm_f8 = {{UVNOISEFILTER32, UVNOISEFILTER32}}; - static const __m64_wrapper gm_80 = {{UVBLACK32, UVBLACK32}}; - __m64 *data64 = (__m64*)(((long int)(data) + 16 + 7) & (~7)); - register __m64 sum1, sum2, m_03, /*m_f8,*/ m_80; - - /*sum1 = _m_pxor(sum1, sum1); sum1 = _mm_setzero_si64(); */ - /*sum2 = _m_pxor(sum2, sum2); sum2 = _mm_setzero_si64(); */ - __asm__("pxor %0,%0" : "=y"(sum1)); - __asm__("pxor %0,%0" : "=y"(sum2)); - - /* fetch static data to MMX registers */ - m_03 = gm_03.m64; - /*m_f8 = gm_f8.m64;*/ - m_80 = gm_80.m64; - - length -= 32; /* skip borders (2 x 32 pixels, 2pix/byte) */ - length /= 8; /* 8 bytes / vector */ - - do { - /* process two 8-byte vectors */ - sum1 = _m_por(sum1, - /* grab every byte that is not black (x ^ 0x80 != 0) */ - _m_pxor( - /* filter noise: U/V of each "black" pixel should be 0x7d..0x84 - -> each black pixel should be 0x80 after (x+3) & 0xf8 */ - /*_m_pand(*/ - /* each black pixel should be 0x80..0x87 after adding 3 */ - _m_paddb( - data64[length-1], - m_03)/*, - m_f8)*/, - m_80)); - sum2 = _m_por(sum2, - _m_pxor( - /*_m_pand( */ - _m_paddb( - data64[length-2], - m_03)/*, - m_f8)*/, - m_80)); - length -= 2; - } while(length>0); - - /* combine two result vectors (or), filter noise (and) */ - sum1 = _m_pand(_m_por(sum1, - sum2), - gm_f8.m64); - /* result vector of black line is 0 */ - return 0 == _m_to_int(_m_packsswb(sum1, sum1)); -} -#endif - -#if defined(__SSE__) -typedef union { - uint32_t u32[4]; - __m128 m128; -} __attribute((__aligned__ (16))) __m128_wrapper; -#endif - -#if defined(__SSE__) -static int blank_line_Y_sse(uint8_t *data, int length) -{ - static const __m128_wrapper gmask = {{YNOISEFILTER32, YNOISEFILTER32, - YNOISEFILTER32, YNOISEFILTER32}}; - __m128 *data128 = (__m128*)(((long int)(data) + 32 + 15) & (~15)); - register __m128 sum1, sum2, zero, mask; - - length -= 64; /* skip borders (2 x 32 pixels) */ - length /= 16; /* 16 bytes / loop */ - - /* Start prefetching data to CPU cache */ - _mm_prefetch(data128+length-1, _MM_HINT_NTA); - _mm_prefetch(data128+length-3, _MM_HINT_NTA); - - /* - * Process in two paraller loops, one 16 byte vector / each sub-loop - * - grabs bytes with value larger than treshold - */ - - zero = _mm_setzero_ps(); - mask = gmask.m128; - sum1 = zero; - sum2 = zero; - - do { - _mm_prefetch(data128+length-5, _MM_HINT_NTA); - sum1 = _mm_or_ps(sum1, data128[--length]); - sum2 = _mm_or_ps(sum2, data128[--length]); - } while(length>0); - - return 0x0f == _mm_movemask_ps(_mm_cmpeq_ps(_mm_and_ps(_mm_or_ps(sum1, - sum2), - gmask.m128), - _mm_setzero_ps())); -} -#endif - -#if defined(__SSE__) -static int blank_line_UV_sse(uint8_t *data, int length) -{ - uint8_t *top = data + length - 1; - do { - _mm_prefetch(top, _MM_HINT_NTA); - _mm_prefetch(top-32, _MM_HINT_NTA); - _mm_prefetch(top-64, _MM_HINT_NTA); - _mm_prefetch(top-72, _MM_HINT_NTA); - top -= 128; - } while(top >= data); - - return blank_line_UV_mmx(data, length); -} -#endif - -static int blank_line_YUY2_C(uint8_t *data, int length) -{ - uint32_t *data32 = (uint32_t*)((((long int)data) + 64 + 3) & (~3)); - uint32_t r1 = 0, r2 = 0; - - length -= 128; /* skip borders (2 x 32 pixels, 2 bytes/pixel) */ - length /= 4; /* 2 x 4 bytes / loop */ - - while(length) { - r1 = r1 | ((data32[--length] + YUY2SHIFTUP32) ^ YUY2BLACK32); - r2 = r2 | ((data32[--length] + YUY2SHIFTUP32) ^ YUY2BLACK32); - } - return !((r1|r2) & YUY2NOISEFILTER32); -} - -#if defined(ENABLE_64BIT) -static int blank_line_YUY2_C64(uint8_t *data, int length) -{ - uint64_t *data64 = (uint64_t*)((((long int)data) + 64 + 7) & (~7)); - uint64_t r1 = 0, r2 = 0; - - length -= 128; /* skip borders (2 x 32 pixels, 2 bytes/pixel) */ - length /= 8; /* 2 x 8 bytes / loop */ - - while(length) { - r1 = r1 | ((data64[--length] + YUY2SHIFTUP64) ^ YUY2BLACK64); - r2 = r2 | ((data64[--length] + YUY2SHIFTUP64) ^ YUY2BLACK64); - } - return !((r1|r2) & YUY2NOISEFILTER64); -} -#endif - -#if defined(__MMX__) -static int blank_line_YUY2_mmx(uint8_t *data, int length) -{ - /* not implemented */ - -# if !defined(ENABLE_64BIT) - return blank_line_YUY2_C(data, length); -# else - return blank_line_YUY2_C64(data, length); -# endif -} -#endif - -#if defined(__SSE__) -static int blank_line_YUY2_sse(uint8_t *data, int length) -{ - uint8_t *top = data + length - 1; - do { - _mm_prefetch(top, _MM_HINT_NTA); - _mm_prefetch(top-32, _MM_HINT_NTA); - _mm_prefetch(top-64, _MM_HINT_NTA); - _mm_prefetch(top-72, _MM_HINT_NTA); - top -= 128; - } while(top >= data); - - return blank_line_YUY2_mmx(data, length); -} -#endif - -static void autocrop_init_mm_accel(void) -{ - blank_line_Y = blank_line_Y_C; - blank_line_UV = blank_line_UV_C; - blank_line_YUY2 = blank_line_YUY2_C; - -#if defined(__SSE__) - if(xine_mm_accel() & MM_ACCEL_X86_SSE) { - INFO("autocrop_init_mm_accel: using SSE\n"); - blank_line_Y = blank_line_Y_sse; - blank_line_UV = blank_line_UV_sse; - blank_line_YUY2 = blank_line_YUY2_sse; - return; - } -#endif -#if defined(ENABLE_64BIT) - if(ENABLE_64BIT) { - INFO("autocrop_init_mm_accel: using 64-bit integer operations\n"); - blank_line_Y = blank_line_Y_C64; - blank_line_UV = blank_line_UV_C64; - blank_line_YUY2 = blank_line_YUY2_C64; - return; - } -#endif -#if defined(__MMX__) - if(xine_mm_accel() & MM_ACCEL_X86_MMX) { - /* mmx not faster than normal x64 (?) */ - INFO("autocrop_init_mm_accel: using MMX\n"); - blank_line_Y = blank_line_Y_mmx; - blank_line_UV = blank_line_UV_mmx; - blank_line_YUY2 = blank_line_YUY2_mmx; - return; - } -#endif - INFO("autocrop_init_mm_accel: no compatible acceleration methods found\n"); -} - -static int blank_line_Y_INIT(uint8_t *data, int length) -{ - autocrop_init_mm_accel(); - return (*blank_line_Y)(data, length); -} - -static int blank_line_UV_INIT(uint8_t *data, int length) -{ - autocrop_init_mm_accel(); - return (*blank_line_UV)(data, length); -} - -static int blank_line_YUY2_INIT(uint8_t *data, int length) -{ - autocrop_init_mm_accel(); - return (*blank_line_YUY2)(data, length); -} - -/* - * Analyze frame - * - if frame needs cropping set crop_top & crop_bottom - */ - -#ifdef MARK_FRAME -int dbg_top=0, dbg_bottom=0; -#endif - -static int analyze_frame_yv12(vo_frame_t *frame, int *crop_top, int *crop_bottom) -{ - int y; - int ypitch = frame->pitches[0]; - int upitch = frame->pitches[1]; - int vpitch = frame->pitches[2]; - uint8_t *ydata = frame->base[0]; - uint8_t *udata = frame->base[1]; - uint8_t *vdata = frame->base[2]; - int max_crop = (frame->height / 4) / 2; /* 4:3 --> 16:9 */ - - /* from top -> down */ - ydata += 8 * ypitch; /* skip 8 first lines */ - udata += 4 * upitch; - vdata += 4 * vpitch; - for(y = 8; y <= max_crop *2 /* *2 = 20:9+subs -> 16:9 */ ; y += 2) { - if( ! ( blank_line_UV(udata, (frame->width-LOGOSKIP)/2) || - blank_line_UV(udata+LOGOSKIP/2, (frame->width-LOGOSKIP)/2) ) || - ! ( blank_line_UV(vdata, (frame->width-LOGOSKIP)/2) || - blank_line_UV(vdata+LOGOSKIP/2, (frame->width-LOGOSKIP)/2) ) || - ! ( blank_line_Y( ydata, (frame->width-LOGOSKIP) ) || - blank_line_Y( ydata+LOGOSKIP, (frame->width-LOGOSKIP) ) ) || - ! ( blank_line_Y( ydata+ypitch, (frame->width-LOGOSKIP) ) || - blank_line_Y( ydata+ypitch+LOGOSKIP,(frame->width-LOGOSKIP) ) )) { - break; - } else { - ydata += 2 * ypitch; - udata += upitch; - vdata += vpitch; - } - } - *crop_top = y>8 ? y : 0; - - /* from bottom -> up */ - ydata = frame->base[0] + ((frame->height-4) -1 ) * ypitch; - udata = frame->base[1] + ((frame->height-4)/2 -1 ) * upitch; - vdata = frame->base[2] + ((frame->height-4)/2 -1 ) * vpitch; - for(y = frame->height - 5; y >= frame->height-max_crop; y -=2 ) { - if( ! blank_line_Y(ydata, frame->width) || - ! blank_line_Y(ydata-ypitch, frame->width) || - ! blank_line_UV(udata, frame->width/2) || - ! blank_line_UV(vdata, frame->width/2)) { - break; - } else { - ydata -= 2*ypitch; - udata -= upitch; - vdata -= vpitch; - } - } - *crop_bottom = y; - - /* test for black in center - don't crop if frame is empty */ - if(*crop_top >= max_crop*2 && *crop_bottom <= frame->height-max_crop) { - ydata = frame->base[0] + (frame->height/2)*ypitch; - udata = frame->base[1] + (frame->height/4)*upitch; - vdata = frame->base[2] + (frame->height/4)*vpitch; - if( blank_line_Y(ydata, frame->width) && - blank_line_Y(ydata-ypitch, frame->width) && - blank_line_UV(udata, frame->width/2) && - blank_line_UV(vdata, frame->width/2)) { - TRACE("not cropping black frame\n"); -#if 0 - *crop_top = 0; - *crop_bottom = frame->height - 1; -#else - return 0; -#endif - } - } - return 1; -} - -static int analyze_frame_yuy2(vo_frame_t *frame, int *crop_top, int *crop_bottom) -{ - int y; - int pitch = frame->pitches[0]; - uint8_t *data = frame->base[0]; - int max_crop = (frame->height / 4) / 2; /* 4:3 --> 16:9 */ - - /* from top -> down */ - data += 6 * pitch; /* skip 6 first lines */ - for(y = 6; y <= max_crop *2 /* *2 = 20:9+subs -> 16:9 */ ; y ++) - if( ! ( blank_line_YUY2(data, (frame->width-LOGOSKIP)*2) || - blank_line_YUY2(data+2*LOGOSKIP, (frame->width-LOGOSKIP)*2))) - break; - else - data += pitch; - - *crop_top = y; - - /* from bottom -> up */ - data = frame->base[0] + ((frame->height-4) -1 ) * pitch; - for(y = frame->height - 5; y >= frame->height-max_crop; y -- ) - if( ! blank_line_YUY2(data, frame->width * 2)) - break; - else - data -= pitch; - - *crop_bottom = y; - - /* test for black in center - don't crop if frame is empty */ - if(*crop_top >= max_crop*2 && *crop_bottom <= frame->height-max_crop) { - data = frame->base[0] + (frame->height/2)*pitch; - if( blank_line_YUY2(data, frame->width * 2)) { - TRACE("not cropping black frame\n"); -#if 0 - *crop_top = 0; - *crop_bottom = frame->height - 1; -#else - return 0; -#endif - } - } - - return 1; -} - -static void analyze_frame(vo_frame_t *frame, int *crop_top, int *crop_bottom) -{ - post_video_port_t *port = (post_video_port_t *)frame->port; - autocrop_post_plugin_t *this = (autocrop_post_plugin_t *)port->post; - int result; - - if(frame->format == XINE_IMGFMT_YV12) - result = analyze_frame_yv12(frame, crop_top, crop_bottom); - else /*if(frame->format == XINE_IMGFMT_YUY2)*/ - result = analyze_frame_yuy2(frame, crop_top, crop_bottom); - -#if defined(__MMX__) - _mm_empty(); -#endif - - if(!result) - return; - -#ifdef MARK_FRAME - dbg_top = *crop_top; dbg_bottom = *crop_bottom; -#endif - - if(this->stabilize) { - int bottom = frame->height - *crop_bottom; - int wide = 0; - - /* bottom bar size */ - if(bottom < frame->height/32) { - TRACE("bottom: %d -> 4:3 ", *crop_bottom); - *crop_bottom = frame->height - 1; /* no cropping */ - } else if(bottom < frame->height*3/32) { - TRACE("bottom: %d -> 14:9 (%d) ", *crop_bottom, frame->height * 15 / 16 - 1); - *crop_bottom = frame->height * 15 / 16 - 1; /* 14:9 */ - } else if(bottom < frame->height*3/16) { - TRACE("bottom: %d -> 16:9 (%d) ", *crop_bottom, frame->height * 7 / 8 - 1); - *crop_bottom = frame->height * 7 / 8 - 1; /* 16:9 */ - wide = 1; - } else { - TRACE("bottom: %d -> 20:9 (%d) ", *crop_bottom, frame->height * 3 / 4 - 1); - *crop_bottom = frame->height * 3 / 4 - 1; /* 20:9 */ - wide = 2; - } - - /* top bar size */ - if(*crop_top < frame->height/32) { - TRACE("top: %3d -> 4:3 \n", *crop_top); - *crop_top = 0; /* no cropping */ - } else if(*crop_top < frame->height*3/32) { - TRACE("top: %3d -> 14:9 (%d)\n", *crop_top, frame->height / 16); - *crop_top = frame->height / 16; /* 14:9 */ - } else if(*crop_top < frame->height*3/16 || wide) { - TRACE("top: %3d -> 16:9 (%d)\n", *crop_top, frame->height / 8); - *crop_top = frame->height / 8; /* 16:9 */ - } else { - TRACE("top: %3d -> 20:9 (%d)\n", *crop_top, frame->height / 4); - *crop_top = frame->height / 4; /* 20:9 */ - wide++; - } - switch(wide) { - case 3: *crop_top -= frame->height / 8; - if(*crop_top < 0) - *crop_top = 0; - TRACE(" wide -> center top\n"); - case 2: *crop_bottom += frame->height / 8; - if(*crop_bottom >= frame->height) - *crop_bottom = frame->height-1; - TRACE(" wide -> center bottom\n"); - } - - } else { - - if(*crop_top > (frame->height/8 *2)) /* *2 --> 20:9 -> 16:9 + subtitles */ - *crop_top = frame->height/8 *2 ; - if(*crop_bottom < (frame->height*7/8)) - *crop_bottom = frame->height*7/8; - - if(*crop_top > (frame->height/8)) { - /* if wider than 16:9, prefer cropping top if subtitles are inside bottom bar */ - if(*crop_top + (frame->height - *crop_bottom) > frame->height/4) { - int diff = *crop_top + (frame->height - *crop_bottom) - frame->height/4; - diff &= ~1; - TRACE("balance: %d,%d -> %d,%d\n", - *crop_top, *crop_bottom, - *crop_top, *crop_bottom + diff); -#if 0 - /* this moves image to top (crop only top) */ - *crop_bottom += diff; -#endif -#if 0 - /* this moves image to center */ - /* may cause problems with subtitles ... */ - *crop_top -= diff; -#endif -#if 1 - /* this moves image to center when there are no - detected subtitles inside bottom bar */ - if(this->height_limit_active) { - int reserved = this->height_limit - *crop_bottom; - if(reserved>0) { - *crop_bottom += reserved; - diff -= reserved; - } - } - *crop_top -= diff; -#endif -#if 0 - /* do nothing - image will be centered in video out. - - problems with subtitles using unscaled OSD */ -#endif - } - } - - /* stay inside frame and forget very small bars */ - if(*crop_top <= 8) - *crop_top = 0; - if(*crop_bottom >= (frame->height-6)) - *crop_bottom = frame->height; - - if(*crop_top < frame->height/12 || *crop_bottom > frame->height*11/12) { - /* Small bars -> crop only detected borders */ - if(*crop_top || *crop_bottom < frame->height-1) { - TRACE("Small bars -> <16:9 : start_line = %d end_line = %d (%s%d t%d)\n", - *crop_top, *crop_bottom, - this->height_limit_active ? "height limit " : "", - this->height_limit, - this->height_limit_active ? this->height_limit_timer : 0); - } - } else { - /* Large bars -> crop to 16:9 */ - TRACE("Large bars -> 16:9 : start_line = %d end_line = %d (%s%d t%d)\n", - *crop_top, *crop_bottom, - this->height_limit_active ? "height limit " : "", - this->height_limit, - this->height_limit_active ? this->height_limit_timer : 0); - if(*crop_top < frame->height / 8) - *crop_top = frame->height / 8; - if(*crop_bottom < frame->height * 7 / 8) - *crop_bottom = frame->height * 7 / 8; - } - } - - /* adjust start and stop to even lines */ - (*crop_top) = (*crop_top) & (~1); - (*crop_bottom) = (*crop_bottom + 1) & (~1); -} - -#ifdef MARK_FRAME -static void mark_frame_yv12(autocrop_post_plugin_t *this, - vo_frame_t *frame, int *crop_top, int *crop_bottom) -{ - int ypitch = frame->pitches[0]; - int upitch = frame->pitches[1]; - int vpitch = frame->pitches[2]; - uint8_t *ydata = frame->base[0]; - uint8_t *udata = frame->base[1]; - uint8_t *vdata = frame->base[2]; - - /* draw markers to detected boundaries and expected boundaries */ - if(*crop_top > 4 && *crop_top < 200) { - ydata = frame->base[0] + ((*crop_top)-2)*ypitch; - udata = frame->base[1] + ((*crop_top)/2 -1)*upitch; - memset(ydata, 0xff, frame->width/10); - memset(ydata+ypitch, 0xff, frame->width/10); - memset(udata, 0xff, frame->width/2/10); - - if(dbg_top < *crop_top) dbg_top = *crop_top; - ydata = frame->base[0] + ((dbg_top - *crop_top))*ypitch; - udata = frame->base[1] + ((dbg_top - *crop_top)/2)*upitch; - memset(ydata, 0x80, frame->width/2); - memset(ydata+ypitch, 0x80, frame->width/2); - memset(udata, 0xff, frame->width/2/2); - } - if(*crop_bottom > 300) { - if(*crop_bottom < frame->height - 2) { - ydata = frame->base[0] + (*crop_bottom + 2)*ypitch; - udata = frame->base[1] + ((*crop_bottom)/2)*upitch; - memset(ydata, 0xff, frame->width); - memset(ydata+ypitch, 0xff, frame->width); - memset(udata, 0xff, frame->width/2); - } - if(dbg_bottom - *crop_top - 2 < frame->height) { - ydata = frame->base[0] + (dbg_bottom - *crop_top - 2)*ypitch; - udata = frame->base[1] + (dbg_bottom - *crop_top - 2)/2*upitch; - memset(ydata, 0x80, frame->width/2); - memset(ydata+ypitch, 0xff, frame->width/2); - memset(udata, 0xff, frame->width/2/2); - } - } - if(frame->height > 500) { - /* TODO: use frame height instead of assuming 576 ... -> 72 */ - vdata = frame->base[2] + ((72-*crop_top)/2)*vpitch; -vdata = frame->base[2] + (72/2)*vpitch; - memset(vdata, 0xff, frame->width/2); - vdata = frame->base[2] + ((frame->height-72+(576-*crop_bottom))/2)*vpitch; -vdata = frame->base[2] + ((frame->height-72)/2)*vpitch; - memset(vdata, 0xff, frame->width/2); - } -} -#endif - -/* - * crop frame by copying - */ -#ifndef USE_CROP -static int crop_copy_yv12(vo_frame_t *frame, xine_stream_t *stream) -{ - post_video_port_t *port = (post_video_port_t *)frame->port; - autocrop_post_plugin_t *this = (autocrop_post_plugin_t *)port->post; - vo_frame_t *new_frame; - - int y, result; - int yp = frame->pitches[0], yp2; - int up = frame->pitches[1], up2; - int vp = frame->pitches[2], vp2; - uint8_t *ydata = frame->base[0], *ydata2; - uint8_t *udata = frame->base[1], *udata2; - uint8_t *vdata = frame->base[2], *vdata2; - - int new_height; - float new_ratio; - - /* top bar */ - ydata += this->start_line * yp; - udata += (this->start_line/2) * up; - vdata += (this->start_line/2) * vp; - - new_height = this->end_line - this->start_line; - new_ratio = 12.0/9.0 * ((float)frame->height / (float)new_height); - - new_frame = port->original_port->get_frame(port->original_port, - frame->width, new_height, - new_ratio, frame->format, - frame->flags | VO_BOTH_FIELDS); - - /* ??? */ - frame->ratio = new_frame->ratio; - - _x_post_frame_copy_down(frame, new_frame); - - yp2 = new_frame->pitches[0]; - up2 = new_frame->pitches[1]; - vp2 = new_frame->pitches[2]; - ydata2 = new_frame->base[0]; - udata2 = new_frame->base[1]; - vdata2 = new_frame->base[2]; - - /* - TODO: - save channel logo mask (from top) - - no changes in 3 sec -> next time crop it out ... - */ - - for(y=0; y < new_height/2; y++) { - xine_fast_memcpy(ydata2, ydata, frame->width); - ydata += yp; - ydata2 += yp2; - xine_fast_memcpy(ydata2, ydata, frame->width); - ydata += yp; - ydata2 += yp2; - xine_fast_memcpy(udata2, udata, frame->width/2); - udata += up; - udata2 += up2; - xine_fast_memcpy(vdata2, vdata, frame->width/2); - vdata += vp; - vdata2 += vp2; - } - -#ifdef MARK_FRAME - mark_frame_yv12(this, new_frame, &this->start_line, &this->end_line); -#endif - - result = new_frame->draw(new_frame, stream); - _x_post_frame_copy_up(frame, new_frame); - new_frame->free(new_frame); - - return result; -} - -static int crop_copy_yuy2(vo_frame_t *frame, xine_stream_t *stream) -{ - post_video_port_t *port = (post_video_port_t *)frame->port; - autocrop_post_plugin_t *this = (autocrop_post_plugin_t *)port->post; - vo_frame_t *new_frame; - - int y, result; - int p = frame->pitches[0], p2; - uint8_t *data = frame->base[0], *data2; - - int new_height; - float new_ratio; - - /* top bar */ - data += this->start_line * p; - - new_height = this->end_line - this->start_line; - new_ratio = 12.0/9.0 * ((float)frame->height / (float)new_height); - new_frame = port->original_port->get_frame(port->original_port, - frame->width, new_height, - new_ratio, frame->format, - frame->flags | VO_BOTH_FIELDS); - /* ??? */ - frame->ratio = new_frame->ratio; - - _x_post_frame_copy_down(frame, new_frame); - - p2 = new_frame->pitches[0]; - data2 = new_frame->base[0]; - - for(y=0; y < new_height; y++) { - xine_fast_memcpy(data2, data, frame->width); - data += p; - data2 += p2; - } - - result = new_frame->draw(new_frame, stream); - _x_post_frame_copy_up(frame, new_frame); - new_frame->free(new_frame); - - return result; -} - -#endif - -/* - * crop frame without copying - */ -#ifdef USE_CROP -static int crop_nocopy(vo_frame_t *frame, xine_stream_t *stream) -{ - post_video_port_t *port = (post_video_port_t *)frame->port; - autocrop_post_plugin_t *this = (autocrop_post_plugin_t *)port->post; - int skip; - double new_ratio = frame->ratio; - int new_height; - - if(this->cropping_active) { - frame->crop_top += this->start_line; - frame->crop_bottom += (frame->height + 1 - this->end_line); - - TRACE("crop_nocopy: top ->%d bottom ->%d\n", frame->crop_top, frame->crop_bottom); - - new_height = this->end_line - this->start_line; - new_ratio = 12.0/9.0 * ((float)frame->height / (float)new_height); - } - - _x_post_frame_copy_down(frame, frame->next); - - /* ??? */ - frame->ratio = new_ratio; - - skip = frame->next->draw(frame->next, stream); - TRACE("crop: top %d, bottom %d\n", frame->crop_top, frame->crop_bottom); - _x_post_frame_copy_up(frame, frame->next); - - return skip; -} -#endif - -/* - * Frame handling - */ - -static int autocrop_draw(vo_frame_t *frame, xine_stream_t *stream) -{ - post_video_port_t *port = (post_video_port_t *)frame->port; - autocrop_post_plugin_t *this = (autocrop_post_plugin_t *)port->post; - int result; - int detected_start, detected_end; - - if(!this->autodetect) { - this->start_line = frame->height/8; - this->end_line = frame->height*7/8; - this->crop_total = frame->height/4; -#ifdef USE_CROP - return crop_nocopy(frame, stream); -#else - if(frame->format == XINE_IMGFMT_YV12) - return crop_copy_yv12(frame, stream); - else /*if(frame->format == XINE_IMGFMT_YUY2)*/ - return crop_copy_yuy2(frame, stream); -#endif - } - - /* use pts jumps to track stream changes (and seeks) */ - if(frame->pts > 0) { - if(this->prev_pts>0) { - int64_t dpts = frame->pts - this->prev_pts; - if(dpts < INT64_C(-30*90000) || dpts > INT64_C(30*90000)) { /* 30 sec */ - if(this->height_limit_active) { - this->height_limit_timer = START_TIMER_INIT; - TRACE("short pts jump resetted height limit"); - } - } - if(dpts < INT64_C(-30*60*90000) || dpts > INT64_C(30*60*90000)) { /* 30 min */ - this->cropping_active = 0; - TRACE("long pts jump resetted cropping"); - } - } - this->prev_pts = frame->pts; - } - - /* reset ? */ - if(! this->cropping_active) { - this->prev_start_line = 0; - this->prev_end_line = frame->height; - this->start_timer = START_TIMER_INIT; - this->prev_pts = -1; - if(this->height_limit_active) { - TRACE("height limit reset (no cropping)"); - } - this->height_limit_active = 0; - this->height_limit = frame->height; - } - - /* only 4:3 YV12 frames are cropped */ - if(frame->ratio != 4.0/3.0 || (frame->format != XINE_IMGFMT_YV12 && - frame->format != XINE_IMGFMT_YUY2)) { - this->cropping_active = 0; - - } else if(frame->bad_frame) { - - /* check for letterbox borders only from I-frames */ - } else if(frame->picture_coding_type == 1/*XINE_PICT_I_TYPE*/) { - - analyze_frame(frame, &this->start_line, &this->end_line); - - /* ignore very small bars */ - if(this->start_line > 10 || this->end_line < frame->height - 10) - this->cropping_active = 1; - else - this->cropping_active = 0; - - this->prev_height = frame->height; - this->prev_width = frame->width; - - /* no change unless same values for several frames */ - if(this->stabilize && - (this->start_line != this->prev_start_line || - this->end_line != this->prev_end_line)) { - if(this->stabilize_timer) - this->stabilize_timer--; - else - this->stabilize_timer = 4; - if(this->stabilize_timer) { - TRACE("stabilize start_line: %d -> %d, end_line %d -> %d\n", - this->start_line, this->prev_start_line, - this->end_line, this->prev_end_line); - this->start_line = this->prev_start_line; - this->end_line = this->prev_end_line; - } - } - - } else { - /* reset when format changes */ - if(frame->height != this->prev_height) - this->cropping_active = 0; - if(frame->width != this->prev_width) - this->cropping_active = 0; - } - - /* update timers */ - if(this->start_timer) - this->start_timer--; - - if(this->height_limit_timer) { - if (! --this->height_limit_timer) { - this->height_limit_active = 0; - this->height_limit = frame->height; - TRACE("height limit timer expired"); - } - } - - /* no cropping to be done ? */ - if (/*frame->bad_frame ||*/ !this->cropping_active || this->start_timer>0) { - _x_post_frame_copy_down(frame, frame->next); - result = frame->next->draw(frame->next, stream); - _x_post_frame_copy_up(frame, frame->next); - return result; - } - - /* "soft start" and border stabilization */ - detected_start = this->start_line; - detected_end = this->end_line; - if(this->soft_start) { - if(this->prev_start_line != this->start_line) { - int diff = this->prev_start_line - this->start_line; - if(diff < -4) diff = -4; - else if(diff > 4) diff = 4; - else diff = 0; - this->start_line = this->prev_start_line - diff; - } - if(this->prev_end_line != this->end_line) { - int diff = this->prev_end_line - this->end_line; - if(diff < -4) diff = -4; - else if(diff > 4) diff = 4; - else diff = 0; - this->end_line = this->prev_end_line - diff; - } - } - - /* handle fixed subtitles inside bottom bar */ - if(this->subs_detect) { - if(abs(this->prev_start_line - this->start_line) > 5 ) { - /* reset height limit if top bar changes */ - TRACE("height limit reset, top bar moved from %d -> %d\n", - this->prev_start_line, this->start_line); - this->height_limit_active = 0; - this->height_limit = frame->height; - this->height_limit_timer = 0; - } - if (this->end_line > this->prev_end_line) { - if(!this->height_limit_active || - this->height_limit < this->end_line) { - /* start or increase height limit */ - TRACE("height limit %d -> %d (%d secs)\n", - this->height_limit, this->end_line, - HEIGHT_LIMIT_LIFETIME/25); - this->height_limit = this->end_line; - this->height_limit_timer = HEIGHT_LIMIT_LIFETIME; - this->height_limit_active = 1; - } - if(this->height_limit_active && - this->height_limit_timer < HEIGHT_LIMIT_LIFETIME/4) { - /* keep heigh limit timer running */ - TRACE("height_limit_timer increment (still needed)\n"); - this->height_limit_timer = HEIGHT_LIMIT_LIFETIME/2; - } - } - } - - this->prev_start_line = this->start_line; - this->prev_end_line = this->end_line; - - if(this->subs_detect) { - if(this->height_limit_active) { - /* apply height limit */ - if(this->end_line < this->height_limit) - this->end_line = this->height_limit; - } else { - this->height_limit = frame->height; - } - } - - /* - * do cropping - * - using frame->crop_... does not seem to work with my xv and xine-lib-1.1.1. - * - maybe cropping could be done by adjusting y/u/v data pointers - * and height of frame ? - * -> no time-consuming copying - */ -#ifdef USE_CROP - result = crop_nocopy(frame, stream); -#else - if(frame->format == XINE_IMGFMT_YV12) - result = crop_copy_yv12(frame, stream); - else /*if(frame->format == XINE_IMGFMT_YUY2)*/ - result = crop_copy_yuy2(frame, stream); -#endif - this->crop_total = this->start_line + frame->height - this->end_line; - - /* forget stabilized values */ - this->start_line = detected_start; - this->end_line = detected_end; - - return result; -} - -#ifdef USE_CROP -static vo_frame_t *autocrop_get_frame(xine_video_port_t *port_gen, - uint32_t width, uint32_t height, - double ratio, int format, int flags) -{ - post_video_port_t *port = (post_video_port_t *)port_gen; - post_plugin_t *this_gen = port->post; - autocrop_post_plugin_t *this = (autocrop_post_plugin_t *)this_gen; - vo_frame_t *frame; - - _x_post_rewire(this_gen); - - if (ratio <= 0.0) - if(height > 1) - ratio = (double)width / (double)height; - - if (this->cropping_active && - ratio == 4.0/3.0 && (format == XINE_IMGFMT_YV12 || - format == XINE_IMGFMT_YUY2)) { - int new_height = this->end_line+2 - this->start_line; - float new_ratio = 12.0/9.0 * ((float)height / (float)new_height); - - frame = port->original_port->get_frame(port->original_port, - width, height, - new_ratio, format, flags); - _x_post_inc_usage(port); - frame = _x_post_intercept_video_frame(frame, port); - - frame->ratio = ratio; - return frame; - } - - return port->original_port->get_frame(port->original_port, - width, height, - ratio, format, flags); -} -#endif - -static int autocrop_intercept_frame(post_video_port_t *port, vo_frame_t *frame) -{ - autocrop_post_plugin_t *this = (autocrop_post_plugin_t *)port->post; - - /* Crop only SDTV YV12 4:3 frames ... */ - int intercept = ((frame->format == XINE_IMGFMT_YV12 || - frame->format == XINE_IMGFMT_YUY2) && - frame->ratio == 4.0/3.0 && - frame->width >= 480 && frame->width <= 768 && - frame->height >= 288 && frame->height <= 576); - if(!intercept) { - this->height_limit_active = 0; - this->crop_total = 0; - this->cropping_active = 0; - } - - return intercept; -} - -static int autocrop_intercept_ovl(post_video_port_t *port) -{ - autocrop_post_plugin_t *this = (autocrop_post_plugin_t *)port->post; - - if (!this->cropping_active) - return 0; - - return 1; -} - -static int32_t autocrop_overlay_add_event(video_overlay_manager_t *this_gen, void *event_gen) -{ - post_video_port_t *port = _x_post_ovl_manager_to_port(this_gen); - autocrop_post_plugin_t *this = (autocrop_post_plugin_t *)port->post; - video_overlay_event_t *event = (video_overlay_event_t *)event_gen; - int caps; - - if(this->cropping_active && this->crop_total>10) { - if (event->event_type == OVERLAY_EVENT_SHOW) { - switch (event->object.object_type) { - case 0: - /* regular subtitle */ - /* Subtitle overlays must be coming somewhere inside xine engine */ - - caps = port->stream->video_out->get_capabilities (port->stream->video_out); -#ifdef USE_CROP - if(caps & VO_CAP_CROP) { - if(! event->object.overlay->unscaled || !(caps & VO_CAP_UNSCALED_OVERLAY)) { - event->object.overlay->y -= this->crop_total; - } - } else { - /* object is moved crop_top amount in video_out */ - if(event->object.overlay->unscaled && (caps & VO_CAP_UNSCALED_OVERLAY)) { - /* cancel incorrect move that will be done in video_out */ - event->object.overlay->y += this->start_line; - } else { - /* move crop_bottom pixels up */ - event->object.overlay->y -= (this->crop_total - this->start_line); - } - } - - /* when using cropping overlays are moved in video_out */ - INFO("autocrop_overlay_add_event: subtitle event untouched\n"); -#else - /* when cropping here subtitles coming from inside of xine must be re-positioned */ - if(! event->object.overlay->unscaled || !(caps & VO_CAP_UNSCALED_OVERLAY)) { - event->object.overlay->y -= this->crop_total; - INFO("autocrop_overlay_add_event: subtitle event moved up\n"); - } -#endif - break; - case 1: - /* menu overlay */ - /* All overlays coming from VDR have this type */ - { -#ifdef DVDTEST - int dvd_menu = 0; - if (stream->input_plugin) { - if (stream->input_plugin->get_capabilities (stream->input_plugin) & - INPUT_CAP_SPULANG) { - *((int *)lang) = 0; /* channel */ - if (stream->input_plugin->get_optional_data (stream->input_plugin, lang, - INPUT_OPTIONAL_DATA_SPULANG) - == INPUT_OPTIONAL_SUCCESS) - if(!strcmp(lang, "menu")) - dvd_menu = 1; /* -> cropping off */ - /* should turn on when not in menu ... -> where ? */ - } - } -#endif -#ifdef USE_CROP - if(!event->object.overlay->unscaled) { - event->object.overlay->y += this->start_line;//crop_total; - } else { - caps = port->stream->video_out->get_capabilities (port->stream->video_out); - if(!(caps & VO_CAP_UNSCALED_OVERLAY)) - event->object.overlay->y += this->start_line;//crop_total; - } -#endif - } - break; - } - } - } - - return port->original_manager->add_event(port->original_manager, event_gen); -} - - -/* - * Parameter functions - */ - -static xine_post_api_descr_t *autocrop_get_param_descr(void) -{ - return &autocrop_param_descr; -} - -static int autocrop_set_parameters(xine_post_t *this_gen, void *param_gen) -{ - autocrop_post_plugin_t *this = (autocrop_post_plugin_t *)this_gen; - autocrop_parameters_t *param = (autocrop_parameters_t *)param_gen; - - this->autodetect = param->enable_autodetect; - this->subs_detect = param->enable_subs_detect; - this->soft_start = param->soft_start; - this->stabilize = param->stabilize; - TRACE("autocrop_set_parameters: " - "auto=%d subs=%d soft=%d stabilize=%d\n", - this->autodetect, this->subs_detect, - this->soft_start, this->stabilize); - return 1; -} - -static int autocrop_get_parameters(xine_post_t *this_gen, void *param_gen) -{ - autocrop_post_plugin_t *this = (autocrop_post_plugin_t *)this_gen; - autocrop_parameters_t *param = (autocrop_parameters_t *)param_gen; - - TRACE("autocrop_get_parameters: " - "auto=%d subs=%d soft=%d stabilize=%d\n", - this->autodetect, this->subs_detect, - this->soft_start, this->stabilize); - param->enable_autodetect = this->autodetect; - param->enable_subs_detect = this->subs_detect; - param->soft_start = this->soft_start; - param->stabilize = this->stabilize; - return 1; -} - -static char *autocrop_get_help(void) { - return _("The autocrop plugin is meant to take 4:3 letterboxed frames and " - "convert them to 16:9 by removing black bars on the top and bottom " - "of the frame.\n" - "\n" - "Parameters\n" - " enable_autodetect: Enable automatic letterbox detection\n" - " enable_subs_detect: Enable automatic subtitle detection inside bottom bar\n" - " soft_start: Enable soft start of cropping\n" - " stabilize: Stabilize cropping to\n" - " 14:9, 16:9, (16:9+subs), 20:9, (20:9+subs)\n" - "\n" - ); -} - - -/* - * Open/close - */ - -static void autocrop_dispose(post_plugin_t *this_gen) -{ - if (_x_post_dispose(this_gen)) - free(this_gen); -} - -static post_plugin_t *autocrop_open_plugin(post_class_t *class_gen, - int inputs, - xine_audio_port_t **audio_target, - xine_video_port_t **video_target) -{ - if (video_target && video_target[ 0 ]) { - autocrop_post_plugin_t *this = (autocrop_post_plugin_t*)xine_xmalloc(sizeof(autocrop_post_plugin_t)); - post_in_t *input; - post_out_t *output; - post_video_port_t *port; - xine_post_in_t *input_param; - - static xine_post_api_t post_api = - { autocrop_set_parameters, autocrop_get_parameters, - autocrop_get_param_descr, autocrop_get_help }; - - if (this) { - _x_post_init(&this->post_plugin, 0, 1); - - port = _x_post_intercept_video_port(&this->post_plugin, - video_target[ 0 ], - &input, &output); - - input->xine_in.name = "video in"; - output->xine_out.name = "video out"; - - port->intercept_ovl = autocrop_intercept_ovl; - port->new_manager->add_event = autocrop_overlay_add_event; - port->intercept_frame = autocrop_intercept_frame; -#ifdef USE_CROP - port->new_port.get_frame = autocrop_get_frame; -#endif - port->new_frame->draw = autocrop_draw; - - this->post_plugin.xine_post.video_input[ 0 ] = &port->new_port; - this->post_plugin.dispose = autocrop_dispose; - - input_param = &this->parameter_input; - input_param->name = "parameters"; - input_param->type = XINE_POST_DATA_PARAMETERS; - input_param->data = &post_api; -#if XINE_VERSION_CODE >= 10102 - xine_list_push_back(this->post_plugin.input, input_param); -#else - xine_list_append_content(this->post_plugin.input, input_param); -#endif - this->cropping_active = 0; - this->autodetect = 1; - this->subs_detect = 1; - this->soft_start = 1; - this->stabilize = 1; - this->start_line = 0; - this->end_line = 576; - - this->prev_start_line = 0; - this->prev_end_line = 576; - - return &this->post_plugin; - } - } - - return NULL; -} - - -/* - * Plugin class - */ - -#if POST_PLUGIN_IFACE_VERSION < 10 -static char *autocrop_get_identifier(post_class_t *class_gen) -{ - return "autocrop"; -} - -static char *autocrop_get_description(post_class_t *class_gen) -{ - return "Crop letterboxed 4:3 video to 16:9"; -} - -static void autocrop_class_dispose(post_class_t *class_gen) -{ - free(class_gen); -} -#endif - -static void *autocrop_init_plugin(xine_t *xine, void *data) -{ - post_class_t *class = (post_class_t*)malloc(sizeof(post_class_t)); - - if(class) { - class->open_plugin = autocrop_open_plugin; -#if POST_PLUGIN_IFACE_VERSION < 10 - class->get_identifier = autocrop_get_identifier; - class->get_description = autocrop_get_description; - class->dispose = autocrop_class_dispose; -#else - class->identifier = "autocrop"; - class->description = N_("Crop letterboxed 4:3 video to 16:9"); - class->dispose = default_post_class_dispose; -#endif - } - - return class; -} - - -static post_info_t info = { XINE_POST_TYPE_VIDEO_FILTER }; - -const plugin_info_t xine_plugin_info[] __attribute__((visibility("default"))) = -{ - /* type, API, "name", version, special_info, init_function */ - { PLUGIN_POST, POST_PLUGIN_IFACE_VERSION, "autocrop", XINE_VERSION_CODE, &info, &autocrop_init_plugin }, - { PLUGIN_NONE, 0, "", 0, NULL, NULL } -}; diff --git a/xine_post_swscale.c b/xine_post_swscale.c deleted file mode 100644 index 26ca43fc..00000000 --- a/xine_post_swscale.c +++ /dev/null @@ -1,1730 +0,0 @@ -/* - * Copyright (C) 2000-2007 the xine project - * - * This file is part of xine, a free video player. - * - * xine is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * xine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - * - * $Id: xine_post_swscale.c,v 1.7 2008-03-13 23:08:18 phintuka Exp $ - * - * Simple (faster) resize for avisynth - * Copyright (C) 2002 Tom Barry - * - * Very simple 2 tap linear interpolation. - * It is unfiltered which means it will not soften much. - * - * WarpedResize will do a non-linear stretch/squeeze in both the horizontal - * and vertical dimensions. This can be useful when you want to change the - * aspect ratio of a video clip and have it mostly distorted at the - * top, bottom, and side edges. - * - * - * Ported to linux/xine by Petri Hintukainen <phintuka@users.sourceforge.net> - * - Added x86_64 support - * - Added PIC support (do not clobber ebx in x86, access only local variables from asm) - * - Fixed yv12 stretched warp tables generation - */ - -#include <xine/xine_internal.h> -#include <xine/post.h> - -/*#define DBG(x...)*/ -#define DBG(x...) fprintf(stderr, "post_warp: " x) - -/*#define STREAMING_STORE_TMP*/ -/*#define STREAMING_STORE*/ -/*#define PREFETCH*/ -/* streaming store and prefetch seems to be slower ... - * Tested with P3 (128M L2) and C2D (4M L2). - * Maybe access pattern is enough simple for HW prefetchers. - */ - -/*#define VANILLA*/ - -/* - * This function accepts a position from 0 to 1 and warps it, to 0 through 1 based - * upon the wFact var. The warp equations are designed to: - * - * * Always be rising but yield results from 0 to 1 - * - * * Have a first derivative that doesn't go to 0 or infinity, at least close - * to the center of the screen - * - * * Have a curvature (absolute val of 2nd derivative) that is small in the - * center and smoothly rises towards the edges. We would like the curvature - * to be everywhere = 0 when the warp factor = 1 - */ -static double WarpFactor(double position, double wFact) -{ - double x; - double z; - double w; - x = 2 * (position - .5); - if (1) /*(wFact < 1.0)*/ - /* For warp factor < 1 the warp is calculated as (1-w) * x^3 + w *x, centered - * - * The warp is calculated as z = (1 - w) * x^3 + w * x, centered - * around .5 and ranging from 0 to 1. After some tinkering this seems - * to give decent values and derivatives at the right places. - */ - w = 2.0 - wFact; /* reverse parm for compat with initial release */ - - if (x < 0.0) { - z = -(1 - w) * x*x*x - w * x; /* -1 < x < 0, wFact < 1 */ - return .5 - .5 * z; - } else { - z = (1 - w) * x*x*x + w * x; /* -1 < x < 0, wFact < 1 */ - return .5 + .5 * z; /* amts to same formula as above for now */ - } -} - -/* - * YV12 - * - * For each horizontal output pair of pixels there is are 2 qword masks followed by 2 int - * offsets. The 2 masks are the weights to be used for the luma and chroma, respectively. - * Each mask contains LeftWeight1, RightWeight1, LeftWeight2, RightWeight2. So a pair of pixels - * will later be processed each pass through the horizontal resize loop. I think with my - * current math the Horizontal Luma and Chroma contains the same values but since I may have screwed it - * up I'll leave it this way for now. Vertical chroma is different. - * - * Note - try just using the luma calcs for both, seem to be the same. - * - * The weights are scaled 0-256 and the left and right weights will sum to 256 for each pixel. - */ -static void init_tables_yv12(int newwidth, int newheight, int oldwidth, int oldheight, - int Interlaced, double hWarp, double vWarp, - uint32_t *hControl, uint32_t *vOffsets, uint32_t *vWeights, - uint32_t *hControlUV, uint32_t *vOffsetsUV, uint32_t *vWeightsUV) -{ - int i; - int j; - int k; - int wY1; - int wY2; - DBG("init_yv12: %dx%d->%dx%d hWarp %1.3lf vWarp %1.3lf\n", - oldwidth, oldheight, newwidth, newheight, hWarp, vWarp); - - /* First set up horizontal table, use for both luma & chroma since - * it seems to have the same equation. - * We will geneerate these values in pairs, mostly because that's the way - * I wrote it for YUY2 above. - */ - - for(i=0; i < newwidth; i+=2) { - /* first make even pixel control */ - if (hWarp==1) /*if no warp factor */ - j = i * 256 * (oldwidth-1) / (newwidth-1); - else /* stretch and warp somehow */ - j = (int) (256 * WarpFactor(i / (newwidth-1.0), hWarp) * (oldwidth-1)); - - k = j>>8; - wY2 = j - (k << 8); /* luma weight of right pixel */ - wY1 = 256 - wY2; /* luma weight of left pixel */ - - if (k > oldwidth - 2) { - hControl[i*3+4] = oldwidth - 1; /* point to last byte */ - hControl[i*3] = 0x00000100; /* use 100% of rightmost Y */ - } else { - hControl[i*3+4] = k; /* pixel offset */ - hControl[i*3] = wY2 << 16 | wY1; /* luma weights */ - } - - /* now make odd pixel control */ - if (hWarp==1) /* if no warp factor */ - j = (i+1) * 256 * (oldwidth-1) / (newwidth-1); - else /* stretch and warp somehow */ - j = (int) (256 * WarpFactor((i+1) / (newwidth-1.0), hWarp) * (oldwidth-1)); - - k = j>>8; - wY2 = j - (k << 8); /* luma weight of right pixel */ - wY1 = 256 - wY2; /* luma weight of left pixel */ - - if (k > oldwidth - 2) { - hControl[i*3+5] = oldwidth - 1; /* point to last byte */ - hControl[i*3+1] = 0x00000100; /* use 100% of rightmost Y */ - } else { - hControl[i*3+5] = k; /* pixel offset */ - hControl[i*3+1] = wY2 << 16 | wY1; /* luma weights */ - } - } - - hControl[newwidth*3+4] = 2 * (oldwidth-1); /* give it something to prefetch at end */ - hControl[newwidth*3+5] = 2 * (oldwidth-1); /* " */ -#ifndef VANILLA - // UV - for(i=0; i < newwidth/2; i+=2) { - /* first make even pixel control */ - if (hWarp==1) /*if no warp factor */ - j = i * 256 * (oldwidth/2-1) / (newwidth/2-1); - else /* stretch and warp somehow */ - j = (int) (256 * WarpFactor(i / (newwidth/2-1.0), hWarp) * (oldwidth/2-1)); - - k = j>>8; - wY2 = j - (k << 8); /* luma weight of right pixel */ - wY1 = 256 - wY2; /* luma weight of left pixel */ - - if (k > oldwidth/2 - 2) { - hControlUV[i*3+4] = oldwidth/2 - 1; /* point to last byte */ - hControlUV[i*3] = 0x00000100; /* use 100% of rightmost Y */ - } else { - hControlUV[i*3+4] = k; /* pixel offset */ - hControlUV[i*3] = wY2 << 16 | wY1; /* luma weights */ - } - - /* now make odd pixel control */ - if (hWarp==1) /* if no warp factor */ - j = (i+1) * 256 * (oldwidth/2-1) / (newwidth/2-1); - else /* stretch and warp somehow */ - j = (int) (256 * WarpFactor((i+1) / (newwidth/2-1.0), hWarp) * (oldwidth/2-1)); - - k = j>>8; - wY2 = j - (k << 8); /* luma weight of right pixel */ - wY1 = 256 - wY2; /* luma weight of left pixel */ - - if (k > oldwidth/2 - 2) { - hControlUV[i*3+5] = oldwidth/2 - 1; /* point to last byte */ - hControlUV[i*3+1] = 0x00000100; /* use 100% of rightmost Y */ - } else { - hControlUV[i*3+5] = k; /* pixel offset */ - hControlUV[i*3+1] = wY2 << 16 | wY1; /* luma weights */ - } - } - - hControlUV[newwidth/2*3+4] = (oldwidth/2-1); /* give it something to prefetch at end */ - hControlUV[newwidth/2*3+5] = (oldwidth/2-1); /* " */ -#endif - - /* Next set up vertical tables. The offsets are measured in lines and will be mult */ - /* by the source pitch later . */ - - /* For YV12 we need separate Luma and chroma tables */ - - /* First Luma Table */ - for(i=0; i< newheight; ++i) { - if (vWarp==1) /* if no warp factor */ - j = i * 256 * (oldheight-1) / (newheight-1); - else /* stretch and warp somehow */ - j = (int) (256 * WarpFactor(i / (newheight-1.0), vWarp) * (oldheight-1)); - - if (Interlaced) { /* do hard way? */ - if (i%2) { /* is odd output line? */ - if (j < 256) { /* before 1st odd input line */ - vOffsets[i] = 1; /* all from line 1 */ - vWeights[i] = 0; /* weight to give to 2nd line */ - } else { - k = (((j-256) >> 9) << 1) + 1; /* next lowest odd line */ - vOffsets[i] = k; - wY2 = j - (k << 8); - vWeights[i] = wY2 >> 1; /* weight to give to 2nd line */ - } - } else { /* is even output line */ - k = (j >> 9) << 1; /* next lower even line */ - vOffsets[i] = k; - wY2 = j - (k << 8); - vWeights[i] = wY2 >> 1; /* weight to give to 2nd line */ - } - } else { /* simple way, do as progressive */ - k = j >> 8; - vOffsets[i] = k; - wY2 = j - (k << 8); - vWeights[i] = wY2; /* weight to give to 2nd line */ - } - } - - /* Vertical table for chroma */ - for(i=0; i< newheight/2; ++i) { - if (vWarp==1) /* if no warp factor */ -#ifdef VANILLA - j = (int) ( (i+.25) * 256 * (oldheight-1) / (newheight-1.0) - 64 ); -#else - j = (int) ( (i+.25) * 256 * (oldheight/2-1) / (newheight/2-1.0) - 64 ); -#endif - else /* stretch and warp somehow */ -#ifdef VANILLA - j = (int) (256 * WarpFactor( (i+.25) / (newheight-1.0), vWarp) * (oldheight-1.0) ); -#else - j = (int) (256 * WarpFactor( (i+.25) / (newheight/2 - 1.0), vWarp) * (oldheight/2 - 1.0) ); -#endif -#ifndef VANILLA - if(j<0) j=0; -#endif - if (Interlaced) { /* do hard way? */ - if (i%2) { /* is odd output line? */ - if (j < 256) { /* before 1st odd input line */ - vOffsetsUV[i] = 1; /* all from line 1 */ - vWeightsUV[i] = 0; /* weight to give to 2nd line */ - } else { - k = (((j-256) >> 9) << 1) + 1; /* next lowest odd line */ - vOffsetsUV[i] = k; - wY2 = j - (k << 8); - vWeightsUV[i] = wY2 >> 1; /* weight to give to 2nd line */ - } - } else { /* is even output line */ -#ifdef VANILLA - k = (j >> 9) << 1; /* next lower even line */ - vOffsetsUV[i] = k; - wY2 = j - (k << 8); - vWeightsUV[i] = wY2 >> 1; /* weight to give to 2nd line */ -#else - k = (j / 512) << 1; /* next lower even line */ - vOffsetsUV[i] = k; - wY2 = j - (k << 8); - vWeightsUV[i] = wY2 >> 1; /* weight to give to 2nd line */ -#endif - } - } else { /* simple way, do as progressive */ -#ifdef VANILLA - k = j >> 8; -#else - k = j / 256; /* j >> 8; does not work right if -256 < j < 0 */ -#endif - vOffsetsUV[i] = k; - wY2 = j - (k << 8); - vWeightsUV[i] = wY2; /* weight to give to 2nd line */ - } - } -} - -/* - * YUY2 - * - * For each horizontal output pair of pixels there is are 2 qword masks followed by 2 int - * offsets. The 2 masks are the weights to be used for the luma and chroma, respectively. - * Each mask contains LeftWeight1, RightWeight1, LeftWeight2, RightWeight2. So a pair of pixels - * will later be processed each pass through the horizontal resize loop. - * - * The weights are scaled 0-256 and the left and right weights will sum to 256 for each pixel. - */ -static void init_tables_yuy2(int newwidth, int newheight, int oldwidth, int oldheight, - int Interlaced, double hWarp, double vWarp, - uint32_t *hControl, uint32_t *vOffsets, uint32_t *vWeights ) -{ - int i; - int j; - int k; - int wY1; - int wY2; - int wUV1; - int wUV2; - DBG("init_yuy2: %dx%d->%dx%d hWarp %1.3lf vWarp %1.3lf\n", - oldwidth, oldheight, newwidth, newheight, hWarp, vWarp); - - /* First set up horizontal table */ - for(i=0; i < newwidth; i+=2) { - /* first make even pixel control */ - if (hWarp==1) /* if no warp factor */ - j = i * 256 * (oldwidth-1) / (newwidth-1); - else /* stretch and warp somehow */ - j = (int) (256 * WarpFactor(i / (newwidth-1.0), hWarp) * (oldwidth-1)); - - k = j>>8; - wY2 = j - (k << 8); /* luma weight of right pixel */ - wY1 = 256 - wY2; /* luma weight of left pixel */ - wUV2 = (k%2) ? 128 + (wY2 >> 1) : wY2 >> 1; - wUV1 = 256 - wUV2; - - if (k > oldwidth - 2) { - hControl[i*3+4] = oldwidth - 1; /* point to last byte */ - hControl[i*3] = 0x00000100; /* use 100% of rightmost Y */ - hControl[i*3+2] = 0x00000100; /* use 100% of rightmost U */ - } else { - hControl[i*3+4] = k; /* pixel offset */ - hControl[i*3] = wY2 << 16 | wY1; /* luma weights */ - hControl[i*3+2] = wUV2 << 16 | wUV1; /* chroma weights */ - } - - /* now make odd pixel control */ - if (hWarp==1) /* if no warp factor */ - j = (i+1) * 256 * (oldwidth-1) / (newwidth-1); - else /* stretch and warp somehow */ - j = (int) (256 * WarpFactor((i+1) / (newwidth-1.0), hWarp) * (oldwidth-1)); - - k = j>>8; - wY2 = j - (k << 8); /* luma weight of right pixel */ - wY1 = 256 - wY2; /* luma weight of left pixel */ - wUV2 = (k%2) ? 128 + (wY2 >> 1) : wY2 >> 1; - wUV1 = 256 - wUV2; - - if (k > oldwidth - 2) { - hControl[i*3+5] = oldwidth - 1; /* point to last byte */ - hControl[i*3+1] = 0x00000100; /* use 100% of rightmost Y */ - hControl[i*3+3] = 0x00000100; /* use 100% of rightmost V */ - } else { - hControl[i*3+5] = k; /* pixel offset */ - hControl[i*3+1] = wY2 << 16 | wY1; /* luma weights */ - /* hControl[i*3+3] = wUV2 << 16 | wUV1; // chroma weights */ - /* horiz chroma weights should be same as for even pixel - trbarry 09/16/2002 */ - hControl[i*3+3] = hControl[i*3+2]; /* chroma weights */ - } - } - - hControl[newwidth*3+4] = 2 * (oldwidth-1); /* give it something to prefetch at end */ - hControl[newwidth*3+5] = 2 * (oldwidth-1); - - /* Next set up vertical table. The offsets are measured in lines and will be mult */ - /* by the source pitch later */ - for(i=0; i< newheight; ++i) { - if (vWarp==1) /* if no warp factor */ - j = i * 256 * (oldheight-1) / (newheight-1); - else /* stretch and warp somehow */ - j = (int) (256 * WarpFactor(i / (newheight-1.0), vWarp) * (oldheight-1)); - - if (Interlaced) { /* do hard way? */ - if (i%2) { /* is odd output line? */ - if (j < 256) { /* before 1st odd input line */ - vOffsets[i] = 1; /* all from line 1 */ - vWeights[i] = 0; /* weight to give to 2nd line */ - } else { - k = (((j-256) >> 9) << 1) + 1; /* next lowest odd line */ - vOffsets[i] = k; - wY2 = j - (k << 8); - vWeights[i] = wY2 >> 1; /* weight to give to 2nd line */ - } - } else { /* is even output line */ - k = (j >> 9) << 1; /* next lower even line */ - vOffsets[i] = k; - wY2 = j - (k << 8); - vWeights[i] = wY2 >> 1; /* weight to give to 2nd line */ - } - } else { /* simple way, do as progressive */ - k = j >> 8; - vOffsets[i] = k; - wY2 = j - (k << 8); - vWeights[i] = wY2; /* weight to give to 2nd line */ - } - } -} - -/* Register allocation */ -/* index/counter registers (REGA, REGC) are loaded from 32bit vars/arrays ! */ -#define REGEA "eax" -#define REGEB "ebx" -#if defined(__x86_64__) -# define REGA "rax" -# define REGB "rbx" -# define REGC "ecx" -# define REGD "rdx" -# define REGDI "rdi" -# define REGSI "rsi" -#elif defined(__i386__) -# define REGA "eax" -# define REGB "ebx" -# define REGC "ecx" -# define REGD "edx" -# define REGDI "edi" -# define REGSI "esi" -#endif - -/* variables accessed from assembler code */ -#define _FPround1 "%0" -#define _vWeight1 "%1" -#define _vWeight2 "%2" -#define _YMask "%3" -#define _src_row_size "%4" -#define _EndOffset "%5" -#define _pControl "%6" -#define _row_size "%7" -#define _vWorkYW "%8" -#define _dstp "%9" -#define _vWorkUVW "%10" -#define _FPround2 "%11" -#define _srcp1 "%12" -#define _srcp2 "%13" -#if !defined(__x86_64__) -#define _oldbx "%14" -#define _SSEMMXenabledW "%15" -#define _SSE2enabledW "%16" -#endif - -/* Labels */ -#define vMaybeSSEMMX "1" -#define LessThan8 "2" -#define LessThan4 "3" -#define AllDone "4" -#define LastOne "5" -#define vLoopSSE2_Fetch "6" -#define vLoopSSE2 "7" -#define vLoopSSEMMX_Fetch "8" -#define vLoopSSEMMX "9" -#define vLoopMMX "10" -#define MoreSpareChange "11" -#define DoHorizontal "12" -#define hLoopMMX "13" -#define hLoopMMXSSE "14" - - -/* structure for mmx constants */ -typedef union { - uint64_t uq[1]; /* Unsigned Quadword */ - uint32_t ud[2]; /* Unsigned Doubleword */ -} ATTR_ALIGN(16) mmx_t; - -/* structure for sse2 constants */ -typedef union { - uint64_t uq[2]; /* Unsigned Quadword */ - uint32_t ud[4]; /* Unsigned Doubleword */ -} ATTR_ALIGN(16) sse2_t; - - -static int do_warp_yuy2(uint8_t *dst, const uint8_t *src, - const int dst_pitch, const int src_pitch, - const int dst_width, const int dst_height, - const int src_width, const int src_height, - const int Interlaced, const uint32_t * const hControl, - const uint32_t * const vOffsets, const uint32_t * const vWeights, - uint32_t *vWorkY, uint32_t *vWorkUV, - int dst_start) -{ -#if defined(__i386__) || defined(__x86_64__) - sse2_t YMask = {uq:{UINT64_C(0x00ff00ff00ff00ff),UINT64_C(0x00ff00ff00ff00ff)}}; /* keeps only luma */ - sse2_t FPround1 = {uq:{UINT64_C(0x0080008000800080),UINT64_C(0x0080008000800080)}}; /* round words */ - sse2_t FPround2 = {uq:{UINT64_C(0x0000008000000080),UINT64_C(0x0000008000000080)}}; /* round dwords */ - sse2_t vWeight1; - sse2_t vWeight2; - - const uint32_t *pControl = &hControl[0]; - const uint32_t *vWorkYW = vWorkY; - const uint32_t *vWorkUVW = vWorkUV; - const uint8_t *srcp = src; - const uint8_t *srcp1; - const uint8_t *srcp2; - uint8_t *dstp = dst + dst_pitch*dst_start; - - const uint32_t src_row_size = src_width * 2; - const uint32_t row_size = dst_width * 2; - const uint32_t EndOffset = src_row_size / 2; - -#if !defined(__x86_64__) - const int accel = xine_mm_accel(); - const uint32_t SSE2enabledW = !!(accel & MM_ACCEL_X86_SSE2); /* in local storage for asm */ - const uint32_t SSEMMXenabledW = !!(accel & MM_ACCEL_X86_MMXEXT); /* in local storage for asm */ - long int oldbx; -#endif - int y; - - for (y = dst_start; y < dst_height; y++) { - - if(vOffsets[y] >= src_height) { - /* slice completed */ - /*DBG("do_warp_yuy2: max input height reached: need line %d, height %d\n -> Returning next output line: %d\n", - vOffsets[y], src_height, y);*/ - return y; - } - - vWeight1.ud[0] = vWeight1.ud[1] = vWeight1.ud[2] = vWeight1.ud[3] = - (256-vWeights[y]) << 16 | (256-vWeights[y]); - vWeight2.ud[0] = vWeight2.ud[1] = vWeight2.ud[2] = vWeight2.ud[3] = - vWeights[y] << 16 | vWeights[y]; - - srcp1 = srcp + vOffsets[y] * src_pitch; - if (Interlaced) - srcp2 = (y < dst_height-2) ? srcp1 + 2 * src_pitch : srcp1; - else - srcp2 = (y < dst_height-1) ? srcp1 + src_pitch : srcp1; - - __asm__ __volatile__ ( -#if !defined(__x86_64__) - /* store ebx (PIC) */ - "mov %%"REGB", "_oldbx" \n\t" -#endif - "movl "_src_row_size", %%"REGC" \n\t" - "shrl $3, %%"REGC" \n\t" /* 8 bytes a time */ - "mov "_srcp1", %%"REGSI" \n\t" /* top of 2 src lines to get */ - "mov "_srcp2", %%"REGD" \n\t" /* next " */ - "mov "_vWorkYW", %%"REGDI" \n\t" /* luma work destination line */ - "mov "_vWorkUVW", %%"REGB" \n\t" /* luma work destination line */ - "xor %%"REGA", %%"REGA" \n\t" -#if !defined(__x86_64__) - /* Let's check here to see if we are on a P4 or higher and can use SSE2 instructions. - * This first loop is not the performance bottleneck anyway but it is trivial to tune - * using SSE2 if we have proper alignment. - */ - "testl $1, "_SSE2enabledW" \n\t" /* is SSE2 supported?*/ - "jz "vMaybeSSEMMX"f \n\t" /* n, can't do anyway*/ -#endif - "cmpl $2, %%"REGC" \n\t" /* we have at least 16 bytes, 2 qwords? */ - "jl "vMaybeSSEMMX"f \n\t" /* n, don't bother*/ - - "shrl $1, %%"REGC" \n\t" /* do 16 bytes at a time instead*/ - "decl %%"REGC" \n" /* jigger loop ct */ - - ".align 16 \n\t" - - "movdqa "_FPround1", %%xmm0 \n\t" - "movdqa "_vWeight1", %%xmm5 \n\t" - "movdqa "_vWeight2", %%xmm6 \n\t" - "movdqa "_YMask", %%xmm7 \n" - - ""vLoopSSE2_Fetch": \n\t" -#ifdef PREFETCH - " prefetcht0 16(%%"REGSI", %%"REGA", 2) \n\t" - " prefetcht0 16(%%"REGD", %%"REGA", 2) \n" -#endif - ""vLoopSSE2": \n\t" - " movdqu (%%"REGSI", %%"REGA", 2), %%xmm1 \n\t" /* top of 2 lines to interpolate */ - " movdqu (%%"REGD", %%"REGA", 2), %%xmm2 \n\t" /* 2nd of 2 lines */ - - " movdqa %%xmm1, %%xmm3 \n\t" /* get chroma bytes */ - " pand %%xmm7, %%xmm1 \n\t" /* keep only luma */ - " psrlw $8, %%xmm3 \n\t" /* right just chroma */ - " pmullw %%xmm5, %%xmm1 \n\t" /* mult by weighting factor */ - " pmullw %%xmm5, %%xmm3 \n\t" /* mult by weighting factor */ - - " movdqa %%xmm2, %%xmm4 \n\t" /* get chroma bytes */ - " pand %%xmm7, %%xmm2 \n\t" /* keep only luma */ - " psrlw $8, %%xmm4 \n\t" /* right just chroma */ - " pmullw %%xmm6, %%xmm2 \n\t" /* mult by weighting factor */ - " pmullw %%xmm6, %%xmm4 \n\t" /* mult by weighting factor */ - - " paddw %%xmm2, %%xmm1 \n\t" /* combine lumas */ - " paddusw %%xmm0, %%xmm1 \n\t" /* round */ - " psrlw $8, %%xmm1 \n\t" /* right adjust luma */ -#ifdef STREAMING_STORE_TMP - " movntdq %%xmm1, (%%"REGDI", %%"REGA", 2) \n\t" /* save lumas in our work area */ -#else - " movdqu %%xmm1, (%%"REGDI", %%"REGA", 2) \n\t" /* save lumas in our work area */ -#endif - " paddw %%xmm4, %%xmm3 \n\t" /* combine chromas */ - " paddusw %%xmm0, %%xmm3 \n\t" /* round */ - " psrlw $8, %%xmm3 \n\t" /* right adjust chroma */ - " packuswb %%xmm3, %%xmm3 \n\t" /* pack UV's into low dword */ - " movdq2q %%xmm3, %%mm1 \n\t" /* save in our work area */ -#ifdef STREAMING_STORE_TMP - " movntq %%mm1, (%%"REGB", %%"REGA") \n\t" /* save in our work area */ -#else - " movq %%mm1, (%%"REGB", %%"REGA") \n\t" /* save in our work area */ -#endif - " lea 8(%%"REGA"), %%"REGA" \n\t" - " decl %%"REGC" \n\t" - - " jg "vLoopSSE2_Fetch"b \n\t" /* if not on last one loop, prefetch */ - " jz "vLoopSSE2"b \n\t" /* or just loop, or not */ - - /* done with our SSE2 fortified loop but we may need to pick up the spare change */ -#ifdef STREAMING_STORE_TMP - " sfence \n\t" -#endif - " movl "_src_row_size", %%"REGC" \n\t" /* get count again */ - " andl $15, %%"REGC" \n\t" /* just need mod 16 */ - - " movq "_YMask", %%mm7 \n\t" /* useful luma mask constant - lazy dupl init */ - " movq "_vWeight1", %%mm5 \n\t" - " movq "_vWeight2", %%mm6 \n\t" - " movq "_FPround1", %%mm0 \n\t" /* useful rounding constant */ - - " shrl $3, %%"REGC" \n\t" /* 8 bytes at a time, any? */ - " jz "MoreSpareChange"f \n" /* n, did them all */ - - /* Let's check here to see if we are on a P2 or Athlon and can use SSEMMX instructions. - * This first loop is not the performance bottleneck anyway but it is trivial to tune - * using SSE if we have proper alignment. - */ - ""vMaybeSSEMMX": \n\t" - - " movq "_YMask", %%mm7 \n\t" /* useful luma mask constant - lazy dupl init */ - " movq "_vWeight1", %%mm5 \n\t" - " movq "_vWeight2", %%mm6 \n\t" - " movq "_FPround1", %%mm0 \n\t" /* useful rounding constant */ -#if !defined(__x86_64__) - " testl $1, "_SSEMMXenabledW" \n\t" /* MMXEXTsupported? */ - " jz "vLoopMMX"f \n\t" /* n, can't do anyway */ -#endif - " decl %%"REGC" \n" /* jigger loop ctr */ - - ".align 16 \n" - ""vLoopSSEMMX_Fetch": \n\t" -#ifdef PREFETCH - " prefetcht0 8(%%"REGSI", %%"REGA", 2) \n\t" - " prefetcht0 8(%%"REGD", %%"REGA", 2) \n" -#endif - ""vLoopSSEMMX": \n\t" - " movq (%%"REGSI", %%"REGA", 2), %%mm1 \n\t" /* top of 2 lines to interpolate */ - " movq (%%"REGD", %%"REGA", 2), %%mm2 \n\t" /* 2nd of 2 lines */ - - " movq %%mm1, %%mm3 \n\t" /* copy top bytes */ - " pand %%mm7, %%mm1 \n\t" /* keep only luma */ - " pxor %%mm1, %%mm3 \n\t" /* keep only chroma */ - " psrlw $8, %%mm3 \n\t" /* right just chroma */ - " pmullw %%mm5, %%mm1 \n\t" /* mult by weighting factor */ - " pmullw %%mm5, %%mm3 \n\t" /* mult by weighting factor */ - - " movq %%mm2, %%mm4 \n\t" /* copy 2nd bytes */ - " pand %%mm7, %%mm2 \n\t" /* keep only luma */ - " pxor %%mm2, %%mm4 \n\t" /* keep only chroma */ - " psrlw $8, %%mm4 \n\t" /* right just chroma */ - " pmullw %%mm6, %%mm2 \n\t" /* mult by weighting factor */ - " pmullw %%mm6, %%mm4 \n\t" /* mult by weighting factor */ - - " paddw %%mm2, %%mm1 \n\t" /* combine lumas */ - " paddusw %%mm0, %%mm1 \n\t" /* round */ - " psrlw $8, %%mm1 \n\t" /* right adjust luma */ -#ifdef STREAMING_STORE_TMP - " movntq %%mm1, (%%"REGDI", %%"REGA", 2) \n\t" /* save lumas in our work area */ -#else - " movq %%mm1, (%%"REGDI", %%"REGA", 2) \n\t" /* save lumas in our work area */ -#endif - " paddw %%mm4, %%mm3 \n\t" /* combine chromas */ - " paddusw %%mm0, %%mm3 \n\t" /* round */ - " psrlw $8, %%mm3 \n\t" /* right adjust chroma */ - " packuswb %%mm3, %%mm3 \n\t" /* pack UV's into low dword */ - " movd %%mm3, (%%"REGB", %%"REGA") \n\t" /* save in our work area */ - - " lea 4(%%"REGA"), %%"REGA" \n\t" - " decl %%"REGC" \n\t" - " jg "vLoopSSEMMX_Fetch"b \n\t" /* if not on last one loop, prefetch */ - " jz "vLoopSSEMMX"b \n\t" /* or just loop, or not */ -#ifdef STREAMING_STORE_TMP - " sfence \n\t" -#endif - " jmp "MoreSpareChange"f \n" /* all done with vertical */ - - ".align 16 \n" - ""vLoopMMX": \n\t" - - " movq (%%"REGSI", %%"REGA", 2), %%mm1 \n\t" /* top of 2 lines to interpolate */ - " movq (%%"REGD", %%"REGA", 2), %%mm2 \n\t" /* 2nd of 2 lines */ - - " movq %%mm1, %%mm3 \n\t" /* copy top bytes */ - " pand %%mm7, %%mm1 \n\t" /* keep only luma */ - " pxor %%mm1, %%mm3 \n\t" /* keep only chroma */ - " psrlw $8, %%mm3 \n\t" /* right just chroma */ - " pmullw %%mm5, %%mm1 \n\t" /* mult by weighting factor */ - " pmullw %%mm5, %%mm3 \n\t" /* mult by weighting factor */ - - " movq %%mm2, %%mm4 \n\t" /* copy 2nd bytes */ - " pand %%mm7, %%mm2 \n\t" /* keep only luma */ - " pxor %%mm2, %%mm4 \n\t" /* keep only chroma */ - " psrlw $8, %%mm4 \n\t" /* right just chroma */ - " pmullw %%mm6, %%mm2 \n\t" /* mult by weighting factor */ - " pmullw %%mm6, %%mm4 \n\t" /* mult by weighting factor */ - - " paddw %%mm2, %%mm1 \n\t" /* combine lumas */ - " paddusw %%mm0, %%mm1 \n\t" /* round */ - " psrlw $8, %%mm1 \n\t" /* right adjust luma */ - " movq %%mm1, (%%"REGDI", %%"REGA", 2) \n\t" /* save lumas in our work area */ - - " paddw %%mm4, %%mm3 \n\t" /* combine chromas */ - " paddusw %%mm0, %%mm3 \n\t" /* round */ - " psrlw $8, %%mm3 \n\t" /* right adjust chroma */ - " packuswb %%mm3, %%mm3 \n\t" /* pack UV's into low dword */ - " movd %%mm3, (%%"REGB", %%"REGA") \n\t" /* save in our work area */ - - " lea 4(%%"REGA"), %%"REGA" \n\t" - " loop "vLoopMMX"b \n" - - /* Add a little code here to check if we have 2 more pixels to do and, if so, make one - * more pass thru vLoopMMX. We were processing in multiples of 4 pixels and alway have - * an even number so there will never be more than 2 left. trbarry 7/29/2002 - */ - ""MoreSpareChange": \n\t" - - " cmpl "_EndOffset", %%"REGEA" \n\t" /* did we get them all */ - " jnl "DoHorizontal"f \n\t" /* yes, else have 2 left */ - " movl $1, %%"REGC" \n\t" /* jigger loop ct */ - " sub $2, %%"REGA" \n\t" /* back up 2 pixels (4 bytes, but eax carried as 1/2) */ - " jmp "vLoopMMX"b \n" - - /* We've taken care of the vertical scaling, now do horizontal */ - ""DoHorizontal": \n\t" - - " movq "_YMask", %%mm7 \n\t" /* useful 0U0U.. mask constant */ - " movq "_FPround2", %%mm6 \n\t" /* useful rounding constant, dwords */ - " mov "_pControl", %%"REGSI" \n\t" /* @ horiz control bytes */ - " movl "_row_size", %%"REGC" \n\t" - " shrl $2, %%"REGC" \n\t" /* bytes a time, 2 pixels */ - " mov "_vWorkYW", %%"REGD" \n\t" /* our luma data, as 0Y0Y 0Y0Y.. */ - " mov "_dstp", %%"REGDI" \n\t" /* the destination line */ - " mov "_vWorkUVW", %%"REGB" \n" /* chroma data, as UVUV UVUV... */ - - ".align 16 \n" - ""hLoopMMX": \n\t" - - /* x86_64: must use movl (accessing table of uint32's) */ - " movl 16(%%"REGSI"), %%"REGEA" \n\t" /* get data offset in pixels, 1st pixel pair */ - " movd (%%"REGD", %%"REGA", 2), %%mm0 \n\t" /* copy luma pair */ - " shr $1, %%"REGA" \n\t" /* div offset by 2 */ - " movd (%%"REGB", %%"REGA", 2), %%mm1 \n\t" /* copy UV pair VUVU */ - " psllw $8, %%mm1 \n\t" /* shift out V, keep 0000U0U0 */ - - /* we need to use both even and odd croma from same location - trb 9/2002 */ - " punpckldq (%%"REGB", %%"REGA", 2), %%mm1 \r\n" /* copy UV pair VUVU */ - " psrlw $8, %%mm1 \r\n" /* shift out U0, keep 0V0V 0U0U */ - " movl 20(%%"REGSI"), %%"REGEA" \r\n" /* get data offset in pixels, 2nd pixel pair */ - " punpckldq (%%"REGD", %%"REGA", 2), %%mm0 \r\n" /* copy luma pair */ - - " pmaddwd (%%"REGSI"), %%mm0 \r\n" /* mult and sum lumas by ctl weights */ - " paddusw %%mm6, %%mm0 \r\n" /* round */ - " psrlw $8, %%mm0 \r\n" /* right just 2 luma pixel value 000Y,000Y */ - - " pmaddwd 8(%%"REGSI"), %%mm1 \r\n" /* mult and sum chromas by ctl weights */ - " paddusw %%mm6, %%mm1 \r\n" /* round */ - " pslld $8, %%mm1 \r\n" /* shift into low bytes of different words */ - " pand %%mm7, %%mm1 \r\n" /* keep only 2 chroma values 0V00,0U00 */ - " por %%mm1, %%mm0 \r\n" /* combine luma and chroma, 0V0Y,0U0Y */ - " packuswb %%mm0, %%mm0 \r\n" /* pack all into low dword, xxxxVYUY */ - " movd %%mm0, (%%"REGDI") \n\t" /* done with 2 pixels */ - - " lea 24(%%"REGSI"), %%"REGSI" \n\t" /* bump to next control bytest */ - " lea 4(%%"REGDI"), %%"REGDI" \n\t" /* bump to next output pixel addr */ - - " loop "hLoopMMX"b \n\t" /* loop for more */ - - "emms \n\t" - /* done with one line */ - -#if !defined(__x86_64__) - "mov "_oldbx", %%"REGB" \n\t" -#endif - :: - "m" /*0*/(FPround1), - "m" /*1*/(vWeight1), - "m" /*2*/(vWeight2), - "m" /*3*/(YMask), - "m" /*4*/(src_row_size), - "m" /*5*/(EndOffset), - "m" /*6*/(pControl), - "m" /*7*/(row_size), - "m" /*8*/(vWorkYW), - "m" /*9*/(dstp), - "m" /*10*/(vWorkUVW), - "m" /*11*/(FPround2), - "m" /*12*/(srcp1), - "m" /*13*/(srcp2) -#if !defined(__x86_64__) - , - "m" /*14*/(oldbx), - "m" /*15*/(SSEMMXenabledW), - "m" /*16*/(SSE2enabledW) - : REGA, /*REGB,*/ REGC, REGD, REGSI, REGDI -#else - : REGA, REGB, REGC, REGD, REGSI, REGDI -#endif - ); - - dstp += dst_pitch; - } -#endif - return 0; -} - -static int do_warp_yv12(uint8_t *dst, const uint8_t * const src, - const int dst_pitch, const int src_pitch, - const int dst_width, const int dst_height, - const int src_width, const int src_height, - const int Interlaced, const uint32_t * const hControl, - const uint32_t * vOffsets, const uint32_t * vWeights, - uint32_t *vWorkY, int dst_start) -{ -#if defined(__i386__) || defined(__x86_64__) - sse2_t FPround1 = {uq:{UINT64_C(0x0080008000800080),UINT64_C(0x0080008000800080)}}; /* round words */ - sse2_t FPround2 = {uq:{UINT64_C(0x0000008000000080),UINT64_C(0x0000008000000080)}}; /* round dwords */ - sse2_t vWeight1; - sse2_t vWeight2; - - const uint32_t *pControl = &hControl[0]; - const uint32_t *vWorkYW = vWorkY; - const uint8_t *srcp = src; - const uint8_t *srcp1; - const uint8_t *srcp2; - uint8_t *dstp = dst + dst_pitch*dst_start; - - const uint32_t src_row_size = src_width; - const uint32_t row_size = dst_width; - -#if !defined(__x86_64__) - const int accel = xine_mm_accel(); - const uint32_t SSE2enabledW = !!(accel & MM_ACCEL_X86_SSE2); /* in local storage for asm */ - const uint32_t SSEMMXenabledW = !!(accel & MM_ACCEL_X86_MMXEXT); /* in local storage for asm */ - long int oldbx; -#endif - int y; - - /* Operation in sliced mode: - * - continue until required next source line is out of slice - * - return next output line - * - at next call, continue from next souce line - */ - - for (y = dst_start; y < dst_height; y++) { - if(vOffsets[y] >= src_height) { - /* slice completed */ - /*DBG("do_warp_yv12: max input height reached: need line %d, height %d\n -> Returning next output line: %d , start was %d\n", - (int)vOffsets[y], (int)src_height, (int)y, (int)dst_start);*/ - return y; - } - - vWeight1.ud[0] = vWeight1.ud[1] = vWeight1.ud[2] = vWeight1.ud[3] = - (256-vWeights[y]) << 16 | (256-vWeights[y]); - vWeight2.ud[0] = vWeight2.ud[1] = vWeight2.ud[2] = vWeight2.ud[3] = - vWeights[y] << 16 | vWeights[y]; - - srcp1 = srcp + vOffsets[y] * src_pitch; - - if (Interlaced) - srcp2 = (y < dst_height-2) ? srcp1 + 2 * src_pitch : srcp1; - else - srcp2 = (y < dst_height-1) ? srcp1 + src_pitch : srcp1; - - __asm__ __volatile__( - "movl "_src_row_size", %%"REGC" \n\t" - "shr $3, %%"REGC" \n\t" /* 8 bytes a time */ - "mov "_srcp1", %%"REGSI" \n\t" /* top of 2 src lines to get */ - "mov "_srcp2", %%"REGD" \n\t" /* next " */ - "mov "_vWorkYW", %%"REGDI" \n\t" /* luma work destination line */ - "xor %%"REGA", %%"REGA" \n\t" -#if !defined(__x86_64__) - /* Let's check here to see if we are on a P4 or higher and can use SSE2 instructions. - * This first loop is not the performance bottleneck anyway but it is trivial to tune - * using SSE2 if we have proper alignment. - */ - "testl $1, "_SSE2enabledW" \n\t" /* is SSE2 supported? */ - "jz "vMaybeSSEMMX"f \n\t" /* n, can't do anyway */ -#endif - "cmpl $2, %%"REGC" \n\t" /* we have at least 16 byts, 2 qwords? */ - "jl "vMaybeSSEMMX"f \n\t" /* n, don't bother */ - - "mov %%"REGSI", %%"REGB" \n\t" - "or %%"REGD", %%"REGB" \n\t" - "test $15, %%"REGB" \n\t" /* both src rows 16 byte aligned? */ - "jnz "vMaybeSSEMMX"f \n\t" /* n, don't use sse2 */ - - "shr $1, %%"REGC" \n\t" /* do 16 bytes at a time instead */ - "dec %%"REGC" \n\t" /* jigger loop ct */ - - "movdqa "_FPround1", %%xmm0 \n\t" - "movdqa "_vWeight1", %%xmm5 \n\t" - "movdqa "_vWeight2", %%xmm6 \n\t" - "pxor %%xmm7, %%xmm7 \n" - - ".align 16 \n" - ""vLoopSSE2_Fetch": \n\t" -#ifdef PREFETCH - " prefetcht0 16(%%"REGSI", %%"REGA", 2) \n\t" - " prefetcht0 16(%%"REGD", %%"REGA", 2) \n" -#endif - ""vLoopSSE2": \n\t" - /* we're already checked pointers to be on dqword aligned */ - " movdqa (%%"REGSI", %%"REGA"), %%xmm1 \n\t" /* top of 2 lines to interpolate */ - " movdqa (%%"REGD", %%"REGA"), %%xmm3 \n\t" /* 2nd of 2 lines */ - " movdqa %%xmm1, %%xmm2 \n\t" - " movdqa %%xmm3, %%xmm4 \n\t" - - " punpcklbw %%xmm7, %%xmm1 \n\t" /* make words */ - " punpckhbw %%xmm7, %%xmm2 \n\t" /* " */ - " punpcklbw %%xmm7, %%xmm3 \n\t" /* " */ - " punpckhbw %%xmm7, %%xmm4 \n\t" /* " */ - - " pmullw %%xmm5, %%xmm1 \n\t" /* mult by top weighting factor */ - " pmullw %%xmm5, %%xmm2 \n\t" /* " */ - " pmullw %%xmm6, %%xmm3 \n\t" /* mult by bot weighting factor */ - " pmullw %%xmm6, %%xmm4 \n\t" /* " */ - - " paddw %%xmm3, %%xmm1 \n\t" /* combine lumas low */ - " paddw %%xmm4, %%xmm2 \n\t" /* combine lumas high */ - - " paddusw %%xmm0, %%xmm1 \n\t" /* round */ - " paddusw %%xmm0, %%xmm2 \n\t" /* round */ - - " psrlw $8, %%xmm1 \n\t" /* right adjust luma */ - " psrlw $8, %%xmm2 \n\t" /* right adjust luma */ - - " packuswb %%xmm2, %%xmm1 \n\t" /* pack words to our 16 byte answer */ -#ifdef STREAMING_STORE_TMP - " movntdq %%xmm1, (%%"REGDI", %%"REGA") \n\t" /* save lumas in our work area */ -#else - " movdqu %%xmm1, (%%"REGDI", %%"REGA") \n\t" /* save lumas in our work area */ -#endif - " lea 16(%%"REGA"), %%"REGA" \n\t" - " decl %%"REGC" \n\t" - - " jg "vLoopSSE2_Fetch"b \n\t" /* if not on last one loop, prefetch */ - " jz "vLoopSSE2"b \n\t" /* or just loop, or not */ - - /* done with our SSE2 fortified loop but we may need to pick up the spare change */ -#ifdef STREAMING_STORE_TMP - " sfence \n\t" -#endif - " movl "_src_row_size", %%"REGC" \n\t" /* get count again */ - " andl $15, %%"REGC" \n\t" /* just need mod 16 */ - " movq "_vWeight1", %%mm5 \n\t" - " movq "_vWeight2", %%mm6 \n\t" - " movq "_FPround1", %%mm0 \n\t" /* useful rounding constant */ - - " shrl $3, %%"REGC" \n\t" /* 8 bytes at a time, any? */ - " jz "MoreSpareChange"f \n" /* n, did them all */ - - /* Let's check here to see if we are on a P2 or Athlon and can use SSEMMX instructions. - * This first loop is not the performance bottleneck anyway but it is trivial to tune - * using SSE if we have proper alignment. - */ - ""vMaybeSSEMMX": \n\t" - - " movq "_vWeight1", %%mm5 \n\t" - " movq "_vWeight2", %%mm6 \n\t" - " movq "_FPround1", %%mm0 \n\t" /* useful rounding constant */ - " pxor %%mm7, %%mm7 \n\t" -#if !defined(__x86_64__) - " testl $1, "_SSEMMXenabledW" \n\t"/* MMXEXTsupported? */ - " jz "vLoopMMX"f \n\t" /* n, can't do anyway */ -#endif - " decl %%"REGC" \n" /* jigger loop ctr */ - - ".align 16 \n" - ""vLoopSSEMMX_Fetch": \n\t" -#ifdef PREFETCH - " prefetcht0 8(%%"REGSI", %%"REGA") \n\t" - " prefetcht0 8(%%"REGD", %%"REGA") \n" -#endif - ""vLoopSSEMMX": \n\t" - - " movq (%%"REGSI", %%"REGA"), %%mm1 \n\t" /* top of 2 lines to interpolate */ - " movq (%%"REGD", %%"REGA"), %%mm3 \n\t" /* 2nd of 2 lines */ - - " movq %%mm1, %%mm2 \n\t" - " movq %%mm3, %%mm4 \n\t" - - " punpcklbw %%mm7, %%mm1 \n\t" /* make words */ - " punpckhbw %%mm7, %%mm2 \n\t" /* " */ - " punpcklbw %%mm7, %%mm3 \n\t" /* " */ - " punpckhbw %%mm7, %%mm4 \n\t" /* " */ - - " pmullw %%mm5, %%mm1 \n\t" /* mult by top weighting factor */ - " pmullw %%mm5, %%mm2 \n\t" /* " */ - " pmullw %%mm6, %%mm3 \n\t" /* mult by bot weighting factor */ - " pmullw %%mm6, %%mm4 \n\t" /* " */ - - " paddw %%mm3, %%mm1 \n\t" /* combine lumas low */ - " paddw %%mm4, %%mm2 \n\t" /* combine lumas high */ - - " paddusw %%mm0, %%mm1 \n\t" /* round */ - " paddusw %%mm0, %%mm2 \n\t" /* round */ - - " psrlw $8, %%mm1 \n\t" /* right adjust luma */ - " psrlw $8, %%mm2 \n\t" /* right adjust luma */ - - " packuswb %%mm2, %%mm1 \n\t" /* pack words to our 8 byte answer */ -#ifdef STREAMING_STORE_TMP - " movntq %%mm1, (%%"REGDI", %%"REGA") \n\t" /* save lumas in our work area */ -#else - " movq %%mm1, (%%"REGDI", %%"REGA") \n\t" /* save lumas in our work area */ -#endif - " lea 8(%%"REGA"), %%"REGA" \n\t" - " decl %%"REGC" \n\t" - - " jg "vLoopSSEMMX_Fetch"b \n\t" /* if not on last one loop, prefetch */ - " jz "vLoopSSEMMX"b \n\t" /* or just loop, or not */ -#ifdef STREAMING_STORE_TMP - " sfence \n\t" -#endif - " jmp "MoreSpareChange"f \n" /* all done with vertical */ - - ".align 16 \n" - ""vLoopMMX": \n\t" - - " movq (%%"REGSI", %%"REGA"), %%mm1 \n\t" /* top of 2 lines to interpolate */ - " movq (%%"REGD", %%"REGA"), %%mm3 \n\t" /* 2nd of 2 lines */ - - " movq %%mm1, %%mm2 \n\t" - " movq %%mm3, %%mm4 \n\t" - - " punpcklbw %%mm7, %%mm1 \n\t" /* make words */ - " punpckhbw %%mm7, %%mm2 \n\t" /* " */ - " punpcklbw %%mm7, %%mm3 \n\t" /* " */ - " punpckhbw %%mm7, %%mm4 \n\t" /* " */ - - " pmullw %%mm5, %%mm1 \n\t" /* mult by top weighting factor */ - " pmullw %%mm5, %%mm2 \n\t" /* " */ - " pmullw %%mm6, %%mm3 \n\t" /* mult by bot weighting factor */ - " pmullw %%mm6, %%mm4 \n\t" /* " */ - - " paddw %%mm3, %%mm1 \n\t" /* combine lumas low */ - " paddw %%mm4, %%mm2 \n\t" /* combine lumas high */ - - " paddusw %%mm0, %%mm1 \n\t" /* round */ - " paddusw %%mm0, %%mm2 \n\t" /* round */ - - " psrlw $8, %%mm1 \n\t" /* right adjust luma */ - " psrlw $8, %%mm2 \n\t" /* right adjust luma */ - - " packuswb %%mm2, %%mm1 \n\t" /* pack words to our 8 byte answer */ - " movq %%mm1, (%%"REGDI", %%"REGA") \n\t" /* save lumas in our work area */ - - " lea 8(%%"REGA"), %%"REGA" \n\t" - " loop "vLoopMMX"b \n" - - /* Add a little code here to check if we have more pixels to do and, if so, make one - * more pass thru vLoopMMX. We were processing in multiples of 8 pixels and alway have - * an even number so there will never be more than 7 left. - */ - ""MoreSpareChange": \n\t" - - " cmpl "_src_row_size", %%"REGEA" \n\t" /* did we get them all */ - " jnl "DoHorizontal"f \n\t" /* yes, else have 2 left */ - " movl $1, %%"REGC" \n\t" /* jigger loop ct */ - " movl "_src_row_size", %%"REGEA" \n\t" - " sub $8, %%"REGA" \n\t" /* back up to last 8 pixels */ - " jmp "vLoopMMX"b \n" - - /* We've taken care of the vertical scaling, now do horizontal */ - ""DoHorizontal": \n\t" - " pxor %%mm7, %%mm7 \n\t" - " movq "_FPround2", %%mm6 \n\t" /* useful rounding constant, dwords */ - " mov "_pControl", %%"REGSI" \n\t" /* @ horiz control bytes */ - " movl "_row_size", %%"REGC" \n\t" - " shrl $2, %%"REGC" \n\t" /* 4 bytes a time, 4 pixels */ - " mov "_vWorkYW", %%"REGD" \n\t" /* our luma data, as 0Y0Y 0Y0Y.. */ - " mov "_dstp", %%"REGDI" \n\t" /* the destination line */ -#if !defined(__x86_64__) - " testl $1, "_SSEMMXenabledW" \n\t" /* MMXEXTsupported? */ - " jz "hLoopMMX"f \n\t" /* n, can't do anyway */ -#endif - /* With SSE support we will make 8 pixels (from 8 pairs) at a time */ - " shrl $1, %%"REGC" \n\t" /* 8 bytes a time instead of 4 */ - " jz "LessThan8"f \n" - - ".align 16 \n" - ""hLoopMMXSSE": \n\t" - - - /* handle first 2 pixels */ - /* phi: must use movl here (x86_64, reading from table of uint_32's) */ - " movl 16(%%"REGSI"), %%"REGEA" \n\t" /* get data offset in pixels, 1st pixel pair */ - " movl 20(%%"REGSI"), %%"REGEB" \r\n" /* get data offset in pixels, 2nd pixel pair */ - - " movd (%%"REGD", %%"REGA"), %%mm0 \n\t" /* copy luma pair 0000xxYY */ - " punpcklwd (%%"REGD", %%"REGB"), %%mm0 \r\n" /* 2nd luma pair, now xxxxYYYY */ - " punpcklbw %%mm7, %%mm0 \n\t" /* make words out of bytes, 0Y0Y0Y0Y */ - " movl 16+24(%%"REGSI"), %%"REGEA" \n\t" /* get data offset in pixels, 3st pixel pair */ - " movl 20+24(%%"REGSI"), %%"REGEB" \r\n" /* get data offset in pixels, 4nd pixel pair */ - " pmaddwd (%%"REGSI"), %%mm0 \n\t" /* mult and sum lumas by ctl weights */ - " paddusw %%mm6, %%mm0 \n\t" /* round */ - " psrlw $8, %%mm0 \n\t" /* right just 4 luma pixel value 0Y0Y0Y0Y */ - - /* handle 3rd and 4th pixel pairs */ - " movd (%%"REGD", %%"REGA"), %%mm1 \n\t" /* copy luma pair 0000xxYY */ - " punpcklwd (%%"REGD", %%"REGB"), %%mm1 \r\n" /* 2nd luma pair, now xxxxYYYY */ - " punpcklbw %%mm7, %%mm1 \n\t" /* make words out of bytes, 0Y0Y0Y0Y */ - " movl 16+48(%%"REGSI"), %%"REGEA" \n\t" /* get data offset in pixels, 5st pixel pair */ - " movl 20+48(%%"REGSI"), %%"REGEB" \r\n" /* get data offset in pixels, 6nd pixel pair */ - " pmaddwd 24(%%"REGSI"), %%mm1 \n\t" /* mult and sum lumas by ctl weights */ - " paddusw %%mm6, %%mm1 \n\t" /* round */ - " psrlw $8, %%mm1 \n\t" /* right just 4 luma pixel value 0Y0Y0Y0Y */ - - /* handle 5th and 6th pixel pairs */ - " movd (%%"REGD", %%"REGA"), %%mm2 \n\t" /* copy luma pair 0000xxYY */ - " punpcklwd (%%"REGD", %%"REGB"), %%mm2 \r\n" /* 2nd luma pair, now xxxxYYYY */ - " punpcklbw %%mm7, %%mm2 \n\t" /* make words out of bytes, 0Y0Y0Y0Y */ - " movl 16+72(%%"REGSI"), %%"REGEA" \n\t" /* get data offset in pixels, 7st pixel pair */ - " movl 20+72(%%"REGSI"), %%"REGEB" \r\n" /* get data offset in pixels, 8nd pixel pair */ - " pmaddwd 48(%%"REGSI"), %%mm2 \n\t" /* mult and sum lumas by ctl weights */ - " paddusw %%mm6, %%mm2 \n\t" /* round */ - " psrlw $8, %%mm2 \n\t" /* right just 4 luma pixel value 0Y0Y0Y0Y */ - - /* handle 7th and 8th pixel pairs */ - " movd (%%"REGD", %%"REGA"), %%mm3 \n\t" /* copy luma pair 0000xxYY */ - " punpcklwd (%%"REGD", %%"REGB"), %%mm3 \r\n" /* 2nd luma pair, now xxxxYYYY */ - " punpcklbw %%mm7, %%mm3 \n\t" /* make words out of bytes, 0Y0Y0Y0Y */ - " pmaddwd 72(%%"REGSI"), %%mm3 \n\t" /* mult and sum lumas by ctl weights */ - " paddusw %%mm6, %%mm3 \n\t" /* round */ - " psrlw $8, %%mm3 \n\t" /* right just 4 luma pixel value 0Y0Y0Y0Y */ - - /* combine, store, and loop */ - " packuswb %%mm1, %%mm0 \n\t" /* pack into qword, 0Y0Y0Y0Y */ - " packuswb %%mm3, %%mm2 \n\t" /* pack into qword, 0Y0Y0Y0Y */ - " packuswb %%mm2, %%mm0 \n\t" /* and again into YYYYYYYY */ -#ifdef STREAMING_STORE - " movntq %%mm0, (%%"REGDI") \n\t" /* done with 4 pixels */ -#else - " movq %%mm0, (%%"REGDI") \n\t" /* done with 4 pixels */ -#endif - - " lea 96(%%"REGSI"), %%"REGSI" \n\t" - " lea 8(%%"REGDI"), %%"REGDI" \n\t" - " decl %%"REGC" \n\t" - " jg "hLoopMMXSSE"b \n\t" /* loop for more */ -#ifdef STREAMING_STORE - " sfence \n" -#endif - ""LessThan8": \n\t" - " movl "_row_size", %%"REGC" \n\t" - " andl $7, %%"REGC" \n\t" /* we have done all but maybe this */ - " shrl $2, %%"REGC" \n\t" /* now do only 4 bytes at a time */ - " jz "LessThan4"f \n" - - ".align 16 \n" - ""hLoopMMX": \n\t" - - /* handle first 2 pixels */ - " movl 16(%%"REGSI"), %%"REGEA" \n\t" /* get data offset in pixels, 1st pixel pair */ - " movl 20(%%"REGSI"), %%"REGEB" \r\n" /* get data offset in pixels, 2nd pixel pair */ - " movd (%%"REGD", %%"REGA"), %%mm0 \n\t" /* copy luma pair 0000xxYY */ - " punpcklwd (%%"REGD", %%"REGB"), %%mm0 \r\n" /* 2nd luma pair, now xxxxYYYY */ - " punpcklbw %%mm7, %%mm0 \n\t" /* make words out of bytes, 0Y0Y0Y0Y */ - " movl 16+24(%%"REGSI"), %%"REGEA" \n\t" /* get data offset in pixels, 3st pixel pair */ - " movl 20+24(%%"REGSI"), %%"REGEB" \r\n" /* get data offset in pixels, 4nd pixel pair */ - " pmaddwd (%%"REGSI"), %%mm0 \n\t" /* mult and sum lumas by ctl weights */ - " paddusw %%mm6, %%mm0 \n\t" /* round */ - " psrlw $8, %%mm0 \n\t" /* right just 4 luma pixel value 0Y0Y0Y0Y */ - - /* handle 3rd and 4th pixel pairs */ - " movd (%%"REGD", %%"REGA"), %%mm1 \n\t" /* copy luma pair 0000xxYY */ - " punpckldq (%%"REGD", %%"REGB"), %%mm1 \r\n" /* 2nd luma pair, now xxxxYYYY */ - " punpcklbw %%mm7, %%mm1 \n\t" /* make words out of bytes, 0Y0Y0Y0Y */ - " pmaddwd 24(%%"REGSI"), %%mm1 \n\t" /* mult and sum lumas by ctl weights */ - " paddusw %%mm6, %%mm1 \n\t" /* round */ - " psrlw $8, %%mm1 \n\t" /* right just 4 luma pixel value 0Y0Y0Y0Y */ - - /* combine, store, and loop */ - " packuswb %%mm1, %%mm0 \n\t" /* pack into qword, 0Y0Y0Y0Y */ - " packuswb %%mm7, %%mm0 \n\t" /* and again into 0000YYYY */ - " movd %%mm0, (%%"REGDI") \n\t" /* done with 4 pixels */ - " lea 48(%%"REGSI"), %%"REGSI" \n\t" - " lea 4(%%"REGDI"), %%"REGDI" \n\t" - - " loop "hLoopMMX"b \n" /* loop for more */ - - /* test to see if we have a mod 4 size row, if not then more spare change */ - ""LessThan4": \n\t" - " movl "_row_size", %%"REGC" \n\t" - " andl $3, %%"REGC" \n\t" /* remainder side mod 4 */ - " cmpl $2, %%"REGC" \n\t" - " jl "LastOne"f \n\t" /* none, none */ - - /* handle 2 more pixels */ - " movl 16(%%"REGSI"), %%"REGEA" \n\t" /* get data offset in pixels, 1st pixel pair */ - " movl 20(%%"REGSI"), %%"REGEB" \r\n" /* get data offset in pixels, 2nd pixel pair */ - " movd (%%"REGD", %%"REGA"), %%mm0 \n\t" /* copy luma pair 0000xxYY */ - " punpcklwd (%%"REGD", %%"REGB"), %%mm0 \r\n" /* 2nd luma pair, now xxxxYYYY */ - " punpcklbw %%mm7, %%mm0 \n\t" /* make words out of bytes, 0Y0Y0Y0Y */ - - " pmaddwd (%%"REGSI"), %%mm0 \n\t" /* mult and sum lumas by ctl weights */ - " paddusw %%mm6, %%mm0 \n\t" /* round */ - " psrlw $8, %%mm0 \n\t" /* right just 4 luma pixel value 0Y0Y0Y0Y */ - " packuswb %%mm7, %%mm0 \n\t" /* pack into qword, 00000Y0Y */ - " packuswb %%mm7, %%mm0 \n\t" /* and again into 000000YY */ - " movd %%mm0, (%%"REGDI") \n\t" /* store, we are guarrenteed room in buffer (8 byte mult) */ - " subl $2, %%"REGC" \n\t" - - " lea 24(%%"REGSI"), %%"REGSI" \n\t" /* bump to next control bytes */ - " lea 2(%%"REGDI"), %%"REGDI" \n" /* bump to next output pixel addr */ - - /* maybe one last pixel */ - ""LastOne": \n\t" - " cmpl $0, %%"REGC" \r\n" /* still more ? */ - " jz "AllDone"f \r\n" /* n, done */ - " movl 16(%%"REGSI"), %%"REGEA" \n\t" /* get data offset in pixels, 1st pixel pair */ - " movd (%%"REGD", %%"REGA"), %%mm0 \n\t" /* copy luma pair 0000xxYY */ - " punpcklbw %%mm7, %%mm0 \n\t" /* make words out of bytes, 0Y0Y0Y0Y */ - - " pmaddwd (%%"REGSI"), %%mm0 \n\t" /* mult and sum lumas by ctl weights */ - " paddusw %%mm6, %%mm0 \n\t" /* round */ - " psrlw $8, %%mm0 \n\t" /* right just 4 luma pixel value 0Y0Y0Y0Y */ - " movd %%mm0, %%"REGEA" \n\t" - " movb %%al, (%%"REGDI") \n" /* store last one */ - - ""AllDone": \n\t" - " emms \n\t" -#if !defined(__x86_64__) - "mov "_oldbx", %%"REGB" \n\t" -#endif - :: - "m" /*0*/(FPround1), - "m" /*1*/(vWeight1), - "m" /*2*/(vWeight2), - "m" /*3*/(y/*YMask[0]*/), - "m" /*4*/(src_row_size), - "m" /*5*/(y/*EndOffset*/), - "m" /*6*/(pControl), - "m" /*7*/(row_size), - "m" /*8*/(vWorkYW), - "m" /*9*/(dstp), - "m" /*10*/(y/*vWorkUVW*/), - "m" /*11*/(FPround2), - "m" /*12*/(srcp1), - "m" /*13*/(srcp2) -#if !defined(__x86_64__) - , - "m" /*14*/(oldbx), - "m" /*15*/(SSEMMXenabledW), - "m" /*16*/(SSE2enabledW) - : REGA, /*REGB,*/ REGC, REGD, REGSI, REGDI -#else - : REGA, REGB, REGC, REGD, REGSI, REGDI -#endif - ); - - dstp += dst_pitch; - } -#endif - return 0; -} - -/* - * tools - */ - -#ifndef ALIGN -# define ALIGN(b,p) ((void*)((((unsigned long)(p)) + (b)-1) & (~((b)-1)))) -#endif -#ifndef MIN -# define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif -#ifndef MAX -# define MAX(a,b) ((a) > (b) ? (a) : (b)) -#endif -#ifndef FABS -# define FABS(x) ((x) < 0.0 ? -(x) : (x)) -#endif - -/* - * xine plugin - */ - -#define PLUGIN_ID "warp" -#define PLUGIN_DESCR "(non-)linear software scaling post plugin"; -#define PLUGIN_T warp_plugin_t -/*#define POST_THREADS*/ -/*#define POST_SLICES*/ -#include "xine/post_util.h" - - -/* plugin class initialization function */ -void *warp_init_plugin(xine_t *xine, void *); - -/* plugin class functions */ -static post_plugin_t *open_plugin(post_class_t *class_gen, int inputs, - xine_audio_port_t **audio_target, - xine_video_port_t **video_target); - -/* plugin instance functions */ -static void warp_dispose(post_plugin_t *this_gen); - -/* vo_frame functions */ -static vo_frame_t *got_frame(vo_frame_t *frame); -static void draw_internal(vo_frame_t *frame, vo_frame_t *new_frame); - - -/* parameter functions */ -static xine_post_api_descr_t *warp_get_param_descr(void); -static int warp_set_parameters(xine_post_t *this_gen, void *param_gen); -static int warp_get_parameters(xine_post_t *this_gen, void *param_gen); -static char *warp_get_help(void); - - -typedef struct warp_parameters_s { - int output_width; - int output_height; - double output_aspect; - int no_downscaling; -} warp_parameters_t; - -START_PARAM_DESCR(warp_parameters_t) -PARAM_ITEM(POST_PARAM_TYPE_INT, output_width, NULL, 640, 1920, 0, - "output video width") -PARAM_ITEM(POST_PARAM_TYPE_INT, output_height, NULL, 480, 1080, 0, - "output video height") -PARAM_ITEM(POST_PARAM_TYPE_DOUBLE, output_aspect, NULL, 1, 3, 0, - "output video aspect ratio") -PARAM_ITEM(POST_PARAM_TYPE_BOOL, no_downscaling,NULL, 0, 1, 0, - "disable downscaling") -END_PARAM_DESCR(warp_param_descr) - - -typedef struct { - post_plugin_t post; - - xine_post_in_t parameter_input; - - /* User config (changes to actual config are delayed) */ - warp_parameters_t config; - - /* Current config */ - int enable; - int output_width; - int output_height; - double output_aspect; - double factor_x; - double factor_y; - - /* Last seen input frame */ - int input_width; - int input_height; - int input_format; - int input_interlaced; - double input_aspect; - - /* working buffers */ - uint32_t *vWorkY; - uint32_t *vWorkUV; - - /* scaling tables */ - uint32_t *hControl; - uint32_t *hControlUV; - uint32_t *vOffsets; - uint32_t *vOffsetsUV; - uint32_t *vWeights; - uint32_t *vWeightsUV; - - /* memory for work areas and scaling tables */ - void *pMem; - -} warp_plugin_t; - -/* - * - */ - -static void init_tables(warp_plugin_t *this) -{ -#define BP(x) ((uint8_t*)(x)) - /* allocate memory for scaling tables and workspace */ - free(this->pMem); - this->pMem = xine_xmalloc(this->input_width*3 + this->output_width*sizeof(uint32_t)*3*2 + - this->output_height*sizeof(uint32_t)*4 + 2*9*128); - - /* - aligned for P4 cache line */ - this->vWorkY = (uint32_t*)ALIGN(128, this->pMem); - this->vWorkUV = (uint32_t*)ALIGN(128, BP(this->vWorkY) + this->input_width*2 + 128); - this->hControl = (uint32_t*)ALIGN(128, BP(this->vWorkUV) + this->input_width + 128); - this->vOffsets = (uint32_t*)ALIGN(128, BP(this->hControl) + this->output_width * sizeof(uint32_t) * 3 + 128); - this->vWeights = (uint32_t*)ALIGN(128, BP(this->vOffsets) + this->output_height * sizeof(uint32_t) + 128); - - if (this->input_format == XINE_IMGFMT_YV12) { - this->vOffsetsUV = (uint32_t*)ALIGN(128, BP(this->vWeights) + this->output_height * sizeof(uint32_t) + 128); - this->vWeightsUV = (uint32_t*)ALIGN(128, BP(this->vOffsetsUV) + this->output_height * sizeof(uint32_t) + 128); - this->hControlUV = (uint32_t*)ALIGN(128, BP(this->vWeightsUV) + this->output_height * sizeof(uint32_t) + 128); - - init_tables_yv12(this->output_width, this->output_height, - this->input_width, this->input_height, - this->input_interlaced, this->factor_x, this->factor_y, - this->hControl, this->vOffsets, this->vWeights, - this->hControlUV, this->vOffsetsUV, this->vWeightsUV ); - - } else if (this->input_format == XINE_IMGFMT_YUY2) { - - init_tables_yuy2(this->output_width, this->output_height, - this->input_width, this->input_height, - this->input_interlaced, this->factor_x, this->factor_y, - this->hControl, this->vOffsets, this->vWeights ); - } -} - -static void calculate_factors(warp_plugin_t *this) -{ - /* try to guess amount to stretch/shrink */ - double adiff = this->input_aspect - this->output_aspect; - this->factor_x = 1.0; - this->factor_y = 1.0; - - if (adiff > 0.1) { - - if (adiff > 0.1 + ((16.0-12.0)/9.0)) { - /* >16:9 -> >4:3 */ - DBG("aspect ratio diff %1.3lf > 0 : too large !\n", adiff); - this->factor_x = 0.95; - this->factor_y = 1.15; - this->output_aspect += (adiff - 4.0/9.0); - DBG(" changing target ratio to %3.1lf\n", this->output_aspect); - } else { - /* 16:9 ... 12:9 -> 4:3 */ - DBG("aspect ratio diff %1.3lf > 0 : 16.9...12:9 -> 4:3\n", adiff); - this->factor_x = 1.0 - 0.05 * adiff * 9.0/4.0; - this->factor_y = 1.0 + 0.15 * adiff * 9.0/4.0; - } - - } else if (adiff < -0.1) { - - if(adiff < -0.1-((16.0-12.0)/9.0)) { - /* <4:3 -> <16:9 */ - DBG("aspect ratio diff %1.3lf > 0 : too large !\n", adiff); - this->factor_x = 1.05; - this->factor_y = 0.85; - this->output_aspect += (adiff + 4.0/9.0); - DBG(" changing target ratio to %3.1lf\n", this->output_aspect); - } else { - /* 4:3...16:9 -> 16:9 */ - DBG("aspect ratio diff %1.3lf < 0 : 4:3...16:9 -> 16:9\n", adiff); - this->factor_x = 1.0 + 0.05 * adiff * 9.0/4.0; - this->factor_y = 1.0 - 0.15 * adiff * 9.0/4.0; - } - - } else { - DBG("aspect ratio matches, no warp\n"); - this->factor_x = 1.0; - this->factor_y = 1.0; - } - - DBG("factor_x = %1.3lf factor_y = %1.3lf output ratio = %1.3lf\n", - this->factor_x, this->factor_y, this->output_aspect); -} - -/* - * - */ - -void *warp_init_plugin(xine_t *xine, void *data) -{ -#if !defined(__x86_64__) - /* Need at least MMX */ - if (!(xine_mm_accel() & MM_ACCEL_X86_MMX)) { - fprintf(stderr, "warp_init_plugin: ERROR: at least MMX required\n"); - return NULL; - } -#endif - - return init_plugin(xine, data); -} - -static post_plugin_t *open_plugin(post_class_t *class_gen, int inputs, - xine_audio_port_t **audio_target, - xine_video_port_t **video_target) -{ - warp_plugin_t *this = (warp_plugin_t *) xine_xmalloc(sizeof(warp_plugin_t)); - post_plugin_t *this_gen = (post_plugin_t *) this; - post_in_t *input; - post_out_t *output; - xine_post_in_t *input_param; - post_video_port_t *port; - - static xine_post_api_t post_api = - { warp_set_parameters, warp_get_parameters, warp_get_param_descr, warp_get_help }; - - if (!this || !video_target || !video_target[0]) { - free(this); - return NULL; - } - - _x_post_init(this_gen, 0, 1); - - port = _x_post_intercept_video_port(this_gen, video_target[0], &input, &output); - port->intercept_frame = intercept_frame_yuy; - port->new_frame->draw = post_draw; - input->xine_in.name = "video"; - output->xine_out.name = "video (scaled)"; - this_gen->xine_post.video_input[0] = &port->new_port; - - this_gen->dispose = warp_dispose; - - input_param = &this->parameter_input; - input_param->name = "parameters"; - input_param->type = XINE_POST_DATA_PARAMETERS; - input_param->data = &post_api; - xine_list_push_back(this_gen->input, input_param); - - this->config.output_aspect = 0.0; /* -> do not change aspect ratio */ - this->config.output_width = 0; /* -> do not change width */ - this->config.output_height = 0; /* -> do not change height */ - this->config.no_downscaling = 0; - - this->input_width = 0; /* not known yet, triggers initialization later */ - this->input_height = 0; - - return this_gen; -} - -static void warp_dispose(post_plugin_t *this_gen) -{ - if (_x_post_dispose(this_gen)) { - warp_plugin_t *this = (warp_plugin_t *) this_gen; - - DBG("dispose\n"); - - free(this->pMem); - free(this); - } -} - -static vo_frame_t *got_frame(vo_frame_t *frame) -{ - post_video_port_t *port = (post_video_port_t *)frame->port; - warp_plugin_t *this = (warp_plugin_t *)port->post; - double adiff = this->input_aspect - frame->ratio; - - if (this->input_width != frame->width || this->input_height != frame->height || - this->input_format != frame->format || FABS(adiff)>0.1 || - this->input_interlaced != !!(frame->flags & VO_INTERLACED_FLAG)) { - - DBG("detected frame format change: %dx%d -> %dx%d, interlaced %d->%d, aspect %1.3lf->%1.3lf, %s->%s\n", - this->input_width, this->input_height, frame->width, frame->height, - this->input_interlaced, !!(frame->flags & VO_INTERLACED_FLAG), - this->input_aspect, frame->ratio, - this->input_format==XINE_IMGFMT_YV12 ? "yv12":"yuy2", - frame->format==XINE_IMGFMT_YV12 ? "yv12":"yuy2" ); - - /* free tables and buffers */ - free(this->pMem); - this->pMem = NULL; - - /* remember frame properties to detect changes in video format */ - this->input_width = frame->width; - this->input_height = frame->height; - this->input_format = frame->format; - this->input_aspect = frame->ratio; - this->input_interlaced = !!(frame->flags & VO_INTERLACED_FLAG); - - /* re-configure target size and aspect ratio */ - this->output_aspect = this->config.output_aspect ?: frame->ratio; - if (!this->config.no_downscaling) { - this->output_width = this->config.output_width ?: frame->width; - this->output_height = this->config.output_height ?: frame->height; - } else { - this->output_width = MAX(this->config.output_width, frame->width); - this->output_height = MAX(this->config.output_height, frame->height); - } - - /* calculate warp function factors */ - calculate_factors(this); - - adiff = this->input_aspect - this->output_aspect; - if(this->output_width == frame->width && - this->output_height == frame->height && - adiff < 0.1 && - adiff > -0.1 ) { - this->enable = 0; - DBG("--> nothing to do, disabling processing for now"); - return NULL; - } - - this->enable = 1; - - init_tables(this); - } - - if (!this->enable) - return NULL; - - return port->original_port->get_frame(port->original_port, - this->output_width, this->output_height, - this->output_aspect, frame->format, - frame->flags | VO_BOTH_FIELDS); -} - -static void draw_internal(vo_frame_t *frame, vo_frame_t *new_frame) -{ - post_video_port_t *port = (post_video_port_t *)frame->port; - warp_plugin_t *this = (warp_plugin_t *)port->post; - int proc_height = frame->height; - - if (frame->format == XINE_IMGFMT_YV12) { - - do_warp_yv12(new_frame->base[0], frame->base[0], - new_frame->pitches[0], frame->pitches[0], - this->output_width, this->output_height, - frame->width, proc_height, - this->input_interlaced, - this->hControl, this->vOffsets, this->vWeights, - this->vWorkY, - 0); - proc_height /= 2; - do_warp_yv12(new_frame->base[1], frame->base[1], - new_frame->pitches[1], frame->pitches[1], - this->output_width/2, this->output_height/2, - frame->width/2, proc_height, - this->input_interlaced, - this->hControlUV, this->vOffsetsUV, this->vWeightsUV, - this->vWorkUV, - 0); - do_warp_yv12(new_frame->base[2], frame->base[2], - new_frame->pitches[2], frame->pitches[2], - this->output_width/2, this->output_height/2, - frame->width/2, proc_height, - this->input_interlaced, - this->hControlUV, this->vOffsetsUV, this->vWeightsUV, - this->vWorkUV, - 0); - - } else if (frame->format == XINE_IMGFMT_YUY2) { - do_warp_yuy2(new_frame->base[0], frame->base[0], - new_frame->pitches[0], frame->pitches[0], - this->output_width, this->output_height, - frame->width, proc_height, - this->input_interlaced, - this->hControl, this->vOffsets, this->vWeights, - this->vWorkY, this->vWorkUV, - 0); - } -} - -/* - * parameter functions - */ - -static xine_post_api_descr_t *warp_get_param_descr(void) -{ - return &warp_param_descr; -} - -static int warp_set_parameters(xine_post_t *this_gen, void *param_gen) -{ - warp_plugin_t *this = (warp_plugin_t *)this_gen; - warp_parameters_t *params = (warp_parameters_t *)param_gen; - - memcpy(&this->config, params, sizeof(warp_parameters_t)); - this->input_width = this->input_height = 0; - - if(this->config.output_aspect > 999) - this->config.output_aspect /= 1000.0; - - DBG("warp_set_parameters: " - "output_width=%d, output_height=%d, output_aspect=%4.3lf, no_downscaling=%d\n", - this->config.output_width, this->config.output_height, this->config.output_aspect, - this->config.no_downscaling); - - return 1; -} - -static int warp_get_parameters(xine_post_t *this_gen, void *param_gen) -{ - warp_plugin_t *this = (warp_plugin_t *)this_gen; - warp_parameters_t *params = (warp_parameters_t *)param_gen; - - DBG("warp_get_parameters\n"); - memcpy(params, &this->config, sizeof(warp_parameters_t)); - - return 1; -} - -static char *warp_get_help(void) { - return _( - "The warp plugin scales video to another resolution. " - "It supports non-linear stretching to change video aspect ratio. " - "\n" - "Parameters\n" - " output_width: Scale video to width\n" - " (0 -> do not change video width)\n" - " output_height: Scale video to height\n" - " (0 -> do not change video height)\n" - " output_aspect: Adjust aspect ratio using non-linear scaling\n" - " (0 -> do not change video aspect ratio)\n" - " no_downscaling: Do not downscale video\n" - "\n" - ); -} - - -/* - * plugin info - */ - -static post_info_t info = { XINE_POST_TYPE_VIDEO_FILTER }; - -const plugin_info_t xine_plugin_info[] __attribute__((visibility("default"))) = -{ - /* type, API, "name", version, special_info, init_function */ - { PLUGIN_POST, POST_PLUGIN_IFACE_VERSION, "warp", XINE_VERSION_CODE, &info, &warp_init_plugin }, - { PLUGIN_POST, POST_PLUGIN_IFACE_VERSION, "swscale", XINE_VERSION_CODE, &info, &warp_init_plugin }, - { PLUGIN_NONE, 0, "", 0, NULL, NULL } -}; diff --git a/xine_sxfe_frontend.c b/xine_sxfe_frontend.c deleted file mode 100644 index e576a903..00000000 --- a/xine_sxfe_frontend.c +++ /dev/null @@ -1,1495 +0,0 @@ -/* - * xine_sxfe_frontend.c: Simple front-end, X11 functions - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: xine_sxfe_frontend.c,v 1.41 2008-04-10 15:01:31 phintuka Exp $ - * - */ - -/*#define HAVE_XF86VIDMODE*/ - -#include <errno.h> -#include <inttypes.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <dlfcn.h> -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <sys/types.h> -#include <unistd.h> -#include <time.h> -#include <pthread.h> -#include <sched.h> -#include <poll.h> -#include <sys/ipc.h> -#include <sys/shm.h> - -#include <X11/Xlib.h> -#include <X11/Xatom.h> -#include <X11/keysym.h> -#include <X11/Xutil.h> -#include <X11/extensions/XShm.h> -#ifdef HAVE_XRENDER -# include <X11/extensions/Xrender.h> -#endif -#ifdef HAVE_XF86VIDMODE -# include <X11/extensions/xf86vmode.h> -#endif -#ifdef HAVE_XDPMS -# include <X11/extensions/dpms.h> -#endif -#ifdef HAVE_XV_FIELD_ORDER -# include <X11/extensions/Xvlib.h> -#endif - -#ifdef boolean -# define HAVE_BOOLEAN -#endif -#include <jpeglib.h> -#undef boolean - -/* framegrab ports */ -#define XINE_ENABLE_EXPERIMENTAL_FEATURES - -#include <xine.h> -#ifndef XINE_ENGINE_INTERNAL -# define XINE_ENGINE_INTERNAL -# include <xine/xine_internal.h> -# undef XINE_ENGINE_INTERNAL -#else -# include <xine/xine_internal.h> -#endif -#include <xine/xineutils.h> -#include <xine/input_plugin.h> -#include <xine/plugin_catalog.h> - -#include "xine_input_vdr.h" -#include "xine_osd_command.h" - -#include "xine_frontend.h" -#include "xine/post.h" - -#ifndef WIN_LAYER_NORMAL - #define WIN_LAYER_NORMAL 4 -#endif -#ifndef WIN_LAYER_ONTOP - #define WIN_LAYER_ONTOP 6 -#endif - -#define MWM_HINTS_DECORATIONS (1L << 1) -#define PROP_MWM_HINTS_ELEMENTS 5 -typedef struct _mwmhints { - uint32_t flags; - uint32_t functions; - uint32_t decorations; - int32_t input_mode; - uint32_t status; -} MWMHints; - -#ifdef HAVE_XRENDER -/* HUD Scaling */ -typedef struct _xrender_surf -{ - int w, h; - int depth; - Visual *vis; - Drawable draw; - Picture pic; - int allocated : 1; -} Xrender_Surf; -#endif /* HAVE_XRENDER */ - -/* - * data - */ - -typedef struct sxfe_s { - - /* function pointers */ - frontend_t fe; - void (*update_display_size)(frontend_t*); - - /* vdr */ - fe_keypress_f keypress; - - /* X11 */ - Display *display; - Window window[2]; - int screen; - int window_id; /* output to another window */ - int completion_event; -#ifdef HAVE_XF86VIDMODE - int XF86_modelines_count; - XF86VidModeModeInfo** XF86_modelines; -#endif -#ifdef HAVE_XDPMS - BOOL dpms_state; -#endif - - /* Atoms */ - Atom atom_wm_delete_window; - Atom atom_sxfe_interrupt; - Atom atom_wm_hints, atom_win_layer; - Atom atom_state, atom_state_add, atom_state_del; - Atom atom_state_above, atom_state_fullscreen, atom_state_on_top; - - /* xine stuff */ - xine_t *xine; - xine_stream_t *stream; - xine_stream_t *slave_stream; - input_plugin_t *input; - xine_video_port_t *video_port; - xine_video_port_t *video_port_none; - xine_audio_port_t *audio_port; - xine_audio_port_t *audio_port_none; - xine_event_queue_t *event_queue; - - post_plugins_t *postplugins; - - x11_visual_t vis; - int xine_visual_type; - - uint16_t pes_buffers; - - /* frontend */ - double display_ratio; - double video_aspect; - char *aspect_controller; - int xpos, ypos; - uint16_t video_width, video_height; - uint16_t width, height; - uint16_t origxpos, origypos; - uint16_t origwidth, origheight; - uint8_t aspect; - uint8_t cropping; - uint8_t scale_video; - uint8_t overscan; - uint8_t playback_finished; - uint8_t slave_playback_finished; - uint8_t fullscreen; - uint8_t vmode_switch; - uint8_t field_order; - uint8_t fullscreen_state_forced; - uint8_t stay_above; - uint8_t no_border; - uint8_t check_move; - - /* strings */ - char configfile[256]; - char modeline[256]; - - /* HUD stuff */ -#ifdef HAVE_XRENDER - uint8_t hud; - GC gc; - Window hud_window; - XImage *hud_img; - Visual *hud_vis; - XShmSegmentInfo hud_shminfo; - Xrender_Surf *surf_win; - Xrender_Surf *surf_img; - int osd_width; - int osd_height; - int osd_pad_x; - int osd_pad_y; - uint32_t* hud_img_mem; -#endif /* HAVE_XRENDER */ - -} fe_t, sxfe_t; - - -/* Common (non-X11/FB) frontend functions */ -#include "xine_frontend.c" - -#include "vdrlogo_32x32.c" - -#define DOUBLECLICK_TIME 500 // ms - -#define OSD_DEF_WIDTH 720 -#define OSD_DEF_HEIGHT 576 -#define HUD_MAX_WIDTH 1920 -#define HUD_MAX_HEIGHT 1080 - -static void fe_dest_size_cb (void *data, - int video_width, int video_height, double video_pixel_aspect, - int *dest_width, int *dest_height, double *dest_pixel_aspect) -{ - fe_t *this = (fe_t *)data; - - if (!this) - return; - - *dest_width = this->width; - *dest_height = this->height; - - *dest_pixel_aspect = fe_dest_pixel_aspect(this, video_pixel_aspect, - video_width, video_height); -} - -static void set_fullscreen_props(sxfe_t *this) -{ - XEvent ev; - - if(this->window_id > 0) - return; - - if(this->atom_state == None) { - this->atom_win_layer = XInternAtom(this->display, "_WIN_LAYER", False); - this->atom_state = XInternAtom(this->display, "_NET_WM_STATE", False); - this->atom_state_add = XInternAtom(this->display, "_NET_WM_STATE_ADD", False); - this->atom_state_del = XInternAtom(this->display, "_NET_WM_STATE_DEL", False); - this->atom_state_above = XInternAtom(this->display, "_NET_WM_STATE_ABOVE", False); - this->atom_state_fullscreen = XInternAtom(this->display, "_NET_WM_STATE_FULLSCREEN", False); - this->atom_state_on_top = XInternAtom(this->display, "_NET_WM_STATE_STAYS_ON_TOP", False); - } - - memset(&ev, 0, sizeof(ev)); - ev.type = ClientMessage; - ev.xclient.type = ClientMessage; - ev.xclient.message_type = this->atom_state; - ev.xclient.display = this->display; - ev.xclient.window = this->window[1]; - ev.xclient.format = 32; - ev.xclient.data.l[0] = 1; - /*ev.xclient.data.l[0] = this->atom_state_add;*/ - - /* _NET_WM_STATE_FULLSCREEN */ - XLockDisplay(this->display); - ev.xclient.data.l[1] = this->atom_state_fullscreen; - XSendEvent(this->display, DefaultRootWindow(this->display), False, - SubstructureNotifyMask|SubstructureRedirectMask, &ev); - XUnlockDisplay(this->display); - - /* _NET_WM_STATE_ABOVE */ - XLockDisplay(this->display); - ev.xclient.data.l[1] = this->atom_state_above; - XSendEvent(this->display, DefaultRootWindow(this->display), False, - SubstructureNotifyMask|SubstructureRedirectMask, &ev); - XUnlockDisplay(this->display); - - /* _NET_WM_STATE_ON_TOP */ - XLockDisplay(this->display); - ev.xclient.data.l[1] = this->atom_state_on_top; - XSendEvent(this->display, DefaultRootWindow(this->display), False, - SubstructureNotifyMask|SubstructureRedirectMask, &ev); - XUnlockDisplay(this->display); -} - -static void set_border(sxfe_t *this, int border) -{ - MWMHints mwmhints; - - if(this->window_id > 0) - return; - - this->no_border = border ? 0 : 1; - - /* Set/remove border */ - this->atom_wm_hints = XInternAtom(this->display, "_MOTIF_WM_HINTS", False); - mwmhints.flags = MWM_HINTS_DECORATIONS; - mwmhints.decorations = this->no_border ? 0 : 1; - XChangeProperty(this->display, this->window[0], this->atom_wm_hints, this->atom_wm_hints, 32, - PropModeReplace, (unsigned char *) &mwmhints, - PROP_MWM_HINTS_ELEMENTS); -} - -static void set_above(sxfe_t *this, int stay_above) -{ - XEvent ev; - long propvalue[1]; - - if(this->window_id > 0) - return; - - if(this->stay_above != stay_above) { -#ifdef FE_STANDALONE - char *name, *newname = NULL; - if(XFetchName(this->display, this->window[0], &name) && name) { - if(strstr(name, " (top)")) - *strstr(name, " (top)") = 0; - if(stay_above) - asprintf(&newname, "%s (top)", name); - XStoreName(this->display, this->window[0], newname ?: name); - XStoreName(this->display, this->window[1], newname ?: name); - XFree(name); - free(newname); - } else { - XStoreName(this->display, this->window[0], stay_above ? "VDR - (top)" : "VDR"); - } -#else - XStoreName(this->display, this->window[0], stay_above ? "Local VDR (top)" : "Local VDR"); -#endif - this->stay_above = stay_above; - } - - memset(&ev, 0, sizeof(ev)); - ev.type = ClientMessage; - ev.xclient.type = ClientMessage; - ev.xclient.message_type = this->atom_state; - ev.xclient.display = this->display; - ev.xclient.window = this->window[0]; - ev.xclient.format = 32; - ev.xclient.data.l[0] = stay_above ? 1:0; /*this->atom_state_add : this->atom_state_del;*/ - - /* _NET_WM_STATE_ABOVE */ - XLockDisplay(this->display); - ev.xclient.data.l[1] = this->atom_state_above; - XSendEvent(this->display, DefaultRootWindow(this->display), False, - SubstructureNotifyMask|SubstructureRedirectMask, &ev); - XUnlockDisplay(this->display); - - /* _NET_WM_STATE_ON_TOP */ - XLockDisplay(this->display); - ev.xclient.data.l[1] = this->atom_state_on_top; - XSendEvent(this->display, DefaultRootWindow(this->display), False, - SubstructureNotifyMask|SubstructureRedirectMask, &ev); - XUnlockDisplay(this->display); - - /* _NET_WM_STATE_STICKY */ - XLockDisplay(this->display); - ev.xclient.data.l[1] = XInternAtom(this->display, "_NET_WM_STATE_STICKY", False); - XSendEvent(this->display, DefaultRootWindow(this->display), False, - SubstructureNotifyMask|SubstructureRedirectMask, &ev); - XUnlockDisplay(this->display); - - /* _WIN_LAYER */ - propvalue[0] = stay_above ? WIN_LAYER_ONTOP : WIN_LAYER_NORMAL; - XLockDisplay(this->display); - XChangeProperty(this->display, this->window[0], XInternAtom(this->display, "_WIN_LAYER", False), - XA_CARDINAL, 32, PropModeReplace, (unsigned char *)propvalue, - 1); - XUnlockDisplay(this->display); - -#if 0 - /* sticky */ - memset(&ev, 0, sizeof(ev)); - ev.xclient.type = ClientMessage; - ev.xclient.message_type = XInternAtom(this->display, "_WIN_STATE", False); - ev.xclient.display = this->display; - ev.xclient.window = this->window[0]; - ev.xclient.format = 32; - ev.xclient.data.l[0] = (1<<0); - ev.xclient.data.l[1] = (stay_above?(1<<0):0); - XSendEvent(this->display, DefaultRootWindow(this->display), False, - SubstructureNotifyMask|SubstructureRedirectMask, &ev); -#endif -#if 0 - /* on top */ - memset(&ev, 0, sizeof(ev)); - ev.xclient.type = ClientMessage; - ev.xclient.message_type = XInternAtom(this->display, "_WIN_LAYER", False); - ev.xclient.display = this->display; - ev.xclient.window = this->window[0]; - ev.xclient.format = 32; - ev.xclient.data.l[0] = (stay_above?10:6); - XSendEvent(this->display, DefaultRootWindow(this->display), False, - SubstructureNotifyMask|SubstructureRedirectMask, &ev); -#endif -#if 0 - /* layer */ - XClientMessageEvent xev; - - memset(&xev, 0, sizeof(xev)); - xev.type = ClientMessage; - xev.display = this->display; - xev.window = this->window[0]; - xev.message_type = this->atom_win_layer; - xev.format = 32; - xev.data.l[0] = 10; - xev.data.l[1] = CurrentTime; - XSendEvent(this->display, DefaultRootWindow(this->display), False, - SubstructureNotifyMask, (XEvent *) & xev); - - XMapRaised(this->display, this->window[0]); -#endif -#if 0 - xine_port_send_gui_data(this->video_port, XINE_GUI_SEND_DRAWABLE_CHANGED, - (void*) this->window[this->fullscreen ? 1 : 0]); -#endif -} - -static void set_cursor(Display *dpy, Window win, const int enable) -{ - if(enable) - XDefineCursor(dpy, win, None); - else { - /* no cursor */ - static char bm_no_data[] = { 0,0,0,0, 0,0,0,0 }; - Pixmap bm_no; - Cursor no_ptr; - XColor black, dummy; - bm_no = XCreateBitmapFromData(dpy, win, bm_no_data, 8, 8); - XAllocNamedColor(dpy, DefaultColormapOfScreen(DefaultScreenOfDisplay(dpy)), - "black", &black, &dummy); - no_ptr = XCreatePixmapCursor(dpy, bm_no, bm_no, &black, &black, 0, 0); - XDefineCursor(dpy, win, None); - XDefineCursor(dpy, win, no_ptr); - } -} - -#ifdef HAVE_XRENDER -Xrender_Surf * xrender_surf_new(Display *dpy, Drawable draw, Visual *vis, int w, int h, int alpha) -{ - Xrender_Surf *rs; - XRenderPictFormat *fmt; - XRenderPictureAttributes att; - - rs = calloc(1, sizeof (Xrender_Surf)); - - if(alpha) - fmt = XRenderFindStandardFormat (dpy, PictStandardARGB32); - else - fmt = XRenderFindStandardFormat (dpy, PictStandardRGB24); - rs->w = w; - rs->h = h; - rs->depth = fmt->depth; - rs->vis = vis; - rs->draw = XCreatePixmap(dpy, draw, w, h, fmt->depth); - att.dither = 1; - att.component_alpha = 1; - att.repeat = 0; - rs->pic = XRenderCreatePicture(dpy, rs->draw, fmt, CPRepeat | CPDither | CPComponentAlpha, &att); - rs->allocated = 1; - return rs; -} - -void xrender_surf_blend(Display *dpy, Xrender_Surf *src, Xrender_Surf *dst, - int x, int y, int w, int h, XDouble scale_x, XDouble scale_y, int smooth) -{ - XTransform xf; - - if(!scale_x) - scale_x = 1; - if(!scale_y) - scale_y = 1; - - xf.matrix[0][0] = XDoubleToFixed(1 / scale_x); xf.matrix[0][1] = 0; xf.matrix[0][2] = 0; - xf.matrix[1][0] = 0; xf.matrix[1][1] = XDoubleToFixed(1 / scale_y); xf.matrix[1][2] = 0; - xf.matrix[2][0] = 0; xf.matrix[2][1] = 0; xf.matrix[2][2] = 65536; - if(smooth) - XRenderSetPictureFilter(dpy, src->pic, "bilinear", NULL, 0); - else - XRenderSetPictureFilter(dpy, src->pic, "nearest", NULL, 0); - XRenderSetPictureTransform(dpy, src->pic, &xf); - XRenderComposite(dpy, PictOpSrc, src->pic, None, dst->pic, - x * scale_x + 1, - y * scale_y + 1, - 0, 0, - x * scale_x, - y * scale_y, - w * scale_x + 1, - h * scale_y + 1); -} - -Xrender_Surf * xrender_surf_adopt(Display *dpy, Drawable draw, Visual *vis, int w, int h) -{ - Xrender_Surf *rs; - XRenderPictFormat *fmt; - XRenderPictureAttributes att; - - rs = calloc(1, sizeof(Xrender_Surf)); - - fmt = XRenderFindVisualFormat(dpy, vis); - rs->w = w; - rs->h = h; - rs->depth = fmt->depth; - rs->vis = vis; - rs->draw = draw; - att.dither = 1; - att.component_alpha = 1; - att.repeat = 0; - rs->pic = XRenderCreatePicture(dpy, rs->draw, fmt, CPRepeat | CPDither | CPComponentAlpha, &att); - rs->allocated = 0; - return rs; -} - -void xrender_surf_free(Display *dpy, Xrender_Surf *rs) -{ - if(rs->allocated) - XFreePixmap(dpy, rs->draw); - XRenderFreePicture(dpy, rs->pic); - free(rs); -} - -static Visual *find_argb_visual(Display *dpy, int scr) -{ - XVisualInfo *xvi, template; - int nvi, i; - XRenderPictFormat *format; - Visual *visual; - - template.screen = scr; - template.depth = 32; - template.class = TrueColor; - xvi = XGetVisualInfo(dpy, VisualScreenMask | VisualDepthMask | - VisualClassMask, &template, &nvi); - - if(!xvi) { - LOGERR("find_argb_visual: XGetVisualInfo failed (no xvi)"); - return 0; - } - - visual = 0; - for(i = 0; i < nvi; i++) { - LOGDBG("find_argb_visual: iteration %d of %d", i, nvi); - format = XRenderFindVisualFormat(dpy, xvi[i].visual); - if((format->type == PictTypeDirect) && format->direct.alphaMask) { - visual = xvi[i].visual; - break; - } - } - - XFree(xvi); - - if(!visual) - LOGERR("find_argb_visual: No visual found"); - - return visual; -} - -static void hud_fill_img_memory(uint32_t* dst, const struct osd_command_s *cmd) -{ - int i, pixelcounter = 0; - int idx = cmd->y * HUD_MAX_WIDTH + cmd->x; - - for(i = 0; i < cmd->num_rle; ++i) { - const uint8_t alpha = (cmd->palette + (cmd->data + i)->color)->alpha; - const uint8_t r = (cmd->palette + (cmd->data + i)->color)->r; - const uint8_t g = (cmd->palette + (cmd->data + i)->color)->g; - const uint8_t b = (cmd->palette + (cmd->data + i)->color)->b; - int j, finalcolor = 0; - finalcolor |= ((alpha << 24) & 0xFF000000); - finalcolor |= ((r << 16) & 0x00FF0000); - finalcolor |= ((g << 8) & 0x0000FF00); - finalcolor |= (b & 0x000000FF); - - for(j = 0; j < (cmd->data + i)->len; ++j) { - if(pixelcounter >= cmd->w) { - idx += HUD_MAX_WIDTH - pixelcounter; - pixelcounter = 0; - } - dst[idx++] = finalcolor; - ++pixelcounter; - } - } -} - -static int hud_osd_command(frontend_t *this_gen, struct osd_command_s *cmd) -{ - sxfe_t *this = (sxfe_t*)this_gen; - if(this && this->hud && cmd) { - XLockDisplay(this->display); - switch(cmd->cmd) { - case OSD_Nop: /* Do nothing ; used to initialize delay_ms counter */ - LOGDBG("HUD osd NOP"); - break; - - case OSD_Size: /* Set size of VDR OSD area */ - LOGDBG("HUD Set Size"); - this->osd_width = (cmd->w > 0) ? cmd->w : OSD_DEF_WIDTH; - this->osd_height = (cmd->h > 0) ? cmd->h : OSD_DEF_HEIGHT; - this->osd_pad_x = (this->osd_width != OSD_DEF_WIDTH) ? 96 : 0; - this->osd_pad_y = (this->osd_height != OSD_DEF_HEIGHT) ? 90 : 0; - break; - - case OSD_Set_RLE: /* Create/update OSD window. Data is rle-compressed. */ - LOGDBG("HUD Set RLE"); - if(this->completion_event != -1) { - hud_fill_img_memory((uint32_t*)(this->hud_img->data), cmd); - if(!cmd->scaling) { - /* Place image directly onto hud window */ - XShmPutImage(this->display, this->hud_window, this->gc, this->hud_img, - cmd->x + cmd->dirty_area.x1, cmd->y + cmd->dirty_area.y1, - cmd->x + cmd->dirty_area.x1, cmd->y + cmd->dirty_area.y1, - cmd->dirty_area.x2 - cmd->dirty_area.x1, - cmd->dirty_area.y2 - cmd->dirty_area.y1, - False); - } else { - /* Place image onto Xrender surface which will be blended onto hud window */ - XShmPutImage(this->display, this->surf_img->draw, this->gc, this->hud_img, - cmd->x + cmd->dirty_area.x1 - 1, cmd->y + cmd->dirty_area.y1 - 1, - cmd->x + cmd->dirty_area.x1 - 1, cmd->y + cmd->dirty_area.y1 - 1, - cmd->dirty_area.x2 - cmd->dirty_area.x1 + 2, - cmd->dirty_area.y2 - cmd->dirty_area.y1 + 2, - False); - xrender_surf_blend(this->display, this->surf_img, this->surf_win, - cmd->x + cmd->dirty_area.x1 - 1, cmd->y + cmd->dirty_area.y1 - 1, - cmd->dirty_area.x2 - cmd->dirty_area.x1 + 2, - cmd->dirty_area.y2 - cmd->dirty_area.y1 + 2, - (XDouble)(this->width) / (XDouble)(this->osd_width + this->osd_pad_x), - (XDouble)(this->height) / (XDouble)(this->osd_height + this->osd_pad_y), - (cmd->scaling & 2)); // HUD_SCALING_BILINEAR=2 - } - } else { - hud_fill_img_memory(this->hud_img_mem, cmd); - if(!cmd->scaling) { - /* Place image directly onto hud window (always unscaled) */ - XPutImage(this->display, this->hud_window, this->gc, this->hud_img, - cmd->x + cmd->dirty_area.x1, cmd->y + cmd->dirty_area.y1, - cmd->x + cmd->dirty_area.x1, cmd->y + cmd->dirty_area.y1, - cmd->dirty_area.x2 - cmd->dirty_area.x1, - cmd->dirty_area.y2 - cmd->dirty_area.y1); - } else { - /* Place image onto Xrender surface which will be blended onto hud window */ - XPutImage(this->display, this->surf_img->draw, this->gc, this->hud_img, - cmd->x + cmd->dirty_area.x1 - 1, cmd->y + cmd->dirty_area.y1 - 1, - cmd->x + cmd->dirty_area.x1 - 1, cmd->y + cmd->dirty_area.y1 - 1, - cmd->dirty_area.x2 - cmd->dirty_area.x1 + 2, - cmd->dirty_area.y2 - cmd->dirty_area.y1 + 2); - xrender_surf_blend(this->display, this->surf_img, this->surf_win, - cmd->x + cmd->dirty_area.x1 - 1, cmd->y + cmd->dirty_area.y1 - 1, - cmd->dirty_area.x2 - cmd->dirty_area.x1 + 2, - cmd->dirty_area.y2 - cmd->dirty_area.y1 + 2, - (XDouble)(this->width) / (XDouble)(this->osd_width + this->osd_pad_x), - (XDouble)(this->height) / (XDouble)(this->osd_height + this->osd_pad_y), - (cmd->scaling & 2)); // HUD_SCALING_BILINEAR=2 - } - } - break; - - case OSD_SetPalette: /* Modify palette of already created OSD window */ - LOGDBG("HUD osd SetPalette"); - break; - - case OSD_Move: /* Change x/y position of already created OSD window */ - LOGDBG("HUD osd Move"); - break; - - case OSD_Set_YUV: /* Create/update OSD window. Data is in YUV420 format. */ - LOGDBG("HUD osd set YUV"); - break; - - case OSD_Close: /* Close OSD window */ - LOGDBG("HUD osd Close"); - XSetForeground(this->display, this->gc, 0x00000000); - XFillRectangle(this->display, this->hud_window, this->gc, - 0, 0, this->width, this->height); - XFlush(this->display); - break; - - default: - LOGDBG("hud_osd_command: unknown osd command"); - break; - } - XUnlockDisplay(this->display); - } - return 1; -} - -static int hud_osd_open(frontend_t *this_gen) -{ - sxfe_t *this = (sxfe_t*)this_gen; - if(this && this->hud) { - int dummy; - - XLockDisplay(this->display); - - LOGDBG("opening HUD OSD window..."); - - if(!XRenderQueryExtension(this->display, &dummy, &dummy)) { - LOGMSG("hud_osd_open: ERROR: XRender extension not available."); - LOGMSG("XRender extension must be enabled in X configuration (xorg.conf etc.)"); - this->hud = 0; - XUnlockDisplay(this->display); - return 1; - } - - this->hud_vis = find_argb_visual(this->display, DefaultScreen(this->display)); - if(!this->hud_vis) { - LOGMSG("find_argb_visual() failed. HUD OSD disabled."); - this->hud = 0; - XUnlockDisplay(this->display); - return 1; - } - - Colormap hud_colormap = XCreateColormap(this->display, - RootWindow(this->display, DefaultScreen(this->display)), - this->hud_vis, AllocNone); - - XSetWindowAttributes attributes; - attributes.override_redirect = True; - attributes.background_pixel = 0x00000000; - attributes.border_pixel = 0; - attributes.colormap = hud_colormap; - attributes.backing_store = Always; - - this->hud_window = XCreateWindow(this->display, DefaultRootWindow(this->display), - this->xpos, this->ypos, - this->width, this->height, - 0, 32, InputOutput, this->hud_vis, - CWBackPixel | CWBorderPixel | - CWOverrideRedirect | CWColormap, - &attributes); - - XSelectInput(this->display, this->hud_window, - StructureNotifyMask | - ExposureMask | - KeyPressMask | - ButtonPressMask | - FocusChangeMask); - - XStoreName(this->display, this->hud_window, "HUD"); - this->gc = XCreateGC(this->display, this->hud_window, 0, NULL); - - if(this->completion_event != -1) { - this->hud_img = XShmCreateImage(this->display, this->hud_vis, 32, ZPixmap, NULL, &(this->hud_shminfo), - HUD_MAX_WIDTH, HUD_MAX_HEIGHT); - - this->hud_shminfo.shmid = shmget(IPC_PRIVATE, this->hud_img->bytes_per_line * this->hud_img->height, - IPC_CREAT | 0777); - - this->hud_shminfo.shmaddr = this->hud_img->data = shmat(this->hud_shminfo.shmid, 0, 0); - this->hud_shminfo.readOnly = True; - - XShmAttach(this->display, &(this->hud_shminfo)); - } else { - /* Fall-back to traditional memory */ - LOGMSG("hud_osd_open: XShm not available, falling back to normal (slow) memory"); - this->hud_img_mem = malloc(4 * HUD_MAX_WIDTH * HUD_MAX_HEIGHT); - this->hud_img = XCreateImage(this->display, this->hud_vis, 32, ZPixmap, 0, (char*)this->hud_img_mem, - HUD_MAX_WIDTH, HUD_MAX_HEIGHT, 32, 0); - } - - this->surf_win = xrender_surf_adopt(this->display, this->hud_window, this->hud_vis, HUD_MAX_WIDTH, HUD_MAX_HEIGHT); - this->surf_img = xrender_surf_new(this->display, this->hud_window, this->hud_vis, HUD_MAX_WIDTH, HUD_MAX_HEIGHT, 1); - - XUnlockDisplay(this->display); - -#ifndef FE_STANDALONE - this->fe.xine_osd_command = hud_osd_command; -#endif - } - return 1; -} - -static void hud_osd_close(frontend_t *this_gen) -{ - sxfe_t *this = (sxfe_t*)this_gen; - if(this && this->hud) { - XLockDisplay(this->display); - LOGDBG("closing hud window..."); - - if(this->completion_event != -1) { - XShmDetach(this->display, &(this->hud_shminfo)); - XDestroyImage(this->hud_img); - shmdt(this->hud_shminfo.shmaddr); - shmctl(this->hud_shminfo.shmid, IPC_RMID, 0); - } else - XDestroyImage(this->hud_img); - - if(this->surf_img) - xrender_surf_free(this->display, this->surf_img); - if(this->surf_win) - xrender_surf_free(this->display, this->surf_win); - - XDestroyWindow(this->display, this->hud_window); - XUnlockDisplay(this->display); - } -} -#endif /* HAVE_XRENDER */ - - -/* - * sxfe_display_open - * - * connect to X server, create windows - */ - -static int sxfe_display_open(frontend_t *this_gen, int width, int height, int fullscreen, int hud, - int modeswitch, const char *modeline, int aspect, - fe_keypress_f keyfunc, const char *video_port, - int scale_video, int field_order) -{ - sxfe_t *this = (sxfe_t*)this_gen; - - MWMHints mwmhints; - XSizeHints hint; - double res_h, res_v, aspect_diff; - - if(this->display) - this->fe.fe_display_close(this_gen); - - if(keyfunc) { - this->keypress = keyfunc; - this->keypress("XKeySym", ""); /* triggers learning mode */ - } - - LOGDBG("sxfe_display_open(width=%d, height=%d, fullscreen=%d, display=%s)", - width, height, fullscreen, video_port); - - if(hud) { -#ifdef HAVE_XRENDER - LOGDBG("sxfe_display_open: Enabling HUD OSD"); - this->hud = hud; - this->osd_width = OSD_DEF_WIDTH; - this->osd_height = OSD_DEF_HEIGHT; - this->osd_pad_x = 0; - this->osd_pad_y = 0; -#else - LOGMSG("sxfe_display_open: Application was compiled without XRender support. HUD OSD disabled."); -#endif - } - - this->xpos = 0; - this->ypos = 0; - this->origxpos = 0; - this->origypos = 0; - this->width = width; - this->height = height; - this->origwidth = width>0 ? width : OSD_DEF_WIDTH; - this->origheight = height>0 ? height : OSD_DEF_HEIGHT; - this->check_move = 0; - - this->fullscreen = fullscreen; - this->vmode_switch = modeswitch; - this->aspect = aspect; - this->cropping = 0; - this->field_order = field_order ? 1 : 0; - this->scale_video = scale_video; - this->overscan = 0; - this->fullscreen_state_forced = 0; - strn0cpy(this->modeline, modeline ? : "", sizeof(this->modeline)); - - /* - * init x11 stuff - */ - - if (!XInitThreads ()) { - LOGERR("sxfe_display_open: XInitThreads failed"); - free(this); - return 0; - } - - if(video_port && strlen(video_port)>2) { - if(!(this->display = XOpenDisplay(video_port))) - LOGERR("sxfe_display_open: failed to connect to X server (%s)", - video_port); - } - if(!this->display) { - if(NULL!=(video_port=getenv("DISPLAY")) && !(this->display = XOpenDisplay(video_port))) - LOGERR("sxfe_display_open: failed to connect to X server (%s)", - video_port); - } - if(!this->display) { - this->display = XOpenDisplay(NULL); - } - if(!this->display) { - if(!(this->display = XOpenDisplay(":0.0"))) - LOGERR("sxfe_display_open: failed to connect to X server (:0.0)"); - } - if(!this->display) { - if(!(this->display = XOpenDisplay("127.0.0.1:0.0"))) - LOGERR("sxfe_display_open: failed to connect to X server (127.0.0.1:0.0"); - } - if (!this->display) { - LOGERR("sxfe_display_open: failed to connect to X server."); - LOGMSG("If X server is running, try running \"xhost +\" in xterm window"); - return 0; - } - - XLockDisplay (this->display); - - this->screen = DefaultScreen(this->display); - - /* #warning sxfe_display_open: TODO: switch vmode */ - - /* completion event */ - if (XShmQueryExtension (this->display) == True) { - this->completion_event = XShmGetEventBase (this->display) + ShmCompletion; - } else { - this->completion_event = -1; - } - - if(fullscreen) { - this->width = DisplayWidth(this->display, this->screen); - this->height = DisplayHeight(this->display, this->screen); - } - - if(this->window_id > 0) { - LOGMSG("sxfe_diaplay_open(): Using X11 window %d for output", this->window_id); - this->window[0] = this->window[1] = (Window)this->window_id; - XUnmapWindow(this->display, this->window[0]); - } else { - /* create and display our video window */ - this->window[0] = XCreateSimpleWindow (this->display, - DefaultRootWindow(this->display), - this->xpos, this->ypos, - this->width, this->height, - 1, 0, 0); - this->window[1] = XCreateSimpleWindow(this->display, XDefaultRootWindow(this->display), - 0, 0, (DisplayWidth(this->display, this->screen)), - (DisplayHeight(this->display, this->screen)), 0, 0, 0); - } - - hint.flags = USSize | USPosition | PPosition | PSize; - hint.x = 0; - hint.y = 0; - hint.width = DisplayWidth(this->display, this->screen); - hint.height = DisplayHeight(this->display, this->screen); - XSetNormalHints(this->display, this->window[1], &hint); - - if(this->window_id <= 0) { - /* full-screen window */ - set_fullscreen_props(this); - - /* no border in fullscreen window */ - this->atom_wm_hints = XInternAtom(this->display, "_MOTIF_WM_HINTS", False); - mwmhints.flags = MWM_HINTS_DECORATIONS; - mwmhints.decorations = 0; - XChangeProperty(this->display, this->window[1], this->atom_wm_hints, this->atom_wm_hints, 32, - PropModeReplace, (unsigned char *) &mwmhints, - PROP_MWM_HINTS_ELEMENTS); - } - - /* Select input */ - XSelectInput (this->display, this->window[0], - StructureNotifyMask | - ExposureMask | - KeyPressMask | - ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | - FocusChangeMask); - XSelectInput (this->display, this->window[1], - StructureNotifyMask | - ExposureMask | - KeyPressMask | - ButtonPressMask | - FocusChangeMask); - - - if(this->window_id <= 0) { - /* Window name */ -#ifdef FE_STANDALONE - XStoreName(this->display, this->window[0], "VDR - "); - XStoreName(this->display, this->window[1], "VDR - "); -#else - XStoreName(this->display, this->window[0], "Local VDR"); - XStoreName(this->display, this->window[1], "Local VDR"); -#endif - - /* Icon */ - XChangeProperty(this->display, this->window[0], - XInternAtom(this->display, "_NET_WM_ICON", False), - XA_CARDINAL, 32, PropModeReplace, - (unsigned char *) &vdrlogo_32x32, - 2 + vdrlogo_32x32.width*vdrlogo_32x32.height); - } - - /* Map current window */ - XMapRaised (this->display, this->window[this->fullscreen ? 1 : 0]); - - /* determine display aspect ratio */ - res_h = (DisplayWidth (this->display, this->screen)*1000 - / DisplayWidthMM (this->display, this->screen)); - res_v = (DisplayHeight (this->display, this->screen)*1000 - / DisplayHeightMM (this->display, this->screen)); - this->display_ratio = res_v / res_h; - aspect_diff = this->display_ratio - 1.0; - if ((aspect_diff < 0.01) && (aspect_diff > -0.01)) { - this->display_ratio = 1.0; - } - LOGDBG("Display size : %d x %d mm", - DisplayWidthMM (this->display, this->screen), - DisplayHeightMM (this->display, this->screen)); - LOGDBG(" %d x %d pixels", - DisplayWidth (this->display, this->screen), - DisplayHeight (this->display, this->screen)); - LOGDBG(" %ddpi / %ddpi", - (int)(res_v/1000*25.4), (int)(res_h/1000*25.4)); - LOGDBG("Display ratio: %f/%f = %f", res_v, res_h, this->display_ratio); - - /* we want to get notified if user closes the window */ - this->atom_wm_delete_window = XInternAtom(this->display, "WM_DELETE_WINDOW", False); - XSetWMProtocols(this->display, this->window[this->fullscreen ? 1 : 0], &(this->atom_wm_delete_window), 1); - - if(this->window_id <= 0) - set_cursor(this->display, this->window[1], 0); - - XUnlockDisplay (this->display); - - /* No screen saver */ - /* #warning TODO: suspend --> activate blank screen saver / DPMS display off ? */ - XSetScreenSaver(this->display, 0, 0, DefaultBlanking, DefaultExposures); -#ifdef HAVE_XDPMS - { - int dpms_dummy; - if (DPMSQueryExtension(this->display, &dpms_dummy, &dpms_dummy) && DPMSCapable(this->display)) { - CARD16 dpms_level; - DPMSInfo(this->display, &dpms_level, &this->dpms_state); - DPMSDisable(this->display); - } else { - LOGMSG("sxfe_display_open: DPMS unavailable"); - } - } -#endif - - this->xine_visual_type = XINE_VISUAL_TYPE_X11; - this->vis.display = this->display; - this->vis.screen = this->screen; - this->vis.d = this->window[this->fullscreen ? 1 : 0]; - this->vis.dest_size_cb = fe_dest_size_cb; - this->vis.frame_output_cb = fe_frame_output_cb; - this->vis.user_data = this; - - this->atom_sxfe_interrupt = XInternAtom(this->display, "SXFE_INTERRUPT", False); - - set_fullscreen_props(this); - -#ifdef HAVE_XRENDER - return hud_osd_open(this_gen); -#else - return 1; -#endif -} - -/* - * sxfe_display_config - * - * configure windows - */ -static int sxfe_display_config(frontend_t *this_gen, - int width, int height, int fullscreen, - int modeswitch, const char *modeline, - int aspect, int scale_video, - int field_order) -{ - sxfe_t *this = (sxfe_t*)this_gen; - - if(this->fullscreen_state_forced) - fullscreen = this->fullscreen ? 1 : 0; - - if(!fullscreen && (this->width != width || this->height != height)) { - this->width = width; - this->height = height; - - XLockDisplay(this->display); - XResizeWindow(this->display, this->window[0], this->width, this->height); - XUnlockDisplay(this->display); - if(!fullscreen && !this->fullscreen) - xine_port_send_gui_data(this->video_port, XINE_GUI_SEND_DRAWABLE_CHANGED, - (void*) this->window[0]); - } - - if(fullscreen) { - this->width = DisplayWidth(this->display, this->screen); - this->height = DisplayHeight(this->display, this->screen); - } - - if(fullscreen != this->fullscreen) { - Window tmp_win; - XLockDisplay(this->display); - XUnmapWindow(this->display, this->window[this->fullscreen ? 1 : 0]); - this->fullscreen = fullscreen ? 1 : 0; - if(fullscreen) - set_fullscreen_props(this); - else - set_above(this, this->stay_above); - XMapRaised(this->display, this->window[this->fullscreen ? 1 : 0]); - if(!fullscreen) { - XResizeWindow(this->display, this->window[0], this->width, this->height); - XMoveWindow(this->display, this->window[0], this->xpos, this->ypos); - LOGDBG("sxfe_display_config: XMoveWindow called with x=%d and y=%d", - this->xpos, this->ypos); - this->check_move = 1; - set_above(this, this->stay_above); - } else { - set_fullscreen_props(this); - } - XSync(this->display, False); - XTranslateCoordinates(this->display, this->window[this->fullscreen ? 1 : 0], - DefaultRootWindow(this->display), - 0, 0, &this->xpos, &this->ypos, &tmp_win); - XUnlockDisplay(this->display); - xine_port_send_gui_data(this->video_port, XINE_GUI_SEND_DRAWABLE_CHANGED, - (void*) this->window[this->fullscreen ? 1 : 0]); - } - - if(!modeswitch && strcmp(modeline, this->modeline)) { - strn0cpy(this->modeline, modeline, sizeof(this->modeline)); - /* #warning TODO - switch vmode */ - } - - this->vmode_switch = modeswitch; - this->aspect = aspect; - this->scale_video = scale_video; -#ifdef HAVE_XV_FIELD_ORDER - if(this->field_order != field_order) { - if(XInternAtom(this->display, "XV_SWAP_FIELDS", True) != None) - XvSetPortAttribute (this->display, 53, - XInternAtom (this->display, "XV_SWAP_FIELDS", False), - field_order); - } -#endif - this->field_order = field_order ? 1 : 0; - - return 1; -} - -static void sxfe_toggle_fullscreen(sxfe_t *this) -{ - int force = this->fullscreen_state_forced; - this->fullscreen_state_forced = 0; - - if(!this->fullscreen) { - this->origwidth = this->width; - this->origheight = this->height; - this->origxpos = this->xpos; - this->origypos = this->ypos; - } else { - this->xpos = this->origxpos; - this->ypos = this->origypos; - } - - this->fe.fe_display_config((frontend_t*)this, this->origwidth, this->origheight, - this->fullscreen ? 0 : 1, - this->vmode_switch, this->modeline, - this->aspect, this->scale_video, this->field_order); - - this->fullscreen_state_forced = !force; -} - -/* - * X event loop - */ - -static void sxfe_interrupt(frontend_t *this_gen) -{ - sxfe_t *this = (sxfe_t*)this_gen; - XClientMessageEvent ev2; - - ev2.type = ClientMessage; - ev2.display = this->display; - ev2.window = this->window[this->fullscreen ? 1 : 0]; - ev2.message_type = this->atom_sxfe_interrupt; - ev2.format = 32; - - if(!XSendEvent(ev2.display, ev2.window, TRUE, /*KeyPressMask*/0, (XEvent *)&ev2)) - LOGERR("sxfe_interrupt: XSendEvent(ClientMessage) FAILED\n"); - - XFlush(this->display); -} - -static int sxfe_run(frontend_t *this_gen) -{ - sxfe_t *this = (sxfe_t*)this_gen; - static int dragging = 0, drx = 0, dry = 0; - - int keep_going = 1; - XEvent event; - - /* poll X server (connection socket). - (XNextEvent will block if no events are queued). - We want to use timeout, blocking for long time usually causes vdr - watchdog to emergency exit ... */ - if (! XPending(this->display)) { - struct pollfd pfd[2]; - pfd[0].fd = ConnectionNumber(this->display); - pfd[0].events = POLLIN; - if(poll(pfd, 1, 50) < 1 || !(pfd[0].revents & POLLIN)) { - return 1; - } - } - - while(keep_going && XPending(this->display) > 0) { - - XNextEvent (this->display, &event); - - switch (event.type) { - case Expose: - if (event.xexpose.count == 0) - xine_port_send_gui_data (this->video_port, XINE_GUI_SEND_EXPOSE_EVENT, &event); - break; - - case ConfigureNotify: - { - XConfigureEvent *cev = (XConfigureEvent *) &event; - Window tmp_win; - - /* Move and resize HUD along with main or fullscreen window */ -#ifdef HAVE_XRENDER - if(this->hud) { - if(cev->window == this->window[0]) { - int hud_x, hud_y; - XLockDisplay(cev->display); - XTranslateCoordinates(this->display, this->window[0], - DefaultRootWindow(this->display), - 0, 0, &hud_x, &hud_y, &tmp_win); - XResizeWindow(this->display, this->hud_window, cev->width, cev->height); - XMoveWindow(this->display, this->hud_window, hud_x, hud_y); - set_cursor(this->display, this->hud_window, 1); - XUnlockDisplay(cev->display); - } else if(cev->window == this->window[1]) { - XLockDisplay(cev->display); - XResizeWindow(this->display, this->hud_window, cev->width, cev->height); - XMoveWindow(this->display, this->hud_window, 0, 0); - set_cursor(this->display, this->hud_window, 0); - XUnlockDisplay(cev->display); - } - } -#endif - this->width = cev->width; - this->height = cev->height; - - if(this->window[0] == cev->window && this->check_move) { - LOGDBG("ConfigureNotify reveived with x=%d, y=%d, check_move=%d", - cev->x, cev->y, this->check_move); - this->check_move = 0; - if(this->xpos != cev->x && this->ypos != cev->y) - XMoveWindow(this->display, this->window[0], cev->x, cev->y); - } - - if ((cev->x == 0) && (cev->y == 0)) { - XLockDisplay(cev->display); - if(!this->fullscreen) - XTranslateCoordinates(cev->display, cev->window, - DefaultRootWindow(cev->display), - 0, 0, &this->xpos, &this->ypos, &tmp_win); - XUnlockDisplay(cev->display); - } else { - if(!this->fullscreen) { - this->xpos = cev->x; - this->ypos = cev->y; - } - } - break; - } - -#ifdef HAVE_XRENDER - case FocusIn: - { - if(this->hud) { - XFocusChangeEvent *fev = (XFocusChangeEvent *) &event; - /* Show HUD again if sxfe window receives focus */ - if(fev->window == this->window[0] || fev->window == this->window[1]) { - XLockDisplay(fev->display); - XMapWindow(this->display, this->hud_window); - XUnlockDisplay(fev->display); - } - } - break; - } - case FocusOut: - { - if(this->hud) { - XFocusChangeEvent *fev = (XFocusChangeEvent *) &event; - /* Dismiss HUD window if focusing away from frontend window */ - if(fev->window == this->window[0] || fev->window == this->window[1]) { - XLockDisplay(fev->display); - XUnmapWindow(this->display, this->hud_window); - XUnlockDisplay(fev->display); - } - } - break; - } -#endif /* HAVE_XRENDER */ - case ButtonRelease: - { - dragging = 0; - break; - } - - case MotionNotify: - { - if(dragging && !this->fullscreen) { - XMotionEvent *mev = (XMotionEvent *) &event; - Window tmp_win; - int xpos, ypos; - - XLockDisplay(this->display); - - while(XCheckMaskEvent(this->display, ButtonMotionMask, &event)); - - XTranslateCoordinates(this->display, this->window[0], - DefaultRootWindow(this->display), - 0, 0, &xpos, &ypos, &tmp_win); - - this->xpos = (xpos += mev->x_root - drx); - this->ypos = (ypos += mev->y_root - dry); - drx = mev->x_root; - dry = mev->y_root; - - XMoveWindow(this->display, this->window[0], xpos, ypos); - LOGDBG("MotionNotify: XMoveWindow called with x=%d and y=%d", xpos, ypos); - - XUnlockDisplay(this->display); - } - break; - } - - case ButtonPress: - { - XButtonEvent *bev = (XButtonEvent *) &event; - if(bev->button == Button1) { - static Time prev_time = 0; - if(bev->time - prev_time < DOUBLECLICK_TIME) { - /* Toggle fullscreen */ - sxfe_toggle_fullscreen(this); - prev_time = 0; /* don't react to third click ... */ - } else { - prev_time = bev->time; - if(!this->fullscreen && this->no_border && !dragging) { - dragging = 1; - drx = bev->x_root; - dry = bev->y_root; - } - } - } else if(bev->button == Button3) { - if(!this->fullscreen) { - if(!this->stay_above) { - set_above(this, 1); - } else if(!this->no_border) { - set_border(this, 0); - } else { - set_border(this, 1); - set_above(this, 0); - } - } - } - break; - } - - case KeyPress: - case KeyRelease: - { - XKeyEvent *kevent = (XKeyEvent *) &event; - KeySym ks; - char *ksname; - char buffer[20]; - int buf_len = 20; - XComposeStatus status; - - if(kevent->keycode) { - XLookupString(kevent, buffer, buf_len, &ks, &status); - ksname = XKeysymToString(ks); -#if defined(XINELIBOUTPUT_FE_TOGGLE_FULLSCREEN) || defined(INTERPRET_LIRC_KEYS) - if(ks == XK_f || ks == XK_F) { - sxfe_toggle_fullscreen(this); - } else if(ks == XK_d || ks == XK_D) { - xine_set_param(this->stream, XINE_PARAM_VO_DEINTERLACE, - xine_get_param(this->stream, XINE_PARAM_VO_DEINTERLACE) ? 0 : 1); - } else -#endif -#ifdef FE_STANDALONE - if(ks == XK_Escape) { - terminate_key_pressed = 1; - keep_going = 0; - } else if(this->input || find_input(this)) - process_xine_keypress(this->input, "XKeySym",ksname, 0, 0); -#else - if(this->keypress) - this->keypress("XKeySym",ksname); -#endif - } - } - break; - - case ClientMessage: - { - XClientMessageEvent *cmessage = (XClientMessageEvent *) &event; - if ( cmessage->message_type == this->atom_sxfe_interrupt ) - LOGDBG("ClientMessage: sxfe_interrupt"); - - if ( cmessage->data.l[0] == this->atom_wm_delete_window ) - /* we got a window deletion message from out window manager.*/ - LOGDBG("ClientMessage: WM_DELETE_WINDOW"); - keep_going=0; - } - } - - if (event.type == this->completion_event) - xine_port_send_gui_data (this->video_port, XINE_GUI_SEND_COMPLETION_EVENT, &event); - } - - return keep_going; -} - -static void sxfe_display_close(frontend_t *this_gen) -{ - sxfe_t *this = (sxfe_t*)this_gen; - -#ifdef HAVE_XRENDER - hud_osd_close(this_gen); -#endif - - if(this && this->display) { - - if(this->xine) - this->fe.xine_exit(this_gen); - -#ifdef HAVE_XDPMS - if(this->dpms_state == TRUE) - DPMSEnable(this->display); -#endif - if(this->window_id <= 0) { - XLockDisplay(this->display); - XUnmapWindow(this->display, this->window[this->fullscreen ? 1 : 0]); - XDestroyWindow(this->display, this->window[0]); - XDestroyWindow(this->display, this->window[1]); - XUnlockDisplay(this->display); - } - XCloseDisplay (this->display); - this->display = NULL; - } -} - -static int sxfe_xine_play(frontend_t *this_gen) -{ - int r = fe_xine_play(this_gen); - -#ifdef FE_STANDALONE -# ifdef HAVE_XRENDER - sxfe_t *this = (sxfe_t*)this_gen; - - if(r && this->input && this->hud) { - vdr_input_plugin_t *input_vdr = (vdr_input_plugin_t *)this->input; - LOGDBG("sxfe_xine_play: Enabling HUD OSD"); - input_vdr->f.fe_handle = this_gen; - input_vdr->f.intercept_osd = hud_osd_command; - } -# endif /* HAVE_XRENDER */ -#endif /* FE_STANDALONE */ - - return r; -} - -static frontend_t *sxfe_get_frontend(void) -{ - sxfe_t *this = malloc(sizeof(sxfe_t)); - memset(this, 0, sizeof(sxfe_t)); - - this->window_id = -1; - - this->fe.fe_display_open = sxfe_display_open; - this->fe.fe_display_config = sxfe_display_config; - this->fe.fe_display_close = sxfe_display_close; - - this->fe.xine_init = fe_xine_init; - this->fe.xine_open = fe_xine_open; - this->fe.xine_play = sxfe_xine_play; - this->fe.xine_stop = fe_xine_stop; - this->fe.xine_close = fe_xine_close; - this->fe.xine_exit = fe_xine_exit; - this->fe.xine_is_finished = fe_is_finished; - - this->fe.fe_run = sxfe_run; - this->fe.fe_interrupt = sxfe_interrupt; - this->fe.fe_free = fe_free; - - this->fe.grab = fe_grab; -#ifndef FE_STANDALONE - this->fe.xine_osd_command = xine_osd_command; - this->fe.xine_control = xine_control; - - this->fe.xine_queue_pes_packet = xine_queue_pes_packet; -#endif /*#ifndef FE_STANDALONE */ - - return (frontend_t*)this; -} - -/* ENTRY POINT */ -const fe_creator_f fe_creator __attribute__((visibility("default"))) = sxfe_get_frontend; - - - diff --git a/xineliboutput.c b/xineliboutput.c deleted file mode 100644 index fd84fca5..00000000 --- a/xineliboutput.c +++ /dev/null @@ -1,277 +0,0 @@ -/* - * vdr-xineliboutput: xine-lib based output device plugin for VDR - * - * Copyright (C) 2003-2006 Petri Hintukainen <phintuka@cc.hut.fi> - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * Or, point your browser to http://www.gnu.org/copyleft/gpl.html - * - * - * xineliboutput.c: VDR Plugin interface - * - * $Id: xineliboutput.c,v 1.29 2008-04-14 22:44:32 phintuka Exp $ - * - */ - -#include <vdr/plugin.h> - -#include "logdefs.h" -#include "i18n.h" -#include "config.h" -#include "device.h" -#include "setup_menu.h" -#include "menu.h" -#include "media_player.h" - -#if VDRVERSNUM < 10400 -# error VDR versions < 1.4.0 are not supported ! -#endif - -//---------------------------------plugin------------------------------------- - -static const char *VERSION = "1.0.1-cvs"; -static const char *DESCRIPTION = trNOOP("X11/xine-lib output plugin"); -static const char *MAINMENUENTRY = trNOOP("Media Player"); - -cOsdObject *g_PendingMenuAction = NULL; - -class cPluginXinelibOutput : public cPlugin -{ - private: - // Add any member variables or functions you may need here. - - public: - cPluginXinelibOutput(void); - virtual ~cPluginXinelibOutput(); - - virtual const char *Version(void) { return VERSION; } - virtual const char *Description(void) { return tr(DESCRIPTION); } - virtual const char *CommandLineHelp(void); - - virtual bool ProcessArgs(int argc, char *argv[]); - virtual bool Initialize(void); - virtual bool Start(void); - virtual void Stop(void); - //virtual void Housekeeping(void); - virtual void MainThreadHook(); - //virtual cString Active(void); - //virtual time_t WakeupTime(void); - - virtual const char *MainMenuEntry(void) { return xc.hide_main_menu ? NULL : tr(MAINMENUENTRY); } - virtual cOsdObject *MainMenuAction(void); - - virtual cMenuSetupPage *SetupMenu(void); - virtual bool SetupParse(const char *Name, const char *Value); - - virtual bool Service(const char *Id, void *Data = NULL); - //virtual const char **SVDRPHelpPages(void); - //virtual cString SVDRPCommand(const char *Command, const char *Option, int &ReplyCode); -}; - -cPluginXinelibOutput::cPluginXinelibOutput(void) -{ - // Initialize any member variables here. - // DON'T DO ANYTHING ELSE THAT MAY HAVE SIDE EFFECTS, REQUIRE GLOBAL - // VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT! -} - -cPluginXinelibOutput::~cPluginXinelibOutput() -{ - // Clean up after yourself! - cXinelibDevice::Dispose(); -} - - -const char cmdLineHelp[] = -" -l NAME --local=NAME Use local frontend NAME\n" -" Supported frontends:\n" -" sxfe (X11)\n" -" fbfe (framebuffer)\n" -" none (only remote frontends)\n" -" -r PORT --remote=PORT Listen PORT for remote clients\n" -" (default "LISTEN_PORT_S")\n" -" none or 0 disables remote mode\n" -" Also local interface address can be specified:\n" -" --remote=<ip>:<port> (default is all interfaces)\n" -" -A NAME --audio=NAME Use audio driver NAME for local frontend\n" -" Supported values:\n" -" auto, alsa, oss, esound, none\n" -" -V NAME --video=NAME Use video driver NAME for local frontend\n" -" Supported values:\n" -" for sxfe: auto, x11, xshm, xv, xvmc, xxmc,\n" -" vidix, sdl, opengl, none\n" -" for fbfe: auto, fb, DirectFB, vidixfb,\n" -" sdl, dxr3, aadxr3, none\n" -#if 0 -" -m M --modeline=M Use modeline M for local frontend\n" -" (example: )\n" -#endif -" -f --fullscreen Fullscreen mode (X11)\n" -" -D --hud Head Up Display OSD (X11)\n" -" -w --width=x Window width\n" -" -h --height=x Window width\n" -" -d DISP --display=DISP Use X11 display DISP\n" -" (or framebuffer device name)\n" -" -P NAME --post=NAME Use xine post plugin NAME\n" -" format: pluginname[:arg=val[,arg=val]][,...]\n" -" example: \n" -" --post=upmix;tvtime:enabled=1,cheap_mode=1\n" -" -p --primary Force xineliboutput to be primary device when\n" -" there are active frontend(s)\n" -" -c --exit-on-close Exit vdr when local frontend window is closed\n" -; - -const char *cPluginXinelibOutput::CommandLineHelp(void) -{ - // Return a string that describes all known command line options. - return cmdLineHelp; -} - -bool cPluginXinelibOutput::ProcessArgs(int argc, char *argv[]) -{ - // Implement command line argument processing here if applicable. - return xc.ProcessArgs(argc, argv); -} - -bool cPluginXinelibOutput::Initialize(void) -{ - // Initialize any background activities the plugin shall perform. - TRACEF("cPluginXinelibOutput::Initialize"); - -#if VDRVERSNUM < 10507 - RegisterI18n(Phrases); -#endif - - cXinelibDevice::Instance(); - return true; -} - -bool cPluginXinelibOutput::Start(void) -{ - // Start any background activities the plugin shall perform. - TRACEF("cPluginXinelibOutput::Start"); - return cXinelibDevice::Instance().StartDevice(); -} - -void cPluginXinelibOutput::MainThreadHook(void) -{ - TRACEF("cPluginXinelibOutput::MainThreadHook"); - return cXinelibDevice::Instance().MainThreadHook(); -} - -void cPluginXinelibOutput::Stop(void) -{ - // Start any background activities the plugin shall perform. - TRACEF("cPluginXinelibOutput::Stop"); - return cXinelibDevice::Instance().StopDevice(); -} - -cOsdObject *cPluginXinelibOutput::MainMenuAction(void) -{ - // Perform the action when selected from the main VDR menu. - TRACEF("cPluginXinelibOutput::MainMenuAction"); - - if(xc.main_menu_mode == CloseOsd) { - xc.main_menu_mode = ShowMenu; - return NULL; - } - - if(g_PendingMenuAction) { - cOsdObject *tmp = g_PendingMenuAction; - g_PendingMenuAction = NULL; - return tmp; - } - - if(xc.hide_main_menu) - return NULL; - -#ifdef HAVE_XV_FIELD_ORDER - xc.field_order = xc.field_order ? 0 : 1; - cXinelibDevice::Instance().ConfigureWindow(xc.fullscreen, xc.width, xc.height, - xc.modeswitch, xc.modeline, xc.display_aspect, - xc.scale_video, xc.field_order); -#endif - return new cMenuXinelib(); -} - -cMenuSetupPage *cPluginXinelibOutput::SetupMenu(void) -{ - // Return a setup menu in case the plugin supports one. - TRACEF("cPluginXinelibOutput::SetupMenu"); - return new cMenuSetupXinelib(); -} - -bool cPluginXinelibOutput::SetupParse(const char *Name, const char *Value) -{ - // Parse your own setup parameters and store their values. - return xc.SetupParse(Name, Value); -} - -bool cPluginXinelibOutput::Service(const char *Id, void *Data) -{ - if(Id) { - char *CData = (char*)Data; - - if(!strcmp(Id, "MediaPlayer-1.0")) { - if(CData && *CData) { - LOGMSG("Service(%s, %s)", Id, CData); - cControl::Launch(new cXinelibPlayerControl(ShowFiles, CData)); - return true; - } - LOGMSG("Service(%s) -> true", Id); - return true; - } - - else if(!strcmp(Id, "MusicPlayer-1.0")) { - if(CData && *CData) { - LOGMSG("Service(%s, %s)", Id, CData); - cControl::Launch(new cXinelibPlayerControl(ShowMusic, CData)); - return true; - } - LOGMSG("Service(%s) -> true", Id); - return true; - } - - else if(!strcmp(Id, "DvdPlayer-1.0")) { - if(Data && *CData) { - LOGMSG("Service(%s, %s)", Id, CData); - cControl::Launch(new cXinelibDvdPlayerControl(CData)); - return true; - } - LOGMSG("Service(%s) -> true", Id); - return true; - } - - else if(!strcmp(Id, "ImagePlayer-1.0")) { - if(CData && *CData) { - LOGMSG("Service(%s, %s)", Id, CData); - char **list = new char*[2]; - list[0] = strdup(CData); - list[1] = NULL; - cControl::Launch(new cXinelibImagesControl(list, 0, 1)); - return true; - } - LOGMSG("Service(%s) -> true", Id); - return true; - } - - } - return false; -} - -extern "C" -void *VDRPluginCreator(void) __attribute__((visibility("default"))); - -VDRPLUGINCREATOR(cPluginXinelibOutput); // Don't touch this! -- cgit v1.2.3