summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManiac <maniac>2011-05-10 20:46:03 +0200
committerManiac <maniac>2011-05-10 20:46:03 +0200
commit032f825e6adc49ea52e45410bf98c90ae6fd27ec (patch)
tree2fc7e5a9bf65f720fc31f3072b16ab37007eafd1
downloadvdr-plugin-skinpearlhd-0.0.1.tar.gz
vdr-plugin-skinpearlhd-0.0.1.tar.bz2
initial import0.0.1
-rw-r--r--COPYING340
-rw-r--r--HISTORY6
-rw-r--r--Makefile115
-rw-r--r--README37
-rw-r--r--bitmap.c112
-rw-r--r--bitmap.h35
-rw-r--r--config.c58
-rw-r--r--config.h40
-rw-r--r--pearlhd.c1910
-rw-r--r--pearlhd.h21
-rw-r--r--po/de_DE.po173
-rw-r--r--services/epgsearchservices.h195
-rw-r--r--setup.c204
-rw-r--r--setup.h23
-rw-r--r--skinpearlhd.c162
15 files changed, 3431 insertions, 0 deletions
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..f90922e
--- /dev/null
+++ b/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/HISTORY b/HISTORY
new file mode 100644
index 0000000..07928fa
--- /dev/null
+++ b/HISTORY
@@ -0,0 +1,6 @@
+VDR Plugin 'skinpearlhd' Revision History
+-----------------------------------------
+
+2011-05-10: Version 0.0.1
+
+- Initial revision.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..d938c07
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,115 @@
+#
+# Makefile for a Video Disk Recorder plugin
+#
+# $Id$
+
+# 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 = skinpearlhd
+
+### 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
+INCLUDES += -I/usr/include/ImageMagick
+
+DEFINES += -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
+
+### The object files (add further files here):
+
+OBJS = $(PLUGIN).o pearlhd.o bitmap.o config.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-$(PLUGIN) --package-version=$(VERSION) --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) $(LDFLAGS) -shared $(OBJS) -lMagick++ -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/README b/README
new file mode 100644
index 0000000..5f55183
--- /dev/null
+++ b/README
@@ -0,0 +1,37 @@
+This is a "plugin" for the Video Disk Recorder (VDR).
+
+Written by: Maniac
+
+Project's homepage: http://projects.vdr-developer.org/projects/show/plg-skinpearlhd
+
+Latest version available at: http://projects.vdr-developer.org/git/?p=vdr-plugin-skinpearlhd.git
+
+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:
+============
+
+This is a conversion of the PearlHD-Skin written by mapovi to a native vdr-plugin.
+The original skin uses the text2skin-plugin.
+Only 1920x1080 at truecolor or 256 colors supported for now. Support for 1280x720 will follow in a later version.
+
+Requirements:
+=============
+
+ - ImageMagick
+
+Comandline parameter:
+=====================
+
+ -e DIR, --epgimages=DIR set directory for epgimages
+
+Setup:
+======
+Almost all options can be configured in the setup menu of the plugin.
+The default directory for epgimages is $(VDRCONFDIR)/plugins/tvm2vdr/epgimages
+Logo directory is $(VDRCONFDIR)/plugins/skinpearlhd/logos
+You can use png or jpg logos. \ No newline at end of file
diff --git a/bitmap.c b/bitmap.c
new file mode 100644
index 0000000..a30e1d5
--- /dev/null
+++ b/bitmap.c
@@ -0,0 +1,112 @@
+#ifdef HAVE_C295
+#include <stl.h>
+#endif
+#include "bitmap.h"
+
+using namespace std; //need ???
+using namespace Magick;
+
+cOSDImageBitmap::cOSDImageBitmap() {
+}
+
+cOSDImageBitmap::~cOSDImageBitmap() {
+}
+
+bool cOSDImageBitmap::LoadZoomed(const char *file, int zoomWidth, int zoomHeight, int zoomLeft, int zoomTop) {
+ bool status;
+ status = LoadImageMagick(imgkZoom, file);
+ if (zoomWidth != 0)
+ imgkZoom.crop(Geometry(zoomWidth, zoomHeight, zoomLeft, zoomTop));
+ height = imgkZoom.rows();
+ width = imgkZoom.columns();
+ return status;
+}
+
+bool cOSDImageBitmap::Load(const char *file)
+{
+ return LoadImageMagick(imgkImage, file);
+}
+
+void cOSDImageBitmap::Render(cBitmap & bmp, int colors, int alpha)
+{
+ dsyslog("start to rande image");
+ if (!loadingFailed) {
+ // quantize the picture
+ QuantizeImageMagick(imgkImage, colors, false);
+ // generate cBitmap
+ ConvertImgk2Bmp(bmp, imgkImage, colors);
+ } else {
+ dsyslog("can't rander image, loading failed!!!!!!!!!!!!!!!!!");
+ }
+}
+
+void cOSDImageBitmap::Render(cBitmap &bmp, int wWindow, int hWindow, int colors, bool dither) {
+ int w = wWindow;
+ int h = hWindow;
+ int wNew, hNew;
+ wNew = wWindow;
+ hNew = hWindow;
+ if (!loadingFailed) {
+ Image imgkRender = imgkImage;
+ width = imgkRender.columns();
+ height = imgkRender.rows();
+ if (height != h || width != w) {
+ imgkRender.scale(Geometry(wNew, hNew, 0, 0) );
+ width = imgkRender.columns();
+ height = imgkRender.rows();
+ }
+ QuantizeImageMagick(imgkRender, colors, dither);
+ ConvertImgk2Bmp(bmp, imgkRender, colors);
+ }
+}
+
+bool cOSDImageBitmap::LoadImageMagick(Image &imgkLoad, const char *file) {
+ try {
+ imgkLoad.read(file);
+ if (imgkLoad.fileSize() == 0) {
+ loadingFailed = true;
+ return false;
+ }
+ else {
+ height = imgkLoad.baseRows();
+ width = imgkLoad.baseColumns();
+ origWidth = width;
+ origHeight = height;
+ loadingFailed = false;
+ return true;
+ }
+ }
+ catch(exception &error)
+ {
+ loadingFailed = true;
+ return false;
+ }
+}
+
+void cOSDImageBitmap::QuantizeImageMagick(Image &imgkQuant, int colors, bool dither) {
+ if (colors < 24)
+ {
+ imgkQuant.quantizeColors(colors);
+ imgkQuant.quantizeDither(dither);
+ }
+ imgkQuant.quantize();
+}
+
+void cOSDImageBitmap::ConvertImgk2Bmp(cBitmap &bmp, Image &imgkConv, int colors) {
+ int w = Width();
+ int h = Height();
+ tColor col;
+ bmp.SetSize(w, h);
+ bmp.SetBpp(colors);
+ const PixelPacket *pixels = imgkConv.getConstPixels(0, 0, w, h);
+ for (int iy = 0; iy < h; iy++) {
+ for (int ix = 0; ix < w; ix++) {
+ col = (0xFF << 24)
+ | ( (pixels->green * 255 / MaxRGB) << 8)
+ | ( (pixels->red * 255 / MaxRGB) << 16)
+ | ( (pixels->blue * 255 / MaxRGB) );
+ bmp.DrawPixel(ix, iy, col);
+ pixels++;
+ }
+ }
+}
diff --git a/bitmap.h b/bitmap.h
new file mode 100644
index 0000000..debbbe8
--- /dev/null
+++ b/bitmap.h
@@ -0,0 +1,35 @@
+#ifndef _OSDIMAGE_BITMAP_H_
+#define _OSDIMAGE_BITMAP_H_
+
+#define X_DISPLAY_MISSING
+
+#include <vdr/osd.h>
+#include <vdr/skins.h>
+#include <Magick++.h>
+
+using namespace Magick;
+
+class cOSDImageBitmap {
+public:
+ cOSDImageBitmap();
+ ~cOSDImageBitmap();
+ bool LoadZoomed(const char *file, int zoomWidth, int zoomHeight, int zoomLeft, int zoomTop);
+ bool Load(const char *file);
+ void Save(const char *file);
+ void Render(cBitmap &bmp, int wWindow, int hWindow, int colors, bool dither);
+ void Render(cBitmap &bmp, int colors, int alpha=255);
+ inline int Width() { return width; }
+ inline int Height() { return height; }
+
+private:
+ bool LoadImageMagick(Image &imgkLoad, const char *file);
+ void QuantizeImageMagick(Image &imgkQuant, int colors, bool dither);
+ void ConvertImgk2Bmp(cBitmap &bmp, Image &imgkConv, int colors);
+ Image imgkZoom, imgkImage;
+ int ZoomWidth, ZoomHeight, ZoomLeft, ZoomTop;
+ int origWidth, origHeight;
+ bool loadingFailed;
+ int width, height;
+};
+
+#endif
diff --git a/config.c b/config.c
new file mode 100644
index 0000000..ef1ff81
--- /dev/null
+++ b/config.c
@@ -0,0 +1,58 @@
+#include "config.h"
+
+cSkinPearlHDConfig PearlHDConfig;
+
+cTheme Theme;
+
+// --- cSkinPearlHDConfig ----------------------------------------------------------
+cSkinPearlHDConfig::cSkinPearlHDConfig(void)
+{
+ ChannelLogoPos = 0;
+ ChannelLogoFormat = 0;
+ CryptSymbols = 0;
+ oClockText = 1;
+ RecShowClock = 1;
+ DisplayEpgImages = 0;
+ EpgImagesFormat = 1;
+ MenuPaddingWidth = 240;
+ MenuPaddingHeight = 135;
+ LineHeight = 50;
+ ChannelInfoPadding = 240;
+ RecTitleInfoHead = 0;
+ RecTitleInfo = 0;
+ *EpgImagesDir = NULL;
+ EpgDirSet = false;
+}
+
+cSkinPearlHDConfig::~cSkinPearlHDConfig()
+{
+}
+
+bool cSkinPearlHDConfig::SetupParse(const char *Name, const char *Value)
+{
+ if (strcmp(Name, "ChannelLogoPos") == 0) ChannelLogoPos = atoi(Value);
+ else if (strcmp(Name, "ChannelLogoFormat") == 0) ChannelLogoFormat = atoi(Value);
+ else if (strcmp(Name, "ButtonRedText") == 0) strncpy(ButtonRedText, Value, 20);
+ else if (strcmp(Name, "ButtonGreenText") == 0) strncpy(ButtonGreenText, Value, 20);
+ else if (strcmp(Name, "ButtonYellowText") == 0) strncpy(ButtonYellowText, Value, 20);
+ else if (strcmp(Name, "ButtonBlueText") == 0) strncpy(ButtonBlueText, Value, 20);
+ else if (strcmp(Name, "CryptSymbols") == 0) CryptSymbols = atoi(Value);
+ else if (strcmp(Name, "oClockText") == 0) oClockText = atoi(Value);
+ else if (strcmp(Name, "RecShowClock") == 0) RecShowClock = atoi(Value);
+ else if (strcmp(Name, "DisplayEpgImages") == 0) DisplayEpgImages = atoi(Value);
+ else if (strcmp(Name, "EpgImagesFormat") == 0) EpgImagesFormat = atoi(Value);
+ else if (strcmp(Name, "MenuPaddingWidth") == 0) MenuPaddingWidth = atoi(Value);
+ else if (strcmp(Name, "MenuPaddingHeight") == 0) MenuPaddingHeight = atoi(Value);
+ else if (strcmp(Name, "LineHeight") == 0) LineHeight = atoi(Value);
+ else if (strcmp(Name, "ChannelInfoPadding") == 0) ChannelInfoPadding = atoi(Value);
+ else if (strcmp(Name, "RecTitleInfoHead") == 0) RecTitleInfoHead = atoi(Value);
+ else if (strcmp(Name, "RecTitleInfo") == 0) RecTitleInfo = atoi(Value);
+ else return false;
+ return true;
+}
+
+ void cSkinPearlHDConfig::SetEpgImagesDir(const char *Dir)
+ {
+ strncpy(EpgImagesDir, Dir, 100);
+ EpgDirSet = true;
+ }
diff --git a/config.h b/config.h
new file mode 100644
index 0000000..ebbddc0
--- /dev/null
+++ b/config.h
@@ -0,0 +1,40 @@
+#ifndef __SKINPEARLHD_CONFIG_H
+#define __SKINPEARLHD_CONFIG_H
+
+#include <vdr/themes.h>
+#include <vdr/config.h>
+
+class cSkinPearlHDConfig
+{
+private:
+
+public:
+ cSkinPearlHDConfig(void);
+ ~cSkinPearlHDConfig();
+ bool SetupParse(const char *Name, const char *Value);
+ void SetEpgImagesDir(const char *Dir);
+
+ int ChannelLogoPos;
+ int ChannelLogoFormat;
+ char ButtonRedText[20];
+ char ButtonGreenText[20];
+ char ButtonYellowText[20];
+ char ButtonBlueText[20];
+ int CryptSymbols;
+ int oClockText;
+ int RecShowClock;
+ int DisplayEpgImages;
+ int EpgImagesFormat;
+ int MenuPaddingWidth;
+ int MenuPaddingHeight;
+ int LineHeight;
+ int ChannelInfoPadding;
+ int RecTitleInfoHead;
+ int RecTitleInfo;
+ char EpgImagesDir[100];
+ bool EpgDirSet;
+};
+
+extern cSkinPearlHDConfig PearlHDConfig;
+
+#endif //__SKINPEARLHD_CONFIG_H
diff --git a/pearlhd.c b/pearlhd.c
new file mode 100644
index 0000000..7c22bd2
--- /dev/null
+++ b/pearlhd.c
@@ -0,0 +1,1910 @@
+#include "pearlhd.h"
+#include "bitmap.h"
+#include "config.h"
+#include "services/epgsearchservices.h"
+
+#include <string>
+#include <sstream>
+#include <sys/time.h>
+
+#include <vdr/config.h>
+#include <vdr/device.h>
+#include <vdr/timers.h>
+#include <vdr/menu.h>
+#include <vdr/font.h>
+#include <vdr/osd.h>
+#include <vdr/themes.h>
+#include <vdr/plugin.h>
+
+#define MENU_TYPE_VDR 1
+#define MENU_TYPE_SCHEDULE 2
+#define MENU_TYPE_RECORDINGS 3
+#define MENU_TYPE_RECORDING 4
+#define MENU_TYPE_EVENT 5
+
+static cTheme Theme;
+
+THEME_CLR(Theme, clrMainLight, 0x80000000);
+THEME_CLR(Theme, clrMainSolid, 0xCC000000);
+THEME_CLR(Theme, clrBar, 0x80bbe5ff);
+THEME_CLR(Theme, clrBarFill, 0x803b86b6);
+THEME_CLR(Theme, clrBarBlock, 0x80ff6969);
+THEME_CLR(Theme, clrFontColor, 0xFFFFFFFF);
+
+THEME_CLR(Theme, clrDivider, 0xCC8c8c8c);
+
+THEME_CLR(Theme, clrSymbolGreen, 0x6000ff00);
+THEME_CLR(Theme, clrSymbolRed, 0xAAff0000);
+
+THEME_CLR(Theme, clrStatus, 0xAA6d8c00);
+THEME_CLR(Theme, clrWarning, 0xAAff8a00);
+THEME_CLR(Theme, clrError, 0xAAff0000);
+
+THEME_CLR(Theme, clrLoLight, 0x95000000);
+THEME_CLR(Theme, clrFontColorInactive, 0x993b86b6);
+THEME_CLR(Theme, clrMessageWhite, 0xffffffff);
+THEME_CLR(Theme, clrMessageBlack, 0xff000000);
+
+THEME_CLR(Theme, clrMark, 0xFFe39b00);
+THEME_CLR(Theme, clrKeep, 0xFF6d8c00);
+
+THEME_CLR(Theme, clrMainSolidOverlay, 0xDD000000);
+
+// --- cSkinPearlHDDisplayChannel ----------------------------------------------
+
+class cSkinPearlHDDisplayChannel : public cSkinDisplayChannel {
+private:
+ cOsd *osd;
+
+ int heightChannelBar;
+ int heightProgressBar;
+ int heightInfoBar;
+ int heightButtons;
+ int widthButtons;
+
+ int heightClock;
+ int widthClock;
+
+ int x1ChannelInfo;
+ int x2ChannelInfo;
+ int y1ChannelInfo;
+ int y2ChannelInfo;
+ int xSymbolStart;
+ int ySymbol;
+ int symbolWidth;
+ int x1DateTime;
+ int x2DateTime;
+ int y1DateTime;
+ int x1Message;
+ int x2Message;
+ int y1Message;
+ int y2Message;
+ int bpp;
+ bool isGroupSep;
+ unsigned long blinkNext;
+ int blinkState;
+ bool withInfo;
+ int lineHeight;
+ const cFont *fontSansBook15;
+ const cFont *fontSansBook27;
+ const cFont *fontSansBook37;
+ const cFont *fontSansBold16;
+ const cFont *fontCryptSymbols;
+ std::string logoPath, logoFormat;
+ void DrawRedButton(int xButton, int yButton);
+ void DrawGreenButton(int xButton, int yButton);
+ void DrawYellowButton(int xButton, int yButton);
+ void DrawBlueButton(int xButton, int yButton);
+ void DrawCryptSymbol(int xSymbol, int ySymbol, const char *Text, tColor color, tColor bgcolor);
+public:
+ cSkinPearlHDDisplayChannel(bool WithInfo);
+ virtual ~cSkinPearlHDDisplayChannel();
+ virtual void SetChannel(const cChannel *Channel, int Number);
+ virtual void SetEvents(const cEvent *Present, const cEvent *Following);
+ virtual void SetMessage(eMessageType Type, const char *Text);
+ virtual void Flush(void);
+ };
+
+cSkinPearlHDDisplayChannel::cSkinPearlHDDisplayChannel(bool WithInfo)
+{
+ bpp = 0;
+ fontSansBook15 = cFont::CreateFont("VDRSymbols Sans:Book", 15);
+ fontSansBook27 = cFont::CreateFont("VDRSymbols Sans:Book", 27);
+ fontSansBook37 = cFont::CreateFont("VDRSymbols Sans:Book", 37);
+ fontSansBold16 = cFont::CreateFont("VDRSymbols Sans:Bold", 16);
+ fontCryptSymbols = cFont::CreateFont("VDRSymbols Sans:Bold", 9);
+ x1ChannelInfo = PearlHDConfig.ChannelInfoPadding;
+ x2ChannelInfo = cOsd::OsdWidth() - PearlHDConfig.ChannelInfoPadding;
+ y1ChannelInfo = cOsd::OsdHeight() - 340;
+ y2ChannelInfo = cOsd::OsdHeight() - 55;
+ x1DateTime = cOsd::OsdWidth() - 460;
+ x2DateTime = cOsd::OsdWidth();
+ y1DateTime = 0;
+ x1Message = 480;
+ x2Message = cOsd::OsdWidth() - 1;
+ y1Message = cOsd::OsdHeight() - 70;
+ y2Message = cOsd::OsdHeight() - 1;
+ xSymbolStart = x2ChannelInfo-255;
+ ySymbol = y2ChannelInfo-278;
+ symbolWidth = 50;
+
+ blinkNext=0;
+ blinkState=0;
+
+ osd = cOsdProvider::NewOsd(cOsd::OsdLeft(), cOsd::OsdTop());
+ tArea Areas[] = { { 0, 0, cOsd::OsdWidth() - 1, cOsd::OsdHeight() - 1, 32 } }; // TrueColor
+ if (osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
+ {
+ osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
+ bpp = 24;
+ }
+ else
+ {
+ tArea Areas[] = { { 0, 0, cOsd::OsdWidth() - 1, y2ChannelInfo - 1, 8 },
+ { x2ChannelInfo - 957, y2ChannelInfo, x2ChannelInfo - 478, cOsd::OsdHeight() - 1, 8 },
+ { x2ChannelInfo - 477, y2ChannelInfo, x2ChannelInfo - 1, cOsd::OsdHeight() - 1, 8 } }; // 256 colors
+ if (osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
+ {
+ bpp = 8;
+ osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
+ }
+ }
+
+ osd->DrawRectangle(cOsd::OsdLeft(), cOsd::OsdTop(), cOsd::OsdWidth(), cOsd::OsdHeight(), clrTransparent);
+
+ if (strcmp(PearlHDConfig.ButtonRedText, "") != 0)
+ {
+ DrawRedButton(x2ChannelInfo - 957, y2ChannelInfo);
+ osd->DrawText(x2ChannelInfo - 957, y2ChannelInfo, PearlHDConfig.ButtonRedText, Theme.Color(clrMessageWhite), clrTransparent, fontSansBook27, 239, 0, taCenter);
+ }
+ if (strcmp(PearlHDConfig.ButtonGreenText, "") != 0)
+ {
+ DrawGreenButton(x2ChannelInfo - 717, y2ChannelInfo);
+ osd->DrawText(x2ChannelInfo - 717, y2ChannelInfo, PearlHDConfig.ButtonGreenText, Theme.Color(clrMessageBlack), clrTransparent, fontSansBook27, 237, 0, taCenter);
+ }
+ if (strcmp(PearlHDConfig.ButtonYellowText, "") != 0)
+ {
+ DrawYellowButton(x2ChannelInfo - 477, y2ChannelInfo);
+ osd->DrawText(x2ChannelInfo - 477, y2ChannelInfo, PearlHDConfig.ButtonYellowText, Theme.Color(clrMessageBlack), clrTransparent, fontSansBook27, 237, 0, taCenter);
+ }
+ if (strcmp(PearlHDConfig.ButtonBlueText, "") != 0)
+ {
+ DrawBlueButton(x2ChannelInfo - 237, y2ChannelInfo);
+ osd->DrawText(x2ChannelInfo - 237, y2ChannelInfo, PearlHDConfig.ButtonBlueText, Theme.Color(clrMessageWhite), clrTransparent, fontSansBook27, 237, 0, taCenter);
+ }
+
+ logoPath = cPlugin::ConfigDirectory();
+ logoPath += "/skinpearlhd/logos/";
+ switch (PearlHDConfig.ChannelLogoFormat)
+ {
+ case 0:
+ logoFormat = "png";
+ break;
+ case 1:
+ logoFormat = "jpg";
+ break;
+ }
+}
+
+cSkinPearlHDDisplayChannel::~cSkinPearlHDDisplayChannel()
+{
+ delete osd;
+}
+
+void cSkinPearlHDDisplayChannel::SetChannel(const cChannel *Channel, int Number)
+{
+ osd->DrawEllipse(x1ChannelInfo, y1ChannelInfo, x1ChannelInfo + 50, y1ChannelInfo + 50, Theme.Color(clrMainLight), 2);
+ osd->DrawRectangle(x1ChannelInfo + 50, y1ChannelInfo, x2ChannelInfo, y1ChannelInfo + 50, Theme.Color(clrMainLight));
+ osd->DrawRectangle(x1ChannelInfo, y1ChannelInfo + 70, x2ChannelInfo, y2ChannelInfo, Theme.Color(clrMainSolid));
+
+ std::string displayLogoPath = logoPath + Channel->Name() + "." + logoFormat;
+ cOSDImageBitmap osdbitmap;
+ cBitmap logo (1, 1, bpp);
+
+ switch (PearlHDConfig.ChannelLogoPos)
+ {
+ case 1 :
+ if(osdbitmap.Load(displayLogoPath.c_str())){
+ logo.SetSize(64, 48);
+ osdbitmap.Render(logo, 64, 48, bpp, false);
+ osd->DrawBitmap(x1ChannelInfo+120, y1ChannelInfo, logo);
+ }
+ break;
+
+ case 2 :
+ if(osdbitmap.Load(displayLogoPath.c_str())){
+ logo.SetSize(120, 120);
+ osdbitmap.Render(logo, 120, 120, bpp, false);
+ osd->DrawBitmap(x2ChannelInfo-125, y1ChannelInfo+195, logo);
+ }
+ break;
+ }
+
+ if (Channel && !Channel->GroupSep()) {
+ isGroupSep = false;
+ char sNumber[50];
+ switch (PearlHDConfig.ChannelLogoPos)
+ {
+ case 0 :
+ case 2 :
+ snprintf(sNumber, sizeof(sNumber), "%d", Channel->Number());
+ osd->DrawText(x1ChannelInfo + 120, y1ChannelInfo + 13, sNumber, Theme.Color(clrFontColor), clrTransparent, fontSansBook27);
+ osd->DrawText(x1ChannelInfo + 240, y1ChannelInfo + 5, Channel->Name(), Theme.Color(clrFontColor), clrTransparent, fontSansBook37, x2ChannelInfo - (x1ChannelInfo + 240), 0, taLeft);
+ break;
+
+ case 1 :
+ snprintf(sNumber, sizeof(sNumber), "%d - %s", Channel->Number(), Channel->Name());
+ osd->DrawText(x1ChannelInfo + 240, y1ChannelInfo + 5, sNumber, Theme.Color(clrFontColor), clrTransparent, fontSansBook37, x2ChannelInfo - (x1ChannelInfo + 240), 0, taLeft);
+ break;
+ }
+
+ int xSymbol = xSymbolStart;
+
+ //Teletext
+ osd->DrawRectangle(xSymbol+1, ySymbol+1, xSymbol+35, ySymbol+26, Theme.Color(Channel->Tpid() ? clrSymbolGreen : clrDivider));
+ osd->DrawRectangle(xSymbol+2, ySymbol+2, xSymbol+34, ySymbol+25, Theme.Color(clrMainLight));
+ osd->DrawRectangle(xSymbol+4, ySymbol+5, xSymbol+32, ySymbol+7, Theme.Color(Channel->Tpid() ? clrSymbolGreen : clrDivider));
+ osd->DrawRectangle(xSymbol+4, ySymbol+10, xSymbol+32, ySymbol+12, Theme.Color(Channel->Tpid() ? clrSymbolGreen : clrDivider));
+ osd->DrawRectangle(xSymbol+4, ySymbol+15, xSymbol+32, ySymbol+17, Theme.Color(Channel->Tpid() ? clrSymbolGreen : clrDivider));
+ osd->DrawRectangle(xSymbol+4, ySymbol+20, xSymbol+32, ySymbol+22, Theme.Color(Channel->Tpid() ? clrSymbolGreen : clrDivider));
+
+ //DolbyDigital
+ xSymbol += symbolWidth;
+ osd->DrawRectangle(xSymbol+1, ySymbol+1, xSymbol+35, ySymbol+26, Theme.Color(Channel->Dpid(0) ? clrSymbolGreen : clrDivider));
+ osd->DrawRectangle(xSymbol+2, ySymbol+2, xSymbol+34, ySymbol+25, Theme.Color(clrMainLight));
+ osd->DrawRectangle(xSymbol+18, ySymbol+2, xSymbol+18, ySymbol+26, Theme.Color(Channel->Dpid(0) ? clrSymbolGreen : clrDivider));
+ osd->DrawEllipse(xSymbol+4, ySymbol+4, xSymbol+16, ySymbol+22, Theme.Color(Channel->Dpid(0) ? clrSymbolGreen : clrDivider), 5);
+ osd->DrawEllipse(xSymbol+20, ySymbol+4, xSymbol+32, ySymbol+22, Theme.Color(Channel->Dpid(0) ? clrSymbolGreen : clrDivider), 7);
+
+ //MultiLang
+ xSymbol += symbolWidth;
+ osd->DrawRectangle(xSymbol+1, ySymbol+1, xSymbol+35, ySymbol+26, Theme.Color(Channel->Apid(1) ? clrSymbolGreen : clrDivider));
+ osd->DrawRectangle(xSymbol+2, ySymbol+2, xSymbol+34, ySymbol+25, Theme.Color(clrMainLight));
+ osd->DrawEllipse(xSymbol+5, ySymbol+6, xSymbol+18, ySymbol+22, Theme.Color(Channel->Apid(1) ? clrSymbolGreen : clrDivider));
+ osd->DrawEllipse(xSymbol+5, ySymbol+8, xSymbol+18, ySymbol+20, Theme.Color(Channel->Apid(1) ? clrSymbolGreen : clrDivider));
+ osd->DrawEllipse(xSymbol+19, ySymbol+6, xSymbol+32, ySymbol+22, Theme.Color(Channel->Apid(1) ? clrSymbolGreen : clrDivider));
+ osd->DrawEllipse(xSymbol+19, ySymbol+8, xSymbol+32, ySymbol+20, Theme.Color(Channel->Apid(1) ? clrSymbolGreen : clrMainLight));
+
+ if (Channel->Apid(1))
+ {
+ switch (cDevice::PrimaryDevice()->GetAudioChannel())
+ {
+ case 1:
+ osd->DrawEllipse(xSymbol+19, ySymbol+8, xSymbol+32, ySymbol+20, Theme.Color(clrMainLight));
+ break;
+
+ case 2 :
+ osd->DrawEllipse(xSymbol+5, ySymbol+8, xSymbol+18, ySymbol+20, Theme.Color(clrMainLight));
+ break;
+ }
+ }
+
+ //Encrypted
+ xSymbol += symbolWidth;
+ osd->DrawRectangle(xSymbol+1, ySymbol+1, xSymbol+35, ySymbol+26, Theme.Color(Channel->Ca() ? clrSymbolGreen : clrDivider));
+ osd->DrawRectangle(xSymbol+2, ySymbol+2, xSymbol+34, ySymbol+25, Theme.Color(clrMainLight));
+ osd->DrawEllipse(xSymbol+19, ySymbol+9, xSymbol+32, ySymbol+23, Theme.Color(Channel->Ca() ? clrSymbolGreen : clrDivider));
+ osd->DrawEllipse(xSymbol+22, ySymbol+12, xSymbol+29, ySymbol+20, Theme.Color(clrMainLight));
+ osd->DrawRectangle(xSymbol+4, ySymbol+9, xSymbol+22, ySymbol+11, Theme.Color(Channel->Ca() ? clrSymbolGreen : clrDivider));
+ osd->DrawRectangle(xSymbol+6, ySymbol+11, xSymbol+8, ySymbol+15, Theme.Color(Channel->Ca() ? clrSymbolGreen : clrDivider));
+ osd->DrawRectangle(xSymbol+10, ySymbol+11, xSymbol+12, ySymbol+15, Theme.Color(Channel->Ca() ? clrSymbolGreen : clrDivider));
+
+ //Recording
+ xSymbol += symbolWidth;
+ osd->DrawRectangle(xSymbol+1, ySymbol+1, xSymbol+35, ySymbol+26, Theme.Color(cRecordControls::Active() ? clrSymbolRed : clrDivider));
+ osd->DrawRectangle(xSymbol+2, ySymbol+2, xSymbol+34, ySymbol+25, Theme.Color(clrMainLight));
+ osd->DrawText(xSymbol+4, ySymbol+3, "rec", Theme.Color(cRecordControls::Active() ? clrSymbolRed : clrDivider), clrTransparent, fontSansBold16);
+
+ //CryptSymbols
+ if (PearlHDConfig.CryptSymbols)
+ {
+ #define NUM_CA_IDS 9
+ bool caOn[NUM_CA_IDS];
+ for (int i=0;i<NUM_CA_IDS;i++)
+ caOn[i] = false;
+ const char *caShort[NUM_CA_IDS] = {"B", "I", "NDS", "N", "S", "V", "C", "CW", "BC" };
+ int xCa = x2ChannelInfo-605;
+ int widthCa = 40;
+
+ for (int i=0; Channel->Ca(i) != 0 ; i++)
+ {
+ switch (Channel->Ca(i))
+ {
+ case 0x2600 : //Biss
+ caOn[0] = true;
+ break;
+
+ case 0x0600 ... 0x06FF : //Irdeto
+ caOn[1] = true;
+ break;
+
+ case 0x0900 ... 0x09FF : //NDS
+ caOn[2] = true;
+ break;
+
+ case 0x1200 ... 0x12FF : //Nagra
+ case 0x1800 ... 0x18FF : //Nagra
+ caOn[3] = true;
+ break;
+
+ case 0x0100 ... 0x01FF : //Seca
+ caOn[4] = true;
+ break;
+
+ case 0x0500 ... 0x05FF : //Viaccess
+ caOn[5] = true;
+ break;
+
+ case 0x0B00 ... 0x0BFF : //Conax
+ caOn[6] = true;
+ break;
+
+ case 0x0D00 ... 0x0DFF : //Cryptoworks
+ caOn[7] = true;
+ break;
+
+ case 0x1700 ... 0x17FF : //Betacrypt
+ caOn[8] = true;
+ break;
+ }
+ }
+
+ for (int i=0;i<NUM_CA_IDS;i++)
+ {
+ DrawCryptSymbol(xCa, ySymbol+1, caShort[i], Theme.Color(caOn[i] ? clrSymbolGreen : clrDivider), Theme.Color(clrMainLight));
+ xCa += widthCa;
+ }
+ }
+ }
+ else
+ {
+ isGroupSep=true;
+ osd->DrawText(x1ChannelInfo + 240, y1ChannelInfo + 5, Channel->Name(), Theme.Color(clrFontColor), clrTransparent, fontSansBook37);
+ }
+}
+
+void cSkinPearlHDDisplayChannel::SetEvents(const cEvent *Present, const cEvent *Following)
+{
+ for (int i = 0; i < 2; i++) {
+ const cEvent *e = !i ? Present : Following;
+ if (e) {
+ osd->DrawText(x1ChannelInfo + 120, y1ChannelInfo + 98 + (i * 95), e->GetTimeString(), Theme.Color(clrFontColor), Theme.Color(clrMainSolid), fontSansBook27, 120);
+
+ char title[100];
+ if (e->HasTimer())
+ {
+ snprintf (title, sizeof(title), "%s *", e->Title());
+ }
+ else
+ {
+ snprintf (title, sizeof(title), "%s", e->Title());
+ }
+ osd->DrawText(x1ChannelInfo + 240, y1ChannelInfo + 106 + (i * 95), title, Theme.Color(clrFontColor), Theme.Color(clrMainSolid), fontSansBook27, (x2ChannelInfo -125) - (x1ChannelInfo + 240));
+ osd->DrawText(x1ChannelInfo + 240, y1ChannelInfo + 151 + (i * 95), e->ShortText(), Theme.Color(clrFontColor), Theme.Color(clrMainSolid), fontSansBook27, (x2ChannelInfo -125) - (x1ChannelInfo + 240));
+
+ if (PearlHDConfig.ChannelLogoPos != 2)
+ {
+ if (i == 0)
+ {
+ osd->DrawRectangle(x1ChannelInfo, y1ChannelInfo + 50, x2ChannelInfo, y1ChannelInfo + 70, Theme.Color(clrBar));
+ int xBarLength = (int)(ceil((float)((time(NULL) - e->StartTime())) / (float)(e->Duration()) * (float)(x2ChannelInfo - x1ChannelInfo)));
+ osd->DrawRectangle(x1ChannelInfo, y1ChannelInfo + 50, x1ChannelInfo + xBarLength, y1ChannelInfo + 70, Theme.Color(clrBarFill));
+ int iRemaining = (e->Duration() - (time(NULL) - e->StartTime())) / 60;
+ char sRemaining[12];
+ snprintf(sRemaining, sizeof(sRemaining), "%d", iRemaining);
+ osd->DrawText(x2ChannelInfo - 120, y1ChannelInfo + 95, "m", Theme.Color(clrFontColor), Theme.Color(clrMainSolid), fontSansBook15, 95, 0, taRight);
+ osd->DrawText(x2ChannelInfo - 120, y1ChannelInfo + 95, sRemaining, Theme.Color(clrFontColor), Theme.Color(clrMainSolid), fontSansBook27, 75, 0, taRight);
+ }
+ else
+ {
+ char sNextDuration[12];
+ snprintf(sNextDuration, sizeof(sNextDuration), "%d", e->Duration() / 60);
+ osd->DrawText(x2ChannelInfo - 120, y1ChannelInfo + 190, "m", Theme.Color(clrFontColor), Theme.Color(clrMainSolid), fontSansBook15, 95, 0, taRight);
+ osd->DrawText(x2ChannelInfo - 120, y1ChannelInfo + 190, sNextDuration, Theme.Color(clrFontColor), Theme.Color(clrMainSolid), fontSansBook27, 75, 0, taRight);
+ }
+ }
+ }
+ }
+}
+
+void cSkinPearlHDDisplayChannel::SetMessage(eMessageType Type, const char *Text)
+{
+ if (Text) {
+ osd->DrawRectangle(x1Message + 50, y1Message, x2Message, y1Message + 50, Theme.Color(clrMainLight));
+ osd->DrawEllipse(x1Message, y1Message, x1Message + 50, y1Message + 50, Theme.Color(clrMainLight), 2);
+ switch(Type) {
+ case mtInfo :
+ osd->DrawRectangle(x1Message, y1Message + 50, x2Message, y2Message, Theme.Color(clrMainSolid));
+ break;
+ case mtStatus :
+ osd->DrawRectangle(x1Message, y1Message + 50, x2Message, y2Message, Theme.Color(clrStatus));
+ break;
+ case mtWarning :
+ osd->DrawRectangle(x1Message, y1Message + 50, x2Message, y2Message, Theme.Color(clrWarning));
+ break;
+ case mtError :
+ osd->DrawRectangle(x1Message, y1Message + 50, x2Message, y2Message, Theme.Color(clrError));
+ break;
+ }
+ osd->DrawText(x1Message + 50, y1Message + 15, Text, Theme.Color(clrFontColor), clrTransparent, fontSansBook27, x2Message - (x1Message+50), 0, taRight);
+ }
+}
+
+void cSkinPearlHDDisplayChannel::Flush(void)
+{
+ osd->DrawRectangle(x1DateTime, y1DateTime, x2DateTime, y1DateTime + 20, Theme.Color(clrMainLight));
+ osd->DrawEllipse(x1DateTime, y1DateTime + 20, x1DateTime + 50, y1DateTime + 70, Theme.Color(clrMainLight), 3);
+ osd->DrawRectangle(x1DateTime + 50, y1DateTime + 20, x2DateTime, y1DateTime + 70, Theme.Color(clrMainLight));
+ char datetime[50];
+ struct tm tm_r;
+ time_t t;
+ time(&t);
+ tm *tm = localtime_r(&t, &tm_r);
+ snprintf(datetime, sizeof(datetime), "%s %02d.%02d. %02d:%02d", *WeekDayNameFull(t), tm->tm_mday, tm->tm_mon + 1, tm->tm_hour, tm->tm_min);
+ osd->DrawText(x1DateTime + 30, y1DateTime + 20, datetime, Theme.Color(clrFontColor), clrTransparent, fontSansBook27);
+
+ cPlugin *p = cPluginManager::GetPlugin("epgsearch");
+ if (!isGroupSep && p)
+ {
+ Epgsearch_lastconflictinfo_v1_0 *serviceData = new Epgsearch_lastconflictinfo_v1_0;
+ if (serviceData)
+ {
+ serviceData->nextConflict = 0;
+ serviceData->relevantConflicts = 0;
+ serviceData->totalConflicts = 0;
+
+ p->Service("Epgsearch-lastconflictinfo-v1.0", serviceData);
+ if (serviceData->totalConflicts > 0)
+ {
+ int delay = cRecordControls::Active() ? 800 : 400;
+ if (cTimeMs::Now() > blinkNext)
+ {
+ osd->DrawText(xSymbolStart+200+4, ySymbol+3, "rec", Theme.Color(blinkState ? clrSymbolRed : clrDivider), Theme.Color(clrMainLight), fontSansBold16);
+ blinkNext = cTimeMs::Now() + delay;
+ blinkState = blinkState ^ 1;
+ }
+ }
+ }
+ }
+
+ osd->Flush();
+}
+
+void cSkinPearlHDDisplayChannel::DrawRedButton(int xButton, int yButton)
+{
+ osd->DrawRectangle(xButton, yButton, xButton+237, yButton+4, 0xb4690000);
+ osd->DrawRectangle(xButton, yButton+4, xButton+237, yButton+6, 0xb4740000);
+ osd->DrawRectangle(xButton, yButton+6, xButton+237, yButton+8, 0xb47c0000);
+ osd->DrawRectangle(xButton, yButton+8, xButton+237, yButton+11, 0xb4860000);
+ osd->DrawRectangle(xButton, yButton+11, xButton+237, yButton+14, 0xb4960000);
+ osd->DrawRectangle(xButton, yButton+14, xButton+237, yButton+16, 0xb4a60000);
+ osd->DrawRectangle(xButton, yButton+16, xButton+237, yButton+17, 0xb4ac0000);
+ osd->DrawRectangle(xButton, yButton+17, xButton+237, yButton+19, 0xb4b70000);
+ osd->DrawRectangle(xButton, yButton+19, xButton+237, yButton+20, 0xb4bd0000);
+ osd->DrawRectangle(xButton, yButton+20, xButton+237, yButton+21, 0xb4c20000);
+ osd->DrawRectangle(xButton, yButton+21, xButton+237, yButton+23, 0xb4cd0000);
+ osd->DrawRectangle(xButton+1, yButton+23, xButton+237, yButton+24, 0xb4d80000);
+ osd->DrawRectangle(xButton+1, yButton+24, xButton+236, yButton+25, 0xb4d80000);
+ osd->DrawRectangle(xButton+1, yButton+25, xButton+236, yButton+26, 0xb4d80000);
+ osd->DrawRectangle(xButton+2, yButton+26, xButton+235, yButton+27, 0xb4e20000);
+ osd->DrawRectangle(xButton+3, yButton+27, xButton+235, yButton+28, 0xb4e20000);
+ osd->DrawRectangle(xButton+3, yButton+28, xButton+234, yButton+29, 0xb4ef0000);
+ osd->DrawRectangle(xButton+4, yButton+29, xButton+233, yButton+30, 0xb4ef0000);
+ osd->DrawRectangle(xButton+5, yButton+30, xButton+232, yButton+31, 0xb4ef0000);
+ osd->DrawRectangle(xButton+6, yButton+31, xButton+231, yButton+32, 0xb4f80000);
+ osd->DrawRectangle(xButton+8, yButton+32, xButton+229, yButton+33, 0xb4f80000);
+ osd->DrawRectangle(xButton+10, yButton+33, xButton+227, yButton+34, 0xb4f80000);
+}
+
+void cSkinPearlHDDisplayChannel::DrawGreenButton(int xButton, int yButton)
+{
+ osd->DrawRectangle(xButton, yButton, xButton+237, yButton+2, 0xb4006400);
+ osd->DrawRectangle(xButton, yButton+2, xButton+237, yButton+5, 0xb4006d00);
+ osd->DrawRectangle(xButton, yButton+5, xButton+237, yButton+6, 0xb4007400);
+ osd->DrawRectangle(xButton, yButton+6, xButton+237, yButton+8, 0xb4007c00);
+ osd->DrawRectangle(xButton, yButton+8, xButton+237, yButton+9, 0xb4008100);
+ osd->DrawRectangle(xButton, yButton+9, xButton+237, yButton+11, 0xb4008600);
+ osd->DrawRectangle(xButton, yButton+10, xButton+237, yButton+11, 0xb4008b00);
+ osd->DrawRectangle(xButton, yButton+11, xButton+237, yButton+12, 0xb4009000);
+ osd->DrawRectangle(xButton, yButton+12, xButton+237, yButton+13, 0xb4009600);
+ osd->DrawRectangle(xButton, yButton+13, xButton+237, yButton+14, 0xb4009b00);
+ osd->DrawRectangle(xButton, yButton+14, xButton+237, yButton+15, 0xb400a100);
+ osd->DrawRectangle(xButton, yButton+15, xButton+237, yButton+16, 0xb400a600);
+ osd->DrawRectangle(xButton, yButton+16, xButton+237, yButton+17, 0xb400ac00);
+ osd->DrawRectangle(xButton, yButton+17, xButton+237, yButton+18, 0xb400b200);
+ osd->DrawRectangle(xButton, yButton+18, xButton+237, yButton+19, 0xb400b700);
+ osd->DrawRectangle(xButton, yButton+19, xButton+237, yButton+20, 0xb400bd00);
+ osd->DrawRectangle(xButton, yButton+20, xButton+237, yButton+21, 0xb400c200);
+ osd->DrawRectangle(xButton, yButton+21, xButton+237, yButton+22, 0xb400c800);
+ osd->DrawRectangle(xButton, yButton+22, xButton+237, yButton+23, 0xb400cd00);
+ osd->DrawRectangle(xButton+1, yButton+23, xButton+237, yButton+24, 0xb400d300);
+ osd->DrawRectangle(xButton+1, yButton+24, xButton+236, yButton+25, 0xb400d800);
+ osd->DrawRectangle(xButton+1, yButton+25, xButton+236, yButton+26, 0xb400dd00);
+ osd->DrawRectangle(xButton+2, yButton+26, xButton+235, yButton+27, 0xb400e200);
+ osd->DrawRectangle(xButton+3, yButton+27, xButton+235, yButton+28, 0xb400e200);
+ osd->DrawRectangle(xButton+3, yButton+28, xButton+234, yButton+29, 0xb400ef00);
+ osd->DrawRectangle(xButton+4, yButton+29, xButton+233, yButton+30, 0xb400ef00);
+ osd->DrawRectangle(xButton+5, yButton+30, xButton+232, yButton+31, 0xb400ef00);
+ osd->DrawRectangle(xButton+6, yButton+31, xButton+231, yButton+32, 0xb400f800);
+ osd->DrawRectangle(xButton+8, yButton+32, xButton+229, yButton+33, 0xb400f800);
+ osd->DrawRectangle(xButton+10, yButton+33, xButton+227, yButton+34, 0xb400f800);
+}
+
+void cSkinPearlHDDisplayChannel::DrawYellowButton(int xButton, int yButton)
+{
+ osd->DrawRectangle(xButton, yButton, xButton+237, yButton+3, 0xb4666600);
+ osd->DrawRectangle(xButton, yButton+3, xButton+237, yButton+4, 0xb46d6d00);
+ osd->DrawRectangle(xButton, yButton+4, xButton+237, yButton+6, 0xb4707000);
+ osd->DrawRectangle(xButton, yButton+6, xButton+237, yButton+8, 0xb47c7c00);
+ osd->DrawRectangle(xButton, yButton+8, xButton+237, yButton+10, 0xb4868600);
+ osd->DrawRectangle(xButton, yButton+10, xButton+237, yButton+11, 0xb48b8b00);
+ osd->DrawRectangle(xButton, yButton+11, xButton+237, yButton+12, 0xb4909000);
+ osd->DrawRectangle(xButton, yButton+12, xButton+237, yButton+14, 0xb49b9b00);
+ osd->DrawRectangle(xButton, yButton+14, xButton+237, yButton+16, 0xb4a6a600);
+ osd->DrawRectangle(xButton, yButton+16, xButton+237, yButton+17, 0xb4acac00);
+ osd->DrawRectangle(xButton, yButton+17, xButton+237, yButton+19, 0xb4b7b700);
+ osd->DrawRectangle(xButton, yButton+19, xButton+237, yButton+20, 0xb4bdbd00);
+ osd->DrawRectangle(xButton, yButton+20, xButton+237, yButton+21, 0xb4c2c200);
+ osd->DrawRectangle(xButton, yButton+21, xButton+237, yButton+23, 0xb4cdcd00);
+ osd->DrawRectangle(xButton+1, yButton+23, xButton+237, yButton+24, 0xb4d3d300);
+ osd->DrawRectangle(xButton+1, yButton+24, xButton+236, yButton+25, 0xb4d8d800);
+ osd->DrawRectangle(xButton+1, yButton+25, xButton+236, yButton+26, 0xb4dddd00);
+ osd->DrawRectangle(xButton+2, yButton+26, xButton+235, yButton+27, 0xb4e2e200);
+ osd->DrawRectangle(xButton+3, yButton+27, xButton+235, yButton+28, 0xb4e2e200);
+ osd->DrawRectangle(xButton+3, yButton+28, xButton+234, yButton+29, 0xb4efef00);
+ osd->DrawRectangle(xButton+4, yButton+29, xButton+233, yButton+30, 0xb4efef00);
+ osd->DrawRectangle(xButton+5, yButton+30, xButton+232, yButton+31, 0xb4efef00);
+ osd->DrawRectangle(xButton+6, yButton+31, xButton+231, yButton+32, 0xb4f8f800);
+ osd->DrawRectangle(xButton+8, yButton+32, xButton+229, yButton+33, 0xb4f8f800);
+ osd->DrawRectangle(xButton+10, yButton+33, xButton+227, yButton+34, 0xb4f8f800);
+}
+
+void cSkinPearlHDDisplayChannel::DrawBlueButton(int xButton, int yButton)
+{
+ osd->DrawRectangle(xButton, yButton, xButton+237, yButton+4, 0xb4000068);
+ osd->DrawRectangle(xButton, yButton+4, xButton+237, yButton+6, 0xb4000072);
+ osd->DrawRectangle(xButton, yButton+6, xButton+237, yButton+8, 0xb400007a);
+ osd->DrawRectangle(xButton, yButton+8, xButton+237, yButton+11, 0xb4000086);
+ osd->DrawRectangle(xButton, yButton+11, xButton+237, yButton+14, 0xb4000096);
+ osd->DrawRectangle(xButton, yButton+14, xButton+237, yButton+16, 0xb40000a4);
+ osd->DrawRectangle(xButton, yButton+16, xButton+237, yButton+17, 0xb40000ac);
+ osd->DrawRectangle(xButton, yButton+17, xButton+237, yButton+19, 0xb40000b5);
+ osd->DrawRectangle(xButton, yButton+19, xButton+237, yButton+20, 0xb40000bd);
+ osd->DrawRectangle(xButton, yButton+20, xButton+237, yButton+21, 0xb40000c2);
+ osd->DrawRectangle(xButton, yButton+21, xButton+237, yButton+23, 0xb40000cb);
+ osd->DrawRectangle(xButton+1, yButton+23, xButton+237, yButton+24, 0xb40000d8);
+ osd->DrawRectangle(xButton+1, yButton+24, xButton+236, yButton+25, 0xb40000d8);
+ osd->DrawRectangle(xButton+1, yButton+25, xButton+236, yButton+26, 0xb40000d8);
+ osd->DrawRectangle(xButton+2, yButton+26, xButton+235, yButton+27, 0xb40000e4);
+ osd->DrawRectangle(xButton+3, yButton+27, xButton+235, yButton+28, 0xb40000e4);
+ osd->DrawRectangle(xButton+3, yButton+28, xButton+234, yButton+29, 0xb40000ee);
+ osd->DrawRectangle(xButton+4, yButton+29, xButton+233, yButton+30, 0xb40000ee);
+ osd->DrawRectangle(xButton+5, yButton+30, xButton+232, yButton+31, 0xb40000ee);
+ osd->DrawRectangle(xButton+6, yButton+31, xButton+231, yButton+32, 0xb40000f8);
+ osd->DrawRectangle(xButton+8, yButton+32, xButton+229, yButton+33, 0xb40000f8);
+ osd->DrawRectangle(xButton+10, yButton+33, xButton+227, yButton+34, 0xb40000f8);
+}
+
+void cSkinPearlHDDisplayChannel::DrawCryptSymbol(int xSymbol, int ySymbol, const char *Text, tColor color, tColor bgcolor)
+{
+ osd->DrawRectangle (xSymbol, ySymbol, xSymbol+25, ySymbol+20, color);
+ osd->DrawRectangle (xSymbol+1, ySymbol+1, xSymbol+24, ySymbol+19, bgcolor);
+ osd->DrawText (xSymbol+2, ySymbol+5, Text, color, clrTransparent, fontCryptSymbols, 22, 0, taCenter);
+}
+
+// --- cSkinPearlHDDisplayMenu -------------------------------------------------
+
+class cSkinPearlHDDisplayMenu : public cSkinDisplayMenu {
+private:
+ cOsd *osd;
+ int x1Menu, x2Menu, y1Menu, y2Menu;
+ int x1Scrollbar, x2Scrollbar, y1Scrollbar, y2Scrollbar;
+ int rightSmall, rightBig;
+ int lineHeight;
+ tColor frameColor;
+ int currentIndex;
+ bool message;
+ cString lastDate;
+ void DrawScrollbar(int Total, int Offset, int Shown, int Top, int Height, bool CanScrollUp, bool CanScrollDown);
+ void SetTextScrollbar(void);
+ const cFont *fontSansBook15;
+ const cFont *fontSansBook20;
+ const cFont *fontSansBook22;
+ const cFont *fontSansBook27;
+ const cFont *fontSansBook37;
+ const cFont *fontSansBook57;
+ const cFont *fontSansBold27;
+ const cFont *fontSansBold37;
+ int menuType;
+ int bpp;
+ unsigned long blinkNext;
+ int blinkState;
+ const cBitmap *bRecTitleHead;
+ const char *MenuTitleClean(std::string Title);
+ const char *MenuTitleRest(std::string Title);
+ void DrawHeader();
+ void DrawRedButton(int xButton, int yButton);
+ void DrawGreenButton(int xButton, int yButton);
+ void DrawYellowButton(int xButton, int yButton);
+ void DrawBlueButton(int xButton, int yButton);
+ int GetRecordingLength(const char *FileName, double FramesPerSecond, bool IsPesRecording);
+ int GetRecordingCuttedLength(const char *FileName, double FramesPerSecond, bool IsPesRecording);
+public:
+ cSkinPearlHDDisplayMenu(void);
+ virtual ~cSkinPearlHDDisplayMenu();
+ virtual void Scroll(bool Up, bool Page);
+ virtual int MaxItems(void);
+ virtual void Clear(void);
+ virtual void SetTitle(const char *Title);
+ virtual void SetButtons(const char *Red, const char *Green = NULL, const char *Yellow = NULL, const char *Blue = NULL);
+ virtual void SetMessage(eMessageType Type, const char *Text);
+ virtual void SetItem(const char *Text, int Index, bool Current, bool Selectable);
+ virtual void SetEvent(const cEvent *Event);
+ virtual void SetRecording(const cRecording *Recording);
+ virtual void SetText(const char *Text, bool FixedFont);
+ virtual int GetTextAreaWidth(void) const;
+ virtual const cFont *GetTextAreaFont(bool FixedFont) const;
+ virtual void Flush(void);
+ };
+
+cSkinPearlHDDisplayMenu::cSkinPearlHDDisplayMenu(void)
+{
+ bpp=0;
+ lineHeight = PearlHDConfig.LineHeight;
+ currentIndex = -1;
+ message = false;
+ x1Menu = PearlHDConfig.MenuPaddingWidth;
+ x2Menu = cOsd::OsdWidth() - PearlHDConfig.MenuPaddingWidth;
+ y1Menu = PearlHDConfig.MenuPaddingHeight;
+ y2Menu = cOsd::OsdHeight() - PearlHDConfig.MenuPaddingHeight;
+ fontSansBook15 = cFont::CreateFont("VDRSymbols Sans:Book", 15);
+ fontSansBook20 = cFont::CreateFont("VDRSymbols Sans:Book", 20);
+ fontSansBook22 = cFont::CreateFont("VDRSymbols Sans:Book", 22);
+ fontSansBook27 = cFont::CreateFont("VDRSymbols Sans:Book", 27);
+ fontSansBook37 = cFont::CreateFont("VDRSymbols Sans:Book", 37);
+ fontSansBook57 = cFont::CreateFont("VDRSymbols Sans:Book", 57);
+ fontSansBold27 = cFont::CreateFont("VDRSymbols Sans:Bold", 27);
+ fontSansBold37 = cFont::CreateFont("VDRSymbols Sans:Bold", 37);
+ menuType = 0;
+ blinkNext=0;
+ blinkState=0;
+
+ osd = cOsdProvider::NewOsd(cOsd::OsdLeft(), cOsd::OsdTop());
+ tArea Areas[] = { { 0, 0, cOsd::OsdWidth() - 1, cOsd::OsdHeight() - 1, 32 } };
+ if (osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
+ {
+ bpp=24;
+ osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
+ }
+ else
+ {
+ tArea Areas[] = { { 0, 0, cOsd::OsdWidth() - 1, y2Menu, 8 },
+ { x2Menu - 957, y2Menu + 1, x2Menu - 478, cOsd::OsdHeight() - 1, 8 },
+ { x2Menu - 477, y2Menu + 1, x2Menu - 1, cOsd::OsdHeight() - 1, 8 } }; // 256 colors
+ if (osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
+ {
+ bpp=8;
+ osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
+ }
+ }
+ osd->DrawRectangle(1,1,1,1, clrTransparent);
+ osd->DrawRectangle(x2Menu-957, y2Menu+1, x2Menu-957, y2Menu+1, clrTransparent);
+ osd->DrawRectangle(x2Menu-477, y2Menu+1, x2Menu-477, y2Menu+1, clrTransparent);
+}
+
+cSkinPearlHDDisplayMenu::~cSkinPearlHDDisplayMenu()
+{
+ delete osd;
+}
+
+void cSkinPearlHDDisplayMenu::DrawScrollbar(int Total, int Offset, int Shown, int Top, int Height, bool CanScrollUp, bool CanScrollDown)
+{
+ if (Total > 0 && Total > Shown) {
+ int th = int((y2Scrollbar - y1Scrollbar) * double(Shown) / Total + 0.5);
+ int tt = int(y1Scrollbar + (y2Scrollbar - y1Scrollbar) * double(Offset) / Total + 0.5);
+ int tb = tt + th;
+ osd->DrawRectangle(x1Scrollbar, y1Scrollbar, x2Scrollbar, y2Scrollbar, Theme.Color(clrBar));
+ osd->DrawRectangle(x1Scrollbar, tt, x2Scrollbar, tb - 1, Theme.Color(clrBarFill));
+ }
+}
+
+void cSkinPearlHDDisplayMenu::SetTextScrollbar(void)
+{
+ if (textScroller.CanScroll())
+ {
+ DrawScrollbar(textScroller.Total(), textScroller.Offset(), textScroller.Shown(), textScroller.Top(), textScroller.Height(), textScroller.CanScrollUp(), textScroller.CanScrollDown());
+ }
+}
+
+void cSkinPearlHDDisplayMenu::Scroll(bool Up, bool Page)
+{
+ cSkinDisplayMenu::Scroll(Up, Page);
+ SetTextScrollbar();
+}
+
+int cSkinPearlHDDisplayMenu::MaxItems(void)
+{
+ return ( ((y2Menu-84) - (y1Menu+175)) / lineHeight);
+}
+
+void cSkinPearlHDDisplayMenu::Clear(void)
+{
+ textScroller.Reset();
+}
+
+void cSkinPearlHDDisplayMenu::SetTitle(const char *Title)
+{
+ if (strcmp(trVDR("VDR"), MenuTitleClean(Title)) == 0)
+ menuType = MENU_TYPE_VDR;
+ else if (strcmp(trVDR("Commands"), MenuTitleClean(Title)) == 0)
+ menuType = MENU_TYPE_VDR;
+ else if (strcmp(trVDR("Schedule"), MenuTitleClean(Title)) == 0)
+ menuType = MENU_TYPE_SCHEDULE;
+ else if (strcmp(trVDR("Channels"), MenuTitleClean(Title)) == 0)
+ menuType = MENU_TYPE_SCHEDULE;
+ else if (strcmp(trVDR("Setup"), MenuTitleClean(Title)) == 0)
+ menuType = MENU_TYPE_SCHEDULE;
+ else if (strcmp(trVDR("Edit timer"), MenuTitleClean(Title)) == 0)
+ menuType = MENU_TYPE_SCHEDULE;
+ else if (strcmp(trVDR("Recordings"), MenuTitleClean(Title)) == 0)
+ menuType = MENU_TYPE_RECORDINGS;
+ else if (strcmp(trVDR("Timers"), MenuTitleClean(Title)) == 0)
+ menuType = MENU_TYPE_RECORDINGS;
+ else
+ menuType = -1;
+
+ DrawHeader();
+
+ switch (menuType)
+ {
+ case MENU_TYPE_VDR :
+ //Sub Menu VDR, Commands
+ osd->DrawRectangle(x1Menu, y1Menu+117, x2Menu-480, y2Menu, Theme.Color(clrMainLight));
+
+ // Background right
+ osd->DrawRectangle(x2Menu-479, y1Menu+117, x2Menu, y2Menu, Theme.Color(clrMainSolid));
+ osd->DrawText(x2Menu-479, y2Menu-55, MenuTitleRest(Title), Theme.Color(clrFontColor), Theme.Color(clrMainSolid), fontSansBook27, 449, 0, taRight);
+ break;
+
+ case MENU_TYPE_SCHEDULE :
+ // Sub Menu Schedule, Channels, Setup, Edit timer
+ osd->DrawRectangle(x1Menu, y1Menu+117, x2Menu-360, y2Menu, Theme.Color(clrMainLight));
+
+ //Background Right
+ osd->DrawRectangle(x2Menu-360, y1Menu+117, x2Menu, y2Menu, Theme.Color(clrMainSolid));
+ osd->DrawText(x2Menu-360, y2Menu-55, MenuTitleRest(Title), Theme.Color(clrFontColor), Theme.Color(clrMainSolid), fontSansBook27, 330, 0, taRight);
+ osd->DrawText(x1Menu+75, y1Menu+60, Title, Theme.Color(clrFontColor), clrTransparent, fontSansBook37);
+ break;
+
+ default :
+ //Sub Menu Default
+ osd->DrawRectangle(x1Menu, y1Menu+117, x2Menu, y2Menu, Theme.Color(clrMainLight));
+ osd->DrawText(x1Menu+75, y1Menu+60, MenuTitleClean(Title), Theme.Color(clrFontColor), clrTransparent, fontSansBook37);
+ break;
+ }
+}
+
+void cSkinPearlHDDisplayMenu::SetButtons(const char *Red, const char *Green, const char *Yellow, const char *Blue)
+{
+ if (Red)
+ {
+ DrawRedButton(x2Menu-957, y2Menu);
+ osd->DrawText(x2Menu-957, y2Menu+1, Red, Theme.Color(clrMessageWhite), clrTransparent, fontSansBook27, 239, 0, taCenter);
+ }
+ else
+ osd->DrawRectangle(x2Menu-957, y2Menu, x2Menu-718, y2Menu+35, clrTransparent);
+
+ if (Green)
+ {
+ DrawGreenButton(x2Menu-717, y2Menu);
+ osd->DrawText(x2Menu-717, y2Menu+1, Green, Theme.Color(clrMessageBlack), clrTransparent, fontSansBook27, 237, 0, taCenter);
+ }
+ else
+ osd->DrawRectangle(x2Menu-717, y2Menu, x2Menu-478, y2Menu+35, clrTransparent);
+
+ if (Yellow)
+ {
+ DrawYellowButton(x2Menu-477, y2Menu);
+ osd->DrawText(x2Menu-477, y2Menu+1, Yellow, Theme.Color(clrMessageBlack), clrTransparent, fontSansBook27, 241, 0, taCenter);
+ }
+ else
+ osd->DrawRectangle(x2Menu-477, y2Menu, x2Menu-238, y2Menu+35, clrTransparent);
+
+ if (Blue)
+ {
+ DrawBlueButton(x2Menu-237, y2Menu);
+ osd->DrawText(x2Menu-237, y2Menu+1, Blue, Theme.Color(clrMessageWhite), clrTransparent, fontSansBook27, 237, 0, taCenter);
+ }
+ else
+ osd->DrawRectangle(x2Menu-237, y2Menu, x2Menu, y2Menu+35, clrTransparent);
+}
+
+void cSkinPearlHDDisplayMenu::SetMessage(eMessageType Type, const char *Text)
+{
+ if (Text) {
+ tColor color;
+ int MessageX2;
+ switch (Type) {
+ case mtInfo :
+ color = Theme.Color(clrMainSolid);
+ break;
+ case mtStatus :
+ color = Theme.Color(clrStatus);
+ break;
+ case mtWarning :
+ color = Theme.Color(clrWarning);
+ break;
+ case mtError :
+ color = Theme.Color(clrError);
+ break;
+ }
+ switch (menuType) {
+ case MENU_TYPE_VDR :
+ MessageX2 = x2Menu-479;
+ break;
+ case MENU_TYPE_SCHEDULE :
+ MessageX2 = x2Menu-360;
+ break;
+ default :
+ MessageX2 = x2Menu;
+ }
+ osd->SaveRegion(x1Menu, y1Menu+117, MessageX2, y1Menu+158);
+ osd->DrawRectangle(x1Menu, y1Menu+117, MessageX2, y1Menu+158, color);
+ osd->DrawText(x1Menu+75, y1Menu+122, Text, Theme.Color(clrMessageWhite), clrTransparent, fontSansBook27);
+ }
+ else {
+ osd->RestoreRegion();
+ message = false;
+ }
+}
+
+void cSkinPearlHDDisplayMenu::SetItem(const char *Text, int Index, bool Current, bool Selectable)
+{
+ int x1Item;
+ int y1Item;
+ int x2Item;
+ int y2Item;
+ switch (menuType)
+ {
+ case MENU_TYPE_VDR :
+ x1Item = x1Menu;
+ y1Item = y1Menu+175 + (lineHeight * Index);
+ x2Item = x2Menu-480;
+ y2Item = y1Item + lineHeight;
+ break;
+ case MENU_TYPE_SCHEDULE :
+ x1Item = x1Menu;
+ y1Item = y1Menu+175 + (lineHeight * Index);
+ x2Item = x2Menu-360;
+ y2Item = y1Item + lineHeight;
+ break;
+ default :
+ x1Item = x1Menu;
+ y1Item = y1Menu+175 + (lineHeight * Index);
+ x2Item = x2Menu;
+ y2Item = y1Item + lineHeight;
+ }
+ if (Current) {
+ osd->DrawRectangle(x1Item+74, y1Item, x2Item-1, y2Item-6, Theme.Color(clrMainSolid));
+ osd->DrawEllipse(x1Item+60, y1Item, x1Item+74, y1Item+15, Theme.Color(clrMainSolid), 2);
+ osd->DrawRectangle(x1Item+60, y1Item+14, x1Item+74, y2Item-21, Theme.Color(clrMainSolid));
+ osd->DrawEllipse(x1Item+60, y2Item-21, x1Item+74, y2Item-6, Theme.Color(clrMainSolid), 3);
+ }
+ else {
+ osd->DrawRectangle(x1Item+74, y1Item, x2Item-1, y2Item-6, Theme.Color(clrLoLight));
+ osd->DrawEllipse(x1Item+60, y1Item, x1Item+74, y1Item+15, Theme.Color(clrLoLight), 2);
+ osd->DrawRectangle(x1Item+60, y1Item+14, x1Item+74, y2Item-21, Theme.Color(clrLoLight));
+ osd->DrawEllipse(x1Item+60, y2Item-21, x1Item+74, y2Item-6, Theme.Color(clrLoLight), 3);
+ }
+
+ for (int i = 0; i < MaxTabs; i++) {
+ const char *s = GetTabbedText(Text, i);
+ if (s) {
+ int xt = x1Item+75 + Tab(i);
+ osd->DrawText(xt, y1Item+4, s, Current ? Theme.Color(clrFontColor) : Theme.Color(clrFontColorInactive), clrTransparent, fontSansBook27, x2Item - xt - 4);
+ }
+ if (!Tab(i + 1))
+ break;
+ }
+ SetEditableWidth(Tab(1));
+}
+
+void cSkinPearlHDDisplayMenu::SetEvent(const cEvent *Event)
+{
+ if (!Event)
+ return;
+
+ menuType = MENU_TYPE_EVENT;
+
+ DrawHeader();
+
+ osd->DrawRectangle(x1Menu, y1Menu+117, x2Menu-360, y2Menu, Theme.Color(clrMainLight));
+ osd->DrawRectangle(x2Menu-360, y1Menu+117, x2Menu-1, y2Menu, Theme.Color(clrMainSolid));
+
+ if(PearlHDConfig.DisplayEpgImages)
+ {
+ char logoFormat[4];
+ switch (PearlHDConfig.EpgImagesFormat)
+ {
+ case 0:
+ snprintf(logoFormat, sizeof(logoFormat), "png");
+ break;
+ case 1:
+ snprintf(logoFormat, sizeof(logoFormat), "jpg");
+ break;
+ }
+
+ cOSDImageBitmap osdbitmap;
+ cBitmap epgImg (300, 225, bpp);
+
+ std::stringstream epgPath;
+ if (PearlHDConfig.EpgDirSet)
+ epgPath << PearlHDConfig.EpgImagesDir;
+ else
+ {
+ epgPath << cPlugin::ConfigDirectory() << "/tvm2vdr/epgimages";
+ }
+ epgPath << "/" << Event->EventID() << "." << logoFormat;
+ if(osdbitmap.Load(epgPath.str().c_str())){
+ osdbitmap.Render(epgImg, 300, 225, bpp, false);
+ osd->DrawBitmap(x2Menu-330, y2Menu-285, epgImg);
+ }
+ }
+
+ osd->DrawText(x1Menu+75, y1Menu+60, Event->Title(), Theme.Color(clrFontColor), clrTransparent, fontSansBook37);
+
+ char text[32];
+ snprintf(text, sizeof(text), "%s %s - %s", *Event->GetDateString(), *Event->GetTimeString(), *Event->GetEndTimeString());
+ osd->DrawText(x1Menu+75, y1Menu+310, text, Theme.Color(clrFontColor), clrTransparent, fontSansBook27);
+
+ if (Event->Vps())
+ {
+ snprintf(text, sizeof(text), "%d min | VPS: %s", Event->Duration() / 60, *Event->GetVpsString());
+ osd->DrawText(x1Menu+75, y1Menu+215, text, Theme.Color(clrFontColor), clrTransparent, fontSansBook20);
+ }
+ else
+ {
+ snprintf(text, sizeof(text), "%d min", Event->Duration() / 60);
+ osd->DrawText(x1Menu+75, y1Menu+235, text, Theme.Color(clrFontColor), clrTransparent, fontSansBook20);
+ }
+
+ //Scrollbar position
+ x1Scrollbar = x2Menu-380;
+ x2Scrollbar = x2Menu - 360;
+ y1Scrollbar = y1Menu + 117;
+ y2Scrollbar = y2Menu - 1;
+
+ if (isempty(Event->Description()))
+ {
+ textScroller.Set (osd, x1Menu+75, y1Menu+170, x2Menu-510, y2Menu-1, Event->ShortText(), fontSansBold27, Theme.Color(clrFontColor), Theme.Color(clrMainLight));
+ }
+ else
+ {
+ osd->DrawText(x1Menu+75, y1Menu+270, Event->ShortText(), Theme.Color(clrFontColor), clrTransparent, fontSansBold27);
+ textScroller.Set (osd, x1Menu+75, y1Menu+347, (x2Menu-360-150) - (x1Menu+75), (y2Menu - 41) - (y1Menu + 347), Event->Description(), fontSansBook27, Theme.Color(clrFontColor), Theme.Color(clrMainLight));
+ }
+ SetTextScrollbar();
+}
+
+void cSkinPearlHDDisplayMenu::SetRecording(const cRecording *Recording)
+{
+ if (!Recording)
+ return;
+
+ menuType = MENU_TYPE_RECORDING;
+ DrawHeader();
+
+ const cRecordingInfo *Info = Recording->Info();
+ osd->DrawRectangle(x1Menu, y1Menu+117, x2Menu-360, y2Menu, Theme.Color(clrMainLight));
+
+ osd->DrawRectangle(x2Menu-360, y1Menu+117, x2Menu-1, y2Menu, Theme.Color(clrMainSolid));
+
+ osd->DrawText(x1Menu+75, y1Menu+60, Info->Title(), Theme.Color(clrFontColor), clrTransparent, fontSansBold37);
+
+ char text[32];
+ snprintf(text, sizeof(text), "%s %s", *DateString(Recording->start), *TimeString(Recording->start));
+ osd->DrawText(x1Menu+75, y1Menu+175, text, Theme.Color(clrFontColor), clrTransparent, fontSansBook27);
+
+ int RecordingLength, RecordingCuttedLength;
+ #if VDRVERSNUM >= 10703
+ RecordingLength = GetRecordingLength(Recording->FileName(), Recording->FramesPerSecond(), Recording->IsPesRecording());
+ RecordingCuttedLength = GetRecordingCuttedLength(Recording->FileName(), Recording->FramesPerSecond(), Recording->IsPesRecording());
+ #else
+ RecordingLength = GetRecordingLength(Recording->FileName(), FRAMESPERSEC, true);
+ RecordingCuttedLength = GetRecordingCuttedLength(Recording->FileName(), FRAMESPERSEC, true);
+ #endif
+ char length[50];
+ snprintf(length, sizeof(length), "%d min | %s: %d min", RecordingLength, tr("cutted"), RecordingCuttedLength);
+ osd->DrawText(x1Menu+75, y1Menu+215, length, Theme.Color(clrFontColor), clrTransparent, fontSansBook20);
+
+ //Scrollbar position
+ x1Scrollbar = x2Menu-380;
+ x2Scrollbar = x2Menu-360;
+ y1Scrollbar = y1Menu+117;
+ y2Scrollbar = y2Menu-1;
+
+ if (isempty(Info->Description()))
+ {
+ textScroller.Set (osd, x1Menu+75, y1Menu+270, (x2Menu-510) - (x1Menu+75), (y2Menu-1) - (y1Menu+270), Info->ShortText(), fontSansBook27, Theme.Color(clrFontColor), Theme.Color(clrMainLight));
+ }
+
+ if (isempty(Info->ShortText()))
+ osd->DrawText(x1Menu+75, y1Menu+290, Info->Title(), Theme.Color(clrFontColor), clrTransparent, fontSansBook27);
+
+ if (!isempty(Info->Description()))
+ {
+ osd->DrawText(x1Menu+75, y1Menu+290, Info->ShortText(), Theme.Color(clrFontColor), clrTransparent, fontSansBook27);
+ textScroller.Set (osd, x1Menu+75, y1Menu+347, (x2Menu-510) - (x1Menu+75), (y2Menu-41) - (y1Menu+347), Info->Description(), fontSansBook27, Theme.Color(clrFontColor), Theme.Color(clrMainLight));
+ }
+
+ SetTextScrollbar();
+}
+
+void cSkinPearlHDDisplayMenu::SetText(const char *Text, bool FixedFont)
+{
+ //Scrollbar position
+ x1Scrollbar = x2Menu - 20;
+ x2Scrollbar = x2Menu;
+ y1Scrollbar = y1Menu + 117;
+ y2Scrollbar = y2Menu - 1;
+
+ textScroller.Set (osd, x1Menu+75, y1Menu+175, (x2Menu-40) - (x1Menu+75), (y2Menu-60) - (y1Menu+175), Text, fontSansBook27, Theme.Color(clrFontColor), Theme.Color(clrMainLight));
+ SetTextScrollbar();
+}
+
+int cSkinPearlHDDisplayMenu::GetTextAreaWidth(void) const
+{
+ return (x2Menu-40) - (x1Menu+75);
+}
+
+const cFont *cSkinPearlHDDisplayMenu::GetTextAreaFont(bool FixedFont) const
+{
+ return fontSansBook27;
+}
+
+void cSkinPearlHDDisplayMenu::Flush(void)
+{
+ char datestring[50];
+ struct tm tm_r;
+ time_t t;
+ time(&t);
+ tm *tmt = localtime_r(&t, &tm_r);
+ strftime(datestring, sizeof(datestring), "%d.%m.%Y", tmt);
+
+ int oClockWidth = 0;
+ switch (menuType)
+ {
+ case MENU_TYPE_VDR :
+ if (PearlHDConfig.oClockText)
+ {
+ oClockWidth = fontSansBook27->Width(tr("oClock")) + 10;
+ osd->DrawText(x2Menu-479, y1Menu+146, tr("oClock"), Theme.Color(clrFontColor), Theme.Color(clrMainSolid), fontSansBook27, 449, 0, taRight);
+ }
+ osd->DrawText(x2Menu-479, y1Menu+136, *TimeString(t), Theme.Color(clrFontColor), Theme.Color(clrMainSolid), fontSansBook37, 449-oClockWidth, 0, taRight);
+ osd->DrawText(x2Menu-479, y1Menu+187, *WeekDayNameFull(t), Theme.Color(clrFontColor), Theme.Color(clrMainSolid), fontSansBook27, 449, 0, taRight);
+ osd->DrawText(x2Menu-479, y1Menu+225, datestring, Theme.Color(clrFontColor), Theme.Color(clrMainSolid), fontSansBook20, 449, 0, taRight);
+ break;
+
+ case MENU_TYPE_SCHEDULE :
+ case MENU_TYPE_RECORDING :
+ case MENU_TYPE_EVENT :
+ if (PearlHDConfig.oClockText)
+ {
+ oClockWidth = fontSansBook27->Width(tr("oClock")) + 10;
+ osd->DrawText(x2Menu-360, y1Menu+146, tr("oClock"), Theme.Color(clrFontColor), Theme.Color(clrMainSolid), fontSansBook27, 330, 0, taRight);
+ }
+ osd->DrawText(x2Menu-360, y1Menu+136, *TimeString(t), Theme.Color(clrFontColor), Theme.Color(clrMainSolid), fontSansBook37, 330-oClockWidth, 0, taRight);
+ osd->DrawText(x2Menu-360, y1Menu+187, *WeekDayNameFull(t), Theme.Color(clrFontColor), Theme.Color(clrMainSolid), fontSansBook27, 330, 0, taRight);
+ osd->DrawText(x2Menu-360, y1Menu+225, datestring, Theme.Color(clrFontColor), Theme.Color(clrMainSolid), fontSansBook20, 330, 0, taRight);
+ break;
+
+ case MENU_TYPE_RECORDINGS :
+ if (!PearlHDConfig.RecShowClock)
+ break;
+ if (PearlHDConfig.oClockText)
+ {
+ oClockWidth = fontSansBook27->Width(tr("oClock")) + 10;
+ osd->DrawText(x2Menu-90, y2Menu-55, tr("oClock"), Theme.Color(clrFontColor), Theme.Color(clrMainLight), fontSansBook27, 60, 0, taRight);
+ }
+ osd->DrawText(x2Menu-300, y2Menu-55, *TimeString(t), Theme.Color(clrFontColor), Theme.Color(clrMainLight), fontSansBook27, 270-oClockWidth, 0, taRight);
+ break;
+ }
+
+ if (PearlHDConfig.RecTitleInfoHead && menuType == MENU_TYPE_VDR && cRecordControls::Active())
+ {
+ cTimer *t = Timers.First();
+ std::string RecTitleHeadString = "";
+ Timers.SetEvents();
+ bool bFirst = true;
+ for (; t != NULL; t = Timers.Next(t))
+ {
+ if (t->Recording())
+ {
+ const cEvent *tevent = t->Event();
+ if (tevent)
+ {
+ if (!bFirst)
+ {
+ RecTitleHeadString += " - ";
+ }
+ else
+ bFirst = false;
+ RecTitleHeadString += tevent->Title();
+ }
+ }
+ }
+ osd->DrawEllipse(x1Menu+95, y1Menu+78, x1Menu+110, y1Menu+93, Theme.Color(clrError));
+ //TODO Marquee
+ osd->DrawText(x1Menu+127, y1Menu+70, RecTitleHeadString.c_str(), Theme.Color(clrFontColor), Theme.Color(clrMainSolid), fontSansBook27, (x2Menu-479) - (x1Menu+127), 0, taLeft);
+ }
+
+ if ((PearlHDConfig.RecTitleInfo != 0) && menuType == MENU_TYPE_VDR)
+ {
+ int iEventCounter = 0;
+ int iNumTimers = 0;
+ int x1InfoBottom = x2Menu-479;
+ int x2InfoBottom = x2Menu;
+ int y1InfoBottom;
+
+ if (PearlHDConfig.RecTitleInfo == 2)
+ y1InfoBottom = y1Menu+660;
+ else
+ y1InfoBottom = y1Menu+410;
+
+ int iEventHeight = 50;
+ cTimer *t = Timers.First();
+ Timers.SetEvents();
+
+ for (; t != NULL; t = Timers.Next(t))
+ iNumTimers++;
+ t = Timers.First();
+
+ if ((PearlHDConfig.RecTitleInfo == 2) && iNumTimers < 3)
+ y1InfoBottom += (iEventHeight * iNumTimers);
+
+ for (; t != NULL; t = Timers.Next(t))
+ {
+ osd->DrawRectangle(x1InfoBottom+14, y1InfoBottom, x2InfoBottom-1, y1InfoBottom+45, Theme.Color(clrMainSolidOverlay));
+ osd->DrawEllipse(x1InfoBottom, y1InfoBottom, x1InfoBottom+14, y1InfoBottom+15, Theme.Color(clrMainSolidOverlay), 2);
+ osd->DrawRectangle(x1InfoBottom, y1InfoBottom+14, x1InfoBottom+14, y1InfoBottom+31, Theme.Color(clrMainSolidOverlay));
+ osd->DrawEllipse(x1InfoBottom, y1InfoBottom+31, x1InfoBottom+14, y1InfoBottom+45, Theme.Color(clrMainSolidOverlay), 3);
+
+ std::stringstream st;
+ st << (t->Recording() ? t->Stop() : t->Start());
+ std::string timestring;
+ timestring = st.str();
+ timestring.insert(2, ":");
+ timestring += " / ";
+ timestring += t->Channel()->Name();
+
+ osd->DrawText(x1InfoBottom+20, y1InfoBottom+10, timestring.c_str(), Theme.Color(clrFontColor), Theme.Color(clrMainSolidOverlay), fontSansBook22, (x2InfoBottom-51) - (x1InfoBottom+20), 0, taRight);
+ osd->DrawText(x2InfoBottom-48, y1InfoBottom+6, t->Recording() ? "R" : "T", Theme.Color(t->Recording() ? clrError : clrStatus), Theme.Color(clrMainSolidOverlay), fontSansBook15, 17, 0, taRight);
+
+ y1InfoBottom += iEventHeight;
+ iEventCounter++;
+ if (iEventCounter == 3)
+ break;
+ }
+
+ cPlugin *p = cPluginManager::GetPlugin("epgsearch");
+ if ((PearlHDConfig.RecTitleInfo == 2) && p)
+ {
+ Epgsearch_lastconflictinfo_v1_0 *serviceData = new Epgsearch_lastconflictinfo_v1_0;
+ if (serviceData)
+ {
+ serviceData->nextConflict = 0;
+ serviceData->relevantConflicts = 0;
+ serviceData->totalConflicts = 0;
+
+ p->Service("Epgsearch-lastconflictinfo-v1.0", serviceData);
+ if (serviceData->totalConflicts > 0)
+ {
+ int delay = 2000;
+ if (cTimeMs::Now() > blinkNext)
+ {
+ char conflict[50];
+ snprintf(conflict, sizeof(conflict), "%d %s!", serviceData->totalConflicts, tr("Conflicting Timers"));
+ osd->DrawRectangle(x1InfoBottom+14, y1InfoBottom, x2InfoBottom-1, y1InfoBottom+45, Theme.Color(clrMainSolidOverlay));
+ osd->DrawEllipse(x1InfoBottom, y1InfoBottom, x1InfoBottom+14, y1InfoBottom+15, Theme.Color(clrMainSolidOverlay), 2);
+ osd->DrawRectangle(x1InfoBottom, y1InfoBottom+14, x1InfoBottom+14, y1InfoBottom+31, Theme.Color(clrMainSolidOverlay));
+ osd->DrawEllipse(x1InfoBottom, y1InfoBottom+31, x1InfoBottom+14, y1InfoBottom+45, Theme.Color(clrMainSolidOverlay), 3);
+ osd->DrawText(x1InfoBottom+20, y1InfoBottom+6, conflict, Theme.Color(blinkState ? clrError : clrFontColor), Theme.Color(clrMainSolidOverlay), fontSansBook22, (x2InfoBottom-31) - (x1InfoBottom+20), 0, taRight);
+ blinkNext = cTimeMs::Now() + delay;
+ blinkState = blinkState ^ 1;
+ }
+ }
+ }
+ }
+ }
+
+ osd->Flush();
+}
+
+const char *cSkinPearlHDDisplayMenu::MenuTitleClean(std::string Title)
+{
+ int pos = -1;
+ if ((pos = Title.find(" - ")) != -1) {
+ Title.erase(pos);
+ while (Title[Title.length() - 1] == ' ')
+ Title.erase(Title.length() - 1);
+ }
+ return Title.c_str();
+}
+
+const char *cSkinPearlHDDisplayMenu::MenuTitleRest(std::string Title)
+{
+ int pos = -1;
+ if ((pos = Title.find(" - ")) != -1) {
+ Title.erase(0, pos + 3);
+ while (Title[0] == ' ')
+ Title.erase(0, 1);
+ }
+ return Title.c_str();
+}
+
+void cSkinPearlHDDisplayMenu::DrawHeader()
+{
+ osd->DrawEllipse(x1Menu, y1Menu, x1Menu+50, y1Menu+50, Theme.Color(clrMainSolid), 2);
+ osd->DrawRectangle(x1Menu+50, y1Menu, x2Menu, y1Menu+50, Theme.Color(clrMainSolid));
+ osd->DrawRectangle(x1Menu, y1Menu+50, x2Menu, y1Menu+115, Theme.Color(clrMainSolid));
+ osd->DrawText(x2Menu-300, y1Menu+43, "VDR", Theme.Color(clrFontColor), clrTransparent, fontSansBook57, 232, 0, taRight);
+ osd->DrawText(x2Menu-300, y1Menu+50, "HD", Theme.Color(clrFontColor), clrTransparent, fontSansBook27, 270, 0, taRight);
+ osd->DrawRectangle(x1Menu, y1Menu+115, x2Menu, y1Menu+117, Theme.Color(clrDivider));
+}
+
+void cSkinPearlHDDisplayMenu::DrawRedButton(int xButton, int yButton)
+{
+ osd->DrawRectangle(xButton, yButton, xButton+237, yButton+4, 0xb4690000);
+ osd->DrawRectangle(xButton, yButton+4, xButton+237, yButton+6, 0xb4740000);
+ osd->DrawRectangle(xButton, yButton+6, xButton+237, yButton+8, 0xb47c0000);
+ osd->DrawRectangle(xButton, yButton+8, xButton+237, yButton+11, 0xb4860000);
+ osd->DrawRectangle(xButton, yButton+11, xButton+237, yButton+14, 0xb4960000);
+ osd->DrawRectangle(xButton, yButton+14, xButton+237, yButton+16, 0xb4a60000);
+ osd->DrawRectangle(xButton, yButton+16, xButton+237, yButton+17, 0xb4ac0000);
+ osd->DrawRectangle(xButton, yButton+17, xButton+237, yButton+19, 0xb4b70000);
+ osd->DrawRectangle(xButton, yButton+19, xButton+237, yButton+20, 0xb4bd0000);
+ osd->DrawRectangle(xButton, yButton+20, xButton+237, yButton+21, 0xb4c20000);
+ osd->DrawRectangle(xButton, yButton+21, xButton+237, yButton+23, 0xb4cd0000);
+ osd->DrawRectangle(xButton+1, yButton+23, xButton+237, yButton+24, 0xb4d80000);
+ osd->DrawRectangle(xButton+1, yButton+24, xButton+236, yButton+25, 0xb4d80000);
+ osd->DrawRectangle(xButton+1, yButton+25, xButton+236, yButton+26, 0xb4d80000);
+ osd->DrawRectangle(xButton+2, yButton+26, xButton+235, yButton+27, 0xb4e20000);
+ osd->DrawRectangle(xButton+3, yButton+27, xButton+235, yButton+28, 0xb4e20000);
+ osd->DrawRectangle(xButton+3, yButton+28, xButton+234, yButton+29, 0xb4ef0000);
+ osd->DrawRectangle(xButton+4, yButton+29, xButton+233, yButton+30, 0xb4ef0000);
+ osd->DrawRectangle(xButton+5, yButton+30, xButton+232, yButton+31, 0xb4ef0000);
+ osd->DrawRectangle(xButton+6, yButton+31, xButton+231, yButton+32, 0xb4f80000);
+ osd->DrawRectangle(xButton+8, yButton+32, xButton+229, yButton+33, 0xb4f80000);
+ osd->DrawRectangle(xButton+10, yButton+33, xButton+227, yButton+34, 0xb4f80000);
+}
+
+void cSkinPearlHDDisplayMenu::DrawGreenButton(int xButton, int yButton)
+{
+ osd->DrawRectangle(xButton, yButton, xButton+237, yButton+2, 0xb4006400);
+ osd->DrawRectangle(xButton, yButton+2, xButton+237, yButton+5, 0xb4006d00);
+ osd->DrawRectangle(xButton, yButton+5, xButton+237, yButton+6, 0xb4007400);
+ osd->DrawRectangle(xButton, yButton+6, xButton+237, yButton+8, 0xb4007c00);
+ osd->DrawRectangle(xButton, yButton+8, xButton+237, yButton+9, 0xb4008100);
+ osd->DrawRectangle(xButton, yButton+9, xButton+237, yButton+11, 0xb4008600);
+ osd->DrawRectangle(xButton, yButton+10, xButton+237, yButton+11, 0xb4008b00);
+ osd->DrawRectangle(xButton, yButton+11, xButton+237, yButton+12, 0xb4009000);
+ osd->DrawRectangle(xButton, yButton+12, xButton+237, yButton+13, 0xb4009600);
+ osd->DrawRectangle(xButton, yButton+13, xButton+237, yButton+14, 0xb4009b00);
+ osd->DrawRectangle(xButton, yButton+14, xButton+237, yButton+15, 0xb400a100);
+ osd->DrawRectangle(xButton, yButton+15, xButton+237, yButton+16, 0xb400a600);
+ osd->DrawRectangle(xButton, yButton+16, xButton+237, yButton+17, 0xb400ac00);
+ osd->DrawRectangle(xButton, yButton+17, xButton+237, yButton+18, 0xb400b200);
+ osd->DrawRectangle(xButton, yButton+18, xButton+237, yButton+19, 0xb400b700);
+ osd->DrawRectangle(xButton, yButton+19, xButton+237, yButton+20, 0xb400bd00);
+ osd->DrawRectangle(xButton, yButton+20, xButton+237, yButton+21, 0xb400c200);
+ osd->DrawRectangle(xButton, yButton+21, xButton+237, yButton+22, 0xb400c800);
+ osd->DrawRectangle(xButton, yButton+22, xButton+237, yButton+23, 0xb400cd00);
+ osd->DrawRectangle(xButton+1, yButton+23, xButton+237, yButton+24, 0xb400d300);
+ osd->DrawRectangle(xButton+1, yButton+24, xButton+236, yButton+25, 0xb400d800);
+ osd->DrawRectangle(xButton+1, yButton+25, xButton+236, yButton+26, 0xb400dd00);
+ osd->DrawRectangle(xButton+2, yButton+26, xButton+235, yButton+27, 0xb400e200);
+ osd->DrawRectangle(xButton+3, yButton+27, xButton+235, yButton+28, 0xb400e200);
+ osd->DrawRectangle(xButton+3, yButton+28, xButton+234, yButton+29, 0xb400ef00);
+ osd->DrawRectangle(xButton+4, yButton+29, xButton+233, yButton+30, 0xb400ef00);
+ osd->DrawRectangle(xButton+5, yButton+30, xButton+232, yButton+31, 0xb400ef00);
+ osd->DrawRectangle(xButton+6, yButton+31, xButton+231, yButton+32, 0xb400f800);
+ osd->DrawRectangle(xButton+8, yButton+32, xButton+229, yButton+33, 0xb400f800);
+ osd->DrawRectangle(xButton+10, yButton+33, xButton+227, yButton+34, 0xb400f800);
+}
+
+void cSkinPearlHDDisplayMenu::DrawYellowButton(int xButton, int yButton)
+{
+ osd->DrawRectangle(xButton, yButton, xButton+237, yButton+3, 0xb4666600);
+ osd->DrawRectangle(xButton, yButton+3, xButton+237, yButton+4, 0xb46d6d00);
+ osd->DrawRectangle(xButton, yButton+4, xButton+237, yButton+6, 0xb4707000);
+ osd->DrawRectangle(xButton, yButton+6, xButton+237, yButton+8, 0xb47c7c00);
+ osd->DrawRectangle(xButton, yButton+8, xButton+237, yButton+10, 0xb4868600);
+ osd->DrawRectangle(xButton, yButton+10, xButton+237, yButton+11, 0xb48b8b00);
+ osd->DrawRectangle(xButton, yButton+11, xButton+237, yButton+12, 0xb4909000);
+ osd->DrawRectangle(xButton, yButton+12, xButton+237, yButton+14, 0xb49b9b00);
+ osd->DrawRectangle(xButton, yButton+14, xButton+237, yButton+16, 0xb4a6a600);
+ osd->DrawRectangle(xButton, yButton+16, xButton+237, yButton+17, 0xb4acac00);
+ osd->DrawRectangle(xButton, yButton+17, xButton+237, yButton+19, 0xb4b7b700);
+ osd->DrawRectangle(xButton, yButton+19, xButton+237, yButton+20, 0xb4bdbd00);
+ osd->DrawRectangle(xButton, yButton+20, xButton+237, yButton+21, 0xb4c2c200);
+ osd->DrawRectangle(xButton, yButton+21, xButton+237, yButton+23, 0xb4cdcd00);
+ osd->DrawRectangle(xButton+1, yButton+23, xButton+237, yButton+24, 0xb4d3d300);
+ osd->DrawRectangle(xButton+1, yButton+24, xButton+236, yButton+25, 0xb4d8d800);
+ osd->DrawRectangle(xButton+1, yButton+25, xButton+236, yButton+26, 0xb4dddd00);
+ osd->DrawRectangle(xButton+2, yButton+26, xButton+235, yButton+27, 0xb4e2e200);
+ osd->DrawRectangle(xButton+3, yButton+27, xButton+235, yButton+28, 0xb4e2e200);
+ osd->DrawRectangle(xButton+3, yButton+28, xButton+234, yButton+29, 0xb4efef00);
+ osd->DrawRectangle(xButton+4, yButton+29, xButton+233, yButton+30, 0xb4efef00);
+ osd->DrawRectangle(xButton+5, yButton+30, xButton+232, yButton+31, 0xb4efef00);
+ osd->DrawRectangle(xButton+6, yButton+31, xButton+231, yButton+32, 0xb4f8f800);
+ osd->DrawRectangle(xButton+8, yButton+32, xButton+229, yButton+33, 0xb4f8f800);
+ osd->DrawRectangle(xButton+10, yButton+33, xButton+227, yButton+34, 0xb4f8f800);
+}
+
+void cSkinPearlHDDisplayMenu::DrawBlueButton(int xButton, int yButton)
+{
+ osd->DrawRectangle(xButton, yButton, xButton+237, yButton+4, 0xb4000068);
+ osd->DrawRectangle(xButton, yButton+4, xButton+237, yButton+6, 0xb4000072);
+ osd->DrawRectangle(xButton, yButton+6, xButton+237, yButton+8, 0xb400007a);
+ osd->DrawRectangle(xButton, yButton+8, xButton+237, yButton+11, 0xb4000086);
+ osd->DrawRectangle(xButton, yButton+11, xButton+237, yButton+14, 0xb4000096);
+ osd->DrawRectangle(xButton, yButton+14, xButton+237, yButton+16, 0xb40000a4);
+ osd->DrawRectangle(xButton, yButton+16, xButton+237, yButton+17, 0xb40000ac);
+ osd->DrawRectangle(xButton, yButton+17, xButton+237, yButton+19, 0xb40000b5);
+ osd->DrawRectangle(xButton, yButton+19, xButton+237, yButton+20, 0xb40000bd);
+ osd->DrawRectangle(xButton, yButton+20, xButton+237, yButton+21, 0xb40000c2);
+ osd->DrawRectangle(xButton, yButton+21, xButton+237, yButton+23, 0xb40000cb);
+ osd->DrawRectangle(xButton+1, yButton+23, xButton+237, yButton+24, 0xb40000d8);
+ osd->DrawRectangle(xButton+1, yButton+24, xButton+236, yButton+25, 0xb40000d8);
+ osd->DrawRectangle(xButton+1, yButton+25, xButton+236, yButton+26, 0xb40000d8);
+ osd->DrawRectangle(xButton+2, yButton+26, xButton+235, yButton+27, 0xb40000e4);
+ osd->DrawRectangle(xButton+3, yButton+27, xButton+235, yButton+28, 0xb40000e4);
+ osd->DrawRectangle(xButton+3, yButton+28, xButton+234, yButton+29, 0xb40000ee);
+ osd->DrawRectangle(xButton+4, yButton+29, xButton+233, yButton+30, 0xb40000ee);
+ osd->DrawRectangle(xButton+5, yButton+30, xButton+232, yButton+31, 0xb40000ee);
+ osd->DrawRectangle(xButton+6, yButton+31, xButton+231, yButton+32, 0xb40000f8);
+ osd->DrawRectangle(xButton+8, yButton+32, xButton+229, yButton+33, 0xb40000f8);
+ osd->DrawRectangle(xButton+10, yButton+33, xButton+227, yButton+34, 0xb40000f8);
+}
+
+int cSkinPearlHDDisplayMenu::GetRecordingLength(const char *FileName, double FramesPerSecond, bool IsPesRecording)
+{
+#define INDEXFILESUFFIX "/index"
+ struct tIndex { int offset; uchar type; uchar number; short reserved; };
+ struct stat buf;
+ cString fullname = cString::sprintf("%s%s", FileName, IsPesRecording ? INDEXFILESUFFIX ".vdr" : INDEXFILESUFFIX);
+ if (FileName && *fullname && access(fullname, R_OK) == 0 && stat(fullname, &buf) == 0)
+ return buf.st_size ? ((buf.st_size - 1) / sizeof(tIndex) + 1) / (60 * FramesPerSecond) : 0;
+ return 0;
+}
+
+int cSkinPearlHDDisplayMenu::GetRecordingCuttedLength(const char *FileName, double FramesPerSecond, bool IsPesRecording)
+{
+ cMarks marks;
+ double length = 0;
+ int totalLength = GetRecordingLength(FileName, FramesPerSecond, IsPesRecording);
+ const double diffIFrame = FramesPerSecond / 2; // approx. 1/2 sec.
+
+#if VDRVERSNUM >= 10703
+ marks.Load(FileName, FramesPerSecond, IsPesRecording);
+#else
+ marks.Load(FileName);
+#endif
+
+ if (marks.Count()) {
+ int start = 1; // first frame
+ bool isStart = true;
+
+ for (cMark *m = marks.First(); m; m = marks.GetNext(m->position)) {
+ if (isStart)
+ start = m->position;
+ else
+ length += (double)(m->position - start + 1 + diffIFrame) / (60 * FramesPerSecond); // [min]
+
+ isStart = !isStart;
+ }
+
+ // if there is no end-mark the last segment goes to the end of the rec.
+ if (!isStart)
+ length += totalLength - (double)(start - 1 - diffIFrame) / (60 * FramesPerSecond); // [min]
+ }
+
+ // just to avoid, that the cutted length is bigger than the total length
+ return (int)length > totalLength ? totalLength : (int)length;
+}
+
+// --- cSkinPearlHDDisplayReplay -----------------------------------------------
+
+class cSkinPearlHDDisplayReplay : public cSkinDisplayReplay {
+private:
+ cOsd *osd;
+ int x1, x2;
+ int y1, y2;
+ const cFont *fontSansBook27;
+ char *current;
+ char *total;
+ int x1Message;
+ int x2Message;
+ int y1Message;
+ int y2Message;
+public:
+ cSkinPearlHDDisplayReplay(bool ModeOnly);
+ virtual ~cSkinPearlHDDisplayReplay();
+ virtual void SetTitle(const char *Title);
+ virtual void SetMode(bool Play, bool Forward, int Speed);
+ virtual void SetProgress(int Current, int Total);
+ virtual void SetCurrent(const char *Current);
+ virtual void SetTotal(const char *Total);
+ virtual void SetJump(const char *Jump);
+ virtual void SetMessage(eMessageType Type, const char *Text);
+ virtual void Flush(void);
+ };
+
+cSkinPearlHDDisplayReplay::cSkinPearlHDDisplayReplay(bool ModeOnly)
+{
+ fontSansBook27 = cFont::CreateFont("VDRSymbols Sans:Book", 27);
+ x1 = 0;
+ x2 = cOsd::OsdWidth();
+ y1 = 0;
+ y2 = cOsd::OsdHeight();
+ x1Message = 480;
+ x2Message = cOsd::OsdWidth() - 1;
+ y1Message = cOsd::OsdHeight() - 70;
+ y2Message = cOsd::OsdHeight() - 1;
+
+ osd = cOsdProvider::NewOsd(cOsd::OsdLeft(), cOsd::OsdTop());
+ tArea Areas[] = { { 0, 0, x2 - 1, y2 - 1, 32 } }; // TrueColor
+ if (osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
+ osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
+ else {
+ tArea Areas[] = { { 0, 0, x2 - 1, y2 - 1, 8 } }; // 256 colors
+ if (osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
+ osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
+ }
+
+ if (!ModeOnly)
+ {
+ osd->DrawRectangle(x2-360, y1, x2-1, y1+20, Theme.Color(clrMainLight));
+ osd->DrawEllipse(x2-360, y1+20, x2-310, y1+70, Theme.Color(clrMainLight), 3);
+ osd->DrawRectangle(x2-310, y1+20, x2-1, y1+70, Theme.Color(clrMainLight));
+
+ osd->DrawEllipse(x1, y2-110, x1+50, y2-60, Theme.Color(clrMainLight), 2);
+ osd->DrawRectangle(x1+51, y2-110, x2-1, y2-60, Theme.Color(clrMainLight));
+ osd->DrawRectangle(x1, y2-60, x2-1, y2-40, Theme.Color(clrMainSolid));
+ }
+}
+
+cSkinPearlHDDisplayReplay::~cSkinPearlHDDisplayReplay()
+{
+ delete osd;
+}
+
+void cSkinPearlHDDisplayReplay::SetTitle(const char *Title)
+{
+ osd->DrawText(x1+240, y2-95, Title, Theme.Color(clrFontColor), clrTransparent, fontSansBook27);
+}
+
+static const char *ReplaySymbols[2][2][5] = {
+ { { tr("Pause"), tr("Slow rewind"), tr("Slow rewind x1"), tr("Slow rewind x2"), tr("Slow rewind x3") },
+ { tr("Pause"), tr("Slow forward"), tr("Slow forward x1"), tr("Slow forward x2"), tr("Slow forward x3") }, },
+ { { tr("Playing"), tr("Fast rewind"), tr("Fast rewind x1"), tr("Fast rewind x2"), tr("Fast rewind x3") },
+ { tr("Playing"), tr("Fast forward"), tr("Fast forward x1"), tr("Fast forward x2"), tr("Fast forward x3") } }
+ };
+
+void cSkinPearlHDDisplayReplay::SetMode(bool Play, bool Forward, int Speed)
+{
+ if (Speed < -1)
+ Speed = -1;
+ if (Speed > 3)
+ Speed = 3;
+ osd->DrawText(x2-310,y1+20, ReplaySymbols[Play][Forward][Speed + 1], Theme.Color(clrFontColor), Theme.Color(clrMainLight), fontSansBook27, 290, 40, taRight);
+}
+
+void cSkinPearlHDDisplayReplay::SetProgress(int Current, int Total)
+{
+ cProgressBar pb(x2-x1-1, 39, Current, Total, marks, Theme.Color(clrBarFill), Theme.Color(clrBar), Theme.Color(clrKeep), Theme.Color(clrMark), clrTransparent);
+ osd->DrawBitmap(x1, y2-40, pb);
+}
+
+void cSkinPearlHDDisplayReplay::SetCurrent(const char *Current)
+{
+ current = (char*) malloc(sizeof(Current));
+ strcpy (current, Current);
+}
+
+void cSkinPearlHDDisplayReplay::SetTotal(const char *Total)
+{
+ total = (char*) malloc(sizeof(Total));
+ strcpy (total, Total);
+}
+
+void cSkinPearlHDDisplayReplay::SetJump(const char *Jump)
+{
+ osd->DrawEllipse(x2-360, y2-160, x2-310, y2-111, Theme.Color(clrMainLight), 2);
+ osd->DrawRectangle(x2-310, y2-160, x2-1, y2-111, Theme.Color(clrMainLight));
+ osd->DrawText(x2-250, y2-150, Jump, Theme.Color(clrFontColor), Theme.Color(clrMainLight), fontSansBook27, 220, 39, taRight);
+}
+
+void cSkinPearlHDDisplayReplay::SetMessage(eMessageType Type, const char *Text)
+{
+ if (Text) {
+ osd->DrawRectangle(x1Message + 50, y1Message, x2Message, y1Message + 50, Theme.Color(clrMainLight));
+ osd->DrawEllipse(x1Message, y1Message, x1Message + 50, y1Message + 50, Theme.Color(clrMainLight), 2);
+ switch(Type) {
+ case mtInfo :
+ osd->DrawRectangle(x1Message, y1Message + 50, x2Message, y2Message, Theme.Color(clrMainSolid));
+ break;
+ case mtStatus :
+ osd->DrawRectangle(x1Message, y1Message + 50, x2Message, y2Message, Theme.Color(clrStatus));
+ break;
+ case mtWarning :
+ osd->DrawRectangle(x1Message, y1Message + 50, x2Message, y2Message, Theme.Color(clrWarning));
+ break;
+ case mtError :
+ osd->DrawRectangle(x1Message, y1Message + 50, x2Message, y2Message, Theme.Color(clrError));
+ break;
+ }
+ osd->DrawText(x1Message + 50, y1Message + 15, Text, Theme.Color(clrFontColor), clrTransparent, fontSansBook27, x2Message - (x1Message+50), 0, taRight);
+ }
+ else {
+ osd->RestoreRegion();
+ }
+}
+
+void cSkinPearlHDDisplayReplay::Flush(void)
+{
+ if (current && total)
+ {
+ char timeplayed[50];
+ snprintf (timeplayed, sizeof(timeplayed), "%s %s %s", current, tr("of"), total);
+ osd->DrawText(x2-30-fontSansBook27->Width(timeplayed), y2-110, timeplayed, Theme.Color(clrFontColor), Theme.Color(clrMainLight), fontSansBook27, fontSansBook27->Width(timeplayed), 50, taRight);
+ }
+ osd->Flush();
+}
+
+// --- cSkinPearlHDDisplayVolume -----------------------------------------------
+
+class cSkinPearlHDDisplayVolume : public cSkinDisplayVolume {
+private:
+ cOsd *osd;
+ int x1, x2;
+ int y1, y2;
+ const cFont *fontSansBook27;
+public:
+ cSkinPearlHDDisplayVolume(void);
+ virtual ~cSkinPearlHDDisplayVolume();
+ virtual void SetVolume(int Current, int Total, bool Mute);
+ virtual void Flush(void);
+ };
+
+cSkinPearlHDDisplayVolume::cSkinPearlHDDisplayVolume(void)
+{
+ x1 = 0;
+ x2 = cOsd::OsdWidth();
+ y1 = 0;
+ y2 = cOsd::OsdHeight();
+ fontSansBook27 = cFont::CreateFont("VDRSymbols Sans:Book", 27);
+
+ osd = cOsdProvider::NewOsd(cOsd::OsdLeft(), cOsd::OsdTop());
+ tArea Areas[] = { { 0, 0, x2 - 1, y2 - 1, 32 } }; // TrueColor
+ if (osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
+ osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
+ else {
+ tArea Areas[] = { { 0, 0, x2 - 1, y2 - 1, 8 } }; // 256 colors
+ if (osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
+ osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
+ }
+}
+
+cSkinPearlHDDisplayVolume::~cSkinPearlHDDisplayVolume()
+{
+ delete osd;
+}
+
+void cSkinPearlHDDisplayVolume::SetVolume(int Current, int Total, bool Mute)
+{
+ osd->DrawRectangle(x2-360, y1, x2-1, y1+20, Theme.Color(clrMainLight));
+ osd->DrawEllipse(x2-360, y1+20, x2-310, y1+70, Theme.Color(clrMainLight), 3);
+ osd->DrawRectangle(x2-310, y1+20, x2-1, y1+70, Theme.Color(clrMainLight));
+
+ if (!Mute)
+ {
+ osd->DrawText(x2-300, y1+20, tr("Volume"), Theme.Color(clrFontColor), Theme.Color(clrMainLight), fontSansBook27);
+ int iVolLengthTotal = (x2-1) - x1;
+ int iVolLengthCurrent = (int)((float)((float)Current / (float)Total) * (float)iVolLengthTotal);
+ osd->DrawRectangle(x1, y2-40, x2-1, y2-1, Theme.Color(clrBar));
+ osd->DrawRectangle(x1, y2-40, x1+iVolLengthCurrent, y2-1, Theme.Color(clrBarFill));
+ }
+ else
+ osd->DrawRectangle(x1, y2-40, x2-1, y2-1, Theme.Color(clrBarBlock));
+
+ char vol[5];
+ snprintf(vol, sizeof(vol), "%d", Current);
+ osd->DrawText(x2-100, y1+20, Mute ? tr("Mute") : vol, Theme.Color(clrFontColor), Theme.Color(clrMainLight), fontSansBook27, 80, 0, taRight);
+}
+
+void cSkinPearlHDDisplayVolume::Flush(void)
+{
+ osd->Flush();
+}
+
+// --- cSkinPearlHDDisplayTracks -----------------------------------------------
+
+class cSkinPearlHDDisplayTracks : public cSkinDisplayTracks {
+private:
+ cOsd *osd;
+ int x1, x2;
+ int y1, y2;
+ int lineHeight;
+ int currentIndex;
+ void SetItem(const char *Text, int Index, bool Current);
+ const cFont *fontSansBook27;
+ const cFont *fontSansBook37;
+public:
+ cSkinPearlHDDisplayTracks(const char *Title, int NumTracks, const char * const *Tracks);
+ virtual ~cSkinPearlHDDisplayTracks();
+ virtual void SetTrack(int Index, const char * const *Tracks);
+ virtual void SetAudioChannel(int AudioChannel);
+ virtual void Flush(void);
+ };
+
+cSkinPearlHDDisplayTracks::cSkinPearlHDDisplayTracks(const char *Title, int NumTracks, const char * const *Tracks)
+{
+ lineHeight = 50;
+ currentIndex = -1;
+ x1 = 0;
+ x2 = cOsd::OsdWidth();
+ y1 = 0;
+ y2 = cOsd::OsdHeight();
+ fontSansBook27 = cFont::CreateFont("VDRSymbols Sans:Book", 27);
+ fontSansBook37 = cFont::CreateFont("VDRSymbols Sans:Book", 37);
+
+ osd = cOsdProvider::NewOsd(cOsd::OsdLeft(), cOsd::OsdTop());
+ tArea Areas[] = { { 0, 0, x2 - 1, y2 - 1, 32 } }; // TrueColor
+ if (osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
+ osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
+ else {
+ tArea Areas[] = { { 0, 0, x2 - 1, y2 - 1, 8 } }; // 256 colors
+ if (osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
+ osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
+ }
+
+ osd->DrawEllipse(x1+480, y1+345, x1+530, y1+395, Theme.Color(clrMainSolid), 2);
+ osd->DrawRectangle(x1+531, y1+345, x2-480, y1+395, Theme.Color(clrMainSolid));
+ osd->DrawRectangle(x1+480, y1+396, x2-480, y1+444, Theme.Color(clrMainSolid));
+ osd->DrawRectangle(x1+480, y1+444, x2-480, y1+446, Theme.Color(clrDivider));
+ osd->DrawRectangle(x1+480, y1+446, x2-480, y2-406, Theme.Color(clrMainLight));
+ osd->DrawRectangle(x1+480, y2-405, x2-530, y2-355, Theme.Color(clrMainLight));
+ osd->DrawEllipse(x2-530, y2-405, x2-480, y2-355, Theme.Color(clrMainLight), 4);
+ osd->DrawText(x1+730, y1+380, Title, Theme.Color(clrFontColor), clrTransparent, fontSansBook37, (x2-500) - (x1+730), 0, taRight);
+
+ for (int i = 0; i < NumTracks; i++)
+ SetItem(Tracks[i], i, false);
+}
+
+cSkinPearlHDDisplayTracks::~cSkinPearlHDDisplayTracks()
+{
+ delete osd;
+}
+
+void cSkinPearlHDDisplayTracks::SetItem(const char *Text, int Index, bool Current)
+{
+ int x1Item=x1+480;
+ int y1Item=y1+460 + (lineHeight * Index);
+ int x2Item=x2-480;
+ int y2Item=y1Item + lineHeight;
+
+ osd->DrawRectangle(x1Item+74, y1Item, x2Item-1, y2Item-6, Theme.Color(Current ? clrMainSolid : clrLoLight));
+ osd->DrawEllipse(x1Item+60, y1Item, x1Item+74, y1Item+15, Theme.Color(Current ? clrMainSolid : clrLoLight), 2);
+ osd->DrawRectangle(x1Item+60, y1Item+14, x1Item+74, y2Item-21, Theme.Color(Current ? clrMainSolid : clrLoLight));
+ osd->DrawEllipse(x1Item+60, y2Item-21, x1Item+74, y2Item-6, Theme.Color(Current ? clrMainSolid : clrLoLight), 3);
+ osd->DrawText(x1Item+80, y1Item+5, Text, Theme.Color(Current ? clrFontColor : clrFontColorInactive), clrTransparent, fontSansBook27, (x2Item-21) - (x1Item+80), 0, taRight);
+
+ if (Current)
+ {
+ osd->DrawRectangle(x1Item+74, y1Item, x2Item-1, y2Item-6, Theme.Color(clrMainSolid));
+ osd->DrawEllipse(x1Item+60, y1Item, x1Item+74, y1Item+15, Theme.Color(clrMainSolid), 2);
+ osd->DrawRectangle(x1Item+60, y1Item+14, x1Item+74, y2Item-21, Theme.Color(clrMainSolid));
+ osd->DrawEllipse(x1Item+60, y2Item-21, x1Item+74, y2Item-6, Theme.Color(clrMainSolid), 3);
+ osd->DrawText(x1Item+80, y1Item+5, Text, Theme.Color(clrFontColor), clrTransparent, fontSansBook27, (x2Item-21) - (x1Item+80), 0, taRight);
+ currentIndex = Index;
+ }
+ else if (currentIndex == Index)
+ {
+ osd->DrawRectangle(x1Item+74, y1Item, x2Item-1, y2Item-6, Theme.Color(clrLoLight));
+ osd->DrawEllipse(x1Item+60, y1Item, x1Item+74, y1Item+15, Theme.Color(clrLoLight), 2);
+ osd->DrawRectangle(x1Item+60, y1Item+14, x1Item+74, y2Item-21, Theme.Color(clrLoLight));
+ osd->DrawEllipse(x1Item+60, y2Item-21, x1Item+74, y2Item-6, Theme.Color(clrLoLight), 3);
+ osd->DrawText(x1Item+80, y1Item+5, Text, Theme.Color(clrFontColorInactive), clrTransparent, fontSansBook27, (x2Item-21) - (x1Item+80), 0, taRight);
+ }
+}
+
+void cSkinPearlHDDisplayTracks::SetTrack(int Index, const char * const *Tracks)
+{
+ if (currentIndex >= 0)
+ SetItem(Tracks[currentIndex], currentIndex, false);
+ SetItem(Tracks[Index], Index, true);
+}
+
+void cSkinPearlHDDisplayTracks::SetAudioChannel(int AudioChannel)
+{
+ int x1Icon = x1+555;
+ int y1Icon = y1+390;
+
+ switch (AudioChannel) {
+ case 0:
+ osd->DrawRectangle(x1Icon+2, y1Icon+2, x1Icon+23, y1Icon+18, Theme.Color(clrFontColor));
+ osd->DrawRectangle(x1Icon+3, y1Icon+3, x1Icon+22, y1Icon+17, Theme.Color(clrMainLight));
+ osd->DrawEllipse(x1Icon+5, y1Icon+6, x1Icon+13, y1Icon+14, Theme.Color(clrFontColor));
+ osd->DrawEllipse(x1Icon+6, y1Icon+7, x1Icon+14, y1Icon+13, Theme.Color(clrFontColor));
+ osd->DrawEllipse(x1Icon+12, y1Icon+6, x1Icon+20, y1Icon+14, Theme.Color(clrFontColor));
+ osd->DrawEllipse(x1Icon+13, y1Icon+7, x1Icon+19, y1Icon+13, Theme.Color(clrFontColor));
+ break;
+ case 1:
+ osd->DrawRectangle(x1Icon+2, y1Icon+2, x1Icon+23, y1Icon+18, Theme.Color(clrFontColor));
+ osd->DrawRectangle(x1Icon+3, y1Icon+3, x1Icon+22, y1Icon+17, Theme.Color(clrMainLight));
+ osd->DrawEllipse(x1Icon+5, y1Icon+6, x1Icon+13, y1Icon+14, Theme.Color(clrFontColor));
+ osd->DrawEllipse(x1Icon+6, y1Icon+7, x1Icon+14, y1Icon+13, Theme.Color(clrFontColor));
+ osd->DrawEllipse(x1Icon+12, y1Icon+6, x1Icon+20, y1Icon+14, Theme.Color(clrFontColor));
+ osd->DrawEllipse(x1Icon+13, y1Icon+7, x1Icon+19, y1Icon+13, Theme.Color(clrMainLight));
+ break;
+ case 2:
+ osd->DrawRectangle(x1Icon+2, y1Icon+2, x1Icon+23, y1Icon+18, Theme.Color(clrFontColor));
+ osd->DrawRectangle(x1Icon+3, y1Icon+3, x1Icon+22, y1Icon+17, Theme.Color(clrMainLight));
+ osd->DrawEllipse(x1Icon+5, y1Icon+6, x1Icon+13, y1Icon+14, Theme.Color(clrFontColor));
+ osd->DrawEllipse(x1Icon+6, y1Icon+7, x1Icon+14, y1Icon+13, Theme.Color(clrMainLight));
+ osd->DrawEllipse(x1Icon+12, y1Icon+6, x1Icon+20, y1Icon+14, Theme.Color(clrFontColor));
+ osd->DrawEllipse(x1Icon+13, y1Icon+7, x1Icon+19, y1Icon+13, Theme.Color(clrFontColor));
+ break;
+ default: ;
+ }
+}
+
+void cSkinPearlHDDisplayTracks::Flush(void)
+{
+ osd->Flush();
+}
+
+// --- cSkinPearlHDDisplayMessage ----------------------------------------------
+
+class cSkinPearlHDDisplayMessage : public cSkinDisplayMessage {
+private:
+ cOsd *osd;
+ int x1Message;
+ int x2Message;
+ int y1Message;
+ int y2Message;
+ const cFont *fontSansBook27;
+public:
+ cSkinPearlHDDisplayMessage(void);
+ virtual ~cSkinPearlHDDisplayMessage();
+ virtual void SetMessage(eMessageType Type, const char *Text);
+ virtual void Flush(void);
+ };
+
+cSkinPearlHDDisplayMessage::cSkinPearlHDDisplayMessage(void)
+{
+ fontSansBook27 = cFont::CreateFont("VDRSymbols Sans:Book", 27);
+ x1Message = 480;
+ x2Message = cOsd::OsdWidth() - 1;
+ y1Message = cOsd::OsdHeight() - 70;
+ y2Message = cOsd::OsdHeight() - 1;
+ fontSansBook27 = cFont::CreateFont("VDRSymbols Sans:Book", 27);
+
+ osd = cOsdProvider::NewOsd(cOsd::OsdLeft(), cOsd::OsdTop());
+ tArea Areas[] = { { 0, 0, x2Message, y2Message, 32 } }; // TrueColor
+ if (osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
+ osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
+ else {
+ tArea Areas[] = { { 0, 0, x2Message, y2Message, 8 } }; // 256 colors
+ if (osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
+ osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
+ }
+}
+
+cSkinPearlHDDisplayMessage::~cSkinPearlHDDisplayMessage()
+{
+ delete osd;
+}
+
+void cSkinPearlHDDisplayMessage::SetMessage(eMessageType Type, const char *Text)
+{
+ if (Text) {
+ osd->DrawRectangle(x1Message + 50, y1Message, x2Message, y1Message + 50, Theme.Color(clrMainLight));
+ osd->DrawEllipse(x1Message, y1Message, x1Message + 50, y1Message + 50, Theme.Color(clrMainLight), 2);
+ switch(Type) {
+ case mtInfo :
+ osd->DrawRectangle(x1Message, y1Message + 50, x2Message, y2Message, Theme.Color(clrMainSolid));
+ break;
+ case mtStatus :
+ osd->DrawRectangle(x1Message, y1Message + 50, x2Message, y2Message, Theme.Color(clrStatus));
+ break;
+ case mtWarning :
+ osd->DrawRectangle(x1Message, y1Message + 50, x2Message, y2Message, Theme.Color(clrWarning));
+ break;
+ case mtError :
+ osd->DrawRectangle(x1Message, y1Message + 50, x2Message, y2Message, Theme.Color(clrError));
+ break;
+ }
+ osd->DrawText(x1Message + 50, y1Message + 15, Text, Theme.Color(clrFontColor), clrTransparent, fontSansBook27, x2Message - (x1Message+50), 0, taRight);
+ }
+}
+
+void cSkinPearlHDDisplayMessage::Flush(void)
+{
+ osd->Flush();
+}
+
+// --- cSkinPearlHD ----------------------------------------------------------
+
+cSkinPearlHD::cSkinPearlHD() : cSkin("PearlHD", &::Theme)
+{
+ // Get the "classic" skin to be used as fallback skin if any of the OSD
+ // menu fails to open.
+ skinFallback = Skins.First();
+ for (cSkin *Skin = Skins.First(); Skin; Skin = Skins.Next(Skin)) {
+ if (strcmp(Skin->Name(), "classic") == 0) {
+ skinFallback = Skin;
+ break;
+ }
+ }
+}
+
+const char *cSkinPearlHD::Description(void)
+{
+ return tr("PearlHD");
+}
+
+cSkinDisplayChannel *cSkinPearlHD::DisplayChannel(bool WithInfo)
+{
+ try {
+ return new cSkinPearlHDDisplayChannel(WithInfo);
+ } catch(...) {
+ return skinFallback->DisplayChannel(WithInfo);
+ }
+}
+
+cSkinDisplayMenu *cSkinPearlHD::DisplayMenu(void)
+{
+ try {
+ return new cSkinPearlHDDisplayMenu;
+ } catch (...) {
+ return skinFallback->DisplayMenu();
+ }
+}
+
+cSkinDisplayReplay *cSkinPearlHD::DisplayReplay(bool ModeOnly)
+{
+ try {
+ return new cSkinPearlHDDisplayReplay(ModeOnly);
+ } catch (...) {
+ return skinFallback->DisplayReplay(ModeOnly);
+ }
+}
+
+cSkinDisplayVolume *cSkinPearlHD::DisplayVolume(void)
+{
+ try {
+ return new cSkinPearlHDDisplayVolume;
+ } catch (...) {
+ return skinFallback->DisplayVolume();
+ }
+}
+
+cSkinDisplayTracks *cSkinPearlHD::DisplayTracks(const char *Title, int NumTracks, const char *const *Tracks)
+{
+ try {
+ return new cSkinPearlHDDisplayTracks(Title, NumTracks, Tracks);
+ } catch (...) {
+ return skinFallback->DisplayTracks(Title, NumTracks, Tracks);
+ }
+}
+
+cSkinDisplayMessage *cSkinPearlHD::DisplayMessage(void)
+{
+ try {
+ return new cSkinPearlHDDisplayMessage;
+ } catch (...) {
+ return skinFallback->DisplayMessage();
+ }
+}
diff --git a/pearlhd.h b/pearlhd.h
new file mode 100644
index 0000000..66ab50a
--- /dev/null
+++ b/pearlhd.h
@@ -0,0 +1,21 @@
+#ifndef __PEARLHD_H
+#define __PEARLHD_H
+
+#include <vdr/skins.h>
+#include <vdr/skinclassic.h>
+
+class cSkinPearlHD : public cSkin {
+ private:
+ cSkin *skinFallback;
+
+ public:
+ cSkinPearlHD();
+ virtual const char *Description(void);
+ virtual cSkinDisplayChannel *DisplayChannel(bool WithInfo);
+ virtual cSkinDisplayMenu *DisplayMenu(void);
+ virtual cSkinDisplayReplay *DisplayReplay(bool ModeOnly);
+ virtual cSkinDisplayVolume *DisplayVolume(void);
+ virtual cSkinDisplayTracks *DisplayTracks(const char *Title, int NumTracks, const char * const *Tracks);
+ virtual cSkinDisplayMessage *DisplayMessage(void);
+ };
+#endif //__PEARLHD
diff --git a/po/de_DE.po b/po/de_DE.po
new file mode 100644
index 0000000..87ec0d1
--- /dev/null
+++ b/po/de_DE.po
@@ -0,0 +1,173 @@
+# VDR plugin language source file.
+# This file is distributed under the same license as the VDR package.
+msgid ""
+msgstr ""
+"Project-Id-Version: VDR 1.7.17\n"
+"Report-Msgid-Bugs-To: <see README>\n"
+"POT-Creation-Date: 2011-05-10 18:12+0200\n"
+"PO-Revision-Date: 2010-10-10 10:10+0300\n"
+"Last-Translator: a\n"
+"Language-Team: German\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-15\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: de\n"
+
+msgid "cutted"
+msgstr "geschnitten"
+
+msgid "oClock"
+msgstr "Uhr"
+
+msgid "Conflicting Timers"
+msgstr "Timerkonflikte"
+
+msgid "Pause"
+msgstr "Pause"
+
+msgid "Slow rewind"
+msgstr "Zeitlupe Rückwärts"
+
+#, fuzzy
+msgid "Slow rewind x1"
+msgstr "Zeitlupe Rückwärts"
+
+#, fuzzy
+msgid "Slow rewind x2"
+msgstr "Zeitlupe Rückwärts"
+
+#, fuzzy
+msgid "Slow rewind x3"
+msgstr "Zeitlupe Rückwärts"
+
+msgid "Slow forward"
+msgstr "Zeitlupe Vorwärts"
+
+#, fuzzy
+msgid "Slow forward x1"
+msgstr "Zeitlupe Vorwärts"
+
+#, fuzzy
+msgid "Slow forward x2"
+msgstr "Zeitlupe Vorwärts"
+
+#, fuzzy
+msgid "Slow forward x3"
+msgstr "Zeitlupe Vorwärts"
+
+msgid "Playing"
+msgstr "Playing"
+
+msgid "Fast rewind"
+msgstr "Zurückspulen"
+
+#, fuzzy
+msgid "Fast rewind x1"
+msgstr "Zurückspulen"
+
+#, fuzzy
+msgid "Fast rewind x2"
+msgstr "Zurückspulen"
+
+#, fuzzy
+msgid "Fast rewind x3"
+msgstr "Zurückspulen"
+
+msgid "Fast forward"
+msgstr "Vorlauf"
+
+#, fuzzy
+msgid "Fast forward x1"
+msgstr "Vorlauf"
+
+#, fuzzy
+msgid "Fast forward x2"
+msgstr "Vorlauf"
+
+#, fuzzy
+msgid "Fast forward x3"
+msgstr "Vorlauf"
+
+msgid "of"
+msgstr "von"
+
+msgid "Volume"
+msgstr "Lautstärke"
+
+msgid "Mute"
+msgstr "Stumm"
+
+msgid "PearlHD"
+msgstr ""
+
+msgid "General"
+msgstr ""
+
+msgid "Don't show"
+msgstr "nicht anzeigen"
+
+msgid "Top"
+msgstr "Oben"
+
+msgid "Bottom"
+msgstr "Unten"
+
+msgid "Display oClock text"
+msgstr "Uhrtext anzeigen"
+
+msgid "Display clock in Recordings/Timer menu"
+msgstr "Uhrzeit im Aufnahme/Timer Menü anzeigen"
+
+msgid "Display epg images"
+msgstr "EPG-Bilder anzeigen"
+
+msgid "Epg images format"
+msgstr "EPG-Bildformat"
+
+msgid "Padding sides"
+msgstr "Abstand zu den Seiten"
+
+msgid "Padding top/bottom"
+msgstr "Abstand nach oben/unten"
+
+msgid "Item line height"
+msgstr "Eintraghöhe"
+
+msgid "Show running recordings in the header"
+msgstr "Laufende Aufnahmen im Kopf anzeigen"
+
+msgid "Show timers in the right bar at"
+msgstr "Timer im rechten Bereich anzeigen"
+
+msgid "Channel Info"
+msgstr "Kanal Informationen"
+
+msgid "Left"
+msgstr "Links"
+
+msgid "Right"
+msgstr "Rechts"
+
+msgid "Channel logo position"
+msgstr "Kanal Logo Position"
+
+msgid "Channel logo format"
+msgstr "Knala Logo Format"
+
+msgid "Button red text"
+msgstr "Beschriftung roter Button"
+
+msgid "Button green text"
+msgstr "Beschriftung grüner Button"
+
+msgid "Button yellow text"
+msgstr "Beschriftung gelber Button"
+
+msgid "Button blue text"
+msgstr "Beschriftung blauer Button"
+
+msgid "Display crypt symbols"
+msgstr "Symbole zur Verschlüsselung anzeigen"
+
+msgid "Menu"
+msgstr "Menü"
diff --git a/services/epgsearchservices.h b/services/epgsearchservices.h
new file mode 100644
index 0000000..748d94d
--- /dev/null
+++ b/services/epgsearchservices.h
@@ -0,0 +1,195 @@
+/*
+Copyright (C) 2004-2011 Christian Wieninger
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+
+The author can be reached at cwieninger@gmx.de
+
+The project's page is at http://winni.vdr-developer.org/epgsearch
+*/
+
+#ifndef EPGSEARCHSERVICES_INC
+#define EPGSEARCHSERVICES_INC
+
+#include <string>
+#include <list>
+#include <memory>
+#include <set>
+#include <vdr/osdbase.h>
+
+// Data structure for service "Epgsearch-search-v1.0"
+struct Epgsearch_search_v1_0
+{
+// in
+ char* query; // search term
+ int mode; // search mode (0=phrase, 1=and, 2=or, 3=regular expression)
+ int channelNr; // channel number to search in (0=any)
+ bool useTitle; // search in title
+ bool useSubTitle; // search in subtitle
+ bool useDescription; // search in description
+// out
+ cOsdMenu* pResultMenu; // pointer to the menu of results
+};
+
+// Data structure for service "Epgsearch-exttimeredit-v1.0"
+struct Epgsearch_exttimeredit_v1_0
+{
+// in
+ cTimer* timer; // pointer to the timer to edit
+ bool bNew; // flag that indicates, if this is a new timer or an existing one
+ const cEvent* event; // pointer to the event corresponding to this timer (may be NULL)
+// out
+ cOsdMenu* pTimerMenu; // pointer to the menu of results
+};
+
+// Data structure for service "Epgsearch-updatesearchtimers-v1.0"
+struct Epgsearch_updatesearchtimers_v1_0
+{
+// in
+ bool showMessage; // inform via osd when finished?
+};
+
+// Data structure for service "Epgsearch-osdmessage-v1.0"
+struct Epgsearch_osdmessage_v1_0
+{
+// in
+ char* message; // the message to display
+ eMessageType type;
+};
+
+// Data structure for service "EpgsearchMenu-v1.0"
+struct EpgSearchMenu_v1_0
+{
+// in
+// out
+ cOsdMenu* Menu; // pointer to the menu
+};
+
+// Data structure for service "Epgsearch-lastconflictinfo-v1.0"
+struct Epgsearch_lastconflictinfo_v1_0
+{
+// in
+// out
+ time_t nextConflict; // next conflict date, 0 if none
+ int relevantConflicts; // number of relevant conflicts
+ int totalConflicts; // total number of conflicts
+};
+
+// Data structure for service "Epgsearch-searchresults-v1.0"
+struct Epgsearch_searchresults_v1_0
+{
+// in
+ char* query; // search term
+ int mode; // search mode (0=phrase, 1=and, 2=or, 3=regular expression)
+ int channelNr; // channel number to search in (0=any)
+ bool useTitle; // search in title
+ bool useSubTitle; // search in subtitle
+ bool useDescription; // search in description
+// out
+
+ class cServiceSearchResult : public cListObject
+ {
+ public:
+ const cEvent* event;
+ cServiceSearchResult(const cEvent* Event) : event(Event) {}
+ };
+
+ cList<cServiceSearchResult>* pResultList; // pointer to the results
+};
+
+// Data structure for service "Epgsearch-switchtimer-v1.0"
+struct Epgsearch_switchtimer_v1_0
+{
+// in
+ const cEvent* event;
+ int mode; // mode (0=query existance, 1=add/modify, 2=delete)
+// in/out
+ int switchMinsBefore;
+ int announceOnly;
+// out
+ bool success; // result
+};
+
+// Data structures for service "Epgsearch-services-v1.0"
+class cServiceHandler
+{
+ public:
+ virtual std::list<std::string> SearchTimerList() = 0;
+ // returns a list of search timer entries in the same format as used in epgsearch.conf
+ virtual int AddSearchTimer(const std::string&) = 0;
+ // adds a new search timer and returns its ID (-1 on error)
+ virtual bool ModSearchTimer(const std::string&) = 0;
+ // edits an existing search timer and returns success
+ virtual bool DelSearchTimer(int) = 0;
+ // deletes search timer with given ID and returns success
+ virtual std::list<std::string> QuerySearchTimer(int) = 0;
+ // returns the search result of the searchtimer with given ID in the same format as used in SVDRP command 'QRYS' (->MANUAL)
+ virtual std::list<std::string> QuerySearch(std::string) = 0;
+ // returns the search result of the searchtimer with given settings in the same format as used in SVDRP command 'QRYS' (->MANUAL)
+ virtual std::list<std::string> ExtEPGInfoList() = 0;
+ // returns a list of extended EPG categories in the same format as used in epgsearchcats.conf
+ virtual std::list<std::string> ChanGrpList() = 0;
+ // returns a list of channel groups maintained by epgsearch
+ virtual std::list<std::string> BlackList() = 0;
+ // returns a list of blacklists in the same format as used in epgsearchblacklists.conf
+ virtual std::set<std::string> DirectoryList() = 0;
+ // List of all recording directories used in recordings, timers, search timers or in epgsearchdirs.conf
+ virtual ~cServiceHandler() {}
+ // Read a setup value
+ virtual std::string ReadSetupValue(const std::string& entry) = 0;
+ // Write a setup value
+ virtual bool WriteSetupValue(const std::string& entry, const std::string& value) = 0;
+};
+
+struct Epgsearch_services_v1_0
+{
+// in/out
+ std::auto_ptr<cServiceHandler> handler;
+};
+
+// Data structures for service "Epgsearch-services-v1.1"
+class cServiceHandler_v1_1 : public cServiceHandler
+{
+ public:
+ // Get timer conflicts
+ virtual std::list<std::string> TimerConflictList(bool relOnly=false) = 0;
+ // Check if a conflict check is advised
+ virtual bool IsConflictCheckAdvised() = 0;
+};
+
+struct Epgsearch_services_v1_1
+{
+// in/out
+ std::auto_ptr<cServiceHandler_v1_1> handler;
+};
+
+// Data structures for service "Epgsearch-services-v1.2"
+class cServiceHandler_v1_2 : public cServiceHandler_v1_1
+{
+ public:
+ // List of all recording directories used in recordings, timers (and optionally search timers or in epgsearchdirs.conf)
+ virtual std::set<std::string> ShortDirectoryList() = 0;
+ // Evaluate an expression against an event
+ virtual std::string Evaluate(const std::string& expr, const cEvent* event) = 0;
+};
+
+struct Epgsearch_services_v1_2
+{
+// in/out
+ std::auto_ptr<cServiceHandler_v1_2> handler;
+};
+
+#endif
diff --git a/setup.c b/setup.c
new file mode 100644
index 0000000..bed7b06
--- /dev/null
+++ b/setup.c
@@ -0,0 +1,204 @@
+#include <vdr/menuitems.h>
+#include "config.h"
+#include "setup.h"
+
+extern cSkinPearlHDConfig PearlHDConfig;
+
+// --- cSkinPearlHDSetupMenu ------------------------------------------------------
+class cSkinPearlHDSetupMenu : public cOsdMenu
+{
+private:
+ cSkinPearlHDConfig *tmpconfig;
+ void Setup(void);
+ const char *EpgImagesFormatItems[2];
+ const char *RecTitleInfoItems[3];
+
+protected:
+ virtual eOSState ProcessKey(eKeys Key);
+
+public:
+ cSkinPearlHDSetupMenu(cSkinPearlHDConfig *tmpPearlHDConfig);
+ virtual ~cSkinPearlHDSetupMenu();
+};
+
+cSkinPearlHDSetupMenu::cSkinPearlHDSetupMenu(cSkinPearlHDConfig *tmpConfig)
+:cOsdMenu("", 33)
+{
+ SetTitle(cString::sprintf("%s - '%s' %s", trVDR("Setup"), "PearlHD", tr("General")));
+
+ tmpconfig = tmpConfig;
+ EpgImagesFormatItems[0] = "png";
+ EpgImagesFormatItems[1] = "jpg";
+
+ RecTitleInfoItems[0] = tr("Don't show");
+ RecTitleInfoItems[1] = tr("Top");
+ RecTitleInfoItems[2] = tr("Bottom");
+
+ Setup();
+}
+
+cSkinPearlHDSetupMenu::~cSkinPearlHDSetupMenu()
+{
+}
+
+
+void cSkinPearlHDSetupMenu::Setup(void)
+{
+ Add(new cMenuEditBoolItem(tr("Display oClock text"), &tmpconfig->oClockText));
+ Add(new cMenuEditBoolItem(tr("Display clock in Recordings/Timer menu"), &tmpconfig->RecShowClock));
+ Add(new cMenuEditBoolItem(tr("Display epg images"), &tmpconfig->DisplayEpgImages));
+ Add(new cMenuEditStraItem(tr("Epg images format"), &tmpconfig->EpgImagesFormat, 2, EpgImagesFormatItems));
+ Add(new cMenuEditIntItem(tr("Padding sides"), &tmpconfig->MenuPaddingWidth));
+ Add(new cMenuEditIntItem(tr("Padding top/bottom"), &tmpconfig->MenuPaddingHeight));
+ Add(new cMenuEditIntItem(tr("Item line height"), &tmpconfig->LineHeight));
+ Add(new cMenuEditBoolItem(tr("Show running recordings in the header"), &tmpconfig->RecTitleInfoHead));
+ Add(new cMenuEditStraItem(tr("Show timers in the right bar at"), &tmpconfig->RecTitleInfo, 3, RecTitleInfoItems));
+}
+
+eOSState cSkinPearlHDSetupMenu::ProcessKey(eKeys Key)
+{
+ eOSState state = cOsdMenu::ProcessKey(Key);
+
+ if (state == osUnknown) {
+ switch (Key) {
+ case kOk:
+ case kBack:
+ state = osBack;
+ break;
+ default: break;
+ }
+ }
+
+ return state;
+}
+
+// --- cSkinPearlHDSetupChannelInfo ------------------------------------------------------
+class cSkinPearlHDSetupChannelInfo : public cOsdMenu
+{
+private:
+ cSkinPearlHDConfig *tmpconfig;
+ void Setup(void);
+ const char * ChannelLogoPosItems[3];
+ const char * ChannelLogoFormatItems[2];
+
+protected:
+ virtual eOSState ProcessKey(eKeys Key);
+
+public:
+ cSkinPearlHDSetupChannelInfo(cSkinPearlHDConfig *tmpConfig);
+ virtual ~cSkinPearlHDSetupChannelInfo();
+};
+
+cSkinPearlHDSetupChannelInfo::cSkinPearlHDSetupChannelInfo(cSkinPearlHDConfig *tmpConfig)
+:cOsdMenu("", 33)
+{
+ SetTitle(cString::sprintf("%s - '%s' %s", trVDR("Setup"), "PearlHD", tr("Channel Info")));
+
+ tmpconfig = tmpConfig;
+
+ ChannelLogoPosItems[0] = tr("Don't show");
+ ChannelLogoPosItems[1] = tr("Left");
+ ChannelLogoPosItems[2] = tr("Right");
+
+ ChannelLogoFormatItems[0] = "png";
+ ChannelLogoFormatItems[1] = "jpg";
+
+ Setup();
+}
+
+cSkinPearlHDSetupChannelInfo::~cSkinPearlHDSetupChannelInfo()
+{
+}
+
+void cSkinPearlHDSetupChannelInfo::Setup(void)
+{
+ Add(new cMenuEditStraItem(tr("Channel logo position"), &tmpconfig->ChannelLogoPos, 3, ChannelLogoPosItems));
+ Add(new cMenuEditStraItem(tr("Channel logo format"), &tmpconfig->ChannelLogoFormat, 2, ChannelLogoFormatItems));
+ Add(new cMenuEditStrItem(tr("Button red text"), &tmpconfig->ButtonRedText[0], 20));
+ Add(new cMenuEditStrItem(tr("Button green text"), &tmpconfig->ButtonGreenText[0], 20));
+ Add(new cMenuEditStrItem(tr("Button yellow text"), &tmpconfig->ButtonYellowText[0], 20));
+ Add(new cMenuEditStrItem(tr("Button blue text"), &tmpconfig->ButtonBlueText[0], 20));
+ Add(new cMenuEditBoolItem(tr("Display crypt symbols"), &tmpconfig->CryptSymbols));
+ Add(new cMenuEditIntItem(tr("Padding sides"), &tmpconfig->ChannelInfoPadding));
+}
+
+eOSState cSkinPearlHDSetupChannelInfo::ProcessKey(eKeys Key)
+{
+ eOSState state = cOsdMenu::ProcessKey(Key);
+
+ if (state == osUnknown) {
+ switch (Key) {
+ case kOk:
+ case kBack:
+ state = osBack;
+ break;
+ default: break;
+ }
+ }
+ return state;
+}
+
+
+// --- cSkinPearlHDSetup ------------------------------------------------------
+cSkinPearlHDSetup::cSkinPearlHDSetup(void)
+{
+ tmpPearlHDConfig = PearlHDConfig;
+
+ Setup();
+}
+
+cSkinPearlHDSetup::~cSkinPearlHDSetup()
+{
+}
+
+void cSkinPearlHDSetup::Setup(void)
+{
+ Add(new cOsdItem(tr("Channel Info"), osUser1));
+ Add(new cOsdItem(tr("Menu"), osUser2));
+}
+
+eOSState cSkinPearlHDSetup::ProcessKey(eKeys Key)
+{
+ bool hadSubMenu = HasSubMenu();
+ eOSState state = cOsdMenu::ProcessKey(Key);
+
+ if (hadSubMenu && !HasSubMenu() && Key == kOk)
+ Store();
+
+ switch (state) {
+ case osUser1:
+ AddSubMenu(new cSkinPearlHDSetupChannelInfo(&tmpPearlHDConfig));
+ state=osContinue;
+ break;
+ case osUser2:
+ AddSubMenu(new cSkinPearlHDSetupMenu(&tmpPearlHDConfig));
+ state=osContinue;
+ break;
+ default:
+ break;
+ }
+ return state;
+}
+
+void cSkinPearlHDSetup::Store(void)
+{
+ PearlHDConfig = tmpPearlHDConfig;
+
+ SetupStore("ChannelLogoPos", PearlHDConfig.ChannelLogoPos);
+ SetupStore("ChannelLogoFormat", PearlHDConfig.ChannelLogoFormat);
+ SetupStore("ButtonRedText", PearlHDConfig.ButtonRedText);
+ SetupStore("ButtonGreenText", PearlHDConfig.ButtonGreenText);
+ SetupStore("ButtonYellowText", PearlHDConfig.ButtonYellowText);
+ SetupStore("ButtonBlueText", PearlHDConfig.ButtonBlueText);
+ SetupStore("CryptSymbols", PearlHDConfig.CryptSymbols);
+ SetupStore("oClockText", PearlHDConfig.oClockText);
+ SetupStore("RecShowClock", PearlHDConfig.RecShowClock);
+ SetupStore("DisplayEpgImages", PearlHDConfig.DisplayEpgImages);
+ SetupStore("EpgImagesFormat", PearlHDConfig.EpgImagesFormat);
+ SetupStore("MenuPaddingWidth", PearlHDConfig.MenuPaddingWidth);
+ SetupStore("MenuPaddingHeight", PearlHDConfig.MenuPaddingHeight);
+ SetupStore("LineHeight", PearlHDConfig.LineHeight);
+ SetupStore("ChannelInfoPadding", PearlHDConfig.ChannelInfoPadding);
+ SetupStore("RecTitleInfoHead", PearlHDConfig.RecTitleInfoHead);
+ SetupStore("RecTitleInfo", PearlHDConfig.RecTitleInfo);
+}
diff --git a/setup.h b/setup.h
new file mode 100644
index 0000000..d8b7f98
--- /dev/null
+++ b/setup.h
@@ -0,0 +1,23 @@
+#ifndef __SKINPEARLHD_SETUP_H
+#define __SKINPEARLHD_SETUP_H
+
+#include <vdr/plugin.h>
+#include "config.h"
+
+
+class cSkinPearlHDSetup : public cMenuSetupPage
+{
+private:
+ cSkinPearlHDConfig tmpPearlHDConfig;
+ void Setup(void);
+
+protected:
+ virtual eOSState ProcessKey(eKeys Key);
+ virtual void Store(void);
+
+public:
+ cSkinPearlHDSetup(void);
+ virtual ~cSkinPearlHDSetup();
+};
+
+#endif //__SKINPEARLHD_SETUP_H
diff --git a/skinpearlhd.c b/skinpearlhd.c
new file mode 100644
index 0000000..18538eb
--- /dev/null
+++ b/skinpearlhd.c
@@ -0,0 +1,162 @@
+/*
+ * skinpearlhd.c: A plugin for the Video Disk Recorder
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ * $Id$
+ */
+#include <getopt.h>
+#include <string>
+
+#include "pearlhd.h"
+#include "setup.h"
+#include "config.h"
+
+#include <vdr/plugin.h>
+
+static const char *VERSION = "0.0.1";
+static const char *DESCRIPTION = "PearlHD Skin";
+
+class cPluginSkinpearlhd : public cPlugin {
+private:
+
+public:
+ cPluginSkinpearlhd(void);
+ virtual ~cPluginSkinpearlhd();
+ virtual const char *Version(void) { return VERSION; }
+ virtual const char *Description(void) { return DESCRIPTION; }
+ virtual const char *CommandLineHelp(void);
+ virtual bool ProcessArgs(int argc, char *argv[]);
+ virtual bool Initialize(void);
+ virtual bool Start(void);
+ virtual void Stop(void);
+ virtual void Housekeeping(void);
+ virtual void MainThreadHook(void);
+ virtual cString Active(void);
+ virtual time_t WakeupTime(void);
+ virtual const char *MainMenuEntry(void) { return NULL; }
+ virtual cOsdObject *MainMenuAction(void);
+ virtual cMenuSetupPage *SetupMenu(void);
+ virtual bool SetupParse(const char *Name, const char *Value);
+ virtual bool Service(const char *Id, void *Data = NULL);
+ virtual const char **SVDRPHelpPages(void);
+ virtual cString SVDRPCommand(const char *Command, const char *Option, int &ReplyCode);
+ };
+
+cPluginSkinpearlhd::cPluginSkinpearlhd(void)
+{
+ // Initialize any member variables here.
+ // DON'T DO ANYTHING ELSE THAT MAY HAVE SIDE EFFECTS, REQUIRE GLOBAL
+ // VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT!
+}
+
+cPluginSkinpearlhd::~cPluginSkinpearlhd()
+{
+ // Clean up after yourself!
+}
+
+const char *cPluginSkinpearlhd::CommandLineHelp(void)
+{
+ // Return a string that describes all known command line options.
+ return " -e DIR, --epgimages=DIR search in DIR for epg-images\n";
+}
+
+bool cPluginSkinpearlhd::ProcessArgs(int argc, char *argv[])
+{
+ // Implement command line argument processing here if applicable.
+ static struct option long_options[] = {
+ { "epgimages", required_argument, NULL, 'e' },
+ { NULL, no_argument, NULL, 0 }
+ };
+
+ int c;
+ while ((c = getopt_long(argc, argv, "e:", long_options, NULL)) != -1) {
+ switch (c) {
+ case 'e':
+ PearlHDConfig.SetEpgImagesDir(optarg);
+ break;
+ default:
+ break;
+ }
+ }
+ return true;
+}
+
+bool cPluginSkinpearlhd::Initialize(void)
+{
+ // Initialize any background activities the plugin shall perform.
+ return true;
+}
+
+bool cPluginSkinpearlhd::Start(void)
+{
+ // Start any background activities the plugin shall perform.
+ new cSkinPearlHD;
+ return true;
+}
+
+void cPluginSkinpearlhd::Stop(void)
+{
+ // Stop any background activities the plugin is performing.
+}
+
+void cPluginSkinpearlhd::Housekeeping(void)
+{
+ // Perform any cleanup or other regular tasks.
+}
+
+void cPluginSkinpearlhd::MainThreadHook(void)
+{
+ // Perform actions in the context of the main program thread.
+ // WARNING: Use with great care - see PLUGINS.html!
+}
+
+cString cPluginSkinpearlhd::Active(void)
+{
+ // Return a message string if shutdown should be postponed
+ return NULL;
+}
+
+time_t cPluginSkinpearlhd::WakeupTime(void)
+{
+ // Return custom wakeup time for shutdown script
+ return 0;
+}
+
+cOsdObject *cPluginSkinpearlhd::MainMenuAction(void)
+{
+ // Perform the action when selected from the main VDR menu.
+ return NULL;
+}
+
+cMenuSetupPage *cPluginSkinpearlhd::SetupMenu(void)
+{
+ // Return a setup menu in case the plugin supports one.
+ return new cSkinPearlHDSetup();
+}
+
+bool cPluginSkinpearlhd::SetupParse(const char *Name, const char *Value)
+{
+ // Parse your own setup parameters and store their values.
+ return PearlHDConfig.SetupParse(Name, Value);
+}
+
+bool cPluginSkinpearlhd::Service(const char *Id, void *Data)
+{
+ // Handle custom service requests from other plugins
+ return false;
+}
+
+const char **cPluginSkinpearlhd::SVDRPHelpPages(void)
+{
+ // Return help text for SVDRP commands this plugin implements
+ return NULL;
+}
+
+cString cPluginSkinpearlhd::SVDRPCommand(const char *Command, const char *Option, int &ReplyCode)
+{
+ // Process SVDRP commands this plugin implements
+ return NULL;
+}
+
+VDRPLUGINCREATOR(cPluginSkinpearlhd); // Don't touch this!