diff options
author | Klaus Schmidinger <kls (at) cadsoft (dot) de> | 2011-04-17 16:50:00 +0200 |
---|---|---|
committer | Klaus Schmidinger <Klaus (dot) Schmidinger (at) tvdr (dot) de> | 2011-04-17 17:09:00 +0200 |
commit | 8b9350c091bc5ae8c9bb30b83a1fb567c3a7cb7f (patch) | |
tree | 51880b55c64c719561524fa4721d933b9205656e /PLUGINS/src | |
parent | 5619c0602bc623adeddf3385ada8c742aaea9762 (diff) | |
download | vdr-patches-8b9350c091bc5ae8c9bb30b83a1fb567c3a7cb7f.tar.gz vdr-patches-8b9350c091bc5ae8c9bb30b83a1fb567c3a7cb7f.tar.bz2 |
Version 1.7.18
- Changed -O2 to -O3 in Make.config.template (reported by Matti Lehtimäki).
- Added a missing 'default' case in cPixmapMemory::DrawEllipse().
- Fixed some direct comparisons of double values.
- Fixed detecting frames on channels that broadcast with separate "fields" instead
of complete frames.
- Made updating the editing marks during replay react faster in case the marks
file has just been written (with a patch from Udo Richter).
- Fixed horizontal scaling of subtitles (reported by Reinhard Nissl).
- Stripped the note "The data returned by this function is only used for informational
purposes (if any)" from the description of cDevice::GetVideoSize(). The VideoAspect
is now used to properly scale subtitles.
- Fixed cUnbufferedFile::Seek() in case it is compiled without USE_FADVISE (thanks
to Juergen Lock).
- Fixed the Language header of the Serbian translation file (thanks to Ville Skyttä).
- Added anti-aliasing when upscaling bitmaps, which improves the display of SD subtitles
when replayed on an HD OSD (thanks to Reinhard Nissl for his help in debugging).
- Renamed cBitmap::Scale() to Scaled(), because it doesn't modify the bitmap itself,
but rather returns a scaled copy.
- Fixed the description of cReceiver in PLUGINS.html, regarding detaching a receiver
from its device before deleting it (reported by Winfried Köhler). This change in
behavior was introduced in version 1.5.7.
- Fixed scaling subtitles in case the OSD size is exactly the same as the display
size of the subtitles.
- Added a missing initialization to sDvbSpuRect (reported by Sergiu Dotenco).
- Replaced "%lld" and "%llX" print format specifiers with "PRId64" and "PRIX64" to
avoid compiler warnings with gcc 4.5.2 (thanks to Sergiu Dotenco).
On a personal note: I find it a step in the totally wrong direction that there
have been macros introduced to work around this problem in the first place. There
should have been "real" format specifiers defined that address this. These macros
are nothing but an ugly workaround.
- Added Cancel(3) to ~cTrueColorDemo() in the "osddemo" plugin (thanks to Reinhard Nissl).
- Added a missing font deletion in cTrueColorDemo::Action() in the "osddemo" plugin
(thanks to Reinhard Nissl).
- Fixed a buffer overflow in cFont::Bidi() (thanks to Reinhard Nissl).
- Added HD stream content identifiers to vdr.5 (thanks to Christoph Haubrich).
- Made cRecordingInfo::Read(FILE *f) private to avoid calls to it from outside
cRecordingInfo or cRecording (reported by Mika Laitio).
- The dvbhddevice plugin is now part of the VDR distribution archive (thanks to
Andreas Regel).
- Removed an obsolete local variable in dvbsdffosd.c (thanks to Paul Menzel).
- Fixed a possible NULL pointer dereference in osddemo.c (reported by Paul Menzel).
- Now using pkg-config to get fribidi, freetype and fontconfig cflags and libs (thanks
to Ville Skyttä).
- The Makefile now also installs the include files (thanks to Ville Skyttä).
- Added handling of "ANSI/SCTE 57" descriptors (thanks too Rolf Ahrenberg).
- Avoiding an unecessary call to Recordings.ResetResume() (thanks to Reinhard
Nissl).
Diffstat (limited to 'PLUGINS/src')
-rw-r--r-- | PLUGINS/src/dvbhddevice/COPYING | 340 | ||||
-rw-r--r-- | PLUGINS/src/dvbhddevice/HISTORY | 16 | ||||
-rw-r--r-- | PLUGINS/src/dvbhddevice/Makefile | 114 | ||||
-rw-r--r-- | PLUGINS/src/dvbhddevice/README | 18 | ||||
-rw-r--r-- | PLUGINS/src/dvbhddevice/bitbuffer.c | 97 | ||||
-rw-r--r-- | PLUGINS/src/dvbhddevice/bitbuffer.h | 31 | ||||
-rw-r--r-- | PLUGINS/src/dvbhddevice/dvbhddevice.c | 48 | ||||
-rw-r--r-- | PLUGINS/src/dvbhddevice/dvbhdffdevice.c | 760 | ||||
-rw-r--r-- | PLUGINS/src/dvbhddevice/dvbhdffdevice.h | 123 | ||||
-rw-r--r-- | PLUGINS/src/dvbhddevice/hdffcmd.c | 1120 | ||||
-rw-r--r-- | PLUGINS/src/dvbhddevice/hdffcmd.h | 102 | ||||
-rw-r--r-- | PLUGINS/src/dvbhddevice/hdffmsgdef.h | 304 | ||||
-rw-r--r-- | PLUGINS/src/dvbhddevice/hdffosd.c | 755 | ||||
-rw-r--r-- | PLUGINS/src/dvbhddevice/hdffosd.h | 26 | ||||
-rw-r--r-- | PLUGINS/src/dvbhddevice/setup.c | 252 | ||||
-rw-r--r-- | PLUGINS/src/dvbhddevice/setup.h | 53 | ||||
-rw-r--r-- | PLUGINS/src/dvbsddevice/HISTORY | 4 | ||||
-rw-r--r-- | PLUGINS/src/dvbsddevice/dvbsddevice.c | 4 | ||||
-rw-r--r-- | PLUGINS/src/dvbsddevice/dvbsdffosd.c | 8 | ||||
-rw-r--r-- | PLUGINS/src/osddemo/HISTORY | 9 | ||||
-rw-r--r-- | PLUGINS/src/osddemo/osddemo.c | 12 |
21 files changed, 4184 insertions, 12 deletions
diff --git a/PLUGINS/src/dvbhddevice/COPYING b/PLUGINS/src/dvbhddevice/COPYING new file mode 100644 index 0000000..f90922e --- /dev/null +++ b/PLUGINS/src/dvbhddevice/COPYING @@ -0,0 +1,340 @@ + 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/PLUGINS/src/dvbhddevice/HISTORY b/PLUGINS/src/dvbhddevice/HISTORY new file mode 100644 index 0000000..aa788fd --- /dev/null +++ b/PLUGINS/src/dvbhddevice/HISTORY @@ -0,0 +1,16 @@ +VDR Plugin 'dvbhddevice' Revision History +----------------------------------------- + +2009-12-29: Version 0.0.1 + +- Initial revision. + +2010-01-04: Version 0.0.2 + +- Calling the MakePrimaryDevice() function of the base class to allow + the cDevice to stop displaying subtitles. +- Added support for DVB cards with multiple frontends. + +2011-04-17: Version 0.0.3 + +- Added support for TrueColor OSD. diff --git a/PLUGINS/src/dvbhddevice/Makefile b/PLUGINS/src/dvbhddevice/Makefile new file mode 100644 index 0000000..ea1b9d1 --- /dev/null +++ b/PLUGINS/src/dvbhddevice/Makefile @@ -0,0 +1,114 @@ +# +# Makefile for a Video Disk Recorder plugin +# +# $Id: Makefile 1.7 2011/04/17 11:40:55 kls 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. +# IMPORTANT: the presence of this macro is important for the Make.config +# file. So it must be defined, even if it is not used here! +# +PLUGIN = dvbhddevice + +### The version number of this plugin (taken from the main source file): + +VERSION = $(shell grep 'static const char \*VERSION *=' $(PLUGIN).c | awk '{ print $$6 }' | sed -e 's/[";]//g') + +### The C++ compiler and options: + +CXX ?= g++ +CXXFLAGS ?= -g -O3 -Wall -Woverloaded-virtual -Wno-parentheses + +### The directory environment: + +VDRDIR = ../../.. +LIBDIR = ../../lib +TMPDIR = /tmp + +### Make sure that necessary options are included: + +include $(VDRDIR)/Make.global + +### Allow user defined options to overwrite defaults: + +-include $(VDRDIR)/Make.config + +### The version number of VDR's plugin API (taken from VDR's "config.h"): + +APIVERSION = $(shell sed -ne '/define APIVERSION/s/^.*"\(.*\)".*$$/\1/p' $(VDRDIR)/config.h) + +### The name of the distribution archive: + +ARCHIVE = $(PLUGIN)-$(VERSION) +PACKAGE = vdr-$(ARCHIVE) + +### Includes and Defines (add further entries here): + +INCLUDES += -I$(VDRDIR)/include + +DEFINES += -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"' + +### The object files (add further files here): + +OBJS = $(PLUGIN).o bitbuffer.o dvbhdffdevice.o hdffcmd.o hdffosd.o setup.o + +### The main target: + +all: libvdr-$(PLUGIN).so i18n + +### Implicit rules: + +%.o: %.c + $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) $< + +### Dependencies: + +MAKEDEP = $(CXX) -MM -MG +DEPFILE = .dependencies +$(DEPFILE): Makefile + @$(MAKEDEP) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.c) > $@ + +-include $(DEPFILE) + +### 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 --package-name=VDR --package-version=$(VDRVERSION) --msgid-bugs-address='<see README>' -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) $(I18Npot) + +### Targets: + +libvdr-$(PLUGIN).so: $(OBJS) + $(CXX) $(CXXFLAGS) -shared $(OBJS) -o $@ + @cp --remove-destination $@ $(LIBDIR)/$@.$(APIVERSION) + +dist: $(I18Npo) clean + @-rm -rf $(TMPDIR)/$(ARCHIVE) + @mkdir $(TMPDIR)/$(ARCHIVE) + @cp -a * $(TMPDIR)/$(ARCHIVE) + @tar czf $(PACKAGE).tgz -C $(TMPDIR) $(ARCHIVE) + @-rm -rf $(TMPDIR)/$(ARCHIVE) + @echo Distribution package created as $(PACKAGE).tgz + +clean: + @-rm -f $(OBJS) $(DEPFILE) *.so *.tgz core* *~ $(PODIR)/*.mo $(PODIR)/*.pot diff --git a/PLUGINS/src/dvbhddevice/README b/PLUGINS/src/dvbhddevice/README new file mode 100644 index 0000000..5697dea --- /dev/null +++ b/PLUGINS/src/dvbhddevice/README @@ -0,0 +1,18 @@ +This is a "plugin" for the Video Disk Recorder (VDR). + +Written by: Andreas Regel <andreas.regel@gmx.de> + +Project's homepage: http://powarman.dyndns.org/hg/dvbhddevice + +Latest version available at: http://powarman.dyndns.org/hg/dvbhddevice + +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. +See the file COPYING for more information. + +Description: + +The 'dvbhddevice' plugin implements the output device for the +"Full Featured TechnoTrend S2-6400" DVB cards. diff --git a/PLUGINS/src/dvbhddevice/bitbuffer.c b/PLUGINS/src/dvbhddevice/bitbuffer.c new file mode 100644 index 0000000..244b85e --- /dev/null +++ b/PLUGINS/src/dvbhddevice/bitbuffer.c @@ -0,0 +1,97 @@ +/* + * bitbuffer.c: TODO(short description) + * + * See the README file for copyright information and how to reach the author. + * + * $Id: bitbuffer.c 1.1 2009/12/29 14:29:20 kls Exp $ + */ + +#include "bitbuffer.h" +#include <stdlib.h> + +cBitBuffer::cBitBuffer(uint32_t MaxLength) +{ + mData = NULL; + mMaxLength = 0; + mBitPos = 0; + + if (MaxLength <= 0x10000) + { + mData = new uint8_t[MaxLength]; + if (mData) + { + mMaxLength = MaxLength * 8; + } + } +} + +cBitBuffer::~cBitBuffer(void) +{ + if (mData) + delete[] mData; +} + +uint8_t * cBitBuffer::GetData(void) +{ + return mData; +} + +uint32_t cBitBuffer::GetMaxLength(void) +{ + return mMaxLength / 8; +} + +uint32_t cBitBuffer::GetBits(int NumBits) +{ + return 0; +} + +void cBitBuffer::SetBits(int NumBits, uint32_t Data) +{ + uint32_t nextBitPos; + uint32_t bytePos; + uint32_t bitsInByte; + int shift; + + if (NumBits <= 0 || NumBits > 32) + return; + + nextBitPos = mBitPos + NumBits; + + if (nextBitPos > mMaxLength) + return; + + bytePos = mBitPos / 8; + bitsInByte = mBitPos % 8; + + mData[bytePos] &= (uint8_t) (0xFF << (8 - bitsInByte)); + shift = NumBits - (8 - bitsInByte); + if (shift > 0) + mData[bytePos] |= (uint8_t) (Data >> shift); + else + mData[bytePos] |= (uint8_t) (Data << (-shift)); + NumBits -= 8 - bitsInByte; + bytePos++; + while (NumBits > 0) + { + shift = NumBits - 8; + if (shift > 0) + mData[bytePos] = (uint8_t) (Data >> shift); + else + mData[bytePos] = (uint8_t) (Data << (-shift)); + NumBits -= 8; + bytePos++; + } + mBitPos = nextBitPos; +} + +uint32_t cBitBuffer::GetByteLength(void) +{ + return (mBitPos + 7) / 8; +} + +void cBitBuffer::SetDataByte(uint32_t Position, uint8_t Data) +{ + if (Position < mMaxLength) + mData[Position] = Data; +} diff --git a/PLUGINS/src/dvbhddevice/bitbuffer.h b/PLUGINS/src/dvbhddevice/bitbuffer.h new file mode 100644 index 0000000..e7b3650 --- /dev/null +++ b/PLUGINS/src/dvbhddevice/bitbuffer.h @@ -0,0 +1,31 @@ +/* + * bitbuffer.h: TODO(short description) + * + * See the README file for copyright information and how to reach the author. + * + * $Id: bitbuffer.h 1.1 2009/12/29 14:27:03 kls Exp $ + */ + +#ifndef _HDFF_BITBUFFER_H_ +#define _HDFF_BITBUFFER_H_ + +#include <stdint.h> + +class cBitBuffer +{ +private: + uint8_t * mData; + uint32_t mMaxLength; + uint32_t mBitPos; +public: + cBitBuffer(uint32_t MaxLength); + ~cBitBuffer(void); + uint8_t * GetData(void); + uint32_t GetMaxLength(void); + uint32_t GetBits(int NumBits); + void SetBits(int NumBits, uint32_t Data); + uint32_t GetByteLength(void); + void SetDataByte(uint32_t Position, uint8_t Data); +}; + +#endif diff --git a/PLUGINS/src/dvbhddevice/dvbhddevice.c b/PLUGINS/src/dvbhddevice/dvbhddevice.c new file mode 100644 index 0000000..d639922 --- /dev/null +++ b/PLUGINS/src/dvbhddevice/dvbhddevice.c @@ -0,0 +1,48 @@ +/* + * dvbhddevice.c: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id: dvbhddevice.c 1.12 2011/04/17 11:20:22 kls Exp $ + */ + +#include <vdr/plugin.h> +#include "dvbhdffdevice.h" +#include "setup.h" + +static const char *VERSION = "0.0.3"; +static const char *DESCRIPTION = "HD Full Featured DVB device"; + +class cPluginDvbhddevice : public cPlugin { +private: + cDvbHdFfDeviceProbe *probe; +public: + cPluginDvbhddevice(void); + virtual ~cPluginDvbhddevice(); + virtual const char *Version(void) { return VERSION; } + virtual const char *Description(void) { return DESCRIPTION; } + virtual cMenuSetupPage *SetupMenu(void); + virtual bool SetupParse(const char *Name, const char *Value); + }; + +cPluginDvbhddevice::cPluginDvbhddevice(void) +{ + probe = new cDvbHdFfDeviceProbe; +} + +cPluginDvbhddevice::~cPluginDvbhddevice() +{ + delete probe; +} + +cMenuSetupPage *cPluginDvbhddevice::SetupMenu(void) +{ + return new cHdffSetupPage(cDvbHdFfDevice::GetHdffCmdHandler()); +} + +bool cPluginDvbhddevice::SetupParse(const char *Name, const char *Value) +{ + return gHdffSetup.SetupParse(Name, Value); +} + +VDRPLUGINCREATOR(cPluginDvbhddevice); // Don't touch this! diff --git a/PLUGINS/src/dvbhddevice/dvbhdffdevice.c b/PLUGINS/src/dvbhddevice/dvbhdffdevice.c new file mode 100644 index 0000000..9263009 --- /dev/null +++ b/PLUGINS/src/dvbhddevice/dvbhdffdevice.c @@ -0,0 +1,760 @@ +/* + * dvbhdffdevice.c: The DVB HD Full Featured device interface + * + * See the README file for copyright information and how to reach the author. + * + * $Id: dvbhdffdevice.c 1.29 2011/04/17 11:20:22 kls Exp $ + */ + +#include "dvbhdffdevice.h" +#include <errno.h> +#include <limits.h> +#include <libsi/si.h> +#include <linux/videodev2.h> +#include <linux/dvb/audio.h> +#include <linux/dvb/dmx.h> +#include <linux/dvb/video.h> +#include <sys/ioctl.h> +#include <sys/mman.h> +#include <vdr/eitscan.h> +#include <vdr/transfer.h> +#include "hdffosd.h" +#include "setup.h" + +// --- cDvbHdFfDevice ---------------------------------------------------------- + +int cDvbHdFfDevice::devHdffOffset = -1; + +cDvbHdFfDevice::cDvbHdFfDevice(int Adapter, int Frontend) +:cDvbDevice(Adapter, Frontend) +{ + spuDecoder = NULL; + audioChannel = 0; + playMode = pmNone; + mHdffCmdIf = NULL; + + // Devices that are only present on cards with decoders: + + fd_osd = DvbOpen(DEV_DVB_OSD, adapter, frontend, O_RDWR); + fd_video = DvbOpen(DEV_DVB_VIDEO, adapter, frontend, O_RDWR | O_NONBLOCK); + fd_audio = DvbOpen(DEV_DVB_AUDIO, adapter, frontend, O_RDWR | O_NONBLOCK); + + //TODO missing /dev/video offset calculation + + isHdffPrimary = false; + if (devHdffOffset < 0) { + devHdffOffset = adapter; + isHdffPrimary = true; + mHdffCmdIf = new HDFF::cHdffCmdIf(fd_osd); + mHdffCmdIf->CmdAvSetAudioDelay(gHdffSetup.AudioDelay); + mHdffCmdIf->CmdAvSetAudioDownmix((HDFF::eDownmixMode) gHdffSetup.AudioDownmix); + mHdffCmdIf->CmdMuxSetVideoOut((HDFF::eVideoOut) gHdffSetup.AnalogueVideo); + mHdffCmdIf->CmdHdmiSetVideoMode(gHdffSetup.GetVideoMode()); + HDFF::tHdmiConfig hdmiConfig; + hdmiConfig.TransmitAudio = true; + hdmiConfig.ForceDviMode = false; + hdmiConfig.CecEnabled = gHdffSetup.CecEnabled; + mHdffCmdIf->CmdHdmiConfigure(&hdmiConfig); + if (gHdffSetup.CecEnabled) + mHdffCmdIf->CmdHdmiSendCecCommand(HDFF::cecCommandTvOn); + mHdffCmdIf->CmdRemoteSetProtocol((HDFF::eRemoteProtocol) gHdffSetup.RemoteProtocol); + mHdffCmdIf->CmdRemoteSetAddressFilter(gHdffSetup.RemoteAddress >= 0, gHdffSetup.RemoteAddress); + } + + // Video format: + + SetVideoFormat(Setup.VideoFormat); +} + +cDvbHdFfDevice::~cDvbHdFfDevice() +{ + delete spuDecoder; + if (isHdffPrimary) + delete mHdffCmdIf; + // We're not explicitly closing any device files here, since this sometimes + // caused segfaults. Besides, the program is about to terminate anyway... +} + +void cDvbHdFfDevice::MakePrimaryDevice(bool On) +{ + if (On) + new cHdffOsdProvider(mHdffCmdIf); + cDvbDevice::MakePrimaryDevice(On); +} + +bool cDvbHdFfDevice::HasDecoder(void) const +{ + return isHdffPrimary; +} + +cSpuDecoder *cDvbHdFfDevice::GetSpuDecoder(void) +{ + if (!spuDecoder && IsPrimaryDevice()) + spuDecoder = new cDvbSpuDecoder(); + return spuDecoder; +} + +uchar *cDvbHdFfDevice::GrabImage(int &Size, bool Jpeg, int Quality, int SizeX, int SizeY) +{ + //TODO + return NULL; +} + +void cDvbHdFfDevice::SetVideoDisplayFormat(eVideoDisplayFormat VideoDisplayFormat) +{ + //TODO??? + cDevice::SetVideoDisplayFormat(VideoDisplayFormat); +} + +void cDvbHdFfDevice::SetVideoFormat(bool VideoFormat16_9) +{ + HDFF::tVideoFormat videoFormat; + videoFormat.AutomaticEnabled = true; + videoFormat.AfdEnabled = true; + videoFormat.TvFormat = (HDFF::eTvFormat) gHdffSetup.TvFormat; + videoFormat.VideoConversion = (HDFF::eVideoConversion) gHdffSetup.VideoConversion; + mHdffCmdIf->CmdAvSetVideoFormat(0, &videoFormat); +} + +eVideoSystem cDvbHdFfDevice::GetVideoSystem(void) +{ + eVideoSystem VideoSystem = vsPAL; + if (fd_video >= 0) { + video_size_t vs; + if (ioctl(fd_video, VIDEO_GET_SIZE, &vs) == 0) { + if (vs.h == 480 || vs.h == 240) + VideoSystem = vsNTSC; + } + else + LOG_ERROR; + } + return VideoSystem; +} + +void cDvbHdFfDevice::GetVideoSize(int &Width, int &Height, double &VideoAspect) +{ + if (fd_video >= 0) { + video_size_t vs; + if (ioctl(fd_video, VIDEO_GET_SIZE, &vs) == 0) { + Width = vs.w; + Height = vs.h; + switch (vs.aspect_ratio) { + default: + case VIDEO_FORMAT_4_3: VideoAspect = 4.0 / 3.0; break; + case VIDEO_FORMAT_16_9: VideoAspect = 16.0 / 9.0; break; + case VIDEO_FORMAT_221_1: VideoAspect = 2.21; break; + } + return; + } + else + LOG_ERROR; + } + cDevice::GetVideoSize(Width, Height, VideoAspect); +} + +void cDvbHdFfDevice::GetOsdSize(int &Width, int &Height, double &PixelAspect) +{ + gHdffSetup.GetOsdSize(Width, Height, PixelAspect); +} + +/*TODO obsolete? +bool cDvbHdFfDevice::SetAudioBypass(bool On) +{ + if (setTransferModeForDolbyDigital != 1) + return false; + return ioctl(fd_audio, AUDIO_SET_BYPASS_MODE, On) == 0; +} +TODO*/ + +bool cDvbHdFfDevice::SetPid(cPidHandle *Handle, int Type, bool On) +{ + if (Handle->pid) { + dmx_pes_filter_params pesFilterParams; + memset(&pesFilterParams, 0, sizeof(pesFilterParams)); + if (On) { + if (Handle->handle < 0) { + Handle->handle = DvbOpen(DEV_DVB_DEMUX, adapter, frontend, O_RDWR | O_NONBLOCK, true); + if (Handle->handle < 0) { + LOG_ERROR; + return false; + } + } + if (Type == ptPcr) + mHdffCmdIf->CmdAvSetPcrPid(0, Handle->pid); + else if (Type == ptVideo) { + if (Handle->streamType == 0x1B) + mHdffCmdIf->CmdAvSetVideoPid(0, Handle->pid, HDFF::videoStreamH264); + else + mHdffCmdIf->CmdAvSetVideoPid(0, Handle->pid, HDFF::videoStreamMpeg2); + } + else if (Type == ptAudio) + mHdffCmdIf->CmdAvSetAudioPid(0, Handle->pid, HDFF::audioStreamMpeg1); + else if (Type == ptDolby) + mHdffCmdIf->CmdAvSetAudioPid(0, Handle->pid, HDFF::audioStreamAc3); + if (!(Type <= ptDolby && Handle->used <= 1)) { + pesFilterParams.pid = Handle->pid; + pesFilterParams.input = DMX_IN_FRONTEND; + pesFilterParams.output = DMX_OUT_TS_TAP; + pesFilterParams.pes_type= DMX_PES_OTHER; + pesFilterParams.flags = DMX_IMMEDIATE_START; + if (ioctl(Handle->handle, DMX_SET_PES_FILTER, &pesFilterParams) < 0) { + LOG_ERROR; + return false; + } + } + } + else if (!Handle->used) { + CHECK(ioctl(Handle->handle, DMX_STOP)); + if (Type == ptPcr) + mHdffCmdIf->CmdAvSetPcrPid(0, 0); + else if (Type == ptVideo) + mHdffCmdIf->CmdAvSetVideoPid(0, 0, HDFF::videoStreamMpeg2); + else if (Type == ptAudio) + mHdffCmdIf->CmdAvSetAudioPid(0, 0, HDFF::audioStreamMpeg1); + else if (Type == ptDolby) + mHdffCmdIf->CmdAvSetAudioPid(0, 0, HDFF::audioStreamAc3); + //TODO missing setting to 0x1FFF??? see cDvbDevice::SetPid() + close(Handle->handle); + Handle->handle = -1; + } + } + return true; +} + +void cDvbHdFfDevice::TurnOffLiveMode(bool LiveView) +{ + // Turn off live PIDs: + + DetachAll(pidHandles[ptAudio].pid); + DetachAll(pidHandles[ptVideo].pid); + DetachAll(pidHandles[ptPcr].pid); + DetachAll(pidHandles[ptTeletext].pid); + DelPid(pidHandles[ptAudio].pid); + DelPid(pidHandles[ptVideo].pid); + DelPid(pidHandles[ptPcr].pid, ptPcr); + DelPid(pidHandles[ptTeletext].pid); + DelPid(pidHandles[ptDolby].pid); +} + +bool cDvbHdFfDevice::SetChannelDevice(const cChannel *Channel, bool LiveView) +{ + int apid = Channel->Apid(0); + int vpid = Channel->Vpid(); + int dpid = Channel->Dpid(0); + + bool DoTune = !IsTunedToTransponder(Channel); + + bool pidHandlesVideo = pidHandles[ptVideo].pid == vpid; + bool pidHandlesAudio = pidHandles[ptAudio].pid == apid; + + bool TurnOffLivePIDs = DoTune + || !IsPrimaryDevice() + || LiveView // for a new live view the old PIDs need to be turned off + || pidHandlesVideo // for recording the PIDs must be shifted from DMX_PES_AUDIO/VIDEO to DMX_PES_OTHER + ; + + bool StartTransferMode = IsPrimaryDevice() && !DoTune + && (LiveView && HasPid(vpid ? vpid : apid) && (!pidHandlesVideo || (!pidHandlesAudio && (dpid ? pidHandles[ptAudio].pid != dpid : true)))// the PID is already set as DMX_PES_OTHER + || !LiveView && (pidHandlesVideo || pidHandlesAudio) // a recording is going to shift the PIDs from DMX_PES_AUDIO/VIDEO to DMX_PES_OTHER + ); + if (CamSlot() && !ChannelCamRelations.CamDecrypt(Channel->GetChannelID(), CamSlot()->SlotNumber())) + StartTransferMode |= LiveView && IsPrimaryDevice() && Channel->Ca() >= CA_ENCRYPTED_MIN; + + bool TurnOnLivePIDs = !StartTransferMode && LiveView; + + // Turn off live PIDs if necessary: + + if (TurnOffLivePIDs) + TurnOffLiveMode(LiveView); + + // Set the tuner: + + if (!cDvbDevice::SetChannelDevice(Channel, LiveView)) + return false; + + // If this channel switch was requested by the EITScanner we don't wait for + // a lock and don't set any live PIDs (the EITScanner will wait for the lock + // by itself before setting any filters): + + if (EITScanner.UsesDevice(this)) //XXX + return true; + + // PID settings: + + if (TurnOnLivePIDs) { + //SetAudioBypass(false);//TODO obsolete? + if (!(AddPid(Channel->Ppid(), ptPcr) && AddPid(vpid, ptVideo, Channel->Vtype()) && AddPid(apid, ptAudio))) { + esyslog("ERROR: failed to set PIDs for channel %d on device %d", Channel->Number(), CardIndex() + 1); + return false; + } + if (IsPrimaryDevice()) + AddPid(Channel->Tpid(), ptTeletext);//TODO obsolete? + } + else if (StartTransferMode) + cControl::Launch(new cTransferControl(this, Channel)); + + return true; +} + +int cDvbHdFfDevice::GetAudioChannelDevice(void) +{ + return audioChannel; +} + +void cDvbHdFfDevice::SetAudioChannelDevice(int AudioChannel) +{ + mHdffCmdIf->CmdAvSetAudioChannel(AudioChannel); + audioChannel = AudioChannel; +} + +void cDvbHdFfDevice::SetVolumeDevice(int Volume) +{ + mHdffCmdIf->CmdMuxSetVolume(Volume * 100 / 255); +} + +void cDvbHdFfDevice::SetDigitalAudioDevice(bool On) +{ + // not needed +} + +void cDvbHdFfDevice::SetAudioTrackDevice(eTrackType Type) +{ + //printf("SetAudioTrackDevice %d\n", Type); + const tTrackId *TrackId = GetTrack(Type); + if (TrackId && TrackId->id) { + if (IS_AUDIO_TRACK(Type)) { + if (pidHandles[ptAudio].pid && pidHandles[ptAudio].pid != TrackId->id) { + DetachAll(pidHandles[ptAudio].pid); + if (CamSlot()) + CamSlot()->SetPid(pidHandles[ptAudio].pid, false); + pidHandles[ptAudio].pid = TrackId->id; + SetPid(&pidHandles[ptAudio], ptAudio, true); + if (CamSlot()) { + CamSlot()->SetPid(pidHandles[ptAudio].pid, true); + CamSlot()->StartDecrypting(); + } + } + } + else if (IS_DOLBY_TRACK(Type)) { + pidHandles[ptDolby].pid = TrackId->id; + SetPid(&pidHandles[ptDolby], ptDolby, true); + } + } +} + +bool cDvbHdFfDevice::CanReplay(void) const +{ + return cDevice::CanReplay(); +} + +bool cDvbHdFfDevice::SetPlayMode(ePlayMode PlayMode) +{ + if (PlayMode == pmNone) { + mHdffCmdIf->CmdAvEnableVideoAfterStop(0, false); + mHdffCmdIf->CmdAvSetPcrPid(0, 0); + mHdffCmdIf->CmdAvSetVideoPid(0, 0, HDFF::videoStreamMpeg2); + mHdffCmdIf->CmdAvSetAudioPid(0, 0, HDFF::audioStreamMpeg1); + + ioctl(fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_DEMUX); + mHdffCmdIf->CmdAvSetDecoderInput(0, 0); + mHdffCmdIf->CmdAvEnableSync(0, true); + mHdffCmdIf->CmdAvSetPlayMode(0, true); + } + else { + if (playMode == pmNone) + TurnOffLiveMode(true); + + mHdffCmdIf->CmdAvSetPlayMode(1, Transferring()); + mHdffCmdIf->CmdAvSetStc(0, 100000); + mHdffCmdIf->CmdAvEnableSync(0, true); + mHdffCmdIf->CmdAvEnableVideoAfterStop(0, true); + + playVideoPid = -1; + playAudioPid = -1; + audioCounter = 0; + videoCounter = 0; + + mHdffCmdIf->CmdAvSetDecoderInput(0, 2); + ioctl(fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_MEMORY); + } + playMode = PlayMode; + return true; +} + +int64_t cDvbHdFfDevice::GetSTC(void) +{ + if (fd_video >= 0) { + uint64_t pts; + if (ioctl(fd_video, VIDEO_GET_PTS, &pts) == -1) { + esyslog("ERROR: pts %d: %m", CardIndex() + 1); + return -1; + } + return pts; + } + if (fd_audio >= 0) { + uint64_t pts; + if (ioctl(fd_audio, AUDIO_GET_PTS, &pts) == -1) { + esyslog("ERROR: pts %d: %m", CardIndex() + 1); + return -1; + } + return pts; + } + return -1; +} + +void cDvbHdFfDevice::TrickSpeed(int Speed) +{ + mHdffCmdIf->CmdAvEnableSync(0, false); + mHdffCmdIf->CmdAvSetAudioPid(0, 0, HDFF::audioStreamMpeg1); + playAudioPid = -1; + if (Speed > 0) + mHdffCmdIf->CmdAvSetVideoSpeed(0, 100 / Speed); +} + +void cDvbHdFfDevice::Clear(void) +{ + CHECK(ioctl(fd_video, VIDEO_CLEAR_BUFFER)); + mHdffCmdIf->CmdAvSetVideoPid(0, 0, HDFF::videoStreamMpeg1); + mHdffCmdIf->CmdAvSetAudioPid(0, 0, HDFF::audioStreamMpeg1); + playVideoPid = -1; + playAudioPid = -1; + cDevice::Clear(); +} + +void cDvbHdFfDevice::Play(void) +{ + mHdffCmdIf->CmdAvEnableSync(0, true); + mHdffCmdIf->CmdAvSetVideoSpeed(0, 100); + mHdffCmdIf->CmdAvSetAudioSpeed(0, 100); + cDevice::Play(); +} + +void cDvbHdFfDevice::Freeze(void) +{ + mHdffCmdIf->CmdAvSetVideoSpeed(0, 0); + mHdffCmdIf->CmdAvSetAudioSpeed(0, 0); + cDevice::Freeze(); +} + +void cDvbHdFfDevice::Mute(void) +{ + //TODO??? + cDevice::Mute(); +} + +static HDFF::eVideoStreamType MapVideoStreamTypes(int Vtype) +{ + switch (Vtype) { + case 0x01: return HDFF::videoStreamMpeg1; + case 0x02: return HDFF::videoStreamMpeg2; + case 0x1B: return HDFF::videoStreamH264; + default: return HDFF::videoStreamMpeg2; // fallback to MPEG2 + } +} + +void cDvbHdFfDevice::StillPicture(const uchar *Data, int Length) +{ + if (!Data || Length < TS_SIZE) + return; + if (Data[0] == 0x47) { + // TS data + cDevice::StillPicture(Data, Length); + } + else if (Data[0] == 0x00 && Data[1] == 0x00 && Data[2] == 0x01 && (Data[3] & 0xF0) == 0xE0) { + // PES data + char *buf = MALLOC(char, Length); + if (!buf) + return; + int i = 0; + int blen = 0; + while (i < Length - 6) { + if (Data[i] == 0x00 && Data[i + 1] == 0x00 && Data[i + 2] == 0x01) { + int len = Data[i + 4] * 256 + Data[i + 5]; + if ((Data[i + 3] & 0xF0) == 0xE0) { // video packet + // skip PES header + int offs = i + 6; + // skip header extension + if ((Data[i + 6] & 0xC0) == 0x80) { + // MPEG-2 PES header + if (Data[i + 8] >= Length) + break; + offs += 3; + offs += Data[i + 8]; + len -= 3; + len -= Data[i + 8]; + if (len < 0 || offs + len > Length) + break; + } + else { + // MPEG-1 PES header + while (offs < Length && len > 0 && Data[offs] == 0xFF) { + offs++; + len--; + } + if (offs <= Length - 2 && len >= 2 && (Data[offs] & 0xC0) == 0x40) { + offs += 2; + len -= 2; + } + if (offs <= Length - 5 && len >= 5 && (Data[offs] & 0xF0) == 0x20) { + offs += 5; + len -= 5; + } + else if (offs <= Length - 10 && len >= 10 && (Data[offs] & 0xF0) == 0x30) { + offs += 10; + len -= 10; + } + else if (offs < Length && len > 0) { + offs++; + len--; + } + } + if (blen + len > Length) // invalid PES length field + break; + memcpy(&buf[blen], &Data[offs], len); + i = offs + len; + blen += len; + } + else if (Data[i + 3] >= 0xBD && Data[i + 3] <= 0xDF) // other PES packets + i += len + 6; + else + i++; + } + else + i++; + } + mHdffCmdIf->CmdAvShowStillImage(0, (uint8_t *)buf, blen, MapVideoStreamTypes(PatPmtParser()->Vtype())); + free(buf); + } + else { + // non-PES data + mHdffCmdIf->CmdAvShowStillImage(0, Data, Length, MapVideoStreamTypes(PatPmtParser()->Vtype())); + } +} + +bool cDvbHdFfDevice::Poll(cPoller &Poller, int TimeoutMs) +{ + Poller.Add(fd_video, true); + return Poller.Poll(TimeoutMs); +} + +bool cDvbHdFfDevice::Flush(int TimeoutMs) +{ + //TODO actually this function should wait until all buffered data has been processed by the card, but how? + return true; +} + +void cDvbHdFfDevice::BuildTsPacket(uint8_t * TsBuffer, bool PusiSet, uint16_t Pid, uint8_t Counter, const uint8_t * Data, uint32_t Length) +{ + TsBuffer[0] = 0x47; + TsBuffer[1] = PusiSet ? 0x40 : 0x00; + TsBuffer[1] |= Pid >> 8; + TsBuffer[2] = Pid & 0xFF; + if (Length >= 184) + { + TsBuffer[3] = 0x10 | Counter; + memcpy(TsBuffer + 4, Data, 184); + } + else + { + uint8_t adaptationLength; + + TsBuffer[3] = 0x30 | Counter; + adaptationLength = 183 - Length; + TsBuffer[4] = adaptationLength; + if (adaptationLength > 0) + { + TsBuffer[5] = 0x00; + memset(TsBuffer + 6, 0xFF, adaptationLength - 1); + } + memcpy(TsBuffer + 5 + adaptationLength, Data, Length); + } +} + +uint32_t cDvbHdFfDevice::PesToTs(uint8_t * TsBuffer, uint16_t Pid, uint8_t & Counter, const uint8_t * Data, uint32_t Length) +{ + uint32_t tsOffset; + uint32_t i; + + tsOffset = 0; + i = 0; + while (Length > 0) + { + BuildTsPacket(TsBuffer + tsOffset, i == 0, Pid, Counter, Data + i * 184, Length); + if (Length >= 184) + Length -= 184; + else + Length = 0; + Counter = (Counter + 1) & 15; + tsOffset += 188; + i++; + } + return tsOffset; +} + +int cDvbHdFfDevice::PlayVideo(const uchar *Data, int Length) +{ + //TODO: support greater Length + uint8_t tsBuffer[188 * 16]; + uint32_t tsLength; + int pid = 100; + + tsLength = PesToTs(tsBuffer, pid, videoCounter, Data, Length); + + if (pid != playVideoPid) { + playVideoPid = pid; + mHdffCmdIf->CmdAvSetVideoPid(0, playVideoPid, HDFF::videoStreamMpeg2, true); + } + if (WriteAllOrNothing(fd_video, tsBuffer, tsLength, 1000, 10) <= 0) + Length = 0; + return Length; +} + +int cDvbHdFfDevice::PlayAudio(const uchar *Data, int Length, uchar Id) +{ + uint8_t streamId; + uint8_t tsBuffer[188 * 16]; + uint32_t tsLength; + HDFF::eAudioStreamType streamType = HDFF::audioStreamMpeg1; + HDFF::eAVContainerType containerType = HDFF::avContainerPes; + int pid; + + streamId = Data[3]; + if (streamId >= 0xC0 && streamId <= 0xDF) + { + streamType = HDFF::audioStreamMpeg1; + } + else if (streamId == 0xBD) + { + const uint8_t * payload = Data + 9 + Data[8]; + if ((payload[0] & 0xF8) == 0xA0) + { + containerType = HDFF::avContainerPesDvd; + streamType = HDFF::audioStreamPcm; + } + else if ((payload[0] & 0xF8) == 0x88) + { + containerType = HDFF::avContainerPesDvd; + streamType = HDFF::audioStreamDts; + } + else if ((payload[0] & 0xF8) == 0x80) + { + containerType = HDFF::avContainerPesDvd; + streamType = HDFF::audioStreamAc3; + } + else + { + streamType = HDFF::audioStreamAc3; + } + } + pid = 200 + (int) streamType; + tsLength = PesToTs(tsBuffer, pid, audioCounter, Data, Length); + + if (pid != playAudioPid) { + playAudioPid = pid; + mHdffCmdIf->CmdAvSetAudioPid(0, playAudioPid, streamType, containerType); + } + if (WriteAllOrNothing(fd_video, tsBuffer, tsLength, 1000, 10) <= 0) + Length = 0; + return Length; +} + +int cDvbHdFfDevice::PlayTsVideo(const uchar *Data, int Length) +{ + int pid = TsPid(Data); + if (pid != playVideoPid) { + PatPmtParser(); + if (pid == PatPmtParser()->Vpid()) { + playVideoPid = pid; + mHdffCmdIf->CmdAvSetVideoPid(0, playVideoPid, MapVideoStreamTypes(PatPmtParser()->Vtype()), true); + } + } + return WriteAllOrNothing(fd_video, Data, Length, 1000, 10); +} + +static HDFF::eAudioStreamType MapAudioStreamTypes(int Atype) +{ + switch (Atype) { + case 0x03: return HDFF::audioStreamMpeg1; + case 0x04: return HDFF::audioStreamMpeg2; + case SI::AC3DescriptorTag: return HDFF::audioStreamAc3; + case SI::EnhancedAC3DescriptorTag: return HDFF::audioStreamEAc3; + case 0x0F: return HDFF::audioStreamAac; + case 0x11: return HDFF::audioStreamHeAac; + default: return HDFF::audioStreamMaxValue; // there is no HDFF::audioStreamNone + } +} + +int cDvbHdFfDevice::PlayTsAudio(const uchar *Data, int Length) +{ + int pid = TsPid(Data); + if (pid != playAudioPid) { + playAudioPid = pid; + int AudioStreamType = -1; + for (int i = 0; PatPmtParser()->Apid(i); i++) { + if (playAudioPid == PatPmtParser()->Apid(i)) { + AudioStreamType = PatPmtParser()->Atype(i); + break; + } + } + if (AudioStreamType < 0) { + for (int i = 0; PatPmtParser()->Dpid(i); i++) { + if (playAudioPid == PatPmtParser()->Dpid(i)) { + AudioStreamType = PatPmtParser()->Dtype(i); + break; + } + } + } + mHdffCmdIf->CmdAvSetAudioPid(0, playAudioPid, MapAudioStreamTypes(AudioStreamType)); + } + return WriteAllOrNothing(fd_video, Data, Length, 1000, 10); +} + +HDFF::cHdffCmdIf *cDvbHdFfDevice::GetHdffCmdHandler(void) +{ + //TODO why not just keep a pointer? + if (devHdffOffset >= 0) { + cDvbHdFfDevice *device = (cDvbHdFfDevice *)GetDevice(devHdffOffset); + if (device) + return device->mHdffCmdIf; + } + return NULL; +} + +// --- cDvbHdFfDeviceProbe --------------------------------------------------- + +bool cDvbHdFfDeviceProbe::Probe(int Adapter, int Frontend) +{ + static uint32_t SubsystemIds[] = { + 0x13C23009, // Technotrend S2-6400 HDFF + 0x00000000 + }; + cString FileName; + cReadLine ReadLine; + FILE *f = NULL; + uint32_t SubsystemId = 0; + FileName = cString::sprintf("/sys/class/dvb/dvb%d.frontend%d/device/subsystem_vendor", Adapter, Frontend); + if ((f = fopen(FileName, "r")) != NULL) { + if (char *s = ReadLine.Read(f)) + SubsystemId = strtoul(s, NULL, 0) << 16; + fclose(f); + } + FileName = cString::sprintf("/sys/class/dvb/dvb%d.frontend%d/device/subsystem_device", Adapter, Frontend); + if ((f = fopen(FileName, "r")) != NULL) { + if (char *s = ReadLine.Read(f)) + SubsystemId |= strtoul(s, NULL, 0); + fclose(f); + } + for (uint32_t *sid = SubsystemIds; *sid; sid++) { + if (*sid == SubsystemId) { + FileName = cString::sprintf("/dev/dvb/adapter%d/osd0", Adapter); + int fd = open(FileName, O_RDWR); + if (fd != -1) { //TODO treat the second path of the S2-6400 as a budget device + close(fd); + dsyslog("creating cDvbHdFfDevice"); + new cDvbHdFfDevice(Adapter, Frontend); + return true; + } + } + } + return false; +} diff --git a/PLUGINS/src/dvbhddevice/dvbhdffdevice.h b/PLUGINS/src/dvbhddevice/dvbhdffdevice.h new file mode 100644 index 0000000..4dcfb6a --- /dev/null +++ b/PLUGINS/src/dvbhddevice/dvbhdffdevice.h @@ -0,0 +1,123 @@ +/* + * dvbhdffdevice.h: The DVB HD Full Featured device interface + * + * See the README file for copyright information and how to reach the author. + * + * $Id: dvbhdffdevice.h 1.6 2010/03/13 11:18:13 kls Exp $ + */ + +#ifndef __DVBHDFFDEVICE_H +#define __DVBHDFFDEVICE_H + +#include "hdffcmd.h" +#include "vdr/dvbdevice.h" +#include "vdr/dvbspu.h" + +/// The cDvbHdFfDevice implements a DVB device which can be accessed through the Linux DVB driver API. + +class cDvbHdFfDevice : public cDvbDevice { +private: + int fd_osd, fd_audio, fd_video; +protected: + virtual void MakePrimaryDevice(bool On); +public: + static bool Probe(int Adapter, int Frontend); + cDvbHdFfDevice(int Adapter, int Frontend); + virtual ~cDvbHdFfDevice(); + virtual bool HasDecoder(void) const; + +// SPU facilities + +private: + cDvbSpuDecoder *spuDecoder; +public: + virtual cSpuDecoder *GetSpuDecoder(void); + +// Channel facilities + +private: + void TurnOffLiveMode(bool LiveView); +protected: + virtual bool SetChannelDevice(const cChannel *Channel, bool LiveView); + +// PID handle facilities + +protected: + virtual bool SetPid(cPidHandle *Handle, int Type, bool On); + +// Image Grab facilities + +public: + virtual uchar *GrabImage(int &Size, bool Jpeg = true, int Quality = -1, int SizeX = -1, int SizeY = -1); + +// Video format facilities + +public: + virtual void SetVideoDisplayFormat(eVideoDisplayFormat VideoDisplayFormat); + virtual void SetVideoFormat(bool VideoFormat16_9); + virtual eVideoSystem GetVideoSystem(void); + virtual void GetVideoSize(int &Width, int &Height, double &VideoAspect); + virtual void GetOsdSize(int &Width, int &Height, double &PixelAspect); + +// Track facilities + +protected: + virtual void SetAudioTrackDevice(eTrackType Type); + +// Audio facilities + +private: + int audioChannel; +protected: + virtual int GetAudioChannelDevice(void); + virtual void SetAudioChannelDevice(int AudioChannel); + virtual void SetVolumeDevice(int Volume); + virtual void SetDigitalAudioDevice(bool On); + +// Player facilities + +private: + int playVideoPid; + int playAudioPid; + + // Pes2Ts conversion stuff + uint8_t videoCounter; + uint8_t audioCounter; + void BuildTsPacket(uint8_t * TsBuffer, bool PusiSet, uint16_t Pid, uint8_t Counter, const uint8_t * Data, uint32_t Length); + uint32_t PesToTs(uint8_t * TsBuffer, uint16_t Pid, uint8_t & Counter, const uint8_t * Data, uint32_t Length); + +protected: + ePlayMode playMode; + virtual bool CanReplay(void) const; + virtual bool SetPlayMode(ePlayMode PlayMode); + virtual int PlayVideo(const uchar *Data, int Length); + virtual int PlayAudio(const uchar *Data, int Length, uchar Id); + virtual int PlayTsVideo(const uchar *Data, int Length); + virtual int PlayTsAudio(const uchar *Data, int Length); +public: + virtual int64_t GetSTC(void); + virtual void TrickSpeed(int Speed); + virtual void Clear(void); + virtual void Play(void); + virtual void Freeze(void); + virtual void Mute(void); + virtual void StillPicture(const uchar *Data, int Length); + virtual bool Poll(cPoller &Poller, int TimeoutMs = 0); + virtual bool Flush(int TimeoutMs = 0); + +// HDFF specific things + +public: + static HDFF::cHdffCmdIf *GetHdffCmdHandler(void); +private: + static int devHdffOffset;//TODO + bool isHdffPrimary;//TODO implicit! + HDFF::cHdffCmdIf *mHdffCmdIf; +}; + +class cDvbHdFfDeviceProbe : public cDvbDeviceProbe { +public: + virtual bool Probe(int Adapter, int Frontend); + }; + +#endif //__DVBHDFFDEVICE_H diff --git a/PLUGINS/src/dvbhddevice/hdffcmd.c b/PLUGINS/src/dvbhddevice/hdffcmd.c new file mode 100644 index 0000000..ecd26ed --- /dev/null +++ b/PLUGINS/src/dvbhddevice/hdffcmd.c @@ -0,0 +1,1120 @@ +/* + * hdffcmd.c: TODO(short description) + * + * See the README file for copyright information and how to reach the author. + * + * $Id: hdffcmd.c 1.19 2011/04/17 11:20:22 kls Exp $ + */ + +#include "hdffcmd.h" +#include <linux/dvb/osd.h> +#include <stdio.h> +#include <string.h> +#include <sys/ioctl.h> +#include <vdr/tools.h> + +namespace HDFF +{ + +cHdffCmdIf::cHdffCmdIf(int OsdDev) +{ + mOsdDev = OsdDev; + if (mOsdDev < 0) + { + //printf("ERROR: invalid OSD device handle (%d)!\n", mOsdDev); + } +} + +cHdffCmdIf::~cHdffCmdIf(void) +{ +} + +void cHdffCmdIf::CmdBuildHeader(cBitBuffer & MsgBuf, eMessageType MsgType, eMessageGroup MsgGroup, eMessageId MsgId) +{ + MsgBuf.SetBits(16, 0); // length field will be set later + MsgBuf.SetBits(6, 0); // reserved + MsgBuf.SetBits(2, MsgType); + MsgBuf.SetBits(8, MsgGroup); + MsgBuf.SetBits(16, MsgId); +} + +uint32_t cHdffCmdIf::CmdSetLength(cBitBuffer & MsgBuf) +{ + uint32_t length; + + length = MsgBuf.GetByteLength() - 2; + MsgBuf.SetDataByte(0, (uint8_t) (length >> 8)); + MsgBuf.SetDataByte(1, (uint8_t) length); + + return length + 2; +} + + +uint32_t cHdffCmdIf::CmdGetFirmwareVersion(char * pString, uint32_t MaxLength) +{ + cBitBuffer cmdBuf(MAX_CMD_LEN); + cBitBuffer resBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + osd_cmd.result_data = resBuf.GetData(); + osd_cmd.result_len = resBuf.GetMaxLength(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupGeneric, msgGenGetFirmwareVersion); + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); + if (osd_cmd.result_len > 0) + { + uint8_t * result = resBuf.GetData(); + uint8_t textLength = result[9]; + if (textLength >= MaxLength) + textLength = MaxLength - 1; + memcpy(pString, &result[10], textLength); + pString[textLength] = 0; + return (result[6] << 16) | (result[7] << 8) | result[8]; + } + return 0; +} + +uint32_t cHdffCmdIf::CmdGetInterfaceVersion(char * pString, uint32_t MaxLength) +{ + cBitBuffer cmdBuf(MAX_CMD_LEN); + cBitBuffer resBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + osd_cmd.result_data = resBuf.GetData(); + osd_cmd.result_len = resBuf.GetMaxLength(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupGeneric, msgGenGetInterfaceVersion); + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); + if (osd_cmd.result_len > 0) + { + uint8_t * result = resBuf.GetData(); + uint8_t textLength = result[9]; + if (textLength >= MaxLength) + textLength = MaxLength - 1; + memcpy(pString, &result[10], textLength); + pString[textLength] = 0; + return (result[6] << 16) | (result[7] << 8) | result[8]; + } + return 0; +} + +uint32_t cHdffCmdIf::CmdGetCopyrights(uint8_t Index, char * pString, uint32_t MaxLength) +{ + cBitBuffer cmdBuf(MAX_CMD_LEN); + cBitBuffer resBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + osd_cmd.result_data = resBuf.GetData(); + osd_cmd.result_len = resBuf.GetMaxLength(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupGeneric, msgGenGetCopyrights); + cmdBuf.SetBits(8, Index); + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); + if (osd_cmd.result_len > 0) + { + uint8_t * result = resBuf.GetData(); + uint8_t index = result[6]; + uint8_t textLen = result[7]; + if (index == Index && textLen > 0) + { + if (textLen >= MaxLength) + { + textLen = MaxLength - 1; + } + memcpy(pString, result + 8, textLen); + pString[textLen] = 0; + return textLen; + } + } + return 0; +} + + +void cHdffCmdIf::CmdAvSetPlayMode(uint8_t PlayMode, bool Realtime) +{ + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvDec, msgAvSetPlayMode); + cmdBuf.SetBits(1, Realtime ? 1 : 0); + cmdBuf.SetBits(7, PlayMode); + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +void cHdffCmdIf::CmdAvSetVideoPid(uint8_t DecoderIndex, uint16_t VideoPid, eVideoStreamType StreamType, bool PlaybackMode) +{ + //printf("SetVideoPid %d %d\n", VideoPid, StreamType); + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvDec, msgAvSetVideoPid); + cmdBuf.SetBits(4, DecoderIndex); + cmdBuf.SetBits(4, StreamType); + cmdBuf.SetBits(1, PlaybackMode ? 1 : 0); + cmdBuf.SetBits(15, VideoPid); + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +void cHdffCmdIf::CmdAvSetAudioPid(uint8_t DecoderIndex, uint16_t AudioPid, eAudioStreamType StreamType, eAVContainerType ContainerType) +{ + //printf("SetAudioPid %d %d %d\n", AudioPid, StreamType, ContainerType); + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvDec, msgAvSetAudioPid); + cmdBuf.SetBits(4, DecoderIndex); + cmdBuf.SetBits(4, StreamType); + cmdBuf.SetBits(2, 0); // reserved + cmdBuf.SetBits(1, ContainerType); + cmdBuf.SetBits(13, AudioPid); + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +void cHdffCmdIf::CmdAvSetPcrPid(uint8_t DecoderIndex, uint16_t PcrPid) +{ + //printf("SetPcrPid %d\n", PcrPid); + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvDec, msgAvSetPcrPid); + cmdBuf.SetBits(4, DecoderIndex); + cmdBuf.SetBits(4, 0); // reserved + cmdBuf.SetBits(16, PcrPid); + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +void cHdffCmdIf::CmdAvSetTeletextPid(uint8_t DecoderIndex, uint16_t TeletextPid) +{ + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvDec, msgAvSetTeletextPid); + cmdBuf.SetBits(4, DecoderIndex); + cmdBuf.SetBits(4, 0); // reserved + cmdBuf.SetBits(16, TeletextPid); + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +void cHdffCmdIf::CmdAvSetVideoWindow(uint8_t DecoderIndex, bool Enable, uint16_t X, uint16_t Y, uint16_t Width, uint16_t Height) +{ + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvDec, msgAvSetVideoWindow); + cmdBuf.SetBits(4, DecoderIndex); + cmdBuf.SetBits(3, 0); // reserved + if (Enable) + cmdBuf.SetBits(1, 1); + else + cmdBuf.SetBits(1, 0); + cmdBuf.SetBits(16, X); + cmdBuf.SetBits(16, Y); + cmdBuf.SetBits(16, Width); + cmdBuf.SetBits(16, Height); + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +void cHdffCmdIf::CmdAvShowStillImage(uint8_t DecoderIndex, const uint8_t * pStillImage, int Size, eVideoStreamType StreamType) +{ + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + osd_raw_data_t osd_data; + + memset(&osd_data, 0, sizeof(osd_raw_data_t)); + osd_data.data_buffer = (void *) pStillImage; + osd_data.data_length = Size; + ioctl(mOsdDev, OSD_RAW_DATA, &osd_data); + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvDec, msgAvShowStillImage); + cmdBuf.SetBits(4, DecoderIndex); + cmdBuf.SetBits(4, StreamType); + cmdBuf.SetBits(16, osd_data.data_handle); + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +void cHdffCmdIf::CmdAvSetDecoderInput(uint8_t DecoderIndex, uint8_t DemultiplexerIndex) +{ + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvDec, msgAvSetDecoderInput); + cmdBuf.SetBits(4, DecoderIndex); + cmdBuf.SetBits(4, DemultiplexerIndex); + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +void cHdffCmdIf::CmdAvSetDemultiplexerInput(uint8_t DemultiplexerIndex, uint8_t TsInputIndex) +{ + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvDec, msgAvSetDemultiplexerInput); + cmdBuf.SetBits(4, DemultiplexerIndex); + cmdBuf.SetBits(4, TsInputIndex); + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +void cHdffCmdIf::CmdAvSetVideoFormat(uint8_t DecoderIndex, const tVideoFormat * pVideoFormat) +{ + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvDec, msgAvSetVideoFormat); + cmdBuf.SetBits(4, DecoderIndex); + if (pVideoFormat->AutomaticEnabled) + { + cmdBuf.SetBits(1, 1); + } + else + { + cmdBuf.SetBits(1, 0); + } + if (pVideoFormat->AfdEnabled) + { + cmdBuf.SetBits(1, 1); + } + else + { + cmdBuf.SetBits(1, 0); + } + cmdBuf.SetBits(2, pVideoFormat->TvFormat); + cmdBuf.SetBits(8, pVideoFormat->VideoConversion); + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +void cHdffCmdIf::CmdAvSetVideoOutputMode(uint8_t DecoderIndex, eVideoOutputMode OutputMode) +{ + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvDec, msgAvSetVideoOutputMode); + cmdBuf.SetBits(8, OutputMode); + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +void cHdffCmdIf::CmdAvSetStc(uint8_t DecoderIndex, uint64_t Stc) +{ + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvDec, msgAvSetStc); + cmdBuf.SetBits(4, DecoderIndex); + cmdBuf.SetBits(3, 0); // reserved + cmdBuf.SetBits(1, (uint32_t) (Stc >> 32)); + cmdBuf.SetBits(32, (uint32_t) Stc); + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +void cHdffCmdIf::CmdAvFlushBuffer(uint8_t DecoderIndex, bool FlushAudio, bool FlushVideo) +{ + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvDec, msgAvFlushBuffer); + cmdBuf.SetBits(4, DecoderIndex); + if (FlushAudio) + { + cmdBuf.SetBits(1, 1); + } + else + { + cmdBuf.SetBits(1, 0); + } + if (FlushVideo) + { + cmdBuf.SetBits(1, 1); + } + else + { + cmdBuf.SetBits(1, 0); + } + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +void cHdffCmdIf::CmdAvEnableSync(uint8_t DecoderIndex, bool EnableSync) +{ + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvDec, msgAvEnableSync); + cmdBuf.SetBits(4, DecoderIndex); + if (EnableSync) + { + cmdBuf.SetBits(1, 1); + cmdBuf.SetBits(1, 1); + } + else + { + cmdBuf.SetBits(1, 0); + cmdBuf.SetBits(1, 0); + } + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +void cHdffCmdIf::CmdAvSetVideoSpeed(uint8_t DecoderIndex, int32_t Speed) +{ + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvDec, msgAvSetVideoSpeed); + cmdBuf.SetBits(4, DecoderIndex); + cmdBuf.SetBits(4, 0); + cmdBuf.SetBits(32, Speed); + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +void cHdffCmdIf::CmdAvSetAudioSpeed(uint8_t DecoderIndex, int32_t Speed) +{ + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvDec, msgAvSetAudioSpeed); + cmdBuf.SetBits(4, DecoderIndex); + cmdBuf.SetBits(4, 0); + cmdBuf.SetBits(32, Speed); + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +void cHdffCmdIf::CmdAvEnableVideoAfterStop(uint8_t DecoderIndex, bool EnableVideoAfterStop) +{ + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvDec, msgAvEnableVideoAfterStop); + cmdBuf.SetBits(4, DecoderIndex); + if (EnableVideoAfterStop) + { + cmdBuf.SetBits(1, 1); + } + else + { + cmdBuf.SetBits(1, 0); + } + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +void cHdffCmdIf::CmdAvSetAudioDelay(int16_t Delay) +{ + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvDec, msgAvSetAudioDelay); + cmdBuf.SetBits(16, Delay); + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +void cHdffCmdIf::CmdAvSetAudioDownmix(eDownmixMode DownmixMode) +{ + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvDec, msgAvSetAudioDownmix); + cmdBuf.SetBits(8, DownmixMode); + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +void cHdffCmdIf::CmdAvSetAudioChannel(uint8_t AudioChannel) +{ + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvDec, msgAvSetAudioChannel); + cmdBuf.SetBits(8, AudioChannel); + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + + +void cHdffCmdIf::CmdOsdConfigure(const tOsdConfig * pConfig) +{ + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdConfigure); + if (pConfig->FontAntialiasing) + { + cmdBuf.SetBits(1, 1); + } + else + { + cmdBuf.SetBits(1, 0); + } + if (pConfig->FontKerning) + { + cmdBuf.SetBits(1, 1); + } + else + { + cmdBuf.SetBits(1, 0); + } + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +void cHdffCmdIf::CmdOsdReset(void) +{ + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdReset); + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +uint32_t cHdffCmdIf::CmdOsdCreateDisplay(uint32_t Width, uint32_t Height, eColorType ColorType) +{ + //printf("CreateDisplay %d %d %d\n", Width, Height, ColorType); + cBitBuffer cmdBuf(MAX_CMD_LEN); + cBitBuffer resBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + osd_cmd.result_data = resBuf.GetData(); + osd_cmd.result_len = resBuf.GetMaxLength(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdCreateDisplay); + cmdBuf.SetBits(16, Width); + cmdBuf.SetBits(16, Height); + cmdBuf.SetBits(8, ColorType); + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); + if (osd_cmd.result_len > 0) + { + uint8_t * result = resBuf.GetData(); + return (result[6] << 24) | (result[7] << 16) | (result[8] << 8) | result[9]; + } + return InvalidHandle; +} + +void cHdffCmdIf::CmdOsdDeleteDisplay(uint32_t hDisplay) +{ + //printf("DeleteDisplay\n"); + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdDeleteDisplay); + cmdBuf.SetBits(32, hDisplay); + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +void cHdffCmdIf::CmdOsdEnableDisplay(uint32_t hDisplay, bool Enable) +{ + //printf("EnableDisplay\n"); + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdEnableDisplay); + cmdBuf.SetBits(32, hDisplay); + if (Enable) + { + cmdBuf.SetBits(1, 1); + } + else + { + cmdBuf.SetBits(1, 0); + } + cmdBuf.SetBits(7, 0); // reserved + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +void cHdffCmdIf::CmdOsdSetDisplayOutputRectangle(uint32_t hDisplay, uint32_t X, uint32_t Y, uint32_t Width, uint32_t Height) +{ + //printf("SetOutputRect %d %d %d %d %d\n", hDisplay, X, Y, Width, Height); + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdSetDisplayOutputRectangle); + cmdBuf.SetBits(32, hDisplay); + cmdBuf.SetBits(16, X); + cmdBuf.SetBits(16, Y); + cmdBuf.SetBits(16, Width); + cmdBuf.SetBits(16, Height); + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +void cHdffCmdIf::CmdOsdSetDisplayClippingArea(uint32_t hDisplay, bool Enable, uint32_t X, uint32_t Y, uint32_t Width, uint32_t Height) +{ + //printf("SetClippingArea %d %d %d %d %d %d\n", hDisplay, Enable, X, Y, Width, Height); + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdSetDisplayClippingArea); + cmdBuf.SetBits(32, hDisplay); + if (Enable) + { + cmdBuf.SetBits(1, 1); + } + else + { + cmdBuf.SetBits(1, 0); + } + cmdBuf.SetBits(7, 0); // reserved + cmdBuf.SetBits(16, X); + cmdBuf.SetBits(16, Y); + cmdBuf.SetBits(16, Width); + cmdBuf.SetBits(16, Height); + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +void cHdffCmdIf::CmdOsdRenderDisplay(uint32_t hDisplay) +{ + //printf("Render\n"); + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdRenderDisplay); + cmdBuf.SetBits(32, hDisplay); + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +uint32_t cHdffCmdIf::CmdOsdCreatePalette(eColorType ColorType, eColorFormat ColorFormat, + uint32_t NumColors, const uint32_t * pColors) +{ + cBitBuffer cmdBuf(MAX_CMD_LEN); + cBitBuffer resBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + uint32_t i; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + osd_cmd.result_data = resBuf.GetData(); + osd_cmd.result_len = resBuf.GetMaxLength(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdCreatePalette); + cmdBuf.SetBits(8, ColorType); + cmdBuf.SetBits(8, ColorFormat); + if (NumColors > 256) + NumColors = 256; + cmdBuf.SetBits(8, NumColors == 256 ? 0 : NumColors); + for (i = 0; i < NumColors; i++) + { + cmdBuf.SetBits(32, pColors[i]); + } + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); + if (osd_cmd.result_len > 0) + { + uint8_t * result = resBuf.GetData(); + return (result[6] << 24) | (result[7] << 16) | (result[8] << 8) | result[9]; + } + return InvalidHandle; +} + +void cHdffCmdIf::CmdOsdDeletePalette(uint32_t hPalette) +{ + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdDeletePalette); + cmdBuf.SetBits(32, hPalette); + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +void cHdffCmdIf::CmdOsdSetDisplayPalette(uint32_t hDisplay, uint32_t hPalette) +{ + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdSetDisplayPalette); + cmdBuf.SetBits(32, hDisplay); + cmdBuf.SetBits(32, hPalette); + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +void cHdffCmdIf::CmdOsdSetPaletteColors(uint32_t hPalette, eColorFormat ColorFormat, + uint8_t StartColor, uint32_t NumColors, const uint32_t * pColors) +{ + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + uint32_t i; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdSetPaletteColors); + cmdBuf.SetBits(32, hPalette); + cmdBuf.SetBits(8, ColorFormat); + cmdBuf.SetBits(8, StartColor); + if (NumColors > 256) + NumColors = 256; + cmdBuf.SetBits(8, NumColors == 256 ? 0 : NumColors); + for (i = 0; i < NumColors; i++) + { + cmdBuf.SetBits(32, pColors[i]); + } + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +uint32_t cHdffCmdIf::CmdOsdCreateFontFace(const uint8_t * pFontData, uint32_t DataSize) +{ + //printf("CreateFontFace %d\n", DataSize); + cBitBuffer cmdBuf(MAX_CMD_LEN); + cBitBuffer resBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + osd_raw_data_t osd_data; + + memset(&osd_data, 0, sizeof(osd_raw_data_t)); + osd_data.data_buffer = pFontData; + osd_data.data_length = DataSize; + ioctl(mOsdDev, OSD_RAW_DATA, &osd_data); + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + osd_cmd.result_data = resBuf.GetData(); + osd_cmd.result_len = resBuf.GetMaxLength(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdCreateFontFace); + cmdBuf.SetBits(16, osd_data.data_handle); + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); + if (osd_cmd.result_len > 0) + { + uint8_t * result = resBuf.GetData(); + return (result[6] << 24) | (result[7] << 16) | (result[8] << 8) | result[9]; + } + return InvalidHandle; +} + +void cHdffCmdIf::CmdOsdDeleteFontFace(uint32_t hFontFace) +{ + //printf("DeleteFontFace %08X\n", hFontFace); + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdDeleteFontFace); + cmdBuf.SetBits(32, hFontFace); + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +uint32_t cHdffCmdIf::CmdOsdCreateFont(uint32_t hFontFace, uint32_t Size) +{ + //printf("CreateFont %d\n", Size); + cBitBuffer cmdBuf(MAX_CMD_LEN); + cBitBuffer resBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + osd_cmd.result_data = resBuf.GetData(); + osd_cmd.result_len = resBuf.GetMaxLength(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdCreateFont); + cmdBuf.SetBits(32, hFontFace); + cmdBuf.SetBits(32, Size); + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); + if (osd_cmd.result_len > 0) + { + uint8_t * result = resBuf.GetData(); + return (result[6] << 24) | (result[7] << 16) | (result[8] << 8) | result[9]; + } + return InvalidHandle; +} + +void cHdffCmdIf::CmdOsdDeleteFont(uint32_t hFont) +{ + //printf("DeleteFont %08X\n", hFont); + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdDeleteFont); + cmdBuf.SetBits(32, hFont); + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +void cHdffCmdIf::CmdOsdDrawRectangle(uint32_t hDisplay, int X, int Y, int Width, int Height, uint32_t Color) +{ + //printf("Rect (%d,%d) %d x %d, %08X\n", X, Y, Width, Height, Color); + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdDrawRectangle); + cmdBuf.SetBits(32, hDisplay); + cmdBuf.SetBits(16, X); + cmdBuf.SetBits(16, Y); + cmdBuf.SetBits(16, Width); + cmdBuf.SetBits(16, Height); + cmdBuf.SetBits(32, Color); + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +void cHdffCmdIf::CmdOsdDrawEllipse(uint32_t hDisplay, int CX, int CY, int RadiusX, int RadiusY, + uint32_t Color, uint32_t Flags) +{ + //printf("Ellipse (%d,%d) %d x %d, %08X, %d\n", CX, CY, RadiusX, RadiusY, Color, Flags); + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdDrawEllipse); + cmdBuf.SetBits(32, hDisplay); + cmdBuf.SetBits(16, CX); + cmdBuf.SetBits(16, CY); + cmdBuf.SetBits(16, RadiusX); + cmdBuf.SetBits(16, RadiusY); + cmdBuf.SetBits(32, Color); + cmdBuf.SetBits(32, Flags); + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +void cHdffCmdIf::CmdOsdDrawText(uint32_t hDisplay, uint32_t hFont, int X, int Y, const char * pText, uint32_t Color) +{ + //printf("Text %08X (%d,%d), %s, %08X\n", hFont, X, Y, pText, Color); + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + int i; + int length; + + length = 0; + while (pText[length]) + { + length++; + } + if (length > 980) + length = 980; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdDrawText); + cmdBuf.SetBits(32, hDisplay); + cmdBuf.SetBits(32, hFont); + cmdBuf.SetBits(16, X); + cmdBuf.SetBits(16, Y); + cmdBuf.SetBits(32, Color); + cmdBuf.SetBits(16, length); + for (i = 0; i < length; i++) + { + cmdBuf.SetBits(8, pText[i]); + } + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +void cHdffCmdIf::CmdOsdDrawTextW(uint32_t hDisplay, uint32_t hFont, int X, int Y, const uint16_t * pText, uint32_t Color) +{ + //printf("TextW %08X (%d,%d), %08X\n", hFont, X, Y, Color); + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + int i; + int length; + + length = 0; + while (pText[length]) + { + length++; + } + if (length > 480) + length = 480; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdDrawTextW); + cmdBuf.SetBits(32, hDisplay); + cmdBuf.SetBits(32, hFont); + cmdBuf.SetBits(16, X); + cmdBuf.SetBits(16, Y); + cmdBuf.SetBits(32, Color); + cmdBuf.SetBits(16, length); + for (i = 0; i < length; i++) + { + cmdBuf.SetBits(16, pText[i]); + } + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +void cHdffCmdIf::CmdOsdDrawBitmap(uint32_t hDisplay, int X, int Y, const uint8_t * pBitmap, + int BmpWidth, int BmpHeight, int BmpSize, + eColorType ColorType, uint32_t hPalette) +{ + //printf("Bitmap (%d,%d) %d x %d\n", X, Y, BmpWidth, BmpHeight); + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + osd_raw_data_t osd_data; + + memset(&osd_data, 0, sizeof(osd_raw_data_t)); + osd_data.data_buffer = pBitmap; + osd_data.data_length = BmpSize; + ioctl(mOsdDev, OSD_RAW_DATA, &osd_data); + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdDrawBitmap); + cmdBuf.SetBits(32, hDisplay); + cmdBuf.SetBits(16, X); + cmdBuf.SetBits(16, Y); + cmdBuf.SetBits(16, BmpWidth); + cmdBuf.SetBits(16, BmpHeight); + cmdBuf.SetBits(8, ColorType); + cmdBuf.SetBits(6, 0); // reserved + cmdBuf.SetBits(2, 0); // uncompressed + cmdBuf.SetBits(32, hPalette); + cmdBuf.SetBits(16, osd_data.data_handle); + cmdBuf.SetBits(32, 0); + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +void cHdffCmdIf::CmdOsdSaveRegion(uint32_t hDisplay, int X, int Y, int Width, int Height) +{ + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdSaveRegion); + cmdBuf.SetBits(32, hDisplay); + cmdBuf.SetBits(16, X); + cmdBuf.SetBits(16, Y); + cmdBuf.SetBits(16, Width); + cmdBuf.SetBits(16, Height); + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +void cHdffCmdIf::CmdOsdRestoreRegion(uint32_t hDisplay) +{ + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupOsd, msgOsdRestoreRegion); + cmdBuf.SetBits(32, hDisplay); + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +void cHdffCmdIf::CmdMuxSetVideoOut(eVideoOut VideoOut) +{ + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvMux, msgMuxSetVideoOut); + cmdBuf.SetBits(4, VideoOut); + cmdBuf.SetBits(4, 0); // reserved + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +void cHdffCmdIf::CmdMuxSetVolume(uint8_t Volume) +{ + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvMux, msgMuxSetVolume); + cmdBuf.SetBits(8, Volume); + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +void cHdffCmdIf::CmdMuxMuteAudio(bool Mute) +{ + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupAvMux, msgMuxSetAudioMute); + cmdBuf.SetBits(1, Mute); + cmdBuf.SetBits(7, 0); // reserved + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +void cHdffCmdIf::CmdHdmiSetVideoMode(eHdmiVideoMode VideoMode) +{ + //printf("HdmiSetVideoMode %d\n", VideoMode); + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupHdmi, msgHdmiSetVideoMode); + cmdBuf.SetBits(8, VideoMode); + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +void cHdffCmdIf::CmdHdmiConfigure(const tHdmiConfig * pConfig) +{ + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupHdmi, msgHdmiConfigure); + if (pConfig->TransmitAudio) + { + cmdBuf.SetBits(1, 1); + } + else + { + cmdBuf.SetBits(1, 0); + } + if (pConfig->ForceDviMode) + { + cmdBuf.SetBits(1, 1); + } + else + { + cmdBuf.SetBits(1, 0); + } + if (pConfig->CecEnabled) + { + cmdBuf.SetBits(1, 1); + } + else + { + cmdBuf.SetBits(1, 0); + } + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +void cHdffCmdIf::CmdHdmiSendCecCommand(eCecCommand Command) +{ + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupHdmi, msgHdmiSendCecCommand); + cmdBuf.SetBits(8, Command); + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +void cHdffCmdIf::CmdRemoteSetProtocol(eRemoteProtocol Protocol) +{ + //printf("%s %d\n", __func__, Protocol); + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupRemoteControl, msgRemoteSetProtocol); + cmdBuf.SetBits(8, Protocol); + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +void cHdffCmdIf::CmdRemoteSetAddressFilter(bool Enable, uint32_t Address) +{ + //printf("%s %d %d\n", __func__, Enable, Address); + cBitBuffer cmdBuf(MAX_CMD_LEN); + osd_raw_cmd_t osd_cmd; + + memset(&osd_cmd, 0, sizeof(osd_raw_cmd_t)); + osd_cmd.cmd_data = cmdBuf.GetData(); + CmdBuildHeader(cmdBuf, msgTypeCommand, msgGroupRemoteControl, msgRemoteSetAddressFilter); + cmdBuf.SetBits(1, Enable); + cmdBuf.SetBits(7, 0); // reserved + cmdBuf.SetBits(32, Address); + osd_cmd.cmd_len = CmdSetLength(cmdBuf); + ioctl(mOsdDev, OSD_RAW_CMD, &osd_cmd); +} + +} // end of namespace diff --git a/PLUGINS/src/dvbhddevice/hdffcmd.h b/PLUGINS/src/dvbhddevice/hdffcmd.h new file mode 100644 index 0000000..cd641eb --- /dev/null +++ b/PLUGINS/src/dvbhddevice/hdffcmd.h @@ -0,0 +1,102 @@ +/* + * hdffcmd.h: TODO(short description) + * + * See the README file for copyright information and how to reach the author. + * + * $Id: hdffcmd.h 1.17 2011/04/17 11:20:22 kls Exp $ + */ + +#ifndef _HDFF_CMD_H_ +#define _HDFF_CMD_H_ + +#include "bitbuffer.h" +#include "hdffmsgdef.h" + +namespace HDFF +{ + +class cHdffCmdIf +{ +private: + int mOsdDev; + + void CmdBuildHeader(cBitBuffer & MsgBuf, eMessageType MsgType, eMessageGroup MsgGroup, eMessageId MsgId); + uint32_t CmdSetLength(cBitBuffer & MsgBuf); + +public: + cHdffCmdIf(int OsdDev); + ~cHdffCmdIf(void); + + uint32_t CmdGetFirmwareVersion(char * pString, uint32_t MaxLength); + uint32_t CmdGetInterfaceVersion(char * pString, uint32_t MaxLength); + uint32_t CmdGetCopyrights(uint8_t Index, char * pString, uint32_t MaxLength); + + void CmdAvSetPlayMode(uint8_t PlayMode, bool Realtime); + void CmdAvSetVideoPid(uint8_t DecoderIndex, uint16_t VideoPid, eVideoStreamType StreamType, bool PlaybackMode = false); + void CmdAvSetAudioPid(uint8_t DecoderIndex, uint16_t AudioPid, eAudioStreamType StreamType, eAVContainerType ContainerType = avContainerPes); + void CmdAvSetPcrPid(uint8_t DecoderIndex, uint16_t PcrPid); + void CmdAvSetTeletextPid(uint8_t DecoderIndex, uint16_t TeletextPid); + void CmdAvSetVideoWindow(uint8_t DecoderIndex, bool Enable, uint16_t X, uint16_t Y, uint16_t Width, uint16_t Height); + void CmdAvShowStillImage(uint8_t DecoderIndex, const uint8_t * pStillImage, int Size, eVideoStreamType StreamType); + void CmdAvSetDecoderInput(uint8_t DecoderIndex, uint8_t DemultiplexerIndex); + void CmdAvSetDemultiplexerInput(uint8_t DemultiplexerIndex, uint8_t TsInputIndex); + void CmdAvSetVideoFormat(uint8_t DecoderIndex, const tVideoFormat * pVideoFormat); + void CmdAvSetVideoOutputMode(uint8_t DecoderIndex, eVideoOutputMode OutputMode); + void CmdAvSetStc(uint8_t DecoderIndex, uint64_t Stc); + void CmdAvFlushBuffer(uint8_t DecoderIndex, bool FlushAudio, bool FlushVideo); + void CmdAvEnableSync(uint8_t DecoderIndex, bool EnableSync); + void CmdAvSetVideoSpeed(uint8_t DecoderIndex, int32_t Speed); + void CmdAvSetAudioSpeed(uint8_t DecoderIndex, int32_t Speed); + void CmdAvEnableVideoAfterStop(uint8_t DecoderIndex, bool EnableVideoAfterStop); + void CmdAvSetAudioDelay(int16_t Delay); + void CmdAvSetAudioDownmix(eDownmixMode DownmixMode); + void CmdAvSetAudioChannel(uint8_t AudioChannel); + + void CmdOsdConfigure(const tOsdConfig * pConfig); + void CmdOsdReset(void); + + uint32_t CmdOsdCreateDisplay(uint32_t Width, uint32_t Height, eColorType ColorType); + void CmdOsdDeleteDisplay(uint32_t hDisplay); + void CmdOsdEnableDisplay(uint32_t hDisplay, bool Enable); + void CmdOsdSetDisplayOutputRectangle(uint32_t hDisplay, uint32_t X, uint32_t Y, uint32_t Width, uint32_t Height); + void CmdOsdSetDisplayClippingArea(uint32_t hDisplay, bool Enable, uint32_t X, uint32_t Y, uint32_t Width, uint32_t Height); + void CmdOsdRenderDisplay(uint32_t hDisplay); + + uint32_t CmdOsdCreatePalette(eColorType ColorType, eColorFormat ColorFormat, + uint32_t NumColors, const uint32_t * pColors); + void CmdOsdDeletePalette(uint32_t hPalette); + void CmdOsdSetDisplayPalette(uint32_t hDisplay, uint32_t hPalette); + void CmdOsdSetPaletteColors(uint32_t hPalette, eColorFormat ColorFormat, + uint8_t StartColor, uint32_t NumColors, const uint32_t * pColors); + + uint32_t CmdOsdCreateFontFace(const uint8_t * pFontData, uint32_t DataSize); + void CmdOsdDeleteFontFace(uint32_t hFontFace); + uint32_t CmdOsdCreateFont(uint32_t hFontFace, uint32_t Size); + void CmdOsdDeleteFont(uint32_t hFont); + + void CmdOsdDrawRectangle(uint32_t hDisplay, int X, int Y, int Width, int Height, uint32_t Color); + void CmdOsdDrawEllipse(uint32_t hDisplay, int CX, int CY, int RadiusX, int RadiusY, + uint32_t Color, uint32_t Flags); + void CmdOsdDrawText(uint32_t hDisplay, uint32_t hFont, int X, int Y, const char * pText, uint32_t Color); + void CmdOsdDrawTextW(uint32_t hDisplay, uint32_t hFont, int X, int Y, const uint16_t * pText, uint32_t Color); + void CmdOsdDrawBitmap(uint32_t hDisplay, int X, int Y, const uint8_t * pBitmap, + int BmpWidth, int BmpHeight, int BmpSize, + eColorType ColorType, uint32_t hPalette); + void CmdOsdSaveRegion(uint32_t hDisplay, int X, int Y, int Width, int Height); + void CmdOsdRestoreRegion(uint32_t hDisplay); + + void CmdMuxSetVideoOut(eVideoOut VideoOut); + void CmdMuxSetVolume(uint8_t Volume); + void CmdMuxMuteAudio(bool Mute); + + void CmdHdmiSetVideoMode(eHdmiVideoMode VideoMode); + void CmdHdmiConfigure(const tHdmiConfig * pConfig); + void CmdHdmiSendCecCommand(eCecCommand Command); + + void CmdRemoteSetProtocol(eRemoteProtocol Protocol); + void CmdRemoteSetAddressFilter(bool Enable, uint32_t Address); +}; + +} // end of namespace + +#endif diff --git a/PLUGINS/src/dvbhddevice/hdffmsgdef.h b/PLUGINS/src/dvbhddevice/hdffmsgdef.h new file mode 100644 index 0000000..a6c3f4b --- /dev/null +++ b/PLUGINS/src/dvbhddevice/hdffmsgdef.h @@ -0,0 +1,304 @@ +/* + * hdffmsgdef.h: TODO(short description) + * + * See the README file for copyright information and how to reach the author. + * + * $Id: hdffmsgdef.h 1.12 2011/04/17 11:20:22 kls Exp $ + */ + +#ifndef _HDFF_MSGDEF_H_ +#define _HDFF_MSGDEF_H_ + +#define MAX_CMD_LEN 1536 + +namespace HDFF +{ + +typedef enum _eMessageType +{ + msgTypeCommand, + msgTypeAnswer, + msgTypeResult, + msgTypeEvent +} eMessageType; + +typedef enum _eMessageGroup +{ + msgGroupGeneric, + msgGroupAvDec, + msgGroupAvMux, + msgGroupFrontend, + msgGroupOsd, + msgGroupHdmi, + msgGroupRemoteControl +} eMessageGroup; + +typedef enum _eMessageId +{ + msgGenGetFirmwareVersion = 0, + msgGenGetInterfaceVersion, + msgGenGetCopyrights, + + msgAvSetAudioPid = 0, + msgAvSetVideoPid, + msgAvSetPcrPid, + msgAvSetTeletextPid, + msgAvShowStillImage, + msgAvSetVideoWindow, + msgAvSetDecoderInput, + msgAvSetDemultiplexerInput, + msgAvSetVideoFormat, + msgAvSetVideoOutputMode, + msgAvSetStc, + msgAvFlushBuffer, + msgAvEnableSync, + msgAvSetVideoSpeed, + msgAvSetAudioSpeed, + msgAvEnableVideoAfterStop, + msgAvGetVideoFormatInfo, + msgAvSetAudioDelay, + msgAvSetAudioDownmix, + msgAvSetAudioChannel, + msgAvSetPlayMode, + + msgMuxSetVideoOut = 0, + msgMuxSetSlowBlank, + msgMuxSetFastBlank, + msgMuxSetVolume, + msgMuxSetAudioMute, + + msgOsdConfigure = 0, + msgOsdReset, + msgOsdCreateDisplay = 10, + msgOsdDeleteDisplay, + msgOsdEnableDisplay, + msgOsdSetDisplayOutputRectangle, + msgOsdSetDisplayClippingArea, + msgOsdRenderDisplay, + msgOsdSaveRegion, + msgOsdRestoreRegion, + msgOsdCreatePalette = 30, + msgOsdDeletePalette, + msgOsdSetDisplayPalette, + msgOsdSetPaletteColors, + msgOsdCreateFontFace = 50, + msgOsdDeleteFontFace, + msgOsdCreateFont, + msgOsdDeleteFont, + msgOsdDrawPixel = 70, + msgOsdDrawRectangle, + msgOsdDrawCircle, + msgOsdDrawEllipse, + msgOsdDrawSlope, + msgOsdDrawText, + msgOsdDrawTextW, + msgOsdDrawBitmap, + + msgHdmiEnableOutput = 0, + msgHdmiSetVideoMode, + msgHdmiConfigure, + msgHdmiIsDisplayConnected, + msgHdmiGetDisplayInfo, + msgHdmiGetVideoMode, + msgHdmiSendCecCommand, + + msgRemoteSetProtocol = 0, + msgRemoteSetAddressFilter, + msgRemoteKeyEvent +} eMessageId; + + +// AvDec definitions + +typedef enum _eAVContainerType +{ + avContainerPes, + avContainerPesDvd, + avContainerMaxValue +} eAVContainerType; + +typedef enum _eAudioStreamType +{ + audioStreamMpeg1, + audioStreamMpeg2, + audioStreamAc3, + audioStreamAac, + audioStreamHeAac, + audioStreamPcm, + audioStreamEAc3, + audioStreamDts, + audioStreamMaxValue +} eAudioStreamType; + +typedef enum _eVideoStreamType +{ + videoStreamMpeg1, + videoStreamMpeg2, + videoStreamH264, + videoStreamMpeg4Asp, + videoStreamVc1, + videoStreamMaxValue +} eVideoStreamType; + + +typedef enum _eTvFormat +{ + tvFormat4by3, + tvFormat16by9, + tvFormatMaxValue +} eTvFormat; + +typedef enum _eVideoConversion +{ + videoConversionAutomatic, + videoConversionLetterbox16by9, + videoConversionLetterbox14by9, + videoConversionPillarbox, + videoConversionCentreCutOut, + videoConversionAlways16by9, + videoConversionMaxValue +} eVideoConversion; + +typedef struct _tVideoFormat +{ + bool AutomaticEnabled; + bool AfdEnabled; + eTvFormat TvFormat; + eVideoConversion VideoConversion; +} tVideoFormat; + +typedef enum _eVideoOutputMode +{ + videoOutputClone, + videoOutputDualView, + videoOutputMaxValue +} eVideoOutputMode; + +typedef enum _eDownmixMode +{ + downmixOff, + downmixAnalog, + downmixAlways, + downmixAutomatic, + downmixHdmi +} eDownmixMode; + +// AvMux definitions + +typedef enum _eVideoOut +{ + videoOutDisabled, + videoOutRgb, + videoOutCvbsYuv, + videoOutYc, + videoOutMaxValue +} eVideoOut; + +typedef enum _eSlowBlank +{ + slowBlankOff, + slowBlank16by9, + slowBlank4by3, + slowBlankMaxValue +} eSlowBlank; + +typedef enum _eFastBlank +{ + fastBlankCvbs, + fastBlankRgb, + fastBlankMaxValue +} eFastBlank; + + +// OSD definitions + +#define InvalidHandle 0xFFFFFFFF +#define ScreenDisplayHandle 0xFFFFFFFE + +#define PositionScreenCentered 0xFFFF + +#define SizeFullScreen 0xFFFF +#define SizeSameAsSource 0xFFFE + +#define FontFaceTiresias 0x00000000 + +typedef enum _eColorType +{ + colorTypeClut1, + colorTypeClut2, + colorTypeClut4, + colorTypeClut8, + colorTypeARGB8888, + colorTypeARGB8565, + colorTypeARGB4444, + colorTypeARGB1555, +} eColorType; + +typedef enum _eColorFormat +{ + colorFormatARGB, + colorFormatACbYCr, +} eColorFormat; + +typedef enum _eDrawingFlags +{ + drawFull, + drawHalfTop, + drawHalfLeft, + drawHalfBottom, + drawHalfRight, + drawQuarterTopLeft, + drawQuarterTopRight, + drawQuarterBottomLeft, + drawQuarterBottomRight, + drawQuarterTopLeftInverted, + drawQuarterTopRightInverted, + drawQuarterBottomLeftInverted, + drawQuarterBottomRightInverted +} eDrawingFlags; + +typedef struct _tOsdConfig +{ + bool FontAntialiasing; + bool FontKerning; +} tOsdConfig; + +// HDMI definitions + +typedef enum _eHdmiVideoMode +{ + videoMode576p50 = 18, + videoMode720p50 = 19, + videoMode1080i50 = 20, + videoMode576i50 = 22, + videoModeMaxValue +} eHdmiVideoMode; + +typedef enum _eCecCommand +{ + cecCommandTvOn, + cecCommandTvOff, + cecCommandActiveSource, + cecCommandInactiveSource +} eCecCommand; + +typedef struct _tHdmiConfig +{ + bool TransmitAudio; + bool ForceDviMode; + bool CecEnabled; +} tHdmiConfig; + +// Remote control definitions + +typedef enum _eRemoteProtocol +{ + remoteProtocolNone, + remoteProtocolRc5, + remoteProtocolRc6, + remoteProtocolMaxValue +} eRemoteProtocol; + +} // end of namespace + +#endif diff --git a/PLUGINS/src/dvbhddevice/hdffosd.c b/PLUGINS/src/dvbhddevice/hdffosd.c new file mode 100644 index 0000000..254f2af --- /dev/null +++ b/PLUGINS/src/dvbhddevice/hdffosd.c @@ -0,0 +1,755 @@ +/* + * hdffosd.c: Implementation of the DVB HD Full Featured On Screen Display + * + * See the README file for copyright information and how to reach the author. + * + * $Id: hdffosd.c 1.9 2011/04/17 11:20:22 kls Exp $ + */ + +#include "hdffosd.h" +#include <linux/dvb/osd.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include "hdffcmd.h" +#include "setup.h" + +#define MAX_NUM_FONTFACES 8 +#define MAX_NUM_FONTS 8 +#define MAX_BITMAP_SIZE (1024*1024) + +typedef struct _tFontFace +{ + cString Name; + uint32_t Handle; +} tFontFace; + +typedef struct _tFont +{ + uint32_t hFontFace; + int Size; + uint32_t Handle; +} tFont; + +class cHdffOsd : public cOsd +{ +private: + HDFF::cHdffCmdIf * mHdffCmdIf; + int mLeft; + int mTop; + int mDispWidth; + int mDispHeight; + bool shown; + bool mChanged; + bool mBitmapModified; + uint32_t mDisplay; + tFontFace mFontFaces[MAX_NUM_FONTFACES]; + tFont mFonts[MAX_NUM_FONTS]; + uint32_t mBitmapPalette; + uint32_t mBitmapColors[256]; + uint32_t mBitmapNumColors; + +protected: + virtual void SetActive(bool On); +public: + cHdffOsd(int Left, int Top, HDFF::cHdffCmdIf * pHdffCmdIf, uint Level); + virtual ~cHdffOsd(); + cBitmap *GetBitmap(int Area); + virtual eOsdError CanHandleAreas(const tArea *Areas, int NumAreas); + virtual eOsdError SetAreas(const tArea *Areas, int NumAreas); + virtual void SaveRegion(int x1, int y1, int x2, int y2); + virtual void RestoreRegion(void); + virtual void DrawPixel(int x, int y, tColor Color); + virtual void DrawBitmap(int x, int y, const cBitmap &Bitmap, tColor ColorFg = 0, tColor ColorBg = 0, bool ReplacePalette = false, bool Overlay = false); + virtual void DrawText(int x, int y, const char *s, tColor ColorFg, tColor ColorBg, const cFont *Font, int Width = 0, int Height = 0, int Alignment = taDefault); + virtual void DrawRectangle(int x1, int y1, int x2, int y2, tColor Color); + virtual void DrawEllipse(int x1, int y1, int x2, int y2, tColor Color, int Quadrants = 0); + virtual void DrawSlope(int x1, int y1, int x2, int y2, tColor Color, int Type); + virtual void Flush(void); +}; + +cHdffOsd::cHdffOsd(int Left, int Top, HDFF::cHdffCmdIf * pHdffCmdIf, uint Level) +: cOsd(Left, Top, Level) +{ + double pixelAspect; + HDFF::tOsdConfig config; + + //printf("cHdffOsd %d, %d, %d\n", Left, Top, Level); + mHdffCmdIf = pHdffCmdIf; + mLeft = Left; + mTop = Top; + shown = false; + mChanged = false; + mBitmapModified = false; + mBitmapPalette = InvalidHandle; + config.FontKerning = false; + config.FontAntialiasing = Setup.AntiAlias ? true : false; + mHdffCmdIf->CmdOsdConfigure(&config); + + gHdffSetup.GetOsdSize(mDispWidth, mDispHeight, pixelAspect); + mDisplay = mHdffCmdIf->CmdOsdCreateDisplay(mDispWidth, mDispHeight, HDFF::colorTypeARGB8888); + mHdffCmdIf->CmdOsdSetDisplayOutputRectangle(mDisplay, 0, 0, SizeFullScreen, SizeFullScreen); + for (int i = 0; i < MAX_NUM_FONTFACES; i++) + { + mFontFaces[i].Name = ""; + mFontFaces[i].Handle = InvalidHandle; + } + for (int i = 0; i < MAX_NUM_FONTS; i++) + { + mFonts[i].hFontFace = InvalidHandle; + mFonts[i].Size = 0; + mFonts[i].Handle = InvalidHandle; + } +} + +cHdffOsd::~cHdffOsd() +{ + //printf("~cHdffOsd %d %d\n", mLeft, mTop); + SetActive(false); + + for (int i = 0; i < MAX_NUM_FONTS; i++) + { + if (mFonts[i].Handle == InvalidHandle) + break; + mHdffCmdIf->CmdOsdDeleteFont(mFonts[i].Handle); + } + for (int i = 0; i < MAX_NUM_FONTFACES; i++) + { + if (mFontFaces[i].Handle == InvalidHandle) + break; + mHdffCmdIf->CmdOsdDeleteFontFace(mFontFaces[i].Handle); + } + + if (mBitmapPalette != InvalidHandle) + mHdffCmdIf->CmdOsdDeletePalette(mBitmapPalette); + mHdffCmdIf->CmdOsdDrawRectangle(mDisplay, 0, 0, mDispWidth, mDispHeight, 0); + mHdffCmdIf->CmdOsdRenderDisplay(mDisplay); + mHdffCmdIf->CmdOsdDeleteDisplay(mDisplay); +} + +cBitmap * cHdffOsd::GetBitmap(int Area) +{ + //printf("GetBitmap %d\n", Area); + mChanged = true; + mBitmapModified = true; + return cOsd::GetBitmap(Area); +} + +eOsdError cHdffOsd::CanHandleAreas(const tArea *Areas, int NumAreas) +{ + eOsdError Result = cOsd::CanHandleAreas(Areas, NumAreas); + if (Result == oeOk) + { + for (int i = 0; i < NumAreas; i++) + { + if (Areas[i].bpp != 1 && Areas[i].bpp != 2 && Areas[i].bpp != 4 && Areas[i].bpp != 8) + return oeBppNotSupported; + } + } + return Result; +} + +eOsdError cHdffOsd::SetAreas(const tArea *Areas, int NumAreas) +{ + for (int i = 0; i < NumAreas; i++) + { + //printf("SetAreas %d: %d %d %d %d %d\n", i, Areas[i].x1, Areas[i].y1, Areas[i].x2, Areas[i].y2, Areas[i].bpp); + } + mHdffCmdIf->CmdOsdDrawRectangle(mDisplay, 0, 0, mDispWidth, mDispHeight, 0); + mHdffCmdIf->CmdOsdRenderDisplay(mDisplay); + return cOsd::SetAreas(Areas, NumAreas); +} + +void cHdffOsd::SetActive(bool On) +{ + if (On != Active()) + { + cOsd::SetActive(On); + if (On) + { + } + else if (shown) + { + shown = false; + } + } +} + +void cHdffOsd::SaveRegion(int x1, int y1, int x2, int y2) +{ + mHdffCmdIf->CmdOsdSaveRegion(mDisplay, mLeft + x1, mTop + y1, x2 - x1 + 1, y2 - y1 + 1); + mChanged = true; + mBitmapModified = false; +} + +void cHdffOsd::RestoreRegion(void) +{ + mHdffCmdIf->CmdOsdRestoreRegion(mDisplay); + mChanged = true; + mBitmapModified = false; +} + +void cHdffOsd::DrawPixel(int x, int y, tColor Color) +{ + //printf("DrawPixel\n"); + mBitmapModified = false; +} + +void cHdffOsd::DrawBitmap(int x, int y, const cBitmap &Bitmap, tColor ColorFg, tColor ColorBg, bool ReplacePalette, bool Overlay) +{ + //printf("DrawBitmap %d %d %d\n", x, y, Overlay); + int i; + int numColors; + const tColor * colors = Bitmap.Colors(numColors); + + for (i = 0; i < numColors; i++) + { + mBitmapColors[i] = colors[i]; + if (ColorFg || ColorBg) + { + if (i == 0) + mBitmapColors[i] = ColorBg; + else if (i == 1) + mBitmapColors[i] = ColorFg; + } + } + if (mBitmapPalette == InvalidHandle) + { + mBitmapPalette = mHdffCmdIf->CmdOsdCreatePalette(HDFF::colorTypeClut8, + HDFF::colorFormatARGB, numColors, mBitmapColors); + } + else + { + mHdffCmdIf->CmdOsdSetPaletteColors(mBitmapPalette, + HDFF::colorFormatARGB, 0, numColors, mBitmapColors); + } + mHdffCmdIf->CmdOsdDrawBitmap(mDisplay, mLeft + x, mTop + y, + (uint8_t *) Bitmap.Data(0, 0), Bitmap.Width(), Bitmap.Height(), + Bitmap.Width() * Bitmap.Height(), HDFF::colorTypeClut8, mBitmapPalette); +#if 0 + uint32_t * tmpBitmap = new uint32_t[Bitmap.Width() * Bitmap.Height()]; + for (int ix = 0; ix < Bitmap.Width(); ix++) + { + for (int iy = 0; iy < Bitmap.Height(); iy++) + { + const tIndex * pixel = Bitmap.Data(ix, iy); + tColor color = Bitmap.Color(*pixel); + if (!Overlay || *pixel != 0) + { + if (ColorFg || ColorBg) + { + if (*pixel == 0) + color = ColorBg; + else if (*pixel == 1) + color = ColorFg; + } + tmpBitmap[Bitmap.Width() * iy + ix] = color; + } + } + } + mHdffCmdIf->CmdOsdDrawBitmap(mDisplay, mLeft + x, mTop + y, + (uint8_t *) tmpBitmap, Bitmap.Width(), Bitmap.Height(), + Bitmap.Width() * Bitmap.Height() * 4, HDFF::colorTypeARGB8888, InvalidHandle); + delete[] tmpBitmap; +#endif + mChanged = true; + mBitmapModified = false; +} + +void cHdffOsd::DrawText(int x, int y, const char *s, tColor ColorFg, tColor ColorBg, const cFont *Font, int Width, int Height, int Alignment) +{ + int w = Font->Width(s); + int h = Font->Height(); + int limit = 0; + int cw = Width ? Width : w; + int ch = Height ? Height : h; + int i; + int size = Font->Size(); + tFontFace * pFontFace; + tFont * pFont; + + if (ColorBg != clrTransparent) + mHdffCmdIf->CmdOsdDrawRectangle(mDisplay, mLeft + x, mTop + y, cw, ch, ColorBg); + + if (s == NULL) + return; + + pFontFace = NULL; + for (i = 0; i < MAX_NUM_FONTFACES; i++) + { + if (mFontFaces[i].Handle == InvalidHandle) + break; + + if (strcmp(mFontFaces[i].Name, Font->FontName()) == 0) + { + pFontFace = &mFontFaces[i]; + break; + } + } + if (pFontFace == NULL) + { + if (i < MAX_NUM_FONTFACES) + { + cString fontFileName = Font->FontName(); + FILE * fp = fopen(fontFileName, "rb"); + if (fp) + { + fseek(fp, 0, SEEK_END); + long fileSize = ftell(fp); + fseek(fp, 0, SEEK_SET); + if (fileSize > 0) + { + uint8_t * buffer = new uint8_t[fileSize]; + if (buffer) + { + if (fread(buffer, fileSize, 1, fp) == 1) + { + mFontFaces[i].Handle = mHdffCmdIf->CmdOsdCreateFontFace(buffer, fileSize); + if (mFontFaces[i].Handle != InvalidHandle) + { + mFontFaces[i].Name = Font->FontName(); + pFontFace = &mFontFaces[i]; + } + } + delete[] buffer; + } + } + fclose(fp); + } + } + } + if (pFontFace == NULL) + return; + + pFont = NULL; + for (i = 0; i < MAX_NUM_FONTS; i++) + { + if (mFonts[i].Handle == InvalidHandle) + break; + + if (mFonts[i].hFontFace == pFontFace->Handle + && mFonts[i].Size == size) + { + pFont = &mFonts[i]; + break; + } + } + if (pFont == NULL) + { + if (i < MAX_NUM_FONTS) + { + mFonts[i].Handle = mHdffCmdIf->CmdOsdCreateFont(pFontFace->Handle, size); + if (mFonts[i].Handle != InvalidHandle) + { + mFonts[i].hFontFace = pFontFace->Handle; + mFonts[i].Size = size; + pFont = &mFonts[i]; + } + } + } + if (pFont == NULL) + return; + + mHdffCmdIf->CmdOsdSetDisplayClippingArea(mDisplay, true, mLeft + x, mTop + y, cw, ch); + + if (Width || Height) + { + limit = x + cw;// - mLeft; + if (Width) + { + if ((Alignment & taLeft) != 0) + ; + else if ((Alignment & taRight) != 0) + { + if (w < Width) + x += Width - w; + } + else + { // taCentered + if (w < Width) + x += (Width - w) / 2; + } + } + if (Height) + { + if ((Alignment & taTop) != 0) + ; + else if ((Alignment & taBottom) != 0) + { + if (h < Height) + y += Height - h; + } + else + { // taCentered + if (h < Height) + y += (Height - h) / 2; + } + } + } + //x -= mLeft; + //y -= mTop; + { + uint16_t tmp[1000]; + uint16_t len = 0; + while (*s && (len < (sizeof(tmp) - 1))) + { + int sl = Utf8CharLen(s); + uint sym = Utf8CharGet(s, sl); + s += sl; + tmp[len] = sym; + len++; + } + tmp[len] = 0; + mHdffCmdIf->CmdOsdDrawTextW(mDisplay, pFont->Handle, x + mLeft, y + mTop + h, tmp, ColorFg); + } + //mHdffCmdIf->CmdOsdDrawText(mDisplay, pFont->Handle, x + mLeft, y + mTop + h - 7, s, ColorFg); + mHdffCmdIf->CmdOsdSetDisplayClippingArea(mDisplay, false, 0, 0, 0, 0); + //Font->DrawText(this, x, y, s, ColorFg, ColorBg, limit); + mChanged = true; + mBitmapModified = false; +} + +void cHdffOsd::DrawRectangle(int x1, int y1, int x2, int y2, tColor Color) +{ + mHdffCmdIf->CmdOsdDrawRectangle(mDisplay, mLeft + x1, mTop + y1, x2 - x1 + 1, y2 - y1 + 1, Color); + mChanged = true; + mBitmapModified = false; +} + +void cHdffOsd::DrawEllipse(int x1, int y1, int x2, int y2, tColor Color, int Quadrants) +{ + uint32_t flags; + int cx; + int cy; + int rx; + int ry; + + switch (abs(Quadrants)) + { + case 1: + if (Quadrants > 0) + flags = HDFF::drawQuarterTopRight; + else + flags = HDFF::drawQuarterTopRightInverted; + cx = x1; + cy = y2; + rx = x2 - x1; + ry = y2 - y1; + break; + case 2: + if (Quadrants > 0) + flags = HDFF::drawQuarterTopLeft; + else + flags = HDFF::drawQuarterTopLeftInverted; + cx = x2; + cy = y2; + rx = x2 - x1; + ry = y2 - y1; + break; + case 3: + if (Quadrants > 0) + flags = HDFF::drawQuarterBottomLeft; + else + flags = HDFF::drawQuarterBottomLeftInverted; + cx = x2; + cy = y1; + rx = x2 - x1; + ry = y2 - y1; + break; + case 4: + if (Quadrants > 0) + flags = HDFF::drawQuarterBottomRight; + else + flags = HDFF::drawQuarterBottomRightInverted; + cx = x1; + cy = y1; + rx = x2 - x1; + ry = y2 - y1; + break; + case 5: + flags = HDFF::drawHalfRight; + cx = x1; + cy = (y1 + y2) / 2; + rx = x2 - x1; + ry = (y2 - y1) / 2; + break; + case 6: + flags = HDFF::drawHalfTop; + cx = (x1 + x2) / 2; + cy = y2; + rx = (x2 - x1) / 2; + ry = y2 - y1; + break; + case 7: + flags = HDFF::drawHalfLeft; + cx = x2; + cy = (y1 + y2) / 2; + rx = x2 - x1; + ry = (y2 - y1) / 2; + break; + case 8: + flags = HDFF::drawHalfBottom; + cx = (x1 + x2) / 2; + cy = y1; + rx = (x2 - x1) / 2; + ry = y2 - y1; + break; + default: + flags = HDFF::drawFull; + cx = (x1 + x2) / 2; + cy = (y1 + y2) / 2; + rx = (x2 - x1) / 2; + ry = (y2 - y1) / 2; + break; + } + mHdffCmdIf->CmdOsdDrawEllipse(mDisplay, mLeft + cx, mTop + cy, rx, ry, Color, flags); + mChanged = true; + mBitmapModified = false; +} + +void cHdffOsd::DrawSlope(int x1, int y1, int x2, int y2, tColor Color, int Type) +{ + //printf("DrawSlope\n"); + mChanged = true; + mBitmapModified = false; +} + +void cHdffOsd::Flush(void) +{ + if (!Active()) + return; + + if (!mChanged) + return; + + //printf("Flush\n"); + if (mBitmapModified) + { + cBitmap *Bitmap; + for (int i = 0; (Bitmap = GetBitmap(i)) != NULL; i++) + { + DrawBitmap(0, 0, *Bitmap); + } + } + + mHdffCmdIf->CmdOsdRenderDisplay(mDisplay); + + mChanged = false; + mBitmapModified = false; +} + + +class cHdffOsdRaw : public cOsd +{ +private: + HDFF::cHdffCmdIf * mHdffCmdIf; + int mDispWidth; + int mDispHeight; + bool shown; + uint32_t mDisplay; + uint32_t mBitmapPalette; + uint32_t mBitmapColors[256]; + uint32_t mBitmapNumColors; + +protected: + virtual void SetActive(bool On); +public: + cHdffOsdRaw(int Left, int Top, HDFF::cHdffCmdIf * pHdffCmdIf, uint Level); + virtual ~cHdffOsdRaw(); + virtual eOsdError CanHandleAreas(const tArea *Areas, int NumAreas); + virtual eOsdError SetAreas(const tArea *Areas, int NumAreas); + virtual void Flush(void); +}; + +cHdffOsdRaw::cHdffOsdRaw(int Left, int Top, HDFF::cHdffCmdIf * pHdffCmdIf, uint Level) +: cOsd(Left, Top, Level) +{ + double pixelAspect; + + //printf("cHdffOsdRaw %d, %d, %d\n", Left, Top, Level); + mHdffCmdIf = pHdffCmdIf; + shown = false; + mBitmapPalette = InvalidHandle; + + gHdffSetup.GetOsdSize(mDispWidth, mDispHeight, pixelAspect); + mDisplay = mHdffCmdIf->CmdOsdCreateDisplay(mDispWidth, mDispHeight, HDFF::colorTypeARGB8888); + mHdffCmdIf->CmdOsdSetDisplayOutputRectangle(mDisplay, 0, 0, SizeFullScreen, SizeFullScreen); +} + +cHdffOsdRaw::~cHdffOsdRaw() +{ + //printf("~cHdffOsdRaw %d %d\n", Left(), Top()); + SetActive(false); + + if (mBitmapPalette != InvalidHandle) + mHdffCmdIf->CmdOsdDeletePalette(mBitmapPalette); + mHdffCmdIf->CmdOsdDrawRectangle(mDisplay, 0, 0, mDispWidth, mDispHeight, 0); + mHdffCmdIf->CmdOsdRenderDisplay(mDisplay); + mHdffCmdIf->CmdOsdDeleteDisplay(mDisplay); +} + +void cHdffOsdRaw::SetActive(bool On) +{ + if (On != Active()) + { + cOsd::SetActive(On); + if (On) + { + } + else if (shown) + { + shown = false; + } + } +} + +eOsdError cHdffOsdRaw::CanHandleAreas(const tArea *Areas, int NumAreas) +{ + eOsdError Result = cOsd::CanHandleAreas(Areas, NumAreas); + if (Result == oeOk) + { + for (int i = 0; i < NumAreas; i++) + { + if (Areas[i].bpp != 1 && Areas[i].bpp != 2 && Areas[i].bpp != 4 && Areas[i].bpp != 8 + && (Areas[i].bpp != 32 || !gHdffSetup.TrueColorOsd)) + return oeBppNotSupported; + } + } + return Result; +} + +eOsdError cHdffOsdRaw::SetAreas(const tArea *Areas, int NumAreas) +{ + for (int i = 0; i < NumAreas; i++) + { + //printf("SetAreas %d: %d %d %d %d %d\n", i, Areas[i].x1, Areas[i].y1, Areas[i].x2, Areas[i].y2, Areas[i].bpp); + } + mHdffCmdIf->CmdOsdDrawRectangle(mDisplay, 0, 0, mDispWidth, mDispHeight, 0); + mHdffCmdIf->CmdOsdRenderDisplay(mDisplay); + return cOsd::SetAreas(Areas, NumAreas); +} + +void cHdffOsdRaw::Flush(void) +{ + if (!Active()) + return; + //struct timeval start; + //struct timeval end; + //struct timezone timeZone; + //gettimeofday(&start, &timeZone); + + bool render = false; + if (IsTrueColor()) + { + LOCK_PIXMAPS; + while (cPixmapMemory *pm = RenderPixmaps()) + { + int w = pm->ViewPort().Width(); + int h = pm->ViewPort().Height(); + int d = w * sizeof(tColor); + int Chunk = MAX_BITMAP_SIZE / w / sizeof(tColor); + if (Chunk > h) + Chunk = h; + for (int y = 0; y < h; y += Chunk) + { + int hc = Chunk; + if (y + hc > h) + hc = h - y; + mHdffCmdIf->CmdOsdDrawBitmap(mDisplay, + Left() + pm->ViewPort().X(), Top() + pm->ViewPort().Y() + y, + pm->Data() + y * d, w, hc, hc * d, + HDFF::colorTypeARGB8888, InvalidHandle); + } + delete pm; + render = true; + } + } + else + { + uint8_t * buffer = new uint8_t[MAX_BITMAP_SIZE]; + if (!buffer) + return; + cBitmap * bitmap; + for (int i = 0; (bitmap = GetBitmap(i)) != NULL; i++) + { + int x1 = 0, y1 = 0, x2 = 0, y2 = 0; + if (!shown || bitmap->Dirty(x1, y1, x2, y2)) + { + if (!shown) + { + x2 = bitmap->Width() - 1; + y2 = bitmap->Height() - 1; + } + // commit colors: + int numColors; + const tColor * colors = bitmap->Colors(numColors); + if (colors) + { + for (int c = 0; c < numColors; c++) + mBitmapColors[c] = colors[c]; + if (mBitmapPalette == InvalidHandle) + { + mBitmapPalette = mHdffCmdIf->CmdOsdCreatePalette(HDFF::colorTypeClut8, + HDFF::colorFormatARGB, numColors, mBitmapColors); + } + else + { + mHdffCmdIf->CmdOsdSetPaletteColors(mBitmapPalette, + HDFF::colorFormatARGB, 0, numColors, mBitmapColors); + } + } + // commit modified data: + int width = x2 - x1 + 1; + int height = y2 - y1 + 1; + int chunk = MAX_BITMAP_SIZE / width; + if (chunk > height) + chunk = height; + for (int y = 0; y < height; y += chunk) + { + int hc = chunk; + if (y + hc > height) + hc = height - y; + for (int r = 0; r < hc; r++) + memcpy(buffer + r * width, bitmap->Data(x1, y1 + y + r), width); + mHdffCmdIf->CmdOsdDrawBitmap(mDisplay, + Left() + bitmap->X0() + x1, Top() + bitmap->Y0() + y1 + y, + buffer, width, hc, hc * width, + HDFF::colorTypeClut8, mBitmapPalette); + } + render = true; + } + bitmap->Clean(); + } + delete[] buffer; + } + if (render) + { + mHdffCmdIf->CmdOsdRenderDisplay(mDisplay); + //gettimeofday(&end, &timeZone); + //int timeNeeded = end.tv_usec - start.tv_usec; + //timeNeeded += (end.tv_sec - start.tv_sec) * 1000000; + //printf("time = %d\n", timeNeeded); + } + shown = true; +} + + + + +cHdffOsdProvider::cHdffOsdProvider(HDFF::cHdffCmdIf * HdffCmdIf) +{ + mHdffCmdIf = HdffCmdIf; +} + +cOsd *cHdffOsdProvider::CreateOsd(int Left, int Top, uint Level) +{ + //printf("CreateOsd %d %d %d\n", Left, Top, Level); + if (gHdffSetup.HighLevelOsd) + return new cHdffOsd(Left, Top, mHdffCmdIf, Level); + else + return new cHdffOsdRaw(Left, Top, mHdffCmdIf, Level); +} + +bool cHdffOsdProvider::ProvidesTrueColor(void) +{ + return gHdffSetup.TrueColorOsd && !gHdffSetup.HighLevelOsd; +} diff --git a/PLUGINS/src/dvbhddevice/hdffosd.h b/PLUGINS/src/dvbhddevice/hdffosd.h new file mode 100644 index 0000000..533897e --- /dev/null +++ b/PLUGINS/src/dvbhddevice/hdffosd.h @@ -0,0 +1,26 @@ +/* + * hdffosd.h: Implementation of the DVB HD Full Featured On Screen Display + * + * See the README file for copyright information and how to reach the author. + * + * $Id: hdffosd.h 1.2 2011/01/30 15:27:48 kls Exp $ + */ + +#ifndef _HDFF_OSD_H_ +#define _HDFF_OSD_H_ + +#include <vdr/osd.h> + +#include "hdffcmd.h" + +class cHdffOsdProvider : public cOsdProvider +{ +private: + HDFF::cHdffCmdIf * mHdffCmdIf; +public: + cHdffOsdProvider(HDFF::cHdffCmdIf * pHdffCmdIf); + virtual cOsd *CreateOsd(int Left, int Top, uint Level); + virtual bool ProvidesTrueColor(void); +}; + +#endif diff --git a/PLUGINS/src/dvbhddevice/setup.c b/PLUGINS/src/dvbhddevice/setup.c new file mode 100644 index 0000000..3cb69b1 --- /dev/null +++ b/PLUGINS/src/dvbhddevice/setup.c @@ -0,0 +1,252 @@ +/* + * setup.c: Setup for the DVB HD Full Featured On Screen Display + * + * See the README file for copyright information and how to reach the author. + * + * $Id: setup.c 1.11 2011/04/17 11:45:17 kls Exp $ + */ + +#include "setup.h" +#include "hdffcmd.h" + +const int kResolutions = 4; +const int kTvFormats = 2; +const int kVideoConversions = 6; +const int kAnalogueVideos = 4; +const int kAudioDownmixes = 5; +const int kOsdSizes = 5; +const int kRemoteProtocols = 3; + +const int kResolution1080i = 0; +const int kResolution720p = 1; +const int kResolution576p = 2; +const int kResolution576i = 3; + +static const char * ResolutionItems[] = +{ + "1080i", + "720p", + "576p", + "576i", + NULL +}; + +static const char * TvFormatItems[] = +{ + "4/3", + "16/9", + NULL +}; + +static const char * VideoConversionItems[] = +{ + "Automatic", + "Letterbox 16/9", + "Letterbox 14/9", + "Pillarbox", + "CentreCutOut", + "Always 16/9", + NULL +}; + +static const char * AnalogueVideoItems[] = +{ + "Disabled", + "RGB", + "CVBS + YUV", + "YC (S-Video)", + NULL +}; + +static const char * AudioDownmixItems[] = +{ + "Disabled", + "Analogue only", + "Always", + "Automatic", + "HDMI only", + NULL +}; + +static const char * OsdSizeItems[] = +{ + "Follow resolution", + "1920x1080", + "1280x720", + "1024x576", + "720x576", + NULL +}; + +static const char * RemoteProtocolItems[] = +{ + "none", + "RC5", + "RC6", + NULL +}; + +cHdffSetup gHdffSetup; + +cHdffSetup::cHdffSetup(void) +{ + Resolution = kResolution1080i; + TvFormat = HDFF::tvFormat16by9; + VideoConversion = HDFF::videoConversionPillarbox; + AnalogueVideo = HDFF::videoOutCvbsYuv; + AudioDelay = 0; + AudioDownmix = HDFF::downmixAutomatic; + OsdSize = 0; + CecEnabled = 1; + RemoteProtocol = 1; + RemoteAddress = -1; + HighLevelOsd = 1; + TrueColorOsd = 1; +} + +bool cHdffSetup::SetupParse(const char *Name, const char *Value) +{ + if (strcmp(Name, "Resolution") == 0) Resolution = atoi(Value); + else if (strcmp(Name, "TvFormat") == 0) TvFormat = atoi(Value); + else if (strcmp(Name, "VideoConversion") == 0) VideoConversion = atoi(Value); + else if (strcmp(Name, "AnalogueVideo") == 0) AnalogueVideo = atoi(Value); + else if (strcmp(Name, "AudioDelay") == 0) AudioDelay = atoi(Value); + else if (strcmp(Name, "AudioDownmix") == 0) AudioDownmix = atoi(Value); + else if (strcmp(Name, "OsdSize") == 0) OsdSize = atoi(Value); + else if (strcmp(Name, "CecEnabled") == 0) CecEnabled = atoi(Value); + else if (strcmp(Name, "RemoteProtocol") == 0) RemoteProtocol = atoi(Value); + else if (strcmp(Name, "RemoteAddress") == 0) RemoteAddress = atoi(Value); + else if (strcmp(Name, "HighLevelOsd") == 0) HighLevelOsd = atoi(Value); + else if (strcmp(Name, "TrueColorOsd") == 0) TrueColorOsd = atoi(Value); + else return false; + return true; +} + +void cHdffSetup::GetOsdSize(int &Width, int &Height, double &PixelAspect) +{ + if (OsdSize == 0) { + if (Resolution == kResolution1080i) { + Width = 1920; + Height = 1080; + } + else if (Resolution == kResolution720p) { + Width = 1280; + Height = 720; + } + else { + Width = 720; + Height = 576; + } + if (TvFormat == HDFF::tvFormat16by9) + PixelAspect = 16.0 / 9.0; + else + PixelAspect = 4.0 / 3.0; + } + else if (OsdSize == 1) { + Width = 1920; + Height = 1080; + PixelAspect = 16.0 / 9.0; + } + else if (OsdSize == 2) { + Width = 1280; + Height = 720; + PixelAspect = 16.0 / 9.0; + } + else if (OsdSize == 3) { + Width = 1024; + Height = 576; + PixelAspect = 16.0 / 9.0; + } + else { + Width = 720; + Height = 576; + PixelAspect = 4.0 / 3.0; + } + PixelAspect /= double(Width) / Height; +} + +HDFF::eHdmiVideoMode cHdffSetup::GetVideoMode(void) +{ + switch (Resolution) + { + case kResolution1080i: + default: + return HDFF::videoMode1080i50; + case kResolution720p: + return HDFF::videoMode720p50; + case kResolution576p: + return HDFF::videoMode576p50; + case kResolution576i: + return HDFF::videoMode576i50; + } +} + +cHdffSetupPage::cHdffSetupPage(HDFF::cHdffCmdIf * pHdffCmdIf) +{ + mHdffCmdIf = pHdffCmdIf; + mNewHdffSetup = gHdffSetup; + + Add(new cMenuEditStraItem("Resolution", &mNewHdffSetup.Resolution, kResolutions, ResolutionItems)); + Add(new cMenuEditStraItem("TV format", &mNewHdffSetup.TvFormat, kTvFormats, TvFormatItems)); + Add(new cMenuEditStraItem("Video Conversion", &mNewHdffSetup.VideoConversion, kVideoConversions, VideoConversionItems)); + Add(new cMenuEditStraItem("Analogue Video", &mNewHdffSetup.AnalogueVideo, kAnalogueVideos, AnalogueVideoItems)); + Add(new cMenuEditIntItem("Audio Delay (ms)", &mNewHdffSetup.AudioDelay, 0, 500)); + Add(new cMenuEditStraItem("Audio Downmix", &mNewHdffSetup.AudioDownmix, kAudioDownmixes, AudioDownmixItems)); + Add(new cMenuEditStraItem("Osd Size", &mNewHdffSetup.OsdSize, kOsdSizes, OsdSizeItems)); + Add(new cMenuEditBoolItem("HDMI CEC", &mNewHdffSetup.CecEnabled)); + Add(new cMenuEditStraItem("Remote Control Protocol", &mNewHdffSetup.RemoteProtocol, kRemoteProtocols, RemoteProtocolItems)); + Add(new cMenuEditIntItem("Remote Control Address", &mNewHdffSetup.RemoteAddress, -1, 31)); + Add(new cMenuEditBoolItem("High Level OSD", &mNewHdffSetup.HighLevelOsd)); + Add(new cMenuEditBoolItem("Allow True Color OSD", &mNewHdffSetup.TrueColorOsd)); +} + +cHdffSetupPage::~cHdffSetupPage(void) +{ +} + +void cHdffSetupPage::Store(void) +{ + SetupStore("Resolution", mNewHdffSetup.Resolution); + SetupStore("TvFormat", mNewHdffSetup.TvFormat); + SetupStore("VideoConversion", mNewHdffSetup.VideoConversion); + SetupStore("AnalogueVideo", mNewHdffSetup.AnalogueVideo); + SetupStore("AudioDelay", mNewHdffSetup.AudioDelay); + SetupStore("AudioDownmix", mNewHdffSetup.AudioDownmix); + SetupStore("OsdSize", mNewHdffSetup.OsdSize); + SetupStore("CecEnabled", mNewHdffSetup.CecEnabled); + SetupStore("RemoteProtocol", mNewHdffSetup.RemoteProtocol); + SetupStore("RemoteAddress", mNewHdffSetup.RemoteAddress); + SetupStore("HighLevelOsd", mNewHdffSetup.HighLevelOsd); + SetupStore("TrueColorOsd", mNewHdffSetup.TrueColorOsd); + + if (mHdffCmdIf) + { + if (mNewHdffSetup.Resolution != gHdffSetup.Resolution) + { + mHdffCmdIf->CmdHdmiSetVideoMode(mNewHdffSetup.GetVideoMode()); + } + HDFF::tVideoFormat videoFormat; + HDFF::tHdmiConfig hdmiConfig; + + videoFormat.AutomaticEnabled = true; + videoFormat.AfdEnabled = true; + videoFormat.TvFormat = (HDFF::eTvFormat) mNewHdffSetup.TvFormat; + videoFormat.VideoConversion = (HDFF::eVideoConversion) mNewHdffSetup.VideoConversion; + mHdffCmdIf->CmdAvSetVideoFormat(0, &videoFormat); + + mHdffCmdIf->CmdAvSetAudioDelay(mNewHdffSetup.AudioDelay); + mHdffCmdIf->CmdAvSetAudioDownmix((HDFF::eDownmixMode) mNewHdffSetup.AudioDownmix); + + mHdffCmdIf->CmdMuxSetVideoOut((HDFF::eVideoOut) mNewHdffSetup.AnalogueVideo); + + hdmiConfig.TransmitAudio = true; + hdmiConfig.ForceDviMode = false; + hdmiConfig.CecEnabled = mNewHdffSetup.CecEnabled; + mHdffCmdIf->CmdHdmiConfigure(&hdmiConfig); + + mHdffCmdIf->CmdRemoteSetProtocol((HDFF::eRemoteProtocol) mNewHdffSetup.RemoteProtocol); + mHdffCmdIf->CmdRemoteSetAddressFilter(mNewHdffSetup.RemoteAddress >= 0, mNewHdffSetup.RemoteAddress); + } + + gHdffSetup = mNewHdffSetup; +} diff --git a/PLUGINS/src/dvbhddevice/setup.h b/PLUGINS/src/dvbhddevice/setup.h new file mode 100644 index 0000000..07c9d1a --- /dev/null +++ b/PLUGINS/src/dvbhddevice/setup.h @@ -0,0 +1,53 @@ +/* + * setup.h: Setup for the DVB HD Full Featured On Screen Display + * + * See the README file for copyright information and how to reach the author. + * + * $Id: setup.h 1.8 2011/04/17 11:20:22 kls Exp $ + */ + +#ifndef _HDFF_SETUP_H_ +#define _HDFF_SETUP_H_ + +#include <vdr/plugin.h> +#include "hdffcmd.h" + +struct cHdffSetup +{ + cHdffSetup(void); + bool SetupParse(const char * Name, const char * Value); + void GetOsdSize(int &Width, int &Height, double &PixelAspect); + HDFF::eHdmiVideoMode GetVideoMode(void); + + int Resolution; + int TvFormat; + int VideoConversion; + int AnalogueVideo; + int AudioDelay; + int AudioDownmix; + int OsdSize; + int CecEnabled; + int RemoteProtocol; + int RemoteAddress; + + int HighLevelOsd; + int TrueColorOsd; +}; + +extern cHdffSetup gHdffSetup; + +class cHdffSetupPage : public cMenuSetupPage +{ +private: + HDFF::cHdffCmdIf * mHdffCmdIf; + cHdffSetup mNewHdffSetup; + +protected: + virtual void Store(void); + +public: + cHdffSetupPage(HDFF::cHdffCmdIf * pHdffCmdIf); + virtual ~cHdffSetupPage(void); +}; + +#endif diff --git a/PLUGINS/src/dvbsddevice/HISTORY b/PLUGINS/src/dvbsddevice/HISTORY index 0d1047b..9672f6f 100644 --- a/PLUGINS/src/dvbsddevice/HISTORY +++ b/PLUGINS/src/dvbsddevice/HISTORY @@ -15,3 +15,7 @@ VDR Plugin 'dvbsddevice' Revision History - The PCR pid is now recorded for channels where this is different from the video PID. + +2011-04-17: Version 0.0.4 + +- Removed an obsolete local variable in dvbsdffosd.c (thanks to Paul Menzel). diff --git a/PLUGINS/src/dvbsddevice/dvbsddevice.c b/PLUGINS/src/dvbsddevice/dvbsddevice.c index cc48b28..6f042d8 100644 --- a/PLUGINS/src/dvbsddevice/dvbsddevice.c +++ b/PLUGINS/src/dvbsddevice/dvbsddevice.c @@ -3,13 +3,13 @@ * * See the README file for copyright information and how to reach the author. * - * $Id: dvbsddevice.c 1.3 2010/01/30 10:05:42 kls Exp $ + * $Id: dvbsddevice.c 1.4 2011/04/17 12:55:43 kls Exp $ */ #include <vdr/plugin.h> #include "dvbsdffdevice.h" -static const char *VERSION = "0.0.3"; +static const char *VERSION = "0.0.4"; static const char *DESCRIPTION = "SD Full Featured DVB device"; class cPluginDvbsddevice : public cPlugin { diff --git a/PLUGINS/src/dvbsddevice/dvbsdffosd.c b/PLUGINS/src/dvbsddevice/dvbsdffosd.c index 4b60ef5..46c65e0 100644 --- a/PLUGINS/src/dvbsddevice/dvbsdffosd.c +++ b/PLUGINS/src/dvbsddevice/dvbsdffosd.c @@ -3,7 +3,7 @@ * * See the README file for copyright information and how to reach the author. * - * $Id: dvbsdffosd.c 2.2 2010/09/19 12:43:45 kls Exp $ + * $Id: dvbsdffosd.c 2.3 2011/04/17 12:55:09 kls Exp $ */ #include "dvbsdffosd.h" @@ -73,8 +73,7 @@ void cDvbSdFfOsd::SetActive(bool On) Flush(); } else if (shown) { - cBitmap *Bitmap; - for (int i = 0; (Bitmap = GetBitmap(i)) != NULL; i++) { + for (int i = 0; GetBitmap(i); i++) { Cmd(OSD_SetWindow, 0, i + 1); Cmd(OSD_Close); } @@ -108,8 +107,7 @@ eOsdError cDvbSdFfOsd::CanHandleAreas(const tArea *Areas, int NumAreas) eOsdError cDvbSdFfOsd::SetAreas(const tArea *Areas, int NumAreas) { if (shown) { - cBitmap *Bitmap; - for (int i = 0; (Bitmap = GetBitmap(i)) != NULL; i++) { + for (int i = 0; GetBitmap(i); i++) { Cmd(OSD_SetWindow, 0, i + 1); Cmd(OSD_Close); } diff --git a/PLUGINS/src/osddemo/HISTORY b/PLUGINS/src/osddemo/HISTORY index 1270fbf..ac386b0 100644 --- a/PLUGINS/src/osddemo/HISTORY +++ b/PLUGINS/src/osddemo/HISTORY @@ -25,3 +25,12 @@ VDR Plugin 'osddemo' Revision History 2011-02-20: Version 0.2.0 - Added support for TrueColor OSD. + +2011-03-28: Version 0.2.1 + +- Added Cancel(3) to ~cTrueColorDemo() (thanks to Reinhard Nissl). +- Added a missing font deletion in cTrueColorDemo::Action() (thanks to Reinhard Nissl). + +2011-04-17: Version 0.2.2 + +- Fixed a possible NULL pointer dereference in osddemo.c (reported by Paul Menzel). diff --git a/PLUGINS/src/osddemo/osddemo.c b/PLUGINS/src/osddemo/osddemo.c index 2e6a33b..9ad9df7 100644 --- a/PLUGINS/src/osddemo/osddemo.c +++ b/PLUGINS/src/osddemo/osddemo.c @@ -3,13 +3,13 @@ * * See the README file for copyright information and how to reach the author. * - * $Id: osddemo.c 2.3 2011/02/26 12:08:13 kls Exp $ + * $Id: osddemo.c 2.5 2011/04/17 13:05:13 kls Exp $ */ #include <vdr/osd.h> #include <vdr/plugin.h> -static const char *VERSION = "0.2.0"; +static const char *VERSION = "0.2.2"; static const char *DESCRIPTION = "Demo of arbitrary OSD setup"; static const char *MAINMENUENTRY = "Osd Demo"; @@ -103,6 +103,7 @@ cTrueColorDemo::cTrueColorDemo(void) cTrueColorDemo::~cTrueColorDemo() { + Cancel(3); delete osd; } @@ -262,12 +263,13 @@ void cTrueColorDemo::Action(void) case 3: { if (cFont *Font = cFont::CreateFont(DefaultFontOsd, osd->Height() / 10)) { NextPixmap = CreateTextPixmap("Millions of colors", Line, 1, clrYellow, clrTransparent, Font); + delete Font; if (NextPixmap) { FadeInPixmap = NextPixmap; + Start = cTimeMs::Now(); + StartLine = Line; + Line += NextPixmap->DrawPort().Height(); } - Start = cTimeMs::Now(); - StartLine = Line; - Line += NextPixmap->DrawPort().Height(); } State++; } |