diff options
-rw-r--r-- | COPYING | 340 | ||||
-rw-r--r-- | HISTORY | 6 | ||||
-rw-r--r-- | Makefile | 115 | ||||
-rw-r--r-- | README | 37 | ||||
-rw-r--r-- | bitmap.c | 112 | ||||
-rw-r--r-- | bitmap.h | 35 | ||||
-rw-r--r-- | config.c | 58 | ||||
-rw-r--r-- | config.h | 40 | ||||
-rw-r--r-- | pearlhd.c | 1910 | ||||
-rw-r--r-- | pearlhd.h | 21 | ||||
-rw-r--r-- | po/de_DE.po | 173 | ||||
-rw-r--r-- | services/epgsearchservices.h | 195 | ||||
-rw-r--r-- | setup.c | 204 | ||||
-rw-r--r-- | setup.h | 23 | ||||
-rw-r--r-- | skinpearlhd.c | 162 |
15 files changed, 3431 insertions, 0 deletions
@@ -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. @@ -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 @@ -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 @@ -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); +} @@ -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! |