diff options
author | cvs2svn <admin@example.com> | 2010-02-07 01:14:50 +0000 |
---|---|---|
committer | cvs2svn <admin@example.com> | 2010-02-07 01:14:50 +0000 |
commit | cdb612d1b83c1c7f09fbed8454ffb155110ae14a (patch) | |
tree | d5107099e53c682a44cd7faf4d9785cea97c7f44 | |
parent | 96b85a7fe6cc9ad9737b3c6d3ad731a54fb8b636 (diff) | |
download | xineliboutput-cdb612d1b83c1c7f09fbed8454ffb155110ae14a.tar.gz xineliboutput-cdb612d1b83c1c7f09fbed8454ffb155110ae14a.tar.bz2 |
This commit was manufactured by cvs2svn to create branch
'unlabeled-1.30.2.9.2'.
100 files changed, 0 insertions, 45967 deletions
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. - - <one line to give the program's name and a brief idea of what it does.> - Copyright (C) <year> <name of author> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 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. - - <signature of Ty Coon>, 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. diff --git a/Makefile b/Makefile deleted file mode 100644 index 998e581d..00000000 --- a/Makefile +++ /dev/null @@ -1,585 +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.38.2.8 2009-08-13 11:12:36 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_DBUS_GLIB_1 = 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 <X11/Xlib.h>";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 <X11/extensions/Xrender.h>";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 <X11/Xlib.h>";echo "\#include <X11/extensions/dpms.h>";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 <X11/extensions/Xinerama.h>";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 - ifeq ($(shell (pkg-config --exists dbus-glib-1 >/dev/null 2>&1 && echo "1") || echo "0"), 1) - HAVE_DBUS_GLIB_1 = 1 - else - $(warning dbus-glib-1 not detected. Disabling gnome-screensaver support. ) - 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 - -# check for libexractor -ifeq ($(shell pkg-config libextractor && echo "1"), 1) - HAVE_EXTRACTOR_H = 1 -else - $(warning libextractor not found.) -endif - -# -# Override configuration here or in ../../../Make.config -# - -USE_ICONV = 1 -#XINELIBOUTPUT_X11 = 1 -#HAVE_XRENDER = 1 -#HAVE_XDPMS = 1 -#HAVE_XINERAMA = 1 -#HAVE_DBUS_GLIB_1 = 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 -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) -# need -lm for ceil/floor in HUD OSD - LIBS_X11 += -lXrender -lm -endif -ifeq ($(HAVE_XINERAMA), 1) - LIBS_X11 += -lXinerama -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_LIBEXTRACTOR=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 -ifeq ($(HAVE_DBUS_GLIB_1), 1) - DEFINES += -DHAVE_DBUS_GLIB_1=1 - LIBS_X11 += $(shell pkg-config --libs dbus-glib-1 2>/dev/null) - INCLUDES_DBUS += $(shell pkg-config --cflags dbus-glib-1 2>/dev/null) -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 \ - tools/metainfo_menu.o logdefs.o tools/rle.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 logdefs.o - OBJS_SXFE = xine_sxfe_frontend_standalone.o xine/post.o tools/vdrdiscovery.o logdefs.o - ifeq ($(HAVE_DBUS_GLIB_1), 1) - OBJS_SXFE_SO += tools/gnome_screensaver.o - OBJS_SXFE += tools/gnome_screensaver.o - endif -else - OBJS_SXFE_SO = - OBJS_SXFE = -endif - -ifeq ($(XINELIBOUTPUT_FB), 1) - OBJS_FBFE_SO = xine_fbfe_frontend.o xine/post.o logdefs.o - OBJS_FBFE = xine_fbfe_frontend_standalone.o xine/post.o tools/vdrdiscovery.o logdefs.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/gnome_screensaver.o: tools/gnome_screensaver.c tools/gnome_screensaver.h - $(CC) $(CFLAGS) -c $(DEFINES) $(INCLUDES) $(INCLUDES_DBUS) $(OPTFLAGS) tools/gnome_screensaver.c -o $@ -tools/rle.o: tools/rle.c tools/rle.h - $(CC) $(CFLAGS) -c $(DEFINES) $(INCLUDES) $(OPTFLAGS) tools/rle.c -o $@ -logdefs.o: logdefs.c logdefs.h - $(CC) $(CFLAGS) -c $(DEFINES) $(INCLUDES) $(OPTFLAGS) logdefs.c -o $@ -tools/vdrdiscovery.o: tools/vdrdiscovery.c tools/vdrdiscovery.h - $(CC) $(CFLAGS) -c $(DEFINES) $(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 tools/gnome_screensaver.h - $(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 tools/gnome_screensaver.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='<phintuka@users.sourceforge.net>' -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) - @mkdir -p $(DESTDIR)/$(XINEPLUGINDIR)/post - @echo Installing $(DESTDIR)/$(XINEPLUGINDIR)/$(XINEINPUTVDR) - @-rm -rf $(DESTDIR)/$(XINEPLUGINDIR)/$(XINEINPUTVDR) - @$(INSTALL) -m 0644 $(XINEINPUTVDR) $(DESTDIR)/$(XINEPLUGINDIR)/$(XINEINPUTVDR) - @echo Installing $(DESTDIR)/$(XINEPLUGINDIR)/post/$(XINEPOSTAUTOCROP) - @-rm -rf $(DESTDIR)/$(XINEPLUGINDIR)/post/$(XINEPOSTAUTOCROP) - @$(INSTALL) -m 0644 $(XINEPOSTAUTOCROP) $(DESTDIR)/$(XINEPLUGINDIR)/post/$(XINEPOSTAUTOCROP) - @echo Installing $(DESTDIR)/$(XINEPLUGINDIR)/post/$(XINEPOSTSWSCALE) - @-rm -rf $(DESTDIR)/$(XINEPLUGINDIR)/post/$(XINEPOSTSWSCALE) - @$(INSTALL) -m 0644 $(XINEPOSTSWSCALE) $(DESTDIR)/$(XINEPLUGINDIR)/post/$(XINEPOSTSWSCALE) - @echo Installing $(DESTDIR)/$(XINEPLUGINDIR)/post/$(XINEPOSTAUDIOCHANNEL) - @-rm -rf $(DESTDIR)/$(XINEPLUGINDIR)/post/$(XINEPOSTAUDIOCHANNEL) - @$(INSTALL) -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) -m 0644 $(XINEPOSTHEADPHONE) $(DESTDIR)/$(XINEPLUGINDIR)/post/$(XINEPOSTHEADPHONE) -endif -ifeq ($(XINELIBOUTPUT_FB), 1) - @echo Installing $(DESTDIR)/$(BINDIR)/vdr-fbfe - @mkdir -p $(DESTDIR)/$(BINDIR) - @-rm -rf $(DESTDIR)/$(BINDIR)/vdr-fbfe - @$(INSTALL) -m 0755 vdr-fbfe $(DESTDIR)/$(BINDIR)/vdr-fbfe -endif -ifeq ($(XINELIBOUTPUT_X11), 1) - @echo Installing $(DESTDIR)/$(BINDIR)/vdr-sxfe - @mkdir -p $(DESTDIR)/$(BINDIR) - @-rm -rf $(DESTDIR)/$(BINDIR)/vdr-sxfe - @$(INSTALL) -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 131251c7..00000000 --- a/README +++ /dev/null @@ -1,664 +0,0 @@ -This is a "plugin" for the Video Disk Recorder (VDR). - -Written by: Petri Hintukainen <phintuka@users.sourceforge.net> - -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) - - libjpeg for grabbing in JPEG format - -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 negotiate 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 - negotiate best available transport. Use best available audio - and video driver. - vdr-fbfe - or - vdr-sxfe - - Connect to 192.168.1.3 default port and negotiate 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 on - 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 | vdpau | - XDirectFB | opengl | sdl | none [:display]] - Examples: - --video xv - --video xvmc:127.0.0.1:1.0 - - With framebuffer frontend (vdr-fbfe): - 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 - - -VDPAU - - All video scaling, cropping, and postprocessing options must be disabled - if the VDPAU output device is used. - De-interlacing can be enabled with command-line option --post tvtime: - Examples: - vdr-sxfe --video vdpau --post tvtime:method=use_vo_driver - vdr -P"xineliboutput --video=vdpau --post=tvtime:method=use_vo_driver" - - -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. - - - Try to adjust OSD size and offsets to get rid of possible graphical - corruption. - - - 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 frontend control keys - - When frontend is started with --hotkeys command-line option, following - keyboard and LIRC keys are interpreted by vdr-sxfe/vdr-fbfe: - - Keyboard (console and X11 window) - f, F Toggle fullscreen state - d, D Toggle deinterlacing - - LIRC - Fullscreen Toggle fullscreen state - Deinterlace Toggle deinterlacing - Quit Close program - - [ this run-time option replaces old build-time options - INTERPRET_LIRC_KEYS and XINELIBOUTPUT_FE_FULLSCREEN_TOGGLE ] - - -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 <vdrkey> 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=<x_window_id> - - -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://<server ip>:37892 - - Client 3: vdr-sxfe xvdr://<server ip>: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 Binary files differdeleted file mode 100644 index 1d466be0..00000000 --- a/black_720x576.mpg +++ /dev/null diff --git a/config.c b/config.c deleted file mode 100644 index 8dd80409..00000000 --- a/config.c +++ /dev/null @@ -1,972 +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.63.2.8 2009-11-16 11:25:32 phintuka Exp $ - * - */ - -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <getopt.h> - -#include <vdr/config.h> -#include <vdr/videodir.h> -#include <vdr/device.h> - -#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_osdBlendingMethods[] = { - trNOOP("Software"), - trNOOP("Hardware"), - 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 -}; - -const char * const config_t::s_osdSizes[] = { - trNOOP("automatic"), - "720x576", - "1280x720", - "1920x1080", - trNOOP("custom"), - NULL -}; - -const char * const config_t::s_decoders_MPEG2[] = { - trNOOP("automatic"), - "libmpeg2", - "FFmpeg", - NULL -}; - -const char * const config_t::s_decoders_H264[] = { - trNOOP("automatic"), - "FFmpeg", - "CoreAVC", - NULL -}; - -const char * const config_t::s_ff_skip_loop_filters[] = { - trNOOP("automatic"), - trNOOP("default"), - trNOOP("none"), - trNOOP("nonref"), - trNOOP("bidir"), - trNOOP("nonkey"), - trNOOP("all"), - NULL -}; - -const char * const config_t::s_ff_speed_over_accuracy[] = { - trNOOP("automatic"), - trNOOP("yes"), - trNOOP("no"), -}; - -static const char exts_playlist[][4] = { - "asx", - "m3u", - "pls", - "ram", -}; - -static const char exts_audio[][8] = { - "ac3", - "asf", - "au", - "aud", - "flac", - "mpa", - "mpega", - "mp2", - "mp3", - "m4a", - "ogg", - "ogm", - "ra", - "spx", - "wav", - "wma", -}; - -static const char exts_video[][8] = { - "asf", - "avi", - "dat", - "divx", - "dv", - "fli", - "flv", - "iso", /* maybe dvd */ - "mkv", - "mov", - "mpeg", - "mpg", - "mpv", - "mp4", - "m2v", - "m2t", - "m2ts", - "m4v", - "mts", - "pes", - "rm", - "ts", - "vdr", - "vob", - "wmv", - "xvid", -}; - -static const char exts_image[][8] = { - "bmp", - "gif", - "jpeg", - "jpg", - "mng", - "png", - "tiff", -}; - -#define DEF_EXT_IS(TYPE) \ -static bool ext_is_ ## TYPE(const char *ext) \ -{ \ - for(unsigned int i=0; i<sizeof(exts_ ## TYPE)/sizeof(exts_ ## TYPE[0]); i++) \ - if(!strcasecmp(ext, exts_ ## TYPE[i])) \ - return true; \ - return false; \ -} -DEF_EXT_IS(playlist) -DEF_EXT_IS(audio) -DEF_EXT_IS(video) -DEF_EXT_IS(image) - -static const char *get_extension(const char *fname) -{ - if(fname) { - const char *pos = strrchr(fname, '.'); - if(pos) - return pos+1; - } - return NULL; -} - -static char *strcatrealloc(char *dest, const char *src) -{ - if (!src || !*src) - return dest; - - size_t 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) -{ - const char *ext = get_extension(fname); - return ext && ext_is_playlist(ext); -} - -bool config_t::IsAudioFile(const char *fname) -{ - const char *ext = get_extension(fname); - return ext && (ext_is_audio(ext) || ext_is_playlist(ext)); -} - -bool config_t::IsVideoFile(const char *fname) -{ - const char *ext = get_extension(fname); - return ext && (ext_is_video(ext) || ext_is_audio(ext) || ext_is_playlist(ext)); -} - -bool config_t::IsImageFile(const char *fname) -{ - const char *ext = get_extension(fname); - return ext && (ext_is_image(ext) || ext_is_playlist(ext)); -} - -bool config_t::IsDvdImage(const char *fname) -{ - const char *ext = get_extension(fname); - return (ext && !strcasecmp(ext, "iso")) ? true : false; -} - -bool config_t::IsDvdFolder(const char *fname) -{ - struct stat st; - cString buf, folder; - - buf = cString::sprintf("%s/VIDEO_TS/", fname); - if (stat(buf, &st) == 0) { - folder = buf; - } else { - buf = cString::sprintf("%s/video_ts/", fname); - if (stat(buf, &st) == 0) - folder = buf; - else - return false; - } - - buf = cString::sprintf("%s/video_ts.ifo", *folder); - if (stat(buf, &st) == 0) - return true; - - buf = cString::sprintf("%s/VIDEO_TS.IFO", *folder); - if (stat(buf, &st) == 0) - return true; - - return false; -} - -bool config_t::IsBluRayFolder(const char *fname) -{ - struct stat st; - cString buf, folder; - - buf = cString::sprintf("%s/BDMV/", fname); - if (stat(buf, &st) == 0) { - folder = buf; - } else { - buf = cString::sprintf("%s/bdmv/", fname); - if (stat(buf, &st) == 0) - folder = buf; - else - return false; - } - - buf = cString::sprintf("%s/MovieObject.bdmv", *folder); - if (stat(buf, &st) == 0) - return true; - - buf = cString::sprintf("%s/movieobject.bdmv", *folder); - if (stat(buf, &st) == 0) - return true; - - buf = cString::sprintf("%s/MOVIEOBJECT.BDMV", *folder); - if (stat(buf, &st) == 0) - 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; - config_file = 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_size = OSD_SIZE_auto; - osd_width = 720; - osd_height = 576; - osd_width_auto = 0; - osd_height_auto = 0; - osd_mixer = OSD_MIXER_FULL; - osd_scaling = OSD_SCALING_NEAREST; - hud_osd = 0; - - osd_blending = OSD_BLENDING_SOFTWARE; - osd_blending_lowresvideo = OSD_BLENDING_HARDWARE; - -#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; - dvb_subtitles = 0; - - 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_max_clients = MAXCLIENTS; - 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; - sharpness = -1; - noise_reduction = -1; - vo_aspect_ratio = 0; - - live_mode_sync = 1; // Sync SCR to transponder clock in live mode - scr_tuning = 0; // Fine-tune xine egine SCR (to sync video to graphics output) - scr_hz = 90000; // Current SCR speed (Hz), default is 90000 - - decoder_mpeg2 = DECODER_MPEG2_auto; - decoder_h264 = DECODER_H264_auto; - ff_h264_speed_over_accurancy = FF_H264_SPEED_OVER_ACCURACY_auto; - ff_h264_skip_loop_filter = FF_H264_SKIP_LOOPFILTER_auto; - - strn0cpy(media_root_dir, "/", sizeof(media_root_dir)); - 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; - dvd_arrow_keys_control_playback = 1; - media_menu_items = ~0; - - 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:C: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' }, - { "config", required_argument, NULL, 'C' }, - { "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"); -#ifndef HAVE_XRENDER - LOGMSG("HUD OSD not supported\n"); -#endif - 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 'C': config_file = strdup(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) -{ - const 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.Size")) osd_size = strstra(Value, s_osdSizes, 0); - else if (!strcasecmp(Name, "OSD.Width")) osd_width = atoi(Value); - else if (!strcasecmp(Name, "OSD.Height")) osd_height = 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.Blending")) osd_blending = atoi(Value); - else if (!strcasecmp(Name, "OSD.BlendingLowRes")) osd_blending_lowresvideo = atoi(Value); -#if 1 - // < 1.0.1 - else if (!strcasecmp(Name, "OSD.UnscaledAlways")) osd_blending = atoi(Value); - else if (!strcasecmp(Name, "OSD.UnscaledLowRes")) osd_blending_lowresvideo = atoi(Value); -#endif - 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, "OSD.DvbSubtitles")) dvb_subtitles = 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.MaxClients")) remote_max_clients = 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.Sharpness")) sharpness = atoi(Value); - else if (!strcasecmp(Name, "Video.NoiseReduction")) noise_reduction = 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, "Video.Decoder.MPEG2")) decoder_mpeg2 = strstra(Value, s_decoders_MPEG2, 0); - else if (!strcasecmp(Name, "Video.Decoder.H264")) decoder_h264 = strstra(Value, s_decoders_H264, 0); - else if (!strcasecmp(Name, "Video.Decoder.H264.SpeedOverAccuracy")) ff_h264_speed_over_accurancy = strstra(Value, s_ff_speed_over_accuracy, 0); - else if (!strcasecmp(Name, "Video.Decoder.H264.SkipLoopFilter")) ff_h264_skip_loop_filter = strstra(Value, s_ff_skip_loop_filters, 0); - - 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); - - else if (!strcasecmp(Name, "Media.RootDir")) STRN0CPY(media_root_dir, Value); - 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, "Media.DVD.ArrowKeysControlPlayback")) dvd_arrow_keys_control_playback = atoi(Value); - else if (!strcasecmp(Name, "Media.MenuItems")) media_menu_items = 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")) live_mode_sync = atoi(Value); - else if (!strcasecmp(Name, "Advanced.AdjustSCR")) scr_tuning = atoi(Value); - else if (!strcasecmp(Name, "Advanced.SCRSpeed")) 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 4934d34c..00000000 --- a/config.h +++ /dev/null @@ -1,476 +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.46.2.7 2009-11-16 11:23:57 phintuka Exp $ - * - */ - -#ifndef _XINELIB_CONFIG_H_ -#define _XINELIB_CONFIG_H_ - -#include <string.h> -#include <stdint.h> - -#include <vdr/config.h> - -// Max number of remote clients -#define MAXCLIENTS 10 - -// 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 - -#define SUBTITLESIZE_count 7 - -// OSD blending methods -#define OSD_BLENDING_SOFTWARE 0 // xine-lib "normal" osd -#define OSD_BLENDING_HARDWARE 1 // xine-lib "unscaled osd" -#define OSD_BLENDING_count 2 - -// 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 - -#if VDRVERSNUM >= 10510 -# define DEVICE_SUPPORTS_IBP_TRICKSPEED -#endif - -// OSD size -#define OSD_SIZE_auto 0 // frontend display resolution -#define OSD_SIZE_720x576 1 -#define OSD_SIZE_1280x720 2 -#define OSD_SIZE_1920x1080 3 -#define OSD_SIZE_custom 4 -#define OSD_SIZE_count 5 - -// Media player menu (bitmask) -#define MEDIA_MENU_FILES (1<<0) -#define MEDIA_MENU_MUSIC (1<<1) -#define MEDIA_MENU_IMAGES (1<<2) -#define MEDIA_MENU_DVD (1<<3) -#define MEDIA_MENU_CD (1<<4) -#define MEDIA_MENU_BLURAY (1<<5) -#define MEDIA_MENU_VIDEO_SETUP (1<<6) -#define MEDIA_MENU_AUDIO_SETUP (1<<7) - -// Video decoder -#define DECODER_MPEG2_auto 0 /* use value from frontend config_xineliboutput */ -#define DECODER_MPEG2_LIBMPEG2 1 -#define DECODER_MPEG2_FFMPEG 2 -#define DECODER_MPEG2_count 3 - -#define DECODER_H264_auto 0 /* use value from frontend config_xineliboutput */ -#define DECODER_H264_FFMPEG 1 -#define DECODER_H264_COREAVC 2 -#define DECODER_H264_count 3 - -#define FF_H264_SKIP_LOOPFILTER_auto 0 /* use value from frontend config_xineliboutput */ -#define FF_H264_SKIP_LOOPFILTER_DEFAULT 1 -#define FF_H264_SKIP_LOOPFILTER_NONE 2 -#define FF_H264_SKIP_LOOPFILTER_NONREF 3 -#define FF_H264_SKIP_LOOPFILTER_BIDIR 4 -#define FF_H264_SKIP_LOOPFILTER_NONKEY 5 -#define FF_H264_SKIP_LOOPFILTER_ALL 6 -#define FF_H264_SKIP_LOOPFILTER_count 7 - -#define FF_H264_SPEED_OVER_ACCURACY_auto 0 /* use value from frontend config_xineliboutput */ -#define FF_H264_SPEED_OVER_ACCURACY_no 1 -#define FF_H264_SPEED_OVER_ACCURACY_yes 2 -#define FF_H264_SPEED_OVER_ACCURACY_count 3 - -#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 [PES_BUFFERS_count + 1]; - static const int i_pesBufferSize [PES_BUFFERS_count + 1]; - static const char * const s_aspects [ASPECT_count + 1]; - static const char * const s_vo_aspects [VO_ASPECT_count + 1]; - static const char * const s_deinterlaceMethods [DEINTERLACE_count + 1]; - static const char * const s_deinterlaceMethodNames [DEINTERLACE_count + 1]; - static const char * const s_fieldOrder [FIELD_ORDER_count + 1]; - static const char * const s_audioDriverNames [AUDIO_DRIVER_count + 1]; - static const char * const s_audioDrivers [AUDIO_DRIVER_count + 1]; - static const char * const s_videoDriverNamesX11 [X11_DRIVER_count + 1]; - static const char * const s_videoDriversX11 [X11_DRIVER_count + 1]; - static const char * const s_videoDriverNamesFB [FB_DRIVER_count + 1]; - static const char * const s_videoDriversFB [FB_DRIVER_count + 1]; - static const char * const s_frontendNames [FRONTEND_count + 1]; - static const char * const s_frontends [FRONTEND_count + 1]; - static const char * const s_frontend_files [FRONTEND_count + 1]; - static const char * const s_audioEqNames [AUDIO_EQ_count + 1]; - static const char * const s_audioVisualizations [AUDIO_VIS_count + 1]; - static const char * const s_audioVisualizationNames[AUDIO_VIS_count + 1]; - static const char * const s_speakerArrangements [SPEAKERS_count + 1]; - static const char * const s_subtitleSizes [SUBTITLESIZE_count + 1]; - static const char * const s_osdBlendingMethods [OSD_BLENDING_count + 1]; - static const char * const s_osdMixers [OSD_MIXER_count + 1]; - static const char * const s_osdScalings [OSD_SCALING_count + 1]; - static const char * const s_osdSizes [OSD_SIZE_count + 1]; - static const char * const s_decoders_MPEG2 [DECODER_MPEG2_count + 1]; - static const char * const s_decoders_H264 [DECODER_H264_count + 1]; - static const char * const s_ff_skip_loop_filters [FF_H264_SKIP_LOOPFILTER_count + 1]; - static const char * const s_ff_speed_over_accuracy [FF_H264_SPEED_OVER_ACCURACY_count + 1]; - - static const char * const s_subExts[]; - - 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 - char *config_file; // config file 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 sharpness; // 0...0xffff, -1 == off - int noise_reduction; // 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_size; - int osd_width; - int osd_height; - int osd_width_auto; - int osd_height_auto; - int osd_mixer; // show multiple OSD layers - int osd_scaling; // OSD scaling mode: off, nearest, bilinear - int hud_osd; // head up display OSD - int osd_blending; // OSD blending method - int osd_blending_lowresvideo; // Use hardware blending for low-resolution video - 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 } - int dvb_subtitles; // send DVB subtitles in data stream (decode+display using xine-lib or external media player) - - // Media player -#if VDRVERSNUM < 10515 - int spu_autoshow; // Preferred SPU language(s) for media player - char spu_lang[4][4]; -#endif - char media_root_dir[4096]; // restrict file browser - 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; - int dvd_arrow_keys_control_playback; - uint media_menu_items; // enabled items in media player menu (bitmask) - - // 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_max_clients; // Max. number of clients - - int remote_usebcast; // Use broadcasts 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_tuning; /* Fine-tune xine egine SCR (to sync video to graphics output) */ - int scr_hz; /* Current SCR speed (Hz), default is 90000 */ - - int decoder_mpeg2; /* DECODER_MPEG2_... */ - int decoder_h264; /* DECODER_H264_... */ - int ff_h264_speed_over_accurancy; - int ff_h264_skip_loop_filter; /* FF_H264_SKIP_LOOPFILTER_* */ - - config_t(); - - bool SetupParse(const char *Name, const char *Value); - bool ProcessArgs(int argc, char *argv[]); - - static bool IsImageFile(const char *); - static bool IsAudioFile(const char *); - static bool IsVideoFile(const char *); - static bool IsPlaylistFile(const char *); - static bool IsDvdFolder(const char *); - static bool IsBluRayFolder(const char *); - static bool IsDvdImage(const char *); - - cString AutocropOptions(void); - cString SwScaleOptions(void); - cString FfmpegPpOptions(void); - cString UnsharpOptions(void); - cString Denoise3dOptions(void); - - template<typename T> bool IsOptionHidden(T & option) - { return hidden_options[(int)((long int)&option - (long int)this)];}; - template<typename T> 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<typename T> void HideOption(T & option) - { hidden_options[(int)((long int)&option - (long int)this)] = 1;}; - template<typename T> 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 151b4487..00000000 --- a/device.c +++ /dev/null @@ -1,1739 +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.2.11 2009-09-14 13:09:23 phintuka Exp $ - * - */ - -#define __STDC_FORMAT_MACROS -#define __STDC_CONSTANT_MACROS -#include <inttypes.h> - -#include <vdr/config.h> -#include <vdr/thread.h> -#include <vdr/dvbspu.h> -#include <vdr/channels.h> -#include <vdr/skins.h> -#include <vdr/status.h> -#include <vdr/remote.h> - -//#define XINELIBOUTPUT_DEBUG -//#define XINELIBOUTPUT_DEBUG_STDERR -//#define TRACK_EXEC_TIME -//#define FORWARD_DVD_SPUS -//#define DEBUG_SWITCHING_TIME -//#define LOG_TRICKSPEED - -#include "logdefs.h" -#include "config.h" -#include "osd.h" - -#include "tools/listiter.h" -#include "tools/mpeg.h" -#include "tools/pes.h" -#include "tools/ts.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_h264 = false; - - m_VideoSize = (video_size_t*)calloc(1, sizeof(video_size_t)); -} - -cXinelibDevice::~cXinelibDevice() -{ - TRACEF("cXinelibDevice::~cXinelibDevice"); - - StopDevice(); - - m_pInstance = NULL; - - free (m_VideoSize); -} - -bool cXinelibDevice::StartDevice() -{ - TRACEF("cXinelibDevice::StartDevice"); - - if(m_local) - m_local->Start(); - if(m_server) - m_server->Start(); - - // if(dynamic_cast<cXinelibLocal*>(it)) - if(m_local) { - int timer = 0; - while (!m_local->IsReady()) { - cCondWait::SleepMs(100); - if (!m_local->Active()) { - 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->Active()) { - 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) - delete server; - if(local) - delete local; - - m_clients.Clear(); -} - -// -// Primary device switching -// - -void cXinelibDevice::MakePrimaryDevice(bool On) -{ - TRACEF("cXinelibDevice::MakePrimaryDevice"); - - cDevice::MakePrimaryDevice(On); - - 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 sharpness, - int noise_reduction, int contrast, int overscan, int vo_aspect_ratio) -{ - TRACEF("cXinelibDevice::ConfigureVideo"); - - if(m_local) - m_local->ConfigureVideo(hue, saturation, brightness, sharpness, noise_reduction, contrast, overscan, vo_aspect_ratio); - if(m_server) - m_server->ConfigureVideo(hue, saturation, brightness, sharpness, noise_reduction, 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); - 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->Active()) - cCondWait::SleepMs(25); - - if (!m_local->Active()) { - 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->Active()) - cCondWait::SleepMs(10); - - if (!m_server->Active()) { - 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); - 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 = "<<m_RadioStream); - - m_StreamStart = true; - m_liveMode = true; - m_TrickSpeed = -1; - m_SkipAudio = false; - m_AudioCount = 0; - m_spuPresent = false; - - Clear(); - ForEach(m_clients, &cXinelibThread::SetNoVideo, m_RadioStream); - ForEach(m_clients, &cXinelibThread::SetLiveMode, true); - ForEach(m_clients, &cXinelibThread::ResumeOutput); -} - -void cXinelibDevice::SetReplayMode(void) -{ - TRACEF("cXinelibDevice::SetReplayMode"); - - m_RadioStream = true; // first seen replayed video packet resets this - m_AudioCount = 15; - m_StreamStart = true; - - ForEach(m_clients, &cXinelibThread::SetLiveMode, false); - Clear(); - ForEach(m_clients, &cXinelibThread::SetNoVideo, false /*m_RadioStream*/); - if(m_RadioStream && !m_liveMode) - ForEach(m_clients, &cXinelibThread::BlankDisplay); - ForEach(m_clients, &cXinelibThread::ResumeOutput); - - m_liveMode = false; -} - -bool cXinelibDevice::SetPlayMode(ePlayMode PlayMode) -{ - TRACEF("cXinelibDevice::SetPlayMode"); - -#ifdef XINELIBOUTPUT_DEBUG - switch (PlayMode) { - case pmNone: - TRACE("cXinelibDevice::SetPlayMode audio/video from decoder"); break; - case pmAudioVideo: - TRACE("cXinelibDevice::SetPlayMode audio/video from player"); break; - case pmVideoOnly: - TRACE("cXinelibDevice::SetPlayMode video from player, audio from decoder"); break; - case pmAudioOnly: - TRACE("cXinelibDevice::SetPlayMode audio from player, video from decoder"); break; - case pmAudioOnlyBlack: - TRACE("cXinelibDevice::SetPlayMode audio only from player, no video (black screen)"); break; - case pmExtern_THIS_SHOULD_BE_AVOIDED: - TRACE("cXinelibDevice::SetPlayMode this should be avoided"); break; - } -#endif - - m_ac3Present = false; - m_spuPresent = false; - -#if VDRVERSNUM < 10515 - ClrAvailableDvdSpuTracks(); -#endif - m_PlayMode = PlayMode; - - TrickSpeed(-1); - if (m_PlayMode == pmAudioOnlyBlack) { - TRACE("pmAudioOnlyBlack --> 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); - - 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<bool>, true); - - return r; -} - - -// -// Playback of files and images -// - -int cXinelibDevice::PlayFileCtrl(const char *Cmd, int TimeoutMs) -{ - TRACEF("cXinelibDevice::PlayFile"); - int result = -1; - - /*if(m_PlayingFile != pmNone)*/ { - if(m_server) - result = m_server->PlayFileCtrl(Cmd, TimeoutMs); - if(m_local) - result = m_local->PlayFileCtrl(Cmd, TimeoutMs); - } - 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, - int TimeoutMs) -{ - 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, TimeoutMs); - if(m_local) - result = m_local->PlayFile(FileName, Position, LoopPlay, PlayMode, TimeoutMs); - } else if(/*!FileName &&*/m_PlayingFile != pmNone) { - if(m_server) - result = m_server->PlayFile(NULL, 0, 0, pmNone, TimeoutMs); - if(m_local) - result = m_local->PlayFile(NULL, 0, 0, pmNone, TimeoutMs); - 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 - - if (!buf || length <= 0) - return length; - - // - // 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; - } - } - - bool isMpeg1 = false; - if (DATA_IS_PES(buf)) { - 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 */ - if (DATA_IS_PES(buf)) - pes_change_pts((uchar*)buf, length, INT64_C(0)); - } - 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 (!DATA_IS_PES(buf)) { - LOGMSG("PlayVideo: data is not PES !"); - 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; - } - - if (pes_get_video_size(buf, length, m_VideoSize, m_h264 ? 1:0)) { - m_StreamStart = false; - LOGDBG("Detected video size %dx%d", m_VideoSize->width, m_VideoSize->height); - ForEach(m_clients, &cXinelibThread::SetHDMode, (m_VideoSize->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_IS_PES(Data) && ((Data[3] & 0xF0) == 0xE0); - bool isMpeg1 = isPes && ((Data[6] & 0xC0) != 0x80); - bool isH264 = isPes && pes_is_frame_h264(Data, Length); - int i; - - if(m_PlayingFile && (m_PlayingFile == pmAudioVideo || m_PlayingFile == pmVideoOnly)) - return; - - ForEach(m_clients, &cXinelibThread::Clear); - ForEach(m_clients, &cXinelibThread::SetNoVideo, false); - ForEach(m_clients, &cXinelibThread::SetLiveMode, false); - ForEach(m_clients, &cXinelibThread::SetStillMode, true); - ForEach(m_clients, &cXinelibThread::TrickSpeed, 1); - - m_TrickSpeed = -1; // to make Poll work ... - m_SkipAudio = 1; // enables audio and pts stripping - - for(i=0; i<STILLPICTURE_REPEAT_COUNT; i++) - if(isMpeg1) { - ForEach(m_clients, &cXinelibThread::Play_Mpeg1_PES, Data, Length, - &mmin<int>, Length); - } else if(isPes) { - /*cDevice::*/PlayPes(Data, Length, m_SkipAudio); - } else { - ForEach(m_clients, &cXinelibThread::Play_Mpeg2_ES, - Data, Length, VIDEO_STREAM, - &mand<bool>, true); - } - - if(!isH264) { - // creates empty video PES with pseudo-pts - ForEach(m_clients, &cXinelibThread::Play_Mpeg2_ES, - Data, 0, VIDEO_STREAM, - &mand<bool>, true); - } - - ForEach(m_clients, &cXinelibThread::Flush, 60, - &mand<bool>, true); - - m_TrickSpeed = 0; - m_SkipAudio = 0; -} - -int cXinelibDevice::PlayAudio(const uchar *buf, int length, uchar Id) -{ - TRACEF("cXinelibDevice::PlayAudio"); - TRACK_TIME(100); - - if(!buf || length < 6) - return length; - -#ifdef SKIP_AC3_AUDIO - // skip AC3 audio - if(((unsigned char *)buf)[3] == PRIVATE_STREAM1) { - TRACE("cXinelibDevice::PlayVideo: PRIVATE_STREAM1 discarded"); - return length; - } -#endif - - // strip audio in trick speed modes and when displaying still images - if(m_SkipAudio /*|| m_TrickSpeed > 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::PlaySubtitle(const uchar *buf, int length) -{ - TRACEF("cXinelibDevice::PlaySpu"); - - if(!buf || length < 6) - return length; - - if(((unsigned char *)buf)[3] == PRIVATE_STREAM1) { - - int PayloadOffset = buf[8] + 9; - uchar SubStreamId = buf[PayloadOffset]; - //uchar SubStreamType = SubStreamId & 0xF0; - uchar SubStreamIndex = SubStreamId & 0x1F; - - if(!m_spuPresent) { - TRACE("cXinelibDevice::PlaySpu first DVD SPU frame"); - Skins.QueueMessage(mtInfo,"DVD Subtitles"); - m_spuPresent = true; - - ForEach(m_clients, &cXinelibThread::SpuStreamChanged, (int)SubStreamIndex); - } - - // Strip all but selected SPU track - if(SubStreamIndex != m_CurrentDvdSpuTrack) - return length; - } - - return PlayAny(buf, length); -} -#else -int cXinelibDevice::PlaySubtitle(const uchar *Data, int Length) -{ - if(!xc.dvb_subtitles) - return cDevice::PlaySubtitle(Data, Length); - return PlayAny(Data, 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(); -} - -void cXinelibDevice::GetOsdSize(int &Width, int &Height, double &PixelAspect) -{ - switch (xc.osd_size) { - case OSD_SIZE_720x576: - Width = 720; - Height = 576; - break; - case OSD_SIZE_1280x720: - Width = 1280; - Height = 720; - break; - case OSD_SIZE_1920x1080: - Width = 1920; - Height = 1080; - break; - case OSD_SIZE_auto: - if (xc.osd_width_auto > 0 && xc.osd_height_auto > 0) { - Width = xc.osd_width_auto; - Height = xc.osd_height_auto; - break; - } - case OSD_SIZE_custom: - default: - Width = xc.osd_width; - Height = xc.osd_height; - break; - } - PixelAspect = 16.0 / 9.0 / (double)Width * (double)Height; -} - -// -// 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 (Quality < 0) - Quality = 100; - - 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 PlaySubtitle(Data, Length); - 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, track; - size_t len; - 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 72447247..00000000 --- a/device.h +++ /dev/null @@ -1,277 +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.2.4 2009-09-14 10:51:55 phintuka Exp $ - * - */ - -#ifndef __XINELIB_DEVICE_H -#define __XINELIB_DEVICE_H - -#include <vdr/config.h> -#include <vdr/device.h> -#include <vdr/tools.h> - -class cXinelibStatusMonitor; -class cXinelibThread; -class cChannel; -class cFunctor; - -struct video_size_s; - -typedef enum { - miTitle = 0, - miTracknumber = 1, - miArtist = 2, - miAlbum = 3, - miDvdTitleNo = 4, - miDvdButtons = 5, - mi_Count = 6 -} 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<cFunctor> 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); - - struct video_size_s *m_VideoSize; - virtual void GetOsdSize(int &Width, int &Height, double &PixelAspect); - - // Track facilities - - protected: - virtual void SetAudioTrackDevice(eTrackType Type); - 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 - - // 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<cXinelibThread> 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 sharpness, - int noise_reduction, 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 TimeoutMs = -1); - int PlayFileCtrl(const char *Cmd, int TimeoutMs = -1); - bool EndOfStreamReached(void); - - // Metainfo cache - - 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: - const char *GetMetaInfo(eMetainfoType Type); - void SetMetaInfo(eMetainfoType Type, const char *Value); - - // 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_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); - virtual int PlaySubtitle(const uchar *Data, int Length); - -#if VDRVERSNUM < 10510 - // 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 <vdr/status.h> - -#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 <vdr/player.h> - -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 <vdr/config.h> - -#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<AUDIO_EQ_count; i++) - DrawBar(i); - } - } -} - -eOSState cEqualizer::ProcessKey(eKeys key) -{ - eOSState state = cOsdObject::ProcessKey(key); - if (state == osUnknown) { - switch (key & ~k_Repeat) { - case kDown: - m_Values[m_Current] -= ADJUST_STEP; - if(m_Values[m_Current] < ADJUST_MIN) - m_Values[m_Current] = ADJUST_MIN; - 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 kUp: - m_Values[m_Current] += ADJUST_STEP; - if(m_Values[m_Current] > 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 <vdr/config.h> -#include <vdr/osdbase.h> - -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 df13bc33..00000000 --- a/examples/remote.conf.example +++ /dev/null @@ -1,63 +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.Info I -XKeySym.Audio A -XKeySym.Subtitles S -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 97c2adbd..00000000 --- a/frontend.c +++ /dev/null @@ -1,896 +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.2.6 2009-09-14 10:10:20 phintuka Exp $ - * - */ - -#define __STDC_FORMAT_MACROS -#define __STDC_CONSTANT_MACROS -#include <inttypes.h> - -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <sys/types.h> -#include <unistd.h> -#include <time.h> -#include <pthread.h> -#include <arpa/inet.h> -#include <netinet/in.h> -#include <netdb.h> -#include <sys/ioctl.h> -#include <sys/socket.h> - -#include <vdr/config.h> -#include <vdr/tools.h> -#include <vdr/plugin.h> - -#include "logdefs.h" -#include "config.h" -#include "frontend.h" -#include "device.h" - -#include "tools/pes.h" -#include "tools/mpeg.h" -#include "tools/h264.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 <vdr/status.h> -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) ?: *cString::sprintf("%03d", id+1)); - 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) ?: *cString::sprintf("%03d", id+1)); - 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, "DVDBUTTONS ", 11)) { - map += 11; - while(*map == ' ') map++; - cXinelibDevice::Instance().SetMetaInfo(miDvdButtons, map); - } - - else if(!strncmp(info, "TITLE ", 6)) { - map += 6; - while(*map == ' ') map++; - cXinelibDevice::Instance().SetMetaInfo(miTitle, map); - } - - else if(!strncmp(info, "DVDTITLE ", 9)) { - 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 - } - - else if (!strncmp(info, "WINDOW ", 7)) { - int w, h; - map += 7; - while(*map == ' ') map++; - if (2 == sscanf(map, "%dx%d", &w, &h)) { - xc.osd_width_auto = w; - xc.osd_height_auto = h; - } - } - - free(pmap); -} - -cXinelibThread::cXinelibThread(const char *Description) : cThread(Description) -{ - TRACEF("cXinelibThread::cXinelibThread"); - - m_Volume = 255; - m_bReady = false; - m_bNoVideo = true; - m_bLiveMode = true; /* can't be replaying when there is no output device */ - m_StreamPos = 0; - m_LastClearPos = 0; - m_Frames = 0; - m_bEndOfStreamReached = false; - m_bPlayingFile = false; - m_StatusMonitor = NULL; -} - -cXinelibThread::~cXinelibThread() -{ - TRACEF("cXinelibThread::~cXinelibThread"); - - Cancel(3); - - if (m_StatusMonitor) - DELETENULL(m_StatusMonitor); -} - -// -// Thread control -// - -bool cXinelibThread::IsReady(void) -{ - LOCK_THREAD; - return m_bReady; -} - -// -// 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"); - - char buf[128]; - - { - LOCK_THREAD; - - if (m_StreamPos == m_LastClearPos) { - //LOGDBG("cXinelibThread::Clear(): double Clear() ignored"); - return; - } - m_LastClearPos = m_StreamPos; - - snprintf(buf, sizeof(buf), "DISCARD %" PRId64 " %d", m_StreamPos, m_Frames); - } - - /* 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<i1+5) return len; - - data2[i2++] = 0x80; - - if ((data1[i1] & 0xf0) == 0x20) { - /* PTS */ - data2[i2++] = 0x80; - data2[i2++] = 5; - data2[i2++] = data1[i1++] & 0x0E; - data2[i2++] = data1[i1++] & 0xFF; - data2[i2++] = data1[i1++] & 0xFE; - data2[i2++] = data1[i1++] & 0xFF; - data2[i2++] = data1[i1++] & 0xFE; - } - else if ((data1[i1] & 0xf0) == 0x30) { - /* PTS & DTS */ - data2[i2++] = 0x80|0x40; - data2[i2++] = 10; - data2[i2++] = data1[i1++] & 0x0E; - data2[i2++] = data1[i1++] & 0xFF; - data2[i2++] = data1[i1++] & 0xFE; - data2[i2++] = data1[i1++] & 0xFF; - data2[i2++] = data1[i1++] & 0xFE; - - data2[i2++] = data1[i1++] & 0x0E; - data2[i2++] = data1[i1++] & 0xFF; - data2[i2++] = data1[i1++] & 0xFE; - data2[i2++] = data1[i1++] & 0xFF; - data2[i2++] = data1[i1++] & 0xFE; - } else { - i1++; - data2[i2++] = 0; /* no pts, no dts */ - data2[i2++] = 0; /* header len */ - } - - int newlen = ((data1[4]<<8) | data1[5]) + (i2-i1), loops=0; - data2[4] = ((newlen)&0xff00)>>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; - bool h264 = IS_NAL_AUD(data); - - 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; - seq_end[12] = h264 ? NAL_END_SEQ : 0xB7; - 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"); - 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(); - const char *end = strrchr(SetupPath, '/'); - if(end) { - SetupPath.Truncate(end - (const char *)SetupPath); - 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, - int TimeoutMs) -{ - 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, TimeoutMs); - - 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); - -#if VDRVERSNUM >= 10515 - // set preferred subtitle language - if (Setup.DisplaySubtitles) { - const char *langs = I18nLanguageCode(Setup.SubtitleLanguages[0]); - if (langs) { - char lang1[5]; - strn0cpy(lang1, langs, 4); /* truncate */ - const char *spu_lang = iso639_1_to_iso639_2(lang1); - LOGMSG("Preferred SPU language: %s (%s)", lang1, spu_lang); - if (spu_lang && spu_lang[0] && spu_lang[1] && !spu_lang[2]) - Xine_Control(cString::sprintf("SPUSTREAM %s", spu_lang)); - } - } else { - LOGMSG("Preferred SPU language: (none)"); - Xine_Control(cString::sprintf("SPUSTREAM %d", ttXSubtitleNone)); - } -#endif - } - - return Running() && !result; -} - - -// -// 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.sharpness, xc.noise_reduction, 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_tuning ? 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 sharpness, - int noise_reduction, 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 %d %d", - hue, saturation, brightness, sharpness, noise_reduction, 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 e4e718d4..00000000 --- a/frontend.h +++ /dev/null @@ -1,151 +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.24.2.2 2009-09-14 09:42:39 phintuka Exp $ - * - */ - -#ifndef __XINELIB_FRONTEND_H -#define __XINELIB_FRONTEND_H - -#include <vdr/tools.h> -#include <vdr/thread.h> -#include <vdr/device.h> // 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: - bool IsReady(void); - - // - // 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); }; - virtual void SetHeader(const uchar *data, int length, bool reset = false) {}; - - // 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, - int TimeoutMs = -1); - virtual int PlayFileCtrl(const char *Cmd, int TimeoutMs=-1) { 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 sharpness, int noise_reduction, 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_bReady; - bool m_bNoVideo; - bool m_bLiveMode; - bool m_bEndOfStreamReached; - bool m_bPlayingFile; - int m_Volume; - cString m_FileName; - uint64_t m_StreamPos; - uint64_t m_LastClearPos; - 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 5ce90c9f..00000000 --- a/frontend_local.c +++ /dev/null @@ -1,466 +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.2.5 2009-09-13 18:48:11 phintuka Exp $ - * - */ - -#define __STDC_CONSTANT_MACROS - -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <sys/types.h> -#include <unistd.h> -#include <dlfcn.h> - -#include <vdr/config.h> -#include <vdr/tools.h> -#include <vdr/shutdown.h> -#include <vdr/plugin.h> - -#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; - - if (!xc.config_file && - 0 < asprintf(&xc.config_file, - "%s/xineliboutput/config", - cPlugin::ConfigDirectory())) - LOGMSG("cXinelibLocal: Using xine-lib configuration file %s", xc.config_file); -} - -cXinelibLocal::~cXinelibLocal() -{ - TRACEF("cXinelibLocal::~cXinelibLocal"); - - m_bReady = false; - - Cancel(-1); - - { - LOCK_FE; - m_bReady = false; - if(fe) - fe->fe_interrupt(fe); - } - - Cancel(3); - - if (fe) { - fe->fe_free(fe); - fe = NULL; - } - if (h_fe_lib) { - dlclose(h_fe_lib); - } -} - -// -// Data transfer -// - -int cXinelibLocal::Play_PES(const uchar *data, int len) -{ - TRACEF("cXinelibLocal::Play_PES"); - - { - LOCK_FE; - if (fe && Running()) { - 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"); - - union { - char buf[32]; - int64_t pts; - } u = {"GETSTC\r\n"}; - - LOCK_FE; - - if (fe && m_bReady) - if (0 == fe->xine_control(fe, u.buf)) - return u.pts; - - return INT64_C(-1); -} - -// -// 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, -1, -1, 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 && Running()) - cCondWait::SleepMs(100); - - cCondWait::SleepMs(100); -} - -// -// Xine control -// - -int cXinelibLocal::Xine_Control(const char *cmd) -{ - TRACEF("cXinelibLocal::Xine_Control"); - if (cmd && *cmd && Running()) { - 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"); - Cancel(-1); - } else { - LOGDBG("cXinelibLocal::Action - fe created"); - if(!curr_fe->fe_display_open(curr_fe, 0, 0, xc.width, xc.height, xc.fullscreen, xc.hud_osd, - xc.modeswitch, xc.modeline, xc.display_aspect, - keypress_handler, 0/*no_x_kbd*/, 0/*gui_hotkeys*/, - xc.video_port, - xc.scale_video, - xc.field_order, - NULL, -1)) { - LOGMSG("cXinelibLocal: Error initializing display"); - Cancel(-1); - } else { - LOGDBG("cXinelibLocal::Action - fe->fe_display_open ok"); - } - } - } - - // main loop - while (Running()) { - - { - // 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, xc.config_file)) { - 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 (Running() && 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); - } - - LOGMSG("cXinelibLocal::Action: thread finished"); -} - diff --git a/frontend_local.h b/frontend_local.h deleted file mode 100644 index 2054ec51..00000000 --- a/frontend_local.h +++ /dev/null @@ -1,70 +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.7 2009-08-18 12:36:56 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(); - - 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.h b/frontend_svr.h deleted file mode 100644 index 1c657f42..00000000 --- a/frontend_svr.h +++ /dev/null @@ -1,140 +0,0 @@ -/* - * frontend_svr.h: server for remote frontends - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: frontend_svr.h,v 1.24 2009-08-18 12:30:34 phintuka Exp $ - * - */ - -#ifndef __XINELIB_FRONTEND_SVR_H -#define __XINELIB_FRONTEND_SVR_H - - -#include "config.h" -#include "frontend.h" - -//----------------------------- cXinelibServer -------------------------------- - -#define CTRL_BUF_SIZE 1024 - -class cBackgroundWriterI; -class cUdpScheduler; -class cStcFuture; -class cCmdFutures; -class cConnState; - -#include "tools/cxsocket.h" - -class cXinelibServer : public cXinelibThread -{ - - public: - cXinelibServer(int listen_port); - virtual ~cXinelibServer(); - - protected: - virtual void Action(void); - - public: - // Playback control - virtual void TrickSpeed(int Speed); - - // Data transfer - 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); - virtual int64_t GetSTC(); - virtual void SetHDMode(bool On); - - // Image grabbing - virtual uchar *GrabImage(int &Size, bool Jpeg, int Quality, - int SizeX, int SizeY); - // Playback files - virtual int PlayFileCtrl(const char *Cmd, int TimeoutMs=-1); - virtual bool EndOfStreamReached(void); - - // Configuration - virtual bool Listen(int port); - -protected: - // Playback control - virtual int Xine_Control(const char *cmd); - virtual int Xine_Control_Sync(const char *cmd); - -protected: - - // Handling of messages from client(s) - - void Handle_Discovery_Broadcast(void); - void Handle_ClientConnected(int fd); - - void Read_Control(int cli); - void Handle_Control(int cli, const char *cmd); - - void Handle_Control_PIPE (int cli, const char *arg); - void Handle_Control_RTP (int cli, const char *arg); - void Handle_Control_UDP (int cli, const char *arg); - void Handle_Control_DATA (int cli, const char *arg); - void Handle_Control_KEY (int cli, const char *arg); - void Handle_Control_UDP_RESEND(int cli, const char *arg); - void Handle_Control_CONFIG (int cli); - void Handle_Control_GRAB (int cli, const char *arg); - void Handle_Control_CONTROL (int cli, const char *arg); - void Handle_Control_HTTP (int cli, const char *arg); - void Handle_Control_RTSP (int cli, const char *arg); - - void CloseDataConnection(int cli); - void CloseConnection (int cli); - -protected: - - // Data - - int m_Port; - int m_ServerId; - - int fd_listen; - int fd_discovery; - - cxSocket fd_control[MAXCLIENTS]; - int fd_data [MAXCLIENTS]; - - int m_OsdTimeouts[MAXCLIENTS]; - char m_CtrlBuf [MAXCLIENTS][CTRL_BUF_SIZE + 1]; - int m_CtrlBufPos [MAXCLIENTS]; - - int m_ConnType [MAXCLIENTS]; // Control connection type. See frontend_svr.c. - bool m_bUdp [MAXCLIENTS]; // Client uses UDP transport - bool m_bMulticast [MAXCLIENTS]; // Client uses multicast RTP - bool m_bConfigOk [MAXCLIENTS]; // Client has been configured - int m_iMulticastMask; // bit [cli] is 1 or 0. 1 == multicast in use. - int m_MasterCli; // Master client (controls playback speed) - - cString m_PipesDir; - - cBackgroundWriterI *m_Writer[MAXCLIENTS]; // buffered output (pipe/tcp/http) - cConnState *m_State[MAXCLIENTS]; // connection state (http/rtsp) - cUdpScheduler *m_Scheduler; - bool m_Master; - - // Storage for return values of pending RPCs - cStcFuture *m_StcFuture; - cCmdFutures *m_Futures; - - int m_Token; - int AllocToken(void); - bool HasClients(void); - - // Cache current PAT/PMT for new clients - uchar *m_Header; - size_t m_HeaderLength; // bytes used - size_t m_HeaderSize; // bytes allocated - public: - void SetHeader(const uchar *Data, int Length, bool Reset = false); -}; - -#endif // __XINELIB_FRONTEND_SVR_H diff --git a/i18n.c b/i18n.c deleted file mode 100644 index 5d95c0e4..00000000 --- a/i18n.c +++ /dev/null @@ -1,4331 +0,0 @@ -/* - * i18n.c: Internationalization - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: i18n.c,v 1.38 2008-10-17 20:19:41 phintuka Exp $ - * - * Translations provided by: - * - * Finnish Petri Hintukainen, Rolf Ahrenberg - * Russian Vladimir Monchenko - * German Udo Richter - * Italian Diego Pierotto - * - */ - -#include <vdr/config.h> -#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 - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Poistetaanko kuva ?", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "ÃÔÐÛØâì ÚÐàâØÝÚã ?", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " TCP transport", // English - " TCP-Übertragung", // Deutsch - "", // Slovenski - " Protocollo TCP", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - " TCP-siirto", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "TCP âàÐÝáßÞàâ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " UDP transport", // English - " UDP-Übertragung", // Deutsch - "", // Slovenski - " Protocollo UDP", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - " UDP-siirto", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // 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 - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - " RTP (multicast) -siirto", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - " RTP (èØàÞÚÞÒÕéÐâÕÛìÝëÙ) âàÐÝáßÞàâ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " PIPE transport", // English - " Pipe-Übertragung", // Deutsch - "", // Slovenski - " Protocollo PIPE", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - " PIPE-siirto", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // 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 - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - " Palvelimen broadcast-ilmoitukset", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - " ÁÕàÒÕà ØáßÞÛì×ãÕâ èØàÞÚÞÒÕéÐÝØÕ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Audio equalizer >>", // English - "Audio-Equalizer >>", // Deutsch - "", // Slovenski - "Equalizzatore audio >>", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Taajuuskorjain >>", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "°ãÔØÞ íÚÒÐÛÐÙ×Õà >>", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Audio Equalizer", // English - "Audio Equalizer", // Deutsch - "", // Slovenski - "Equalizzatore audio", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Taajuuskorjain", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "°ãÔØÞ íÚÒÐÛÐÙ×Õà", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Grayscale", // English - "Graustufen", // Deutsch - "", // Slovenski - "Scala di grigi", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Harmaasävy", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "¾ââÕÝÚØ áÕàÞÓÞ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Bitmap", // English - "Bitmap", // Deutsch - "", // Slovenski - "Bitmap", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Bittikartta", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "±ØâÞÒÐï ÚÐàâÐ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Button$Info", // English - "Info", // Deutsch - "", // Slovenski - "Info", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Tiedot", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Audio Compression", // English - "Audio-Komprimierung", // Deutsch - "", // Slovenski - "Compressione audio", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Voimista hiljaisia ääniä", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "°ãÔØÞ ÚÞÜßàÕááØï", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Play file >>", // English - "Datei abspielen >>", // Deutsch - "", // Slovenski - "Riproduci file >>", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Toista tiedosto >>", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "¿àÞØÓàÐâì äÐÙÛ >>", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Play music >>", // English - "Musik abspielen >>", // Deutsch - "", // Slovenski - "Riproduci musica >>", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Toista musiikkia >>", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "¿àÞØÓàÐâì äÐÙÛ >>", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "View images >>", // English - "Bilder ansehen >>", // Deutsch - "", // Slovenski - "Visualizza immagini >>", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Katsele kuvia >>", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "¿àÞáÜÞâàÕâì Ø×ÞÑàÐÖÕÝØï >>", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Play file", // English - "Datei abspielen", // Deutsch - "", // Slovenski - "Riproduci file", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Toista tiedosto", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "¿àÞØÓàÐâì äÐÙÛ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Images", // English - "Bilder", // Deutsch - "", // Slovenski - "Immagini", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Kuvat", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "¸×ÞÑàÐÖÕÝØï", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "CenterCutOut", // English - "CenterCutOut", // Deutsch - "", // Slovenski - "CenterCutOut", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "CenterCutOut", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Test Images", // English - "Testbilder", // Deutsch - "", // Slovenski - "Prova immagini", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Testikuvat", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "ÂÕáâÞÒëÕ Ø×ÞÑàÐÖÕÝØï", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Visualization", // English - "Visualisierung", // Deutsch - "", // Slovenski - "Visualizzazione", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Visualisointi", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // 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 - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Miksaa stereoääni 5.1-kanavaiseksi", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // 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 - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Miksaa AC3-ääni surroundiksi", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Framebuffer device", // English - "Framebuffer-Device", // Deutsch - "", // Slovenski - "Periferica framebuffer", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Framebuffer-laite", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "Framebuffer ãáâàÞÙáâÒÞ", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Use hardware for low-res video", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - " Laitteisto matalaresoluutioisella videolla", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // 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 - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Toista DVD-levy etäkoneesta >>", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Play DVD disc >>", // English - "DVD abspielen >>", // Deutsch - "", // Slovenski - "Riproduci disco DVD >>", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Toista DVD-levy >>", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // 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 - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Leikkaa 4:3-letterbox 16:9:ksi", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Play only audio", // English - "Nur Audio spielen", // Deutsch - "", // Slovenski - "Riproduci solo audio", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Toista pelkkä ääni", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Off", // English - "Aus", // Deutsch - "", // Slovenski - "Disattivo", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "ei käytössä", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "OSS", // English - "OSS", // Deutsch - "", // Slovenski - "OSS", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "OSS", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Alsa", // English - "Alsa", // Deutsch - "", // Slovenski - "Alsa", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Alsa", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Goom", // English - "Goom", // Deutsch - "", // Slovenski - "Goom", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Goom", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Oscilloscope", // English - "Oszilloskop", // Deutsch - "", // Slovenski - "Oscilloscopio", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Oskilloskooppi", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "FFT Scope", // English - "FFT Spektrum", // Deutsch - "", // Slovenski - "Spettro FFT", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Spektri", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "FFT Graph", // English - "FFT Graph", // Deutsch - "", // Slovenski - "Grafico FFT", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Spektrogrammi", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "X11 (sxfe)", // English - "X11 (sxfe)", // Deutsch - "", // Slovenski - "X11 (sxfe)", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "X11 (sxfe)", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Framebuffer (fbfe)", // English - "Framebuffer (fbfe)", // Deutsch - "", // Slovenski - "Framebuffer (fbfe)", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Framebuffer (fbfe)", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Xv", // English - "Xv", // Deutsch - "", // Slovenski - "Xv", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Xv", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "XShm", // English - "XShm", // Deutsch - "", // Slovenski - "XShm", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "XShm", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Bob", // English - "Bob", // Deutsch - "", // Slovenski - "Bob", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Bob", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Weave", // English - "Weave", // Deutsch - "", // Slovenski - "Weave", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Weave", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Greedy", // English - "Greedy", // Deutsch - "", // Slovenski - "Greedy", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Greedy", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "One Field", // English - "Ein Halbbild", // Deutsch - "", // Slovenski - "Un campo", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "One Field", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "One Field XV", // English - "Ein Halbbild XV", // Deutsch - "", // Slovenski - "Un campo XV", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "One Field XV", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Linear Blend", // English - "Linear mischen", // Deutsch - "", // Slovenski - "Trasparenza lineare", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Linear Blend", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "TvTime", // English - "TvTime", // Deutsch - "", // Slovenski - "TvTime", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "TvTime", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Address", // English - " Multicast-Adresse", // Deutsch - "", // Slovenski - " Indirizzo", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - " Osoite", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Port", // English - " Multicast-Port", // Deutsch - "", // Slovenski - " Porta", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - " Portti", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " TTL", // English - " Multicast-TTL", // Deutsch - "", // Slovenski - " TTL", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - " TTL-aika", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Transmit always on", // English - " Immer senden", // Deutsch - "", // Slovenski - " Trasmetti sempre", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - " Pidä lähetys aina päällä", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Speakers", // English - "Lautsprecher", // Deutsch - "", // Slovenski - "Altoparlanti", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Kaiuttimet", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // 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 - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Kuulokkeet 2.0", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Autodetect letterbox", // English - " Letterbox automatisch erkennen", // Deutsch - "", // Slovenski - " Rileva letterbox in automatico", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - " Tunnista letterbox automaattisesti", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Soft start", // English - " Weich starten", // Deutsch - "", // Slovenski - " Avvio leggero", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - " Portaittainen aloitus", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Crop to", // English - " Schneide auf", // Deutsch - "", // Slovenski - " Ritaglia a", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - " Leikkaa kokoon", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Detect subtitles", // English - " Erkenne Untertitel", // Deutsch - "", // Slovenski - " Rileva sottotitoli", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - " Huomioi tekstitys", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - - // 1.0.0pre4: - { "Media", // English - "Medien", // Deutsch - "", // Slovenski - "Media", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Media", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Video settings", // English - "Video-Einstellungen", // Deutsch - "", // Slovenski - "Impostazioni video", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Videoasetukset", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Audio settings", // English - "Audio-Einstellungen", // Deutsch - "", // Slovenski - "Impostazioni audio", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Ääniasetukset", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // 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 - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Leikkaa kuvan reunoja (overscan)", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Smooth fast forward", // English - "", // Deutsch - "", // Slovenski - "Avanzamento veloce leggero", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Tasainen kuvakelaus", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // 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 - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Käytä jälkikäsittelyä (ffmpeg)", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - // ffmpeg post processing - { " Quality", // English - " Qualität", // Deutsch - "", // Slovenski - " Qualità", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - " Laatu", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Mode", // English - " Modus", // Deutsch - "", // Slovenski - " Modalità", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - " Moodi", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - // tvtime de-interlacing - { " Method", // English - " Methode", // Deutsch - "", // Slovenski - " Metodo", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - " Menetelmä", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Cheap mode", // English - " einfacher Modus", // Deutsch - "", // Slovenski - " Modo economico", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - " Käytä Cheap-moodia", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Pulldown", // English - " Pulldown", // Deutsch - "", // Slovenski - " Pulldown", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - " Pulldown-moodi", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Frame rate", // English - " Bildrate", // Deutsch - "", // Slovenski - " Frame rate", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - " Ruudunpäivitys", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Judder Correction", // English - " Ruckel-Korrektur", // Deutsch - "", // Slovenski - " Correzione gamma", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - " Käytä tärinänkorjausta", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // 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 - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - " Tunnista progressiivinen kuva", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Chroma Filter", // English - " Chrominanz-Filter", // Deutsch - "", // Slovenski - " Filtro Chroma", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - " Käytä Chroma-suodinta", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Select subtitle track", // English - "Wähle Untertitel", // Deutsch - "", // Slovenski - "Seleziona traccia sottotitoli", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Valitse tekstityskieli", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Select subtitle track >>", // English - "Wähle Untertitel >>", // Deutsch - "", // Slovenski - "Seleziona traccia sottotitoli >>", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Valitse tekstityskieli >>", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Subtitles", // English - "Untertitel", // Deutsch - "", // Slovenski - "Sottotitoli", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Tekstitys", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "External subtitle size", // English - "Untertitel größe", // Deutsch - "", // Slovenski - "Dimensione sottotitoli esterni", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Erillisen tekstityksen koko", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Aspect ratio", // English - "Seitenverhältnis", // Deutsch - "", // Slovenski - "Proporzioni", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Kuvasuhde", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Play music", // English - "Musik abspielen", // Deutsch - "", // Slovenski - "Riproduci musica", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Toista musiikkia", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Random play", // English - "Zufallswiedergabe", // Deutsch - "", // Slovenski - "Riproduzione casuale", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Satunnaistoisto", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Normal play", // English - "Normale Wiedergabe", // Deutsch - "", // Slovenski - "Riproduzione normale", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Normaali toisto", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // 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 - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Näyttölaitteen alustus epäonnistui", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // 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 - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Palvelimen käynnistys epäonnistui", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - // Goom options - { " Width", // English - " Breite", // Deutsch - "", // Slovenski - " Larghezza", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - " Leveys", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Height", // English - " Höhe", // Deutsch - "", // Slovenski - " Altezza", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - " Korkeus", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Speed", // English - " Bildrate", // Deutsch - "", // Slovenski - " Velocità", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - " Nopeus", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " SAP announcements", // English - " SAP-Ankündigungen", // Deutsch - "", // Slovenski - " Annunci SAP", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - " SAP-ilmoitukset", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Play remote CD >>", // English - "Entfernte CD abspielen >>", // Deutsch - "", // Slovenski - "Riproduci CD remoto >>", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Toista CD-levy etäkoneesta >>", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Play audio CD >>", // English - "Musik-CD abspielen >>", // Deutsch - "", // Slovenski - "Riproduci CD audio >>", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Toista CD-levy >>", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // 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 - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - " HTTP -siirto mediatiedostoille", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // 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 - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Muut verkkopalvelut", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "HTTP server", // English - "HTTP-Server", // Deutsch - "", // Slovenski - "Server HTTP", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "HTTP-palvelin", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "RTSP server", // English - "RTSP-Server", // Deutsch - "", // Slovenski - "Server RTSP", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "RTSP-palvelin", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // 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 - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Anna HTTP-asiakkaiden ohjata VDR:ää", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // 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 - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Anna RTSP-asiakkaiden ohjata VDR:ää", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Button$Queue", // English - "Warteschlange", // Deutsch - "", // Slovenski - "Coda", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Soittolistalle", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Button$Sort", // English - "Sortiere", // Deutsch - "", // Slovenski - "Ordina", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Järjestä", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Button$Remove", // English - "Entferne", // Deutsch - "", // Slovenski - "Rimuovi", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Poista", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Button$Add files", // English - "Füge Dateien hinzu", // Deutsch - "", // Slovenski - "Aggiungi files", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Lisää", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Button$Random", // English - "Zufall", // Deutsch - "", // Slovenski - "Casuale", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Satunnaistoisto", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Button$Normal", // English - "Normal", // Deutsch - "", // Slovenski - "Normale", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Normaali toisto", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // 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 - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Ei tekstitystä", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Playlist", // English - "Wiedergabeliste", // Deutsch - "", // Slovenski - "Lista esecuzione", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Soittolista", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // 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 - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Lisää soittolistalle", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // 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 - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Lisätty soittolistalle", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Volume control", // English - "", // Deutsch - "", // Slovenski - "Controllo volume", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Äänenvoimakkuuden säätö", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Hardware", // English - "", // Deutsch - "", // Slovenski - "Hardware", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Laitteistolla", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Software", // English - "", // Deutsch - "", // Slovenski - "Software", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Ohjelmallisesti", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "3D Denoiser", // English - "", // Deutsch - "", // Slovenski - "3D Denoiser", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "3D kohinanpoisto", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - // 3D Denoiser - { " Spatial luma strength", // English - "", // Deutsch - "", // Slovenski - " Resistenza luma spaziale", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - " Luman tilavoimakkuus", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Spatial chroma strength", // English - "", // Deutsch - "", // Slovenski - " Resistenza chroma spaziale", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - " Chroman tilavoimakkuus", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Temporal strength", // English - "", // Deutsch - "", // Slovenski - " Resistenza temporale", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - " Ajallinen voimakkuus", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Sharpen / Blur", // English - "", // Deutsch - "", // Slovenski - "Nitido / Blur", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Terävöinti / Sumennus", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // 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 - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - " Luma-matriisin leveys", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Height of the luma matrix", // English - "", // Deutsch - "", // Slovenski - " Altezza della matrice luma", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - " Luma-matriisin korkeus", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // 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 - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - " Luma-terävöinti/-sumennus", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Width of the chroma matrix", // English - "", // Deutsch - "", // Slovenski - " Larghezza della matrice chroma", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - " Chroma-matriisin leveys", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Height of the chroma matrix", // English - "", // Deutsch - "", // Slovenski - " Altezza della matrice chroma", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - " Chroma-matriisin korkeus", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // 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 - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - " Chroma-terävöinti/-sumennus", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Headphones 2.0", // English - "", // Deutsch - "", // Slovenski - "Cuffie 2.0", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Kuulokkeet 2.0", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Pass Through", // English - "", // Deutsch - "", // Slovenski - "Passa attraverso", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Läpivienti", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Show the track number", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Näytä raidan numero", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Show the name of the artist", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Näytä esittäjän nimi", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Show the name of the album", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Näytä levyn nimi", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Cache metainfo", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Tallenna metatieto", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Scan for metainfo", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Tutki kappaleiden metatiedot", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Playlist settings", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Soittolistan asetukset", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Video aspect ratio", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Videon kuvasuhde", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "square", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "neliö", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "anamorphic", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "anamorfinen", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Software scaling", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Skaalaus ohjelmistolla", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Change aspect ratio", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - " Muuta kuvasuhdetta", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Change video size", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - " Muuta videokuvan kokoa", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Fastest trick speed", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Suurin kelausnopeus", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Blending method", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Piirtotapa", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Scaling method", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Skaalaus", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Show all layers", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Näytä kaikki kerrokset", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Advanced", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Advanced settings", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " * Following settings won't work with UDP/RTP *", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - " * Seuraavat asetukset eivät toimi UDP/RTP:n kanssa *", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Sync to transponder in live mode", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Tahdistu lähetteeseen live-tilassa", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { "Adjust SCR", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - "Säädä SCR:ää", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Clock speed (Hz)", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - " Kellon nopeus (Hz)", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // Ellinika - "", // Svenska - "", // Romaneste - "", // Magyar - "", // Catala - "", // Russian - "", // Croatian - "", // Eesti - "", // Dansk - "", // Czech - }, - { " Clock Adjustment (%)", // English - "", // Deutsch - "", // Slovenski - "", // Italiano - "", // Nederlands - "", // Portugu<EA>s - "", // Fran<E7>ais - "", // Norsk - " Kellon säätö (%)", // Suomi - "", // Polski - "", // Espa<F1>ol - "", // 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 <vdr/i18n.h> - -#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.c b/logdefs.c deleted file mode 100644 index 063e1924..00000000 --- a/logdefs.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - * logdefs.c: Logging and debug output - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: logdefs.c,v 1.2 2008-11-04 12:29:36 phintuka Exp $ - * - */ - -#include "logdefs.h" - -#include <stdio.h> -#include <unistd.h> -#include <sys/syscall.h> -#include <stdarg.h> - -#ifndef __APPLE__ -# include <linux/unistd.h> /* syscall(__NR_gettid) */ -#endif - -/* next symbol is dynamically linked from input plugin */ -int LogToSysLog __attribute__((visibility("default"))) = 1; /* log to syslog instead of console */ - -void x_syslog(int level, const char *module, 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] %s%s\n", (long int)syscall(__NR_gettid), module, buf); - } else { - syslog(level, "[%ld] %s%s", (long int)syscall(__NR_gettid), module, buf); - } -#else - if(!LogToSysLog) { - fprintf(stderr, "%s%s\n", module, buf); - } else { - syslog(level, "%s%s", module, buf); - } -#endif - - va_end(argp); -} - diff --git a/logdefs.h b/logdefs.h deleted file mode 100644 index adaae658..00000000 --- a/logdefs.h +++ /dev/null @@ -1,194 +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.14 2009-08-01 19:46:49 phintuka Exp $ - * - */ - -#ifndef _LOGDEFS_H_ -#define _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 - */ - -#include <syslog.h> /* logging levels: LOG_ERR, LOG_INFO, LOG_DEBUG */ - -#define SYSLOGLEVEL_NONE 0 -#define SYSLOGLEVEL_ERRORS 1 -#define SYSLOGLEVEL_INFO 2 -#define SYSLOGLEVEL_DEBUG 3 -#define SYSLOGLEVEL_VERBOSE 4 - -#if defined(esyslog) -# define x_syslog(l,m,x...) syslog_with_tid(l, m x) -#else - -# ifdef __cplusplus - extern "C" { -# endif - - /* from xine_frontend.c or vdr/tools.c: */ - extern int SysLogLevel; /* errors, info, debug */ - - /* from logdefs.c: */ - extern int LogToSysLog; - - void x_syslog(int level, const char *module, const char *fmt, ...) - __attribute__((format (printf, 3, 4))) - __attribute__((visibility("default"))); - -# ifdef __cplusplus - } /* extern "C" { */ -# endif - -#endif /* VDR */ - -#ifdef NEED_x_syslog -# error NEED_x_syslog is deprecated -#endif - - -/* - * Macros used for logging - */ - -#include <errno.h> - -#define LOG_ERRNO \ - x_syslog(LOG_ERR, LOG_MODULENAME, " (ERROR (%s,%d): %s)", \ - __FILE__, __LINE__, strerror(errno)) - -#define LOGERR(x...) \ - do { \ - if (SysLogLevel >= SYSLOGLEVEL_ERRORS) { \ - x_syslog(LOG_ERR, LOG_MODULENAME, x); \ - if (errno) \ - LOG_ERRNO; \ - } \ - } while(0) -#define LOGMSG(x...) \ - do { \ - if (SysLogLevel >= SYSLOGLEVEL_INFO) \ - x_syslog(LOG_INFO, LOG_MODULENAME, x); \ - } while(0) -#define LOGDBG(x...) \ - do { \ - if (SysLogLevel >= SYSLOGLEVEL_DEBUG) \ - x_syslog(LOG_DEBUG, LOG_MODULENAME, x); \ - } while(0) -#define LOGVERBOSE(x...) \ - do { \ - if (SysLogLevel >= SYSLOGLEVEL_VERBOSE) \ - x_syslog(LOG_DEBUG, LOG_MODULENAME, 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 <fstream> -# include <iostream> -# include <stdio.h> -# -# 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 0cd2502e..00000000 --- a/media_player.c +++ /dev/null @@ -1,1359 +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.52.2.7 2009-09-16 09:56:11 phintuka Exp $ - * - */ - -#include <unistd.h> - -#include <vdr/config.h> -#include <vdr/status.h> -#include <vdr/interface.h> -#include <vdr/tools.h> - -#include "config.h" -#include "media_player.h" -#include "device.h" -#include "tools/playlist.h" -#include "tools/metainfo_menu.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_Error; - bool m_UseResumeFile; - int m_Speed; - - void UpdateNumTracks(void); - - 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 Playing(void) { return !(m_Error || cXinelibDevice::Instance().EndOfStreamReached()); } - bool Error(void) { return m_Error; } - void UseResumeFile(bool Val) { m_UseResumeFile = Val; } - - /* 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_UseResumeFile = true; - m_Error = false; - m_Speed = 1; - - if(File) { - size_t 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); - return !m_Error; - } - - return false; -} - -void cXinelibPlayer::UpdateNumTracks(void) -{ - // cdda tracks - if(m_Playlist.Count() == 1 && !strcmp("cdda:/", m_Playlist.First()->Filename)) { - int count = cXinelibDevice::Instance().PlayFileCtrl("GETAUTOPLAYSIZE CD", 10000); - if(count>1) { - for(int i=0; i<count; i++) - m_Playlist.Read(cString::sprintf("cdda:/%d", i+1)); - m_Playlist.Del(m_Playlist.First()); - } - } -} - -void cXinelibPlayer::Activate(bool On) -{ - int pos = 0, len = 0, fd = -1; - if(On) { - if(m_UseResumeFile && !*m_ResumeFile) - m_ResumeFile = cString::sprintf("%s.resume", *m_File); - if(m_UseResumeFile && 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%s", - m_File[0] == '/' ? "file:" : "", - *cPlaylist::EscapeMrl(m_File), - m_SubFile[0] == '/' ? "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); - - // Start replay - UpdateNumTracks(); - m_Error = !cXinelibDevice::Instance().PlayFile(mrl, pos); - LOGDBG("cXinelibPlayer playing %s (%s)", *m_File, m_Error ? "FAIL" : "OK"); - - if(!m_Error) { - // 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; - - UpdateNumTracks(); - } - } else { - if(m_UseResumeFile && *m_ResumeFile) { - pos = cXinelibDevice::Instance().PlayFileCtrl("GETPOS"); - len = cXinelibDevice::Instance().PlayFileCtrl("GETLENGTH"); - if(pos>10000 && 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); - m_Error = 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 <vdr/skins.h> - -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->UseResumeFile( (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 { - size_t 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 new cMetainfoMenu(m_Player->Playlist().Current()->Filename); -} - -eOSState cXinelibPlayerControl::ProcessKey(eKeys Key) -{ - if ( !m_Player->Playing() ) { - LOGDBG("cXinelibPlayerControl: EndOfStreamReached"); - if (m_Mode == ShowMusic && m_Player->Files() == 1 && !m_Player->Error()) { - 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) -{ - // Check for end of stream and failed open - if ( !m_Player->Playing() ) { - LOGDBG("cXinelibDvdPlayerControl: EndOfStreamReached"); - Hide(); - return osEnd; - } - - // Update DVD title information - 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); - } - - // Handle menu selection - 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; - } - - // Update progress bar display - if (m_DisplayReplay) - Show(); - - // Handle menu navigation - - bool MenuDomain = !xc.dvd_arrow_keys_control_playback; - if(Key != kNone || m_DisplayReplay) { - const char *dt = cXinelibDevice::Instance().GetMetaInfo(miDvdTitleNo); - if(dt && !strcmp("0", dt)) - MenuDomain = true; - else { - dt = cXinelibDevice::Instance().GetMetaInfo(miDvdButtons); - if(dt && *dt && *dt != '0') - 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; - } - } - - // Handle normal keys - - 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_Mrl; - bool m_Active; - bool m_Error; - cXinelibDevice *m_Dev; - - bool Play(void); - - protected: - virtual void Activate(bool On); - - public: - cXinelibImagePlayer(const char *File); - virtual ~cXinelibImagePlayer(); - - bool ShowImage(const char *File); - bool Error(void) { return m_Error; } -}; - -cXinelibImagePlayer::cXinelibImagePlayer(const char *File) -{ - m_Mrl = File; - m_Active = false; - m_Error = false; - m_Dev = &(cXinelibDevice::Instance()); -} - -cXinelibImagePlayer::~cXinelibImagePlayer() -{ - Activate(false); - Detach(); -} - -bool cXinelibImagePlayer::Play(void) -{ - if ((*m_Mrl)[0] == '/') - m_Mrl = cString::sprintf("file:%s", *cPlaylist::EscapeMrl(m_Mrl)); - - return m_Dev->PlayFile(m_Mrl, 0, true); -} - -void cXinelibImagePlayer::Activate(bool On) -{ - m_Active = On; - m_Error = false; - if (On) - Play(); - else - m_Dev->PlayFile(NULL); -} - -bool cXinelibImagePlayer::ShowImage(const char *File) -{ - m_Mrl = File; - if (m_Active) - return Play(); - 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; i<m_Count; i++) - m_Files[i] = m_Files[i+1]; - m_Count--; - m_Files[m_Count] = NULL; - Seek(0); - } - } -} - -cOsdObject *cXinelibImagesControl::GetInfo(void) -{ - return new cMetainfoMenu(m_Files[m_Index]); -} - -void cXinelibImagesControl::Seek(int Rel) -{ - if(m_Index == m_Count-1 && Rel>0) - 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 8b55fceb..00000000 --- a/media_player.h +++ /dev/null @@ -1,127 +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.16 2008-05-07 13:27:15 phintuka Exp $ - * - */ - -#ifndef __XINELIB_PLAYER_H -#define __XINELIB_PLAYER_H - -#include <vdr/player.h> - -#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); - - virtual cOsdObject *GetInfo(void); - - 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 ce03d022..00000000 --- a/menu.c +++ /dev/null @@ -1,1069 +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.57.2.7 2009-09-16 16:54:24 phintuka Exp $ - * - */ - -#include <dirent.h> - -#include <vdr/config.h> -#include <vdr/interface.h> -#include <vdr/menu.h> -#include <vdr/plugin.h> -#include <vdr/videodir.h> - -#include "logdefs.h" -#include "config.h" -#include "menu.h" -#include "menuitems.h" -#include "tools/metainfo_menu.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; - const char *help[4]; - - virtual bool ScanDir(const char *DirName); - virtual eOSState Open(bool ForceOpen = false, bool Queue = false, bool Rewind = 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) -{ - const 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 - // delete old keys (<1.0.0) - cPluginManager::GetPlugin(PLUGIN_NAME_I18N)->SetupStore("BrowseMusicDir"); - cPluginManager::GetPlugin(PLUGIN_NAME_I18N)->SetupStore("BrowseFilesDir"); - cPluginManager::GetPlugin(PLUGIN_NAME_I18N)->SetupStore("BrowseImagesDir"); -#endif -} - -void cMenuBrowseFiles::SetHelpButtons(void) -{ - bool isDir = !GetCurrent() || GetCurrent()->IsDir(); - bool isFile = !isDir; - - if (isDir && !strcmp("..", GetCurrent()->Name())) { - help[0] = help[1] = help[2] = help[3] = NULL; - } else if (m_Mode == ShowMusic) { - help[0] = isDir ? trVDR("Button$Play") : NULL; - help[1] = tr ("Button$Queue"); - help[2] = isFile ? trVDR("Button$Delete") : NULL; - help[3] = isFile ? trVDR("Button$Info") : NULL; - } else if (m_Mode == ShowImages) { - help[0] = isDir ? trVDR("Button$Play") : NULL; - help[1] = NULL; - help[2] = isFile ? trVDR("Button$Delete") : NULL; - help[3] = isFile ? trVDR("Button$Info") : NULL; - } else { - bool isDvd = GetCurrent() && (GetCurrent()->IsDvd() || GetCurrent()->IsBluRay()); - bool hasResume = GetCurrent() && GetCurrent()->HasResume(); - - help[0] = isDir && isDvd ? trVDR("Button$Open") : NULL; - help[1] = hasResume ? trVDR("Button$Rewind") : NULL; - help[2] = isFile || isDvd ? trVDR("Button$Delete") : NULL; - help[3] = isFile ? trVDR("Button$Info") : NULL; - } - - SetHelp(help[0], help[1], help[2], help[3]); - 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 Queue, bool Rewind) -{ - if(!GetCurrent()) { - return osContinue; - } - - /* parent directory */ - if (!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() && !GetCurrent()->IsBluRay()) { - /* 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 - } - } - - /* go to directory */ - const char *d = GetCurrent()->Name(); - char *buffer = NULL; - if(asprintf(&buffer, "%s/%s", m_CurrentDir, d) >= 0) { - 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()) { - if (Rewind) - unlink(cString::sprintf("%s.resume", *f)); - 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()) - if(asprintf(&files[i++], "%s/%s", m_CurrentDir, it->Name()) < 0) - i--; - } - cControl::Shutdown(); - cControl::Launch(new cXinelibImagesControl(files, index, i)); - } - return osEnd; - } - return osContinue; -} - -eOSState cMenuBrowseFiles::Info(void) -{ - if(GetCurrent() && !GetCurrent()->IsDir()) { - cString filename = cString::sprintf("%s/%s", m_CurrentDir, GetCurrent()->Name()); - return AddSubMenu(new cMetainfoMenu(filename)); - } - 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 - Add(new cFileListItem(e->d_name, true, false, false, - xc.IsDvdFolder(buffer), xc.IsBluRayFolder(buffer))); - - // 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)); - - // DVD image (.iso) - } else if (m_Mode == ShowFiles && xc.IsDvdImage(buffer)) { - Add(new cFileListItem(e->d_name, false, false, false, true)); - - // video - } else if (m_Mode == ShowFiles && xc.IsVideoFile(buffer)) { - cString subfile; - cString resumefile; - - // separate subtitles ? - cString basename = cString::sprintf("%s/%s", DirName, e->d_name); - const char *p = strrchr(basename, '.'); - if (p) - basename.Truncate(p - basename); - int i; - for(i=0; xc.s_subExts[i] && !*subfile; i++) { - cString tmp = cString::sprintf("%s%s", *basename, xc.s_subExts[i]); - if (stat(tmp, &st) == 0) - subfile = tmp; - } - - // resume file ? - resumefile = cString::sprintf("%s/%s.resume", DirName, e->d_name); - if (stat(resumefile, &st) != 0) - resumefile = NULL; - - Add(new cFileListItem(e->d_name, false, *resumefile, subfile)); - } - } - } - } - } - 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, m_OnlyQueue); - case kRed: if (help[0]) - return Open(true); - break; - case kGreen: if (help[1]) - return Open(true, - m_Mode == ShowMusic ? m_OnlyQueue=true : false, - m_Mode != ShowMusic); - break; - case kYellow: if (help[2]) - return Delete(); - break; - case kBlue: if (help[3]) - return Info(); - break; - 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.sharpness, - xc.noise_reduction, 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.sharpness, - xc.noise_reduction, 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.sharpness, - xc.noise_reduction, 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 <vdr/menuitems.h> - -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 3d8e8387..00000000 --- a/menuitems.c +++ /dev/null @@ -1,224 +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.2.3 2009-09-13 13:11:03 phintuka Exp $ - * - */ - -#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(); -} - -static int my_exp10(int x) -{ - int r = 1; - for (; x > 0; x--, r *= 10) ; - return r; -} - -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)) / (float)my_exp10(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_IsBluRay = 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, bool IsBluRay) -{ - m_Name = name; - m_IsDir = IsDir; - m_IsDvd = IsDvd; - m_IsBluRay = IsBluRay; - m_HasResume = HasResume; - m_SubFile = subfile; - m_ShowFlags = true; - m_Up = m_IsDir && !strcmp(m_Name, ".."); - Set(); -} - -void cFileListItem::Set(void) -{ - cString txt; - const 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 if (m_IsBluRay) - txt = cString::sprintf("\tB\t[%s] ", *m_Name); - 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_IsBluRay ? 'B' : ' ', *m_Name); - if(NULL != (pt = strrchr(txt,'.'))) - txt.Truncate(pt - txt); - } - } 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,'.'))) - txt.Truncate(pt - txt); - } - } - 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/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 <phintuka@cc.hut.fi> - * - * 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 <stdio.h> - -#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 Binary files differdeleted file mode 100644 index cff01b4c..00000000 --- a/nosignal_720x576.mpg +++ /dev/null @@ -1,629 +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.25.2.4 2009-09-18 10:59:35 phintuka Exp $ - * - */ - -#include <vdr/config.h> -#include <vdr/tools.h> -#include <vdr/thread.h> - -#include "logdefs.h" -#include "config.h" -#include "device.h" -#include "xine_osd_command.h" -#include "tools/rle.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<colors; c++) { - int A = (palette[c] & 0xff000000) >> 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<colors; c++) - clut[c].alpha >>= 1; /* fade */ - if(xc.osd_mixer & OSD_MIXER_GRAY) - for(c=0; c<colors; c++) { - if(rgb) - clut[c].r = clut[c].g = clut[c].b = (clut[c].r + clut[c].g + clut[c].b)/3; - else - clut[c].cb = clut[c].cr = 0x80; - } - } - } -} - -// -// 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 CmdPalette(int Wnd, int Colors, unsigned int *Palette); - void CmdMove(int Wnd, int Width, int Height); - void CmdClose(int Wnd); - void CmdFlush(void); - - /* map single OSD window indexes to unique xine-side window handles */ - static uint64_t m_HandlesBitmap; - int *m_WindowHandles; - int AllocWindowHandles(int NumWindows); - void FreeWindowHandles(void); - - protected: - static cMutex m_Lock; - static cList<cXinelibOsd> m_OsdStack; - - bool m_IsVisible; - bool m_Refresh; - uint m_Layer; - uint16_t m_ExtentWidth; - uint16_t m_ExtentHeight; - - 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> cXinelibOsd::m_OsdStack; -cMutex cXinelibOsd::m_Lock; -uint64_t cXinelibOsd::m_HandlesBitmap; - -int cXinelibOsd::AllocWindowHandles(int NumWindows) -{ - uint64_t bit = 1; - int index = 0, wnd = 0; - - FreeWindowHandles(); - m_WindowHandles = new int[NumWindows+1]; - - for (index = 0; index < MAX_OSD_OBJECT; index++) { - if (! (m_HandlesBitmap & bit)) { - m_WindowHandles[wnd++] = index; - m_HandlesBitmap |= bit; - } - if (wnd >= NumWindows) - break; - bit <<= 1; - } - m_WindowHandles[NumWindows] = -1; - - if (wnd < NumWindows) { - LOGMSG("cXinelibOsd::AllocOsdHandles(): Too many open OSD windows !"); - while(wnd < NumWindows) m_WindowHandles[wnd++] = -1; - return 0; - } - - return NumWindows; -} - -void cXinelibOsd::FreeWindowHandles(void) -{ - if (m_WindowHandles) { - int wnd = 0; - while (m_WindowHandles[wnd] >= 0) { - m_HandlesBitmap &= ~( ((uint64_t)1) << m_WindowHandles[wnd]); - wnd++; - } - delete [] m_WindowHandles; - m_WindowHandles = NULL; - } -} - -void cXinelibOsd::CmdSize(int Width, int Height) -{ - TRACEF("cXinelibOsd::CmdSize"); - - if (m_Device) { - osd_command_t osdcmd = {0}; - - for (int Wnd = 0; GetBitmap(Wnd); Wnd++) { - osdcmd.cmd = OSD_Size; - osdcmd.wnd = m_WindowHandles[Wnd]; - osdcmd.w = Width; - osdcmd.h = Height; - - m_Device->OsdCmd((void*)&osdcmd); - } - } -} - -void cXinelibOsd::CmdMove(int Wnd, int NewX, int NewY) -{ - TRACEF("cXinelibOsd::CmdMove"); - - if (m_Device) { - osd_command_t osdcmd = {0}; - - osdcmd.cmd = OSD_Move; - osdcmd.wnd = m_WindowHandles[Wnd]; - osdcmd.x = NewX; - osdcmd.y = NewY; - - m_Device->OsdCmd((void*)&osdcmd); - } -} - -void cXinelibOsd::CmdPalette(int Wnd, int Colors, unsigned int *Palette) -{ - TRACEF("cXinelibOsd::CmdPalette"); - - if (m_Device) { - xine_clut_t clut[Colors]; - osd_command_t osdcmd = {0}; - - osdcmd.cmd = OSD_SetPalette; - osdcmd.wnd = m_WindowHandles[Wnd]; - osdcmd.palette = clut; - osdcmd.colors = Colors; - - prepare_palette(&clut[0], Palette, Colors, /*Top*/(Prev() == NULL), true); - - m_Device->OsdCmd((void*)&osdcmd); - } -} - -void cXinelibOsd::CmdClose(int Wnd) -{ - TRACEF("cXinelibOsd::CmdClose"); - - if (m_Device) { - osd_command_t osdcmd = {0}; - - osdcmd.cmd = OSD_Close; - osdcmd.wnd = m_WindowHandles[Wnd]; - - if (m_Refresh) - osdcmd.flags |= OSDFLAG_REFRESH; - if (Prev() == NULL) - osdcmd.flags |= OSDFLAG_TOP_LAYER; - - m_Device->OsdCmd((void*)&osdcmd); - } -} - -void cXinelibOsd::CmdFlush(void) -{ - TRACEF("cXinelibOsd::CmdFlush"); - - if (m_Device) { - osd_command_t osdcmd = {0}; - - osdcmd.cmd = OSD_Flush; - - 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) { - - xine_clut_t clut[Colors]; - osd_command_t osdcmd = {0}; - - osdcmd.cmd = OSD_Set_RLE; - osdcmd.wnd = m_WindowHandles[Wnd]; - osdcmd.layer = saturate(m_Layer, 0, 0xffff); - osdcmd.x = X0; - osdcmd.y = Y0; - osdcmd.w = W; - osdcmd.h = H; - osdcmd.colors = Colors; - osdcmd.palette = clut; - osdcmd.scaling = xc.osd_scaling; - - if (DirtyArea) - memcpy(&osdcmd.dirty_area, DirtyArea, sizeof(osd_rect_t)); - if (m_Refresh) - osdcmd.flags |= OSDFLAG_REFRESH; - if (xc.osd_blending == OSD_BLENDING_HARDWARE) - osdcmd.flags |= OSDFLAG_UNSCALED; - if (xc.osd_blending_lowresvideo == OSD_BLENDING_HARDWARE) - osdcmd.flags |= OSDFLAG_UNSCALED_LOWRES; - if (Prev() == NULL) - osdcmd.flags |= OSDFLAG_TOP_LAYER; - - prepare_palette(&clut[0], Palette, Colors, /*Top*/(Prev() == NULL), true); - - if (xc.osd_blending_lowresvideo == OSD_BLENDING_HARDWARE) - osdcmd.flags |= OSDFLAG_UNSCALED_LOWRES; - osdcmd.num_rle = rle_compress(&osdcmd.data, Data, W, H); - osdcmd.datalen = 4 * osdcmd.num_rle; - - m_Device->OsdCmd((void*)&osdcmd); - - 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; - m_ExtentWidth = 720; - m_ExtentHeight = 576; - - m_WindowHandles = NULL; -} - -cXinelibOsd::~cXinelibOsd() -{ - TRACEF("cXinelibOsd::~cXinelibOsd"); - - cMutexLock ml(&m_Lock); - - CloseWindows(); - FreeWindowHandles(); - - 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"); - - // Close all existing windows - CloseWindows(); - FreeWindowHandles(); - - eOsdError Result = cOsd::SetAreas(Areas, NumAreas); - - if (Result != oeOk) - return Result; - - // Allocate xine OSD window handles - if (!AllocWindowHandles(NumAreas)) { - FreeWindowHandles(); - return oeTooManyAreas; - } - - // Detect full OSD area size - if(Left() + Width() > 720 || Top() + Height() > 576) { - m_ExtentWidth = Setup.OSDWidth + 2 * Setup.OSDLeft; - m_ExtentHeight = Setup.OSDHeight + 2 * Setup.OSDTop; - LOGDBG("Detected HD OSD, size > %dx%d, using setup values %dx%d", - 2*Left() + Width(), 2*Top() + Height(), - m_ExtentWidth, m_ExtentHeight); - } else { - m_ExtentWidth = 720; - m_ExtentHeight = 576; - } - CmdSize(m_ExtentWidth, m_ExtentHeight); - - return Result; -} - -eOsdError cXinelibOsd::CanHandleAreas(const tArea *Areas, int NumAreas) -{ - TRACEF("cXinelibOsd::CanHandleAreas"); - - eOsdError Result = cOsd::CanHandleAreas(Areas, NumAreas); - - if (Result != oeOk) - return Result; - - if (NumAreas > MAX_OSD_OBJECT) - return oeTooManyAreas; - - for (int i = 0; i < NumAreas; i++) { - if (Areas[i].bpp < 1 || Areas[i].bpp > 8) { - LOGMSG("cXinelibOsd::CanHandleAreas(): invalid bpp (%d)", Areas[i].bpp); - return oeBppNotSupported; - } - } - - // enough free xine OSD windows ? - uint64_t bit = 1; - int windows = NumAreas; - for (int index = 0; index < MAX_OSD_OBJECT && windows > 0; index++) { - if (! (m_HandlesBitmap & bit)) - windows--; - bit <<= 1; - } - if (windows > 0) { - LOGMSG("cXinelibOsd::CanHandleAreas(): not enough free window handles !"); - return oeTooManyAreas; - } - - return oeOk; -} - -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); - if (Colors) { - 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(); - CmdSize(m_ExtentWidth, m_ExtentHeight); - 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); - if (m_WindowHandles[i] < 0) - LOGMSG("Close unallocated OSD %d.%d @%d", Index(), i, m_WindowHandles[i]); - CmdClose(i); - } - } - - if (!m_Refresh) - CmdFlush(); -} - -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 (1/*xc.osd_mixer == OSD_MIXER_NONE*/) { - // hide all but top-most OSD - LOGOSD(" OSD mixer off"); - 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); - } - - } else /*if(xc.osd_mixer > OSD_MIXER_NONE)*/ { - LOGOSD("OSD mixer on (%d)", xc.osd_mixer); - it = cXinelibOsd::m_OsdStack.Last(); - while (cXinelibOsd::m_OsdStack.Prev(it)) { - LOGOSD(" -> show OSD %d", it->Index()); - it->Show(); - 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); - } -} - - - @@ -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 <vdr/osd.h> - -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 61289a12..00000000 --- a/po/cs_CZ.po +++ /dev/null @@ -1,660 +0,0 @@ -# VDR plugin language source file. -# Copyright (C) 2007 Klaus Schmidinger <kls@cadsoft.de> -# This file is distributed under the same license as the VDR package. -# -msgid "" -msgstr "" -"Project-Id-Version: Xineliboutput 1.0.5\n" -"Report-Msgid-Bugs-To: <phintuka@users.sourceforge.net>\n" -"POT-Creation-Date: 2009-06-09 14:45+0300\n" -"PO-Revision-Date: 2008-03-20 23:57+0100\n" -"Last-Translator: Maya <maja373@gmail.com>\n" -"Language-Team: <vdr@linuxtv.org>\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 "Software" -msgstr "softwarové" - -msgid "Hardware" -msgstr "hardwarové" - -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 "none" -msgstr "" - -msgid "nonref" -msgstr "" - -msgid "bidir" -msgstr "" - -msgid "nonkey" -msgstr "" - -msgid "all" -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 "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 "Use Video-Out Driver" -msgstr "" - -msgid "vector" -msgstr "" - -msgid "full" -msgstr "" - -msgid "half (top)" -msgstr "" - -msgid "half (bottom)" -msgstr "" - -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 "Sharpness" -msgstr "" - -msgid "Noise Reduction" -msgstr "" - -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 "DVB subtitle decoder" -msgstr "" - -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 " Max number of clients" -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 "Arrow keys control DVD playback" -msgstr "" - -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 235d564d..00000000 --- a/po/de_DE.po +++ /dev/null @@ -1,659 +0,0 @@ -# VDR plugin language source file. -# Copyright (C) 2007 Klaus Schmidinger <kls@cadsoft.de> -# This file is distributed under the same license as the VDR package. -# Udo Richter -# -msgid "" -msgstr "" -"Project-Id-Version: Xineliboutput 1.0.5\n" -"Report-Msgid-Bugs-To: <phintuka@users.sourceforge.net>\n" -"POT-Creation-Date: 2009-06-09 14:45+0300\n" -"PO-Revision-Date: 2007-11-23 10:17+0200\n" -"Last-Translator: Udo Richter\n" -"Language-Team: <vdr@linuxtv.org>\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 "Software" -msgstr "" - -msgid "Hardware" -msgstr "" - -msgid "no" -msgstr "" - -msgid "grayscale" -msgstr "" - -msgid "transparent" -msgstr "" - -msgid "transparent grayscale" -msgstr "" - -msgid "yes" -msgstr "" - -msgid "nearest" -msgstr "" - -msgid "bilinear" -msgstr "" - -msgid "none" -msgstr "" - -msgid "nonref" -msgstr "" - -msgid "bidir" -msgstr "" - -msgid "nonkey" -msgstr "" - -msgid "all" -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 "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 "Use Video-Out Driver" -msgstr "" - -msgid "vector" -msgstr "" - -msgid "full" -msgstr "" - -msgid "half (top)" -msgstr "" - -msgid "half (bottom)" -msgstr "" - -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 "Sharpness" -msgstr "" - -msgid "Noise Reduction" -msgstr "" - -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 "DVB subtitle decoder" -msgstr "" - -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 " Max number of clients" -msgstr "" - -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 "Arrow keys control DVD playback" -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 054fe580..00000000 --- a/po/fi_FI.po +++ /dev/null @@ -1,660 +0,0 @@ -# VDR plugin language source file. -# Copyright (C) 2007 Klaus Schmidinger <kls@cadsoft.de> -# This file is distributed under the same license as the VDR package. -# Petri Hintukainen -# Rolf Ahrenberg -# -msgid "" -msgstr "" -"Project-Id-Version: Xineliboutput 1.0.5\n" -"Report-Msgid-Bugs-To: <phintuka@users.sourceforge.net>\n" -"POT-Creation-Date: 2009-06-09 14:45+0300\n" -"PO-Revision-Date: 2008-10-06 11:19+0200\n" -"Last-Translator: Rolf Ahrenberg\n" -"Language-Team: <vdr@linuxtv.org>\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\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 "DVB" - -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 "Mono 1.0" - -msgid "Stereo 2.0" -msgstr "Stereo 2.0" - -msgid "Headphones 2.0" -msgstr "Kuulokkeet 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 "läpivienti" - -msgid "very large" -msgstr "erittäin suuri" - -msgid "Software" -msgstr "ohjelmallisesti" - -msgid "Hardware" -msgstr "laitteistolla" - -msgid "no" -msgstr "ei" - -msgid "grayscale" -msgstr "harmaasävy" - -msgid "transparent" -msgstr "läpinäkyvä" - -msgid "transparent grayscale" -msgstr "läpinäkyvä harmaasävy" - -msgid "yes" -msgstr "kyllä" - -msgid "nearest" -msgstr "lähin" - -msgid "bilinear" -msgstr "bilineaarinen" - -msgid "none" -msgstr "ei" - -msgid "nonref" -msgstr "ei referoituja" - -msgid "bidir" -msgstr "vain B-ruudut" - -msgid "nonkey" -msgstr "ei avainruutuja" - -msgid "all" -msgstr "kaikki" - -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 "Kuulokkeiden äänimoodi" - -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 "Käytössä" - -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 "Oletussoittolistaa ei löydetä" - -msgid "Default playlist is not symlink" -msgstr "Oletussoittolista ei ole symbolinen linkki" - -msgid "Default playlist not defined" -msgstr "Oletussoittolistaa ei ole määritelty" - -msgid "Delay" -msgstr "Viive" - -msgid "ms" -msgstr "ms" - -#, c-format -msgid "xineliboutput: hotkey %s not binded" -msgstr "xineliboutput: pikanäppäintä %s ei ole kytketty" - -msgid "Audio" -msgstr "Ääni" - -msgid "Speakers" -msgstr "Kaiuttimet" - -msgid "Volume control" -msgstr "Äänenvoimakkuuden säätö" - -msgid "Mix to headphones" -msgstr "Miksaa kuulokkeille" - -msgid "Visualization" -msgstr "Visualisointi" - -msgid " Width" -msgstr " Leveys" - -msgid "px" -msgstr "px" - -msgid " Height" -msgstr " Korkeus" - -msgid " Speed" -msgstr " Nopeus" - -msgid "fps" -msgstr "fps" - -msgid "Audio Equalizer" -msgstr "Taajuuskorjain" - -msgid "Use Video-Out Driver" -msgstr "videoajuri" - -msgid "vector" -msgstr "vektoroitu" - -msgid "full" -msgstr "täysi" - -msgid "half (top)" -msgstr "alempi puolisko" - -msgid "half (bottom)" -msgstr "ylempi puolisko" - -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 "Sharpness" -msgstr "Terävöinti" - -msgid "Noise Reduction" -msgstr "Kohinanpoisto" - -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 "DVB subtitle decoder" -msgstr "DVB-tekstityksen dekooderi" - -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 " Max number of clients" -msgstr " Asiakkaiden maksimimäärä" - -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 "Arrow keys control DVD playback" -msgstr "Ohjaa nuolinäppäimillä DVD-toistoa" - -msgid "Grayscale" -msgstr "Harmaasävy" - -msgid "Bitmap" -msgstr "Bittikartta" - -msgid "OSD" -msgstr "Kuvaruutunäyttö" - -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 62de6dde..00000000 --- a/po/it_IT.po +++ /dev/null @@ -1,661 +0,0 @@ -# VDR plugin language source file. -# Copyright (C) 2007 Klaus Schmidinger <kls@cadsoft.de> -# This file is distributed under the same license as the VDR package. -# -msgid "" -msgstr "" -"Project-Id-Version: Xineliboutput 1.0.5\n" -"Report-Msgid-Bugs-To: <phintuka@users.sourceforge.net>\n" -"POT-Creation-Date: 2009-09-25 16:04+0300\n" -"PO-Revision-Date: 2009-02-08 20:09+0100\n" -"Last-Translator: Diego Pierotto <vdr-italian@tiscali.it>\n" -"Language-Team: <vdr@linuxtv.org>\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=utf-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Poedit-Language: Italian\n" -"X-Poedit-Country: ITALY\n" -"X-Poedit-SourceCharset: utf-8\n" - -msgid "custom" -msgstr "personalizza" - -msgid "tiny" -msgstr "molto piccola" - -msgid "small" -msgstr "piccola" - -msgid "medium" -msgstr "media" - -msgid "large" -msgstr "grande" - -msgid "huge" -msgstr "enorme" - -msgid "automatic" -msgstr "automatico" - -msgid "default" -msgstr "predefinita" - -msgid "Pan&Scan" -msgstr "Pan&Scan" - -msgid "CenterCutOut" -msgstr "CenterCutOut" - -msgid "square" -msgstr "quadrato" - -msgid "anamorphic" -msgstr "anamorfico" - -msgid "DVB" -msgstr "DVB" - -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 "Software" -msgstr "Software" - -msgid "Hardware" -msgstr "Hardware" - -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 "più vicino" - -msgid "bilinear" -msgstr "bilineare" - -msgid "none" -msgstr "nessuno" - -msgid "nonref" -msgstr "nonref" - -msgid "bidir" -msgstr "bidir" - -msgid "nonkey" -msgstr "nonkey" - -msgid "all" -msgstr "tutti" - -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 "Eliminare immagine ?" - -msgid "Images" -msgstr "Immagini" - -msgid "Play music" -msgstr "Riproduci musica" - -msgid "Add to playlist" -msgstr "Aggiungi alla lista esec." - -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 "Formato" - -msgid "Video aspect ratio" -msgstr "Formato video" - -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 "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 "Use Video-Out Driver" -msgstr "Utilizza driver uscita video" - -msgid "vector" -msgstr "vettoriale" - -msgid "full" -msgstr "intero" - -msgid "half (top)" -msgstr "metà (superiore)" - -msgid "half (bottom)" -msgstr "metà (inferiore)" - -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 "Ridimensionamento software" - -msgid " Change aspect ratio" -msgstr " Cambia formato video" - -msgid " Change video size" -msgstr " Cambia dimensione video" - -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 " Modalità economica" - -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 "Denoiser 3D" - -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 "Sharpness" -msgstr "Nitidezza" - -msgid "Noise Reduction" -msgstr "Riduzione rumore" - -msgid "Smooth fast forward" -msgstr "Avanzamento veloce leggero" - -msgid "Fastest trick speed" -msgstr "Trucco velocità più rapida" - -msgid "On-Screen Display" -msgstr "Messaggi in sovrimpressione (OSD)" - -msgid "Hide main menu" -msgstr "Nascondi voce menu principale" - -msgid "Blending method" -msgstr "Metodo di sfocatura" - -msgid " Use hardware for low-res video" -msgstr " Usa hardware video bassa risoluz." - -msgid "Scaling method" -msgstr "Metodo ridimensione" - -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 "DVB subtitle decoder" -msgstr "Decoder sottotitoli DVB" - -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 " Max number of clients" -msgstr " Numero massimo di client" - -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 file multimediali" - -msgid "Additional network services" -msgstr "Ulteriori servizi di rete" - -msgid "HTTP server" -msgstr "Server HTTP" - -msgid "HTTP clients can control VDR" -msgstr "Controllo VDR da client HTTP" - -msgid "RTSP server" -msgstr "Server RTSP" - -msgid "RTSP clients can control VDR" -msgstr "Controllo VDR da client RTSP" - -msgid "Playlist settings" -msgstr "Impostazioni lista esec." - -msgid "Show the track number" -msgstr "Mostra il numero della traccia" - -msgid "Show the name of the artist" -msgstr "Mostra il nome dell'artista" - -msgid "Show the name of the album" -msgstr "Mostra il nome dell'album" - -msgid "Scan for metainfo" -msgstr "Scansione metainfo" - -msgid "Cache metainfo" -msgstr "Cache metainfo" - -msgid "Arrow keys control DVD playback" -msgstr "Riproduzione DVD con tasti freccia" - -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 aeaf9ab6..00000000 --- a/po/ru_RU.po +++ /dev/null @@ -1,659 +0,0 @@ -# VDR plugin language source file. -# Copyright (C) 2007 Klaus Schmidinger <kls@cadsoft.de> -# This file is distributed under the same license as the VDR package. -# Vladimir Monchenko -# -msgid "" -msgstr "" -"Project-Id-Version: Xineliboutput 1.0.5\n" -"Report-Msgid-Bugs-To: <phintuka@users.sourceforge.net>\n" -"POT-Creation-Date: 2009-06-09 14:45+0300\n" -"PO-Revision-Date: 2007-11-23 10:17+0200\n" -"Last-Translator: Vladimir Monchenko\n" -"Language-Team: <vdr@linuxtv.org>\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 "Software" -msgstr "" - -msgid "Hardware" -msgstr "" - -msgid "no" -msgstr "" - -msgid "grayscale" -msgstr "" - -msgid "transparent" -msgstr "" - -msgid "transparent grayscale" -msgstr "" - -msgid "yes" -msgstr "" - -msgid "nearest" -msgstr "" - -msgid "bilinear" -msgstr "" - -msgid "none" -msgstr "" - -msgid "nonref" -msgstr "" - -msgid "bidir" -msgstr "" - -msgid "nonkey" -msgstr "" - -msgid "all" -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 "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 "Use Video-Out Driver" -msgstr "" - -msgid "vector" -msgstr "" - -msgid "full" -msgstr "" - -msgid "half (top)" -msgstr "" - -msgid "half (bottom)" -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 "Sharpness" -msgstr "" - -msgid "Noise Reduction" -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 "DVB subtitle decoder" -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 " Max number of clients" -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 "Arrow keys control DVD playback" -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/po/zh_CN.po b/po/zh_CN.po deleted file mode 100644 index 2ed8f055..00000000 --- a/po/zh_CN.po +++ /dev/null @@ -1,662 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. -# -msgid "" -msgstr "" -"Project-Id-Version: Xineliboutput 1.0.5\n" -"Report-Msgid-Bugs-To: <phintuka@users.sourceforge.net>\n" -"POT-Creation-Date: 2009-09-25 16:04+0300\n" -"PO-Revision-Date: 2009-09-21 23:32+0800\n" -"Last-Translator: NanFeng <nfgx@21cn.com>\n" -"Language-Team: <vdr@linuxtv.org>\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=utf-8\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 "全景扫æ" - -msgid "CenterCutOut" -msgstr "CenterCutOut" - -msgid "square" -msgstr "广场" - -msgid "anamorphic" -msgstr "å˜å½¢" - -msgid "DVB" -msgstr "DVB" - -msgid "off" -msgstr "å…³" - -msgid "normal" -msgstr "æ£å¸¸" - -msgid "inverted" -msgstr "å转" - -msgid "no audio" -msgstr "没有音频" - -msgid "no video" -msgstr "没有视频" - -msgid "Off" -msgstr "å…³" - -msgid "Goom" -msgstr "Goom" - -msgid "Oscilloscope" -msgstr "示波器" - -msgid "FFT Scope" -msgstr "FFT的范围" - -msgid "FFT Graph" -msgstr "FFT 图åƒ" - -msgid "Mono 1.0" -msgstr "å•å£°é“ 1.0" - -msgid "Stereo 2.0" -msgstr "立体声2.0" - -msgid "Headphones 2.0" -msgstr "耳机2.0" - -msgid "Stereo 2.1" -msgstr "立体声2.1" - -msgid "Surround 3.0" -msgstr "环绕声3.0" - -msgid "Surround 4.0" -msgstr "环绕声4.0" - -msgid "Surround 4.1" -msgstr "环绕声4.1" - -msgid "Surround 5.0" -msgstr "环绕声5.0" - -msgid "Surround 5.1" -msgstr "环绕声5.1" - -msgid "Surround 6.0" -msgstr "环绕声6.0" - -msgid "Surround 6.1" -msgstr "环绕声6.1" - -msgid "Surround 7.1" -msgstr "环绕声7.1" - -msgid "Pass Through" -msgstr "通过" - -msgid "very large" -msgstr "éžå¸¸å¤§" - -msgid "Software" -msgstr "软件" - -msgid "Hardware" -msgstr "硬件" - -msgid "no" -msgstr "å¦" - -msgid "grayscale" -msgstr "ç°åº¦" - -msgid "transparent" -msgstr "逿˜Ž" - -msgid "transparent grayscale" -msgstr "逿˜Žç°åº¦" - -msgid "yes" -msgstr "是" - -msgid "nearest" -msgstr "最近" - -msgid "bilinear" -msgstr "åŒçº¿æ€§" - -msgid "none" -msgstr "æ— " - -msgid "nonref" -msgstr "nonref" - -msgid "bidir" -msgstr "åŒå‘å£" - -msgid "nonkey" -msgstr "nonkey" - -msgid "all" -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 "æ’æ”¾DVD光盘 >>" - -msgid "Play remote CD >>" -msgstr "æ’æ”¾è¿œç¨‹å…‰ç›˜ >>" - -msgid "Play audio CD >>" -msgstr "æ’æ”¾éŸ³ä¹CD >>" - -msgid "Select subtitle track >>" -msgstr "" - -msgid "Video settings" -msgstr "视频设置" - -msgid "Play only audio" -msgstr "åªæ’放声音" - -msgid "Crop letterbox 4:3 to 16:9" -msgstr "选择4:3或者16:9" - -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 "缩混的AC3" - -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 "毫秒" - -#, c-format -msgid "xineliboutput: hotkey %s not binded" -msgstr "xineliboutput的:çƒé”®%sä¸å¯ç»‘定" - -msgid "Audio" -msgstr "音频" - -msgid "Speakers" -msgstr "å–‡å" - -msgid "Volume control" -msgstr "éŸ³é‡æŽ§åˆ¶" - -msgid "Mix to headphones" -msgstr "组åˆï¼Œä»¥è€³æœº" - -msgid "Visualization" -msgstr "å¯è§†åŒ–" - -msgid " Width" -msgstr "宽度" - -msgid "px" -msgstr "px" - -msgid " Height" -msgstr "高度" - -msgid " Speed" -msgstr "速度" - -msgid "fps" -msgstr "帧" - -msgid "Audio Equalizer" -msgstr "音频å‡è¡¡å™¨" - -msgid "Use Video-Out Driver" -msgstr "使用视频输出驱动器" - -msgid "vector" -msgstr "载体" - -msgid "full" -msgstr "å…¨" - -msgid "half (top)" -msgstr "åŠ(上)" - -msgid "half (bottom)" -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 "åŽå¤„ç†ï¼ˆffmpeg)" - -msgid " Quality" -msgstr " Quality" - -msgid " Mode" -msgstr " Mode" - -msgid " Method" -msgstr " Method" - -msgid " Cheap mode" -msgstr " Cheap mode" - -msgid " Pulldown" -msgstr " Pulldown" - -msgid " Frame rate" -msgstr " Frame rate" - -msgid " Judder Correction" -msgstr " Judder Correction" - -msgid " Use progressive frame flag" -msgstr " Use progressive frame flag" - -msgid " Chroma Filter" -msgstr " Chroma Filter" - -msgid "Sharpen / Blur" -msgstr "é”化/模糊" - -msgid " Width of the luma matrix" -msgstr " Width of the luma matrix" - -msgid " Height of the luma matrix" -msgstr " Height of the luma matrix" - -msgid " Amount of luma sharpness/blur" -msgstr " Amount of luma sharpness/blur" - -msgid " Width of the chroma matrix" -msgstr " Width of the chroma matrix" - -msgid " Height of the chroma matrix" -msgstr " Height of the chroma matrix" - -msgid " Amount of chroma sharpness/blur" -msgstr " Amount of chroma sharpness/blur" - -msgid "3D Denoiser" -msgstr "3D噪点去除" - -msgid " Spatial luma strength" -msgstr " Spatial luma strength" - -msgid " Spatial chroma strength" -msgstr " Spatial luma strength" - -msgid " Temporal strength" -msgstr " Temporal strength" - -msgid "HUE" -msgstr "色相" - -msgid "Saturation" -msgstr "饱和度" - -msgid "Contrast" -msgstr "对比度" - -msgid "Brightness" -msgstr "亮度" - -msgid "Sharpness" -msgstr "é”利" - -msgid "Noise Reduction" -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 "DVB subtitle decoder" -msgstr "DVBå—幕解ç 器" - -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 "帧缓冲设备" - -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 " Max number of clients" -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 "TTL" - -msgid " Transmit always on" -msgstr "ä¼ é€æ°¸è¿œåœ¨çº¿" - -msgid " SAP announcements" -msgstr "SAPå…¬å¸å…¬å¸ƒ" - -msgid " Server announce broadcasts" -msgstr "æœåŠ¡å™¨å®£å¸ƒå¹¿æ’" - -msgid " HTTP transport for media files" -msgstr "HTTPä¼ è¾“åª’ä½“æ–‡ä»¶" - -msgid "Additional network services" -msgstr "其他网络æœåŠ¡" - -msgid "HTTP server" -msgstr "HTTPæœåС噍" - -msgid "HTTP clients can control VDR" -msgstr "HTTP客户端å¯ä»¥æŽ§åˆ¶VDR" - -msgid "RTSP server" -msgstr "RTSPæœåС噍" - -msgid "RTSP clients can control VDR" -msgstr "RTSPå议的客户å¯ä»¥æŽ§åˆ¶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 "Arrow keys control DVD playback" -msgstr "å…许按键控制DVD回放" - -msgid "Grayscale" -msgstr "ç°åº¦" - -msgid "Bitmap" -msgstr "ä½å›¾" - -msgid "OSD" -msgstr "èœå•" - -msgid "Media Player" -msgstr "åª’ä½“æ’æ”¾å™¨" - -msgid "Test Images" -msgstr "测试图åƒ" - -msgid "X11/xine-lib output plugin" -msgstr "X11/xine-lib 视频输出æ’ä»¶ by NFVDR-HD" - -#~ msgid "Resolution" -#~ msgstr "解决方案" diff --git a/po/zh_TW.po b/po/zh_TW.po deleted file mode 100644 index b56d1abf..00000000 --- a/po/zh_TW.po +++ /dev/null @@ -1,709 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. -# -msgid "" -msgstr "" -"Project-Id-Version: Xineliboutput 1.0.5\n" -"Report-Msgid-Bugs-To: <phintuka@users.sourceforge.net>\n" -"POT-Creation-Date: 2009-09-25 16:04+0300\n" -"PO-Revision-Date: 2009-09-21 23:32+0800\n" -"Last-Translator: NanFeng <nfgx@21cn.com>\n" -"Language-Team: <vdr@linuxtv.org>\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=utf-8\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 "全景掃æ" - -msgid "CenterCutOut" -msgstr "CenterCutOut" - -msgid "square" -msgstr "å»£å ´" - -msgid "anamorphic" -msgstr "變形" - -msgid "DVB" -msgstr "DVB" - -msgid "off" -msgstr "é—œ" - -msgid "normal" -msgstr "æ£å¸¸" - -msgid "inverted" -msgstr "å轉" - -msgid "no audio" -msgstr "æ²’æœ‰éŸ³é »" - -msgid "no video" -msgstr "æ²’æœ‰è¦–é »" - -msgid "Off" -msgstr "é—œ" - -msgid "Goom" -msgstr "Goom" - -msgid "Oscilloscope" -msgstr "示波器" - -msgid "FFT Scope" -msgstr "FFT的範åœ" - -msgid "FFT Graph" -msgstr "FFT圖åƒ" - -msgid "Mono 1.0" -msgstr "å–®è²é“1.0" - -msgid "Stereo 2.0" -msgstr "ç«‹é«”è²2.0" - -msgid "Headphones 2.0" -msgstr "耳機2.0" - -msgid "Stereo 2.1" -msgstr "ç«‹é«”è²2.1" - -msgid "Surround 3.0" -msgstr "環繞è²3.0" - -msgid "Surround 4.0" -msgstr "環繞è²4.0" - -msgid "Surround 4.1" -msgstr "環繞è²4.1" - -msgid "Surround 5.0" -msgstr "環繞è²5.0" - -msgid "Surround 5.1" -msgstr "環繞è²5.1" - -msgid "Surround 6.0" -msgstr "環繞è²6.0" - -msgid "Surround 6.1" -msgstr "環繞è²6.1" - -msgid "Surround 7.1" -msgstr "環繞è²7.1" - -msgid "Pass Through" -msgstr "通éŽ" - -msgid "very large" -msgstr "éžå¸¸å¤§" - -msgid "Software" -msgstr "軟件" - -msgid "Hardware" -msgstr "硬件" - -msgid "no" -msgstr "å¦" - -msgid "grayscale" -msgstr "ç°åº¦" - -msgid "transparent" -msgstr "逿˜Ž" - -msgid "transparent grayscale" -msgstr "逿˜Žç°åº¦" - -msgid "yes" -msgstr "是" - -msgid "nearest" -msgstr "最近" - -msgid "bilinear" -msgstr "雙線性" - -msgid "none" -msgstr "ç„¡" - -msgid "nonref" -msgstr "nonref" - -msgid "bidir" -msgstr "é›™å‘å£" - -msgid "nonkey" -msgstr "nonkey" - -msgid "all" -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 "æ’æ”¾DVD光盤>>" - -msgid "Play remote CD >>" -msgstr "æ’æ”¾é 程光盤>>" - -msgid "Play audio CD >>" -msgstr "æ’æ”¾éŸ³æ¨‚CD >>" - -msgid "Select subtitle track >>" -msgstr "" - -msgid "Video settings" -msgstr "è¦–é »è¨ç½®" - -msgid "Play only audio" -msgstr "åªæ’放è²éŸ³" - -msgid "Crop letterbox 4:3 to 16:9" -msgstr "鏿“‡4:3或者16:9" - -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 "縮混的AC3" - -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 "毫秒" - -#, c-format -msgid "xineliboutput: hotkey %s not binded" -msgstr "xineliboutput的:熱éµ%sä¸å¯ç¶å®š" - -msgid "Audio" -msgstr "éŸ³é »" - -msgid "Speakers" -msgstr "å–‡å" - -msgid "Volume control" -msgstr "éŸ³é‡æŽ§åˆ¶" - -msgid "Mix to headphones" -msgstr "組åˆï¼Œä»¥è€³æ©Ÿ" - -msgid "Visualization" -msgstr "å¯è¦–化" - -#, fuzzy -msgid " Width" -msgstr "寬度" - -msgid "px" -msgstr "px" - -#, fuzzy -msgid " Height" -msgstr "高度" - -#, fuzzy -msgid " Speed" -msgstr "速度" - -msgid "fps" -msgstr "å¹€" - -msgid "Audio Equalizer" -msgstr "éŸ³é »å‡è¡¡å™¨" - -msgid "Use Video-Out Driver" -msgstr "ä½¿ç”¨è¦–é »è¼¸å‡ºé©…å‹•å™¨" - -msgid "vector" -msgstr "載體" - -msgid "full" -msgstr "å…¨" - -msgid "half (top)" -msgstr "åŠ(上)" - -msgid "half (bottom)" -msgstr "åŠ(下)" - -msgid "Video" -msgstr "è¦–é »" - -#, fuzzy -msgid " Autodetect letterbox" -msgstr "è‡ªå‹•æª¢æ¸¬ç›’åæ¨¡å¼" - -#, fuzzy -msgid " Soft start" -msgstr "軟啟動" - -#, fuzzy -msgid " Crop to" -msgstr "剪è£" - -#, fuzzy -msgid " Detect subtitles" -msgstr "檢測的å—幕" - -msgid "Software scaling" -msgstr "軟件縮放" - -#, fuzzy -msgid " Change aspect ratio" -msgstr "更改寬高比" - -#, fuzzy -msgid " Change video size" -msgstr "æ”¹è®Šè¦–é »å¤§å°" - -#, fuzzy -msgid " Allow downscaling" -msgstr "å…許縮å°å°ºåº¦" - -msgid "Post processing (ffmpeg)" -msgstr "後處ç†ï¼ˆffmpeg)" - -#, fuzzy -msgid " Quality" -msgstr " Quality" - -#, fuzzy -msgid " Mode" -msgstr " Mode" - -#, fuzzy -msgid " Method" -msgstr " Method" - -#, fuzzy -msgid " Cheap mode" -msgstr " Cheap mode" - -#, fuzzy -msgid " Pulldown" -msgstr " Pulldown" - -#, fuzzy -msgid " Frame rate" -msgstr " Frame rate" - -#, fuzzy -msgid " Judder Correction" -msgstr " Judder Correction" - -#, fuzzy -msgid " Use progressive frame flag" -msgstr " Use progressive frame flag" - -#, fuzzy -msgid " Chroma Filter" -msgstr " Chroma Filter" - -msgid "Sharpen / Blur" -msgstr "銳化/模糊" - -#, fuzzy -msgid " Width of the luma matrix" -msgstr " Width of the luma matrix" - -#, fuzzy -msgid " Height of the luma matrix" -msgstr " Height of the luma matrix" - -#, fuzzy -msgid " Amount of luma sharpness/blur" -msgstr " Amount of luma sharpness/blur" - -#, fuzzy -msgid " Width of the chroma matrix" -msgstr " Width of the chroma matrix" - -#, fuzzy -msgid " Height of the chroma matrix" -msgstr " Height of the chroma matrix" - -#, fuzzy -msgid " Amount of chroma sharpness/blur" -msgstr " Amount of chroma sharpness/blur" - -msgid "3D Denoiser" -msgstr "3D噪點去除" - -#, fuzzy -msgid " Spatial luma strength" -msgstr " Spatial luma strength" - -#, fuzzy -msgid " Spatial chroma strength" -msgstr " Spatial luma strength" - -#, fuzzy -msgid " Temporal strength" -msgstr " Temporal strength" - -msgid "HUE" -msgstr "色相" - -msgid "Saturation" -msgstr "飽和度" - -msgid "Contrast" -msgstr "å°æ¯”度" - -msgid "Brightness" -msgstr "亮度" - -msgid "Sharpness" -msgstr "銳利" - -msgid "Noise Reduction" -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 "æ··åˆæ–¹æ³•" - -#, fuzzy -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 "DVB subtitle decoder" -msgstr "DVBå—幕解碼器" - -msgid "Decoder" -msgstr "解碼器" - -msgid "Buffer size" -msgstr "ç·©è¡å€å¤§å°" - -#, fuzzy -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 "幀緩è¡è¨å‚™" - -msgid "Fullscreen mode" -msgstr "免屿¨¡å¼" - -#, fuzzy -msgid " Window width" -msgstr "窗å£å¯¬åº¦" - -#, fuzzy -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 "å…許é 程客戶" - -#, fuzzy -msgid " Listen port (TCP and broadcast)" -msgstr "è½ç«¯å£(TCP和廣æ’)" - -#, fuzzy -msgid " Listen address" -msgstr "åµè½åœ°å€" - -#, fuzzy -msgid " Remote keyboard" -msgstr "é 程éµç›¤" - -#, fuzzy -msgid " Max number of clients" -msgstr "最大數é‡çš„客戶" - -#, fuzzy -msgid " PIPE transport" -msgstr "PIPE傳é€" - -#, fuzzy -msgid " TCP transport" -msgstr "TCP傳é€" - -#, fuzzy -msgid " UDP transport" -msgstr "UDP傳é€" - -#, fuzzy -msgid " RTP (multicast) transport" -msgstr "RTP (組æ’)傳é€" - -#, fuzzy -msgid " Address" -msgstr "地å€" - -#, fuzzy -msgid " Port" -msgstr "端å£" - -#, fuzzy -msgid " TTL" -msgstr "TTL" - -#, fuzzy -msgid " Transmit always on" -msgstr "傳逿°¸é 在線" - -#, fuzzy -msgid " SAP announcements" -msgstr "SAPå…¬å¸å…¬ä½ˆ" - -#, fuzzy -msgid " Server announce broadcasts" -msgstr "æœå‹™å™¨å®£å¸ƒå»£æ’" - -#, fuzzy -msgid " HTTP transport for media files" -msgstr "HTTP傳輸媒體文件" - -msgid "Additional network services" -msgstr "其他網絡æœå‹™" - -msgid "HTTP server" -msgstr "HTTPæœå‹™å™¨" - -msgid "HTTP clients can control VDR" -msgstr "HTTP客戶端å¯ä»¥æŽ§åˆ¶VDR" - -msgid "RTSP server" -msgstr "RTSPæœå‹™å™¨" - -msgid "RTSP clients can control VDR" -msgstr "RTSPå”è°çš„客戶å¯ä»¥æŽ§åˆ¶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 "Arrow keys control DVD playback" -msgstr "å…è¨±æŒ‰éµæŽ§åˆ¶DVD回放" - -msgid "Grayscale" -msgstr "ç°åº¦" - -msgid "Bitmap" -msgstr "ä½åœ–" - -msgid "OSD" -msgstr "èœå–®" - -msgid "Media Player" -msgstr "åª’é«”æ’æ”¾å™¨" - -msgid "Test Images" -msgstr "測試圖åƒ" - -msgid "X11/xine-lib output plugin" -msgstr "X11/xine-libè¦–é »è¼¸å‡ºæ’ä»¶by NFVDR-HD" - -#~ msgid "Resolution" -#~ msgstr "解決方案" diff --git a/setup_menu.c b/setup_menu.c deleted file mode 100644 index 9af9dd54..00000000 --- a/setup_menu.c +++ /dev/null @@ -1,2038 +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.62.2.3 2009-11-16 11:34:49 phintuka Exp $ - * - */ - -#include <vdr/config.h> -#include <vdr/plugin.h> -#include <vdr/remote.h> - -#include "config.h" -#include "device.h" -#include "menuitems.h" -#include "i18n.h" // trVDR for vdr-1.4.x -#include "osd.h" // cXinelibOsdProvider::RefreshOsd() -#include "setup_menu.h" - - -namespace XinelibOutputSetupMenu { - -//#define INTEGER_CONFIG_VIDEO_CONTROLS -//#define LINEAR_VIDEO_CONTROLS -//#define LOGARITHM_SCALING - -#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 -#ifdef LOGARITHM_SCALING -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 }; -#else -const int ind2ctrl_tbl[33] = { - -1, - 0x0000, 0x0843, 0x1085, 0x18c7, 0x2109, 0x294b, 0x318d, 0x39cf, - 0x4211, 0x4a53, 0x5295, 0x5ad7, 0x6319, 0x6b5b, 0x739d, 0x7bdf, - 0x8421, 0x8c63, 0x94a5, 0x9ce7, 0xa529, 0xad6b, 0xb5ad, 0xbdef, - 0xc631, 0xce73, 0xd6b5, 0xdef7, 0xe739, 0xef7b, 0xf7bd, 0xffff -}; -#endif -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<AUDIO_EQ_count; i++) - Add(new cMenuEditTypedIntItem(config_t::s_audioEqNames[i], "%", - &newconfig.audio_equalizer[i], - -100, 100, tr("Off"))); - - if(current<1) current=1; /* first item is not selectable */ - SetCurrent(Get(current)); - Display(); -} - -eOSState cMenuSetupAudioEq::ProcessKey(eKeys Key) -{ - eOSState state = cMenuSetupPage::ProcessKey(Key); - - Key = NORMALKEY(Key); - - if(Key == kLeft || Key == kRight) { - cXinelibDevice::Instance().ConfigurePostprocessing( - xc.deinterlace_method, xc.audio_delay, xc.audio_compression, - newconfig.audio_equalizer, xc.audio_surround, xc.speaker_type); - } - - return state; -} - -void cMenuSetupAudioEq::Store(void) -{ - memcpy(&xc, &newconfig, sizeof(config_t)); - - char tmp[256]; - sprintf(tmp,"%d %d %d %d %d %d %d %d %d %d", - xc.audio_equalizer[0], xc.audio_equalizer[1], - xc.audio_equalizer[2], xc.audio_equalizer[3], - xc.audio_equalizer[4], xc.audio_equalizer[5], - xc.audio_equalizer[6], xc.audio_equalizer[7], - xc.audio_equalizer[8], xc.audio_equalizer[9]); - SetupStore("Audio.Equalizer", tmp); - Setup.Save(); -} - -//--- cMenuSetupVideo -------------------------------------------------------- - -static const char * const tvtime_method[] = - { "use_vo_driver", - "Linear", - "LinearBlend", - "Greedy", - "Greedy2Frame", - "Weave", - "LineDoubler", - "Vertical", - "ScalerBob", - "GreedyH", - "TomsMoComp", - NULL}; - -static const int tvtime_methods_count = (sizeof(tvtime_method)/sizeof(tvtime_method[0]) - 1); - -static const char * const tvtime_method_name[] = - {trNOOP("Use Video-Out Driver"), // "use_vo_driver" - "Linear Interpolation", // "Linear", - "Linear Blend (mplayer)", // "LinearBlend", - "Greedy - Low motion (DScaler)", // "Greedy", - "Greedy 2-frame (DScaler)", // "Greedy2Frame", - "Weave Last Field", // "Weave", - "Line Doubler", // "LineDoubler", - "Vertical Blend (ffmpeg)", // "Vertical", - "Scaler Bob", // "ScalerBob", - "Greedy - High Motion (DScaler)", // "GreedyH", - "Tom's Motion Compensated (DScaler)", // "TomsMoComp", - NULL}; - -static const char * const tvtime_pulldown[] = - { "none", - "vector", - NULL}; - -static const char * const tvtime_pulldown_name[] = - { trNOOP("none"), - trNOOP("vector"), - NULL}; - -static const char * const tvtime_framerate[] = - { "full", - "half_top", - "half_bottom", - NULL}; - -static const char * const tvtime_framerate_name[] = - { trNOOP("full"), - trNOOP("half (top)"), - trNOOP("half (bottom)"), - NULL}; - -struct tvtime_s { - int method; - int cheap_mode; // on/off - int pulldown; // none, vector - int framerate; // full, half_top, half_bottom - int judder_correction; // on/off - int use_progressive_frame_flag; // on/off - int chroma_filter; // on/off - - void Parse(const char *str) - { - cheap_mode = strstr(str, "cheap_mode=1") ? 1 : 0; - pulldown = strstr(str, "pulldown=none") ? 0 : - strstr(str, "pulldown=0") ? 0 : 1; - framerate = strstr(str, "framerate_mode=half_top") ? 1 : - strstr(str, "framerate_mode=1") ? 1 : - strstr(str, "framerate_mode=half_bottom") ? 2 : - strstr(str, "framerate_mode=2") ? 2 : 0; - chroma_filter = strstr(str, "chroma_filter=1") ? 1 : 0; - judder_correction = strstr(str, "judder_correction=0") ? 0 : 1; - use_progressive_frame_flag = strstr(str, "use_progressive_frame_flag=0") ? 0 : 1; - method=1; - const char *m = strstr(str, "method="); - if(m) { - char *tmp = strdup(m + 7); - if(strchr(tmp, ',')) - *strchr(tmp, ',') = 0; - method = strstra(tmp, tvtime_method, 1); - free(tmp); - } - } - - const char *ToString(void) - { - static char buf[256]; - snprintf(buf, sizeof(buf), - "method=%s,cheap_mode=%d,pulldown=%s,framerate_mode=%s," - "judder_correction=%d,use_progressive_frame_flag=%d," - "chroma_filter=%d,enabled=1", - tvtime_method[method], cheap_mode, tvtime_pulldown[pulldown], - tvtime_framerate[framerate], judder_correction, - use_progressive_frame_flag, chroma_filter); - buf[sizeof(buf)-1] = 0; - return buf; - } -}; - -class cMenuSetupVideo : public cMenuSetupPage -{ - private: - config_t newconfig; - - cOsdItem *ctrl_autocrop; - cOsdItem *ctrl_swscale; - cOsdItem *ctrl_swscale_resize; - cOsdItem *ctrl_swscale_aspect; - cOsdItem *ctrl_swscale_width; - cOsdItem *ctrl_swscale_height; - cOsdItem *ctrl_hue; - cOsdItem *ctrl_saturation; - cOsdItem *ctrl_contrast; - cOsdItem *ctrl_brightness; - cOsdItem *ctrl_sharpness; - cOsdItem *ctrl_noise_reduction; - cOsdItem *ctrl_overscan; - cOsdItem *ctrl_pp; - cOsdItem *ctrl_deinterlace; - cOsdItem *ctrl_tvtime_method; - cOsdItem *ctrl_unsharp; - cOsdItem *ctrl_denoise3d; - cOsdItem *ctrl_vo_aspect_ratio; - - int deinterlace; - struct tvtime_s tvtime; - - protected: - virtual void Store(void); - void Set(void); - - public: - cMenuSetupVideo(void); - ~cMenuSetupVideo(void); - - virtual eOSState ProcessKey(eKeys Key); -}; - -cMenuSetupVideo::cMenuSetupVideo(void) -{ - memcpy(&newconfig, &xc, sizeof(config_t)); - - newconfig.hue = CONTROL_TO_INDEX(newconfig.hue); - newconfig.saturation = CONTROL_TO_INDEX(newconfig.saturation); - newconfig.contrast = CONTROL_TO_INDEX(newconfig.contrast); - newconfig.brightness = CONTROL_TO_INDEX(newconfig.brightness); - newconfig.sharpness = CONTROL_TO_INDEX(newconfig.sharpness); - newconfig.noise_reduction = CONTROL_TO_INDEX(newconfig.noise_reduction); - - deinterlace = strstra(xc.deinterlace_method, xc.s_deinterlaceMethods, 0); - - tvtime.Parse(newconfig.deinterlace_opts); - - Set(); -} - -cMenuSetupVideo::~cMenuSetupVideo(void) -{ - cXinelibDevice::Instance().ConfigureVideo(xc.hue, xc.saturation, - xc.brightness, xc.sharpness, - xc.noise_reduction, xc.contrast, - xc.overscan, xc.vo_aspect_ratio); - cXinelibDevice::Instance().ConfigurePostprocessing( - "autocrop", xc.autocrop ? true : false, xc.AutocropOptions()); - cXinelibDevice::Instance().ConfigurePostprocessing( - "swscale", xc.swscale ? true : false, xc.SwScaleOptions()); - cXinelibDevice::Instance().ConfigurePostprocessing( - "pp", xc.ffmpeg_pp ? true : false, xc.FfmpegPpOptions()); - cXinelibDevice::Instance().ConfigurePostprocessing( - "unsharp", xc.unsharp ? true : false, xc.UnsharpOptions()); - cXinelibDevice::Instance().ConfigurePostprocessing( - "denoise3d", xc.denoise3d ? true : false, xc.Denoise3dOptions()); - cXinelibDevice::Instance().ConfigurePostprocessing( - xc.deinterlace_method, xc.audio_delay, xc.audio_compression, - xc.audio_equalizer, xc.audio_surround, xc.speaker_type); -} - -void cMenuSetupVideo::Set(void) -{ - SetPlugin(cPluginManager::GetPlugin(PLUGIN_NAME_I18N)); - int current = Current(); - Clear(); - - Add(NewTitle(tr("Video"))); - - Add(ctrl_vo_aspect_ratio = - new cMenuEditStraI18nItem(tr("Aspect ratio"), &newconfig.vo_aspect_ratio, - VO_ASPECT_count, xc.s_vo_aspects)); - - Add(ctrl_autocrop = - new cMenuEditBoolItem(tr("Crop letterbox 4:3 to 16:9"), - &newconfig.autocrop)); - if(newconfig.autocrop) { - Add(new cMenuEditBoolItem(tr(" Autodetect letterbox"), - &newconfig.autocrop_autodetect)); - Add(new cMenuEditBoolItem(tr(" Soft start"), - &newconfig.autocrop_soft)); - Add(new cMenuEditBoolItem(tr(" Crop to"), - &newconfig.autocrop_fixedsize, - "4:3...20:9", "14:9/16:9")); - Add(new cMenuEditBoolItem(tr(" Detect subtitles"), - &newconfig.autocrop_subs)); - } - - ctrl_swscale_resize = ctrl_swscale_aspect = ctrl_swscale_width = ctrl_swscale_height = NULL; - Add(ctrl_swscale = - new cMenuEditBoolItem(tr("Software scaling"), - &newconfig.swscale)); - if(newconfig.swscale) { - Add(ctrl_swscale_aspect = - new cMenuEditBoolItem(tr(" Change aspect ratio"), - &newconfig.swscale_change_aspect)); - Add(ctrl_swscale_resize = - new cMenuEditBoolItem(tr(" Change video size"), - &newconfig.swscale_resize)); - if(newconfig.swscale_resize) { - Add(ctrl_swscale_width = - new cMenuEditIntItem( tr(" Width"), - &newconfig.swscale_width, 360, 2000)); - Add(ctrl_swscale_height = - new cMenuEditIntItem( tr(" Height"), - &newconfig.swscale_height, 288, 1200)); - Add(new cMenuEditBoolItem(tr(" Allow downscaling"), - &newconfig.swscale_downscale)); - } - } - - Add(ctrl_overscan = - new cMenuEditTypedIntItem(tr("Overscan (crop image borders)"), "%", - &newconfig.overscan, 0, 10, - tr("Off"))); - - Add(ctrl_pp = new cMenuEditBoolItem(tr("Post processing (ffmpeg)"), - &newconfig.ffmpeg_pp)); - if(newconfig.ffmpeg_pp) { - Add(new cMenuEditIntItem( tr(" Quality"), - &newconfig.ffmpeg_pp_quality, 0, 6)); - Add(new cMenuEditStrItem( tr(" Mode"), newconfig.ffmpeg_pp_mode, - 255, OptionsChars)); - } - - Add(ctrl_deinterlace = - new cMenuEditStraI18nItem(tr("Deinterlacing"), &deinterlace, - DEINTERLACE_count, - xc.s_deinterlaceMethodNames)); - - ctrl_tvtime_method = NULL; - if(deinterlace == DEINTERLACE_TVTIME) { - Add(ctrl_tvtime_method = - new cMenuEditStraI18nItem(tr(" Method"), &tvtime.method, - tvtime_methods_count, tvtime_method_name)); - Add(new cMenuEditBoolItem(tr(" Cheap mode"), &tvtime.cheap_mode)); - Add(new cMenuEditStraI18nItem(tr(" Pulldown"), &tvtime.pulldown, - 2, tvtime_pulldown_name)); - Add(new cMenuEditStraI18nItem(tr(" Frame rate"), &tvtime.framerate, - 3, tvtime_framerate_name)); - Add(new cMenuEditBoolItem(tr(" Judder Correction"), &tvtime.judder_correction)); - Add(new cMenuEditBoolItem(tr(" Use progressive frame flag"), - &tvtime.use_progressive_frame_flag)); - Add(new cMenuEditBoolItem(tr(" Chroma Filter"), - &tvtime.chroma_filter)); - } - - Add(ctrl_unsharp = new cMenuEditBoolItem(tr("Sharpen / Blur"), - &newconfig.unsharp)); - if(newconfig.unsharp) { - Add(new cMenuEditOddIntItem( tr(" Width of the luma matrix"), - &newconfig.unsharp_luma_matrix_width, 3, 11)); - Add(new cMenuEditOddIntItem( tr(" Height of the luma matrix"), - &newconfig.unsharp_luma_matrix_height, 3, 11)); - Add(new cMenuEditFpIntItem( tr(" Amount of luma sharpness/blur"), - &newconfig.unsharp_luma_amount, -20, 20, 1, - tr("Off"))); - Add(new cMenuEditOddIntItem( tr(" Width of the chroma matrix"), - &newconfig.unsharp_chroma_matrix_width, 3, 11)); - Add(new cMenuEditOddIntItem( tr(" Height of the chroma matrix"), - &newconfig.unsharp_chroma_matrix_height, 3, 11)); - Add(new cMenuEditFpIntItem( tr(" Amount of chroma sharpness/blur"), - &newconfig.unsharp_chroma_amount, -20, 20, 1, - tr("Off"))); - } - - Add(ctrl_denoise3d = new cMenuEditBoolItem(tr("3D Denoiser"), - &newconfig.denoise3d)); - if(newconfig.denoise3d) { - Add(new cMenuEditFpIntItem( tr(" Spatial luma strength"), - &newconfig.denoise3d_luma, 0, 100, 1)); - Add(new cMenuEditFpIntItem( tr(" Spatial chroma strength"), - &newconfig.denoise3d_chroma, 0, 100, 1)); - Add(new cMenuEditFpIntItem( tr(" Temporal strength"), - &newconfig.denoise3d_time, 0, 100, 1)); - } - - -#ifdef INTEGER_CONFIG_VIDEO_CONTROLS - Add(new cMenuEditIntItem(tr("HUE"), &newconfig.hue, -1, 0xffff)); - Add(new cMenuEditIntItem(tr("Saturation"), &newconfig.saturation,-1,0xffff)); - Add(new cMenuEditIntItem(tr("Contrast"), &newconfig.contrast, -1, 0xffff)); - Add(new cMenuEditIntItem(tr("Brightness"), &newconfig.brightness,-1,0xffff)); - Add(new cMenuEditIntItem(tr("Sharpness"), &newconfig.sharpness, -1,0xffff)); - Add(new cMenuEditIntItem(tr("Noise Reduction"), &newconfig.noise_reduction, -1,0xffff)); -#else - Add(ctrl_hue = new cMenuEditStraItem(tr("HUE"), &newconfig.hue, 33, - controls)); - Add(ctrl_saturation = - new cMenuEditStraItem(tr("Saturation"), &newconfig.saturation, 33, - controls)); - Add(ctrl_contrast = - new cMenuEditStraItem(tr("Contrast"), &newconfig.contrast, 33, - controls)); - Add(ctrl_brightness = - new cMenuEditStraItem(tr("Brightness"), &newconfig.brightness, 33, - controls)); - Add(ctrl_sharpness = - new cMenuEditStraItem(tr("Sharpness"), &newconfig.sharpness, 33, - controls)); - Add(ctrl_noise_reduction = - new cMenuEditStraItem(tr("Noise Reduction"), &newconfig.noise_reduction, 33, - controls)); -#endif - -#ifdef DEVICE_SUPPORTS_IBP_TRICKSPEED - Add(new cMenuEditBoolItem(tr("Smooth fast forward"), - &newconfig.ibp_trickspeed)); -#endif - Add(new cMenuEditIntItem(tr("Fastest trick speed"), - &newconfig.max_trickspeed, 1, 12)); - - if(current<1) current=1; /* first item is not selectable */ - SetCurrent(Get(current)); - //SetCurrent(Get(1)); - Display(); -} - -eOSState cMenuSetupVideo::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_hue || item == ctrl_saturation || - item == ctrl_sharpness || item == ctrl_noise_reduction || - item == ctrl_contrast || item == ctrl_brightness || - item == ctrl_overscan || item == ctrl_vo_aspect_ratio) -#ifdef INTEGER_CONFIG_VIDEO_CONTROLS - cXinelibDevice::Instance().ConfigureVideo(newconfig.hue, - newconfig.saturation, - newconfig.brightness, - newconfig.sharpness, - newconfig.noise_reduction, - newconfig.contrast, - newconfig.overscan, - newconfig.vo_aspect_ratio); -#else - cXinelibDevice::Instance().ConfigureVideo( - INDEX_TO_CONTROL(newconfig.hue), - INDEX_TO_CONTROL(newconfig.saturation), - INDEX_TO_CONTROL(newconfig.brightness), - INDEX_TO_CONTROL(newconfig.sharpness), - INDEX_TO_CONTROL(newconfig.noise_reduction), - INDEX_TO_CONTROL(newconfig.contrast), - newconfig.overscan, newconfig.vo_aspect_ratio); -#endif - else if(item == ctrl_autocrop) { - cXinelibDevice::Instance().ConfigurePostprocessing( - "autocrop", newconfig.autocrop ? true : false, - newconfig.AutocropOptions()); - Set(); - } - else if(item == ctrl_swscale || - item == ctrl_swscale_resize || - item == ctrl_swscale_aspect || - item == ctrl_swscale_width || - item == ctrl_swscale_height) { - cXinelibDevice::Instance().ConfigurePostprocessing( - "swscale", newconfig.swscale ? true : false, - newconfig.SwScaleOptions()); - Set(); - } - else if(item == ctrl_pp) { - cXinelibDevice::Instance().ConfigurePostprocessing( - "pp", newconfig.ffmpeg_pp ? true : false, - newconfig.FfmpegPpOptions()); - Set(); - } - else if(item == ctrl_unsharp) { - cXinelibDevice::Instance().ConfigurePostprocessing( - "unsharp", newconfig.unsharp ? true : false, - newconfig.UnsharpOptions()); - Set(); - } - else if(item == ctrl_denoise3d) { - cXinelibDevice::Instance().ConfigurePostprocessing( - "denoise3d", newconfig.denoise3d ? true : false, - newconfig.Denoise3dOptions()); - Set(); - } - else if(item == ctrl_deinterlace) { - if(deinterlace == DEINTERLACE_TVTIME && !ctrl_tvtime_method) { - Set(); - } else if(deinterlace != DEINTERLACE_TVTIME && ctrl_tvtime_method) { - Set(); - } - } - - return state; -} - -void cMenuSetupVideo::Store(void) -{ - memcpy(&xc, &newconfig, sizeof(config_t)); - -#ifdef INTEGER_CONFIG_VIDEO_CONTROLS -#else - xc.hue = INDEX_TO_CONTROL(xc.hue); - xc.saturation = INDEX_TO_CONTROL(xc.saturation); - xc.contrast = INDEX_TO_CONTROL(xc.contrast); - xc.brightness = INDEX_TO_CONTROL(xc.brightness); - xc.sharpness = INDEX_TO_CONTROL(xc.sharpness); - xc.noise_reduction = INDEX_TO_CONTROL(xc.noise_reduction); -#endif - - strn0cpy(xc.deinterlace_method, xc.s_deinterlaceMethods[deinterlace], sizeof(xc.deinterlace_method)); - strn0cpy(xc.deinterlace_opts, tvtime.ToString(), sizeof(xc.deinterlace_opts)); - SetupStore("Video.Deinterlace", xc.deinterlace_method); - SetupStore("Video.DeinterlaceOptions", xc.deinterlace_opts); - - SetupStore("Video.AutoCrop", xc.autocrop); - SetupStore("Video.AutoCrop.AutoDetect", xc.autocrop_autodetect); - SetupStore("Video.AutoCrop.SoftStart", xc.autocrop_soft); - SetupStore("Video.AutoCrop.FixedSize", xc.autocrop_fixedsize); - SetupStore("Video.AutoCrop.DetectSubs", xc.autocrop_subs); - SetupStore("Video.SwScale", xc.swscale); - SetupStore("Video.SwScale.Aspect", xc.swscale_change_aspect); - SetupStore("Video.SwScale.Resize", xc.swscale_resize); - SetupStore("Video.SwScale.Width", xc.swscale_width); - SetupStore("Video.SwScale.Height", xc.swscale_height); - SetupStore("Video.SwScale.Downscale", xc.swscale_downscale); - SetupStore("Video.HUE", xc.hue); - SetupStore("Video.Saturation", xc.saturation); - SetupStore("Video.Contrast", xc.contrast); - SetupStore("Video.Brightness", xc.brightness); - SetupStore("Video.Sharpness", xc.sharpness); - SetupStore("Video.NoiseReduction", xc.noise_reduction); - SetupStore("Video.Overscan", xc.overscan); - SetupStore("Video.IBPTrickSpeed", xc.ibp_trickspeed); - SetupStore("Video.MaxTrickSpeed", xc.max_trickspeed); - SetupStore("Video.AspectRatio", xc.vo_aspect_ratio); - SetupStore("Post.pp.Enable", xc.ffmpeg_pp); - SetupStore("Post.pp.Quality", xc.ffmpeg_pp_quality); - SetupStore("Post.pp.Mode", xc.ffmpeg_pp_mode); - SetupStore("Post.unsharp.Enable", xc.unsharp); - SetupStore("Post.unsharp.luma_matrix_width", xc.unsharp_luma_matrix_width); - SetupStore("Post.unsharp.luma_matrix_height", xc.unsharp_luma_matrix_height); - SetupStore("Post.unsharp.luma_amount", xc.unsharp_luma_amount); - SetupStore("Post.unsharp.chroma_matrix_width", xc.unsharp_chroma_matrix_width); - SetupStore("Post.unsharp.chroma_matrix_height", xc.unsharp_chroma_matrix_height); - SetupStore("Post.unsharp.chroma_amount", xc.unsharp_chroma_amount); - SetupStore("Post.denoise3d.Enable", xc.denoise3d); - SetupStore("Post.denoise3d.luma", xc.denoise3d_luma); - SetupStore("Post.denoise3d.chroma", xc.denoise3d_chroma); - SetupStore("Post.denoise3d.time", xc.denoise3d_time); - SetupStore("Video.Decoder.MPEG2", xc.s_decoders_MPEG2[xc.decoder_mpeg2]); - SetupStore("Video.Decoder.H264", xc.s_decoders_H264[xc.decoder_h264]); -#if 1 - // delete old keys (<1.0.0) - SetupStore("Video.AutoScale"); -#endif - Setup.Save(); -} - - -//--- cMenuSetupOSD ---------------------------------------------------------- - -class cMenuSetupOSD : public cMenuSetupPage -{ - private: - config_t newconfig; - - int orig_alpha_correction; - int orig_alpha_correction_abs; - - cOsdItem *ctrl_scaling; - cOsdItem *ctrl_alpha; - cOsdItem *ctrl_alpha_abs; - cOsdItem *ctrl_blending; - cOsdItem *ctrl_lowres; -#if VDRVERSNUM < 10515 - cOsdItem *ctrl_spulang0; -#endif - - protected: - virtual void Store(void); - void Set(void); - - public: - cMenuSetupOSD(void); - ~cMenuSetupOSD(); - - virtual eOSState ProcessKey(eKeys Key); -}; - -cMenuSetupOSD::cMenuSetupOSD(void) -{ - memcpy(&newconfig, &xc, sizeof(config_t)); - orig_alpha_correction = xc.alpha_correction; - orig_alpha_correction_abs = xc.alpha_correction_abs; - newconfig.extsub_size++; - - Set(); -} - -cMenuSetupOSD::~cMenuSetupOSD() -{ - xc.alpha_correction = orig_alpha_correction; - xc.alpha_correction_abs = orig_alpha_correction_abs; -} - -void cMenuSetupOSD::Set(void) -{ - SetPlugin(cPluginManager::GetPlugin(PLUGIN_NAME_I18N)); - int current = Current(); - Clear(); - - ctrl_scaling = NULL; - ctrl_blending = NULL; - ctrl_lowres = NULL; - ctrl_alpha = NULL; - ctrl_alpha_abs = NULL; -#if VDRVERSNUM < 10515 - ctrl_spulang0 = NULL; -#endif - - Add(NewTitle(tr("On-Screen Display"))); - Add(new cMenuEditBoolItem(tr("Hide main menu"), - &newconfig.hide_main_menu)); - - Add(ctrl_blending = - new cMenuEditBoolItem(tr("Blending method"), - &newconfig.osd_blending, - tr(xc.s_osdBlendingMethods[OSD_BLENDING_SOFTWARE]), - tr(xc.s_osdBlendingMethods[OSD_BLENDING_HARDWARE]))); - if(newconfig.osd_blending == OSD_BLENDING_SOFTWARE) { - Add(ctrl_lowres = - new cMenuEditBoolItem(tr(" Use hardware for low-res video"), - &newconfig.osd_blending_lowresvideo)); - } - - Add(ctrl_scaling = - new cMenuEditStraI18nItem(tr("Scaling method"), &newconfig.osd_scaling, - OSD_SCALING_count, xc.s_osdScalings)); - -#if VDRVERSNUM >= 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 VDRVERSNUM >= 10510 - Add(new cMenuEditBoolItem(tr("DVB subtitle decoder"), - &newconfig.dvb_subtitles, - "VDR", - "frontend")); -#endif - - 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.osd_blending==OSD_BLENDING_SOFTWARE && !ctrl_lowres) - Set(); - if(newconfig.osd_blending!=OSD_BLENDING_SOFTWARE && 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.Blending", xc.osd_blending); - SetupStore("OSD.BlendingLowRes", xc.osd_blending_lowresvideo); -#if 1 - // Delete old keys (<=1.0.0) - SetupStore("OSD.UnscaledAlways"); - SetupStore("OSD.UnscaledLowRes"); - SetupStore("OSD.UnscaledOpaque"); - SetupStore("OSD.Prescale"); - SetupStore("OSD.Downscale"); -#endif - 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 - SetupStore("OSD.DvbSubtitles", xc.dvb_subtitles); - - 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 1 - // delete old keys (<1.0.0) - SetupStore("Decoder.Priority"); - SetupStore("Decoder.InactivityTimer"); -#endif - - 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 cMenuEditIntItem( tr(" Max number of clients"), - &newconfig.remote_max_clients, - 1, MAXCLIENTS)); - - 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.MaxClients", xc.remote_max_clients); - 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)); - - Add(new cMenuEditBoolItem(tr("Arrow keys control DVD playback"), - &newconfig.dvd_arrow_keys_control_playback)); - - Add(NewTitle(tr("Media Player"))); - Add(new cMenuEditBitItem(tr("Play file >>"), &newconfig.media_menu_items, MEDIA_MENU_FILES)); - Add(new cMenuEditBitItem(tr("Play music >>"), &newconfig.media_menu_items, MEDIA_MENU_MUSIC)); - Add(new cMenuEditBitItem(tr("View images >>"), &newconfig.media_menu_items, MEDIA_MENU_IMAGES)); - Add(new cMenuEditBitItem(tr("Play DVD disc >>"), &newconfig.media_menu_items, MEDIA_MENU_DVD)); - Add(new cMenuEditBitItem(tr("Play audio CD >>"), &newconfig.media_menu_items, MEDIA_MENU_CD)); - Add(new cMenuEditBitItem(tr("Play BluRay disc >>"), &newconfig.media_menu_items, MEDIA_MENU_BLURAY)); - Add(new cMenuEditBitItem(tr("Video settings"), &newconfig.media_menu_items, MEDIA_MENU_VIDEO_SETUP)); - Add(new cMenuEditBitItem(tr("Audio settings"), &newconfig.media_menu_items, MEDIA_MENU_AUDIO_SETUP)); - - 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); - SetupStore("Media.DVD.ArrowKeysControlPlayback", xc.dvd_arrow_keys_control_playback); - SetupStore("Media.MenuItems", xc.media_menu_items); - - Setup.Save(); -} - -} // namespace - - -//--- cMenuTestImages ------------------------------------------------------ - -#include <vdr/osdbase.h> - -#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; x<OSD_W;x++) { - m_Osd->DrawPixel(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, xc.sharpness, xc.noise_reduction, 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, xc.sharpness, xc.noise_reduction, 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; x<OSD_W; x+=bpp) { - bit = (x/bpp) & 1; - for(y=0; y<OSD_H; y+=bpp) { - m_Osd->DrawRectangle(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 <vdr/remote.h> // 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 <vdr/menuitems.h> - -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 480325f0..00000000 --- a/tools.c +++ /dev/null @@ -1,24 +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.2 2009-01-27 09:25:22 phintuka Exp $ - * - */ - -#define __STDC_CONSTANT_MACROS -#include <stdint.h> -#define __STDC_FORMAT_MACROS -#include <inttypes.h> - -#include <vdr/tools.h> -#include "logdefs.h" - -//#include "tools/vdrdiscovery.c" - -#include "tools/pes.c" -#include "tools/mpeg.c" -#include "tools/h264.c" -#include "tools/ts.c" diff --git a/tools/backgroundwriter.c b/tools/backgroundwriter.c deleted file mode 100644 index 6b7c8ff4..00000000 --- a/tools/backgroundwriter.c +++ /dev/null @@ -1,500 +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.18 2009-07-24 18:11:20 phintuka Exp $ - * - */ - -#define __STDC_FORMAT_MACROS -#define __STDC_CONSTANT_MACROS -#include <inttypes.h> - -#include <stdint.h> -#include <unistd.h> -#include <netinet/tcp.h> // CORK, NODELAY - -#include <vdr/tools.h> -#include <vdr/config.h> // VDRVERSNUM - -#include "../logdefs.h" -#include "../xine_input_vdr_net.h" // stream_tcp_header_t -#include "ts.h" -#include "pes.h" - -#include "backgroundwriter.h" - - -#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_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() -{ - 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; -} - -void cBackgroundWriterI::Cork(void) -{ - if (m_IsSocket) { -#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 - } -} - -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 && - Running() && - m_RingBuffer.Available() > 0) - cCondWait::SleepMs(3); - } - - int Available = m_RingBuffer.Available(); - if(m_IsSocket && Available <= 0) { - // flush corked data too - Cork(); - } - - return 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 = 0; - uint64_t GetPos = 0; - cPoller Poller (m_fd, true); - bool CorkReq = false; - - while (Running()) { - - if(Poller.Poll(100)) { - - if (CorkReq && m_RingBuffer.Available() <= 0) { - // Force TCP packet to avoid delaying control messages - Cork(); - CorkReq = false; - } - - uint64_t StartPos; - int Count = 0; - int n; - uchar *Data = m_RingBuffer.Get(Count); - - if(Data && Count > 0) { - - Lock(); // uint64_t m_DiscardStart can not be read atomically (IA32) - StartPos = m_DiscardEnd; - Unlock(); - - // Discard data ? - if(StartPos > GetPos) { - if(NextHeaderPos == GetPos) { - // we're at frame boundary - // drop only data packets, not control messages - uint8_t *pkt = TCP_PAYLOAD(Data); - if (DATA_IS_PES(pkt) || DATA_IS_TS(pkt)) { - Count = min(Count, (int)(StartPos - GetPos)); - - // size of next (complete) packet. - // drop only one packet at time. - stream_tcp_header_t *header = (stream_tcp_header_t*)Data; - int pkt_len = ntohl(header->len) + sizeof(stream_tcp_header_t); - if (Count >= pkt_len) { - // drop only complete packets. - // some packets are not dropped (packets overlapping end of ringbuffer) - Count = pkt_len; - - m_RingBuffer.Del(Count); - GetPos += Count; - NextHeaderPos = GetPos; - - CorkReq = true; // force sending last frame - - continue; - } - } - } - } - - // Next frame ? - if(GetPos == NextHeaderPos) { - if(Count < (int)sizeof(stream_tcp_header_t)) - LOGMSG("cBackgroundWriter @NextHeaderPos: Count < header size !"); - - // limit single write to size of next (complete) packet. - // (we need to track packet boundaries) - stream_tcp_header_t *header = (stream_tcp_header_t*)Data; - int pkt_len = ntohl(header->len) + sizeof(stream_tcp_header_t); - if (Count > pkt_len) - Count = pkt_len; - // next packet start position in stream - NextHeaderPos = GetPos + pkt_len; - - // check for control message - uint8_t *pkt = TCP_PAYLOAD(Data); - if (!DATA_IS_PES(pkt) && !DATA_IS_TS(pkt)) - CorkReq = true; - - } else { - Count = min(Count, (int)(NextHeaderPos-GetPos)); - } - - 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 " - <<m_fd<<" - retrying"); - continue; - - } else { - LOGERR("cBackgroundWriter: TCP write error"); - break; - } - } - - GetPos += n; - m_RingBuffer.Del(n); - } - } - } - - m_RingBuffer.Clear(); -} - -int cTcpWriter::Put(uint64_t StreamPos, - const uchar *Data, int DataCount) -{ - stream_tcp_header_t header; - header.pos = htonull(StreamPos); - header.len = htonl(DataCount); - return Put((uchar*)&header, sizeof(header), Data, DataCount); -} - -int cTcpWriter::Put(const uchar *Header, int HeaderCount, - const uchar *Data, int DataCount) -{ - if (Running()) { - - // Serialize Put access to keep Data and Header together - LOCK_THREAD; - - if(m_RingBuffer.Free() < HeaderCount+DataCount) { - //LOGMSG("cXinelibServer: TCP buffer overflow !"); - if(m_BufferOverflows++ > MAX_OVERFLOWS_BEFORE_DISCONNECT) { - LOGMSG("cXinelibServer: Too many TCP buffer overflows, dropping client"); - m_RingBuffer.Clear(); - Cancel(-1); - 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(); - Cancel(-1); - } - - return 0; -} - - -// -// cRawWriter -// - -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 (Running()) { - - if(Poller.Poll(100)) { - - uint64_t StartPos; - int Count = 0; - int n; - uchar *Data = m_RingBuffer.Get(Count); - - if(Data && Count > 0) { - - Lock(); // uint64_t m_DiscardStart can not be read atomically (IA32) - StartPos = m_DiscardEnd; - Unlock(); - - // Discard data ? - if(StartPos > GetPos) { - if(NextHeaderPos == GetPos) { - // we're at frame boundary - Count = min(Count, (int)(StartPos - GetPos)); - - m_RingBuffer.Del(Count); - GetPos += Count; - NextHeaderPos = GetPos; - continue; - } - } - - // Next frame ? - if(GetPos == NextHeaderPos) { - if(Count < 6) - LOGMSG("cBackgroundWriter @NextHeaderPos: Count < header size !"); - - int packlen = DATA_IS_TS(Data) ? TS_SIZE : 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)); - } - - 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 " - <<m_fd<<" - retrying"); - continue; - - } else { - LOGERR("cBackgroundWriter: TCP write error"); - break; - } - } - - GetPos += n; - m_RingBuffer.Del(n); - } - } - } - - m_RingBuffer.Clear(); -} - -int cRawWriter::Put(uint64_t StreamPos, - const uchar *Data, int DataCount) -{ - if (Running()) { - - // Serialize Put access to keep Data and Header together - LOCK_THREAD; - - if(m_RingBuffer.Free() < DataCount) { - if(m_BufferOverflows++ > MAX_OVERFLOWS_BEFORE_DISCONNECT) { - LOGMSG("cXinelibServer: Too many TCP buffer overflows, dropping client"); - m_RingBuffer.Clear(); - Cancel(-1); - 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(); - Cancel(-1); - } - - 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 d0ee5b30..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.6 2009-07-24 05:24:22 phintuka Exp $ - * - */ - -#ifndef __BACKGROUNDWRITER_H -#define __BACKGROUNDWRITER_H - -#include <stdint.h> - -#include <vdr/thread.h> -#include <vdr/ringbuffer.h> - -// -// cBackgroundWriterI -// - generic interface for buffered output -// -class cBackgroundWriterI : public cThread -{ - protected: - cRingBufferLinear m_RingBuffer; - - 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; - void Cork(void); - - 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 569c491b..00000000 --- a/tools/bitstream.h +++ /dev/null @@ -1,175 +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.3 2009-02-14 20:44:15 phintuka Exp $ - * - */ - -#ifndef _XINELIBOUTPUT_BITSTREAM_H_ -#define _XINELIBOUTPUT_BITSTREAM_H_ - - -# 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<<n) - 1); -} - -static inline int br_get_bit(br_state *br) -{ - if(!br->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<<n) - 1) + br_get_bits(br, n) : 0; -} - -static inline int32_t br_get_se_golomb(br_state *br) -{ - uint32_t r = br_get_ue_golomb(br) + 1; - return (r&1) ? -(r>>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 <inttypes.h> - -#include <stdlib.h> -#include <stdarg.h> -#include <errno.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/ioctl.h> -#ifndef __APPLE__ -# include <sys/sendfile.h> -#endif -#include <netinet/tcp.h> - -#include <vdr/config.h> -#include <vdr/tools.h> - -#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 <sys/ioctl.h> -#include <net/if.h> - -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; n<conf.ifc_len/sizeof(struct ifreq); n++) { - struct sockaddr_in *in = (struct sockaddr_in *) &buf[n].ifr_addr; -# if 0 - uint32_t tmp = ntohl(in->sin_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 <inttypes.h> -#include <sys/types.h> -#include <sys/socket.h> - -#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 <vdr/tools.h> - -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<count; i++) - Add(Socks[i].handle(), Out); - } -}; - -// -// Set socket buffers -// -static inline void set_socket_buffers(int s, int txbuf, int rxbuf) -{ - int max_buf = txbuf; - /*while(max_buf) {*/ - errno = 0; - if(setsockopt(s, SOL_SOCKET, SO_SNDBUF, &max_buf, sizeof(int))) { - LOGERR("setsockopt(SO_SNDBUF,%d) failed", max_buf); - /*max_buf >>= 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<MAX_DBG_MUTEX; i++) - if(dbgdata[i].lock == mutex) { - dbgdata[i].line = line; - dbgdata[i].tid = syscall(__NR_gettid); - return; - } - - LOGMSG("********** dbg_setdata: new entry (0x%lx at %d)", (unsigned long int)mutex, line); - for(i=0; i<MAX_DBG_MUTEX; i++) - if(!dbgdata[i].lock) { - dbgdata[i].lock = mutex; - dbgdata[i].line = line; - dbgdata[i].tid = syscall(__NR_gettid); - return; - } - - LOGMSG("********** dbg_setdata: table full !"); -} - -static int dbg_getdata(pthread_mutex_t *mutex, int line) -{ - int i; - for(i=0; i<MAX_DBG_MUTEX; i++) - if(dbgdata[i].lock == mutex) - return dbgdata[i].line; - - LOGMSG("********** dbg_getdata: NO ENTRY ! (%d)", line); - return -1; -} - -static void dbg_deldata(pthread_mutex_t *mutex, int line) -{ - int i; - for(i=0; i<MAX_DBG_MUTEX; i++) - if(dbgdata[i].lock == mutex) { - dbgdata[i].lock = NULL; - return; - } - - LOGMSG("********** dbg_deldata: NO ENTRY ! (%d)", line); - return; -} - -static int dbg_init(pthread_mutex_t *mutex, pthread_mutexattr_t *pattr, int line) -{ - int r; - - errno = 0; - if(!pattr) { - pthread_mutexattr_t attr; - pthread_mutexattr_init(&attr); - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK_NP); - r = pthread_mutex_init(mutex, &attr); - } else { - LOGMSG("********** dbg_init: mutex attribute already given !"); - r = pthread_mutex_init(mutex, pattr); - } - - if(r) - LOGERR("********** dbg_init: pthread_mutex_init FAILED at %d", line); - - dbg_setdata(mutex, line); - - return r; -} - -static int dbg_free(pthread_mutex_t *mutex, int line) -{ - int r; - - errno = 0; - r = pthread_mutex_destroy(mutex); - - if(r) - LOGERR("********** dbg_free: pthread_mutex_destroy FAILED at %d ; last lock at %d", - line, dbg_getdata(mutex, line)); - dbg_deldata(mutex, line); - - return r; -} - -static int dbg_lock(pthread_mutex_t *mutex, int line) -{ - int r; - /*struct timespec abs_timeout;*/ - - /* try lock first to reduce logging */ - errno = 0; - r = pthread_mutex_trylock(mutex); - if(!r) { - dbg_setdata(mutex,line); - return r; - } - - /* try failed - we're going to wait, so log at wait start and end to detect deadlocks */ - LOGERR("********** dbg_lock: pthread_mutex_trylock failed at %d (locked at %d)", - line, dbg_getdata(mutex, line)); - - /* int pthread_mutex_timedlock(pthread_mutex_t *restrict mutex, - const struct timespec *restrict abs_timeout); */ - - errno = 0; - r = pthread_mutex_lock(mutex); - - if(r) - LOGERR("********** dbg_lock: pthread_mutex_lock FAILED at %d", line); - - dbg_setdata(mutex, line); - LOGMSG("********** dbg_lock: pthread_mutex_lock done at %d", line); - - return r; -} - -static int dbg_trylock(pthread_mutex_t *mutex, int line) -{ - int r; - /*struct timespec abs_timeout;*/ - - /* try lock first to reduce logging */ - errno = 0; - r = pthread_mutex_trylock(mutex); - if(!r) { - dbg_setdata(mutex,line); - return r; - } - - LOGERR("********** dbg_trylock: pthread_mutex_trylock failed at %d (locked at %d)", - line, dbg_getdata(mutex, line)); - - return r; -} - -static int dbg_unlock(pthread_mutex_t *mutex, int line) -{ - int r; - - errno = 0; - r = pthread_mutex_unlock(mutex); - - if(r) - LOGERR("********** dbg_unlock: pthread_mutex_unlock FAILED at %d (last locket at %d)", - line, dbg_getdata(mutex, line)); - - //else - // dbg_setdata(mutex, 0); - - return r; -} - -/* override pthread_ functions with own ones */ -#define pthread_mutex_init(l,a) dbg_init(l, a, __LINE__) -#define pthread_mutex_lock(l) dbg_lock(l, __LINE__) -#define pthread_mutex_trylock(l) dbg_trylock(l, __LINE__) -#define pthread_mutex_unlock(l) dbg_unlock(l, __LINE__) -#define pthread_mutex_destroy(l) dbg_free(l, __LINE__) - -#else -# error debug_mutex.h included twice -#endif /* DEBUG_MUTEX_H */ diff --git a/tools/display_message.h b/tools/display_message.h deleted file mode 100644 index 407f07c8..00000000 --- a/tools/display_message.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * display_message.h: Display simple message - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: display_message.h,v 1.2 2007-01-06 04:28:08 phintuka Exp $ - * - */ - -#ifndef __DISPLAY_MESSAGE_H -#define __DISPLAY_MESSAGE_H - -#include <vdr/osdbase.h> -#include <vdr/skins.h> - -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 <vdr/tools.h> - - -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<class TCLASS> -cFunctor *CreateFunctor(TCLASS *c, - void (TCLASS::*fp)(void)); - -template<class TCLASS, class TARG1> -cFunctor *CreateFunctor(TCLASS *c, - void (TCLASS::*fp)(TARG1), - TARG1 arg1); -#endif - -template<class TCLASS, class TRESULT> -cFunctor *CreateFunctor(TCLASS *c, - TRESULT (TCLASS::*fp)(void)); - -template<class TCLASS, class TRESULT, class TARG1> -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 TCLASS> -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>(TCLASS*,TFUNC); -}; - -template <class TCLASS, class TARG1> -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,TARG1>(TCLASS*,TFUNC,TARG1); -}; -#endif - -template <class TCLASS, class TRESULT> -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,TRESULT>(TCLASS*,TFUNC); -}; - -template <class TCLASS, class TRESULT, class TARG1> -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,TRESULT>(TCLASS*,TFUNC,TARG1); -}; - -#if 1 /* gcc 3.3.x (?) does not accept class TRESULT=void */ -template<class TCLASS> -cFunctor *CreateFunctor(TCLASS *c, - void (TCLASS::*fp)(void)) -{ - return new cFunctor0<TCLASS>(c, fp); -} - -template<class TCLASS, class TARG1> -cFunctor *CreateFunctor(TCLASS *c, - void (TCLASS::*fp)(TARG1), - TARG1 arg1) -{ - return new cFunctor1<TCLASS,TARG1>(c, fp, arg1); -} -#endif - -template<class TCLASS, class TRESULT> -cFunctor *CreateFunctor(TCLASS *c, - TRESULT (TCLASS::*fp)(void)) -{ - return new cFunctorR0<TCLASS,TRESULT>(c, fp); -} - -template<class TCLASS, class TRESULT, class TARG1> -cFunctor *CreateFunctor(TCLASS *c, - TRESULT (TCLASS::*fp)(TARG1), - TARG1 arg1) -{ - return new cFunctorR1<TCLASS,TRESULT,TARG1>(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 <vdr/thread.h> - -template <class T> -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 <vdr/remote.h> - -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/gnome_screensaver.c b/tools/gnome_screensaver.c deleted file mode 100644 index a23d4236..00000000 --- a/tools/gnome_screensaver.c +++ /dev/null @@ -1,135 +0,0 @@ -/* - * gnome_screensaver.c v0.0.7 - * - * Enable/Disable the GNOME screensaver - * Supports GNOME screensaver API 2.14 and 2.15 - * - * Call gnome_screensaver_control(1) to enable and - * gnome_screensaver_control(0) to disable - * - */ -/* - * Orginally written for mplayer by Piotr Kaczuba - * (http://lists.mplayerhq.hu/pipermail/mplayer-dev-eng/2006-April/042661.html) - * - * Modified for xineliboutput by Alex Stansfield - * (http://www.linuxtv.org/pipermail/vdr/2007-July/013458.html) - */ - -#include <stdlib.h> -#include <unistd.h> -#include <dbus/dbus-glib.h> -#include <stdio.h> -#include <stdarg.h> -#include <string.h> - -#define LOG_MODULENAME "[vdr-fe] " -#include "../logdefs.h" - -#include "gnome_screensaver.h" - -#define GS_SERVICE "org.gnome.ScreenSaver" -#define GS_PATH "/org/gnome/ScreenSaver" -#define GS_INTERFACE "org.gnome.ScreenSaver" - -#define GS_APPLICATION_NAME "vdr-sxfe" -#define GS_REASON_FOR_INHIBIT "Watching TV" - -/* Log Messages */ -#define MSG_OpenBusConnectionError "Failed to open connection to bus: %s" -#define MSG_RemoteMethodException "Caught remote method exception %s: %s" -#define MSG_GnomeAPI215Failed "GNOME screensaver 2.15 API failed, trying 2.14 API" -#define MSG_GError "Error: %s" -#define MSG_GNOMEScreensaverEnabled "GNOME screensaver enabled" -#define MSG_GNOMEScreensaverDisabled "GNOME screensaver disabled" - -static guint32 cookie; - -void gnome_screensaver_control(int enable) -{ - DBusGConnection *connection; - GError *error; - DBusGProxy *proxy; - gboolean ret; - - g_type_init(); - - /* Get a connection to the session bus */ - error = NULL; - connection = dbus_g_bus_get(DBUS_BUS_SESSION, &error); - if (!connection) { - LOGERR(MSG_OpenBusConnectionError, error ? error->message : "<null>"); - g_error_free(error); - return; - } - - /* Create a proxy object */ - proxy = dbus_g_proxy_new_for_name(connection, - GS_SERVICE, GS_PATH, GS_INTERFACE); - if (!proxy) { - LOGDBG("Failed to get a proxy for gnome-screensaver"); - return; - } - - /* Enable the screensaver */ - if (enable) { - /* First call the GNOME screensaver 2.15 API method */ - error = NULL; - ret = - dbus_g_proxy_call(proxy, "UnInhibit", &error, - G_TYPE_UINT, cookie, - G_TYPE_INVALID, G_TYPE_INVALID); - - /* If this fails, try the GNOME screensaver 2.14 API */ - if (!ret && error->domain == DBUS_GERROR - && error->code == DBUS_GERROR_UNKNOWN_METHOD) { - LOGERR(MSG_GnomeAPI215Failed); - g_error_free(error); - error = NULL; - ret = - dbus_g_proxy_call(proxy, "AllowActivation", &error, - G_TYPE_INVALID, G_TYPE_INVALID); - } - } - /* Disable the screensaver */ - else { - /* First call the GNOME screensaver 2.15 API method */ - error = NULL; - ret = - dbus_g_proxy_call(proxy, "Inhibit", &error, - G_TYPE_STRING, GS_APPLICATION_NAME, - G_TYPE_STRING, GS_REASON_FOR_INHIBIT, - G_TYPE_INVALID, - G_TYPE_UINT, &cookie, - G_TYPE_INVALID); - - /* If this fails, try the GNOME screensaver 2.14 API */ - if (!ret && error->domain == DBUS_GERROR - && error->code == DBUS_GERROR_UNKNOWN_METHOD) { - LOGERR(MSG_GnomeAPI215Failed); - g_error_free(error); - error = NULL; - ret = - dbus_g_proxy_call(proxy, "InhibitActivation", &error, - G_TYPE_STRING, GS_REASON_FOR_INHIBIT, - G_TYPE_INVALID, G_TYPE_INVALID); - } - } - - if (!ret) { - /* Check if it's a remote exception or a regular GError */ - if (error->domain == DBUS_GERROR - && error->code == DBUS_GERROR_REMOTE_EXCEPTION) { - LOGERR(MSG_RemoteMethodException, dbus_g_error_get_name(error), error->message); - } - else { - LOGERR(MSG_GError, error->message); - } - g_error_free(error); - } - else { - LOGMSG(enable ? MSG_GNOMEScreensaverEnabled : MSG_GNOMEScreensaverDisabled); - } - - g_object_unref(proxy); -} diff --git a/tools/gnome_screensaver.h b/tools/gnome_screensaver.h deleted file mode 100644 index 84dee38e..00000000 --- a/tools/gnome_screensaver.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _GNOME_SCREENSAVER_H -#define _GNOME_SCREENSAVER_H - -extern void gnome_screensaver_control(int enable); - -#endif /* !_GNOME_SCREENSAVER_H */ diff --git a/tools/http.c b/tools/http.c deleted file mode 100644 index 0e7de26a..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.7 2009-06-02 08:37:58 phintuka Exp $ - * - */ - -#define __STDC_FORMAT_MACROS -#include <inttypes.h> - -#include <string.h> - -#include <vdr/config.h> -#include <vdr/tools.h> - -#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> 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 */ - const 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 <vdr/tools.h> - - -#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<cHeader> 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 <vdr/tools.h> -#include <vdr/thread.h> - -#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<cHttpStreamer> 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 be7647b6..00000000 --- a/tools/iconv.h +++ /dev/null @@ -1,96 +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.6 2008-09-22 10:56:31 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 <iconv.h> -#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; - char *in = (char*)Text; - 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 ae30fa0e..00000000 --- a/tools/iso639.h +++ /dev/null @@ -1,186 +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.4 2009-05-29 14:25:06 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"}, - {"heb", "iw"}, - {"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 (!memcmp(ISO639_map[i].iso639_1, lang, 2)) - return ISO639_map[i].iso639_2; - LOGMSG("Unknown iso639-2 code: %s", lang); - } - return lang; - } - return NULL; -} - -static const char *iso639_1_to_iso639_2(const char *lang) -{ - if (lang && lang[0]) { - if (lang[1] && lang[2] && !lang[3]) { - for (unsigned int i = 0 ; i < sizeof(ISO639_map) / sizeof(ISO639_map[0]); i++) - if (!memcmp(ISO639_map[i].iso639_2, lang, 3)) - return ISO639_map[i].iso639_1; - LOGMSG("Unknown iso639-1 code: %s", lang); - } - return lang; - } - return NULL; -} - -#endif diff --git a/tools/metainfo_menu.c b/tools/metainfo_menu.c deleted file mode 100644 index 9dc47ec6..00000000 --- a/tools/metainfo_menu.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * metainfo_menu.c: Media file info menu - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: metainfo_menu.c,v 1.5.2.1 2009-09-13 12:17:53 phintuka Exp $ - * - */ - -#ifdef HAVE_LIBEXTRACTOR -# include <extractor.h> -#endif - -#include <vdr/status.h> - -#include "../i18n.h" -#include "../config.h" - -#include "metainfo_menu.h" - - -// -// cMetainfoMenu -// - -cMetainfoMenu::cMetainfoMenu(cString Filename) : - cOsdMenu(Filename), - m_Filename(Filename) -{ - const char *Title = strrchr(Filename, '/'); - if(Title && *(Title+1)) - SetTitle(Title+1); -} - -cMetainfoMenu::~cMetainfoMenu() -{ -} - -void cMetainfoMenu::Display(void) -{ - cOsdMenu::Display(); - - char metadata[4096]; - metadata[0] = 0; - -#ifdef HAVE_LIBEXTRACTOR - EXTRACTOR_ExtractorList * plugins; - EXTRACTOR_KeywordList * md_list; - plugins = EXTRACTOR_loadDefaultLibraries(); - md_list = EXTRACTOR_getKeywords(plugins, m_Filename); - md_list = EXTRACTOR_removeEmptyKeywords (md_list); - md_list = EXTRACTOR_removeDuplicateKeywords(md_list, 0); - md_list = EXTRACTOR_removeKeywordsOfType(md_list, EXTRACTOR_THUMBNAILS); - - uint pos = 0; - int n; - while(md_list) { - const char *key = EXTRACTOR_getKeywordTypeAsString(md_list->keywordType); - if(key && pos < sizeof(metadata)) - if(0 < (n = snprintf(metadata+pos, sizeof(metadata)-pos, "%s: %s\n", key, md_list->keyword))) - pos += n; - md_list = md_list->next; - } - metadata[sizeof(metadata)-1] = 0; - - EXTRACTOR_freeKeywords(md_list); - EXTRACTOR_removeAll(plugins); /* unload plugins */ -#else - cString cmd; - if(xc.IsPlaylistFile(m_Filename)) - cmd = cString::sprintf("file -b '%s'; cat '%s'", *m_Filename, *m_Filename); - else if(xc.IsAudioFile(m_Filename)) - cmd = cString::sprintf("mp3info -x '%s' ; file -b '%s'", *m_Filename, *m_Filename); - else if(xc.IsVideoFile(m_Filename)) - cmd = cString::sprintf("file -b '%s'; midentify '%s'", *m_Filename, *m_Filename); - else if(xc.IsImageFile(m_Filename)) - cmd = cString::sprintf("file -b '%s'; identify '%s'", *m_Filename, *m_Filename); - else - cmd = cString::sprintf("file -b '%s'", *m_Filename); - - cPipe p; - if(p.Open(*cmd, "r")) { - int n = fread(metadata, 1, sizeof(metadata)-1, p); - if(n>0) { - metadata[n] = 0; - strreplace(metadata, ',', '\n'); - } - } -#endif - DisplayMenu()->SetText(metadata, false); - cStatus::MsgOsdTextItem(cString::sprintf("%s\n%s", tr("Metainfo"), *m_Filename)); -} - -eOSState cMetainfoMenu::ProcessKey(eKeys Key) -{ - eOSState state = cOsdMenu::ProcessKey(Key); - return state; -} diff --git a/tools/metainfo_menu.h b/tools/metainfo_menu.h deleted file mode 100644 index 45d60f22..00000000 --- a/tools/metainfo_menu.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * metainfo_menu.h: Media file info menu - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: metainfo_menu.h,v 1.1 2008-05-07 13:27:15 phintuka Exp $ - * - */ - -#ifndef __XINELIB_INFO_MENU_H_ -#define __XINELIB_INFO_MENU_H_ - -// -// cMetainfoMenu -// - -#include <vdr/osdbase.h> - -class cMetainfoMenu : public cOsdMenu -{ - protected: - - cString m_Filename; - - public: - - cMetainfoMenu(cString Filename); - virtual ~cMetainfoMenu(); - - virtual void Display(void); - - // cOsdMenu - virtual eOSState ProcessKey(eKeys Key); - -}; - -#endif // __XINELIB_INFO_MENU_H_ diff --git a/tools/pes.c b/tools/pes.c deleted file mode 100644 index 14773f2e..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.10 2009-07-01 09:31:17 phintuka Exp $ - * - */ - -#include <inttypes.h> -#include <string.h> - -#include "../logdefs.h" - -#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 NO_PTS; - if ((buf[6] & 0x30) != 0) - return NO_PTS; - - if ((len > 13) && (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 NO_PTS; -} - -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 NO_PTS; - if ((buf[6] & 0x30) != 0) - return NO_PTS; - - 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 NO_PTS; -} - -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 > 13) && (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] &= 0x3f; /* clear pts and dts flags */ - buf[8] -= n; /* 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 (IS_NAL_AUD(buf)) - return 1; - return 0; -} - -uint8_t pes_get_picture_type(const uint8_t *buf, int len) -{ - int i = PES_HEADER_LEN(buf); - - buf += i; - len -= i; - - if (buf[0] == 0x00 && buf[1] == 0x00 && buf[2] == 0x01) { - if (buf[3] == NAL_AUD) - return h264_get_picture_type(buf, len); - 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 = PES_HEADER_LEN(buf); - - buf += i; - len -= i; - - if (h264 || IS_NAL_AUD(buf)) - return h264_get_video_size(buf, len, size); - - return mpeg2_get_video_size(buf, len, size); -} - diff --git a/tools/pes.h b/tools/pes.h deleted file mode 100644 index d25374a7..00000000 --- a/tools/pes.h +++ /dev/null @@ -1,120 +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.13 2009-07-01 09:56:26 phintuka Exp $ - * - */ - -#ifndef _XINELIBOUTPUT_PES_H_ -#define _XINELIBOUTPUT_PES_H_ - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * Constants - */ - -#define PES_CHUNK_SIZE 2048 - -#define MAX_SCR ((int64_t)0x1ffffffffLL) - -#define NO_PTS (INT64_C(-1)) - -/* 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_MPEG_AUDIO_PACKET(data) (AUDIO_STREAM == ((data)[3] & ~AUDIO_STREAM_MASK)) -#define IS_PS1_PACKET(data) (PRIVATE_STREAM1 == (data)[3]) -#define IS_PADDING_PACKET(data) (PADDING_STREAM == (data)[3]) -#define IS_AUDIO_PACKET(data) (IS_MPEG_AUDIO_PACKET(data) || IS_PS1_PACKET(data)) - -#define PES_HAS_PTS(data) ((data)[7] & 0x80) -#define PES_HAS_DTS(data) ((data)[7] & 0x40) - -#define DATA_IS_PES(data) (!(data)[0] && !(data)[1] && (data)[2] == 1) - -#define PES_HEADER_LEN(data) (8 + (data)[8] + 1) - - -/* - * timestamps - */ - -static inline int pts_to_ms(int64_t pts) { return (int)(pts/INT64_C(90)); } -static inline int64_t ms_to_pts(int ms) { return ((int64_t)(ms)) * INT64_C(90); } - -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 - */ - -struct video_size_s; - -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, struct video_size_s *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])); -} - - -#ifdef __cplusplus -} /* extern "C" { */ -#endif - -#endif /* _XINELIBOUTPUT_PES_H_ */ diff --git a/tools/playlist.c b/tools/playlist.c deleted file mode 100644 index e812e112..00000000 --- a/tools/playlist.c +++ /dev/null @@ -1,1003 +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.2.7 2009-11-16 11:30:09 phintuka Exp $ - * - */ - -#include <stdlib.h> - -#ifdef HAVE_LIBEXTRACTOR -# include <extractor.h> - // 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_LIBEXTRACTOR -# endif -#endif - -#include <vdr/config.h> -#include <vdr/tools.h> -#include <vdr/thread.h> - -#include "../config.h" - -#include "playlist.h" - -#include "../logdefs.h" - - -#ifndef PLAYLIST_CACHE -# define PLAYLIST_CACHE ".xineliboutput-playlist.pls" -#endif - -#define MAX_PLAYLIST_FILES 1024 - -static void strip_extension(cString& fname) -{ - const char *ext = strrchr(fname, '.'); - if (ext) - fname.Truncate(ext - fname); -} - -// -// cPlaylistItem -// - -cPlaylistItem::cPlaylistItem(const char *filename) -{ - const char *pt; - - Filename = filename; - Position = -1; - - if(NULL != (pt = strrchr(filename, '/'))) - Title = pt + 1; - else - Title = filename; - - strip_extension(Title); -} - -cPlaylistItem::cPlaylistItem(const char *filename, - const char *path, - const char *title, - int position) -{ - 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) - strip_extension(Title); -} - -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_LIBEXTRACTOR -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; - const int priority = 10; - errno = 0; - if((nice(priority) == -1) && errno) - LOGDBG("ID3Scanner: Can't nice to value: %d", priority); - - 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_LIBEXTRACTOR - 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 = md_list->keyword; - else if (!strcasecmp(key,"artist")) - Item->Artist = md_list->keyword; - else if (!strcasecmp(key,"album")) - Item->Album = 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, "<REF HREF"); - if(!pt) - pt = strstr(line, "<ref href"); - if(!pt) - pt = strstr(line, "<ENTRY HREF"); - if(!pt) - pt = strstr(line, "<entry href"); - if(pt) { - pt = strchr(pt, '='); - if(pt) { - pt = strchr(pt, '\"'); - if(pt) { - pt++; - if(strchr(pt, '\"')) - *strchr(pt, '\"') = 0; - return pt; - } - } - } - - pt = strstr(line, "<TITLE>"); - if(!pt) - pt = strstr(line, "<title>"); - 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; - const 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 (*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((*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); - const char *ext = strrchr(file, '.'); - if(!strcasecmp(ext, ".pls")) - parser = new cPlsReader(*this); - else if(!strcasecmp(ext, ".asx")) - parser = new cAsxReader(*this); - else /*if(!strcasecmp(ext, ".m3u"))*/ - parser = new cM3uReader(*this); /* parses plain lists (.ram, ...) too ...*/ - - /* get folder */ - cString Folder = file; - const char *folder = strrchr(Folder, '/'); - if (folder) - Folder.Truncate(folder - Folder + 1); - - int n = 0; - cReadLine r; - char *pt; - while(NULL != (pt = r.Read(f)) && n < MAX_PLAYLIST_FILES) { - if(NULL != (pt = parser->Parse(pt))) { - - 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", *Folder, 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, Folder, 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 = path; - const char *pt = strrchr(tmp, '/'); - if(pt && pt > *tmp) { - tmp.Truncate(pt - tmp); - 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) { - const char *pt; - m_Folder = PlaylistFile; - if (NULL != (pt=strrchr(m_Folder, '/'))) - m_Folder.Truncate(pt - m_Folder + 1); - } - - if(xc.IsPlaylistFile(PlaylistFile)) { - // Read playlist file - Result = ReadPlaylist(PlaylistFile); - m_Origin = ePlaylist; - - cString dir = LastDir(m_Folder); - const char *name = strrchr(PlaylistFile, '/'); - name = name ? name+1 : NULL; - if(*dir && name) - m_Name = cString::sprintf("%s - %s", *dir, name); - else - m_Name = name ?: ""; - - strip_extension(m_Name); - - } else if(PlaylistFile[ 0] == '/' && - PlaylistFile[strlen(PlaylistFile)-1] == '/') { - // Scan folder - Result = ScanFolder(PlaylistFile, Recursive) > 0; - m_Origin = eImplicit; - Sort(); - - if(!*m_Name) { - m_Name = PlaylistFile; - m_Name.Truncate( strrchr(m_Name, '/') - m_Name); - 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; - char *buf = (char *)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 = (char *)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(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/rle.c b/tools/rle.c deleted file mode 100644 index 2425630b..00000000 --- a/tools/rle.c +++ /dev/null @@ -1,171 +0,0 @@ -/* - * rle.c: RLE utils - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: rle.c,v 1.3 2009-02-16 16:14:58 phintuka Exp $ - * - */ - -#include <stdint.h> -#include <stdlib.h> - -#include "../xine_osd_command.h" - -#include "rle.h" - - -#undef MAX -#define MAX(a,b) ((a) > (b) ? (a) : (b)) - -/* - * rle_compress() - * - */ -int rle_compress(xine_rle_elem_t **rle_data, const uint8_t *data, uint w, uint h) -{ - xine_rle_elem_t rle, *rle_p = 0, *rle_base; - int x, y, num_rle = 0, rle_size = 8128; - const uint8_t *c; - - rle_p = (xine_rle_elem_t*)malloc(4*rle_size); - rle_base = rle_p; - - for (y = 0; y < h; y++) { - rle.len = 0; - rle.color = 0; - c = data + y * w; - for (x = 0; x < w; x++, c++) { - if (rle.color != *c) { - if (rle.len) { - if ( (num_rle + h-y+1) > 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++; - } - - *rle_data = rle_base; - return num_rle; -} - -/* - * rle_scale_nearest() - * - * - Simple nearest-neighbour scaling for RLE-compressed image - * - fast scaling in compressed form without decompression - */ -xine_rle_elem_t *rle_scale_nearest(const xine_rle_elem_t *old_rle, int *rle_elems, - uint w, uint h, uint new_w, uint new_h) -{ - #define FACTORBASE 0x100 - #define FACTOR2PIXEL(f) ((f)>>8) - #define SCALEX(x) FACTOR2PIXEL(factor_x*(x)) - #define SCALEY(y) FACTOR2PIXEL(factor_y*(y)) - - uint old_w = w, old_h = h; - uint old_y = 0, new_y = 0; - uint factor_x = FACTORBASE*new_w/old_w; - uint factor_y = FACTORBASE*new_h/old_h; - uint rle_size = MAX(8128, *rle_elems * new_h/h ); /* guess ... */ - uint num_rle = 0; - xine_rle_elem_t *new_rle = (xine_rle_elem_t*)malloc(sizeof(xine_rle_elem_t)*rle_size); - xine_rle_elem_t *new_rle_start = new_rle; - - /* we assume rle elements are breaked at end of line */ - while (old_y < old_h) { - uint elems_current_line = 0; - uint old_x = 0, new_x = 0; - - while (old_x < old_w) { - uint 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; - uint 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 ? */ - uint 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++; - } - } - } - - *rle_elems = num_rle; - return new_rle_start; -} diff --git a/tools/rle.h b/tools/rle.h deleted file mode 100644 index d6900e8f..00000000 --- a/tools/rle.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * rle.h: RLE utils - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: rle.h,v 1.2 2009-02-16 16:14:58 phintuka Exp $ - * - */ - -#ifndef XINELIBOUTPUT_RLE_H_ -#define XINELIBOUTPUT_RLE_H_ - -#if defined __cplusplus -extern "C" { -#endif - -typedef enum { - scale_fast = 0, /* simple pixel doubling/dropping */ - scale_good_BW = 1, /* linear interpolation, palette re-generation */ -} scale_mode_t; - - -struct xine_rle_elem_s; -struct xine_clut_s; - - -int rle_compress(struct xine_rle_elem_s **rle_data, const uint8_t *data, uint w, uint h); - -void rle_uncompress_lut8(const struct xine_rle_elem_s *rle_data, - uint8_t *data, uint w, uint h); -void rle_uncompress_argb(uint32_t *dst, - const struct xine_rle_elem_s *rle_data, uint num_rle, - uint w, uint h, uint stride, - struct xine_clut_s *palette); - -/* - * rle_scale_nearest() - * - * - Simple nearest-neighbour scaling for RLE-compressed image - * - fast scaling in compressed form without decompression - */ -struct xine_rle_elem_s *rle_scale_nearest(const struct xine_rle_elem_s *old_rle, - int *rle_elems, - uint w, uint h, uint new_w, uint new_h); - - -#if defined __cplusplus -} -#endif - -#endif /* XINELIBOUTPUT_RLE_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 514c29c1..00000000 --- a/tools/sdp.h +++ /dev/null @@ -1,112 +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.5 2009-02-10 12:42:38 phintuka Exp $ - * - */ - -#ifndef XINELIBOUTPUT_SDP_H_ -#define XINELIBOUTPUT_SDP_H_ - - -#define SDP_MIME_TYPE "application/sdp" - -#define SDP_PAYLOAD_MPEG_PES 96 -#define SDP_PAYLOAD_MPEG_TS 33 - -static const char *vdr_sdp_description(const char *vdr_ip, - int vdr_svdrp_port, - int vdr_xineliboutput_port, - const char *rtp_ip, - uint32_t rtp_ssrc, - uint32_t payload_type, - int rtp_port, - int rtp_ttl) -{ - static uint8_t s_serial = 0; - static cString s_data; - static char s_hostname[257] = {0}; - - uint64_t serial = (time(NULL) << 2) + ((s_serial++) & 0x03); - cString payload; - - if (!s_hostname[0]) - gethostname(s_hostname, 256); - - if (payload_type == SDP_PAYLOAD_MPEG_PES) { - payload = cString::sprintf( - /* video/mp2p udp/rtp */ - /* media */ "m=video %d RTP/AVP 96" - /* */ "\r\n" "a=rtpmap:96 MP2P/90000" - , rtp_port - ); - } else { - payload = cString::sprintf( - /* video/mp2t udp/rtp */ - /* media */ "m=video %d RTP/AVP 33" - , rtp_port - ); - } - - s_data = cString::sprintf( - /*** 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" "%s" - - /* 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 - - /* media */ - , rtp_ip, rtp_ttl - , *payload - -#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 6044b794..00000000 --- a/tools/udp_buffer.h +++ /dev/null @@ -1,144 +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.6 2009-03-24 19:35:23 phintuka Exp $ - * - */ - -#ifndef __UDP_BUFFER_H -#define __UDP_BUFFER_H - -#include <stdint.h> - -#include <vdr/config.h> // VDRVERSNUM - -#include "../xine_input_vdr_net.h" // frame headers -#include "ts.h" - -#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; -#if VDRVERSNUM >= 10701 - if (DATA_IS_TS(Data)) - header->rtp_hdr.raw[1] = RTP_PAYLOAD_TYPE_TS; - else - header->rtp_hdr.raw[1] = RTP_PAYLOAD_TYPE_PES; -#else - header->rtp_hdr.raw[1] = RTP_PAYLOAD_TYPE_PES; -#endif - 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; - - m_RtpSeqNo = (m_RtpSeqNo + 1) & 0xFFFF; - m_SeqNo = (m_SeqNo + 1) & UDP_SEQ_MASK; - - return header; - } -}; - - -#endif diff --git a/tools/udp_pes_scheduler.c b/tools/udp_pes_scheduler.c deleted file mode 100644 index 683d2319..00000000 --- a/tools/udp_pes_scheduler.c +++ /dev/null @@ -1,930 +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.c,v 1.50.2.1 2009-09-13 12:43:02 phintuka Exp $ - * - */ - -//#define LOG_UDP_RATE -//#define LOG_RESEND -//#define LOG_SCR - -#define __STDC_FORMAT_MACROS -#define __STDC_CONSTANT_MACROS -#include <inttypes.h> - -#include <stdint.h> -#include <stdlib.h> -#include <errno.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/ioctl.h> - -#include <vdr/config.h> -#include <vdr/tools.h> -#include <vdr/videodir.h> - -#include "../logdefs.h" // logging -#include "../config.h" // configuration data -#include "../xine_input_vdr_net.h" // frame headers and constants - -#include "ts.h" -#include "pes.h" -#include "udp_buffer.h" -#include "time_pts.h" -#include "cxsocket.h" -#include "sap.h" // SAP - Session Announcement Protocol -#include "sdp.h" // SDP - Session Description Protocol -#include "rtcp.h" // RTCP - -#include "udp_pes_scheduler.h" - - -#ifdef LOG_RESEND -# define LOGRESEND LOGDBG -#else -# define LOGRESEND(x...) -#endif - -#ifdef LOG_SCR -# define LOGSCR LOGDBG -#else -# define LOGSCR(x...) -#endif - -/* - * constants - */ - -const uint MAX_QUEUE_SIZE = 64; // ~ 65 ms with typical DVB stream -const uint MAX_LIVE_QUEUE_SIZE = (64+60); // ~ 100 ms with typical DVB stream -const uint HARD_LIMIT = (4*1024); // ~ 40 Mbit/s === 4 Mb/s - -const uint MAX_BURST_BYTES = 32768; // 32 kb -const uint MAX_BURST_FRAMES = 15; // 15 UDP packets - -const uint RTCP_MIN_INTERVAL = 45000; // 500 ms (pts units) - -// initial burst length after seek (500ms = ~13 video frames) -const int64_t INITIAL_BURST_TIME = INT64_C(45000); // pts units (90kHz) - -// assume seek when when pts difference between two frames exceeds this (2,5 seconds) -const int64_t JUMP_LIMIT_TIME = INT64_C(225000); // pts units (90kHz) - -const uint SCHEDULER_MIN_DELAY_MS = 3; -const uint SCHEDULER_MAX_DELAY_MS = 20; - -static inline int64_t abs64(int64_t val) { return val<0 ? -val : val; } - -cUdpScheduler::cUdpScheduler() -{ - - // Scheduler data - - m_ScrSource = eScrDetect; - m_CurrentAudioVtime = 0; - m_CurrentVideoVtime = 0; - m_CurrentPcr = 0; - - m_MasterClock.Set(INT64_C(0)); - - m_BurstBytes = 0; - m_BurstFrames = 0; - - m_Master = false; - m_TrickSpeed = false; - - // RTP - - srandom(time(NULL) ^ getpid()); - - m_ssrc = random(); - LOGDBG("RTP SSRC: 0x%08x", m_ssrc); - m_LastRtcpTime = 0; - m_Frames = 0; - m_Octets = 0; - m_RtpScr.Set((int64_t)random()); - - m_fd_sap = -1; - - // Queuing - - int i; - for(i=0; i<MAX_UDP_HANDLES; i++) - m_Handles[i] = -1; - - m_BackLog = new cUdpBackLog; - - m_QueueNextSeq = 0; - m_QueuePending = 0; - - // Thread - - Start(); -} - -cUdpScheduler::~cUdpScheduler() -{ - m_Lock.Lock(); - - Cancel(-1); - m_Cond.Broadcast(); - m_CondWait.Signal(); - m_Lock.Unlock(); - - Cancel(3); - - if(m_fd_rtcp.open() || m_fd_rtp.open()) - Send_SAP(false); - - CLOSESOCKET(m_fd_sap); - - delete m_BackLog; -} - -void cUdpScheduler::Scheduler_Sleep(int ms) -{ - m_CondWait.Wait(ms); - m_BurstBytes = 0; - m_BurstFrames = 0; -} - -bool cUdpScheduler::AddRtp(void) -{ - cMutexLock ml(&m_Lock); - - if(m_fd_rtcp.open()) { - LOGERR("cUdpScheduler::AddHandle: RTCP socket already open !"); - Send_SAP(false); - m_fd_rtcp.close(); - } - - /* need new ssrc */ - m_ssrc = random(); - LOGDBG("RTP SSRC: 0x%08x", m_ssrc); - - // - // RTP - // - if(! m_fd_rtp.create(cxSocket::estDGRAM)) { - LOGERR("socket() failed (UDP/RTP multicast)"); - return false; - } - - // Set buffer sizes - m_fd_rtp.set_buffers(KILOBYTE(256), 2048); - - // Set multicast socket options - if(!m_fd_rtp.set_multicast(xc.remote_rtp_ttl)) { - m_fd_rtp.close(); - return false; - } - - if(xc.remote_local_ip[0]) { - struct sockaddr_in name; - name.sin_family = AF_INET; - name.sin_addr.s_addr = inet_addr(xc.remote_local_ip); - if(name.sin_addr.s_addr == INADDR_NONE) - LOGERR("Local address %s is invalid", xc.remote_local_ip); - name.sin_port = htons(xc.remote_rtp_port); - if (bind(m_fd_rtp.handle(), (struct sockaddr *)&name, sizeof(name)) < 0) - LOGERR("bind(%s:%d) failed for udp/rtp multicast", xc.remote_local_ip, xc.remote_rtp_port); -#if 0 - struct ip_mreqn mreqn; - mreqn.imr_multiaddr.s_addr = inet_addr(xc.remote_rtp_addr); - mreqn.imr_address.s_addr = inet_addr(xc.remote_local_ip); /* IP address of local interface */ - //mreqn.imr_ifindex = ; /* interface index */ - if(setsockopt(m_fd_rtp.handle(), IPPROTO_IP, IP_MULTICAST_IF, &mreqn, sizeof(mreqn))) - LOGERR("setting multicast source address/interface failed"); -#endif - } - - // Connect to multicast address - if(!m_fd_rtp.connect(xc.remote_rtp_addr, xc.remote_rtp_port) && - errno != EINPROGRESS) { - LOGERR("connect(fd_rtp) failed. Address=%s, port=%d", - xc.remote_rtp_addr, xc.remote_rtp_port); - m_fd_rtp.close(); - return false; - } - - // Set to non-blocking mode - m_fd_rtp.set_blocking(false); - - // - // RTCP - // - if(! m_fd_rtcp.create(cxSocket::estDGRAM)) - LOGERR("socket() failed (RTCP multicast)"); - - m_fd_rtcp.set_buffers(16384, 16384); - if(!m_fd_rtcp.set_multicast(xc.remote_rtp_ttl)) - m_fd_rtcp.close(); - - if(xc.remote_local_ip[0]) { - struct sockaddr_in name; - name.sin_family = AF_INET; - name.sin_addr.s_addr = inet_addr(xc.remote_local_ip); - name.sin_port = htons(xc.remote_rtp_port+1); - if (bind(m_fd_rtcp.handle(), (struct sockaddr *)&name, sizeof(name)) < 0) - LOGERR("bind(%s:%d) failed for udp/rtp multicast", xc.remote_local_ip, xc.remote_rtp_port); -#if 0 - struct ip_mreqn mreqn; - mreqn.imr_multiaddr.s_addr = inet_addr(xc.remote_rtp_addr); - mreqn.imr_address.s_addr = inet_addr(xc.remote_local_ip); /* IP address of local interface */ - //mreqn.imr_ifindex = ; /* interface index */ - if(setsockopt(m_fd_rtp.handle(), IPPROTO_IP, IP_MULTICAST_IF, &mreqn, sizeof(mreqn))) - LOGERR("setting multicast source address/interface failed"); -#endif - } - - /* RTCP port (RFC 1889) */ - if(!m_fd_rtcp.connect(xc.remote_rtp_addr, xc.remote_rtp_port + 1) && - errno != EINPROGRESS) { - LOGERR("connect(fd_rtcp) failed. Address=%s, port=%d", - xc.remote_rtp_addr, xc.remote_rtp_port + - (xc.remote_rtp_port&1)?-1:1); - m_fd_rtcp.close(); - } - - // Set to non-blocking mode - m_fd_rtcp.set_blocking(false); - - // Finished - - if(!AddHandle(m_fd_rtp)) - LOGERR("cUdpScheduler::AddHandle(fd_rtp) failed"); - - Send_SAP(true); - - return true; -} - -bool cUdpScheduler::AddHandle(int fd) -{ - cMutexLock ml(&m_Lock); - - int i; - - for(i=0; i<MAX_UDP_HANDLES; i++) - if(m_Handles[i] < 0 || m_Handles[i] == fd) { - m_Handles[i] = fd; - - /* query socket send buffer size */ - m_wmem[i] = 0x10000; /* default to 64k */ - socklen_t l = sizeof(int); - if(getsockopt(m_Handles[i], SOL_SOCKET, SO_SNDBUF, &m_wmem[i], &l)) - LOGERR("getsockopt(SO_SNDBUF) failed"); - m_wmem[i] /= 2; /* man 7 socket */ - - m_Cond.Broadcast(); - - return true; - } - - return false; -} - -void cUdpScheduler::RemoveRtp(void) -{ - cMutexLock ml(&m_Lock); - - if(m_fd_rtp.open() || m_fd_rtcp.open()) { - Send_SAP(false); - - RemoveHandle(m_fd_rtp); - - m_fd_rtp.close(); - m_fd_rtcp.close(); - CLOSESOCKET(m_fd_sap); - } -} - -void cUdpScheduler::RemoveHandle(int fd) -{ - cMutexLock ml(&m_Lock); - - int i; - for(i=0; i<MAX_UDP_HANDLES; i++) - if(m_Handles[i] == fd) - break; - - for(; i<MAX_UDP_HANDLES-1; i++) - m_Handles[i] = m_Handles[i+1]; - - m_Handles[MAX_UDP_HANDLES-1] = -1; - - if(m_Handles[0] < 0) { - // No clients left ... - - // Flush all buffers - m_QueueNextSeq = 0; - m_QueuePending = 0; - - m_BackLogDeleteMutex.Lock(); - delete m_BackLog; - m_BackLog = new cUdpBackLog; - m_BackLogDeleteMutex.Unlock(); - - m_Frames = 0; - m_Octets = 0; - } -} - -int cUdpScheduler::Poll(int TimeoutMs, bool Master) -{ - cMutexLock ml(&m_Lock); - - m_Master = Master; - - if(m_Handles[0] < 0) { - // no clients, so we can eat all data we are given ... - return DEFAULT_POLL_SIZE; - } - - uint limit = m_Master ? MAX_QUEUE_SIZE : MAX_LIVE_QUEUE_SIZE; - if(m_QueuePending >= limit) { - uint64_t WaitEnd = cTimeMs::Now(); - if(TimeoutMs >= 0) - WaitEnd += (uint64_t)TimeoutMs; - - while (cTimeMs::Now() < WaitEnd && - Running() && - m_QueuePending >= limit) - m_Cond.TimedWait(m_Lock, 5); - } - - return limit > m_QueuePending ? limit - m_QueuePending : 0; -} - -bool cUdpScheduler::Flush(int TimeoutMs) -{ - cMutexLock ml(&m_Lock); - - if(m_Handles[0] < 0) - return true; - - if(m_QueuePending > 0) { - uint64_t WaitEnd = cTimeMs::Now(); - if(TimeoutMs >= 0) - WaitEnd += (uint64_t)TimeoutMs; - - while (cTimeMs::Now() < WaitEnd && - Running() && - m_QueuePending > 0) - m_Cond.TimedWait(m_Lock, 5); - } - return m_QueuePending == 0; -} - -void cUdpScheduler::Clear(void) -{ - cMutexLock ml(&m_Lock); - - m_BackLog->Clear(m_QueuePending); - - m_QueuePending = 0; - m_Cond.Broadcast(); - - m_ScrSource = eScrDetect; -} - -void cUdpScheduler::Pause(bool On) -{ - cMutexLock ml(&m_Lock); - - if(On) - m_MasterClock.Pause(); - else - m_MasterClock.Resume(); - - m_TrickSpeed = false; -} - -void cUdpScheduler::TrickSpeed(const int Multiplier) -{ - cMutexLock ml(&m_Lock); - -#ifdef LOG_SCR - if(Multiplier == 1 || Multiplier == -1) { - LOGMSG("UDP clock --> normal"); - } else if(Multiplier < 0) - LOGMSG("UDP clock --> %dx", -Multiplier); - else - LOGMSG("UDP clock --> 1/%d", Multiplier); -#endif - - m_MasterClock.TrickSpeed(Multiplier); - - m_TrickSpeed = (Multiplier==-1 || Multiplier==1) ? false : true; -} - -void cUdpScheduler::SetScrSpeed(const int Speed) -{ - cMutexLock ml(&m_Lock); - - m_MasterClock.SetScrSpeed(Speed); - m_RtpScr.SetScrSpeed(Speed); -} - -bool cUdpScheduler::Queue(uint64_t StreamPos, const uchar *Data, int Length) -{ - cMutexLock ml(&m_Lock); - - if(m_Handles[0] < 0) - return true; - - uint limit = m_Master ? MAX_QUEUE_SIZE : MAX_LIVE_QUEUE_SIZE; - if(m_QueuePending >= limit) - return false; - - m_BackLog->MakeFrame(StreamPos, Data, Length); - m_QueuePending++; - - m_Cond.Broadcast(); - - return true; -} - -void cUdpScheduler::QueuePadding(void) -{ - cMutexLock ml(&m_Lock); - - if (m_Handles[0] < 0) - return; - - if (m_QueuePending > 2) - return; - - QueuePaddingInternal(); - - m_Cond.Broadcast(); -} - -void cUdpScheduler::QueuePaddingInternal(void) -{ - static unsigned const char Padding[] = {0x00,0x00,0x01,0xBE,0x00,0x02,0xff,0xff}; - - int PrevSeq = (m_QueueNextSeq + UDP_BUFFER_SIZE - 1) & UDP_BUFFER_MASK; - stream_rtp_header_impl_t *Frame = m_BackLog->Get(PrevSeq); - if (Frame) { - int PrevLen = m_BackLog->PayloadSize(PrevSeq); - uint64_t Pos = ntohll(Frame->hdr_ext.pos) + PrevLen - 8; - m_BackLog->MakeFrame(Pos, Padding, 8); - } else - m_BackLog->MakeFrame(0, Padding, 8); - - m_QueuePending++; -} - -int cUdpScheduler::CalcElapsedVtime(int64_t pts, ScrSource_t ScrSource) -{ - int64_t diff = 0; - - switch (ScrSource) { - - case eScrFromVideo: - diff = pts - m_CurrentVideoVtime; - if (diff > JUMP_LIMIT_TIME || (-diff) > JUMP_LIMIT_TIME) { // 1 s (must be > GOP) - // RESET - LOGSCR("cUdpScheduler SCR RESET (Video jump %lld->%lld)", m_CurrentVideoVtime, pts); - m_CurrentVideoVtime = pts; - - // Use video pts for sync only in audioless trickspeeds - // (audio has smaller, constant and increasing intervals) - if (m_TrickSpeed) - m_MasterClock.Set(m_CurrentVideoVtime + INITIAL_BURST_TIME); - - return -1; - } - if (diff < 0) /* ignore small negative differences (B/P frames are sent out-of-order) */ - diff = 0; - else - m_CurrentVideoVtime = pts; - break; - - case eScrFromAudio: - diff = abs64(pts - m_CurrentAudioVtime); - if (diff > JUMP_LIMIT_TIME) { // 1 sec - // RESET - LOGSCR("cUdpScheduler SCR RESET (Audio jump %lld->%lld)", m_CurrentAudioVtime, pts); - m_CurrentAudioVtime = pts; - m_MasterClock.Set(m_CurrentAudioVtime + INITIAL_BURST_TIME); - return -1; - } - m_CurrentAudioVtime = pts; - break; - - case eScrFromPcr: - diff = pts - m_CurrentPcr; - if (diff > JUMP_LIMIT_TIME || diff < 0) { // 1 sec - // RESET - LOGSCR("cUdpScheduler RESET (PCR jump %lld->%lld)", m_CurrentPcr, pts); - m_CurrentPcr = pts; - m_MasterClock.Set(m_CurrentPcr + INITIAL_BURST_TIME); - return -1; - } - m_CurrentPcr = pts; - break; - - default: break; - } - - return (int) diff; -} - -void cUdpScheduler::Send_RTCP(void) -{ - if(!m_fd_rtcp.open()) - return; - - uint64_t scr = m_RtpScr.Now(); - - if(scr > (m_LastRtcpTime + RTCP_MIN_INTERVAL)) { - uint8_t frame[2048], *content = frame; - char hostname[64] = ""; - rtcp_packet_t *msg = (rtcp_packet_t *)content; - struct timeval tv; - - gettimeofday(&tv, NULL); - gethostname(hostname, sizeof(hostname)-1); - hostname[sizeof(hostname)-1] = 0; - - // SR (Sender report) - msg->hdr.raw[0] = 0x81; // RTP version = 2, Report count = 1 */ - msg->hdr.ptype = RTCP_SR; - msg->hdr.length = htons(6); // length 6 dwords - - msg->sr.ssrc = htonl(m_ssrc); - msg->sr.ntp_sec = htonl(tv.tv_sec + 0x83AA7E80); - msg->sr.ntp_frac = htonl((uint32_t)((double)tv.tv_usec*(double)(1LL<<32)*1.0e-6)); - msg->sr.rtp_ts = htonl((uint32_t)(scr & 0xffffffff)); - msg->sr.psent = htonl((uint32_t)(m_Frames & 0xffffffff)); - msg->sr.osent = htonl((uint32_t)(m_Octets & 0xffffffff)); - - content += sizeof(rtcp_common_t) + sizeof(rtcp_sr_t); - msg = (rtcp_packet_t *)content; - - // SDES - msg->hdr.raw[0] = 0x81; // RTP version = 2, Report count = 1 */ - msg->hdr.ptype = RTCP_SDES; - msg->hdr.count = 1; - - msg->sdes.ssrc = m_ssrc; - msg->sdes.item[0].type = RTCP_SDES_CNAME; - sprintf(msg->sdes.item[0].data, "VDR@%s:%d%c%c%c", - hostname[0] ? hostname : xc.remote_rtp_addr, - xc.remote_rtp_port, 0, 0, 0); - msg->sdes.item[0].length = strlen(msg->sdes.item[0].data); - msg->hdr.length = htons(1 + 1 + ((msg->sdes.item[0].length - 2) + 3) / 4); - - content += sizeof(rtcp_common_t) + 4*ntohs(msg->hdr.length); - msg = (rtcp_packet_t *)content; - - // Send -#ifndef LOG_RTCP - (void) m_fd_rtcp.send(frame, content - frame); -#else - LOGMSG("RTCP send (%d)", m_fd_rtcp.send(frame, content - frame)); - for(int i=0; i<content-frame; i+=16) - LOGMSG("%02X %02X %02X %02X %02X %02X %02X %02X " - "%02X %02X %02X %02X %02X %02X %02X %02X " - " %c%c%c%c%c%c%c%c %c%c%c%c%c%c%c%c", - frame[i+0],frame[i+1],frame[i+2],frame[i+3], - frame[i+4],frame[i+5],frame[i+6],frame[i+7], - frame[i+8],frame[i+9],frame[i+10],frame[i+11], - frame[i+12],frame[i+13],frame[i+14],frame[i+15], - frame[i+0],frame[i+1],frame[i+2],frame[i+3], - frame[i+4],frame[i+5],frame[i+6],frame[i+7], - frame[i+8],frame[i+9],frame[i+10],frame[i+11], - frame[i+12],frame[i+13],frame[i+14],frame[i+15]); -#endif - - m_LastRtcpTime = scr; - } -} - - -void cUdpScheduler::Send_SAP(bool Announce) -{ - if(!xc.remote_rtp_sap || !m_fd_rtp.open()) - return; - - char ip[64] = ""; - uint32_t local_addr = m_fd_rtp.get_local_address(ip); - - if(!local_addr) - return; - - uint32_t payload_type = VDRVERSNUM > 10702 ? SDP_PAYLOAD_MPEG_TS : SDP_PAYLOAD_MPEG_PES; - const char *sdp_descr = vdr_sdp_description(ip, - 2001, - xc.listen_port, - xc.remote_rtp_addr, - payload_type, - m_ssrc, - xc.remote_rtp_port, - xc.remote_rtp_ttl); - if(!sdp_descr) - return; - -#if 1 - /* store copy of SDP data */ - if(m_fd_sap < 0) { - cString fname = AddDirectory(VideoDirectory, - cString::sprintf("xineliboutput@%s.sdp", - ip)); - FILE *fp = fopen(fname, "w"); - if(fp) { - fprintf(fp, "%s", sdp_descr); - fclose(fp); - } - } -#endif - - sap_pdu_t *pdu = sap_create_pdu(local_addr, - Announce, - (m_ssrc >> 16 | m_ssrc) & 0xffff, - "application/sdp", - sdp_descr); - - if(!sap_send_pdu(&m_fd_sap, pdu, 0)) - LOGERR("SAP/SDP announce failed"); - free(pdu); - - if(!Announce) - CLOSESOCKET(m_fd_sap); -} - -void cUdpScheduler::Schedule(const uchar *Data, int Length) -{ - bool Audio = IS_AUDIO_PACKET(Data), Video = IS_VIDEO_PACKET(Data); - int64_t pts = PES_HAS_PTS(Data) ? pes_get_pts(Data, Length) : INT64_C(-1); - int elapsed = pts>0 ? CalcElapsedVtime(pts, Audio ? eScrFromAudio : eScrFromVideo) : 0; - - if(elapsed > 0) { - int64_t now = m_MasterClock.Now(); - LOGSCR("PTS: %lld (%s) elapsed %d ms (PID %02x)", - pts, Video?"Video":Audio?"Audio":"?", pts_to_ms(elapsed), Data[3]); - - // - // Detect discontinuity - // - if(Audio) { - if(now > m_CurrentAudioVtime && (now - m_CurrentAudioVtime)>JUMP_LIMIT_TIME) { - LOGSCR("cUdpScheduler MasterClock init (was in past)"); - m_MasterClock.Set(m_CurrentAudioVtime + INITIAL_BURST_TIME); - } else if(now < m_CurrentAudioVtime && (m_CurrentAudioVtime-now)>JUMP_LIMIT_TIME) { - LOGSCR("cUdpScheduler MasterClock init (was in future)"); - m_MasterClock.Set(m_CurrentAudioVtime + INITIAL_BURST_TIME); - } - } - - else if(Video && m_TrickSpeed) { - if(now > m_CurrentVideoVtime && (now - m_CurrentVideoVtime)>JUMP_LIMIT_TIME) { - LOGSCR("cUdpScheduler MasterClock init (was in past) - VIDEO"); - m_MasterClock.Set(m_CurrentVideoVtime + INITIAL_BURST_TIME); - } else if(now < m_CurrentVideoVtime && (m_CurrentVideoVtime-now)>JUMP_LIMIT_TIME) { - LOGSCR("cUdpScheduler MasterClock init (was in future) - VIDEO"); - m_MasterClock.Set(m_CurrentVideoVtime + INITIAL_BURST_TIME); - } - } - - // - // Delay - // - uint delay_ms = 0; - if(m_TrickSpeed ) { - if(m_CurrentVideoVtime > now) { - delay_ms = pts_to_ms(m_CurrentVideoVtime - now); - LOGSCR("cUdpScheduler sleeping %d ms " - "(time reference: %s, beat interval %d ms)", - delay_ms, (Audio?"Audio PTS":"Video PTS"), pts_to_ms(elapsed)); - } - } else { - if(m_CurrentAudioVtime > now) { - delay_ms = pts_to_ms(m_CurrentAudioVtime - now); - LOGSCR("cUdpScheduler sleeping %d ms " - "(time reference: %s, beat interval %d ms)", - delay_ms, (Audio?"Audio PTS":"Video PTS"), pts_to_ms(elapsed)); - } - } - - while (delay_ms > SCHEDULER_MIN_DELAY_MS) { - if (delay_ms > SCHEDULER_MAX_DELAY_MS) - delay_ms = SCHEDULER_MAX_DELAY_MS; - LOGSCR(" -> cUdpScheduler sleeping %d ms ", delay_ms); - Scheduler_Sleep(delay_ms); - - now = m_MasterClock.Now(); - delay_ms = pts_to_ms(m_CurrentVideoVtime - now); - } - } -} - -void cUdpScheduler::Action(void) -{ - /* UDP Scheduler needs high priority */ - const int priority = -5; - SetPriority(priority); - errno = 0; - if ((nice(priority) == -1) && errno) - LOGDBG("cUdpScheduler: Can't nice to value: %d", priority); - - m_Lock.Lock(); - - while (Running()) { - - if(m_Handles[0] < 0) { - m_Cond.TimedWait(m_Lock, 5000); - continue; - } - - // Wait until we have outgoing data in queue - if(m_QueuePending <= 0) { - m_BurstFrames = m_BurstBytes = 0; - m_Cond.TimedWait(m_Lock, 100); - if(m_QueuePending <= 0) { - // Still nothing... - // Send padding frame once in 100ms so clients can detect - // possible missing frames and server shutdown - QueuePaddingInternal(); - } - continue; // to check Running() - } - - // Take next frame from queue - stream_rtp_header_impl_t *frame = m_BackLog->Get(m_QueueNextSeq); - int PayloadSize = m_BackLog->PayloadSize(m_QueueNextSeq); - int UdpPacketLen = PayloadSize + sizeof(stream_udp_header_t); - int RtpPacketLen = PayloadSize + sizeof(stream_rtp_header_impl_t); - - m_QueueNextSeq = (m_QueueNextSeq + 1) & UDP_BUFFER_MASK; - m_QueuePending--; - - m_Cond.Broadcast(); - m_BackLogDeleteMutex.Lock(); /* ensure frame will not be deleted from queue */ - m_Lock.Unlock(); - - // Schedule frame - if(m_Master) - Schedule(frame->payload, PayloadSize); - - // Need some bandwidth limit for ex. sequence of still frames when - // moving cutting marks very fast (no audio or PTS available). - // Hard limit for used bandwidth: - // - ~1 frames/ms & 8kb/ms -> 8mb/s -> ~ 80 Mbit/s ( / client) - // - max burst 15 frames or 32 kb - m_BurstFrames ++; - m_BurstBytes += PayloadSize; - if (m_BurstFrames >= MAX_BURST_FRAMES && m_BurstBytes >= MAX_BURST_BYTES) { - Scheduler_Sleep(4); -#ifdef LOG_UDP_RATE - static uint64_t dbg_timer = cTimeMs::Now(); - static int dbg_bytes = 0; - dbg_bytes += bytes; - if (dbg_timer + 60000 <= cTimeMs::Now()) { - LOGDBG("UDP rate: %4d Kbps (queue %d)", dbg_bytes/(60*1024/8), m_QueuePending); - dbg_bytes = 0; - dbg_timer = cTimeMs::Now(); - } -#endif - } - - /* tag frame with ssrc and timestamp */ - frame->rtp_hdr.ts = htonl((uint32_t)(m_RtpScr.Now() & 0xffffffff)); - frame->rtp_hdr.ssrc = htonl(m_ssrc); - - /* deliver to all active sockets */ - for(int i=0; i<MAX_UDP_HANDLES && m_Handles[i]>=0; i++) { - - // - // use TIOCOUTQ ioctl instead of poll/select. - // - poll/select for UDP/RTP may return true even when queue - // is (almost) full - // - kernel silently drops frames it cant send - // -> poll() + send() just causes frames to be dropped - // - uint size = 0; - if(!ioctl(m_Handles[i], TIOCOUTQ, &size)) { - if(size >= (m_wmem[i] - 2*RtpPacketLen)) { - LOGMSG("cUdpScheduler: kernel transmit queue > ~%dkb (max %dkb) ! (master=%d)", - (m_wmem[i] - 2*RtpPacketLen)/1024, m_wmem[i]/1024, m_Master); - Scheduler_Sleep(2); - } - } else { - if(m_QueuePending > (MAX_QUEUE_SIZE-5)) - LOGDBG("cUdpScheduler: kernel transmit queue > ~30kb ! (master=%d ; Queue=%d)", - m_Master, m_QueuePending); - Scheduler_Sleep(2); - } - - if(m_Handles[i] == m_fd_rtp.handle()) { - if(send(m_Handles[i], frame, RtpPacketLen, 0) <= 0) - LOGERR("cUdpScheduler: UDP/RTP send() failed !"); - } else { - /* UDP: send without rtp header */ - if (send(m_Handles[i], RTP_UDP_PAYLOAD(frame), UdpPacketLen, 0) <= 0) - LOGERR("cUdpScheduler: UDP send() failed !"); - } - } - - m_BackLogDeleteMutex.Unlock(); /* release queue */ - m_Lock.Lock(); - - m_Frames ++; - m_Octets += PayloadSize; - if(m_fd_rtcp.open() && (m_Frames & 0xff) == 1) { // every 256th frame - Send_RTCP(); -#if 0 - if((m_Frames & 0xff00) == 0) // every 65536th frame (~ 2 min) - Send_SAP(); -#else - if((m_Frames & 0x0300) == 0) // every 1024th frame (~ 2...4 sec) - Send_SAP(); -#endif - } - } - - m_Lock.Unlock(); -} - -void cUdpScheduler::ReSend(int fd, uint64_t Pos, int Seq1, int Seq2) -{ - if(fd < 0) /* no re-send for RTP */ - return; - - struct { - stream_udp_header_t hdr; - char payload[64-sizeof(stream_udp_header_t)]; - } udp_ctrl = {{(uint64_t)INT64_C(-1), (uint16_t)-1}, {0}}; - - // Handle buffer wrap - if(Seq1 > Seq2) - Seq2 += UDP_BUFFER_SIZE; - - cMutexLock ml(&m_Lock); // keeps also scheduler thread suspended ... - - if(Seq2-Seq1 > 64) { - LOGDBG("cUdpScheduler::ReSend: requested range too large (%d-%d)", Seq1, Seq2); - snprintf(udp_ctrl.payload, sizeof(udp_ctrl.payload), - "UDP MISSING %d-%d %" PRIu64, - Seq1, (Seq2 & UDP_BUFFER_MASK), Pos); - send(fd, &udp_ctrl, sizeof(udp_ctrl), 0); - return; - } - - // re-send whole range - for(; Seq1 <= Seq2; Seq1++) { - - // Wait if kernel queue is full - int size = 0; - if(!ioctl(fd, TIOCOUTQ, &size)) - if(size > ((0x10000)/2 - 2048)) { // assume 64k kernel buffer - LOGDBG("cUdpScheduler::ReSend: kernel transmit queue > ~30kb !"); - Scheduler_Sleep(2); - } - - stream_rtp_header_impl_t *frame = m_BackLog->Get(Seq1); - - if(frame) { - if(ntohull(frame->hdr_ext.pos) - Pos < 100000) { - send(fd, - RTP_UDP_PAYLOAD(frame), - m_BackLog->PayloadSize(Seq1) + sizeof(stream_udp_header_t), - 0); - LOGRESEND("cUdpScheduler::ReSend: %d (%d bytes) @%lld sent", - Seq1, m_BackLog->PayloadSize(Seq1), Pos); - Pos = ntohull(frame->hdr_ext.pos) + m_BackLog->PayloadSize(Seq1); - continue; - } else { - // buffer has been lost long time ago... - LOGRESEND("cUdpScheduler::ReSend: Requested position does not match " - "(%lld ; has %lld)", Pos, ntohll(frame->hdr_ext.pos)); - } - } else { - LOGRESEND("cUdpScheduler::ReSend: %d @%lld missing", Seq1, Pos); - } - - // buffer has been lost - send packet missing info - - LOGRESEND("cUdpScheduler::ReSend: missing %d-%d @%d (hdr 0x%llx 0x%x)", - Seq1, Seq1, Pos, udp_ctrl.hdr.pos, udp_ctrl.hdr.seq); - - int Seq0 = Seq1; - for(; Seq1 < Seq2; Seq1++) { - stream_rtp_header_impl_t *frame = m_BackLog->Get(Seq1+1); - if(frame && (ntohull(frame->hdr_ext.pos) - Pos < 100000)) - break; - } - - snprintf(udp_ctrl.payload, sizeof(udp_ctrl.payload), - "UDP MISSING %d-%d %" PRIu64, - Seq0, (Seq1 & UDP_BUFFER_MASK), Pos); - - send(fd, &udp_ctrl, sizeof(udp_ctrl), 0); - } -} diff --git a/tools/udp_pes_scheduler.h b/tools/udp_pes_scheduler.h deleted file mode 100644 index 99f1861b..00000000 --- a/tools/udp_pes_scheduler.h +++ /dev/null @@ -1,130 +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.22 2009-08-19 11:32:21 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 QueuePadding(void); - 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: - - // Signalling - - cCondVar m_Cond; - cMutex m_Lock; - - // Clients - - int m_Handles[MAX_UDP_HANDLES]; - uint m_wmem[MAX_UDP_HANDLES]; /* kernel buffer size */ - - cxSocket m_fd_rtp; - cxSocket m_fd_rtcp; - - // Queue - - uint m_QueueNextSeq; /* next outgoing */ - uint m_QueuePending; /* outgoing queue size */ - cUdpBackLog *m_BackLog; /* queue for incoming data (not yet send) and retransmissions */ - cMutex m_BackLogDeleteMutex; - - // Scheduling - - typedef enum { - /* from worst to best */ - eScrDetect = 0, - eScrFromVideo = 1, - eScrFromPS1 = 2, - eScrFromAudio = 3, - eScrFromPcr = 4, - } ScrSource_t; - - cTimePts m_MasterClock; /* Current MPEG PTS (synchronized to current stream) */ - bool m_TrickSpeed; /* current (replay) speed */ - bool m_Master; /* if true, we are master metronom for playback */ - - ScrSource_t m_ScrSource; - int64_t m_CurrentAudioVtime; - int64_t m_CurrentVideoVtime; - int64_t m_CurrentPcr; - - uint m_BurstBytes; /* number of bytes sent without sleeps */ - uint m_BurstFrames; /* number of frames sent without sleeps */ - - cCondWait m_CondWait; - - int CalcElapsedVtime(int64_t pts, ScrSource_t ScrSource); - void Schedule(const uchar *Data, int Length); - void Scheduler_Sleep(int ms); - void QueuePaddingInternal(void); - - // RTP - - uint32_t m_ssrc; /* RTP synchronization source id */ - cTimePts m_RtpScr; /* 90 kHz monotonic time source for RTP timestamps */ - - // RTCP - - uint64_t m_LastRtcpTime; - uint32_t m_Frames; - uint32_t m_Octets; - - void Send_RTCP(void); - - // SAP - - int m_fd_sap; - - void Send_SAP(bool Announce = true); - - // Thread - - virtual void Action(void); -}; - -#endif diff --git a/tools/vdrdiscovery.c b/tools/vdrdiscovery.c deleted file mode 100644 index e301056d..00000000 --- a/tools/vdrdiscovery.c +++ /dev/null @@ -1,273 +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.9 2009-06-29 21:23:33 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> - -#define LOG_MODULENAME "[discovery] " -#include "../logdefs.h" - -#include "vdrdiscovery.h" - -/* - * constants - */ - -#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; - int iBroadcast = 1, iReuse = 1; - struct sockaddr_in sin; - - if ((fd_discovery = socket(PF_INET, SOCK_DGRAM, 0/*IPPROTO_TCP*/)) < 0) { - LOGERR("discovery_init: socket() failed"); - return -1; - } - - if (setsockopt(fd_discovery, SOL_SOCKET, SO_BROADCAST, &iBroadcast, sizeof(int)) < 0) - LOGERR("discovery_init: setsockopt(SO_BROADCAST) failed"); - - if (setsockopt(fd_discovery, SOL_SOCKET, SO_REUSEADDR, &iReuse, sizeof(int)) < 0) - LOGERR("discovery_init: 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("discovery_init: bind() failed"); - close(fd_discovery); - return -1; - } - - return fd_discovery; -} - -int udp_discovery_init(void) -{ - return discovery_init(DISCOVERY_PORT); -} - -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; -} - -int udp_discovery_broadcast(int fd_discovery, int server_port, const char *server_address) -{ - char *msg = NULL; - int result; - - if(server_address && *server_address) { - result = 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 { - result = 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); - } - - if (result >= 0) { - result = udp_discovery_send(fd_discovery, DISCOVERY_PORT, msg); - free(msg); - } - - return result; -} - -static inline int udp_discovery_search(int fd_discovery, int port) -{ - char *msg = NULL; - int result; - - 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); - - if (result >= 0) { - result = udp_discovery_send(fd_discovery, port, msg); - free(msg); - } - - return result; -} - -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; -} - -int udp_discovery_is_valid_search(const char *buf) -{ - static 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; -} - -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; -} - - diff --git a/tools/vdrdiscovery.h b/tools/vdrdiscovery.h deleted file mode 100644 index de612733..00000000 --- a/tools/vdrdiscovery.h +++ /dev/null @@ -1,81 +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.5 2009-02-10 15:26:11 phintuka Exp $ - * - */ - -#ifndef _VDRDISCOVERY_H_ -#define _VDRDISCOVERY_H_ - -#define DISCOVERY_MSG_MAXSIZE 1024 - -#ifdef __cplusplus -extern "C" { -#endif - -struct sockaddr_in; - -/* - * Client interface - */ - -/* - * udp_discovery_find_server() - * - * Search for server. Return address and port. - * Returns 0 on success. - */ -int udp_discovery_find_server(int *port, char *address); - -/* - * Server interface - */ - -/* - * udp_discovery_init() - * - * Initialize server socket. Return value is the socket file descriptor, - * and can be used for polling. - * Returns < 0 on error. - */ -int udp_discovery_init(void); - -/* - * udp_discovery_broadcast() - * - * Send server announcement. - * Returns 0 on success. - */ -int udp_discovery_broadcast(int fd_discovery, int server_port, const char *server_address); - -/* - * udp_discovery_recv() - * - * Receive query or announcement. - * Returns number of bytes received, <= 0 on error. - * Result is null-terminated string, not more than DISCOVERY_MSG_MAXSIZE bytes. - */ -int udp_discovery_recv(int fd_discovery, char *buf, int timeout, - struct sockaddr_in *source); - -/* - * udp_discovery_is_valid_search() - * - * Check if string is valid search message. - * Returns 1 for valid messages, 0 for invalid messages. - */ -int udp_discovery_is_valid_search(const char *buf); - -#ifdef __cplusplus -}; -#endif - - -#endif // _VDRDISCOVERY_H_ diff --git a/vdrlogo_32x32.c b/vdrlogo_32x32.c deleted file mode 100644 index 00045db6..00000000 --- a/vdrlogo_32x32.c +++ /dev/null @@ -1,141 +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.4 2009-05-27 09:39:08 phintuka Exp $ - * - */ - -/* GIMP RGBA C-Source image dump (vdrlogo_32x32.c) */ - -typedef struct { - const uint32_t width; - const uint32_t height; - const uint8_t pixel_data[32 * 32 * sizeof(uint32_t) + 1]; -} __attribute__((packed)) sxfe_32x32_icon_t; - -static const sxfe_32x32_icon_t vdrlogo_32x32 = { - 32, 32, /*4,*/ - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\214v\246\32<\31xcT5\210F\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0sZ\226\37F$|^;\30yc;\30yc;\30ycC!~cY7\205U\231\210\265FL" - ".\202c<\30yc;\30yc;\30yc;\30yc;\30yc;\30ycE\"\177cU4\200Jv^\227\14\0\0\0" - "\0\0\0\0\0\0\0\0\0\243\224\304\10B\33z\354I!~\366\315\276\331\22\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0R3\202a>\24z\367:\17y\377:\17x\377" - ":\17x\377:\17x\377:\17y\377:\17|\377>\25{\377_C\204\377M*\200\377:\20x\377" - ":\20x\377:\20w\377:\20w\377:\20w\377:\17x\377:\17y\377@\31|\357eH\215G\0" - "\0\0\0\0\0\0\0\0\0\0\0R.\204\225;\17z\377tY\231e\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0mT\223\40=\24z\373=\33n\377>!f\377lax\254f^n\211f]q\211e" - "]r\220_Ov\254J*x\363;\17y\377cH\215\345gbjvgbjskfmsnipsqkrsoiv|^G|\274<\23" - "y\377E\36~\352\272\252\320\21\0\0\0\0\0\0\0\0u\\\2261;\22z\377Y7\207\304" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0O+\204\202;\21u\377M4t\370;\20y\377" - "rf\207Y\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\240\227\256\"J(\177\341:\21{\377" - "sZ\233J\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\342\340\343\1P*\203\266;" - "\17x\377zi\220a\0\0\0\0\0\0\0\0\0\0\0\0K&\204\316A\32{\375\243\230\264\37" - "\0\0\0\0\0\0\0\0\0\0\0\0\335\313\362\3C\34}\340M1t\370J&\177\251:\20x\377" - "rf\207Y\0\0\0\0ddd\6\24\24\24\301\35\35\35\301ZZZ\22hL\217X;\17{\377[=\212" - "\265\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0G!~\251:\17y\377se\205" - "{\0\0\0\0\0\0\0\0\0\0\0\0W7\203g9\20z\377iM\221}\0\0\0\0\0\0\0\0\0\0\0\0" - "\\;\215F:\20y\377eU{\250?\26y\230:\20x\377rf\207Y\0\0\0\0fgg$GB3\377NKF\377" - "JJJ\177\231\205\264\21=\23x\377T2\201\360\335\337\320\1\0\0\0\0\0\0\0\0\0" - "\0\0\0\236\213\273\17Y7\210i<\23y\372?\32o\377\222\216\227H\0\0\0\0\0\0\0" - "\0\0\0\0\0\212t\252\15@\30}\364T2\207\330\351\343\345\1\0\0\0\0\0\0\0\0H" - "#~\252=\31r\377\225\216\230E?\26y\230:\20x\377rf\207Y\0\0\0\0\222\217\220" - "\"\260\2215\377\237\213K\377788\236\352\332\366\6F\36\201\377L'|\377H$\202" - "\366@\30}\365@\30}\365A\27{\365=\23y\375;\17x\377;\31n\377j_w\254\327\322" - "\326\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0I&\201\236>\24z\377\226\203\2617\0" - "\0\0\0|b\242\24=\24{\367V@x\340\344\342\343\2?\26y\230:\20x\377rf\207Y\0" - "\0\0\0TUU\236\353\352\353\377\355\354\354\377('(\366MJP2B\31}\377I'z\377" - "bN\201\357T?v\365P8v\367<\27u\377:\21x\377UDq\330\177}\203]\333\335\332\2" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0eM\222;;\20z\377aC\214\223\0\0\0" - "\0L*\205n:\21w\377od}\202\0\0\0\0?\26y\230:\20x\377rf\207YY\\\\\40\230\230" - "\232\372\364\365\365\377\366\366\366\377||}\3772-8\327:\17x\377U9}\372\337" - "\342\332\3\0\0\0\0\340\340\330\2\203w\230TE\40z\365<\23{\367W7\210D\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\327\305\357\1G\"}\330O,\203\353" - "\336\322\347\6F\37~\321F&r\375\255\254\256$\0\0\0\0?\26y\230:\17x\377\200" - "t\216c\262\222D\221\272\260\216\377\363\364\365\377\366\366\366\377\212\201" - "^\3773#%\377:\17x\377[Hx\302\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0xb\232]<\24z" - "\377>\27z\353\204l\242\36\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "R2\205t;\20z\377y`\231w;\21v\377`Nz\303\0\0\0\0\0\0\0\0@\27z\230:\17y\377" - "\242\217r\245\355\272\21\377\310\240\20\377\331\326\323\377\324\324\324\377" - "\311\231\37\377\337\257\25\377S-^\377|u\203e\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0_?\214\2539\20z\377M*\202\262\367\361\363\2\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\205o\246\27?\26{\371J$\177\370:\24s\377\202{\206`" - "\0\0\0\0\0\0\0\0?\26z\230;\17x\377gG\200\325}QB\377\214\\C\377<\40L\377$" - "\15H\377\207^\25\377V9,\377TM_\307\312\317\307\5\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\242\215\271\26I$\200\355;\20z\377_C\213Y\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0M+\202\2619\20z\377P5u\361\313\314\307\15" - "\0\0\0\0\0\0\0\0>\25x\231;\17y\377:\20y\377:\17y\377;\17y\3779\17z\377<\24" - "p\377@)`\376bXo\262\266\264\253\26\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0u\\\233`<\21y\377A\34|\351\205s\246\25\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\221\211\2319kct\217|y\206a\0\0\0\0\0\0\0\0\0\0\0" - "\0\204y\215Mjcx\217kav\215lbx\217kar\215icr\205\202\202\204i\260\261\251" - "&\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\360\355\347\3wo\202zj`u\215\217\220\223?\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", -}; - diff --git a/vdrlogo_720x576.mpg b/vdrlogo_720x576.mpg Binary files differdeleted file mode 100644 index 2ef0f3f4..00000000 --- a/vdrlogo_720x576.mpg +++ /dev/null diff --git a/xine/post.c b/xine/post.c deleted file mode 100644 index 6c637634..00000000 --- a/xine/post.c +++ /dev/null @@ -1,901 +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 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 **) calloc(2, sizeof(char *)); - 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) -{ - char *p; - 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 **) calloc(2, sizeof(post_element_t *)); - else - post_elements = (post_element_t **) - realloc(post_elements, sizeof(post_element_t *) * ((*post_elements_num) + 2)); - - post_elements[(*post_elements_num)] = calloc(1, 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 = calloc( (*post_elements_num), sizeof(post_element_t *)); - - 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 = calloc( (*post_elements_num), sizeof(post_element_t *)); - - 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 355e8e2c..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 a539d31d..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.5 2008-12-14 00:52:35 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 = calloc(1, 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 bdab04fa..00000000 --- a/xine_fbfe_frontend.c +++ /dev/null @@ -1,390 +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.20.2.5 2009-10-08 12:13:11 phintuka Exp $ - * - */ - -#include <inttypes.h> -#include <sys/ioctl.h> -#include <fcntl.h> -#include <stdio.h> -#include <unistd.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/post.h" - -#include "xine_frontend.h" - - -/* - * data - */ - -typedef struct fbfe_s { - - /* function pointers / base class */ - union { - frontend_t fe; /* generic frontend */ - }; - - void (*update_display_size_cb)(frontend_t*); - void (*toggle_fullscreen_cb) (frontend_t*); - - /* from xine_frontend.c */ - double (*dest_pixel_aspect) (const frontend_t *, - double video_pixel_aspect, - int video_width, int video_height); - void (*frame_output_handler)(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); - - /* vdr */ - fe_keypress_f keypress; - - /* xine stuff */ - xine_t *xine; - xine_stream_t *stream; - xine_stream_t *slave_stream; - vdr_input_plugin_if_t *input_plugin; - 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 *video_port_name; - char *aspect_controller; - - int xine_visual_type; - fb_visual_t vis; - - uint16_t pes_buffers; - - /* stored original handlers */ - 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, - const char *config_file); - - /* 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 terminate_key_pressed; - uint8_t playback_finished; - uint8_t slave_playback_finished; - uint8_t aspect; - uint8_t cropping; - uint8_t scale_video; - uint8_t field_order; - - /* strings */ - char *configfile; - - /* display */ -/*char *modeline;*/ - int fd_tty; - - uint8_t fullscreen : 1; -/*uint8_t vmode_switch : 1;*/ - -} fbfe_t, fe_t; - -/* Common (non-X11/FB) frontend functions */ -#include "xine_frontend.c" - -static void fbfe_update_display_size(frontend_t *this_gen) -{ - fbfe_t *this = (fbfe_t*)this_gen; - if(this->fullscreen && this->video_port) { - 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); - } -} - -/* - * update_DFBARGS - * - * (optionally) add fbdev option to DFBARGS environment variable - */ -static void update_DFBARGS(const char *fb_dev) -{ - const char *env_old = getenv("DFBARGS"); - char *env_new = NULL; - - if (env_old) { - char *env_tmp = strdup(env_old); - char *head = strstr(env_tmp, "fbdev="); - - if (head) { - char *tail = strchr(head, ','); - if(head == env_tmp) - head = NULL; - else - *head = 0; - if(asprintf(&env_new, "%sfbdev=%s%s", - head ? env_tmp : "", fb_dev, tail ? tail : "") < 0) { - free(env_tmp); - return; - } - } else { - if(asprintf(&env_new, "fbdev=%s%s%s", fb_dev, env_tmp ? "," : "", env_tmp ?: "") < 0) { - free(env_tmp); - return; - } - } - free(env_tmp); - - LOGMSG("replacing environment variable DFBARGS with %s (original was %s)", - env_new, env_old); - - } else { - if(asprintf(&env_new, "fbdev=%s", fb_dev) < 0) - return; - - LOGMSG("setting environment variable DFBARGS to %s", env_new); - } - - setenv("DFBARGS", env_new, 1); - free(env_new); -} - -/* - * fbfe_display_open - */ -static int fbfe_display_open(frontend_t *this_gen, - int xpos, int ypos, - int width, int height, int fullscreen, int hud, - int modeswitch, const char *modeline, int aspect, - fe_keypress_f keyfunc, int no_x_kbd, int gui_hotkeys, - const char *video_port, int scale_video, int field_order, - const char *aspect_controller, int window_id) -{ - fbfe_t *this = (fbfe_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 = xpos; - this->ypos = ypos; - this->width = width; - this->height = height; - this->aspect = aspect; - this->cropping = 0; - this->field_order = 0/*field_order ? 1 : 0*/; - this->scale_video = scale_video; - this->overscan = 0; - this->display_ratio = 1.0; - this->aspect_controller = aspect_controller ? strdup(aspect_controller) : NULL; - - this->fullscreen = fullscreen; -/*this->vmode_switch = modeswitch;*/ -/*this->modeline = strdup(modeline ?: "");*/ - - /* setup xine FB visual */ - this->xine_visual_type = XINE_VISUAL_TYPE_FB; - this->vis.frame_output_cb = fe_frame_output_cb; - this->vis.user_data = this; - - /* select framebuffer device ? */ - if(video_port && !strncmp(video_port, "/dev/", 5)) - this->video_port_name = strdup(video_port); - else - this->video_port_name = NULL; - - /* set console to graphics mode */ -#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 xpos, int ypos, - int width, int height, int fullscreen, - int modeswitch, const char *modeline, - int aspect, int scale_video, int field_order) -{ - fbfe_t *this = (fbfe_t*)this_gen; - - if(!this) - return 0; - - this->xpos = xpos >= 0 ? xpos : this->xpos; - this->ypos = ypos >= 0 ? ypos : this->ypos; - this->width = width >= 0 ? width : this->width; - this->height = height >= 0 ? height : this->height; - this->aspect = aspect; - this->scale_video = scale_video; - this->field_order = field_order; - this->fullscreen = fullscreen; -/*this->vmode_switch = modeswitch;*/ -#if 0 - if(!modeswitch && strcmp(modeline, this->modeline)) { - strn0cpy(this->modeline, modeline, sizeof(this->modeline)); - /* XXX TODO - switch vmode */ - } -#endif - - return 1; -} - -static void fbfe_interrupt(frontend_t *this_gen) -{ - /* stop fbfe_run() */ -} - -static int fbfe_run(frontend_t *this_gen) -{ - fbfe_t *this = (fbfe_t*)this_gen; - - if (!this || this->fe.xine_is_finished(this_gen, 0) != FE_XINE_RUNNING) - return 0; - - /* just sleep 500ms */ - select(0, NULL, NULL, NULL, &(struct timeval){ .tv_sec = 0, .tv_usec = 500*1000 }); - - return 1; -} - -static void fbfe_display_close(frontend_t *this_gen) -{ - fbfe_t *this = (fbfe_t*)this_gen; - - if (!this) - return; - - 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; - } - - free(this->video_port_name); - this->video_port_name = NULL; - - free(this->aspect_controller); - this->aspect_controller = NULL; -} - -static int fbfe_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, - const char *config_file) -{ - fbfe_t *this = (fbfe_t*)this_gen; - - if (video_driver && !strcmp(video_driver, "DirectFB")) - update_DFBARGS(this->video_port_name); - - return this->fe_xine_init(this_gen, audio_driver, audio_port, - video_driver, pes_buffers, static_post_plugins, config_file); -} - -static frontend_t *fbfe_get_frontend(void) -{ - fbfe_t *this = calloc(1, sizeof(fbfe_t)); - - this->fd_tty = -1; - - init_fe((fe_t*)this); - - 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.fe_run = fbfe_run; - this->fe.fe_interrupt = fbfe_interrupt; - - this->update_display_size_cb = fbfe_update_display_size; - - /* override */ - this->fe_xine_init = this->fe.xine_init; - this->fe.xine_init = fbfe_xine_init; - - 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 7419cac2..00000000 --- a/xine_frontend.c +++ /dev/null @@ -1,1934 +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.2.15 2009-10-08 13:13:53 phintuka Exp $ - * - */ - -#include <inttypes.h> -#include <stdlib.h> -#include <stdio.h> -#include <unistd.h> - -# ifdef boolean -# define HAVE_BOOLEAN -# endif -# include <jpeglib.h> -# undef boolean - -#define XINE_ENGINE_INTERNAL -#include <xine.h> -#include <xine/xine_internal.h> - -#ifndef XINE_VERSION_CODE -# define XINE_VERSION_CODE (XINE_MAJOR_VERSION*10000 + \ - XINE_MINOR_VERSION*100 + \ - XINE_SUB_VERSION) -#endif - -#define LOG_MODULENAME "[vdr-fe] " -#include "logdefs.h" - -#include "xine_input_vdr.h" -#include "xine_input_vdr_mrl.h" -#include "xine/post.h" - -#undef MIN -#define MIN(a,b) ( (a) < (b) ? (a) : (b)) -#undef MAX -#define MAX(a,b) ( (a) > (b) ? (a) : (b)) - -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; -} - -/* - * list available plugins - */ - -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"); -} - -void list_xine_plugins(frontend_t *fe, int verbose) -{ - fe_t *this = (fe_t *)fe; - - xine_t *tmp_xine = NULL; - xine_t *xine = this ? this->xine : NULL; - - if (!xine) - xine_init(xine = tmp_xine = xine_new()); - - 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); - } - - if (tmp_xine) - xine_exit(tmp_xine); -} - -/* - * detect input plugin - */ - -static int find_input_plugin(fe_t *this) -{ - if(!this->input_plugin) { - if(!this->stream || !this->stream->input_plugin || - !this->stream->input_plugin->input_class || this->playback_finished) { - LOGMSG("find_input_plugin: 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), - MRL_ID)) { -#else - if(strcmp(this->stream->input_plugin->input_class->identifier, - MRL_ID)) { -#endif - LOGMSG("find_input_plugin: current xine input plugin is not " MRL_ID " !"); - return 0; - } - this->input_plugin = (vdr_input_plugin_if_t*)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 frontend_t *this_gen, double video_pixel_aspect, - int video_width, int video_height) -{ - const fe_t *this = (const fe_t*)this_gen; - /*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 = this->dest_pixel_aspect((frontend_t*)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_format_change_data_t framedata = { - .width = video_width, - .height = video_height, - .aspect = 0, /* TODO */ - .pan_scan = 0, - }; - const xine_event_t event = { - .type = XINE_EVENT_FRAME_FORMAT_CHANGE, - .stream = this->stream, - .data = &framedata, - .data_length = sizeof(framedata), - }; - 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); - if(system(cmd) == -1) - LOGERR("Executing /bin/sh -c %s failed", 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: - LOGDBG("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, - const char *config_file) -{ - fe_t *this = (fe_t*)this_gen; - post_plugins_t *posts = NULL; - - if(!this) - return 0; - - /* check xine-lib version */ - if(!xine_check_version(1, 1, 0)) { - LOGERR("xine-lib is too old, require at least xine library version 1.1.0\n"); - return FE_ERROR; - } - - - /* - * 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_plugin = NULL; - - /* create a new xine and load config file */ - this->xine = xine_new(); - if(!this->xine) - return 0; - - /* Set xine engine logging verbosity */ - this->xine->verbosity = (SysLogLevel>2); - - /*xine_register_log_cb(this->xine, xine_log_cb, this);*/ - - free(this->configfile); - this->configfile = NULL; - if (config_file) - this->configfile = strdup(config_file); - else if(asprintf(&this->configfile, "%s%s", xine_get_homedir(), - "/.xine/config_xineliboutput") < 0) - return 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); - - if(this->video_port_name) { - if(video_driver && !strcmp(video_driver, "fb")) - x_upd_str("video.device.fb_device", this->video_port_name); - } - - 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); - return 0; - } - - this->video_port_none = NULL; - - /* re-configure display size (DirectFB driver changes display mode in init) */ - if(this->update_display_size_cb) - this->update_display_size_cb(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"); - xine_exit(this->xine); - 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 = calloc(1, 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) { - if(!xine_check_version(1,1,9)) - LOGMSG("FFmpeg multithreaded video decoding is not supported in xine-lib < 1.1.9"); - else - LOGMSG("Enabling FFmpeg 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_plugin = NULL; - this->playback_finished = 1; - this->terminate_key_pressed = 0; - - if (asprintf(&url, "%s#nocache", mrl ? : MRL_ID "://") < 0) - return 0; - - 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); - - 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:%s\") post plugin", name, args); - } - - 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; - - if(!this) - return 0; - - fe_post_rewire(this); - - this->input_plugin = NULL; - this->playback_finished = xine_play(this->stream, 0, 0) ? 0 : 1; - - if(!find_input_plugin(this)) - return -1; - - this->input_plugin->f.xine_input_event = this->keypress; - this->input_plugin->f.fe_control = fe_control; - this->input_plugin->f.fe_handle = this_gen; - - if(this->playback_finished) - LOGMSG("Error playing " MRL_ID ":// !"); - - char str[128]; - snprintf(str, sizeof(str), "INFO WINDOW %dx%d", this->width, this->height); - this->fe.send_event(&this->fe, str); - - 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_plugin = 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) { - if(this->input_plugin) { - this->input_plugin->f.xine_input_event = NULL; - this->input_plugin->f.fe_control = NULL; - } - - 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_plugin || !this->playback_finished) - fe_xine_close(this_gen); - fe_post_unload(this); - - if(this->configfile) { - xine_config_save (this->xine, this->configfile); - free(this->configfile); - this->configfile = NULL; - } - 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->configfile); - free(this); - } -} - -static int fe_is_finished(frontend_t *this_gen, int slave_stream) -{ - fe_t *this = (fe_t*)this_gen; - - if (!this) - return FE_XINE_ERROR; - if (this->terminate_key_pressed) - return FE_XINE_EXIT; - if (this->playback_finished) - return FE_XINE_ERROR; - - if (slave_stream) { - if (!this->slave_stream || this->slave_playback_finished) - return FE_XINE_EXIT; - } - - return FE_XINE_RUNNING; -} - -/************************** hooks to input plugin ****************************/ - -/* - * data/control from VDR - */ - -static int xine_control(frontend_t *this_gen, const char *cmd) -{ - fe_t *this = (fe_t*)this_gen; - - if(!find_input_plugin(this)) - return -1; - - return this->input_plugin->f.push_input_control(this->input_plugin, cmd); -} - -static int xine_osd_command(frontend_t *this_gen, struct osd_command_s *cmd) { - fe_t *this = (fe_t*)this_gen; - - if(!find_input_plugin(this)) - return -1; - - return this->input_plugin->f.push_input_osd(this->input_plugin, cmd); -} - -static int xine_queue_pes_packet(frontend_t *this_gen, const char *data, int len) -{ - fe_t *this = (fe_t*)this_gen; - - if(!find_input_plugin(this)) - return 0/*-1*/; - - return this->input_plugin->f.push_input_write(this->input_plugin, data, len); -} - -/* - * control from frontend to xine/vdr - */ - - -static int fe_send_input_event(frontend_t *this_gen, const char *map, - const char *key, int repeat, int release) -{ - fe_t *this = (fe_t*)this_gen; - - LOGDBG("Keypress: %s %s %s %s", - map, key, repeat?"Repeat":"", release?"Release":""); - - /* local mode: --> vdr callback */ - if(this->keypress) { - this->keypress(map, key); - return FE_OK; - } - - /* remote mode: --> input plugin --> vdr */ - if (find_input_plugin(this)) { - if (this->input_plugin->f.post_vdr_event) { - - char *msg = NULL; - if (map) { - if (asprintf(&msg, "KEY %s %s %s %s\r\n", map, key, - repeat?"Repeat":"", release?"Release":"") < 0) - msg = NULL; - } else { - if (asprintf(&msg, "KEY %s\r\n", key) < 0) - msg = NULL; - } - - if (msg) { - int r = this->input_plugin->f.post_vdr_event(this->input_plugin, msg); - free(msg); - if (r > 0) - return FE_OK; - } - LOGMSG("fe_send_input_event: message KEY %s lost", key); - return FE_ERROR; - } - } - - LOGMSG("fe_send_input_event: handler not set, event lost !"); - return FE_ERROR; -} - - -static int fe_send_event(frontend_t *this_gen, const char *data) -{ - fe_t *this = (fe_t*)this_gen; - - if (!data) - return FE_ERROR; - - if (!strcmp(data, "TOGGLE_FULLSCREEN")) { - if(this->toggle_fullscreen_cb) - this->toggle_fullscreen_cb(this_gen); - - } else if (!strcmp(data, "QUIT")) { - this->terminate_key_pressed = 1; - - } else if(!strcmp(data, "TOGGLE_DEINTERLACE")) { - xine_set_param(this->stream, XINE_PARAM_VO_DEINTERLACE, - xine_get_param(this->stream, XINE_PARAM_VO_DEINTERLACE) ? 0 : 1); - - } else if(!strncasecmp(data, "DEINTERLACE ", 12)) { - xine_set_param(this->stream, XINE_PARAM_VO_DEINTERLACE, atoi(data+12) ? 1 : 0); - - } else { - - LOGDBG("Event: %s", data); - - /* local mode: --> vdr callback */ - if (this->keypress) { - this->keypress(data, NULL); - return FE_OK; - } - - /* remote mode: --> input plugin --> vdr */ - if (find_input_plugin(this)) { - if (this->input_plugin->f.post_vdr_event) { - char *msg = NULL; - if (asprintf(&msg, "%s\r\n", data) < 1) - msg = NULL; - if (msg) { - int r = this->input_plugin->f.post_vdr_event(this->input_plugin, msg); - free(msg); - return (r > 0) ? FE_OK : FE_ERROR; - } - return FE_ERROR; - } - } - } - - return FE_OK; -} - -/* - * 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); - this->video_width = this->video_height = 0; - - } else if(!strncmp(cmd, "SLAVE 0x", 8)) { - unsigned long pt; - if(1 == sscanf(cmd+8, "%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; - this->video_width = this->video_height = 0; - } - - } 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+10, "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, MRL_ID "+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); - } - } - - - return NULL; -} - -/* - * --- RgbToJpeg ------------------------------------------------------------- - * - * source: vdr-1.3.42, tools.c - * modified to accept YUV data - * - * - 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 vo_frame_t *yuy2_to_yv12_frame(xine_stream_t *stream, vo_frame_t *frame) -{ - /* convert yuy12 frames to yv12 */ - if (frame && frame->format == XINE_IMGFMT_YUY2) { - stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0); - vo_frame_t *img = stream->video_out->get_frame (stream->video_out, - frame->width, frame->height, - frame->ratio, XINE_IMGFMT_YV12, - VO_BOTH_FIELDS); - stream->xine->port_ticket->release(stream->xine->port_ticket, 0); - - if (!img) { - LOGMSG("yuy2_to_yv12_frame: 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); - return img; - } - - return frame; -} - -static char *frame_compress_jpeg(fe_t *this, int *size, int quality, vo_frame_t *frame) -{ - struct jpeg_destination_mgr jdm; - struct jpeg_compress_struct cinfo; - struct jpeg_error_mgr jerr; - tJpegCompressData jcd; - - /* convert yuy2 frames to yv12 */ - frame = yuy2_to_yv12_frame(this->stream, frame); - - /* 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 = frame->width; - cinfo.image_height = frame->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) * frame->height); - JSAMPROW *rpU = (JSAMPROW*)malloc(sizeof(JSAMPROW) * frame->height); - JSAMPROW *rpV = (JSAMPROW*)malloc(sizeof(JSAMPROW) * frame->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 < frame->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 < frame->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; -} - -static vo_frame_t *yv12_to_yuy2_frame(xine_stream_t *stream, vo_frame_t *frame) -{ - /* convert yv12 frames to yuy2 */ - if (frame && frame->format == XINE_IMGFMT_YV12) { - stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0); - vo_frame_t *img = stream->video_out->get_frame (stream->video_out, - frame->width, frame->height, - frame->ratio, XINE_IMGFMT_YUY2, - VO_BOTH_FIELDS); - stream->xine->port_ticket->release(stream->xine->port_ticket, 0); - - if (!img) { - LOGMSG("yv12_to_yuy2_frame: get_frame failed"); - frame->free(frame); - return NULL; - } - - init_yuv_conversion(); - yv12_to_yuy2(frame->base[0], frame->pitches[0], - frame->base[1], frame->pitches[1], - frame->base[2], frame->pitches[2], - img->base[0], img->pitches[0], - frame->width, frame->height, - frame->progressive_frame); - - frame->free(frame); - return img; - } - - return frame; -} - -#define YCBCR_TO_RGB( y, cb, cr, r, g, b ) \ - do { \ - int _y, _cb, _cr, _r, _g, _b; \ - _y = ((y) - 16) * 76309; \ - _cb = (cb) - 128; \ - _cr = (cr) - 128; \ - _r = (_y + _cr * 104597 + 0x8000) >> 16; \ - _g = (_y - _cb * 25675 - _cr * 53279 + 0x8000) >> 16; \ - _b = (_y + _cb * 132201 + 0x8000) >> 16; \ - (r) = (_r < 0) ? 0 : ((_r > 255) ? 255 : _r); \ - (g) = (_g < 0) ? 0 : ((_g > 255) ? 255 : _g); \ - (b) = (_b < 0) ? 0 : ((_b > 255) ? 255 : _b); \ -} while (0) - -static char *frame_compress_pnm(fe_t *this, int *size, vo_frame_t *frame) -{ - /* ensure yuy2 */ - if (!(frame = yv12_to_yuy2_frame(this->stream, frame))) - return NULL; - - /* convert to PNM */ - - /* allocate memory for result */ - size_t bytes = frame->width * frame->height * 3; - uint8_t *pnm = malloc(bytes + 64); - if (!pnm) { - LOGMSG("fe_grab: malloc failed"); - return NULL; - } - - /* PNM header */ - sprintf((char*)pnm, "P6\n%d\n%d\n255\n", frame->width, frame->height); - int hdrlen = strlen((char*)pnm); - uint8_t *p = pnm + hdrlen; - uint8_t *s = frame->base[0]; - int x, y; - - *size = bytes + hdrlen; - - /* convert to RGB */ - for (y=0; y < frame->height; y++) { - for (x=0; x < frame->width; x+=2, s+=4, p+=6) { - YCBCR_TO_RGB(s[0], s[1], s[3], p[0], p[1], p[2]); - YCBCR_TO_RGB(s[2], s[1], s[3], p[3], p[4], p[5]); - } - s = frame->base[0] + y*frame->pitches[0]; - } - - return (char*)pnm; -} - -#ifdef XINE_GUI_SEND_GRAB_FRAME -static char *fe_grab_raw_frame(fe_t *this, int *size, int jpeg, int quality, int width, int height, xine_grab_frame_t *frame) -{ - frame->width = width; - frame->height = height; - if (xine_port_send_gui_data(this->stream->video_out, XINE_GUI_SEND_GRAB_FRAME, frame)) - return NULL; - - if (jpeg) { - /* Compress JPEG */ - struct jpeg_destination_mgr jdm; - struct jpeg_compress_struct cinfo; - struct jpeg_error_mgr jerr; - tJpegCompressData jcd; - - 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_RGB; - - jpeg_set_defaults(&cinfo); - jpeg_set_quality(&cinfo, quality, TRUE); - jpeg_start_compress(&cinfo, TRUE); - - JSAMPROW rp[height]; - int rs = width * 3; - int k; - for (k = 0; k < height; k++) - rp[k] = frame->img + k * rs; - jpeg_write_scanlines(&cinfo, rp, height); - - jpeg_finish_compress(&cinfo); - jpeg_destroy_compress(&cinfo); - - *size = jcd.size; - return (char*) jcd.mem; - } - - /* convert to PNM */ - - /* allocate memory for result */ - size_t bytes = width * height * 3; - uint8_t *pnm = malloc(bytes + 64); - if (!pnm) { - LOGMSG("fe_grab: malloc failed"); - return NULL; - } - - /* PNM header */ - sprintf((char*)pnm, "P6\n%d\n%d\n255\n", width, height); - int hdrlen = strlen((char*)pnm); - - /* copy image */ - xine_fast_memcpy(pnm + hdrlen, frame->img, bytes); - - *size = bytes + hdrlen; - return (char*)pnm; -} -#endif - -static char *fe_grab(frontend_t *this_gen, int *size, int jpeg, - int quality, int width, int height) -{ - fe_t *this = (fe_t*)this_gen; - vo_frame_t *frame; - - if(!find_input_plugin(this)) - return 0; - - LOGDBG("fe_grab: grabbing %s %d %dx%d", - jpeg ? "JPEG" : "PNM", quality, width, height); - - /* validate parameters */ - if ((quality < 0) || (quality > 100)) - quality = 100; - width = (MAX(16, MIN(width, 1920)) + 1) & ~1; /* 16...1920, even */ - height = (MAX(16, MIN(width, 1200)) + 1) & ~1; /* 16...1200, even */ - - /* get last frame */ - this->stream->xine->port_ticket->acquire(this->stream->xine->port_ticket, 0); -#ifdef XINE_GUI_SEND_GRAB_FRAME - xine_grab_frame_t *grab_frame; - if (!xine_port_send_gui_data(this->stream->video_out, XINE_GUI_SEND_ALLOC_GRAB_FRAME, &grab_frame)) { - char *img = fe_grab_raw_frame(this, size, jpeg, quality, width, height, grab_frame); - xine_port_send_gui_data(this->stream->video_out, XINE_GUI_SEND_FREE_GRAB_FRAME, grab_frame); - this->stream->xine->port_ticket->release(this->stream->xine->port_ticket, 0); - return img; - } -#endif - 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) { - LOGMSG("fe_grab: get_last_frame() failed"); - return NULL; - } - - /* Scale image */ - if (frame->width != width || frame->height != height) { - /* #warning TODO - scaling here */ - LOGMSG("fe_grab: scaling not implemented"); - } - - if (!jpeg) - return frame_compress_pnm(this, size, frame); - - return frame_compress_jpeg(this, size, quality, frame); -} - -/* - * init_fe() - * - * initialize function pointers - */ -void init_fe(fe_t *fe) -{ - fe->fe.xine_init = fe_xine_init; - fe->fe.xine_open = fe_xine_open; - fe->fe.xine_play = fe_xine_play; - fe->fe.xine_stop = fe_xine_stop; - fe->fe.xine_close = fe_xine_close; - fe->fe.xine_exit = fe_xine_exit; - - fe->fe.fe_free = fe_free; - - fe->fe.xine_is_finished = fe_is_finished; - - fe->fe.xine_osd_command = xine_osd_command; - fe->fe.xine_control = xine_control; - fe->fe.xine_queue_pes_packet = xine_queue_pes_packet; - - fe->fe.grab = fe_grab; - - fe->fe.send_event = fe_send_event; - fe->fe.send_input_event = fe_send_input_event; - - fe->dest_pixel_aspect = fe_dest_pixel_aspect; - fe->frame_output_handler = fe_frame_output_cb; -} - -#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 f588dc04..00000000 --- a/xine_frontend.h +++ /dev/null @@ -1,130 +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.19 2009-05-31 16:51:25 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; - -struct osd_command_s; - -#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 - -/* xine_is_finished return values */ -#define FE_XINE_RUNNING 0 -#define FE_XINE_ERROR -1 -#define FE_XINE_EXIT 1 - -/* return values */ -#define FE_OK 1 -#define FE_ERROR 0 - -struct frontend_s { - /* Display */ - int (*fe_display_open)(frontend_t*, - int xpos, int ypos, - int winwidth, int winheight, - int fullscreen, int hud, int modeswitch, const char *modeline, - int aspect, fe_keypress_f keypresshandler, - int no_x_kbd, int gui_hotkeys, - const char *video_port, - int scale_video, int field_order, - const char *aspect_controller, int window_id); - int (*fe_display_config)(frontend_t *, - int xpos, int ypos, - 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, - const char *config_file); - 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*); - - int (*xine_is_finished)(frontend_t*, int slave_stream); - - /* Data transfer VDR -> frontend/xine */ - 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); - - /* events from frontend -> xine/vdr */ - int (*send_event)(frontend_t *fe, const char *data); - int (*send_input_event)(frontend_t *fe, - const char *map, const char *key, - int repeat, int release); -#if 0 - frontend_config_t config; -#endif -}; - -typedef frontend_t *(*fe_creator_f)(void); - -void list_xine_plugins(frontend_t *fe, int verbose); - - -#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 f5403dbb..00000000 --- a/xine_frontend_lirc.c +++ /dev/null @@ -1,280 +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.21.2.1 2009-08-21 11:23:45 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. - * - */ - - -#include <stdint.h> -#include <stdio.h> -#include <unistd.h> -#include <pthread.h> -#include <netinet/in.h> -#include <sys/time.h> -#include <sys/socket.h> -#include <sys/un.h> - -#include "logdefs.h" - -#include "xine_frontend.h" -#include "xine_frontend_lirc.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; - -/* xine_frontend_main.c: */ -extern int gui_hotkeys; - -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; - strncpy(addr.sun_path, (char*)lirc_device_name, sizeof(addr.sun_path)); - addr.sun_path[sizeof(addr.sun_path)-1] = 0; - - 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_gen) -{ - frontend_t *fe = (frontend_t*)fe_gen; - 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"); - - const int priority = -1; - errno = 0; - if((nice(priority) == -1) && errno) - LOGDBG("LIRC: Can't nice to value: %d", priority); - - lircd_connect(); - - while(lirc_device_name && fd_lirc >= 0) { - fd_set set; - int ready, ret = -1; - FD_ZERO(&set); - FD_SET(fd_lirc, &set); - - pthread_testcancel(); - 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); - } - - pthread_testcancel(); - if(ready < 0) { - LOGMSG("LIRC connection lost ?"); - break; - } - - if(ready) { - - do { - errno = 0; - ret = read(fd_lirc, buf, sizeof(buf)); - pthread_testcancel(); - } while(ret < 0 && errno == EINTR); - - if (ret <= 0 ) { - /* try reconnecting */ - LOGERR("LIRC connection lost"); - lircd_connect(); - while(lirc_device_name && fd_lirc < 0) { - pthread_testcancel(); - 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); - fe->send_input_event(fe, "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 (gui_hotkeys) { - if(!strcmp(KeyName, "Quit")) { - fe->send_event(fe, "QUIT"); - break; - } - if(!strcmp(KeyName, "Fullscreen")) { - if(!repeat) - fe->send_event(fe, "TOGGLE_FULLSCREEN"); - continue; - } - if(!strcmp(KeyName, "Deinterlace")) { - if(!repeat) - fe->send_event(fe, "TOGGLE_DEINTERLACE"); - continue; - } - } - - alarm(3); - fe->send_input_event(fe, "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); - fe->send_input_event(fe, "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(struct frontend_s *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_lirc.h b/xine_frontend_lirc.h deleted file mode 100644 index df3972a6..00000000 --- a/xine_frontend_lirc.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * xine_frontend_lirc.h: - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: xine_frontend_lirc.h,v 1.3 2008-11-13 22:58:40 phintuka Exp $ - * - */ - -#ifndef XINE_FRONTEND_LIRC_H -#define XINE_FRONTEND_LIRC_H - -struct frontend_s; - -void lirc_start(struct frontend_s *fe, char *lirc_dev, int repeat_emu); -void lirc_stop(void); - -#endif /* XINE_FRONTEND_LIRC_H */ diff --git a/xine_frontend_main.c b/xine_frontend_main.c deleted file mode 100644 index fb8aec14..00000000 --- a/xine_frontend_main.c +++ /dev/null @@ -1,847 +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.2.17 2009-08-21 11:50:41 phintuka Exp $ - * - */ - -#include <stdio.h> -#include <inttypes.h> -#include <stdlib.h> -#include <string.h> -#include <poll.h> -#include <errno.h> -#include <termios.h> -#include <pthread.h> -#include <unistd.h> -#include <syslog.h> -#include <getopt.h> -#include <signal.h> - -#include <xine.h> /* xine_get_version */ - -#include "logdefs.h" - -#include "xine_input_vdr_mrl.h" -#include "xine_frontend.h" -#include "tools/vdrdiscovery.h" -#include "xine_frontend_lirc.h" - -/* static data */ - -/* next symbol is dynamically linked from input plugin */ -int SysLogLevel __attribute__((visibility("default"))) = SYSLOGLEVEL_INFO; /* errors and info, no debug */ - -volatile int last_signal = 0; -int gui_hotkeys = 0; - -/* - * stdin (keyboard/slave mode) reading - */ - -/* static data */ -pthread_t kbd_thread; -struct termios tm, saved_tm; - -/* include LIRC forwarding code */ -#include "xine_frontend_lirc.c" - -/* - * read_key() - * - * Try to read single char from stdin. - * - * Returns: >=0 char readed - * -1 nothing to read - * -2 fatal error - */ -#define READ_KEY_ERROR -2 -#define READ_KEY_EAGAIN -1 -static int read_key(void) -{ - unsigned char ch; - int err; - struct pollfd pfd; - pfd.fd = STDIN_FILENO; - pfd.events = POLLIN; - - errno = 0; - pthread_testcancel(); - - if (1 == (err = poll(&pfd, 1, 50))) { - pthread_testcancel(); - - 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 READ_KEY_ERROR; - - } else if (err < 0 && errno != EINTR) { - LOGERR("read_key: poll(stdin) failed"); - return READ_KEY_ERROR; - } - - pthread_testcancel(); - return READ_KEY_EAGAIN; -} - -/* - * read_key_seq() - * - * Read a key sequence from stdin. - * Key sequence is either normal key or escape sequence. - * - * Returns the key or escape sequence as uint64_t. - */ -#define READ_KEY_SEQ_ERROR 0xffffffff -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 == READ_KEY_ERROR) - return READ_KEY_SEQ_ERROR; - - return k; -} - -/* - * kbd_receiver_thread() - * - * Read key(sequence)s from stdin and pass those to frontend. - */ - -static void kbd_receiver_thread_cleanup(void *arg) -{ - int status; - tcsetattr(STDIN_FILENO, TCSANOW, &saved_tm); - status = system("setterm -cursor on"); - LOGMSG("Keyboard thread terminated"); -} - -static void *kbd_receiver_thread(void *fe_gen) -{ - frontend_t *fe = (frontend_t*)fe_gen; - uint64_t code = 0; - char str[64]; - int status; - - status = system("setterm -cursor off"); - status = 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); - } - - pthread_cleanup_push(kbd_receiver_thread_cleanup, NULL); - - do { - alarm(0); - errno = 0; - code = read_key_seq(); - alarm(3); /* watchdog */ - if (code == 0) - continue; - if (code == READ_KEY_SEQ_ERROR) - break; - if (code == 27) { - fe->send_event(fe, "QUIT"); - break; - } - - if (gui_hotkeys) { - if (code == 'f' || code == 'F') { - fe->send_event(fe, "TOGGLE_FULLSCREEN"); - continue; - } else if (code == 'd' || code == 'D') { - fe->send_event(fe, "TOGGLE_DEINTERLACE"); - continue; - } - } - - snprintf(str, sizeof(str), "%016" PRIX64, code); - fe->send_input_event(fe, "KBD", str, 0, 0); - - } while (fe->xine_is_finished(fe, 0) != FE_XINE_EXIT); - - alarm(0); - - LOGDBG("Keyboard thread terminating"); - - pthread_cleanup_pop(1); - - pthread_exit(NULL); - return NULL; /* never reached */ -} - -/* - * slave_receiver_thread() - * - * Read slave mode commands from stdin - * Interpret and execute valid commands - */ - -static void slave_receiver_thread_cleanup(void *arg) -{ - /* restore terminal settings */ - tcsetattr(STDIN_FILENO, TCSANOW, &saved_tm); - LOGDBG("Slave mode receiver terminated"); -} - -static void *slave_receiver_thread(void *fe_gen) -{ - frontend_t *fe = (frontend_t*)fe_gen; - char str[128], *pt; - - tcgetattr(STDIN_FILENO, &saved_tm); - - pthread_cleanup_push(slave_receiver_thread_cleanup, NULL); - - do { - errno = 0; - str[0] = 0; - - pthread_testcancel(); - if (!fgets(str, sizeof(str), stdin)) - break; - pthread_testcancel(); - - if (NULL != (pt = strchr(str, '\r'))) - *pt = 0; - if (NULL != (pt = strchr(str, '\n'))) - *pt = 0; - - if (!strncasecmp(str, "QUIT", 4)) { - fe->send_event(fe, "QUIT"); - break; - } - if (!strncasecmp(str, "FULLSCREEN", 10)) { - fe->send_event(fe, "TOGGLE_FULLSCREEN"); - continue; - } - if (!strncasecmp(str, "DEINTERLACE ", 12)) { - fe->send_event(fe, str); - continue; - } - if (!strncasecmp(str, "HITK ", 5)) { - fe->send_input_event(fe, NULL, str+5, 0, 0); - continue; - } - - LOGMSG("Unknown slave mode command: %s", str); - - } while (fe->xine_is_finished(fe, 0) != FE_XINE_EXIT); - - LOGDBG("Slave mode receiver terminating"); - - pthread_cleanup_pop(1); - - pthread_exit(NULL); - return NULL; /* never reached */ -} - -/* - * kbd_start() - * - * Start keyboard/slave mode reader thread - */ -static void kbd_start(frontend_t *fe, int slave_mode) -{ - int err; - 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)); - } -} - -/* - * kbd_stop() - * - * Stop keyboard/slave mode reader thread - */ -static void kbd_stop(void) -{ - void *p; - - pthread_cancel(kbd_thread); - pthread_join(kbd_thread, &p); -} - -/* - * SignalHandler() - */ -static void SignalHandler(int signum) -{ - LOGMSG("caught signal %d", signum); - - switch (signum) { - case SIGHUP: - last_signal = signum; - case SIGPIPE: - break; - default: - if (last_signal) { - LOGMSG("SignalHandler: exit(-1)"); - exit(-1); - } - last_signal = signum; - break; - } - - signal(signum, SignalHandler); -} - -/* - * strcatrealloc() - */ -static char *strcatrealloc(char *dest, const char *src) -{ - size_t 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 data - */ - -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" -#ifdef HAVE_XRENDER - " --hud Head Up Display OSD mode\n" -#endif - " --width=x Video window width\n" - " --height=x Video window height\n" - " --geometry=WxH[+X+Y] Set output window geometry (X style)\n" - " --buffers=x Number of PES buffers\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" - " --config=file Use config file (default: ~/.xine/config_xineliboutput).\n" - " --verbose Verbose debug output\n" - " --silent Silent mode (report only errors)\n" - " --syslog Write all output to system log\n" - " --nokbd Disable console keyboard input\n" -#ifndef IS_FBFE - " --noxkbd Disable X11 keyboard input\n" -#endif - " --hotkeys Enable frontend GUI hotkeys\n" - " --terminal=dev Controlling tty" - " --daemon Run as daemon (disable keyboard,\n" - " log to syslog and fork to background)\n" - " --slave Enable slave mode (read commands from stdin)\n" - " --reconnect Automatically reconnect when connection has been lost\n" - " --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[] = "HA:V:d:W:a:fg:Dw:h:B:nP:L:C:T:vsxlkobSRtur"; - -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' }, - { "geometry", required_argument, NULL, 'g' }, - { "hud", no_argument, NULL, 'D' }, - { "width", required_argument, NULL, 'w' }, - { "height", required_argument, NULL, 'h' }, - { "buffers", required_argument, NULL, 'B' }, - { "noscaling", no_argument, NULL, 'n' }, - { "post", required_argument, NULL, 'P' }, - { "lirc", optional_argument, NULL, 'L' }, - { "config", required_argument, NULL, 'C' }, - { "terminal", required_argument, NULL, 'T' }, - - { "verbose", no_argument, NULL, 'v' }, - { "silent", no_argument, NULL, 's' }, - { "syslog", no_argument, NULL, 'l' }, - { "nokbd", no_argument, NULL, 'k' }, - { "noxkbd", no_argument, NULL, 'x' }, - { "hotkeys", no_argument, NULL, 'o' }, - { "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[]) -{ - int ftcp = 0, fudp = 0, frtp = 0, reconnect = 0, firsttry = 1; - int fullscreen = 0, hud = 0, xpos = 0, ypos = 0, width = 720, height = 576; - int pes_buffers = 250; - int scale_video = 1, aspect = 1; - int daemon_mode = 0, nokbd = 0, noxkbd = 0, slave_mode = 0; - int repeat_emu = 0; - int window_id = -1; - int xmajor, xminor, xsub; - int c; - int xine_finished = FE_XINE_ERROR; - char *mrl = NULL; - char *video_driver = NULL; - char *audio_driver = NULL; - char *audio_device = NULL; - char *video_port = NULL; - char *static_post_plugins = NULL; - char *lirc_dev = NULL; - char *aspect_controller = NULL; - const char *tty = NULL; - const char *exec_name = argv[0]; - const char *config_file = NULL; - - extern const fe_creator_f fe_creator; - frontend_t *fe = NULL; - - LogToSysLog = 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] [" MRL_ID "[+udp|+tcp|+rtp]:[//host[:port]]] \n" - "\nAvailable options:\n", exec_name); - printf("%s", help_str); - list_xine_plugins(NULL, SysLogLevel>2); - exit(0); - case 'A': audio_driver = strdup(optarg); - audio_device = strchr(audio_driver, ':'); - if (audio_device) - *(audio_device++) = 0; - PRINTF("Audio driver: %s\n", audio_driver); - if (audio_device) - PRINTF("Audio device: %s\n", audio_device); - break; - case 'V': video_driver = strdup(optarg); - video_port = strchr(video_driver, ':'); - if (video_port) - *(video_port++) = 0; - PRINTF("Video driver: %s\n", video_driver); - if (video_port) - PRINTF("Video port: %s\n", video_port); - break; -#ifndef IS_FBFE - case 'W': window_id = atoi(optarg); - break; - case 'd': video_port = strdup(optarg); - break; - case 'x': noxkbd = 1; - 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[4] == ':') - 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; -#ifdef HAVE_XRENDER - PRINTF("HUD OSD mode\n"); -#else - PRINTF("HUD OSD not supported\n"); -#endif - break; - case 'w': width = atoi(optarg); - PRINTF("Width: %d\n", width); - break; - case 'g': sscanf (optarg, "%dx%d+%d+%d", &width, &height, &xpos, &ypos); - PRINTF("Geometry: %dx%d+%d+%d\n", width, height, xpos, ypos); - break; - case 'h': height = atoi(optarg); - PRINTF("Height: %d\n", height); - break; - case 'B': pes_buffers = atoi(optarg); - PRINTF("Buffers: %d\n", pes_buffers); - break; - case 'T': tty = optarg; - if (access(tty, R_OK | W_OK) < 0) { - PRINTF("Can't access terminal: %s\n", tty); - return -2; - } - PRINTF("Terminal: %s", tty); - 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 'C': config_file = optarg; - PRINTF("Config file: %s\n", config_file); - break; - case 'L': lirc_dev = strdup(optarg ? : "/dev/lircd"); - if (strstr(lirc_dev, ",repeatemu")) { - *strstr(lirc_dev, ",repeatemu") = 0; - repeat_emu = 1; - } - PRINTF("LIRC device: %s%s\n", lirc_dev, - repeat_emu?", emulating key repeat":""); - break; - case 'v': SysLogLevel = (SysLogLevel<SYSLOGLEVEL_DEBUG) ? SYSLOGLEVEL_DEBUG : SysLogLevel+1; - PRINTF("Verbose mode\n"); - break; - case 's': 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 'o': gui_hotkeys = 1; - PRINTF("GUI hotkeys enabled\n" - " mapping keyboard f,F -> fullscreen toggle\n" - " keyboard d,D -> deinterlace toggle\n" - " LIRC Deinterlace -> deinterlace toggle\n" - " LIRC Fullscreen -> fullscreen toggle\n" - " LIRC Quit -> exit\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"); - - if (tty) { - /* claim new controlling terminal */ - stdin = freopen(tty, "r", stdin); - stdout = freopen(tty, "w", stdout); - stderr = freopen(tty, "w", stderr); - } - -#if 1 - /* backward compability */ - if (mrl && ( !strncmp(mrl, MRL_ID ":tcp:", MRL_ID_LEN+5) || - !strncmp(mrl, MRL_ID ":udp:", MRL_ID_LEN+5) || - !strncmp(mrl, MRL_ID ":rtp:", MRL_ID_LEN+5) || - !strncmp(mrl, MRL_ID ":pipe:", MRL_ID_LEN+6))) - mrl[4] = '+'; -#endif - - /* If server address not given, try to find server automatically */ - if (!mrl || - !strcmp(mrl, MRL_ID ":") || - !strcmp(mrl, MRL_ID "+tcp:") || - !strcmp(mrl, MRL_ID "+udp:") || - !strcmp(mrl, MRL_ID "+rtp:") || - !strcmp(mrl, MRL_ID "+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; - if (asprintf(&mrl, "%s//%s:%d", tmp, address, port) < 0) - return -1; - free(tmp); - } else - if (asprintf(&mrl, MRL_ID "://%s:%d", address, port) < 0) - return -1; - } 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(MRL_ID "://127.0.0.1"); - } - } - - if (mrl && - strncmp(mrl, MRL_ID ":", MRL_ID_LEN+1) && - strncmp(mrl, MRL_ID "+", MRL_ID_LEN+1)) { - char *mrl2 = mrl; - PRINTF("WARNING: MRL does not start with \'" MRL_ID ":\' (%s)", mrl); - if (asprintf(&mrl, MRL_ID "://%s", mrl) < 0) - return -1; - free(mrl2); - } - - { - char *tmp = NULL, *mrl2 = mrl; - if (frtp && !strstr(mrl, "rtp:")) - tmp = strdup(MRL_ID "+rtp:"); - else if (fudp && !strstr(mrl, "udp:")) - tmp = strdup(MRL_ID "+udp:"); - else if (ftcp && !strstr(mrl, "tcp:")) - tmp = strdup(MRL_ID "+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; - } - - /* Initialize display */ - if (!fe->fe_display_open(fe, xpos, ypos, width, height, fullscreen, hud, 0, - "", aspect, NULL, noxkbd, gui_hotkeys, - video_port, scale_video, 0, - aspect_controller, window_id)) { - fprintf(stderr, "Error opening display\n"); - fe->fe_free(fe); - return -4; - } - - /* Initialize xine */ - if (!fe->xine_init(fe, audio_driver, audio_device, video_driver, - pes_buffers, static_post_plugins, config_file)) { - fprintf(stderr, "Error initializing xine\n"); - list_xine_plugins(fe, SysLogLevel>2); - fe->fe_free(fe); - return -5; - } - - if (SysLogLevel > 2) - list_xine_plugins(fe, SysLogLevel>2); - - /* 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); - - 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); - fe->fe_free(fe); - return -6; - } - - if (!fe->xine_play(fe)) { - if (!firsttry) { - PRINTF("Error playing %s\n", argv[1]); - continue; - } - fprintf(stderr, "Error playing %s\n", argv[1]); - fe->fe_free(fe); - return -7; - } - - if (firsttry) { - - /* Start LIRC forwarding */ - lirc_start(fe, lirc_dev, repeat_emu); - - /* Start keyboard listener thread */ - if (!nokbd) { - PRINTF("\n\nPress Esc to exit\n\n"); - kbd_start(fe, slave_mode); - } - } - - /* Main loop */ - - sleep(2); /* give input_vdr some time to establish connection */ - - fflush(stdout); - fflush(stderr); - - while (!last_signal && fe->fe_run(fe)) - ; - xine_finished = fe->xine_is_finished(fe,0); - - fe->xine_close(fe); - firsttry = 0; - - /* HUP reconnects */ - if (last_signal == SIGHUP) - last_signal = 0; - - } while (!last_signal && xine_finished != FE_XINE_EXIT && reconnect); - - /* Clean up */ - - PRINTF("Terminating...\n"); - - fe->send_event(fe, "QUIT"); - - /* stop input threads */ - lirc_stop(); - if (!nokbd) - kbd_stop(); - - fe->fe_free(fe); - - free(static_post_plugins); - free(mrl); - free(audio_driver); - free(video_driver); - free(aspect_controller); - free(lirc_dev); - - return xine_finished==FE_XINE_EXIT ? 0 : 1; -} diff --git a/xine_input_vdr.c b/xine_input_vdr.c deleted file mode 100644 index a553f56c..00000000 --- a/xine_input_vdr.c +++ /dev/null @@ -1,6977 +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.138.2.40 2009-11-15 12:35:53 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> - -#if XINE_VERSION_CODE >= 10190 -# include <libavutil/mem.h> -#endif -#ifndef XINE_VERSION_CODE -# error XINE_VERSION_CODE undefined ! -#endif - -#include "xine_input_vdr.h" -#include "xine_input_vdr_net.h" -#include "xine_osd_command.h" - -#include "tools/mpeg.h" -#include "tools/pes.h" -#include "tools/ts.h" - -/***************************** DEFINES *********************************/ - -/* Support for ffmpeg mpeg2 decoder. - Priority must be increased in $HOME/.xine/config_xineliboutput: - engine.decoder_priorities.ffmpegvideo:1 -*/ -#define FFMPEG_DEC -/* Support for dshowserver/CoreAVC H.264 decoder */ -#define COREAVC_DEC - -/*#define LOG_UDP*/ -/*#define LOG_OSD*/ -/*#define LOG_CMD*/ -/*#define LOG_SCR*/ -/*#define LOG_TRACE*/ -/*#define LOG_GRAPH*/ - -#define METRONOM_PREBUFFER_VAL (4 * 90000 / 25 ) -#define HD_BUF_NUM_BUFS (2500) /* 2k payload * 2500 = 5MB */ -#define HD_BUF_ELEM_SIZE (2048+64) -#define HD_BUF_RESERVED_BUFS 2 -#define TEST_H264 1 -#define TEST_DVB_SPU 1 /* process DVB SPUs */ -#define TEST_DVD_SPU 1 /* process DVD SPUs */ -#define VDR_SUBTITLES 1 /* compability mode for vdr-subtitles plugin */ - -#define RADIO_MAX_BUFFERS 10 - -#define SLAVE_VIDEO_FIFO_SIZE 1000 - -#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_BASE ( 0x0f000000) /* 0x0f000000 */ -#define CONTROL_BUF_BLANK (CONTROL_BUF_BASE|0x00010000) /* 0x0f010000 */ -#define CONTROL_BUF_CLEAR (CONTROL_BUF_BASE|0x00020000) /* 0x0f020000 */ -#define BUF_NETWORK_BLOCK (BUF_DEMUX_BLOCK |0x00010000) /* 0x05010000 */ - -#define SPU_CHANNEL_NONE (-2) -#define SPU_CHANNEL_AUTO (-1) - -/******************************* LOG ***********************************/ - -#ifndef __APPLE__ -# include <linux/unistd.h> /* syscall(__NR_gettid) */ -#endif - -static const char module_revision[] = "$Id: xine_input_vdr.c,v 1.138.2.40 2009-11-15 12:35:53 phintuka Exp $"; -static const char log_module_input_vdr[] = "[input_vdr] "; -#define LOG_MODULENAME log_module_input_vdr -#define SysLogLevel iSysLogLevel - -#include "logdefs.h" - -int iSysLogLevel = 1; /* 0:none, 1:errors, 2:info, 3:debug */ -int bLogToSysLog = 0; -int bSymbolsFound = 0; - -void x_syslog(int level, const char *module, 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, "%s%s\n", module, buf); - } else { - syslog(level, "%s%s", module, buf); - } -#else - if(!bLogToSysLog) { - fprintf(stderr,"[%ld] %s%s\n", syscall(__NR_gettid), module, buf); - } else { - syslog(level, "[%ld] %s%s", syscall(__NR_gettid), module, 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); - } -} - -#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 - -#ifndef MIN -# define MIN(a,b) ((a)<(b)?(a):(b)) -#endif -#ifndef MAX -# define MAX(a,b) ((a)>(b)?(a):(b)) -#endif - -#ifdef LOG_GRAPH -static void log_graph(int val, int symb) -{ - static char headr[] = "|<- 0 100% ->|"; - static char meter[sizeof(headr)]; - - if (!symb || symb == 1) { - time_t t; - struct tm *tm; - - time(&t); - tm = localtime(&t); - printf("%02d:%02d:%02d %s", tm->tm_hour, tm->tm_min, tm->tm_sec, symb ? meter : headr); - memset(meter, ' ', sizeof(headr) - 1); - return; - } - - val = MIN(val, (int)sizeof(headr) - 2); - val = MAX(val, 0); -#if 0 - if (symb == ':') { - meter[val] = meter[val] == '%' ? '#' : symb; - } else if (symb == '*') { - meter[val] = meter[val] == '%' ? '1' : - meter[val] == ':' ? '2' : - meter[val] == '#' ? '3' : symb; - } else { - meter[val] = symb; - } -#else - meter[val] = symb; -#endif -} -#endif - - -/************************************************************************/ - -#include "tools/pes.c" -#include "tools/mpeg.c" -#include "tools/h264.c" - -/******************************* 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; - int smooth_scr_tuning; - double scr_tuning_step; - int num_buffers_hd; -} vdr_input_class_t; - -/* input plugin */ -typedef struct vdr_input_plugin_s { - union { - vdr_input_plugin_if_t iface; - struct { - input_plugin_t input_plugin; - 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 */ - uint16_t prev_audio_stream_id; /* ((PES PID) << 8) | (SUBSTREAM ID) */ - int8_t h264; /* -1: unknown, 0: no, 1: yes */ - uint8_t ffmpeg_mpeg2_decoder : 1; - uint8_t coreavc_h264_decoder : 1; - uint8_t read_timeouts; /* number of timeouts in read_block */ - uint8_t write_overflows; - uint8_t no_video : 1; - uint8_t live_mode : 1; - uint8_t still_mode : 1; - uint8_t stream_start : 1; - uint8_t send_pts : 1; - uint8_t loop_play : 1; - uint8_t dvd_menu : 1; - uint8_t hd_stream : 1; /* true if current stream is HD */ - uint8_t sw_volume_control : 1; - uint8_t bih_posted : 1; - uint8_t dvd_subtitles : 1; - - /* SCR */ - pvrscr_t *scr; - int speed_before_pause; - int16_t scr_tuning; - uint8_t fixed_scr : 1; - uint8_t scr_live_sync : 1; - uint8_t is_paused : 1; - uint8_t is_trickspeed : 1; - struct { - /* buffer level data for scr tuning algorithm */ - uint cnt; - uint fill_avg; - uint fill_min; - uint fill_max; - } scr_buf; - uint I_frames; /* amount of I-frames passed to demux */ - uint B_frames; - uint P_frames; - - /* Network */ - pthread_t control_thread; - pthread_t data_thread; - pthread_mutex_t fd_control_lock; - uint8_t threads_initialized; - uint8_t tcp, udp, rtp; - volatile int control_running; - volatile int fd_data; - volatile int fd_control; - 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 *hd_buffer; /* more buffer for HD streams */ - uint64_t discard_index; /* index of next byte to feed to demux; - all data before this offset will - be discarded */ - uint64_t discard_index_ds; - uint discard_frame; - uint64_t guard_index; /* data before this offset will not be discarded */ - uint guard_frame; - uint64_t curpos; /* current position (demux side) */ - uint curframe; - int max_buffers; /* max no. of non-demuxed buffers */ - int64_t last_delivered_vid_pts; /* detect PTS wraps */ - - /* saved video properties */ - uint8_t video_properties_saved; - int orig_hue; - int orig_brightness; - int orig_saturation; - int orig_sharpness; - int orig_noise_reduction; - int orig_contrast; - int orig_vo_aspect_ratio; - - /* OSD */ - pthread_mutex_t osd_lock; - uint16_t vdr_osd_width, vdr_osd_height; - uint16_t video_width, video_height; - 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 */ - - uint16_t current_seq; /* sequence number of last received packet */ - uint8_t is_padding; /* true, if last received packet was padding packet */ - - /* missing frames ratio statistics */ - int16_t missed_frames; - int16_t received_frames; - - /* SCR adjust */ - uint8_t scr_jump_done; - - int resend_requested; -}; - -/* 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 = calloc(1, 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 - -/********************* cancellable mutex locking *************************/ - -/* - * mutex cleanup() - * - * Unlock mutex. Used as thread cleanup handler. - */ -static void mutex_cleanup(void *arg) -{ - pthread_mutex_unlock((pthread_mutex_t *)arg); -} - -/* - * mutex_lock_cancellable() / mutex_unlock_cancellable() - * - * mutex lock/unlock for cancellable sections - * - * - do not enter protected section if locking fails - * - unlock mutex if thread is cancelled while holding the lock - * - * - lock/unlock must be used pairwise within the same lexical scope ! - * - */ -#define mutex_lock_cancellable(mutex) \ - if (pthread_mutex_lock(mutex)) { \ - LOGERR("pthread_mutex_lock (%s) failed, skipping locked block !", #mutex); \ - } else { \ - pthread_cleanup_push(mutex_cleanup, (void*) mutex); - -#define mutex_unlock_cancellable(mutex) \ - if (pthread_mutex_unlock(mutex)) \ - LOGERR("pthread_mutex_unlock (%s) failed !", #mutex); \ - pthread_cleanup_pop(0); \ - } - -/******************************* SCR ************************************* - * - * unix System Clock Reference + fine tuning - * - * pvrscr code is mostly copied from xine, input_pvr.c - * - * fine tuning 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_tuning; - - 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_tuning; - - pthread_mutex_unlock (&this->lock); - - return speed; -} - -static void pvrscr_speed_tuning (pvrscr_t *this, double factor) -{ - pthread_mutex_lock (&this->lock); - - pvrscr_set_pivot( this ); - this->speed_tuning = factor; - this->speed_factor = (double) this->xine_speed * (double)this->scr_speed_base /*90000.0*/ / - (1.0*XINE_FINE_SPEED_NORMAL) * - this->speed_tuning; - - 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_tuning; - - 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 = calloc(1, sizeof(pvrscr_t)); - - 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_tuning(this, 1.0 ); - pvrscr_set_fine_speed (&this->scr, XINE_SPEED_PAUSE); - - LOGSCR("SCR init complete"); - - return this; -} - -/* - * SCR fine tuning - * - * fine tuning is used to change playback speed in live mode - * to keep in sync with mpeg source - * - */ - -#define SCR_TUNING_PAUSED -10000 -#define SCR_TUNING_OFF 0 - -#ifdef LOG_SCR -static inline const char *scr_tuning_str(int value) -{ - switch(value) { - case 2: return "SCR +2"; - case 1: return "SCR +1"; - case SCR_TUNING_OFF: return "SCR +0"; - case -1: return "SCR -1"; - case -2: return "SCR -2"; - case SCR_TUNING_PAUSED: return "SCR PAUSED"; - default: break; - } - return "ERROR"; -} -#endif - -#ifdef LOG_SCR -static void log_buffer_fill(vdr_input_plugin_t *this) -{ - /* - * Trace current buffer and tuning status - */ - static int cnt = 0; - - if ( ! ((cnt++) % 2500) || - (this->scr_tuning == SCR_TUNING_PAUSED && !(cnt%10)) || - (this->no_video && !(cnt%50))) { - LOGSCR("Buffer %2d%% (%3d/%3d) %s", - 100 * num_used / (num_used + num_free), - num_used, num_used + num_free, - scr_tuning_str(this->scr_tuning)); - } - - if (this->scr_tuning == SCR_TUNING_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); - } - } -} -#else -# define log_buffer_fill(this) -#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_tuning_set_paused(vdr_input_plugin_t *this) -{ - if(this->scr_tuning != SCR_TUNING_PAUSED && - !this->slave_stream && - !this->is_trickspeed) { - - this->scr_tuning = SCR_TUNING_PAUSED; /* marked as paused */ - if(this->scr) - pvrscr_speed_tuning(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_tuning(vdr_input_plugin_t *this, int new_speed) -{ - if(this->scr_tuning != SCR_TUNING_OFF) { - this->scr_tuning = SCR_TUNING_OFF; /* marked as normal */ - if(this->scr) - pvrscr_speed_tuning(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_tuning = this->scr_tuning; - /*int num_vbufs = 0;*/ - - if (this->hd_stream) { - 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); - - log_buffer_fill(this); - - /* - * SCR -> PAUSE - * - If buffer is empty, pause SCR (playback) for a while - */ - if( num_used < 1 && - scr_tuning != SCR_TUNING_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_tuning_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_tuning == SCR_TUNING_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 tuning 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_tuning(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_tuning = SCR_TUNING_OFF; - - } else if(this->no_video) { /* radio stream ? */ - if( num_used >= (RADIO_MAX_BUFFERS-1)) - scr_tuning = +1; /* play faster */ - else if( num_used <= (RADIO_MAX_BUFFERS/3)) - scr_tuning = -1; /* play slower */ - else - scr_tuning = SCR_TUNING_OFF; - - } else if(this->class->smooth_scr_tuning) { - /* - * Experimental only. - * Major sync point displacements are handled by xine-lib. - * This provides much faster sync after channel switch, replay start etc. - */ - - int bfill, trim_rel, trim_act; - -#define DIVIDER 8000 -#define WEIGHTING 2 -#define CENTER_POS 0 -#define MAX_TRIM_REL 1 -#define MAX_TRIM_ABS 2 -#define MIN_FILL_PER_CENT 0 -#define MAX_FILL_PER_CENT 100 -#define TARGET_FILL_PER_CENT 50 - -#ifdef LOG_GRAPH - if (!this->scr_buf.cnt) { - log_graph(0, 0); - printf(" R\n"); - } -#endif - trim_act = scr_tuning - CENTER_POS; - bfill = MAX_FILL_PER_CENT * num_used / (num_used + num_free); - this->scr_buf.fill_avg += bfill; - this->scr_buf.fill_min = MIN(this->scr_buf.fill_min, bfill); - this->scr_buf.fill_max = MAX(this->scr_buf.fill_max, bfill); - -#ifdef LOG_GRAPH - log_graph(bfill, '.'); -#endif - ++this->scr_buf.cnt; - if (!(this->scr_buf.cnt % DIVIDER)) { - this->scr_buf.fill_avg /= DIVIDER; - trim_rel = (this->scr_buf.fill_avg - TARGET_FILL_PER_CENT) / WEIGHTING; - trim_rel = MIN(trim_rel, MAX_TRIM_REL); - trim_rel = MAX(trim_rel, -MAX_TRIM_REL); - -#ifdef LOG_GRAPH - log_graph(this->scr_buf.fill_avg, '|'); - log_graph(0, 1); - printf(" %2d%% %2d%% %2d%% [%3d%+4d]\n", - this->scr_buf.fill_min, - this->scr_buf.fill_max, - this->scr_buf.fill_avg, - trim_act, trim_rel); -#endif - - this->scr_buf.fill_avg = 0; - this->scr_buf.fill_min = MAX_FILL_PER_CENT; - this->scr_buf.fill_max = MIN_FILL_PER_CENT; - - if (trim_rel) { - trim_act += trim_rel; - trim_act = MIN(trim_act, MAX_TRIM_ABS); - trim_act = MAX(trim_act, -MAX_TRIM_ABS); - /* reprog clock correction */ - scr_tuning = trim_act + CENTER_POS; - } - } - - } else { - if( num_used > 4*num_free ) - scr_tuning = +2; /* play 1% faster */ - else if( num_used > 2*num_free ) - scr_tuning = +1; /* play .5% faster */ - else if( num_free > 4*num_used ) /* <20% */ - scr_tuning = -2; /* play 1% slower */ - else if( num_free > 2*num_used ) /* <33% */ - scr_tuning = -1; /* play .5% slower */ - else if( (scr_tuning > 0 && num_free > num_used) || - (scr_tuning < 0 && num_used > num_free) ) - scr_tuning = SCR_TUNING_OFF; - } - - if( scr_tuning != this->scr_tuning ) { - LOGSCR("scr_tuning: %s -> %s (buffer %d/%d) (tuning now %f%%)", - scr_tuning_str(this->scr_tuning), - scr_tuning_str(scr_tuning), num_used, num_free, this->class->scr_tuning_step * scr_tuning * 100.0); - this->scr_tuning = scr_tuning; - - /* make it play .5% / 1% faster or slower */ - if(this->scr) - pvrscr_speed_tuning(this->scr, 1.0 + (this->class->scr_tuning_step * scr_tuning) ); - } - - /* - * SCR -> NORMAL - * - If we are in replay (or trick speed) mode, switch SCR tuning off - * as we can always have complete control on incoming data rate - */ - } else if( this->scr_tuning ) { - reset_scr_tuning(this, -1); - } -} - -/******************************* TOOLS ***********************************/ - -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 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; -} - -/**************************** socket I/O *********************************/ - -/* - * io_select_rd() - * - * - poll socket for read - * - timeouts in 500 ms - * - returns XIO_* - */ -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; -} - -/* - * write_control_data() - * - * - write len bytes to control socket. - * - returns number of bytes written, < 0 on error. - * - * NOTE: caller must hold fd_control lock ! - */ -static ssize_t write_control_data(vdr_input_plugin_t *this, const void *str, size_t len) -{ - size_t ret, result = len; - - while (len > 0) { - - if (!this->control_running) { - LOGERR("write_control aborted"); - return -1; - } - - /* poll the socket */ - 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 -1; - } - - if (!this->control_running) { - LOGERR("write_control aborted"); - return -1; - } - - 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 -1; - } - len -= ret; - str += ret; - } - - return result; -} - -/* - * write_control() - * - * - write null-terminated string to control socket. - * - returns number of bytes written, < 0 on error - * - * NOTE: caller should NOT hold fd_control lock ! - */ -static ssize_t write_control(vdr_input_plugin_t *this, const char *str) -{ - ssize_t ret = -1; - mutex_lock_cancellable (&this->fd_control_lock); - ret = write_control_data(this, str, strlen(str)); - mutex_unlock_cancellable (&this->fd_control_lock); - return ret; -} - -/* - * printf_control() - * - * - returns number of bytes written, < 0 on error - * - * NOTE: caller should NOT hold fd_control lock ! - */ -static ssize_t printf_control(vdr_input_plugin_t *this, const char *fmt, ...) -{ - va_list argp; - char buf[512]; - ssize_t result; - - va_start(argp, fmt); - vsnprintf(buf, sizeof(buf), fmt, argp); - buf[sizeof(buf)-1] = 0; - - result = write_control(this, buf); - - va_end(argp); - - return result; -} - -/* - * readline_control() - * - * - read CR/LF terminated string from control socket - * - remove trailing CR/LF - * - returns > 0 : length of string - * = 0 : timeout - * < 0 : error - */ -static ssize_t readline_control(vdr_input_plugin_t *this, char *buf, size_t maxlen, int timeout) -{ - int poll_result; - ssize_t read_result; - size_t total_bytes = 0; - - *buf = 0; - while (total_bytes < maxlen - 1) { - - if (!this->control_running && timeout < 0) - return -1; - - pthread_testcancel(); - poll_result = io_select_rd(this->fd_control); - pthread_testcancel(); - - if (!this->control_running && timeout < 0) - return -1; - - if (poll_result == XIO_TIMEOUT) { - if (timeout == 0) - return 0; - if (timeout > 0) - timeout--; - continue; - } - if (poll_result == XIO_ABORTED) { - LOGERR("readline_control: XIO_ABORTED at [%u]", (uint)total_bytes); - continue; - } - if (poll_result != XIO_READY /* == XIO_ERROR */) { - LOGERR("readline_control: poll error at [%u]", (uint)total_bytes); - return -1; - } - - errno = 0; - read_result = read (this->fd_control, buf + total_bytes, 1); - pthread_testcancel(); - - if (!this->control_running && timeout < 0) - return -1; - - if (read_result <= 0) { - if (read_result == 0) - LOGERR("Control stream disconnected"); - else - LOGERR("readline_control: read error at [%u]", (uint)total_bytes); - if (read_result < 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", len, buf); - } - - TRACE("readline_control: %d bytes (max %d)\n", len, maxlen); - - return total_bytes; -} - -/* - * read_control() - * - * - read len bytes from control socket - * - returns < 0 on error - */ -static ssize_t read_control(vdr_input_plugin_t *this, uint8_t *buf, size_t len) -{ - int poll_result; - ssize_t num_bytes; - size_t total_bytes = 0; - - while (total_bytes < len) { - - if (!this->control_running) - return -1; - - pthread_testcancel(); - poll_result = io_select_rd(this->fd_control); - pthread_testcancel(); - - if (!this->control_running) - return -1; - - if (poll_result == XIO_TIMEOUT) { - continue; - } - if (poll_result == XIO_ABORTED) { - LOGERR("read_control: XIO_ABORTED"); - continue; - } - if (poll_result == 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; -} - -const char * get_decoder_name(xine_t *xine, int video_type) -{ - int streamtype = (video_type >> 16) & 0xFF; - plugin_node_t *node = xine->plugin_catalog->video_decoder_map[streamtype][0]; - if (node) { - plugin_info_t *info = node->info; - if (info) { -#if 0 - decoder_info_t *decinfo = (decoder_info_t*) info->special_info; - if (decinfo) - LOGMSG("get_decoder_name(): Video type %02x0000 is handled by %s (priority %d)", - streamtype, info->id, decinfo->priority); -#endif - return info->id; - } - } - return ""; -} - -static void detect_video_decoders(vdr_input_plugin_t *this) -{ - if (!strcmp(get_decoder_name(this->class->xine, BUF_VIDEO_MPEG), "ffmpegvideo")) - this->ffmpeg_mpeg2_decoder = 1; - LOGMSG("Using decoder \"%s\" for mpeg2 video", - this->ffmpeg_mpeg2_decoder ? "FFmpeg" : "libmpeg2"); - - if (!strcmp(get_decoder_name(this->class->xine, BUF_VIDEO_H264), "dshowserver")) - this->coreavc_h264_decoder = 1; - LOGMSG("Using decoder \"%s\" for H.264 video", - this->coreavc_h264_decoder ? "dshowserver (CoreAVC)" : "FFmpeg"); -} - -/************************** 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); -} - -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; -} - -static buf_element_t *fifo_buffer_timed_get(fifo_buffer_t *fifo, int timeout) -{ - buf_element_t *buf = fifo_buffer_try_get (fifo); - - if (!buf) { - struct timespec abstime; - int result = 0; - create_timeout_time (&abstime, timeout); - - mutex_lock_cancellable (&fifo->mutex); - while (fifo->first == NULL && !result) - result = pthread_cond_timedwait (&fifo->not_empty, &fifo->mutex, &abstime); - mutex_unlock_cancellable (&fifo->mutex); - buf = fifo_buffer_try_get (fifo); - } - - return buf; -} - -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); - } - if (this->hd_buffer) { - pthread_mutex_lock(&this->hd_buffer->buffer_pool_mutex); - pthread_cond_broadcast(&this->hd_buffer->buffer_pool_cond_not_empty); - pthread_mutex_unlock(&this->hd_buffer->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; - unsigned char *multi_buffer; - - LOGDBG("fifo_buffer_new..."); - this = calloc(1, 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 - */ - - multi_buffer = this->buffer_pool_base = av_mallocz (num_buffers * buf_size); - - pthread_mutex_init (&this->buffer_pool_mutex, NULL); - pthread_cond_init (&this->buffer_pool_cond_not_empty, NULL); - - 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 = calloc(1, 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); - } - - LOGDBG("fifo_buffer_new done."); - return this; -} -#endif - -static void flush_all_fifos (vdr_input_plugin_t *this, int full) -{ - LOGDBG("flush_all_fifos(%s)", full ? "full" : ""); - - if (this->udp_data) { - int i; - for (i = 0; i <= UDP_SEQ_MASK; i++) - if (this->udp_data->queue[i]) { - this->udp_data->queue[i]->free_buffer(this->udp_data->queue[i]); - this->udp_data->queue[i] = NULL; - } - } - - if (full) { - 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->block_buffer) - this->block_buffer->clear(this->block_buffer); - if (this->hd_buffer) - this->hd_buffer->clear(this->hd_buffer); -} - -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 && size <= HD_BUF_ELEM_SIZE) { - buf = this->hd_buffer->buffer_pool_try_alloc(this->hd_buffer); - } - - /* 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 */ - 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_NETWORK_BLOCK) { - 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,PADDING_STREAM,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; -} - -static 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); - } -} - -/* - * post_sequence_end() - * - * Add MPEG2 or H.264 sequence end code to fifo buffer - */ -static void post_sequence_end(fifo_buffer_t *fifo, uint32_t video_type) -{ - buf_element_t *buf = fifo->buffer_pool_try_alloc(fifo); - if (buf) { - buf->type = video_type; - buf->size = 4; - buf->decoder_flags = BUF_FLAG_FRAME_END; - buf->content[0] = 0x00; - buf->content[1] = 0x00; - buf->content[2] = 0x01; - buf->content[3] = (video_type == BUF_VIDEO_H264) ? NAL_END_SEQ : 0xB7; - fifo->put(fifo, 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 ...*/ - vo_frame_t *img = NULL; - int width = this->video_width; - int height = this->video_height; - - 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 <= 1200) { - 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); - } else { - LOGMSG("queue_blank_yv12: invalid dimensions %dx%d in stream_info !", width, height); - } - - 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); -} - -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; - fifo_buffer_t *fifo = this->stream->video_fifo; - char *path, *home; - - if (fifo->num_free(fifo) < 10) { - LOGMSG("queue_nosignal: not enough free buffers (%d) !", - fifo->num_free(fifo)); - return; - } - - if (asprintf(&home,"%s/.xine/nosignal.mpg", xine_get_homedir()) < 0) - return; - 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 = fifo->buffer_pool_try_alloc(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; - if(pos >= datalen) - buf->decoder_flags |= BUF_FLAG_FRAME_END; - fifo->put(fifo, buf); - } else { - LOGMSG("Error: queue_nosignal: no buffers !"); - break; - } - } - - /* sequence end */ - post_sequence_end(fifo, BUF_VIDEO_MPEG); - - put_control_buf(fifo, fifo, BUF_CONTROL_FLUSH_DECODER); - put_control_buf(fifo, fifo, BUF_CONTROL_NOP); - - free(tmp); -} - - -/*************************** 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 MRL_ID "+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 !"); - errno = EAGAIN; - 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 = calloc(1, 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 ************************************/ - -#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; - xine_stream_t *stream = this->slave_stream ?: this->stream; - 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 || !stream) { - LOGMSG("exec_osd_command: Stream not initialized !"); - return CONTROL_DISCONNECTED; - } - - if(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 = - stream->video_out->get_overlay_manager(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(stream); - if(cmd->pts) { - ov_event.vpts = cmd->pts + - stream->metronom->get_option(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(stream); - - } else if(cmd->cmd == OSD_Flush) { - /* TODO */ - } 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; - - stream->video_out->enable_ovl(stream->video_out, 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(!(stream->video_out->get_capabilities(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; - - 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); - - 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 = stream->video_out->get_property(stream->video_out, - VO_PROP_WINDOW_WIDTH); - int win_height = stream->video_out->get_property(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(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) && - 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; - - /* 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"); - } -} - -/* - * vdr_plugin_exec_osd_command() - * - * - entry point for VDR-based osd_command_t events - */ -static int vdr_plugin_exec_osd_command(vdr_input_plugin_if_t *this_if, - osd_command_t *cmd) -{ - vdr_input_plugin_t *this = (vdr_input_plugin_t *) this_if; - int result = CONTROL_DISCONNECTED; - - 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; - } - - mutex_lock_cancellable (&this->osd_lock); - - if (!(cmd->flags & OSDFLAG_YUV_CLUT)) - palette_rgb_to_yuy(cmd->palette, cmd->colors); - cmd->flags &= ~OSDFLAG_YUV_CLUT; - - 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); - - mutex_unlock_cancellable (&this->osd_lock); - - 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 ); -} - -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) -{ - 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 %"PRIu64", flush skipped", - discard_index, this->curpos); - return; - } - - /* reset speed */ - if(xine_get_param(this->stream, XINE_PARAM_FINE_SPEED) <= 0) { - LOGMSG("vdr_flush_engine: playback is paused <0>"); - xine_set_param(this->stream, XINE_PARAM_FINE_SPEED, XINE_FINE_SPEED_NORMAL); - } - - /* suspend demuxer */ - this->stream->demux_action_pending = 1; - pthread_cond_broadcast(&this->engine_flushed); - 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_tuning(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) { - LOGMSG("vdr_flush_engine: playback is paused <1>"); - 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; - - 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 sharpness, - int noise_reduction, 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 || - sharpness>=0 || noise_reduction>=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 ); -#ifdef XINE_PARAM_VO_SHARPNESS - this->orig_sharpness = xine_get_param(this->stream, - XINE_PARAM_VO_SHARPNESS ); -#endif -#ifdef XINE_PARAM_VO_NOISE_REDUCTION - this->orig_noise_reduction = xine_get_param(this->stream, - XINE_PARAM_VO_NOISE_REDUCTION ); -#endif - 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 ); -#ifdef XINE_PARAM_VO_SHARPNESS - if(sharpness>=0 || this->video_properties_saved) - xine_set_param(this->stream, XINE_PARAM_VO_SHARPNESS, - sharpness>=0 ? sharpness : this->orig_sharpness ); -#endif -#ifdef XINE_PARAM_VO_NOISE_REDUCTION - if(noise_reduction>=0 || this->video_properties_saved) - xine_set_param(this->stream, XINE_PARAM_VO_NOISE_REDUCTION, - noise_reduction>=0 ? noise_reduction : this->orig_noise_reduction ); -#endif - 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 && sharpness<0 && noise_reduction<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 tuning */ - if(this->live_mode) { -#ifndef TEST_SCR_PAUSE - LOGSCR("pause scr tuning by set_live_mode"); - scr_tuning_set_paused(this); -#endif - } else { - LOGSCR("reset scr tuning by set_live_mode"); - reset_scr_tuning(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_tuning(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_tuning != SCR_TUNING_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); - - if (asprintf(&meta, - "INFO METAINFO title=@%s@ artist=@%s@ album=@%s@ tracknumber=@%s@\r\n", - title?:"", artist?:"", album?:"", tracknumber?:"") < 0) - return; - - if(this->fd_control < 0) - this->funcs.xine_input_event(meta, NULL); - else - write_control(this, meta); - - free(meta); - } -} - -#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; - - /* 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; - } - - memset(&sghdr, 0, sizeof(sghdr)); - memset(buffer, 0, sizeof(buffer)); - memset(sense, 0, sizeof(sense)); - memset(cmd, 0, sizeof(cmd)); - - 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 void dvd_menu_domain(vdr_input_plugin_t *this, int value) -{ - if (value) { - LOGDBG("dvd_menu_domain(1)"); - this->dvd_menu = 1; - this->slave_stream->spu_channel_user = SPU_CHANNEL_AUTO; - this->slave_stream->spu_channel = this->slave_stream->spu_channel_auto; - } else { - LOGDBG("dvd_menu_domain(0)"); - this->dvd_menu = 0; - } -} - -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); - this->dvd_menu = 0; - - 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_tuning(this, this->speed_before_pause = XINE_FINE_SPEED_NORMAL); - this->slave_stream->metronom->set_option(this->slave_stream->metronom, - METRONOM_PREBUFFER, 90000); -#endif - - 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); - 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) { - 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"); - - _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; - 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 %lu\r\n", this->token, (unsigned long)data->size); - mutex_lock_cancellable (&this->fd_control_lock); - write_control_data(this, s, strlen(s)); - write_control_data(this, data->data, data->size); - mutex_unlock_cancellable (&this->fd_control_lock); - } 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); - } - - 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 = {0}; - int err = CONTROL_OK; - - if (!this->control_running) - return CONTROL_DISCONNECTED; - - /* read struct size first */ - size_t todo, expect = sizeof(osd_command_t); - uint8_t *pt = (uint8_t*)&osdcmd; - if (read_control(this, pt, sizeof(osdcmd.size)) != sizeof(osdcmd.size)) { - LOGMSG("control: error reading OSDCMD data length"); - return CONTROL_DISCONNECTED; - } - pt += sizeof(osdcmd.size); - expect -= sizeof(osdcmd.size); - todo = osdcmd.size - sizeof(osdcmd.size); - - /* read data */ - size_t bytes = MIN(todo, expect); - if (read_control(this, pt, bytes) != bytes) { - LOGMSG("control: error reading OSDCMD data"); - return CONTROL_DISCONNECTED; - } - - if (expect < todo) { - /* server uses larger struct, discard rest of data */ - uint8_t dummy[todo-expect]; - LOGMSG("osd_command_t size %d, expected %d", (int)osdcmd.size, (int)expect); - if (read_control(this, dummy, todo-expect) != todo-expect) { - LOGMSG("control: error reading OSDCMD data (unknown part)"); - return CONTROL_DISCONNECTED; - } - } - - ntoh_osdcmd(osdcmd); - - /* read palette */ - 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; - } - - /* read (RLE) data */ - 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(&this->iface, &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"}, -}; - -/* - * vdr_plugin_poll() - * - * Query buffer state - * Returns amount of free PES buffer blocks in queue. - */ -static int vdr_plugin_poll(vdr_input_plugin_t *this, int timeout_ms) -{ - struct timespec abstime; - fifo_buffer_t *fifo = this->buffer_pool; - int reserved_bufs = (fifo->buffer_pool_capacity - this->max_buffers); - 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), fifo: blocks=%d, bytes=%d", - timeout_ms, fifo->size(fifo), fifo->data_size(fifo)); - - pthread_mutex_lock (&fifo->buffer_pool_mutex); - result = fifo->buffer_pool_num_free - reserved_bufs; - pthread_mutex_unlock (&fifo->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_tuning == SCR_TUNING_PAUSED) { - LOGSCR("scr tuning reset by POLL"); - reset_scr_tuning(this,this->speed_before_pause); - } - pthread_mutex_unlock(&this->lock); - - signal_buffer_not_empty(this); - - VDR_ENTRY_UNLOCK(); - - pthread_mutex_lock (&fifo->buffer_pool_mutex); - while (result <= 5) { - if (pthread_cond_timedwait (&fifo->buffer_pool_cond_not_empty, - &fifo->buffer_pool_mutex, - &abstime) == ETIMEDOUT) - break; - result = fifo->buffer_pool_num_free - reserved_bufs; - } - pthread_mutex_unlock (&fifo->buffer_pool_mutex); - VDR_ENTRY_LOCK(0); - } - - TRACE("vdr_plugin_poll returns, %d free (%d used, %d bytes)\n", - result, fifo->size(fifo), fifo->data_size(fifo)); - - /* 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; -} - -/* - * vdr_plugin_flush() - * - * Flush all data from buffers to output devices. - * Returns 0 when 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); - - post_sequence_end(buffer, this->h264>0 ? BUF_VIDEO_H264 : BUF_VIDEO_MPEG); - put_control_buf(buffer, pool, BUF_CONTROL_FLUSH_DECODER); - put_control_buf(buffer, pool, BUF_CONTROL_NOP); - - if (result <= 0) - return 0; - - 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; -} - -/* - * vdr_plugin_flush_remote() - * - * vdr_plugin_flush() Wrapper for remote mode - * - wait for data in network buffers - */ -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 tuning by flush_remote"); - reset_scr_tuning(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 tuning by flush_remote"); - reset_scr_tuning(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(vdr_input_plugin_if_t *this_if, const char *cmd) -{ - vdr_input_plugin_t *this = (vdr_input_plugin_t *) this_if; - 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( !memcmp(cmd, str_poll, 4) || - !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 */ - - LOGVERBOSE("<control> %s",cmd); - - if(!strncasecmp(cmd, "OSDCMD", 6)) { - err = handle_control_osdcmd(this); - - } else if(!strncasecmp(cmd, "VIDEO_PROPERTIES ", 17)) { - int hue, saturation, brightness, sharpness, noise_reduction, contrast, vo_aspect_ratio; - if(7 == sscanf(cmd+17, "%d %d %d %d %d %d %d", - &hue, &saturation, &brightness, &sharpness, &noise_reduction, &contrast, &vo_aspect_ratio)) - err = set_video_properties(this, hue, saturation, brightness, sharpness, noise_reduction, 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+10, "%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 = { - .type = eventmap[i].type, - .stream = this->slave_stream ?: this->stream, - /* tag event to prevent circular input events - (vdr -> here -> event_listener -> vdr -> ...) */ - .data = "VDR", - .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+7, "%d", &tmp32)) { - pthread_mutex_lock(&this->lock); - if (tmp32 && !this->hd_stream) { - cfg_entry_t *e = this->class->xine->config->lookup_entry(this->class->xine->config, - "engine.buffers.video_num_frames"); - if (e && e->num_value < 32) { - LOGMSG("WARNING: xine-engine setting \"engine.buffers.video_num_frames\":%d is " - "too small for some HD channels", e->num_value); - } - - } - if(tmp32) { - if(!this->hd_buffer) - this->hd_buffer = fifo_buffer_new(this->stream, this->class->num_buffers_hd, HD_BUF_ELEM_SIZE); - this->hd_stream = 1; - } else { - this->hd_stream = 0; - } - pthread_mutex_unlock(&this->lock); - } - - } else if(!strncasecmp(cmd, "NOVIDEO ", 8)) { - if(1 == sscanf(cmd+8, "%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+8, "%" 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+10, "%" 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+11, "%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+6, "%d", &tmp32)) { - this->still_mode = tmp32; - if(this->still_mode) - reset_scr_tuning(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_tuning(this, -1); - } - pthread_mutex_unlock(&this->lock); - - } else if(!strncasecmp(cmd, "LIVE ", 5)) { - err = (1 == sscanf(cmd+5, "%d", &tmp32)) ? set_live_mode(this, tmp32) - : CONTROL_PARAM_ERROR; - - } else if(!strncasecmp(cmd, "MASTER ", 7)) { - if(1 == sscanf(cmd+7, "%d", &tmp32)) - this->fixed_scr = tmp32 ? 1 : 0; - else - err = CONTROL_PARAM_ERROR; - - } else if(!strncasecmp(cmd, "VOLUME ", 7)) { - if(1 == sscanf(cmd+7, "%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+17, "%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+14, "%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+9, "%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+10,"%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) { - } else { - if(1 == sscanf(cmd+12, "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; - int ch_auto = strstr(cmd+10, "auto") ? 1 : 0; - int is_dvd = 0; - - if (this->slave_stream && this->slave_stream->input_plugin) { - const char *mrl = this->slave_stream->input_plugin->get_mrl(this->slave_stream->input_plugin); - is_dvd = !strncmp(mrl, "dvd:/", 5); - } - - if(strstr(cmd+10, "NEXT")) - ch = ch < max_ch ? ch+1 : -2; - else if(strstr(cmd+10, "PREV")) - ch = ch > -2 ? ch-1 : max_ch-1; - else if(1 == sscanf(cmd+10, "%d", &tmp32)) { - ch = tmp32; - } else if(cmd[10] && cmd[11] && (cmd[12] < 'a' || cmd[12] > 'z')) { - /* ISO 639-1 language code */ - const char spu_lang[3] = {cmd[10], cmd[11], 0}; - LOGMSG("Preferred SPU language: %s", spu_lang); - this->class->xine->config->update_string(this->class->xine->config, - "media.dvd.language", spu_lang); - ch = old_ch = 0; - } else - err = CONTROL_PARAM_ERROR; - - if (old_ch == SPU_CHANNEL_AUTO) - old_ch = stream->spu_channel_auto; - - if (ch != old_ch) { - if (is_dvd && ch_auto && stream->spu_channel_user == SPU_CHANNEL_AUTO) { - LOGDBG("Automatic SPU channel %d->%d ignored", old_ch, ch); - } else { - LOGDBG("Forced SPU channel %d->%d", old_ch, 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+11, "%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+6, "%d", &tmp32)) { - if(this->fd_control >= 0) { - uint32_t frame = 0; - tmp64 = 0ULL; - tmp32 = 0; - sscanf(cmd+6, "%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)) { - if(1 == sscanf(cmd+6, "%d", &tmp32)) - this->token = tmp32; - else - err = CONTROL_PARAM_ERROR; - - } 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 (cmd[15]==' ' && cmd[16]) { - /* query from specific input plugin */ - const char *cls_name = cmd + 16; - this->autoplay_size = 0; - if (! xine_get_browse_mrls (stream->xine, - cls_name, - NULL, &this->autoplay_size)) - /* try older method */ - xine_get_autoplay_mrls(stream->xine, cls_name, &this->autoplay_size); - } - - 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+10, "%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+11, "%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("vdr_plugin_parse_control(): 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->iface, 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; - size_t cnt; - - /* DVD title and menu domain detection */ -#ifdef XINE_STREAM_INFO_DVD_TITLE_NUMBER - i = _x_stream_info_get(this->slave_stream, XINE_STREAM_INFO_DVD_TITLE_NUMBER); - if(i >= 0) { - if (i == 0) - dvd_menu_domain(this, 1); - 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("%s", tracks); - } -#endif - - /* 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++; - if(current == SPU_CHANNEL_AUTO) - current = this->slave_stream->spu_channel_auto; - } - 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); - } -} - -/* 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->fd_control >= 0) { - /* remote mode: -> input_plugin -> connection -> VDR */ - printf_control(this, "KEY %s\r\n", vdr_keymap[i].name); - } - 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); - if (tt == 0) - dvd_menu_domain(this, 1); -#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_NUM_BUTTONS: - if (event->stream == this->slave_stream) { - xine_ui_data_t *data = (xine_ui_data_t*)event->data; - char msg[64]; - dvd_menu_domain(this, data->num_buttons > 0); - snprintf(msg, sizeof(msg), "INFO DVDBUTTONS %d\r\n", data->num_buttons); - 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) { - LOGDBG("XINE_EVENT_UI_PLAYBACK_FINISHED"); - this->control_running = 0; -#if 1 - if(iSysLogLevel >= SYSLOGLEVEL_DEBUG) { - /* 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 = { - .type = XINE_EVENT_UI_PLAYBACK_FINISHED, - .data_length = 0, - }; - 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'; - - LOGVERBOSE("<control> <data> %s", cmd); - - if(!strncasecmp(cmd, "DISCARD ", 8)) { - uint64_t index; - if(1 == sscanf(cmd+8, "%" PRIu64, &index)) { - int counter = 100; - //this->block_buffer->clear(this->block_buffer); - - pthread_mutex_lock(&this->lock); - - if (this->discard_index < index) - LOGDBG("data_stream_parse_control: waiting for engine_flushed condition %"PRIu64"<%"PRIu64, - this->discard_index, index); - - while(this->control_running && - this->discard_index < index && - --counter > 0) { - struct timespec abstime; - create_timeout_time(&abstime, 10); - pthread_cond_timedwait(&this->engine_flushed, &this->lock, &abstime); - } - pthread_mutex_unlock(&this->lock); - - if (this->discard_index >= index) { - LOGVERBOSE("wait_stream_sync: streams synced at %"PRIu64"/%"PRIu64, - this->discard_index, index); - return; - } - LOGMSG("wait_stream_sync: Timed out ! diff %"PRId64, - (int64_t)(this->discard_index - index)); - } - return; - } - - vdr_plugin_parse_control(&this->iface, 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, 2048+sizeof(stream_tcp_header_t), 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, 2048+sizeof(stream_tcp_header_t), 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_NETWORK_BLOCK; - 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, 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, 2048+sizeof(stream_rtp_header_impl_t), 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, tuning=%d) time %ds", - this->live_mode, this->scr_tuning, - (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, 2048+sizeof(stream_rtp_header_impl_t), 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_NETWORK_BLOCK; - - 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_PES || - rtp_pkt->rtp_hdr.raw[1] == RTP_PAYLOAD_TYPE_TS ) && - 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)+12, "%d-%d %" PRIu64, - &seq1, &seq2, &rpos); - read_buffer->size = sizeof(stream_udp_header_t); - read_buffer->type = BUF_NETWORK_BLOCK; - 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 - */ - - udp->current_seq = pkt->seq & UDP_SEQ_MASK; - udp->is_padding = DATA_IS_PES(pkt_data) && IS_PADDING_PACKET(pkt_data); - - /* first received frame initializes sequence counter */ - if (udp->received_frames == -1) { - udp->next_seq = udp->current_seq; - udp->received_frames = 0; - } - - /* check if received sequence number is inside allowed window - (half of whole range) */ - - if (ADDSEQ(udp->current_seq, -udp->next_seq) > ((UDP_SEQ_MASK+1) >> 1)/*0x80*/) { - struct sockaddr_in sin; - LOGUDP("Received SeqNo out of window (%d ; [%d..%d])", - udp->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[udp->current_seq]) { - /* Duplicate packet or lot of dropped packets */ - LOGUDP("Got duplicate or window exceeded ? (queue slot %d in use) !", - udp->current_seq); - udp->queue[udp->current_seq]->free_buffer(udp->queue[udp->current_seq]); - udp->queue[udp->current_seq] = NULL; - if (!udp->queued) - LOGERR("UDP queue corrupt !!!"); - else - udp->queued--; - } - - udp->queue[udp->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(udp->current_seq) != udp->next_seq && udp->queued) { - - if(!udp->resend_requested) { - int max_req = 20; - - while(!udp->queue[udp->current_seq] && --max_req > 0) - INCSEQ(udp->current_seq); - - printf_control(this, "UDP RESEND %d-%d %" PRIu64 "\r\n", - udp->next_seq, PREVSEQ(udp->current_seq), - udp->queue_input_pos); - udp->resend_requested = - (udp->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(udp->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"); - - if (nice(-1) < 0) ; - - 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((vdr_input_plugin_if_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(vdr_input_plugin_if_t *this_if, const char *data, int len) -{ - vdr_input_plugin_t *this = (vdr_input_plugin_t *) this_if; - buf_element_t *buf = NULL; - - if(this->slave_stream) - return len; - -#ifdef TEST_PIP - /* some (older?) VDR recordings have video PID != 0xE0 ... */ - - /* slave (PES) */ - if(!buf[0] && ((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 (this->write_overflows++ > 1) - LOGMSG("vdr_plugin_write: buffer overflow ! (%d bytes)", len); - VDR_ENTRY_UNLOCK(); - xine_usec_sleep(5*1000); - errno = EAGAIN; - return 0; /* EAGAIN */ - } - this->write_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; -} - -/* - * post_vdr_event() - * - * - Called by frontend - * - forward (input) events to VDR - * - * It is safe to cancel thread while this function is being executed. - */ -static int post_vdr_event(vdr_input_plugin_if_t *this_if, const char *msg) -{ - vdr_input_plugin_t *this = (vdr_input_plugin_t *) this_if; - - if (msg && this->fd_control >= 0) - return write_control (this, msg); - - LOGMSG("post_vdr_event: error ! \"%s\" not delivered.", msg ?: "<null>"); - return -1; -} - - -/******************************* 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] == PRIVATE_STREAM1) { - /* 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 != ((PRIVATE_STREAM1<<8) | SubStreamId)) { - LOGDBG("Audio changed -> AC3 %d (BD:%02X)", SubStreamIndex, SubStreamId); - this->prev_audio_stream_id = ((PRIVATE_STREAM1<<8) | SubStreamId); - audio_changed = 1; - } - break; - case 0xA0: /* LPCM */ - if(this->prev_audio_stream_id != ((PRIVATE_STREAM1<<8) | SubStreamId)) { - LOGDBG("Audio changed -> LPCM %d (BD:%02X)", SubStreamIndex, SubStreamId); - this->prev_audio_stream_id = ((PRIVATE_STREAM1<<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; -} - -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 = pes_get_pts(buf->content, buf->size); - if(pts >= 0) { - if (IS_VIDEO_PACKET(buf->content)) - this->last_delivered_vid_pts = pts; - else { - 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 -} - -/* - * post_frame_end() - * - * Signal end of video frame to decoder. - * - * This function is used with: - * - FFmpeg mpeg2 decoder - * - FFmpeg and CoreAVC H.264 decoders - * - NOT with libmpeg2 mpeg decoder - */ -static void post_frame_end(vdr_input_plugin_t *this, buf_element_t *vid_buf) -{ - buf_element_t *cbuf = get_buf_element (this, sizeof(xine_bmiheader), 1); - - if (!cbuf) { - LOGMSG("post_frame_end(): get_buf_element() failed, retrying"); - xine_usec_sleep (10*1000); - - if (!(cbuf = get_buf_element (this, sizeof(xine_bmiheader), 1))) { - LOGERR("post_frame_end(): get_buf_element() failed !"); - return; - } - } - - cbuf->type = this->h264 > 0 ? BUF_VIDEO_H264 : BUF_VIDEO_MPEG; - cbuf->decoder_flags = BUF_FLAG_FRAME_END; - - if(!this->bih_posted) { - video_size_t size = {0}; - if (pes_get_video_size(vid_buf->content, vid_buf->size, &size, this->h264 > 0)) { - xine_bmiheader *bmi = (xine_bmiheader*) cbuf->content; - memset(bmi, 0, sizeof(xine_bmiheader)); - - cbuf->decoder_flags |= BUF_FLAG_HEADER; - bmi->biSize = sizeof(xine_bmiheader); - bmi->biWidth = size.width; - bmi->biHeight = size.height; - - if (!this->h264 && size.pixel_aspect.num) { - cbuf->decoder_flags |= BUF_FLAG_ASPECT; - /* pixel ratio -> frame ratio */ - if(size.pixel_aspect.num > size.height) { - cbuf->decoder_info[1] = size.pixel_aspect.num / size.height; - cbuf->decoder_info[2] = size.pixel_aspect.den / size.width; - } else { - cbuf->decoder_info[1] = size.pixel_aspect.num * size.width; - cbuf->decoder_info[2] = size.pixel_aspect.den * size.height; - } - } - - LOGDBG("post_frame_end: video width %d, height %d, pixel aspect %d:%d", - size.width, size.height, size.pixel_aspect.num, size.pixel_aspect.den); - - this->bih_posted = 1; - } - } - - this->stream->video_fifo->put (this->stream->video_fifo, cbuf); -} - -/* - * update_frames() - * - * Update frame type counters. - * Collected information is used to start replay when enough data has been buffered - */ -static uint8_t update_frames(vdr_input_plugin_t *this, const uint8_t *data, int len) -{ - uint8_t type = pes_get_picture_type(data, len); - - if (!this->I_frames) - this->P_frames = this->B_frames = 0; - - switch (type) { - case I_FRAME: this->I_frames++; LOGSCR("I"); break; - case P_FRAME: this->P_frames++; LOGSCR("P"); break; - case B_FRAME: this->B_frames++; LOGSCR("B"); break; - default: break; - } - return type; -} - -/* - * detect_h264() - * - * Detect video codec (MPEG2 or H.264) - */ -#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] == NAL_AUD) { - 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]); - } - - return this->h264; -} -#endif /* TEST_H264 */ - -#ifdef TEST_H264 -/* - * post_frame_h264() - * - * H.264 video stream demuxing - * - mpeg_block demuxer does not regonize H.264 video - */ -buf_element_t *post_frame_h264(vdr_input_plugin_t *this, buf_element_t *buf) -{ - int64_t pts = pes_get_pts (buf->content, buf->size); - uint8_t *data = buf->content; - int i = 9 + data[8]; - - /* skip PES header */ - data += i; - - /* Detect video frame boundaries */ - - /* Access Unit Delimiter */ - if (IS_NAL_AUD(data)) { - - if (this->I_frames < 4) - update_frames (this, buf->content, buf->size); - - post_frame_end (this, buf); - } - - /* Handle PTS and DTS */ - - buf->decoder_info[0] = 0; - if (pts >= INT64_C(0)) { -#if 0 - if (! PES_HAS_DTS(buf->content)) { - buf->decoder_info[0] = pts; - } else { - int64_t dts = pes_get_dts (buf->content, buf->size); - 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); - } -#if 0 - /* 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 (PES_HAS_DTS(buf->content)) { - LOGDBG("H.264: -> pts %"PRId64" <- 0 (DTS)", pts); - /*buf->pts = 0;*/ - } else { - LOGDBG("H.264: -> pts %"PRId64, pts); - buf->pts = pts; - } -#else - buf->pts = pts; -#endif - this->last_delivered_vid_pts = pts; - } - - if (PES_HAS_DTS(buf->content)) { - int64_t dts = pes_get_dts (buf->content, buf->size); - buf->decoder_info[0] = pts - dts; - } - - /* bypass demuxer ... */ - - buf->type = BUF_VIDEO_H264; - buf->content += i; - buf->size -= i; - - /* Check for end of still image. - VDR ensures that H.264 still images end with an end of sequence NAL unit */ - if (buf->size > 4) { - uint8_t *end = buf->content + buf->size; - if (IS_NAL_END_SEQ(end-4)) { - LOGMSG("post_frame_h264: Still frame ? (frame ends with end of sequence NAL unit)"); - buf->decoder_flags |= BUF_FLAG_FRAME_END; - } - } - - this->stream->video_fifo->put (this->stream->video_fifo, buf); - - return NULL; -} -#endif /* TEST_H264 */ - -#if defined(TEST_DVB_SPU) || defined(TEST_DVD_SPU) -/* - * post_spu() - * - * Subtitle stream demuxing - * - mpeg_block demuxer does not regonize DVB subtitles - */ -static buf_element_t *post_spu(vdr_input_plugin_t *this, buf_element_t *buf) -{ - uint8_t *p = buf->content; - uint packet_len = buf->size; - uint header_len = p[8]; - uint substream_header_len = 4; - int64_t pts = pes_get_pts(buf->content, buf->size); - -# ifdef VDR_SUBTITLES - /* Compatibility mode for old subtitles plugin: */ - if ((p[7] & 0x01) && (p[header_len + 6] & 0x81) == 0x01 && p[header_len + 7] == 0x81) { - header_len--; - substream_header_len = 1; - } -# endif - - /* Skip PES header */ - p += header_len + 9; - packet_len -= header_len + 9; - - /* Process only PS1 SPU frames */ - if ((p[0] & 0xE0) == 0x20) { - uint spu_id = (p[0] & 0x1f); -# if 0 - uint payload_len = (buf->content[4] << 8) | buf->content[5]; - LOGMSG("DV? SPU: %d (%5d bytes : %d %s) -- %02x %02x %02x %02x %02x %02x %02x %02x", - spu_id, packet_len, payload_len, pts>=0?"pts":" ", - (unsigned)p[0], (unsigned)p[1], (unsigned)p[2], (unsigned)p[3], - (unsigned)p[4], (unsigned)p[5], (unsigned)p[6], (unsigned)p[7]); -# endif - -# if 1 - _x_select_spu_channel(this->stream, spu_id); -# else - /* only one SPU channel */ - spu_id = 0; -# endif - -# ifdef TEST_DVD_SPU - if (pts >= 0) - this->dvd_subtitles = 0; - - if (this->dvd_subtitles || - ( pts >= 0 && substream_header_len != 1 && - (p[2] || (p[3] & 0xfe)))) { - // || if (p[4] == 20 && p[5] == 00 && p[6] == 0f || p[4] == 0f) --> DVB - LOGMSG("post_spu: Detected DVD SPU"); - this->dvd_subtitles = 1; - spu_id = (p[0] & 0x1f); - - buf->content = p+1; - buf->size = packet_len-1; - - buf->type = BUF_SPU_DVD + spu_id; - buf->decoder_flags |= BUF_FLAG_SPECIAL; - buf->decoder_info[1] = BUF_SPECIAL_SPU_DVD_SUBTYPE; - buf->decoder_info[2] = SPU_DVD_SUBTYPE_PACKAGE; - buf->pts = pts; - - this->stream->video_fifo->put (this->stream->video_fifo, buf); - return NULL; - } -# endif - -# ifdef TEST_DVB_SPU - /* Skip substream header */ - p += substream_header_len; - buf->content = p; - buf->size = packet_len - substream_header_len; - - /* Special buffer when payload packet changes */ - if (pts >= 0) { - buf_element_t *cbuf = get_buf_element(this, 0, 1); - int data_id = *(p+0); - int substream_id = *(p+1); - int segment_type = *(p+3); - int page_id = (*(p+4) << 8) | *(p+5); - int segment_length = (*(p+6) << 8) | *(p+7); - - spu_dvb_descriptor_t *spu_descriptor = (spu_dvb_descriptor_t *) cbuf->content; - memset(spu_descriptor, 0, sizeof(spu_dvb_descriptor_t)); - spu_descriptor->comp_page_id = page_id; - - LOGDBG("DVB SPU: data_id %02x, substream_id %02x, segment_type %02x, page_id %04x, segment_len %d", - data_id, substream_id, segment_type, page_id, segment_length); - - cbuf->type = BUF_SPU_DVB + spu_id; - cbuf->size = 0; - cbuf->decoder_flags = BUF_FLAG_SPECIAL; - cbuf->decoder_info[1] = BUF_SPECIAL_SPU_DVB_DESCRIPTOR; - cbuf->decoder_info[2] = sizeof(spu_dvb_descriptor_t); - cbuf->decoder_info_ptr[2] = spu_descriptor; - - this->stream->video_fifo->put (this->stream->video_fifo, cbuf); - } - - buf->type = BUF_SPU_DVB + spu_id; - buf->pts = pts; - buf->decoder_info[2] = pts >= 0 ? 0xffff : 0; /* hack - size unknown here (?) */ - - this->stream->video_fifo->put (this->stream->video_fifo, buf); - - return NULL; - } -#endif - - LOGDBG("post_spu: PES packet left unprocessed !"); - return buf; -} -#endif - -/* - * Preprocess buffer before passing it to demux - * - handle discard - * - handle display blanking - * - handle stream start - * - strip network headers - */ -static buf_element_t *preprocess_buf(vdr_input_plugin_t *this, buf_element_t *buf) -{ - /* internal control bufs */ - if(buf->type == CONTROL_BUF_BLANK) { - - 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); - - buf->free_buffer(buf); - return NULL; - } - - /* demuxed video, control messages, ... go directly to demuxer */ - if (buf->type != BUF_NETWORK_BLOCK && - buf->type != BUF_DEMUX_BLOCK) - 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); - return NULL; - } - - /* ignore UDP/RTP "idle" padding */ - if (!DATA_IS_TS(buf->content) && IS_PADDING_PACKET(buf->content)) { - pthread_mutex_unlock(&this->lock); - return buf; - } - - /* First packet ? */ - if (this->stream_start) { - this->last_delivered_vid_pts = INT64_C(-1); - this->send_pts = 1; - this->stream_start = 0; - this->bih_posted = 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); - return buf; -} - -/* - * Demux some buffers not supported by mpeg_block demuxer: - * - H.264 video - * - DVB Subtitles - */ -static buf_element_t *demux_buf(vdr_input_plugin_t *this, buf_element_t *buf) -{ -#ifdef TEST_H264 - /* H.264 */ - if (IS_VIDEO_PACKET(buf->content)) { - if (this->h264) { - if (this->h264 < 0) - this->h264 = detect_h264(this, buf->content, buf->size); - - if (this->h264 > 0) - buf = post_frame_h264(this, buf); - } - return buf; - } -#endif - -#if defined(TEST_DVB_SPU) || defined(TEST_DVD_SPU) - /* DVB/DVD subtitles */ - if (buf->content[3] == PRIVATE_STREAM1) { - uint8_t *data = buf->content; - int payload_offset = data[8] + 9; -# ifdef VDR_SUBTITLES - /* Compatibility mode for old subtitles plugin: */ - if ((data[7] & 0x01) && (data[payload_offset - 3] & 0x81) == 0x01 && data[payload_offset - 2] == 0x81) { - payload_offset--; - LOGDBG("DVB SPU: Old vdr-subtitles compability mode"); - } -# endif - uint8_t substream_id = data[payload_offset]; - uint8_t substream_type = substream_id & 0xF0; - switch (substream_type) { - case 0x20: /* SPU */ - case 0x30: /* SPU */ - buf = post_spu(this, buf); - break; - default: break; - } - return buf; - } -#endif - - return buf; -} - -/* - * Postprocess buffer before passing it to demuxer - * - Track audio stream changes - * - Detect pts wraps - * - Signal new pts upstream after stream changes - * - Special handling for still images - * - Count video frames for SCR tuning - * - Special handling for ffmpeg mpeg2 video decoder - */ -static void postprocess_buf(vdr_input_plugin_t *this, buf_element_t *buf, int need_pause) -{ - track_audio_stream_change(this, buf); - - pts_wrap_workaround(this, buf); - - /* Send current PTS ? */ - if(this->send_pts) { - int64_t pts = pes_get_pts(buf->content, buf->size); - if(pts > 0) { -#ifdef TEST_SCR_PAUSE - if(need_pause) - scr_tuning_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 first frame 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 - - /* generated still images start with empty video PES, PTS = 0. - Reset metronom pts so images will be displayed */ - if(this->still_mode && buf->size == 14) { - int64_t pts = pes_get_pts(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 - - /* Count video frames for SCR tuning algorithm */ - if(this->live_mode && this->I_frames < 4) - if(IS_VIDEO_PACKET(buf->content) && buf->size > 32) - update_frames(this, buf->content, buf->size); - -#else /* FFMPEG_DEC */ - - /* Count video frames for SCR tuning algorithm */ - if(this->ffmpeg_mpeg2_decoder || (this->live_mode && this->I_frames < 4)) - if(IS_VIDEO_PACKET(buf->content) && buf->size > 32) { - uint8_t type = update_frames(this, buf->content, buf->size); - if(type && this->ffmpeg_mpeg2_decoder) { - /* signal FRAME_END to decoder */ - post_frame_end(this, buf); - /* 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 == B_FRAME && PES_HAS_PTS(buf->content)) - pes_strip_pts(buf->content, buf->size); - } - } - -#endif -} - -static void handle_disconnect(vdr_input_plugin_t *this) -{ - LOGMSG("read_block: no data source, returning NULL"); - - flush_all_fifos (this, 0); - - set_playback_speed(this, 1); - this->live_mode = 0; - reset_scr_tuning(this, XINE_FINE_SPEED_NORMAL); - this->stream->emergency_brake = 1; - - errno = ENOTCONN; -} - -static int adjust_scr_speed(vdr_input_plugin_t *this) -{ - int need_pause = 0; - - if(pthread_mutex_lock(&this->lock)) { - LOGERR("adjust_scr_speed: pthread_mutex_lock failed"); - return 0; - } - - if( (!this->live_mode && (this->fd_control < 0 || - this->fixed_scr)) || - this->slave_stream) { - if(this->scr_tuning) - reset_scr_tuning(this, this->speed_before_pause); - } else { -#ifdef TEST_SCR_PAUSE - if(this->stream_start || this->send_pts) { - reset_scr_tuning(this, this->speed_before_pause); - need_pause = 1; - } else { - vdr_adjust_realtime_speed(this); - } -#else - vdr_adjust_realtime_speed(this); -#endif - } - pthread_mutex_unlock(&this->lock); - - return need_pause; -} - -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; - int need_pause = 0; - - TRACE("vdr_plugin_read_block"); - - /* adjust SCR speed */ - need_pause = adjust_scr_speed(this); - - do { - - /* check for disconnection/termination */ - if (!this->funcs.push_input_write /* reading from socket */ && - !this->control_running) { - /* disconnected ? */ - handle_disconnect(this); - return NULL; - } - - /* 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"); - } - - buf = fifo_buffer_timed_get(this->block_buffer, 500); - if (!buf) { - if (!this->is_paused && - !this->still_mode && - !this->is_trickspeed && - !this->slave_stream && - this->stream->video_fifo->fifo_size <= 0) { - this->read_timeouts++; - - if(this->read_timeouts > 16) { - LOGMSG("No data in 8 seconds, queuing no signal image"); - queue_nosignal(this); - this->read_timeouts = 0; - } - } else { - this->read_timeouts = 0; - } - - if(NULL != (buf = make_padding_frame(this))) - return buf; - LOGMSG("make_padding_frame FAILED"); - continue; - } - this->read_timeouts = 0; - - if(! (buf = preprocess_buf(this, buf))) - continue; - - /* control buffers go always to demuxer */ - if ((buf->type & BUF_MAJOR_MASK) == BUF_CONTROL_BASE) - return buf; - /* ignore UDP/RTP "idle" padding */ - if(IS_PADDING_PACKET(buf->content)) - return buf; - - buf = demux_buf(this, buf); - - } while (!buf); - - postprocess_buf(this, buf, need_pause); - - 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) -{ - return 2048; -} - -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 = { - .cmd = OSD_Close, - .wnd = i, - }; - LOGDBG("Closing osd %d", i); - exec_osd_command(this, &cmd); - } - } - - /* restore video properties */ - if(this->video_properties_saved) - set_video_properties(this, -1,-1,-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 */ - LOGDBG("Disposing fifos"); - - /* need to get all buffer elements back before disposing own buffers ... */ - flush_all_fifos (this, 1); - - if (this->block_buffer) - this->block_buffer->dispose(this->block_buffer); - if (this->hd_buffer) - this->hd_buffer->dispose(this->hd_buffer); - - 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 - } - -#ifdef INPUT_OPTIONAL_DATA_DEMUXER - else if(data_type == INPUT_OPTIONAL_DATA_DEMUXER) { - static const char demux_name[] = "mpeg_block"; - *((const char **)data) = demux_name; - return INPUT_OPTIONAL_SUCCESS; - } -#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; - - /* 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; - } - - this->scr_tuning = SCR_TUNING_OFF; - this->curpos = 0; - - /* 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); - - LOGDBG("xine_input_xvdr: revision %s", module_revision); - - if (this->class->num_buffers_hd != HD_BUF_NUM_BUFS) - LOGMSG("Using non-default \"media." MRL_ID ".num_buffers_hd:%d\"", this->class->num_buffers_hd); - - 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((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 - 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, MRL_ID "+tcp://", MRL_ID_LEN+7) && (this->tcp=1)) || - (!strncasecmp(this->mrl, MRL_ID "+udp://", MRL_ID_LEN+7) && (this->udp=1)) || - (!strncasecmp(this->mrl, MRL_ID "+rtp://", MRL_ID_LEN+7) && (this->rtp=1)) || - (!strncasecmp(this->mrl, MRL_ID "+pipe://", MRL_ID_LEN+8)) || - (!strncasecmp(this->mrl, MRL_ID ":tcp://", MRL_ID_LEN+7) && (this->tcp=1)) || - (!strncasecmp(this->mrl, MRL_ID ":udp://", MRL_ID_LEN+7) && (this->udp=1)) || - (!strncasecmp(this->mrl, MRL_ID ":rtp://", MRL_ID_LEN+7) && (this->rtp=1)) || - (!strncasecmp(this->mrl, MRL_ID ":pipe://", MRL_ID_LEN+8)) || - (!strncasecmp(this->mrl, MRL_ID "://", MRL_ID_LEN+3))) { - - 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 scr tuning step change */ -static void vdr_class_scr_tuning_step_cb(void *data, xine_cfg_entry_t *cfg) -{ - vdr_input_class_t *class = (vdr_input_class_t *) data; - - class->scr_tuning_step = cfg->num_value / 1000000.0; -} - -/* callback on scr tuning mode change */ -static void vdr_class_smooth_scr_tuning_cb(void *data, xine_cfg_entry_t *cfg) -{ - vdr_input_class_t *class = (vdr_input_class_t *) data; - - class->smooth_scr_tuning = cfg->num_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, MRL_ID ":", MRL_ID_LEN+1) && - strncasecmp (mrl, MRL_ID "+", MRL_ID_LEN+1)) - return NULL; - - if(!strncasecmp(mrl, MRL_ID "+slave://0x", MRL_ID_LEN+11)) { - LOGMSG("vdr_class_get_instance: slave stream requested"); - return fifo_class_get_instance(class_gen, stream, data); - } - - this = calloc(1, 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->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, MRL_ID "://", MRL_ID_LEN+3)) && - (strlen(mrl)==7)) - || (!strncasecmp(mrl, MRL_ID ":///", MRL_ID_LEN+4)); - - 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, MRL_ID ":") || - !strcasecmp(mrl, MRL_ID ":/") || - !strcasecmp(mrl, MRL_ID "://") || - !strcasecmp(mrl, MRL_ID ":///")) { - /* default to local host */ - free(this->mrl); - this->mrl = strdup(MRL_ID "://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.post_vdr_event = post_vdr_event; - } - - detect_video_decoders(this); - - 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 MRL_ID; -} -#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; - config_values_t *config = this->xine->config; - - config->unregister_callback(config, "media." MRL_ID ".default_mrl"); - config->unregister_callback(config, "media." MRL_ID ".osd.fast_scaling"); - config->unregister_callback(config, "media." MRL_ID ".scr_tuning_step"); - config->unregister_callback(config, "media." MRL_ID ".smooth_scr_tuning"); - free (this); -} - -static void *input_xvdr_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 < 1) ? "NONE" : - (iSysLogLevel < 2) ? "ERRORS" : - (iSysLogLevel < 3) ? "INFO" : - (iSysLogLevel < 4) ? "DEBUG" : - "VERBOSE DEBUG"); - } - } - - this = calloc(1, sizeof (vdr_input_class_t)); - - this->xine = xine; - - this->mrls[ 0 ] = config->register_string(config, - "media." MRL_ID ".default_mrl", - MRL_ID "://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, - "media." MRL_ID ".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->scr_tuning_step = config->register_num(config, - "media." MRL_ID ".scr_tuning_step", 5000, - _("SRC tuning step"), - _("SCR tuning step width unit %1000000."), - 10, vdr_class_scr_tuning_step_cb, - (void *)this) / 1000000.0; - - this->smooth_scr_tuning = config->register_bool(config, - "media." MRL_ID ".smooth_scr_tuning", 0, - _("Smoother SRC tuning"), - _("Smoother SCR tuning"), - 10, vdr_class_smooth_scr_tuning_cb, - (void *)this); - - this->num_buffers_hd = config->register_num(config, - "media." MRL_ID ".num_buffers_hd", HD_BUF_NUM_BUFS, - _("number of buffers for HD content"), - _("number of buffers for HD content"), - 10, NULL, NULL); - - 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 = MRL_ID; - 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, MRL_ID, XINE_VERSION_CODE, NULL, input_xvdr_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 1039ca8c..00000000 --- a/xine_input_vdr.h +++ /dev/null @@ -1,68 +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.10 2009-02-25 14:34:24 phintuka Exp $ - * - */ - -#ifndef __XINE_INPUT_VDR_H_ -#define __XINE_INPUT_VDR_H_ - -#if defined __cplusplus -extern "C" { -#endif - -#include <xine/input_plugin.h> - -#include "xine_input_vdr_mrl.h" - -struct input_plugin_s; -struct vdr_input_plugin_if_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 vdr_input_plugin_if_s *, const char *, int); - int (*push_input_control)(struct vdr_input_plugin_if_s *, const char *); - int (*push_input_osd) (struct vdr_input_plugin_if_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 (*post_vdr_event) (struct vdr_input_plugin_if_s *, const char *); -} vdr_input_plugin_funcs_t; - -typedef struct vdr_input_plugin_if_s { - input_plugin_t input_plugin; - vdr_input_plugin_funcs_t f; -} vdr_input_plugin_if_t; - -#define CONTROL_OK 0 -#define CONTROL_UNKNOWN -1 -#define CONTROL_PARAM_ERROR -2 -#define CONTROL_DISCONNECTED -3 - -typedef struct grab_data_s { - size_t size; - char *data; -} grab_data_t; - -#if defined __cplusplus -} -#endif - - -#endif /*__XINE_INPUT_VDR_H_*/ - diff --git a/xine_input_vdr_mrl.h b/xine_input_vdr_mrl.h deleted file mode 100644 index 9924d5cc..00000000 --- a/xine_input_vdr_mrl.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * xine_input_vdr_mrl.h: - * - * See the main source file 'xineliboutput.c' for copyright information and - * how to reach the author. - * - * $Id: xine_input_vdr_mrl.h,v 1.1 2008-11-11 23:46:41 phintuka Exp $ - * - */ - -#ifndef XINE_INPUT_VDR_MRL_H -#define XINE_INPUT_VDR_MRL_H - -# ifndef MRL_ID - -# define MRL_ID "xvdr" - -# undef MRL_ID_LEN -# define MRL_ID_LEN 4 - -# endif - -#endif diff --git a/xine_input_vdr_net.h b/xine_input_vdr_net.h deleted file mode 100644 index 5d42ab5b..00000000 --- a/xine_input_vdr_net.h +++ /dev/null @@ -1,176 +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.12 2009-07-22 11:29:28 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; - -#define TCP_PAYLOAD(pkt) ((uint8_t*)(pkt)+sizeof(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 - -#define UDP_PAYLOAD(pkt) ((uint8_t*)(pkt)+sizeof(stream_udp_header_t)) - - -/* - * 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 { - uint16_t padding0; /* must be padded to full DWORDs */ - stream_udp_header_t udphdr; - } PACKED; - - struct { - uint16_t padding1; /* 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_PES 96 /* application */ -#define RTP_PAYLOAD_TYPE_TS 33 /* MPEG-TS */ - -#define RTP_VERSION_BYTE (RTP_VERSION<<6) -#define RTP_PAYLOAD_TYPE_PES_M (RTP_PAYLOAD_TYPE_PES|RTP_MARKER_BIT) -#define RTP_PAYLOAD_TYPE_TS_M (RTP_PAYLOAD_TYPE_TS |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 - -#define RTP_PAYLOAD(pkt) ((uint8_t*)(pkt)+sizeof(stream_rtp_header_impl_t)) -/* access UDP header inside RTP header extension */ -#define RTP_UDP_PAYLOAD(pkt) (RTP_PAYLOAD(pkt)-sizeof(stream_udp_header_t)) - -#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 7988b0fb..00000000 --- a/xine_osd_command.h +++ /dev/null @@ -1,157 +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.14 2008-12-19 15:08:19 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_Flush = 8 /* Flush all pending OSD operations immediately */ -} 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 */ - -#define OSDFLAG_TOP_LAYER 0x10 /* window is part of top layer OSD */ - -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 { - uint8_t size; /* size of osd_command_t struct */ - - uint8_t cmd; /* osd_command_id_t */ - - uint8_t wnd; /* OSD window handle */ - uint8_t layer; /* OSD layer */ - - 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.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.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 9326162b..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.6 2008-05-22 09:56:02 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 = calloc(1, 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 = calloc(1, 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_swscale.c b/xine_post_swscale.c deleted file mode 100644 index 9e5be7c2..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.9 2008-12-13 14:24:03 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 = malloc(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 = calloc(1, 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\n"); - 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 412618cd..00000000 --- a/xine_sxfe_frontend.c +++ /dev/null @@ -1,1868 +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.2.24 2009-10-08 12:13:11 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 <math.h> - -/* X11 */ -#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_XINERAMA -# include <X11/extensions/Xinerama.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" - -#ifdef HAVE_DBUS_GLIB_1 -# include "tools/gnome_screensaver.h" -#endif - -#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 -{ - Visual *vis; - Drawable draw; - Picture pic; - uint16_t w, h; - uint8_t depth; - uint8_t allocated : 1; -} Xrender_Surf; -#endif /* HAVE_XRENDER */ - -/* - * data - */ - -typedef struct sxfe_s { - - /* function pointers / base class */ - union { - frontend_t fe; /* generic frontend */ - }; - - void (*update_display_size_cb)(frontend_t*); - void (*toggle_fullscreen_cb) (frontend_t*); - - /* from xine_frontend.c */ - double (*dest_pixel_aspect) (const frontend_t *, - double video_pixel_aspect, - int video_width, int video_height); - void (*frame_output_handler)(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); - - /* vdr */ - fe_keypress_f keypress; - - /* stored original handlers */ - int (*fe_xine_open)(frontend_t *this_gen, const char *mrl); - int (*fe_xine_play)(frontend_t *this_gen); - - - /* 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 - Time prev_click_time; /* time of previous mouse button click (grab double clicks) */ -#ifdef HAVE_XDPMS - BOOL dpms_state; -#endif - - /* Atoms */ - Atom xa_SXFE_INTERRUPT; - Atom xa_WM_DELETE_WINDOW; - Atom xa_MOTIF_WM_HINTS; - Atom xa_WIN_LAYER; - Atom xa_WIN_STATE; - Atom xa_NET_ACTIVE_WINDOW; - Atom xa_NET_WM_STATE; - Atom xa_NET_WM_STATE_ADD; - Atom xa_NET_WM_STATE_DEL; - Atom xa_NET_WM_STATE_ABOVE; - Atom xa_NET_WM_STATE_STICKY; - Atom xa_NET_WM_STATE_FULLSCREEN; - Atom xa_NET_WM_STATE_STAYS_ON_TOP; - - int xinerama_screen; /* current xinerama screen, -1 = auto */ - uint16_t xinerama_x; /* left-top position of current xinerama screen */ - uint16_t xinerama_y; - uint16_t origwidth; /* saved window-mode window size */ - uint16_t origheight; - uint16_t origxpos; /* saved window-mode window position */ - uint16_t origypos; - uint16_t dragging_x; - uint16_t dragging_y; - - uint8_t fullscreen : 1; -/*uint8_t vmode_switch : 1;*/ - uint8_t fullscreen_state_forced : 1; - uint8_t stay_above : 1; - uint8_t no_border : 1; - uint8_t check_move : 1; - uint8_t dragging : 1; - uint8_t hud : 1; - uint8_t gui_hotkeys : 1; - uint8_t no_x_kbd : 1; - - /* xine stuff */ - xine_t *xine; - xine_stream_t *stream; - xine_stream_t *slave_stream; - vdr_input_plugin_if_t *input_plugin; - 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; - char *video_port_name; - int xpos, ypos; - uint16_t video_width, video_height; - uint16_t width, height; - uint8_t aspect; - uint8_t cropping; - uint8_t scale_video; - uint8_t overscan; - uint8_t terminate_key_pressed; - uint8_t playback_finished; - uint8_t slave_playback_finished; - uint8_t field_order; - - /* strings */ - char *configfile; - - /* HUD stuff */ -#ifdef HAVE_XRENDER - XImage *hud_img; - Visual *hud_vis; - Xrender_Surf *surf_win; - Xrender_Surf *surf_img; - uint32_t *hud_img_mem; - GC gc; - Window hud_window; - XShmSegmentInfo hud_shminfo; - - uint16_t osd_width; - uint16_t osd_height; -#endif /* HAVE_XRENDER */ - -} fe_t, sxfe_t; - - -/* Common (non-X11/FB) frontend functions */ -#include "xine_frontend.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 sxfe_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 = this->dest_pixel_aspect((frontend_t*)this, video_pixel_aspect, - video_width, video_height); -} - -static void init_atoms(sxfe_t *this) -{ - if (this->xa_SXFE_INTERRUPT == None) { - this->xa_SXFE_INTERRUPT = XInternAtom(this->display, "SXFE_INTERRUPT", False); - this->xa_WM_DELETE_WINDOW = XInternAtom(this->display, "WM_DELETE_WINDOW", False); - this->xa_MOTIF_WM_HINTS = XInternAtom(this->display, "_MOTIF_WM_HINTS", False); - this->xa_WIN_LAYER = XInternAtom(this->display, "_WIN_LAYER", False); - this->xa_WIN_STATE = XInternAtom(this->display, "_WIN_STATE", False); - this->xa_NET_ACTIVE_WINDOW = XInternAtom(this->display, "_NET_ACTIVE_WINDOW", False); - this->xa_NET_WM_STATE = XInternAtom(this->display, "_NET_WM_STATE", False); - this->xa_NET_WM_STATE_ADD = XInternAtom(this->display, "_NET_WM_STATE_ADD", False); - this->xa_NET_WM_STATE_DEL = XInternAtom(this->display, "_NET_WM_STATE_DEL", False); - this->xa_NET_WM_STATE_ABOVE = XInternAtom(this->display, "_NET_WM_STATE_ABOVE", False); - this->xa_NET_WM_STATE_STICKY= XInternAtom(this->display, "_NET_WM_STATE_STICKY", False); - this->xa_NET_WM_STATE_FULLSCREEN = XInternAtom(this->display, "_NET_WM_STATE_FULLSCREEN", False); - this->xa_NET_WM_STATE_STAYS_ON_TOP = XInternAtom(this->display, "_NET_WM_STATE_STAYS_ON_TOP", False); - } -} - -static void set_fs_size_hint(sxfe_t *this) -{ - XSizeHints hint; - hint.flags = USSize | USPosition | PPosition | PSize; - hint.x = this->xinerama_x; - hint.y = this->xinerama_y; - hint.width = this->width; - hint.height = this->height; - XLockDisplay(this->display); - XSetNormalHints(this->display, this->window[1], &hint); - XUnlockDisplay(this->display); -} - -/* set_border - * - * Set/remove window border - * - */ -static void set_border(sxfe_t *this, Window window, int border) -{ - MWMHints mwmhints = { - .flags = MWM_HINTS_DECORATIONS, - .decorations = border ? 1 : 0, - }; - - if(this->window_id > 0) - return; - - XLockDisplay(this->display); - XChangeProperty(this->display, window, - this->xa_MOTIF_WM_HINTS, this->xa_MOTIF_WM_HINTS, 32, - PropModeReplace, (unsigned char *) &mwmhints, - PROP_MWM_HINTS_ELEMENTS); - XUnlockDisplay(this->display); -} - -static void set_fullscreen_props(sxfe_t *this) -{ - XEvent ev; - - if(this->window_id > 0) - return; - - set_fs_size_hint(this); - - /* no border in fullscreen window */ - set_border(this, this->window[1], 0); - - memset(&ev, 0, sizeof(ev)); - ev.type = ClientMessage; - ev.xclient.type = ClientMessage; - ev.xclient.message_type = this->xa_NET_WM_STATE; - ev.xclient.display = this->display; - ev.xclient.window = this->window[1]; - ev.xclient.format = 32; - ev.xclient.data.l[0] = 1; - - /* _NET_WM_STATE_FULLSCREEN */ - XLockDisplay(this->display); - ev.xclient.data.l[1] = this->xa_NET_WM_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->xa_NET_WM_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->xa_NET_WM_STATE_STAYS_ON_TOP; - XSendEvent(this->display, DefaultRootWindow(this->display), False, - SubstructureNotifyMask|SubstructureRedirectMask, &ev); - XUnlockDisplay(this->display); - - /* _NET_ACTIVE_WINDOW */ - XLockDisplay(this->display); - ev.xclient.message_type = this->xa_NET_ACTIVE_WINDOW; - ev.xclient.data.l[0] = 0; - ev.xclient.data.l[1] = 0; - XSendEvent(this->display, DefaultRootWindow(this->display), False, - SubstructureNotifyMask|SubstructureRedirectMask, &ev); - XUnlockDisplay(this->display); -} - -static void update_window_title(sxfe_t *this) -{ - XLockDisplay(this->display); - - if (!this->keypress) { /* handler is set only in local mode */ - char *name = NULL; - if (XFetchName(this->display, this->window[0], &name) && name) { - char *newname = NULL; - if (strstr(name, " (top)")) - *strstr(name, " (top)") = 0; - if (this->stay_above) - if (asprintf(&newname, "%s (top)", name) < 0) - newname = NULL; - 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], this->stay_above ? "VDR - (top)" : "VDR"); - XStoreName(this->display, this->window[1], this->stay_above ? "VDR - (top)" : "VDR"); - } - } else { - XStoreName(this->display, this->window[0], this->stay_above ? "Local VDR (top)" : "Local VDR"); - XStoreName(this->display, this->window[1], this->stay_above ? "Local VDR (top)" : "Local VDR"); - } - - XUnlockDisplay(this->display); -} - -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) { - this->stay_above = stay_above; - /* Update window title */ - update_window_title(this); - } - - memset(&ev, 0, sizeof(ev)); - ev.type = ClientMessage; - ev.xclient.type = ClientMessage; - ev.xclient.message_type = this->xa_NET_WM_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; - - /* _NET_WM_STATE_ABOVE */ - XLockDisplay(this->display); - ev.xclient.data.l[1] = this->xa_NET_WM_STATE_ABOVE; - XSendEvent(this->display, DefaultRootWindow(this->display), False, - SubstructureNotifyMask|SubstructureRedirectMask, &ev); - XUnlockDisplay(this->display); - - /* _NET_WM_STATE_STAYS_ON_TOP */ - XLockDisplay(this->display); - ev.xclient.data.l[1] = this->xa_NET_WM_STATE_STAYS_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] = this->xa_NET_WM_STATE_STICKY; - 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], this->xa_WIN_LAYER, - 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 = this->xa_WIN_STATE; - 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 = this->xa_WIN_LAYER; - 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->xa_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 -} - -/* - * set_cursor - * - * Disable mouse cursor in video window (set transparent cursor) - */ -static void set_cursor(Display *dpy, Window win, const int enable) -{ - if(enable) - XDefineCursor(dpy, win, None); - else { - /* no cursor */ - const char bm_no_data[] = { 0,0,0,0, 0,0,0,0 }; - Cursor no_ptr; - XColor black, dummy; - Pixmap 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); - } -} - -static void update_xinerama_info(sxfe_t *this) -{ -#ifdef HAVE_XINERAMA - int screen = this->xinerama_screen; - this->xinerama_x = this->xinerama_y = 0; - XLockDisplay(this->display); - if(screen >= -1 && XineramaIsActive(this->display)) { - XineramaScreenInfo *screens; - int num_screens; - screens = XineramaQueryScreens(this->display, &num_screens); - if(screen >= num_screens) - screen = num_screens - 1; - if(screen == -1) { - const int x = this->origxpos + this->origwidth / 2; - const int y = this->origypos + this->origheight / 2; - for(screen = num_screens - 1; screen > 0; screen--) { - const int x0 = screens[screen].x_org; - const int y0 = screens[screen].y_org; - const int x1 = x0 + screens[screen].width; - const int y1 = y0 + screens[screen].height; - if(x0 <= x && x <= x1 && y0 <= y && y <= y1) - break; - } - } - if (screen < 0) - screen = 0; - this->xinerama_x = screens[screen].x_org; - this->xinerama_y = screens[screen].y_org; - this->width = screens[screen].width; - this->height = screens[screen].height; - - XFree(screens); - } - XUnlockDisplay(this->display); -#endif -} - -/* - * update_screen_size - * - * Update screen size (= size of fullscreen window) - */ -static void update_screen_size(sxfe_t *this) -{ - this->width = DisplayWidth(this->display, this->screen); - this->height = DisplayHeight(this->display, this->screen); - update_xinerama_info(this); -} - -/* - * HUD OSD stuff - */ - -#ifdef HAVE_XRENDER -static 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)); - - fmt = XRenderFindStandardFormat(dpy, alpha ? PictStandardARGB32 : 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; -} - -static 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.0 / scale_x); xf.matrix[0][1] = 0; xf.matrix[0][2] = 0; - xf.matrix[1][0] = 0; xf.matrix[1][1] = XDoubleToFixed(1.0 / scale_y); xf.matrix[1][2] = 0; - xf.matrix[2][0] = 0; xf.matrix[2][1] = 0; xf.matrix[2][2] = XDoubleToFixed(1.0); - XRenderSetPictureFilter(dpy, src->pic, smooth ? "bilinear" : "nearest", NULL, 0); - XRenderSetPictureTransform(dpy, src->pic, &xf); - x = (int)ceil((double)(x?x-1:0) * scale_x); - y = (int)ceil((double)(y?y-1:0) * scale_y); - w = (int)floor((double)(w+2) * scale_x); - h = (int)floor((double)(h+2) * scale_y); - XRenderComposite(dpy, PictOpSrc, src->pic, None, dst->pic, x, y, 0, 0, x, y, w, h); -} - -static 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; -} - -static 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; - - XSetForeground(this->display, this->gc, 0x00000000); - XFillRectangle(this->display, this->surf_img->draw, this->gc, - 0, 0, this->osd_width+2, this->osd_height+2); - XFlush(this->display); - break; - - case OSD_Set_RLE: /* Create/update OSD window. Data is rle-compressed. */ - LOGDBG("HUD Set RLE"); - if (!(cmd->flags & OSDFLAG_TOP_LAYER)) - break; - 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 + 1, - cmd->dirty_area.y2 - cmd->dirty_area.y1 + 1, - 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, 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 + 1, - cmd->dirty_area.y2 - cmd->dirty_area.y1 + 1, - False); - xrender_surf_blend(this->display, this->surf_img, this->surf_win, - cmd->x + cmd->dirty_area.x1, cmd->y + cmd->dirty_area.y1, - cmd->dirty_area.x2 - cmd->dirty_area.x1 + 1, - cmd->dirty_area.y2 - cmd->dirty_area.y1 + 1, - (XDouble)this->width / (XDouble)this->osd_width, - (XDouble)this->height / (XDouble)this->osd_height, - (cmd->scaling & 2)); // Note: 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 + 1, - cmd->dirty_area.y2 - cmd->dirty_area.y1 + 1); - } 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, 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 + 1, - cmd->dirty_area.y2 - cmd->dirty_area.y1 + 1); - xrender_surf_blend(this->display, this->surf_img, this->surf_win, - cmd->x + cmd->dirty_area.x1, cmd->y + cmd->dirty_area.y1, - cmd->dirty_area.x2 - cmd->dirty_area.x1 + 1, - cmd->dirty_area.y2 - cmd->dirty_area.y1 + 1, - (XDouble)this->width / (XDouble)this->osd_width, - (XDouble)this->height / (XDouble)this->osd_height, - (cmd->scaling & 2)); // Note: 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"); - if (!(cmd->flags & OSDFLAG_TOP_LAYER)) - break; - XSetForeground(this->display, this->gc, 0x00000000); - XFillRectangle(this->display, this->hud_window, this->gc, - 0, 0, this->width, this->height); - XFillRectangle(this->display, this->surf_img->draw, this->gc, - 0, 0, this->osd_width+2, this->osd_height+2); - XFlush(this->display); - break; - - default: - LOGDBG("hud_osd_command: unknown osd command"); - break; - } - XUnlockDisplay(this->display); - } - return 1; -} - -static int hud_osd_open(sxfe_t *this) -{ - 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); - - this->fe.xine_osd_command = hud_osd_command; - } - return 1; -} - -/* - * hud_osd_resize - * - * - Move and resize HUD along with main or fullscreen window - */ -static void hud_osd_resize(sxfe_t *this, Window video_window, int width, int height) -{ - if(this->hud) { - if(video_window == this->window[0]) { - int hud_x, hud_y; - Window tmp_win; - XLockDisplay(this->display); - XTranslateCoordinates(this->display, this->window[0], - DefaultRootWindow(this->display), - 0, 0, &hud_x, &hud_y, &tmp_win); - XResizeWindow(this->display, this->hud_window, width, height); - XMoveWindow(this->display, this->hud_window, hud_x, hud_y); - set_cursor(this->display, this->hud_window, 1); - XUnlockDisplay(this->display); - } else if(video_window == this->window[1]) { - XLockDisplay(this->display); - XResizeWindow(this->display, this->hud_window, width, height); - XMoveWindow(this->display, this->hud_window, 0, 0); - set_cursor(this->display, this->hud_window, 0); - XUnlockDisplay(this->display); - } - } -} - -/* - * hud_osd_focus - * - * - show / hide HUD OSD window - */ -static void hud_osd_focus(sxfe_t *this, XFocusChangeEvent *fev) -{ - if(this && this->hud) - if(fev->window == this->window[0] || fev->window == this->window[1]) { - - XLockDisplay(this->display); - - if(fev->type == FocusIn) - /* Show HUD again if sxfe window receives focus */ - XMapWindow(this->display, this->hud_window); - - else if(fev->type == FocusOut) - /* Dismiss HUD window if focusing away from frontend window */ - XUnmapWindow(this->display, this->hud_window); - - XUnlockDisplay(this->display); - } -} - -static void hud_osd_close(sxfe_t *this) -{ - 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 */ - -/* - * disable_DPMS - */ -static void disable_DPMS(sxfe_t *this) -{ -#ifdef HAVE_XDPMS - int dpms_dummy; - XLockDisplay(this->display); - 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("disable_DPMS: DPMS unavailable"); - } - XUnlockDisplay(this->display); -#endif -} - -/* - * open_display - * - * Try to connect to X server, in order - * 1) user-given display - * 2) DISPLAY environment variable - * 3) default display - * 4) :0.0 - * 5) 127.0.0.1:0.0 - */ -static int open_display(sxfe_t *this, const char *video_port) -{ - 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; - } - - return 1; -} - -/* - * set_icon - */ -static void set_icon(sxfe_t *this) -{ -# include "vdrlogo_32x32.c" - XLockDisplay(this->display); -#if defined(__WORDSIZE) && (__WORDSIZE == 32) - /* 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); -#else - long q[2+32*32]; - uint32_t *p = (uint32_t*)&vdrlogo_32x32; - int i; - for (i = 0; i < 2 + vdrlogo_32x32.width*vdrlogo_32x32.height; i++) - q[i] = p[i]; - XChangeProperty(this->display, this->window[0], - XInternAtom(this->display, "_NET_WM_ICON", False), - XA_CARDINAL, 32, PropModeReplace, - (unsigned char *) q, - 2 + vdrlogo_32x32.width*vdrlogo_32x32.height); -#endif - XUnlockDisplay(this->display); -} - -/* - * detect_display_ratio - * - * Calculate display aspect ratio - */ -static double detect_display_ratio(Display *dpy, int screen) -{ - double res_h = DisplayWidth (dpy, screen) * 1000.0 / DisplayWidthMM (dpy, screen); - double res_v = DisplayHeight (dpy, screen) * 1000.0 / DisplayHeightMM (dpy, screen); - - double display_ratio = res_v / res_h; - double diff = display_ratio - 1.0; - - if ((diff < 0.01) && (diff > -0.01)) - display_ratio = 1.0; - - LOGDBG("Display size : %d x %d mm", - DisplayWidthMM (dpy, screen), - DisplayHeightMM (dpy, screen)); - LOGDBG(" %d x %d pixels", - DisplayWidth (dpy, screen), - DisplayHeight (dpy, 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, display_ratio); - - return display_ratio; -} - -/* - * create_windows - * - * Create and initialize fullscreen and windowed mode X11 windows - * - Borderless fullscreen window - * - Set window title and icon - */ -static void create_windows(sxfe_t *this) -{ - XLockDisplay(this->display); - /* 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), - this->xinerama_x, this->xinerama_y, - this->width, this->height, - 0, 0, 0); - - /* full-screen window */ - set_fullscreen_props(this); - - /* Window hint */ - XClassHint *classHint = XAllocClassHint(); - if(classHint) { - classHint->res_name = "VDR"; - classHint->res_class = "VDR"; - XSetClassHint(this->display, this->window[0], classHint); - XSetClassHint(this->display, this->window[1], classHint); - XFree(classHint); - } - - /* Window name */ - const char *initial_title = (!this->keypress) ? "Connecting to VDR ..." : "Local VDR"; - XStoreName(this->display, this->window[0], initial_title); - XStoreName(this->display, this->window[1], initial_title); - - /* Icon */ - set_icon(this); - XUnlockDisplay(this->display); -} - -/* - * sxfe_display_open - * - * connect to X server, create windows - */ -static int sxfe_display_open(frontend_t *this_gen, - int xpos, int ypos, - int width, int height, int fullscreen, int hud, - int modeswitch, const char *modeline, int aspect, - fe_keypress_f keyfunc, int no_x_kbd, int gui_hotkeys, - const char *video_port, int scale_video, int field_order, - const char *aspect_controller, int window_id) -{ - sxfe_t *this = (sxfe_t*)this_gen; - - 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; -#else - LOGMSG("sxfe_display_open: Application was compiled without XRender support. HUD OSD disabled."); -#endif - } - - this->xpos = xpos; - this->ypos = ypos; - this->width = width; - this->height = height; - this->aspect = aspect; - this->cropping = 0; - this->overscan = 0; - this->scale_video = scale_video; - this->field_order = field_order ? 1 : 0; - this->aspect_controller = aspect_controller ? strdup(aspect_controller) : NULL; - - this->origxpos = xpos; - this->origypos = ypos; - this->origwidth = width>0 ? width : OSD_DEF_WIDTH; - this->origheight = height>0 ? height : OSD_DEF_HEIGHT; - - this->check_move = 0; - this->dragging = 0; - this->dragging_x = 0; - this->dragging_y = 0; - - this->fullscreen = fullscreen; -/*this->vmode_switch = modeswitch;*/ - this->fullscreen_state_forced = 0; -/*strn0cpy(this->modeline, modeline ? : "", sizeof(this->modeline));*/ - this->window_id = window_id; - - this->xinerama_screen = -1; - - this->gui_hotkeys = gui_hotkeys; - this->no_x_kbd = no_x_kbd ? 1 : 0; - - /* - * init x11 stuff - */ - - if (!XInitThreads ()) { - LOGERR("sxfe_display_open: XInitThreads failed"); - free(this); - return 0; - } - - if (!open_display(this, video_port)) - return 0; - - XLockDisplay (this->display); - - this->screen = DefaultScreen(this->display); - - /* #warning sxfe_display_open: TODO: switch vmode */ - - /* completion event */ - this->completion_event = -1; - if (XShmQueryExtension (this->display) == True) { - this->completion_event = XShmGetEventBase (this->display) + ShmCompletion; - } - - init_atoms(this); - - if(fullscreen) - update_screen_size(this); - - /* Output to existing window ? (embedded to another app) */ - 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_windows(this); - } - - /* 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); - - /* Map current window */ - XMapRaised (this->display, this->window[this->fullscreen ? 1 : 0]); - XMoveWindow(this->display, this->window[0], this->xpos, this->ypos); - - /* determine display aspect ratio */ - this->display_ratio = detect_display_ratio(this->display, this->screen); - - /* we want to get notified if user closes the window */ - XSetWMProtocols(this->display, this->window[this->fullscreen ? 1 : 0], &(this->xa_WM_DELETE_WINDOW), 1); - - /* Hide cursor */ - if(this->window_id <= 0) - set_cursor(this->display, this->window[1], 0); - - /* No screen saver */ - /* #warning TODO: suspend --> activate blank screen saver / DPMS display off ? */ - XSetScreenSaver(this->display, 0, 0, DefaultBlanking, DefaultExposures); - - /* Disable DPMS */ - disable_DPMS(this); - -#ifdef HAVE_DBUS_GLIB_1 - /* Disable GNOME screensaver */ - gnome_screensaver_control(0); -#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 = sxfe_dest_size_cb; - this->vis.frame_output_cb = fe_frame_output_cb; - this->vis.user_data = this; - - set_fullscreen_props(this); - - XUnlockDisplay (this->display); -#ifdef HAVE_XRENDER - return hud_osd_open(this); -#else - return 1; -#endif -} - -/* - * sxfe_display_config - * - * configure windows - */ -static int sxfe_display_config(frontend_t *this_gen, - int xpos, int ypos, - 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 (xpos < 0) xpos = this->xpos; - if (ypos < 0) ypos = this->ypos; - - if ( !fullscreen && - ( this->width != width || this->height != height || - this->xpos != xpos || this->ypos != ypos)) { - this->xpos = xpos; - this->ypos = ypos; - this->width = width; - this->height = height; - - XLockDisplay(this->display); - XResizeWindow(this->display, this->window[0], this->width, this->height); - XMoveWindow(this->display, this->window[0], this->xpos, this->ypos); - 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) - update_screen_size(this); - - if(fullscreen != this->fullscreen) { - Window tmp_win; - int tmp_x, tmp_y; - 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); - XResizeWindow(this->display, this->window[1], this->width, this->height); - XMoveWindow(this->display, this->window[1], this->xinerama_x, this->xinerama_y); - } - XSync(this->display, False); - if(XTranslateCoordinates(this->display, this->window[this->fullscreen ? 1 : 0], - DefaultRootWindow(this->display), - 0, 0, &tmp_x, &tmp_y, &tmp_win)) { - this->xpos = tmp_x; - this->ypos = tmp_y; - } - XUnlockDisplay(this->display); - xine_port_send_gui_data(this->video_port, XINE_GUI_SEND_DRAWABLE_CHANGED, - (void*) this->window[this->fullscreen ? 1 : 0]); - } - -#if 0 - if(!modeswitch && strcmp(modeline, this->modeline)) { - strn0cpy(this->modeline, modeline, sizeof(this->modeline)); - /* #warning TODO - switch vmode */ - } -#endif - -/*this->vmode_switch = modeswitch;*/ - this->aspect = aspect; - this->scale_video = scale_video; - this->field_order = field_order ? 1 : 0; - - return 1; -} - -static void sxfe_toggle_fullscreen(frontend_t *this_gen) -{ - sxfe_t *this = (sxfe_t*)this_gen; - - 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, -1, -1, this->origwidth, this->origheight, - this->fullscreen ? 0 : 1, - 0/*this->vmode_switch*/, NULL/*this->modeline*/, - this->aspect, this->scale_video, this->field_order); - - this->fullscreen_state_forced = !force; -} - -/* - * X event loop - */ - -/* - * sxfe_interrupt - * - * - Interrupt X event loop (sxfe_run) - * - */ -static void sxfe_interrupt(frontend_t *this_gen) -{ - sxfe_t *this = (sxfe_t*)this_gen; - - XClientMessageEvent event = { - .type = ClientMessage, - .display = this->display, - .window = this->window[this->fullscreen ? 1 : 0], - .message_type = this->xa_SXFE_INTERRUPT, - .format = 32, - }; - XLockDisplay (this->display); - if(!XSendEvent(event.display, event.window, 1, /*KeyPressMask*/0, (XEvent *)&event)) - LOGERR("sxfe_interrupt: XSendEvent(ClientMessage) FAILED\n"); - - XFlush(this->display); - XUnlockDisplay (this->display); -} - -/* - * XKeyEvent handler - * - */ -static void XKeyEvent_handler(sxfe_t *this, XKeyEvent *kev) -{ - if(kev->keycode && kev->type == KeyPress) { - KeySym ks; - char buffer[20]; - XComposeStatus status; - const char *fe_event = NULL; - - XLockDisplay (this->display); - XLookupString(kev, buffer, sizeof(buffer), &ks, &status); - XUnlockDisplay (this->display); - - switch(ks) { - case XK_f: - case XK_F: - if (this->gui_hotkeys) - fe_event = "TOGGLE_FULLSCREEN"; - break; - case XK_d: - case XK_D: - if (this->gui_hotkeys) - fe_event = "TOGGLE_DEINTERLACE"; - break; - case XK_Escape: - if (!this->keypress) { /* ESC exits only in remote mode */ - fe_event = "QUIT"; - } - break; - default:; - } - if (fe_event) - this->fe.send_event((frontend_t*)this, fe_event); - else if (!this->no_x_kbd) - this->fe.send_input_event((frontend_t*)this, "XKeySym", XKeysymToString(ks), 0, 0); - } -} - -/* - * XConfigureEvent handler - * - */ -static void XConfigureEvent_handler(sxfe_t *this, XConfigureEvent *cev) -{ - /* Move and resize HUD along with main or fullscreen window */ -#ifdef HAVE_XRENDER - if(this->hud) - hud_osd_resize(this, cev->window, cev->width, cev->height); -#endif - - /* update video window size */ - if (this->width != cev->width || this->height != cev->height) { - this->width = cev->width; - this->height = cev->height; - - /* inform VDR about new size */ - char str[128]; - snprintf(str, sizeof(str), "INFO WINDOW %dx%d", this->width, this->height); - this->fe.send_event((frontend_t*)this, str); - } - - 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) { - XLockDisplay (this->display); - XMoveWindow(this->display, this->window[0], cev->x, cev->y); - XUnlockDisplay (this->display); - } - } - - if ((cev->x == 0) && (cev->y == 0)) { - if(!this->fullscreen) { - int tmp_x, tmp_y; - Window tmp_win; - XLockDisplay(this->display); - if(XTranslateCoordinates(this->display, cev->window, - DefaultRootWindow(this->display), - 0, 0, &tmp_x, &tmp_y, &tmp_win)) { - this->xpos = tmp_x; - this->ypos = tmp_y; - } - XUnlockDisplay(this->display); - } - } else { - if(!this->fullscreen) { - /* update video window position */ - this->xpos = cev->x; - this->ypos = cev->y; - } - } -} - -/* - * XMotionEvent handler - * - * Track mouse movement when Button1 is pressed down - * - enable window dragging: user can simply drag window around screen - * - useful when window is borderless (no title bar) - */ -static void XMotionEvent_handler(sxfe_t *this, XMotionEvent *mev) -{ - if(this->dragging && !this->fullscreen) { - Window tmp_win; - int xpos, ypos; - - XLockDisplay(this->display); - - while(XCheckMaskEvent(this->display, ButtonMotionMask, (XEvent*)mev)); - - XTranslateCoordinates(this->display, this->window[0], - DefaultRootWindow(this->display), - 0, 0, &xpos, &ypos, &tmp_win); - - this->xpos = (xpos += mev->x_root - this->dragging_x); - this->ypos = (ypos += mev->y_root - this->dragging_y); - this->dragging_x = mev->x_root; - this->dragging_y = 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); - } -} - -/* - * XButtonEvent handler - * - * - Double click switches between windowed and fullscreen mode - * - Window can be moved by dragging it - * - Right mouse button switches window state: - * normal window -> borderless window -> always on top -> ... - */ -static void XButtonEvent_handler(sxfe_t *this, XButtonEvent *bev) -{ - switch(bev->button) { - case Button1: - /* Double-click toggles between fullscreen and windowed mode */ - if(bev->time - this->prev_click_time < DOUBLECLICK_TIME) { - /* Toggle fullscreen */ - this->toggle_fullscreen_cb((frontend_t*)this); - this->prev_click_time = 0; /* don't react to third click ... */ - } else { - this->prev_click_time = bev->time; - if(!this->fullscreen && this->no_border && !this->dragging) { - /* start dragging window */ - this->dragging = 1; - this->dragging_x = bev->x_root; - this->dragging_y = bev->y_root; - } - } - break; - - case Button3: - /* Toggle border and stacking */ - if(!this->fullscreen) { - if(!this->stay_above) { - set_above(this, 1); - } else if(!this->no_border) { - set_border(this, this->window[0], 0); - this->no_border = 1; - } else { - set_border(this, this->window[0], 1); - this->no_border = 0; - set_above(this, 0); - } - } - break; - } -} - -/* - * sxfe_run - * - * - main X event loop - */ -static int sxfe_run(frontend_t *this_gen) -{ - sxfe_t *this = (sxfe_t*)this_gen; - - /* poll X server (connection socket). - * (XNextEvent will block until 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 = { - .fd = ConnectionNumber(this->display), - .events = POLLIN, - }; - if (poll(&pfd, 1, 50) < 1 || !(pfd.revents & POLLIN)) { - return 1; - } - } - - while (XPending(this->display) > 0) { - - XEvent event; - - XLockDisplay (this->display); - XNextEvent (this->display, &event); - XUnlockDisplay (this->display); - - 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_handler(this, (XConfigureEvent *) &event); - break; - -#ifdef HAVE_XRENDER - case FocusIn: - case FocusOut: - hud_osd_focus(this, (XFocusChangeEvent *) &event); - break; -#endif - - case ButtonRelease: - this->dragging = 0; - break; - - case MotionNotify: - XMotionEvent_handler(this, (XMotionEvent *) &event); - break; - - case ButtonPress: - XButtonEvent_handler(this, (XButtonEvent *) &event); - break; - - case KeyPress: - case KeyRelease: - XKeyEvent_handler(this, (XKeyEvent *) &event); - break; - - case ClientMessage: - { - XClientMessageEvent *cmessage = (XClientMessageEvent *) &event; - if ( cmessage->message_type == this->xa_SXFE_INTERRUPT ) - LOGDBG("ClientMessage: sxfe_interrupt"); - - if ( cmessage->data.l[0] == this->xa_WM_DELETE_WINDOW ) { - /* we got a window deletion message from out window manager.*/ - LOGDBG("ClientMessage: WM_DELETE_WINDOW"); - - this->fe.send_event((frontend_t*)this, "QUIT"); - } - break; - } - } - - if (event.type == this->completion_event) - xine_port_send_gui_data (this->video_port, XINE_GUI_SEND_COMPLETION_EVENT, &event); - } - - return !this->fe.xine_is_finished((frontend_t*)this, 0); -} - -static void sxfe_display_close(frontend_t *this_gen) -{ - sxfe_t *this = (sxfe_t*)this_gen; - - if(!this) - return; - - if(this->xine) - this->fe.xine_exit(this_gen); - - if(this->display) { - -#ifdef HAVE_XRENDER - hud_osd_close(this); -#endif - -#ifdef HAVE_DBUS_GLIB_1 - /* Restore GNOE screensaver */ - gnome_screensaver_control(1); -#endif - -#ifdef HAVE_XDPMS - if(this->dpms_state) - 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; - } - - free(this->aspect_controller); - this->aspect_controller = NULL; -#if 0 - free(this->modeline); - this->modeline = NULL; -#endif -} - -/* - * sxfe_xine_open - * - * Override fe_xine_open: - * - Set window name: append remote host address to title bar text - */ -static int sxfe_xine_open(frontend_t *this_gen, const char *mrl) -{ - sxfe_t *this = (sxfe_t*)this_gen; - - int result = this->fe_xine_open(this_gen, mrl); - - if(result && mrl && !strncmp(mrl, MRL_ID, MRL_ID_LEN) && strstr(mrl, "//")) { - char *name = NULL, *end; - if (asprintf(&name, "VDR - %s", strstr(mrl, "//")+2) >= 0) { - if (NULL != (end = strstr(name, ":37890")) || /* hide only default port */ - NULL != (end = strchr(name, '#'))) /* hide attributes */ - *end = 0; - XStoreName(this->display, this->window[0], name); - XStoreName(this->display, this->window[1], name); - free(name); - } - } - - return result; -} - -static int sxfe_xine_play(frontend_t *this_gen) -{ - sxfe_t *this = (sxfe_t*)this_gen; - - int result = this->fe_xine_play(this_gen); - -#ifdef HAVE_XRENDER - if (result && this->input_plugin && this->hud) { - LOGDBG("sxfe_xine_play: Enabling HUD OSD"); - this->input_plugin->f.fe_handle = this_gen; - this->input_plugin->f.intercept_osd = hud_osd_command; - } -#endif /* HAVE_XRENDER */ - - return result; -} - -static frontend_t *sxfe_get_frontend(void) -{ - sxfe_t *this = calloc(1, sizeof(sxfe_t)); - - init_fe((fe_t*)this); - - 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.fe_run = sxfe_run; - this->fe.fe_interrupt = sxfe_interrupt; - - this->toggle_fullscreen_cb = sxfe_toggle_fullscreen; - - /* override */ - - this->fe_xine_open = this->fe.xine_open; - this->fe_xine_play = this->fe.xine_play; - - this->fe.xine_open = sxfe_xine_open; - this->fe.xine_play = sxfe_xine_play; - - return (frontend_t*)this; -} - -/* ENTRY POINT */ -const fe_creator_f fe_creator __attribute__((visibility("default"))) = sxfe_get_frontend; - - - |