commit b0509b5182b6e0d04f05e6b3d5676b0d21f51966 Author: louis Date: Sat Sep 27 09:25:14 2014 +0200 initial commit version 0.0.1 diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..f90922e --- /dev/null +++ b/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/HISTORY b/HISTORY new file mode 100644 index 0000000..23775a8 --- /dev/null +++ b/HISTORY @@ -0,0 +1,7 @@ +VDR Plugin 'skindesigner' Revision History +--------------------------------------- + +2014-09-27: Version 0.0.1 + +- Initial revision. + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..1b32acc --- /dev/null +++ b/Makefile @@ -0,0 +1,176 @@ +# +# Makefile for a Video Disk Recorder plugin +# +# $Id$ Makefile 1.0 2014/07/24 louis Exp $ + +# External image lib to use: imagemagick, graphicsmagick +IMAGELIB = imagemagick + +# The official name of this plugin. +PLUGIN = skindesigner + +### 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 directory environment: + +# Use package data if installed...otherwise assume we're under the VDR source directory: +PKGCFG = $(if $(VDRDIR),$(shell pkg-config --variable=$(1) $(VDRDIR)/vdr.pc),$(shell pkg-config --variable=$(1) vdr || pkg-config --variable=$(1) ../../../vdr.pc)) +LIBDIR = $(call PKGCFG,libdir) +LOCDIR = $(call PKGCFG,locdir) +PLGCFG = $(call PKGCFG,plgcfg) +VDRCONFDIR = $(call PKGCFG,configdir) +PLGRESDIR = $(call PKGCFG,resdir)/plugins/$(PLUGIN) +TMPDIR ?= /tmp + +### The compiler options: +export CFLAGS = $(call PKGCFG,cflags) +export CXXFLAGS = $(call PKGCFG,cxxflags) + +### Allow user defined options to overwrite defaults: + +-include $(PLGCFG) + +### The version number of VDR's plugin API: +APIVERSION = $(call PKGCFG,apiversion) + +### The name of the distribution archive: +ARCHIVE = $(PLUGIN)-$(VERSION) +PACKAGE = vdr-$(ARCHIVE) + +### The name of the shared object file: +SOFILE = libvdr-$(PLUGIN).so + +### Includes and Defines and Dependencies: +DEFINES += -DPLUGIN_NAME_I18N='"$(PLUGIN)"' +DEFINES += $(shell xml2-config --cflags) + +INCLUDES += $(shell pkg-config --cflags freetype2 fontconfig) + +ifeq ($(IMAGELIB), imagemagick) + INCLUDES += $(shell pkg-config --cflags Magick++) + LIBS += $(shell pkg-config --libs Magick++) +else ifeq ($(IMAGELIB), graphicsmagick) + INCLUDES += $(shell pkg-config --cflags GraphicsMagick++) + LIBS += $(shell pkg-config --libs GraphicsMagick++) +endif + +LIBS += $(shell xml2-config --libs) + +### The object files: +OBJS = $(PLUGIN).o \ + config.o \ + setup.o \ + designer.o \ + displaychannel.o \ + displaymenu.o \ + displaymessage.o \ + displayreplay.o \ + displaytracks.o \ + displayvolume.o \ + libcore/pixmapcontainer.o \ + libcore/fontmanager.o \ + libcore/imagecache.o \ + libcore/imagemagickwrapper.o \ + libcore/imagescaler.o \ + libcore/helpers.o \ + libcore/imageloader.o \ + libcore/timers.o \ + libtemplate/globals.o \ + libtemplate/parameter.o \ + libtemplate/template.o \ + libtemplate/templateview.o \ + libtemplate/templateviewelement.o \ + libtemplate/templateviewlist.o \ + libtemplate/templatepixmap.o \ + libtemplate/templateviewtab.o \ + libtemplate/templatefunction.o \ + libtemplate/templateloopfunction.o \ + libtemplate/xmlparser.o \ + views/view.o \ + views/displaychannelview.o \ + views/displaymenurootview.o \ + views/displaymenuview.o \ + views/displaymenulistview.o \ + views/displaymenuitemview.o \ + views/displaymenuitemcurrentview.o \ + views/displaymenudetailview.o \ + views/displaymenutabview.o \ + views/displaymessageview.o \ + views/displayreplayview.o \ + views/displayvolumeview.o \ + views/displayaudiotracksview.o + +### The main target: + +all: $(SOFILE) i18n + +### Implicit rules: + +%.o: %.c + $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) -o $@ $< + +### Dependencies: + +MAKEDEP = $(CXX) -MM -MG +DEPFILE = .dependencies +$(DEPFILE): Makefile + @$(MAKEDEP) $(CXXFLAGS) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.c) > $@ + +-include $(DEPFILE) + +### Internationalization (I18N): + +PODIR = po +I18Npo = $(wildcard $(PODIR)/*.po) +I18Nmo = $(addsuffix .mo, $(foreach file, $(I18Npo), $(basename $(file)))) +I18Nmsgs = $(addprefix $(DESTDIR)$(LOCDIR)/, $(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='' -o $@ `ls $^` + +%.po: $(I18Npot) + msgmerge -U --no-wrap --no-location --backup=none -q -N $@ $< + @touch $@ + +$(I18Nmsgs): $(DESTDIR)$(LOCDIR)/%/LC_MESSAGES/vdr-$(PLUGIN).mo: $(PODIR)/%.mo + install -D -m644 $< $@ + +.PHONY: i18n +i18n: $(I18Nmo) $(I18Npot) + +install-i18n: $(I18Nmsgs) + +### Targets: + +$(SOFILE): $(OBJS) + $(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(OBJS) $(LIBS) -o $@ + +install-lib: $(SOFILE) + install -D $^ $(DESTDIR)$(LIBDIR)/$^.$(APIVERSION) + +install-themes: + mkdir -p $(DESTDIR)$(VDRCONFDIR)/themes + cp themes/* $(DESTDIR)$(VDRCONFDIR)/themes + +install-skins: + mkdir -p $(DESTDIR)$(PLGRESDIR)/skins + cp -r skins/* $(DESTDIR)$(PLGRESDIR)/skins + +install: install-lib install-i18n install-themes install-skins + +dist: $(I18Npo) clean + @-rm -rf $(TMPDIR)/$(ARCHIVE) + @mkdir $(TMPDIR)/$(ARCHIVE) + @cp -a * $(TMPDIR)/$(ARCHIVE) + @tar czf $(PACKAGE).tgz --exclude .git* --exclude *.o --exclude *.rej --exclude *.orig -C $(TMPDIR) $(ARCHIVE) + @-rm -rf $(TMPDIR)/$(ARCHIVE) + @echo Distribution package created as $(PACKAGE).tgz + +clean: + @-rm -f $(PODIR)/*.mo $(PODIR)/*.pot + @-rm -f $(OBJS) $(DEPFILE) *.so *.tgz core* *~ diff --git a/README b/README new file mode 100644 index 0000000..3f1a3f2 --- /dev/null +++ b/README @@ -0,0 +1,102 @@ +This is a "plugin" for the Video Disk Recorder (VDR). + +Written by: Louis Braun + +Project's homepage: http://projects.vdr-developer.org/projects/plg-skindesigner + +Latest version: http://projects.vdr-developer.org/projects/plg-skindesigner/files +GIT repository: git clone git://projects.vdr-developer.org/plg-skindesigner.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 +----------- + +Skindesigner is a VDR skin engine that displays XML based Skins. + +Currently two XML Skins (MetrixHD and nOpacity freestyle) are included in +/skins/ + +Requirements +------------ + +- VDR version >= 2.0.0 + +- Installed ImageMagick or GraphicsMagick for displaying png/jpg Icons, Channel Logos + and EPG Images (configurable during make via IMAGELIB = imagemagick|graphicsmagick + parameter) + +- libxml2 + +- for scaling the video picture to fit into the VDR menu window please use + softhddevice plugin revision 87c1c7be (2013-01-01) or newer. + +- epgsearch Git since commit ba7c6277 (2013-01-03) to correctly replace the schedules + menu with epgsearch + +Installation +------------ + +After "normal" Plugin installation you have to care about the paths for the +XML skins and epg images. The following paths can be set at startup: + +-s , --skinpath= + Path to the XML skins (Default: /plugins/skindesigner/skins/) + +-e path, --epgimages=path + Path to the epgimages (Default: /epgimages/) + +ResourceDirectory and CacheDirectory are taken from your VDR configuration (make.config +or vdr.pc). + +During a "make install" the included skins are automatically copied from +/skins/ to the configured path. + +For S2-6400 Users: Disable High Level OSD, otherwise the plugin will not be +loaded because lack of true color support + +For Xine-Plugin Users: Set "Blend scaled Auto" as OSD display mode to achieve +an suitable true color OSD. + +For Xineliboutput Users: Start vdr-sxfe with the --hud option enabled + +Since the default skin MetrixHD uses VDROpenSans as font which is not installed per +default, you may want to install this font (included in /fonts/) +first. Otherwise the inside VDRs OSD menu configured vdrOsd Font is used as default. + +Channel Logos +------------- + +Since each XML skin is responsible for it's used channel logos, skindesigner searches +for channel logos only in the skin dependend directory + +/plugins/skindesigner/skins//logos + +Each copy your used logos directly to this directory or set a symbolic link to a common +channellogo directory. + +I recommend to use channel logos from https://github.com/3PO/Senderlogos +To download them just change in the directory you want to place the logos +and do a: +git clone https://github.com/3PO/Senderlogos.git logos +An update of the logos can then be done with a "git pull" just inside this +directory. + +In this logo pack all files are named only with lower case letters. +Skindesigner uses the channel name CONVERTED TO LOWER CASE LETTERS to search for an +appropriate channel logo. With this, approximately 90% of the channel logos should work +immediately after placing the channel logos in the correct place. So if you have to change +the name of a channel logo (may be by inserting a space or a hyphen) so that it fits to +the channel name, only use lower case letters, and not the name of the channel with upper +and lower letters as displayed inside VDR. +If no logo is found for the channel name, additionally a search for a logo named as the +ChannelID is performed. Analog to the channel name the ChannelID is also converted to lower +case letters. This allows channel logos for channels with changing names (for instance +Sky Feed Channels). +Additional hint: some channels have slashes in their name (in germany nick/comedy for instance). +In this example, as a dirty hack just create a folder in your channel logo directory named +"nick" and place an image named "comedy.png" inside this folder. diff --git a/config.c b/config.c new file mode 100644 index 0000000..3b88b8e --- /dev/null +++ b/config.c @@ -0,0 +1,76 @@ +#include "config.h" +#include "libcore/helpers.h" +#include "libcore/imageloader.h" + +cDesignerConfig::cDesignerConfig() { + epgImagePathSet = false; + skinPathSet = false; + //Common + logoExtension = "png"; + numLogosPerSizeInitial = 30; + limitLogoCache = 1; + numLogosMax = 200; + debugImageLoading = 0; + //default logo width and height + logoWidth = 268; + logoHeight = 200; + replaceDecPoint = false; +} + +cDesignerConfig::~cDesignerConfig() { +} + +void cDesignerConfig::SetPathes(void) { + if (!skinPathSet) + skinPath = cString::sprintf("%s/skins/", cPlugin::ResourceDirectory(PLUGIN_NAME_I18N)); + if (!epgImagePathSet) + epgImagePath = cString::sprintf("%s/epgimages/", cPlugin::CacheDirectory(PLUGIN_NAME_I18N)); + + dsyslog("skindesigner: using Skin Directory %s", *skinPath); + dsyslog("skindesigner: using EPG Images Directory %s", *epgImagePath); + +} + +void cDesignerConfig::SetSkinPath(cString path) { + skinPath = CheckSlashAtEnd(*path); + skinPathSet = true; +} + +void cDesignerConfig::SetEpgImagePath(cString path) { + epgImagePath = CheckSlashAtEnd(*path); + epgImagePathSet = true; +} + +void cDesignerConfig::SetChannelLogoSize(void) { + cImageLoader imgLoader; + imgLoader.DeterminateChannelLogoSize(logoWidth, logoHeight); + dsyslog("skindesigner: using %dx%d px as original channel logo size", logoWidth, logoHeight); +} + +void cDesignerConfig::CheckDecimalPoint(void) { + struct lconv *pLocInfo; + pLocInfo = localeconv(); + string decimalPoint = pLocInfo->decimal_point; + if (decimalPoint.compare(".")) { + dsyslog("skindesigner: using decimal point %s", decimalPoint.c_str()); + replaceDecPoint = true; + decPoint = decimalPoint[0]; + } +} + +cString cDesignerConfig::CheckSlashAtEnd(std::string path) { + try { + if (!(path.at(path.size()-1) == '/')) + return cString::sprintf("%s/", path.c_str()); + } catch (...) {return path.c_str();} + return path.c_str(); +} + +bool cDesignerConfig::SetupParse(const char *Name, const char *Value) { + if (!strcasecmp(Name, "DebugImageLoading")) debugImageLoading = atoi(Value); + else if (!strcasecmp(Name, "LimitChannelLogoCache")) limitLogoCache = atoi(Value); + else if (!strcasecmp(Name, "NumberLogosInitially")) numLogosPerSizeInitial = atoi(Value); + else if (!strcasecmp(Name, "NumberLogosMax")) numLogosMax = atoi(Value); + else return false; + return true; +} diff --git a/config.h b/config.h new file mode 100644 index 0000000..73fb54f --- /dev/null +++ b/config.h @@ -0,0 +1,53 @@ +#ifndef __DESIGNER_CONFIG_H +#define __DESIGNER_CONFIG_H + +#include +#include +#include +#include +#include +#include +#include "libcore/fontmanager.h" +#include "libcore/imagecache.h" + +class cDesignerConfig { +private: + cString CheckSlashAtEnd(std::string path); + bool epgImagePathSet; + bool skinPathSet; +public: + cDesignerConfig(); + ~cDesignerConfig(); + bool SetupParse(const char *Name, const char *Value); + void SetSkinPath(cString path); + void SetEpgImagePath(cString path); + void SetPathes(void); + void SetChannelLogoSize(void); + void CheckDecimalPoint(void); + cString logoExtension; + cString skinPath; + cString epgImagePath; + int numLogosPerSizeInitial; + int limitLogoCache; + int numLogosMax; + int debugImageLoading; + int logoWidth; + int logoHeight; + bool replaceDecPoint; + char decPoint; +}; +#ifdef DEFINE_CONFIG + bool firstDisplay = true; + cDesignerConfig config; + cFontManager *fontManager; + cImageCache *imgCache; + cTheme Theme; +#else + extern bool firstDisplay; + extern cDesignerConfig config; + extern cFontManager *fontManager; + extern cImageCache *imgCache; + extern cTheme Theme; +#endif + +#endif //__DESIGNER_CONFIG_H diff --git a/designer.c b/designer.c new file mode 100644 index 0000000..61d0cfd --- /dev/null +++ b/designer.c @@ -0,0 +1,309 @@ +#include "designer.h" +#include "libcore/helpers.h" + +cSkinDesigner::cSkinDesigner(void) : cSkin("skindesigner", &::Theme) { + backupSkin = NULL; + useBackupSkin = false; + + SetOSDSize(); + osdTheme = Setup.OSDTheme; + config.SetPathes(); + config.SetChannelLogoSize(); + config.CheckDecimalPoint(); + fontManager = new cFontManager(); + imgCache = new cImageCache(); + + globals = NULL; + channelTemplate = NULL; + menuTemplate = NULL; + messageTemplate = NULL; + replayTemplate = NULL; + volumeTemplate = NULL; + audiotracksTemplate = NULL; + + cStopWatch watch; + bool ok = LoadTemplates(); + if (!ok) { + esyslog("skindesigner: error during loading of templates - using LCARS as backup"); + backupSkin = new cSkinLCARS(); + useBackupSkin = true; + } else { + CacheTemplates(); + watch.Stop("templates loaded and cache created"); + } +} + +cSkinDesigner::~cSkinDesigner(void) { + if (globals) + delete globals; + DeleteTemplates(); + if (backupSkin) + delete backupSkin; +} + +const char *cSkinDesigner::Description(void) { + return "SkinDesigner"; +} + +cSkinDisplayChannel *cSkinDesigner::DisplayChannel(bool WithInfo) { + cSkinDisplayChannel *displayChannel = NULL; + if (!useBackupSkin) { + ReloadCaches(); + displayChannel = new cSDDisplayChannel(channelTemplate, WithInfo); + } else { + displayChannel = backupSkin->DisplayChannel(WithInfo); + } + return displayChannel; +} + +cSkinDisplayMenu *cSkinDesigner::DisplayMenu(void) { + cSkinDisplayMenu *displayMenu = NULL; + if (!useBackupSkin) { + ReloadCaches(); + displayMenu = new cSDDisplayMenu(menuTemplate); + } else { + displayMenu = backupSkin->DisplayMenu(); + } + return displayMenu; +} + +cSkinDisplayReplay *cSkinDesigner::DisplayReplay(bool ModeOnly) { + cSkinDisplayReplay *displayReplay = NULL; + if (!useBackupSkin) { + ReloadCaches(); + displayReplay = new cSDDisplayReplay(replayTemplate, ModeOnly); + } else { + displayReplay = backupSkin->DisplayReplay(ModeOnly); + } + return displayReplay; +} + +cSkinDisplayVolume *cSkinDesigner::DisplayVolume(void) { + cSkinDisplayVolume *displayVolume = NULL; + if (!useBackupSkin) { + ReloadCaches(); + displayVolume = new cSDDisplayVolume(volumeTemplate); + } else { + displayVolume = backupSkin->DisplayVolume(); + } + return displayVolume; +} + +cSkinDisplayTracks *cSkinDesigner::DisplayTracks(const char *Title, int NumTracks, const char * const *Tracks) { + cSkinDisplayTracks *displayTracks = NULL; + if (!useBackupSkin) { + ReloadCaches(); + displayTracks = new cSDDisplayTracks(audiotracksTemplate, Title, NumTracks, Tracks); + } else { + displayTracks = backupSkin->DisplayTracks(Title, NumTracks, Tracks); + } + return displayTracks; +} + +cSkinDisplayMessage *cSkinDesigner::DisplayMessage(void) { + cSkinDisplayMessage *displayMessage = NULL; + if (!useBackupSkin) { + ReloadCaches(); + displayMessage = new cSDDisplayMessage(messageTemplate); + } else { + displayMessage = backupSkin->DisplayMessage(); + } + return displayMessage; +} + +void cSkinDesigner::Reload(void) { + dsyslog("skindesigner: forcing full reload of templates"); + if (cOsd::IsOpen()) { + esyslog("skindesigner: OSD is open, close first!"); + return; + } + DeleteTemplates(); + cStopWatch watch; + bool ok = LoadTemplates(); + if (!ok) { + esyslog("skindesigner: error during loading of templates - using LCARS as backup"); + if (!backupSkin) + backupSkin = new cSkinLCARS(); + useBackupSkin = true; + } else { + CacheTemplates(); + useBackupSkin = false; + watch.Stop("templates reloaded and cache created"); + } +} + +void cSkinDesigner::ListAvailableFonts(void) { + fontManager->ListAvailableFonts(); +} + +/********************************************************************************* +* PRIVATE FUNCTIONS +*********************************************************************************/ +void cSkinDesigner::DeleteTemplates(void) { + if (channelTemplate) { + delete channelTemplate; + channelTemplate = NULL; + } + if (menuTemplate) { + delete menuTemplate; + menuTemplate = NULL; + } + if (messageTemplate) { + delete messageTemplate; + messageTemplate = NULL; + } + if (replayTemplate) { + delete replayTemplate; + replayTemplate = NULL; + } + if (volumeTemplate) { + delete volumeTemplate; + volumeTemplate = NULL; + } + if (audiotracksTemplate) { + delete audiotracksTemplate; + audiotracksTemplate = NULL; + } +} + +bool cSkinDesigner::LoadTemplates(void) { + + globals = new cGlobals(); + bool ok = globals->ReadFromXML(); + if (!ok) { + esyslog("skindesigner: error parsing globals, aborting"); + return false; + } + //globals->Debug(); + + DeleteTemplates(); + + channelTemplate = new cTemplate(vtDisplayChannel); + channelTemplate->SetGlobals(globals); + ok = channelTemplate->ReadFromXML(); + if (!ok) { + esyslog("skindesigner: error reading displaychannel template, aborting"); + DeleteTemplates(); + return false; + } + channelTemplate->Translate(); + + menuTemplate = new cTemplate(vtDisplayMenu); + menuTemplate->SetGlobals(globals); + ok = menuTemplate->ReadFromXML(); + if (!ok) { + esyslog("skindesigner: error reading displaymenu template, aborting"); + DeleteTemplates(); + return false; + } + menuTemplate->Translate(); + + messageTemplate = new cTemplate(vtDisplayMessage); + messageTemplate->SetGlobals(globals); + ok = messageTemplate->ReadFromXML(); + if (!ok) { + esyslog("skindesigner: error reading displaymessage template, aborting"); + DeleteTemplates(); + return false; + } + messageTemplate->Translate(); + + replayTemplate = new cTemplate(vtDisplayReplay); + replayTemplate->SetGlobals(globals); + ok = replayTemplate->ReadFromXML(); + if (!ok) { + esyslog("skindesigner: error reading displayreplay template, aborting"); + DeleteTemplates(); + return false; + } + replayTemplate->Translate(); + + volumeTemplate = new cTemplate(vtDisplayVolume); + volumeTemplate->SetGlobals(globals); + ok = volumeTemplate->ReadFromXML(); + if (!ok) { + esyslog("skindesigner: error reading displayvolume template, aborting"); + DeleteTemplates(); + return false; + } + volumeTemplate->Translate(); + + audiotracksTemplate = new cTemplate(vtDisplayAudioTracks); + audiotracksTemplate->SetGlobals(globals); + ok = audiotracksTemplate->ReadFromXML(); + if (!ok) { + esyslog("skindesigner: error reading displayaudiotracks template, aborting"); + DeleteTemplates(); + return false; + } + audiotracksTemplate->Translate(); + + dsyslog("skindesigner: templates successfully validated and parsed"); + return true; +} + +void cSkinDesigner::CacheTemplates(void) { + channelTemplate->PreCache(); + menuTemplate->PreCache(); + messageTemplate->PreCache(); + replayTemplate->PreCache(); + volumeTemplate->PreCache(); + audiotracksTemplate->PreCache(); + dsyslog("skindesigner: templates cached"); + fontManager->CacheFonts(channelTemplate); + fontManager->CacheFonts(menuTemplate); + fontManager->CacheFonts(messageTemplate); + fontManager->CacheFonts(replayTemplate); + fontManager->CacheFonts(volumeTemplate); + fontManager->CacheFonts(audiotracksTemplate); + dsyslog("skindesigner: fonts cached"); + dsyslog("skindesigner: caching images..."); + imgCache->Clear(); + channelTemplate->CacheImages(); + menuTemplate->CacheImages(); + messageTemplate->CacheImages(); + replayTemplate->CacheImages(); + volumeTemplate->CacheImages(); + audiotracksTemplate->CacheImages(); + imgCache->Debug(false); +} + +void cSkinDesigner::ReloadCaches(void) { + if (OsdSizeChanged() || ThemeChanged()) { + cStopWatch watch; + bool ok = LoadTemplates(); + if (ok) { + CacheTemplates(); + } + watch.Stop("templates reloaded and cache recreated"); + } +} + +void cSkinDesigner::SetOSDSize(void) { + osdSize.SetWidth(cOsd::OsdWidth()); + osdSize.SetHeight(cOsd::OsdHeight()); + osdSize.SetX(cOsd::OsdLeft()); + osdSize.SetY(cOsd::OsdTop()); +} + +bool cSkinDesigner::OsdSizeChanged(void) { + if ((osdSize.Width() != cOsd::OsdWidth()) || + (osdSize.Height() != cOsd::OsdHeight()) || + (osdSize.X() != cOsd::OsdLeft()) || + (osdSize.Y() != cOsd::OsdTop())) { + dsyslog("skindesigner: osd size changed"); + dsyslog("skindesigner: old osd size: top %d left %d size %d * %d", osdSize.X(), osdSize.Y(), osdSize.Width(), osdSize.Height()); + SetOSDSize(); + dsyslog("skindesigner: new osd size: top %d left %d size %d * %d", osdSize.X(), osdSize.Y(), osdSize.Width(), osdSize.Height()); + return true; + } + return false; +} + +bool cSkinDesigner::ThemeChanged(void) { + if (osdTheme.compare(Setup.OSDTheme) != 0) { + osdTheme = Setup.OSDTheme; + return true; + } + return false; +} \ No newline at end of file diff --git a/designer.h b/designer.h new file mode 100644 index 0000000..4ba4f63 --- /dev/null +++ b/designer.h @@ -0,0 +1,49 @@ +#ifndef __SKINDESIGNER_H +#define __SKINDESIGNER_H + +#include "config.h" +#include "libtemplate/template.h" +#include "libtemplate/xmlparser.h" +#include "displaychannel.h" +#include "displaymenu.h" +#include "displayreplay.h" +#include "displayvolume.h" +#include "displaytracks.h" +#include "displaymessage.h" +#include + +class cSkinDesigner : public cSkin { +private: + cSkinLCARS *backupSkin; + bool useBackupSkin; + cRect osdSize; + std::string osdTheme; + cGlobals *globals; + cTemplate *channelTemplate; + cTemplate *menuTemplate; + cTemplate *messageTemplate; + cTemplate *replayTemplate; + cTemplate *volumeTemplate; + cTemplate *audiotracksTemplate; + void DeleteTemplates(void); + void ReloadCaches(void); + bool LoadTemplates(void); + void CacheTemplates(void); + void SetOSDSize(void); + bool OsdSizeChanged(void); + bool ThemeChanged(void); +public: + cSkinDesigner(void); + virtual ~cSkinDesigner(void); + 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); + void Reload(void); + void ListAvailableFonts(void); +}; + +#endif //__SKINDESIGNER_H diff --git a/displaychannel.c b/displaychannel.c new file mode 100644 index 0000000..4e99002 --- /dev/null +++ b/displaychannel.c @@ -0,0 +1,193 @@ +#include "displaychannel.h" +#include "libcore/timers.h" + +cSDDisplayChannel::cSDDisplayChannel(cTemplate *channelTemplate, bool WithInfo) { + if (firstDisplay) { + firstDisplay = false; + doOutput = false; + return; + } else if (!channelTemplate) { + esyslog("skindesigner: displayChannel no valid template - aborting"); + doOutput = false; + return; + } else { + doOutput = true; + } + groupSep = false; + present = NULL; + currentLast = 0; + channelChange = false; + initial = true; + + channelView = new cDisplayChannelView(channelTemplate->GetRootView()); + if (!channelView->createOsd()) { + doOutput = false; + return; + } + channelView->DrawBackground(); + channelView->DrawSignalBackground(); +} + +cSDDisplayChannel::~cSDDisplayChannel() { + if (!doOutput) + return; + delete channelView; +} + +void cSDDisplayChannel::SetChannel(const cChannel *Channel, int Number) { + if (!doOutput) + return; + + channelChange = true; + groupSep = false; + + cString ChannelNumber(""); + cString ChannelName(""); + cString ChannelID(""); + + if (Channel) { + ChannelName = Channel->Name(); + ChannelID = Channel->GetChannelID().ToString(); + if (!Channel->GroupSep()) { + ChannelNumber = cString::sprintf("%d%s", Channel->Number(), Number ? "-" : ""); + } else { + groupSep = true; + } + } else if (Number) { + ChannelNumber = cString::sprintf("%d-", Number); + } else { + ChannelName = ChannelString(NULL, 0); + } + channelView->ClearChannel(); + channelView->ClearEPGInfo(); + channelView->ClearStatusIcons(); + channelView->ClearChannelGroups(); + channelView->ClearScraperContent(); + if (!groupSep) { + channelView->DrawChannel(ChannelNumber, ChannelName, ChannelID, (Number > 0)?true:false); + channelView->DrawProgressBarBack(); + channelView->DrawSignalBackground(); + if (Channel) + channelView->DrawStatusIcons(Channel); + } else { + channelView->ClearSignal(); + channelView->ClearSignalBackground(); + channelView->ClearProgressBar(); + channelView->ClearProgressBarBack(); + if (Channel) + channelView->DrawChannelGroups(Channel, ChannelName); + } + +} + +void cSDDisplayChannel::SetEvents(const cEvent *Present, const cEvent *Following) { + if (!doOutput) + return; + + present = Present; + channelView->ClearProgressBar(); + if (!groupSep) { + channelView->ClearEPGInfo(); + } + + cGlobalSortedTimers SortedTimers;// local and remote timers + + bool recPresent = false; + if (Present) { + if (!groupSep) { + SetProgressBar(Present); + } + eTimerMatch TimerMatch = tmNone; + const cTimer *Timer = Timers.GetMatch(Present, &TimerMatch); + if (Timer && Timer->Recording()) { + recPresent = true; + } + for (int i = 0; i < SortedTimers.Size() && !recPresent; i++) + if (const cTimer *Timer = SortedTimers[i]) + if (Timer->Channel()->GetChannelID() == Present->ChannelID()) + if (const cEvent *timerEvent = Timer->Event()) + if (Present->EventID() == timerEvent->EventID()) + recPresent = Timer->Recording(); + + } + bool recFollowing = false; + if (Following) { + recFollowing = Following->HasTimer(); + for (int i = 0; i < SortedTimers.Size() && !recFollowing; i++) + if (const cTimer *Timer = SortedTimers[i]) + if (Timer->Channel()->GetChannelID() == Following->ChannelID()) + if (const cEvent *timerEvent = Timer->Event()) + if (Following->EventID() == timerEvent->EventID()) + recFollowing = true; + } + + if (Present || Following) { + channelView->DrawEPGInfo(Present, Following, recPresent, recFollowing); + channelView->DrawScraperContent(Present); + } +} + +void cSDDisplayChannel::SetProgressBar(const cEvent *present) { + int Current = 0; + int Total = 0; + time_t t = time(NULL); + if (t > present->StartTime()) + Current = t - present->StartTime(); + Total = present->Duration(); + if ((Current > currentLast + 3) || initial || channelChange) { + currentLast = Current; + cString start = present->GetTimeString(); + cString stop = present->GetEndTimeString(); + channelView->DrawProgressBar(start, stop, Current, Total); + } +} + + +void cSDDisplayChannel::SetMessage(eMessageType Type, const char *Text) { + if (!doOutput) + return; + channelView->ClearChannel(); + channelView->ClearEPGInfo(); + channelView->ClearStatusIcons(); + channelView->ClearScreenResolution(); + channelView->ClearProgressBar(); + channelView->ClearProgressBarBack(); + channelView->ClearSignal(); + channelView->ClearSignalBackground(); + channelView->ClearScraperContent(); + channelView->DisplayMessage(Type, Text); + groupSep = true; +} + +void cSDDisplayChannel::Flush(void) { + if (!doOutput) + return; + + if (initial || channelChange) { + channelView->DrawDate(); + } + + if (present) { + SetProgressBar(present); + } else { + channelView->ClearProgressBar(); + } + + if (!groupSep) { + channelView->DrawScreenResolution(); + channelView->DrawSignal(); + } else { + channelView->ClearStatusIcons(); + channelView->ClearScreenResolution(); + channelView->ClearSignal(); + channelView->ClearSignalBackground(); + } + + if (initial) { + channelView->DoStart(); + } + + initial = false; + channelChange = false; + channelView->Flush(); +} \ No newline at end of file diff --git a/displaychannel.h b/displaychannel.h new file mode 100644 index 0000000..44d69e5 --- /dev/null +++ b/displaychannel.h @@ -0,0 +1,32 @@ +#ifndef __DISPLAYCHANNEL_H +#define __DISPLAYCHANNEL_H + +#include +#include "config.h" +#include "libtemplate/template.h" +#include "views/displaychannelview.h" + +class cSDDisplayChannel : public cSkinDisplayChannel { +private: + cDisplayChannelView *channelView; + bool doOutput; + bool initial; + bool groupSep; + bool channelChange; + time_t lastSignalDisplay; + int lastSignalStrength; + int lastSignalQuality; + int lastScreenWidth; + int currentLast; + bool showSignal; + const cEvent *present; + void SetProgressBar(const cEvent *present); +public: + cSDDisplayChannel(cTemplate *channelTemplate, bool WithInfo); + virtual ~cSDDisplayChannel(); + 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); +}; +#endif //__DISPLAYCHANNEL_H \ No newline at end of file diff --git a/displaymenu.c b/displaymenu.c new file mode 100644 index 0000000..73e489d --- /dev/null +++ b/displaymenu.c @@ -0,0 +1,233 @@ +#include "displaymenu.h" +#include "libcore/helpers.h" + +cSDDisplayMenu::cSDDisplayMenu(cTemplate *menuTemplate) { + doOutput = true; + state = vsInit; + if (!menuTemplate) { + doOutput = false; + esyslog("skindesigner: displayMenu no valid template - aborting"); + return; + } + rootView = new cDisplayMenuRootView(menuTemplate->GetRootView()); + if (!rootView->createOsd()) { + doOutput = false; + return; + } +} + +cSDDisplayMenu::~cSDDisplayMenu() { + if (!doOutput) + return; + delete rootView; +} + +void cSDDisplayMenu::Scroll(bool Up, bool Page) { + if (!doOutput) + return; + rootView->KeyInput(Up, Page); +} + +int cSDDisplayMenu::MaxItems(void) { + if (!doOutput) + return 0; + int maxItems = rootView->GetMaxItems(); + return maxItems; +} + +void cSDDisplayMenu::Clear(void) { + if (!doOutput) + return; + rootView->Clear(); +} + +void cSDDisplayMenu::SetMenuCategory(eMenuCategory MenuCat) { + if (!doOutput) + return; + rootView->SetMenu(MenuCat, (state == vsInit) ? true : false); + cSkinDisplayMenu::SetMenuCategory(MenuCat); + if (state != vsInit) + state = vsMenuInit; +} + +void cSDDisplayMenu::SetTitle(const char *Title) { + if (!doOutput) + return; + rootView->SetTitle(Title); +} + +void cSDDisplayMenu::SetButtons(const char *Red, const char *Green, const char *Yellow, const char *Blue) { + if (!doOutput) + return; + rootView->SetButtonTexts(Red, Green, Yellow, Blue); + if (state != vsInit && MenuCategory() != mcMain) + state = vsMenuInit; +} + +void cSDDisplayMenu::SetMessage(eMessageType Type, const char *Text) { + if (!doOutput) + return; + rootView->SetMessage(Type, Text); + rootView->DoFlush(); +} + +bool cSDDisplayMenu::SetItemEvent(const cEvent *Event, int Index, bool Current, bool Selectable, const cChannel *Channel, bool WithDate, eTimerMatch TimerMatch) { + if (!doOutput) + return true; + if (!rootView->SubViewAvailable()) + return false; + if (Current) { + if (Channel) { + rootView->SetChannel(Channel); + } else if (Event) { + rootView->SetChannel(Channels.GetByChannelID(Event->ChannelID())); + } + } + cDisplayMenuListView *list = rootView->GetListView(); + if (!list) + return false; + list->AddSchedulesMenuItem(Index, Event, Channel, TimerMatch, MenuCategory(), Current, Selectable); + if (state == vsIdle) + state = vsMenuUpdate; + return true; +} + +bool cSDDisplayMenu::SetItemTimer(const cTimer *Timer, int Index, bool Current, bool Selectable) { + if (!doOutput) + return true; + if (!rootView->SubViewAvailable()) + return false; + cDisplayMenuListView *list = rootView->GetListView(); + if (!list) + return false; + list->AddTimersMenuItem(Index, Timer, Current, Selectable); + if (state == vsIdle) + state = vsMenuUpdate; + return true; +} + +bool cSDDisplayMenu::SetItemChannel(const cChannel *Channel, int Index, bool Current, bool Selectable, bool WithProvider) { + if (!doOutput) + return true; + if (!rootView->SubViewAvailable()) + return false; + cDisplayMenuListView *list = rootView->GetListView(); + if (!list) + return false; + list->AddChannelsMenuItem(Index, Channel, WithProvider, Current, Selectable); + if (state == vsIdle) + state = vsMenuUpdate; + return true; +} + +bool cSDDisplayMenu::SetItemRecording(const cRecording *Recording, int Index, bool Current, bool Selectable, int Level, int Total, int New) { + if (!doOutput) + return true; + if (!rootView->SubViewAvailable()) + return false; + cDisplayMenuListView *list = rootView->GetListView(); + if (!list) + return false; + list->AddRecordingMenuItem(Index, Recording, Level, Total, New, Current, Selectable); + if (state == vsIdle) + state = vsMenuUpdate; + return true; +} + +void cSDDisplayMenu::SetItem(const char *Text, int Index, bool Current, bool Selectable) { + if (!doOutput) + return; + cDisplayMenuListView *list = rootView->GetListView(); + if (!list) { + return; + } + eMenuCategory cat = MenuCategory(); + if (cat == mcMain) { + list->AddMainMenuItem(Index, Text, Current, Selectable); + } else if (cat == mcSetup) { + list->AddSetupMenuItem(Index, Text, Current, Selectable); + } else { + string *tabTexts = new string[MaxTabs]; + for (int i=0; iAddDefaultMenuItem(Index, tabTexts, Current, Selectable); + SetEditableWidth( rootView->GetListViewWidth() / 2); + } + if (state == vsIdle) + state = vsMenuUpdate; +} + +void cSDDisplayMenu::SetTabs(int Tab1, int Tab2, int Tab3, int Tab4, int Tab5) { + if (!doOutput) + return; + rootView->SetTabs(Tab1, Tab2, Tab3, Tab4, Tab5); +} + +int cSDDisplayMenu::GetTextAreaWidth(void) const { + int areaWidth = rootView->GetTextAreaWidth(); + return areaWidth; +} + +const cFont *cSDDisplayMenu::GetTextAreaFont(bool FixedFont) const { + return NULL; +} + +void cSDDisplayMenu::SetScrollbar(int Total, int Offset) { + if (!doOutput) + return; + rootView->RenderMenuScrollBar(Total, Offset); +} + +void cSDDisplayMenu::SetEvent(const cEvent *Event) { + if (!doOutput) + return; + rootView->SetDetailedViewEvent(Event); + state = vsMenuDetail; +} + +void cSDDisplayMenu::SetRecording(const cRecording *Recording) { + if (!doOutput) + return; + rootView->SetDetailedViewRecording(Recording); + state = vsMenuDetail; +} + +void cSDDisplayMenu::SetText(const char *Text, bool FixedFont) { + if (!doOutput) + return; + rootView->SetDetailedViewText(Text); + state = vsMenuDetail; +} + +void cSDDisplayMenu::Flush(void) { + if (!doOutput) + return; + if (state == vsInit) { + rootView->Start(); + rootView->RenderMenuItems(); + rootView->DoFlush(); + } else if (state == vsMenuInit) { + rootView->Render(); + rootView->DoFlush(); + rootView->RenderMenuItems(); + rootView->DoFlush(); + } else if (state == vsMenuUpdate) { + rootView->RenderMenuItems(); + rootView->DoFlush(); + } else if (state == vsMenuDetail) { + rootView->Render(); + rootView->DoFlush(); + rootView->RenderDetailView(); + rootView->DoFlush(); + } else { + if (rootView->RenderDynamicElements()) + rootView->DoFlush(); + } + state = vsIdle; +} diff --git a/displaymenu.h b/displaymenu.h new file mode 100644 index 0000000..58bc9c9 --- /dev/null +++ b/displaymenu.h @@ -0,0 +1,48 @@ +#ifndef __DISPLAYMENU_H +#define __DISPLAYMENU_H + +#include "designer.h" +#include "libtemplate/template.h" +#include "views/displaymenurootview.h" + +enum eViewState { + vsInit, + vsMenuInit, + vsMenuUpdate, + vsMenuDetail, + vsIdle +}; + +class cSDDisplayMenu : public cSkinDisplayMenu { +private: + cDisplayMenuRootView *rootView; + eViewState state; + bool doOutput; +protected: + int Tab(int n); +public: + cSDDisplayMenu(cTemplate *menuTemplate); + virtual ~cSDDisplayMenu(); + virtual void Scroll(bool Up, bool Page); + virtual int MaxItems(void); + virtual void Clear(void); + virtual void SetMenuCategory(eMenuCategory MenuCat); + 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 bool SetItemEvent(const cEvent *Event, int Index, bool Current, bool Selectable, const cChannel *Channel, bool WithDate, eTimerMatch TimerMatch); + virtual bool SetItemTimer(const cTimer *Timer, int Index, bool Current, bool Selectable); + virtual bool SetItemChannel(const cChannel *Channel, int Index, bool Current, bool Selectable, bool WithProvider); + virtual bool SetItemRecording(const cRecording *Recording, int Index, bool Current, bool Selectable, int Level, int Total, int New); + virtual void SetScrollbar(int Total, int Offset); + virtual void SetEvent(const cEvent *Event); + virtual void SetRecording(const cRecording *Recording); + virtual void SetText(const char *Text, bool FixedFont); + virtual void Flush(void); + virtual void SetTabs(int Tab1, int Tab2 = 0, int Tab3 = 0, int Tab4 = 0, int Tab5 = 0); + virtual int GetTextAreaWidth(void) const; + virtual const cFont *GetTextAreaFont(bool FixedFont) const; +}; + +#endif //__DISPLAYMENU_H diff --git a/displaymessage.c b/displaymessage.c new file mode 100644 index 0000000..f64a898 --- /dev/null +++ b/displaymessage.c @@ -0,0 +1,43 @@ +#include "displaymessage.h" + +cSDDisplayMessage::cSDDisplayMessage(cTemplate *messageTemplate) { + doOutput = true; + initial = true; + if (!messageTemplate) { + doOutput = false; + esyslog("skindesigner: displayMessage no valid template - aborting"); + return; + } + messageView = new cDisplayMessageView(messageTemplate->GetRootView()); + if (!messageView->createOsd()) { + doOutput = false; + return; + } + messageView->DrawBackground(); +} + +cSDDisplayMessage::~cSDDisplayMessage() { + if (!doOutput) + return; + delete messageView; +} + +void cSDDisplayMessage::SetMessage(eMessageType Type, const char *Text) { + if (!doOutput) + return; + if (!Text) + return; + messageView->DrawMessage(Type, Text); +} + + +void cSDDisplayMessage::Flush(void) { + if (!doOutput) + return; + if (initial) { + messageView->DoFadeIn(); + initial = false; + } else { + messageView->Flush(); + } +} diff --git a/displaymessage.h b/displaymessage.h new file mode 100644 index 0000000..f1fd01b --- /dev/null +++ b/displaymessage.h @@ -0,0 +1,22 @@ +#ifndef __DISPLAYMESSAGE_H +#define __DISPLAYMESSAGE_H + +#include +#include +#include "config.h" +#include "libtemplate/template.h" +#include "views/displaymessageview.h" + +class cSDDisplayMessage : public cSkinDisplayMessage { +private: + cDisplayMessageView *messageView; + bool doOutput; + bool initial; +public: + cSDDisplayMessage(cTemplate *messageTemplate); + virtual ~cSDDisplayMessage(); + virtual void SetMessage(eMessageType Type, const char *Text); + virtual void Flush(void); +}; + +#endif //__DISPLAYMESSAGE_H \ No newline at end of file diff --git a/displayreplay.c b/displayreplay.c new file mode 100644 index 0000000..53a43d8 --- /dev/null +++ b/displayreplay.c @@ -0,0 +1,131 @@ +#define __STL_CONFIG_H +#include "displayreplay.h" + +cSDDisplayReplay::cSDDisplayReplay(cTemplate *replayTemplate, bool ModeOnly) { + doOutput = true; + initial = true; + modeOnly = ModeOnly; + numMarksLast = 0; + lastMarks = NULL; + if (!replayTemplate) { + doOutput = false; + esyslog("skindesigner: displayReplay no valid template - aborting"); + return; + } + replayView = new cDisplayReplayView(replayTemplate->GetRootView()); + if (!replayView->createOsd()) { + doOutput = false; + return; + } + replayView->DrawBackground(modeOnly); +} + +cSDDisplayReplay::~cSDDisplayReplay() { + if (!doOutput) + return; + delete replayView; + if (lastMarks) { + delete[] lastMarks; + } +} + +void cSDDisplayReplay::SetRecording(const cRecording *Recording) { + if (!doOutput) + return; + replayView->DrawTitle(Recording); + replayView->DrawRecordingInformation(Recording); + replayView->DrawScraperContent(Recording); +} + +void cSDDisplayReplay::SetMode(bool Play, bool Forward, int Speed) { + if (!doOutput) + return; + replayView->DrawControlIcons(Play, Forward, Speed, modeOnly); +} + +void cSDDisplayReplay::SetProgress(int Current, int Total) { + if (!doOutput) + return; + replayView->DrawProgressBar(Current, Total); + if (MarksChanged()) { + replayView->DrawMarks(marks, Total); + } +} + +void cSDDisplayReplay::SetCurrent(const char *Current) { + if (!doOutput) + return; + replayView->DrawCurrent(Current); +} + +void cSDDisplayReplay::SetTotal(const char *Total) { + if (!doOutput) + return; + replayView->DrawTotal(Total); +} + +void cSDDisplayReplay::SetJump(const char *Jump) { + if (!doOutput) + return; + replayView->DrawJump(Jump); +} + +void cSDDisplayReplay::SetMessage(eMessageType Type, const char *Text) { + if (!doOutput) + return; + replayView->DrawMessage(Type, Text); +} + +void cSDDisplayReplay::Flush(void) { + if (!doOutput) + return; + replayView->DrawDate(modeOnly); + if (initial) { + replayView->DoFadeIn(); + initial = false; + } else { + replayView->Flush(); + } +} + +/**************************************************************************************** +* Private Functions +*****************************************************************************************/ + +bool cSDDisplayReplay::MarksChanged(void) { + if (!marks) + return false; + int numMarks = marks->Count(); + if (numMarks != numMarksLast) { + RememberMarks(); + return true; + } + if (!lastMarks) + return false; + int i=0; + for (const cMark *m = marks->First(); m; m = marks->Next(m)) { + if (m->Position() != lastMarks[i]) { + RememberMarks(); + return true; + } + i++; + } + return false; +} + +void cSDDisplayReplay::RememberMarks(void) { + if (!marks) + return; + numMarksLast = marks->Count(); + if (numMarksLast < 1) + return; + if (lastMarks) { + delete[] lastMarks; + } + lastMarks = new int[numMarksLast]; + int i=0; + for (const cMark *m = marks->First(); m; m = marks->Next(m)) { + lastMarks[i] = m->Position(); + i++; + } +} diff --git a/displayreplay.h b/displayreplay.h new file mode 100644 index 0000000..a63c8d8 --- /dev/null +++ b/displayreplay.h @@ -0,0 +1,34 @@ +#ifndef __DISPLAYREPLAY_H +#define __DISPLAYREPLAY_H + +#include +#include +#include "config.h" +#include "libtemplate/template.h" +#include "views/displayreplayview.h" + +class cSDDisplayReplay : public cSkinDisplayReplay { +private: + cDisplayReplayView *replayView; + bool initial; + bool doOutput; + bool modeOnly; + int numMarksLast; + int *lastMarks; + bool MarksChanged(void); + void RememberMarks(void); +public: + cSDDisplayReplay(cTemplate *replayTemplate, bool ModeOnly); + virtual ~cSDDisplayReplay(); + virtual void SetRecording(const cRecording *Recording); + 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); +}; + +#endif //__DISPLAYREPLAY_H \ No newline at end of file diff --git a/displaytracks.c b/displaytracks.c new file mode 100644 index 0000000..6316221 --- /dev/null +++ b/displaytracks.c @@ -0,0 +1,58 @@ +#include "displaytracks.h" + + +cSDDisplayTracks::cSDDisplayTracks(cTemplate *audiotracksTemplate, const char *Title, int NumTracks, const char * const *Tracks) { + initial = true; + numTracks = NumTracks; + doOutput = true; + currentTrack = 0; + menuTitle = Title; + if (!audiotracksTemplate) { + esyslog("skindesigner: displayTracks no valid template - aborting"); + doOutput = false; + return; + } + tracksView = new cDisplayAudiotracksView(NumTracks, audiotracksTemplate->GetRootView()); + if (!tracksView->createOsd()) { + doOutput = false; + return; + } + tracksView->DrawBackground(); + + cDisplayMenuListView *list = tracksView->GetListView(); + if (list) { + for (int i = 0; i < NumTracks; i++) { + list->AddTracksMenuItem(i, Tracks[i], (i==currentTrack)?true:false, true); + } + } +} + +cSDDisplayTracks::~cSDDisplayTracks() { + if (!doOutput) + return; + delete tracksView; +} + +void cSDDisplayTracks::SetTrack(int Index, const char * const *Tracks) { + cDisplayMenuListView *list = tracksView->GetListView(); + if (list) { + list->AddTracksMenuItem(currentTrack, Tracks[currentTrack], false, true); + list->AddTracksMenuItem(Index, Tracks[Index], true, true); + currentTrack = Index; + } +} + +void cSDDisplayTracks::SetAudioChannel(int AudioChannel) { + tracksView->DrawHeader(menuTitle, AudioChannel); +} + +void cSDDisplayTracks::Flush(void) { + if (!doOutput) + return; + if (initial) { + tracksView->DoFadeIn(); + } + initial = false; + tracksView->RenderMenuItems(); + tracksView->Flush(); +} diff --git a/displaytracks.h b/displaytracks.h new file mode 100644 index 0000000..4dd978c --- /dev/null +++ b/displaytracks.h @@ -0,0 +1,27 @@ +#ifndef __DISPLAYTRACKS_H +#define __DISPLAYTRACKS_H + +#include +#include +#include "config.h" +#include "libtemplate/template.h" +#include "views/displayaudiotracksview.h" + +class cSDDisplayTracks : public cSkinDisplayTracks { +private: + cDisplayAudiotracksView *tracksView; + bool initial; + int numTracks; + bool doOutput; + int currentTrack; + const char *menuTitle; +public: + cSDDisplayTracks(cTemplate *audiotracksTemplate, const char *Title, int NumTracks, const char * const *Tracks); + virtual ~cSDDisplayTracks(); + virtual void SetTrack(int Index, const char * const *Tracks); + virtual void SetAudioChannel(int AudioChannel); + virtual void Flush(void); +}; + + +#endif //__DISPLAYTRACKS_H \ No newline at end of file diff --git a/displayvolume.c b/displayvolume.c new file mode 100644 index 0000000..5efa32f --- /dev/null +++ b/displayvolume.c @@ -0,0 +1,43 @@ +#include "displayvolume.h" + +#include "config.h" +#include "libcore/helpers.h" + +cSDDisplayVolume::cSDDisplayVolume(cTemplate *volumeTemplate) { + doOutput = true; + initial = true; + if (!volumeTemplate) { + doOutput = false; + esyslog("skindesigner: displayVolume no valid template - aborting"); + return; + } + volumeView = new cDisplayVolumeView(volumeTemplate->GetRootView()); + if (!volumeView->createOsd()) { + doOutput = false; + } else { + volumeView->DrawBackground(); + } +} + +cSDDisplayVolume::~cSDDisplayVolume() { + if (!doOutput) + return; + delete volumeView; +} + +void cSDDisplayVolume::SetVolume(int Current, int Total, bool Mute) { + if (!doOutput) + return; + volumeView->DrawVolume(Current, Total, Mute); +} + +void cSDDisplayVolume::Flush(void) { + if (!doOutput) + return; + if (initial) { + volumeView->DoFadeIn(); + initial = false; + } else { + volumeView->Flush(); + } +} diff --git a/displayvolume.h b/displayvolume.h new file mode 100644 index 0000000..1bfc877 --- /dev/null +++ b/displayvolume.h @@ -0,0 +1,21 @@ +#ifndef __DISPLAYVOLUME_H +#define __DISPLAYVOLUME_H + +#include +#include "config.h" +#include "libtemplate/template.h" +#include "views/displayvolumeview.h" + +class cSDDisplayVolume : public cSkinDisplayVolume { +private: + cDisplayVolumeView *volumeView; + bool doOutput; + bool initial; +public: + cSDDisplayVolume(cTemplate *volumeTemplate); + virtual ~cSDDisplayVolume(); + virtual void SetVolume(int Current, int Total, bool Mute); + virtual void Flush(void); +}; + +#endif //__DISPLAYVOLUME_H \ No newline at end of file diff --git a/fonts/VDROpenSans/Apache License.txt b/fonts/VDROpenSans/Apache License.txt new file mode 100644 index 0000000..989e2c5 --- /dev/null +++ b/fonts/VDROpenSans/Apache License.txt @@ -0,0 +1,201 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/fonts/VDROpenSans/VDROpenSans-Bold.ttf b/fonts/VDROpenSans/VDROpenSans-Bold.ttf new file mode 100644 index 0000000..9d51f27 Binary files /dev/null and b/fonts/VDROpenSans/VDROpenSans-Bold.ttf differ diff --git a/fonts/VDROpenSans/VDROpenSans-BoldItalic.ttf b/fonts/VDROpenSans/VDROpenSans-BoldItalic.ttf new file mode 100644 index 0000000..61fc899 Binary files /dev/null and b/fonts/VDROpenSans/VDROpenSans-BoldItalic.ttf differ diff --git a/fonts/VDROpenSans/VDROpenSans-ExtraBold.ttf b/fonts/VDROpenSans/VDROpenSans-ExtraBold.ttf new file mode 100644 index 0000000..3701480 Binary files /dev/null and b/fonts/VDROpenSans/VDROpenSans-ExtraBold.ttf differ diff --git a/fonts/VDROpenSans/VDROpenSans-ExtraBoldItalic.ttf b/fonts/VDROpenSans/VDROpenSans-ExtraBoldItalic.ttf new file mode 100644 index 0000000..b760f90 Binary files /dev/null and b/fonts/VDROpenSans/VDROpenSans-ExtraBoldItalic.ttf differ diff --git a/fonts/VDROpenSans/VDROpenSans-Italic.ttf b/fonts/VDROpenSans/VDROpenSans-Italic.ttf new file mode 100644 index 0000000..4fc4fe1 Binary files /dev/null and b/fonts/VDROpenSans/VDROpenSans-Italic.ttf differ diff --git a/fonts/VDROpenSans/VDROpenSans-Light.ttf b/fonts/VDROpenSans/VDROpenSans-Light.ttf new file mode 100644 index 0000000..4806a9c Binary files /dev/null and b/fonts/VDROpenSans/VDROpenSans-Light.ttf differ diff --git a/fonts/VDROpenSans/VDROpenSans-LightItalic.ttf b/fonts/VDROpenSans/VDROpenSans-LightItalic.ttf new file mode 100644 index 0000000..4380547 Binary files /dev/null and b/fonts/VDROpenSans/VDROpenSans-LightItalic.ttf differ diff --git a/fonts/VDROpenSans/VDROpenSans-Regular.ttf b/fonts/VDROpenSans/VDROpenSans-Regular.ttf new file mode 100644 index 0000000..eaa8273 Binary files /dev/null and b/fonts/VDROpenSans/VDROpenSans-Regular.ttf differ diff --git a/fonts/VDROpenSans/VDROpenSans-Semibold.ttf b/fonts/VDROpenSans/VDROpenSans-Semibold.ttf new file mode 100644 index 0000000..2394fe1 Binary files /dev/null and b/fonts/VDROpenSans/VDROpenSans-Semibold.ttf differ diff --git a/fonts/VDROpenSans/VDROpenSans-SemiboldItalic.ttf b/fonts/VDROpenSans/VDROpenSans-SemiboldItalic.ttf new file mode 100644 index 0000000..1afcda3 Binary files /dev/null and b/fonts/VDROpenSans/VDROpenSans-SemiboldItalic.ttf differ diff --git a/libcore/fontmanager.c b/libcore/fontmanager.c new file mode 100644 index 0000000..1dcba44 --- /dev/null +++ b/libcore/fontmanager.c @@ -0,0 +1,174 @@ +#include "fontmanager.h" +#include "../config.h" +#include +#include FT_FREETYPE_H + +using namespace std; + +cMutex cFontManager::mutex; + +cFontManager::cFontManager() { +} + +cFontManager::~cFontManager() { + DeleteFonts(); +} + +void cFontManager::CacheFonts(cTemplate *tpl) { + cMutexLock MutexLock(&mutex); + + vector< pair > usedFonts = tpl->GetUsedFonts(); + + cStringList availableFonts; + cFont::GetAvailableFontNames(&availableFonts); + + for (vector< pair >::iterator ft = usedFonts.begin(); ft != usedFonts.end(); ft++) { + string fontName = ft->first; + int fontSize = ft->second; + if (fontSize < 1) { + continue; + } + + int fontAvailable = availableFonts.Find(fontName.c_str()); + if (fontAvailable == -1) { + esyslog("skindesigner: font %s not available, skipping", fontName.c_str()); + continue; + } + + InsertFont(fontName, fontSize); + } +} + +void cFontManager::Debug(void) { + dsyslog("skindesigner: fontmanager fonts available:"); + for (map < string, map< int, cFont* > >::iterator fts = fonts.begin(); fts != fonts.end(); fts++) { + dsyslog("skindesigner: FontName %s", fts->first.c_str()); + for (map::iterator ftSizes = (fts->second).begin(); ftSizes != (fts->second).end(); ftSizes++) { + int confHeight = ftSizes->first; + int realHeight = (ftSizes->second)->Height(); + dsyslog("skindesigner: fontSize %d, fontHeight %d, ratio %f", confHeight, realHeight, (double)confHeight / (double)realHeight); + } + } +} + +void cFontManager::ListAvailableFonts(void) { + cStringList availableFonts; + cFont::GetAvailableFontNames(&availableFonts); + int numFonts = availableFonts.Size(); + esyslog("skindesigner: %d Fonts available:", numFonts); + for (int i=0; i >::iterator it = fonts.begin(); it != fonts.end(); it++) { + for(map::iterator it2 = (it->second).begin(); it2 != (it->second).end(); it2++) { + delete it2->second; + } + } + fonts.clear(); +} + +int cFontManager::Width(string fontName, int fontSize, const char *text) { + cMutexLock MutexLock(&mutex); + if (!text) + return 0; + cFont *font = GetFont(fontName, fontSize); + //if not already cached, load it new + if (!font) + InsertFont(fontName, fontSize); + font = GetFont(fontName, fontSize); + if (!font) + return 0; + int width = font->Width(text); + return width; +} + +int cFontManager::Height(string fontName, int fontSize) { + cMutexLock MutexLock(&mutex); + cFont *font = GetFont(fontName, fontSize); + //if not already cached, load it new + if (!font) + InsertFont(fontName, fontSize); + font = GetFont(fontName, fontSize); + if (!font) + return 0; + return font->Height(); +} + +cFont *cFontManager::Font(string fontName, int fontSize) { + cMutexLock MutexLock(&mutex); + cFont *font = GetFont(fontName, fontSize); + //if not already cached, load it new + if (!font) + InsertFont(fontName, fontSize); + font = GetFont(fontName, fontSize); + return font; +} + +/******************************************************************************** +* Private Functions +********************************************************************************/ + +cFont *cFontManager::CreateFont(string name, int size) { + cMutexLock MutexLock(&mutex); + cFont *fontTmp = cFont::CreateFont(name.c_str(), size); + if (!fontTmp) + fontTmp = cFont::CreateFont(Setup.FontOsd, size); + int realHeight = fontTmp->Height(); + delete fontTmp; + cFont *font = cFont::CreateFont(name.c_str(), (double)size / (double)realHeight * (double)size); + if (!font) + font = cFont::CreateFont(Setup.FontOsd, (double)size / (double)realHeight * (double)size); + return font; +} + +void cFontManager::InsertFont(string name, int size) { + cFont *newFont = CreateFont(name, size); + if (!newFont) + return; + map < string, map< int, cFont* > >::iterator hit = fonts.find(name); + if (hit != fonts.end()) { + (hit->second).insert(pair(size, newFont)); + } else { + map fontsizes; + fontsizes.insert(pair(size, newFont)); + fonts.insert(pair >(name, fontsizes)); + } +} + +cFont *cFontManager::GetFont(string name, int size) { + map< string, map >::iterator hitName = fonts.find(name); + if (hitName == fonts.end()) + return NULL; + map::iterator hitSize = (hitName->second).find(size); + if (hitSize == (hitName->second).end()) + return NULL; + return hitSize->second; +} + +int cFontManager::GetFontHeight(const char *name, int height, int charWidth) { + FT_Library library; + FT_Face face; + cString fontFileName = cFont::GetFontFileName(name); + + int descender = 0; + int y_ppem = 0; + int error = FT_Init_FreeType(&library); + if (error) return 0; + error = FT_New_Face(library, fontFileName, 0, &face); + if (error) return 0; + error = FT_Set_Char_Size(face, charWidth * 64, height * 64, 0, 0); + if (error) return 0; + + descender = face->size->metrics.descender/64; + y_ppem = face->size->metrics.y_ppem; + int realHeight = y_ppem + descender; + + FT_Done_Face(face); + FT_Done_FreeType(library); + + return realHeight; +} diff --git a/libcore/fontmanager.h b/libcore/fontmanager.h new file mode 100644 index 0000000..7067dfc --- /dev/null +++ b/libcore/fontmanager.h @@ -0,0 +1,35 @@ +#ifndef __FONTMANAGER_H +#define __FONTMANAGER_H + +#include +#include +#include +#include + +#include "../libtemplate/template.h" + +using namespace std; + +class cFontManager { + private: + static cMutex mutex; + map < string, map< int, cFont* > > fonts; + cFont *CreateFont(string name, int size); + void InsertFont(string name, int size); + cFont *GetFont(string name, int size); + int GetFontHeight(const char *name, int height, int charWidth = 0); + public: + cFontManager(); + ~cFontManager(); + void Lock(void) { mutex.Lock(); }; + void Unlock(void) { mutex.Unlock(); }; + void CacheFonts(cTemplate *tpl); + void DeleteFonts(void); + int Width(string fontName, int fontSize, const char *text); + int Height(string fontName, int fontSize); + cFont *Font(string fontName, int fontSize); + void Debug(void); + void ListAvailableFonts(void); +}; + +#endif //__FONTMANAGER_H \ No newline at end of file diff --git a/libcore/helpers.c b/libcore/helpers.c new file mode 100644 index 0000000..81880a0 --- /dev/null +++ b/libcore/helpers.c @@ -0,0 +1,155 @@ +#include +#include +#include +#include "helpers.h" +#include + +cPlugin *GetScraperPlugin(void) { + static cPlugin *pScraper = cPluginManager::GetPlugin("scraper2vdr"); + if( !pScraper ) // if it doesn't exit, try tvscraper + pScraper = cPluginManager::GetPlugin("tvscraper"); + return pScraper; +} + +cSize ScaleToFit(int widthMax, int heightMax, int widthOriginal, int heightOriginal) { + int width = 1; + int height = 1; + + if ((widthMax == 0)||(heightMax==0)||(widthOriginal==0)||(heightOriginal==0)) + return cSize(width, height); + + if ((widthOriginal <= widthMax) && (heightOriginal <= heightMax)) { + width = widthOriginal; + height = heightOriginal; + } else if ((widthOriginal > widthMax) && (heightOriginal <= heightMax)) { + width = widthMax; + height = (double)width/(double)widthOriginal * heightOriginal; + } else if ((widthOriginal <= widthMax) && (heightOriginal > heightMax)) { + height = heightMax; + width = (double)height/(double)heightOriginal * widthOriginal; + } else { + width = widthMax; + height = (double)width/(double)widthOriginal * heightOriginal; + if (height > heightMax) { + height = heightMax; + width = (double)height/(double)heightOriginal * widthOriginal; + } + } + return cSize(width, height); +} + +int Minimum(int a, int b, int c, int d, int e, int f) { + int min = a; + if (b < min) min = b; + if (c < min) min = c; + if (d < min) min = d; + if (e < min) min = e; + if (f < min) min = f; + return min; +} + +string CutText(string &text, int width, string fontName, int fontSize) { + if (width <= fontManager->Font(fontName, fontSize)->Size()) + return text.c_str(); + cTextWrapper twText; + twText.Set(text.c_str(), fontManager->Font(fontName, fontSize), width); + string cuttedTextNative = twText.GetLine(0); + stringstream sstrText; + sstrText << cuttedTextNative << "..."; + string cuttedText = sstrText.str(); + int actWidth = fontManager->Width(fontName, fontSize, cuttedText.c_str()); + if (actWidth > width) { + int overlap = actWidth - width; + int charWidth = fontManager->Width(fontName, fontSize, "."); + if (charWidth == 0) + charWidth = 1; + int cutChars = overlap / charWidth; + if (cutChars > 0) { + cuttedTextNative = cuttedTextNative.substr(0, cuttedTextNative.length() - cutChars); + stringstream sstrText2; + sstrText2 << cuttedTextNative << "..."; + cuttedText = sstrText2.str(); + } + } + return cuttedText; +} + + +string StrToLowerCase(string str) { + string lowerCase = str; + const int length = lowerCase.length(); + for(int i=0; i < length; ++i) { + lowerCase[i] = std::tolower(lowerCase[i]); + } + return lowerCase; +} + +bool isNumber(const string& s) { + string::const_iterator it = s.begin(); + while (it != s.end() && std::isdigit(*it)) ++it; + return !s.empty() && it == s.end(); +} + +bool FileExists(const string &path, const string &name, const string &ext) { + stringstream fileName; + fileName << path << name << "." << ext; + struct stat buffer; + return (stat (fileName.str().c_str(), &buffer) == 0); +} + +bool FirstFileInFolder(string &path, string &extension, string &fileName) { + DIR *folder = NULL; + struct dirent *file; + folder = opendir(path.c_str()); + if (!folder) + return false; + while (file = readdir(folder)) { + if (endswith(file->d_name, extension.c_str())) { + string currentFileName = file->d_name; + int strlength = currentFileName.size(); + if (strlength < 8) + continue; + fileName = currentFileName; + return true; + } + } + return false; +} + +// split: receives a char delimiter; returns a vector of strings +// By default ignores repeated delimiters, unless argument rep == 1. +vector& splitstring::split(char delim, int rep) { + if (!flds.empty()) flds.clear(); // empty vector if necessary + string work = data(); + string buf = ""; + int i = 0; + while (i < work.length()) { + if (work[i] != delim) + buf += work[i]; + else if (rep == 1) { + flds.push_back(buf); + buf = ""; + } else if (buf.length() > 0) { + flds.push_back(buf); + buf = ""; + } + i++; + } + if (!buf.empty()) + flds.push_back(buf); + return flds; +} + +cStopWatch::cStopWatch(void) { + start = cTimeMs::Now(); + last = start; +} + +void cStopWatch::Report(const char* message) { + dsyslog("skindesigner: %s - needed %d ms", message, (int)(cTimeMs::Now() - last)); + last = cTimeMs::Now(); +} + +void cStopWatch::Stop(const char* message) { + dsyslog("skindesigner: %s - needed %d ms", message, (int)(cTimeMs::Now() - start)); +} diff --git a/libcore/helpers.h b/libcore/helpers.h new file mode 100644 index 0000000..60f3345 --- /dev/null +++ b/libcore/helpers.h @@ -0,0 +1,35 @@ +#ifndef __HELPERS_H +#define __HELPERS_H + +#include +#include +#include "../config.h" + +cPlugin *GetScraperPlugin(void); + +cSize ScaleToFit(int widthMax, int heightMax, int widthOriginal, int heightOriginal); +int Minimum(int a, int b, int c, int d, int e, int f); +std::string CutText(string &text, int width, string fontName, int fontSize); +std::string StrToLowerCase(string str); +bool isNumber(const string& s); +bool FileExists(const string &path, const string &name, const string &ext); +bool FirstFileInFolder(string &path, string &extension, string &fileName); + +class splitstring : public std::string { + std::vector flds; +public: + splitstring(const char *s) : std::string(s) { }; + std::vector& split(char delim, int rep=0); +}; + +class cStopWatch { +private: + uint64_t start; + uint64_t last; +public: + cStopWatch(void); + ~cStopWatch(void) {}; + void Report(const char* message); + void Stop(const char* message); +}; +#endif // __HELPERS_H diff --git a/libcore/imagecache.c b/libcore/imagecache.c new file mode 100644 index 0000000..7347c0a --- /dev/null +++ b/libcore/imagecache.c @@ -0,0 +1,389 @@ +#include +#include +#include +#include +#include +#include "imagecache.h" +#include "../config.h" +#include "helpers.h" + +using namespace Magick; + +cMutex cImageCache::mutex; + +string cImageCache::items[16] = { "Schedule", "Channels", "Timers", "Recordings", "Setup", "Commands", + "OSD", "EPG", "DVB", "LNB", "CAM", "Recording", "Replay", "Miscellaneous", "Plugins", "Restart"}; + +cImageCache::cImageCache() : cImageMagickWrapper() { + tempStaticLogo = NULL; +} + +cImageCache::~cImageCache() { + Clear(); + if (tempStaticLogo) { + delete tempStaticLogo; + tempStaticLogo = NULL; + } +} + +void cImageCache::CacheLogo(int width, int height) { + if (config.numLogosPerSizeInitial == 0) + return; + if (width == 0 || height == 0) + return; + + int channelsCached = 0; + + for (const cChannel *channel = Channels.First(); channel; channel = Channels.Next(channel)) { + if (channelsCached >= config.numLogosPerSizeInitial) + break; + if (channel->GroupSep()) { + continue; + } + bool success = LoadLogo(channel); + if (success) { + channelsCached++; + cImage *image = CreateImage(width, height); + stringstream logoName; + logoName << *channel->GetChannelID().ToString() << "_" << width << "x" << height; + std::map::iterator hit = channelLogoCache.find(logoName.str()); + if (hit != channelLogoCache.end()) { + delete image; + return; + } + channelLogoCache.insert(pair(logoName.str(), image)); + } + } +} + +cImage *cImageCache::GetLogo(string channelID, int width, int height) { + cMutexLock MutexLock(&mutex); + + stringstream logoName; + logoName << channelID << "_" << width << "x" << height; + + std::map::iterator hit = channelLogoCache.find(logoName.str()); + + if (hit != channelLogoCache.end()) { + return (cImage*)hit->second; + } else { + tChannelID chanID = tChannelID::FromString(channelID.c_str()); + const cChannel *channel = Channels.GetByChannelID(chanID); + if (!channel) + return NULL; + bool success = LoadLogo(channel); + if (success) { + if (config.limitLogoCache && (channelLogoCache.size() >= config.numLogosMax)) { + //logo cache is full, don't cache anymore + if (tempStaticLogo) { + delete tempStaticLogo; + tempStaticLogo = NULL; + } + tempStaticLogo = CreateImage(width, height); + return tempStaticLogo; + } else { + //add requested logo to cache + cImage *image = CreateImage(width, height); + channelLogoCache.insert(pair(logoName.str(), image)); + hit = channelLogoCache.find(logoName.str()); + if (hit != channelLogoCache.end()) { + return (cImage*)hit->second; + } + } + } + } + return NULL; +} + +cImage *cImageCache::GetSeparatorLogo(string name, int width, int height) { + cMutexLock MutexLock(&mutex); + + stringstream logoName; + logoName << name << "_" << width << "x" << height; + + std::map::iterator hit = channelLogoCache.find(logoName.str()); + + if (hit != channelLogoCache.end()) { + return (cImage*)hit->second; + } else { + bool success = LoadSeparatorLogo(name); + if (success) { + //add requested logo to cache + cImage *image = CreateImage(width, height); + channelLogoCache.insert(pair(logoName.str(), image)); + hit = channelLogoCache.find(logoName.str()); + if (hit != channelLogoCache.end()) { + return (cImage*)hit->second; + } + } + } + return NULL; +} + +bool cImageCache::LogoExists(string channelID) { + tChannelID chanID = tChannelID::FromString(channelID.c_str()); + const cChannel *channel = Channels.GetByChannelID(chanID); + if (!channel) + return false; + string logoPath = *cString::sprintf("%s%s/logos/", *config.skinPath, Setup.OSDTheme); + string logoLower = StrToLowerCase(channel->Name()); + string logoExt = *config.logoExtension; + bool logoExists = FileExists(logoPath, logoLower, logoExt); + if (logoExists) { + return true; + } + logoExists = FileExists(logoPath, channelID, logoExt); + if (logoExists) { + return true; + } + return false; +} + +bool cImageCache::SeparatorLogoExists(string name) { + string separatorPath = *cString::sprintf("%s%s/logos/separatorlogos/", *config.skinPath, Setup.OSDTheme); + string nameLower = StrToLowerCase(name.c_str()); + string logoExt = *config.logoExtension; + bool logoExists = FileExists(separatorPath, nameLower, logoExt); + if (logoExists) { + return true; + } + return false; +} + +void cImageCache::CacheIcon(eImageType type, string name, int width, int height) { + if (width < 1 || width > 1920 || height < 1 || height > 1080) + return; + bool success = LoadIcon(type, name); + if (!success) + return; + stringstream iconName; + iconName << name << "_" << width << "x" << height; + cImage *image = CreateImage(width, height, true); + iconCache.insert(pair(iconName.str(), image)); +} + +cImage *cImageCache::GetIcon(eImageType type, string name, int width, int height) { + if (width < 1 || width > 1920 || height < 1 || height > 1080) + return NULL; + cMutexLock MutexLock(&mutex); + stringstream iconName; + iconName << name << "_" << width << "x" << height; + map::iterator hit = iconCache.find(iconName.str()); + if (hit != iconCache.end()) { + return (cImage*)hit->second; + } else { + bool success = LoadIcon(type, name); + if (!success) + return NULL; + cImage *image = CreateImage(width, height, true); + iconCache.insert(pair(iconName.str(), image)); + hit = iconCache.find(iconName.str()); + if (hit != iconCache.end()) { + return (cImage*)hit->second; + } + } + return NULL; +} + +string cImageCache::GetIconName(string label) { + //check for standard menu entries + for (int i=0; i<16; i++) { + string s = trVDR(items[i].c_str()); + if (s == label) { + return *cString::sprintf("standardicons/%s", items[i].c_str()); + } + } + //check for special main menu entries "stop recording", "stop replay" + string stopRecording = skipspace(trVDR(" Stop recording ")); + string stopReplay = skipspace(trVDR(" Stop replaying")); + try { + if (label.substr(0, stopRecording.size()) == stopRecording) { + return "standardicons/StopRecording"; + } + if (label.substr(0, stopReplay.size()) == stopReplay) { + return "standardicons/StopReplay"; + } + } catch (...) {} + //check for Plugins + for (int i = 0; ; i++) { + cPlugin *p = cPluginManager::GetPlugin(i); + if (p) { + const char *mainMenuEntry = p->MainMenuEntry(); + if (mainMenuEntry) { + string plugMainEntry = mainMenuEntry; + try { + if (label.substr(0, plugMainEntry.size()) == plugMainEntry) { + return *cString::sprintf("pluginicons/%s", p->Name()); + } + } catch (...) {} + } + } else + break; + } + return *cString::sprintf("customicons/%s", label.c_str()); +} + +void cImageCache::CacheSkinpart(string name, int width, int height) { + if (width < 1 || width > 1920 || height < 1 || height > 1080) + return; + bool success = LoadSkinpart(name); + if (!success) + return; + stringstream iconName; + iconName << name << "_" << width << "x" << height; + cImage *image = CreateImage(width, height, false); + skinPartsCache.insert(pair(iconName.str(), image)); +} + +cImage *cImageCache::GetSkinpart(string name, int width, int height) { + if (width < 1 || width > 1920 || height < 1 || height > 1080) + return NULL; + cMutexLock MutexLock(&mutex); + stringstream iconName; + iconName << name << "_" << width << "x" << height; + map::iterator hit = skinPartsCache.find(iconName.str()); + if (hit != skinPartsCache.end()) { + return (cImage*)hit->second; + } else { + bool success = LoadSkinpart(name); + if (!success) + return NULL; + cImage *image = CreateImage(width, height, false); + skinPartsCache.insert(pair(iconName.str(), image)); + hit = skinPartsCache.find(iconName.str()); + if (hit != skinPartsCache.end()) { + return (cImage*)hit->second; + } + } + return NULL; +} + +bool cImageCache::LoadIcon(eImageType type, string name) { + bool success = false; + cString subdir(""); + if (type == itMenuIcon) + subdir = "menuicons"; + else if (type == itIcon) + subdir = "icons"; + cString iconPath = cString::sprintf("%s%s/graphics/%s/", *config.skinPath, Setup.OSDTheme, *subdir); + success = LoadImage(name, *iconPath, "png"); + if (success) { + return true; + } + return false; +} + +bool cImageCache::LoadLogo(const cChannel *channel) { + if (!channel) + return false; + cString logoPath = cString::sprintf("%s%s/logos/", *config.skinPath, Setup.OSDTheme); + string channelID = StrToLowerCase(*(channel->GetChannelID().ToString())); + string logoLower = StrToLowerCase(channel->Name()); + bool success = false; + success = LoadImage(channelID.c_str(), *logoPath, *config.logoExtension); + if (success) + return true; + success = LoadImage(logoLower.c_str(), *logoPath, *config.logoExtension); + if (success) + return true; + return false; +} + +bool cImageCache::LoadSeparatorLogo(string name) { + cString separatorPath = cString::sprintf("%s%s/logos/separatorlogos/", *config.skinPath, Setup.OSDTheme); + string nameLower = StrToLowerCase(name.c_str()); + bool success = false; + success = LoadImage(nameLower.c_str(), *separatorPath, *config.logoExtension); + if (success) + return true; + return false; +} + +bool cImageCache::LoadSkinpart(string name) { + bool success = false; + cString iconPath = cString::sprintf("%s%s/graphics/skinparts/", *config.skinPath, Setup.OSDTheme); + success = LoadImage(name, *iconPath, "png"); + if (success) { + return true; + } + return false; +} + +void cImageCache::Clear(void) { + for(map::const_iterator it = iconCache.begin(); it != iconCache.end(); it++) { + cImage *img = (cImage*)it->second; + delete img; + } + iconCache.clear(); + + for(map::const_iterator it = channelLogoCache.begin(); it != channelLogoCache.end(); it++) { + cImage *img = (cImage*)it->second; + delete img; + } + channelLogoCache.clear(); + + for(map::const_iterator it = skinPartsCache.begin(); it != skinPartsCache.end(); it++) { + cImage *img = (cImage*)it->second; + delete img; + } + skinPartsCache.clear(); +} + +void cImageCache::Debug(bool full) { + int sizeIconCache = 0; + int numIcons = 0; + GetIconCacheSize(numIcons, sizeIconCache); + dsyslog("skindesigner: cached %d icons - size %d byte", numIcons, sizeIconCache); + if (full) { + for(std::map::const_iterator it = iconCache.begin(); it != iconCache.end(); it++) { + string name = it->first; + dsyslog("skindesigner: cached icon %s", name.c_str()); + } + } + + int sizeLogoCache = 0; + int numLogos = 0; + GetLogoCacheSize(numLogos, sizeLogoCache); + dsyslog("skindesigner: cached %d logos - size %d byte", numLogos, sizeLogoCache); + if (full) { + for(std::map::const_iterator it = channelLogoCache.begin(); it != channelLogoCache.end(); it++) { + string name = it->first; + dsyslog("skindesigner: cached logo %s", name.c_str()); + } + } + + int sizeSkinpartCache = 0; + int numSkinparts = 0; + GetSkinpartsCacheSize(numSkinparts, sizeSkinpartCache); + dsyslog("skindesigner: cached %d skinparts - size %d byte", numSkinparts, sizeSkinpartCache); + if (full) { + for(std::map::const_iterator it = skinPartsCache.begin(); it != skinPartsCache.end(); it++) { + string name = it->first; + dsyslog("skindesigner: cached skinpart %s", name.c_str()); + } + } +} + +void cImageCache::GetIconCacheSize(int &num, int &size) { + num = iconCache.size(); + for (map::iterator icon = iconCache.begin(); icon != iconCache.end(); icon++) { + cImage* img = icon->second; + size += img->Width() * img->Height() * sizeof(tColor); + } +} + +void cImageCache::GetLogoCacheSize(int &num, int &size) { + num = channelLogoCache.size(); + for (map::iterator logo = channelLogoCache.begin(); logo != channelLogoCache.end(); logo++) { + cImage* img = logo->second; + size += img->Width() * img->Height() * sizeof(tColor); + } +} + +void cImageCache::GetSkinpartsCacheSize(int &num, int &size) { + num = skinPartsCache.size(); + for (map::iterator skinpart = skinPartsCache.begin(); skinpart != skinPartsCache.end(); skinpart++) { + cImage* img = skinpart->second; + size += img->Width() * img->Height() * sizeof(tColor); + } +} diff --git a/libcore/imagecache.h b/libcore/imagecache.h new file mode 100644 index 0000000..9e700bf --- /dev/null +++ b/libcore/imagecache.h @@ -0,0 +1,53 @@ +#ifndef __NOPACITY_IMAGECACHE_H +#define __NOPACITY_IMAGECACHE_H + +#define X_DISPLAY_MISSING + +#include +#include +#include +#include +#include "imagemagickwrapper.h" +#include "../libtemplate/templatefunction.h" + +using namespace Magick; + +class cImageCache : public cImageMagickWrapper { +public: + cImageCache(); + ~cImageCache(); + void Lock(void) { mutex.Lock(); } + void Unlock(void) { mutex.Unlock(); } + //channel logos + void CacheLogo(int width, int height); + cImage *GetLogo(string channelID, int width, int height); + bool LogoExists(string channelID); + cImage *GetSeparatorLogo(string name, int width, int height); + bool SeparatorLogoExists(string name); + //icons + void CacheIcon(eImageType type, string path, int width, int height); + cImage *GetIcon(eImageType type, string name, int width, int height); + string GetIconName(string label); + //skinparts + void CacheSkinpart(string path, int width, int height); + cImage *GetSkinpart(string name, int width, int height); + //helpers + void Clear(void); + void Debug(bool full); + void GetIconCacheSize(int &num, int &size); + void GetLogoCacheSize(int &num, int &size); + void GetSkinpartsCacheSize(int &num, int &size); +private: + static cMutex mutex; + static string items[16]; + cImage *tempStaticLogo; + map iconCache; + map channelLogoCache; + map skinPartsCache; + bool LoadIcon(eImageType type, string name); + bool LoadLogo(const cChannel *channel); + bool LoadSeparatorLogo(string name); + bool LoadSkinpart(string name); +}; + +#endif //__NOPACITY_IMAGECACHE_H diff --git a/libcore/imageloader.c b/libcore/imageloader.c new file mode 100644 index 0000000..1b220a6 --- /dev/null +++ b/libcore/imageloader.c @@ -0,0 +1,56 @@ +#include "../config.h" +#include "helpers.h" +#include "imageloader.h" +#include +#include +#include +#include + +using namespace Magick; + +cImageLoader::cImageLoader() : cImageMagickWrapper() { +} + +cImageLoader::~cImageLoader() { +} + +cImage cImageLoader::GetImage() { + return CreateImageCopy(); +} + +bool cImageLoader::LoadImage(const char *path, int width, int height) { + if (cImageMagickWrapper::LoadImage(path)) { + buffer.sample(Geometry(width, height)); + return true; + } + return false; +} + +void cImageLoader::DeterminateChannelLogoSize(int &width, int &height) { + cString logoPath = cString::sprintf("%s%s/logos/", *config.skinPath, Setup.OSDTheme); + cString logoExt = config.logoExtension; + DIR *folder = NULL; + struct dirent *file; + folder = opendir(logoPath); + if (!folder) { + return; + } + while (file = readdir(folder)) { + if (endswith(file->d_name, *logoExt)) { + std::stringstream filePath; + filePath << *logoPath << file->d_name; + Image logo; + try { + logo.read(filePath.str().c_str()); + Geometry g = logo.size(); + int logoWidth = g.width(); + int logoHeight = g.height(); + if (logoWidth > 0 && logoHeight > 0) { + width = logoWidth; + height = logoHeight; + return; + } + } catch( ... ) { } + } + } +} diff --git a/libcore/imageloader.h b/libcore/imageloader.h new file mode 100644 index 0000000..2a148be --- /dev/null +++ b/libcore/imageloader.h @@ -0,0 +1,23 @@ +#ifndef __NOPACITY_IMAGELOADER_H +#define __NOPACITY_IMAGELOADER_H + +#define X_DISPLAY_MISSING + +#include +#include +#include +#include "imagemagickwrapper.h" + +using namespace Magick; + +class cImageLoader : public cImageMagickWrapper { +public: + cImageLoader(); + ~cImageLoader(); + cImage GetImage(); + bool LoadImage(const char *path, int width, int height); + void DeterminateChannelLogoSize(int &width, int &height); +private: +}; + +#endif //__NOPACITY_IMAGELOADER_H diff --git a/libcore/imagemagickwrapper.c b/libcore/imagemagickwrapper.c new file mode 100644 index 0000000..ab1bcba --- /dev/null +++ b/libcore/imagemagickwrapper.c @@ -0,0 +1,162 @@ +#include +#include +#include "imagemagickwrapper.h" +#include "../config.h" +#include "imagescaler.h" + +cImageMagickWrapper::cImageMagickWrapper() { + InitializeMagick(NULL); +} + +cImageMagickWrapper::~cImageMagickWrapper() { +} + +cImage *cImageMagickWrapper::CreateImage(int width, int height, bool preserveAspect) { + int w, h; + w = buffer.columns(); + h = buffer.rows(); + if (width == 0) + width = w; + if (height == 0) + height = h; + if (preserveAspect) { + unsigned scale_w = 1000 * width / w; + unsigned scale_h = 1000 * height / h; + if (scale_w > scale_h) + width = w * height / h; + else + height = h * width / w; + } + const PixelPacket *pixels = buffer.getConstPixels(0, 0, w, h); + cImage *image = new cImage(cSize(width, height)); + tColor *imgData = (tColor *)image->Data(); + if (w != width || h != height) { + ImageScaler scaler; + scaler.SetImageParameters(imgData, width, width, height, w, h); + for (const void *pixels_end = &pixels[w*h]; pixels < pixels_end; ++pixels) + scaler.PutSourcePixel(pixels->blue / ((MaxRGB + 1) / 256), + pixels->green / ((MaxRGB + 1) / 256), + pixels->red / ((MaxRGB + 1) / 256), + ~((unsigned char)(pixels->opacity / ((MaxRGB + 1) / 256)))); + return image; + } + for (const void *pixels_end = &pixels[width*height]; pixels < pixels_end; ++pixels) + *imgData++ = ((~int(pixels->opacity / ((MaxRGB + 1) / 256)) << 24) | + (int(pixels->green / ((MaxRGB + 1) / 256)) << 8) | + (int(pixels->red / ((MaxRGB + 1) / 256)) << 16) | + (int(pixels->blue / ((MaxRGB + 1) / 256)) )); + return image; +} + +cImage cImageMagickWrapper::CreateImageCopy() { + int w, h; + w = buffer.columns(); + h = buffer.rows(); + cImage image (cSize(w, h)); + const PixelPacket *pixels = buffer.getConstPixels(0, 0, w, h); + for (int iy = 0; iy < h; ++iy) { + for (int ix = 0; ix < w; ++ix) { + tColor col = (~int(pixels->opacity * 255 / MaxRGB) << 24) + | (int(pixels->green * 255 / MaxRGB) << 8) + | (int(pixels->red * 255 / MaxRGB) << 16) + | (int(pixels->blue * 255 / MaxRGB) ); + image.SetPixel(cPoint(ix, iy), col); + ++pixels; + } + } + return image; +} + +bool cImageMagickWrapper::LoadImage(std::string FileName, std::string Path, std::string Extension) { + try { + std::stringstream sstrImgFile; + sstrImgFile << Path << FileName << "." << Extension; + std::string imgFile = sstrImgFile.str(); + if (config.debugImageLoading) + dsyslog("skindesigner: trying to load: %s", imgFile.c_str()); + buffer.read(imgFile.c_str()); + if (config.debugImageLoading) + dsyslog("skindesigner: %s sucessfully loaded", imgFile.c_str()); + } catch( Magick::Warning &warning ) { + if (config.debugImageLoading) + dsyslog("skindesigner: Magick Warning: %s", warning.what()); + return true; + } catch( Magick::Error &error ) { + if (config.debugImageLoading) + dsyslog("skindesigner: Magick Error: %s", error.what()); + return false; + } catch(...) { + if (config.debugImageLoading) + dsyslog("skindesigner: an unknown Magick error occured during image loading"); + return false; + } + return true; +} + +bool cImageMagickWrapper::LoadImage(const char *fullpath) { + if ((fullpath == NULL) || (strlen(fullpath) < 5)) + return false; + try { + if (config.debugImageLoading) + dsyslog("skindesigner: trying to load: %s", fullpath); + buffer.read(fullpath); + if (config.debugImageLoading) + dsyslog("skindesigner: %s sucessfully loaded", fullpath); + } catch( Magick::Warning &warning ) { + if (config.debugImageLoading) + dsyslog("skindesigner: Magick Warning: %s", warning.what()); + return true; + } catch( Magick::Error &error ) { + if (config.debugImageLoading) + dsyslog("skindesigner: Magick Error: %s", error.what()); + return false; + } catch(...) { + if (config.debugImageLoading) + dsyslog("skindesigner: an unknown Magick error occured during image loading"); + return false; + } + return true; +} + +Color cImageMagickWrapper::Argb2Color(tColor col) { + tIndex alpha = (col & 0xFF000000) >> 24; + tIndex red = (col & 0x00FF0000) >> 16; + tIndex green = (col & 0x0000FF00) >> 8; + tIndex blue = (col & 0x000000FF); + Color color(MaxRGB*red/255, MaxRGB*green/255, MaxRGB*blue/255, MaxRGB*(0xFF-alpha)/255); + return color; +} + +void cImageMagickWrapper::CreateGradient(tColor back, tColor blend, int width, int height, double wfactor, double hfactor) { + Color Back = Argb2Color(back); + Color Blend = Argb2Color(blend); + int maxw = MaxRGB * wfactor; + int maxh = MaxRGB * hfactor; + + Image imgblend(Geometry(width, height), Blend); + imgblend.modifyImage(); + imgblend.type(TrueColorMatteType); + PixelPacket *pixels = imgblend.getPixels(0, 0, width, height); + for (int x = 0; x < width; x++) { + for (int y = 0; y < height; y++) { + PixelPacket *pixel = pixels + y * width + x; + int opacity = (maxw / width * x + maxh - maxh / height * y) / 2; + pixel->opacity = (opacity <= MaxRGB) ? opacity : MaxRGB; + } + } + imgblend.syncPixels(); + + Image imgback(Geometry(width, height), Back); + imgback.composite(imgblend, 0, 0, OverCompositeOp); + + buffer = imgback; +} + +void cImageMagickWrapper::CreateBackground(tColor back, tColor blend, int width, int height, bool mirror) { + CreateGradient(back, blend, width, height, 0.8, 0.8); + if (mirror) + buffer.flop(); +} +void cImageMagickWrapper::CreateBackgroundReverse(tColor back, tColor blend, int width, int height) { + CreateGradient(back, blend, width, height, 1.3, 0.7); +} diff --git a/libcore/imagemagickwrapper.h b/libcore/imagemagickwrapper.h new file mode 100644 index 0000000..5f9901e --- /dev/null +++ b/libcore/imagemagickwrapper.h @@ -0,0 +1,28 @@ +#ifndef __NOPACITY_IMAGEMAGICKWRAPPER_H +#define __NOPACITY_IMAGEMAGICKWRAPPER_H + +#define X_DISPLAY_MISSING + +#include +#include + +using namespace Magick; + +class cImageMagickWrapper { +private: + void CreateGradient(tColor back, tColor blend, int width, int height, double wfactor, double hfactor); +public: + cImageMagickWrapper(); + ~cImageMagickWrapper(); +protected: + Image buffer; + Color Argb2Color(tColor col); + cImage *CreateImage(int width, int height, bool preserveAspect = true); + cImage CreateImageCopy(void); + bool LoadImage(std::string FileName, std::string Path, std::string Extension); + bool LoadImage(const char *fullpath); + void CreateBackground(tColor back, tColor blend, int width, int height, bool mirror = false); + void CreateBackgroundReverse(tColor back, tColor blend, int width, int height); +}; + +#endif //__NOPACITY_IMAGEMAGICKWRAPPER_H diff --git a/libcore/imagescaler.c b/libcore/imagescaler.c new file mode 100644 index 0000000..64fe3dc --- /dev/null +++ b/libcore/imagescaler.c @@ -0,0 +1,149 @@ + +#include "imagescaler.h" + +#include +#include + +ImageScaler::ImageScaler() : + m_memory(NULL), + m_hor_filters(NULL), + m_ver_filters(NULL), + m_buffer(NULL), + m_dst_image(NULL), + m_dst_stride(0), + m_dst_width(0), + m_dst_height(0), + m_src_width(0), + m_src_height(0), + m_src_x(0), + m_src_y(0), + m_dst_x(0), + m_dst_y(0) { +} + +ImageScaler::~ImageScaler() { + if ( m_memory ) free( m_memory ); +} + +// sin(x)/(x) +static float sincf( float x ) { + if ( fabsf(x) < 0.05f ) return 1.0f - (1.0f/6.0f)*x*x; // taylor series approximation to avoid 0/0 + return sin(x)/x; +} + +static void CalculateFilters( ImageScaler::Filter *filters, int dst_size, int src_size ) { + const float fc = dst_size >= src_size ? 1.0f : ((float) dst_size)/((float) src_size); + + for (int i = 0; i < dst_size; i++) { + const int d = 2*dst_size; // sample position denominator + const int e = (2*i+1) * src_size - dst_size; // sample position enumerator + int offset = e / d; // truncated sample position + const float sub_offset = ((float) (e - offset*d)) / ((float) d); // exact sample position is (float) e/d = offset + sub_offset + + // calculate filter coefficients + float h[4]; + for (int j=0; j<4; j++) { + const float t = 3.14159265359f * (sub_offset+(1-j)); + h[j] = sincf( fc * t ) * cosf( 0.25f * t ); // sinc-lowpass and cos-window + } + + // ensure that filter does not reach out off image bounds: + while ( offset < 1 ) { + h[0] += h[1]; + h[1] = h[2]; + h[2] = h[3]; + h[3] = 0.0f; + offset++; + } + + while ( offset+3 > src_size ) { + h[3] += h[2]; + h[2] = h[1]; + h[1] = h[0]; + h[0] = 0.0f; + offset--; + } + + // coefficients are normalized to sum up to 2048 + const float norm = 2048.0f / ( h[0] + h[1] + h[2] + h[3] ); + + offset--; // offset of fist used pixel + + filters[i].m_offset = offset + 4; // store offset of first unused pixel + + for (int j=0; j<4; j++) { + const float t = norm * h[j]; + filters[i].m_coeff[(offset+j) & 3] = (int) ((t > 0.0f) ? (t+0.5f) : (t-0.5f)); // consider ring buffer index permutations + } + } + + // set end marker + filters[dst_size].m_offset = (unsigned) -1; + +} + +void ImageScaler::SetImageParameters( unsigned *dst_image, unsigned dst_stride, unsigned dst_width, unsigned dst_height, unsigned src_width, unsigned src_height ) { + m_src_x = 0; + m_src_y = 0; + m_dst_x = 0; + m_dst_y = 0; + + m_dst_image = dst_image; + m_dst_stride = dst_stride; + + // if image dimensions do not change we can keep the old filter coefficients + if ( (src_width == m_src_width) && (src_height == m_src_height) && (dst_width == m_dst_width) && (dst_height == m_dst_height) ) return; + + m_dst_width = dst_width; + m_dst_height = dst_height; + m_src_width = src_width; + m_src_height = src_height; + + if ( m_memory ) free( m_memory ); + + const unsigned hor_filters_size = (m_dst_width + 1) * sizeof(Filter); // reserve one extra position for end marker + const unsigned ver_filters_size = (m_dst_height + 1) * sizeof(Filter); + const unsigned buffer_size = 4 * m_dst_width * sizeof(TmpPixel); + + char *p = (char *) malloc( hor_filters_size + ver_filters_size + buffer_size ); + + m_memory = p; + + m_hor_filters = (Filter *) p; p += hor_filters_size; + m_ver_filters = (Filter *) p; p += ver_filters_size; + m_buffer = (TmpPixel *) p; + + CalculateFilters( m_hor_filters, m_dst_width , m_src_width ); + CalculateFilters( m_ver_filters, m_dst_height, m_src_height ); +} + +// shift range to 0..255 and clamp overflows +static unsigned shift_clamp( int x ) { + x = ( x + (1<<21) ) >> 22; + if ( x < 0 ) return 0; + if ( x > 255 ) return 255; + return x; +} + +void ImageScaler::NextSourceLine() { + m_dst_x = 0; + m_src_x = 0; + m_src_y++; + + while ( m_ver_filters[m_dst_y].m_offset == m_src_y ) { + const int h0 = m_ver_filters[m_dst_y].m_coeff[0]; + const int h1 = m_ver_filters[m_dst_y].m_coeff[1]; + const int h2 = m_ver_filters[m_dst_y].m_coeff[2]; + const int h3 = m_ver_filters[m_dst_y].m_coeff[3]; + const TmpPixel *src = m_buffer; + unsigned *dst = m_dst_image + m_dst_stride * m_dst_y; + + for (unsigned i=0; im_offset == m_src_x ) { + *bp = m_hbuf[0]*fh->m_coeff[0] + m_hbuf[1]*fh->m_coeff[1] + m_hbuf[2]*fh->m_coeff[2] + m_hbuf[3]*fh->m_coeff[3]; + m_dst_x++; + bp += 4; + } + + if ( m_src_x == m_src_width ) NextSourceLine(); + } + +private: + + //! temporary image pixel class - a 4-element integer vector + class TmpPixel { + public: + TmpPixel() { + } + + TmpPixel( int c0, int c1, int c2, int c3 ) { + Set(c0,c1,c2,c3); + } + + void Set( int c0, int c1, int c2, int c3 ) { + m_comp[0] = c0; + m_comp[1] = c1; + m_comp[2] = c2; + m_comp[3] = c3; + } + + TmpPixel operator*( int s ) const { + return TmpPixel( m_comp[0]*s, m_comp[1]*s, m_comp[2]*s, m_comp[3]*s ); + } + + TmpPixel operator+( const TmpPixel &x ) const { + return TmpPixel( m_comp[0] + x[0], m_comp[1] + x[1], m_comp[2] + x[2], m_comp[3] + x[3] ); + } + + // return component i=[0..3] - No range check! + int operator[](unsigned i) const { + return m_comp[i]; + } + + private: + int m_comp[4]; + }; + + //! this is called whenever one input line is processed completely + void NextSourceLine(); + + TmpPixel m_hbuf[4]; //! ring buffer for 4 input pixels + char *m_memory; //! buffer container + Filter *m_hor_filters; //! buffer for horizontal filters (one for each output image column) + Filter *m_ver_filters; //! buffer for vertical filters (one for each output image row) + TmpPixel *m_buffer; //! buffer contains 4 horizontally filtered input lines, multiplexed + unsigned *m_dst_image; //! pointer to destination image + unsigned m_dst_stride; //! destination image stride + unsigned m_dst_width; //! destination image width + unsigned m_dst_height; //! destination image height + unsigned m_src_width; //! source image width + unsigned m_src_height; //! source image height + unsigned m_src_x; //! x position of next source image pixel + unsigned m_src_y; //! y position of source image line currently beeing processed + unsigned m_dst_x; //! x position of next destination image pixel + unsigned m_dst_y; //! x position of next destination image line +}; + +#endif // _ImageScaler_h + diff --git a/libcore/pixmapcontainer.c b/libcore/pixmapcontainer.c new file mode 100644 index 0000000..6329638 --- /dev/null +++ b/libcore/pixmapcontainer.c @@ -0,0 +1,477 @@ +#define __STL_CONFIG_H +#include "pixmapcontainer.h" +#include "../config.h" + +cMutex cPixmapContainer::mutex; +cOsd *cPixmapContainer::osd = NULL; +eFlushState cPixmapContainer::flushState = fsOpen; + +cPixmapContainer::cPixmapContainer(int numPixmaps) { + this->numPixmaps = numPixmaps; + pixContainerInit = true; + mutex.Lock(); + pixmaps = new cPixmap*[numPixmaps]; + pixmapsTransparency = new int[numPixmaps]; + for(int i=0; i < numPixmaps; i++) { + pixmaps[i] = NULL; + pixmapsTransparency[i] = 0; + } + mutex.Unlock(); + checkRunning = false; + fadeTime = 0; + deleteOsdOnExit = false; +} + +cPixmapContainer::~cPixmapContainer(void) { + for (int i=0; i < numPixmaps; i++) { + mutex.Lock(); + if (pixmaps[i] && osd) { + osd->DestroyPixmap(pixmaps[i]); + pixmaps[i] = NULL; + } + mutex.Unlock(); + } + delete[] pixmaps; + delete[] pixmapsTransparency; + if (deleteOsdOnExit && osd) { + mutex.Lock(); + delete osd; + osd = NULL; + mutex.Unlock(); + } +} + +bool cPixmapContainer::CreateOsd(int Left, int Top, int Width, int Height) { + if (osd) { + return true; + } + cOsd *newOsd = cOsdProvider::NewOsd(Left, Top); + if (newOsd) { + tArea Area = { 0, 0, Width, Height, 32 }; + if (newOsd->SetAreas(&Area, 1) == oeOk) { + osd = newOsd; + return true; + } + } + return false; +} + +void cPixmapContainer::LockFlush(void) { + flushState = fsLock; +} + +void cPixmapContainer::OpenFlush(void) { + flushState = fsOpen; +} + +bool cPixmapContainer::PixmapExists(int num) { + cMutexLock MutexLock(&mutex); + if (pixmaps[num]) + return true; + return false; +} + +void cPixmapContainer::DoFlush(void) { + cMutexLock MutexLock(&mutex); + if (!osd || (checkRunning && !Running())) + return; + if (flushState == fsOpen) { + osd->Flush(); + } +} + +void cPixmapContainer::CreatePixmap(int num, int Layer, const cRect &ViewPort, const cRect &DrawPort) { + cMutexLock MutexLock(&mutex); + if (!osd || (checkRunning && !Running())) + return; + pixmaps[num] = osd->CreatePixmap(Layer, ViewPort, DrawPort); + pixmaps[num]->Fill(clrTransparent); + if (pixContainerInit && fadeTime) { + pixmaps[num]->SetAlpha(0); + } else if (pixmapsTransparency[num] > 0) { + int alpha = (100 - pixmapsTransparency[num])*255/100; + pixmaps[num]->SetAlpha(alpha); + } +} + +bool cPixmapContainer::DestroyPixmap(int num) { + cMutexLock MutexLock(&mutex); + if (pixmaps[num] && osd) { + osd->DestroyPixmap(pixmaps[num]); + pixmaps[num] = NULL; + return true; + } + return false; +} + +void cPixmapContainer::DrawText(int num, const cPoint &Point, const char *s, tColor ColorFg, tColor ColorBg, std::string fontName, int fontSize) { + if (checkRunning && !Running()) + return; + cMutexLock MutexLock(&mutex); + if (!pixmaps[num]) + return; + fontManager->Lock(); + cFont *font = fontManager->Font(fontName, fontSize); + if (font) + pixmaps[num]->DrawText(Point, s, ColorFg, ColorBg, font); + fontManager->Unlock(); +} + + +void cPixmapContainer::DrawRectangle(int num, const cRect &Rect, tColor Color) { + if (checkRunning && !Running()) + return; + cMutexLock MutexLock(&mutex); + if (!pixmaps[num]) + return; + pixmaps[num]->DrawRectangle(Rect, Color); +} + +void cPixmapContainer::DrawEllipse(int num, const cRect &Rect, tColor Color, int Quadrants) { + if (checkRunning && !Running()) + return; + cMutexLock MutexLock(&mutex); + if (!pixmaps[num]) + return; + pixmaps[num]->DrawEllipse(Rect, Color, Quadrants); +} + +void cPixmapContainer::DrawImage(int num, const cPoint &Point, const cImage &Image) { + if (checkRunning && !Running()) + return; + cMutexLock MutexLock(&mutex); + if (!pixmaps[num]) + return; + pixmaps[num]->DrawImage(Point, Image); +} + +void cPixmapContainer::DrawBitmap(int num, const cPoint &Point, const cBitmap &Bitmap, tColor ColorFg, tColor ColorBg, bool Overlay) { + if (checkRunning && !Running()) + return; + cMutexLock MutexLock(&mutex); + if (!pixmaps[num]) + return; + pixmaps[num]->DrawBitmap(Point, Bitmap, ColorFg, ColorBg, Overlay); +} + +void cPixmapContainer::Fill(int num, tColor Color) { + if (checkRunning && !Running()) + return; + cMutexLock MutexLock(&mutex); + if (!pixmaps[num]) + return; + pixmaps[num]->Fill(Color); +} + +void cPixmapContainer::SetAlpha(int num, int Alpha) { + if (checkRunning && !Running()) + return; + cMutexLock MutexLock(&mutex); + if (!pixmaps[num]) + return; + pixmaps[num]->SetAlpha(Alpha); +} + +void cPixmapContainer::SetTransparency(int num, int Transparency) { + if (Transparency < 0 && Transparency > 100) + return; + pixmapsTransparency[num] = Transparency; +} + +void cPixmapContainer::SetLayer(int num, int Layer) { + cMutexLock MutexLock(&mutex); + if (!pixmaps[num]) + return; + pixmaps[num]->SetLayer(Layer); +} + +int cPixmapContainer::Width(int num) { + if (checkRunning && !Running()) + return 0; + cMutexLock MutexLock(&mutex); + if (!pixmaps[num]) + return 0; + int width = pixmaps[num]->ViewPort().Width(); + return width; +} + +int cPixmapContainer::Height(int num) { + if (checkRunning && !Running()) + return 0; + cMutexLock MutexLock(&mutex); + if (!pixmaps[num]) + return 0; + int height = pixmaps[num]->ViewPort().Height(); + return height; +} + +int cPixmapContainer::DrawportWidth(int num) { + if (checkRunning && !Running()) + return 0; + cMutexLock MutexLock(&mutex); + if (!pixmaps[num]) + return 0; + int width = pixmaps[num]->DrawPort().Width(); + return width; +} + +int cPixmapContainer::DrawportHeight(int num) { + if (checkRunning && !Running()) + return 0; + cMutexLock MutexLock(&mutex); + if (!pixmaps[num]) + return 0; + int height = pixmaps[num]->DrawPort().Height(); + return height; +} + +int cPixmapContainer::DrawportX(int num) { + if (checkRunning && !Running()) + return 0; + cMutexLock MutexLock(&mutex); + if (!pixmaps[num]) + return 0; + int x = pixmaps[num]->DrawPort().X(); + return x; +} + +int cPixmapContainer::DrawportY(int num) { + if (checkRunning && !Running()) + return 0; + cMutexLock MutexLock(&mutex); + if (!pixmaps[num]) + return 0; + int y = pixmaps[num]->DrawPort().Y(); + return y; +} + +void cPixmapContainer::SetDrawPortPoint(int num, const cPoint &Point) { + if (checkRunning && !Running()) + return; + cMutexLock MutexLock(&mutex); + if (!pixmaps[num]) + return; + pixmaps[num]->SetDrawPortPoint(Point); +} + +/*************************************************************************** +* HELPERS -- do not access the pixmaps array directly, use wrapper functions +* to ensure that a proper lock is set before accessing pixmaps +****************************************************************************/ + +void cPixmapContainer::FadeIn(void) { + if (!fadeTime) + return; + uint64_t Start = cTimeMs::Now(); + int FadeFrameTime = fadeTime / 10; + while (Running()) { + uint64_t Now = cTimeMs::Now(); + double t = min(double(Now - Start) / fadeTime, 1.0); + int Alpha = t * ALPHA_OPAQUE; + for (int i = 0; i < numPixmaps; i++) { + if (!PixmapExists(i)) + continue; + if (pixmapsTransparency[i] > 0) { + int alpha = (100 - pixmapsTransparency[i])*Alpha/100; + SetAlpha(i, alpha); + } else { + SetAlpha(i, Alpha); + } + } + DoFlush(); + int Delta = cTimeMs::Now() - Now; + if (Running() && (Delta < FadeFrameTime)) + cCondWait::SleepMs(FadeFrameTime - Delta); + if ((int)(Now - Start) > fadeTime) + break; + } +} + +void cPixmapContainer::FadeOut(void) { + if (!fadeTime) + return; + uint64_t Start = cTimeMs::Now(); + int FadeFrameTime = fadeTime / 10; + while (true) { + uint64_t Now = cTimeMs::Now(); + double t = min(double(Now - Start) / fadeTime, 1.0); + int Alpha = (1 - t) * ALPHA_OPAQUE; + for (int i = 0; i < numPixmaps; i++) { + if (!PixmapExists(i)) + continue; + if (pixmapsTransparency[i] > 0) { + int alpha = (100 - pixmapsTransparency[i])*Alpha/100; + SetAlpha(i, alpha); + } else { + SetAlpha(i, Alpha); + } + } + DoFlush(); + int Delta = cTimeMs::Now() - Now; + if (Running() && (Delta < FadeFrameTime)) + cCondWait::SleepMs(FadeFrameTime - Delta); + if ((int)(Now - Start) > fadeTime) + break; + } +} + +/***************************************** +* scrollSpeed: 1 slow +* 2 medium +* 3 fast +******************************************/ +void cPixmapContainer::ScrollHorizontal(int num, int scrollDelay, int scrollSpeed, int scrollMode) { + bool carriageReturn = (scrollMode == 1) ? true : false; + + int scrollDelta = 1; + int drawPortX; + + int FrameTime = 0; + if (scrollSpeed == 1) + FrameTime = 50; + else if (scrollSpeed == 2) + FrameTime = 30; + else + FrameTime = 15; + if (!Running()) + return; + int maxX = DrawportWidth(num) - Width(num); + bool doSleep = false; + while (Running()) { + if (doSleep) { + DoSleep(scrollDelay); + doSleep = false; + } + if (!Running()) + return; + uint64_t Now = cTimeMs::Now(); + drawPortX = DrawportX(num); + drawPortX -= scrollDelta; + + if (abs(drawPortX) > maxX) { + DoSleep(scrollDelay); + if (carriageReturn) + drawPortX = 0; + else { + scrollDelta *= -1; + drawPortX -= scrollDelta; + } + doSleep = true; + } + if (!carriageReturn && (drawPortX == 0)) { + scrollDelta *= -1; + doSleep = true; + } + SetDrawPortPoint(num, cPoint(drawPortX, 0)); + int Delta = cTimeMs::Now() - Now; + DoFlush(); + if (Running() && (Delta < FrameTime)) + cCondWait::SleepMs(FrameTime - Delta); + } +} + +/***************************************** +* scrollSpeed: 1 slow +* 2 medium +* 3 fast +******************************************/ +void cPixmapContainer::ScrollVertical(int num, int scrollDelay, int scrollSpeed) { + if (!scrollSpeed) + return; + DoSleep(scrollDelay); + int drawPortY; + int FrameTime = 0; + if (scrollSpeed == 1) + FrameTime = 50; + else if (scrollSpeed == 2) + FrameTime = 30; + else + FrameTime = 15; + int maxY = DrawportHeight(num) - Height(num); + bool doSleep = false; + while (Running()) { + if (doSleep) { + doSleep = false; + DoSleep(scrollDelay); + } + uint64_t Now = cTimeMs::Now(); + drawPortY = DrawportY(num); + drawPortY -= 1; + if (abs(drawPortY) > maxY) { + doSleep = true; + DoSleep(scrollDelay); + drawPortY = 0; + } + SetDrawPortPoint(num, cPoint(0, drawPortY)); + if (doSleep) { + DoSleep(scrollDelay); + } + int Delta = cTimeMs::Now() - Now; + DoFlush(); + if (Running() && (Delta < FrameTime)) + cCondWait::SleepMs(FrameTime - Delta); + } +} + +void cPixmapContainer::CancelSave(void) { + Cancel(-1); + while (Active()) + cCondWait::SleepMs(10); +} + +void cPixmapContainer::DoSleep(int duration) { + int sleepSlice = 10; + for (int i = 0; Running() && (i*sleepSlice < duration); i++) + cCondWait::SleepMs(sleepSlice); +} + +void cPixmapContainer::DrawBlendedBackground(int num, int xStart, int width, tColor color, tColor colorBlending, bool fromTop) { + int height = Height(num); + int numSteps = 16; + int alphaStep = 0x0F; + int alpha = 0x00; + int step, begin, end; + if (fromTop) { + step = 1; + begin = 0; + end = numSteps; + } else { + step = -1; + begin = height; + end = height - numSteps; + } + tColor clr; + bool cont = true; + for (int i = begin; cont; i = i + step) { + clr = AlphaBlend(color, colorBlending, alpha); + DrawRectangle(num, cRect(xStart,i,width,1), clr); + alpha += alphaStep; + if (i == end) + cont = false; + } +} + +void cPixmapContainer::DrawRoundedCorners(int num, int radius, int x, int y, int width, int height) { + if (radius > 2) { + DrawEllipse(num, cRect(x, y, radius, radius), clrTransparent, -2); + DrawEllipse(num, cRect(x + width - radius, y , radius, radius), clrTransparent, -1); + DrawEllipse(num, cRect(x, y + height - radius, radius, radius), clrTransparent, -3); + DrawEllipse(num, cRect(x + width - radius, y + height - radius, radius, radius), clrTransparent, -4); + } +} + +void cPixmapContainer::DrawRoundedCornersWithBorder(int num, tColor borderColor, int radius, int width, int height) { + if (radius < 3) + return; + DrawEllipse(num, cRect(0,0,radius,radius), borderColor, -2); + DrawEllipse(num, cRect(-1,-1,radius,radius), clrTransparent, -2); + + DrawEllipse(num, cRect(width-radius,0,radius,radius), borderColor, -1); + DrawEllipse(num, cRect(width-radius+1,-1,radius,radius), clrTransparent, -1); + + DrawEllipse(num, cRect(0,height-radius,radius,radius), borderColor, -3); + DrawEllipse(num, cRect(-1,height-radius+1,radius,radius), clrTransparent, -3); + + DrawEllipse(num, cRect(width-radius,height-radius,radius,radius), borderColor, -4); + DrawEllipse(num, cRect(width-radius+1,height-radius+1,radius,radius), clrTransparent, -4); +} diff --git a/libcore/pixmapcontainer.h b/libcore/pixmapcontainer.h new file mode 100644 index 0000000..06f9104 --- /dev/null +++ b/libcore/pixmapcontainer.h @@ -0,0 +1,73 @@ +#ifndef __PIXMAP_CONTAINER_H +#define __PIXMAP_CONTAINER_H + +#include +#include +#include "fontmanager.h" + +enum eFlushState { + fsOpen, + fsLock, + fsCount, +}; + +class cPixmapContainer : public cThread { +private: + static cMutex mutex; + static cOsd *osd; + static eFlushState flushState; + bool pixContainerInit; + int numPixmaps; + cPixmap **pixmaps; + int *pixmapsTransparency; + bool checkRunning; + int fadeTime; + bool deleteOsdOnExit; +protected: + void SetInitFinished(void) { pixContainerInit = false; }; + bool CreateOsd(int Left, int Top, int Width, int Height); + void DeleteOsdOnExit(void) { deleteOsdOnExit = true; }; + void LockFlush(void); + void OpenFlush(void); + //Wrappers for access to pixmaps + bool PixmapExists(int num); + int NumPixmaps(void) { return numPixmaps; }; + void CreatePixmap(int num, int Layer, const cRect &ViewPort, const cRect &DrawPort = cRect::Null); + bool DestroyPixmap(int num); + void DrawText(int num, const cPoint &Point, const char *s, tColor ColorFg, tColor ColorBg, std::string fontName, int fontSize); + void DrawRectangle(int num, const cRect &Rect, tColor Color); + void DrawEllipse(int num, const cRect &Rect, tColor Color, int Quadrants = 0); + void DrawImage(int num, const cPoint &Point, const cImage &Image); + void DrawBitmap(int num, const cPoint &Point, const cBitmap &Bitmap, tColor ColorFg = 0, tColor ColorBg = 0, bool Overlay = false); + void Fill(int num, tColor Color); + void SetAlpha(int num, int Alpha); + void SetTransparency(int num, int Transparency); + void SetLayer(int num, int Layer); + int Width(int num); + int Height(int num); + int DrawportWidth(int num); + int DrawportHeight(int num); + int DrawportX(int num); + int DrawportY(int num); + void SetDrawPortPoint(int num, const cPoint &Point); + void SetCheckRunning(void) { checkRunning = true; }; + void UnsetCheckRunning(void) { checkRunning = false; }; + //HELPERS -- do not access the pixmaps array directly, use wrapper functions + void SetFadeTime(int fade) { fadeTime = fade; }; + void FadeIn(void); + void FadeOut(void); + void ScrollVertical(int num, int scrollDelay, int scrollSpeed); + void ScrollHorizontal(int num, int scrollDelay, int scrollSpeed, int scrollMode); + void CancelSave(void); + void DoSleep(int duration); + void DrawBlendedBackground(int num, int xStart, int width, tColor color, tColor colorBlending, bool fromTop); + void DrawRoundedCorners(int num, int radius, int x, int y, int width, int height); + void DrawRoundedCornersWithBorder(int num, tColor borderColor, int radius, int width, int height); +public: + cPixmapContainer(int numPixmaps); + virtual ~cPixmapContainer(void); + void DoFlush(void); + virtual void Action(void) {}; +}; + +#endif //__PIXMAP_CONTAINER_H \ No newline at end of file diff --git a/libcore/timers.c b/libcore/timers.c new file mode 100644 index 0000000..09af69b --- /dev/null +++ b/libcore/timers.c @@ -0,0 +1,84 @@ +#include "timers.h" +#include "../services/epgsearch.h" +#include "../services/remotetimers.h" + +static int CompareTimers(const void *a, const void *b) { + return (*(const cTimer **)a)->Compare(**(const cTimer **)b); +} + +cGlobalSortedTimers::cGlobalSortedTimers(bool forceRefresh) : cVector(Timers.Count()) { + static bool initial = true; + static cRemoteTimerRefresh *remoteTimerRefresh = NULL; + + if (forceRefresh) + initial = true; + //check if remotetimers plugin is available + static cPlugin* pRemoteTimers = cPluginManager::GetPlugin("remotetimers"); + + cSchedulesLock SchedulesLock; + const cSchedules *Schedules = cSchedules::Schedules(SchedulesLock); + + if (pRemoteTimers && initial) { + cString errorMsg; + pRemoteTimers->Service("RemoteTimers::RefreshTimers-v1.0", &errorMsg); + initial = false; + } + + for (cTimer *Timer = Timers.First(); Timer; Timer = Timers.Next(Timer)) + Append(Timer); + + //if remotetimers plugin is available, take timers also from him + if (pRemoteTimers) { + cTimer* remoteTimer = NULL; + while (pRemoteTimers->Service("RemoteTimers::ForEach-v1.0", &remoteTimer) && remoteTimer != NULL) { + remoteTimer->SetEventFromSchedule(Schedules); // make sure the event is current + Append(remoteTimer); + } + } + + Sort(CompareTimers); + + if (pRemoteTimers && (remoteTimerRefresh == NULL)) + remoteTimerRefresh = new cRemoteTimerRefresh(); +} + +int cGlobalSortedTimers::NumTimerConfilicts(void) { + int numConflicts = 0; + cPlugin *p = cPluginManager::GetPlugin("epgsearch"); + if (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->relevantConflicts > 0) { + numConflicts = serviceData->relevantConflicts; + } + delete serviceData; + } + } + return numConflicts; +} + +cRemoteTimerRefresh::cRemoteTimerRefresh(): cThread("skindesigner: RemoteTimers::RefreshTimers") { + Start(); +} + +cRemoteTimerRefresh::~cRemoteTimerRefresh(void) { + Cancel(-1); + while (Active()) + cCondWait::SleepMs(10); +} + +void cRemoteTimerRefresh::Action(void) { + #define REFESH_INTERVALL_MS 30000 + while (Running()) { + cCondWait::SleepMs(REFESH_INTERVALL_MS); + if (!cOsd::IsOpen()) {//make sure that no timer is currently being edited + cGlobalSortedTimers(true); + Timers.SetModified(); + } + } +} + \ No newline at end of file diff --git a/libcore/timers.h b/libcore/timers.h new file mode 100644 index 0000000..81d988a --- /dev/null +++ b/libcore/timers.h @@ -0,0 +1,20 @@ +#ifndef __NOPACITY_TIMERS_H +#define __NOPACITY_TIMERS_H + +#include +#include + +class cGlobalSortedTimers : public cVector { + public: + cGlobalSortedTimers(bool forceRefresh = false); + int NumTimerConfilicts(void); +}; + +class cRemoteTimerRefresh: public cThread { + protected: + virtual void Action(void); + public: + cRemoteTimerRefresh(void); + virtual ~cRemoteTimerRefresh(void); +}; +#endif //__NOPACITY_TIMERS_H diff --git a/libtemplate/globals.c b/libtemplate/globals.c new file mode 100644 index 0000000..9e9ce5f --- /dev/null +++ b/libtemplate/globals.c @@ -0,0 +1,98 @@ +#include "globals.h" +#include "xmlparser.h" +#include + +cGlobals::cGlobals(void) { + fonts.insert(pair("vdrOsd", Setup.FontOsd)); + fonts.insert(pair("vdrFix", Setup.FontFix)); + fonts.insert(pair("vdrSml", Setup.FontSml)); + + string loc = setlocale(LC_NAME, NULL); + size_t index = loc.find_first_of("."); + string langISO = ""; + if (index > 0) { + langISO = loc.substr(0, index); + } + if (langISO.size() == 5) { + language = langISO.c_str(); + } else { + language = "en_EN"; + } + dsyslog("skindesigner: using language %s", language.c_str()); +} + +bool cGlobals::ReadFromXML(void) { + std::string xmlFile = "globals.xml"; + cXmlParser parser; + if (!parser.ReadGlobals(this, xmlFile)) + return false; + if (!parser.ParseGlobals()) + return false; + return true; +} + +bool cGlobals::Translate(string text, string &translation) { + string transStart = "{tr("; + string transEnd = ")}"; + size_t foundStart = text.find(transStart); + size_t foundEnd = text.find(transEnd); + bool translated = false; + + while (foundStart != string::npos && foundEnd != string::npos) { + string token = text.substr(foundStart + 1, foundEnd - foundStart); + string transToken = DoTranslate(token); + if (transToken.size() > 0) + translated = true; + else + return false; + text.replace(foundStart, foundEnd - foundStart + 2, transToken); + foundStart = text.find(transStart); + foundEnd = text.find(transEnd); + } + if (translated) + translation = text; + return translated; +} + +string cGlobals::DoTranslate(string token) { + string translation = ""; + map >::iterator hit = translations.find(token); + if (hit == translations.end()) { + esyslog("skindesigner: invalid translation token %s", token.c_str()); + return translation; + } + map< string, string > translats = hit->second; + map< string, string >::iterator trans = translats.find(language); + if (trans != translats.end()) { + translation = trans->second; + } else { + map< string, string >::iterator transDefault = translats.find("en_EN"); + if (transDefault != translats.end()) { + translation = transDefault->second; + } + } + return translation; +} + +void cGlobals::Debug(void) { + dsyslog("skindesigner: GLOBAL VARIABLES"); + for (map ::iterator col = colors.begin(); col != colors.end(); col++) { + dsyslog("skindesigner: Color \"%s\": %x", (col->first).c_str(), col->second); + } + for (map ::iterator myInt = intVars.begin(); myInt != intVars.end(); myInt++) { + dsyslog("skindesigner: Integer Variable \"%s\": %d", (myInt->first).c_str(), myInt->second); + } + for (map ::iterator myStr = stringVars.begin(); myStr != stringVars.end(); myStr++) { + dsyslog("skindesigner: String Variable \"%s\": \"%s\"", (myStr->first).c_str(), (myStr->second).c_str()); + } + for (map ::iterator font = fonts.begin(); font != fonts.end(); font++) { + dsyslog("skindesigner: Font \"%s\": \"%s\"", (font->first).c_str(), (font->second).c_str()); + } + for (map >::iterator trans = translations.begin(); trans != translations.end(); trans++) { + dsyslog("skindesigner: Translation Token %s", (trans->first).c_str()); + map< string, string > tokenTrans = trans->second; + for (map< string, string >::iterator transTok = tokenTrans.begin(); transTok != tokenTrans.end(); transTok++) { + dsyslog("skindesigner: language %s, translation %s", (transTok->first).c_str(), (transTok->second).c_str()); + } + } +} diff --git a/libtemplate/globals.h b/libtemplate/globals.h new file mode 100644 index 0000000..f7a959e --- /dev/null +++ b/libtemplate/globals.h @@ -0,0 +1,38 @@ +#ifndef __XMLGLOBALS_H +#define __XMLGLOBALS_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +typedef uint32_t tColor; + +// --- cGlobals ------------------------------------------------------------- + +class cGlobals { +private: + string language; + string DoTranslate(string token); +public: + cGlobals(void); + virtual ~cGlobals(void) {}; + map colors; + map intVars; + map stringVars; + map fonts; + map > translations; + bool ReadFromXML(void); + bool Translate(string text, string &translation); + void Debug(void); +}; + +#endif //__XMLGLOBALS_H \ No newline at end of file diff --git a/libtemplate/parameter.c b/libtemplate/parameter.c new file mode 100644 index 0000000..e7dd30a --- /dev/null +++ b/libtemplate/parameter.c @@ -0,0 +1,394 @@ +#include "parameter.h" + +using namespace std; + +// --- cNumericParameter ------------------------------------------------------------- + +cNumericParameter::cNumericParameter(string value) { + this->value = value; + globals = NULL; + isValid = false; + width = 0; + height = 0; + columnWidth = -1; + rowHeight = -1; + hor = true; + defaultValue = 0; +} + +cNumericParameter::~cNumericParameter(void) { +} + +void cNumericParameter::SetAreaSize(int w, int h) { + width = w; + height = h; +} + +int cNumericParameter::Parse(string &parsedValue) { + int retVal = defaultValue; + + if (IsNumber(value)) { + isValid = true; + retVal = atoi(value.c_str()); + return retVal; + } + + //checking for percent value + bool isPercentValue = CheckPercentValue(retVal); + if (isPercentValue) { + isValid = true; + return retVal; + } + + //checking for expression + bool isValidExpression = CheckExpression(retVal, parsedValue); + if (isValidExpression) { + isValid = true; + return retVal; + } + + return retVal; +} + +bool cNumericParameter::IsNumber(const string& s) { + string::const_iterator it = s.begin(); + while (it != s.end() && isdigit(*it)) ++it; + return !s.empty() && it == s.end(); +} + +bool cNumericParameter::CheckPercentValue(int &val) { + bool ok = false; + size_t posPercent = value.find('%'); + if (posPercent != string::npos) { + string strPerc = value.substr(0, posPercent); + if (!IsNumber(strPerc)) { + return ok; + } + int perc = atoi(strPerc.c_str()); + if (hor) { + val = width * perc / 100; + } else { + val = height * perc / 100; + } + ok = true; + } + return ok; +} + +bool cNumericParameter::CheckExpression(int &val, string &parsedVal) { + bool ok = false; + string parsedValue = value; + //remove white spaces + parsedValue.erase( std::remove_if( parsedValue.begin(), parsedValue.end(), ::isspace ), parsedValue.end() ); + + //check and replace {areawidth} and {areaheight} tokens + string tokenWidth = "{areawidth}"; + string tokenHeight = "{areaheight}"; + + stringstream sw; + sw << width; + string strWidth = sw.str(); + stringstream sh; + sh << height; + string strHeight = sh.str(); + + bool foundToken = true; + while(foundToken) { + size_t foundTokenWidth = parsedValue.find(tokenWidth); + if (foundTokenWidth != string::npos) { + parsedValue = parsedValue.replace(foundTokenWidth, tokenWidth.size(), strWidth); + } else { + foundToken = false; + } + } + + foundToken = true; + while(foundToken) { + size_t foundTokenHeight = parsedValue.find(tokenHeight); + if (foundTokenHeight != string::npos) { + parsedValue = parsedValue.replace(foundTokenHeight, tokenHeight.size(), strHeight); + } else { + foundToken = false; + } + } + + //check and replace {columnwidth} and {rowheight} tokens for loop functions + if (columnWidth > 0 || rowHeight > 0) { + tokenWidth = "{columnwidth}"; + tokenHeight = "{rowheight}"; + stringstream cw; + cw << columnWidth; + strWidth = cw.str(); + stringstream rh; + rh << rowHeight; + strHeight = rh.str(); + + foundToken = true; + while(foundToken) { + size_t foundTokenWidth = parsedValue.find(tokenWidth); + if (foundTokenWidth != string::npos) { + parsedValue = parsedValue.replace(foundTokenWidth, tokenWidth.size(), strWidth); + } else { + foundToken = false; + } + } + + foundToken = true; + while(foundToken) { + size_t foundTokenHeight = parsedValue.find(tokenHeight); + if (foundTokenHeight != string::npos) { + parsedValue = parsedValue.replace(foundTokenHeight, tokenHeight.size(), strHeight); + } else { + foundToken = false; + } + } + } + + if (globals) { + for (map::iterator globInt = globals->intVars.begin(); globInt != globals->intVars.end(); globInt++) { + stringstream sToken; + sToken << "{" << globInt->first << "}"; + string token = sToken.str(); + size_t foundToken = parsedValue.find(token); + if (foundToken != string::npos) { + stringstream st; + st << globInt->second; + parsedValue = parsedValue.replace(foundToken, token.size(), st.str()); + } + } + } + + if (IsNumber(parsedValue)) { + ok = true; + val = atoi(parsedValue.c_str()); + return ok; + } + + if (!ValidNumericExpression(parsedValue)) { + parsedVal = parsedValue; + return ok; + } + ok = true; + char * expression = new char[parsedValue.size() + 1]; + std::copy(parsedValue.begin(), parsedValue.end(), expression); + expression[parsedValue.size()] = '\0'; + int expRes = EvaluateTheExpression(expression); + val = expRes; + delete[] expression; + return ok; +} + +bool cNumericParameter::ValidNumericExpression(string &parsedValue) { + string::const_iterator it = parsedValue.begin(); + while (it != parsedValue.end() && (isdigit(*it) || *it == '.' || *it == ',' || *it == '+' || *it == '-' || *it == '*' || *it == '/')) ++it; + return !parsedValue.empty() && it == parsedValue.end(); +} + +int cNumericParameter::EvaluateTheExpression(char* expr) { + return round(ParseSummands(expr)); +} + +double cNumericParameter::ParseAtom(char*& expr) { + // Read the number from string + char* end_ptr; + double res = strtod(expr, &end_ptr); + // Advance the pointer and return the result + expr = end_ptr; + return res; +} + +// Parse multiplication and division +double cNumericParameter::ParseFactors(char*& expr) { + double num1 = ParseAtom(expr); + for(;;) { + // Save the operation + char op = *expr; + if(op != '/' && op != '*') + return num1; + expr++; + double num2 = ParseAtom(expr); + // Perform the saved operation + if(op == '/') { + if (num2 != 0) { + num1 /= num2; + } + } else + num1 *= num2; + } +} + +// Parse addition and subtraction +double cNumericParameter::ParseSummands(char*& expr) { + double num1 = ParseFactors(expr); + for(;;) { + char op = *expr; + if(op != '-' && op != '+') + return num1; + expr++; + double num2 = ParseFactors(expr); + if(op == '-') + num1 -= num2; + else + num1 += num2; + } +} + +// --- cConditionalParameter ------------------------------------------------------------- + +cConditionalParameter::cConditionalParameter(cGlobals *globals, string value) { + this->globals = globals; + isTrue = false; + this->value = value; + type = cpNone; +} + +cConditionalParameter::~cConditionalParameter(void) { +} + +void cConditionalParameter::Tokenize(void) { + size_t posAnd = value.find("++"); + if (posAnd != string::npos) { + type = cpAnd; + TokenizeValue("++"); + } else { + size_t posOr = value.find("||"); + if (posOr != string::npos) { + type = cpOr; + TokenizeValue("||"); + } + } + if (type == cpNone) { + InsertCondition(value); + } +} + +bool cConditionalParameter::Evaluate(map < string, int > *intTokens, map < string, string > *stringTokens) { + isTrue = false; + bool first = true; + for (vector::iterator cond = conditions.begin(); cond != conditions.end(); cond++) { + bool tokenTrue = false; + + if (cond->type == ctStringSet) { + if (stringTokens) { + map < string, string >::iterator hit = stringTokens->find(cond->tokenName); + if (hit != stringTokens->end()) { + string value = hit->second; + if (value.size() > 0) + tokenTrue = true; + } + } + } else { + int tokenValue = EvaluateParameter(cond->tokenName, intTokens, stringTokens); + if (cond->type == ctBool) { + tokenTrue = tokenValue; + } else if (cond->type == ctGreater) { + tokenTrue = (tokenValue > cond->compareValue) ? true : false; + } else if (cond->type == ctLower) { + tokenTrue = (tokenValue < cond->compareValue) ? true : false; + } else if (cond->type == ctEquals) { + tokenTrue = (tokenValue == cond->compareValue) ? true : false; + } + } + + if (cond->isNegated) + tokenTrue = !tokenTrue; + if (type == cpAnd) { + if (first) + isTrue = tokenTrue; + else + isTrue = isTrue && tokenTrue; + } else if (type == cpOr) { + isTrue = isTrue || tokenTrue; + } else { + isTrue = tokenTrue; + } + first = false; + } +} + +int cConditionalParameter::EvaluateParameter(string token, map < string, int > *intTokens, map < string, string > *stringTokens) { + //first check globals + map < string, int >::iterator hitGlobals = globals->intVars.find(token); + if (hitGlobals != globals->intVars.end()) { + return hitGlobals->second; + } else { + //then check tokens + if (intTokens) { + map < string, int >::iterator hit = intTokens->find(token); + if (hit != intTokens->end()) { + return hit->second; + } + } + if (stringTokens) { + map < string, string >::iterator hit = stringTokens->find(token); + if (hit != stringTokens->end()) { + string value = hit->second; + return atoi(value.c_str()); + } + } + } + return 0; +} + +void cConditionalParameter::TokenizeValue(string sep) { + string buffer = value; + bool sepFound = true; + while (sepFound) { + size_t posSep = buffer.find(sep); + if (posSep == string::npos) { + InsertCondition(buffer); + sepFound = false; + } + string token = buffer.substr(0, posSep); + buffer = buffer.replace(0, posSep + sep.size(), ""); + InsertCondition(token); + } +} + +void cConditionalParameter::InsertCondition(string cond) { + cond.erase( std::remove_if( cond.begin(), cond.end(), ::isspace ), cond.end() ); + + if (cond.size() < 1) + return; + + size_t tokenStart = cond.find('{'); + size_t tokenEnd = cond.find('}'); + + if (tokenStart == string::npos || tokenEnd == string::npos || tokenStart > tokenEnd) + return; + + string tokenName = cond.substr(tokenStart + 1, tokenEnd - tokenStart - 1); + string rest = cond.replace(tokenStart, tokenEnd - tokenStart + 1, ""); + + sCondition sCond; + sCond.tokenName = tokenName; + sCond.type = ctBool; + sCond.compareValue = 0; + sCond.isNegated = false; + if (!rest.compare("not")) { + sCond.isNegated = true; + } else if (!rest.compare("isset")) { + sCond.type = ctStringSet; + } else if (startswith(rest.c_str(), "gt(")) { + string compVal = rest.substr(4, rest.size() - 5); + sCond.compareValue = atoi(compVal.c_str()); + sCond.type = ctGreater; + } else if (startswith(rest.c_str(), "lt(")) { + string compVal = rest.substr(4, rest.size() - 5); + sCond.compareValue = atoi(compVal.c_str()); + sCond.type = ctLower; + } else if (startswith(rest.c_str(), "eq(")) { + string compVal = rest.substr(4, rest.size() - 5); + sCond.compareValue = atoi(compVal.c_str()); + sCond.type = ctEquals; + } + + conditions.push_back(sCond); +} + +void cConditionalParameter::Debug(void) { + dsyslog("skindesigner: Condition %s, Type: %s, cond is %s", value.c_str(), (type == cpAnd)?"and combination":((type == cpOr)?"or combination":"single param") , isTrue?"true":"false"); + for (vector::iterator it = conditions.begin(); it != conditions.end(); it++) { + dsyslog("skindesigner: cond token %s, type: %d, compareValue %d, negated: %d", it->tokenName.c_str(), it->type, it->compareValue, it->isNegated); + } +} \ No newline at end of file diff --git a/libtemplate/parameter.h b/libtemplate/parameter.h new file mode 100644 index 0000000..914f3fc --- /dev/null +++ b/libtemplate/parameter.h @@ -0,0 +1,138 @@ +#ifndef __TEMPLATEPARAMETER_H +#define __TEMPLATEPARAMETER_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "globals.h" + +using namespace std; + +enum eAlign { + alLeft, + alCenter, + alRight, + alTop, + alBottom +}; + +enum eScrollMode { + smNone, + smCarriageReturn, + smForthAndBack +}; + +enum eScrollSpeed { + ssNone, + ssSlow, + ssMedium, + ssFast +}; + +enum eOrientation { + orNone, + orHorizontal, + orVertical, + orAbsolute +}; + +// --- cNumericParameter ------------------------------------------------------------- + +class cNumericParameter { +private: + cGlobals *globals; + string value; + bool isValid; + int width; + int height; + int columnWidth; + int rowHeight; + bool hor; + int defaultValue; + bool IsNumber(const string& s); + bool CheckPercentValue(int &val); + bool CheckExpression(int &val, string &parsedVal); + bool ValidNumericExpression(string &parsedValue); + int EvaluateTheExpression(char* expr); + double ParseAtom(char*& expr); + double ParseFactors(char*& expr); + double ParseSummands(char*& expr); +public: + cNumericParameter(string value); + virtual ~cNumericParameter(void); + void SetGlobals(cGlobals *globals) { this->globals = globals; }; + void SetAreaSize(int w, int h); + void SetLoopContainer(int columnWidth, int rowHeight) { this->columnWidth = columnWidth; this->rowHeight = rowHeight; }; + void SetDefault(int def) { defaultValue = def; }; + void SetHorizontal(void) { hor = true; }; + void SetVertical(void) { hor = false; }; + int Parse(string &parsedValue); + bool Valid(void) { return isValid; }; +}; + +// --- cTextToken ------------------------------------------------------------- + +enum eTextTokenType { + ttConstString, + ttToken, + ttConditionalToken +}; + +class cTextToken { +public: + eTextTokenType type; + string value; + vector subTokens; +}; + +// --- cConditionalParameter ------------------------------------------------------------- + +enum eCondParameterType { + cpAnd, + cpOr, + cpNone +}; + +enum eCondType { + ctLower, + ctGreater, + ctEquals, + ctBool, + ctStringSet, + ctNone +}; + +struct sCondition { + string tokenName; + bool isNegated; + eCondType type; + int compareValue; +}; + +class cConditionalParameter { +private: + cGlobals *globals; + bool isTrue; + string value; + eCondParameterType type; + vector conditions; + void TokenizeValue(string sep); + void InsertCondition(string cond); + int EvaluateParameter(string token, map < string, int > *intTokens, map < string, string > *stringTokens); +public: + cConditionalParameter(cGlobals *globals, string value); + virtual ~cConditionalParameter(void); + void Tokenize(void); + bool Evaluate(map < string, int > *intTokens, map < string, string > *stringTokens); + bool IsTrue(void) { return isTrue; }; + void Debug(void); +}; +#endif //__TEMPLATEPARAMETER_H \ No newline at end of file diff --git a/libtemplate/template.c b/libtemplate/template.c new file mode 100644 index 0000000..b5889ad --- /dev/null +++ b/libtemplate/template.c @@ -0,0 +1,273 @@ + #include "template.h" +#include "xmlparser.h" +#include "../config.h" + +// --- cTemplate ------------------------------------------------------------- + +cTemplate::cTemplate(eViewType viewType) { + globals = NULL; + rootView = NULL; + this->viewType = viewType; + CreateView(); +} + +cTemplate::~cTemplate() { + + if (rootView) + delete rootView; + +} + +/******************************************************************* +* Public Functions +*******************************************************************/ +bool cTemplate::ReadFromXML(void) { + std::string xmlFile; + switch (viewType) { + case vtDisplayChannel: + xmlFile = "displaychannel.xml"; + break; + case vtDisplayMenu: + xmlFile = "displaymenu.xml"; + break; + case vtDisplayMessage: + xmlFile = "displaymessage.xml"; + break; + case vtDisplayReplay: + xmlFile = "displayreplay.xml"; + break; + case vtDisplayVolume: + xmlFile = "displayvolume.xml"; + break; + case vtDisplayAudioTracks: + xmlFile = "displayaudiotracks.xml"; + break; + default: + return false; + } + + cXmlParser parser; + if (!parser.ReadView(rootView, xmlFile)) { + return false; + } + if (!parser.ParseView()) { + return false; + } + return true; +} + +void cTemplate::SetGlobals(cGlobals *globals) { + this->globals = globals; + rootView->SetGlobals(globals); +} + +void cTemplate::Translate(void) { + rootView->Translate(); +} + + +void cTemplate::PreCache(void) { + rootView->PreCache(false); +} + +vector< pair > cTemplate::GetUsedFonts(void) { + vector< pair > usedFonts; + + GetUsedFonts(rootView, usedFonts); + + rootView->InitSubViewIterator(); + cTemplateView *subView = NULL; + while(subView = rootView->GetNextSubView()) { + GetUsedFonts(subView, usedFonts); + } + + return usedFonts; +} + + +void cTemplate::CacheImages(void) { + CacheImages(rootView); + + rootView->InitSubViewIterator(); + cTemplateView *subView = NULL; + while(subView = rootView->GetNextSubView()) { + CacheImages(subView); + } +} + +void cTemplate::Debug(void) { + + rootView->Debug(); + +} + +/******************************************************************* +* Private Functions +*******************************************************************/ + +void cTemplate::CreateView(void) { + switch (viewType) { + case vtDisplayChannel: + rootView = new cTemplateViewChannel(); + break; + case vtDisplayMenu: + rootView = new cTemplateViewMenu(); + break; + case vtDisplayReplay: + rootView = new cTemplateViewReplay(); + break; + case vtDisplayVolume: + rootView = new cTemplateViewVolume(); + break; + case vtDisplayAudioTracks: + rootView = new cTemplateViewAudioTracks(); + break; + case vtDisplayMessage: + rootView = new cTemplateViewMessage(); + break; + default: + esyslog("skindesigner: unknown view %d", viewType); + } +} + +void cTemplate::GetUsedFonts(cTemplateView *view, vector< pair > &usedFonts) { + //used fonts in viewElements + view->InitViewElementIterator(); + cTemplateViewElement *viewElement = NULL; + while(viewElement = view->GetNextViewElement()) { + viewElement->InitIterator(); + cTemplatePixmap *pix = NULL; + while(pix = viewElement->GetNextPixmap()) { + pix->InitIterator(); + cTemplateFunction *func = NULL; + while(func = pix->GetNextFunction()) { + if (func->GetType() == ftDrawText) { + usedFonts.push_back(pair(func->GetFontName(), func->GetNumericParameter(ptFontSize))); + } + } + } + } + //used fonts in viewLists pixmaps + view->InitViewListIterator(); + cTemplateViewList *viewList = NULL; + while(viewList = view->GetNextViewList()) { + viewList->InitIterator(); + cTemplatePixmap *pix = NULL; + while(pix = viewList->GetNextPixmap()) { + pix->InitIterator(); + cTemplateFunction *func = NULL; + while(func = pix->GetNextFunction()) { + if (func->GetType() == ftDrawText) { + usedFonts.push_back(pair(func->GetFontName(), func->GetNumericParameter(ptFontSize))); + } + } + } + cTemplateViewElement *listElement = viewList->GetListElement(); + listElement->InitIterator(); + while(pix = listElement->GetNextPixmap()) { + pix->InitIterator(); + cTemplateFunction *func = NULL; + while(func = pix->GetNextFunction()) { + if (func->GetType() == ftDrawText) { + usedFonts.push_back(pair(func->GetFontName(), func->GetNumericParameter(ptFontSize))); + } + } + } + } + //used fonts in viewTabs + view->InitViewTabIterator(); + cTemplateViewTab *viewTab = NULL; + while(viewTab = view->GetNextViewTab()) { + viewTab->InitIterator(); + cTemplateFunction *func = NULL; + while(func = viewTab->GetNextFunction()) { + if (func->GetType() == ftDrawText) { + usedFonts.push_back(pair(func->GetFontName(), func->GetNumericParameter(ptFontSize))); + } + } + } +} + +void cTemplate::CacheImages(cTemplateView *view) { + //used images in viewElements + view->InitViewElementIterator(); + cTemplateViewElement *viewElement = NULL; + while(viewElement = view->GetNextViewElement()) { + viewElement->InitIterator(); + cTemplatePixmap *pix = NULL; + while(pix = viewElement->GetNextPixmap()) { + pix->InitIterator(); + cTemplateFunction *func = NULL; + while(func = pix->GetNextFunction()) { + if (func->GetType() == ftDrawImage) { + CacheImage(func); + } + } + } + } + //used images in viewLists pixmaps + view->InitViewListIterator(); + cTemplateViewList *viewList = NULL; + while(viewList = view->GetNextViewList()) { + viewList->InitIterator(); + cTemplatePixmap *pix = NULL; + while(pix = viewList->GetNextPixmap()) { + pix->InitIterator(); + cTemplateFunction *func = NULL; + while(func = pix->GetNextFunction()) { + if (func->GetType() == ftDrawImage) { + CacheImage(func); + } + } + } + cTemplateViewElement *listElement = viewList->GetListElement(); + listElement->InitIterator(); + while(pix = listElement->GetNextPixmap()) { + pix->InitIterator(); + cTemplateFunction *func = NULL; + while(func = pix->GetNextFunction()) { + if (func->GetType() == ftDrawImage) { + CacheImage(func); + } + } + } + } + //used logos in viewTabs + view->InitViewTabIterator(); + cTemplateViewTab *viewTab = NULL; + while(viewTab = view->GetNextViewTab()) { + viewTab->InitIterator(); + cTemplateFunction *func = NULL; + while(func = viewTab->GetNextFunction()) { + if (func->GetType() == ftDrawImage) { + CacheImage(func); + } + } + } +} + +void cTemplate::CacheImage(cTemplateFunction *func) { + eImageType imgType = (eImageType)func->GetNumericParameter(ptImageType); + int width = func->GetNumericParameter(ptWidth); + int height = func->GetNumericParameter(ptHeight); + + switch (imgType) { + case itIcon: + case itMenuIcon: { + string path = func->GetParameter(ptPath); + imgCache->CacheIcon(imgType, path, width, height); + break; } + case itChannelLogo: { + string doCache = func->GetParameter(ptCache); + if (!doCache.compare("true")) { + imgCache->CacheLogo(width, height); + } + break; } + case itSkinPart: { + string path = func->GetParameter(ptPath); + imgCache->CacheSkinpart(path, width, height); + break; } + default: + break; + } +} diff --git a/libtemplate/template.h b/libtemplate/template.h new file mode 100644 index 0000000..a4ef238 --- /dev/null +++ b/libtemplate/template.h @@ -0,0 +1,57 @@ +#ifndef __TEMPLATE_H +#define __TEMPLATE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "globals.h" +#include "templateview.h" +#include "templateviewelement.h" +#include "templatepixmap.h" +#include "templatefunction.h" + +using namespace std; + +// --- cTemplate ------------------------------------------------------------- +enum eViewType { + vtDisplayChannel, + vtDisplayMenu, + vtDisplayReplay, + vtDisplayVolume, + vtDisplayAudioTracks, + vtDisplayMessage +}; + +class cTemplate { +private: + eViewType viewType; + void CacheImage(cTemplateFunction *func); +protected: + cGlobals *globals; + cTemplateView *rootView; + void CreateView(void); + void GetUsedFonts(cTemplateView *view, vector< pair > &usedFonts); + void CacheImages(cTemplateView *view); +public: + cTemplate(eViewType viewType); + virtual ~cTemplate(void); + bool ReadFromXML(void); + void SetGlobals(cGlobals *globals); + cTemplateView *GetRootView(void) { return rootView; }; + void Translate(void); + void PreCache(void); + //get fonts for pre caching + vector< pair > GetUsedFonts(void); + void CacheImages(void); + //Debug + void Debug(void); +}; + +#endif //__TEMPLATE_H \ No newline at end of file diff --git a/libtemplate/templatefunction.c b/libtemplate/templatefunction.c new file mode 100644 index 0000000..9dca94e --- /dev/null +++ b/libtemplate/templatefunction.c @@ -0,0 +1,1474 @@ +#include "templatefunction.h" +#include "../config.h" +#include "../libcore/helpers.h" + +using namespace std; + +// --- cTemplateFunction ------------------------------------------------------------- + +cTemplateFunction::cTemplateFunction(eFuncType type) { + this->type = type; + debug = false; + containerX = 0; + containerY = 0; + containerWidth = 0; + containerHeight = 0; + columnWidth = -1; + rowHeight = -1; + globals = NULL; + condParam = NULL; + parsedCompletely = false; + updated = false; + alreadyCutted = false; + parsedTextWidth = 0; + fontName = ""; + imgPath = ""; + textboxHeight = 0; + stringTokens = NULL; + intTokens = NULL; + parsedText = ""; + cuttedText = ""; +} + +cTemplateFunction::~cTemplateFunction(void) { + if (condParam) + delete condParam; +} + +/******************************************************************* +* Public Functions +*******************************************************************/ + +void cTemplateFunction::SetParameters(vector > params) { + for (vector >::iterator it = params.begin(); it != params.end(); it++) { + string name = it->first; + pair< eParamType, string > p; + if (!name.compare("debug")) { + string value = it->second; + if (!value.compare("true")) { + debug = true; + } + continue; + } else if (!name.compare("condition")) { + p.first = ptCond; + } else if (!name.compare("name")) { + p.first = ptName; + } else if (!name.compare("x")) { + p.first = ptX; + } else if (!name.compare("y")) { + p.first = ptY; + } else if (!name.compare("width")) { + p.first = ptWidth; + } else if (!name.compare("height")) { + p.first = ptHeight; + } else if (!name.compare("menuitemwidth")) { + p.first = ptMenuItemWidth; + } else if (!name.compare("fadetime")) { + p.first = ptFadeTime; + } else if (!name.compare("imagetype")) { + p.first = ptImageType; + } else if (!name.compare("path")) { + p.first = ptPath; + } else if (!name.compare("color")) { + p.first = ptColor; + } else if (!name.compare("font")) { + p.first = ptFont; + } else if (!name.compare("fontsize")) { + p.first = ptFontSize; + } else if (!name.compare("text")) { + p.first = ptText; + } else if (!name.compare("layer")) { + p.first = ptLayer; + } else if (!name.compare("transparency")) { + p.first = ptTransparency; + } else if (!name.compare("quadrant")) { + p.first = ptQuadrant; + } else if (!name.compare("align")) { + p.first = ptAlign; + } else if (!name.compare("valign")) { + p.first = ptValign; + } else if (!name.compare("delay")) { + p.first = ptDelay; + } else if (!name.compare("mode")) { + p.first = ptScrollMode; + } else if (!name.compare("scrollspeed")) { + p.first = ptScrollSpeed; + } else if (!name.compare("orientation")) { + p.first = ptOrientation; + } else if (!name.compare("numlistelements")) { + p.first = ptNumElements; + } else if (!name.compare("scrollelement")) { + p.first = ptScrollElement; + } else if (!name.compare("scrollheight")) { + p.first = ptScrollHeight; + } else if (!name.compare("float")) { + p.first = ptFloat; + } else if (!name.compare("floatwidth")) { + p.first = ptFloatWidth; + } else if (!name.compare("floatheight")) { + p.first = ptFloatHeight; + } else if (!name.compare("maxlines")) { + p.first = ptMaxLines; + } else if (!name.compare("columnwidth")) { + p.first = ptColumnWidth; + } else if (!name.compare("rowheight")) { + p.first = ptRowHeight; + } else if (!name.compare("overflow")) { + p.first = ptOverflow; + } else if (!name.compare("scaletvx")) { + p.first = ptScaleTvX; + } else if (!name.compare("scaletvy")) { + p.first = ptScaleTvY; + } else if (!name.compare("scaletvwidth")) { + p.first = ptScaleTvWidth; + } else if (!name.compare("scaletvheight")) { + p.first = ptScaleTvHeight; + } else if (!name.compare("cache")) { + p.first = ptCache; + } else if (!name.compare("determinatefont")) { + p.first = ptDeterminateFont; + } else { + p.first = ptNone; + } + p.second = it->second; + nativeParameters.insert(p); + } +} + +void cTemplateFunction::SetParameter(eParamType type, string value) { + nativeParameters.erase(type); + nativeParameters.insert(pair(type, value)); +} + +void cTemplateFunction::SetContainer(int x, int y, int w, int h) { + containerX = x; + containerY = y; + containerWidth = w; + containerHeight = h; +} + +void cTemplateFunction::SetLoopContainer(int columnWidth, int rowHeight) { + this->columnWidth = columnWidth; + this->rowHeight = rowHeight; +} + +void cTemplateFunction::SetWidthManually(string width) { + nativeParameters.erase(ptWidth); + nativeParameters.insert(pair(ptWidth, width)); +} + +void cTemplateFunction::SetHeightManually(string height) { + nativeParameters.erase(ptHeight); + nativeParameters.insert(pair(ptHeight, height)); +} + +void cTemplateFunction::SetXManually(int newX) { + numericParameters.erase(ptX); + numericParameters.insert(pair(ptX, newX)); +} + +void cTemplateFunction::SetYManually(int newY) { + numericParameters.erase(ptY); + numericParameters.insert(pair(ptY, newY)); +} + +void cTemplateFunction::SetTextboxHeight(int boxHeight) { + numericParameters.erase(ptHeight); + numericParameters.insert(pair(ptHeight, boxHeight)); +} + +void cTemplateFunction::SetTranslatedText(string translation) { + if (type != ftDrawText && type != ftDrawTextBox) + return; + if (translation.size() == 0) + return; + nativeParameters.erase(ptText); + nativeParameters.insert(pair(ptText, translation)); +} + +void cTemplateFunction::SetMaxTextWidth(int maxWidth) { + if (type != ftDrawText) + return; + numericParameters.erase(ptWidth); + numericParameters.insert(pair(ptWidth, maxWidth)); +} + +bool cTemplateFunction::CalculateParameters(void) { + bool paramValid = true; + bool paramsValid = true; + for (map< eParamType, string >::iterator param = nativeParameters.begin(); param != nativeParameters.end(); param++) { + paramValid = true; + eParamType type = param->first; + string value = param->second; + switch (type) { + case ptCond: + paramValid = SetCondition(value); + break; + case ptX: + case ptY: + case ptWidth: + case ptHeight: + case ptMenuItemWidth: + case ptFadeTime: + case ptDelay: + case ptFontSize: + case ptLayer: + case ptTransparency: + case ptQuadrant: + case ptNumElements: + case ptFloatWidth: + case ptFloatHeight: + case ptMaxLines: + case ptColumnWidth: + case ptRowHeight: + case ptScaleTvX: + case ptScaleTvY: + case ptScaleTvWidth: + case ptScaleTvHeight: + SetNumericParameter(type, value); + break; + case ptAlign: + case ptValign: + paramValid = SetAlign(type, value); + break; + case ptImageType: + paramValid = SetImageType(type, value); + break; + case ptColor: + paramValid = SetColor(type, value); + break; + case ptFont: + paramValid = SetFont(type, value); + break; + case ptText: + paramValid = SetTextTokens(value); + break; + case ptScrollMode: + paramValid = SetScrollMode(value); + break; + case ptScrollSpeed: + paramValid = SetScrollSpeed(value); + break; + case ptOrientation: + paramValid = SetOrientation(value); + break; + case ptFloat: + paramValid = SetFloating(value); + break; + case ptOverflow: + paramValid = SetOverflow(value); + default: + paramValid = true; + break; + } + if (!paramValid) { + paramsValid = false; + esyslog("skindesigner: %s: invalid parameter %d, value %s", GetFuncName().c_str(), type, value.c_str()); + } + } + return paramsValid; +} + +void cTemplateFunction::CompleteParameters(void) { + switch (type) { + case ftDrawImage: { + //Calculate img size + if ((GetNumericParameter(ptImageType) == itChannelLogo)||(GetNumericParameter(ptImageType) == itSepLogo)) { + int logoWidthOrig = config.logoWidth; + int logoHeightOrig = config.logoHeight; + int logoWidth = GetNumericParameter(ptWidth); + int logoHeight = GetNumericParameter(ptHeight); + if (logoWidth <= 0 && logoHeight <= 0) + break; + if (logoWidth <= 0 && logoHeightOrig > 0) { + logoWidth = logoHeight * logoWidthOrig / logoHeightOrig; + numericParameters.erase(ptWidth); + numericParameters.insert(pair(ptWidth, logoWidth)); + } else if (logoHeight <= 0 && logoWidthOrig > 0) { + logoHeight = logoWidth * logoHeightOrig / logoWidthOrig; + numericParameters.erase(ptHeight); + numericParameters.insert(pair(ptHeight, logoHeight)); + } + } + CalculateAlign(GetNumericParameter(ptWidth), GetNumericParameter(ptHeight)); + if (imgPath.size() == 0) { + imgPath = GetParameter(ptPath); + } + break; } + case ftDrawRectangle: + CalculateAlign(GetNumericParameter(ptWidth), GetNumericParameter(ptHeight)); + break; + case ftDrawEllipse: + CalculateAlign(GetNumericParameter(ptWidth), GetNumericParameter(ptHeight)); + break; + case ftDrawText: + CalculateAlign(GetWidth(), GetHeight()); + break; + default: + break; + } +} + +void cTemplateFunction::ClearDynamicParameters(void) { + parsedText = ""; + cuttedText = ""; + alreadyCutted = false; + parsedTextWidth = 0; + textboxHeight = 0; + + //clear dynamically parsed int parameters + for (map::iterator it = numericDynamicParameters.begin(); it != numericDynamicParameters.end(); it++) { + numericParameters.erase(it->first); + } + //restoring dynamic numeric parameters only if x, y, width or height of other elements is needed dynamically + for (map::iterator it = nativeParameters.begin(); it != nativeParameters.end(); it++) { + eParamType paramType = it->first; + if (paramType == ptX || + paramType == ptY || + paramType == ptWidth || + paramType == ptHeight || + paramType == ptFloatWidth || + paramType == ptFloatHeight) + { + string value = it->second; + if (value.find("{width(") != string::npos || value.find("{height(") != string::npos || value.find("{posx(") != string::npos || value.find("{posy(") != string::npos) { + numericDynamicParameters.erase(paramType); + SetNumericParameter(paramType, value); + } + } + } + +} + +bool cTemplateFunction::ParseParameters(void) { + updated = false; + parsedCompletely = true; + + if (stringTokens) { + ParseStringParameters(); + } + + if (intTokens && numericDynamicParameters.size() > 0) { + ParseNumericalParameters(); + } + + if (condParam) { + condParam->Evaluate(intTokens, stringTokens); + } + + return parsedCompletely; +} + +string cTemplateFunction::GetParameter(eParamType type) { + map::iterator hit = nativeParameters.find(type); + if (hit == nativeParameters.end()) + return ""; + return hit->second; +} + +int cTemplateFunction::GetNumericParameter(eParamType type) { + map::iterator hit = numericParameters.find(type); + if (hit == numericParameters.end()) { + //Set Default Value for Integer Parameters + if (type == ptLayer) + return 1; + else if (type == ptTransparency) + return 0; + else if (type == ptDelay) + return 0; + else if (type == ptFadeTime) + return 0; + else if (type == ptMenuItemWidth) + return 0; + return -1; + } + return hit->second; +} + +string cTemplateFunction::GetText(bool cut) { + if (!cut) { + return parsedText; + } + if (alreadyCutted && cuttedText.size() > 0) { + return cuttedText; + } + alreadyCutted = true; + int maxWidth = GetNumericParameter(ptWidth); + if (maxWidth > 0) { + parsedTextWidth = fontManager->Width(fontName, GetNumericParameter(ptFontSize), parsedText.c_str()); + if (parsedTextWidth > maxWidth) { + cuttedText = CutText(parsedText, maxWidth, fontName, GetNumericParameter(ptFontSize)); + return cuttedText; + } + } + return parsedText; +} + + +tColor cTemplateFunction::GetColorParameter(eParamType type) { + map::iterator hit = colorParameters.find(type); + if (hit == colorParameters.end()) + return 0x00000000; + return hit->second; +} + +int cTemplateFunction::GetWidth(bool cutted) { + int funcWidth = 0; + switch (type) { + case ftDrawText: { + if (cutted) { + if (!alreadyCutted) { + alreadyCutted = true; + int maxWidth = GetNumericParameter(ptWidth); + if (maxWidth > 0) { + parsedTextWidth = fontManager->Width(fontName, GetNumericParameter(ptFontSize), parsedText.c_str()); + if (parsedTextWidth > maxWidth) { + cuttedText = CutText(parsedText, maxWidth, fontName, GetNumericParameter(ptFontSize)); + } + } + } + if (cuttedText.size() > 0) + return fontManager->Width(fontName, GetNumericParameter(ptFontSize), cuttedText.c_str()); + } + if (parsedTextWidth > 0) + funcWidth = parsedTextWidth; + else + funcWidth = fontManager->Width(fontName, GetNumericParameter(ptFontSize), parsedText.c_str()); + break; } + case ftFill: + case ftDrawImage: + case ftDrawRectangle: + case ftDrawEllipse: + case ftDrawTextBox: + funcWidth = GetNumericParameter(ptWidth); + break; + default: + esyslog("skindesigner: GetWidth not implemented for funcType %d", type); + break; + } + return funcWidth; +} + +int cTemplateFunction::GetHeight(void) { + int funcHeight = 0; + switch (type) { + case ftDrawText: + funcHeight = fontManager->Height(fontName, GetNumericParameter(ptFontSize)); + break; + case ftFill: + case ftDrawImage: + case ftDrawRectangle: + case ftDrawEllipse: + funcHeight = GetNumericParameter(ptHeight); + break; + case ftDrawTextBox: { + int maxLines = GetNumericParameter(ptMaxLines); + int fixedBoxHeight = GetNumericParameter(ptHeight); + if (maxLines > 0) { + funcHeight = maxLines * fontManager->Height(fontName, GetNumericParameter(ptFontSize)); + } else if (fixedBoxHeight > 0) { + funcHeight = fixedBoxHeight; + } else if (textboxHeight > 0) { + funcHeight = textboxHeight; + } else { + funcHeight = CalculateTextBoxHeight(); + textboxHeight = funcHeight; + } + break; } + case ftLoop: + //TODO: to be implemented + break; + default: + esyslog("skindesigner: GetHeight not implemented for funcType %d", type); + break; + } + return funcHeight; +} + +void cTemplateFunction::GetNeededWidths(multimap *widths) { + for (map::iterator param = numericDynamicParameters.begin(); param !=numericDynamicParameters.end(); param++) { + string val = param->second; + size_t posStart = val.find("{width("); + while (posStart != string::npos) { + size_t posEnd = val.find(")", posStart+1); + if (posEnd != string::npos) { + string label = val.substr(posStart+7, posEnd - posStart - 7); + widths->insert(pair(param->first, label)); + val = val.replace(posStart, posEnd - posStart, ""); + } else { + break; + } + posStart = val.find("{width("); + } + } +} + +void cTemplateFunction::GetNeededHeights(multimap *heights) { + for (map::iterator param = numericDynamicParameters.begin(); param !=numericDynamicParameters.end(); param++) { + string val = param->second; + size_t posStart = val.find("{height("); + while (posStart != string::npos) { + size_t posEnd = val.find(")", posStart + 1); + if (posEnd != string::npos) { + string label = val.substr(posStart + 8, posEnd - posStart - 8); + heights->insert(pair(param->first, label)); + val = val.replace(posStart, posEnd - posStart, ""); + } else { + break; + } + posStart = val.find("{height("); + } + } +} + +void cTemplateFunction::GetNeededPosX(multimap *posXs) { + for (map::iterator param = numericDynamicParameters.begin(); param !=numericDynamicParameters.end(); param++) { + string val = param->second; + size_t posStart = val.find("{posx("); + while (posStart != string::npos) { + size_t posEnd = val.find(")", posStart+1); + if (posEnd != string::npos) { + string label = val.substr(posStart+6, posEnd - posStart - 6); + posXs->insert(pair(param->first, label)); + val = val.replace(posStart, posEnd - posStart, ""); + } else { + break; + } + posStart = val.find("{posx("); + } + } +} + +void cTemplateFunction::GetNeededPosY(multimap *posYs) { + for (map::iterator param = numericDynamicParameters.begin(); param !=numericDynamicParameters.end(); param++) { + string val = param->second; + size_t posStart = val.find("{posy("); + while (posStart != string::npos) { + size_t posEnd = val.find(")", posStart+1); + if (posEnd != string::npos) { + string label = val.substr(posStart+6, posEnd - posStart - 6); + posYs->insert(pair(param->first, label)); + val = val.replace(posStart, posEnd - posStart, ""); + } else { + break; + } + posStart = val.find("{posy("); + } + } +} + +void cTemplateFunction::SetWidth(eParamType type, string label, int funcWidth) { + updated = false; + map< eParamType, string >::iterator hit = numericDynamicParameters.find(type); + if (hit == numericDynamicParameters.end()) + return; + stringstream needle; + needle << "{width(" << label << ")}"; + size_t posFound = (hit->second).find(needle.str()); + if (posFound == string::npos) + return; + stringstream repl; + repl << funcWidth; + string parsedVal = (hit->second).replace(posFound, needle.str().size(), repl.str()); + + cNumericParameter param(parsedVal); + param.SetAreaSize(containerWidth, containerHeight); + param.SetGlobals(globals); + int val = param.Parse(parsedVal); + if (param.Valid()) { + updated = true; + numericParameters.insert(pair(type, val)); + } else { + numericDynamicParameters.erase(type); + numericDynamicParameters.insert(pair(type, parsedVal)); + } +} + +void cTemplateFunction::SetHeight(eParamType type, string label, int funcHeight) { + updated = false; + map< eParamType, string >::iterator hit = numericDynamicParameters.find(type); + if (hit == numericDynamicParameters.end()) + return; + stringstream needle; + needle << "{height(" << label << ")}"; + size_t posFound = (hit->second).find(needle.str()); + if (posFound == string::npos) + return; + stringstream repl; + repl << funcHeight; + string parsedVal = (hit->second).replace(posFound, needle.str().size(), repl.str()); + + cNumericParameter param(parsedVal); + param.SetAreaSize(containerWidth, containerHeight); + param.SetGlobals(globals); + int val = param.Parse(parsedVal); + if (param.Valid()) { + updated = true; + numericParameters.insert(pair(type, val)); + } else { + numericDynamicParameters.erase(type); + numericDynamicParameters.insert(pair(type, parsedVal)); + } +} + +void cTemplateFunction::SetX(eParamType type, string label, int funcX) { + updated = false; + map< eParamType, string >::iterator hit = numericDynamicParameters.find(type); + if (hit == numericDynamicParameters.end()) + return; + stringstream needle; + needle << "{posx(" << label << ")}"; + size_t posFound = (hit->second).find(needle.str()); + if (posFound == string::npos) + return; + stringstream repl; + repl << funcX; + string parsedVal = (hit->second).replace(posFound, needle.str().size(), repl.str()); + + cNumericParameter param(parsedVal); + param.SetAreaSize(containerWidth, containerHeight); + param.SetGlobals(globals); + int val = param.Parse(parsedVal); + if (param.Valid()) { + updated = true; + numericParameters.insert(pair(type, val)); + } else { + numericDynamicParameters.erase(type); + numericDynamicParameters.insert(pair(type, parsedVal)); + } +} + +void cTemplateFunction::SetY(eParamType type, string label, int funcY) { + updated = false; + map< eParamType, string >::iterator hit = numericDynamicParameters.find(type); + if (hit == numericDynamicParameters.end()) + return; + stringstream needle; + needle << "{posy(" << label << ")}"; + size_t posFound = (hit->second).find(needle.str()); + if (posFound == string::npos) + return; + stringstream repl; + repl << funcY; + string parsedVal = (hit->second).replace(posFound, needle.str().size(), repl.str()); + + cNumericParameter param(parsedVal); + param.SetAreaSize(containerWidth, containerHeight); + param.SetGlobals(globals); + int val = param.Parse(parsedVal); + if (param.Valid()) { + updated = true; + numericParameters.insert(pair(type, val)); + } else { + numericDynamicParameters.erase(type); + numericDynamicParameters.insert(pair(type, parsedVal)); + } +} + +bool cTemplateFunction::DoExecute(void) { + if (!condParam) + return true; + return condParam->IsTrue(); +} + +/******************************************************************* +* Private Functions +*******************************************************************/ + +bool cTemplateFunction::SetCondition(string cond) { + if (condParam) + delete condParam; + condParam = new cConditionalParameter(globals, cond); + condParam->Tokenize(); + return true; +} + + +bool cTemplateFunction::SetNumericParameter(eParamType type, string value) { + if (config.replaceDecPoint) { + if (value.find_first_of('.') != string::npos) { + std::replace( value.begin(), value.end(), '.', config.decPoint); + } + } + + cNumericParameter param(value); + param.SetAreaSize(containerWidth, containerHeight); + param.SetLoopContainer(columnWidth, rowHeight); + param.SetGlobals(globals); + switch (type) { + case ptX: + case ptWidth: + case ptMenuItemWidth: + case ptScaleTvX: + case ptScaleTvWidth: + param.SetHorizontal(); + break; + case ptY: + case ptHeight: + case ptFontSize: + case ptScaleTvY: + case ptScaleTvHeight: + param.SetVertical(); + break; + case ptLayer: + param.SetDefault(1); + break; + default: + break; + } + string parsedValue = ""; + int val = param.Parse(parsedValue); + if (param.Valid()) { + if (this->type < ftLoop && type == ptX) { + val += containerX; + } + if (this->type < ftLoop && type == ptY) { + val += containerY; + } + numericParameters.insert(pair(type, val)); + } else { + numericDynamicParameters.insert(pair(type, parsedValue)); + } + return param.Valid(); +} + +bool cTemplateFunction::SetAlign(eParamType type, string value) { + eAlign align = alLeft; + bool ok = true; + if (!value.compare("center")) { + align = alCenter; + } else if (!value.compare("right")) { + align = alRight; + } else if (!value.compare("top")) { + align = alTop; + } else if (!value.compare("bottom")) { + align = alBottom; + } else if (!value.compare("left")) { + align = alLeft; + } else { + ok = false; + } + numericParameters.insert(pair(type, align)); + return ok; +} + +bool cTemplateFunction::SetFont(eParamType type, string value) { + //check if token + if ((value.find("{") == 0) && (value.find("}") == (value.size()-1))) { + value = value.substr(1, value.size()-2); + map::iterator hit = globals->fonts.find(value); + if (hit != globals->fonts.end()) { + fontName = hit->second; + } else { + map::iterator def = globals->fonts.find("vdrOsd"); + if (def == globals->fonts.end()) + return false; + fontName = def->second; + } + } else { + //if no token, directly use input + fontName = value; + } + return true; +} + +bool cTemplateFunction::SetImageType(eParamType type, string value) { + eImageType imgType = itImage; + bool ok = true; + if (!value.compare("channellogo")) { + imgType = itChannelLogo; + } else if (!value.compare("seplogo")) { + imgType = itSepLogo; + } else if (!value.compare("skinpart")) { + imgType = itSkinPart; + } else if (!value.compare("menuicon")) { + imgType = itMenuIcon; + } else if (!value.compare("icon")) { + imgType = itIcon; + } else if (!value.compare("image")) { + imgType = itImage; + } else { + ok = false; + } + numericParameters.insert(pair(ptImageType, imgType)); + return ok; +} + + +bool cTemplateFunction::SetColor(eParamType type, string value) { + if (globals) { + for (map::iterator col = globals->colors.begin(); col != globals->colors.end(); col++) { + stringstream sColName; + sColName << "{" << col->first << "}"; + string colName = sColName.str(); + if (!colName.compare(value)) { + tColor colVal = col->second; + colorParameters.insert(pair(type, colVal)); + return true; + } + } + } + if (value.size() != 8) + return false; + std::stringstream str; + str << value; + tColor colVal; + str >> std::hex >> colVal; + colorParameters.insert(pair(type, colVal)); + return true; +} + +bool cTemplateFunction::SetTextTokens(string value) { + textTokens.clear(); + //first replace globals + for (map::iterator globStr = globals->stringVars.begin(); globStr != globals->stringVars.end(); globStr++) { + stringstream sToken; + sToken << "{" << globStr->first << "}"; + string token = sToken.str(); + size_t foundToken = value.find(token); + if (foundToken != string::npos) { + value = value.replace(foundToken, token.size(), globStr->second); + } + } + //now tokenize + bool tokenFound = true; + while (tokenFound) { + //search for conditional token or normal token + size_t tokenStart = value.find_first_of('{'); + size_t conditionStart = value.find_first_of('|'); + if (tokenStart == string::npos && conditionStart == string::npos) { + if (value.size() > 0) { + cTextToken token; + token.type = ttConstString; + token.value = value; + textTokens.push_back(token); + } + tokenFound = false; + continue; + } else if (tokenStart != string::npos && conditionStart == string::npos) { + size_t tokenEnd = value.find_first_of('}'); + ParseTextToken(value, tokenStart, tokenEnd); + } else if (tokenStart != string::npos && conditionStart != string::npos) { + if (tokenStart < conditionStart) { + size_t tokenEnd = value.find_first_of('}'); + ParseTextToken(value, tokenStart, tokenEnd); + } else { + size_t conditionEnd = value.find_first_of('|', conditionStart+1); + ParseConditionalTextToken(value, conditionStart, conditionEnd); + } + } + } + return true; +} + +void cTemplateFunction::ParseTextToken(string &value, size_t start, size_t end) { + cTextToken token; + if (start > 0) { + string constString = value.substr(0, start); + value = value.replace(0, start, ""); + token.type = ttConstString; + token.value = constString; + textTokens.push_back(token); + } else { + string tokenName = value.substr(1, end - start - 1); + value = value.replace(0, end - start + 1, ""); + token.type = ttToken; + token.value = tokenName; + textTokens.push_back(token); + } +} + +void cTemplateFunction::ParseConditionalTextToken(string &value, size_t start, size_t end) { + cTextToken token; + if (start > 0) { + string constString = value.substr(0, start); + value = value.replace(0, start, ""); + token.type = ttConstString; + token.value = constString; + textTokens.push_back(token); + } else { + string condToken = value.substr(start + 1, end - start - 1); + value = value.replace(0, end - start + 1, ""); + size_t tokenStart = condToken.find_first_of('{'); + size_t tokenEnd = condToken.find_first_of('}'); + vector subTokens; + if (tokenStart > 0) { + cTextToken subToken; + string constString = condToken.substr(0, tokenStart); + condToken = condToken.replace(0, tokenStart, ""); + subToken.type = ttConstString; + subToken.value = constString; + subTokens.push_back(subToken); + } + string tokenName = condToken.substr(1, tokenEnd - tokenStart - 1); + condToken = condToken.replace(0, tokenEnd - tokenStart + 1, ""); + + cTextToken subToken2; + subToken2.type = ttToken; + subToken2.value = tokenName; + subTokens.push_back(subToken2); + + if (condToken.size() > 0) { + cTextToken subToken3; + subToken3.type = ttConstString; + subToken3.value = condToken; + subTokens.push_back(subToken3); + } + + token.type = ttConditionalToken; + token.value = tokenName; + token.subTokens = subTokens; + textTokens.push_back(token); + } + +} + +bool cTemplateFunction::SetScrollMode(string value) { + eScrollMode mode = smNone; + bool ok = true; + if (!value.compare("forthandback")) + mode = smForthAndBack; + else if (!value.compare("carriagereturn")) + mode = smCarriageReturn; + else + ok = false; + numericParameters.insert(pair(ptScrollMode, mode)); + return ok; +} + +bool cTemplateFunction::SetScrollSpeed(string value) { + eScrollSpeed speed = ssMedium; + bool ok = true; + if (!value.compare("slow")) + speed = ssSlow; + else if (!value.compare("fast")) + speed = ssFast; + else if (!value.compare("medium")) + speed = ssMedium; + else + ok = false; + numericParameters.insert(pair(ptScrollSpeed, speed)); + return ok; + +} + +bool cTemplateFunction::SetOrientation(string value) { + eOrientation orientation = orNone; + bool ok = true; + if (!value.compare("horizontal")) + orientation = orHorizontal; + else if (!value.compare("vertical")) + orientation = orVertical; + else if (!value.compare("absolute")) + orientation = orAbsolute; + else + ok = false; + numericParameters.insert(pair(ptOrientation, orientation)); + return ok; +} + +bool cTemplateFunction::SetFloating(string value) { + eFloatType floatType = flNone; + bool ok = true; + if (!value.compare("topleft")) + floatType = flTopLeft; + else if (!value.compare("topright")) + floatType = flTopRight; + else + ok = false; + numericParameters.insert(pair(ptFloat, floatType)); + return ok; +} + +bool cTemplateFunction::SetOverflow(string value) { + eOverflowType overflowType = otNone; + bool ok = true; + if (!value.compare("linewrap")) + overflowType = otWrap; + else if (!value.compare("cut")) + overflowType = otCut; + else + ok = false; + numericParameters.insert(pair(ptOverflow, overflowType)); + return ok; +} + +void cTemplateFunction::ParseStringParameters(void) { + //first replace stringtokens in Text (drawText) + stringstream text; + for (vector::iterator it = textTokens.begin(); it !=textTokens.end(); it++) { + updated = true; + if ((*it).type == ttConstString) { + text << (*it).value; + } else if ((*it).type == ttToken) { + bool found = false; + string tokenName = (*it).value; + if (stringTokens) { + map < string, string >::iterator hit = stringTokens->find(tokenName); + if (hit != stringTokens->end()) { + text << hit->second; + found = true; + } + } + if (!found && intTokens) { + map < string, int >::iterator hitInt = intTokens->find(tokenName); + if (hitInt != intTokens->end()) { + text << hitInt->second; + found = true; + } + } + if (!found) { + text << "{" << tokenName << "}"; + } + } else if ((*it).type == ttConditionalToken) { + bool found = false; + string tokenName = (*it).value; + if (stringTokens) { + map < string, string >::iterator hit = stringTokens->find(tokenName); + if (hit != stringTokens->end()) { + string replaceText = hit->second; + if (replaceText.size() > 0) { + for (vector::iterator it2 = (*it).subTokens.begin(); it2 != (*it).subTokens.end(); it2++) { + if ((*it2).type == ttConstString) { + text << (*it2).value; + } else { + text << replaceText; + } + } + } + found = true; + } + } + if (!found && intTokens) { + map < string, int >::iterator hitInt = intTokens->find(tokenName); + if (hitInt != intTokens->end()) { + int intVal = hitInt->second; + if (intVal > 0) { + for (vector::iterator it2 = (*it).subTokens.begin(); it2 != (*it).subTokens.end(); it2++) { + if ((*it2).type == ttConstString) { + text << (*it2).value; + } else { + text << intVal; + } + } + } + found = true; + } + } + } + } + parsedText = text.str(); + + //now check further possible string variables + string path = GetParameter(ptPath); + if (stringTokens && path.size() > 0 && path.find("{") != string::npos) { + for (map < string, string >::iterator it = stringTokens->begin(); it != stringTokens->end(); it++) { + size_t found = path.find(it->first); + if (found != string::npos) { + updated = true; + imgPath = path; + if (found > 0 && ((it->first).size() + 2 <= imgPath.size())) + imgPath.replace(found-1, (it->first).size() + 2, it->second); + break; + } + } + } +} + +void cTemplateFunction::ParseNumericalParameters(void) { + parsedCompletely = true; + for (map::iterator param = numericDynamicParameters.begin(); param !=numericDynamicParameters.end(); param++) { + string val = param->second; + for (map::iterator tok = intTokens->begin(); tok != intTokens->end(); tok++) { + stringstream sToken; + sToken << "{" << tok->first << "}"; + string token = sToken.str(); + size_t foundToken = val.find(token); + //replace token as often as it appears + while (foundToken != string::npos) { + stringstream sVal; + sVal << tok->second; + val = val.replace(foundToken, token.size(), sVal.str()); + foundToken = val.find(token); + } + } + cNumericParameter p(val); + string parsedVal = ""; + int newVal = p.Parse(parsedVal); + if (p.Valid()) { + updated = true; + numericParameters.insert(pair(param->first, newVal)); + } else { + parsedCompletely = false; + } + } +} + +void cTemplateFunction::CalculateAlign(int elementWidth, int elementHeight) { + int align = GetNumericParameter(ptAlign); + //if element is used in a loop, use loop box width + int boxWidth = (columnWidth > 0) ? columnWidth : containerWidth; + int boxHeight = (rowHeight > 0) ? rowHeight : containerHeight; + if (align == alCenter) { + int xNew = (boxWidth - elementWidth) / 2; + numericParameters.erase(ptX); + numericParameters.insert(pair(ptX, xNew)); + } else if (align == alRight) { + int xNew = boxWidth - elementWidth; + numericParameters.erase(ptX); + numericParameters.insert(pair(ptX, xNew)); + } + + int vAlign = GetNumericParameter(ptValign); + if (vAlign == alCenter) { + int yNew = (boxHeight - elementHeight) / 2; + numericParameters.erase(ptY); + numericParameters.insert(pair(ptY, yNew)); + } else if (vAlign == alBottom) { + int yNew = boxHeight - elementHeight; + numericParameters.erase(ptY); + numericParameters.insert(pair(ptY, yNew)); + } +} + +int cTemplateFunction::CalculateTextBoxHeight(void) { + int width = GetNumericParameter(ptWidth); + string fontName = GetFontName(); + int fontSize = GetNumericParameter(ptFontSize); + string text = GetText(false); + const cFont *font = fontManager->Font(fontName, fontSize); + if (!font) + return 0; + + int fontHeight = fontManager->Height(fontName, fontSize); + int floatType = GetNumericParameter(ptFloat); + + if (floatType == flNone) { + cTextWrapper wrapper; + wrapper.Set(text.c_str(), font, width); + int lines = wrapper.Lines(); + return (lines * fontHeight); + } + + int floatWidth = GetNumericParameter(ptFloatWidth); + int floatHeight = GetNumericParameter(ptFloatHeight); + + cTextWrapper wTextTall; + cTextWrapper wTextFull; + + int linesNarrow = floatHeight / fontHeight; + int widthNarrow = width - floatWidth; + int linesDrawn = 0; + int curY = 0; + bool drawNarrow = true; + + splitstring s(text.c_str()); + vector flds = s.split('\n', 1); + + if (flds.size() < 1) + return 0; + + stringstream sstrTextTall; + stringstream sstrTextFull; + + for (int i=0; iDebug(); + } + esyslog("skindesigner: --- Native Parameters:"); + for (map::iterator it = nativeParameters.begin(); it != nativeParameters.end(); it++) { + esyslog("skindesigner: \"%s\" = \"%s\"", GetParamName(it->first).c_str(), (it->second).c_str()); + } + if (numericParameters.size() > 0) { + esyslog("skindesigner: --- Integer Parameters: "); + for (map::iterator it = numericParameters.begin(); it != numericParameters.end(); it++) { + esyslog("skindesigner: %s = %d", GetParamName(it->first).c_str(), it->second); + } + } + if (numericDynamicParameters.size() > 0) { + esyslog("skindesigner: --- Dynamic Integer Parameters: "); + for (map::iterator it = numericDynamicParameters.begin(); it != numericDynamicParameters.end(); it++) { + esyslog("skindesigner: %s = %s", GetParamName(it->first).c_str(), (it->second).c_str()); + } + } + if (colorParameters.size() > 0) { + esyslog("skindesigner: --- Color Parameters:"); + for (map::iterator it = colorParameters.begin(); it != colorParameters.end(); it++) { + esyslog("skindesigner: %s = %x", GetParamName(it->first).c_str(), it->second); + } + } + if (textTokens.size() > 0) { + esyslog("skindesigner: --- Text Tokens:"); + int i=0; + for (vector::iterator it = textTokens.begin(); it != textTokens.end(); it++) { + eTextTokenType tokenType = (*it).type; + string tokType = ""; + if (tokenType == ttConstString) + tokType = "Const: "; + else if (tokenType == ttToken) + tokType = "Token: "; + else if (tokenType == ttConditionalToken) + tokType = "Conditional Token: "; + esyslog("skindesigner: %s %d = \"%s\"", tokType.c_str(), i++, (*it).value.c_str()); + if (tokenType == ttConditionalToken) { + for (vector::iterator it2 = (*it).subTokens.begin(); it2 != (*it).subTokens.end(); it2++) { + eTextTokenType tokenTypeCond = (*it2).type; + string tokTypeCond = ""; + if (tokenTypeCond == ttConstString) + tokTypeCond = "Const: "; + else if (tokenTypeCond == ttToken) + tokTypeCond = "Token: "; + esyslog("skindesigner: %s \"%s\"", tokTypeCond.c_str(), (*it2).value.c_str()); + } + } + } + } + if (fontName.size() > 0) { + esyslog("skindesigner: --- Font Name: \"%s\"", fontName.c_str()); + } + if (parsedText.size() > 0) { + esyslog("skindesigner: --- Parsed Text: \"%s\"", parsedText.c_str()); + } + if (type == ftDrawText) { + esyslog("skindesigner: --- Cutted Text: \"%s\"", cuttedText.c_str()); + esyslog("skindesigner: --- Parsed Text Width: %d", parsedTextWidth); + esyslog("skindesigner: --- Already Cutted: %s", alreadyCutted ? "true" : "false"); + } + if (imgPath.size() > 0) { + esyslog("skindesigner: --- Image Path: \"%s\"", imgPath.c_str()); + } +} diff --git a/libtemplate/templatefunction.h b/libtemplate/templatefunction.h new file mode 100644 index 0000000..9a784c5 --- /dev/null +++ b/libtemplate/templatefunction.h @@ -0,0 +1,211 @@ +#ifndef __TEMPLATEFUNCTION_H +#define __TEMPLATEFUNCTION_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "globals.h" +#include "parameter.h" + +using namespace std; + +// --- cTemplateFunction ------------------------------------------------------------- + +enum eFuncType { + ftOsd, + ftView, + ftViewElement, + ftViewList, + ftPixmap, + ftPixmapScroll, + ftLoop, + ftFill, + ftDrawText, + ftDrawTextBox, + ftDrawImage, + ftDrawRectangle, + ftDrawEllipse, + ftNone +}; + +enum eParamType { + ptCond, + ptName, + ptX, + ptY, + ptWidth, + ptHeight, + ptMenuItemWidth, + ptFadeTime, + ptDelay, + ptImageType, + ptPath, + ptColor, + ptFont, + ptFontSize, + ptText, + ptLayer, + ptTransparency, + ptQuadrant, + ptAlign, + ptValign, + ptScrollMode, + ptScrollSpeed, + ptOrientation, + ptNumElements, + ptScrollElement, + ptScrollHeight, + ptFloat, + ptFloatWidth, + ptFloatHeight, + ptMaxLines, + ptColumnWidth, + ptRowHeight, + ptOverflow, + ptScaleTvX, + ptScaleTvY, + ptScaleTvWidth, + ptScaleTvHeight, + ptCache, + ptDeterminateFont, + ptNone +}; + +enum eImageType { + itChannelLogo, + itSepLogo, + itSkinPart, + itMenuIcon, + itIcon, + itImage +}; + +enum eFloatType { + flNone, + flTopLeft, + flTopRight +}; + +enum eOverflowType { + otNone, + otWrap, + otCut +}; + +class cTemplateFunction { +protected: + eFuncType type; + bool debug; + int containerX; //X of parent container + int containerY; //Y of parent container + int containerWidth; //width of parent container + int containerHeight; //height of parent container + int columnWidth; //if func is executed in a loop, width of loop column + int rowHeight; //if func is executed in a loop, height of loop row + cGlobals *globals; //globals + map< eParamType, string > nativeParameters; //native parameters directly from xml + map< eParamType, int > numericParameters; //sucessfully parsed numeric parameters + map< eParamType, string > numericDynamicParameters; //numeric parameters with dynamic tokens + bool parsedCompletely; + bool updated; + map< eParamType, tColor > colorParameters; + cConditionalParameter *condParam; + //drawimage parameters + string imgPath; + //drawtext parameters + string fontName; + vector textTokens; + string parsedText; + int parsedTextWidth; + string cuttedText; + bool alreadyCutted; + //drawtextbox parameters + int textboxHeight; + //dynamic tokens + map < string, string > *stringTokens; + map < string, int > *intTokens; + //private functions + bool SetCondition(string cond); + bool SetNumericParameter(eParamType type, string value); + bool SetAlign(eParamType type, string value); + bool SetFont(eParamType type, string value); + bool SetImageType(eParamType type, string value); + bool SetColor(eParamType type, string value); + bool SetTextTokens(string value); + void ParseTextToken(string &value, size_t start, size_t end); + void ParseConditionalTextToken(string &value, size_t start, size_t end); + bool SetScrollMode(string value); + bool SetScrollSpeed(string value); + bool SetOrientation(string value); + bool SetFloating(string value); + bool SetOverflow(string value); + void ParseStringParameters(void); + void ParseNumericalParameters(void); + void CalculateAlign(int elementWidth, int elementHeight); + int CalculateTextBoxHeight(void); +public: + cTemplateFunction(eFuncType type); + virtual ~cTemplateFunction(void); + //Setter Functions + void SetParameters(vector > params); + void SetParameter(eParamType type, string value); + void SetContainer(int x, int y, int w, int h); + void SetLoopContainer(int columnWidth, int rowHeight); + void SetWidthManually(string width); + void SetHeightManually(string height); + void SetXManually(int newX); + void SetYManually(int newY); + void SetMaxTextWidth(int maxWidth); + void SetTextboxHeight(int boxHeight); + void SetGlobals(cGlobals *globals) { this->globals = globals; }; + void SetTranslatedText(string translation); + //PreCache Parameters + bool CalculateParameters(void); + void CompleteParameters(void); + //Set and Unset Dynamic Tokens from view + void SetStringTokens(map < string, string > *tok) { stringTokens = tok; }; + void SetIntTokens(map < string, int > *tok) { intTokens = tok; }; + void UnsetIntTokens(void) { intTokens = NULL; }; + void UnsetStringTokens(void) { stringTokens = NULL; }; + //Clear dynamically parameters + void ClearDynamicParameters(void); + //Parse parameters with dynamically set Tokens + bool ParseParameters(void); + //Getter Functions + eFuncType GetType(void) { return type; }; + bool DoDebug(void) { return debug; }; + string GetParameter(eParamType type); + int GetNumericParameter(eParamType type); + string GetText(bool cut = true); + string GetImagePath(void) { return imgPath; }; + tColor GetColorParameter(eParamType type); + string GetFontName(void) { return fontName; }; + string GetFuncName(void); + string GetParamName(eParamType pt); + //Dynamic width or height parameter + int GetWidth(bool cutted = true); + int GetHeight(void); + void GetNeededWidths(multimap *widths); + void GetNeededHeights(multimap *heights); + void GetNeededPosX(multimap *posXs); + void GetNeededPosY(multimap *posYs); + void SetWidth(eParamType type, string label, int funcWidth); + void SetHeight(eParamType type, string label, int funcHeight); + void SetX(eParamType type, string label, int funcX); + void SetY(eParamType type, string label, int funcY); + //Status Functions + bool ParsedCompletely(void) { return parsedCompletely; }; + bool DoExecute(void); + bool Updated(void) { return updated; }; + //Debug + void Debug(void); +}; + +#endif //__TEMPLATEFUNCTION_H \ No newline at end of file diff --git a/libtemplate/templateloopfunction.c b/libtemplate/templateloopfunction.c new file mode 100644 index 0000000..b0030d3 --- /dev/null +++ b/libtemplate/templateloopfunction.c @@ -0,0 +1,208 @@ +#include "templateloopfunction.h" +#include "../libcore/helpers.h" + +using namespace std; + +// --- cTemplateFunction ------------------------------------------------------------- + +cTemplateLoopFunction::cTemplateLoopFunction(void) : cTemplateFunction(ftLoop) { +} + +cTemplateLoopFunction::~cTemplateLoopFunction(void) { +} + +void cTemplateLoopFunction::InitIterator(void) { + funcIt = functions.begin(); +} + +void cTemplateLoopFunction::AddFunction(string name, vector > ¶ms) { + eFuncType type = ftNone; + + if (!name.compare("drawtext")) { + type = ftDrawText; + } else if (!name.compare("drawtextbox")) { + type = ftDrawTextBox; + } else if (!name.compare("drawimage")) { + type = ftDrawImage; + } else if (!name.compare("drawrectangle")) { + type = ftDrawRectangle; + } else if (!name.compare("drawellipse")) { + type = ftDrawEllipse; + } + + if (type == ftNone) { + return; + } + + cTemplateFunction *f = new cTemplateFunction(type); + f->SetParameters(params); + functions.push_back(f); +} + +void cTemplateLoopFunction::CalculateLoopFuncParameters(void) { + int columnWidth = GetNumericParameter(ptColumnWidth); + int rowHeight = GetNumericParameter(ptRowHeight); + for (vector::iterator func = functions.begin(); func != functions.end(); func++) { + (*func)->SetGlobals(globals); + (*func)->SetContainer(0, 0, containerWidth, containerHeight); + (*func)->SetLoopContainer(columnWidth, rowHeight); + (*func)->CalculateParameters(); + (*func)->CompleteParameters(); + } +} + +cTemplateFunction *cTemplateLoopFunction::GetNextFunction(void) { + if (funcIt == functions.end()) + return NULL; + cTemplateFunction *func = *funcIt; + funcIt++; + return func; +} + +void cTemplateLoopFunction::ClearDynamicParameters(void) { + InitIterator(); + cTemplateFunction *func = NULL; + while(func = GetNextFunction()) { + func->ClearDynamicParameters(); + } +} + +void cTemplateLoopFunction::ParseDynamicParameters(map *tokens) { + if (!tokens) + return; + InitIterator(); + cTemplateFunction *func = NULL; + + map intTokens; + for (map ::iterator it = tokens->begin(); it != tokens->end(); it++) { + if (isNumber(it->second)) + intTokens.insert(pair(it->first, atoi((it->second).c_str()))); + } + + bool completelyParsed = true; + while(func = GetNextFunction()) { + func->SetStringTokens(tokens); + func->SetIntTokens(&intTokens); + bool funcCompletelyParsed = func->ParseParameters(); + if (!funcCompletelyParsed) + completelyParsed = false; + if (func->Updated()) + func->CompleteParameters(); + func->UnsetStringTokens(); + func->UnsetIntTokens(); + } + if (completelyParsed) { + return; + } + + ReplaceWidthFunctions(); + ReplaceHeightFunctions(); +} + +int cTemplateLoopFunction::GetLoopElementsWidth(void) { + int cW = GetNumericParameter(ptColumnWidth); + if (cW > 0) { + return cW; + } + InitIterator(); + cTemplateFunction *func = NULL; + int maxWidth = 1; + while(func = GetNextFunction()) { + int funcWidth = func->GetWidth(true); + if (funcWidth > maxWidth) + maxWidth = funcWidth; + } + return maxWidth; +} + +int cTemplateLoopFunction::GetLoopElementsHeight(void) { + int rH = GetNumericParameter(ptRowHeight); + if (rH > 0) + return rH; + InitIterator(); + cTemplateFunction *func = NULL; + int maxHeight = 1; + while(func = GetNextFunction()) { + int funcY = func->GetNumericParameter(ptY); + int funcHeight = func->GetHeight(); + int totalHeight = funcY + funcHeight; + if (totalHeight > maxHeight) + maxHeight = totalHeight; + } + return maxHeight; +} + +void cTemplateLoopFunction::ReplaceWidthFunctions(void) { + InitIterator(); + cTemplateFunction *func = NULL; + while(func = GetNextFunction()) { + if (func->ParsedCompletely()) { + continue; + } + multimap widths; + func->GetNeededWidths(&widths); + for (map::iterator names = widths.begin(); names !=widths.end(); names++) { + eParamType type = names->first; + string label = names->second; + int funcWidth = 0; + for (vector::iterator it = functions.begin(); it != functions.end(); it++) { + cTemplateFunction *myFunc = *it; + string myFuncName = myFunc->GetParameter(ptName); + if (!myFuncName.compare(label)) { + funcWidth = myFunc->GetWidth(); + func->SetWidth(type, label, funcWidth); + if (func->Updated()) { + func->CompleteParameters(); + } + } + } + } + } +} + +void cTemplateLoopFunction::ReplaceHeightFunctions(void) { + InitIterator(); + cTemplateFunction *func = NULL; + while(func = GetNextFunction()) { + if (func->ParsedCompletely()) { + continue; + } + multimap heights; + func->GetNeededHeights(&heights); + for (map::iterator names = heights.begin(); names !=heights.end(); names++) { + eParamType type = names->first; + string label = names->second; + int funcHeight = 0; + for (vector::iterator it = functions.begin(); it != functions.end(); it++) { + cTemplateFunction *myFunc = *it; + string myFuncName = myFunc->GetParameter(ptName); + if (!myFuncName.compare(label)) { + funcHeight = myFunc->GetHeight(); + func->SetHeight(type, label, funcHeight); + if (func->Updated()) { + func->CompleteParameters(); + } + } + } + } + } +} + +bool cTemplateLoopFunction::Ready(void) { + bool isReady = true; + map< eParamType, string >::iterator hit = numericDynamicParameters.find(ptColumnWidth); + if (hit != numericDynamicParameters.end()) + isReady = false; + hit = numericDynamicParameters.find(ptRowHeight); + if (hit != numericDynamicParameters.end()) + isReady = false; + return isReady; +} + +void cTemplateLoopFunction::Debug(void) { + cTemplateFunction::Debug(); + esyslog("skindesigner: functions to be looped:"); + for (vector::iterator func = functions.begin(); func != functions.end(); func++) { + (*func)->Debug(); + } +} \ No newline at end of file diff --git a/libtemplate/templateloopfunction.h b/libtemplate/templateloopfunction.h new file mode 100644 index 0000000..5335279 --- /dev/null +++ b/libtemplate/templateloopfunction.h @@ -0,0 +1,33 @@ +#ifndef __TEMPLATELOOPFUNCTION_H +#define __TEMPLATELOOPFUNCTION_H + +#include "templatefunction.h" + +using namespace std; + +// --- cTemplateLoopFunction ------------------------------------------------------------- + +class cTemplateLoopFunction : public cTemplateFunction { +private: + vector functions; + vector::iterator funcIt; + void ReplaceWidthFunctions(void); + void ReplaceHeightFunctions(void); +public: + cTemplateLoopFunction(void); + virtual ~cTemplateLoopFunction(void); + void AddFunction(string name, vector > ¶ms); + void CalculateLoopFuncParameters(void); + void InitIterator(void); + cTemplateFunction *GetNextFunction(void); + void ClearDynamicParameters(void); + void ParseDynamicParameters(map *tokens); + int GetLoopElementsWidth(void); + int GetLoopElementsHeight(void); + int GetContainerWidth(void) { return containerWidth; }; + int GetContainerHeight(void) { return containerHeight; }; + bool Ready(void); + void Debug(void); +}; + +#endif //__TEMPLATELOOPFUNCTION_H diff --git a/libtemplate/templatepixmap.c b/libtemplate/templatepixmap.c new file mode 100644 index 0000000..8aaa4f3 --- /dev/null +++ b/libtemplate/templatepixmap.c @@ -0,0 +1,473 @@ +#include "templatepixmap.h" + +using namespace std; + +// --- cTemplatePixmap ------------------------------------------------------------- + +cTemplatePixmap::cTemplatePixmap(void) { + parameters = NULL; + containerX = 0; + containerY = 0; + containerWidth = 0; + containerHeight = 0; + globals = NULL; + scrolling = false; +} + +cTemplatePixmap::~cTemplatePixmap() { + for (vector::iterator it = functions.begin(); it != functions.end(); it++) { + delete (*it); + } + if (parameters) + delete parameters; +} + +void cTemplatePixmap::SetParameters(vector > ¶ms) { + parameters = new cTemplateFunction(ftPixmap); + parameters->SetGlobals(globals); + parameters->SetParameters(params); +} + +void cTemplatePixmap::SetContainer(int x, int y, int w, int h) { + containerX = x; + containerY = y; + containerWidth = w; + containerHeight = h; +} + +void cTemplatePixmap::SetWidth(int width) { + cString pWidth = cString::sprintf("%d", width); + parameters->SetWidthManually(*pWidth); +} + +void cTemplatePixmap::SetHeight(int height) { + cString pHeight = cString::sprintf("%d", height); + parameters->SetHeightManually(*pHeight); +} + +void cTemplatePixmap::SetX(int x) { + parameters->SetXManually(x); +} + +void cTemplatePixmap::SetY(int y) { + parameters->SetYManually(y); +} + +void cTemplatePixmap::ClearDynamicParameters(void) { + parameters->ClearDynamicParameters(); +} + +void cTemplatePixmap::ParseDynamicParameters(map *intTokens, bool initFuncs) { + parameters->ClearDynamicParameters(); + parameters->SetIntTokens(intTokens); + parameters->ParseParameters(); + parameters->UnsetIntTokens(); + + if (!DoExecute()) { + parameters->ClearDynamicParameters(); + return; + } + + if (!initFuncs || !Ready()) + return; + + int x = parameters->GetNumericParameter(ptX); + int y = parameters->GetNumericParameter(ptY); + int width = parameters->GetNumericParameter(ptWidth); + int height = parameters->GetNumericParameter(ptHeight); + + for (vector::iterator func = functions.begin(); func != functions.end(); func++) { + (*func)->SetContainer(x, y, width, height); + (*func)->CalculateParameters(); + (*func)->CompleteParameters(); + if ((*func)->GetType() == ftLoop) { + cTemplateLoopFunction *loopFunc = dynamic_cast(*func); + if (!loopFunc->Ready()) { + loopFunc->SetIntTokens(intTokens); + loopFunc->ParseParameters(); + loopFunc->UnsetIntTokens(); + } + loopFunc->CalculateLoopFuncParameters(); + } + } +} + +void cTemplatePixmap::AddFunction(string name, vector > ¶ms) { + eFuncType type = ftNone; + + if (!name.compare("fill")) { + type = ftFill; + } else if (!name.compare("drawtext")) { + type = ftDrawText; + } else if (!name.compare("drawtextbox")) { + type = ftDrawTextBox; + } else if (!name.compare("drawimage")) { + type = ftDrawImage; + } else if (!name.compare("drawrectangle")) { + type = ftDrawRectangle; + } else if (!name.compare("drawellipse")) { + type = ftDrawEllipse; + } + + if (type == ftNone) { + return; + } + + cTemplateFunction *f = new cTemplateFunction(type); + f->SetParameters(params); + functions.push_back(f); +} + +void cTemplatePixmap::AddLoopFunction(cTemplateLoopFunction *lf) { + functions.push_back(lf); +} + + +bool cTemplatePixmap::CalculateParameters(void) { + bool paramsValid = true; + //Calculate Pixmap Size + parameters->SetContainer(containerX, containerY, containerWidth, containerHeight); + parameters->SetGlobals(globals); + paramsValid = parameters->CalculateParameters(); + + int pixWidth = parameters->GetNumericParameter(ptWidth); + int pixHeight = parameters->GetNumericParameter(ptHeight); + + for (vector::iterator func = functions.begin(); func != functions.end(); func++) { + (*func)->SetGlobals(globals); + if (!Ready()) + continue; + (*func)->SetContainer(0, 0, pixWidth, pixHeight); + paramsValid = (*func)->CalculateParameters(); + (*func)->CompleteParameters(); + if ((*func)->GetType() == ftLoop) { + cTemplateLoopFunction *loopFunc = dynamic_cast(*func); + loopFunc->CalculateLoopFuncParameters(); + } + } + + return paramsValid; +} + +void cTemplatePixmap::ClearDynamicFunctionParameters(void) { + InitIterator(); + cTemplateFunction *func = NULL; + while(func = GetNextFunction()) { + func->ClearDynamicParameters(); + } +} + +void cTemplatePixmap::ParseDynamicFunctionParameters(map *stringTokens, map *intTokens) { + InitIterator(); + cTemplateFunction *func = NULL; + bool completelyParsed = true; + bool updated = false; + while(func = GetNextFunction()) { + func->SetStringTokens(stringTokens); + func->SetIntTokens(intTokens); + bool funcCompletelyParsed = func->ParseParameters(); + if (!funcCompletelyParsed) + completelyParsed = false; + if (func->Updated()) + func->CompleteParameters(); + func->UnsetIntTokens(); + func->UnsetStringTokens(); + } + + if (completelyParsed) { + return; + } + + ReplaceWidthFunctions(); + ReplaceHeightFunctions(); + ReplacePosXFunctions(); + ReplacePosYFunctions(); +} + +bool cTemplatePixmap::CalculateDrawPortSize(cSize &size, map < string, vector< map< string, string > > > *loopTokens) { + int pixWidth = parameters->GetNumericParameter(ptWidth); + int pixHeight = parameters->GetNumericParameter(ptHeight); + int orientation = parameters->GetNumericParameter(ptOrientation); + if (orientation < 0) + orientation = orVertical; + if (orientation == orHorizontal) { + //get function which determinates drawport width + cTemplateFunction *scrollFunc = GetScrollFunction(); + if (!scrollFunc) + return false; + int drawportWidth = scrollFunc->GetWidth(false) + scrollFunc->GetNumericParameter(ptX) + 10; + if (drawportWidth > pixWidth) { + size.SetWidth(drawportWidth); + size.SetHeight(pixHeight); + return true; + } + } else if (orientation == orVertical) { + //check "last" element height + InitIterator(); + cTemplateFunction *f = NULL; + int drawportHeight = 1; + while (f = GetNextFunction()) { + if (f->GetType() == ftLoop) { + cTemplateLoopFunction *loopFunc = dynamic_cast(f); + //get number of loop tokens + string loopTokenName = loopFunc->GetParameter(ptName); + int numLoopTokens = 0; + map < string, vector< map< string, string > > >::iterator hit = loopTokens->find(loopTokenName); + if (hit != loopTokens->end()) { + vector< map > loopToken = hit->second; + numLoopTokens = loopToken.size(); + //parse first loop token element to get correct height + vector< map >::iterator firstLoopToken = loopToken.begin(); + loopFunc->ClearDynamicParameters(); + loopFunc->ParseDynamicParameters(&(*firstLoopToken)); + } + int orientation = loopFunc->GetNumericParameter(ptOrientation); + int yFunc = loopFunc->GetNumericParameter(ptY); + int heightFunc = loopFunc->GetLoopElementsHeight(); + if (loopTokens && orientation == orVertical) { + //height is height of loop elements times num loop elements + heightFunc = heightFunc * numLoopTokens; + } else if (loopTokens && orientation == orHorizontal) { + int overflow = loopFunc->GetNumericParameter(ptOverflow); + if (overflow == otCut) { + //do nothing, height is only height of one line + } else if (overflow == otWrap) { + int widthFunc = loopFunc->GetLoopElementsWidth(); + if (widthFunc <= 0) + continue; + int loopWidth = loopFunc->GetNumericParameter(ptWidth); + if (loopWidth <= 0) + loopWidth = loopFunc->GetContainerWidth(); + int elementsPerRow = loopWidth / widthFunc; + int rest = loopWidth % widthFunc; + if (rest > 0) + elementsPerRow++; + if (elementsPerRow <= 0) + continue; + int lines = numLoopTokens / elementsPerRow; + rest = numLoopTokens % elementsPerRow; + if (rest > 0) + lines++; + heightFunc = heightFunc * lines; + } + } + int neededHeight = heightFunc + yFunc; + if (neededHeight > drawportHeight) + drawportHeight = neededHeight; + } else { + int yFunc = f->GetNumericParameter(ptY); + int heightFunc = f->GetHeight(); + int neededHeight = heightFunc + yFunc; + if (neededHeight > drawportHeight) + drawportHeight = neededHeight; + } + } + if (drawportHeight > pixHeight) { + size.SetWidth(pixWidth); + size.SetHeight(drawportHeight); + return true; + } + } + size.SetWidth(0); + size.SetHeight(0); + return false; +} + +void cTemplatePixmap::SetScrollingTextWidth(void) { + int orientation = parameters->GetNumericParameter(ptOrientation); + if (orientation != orHorizontal) + return; + int pixWidth = parameters->GetNumericParameter(ptWidth); + InitIterator(); + cTemplateFunction *func = NULL; + while(func = GetNextFunction()) { + if (func->GetType() == ftDrawText) { + int offset = func->GetNumericParameter(ptX); + func->SetMaxTextWidth(pixWidth - offset); + } + } +} + + +cTemplateFunction *cTemplatePixmap::GetScrollFunction(void) { + string scrollElement = parameters->GetParameter(ptScrollElement); + if (scrollElement.size() == 0) + return NULL; + InitIterator(); + cTemplateFunction *f = NULL; + bool foundElement = false; + while (f = GetNextFunction()) { + string funcName = f->GetParameter(ptName); + if (!funcName.compare(scrollElement)) { + return f; + } + } + return NULL; +} + +cRect cTemplatePixmap::GetPixmapSize(void) { + cRect size; + size.SetX(GetNumericParameter(ptX)); + size.SetY(GetNumericParameter(ptY)); + size.SetWidth(GetNumericParameter(ptWidth)); + size.SetHeight(GetNumericParameter(ptHeight)); + return size; +} + +int cTemplatePixmap::GetNumericParameter(eParamType type) { + if (!parameters) + return -1; + return parameters->GetNumericParameter(type); +} + +void cTemplatePixmap::InitIterator(void) { + funcIt = functions.begin(); +} + +cTemplateFunction *cTemplatePixmap::GetNextFunction(void) { + if (funcIt == functions.end()) + return NULL; + cTemplateFunction *func = *funcIt; + funcIt++; + return func; +} + +bool cTemplatePixmap::Ready(void) { + int myX = parameters->GetNumericParameter(ptX); + if (myX < 0) + return false; + int myY = parameters->GetNumericParameter(ptY); + if (myY < 0) + return false; + int myWidth = parameters->GetNumericParameter(ptWidth); + if (myWidth < 1) + return false; + int myHeight = parameters->GetNumericParameter(ptHeight); + if (myHeight < 1) + return false; + return true; +} + +void cTemplatePixmap::ReplaceWidthFunctions(void) { + InitIterator(); + cTemplateFunction *func = NULL; + while(func = GetNextFunction()) { + if (func->ParsedCompletely()) { + continue; + } + multimap widths; + func->GetNeededWidths(&widths); + for (map::iterator names = widths.begin(); names !=widths.end(); names++) { + eParamType type = names->first; + string label = names->second; + int funcWidth = 0; + for (vector::iterator it = functions.begin(); it != functions.end(); it++) { + cTemplateFunction *myFunc = *it; + string myFuncName = myFunc->GetParameter(ptName); + if (!myFuncName.compare(label)) { + funcWidth = myFunc->GetWidth(); + func->SetWidth(type, label, funcWidth); + if (func->Updated()) { + func->CompleteParameters(); + } + } + } + } + } +} + +void cTemplatePixmap::ReplaceHeightFunctions(void) { + InitIterator(); + cTemplateFunction *func = NULL; + while(func = GetNextFunction()) { + if (func->ParsedCompletely()) { + continue; + } + multimap heights; + func->GetNeededHeights(&heights); + for (map::iterator names = heights.begin(); names !=heights.end(); names++) { + eParamType type = names->first; + string label = names->second; + int funcHeight = 0; + for (vector::iterator it = functions.begin(); it != functions.end(); it++) { + cTemplateFunction *myFunc = *it; + string myFuncName = myFunc->GetParameter(ptName); + if (!myFuncName.compare(label)) { + funcHeight = myFunc->GetHeight(); + func->SetHeight(type, label, funcHeight); + if (func->Updated()) { + func->CompleteParameters(); + } + } + } + } + } +} + +void cTemplatePixmap::ReplacePosXFunctions(void) { + InitIterator(); + cTemplateFunction *func = NULL; + while(func = GetNextFunction()) { + if (func->ParsedCompletely()) { + continue; + } + multimap posXs; + func->GetNeededPosX(&posXs); + for (map::iterator names = posXs.begin(); names !=posXs.end(); names++) { + eParamType type = names->first; + string label = names->second; + int funcX = 0; + for (vector::iterator it = functions.begin(); it != functions.end(); it++) { + cTemplateFunction *myFunc = *it; + string myFuncName = myFunc->GetParameter(ptName); + if (!myFuncName.compare(label)) { + funcX = myFunc->GetNumericParameter(ptX); + if (funcX > -1) { + func->SetX(type, label, funcX); + if (func->Updated()) { + func->CompleteParameters(); + } + } + } + } + } + } +} + +void cTemplatePixmap::ReplacePosYFunctions(void) { + InitIterator(); + cTemplateFunction *func = NULL; + while(func = GetNextFunction()) { + if (func->ParsedCompletely()) { + continue; + } + multimap posYs; + func->GetNeededPosY(&posYs); + for (map::iterator names = posYs.begin(); names !=posYs.end(); names++) { + eParamType type = names->first; + string label = names->second; + int funcY = 0; + for (vector::iterator it = functions.begin(); it != functions.end(); it++) { + cTemplateFunction *myFunc = *it; + string myFuncName = myFunc->GetParameter(ptName); + if (!myFuncName.compare(label)) { + funcY = myFunc->GetNumericParameter(ptY); + if (funcY > -1) { + func->SetY(type, label, funcY); + if (func->Updated()) { + func->CompleteParameters(); + } + } + } + } + } + } +} + +void cTemplatePixmap::Debug(void) { + esyslog("skindesigner: pixmap container size x: %d, y: %d, width: %d, height %d", containerX, containerY, containerWidth, containerHeight); + parameters->Debug(); + for (vector::iterator it = functions.begin(); it != functions.end(); it++) { + (*it)->Debug(); + } +} diff --git a/libtemplate/templatepixmap.h b/libtemplate/templatepixmap.h new file mode 100644 index 0000000..6cf3bd5 --- /dev/null +++ b/libtemplate/templatepixmap.h @@ -0,0 +1,82 @@ +#ifndef __TEMPLATEPIXMAP_H +#define __TEMPLATEPIXMAP_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "globals.h" +#include "templateloopfunction.h" + +using namespace std; + +// --- cTemplatePixmap ------------------------------------------------------------- + +class cTemplatePixmap { +protected: + bool scrolling; + cTemplateFunction *parameters; + vector functions; + vector::iterator funcIt; + int containerX; + int containerY; + int containerWidth; + int containerHeight; + cGlobals *globals; + //functions replacing {width(label)} and {height(label)} tokens + void ReplaceWidthFunctions(void); + void ReplaceHeightFunctions(void); + //functions replacing {posx(label)} and {posy(label)} tokens + void ReplacePosXFunctions(void); + void ReplacePosYFunctions(void); + //Get Scrolling Function + cTemplateFunction *GetScrollFunction(void); +public: + cTemplatePixmap(void); + virtual ~cTemplatePixmap(void); + //Setter Functions + void SetScrolling(void) { scrolling = true; }; + void SetParameters(vector > ¶ms); + void SetWidth(int width); + void SetHeight(int height); + void SetX(int x); + void SetY(int y); + void SetContainer(int x, int y, int w, int h); + void SetGlobals(cGlobals *globals) { this->globals = globals; }; + void AddFunction(string name, vector > ¶ms); + void AddLoopFunction(cTemplateLoopFunction *lf); + //PreCache Parameters + bool CalculateParameters(void); + //clear dynamically set function parameters + void ClearDynamicFunctionParameters(void); + //Clear dynamically set pixmap parameters + void ClearDynamicParameters(void); + //Parse pixmap parameters with dynamically set Tokens + void ParseDynamicParameters(map *intTokens, bool initFuncs); + //Parse all function parameters with dynamically set Tokens + void ParseDynamicFunctionParameters(map *stringTokens, map *intTokens); + //Calculate size of drawport in case area scrolls + bool CalculateDrawPortSize(cSize &size, map < string, vector< map< string, string > > > *loopTokens = NULL); + //Set max width for text in scrollarea + void SetScrollingTextWidth(void); + //Getter Functions + cRect GetPixmapSize(void); + int GetNumericParameter(eParamType type); + bool Scrolling(void) { return scrolling; }; + bool DoExecute(void) { return parameters->DoExecute(); }; + bool DoDebug(void) { return parameters->DoDebug(); }; + bool Ready(void); + //Traverse Functions + void InitIterator(void); + cTemplateFunction *GetNextFunction(void); + //Debug + void Debug(void); +}; + +#endif //__TEMPLATEPIXMAP_H \ No newline at end of file diff --git a/libtemplate/templateview.c b/libtemplate/templateview.c new file mode 100644 index 0000000..abaedc8 --- /dev/null +++ b/libtemplate/templateview.c @@ -0,0 +1,1567 @@ +#include "templateview.h" + +// --- cTemplateView ------------------------------------------------------------- + +cTemplateView::cTemplateView(void) { + globals = NULL; + parameters = NULL; + containerX = 0; + containerY = 0; + containerWidth = 0; + containerHeight = 0; + SetFunctionDefinitions(); +} + +cTemplateView::~cTemplateView() { + + for (map < eViewElement, cTemplateViewElement* >::iterator it = viewElements.begin(); it != viewElements.end(); it++) { + delete it->second; + } + + for (map < eViewList, cTemplateViewList* >::iterator it = viewLists.begin(); it != viewLists.end(); it++) { + delete it->second; + } + + for (vector < cTemplateViewTab* >::iterator it = viewTabs.begin(); it != viewTabs.end(); it++) { + delete *it; + } + + if (parameters) + delete parameters; + +} + +/******************************************************************* +* Public Functions +*******************************************************************/ + +void cTemplateView::SetParameters(vector > ¶ms) { + parameters = new cTemplateFunction(ftView); + parameters->SetGlobals(globals); + parameters->SetParameters(params); +} + +void cTemplateView::SetContainer(int x, int y, int width, int height) { + containerX = x; + containerY = y; + containerWidth = width; + containerHeight = height; +} + +cTemplateViewElement *cTemplateView::GetViewElement(eViewElement ve) { + map < eViewElement, cTemplateViewElement* >::iterator hit = viewElements.find(ve); + if (hit == viewElements.end()) + return NULL; + return hit->second; +} + +void cTemplateView::InitViewElementIterator(void) { + veIt = viewElements.begin(); +} + +cTemplateViewElement *cTemplateView::GetNextViewElement(void) { + if (veIt == viewElements.end()) + return NULL; + cTemplateViewElement *viewElement = veIt->second; + veIt++; + return viewElement; +} + +cTemplateViewList *cTemplateView::GetViewList(eViewList vl) { + map < eViewList, cTemplateViewList* >::iterator hit = viewLists.find(vl); + if (hit == viewLists.end()) + return NULL; + return hit->second; +} + +void cTemplateView::InitViewListIterator(void) { + vlIt = viewLists.begin(); +} + +cTemplateViewList *cTemplateView::GetNextViewList(void) { + if (vlIt == viewLists.end()) + return NULL; + cTemplateViewList *viewList = vlIt->second; + vlIt++; + return viewList; +} + +cTemplateView *cTemplateView::GetSubView(eSubView sv) { + map < eSubView, cTemplateView* >::iterator hit = subViews.find(sv); + if (hit == subViews.end()) + return NULL; + return hit->second; +} + +void cTemplateView::InitViewTabIterator(void) { + vtIt = viewTabs.begin(); +} + +cTemplateViewTab *cTemplateView::GetNextViewTab(void) { + if (vtIt == viewTabs.end()) { + return NULL; + } + cTemplateViewTab *tab = *vtIt; + vtIt++; + return tab; +} + +void cTemplateView::InitSubViewIterator(void) { + svIt = subViews.begin(); +} + +cTemplateView *cTemplateView::GetNextSubView(void) { + if (svIt == subViews.end()) + return NULL; + cTemplateView *subView = svIt->second; + svIt++; + return subView; +} + +int cTemplateView::GetNumericParameter(eParamType type) { + if (!parameters) + return 0; + return parameters->GetNumericParameter(type); +} + +cRect cTemplateView::GetOsdSize(void) { + cRect osdSize; + if (!parameters) { + return osdSize; + } + osdSize.SetX(parameters->GetNumericParameter(ptX)); + osdSize.SetY(parameters->GetNumericParameter(ptY)); + osdSize.SetWidth(parameters->GetNumericParameter(ptWidth)); + osdSize.SetHeight(parameters->GetNumericParameter(ptHeight)); + return osdSize; +} + +int cTemplateView::GetNumPixmaps(void) { + int numPixmaps = 0; + for (map < eViewElement, cTemplateViewElement* >::iterator it = viewElements.begin(); it != viewElements.end(); it++) { + cTemplateViewElement *viewElement = it->second; + numPixmaps += viewElement->GetNumPixmaps(); + } + return numPixmaps; +} + +int cTemplateView::GetNumPixmapsViewElement(eViewElement ve) { + map < eViewElement, cTemplateViewElement* >::iterator hit = viewElements.find(ve); + if (hit == viewElements.end()) + return 0; + cTemplateViewElement *viewElement = hit->second; + return viewElement->GetNumPixmaps(); +} + +int cTemplateView::GetNumListViewMenuItems(void) { + int numElements = 0; + cTemplateViewList *menuList = GetViewList(vlMenuItem); + if (!menuList) + return numElements; + return menuList->GetNumericParameter(ptNumElements); +} + +bool cTemplateView::GetScalingWindow(cRect &scalingWindow) { + if (!parameters) + return false; + bool doScale = false; + int scaleX = parameters->GetNumericParameter(ptScaleTvX); + int scaleY = parameters->GetNumericParameter(ptScaleTvY); + int scaleWidth = parameters->GetNumericParameter(ptScaleTvWidth); + int scaleHeight = parameters->GetNumericParameter(ptScaleTvHeight); + if (scaleX > -1 && scaleY > -1 && scaleWidth > -1 && scaleHeight > -1) { + cRect suggestedScaleWindow(scaleX, scaleY, scaleWidth, scaleHeight); + scalingWindow = cDevice::PrimaryDevice()->CanScaleVideo(suggestedScaleWindow); + doScale = true; + } else { + scalingWindow = cDevice::PrimaryDevice()->CanScaleVideo(cRect::Null); + } + return doScale; +} + +bool cTemplateView::ValidViewElement(const char *viewElement) { + set::iterator hit = viewElementsAllowed.find(viewElement); + if (hit == viewElementsAllowed.end()) + return false; + return true; +} + +bool cTemplateView::ValidSubView(const char *subView) { + set::iterator hit = subViewsAllowed.find(subView); + if (hit == subViewsAllowed.end()) + return false; + return true; +} + +bool cTemplateView::ValidViewList(const char *viewList) { + set::iterator hit = viewListsAllowed.find(viewList); + if (hit == viewListsAllowed.end()) + return false; + return true; +} + +bool cTemplateView::ValidFunction(const char *func) { + map < string, set < string > >::iterator hit = funcsAllowed.find(func); + if (hit == funcsAllowed.end()) + return false; + return true; +} + +bool cTemplateView::ValidAttribute(const char *func, const char *att) { + map < string, set < string > >::iterator hit = funcsAllowed.find(func); + if (hit == funcsAllowed.end()) + return false; + + set::iterator hitAtt = (hit->second).find(att); + if (hitAtt == (hit->second).end()) + return false; + + return true; +} + +void cTemplateView::Translate(void) { + //Translate ViewElements + InitViewElementIterator(); + cTemplateViewElement *viewElement = NULL; + while(viewElement = GetNextViewElement()) { + viewElement->InitIterator(); + cTemplatePixmap *pix = NULL; + while(pix = viewElement->GetNextPixmap()) { + pix->InitIterator(); + cTemplateFunction *func = NULL; + while(func = pix->GetNextFunction()) { + if (func->GetType() == ftDrawText || func->GetType() == ftDrawTextBox) { + string text = func->GetParameter(ptText); + string translation; + bool translated = globals->Translate(text, translation); + if (translated) { + func->SetTranslatedText(translation); + } + } + } + } + } + //Translate viewLists + InitViewListIterator(); + cTemplateViewList *viewList = NULL; + while(viewList = GetNextViewList()) { + viewList->InitIterator(); + cTemplatePixmap *pix = NULL; + while(pix = viewList->GetNextPixmap()) { + pix->InitIterator(); + cTemplateFunction *func = NULL; + while(func = pix->GetNextFunction()) { + if (func->GetType() == ftDrawText || func->GetType() == ftDrawTextBox) { + string text = func->GetParameter(ptText); + string translation; + bool translated = globals->Translate(text, translation); + if (translated) { + func->SetTranslatedText(translation); + } + } + } + } + cTemplateViewElement *listElement = viewList->GetListElement(); + listElement->InitIterator(); + while(pix = listElement->GetNextPixmap()) { + pix->InitIterator(); + cTemplateFunction *func = NULL; + while(func = pix->GetNextFunction()) { + if (func->GetType() == ftDrawText || func->GetType() == ftDrawTextBox) { + string text = func->GetParameter(ptText); + string translation; + bool translated = globals->Translate(text, translation); + if (translated) { + func->SetTranslatedText(translation); + } + } + } + } + + cTemplateViewElement *listElementCurrent = viewList->GetListElementCurrent(); + if (listElementCurrent) { + listElementCurrent->InitIterator(); + while(pix = listElementCurrent->GetNextPixmap()) { + pix->InitIterator(); + cTemplateFunction *func = NULL; + while(func = pix->GetNextFunction()) { + if (func->GetType() == ftDrawText || func->GetType() == ftDrawTextBox) { + string text = func->GetParameter(ptText); + string translation; + bool translated = globals->Translate(text, translation); + if (translated) { + func->SetTranslatedText(translation); + } + } + } + } + } + } + + //Translate viewTabs + InitViewTabIterator(); + cTemplateViewTab *viewTab = NULL; + while(viewTab = GetNextViewTab()) { + string tabName = viewTab->GetName(); + string tabTrans; + bool translated = globals->Translate(tabName, tabTrans); + if (translated) { + viewTab->SetName(tabTrans); + } + viewTab->InitIterator(); + cTemplateFunction *func = NULL; + while(func = viewTab->GetNextFunction()) { + if (func->GetType() == ftDrawText || func->GetType() == ftDrawTextBox) { + string text = func->GetParameter(ptText); + string translation; + translated = globals->Translate(text, translation); + if (translated) { + func->SetTranslatedText(translation); + } + } + } + } + + //Translate Subviews + InitSubViewIterator(); + cTemplateView *subView = NULL; + while(subView = GetNextSubView()) { + subView->Translate(); + } +} + +void cTemplateView::PreCache(bool isSubview) { + + if (!isSubview) { + int osdW = cOsd::OsdWidth(); + int osdH = cOsd::OsdHeight(); + parameters->SetContainer(0, 0, osdW, osdH); + } else { + parameters->SetContainer(containerX, containerY, containerWidth, containerHeight); + } + //Calculate OSD Size + parameters->CalculateParameters(); + + int osdX = parameters->GetNumericParameter(ptX); + int osdY = parameters->GetNumericParameter(ptY); + int osdWidth = parameters->GetNumericParameter(ptWidth); + int osdHeight = parameters->GetNumericParameter(ptHeight); + int pixOffset = 0; + + //Cache ViewElements + for (map < eViewElement, cTemplateViewElement* >::iterator it = viewElements.begin(); it != viewElements.end(); it++) { + cTemplateViewElement *viewElement = it->second; + viewElement->SetGlobals(globals); + viewElement->SetContainer(0, 0, osdWidth, osdHeight); + viewElement->CalculatePixmapParameters(); + viewElement->SetPixOffset(pixOffset); + pixOffset += viewElement->GetNumPixmaps(); + } + + //Cache ViewLists + for (map < eViewList, cTemplateViewList* >::iterator it = viewLists.begin(); it != viewLists.end(); it++) { + cTemplateViewList *viewList = it->second; + viewList->SetGlobals(globals); + viewList->SetContainer(0, 0, osdWidth, osdHeight); + viewList->CalculateListParameters(); + } + + //Cache ViewTabs + for (vector::iterator tab = viewTabs.begin(); tab != viewTabs.end(); tab++) { + (*tab)->SetContainer(containerX, containerY, containerWidth, containerHeight); + (*tab)->SetGlobals(globals); + (*tab)->CalculateParameters(); + } + + //Cache Subviews + for (map < eSubView, cTemplateView* >::iterator it = subViews.begin(); it != subViews.end(); it++) { + cTemplateView *subView = it->second; + subView->SetContainer(0, 0, osdWidth, osdHeight); + subView->PreCache(true); + } + +} + +void cTemplateView::Debug(void) { + + esyslog("skindesigner: TemplateView %s", viewName.c_str());; + + parameters->Debug(); + + for (map < eViewElement, cTemplateViewElement* >::iterator it = viewElements.begin(); it != viewElements.end(); it++) { + esyslog("skindesigner: ++++++++ ViewElement: %s", GetViewElementName(it->first).c_str()); + cTemplateViewElement *viewElement = it->second; + viewElement->Debug(); + } + + for (map < eViewList, cTemplateViewList* >::iterator it = viewLists.begin(); it != viewLists.end(); it++) { + esyslog("skindesigner: ++++++++ ViewList: %s", GetViewListName(it->first).c_str()); + cTemplateViewList *viewList = it->second; + viewList->Debug(); + } + + for (vector::iterator tab = viewTabs.begin(); tab != viewTabs.end(); tab++) { + esyslog("skindesigner: ++++++++ ViewTab"); + (*tab)->Debug(); + } + + for (map < eSubView, cTemplateView* >::iterator it = subViews.begin(); it!= subViews.end(); it++) { + esyslog("skindesigner: ++++++++ SubView: %s", GetSubViewName(it->first).c_str()); + cTemplateView *subView = it->second; + subView->Debug(); + } + +} + + +void cTemplateView::SetFunctionDefinitions(void) { + + string name = "area"; + set attributes; + attributes.insert("debug"); + attributes.insert("condition"); + attributes.insert("x"); + attributes.insert("y"); + attributes.insert("width"); + attributes.insert("height"); + attributes.insert("layer"); + attributes.insert("transparency"); + funcsAllowed.insert(pair< string, set >(name, attributes)); + + name = "areascroll"; + attributes.clear(); + attributes.insert("debug"); + attributes.insert("orientation"); + attributes.insert("delay"); + attributes.insert("mode"); + attributes.insert("scrollspeed"); + attributes.insert("condition"); + attributes.insert("scrollelement"); + attributes.insert("x"); + attributes.insert("y"); + attributes.insert("width"); + attributes.insert("height"); + attributes.insert("layer"); + attributes.insert("transparency"); + funcsAllowed.insert(pair< string, set >(name, attributes)); + + name = "loop"; + attributes.clear(); + attributes.insert("debug"); + attributes.insert("name"); + attributes.insert("orientation"); + attributes.insert("condition"); + attributes.insert("x"); + attributes.insert("y"); + attributes.insert("width"); + attributes.insert("height"); + attributes.insert("columnwidth"); + attributes.insert("rowheight"); + attributes.insert("overflow"); + attributes.insert("maxitems"); + funcsAllowed.insert(pair< string, set >(name, attributes)); + + name = "fill"; + attributes.clear(); + attributes.insert("debug"); + attributes.insert("condition"); + attributes.insert("color"); + funcsAllowed.insert(pair< string, set >(name, attributes)); + + name = "drawtext"; + attributes.clear(); + attributes.insert("debug"); + attributes.insert("condition"); + attributes.insert("name"); + attributes.insert("x"); + attributes.insert("y"); + attributes.insert("width"); + attributes.insert("align"); + attributes.insert("valign"); + attributes.insert("font"); + attributes.insert("fontsize"); + attributes.insert("color"); + attributes.insert("text"); + funcsAllowed.insert(pair< string, set >(name, attributes)); + + name = "drawtextbox"; + attributes.clear(); + attributes.insert("debug"); + attributes.insert("condition"); + attributes.insert("name"); + attributes.insert("x"); + attributes.insert("y"); + attributes.insert("width"); + attributes.insert("height"); + attributes.insert("align"); + attributes.insert("maxlines"); + attributes.insert("font"); + attributes.insert("fontsize"); + attributes.insert("color"); + attributes.insert("text"); + attributes.insert("float"); + attributes.insert("floatwidth"); + attributes.insert("floatheight"); + funcsAllowed.insert(pair< string, set >(name, attributes)); + + name = "drawimage"; + attributes.clear(); + attributes.insert("debug"); + attributes.insert("condition"); + attributes.insert("name"); + attributes.insert("x"); + attributes.insert("y"); + attributes.insert("align"); + attributes.insert("valign"); + attributes.insert("width"); + attributes.insert("height"); + attributes.insert("imagetype"); + attributes.insert("path"); + attributes.insert("align"); + attributes.insert("valign"); + attributes.insert("cache"); + funcsAllowed.insert(pair< string, set >(name, attributes)); + + name = "drawrectangle"; + attributes.clear(); + attributes.insert("debug"); + attributes.insert("condition"); + attributes.insert("name"); + attributes.insert("x"); + attributes.insert("y"); + attributes.insert("align"); + attributes.insert("valign"); + attributes.insert("width"); + attributes.insert("height"); + attributes.insert("color"); + funcsAllowed.insert(pair< string, set >(name, attributes)); + + name = "drawellipse"; + attributes.clear(); + attributes.insert("debug"); + attributes.insert("condition"); + attributes.insert("name"); + attributes.insert("x"); + attributes.insert("y"); + attributes.insert("align"); + attributes.insert("valign"); + attributes.insert("width"); + attributes.insert("height"); + attributes.insert("color"); + attributes.insert("quadrant"); + funcsAllowed.insert(pair< string, set >(name, attributes)); + +} + +/************************************************************************************ +* cTemplateViewChannel +************************************************************************************/ + +cTemplateViewChannel::cTemplateViewChannel(void) { + + viewName = "displaychannel"; + //definition of allowed parameters for class itself + set attributes; + attributes.insert("x"); + attributes.insert("y"); + attributes.insert("width"); + attributes.insert("height"); + attributes.insert("fadetime"); + attributes.insert("scaletvx"); + attributes.insert("scaletvy"); + attributes.insert("scaletvwidth"); + attributes.insert("scaletvheight"); + funcsAllowed.insert(pair< string, set >(viewName, attributes)); + + SetViewElements(); +} + +cTemplateViewChannel::~cTemplateViewChannel() { +} + +void cTemplateViewChannel::SetViewElements(void) { + viewElementsAllowed.insert("background"); + viewElementsAllowed.insert("channelinfo"); + viewElementsAllowed.insert("channelgroup"); + viewElementsAllowed.insert("epginfo"); + viewElementsAllowed.insert("progressbar"); + viewElementsAllowed.insert("progressbarback"); + viewElementsAllowed.insert("statusinfo"); + viewElementsAllowed.insert("screenresolution"); + viewElementsAllowed.insert("signalquality"); + viewElementsAllowed.insert("signalqualityback"); + viewElementsAllowed.insert("scrapercontent"); + viewElementsAllowed.insert("datetime"); + viewElementsAllowed.insert("message"); +} + +string cTemplateViewChannel::GetViewElementName(eViewElement ve) { + string name; + switch (ve) { + case veBackground: + name = "Background"; + break; + case veChannelInfo: + name = "ChannelInfo"; + break; + case veChannelGroup: + name = "ChannelGroup"; + break; + case veEpgInfo: + name = "EpgInfo"; + break; + case veProgressBar: + name = "ProgressBar"; + break; + case veProgressBarBack: + name = "ProgressBar Background"; + break; + case veStatusInfo: + name = "StatusInfo"; + break; + case veScreenResolution: + name = "Screen Resolution"; + break; + case veSignalQuality: + name = "Signal Quality"; + break; + case veSignalQualityBack: + name = "Signal Quality Background"; + break; + case veScraperContent: + name = "Scraper Content"; + break; + case veDateTime: + name = "DateTime"; + break; + case veMessage: + name = "Message"; + break; + default: + name = "Unknown"; + break; + }; + return name; +} + +void cTemplateViewChannel::AddPixmap(string sViewElement, cTemplatePixmap *pix, bool debugViewElement) { + eViewElement ve = veUndefined; + + if (!sViewElement.compare("background")) { + ve = veBackground; + } else if (!sViewElement.compare("channelinfo")) { + ve = veChannelInfo; + } else if (!sViewElement.compare("channelgroup")) { + ve = veChannelGroup; + } else if (!sViewElement.compare("epginfo")) { + ve = veEpgInfo; + } else if (!sViewElement.compare("progressbar")) { + ve = veProgressBar; + } else if (!sViewElement.compare("progressbarback")) { + ve = veProgressBarBack; + } else if (!sViewElement.compare("statusinfo")) { + ve = veStatusInfo; + } else if (!sViewElement.compare("screenresolution")) { + ve = veScreenResolution; + } else if (!sViewElement.compare("signalquality")) { + ve = veSignalQuality; + } else if (!sViewElement.compare("signalqualityback")) { + ve = veSignalQualityBack; + } else if (!sViewElement.compare("scrapercontent")) { + ve = veScraperContent; + } else if (!sViewElement.compare("datetime")) { + ve = veDateTime; + } else if (!sViewElement.compare("message")) { + ve = veMessage; + } + + if (ve == veUndefined) { + esyslog("skindesigner: unknown ViewElement in displaychannel: %s", sViewElement.c_str()); + return; + } + + pix->SetGlobals(globals); + + map < eViewElement, cTemplateViewElement* >::iterator hit = viewElements.find(ve); + if (hit == viewElements.end()) { + cTemplateViewElement *viewElement = new cTemplateViewElement(); + viewElement->AddPixmap(pix); + viewElements.insert(pair< eViewElement, cTemplateViewElement*>(ve, viewElement)); + if (debugViewElement) + viewElement->ActivateDebugTokens(); + } else { + (hit->second)->AddPixmap(pix); + } +} + +/************************************************************************************ +* cTemplateViewMenu +************************************************************************************/ + +cTemplateViewMenu::cTemplateViewMenu(void) { + + viewName = "displaymenu"; + //definition of allowed parameters for class itself + set attributes; + attributes.insert("x"); + attributes.insert("y"); + attributes.insert("width"); + attributes.insert("height"); + attributes.insert("fadetime"); + funcsAllowed.insert(pair< string, set >(viewName, attributes)); + + string subViewName = "menudefault"; + //definition of allowed parameters for subtemplate menumain + attributes.clear(); + attributes.insert("x"); + attributes.insert("y"); + attributes.insert("width"); + attributes.insert("height"); + attributes.insert("fadetime"); + attributes.insert("scaletvx"); + attributes.insert("scaletvy"); + attributes.insert("scaletvwidth"); + attributes.insert("scaletvheight"); + funcsAllowed.insert(pair< string, set >(subViewName, attributes)); + + subViewName = "menumain"; + //definition of allowed parameters for subtemplate menumain + attributes.clear(); + attributes.insert("x"); + attributes.insert("y"); + attributes.insert("width"); + attributes.insert("height"); + attributes.insert("fadetime"); + attributes.insert("scaletvx"); + attributes.insert("scaletvy"); + attributes.insert("scaletvwidth"); + attributes.insert("scaletvheight"); + funcsAllowed.insert(pair< string, set >(subViewName, attributes)); + + subViewName = "menusetup"; + //definition of allowed parameters for subtemplate menumain + attributes.clear(); + attributes.insert("x"); + attributes.insert("y"); + attributes.insert("width"); + attributes.insert("height"); + attributes.insert("fadetime"); + attributes.insert("scaletvx"); + attributes.insert("scaletvy"); + attributes.insert("scaletvwidth"); + attributes.insert("scaletvheight"); + funcsAllowed.insert(pair< string, set >(subViewName, attributes)); + + subViewName = "menuschedules"; + //definition of allowed parameters for subtemplate menumain + attributes.clear(); + attributes.insert("x"); + attributes.insert("y"); + attributes.insert("width"); + attributes.insert("height"); + attributes.insert("fadetime"); + attributes.insert("scaletvx"); + attributes.insert("scaletvy"); + attributes.insert("scaletvwidth"); + attributes.insert("scaletvheight"); + funcsAllowed.insert(pair< string, set >(subViewName, attributes)); + + subViewName = "menuchannels"; + //definition of allowed parameters for subtemplate menumain + attributes.clear(); + attributes.insert("x"); + attributes.insert("y"); + attributes.insert("width"); + attributes.insert("height"); + attributes.insert("fadetime"); + attributes.insert("scaletvx"); + attributes.insert("scaletvy"); + attributes.insert("scaletvwidth"); + attributes.insert("scaletvheight"); + funcsAllowed.insert(pair< string, set >(subViewName, attributes)); + + subViewName = "menutimers"; + //definition of allowed parameters for subtemplate menumain + attributes.clear(); + attributes.insert("x"); + attributes.insert("y"); + attributes.insert("width"); + attributes.insert("height"); + attributes.insert("fadetime"); + attributes.insert("scaletvx"); + attributes.insert("scaletvy"); + attributes.insert("scaletvwidth"); + attributes.insert("scaletvheight"); + funcsAllowed.insert(pair< string, set >(subViewName, attributes)); + + subViewName = "menurecordings"; + //definition of allowed parameters for subtemplate menumain + attributes.clear(); + attributes.insert("x"); + attributes.insert("y"); + attributes.insert("width"); + attributes.insert("height"); + attributes.insert("fadetime"); + attributes.insert("scaletvx"); + attributes.insert("scaletvy"); + attributes.insert("scaletvwidth"); + attributes.insert("scaletvheight"); + funcsAllowed.insert(pair< string, set >(subViewName, attributes)); + + subViewName = "menudetailedepg"; + //definition of allowed parameters for subtemplate menumain + attributes.clear(); + attributes.insert("x"); + attributes.insert("y"); + attributes.insert("width"); + attributes.insert("height"); + attributes.insert("fadetime"); + attributes.insert("scaletvx"); + attributes.insert("scaletvy"); + attributes.insert("scaletvwidth"); + attributes.insert("scaletvheight"); + funcsAllowed.insert(pair< string, set >(subViewName, attributes)); + + subViewName = "menudetailedrecording"; + //definition of allowed parameters for subtemplate menumain + attributes.clear(); + attributes.insert("x"); + attributes.insert("y"); + attributes.insert("width"); + attributes.insert("height"); + attributes.insert("fadetime"); + attributes.insert("scaletvx"); + attributes.insert("scaletvy"); + attributes.insert("scaletvwidth"); + attributes.insert("scaletvheight"); + funcsAllowed.insert(pair< string, set >(subViewName, attributes)); + + subViewName = "menudetailedtext"; + //definition of allowed parameters for subtemplate menumain + attributes.clear(); + attributes.insert("x"); + attributes.insert("y"); + attributes.insert("width"); + attributes.insert("height"); + attributes.insert("fadetime"); + attributes.insert("scaletvx"); + attributes.insert("scaletvy"); + attributes.insert("scaletvwidth"); + attributes.insert("scaletvheight"); + funcsAllowed.insert(pair< string, set >(subViewName, attributes)); + + //definition of allowed parameters for timerlist viewlist + attributes.clear(); + attributes.insert("x"); + attributes.insert("y"); + attributes.insert("width"); + attributes.insert("height"); + attributes.insert("orientation"); + attributes.insert("align"); + attributes.insert("numlistelements"); + funcsAllowed.insert(pair< string, set >("timerlist", attributes)); + + //definition of allowed parameters for menuitems viewlist + attributes.clear(); + attributes.insert("x"); + attributes.insert("y"); + attributes.insert("width"); + attributes.insert("height"); + attributes.insert("orientation"); + attributes.insert("align"); + attributes.insert("menuitemwidth"); + attributes.insert("determinatefont"); + attributes.insert("numlistelements"); + funcsAllowed.insert(pair< string, set >("menuitems", attributes)); + + //definition of allowed parameters for currentitems viewlist + attributes.clear(); + attributes.insert("delay"); + attributes.insert("fadetime"); + funcsAllowed.insert(pair< string, set >("currentelement", attributes)); + + //definition of allowed parameters for viewtab + attributes.clear(); + attributes.insert("debug"); + attributes.insert("name"); + attributes.insert("condition"); + attributes.insert("x"); + attributes.insert("y"); + attributes.insert("width"); + attributes.insert("height"); + attributes.insert("layer"); + attributes.insert("transparency"); + attributes.insert("scrollheight"); + funcsAllowed.insert(pair< string, set >("tab", attributes)); + + SetSubViews(); + SetViewElements(); + SetViewLists(); + +} + +cTemplateViewMenu::~cTemplateViewMenu() { +} + +void cTemplateViewMenu::SetSubViews(void) { + subViewsAllowed.insert("menudefault"); + subViewsAllowed.insert("menumain"); + subViewsAllowed.insert("menusetup"); + subViewsAllowed.insert("menuschedules"); + subViewsAllowed.insert("menutimers"); + subViewsAllowed.insert("menurecordings"); + subViewsAllowed.insert("menuchannels"); + subViewsAllowed.insert("menudetailedepg"); + subViewsAllowed.insert("menudetailedrecording"); + subViewsAllowed.insert("menudetailedtext"); +} + +void cTemplateViewMenu::SetViewElements(void) { + viewElementsAllowed.insert("background"); + viewElementsAllowed.insert("datetime"); + viewElementsAllowed.insert("header"); + viewElementsAllowed.insert("colorbuttons"); + viewElementsAllowed.insert("message"); + viewElementsAllowed.insert("discusage"); + viewElementsAllowed.insert("systemload"); + viewElementsAllowed.insert("timers"); + viewElementsAllowed.insert("devices"); + viewElementsAllowed.insert("scrollbar"); + viewElementsAllowed.insert("detailheader"); + viewElementsAllowed.insert("tablabels"); +} + +void cTemplateViewMenu::SetViewLists(void) { + viewListsAllowed.insert("timerlist"); + viewListsAllowed.insert("menuitems"); +} + +string cTemplateViewMenu::GetSubViewName(eSubView sv) { + string name; + switch (sv) { + case svMenuDefault: + name = "Default Menu"; + break; + case svMenuMain: + name = "Main Menu"; + break; + case svMenuSetup: + name = "Setup Menu"; + break; + case svMenuSchedules: + name = "Schedules Menu"; + break; + case svMenuTimers: + name = "Timers Menu"; + break; + case svMenuRecordings: + name = "Recordings Menu"; + break; + case svMenuChannels: + name = "Channels Menu"; + break; + case svMenuDetailedEpg: + name = "Detailed EPG"; + break; + case svMenuDetailedRecording: + name = "Detailed Recording"; + break; + case svMenuDetailedText: + name = "Detailed Text"; + break; + default: + name = "Unknown"; + break; + }; + return name; +} + + +string cTemplateViewMenu::GetViewElementName(eViewElement ve) { + string name; + switch (ve) { + case veBackground: + name = "Background"; + break; + case veDateTime: + name = "DateTime"; + break; + case veHeader: + name = "Header"; + break; + case veButtons: + name = "Color Buttons"; + break; + case veMessage: + name = "Message"; + break; + case veDiscUsage: + name = "Disc Usage"; + break; + case veSystemLoad: + name = "System Load"; + break; + case veTimers: + name = "Timers"; + break; + case veDevices: + name = "Devices"; + break; + case veMenuItem: + name = "Menu Item"; + break; + case veMenuCurrentItemDetail: + name = "Menu Current Item Detail"; + break; + case veScrollbar: + name = "Scrollbar"; + break; + case veDetailHeader: + name = "Detail header"; + break; + case veTabLabels: + name = "tab labels"; + break; + default: + name = "Unknown"; + break; + }; + return name; +} + +string cTemplateViewMenu::GetViewListName(eViewList vl) { + string name; + switch (vl) { + case vlTimerList: + name = "Timer List"; + break; + case vlMenuItem: + name = "Menu Item"; + break; + default: + name = "Unknown"; + break; + }; + return name; +} + +void cTemplateViewMenu::AddSubView(string sSubView, cTemplateView *subView) { + eSubView sv = svUndefined; + + if (!sSubView.compare("menumain")) { + sv = svMenuMain; + } else if (!sSubView.compare("menudefault")) { + sv = svMenuDefault; + } else if (!sSubView.compare("menuschedules")) { + sv = svMenuSchedules; + } else if (!sSubView.compare("menusetup")) { + sv = svMenuSetup; + } else if (!sSubView.compare("menuschedules")) { + sv = svMenuSchedules; + } else if (!sSubView.compare("menutimers")) { + sv = svMenuTimers; + } else if (!sSubView.compare("menurecordings")) { + sv = svMenuRecordings; + } else if (!sSubView.compare("menuchannels")) { + sv = svMenuChannels; + } else if (!sSubView.compare("menudetailedepg")) { + sv = svMenuDetailedEpg; + } else if (!sSubView.compare("menudetailedrecording")) { + sv = svMenuDetailedRecording; + } else if (!sSubView.compare("menudetailedtext")) { + sv = svMenuDetailedText; + } + + if (sv == svUndefined) { + esyslog("skindesigner: unknown SubView in displayMenu: %s", sSubView.c_str()); + return; + } + subView->SetGlobals(globals); + subViews.insert(pair(sv, subView)); +} + +void cTemplateViewMenu::AddPixmap(string sViewElement, cTemplatePixmap *pix, bool debugViewElement) { + eViewElement ve = veUndefined; + + if (!sViewElement.compare("background")) { + ve = veBackground; + } else if (!sViewElement.compare("datetime")) { + ve = veDateTime; + } else if (!sViewElement.compare("header")) { + ve = veHeader; + } else if (!sViewElement.compare("colorbuttons")) { + ve = veButtons; + } else if (!sViewElement.compare("message")) { + ve = veMessage; + } else if (!sViewElement.compare("discusage")) { + ve = veDiscUsage; + } else if (!sViewElement.compare("systemload")) { + ve = veSystemLoad; + } else if (!sViewElement.compare("timers")) { + ve = veTimers; + } else if (!sViewElement.compare("devices")) { + ve = veDevices; + } else if (!sViewElement.compare("scrollbar")) { + ve = veScrollbar; + } else if (!sViewElement.compare("detailheader")) { + ve = veDetailHeader; + } else if (!sViewElement.compare("tablabels")) { + ve = veTabLabels; + } + + if (ve == veUndefined) { + esyslog("skindesigner: unknown ViewElement in displayMenu: %s", sViewElement.c_str()); + return; + } + + pix->SetGlobals(globals); + + map < eViewElement, cTemplateViewElement* >::iterator hit = viewElements.find(ve); + if (hit == viewElements.end()) { + cTemplateViewElement *viewElement = new cTemplateViewElement(); + viewElement->AddPixmap(pix); + viewElements.insert(pair< eViewElement, cTemplateViewElement*>(ve, viewElement)); + if (debugViewElement) + viewElement->ActivateDebugTokens(); + } else { + (hit->second)->AddPixmap(pix); + } +} + +void cTemplateViewMenu::AddViewList(string sViewList, cTemplateViewList *viewList) { + + eViewList vl = vlUndefined; + if (!sViewList.compare("timerlist")) { + vl = vlTimerList; + } else if (!sViewList.compare("menuitems")) { + vl = vlMenuItem; + } + + if (vl == vlUndefined) { + esyslog("skindesigner: unknown ViewList in displaymenu: %s", sViewList.c_str()); + return; + } + + viewList->SetGlobals(globals); + viewLists.insert(pair< eViewList, cTemplateViewList*>(vl, viewList)); +} + +void cTemplateViewMenu::AddViewTab(cTemplateViewTab *viewTab) { + viewTabs.push_back(viewTab); +} + +/************************************************************************************ +* cTemplateViewMessage +************************************************************************************/ + +cTemplateViewMessage::cTemplateViewMessage(void) { + + viewName = "displaymessage"; + //definition of allowed parameters for class itself + set attributes; + attributes.insert("x"); + attributes.insert("y"); + attributes.insert("width"); + attributes.insert("height"); + attributes.insert("fadetime"); + attributes.insert("scaletvx"); + attributes.insert("scaletvy"); + attributes.insert("scaletvwidth"); + attributes.insert("scaletvheight"); + funcsAllowed.insert(pair< string, set >(viewName, attributes)); + + SetViewElements(); +} + +cTemplateViewMessage::~cTemplateViewMessage() { +} + +void cTemplateViewMessage::SetViewElements(void) { + viewElementsAllowed.insert("background"); + viewElementsAllowed.insert("message"); +} + +string cTemplateViewMessage::GetViewElementName(eViewElement ve) { + string name; + switch (ve) { + case veBackground: + name = "Background"; + break; + case veMessage: + name = "Message"; + break; + default: + name = "Unknown"; + break; + }; + return name; +} + +void cTemplateViewMessage::AddPixmap(string sViewElement, cTemplatePixmap *pix, bool debugViewElement) { + eViewElement ve = veUndefined; + + if (!sViewElement.compare("background")) { + ve = veBackground; + } else if (!sViewElement.compare("message")) { + ve = veMessage; + } + + if (ve == veUndefined) { + esyslog("skindesigner: unknown ViewElement in displaymessage: %s", sViewElement.c_str()); + return; + } + + pix->SetGlobals(globals); + + map < eViewElement, cTemplateViewElement* >::iterator hit = viewElements.find(ve); + if (hit == viewElements.end()) { + cTemplateViewElement *viewElement = new cTemplateViewElement(); + viewElement->AddPixmap(pix); + viewElements.insert(pair< eViewElement, cTemplateViewElement*>(ve, viewElement)); + if (debugViewElement) + viewElement->ActivateDebugTokens(); + } else { + (hit->second)->AddPixmap(pix); + } +} + +/************************************************************************************ +* cTemplateViewReplay +************************************************************************************/ + +cTemplateViewReplay::cTemplateViewReplay(void) { + + viewName = "displayreplay"; + //definition of allowed parameters for class itself + set attributes; + attributes.insert("x"); + attributes.insert("y"); + attributes.insert("width"); + attributes.insert("height"); + attributes.insert("fadetime"); + attributes.insert("scaletvx"); + attributes.insert("scaletvy"); + attributes.insert("scaletvwidth"); + attributes.insert("scaletvheight"); + funcsAllowed.insert(pair< string, set >(viewName, attributes)); + + SetViewElements(); +} + +cTemplateViewReplay::~cTemplateViewReplay() { +} + +void cTemplateViewReplay::SetViewElements(void) { + viewElementsAllowed.insert("background"); + viewElementsAllowed.insert("backgroundmodeonly"); + viewElementsAllowed.insert("datetime"); + viewElementsAllowed.insert("rectitle"); + viewElementsAllowed.insert("recinfo"); + viewElementsAllowed.insert("scrapercontent"); + viewElementsAllowed.insert("currenttime"); + viewElementsAllowed.insert("totaltime"); + viewElementsAllowed.insert("progressbar"); + viewElementsAllowed.insert("cutmarks"); + viewElementsAllowed.insert("controlicons"); + viewElementsAllowed.insert("controliconsmodeonly"); + viewElementsAllowed.insert("jump"); + viewElementsAllowed.insert("message"); +} + +string cTemplateViewReplay::GetViewElementName(eViewElement ve) { + string name; + switch (ve) { + case veBackground: + name = "Background"; + break; + case veDateTime: + name = "DateTime"; + break; + case veRecTitle: + name = "Recording Title"; + break; + case veRecInfo: + name = "Recording Information"; + break; + case veRecCurrent: + name = "Recording current Time"; + break; + case veRecTotal: + name = "Recording total Time"; + break; + case veRecProgressBar: + name = "Rec Progress Bar"; + break; + case veCuttingMarks: + name = "Cutting Marks"; + break; + case veControlIcons: + name = "Control Icons"; + break; + case veControlIconsModeOnly: + name = "Control Icons Mode only"; + break; + case veBackgroundModeOnly: + name = "Background Mode only"; + break; + case veRecJump: + name = "Recording Jump"; + break; + case veScraperContent: + name = "Scraper Content"; + break; + default: + name = "Unknown"; + break; + }; + return name; +} + +void cTemplateViewReplay::AddPixmap(string sViewElement, cTemplatePixmap *pix, bool debugViewElement) { + eViewElement ve = veUndefined; + + if (!sViewElement.compare("background")) { + ve = veBackground; + } else if (!sViewElement.compare("datetime")) { + ve = veDateTime; + } else if (!sViewElement.compare("rectitle")) { + ve = veRecTitle; + } else if (!sViewElement.compare("recinfo")) { + ve = veRecInfo; + } else if (!sViewElement.compare("scrapercontent")) { + ve = veScraperContent; + } else if (!sViewElement.compare("currenttime")) { + ve = veRecCurrent; + } else if (!sViewElement.compare("totaltime")) { + ve = veRecTotal; + } else if (!sViewElement.compare("progressbar")) { + ve = veRecProgressBar; + } else if (!sViewElement.compare("cutmarks")) { + ve = veCuttingMarks; + } else if (!sViewElement.compare("controlicons")) { + ve = veControlIcons; + } else if (!sViewElement.compare("controliconsmodeonly")) { + ve = veControlIconsModeOnly; + } else if (!sViewElement.compare("backgroundmodeonly")) { + ve = veBackgroundModeOnly; + } else if (!sViewElement.compare("jump")) { + ve = veRecJump; + } else if (!sViewElement.compare("message")) { + ve = veMessage; + } + + if (ve == veUndefined) { + esyslog("skindesigner: unknown ViewElement in displayreplay: %s", sViewElement.c_str()); + return; + } + + pix->SetGlobals(globals); + + map < eViewElement, cTemplateViewElement* >::iterator hit = viewElements.find(ve); + if (hit == viewElements.end()) { + cTemplateViewElement *viewElement = new cTemplateViewElement(); + viewElement->AddPixmap(pix); + viewElements.insert(pair< eViewElement, cTemplateViewElement*>(ve, viewElement)); + if (debugViewElement) + viewElement->ActivateDebugTokens(); + } else { + (hit->second)->AddPixmap(pix); + } +} + + +/************************************************************************************ +* cTemplateViewVolume +************************************************************************************/ + +cTemplateViewVolume::cTemplateViewVolume(void) { + + viewName = "displayvolume"; + //definition of allowed parameters for class itself + set attributes; + attributes.insert("x"); + attributes.insert("y"); + attributes.insert("width"); + attributes.insert("height"); + attributes.insert("fadetime"); + attributes.insert("scaletvx"); + attributes.insert("scaletvy"); + attributes.insert("scaletvwidth"); + attributes.insert("scaletvheight"); + funcsAllowed.insert(pair< string, set >(viewName, attributes)); + + SetViewElements(); +} + +cTemplateViewVolume::~cTemplateViewVolume() { +} + +void cTemplateViewVolume::SetViewElements(void) { + viewElementsAllowed.insert("background"); + viewElementsAllowed.insert("volume"); +} + +string cTemplateViewVolume::GetViewElementName(eViewElement ve) { + string name; + switch (ve) { + case veBackground: + name = "Background"; + break; + case veVolume: + name = "Volume"; + break; + default: + name = "Unknown"; + break; + }; + return name; +} + +void cTemplateViewVolume::AddPixmap(string sViewElement, cTemplatePixmap *pix, bool debugViewElement) { + eViewElement ve = veUndefined; + + if (!sViewElement.compare("background")) { + ve = veBackground; + } else if (!sViewElement.compare("volume")) { + ve = veVolume; + } + + if (ve == veUndefined) { + esyslog("skindesigner: unknown ViewElement in displayvolume: %s", sViewElement.c_str()); + return; + } + + pix->SetGlobals(globals); + + map < eViewElement, cTemplateViewElement* >::iterator hit = viewElements.find(ve); + if (hit == viewElements.end()) { + cTemplateViewElement *viewElement = new cTemplateViewElement(); + viewElement->AddPixmap(pix); + viewElements.insert(pair< eViewElement, cTemplateViewElement*>(ve, viewElement)); + if (debugViewElement) + viewElement->ActivateDebugTokens(); + } else { + (hit->second)->AddPixmap(pix); + } +} + +/************************************************************************************ +* cTemplateViewAudioTracks +************************************************************************************/ + +cTemplateViewAudioTracks::cTemplateViewAudioTracks(void) { + + viewName = "displayaudiotracks"; + //definition of allowed parameters for class itself + set attributes; + attributes.insert("x"); + attributes.insert("y"); + attributes.insert("width"); + attributes.insert("height"); + attributes.insert("fadetime"); + attributes.insert("scaletvx"); + attributes.insert("scaletvy"); + attributes.insert("scaletvwidth"); + attributes.insert("scaletvheight"); + funcsAllowed.insert(pair< string, set >(viewName, attributes)); + + //definition of allowed parameters for menuitems viewlist + attributes.clear(); + attributes.insert("x"); + attributes.insert("y"); + attributes.insert("width"); + attributes.insert("height"); + attributes.insert("orientation"); + attributes.insert("align"); + attributes.insert("menuitemwidth"); + attributes.insert("numlistelements"); + funcsAllowed.insert(pair< string, set >("menuitems", attributes)); + + SetViewElements(); + SetViewLists(); +} + +cTemplateViewAudioTracks::~cTemplateViewAudioTracks() { +} + +void cTemplateViewAudioTracks::SetViewElements(void) { + viewElementsAllowed.insert("background"); + viewElementsAllowed.insert("header"); +} + +void cTemplateViewAudioTracks::SetViewLists(void) { + viewListsAllowed.insert("menuitems"); +} + +string cTemplateViewAudioTracks::GetViewElementName(eViewElement ve) { + string name; + switch (ve) { + case veBackground: + name = "Background"; + break; + case veHeader: + name = "Header"; + break; + default: + name = "Unknown"; + break; + }; + return name; +} + +string cTemplateViewAudioTracks::GetViewListName(eViewList vl) { + string name; + switch (vl) { + case vlMenuItem: + name = "Menu Item"; + break; + default: + name = "Unknown"; + break; + }; + return name; +} + +void cTemplateViewAudioTracks::AddPixmap(string sViewElement, cTemplatePixmap *pix, bool debugViewElement) { + eViewElement ve = veUndefined; + + if (!sViewElement.compare("background")) { + ve = veBackground; + } else if(!sViewElement.compare("header")) { + ve = veHeader; + } + + if (ve == veUndefined) { + esyslog("skindesigner: unknown ViewElement in displayaudiotracks: %s", sViewElement.c_str()); + return; + } + + pix->SetGlobals(globals); + + map < eViewElement, cTemplateViewElement* >::iterator hit = viewElements.find(ve); + if (hit == viewElements.end()) { + cTemplateViewElement *viewElement = new cTemplateViewElement(); + viewElement->AddPixmap(pix); + viewElements.insert(pair< eViewElement, cTemplateViewElement*>(ve, viewElement)); + if (debugViewElement) + viewElement->ActivateDebugTokens(); + } else { + (hit->second)->AddPixmap(pix); + } +} + +void cTemplateViewAudioTracks::AddViewList(string sViewList, cTemplateViewList *viewList) { + + eViewList vl = vlUndefined; + if (!sViewList.compare("menuitems")) { + vl = vlMenuItem; + } + + if (vl == vlUndefined) { + esyslog("skindesigner: unknown ViewList in displaymenu: %s", sViewList.c_str()); + return; + } + + viewList->SetGlobals(globals); + viewLists.insert(pair< eViewList, cTemplateViewList*>(vl, viewList)); +} diff --git a/libtemplate/templateview.h b/libtemplate/templateview.h new file mode 100644 index 0000000..414deaa --- /dev/null +++ b/libtemplate/templateview.h @@ -0,0 +1,198 @@ +#ifndef __TEMPLATEVIEW_H +#define __TEMPLATEVIEW_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "templateviewelement.h" +#include "templateviewlist.h" +#include "templatepixmap.h" +#include "templateviewtab.h" +#include "templatefunction.h" + +using namespace std; + +// --- cTemplateView ------------------------------------------------------------- + +enum eSubView { + svUndefined, + svMenuDefault, + svMenuMain, + svMenuSetup, + svMenuSchedules, + svMenuTimers, + svMenuRecordings, + svMenuChannels, + svMenuDetailedEpg, + svMenuDetailedRecording, + svMenuDetailedText +}; + +class cTemplateView { +private: +protected: + cGlobals *globals; + //view parameters + string viewName; + cTemplateFunction *parameters; + int containerX; + int containerY; + int containerWidth; + int containerHeight; + //basic view data structures + map < eViewElement, cTemplateViewElement* > viewElements; + map < eViewList, cTemplateViewList* > viewLists; + map < eSubView, cTemplateView* > subViews; + vector< cTemplateViewTab* > viewTabs; + //helpers to iterate data structures + map < eViewElement, cTemplateViewElement* >::iterator veIt; + map < eViewList, cTemplateViewList* >::iterator vlIt; + map < eSubView, cTemplateView* >::iterator svIt; + vector< cTemplateViewTab* >::iterator vtIt; + //helpers to check valid xml templates + set subViewsAllowed; + set viewElementsAllowed; + set viewListsAllowed; + map < string, set < string > > funcsAllowed; + void SetFunctionDefinitions(void); +public: + cTemplateView(void); + virtual ~cTemplateView(void); + virtual string GetSubViewName(eSubView sv) { return ""; }; + virtual string GetViewElementName(eViewElement ve) { return ""; }; + virtual string GetViewListName(eViewList vl) { return ""; }; + virtual void AddSubView(string sSubView, cTemplateView *subView) {}; + virtual void AddPixmap(string sViewElement, cTemplatePixmap *pix, bool debugViewElement) {}; + virtual void AddViewList(string sViewList, cTemplateViewList *viewList) {}; + virtual void AddViewTab(cTemplateViewTab *viewTab) {}; + //Setter Functions + void SetGlobals(cGlobals *globals) { this->globals = globals; }; + void SetParameters(vector > ¶ms); + void SetContainer(int x, int y, int width, int height); + //access view elements + cTemplateViewElement *GetViewElement(eViewElement ve); + void InitViewElementIterator(void); + cTemplateViewElement *GetNextViewElement(void); + //access list elements + cTemplateViewList *GetViewList(eViewList vl); + void InitViewListIterator(void); + cTemplateViewList *GetNextViewList(void); + //access tabs + void InitViewTabIterator(void); + cTemplateViewTab *GetNextViewTab(void); + //access sub views + cTemplateView *GetSubView(eSubView sv); + void InitSubViewIterator(void); + cTemplateView *GetNextSubView(void); + //Getter Functions + const char *GetViewName(void) { return viewName.c_str(); }; + int GetNumericParameter(eParamType type); + cRect GetOsdSize(void); + int GetNumPixmaps(void); + int GetNumPixmapsViewElement(eViewElement ve); + int GetNumListViewMenuItems(void); + bool GetScalingWindow(cRect &scalingWindow); + //Checks for parsing template XML files + bool ValidSubView(const char *subView); + bool ValidViewElement(const char *viewElement); + bool ValidViewList(const char *viewList); + bool ValidFunction(const char *func); + bool ValidAttribute(const char *func, const char *att); + //Caching + void Translate(void); + void PreCache(bool isSubview); + //Debug + void Debug(void); +}; + +// --- cTemplateViewChannel ------------------------------------------------------------- + +class cTemplateViewChannel : public cTemplateView { +private: + void SetViewElements(void); + void SetViewLists(void); +public: + cTemplateViewChannel(void); + virtual ~cTemplateViewChannel(void); + string GetViewElementName(eViewElement ve); + void AddPixmap(string viewElement, cTemplatePixmap *pix, bool debugViewElement); +}; + +// --- cTemplateViewMenu ------------------------------------------------------------- + +class cTemplateViewMenu : public cTemplateView { +private: + void SetSubViews(void); + void SetViewElements(void); + void SetViewLists(void); +public: + cTemplateViewMenu(void); + virtual ~cTemplateViewMenu(void); + string GetSubViewName(eSubView sv); + string GetViewElementName(eViewElement ve); + string GetViewListName(eViewList vl); + void AddSubView(string sSubView, cTemplateView *subView); + void AddPixmap(string viewElement, cTemplatePixmap *pix, bool debugViewElement); + void AddViewList(string sViewList, cTemplateViewList *viewList); + void AddViewTab(cTemplateViewTab *viewTab); +}; + +// --- cTemplateViewMessage ------------------------------------------------------------- + +class cTemplateViewMessage : public cTemplateView { +private: + void SetViewElements(void); +public: + cTemplateViewMessage(void); + virtual ~cTemplateViewMessage(void); + string GetViewElementName(eViewElement ve); + void AddPixmap(string viewElement, cTemplatePixmap *pix, bool debugViewElement); +}; + +// --- cTemplateViewReplay ------------------------------------------------------------- + +class cTemplateViewReplay : public cTemplateView { +private: + void SetViewElements(void); +public: + cTemplateViewReplay(void); + virtual ~cTemplateViewReplay(void); + string GetViewElementName(eViewElement ve); + void AddPixmap(string viewElement, cTemplatePixmap *pix, bool debugViewElement); +}; + +// --- cTemplateViewVolume ------------------------------------------------------------- + +class cTemplateViewVolume : public cTemplateView { +private: + void SetViewElements(void); +public: + cTemplateViewVolume(void); + virtual ~cTemplateViewVolume(void); + string GetViewElementName(eViewElement ve); + void AddPixmap(string viewElement, cTemplatePixmap *pix, bool debugViewElement); +}; + +// --- cTemplateViewAudioTracks ------------------------------------------------------------- + +class cTemplateViewAudioTracks : public cTemplateView { +private: + void SetViewElements(void); + void SetViewLists(void); +public: + cTemplateViewAudioTracks(void); + virtual ~cTemplateViewAudioTracks(void); + string GetViewElementName(eViewElement ve); + string GetViewListName(eViewList vl); + void AddPixmap(string viewElement, cTemplatePixmap *pix, bool debugViewElement); + void AddViewList(string sViewList, cTemplateViewList *viewList); +}; + +#endif //__TEMPLATEVIEW_H diff --git a/libtemplate/templateviewelement.c b/libtemplate/templateviewelement.c new file mode 100644 index 0000000..87aeade --- /dev/null +++ b/libtemplate/templateviewelement.c @@ -0,0 +1,128 @@ +#include "templateviewelement.h" +#include "../config.h" + +cTemplateViewElement::cTemplateViewElement(void) { + debugTokens = false; + parameters = NULL; + containerX = 0; + containerY = 0; + containerWidth = 0; + containerHeight = 0; + pixOffset = -1; +} + +cTemplateViewElement::~cTemplateViewElement(void) { + if (parameters) + delete parameters; + for (vector::iterator it = viewPixmaps.begin(); it != viewPixmaps.end(); it++) { + delete (*it); + } +} + +void cTemplateViewElement::SetContainer(int x, int y, int width, int height) { + containerX = x; + containerY = y; + containerWidth = width; + containerHeight = height; +} + +void cTemplateViewElement::SetGlobals(cGlobals *globals) { + this->globals = globals; + for (vector::iterator pix = viewPixmaps.begin(); pix != viewPixmaps.end(); pix++) { + (*pix)->SetGlobals(globals); + } +} + +void cTemplateViewElement::SetParameters(vector > ¶ms) { + parameters = new cTemplateFunction(ftViewElement); + parameters->SetGlobals(globals); + parameters->SetParameters(params); +} + +bool cTemplateViewElement::CalculateParameters(void) { + if (!parameters) + return true; + bool paramsValid = true; + parameters->SetContainer(containerX, containerY, containerWidth, containerHeight); + parameters->SetGlobals(globals); + paramsValid = parameters->CalculateParameters(); + + return paramsValid; +} + +bool cTemplateViewElement::CalculatePixmapParameters(void) { + bool paramsValid = true; + for (vector::iterator pix = viewPixmaps.begin(); pix != viewPixmaps.end(); pix++) { + (*pix)->SetContainer(containerX, containerY, containerWidth, containerHeight); + (*pix)->SetGlobals(globals); + paramsValid = paramsValid && (*pix)->CalculateParameters(); + } + return paramsValid; +} + +bool cTemplateViewElement::CalculatePixmapParametersList(int orientation, int numElements) { + bool paramsValid = true; + for (vector::iterator pix = viewPixmaps.begin(); pix != viewPixmaps.end(); pix++) { + (*pix)->SetContainer(containerX, containerY, containerWidth, containerHeight); + (*pix)->SetGlobals(globals); + if (orientation == orHorizontal) { + if (numElements > 0) { + int width = containerWidth / numElements; + (*pix)->SetWidth(width); + } + } else if (orientation == orVertical) { + if (numElements > 0) { + int height = containerHeight / numElements; + (*pix)->SetHeight(height); + } + } + paramsValid = paramsValid && (*pix)->CalculateParameters(); + } + return paramsValid; +} + +int cTemplateViewElement::GetNumericParameter(eParamType type) { + if (!parameters) + return -1; + return parameters->GetNumericParameter(type); +} + +void cTemplateViewElement::InitIterator(void) { + pixIterator = viewPixmaps.begin(); +} + +cTemplatePixmap *cTemplateViewElement::GetNextPixmap(void) { + if (pixIterator == viewPixmaps.end()) + return NULL; + cTemplatePixmap *pix = *pixIterator; + pixIterator++; + return pix; +} + +cTemplateFunction *cTemplateViewElement::GetFunction(string name) { + InitIterator(); + cTemplatePixmap *pix = NULL; + while (pix = GetNextPixmap()) { + pix->InitIterator(); + cTemplateFunction *func = NULL; + while(func = pix->GetNextFunction()) { + if (func->GetType() == ftDrawText) { + string funcName = func->GetParameter(ptName); + if (!funcName.compare(name)) + return func; + } else { + continue; + } + } + } + return NULL; +} + +void cTemplateViewElement::Debug(void) { + esyslog("skindesigner: viewelement container size x: %d, y: %d, width: %d, height %d", containerX, containerY, containerWidth, containerHeight); + if (parameters) + parameters->Debug(); + for (vector::iterator it = viewPixmaps.begin(); it != viewPixmaps.end(); it++) { + (*it)->Debug(); + } +} \ No newline at end of file diff --git a/libtemplate/templateviewelement.h b/libtemplate/templateviewelement.h new file mode 100644 index 0000000..84db627 --- /dev/null +++ b/libtemplate/templateviewelement.h @@ -0,0 +1,99 @@ +#ifndef __TEMPLATEVIEWELEMENT_H +#define __TEMPLATEVIEWELEMENT_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "templatepixmap.h" +#include "templatefunction.h" + +using namespace std; + +// --- cTemplateViewElement ------------------------------------------------------------- + +enum eViewElement { + //Common ViewElements + veUndefined, + veBackground, + veDateTime, + veMessage, + //DisplayChannel ViewElements + veChannelInfo, + veChannelGroup, + veEpgInfo, + veProgressBar, + veProgressBarBack, + veStatusInfo, + veScreenResolution, + veSignalQuality, + veSignalQualityBack, + veScraperContent, + //DisplayMenu ViewElements + veHeader, + veButtons, + veDiscUsage, + veSystemLoad, + veTimers, + veDevices, + veMenuItem, + veMenuCurrentItemDetail, + veScrollbar, + veDetailHeader, + veTabLabels, + //DisplayReplay ViewElements + veRecTitle, + veRecInfo, + veRecCurrent, + veRecTotal, + veRecProgressBar, + veCuttingMarks, + veControlIcons, + veControlIconsModeOnly, + veBackgroundModeOnly, + veRecJump, + //DisplayVolume ViewElements + veVolume +}; + +class cTemplateViewElement { +protected: + bool debugTokens; + cGlobals *globals; + cTemplateFunction *parameters; + int containerX; + int containerY; + int containerWidth; + int containerHeight; + vector viewPixmaps; + vector::iterator pixIterator; + int pixOffset; +public: + cTemplateViewElement(void); + virtual ~cTemplateViewElement(void); + void SetParameters(vector > ¶ms); + bool CalculateParameters(void); + bool CalculatePixmapParameters(void); + bool CalculatePixmapParametersList(int orientation, int numElements); + int GetNumericParameter(eParamType type); + void AddPixmap(cTemplatePixmap *pix) { viewPixmaps.push_back(pix); }; + virtual void SetGlobals(cGlobals *globals); + void SetContainer(int x, int y, int width, int height); + void SetPixOffset(int offset) { pixOffset = offset; }; + int GetPixOffset(void) { return pixOffset; }; + virtual int GetNumPixmaps(void) { return viewPixmaps.size(); }; + void InitIterator(void); + cTemplatePixmap *GetNextPixmap(void); + cTemplateFunction *GetFunction(string name); + void ActivateDebugTokens(void) {debugTokens = true; }; + bool DebugTokens(void) { return debugTokens; }; + virtual void Debug(void); +}; + +#endif //__TEMPLATEVIEWELEMENT_H \ No newline at end of file diff --git a/libtemplate/templateviewlist.c b/libtemplate/templateviewlist.c new file mode 100644 index 0000000..808a89f --- /dev/null +++ b/libtemplate/templateviewlist.c @@ -0,0 +1,138 @@ +#include "templateviewlist.h" +#include "../config.h" + +cTemplateViewList::cTemplateViewList(void) : cTemplateViewElement() { + listElement = NULL; + currentElement = NULL; +} + +cTemplateViewList::~cTemplateViewList(void) { + if (listElement) + delete listElement; + if (currentElement) + delete currentElement; +} + +void cTemplateViewList::SetGlobals(cGlobals *globals) { + cTemplateViewElement::SetGlobals(globals); + if (listElement) + listElement->SetGlobals(globals); + if (currentElement) + currentElement->SetGlobals(globals); +} + +bool cTemplateViewList::CalculateListParameters(void) { + if (!parameters) + return false; + parameters->SetContainer(containerX, containerY, containerWidth, containerHeight); + parameters->SetGlobals(globals); + bool paramsValid = parameters->CalculateParameters(); + if (!listElement) + return false; + listElement->SetContainer(parameters->GetNumericParameter(ptX), + parameters->GetNumericParameter(ptY), + parameters->GetNumericParameter(ptWidth), + parameters->GetNumericParameter(ptHeight)); + paramsValid = listElement->CalculateParameters(); + paramsValid = listElement->CalculatePixmapParametersList(parameters->GetNumericParameter(ptOrientation), + parameters->GetNumericParameter(ptNumElements)); + if (!currentElement) + return paramsValid; + currentElement->SetContainer(parameters->GetNumericParameter(ptX), + parameters->GetNumericParameter(ptY), + parameters->GetNumericParameter(ptWidth), + parameters->GetNumericParameter(ptHeight)); + paramsValid = currentElement->CalculateParameters(); + paramsValid = currentElement->CalculatePixmapParameters(); + currentElement->SetPixOffset(0); + return paramsValid; +} + +bool cTemplateViewList::CalculateListParameters(map < string, int > *intTokens) { + if (!parameters) + return false; + parameters->ClearDynamicParameters(); + parameters->SetIntTokens(intTokens); + parameters->ParseParameters(); + parameters->UnsetIntTokens(); + + listElement->SetContainer(parameters->GetNumericParameter(ptX), + parameters->GetNumericParameter(ptY), + parameters->GetNumericParameter(ptWidth), + parameters->GetNumericParameter(ptHeight)); + bool paramsValid = listElement->CalculateParameters(); + paramsValid = listElement->CalculatePixmapParametersList(parameters->GetNumericParameter(ptOrientation), + parameters->GetNumericParameter(ptNumElements)); + return paramsValid; +} + +int cTemplateViewList::GetAverageFontWidth(void) { + int defaultAverageFontWidth = 20; + + if (!listElement) + return defaultAverageFontWidth; + + int numItems = GetNumericParameter(ptNumElements); + int listHeight = GetNumericParameter(ptHeight); + if (listHeight <= 0) + return defaultAverageFontWidth; + int itemHeight = (double)listHeight / (double)numItems; + string fontFuncName = parameters->GetParameter(ptDeterminateFont); + + cTemplateFunction *fontFunc = listElement->GetFunction(fontFuncName); + if (!fontFunc) + return defaultAverageFontWidth; + + string fontNameToken = fontFunc->GetParameter(ptFont); + string paramFontSize = fontFunc->GetParameter(ptFontSize); + + string fontName = ""; + if ((fontNameToken.find("{") == 0) && (fontNameToken.find("}") == (fontNameToken.size()-1))) { + fontNameToken = fontNameToken.substr(1, fontNameToken.size()-2); + map::iterator hit = globals->fonts.find(fontNameToken); + if (hit != globals->fonts.end()) { + fontName = hit->second; + } else { + map::iterator def = globals->fonts.find("vdrOsd"); + if (def == globals->fonts.end()) + return defaultAverageFontWidth; + fontName = def->second; + } + } else { + //if no token, directly use input + fontName = fontNameToken; + } + + cNumericParameter pFontSize(paramFontSize); + pFontSize.SetGlobals(globals); + pFontSize.SetAreaSize(1000, itemHeight); + pFontSize.SetVertical(); + int fontSize = pFontSize.Parse(paramFontSize); + if (!pFontSize.Valid()) + return defaultAverageFontWidth; + + int averageFontWidth = fontManager->Width(fontName, fontSize, "x") + 3; + return averageFontWidth; +} + +int cTemplateViewList::GetMenuItemWidth(void) { + return GetNumericParameter(ptMenuItemWidth); +} + + +int cTemplateViewList::GetNumPixmaps(void) { + if (!listElement) + return 0; + return listElement->GetNumPixmaps(); +} + +void cTemplateViewList::Debug(void) { + if (parameters) + parameters->Debug(); + esyslog("skindesigner: --- listelement: "); + if (listElement) + listElement->Debug(); + esyslog("skindesigner: --- currentelement: "); + if (currentElement) + currentElement->Debug(); +} \ No newline at end of file diff --git a/libtemplate/templateviewlist.h b/libtemplate/templateviewlist.h new file mode 100644 index 0000000..8998384 --- /dev/null +++ b/libtemplate/templateviewlist.h @@ -0,0 +1,49 @@ +#ifndef __TEMPLATEVIEWLIST_H +#define __TEMPLATEVIEWLIST_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "templateviewelement.h" + +using namespace std; + +// --- cTemplateViewList ------------------------------------------------------------- + +enum eViewList { + vlUndefined, + //DisplayChannel ViewLists + vlDvbDeviceInfoList, + //DisplayMenu ViewLists + vlTimerList, + vlMenuItem +}; + +class cTemplateViewList : public cTemplateViewElement { +private: + cTemplateViewElement *listElement; + cTemplateViewElement *currentElement; +public: + cTemplateViewList(void); + ~cTemplateViewList(void); + void SetGlobals(cGlobals *globals); + void AddListElement(cTemplateViewElement *listElement) { this->listElement = listElement; }; + void AddCurrentElement(cTemplateViewElement *currentElement) { this->currentElement = currentElement; }; + bool CalculateListParameters(void); + bool CalculateListParameters(map < string, int > *intTokens); + cTemplateViewElement *GetListElement(void) { return listElement; }; + cTemplateViewElement *GetListElementCurrent(void) { return currentElement; }; + int GetAverageFontWidth(void); + int GetMenuItemWidth(void); + int GetNumPixmaps(void); + void Debug(void); +}; + +#endif //__TEMPLATEVIEWLIST_H \ No newline at end of file diff --git a/libtemplate/templateviewtab.c b/libtemplate/templateviewtab.c new file mode 100644 index 0000000..1e9f463 --- /dev/null +++ b/libtemplate/templateviewtab.c @@ -0,0 +1,38 @@ +#include "templateviewtab.h" + +cTemplateViewTab::cTemplateViewTab(void) : cTemplatePixmap() { + scrollStep = -1; +} + +cTemplateViewTab::~cTemplateViewTab(void) { +} + +int cTemplateViewTab::GetScrollStep(void) { + if (scrollStep > 0) + return scrollStep; + int pixWidth = GetNumericParameter(ptWidth); + int pixHeight = GetNumericParameter(ptHeight); + string scrollHeight = parameters->GetParameter(ptScrollHeight); + + cNumericParameter p(scrollHeight); + p.SetAreaSize(pixWidth, pixHeight); + string parsedValue = ""; + scrollStep = p.Parse(parsedValue); + if (scrollStep < 1) + scrollStep = 50; + return scrollStep; +} + +string cTemplateViewTab::GetName(void) { + return parameters->GetParameter(ptName); +} + +void cTemplateViewTab::SetName(string trans) { + parameters->SetParameter(ptName, trans); +} + +void cTemplateViewTab::Debug(void) { + esyslog("skindesigner: cTemplateViewTab Debug %s", GetName().c_str()); + cTemplatePixmap::Debug(); + esyslog("skindesigner: -------------------------------------------------------"); +} diff --git a/libtemplate/templateviewtab.h b/libtemplate/templateviewtab.h new file mode 100644 index 0000000..8514cad --- /dev/null +++ b/libtemplate/templateviewtab.h @@ -0,0 +1,31 @@ +#ifndef __TEMPLATEVIEWTAB_H +#define __TEMPLATEVIEWTAB_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "templatepixmap.h" + +using namespace std; + +// --- cTemplateViewTab ------------------------------------------------------------- + +class cTemplateViewTab : public cTemplatePixmap { +private: + int scrollStep; +public: + cTemplateViewTab(void); + ~cTemplateViewTab(void); + int GetScrollStep(void); + string GetName(void); + void SetName(string trans); + void Debug(void); +}; + +#endif //__TEMPLATEVIEWTAB_H \ No newline at end of file diff --git a/libtemplate/xmlparser.c b/libtemplate/xmlparser.c new file mode 100644 index 0000000..f9a723a --- /dev/null +++ b/libtemplate/xmlparser.c @@ -0,0 +1,728 @@ +#include "xmlparser.h" +#include "../config.h" + +using namespace std; + +void SkinDesignerXMLErrorHandler (void * userData, xmlErrorPtr error) { + esyslog("skindesigner: Error in XML: %s", error->message); +} + +cXmlParser::cXmlParser(void) { + doc = NULL; + root = NULL; + ctxt = NULL; + + xmlInitParser(); + initGenericErrorDefaultFunc(NULL); + xmlSetStructuredErrorFunc(NULL, SkinDesignerXMLErrorHandler); + ctxt = xmlNewParserCtxt(); +} + +cXmlParser::~cXmlParser() { + DeleteDocument(); + xmlFreeParserCtxt(ctxt); + xmlCleanupParser(); +} + +/********************************************************************* +* PUBLIC Functions +*********************************************************************/ +bool cXmlParser::ReadView(cTemplateView *view, string xmlFile) { + this->view = view; + + string xmlPath = GetPath(xmlFile); + + if (ctxt == NULL) { + esyslog("skindesigner: Failed to allocate parser context"); + return false; + } + + doc = xmlCtxtReadFile(ctxt, xmlPath.c_str(), NULL, XML_PARSE_NOENT | XML_PARSE_DTDVALID); + + if (doc == NULL) { + esyslog("skindesigner: ERROR: TemplateView %s not parsed successfully.", xmlPath.c_str()); + return false; + } + if (ctxt->valid == 0) { + esyslog("skindesigner: Failed to validate %s", xmlPath.c_str()); + return false; + } + + root = xmlDocGetRootElement(doc); + + if (root == NULL) { + esyslog("skindesigner: ERROR: TemplateView %s is empty", xmlPath.c_str()); + return false; + } + + if (xmlStrcmp(root->name, (const xmlChar *) view->GetViewName())) { + return false; + } + return true; +} + +bool cXmlParser::ReadGlobals(cGlobals *globals, string xmlFile) { + this->globals = globals; + + string xmlPath = GetPath(xmlFile); + + if (ctxt == NULL) { + esyslog("skindesigner: Failed to allocate parser context"); + return false; + } + + doc = xmlCtxtReadFile(ctxt, xmlPath.c_str(), NULL, XML_PARSE_NOENT | XML_PARSE_DTDVALID); + + if (doc == NULL ) { + esyslog("skindesigner: ERROR: Globals %s not parsed successfully.", xmlPath.c_str()); + return false; + } + + root = xmlDocGetRootElement(doc); + + if (ctxt->valid == 0) { + esyslog("skindesigner: Failed to validate %s", xmlPath.c_str()); + return false; + } + + if (root == NULL) { + esyslog("skindesigner: ERROR: Globals %s is empty", xmlPath.c_str()); + return false; + } + + if (xmlStrcmp(root->name, (const xmlChar *) "globals")) { + return false; + } + return true; +} + +bool cXmlParser::ParseView(void) { + vector > rootAttribs; + ParseAttributes(root->properties, root, rootAttribs); + + if (!view) + return false; + + view->SetParameters(rootAttribs); + + xmlNodePtr node = root->xmlChildrenNode; + + while (node != NULL) { + + if (node->type != XML_ELEMENT_NODE) { + node = node->next; + continue; + } + + if (view->ValidSubView((const char*)node->name)) { + ParseSubView(node); + } else if (view->ValidViewElement((const char*)node->name)) { + bool debugViewElement = DebugViewElement(node); + ParseViewElement(node->name, node->xmlChildrenNode, debugViewElement); + } else if (view->ValidViewList((const char*)node->name)) { + ParseViewList(node); + } else { + return false; + } + + node = node->next; + } + + return true; + +} + +bool cXmlParser::ParseGlobals(void) { + xmlNodePtr node = root->xmlChildrenNode; + + while (node != NULL) { + if (node->type != XML_ELEMENT_NODE) { + node = node->next; + continue; + } + if (!xmlStrcmp(node->name, (const xmlChar *) "colors")) { + ParseGlobalColors(node->xmlChildrenNode); + node = node->next; + continue; + } else if (!xmlStrcmp(node->name, (const xmlChar *) "variables")) { + ParseGlobalVariables(node->xmlChildrenNode); + node = node->next; + continue; + } else if (!xmlStrcmp(node->name, (const xmlChar *) "fonts")) { + ParseGlobalFonts(node->xmlChildrenNode); + node = node->next; + continue; + } else if (!xmlStrcmp(node->name, (const xmlChar *) "translations")) { + ParseTranslations(node->xmlChildrenNode); + node = node->next; + continue; + } + node = node->next; + } + + return true; + +} + +void cXmlParser::DeleteDocument(void) { + if (doc) { + xmlFreeDoc(doc); + doc = NULL; + } +} + +/********************************************************************* +* PRIVATE Functions +*********************************************************************/ + +string cXmlParser::GetPath(string xmlFile) { + return *cString::sprintf("%s%s/xmlfiles/%s", *config.skinPath, Setup.OSDTheme, xmlFile.c_str()); +} + +void cXmlParser::ParseGlobalColors(xmlNodePtr node) { + if (!node) + return; + + while (node != NULL) { + + if (node->type != XML_ELEMENT_NODE) { + node = node->next; + continue; + } + if (xmlStrcmp(node->name, (const xmlChar *) "color")) { + node = node->next; + continue; + } + xmlAttrPtr attr = node->properties; + if (attr == NULL) { + node = node->next; + continue; + } + xmlChar *colName = NULL; + xmlChar *colValue = NULL; + bool ok = false; + while (NULL != attr) { + if (xmlStrcmp(attr->name, (const xmlChar *) "name")) { + attr = attr->next; + continue; + } + ok = true; + colName = xmlGetProp(node, attr->name); + attr = attr->next; + } + if (ok) { + colValue = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); + if (colName && colValue) + InsertColor((const char*)colName, (const char*)colValue); + } + if (colName) + xmlFree(colName); + if (colValue) + xmlFree(colValue); + node = node->next; + } +} + +void cXmlParser::InsertColor(string name, string value) { + if (value.size() != 8) + return; + std::stringstream str; + str << value; + tColor colVal; + str >> std::hex >> colVal; + globals->colors.insert(pair(name, colVal)); +} + +void cXmlParser::ParseGlobalVariables(xmlNodePtr node) { + if (!node) + return; + + while (node != NULL) { + + if (node->type != XML_ELEMENT_NODE) { + node = node->next; + continue; + } + if (xmlStrcmp(node->name, (const xmlChar *) "var")) { + node = node->next; + continue; + } + xmlAttrPtr attr = node->properties; + if (attr == NULL) { + node = node->next; + continue; + } + xmlChar *varName = NULL; + xmlChar *varType = NULL; + xmlChar *varValue = NULL; + while (NULL != attr) { + if (!xmlStrcmp(attr->name, (const xmlChar *) "name")) { + varName = xmlGetProp(node, attr->name); + } else if (!xmlStrcmp(attr->name, (const xmlChar *) "type")) { + varType = xmlGetProp(node, attr->name); + } else { + attr = attr->next; + continue; + } + attr = attr->next; + } + varValue = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); + if (varName && varType && varValue) + InsertVariable((const char*)varName, (const char*)varType, (const char*)varValue); + if (varName) + xmlFree(varName); + if (varType) + xmlFree(varType); + if (varValue) + xmlFree(varValue); + node = node->next; + } +} + +void cXmlParser::InsertVariable(string name, string type, string value) { + if (!type.compare("int")) { + int val = atoi(value.c_str()); + globals->intVars.insert(pair(name, val)); + } else if (!type.compare("string")) { + globals->stringVars.insert(pair(name, value)); + } +} + +void cXmlParser::ParseGlobalFonts(xmlNodePtr node) { + if (!node) + return; + + while (node != NULL) { + + if (node->type != XML_ELEMENT_NODE) { + node = node->next; + continue; + } + if (xmlStrcmp(node->name, (const xmlChar *) "font")) { + node = node->next; + continue; + } + xmlAttrPtr attr = node->properties; + if (attr == NULL) { + node = node->next; + continue; + } + xmlChar *fontName = NULL; + xmlChar *fontValue = NULL; + bool ok = false; + while (NULL != attr) { + if (xmlStrcmp(attr->name, (const xmlChar *) "name")) { + attr = attr->next; + continue; + } + ok = true; + fontName = xmlGetProp(node, attr->name); + attr = attr->next; + } + if (ok) { + fontValue = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); + if (fontName && fontValue) + globals->fonts.insert(pair((const char*)fontName, (const char*)fontValue)); + } + if (fontName) + xmlFree(fontName); + if (fontValue) + xmlFree(fontValue); + node = node->next; + } +} + +void cXmlParser::ParseTranslations(xmlNodePtr node) { + if (!node) + return; + + while (node != NULL) { + + if (node->type != XML_ELEMENT_NODE) { + node = node->next; + continue; + } + if (xmlStrcmp(node->name, (const xmlChar *) "token")) { + node = node->next; + continue; + } + xmlAttrPtr attr = node->properties; + if (attr == NULL) { + node = node->next; + continue; + } + xmlChar *tokenName; + bool ok = false; + while (NULL != attr) { + if (xmlStrcmp(attr->name, (const xmlChar *) "name")) { + attr = attr->next; + continue; + } + ok = true; + tokenName = xmlGetProp(node, attr->name); + attr = attr->next; + } + if (!ok) + continue; + map < string, string > tokenTranslations; + xmlNodePtr nodeTrans = node->xmlChildrenNode; + while (nodeTrans != NULL) { + if (nodeTrans->type != XML_ELEMENT_NODE) { + nodeTrans = nodeTrans->next; + continue; + } + xmlChar *language = NULL; + if (xmlStrcmp(nodeTrans->name, (const xmlChar *) "trans")) { + nodeTrans = nodeTrans->next; + continue; + } + xmlAttrPtr attrTrans = nodeTrans->properties; + if (attrTrans == NULL) { + nodeTrans = nodeTrans->next; + continue; + } + ok = false; + + while (NULL != attrTrans) { + if (!ok && xmlStrcmp(attrTrans->name, (const xmlChar *) "lang")) { + attrTrans = attrTrans->next; + continue; + } + ok = true; + language = xmlGetProp(nodeTrans, attrTrans->name); + attrTrans = attrTrans->next; + } + if (!ok) + continue; + xmlChar *value = NULL; + value = xmlNodeListGetString(doc, nodeTrans->xmlChildrenNode, 1); + if (language && value) + tokenTranslations.insert(pair((const char*)language, (const char*)value)); + if (language) + xmlFree(language); + if (value) + xmlFree(value); + nodeTrans = nodeTrans->next; + } + globals->translations.insert(pair >((const char*)tokenName, tokenTranslations)); + xmlFree(tokenName); + node = node->next; + } +} + +bool cXmlParser::ParseSubView(xmlNodePtr node) { + if (!node) + return false; + + if (!view) + return false; + + cTemplateView *subView = new cTemplateViewMenu(); + view->AddSubView((const char*)node->name, subView); + + vector > subViewAttribs; + ParseAttributes(node->properties, node, subViewAttribs); + + subView->SetParameters(subViewAttribs); + + xmlNodePtr childNode = node->xmlChildrenNode; + + while (childNode != NULL) { + + if (childNode->type != XML_ELEMENT_NODE) { + childNode = childNode->next; + continue; + } + + if (subView->ValidViewElement((const char*)childNode->name)) { + bool debugViewElement = DebugViewElement(childNode); + ParseViewElement(childNode->name, childNode->xmlChildrenNode, debugViewElement, subView); + } else if (subView->ValidViewList((const char*)childNode->name)) { + ParseViewList(childNode, subView); + } else if (!xmlStrcmp(childNode->name, (const xmlChar *) "tab")) { + ParseViewTab(childNode, subView); + } else { + return false; + } + + childNode = childNode->next; + } + + + + return true; + +} + +void cXmlParser::ParseViewElement(const xmlChar * viewElement, xmlNodePtr node, bool debugVE, cTemplateView *subView) { + if (!node) + return; + + if (!view) + return; + + if (debugVE) { + dsyslog("skindesigner: activating debugging of viewElement %s", (const char*)viewElement); + } + + while (node != NULL) { + + if (node->type != XML_ELEMENT_NODE) { + node = node->next; + continue; + } + + if (xmlStrcmp(node->name, (const xmlChar *) "area") && xmlStrcmp(node->name, (const xmlChar *) "areascroll")) { + esyslog("skindesigner: invalid tag \"%s\"", node->name); + node = node->next; + continue; + } + + xmlAttrPtr attr = node->properties; + vector > attribs; + ParseAttributes(attr, node, attribs); + + cTemplatePixmap *pix = new cTemplatePixmap(); + if (!xmlStrcmp(node->name, (const xmlChar *) "areascroll")) { + pix->SetScrolling(); + } + pix->SetParameters(attribs); + ParseFunctionCalls(node->xmlChildrenNode, pix); + if (subView) + subView->AddPixmap((const char*)viewElement, pix, debugVE); + else + view->AddPixmap((const char*)viewElement, pix, debugVE); + + node = node->next; + } +} + +void cXmlParser::ParseViewList(xmlNodePtr parentNode, cTemplateView *subView) { + if (!parentNode || !view) + return; + + xmlAttrPtr attr = parentNode->properties; + vector > attribs; + ParseAttributes(attr, parentNode, attribs); + + cTemplateViewList *viewList = new cTemplateViewList(); + viewList->SetGlobals(globals); + viewList->SetParameters(attribs); + + xmlNodePtr node = parentNode->xmlChildrenNode; + + while (node != NULL) { + + if (node->type != XML_ELEMENT_NODE) { + node = node->next; + continue; + } + + if (!xmlStrcmp(node->name, (const xmlChar *) "currentelement")) { + xmlNodePtr childNode = node->xmlChildrenNode; + if (!childNode) + continue; + cTemplateViewElement *currentElement = new cTemplateViewElement(); + xmlAttrPtr attrCur = node->properties; + vector > attribsCur; + ParseAttributes(attrCur, node, attribsCur); + currentElement->SetGlobals(globals); + currentElement->SetParameters(attribsCur); + bool debugCurrent = false; + for (vector >::iterator it = attribsCur.begin(); it != attribsCur.end(); it++) { + if (!(it->first).compare("debug")) { + debugCurrent = true; + break; + } + } + if (debugCurrent) + currentElement->ActivateDebugTokens(); + while (childNode != NULL) { + if (childNode->type != XML_ELEMENT_NODE) { + childNode = childNode->next; + continue; + } + if ((!xmlStrcmp(childNode->name, (const xmlChar *) "area")) || (!xmlStrcmp(childNode->name, (const xmlChar *) "areascroll"))) { + xmlAttrPtr attrPix = childNode->properties; + vector > attribsPix; + ParseAttributes(attrPix, childNode, attribsPix); + cTemplatePixmap *pix = new cTemplatePixmap(); + pix->SetParameters(attribsPix); + ParseFunctionCalls(childNode->xmlChildrenNode, pix); + if (!xmlStrcmp(childNode->name, (const xmlChar *) "areascroll")) { + pix->SetScrolling(); + } + currentElement->AddPixmap(pix); + } + childNode = childNode->next; + } + viewList->AddCurrentElement(currentElement); + } else if (!xmlStrcmp(node->name, (const xmlChar *) "listelement")) { + bool debugViewList = DebugViewElement(node); + xmlNodePtr childNode = node->xmlChildrenNode; + if (!childNode) + continue; + cTemplateViewElement *listElement = new cTemplateViewElement(); + if (debugViewList) + listElement->ActivateDebugTokens(); + while (childNode != NULL) { + if (childNode->type != XML_ELEMENT_NODE) { + childNode = childNode->next; + continue; + } + if ((!xmlStrcmp(childNode->name, (const xmlChar *) "area")) || (!xmlStrcmp(childNode->name, (const xmlChar *) "areascroll"))) { + xmlAttrPtr attrPix = childNode->properties; + vector > attribsPix; + ParseAttributes(attrPix, childNode, attribsPix); + cTemplatePixmap *pix = new cTemplatePixmap(); + pix->SetParameters(attribsPix); + ParseFunctionCalls(childNode->xmlChildrenNode, pix); + if (!xmlStrcmp(childNode->name, (const xmlChar *) "areascroll")) { + pix->SetScrolling(); + } + listElement->AddPixmap(pix); + } + childNode = childNode->next; + } + viewList->AddListElement(listElement); + } else { + node = node->next; + continue; + } + node = node->next; + } + if (subView) + subView->AddViewList((const char*)parentNode->name, viewList); + else + view->AddViewList((const char*)parentNode->name, viewList); +} + +void cXmlParser::ParseViewTab(xmlNodePtr parentNode, cTemplateView *subView) { + if (!parentNode || !view || !subView) + return; + + xmlAttrPtr attr = parentNode->properties; + vector > attribs; + ParseAttributes(attr, parentNode, attribs); + + cTemplateViewTab *viewTab = new cTemplateViewTab(); + viewTab->SetGlobals(globals); + viewTab->SetParameters(attribs); + viewTab->SetScrolling(); + xmlNodePtr node = parentNode->xmlChildrenNode; + ParseFunctionCalls(node, viewTab); + + subView->AddViewTab(viewTab); +} + +void cXmlParser::ParseFunctionCalls(xmlNodePtr node, cTemplatePixmap *pix) { + if (!node) + return; + + if (!view) + return; + + while (node != NULL) { + + if (node->type != XML_ELEMENT_NODE) { + node = node->next; + continue; + } + + if (!xmlStrcmp(node->name, (const xmlChar *) "loop")) { + xmlNodePtr childNode = node->xmlChildrenNode; + if (!childNode) + continue; + xmlAttrPtr attr = node->properties; + vector > attribs; + ParseAttributes(attr, node, attribs); + cTemplateLoopFunction *loopFunc = new cTemplateLoopFunction(); + loopFunc->SetParameters(attribs); + ParseLoopFunctionCalls(childNode, loopFunc); + pix->AddLoopFunction(loopFunc); + node = node->next; + } else if (view->ValidFunction((const char*)node->name)) { + xmlAttrPtr attr = node->properties; + vector > attribs; + ParseAttributes(attr, node, attribs); + pix->AddFunction((const char*)node->name, attribs); + node = node->next; + } else { + node = node->next; + continue; + } + + } +} + +void cXmlParser::ParseLoopFunctionCalls(xmlNodePtr node, cTemplateLoopFunction *loopFunc) { + if (!node) + return; + + if (!view) + return; + + while (node != NULL) { + + if (node->type != XML_ELEMENT_NODE) { + node = node->next; + continue; + } + if (view->ValidFunction((const char*)node->name)) { + xmlAttrPtr attr = node->properties; + vector > attribs; + ParseAttributes(attr, node, attribs); + loopFunc->AddFunction((const char*)node->name, attribs); + node = node->next; + } else { + node = node->next; + continue; + } + + } +} + +bool cXmlParser::ParseAttributes(xmlAttrPtr attr, xmlNodePtr node, vector > &attribs) { + if (attr == NULL) { + return false; + } + + if (!view) + return false; + + while (NULL != attr) { + + string name = (const char*)attr->name; + if (!name.compare("debug")) { + attribs.push_back(pair((const char*)attr->name, "true")); + attr = attr->next; + continue; + } + + xmlChar *value = NULL; + value = xmlGetProp(node, attr->name); + if (!view->ValidAttribute((const char*)node->name, (const char*)attr->name)) { + attr = attr->next; + if (value) + xmlFree(value); + continue; + } + if (value) + attribs.push_back(pair((const char*)attr->name, (const char*)value)); + attr = attr->next; + if (value) + xmlFree(value); + } + return true; +} + +bool cXmlParser::DebugViewElement(xmlNodePtr node) { + xmlAttrPtr attr = node->properties; + vector > attribs; + ParseAttributes(attr, node, attribs); + for (vector >::iterator it = attribs.begin(); it != attribs.end(); it++) { + if (!(it->first).compare("debug")) + return true; + } + return false; +} diff --git a/libtemplate/xmlparser.h b/libtemplate/xmlparser.h new file mode 100644 index 0000000..ecdcca3 --- /dev/null +++ b/libtemplate/xmlparser.h @@ -0,0 +1,56 @@ +#ifndef __XMLPARSER_H +#define __XMLPARSER_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "templateview.h" +#include "templateviewlist.h" +#include "templateviewtab.h" + +using namespace std; + +// --- cXmlParser ------------------------------------------------------------- + +class cXmlParser { +private: + cTemplateView *view; + cGlobals *globals; + xmlParserCtxtPtr ctxt; + xmlDocPtr doc; + xmlNodePtr root; + string GetPath(string xmlFile); + void ParseGlobalColors(xmlNodePtr node); + void InsertColor(string name, string value); + void ParseGlobalVariables(xmlNodePtr node); + void InsertVariable(string name, string type, string value); + void ParseGlobalFonts(xmlNodePtr node); + void ParseTranslations(xmlNodePtr node); + bool ParseSubView(xmlNodePtr node); + void ParseViewElement(const xmlChar * viewElement, xmlNodePtr node, bool debugVE, cTemplateView *subView = NULL); + void ParseViewList(xmlNodePtr parentNode, cTemplateView *subView = NULL); + void ParseViewTab(xmlNodePtr parentNode, cTemplateView *subView); + void ParseFunctionCalls(xmlNodePtr node, cTemplatePixmap *pix); + void ParseLoopFunctionCalls(xmlNodePtr node, cTemplateLoopFunction *loopFunc); + bool ParseAttributes(xmlAttrPtr attr, xmlNodePtr node, vector > &attribs); + bool DebugViewElement(xmlNodePtr node); +public: + cXmlParser(void); + virtual ~cXmlParser(void); + bool ReadView(cTemplateView *view, string xmlFile); + bool ReadGlobals(cGlobals *globals, string xmlFile); + bool ParseView(void); + bool ParseGlobals(void); + void DeleteDocument(void); +}; + +#endif //__XMLPARSER_H \ No newline at end of file diff --git a/services/epgsearch.h b/services/epgsearch.h new file mode 100644 index 0000000..0c38793 --- /dev/null +++ b/services/epgsearch.h @@ -0,0 +1,167 @@ +/* +Copyright (C) 2004-2007 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 + +// Added by Andreas Mair (mail _AT_ andreas _DOT_ vdr-developer _DOT_ org) +#define EPGSEARCH_SEARCHRESULTS_SERVICE_STRING_ID "Epgsearch-searchresults-v1.0" +#define EPGSEARCH_LASTCONFLICTINFO_SERVICE_STRING_ID "Epgsearch-lastconflictinfo-v1.0" + +#include +#include +#include +#include +#include + +// 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* 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 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 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 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 ExtEPGInfoList() = 0; + // returns a list of extended EPG categories in the same format as used in epgsearchcats.conf + virtual std::list ChanGrpList() = 0; + // returns a list of channel groups maintained by epgsearch + virtual std::list BlackList() = 0; + // returns a list of blacklists in the same format as used in epgsearchblacklists.conf + virtual std::set 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 handler; +}; + +#endif diff --git a/services/remotetimers.h b/services/remotetimers.h new file mode 100644 index 0000000..2dc8a97 --- /dev/null +++ b/services/remotetimers.h @@ -0,0 +1,141 @@ +/* + * remotetimers.h: Public interface of the plugin's services + * + * Copyright (C) 2008-2011 Frank Schmirler + * + * This file is part of VDR Plugin remotetimers. + * + * 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 + */ + +#ifndef _SERVICE__H +#define _SERVICE__H + +#ifndef __TIMERS_H +#include +#include +#endif + +/* + * If the Data argument is NULL, all service calls return true. + * Otherwise the return value indicates success or failure of the service call. + * + * The service calls are not thread safe and must be called from the VDR main loop. + */ + +/* + * RemoteTimers::InstantRecording-v1.0 + * Start an instant recording or pause live TV. VDR needs to be patched to support this. + * The service returns false if a local timer should be used. An error occured if true is returned but the out parameters name and fileName are NULL. + * Data points to the following structure where pause indicates if it is an instant recording or an attempt to pause live TV. + */ + +struct RemoteTimers_InstantRecording_v1_0 { +//in + const cTimer *timer; + bool pause; + const cEvent *event; +//out + cString name; + cString fileName; +}; + +/* + * RemoteTimers::RefreshTimers-v1.0 + * Fetch timer list from remote VDR. You must call this service before you can use one of the service calls below. + * Data points to a cString which in case of failure (service call returns false) contains an error message. + */ + +//out +// cString errorMsg; + +/* + * RemoteTimers::ForEach-v1.0 + * Iterates the list of remote timers. + * The service call always returns true. + * Data points to a cTimer* which must be NULL to return the first timer. Pass the previously returned timer to get the next one until cTimer* is NULL. + * + * RemoteTimers::GetTimer-v1.0 + * Test if the timer exists as either a remote or a local timer. + * The service call always returns true. + * Data points to a cTimer* which points to the timer you are looking for. If found, cTimer* will point to the timer, otherwise it will be NULL. + */ + +//in+out +// cTimer* timer; + +/* + * RemoteTimers::GetMatch-v1.0 + * Find the remote or local timer which matches the event best. + * The service call always returns true. + * Data points to the following structure: + */ + +struct RemoteTimers_GetMatch_v1_0 { +//in + const cEvent *event; +//out + cTimer *timer; + int timerMatch; + int timerType; + bool isRemote; +}; + +/* + * RemoteTimers::GetTimerByEvent-v1.0 + * Find the remote or local timer matching the event. + * If no timer matches, the service call returns false. + * Data points to a RemoteTimers_Event_v1_0 struct. + * + * RemoteTimers::NewTimerByEvent-v1.0 + * Add a new timer for an event. + * In case of an error, the service call returns false and the structure includes an error message. + * Data points to a RemoteTimers_Event_v1_0 struct. + */ + +struct RemoteTimers_Event_v1_0 { +//in + const cEvent *event; +//out + cTimer *timer; + cString errorMsg; +}; + +/* + * RemoteTimers::NewTimer-v1.0 + * Add a new timer. + * In case of an error, the service call returns false and the structure includes an error message. + * Data points to a RemoteTimers_Timer_v1_0 struct. + * + * RemoteTimers::ModTimer-v1.0 + * Change an existing timer. + * In case of an error, the service call returns false and the structure includes an error message. + * Data points to a RemoteTimers_Timer_v1_0 struct. + * + * RemoteTimers::DelTimer-v1.0 + * Delete an existing timer. + * In case of an error, the service call returns false and the structure includes an error message. + * Data points to a RemoteTimers_Timer_v1_0 struct. + */ + +struct RemoteTimers_Timer_v1_0 { +//in+out + cTimer *timer; +//out + cString errorMsg; +}; + +#endif //_SERVICE__H diff --git a/services/scraper2vdr.h b/services/scraper2vdr.h new file mode 100644 index 0000000..a5d6043 --- /dev/null +++ b/services/scraper2vdr.h @@ -0,0 +1,214 @@ +#ifndef __SCRAPER2VDRSERVICES_H +#define __SCRAPER2VDRSERVICES_H + +#include +#include +#include +#include + +enum tvType { + tSeries, + tMovie, + tNone, +}; + +/********************************************************************* +* Helper Structures +*********************************************************************/ +class cTvMedia { +public: + cTvMedia(void) { + path = ""; + width = height = 0; + }; + std::string path; + int width; + int height; +}; + +class cEpisode { +public: + cEpisode(void) { + number = 0; + season = 0; + name = ""; + firstAired = ""; + guestStars = ""; + overview = ""; + rating = 0.0; + }; + int number; + int season; + std::string name; + std::string firstAired; + std::string guestStars; + std::string overview; + float rating; + cTvMedia episodeImage; +}; + +class cActor { +public: + cActor(void) { + name = ""; + role = ""; + }; + std::string name; + std::string role; + cTvMedia actorThumb; +}; + +/********************************************************************* +* Data Structures for Service Calls +*********************************************************************/ + +// Data structure for service "GetEventType" +class ScraperGetEventType { +public: + ScraperGetEventType(void) { + event = NULL; + recording = NULL; + type = tNone; + movieId = 0; + seriesId = 0; + episodeId = 0; + }; +// in + const cEvent *event; // check type for this event + const cRecording *recording; // or for this recording +//out + tvType type; //typeSeries or typeMovie + int movieId; + int seriesId; + int episodeId; +}; + +//Data structure for full series and episode information +class cMovie { +public: + cMovie(void) { + title = ""; + originalTitle = ""; + tagline = ""; + overview = ""; + adult = false; + collectionName = ""; + budget = 0; + revenue = 0; + genres = ""; + homepage = ""; + releaseDate = ""; + runtime = 0; + popularity = 0.0; + voteAverage = 0.0; + }; +//IN + int movieId; // movieId fetched from ScraperGetEventType +//OUT + std::string title; + std::string originalTitle; + std::string tagline; + std::string overview; + bool adult; + std::string collectionName; + int budget; + int revenue; + std::string genres; + std::string homepage; + std::string releaseDate; + int runtime; + float popularity; + float voteAverage; + cTvMedia poster; + cTvMedia fanart; + cTvMedia collectionPoster; + cTvMedia collectionFanart; + std::vector actors; +}; + +//Data structure for full series and episode information +class cSeries { +public: + cSeries(void) { + seriesId = 0; + episodeId = 0; + name = ""; + overview = ""; + firstAired = ""; + network = ""; + genre = ""; + rating = 0.0; + status = ""; + }; +//IN + int seriesId; // seriesId fetched from ScraperGetEventType + int episodeId; // episodeId fetched from ScraperGetEventType +//OUT + std::string name; + std::string overview; + std::string firstAired; + std::string network; + std::string genre; + float rating; + std::string status; + cEpisode episode; + std::vector actors; + std::vector posters; + std::vector banners; + std::vector fanarts; + cTvMedia seasonPoster; +}; + +// Data structure for service "GetPosterBanner" +class ScraperGetPosterBanner { +public: + ScraperGetPosterBanner(void) { + type = tNone; + event = NULL; + }; +// in + const cEvent *event; // check type for this event +//out + tvType type; //typeSeries or typeMovie + cTvMedia poster; + cTvMedia banner; +}; + +// Data structure for service "GetPosterBannerV2" +class ScraperGetPosterBannerV2 { +public: + ScraperGetPosterBannerV2(void) { + type = tNone; + event = NULL; + recording = NULL; + }; +// in + const cEvent *event; // check type for this event + const cRecording *recording; // check type for this recording +//out + tvType type; //typeSeries or typeMovie + cTvMedia poster; + cTvMedia banner; +}; + +// Data structure for service "GetPoster" +class ScraperGetPoster { +public: +// in + const cEvent *event; // check type for this event + const cRecording *recording; // or for this recording +//out + cTvMedia poster; +}; + +// Data structure for service "GetPosterThumb" +class ScraperGetPosterThumb { +public: +// in + const cEvent *event; // check type for this event + const cRecording *recording; // or for this recording +//out + cTvMedia poster; +}; + +#endif //__SCRAPER2VDRSERVICES_H \ No newline at end of file diff --git a/setup.c b/setup.c new file mode 100644 index 0000000..0b85782 --- /dev/null +++ b/setup.c @@ -0,0 +1,73 @@ +#include "setup.h" + +cSkinDesignerSetup::cSkinDesignerSetup() { + data = config; + Setup(); +} + +cSkinDesignerSetup::~cSkinDesignerSetup() { +} + + +void cSkinDesignerSetup::Setup(void) { + int current = Current(); + Clear(); + + Add(new cMenuEditBoolItem(tr("Debug Image Loading"), &data.debugImageLoading)); + + Add(new cMenuEditBoolItem(tr("Limit Channel Logo Cache"), &data.limitLogoCache)); + Add(new cMenuEditIntItem(tr("Number to cache initially (per size)"), &data.numLogosPerSizeInitial, 0, 1000)); + Add(new cMenuEditIntItem(tr("Number to cache in maximum"), &data.numLogosMax, 0, 1000)); + + cString message = cString::sprintf("--------------------- %s ---------------------", tr("Cache Statistics")); + Add(new cOsdItem(*message)); + cList::Last()->SetSelectable(false); + + int sizeIconCache = 0; + int numIcons = 0; + imgCache->GetIconCacheSize(numIcons, sizeIconCache); + cString iconCacheInfo = cString::sprintf("%s %d %s - %s %d %s", tr("cached"), numIcons, tr("icons"), tr("size"), sizeIconCache, tr("byte")); + Add(new cOsdItem(*iconCacheInfo)); + cList::Last()->SetSelectable(false); + + int sizeLogoCache = 0; + int numLogos = 0; + imgCache->GetLogoCacheSize(numLogos, sizeLogoCache); + cString logoCacheInfo = cString::sprintf("%s %d %s - %s %d %s", tr("cached"), numLogos, tr("logos"), tr("size"), sizeLogoCache, tr("byte")); + Add(new cOsdItem(*logoCacheInfo)); + cList::Last()->SetSelectable(false); + + int sizeSkinpartCache = 0; + int numSkinparts = 0; + imgCache->GetSkinpartsCacheSize(numSkinparts, sizeSkinpartCache); + cString skinpartCacheInfo = cString::sprintf("%s %d %s - %s %d %s", tr("cached"), numSkinparts, tr("skinparts"), tr("size"), sizeSkinpartCache, tr("byte")); + Add(new cOsdItem(*skinpartCacheInfo)); + cList::Last()->SetSelectable(false); + + SetCurrent(Get(current)); + Display(); +} + +eOSState cSkinDesignerSetup::ProcessKey(eKeys Key) { + eOSState state = cMenuSetupPage::ProcessKey(Key); + switch (state) { + case osContinue: { + if (NORMALKEY(Key) == kUp || NORMALKEY(Key) == kDown) { + cOsdItem* item = Get(Current()); + if (item) + item->ProcessKey(kNone); + } + break; } + default: break; + } + return state; +} + +void cSkinDesignerSetup::Store(void) { + config = data; + + SetupStore("DebugImageLoading", config.debugImageLoading); + SetupStore("LimitChannelLogoCache", config.limitLogoCache); + SetupStore("NumberLogosInitially", config.numLogosPerSizeInitial); + SetupStore("NumberLogosMax", config.numLogosMax); +} \ No newline at end of file diff --git a/setup.h b/setup.h new file mode 100644 index 0000000..ea9bf13 --- /dev/null +++ b/setup.h @@ -0,0 +1,16 @@ +#ifndef __SKINDESIGNER_SETUP_H +#define __SKINDESIGNER_SETUP_H + +#include "config.h" + +class cSkinDesignerSetup : public cMenuSetupPage { + public: + cSkinDesignerSetup(void); + virtual ~cSkinDesignerSetup(); + private: + cDesignerConfig data; + void Setup(void); + virtual eOSState ProcessKey(eKeys Key); + virtual void Store(void); +}; +#endif //__SKINDESIGNER_SETUP_H \ No newline at end of file diff --git a/skindesigner.c b/skindesigner.c new file mode 100644 index 0000000..5074c9d --- /dev/null +++ b/skindesigner.c @@ -0,0 +1,165 @@ +/* + * skindesigner.c: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id$ + */ +#include +#include +#include + +#define DEFINE_CONFIG 1 +#include "config.h" +#include "designer.h" +#include "setup.h" + + +#if defined(APIVERSNUM) && APIVERSNUM < 20000 +#error "VDR-2.0.0 API version or greater is required!" +#endif + + +static const char *VERSION = "0.0.1"; +static const char *DESCRIPTION = "SkinDesigner"; +static const char *MAINMENUENTRY = "Skin Designer"; + +class cPluginSkinDesigner : public cPlugin { +private: + cSkinDesigner *skinDesigner; +public: + cPluginSkinDesigner(void); + virtual ~cPluginSkinDesigner(); + 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); +}; + +cPluginSkinDesigner::cPluginSkinDesigner(void) { + skinDesigner = NULL; +} + +cPluginSkinDesigner::~cPluginSkinDesigner() { +} + +const char *cPluginSkinDesigner::CommandLineHelp(void) { + return + " -s , --skinpath= Set directory where xml skins are stored\n" + " -e , --epgimages= Set directory where epgimages are stored\n"; +} + +bool cPluginSkinDesigner::ProcessArgs(int argc, char *argv[]) { + // Implement command line argument processing here if applicable. + static const struct option long_options[] = { + { "epgimages", required_argument, NULL, 'e' }, + { "skinpath", required_argument, NULL, 's' }, + { 0, 0, 0, 0 } + }; + + int c; + while ((c = getopt_long(argc, argv, "e:s:", long_options, NULL)) != -1) { + switch (c) { + case 'e': + config.SetEpgImagePath(cString(optarg)); + break; + case 's': + config.SetSkinPath(cString(optarg)); + break; + default: + return false; + } + } + return true; +} + +bool cPluginSkinDesigner::Initialize(void) { + return true; +} + +bool cPluginSkinDesigner::Start(void) { + if (!cOsdProvider::SupportsTrueColor()) { + esyslog("skinDesigner: No TrueColor OSD found! Using default Skin LCARS!"); + return new cSkinLCARS(); + } else + dsyslog("skinDesigner: TrueColor OSD found"); + skinDesigner = new cSkinDesigner(); + return skinDesigner; +} + +void cPluginSkinDesigner::Stop(void) { + delete imgCache; + delete fontManager; +} + +void cPluginSkinDesigner::Housekeeping(void) { +} + +void cPluginSkinDesigner::MainThreadHook(void) { +} + +cString cPluginSkinDesigner::Active(void) { + return NULL; +} + +time_t cPluginSkinDesigner::WakeupTime(void) { + return 0; +} + +cOsdObject *cPluginSkinDesigner::MainMenuAction(void) { + return NULL; +} + +cMenuSetupPage *cPluginSkinDesigner::SetupMenu(void) { + return new cSkinDesignerSetup(); +} + +bool cPluginSkinDesigner::SetupParse(const char *Name, const char *Value) { + return config.SetupParse(Name, Value); +} + +bool cPluginSkinDesigner::Service(const char *Id, void *Data) { + return false; +} + +const char **cPluginSkinDesigner::SVDRPHelpPages(void) { + static const char *HelpPages[] = { + "RELD\n" + " force reload of templates and caches", + "LSTF\n" + " List available Fonts", + 0 + }; + return HelpPages; +} + +cString cPluginSkinDesigner::SVDRPCommand(const char *Command, const char *Option, int &ReplyCode) { + if (strcasecmp(Command, "RELD") == 0) { + if (skinDesigner) { + skinDesigner->Reload(); + return "SKINDESIGNER reload of templates and caches forced."; + } + } else if (strcasecmp(Command, "LSTF") == 0) { + if (skinDesigner) { + skinDesigner->ListAvailableFonts(); + return "SKINDESIGNER available fonts listed in syslog."; + } + } + return NULL; +} + +VDRPLUGINCREATOR(cPluginSkinDesigner); // Don't touch this! diff --git a/skins/default/graphics/icons/ico_ac3.png b/skins/default/graphics/icons/ico_ac3.png new file mode 100644 index 0000000..5b8614a Binary files /dev/null and b/skins/default/graphics/icons/ico_ac3.png differ diff --git a/skins/default/graphics/icons/ico_activetimer.png b/skins/default/graphics/icons/ico_activetimer.png new file mode 100644 index 0000000..af4c33c Binary files /dev/null and b/skins/default/graphics/icons/ico_activetimer.png differ diff --git a/skins/default/graphics/icons/ico_channelsep.png b/skins/default/graphics/icons/ico_channelsep.png new file mode 100644 index 0000000..bf51238 Binary files /dev/null and b/skins/default/graphics/icons/ico_channelsep.png differ diff --git a/skins/default/graphics/icons/ico_crypt_off.png b/skins/default/graphics/icons/ico_crypt_off.png new file mode 100644 index 0000000..b612aec Binary files /dev/null and b/skins/default/graphics/icons/ico_crypt_off.png differ diff --git a/skins/default/graphics/icons/ico_crypt_on.png b/skins/default/graphics/icons/ico_crypt_on.png new file mode 100644 index 0000000..55abed4 Binary files /dev/null and b/skins/default/graphics/icons/ico_crypt_on.png differ diff --git a/skins/default/graphics/icons/ico_cutted.png b/skins/default/graphics/icons/ico_cutted.png new file mode 100644 index 0000000..b90c9c1 Binary files /dev/null and b/skins/default/graphics/icons/ico_cutted.png differ diff --git a/skins/default/graphics/icons/ico_discusage.png b/skins/default/graphics/icons/ico_discusage.png new file mode 100644 index 0000000..f40fcd9 Binary files /dev/null and b/skins/default/graphics/icons/ico_discusage.png differ diff --git a/skins/default/graphics/icons/ico_dolby_off.png b/skins/default/graphics/icons/ico_dolby_off.png new file mode 100644 index 0000000..17815f5 Binary files /dev/null and b/skins/default/graphics/icons/ico_dolby_off.png differ diff --git a/skins/default/graphics/icons/ico_dolby_on.png b/skins/default/graphics/icons/ico_dolby_on.png new file mode 100644 index 0000000..c06c18e Binary files /dev/null and b/skins/default/graphics/icons/ico_dolby_on.png differ diff --git a/skins/default/graphics/icons/ico_ff.png b/skins/default/graphics/icons/ico_ff.png new file mode 100644 index 0000000..5ffbe4b Binary files /dev/null and b/skins/default/graphics/icons/ico_ff.png differ diff --git a/skins/default/graphics/icons/ico_ff_1x.png b/skins/default/graphics/icons/ico_ff_1x.png new file mode 100644 index 0000000..96a74bc Binary files /dev/null and b/skins/default/graphics/icons/ico_ff_1x.png differ diff --git a/skins/default/graphics/icons/ico_ff_2x.png b/skins/default/graphics/icons/ico_ff_2x.png new file mode 100644 index 0000000..54657bf Binary files /dev/null and b/skins/default/graphics/icons/ico_ff_2x.png differ diff --git a/skins/default/graphics/icons/ico_ff_3x.png b/skins/default/graphics/icons/ico_ff_3x.png new file mode 100644 index 0000000..ac21eca Binary files /dev/null and b/skins/default/graphics/icons/ico_ff_3x.png differ diff --git a/skins/default/graphics/icons/ico_ff_off.png b/skins/default/graphics/icons/ico_ff_off.png new file mode 100644 index 0000000..5a9ab50 Binary files /dev/null and b/skins/default/graphics/icons/ico_ff_off.png differ diff --git a/skins/default/graphics/icons/ico_hd_off.png b/skins/default/graphics/icons/ico_hd_off.png new file mode 100644 index 0000000..cd0492a Binary files /dev/null and b/skins/default/graphics/icons/ico_hd_off.png differ diff --git a/skins/default/graphics/icons/ico_hd_on.png b/skins/default/graphics/icons/ico_hd_on.png new file mode 100644 index 0000000..5f6cfa5 Binary files /dev/null and b/skins/default/graphics/icons/ico_hd_on.png differ diff --git a/skins/default/graphics/icons/ico_line_off.png b/skins/default/graphics/icons/ico_line_off.png new file mode 100644 index 0000000..94591ee Binary files /dev/null and b/skins/default/graphics/icons/ico_line_off.png differ diff --git a/skins/default/graphics/icons/ico_line_on.png b/skins/default/graphics/icons/ico_line_on.png new file mode 100644 index 0000000..1584078 Binary files /dev/null and b/skins/default/graphics/icons/ico_line_on.png differ diff --git a/skins/default/graphics/icons/ico_mute.png b/skins/default/graphics/icons/ico_mute.png new file mode 100644 index 0000000..4eefc75 Binary files /dev/null and b/skins/default/graphics/icons/ico_mute.png differ diff --git a/skins/default/graphics/icons/ico_pause.png b/skins/default/graphics/icons/ico_pause.png new file mode 100644 index 0000000..405a097 Binary files /dev/null and b/skins/default/graphics/icons/ico_pause.png differ diff --git a/skins/default/graphics/icons/ico_pause_off.png b/skins/default/graphics/icons/ico_pause_off.png new file mode 100644 index 0000000..6f02e39 Binary files /dev/null and b/skins/default/graphics/icons/ico_pause_off.png differ diff --git a/skins/default/graphics/icons/ico_play.png b/skins/default/graphics/icons/ico_play.png new file mode 100644 index 0000000..02a01c0 Binary files /dev/null and b/skins/default/graphics/icons/ico_play.png differ diff --git a/skins/default/graphics/icons/ico_play_off.png b/skins/default/graphics/icons/ico_play_off.png new file mode 100644 index 0000000..d87322a Binary files /dev/null and b/skins/default/graphics/icons/ico_play_off.png differ diff --git a/skins/default/graphics/icons/ico_rec_off.png b/skins/default/graphics/icons/ico_rec_off.png new file mode 100644 index 0000000..224baea Binary files /dev/null and b/skins/default/graphics/icons/ico_rec_off.png differ diff --git a/skins/default/graphics/icons/ico_rec_on.png b/skins/default/graphics/icons/ico_rec_on.png new file mode 100644 index 0000000..7bc18a7 Binary files /dev/null and b/skins/default/graphics/icons/ico_rec_on.png differ diff --git a/skins/default/graphics/icons/ico_recfolder.png b/skins/default/graphics/icons/ico_recfolder.png new file mode 100644 index 0000000..e3df65b Binary files /dev/null and b/skins/default/graphics/icons/ico_recfolder.png differ diff --git a/skins/default/graphics/icons/ico_recnew.png b/skins/default/graphics/icons/ico_recnew.png new file mode 100644 index 0000000..b9166ba Binary files /dev/null and b/skins/default/graphics/icons/ico_recnew.png differ diff --git a/skins/default/graphics/icons/ico_rew.png b/skins/default/graphics/icons/ico_rew.png new file mode 100644 index 0000000..1505f79 Binary files /dev/null and b/skins/default/graphics/icons/ico_rew.png differ diff --git a/skins/default/graphics/icons/ico_rew_1x.png b/skins/default/graphics/icons/ico_rew_1x.png new file mode 100644 index 0000000..6ddbde4 Binary files /dev/null and b/skins/default/graphics/icons/ico_rew_1x.png differ diff --git a/skins/default/graphics/icons/ico_rew_2x.png b/skins/default/graphics/icons/ico_rew_2x.png new file mode 100644 index 0000000..9b7ee52 Binary files /dev/null and b/skins/default/graphics/icons/ico_rew_2x.png differ diff --git a/skins/default/graphics/icons/ico_rew_3x.png b/skins/default/graphics/icons/ico_rew_3x.png new file mode 100644 index 0000000..4a3abeb Binary files /dev/null and b/skins/default/graphics/icons/ico_rew_3x.png differ diff --git a/skins/default/graphics/icons/ico_rew_off.png b/skins/default/graphics/icons/ico_rew_off.png new file mode 100644 index 0000000..a84a7f3 Binary files /dev/null and b/skins/default/graphics/icons/ico_rew_off.png differ diff --git a/skins/default/graphics/icons/ico_stereo.png b/skins/default/graphics/icons/ico_stereo.png new file mode 100644 index 0000000..7f3610d Binary files /dev/null and b/skins/default/graphics/icons/ico_stereo.png differ diff --git a/skins/default/graphics/icons/ico_timer_active.png b/skins/default/graphics/icons/ico_timer_active.png new file mode 100644 index 0000000..28c2f81 Binary files /dev/null and b/skins/default/graphics/icons/ico_timer_active.png differ diff --git a/skins/default/graphics/icons/ico_timer_inactive.png b/skins/default/graphics/icons/ico_timer_inactive.png new file mode 100644 index 0000000..c4b1860 Binary files /dev/null and b/skins/default/graphics/icons/ico_timer_inactive.png differ diff --git a/skins/default/graphics/icons/ico_timer_recording.png b/skins/default/graphics/icons/ico_timer_recording.png new file mode 100644 index 0000000..86dc66b Binary files /dev/null and b/skins/default/graphics/icons/ico_timer_recording.png differ diff --git a/skins/default/graphics/icons/ico_txt_off.png b/skins/default/graphics/icons/ico_txt_off.png new file mode 100644 index 0000000..a445bc5 Binary files /dev/null and b/skins/default/graphics/icons/ico_txt_off.png differ diff --git a/skins/default/graphics/icons/ico_txt_on.png b/skins/default/graphics/icons/ico_txt_on.png new file mode 100644 index 0000000..ad14ff7 Binary files /dev/null and b/skins/default/graphics/icons/ico_txt_on.png differ diff --git a/skins/default/graphics/icons/ico_volume.png b/skins/default/graphics/icons/ico_volume.png new file mode 100644 index 0000000..3a72514 Binary files /dev/null and b/skins/default/graphics/icons/ico_volume.png differ diff --git a/skins/default/graphics/icons/ico_widescreen_off.png b/skins/default/graphics/icons/ico_widescreen_off.png new file mode 100644 index 0000000..dffd6a5 Binary files /dev/null and b/skins/default/graphics/icons/ico_widescreen_off.png differ diff --git a/skins/default/graphics/icons/ico_widescreen_on.png b/skins/default/graphics/icons/ico_widescreen_on.png new file mode 100644 index 0000000..876bb55 Binary files /dev/null and b/skins/default/graphics/icons/ico_widescreen_on.png differ diff --git a/skins/default/graphics/menuicons/customicons/Applikationen.png b/skins/default/graphics/menuicons/customicons/Applikationen.png new file mode 100644 index 0000000..3c3b616 Binary files /dev/null and b/skins/default/graphics/menuicons/customicons/Applikationen.png differ diff --git a/skins/default/graphics/menuicons/customicons/Audio.png b/skins/default/graphics/menuicons/customicons/Audio.png new file mode 100644 index 0000000..ff387fe Binary files /dev/null and b/skins/default/graphics/menuicons/customicons/Audio.png differ diff --git a/skins/default/graphics/menuicons/customicons/Aufnahmen-Liste aktualisieren.png b/skins/default/graphics/menuicons/customicons/Aufnahmen-Liste aktualisieren.png new file mode 100644 index 0000000..3cdddc9 Binary files /dev/null and b/skins/default/graphics/menuicons/customicons/Aufnahmen-Liste aktualisieren.png differ diff --git a/skins/default/graphics/menuicons/customicons/Dienstprogramme.png b/skins/default/graphics/menuicons/customicons/Dienstprogramme.png new file mode 100644 index 0000000..793aba6 Binary files /dev/null and b/skins/default/graphics/menuicons/customicons/Dienstprogramme.png differ diff --git a/skins/default/graphics/menuicons/customicons/FireFox.png b/skins/default/graphics/menuicons/customicons/FireFox.png new file mode 100644 index 0000000..192fadc Binary files /dev/null and b/skins/default/graphics/menuicons/customicons/FireFox.png differ diff --git a/skins/default/graphics/menuicons/customicons/Info.png b/skins/default/graphics/menuicons/customicons/Info.png new file mode 100644 index 0000000..6737431 Binary files /dev/null and b/skins/default/graphics/menuicons/customicons/Info.png differ diff --git a/skins/default/graphics/menuicons/customicons/Internet.png b/skins/default/graphics/menuicons/customicons/Internet.png new file mode 100644 index 0000000..f3db150 Binary files /dev/null and b/skins/default/graphics/menuicons/customicons/Internet.png differ diff --git a/skins/default/graphics/menuicons/customicons/Medien.png b/skins/default/graphics/menuicons/customicons/Medien.png new file mode 100644 index 0000000..0ce2360 Binary files /dev/null and b/skins/default/graphics/menuicons/customicons/Medien.png differ diff --git a/skins/default/graphics/menuicons/customicons/Rechner neu starten.png b/skins/default/graphics/menuicons/customicons/Rechner neu starten.png new file mode 100644 index 0000000..5783ccf Binary files /dev/null and b/skins/default/graphics/menuicons/customicons/Rechner neu starten.png differ diff --git a/skins/default/graphics/menuicons/customicons/Remote wakeup.png b/skins/default/graphics/menuicons/customicons/Remote wakeup.png new file mode 100644 index 0000000..1cd2f6e Binary files /dev/null and b/skins/default/graphics/menuicons/customicons/Remote wakeup.png differ diff --git a/skins/default/graphics/menuicons/customicons/Spiele.png b/skins/default/graphics/menuicons/customicons/Spiele.png new file mode 100644 index 0000000..8e07161 Binary files /dev/null and b/skins/default/graphics/menuicons/customicons/Spiele.png differ diff --git a/skins/default/graphics/menuicons/customicons/System herunterfahren.png b/skins/default/graphics/menuicons/customicons/System herunterfahren.png new file mode 100644 index 0000000..e0234df Binary files /dev/null and b/skins/default/graphics/menuicons/customicons/System herunterfahren.png differ diff --git a/skins/default/graphics/menuicons/customicons/System.png b/skins/default/graphics/menuicons/customicons/System.png new file mode 100644 index 0000000..81d100e Binary files /dev/null and b/skins/default/graphics/menuicons/customicons/System.png differ diff --git a/skins/default/graphics/menuicons/customicons/Tools.png b/skins/default/graphics/menuicons/customicons/Tools.png new file mode 100644 index 0000000..cf328ef Binary files /dev/null and b/skins/default/graphics/menuicons/customicons/Tools.png differ diff --git a/skins/default/graphics/menuicons/customicons/Tunderbird.png b/skins/default/graphics/menuicons/customicons/Tunderbird.png new file mode 100644 index 0000000..5ae27e0 Binary files /dev/null and b/skins/default/graphics/menuicons/customicons/Tunderbird.png differ diff --git a/skins/default/graphics/menuicons/customicons/USB Massenspeicher sicher entfernen.png b/skins/default/graphics/menuicons/customicons/USB Massenspeicher sicher entfernen.png new file mode 100644 index 0000000..cd7b81c Binary files /dev/null and b/skins/default/graphics/menuicons/customicons/USB Massenspeicher sicher entfernen.png differ diff --git a/skins/default/graphics/menuicons/customicons/VDR neu starten.png b/skins/default/graphics/menuicons/customicons/VDR neu starten.png new file mode 100644 index 0000000..14904ca Binary files /dev/null and b/skins/default/graphics/menuicons/customicons/VDR neu starten.png differ diff --git a/skins/default/graphics/menuicons/customicons/Video.png b/skins/default/graphics/menuicons/customicons/Video.png new file mode 100644 index 0000000..490ca4b Binary files /dev/null and b/skins/default/graphics/menuicons/customicons/Video.png differ diff --git a/skins/default/graphics/menuicons/customicons/Web.png b/skins/default/graphics/menuicons/customicons/Web.png new file mode 100644 index 0000000..20260e3 Binary files /dev/null and b/skins/default/graphics/menuicons/customicons/Web.png differ diff --git a/skins/default/graphics/menuicons/customicons/XBMC.png b/skins/default/graphics/menuicons/customicons/XBMC.png new file mode 100644 index 0000000..c7c4c04 Binary files /dev/null and b/skins/default/graphics/menuicons/customicons/XBMC.png differ diff --git a/skins/default/graphics/menuicons/customicons/Xterm.png b/skins/default/graphics/menuicons/customicons/Xterm.png new file mode 100644 index 0000000..fa75282 Binary files /dev/null and b/skins/default/graphics/menuicons/customicons/Xterm.png differ diff --git a/skins/default/graphics/menuicons/customicons/audiovideo.png b/skins/default/graphics/menuicons/customicons/audiovideo.png new file mode 100644 index 0000000..726538d Binary files /dev/null and b/skins/default/graphics/menuicons/customicons/audiovideo.png differ diff --git a/skins/default/graphics/menuicons/customicons/markad_status.png b/skins/default/graphics/menuicons/customicons/markad_status.png new file mode 100644 index 0000000..4fdc7a4 Binary files /dev/null and b/skins/default/graphics/menuicons/customicons/markad_status.png differ diff --git a/skins/default/graphics/menuicons/customicons/schneiden_abbrechen.png b/skins/default/graphics/menuicons/customicons/schneiden_abbrechen.png new file mode 100644 index 0000000..b2e0bd3 Binary files /dev/null and b/skins/default/graphics/menuicons/customicons/schneiden_abbrechen.png differ diff --git a/skins/default/graphics/menuicons/customicons/tux.png b/skins/default/graphics/menuicons/customicons/tux.png new file mode 100644 index 0000000..c5b4742 Binary files /dev/null and b/skins/default/graphics/menuicons/customicons/tux.png differ diff --git a/skins/default/graphics/menuicons/customicons/usb.png b/skins/default/graphics/menuicons/customicons/usb.png new file mode 100644 index 0000000..c4db1d4 Binary files /dev/null and b/skins/default/graphics/menuicons/customicons/usb.png differ diff --git a/skins/default/graphics/menuicons/customicons/vdrlogo.png b/skins/default/graphics/menuicons/customicons/vdrlogo.png new file mode 100644 index 0000000..037a191 Binary files /dev/null and b/skins/default/graphics/menuicons/customicons/vdrlogo.png differ diff --git a/skins/default/graphics/menuicons/customicons/yaicon_blue.png b/skins/default/graphics/menuicons/customicons/yaicon_blue.png new file mode 100644 index 0000000..2c49273 Binary files /dev/null and b/skins/default/graphics/menuicons/customicons/yaicon_blue.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/admin.png b/skins/default/graphics/menuicons/pluginicons/admin.png new file mode 100644 index 0000000..cf328ef Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/admin.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/arghdirector.png b/skins/default/graphics/menuicons/pluginicons/arghdirector.png new file mode 100644 index 0000000..bbd221a Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/arghdirector.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/autostart.png b/skins/default/graphics/menuicons/pluginicons/autostart.png new file mode 100644 index 0000000..6fdb1bb Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/autostart.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/avahi4vdr.png b/skins/default/graphics/menuicons/pluginicons/avahi4vdr.png new file mode 100644 index 0000000..044e71d Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/avahi4vdr.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/avards.png b/skins/default/graphics/menuicons/pluginicons/avards.png new file mode 100644 index 0000000..cf8d037 Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/avards.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/block.png b/skins/default/graphics/menuicons/pluginicons/block.png new file mode 100644 index 0000000..86127c2 Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/block.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/burn.png b/skins/default/graphics/menuicons/pluginicons/burn.png new file mode 100644 index 0000000..305d7ff Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/burn.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/cdplayer.png b/skins/default/graphics/menuicons/pluginicons/cdplayer.png new file mode 100644 index 0000000..89a6c19 Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/cdplayer.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/chanman.png b/skins/default/graphics/menuicons/pluginicons/chanman.png new file mode 100644 index 0000000..a73e83c Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/chanman.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/check.png b/skins/default/graphics/menuicons/pluginicons/check.png new file mode 100644 index 0000000..d487a24 Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/check.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/conflictcheckonly.png b/skins/default/graphics/menuicons/pluginicons/conflictcheckonly.png new file mode 100644 index 0000000..7f832bd Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/conflictcheckonly.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/ddci.png b/skins/default/graphics/menuicons/pluginicons/ddci.png new file mode 100644 index 0000000..4ad459c Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/ddci.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/devstatus.png b/skins/default/graphics/menuicons/pluginicons/devstatus.png new file mode 100644 index 0000000..96c0ec1 Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/devstatus.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/dummydevice.png b/skins/default/graphics/menuicons/pluginicons/dummydevice.png new file mode 100644 index 0000000..11fd707 Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/dummydevice.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/duplicates.png b/skins/default/graphics/menuicons/pluginicons/duplicates.png new file mode 100644 index 0000000..dc1be57 Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/duplicates.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/dvbapi.png b/skins/default/graphics/menuicons/pluginicons/dvbapi.png new file mode 100644 index 0000000..b966461 Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/dvbapi.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/dvbhddevice.png b/skins/default/graphics/menuicons/pluginicons/dvbhddevice.png new file mode 100644 index 0000000..b874297 Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/dvbhddevice.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/dvbsddevice.png b/skins/default/graphics/menuicons/pluginicons/dvbsddevice.png new file mode 100644 index 0000000..106184e Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/dvbsddevice.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/dynamite.png b/skins/default/graphics/menuicons/pluginicons/dynamite.png new file mode 100644 index 0000000..28ea35a Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/dynamite.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/eepg.png b/skins/default/graphics/menuicons/pluginicons/eepg.png new file mode 100644 index 0000000..3938b96 Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/eepg.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/epg2vdr.png b/skins/default/graphics/menuicons/pluginicons/epg2vdr.png new file mode 100644 index 0000000..ac8757e Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/epg2vdr.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/epgsearch.png b/skins/default/graphics/menuicons/pluginicons/epgsearch.png new file mode 100644 index 0000000..5eab415 Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/epgsearch.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/epgsearchonly.png b/skins/default/graphics/menuicons/pluginicons/epgsearchonly.png new file mode 100644 index 0000000..b5186e7 Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/epgsearchonly.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/epgsync.png b/skins/default/graphics/menuicons/pluginicons/epgsync.png new file mode 100644 index 0000000..5c14009 Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/epgsync.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/externalplayer.png b/skins/default/graphics/menuicons/pluginicons/externalplayer.png new file mode 100644 index 0000000..2bd67db Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/externalplayer.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/extrecmenu.png b/skins/default/graphics/menuicons/pluginicons/extrecmenu.png new file mode 100644 index 0000000..6f613f1 Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/extrecmenu.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/favorites.png b/skins/default/graphics/menuicons/pluginicons/favorites.png new file mode 100644 index 0000000..409c852 Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/favorites.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/femon.png b/skins/default/graphics/menuicons/pluginicons/femon.png new file mode 100644 index 0000000..e87b711 Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/femon.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/fepg.png b/skins/default/graphics/menuicons/pluginicons/fepg.png new file mode 100644 index 0000000..65023ed Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/fepg.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/filebrowser.png b/skins/default/graphics/menuicons/pluginicons/filebrowser.png new file mode 100644 index 0000000..d3f90e0 Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/filebrowser.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/fritzbox.png b/skins/default/graphics/menuicons/pluginicons/fritzbox.png new file mode 100644 index 0000000..7bfc229 Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/fritzbox.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/graphlcd.png b/skins/default/graphics/menuicons/pluginicons/graphlcd.png new file mode 100644 index 0000000..39ffd35 Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/graphlcd.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/graphtft.png b/skins/default/graphics/menuicons/pluginicons/graphtft.png new file mode 100644 index 0000000..39ffd35 Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/graphtft.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/image.png b/skins/default/graphics/menuicons/pluginicons/image.png new file mode 100644 index 0000000..33644e0 Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/image.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/imonlcd.png b/skins/default/graphics/menuicons/pluginicons/imonlcd.png new file mode 100644 index 0000000..3d34fc4 Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/imonlcd.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/iptv.png b/skins/default/graphics/menuicons/pluginicons/iptv.png new file mode 100644 index 0000000..4494ddc Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/iptv.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/lcdproc.png b/skins/default/graphics/menuicons/pluginicons/lcdproc.png new file mode 100644 index 0000000..3d34fc4 Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/lcdproc.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/mailbox.png b/skins/default/graphics/menuicons/pluginicons/mailbox.png new file mode 100644 index 0000000..1bc76e8 Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/mailbox.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/makemkv.png b/skins/default/graphics/menuicons/pluginicons/makemkv.png new file mode 100644 index 0000000..41cddf1 Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/makemkv.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/markad.png b/skins/default/graphics/menuicons/pluginicons/markad.png new file mode 100644 index 0000000..b3defaf Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/markad.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/mlist.png b/skins/default/graphics/menuicons/pluginicons/mlist.png new file mode 100644 index 0000000..19c367f Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/mlist.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/music.png b/skins/default/graphics/menuicons/pluginicons/music.png new file mode 100644 index 0000000..abb012e Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/music.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/noepg.png b/skins/default/graphics/menuicons/pluginicons/noepg.png new file mode 100644 index 0000000..eb9410d Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/noepg.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/nordlichtsepg.png b/skins/default/graphics/menuicons/pluginicons/nordlichtsepg.png new file mode 100644 index 0000000..3ee3fa2 Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/nordlichtsepg.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/osdteletext.png b/skins/default/graphics/menuicons/pluginicons/osdteletext.png new file mode 100644 index 0000000..664e770 Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/osdteletext.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/peer.png b/skins/default/graphics/menuicons/pluginicons/peer.png new file mode 100644 index 0000000..998d568 Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/peer.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/play.png b/skins/default/graphics/menuicons/pluginicons/play.png new file mode 100644 index 0000000..2848fc6 Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/play.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/pvrinput.png b/skins/default/graphics/menuicons/pluginicons/pvrinput.png new file mode 100644 index 0000000..724f698 Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/pvrinput.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/quickepgsearch.png b/skins/default/graphics/menuicons/pluginicons/quickepgsearch.png new file mode 100644 index 0000000..76a31f4 Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/quickepgsearch.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/radio.png b/skins/default/graphics/menuicons/pluginicons/radio.png new file mode 100644 index 0000000..193b7d4 Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/radio.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/remote.png b/skins/default/graphics/menuicons/pluginicons/remote.png new file mode 100644 index 0000000..7f46b1b Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/remote.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/remotetimers.png b/skins/default/graphics/menuicons/pluginicons/remotetimers.png new file mode 100644 index 0000000..fae3b79 Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/remotetimers.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/rssreader.png b/skins/default/graphics/menuicons/pluginicons/rssreader.png new file mode 100644 index 0000000..db538f0 Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/rssreader.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/sc.png b/skins/default/graphics/menuicons/pluginicons/sc.png new file mode 100644 index 0000000..2472d6c Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/sc.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/scraper2vdr.png b/skins/default/graphics/menuicons/pluginicons/scraper2vdr.png new file mode 100644 index 0000000..a106cb5 Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/scraper2vdr.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/screenshot.png b/skins/default/graphics/menuicons/pluginicons/screenshot.png new file mode 100644 index 0000000..be9b4d5 Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/screenshot.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/seduatmo.png b/skins/default/graphics/menuicons/pluginicons/seduatmo.png new file mode 100644 index 0000000..4b5292f Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/seduatmo.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/skyselectfeeds.png b/skins/default/graphics/menuicons/pluginicons/skyselectfeeds.png new file mode 100644 index 0000000..d81a024 Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/skyselectfeeds.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/sleeptimer.png b/skins/default/graphics/menuicons/pluginicons/sleeptimer.png new file mode 100644 index 0000000..cd4956f Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/sleeptimer.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/softhddevice.png b/skins/default/graphics/menuicons/pluginicons/softhddevice.png new file mode 100644 index 0000000..df13f2c Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/softhddevice.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/streamdev-server.png b/skins/default/graphics/menuicons/pluginicons/streamdev-server.png new file mode 100644 index 0000000..e89ed8b Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/streamdev-server.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/systeminfo.png b/skins/default/graphics/menuicons/pluginicons/systeminfo.png new file mode 100644 index 0000000..b14763f Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/systeminfo.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/targavfd.png b/skins/default/graphics/menuicons/pluginicons/targavfd.png new file mode 100644 index 0000000..e91b111 Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/targavfd.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/trayopenng.png b/skins/default/graphics/menuicons/pluginicons/trayopenng.png new file mode 100644 index 0000000..6ebd17d Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/trayopenng.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/tvguide.png b/skins/default/graphics/menuicons/pluginicons/tvguide.png new file mode 100644 index 0000000..968a37c Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/tvguide.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/tvm2vdr.png b/skins/default/graphics/menuicons/pluginicons/tvm2vdr.png new file mode 100644 index 0000000..47f9a91 Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/tvm2vdr.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/tvscraper.png b/skins/default/graphics/menuicons/pluginicons/tvscraper.png new file mode 100644 index 0000000..a106cb5 Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/tvscraper.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/undelete.png b/skins/default/graphics/menuicons/pluginicons/undelete.png new file mode 100644 index 0000000..a53d50a Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/undelete.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/weatherng.png b/skins/default/graphics/menuicons/pluginicons/weatherng.png new file mode 100644 index 0000000..a88f11d Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/weatherng.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/xmltv2vdr.png b/skins/default/graphics/menuicons/pluginicons/xmltv2vdr.png new file mode 100644 index 0000000..ea73c74 Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/xmltv2vdr.png differ diff --git a/skins/default/graphics/menuicons/pluginicons/yaepghg.png b/skins/default/graphics/menuicons/pluginicons/yaepghg.png new file mode 100644 index 0000000..53ce443 Binary files /dev/null and b/skins/default/graphics/menuicons/pluginicons/yaepghg.png differ diff --git a/skins/default/graphics/menuicons/standardicons/CAM.png b/skins/default/graphics/menuicons/standardicons/CAM.png new file mode 100644 index 0000000..a394877 Binary files /dev/null and b/skins/default/graphics/menuicons/standardicons/CAM.png differ diff --git a/skins/default/graphics/menuicons/standardicons/Channels.png b/skins/default/graphics/menuicons/standardicons/Channels.png new file mode 100644 index 0000000..ba2ba78 Binary files /dev/null and b/skins/default/graphics/menuicons/standardicons/Channels.png differ diff --git a/skins/default/graphics/menuicons/standardicons/Commands.png b/skins/default/graphics/menuicons/standardicons/Commands.png new file mode 100644 index 0000000..c6a83ef Binary files /dev/null and b/skins/default/graphics/menuicons/standardicons/Commands.png differ diff --git a/skins/default/graphics/menuicons/standardicons/DVB.png b/skins/default/graphics/menuicons/standardicons/DVB.png new file mode 100644 index 0000000..3789145 Binary files /dev/null and b/skins/default/graphics/menuicons/standardicons/DVB.png differ diff --git a/skins/default/graphics/menuicons/standardicons/EPG.png b/skins/default/graphics/menuicons/standardicons/EPG.png new file mode 100644 index 0000000..e868b90 Binary files /dev/null and b/skins/default/graphics/menuicons/standardicons/EPG.png differ diff --git a/skins/default/graphics/menuicons/standardicons/LNB.png b/skins/default/graphics/menuicons/standardicons/LNB.png new file mode 100644 index 0000000..896dd99 Binary files /dev/null and b/skins/default/graphics/menuicons/standardicons/LNB.png differ diff --git a/skins/default/graphics/menuicons/standardicons/Miscellaneous.png b/skins/default/graphics/menuicons/standardicons/Miscellaneous.png new file mode 100644 index 0000000..2a41c4d Binary files /dev/null and b/skins/default/graphics/menuicons/standardicons/Miscellaneous.png differ diff --git a/skins/default/graphics/menuicons/standardicons/OSD.png b/skins/default/graphics/menuicons/standardicons/OSD.png new file mode 100644 index 0000000..8f571c6 Binary files /dev/null and b/skins/default/graphics/menuicons/standardicons/OSD.png differ diff --git a/skins/default/graphics/menuicons/standardicons/Plugins.png b/skins/default/graphics/menuicons/standardicons/Plugins.png new file mode 100644 index 0000000..3fcba70 Binary files /dev/null and b/skins/default/graphics/menuicons/standardicons/Plugins.png differ diff --git a/skins/default/graphics/menuicons/standardicons/Recording.png b/skins/default/graphics/menuicons/standardicons/Recording.png new file mode 100644 index 0000000..741b1af Binary files /dev/null and b/skins/default/graphics/menuicons/standardicons/Recording.png differ diff --git a/skins/default/graphics/menuicons/standardicons/Recordings.png b/skins/default/graphics/menuicons/standardicons/Recordings.png new file mode 100644 index 0000000..79aeeb7 Binary files /dev/null and b/skins/default/graphics/menuicons/standardicons/Recordings.png differ diff --git a/skins/default/graphics/menuicons/standardicons/Replay.png b/skins/default/graphics/menuicons/standardicons/Replay.png new file mode 100644 index 0000000..621596c Binary files /dev/null and b/skins/default/graphics/menuicons/standardicons/Replay.png differ diff --git a/skins/default/graphics/menuicons/standardicons/Restart.png b/skins/default/graphics/menuicons/standardicons/Restart.png new file mode 100644 index 0000000..aa23cd4 Binary files /dev/null and b/skins/default/graphics/menuicons/standardicons/Restart.png differ diff --git a/skins/default/graphics/menuicons/standardicons/Schedule.png b/skins/default/graphics/menuicons/standardicons/Schedule.png new file mode 100644 index 0000000..3a98cac Binary files /dev/null and b/skins/default/graphics/menuicons/standardicons/Schedule.png differ diff --git a/skins/default/graphics/menuicons/standardicons/Setup.png b/skins/default/graphics/menuicons/standardicons/Setup.png new file mode 100644 index 0000000..d121148 Binary files /dev/null and b/skins/default/graphics/menuicons/standardicons/Setup.png differ diff --git a/skins/default/graphics/menuicons/standardicons/StopRecording.png b/skins/default/graphics/menuicons/standardicons/StopRecording.png new file mode 100644 index 0000000..ed83fbb Binary files /dev/null and b/skins/default/graphics/menuicons/standardicons/StopRecording.png differ diff --git a/skins/default/graphics/menuicons/standardicons/StopReplay.png b/skins/default/graphics/menuicons/standardicons/StopReplay.png new file mode 100644 index 0000000..9192760 Binary files /dev/null and b/skins/default/graphics/menuicons/standardicons/StopReplay.png differ diff --git a/skins/default/graphics/menuicons/standardicons/Timers.png b/skins/default/graphics/menuicons/standardicons/Timers.png new file mode 100644 index 0000000..b866c36 Binary files /dev/null and b/skins/default/graphics/menuicons/standardicons/Timers.png differ diff --git a/skins/default/xmlfiles/displayaudiotracks.xml b/skins/default/xmlfiles/displayaudiotracks.xml new file mode 100644 index 0000000..9698262 --- /dev/null +++ b/skins/default/xmlfiles/displayaudiotracks.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + +
+ + + + + +
+ + + + + + + + + + + + + + + + +
diff --git a/skins/default/xmlfiles/displaychannel.xml b/skins/default/xmlfiles/displaychannel.xml new file mode 100644 index 0000000..6162562 --- /dev/null +++ b/skins/default/xmlfiles/displaychannel.xml @@ -0,0 +1,213 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/skins/default/xmlfiles/displaymenu.xml b/skins/default/xmlfiles/displaymenu.xml new file mode 100644 index 0000000..9125d43 --- /dev/null +++ b/skins/default/xmlfiles/displaymenu.xml @@ -0,0 +1,155 @@ + + + + + + + + + + + +]> + + + + + + + + + + + + + + +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + &displaymenudefault; + &displaymenumain; + &displaymenusetup; + &displaymenuschedules; + &displaymenutimers; + &displaymenuchannels; + &displaymenurecordings; + &displaymenudetailepg; + &displaymenudetailrecording; + &displaymenudetailtext; +
diff --git a/skins/default/xmlfiles/displaymenuchannels.xml b/skins/default/xmlfiles/displaymenuchannels.xml new file mode 100644 index 0000000..cba4cf8 --- /dev/null +++ b/skins/default/xmlfiles/displaymenuchannels.xml @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/skins/default/xmlfiles/displaymenudefault.xml b/skins/default/xmlfiles/displaymenudefault.xml new file mode 100644 index 0000000..c7885d0 --- /dev/null +++ b/skins/default/xmlfiles/displaymenudefault.xml @@ -0,0 +1,184 @@ + + + + + + + + +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/skins/default/xmlfiles/displaymenudetailepg.xml b/skins/default/xmlfiles/displaymenudetailepg.xml new file mode 100644 index 0000000..7c8c399 --- /dev/null +++ b/skins/default/xmlfiles/displaymenudetailepg.xml @@ -0,0 +1,335 @@ + + + + + + + + + + + + + +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/skins/default/xmlfiles/displaymenudetailrecording.xml b/skins/default/xmlfiles/displaymenudetailrecording.xml new file mode 100644 index 0000000..2342ecc --- /dev/null +++ b/skins/default/xmlfiles/displaymenudetailrecording.xml @@ -0,0 +1,310 @@ + + + + + + + + + + + + + +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/skins/default/xmlfiles/displaymenudetailtext.xml b/skins/default/xmlfiles/displaymenudetailtext.xml new file mode 100644 index 0000000..5fd8997 --- /dev/null +++ b/skins/default/xmlfiles/displaymenudetailtext.xml @@ -0,0 +1,99 @@ + + + + + + +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/skins/default/xmlfiles/displaymenumain.xml b/skins/default/xmlfiles/displaymenumain.xml new file mode 100644 index 0000000..a6cfd6b --- /dev/null +++ b/skins/default/xmlfiles/displaymenumain.xml @@ -0,0 +1,276 @@ + + + + + + + + + + + + + + +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/skins/default/xmlfiles/displaymenurecordings.xml b/skins/default/xmlfiles/displaymenurecordings.xml new file mode 100644 index 0000000..f7d1097 --- /dev/null +++ b/skins/default/xmlfiles/displaymenurecordings.xml @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/skins/default/xmlfiles/displaymenuschedules.xml b/skins/default/xmlfiles/displaymenuschedules.xml new file mode 100644 index 0000000..eb856c8 --- /dev/null +++ b/skins/default/xmlfiles/displaymenuschedules.xml @@ -0,0 +1,179 @@ + + +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/skins/default/xmlfiles/displaymenusetup.xml b/skins/default/xmlfiles/displaymenusetup.xml new file mode 100644 index 0000000..b5b8fb4 --- /dev/null +++ b/skins/default/xmlfiles/displaymenusetup.xml @@ -0,0 +1,107 @@ + + + + + + + + + + + +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/skins/default/xmlfiles/displaymenutimers.xml b/skins/default/xmlfiles/displaymenutimers.xml new file mode 100644 index 0000000..60b66a5 --- /dev/null +++ b/skins/default/xmlfiles/displaymenutimers.xml @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/skins/default/xmlfiles/displaymessage.xml b/skins/default/xmlfiles/displaymessage.xml new file mode 100644 index 0000000..01fbbdd --- /dev/null +++ b/skins/default/xmlfiles/displaymessage.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/skins/default/xmlfiles/displayreplay.xml b/skins/default/xmlfiles/displayreplay.xml new file mode 100644 index 0000000..0bf81a2 --- /dev/null +++ b/skins/default/xmlfiles/displayreplay.xml @@ -0,0 +1,231 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/skins/default/xmlfiles/displayvolume.xml b/skins/default/xmlfiles/displayvolume.xml new file mode 100644 index 0000000..25a54fe --- /dev/null +++ b/skins/default/xmlfiles/displayvolume.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/skins/default/xmlfiles/globals.xml b/skins/default/xmlfiles/globals.xml new file mode 100644 index 0000000..b66ddcb --- /dev/null +++ b/skins/default/xmlfiles/globals.xml @@ -0,0 +1,210 @@ + + + + + + + FFFF0000 + FF5FE200 + FFE2DA00 + FF007FE2 + C0000000 + D0000000 + FF1E8BD7 + C01E8BD7 + C0FFFFFF + FFFFFFFF + FF14141E + 00000000 + + + + 5 + 0 + hützligrütz + + + + + Active Timers + Aktive Timer + + + Active Timer + Aktiver Timer + + + Conflicts + Konflikte + + + Disc + Disk + + + free + frei + + + hours + Stunden + + + Reruns + Wiederholungen + + + Reruns of + Wiederholungen von + + + Actors + Schauspieler + + + Episode + Folge + + + Season + Staffel + + + Guest Stars + Gaststars + + + Series First Aired + Erstausstrahlung der Serie + + + Episode First Aired + Erstausstrahlung der Episode + + + Network + TV Station + + + Genre + Genre + + + Status + Status + + + Rating + Bewertung + + + Episode Rating + Bewertung der Folge + + + Recording Information + Aufnahme Informationen + + + Series Galery + Serien Galerie + + + Movie Galery + Spielfilm Galerie + + + Original Title + Originaltitel + + + Budget + Budget + + + Revenue + Einnahmen + + + Adult + Nur für Erwachsene + + + Release Date + Erscheinungsdatum + + + Runtime + Laufzeit + + + Popularity + Popularität + + + Vote Average + Durchschnittliche Wertung + + + Homepage + Homepage + + + Recording size + Größe der Aufnahme + + + Cutted Recording Size + Größe der geschnittenen Aufnahme + + + Recording Length + Länge der Aufnahme + + + Cutted Recording Length + Länge der geschnittenen Aufnahme + + + Bit Rate + Bitrate + + + Format + Format + + + Searchtimer + Suchtimer + + + Volume + Lautstärke + + + + + VDROpen Sans Light:Light + VDROpen Sans Semibold:Semibold + + diff --git a/skins/dtd/displayaudiotracks.dtd b/skins/dtd/displayaudiotracks.dtd new file mode 100644 index 0000000..e6cd869 --- /dev/null +++ b/skins/dtd/displayaudiotracks.dtd @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + +%functions; \ No newline at end of file diff --git a/skins/dtd/displaychannel.dtd b/skins/dtd/displaychannel.dtd new file mode 100644 index 0000000..538540b --- /dev/null +++ b/skins/dtd/displaychannel.dtd @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +%functions; diff --git a/skins/dtd/displaymenu.dtd b/skins/dtd/displaymenu.dtd new file mode 100644 index 0000000..b70a944 --- /dev/null +++ b/skins/dtd/displaymenu.dtd @@ -0,0 +1,251 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +%functions; \ No newline at end of file diff --git a/skins/dtd/displaymessage.dtd b/skins/dtd/displaymessage.dtd new file mode 100644 index 0000000..223ea2d --- /dev/null +++ b/skins/dtd/displaymessage.dtd @@ -0,0 +1,28 @@ + + + + + + + + + + + + + +%functions; \ No newline at end of file diff --git a/skins/dtd/displayreplay.dtd b/skins/dtd/displayreplay.dtd new file mode 100644 index 0000000..baf06d2 --- /dev/null +++ b/skins/dtd/displayreplay.dtd @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +%functions; \ No newline at end of file diff --git a/skins/dtd/displayvolume.dtd b/skins/dtd/displayvolume.dtd new file mode 100644 index 0000000..2be597d --- /dev/null +++ b/skins/dtd/displayvolume.dtd @@ -0,0 +1,28 @@ + + + + + + + + + + + + + +%functions; diff --git a/skins/dtd/functions.dtd b/skins/dtd/functions.dtd new file mode 100644 index 0000000..5e78876 --- /dev/null +++ b/skins/dtd/functions.dtd @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/skins/dtd/globals.dtd b/skins/dtd/globals.dtd new file mode 100644 index 0000000..570fa15 --- /dev/null +++ b/skins/dtd/globals.dtd @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/skins/nopacity/graphics/icons/ico_ac3.png b/skins/nopacity/graphics/icons/ico_ac3.png new file mode 100644 index 0000000..5b8614a Binary files /dev/null and b/skins/nopacity/graphics/icons/ico_ac3.png differ diff --git a/skins/nopacity/graphics/icons/ico_activetimer.png b/skins/nopacity/graphics/icons/ico_activetimer.png new file mode 100644 index 0000000..af4c33c Binary files /dev/null and b/skins/nopacity/graphics/icons/ico_activetimer.png differ diff --git a/skins/nopacity/graphics/icons/ico_arrow_left_channelsep.png b/skins/nopacity/graphics/icons/ico_arrow_left_channelsep.png new file mode 100644 index 0000000..642cd78 Binary files /dev/null and b/skins/nopacity/graphics/icons/ico_arrow_left_channelsep.png differ diff --git a/skins/nopacity/graphics/icons/ico_arrow_right_channelsep.png b/skins/nopacity/graphics/icons/ico_arrow_right_channelsep.png new file mode 100644 index 0000000..1418671 Binary files /dev/null and b/skins/nopacity/graphics/icons/ico_arrow_right_channelsep.png differ diff --git a/skins/nopacity/graphics/icons/ico_channelsep.png b/skins/nopacity/graphics/icons/ico_channelsep.png new file mode 100644 index 0000000..bf51238 Binary files /dev/null and b/skins/nopacity/graphics/icons/ico_channelsep.png differ diff --git a/skins/nopacity/graphics/icons/ico_cutted.png b/skins/nopacity/graphics/icons/ico_cutted.png new file mode 100644 index 0000000..b90c9c1 Binary files /dev/null and b/skins/nopacity/graphics/icons/ico_cutted.png differ diff --git a/skins/nopacity/graphics/icons/ico_daydelimiter.png b/skins/nopacity/graphics/icons/ico_daydelimiter.png new file mode 100644 index 0000000..7ae6053 Binary files /dev/null and b/skins/nopacity/graphics/icons/ico_daydelimiter.png differ diff --git a/skins/nopacity/graphics/icons/ico_discusage.png b/skins/nopacity/graphics/icons/ico_discusage.png new file mode 100644 index 0000000..f40fcd9 Binary files /dev/null and b/skins/nopacity/graphics/icons/ico_discusage.png differ diff --git a/skins/nopacity/graphics/icons/ico_dolbyoff.png b/skins/nopacity/graphics/icons/ico_dolbyoff.png new file mode 100644 index 0000000..ef4f17c Binary files /dev/null and b/skins/nopacity/graphics/icons/ico_dolbyoff.png differ diff --git a/skins/nopacity/graphics/icons/ico_dolbyon.png b/skins/nopacity/graphics/icons/ico_dolbyon.png new file mode 100644 index 0000000..1278abe Binary files /dev/null and b/skins/nopacity/graphics/icons/ico_dolbyon.png differ diff --git a/skins/nopacity/graphics/icons/ico_encrypted.png b/skins/nopacity/graphics/icons/ico_encrypted.png new file mode 100644 index 0000000..2b6345a Binary files /dev/null and b/skins/nopacity/graphics/icons/ico_encrypted.png differ diff --git a/skins/nopacity/graphics/icons/ico_ff.png b/skins/nopacity/graphics/icons/ico_ff.png new file mode 100644 index 0000000..3dea9d3 Binary files /dev/null and b/skins/nopacity/graphics/icons/ico_ff.png differ diff --git a/skins/nopacity/graphics/icons/ico_ff_1x.png b/skins/nopacity/graphics/icons/ico_ff_1x.png new file mode 100644 index 0000000..599256e Binary files /dev/null and b/skins/nopacity/graphics/icons/ico_ff_1x.png differ diff --git a/skins/nopacity/graphics/icons/ico_ff_2x.png b/skins/nopacity/graphics/icons/ico_ff_2x.png new file mode 100644 index 0000000..3eec356 Binary files /dev/null and b/skins/nopacity/graphics/icons/ico_ff_2x.png differ diff --git a/skins/nopacity/graphics/icons/ico_ff_3x.png b/skins/nopacity/graphics/icons/ico_ff_3x.png new file mode 100644 index 0000000..f686658 Binary files /dev/null and b/skins/nopacity/graphics/icons/ico_ff_3x.png differ diff --git a/skins/nopacity/graphics/icons/ico_ff_off.png b/skins/nopacity/graphics/icons/ico_ff_off.png new file mode 100644 index 0000000..cb551c2 Binary files /dev/null and b/skins/nopacity/graphics/icons/ico_ff_off.png differ diff --git a/skins/nopacity/graphics/icons/ico_fta.png b/skins/nopacity/graphics/icons/ico_fta.png new file mode 100644 index 0000000..55e3789 Binary files /dev/null and b/skins/nopacity/graphics/icons/ico_fta.png differ diff --git a/skins/nopacity/graphics/icons/ico_hd1080i.png b/skins/nopacity/graphics/icons/ico_hd1080i.png new file mode 100644 index 0000000..27b85ab Binary files /dev/null and b/skins/nopacity/graphics/icons/ico_hd1080i.png differ diff --git a/skins/nopacity/graphics/icons/ico_hd720p.png b/skins/nopacity/graphics/icons/ico_hd720p.png new file mode 100644 index 0000000..47317d8 Binary files /dev/null and b/skins/nopacity/graphics/icons/ico_hd720p.png differ diff --git a/skins/nopacity/graphics/icons/ico_mute.png b/skins/nopacity/graphics/icons/ico_mute.png new file mode 100644 index 0000000..4eefc75 Binary files /dev/null and b/skins/nopacity/graphics/icons/ico_mute.png differ diff --git a/skins/nopacity/graphics/icons/ico_pause.png b/skins/nopacity/graphics/icons/ico_pause.png new file mode 100644 index 0000000..cd8cad8 Binary files /dev/null and b/skins/nopacity/graphics/icons/ico_pause.png differ diff --git a/skins/nopacity/graphics/icons/ico_pause_off.png b/skins/nopacity/graphics/icons/ico_pause_off.png new file mode 100644 index 0000000..f9a9d94 Binary files /dev/null and b/skins/nopacity/graphics/icons/ico_pause_off.png differ diff --git a/skins/nopacity/graphics/icons/ico_play.png b/skins/nopacity/graphics/icons/ico_play.png new file mode 100644 index 0000000..4cc0541 Binary files /dev/null and b/skins/nopacity/graphics/icons/ico_play.png differ diff --git a/skins/nopacity/graphics/icons/ico_play_off.png b/skins/nopacity/graphics/icons/ico_play_off.png new file mode 100644 index 0000000..7fb820a Binary files /dev/null and b/skins/nopacity/graphics/icons/ico_play_off.png differ diff --git a/skins/nopacity/graphics/icons/ico_recfolder.png b/skins/nopacity/graphics/icons/ico_recfolder.png new file mode 100644 index 0000000..e3df65b Binary files /dev/null and b/skins/nopacity/graphics/icons/ico_recfolder.png differ diff --git a/skins/nopacity/graphics/icons/ico_recnew.png b/skins/nopacity/graphics/icons/ico_recnew.png new file mode 100644 index 0000000..b9166ba Binary files /dev/null and b/skins/nopacity/graphics/icons/ico_recnew.png differ diff --git a/skins/nopacity/graphics/icons/ico_recoff.png b/skins/nopacity/graphics/icons/ico_recoff.png new file mode 100644 index 0000000..4f59218 Binary files /dev/null and b/skins/nopacity/graphics/icons/ico_recoff.png differ diff --git a/skins/nopacity/graphics/icons/ico_recon.png b/skins/nopacity/graphics/icons/ico_recon.png new file mode 100644 index 0000000..14fe7be Binary files /dev/null and b/skins/nopacity/graphics/icons/ico_recon.png differ diff --git a/skins/nopacity/graphics/icons/ico_rew.png b/skins/nopacity/graphics/icons/ico_rew.png new file mode 100644 index 0000000..72408d0 Binary files /dev/null and b/skins/nopacity/graphics/icons/ico_rew.png differ diff --git a/skins/nopacity/graphics/icons/ico_rew_1x.png b/skins/nopacity/graphics/icons/ico_rew_1x.png new file mode 100644 index 0000000..333c30d Binary files /dev/null and b/skins/nopacity/graphics/icons/ico_rew_1x.png differ diff --git a/skins/nopacity/graphics/icons/ico_rew_2x.png b/skins/nopacity/graphics/icons/ico_rew_2x.png new file mode 100644 index 0000000..c5d1084 Binary files /dev/null and b/skins/nopacity/graphics/icons/ico_rew_2x.png differ diff --git a/skins/nopacity/graphics/icons/ico_rew_3x.png b/skins/nopacity/graphics/icons/ico_rew_3x.png new file mode 100644 index 0000000..6ab7a8d Binary files /dev/null and b/skins/nopacity/graphics/icons/ico_rew_3x.png differ diff --git a/skins/nopacity/graphics/icons/ico_rew_off.png b/skins/nopacity/graphics/icons/ico_rew_off.png new file mode 100644 index 0000000..ce18386 Binary files /dev/null and b/skins/nopacity/graphics/icons/ico_rew_off.png differ diff --git a/skins/nopacity/graphics/icons/ico_sd576i.png b/skins/nopacity/graphics/icons/ico_sd576i.png new file mode 100644 index 0000000..994a7a2 Binary files /dev/null and b/skins/nopacity/graphics/icons/ico_sd576i.png differ diff --git a/skins/nopacity/graphics/icons/ico_stereo.png b/skins/nopacity/graphics/icons/ico_stereo.png new file mode 100644 index 0000000..7f3610d Binary files /dev/null and b/skins/nopacity/graphics/icons/ico_stereo.png differ diff --git a/skins/nopacity/graphics/icons/ico_stereooff.png b/skins/nopacity/graphics/icons/ico_stereooff.png new file mode 100644 index 0000000..569a342 Binary files /dev/null and b/skins/nopacity/graphics/icons/ico_stereooff.png differ diff --git a/skins/nopacity/graphics/icons/ico_stereoon.png b/skins/nopacity/graphics/icons/ico_stereoon.png new file mode 100644 index 0000000..eb838b9 Binary files /dev/null and b/skins/nopacity/graphics/icons/ico_stereoon.png differ diff --git a/skins/nopacity/graphics/icons/ico_timer_active.png b/skins/nopacity/graphics/icons/ico_timer_active.png new file mode 100644 index 0000000..28c2f81 Binary files /dev/null and b/skins/nopacity/graphics/icons/ico_timer_active.png differ diff --git a/skins/nopacity/graphics/icons/ico_timer_inactive.png b/skins/nopacity/graphics/icons/ico_timer_inactive.png new file mode 100644 index 0000000..c4b1860 Binary files /dev/null and b/skins/nopacity/graphics/icons/ico_timer_inactive.png differ diff --git a/skins/nopacity/graphics/icons/ico_timer_recording.png b/skins/nopacity/graphics/icons/ico_timer_recording.png new file mode 100644 index 0000000..86dc66b Binary files /dev/null and b/skins/nopacity/graphics/icons/ico_timer_recording.png differ diff --git a/skins/nopacity/graphics/icons/ico_txtoff.png b/skins/nopacity/graphics/icons/ico_txtoff.png new file mode 100644 index 0000000..3b2eac3 Binary files /dev/null and b/skins/nopacity/graphics/icons/ico_txtoff.png differ diff --git a/skins/nopacity/graphics/icons/ico_txton.png b/skins/nopacity/graphics/icons/ico_txton.png new file mode 100644 index 0000000..148f9ef Binary files /dev/null and b/skins/nopacity/graphics/icons/ico_txton.png differ diff --git a/skins/nopacity/graphics/icons/ico_vdrlogo.png b/skins/nopacity/graphics/icons/ico_vdrlogo.png new file mode 100644 index 0000000..200cea7 Binary files /dev/null and b/skins/nopacity/graphics/icons/ico_vdrlogo.png differ diff --git a/skins/nopacity/graphics/icons/ico_volume.png b/skins/nopacity/graphics/icons/ico_volume.png new file mode 100644 index 0000000..3a72514 Binary files /dev/null and b/skins/nopacity/graphics/icons/ico_volume.png differ diff --git a/skins/nopacity/graphics/menuicons/customicons/Applikationen.png b/skins/nopacity/graphics/menuicons/customicons/Applikationen.png new file mode 100644 index 0000000..3c3b616 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/customicons/Applikationen.png differ diff --git a/skins/nopacity/graphics/menuicons/customicons/Audio.png b/skins/nopacity/graphics/menuicons/customicons/Audio.png new file mode 100644 index 0000000..ff387fe Binary files /dev/null and b/skins/nopacity/graphics/menuicons/customicons/Audio.png differ diff --git a/skins/nopacity/graphics/menuicons/customicons/Aufnahmen-Liste aktualisieren.png b/skins/nopacity/graphics/menuicons/customicons/Aufnahmen-Liste aktualisieren.png new file mode 100644 index 0000000..3cdddc9 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/customicons/Aufnahmen-Liste aktualisieren.png differ diff --git a/skins/nopacity/graphics/menuicons/customicons/Dienstprogramme.png b/skins/nopacity/graphics/menuicons/customicons/Dienstprogramme.png new file mode 100644 index 0000000..793aba6 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/customicons/Dienstprogramme.png differ diff --git a/skins/nopacity/graphics/menuicons/customicons/FireFox.png b/skins/nopacity/graphics/menuicons/customicons/FireFox.png new file mode 100644 index 0000000..192fadc Binary files /dev/null and b/skins/nopacity/graphics/menuicons/customicons/FireFox.png differ diff --git a/skins/nopacity/graphics/menuicons/customicons/Info.png b/skins/nopacity/graphics/menuicons/customicons/Info.png new file mode 100644 index 0000000..6737431 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/customicons/Info.png differ diff --git a/skins/nopacity/graphics/menuicons/customicons/Internet.png b/skins/nopacity/graphics/menuicons/customicons/Internet.png new file mode 100644 index 0000000..f3db150 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/customicons/Internet.png differ diff --git a/skins/nopacity/graphics/menuicons/customicons/Medien.png b/skins/nopacity/graphics/menuicons/customicons/Medien.png new file mode 100644 index 0000000..0ce2360 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/customicons/Medien.png differ diff --git a/skins/nopacity/graphics/menuicons/customicons/Rechner neu starten.png b/skins/nopacity/graphics/menuicons/customicons/Rechner neu starten.png new file mode 100644 index 0000000..5783ccf Binary files /dev/null and b/skins/nopacity/graphics/menuicons/customicons/Rechner neu starten.png differ diff --git a/skins/nopacity/graphics/menuicons/customicons/Remote wakeup.png b/skins/nopacity/graphics/menuicons/customicons/Remote wakeup.png new file mode 100644 index 0000000..1cd2f6e Binary files /dev/null and b/skins/nopacity/graphics/menuicons/customicons/Remote wakeup.png differ diff --git a/skins/nopacity/graphics/menuicons/customicons/Spiele.png b/skins/nopacity/graphics/menuicons/customicons/Spiele.png new file mode 100644 index 0000000..8e07161 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/customicons/Spiele.png differ diff --git a/skins/nopacity/graphics/menuicons/customicons/System herunterfahren.png b/skins/nopacity/graphics/menuicons/customicons/System herunterfahren.png new file mode 100644 index 0000000..e0234df Binary files /dev/null and b/skins/nopacity/graphics/menuicons/customicons/System herunterfahren.png differ diff --git a/skins/nopacity/graphics/menuicons/customicons/System.png b/skins/nopacity/graphics/menuicons/customicons/System.png new file mode 100644 index 0000000..81d100e Binary files /dev/null and b/skins/nopacity/graphics/menuicons/customicons/System.png differ diff --git a/skins/nopacity/graphics/menuicons/customicons/Tools.png b/skins/nopacity/graphics/menuicons/customicons/Tools.png new file mode 100644 index 0000000..cf328ef Binary files /dev/null and b/skins/nopacity/graphics/menuicons/customicons/Tools.png differ diff --git a/skins/nopacity/graphics/menuicons/customicons/Tunderbird.png b/skins/nopacity/graphics/menuicons/customicons/Tunderbird.png new file mode 100644 index 0000000..5ae27e0 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/customicons/Tunderbird.png differ diff --git a/skins/nopacity/graphics/menuicons/customicons/USB Massenspeicher sicher entfernen.png b/skins/nopacity/graphics/menuicons/customicons/USB Massenspeicher sicher entfernen.png new file mode 100644 index 0000000..cd7b81c Binary files /dev/null and b/skins/nopacity/graphics/menuicons/customicons/USB Massenspeicher sicher entfernen.png differ diff --git a/skins/nopacity/graphics/menuicons/customicons/VDR neu starten.png b/skins/nopacity/graphics/menuicons/customicons/VDR neu starten.png new file mode 100644 index 0000000..14904ca Binary files /dev/null and b/skins/nopacity/graphics/menuicons/customicons/VDR neu starten.png differ diff --git a/skins/nopacity/graphics/menuicons/customicons/Video.png b/skins/nopacity/graphics/menuicons/customicons/Video.png new file mode 100644 index 0000000..490ca4b Binary files /dev/null and b/skins/nopacity/graphics/menuicons/customicons/Video.png differ diff --git a/skins/nopacity/graphics/menuicons/customicons/Web.png b/skins/nopacity/graphics/menuicons/customicons/Web.png new file mode 100644 index 0000000..20260e3 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/customicons/Web.png differ diff --git a/skins/nopacity/graphics/menuicons/customicons/XBMC.png b/skins/nopacity/graphics/menuicons/customicons/XBMC.png new file mode 100644 index 0000000..c7c4c04 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/customicons/XBMC.png differ diff --git a/skins/nopacity/graphics/menuicons/customicons/Xterm.png b/skins/nopacity/graphics/menuicons/customicons/Xterm.png new file mode 100644 index 0000000..fa75282 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/customicons/Xterm.png differ diff --git a/skins/nopacity/graphics/menuicons/customicons/audiovideo.png b/skins/nopacity/graphics/menuicons/customicons/audiovideo.png new file mode 100644 index 0000000..726538d Binary files /dev/null and b/skins/nopacity/graphics/menuicons/customicons/audiovideo.png differ diff --git a/skins/nopacity/graphics/menuicons/customicons/markad_status.png b/skins/nopacity/graphics/menuicons/customicons/markad_status.png new file mode 100644 index 0000000..4fdc7a4 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/customicons/markad_status.png differ diff --git a/skins/nopacity/graphics/menuicons/customicons/schneiden_abbrechen.png b/skins/nopacity/graphics/menuicons/customicons/schneiden_abbrechen.png new file mode 100644 index 0000000..b2e0bd3 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/customicons/schneiden_abbrechen.png differ diff --git a/skins/nopacity/graphics/menuicons/customicons/tux.png b/skins/nopacity/graphics/menuicons/customicons/tux.png new file mode 100644 index 0000000..c5b4742 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/customicons/tux.png differ diff --git a/skins/nopacity/graphics/menuicons/customicons/usb.png b/skins/nopacity/graphics/menuicons/customicons/usb.png new file mode 100644 index 0000000..c4db1d4 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/customicons/usb.png differ diff --git a/skins/nopacity/graphics/menuicons/customicons/vdrlogo.png b/skins/nopacity/graphics/menuicons/customicons/vdrlogo.png new file mode 100644 index 0000000..037a191 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/customicons/vdrlogo.png differ diff --git a/skins/nopacity/graphics/menuicons/customicons/yaicon_blue.png b/skins/nopacity/graphics/menuicons/customicons/yaicon_blue.png new file mode 100644 index 0000000..2c49273 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/customicons/yaicon_blue.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/admin.png b/skins/nopacity/graphics/menuicons/pluginicons/admin.png new file mode 100644 index 0000000..cf328ef Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/admin.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/arghdirector.png b/skins/nopacity/graphics/menuicons/pluginicons/arghdirector.png new file mode 100644 index 0000000..bbd221a Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/arghdirector.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/autostart.png b/skins/nopacity/graphics/menuicons/pluginicons/autostart.png new file mode 100644 index 0000000..6fdb1bb Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/autostart.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/avahi4vdr.png b/skins/nopacity/graphics/menuicons/pluginicons/avahi4vdr.png new file mode 100644 index 0000000..044e71d Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/avahi4vdr.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/avards.png b/skins/nopacity/graphics/menuicons/pluginicons/avards.png new file mode 100644 index 0000000..cf8d037 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/avards.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/block.png b/skins/nopacity/graphics/menuicons/pluginicons/block.png new file mode 100644 index 0000000..86127c2 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/block.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/burn.png b/skins/nopacity/graphics/menuicons/pluginicons/burn.png new file mode 100644 index 0000000..305d7ff Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/burn.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/cdplayer.png b/skins/nopacity/graphics/menuicons/pluginicons/cdplayer.png new file mode 100644 index 0000000..89a6c19 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/cdplayer.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/chanman.png b/skins/nopacity/graphics/menuicons/pluginicons/chanman.png new file mode 100644 index 0000000..a73e83c Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/chanman.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/check.png b/skins/nopacity/graphics/menuicons/pluginicons/check.png new file mode 100644 index 0000000..d487a24 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/check.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/conflictcheckonly.png b/skins/nopacity/graphics/menuicons/pluginicons/conflictcheckonly.png new file mode 100644 index 0000000..7f832bd Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/conflictcheckonly.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/ddci.png b/skins/nopacity/graphics/menuicons/pluginicons/ddci.png new file mode 100644 index 0000000..4ad459c Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/ddci.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/devstatus.png b/skins/nopacity/graphics/menuicons/pluginicons/devstatus.png new file mode 100644 index 0000000..96c0ec1 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/devstatus.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/dummydevice.png b/skins/nopacity/graphics/menuicons/pluginicons/dummydevice.png new file mode 100644 index 0000000..11fd707 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/dummydevice.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/duplicates.png b/skins/nopacity/graphics/menuicons/pluginicons/duplicates.png new file mode 100644 index 0000000..dc1be57 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/duplicates.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/dvbapi.png b/skins/nopacity/graphics/menuicons/pluginicons/dvbapi.png new file mode 100644 index 0000000..b966461 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/dvbapi.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/dvbhddevice.png b/skins/nopacity/graphics/menuicons/pluginicons/dvbhddevice.png new file mode 100644 index 0000000..b874297 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/dvbhddevice.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/dvbsddevice.png b/skins/nopacity/graphics/menuicons/pluginicons/dvbsddevice.png new file mode 100644 index 0000000..106184e Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/dvbsddevice.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/dynamite.png b/skins/nopacity/graphics/menuicons/pluginicons/dynamite.png new file mode 100644 index 0000000..28ea35a Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/dynamite.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/eepg.png b/skins/nopacity/graphics/menuicons/pluginicons/eepg.png new file mode 100644 index 0000000..3938b96 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/eepg.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/epg2vdr.png b/skins/nopacity/graphics/menuicons/pluginicons/epg2vdr.png new file mode 100644 index 0000000..ac8757e Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/epg2vdr.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/epgsearch.png b/skins/nopacity/graphics/menuicons/pluginicons/epgsearch.png new file mode 100644 index 0000000..5eab415 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/epgsearch.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/epgsearchonly.png b/skins/nopacity/graphics/menuicons/pluginicons/epgsearchonly.png new file mode 100644 index 0000000..b5186e7 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/epgsearchonly.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/epgsync.png b/skins/nopacity/graphics/menuicons/pluginicons/epgsync.png new file mode 100644 index 0000000..5c14009 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/epgsync.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/externalplayer.png b/skins/nopacity/graphics/menuicons/pluginicons/externalplayer.png new file mode 100644 index 0000000..2bd67db Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/externalplayer.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/extrecmenu.png b/skins/nopacity/graphics/menuicons/pluginicons/extrecmenu.png new file mode 100644 index 0000000..6f613f1 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/extrecmenu.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/favorites.png b/skins/nopacity/graphics/menuicons/pluginicons/favorites.png new file mode 100644 index 0000000..409c852 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/favorites.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/femon.png b/skins/nopacity/graphics/menuicons/pluginicons/femon.png new file mode 100644 index 0000000..e87b711 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/femon.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/fepg.png b/skins/nopacity/graphics/menuicons/pluginicons/fepg.png new file mode 100644 index 0000000..65023ed Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/fepg.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/filebrowser.png b/skins/nopacity/graphics/menuicons/pluginicons/filebrowser.png new file mode 100644 index 0000000..d3f90e0 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/filebrowser.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/fritzbox.png b/skins/nopacity/graphics/menuicons/pluginicons/fritzbox.png new file mode 100644 index 0000000..7bfc229 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/fritzbox.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/graphlcd.png b/skins/nopacity/graphics/menuicons/pluginicons/graphlcd.png new file mode 100644 index 0000000..39ffd35 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/graphlcd.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/graphtft.png b/skins/nopacity/graphics/menuicons/pluginicons/graphtft.png new file mode 100644 index 0000000..39ffd35 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/graphtft.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/image.png b/skins/nopacity/graphics/menuicons/pluginicons/image.png new file mode 100644 index 0000000..33644e0 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/image.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/imonlcd.png b/skins/nopacity/graphics/menuicons/pluginicons/imonlcd.png new file mode 100644 index 0000000..3d34fc4 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/imonlcd.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/iptv.png b/skins/nopacity/graphics/menuicons/pluginicons/iptv.png new file mode 100644 index 0000000..4494ddc Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/iptv.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/lcdproc.png b/skins/nopacity/graphics/menuicons/pluginicons/lcdproc.png new file mode 100644 index 0000000..3d34fc4 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/lcdproc.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/mailbox.png b/skins/nopacity/graphics/menuicons/pluginicons/mailbox.png new file mode 100644 index 0000000..1bc76e8 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/mailbox.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/makemkv.png b/skins/nopacity/graphics/menuicons/pluginicons/makemkv.png new file mode 100644 index 0000000..41cddf1 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/makemkv.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/markad.png b/skins/nopacity/graphics/menuicons/pluginicons/markad.png new file mode 100644 index 0000000..b3defaf Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/markad.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/mlist.png b/skins/nopacity/graphics/menuicons/pluginicons/mlist.png new file mode 100644 index 0000000..19c367f Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/mlist.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/music.png b/skins/nopacity/graphics/menuicons/pluginicons/music.png new file mode 100644 index 0000000..abb012e Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/music.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/noepg.png b/skins/nopacity/graphics/menuicons/pluginicons/noepg.png new file mode 100644 index 0000000..eb9410d Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/noepg.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/nordlichtsepg.png b/skins/nopacity/graphics/menuicons/pluginicons/nordlichtsepg.png new file mode 100644 index 0000000..3ee3fa2 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/nordlichtsepg.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/osdteletext.png b/skins/nopacity/graphics/menuicons/pluginicons/osdteletext.png new file mode 100644 index 0000000..664e770 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/osdteletext.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/peer.png b/skins/nopacity/graphics/menuicons/pluginicons/peer.png new file mode 100644 index 0000000..998d568 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/peer.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/play.png b/skins/nopacity/graphics/menuicons/pluginicons/play.png new file mode 100644 index 0000000..2848fc6 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/play.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/pvrinput.png b/skins/nopacity/graphics/menuicons/pluginicons/pvrinput.png new file mode 100644 index 0000000..724f698 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/pvrinput.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/quickepgsearch.png b/skins/nopacity/graphics/menuicons/pluginicons/quickepgsearch.png new file mode 100644 index 0000000..76a31f4 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/quickepgsearch.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/radio.png b/skins/nopacity/graphics/menuicons/pluginicons/radio.png new file mode 100644 index 0000000..193b7d4 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/radio.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/remote.png b/skins/nopacity/graphics/menuicons/pluginicons/remote.png new file mode 100644 index 0000000..7f46b1b Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/remote.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/remotetimers.png b/skins/nopacity/graphics/menuicons/pluginicons/remotetimers.png new file mode 100644 index 0000000..fae3b79 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/remotetimers.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/rssreader.png b/skins/nopacity/graphics/menuicons/pluginicons/rssreader.png new file mode 100644 index 0000000..db538f0 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/rssreader.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/sc.png b/skins/nopacity/graphics/menuicons/pluginicons/sc.png new file mode 100644 index 0000000..2472d6c Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/sc.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/screenshot.png b/skins/nopacity/graphics/menuicons/pluginicons/screenshot.png new file mode 100644 index 0000000..be9b4d5 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/screenshot.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/seduatmo.png b/skins/nopacity/graphics/menuicons/pluginicons/seduatmo.png new file mode 100644 index 0000000..4b5292f Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/seduatmo.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/skyselectfeeds.png b/skins/nopacity/graphics/menuicons/pluginicons/skyselectfeeds.png new file mode 100644 index 0000000..d81a024 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/skyselectfeeds.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/sleeptimer.png b/skins/nopacity/graphics/menuicons/pluginicons/sleeptimer.png new file mode 100644 index 0000000..cd4956f Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/sleeptimer.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/softhddevice.png b/skins/nopacity/graphics/menuicons/pluginicons/softhddevice.png new file mode 100644 index 0000000..df13f2c Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/softhddevice.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/streamdev-server.png b/skins/nopacity/graphics/menuicons/pluginicons/streamdev-server.png new file mode 100644 index 0000000..e89ed8b Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/streamdev-server.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/systeminfo.png b/skins/nopacity/graphics/menuicons/pluginicons/systeminfo.png new file mode 100644 index 0000000..b14763f Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/systeminfo.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/targavfd.png b/skins/nopacity/graphics/menuicons/pluginicons/targavfd.png new file mode 100644 index 0000000..e91b111 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/targavfd.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/trayopenng.png b/skins/nopacity/graphics/menuicons/pluginicons/trayopenng.png new file mode 100644 index 0000000..6ebd17d Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/trayopenng.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/tvguide.png b/skins/nopacity/graphics/menuicons/pluginicons/tvguide.png new file mode 100644 index 0000000..968a37c Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/tvguide.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/tvm2vdr.png b/skins/nopacity/graphics/menuicons/pluginicons/tvm2vdr.png new file mode 100644 index 0000000..47f9a91 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/tvm2vdr.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/tvscraper.png b/skins/nopacity/graphics/menuicons/pluginicons/tvscraper.png new file mode 100644 index 0000000..a106cb5 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/tvscraper.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/undelete.png b/skins/nopacity/graphics/menuicons/pluginicons/undelete.png new file mode 100644 index 0000000..a53d50a Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/undelete.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/weatherng.png b/skins/nopacity/graphics/menuicons/pluginicons/weatherng.png new file mode 100644 index 0000000..a88f11d Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/weatherng.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/xmltv2vdr.png b/skins/nopacity/graphics/menuicons/pluginicons/xmltv2vdr.png new file mode 100644 index 0000000..ea73c74 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/xmltv2vdr.png differ diff --git a/skins/nopacity/graphics/menuicons/pluginicons/yaepghg.png b/skins/nopacity/graphics/menuicons/pluginicons/yaepghg.png new file mode 100644 index 0000000..53ce443 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/pluginicons/yaepghg.png differ diff --git a/skins/nopacity/graphics/menuicons/standardicons/CAM.png b/skins/nopacity/graphics/menuicons/standardicons/CAM.png new file mode 100644 index 0000000..a394877 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/standardicons/CAM.png differ diff --git a/skins/nopacity/graphics/menuicons/standardicons/Channels.png b/skins/nopacity/graphics/menuicons/standardicons/Channels.png new file mode 100644 index 0000000..ba2ba78 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/standardicons/Channels.png differ diff --git a/skins/nopacity/graphics/menuicons/standardicons/Commands.png b/skins/nopacity/graphics/menuicons/standardicons/Commands.png new file mode 100644 index 0000000..c6a83ef Binary files /dev/null and b/skins/nopacity/graphics/menuicons/standardicons/Commands.png differ diff --git a/skins/nopacity/graphics/menuicons/standardicons/DVB.png b/skins/nopacity/graphics/menuicons/standardicons/DVB.png new file mode 100644 index 0000000..3789145 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/standardicons/DVB.png differ diff --git a/skins/nopacity/graphics/menuicons/standardicons/EPG.png b/skins/nopacity/graphics/menuicons/standardicons/EPG.png new file mode 100644 index 0000000..e868b90 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/standardicons/EPG.png differ diff --git a/skins/nopacity/graphics/menuicons/standardicons/LNB.png b/skins/nopacity/graphics/menuicons/standardicons/LNB.png new file mode 100644 index 0000000..896dd99 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/standardicons/LNB.png differ diff --git a/skins/nopacity/graphics/menuicons/standardicons/Miscellaneous.png b/skins/nopacity/graphics/menuicons/standardicons/Miscellaneous.png new file mode 100644 index 0000000..2a41c4d Binary files /dev/null and b/skins/nopacity/graphics/menuicons/standardicons/Miscellaneous.png differ diff --git a/skins/nopacity/graphics/menuicons/standardicons/OSD.png b/skins/nopacity/graphics/menuicons/standardicons/OSD.png new file mode 100644 index 0000000..8f571c6 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/standardicons/OSD.png differ diff --git a/skins/nopacity/graphics/menuicons/standardicons/Plugins.png b/skins/nopacity/graphics/menuicons/standardicons/Plugins.png new file mode 100644 index 0000000..3fcba70 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/standardicons/Plugins.png differ diff --git a/skins/nopacity/graphics/menuicons/standardicons/Recording.png b/skins/nopacity/graphics/menuicons/standardicons/Recording.png new file mode 100644 index 0000000..741b1af Binary files /dev/null and b/skins/nopacity/graphics/menuicons/standardicons/Recording.png differ diff --git a/skins/nopacity/graphics/menuicons/standardicons/Recordings.png b/skins/nopacity/graphics/menuicons/standardicons/Recordings.png new file mode 100644 index 0000000..79aeeb7 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/standardicons/Recordings.png differ diff --git a/skins/nopacity/graphics/menuicons/standardicons/Replay.png b/skins/nopacity/graphics/menuicons/standardicons/Replay.png new file mode 100644 index 0000000..621596c Binary files /dev/null and b/skins/nopacity/graphics/menuicons/standardicons/Replay.png differ diff --git a/skins/nopacity/graphics/menuicons/standardicons/Restart.png b/skins/nopacity/graphics/menuicons/standardicons/Restart.png new file mode 100644 index 0000000..aa23cd4 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/standardicons/Restart.png differ diff --git a/skins/nopacity/graphics/menuicons/standardicons/Schedule.png b/skins/nopacity/graphics/menuicons/standardicons/Schedule.png new file mode 100644 index 0000000..3a98cac Binary files /dev/null and b/skins/nopacity/graphics/menuicons/standardicons/Schedule.png differ diff --git a/skins/nopacity/graphics/menuicons/standardicons/Setup.png b/skins/nopacity/graphics/menuicons/standardicons/Setup.png new file mode 100644 index 0000000..d121148 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/standardicons/Setup.png differ diff --git a/skins/nopacity/graphics/menuicons/standardicons/StopRecording.png b/skins/nopacity/graphics/menuicons/standardicons/StopRecording.png new file mode 100644 index 0000000..ed83fbb Binary files /dev/null and b/skins/nopacity/graphics/menuicons/standardicons/StopRecording.png differ diff --git a/skins/nopacity/graphics/menuicons/standardicons/StopReplay.png b/skins/nopacity/graphics/menuicons/standardicons/StopReplay.png new file mode 100644 index 0000000..9192760 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/standardicons/StopReplay.png differ diff --git a/skins/nopacity/graphics/menuicons/standardicons/Timers.png b/skins/nopacity/graphics/menuicons/standardicons/Timers.png new file mode 100644 index 0000000..b866c36 Binary files /dev/null and b/skins/nopacity/graphics/menuicons/standardicons/Timers.png differ diff --git a/skins/nopacity/graphics/skinparts/buttonblue.png b/skins/nopacity/graphics/skinparts/buttonblue.png new file mode 100644 index 0000000..d00e4d2 Binary files /dev/null and b/skins/nopacity/graphics/skinparts/buttonblue.png differ diff --git a/skins/nopacity/graphics/skinparts/buttongreen.png b/skins/nopacity/graphics/skinparts/buttongreen.png new file mode 100644 index 0000000..8c05c08 Binary files /dev/null and b/skins/nopacity/graphics/skinparts/buttongreen.png differ diff --git a/skins/nopacity/graphics/skinparts/buttonred.png b/skins/nopacity/graphics/skinparts/buttonred.png new file mode 100644 index 0000000..9367c9b Binary files /dev/null and b/skins/nopacity/graphics/skinparts/buttonred.png differ diff --git a/skins/nopacity/graphics/skinparts/buttonyellow.png b/skins/nopacity/graphics/skinparts/buttonyellow.png new file mode 100644 index 0000000..aff8758 Binary files /dev/null and b/skins/nopacity/graphics/skinparts/buttonyellow.png differ diff --git a/skins/nopacity/graphics/skinparts/channellogoback.png b/skins/nopacity/graphics/skinparts/channellogoback.png new file mode 100644 index 0000000..b0e83b1 Binary files /dev/null and b/skins/nopacity/graphics/skinparts/channellogoback.png differ diff --git a/skins/nopacity/graphics/skinparts/discpercent.png b/skins/nopacity/graphics/skinparts/discpercent.png new file mode 100644 index 0000000..cf32be2 Binary files /dev/null and b/skins/nopacity/graphics/skinparts/discpercent.png differ diff --git a/skins/nopacity/graphics/skinparts/displaychannelback.png b/skins/nopacity/graphics/skinparts/displaychannelback.png new file mode 100644 index 0000000..1437384 Binary files /dev/null and b/skins/nopacity/graphics/skinparts/displaychannelback.png differ diff --git a/skins/nopacity/graphics/skinparts/displaychanneltop.png b/skins/nopacity/graphics/skinparts/displaychanneltop.png new file mode 100644 index 0000000..5108435 Binary files /dev/null and b/skins/nopacity/graphics/skinparts/displaychanneltop.png differ diff --git a/skins/nopacity/graphics/skinparts/displayreplayback.png b/skins/nopacity/graphics/skinparts/displayreplayback.png new file mode 100644 index 0000000..d72931f Binary files /dev/null and b/skins/nopacity/graphics/skinparts/displayreplayback.png differ diff --git a/skins/nopacity/graphics/skinparts/displayreplaytop.png b/skins/nopacity/graphics/skinparts/displayreplaytop.png new file mode 100644 index 0000000..064347e Binary files /dev/null and b/skins/nopacity/graphics/skinparts/displayreplaytop.png differ diff --git a/skins/nopacity/graphics/skinparts/displayvolume.png b/skins/nopacity/graphics/skinparts/displayvolume.png new file mode 100644 index 0000000..a5c4c66 Binary files /dev/null and b/skins/nopacity/graphics/skinparts/displayvolume.png differ diff --git a/skins/nopacity/graphics/skinparts/headertop.png b/skins/nopacity/graphics/skinparts/headertop.png new file mode 100644 index 0000000..2bc19a6 Binary files /dev/null and b/skins/nopacity/graphics/skinparts/headertop.png differ diff --git a/skins/nopacity/graphics/skinparts/menubutton.png b/skins/nopacity/graphics/skinparts/menubutton.png new file mode 100644 index 0000000..0800a5e Binary files /dev/null and b/skins/nopacity/graphics/skinparts/menubutton.png differ diff --git a/skins/nopacity/graphics/skinparts/menubuttonactive.png b/skins/nopacity/graphics/skinparts/menubuttonactive.png new file mode 100644 index 0000000..caae104 Binary files /dev/null and b/skins/nopacity/graphics/skinparts/menubuttonactive.png differ diff --git a/skins/nopacity/graphics/skinparts/menubuttondefault.png b/skins/nopacity/graphics/skinparts/menubuttondefault.png new file mode 100644 index 0000000..76735de Binary files /dev/null and b/skins/nopacity/graphics/skinparts/menubuttondefault.png differ diff --git a/skins/nopacity/graphics/skinparts/menubuttondefaultactive.png b/skins/nopacity/graphics/skinparts/menubuttondefaultactive.png new file mode 100644 index 0000000..70c0b8a Binary files /dev/null and b/skins/nopacity/graphics/skinparts/menubuttondefaultactive.png differ diff --git a/skins/nopacity/graphics/skinparts/menubuttontop.png b/skins/nopacity/graphics/skinparts/menubuttontop.png new file mode 100644 index 0000000..1b49cfd Binary files /dev/null and b/skins/nopacity/graphics/skinparts/menubuttontop.png differ diff --git a/skins/nopacity/graphics/skinparts/messageError.png b/skins/nopacity/graphics/skinparts/messageError.png new file mode 100644 index 0000000..a894992 Binary files /dev/null and b/skins/nopacity/graphics/skinparts/messageError.png differ diff --git a/skins/nopacity/graphics/skinparts/messageInfo.png b/skins/nopacity/graphics/skinparts/messageInfo.png new file mode 100644 index 0000000..5f8e62a Binary files /dev/null and b/skins/nopacity/graphics/skinparts/messageInfo.png differ diff --git a/skins/nopacity/graphics/skinparts/messageStatus.png b/skins/nopacity/graphics/skinparts/messageStatus.png new file mode 100644 index 0000000..f4b83f4 Binary files /dev/null and b/skins/nopacity/graphics/skinparts/messageStatus.png differ diff --git a/skins/nopacity/graphics/skinparts/messageWarning.png b/skins/nopacity/graphics/skinparts/messageWarning.png new file mode 100644 index 0000000..f073ed5 Binary files /dev/null and b/skins/nopacity/graphics/skinparts/messageWarning.png differ diff --git a/skins/nopacity/graphics/skinparts/scrollbar.png b/skins/nopacity/graphics/skinparts/scrollbar.png new file mode 100644 index 0000000..f822555 Binary files /dev/null and b/skins/nopacity/graphics/skinparts/scrollbar.png differ diff --git a/skins/nopacity/graphics/skinparts/signal.png b/skins/nopacity/graphics/skinparts/signal.png new file mode 100644 index 0000000..4f03c7a Binary files /dev/null and b/skins/nopacity/graphics/skinparts/signal.png differ diff --git a/skins/nopacity/xmlfiles/displayaudiotracks.xml b/skins/nopacity/xmlfiles/displayaudiotracks.xml new file mode 100644 index 0000000..688f374 --- /dev/null +++ b/skins/nopacity/xmlfiles/displayaudiotracks.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + +
+ + + + + +
+ + + + + + + + + + + + + + + + +
diff --git a/skins/nopacity/xmlfiles/displaychannel.xml b/skins/nopacity/xmlfiles/displaychannel.xml new file mode 100644 index 0000000..8355f84 --- /dev/null +++ b/skins/nopacity/xmlfiles/displaychannel.xml @@ -0,0 +1,218 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/skins/nopacity/xmlfiles/displaymenu.xml b/skins/nopacity/xmlfiles/displaymenu.xml new file mode 100644 index 0000000..f70f6d2 --- /dev/null +++ b/skins/nopacity/xmlfiles/displaymenu.xml @@ -0,0 +1,188 @@ + + + + + + + + + + + +]> + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + &displaymenudefault; + &displaymenumain; + &displaymenusetup; + &displaymenuschedules; + &displaymenutimers; + &displaymenuchannels; + &displaymenurecordings; + &displaymenudetailepg; + &displaymenudetailrecording; + &displaymenudetailtext; +
diff --git a/skins/nopacity/xmlfiles/displaymenuchannels.xml b/skins/nopacity/xmlfiles/displaymenuchannels.xml new file mode 100644 index 0000000..9e1512f --- /dev/null +++ b/skins/nopacity/xmlfiles/displaymenuchannels.xml @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/skins/nopacity/xmlfiles/displaymenudefault.xml b/skins/nopacity/xmlfiles/displaymenudefault.xml new file mode 100644 index 0000000..2c51339 --- /dev/null +++ b/skins/nopacity/xmlfiles/displaymenudefault.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/skins/nopacity/xmlfiles/displaymenudetailepg.xml b/skins/nopacity/xmlfiles/displaymenudetailepg.xml new file mode 100644 index 0000000..3635ec8 --- /dev/null +++ b/skins/nopacity/xmlfiles/displaymenudetailepg.xml @@ -0,0 +1,256 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/skins/nopacity/xmlfiles/displaymenudetailrecording.xml b/skins/nopacity/xmlfiles/displaymenudetailrecording.xml new file mode 100644 index 0000000..07df0fd --- /dev/null +++ b/skins/nopacity/xmlfiles/displaymenudetailrecording.xml @@ -0,0 +1,233 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/skins/nopacity/xmlfiles/displaymenudetailtext.xml b/skins/nopacity/xmlfiles/displaymenudetailtext.xml new file mode 100644 index 0000000..ee44e2a --- /dev/null +++ b/skins/nopacity/xmlfiles/displaymenudetailtext.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/skins/nopacity/xmlfiles/displaymenumain.xml b/skins/nopacity/xmlfiles/displaymenumain.xml new file mode 100644 index 0000000..ba82f48 --- /dev/null +++ b/skins/nopacity/xmlfiles/displaymenumain.xml @@ -0,0 +1,138 @@ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/skins/nopacity/xmlfiles/displaymenurecordings.xml b/skins/nopacity/xmlfiles/displaymenurecordings.xml new file mode 100644 index 0000000..e6dbc4d --- /dev/null +++ b/skins/nopacity/xmlfiles/displaymenurecordings.xml @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/skins/nopacity/xmlfiles/displaymenuschedules.xml b/skins/nopacity/xmlfiles/displaymenuschedules.xml new file mode 100644 index 0000000..d6a27f7 --- /dev/null +++ b/skins/nopacity/xmlfiles/displaymenuschedules.xml @@ -0,0 +1,211 @@ + + +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/skins/nopacity/xmlfiles/displaymenusetup.xml b/skins/nopacity/xmlfiles/displaymenusetup.xml new file mode 100644 index 0000000..c0fd3d3 --- /dev/null +++ b/skins/nopacity/xmlfiles/displaymenusetup.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/skins/nopacity/xmlfiles/displaymenutimers.xml b/skins/nopacity/xmlfiles/displaymenutimers.xml new file mode 100644 index 0000000..0c14138 --- /dev/null +++ b/skins/nopacity/xmlfiles/displaymenutimers.xml @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/skins/nopacity/xmlfiles/displaymessage.xml b/skins/nopacity/xmlfiles/displaymessage.xml new file mode 100644 index 0000000..c5cbff2 --- /dev/null +++ b/skins/nopacity/xmlfiles/displaymessage.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/skins/nopacity/xmlfiles/displayreplay.xml b/skins/nopacity/xmlfiles/displayreplay.xml new file mode 100644 index 0000000..dee1375 --- /dev/null +++ b/skins/nopacity/xmlfiles/displayreplay.xml @@ -0,0 +1,218 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/skins/nopacity/xmlfiles/displayvolume.xml b/skins/nopacity/xmlfiles/displayvolume.xml new file mode 100644 index 0000000..9cd176a --- /dev/null +++ b/skins/nopacity/xmlfiles/displayvolume.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/skins/nopacity/xmlfiles/globals.xml b/skins/nopacity/xmlfiles/globals.xml new file mode 100644 index 0000000..1870789 --- /dev/null +++ b/skins/nopacity/xmlfiles/globals.xml @@ -0,0 +1,207 @@ + + + + + + + FFFF0000 + FF5FE200 + FFE2DA00 + FF007FE2 + FFFFFFFF + 99FFFFFF + FF000000 + FF8EAB21 + FF4C5C11 + FF858585 + B012273F + 99000000 + 99FF0000 + FFFFFFFF + FF363636 + FF858585 + 00000000 + + + + 300 + + + + + free + frei + + + Transponder + Transponder + + + Now + Jetzt + + + Next + Nachfolgend + + + Next Schedules + Nachfolgende Sendungen + + + Reruns + Wiederholungen + + + Reruns of + Wiederholungen von + + + Actors + Schauspieler + + + Episode + Folge + + + Season + Staffel + + + Guest Stars + Gaststars + + + Series First Aired + Erstausstrahlung der Serie + + + Episode First Aired + Erstausstrahlung der Episode + + + Network + TV Station + + + Genre + Genre + + + Status + Status + + + Rating + Bewertung + + + Episode Rating + Bewertung der Folge + + + Recording Information + Aufnahme Informationen + + + Series Galery + Serien Galerie + + + Movie Galery + Spielfilm Galerie + + + Original Title + Originaltitel + + + Budget + Budget + + + Revenue + Einnahmen + + + Adult + Nur für Erwachsene + + + Release Date + Erscheinungsdatum + + + Runtime + Laufzeit + + + Popularity + Popularität + + + Vote Average + Durchschnittliche Wertung + + + Homepage + Homepage + + + Recording size + Größe der Aufnahme + + + Cutted Recording Size + Größe der geschnittenen Aufnahme + + + Recording Length + Länge der Aufnahme + + + Cutted Recording Length + Länge der geschnittenen Aufnahme + + + Bit Rate + Bitrate + + + Format + Format + + + Searchtimer + Suchtimer + + + Volume + Lautstärke + + + + + + diff --git a/skinskeleton/xmlfiles/displayaudiotracks.xml b/skinskeleton/xmlfiles/displayaudiotracks.xml new file mode 100644 index 0000000..a088d97 --- /dev/null +++ b/skinskeleton/xmlfiles/displayaudiotracks.xml @@ -0,0 +1,30 @@ + + + + + + + + + +
+
+ + + + + + + + +
diff --git a/skinskeleton/xmlfiles/displaychannel.xml b/skinskeleton/xmlfiles/displaychannel.xml new file mode 100644 index 0000000..7f55232 --- /dev/null +++ b/skinskeleton/xmlfiles/displaychannel.xml @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/skinskeleton/xmlfiles/displaymenu.xml b/skinskeleton/xmlfiles/displaymenu.xml new file mode 100644 index 0000000..28d18ee --- /dev/null +++ b/skinskeleton/xmlfiles/displaymenu.xml @@ -0,0 +1,87 @@ + + + + + + + + + + + +]> + + + + + + +
+
+ + + + + + + + + + &displaymenudefault; + &displaymenumain; + &displaymenusetup; + &displaymenuschedules; + &displaymenutimers; + &displaymenuchannels; + &displaymenurecordings; + &displaymenudetailepg; + &displaymenudetailrecording; + &displaymenudetailtext; +
diff --git a/skinskeleton/xmlfiles/displaymenuchannels.xml b/skinskeleton/xmlfiles/displaymenuchannels.xml new file mode 100644 index 0000000..242a754 --- /dev/null +++ b/skinskeleton/xmlfiles/displaymenuchannels.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/skinskeleton/xmlfiles/displaymenudefault.xml b/skinskeleton/xmlfiles/displaymenudefault.xml new file mode 100644 index 0000000..aed2738 --- /dev/null +++ b/skinskeleton/xmlfiles/displaymenudefault.xml @@ -0,0 +1,36 @@ + + + + + + + + + diff --git a/skinskeleton/xmlfiles/displaymenudetailepg.xml b/skinskeleton/xmlfiles/displaymenudetailepg.xml new file mode 100644 index 0000000..66d5399 --- /dev/null +++ b/skinskeleton/xmlfiles/displaymenudetailepg.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/skinskeleton/xmlfiles/displaymenudetailrecording.xml b/skinskeleton/xmlfiles/displaymenudetailrecording.xml new file mode 100644 index 0000000..0587e55 --- /dev/null +++ b/skinskeleton/xmlfiles/displaymenudetailrecording.xml @@ -0,0 +1,154 @@ + + + + + + + + + + + + + + + + diff --git a/skinskeleton/xmlfiles/displaymenudetailtext.xml b/skinskeleton/xmlfiles/displaymenudetailtext.xml new file mode 100644 index 0000000..6c91e5d --- /dev/null +++ b/skinskeleton/xmlfiles/displaymenudetailtext.xml @@ -0,0 +1,9 @@ + + + + + + + \ No newline at end of file diff --git a/skinskeleton/xmlfiles/displaymenumain.xml b/skinskeleton/xmlfiles/displaymenumain.xml new file mode 100644 index 0000000..98c108a --- /dev/null +++ b/skinskeleton/xmlfiles/displaymenumain.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/skinskeleton/xmlfiles/displaymenurecordings.xml b/skinskeleton/xmlfiles/displaymenurecordings.xml new file mode 100644 index 0000000..ca4023d --- /dev/null +++ b/skinskeleton/xmlfiles/displaymenurecordings.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/skinskeleton/xmlfiles/displaymenuschedules.xml b/skinskeleton/xmlfiles/displaymenuschedules.xml new file mode 100644 index 0000000..3c615c9 --- /dev/null +++ b/skinskeleton/xmlfiles/displaymenuschedules.xml @@ -0,0 +1,73 @@ + + +
+
+ + + + + + + + + + +
\ No newline at end of file diff --git a/skinskeleton/xmlfiles/displaymenusetup.xml b/skinskeleton/xmlfiles/displaymenusetup.xml new file mode 100644 index 0000000..fe21641 --- /dev/null +++ b/skinskeleton/xmlfiles/displaymenusetup.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + diff --git a/skinskeleton/xmlfiles/displaymenutimers.xml b/skinskeleton/xmlfiles/displaymenutimers.xml new file mode 100644 index 0000000..612c23f --- /dev/null +++ b/skinskeleton/xmlfiles/displaymenutimers.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/skinskeleton/xmlfiles/displaymessage.xml b/skinskeleton/xmlfiles/displaymessage.xml new file mode 100644 index 0000000..11d2ea6 --- /dev/null +++ b/skinskeleton/xmlfiles/displaymessage.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + diff --git a/skinskeleton/xmlfiles/displayreplay.xml b/skinskeleton/xmlfiles/displayreplay.xml new file mode 100644 index 0000000..4f41222 --- /dev/null +++ b/skinskeleton/xmlfiles/displayreplay.xml @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/skinskeleton/xmlfiles/displayvolume.xml b/skinskeleton/xmlfiles/displayvolume.xml new file mode 100644 index 0000000..92d4f7c --- /dev/null +++ b/skinskeleton/xmlfiles/displayvolume.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + diff --git a/skinskeleton/xmlfiles/globals.xml b/skinskeleton/xmlfiles/globals.xml new file mode 100644 index 0000000..01f37fb --- /dev/null +++ b/skinskeleton/xmlfiles/globals.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + diff --git a/themes/skindesigner-default.theme b/themes/skindesigner-default.theme new file mode 100644 index 0000000..f6da510 --- /dev/null +++ b/themes/skindesigner-default.theme @@ -0,0 +1 @@ +Description = MetrixHD diff --git a/themes/skindesigner-nopacity.theme b/themes/skindesigner-nopacity.theme new file mode 100644 index 0000000..85dfa81 --- /dev/null +++ b/themes/skindesigner-nopacity.theme @@ -0,0 +1 @@ +Description = nOpacity Freestyle diff --git a/views/displayaudiotracksview.c b/views/displayaudiotracksview.c new file mode 100644 index 0000000..c4b9f9a --- /dev/null +++ b/views/displayaudiotracksview.c @@ -0,0 +1,79 @@ +#define __STL_CONFIG_H +#include +#include "displayaudiotracksview.h" + +cDisplayAudiotracksView::cDisplayAudiotracksView(int numTracks, cTemplateView *tmplView) : cView(tmplView) { + DeleteOsdOnExit(); + SetFadeTime(tmplView->GetNumericParameter(ptFadeTime)); + + this->numTracks = numTracks; + + cTemplateViewList *tmplMenuItems = tmplView->GetViewList(vlMenuItem); + listView = NULL; + if (tmplMenuItems) { + listView = new cDisplayMenuListView(tmplMenuItems, numTracks); + } +} + +cDisplayAudiotracksView::~cDisplayAudiotracksView() { + if (listView) + delete listView; + CancelSave(); + FadeOut(); +} + +bool cDisplayAudiotracksView::createOsd(void) { + cRect osdSize = tmplView->GetOsdSize(); + bool ok = CreateOsd(cOsd::OsdLeft() + osdSize.X(), + cOsd::OsdTop() + osdSize.Y(), + osdSize.Width(), + osdSize.Height()); + return ok; +} + +void cDisplayAudiotracksView::DrawBackground(void) { + if (!ViewElementImplemented(veBackground)) { + return; + } + + map < string, string > stringTokens; + map < string, int > intTokens; + + intTokens.insert(pair("numtracks", numTracks)); + + DrawViewElement(veBackground, &stringTokens, &intTokens); +} + +void cDisplayAudiotracksView::DrawHeader(const char *title, int audioChannel) { + if (!ViewElementImplemented(veHeader)) { + return; + } + + map < string, string > stringTokens; + map < string, int > intTokens; + + intTokens.insert(pair("numtracks", numTracks)); + if (audioChannel < 0) { + intTokens.insert(pair("isac3", true)); + intTokens.insert(pair("isstereo", false)); + } else { + intTokens.insert(pair("isac3", false)); + intTokens.insert(pair("isstereo", true)); + } + stringTokens.insert(pair("title", title)); + + ClearViewElement(veHeader); + DrawViewElement(veHeader, &stringTokens, &intTokens); +} + +void cDisplayAudiotracksView::RenderMenuItems(void) { + if (listView) + listView->Render(); +} + +void cDisplayAudiotracksView::Action(void) { + SetInitFinished(); + FadeIn(); + DoFlush(); + cView::Action(); +} diff --git a/views/displayaudiotracksview.h b/views/displayaudiotracksview.h new file mode 100644 index 0000000..3414d66 --- /dev/null +++ b/views/displayaudiotracksview.h @@ -0,0 +1,24 @@ +#ifndef __DISPLAYAUDIOTRACKSVIEW_H +#define __DISPLAYAUDIOTRACKSVIEW_H + +#include "../libtemplate/template.h" +#include "displaymenulistview.h" + +class cDisplayAudiotracksView : public cView { +protected: + int numTracks; + cDisplayMenuListView *listView; + virtual void Action(void); +public: + cDisplayAudiotracksView(int numTracks, cTemplateView *tmplView); + virtual ~cDisplayAudiotracksView(); + bool createOsd(void); + void DrawBackground(void); + void DrawHeader(const char *title, int audioChannel); + cDisplayMenuListView *GetListView(void) { return listView; }; + void DoFadeIn(void) { Start(); }; + void Flush(void) { DoFlush(); }; + void RenderMenuItems(void); +}; + +#endif //__DISPLAYAUDIOTRACKSVIEW_H diff --git a/views/displaychannelview.c b/views/displaychannelview.c new file mode 100644 index 0000000..66155a1 --- /dev/null +++ b/views/displaychannelview.c @@ -0,0 +1,452 @@ +#define __STL_CONFIG_H +#include +#include "../services/scraper2vdr.h" +#include "displaychannelview.h" +#include "../libcore/timers.h" +#include "../libcore/helpers.h" + + +cDisplayChannelView::cDisplayChannelView(cTemplateView *tmplView) : cView(tmplView) { + lastDate = ""; + lastScreenWidth = 0; + lastScreenHeight = 0; + lastSignalDisplay = 0; + lastSignalStrength = 0; + lastSignalQuality = 0; + DeleteOsdOnExit(); + SetFadeTime(tmplView->GetNumericParameter(ptFadeTime)); +} + +cDisplayChannelView::~cDisplayChannelView() { + CancelSave(); + FadeOut(); +} + +bool cDisplayChannelView::createOsd(void) { + cRect osdSize = tmplView->GetOsdSize(); + bool ok = CreateOsd(cOsd::OsdLeft() + osdSize.X(), + cOsd::OsdTop() + osdSize.Y(), + osdSize.Width(), + osdSize.Height()); + return ok; +} + +void cDisplayChannelView::DrawBackground(void) { + map < string, string > stringTokens; + map < string, int > intTokens; + DrawViewElement(veBackground, &stringTokens, &intTokens); +} + +void cDisplayChannelView::DrawChannel(cString &number, cString &name, cString &id, bool switching) { + map < string, string > stringTokens; + map < string, int > intTokens; + + stringTokens.insert(pair("channelname", *name)); + stringTokens.insert(pair("channelnumber", *number)); + stringTokens.insert(pair("channelid", *id)); + + intTokens.insert(pair("switching", switching)); + bool logoExisis = imgCache->LogoExists(*id); + intTokens.insert(pair("channellogoexists", logoExisis)); + + DrawViewElement(veChannelInfo, &stringTokens, &intTokens); +} + +void cDisplayChannelView::ClearChannel(void) { + ClearViewElement(veChannelInfo); +} + +void cDisplayChannelView::DrawDate(void) { + if (!ViewElementImplemented(veDateTime)) { + return; + } + cString curDate = DayDateTime(); + if (strcmp(curDate, lastDate)) { + map < string, string > stringTokens; + map < string, int > intTokens; + + time_t t = time(0); // get time now + struct tm * now = localtime(&t); + + intTokens.insert(pair("year", now->tm_year + 1900)); + intTokens.insert(pair("day", now->tm_mday)); + + char monthname[20]; + char monthshort[10]; + strftime(monthshort, sizeof(monthshort), "%b", now); + strftime(monthname, sizeof(monthname), "%B", now); + + stringTokens.insert(pair("monthname", monthname)); + stringTokens.insert(pair("monthnameshort", monthshort)); + stringTokens.insert(pair("month", *cString::sprintf("%02d", now->tm_mon + 1))); + stringTokens.insert(pair("dayleadingzero", *cString::sprintf("%02d", now->tm_mday))); + stringTokens.insert(pair("dayname", *WeekDayNameFull(now->tm_wday))); + stringTokens.insert(pair("daynameshort", *WeekDayName(now->tm_wday))); + stringTokens.insert(pair("time", *TimeString(t))); + + ClearViewElement(veDateTime); + DrawViewElement(veDateTime, &stringTokens, &intTokens); + + lastDate = curDate; + } +} + +void cDisplayChannelView::DrawProgressBar(cString &start, cString &stop, int Current, int Total) { + if (!ViewElementImplemented(veProgressBar)) { + return; + } + + map < string, string > stringTokens; + map < string, int > intTokens; + + stringTokens.insert(pair("start", *start)); + stringTokens.insert(pair("stop", *stop)); + + intTokens.insert(pair("duration", Total)); + intTokens.insert(pair("elapsed", Current)); + intTokens.insert(pair("remaining", Total - Current)); + + DrawViewElement(veProgressBar, &stringTokens, &intTokens); +} + +void cDisplayChannelView::ClearProgressBar(void) { + ClearViewElement(veProgressBar); +} + +void cDisplayChannelView::DrawProgressBarBack(void) { + DrawViewElement(veProgressBarBack); +} + +void cDisplayChannelView::ClearProgressBarBack(void) { + ClearViewElement(veProgressBarBack); +} + +void cDisplayChannelView::DrawEPGInfo(const cEvent *present, const cEvent *next, bool presentRecording, bool nextRecording) { + map < string, string > stringTokens; + map < string, int > intTokens; + + if (present) { + stringTokens.insert(pair("currenttitle", (present->Title())?present->Title():"")); + stringTokens.insert(pair("currentsubtitle", (present->ShortText())?present->ShortText():"")); + stringTokens.insert(pair("currentstart", *present->GetTimeString())); + stringTokens.insert(pair("currentstop", *present->GetEndTimeString())); + + intTokens.insert(pair("currentduration", present->Duration() / 60)); + intTokens.insert(pair("currentelapsed", (int)round((time(NULL) - present->StartTime())/60))); + intTokens.insert(pair("currentremaining", (int)round((present->EndTime() - time(NULL))/60))); + intTokens.insert(pair("currentrecording", presentRecording ? 1 : 0)); + } else { + stringTokens.insert(pair("currenttitle", "")); + stringTokens.insert(pair("currentsubtitle", "")); + stringTokens.insert(pair("currentstart", "")); + stringTokens.insert(pair("currentstop", "")); + + intTokens.insert(pair("currentduration", 0)); + intTokens.insert(pair("currentelapsed", 0)); + intTokens.insert(pair("currentremaining", 0)); + intTokens.insert(pair("currentrecording", 0)); + } + + if (next) { + stringTokens.insert(pair("nexttitle", (next->Title())?next->Title():"")); + stringTokens.insert(pair("nextsubtitle", (next->ShortText())?next->ShortText():"")); + stringTokens.insert(pair("nextstart", *next->GetTimeString())); + stringTokens.insert(pair("nextstop", *next->GetEndTimeString())); + + intTokens.insert(pair("nextduration", next->Duration() / 60)); + intTokens.insert(pair("nextrecording", nextRecording ? 1 : 0)); + } else { + stringTokens.insert(pair("nexttitle", "")); + stringTokens.insert(pair("nextsubtitle", "")); + stringTokens.insert(pair("nextstart", "")); + stringTokens.insert(pair("nextstop", "")); + + intTokens.insert(pair("nextduration", 0)); + intTokens.insert(pair("nextrecording", 0)); + } + DrawViewElement(veEpgInfo, &stringTokens, &intTokens); +} + +void cDisplayChannelView::ClearEPGInfo(void) { + ClearViewElement(veEpgInfo); +} + +void cDisplayChannelView::DrawStatusIcons(const cChannel *Channel) { + if (!ViewElementImplemented(veStatusInfo)) { + return; + } + + bool isRadio = !Channel->Vpid() && Channel->Apid(0); + bool hasVT = Channel->Vpid() && Channel->Tpid(); + bool isStereo = Channel->Apid(0); + bool isDolby = Channel->Dpid(0); + bool isEncrypted = Channel->Ca(); + bool isRecording = cRecordControls::Active(); + cGlobalSortedTimers SortedTimers;// local and remote timers + for (int i = 0; i < SortedTimers.Size() && !isRecording; i++) + if (const cTimer *Timer = SortedTimers[i]) + if (Timer->Recording()) + isRecording = true; + + map < string, int > intTokens; + intTokens.insert(pair("isRadio", isRadio)); + intTokens.insert(pair("hasVT", hasVT)); + intTokens.insert(pair("isStereo", isStereo)); + intTokens.insert(pair("isDolby", isDolby)); + intTokens.insert(pair("isEncrypted", isEncrypted)); + intTokens.insert(pair("isRecording", isRecording)); + + DrawViewElement(veStatusInfo, NULL, &intTokens); +} + +void cDisplayChannelView::ClearStatusIcons(void) { + ClearViewElement(veStatusInfo); +} + +void cDisplayChannelView::DrawScreenResolution(void) { + if (!ViewElementImplemented(veScreenResolution)) { + return; + } + + int screenWidth = 0; + int screenHeight = 0; + double aspect = 0; + + cDevice::PrimaryDevice()->GetVideoSize(screenWidth, screenHeight, aspect); + + if ((lastScreenWidth == screenWidth) && (lastScreenHeight == screenHeight)) + return; + + if ((screenWidth == 0) && (screenHeight == 0)) + return; + + lastScreenWidth = screenWidth; + lastScreenHeight = screenHeight; + + bool isHD = false; + string resName = GetScreenResolutionString(screenWidth, screenHeight, &isHD); + + bool isWideScreen = false; + string aspectName = GetScreenAspectString(aspect, &isWideScreen); + + map < string, string > stringTokens; + map < string, int > intTokens; + + intTokens.insert(pair("screenwidth", screenWidth)); + intTokens.insert(pair("screenheight", screenHeight)); + intTokens.insert(pair("isHD", isHD)); + intTokens.insert(pair("isWideScreen", isWideScreen)); + stringTokens.insert(pair("resolution", resName)); + stringTokens.insert(pair("aspect", aspectName)); + + ClearViewElement(veScreenResolution); + DrawViewElement(veScreenResolution, &stringTokens, &intTokens); +} + +void cDisplayChannelView::ClearScreenResolution(void) { + ClearViewElement(veScreenResolution); + lastScreenWidth = 0; + lastScreenHeight = 0; +} + +string cDisplayChannelView::GetScreenResolutionString(int width, int height, bool *isHD) { + string name = ""; + switch (width) { + case 1920: + case 1440: + name = "hd1080i"; + *isHD = true; + break; + case 1280: + if (height == 720) + name = "hd720p"; + else + name = "hd1080i"; + *isHD = true; + break; + case 720: + name = "sd576i"; + break; + default: + name = "sd576i"; + break; + } + return name; +} + +string cDisplayChannelView::GetScreenAspectString(double aspect, bool *isWideScreen) { + string name = ""; + *isWideScreen = false; + if (aspect == 4.0/3.0) { + name = "4:3"; + *isWideScreen = false; + } else if (aspect == 16.0/9.0) { + name = "16:9"; + *isWideScreen = true; + } else if (aspect == 2.21) { + name = "21:9"; + *isWideScreen = true; + } + return name; +} + +void cDisplayChannelView::DrawScraperContent(const cEvent *event) { + if (!event) + return; + + if (!ViewElementImplemented(veScraperContent)) { + return; + } + + static cPlugin *pScraper = GetScraperPlugin(); + if (!pScraper) { + return; + } + + ScraperGetPosterBanner call; + call.event = event; + if (pScraper->Service("GetPosterBanner", &call)) { + int mediaWidth = 0; + int mediaHeight = 0; + std::string mediaPath = ""; + bool isBanner = false; + + if ((call.type == tSeries) && call.banner.path.size() > 0) { + mediaWidth = call.banner.width; + mediaHeight = call.banner.height; + mediaPath = call.banner.path; + isBanner = true; + } else if (call.type == tMovie && call.poster.path.size() > 0 && call.poster.height > 0) { + mediaWidth = call.poster.width; + mediaHeight = call.poster.height; + mediaPath = call.poster.path; + } else + return; + + map < string, int > intTokens; + map < string, string > stringTokens; + intTokens.insert(pair("mediawidth", mediaWidth)); + intTokens.insert(pair("mediaheight", mediaHeight)); + intTokens.insert(pair("isbanner", isBanner)); + stringTokens.insert(pair("mediapath", mediaPath)); + ClearViewElement(veScraperContent); + DrawViewElement(veScraperContent, &stringTokens, &intTokens); + } +} + +void cDisplayChannelView::ClearScraperContent(void) { + ClearViewElement(veScraperContent); +} + +void cDisplayChannelView::DrawSignal(void) { + if (!ViewElementImplemented(veSignalQuality)) { + return; + } + time_t Now = time(NULL); + if (Now != lastSignalDisplay) { + int SignalStrength = cDevice::ActualDevice()->SignalStrength(); + int SignalQuality = cDevice::ActualDevice()->SignalQuality(); + if (SignalStrength < 0) SignalStrength = 0; + if (SignalQuality < 0) SignalQuality = 0; + if ((SignalStrength == 0)&&(SignalQuality==0)) + return; + if ((lastSignalStrength != SignalStrength) || (lastSignalQuality != SignalQuality)) { + map < string, int > intTokens; + map < string, string > stringTokens; + intTokens.insert(pair("signalstrength", SignalStrength)); + intTokens.insert(pair("signalquality", SignalQuality)); + ClearViewElement(veSignalQuality); + DrawViewElement(veSignalQuality, &stringTokens, &intTokens); + } + lastSignalStrength = SignalStrength; + lastSignalQuality = SignalQuality; + lastSignalDisplay = Now; + } +} + +void cDisplayChannelView::DrawSignalBackground(void) { + if (!ViewElementImplemented(veSignalQualityBack)) { + return; + } + DrawViewElement(veSignalQualityBack); +} + + +void cDisplayChannelView::ClearSignal(void) { + ClearViewElement(veSignalQuality); +} + +void cDisplayChannelView::ClearSignalBackground(void) { + ClearViewElement(veSignalQualityBack); +} + +void cDisplayChannelView::DrawChannelGroups(const cChannel *Channel, cString ChannelName) { + if (!ViewElementImplemented(veChannelGroup)) { + return; + } + + bool separatorExists = imgCache->SeparatorLogoExists(*ChannelName); + string separatorPath = separatorExists ? *ChannelName : ""; + + std::string prevChannelSep = GetChannelSep(Channel, true); + std::string nextChannelSep = GetChannelSep(Channel, false); + bool prevAvailable = (prevChannelSep.size() > 0)?true:false; + bool nextAvailable = (nextChannelSep.size() > 0)?true:false; + + map < string, string > stringTokens; + map < string, int > intTokens; + + intTokens.insert(pair("sepexists", separatorExists)); + intTokens.insert(pair("prevAvailable", prevAvailable)); + intTokens.insert(pair("nextAvailable", nextAvailable)); + stringTokens.insert(pair("group", *ChannelName)); + stringTokens.insert(pair("nextgroup", nextChannelSep)); + stringTokens.insert(pair("prevgroup", prevChannelSep)); + stringTokens.insert(pair("seppath", separatorPath)); + + ClearViewElement(veChannelGroup); + DrawViewElement(veChannelGroup, &stringTokens, &intTokens); +} + +void cDisplayChannelView::ClearChannelGroups(void) { + ClearViewElement(veChannelGroup); +} + +string cDisplayChannelView::GetChannelSep(const cChannel *channel, bool prev) { + std::string sepName = ""; + const cChannel *sep = prev ? Channels.Prev(channel) : + Channels.Next(channel); + for (; sep; (prev)?(sep = Channels.Prev(sep)):(sep = Channels.Next(sep))) { + if (sep->GroupSep()) { + sepName = sep->Name(); + break; + } + } + return sepName; +} + +void cDisplayChannelView::DisplayMessage(eMessageType Type, const char *Text) { + if (!Text) { + ClearViewElement(veMessage); + } + + map < string, string > stringTokens; + map < string, int > intTokens; + + stringTokens.insert(pair("text", Text)); + + intTokens.insert(pair("status", (Type == mtStatus) ? true : false)); + intTokens.insert(pair("info", (Type == mtInfo) ? true : false)); + intTokens.insert(pair("warning", (Type == mtWarning) ? true : false)); + intTokens.insert(pair("error", (Type == mtError) ? true : false)); + + ClearViewElement(veMessage); + DrawViewElement(veMessage, &stringTokens, &intTokens); +} + +void cDisplayChannelView::Action(void) { + SetInitFinished(); + FadeIn(); + DoFlush(); + cView::Action(); +} diff --git a/views/displaychannelview.h b/views/displaychannelview.h new file mode 100644 index 0000000..599ac5f --- /dev/null +++ b/views/displaychannelview.h @@ -0,0 +1,49 @@ +#ifndef __DISPLAYCHANNELVIEW_H +#define __DISPLAYCHANNELVIEW_H + +#include "../libtemplate/template.h" +#include "view.h" + +class cDisplayChannelView : public cView { +private: + cString lastDate; + int lastScreenWidth; + int lastScreenHeight; + int lastSignalDisplay; + int lastSignalStrength; + int lastSignalQuality; + string GetScreenResolutionString(int width, int height, bool *isHD); + string GetScreenAspectString(double aspect, bool *isWideScreen); + string GetChannelSep(const cChannel *channel, bool prev); + virtual void Action(void); +public: + cDisplayChannelView(cTemplateView *tmplView); + virtual ~cDisplayChannelView(); + bool createOsd(void); + void DrawBackground(void); + void DrawChannel(cString &number, cString &name, cString &id, bool switching); + void ClearChannel(void); + void DrawDate(void); + void DrawProgressBar(cString &start, cString &stop, int Current, int Total); + void ClearProgressBar(void); + void DrawProgressBarBack(void); + void ClearProgressBarBack(void); + void DrawEPGInfo(const cEvent *present, const cEvent *next, bool presentRecording, bool nextRecording); + void ClearEPGInfo(void); + void DrawStatusIcons(const cChannel *Channel); + void ClearStatusIcons(void); + void DrawScreenResolution(void); + void ClearScreenResolution(void); + void DrawScraperContent(const cEvent *event); + void ClearScraperContent(void); + void DrawSignal(void); + void DrawSignalBackground(void); + void ClearSignal(void); + void ClearSignalBackground(void); + void DrawChannelGroups(const cChannel *Channel, cString ChannelName); + void ClearChannelGroups(void); + void DisplayMessage(eMessageType Type, const char *Text); + void DoStart(void) { Start(); }; + void Flush(void) { DoFlush(); }; +}; +#endif //__DISPLAYCHANNELVIEW_H diff --git a/views/displaymenudetailview.c b/views/displaymenudetailview.c new file mode 100644 index 0000000..acba9c6 --- /dev/null +++ b/views/displaymenudetailview.c @@ -0,0 +1,929 @@ +#include "displaymenudetailview.h" +#include "../libcore/helpers.h" +#include "../services/scraper2vdr.h" +#include "../services/epgsearch.h" + +cDisplayMenuDetailView::cDisplayMenuDetailView(cTemplateView *tmplDetailView) : cView(tmplDetailView) { + event = NULL; + recording = NULL; + text = NULL; + detailViewInit = true; + currentTmplTab = NULL; + tabView = NULL; +} + +cDisplayMenuDetailView::~cDisplayMenuDetailView() { + CancelSave(); + if (tabView) + delete tabView; +} + +void cDisplayMenuDetailView::Clear(void) { + ClearViewElement(veDetailHeader); + ClearViewElement(veScrollbar); + ClearViewElement(veTabLabels); +} + +void cDisplayMenuDetailView::Render(void) { + if (detailViewInit) { + DrawHeader(); + DoFlush(); + SetTokens(); + InitTabs(); + currentTmplTab = *atIt; + detailViewInit = false; + } + if (!tabView) { + tabView = new cDisplayMenuTabView(currentTmplTab); + tabView->SetTokens(&intTokens, &stringTokens, &loopTokens); + tabView->CreateTab(); + tabView->Start(); + } + DrawScrollbar(); + DrawTabLabels(); +} + +void cDisplayMenuDetailView::KeyLeft(void) { + if (activeTabs.size() > 1) { + currentTmplTab = GetPrevTab(); + delete tabView; + tabView = NULL; + Render(); + DoFlush(); + } else { + bool scrolled = tabView->KeyLeft(); + if (scrolled) { + DrawScrollbar(); + DoFlush(); + } + } +} + +void cDisplayMenuDetailView::KeyRight(void) { + if (activeTabs.size() > 1) { + currentTmplTab = GetNextTab(); + delete tabView; + tabView = NULL; + Render(); + DoFlush(); + } else { + bool scrolled = tabView->KeyRight(); + if (scrolled) { + DrawScrollbar(); + DoFlush(); + } + } +} + +void cDisplayMenuDetailView::KeyUp(void) { + if (!tabView) + return; + bool scrolled = tabView->KeyUp(); + if (scrolled) { + DrawScrollbar(); + DoFlush(); + } +} + +void cDisplayMenuDetailView::KeyDown(void) { + if (!tabView) + return; + bool scrolled = tabView->KeyDown(); + if (scrolled) { + DrawScrollbar(); + DoFlush(); + } +} + + +void cDisplayMenuDetailView::SetTokens(void) { + if (event) { + stringTokens.insert(pair("title", event->Title() ? event->Title() : "")); + stringTokens.insert(pair("shorttext", event->ShortText() ? event->ShortText() : "")); + stringTokens.insert(pair("description", event->Description() ? event->Description() : "")); + stringTokens.insert(pair("start", *(event->GetTimeString()))); + stringTokens.insert(pair("stop", *(event->GetEndTimeString()))); + stringTokens.insert(pair("day", *WeekDayName(event->StartTime()))); + stringTokens.insert(pair("date", *ShortDateString(event->StartTime()))); + stringTokens.insert(pair("channelid", *(event->ChannelID().ToString()))); + + bool isRunning = false; + time_t now = time(NULL); + if ((now >= event->StartTime()) && (now <= event->EndTime())) + isRunning = true; + intTokens.insert(pair("running", isRunning)); + if (isRunning) { + intTokens.insert(pair("elapsed", (now - event->StartTime())/60)); + } else { + intTokens.insert(pair("elapsed", 0)); + } + intTokens.insert(pair("duration", event->Duration() / 60)); + + vector< map< string, string > > reruns; + bool hasReruns = LoadReruns(&reruns); + loopTokens.insert(pair > >("reruns", reruns)); + + intTokens.insert(pair("hasreruns", hasReruns)); + + SetScraperTokens(); + SetEpgPictures(event->EventID()); + + } else if (recording) { + string name = recording->Name() ? recording->Name() : ""; + stringTokens.insert(pair("name", name)); + + const cRecordingInfo *info = recording->Info(); + if (info) { + stringTokens.insert(pair("shorttext", info->ShortText() ? info->ShortText() : "")); + stringTokens.insert(pair("description", info->Description() ? info->Description() : "")); + const cEvent *event = info->GetEvent(); + if (event) { + string recDate = *(event->GetDateString()); + string recTime = *(event->GetTimeString()); + if (recDate.find("1970") != string::npos) { + time_t start = recording->Start(); + recDate = *DateString(start); + recTime = *TimeString(start); + } + int duration = event->Duration() / 60; + int recDuration = recording->LengthInSeconds(); + recDuration = (recDuration>0)?(recDuration / 60):0; + stringTokens.insert(pair("date", recDate.c_str())); + stringTokens.insert(pair("time", recTime.c_str())); + intTokens.insert(pair("duration", recDuration)); + intTokens.insert(pair("durationevent", duration)); + } + } else { + stringTokens.insert(pair("shorttext", "")); + stringTokens.insert(pair("description", "")); + int recDuration = recording->LengthInSeconds(); + recDuration = (recDuration>0)?(recDuration / 60):0; + stringTokens.insert(pair("date", "")); + stringTokens.insert(pair("time", "")); + intTokens.insert(pair("duration", recDuration)); + intTokens.insert(pair("durationevent", 0)); + } + LoadRecordingInformation(); + SetScraperTokens(); + SetRecordingImages(recording->FileName()); + } else if (text) { + stringTokens.insert(pair("text", text)); + } else { + intTokens.insert(pair("running", false)); + intTokens.insert(pair("hasreruns", false)); + } +} + +void cDisplayMenuDetailView::SetScraperTokens(void) { + static cPlugin *pScraper = GetScraperPlugin(); + if (!pScraper || (!event && !recording)) { + intTokens.insert(pair("ismovie", false)); + intTokens.insert(pair("isseries", false)); + return; + } + + ScraperGetEventType getType; + getType.event = event; + getType.recording = recording; + if (!pScraper->Service("GetEventType", &getType)) { + intTokens.insert(pair("ismovie", false)); + intTokens.insert(pair("isseries", false)); + return; + } + + if (getType.type == tMovie) { + cMovie movie; + movie.movieId = getType.movieId; + pScraper->Service("GetMovie", &movie); + intTokens.insert(pair("ismovie", true)); + intTokens.insert(pair("isseries", false)); + + stringTokens.insert(pair("movietitle", movie.title)); + stringTokens.insert(pair("movieoriginalTitle", movie.originalTitle)); + stringTokens.insert(pair("movietagline", movie.tagline)); + stringTokens.insert(pair("movieoverview", movie.overview)); + stringTokens.insert(pair("moviegenres", movie.genres)); + stringTokens.insert(pair("moviehomepage", movie.homepage)); + stringTokens.insert(pair("moviereleasedate", movie.releaseDate)); + stringstream pop; + pop << movie.popularity; + stringTokens.insert(pair("moviepopularity", pop.str())); + stringstream vote; + vote << movie.voteAverage; + stringTokens.insert(pair("movievoteaverage", pop.str())); + stringTokens.insert(pair("posterpath", movie.poster.path)); + stringTokens.insert(pair("fanartpath", movie.fanart.path)); + stringTokens.insert(pair("collectionposterpath", movie.collectionPoster.path)); + stringTokens.insert(pair("collectionfanartpath", movie.collectionFanart.path)); + + intTokens.insert(pair("movieadult", movie.adult)); + intTokens.insert(pair("moviebudget", movie.budget)); + intTokens.insert(pair("movierevenue", movie.revenue)); + intTokens.insert(pair("movieruntime", movie.runtime)); + intTokens.insert(pair("posterwidth", movie.poster.width)); + intTokens.insert(pair("posterheight", movie.poster.height)); + intTokens.insert(pair("fanartwidth", movie.fanart.width)); + intTokens.insert(pair("fanartheight", movie.fanart.height)); + intTokens.insert(pair("collectionposterwidth", movie.collectionPoster.width)); + intTokens.insert(pair("collectionposterheight", movie.collectionPoster.height)); + intTokens.insert(pair("collectionfanartwidth", movie.collectionFanart.width)); + intTokens.insert(pair("collectionfanartheight", movie.collectionFanart.height)); + + vector< map< string, string > > actors; + for (vector::iterator act = movie.actors.begin(); act != movie.actors.end(); act++) { + map< string, string > actor; + actor.insert(pair("actors[name]", (*act).name)); + actor.insert(pair("actors[role]", (*act).role)); + actor.insert(pair("actors[thumb]", (*act).actorThumb.path)); + stringstream actWidth, actHeight; + actWidth << (*act).actorThumb.width; + actHeight << (*act).actorThumb.height; + actor.insert(pair("actors[thumbwidth]", actWidth.str())); + actor.insert(pair("actors[thumbheight]", actHeight.str())); + actors.push_back(actor); + } + loopTokens.insert(pair > >("actors", actors)); + + } else if (getType.type == tSeries) { + cSeries series; + series.seriesId = getType.seriesId; + series.episodeId = getType.episodeId; + pScraper->Service("GetSeries", &series); + intTokens.insert(pair("ismovie", false)); + intTokens.insert(pair("isseries", true)); + //Series Basics + stringTokens.insert(pair("seriesname", series.name)); + stringTokens.insert(pair("seriesoverview", series.overview)); + stringTokens.insert(pair("seriesfirstaired", series.firstAired)); + stringTokens.insert(pair("seriesnetwork", series.network)); + stringTokens.insert(pair("seriesgenre", series.genre)); + stringstream rating; + rating << series.rating; + stringTokens.insert(pair("seriesrating", rating.str())); + stringTokens.insert(pair("seriesstatus", series.status)); + //Episode Information + intTokens.insert(pair("episodenumber", series.episode.number)); + intTokens.insert(pair("episodeseason", series.episode.season)); + stringTokens.insert(pair("episodetitle", series.episode.name)); + stringTokens.insert(pair("episodefirstaired", series.episode.firstAired)); + stringTokens.insert(pair("episodegueststars", series.episode.guestStars)); + stringTokens.insert(pair("episodeoverview", series.episode.overview)); + stringstream eprating; + eprating << series.episode.rating; + stringTokens.insert(pair("episoderating", eprating.str())); + intTokens.insert(pair("episodeimagewidth", series.episode.episodeImage.width)); + intTokens.insert(pair("episodeimageheight", series.episode.episodeImage.height)); + stringTokens.insert(pair("episodeimagepath", series.episode.episodeImage.path)); + //Seasonposter + intTokens.insert(pair("seasonposterwidth", series.seasonPoster.width)); + intTokens.insert(pair("seasonposterheight", series.seasonPoster.height)); + stringTokens.insert(pair("seasonposterpath", series.seasonPoster.path)); + + //Posters + int current = 1; + for(vector::iterator poster = series.posters.begin(); poster != series.posters.end(); poster++) { + stringstream labelWidth, labelHeight, labelPath; + labelWidth << "seriesposter" << current << "width"; + labelHeight << "seriesposter" << current << "height"; + labelPath << "seriesposter" << current << "path"; + + intTokens.insert(pair(labelWidth.str(), (*poster).width)); + intTokens.insert(pair(labelHeight.str(), (*poster).height)); + stringTokens.insert(pair(labelPath.str(), (*poster).path)); + current++; + } + if (current < 3) { + for (; current < 4; current++) { + stringstream labelWidth, labelHeight, labelPath; + labelWidth << "seriesposter" << current << "width"; + labelHeight << "seriesposter" << current << "height"; + labelPath << "seriesposter" << current << "path"; + + intTokens.insert(pair(labelWidth.str(), 0)); + intTokens.insert(pair(labelHeight.str(), 0)); + stringTokens.insert(pair(labelPath.str(), "")); + } + } + + //Banners + current = 1; + for(vector::iterator banner = series.banners.begin(); banner != series.banners.end(); banner++) { + stringstream labelWidth, labelHeight, labelPath; + labelWidth << "seriesbanner" << current << "width"; + labelHeight << "seriesbanner" << current << "height"; + labelPath << "seriesbanner" << current << "path"; + + intTokens.insert(pair(labelWidth.str(), (*banner).width)); + intTokens.insert(pair(labelHeight.str(), (*banner).height)); + stringTokens.insert(pair(labelPath.str(), (*banner).path)); + current++; + } + if (current < 3) { + for (; current < 4; current++) { + stringstream labelWidth, labelHeight, labelPath; + labelWidth << "seriesbanner" << current << "width"; + labelHeight << "seriesbanner" << current << "height"; + labelPath << "seriesbanner" << current << "path"; + + intTokens.insert(pair(labelWidth.str(), 0)); + intTokens.insert(pair(labelHeight.str(), 0)); + stringTokens.insert(pair(labelPath.str(), "")); + } + } + + //Fanarts + current = 1; + for(vector::iterator fanart = series.fanarts.begin(); fanart != series.fanarts.end(); fanart++) { + stringstream labelWidth, labelHeight, labelPath; + labelWidth << "seriesfanart" << current << "width"; + labelHeight << "seriesfanart" << current << "height"; + labelPath << "seriesfanart" << current << "path"; + + intTokens.insert(pair(labelWidth.str(), (*fanart).width)); + intTokens.insert(pair(labelHeight.str(), (*fanart).height)); + stringTokens.insert(pair(labelPath.str(), (*fanart).path)); + current++; + } + if (current < 3) { + for (; current < 4; current++) { + stringstream labelWidth, labelHeight, labelPath; + labelWidth << "seriesfanart" << current << "width"; + labelHeight << "seriesfanart" << current << "height"; + labelPath << "seriesfanart" << current << "path"; + + intTokens.insert(pair(labelWidth.str(), 0)); + intTokens.insert(pair(labelHeight.str(), 0)); + stringTokens.insert(pair(labelPath.str(), "")); + } + } + + //Actors + vector< map< string, string > > actors; + for (vector::iterator act = series.actors.begin(); act != series.actors.end(); act++) { + map< string, string > actor; + actor.insert(pair("actors[name]", (*act).name)); + actor.insert(pair("actors[role]", (*act).role)); + actor.insert(pair("actors[thumb]", (*act).actorThumb.path)); + stringstream actWidth, actHeight; + actWidth << (*act).actorThumb.width; + actHeight << (*act).actorThumb.height; + actor.insert(pair("actors[thumbwidth]", actWidth.str())); + actor.insert(pair("actors[thumbheight]", actHeight.str())); + actors.push_back(actor); + } + loopTokens.insert(pair > >("actors", actors)); + + } else { + intTokens.insert(pair("ismovie", false)); + intTokens.insert(pair("isseries", false)); + } + +} + +void cDisplayMenuDetailView::InitTabs(void) { + tmplView->InitViewTabIterator(); + cTemplateViewTab *tmplTab = NULL; + while(tmplTab = tmplView->GetNextViewTab()) { + tmplTab->ParseDynamicParameters(&intTokens, true); + tmplTab->ClearDynamicFunctionParameters(); + tmplTab->ParseDynamicFunctionParameters(&stringTokens, &intTokens); + if (tmplTab->DoExecute()) { + activeTabs.push_back(tmplTab); + } + } + atIt = activeTabs.begin(); +} + +bool cDisplayMenuDetailView::LoadReruns(vector< map< string, string > > *reruns) { + if (!event) + return false; + + cPlugin *epgSearchPlugin = cPluginManager::GetPlugin("epgsearch"); + if (!epgSearchPlugin) + return false; + + if (isempty(event->Title())) + return false; + + int maxNumReruns = 10; + + Epgsearch_searchresults_v1_0 data; + string strQuery = event->Title(); + data.useSubTitle = true; + data.query = (char *)strQuery.c_str(); + data.mode = 0; + data.channelNr = 0; + data.useTitle = true; + data.useDescription = false; + + bool foundRerun = false; + if (epgSearchPlugin->Service("Epgsearch-searchresults-v1.0", &data)) { + cList* list = data.pResultList; + if (list && (list->Count() > 1)) { + foundRerun = true; + int i = 0; + for (Epgsearch_searchresults_v1_0::cServiceSearchResult *r = list->First(); r && i < maxNumReruns; r = list->Next(r)) { + if ((event->ChannelID() == r->event->ChannelID()) && (event->StartTime() == r->event->StartTime())) + continue; + i++; + map< string, string > rerun; + rerun.insert(pair("reruns[title]", r->event->Title() ? r->event->Title() : "")); + rerun.insert(pair("reruns[shorttext]", r->event->ShortText() ? r->event->ShortText() : "")); + rerun.insert(pair("reruns[start]", *(r->event->GetTimeString()))); + rerun.insert(pair("reruns[start]", *(r->event->GetTimeString()))); + rerun.insert(pair("reruns[stop]", *(r->event->GetEndTimeString()))); + rerun.insert(pair("reruns[date]", *ShortDateString(r->event->StartTime()))); + rerun.insert(pair("reruns[day]", *WeekDayName(r->event->StartTime()))); + string channelID = *(r->event->ChannelID().ToString()); + rerun.insert(pair("reruns[channelid]", channelID)); + bool logoExists = imgCache->LogoExists(channelID); + rerun.insert(pair("reruns[channellogoexists]", logoExists ? "1" : "0")); + + cChannel *channel = Channels.GetByChannelID(r->event->ChannelID(), true, true); + if (channel) { + stringstream channelNumber; + channelNumber << channel->Number(); + rerun.insert(pair("reruns[channelname]", channel->ShortName(true))); + rerun.insert(pair("reruns[channelnumber]", channelNumber.str())); + } else { + rerun.insert(pair("reruns[channelname]", "")); + rerun.insert(pair("reruns[channelnumber]", "")); + } + reruns->push_back(rerun); + } + delete list; + } + } + return foundRerun; +} + +void cDisplayMenuDetailView::LoadRecordingInformation(void) { + const cRecordingInfo *Info = recording->Info(); + if (!Info) + return; + unsigned long long nRecSize = -1; + unsigned long long nFileSize[1000]; + nFileSize[0] = 0; + int i = 0; + struct stat filebuf; + cString filename; + int rc = 0; + do { + if (recording->IsPesRecording()) + filename = cString::sprintf("%s/%03d.vdr", recording->FileName(), ++i); + else + filename = cString::sprintf("%s/%05d.ts", recording->FileName(), ++i); + rc = stat(filename, &filebuf); + if (rc == 0) + nFileSize[i] = nFileSize[i-1] + filebuf.st_size; + else + if (ENOENT != errno) { + nRecSize = -1; + } + } while (i <= 999 && !rc); + nRecSize = nFileSize[i-1]; + + cMarks marks; + bool fHasMarks = marks.Load(recording->FileName(), recording->FramesPerSecond(), recording->IsPesRecording()) && marks.Count(); + cIndexFile *index = new cIndexFile(recording->FileName(), false, recording->IsPesRecording()); + + int nCutLength = 0; + long nCutInFrame = 0; + unsigned long long nRecSizeCut = nRecSize < 0 ? -1 : 0; + unsigned long long nCutInOffset = 0; + + if (fHasMarks && index) { + uint16_t FileNumber; + off_t FileOffset; + + bool fCutIn = true; + cMark *mark = marks.First(); + while (mark) { + int pos = mark->Position(); + index->Get(pos, &FileNumber, &FileOffset); //TODO: will disc spin up? + if (fCutIn) { + nCutInFrame = pos; + fCutIn = false; + if (nRecSize >= 0) + nCutInOffset = nFileSize[FileNumber-1] + FileOffset; + } else { + nCutLength += pos - nCutInFrame; + fCutIn = true; + if (nRecSize >= 0) + nRecSizeCut += nFileSize[FileNumber-1] + FileOffset - nCutInOffset; + } + cMark *nextmark = marks.Next(mark); + mark = nextmark; + } + if (!fCutIn) { + nCutLength += index->Last() - nCutInFrame; + index->Get(index->Last() - 1, &FileNumber, &FileOffset); + if (nRecSize >= 0) + nRecSizeCut += nFileSize[FileNumber-1] + FileOffset - nCutInOffset; + } + } + + if (nRecSize < 0) { + if ((nRecSize = ReadSizeVdr(recording->FileName())) < 0) { + nRecSize = DirSizeMB(recording->FileName()); + } + } + if (nRecSize >= 0) { + cString strRecSize = ""; + cString strRecSizeCut = ""; + + if (fHasMarks) { + if (nRecSize > MEGABYTE(1023)) { + strRecSize = cString::sprintf("%.2f GB", (float)nRecSize / MEGABYTE(1024)); + strRecSizeCut = cString::sprintf("%.2f GB", (float)nRecSizeCut / MEGABYTE(1024)); + } else { + strRecSize = cString::sprintf("%lld MB", nRecSize / MEGABYTE(1)); + strRecSizeCut = cString::sprintf("%lld MB", nRecSizeCut / MEGABYTE(1)); + } + } else { + if (nRecSize > MEGABYTE(1023)) { + strRecSize = cString::sprintf("%.2f GB", (float)nRecSize / MEGABYTE(1024)); + strRecSizeCut = strRecSize; + } else { + strRecSize = cString::sprintf("%lld MB", nRecSize / MEGABYTE(1)); + strRecSizeCut = strRecSize; + } + } + stringTokens.insert(pair("recordingsize", *strRecSize)); + stringTokens.insert(pair("recordingsizecutted", *strRecSizeCut)); + } else { + stringTokens.insert(pair("recordingsize", "")); + stringTokens.insert(pair("recordingsizecutted", "")); + } + + cChannel *channel = Channels.GetByChannelID(Info->ChannelID()); + if (channel) { + stringTokens.insert(pair("recchannelname", channel->Name())); + intTokens.insert(pair("recchannelnumber", channel->Number())); + } + + if (index) { + int nLastIndex = index->Last(); + if (nLastIndex) { + string strLength = *IndexToHMSF(nLastIndex, false, recording->FramesPerSecond()); + string strLengthCutted = ""; + if (fHasMarks) { + strLengthCutted = *IndexToHMSF(nCutLength, false, recording->FramesPerSecond()); + } else { + strLengthCutted = strLength; + } + string strBitrate = *cString::sprintf("%.2f MBit/s", (float)nRecSize / nLastIndex * recording->FramesPerSecond() * 8 / MEGABYTE(1)); + stringTokens.insert(pair("recordinglength", strLength)); + stringTokens.insert(pair("recordinglengthcutted", strLengthCutted)); + stringTokens.insert(pair("recordingbitrate", strBitrate)); + } + delete index; + } + + string recFormat = recording->IsPesRecording() ? "PES" : "TS"; + stringTokens.insert(pair("recordingformat", recFormat)); + + bool searchTimerFound = false; + if (Info) { + const char *aux = NULL; + aux = Info->Aux(); + if (aux) { + string strAux = aux; + string auxEpgsearch = StripXmlTag(strAux, "epgsearch"); + if (!auxEpgsearch.empty()) { + string searchTimer = StripXmlTag(auxEpgsearch, "searchtimer"); + if (!searchTimer.empty()) { + stringTokens.insert(pair("searchtimer", searchTimer)); + searchTimerFound = true; + } + } + } + } + if (!searchTimerFound) + stringTokens.insert(pair("searchtimer", "n.a.")); +} + +string cDisplayMenuDetailView::StripXmlTag(string &Line, const char *Tag) { + // set the search strings + stringstream strStart, strStop; + strStart << "<" << Tag << ">"; + strStop << ""; + // find the strings + string::size_type locStart = Line.find(strStart.str()); + string::size_type locStop = Line.find(strStop.str()); + if (locStart == string::npos || locStop == string::npos) + return ""; + // extract relevant text + int pos = locStart + strStart.str().size(); + int len = locStop - pos; + return len < 0 ? "" : Line.substr(pos, len); +} + + +int cDisplayMenuDetailView::ReadSizeVdr(const char *strPath) { + int dirSize = -1; + char buffer[20]; + char *strFilename = NULL; + if (-1 != asprintf(&strFilename, "%s/size.vdr", strPath)) { + struct stat st; + if (stat(strFilename, &st) == 0) { + int fd = open(strFilename, O_RDONLY); + if (fd >= 0) { + if (safe_read(fd, &buffer, sizeof(buffer)) >= 0) { + dirSize = atoi(buffer); + } + close(fd); + } + } + free(strFilename); + } + return dirSize; +} + +void cDisplayMenuDetailView::SetEpgPictures(int eventId) { + for (int i=0; i<3; i++) { + stringstream picName; + picName << eventId << "_" << i; + bool epgPicAvailable = FileExists(*config.epgImagePath, picName.str(), "jpg"); + stringstream available; + stringstream path; + available << "epgpic" << i+1 << "avaialble"; + path << "epgpic" << i+1 << "path"; + if (epgPicAvailable) { + intTokens.insert(pair(available.str(), true)); + stringTokens.insert(pair(path.str(), *cString::sprintf("%s%s.jpg", *config.epgImagePath, picName.str().c_str()))); + } else { + intTokens.insert(pair(available.str(), false)); + stringTokens.insert(pair(path.str(), "")); + } + } +} + +void cDisplayMenuDetailView::SetRecordingImages(const char *recPath) { + if (!recPath) { + intTokens.insert(pair("recimg1avaialble", false)); + intTokens.insert(pair("recimg2avaialble", false)); + intTokens.insert(pair("recimg3avaialble", false)); + stringTokens.insert(pair("recimg1path", "")); + stringTokens.insert(pair("recimg2path", "")); + stringTokens.insert(pair("recimg3path", "")); + return; + } + + string path = recPath; + DIR *dirHandle; + struct dirent *dirEntry; + dirHandle = opendir(recPath); + if (!dirHandle) { + intTokens.insert(pair("recimg1avaialble", false)); + intTokens.insert(pair("recimg2avaialble", false)); + intTokens.insert(pair("recimg3avaialble", false)); + stringTokens.insert(pair("recimg1path", "")); + stringTokens.insert(pair("recimg2path", "")); + stringTokens.insert(pair("recimg3path", "")); + return; + } + + int picsFound = 0; + while ( 0 != (dirEntry = readdir(dirHandle))) { + if (endswith(dirEntry->d_name, "jpg")) { + string fileName = dirEntry->d_name; + stringstream available; + available << "recimg" << picsFound+1 << "avaialble"; + stringstream path; + path << "recimg" << picsFound+1 << "path"; + intTokens.insert(pair(available.str(), true)); + stringTokens.insert(pair(path.str(), *cString::sprintf("%s/%s", recPath, fileName.c_str()))); + picsFound++; + } + if (picsFound == 3) { + break; + } + } + for (int i=picsFound; i<3; i++) { + stringstream available; + available << "recimg" << i+1 << "avaialble"; + stringstream path; + path << "recimg" << i+1 << "path"; + intTokens.insert(pair(available.str(), false)); + stringTokens.insert(pair(path.str(), "")); + } + closedir(dirHandle); +} + +void cDisplayMenuDetailView::DrawHeader(void) { + map < string, string > headerStringTokens; + map < string, int > headerIntTokens; + + if (event || recording) { + static cPlugin *pScraper = GetScraperPlugin(); + if (!pScraper) { + headerIntTokens.insert(pair("ismovie", false)); + headerIntTokens.insert(pair("isseries", false)); + headerIntTokens.insert(pair("posteravailable", false)); + headerIntTokens.insert(pair("banneravailable", false)); + } else { + ScraperGetEventType getType; + getType.event = event; + getType.recording = recording; + if (!pScraper->Service("GetEventType", &getType)) { + headerIntTokens.insert(pair("ismovie", false)); + headerIntTokens.insert(pair("isseries", false)); + headerIntTokens.insert(pair("posteravailable", false)); + headerIntTokens.insert(pair("banneravailable", false)); + } else { + if (getType.type == tMovie) { + cMovie movie; + movie.movieId = getType.movieId; + pScraper->Service("GetMovie", &movie); + headerIntTokens.insert(pair("ismovie", true)); + headerIntTokens.insert(pair("isseries", false)); + headerIntTokens.insert(pair("posteravailable", true)); + headerIntTokens.insert(pair("banneravailable", false)); + headerStringTokens.insert(pair("posterpath", movie.poster.path)); + headerIntTokens.insert(pair("posterwidth", movie.poster.width)); + headerIntTokens.insert(pair("posterheight", movie.poster.height)); + } else if (getType.type == tSeries) { + cSeries series; + series.seriesId = getType.seriesId; + series.episodeId = getType.episodeId; + pScraper->Service("GetSeries", &series); + headerIntTokens.insert(pair("ismovie", false)); + headerIntTokens.insert(pair("isseries", true)); + vector::iterator poster = series.posters.begin(); + if (poster != series.posters.end()) { + headerIntTokens.insert(pair("posterwidth", (*poster).width)); + headerIntTokens.insert(pair("posterheight", (*poster).height)); + headerStringTokens.insert(pair("posterpath", (*poster).path)); + headerIntTokens.insert(pair("posteravailable", true)); + } else { + headerIntTokens.insert(pair("posterwidth", 0)); + headerIntTokens.insert(pair("posterheight", 0)); + headerStringTokens.insert(pair("posterpath", "")); + headerIntTokens.insert(pair("posteravailable", false)); + } + vector::iterator banner = series.banners.begin(); + if (banner != series.banners.end()) { + headerIntTokens.insert(pair("bannerwidth", (*banner).width)); + headerIntTokens.insert(pair("bannerheight", (*banner).height)); + headerStringTokens.insert(pair("bannerpath", (*banner).path)); + headerIntTokens.insert(pair("banneravailable", true)); + } else { + headerIntTokens.insert(pair("bannerwidth", 0)); + headerIntTokens.insert(pair("bannerheight", 0)); + headerStringTokens.insert(pair("bannerpath", "")); + headerIntTokens.insert(pair("banneravailable", false)); + } + } else { + headerIntTokens.insert(pair("ismovie", false)); + headerIntTokens.insert(pair("isseries", false)); + headerIntTokens.insert(pair("posteravailable", false)); + headerIntTokens.insert(pair("banneravailable", false)); + } + } + } + } + + if (event) { + headerStringTokens.insert(pair("title", event->Title() ? event->Title() : "")); + headerStringTokens.insert(pair("shorttext", event->ShortText() ? event->ShortText() : "")); + headerStringTokens.insert(pair("start", *(event->GetTimeString()))); + headerStringTokens.insert(pair("stop", *(event->GetEndTimeString()))); + headerStringTokens.insert(pair("day", *WeekDayName(event->StartTime()))); + headerStringTokens.insert(pair("date", *ShortDateString(event->StartTime()))); + headerStringTokens.insert(pair("channelid", *(event->ChannelID().ToString()))); + + bool isRunning = false; + time_t now = time(NULL); + if ((now >= event->StartTime()) && (now <= event->EndTime())) + isRunning = true; + headerIntTokens.insert(pair("running", isRunning)); + if (isRunning) { + headerIntTokens.insert(pair("elapsed", (now - event->StartTime())/60)); + } else { + headerIntTokens.insert(pair("elapsed", 0)); + } + headerIntTokens.insert(pair("duration", event->Duration() / 60)); + + stringstream epgImageName; + epgImageName << event->EventID(); + bool epgPicAvailable = FileExists(*config.epgImagePath, epgImageName.str(), "jpg"); + if (epgPicAvailable) { + headerIntTokens.insert(pair("epgpicavailable", true)); + headerStringTokens.insert(pair("epgpicpath", *cString::sprintf("%s%s.jpg", *config.epgImagePath, epgImageName.str().c_str()))); + } else { + epgImageName << "_0"; + epgPicAvailable = FileExists(*config.epgImagePath, epgImageName.str(), "jpg"); + if (epgPicAvailable) { + headerIntTokens.insert(pair("epgpicavailable", true)); + headerStringTokens.insert(pair("epgpicpath", *cString::sprintf("%s%s.jpg", *config.epgImagePath, epgImageName.str().c_str()))); + } else { + headerIntTokens.insert(pair("epgpicavailable", false)); + headerStringTokens.insert(pair("epgpicpath", "")); + } + } + + DrawViewElement(veDetailHeader, &headerStringTokens, &headerIntTokens); + } else if (recording) { + string name = recording->Name() ? recording->Name() : ""; + headerStringTokens.insert(pair("name", name)); + + const cRecordingInfo *info = recording->Info(); + if (info) { + headerStringTokens.insert(pair("shorttext", info->ShortText() ? info->ShortText() : "")); + const cEvent *event = info->GetEvent(); + if (event) { + string recDate = *(event->GetDateString()); + string recTime = *(event->GetTimeString()); + if (recDate.find("1970") != string::npos) { + time_t start = recording->Start(); + recDate = *DateString(start); + recTime = *TimeString(start); + } + int duration = event->Duration() / 60; + int recDuration = recording->LengthInSeconds(); + recDuration = (recDuration>0)?(recDuration / 60):0; + headerStringTokens.insert(pair("date", recDate.c_str())); + headerStringTokens.insert(pair("time", recTime.c_str())); + headerIntTokens.insert(pair("duration", recDuration)); + headerIntTokens.insert(pair("durationevent", duration)); + } + } else { + headerStringTokens.insert(pair("shorttext", "")); + int recDuration = recording->LengthInSeconds(); + recDuration = (recDuration>0)?(recDuration / 60):0; + headerStringTokens.insert(pair("date", "")); + headerStringTokens.insert(pair("time", "")); + headerIntTokens.insert(pair("duration", recDuration)); + headerIntTokens.insert(pair("durationevent", 0)); + } + + string recImage = ""; + string path = recording->FileName() ? recording->FileName() : ""; + string extension = ".jpg"; + if (FirstFileInFolder(path, extension, recImage)) { + headerIntTokens.insert(pair("recimgavailable", true)); + headerStringTokens.insert(pair("recimgpath", *cString::sprintf("%s/%s", path.c_str(), recImage.c_str()))); + } else { + headerIntTokens.insert(pair("recimgavailable", false)); + headerStringTokens.insert(pair("recimgpath", "")); + } + DrawViewElement(veDetailHeader, &headerStringTokens, &headerIntTokens); + } +} + +void cDisplayMenuDetailView::DrawScrollbar(void) { + map < string, string > scrollbarStringTokens; + map < string, int > scrollbarIntTokens; + + int barTop = 0; + int barHeight = 0; + tabView->GetScrollbarPosition(barTop, barHeight); + + scrollbarIntTokens.insert(pair("height", barHeight)); + scrollbarIntTokens.insert(pair("offset", barTop)); + ClearViewElement(veScrollbar); + DrawViewElement(veScrollbar, &scrollbarStringTokens, &scrollbarIntTokens); +} + +void cDisplayMenuDetailView::DrawTabLabels(void) { + if (!ViewElementImplemented(veTabLabels)) { + return; + } + map < string, string > labelStringTokens; + map < string, int > labelIntTokens; + map < string, vector< map< string, string > > > labelLoopTokens; + + vector< map< string, string > > tabLabels; + for (list::iterator it = activeTabs.begin(); it != activeTabs.end(); it++) { + cTemplateViewTab *tab = *it; + map< string, string > tabLabel; + tabLabel.insert(pair< string, string >("tabs[title]", tab->GetName())); + if (tab == currentTmplTab) { + tabLabel.insert(pair< string, string >("tabs[current]", "1")); + } else { + tabLabel.insert(pair< string, string >("tabs[current]", "0")); + } + tabLabels.push_back(tabLabel); + } + labelLoopTokens.insert(pair< string, vector< map< string, string > > >("tabs", tabLabels)); + + ClearViewElement(veTabLabels); + DrawViewElement(veTabLabels, &labelStringTokens, &labelIntTokens, &labelLoopTokens); +} + +cTemplateViewTab *cDisplayMenuDetailView::GetPrevTab(void) { + if (atIt == activeTabs.begin()) { + atIt = activeTabs.end(); + } + atIt--; + return *atIt; +} + +cTemplateViewTab *cDisplayMenuDetailView::GetNextTab(void) { + atIt++; + if (atIt == activeTabs.end()) { + atIt = activeTabs.begin(); + } + return *atIt; +} diff --git a/views/displaymenudetailview.h b/views/displaymenudetailview.h new file mode 100644 index 0000000..c739a28 --- /dev/null +++ b/views/displaymenudetailview.h @@ -0,0 +1,50 @@ +#ifndef __DISPLAYMENUDETAILVIEW_H +#define __DISPLAYMENUDETAILVIEW_H + +#include +#include "../libtemplate/template.h" +#include "view.h" +#include "displaymenutabview.h" + +class cDisplayMenuDetailView : public cView { +private: + bool detailViewInit; + const cEvent *event; + const cRecording *recording; + const char *text; + cTemplateViewTab *currentTmplTab; + list activeTabs; + list::iterator atIt; + cDisplayMenuTabView *tabView; + map < string, string > stringTokens; + map < string, int > intTokens; + map < string, vector< map< string, string > > > loopTokens; + void SetTokens(void); + void SetScraperTokens(void); + void InitTabs(void); + bool LoadReruns(vector< map< string, string > > *reruns); + void LoadRecordingInformation(void); + void SetEpgPictures(int eventId); + void SetRecordingImages(const char *recPath); + string StripXmlTag(string &Line, const char *Tag); + int ReadSizeVdr(const char *strPath); + void DrawHeader(void); + void DrawScrollbar(void); + void DrawTabLabels(void); + cTemplateViewTab *GetPrevTab(void); + cTemplateViewTab *GetNextTab(void); +public: + cDisplayMenuDetailView(cTemplateView *tmplDetailView); + virtual ~cDisplayMenuDetailView(); + void SetEvent(const cEvent *event) { this->event = event; }; + void SetRecording(const cRecording *recording) { this->recording = recording; }; + void SetText(const char *text) { this->text = text; }; + void Clear(void); + void Render(void); + void KeyLeft(void); + void KeyRight(void); + void KeyUp(void); + void KeyDown(void); +}; + +#endif //__DISPLAYMENUDETAILVIEW_H diff --git a/views/displaymenuitemcurrentview.c b/views/displaymenuitemcurrentview.c new file mode 100644 index 0000000..a615794 --- /dev/null +++ b/views/displaymenuitemcurrentview.c @@ -0,0 +1,561 @@ +#include "../services/scraper2vdr.h" +#include "../libcore/helpers.h" +#include "displaymenuitemcurrentview.h" + + +cDisplayMenuItemCurrentView::cDisplayMenuItemCurrentView(cTemplateViewElement *tmplCurrent) : cView(tmplCurrent) { + delay = tmplItem->GetNumericParameter(ptDelay); + SetFadeTime(tmplItem->GetNumericParameter(ptFadeTime)); +} + +cDisplayMenuItemCurrentView::~cDisplayMenuItemCurrentView() { + CancelSave(); +} + +void cDisplayMenuItemCurrentView::SetPosMenuItem(cRect &pos) { + posMenuItem.SetX(pos.X()); + posMenuItem.SetY(pos.Y()); + posMenuItem.SetWidth(pos.Width()); + posMenuItem.SetHeight(pos.Height()); +} + +void cDisplayMenuItemCurrentView::SetTokensPosMenuItem(void) { + intTokens.insert(pair("menuitemx", posMenuItem.X())); + intTokens.insert(pair("menuitemy", posMenuItem.Y())); + intTokens.insert(pair("menuitemwidth", posMenuItem.Width())); + intTokens.insert(pair("menuitemheight", posMenuItem.Height())); +} + +void cDisplayMenuItemCurrentView::SetScraperPoster(const cEvent *event, const cRecording *recording) { + static cPlugin *pScraper = GetScraperPlugin(); + if (!pScraper || (!event && !recording)) { + intTokens.insert(pair("hasposter", false)); + intTokens.insert(pair("posterwidth", -1)); + intTokens.insert(pair("posterheight", -1)); + stringTokens.insert(pair("posterpath", "")); + return; + } + + ScraperGetPoster call; + call.event = event; + call.recording = recording; + if (pScraper->Service("GetPoster", &call)) { + intTokens.insert(pair("hasposter", true)); + intTokens.insert(pair("posterwidth", call.poster.width)); + intTokens.insert(pair("posterheight", call.poster.height)); + stringTokens.insert(pair("posterpath", call.poster.path)); + } else { + intTokens.insert(pair("hasposter", false)); + intTokens.insert(pair("posterwidth", -1)); + intTokens.insert(pair("posterheight", -1)); + stringTokens.insert(pair("posterpath", "")); + } +} + +/************************************************************* +* cDisplayMenuItemCurrentMainView +*************************************************************/ + +cDisplayMenuItemCurrentMainView::cDisplayMenuItemCurrentMainView(cTemplateViewElement *tmplCurrent, string number, string label, string icon) + : cDisplayMenuItemCurrentView(tmplCurrent) { + this->number = number; + this->label = label; + this->icon = icon; +} + +cDisplayMenuItemCurrentMainView::~cDisplayMenuItemCurrentMainView() { +} + +void cDisplayMenuItemCurrentMainView::Prepare(void) { +} + + +void cDisplayMenuItemCurrentMainView::Render(void) { + stringTokens.insert(pair("number", number)); + stringTokens.insert(pair("label", label)); + stringTokens.insert(pair("icon", icon)); + SetTokensPosMenuItem(); + DrawViewElement(veMenuCurrentItemDetail, &stringTokens, &intTokens); +} + +void cDisplayMenuItemCurrentMainView::Clear(void) { + +} + +void cDisplayMenuItemCurrentMainView::Action(void) { + SetInitFinished(); + DoSleep(delay); + Render(); + FadeIn(); + DoFlush(); + if (scrolling) { + DoSleep(scrollDelay); + if (scrollOrientation == orHorizontal) { + ScrollHorizontal(scrollingPix, scrollDelay, scrollSpeed, scrollMode); + } else { + ScrollVertical(scrollingPix, scrollDelay, scrollSpeed); + } + } +} + +/************************************************************* +* cDisplayMenuItemCurrentSchedulesView +*************************************************************/ + +cDisplayMenuItemCurrentSchedulesView::cDisplayMenuItemCurrentSchedulesView(cTemplateViewElement *tmplCurrent, const cEvent *event, const cChannel *channel, eTimerMatch timerMatch, eMenuCategory cat) + : cDisplayMenuItemCurrentView(tmplCurrent) { + this->event = event; + this->channel = channel; + this->timerMatch = timerMatch; + this->cat = cat; +} + +cDisplayMenuItemCurrentSchedulesView::~cDisplayMenuItemCurrentSchedulesView() { +} + +void cDisplayMenuItemCurrentSchedulesView::Prepare(void) { +} + + +void cDisplayMenuItemCurrentSchedulesView::Render(void) { + intTokens.insert(pair("whatson", (cat == mcSchedule) ? true: false)); + intTokens.insert(pair("whatsonnow", (cat == mcScheduleNow) ? true: false)); + intTokens.insert(pair("whatsonnext", (cat == mcScheduleNext) ? true: false)); + if (timerMatch == tmFull) { + intTokens.insert(pair("timerpartitial", false)); + intTokens.insert(pair("timerfull", true)); + } else if (timerMatch == tmPartial) { + intTokens.insert(pair("timerpartitial", true)); + intTokens.insert(pair("timerfull", false)); + } else { + intTokens.insert(pair("timerpartitial", false)); + intTokens.insert(pair("timerfull", false)); + } + + if (event) { + stringTokens.insert(pair("title", event->Title() ? event->Title() : "")); + stringTokens.insert(pair("shorttext", event->ShortText() ? event->ShortText() : "")); + stringTokens.insert(pair("description", event->Description() ? event->Description() : "")); + stringTokens.insert(pair("start", *(event->GetTimeString()))); + stringTokens.insert(pair("stop", *(event->GetEndTimeString()))); + stringTokens.insert(pair("day", *WeekDayName(event->StartTime()))); + stringTokens.insert(pair("date", *ShortDateString(event->StartTime()))); + bool isRunning = false; + time_t now = time(NULL); + if ((now >= event->StartTime()) && (now <= event->EndTime())) + isRunning = true; + intTokens.insert(pair("running", isRunning)); + if (isRunning) { + intTokens.insert(pair("elapsed", (now - event->StartTime())/60)); + } else { + intTokens.insert(pair("elapsed", 0)); + } + intTokens.insert(pair("duration", event->Duration() / 60)); + SetScraperPoster(event); + } + if (channel) { + stringTokens.insert(pair("channelid", *(channel->GetChannelID().ToString()))); + } + + vector< map > schedulesTokens; + if (cat == mcScheduleNow || cat == mcScheduleNext) { + ReadSchedules(&schedulesTokens); + } + map < string, vector< map< string, string > > > loopTokens; + loopTokens.insert(pair > >("schedule", schedulesTokens)); + SetTokensPosMenuItem(); + DrawViewElement(veMenuCurrentItemDetail, &stringTokens, &intTokens, &loopTokens); +} + +void cDisplayMenuItemCurrentSchedulesView::Clear(void) { + +} + +void cDisplayMenuItemCurrentSchedulesView::Action(void) { + SetInitFinished(); + DoSleep(delay); + Render(); + FadeIn(); + DoFlush(); + if (scrolling) { + DoSleep(scrollDelay); + if (scrollOrientation == orHorizontal) { + ScrollHorizontal(scrollingPix, scrollDelay, scrollSpeed, scrollMode); + } else { + ScrollVertical(scrollingPix, scrollDelay, scrollSpeed); + } + } +} + +void cDisplayMenuItemCurrentSchedulesView::ReadSchedules(vector< map > *schedulesTokens) { + if (!event) + return; + const cSchedule *schedule = event->Schedule(); + const cEvent *curEvent = event; + int num = 0; + for (; curEvent; curEvent = schedule->Events()->Next(curEvent)) { + if (num == 0) { + num++; + continue; + } + map element; + element.insert(pair("schedule[start]", *(curEvent->GetTimeString()))); + element.insert(pair("schedule[stop]", *(curEvent->GetEndTimeString()))); + element.insert(pair("schedule[title]", curEvent->Title() ? curEvent->Title() : "")); + element.insert(pair("schedule[shorttext]", curEvent->ShortText() ? curEvent->ShortText() : "")); + schedulesTokens->push_back(element); + num++; + if (num > 10) + break; + } +} + +/************************************************************* +* cDisplayMenuItemCurrentChannelView +*************************************************************/ + +cDisplayMenuItemCurrentChannelView::cDisplayMenuItemCurrentChannelView(cTemplateViewElement *tmplCurrent, const cChannel *channel) + : cDisplayMenuItemCurrentView(tmplCurrent) { + this->channel = channel; +} + +cDisplayMenuItemCurrentChannelView::~cDisplayMenuItemCurrentChannelView() { +} + +void cDisplayMenuItemCurrentChannelView::Prepare(void) { +} + + +void cDisplayMenuItemCurrentChannelView::Render(void) { + if (!channel) + return; + //general channel information + intTokens.insert(pair("number", channel->Number())); + intTokens.insert(pair("transponder", channel->Transponder())); + intTokens.insert(pair("frequency", channel->Frequency())); + + stringTokens.insert(pair("name", channel->Name() ? channel->Name() : "")); + stringTokens.insert(pair("channelid", *(channel->GetChannelID().ToString()))); + + //Channel Source Information + const cSource *source = Sources.Get(channel->Source()); + if (source) { + stringTokens.insert(pair("source", *cSource::ToString(source->Code()))); + stringTokens.insert(pair("sourcedescription", source->Description() ? source->Description() : "")); + stringTokens.insert(pair("source", *cSource::ToString(source->Code()))); + intTokens.insert(pair("isAtsc", source->IsAtsc(source->Code()))); + intTokens.insert(pair("isCable", source->IsCable(source->Code()))); + intTokens.insert(pair("isSat", source->IsSat(source->Code()))); + intTokens.insert(pair("isTerr", source->IsTerr(source->Code()))); + } + + //current schedule + cSchedulesLock schedulesLock; + const cSchedules *schedules = cSchedules::Schedules(schedulesLock); + const cSchedule *schedule = NULL; + schedule = schedules->GetSchedule(channel); + if (schedule) { + const cEvent *presentEvent = schedule->GetPresentEvent(); + if (presentEvent) { + stringTokens.insert(pair("presenteventtitle", presentEvent->Title() ? presentEvent->Title() : "")); + stringTokens.insert(pair("presenteventshorttext", presentEvent->ShortText() ? presentEvent->ShortText() : "")); + stringTokens.insert(pair("presenteventdescription", presentEvent->Description() ? presentEvent->Description() : "")); + stringTokens.insert(pair("presenteventstart", *presentEvent->GetTimeString())); + stringTokens.insert(pair("presenteventstop", *presentEvent->GetEndTimeString())); + stringTokens.insert(pair("presenteventday", *WeekDayName(presentEvent->StartTime()))); + stringTokens.insert(pair("presenteventdate", *ShortDateString(presentEvent->StartTime()))); + intTokens.insert(pair("presenteventelapsed", (time(0) - presentEvent->StartTime())/60)); + intTokens.insert(pair("presenteventduration", presentEvent->Duration() / 60)); + SetScraperPoster(presentEvent); + } else { + stringTokens.insert(pair("presenteventtitle", "")); + stringTokens.insert(pair("presenteventshorttext", "")); + stringTokens.insert(pair("presenteventdescription", "")); + stringTokens.insert(pair("presenteventstart", "")); + stringTokens.insert(pair("presenteventstop", "")); + stringTokens.insert(pair("presenteventday", "")); + stringTokens.insert(pair("presenteventdate", "")); + intTokens.insert(pair("presenteventelapsed", 0)); + intTokens.insert(pair("presenteventduration", 0)); + } + const cList *events = schedule->Events(); + bool inserted = false; + if (events && presentEvent) { + const cEvent *nextEvent = events->Next(presentEvent); + if (nextEvent) { + stringTokens.insert(pair("nexteventtitle", nextEvent->Title() ? nextEvent->Title() : "")); + stringTokens.insert(pair("nexteventshorttext", nextEvent->ShortText() ? nextEvent->ShortText() : "")); + stringTokens.insert(pair("nexteventdescription", nextEvent->Description() ? nextEvent->Description() : "")); + stringTokens.insert(pair("nexteventstart", *nextEvent->GetTimeString())); + stringTokens.insert(pair("nexteventstop", *nextEvent->GetEndTimeString())); + stringTokens.insert(pair("nexteventday", *WeekDayName(nextEvent->StartTime()))); + stringTokens.insert(pair("nexteventdate", *ShortDateString(nextEvent->StartTime()))); + intTokens.insert(pair("nexteventduration", nextEvent->Duration() / 60)); + inserted = true; + } + } + if (!inserted) { + stringTokens.insert(pair("nexteventtitle", "")); + stringTokens.insert(pair("nexteventshorttext", "")); + stringTokens.insert(pair("nexteventdescription", "")); + stringTokens.insert(pair("nexteventstart", "")); + stringTokens.insert(pair("nexteventstop", "")); + stringTokens.insert(pair("nexteventday", "")); + stringTokens.insert(pair("nexteventdate", "")); + intTokens.insert(pair("nexteventduration", 0)); + } + } + + vector< map > schedulesTokens; + ReadSchedules(&schedulesTokens); + + map < string, vector< map< string, string > > > loopTokens; + loopTokens.insert(pair > >("schedule", schedulesTokens)); + SetTokensPosMenuItem(); + DrawViewElement(veMenuCurrentItemDetail, &stringTokens, &intTokens, &loopTokens); +} + +void cDisplayMenuItemCurrentChannelView::Clear(void) { + +} + +void cDisplayMenuItemCurrentChannelView::Action(void) { + SetInitFinished(); + DoSleep(delay); + Render(); + FadeIn(); + DoFlush(); + if (scrolling) { + DoSleep(scrollDelay); + if (scrollOrientation == orHorizontal) { + ScrollHorizontal(scrollingPix, scrollDelay, scrollSpeed, scrollMode); + } else { + ScrollVertical(scrollingPix, scrollDelay, scrollSpeed); + } + } +} + +void cDisplayMenuItemCurrentChannelView::ReadSchedules(vector< map > *schedulesTokens) { + cSchedulesLock schedulesLock; + const cSchedules *schedules = cSchedules::Schedules(schedulesLock); + const cSchedule *schedule = NULL; + schedule = schedules->GetSchedule(channel); + if (!schedule) { + return; + } + const cEvent *curEvent = schedule->GetPresentEvent(); + int num = 0; + for (; curEvent; curEvent = schedule->Events()->Next(curEvent)) { + if (num < 2) { + num++; + continue; + } + map element; + element.insert(pair("schedule[start]", *(curEvent->GetTimeString()))); + element.insert(pair("schedule[stop]", *(curEvent->GetEndTimeString()))); + element.insert(pair("schedule[title]", curEvent->Title() ? curEvent->Title() : "")); + element.insert(pair("schedule[shorttext]", curEvent->ShortText() ? curEvent->ShortText() : "")); + schedulesTokens->push_back(element); + num++; + if (num > 11) + break; + } +} + +/************************************************************* +* cDisplayMenuItemCurrentTimerView +*************************************************************/ + +cDisplayMenuItemCurrentTimerView::cDisplayMenuItemCurrentTimerView(cTemplateViewElement *tmplCurrent, const cTimer *timer) + : cDisplayMenuItemCurrentView(tmplCurrent) { + this->timer = timer; +} + +cDisplayMenuItemCurrentTimerView::~cDisplayMenuItemCurrentTimerView() { +} + +void cDisplayMenuItemCurrentTimerView::Prepare(void) { +} + + +void cDisplayMenuItemCurrentTimerView::Render(void) { + if (!timer) + return; + intTokens.insert(pair("flagactive", timer->HasFlags(tfActive))); + intTokens.insert(pair("flaginstant", timer->HasFlags(tfInstant))); + intTokens.insert(pair("flagvps", timer->HasFlags(tfVps))); + intTokens.insert(pair("flagrecording", timer->Recording())); + intTokens.insert(pair("flagpending", timer->Pending())); + + const char *file = Setup.FoldersInTimerMenu ? NULL : strrchr(timer->File(), FOLDERDELIMCHAR); + if (file && strcmp(file + 1, TIMERMACRO_TITLE) && strcmp(file + 1, TIMERMACRO_EPISODE)) + file++; + else + file = timer->File(); + stringTokens.insert(pair("title", file)); + stringTokens.insert(pair("timerstart", *cString::sprintf("%02d:%02d", timer->Start() / 100, timer->Start() % 100))); + stringTokens.insert(pair("timerstop", *cString::sprintf("%02d:%02d", timer->Stop() / 100, timer->Stop() % 100))); + + string day = ""; + string dayName = ""; + if (timer->WeekDays()) + day = timer->PrintDay(0, timer->WeekDays(), false); + else if (timer->Day() - time(NULL) < 28 * SECSINDAY) { + day = itoa(timer->GetMDay(timer->Day())); + dayName = WeekDayName(timer->Day()); + } else { + struct tm tm_r; + time_t Day = timer->Day(); + localtime_r(&Day, &tm_r); + char buffer[16]; + strftime(buffer, sizeof(buffer), "%Y%m%d", &tm_r); + day = buffer; + } + stringTokens.insert(pair("day", day)); + stringTokens.insert(pair("dayname", dayName)); + + const cChannel *channel = timer->Channel(); + if (channel) { + stringTokens.insert(pair("channelname", channel->Name() ? channel->Name() : "")); + stringTokens.insert(pair("channelid", *(channel->GetChannelID().ToString()))); + intTokens.insert(pair("channelnumber", channel->Number())); + } else { + stringTokens.insert(pair("channelname", "")); + stringTokens.insert(pair("channelid", "")); + intTokens.insert(pair("channelnumber", 0)); + } + + const cEvent *event = timer->Event(); + if (event) { + stringTokens.insert(pair("eventtitle", event->Title() ? event->Title() : "")); + stringTokens.insert(pair("eventstart", *event->GetTimeString())); + stringTokens.insert(pair("eventstop", *event->GetEndTimeString())); + stringTokens.insert(pair("eventshorttext", event->ShortText() ? event->ShortText() : "")); + stringTokens.insert(pair("eventdescription", event->Description() ? event->Description() : "")); + SetScraperPoster(event); + } else { + stringTokens.insert(pair("eventtitle", "")); + stringTokens.insert(pair("eventtitle", "")); + stringTokens.insert(pair("eventstop", "")); + stringTokens.insert(pair("eventshorttext", "")); + stringTokens.insert(pair("eventdescription", "")); + } + SetTokensPosMenuItem(); + DrawViewElement(veMenuCurrentItemDetail, &stringTokens, &intTokens); +} + +void cDisplayMenuItemCurrentTimerView::Clear(void) { + +} + +void cDisplayMenuItemCurrentTimerView::Action(void) { + SetInitFinished(); + DoSleep(delay); + Render(); + FadeIn(); + DoFlush(); + if (scrolling) { + DoSleep(scrollDelay); + if (scrollOrientation == orHorizontal) { + ScrollHorizontal(scrollingPix, scrollDelay, scrollSpeed, scrollMode); + } else { + ScrollVertical(scrollingPix, scrollDelay, scrollSpeed); + } + } +} + +/************************************************************* +* cDisplayMenuItemCurrentRecordingView +*************************************************************/ + +cDisplayMenuItemCurrentRecordingView::cDisplayMenuItemCurrentRecordingView(cTemplateViewElement *tmplCurrent, const cRecording *recording, int level, int total, int newRecs) + : cDisplayMenuItemCurrentView(tmplCurrent) { + this->recording = recording; + this->level = level; + this->total = total; + this->newRecs = newRecs; +} + +cDisplayMenuItemCurrentRecordingView::~cDisplayMenuItemCurrentRecordingView() { +} + +void cDisplayMenuItemCurrentRecordingView::Prepare(void) { +} + + +void cDisplayMenuItemCurrentRecordingView::Render(void) { + if (!recording) + return; + bool isFolder = (total > 0) ? true : false; + intTokens.insert(pair("folder", isFolder)); + + string name = recording->Name() ? recording->Name() : ""; + string buffer = ""; + try { + vector tokens; + istringstream f(name.c_str()); + string s; + while (getline(f, s, FOLDERDELIMCHAR)) { + tokens.push_back(s); + } + buffer = tokens.at(level); + if (!isFolder && recording->IsEdited()) { + buffer = buffer.substr(1); + } + } catch (...) { + buffer = name.c_str(); + } + stringTokens.insert(pair("name", buffer.c_str())); + intTokens.insert(pair("new", recording->IsNew())); + intTokens.insert(pair("newrecordingsfolder", newRecs)); + intTokens.insert(pair("numrecordingsfolder", total)); + intTokens.insert(pair("cutted", recording->IsEdited())); + + SetScraperPoster(NULL, recording); + + const cRecordingInfo *info = recording->Info(); + if (!info) return; + + stringTokens.insert(pair("shorttext", info->ShortText() ? info->ShortText() : "")); + stringTokens.insert(pair("description", info->Description() ? info->Description() : "")); + + const cEvent *event = info->GetEvent(); + if (!event) return; + + string recDate = *(event->GetDateString()); + string recTime = *(event->GetTimeString()); + if (recDate.find("1970") != string::npos) { + time_t start = recording->Start(); + recDate = *DateString(start); + recTime = *TimeString(start); + } + int duration = event->Duration() / 60; + int recDuration = recording->LengthInSeconds(); + recDuration = (recDuration>0)?(recDuration / 60):0; + stringTokens.insert(pair("date", recDate.c_str())); + stringTokens.insert(pair("time", recTime.c_str())); + intTokens.insert(pair("duration", recDuration)); + intTokens.insert(pair("durationevent", duration)); + SetTokensPosMenuItem(); + DrawViewElement(veMenuCurrentItemDetail, &stringTokens, &intTokens); +} + +void cDisplayMenuItemCurrentRecordingView::Clear(void) { + +} + +void cDisplayMenuItemCurrentRecordingView::Action(void) { + SetInitFinished(); + DoSleep(delay); + Render(); + FadeIn(); + DoFlush(); + if (scrolling) { + DoSleep(scrollDelay); + if (scrollOrientation == orHorizontal) { + ScrollHorizontal(scrollingPix, scrollDelay, scrollSpeed, scrollMode); + } else { + ScrollVertical(scrollingPix, scrollDelay, scrollSpeed); + } + } +} diff --git a/views/displaymenuitemcurrentview.h b/views/displaymenuitemcurrentview.h new file mode 100644 index 0000000..12f31e3 --- /dev/null +++ b/views/displaymenuitemcurrentview.h @@ -0,0 +1,94 @@ +#ifndef __DISPLAYMENUITEMCURRENTVIEW_H +#define __DISPLAYMENUITEMCURRENTVIEW_H + +#include "../libtemplate/template.h" +#include "view.h" + +class cDisplayMenuItemCurrentView : public cView { +private: +protected: + int delay; + map < string, string > stringTokens; + map < string, int > intTokens; + cRect posMenuItem; + void SetTokensPosMenuItem(void); + void SetScraperPoster(const cEvent *event, const cRecording *recording=NULL); +public: + cDisplayMenuItemCurrentView(cTemplateViewElement *tmplCurrent); + virtual ~cDisplayMenuItemCurrentView(); + void SetPosMenuItem(cRect &pos); + virtual void Prepare(void) {}; + virtual void Render(void) {}; + virtual void Clear(void) {}; +}; + +class cDisplayMenuItemCurrentMainView: public cDisplayMenuItemCurrentView { +private: + string number; + string label; + string icon; + void Action(void); +public: + cDisplayMenuItemCurrentMainView(cTemplateViewElement *tmplCurrent, string number, string label, string icon); + virtual ~cDisplayMenuItemCurrentMainView(); + void Prepare(void); + void Render(void); + void Clear(void); +}; + +class cDisplayMenuItemCurrentSchedulesView: public cDisplayMenuItemCurrentView { +private: + const cEvent *event; + const cChannel *channel; + eTimerMatch timerMatch; + eMenuCategory cat; + void Action(void); + void ReadSchedules(vector< map > *schedulesTokens); +public: + cDisplayMenuItemCurrentSchedulesView(cTemplateViewElement *tmplCurrent, const cEvent *event, const cChannel *channel, eTimerMatch timerMatch, eMenuCategory cat); + virtual ~cDisplayMenuItemCurrentSchedulesView(); + void Prepare(void); + void Render(void); + void Clear(void); +}; + +class cDisplayMenuItemCurrentChannelView: public cDisplayMenuItemCurrentView { +private: + const cChannel *channel; + void Action(void); + void ReadSchedules(vector< map > *schedulesTokens); +public: + cDisplayMenuItemCurrentChannelView(cTemplateViewElement *tmplCurrent, const cChannel *channel); + virtual ~cDisplayMenuItemCurrentChannelView(); + void Prepare(void); + void Render(void); + void Clear(void); +}; + +class cDisplayMenuItemCurrentTimerView: public cDisplayMenuItemCurrentView { +private: + const cTimer *timer; + void Action(void); +public: + cDisplayMenuItemCurrentTimerView(cTemplateViewElement *tmplCurrent, const cTimer *timer); + virtual ~cDisplayMenuItemCurrentTimerView(); + void Prepare(void); + void Render(void); + void Clear(void); +}; + +class cDisplayMenuItemCurrentRecordingView: public cDisplayMenuItemCurrentView { +private: + const cRecording *recording; + int level; + int total; + int newRecs; + void Action(void); +public: + cDisplayMenuItemCurrentRecordingView(cTemplateViewElement *tmplCurrent, const cRecording *recording, int level, int total, int newRecs); + virtual ~cDisplayMenuItemCurrentRecordingView(); + void Prepare(void); + void Render(void); + void Clear(void); +}; +#endif //__DISPLAYMENUITEMCURRENTVIEW_H diff --git a/views/displaymenuitemview.c b/views/displaymenuitemview.c new file mode 100644 index 0000000..b103cf3 --- /dev/null +++ b/views/displaymenuitemview.c @@ -0,0 +1,731 @@ +#include "displaymenuitemview.h" +#include "../services/scraper2vdr.h" +#include "../config.h" +#include "../libcore/helpers.h" +#include +#include + +/************************************************************* +* cDisplayMenuItemView +*************************************************************/ + +cDisplayMenuItemView::cDisplayMenuItemView(cTemplateViewList *tmplList, bool current, bool selectable) : cViewListItem(tmplList->GetListElement()) { + this->tmplList = tmplList; + this->current = current; + this->selectable = selectable; + itemInit = true; + dirty = true; + num = 0; + currentView = NULL; +} + +cDisplayMenuItemView::~cDisplayMenuItemView() { + if (currentView) + delete currentView; + CancelSave(); +} + +void cDisplayMenuItemView::SetCurrent(bool cur) { + current = cur; + intTokens.erase("current"); + intTokens.insert(pair("current", current)); + dirty = true; +}; + + +void cDisplayMenuItemView::ArrangeContainer(void) { + if (pos > -1) + return; + SetInitFinished(); + pos = num; + numTotal = tmplList->GetNumericParameter(ptNumElements); + container.SetX(tmplList->GetNumericParameter(ptX)); + container.SetY(tmplList->GetNumericParameter(ptY)); + container.SetWidth(tmplList->GetNumericParameter(ptWidth)); + container.SetHeight(tmplList->GetNumericParameter(ptHeight)); + align = tmplList->GetNumericParameter(ptAlign); + listOrientation = tmplList->GetNumericParameter(ptOrientation); +} + +void cDisplayMenuItemView::Clear(void) { + ClearListItem(); + if (currentView) { + delete currentView; + currentView = NULL; + } +} + +void cDisplayMenuItemView::PrepareScrolling(void) { + currentlyScrolling = true; + ClearListItem(); + DrawListItem(&stringTokens, &intTokens); +} + +void cDisplayMenuItemView::EndScrolling(void) { + const cPoint p(0,0); + SetDrawPortPoint(scrollingPix, p); + currentlyScrolling = false; + ClearListItem(); + DrawListItem(&stringTokens, &intTokens); +} + +void cDisplayMenuItemView::Action(void) { + if (scrolling) { + DoSleep(scrollDelay); + PrepareScrolling(); + if (scrollOrientation == orHorizontal) { + ScrollHorizontal(scrollingPix, scrollDelay, scrollSpeed, scrollMode); + } else { + ScrollVertical(scrollingPix, scrollDelay, scrollSpeed); + } + } +} + +void cDisplayMenuItemView::Stop(void) { + if (Running()) { + CancelSave(); + EndScrolling(); + } +} + + +void cDisplayMenuItemView::Debug(void) { + esyslog("skindesigner: current %d, selectable %d", current, selectable); + esyslog("skindesigner: pos %d, numTotal %d", pos, numTotal); + esyslog("skindesigner: container x = %d, y = %d, width = %d, height = %d", container.X(), container.Y(), container.Width(), container.Height()); +} + +/************************************************************* +* cDisplayMenuItemDefaultView +*************************************************************/ + +cDisplayMenuItemDefaultView::cDisplayMenuItemDefaultView(cTemplateViewList *tmplList, string *tabTexts, int *tabs, int *tabWidths, bool current, bool selectable) + : cDisplayMenuItemView(tmplList, current, selectable) { + this->tabTexts = tabTexts; + this->tabs = tabs; + this->tabWidths = tabWidths; + maxTabs = cSkinDisplayMenu::MaxTabs; +} + +cDisplayMenuItemDefaultView::~cDisplayMenuItemDefaultView() { + delete[] tabTexts; +} + +void cDisplayMenuItemDefaultView::SetTabTexts(string *tabTexts) { + delete[] this->tabTexts; + this->tabTexts = tabTexts; +} + +void cDisplayMenuItemDefaultView::SetTokens(void) { + stringTokens.clear(); + intTokens.clear(); + for (int i=0; i(name.str(), tabTexts[i])); + if (i>0) + intTokens.insert(pair(nameUsed.str(), (tabTexts[i].size() > 0) ? 1 : 0 )); + intTokens.insert(pair(nameX.str(), tabs[i])); + intTokens.insert(pair(nameWidth.str(), tabWidths[i])); + } + intTokens.insert(pair("current", current)); + intTokens.insert(pair("separator", !selectable)); +} + +void cDisplayMenuItemDefaultView::Prepare(void) { + ArrangeContainer(); +} + + +void cDisplayMenuItemDefaultView::Render(void) { + DrawListItem(&stringTokens, &intTokens); + dirty = false; +} + +void cDisplayMenuItemDefaultView::Debug(void) { + esyslog("skindesigner: Default Menu Item ---------------"); + cDisplayMenuItemView::Debug(); + for (int i=0; i("number", number)); + stringTokens.insert(pair("label", label)); + stringTokens.insert(pair("icon", icon)); + + intTokens.insert(pair("current", current)); + intTokens.insert(pair("separator", !selectable)); +} + +void cDisplayMenuItemMainView::Prepare(void) { + ArrangeContainer(); + SplitMenuText(); + icon = imgCache->GetIconName(label); +} + + +void cDisplayMenuItemMainView::Render(void) { + + cRect pos = DrawListItem(&stringTokens, &intTokens); + + if (current) { + cTemplateViewElement *tmplCurrent = tmplList->GetListElementCurrent(); + if (tmplCurrent) { + currentView = new cDisplayMenuItemCurrentMainView(tmplCurrent, number, label, icon); + currentView->SetPosMenuItem(pos); + currentView->Start(); + } + } + + dirty = false; +} + +void cDisplayMenuItemMainView::Debug(void) { + esyslog("skindesigner: Main Menu Item ---------------"); + cDisplayMenuItemView::Debug(); + esyslog("skindesigner: item Text: %s", text.c_str()); + esyslog("skindesigner: item Number: %s, Label: %s", number.c_str(), label.c_str()); + esyslog("skindesigner: Icon: %s", icon.c_str()); +} + +/************************************************************* +* Private Functions +*************************************************************/ + +void cDisplayMenuItemMainView::SplitMenuText(void) { + string textPlain = skipspace(text.c_str()); + bool found = false; + bool doBreak = false; + size_t i = 0; + for (; i < textPlain.length(); i++) { + char s = textPlain.at(i); + if (i==0) { + //if text directly starts with nonnumeric, break + if (!(s >= '0' && s <= '9')) { + break; + } + } + if (found) { + if (!(s >= '0' && s <= '9')) { + doBreak = true; + } + } + if (s >= '0' && s <= '9') { + found = true; + } + if (doBreak) + break; + if (i>4) + break; + } + if (found) { + number = skipspace(textPlain.substr(0,i).c_str()); + label = skipspace(textPlain.substr(i).c_str()); + } else { + number = ""; + label = textPlain.c_str(); + } +} + +/************************************************************* +* cDisplayMenuItemSchedulesView +*************************************************************/ + +cDisplayMenuItemSchedulesView::cDisplayMenuItemSchedulesView(cTemplateViewList *tmplList, const cEvent *event, + const cChannel *channel, eTimerMatch timerMatch, + eMenuCategory cat, bool current, bool selectable) + : cDisplayMenuItemView(tmplList, current, selectable) { + this->event = event; + this->channel = channel; + this->timerMatch = timerMatch; + this->cat = cat; +} + +cDisplayMenuItemSchedulesView::~cDisplayMenuItemSchedulesView() { +} + +void cDisplayMenuItemSchedulesView::SetTokens(void) { + if (!itemInit) + return; + itemInit = false; + intTokens.insert(pair("current", current)); + intTokens.insert(pair("separator", !selectable)); + intTokens.insert(pair("whatson", (cat == mcSchedule) ? true: false)); + intTokens.insert(pair("whatsonnow", (cat == mcScheduleNow) ? true: false)); + intTokens.insert(pair("whatsonnext", (cat == mcScheduleNext) ? true: false)); + if (timerMatch == tmFull) { + intTokens.insert(pair("timerpartitial", false)); + intTokens.insert(pair("timerfull", true)); + } else if (timerMatch == tmPartial) { + intTokens.insert(pair("timerpartitial", true)); + intTokens.insert(pair("timerfull", false)); + } else { + intTokens.insert(pair("timerpartitial", false)); + intTokens.insert(pair("timerfull", false)); + } + + if (event) { + if (selectable) { + stringTokens.insert(pair("title", event->Title() ? event->Title() : "")); + stringTokens.insert(pair("shorttext", event->ShortText() ? event->ShortText() : "")); + stringTokens.insert(pair("start", *(event->GetTimeString()))); + stringTokens.insert(pair("stop", *(event->GetEndTimeString()))); + stringTokens.insert(pair("day", *WeekDayName(event->StartTime()))); + stringTokens.insert(pair("date", *ShortDateString(event->StartTime()))); + bool isRunning = false; + time_t now = time(NULL); + if ((now >= event->StartTime()) && (now <= event->EndTime())) + isRunning = true; + intTokens.insert(pair("running", isRunning)); + if (isRunning) { + intTokens.insert(pair("elapsed", (now - event->StartTime())/60)); + } else { + intTokens.insert(pair("elapsed", 0)); + } + intTokens.insert(pair("duration", event->Duration() / 60)); + } else { + stringTokens.insert(pair("title", event->Title() ? ParseSeparator(event->Title()) : "")); + } + } + if (channel) { + stringTokens.insert(pair("channelid", *(channel->GetChannelID().ToString()))); + if (!event && !selectable) { + stringTokens.insert(pair("title", channel->Name() ? ParseSeparator(channel->Name()) : "")); + } + } +} + + +void cDisplayMenuItemSchedulesView::Prepare(void) { + ArrangeContainer(); +} + +void cDisplayMenuItemSchedulesView::Render(void) { + + DrawListItem(&stringTokens, &intTokens); + + if (current) { + cTemplateViewElement *tmplCurrent = tmplList->GetListElementCurrent(); + if (tmplCurrent) { + currentView = new cDisplayMenuItemCurrentSchedulesView(tmplCurrent, event, channel, timerMatch, cat); + currentView->Start(); + } + } + + dirty = false; +} + +void cDisplayMenuItemSchedulesView::Debug(void) { + esyslog("skindesigner: Schedules Menu Item ---------------"); + cDisplayMenuItemView::Debug(); + esyslog("skindesigner: Event: %s", event ? event->Title() : "Event is NULL"); +} + +/************************************************************* +* Private Functions +*************************************************************/ + +string cDisplayMenuItemSchedulesView::ParseSeparator(string sep) { + string separator = sep; + try { + if (separator.find_first_not_of("-") > 0) + separator.erase(0, separator.find_first_not_of("-")+1); + if (separator.find_last_not_of("-") != string::npos) + separator.erase(separator.find_last_not_of("-")+1); + } catch (...) {} + return separator; +} + +/************************************************************* +* cDisplayMenuItemChannelsView +*************************************************************/ + +cDisplayMenuItemChannelsView::cDisplayMenuItemChannelsView(cTemplateViewList *tmplList, const cChannel *channel, + bool withProvider, bool current, bool selectable) + : cDisplayMenuItemView(tmplList, current, selectable) { + this->channel = channel; + this->withProvider = withProvider; +} + +cDisplayMenuItemChannelsView::~cDisplayMenuItemChannelsView() { +} + +void cDisplayMenuItemChannelsView::SetTokens(void) { + if (!itemInit) + return; + itemInit = false; + if (!channel) + return; + //general channel information + intTokens.insert(pair("current", current)); + intTokens.insert(pair("separator", !selectable)); + intTokens.insert(pair("number", channel->Number())); + intTokens.insert(pair("transponder", channel->Transponder())); + intTokens.insert(pair("frequency", channel->Frequency())); + + stringTokens.insert(pair("name", channel->Name() ? channel->Name() : "")); + stringTokens.insert(pair("channelid", *(channel->GetChannelID().ToString()))); + + //Channel Source Information + const cSource *source = Sources.Get(channel->Source()); + if (source) { + stringTokens.insert(pair("source", *cSource::ToString(source->Code()))); + stringTokens.insert(pair("sourcedescription", source->Description() ? source->Description() : "")); + stringTokens.insert(pair("source", *cSource::ToString(source->Code()))); + intTokens.insert(pair("isAtsc", source->IsAtsc(source->Code()))); + intTokens.insert(pair("isCable", source->IsCable(source->Code()))); + intTokens.insert(pair("isSat", source->IsSat(source->Code()))); + intTokens.insert(pair("isTerr", source->IsTerr(source->Code()))); + } + + //current schedule + cSchedulesLock schedulesLock; + const cSchedules *schedules = cSchedules::Schedules(schedulesLock); + const cSchedule *schedule = NULL; + schedule = schedules->GetSchedule(channel); + bool inserted = false; + if (schedule) { + const cEvent *presentEvent = schedule->GetPresentEvent(); + if (presentEvent) { + stringTokens.insert(pair("presenteventtitle", presentEvent->Title() ? presentEvent->Title() : "")); + stringTokens.insert(pair("presenteventstart", *presentEvent->GetTimeString())); + stringTokens.insert(pair("presenteventstop", *presentEvent->GetEndTimeString())); + inserted = true; + } + } + if (!inserted) { + stringTokens.insert(pair("presenteventtitle", "")); + stringTokens.insert(pair("presenteventstart", "")); + stringTokens.insert(pair("presenteventstop", "")); + } +} + + +void cDisplayMenuItemChannelsView::Prepare(void) { + ArrangeContainer(); +} + +void cDisplayMenuItemChannelsView::Render(void) { + + DrawListItem(&stringTokens, &intTokens); + + if (current) { + cTemplateViewElement *tmplCurrent = tmplList->GetListElementCurrent(); + if (tmplCurrent) { + currentView = new cDisplayMenuItemCurrentChannelView(tmplCurrent, channel); + currentView->Start(); + } + } + + dirty = false; +} + +void cDisplayMenuItemChannelsView::Debug(void) { + esyslog("skindesigner: Channels Menu Item ---------------"); + cDisplayMenuItemView::Debug(); + esyslog("skindesigner: Channel: %s", channel ? channel->Name() : "Channel is NULL"); +} + +/************************************************************* +* Private Functions +*************************************************************/ + +/************************************************************* +* cDisplayMenuItemTimersView +*************************************************************/ + +cDisplayMenuItemTimersView::cDisplayMenuItemTimersView(cTemplateViewList *tmplList, const cTimer *timer, bool current, bool selectable) + : cDisplayMenuItemView(tmplList, current, selectable) { + this->timer = timer; +} + +cDisplayMenuItemTimersView::~cDisplayMenuItemTimersView() { +} + +void cDisplayMenuItemTimersView::SetTokens(void) { + if (!timer) + return; + if (!itemInit) { + intTokens.erase("flagactive"); + intTokens.insert(pair("flagactive", timer->HasFlags(tfActive))); + return; + } + itemInit = false; + + intTokens.insert(pair("current", current)); + intTokens.insert(pair("flagactive", timer->HasFlags(tfActive))); + intTokens.insert(pair("flaginstant", timer->HasFlags(tfInstant))); + intTokens.insert(pair("flagvps", timer->HasFlags(tfVps))); + intTokens.insert(pair("flagrecording", timer->Recording())); + intTokens.insert(pair("flagpending", timer->Pending())); + + + const char *file = Setup.FoldersInTimerMenu ? NULL : strrchr(timer->File(), FOLDERDELIMCHAR); + if (file && strcmp(file + 1, TIMERMACRO_TITLE) && strcmp(file + 1, TIMERMACRO_EPISODE)) + file++; + else + file = timer->File(); + stringTokens.insert(pair("title", file)); + stringTokens.insert(pair("timerstart", *cString::sprintf("%02d:%02d", timer->Start() / 100, timer->Start() % 100))); + stringTokens.insert(pair("timerstop", *cString::sprintf("%02d:%02d", timer->Stop() / 100, timer->Stop() % 100))); + + string day = ""; + string dayName = ""; + if (timer->WeekDays()) + day = timer->PrintDay(0, timer->WeekDays(), false); + else if (timer->Day() - time(NULL) < 28 * SECSINDAY) { + day = itoa(timer->GetMDay(timer->Day())); + dayName = WeekDayName(timer->Day()); + } else { + struct tm tm_r; + time_t Day = timer->Day(); + localtime_r(&Day, &tm_r); + char buffer[16]; + strftime(buffer, sizeof(buffer), "%Y%m%d", &tm_r); + day = buffer; + } + stringTokens.insert(pair("day", day)); + stringTokens.insert(pair("dayname", dayName)); + + const cChannel *channel = timer->Channel(); + if (channel) { + stringTokens.insert(pair("channelname", channel->Name() ? channel->Name() : "")); + stringTokens.insert(pair("channelid", *(channel->GetChannelID().ToString()))); + intTokens.insert(pair("channelnumber", channel->Number())); + } else { + stringTokens.insert(pair("channelname", "")); + stringTokens.insert(pair("channelid", "")); + intTokens.insert(pair("channelnumber", 0)); + } + + const cEvent *event = timer->Event(); + if (event) { + stringTokens.insert(pair("eventtitle", event->Title() ? event->Title() : "")); + stringTokens.insert(pair("eventstart", *event->GetTimeString())); + stringTokens.insert(pair("eventstop", *event->GetEndTimeString())); + } else { + stringTokens.insert(pair("eventtitle", "")); + stringTokens.insert(pair("eventtitle", "")); + stringTokens.insert(pair("eventstop", "")); + } +} + + +void cDisplayMenuItemTimersView::Prepare(void) { + ArrangeContainer(); +} + +void cDisplayMenuItemTimersView::Render(void) { + + DrawListItem(&stringTokens, &intTokens); + + if (current) { + cTemplateViewElement *tmplCurrent = tmplList->GetListElementCurrent(); + if (tmplCurrent) { + currentView = new cDisplayMenuItemCurrentTimerView(tmplCurrent, timer); + currentView->Start(); + } + } + + dirty = false; +} + +void cDisplayMenuItemTimersView::Debug(void) { + esyslog("skindesigner: Timers Menu Item ---------------"); + cDisplayMenuItemView::Debug(); + esyslog("skindesigner: Timer: %s", timer ? *(timer->ToDescr()) : "Timer is NULL"); +} + +/************************************************************* +* Private Functions +*************************************************************/ + + +/************************************************************* +* cDisplayMenuItemRecordingView +*************************************************************/ + +cDisplayMenuItemRecordingView::cDisplayMenuItemRecordingView(cTemplateViewList *tmplList, const cRecording *recording, int level, int total, int newRecs, bool current, bool selectable) + : cDisplayMenuItemView(tmplList, current, selectable) { + this->recording = recording; + this->level = level; + this->total = total; + this->newRecs = newRecs; +} + +cDisplayMenuItemRecordingView::~cDisplayMenuItemRecordingView() { +} + +void cDisplayMenuItemRecordingView::SetTokens(void) { + if (!itemInit) return; + itemInit = false; + if (!recording) return; + + intTokens.insert(pair("current", current)); + bool isFolder = (total > 0) ? true : false; + intTokens.insert(pair("folder", isFolder)); + + string name = recording->Name() ? recording->Name() : ""; + string buffer = ""; + try { + vector tokens; + istringstream f(name.c_str()); + string s; + while (getline(f, s, FOLDERDELIMCHAR)) { + tokens.push_back(s); + } + buffer = tokens.at(level); + if (!isFolder && recording->IsEdited()) { + buffer = buffer.substr(1); + } + } catch (...) { + buffer = name.c_str(); + } + stringTokens.insert(pair("name", buffer.c_str())); + intTokens.insert(pair("new", recording->IsNew())); + intTokens.insert(pair("newrecordingsfolder", newRecs)); + intTokens.insert(pair("numrecordingsfolder", total)); + intTokens.insert(pair("cutted", recording->IsEdited())); + + const cEvent *event = NULL; + const cRecordingInfo *info = recording->Info(); + if (!info) return; + event = info->GetEvent(); + if (!event) return; + + string recDate = *(event->GetDateString()); + string recTime = *(event->GetTimeString()); + if (recDate.find("1970") != string::npos) { + time_t start = recording->Start(); + recDate = *DateString(start); + recTime = *TimeString(start); + } + int duration = event->Duration() / 60; + int recDuration = recording->LengthInSeconds(); + recDuration = (recDuration>0)?(recDuration / 60):0; + stringTokens.insert(pair("date", recDate.c_str())); + stringTokens.insert(pair("time", recTime.c_str())); + intTokens.insert(pair("duration", recDuration)); + intTokens.insert(pair("durationevent", duration)); + + static cPlugin *pScraper = GetScraperPlugin(); + if (!pScraper || !recording) { + intTokens.insert(pair("hasposterthumbnail", false)); + intTokens.insert(pair("thumbnailbwidth", -1)); + intTokens.insert(pair("thumbnailheight", -1)); + stringTokens.insert(pair("thumbnailpath", "")); + return; + } + + ScraperGetPosterThumb call; + call.event = NULL; + call.recording = recording; + if (pScraper->Service("GetPosterThumb", &call)) { + intTokens.insert(pair("hasposterthumbnail", true)); + intTokens.insert(pair("thumbnailbwidth", call.poster.width)); + intTokens.insert(pair("thumbnailheight", call.poster.height)); + stringTokens.insert(pair("thumbnailpath", call.poster.path)); + } else { + intTokens.insert(pair("hasposterthumbnail", false)); + intTokens.insert(pair("thumbnailbwidth", -1)); + intTokens.insert(pair("thumbnailheight", -1)); + stringTokens.insert(pair("thumbnailpath", "")); + } +} + + +void cDisplayMenuItemRecordingView::Prepare(void) { + ArrangeContainer(); +} + +void cDisplayMenuItemRecordingView::Render(void) { + + DrawListItem(&stringTokens, &intTokens); + + if (current) { + cTemplateViewElement *tmplCurrent = tmplList->GetListElementCurrent(); + if (tmplCurrent) { + currentView = new cDisplayMenuItemCurrentRecordingView(tmplCurrent, recording, level, total, newRecs); + currentView->Start(); + } + } + + dirty = false; +} + +void cDisplayMenuItemRecordingView::Debug(void) { + esyslog("skindesigner: Recording Menu Item ---------------"); + cDisplayMenuItemView::Debug(); + esyslog("skindesigner: Recording: %s", recording ? recording->Title() : "Recording is NULL"); +} + +/************************************************************* +* cDisplayMenuItemTrackView +*************************************************************/ + +cDisplayMenuItemTrackView::cDisplayMenuItemTrackView(cTemplateViewList *tmplList, const char *title, bool current, bool selectable, int numTracks) + : cDisplayMenuItemView(tmplList, current, selectable) { + this->title = title; + this->numTracks = numTracks; +} + +cDisplayMenuItemTrackView::~cDisplayMenuItemTrackView() { +} + +void cDisplayMenuItemTrackView::SetTokens(void) { + if (!itemInit) return; + itemInit = false; + if (!title) return; + + stringTokens.insert(pair("title", title)); +} + + +void cDisplayMenuItemTrackView::Prepare(void) { + ArrangeContainer(); +} + +void cDisplayMenuItemTrackView::Render(void) { + + DrawListItem(&stringTokens, &intTokens); + + dirty = false; +} + +void cDisplayMenuItemTrackView::Debug(void) { + esyslog("skindesigner: Tracks Menu Item ---------------"); + cDisplayMenuItemView::Debug(); + esyslog("skindesigner: Title: %s", title); +} + diff --git a/views/displaymenuitemview.h b/views/displaymenuitemview.h new file mode 100644 index 0000000..724fed5 --- /dev/null +++ b/views/displaymenuitemview.h @@ -0,0 +1,141 @@ +#ifndef __DISPLAYMENUITEMVIEW_H +#define __DISPLAYMENUITEMVIEW_H + +#include "../libtemplate/template.h" +#include "view.h" +#include "displaymenuitemcurrentview.h" + +class cDisplayMenuItemView : public cViewListItem { +private: +protected: + bool itemInit; + bool dirty; + bool current; + bool selectable; + int num; + cTemplateViewList *tmplList; + map < string, string > stringTokens; + map < string, int > intTokens; + cDisplayMenuItemCurrentView *currentView; + virtual void Action(void); +public: + cDisplayMenuItemView(cTemplateViewList *tmplList, bool current, bool selectable); + virtual ~cDisplayMenuItemView(); + void SetCurrent(bool cur); + void SetNumber(int n) { num = n; }; + void ArrangeContainer(void); + bool Current(void) { return current; }; + void PrepareScrolling(void); + void EndScrolling(void); + virtual void SetTokens(void) {}; + virtual void Prepare(void) {}; + virtual void Render(void) {}; + virtual void Clear(void); + bool Dirty(void) { return dirty; }; + void Stop(void); + virtual void Debug(void); +}; + +class cDisplayMenuItemDefaultView: public cDisplayMenuItemView { +private: + int *tabs; + int *tabWidths; + string *tabTexts; + int maxTabs; +public: + cDisplayMenuItemDefaultView(cTemplateViewList *tmplList, string *tabTexts, int *tabs, int *tabWidths, bool current, bool selectable); + virtual ~cDisplayMenuItemDefaultView(); + void SetTabTexts(string *tabTexts); + void SetTokens(void); + void Prepare(void); + void Render(void); + void Debug(void); +}; + +class cDisplayMenuItemMainView: public cDisplayMenuItemView { +private: + string text; + string number; + string label; + string icon; + void SplitMenuText(void); +public: + cDisplayMenuItemMainView(cTemplateViewList *tmplList, string itemText, bool current, bool selectable); + virtual ~cDisplayMenuItemMainView(); + void SetTokens(void); + void Prepare(void); + void Render(void); + void Debug(void); +}; + +class cDisplayMenuItemSchedulesView: public cDisplayMenuItemView { +private: + const cEvent *event; + const cChannel *channel; + eTimerMatch timerMatch; + eMenuCategory cat; + string ParseSeparator(string sep); +public: + cDisplayMenuItemSchedulesView(cTemplateViewList *tmplList, const cEvent *event, const cChannel *channel, eTimerMatch timerMatch, + eMenuCategory cat, bool current, bool selectable); + virtual ~cDisplayMenuItemSchedulesView(); + void SetTokens(void); + void Prepare(void); + void Render(void); + void Debug(void); +}; + +class cDisplayMenuItemChannelsView: public cDisplayMenuItemView { +private: + const cChannel *channel; + bool withProvider; +public: + cDisplayMenuItemChannelsView(cTemplateViewList *tmplList, const cChannel *channel, bool withProvider, bool current, bool selectable); + virtual ~cDisplayMenuItemChannelsView(); + void SetTokens(void); + void Prepare(void); + void Render(void); + void Debug(void); +}; + +class cDisplayMenuItemTimersView: public cDisplayMenuItemView { +private: + const cTimer *timer; +public: + cDisplayMenuItemTimersView(cTemplateViewList *tmplList, const cTimer *timer, bool current, bool selectable); + virtual ~cDisplayMenuItemTimersView(); + void SetTokens(void); + void Prepare(void); + void Render(void); + void Debug(void); +}; + +class cDisplayMenuItemRecordingView: public cDisplayMenuItemView { +private: + const cRecording *recording; + int level; + int total; + int newRecs; +public: + cDisplayMenuItemRecordingView(cTemplateViewList *tmplList, const cRecording *recording, int level, int total, int newRecs, bool current, bool selectable); + virtual ~cDisplayMenuItemRecordingView(); + void SetTokens(void); + void Prepare(void); + void Render(void); + void Debug(void); +}; + +class cDisplayMenuItemTrackView: public cDisplayMenuItemView { +private: + const char *title; + int numTracks; +public: + cDisplayMenuItemTrackView(cTemplateViewList *tmplList, const char *title, bool current, bool selectable, int numTracks); + virtual ~cDisplayMenuItemTrackView(); + void SetTokens(void); + void Prepare(void); + void Render(void); + void Debug(void); +}; + +#endif //__DISPLAYMENUITEMVIEW_H diff --git a/views/displaymenulistview.c b/views/displaymenulistview.c new file mode 100644 index 0000000..eb8581e --- /dev/null +++ b/views/displaymenulistview.c @@ -0,0 +1,216 @@ +#include +#include "displaymenulistview.h" + + +cDisplayMenuListView::cDisplayMenuListView(cTemplateViewList *tmplList, int count) { + oneColumn = true; + this->tmplList = tmplList; + if (count < 0) { + //if count is not set, the fixed number of items is configured in the template + itemCount = tmplList->GetNumericParameter(ptNumElements); + } else { + //else use the actual numbers of elements + itemCount = count; + map < string, int > intTokens; + intTokens.insert(pair("numelements", count)); + tmplList->CalculateListParameters(&intTokens); + } + menuItems = new cDisplayMenuItemView*[itemCount]; + for (int i=0; iGetMenuItemWidth(); + averageFontWidth = tmplList->GetAverageFontWidth(); + } + + if (!tab1) { + tabs[0] = 0; + tabWidths[0] = menuItemWidth; + } else { + tabs[0] = 0; + if (!tab2) { + tabs[1] = menuItemWidth/2; + tabWidths[0] = tabs[1]; + tabWidths[1] = tabs[1]; + } else { + tabs[0] = 0; + tabs[1] = tab1 ? tabs[0] + tab1 : 0; + tabs[2] = tab2 ? tabs[1] + tab2 : 0; + tabs[3] = tab3 ? tabs[2] + tab3 : 0; + tabs[4] = tab4 ? tabs[3] + tab4 : 0; + tabs[5] = tab5 ? tabs[4] + tab5 : 0; + for (int i = 1; i < cSkinDisplayMenu::MaxTabs; i++) + tabs[i] *= averageFontWidth; + + for (int i = 0; i < cSkinDisplayMenu::MaxTabs; i++) { + if (i == cSkinDisplayMenu::MaxTabs - 1) { + tabWidths[i] = menuItemWidth - tabs[i]; + } else { + tabWidths[i] = tabs[i+1] - tabs[i]; + } + } + } + } +} + +int cDisplayMenuListView::GetListWidth(void) { + if (tmplList) { + return tmplList->GetMenuItemWidth(); + } + return 1920; +} + + +void cDisplayMenuListView::Clear(void) { + for (int i=0; i(menuItems[index]); + if (!menuItem) + return; + menuItem->SetCurrent(current); + menuItem->SetTabTexts(tabTexts); + return; + } + for (int i=1; i 0) { + oneColumn = false; + break; + } + } + cDisplayMenuItemView *item = new cDisplayMenuItemDefaultView(tmplList, tabTexts, tabs, tabWidths, current, selectable); + menuItems[index] = item; +} + +void cDisplayMenuListView::AddMainMenuItem(int index, const char *itemText, bool current, bool selectable) { + if (menuItems[index]) { + menuItems[index]->SetCurrent(current); + return; + } + cDisplayMenuItemView *item = new cDisplayMenuItemMainView(tmplList, itemText, current, selectable); + menuItems[index] = item; +} + +void cDisplayMenuListView::AddSetupMenuItem(int index, const char *itemText, bool current, bool selectable) { + if (menuItems[index]) { + menuItems[index]->SetCurrent(current); + return; + } + cDisplayMenuItemView *item = new cDisplayMenuItemMainView(tmplList, itemText, current, selectable); + menuItems[index] = item; +} + +void cDisplayMenuListView::AddSchedulesMenuItem(int index, const cEvent *event, const cChannel *channel, eTimerMatch timerMatch, + eMenuCategory cat, bool current, bool selectable) { + if (menuItems[index]) { + menuItems[index]->SetCurrent(current); + return; + } + cDisplayMenuItemView *item = new cDisplayMenuItemSchedulesView(tmplList, event, channel, timerMatch, cat, current, selectable); + menuItems[index] = item; +} + +void cDisplayMenuListView::AddChannelsMenuItem(int index, const cChannel *channel, bool withProvider, bool current, bool selectable) { + if (menuItems[index]) { + menuItems[index]->SetCurrent(current); + return; + } + cDisplayMenuItemView *item = new cDisplayMenuItemChannelsView(tmplList, channel, withProvider, current, selectable); + menuItems[index] = item; +} + +void cDisplayMenuListView::AddTimersMenuItem(int index, const cTimer *timer, bool current, bool selectable) { + if (menuItems[index]) { + menuItems[index]->SetCurrent(current); + return; + } + cDisplayMenuItemView *item = new cDisplayMenuItemTimersView(tmplList, timer, current, selectable); + menuItems[index] = item; +} + +void cDisplayMenuListView::AddRecordingMenuItem(int index, const cRecording *recording, int level, int total, int isNew, bool current, bool selectable) { + if (menuItems[index]) { + menuItems[index]->SetCurrent(current); + return; + } + cDisplayMenuItemView *item = new cDisplayMenuItemRecordingView(tmplList, recording, level, total, isNew, current, selectable); + menuItems[index] = item; +} + +void cDisplayMenuListView::AddTracksMenuItem(int index, const char *title, bool current, bool selectable) { + if (menuItems[index]) { + menuItems[index]->SetCurrent(current); + return; + } + cDisplayMenuItemView *item = new cDisplayMenuItemTrackView(tmplList, title, current, selectable, itemCount); + menuItems[index] = item; +} + +void cDisplayMenuListView::Render(void) { + if (tabs[1] && oneColumn) { + tabs[0] = 0; + tabWidths[0] = tmplList->GetMenuItemWidth(); + for (int i=1; iDirty()) { + menuItems[i]->Clear(); + menuItems[i]->SetNumber(i); + menuItems[i]->Prepare(); + menuItems[i]->SetTokens(); + menuItems[i]->Render(); + if (menuItems[i]->Current()) { + current = i; + } else { + menuItems[i]->Stop(); + } + } + } + if (current > -1) { + menuItems[current]->Start(); + } +} + +void cDisplayMenuListView::Debug(void) { + for (int i=0; iDebug(); + } + } +} diff --git a/views/displaymenulistview.h b/views/displaymenulistview.h new file mode 100644 index 0000000..1c2c85f --- /dev/null +++ b/views/displaymenulistview.h @@ -0,0 +1,35 @@ +#ifndef __DISPLAYMENULISTVIEW_H +#define __DISPLAYMENULISTVIEW_H + +#include "../libtemplate/template.h" +#include "view.h" +#include "displaymenuitemview.h" + +class cDisplayMenuListView { +private: + cTemplateViewList *tmplList; + int itemCount; + cDisplayMenuItemView **menuItems; + int *tabs; + int *tabWidths; + bool oneColumn; +public: + cDisplayMenuListView(cTemplateViewList *tmplList, int count = -1); + virtual ~cDisplayMenuListView(); + void Clear(void); + void SetTabs(int tab1, int tab2, int tab3, int tab4, int tab5); + int GetMaxItems(void) { return itemCount; }; + int GetListWidth(void); + void AddDefaultMenuItem(int index, string *tabTexts, bool current, bool selectable); + void AddMainMenuItem(int index, const char *itemText, bool current, bool selectable); + void AddSetupMenuItem(int index, const char *itemText, bool current, bool selectable); + void AddSchedulesMenuItem(int index, const cEvent *event, const cChannel *channel, eTimerMatch timerMatch, eMenuCategory cat, bool current, bool selectable); + void AddChannelsMenuItem(int index, const cChannel *channel, bool withProvider, bool current, bool selectable); + void AddTimersMenuItem(int index, const cTimer *timer, bool current, bool selectable); + void AddRecordingMenuItem(int index, const cRecording *recording, int level, int total, int isNew, bool current, bool selectable); + void AddTracksMenuItem(int index, const char *title, bool current, bool selectable); + void Render(void); + void Debug(void); +}; + +#endif //__DISPLAYMENULISTVIEW_H diff --git a/views/displaymenurootview.c b/views/displaymenurootview.c new file mode 100644 index 0000000..9ee1bcf --- /dev/null +++ b/views/displaymenurootview.c @@ -0,0 +1,495 @@ +#define __STL_CONFIG_H +#include +#include "displaymenurootview.h" +#include "../config.h" +#include "../libcore/helpers.h" + +cDisplayMenuRootView::cDisplayMenuRootView(cTemplateView *rootView) : cView(rootView) { + viewType = svUndefined; + subView = NULL; + subViewAvailable = false; + view = NULL; + listView = NULL; + detailView = NULL; + defaultBackgroundDrawn = false; + defaultHeaderDrawn = false; + defaultButtonsDrawn = false; + defaultDateTimeDrawn = false; + defaultMessageDrawn = false; + DeleteOsdOnExit(); + SetFadeTime(tmplView->GetNumericParameter(ptFadeTime)); +} + +cDisplayMenuRootView::~cDisplayMenuRootView() { + if (view) + delete view; + if (listView) + delete listView; + if (detailView) + delete detailView; +} + +/******************************************************************* +* Public Functions +*******************************************************************/ + +bool cDisplayMenuRootView::createOsd(void) { + cRect osdSize = tmplView->GetOsdSize(); + bool ok = CreateOsd(cOsd::OsdLeft() + osdSize.X(), + cOsd::OsdTop() + osdSize.Y(), + osdSize.Width(), + osdSize.Height()); + return ok; +} + +/* Categories: +mcUndefined = -1, +mcUnknown = 0, +1 mcMain, +2 mcSchedule, +3 mcScheduleNow, +4 mcScheduleNext, +5 mcChannel, +6 mcChannelEdit, +7 mcTimer, +8 mcTimerEdit, +9 mcRecording, +10 mcRecordingInfo, +11 mcPlugin, +12 mcPluginSetup, +13 mcSetup, +14 mcSetupOsd, +15 mcSetupEpg, +16 mcSetupDvb, +17 mcSetupLnb, +18 mcSetupCam, +19 mcSetupRecord, +20 mcSetupReplay, +21 mcSetupMisc, +22 mcSetupPlugins, +23 mcCommand, +24 mcEvent, +25 mcText, +26 mcFolder, +27 mcCam +*/ + +void cDisplayMenuRootView::SetMenu(eMenuCategory menuCat, bool menuInit) { + eSubView newViewType = svUndefined; + bool isListView = true; + switch (menuCat) { + case mcMain: + newViewType = svMenuMain; + break; + case mcSetup: + newViewType = svMenuSetup; + break; + case mcSchedule: + case mcScheduleNow: + case mcScheduleNext: + newViewType = svMenuSchedules; + if (view) + view->SetMenuCat(menuCat); + break; + case mcChannel: + newViewType = svMenuChannels; + break; + case mcTimer: + newViewType = svMenuTimers; + break; + case mcRecording: + newViewType = svMenuRecordings; + break; + case mcEvent: + newViewType = svMenuDetailedEpg; + isListView = false; + break; + case mcRecordingInfo: + newViewType = svMenuDetailedRecording; + isListView = false; + break; + case mcText: + newViewType = svMenuDetailedText; + isListView = false; + break; + default: + newViewType = svMenuDefault; + break; + } + if (newViewType != viewType) { + subView = tmplView->GetSubView(newViewType); + if (!subView) { + subViewAvailable = false; + subView = tmplView->GetSubView(svMenuDefault); + } else { + subViewAvailable = true; + } + //Cleanup + if (view) { + delete view; + view = NULL; + } + if (listView) { + delete listView; + listView = NULL; + } + if (detailView) { + delete detailView; + detailView = NULL; + } + + //Create new View + switch (newViewType) { + case svMenuMain: + view = new cDisplayMenuMainView(subView, menuInit); + break; + case svMenuSchedules: + if (subViewAvailable) + view = new cDisplayMenuSchedulesView(subView, menuCat, menuInit); + else + view = new cDisplayMenuView(subView, menuInit); + break; + default: + view = new cDisplayMenuView(subView, menuInit); + } + + //Cleanup root view + ClearRootView(); + + if (isListView) { + //Create menu item list + cTemplateViewList *tmplMenuItems = subView->GetViewList(vlMenuItem); + if (!tmplMenuItems) + return; + listView = new cDisplayMenuListView(tmplMenuItems); + } else { + //Create detailed view + detailView = new cDisplayMenuDetailView(subView); + } + viewType = newViewType; + } +} + +void cDisplayMenuRootView::SetTitle(const char *title) { + menuTitle = title; + if (view) + view->SetTitle(title); +} + +void cDisplayMenuRootView::SetButtonTexts(const char *Red, const char *Green, const char *Yellow, const char *Blue) { + if (Red) + buttonTexts[0] = Red; + else + buttonTexts[0] = ""; + if (Green) + buttonTexts[1] = Green; + else + buttonTexts[1] = ""; + if (Yellow) + buttonTexts[2] = Yellow; + else + buttonTexts[2] = ""; + if (Blue) + buttonTexts[3] = Blue; + else + buttonTexts[3] = ""; + if (view) + view->SetButtonTexts(buttonTexts); +} + +void cDisplayMenuRootView::SetTabs(int tab1, int tab2, int tab3, int tab4, int tab5) { + if (listView) { + listView->SetTabs(tab1, tab2, tab3, tab4, tab5); + } +} + +void cDisplayMenuRootView::SetMessage(eMessageType type, const char *text) { + if (!view) + return; + if (!view->DrawMessage(type, text)) { + defaultMessageDrawn = true; + DrawMessage(type, text); + } else { + defaultMessageDrawn = false; + } +} + +void cDisplayMenuRootView::SetDetailedViewEvent(const cEvent *event) { + if (!detailView) + detailView = new cDisplayMenuDetailView(subView); + detailView->SetEvent(event); +} + +void cDisplayMenuRootView::SetDetailedViewRecording(const cRecording *recording) { + if (!detailView) + detailView = new cDisplayMenuDetailView(subView); + detailView->SetRecording(recording); +} + +void cDisplayMenuRootView::SetDetailedViewText(const char *text) { + if (!detailView) + detailView = new cDisplayMenuDetailView(subView); + detailView->SetText(text); +} + +void cDisplayMenuRootView::KeyInput(bool up, bool page) { + if (!detailView) + return; + + if (up && page) { + detailView->KeyLeft(); + } else if (!up && page) { + detailView->KeyRight(); + } else if (up && !page) { + detailView->KeyUp(); + } else if (!up && !page) { + detailView->KeyDown(); + } +} + +void cDisplayMenuRootView::Clear(void) { + if (listView) { + listView->Clear(); + } + if (detailView) { + delete detailView; + detailView = NULL; + } +} + +void cDisplayMenuRootView::ClearRootView(void) { + if (defaultBackgroundDrawn && view->BackgroundImplemented()) + ClearViewElement(veBackground); + if (defaultHeaderDrawn) + ClearViewElement(veHeader); + if (defaultButtonsDrawn) + ClearViewElement(veButtons); + if (defaultDateTimeDrawn) + ClearViewElement(veDateTime); + if (defaultMessageDrawn) + ClearViewElement(veMessage); +} + +int cDisplayMenuRootView::GetMaxItems(void) { + if (listView) { + return listView->GetMaxItems(); + } + return 0; +} + +int cDisplayMenuRootView::GetListViewWidth(void) { + if (listView) { + return listView->GetListWidth(); + } + return 0; +} + +int cDisplayMenuRootView::GetTextAreaWidth(void) { + if (!tmplView) + return 1900; + cTemplateView *tempSubView = tmplView->GetSubView(svMenuDefault); + if (!tempSubView) + return 1900; + int areaWidth = tempSubView->GetNumericParameter(ptWidth); + if (areaWidth > 0) + return areaWidth; + return 1900; +} + + +void cDisplayMenuRootView::Render(void) { + + if (!view->DrawBackground()) { + if (!defaultBackgroundDrawn) { + defaultBackgroundDrawn = true; + DrawBackground(); + } + } else { + defaultBackgroundDrawn = false; + } + + if (!view->DrawHeader()) { + defaultHeaderDrawn = true; + DrawHeader(); + } else { + defaultHeaderDrawn = false; + } + + if (!view->DrawColorButtons()) { + defaultButtonsDrawn = true; + DrawColorButtons(); + } else { + defaultButtonsDrawn = false; + } + + if (!view->DrawDateTime()) { + defaultDateTimeDrawn = true; + DrawDateTime(); + } else { + defaultDateTimeDrawn = false; + } + + view->DrawStaticViewElements(); + view->DrawDynamicViewElements(); +} + +void cDisplayMenuRootView::RenderMenuItems(void) { + if (listView) + listView->Render(); +} + +void cDisplayMenuRootView::RenderDetailView(void) { + if (detailView) + detailView->Render(); +} + +void cDisplayMenuRootView::RenderMenuScrollBar(int Total, int Offset) { + if (!listView) + return; + view->DrawScrollbar(listView->GetMaxItems(), Total, Offset); +} + +bool cDisplayMenuRootView::RenderDynamicElements(void) { + return view->DrawDynamicViewElements(); +} + +/******************************************************************* +* Private Functions +*******************************************************************/ + +void cDisplayMenuRootView::DrawBackground(void) { + DrawViewElement(veBackground); +} +void cDisplayMenuRootView::DrawHeader(void) { + if (!ViewElementImplemented(veHeader)) { + return; + } + + map < string, string > stringTokens; + map < string, int > intTokens; + + stringTokens.insert(pair("title", menuTitle)); + stringTokens.insert(pair("vdrversion", VDRVERSION)); + + //check for standard menu entries + bool hasIcon = false; + string icon = imgCache->GetIconName(menuTitle); + if (icon.size() > 0) + hasIcon = true; + + stringTokens.insert(pair("icon", icon)); + intTokens.insert(pair("hasicon", hasIcon)); + + ClearViewElement(veHeader); + DrawViewElement(veHeader, &stringTokens, &intTokens); +} + +void cDisplayMenuRootView::DrawDateTime(void) { + if (!ViewElementImplemented(veDateTime)) { + return; + } + + map < string, string > stringTokens; + map < string, int > intTokens; + + time_t t = time(0); // get time now + struct tm * now = localtime(&t); + + intTokens.insert(pair("year", now->tm_year + 1900)); + intTokens.insert(pair("day", now->tm_mday)); + + char monthname[20]; + char monthshort[10]; + strftime(monthshort, sizeof(monthshort), "%b", now); + strftime(monthname, sizeof(monthname), "%B", now); + + stringTokens.insert(pair("monthname", monthname)); + stringTokens.insert(pair("monthnameshort", monthshort)); + stringTokens.insert(pair("month", *cString::sprintf("%02d", now->tm_mon + 1))); + stringTokens.insert(pair("dayleadingzero", *cString::sprintf("%02d", now->tm_mday))); + stringTokens.insert(pair("dayname", *WeekDayNameFull(now->tm_wday))); + stringTokens.insert(pair("daynameshort", *WeekDayName(now->tm_wday))); + stringTokens.insert(pair("time", *TimeString(t))); + + ClearViewElement(veDateTime); + DrawViewElement(veDateTime, &stringTokens, &intTokens); + +} + + +void cDisplayMenuRootView::DrawColorButtons(void) { + if (!ViewElementImplemented(veButtons)) { + return; + } + + map < string, string > stringTokens; + map < string, int > intTokens; + + stringTokens.insert(pair("red", buttonTexts[0])); + stringTokens.insert(pair("green", buttonTexts[1])); + stringTokens.insert(pair("yellow", buttonTexts[2])); + stringTokens.insert(pair("blue", buttonTexts[3])); + + int colorKeys[4] = { Setup.ColorKey0, Setup.ColorKey1, Setup.ColorKey2, Setup.ColorKey3 }; + + for (int button = 1; button < 5; button++) { + string red = *cString::sprintf("red%d", button); + string green = *cString::sprintf("green%d", button); + string yellow = *cString::sprintf("yellow%d", button); + string blue = *cString::sprintf("blue%d", button); + bool isRed = false; + bool isGreen = false; + bool isYellow = false; + bool isBlue = false; + switch (colorKeys[button-1]) { + case 0: + isRed = true; + break; + case 1: + isGreen = true; + break; + case 2: + isYellow = true; + break; + case 3: + isBlue = true; + break; + default: + break; + } + intTokens.insert(pair(red, isRed)); + intTokens.insert(pair(green, isGreen)); + intTokens.insert(pair(yellow, isYellow)); + intTokens.insert(pair(blue, isBlue)); + } + + ClearViewElement(veButtons); + DrawViewElement(veButtons, &stringTokens, &intTokens); +} + +void cDisplayMenuRootView::DrawMessage(eMessageType type, const char *text) { + if (!text) { + ClearViewElement(veMessage); + return; + } + + map < string, string > stringTokens; + map < string, int > intTokens; + + intTokens.insert(pair("status", (type == mtStatus) ? true : false)); + intTokens.insert(pair("info", (type == mtInfo) ? true : false)); + intTokens.insert(pair("warning", (type == mtWarning) ? true : false)); + intTokens.insert(pair("error", (type == mtError) ? true : false)); + stringTokens.insert(pair("text", text)); + + ClearViewElement(veMessage); + DrawViewElement(veMessage, &stringTokens, &intTokens); +} + +void cDisplayMenuRootView::Action(void) { + SetInitFinished(); + Render(); + view->Start(); + FadeIn(); + DoFlush(); +} diff --git a/views/displaymenurootview.h b/views/displaymenurootview.h new file mode 100644 index 0000000..b3f4c62 --- /dev/null +++ b/views/displaymenurootview.h @@ -0,0 +1,57 @@ +#ifndef __DISPLAYMENUROOTVIEW_H +#define __DISPLAYMENUROOTVIEW_H + +#include "../libtemplate/template.h" +#include "displaymenuview.h" +#include "displaymenulistview.h" +#include "displaymenudetailview.h" + +class cDisplayMenuRootView : public cView { +private: + eSubView viewType; + cTemplateView *subView; + bool subViewAvailable; + cDisplayMenuView *view; + cDisplayMenuListView *listView; + cDisplayMenuDetailView *detailView; + string menuTitle; + string buttonTexts[4]; + bool defaultBackgroundDrawn; + bool defaultHeaderDrawn; + bool defaultButtonsDrawn; + bool defaultDateTimeDrawn; + bool defaultMessageDrawn; + void DrawBackground(void); + void DrawHeader(void); + void DrawDateTime(void); + void DrawColorButtons(void); + void DrawMessage(eMessageType type, const char *text); + void ClearRootView(void); + virtual void Action(void); +public: + cDisplayMenuRootView(cTemplateView *rootView); + virtual ~cDisplayMenuRootView(); + bool createOsd(void); + void SetMenu(eMenuCategory menuCat, bool menuInit); + void SetTitle(const char *title); + void SetChannel(const cChannel *channel) { view->SetChannel(channel); }; + void SetButtonTexts(const char *Red, const char *Green, const char *Yellow, const char *Blue); + void SetTabs(int tab1, int tab2, int tab3, int tab4, int tab5); + void SetMessage(eMessageType type, const char *text); + void SetDetailedViewEvent(const cEvent *event); + void SetDetailedViewRecording(const cRecording *recording); + void SetDetailedViewText(const char *text); + void KeyInput(bool up, bool page); + void Clear(void); + int GetMaxItems(void); + int GetListViewWidth(void); + int GetTextAreaWidth(void); + bool SubViewAvailable(void) { return subViewAvailable; }; + cDisplayMenuListView *GetListView(void) { return listView; }; + void Render(void); + void RenderMenuItems(void); + void RenderDetailView(void); + void RenderMenuScrollBar(int Total, int Offset); + bool RenderDynamicElements(void); +}; +#endif //__DISPLAYMENUROOTVIEW_H diff --git a/views/displaymenutabview.c b/views/displaymenutabview.c new file mode 100644 index 0000000..f9e03f9 --- /dev/null +++ b/views/displaymenutabview.c @@ -0,0 +1,126 @@ +#include "displaymenutabview.h" + + +cDisplayMenuTabView::cDisplayMenuTabView(cTemplateViewTab *tmplTab) : cView(tmplTab) { +} + +cDisplayMenuTabView::~cDisplayMenuTabView() { + CancelSave(); +} + +void cDisplayMenuTabView::SetTokens(map < string, int > *intTokens, map < string, string > *stringTokens, map < string, vector< map< string, string > > > *loopTokens) { + this->intTokens = intTokens; + this->stringTokens = stringTokens; + this->loopTokens = loopTokens; +} + +void cDisplayMenuTabView::Clear(void) { + Fill(0, clrTransparent); +} + +void cDisplayMenuTabView::CreateTab(void) { + //Create Pixmap + if (!PixmapExists(0)) { + cSize drawportSize; + scrolling = tmplTab->CalculateDrawPortSize(drawportSize, loopTokens); + if (scrolling) { + CreateScrollingPixmap(0, tmplTab, drawportSize); + scrollingPix = 0; + scrollOrientation = orVertical; + scrollMode = smNone; + } else { + CreateViewPixmap(0, tmplTab); + } + } +} + + +void cDisplayMenuTabView::Render(void) { + if (tmplTab->DoDebug()) { + tmplTab->Debug(); + } + //Draw Tab, flushing every loop + DrawPixmap(0, tmplTab, loopTokens, true); +} + +bool cDisplayMenuTabView::KeyUp(void) { + if (!scrolling) + return false; + int scrollStep = tmplTab->GetScrollStep(); + int aktHeight = DrawportY(0); + if (aktHeight >= 0) { + return false; + } + int newY = aktHeight + scrollStep; + if (newY > 0) + newY = 0; + SetDrawPortPoint(0, cPoint(0, newY)); + return true; +} + +bool cDisplayMenuTabView::KeyDown(void) { + if (!scrolling) + return false; + + int scrollStep = tmplTab->GetScrollStep(); + int aktHeight = DrawportY(0); + int totalHeight = DrawportHeight(0); + int screenHeight = Height(0); + + if (totalHeight - ((-1)*aktHeight) == screenHeight) { + return false; + } + int newY = aktHeight - scrollStep; + if ((-1)*newY > totalHeight - screenHeight) + newY = (-1)*(totalHeight - screenHeight); + SetDrawPortPoint(0, cPoint(0, newY)); + return true; +} + +bool cDisplayMenuTabView::KeyLeft(void) { + if (!scrolling) + return false; + if (!PixmapExists(0)) + return false; + int aktHeight = DrawportY(0); + int screenHeight = Height(0); + int newY = aktHeight + screenHeight; + if (newY > 0) + newY = 0; + SetDrawPortPoint(0, cPoint(0, newY)); + return true; +} + +bool cDisplayMenuTabView::KeyRight(void) { + if (!scrolling) + return false; + if (!PixmapExists(0)) + return false; + int aktHeight = DrawportY(0); + int screenHeight = Height(0); + int totalHeight = DrawportHeight(0); + int newY = aktHeight - screenHeight; + if ((-1)*newY > totalHeight - screenHeight) + newY = (-1)*(totalHeight - screenHeight); + SetDrawPortPoint(0, cPoint(0, newY)); + return true; +} + +void cDisplayMenuTabView::GetScrollbarPosition(int &barTop, int &barHeight) { + int y = (-1)*DrawportY(0); + int totalHeight = DrawportHeight(0); + int screenHeight = Height(0); + if (totalHeight == 0) + return; + if (totalHeight <= screenHeight) + barHeight = 1000; + else { + barHeight = (double)screenHeight / (double) totalHeight * 1000; + } + barTop = (double)y / (double) totalHeight * 1000; +} + +void cDisplayMenuTabView::Action(void) { + Render(); + DoFlush(); +} \ No newline at end of file diff --git a/views/displaymenutabview.h b/views/displaymenutabview.h new file mode 100644 index 0000000..70a7447 --- /dev/null +++ b/views/displaymenutabview.h @@ -0,0 +1,27 @@ +#ifndef __DISPLAYMENUTABVIEW_H +#define __DISPLAYMENUTABVIEW_H + +#include "../libtemplate/template.h" +#include "view.h" + +class cDisplayMenuTabView : public cView { +private: + map < string, string > *stringTokens; + map < string, int > *intTokens; + map < string, vector< map< string, string > > > *loopTokens; + void Action(void); +public: + cDisplayMenuTabView(cTemplateViewTab *tmplTab); + virtual ~cDisplayMenuTabView(); + void SetTokens(map < string, int > *intTokens, map < string, string > *stringTokens, map < string, vector< map< string, string > > > *loopTokens); + void Clear(void); + void CreateTab(void); + void Render(void); + bool KeyUp(void); + bool KeyDown(void); + bool KeyLeft(void); + bool KeyRight(void); + void GetScrollbarPosition(int &barTop, int &barHeight); +}; + +#endif //__DISPLAYMENUTABVIEW_H diff --git a/views/displaymenuview.c b/views/displaymenuview.c new file mode 100644 index 0000000..3b8c657 --- /dev/null +++ b/views/displaymenuview.c @@ -0,0 +1,539 @@ +#define __STL_CONFIG_H +#include +#include +#include "displaymenuview.h" +#include "../config.h" +#include "../libcore/helpers.h" +#include "../libcore/timers.h" + +cDisplayMenuView::cDisplayMenuView(cTemplateView *tmplView, bool menuInit) : cView(tmplView) { + if (menuInit) + SetFadeTime(tmplView->GetNumericParameter(ptFadeTime)); + else + SetFadeTime(0); + cat = mcUndefined; +} + +cDisplayMenuView::~cDisplayMenuView() { + CancelSave(); + FadeOut(); +} + +bool cDisplayMenuView::DrawBackground(void) { + if (!ViewElementImplemented(veBackground)) { + return false; + } + DrawViewElement(veBackground); + return true; +} + +bool cDisplayMenuView::DrawHeader(void) { + if (!ViewElementImplemented(veHeader)) { + return false; + } + + map < string, string > stringTokens; + map < string, int > intTokens; + + stringTokens.insert(pair("title", menuTitle)); + stringTokens.insert(pair("vdrversion", VDRVERSION)); + + //check for standard menu entries + bool hasIcon = false; + string icon = imgCache->GetIconName(menuTitle); + if (icon.size() > 0) + hasIcon = true; + stringTokens.insert(pair("icon", icon)); + intTokens.insert(pair("hasicon", hasIcon)); + + ClearViewElement(veHeader); + DrawViewElement(veHeader, &stringTokens, &intTokens); + return true; +} + +bool cDisplayMenuView::DrawDateTime(void) { + if (!ViewElementImplemented(veDateTime)) { + return false; + } + + cString curDate = DayDateTime(); + + map < string, string > stringTokens; + map < string, int > intTokens; + + time_t t = time(0); // get time now + struct tm * now = localtime(&t); + + intTokens.insert(pair("year", now->tm_year + 1900)); + intTokens.insert(pair("day", now->tm_mday)); + + char monthname[20]; + char monthshort[10]; + strftime(monthshort, sizeof(monthshort), "%b", now); + strftime(monthname, sizeof(monthname), "%B", now); + + stringTokens.insert(pair("monthname", monthname)); + stringTokens.insert(pair("monthnameshort", monthshort)); + stringTokens.insert(pair("month", *cString::sprintf("%02d", now->tm_mon + 1))); + stringTokens.insert(pair("dayleadingzero", *cString::sprintf("%02d", now->tm_mday))); + stringTokens.insert(pair("dayname", *WeekDayNameFull(now->tm_wday))); + stringTokens.insert(pair("daynameshort", *WeekDayName(now->tm_wday))); + stringTokens.insert(pair("time", *TimeString(t))); + + ClearViewElement(veDateTime); + DrawViewElement(veDateTime, &stringTokens, &intTokens); + return true; +} + +bool cDisplayMenuView::DrawColorButtons(void) { + if (!ViewElementImplemented(veButtons)) { + return false; + } + map < string, string > stringTokens; + map < string, int > intTokens; + + stringTokens.insert(pair("red", buttonTexts[0])); + stringTokens.insert(pair("green", buttonTexts[1])); + stringTokens.insert(pair("yellow", buttonTexts[2])); + stringTokens.insert(pair("blue", buttonTexts[3])); + + int colorKeys[4] = { Setup.ColorKey0, Setup.ColorKey1, Setup.ColorKey2, Setup.ColorKey3 }; + + for (int button = 1; button < 5; button++) { + string red = *cString::sprintf("red%d", button); + string green = *cString::sprintf("green%d", button); + string yellow = *cString::sprintf("yellow%d", button); + string blue = *cString::sprintf("blue%d", button); + bool isRed = false; + bool isGreen = false; + bool isYellow = false; + bool isBlue = false; + switch (colorKeys[button-1]) { + case 0: + isRed = true; + break; + case 1: + isGreen = true; + break; + case 2: + isYellow = true; + break; + case 3: + isBlue = true; + break; + default: + break; + } + intTokens.insert(pair(red, isRed)); + intTokens.insert(pair(green, isGreen)); + intTokens.insert(pair(yellow, isYellow)); + intTokens.insert(pair(blue, isBlue)); + } + + ClearViewElement(veButtons); + DrawViewElement(veButtons, &stringTokens, &intTokens); + return true; +} + +bool cDisplayMenuView::DrawMessage(eMessageType type, const char *text) { + if (!ViewElementImplemented(veMessage)) { + return false; + } + if (!text) { + ClearViewElement(veMessage); + return true; + } + map < string, string > stringTokens; + map < string, int > intTokens; + + intTokens.insert(pair("status", (type == mtStatus) ? true : false)); + intTokens.insert(pair("info", (type == mtInfo) ? true : false)); + intTokens.insert(pair("warning", (type == mtWarning) ? true : false)); + intTokens.insert(pair("error", (type == mtError) ? true : false)); + stringTokens.insert(pair("text", text)); + + ClearViewElement(veMessage); + DrawViewElement(veMessage, &stringTokens, &intTokens); + return true; +} + +void cDisplayMenuView::DrawScrollbar(int numMax, int numDisplayed, int offset) { + if (!ViewElementImplemented(veScrollbar)) { + return; + } + map < string, string > stringTokens; + map < string, int > intTokens; + if (numDisplayed < 1) + return; + + int barHeight = 0; + if (numDisplayed < numMax) + barHeight = 1000; + else + barHeight = (double)numMax * 1000 / (double)numDisplayed; + + int barOffset = (double)offset * 1000 / (double)numDisplayed; + + intTokens.insert(pair("height", barHeight)); + intTokens.insert(pair("offset", barOffset)); + + ClearViewElement(veScrollbar); + DrawViewElement(veScrollbar, &stringTokens, &intTokens); +} + +bool cDisplayMenuView::BackgroundImplemented(void) { + if (!ViewElementImplemented(veBackground)) { + return false; + } + return true; +} + + +void cDisplayMenuView::Action(void) { + SetInitFinished(); + FadeIn(); + DoFlush(); +} + +/************************************************************************ +* cDisplayMenuMainView +************************************************************************/ + +cDisplayMenuMainView::cDisplayMenuMainView(cTemplateView *tmplView, bool menuInit) : cDisplayMenuView(tmplView, menuInit) { + initial = true; + lastSystemLoad = 0.0; + InitDevices(); +} + +cDisplayMenuMainView::~cDisplayMenuMainView() { + CancelSave(); + FadeOut(); + delete[] lastSignalStrength; + delete[] lastSignalQuality; + delete[] recDevices; +} + +void cDisplayMenuMainView::DrawStaticViewElements(void) { + DrawTimers(); + DrawDiscUsage(); +} + +bool cDisplayMenuMainView::DrawDynamicViewElements(void) { + bool loadChanged = DrawLoad(); + bool devicesChanged = DrawDevices(); + initial = false; + return loadChanged || devicesChanged; + +} + +void cDisplayMenuMainView::DrawTimers(void) { + if (!ViewElementImplemented(veTimers)) { + return; + } + + map < string, string > stringTokens; + map < string, int > intTokens; + + map < string, vector< map< string, string > > > timerLoopTokens; + vector< map< string, string > > timers; + + cGlobalSortedTimers SortedTimers;// local and remote timers + int numTimers = SortedTimers.Size(); + + intTokens.insert(pair("numtimers", numTimers)); + + int numTimerConflicts = SortedTimers.NumTimerConfilicts(); + intTokens.insert(pair("numtimerconflicts", numTimerConflicts)); + + for (int i=0; i<15; i++) { + stringstream name; + name << "timer" << i+1 << "exists"; + if (i < numTimers) { + intTokens.insert(pair(name.str(), true)); + } else { + intTokens.insert(pair(name.str(), false)); + } + } + + for (int i = 0; i < numTimers; i++) { + if (i >=15) + break; + map< string, string > timerVals; + const cTimer *Timer = SortedTimers[i]; + const cEvent *event = Timer->Event(); + if (event) { + timerVals.insert(pair< string, string >("timers[title]", event->Title())); + } else { + const char *File = Setup.FoldersInTimerMenu ? NULL : strrchr(Timer->File(), FOLDERDELIMCHAR); + if (File && strcmp(File + 1, TIMERMACRO_TITLE) && strcmp(File + 1, TIMERMACRO_EPISODE)) + File++; + else + File = Timer->File(); + timerVals.insert(pair< string, string >("timers[title]", File)); + } + const cChannel *channel = Timer->Channel(); + if (channel) { + timerVals.insert(pair< string, string >("timers[channelname]", channel->Name())); + stringstream chanNum; + chanNum << channel->Number(); + timerVals.insert(pair< string, string >("timers[channelnumber]", chanNum.str())); + string channelID = *(channel->GetChannelID().ToString()); + timerVals.insert(pair< string, string >("timers[channelid]", channelID)); + bool logoExists = imgCache->LogoExists(channelID); + timerVals.insert(pair< string, string >("timers[channellogoexists]", logoExists ? "1" : "0")); + } else { + timerVals.insert(pair< string, string >("timers[channelname]", "")); + timerVals.insert(pair< string, string >("timers[channelnumber]", "0")); + timerVals.insert(pair< string, string >("timers[channelid]", "")); + timerVals.insert(pair< string, string >("timers[channellogoexists]", "0")); + } + + timerVals.insert(pair< string, string >("timers[recording]", Timer->Recording() ? "1" : "0")); + + cString timerDate(""); + if (Timer->Recording()) { + timerDate = cString::sprintf("-%s", *TimeString(Timer->StopTime())); + } else { + time_t Now = time(NULL); + cString Today = WeekDayName(Now); + cString Time = TimeString(Timer->StartTime()); + cString Day = WeekDayName(Timer->StartTime()); + if (Timer->StartTime() > Now + 6 * SECSINDAY) { + time_t ttm = Timer->StartTime(); + struct tm * timerTime = localtime(&ttm); + timerDate = cString::sprintf("%02d.%02d %s", timerTime->tm_mday, timerTime->tm_mon + 1, *Time); + } else if (strcmp(Day, Today) != 0) + timerDate = cString::sprintf("%s %s", *Day, *Time); + else + timerDate = Time; + if (Timer->Flags() & tfVps) + timerDate = cString::sprintf("VPS %s", *timerDate); + } + timerVals.insert(pair< string, string >("timers[datetime]", *timerDate)); + + timers.push_back(timerVals); + } + + timerLoopTokens.insert(pair< string, vector< map< string, string > > >("timers", timers)); + + ClearViewElement(veTimers); + DrawViewElement(veTimers, &stringTokens, &intTokens, &timerLoopTokens); +} + +void cDisplayMenuMainView::DrawDiscUsage(void) { + if (!ViewElementImplemented(veDiscUsage)) { + return; + } + + map < string, string > stringTokens; + map < string, int > intTokens; + + string vdrUsageString = *cVideoDiskUsage::String(); + int discUsage = cVideoDiskUsage::UsedPercent(); + bool discAlert = (discUsage > 95) ? true : false; + string freeTime = *cString::sprintf("%02d:%02d", cVideoDiskUsage::FreeMinutes() / 60, cVideoDiskUsage::FreeMinutes() % 60); + int freeGB = cVideoDiskUsage::FreeMB() / 1024; + + intTokens.insert(pair("usedpercent", discUsage)); + intTokens.insert(pair("freepercent", 100-discUsage)); + intTokens.insert(pair("discalert", discAlert)); + intTokens.insert(pair("freegb", freeGB)); + stringTokens.insert(pair("freetime", freeTime)); + stringTokens.insert(pair("vdrusagestring", vdrUsageString)); + + ClearViewElement(veDiscUsage); + DrawViewElement(veDiscUsage, &stringTokens, &intTokens); +} + +void cDisplayMenuMainView::InitDevices(void) { + int numDevices = cDevice::NumDevices(); + lastSignalStrength = new int[numDevices]; + lastSignalQuality = new int[numDevices]; + recDevices = new bool[numDevices]; + for (int i=0; i stringTokens; + map < string, int > intTokens; + + double systemLoad; + if (getloadavg(&systemLoad, 1) > 0) { + if (lastSystemLoad == systemLoad) { + return false; + } + string load = *cString::sprintf("%.2f", systemLoad); + stringTokens.insert(pair("load", load)); + lastSystemLoad = systemLoad; + } + + ClearViewElement(veSystemLoad); + DrawViewElement(veSystemLoad, &stringTokens, &intTokens); + + return true; +} + +bool cDisplayMenuMainView::DrawDevices(void) { + if (!ViewElementImplemented(veDevices)) { + return false; + } + int numDevices = cDevice::NumDevices(); + if (!initial) { + //check if drawing is necessary + bool changed = false; + for (int i = 0; i < numDevices; i++) { + const cDevice *device = cDevice::GetDevice(i); + if (!device || !device->NumProvidedSystems()) { + continue; + } + if ((device->SignalStrength() != lastSignalStrength[i]) || (device->SignalQuality() != lastSignalQuality[i])) { + changed = true; + break; + } + } + if (!changed) { + return false; + } + } + + map < string, string > stringTokens; + map < string, int > intTokens; + + map < string, vector< map< string, string > > > deviceLoopTokens; + vector< map< string, string > > devices; + + //check device which currently displays live tv + int deviceLiveTV = -1; + cDevice *primaryDevice = cDevice::PrimaryDevice(); + if (primaryDevice) { + if (!primaryDevice->Replaying() || primaryDevice->Transferring()) + deviceLiveTV = cDevice::ActualDevice()->DeviceNumber(); + else + deviceLiveTV = primaryDevice->DeviceNumber(); + } + + //check currently recording devices + for (cTimer *timer = Timers.First(); timer; timer = Timers.Next(timer)) { + if (!timer->Recording()) { + continue; + } + if (cRecordControl *RecordControl = cRecordControls::GetRecordControl(timer)) { + const cDevice *recDevice = RecordControl->Device(); + if (recDevice) { + recDevices[recDevice->DeviceNumber()] = true; + } + } + } + int actualNumDevices = 0; + for (int i = 0; i < numDevices; i++) { + const cDevice *device = cDevice::GetDevice(i); + if (!device || !device->NumProvidedSystems()) { + continue; + } + actualNumDevices++; + map< string, string > deviceVals; + stringstream strNum; + strNum << actualNumDevices; + deviceVals.insert(pair< string, string >("devices[num]", strNum.str())); + deviceVals.insert(pair< string, string >("devices[type]", *(device->DeviceType()))); + cCamSlot *camSlot = device->CamSlot(); + int camNumber = -1; + if (camSlot) { + camNumber = camSlot->SlotNumber(); + deviceVals.insert(pair< string, string >("devices[hascam]", "1")); + } else { + deviceVals.insert(pair< string, string >("devices[hascam]", "0")); + } + int signalStrength = device->SignalStrength(); + int signalQuality = device->SignalQuality(); + stringstream strCamNumber; + strCamNumber << camNumber; + deviceVals.insert(pair< string, string >("devices[cam]", strCamNumber.str())); + stringstream strStrength; + strStrength << signalStrength; + deviceVals.insert(pair< string, string >("devices[signalstrength]", strStrength.str())); + stringstream strQuality; + strQuality << signalQuality; + deviceVals.insert(pair< string, string >("devices[signalquality]", strQuality.str())); + + deviceVals.insert(pair< string, string >("devices[livetv]", i == deviceLiveTV ? "1" : "0")); + deviceVals.insert(pair< string, string >("devices[recording]", recDevices[i] ? "1" : "0")); + + const cChannel *channel = device->GetCurrentlyTunedTransponder(); + const cSource *source = (channel) ? Sources.Get(channel->Source()) : NULL; + if (channel && channel->Number() > 0) { + stringstream strChanNum; + strChanNum << channel->Number(); + deviceVals.insert(pair< string, string >("devices[channelnumber]", strChanNum.str())); + deviceVals.insert(pair< string, string >("devices[channelname]", channel->Name())); + deviceVals.insert(pair< string, string >("devices[channelid]", *(channel->GetChannelID().ToString()))); + deviceVals.insert(pair< string, string >("devices[istuned]", "1")); + } else { + deviceVals.insert(pair< string, string >("devices[channelnumber]", "0")); + deviceVals.insert(pair< string, string >("devices[channelname]", "")); + deviceVals.insert(pair< string, string >("devices[channelid]", "")); + deviceVals.insert(pair< string, string >("devices[istuned]", "0")); + } + + deviceVals.insert(pair< string, string >("devices[source]", source ? source->Description() : "")); + + devices.push_back(deviceVals); + + lastSignalStrength[i] = signalStrength; + lastSignalQuality[i] = signalQuality; + } + deviceLoopTokens.insert(pair< string, vector< map< string, string > > >("devices", devices)); + + intTokens.insert(pair("numdevices", actualNumDevices)); + + ClearViewElement(veDevices); + DrawViewElement(veDevices, &stringTokens, &intTokens, &deviceLoopTokens); + return true; +} + +/************************************************************************ +* cDisplayMenuSchedulesView +************************************************************************/ + +cDisplayMenuSchedulesView::cDisplayMenuSchedulesView(cTemplateView *tmplView, eMenuCategory menuCat, bool menuInit) : cDisplayMenuView(tmplView, menuInit) { + cat = menuCat; + channel = NULL; +} + +cDisplayMenuSchedulesView::~cDisplayMenuSchedulesView() { + CancelSave(); + FadeOut(); +} + +bool cDisplayMenuSchedulesView::DrawHeader(void) { + if (!ViewElementImplemented(veHeader)) { + return false; + } + + map < string, string > stringTokens; + map < string, int > intTokens; + + intTokens.insert(pair("whatson", (cat == mcSchedule) ? true: false)); + intTokens.insert(pair("whatsonnow", (cat == mcScheduleNow) ? true: false)); + intTokens.insert(pair("whatsonnext", (cat == mcScheduleNext) ? true: false)); + + stringTokens.insert(pair("title", menuTitle)); + stringTokens.insert(pair("vdrversion", VDRVERSION)); + if (channel) { + stringTokens.insert(pair("channelnumber", *cString::sprintf("%d", channel->Number()))); + stringTokens.insert(pair("channelname", channel->Name())); + stringTokens.insert(pair("channelid", *(channel->GetChannelID().ToString()))); + + } + ClearViewElement(veHeader); + DrawViewElement(veHeader, &stringTokens, &intTokens); + return true; +} \ No newline at end of file diff --git a/views/displaymenuview.h b/views/displaymenuview.h new file mode 100644 index 0000000..52f5361 --- /dev/null +++ b/views/displaymenuview.h @@ -0,0 +1,60 @@ +#ifndef __DISPLAYMENUVIEW_H +#define __DISPLAYMENUVIEW_H + +#include "../libtemplate/template.h" +#include "displaymenulistview.h" + +class cDisplayMenuView : public cView { +protected: + eMenuCategory cat; + string menuTitle; + string *buttonTexts; + virtual void Action(void); +public: + cDisplayMenuView(cTemplateView *tmplView, bool menuInit); + virtual ~cDisplayMenuView(); + void SetMenuCat(eMenuCategory newCat) { cat = newCat; }; + void SetTitle(const char *title) {menuTitle = title; }; + virtual void SetChannel(const cChannel *channel) {}; + void SetButtonTexts(string *buttonTexts) { this->buttonTexts = buttonTexts; }; + bool DrawBackground(void); + virtual bool DrawHeader(void); + bool DrawDateTime(void); + bool DrawColorButtons(void); + bool DrawMessage(eMessageType type, const char *text); + void DrawScrollbar(int numMax, int numDisplayed, int offset); + virtual void DrawStaticViewElements(void) {}; + virtual bool DrawDynamicViewElements(void) { return false; }; + bool BackgroundImplemented(void); +}; + +class cDisplayMenuMainView : public cDisplayMenuView { +private: + bool initial; + int* lastSignalStrength; + int* lastSignalQuality; + double lastSystemLoad; + bool* recDevices; + void DrawTimers(void); + void DrawDiscUsage(void); + bool DrawLoad(void); + void InitDevices(void); + bool DrawDevices(void); +public: + cDisplayMenuMainView(cTemplateView *tmplView, bool menuInit); + virtual ~cDisplayMenuMainView(); + void DrawStaticViewElements(void); + bool DrawDynamicViewElements(void); +}; + +class cDisplayMenuSchedulesView : public cDisplayMenuView { +private: + const cChannel *channel; +public: + cDisplayMenuSchedulesView(cTemplateView *tmplView, eMenuCategory menuCat, bool menuInit); + virtual ~cDisplayMenuSchedulesView(); + void SetChannel(const cChannel *channel) { this->channel = channel; }; + bool DrawHeader(void); +}; + +#endif //__DISPLAYMENUVIEW_H diff --git a/views/displaymessageview.c b/views/displaymessageview.c new file mode 100644 index 0000000..f4cedc2 --- /dev/null +++ b/views/displaymessageview.c @@ -0,0 +1,49 @@ +#define __STL_CONFIG_H +#include +#include "displaymessageview.h" + +cDisplayMessageView::cDisplayMessageView(cTemplateView *tmplView) : cView(tmplView) { + DeleteOsdOnExit(); + SetFadeTime(tmplView->GetNumericParameter(ptFadeTime)); +} + +cDisplayMessageView::~cDisplayMessageView() { + CancelSave(); + FadeOut(); +} + +bool cDisplayMessageView::createOsd(void) { + cRect osdSize = tmplView->GetOsdSize(); + bool ok = CreateOsd(cOsd::OsdLeft() + osdSize.X(), + cOsd::OsdTop() + osdSize.Y(), + osdSize.Width(), + osdSize.Height()); + return ok; +} + +void cDisplayMessageView::DrawBackground(void) { + map < string, string > stringTokens; + map < string, int > intTokens; + DrawViewElement(veBackground, &stringTokens, &intTokens); +} + +void cDisplayMessageView::DrawMessage(eMessageType type, const char *text) { + map < string, string > stringTokens; + map < string, int > intTokens; + + stringTokens.insert(pair("text", text)); + + intTokens.insert(pair("status", (type == mtStatus) ? true : false)); + intTokens.insert(pair("info", (type == mtInfo) ? true : false)); + intTokens.insert(pair("warning", (type == mtWarning) ? true : false)); + intTokens.insert(pair("error", (type == mtError) ? true : false)); + + DrawViewElement(veMessage, &stringTokens, &intTokens); +} + +void cDisplayMessageView::Action(void) { + SetInitFinished(); + FadeIn(); + DoFlush(); + cView::Action(); +} diff --git a/views/displaymessageview.h b/views/displaymessageview.h new file mode 100644 index 0000000..1bcc908 --- /dev/null +++ b/views/displaymessageview.h @@ -0,0 +1,19 @@ +#ifndef __DISPLAYMESSAGEVIEW_H +#define __DISPLAYMESSAGEVIEW_H + +#include "../libtemplate/template.h" +#include "view.h" + +class cDisplayMessageView : public cView { +private: + virtual void Action(void); +public: + cDisplayMessageView(cTemplateView *tmplView); + virtual ~cDisplayMessageView(); + bool createOsd(void); + void DrawBackground(void); + void DrawMessage(eMessageType type, const char *text); + void DoFadeIn(void) { Start(); }; + void Flush(void) { DoFlush(); }; +}; +#endif //__DISPLAYMESSAGEVIEW_H diff --git a/views/displayreplayview.c b/views/displayreplayview.c new file mode 100644 index 0000000..bea64b7 --- /dev/null +++ b/views/displayreplayview.c @@ -0,0 +1,376 @@ +#define __STL_CONFIG_H +#include +#include "../services/scraper2vdr.h" +#include "displayreplayview.h" +#include "../libcore/helpers.h" + +cDisplayReplayView::cDisplayReplayView(cTemplateView *tmplView) : cView(tmplView) { + lastDate = ""; + DeleteOsdOnExit(); + SetFadeTime(tmplView->GetNumericParameter(ptFadeTime)); +} + +cDisplayReplayView::~cDisplayReplayView() { + CancelSave(); + FadeOut(); +} + +bool cDisplayReplayView::createOsd(void) { + cRect osdSize = tmplView->GetOsdSize(); + bool ok = CreateOsd(cOsd::OsdLeft() + osdSize.X(), + cOsd::OsdTop() + osdSize.Y(), + osdSize.Width(), + osdSize.Height()); + return ok; +} + +void cDisplayReplayView::DrawBackground(bool modeOnly) { + map < string, string > stringTokens; + map < string, int > intTokens; + if (modeOnly) + DrawViewElement(veBackgroundModeOnly, &stringTokens, &intTokens); + else + DrawViewElement(veBackground, &stringTokens, &intTokens); +} + +void cDisplayReplayView::DrawDate(bool modeOnly) { + if (modeOnly) + return; + if (!ViewElementImplemented(veDateTime)) { + return; + } + cString curDate = DayDateTime(); + if (strcmp(curDate, lastDate)) { + map < string, string > stringTokens; + map < string, int > intTokens; + + time_t t = time(0); // get time now + struct tm * now = localtime(&t); + + intTokens.insert(pair("year", now->tm_year + 1900)); + intTokens.insert(pair("day", now->tm_mday)); + + char monthname[20]; + char monthshort[10]; + strftime(monthshort, sizeof(monthshort), "%b", now); + strftime(monthname, sizeof(monthname), "%B", now); + stringTokens.insert(pair("monthname", monthname)); + stringTokens.insert(pair("monthnameshort", monthshort)); + stringTokens.insert(pair("month", *cString::sprintf("%02d", now->tm_mon + 1))); + stringTokens.insert(pair("dayleadingzero", *cString::sprintf("%02d", now->tm_mday))); + stringTokens.insert(pair("dayname", *WeekDayNameFull(now->tm_wday))); + stringTokens.insert(pair("daynameshort", *WeekDayName(now->tm_wday))); + stringTokens.insert(pair("time", *TimeString(t))); + + ClearViewElement(veDateTime); + DrawViewElement(veDateTime, &stringTokens, &intTokens); + + lastDate = curDate; + } +} + +void cDisplayReplayView::DrawTitle(const cRecording *recording) { + map < string, string > stringTokens; + map < string, int > intTokens; + + const char *recName = NULL; + const cRecordingInfo *recInfo = recording->Info(); + if (recInfo) { + recName = recInfo->Title(); + } + if (!recName) + recName = recording->Name(); + string recShortText = recInfo->ShortText() ? recInfo->ShortText() : ""; + string recDate = *ShortDateString(recording->Start()); + string recTime = *TimeString(recording->Start()); + + stringTokens.insert(pair("rectitle", recName ? recName : "")); + stringTokens.insert(pair("recsubtitle", recShortText)); + stringTokens.insert(pair("recdate", recDate)); + stringTokens.insert(pair("rectime", recTime)); + + DrawViewElement(veRecTitle, &stringTokens, &intTokens); +} + +void cDisplayReplayView::DrawRecordingInformation(const cRecording *recording) { + map < string, string > stringTokens; + map < string, int > intTokens; + + int screenWidth = 0; + int screenHeight = 0; + double aspect = 0; + cDevice::PrimaryDevice()->GetVideoSize(screenWidth, screenHeight, aspect); + bool isHD = false; + string resName = GetScreenResolutionString(screenWidth, screenHeight, &isHD); + bool isWideScreen = false; + string aspectName = GetScreenAspectString(aspect, &isWideScreen); + + intTokens.insert(pair("screenwidth", screenWidth)); + intTokens.insert(pair("screenheight", screenHeight)); + intTokens.insert(pair("isHD", isHD)); + intTokens.insert(pair("isWideScreen", isWideScreen)); + stringTokens.insert(pair("resolution", resName)); + stringTokens.insert(pair("aspect", aspectName)); + + ClearViewElement(veRecInfo); + DrawViewElement(veRecInfo, &stringTokens, &intTokens); +} + +void cDisplayReplayView::DrawScraperContent(const cRecording *recording) { + if (!recording) + return; + + if (!ViewElementImplemented(veScraperContent)) { + return; + } + + static cPlugin *pScraper = GetScraperPlugin(); + if (!pScraper) { + return; + } + + ScraperGetPosterBannerV2 call; + call.event = NULL; + call.recording = recording; + if (pScraper->Service("GetPosterBannerV2", &call)) { + int mediaWidth = 0; + int mediaHeight = 0; + std::string mediaPath = ""; + bool isBanner = false; + + if ((call.type == tSeries) && call.banner.path.size() > 0) { + mediaWidth = call.banner.width; + mediaHeight = call.banner.height; + mediaPath = call.banner.path; + isBanner = true; + } else if (call.type == tMovie && call.poster.path.size() > 0 && call.poster.height > 0) { + mediaWidth = call.poster.width; + mediaHeight = call.poster.height; + mediaPath = call.poster.path; + } else + return; + + map < string, int > intTokens; + map < string, string > stringTokens; + intTokens.insert(pair("mediawidth", mediaWidth)); + intTokens.insert(pair("mediaheight", mediaHeight)); + intTokens.insert(pair("isbanner", isBanner)); + stringTokens.insert(pair("mediapath", mediaPath)); + ClearViewElement(veScraperContent); + DrawViewElement(veScraperContent, &stringTokens, &intTokens); + } +} + +void cDisplayReplayView::DrawCurrent(const char *current) { + map < string, string > stringTokens; + map < string, int > intTokens; + stringTokens.insert(pair("reccurrent", current)); + + ClearViewElement(veRecCurrent); + DrawViewElement(veRecCurrent, &stringTokens, &intTokens); +} + +void cDisplayReplayView::DrawTotal(const char *total) { + map < string, string > stringTokens; + map < string, int > intTokens; + stringTokens.insert(pair("rectotal", total)); + + ClearViewElement(veRecTotal); + DrawViewElement(veRecTotal, &stringTokens, &intTokens); +} + +void cDisplayReplayView::DrawProgressBar(int current, int total) { + map < string, string > stringTokens; + map < string, int > intTokens; + intTokens.insert(pair("current", current)); + intTokens.insert(pair("total", total)); + stringTokens.insert(pair("dummy", "")); + ClearViewElement(veRecProgressBar); + DrawViewElement(veRecProgressBar, &stringTokens, &intTokens); +} + +void cDisplayReplayView::DrawMarks(const cMarks *marks, int total) { + if (!marks) + return; + + map < string, string > stringTokens; + map < string, int > intTokens; + map < string, vector< map< string, string > > > loopTokens; + vector< map< string, string > > markTokens; + stringstream tot; + tot << total; + + bool isStartMark = true; + for (const cMark *m = marks->First(); m; m = marks->Next(m)) { + map< string, string > markVals; + stringstream pos; + pos << m->Position(); + markVals.insert(pair< string, string >("marks[position]", pos.str())); + markVals.insert(pair< string, string >("marks[total]", tot.str())); + markVals.insert(pair< string, string >("marks[startmark]", isStartMark ? "1" : "0")); + const cMark *m2 = marks->Next(m); + if (m2) { + stringstream posNext; + posNext << m2->Position(); + markVals.insert(pair< string, string >("marks[endposition]", posNext.str())); + } else { + markVals.insert(pair< string, string >("marks[endposition]", tot.str())); + } + isStartMark = !isStartMark; + markTokens.push_back(markVals); + } + loopTokens.insert(pair< string, vector< map< string, string > > >("marks", markTokens)); + + ClearViewElement(veCuttingMarks); + DrawViewElement(veCuttingMarks, &stringTokens, &intTokens, &loopTokens); +} + +void cDisplayReplayView::DrawControlIcons(bool play, bool forward, int speed, bool modeOnly) { + map < string, string > stringTokens; + map < string, int > intTokens; + + bool isPlay = false; + bool isPause = false; + bool isFF = false; + bool isFF1x = false; + bool isFF2x = false; + bool isFF3x = false; + bool isRew = false; + bool isRew1x = false; + bool isRew2x = false; + bool isRew3x = false; + + if (speed == -1) { + if (play) { + isPlay = true; + } else { + isPause = true; + } + } else if (forward) { + if (!play) { + isPause = true; + } + if (speed == 1) { + isFF1x = true; + } else if (speed == 2) { + isFF2x = true; + } else if (speed == 3) { + isFF3x = true; + } else { + isFF = true; + } + } else { + if (!play) { + isPause = true; + } + if (speed == 1) { + isRew1x = true; + } else if (speed == 2) { + isRew2x = true; + } else if (speed == 3) { + isRew3x = true; + } else { + isRew = true; + } + } + intTokens.insert(pair("play", isPlay)); + intTokens.insert(pair("pause", isPause)); + intTokens.insert(pair("forward", isFF)); + intTokens.insert(pair("forward1x", isFF1x)); + intTokens.insert(pair("forward2x", isFF2x)); + intTokens.insert(pair("forward3x", isFF3x)); + intTokens.insert(pair("rewind", isRew)); + intTokens.insert(pair("rewind1x", isRew1x)); + intTokens.insert(pair("rewind2x", isRew2x)); + intTokens.insert(pair("rewind3x", isRew3x)); + + if (modeOnly) { + ClearViewElement(veControlIconsModeOnly); + DrawViewElement(veControlIconsModeOnly, &stringTokens, &intTokens); + } else { + ClearViewElement(veControlIcons); + DrawViewElement(veControlIcons, &stringTokens, &intTokens); + } +} + +void cDisplayReplayView::DrawJump(const char *jump) { + if (!jump) { + ClearViewElement(veRecJump); + return; + } + + map < string, string > stringTokens; + map < string, int > intTokens; + stringTokens.insert(pair("jump", jump)); + + ClearViewElement(veRecJump); + DrawViewElement(veRecJump, &stringTokens, &intTokens); +} + +void cDisplayReplayView::DrawMessage(eMessageType type, const char *text) { + if (!text) { + ClearViewElement(veMessage); + } + + map < string, string > stringTokens; + map < string, int > intTokens; + + stringTokens.insert(pair("text", text)); + + intTokens.insert(pair("status", (type == mtStatus) ? true : false)); + intTokens.insert(pair("info", (type == mtInfo) ? true : false)); + intTokens.insert(pair("warning", (type == mtWarning) ? true : false)); + intTokens.insert(pair("error", (type == mtError) ? true : false)); + + ClearViewElement(veMessage); + DrawViewElement(veMessage, &stringTokens, &intTokens); +} + + +void cDisplayReplayView::Action(void) { + SetInitFinished(); + FadeIn(); + DoFlush(); + cView::Action(); +} + +string cDisplayReplayView::GetScreenResolutionString(int width, int height, bool *isHD) { + string name = ""; + switch (width) { + case 1920: + case 1440: + name = "hd1080i"; + *isHD = true; + break; + case 1280: + if (height == 720) + name = "hd720p"; + else + name = "hd1080i"; + *isHD = true; + break; + case 720: + name = "sd576i"; + break; + default: + name = "sd576i"; + break; + } + return name; +} + +string cDisplayReplayView::GetScreenAspectString(double aspect, bool *isWideScreen) { + string name = ""; + *isWideScreen = false; + if (aspect == 4.0/3.0) { + name = "4:3"; + *isWideScreen = false; + } else if (aspect == 16.0/9.0) { + name = "16:9"; + *isWideScreen = true; + } else if (aspect == 2.21) { + name = "21:9"; + *isWideScreen = true; + } + return name; +} \ No newline at end of file diff --git a/views/displayreplayview.h b/views/displayreplayview.h new file mode 100644 index 0000000..9c81917 --- /dev/null +++ b/views/displayreplayview.h @@ -0,0 +1,32 @@ +#ifndef __DISPLAYREPLAYVIEW_H +#define __DISPLAYREPLAYVIEW_H + +#include "../libtemplate/template.h" +#include "view.h" + +class cDisplayReplayView : public cView { +private: + cString lastDate; + string GetScreenResolutionString(int width, int height, bool *isHD); + string GetScreenAspectString(double aspect, bool *isWideScreen); + virtual void Action(void); +public: + cDisplayReplayView(cTemplateView *tmplView); + virtual ~cDisplayReplayView(); + bool createOsd(void); + void DrawBackground(bool modeOnly); + void DrawDate(bool modeOnly); + void DrawTitle(const cRecording *recording); + void DrawRecordingInformation(const cRecording *recording); + void DrawScraperContent(const cRecording *recording); + void DrawCurrent(const char *current); + void DrawTotal(const char *total); + void DrawProgressBar(int current, int total); + void DrawMarks(const cMarks *marks, int total); + void DrawControlIcons(bool play, bool forward, int speed, bool modeOnly); + void DrawJump(const char *jump); + void DrawMessage(eMessageType type, const char *text); + void DoFadeIn(void) { Start(); }; + void Flush(void) { DoFlush(); }; +}; +#endif //__DISPLAYREPLAYVIEW_H diff --git a/views/displayvolumeview.c b/views/displayvolumeview.c new file mode 100644 index 0000000..e3700dd --- /dev/null +++ b/views/displayvolumeview.c @@ -0,0 +1,55 @@ +#define __STL_CONFIG_H +#include +#include "displayvolumeview.h" + +cDisplayVolumeView::cDisplayVolumeView(cTemplateView *tmplView) : cView(tmplView) { + volumeLast = -1; + muteLast = false; + DeleteOsdOnExit(); + SetFadeTime(tmplView->GetNumericParameter(ptFadeTime)); +} + +cDisplayVolumeView::~cDisplayVolumeView() { + CancelSave(); + FadeOut(); +} + +bool cDisplayVolumeView::createOsd(void) { + cRect osdSize = tmplView->GetOsdSize(); + bool ok = CreateOsd(cOsd::OsdLeft() + osdSize.X(), + cOsd::OsdTop() + osdSize.Y(), + osdSize.Width(), + osdSize.Height()); + return ok; +} + +void cDisplayVolumeView::DrawBackground(void) { + map < string, string > stringTokens; + map < string, int > intTokens; + DrawViewElement(veBackground, &stringTokens, &intTokens); +} + +void cDisplayVolumeView::DrawVolume(int current, int total, bool mute) { + if ((volumeLast == current) && (muteLast == mute)) + return; + volumeLast = current; + muteLast = mute; + + map < string, string > stringTokens; + map < string, int > intTokens; + + intTokens.insert(pair("volume", current)); + intTokens.insert(pair("maxvolume", total)); + intTokens.insert(pair("volumepercent", (double)current *100 / (double)total)); + intTokens.insert(pair("mute", mute)); + + ClearViewElement(veVolume); + DrawViewElement(veVolume, &stringTokens, &intTokens); +} + +void cDisplayVolumeView::Action(void) { + SetInitFinished(); + FadeIn(); + DoFlush(); + cView::Action(); +} diff --git a/views/displayvolumeview.h b/views/displayvolumeview.h new file mode 100644 index 0000000..544426e --- /dev/null +++ b/views/displayvolumeview.h @@ -0,0 +1,21 @@ +#ifndef __DISPLAYVOLUMEVIEW_H +#define __DISPLAYVOLUMEVIEW_H + +#include "../libtemplate/template.h" +#include "view.h" + +class cDisplayVolumeView : public cView { +private: + int volumeLast; + bool muteLast; + virtual void Action(void); +public: + cDisplayVolumeView(cTemplateView *tmplView); + virtual ~cDisplayVolumeView(); + bool createOsd(void); + void DrawBackground(void); + void DrawVolume(int current, int total, bool mute); + void DoFadeIn(void) { Start(); }; + void Flush(void) { DoFlush(); }; +}; +#endif //__DISPLAYVOLUMEVIEW_H diff --git a/views/view.c b/views/view.c new file mode 100644 index 0000000..3b72253 --- /dev/null +++ b/views/view.c @@ -0,0 +1,809 @@ +#include "view.h" +#include "../config.h" +#include "../libcore/helpers.h" +#include "../libcore/imageloader.h" + +using namespace std; + +cView::cView(cTemplateView *tmplView) : cPixmapContainer(tmplView->GetNumPixmaps()) { + this->tmplView = tmplView; + tvScaled = tmplView->GetScalingWindow(scalingWindow); + if (tvScaled) { + cDevice::PrimaryDevice()->ScaleVideo(scalingWindow); + } + tmplItem = NULL; + tmplTab = NULL; + Init(); +} + +cView::cView(cTemplateViewElement *tmplItem) : cPixmapContainer(tmplItem->GetNumPixmaps()) { + this->tmplItem = tmplItem; + tmplView = NULL; + tmplTab = NULL; + tvScaled = false; + Init(); +} + +cView::cView(cTemplateViewTab *tmplTab) : cPixmapContainer(1) { + this->tmplTab = tmplTab; + tmplView = NULL; + tmplItem = NULL; + tvScaled = false; + Init(); +} + +cView::~cView() { + if (tvScaled) { + cDevice::PrimaryDevice()->ScaleVideo(cRect::Null); + } +} + +void cView::Init(void) { + viewInit = true; + scrolling = false; + veScroll = veUndefined; + scrollingPix = -1; + scrollOrientation = orHorizontal; + scrollDelay = 0; + scrollMode = smNone; + scrollSpeed = ssMedium; + currentlyScrolling = false; +} + +void cView::Action(void) { + if (scrolling) { + DoSleep(scrollDelay); + if (scrollOrientation == orHorizontal) { + ActivateScrolling(); + ScrollHorizontal(scrollingPix, scrollDelay, scrollSpeed, scrollMode); + } else { + ScrollVertical(scrollingPix, scrollDelay, scrollSpeed); + } + } +} + +void cView::Stop(void) { + CancelSave(); +} + +/******************************************************************************** +* Protected Functions +********************************************************************************/ + +void cView::DrawViewElement(eViewElement ve, map *stringTokens, map *intTokens, map < string, vector< map< string, string > > > *loopTokens) { + //setting correct ViewElement, depending which constructor was used + cTemplateViewElement *viewElement; + if (tmplItem && ve == veMenuCurrentItemDetail) { + viewElement = tmplItem; + } else if (tmplView) { + viewElement = tmplView->GetViewElement(ve); + } + if (!viewElement) + return; + + if (viewElement->DebugTokens()) { + DebugTokens(tmplView ? (tmplView->GetViewElementName(ve)) : "current view", stringTokens, intTokens, loopTokens); + } + + //iterate through pixmaps of viewelement + int pixCurrent = viewElement->GetPixOffset(); + if (pixCurrent < 0) + return; + viewElement->InitIterator(); + cTemplatePixmap *pix = NULL; + while(pix = viewElement->GetNextPixmap()) { + //reset Template + pix->ClearDynamicParameters(); + //create Pixmap if already fully parsed + if (!PixmapExists(pixCurrent) && pix->Ready() && pix->DoExecute() && !pix->Scrolling()) { + CreateViewPixmap(pixCurrent, pix); + } + //check if pixmap needs dynamic parameters + if ((!pix->Ready() || !pix->DoExecute()) && !pix->Scrolling()) { + //parse dynamic parameters and initiate functions + pix->ParseDynamicParameters(intTokens, true); + if (pix->Ready() && pix->DoExecute()) { + CreateViewPixmap(pixCurrent, pix); + } + } else { + //parse dynamic parameters but not initiate functions + pix->ParseDynamicParameters(intTokens, false); + } + //if pixmap still not valid, skip + if (!pix->Ready() && !pix->Scrolling()) { + pixCurrent++; + continue; + } + //if condition for pixmap set, check if cond is true + if (!pix->DoExecute()) { + pixCurrent++; + continue; + } + //parse dynamic tokens of pixmap functions + pix->ClearDynamicFunctionParameters(); + pix->ParseDynamicFunctionParameters(stringTokens, intTokens); + + if (!PixmapExists(pixCurrent) && pix->Scrolling()) { + cSize drawportSize; + scrolling = pix->CalculateDrawPortSize(drawportSize, loopTokens); + if (scrolling) { + CreateScrollingPixmap(pixCurrent, pix, drawportSize); + pix->SetScrollingTextWidth(); + veScroll = ve; + scrollingPix = pixCurrent; + scrollOrientation = pix->GetNumericParameter(ptOrientation); + scrollMode = pix->GetNumericParameter(ptScrollMode); + scrollDelay = pix->GetNumericParameter(ptDelay); + scrollSpeed = pix->GetNumericParameter(ptScrollSpeed); + } else { + CreateViewPixmap(pixCurrent, pix); + } + } + if (pix->DoDebug()) { + pix->Debug(); + } + + DrawPixmap(pixCurrent, pix, loopTokens); + pixCurrent++; + } +} + +void cView::ClearViewElement(eViewElement ve) { + if (!tmplView) + return; + cTemplateViewElement *viewElement = tmplView->GetViewElement(ve); + if (!viewElement) + return; + int pixCurrent = viewElement->GetPixOffset(); + if (pixCurrent < 0) + return; + cTemplatePixmap *pix = NULL; + viewElement->InitIterator(); + while(pix = viewElement->GetNextPixmap()) { + Fill(pixCurrent, clrTransparent); + pixCurrent++; + } +} + +void cView::ActivateScrolling(void) { + if (veScroll == veUndefined) + return; + cTemplateViewElement *scrollViewElement = NULL; + if (tmplView) { + scrollViewElement = tmplView->GetViewElement(veScroll); + } + if (!scrollViewElement) + return; + + ClearViewElement(veScroll); + currentlyScrolling = true; + + int pixCurrent = scrollViewElement->GetPixOffset(); + if (pixCurrent < 0) + return; + scrollViewElement->InitIterator(); + cTemplatePixmap *pix = NULL; + while(pix = scrollViewElement->GetNextPixmap()) { + DrawPixmap(pixCurrent, pix); + pixCurrent++; + } +} + +bool cView::ViewElementImplemented(eViewElement ve) { + return tmplView->GetNumPixmapsViewElement(ve); +} + +void cView::CreateViewPixmap(int num, cTemplatePixmap *pix, cRect *size) { + cRect pixSize; + if (size) { + pixSize = *size; + } else { + pixSize = pix->GetPixmapSize(); + } + int layer = pix->GetNumericParameter(ptLayer); + int transparency = pix->GetNumericParameter(ptTransparency); + SetTransparency(num, transparency); + CreatePixmap(num, layer, pixSize); +} + +void cView::CreateScrollingPixmap(int num, cTemplatePixmap *pix, cSize &drawportSize) { + cRect pixViewPort = pix->GetPixmapSize(); + cRect drawPort; + drawPort.SetX(0); + drawPort.SetY(0); + drawPort.SetWidth(drawportSize.Width()); + drawPort.SetHeight(drawportSize.Height()); + int layer = pix->GetNumericParameter(ptLayer); + int transparency = pix->GetNumericParameter(ptTransparency); + SetTransparency(num, transparency); + CreatePixmap(num, layer, pixViewPort, drawPort); +} + +void cView::DrawPixmap(int num, cTemplatePixmap *pix, map < string, vector< map< string, string > > > *loopTokens, bool flushPerLoop) { + pix->InitIterator(); + cTemplateFunction *func = NULL; + while(func = pix->GetNextFunction()) { + eFuncType type = func->GetType(); + if (func->DoDebug()) { + func->Debug(); + } + if (!func->DoExecute()) { + continue; + } + switch (type) { + case ftFill: + DoFill(num, func); + break; + case ftDrawText: + DoDrawText(num, func); + break; + case ftDrawTextBox: { + int floating = func->GetNumericParameter(ptFloat); + if (floating > flNone) { + DoDrawFloatingTextBox(num, func); + } else { + DoDrawTextBox(num, func); + } + break; } + case ftDrawRectangle: + DoDrawRectangle(num, func); + break; + case ftDrawEllipse: + DoDrawEllipse(num, func); + break; + case ftDrawImage: + DoDrawImage(num, func); + break; + case ftLoop: + if (loopTokens) + DrawLoop(num, func, loopTokens); + break; + default: + break; + } + if (flushPerLoop) { + DoFlush(); + } + } +} + +void cView::DrawLoop(int numPixmap, cTemplateFunction *func, map < string, vector< map< string, string > > > *loopTokens) { + cTemplateLoopFunction *loopFunc = dynamic_cast(func); + if (!loopFunc) + return; + + int loopX0 = loopFunc->GetNumericParameter(ptX); + if (loopX0 < 0) loopX0 = 0; + int loopY0 = loopFunc->GetNumericParameter(ptY); + if (loopY0 < 0) loopY0 = 0; + int orientation = loopFunc->GetNumericParameter(ptOrientation); + int loopWidth = loopFunc->GetNumericParameter(ptWidth); + if (loopWidth <= 0) + loopWidth = loopFunc->GetContainerWidth(); + int loopHeight = loopFunc->GetNumericParameter(ptHeight); + if (loopHeight <= 0) + loopHeight = loopFunc->GetContainerHeight(); + int columnWidth = loopFunc->GetNumericParameter(ptColumnWidth); + int rowHeight = loopFunc->GetNumericParameter(ptRowHeight); + int overflow = loopFunc->GetNumericParameter(ptOverflow); + int maxItems = loopFunc->GetNumericParameter(ptNumElements); + + int x0 = loopX0; + int y0 = loopY0; + + string loopTokenName = loopFunc->GetParameter(ptName); + + map < string, vector< map< string, string > > >::iterator hit = loopTokens->find(loopTokenName); + if (hit == loopTokens->end()) + return; + vector< map > loopToken = hit->second; + int lineNumber=0; + for (vector< map >::iterator line = loopToken.begin(); line != loopToken.end(); line++) { + //check overflow behaviour + if (overflow == otCut) { + if (orientation == orHorizontal) { + if (lineNumber * columnWidth > loopWidth) { + return; + } + } else if (orientation == orVertical) { + if (lineNumber * rowHeight > loopHeight) { + return; + } + } + } else if (overflow == otWrap && orientation == orHorizontal) { + if (x0 + columnWidth > loopWidth) { + x0 = loopX0; + if (rowHeight > 0) { + y0 += rowHeight; + } else { + y0 += loopFunc->GetLoopElementsHeight(); + } + } + } + map tokens = *line; + loopFunc->ClearDynamicParameters(); + loopFunc->ParseDynamicParameters(&tokens); + loopFunc->InitIterator(); + cTemplateFunction *func = NULL; + while(func = loopFunc->GetNextFunction()) { + //do debug? + if (func->DoDebug()) + func->Debug(); + //check if set condition is true + if (!func->DoExecute()) { + continue; + } + //execute + eFuncType type = func->GetType(); + switch (type) { + case ftDrawText: + DoDrawText(numPixmap, func, x0, y0); + break; + case ftDrawTextBox: + DoDrawTextBox(numPixmap, func, x0, y0); + break; + case ftDrawRectangle: + DoDrawRectangle(numPixmap, func, x0, y0); + break; + case ftDrawEllipse: + DoDrawEllipse(numPixmap, func, x0, y0); + break; + case ftDrawImage: + DoDrawImage(numPixmap, func, x0, y0); + break; + default: + break; + } + } + //calculate position of next loop element + if (orientation == orHorizontal) { + if (columnWidth > 0) { + x0 += columnWidth; + } else { + x0 += loopFunc->GetLoopElementsWidth(); + } + } else if (orientation == orVertical) { + if (rowHeight > 0) { + y0 += rowHeight; + } else { + y0 += loopFunc->GetLoopElementsHeight(); + } + } + lineNumber++; + //DoFlush(); + } +} + +void cView::DebugTokens(string viewElement, map *stringTokens, map *intTokens, map < string, vector< map< string, string > > > *loopTokens) { + esyslog("skindesigner: ------------------------------ Tokens for %s:", viewElement.c_str()); + if (stringTokens) { + for (map::iterator st = stringTokens->begin(); st != stringTokens->end(); st++) { + esyslog("skindesigner: string var \"%s\" = \"%s\"", (st->first).c_str(), (st->second).c_str()); + } + } + if (intTokens) { + for (map::iterator it = intTokens->begin(); it != intTokens->end(); it++) { + esyslog("skindesigner: int var \"%s\" = %d", (it->first).c_str(), it->second); + } + } + if (loopTokens) { + for(map < string, vector< map< string, string > > >::iterator it1 = loopTokens->begin(); it1 != loopTokens->end(); it1++) { + int line = 0; + string tokenName = it1->first; + vector< map > tokens = it1->second; + esyslog("skindesigner: loop token %s", tokenName.c_str()); + for (vector< map >::iterator it2 = tokens.begin(); it2 != tokens.end(); it2++) { + esyslog("skindesigner: loop tokens line %d:", line++); + map element = *it2; + for (map::iterator el = element.begin(); el != element.end(); el++) { + esyslog("skindesigner: name: %s, value: %s", (el->first).c_str(), (el->second).c_str()); + } + } + } + } +} + +/***************************************************************** +* Private Functions +*****************************************************************/ + +void cView::DoFill(int num, cTemplateFunction *func) { + tColor col = func->GetColorParameter(ptColor); + Fill(num, col); +} + +void cView::DoDrawText(int num, cTemplateFunction *func, int x0, int y0) { + int x = func->GetNumericParameter(ptX); + if (x < 0) x = 0; + x += x0; + int y = func->GetNumericParameter(ptY); + if (y < 0) y = 0; + y += y0; + cPoint pos(x,y); + string fontName = func->GetFontName(); + int fontSize = func->GetNumericParameter(ptFontSize); + tColor clr = func->GetColorParameter(ptColor); + tColor clrBack = clrTransparent; + string text = ""; + if (!currentlyScrolling) { + text = func->GetText(true); + } else { + text = func->GetText(false); + } + DrawText(num, pos, text.c_str(), clr, clrBack, fontName, fontSize); +} + +void cView::DoDrawTextBox(int num, cTemplateFunction *func, int x0, int y0) { + string text = func->GetText(false); + if (text.size() < 3) + return; + int x = func->GetNumericParameter(ptX); + int y = func->GetNumericParameter(ptY); + if (x < 0) x = 0; + x += x0; + if (y < 0) y = 0; + y += y0; + int width = func->GetNumericParameter(ptWidth); + int height = func->GetNumericParameter(ptHeight); + string fontName = func->GetFontName(); + int fontSize = func->GetNumericParameter(ptFontSize); + int align = func->GetNumericParameter(ptAlign); + int maxLines = func->GetNumericParameter(ptMaxLines); + tColor clr = func->GetColorParameter(ptColor); + tColor clrBack = clrTransparent; + const cFont *font = fontManager->Font(fontName, fontSize); + if (!font) + return; + cTextWrapper wrapper; + wrapper.Set(text.c_str(), font, width); + int fontHeight = fontManager->Height(fontName, fontSize); + int lines = wrapper.Lines(); + int yLine = y; + for (int line=0; line < lines; line++) { + int xLine = x; + if (align == alCenter) { + int textWidth = font->Width(wrapper.GetLine(line)); + xLine += (width - textWidth)/2; + } else if (align == alRight) { + int textWidth = font->Width(wrapper.GetLine(line)); + xLine += (width - textWidth); + } + cPoint pos(xLine, yLine); + if (maxLines > 0 && line == maxLines-1) { + string lastLine = wrapper.GetLine(line); + if (lines > maxLines) { + lastLine += "..."; + } + DrawText(num, pos, lastLine.c_str(), clr, clrBack, fontName, fontSize); + break; + } else if (height > 0 && yLine - y + 2*fontHeight > height) { + DrawText(num, pos, "...", clr, clrBack, fontName, fontSize); + break; + } + DrawText(num, pos, wrapper.GetLine(line), clr, clrBack, fontName, fontSize); + yLine += fontHeight; + } +} + +void cView::DoDrawFloatingTextBox(int num, cTemplateFunction *func) { + string text = func->GetText(false); + if (text.size() < 3) + return; + int x = func->GetNumericParameter(ptX); + int y = func->GetNumericParameter(ptY); + if (x < 0) x = 0; + if (y < 0) y = 0; + int width = func->GetNumericParameter(ptWidth); + int height = func->GetNumericParameter(ptHeight); + string fontName = func->GetFontName(); + int fontSize = func->GetNumericParameter(ptFontSize); + tColor clr = func->GetColorParameter(ptColor); + tColor clrBack = clrTransparent; + const cFont *font = fontManager->Font(fontName, fontSize); + if (!font) + return; + int floatType = func->GetNumericParameter(ptFloat); + int floatWidth = func->GetNumericParameter(ptFloatWidth); + int floatHeight = func->GetNumericParameter(ptFloatHeight); + + cTextWrapper wTextTall; + cTextWrapper wTextFull; + + int fontHeight = fontManager->Height(fontName, fontSize); + int linesNarrow = floatHeight / fontHeight; + int widthNarrow = width - floatWidth; + int linesDrawn = 0; + int curY = 0; + bool drawNarrow = true; + + splitstring s(text.c_str()); + std::vector flds = s.split('\n', 1); + + if (flds.size() < 1) + return; + + std::stringstream sstrTextTall; + std::stringstream sstrTextFull; + + for (int i=0; i 0 && yLine - y + 2*fontHeight > height) { + DrawText(num, pos, "...", clr, clrBack, fontName, fontSize); + break; + } + DrawText(num, pos, wTextFull.GetLine(line), clr, clrBack, fontName, fontSize); + yLine += fontHeight; + } +} + +void cView::DoDrawRectangle(int num, cTemplateFunction *func, int x0, int y0) { + int x = func->GetNumericParameter(ptX); + int y = func->GetNumericParameter(ptY); + if (x < 0) x = 0; + x += x0; + if (y < 0) y = 0; + y += y0; + int w = func->GetNumericParameter(ptWidth); + int h = func->GetNumericParameter(ptHeight); + cRect size(x, y, w, h); + tColor clr = func->GetColorParameter(ptColor); + DrawRectangle(num, size, clr); +} + +void cView::DoDrawEllipse(int num, cTemplateFunction *func, int x0, int y0) { + int x = func->GetNumericParameter(ptX); + int y = func->GetNumericParameter(ptY); + if (x < 0) x = 0; + x += x0; + if (y < 0) y = 0; + y += y0; + int w = func->GetNumericParameter(ptWidth); + int h = func->GetNumericParameter(ptHeight); + cRect size(x, y, w, h); + tColor clr = func->GetColorParameter(ptColor); + int quadrant = func->GetNumericParameter(ptQuadrant); + DrawEllipse(num, size, clr, quadrant); +} + +void cView::DoDrawImage(int num, cTemplateFunction *func, int x0, int y0) { + int x = func->GetNumericParameter(ptX); + int y = func->GetNumericParameter(ptY); + if (x < 0) x = 0; + x += x0; + if (y < 0) y = 0; + y += y0; + cPoint pos(x,y); + int width = func->GetNumericParameter(ptWidth); + int height = func->GetNumericParameter(ptHeight); + string path = func->GetImagePath(); + eImageType type = (eImageType)func->GetNumericParameter(ptImageType); + switch (type) { + case itChannelLogo: { + cImage *logo = imgCache->GetLogo(path, width, height); + if (logo) { + DrawImage(num, pos, *logo); + } + break; } + case itSepLogo: { + cImage *sepLogo = imgCache->GetSeparatorLogo(path, width, height); + if (sepLogo) { + DrawImage(num, pos, *sepLogo); + } + break; } + case itSkinPart: { + cImage *skinpart = imgCache->GetSkinpart(path, width, height); + if (skinpart) { + DrawImage(num, pos, *skinpart); + } + break; } + case itIcon: { + cImage *icon = imgCache->GetIcon(type, path, width, height); + if (icon) { + DrawImage(num, pos, *icon); + } + break; } + case itMenuIcon: { + cImage *icon = imgCache->GetIcon(type, path, width, height); + if (icon) { + DrawImage(num, pos, *icon); + } + break; } + case itImage: { + cImageLoader imgLoader; + if (imgLoader.LoadImage(path.c_str(), width, height)) { + DrawImage(num, pos, imgLoader.GetImage()); + } + break; } + default: + break; + } +} + +/*********************************************************************** +* cViewListItem +************************************************************************/ + +cViewListItem::cViewListItem(cTemplateViewElement *tmplItem) : cView(tmplItem) { + pos = -1; + numTotal = 0; + align = alLeft; + listOrientation = orVertical; +} + +cViewListItem::~cViewListItem() { + +} + +cRect cViewListItem::DrawListItem(map *stringTokens, map *intTokens) { + cRect posItem; + if (!tmplItem) + return posItem; + + if (tmplItem->DebugTokens()) { + DebugTokens("ListItem", stringTokens, intTokens); + } + + tmplItem->InitIterator(); + cTemplatePixmap *pix = NULL; + int pixCurrent = 0; + + while(pix = tmplItem->GetNextPixmap()) { + SetListElementPosition(pix); + if (pixCurrent == 0) { + posItem = pix->GetPixmapSize(); + } + if (!PixmapExists(pixCurrent)) { + pix->ParseDynamicParameters(intTokens, true); + } else { + pix->ParseDynamicParameters(intTokens, false); + } + if (!PixmapExists(pixCurrent) && pix->Ready() && pix->DoExecute() && !pix->Scrolling()) { + CreateViewPixmap(pixCurrent, pix); + } + //if pixmap still not valid, skip + if (!pix->Ready() && !pix->Scrolling()) { + pixCurrent++; + continue; + } + //if condition for pixmap set, check if cond is true + if (!pix->DoExecute()) { + pixCurrent++; + continue; + } + + pix->ClearDynamicFunctionParameters(); + pix->ParseDynamicFunctionParameters(stringTokens, intTokens); + + if (!PixmapExists(pixCurrent) && pix->Scrolling()) { + cSize drawportSize; + scrolling = pix->CalculateDrawPortSize(drawportSize); + pix->SetScrollingTextWidth(); + if (scrolling) { + CreateScrollingPixmap(pixCurrent, pix, drawportSize); + scrollingPix = pixCurrent; + scrollOrientation = pix->GetNumericParameter(ptOrientation); + scrollMode = pix->GetNumericParameter(ptScrollMode); + scrollDelay = pix->GetNumericParameter(ptDelay); + scrollSpeed = pix->GetNumericParameter(ptScrollSpeed); + } else { + CreateViewPixmap(pixCurrent, pix); + } + } + if (pix->DoDebug()) { + pix->Debug(); + } + DrawPixmap(pixCurrent, pix); + pixCurrent++; + } + return posItem; +} + +void cViewListItem::ClearListItem(void) { + int pixMax = NumPixmaps(); + for (int pixCurrent = 0; pixCurrent < pixMax; pixCurrent++) { + Fill(pixCurrent, clrTransparent); + } +} + +void cViewListItem::SetListElementPosition(cTemplatePixmap *pix) { + int itemWidth = pix->GetNumericParameter(ptWidth); + int itemHeight = pix->GetNumericParameter(ptHeight); + int x = 0; + int y = 0; + if (listOrientation == orHorizontal) { + x = container.X(); + int totalWidth = numTotal * itemWidth; + if (align == alCenter) { + y += (container.Width() - totalWidth) / 2; + } else if (align == alBottom) { + y += (container.Width() - totalWidth); + } + x += pos * itemWidth; + y = pix->GetNumericParameter(ptY); + } else if (listOrientation == orVertical) { + y = container.Y(); + int totalHeight = numTotal * itemHeight; + if (align == alCenter) { + y += (container.Height() - totalHeight) / 2; + } else if (align == alBottom) { + y += (container.Height() - totalHeight); + } + y += pos * itemHeight; + x = pix->GetNumericParameter(ptX); + } + pix->SetX(x); + pix->SetY(y); +} + diff --git a/views/view.h b/views/view.h new file mode 100644 index 0000000..4609935 --- /dev/null +++ b/views/view.h @@ -0,0 +1,72 @@ +#ifndef __VIEW_H +#define __VIEW_H + +#include "string" +#include "map" +#include "../libcore/pixmapcontainer.h" +#include "../libtemplate/template.h" + +using namespace std; + +class cView : public cPixmapContainer { +private: + void Init(void); + void DoFill(int num, cTemplateFunction *func); + void DoDrawText(int num, cTemplateFunction *func, int x0 = 0, int y0 = 0); + void DoDrawTextBox(int num, cTemplateFunction *func, int x0 = 0, int y0 = 0); + void DoDrawFloatingTextBox(int num, cTemplateFunction *func); + void DoDrawRectangle(int num, cTemplateFunction *func, int x0 = 0, int y0 = 0); + void DoDrawEllipse(int num, cTemplateFunction *func, int x0 = 0, int y0 = 0); + void DoDrawImage(int num, cTemplateFunction *func, int x0 = 0, int y0 = 0); + void ActivateScrolling(void); +protected: + cTemplateView *tmplView; + cTemplateViewElement *tmplItem; + cTemplateViewTab *tmplTab; + //scaling window + cRect scalingWindow; + bool tvScaled; + bool viewInit; + //true if view is scrollable in general + bool scrolling; + //true if view is actually starting scrolling + bool currentlyScrolling; + eViewElement veScroll; + int scrollingPix; + int scrollOrientation; + int scrollDelay; + int scrollMode; + int scrollSpeed; + void DrawViewElement(eViewElement ve, map *stringTokens = NULL, map *intTokens = NULL, map < string, vector< map< string, string > > > *loopTokens = NULL); + void ClearViewElement(eViewElement ve); + bool ViewElementImplemented(eViewElement ve); + void CreateViewPixmap(int num, cTemplatePixmap *pix, cRect *size = NULL); + void CreateScrollingPixmap(int num, cTemplatePixmap *pix, cSize &drawportSize); + void DrawPixmap(int num, cTemplatePixmap *pix, map < string, vector< map< string, string > > > *loopTokens = NULL, bool flushPerLoop = false); + void DrawLoop(int numPixmap, cTemplateFunction *func, map < string, vector< map< string, string > > > *loopTokens); + void DebugTokens(string viewElement, map *stringTokens, map *intTokens, map < string, vector< map< string, string > > > *loopTokens = NULL); + virtual void Action(void); +public: + cView(cTemplateView *tmplView); + cView(cTemplateViewElement *tmplItem); + cView(cTemplateViewTab *tmplTab); + virtual ~cView(); + virtual void Stop(void); +}; + +class cViewListItem : public cView { +protected: + int pos; + int numTotal; + cRect container; + int align; + int listOrientation; + void SetListElementPosition(cTemplatePixmap *pix); +public: + cViewListItem(cTemplateViewElement *tmplItem); + virtual ~cViewListItem(); + cRect DrawListItem(map *stringTokens, map *intTokens); + void ClearListItem(void); +}; + +#endif //__VIEW_H \ No newline at end of file