diff options
author | louis <louis.braun@gmx.de> | 2014-09-27 09:25:14 +0200 |
---|---|---|
committer | louis <louis.braun@gmx.de> | 2014-09-27 09:25:14 +0200 |
commit | b0509b5182b6e0d04f05e6b3d5676b0d21f51966 (patch) | |
tree | 22b302342f22843e0815eb5f516c85f1478cbf0b | |
download | vdr-plugin-skindesigner-0.0.1.tar.gz vdr-plugin-skindesigner-0.0.1.tar.bz2 |
initial commit version 0.0.10.0.1
503 files changed, 24368 insertions, 0 deletions
@@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. @@ -0,0 +1,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='<see README>' -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* *~ @@ -0,0 +1,102 @@ +This is a "plugin" for the Video Disk Recorder (VDR). + +Written by: Louis Braun <louis DOT braun AT gmx DOT de> + +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 +<pluginsourcedir>/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>, --skinpath=<SKINPATH> + Path to the XML skins (Default: <ResourceDirectory>/plugins/skindesigner/skins/) + +-e path, --epgimages=path + Path to the epgimages (Default: <CacheDirectory>/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 +<SkinSourceDirectory>/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 <SkinSourceDirectory>/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 + +<ResourceDirectory>/plugins/skindesigner/skins/<skinname>/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 <string> +#include <vector> +#include <map> +#include <vdr/tools.h> +#include <vdr/skins.h> +#include <vdr/plugin.h> +#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 <vdr/skinlcars.h> + +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 <vdr/thread.h> +#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; i<MaxTabs; i++) { + const char *s = GetTabbedText(Text, i); + if (s) { + tabTexts[i] = s; + } else { + tabTexts[i] = ""; + } + } + list->AddDefaultMenuItem(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 <vdr/thread.h> +#include <vdr/skins.h> +#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 <vdr/skins.h> +#include <vdr/thread.h> +#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 <vdr/skins.h> +#include <vdr/thread.h> +#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 <vdr/skins.h> +#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 Binary files differnew file mode 100644 index 0000000..9d51f27 --- /dev/null +++ b/fonts/VDROpenSans/VDROpenSans-Bold.ttf diff --git a/fonts/VDROpenSans/VDROpenSans-BoldItalic.ttf b/fonts/VDROpenSans/VDROpenSans-BoldItalic.ttf Binary files differnew file mode 100644 index 0000000..61fc899 --- /dev/null +++ b/fonts/VDROpenSans/VDROpenSans-BoldItalic.ttf diff --git a/fonts/VDROpenSans/VDROpenSans-ExtraBold.ttf b/fonts/VDROpenSans/VDROpenSans-ExtraBold.ttf Binary files differnew file mode 100644 index 0000000..3701480 --- /dev/null +++ b/fonts/VDROpenSans/VDROpenSans-ExtraBold.ttf diff --git a/fonts/VDROpenSans/VDROpenSans-ExtraBoldItalic.ttf b/fonts/VDROpenSans/VDROpenSans-ExtraBoldItalic.ttf Binary files differnew file mode 100644 index 0000000..b760f90 --- /dev/null +++ b/fonts/VDROpenSans/VDROpenSans-ExtraBoldItalic.ttf diff --git a/fonts/VDROpenSans/VDROpenSans-Italic.ttf b/fonts/VDROpenSans/VDROpenSans-Italic.ttf Binary files differnew file mode 100644 index 0000000..4fc4fe1 --- /dev/null +++ b/fonts/VDROpenSans/VDROpenSans-Italic.ttf diff --git a/fonts/VDROpenSans/VDROpenSans-Light.ttf b/fonts/VDROpenSans/VDROpenSans-Light.ttf Binary files differnew file mode 100644 index 0000000..4806a9c --- /dev/null +++ b/fonts/VDROpenSans/VDROpenSans-Light.ttf diff --git a/fonts/VDROpenSans/VDROpenSans-LightItalic.ttf b/fonts/VDROpenSans/VDROpenSans-LightItalic.ttf Binary files differnew file mode 100644 index 0000000..4380547 --- /dev/null +++ b/fonts/VDROpenSans/VDROpenSans-LightItalic.ttf diff --git a/fonts/VDROpenSans/VDROpenSans-Regular.ttf b/fonts/VDROpenSans/VDROpenSans-Regular.ttf Binary files differnew file mode 100644 index 0000000..eaa8273 --- /dev/null +++ b/fonts/VDROpenSans/VDROpenSans-Regular.ttf diff --git a/fonts/VDROpenSans/VDROpenSans-Semibold.ttf b/fonts/VDROpenSans/VDROpenSans-Semibold.ttf Binary files differnew file mode 100644 index 0000000..2394fe1 --- /dev/null +++ b/fonts/VDROpenSans/VDROpenSans-Semibold.ttf diff --git a/fonts/VDROpenSans/VDROpenSans-SemiboldItalic.ttf b/fonts/VDROpenSans/VDROpenSans-SemiboldItalic.ttf Binary files differnew file mode 100644 index 0000000..1afcda3 --- /dev/null +++ b/fonts/VDROpenSans/VDROpenSans-SemiboldItalic.ttf 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 <ft2build.h> +#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<string, int> > usedFonts = tpl->GetUsedFonts(); + + cStringList availableFonts; + cFont::GetAvailableFontNames(&availableFonts); + + for (vector< pair<string, int> >::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<int, cFont*>::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<numFonts; i++) { + esyslog("skindesigner: font %d: %s", i, availableFonts[i]); + } +} + +void cFontManager::DeleteFonts() { + cMutexLock MutexLock(&mutex); + for(map<string, map<int,cFont*> >::iterator it = fonts.begin(); it != fonts.end(); it++) { + for(map<int,cFont*>::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<int, cFont*>(size, newFont)); + } else { + map<int, cFont*> fontsizes; + fontsizes.insert(pair<int, cFont*>(size, newFont)); + fonts.insert(pair<string, map<int, cFont*> >(name, fontsizes)); + } +} + +cFont *cFontManager::GetFont(string name, int size) { + map< string, map<int,cFont*> >::iterator hitName = fonts.find(name); + if (hitName == fonts.end()) + return NULL; + map<int,cFont*>::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 <string> +#include <map> +#include <vector> +#include <vdr/skins.h> + +#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 <string> +#include <sstream> +#include <vector> +#include "helpers.h" +#include <vdr/skins.h> + +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<string>& 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 <vdr/osd.h> +#include <vdr/plugin.h> +#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<std::string> flds; +public: + splitstring(const char *s) : std::string(s) { }; + std::vector<std::string>& 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 <string> +#include <sstream> +#include <map> +#include <fstream> +#include <sys/stat.h> +#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<std::string, cImage*>::iterator hit = channelLogoCache.find(logoName.str()); + if (hit != channelLogoCache.end()) { + delete image; + return; + } + channelLogoCache.insert(pair<string, cImage*>(logoName.str(), image)); + } + } +} + +cImage *cImageCache::GetLogo(string channelID, int width, int height) { + cMutexLock MutexLock(&mutex); + + stringstream logoName; + logoName << channelID << "_" << width << "x" << height; + + std::map<std::string, cImage*>::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<string, cImage*>(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<std::string, cImage*>::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<string, cImage*>(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<string, cImage*>(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<string, cImage*>::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<string, cImage*>(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<string, cImage*>(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<string, cImage*>::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<string, cImage*>(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<string, cImage*>::const_iterator it = iconCache.begin(); it != iconCache.end(); it++) { + cImage *img = (cImage*)it->second; + delete img; + } + iconCache.clear(); + + for(map<string, cImage*>::const_iterator it = channelLogoCache.begin(); it != channelLogoCache.end(); it++) { + cImage *img = (cImage*)it->second; + delete img; + } + channelLogoCache.clear(); + + for(map<std::string, cImage*>::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<std::string, cImage*>::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<std::string, cImage*>::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<std::string, cImage*>::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<string, cImage*>::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<string, cImage*>::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<string, cImage*>::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 <vdr/osd.h> +#include <vdr/skins.h> +#include <Magick++.h> +#include <vector> +#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<string, cImage*> iconCache; + map<string, cImage*> channelLogoCache; + map<string, cImage*> 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 <math.h> +#include <string> +#include <dirent.h> +#include <iostream> + +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 <vdr/osd.h> +#include <vdr/skins.h> +#include <Magick++.h> +#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 <string> +#include <sstream> +#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 <Magick++.h> +#include <vdr/osd.h> + +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 <cstdlib> +#include <cmath> + +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; i<m_dst_width; i++) { + const ImageScaler::TmpPixel t( src[0]*h0 + src[1]*h1 + src[2]*h2 + src[3]*h3 ); + src += 4; + dst[i] = shift_clamp(t[0]) | (shift_clamp(t[1])<<8) | (shift_clamp(t[2])<<16) | (shift_clamp(t[3])<<24); + } + + m_dst_y++; + } +} diff --git a/libcore/imagescaler.h b/libcore/imagescaler.h new file mode 100644 index 0000000..1182811 --- /dev/null +++ b/libcore/imagescaler.h @@ -0,0 +1,97 @@ +#ifndef _ImageScaler_h +#define _ImageScaler_h + +/*! + * this class scales images consisting of 4 components (RGBA) + * to an arbitrary size using a 4-tap filter + */ +class ImageScaler { +public: + + struct Filter { + unsigned m_offset; + short m_coeff[4]; + }; + + ImageScaler(); + ~ImageScaler(); + + //! set destination image and source image size + void SetImageParameters( unsigned *dst_image, unsigned dst_stride, unsigned dst_width, unsigned dst_height, unsigned src_width, unsigned src_height ); + + /*! process one pixel of source image; destination image is written while input is processed + * SetImageParameters() must be called first + */ + void PutSourcePixel( unsigned char c0, unsigned char c1, unsigned char c2, unsigned char c3 ) { + m_hbuf[ (m_src_x++) & 3 ].Set( c0, c1, c2, c3 ); + + TmpPixel *bp = m_buffer + 4 * m_dst_x + (m_src_y & 3); + const Filter *fh; + + while ( (fh=m_hor_filters+m_dst_x)->m_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 <string> +#include <vdr/plugin.h> +#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<const cTimer *>(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 <vdr/timers.h> +#include <vdr/plugin.h> + +class cGlobalSortedTimers : public cVector<const cTimer *> { + 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 <locale.h> + +cGlobals::cGlobals(void) { + fonts.insert(pair<string, string>("vdrOsd", Setup.FontOsd)); + fonts.insert(pair<string, string>("vdrFix", Setup.FontFix)); + fonts.insert(pair<string, string>("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 <string, map< string, string > >::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 <string, tColor>::iterator col = colors.begin(); col != colors.end(); col++) { + dsyslog("skindesigner: Color \"%s\": %x", (col->first).c_str(), col->second); + } + for (map <string, int>::iterator myInt = intVars.begin(); myInt != intVars.end(); myInt++) { + dsyslog("skindesigner: Integer Variable \"%s\": %d", (myInt->first).c_str(), myInt->second); + } + for (map <string, string>::iterator myStr = stringVars.begin(); myStr != stringVars.end(); myStr++) { + dsyslog("skindesigner: String Variable \"%s\": \"%s\"", (myStr->first).c_str(), (myStr->second).c_str()); + } + for (map <string, string>::iterator font = fonts.begin(); font != fonts.end(); font++) { + dsyslog("skindesigner: Font \"%s\": \"%s\"", (font->first).c_str(), (font->second).c_str()); + } + for (map <string, map< string, string > >::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 <iostream> +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <string> +#include <vector> +#include <map> +#include <set> +#include <sstream> +#include <vdr/plugin.h> + +using namespace std; + +typedef uint32_t tColor; + +// --- cGlobals ------------------------------------------------------------- + +class cGlobals { +private: + string language; + string DoTranslate(string token); +public: + cGlobals(void); + virtual ~cGlobals(void) {}; + map <string, tColor> colors; + map <string, int> intVars; + map <string, string> stringVars; + map <string, string> fonts; + map <string, map< string, string > > 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<string, int>::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<sCondition>::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<sCondition>::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 <iostream> +#include <stdio.h> +#include <stdlib.h> +#include <algorithm> +#include <math.h> +#include <string> +#include <vector> +#include <map> +#include <set> +#include <sstream> + +#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<cTextToken> 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<sCondition> 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<string, int> > cTemplate::GetUsedFonts(void) { + vector< pair<string, int> > 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<string, int> > &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<string,int>(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<string,int>(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<string,int>(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<string,int>(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 <iostream> +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <string> +#include <vector> +#include <map> +#include <set> +#include <sstream> + +#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<string, int> > &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<string, int> > 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<pair<string, string> > params) {
+ for (vector<pair<string, string> >::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<eParamType, string>(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<eParamType, string>(ptWidth, width));
+}
+
+void cTemplateFunction::SetHeightManually(string height) {
+ nativeParameters.erase(ptHeight);
+ nativeParameters.insert(pair<eParamType, string>(ptHeight, height));
+}
+
+void cTemplateFunction::SetXManually(int newX) {
+ numericParameters.erase(ptX);
+ numericParameters.insert(pair<eParamType, int>(ptX, newX));
+}
+
+void cTemplateFunction::SetYManually(int newY) {
+ numericParameters.erase(ptY);
+ numericParameters.insert(pair<eParamType, int>(ptY, newY));
+}
+
+void cTemplateFunction::SetTextboxHeight(int boxHeight) {
+ numericParameters.erase(ptHeight);
+ numericParameters.insert(pair<eParamType, int>(ptHeight, boxHeight));
+}
+
+void cTemplateFunction::SetTranslatedText(string translation) {
+ if (type != ftDrawText && type != ftDrawTextBox)
+ return;
+ if (translation.size() == 0)
+ return;
+ nativeParameters.erase(ptText);
+ nativeParameters.insert(pair<eParamType, string>(ptText, translation));
+}
+
+void cTemplateFunction::SetMaxTextWidth(int maxWidth) {
+ if (type != ftDrawText)
+ return;
+ numericParameters.erase(ptWidth);
+ numericParameters.insert(pair<eParamType, int>(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<eParamType,int>(ptWidth, logoWidth));
+ } else if (logoHeight <= 0 && logoWidthOrig > 0) {
+ logoHeight = logoWidth * logoHeightOrig / logoWidthOrig;
+ numericParameters.erase(ptHeight);
+ numericParameters.insert(pair<eParamType,int>(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<eParamType,string>::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<eParamType,string>::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<eParamType,string>::iterator hit = nativeParameters.find(type);
+ if (hit == nativeParameters.end())
+ return "";
+ return hit->second;
+}
+
+int cTemplateFunction::GetNumericParameter(eParamType type) {
+ map<eParamType,int>::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<eParamType,tColor>::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<eParamType,string> *widths) {
+ for (map<eParamType, string>::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<eParamType,string>(param->first, label));
+ val = val.replace(posStart, posEnd - posStart, "");
+ } else {
+ break;
+ }
+ posStart = val.find("{width(");
+ }
+ }
+}
+
+void cTemplateFunction::GetNeededHeights(multimap<eParamType,string> *heights) {
+ for (map<eParamType, string>::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<eParamType,string>(param->first, label));
+ val = val.replace(posStart, posEnd - posStart, "");
+ } else {
+ break;
+ }
+ posStart = val.find("{height(");
+ }
+ }
+}
+
+void cTemplateFunction::GetNeededPosX(multimap<eParamType,string> *posXs) {
+ for (map<eParamType, string>::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<eParamType,string>(param->first, label));
+ val = val.replace(posStart, posEnd - posStart, "");
+ } else {
+ break;
+ }
+ posStart = val.find("{posx(");
+ }
+ }
+}
+
+void cTemplateFunction::GetNeededPosY(multimap<eParamType,string> *posYs) {
+ for (map<eParamType, string>::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<eParamType,string>(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<eParamType, int>(type, val));
+ } else {
+ numericDynamicParameters.erase(type);
+ numericDynamicParameters.insert(pair<eParamType, string>(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<eParamType, int>(type, val));
+ } else {
+ numericDynamicParameters.erase(type);
+ numericDynamicParameters.insert(pair<eParamType, string>(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<eParamType, int>(type, val));
+ } else {
+ numericDynamicParameters.erase(type);
+ numericDynamicParameters.insert(pair<eParamType, string>(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<eParamType, int>(type, val));
+ } else {
+ numericDynamicParameters.erase(type);
+ numericDynamicParameters.insert(pair<eParamType, string>(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<eParamType, int>(type, val));
+ } else {
+ numericDynamicParameters.insert(pair<eParamType, string>(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<eParamType, int>(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<string,string>::iterator hit = globals->fonts.find(value);
+ if (hit != globals->fonts.end()) {
+ fontName = hit->second;
+ } else {
+ map<string,string>::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<eParamType, int>(ptImageType, imgType));
+ return ok;
+}
+
+
+bool cTemplateFunction::SetColor(eParamType type, string value) {
+ if (globals) {
+ for (map<string, tColor>::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<eParamType, tColor>(type, colVal));
+ return true;
+ }
+ }
+ }
+ if (value.size() != 8)
+ return false;
+ std::stringstream str;
+ str << value;
+ tColor colVal;
+ str >> std::hex >> colVal;
+ colorParameters.insert(pair<eParamType, tColor>(type, colVal));
+ return true;
+}
+
+bool cTemplateFunction::SetTextTokens(string value) {
+ textTokens.clear();
+ //first replace globals
+ for (map<string,string>::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<cTextToken> 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<eParamType, int>(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<eParamType, int>(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<eParamType, int>(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<eParamType, int>(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<eParamType, int>(ptOverflow, overflowType));
+ return ok;
+}
+
+void cTemplateFunction::ParseStringParameters(void) {
+ //first replace stringtokens in Text (drawText)
+ stringstream text;
+ for (vector<cTextToken>::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<cTextToken>::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<cTextToken>::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<eParamType, string>::iterator param = numericDynamicParameters.begin(); param !=numericDynamicParameters.end(); param++) {
+ string val = param->second;
+ for (map<string,int >::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<eParamType, int>(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<eParamType,int>(ptX, xNew));
+ } else if (align == alRight) {
+ int xNew = boxWidth - elementWidth;
+ numericParameters.erase(ptX);
+ numericParameters.insert(pair<eParamType,int>(ptX, xNew));
+ }
+
+ int vAlign = GetNumericParameter(ptValign);
+ if (vAlign == alCenter) {
+ int yNew = (boxHeight - elementHeight) / 2;
+ numericParameters.erase(ptY);
+ numericParameters.insert(pair<eParamType,int>(ptY, yNew));
+ } else if (vAlign == alBottom) {
+ int yNew = boxHeight - elementHeight;
+ numericParameters.erase(ptY);
+ numericParameters.insert(pair<eParamType,int>(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<string> flds = s.split('\n', 1);
+
+ if (flds.size() < 1)
+ return 0;
+
+ stringstream sstrTextTall;
+ stringstream sstrTextFull;
+
+ for (int i=0; i<flds.size(); i++) {
+ if (!flds[i].size()) {
+ //empty line
+ linesDrawn++;
+ curY += fontHeight;
+ if (drawNarrow)
+ sstrTextTall << "\n";
+ else
+ sstrTextFull << "\n";
+ } else {
+ cTextWrapper wrapper;
+ if (drawNarrow) {
+ wrapper.Set((flds[i].c_str()), font, widthNarrow);
+ int newLines = wrapper.Lines();
+ //check if wrapper fits completely into narrow area
+ if (linesDrawn + newLines < linesNarrow) {
+ for (int line = 0; line < wrapper.Lines(); line++) {
+ sstrTextTall << wrapper.GetLine(line) << " ";
+ }
+ sstrTextTall << "\n";
+ linesDrawn += newLines;
+ } else {
+ //this wrapper has to be splitted
+ for (int line = 0; line < wrapper.Lines(); line++) {
+ if (line + linesDrawn < linesNarrow) {
+ sstrTextTall << wrapper.GetLine(line) << " ";
+ } else {
+ sstrTextFull << wrapper.GetLine(line) << " ";
+ }
+ }
+ sstrTextFull << "\n";
+ drawNarrow = false;
+ }
+ } else {
+ wrapper.Set((flds[i].c_str()), font, width);
+ for (int line = 0; line < wrapper.Lines(); line++) {
+ sstrTextFull << wrapper.GetLine(line) << " ";
+ }
+ sstrTextFull << "\n";
+ }
+ }
+ }
+ wTextTall.Set(sstrTextTall.str().c_str(), font, widthNarrow);
+ wTextFull.Set(sstrTextFull.str().c_str(), font, width);
+
+ int textLinesTall = wTextTall.Lines();
+ int textLinesFull = wTextFull.Lines();
+
+ return ((textLinesTall+textLinesFull) * fontHeight);
+}
+
+/*******************************************************************
+* Helper Functions
+*******************************************************************/
+
+string cTemplateFunction::GetFuncName(void) {
+ string name;
+ switch (type) {
+ case ftOsd:
+ name = "OSD Parameters";
+ break;
+ case ftView:
+ name = "View Parameters";
+ break;
+ case ftViewElement:
+ name = "View Element Parameters";
+ break;
+ case ftPixmap:
+ name = "Pixmap Parameters";
+ break;
+ case ftPixmapScroll:
+ name = "ScrollPixmap Parameters";
+ break;
+ case ftLoop:
+ name = "Looping Function";
+ break;
+ case ftFill:
+ name = "Function Fill";
+ break;
+ case ftDrawText:
+ name = "Function DrawText";
+ break;
+ case ftDrawTextBox:
+ name = "Function DrawTextBox";
+ break;
+ case ftDrawImage:
+ name = "Function DrawImage";
+ break;
+ case ftDrawRectangle:
+ name = "Function DrawRectangle";
+ break;
+ case ftDrawEllipse:
+ name = "Function DrawEllipse";
+ break;
+ case ftNone:
+ name = "Undefined";
+ break;
+ default:
+ name = "Unknown";
+ break;
+ };
+ return name;
+}
+
+string cTemplateFunction::GetParamName(eParamType pt) {
+ string name;
+ switch (pt) {
+ case ptCond:
+ name = "Condition";
+ break;
+ case ptName:
+ name = "Name";
+ break;
+ case ptX:
+ name = "X";
+ break;
+ case ptY:
+ name = "Y";
+ break;
+ case ptWidth:
+ name = "Width";
+ break;
+ case ptHeight:
+ name = "Height";
+ break;
+ case ptMenuItemWidth:
+ name = "Menu Item Width";
+ break;
+ case ptFadeTime:
+ name = "Fade Time";
+ break;
+ case ptDelay:
+ name = "Delay";
+ break;
+ case ptImageType:
+ name = "Image Type";
+ break;
+ case ptPath:
+ name = "Image Path";
+ break;
+ case ptColor:
+ name = "Color";
+ break;
+ case ptFont:
+ name = "Font";
+ break;
+ case ptFontSize:
+ name = "FontSize";
+ break;
+ case ptText:
+ name = "Text";
+ break;
+ case ptLayer:
+ name = "Layer";
+ break;
+ case ptTransparency:
+ name = "Transparency";
+ break;
+ case ptQuadrant:
+ name = "Quadrant";
+ break;
+ case ptAlign:
+ name = "Align";
+ break;
+ case ptValign:
+ name = "Vertical Align";
+ break;
+ case ptScrollMode:
+ name = "Scroll Mode";
+ break;
+ case ptScrollSpeed:
+ name = "Scroll Speed";
+ break;
+ case ptOrientation:
+ name = "Orientation";
+ break;
+ case ptNumElements:
+ name = "NumElements";
+ break;
+ case ptScrollElement:
+ name = "Scroll Element";
+ break;
+ case ptScrollHeight:
+ name = "Scroll Height";
+ break;
+ case ptFloat:
+ name = "Floating Type";
+ break;
+ case ptFloatWidth:
+ name = "Floating Width";
+ break;
+ case ptFloatHeight:
+ name = "Floating Height";
+ break;
+ case ptMaxLines:
+ name = "Max num of lines";
+ break;
+ case ptColumnWidth:
+ name = "Column Width";
+ break;
+ case ptRowHeight:
+ name = "Row Height";
+ break;
+ case ptOverflow:
+ name = "Overflow Mode";
+ break;
+ case ptScaleTvX:
+ name = "Scale TV Picture X";
+ break;
+ case ptScaleTvY:
+ name = "Scale TV Picture Y";
+ break;
+ case ptScaleTvWidth:
+ name = "Scale TV Picture Width";
+ break;
+ case ptScaleTvHeight:
+ name = "Scale TV Picture Height";
+ break;
+ case ptCache:
+ name = "Cache Image";
+ break;
+ case ptDeterminateFont:
+ name = "Determinate Font";
+ break;
+ default:
+ name = "Unknown";
+ break;
+ };
+ return name;
+}
+
+void cTemplateFunction::Debug(void) {
+ esyslog("skindesigner: Debugging %s, Container: x = %d, y = %d, Size: %dx%d", GetFuncName().c_str(), containerX, containerY, containerWidth, containerHeight);
+ esyslog("skindesigner: --- Native Parameters:");
+
+ if (condParam) {
+ condParam->Debug();
+ }
+ esyslog("skindesigner: --- Native Parameters:");
+ for (map<eParamType,string>::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<eParamType,int>::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<eParamType,string>::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<eParamType,tColor>::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<cTextToken>::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<cTextToken>::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 <iostream> +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <string> +#include <vector> +#include <map> +#include <set> +#include <sstream> + +#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<cTextToken> 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<pair<string, string> > 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<eParamType,string> *widths); + void GetNeededHeights(multimap<eParamType,string> *heights); + void GetNeededPosX(multimap<eParamType,string> *posXs); + void GetNeededPosY(multimap<eParamType,string> *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<pair<string, string> > ¶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<cTemplateFunction*>::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 <string,string> *tokens) { + if (!tokens) + return; + InitIterator(); + cTemplateFunction *func = NULL; + + map <string,int> intTokens; + for (map <string,string>::iterator it = tokens->begin(); it != tokens->end(); it++) { + if (isNumber(it->second)) + intTokens.insert(pair<string, int>(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<eParamType,string> widths; + func->GetNeededWidths(&widths); + for (map<eParamType, string>::iterator names = widths.begin(); names !=widths.end(); names++) { + eParamType type = names->first; + string label = names->second; + int funcWidth = 0; + for (vector<cTemplateFunction*>::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<eParamType,string> heights; + func->GetNeededHeights(&heights); + for (map<eParamType, string>::iterator names = heights.begin(); names !=heights.end(); names++) { + eParamType type = names->first; + string label = names->second; + int funcHeight = 0; + for (vector<cTemplateFunction*>::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<cTemplateFunction*>::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<cTemplateFunction*> functions; + vector<cTemplateFunction*>::iterator funcIt; + void ReplaceWidthFunctions(void); + void ReplaceHeightFunctions(void); +public: + cTemplateLoopFunction(void); + virtual ~cTemplateLoopFunction(void); + void AddFunction(string name, vector<pair<string, string> > ¶ms); + void CalculateLoopFuncParameters(void); + void InitIterator(void); + cTemplateFunction *GetNextFunction(void); + void ClearDynamicParameters(void); + void ParseDynamicParameters(map <string,string> *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<cTemplateFunction*>::iterator it = functions.begin(); it != functions.end(); it++) {
+ delete (*it);
+ }
+ if (parameters)
+ delete parameters;
+}
+
+void cTemplatePixmap::SetParameters(vector<pair<string, string> > ¶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 <string,int> *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<cTemplateFunction*>::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<cTemplateLoopFunction*>(*func);
+ if (!loopFunc->Ready()) {
+ loopFunc->SetIntTokens(intTokens);
+ loopFunc->ParseParameters();
+ loopFunc->UnsetIntTokens();
+ }
+ loopFunc->CalculateLoopFuncParameters();
+ }
+ }
+}
+
+void cTemplatePixmap::AddFunction(string name, vector<pair<string, string> > ¶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<cTemplateFunction*>::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<cTemplateLoopFunction*>(*func);
+ loopFunc->CalculateLoopFuncParameters();
+ }
+ }
+
+ return paramsValid;
+}
+
+void cTemplatePixmap::ClearDynamicFunctionParameters(void) {
+ InitIterator();
+ cTemplateFunction *func = NULL;
+ while(func = GetNextFunction()) {
+ func->ClearDynamicParameters();
+ }
+}
+
+void cTemplatePixmap::ParseDynamicFunctionParameters(map <string,string> *stringTokens, map <string,int> *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<cTemplateLoopFunction*>(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<string,string> > loopToken = hit->second;
+ numLoopTokens = loopToken.size();
+ //parse first loop token element to get correct height
+ vector< map<string,string> >::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<eParamType,string> widths;
+ func->GetNeededWidths(&widths);
+ for (map<eParamType, string>::iterator names = widths.begin(); names !=widths.end(); names++) {
+ eParamType type = names->first;
+ string label = names->second;
+ int funcWidth = 0;
+ for (vector<cTemplateFunction*>::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<eParamType,string> heights;
+ func->GetNeededHeights(&heights);
+ for (map<eParamType, string>::iterator names = heights.begin(); names !=heights.end(); names++) {
+ eParamType type = names->first;
+ string label = names->second;
+ int funcHeight = 0;
+ for (vector<cTemplateFunction*>::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<eParamType,string> posXs;
+ func->GetNeededPosX(&posXs);
+ for (map<eParamType, string>::iterator names = posXs.begin(); names !=posXs.end(); names++) {
+ eParamType type = names->first;
+ string label = names->second;
+ int funcX = 0;
+ for (vector<cTemplateFunction*>::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<eParamType,string> posYs;
+ func->GetNeededPosY(&posYs);
+ for (map<eParamType, string>::iterator names = posYs.begin(); names !=posYs.end(); names++) {
+ eParamType type = names->first;
+ string label = names->second;
+ int funcY = 0;
+ for (vector<cTemplateFunction*>::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<cTemplateFunction*>::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 <iostream> +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <string> +#include <vector> +#include <map> +#include <set> +#include <sstream> + +#include "globals.h" +#include "templateloopfunction.h" + +using namespace std; + +// --- cTemplatePixmap ------------------------------------------------------------- + +class cTemplatePixmap { +protected: + bool scrolling; + cTemplateFunction *parameters; + vector<cTemplateFunction*> functions; + vector<cTemplateFunction*>::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<pair<string, string> > ¶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<pair<string, string> > ¶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 <string,int> *intTokens, bool initFuncs); + //Parse all function parameters with dynamically set Tokens + void ParseDynamicFunctionParameters(map <string,string> *stringTokens, map <string,int> *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<pair<string, string> > ¶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<string>::iterator hit = viewElementsAllowed.find(viewElement); + if (hit == viewElementsAllowed.end()) + return false; + return true; +} + +bool cTemplateView::ValidSubView(const char *subView) { + set<string>::iterator hit = subViewsAllowed.find(subView); + if (hit == subViewsAllowed.end()) + return false; + return true; +} + +bool cTemplateView::ValidViewList(const char *viewList) { + set<string>::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<string>::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<cTemplateViewTab*>::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<cTemplateViewTab*>::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<string> 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<string> >(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<string> >(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<string> >(name, attributes)); + + name = "fill"; + attributes.clear(); + attributes.insert("debug"); + attributes.insert("condition"); + attributes.insert("color"); + funcsAllowed.insert(pair< string, set<string> >(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<string> >(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<string> >(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<string> >(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<string> >(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<string> >(name, attributes)); + +} + +/************************************************************************************ +* cTemplateViewChannel +************************************************************************************/ + +cTemplateViewChannel::cTemplateViewChannel(void) { + + viewName = "displaychannel"; + //definition of allowed parameters for class itself + set<string> 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<string> >(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<string> attributes; + attributes.insert("x"); + attributes.insert("y"); + attributes.insert("width"); + attributes.insert("height"); + attributes.insert("fadetime"); + funcsAllowed.insert(pair< string, set<string> >(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<string> >(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<string> >(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<string> >(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<string> >(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<string> >(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<string> >(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<string> >(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<string> >(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<string> >(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<string> >(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<string> >("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<string> >("menuitems", attributes)); + + //definition of allowed parameters for currentitems viewlist + attributes.clear(); + attributes.insert("delay"); + attributes.insert("fadetime"); + funcsAllowed.insert(pair< string, set<string> >("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<string> >("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<eSubView, cTemplateView*>(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<string> 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<string> >(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<string> 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<string> >(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<string> 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<string> >(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<string> 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<string> >(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<string> >("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 <iostream> +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <string> +#include <vector> +#include <map> +#include <set> +#include <sstream> + +#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<string> subViewsAllowed; + set<string> viewElementsAllowed; + set<string> 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<pair<string, string> > ¶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<cTemplatePixmap*>::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<cTemplatePixmap*>::iterator pix = viewPixmaps.begin(); pix != viewPixmaps.end(); pix++) {
+ (*pix)->SetGlobals(globals);
+ }
+}
+
+void cTemplateViewElement::SetParameters(vector<pair<string, string> > ¶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<cTemplatePixmap*>::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<cTemplatePixmap*>::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<cTemplatePixmap*>::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 <iostream>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string>
+#include <vector>
+#include <map>
+#include <set>
+#include <sstream>
+
+#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<cTemplatePixmap*> viewPixmaps;
+ vector<cTemplatePixmap*>::iterator pixIterator;
+ int pixOffset;
+public:
+ cTemplateViewElement(void);
+ virtual ~cTemplateViewElement(void);
+ void SetParameters(vector<pair<string, string> > ¶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<string,string>::iterator hit = globals->fonts.find(fontNameToken);
+ if (hit != globals->fonts.end()) {
+ fontName = hit->second;
+ } else {
+ map<string,string>::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 <iostream> +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <string> +#include <vector> +#include <map> +#include <set> +#include <sstream> + +#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 <iostream> +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <string> +#include <vector> +#include <map> +#include <set> + +#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<pair<string, string> > 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<string, tColor>(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<string, int>(name, val)); + } else if (!type.compare("string")) { + globals->stringVars.insert(pair<string, string>(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<string, string>((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<string, string>((const char*)language, (const char*)value)); + if (language) + xmlFree(language); + if (value) + xmlFree(value); + nodeTrans = nodeTrans->next; + } + globals->translations.insert(pair<string, map < string, string > >((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<pair<string, string> > 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<pair<string, string> > 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<pair<string, string> > 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<pair<string, string> > attribsCur; + ParseAttributes(attrCur, node, attribsCur); + currentElement->SetGlobals(globals); + currentElement->SetParameters(attribsCur); + bool debugCurrent = false; + for (vector<pair<string, string> >::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<pair<string, string> > 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<pair<string, string> > 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<pair<string, string> > 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<pair<string, string> > 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<pair<string, string> > 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<pair<string, string> > 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<pair<string, string> > &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<string, string>((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<string, string>((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<pair<string, string> > attribs; + ParseAttributes(attr, node, attribs); + for (vector<pair<string, string> >::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 <iostream> +#include <stdio.h> +#include <stdlib.h> +#include <string> +#include <vector> +#include <map> +#include <set> +#include <libxml/parser.h> +#include <libxml/tree.h> +#include <libxml/xmlerror.h> +#include <vdr/plugin.h> + +#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<pair<string, string> > &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 <string> +#include <list> +#include <memory> +#include <set> +#include <vdr/osdbase.h> + +// Data structure for service "Epgsearch-search-v1.0" +struct Epgsearch_search_v1_0 +{ +// in + char* query; // search term + int mode; // search mode (0=phrase, 1=and, 2=or, 3=regular expression) + int channelNr; // channel number to search in (0=any) + bool useTitle; // search in title + bool useSubTitle; // search in subtitle + bool useDescription; // search in description +// out + cOsdMenu* pResultMenu; // pointer to the menu of results +}; + +// Data structure for service "Epgsearch-exttimeredit-v1.0" +struct Epgsearch_exttimeredit_v1_0 +{ +// in + cTimer* timer; // pointer to the timer to edit + bool bNew; // flag that indicates, if this is a new timer or an existing one + const cEvent* event; // pointer to the event corresponding to this timer (may be NULL) +// out + cOsdMenu* pTimerMenu; // pointer to the menu of results +}; + +// Data structure for service "Epgsearch-updatesearchtimers-v1.0" +struct Epgsearch_updatesearchtimers_v1_0 +{ +// in + bool showMessage; // inform via osd when finished? +}; + +// Data structure for service "Epgsearch-osdmessage-v1.0" +struct Epgsearch_osdmessage_v1_0 +{ +// in + char* message; // the message to display + eMessageType type; +}; + +// Data structure for service "EpgsearchMenu-v1.0" +struct EpgSearchMenu_v1_0 +{ +// in +// out + cOsdMenu* Menu; // pointer to the menu +}; + +// Data structure for service "Epgsearch-lastconflictinfo-v1.0" +struct Epgsearch_lastconflictinfo_v1_0 +{ +// in +// out + time_t nextConflict; // next conflict date, 0 if none + int relevantConflicts; // number of relevant conflicts + int totalConflicts; // total number of conflicts +}; + +// Data structure for service "Epgsearch-searchresults-v1.0" +struct Epgsearch_searchresults_v1_0 +{ +// in + char* query; // search term + int mode; // search mode (0=phrase, 1=and, 2=or, 3=regular expression) + int channelNr; // channel number to search in (0=any) + bool useTitle; // search in title + bool useSubTitle; // search in subtitle + bool useDescription; // search in description +// out + + class cServiceSearchResult : public cListObject + { + public: + const cEvent* event; + cServiceSearchResult(const cEvent* Event) : event(Event) {} + }; + + cList<cServiceSearchResult>* pResultList; // pointer to the results +}; + +// Data structure for service "Epgsearch-switchtimer-v1.0" +struct Epgsearch_switchtimer_v1_0 +{ +// in + const cEvent* event; + int mode; // mode (0=query existance, 1=add/modify, 2=delete) +// in/out + int switchMinsBefore; + int announceOnly; +// out + bool success; // result +}; + +// Data structures for service "Epgsearch-services-v1.0" +class cServiceHandler +{ + public: + virtual std::list<std::string> SearchTimerList() = 0; + // returns a list of search timer entries in the same format as used in epgsearch.conf + virtual int AddSearchTimer(const std::string&) = 0; + // adds a new search timer and returns its ID (-1 on error) + virtual bool ModSearchTimer(const std::string&) = 0; + // edits an existing search timer and returns success + virtual bool DelSearchTimer(int) = 0; + // deletes search timer with given ID and returns success + virtual std::list<std::string> QuerySearchTimer(int) = 0; + // returns the search result of the searchtimer with given ID in the same format as used in SVDRP command 'QRYS' (->MANUAL) + virtual std::list<std::string> QuerySearch(std::string) = 0; + // returns the search result of the searchtimer with given settings in the same format as used in SVDRP command 'QRYS' (->MANUAL) + virtual std::list<std::string> ExtEPGInfoList() = 0; + // returns a list of extended EPG categories in the same format as used in epgsearchcats.conf + virtual std::list<std::string> ChanGrpList() = 0; + // returns a list of channel groups maintained by epgsearch + virtual std::list<std::string> BlackList() = 0; + // returns a list of blacklists in the same format as used in epgsearchblacklists.conf + virtual std::set<std::string> DirectoryList() = 0; + // List of all recording directories used in recordings, timers, search timers or in epgsearchdirs.conf + virtual ~cServiceHandler() {} + // Read a setup value + virtual std::string ReadSetupValue(const std::string& entry) = 0; + // Write a setup value + virtual bool WriteSetupValue(const std::string& entry, const std::string& value) = 0; +}; + +struct Epgsearch_services_v1_0 +{ +// in/out + std::auto_ptr<cServiceHandler> handler; +}; + +#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 <vdr@schmirler.de> + * + * 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 <vdr/timers.h> +#include <vdr/epg.h> +#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 <string> +#include <vector> +#include <vdr/epg.h> +#include <vdr/recording.h> + +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<cActor> 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<cActor> actors; + std::vector<cTvMedia> posters; + std::vector<cTvMedia> banners; + std::vector<cTvMedia> 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 @@ -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<cOsdItem>::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<cOsdItem>::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<cOsdItem>::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<cOsdItem>::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 @@ -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 <getopt.h> +#include <vdr/plugin.h> +#include <vdr/skinlcars.h> + +#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>, --skinpath=<SKINPATH> Set directory where xml skins are stored\n" + " -e <EPGIMAGESPATH>, --epgimages=<IMAGESPATH> 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 Binary files differnew file mode 100644 index 0000000..5b8614a --- /dev/null +++ b/skins/default/graphics/icons/ico_ac3.png diff --git a/skins/default/graphics/icons/ico_activetimer.png b/skins/default/graphics/icons/ico_activetimer.png Binary files differnew file mode 100644 index 0000000..af4c33c --- /dev/null +++ b/skins/default/graphics/icons/ico_activetimer.png diff --git a/skins/default/graphics/icons/ico_channelsep.png b/skins/default/graphics/icons/ico_channelsep.png Binary files differnew file mode 100644 index 0000000..bf51238 --- /dev/null +++ b/skins/default/graphics/icons/ico_channelsep.png diff --git a/skins/default/graphics/icons/ico_crypt_off.png b/skins/default/graphics/icons/ico_crypt_off.png Binary files differnew file mode 100644 index 0000000..b612aec --- /dev/null +++ b/skins/default/graphics/icons/ico_crypt_off.png diff --git a/skins/default/graphics/icons/ico_crypt_on.png b/skins/default/graphics/icons/ico_crypt_on.png Binary files differnew file mode 100644 index 0000000..55abed4 --- /dev/null +++ b/skins/default/graphics/icons/ico_crypt_on.png diff --git a/skins/default/graphics/icons/ico_cutted.png b/skins/default/graphics/icons/ico_cutted.png Binary files differnew file mode 100644 index 0000000..b90c9c1 --- /dev/null +++ b/skins/default/graphics/icons/ico_cutted.png diff --git a/skins/default/graphics/icons/ico_discusage.png b/skins/default/graphics/icons/ico_discusage.png Binary files differnew file mode 100644 index 0000000..f40fcd9 --- /dev/null +++ b/skins/default/graphics/icons/ico_discusage.png diff --git a/skins/default/graphics/icons/ico_dolby_off.png b/skins/default/graphics/icons/ico_dolby_off.png Binary files differnew file mode 100644 index 0000000..17815f5 --- /dev/null +++ b/skins/default/graphics/icons/ico_dolby_off.png diff --git a/skins/default/graphics/icons/ico_dolby_on.png b/skins/default/graphics/icons/ico_dolby_on.png Binary files differnew file mode 100644 index 0000000..c06c18e --- /dev/null +++ b/skins/default/graphics/icons/ico_dolby_on.png diff --git a/skins/default/graphics/icons/ico_ff.png b/skins/default/graphics/icons/ico_ff.png Binary files differnew file mode 100644 index 0000000..5ffbe4b --- /dev/null +++ b/skins/default/graphics/icons/ico_ff.png diff --git a/skins/default/graphics/icons/ico_ff_1x.png b/skins/default/graphics/icons/ico_ff_1x.png Binary files differnew file mode 100644 index 0000000..96a74bc --- /dev/null +++ b/skins/default/graphics/icons/ico_ff_1x.png diff --git a/skins/default/graphics/icons/ico_ff_2x.png b/skins/default/graphics/icons/ico_ff_2x.png Binary files differnew file mode 100644 index 0000000..54657bf --- /dev/null +++ b/skins/default/graphics/icons/ico_ff_2x.png diff --git a/skins/default/graphics/icons/ico_ff_3x.png b/skins/default/graphics/icons/ico_ff_3x.png Binary files differnew file mode 100644 index 0000000..ac21eca --- /dev/null +++ b/skins/default/graphics/icons/ico_ff_3x.png diff --git a/skins/default/graphics/icons/ico_ff_off.png b/skins/default/graphics/icons/ico_ff_off.png Binary files differnew file mode 100644 index 0000000..5a9ab50 --- /dev/null +++ b/skins/default/graphics/icons/ico_ff_off.png diff --git a/skins/default/graphics/icons/ico_hd_off.png b/skins/default/graphics/icons/ico_hd_off.png Binary files differnew file mode 100644 index 0000000..cd0492a --- /dev/null +++ b/skins/default/graphics/icons/ico_hd_off.png diff --git a/skins/default/graphics/icons/ico_hd_on.png b/skins/default/graphics/icons/ico_hd_on.png Binary files differnew file mode 100644 index 0000000..5f6cfa5 --- /dev/null +++ b/skins/default/graphics/icons/ico_hd_on.png diff --git a/skins/default/graphics/icons/ico_line_off.png b/skins/default/graphics/icons/ico_line_off.png Binary files differnew file mode 100644 index 0000000..94591ee --- /dev/null +++ b/skins/default/graphics/icons/ico_line_off.png diff --git a/skins/default/graphics/icons/ico_line_on.png b/skins/default/graphics/icons/ico_line_on.png Binary files differnew file mode 100644 index 0000000..1584078 --- /dev/null +++ b/skins/default/graphics/icons/ico_line_on.png diff --git a/skins/default/graphics/icons/ico_mute.png b/skins/default/graphics/icons/ico_mute.png Binary files differnew file mode 100644 index 0000000..4eefc75 --- /dev/null +++ b/skins/default/graphics/icons/ico_mute.png diff --git a/skins/default/graphics/icons/ico_pause.png b/skins/default/graphics/icons/ico_pause.png Binary files differnew file mode 100644 index 0000000..405a097 --- /dev/null +++ b/skins/default/graphics/icons/ico_pause.png diff --git a/skins/default/graphics/icons/ico_pause_off.png b/skins/default/graphics/icons/ico_pause_off.png Binary files differnew file mode 100644 index 0000000..6f02e39 --- /dev/null +++ b/skins/default/graphics/icons/ico_pause_off.png diff --git a/skins/default/graphics/icons/ico_play.png b/skins/default/graphics/icons/ico_play.png Binary files differnew file mode 100644 index 0000000..02a01c0 --- /dev/null +++ b/skins/default/graphics/icons/ico_play.png diff --git a/skins/default/graphics/icons/ico_play_off.png b/skins/default/graphics/icons/ico_play_off.png Binary files differnew file mode 100644 index 0000000..d87322a --- /dev/null +++ b/skins/default/graphics/icons/ico_play_off.png diff --git a/skins/default/graphics/icons/ico_rec_off.png b/skins/default/graphics/icons/ico_rec_off.png Binary files differnew file mode 100644 index 0000000..224baea --- /dev/null +++ b/skins/default/graphics/icons/ico_rec_off.png diff --git a/skins/default/graphics/icons/ico_rec_on.png b/skins/default/graphics/icons/ico_rec_on.png Binary files differnew file mode 100644 index 0000000..7bc18a7 --- /dev/null +++ b/skins/default/graphics/icons/ico_rec_on.png diff --git a/skins/default/graphics/icons/ico_recfolder.png b/skins/default/graphics/icons/ico_recfolder.png Binary files differnew file mode 100644 index 0000000..e3df65b --- /dev/null +++ b/skins/default/graphics/icons/ico_recfolder.png diff --git a/skins/default/graphics/icons/ico_recnew.png b/skins/default/graphics/icons/ico_recnew.png Binary files differnew file mode 100644 index 0000000..b9166ba --- /dev/null +++ b/skins/default/graphics/icons/ico_recnew.png diff --git a/skins/default/graphics/icons/ico_rew.png b/skins/default/graphics/icons/ico_rew.png Binary files differnew file mode 100644 index 0000000..1505f79 --- /dev/null +++ b/skins/default/graphics/icons/ico_rew.png diff --git a/skins/default/graphics/icons/ico_rew_1x.png b/skins/default/graphics/icons/ico_rew_1x.png Binary files differnew file mode 100644 index 0000000..6ddbde4 --- /dev/null +++ b/skins/default/graphics/icons/ico_rew_1x.png diff --git a/skins/default/graphics/icons/ico_rew_2x.png b/skins/default/graphics/icons/ico_rew_2x.png Binary files differnew file mode 100644 index 0000000..9b7ee52 --- /dev/null +++ b/skins/default/graphics/icons/ico_rew_2x.png diff --git a/skins/default/graphics/icons/ico_rew_3x.png b/skins/default/graphics/icons/ico_rew_3x.png Binary files differnew file mode 100644 index 0000000..4a3abeb --- /dev/null +++ b/skins/default/graphics/icons/ico_rew_3x.png diff --git a/skins/default/graphics/icons/ico_rew_off.png b/skins/default/graphics/icons/ico_rew_off.png Binary files differnew file mode 100644 index 0000000..a84a7f3 --- /dev/null +++ b/skins/default/graphics/icons/ico_rew_off.png diff --git a/skins/default/graphics/icons/ico_stereo.png b/skins/default/graphics/icons/ico_stereo.png Binary files differnew file mode 100644 index 0000000..7f3610d --- /dev/null +++ b/skins/default/graphics/icons/ico_stereo.png diff --git a/skins/default/graphics/icons/ico_timer_active.png b/skins/default/graphics/icons/ico_timer_active.png Binary files differnew file mode 100644 index 0000000..28c2f81 --- /dev/null +++ b/skins/default/graphics/icons/ico_timer_active.png diff --git a/skins/default/graphics/icons/ico_timer_inactive.png b/skins/default/graphics/icons/ico_timer_inactive.png Binary files differnew file mode 100644 index 0000000..c4b1860 --- /dev/null +++ b/skins/default/graphics/icons/ico_timer_inactive.png diff --git a/skins/default/graphics/icons/ico_timer_recording.png b/skins/default/graphics/icons/ico_timer_recording.png Binary files differnew file mode 100644 index 0000000..86dc66b --- /dev/null +++ b/skins/default/graphics/icons/ico_timer_recording.png diff --git a/skins/default/graphics/icons/ico_txt_off.png b/skins/default/graphics/icons/ico_txt_off.png Binary files differnew file mode 100644 index 0000000..a445bc5 --- /dev/null +++ b/skins/default/graphics/icons/ico_txt_off.png diff --git a/skins/default/graphics/icons/ico_txt_on.png b/skins/default/graphics/icons/ico_txt_on.png Binary files differnew file mode 100644 index 0000000..ad14ff7 --- /dev/null +++ b/skins/default/graphics/icons/ico_txt_on.png diff --git a/skins/default/graphics/icons/ico_volume.png b/skins/default/graphics/icons/ico_volume.png Binary files differnew file mode 100644 index 0000000..3a72514 --- /dev/null +++ b/skins/default/graphics/icons/ico_volume.png diff --git a/skins/default/graphics/icons/ico_widescreen_off.png b/skins/default/graphics/icons/ico_widescreen_off.png Binary files differnew file mode 100644 index 0000000..dffd6a5 --- /dev/null +++ b/skins/default/graphics/icons/ico_widescreen_off.png diff --git a/skins/default/graphics/icons/ico_widescreen_on.png b/skins/default/graphics/icons/ico_widescreen_on.png Binary files differnew file mode 100644 index 0000000..876bb55 --- /dev/null +++ b/skins/default/graphics/icons/ico_widescreen_on.png diff --git a/skins/default/graphics/menuicons/customicons/Applikationen.png b/skins/default/graphics/menuicons/customicons/Applikationen.png Binary files differnew file mode 100644 index 0000000..3c3b616 --- /dev/null +++ b/skins/default/graphics/menuicons/customicons/Applikationen.png diff --git a/skins/default/graphics/menuicons/customicons/Audio.png b/skins/default/graphics/menuicons/customicons/Audio.png Binary files differnew file mode 100644 index 0000000..ff387fe --- /dev/null +++ b/skins/default/graphics/menuicons/customicons/Audio.png diff --git a/skins/default/graphics/menuicons/customicons/Aufnahmen-Liste aktualisieren.png b/skins/default/graphics/menuicons/customicons/Aufnahmen-Liste aktualisieren.png Binary files differnew file mode 100644 index 0000000..3cdddc9 --- /dev/null +++ b/skins/default/graphics/menuicons/customicons/Aufnahmen-Liste aktualisieren.png diff --git a/skins/default/graphics/menuicons/customicons/Dienstprogramme.png b/skins/default/graphics/menuicons/customicons/Dienstprogramme.png Binary files differnew file mode 100644 index 0000000..793aba6 --- /dev/null +++ b/skins/default/graphics/menuicons/customicons/Dienstprogramme.png diff --git a/skins/default/graphics/menuicons/customicons/FireFox.png b/skins/default/graphics/menuicons/customicons/FireFox.png Binary files differnew file mode 100644 index 0000000..192fadc --- /dev/null +++ b/skins/default/graphics/menuicons/customicons/FireFox.png diff --git a/skins/default/graphics/menuicons/customicons/Info.png b/skins/default/graphics/menuicons/customicons/Info.png Binary files differnew file mode 100644 index 0000000..6737431 --- /dev/null +++ b/skins/default/graphics/menuicons/customicons/Info.png diff --git a/skins/default/graphics/menuicons/customicons/Internet.png b/skins/default/graphics/menuicons/customicons/Internet.png Binary files differnew file mode 100644 index 0000000..f3db150 --- /dev/null +++ b/skins/default/graphics/menuicons/customicons/Internet.png diff --git a/skins/default/graphics/menuicons/customicons/Medien.png b/skins/default/graphics/menuicons/customicons/Medien.png Binary files differnew file mode 100644 index 0000000..0ce2360 --- /dev/null +++ b/skins/default/graphics/menuicons/customicons/Medien.png diff --git a/skins/default/graphics/menuicons/customicons/Rechner neu starten.png b/skins/default/graphics/menuicons/customicons/Rechner neu starten.png Binary files differnew file mode 100644 index 0000000..5783ccf --- /dev/null +++ b/skins/default/graphics/menuicons/customicons/Rechner neu starten.png diff --git a/skins/default/graphics/menuicons/customicons/Remote wakeup.png b/skins/default/graphics/menuicons/customicons/Remote wakeup.png Binary files differnew file mode 100644 index 0000000..1cd2f6e --- /dev/null +++ b/skins/default/graphics/menuicons/customicons/Remote wakeup.png diff --git a/skins/default/graphics/menuicons/customicons/Spiele.png b/skins/default/graphics/menuicons/customicons/Spiele.png Binary files differnew file mode 100644 index 0000000..8e07161 --- /dev/null +++ b/skins/default/graphics/menuicons/customicons/Spiele.png diff --git a/skins/default/graphics/menuicons/customicons/System herunterfahren.png b/skins/default/graphics/menuicons/customicons/System herunterfahren.png Binary files differnew file mode 100644 index 0000000..e0234df --- /dev/null +++ b/skins/default/graphics/menuicons/customicons/System herunterfahren.png diff --git a/skins/default/graphics/menuicons/customicons/System.png b/skins/default/graphics/menuicons/customicons/System.png Binary files differnew file mode 100644 index 0000000..81d100e --- /dev/null +++ b/skins/default/graphics/menuicons/customicons/System.png diff --git a/skins/default/graphics/menuicons/customicons/Tools.png b/skins/default/graphics/menuicons/customicons/Tools.png Binary files differnew file mode 100644 index 0000000..cf328ef --- /dev/null +++ b/skins/default/graphics/menuicons/customicons/Tools.png diff --git a/skins/default/graphics/menuicons/customicons/Tunderbird.png b/skins/default/graphics/menuicons/customicons/Tunderbird.png Binary files differnew file mode 100644 index 0000000..5ae27e0 --- /dev/null +++ b/skins/default/graphics/menuicons/customicons/Tunderbird.png diff --git a/skins/default/graphics/menuicons/customicons/USB Massenspeicher sicher entfernen.png b/skins/default/graphics/menuicons/customicons/USB Massenspeicher sicher entfernen.png Binary files differnew file mode 100644 index 0000000..cd7b81c --- /dev/null +++ b/skins/default/graphics/menuicons/customicons/USB Massenspeicher sicher entfernen.png diff --git a/skins/default/graphics/menuicons/customicons/VDR neu starten.png b/skins/default/graphics/menuicons/customicons/VDR neu starten.png Binary files differnew file mode 100644 index 0000000..14904ca --- /dev/null +++ b/skins/default/graphics/menuicons/customicons/VDR neu starten.png diff --git a/skins/default/graphics/menuicons/customicons/Video.png b/skins/default/graphics/menuicons/customicons/Video.png Binary files differnew file mode 100644 index 0000000..490ca4b --- /dev/null +++ b/skins/default/graphics/menuicons/customicons/Video.png diff --git a/skins/default/graphics/menuicons/customicons/Web.png b/skins/default/graphics/menuicons/customicons/Web.png Binary files differnew file mode 100644 index 0000000..20260e3 --- /dev/null +++ b/skins/default/graphics/menuicons/customicons/Web.png diff --git a/skins/default/graphics/menuicons/customicons/XBMC.png b/skins/default/graphics/menuicons/customicons/XBMC.png Binary files differnew file mode 100644 index 0000000..c7c4c04 --- /dev/null +++ b/skins/default/graphics/menuicons/customicons/XBMC.png diff --git a/skins/default/graphics/menuicons/customicons/Xterm.png b/skins/default/graphics/menuicons/customicons/Xterm.png Binary files differnew file mode 100644 index 0000000..fa75282 --- /dev/null +++ b/skins/default/graphics/menuicons/customicons/Xterm.png diff --git a/skins/default/graphics/menuicons/customicons/audiovideo.png b/skins/default/graphics/menuicons/customicons/audiovideo.png Binary files differnew file mode 100644 index 0000000..726538d --- /dev/null +++ b/skins/default/graphics/menuicons/customicons/audiovideo.png diff --git a/skins/default/graphics/menuicons/customicons/markad_status.png b/skins/default/graphics/menuicons/customicons/markad_status.png Binary files differnew file mode 100644 index 0000000..4fdc7a4 --- /dev/null +++ b/skins/default/graphics/menuicons/customicons/markad_status.png diff --git a/skins/default/graphics/menuicons/customicons/schneiden_abbrechen.png b/skins/default/graphics/menuicons/customicons/schneiden_abbrechen.png Binary files differnew file mode 100644 index 0000000..b2e0bd3 --- /dev/null +++ b/skins/default/graphics/menuicons/customicons/schneiden_abbrechen.png diff --git a/skins/default/graphics/menuicons/customicons/tux.png b/skins/default/graphics/menuicons/customicons/tux.png Binary files differnew file mode 100644 index 0000000..c5b4742 --- /dev/null +++ b/skins/default/graphics/menuicons/customicons/tux.png diff --git a/skins/default/graphics/menuicons/customicons/usb.png b/skins/default/graphics/menuicons/customicons/usb.png Binary files differnew file mode 100644 index 0000000..c4db1d4 --- /dev/null +++ b/skins/default/graphics/menuicons/customicons/usb.png diff --git a/skins/default/graphics/menuicons/customicons/vdrlogo.png b/skins/default/graphics/menuicons/customicons/vdrlogo.png Binary files differnew file mode 100644 index 0000000..037a191 --- /dev/null +++ b/skins/default/graphics/menuicons/customicons/vdrlogo.png diff --git a/skins/default/graphics/menuicons/customicons/yaicon_blue.png b/skins/default/graphics/menuicons/customicons/yaicon_blue.png Binary files differnew file mode 100644 index 0000000..2c49273 --- /dev/null +++ b/skins/default/graphics/menuicons/customicons/yaicon_blue.png diff --git a/skins/default/graphics/menuicons/pluginicons/admin.png b/skins/default/graphics/menuicons/pluginicons/admin.png Binary files differnew file mode 100644 index 0000000..cf328ef --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/admin.png diff --git a/skins/default/graphics/menuicons/pluginicons/arghdirector.png b/skins/default/graphics/menuicons/pluginicons/arghdirector.png Binary files differnew file mode 100644 index 0000000..bbd221a --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/arghdirector.png diff --git a/skins/default/graphics/menuicons/pluginicons/autostart.png b/skins/default/graphics/menuicons/pluginicons/autostart.png Binary files differnew file mode 100644 index 0000000..6fdb1bb --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/autostart.png diff --git a/skins/default/graphics/menuicons/pluginicons/avahi4vdr.png b/skins/default/graphics/menuicons/pluginicons/avahi4vdr.png Binary files differnew file mode 100644 index 0000000..044e71d --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/avahi4vdr.png diff --git a/skins/default/graphics/menuicons/pluginicons/avards.png b/skins/default/graphics/menuicons/pluginicons/avards.png Binary files differnew file mode 100644 index 0000000..cf8d037 --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/avards.png diff --git a/skins/default/graphics/menuicons/pluginicons/block.png b/skins/default/graphics/menuicons/pluginicons/block.png Binary files differnew file mode 100644 index 0000000..86127c2 --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/block.png diff --git a/skins/default/graphics/menuicons/pluginicons/burn.png b/skins/default/graphics/menuicons/pluginicons/burn.png Binary files differnew file mode 100644 index 0000000..305d7ff --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/burn.png diff --git a/skins/default/graphics/menuicons/pluginicons/cdplayer.png b/skins/default/graphics/menuicons/pluginicons/cdplayer.png Binary files differnew file mode 100644 index 0000000..89a6c19 --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/cdplayer.png diff --git a/skins/default/graphics/menuicons/pluginicons/chanman.png b/skins/default/graphics/menuicons/pluginicons/chanman.png Binary files differnew file mode 100644 index 0000000..a73e83c --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/chanman.png diff --git a/skins/default/graphics/menuicons/pluginicons/check.png b/skins/default/graphics/menuicons/pluginicons/check.png Binary files differnew file mode 100644 index 0000000..d487a24 --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/check.png diff --git a/skins/default/graphics/menuicons/pluginicons/conflictcheckonly.png b/skins/default/graphics/menuicons/pluginicons/conflictcheckonly.png Binary files differnew file mode 100644 index 0000000..7f832bd --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/conflictcheckonly.png diff --git a/skins/default/graphics/menuicons/pluginicons/ddci.png b/skins/default/graphics/menuicons/pluginicons/ddci.png Binary files differnew file mode 100644 index 0000000..4ad459c --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/ddci.png diff --git a/skins/default/graphics/menuicons/pluginicons/devstatus.png b/skins/default/graphics/menuicons/pluginicons/devstatus.png Binary files differnew file mode 100644 index 0000000..96c0ec1 --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/devstatus.png diff --git a/skins/default/graphics/menuicons/pluginicons/dummydevice.png b/skins/default/graphics/menuicons/pluginicons/dummydevice.png Binary files differnew file mode 100644 index 0000000..11fd707 --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/dummydevice.png diff --git a/skins/default/graphics/menuicons/pluginicons/duplicates.png b/skins/default/graphics/menuicons/pluginicons/duplicates.png Binary files differnew file mode 100644 index 0000000..dc1be57 --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/duplicates.png diff --git a/skins/default/graphics/menuicons/pluginicons/dvbapi.png b/skins/default/graphics/menuicons/pluginicons/dvbapi.png Binary files differnew file mode 100644 index 0000000..b966461 --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/dvbapi.png diff --git a/skins/default/graphics/menuicons/pluginicons/dvbhddevice.png b/skins/default/graphics/menuicons/pluginicons/dvbhddevice.png Binary files differnew file mode 100644 index 0000000..b874297 --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/dvbhddevice.png diff --git a/skins/default/graphics/menuicons/pluginicons/dvbsddevice.png b/skins/default/graphics/menuicons/pluginicons/dvbsddevice.png Binary files differnew file mode 100644 index 0000000..106184e --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/dvbsddevice.png diff --git a/skins/default/graphics/menuicons/pluginicons/dynamite.png b/skins/default/graphics/menuicons/pluginicons/dynamite.png Binary files differnew file mode 100644 index 0000000..28ea35a --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/dynamite.png diff --git a/skins/default/graphics/menuicons/pluginicons/eepg.png b/skins/default/graphics/menuicons/pluginicons/eepg.png Binary files differnew file mode 100644 index 0000000..3938b96 --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/eepg.png diff --git a/skins/default/graphics/menuicons/pluginicons/epg2vdr.png b/skins/default/graphics/menuicons/pluginicons/epg2vdr.png Binary files differnew file mode 100644 index 0000000..ac8757e --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/epg2vdr.png diff --git a/skins/default/graphics/menuicons/pluginicons/epgsearch.png b/skins/default/graphics/menuicons/pluginicons/epgsearch.png Binary files differnew file mode 100644 index 0000000..5eab415 --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/epgsearch.png diff --git a/skins/default/graphics/menuicons/pluginicons/epgsearchonly.png b/skins/default/graphics/menuicons/pluginicons/epgsearchonly.png Binary files differnew file mode 100644 index 0000000..b5186e7 --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/epgsearchonly.png diff --git a/skins/default/graphics/menuicons/pluginicons/epgsync.png b/skins/default/graphics/menuicons/pluginicons/epgsync.png Binary files differnew file mode 100644 index 0000000..5c14009 --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/epgsync.png diff --git a/skins/default/graphics/menuicons/pluginicons/externalplayer.png b/skins/default/graphics/menuicons/pluginicons/externalplayer.png Binary files differnew file mode 100644 index 0000000..2bd67db --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/externalplayer.png diff --git a/skins/default/graphics/menuicons/pluginicons/extrecmenu.png b/skins/default/graphics/menuicons/pluginicons/extrecmenu.png Binary files differnew file mode 100644 index 0000000..6f613f1 --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/extrecmenu.png diff --git a/skins/default/graphics/menuicons/pluginicons/favorites.png b/skins/default/graphics/menuicons/pluginicons/favorites.png Binary files differnew file mode 100644 index 0000000..409c852 --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/favorites.png diff --git a/skins/default/graphics/menuicons/pluginicons/femon.png b/skins/default/graphics/menuicons/pluginicons/femon.png Binary files differnew file mode 100644 index 0000000..e87b711 --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/femon.png diff --git a/skins/default/graphics/menuicons/pluginicons/fepg.png b/skins/default/graphics/menuicons/pluginicons/fepg.png Binary files differnew file mode 100644 index 0000000..65023ed --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/fepg.png diff --git a/skins/default/graphics/menuicons/pluginicons/filebrowser.png b/skins/default/graphics/menuicons/pluginicons/filebrowser.png Binary files differnew file mode 100644 index 0000000..d3f90e0 --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/filebrowser.png diff --git a/skins/default/graphics/menuicons/pluginicons/fritzbox.png b/skins/default/graphics/menuicons/pluginicons/fritzbox.png Binary files differnew file mode 100644 index 0000000..7bfc229 --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/fritzbox.png diff --git a/skins/default/graphics/menuicons/pluginicons/graphlcd.png b/skins/default/graphics/menuicons/pluginicons/graphlcd.png Binary files differnew file mode 100644 index 0000000..39ffd35 --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/graphlcd.png diff --git a/skins/default/graphics/menuicons/pluginicons/graphtft.png b/skins/default/graphics/menuicons/pluginicons/graphtft.png Binary files differnew file mode 100644 index 0000000..39ffd35 --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/graphtft.png diff --git a/skins/default/graphics/menuicons/pluginicons/image.png b/skins/default/graphics/menuicons/pluginicons/image.png Binary files differnew file mode 100644 index 0000000..33644e0 --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/image.png diff --git a/skins/default/graphics/menuicons/pluginicons/imonlcd.png b/skins/default/graphics/menuicons/pluginicons/imonlcd.png Binary files differnew file mode 100644 index 0000000..3d34fc4 --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/imonlcd.png diff --git a/skins/default/graphics/menuicons/pluginicons/iptv.png b/skins/default/graphics/menuicons/pluginicons/iptv.png Binary files differnew file mode 100644 index 0000000..4494ddc --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/iptv.png diff --git a/skins/default/graphics/menuicons/pluginicons/lcdproc.png b/skins/default/graphics/menuicons/pluginicons/lcdproc.png Binary files differnew file mode 100644 index 0000000..3d34fc4 --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/lcdproc.png diff --git a/skins/default/graphics/menuicons/pluginicons/mailbox.png b/skins/default/graphics/menuicons/pluginicons/mailbox.png Binary files differnew file mode 100644 index 0000000..1bc76e8 --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/mailbox.png diff --git a/skins/default/graphics/menuicons/pluginicons/makemkv.png b/skins/default/graphics/menuicons/pluginicons/makemkv.png Binary files differnew file mode 100644 index 0000000..41cddf1 --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/makemkv.png diff --git a/skins/default/graphics/menuicons/pluginicons/markad.png b/skins/default/graphics/menuicons/pluginicons/markad.png Binary files differnew file mode 100644 index 0000000..b3defaf --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/markad.png diff --git a/skins/default/graphics/menuicons/pluginicons/mlist.png b/skins/default/graphics/menuicons/pluginicons/mlist.png Binary files differnew file mode 100644 index 0000000..19c367f --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/mlist.png diff --git a/skins/default/graphics/menuicons/pluginicons/music.png b/skins/default/graphics/menuicons/pluginicons/music.png Binary files differnew file mode 100644 index 0000000..abb012e --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/music.png diff --git a/skins/default/graphics/menuicons/pluginicons/noepg.png b/skins/default/graphics/menuicons/pluginicons/noepg.png Binary files differnew file mode 100644 index 0000000..eb9410d --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/noepg.png diff --git a/skins/default/graphics/menuicons/pluginicons/nordlichtsepg.png b/skins/default/graphics/menuicons/pluginicons/nordlichtsepg.png Binary files differnew file mode 100644 index 0000000..3ee3fa2 --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/nordlichtsepg.png diff --git a/skins/default/graphics/menuicons/pluginicons/osdteletext.png b/skins/default/graphics/menuicons/pluginicons/osdteletext.png Binary files differnew file mode 100644 index 0000000..664e770 --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/osdteletext.png diff --git a/skins/default/graphics/menuicons/pluginicons/peer.png b/skins/default/graphics/menuicons/pluginicons/peer.png Binary files differnew file mode 100644 index 0000000..998d568 --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/peer.png diff --git a/skins/default/graphics/menuicons/pluginicons/play.png b/skins/default/graphics/menuicons/pluginicons/play.png Binary files differnew file mode 100644 index 0000000..2848fc6 --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/play.png diff --git a/skins/default/graphics/menuicons/pluginicons/pvrinput.png b/skins/default/graphics/menuicons/pluginicons/pvrinput.png Binary files differnew file mode 100644 index 0000000..724f698 --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/pvrinput.png diff --git a/skins/default/graphics/menuicons/pluginicons/quickepgsearch.png b/skins/default/graphics/menuicons/pluginicons/quickepgsearch.png Binary files differnew file mode 100644 index 0000000..76a31f4 --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/quickepgsearch.png diff --git a/skins/default/graphics/menuicons/pluginicons/radio.png b/skins/default/graphics/menuicons/pluginicons/radio.png Binary files differnew file mode 100644 index 0000000..193b7d4 --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/radio.png diff --git a/skins/default/graphics/menuicons/pluginicons/remote.png b/skins/default/graphics/menuicons/pluginicons/remote.png Binary files differnew file mode 100644 index 0000000..7f46b1b --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/remote.png diff --git a/skins/default/graphics/menuicons/pluginicons/remotetimers.png b/skins/default/graphics/menuicons/pluginicons/remotetimers.png Binary files differnew file mode 100644 index 0000000..fae3b79 --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/remotetimers.png diff --git a/skins/default/graphics/menuicons/pluginicons/rssreader.png b/skins/default/graphics/menuicons/pluginicons/rssreader.png Binary files differnew file mode 100644 index 0000000..db538f0 --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/rssreader.png diff --git a/skins/default/graphics/menuicons/pluginicons/sc.png b/skins/default/graphics/menuicons/pluginicons/sc.png Binary files differnew file mode 100644 index 0000000..2472d6c --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/sc.png diff --git a/skins/default/graphics/menuicons/pluginicons/scraper2vdr.png b/skins/default/graphics/menuicons/pluginicons/scraper2vdr.png Binary files differnew file mode 100644 index 0000000..a106cb5 --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/scraper2vdr.png diff --git a/skins/default/graphics/menuicons/pluginicons/screenshot.png b/skins/default/graphics/menuicons/pluginicons/screenshot.png Binary files differnew file mode 100644 index 0000000..be9b4d5 --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/screenshot.png diff --git a/skins/default/graphics/menuicons/pluginicons/seduatmo.png b/skins/default/graphics/menuicons/pluginicons/seduatmo.png Binary files differnew file mode 100644 index 0000000..4b5292f --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/seduatmo.png diff --git a/skins/default/graphics/menuicons/pluginicons/skyselectfeeds.png b/skins/default/graphics/menuicons/pluginicons/skyselectfeeds.png Binary files differnew file mode 100644 index 0000000..d81a024 --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/skyselectfeeds.png diff --git a/skins/default/graphics/menuicons/pluginicons/sleeptimer.png b/skins/default/graphics/menuicons/pluginicons/sleeptimer.png Binary files differnew file mode 100644 index 0000000..cd4956f --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/sleeptimer.png diff --git a/skins/default/graphics/menuicons/pluginicons/softhddevice.png b/skins/default/graphics/menuicons/pluginicons/softhddevice.png Binary files differnew file mode 100644 index 0000000..df13f2c --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/softhddevice.png diff --git a/skins/default/graphics/menuicons/pluginicons/streamdev-server.png b/skins/default/graphics/menuicons/pluginicons/streamdev-server.png Binary files differnew file mode 100644 index 0000000..e89ed8b --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/streamdev-server.png diff --git a/skins/default/graphics/menuicons/pluginicons/systeminfo.png b/skins/default/graphics/menuicons/pluginicons/systeminfo.png Binary files differnew file mode 100644 index 0000000..b14763f --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/systeminfo.png diff --git a/skins/default/graphics/menuicons/pluginicons/targavfd.png b/skins/default/graphics/menuicons/pluginicons/targavfd.png Binary files differnew file mode 100644 index 0000000..e91b111 --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/targavfd.png diff --git a/skins/default/graphics/menuicons/pluginicons/trayopenng.png b/skins/default/graphics/menuicons/pluginicons/trayopenng.png Binary files differnew file mode 100644 index 0000000..6ebd17d --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/trayopenng.png diff --git a/skins/default/graphics/menuicons/pluginicons/tvguide.png b/skins/default/graphics/menuicons/pluginicons/tvguide.png Binary files differnew file mode 100644 index 0000000..968a37c --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/tvguide.png diff --git a/skins/default/graphics/menuicons/pluginicons/tvm2vdr.png b/skins/default/graphics/menuicons/pluginicons/tvm2vdr.png Binary files differnew file mode 100644 index 0000000..47f9a91 --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/tvm2vdr.png diff --git a/skins/default/graphics/menuicons/pluginicons/tvscraper.png b/skins/default/graphics/menuicons/pluginicons/tvscraper.png Binary files differnew file mode 100644 index 0000000..a106cb5 --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/tvscraper.png diff --git a/skins/default/graphics/menuicons/pluginicons/undelete.png b/skins/default/graphics/menuicons/pluginicons/undelete.png Binary files differnew file mode 100644 index 0000000..a53d50a --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/undelete.png diff --git a/skins/default/graphics/menuicons/pluginicons/weatherng.png b/skins/default/graphics/menuicons/pluginicons/weatherng.png Binary files differnew file mode 100644 index 0000000..a88f11d --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/weatherng.png diff --git a/skins/default/graphics/menuicons/pluginicons/xmltv2vdr.png b/skins/default/graphics/menuicons/pluginicons/xmltv2vdr.png Binary files differnew file mode 100644 index 0000000..ea73c74 --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/xmltv2vdr.png diff --git a/skins/default/graphics/menuicons/pluginicons/yaepghg.png b/skins/default/graphics/menuicons/pluginicons/yaepghg.png Binary files differnew file mode 100644 index 0000000..53ce443 --- /dev/null +++ b/skins/default/graphics/menuicons/pluginicons/yaepghg.png diff --git a/skins/default/graphics/menuicons/standardicons/CAM.png b/skins/default/graphics/menuicons/standardicons/CAM.png Binary files differnew file mode 100644 index 0000000..a394877 --- /dev/null +++ b/skins/default/graphics/menuicons/standardicons/CAM.png diff --git a/skins/default/graphics/menuicons/standardicons/Channels.png b/skins/default/graphics/menuicons/standardicons/Channels.png Binary files differnew file mode 100644 index 0000000..ba2ba78 --- /dev/null +++ b/skins/default/graphics/menuicons/standardicons/Channels.png diff --git a/skins/default/graphics/menuicons/standardicons/Commands.png b/skins/default/graphics/menuicons/standardicons/Commands.png Binary files differnew file mode 100644 index 0000000..c6a83ef --- /dev/null +++ b/skins/default/graphics/menuicons/standardicons/Commands.png diff --git a/skins/default/graphics/menuicons/standardicons/DVB.png b/skins/default/graphics/menuicons/standardicons/DVB.png Binary files differnew file mode 100644 index 0000000..3789145 --- /dev/null +++ b/skins/default/graphics/menuicons/standardicons/DVB.png diff --git a/skins/default/graphics/menuicons/standardicons/EPG.png b/skins/default/graphics/menuicons/standardicons/EPG.png Binary files differnew file mode 100644 index 0000000..e868b90 --- /dev/null +++ b/skins/default/graphics/menuicons/standardicons/EPG.png diff --git a/skins/default/graphics/menuicons/standardicons/LNB.png b/skins/default/graphics/menuicons/standardicons/LNB.png Binary files differnew file mode 100644 index 0000000..896dd99 --- /dev/null +++ b/skins/default/graphics/menuicons/standardicons/LNB.png diff --git a/skins/default/graphics/menuicons/standardicons/Miscellaneous.png b/skins/default/graphics/menuicons/standardicons/Miscellaneous.png Binary files differnew file mode 100644 index 0000000..2a41c4d --- /dev/null +++ b/skins/default/graphics/menuicons/standardicons/Miscellaneous.png diff --git a/skins/default/graphics/menuicons/standardicons/OSD.png b/skins/default/graphics/menuicons/standardicons/OSD.png Binary files differnew file mode 100644 index 0000000..8f571c6 --- /dev/null +++ b/skins/default/graphics/menuicons/standardicons/OSD.png diff --git a/skins/default/graphics/menuicons/standardicons/Plugins.png b/skins/default/graphics/menuicons/standardicons/Plugins.png Binary files differnew file mode 100644 index 0000000..3fcba70 --- /dev/null +++ b/skins/default/graphics/menuicons/standardicons/Plugins.png diff --git a/skins/default/graphics/menuicons/standardicons/Recording.png b/skins/default/graphics/menuicons/standardicons/Recording.png Binary files differnew file mode 100644 index 0000000..741b1af --- /dev/null +++ b/skins/default/graphics/menuicons/standardicons/Recording.png diff --git a/skins/default/graphics/menuicons/standardicons/Recordings.png b/skins/default/graphics/menuicons/standardicons/Recordings.png Binary files differnew file mode 100644 index 0000000..79aeeb7 --- /dev/null +++ b/skins/default/graphics/menuicons/standardicons/Recordings.png diff --git a/skins/default/graphics/menuicons/standardicons/Replay.png b/skins/default/graphics/menuicons/standardicons/Replay.png Binary files differnew file mode 100644 index 0000000..621596c --- /dev/null +++ b/skins/default/graphics/menuicons/standardicons/Replay.png diff --git a/skins/default/graphics/menuicons/standardicons/Restart.png b/skins/default/graphics/menuicons/standardicons/Restart.png Binary files differnew file mode 100644 index 0000000..aa23cd4 --- /dev/null +++ b/skins/default/graphics/menuicons/standardicons/Restart.png diff --git a/skins/default/graphics/menuicons/standardicons/Schedule.png b/skins/default/graphics/menuicons/standardicons/Schedule.png Binary files differnew file mode 100644 index 0000000..3a98cac --- /dev/null +++ b/skins/default/graphics/menuicons/standardicons/Schedule.png diff --git a/skins/default/graphics/menuicons/standardicons/Setup.png b/skins/default/graphics/menuicons/standardicons/Setup.png Binary files differnew file mode 100644 index 0000000..d121148 --- /dev/null +++ b/skins/default/graphics/menuicons/standardicons/Setup.png diff --git a/skins/default/graphics/menuicons/standardicons/StopRecording.png b/skins/default/graphics/menuicons/standardicons/StopRecording.png Binary files differnew file mode 100644 index 0000000..ed83fbb --- /dev/null +++ b/skins/default/graphics/menuicons/standardicons/StopRecording.png diff --git a/skins/default/graphics/menuicons/standardicons/StopReplay.png b/skins/default/graphics/menuicons/standardicons/StopReplay.png Binary files differnew file mode 100644 index 0000000..9192760 --- /dev/null +++ b/skins/default/graphics/menuicons/standardicons/StopReplay.png diff --git a/skins/default/graphics/menuicons/standardicons/Timers.png b/skins/default/graphics/menuicons/standardicons/Timers.png Binary files differnew file mode 100644 index 0000000..b866c36 --- /dev/null +++ b/skins/default/graphics/menuicons/standardicons/Timers.png 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 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE displayaudiotracks SYSTEM "../../dtd/displayaudiotracks.dtd"> + +<displayaudiotracks x="25%" y="0" width="50%" height="100%" fadetime="{fadeTime}"> + <!-- Available Variables background: + {numtracks} number of displayed tracks + --> + <background> + <area x="0" y="{areaheight} - {numtracks} * {areaheight} / 10 - {areaheight} / 10" width="100%" height="{areaheight} / 10 + {areaheight} / 10 * {numtracks}" layer="1"> + <fill color="{clrTransBlack}" /> + </area> + </background> + + <!-- Available Variables header: + {numtracks} number of displayed tracks + {title} title of menu + --> + <header> + <area x="0" y="{areaheight} - {numtracks} * {areaheight} / 10 - {areaheight} / 10" width="100%" height="{areaheight} / 10" layer="2"> + <drawtext x="10" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{title}" /> + <drawimage condition="{isstereo}" imagetype="icon" path="ico_stereo" x="{areawidth} - {areaheight}*0.9" valign="center" width="{areaheight}*0.9" height="{areaheight}*0.9"/> + <drawimage condition="{isac3}" imagetype="icon" path="ico_ac3" x="{areawidth} - {areaheight}*0.9" valign="center" width="{areaheight}*0.9" height="{areaheight}*0.9"/> + </area> + </header> + + <!-- Available Variables header: + {numelements} number of displayed tracks + --> + <menuitems x="0" y="{areaheight} - {numelements} * {areaheight} / 10" orientation="vertical" width="100%" height="{numelements} * {areaheight} / 10" align="top" numlistelements="{numelements}"> + <!-- Available Variables auidotrack listelement: + {current} true if item is currently selected + {title} title of auio track + --> + <listelement> + <!-- Background --> + <area x="1%" width="98%" layer="2"> + <fill condition="not{current}" color="{clrTransparent}" /> + <fill condition="{current}" color="{clrTransBlueLight}" /> + </area> + <area x="1%" width="98%" layer="3"> + <drawtext x="10" valign="center" font="{light}" fontsize="60%" color="{clrWhite}" text="{title}" /> + </area> + </listelement> + </menuitems> + +</displayaudiotracks> 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 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE displaychannel SYSTEM "../../dtd/displaychannel.dtd"> + +<displaychannel x="0" y="0" width="100%" height="100%" fadetime="{fadeTime}"> + <background> + <!-- background infobar --> + <area x="0" y="80%" width="100%" height="20%" layer="1"> + <fill color="{clrTransBlack}" /> + </area> + <!-- background datetime --> + <area x="70%" y="0" width="30%" height="13%" layer="1"> + <fill color="{clrTransBlack}" /> + <drawrectangle x="0" y="0" width="45%" height="100%" color="{clrTransBlueLight}" /> + </area> + <!-- background channellogo --> + <area x="0" y="80%" width="20%" height="20%" layer="2"> + <fill color="{clrTransBlueLight}" /> + </area> + </background> + + <!-- Available Variables channelinfo: + {channelnumber} Number of Channel, with "-" in case of channel switching + {channelname} Name of current Channel + {channellogoexists} true if a channel logo exists + {channelid} ChannelID as path to display channel logo + {switching} true if a number is pressed on the remote to switch to a dedicated channel + --> + <channelinfo> + <area x="22%" y="80%" width="76%" height="7%" layer="2"> + <fill condition="not{switching}" color="{clrTransparent}" /> + <drawtext condition="{switching}" x="0" y="-10" font="{light}" fontsize="99%" color="{clrWhite}" text="{channelnumber}: {channelname}" /> + </area> + <area x="0" y="80%" width="20%" height="20%" layer="3"> + <drawimage cache="true" condition="{channellogoexists}" imagetype="channellogo" path="{channelid}" height="98%" align="center" valign="center" /> + <drawtext condition="not{channellogoexists}" x="5" valign="center" font="{light}" fontsize="40%" color="{clrWhite}" text="{channelnumber}: {channelname}" /> + </area> + </channelinfo> + <!-- Available Variables epginfo: + {currenttitle} Title of the current Schedule + {currentsubtitle} Subtitle of the current Schedule + {currentstart} Start of current Schedule in hh:mm + {currentstop} End of current Schedule in hh:mm + {currentduration} Duration of current Schedule in min + {currentelapsed} Elapsed time of current Schedule in min + {currentremaining} Remaining time of current Schedule in min + {currentrecording} true if current Schedule is recorded + {nexttitle} Title of next Schedule + {nextsubtitle} Subtitle of next Schedule + {nextstart} Start of next Schedule in hh:mm + {nextstop} Stop of next Schedule in hh:mm + {nextduration} Duration of next Schedule in min + {nextrecording} true if next Schedule will be recorded + --> + <epginfo> + <area x="22%" y="80%" width="76%" height="7%" layer="2"> + <drawtext name="title" x="0" valign="center" font="{light}" fontsize="99%" color="{clrWhite}" text="{currenttitle}" width="{areawidth} - {width(startstop)}"/> + <drawtext name="startstop" align="right" y="0" font="{light}" fontsize="60%" color="{clrWhite}" text="{currentstart} - {currentstop}" /> + <drawtext align="right" y="45%" font="{light}" fontsize="60%" color="{clrWhite}" text="+ {currentremaining} min" /> + </area> + <area x="22%" y="87%" width="76%" height="7%" layer="2"> + <drawtext x="0" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{nexttitle}" width="{areawidth} - {width(startstop)}"/> + <drawtext name="startstop" align="right" y="0" font="{light}" fontsize="60%" color="{clrWhite}" text="{nextstart} - {nextstop}" /> + <drawtext align="right" y="45%" font="{light}" fontsize="60%" color="{clrWhite}" text="{nextduration} min" /> + </area> + </epginfo> + + <!-- Available Variables progressbar: + {start} Start of current Schedule in hh:mm + {stop} End of current Schedule in hh:mm + {duration} Total Duration of current Schedule in seconds + {elapsed} Elapsed time of current Schedule in seconds + {remaining} Remaining time of current Schedule in seconds + --> + <progressbar> + <area x="22%" y="87%" width="76%" height="3" layer="2"> + <drawrectangle x="0" y="1" width="100%" height="1" color="{clrWhite}" /> + <drawrectangle x="0" y="0" width="{elapsed}/{duration}*{areawidth}" height="3" color="{clrTransBlueLight}" /> + </area> + </progressbar> + + <!-- Available Variables statusinfo: + {isRadio} true if channel is a radio channel + {hasVT} true if channel has video text + {isStereo} true if a stereo audio trac is available + {isDolby} true if a dolby audio track is available + {isEncrypted} true if channel is encrypted + {isRecording} true if currently a recording is running on this channel + --> + <statusinfo> + <area x="22%" y="94%" width="76%" height="6%" layer="2"> + <!-- encrypted / decrypted icon --> + <drawimage name="enc" condition="{isEncrypted}" imagetype="icon" path="ico_crypt_on" x="{areawidth} - {width(enc)}" valign="center" width="{areaheight}*0.8*1.76" height="{areaheight}*0.8"/> + <drawimage condition="not{isEncrypted}" imagetype="icon" path="ico_crypt_off" x="{areawidth} - {width(enc)}" valign="center" width="{areaheight}*0.8*1.76" height="{areaheight}*0.8"/> + <!-- dolby icon --> + <drawimage name="dolby" condition="{isDolby}" imagetype="icon" path="ico_dolby_on" x="{posx(enc)} - 15 - {width(dolby)}" valign="center" width="{areaheight}*0.8*1.48" height="{areaheight}*0.8"/> + <drawimage condition="not{isDolby}" imagetype="icon" path="ico_dolby_off" x="{posx(enc)} - 15 - {width(dolby)}" valign="center" width="{areaheight}*0.8*1.48" height="{areaheight}*0.8"/> + <!-- videotext icon --> + <drawimage name="txt" condition="{hasVT}" imagetype="icon" path="ico_txt_on" x="{posx(dolby)} - 15 - {width(txt)}" valign="center" width="{areaheight}*0.8*1.3" height="{areaheight}*0.8"/> + <drawimage condition="not{hasVT}" imagetype="icon" path="ico_txt_off" x="{posx(dolby)} - 15 - {width(txt)}" valign="center" width="{areaheight}*0.8*1.3" height="{areaheight}*0.8"/> + <!-- recording icon --> + <drawimage name="rec" condition="{isRecording}" imagetype="icon" path="ico_rec_on" x="{posx(txt)} - 15 - {width(rec)}" valign="center" width="{areaheight}*0.8*1.96" height="{areaheight}*0.8"/> + <drawimage condition="not{isRecording}" imagetype="icon" path="ico_rec_off" x="{posx(txt)} - 15 - {width(rec)}" valign="center" width="{areaheight}*0.8*1.96" height="{areaheight}*0.8"/> + </area> + </statusinfo> + + <!-- Available Variables screenresolution: + {screenwidth} width of currently displayed channel in px + {screenheight} height of currently displayed channel in px + {resolution} resolution: hd1080i, hd720p, sd576i + {aspect} screen aspect, each 4:3, 16:9 or 21:9 + {isHD} true for hd1080i and hd720p + {isWideScreen} true if aspect is 16:9 or 21:9 + --> + <screenresolution> + <area x="22%" y="94%" width="76%" height="6%" layer="2"> + <!-- widescreen icon --> + <drawimage name="widescreen" condition="{isWideScreen}" imagetype="icon" path="ico_widescreen_on" x="{areawidth} - {areaheight}*0.8*1.76 - 15 - {areaheight}*0.8*1.48 - 15 - {areaheight}*0.8*1.3 - 15 - {areaheight}*0.8*1.96 - 15 - {width(widescreen)}" valign="center" width="{areaheight}*0.8*1.87" height="{areaheight}*0.8"/> + <drawimage condition="not{isWideScreen}" imagetype="icon" path="ico_widescreen_off" x="{areawidth} - {areaheight}*0.8*1.76 - 15 - {areaheight}*0.8*1.48 - 15 - {areaheight}*0.8*1.3 - 15 - {areaheight}*0.8*1.96 - 15 - {width(widescreen)}" valign="center" width="{areaheight}*0.8*1.87" height="{areaheight}*0.8"/> + <!-- hd/sd icon --> + <drawimage name="hd" condition="{isHD}" imagetype="icon" path="ico_hd_on" x="{posx(widescreen)} - 15 - {width(hd)}" valign="center" width="{areaheight}*0.8*2.04" height="{areaheight}*0.8"/> + <drawimage condition="not{isHD}" imagetype="icon" path="ico_hd_off" x="{posx(widescreen)} - 15 - {width(hd)}" valign="center" width="{areaheight}*0.8*2.04" height="{areaheight}*0.8"/> + <!-- screenresolution text --> + <drawtext name="reslabel" x="{posx(hd)} - 30 - {width(reslabel)}" valign="center" font="{light}" fontsize="70%" color="{clrWhite}" text="{screenwidth}x{screenheight}" /> + </area> + </screenresolution> + + <!-- Available Variables dvbdeviceinfo: + {prevAvailable} true if previous Channel Group is avaialble + {nextAvailable} true if next Channel Group is avaialble + {group} Name of current Channel Group + {nextgroup} Name of next Channel Group + {prevgroup} Name of prev Channel Group + {sepexists} true if a channel separator logo exists + {seppath} path for separator logo to use in imagetype "seplogo" + --> + <channelgroup> + <area x="0" y="80%" width="20%" height="20%" layer="2"> + <drawimage condition="{sepexists}" imagetype="seplogo" path="{seppath}" height="98%" align="center" valign="center" /> + <drawimage condition="not{sepexists}" imagetype="icon" path="ico_channelsep" align="center" valign="center" width="{areaheight}*0.8" height="{areaheight}*0.8"/> + </area> + <area x="22%" y="85%" width="76%" height="10%" layer="2"> + <drawtext x="0" width="30%" valign="center" font="{light}" fontsize="60%" color="{clrWhite}" text="{prevgroup}" /> + <drawtext x="30%" width="40%" valign="center" font="{semibold}" fontsize="80%" color="{clrWhite}" text="{group}" /> + <drawtext align="right" width="30%" valign="center" font="{light}" fontsize="60%" color="{clrWhite}" text="{nextgroup}" /> + </area> + </channelgroup> + + <!-- Available Variables signalquality: + {signalstrength} STR value of currently displayed channel + {signalquality} SNR value of currently displayed channel + --> + <signalquality> + <area x="22%" y="94%" width="76%" height="6%" layer="3"> + <drawtext x="0" valign="center" font="{light}" fontsize="70%" color="{clrWhite}" text="STR: {signalstrength}% SNR: {signalquality}%" /> + </area> + </signalquality> + + <!-- background of signalmeter, will only be drawn if signalquality was deleted --> + <signalqualityback> + </signalqualityback> + + <!-- Available Variables scrapercontent: + {mediapath} Full Path of Poster or Banner to use in image path attribute + {mediawidth} width of image in pixel + {mediaheight} height of image in pixel + {isbanner} true if image is a banner, false if it is a poster + --> + <scrapercontent> + <area condition="{isbanner}" x="0" y="0" width="{areaheight}*0.13*{mediawidth}/{mediaheight}" height="13%" layer="2"> + <drawimage imagetype="image" path="{mediapath}" align="center" valign="center" width="{areawidth}" height="{areaheight}"/> + </area> + <area condition="not{isbanner}" x="0" y="0" width="{areaheight}*0.5*{mediawidth}/{mediaheight}" height="50%" layer="2"> + <drawimage imagetype="image" path="{mediapath}" x="5" y="5" width="{areawidth}-10" height="{areaheight}-10"/> + </area> + </scrapercontent> + + <!-- Available Variables datetime: + {time} time in hh:mm + {day} day in digits + {dayleadingzero} day in digits with leading 0 + {dayname} Full name of the day + {daynameshort} Short 3 char name of the day + {month} month in digits with leading 0 + {monthname} Full name of the month + {monthnameshort} 3 letter abbrivation of month name + {year} year in yyyy + --> + <datetime> + <area x="70%" y="0" width="13%" height="13%" layer="2"> + <drawtext align="right" y="0" font="{light}" fontsize="50%" color="{clrWhite}" text="{dayname}" /> + <drawtext align="right" y="48%" font="{light}" fontsize="50%" color="{clrWhite}" text="{day}. {monthnameshort}" /> + </area> + <area x="85%" y="0" width="13%" height="13%" layer="2"> + <drawtext align="center" valign="center" font="{light}" fontsize="90%" color="{clrWhite}" text="{time}" /> + </area> + </datetime> + <!-- Available Variables message: + {text} message text + {status} true if message is a status message + {info} true if message is a info message + {warning} true if message is a warn message + {error} true if message is a error message + --> + <message> + <area x="10%" y="45%" width="80%" height="10%" layer="1"> + <drawrectangle condition="{status}" x="20" y="0" width="20" height="100%" color="{clrGreen}" /> + <drawrectangle condition="{info}" x="20" y="0" width="20" height="100%" color="{clrBlue}" /> + <drawrectangle condition="{warning}" x="20" y="0" width="20" height="100%" color="{clrYellow}" /> + <drawrectangle condition="{error}" x="20" y="0" width="20" height="100%" color="{clrRed}" /> + <drawtext align="center" valign="center" width="{areawidth} - 80" font="{light}" fontsize="40%" color="{clrWhite}" text="{text}" /> + </area> + </message> +</displaychannel> 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 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE displaymenu SYSTEM "../../dtd/displaymenu.dtd" [ +<!ENTITY displaymenudefault SYSTEM "displaymenudefault.xml"> +<!ENTITY displaymenumain SYSTEM "displaymenumain.xml"> +<!ENTITY displaymenusetup SYSTEM "displaymenusetup.xml"> +<!ENTITY displaymenuschedules SYSTEM "displaymenuschedules.xml"> +<!ENTITY displaymenutimers SYSTEM "displaymenutimers.xml"> +<!ENTITY displaymenuchannels SYSTEM "displaymenuchannels.xml"> +<!ENTITY displaymenurecordings SYSTEM "displaymenurecordings.xml"> +<!ENTITY displaymenudetailepg SYSTEM "displaymenudetailepg.xml"> +<!ENTITY displaymenudetailrecording SYSTEM "displaymenudetailrecording.xml"> +<!ENTITY displaymenudetailtext SYSTEM "displaymenudetailtext.xml"> +]> + +<displaymenu x="3%" y="5%" width="94%" height="90%" fadetime="0"> + <!-- + The following background, header, datetime and colorbuttons definitions are default + implementations. If one or more of these elements are not implemented in the subview, + the default implementations are used. + --> + <background> + <!-- background left Menu --> + <area x="0" y="0" width="63%" height="100%" layer="1"> + <fill color="{clrTransBlack}" /> + </area> + <!-- background right detail view --> + <area x="63%" y="3%" width="37%" height="94%" layer="1"> + <fill color="{clrTransBlueLight}" /> + </area> + </background> + <!-- Available Variables header: + {title} title of current menu + {vdrversion} running VDR Version + {hasicon} true if a menu icon is available + {icon} path of menu icon + --> + <header> + <area x="0" y="0" width="41%" height="10%" layer="2"> + <drawtext condition="not{hasicon}" x="5" width="{areawidth}-10" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{title}" /> + <drawimage condition="{hasicon}" name="menuicon" imagetype="menuicon" path="{icon}" x="5" valign="center" width="{areaheight}*8/10" height="80%"/> + <drawtext condition="{hasicon}" x="{areaheight}" valign="center" width="{areawidth}-{areaheight}-10" font="{light}" fontsize="80%" color="{clrWhite}" text="{title}" /> + </area> + </header> + <!-- Available Variables datetime: + {time} time in hh:mm + {day} day in digits + {dayleadingzero} day in digits with leading 0 + {dayname} Full name of the day + {daynameshort} Short 3 char name of the day + {month} month in digits with leading 0 + {monthname} Full name of the month + {monthnameshort} 3 letter abbrivation of month name + {year} year in yyyy + --> + <datetime> + <area x="41%" y="0" width="12%" height="10%" layer="2"> + <drawtext align="right" y="5%" font="{light}" fontsize="50%" color="{clrWhite}" text="{dayname}" /> + <drawtext align="right" y="45%" font="{light}" fontsize="50%" color="{clrWhite}" text="{day}. {monthnameshort}" /> + </area> + <area x="53%" y="0" width="10%" height="10%" layer="2"> + <drawtext align="center" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{time}" /> + </area> + </datetime> + <!-- Available Variables message: + {text} message text + {status} true if message is an status message + {info} true if message is an info message + {warning} true if message is an warn message + {error} true if message is an error message + --> + <message> + <area x="5%" y="75%" width="90%" height="15%" layer="7"> + <fill color="{clrTransBlack}" /> + <drawrectangle condition="{status}" x="10" y="0" width="10" height="100%" color="{clrGreen}" /> + <drawrectangle condition="{info}" x="10" y="0" width="10" height="100%" color="{clrBlue}" /> + <drawrectangle condition="{warning}" x="10" y="0" width="10" height="100%" color="{clrYellow}" /> + <drawrectangle condition="{error}" x="10" y="0" width="10" height="100%" color="{clrRed}" /> + <drawtext align="center" valign="center" font="{light}" fontsize="50%" color="{clrWhite}" text="{text}" /> + </area> + </message> + <!-- Available Variables colorbuttons: + {red1} true if red button is button 1 + {red2} true if red button is button 2 + {red3} true if red button is button 3 + {red4} true if red button is button 4 + {green1} true if green button is button 1 + {green2} true if green button is button 2 + {green3} true if green button is button 3 + {green4} true if green button is button 4 + {yellow1} true if yellow button is button 1 + {yellow2} true if yellow button is button 2 + {yellow3} true if yellow button is button 3 + {yellow4} true if yellow button is button 4 + {blue1} true if blue button is button 1 + {blue2} true if blue button is button 2 + {blue3} true if blue button is button 3 + {blue4} true if blue button is button 4 + {red} label of red button + {green} label of green button + {yellow} label of yellow button + {blue} label of blue button + --> + <colorbuttons> + <area x="0" y="92%" width="15%" height="8%" layer="2"> + <drawtext condition="{red1}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{red}" /> + <drawrectangle condition="{red1}" x="0" y="0" width="10" height="100%" color="{clrRed}" /> + <drawtext condition="{green1}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{green}" /> + <drawrectangle condition="{green1}" x="0" y="0" width="10" height="100%" color="{clrGreen}" /> + <drawtext condition="{yellow1}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{yellow}" /> + <drawrectangle condition="{yellow1}" x="0" y="0" width="10" height="100%" color="{clrYellow}" /> + <drawtext condition="{blue1}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{blue}" /> + <drawrectangle condition="{blue1}" x="0" y="0" width="10" height="100%" color="{clrBlue}" /> + </area> + <area x="15%" y="92%" width="15%" height="8%" layer="2"> + <drawtext condition="{red2}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{red}" /> + <drawrectangle condition="{red2}" x="0" y="0" width="10" height="100%" color="{clrRed}" /> + <drawtext condition="{green2}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{green}" /> + <drawrectangle condition="{green2}" x="0" y="0" width="10" height="100%" color="{clrGreen}" /> + <drawtext condition="{yellow2}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{yellow}" /> + <drawrectangle condition="{yellow2}" x="0" y="0" width="10" height="100%" color="{clrYellow}" /> + <drawtext condition="{blue2}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{blue}" /> + <drawrectangle condition="{blue2}" x="0" y="0" width="10" height="100%" color="{clrBlue}" /> + </area> + <area x="30%" y="92%" width="15%" height="8%" layer="2"> + <drawtext condition="{red3}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{red}" /> + <drawrectangle condition="{red3}" x="0" y="0" width="10" height="100%" color="{clrRed}" /> + <drawtext condition="{green3}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{green}" /> + <drawrectangle condition="{green3}" x="0" y="0" width="10" height="100%" color="{clrGreen}" /> + <drawtext condition="{yellow3}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{yellow}" /> + <drawrectangle condition="{yellow3}" x="0" y="0" width="10" height="100%" color="{clrYellow}" /> + <drawtext condition="{blue3}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{blue}" /> + <drawrectangle condition="{blue3}" x="0" y="0" width="10" height="100%" color="{clrBlue}" /> + </area> + <area x="45%" y="92%" width="15%" height="8%" layer="2"> + <drawtext condition="{red4}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{red}" /> + <drawrectangle condition="{red4}" x="0" y="0" width="10" height="100%" color="{clrRed}" /> + <drawtext condition="{green4}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{green}" /> + <drawrectangle condition="{green4}" x="0" y="0" width="10" height="100%" color="{clrGreen}" /> + <drawtext condition="{yellow4}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{yellow}" /> + <drawrectangle condition="{yellow4}" x="0" y="0" width="10" height="100%" color="{clrYellow}" /> + <drawtext condition="{blue4}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{blue}" /> + <drawrectangle condition="{blue4}" x="0" y="0" width="10" height="100%" color="{clrBlue}" /> + </area> + </colorbuttons> + &displaymenudefault; + &displaymenumain; + &displaymenusetup; + &displaymenuschedules; + &displaymenutimers; + &displaymenuchannels; + &displaymenurecordings; + &displaymenudetailepg; + &displaymenudetailrecording; + &displaymenudetailtext; +</displaymenu> 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 @@ +<menuchannels x="0" y="0" width="100%" height="100%" fadetime="0"> + <menuitems x="0" y="10%" orientation="vertical" width="100%" height="82%" align="center" numlistelements="16"> + <!-- Available Variables channels menu listelement: + {number} number of the displayed channel + {name} name of the displayed channel + {channelid} ChannelID as path to display channel logo + {transponder} Transponder of channel + {frequency} Frequency of channel + {source} Source of channel (S, C, T) + {sourcedescription} Descriptin of source from sources.conf + {position} orbital position of the satellite in case this is a DVB-S source + {isAtsc} true if channel is a ATSC channel + {isCable} true if channel is cable channel + {isSat} true if channel is a satellite channel + {isTerr} true if channel is terrestrical + {presenteventtitle} title of present event on this channel + {presenteventstart} present event start time in hh::mm + {presenteventstop} present event event stop time in hh::mm + {current} true if item is currently selected + {separator} true if item is a list separator + --> + <listelement> + <!-- Background --> + <area x="1%" width="58%" layer="2"> + <fill condition="not{current}" color="{clrTransparent}" /> + <fill condition="{current}" color="{clrTransBlueLight}" /> + <fill condition="{separator}" color="{clrSemiTransBlack}" /> + </area> + <area condition="not{separator}" x="1%" width="6%" layer="3"> + <drawimage name="logo" imagetype="channellogo" path="{channelid}" x="10" height="100%" valign="center" /> + </area> + <areascroll condition="not{separator}" scrollelement="menutext" mode="forthandback" orientation="horizontal" delay="1000" scrollspeed="medium" x="7%" width="52%" layer="3"> + <drawtext name="menutext" x="20" valign="center" font="{light}" fontsize="95%" color="{clrWhite}" text="{number} {name} - {sourcedescription}, Transp. {transponder}" /> + </areascroll> + <area condition="{separator}" x="7%" width="52%" layer="3"> + <drawtext x="20" valign="center" font="{light}" fontsize="95%" color="{clrWhite}" text="{name}" /> + </area> + </listelement> + <!-- additional element which is drawn for current element --> + <!-- Available Variables channels menu currentelement: + {number} number of the displayed channel + {name} name of the displayed channel + {channelid} ChannelID as path to display channel logo + {transponder} Transponder of channel + {frequency} Frequency of channel + {source} Source of channel (S, C, T) + {sourcedescription} Descriptin of source from sources.conf + {position} orbital position of the satellite in case this is a DVB-S source + {isAtsc} true if channel is a ATSC channel + {isCable} true if channel is cable channel + {isSat} true if channel is a satellite channel + {isTerr} true if channel is terrestrical + {presenteventtitle} title of present event on this channel + {presenteventstart} present event start time in hh::mm + {presenteventstop} present event stop time in hh::mm + {presenteventshorttext} present event short text + {presenteventdescription} present event description + {presenteventday} present event name of day + {presenteventdate} present event date in dd:mm:yy + {presenteventelapsed} present event elapsed time + {presenteventduration} present event duration + {hasposter} true if a scraped poster is available for this elements present evemt + {posterwidth} width of scraped poster + {posterheight} height of scraped poster + {posterpath} absolute path of scraped poster + {nexteventtitle} title of next event on this channel + {nexteventstart} next event start time in hh::mm + {nexteventstop} next event event stop time in hh::mm + {nexteventshorttext} next event short text + {nexteventdescription} next event description + {nexteventday} next event name of day + {nexteventdate} next event date in dd:mm:yy + {nexteventdate} next event duration + {schedule[]} array with following 10 schedules + {schedule[title]} title of event + {schedule[shorttext]} shorttext of event + {schedule[start]} start time of event in hh:mm + {schedule[stop]} stop time of event in hh:mm + --> + <currentelement delay="500" fadetime="0"> + <area x="63%" y="0" width="36%" height="85%" layer="2"> + <drawimage name="logo" imagetype="channellogo" path="{channelid}" x="10" y="0" width="30%" /> + <drawtext name="channame" align="right" y="{height(logo)}/2 - {height(channame)}/2" width="65%" font="{semibold}" fontsize="10%" color="{clrWhite}" text="{name}" /> + <!-- now --> + <drawtext name="now" x="2%" y="{height(logo)}" width="96%" font="{semibold}" fontsize="8%" color="{clrWhite}" text="Now: {presenteventtitle}" /> + <!--progressbar for now --> + <drawtext name="start" x="{areawidth}/4 - {width(start)}" y="{height(logo)} + {height(now)}" font="{light}" fontsize="7%" color="{clrWhite}" text="{presenteventstart}" /> + <drawtext name="stop" x="{areawidth}*3/4" y="{height(logo)} + {height(now)}" font="{light}" fontsize="7%" color="{clrWhite}" text="{presenteventstop}" /> + <drawrectangle x="{areawidth}/4+10" y="{height(logo)} + {height(now)} + {height(start)} / 2" width="{areawidth}/2 - 20" height="1" color="{clrWhite}" /> + <drawrectangle x="{areawidth}/4+10" y="{height(logo)} + {height(now)} + {height(start)} / 2 - 2" width="{areawidth}/2 * {presenteventelapsed} / {presenteventduration} - 20 * {presenteventelapsed} / {presenteventduration}" height="5" color="{clrWhite}" /> + <!-- shorttext and description --> + <drawtextbox name="nowshort" x="2%" y="{posy(start)} + {height(start)} + 10" width="96%" font="{light}" fontsize="6%" color="{clrWhite}" text="{presenteventshorttext}" /> + <drawtextbox name="nowdesc" x="2%" y="{posy(nowshort)} + {height(nowshort)}" width="96%" height="36%" font="{light}" fontsize="6%" color="{clrWhite}" text="{presenteventdescription}" /> + <!-- next --> + <drawtext name="next" x="2%" y="{posy(nowdesc)} + {height(nowdesc)}" width="96%" font="{semibold}" fontsize="7%" color="{clrWhite}" text="Next: {nexteventtitle}" /> + <drawtext name="nexttime" x="2%" y="{posy(next)} + {height(next)}" width="96%" font="{light}" fontsize="6%" color="{clrWhite}" text="{nexteventstart} - {nexteventstop} ({presenteventduration} min)" /> + </area> + <areascroll mode="forthandback" orientation="vertical" delay="1000" scrollspeed="medium" x="63%" y="85%" width="36%" height="15%" layer="2"> + <drawtext x="10" y="0" font="{semibold}" fontsize="30%" color="{clrWhite}" text="Following Schedules:" /> + <loop name="schedule" x="0" y="{areaheight}/4 + 5" orientation="vertical"> + <drawtext x="10" font="{light}" width="{areawidth}-20" fontsize="30%" color="{clrWhite}" text="{schedule[start]} {schedule[title]}" /> + </loop> + </areascroll> + </currentelement> + </menuitems> + <!-- Available Variables colorbuttons: + {height} height in one-tenth of a percent of total height + {offset} offset from top in one-tenth of a percent of total height + --> + <scrollbar> + <area x="60%" y="10%" width="2%" height="82%" layer="3"> + <fill color="{clrWhite}" /> + <drawrectangle x="2" y="2" width="{areawidth} - 4" height="{areaheight} - 4" color="{clrTransparent}" /> + <drawrectangle x="4" y="4 + {areaheight} * {offset} / 1000" width="{areawidth} - 8" height="{areaheight} * {height} / 1000 - 8" color="{clrWhite}" /> + </area> + </scrollbar> +</menuchannels>
\ 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 @@ + <menudefault x="0" y="0" width="100%" height="100%" fadetime="0"> + <background> + <!-- background Menu --> + <area x="0" y="0" width="100%" height="100%" layer="1"> + <fill color="{clrTransBlack}" /> + </area> + </background> + <!-- Available Variables header: + {title} title of current menu + {vdrversion} running VDR Version + {hasicon} true if a menu icon is available + {icon} path of menu icon + --> + <header> + <area x="0" y="0" width="75%" height="10%" layer="2"> + <drawtext condition="not{hasicon}" x="5" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{title}" /> + <drawimage condition="{hasicon}" name="icon" imagetype="menuicon" path="{icon}" x="5" valign="center" width="{areaheight}*8/10" height="80%"/> + <drawtext condition="{hasicon}" x="{areaheight}" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{title}" /> + </area> + </header> + <!-- Available Variables datetime: + {time} time in hh:mm + {day} day in digits + {dayleadingzero} day in digits with leading 0 + {dayname} Full name of the day + {daynameshort} Short 3 char name of the day + {month} month in digits with leading 0 + {monthname} Full name of the month + {year} year in yyyy + --> + <datetime> + <area x="80%" y="0" width="10%" height="10%" layer="2"> + <drawtext align="right" y="0%" font="{light}" fontsize="50%" color="{clrWhite}" text="{dayname}" /> + <drawtext align="right" y="45%" font="{light}" fontsize="50%" color="{clrWhite}" text="{day}. {monthname}" /> + </area> + <area x="90%" y="0" width="10%" height="10%" layer="2"> + <drawtext align="center" valign="center" font="{light}" fontsize="90%" color="{clrWhite}" text="{time}" /> + </area> + </datetime> + + <!-- Available Variables colorbuttons: + {red1} true if red button is button 1 + {red2} true if red button is button 2 + {red3} true if red button is button 3 + {red4} true if red button is button 4 + {green1} true if green button is button 1 + {green2} true if green button is button 2 + {green3} true if green button is button 3 + {green4} true if green button is button 4 + {yellow1} true if yellow button is button 1 + {yellow2} true if yellow button is button 2 + {yellow3} true if yellow button is button 3 + {yellow4} true if yellow button is button 4 + {blue1} true if blue button is button 1 + {blue2} true if blue button is button 2 + {blue3} true if blue button is button 3 + {blue4} true if blue button is button 4 + {red} label of red button + {green} label of green button + {yellow} label of yellow button + {blue} label of blue button + --> + <colorbuttons> + <area x="0" y="92%" width="25%" height="8%" layer="2"> + <drawtext condition="{red1}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{red}" /> + <drawrectangle condition="{red1}" x="0" y="0" width="10" height="100%" color="{clrRed}" /> + <drawtext condition="{green1}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{green}" /> + <drawrectangle condition="{green1}" x="0" y="0" width="10" height="100%" color="{clrGreen}" /> + <drawtext condition="{yellow1}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{yellow}" /> + <drawrectangle condition="{yellow1}" x="0" y="0" width="10" height="100%" color="{clrYellow}" /> + <drawtext condition="{blue1}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{blue}" /> + <drawrectangle condition="{blue1}" x="0" y="0" width="10" height="100%" color="{clrBlue}" /> + </area> + <area x="25%" y="92%" width="25%" height="8%" layer="2"> + <drawtext condition="{red2}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{red}" /> + <drawrectangle condition="{red2}" x="0" y="0" width="10" height="100%" color="{clrRed}" /> + <drawtext condition="{green2}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{green}" /> + <drawrectangle condition="{green2}" x="0" y="0" width="10" height="100%" color="{clrGreen}" /> + <drawtext condition="{yellow2}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{yellow}" /> + <drawrectangle condition="{yellow2}" x="0" y="0" width="10" height="100%" color="{clrYellow}" /> + <drawtext condition="{blue2}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{blue}" /> + <drawrectangle condition="{blue2}" x="0" y="0" width="10" height="100%" color="{clrBlue}" /> + </area> + <area x="50%" y="92%" width="25%" height="8%" layer="2"> + <drawtext condition="{red3}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{red}" /> + <drawrectangle condition="{red3}" x="0" y="0" width="10" height="100%" color="{clrRed}" /> + <drawtext condition="{green3}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{green}" /> + <drawrectangle condition="{green3}" x="0" y="0" width="10" height="100%" color="{clrGreen}" /> + <drawtext condition="{yellow3}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{yellow}" /> + <drawrectangle condition="{yellow3}" x="0" y="0" width="10" height="100%" color="{clrYellow}" /> + <drawtext condition="{blue3}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{blue}" /> + <drawrectangle condition="{blue3}" x="0" y="0" width="10" height="100%" color="{clrBlue}" /> + </area> + <area x="75%" y="92%" width="25%" height="8%" layer="2"> + <drawtext condition="{red4}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{red}" /> + <drawrectangle condition="{red4}" x="0" y="0" width="10" height="100%" color="{clrRed}" /> + <drawtext condition="{green4}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{green}" /> + <drawrectangle condition="{green4}" x="0" y="0" width="10" height="100%" color="{clrGreen}" /> + <drawtext condition="{yellow4}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{yellow}" /> + <drawrectangle condition="{yellow4}" x="0" y="0" width="10" height="100%" color="{clrYellow}" /> + <drawtext condition="{blue4}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{blue}" /> + <drawrectangle condition="{blue4}" x="0" y="0" width="10" height="100%" color="{clrBlue}" /> + </area> + </colorbuttons> + + <scrollbar> + <area x="96%" y="10%" width="2%" height="82%" layer="3"> + <fill color="{clrWhite}" /> + <drawrectangle x="2" y="2" width="{areawidth} - 4" height="{areaheight} - 4" color="{clrTransparent}" /> + <drawrectangle x="4" y="4 + {areaheight} * {offset} / 1000" width="{areawidth} - 8" height="{areaheight} * {height} / 1000 - 8" color="{clrWhite}" /> + </area> + </scrollbar> + <!-- IMPORTANT: menuitemwidth and determinatefont have to be defined here. menuitemwidth defines the total width of the + default menu items, determinatefont the function which sets the actual font to use. With that it is possible to determinate + the correct column widths --> + <menuitems x="0" y="10%" orientation="vertical" width="100%" height="82%" align="center" menuitemwidth="94%" determinatefont="column1" numlistelements="16"> + <!-- Available Variables default menu listelement: + {column1} text of column1 + {column2} text of column2 + {column3} text of column3 + {column4} text of column4 + {column5} text of column5 + {column6} text of column6 + {column2set} true if column2 is used + {column3set} true if column3 is used + {column4set} true if column4 is used + {column5set} true if column5 is used + {column6set} true if column6 is used + {column2x} proposed x value of column2 + {column3x} proposed x value of column3 + {column4x} proposed x value of column4 + {column5x} proposed x value of column5 + {column6x} proposed x value of column6 + {column1width} proposed width of column1 + {column2width} proposed width of column2 + {column3width} proposed width of column3 + {column4width} proposed width of column4 + {column5width} proposed width of column5 + {column6width} proposed width of column6 + {columnscroll} number of column which should have scrollable text + {current} true if column is currently selected + {separator} true if column is a list separator + --> + <listelement> + <area x="0" width="95%" layer="2"> + <fill condition="not{current}" color="{clrTransparent}" /> + <fill condition="{current}" color="{clrTransBlueLight}" /> + </area> + + <areascroll scrollelement="column1" mode="forthandback" orientation="horizontal" delay="1000" scrollspeed="medium" x="1%" width="{column1width}" layer="3"> + <drawtext name="column1" x="{column1x}" width="{column1width}" valign="center" font="{light}" fontsize="90%" color="{clrWhite}" text="{column1}" /> + </areascroll> + <area x="1%" width="100%" layer="3"> + <drawtext condition="{column2set}" x="{column2x}" valign="center" font="{light}" fontsize="90%" width="{column2width}" color="{clrWhite}" text="{column2}" /> + <drawtext condition="{column3set}" x="{column3x}" valign="center" font="{light}" fontsize="90%" width="{column3width}" color="{clrWhite}" text="{column3}" /> + <drawtext condition="{column4set}" x="{column4x}" valign="center" font="{light}" fontsize="90%" width="{column4width}" color="{clrWhite}" text="{column4}" /> + <drawtext condition="{column5set}" x="{column5x}" valign="center" font="{light}" fontsize="90%" width="{column5width}" color="{clrWhite}" text="{column5}" /> + <drawtext condition="{column6set}" x="{column6x}" valign="center" font="{light}" fontsize="90%" width="{column6width}" color="{clrWhite}" text="{column6}" /> + </area> + <!-- + <areascroll condition="not{separator}++eq({columnscroll},1)" scrollelement="column1" mode="forthandback" orientation="horizontal" delay="1000" scrollspeed="medium" x="1%" width="{column1width}" layer="3"> + <drawtext name="column1" x="{column1x}" width="{column1width}" valign="center" font="{vdrOsd}" fontsize="90%" color="{clrWhite}" text="{column1}" /> + </areascroll> + <area condition="not{separator}++eq({columnscroll},1)" x="1%" width="100%" layer="3"> + <drawtext condition="{column2set}" x="{column2x}" valign="center" font="{light}" fontsize="90%" color="{clrWhite}" text="{column2}" /> + <drawtext condition="{column3set}" x="{column3x}" valign="center" font="{light}" fontsize="90%" color="{clrWhite}" text="{column3}" /> + <drawtext condition="{column4set}" x="{column4x}" valign="center" font="{light}" fontsize="90%" color="{clrWhite}" text="{column4}" /> + <drawtext condition="{column5set}" x="{column5x}" valign="center" font="{light}" fontsize="90%" color="{clrWhite}" text="{column5}" /> + <drawtext condition="{column6set}" x="{column6x}" valign="center" font="{light}" fontsize="90%" color="{clrWhite}" text="{column6}" /> + </area> + <areascroll condition="not{separator}++gt({columnscroll},1)" scrollelement="column2" mode="forthandback" orientation="horizontal" delay="1000" scrollspeed="medium" x="{column2x}" width="{column2width}" layer="3"> + <drawtext name="column2" x="0" width="{column2width}" valign="center" font="{light}" fontsize="90%" color="{clrWhite}" text="{column2}" /> + </areascroll> + <area condition="not{separator}++gt({columnscroll},1)" x="1%" width="100%" layer="3"> + <drawtext condition="{column1set}" x="{column1x}" valign="center" font="{light}" fontsize="90%" color="{clrWhite}" text="{column1}" /> + <drawtext condition="{column3set}" x="{column3x}" valign="center" font="{light}" fontsize="90%" color="{clrWhite}" text="{column3}" /> + <drawtext condition="{column4set}" x="{column4x}" valign="center" font="{light}" fontsize="90%" color="{clrWhite}" text="{column4}" /> + <drawtext condition="{column5set}" x="{column5x}" valign="center" font="{light}" fontsize="90%" color="{clrWhite}" text="{column5}" /> + <drawtext condition="{column6set}" x="{column6x}" valign="center" font="{light}" fontsize="90%" color="{clrWhite}" text="{column6}" /> + </area> + --> + </listelement> + </menuitems> +</menudefault> 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 @@ +<menudetailedepg x="0" y="0" width="100%" height="100%" fadetime="0"> + <background> + <area x="0" y="0" width="100%" height="100%" layer="1"> + <fill color="{clrTransBlack}" /> + </area> + <area x="0" y="0" width="100%" height="20%" layer="2"> + <fill color="{clrTransBlueLight}" /> + </area> + <area x="0" y="85%" width="100%" height="2" layer="3"> + <fill color="{clrTransBlueLight}" /> + </area> + </background> + <!-- dummyheader --> + <header> + <area x="0" y="0" width="1" height="1" layer="1"> + <fill color="{clrTransparent}" /> + </area> + </header> + <datetime> + <area x="0" y="0" width="1" height="1" layer="1"> + <fill color="{clrTransparent}" /> + </area> + </datetime> + <!-- Available Variables colorbuttons: + {red1} true if red button is button 1 + {red2} true if red button is button 2 + {red3} true if red button is button 3 + {red4} true if red button is button 4 + {green1} true if green button is button 1 + {green2} true if green button is button 2 + {green3} true if green button is button 3 + {green4} true if green button is button 4 + {yellow1} true if yellow button is button 1 + {yellow2} true if yellow button is button 2 + {yellow3} true if yellow button is button 3 + {yellow4} true if yellow button is button 4 + {blue1} true if blue button is button 1 + {blue2} true if blue button is button 2 + {blue3} true if blue button is button 3 + {blue4} true if blue button is button 4 + {red} label of red button + {green} label of green button + {yellow} label of yellow button + {blue} label of blue button + --> + <colorbuttons> + <area x="0" y="92%" width="25%" height="8%" layer="2"> + <drawtext condition="{red1}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{red}" /> + <drawrectangle condition="{red1}" x="0" y="0" width="10" height="100%" color="{clrRed}" /> + <drawtext condition="{green1}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{green}" /> + <drawrectangle condition="{green1}" x="0" y="0" width="10" height="100%" color="{clrGreen}" /> + <drawtext condition="{yellow1}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{yellow}" /> + <drawrectangle condition="{yellow1}" x="0" y="0" width="10" height="100%" color="{clrYellow}" /> + <drawtext condition="{blue1}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{blue}" /> + <drawrectangle condition="{blue1}" x="0" y="0" width="10" height="100%" color="{clrBlue}" /> + </area> + <area x="25%" y="92%" width="25%" height="8%" layer="2"> + <drawtext condition="{red2}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{red}" /> + <drawrectangle condition="{red2}" x="0" y="0" width="10" height="100%" color="{clrRed}" /> + <drawtext condition="{green2}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{green}" /> + <drawrectangle condition="{green2}" x="0" y="0" width="10" height="100%" color="{clrGreen}" /> + <drawtext condition="{yellow2}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{yellow}" /> + <drawrectangle condition="{yellow2}" x="0" y="0" width="10" height="100%" color="{clrYellow}" /> + <drawtext condition="{blue2}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{blue}" /> + <drawrectangle condition="{blue2}" x="0" y="0" width="10" height="100%" color="{clrBlue}" /> + </area> + <area x="50%" y="92%" width="25%" height="8%" layer="2"> + <drawtext condition="{red3}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{red}" /> + <drawrectangle condition="{red3}" x="0" y="0" width="10" height="100%" color="{clrRed}" /> + <drawtext condition="{green3}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{green}" /> + <drawrectangle condition="{green3}" x="0" y="0" width="10" height="100%" color="{clrGreen}" /> + <drawtext condition="{yellow3}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{yellow}" /> + <drawrectangle condition="{yellow3}" x="0" y="0" width="10" height="100%" color="{clrYellow}" /> + <drawtext condition="{blue3}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{blue}" /> + <drawrectangle condition="{blue3}" x="0" y="0" width="10" height="100%" color="{clrBlue}" /> + </area> + <area x="75%" y="92%" width="25%" height="8%" layer="2"> + <drawtext condition="{red4}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{red}" /> + <drawrectangle condition="{red4}" x="0" y="0" width="10" height="100%" color="{clrRed}" /> + <drawtext condition="{green4}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{green}" /> + <drawrectangle condition="{green4}" x="0" y="0" width="10" height="100%" color="{clrGreen}" /> + <drawtext condition="{yellow4}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{yellow}" /> + <drawrectangle condition="{yellow4}" x="0" y="0" width="10" height="100%" color="{clrYellow}" /> + <drawtext condition="{blue4}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{blue}" /> + <drawrectangle condition="{blue4}" x="0" y="0" width="10" height="100%" color="{clrBlue}" /> + </area> + </colorbuttons> + <!-- Available Variables in detailheader elements: + {title} title of event + {shorttext} shorttext of event + {start} event start time in hh::mm + {stop} event stop time + {day} day of current event + {date} date of current event in dd.mm.yy + {running} true if event is currently running + {elapsed} elapsed time of event, if not running 0 + {duration} duration of event + {channelid} ChannelID as path to display channel logo + {ismovie} true if event is scraped as a movie + {isseries} true if event is scraped as a series + {posteravailable} true if a poster is available + {posterwidth} width of scraped poster + {posterheight} height of scraped poster + {posterpath} absolute path of scraped poster + {banneravailable} true if a banner is available + {bannerwidth} width of banner + {bannerheight} height of banner + {bannerpath} path of banner + {epgpicavailable} true if a epg picture is available + {epgpicpath} path of epg picture + --> + <detailheader> + <area x="1%" y="0" width="98%" height="20%" layer="3"> + <drawimage name="logo" imagetype="channellogo" path="{channelid}" x="0" height="80%" valign="center" /> + <drawimage condition="{isseries}++{banneravailable}++not{epgpicavailable}" imagetype="image" path="{bannerpath}" x="{areawidth} - {areawidth}/3 - 10" valign="center" width="{areawidth}/3" height="{areawidth}/3 * {bannerheight} / {bannerwidth}"/> + <drawimage condition="{ismovie}++{posteravailable}++not{epgpicavailable}" imagetype="image" path="{posterpath}" x="{areawidth} - {areaheight}*8/10" valign="center" width="{areaheight}*8 / 10 * {posterheight} / {posterwidth}" height="{areaheight}*8 / 10"/> + <drawimage condition="{epgpicavailable}" imagetype="image" path="{epgpicpath}" x="{areawidth} - {areaheight}*8/10 * 174 / 130" valign="center" width="{areaheight}*8/10 * 174 / 130" height="{areaheight}*8 / 10"/> + + <drawtext name="title" x="{width(logo)} + 20" valign="center" font="{semibold}" fontsize="35%" color="{clrWhite}" text="{title}" /> + <drawtext name="datetime" x="{width(logo)} + 20" y="{posy(title)} - {height(datetime)}" font="{light}" fontsize="25%" color="{clrWhite}" text="{day} {date} {start} - {stop} ({duration} mins)" /> + <drawtext name="shorttext" x="{width(logo)} + 20" y="{posy(title)} + {height(title)}" font="{light}" fontsize="25%" color="{clrWhite}" text="{shorttext}" /> + </area> + </detailheader> + <!-- Available Variables scrollbar: + {height} height in one-tenth of a percent of total height + {offset} offset from top in one-tenth of a percent of total height + --> + <scrollbar> + <area x="98%" y="20%" width="2%" height="65%" layer="3"> + <fill color="{clrWhite}" /> + <drawrectangle x="2" y="2" width="{areawidth} - 4" height="{areaheight} - 4" color="{clrTransparent}" /> + <drawrectangle x="4" y="4 + {areaheight} * {offset} / 1000" width="{areawidth} - 8" height="{areaheight} * {height} / 1000 - 8" color="{clrWhite}" /> + </area> + </scrollbar> + <!-- Available Variables in tab elements: + {title} title of event + {shorttext} shorttext of event + {description} description of event + {start} event start time in hh::mm + {stop} event stop time + {day} day of current event + {date} date of current event in dd.mm.yy + {running} true if event is currently running + {elapsed} elapsed time of event, if not running 0 + {duration} duration of event + {channelid} ChannelID as path to display channel logo + {hasreruns} true if reruns of this event are found + {reruns[]} array with reruns + {reruns[title]} title of rerun + {reruns[shorttext]} shorttext of rerun + {reruns[date]} date of rerun in dd:mm + {reruns[day]} short dayname of rerun + {reruns[start]} start time of rerun in hh:mm + {reruns[stop]} stop time of rerun in hh:mm + {reruns[channelname]} name of channel on which rerun occurs + {reruns[channelnumber]} number of channel on which rerun occurs + {reruns[channelid]} id of channel on which rerun occurs to display channel logo + {reruns[channellogoexists]} true if channel logo exists + {epgpic1avaialble} true if first epg picture is available + {epgpic2avaialble} true if first epg picture is available + {epgpic3avaialble} true if first epg picture is available + {epgpic1path} path of first epg picture + {epgpic2path} path of second epg picture + {epgpic3path} path of third epg picture + + {ismovie} true if event is scraped as a movie + Available variables for movies: + {movietitle} movie title from themoviedb + {movieoriginalTitle} movie original title from themoviedb + {movietagline} movie tagline from themoviedb + {movieoverview} movie overview from themoviedb + {movieadult} true if movie is rated as adult + {moviebudget} movie budget from themoviedb in $ + {movierevenue} movie revenue from themoviedb in $ + {moviegenres} movie genres from themoviedb + {moviehomepage} movie homepage from themoviedb + {moviereleasedate} movie release date from themoviedb + {movieruntime} movie runtime from themoviedb + {moviepopularity} movie popularity from themoviedb + {movievoteaverage} movie vote average from themoviedb + {posterwidth} width of scraped poster + {posterheight} height of scraped poster + {posterpath} absolute path of scraped poster + {fanartwidth} width of scraped fanart + {fanartheight} height of scraped fanart + {fanartpath} absolute path of scraped fanart + {movieiscollection} true if movie is part of a collection + {moviecollectionName} name of movie collection + {collectionposterwidth} width of scraped collection poster + {collectionposterheight} height of scraped collection poster + {collectionposterpath} absolute path of scraped collection poster + {collectionfanartwidth} width of scraped collection fanart + {collectionfanartheight} height of scraped collection fanart + {collectionfanartpath} absolute path of scraped collection fanart + {actors[]} array with movie actors + {actors[name]} real name of actor + {actors[role]} actor role + {actors[thumb]} absolute path of scraped actor thumb + {actors[thumbwidth]} width of scraped actor thumb + {actors[thumbheight]} height of scraped actor thumb + + {isseries} true if event is scraped as a series + Available variables for series: + {seriesname} name of series + {seriesoverview} series overview + {seriesfirstaired} first aired date + {seriesnetwork} network which produces series + {seriesgenre} series genre + {seriesrating} series thetvdb rating + {seriesstatus} status of series (running / finished) + {episodetitle} title of episode + {episodenumber} number of episode + {episodeseason} season of episode + {episodefirstaired} first aired date of episode + {episodegueststars} guest stars of episode + {episodeoverview} episode overview + {episoderating} user rating for episode + {episodeimagewidth} episode image width + {episodeimageheight} episode image height + {episodeimagepath} episode image path + {seasonposterwidth} episode season poster width + {seasonposterheight} episode season poster height + {seasonposterpath} episode season poster path + {seriesposter1width} width of 1st poster + {seriesposter1height} height of 1st poster + {seriesposter1path} path of 1st poster + {seriesposter2width} width of 2nd poster + {seriesposter2height} height of 2nd poster + {seriesposter2path} path of 2nd poster + {seriesposter3width} width of 3rd poster + {seriesposter3height} height of 3rd poster + {seriesposter3path} path of 3rd poster + {seriesfanart1width} width of 1st fanart + {seriesfanart1height} height of 1st fanart + {seriesfanart1path} path of 1st fanart + {seriesfanart2width} width of 2nd fanart + {seriesfanart2height} height of 2nd fanart + {seriesfanart2path} path of 2nd fanart + {seriesfanart3width} width of 3rd fanart + {seriesfanart3height} height of 3rd fanart + {seriesfanart3path} path of 3rd fanart + {seriesbanner1width} width of 1st banner + {seriesbanner1height} height of 1st banner + {seriesbanner1path} path of 1st banner + {seriesbanner2width} width of 2nd banner + {seriesbanner2height} height of 2nd banner + {seriesbanner2path} path of 2nd banner + {seriesbanner3width} width of 3rd banner + {seriesbanner3height} height of 3rd banner + {seriesbanner3path} path of 3rd fanart + {actors[]} array with movie actors + {actors[name]} real name of actor + {actors[role]} actor role + {actors[thumb]} absolute path of scraped actor thumb + {actors[thumbwidth]} width of scraped actor thumb + {actors[thumbheight]} height of scraped actor thumb + --> + + <!-- a tab is one scrolling area, just position and draw as inside a normal area --> + + <!-- TAB EPGINFO --> + <tab name="EPG Info" x="2%" y="20%" width="94%" height="65%" layer="2" scrollheight="{areaheight}/4"> + <drawtextbox condition="not{isseries}++not{ismovie}" x="0" y="0" width="96%" font="{light}" fontsize="8%" color="{clrWhite}" text="{description}" /> + <drawimage condition="{isseries}" name="seriesposter" imagetype="image" path="{seriesposter1path}" x="{areawidth}*0.75" y="0" width="{areawidth}*0.25" height="{areawidth} * 0.25 * {seriesposter1height} / {seriesposter1width}"/> + <drawimage condition="{ismovie}" name="movieposter" imagetype="image" path="{posterpath}" x="{areawidth}*0.75" y="0" width="{areawidth}*0.25" height="{areawidth} * 0.25 * {posterheight} / {posterwidth}" /> + <drawtextbox condition="{isseries}" x="0" y="0" width="96%" float="topright" floatwidth="{width(seriesposter)} + 10" floatheight="{height(seriesposter)} + 20" font="{light}" fontsize="8%" color="{clrWhite}" text="{description}" /> + <drawtextbox condition="{ismovie}" x="0" y="0" width="96%" float="topright" floatwidth="{width(movieposter)} + 10" floatheight="{height(movieposter)} + 20" font="{light}" fontsize="8%" color="{clrWhite}" text="{description}" /> + </tab> + <!-- TAB RERUNS --> + <tab condition="{hasreruns}" name="{tr(reruns)}" x="2%" y="20%" width="94%" height="65%" layer="2" scrollheight="{areaheight}/4"> + <drawtext align="center" y="0" name="title" font="{light}" fontsize="10%" color="{clrWhite}" text="{tr(rerunsof)} '{title}'" /> + <loop name="reruns" x="0" y="{height(title)} + 10" width="{areawidth}" orientation="vertical"> + <drawimage name="logo" condition="{reruns[channellogoexists]}" imagetype="channellogo" path="{reruns[channelid]}" x="0" height="10%" /> + <drawtext name="channelname" condition="not{reruns[channellogoexists]}" x="-5" font="{light}" fontsize="10%" color="{clrWhite}" text="{reruns[channelname]}" /> + <drawtext condition="{reruns[channellogoexists]}" x="{width(logo)}+20" y="-5" width="{areawidth} - {width(logo)} - 20" font="{light}" fontsize="8%" color="{clrWhite}" text="{reruns[day]} {reruns[date]} {reruns[start]} - {reruns[stop]}: {reruns[title]} {reruns[shorttext]}" /> + <drawtext condition="not{reruns[channellogoexists]}" x="{width(channelname)}+20" y="-5" width="{areawidth} - {width(logo)} - 20" font="{light}" fontsize="8%" color="{clrWhite}" text="{reruns[day]} {reruns[date]} {reruns[start]} - {reruns[stop]}: {reruns[title]} {reruns[shorttext]}" /> + </loop> + </tab> + <!-- TAB ACTORS --> + <tab condition="{isseries}||{ismovie}" name="{tr(actors)}" x="2%" y="20%" width="94%" height="65%" layer="2" scrollheight="{areaheight}/4"> + <drawtext align="center" name="title" y="0" font="{semibold}" fontsize="15%" color="{clrWhite}" text="{tr(actors)}" /> + <loop name="actors" x="0" y="{height(title)} + 10" width="{areawidth}" orientation="horizontal" columnwidth="{areawidth}/5" rowheight="{areawidth}/5*1.8" overflow="linewrap"> + <drawimage name="thumb" imagetype="image" path="{actors[thumb]}" x="20" y="0" width="{columnwidth}-40" height="{columnwidth} * {actors[thumbheight]} / {actors[thumbwidth]} - 40 * {actors[thumbheight]} / {actors[thumbwidth]}"/> + <drawtext align="center" y="{height(thumb)} + 10" width="{columnwidth}" name="actorname" font="{light}" fontsize="7%" color="{clrWhite}" text="{actors[name]}" /> + <drawtext align="center" y="{height(thumb)} + 10 + {height(actorname)}" width="{columnwidth}" font="{light}" fontsize="7%" color="{clrWhite}" text="{actors[role]}" /> + </loop> + </tab> + <!-- TAB TVDBINFO --> + <tab condition="{isseries}" name="TvDBInfo" x="2%" y="20%" width="94%" height="65%" layer="2" scrollheight="{areaheight}/4"> + <drawimage name="banner" imagetype="image" path="{seriesbanner1path}" align="center" y="10" width="{areawidth}*0.9" height="{areawidth} * 0.9 * {seriesbanner1height} / {seriesbanner1width}"/> + <drawimage name="episodeimage" imagetype="image" path="{episodeimagepath}" x="{areawidth}*0.7" y="{height(banner)} + 20" width="{areawidth}*0.3" height="{areawidth} * 0.3 * {episodeimageheight} / {episodeimagewidth}"/> + <drawimage name="seasonposter" imagetype="image" path="{seasonposterpath}" x="{areawidth}*0.7" y="{height(banner)} + {height(episodeimage)} + 30" width="{areawidth}*0.3" height="{areawidth} * 0.3 * {seasonposterheight} / {seasonposterwidth}"/> + <drawtextbox x="0" y="{height(banner)} + 20" width="96%" float="topright" floatwidth="{width(seasonposter)} + 10" floatheight="{height(episodeimage)} + {height(seasonposter)} + 30" font="{light}" fontsize="8%" color="{clrWhite}" text="{tr(episode)}: {episodetitle} ({tr(season)} {episodeseason}, {tr(episode)} {episodenumber}) {episodeoverview}| {tr(gueststars)}: {episodegueststars}|| {tr(seriesfirstaired)}: {seriesfirstaired}|| {tr(episodefirstaired)}: {episodefirstaired}|| {tr(network)}: {seriesnetwork}|| {tr(genre)}: {seriesgenre}|| {tr(status)}: {seriesstatus}|| {tr(rating)}: {seriesrating}|| {tr(episoderating)}: {episoderating} |{seriesoverview} " /> + </tab> + <!-- TAB SERIESGALERY --> + <tab condition="{isseries}" name="{tr(seriesgalery)}" x="2%" y="20%" width="94%" height="65%" layer="2" scrollheight="{areaheight}/4"> + <drawimage name="banner1" imagetype="image" path="{seriesbanner1path}" align="center" y="10" width="{areawidth}*0.9" height="{areawidth} * 0.9 * {seriesbanner1height} / {seriesbanner1width}"/> + <drawimage name="fanart1" imagetype="image" path="{seriesfanart1path}" align="center" y="{posy(banner1)} + {height(banner1)} + 20" width="{areawidth}*0.9" height="{areawidth} * 0.9 * {seriesfanart1height} / {seriesfanart1width}"/> + <drawimage name="banner2" imagetype="image" path="{seriesbanner2path}" align="center" y="{posy(fanart1)} + {height(fanart1)} + 20" width="{areawidth}*0.9" height="{areawidth} * 0.9 * {seriesbanner2height} / {seriesbanner2width}"/> + <drawimage name="fanart2" imagetype="image" path="{seriesfanart2path}" align="center" y="{posy(banner2)} + {height(banner2)} + 20" width="{areawidth}*0.9" height="{areawidth} * 0.9 * {seriesfanart2height} / {seriesfanart2width}"/> + <drawimage name="banner3" imagetype="image" path="{seriesbanner3path}" align="center" y="{posy(fanart2)} + {height(fanart2)} + 20" width="{areawidth}*0.9" height="{areawidth} * 0.9 * {seriesbanner3height} / {seriesbanner3width}"/> + <drawimage name="fanart3" imagetype="image" path="{seriesfanart3path}" align="center" y="{posy(banner3)} + {height(banner3)} + 20" width="{areawidth}*0.9" height="{areawidth} * 0.9 * {seriesfanart3height} / {seriesfanart3width}"/> + <drawimage name="poster1" imagetype="image" path="{seriesposter1path}" align="center" y="{posy(fanart3)} + {height(fanart3)} + 20" width="{areawidth}*0.5" height="{areawidth} * 0.5 * {seriesposter1height} / {seriesposter1width}"/> + <drawimage name="poster2" imagetype="image" path="{seriesposter2path}" align="center" y="{posy(poster1)} + {height(poster1)} + 20" width="{areawidth}*0.5" height="{areawidth} * 0.5 * {seriesposter2height} / {seriesposter2width}"/> + <drawimage name="poster3" imagetype="image" path="{seriesposter3path}" align="center" y="{posy(poster2)} + {height(poster2)} + 20" width="{areawidth}*0.5" height="{areawidth} * 0.5 * {seriesposter3height} / {seriesposter3width}"/> + </tab> + <!-- TAB MOVIEDBINFO --> + <tab condition="{ismovie}" name="MovieDBInfo" x="2%" y="20%" width="94%" height="65%" layer="2" scrollheight="{areaheight}/4"> + <drawimage name="poster" imagetype="image" path="{posterpath}" x="70%" y="10" width="{areawidth}*0.3" height="{areawidth} * 0.3 * {posterheight} / {posterwidth}"/> + <drawtextbox x="0" y="10" width="96%" float="topright" floatwidth="{width(poster)} + 10" floatheight="{height(poster)} + 20" font="{light}" fontsize="8%" color="{clrWhite}" text="{tr(originaltitle)}: {movieoriginalTitle} |{tr(genre)}: {moviegenres} ||{movietagline} |{movieoverview} |{tr(budget)}: {moviebudget} ||{tr(revenue)}: {movierevenue} ||{tr(adult)}: {movieadult} ||{tr(releasedate)}: {moviereleasedate} ||{tr(runtime)}: {movieruntime} min || {tr(popularity)}: {moviepopularity} || {tr(voteaverage)}: {movievoteaverage} || {tr(homepage)}: {moviehomepage}| " /> + </tab> + <!-- TAB MOVIEGALERY --> + <tab condition="{ismovie}" name="{tr(moviegalery)}" x="2%" y="20%" width="94%" height="65%" layer="2" scrollheight="{areaheight}/4"> + <drawimage name="fanart" imagetype="image" path="{fanartpath}" align="center" y="10" width="{areawidth}*0.9" height="{areawidth} * 0.9 * {fanartheight} / {fanartwidth}"/> + <drawimage name="poster" imagetype="image" path="{posterpath}" align="center" y="{height(fanart)} + 30" width="{areawidth}*0.6" height="{areawidth} * 0.6 * {posterheight} / {posterwidth}"/> + <drawimage condition="{movieiscollection}" name="collectionfanart" imagetype="image" path="{collectionfanartpath}" align="center" y="{posy(poster)} + {height(poster)} + 20" width="{areawidth}*0.9" height="{areawidth} * 0.9 * {collectionfanartheight} / {collectionfanartwidth}"/> + <drawimage condition="{movieiscollection}" name="collectionposter" imagetype="image" path="{collectionposterpath}" align="center" y="{posy(collectionfanart)} + {height(collectionfanart)} + 20" width="{areawidth}*0.6" height="{areawidth} * 0.6 * {collectionposterheight} / {collectionposterwidth}"/> + </tab> + + <!-- Available Variables tablabels: + {tabs[]} array with available tab labels + {tabs[title]} title of tab + {tabs[current]} true if tab is displayed currently + --> + <tablabels> + <area x="0" y="85%" width="98%" height="5%" layer="3"> + <loop name="tabs" x="0" y="0" orientation="horizontal"> + <drawrectangle condition="{tabs[current]}" x="0" y="0" width="{width(label)}" height="100%" color="{clrTransBlueLight}" /> + <drawrectangle condition="not{tabs[current]}" x="0" y="0" width="{width(label)}" height="100%" color="{clrTransBlueLight}" /> + <drawrectangle condition="not{tabs[current]}" x="2" y="2" width="{width(label)} - 4" height="{areaheight}-4" color="{clrTransparent}" /> + <drawtext name="label" x="0" valign="center" font="{light}" fontsize="95%" color="{clrWhite}" text=" {tabs[title]} " /> + </loop> + </area> + </tablabels> +</menudetailedepg>
\ 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 @@ +<menudetailedrecording x="0" y="0" width="100%" height="100%" fadetime="0"> + <background> + <area x="0" y="0" width="100%" height="100%" layer="1"> + <fill color="{clrTransBlack}" /> + </area> + <area x="0" y="0" width="100%" height="20%" layer="2"> + <fill color="{clrTransBlueLight}" /> + </area> + <area x="0" y="85%" width="100%" height="2" layer="3"> + <fill color="{clrTransBlueLight}" /> + </area> + </background> + <!-- dummyheader --> + <header> + <area x="0" y="0" width="1" height="1" layer="1"> + <fill color="{clrTransparent}" /> + </area> + </header> + <datetime> + <area x="0" y="0" width="1" height="1" layer="1"> + <fill color="{clrTransparent}" /> + </area> + </datetime> + <!-- Available Variables colorbuttons: + {red1} true if red button is button 1 + {red2} true if red button is button 2 + {red3} true if red button is button 3 + {red4} true if red button is button 4 + {green1} true if green button is button 1 + {green2} true if green button is button 2 + {green3} true if green button is button 3 + {green4} true if green button is button 4 + {yellow1} true if yellow button is button 1 + {yellow2} true if yellow button is button 2 + {yellow3} true if yellow button is button 3 + {yellow4} true if yellow button is button 4 + {blue1} true if blue button is button 1 + {blue2} true if blue button is button 2 + {blue3} true if blue button is button 3 + {blue4} true if blue button is button 4 + {red} label of red button + {green} label of green button + {yellow} label of yellow button + {blue} label of blue button + --> + <colorbuttons> + <area x="0" y="92%" width="25%" height="8%" layer="2"> + <drawtext condition="{red1}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{red}" /> + <drawrectangle condition="{red1}" x="0" y="0" width="10" height="100%" color="{clrRed}" /> + <drawtext condition="{green1}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{green}" /> + <drawrectangle condition="{green1}" x="0" y="0" width="10" height="100%" color="{clrGreen}" /> + <drawtext condition="{yellow1}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{yellow}" /> + <drawrectangle condition="{yellow1}" x="0" y="0" width="10" height="100%" color="{clrYellow}" /> + <drawtext condition="{blue1}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{blue}" /> + <drawrectangle condition="{blue1}" x="0" y="0" width="10" height="100%" color="{clrBlue}" /> + </area> + <area x="25%" y="92%" width="25%" height="8%" layer="2"> + <drawtext condition="{red2}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{red}" /> + <drawrectangle condition="{red2}" x="0" y="0" width="10" height="100%" color="{clrRed}" /> + <drawtext condition="{green2}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{green}" /> + <drawrectangle condition="{green2}" x="0" y="0" width="10" height="100%" color="{clrGreen}" /> + <drawtext condition="{yellow2}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{yellow}" /> + <drawrectangle condition="{yellow2}" x="0" y="0" width="10" height="100%" color="{clrYellow}" /> + <drawtext condition="{blue2}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{blue}" /> + <drawrectangle condition="{blue2}" x="0" y="0" width="10" height="100%" color="{clrBlue}" /> + </area> + <area x="50%" y="92%" width="25%" height="8%" layer="2"> + <drawtext condition="{red3}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{red}" /> + <drawrectangle condition="{red3}" x="0" y="0" width="10" height="100%" color="{clrRed}" /> + <drawtext condition="{green3}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{green}" /> + <drawrectangle condition="{green3}" x="0" y="0" width="10" height="100%" color="{clrGreen}" /> + <drawtext condition="{yellow3}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{yellow}" /> + <drawrectangle condition="{yellow3}" x="0" y="0" width="10" height="100%" color="{clrYellow}" /> + <drawtext condition="{blue3}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{blue}" /> + <drawrectangle condition="{blue3}" x="0" y="0" width="10" height="100%" color="{clrBlue}" /> + </area> + <area x="75%" y="92%" width="25%" height="8%" layer="2"> + <drawtext condition="{red4}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{red}" /> + <drawrectangle condition="{red4}" x="0" y="0" width="10" height="100%" color="{clrRed}" /> + <drawtext condition="{green4}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{green}" /> + <drawrectangle condition="{green4}" x="0" y="0" width="10" height="100%" color="{clrGreen}" /> + <drawtext condition="{yellow4}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{yellow}" /> + <drawrectangle condition="{yellow4}" x="0" y="0" width="10" height="100%" color="{clrYellow}" /> + <drawtext condition="{blue4}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{blue}" /> + <drawrectangle condition="{blue4}" x="0" y="0" width="10" height="100%" color="{clrBlue}" /> + </area> + </colorbuttons> + <!-- Available Variables in detailheader elements: + {name} name of recording + {shorttext} shorttext of recording + {date} date of recording in dd.mm.yy + {time} time of current event in hh:mm + {duration} real duration of recording in minutes + {durationevent} duration of according event in minutes + {ismovie} true if event is scraped as a movie + {isseries} true if event is scraped as a series + {posteravailable} true if a poster is available + {posterwidth} width of scraped poster + {posterheight} height of scraped poster + {posterpath} absolute path of scraped poster + {banneravailable} true if a banner is available + {bannerwidth} width of banner + {bannerheight} height of banner + {bannerpath} path of banner + {recimgavailable} true if a recording image is available in the recording path + {recimgpath} path of rec image + --> + <detailheader> + <area x="1%" y="0" width="98%" height="20%" layer="3"> + <drawimage condition="{isseries}++{banneravailable}++not{recimgavailable}" imagetype="image" path="{bannerpath}" x="{areawidth} - {areawidth}/3 - 10" valign="center" width="{areawidth}/3" height="{areawidth}/3 * {bannerheight} / {bannerwidth}"/> + <drawimage condition="{ismovie}++{posteravailable}++not{recimgavailable}" imagetype="image" path="{posterpath}" x="{areawidth} - {areaheight}*8/10" valign="center" width="{areaheight}*8 / 10 * {posterheight} / {posterwidth}" height="{areaheight}*8 / 10"/> + <drawimage condition="{recimgavailable}" imagetype="image" path="{recimgpath}" x="{areawidth} - {areaheight}*8/10 * 174 / 130" valign="center" width="{areaheight}*8/10 * 174 / 130" height="{areaheight}*8 / 10"/> + + <drawtext name="title" x="20" valign="center" font="{semibold}" fontsize="35%" color="{clrWhite}" text="{name}" /> + <drawtext name="datetime" x="20" y="{posy(title)} - {height(datetime)}" font="{light}" fontsize="25%" color="{clrWhite}" text="{date} {time} ({duration} mins)" /> + <drawtext name="shorttext" x="20" y="{posy(title)} + {height(title)}" font="{light}" fontsize="25%" color="{clrWhite}" text="{shorttext}" /> + </area> + </detailheader> + <!-- Available Variables scrollbar: + {height} height in one-tenth of a percent of total height + {offset} offset from top in one-tenth of a percent of total height + --> + <scrollbar> + <area x="98%" y="20%" width="2%" height="65%" layer="3"> + <fill color="{clrWhite}" /> + <drawrectangle x="2" y="2" width="{areawidth} - 4" height="{areaheight} - 4" color="{clrTransparent}" /> + <drawrectangle x="4" y="4 + {areaheight} * {offset} / 1000" width="{areawidth} - 8" height="{areaheight} * {height} / 1000 - 8" color="{clrWhite}" /> + </area> + </scrollbar> + <!-- Available Variables in tab elements: + {name} title of recording + {shorttext} shorttext of recording + {description} description of recording + {date} date of recording in dd.mm.yy + {time} time of recording in hh:mm + {duration} real duration of recording in minutes + {durationevent} duration of according event in minutes + + {recordingsize} size of recording (automatically in GB / MB) + {recordingsizecutted} size of cutted recording (automatically in GB / MB) + {recordinglength} length of recording (in hh::mm:ss) + {recordinglengthcutted} length of cutted recording (in hh::mm:ss) + {recordingbitrate} bitrate of recording (in MBit/s) + {recordingformat} format of recording (TS / PS) + {searchtimer} name of accordign searchtimer (if available) + + {recimg1avaialble} true if first recording image is available + {recimg2avaialble} true if first recording image is available + {recimg3avaialble} true if first recording image is available + {recimg1path} path of first recording image + {recimg2path} path of second recording image + {recimg3path} path of third recording image + + {ismovie} true if event is scraped as a movie + Available variables for movies: + {movietitle} movie title from themoviedb + {movieoriginalTitle} movie original title from themoviedb + {movietagline} movie tagline from themoviedb + {movieoverview} movie overview from themoviedb + {movieadult} true if movie is rated as adult + {moviebudget} movie budget from themoviedb in $ + {movierevenue} movie revenue from themoviedb in $ + {moviegenres} movie genres from themoviedb + {moviehomepage} movie homepage from themoviedb + {moviereleasedate} movie release date from themoviedb + {movieruntime} movie runtime from themoviedb + {moviepopularity} movie popularity from themoviedb + {movievoteaverage} movie vote average from themoviedb + {posterwidth} width of scraped poster + {posterheight} height of scraped poster + {posterpath} absolute path of scraped poster + {fanartwidth} width of scraped fanart + {fanartheight} height of scraped fanart + {fanartpath} absolute path of scraped fanart + {movieiscollection} true if movie is part of a collection + {moviecollectionName} name of movie collection + {collectionposterwidth} width of scraped collection poster + {collectionposterheight} height of scraped collection poster + {collectionposterpath} absolute path of scraped collection poster + {collectionfanartwidth} width of scraped collection fanart + {collectionfanartheight} height of scraped collection fanart + {collectionfanartpath} absolute path of scraped collection fanart + {actors[]} array with movie actors + {actors[name]} real name of actor + {actors[role]} actor role + {actors[thumb]} absolute path of scraped actor thumb + {actors[thumbwidth]} width of scraped actor thumb + {actors[thumbheight]} height of scraped actor thumb + + {isseries} true if event is scraped as a series + Available variables for series: + {seriesname} name of series + {seriesoverview} series overview + {seriesfirstaired} first aired date + {seriesnetwork} network which produces series + {seriesgenre} series genre + {seriesrating} series thetvdb rating + {seriesstatus} status of series (running / finished) + {episodetitle} title of episode + {episodenumber} number of episode + {episodeseason} season of episode + {episodefirstaired} first aired date of episode + {episodegueststars} guest stars of episode + {episodeoverview} episode overview + {episoderating} user rating for episode + {episodeimagewidth} episode image width + {episodeimageheight} episode image height + {episodeimagepath} episode image path + {seasonposterwidth} episode season poster width + {seasonposterheight} episode season poster height + {seasonposterpath} episode season poster path + {seriesposter1width} width of 1st poster + {seriesposter1height} height of 1st poster + {seriesposter1path} path of 1st poster + {seriesposter2width} width of 2nd poster + {seriesposter2height} height of 2nd poster + {seriesposter2path} path of 2nd poster + {seriesposter3width} width of 3rd poster + {seriesposter3height} height of 3rd poster + {seriesposter3path} path of 3rd poster + {seriesfanart1width} width of 1st fanart + {seriesfanart1height} height of 1st fanart + {seriesfanart1path} path of 1st fanart + {seriesfanart2width} width of 2nd fanart + {seriesfanart2height} height of 2nd fanart + {seriesfanart2path} path of 2nd fanart + {seriesfanart3width} width of 3rd fanart + {seriesfanart3height} height of 3rd fanart + {seriesfanart3path} path of 3rd fanart + {seriesbanner1width} width of 1st banner + {seriesbanner1height} height of 1st banner + {seriesbanner1path} path of 1st banner + {seriesbanner2width} width of 2nd banner + {seriesbanner2height} height of 2nd banner + {seriesbanner2path} path of 2nd banner + {seriesbanner3width} width of 3rd banner + {seriesbanner3height} height of 3rd banner + {seriesbanner3path} path of 3rd fanart + {actors[]} array with movie actors + {actors[name]} real name of actor + {actors[role]} actor role + {actors[thumb]} absolute path of scraped actor thumb + {actors[thumbwidth]} width of scraped actor thumb + {actors[thumbheight]} height of scraped actor thumb + --> + + <!-- a tab is one scrolling area, just position and draw as inside a normal area --> + <tab name="Info" x="2%" y="20%" width="94%" height="65%" layer="2" scrollheight="{areaheight}/4"> + <drawtextbox condition="not{isseries}++not{ismovie}" x="0" y="0" width="96%" font="{light}" fontsize="8%" color="{clrWhite}" text="{description}" /> + <drawimage condition="{isseries}" name="seriesposter" imagetype="image" path="{seriesposter1path}" x="{areawidth}*0.7" y="0" width="{areawidth}*0.3" height="{areawidth} * 0.3 * {seriesposter1height} / {seriesposter1width}"/> + <drawimage condition="{ismovie}" name="movieposter" imagetype="image" path="{posterpath}" x="{areawidth}*0.7" y="0" width="{areawidth}*0.3" height="{areawidth} * 0.3 * {posterheight} / {posterwidth}" /> + <drawtextbox condition="{isseries}" x="0" y="0" width="96%" float="topright" floatwidth="{width(seriesposter)} + 10" floatheight="{height(seriesposter)} + 20" font="{light}" fontsize="8%" color="{clrWhite}" text="{description}" /> + <drawtextbox condition="{ismovie}" x="0" y="0" width="96%" float="topright" floatwidth="{width(movieposter)} + 10" floatheight="{height(movieposter)} + 20" font="{light}" fontsize="8%" color="{clrWhite}" text="{description}" /> + </tab> + <tab name="{tr(recinfo)}" x="2%" y="20%" width="94%" height="65%" layer="2" scrollheight="{areaheight}/4"> + <drawtext align="center" y="0" name="title" font="{light}" fontsize="10%" color="{clrWhite}" text="{tr(recinfo)}" /> + <drawtextbox x="0" y="{height(title)} + 20" width="96%" font="{light}" fontsize="10%" color="{clrWhite}" text="{tr(recsize)}: {recordingsize} {tr(recsizecutted)}: {recordingsizecutted} {tr(reclength)}: {recordinglength} {tr(reclengthcutted)}: {recordinglengthcutted} {tr(bitrate)}: {recordingbitrate} {tr(format)}: {recordingformat} {tr(searchtimer)}: {searchtimer} " /> + </tab> + <tab condition="{isseries}||{ismovie}" name="{tr(actors)}" x="2%" y="20%" width="94%" height="65%" layer="2" scrollheight="{areaheight}/4"> + <drawtext align="center" name="title" y="0" font="{light}" fontsize="10%" color="{clrWhite}" text="{tr(actors)}" /> + <loop name="actors" x="0" y="{height(title)} + 10" width="{areawidth}" orientation="horizontal" columnwidth="{areawidth}/5" rowheight="{areawidth}/5*1.8" overflow="linewrap"> + <drawimage name="thumb" imagetype="image" path="{actors[thumb]}" x="20" y="0" width="{columnwidth}-40" height="{columnwidth} * {actors[thumbheight]} / {actors[thumbwidth]} - 40 * {actors[thumbheight]} / {actors[thumbwidth]}"/> + <drawtext align="center" y="{height(thumb)} + 10" width="{columnwidth}" name="actorname" font="{light}" fontsize="7%" color="{clrWhite}" text="{actors[name]}" /> + <drawtext align="center" y="{height(thumb)} + 10 + {height(actorname)}" width="{columnwidth}" font="{light}" fontsize="7%" color="{clrWhite}" text="{actors[role]}" /> + </loop> + </tab> + <tab condition="{isseries}" name="TvDBInfo" x="2%" y="20%" width="94%" height="65%" layer="2" scrollheight="{areaheight}/4"> + <drawimage name="banner" imagetype="image" path="{seriesbanner1path}" align="center" y="10" width="{areawidth}*0.9" height="{areawidth} * 0.9 * {seriesbanner1height} / {seriesbanner1width}"/> + <drawimage name="episodeimage" imagetype="image" path="{episodeimagepath}" x="{areawidth}*0.7" y="{height(banner)} + 20" width="{areawidth}*0.3" height="{areawidth} * 0.3 * {episodeimageheight} / {episodeimagewidth}"/> + <drawimage name="seasonposter" imagetype="image" path="{seasonposterpath}" x="{areawidth}*0.7" y="{height(banner)} + {height(episodeimage)} + 30" width="{areawidth}*0.3" height="{areawidth} * 0.3 * {seasonposterheight} / {seasonposterwidth}"/> + <drawtextbox x="0" y="{height(banner)} + 20" width="96%" float="topright" floatwidth="{width(seasonposter)} + 10" floatheight="{height(episodeimage)} + {height(seasonposter)} + 30" font="{light}" fontsize="8%" color="{clrWhite}" text="{tr(episode)}: {episodetitle} ({tr(season)} {episodeseason}, {tr(episode)} {episodenumber}) {episodeoverview}| {tr(gueststars)}: {episodegueststars}|| {tr(seriesfirstaired)}: {seriesfirstaired}|| {tr(episodefirstaired)}: {episodefirstaired}|| {tr(network)}: {seriesnetwork}|| {tr(genre)}: {seriesgenre}|| {tr(status)}: {seriesstatus}|| {tr(rating)}: {seriesrating}|| {tr(episoderating)}: {episoderating} |{seriesoverview} " /> + </tab> + <tab condition="{isseries}" name="{tr(seriesgalery)}" x="2%" y="20%" width="94%" height="65%" layer="2" scrollheight="{areaheight}/4"> + <drawimage name="banner1" imagetype="image" path="{seriesbanner1path}" align="center" y="10" width="{areawidth}*0.9" height="{areawidth} * 0.9 * {seriesbanner1height} / {seriesbanner1width}"/> + <drawimage name="fanart1" imagetype="image" path="{seriesfanart1path}" align="center" y="{posy(banner1)} + {height(banner1)} + 20" width="{areawidth}*0.9" height="{areawidth} * 0.9 * {seriesfanart1height} / {seriesfanart1width}"/> + <drawimage name="banner2" imagetype="image" path="{seriesbanner2path}" align="center" y="{posy(fanart1)} + {height(fanart1)} + 20" width="{areawidth}*0.9" height="{areawidth} * 0.9 * {seriesbanner2height} / {seriesbanner2width}"/> + <drawimage name="fanart2" imagetype="image" path="{seriesfanart2path}" align="center" y="{posy(banner2)} + {height(banner2)} + 20" width="{areawidth}*0.9" height="{areawidth} * 0.9 * {seriesfanart2height} / {seriesfanart2width}"/> + <drawimage name="banner3" imagetype="image" path="{seriesbanner3path}" align="center" y="{posy(fanart2)} + {height(fanart2)} + 20" width="{areawidth}*0.9" height="{areawidth} * 0.9 * {seriesbanner3height} / {seriesbanner3width}"/> + <drawimage name="fanart3" imagetype="image" path="{seriesfanart3path}" align="center" y="{posy(banner3)} + {height(banner3)} + 20" width="{areawidth}*0.9" height="{areawidth} * 0.9 * {seriesfanart3height} / {seriesfanart3width}"/> + <drawimage name="poster1" imagetype="image" path="{seriesposter1path}" align="center" y="{posy(fanart3)} + {height(fanart3)} + 20" width="{areawidth}*0.5" height="{areawidth} * 0.5 * {seriesposter1height} / {seriesposter1width}"/> + <drawimage name="poster2" imagetype="image" path="{seriesposter2path}" align="center" y="{posy(poster1)} + {height(poster1)} + 20" width="{areawidth}*0.5" height="{areawidth} * 0.5 * {seriesposter2height} / {seriesposter2width}"/> + <drawimage name="poster3" imagetype="image" path="{seriesposter3path}" align="center" y="{posy(poster2)} + {height(poster2)} + 20" width="{areawidth}*0.5" height="{areawidth} * 0.5 * {seriesposter3height} / {seriesposter3width}"/> + </tab> + <tab condition="{ismovie}" name="MovieDBInfo" x="2%" y="20%" width="94%" height="65%" layer="2" scrollheight="{areaheight}/4"> + <drawimage name="poster" imagetype="image" path="{posterpath}" x="70%" y="10" width="{areawidth}*0.3" height="{areawidth} * 0.3 * {posterheight} / {posterwidth}"/> + <drawtextbox x="0" y="10" width="96%" float="topright" floatwidth="{width(poster)} + 10" floatheight="{height(poster)} + 20" font="{light}" fontsize="8%" color="{clrWhite}" text="{tr(originaltitle)}: {movieoriginalTitle} |{tr(genre)}: {moviegenres} ||{movietagline} |{movieoverview} |{tr(budget)}: {moviebudget}$ ||{tr(revenue)}: {movierevenue}$ ||{tr(adult)}: {movieadult} ||{tr(releasedate)}: {moviereleasedate} ||{tr(runtime)}: {movieruntime} min || {tr(popularity)}: {moviepopularity} || {tr(voteaverage)}: {movievoteaverage} || {tr(homepage)}: {moviehomepage}| " /> + </tab> + <tab condition="{ismovie}" name="{tr(moviegalery)}" x="2%" y="20%" width="94%" height="65%" layer="2" scrollheight="{areaheight}/4"> + <drawimage name="fanart" imagetype="image" path="{fanartpath}" align="center" y="10" width="{areawidth}*0.9" height="{areawidth} * 0.9 * {fanartheight} / {fanartwidth}"/> + <drawimage name="poster" imagetype="image" path="{posterpath}" align="center" y="{height(fanart)} + 30" width="{areawidth}*0.6" height="{areawidth} * 0.6 * {posterheight} / {posterwidth}"/> + <drawimage condition="{movieiscollection}" name="collectionfanart" imagetype="image" path="{collectionfanartpath}" align="center" y="{posy(poster)} + {height(poster)} + 20" width="{areawidth}*0.9" height="{areawidth} * 0.9 * {collectionfanartheight} / {collectionfanartwidth}"/> + <drawimage condition="{movieiscollection}" name="collectionposter" imagetype="image" path="{collectionposterpath}" align="center" y="{posy(collectionfanart)} + {height(collectionfanart)} + 20" width="{areawidth}*0.6" height="{areawidth} * 0.6 * {collectionposterheight} / {collectionposterwidth}"/> + </tab> + + <!-- Available Variables tablabels: + {tabs[]} array with available tab labels + {tabs[title]} title of tab + {tabs[current]} true if tab is displayed currently + --> + <tablabels> + <area x="0" y="85%" width="98%" height="5%" layer="3"> + <loop name="tabs" x="0" y="0" orientation="horizontal"> + <drawrectangle condition="{tabs[current]}" x="0" y="0" width="{width(label)}" height="100%" color="{clrTransBlueLight}" /> + <drawrectangle condition="not{tabs[current]}" x="0" y="0" width="{width(label)}" height="100%" color="{clrTransBlueLight}" /> + <drawrectangle condition="not{tabs[current]}" x="2" y="2" width="{width(label)} - 4" height="{areaheight}-4" color="{clrTransparent}" /> + <drawtext name="label" x="0" valign="center" font="{light}" fontsize="95%" color="{clrWhite}" text=" {tabs[title]} " /> + </loop> + </area> + </tablabels> +</menudetailedrecording> 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 @@ +<menudetailedtext x="0" y="0" width="100%" height="100%" fadetime="0"> + <background> + <area x="0" y="0" width="100%" height="100%" layer="1"> + <fill color="{clrTransBlack}" /> + </area> + </background> + <header> + <area x="0" y="0" width="75%" height="10%" layer="2"> + <drawtext x="5" valign="center" font="{light}" fontsize="50%" color="{clrWhite}" text="{title}" /> + </area> + </header> + <datetime> + <area x="75%" y="0" width="12%" height="10%" layer="2"> + <drawtext align="right" y="15%" font="{light}" fontsize="30%" color="{clrWhite}" text="{dayname}" /> + <drawtext align="right" y="45%" font="{light}" fontsize="30%" color="{clrWhite}" text="{day}. {monthname}" /> + </area> + <area x="87%" y="0" width="13%" height="10%" layer="2"> + <drawtext align="center" valign="center" font="{light}" fontsize="60%" color="{clrWhite}" text="{time}" /> + </area> + </datetime> + <!-- Available Variables colorbuttons: + {red1} true if red button is button 1 + {red2} true if red button is button 2 + {red3} true if red button is button 3 + {red4} true if red button is button 4 + {green1} true if green button is button 1 + {green2} true if green button is button 2 + {green3} true if green button is button 3 + {green4} true if green button is button 4 + {yellow1} true if yellow button is button 1 + {yellow2} true if yellow button is button 2 + {yellow3} true if yellow button is button 3 + {yellow4} true if yellow button is button 4 + {blue1} true if blue button is button 1 + {blue2} true if blue button is button 2 + {blue3} true if blue button is button 3 + {blue4} true if blue button is button 4 + {red} label of red button + {green} label of green button + {yellow} label of yellow button + {blue} label of blue button + --> + <colorbuttons> + <area x="0" y="92%" width="25%" height="8%" layer="2"> + <drawtext condition="{red1}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{red}" /> + <drawrectangle condition="{red1}" x="0" y="0" width="10" height="100%" color="{clrRed}" /> + <drawtext condition="{green1}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{green}" /> + <drawrectangle condition="{green1}" x="0" y="0" width="10" height="100%" color="{clrGreen}" /> + <drawtext condition="{yellow1}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{yellow}" /> + <drawrectangle condition="{yellow1}" x="0" y="0" width="10" height="100%" color="{clrYellow}" /> + <drawtext condition="{blue1}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{blue}" /> + <drawrectangle condition="{blue1}" x="0" y="0" width="10" height="100%" color="{clrBlue}" /> + </area> + <area x="25%" y="92%" width="25%" height="8%" layer="2"> + <drawtext condition="{red2}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{red}" /> + <drawrectangle condition="{red2}" x="0" y="0" width="10" height="100%" color="{clrRed}" /> + <drawtext condition="{green2}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{green}" /> + <drawrectangle condition="{green2}" x="0" y="0" width="10" height="100%" color="{clrGreen}" /> + <drawtext condition="{yellow2}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{yellow}" /> + <drawrectangle condition="{yellow2}" x="0" y="0" width="10" height="100%" color="{clrYellow}" /> + <drawtext condition="{blue2}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{blue}" /> + <drawrectangle condition="{blue2}" x="0" y="0" width="10" height="100%" color="{clrBlue}" /> + </area> + <area x="50%" y="92%" width="25%" height="8%" layer="2"> + <drawtext condition="{red3}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{red}" /> + <drawrectangle condition="{red3}" x="0" y="0" width="10" height="100%" color="{clrRed}" /> + <drawtext condition="{green3}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{green}" /> + <drawrectangle condition="{green3}" x="0" y="0" width="10" height="100%" color="{clrGreen}" /> + <drawtext condition="{yellow3}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{yellow}" /> + <drawrectangle condition="{yellow3}" x="0" y="0" width="10" height="100%" color="{clrYellow}" /> + <drawtext condition="{blue3}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{blue}" /> + <drawrectangle condition="{blue3}" x="0" y="0" width="10" height="100%" color="{clrBlue}" /> + </area> + <area x="75%" y="92%" width="25%" height="8%" layer="2"> + <drawtext condition="{red4}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{red}" /> + <drawrectangle condition="{red4}" x="0" y="0" width="10" height="100%" color="{clrRed}" /> + <drawtext condition="{green4}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{green}" /> + <drawrectangle condition="{green4}" x="0" y="0" width="10" height="100%" color="{clrGreen}" /> + <drawtext condition="{yellow4}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{yellow}" /> + <drawrectangle condition="{yellow4}" x="0" y="0" width="10" height="100%" color="{clrYellow}" /> + <drawtext condition="{blue4}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{blue}" /> + <drawrectangle condition="{blue4}" x="0" y="0" width="10" height="100%" color="{clrBlue}" /> + </area> + </colorbuttons> + <scrollbar> + <area x="98%" y="10%" width="2%" height="80%" layer="3"> + <fill color="{clrWhite}" /> + <drawrectangle x="2" y="2" width="{areawidth} - 4" height="{areaheight} - 4" color="{clrTransparent}" /> + <drawrectangle x="4" y="4 + {areaheight} * {offset} / 1000" width="{areawidth} - 8" height="{areaheight} * {height} / 1000 - 8" color="{clrWhite}" /> + </area> + </scrollbar> + + <!-- Available Variables in tab elements: + {text} detailed text + --> + <tab name="text" x="2%" y="10%" width="94%" height="80%" layer="2" scrollheight="{areaheight}/4"> + <drawtextbox x="0" y="0" width="96%" font="{light}" fontsize="5%" color="{clrWhite}" text="{text}" /> + </tab> +</menudetailedtext>
\ 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 @@ +<menumain x="0" y="0" width="100%" height="100%" fadetime="0"> + <!-- + static content of main menu, is only drawn once at main menu startup + --> + <background> + <!-- main menu background --> + <area x="0" y="0" width="71%" height="70%" layer="1"> + <fill color="{clrTransBlack}" /> + </area> + <!-- datetime background --> + <area x="75%" y="0" width="25%" height="10%" layer="2"> + <drawrectangle x="0" y="0" width="53%" height="100%" color="{clrTransBlueLight}" /> + <drawrectangle x="53%" y="0" width="47%" height="100%" color="{clrTransBlack}" /> + </area> + </background> + <!-- Available Variables header: + {title} title of current menu + {vdrversion} running VDR Version + --> + <header> + <area x="0" y="0" width="70%" height="7%" layer="2"> + <drawtext x="10" valign="center" font="{light}" fontsize="100%" color="{clrWhite}" text="{title} {vdrversion}" /> + </area> + </header> + <!-- Available Variables datetime: + {time} time in hh:mm + {day} day in digits + {dayleadingzero} day in digits with leading 0 + {dayname} Full name of the day + {daynameshort} Short 3 char name of the day + {month} month in digits with leading 0 + {monthname} Full name of the month + {monthnameshort} 3 letter abbrivation of month name + {year} year in yyyy + --> + <datetime> + <area x="75%" y="0" width="13%" height="10%" layer="3"> + <drawtext align="right" y="0%" font="{light}" fontsize="55%" color="{clrWhite}" text="{dayname}" /> + <drawtext align="right" y="45%" font="{light}" fontsize="55%" color="{clrWhite}" text="{day}. {monthnameshort}" /> + </area> + <area x="88%" y="0" width="12%" height="10%" layer="3"> + <drawtext align="center" valign="center" font="{light}" fontsize="100%" color="{clrWhite}" text="{time}" /> + </area> + </datetime> + + <!-- Available Variables colorbuttons: + {red1} true if red button is button 1 + {red2} true if red button is button 2 + {red3} true if red button is button 3 + {red4} true if red button is button 4 + {green1} true if green button is button 1 + {green2} true if green button is button 2 + {green3} true if green button is button 3 + {green4} true if green button is button 4 + {yellow1} true if yellow button is button 1 + {yellow2} true if yellow button is button 2 + {yellow3} true if yellow button is button 3 + {yellow4} true if yellow button is button 4 + {blue1} true if blue button is button 1 + {blue2} true if blue button is button 2 + {blue3} true if blue button is button 3 + {blue4} true if blue button is button 4 + {red} label of red button + {green} label of green button + {yellow} label of yellow button + {blue} label of blue button + --> + <colorbuttons> + <area x="0" y="63%" width="18%" height="7%" layer="2"> + <drawtext condition="{red1}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{red}" /> + <drawrectangle condition="{red1}" x="0" y="0" width="10" height="100%" color="{clrRed}" /> + <drawtext condition="{green1}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{green}" /> + <drawrectangle condition="{green1}" x="0" y="0" width="10" height="100%" color="{clrGreen}" /> + <drawtext condition="{yellow1}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{yellow}" /> + <drawrectangle condition="{yellow1}" x="0" y="0" width="10" height="100%" color="{clrYellow}" /> + <drawtext condition="{blue1}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{blue}" /> + <drawrectangle condition="{blue1}" x="0" y="0" width="10" height="100%" color="{clrBlue}" /> + </area> + <area x="18%" y="63%" width="17%" height="7%" layer="2"> + <drawtext condition="{red2}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{red}" /> + <drawrectangle condition="{red2}" x="0" y="0" width="10" height="100%" color="{clrRed}" /> + <drawtext condition="{green2}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{green}" /> + <drawrectangle condition="{green2}" x="0" y="0" width="10" height="100%" color="{clrGreen}" /> + <drawtext condition="{yellow2}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{yellow}" /> + <drawrectangle condition="{yellow2}" x="0" y="0" width="10" height="100%" color="{clrYellow}" /> + <drawtext condition="{blue2}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{blue}" /> + <drawrectangle condition="{blue2}" x="0" y="0" width="10" height="100%" color="{clrBlue}" /> + </area> + <area x="35%" y="63%" width="18%" height="7%" layer="2"> + <drawtext condition="{red3}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{red}" /> + <drawrectangle condition="{red3}" x="0" y="0" width="10" height="100%" color="{clrRed}" /> + <drawtext condition="{green3}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{green}" /> + <drawrectangle condition="{green3}" x="0" y="0" width="10" height="100%" color="{clrGreen}" /> + <drawtext condition="{yellow3}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{yellow}" /> + <drawrectangle condition="{yellow3}" x="0" y="0" width="10" height="100%" color="{clrYellow}" /> + <drawtext condition="{blue3}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{blue}" /> + <drawrectangle condition="{blue3}" x="0" y="0" width="10" height="100%" color="{clrBlue}" /> + </area> + <area x="53%" y="63%" width="17%" height="7%" layer="2"> + <drawtext condition="{red4}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{red}" /> + <drawrectangle condition="{red4}" x="0" y="0" width="10" height="100%" color="{clrRed}" /> + <drawtext condition="{green4}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{green}" /> + <drawrectangle condition="{green4}" x="0" y="0" width="10" height="100%" color="{clrGreen}" /> + <drawtext condition="{yellow4}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{yellow}" /> + <drawrectangle condition="{yellow4}" x="0" y="0" width="10" height="100%" color="{clrYellow}" /> + <drawtext condition="{blue4}" x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{blue}" /> + <drawrectangle condition="{blue4}" x="0" y="0" width="10" height="100%" color="{clrBlue}" /> + </area> + </colorbuttons> + <!-- Available Variables timers: + {numtimers} number of active timers (max. 15 timers will be displayed) + {numtimerconflicts} number of current timer conflicts + + {timers[]} array with active timers (local and remote if remotetimers plugin is in use) + {timers[title]} title of timer + {timers[datetime]} date and time of timer + {timers[recording]} true if timer is recording currently + {timers[channelname]} name of channel for which timer is created + {timers[channelnumber]} number of channel + {timers[channelid]} ChannelID of channel + {timers[channellogoexists]} true if channel logo exists + --> + <timers> + <area x="0" y="75%" width="{areawidth}/8 - 5" height="25%" layer="1"> + <fill color="{clrTransBlack}" /> + </area> + <area condition="not{numtimerconflicts}" x="0" y="75%" width="{areawidth}/8 - 5" height="25%" layer="2"> + <drawtext align="center" y="15%" font="{light}" fontsize="50%" color="{clrWhite}" text="{numtimers}" /> + <drawtext condition="eq({numtimers}, 0)||gt({numtimers}, 1)" name="timersheader" align="center" y="60%" font="{light}" fontsize="20%" color="{clrWhite}" text="{tr(activetimers)}" /> + <drawtext condition="eq({numtimers}, 1)" name="timersheader" align="center" y="60%" font="{light}" fontsize="20%" color="{clrWhite}" text="{tr(activetimer)}" /> + </area> + <area condition="{numtimerconflicts}" x="0" y="75%" width="{areawidth}/8 - 5" height="25%" layer="2"> + <drawtext align="center" y="0" font="{light}" fontsize="50%" color="{clrWhite}" text="{numtimers}" /> + <drawtext name="timersheader" align="center" y="45%" font="{light}" fontsize="20%" color="{clrWhite}" text="{tr(activetimers)}" /> + <drawtext align="center" y="65%" font="{semibold}" fontsize="20%" color="{clrRed}" text="{numtimerconflicts} {tr(conflicts)}!" /> + </area> + + <area condition="gt({numtimers}, 0)" x="{areawidth}/8" y="75%" width="{areawidth}/8 - 5" height="25%" layer="1"> + <fill color="{clrTransBlack}"/> + </area> + <area condition="gt({numtimers}, 1)" x="2*{areawidth}/8" y="75%" width="{areawidth}/8 - 5" height="25%" layer="1"> + <fill color="{clrTransBlack}"/> + </area> + <area condition="gt({numtimers}, 2)" x="3*{areawidth}/8" y="75%" width="{areawidth}/8 - 5" height="25%" layer="1"> + <fill color="{clrTransBlack}"/> + </area> + <area condition="gt({numtimers}, 3)" x="4*{areawidth}/8" y="75%" width="{areawidth}/8 - 5" height="25%" layer="1"> + <fill color="{clrTransBlack}"/> + </area> + <area condition="gt({numtimers}, 4)" x="5*{areawidth}/8" y="75%" width="{areawidth}/8 - 5" height="25%" layer="1"> + <fill color="{clrTransBlack}"/> + </area> + <area condition="gt({numtimers}, 5)" x="6*{areawidth}/8" y="75%" width="{areawidth}/8 - 5" height="25%" layer="1"> + <fill color="{clrTransBlack}"/> + </area> + <area condition="gt({numtimers}, 6)" x="7*{areawidth}/8" y="75%" width="{areawidth}/8 - 5" height="25%" layer="1"> + <fill color="{clrTransBlack}"/> + </area> + <area x="{areawidth}/8" y="75%" width="{areawidth}*0.875" height="25%" layer="2"> + <loop name="timers" x="0" y="0" orientation="horizontal" columnwidth="{areawidth}/7" rowheight="{areaheight}" overflow="cut"> + <drawrectangle condition="{timers[recording]}" x="0" y="0" width="{columnwidth}-5" height="{rowheight}" color="{clrRed}" /> + <drawimage cache="true" name="logo" imagetype="channellogo" path="{timers[channelid]}" height="40%" align="center" y="10" /> + <drawtextbox x="5" y="{height(logo)} + 10" width="{columnwidth}-10" align="center" maxlines="2" font="{light}" fontsize="15%" color="{clrWhite}" text="{timers[title]}" /> + <drawtext align="center" y="75%" font="{light}" fontsize="20%" color="{clrWhite}" text="{timers[datetime]}" /> + </loop> + </area> + </timers> + + <!-- Available Variables discusage: + {freetime} available disc capacity in hh:mm + {freepercent} available disc capacity in percent + {usedpercent} used disc capacity in percent + {freegb} available disc capacity in gigabytes + {discalert} true if disc usage is > 95% + {vdrusagestring} localized VDR internal usage string + --> + <discusage> + <area x="75%" y="15%" width="25%" height="10%" layer="1"> + <fill condition="not{discalert}" color="{clrTransBlack}"/> + <fill condition="{discalert}" color="{clrRed}"/> + </area> + <area x="75%" y="15%" width="25%" height="10%" layer="2"> + <drawimage imagetype="icon" path="ico_discusage" x="1%" valign="center" width="{areaheight}*0.9" height="{areaheight}*0.9"/> + <drawtext x="{areaheight}+10" y="0" font="{light}" fontsize="55%" color="{clrWhite}" text="{tr(disc)}: {freepercent}% {tr(free)}" /> + <drawtext x="{areaheight}+10" y="45%" font="{light}" fontsize="55%" color="{clrWhite}" text="{freetime} {tr(hours)}" /> + </area> + </discusage> + + <!-- Available Variables devices: + {numdevices} number of available devices + {devices[]} array with available devices + {devices[num]} number of current device + {devices[type]} type of device (DVB-S, DVB-C, ...) + {devices[istuned]} true if device is currently tuned to a transponder + {devices[livetv]} true if device is currently playing livetv + {devices[recording]} true if device is currently recording + {devices[hascam]} true if device has a CAM + {devices[cam]} number of CAM + {devices[signalstrength]} signalstrength of devcie + {devices[signalquality]} signalstrength of devcie + {devices[channelnumber]} number of the currently tuned channel + {devices[channelname]} name of the currently tuned channel + {devices[channelid]} ID of the currently tuned channel + {devices[source]} source of the currently tuned channel + --> + <devices> + <area x="75%" y="40%" width="25%" height="{areaheight}/12 * {numdevices}" layer="1"> + <fill color="{clrTransBlack}"/> + </area> + <area x="75%" y="40%" width="25%" height="{areaheight}/12 * {numdevices}" layer="2"> + <loop name="devices" x="0" y="0" orientation="vertical" columnwidth="{areawidth}" rowheight="{areaheight} / {numdevices}" overflow="cut"> + <drawtext name="label" x="5" y="0" font="{light}" fontsize="{rowheight}*0.4" color="{clrWhite}" text="{devices[num]}: {devices[type]}" /> + <drawtext condition="{devices[hascam]}" x="{width(label)} + 15" y="0" font="{light}" fontsize="{rowheight}*0.40" color="{clrWhite}" text="(CAM {devices[cam]})" /> + <drawtext condition="{devices[recording]} ++ {devices[livetv]}" align="right" y="0" font="{light}" fontsize="{rowheight}*0.40" color="{clrRed}" text="LiveTV, Recording ({devices[channelname]}) " /> + <drawtext condition="{devices[recording]} ++ not{devices[livetv]}" align="right" y="0" font="{light}" fontsize="{rowheight}*0.40" color="{clrRed}" text="Recording ({devices[channelname]}) " /> + <drawtext condition="not{devices[recording]} ++ {devices[livetv]}" align="right" y="0" font="{light}" fontsize="{rowheight}*0.40" color="{clrWhite}" text="LiveTV ({devices[channelname]}) " /> + <drawrectangle condition="{devices[istuned]}" x="5" y="{rowheight}/3 + 5" width="{areawidth} * {devices[signalstrength]} / 100 - 10 * {devices[signalstrength]} / 100" height="{rowheight}/3 - 10" color="{clrTransWhite}" /> + <drawrectangle condition="{devices[istuned]}" x="5" y="2*{rowheight}/3 + 5" width="{areawidth} * {devices[signalquality]} / 100 - 10 * {devices[signalquality]} / 100" height="{rowheight}/3 - 10" color="{clrTransWhite}" /> + <drawtext condition="not{devices[istuned]}" align="center" y="{rowheight}/2" font="{light}" fontsize="{rowheight}*0.40" color="{clrWhite}" text="not tuned" /> + </loop> + </area> + </devices> + + <!-- Available Variables systemload: + {load} current system load + --> + <systemload> + <area x="75%" y="30%" width="25%" height="5%" layer="1"> + <fill color="{clrTransBlack}"/> + </area> + <area x="75%" y="30%" width="25%" height="5%" layer="2"> + <drawtext x="5" valign="center" font="{light}" fontsize="100%" color="{clrWhite}" text="System Load: {load}" /> + </area> + </systemload> + + <menuitems x="0" y="7%" orientation="vertical" width="70%" height="56%" align="center" numlistelements="8"> + <!-- Available Variables main menu listelement: + {label} label of menu item + {number} number of menu item (or empty string if not set) + {icon} path of appropriate icon + {current} true if item is currently selected + {separator} true if item is a list separator + --> + <listelement> + <area x="0" width="60%" layer="2"> + <fill condition="not{current}" color="{clrTransparent}" /> + <fill condition="{current}" color="{clrTransBlueLight}" /> + </area> + <areascroll scrollelement="menutext" mode="forthandback" orientation="horizontal" delay="1000" scrollspeed="medium" x="0" width="60%" layer="3"> + <drawtext name="menutext" x="20" valign="center" font="{light}" fontsize="90%" color="{clrWhite}" text="{number} {label}" /> + </areascroll> + </listelement> + <!-- additional element which is drawn for current element --> + <!-- Available Variables main menu currentelement: + {label} label of menu item + {number} number of menu item (or empty string if not set) + {icon} path of appropriate icon + --> + <currentelement delay="50" fadetime="0"> + <area x="61%" y="22%" width="36%" height="52%" layer="2"> + <fill color="{clrTransBlueLight}" /> + </area> + <area x="61%" y="23%" width="36%" height="50%" layer="3"> + <drawimage imagetype="menuicon" path="{icon}" align="center" valign="center" width="{areaheight} - 10" height="{areaheight} - 10"/> + </area> + </currentelement> + </menuitems> + + <scrollbar> + <area x="68%" y="7%" width="2%" height="56%" layer="2"> + <fill color="{clrWhite}" /> + <drawrectangle x="2" y="2" width="{areawidth} - 4" height="{areaheight} - 4" color="{clrTransparent}" /> + <drawrectangle x="4" y="4 + {areaheight} * {offset} / 1000" width="{areawidth} - 8" height="{areaheight} * {height} / 1000 - 8" color="{clrWhite}" /> + </area> + </scrollbar> +</menumain> 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 @@ +<menurecordings x="0" y="0" width="100%" height="100%" fadetime="0"> + <menuitems x="0" y="10%" orientation="vertical" width="100%" height="82%" align="center" numlistelements="16"> + <!-- Available Variables recordings menu listelement: + {name} Name of recording + {date} Date of recording + {time} Time of recording + {duration} real duration of recording in minutes + {durationevent} duration of corresponding event in minutes + {current} true if item is currently selected + {new} true if recording is new + {cutted} true if recording is cutted + {folder} true if item is a folder + {numrecordingsfolder} if item is a folder, number of recordings in this folder + {newrecordingsfolder} if item is a folder, number of new recordings in this folder + {hasposterthumbnail} true if a scraped poster thumbnail is available for recording + {thumbnailbwidth} width of scraped poster thumbnail + {thumbnailheight} height of scraped poster thumbnail + {thumbnailpath} absolute path of scraped poster thumbnail + --> + <listelement> + <!-- Background --> + <area x="1%" width="58%" layer="2"> + <fill condition="not{current}" color="{clrTransparent}" /> + <fill condition="{current}" color="{clrTransBlueLight}" /> + <fill condition="{separator}" color="{clrSemiTransBlack}" /> + </area> + <!-- recording folder --> + <area condition="{folder}" x="1%" width="58%" layer="2"> + <drawimage name="foldericon" imagetype="icon" path="ico_recfolder" x="10" width="0.9*{areaheight} * 92 / 136" height="0.9*{areaheight}" valign="center" /> + <drawtext x="{width(foldericon)} + 20" valign="center" font="{light}" fontsize="95%" color="{clrWhite}" text="{name} ({numrecordingsfolder}, {newrecordingsfolder} new)" /> + </area> + <!-- recording item --> + <area condition="not{folder}" x="1%" width="58%" layer="2"> + <drawtext x="10" valign="center" font="{light}" fontsize="85%" color="{clrWhite}" text="{date} {time}" /> + <drawtext x="35%" width="60%" valign="center" font="{light}" fontsize="85%" color="{clrWhite}" text="{name}" /> + <drawimage condition="{new}" name="new" imagetype="icon" path="ico_recnew" x="{areawidth} - {areaheight}" width="0.9*{areaheight}" height="0.9*{areaheight}" valign="center" /> + <drawimage condition="{new}++{cutted}" imagetype="icon" path="ico_cutted" x="{areawidth} - 2*{areaheight}" width="0.9*{areaheight}" height="0.9*{areaheight}" valign="center" /> + <drawimage condition="not{new}++{cutted}" imagetype="icon" path="ico_cutted" x="{areawidth} - {areaheight}" width="0.9*{areaheight}" height="0.9*{areaheight}" valign="center" /> + </area> + </listelement> + <!-- additional element which is drawn for current element --> + <!-- Available Variables channels menu currentelement: + {name} Name of recording + {shorttext} Short Text of recording + {description} Descrption of recording + {date} Date of recording + {time} Time of recording + {duration} real duration of recording in minutes + {durationevent} duration of corresponding event in minutes + {new} true if recording is new + {cutted} true if recording is cutted + {folder} true if item is a folder + {numrecordingsfolder} if item is a folder, number of recordings in this folder + {newrecordingsfolder} if item is a folder, number of new recordings in this folder + {hasposter} true if a scraped poster is available for recording + {posterwidth} width of scraped poster + {posterheight} height of scraped poster + {posterpath} absolute path of scraped poster + --> + <currentelement delay="500" fadetime="0"> + <area x="63%" y="0" width="36%" height="100%" layer="2"> + <!-- header --> + <drawtext name="title" x="1%" y="0" width="98%" font="{semibold}" fontsize="8%" color="{clrWhite}" text="{name}" /> + <drawtext name="shorttext" x="1%" y="{height(title)}" width="98%" font="{semibold}" fontsize="6%" color="{clrWhite}" text="{shorttext}" /> + <drawtext name="datetime" x="1%" y="{posy(shorttext)} + {height(shorttext)}" font="{light}" fontsize="5%" color="{clrWhite}" text="{date} {time}, {duration} min" /> + <!-- scraper poster --> + <drawimage condition="{hasposter}" name="poster" imagetype="image" path="{posterpath}" x="1%" y="{posy(datetime)} + {height(datetime)} + 20" width="{areawidth}/3" height="{areawidth}/3 * {posterheight} / {posterwidth}"/> + <!-- description --> + <drawtextbox condition="{hasposter}" x="1%" y="{posy(poster)}" width="98%" height="{areaheight} - {posy(poster)}" float="topleft" floatwidth="{width(poster)} + 10" floatheight="{height(poster)} + 10" font="{light}" fontsize="6%" color="{clrWhite}" text="{description}" /> + <drawtextbox condition="not{hasposter}" x="1%" y="{posy(poster)}" width="98%" height="{areaheight} - {posy(poster)}" font="{light}" fontsize="6%" color="{clrWhite}" text="{description}" /> + </area> + </currentelement> + </menuitems> + <!-- Available Variables colorbuttons: + {height} height in one-tenth of a percent of total height + {offset} offset from top in one-tenth of a percent of total height + --> + <scrollbar> + <area x="60%" y="10%" width="2%" height="82%" layer="3"> + <fill color="{clrWhite}" /> + <drawrectangle x="2" y="2" width="{areawidth} - 4" height="{areaheight} - 4" color="{clrTransparent}" /> + <drawrectangle x="4" y="4 + {areaheight} * {offset} / 1000" width="{areawidth} - 8" height="{areaheight} * {height} / 1000 - 8" color="{clrWhite}" /> + </area> + </scrollbar> +</menurecordings>
\ 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 @@ +<menuschedules x="0" y="0" width="100%" height="100%" fadetime="0"> + <!-- Available Variables header: + {title} title of current menu + {vdrversion} running VDR Version + {channelnumber} Number of Channel of current event + {channelname} Name of current Channel of current event + {channellogoexists} true if a channel logo exists + {channelid} ChannelID as path to display channel logo + {whatson} true if menu "What's on" is displayed + {whatsonnow} true if menu "What's on now" is displayed + {whatsonnext} true if menu "What's on next" is displayed + --> + <header> + <area x="0" y="0" width="38%" height="10%" layer="2"> + <drawtext condition="{whatsonnow}||{whatsonnext}" x="5" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{title}" /> + <drawimage name="logo" condition="{whatson}" imagetype="channellogo" path="{channelid}" x="0" height="100%" align="left" valign="center" /> + <drawtext condition="{whatson}" x="{width(logo)}+20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{channelnumber} - {channelname}" /> + </area> + </header> + + <menuitems x="0" y="10%" orientation="vertical" width="100%" height="82%" align="center" numlistelements="16"> + <!-- Available Variables schedules menu listelement: + {title} title of event + {shorttext} shorttext of event + {start} event start time in hh::mm + {stop} event stop time + {day} day of current event + {date} date of current event in dd.mm.yy + {running} true if event is currently running + {elapsed} elapsed time of event, if not running 0 + {duration} duration of event + {current} true if item is currently selected + {separator} true if item is a list separator + {channelid} ChannelID as path to display channel logo + {whatson} true if menu "What's on" is displayed + {whatsonnow} true if menu "What's on now" is displayed + {whatsonnext} true if menu "What's on next" is displayed + {timerpartitial} true if partitial timer is set for the event + {timerfull} true if full timer is set for the event + --> + <listelement> + <!-- Background --> + <area x="1%" width="58%" layer="2"> + <fill condition="not{current}" color="{clrTransparent}" /> + <fill condition="{current}" color="{clrTransBlueLight}" /> + <fill condition="{separator}" color="{clrSemiTransBlack}" /> + </area> + <!-- WHATSON --> + <areascroll condition="not{separator}++{whatson}++not{running}" scrollelement="menutext" mode="forthandback" orientation="horizontal" delay="1000" scrollspeed="medium" x="1%" width="58%" layer="3"> + <drawtext name="menutext" x="20" valign="center" font="{light}" fontsize="95%" color="{clrWhite}" text="{start} {title}" /> + </areascroll> + <areascroll condition="not{separator}++{whatson}++{running}" scrollelement="menutext" mode="forthandback" orientation="horizontal" delay="1000" scrollspeed="medium" x="1%" width="48%" layer="3"> + <drawtext name="menutext" x="20" valign="center" font="{light}" fontsize="95%" color="{clrWhite}" text="{start} {title}" /> + </areascroll> + <area condition="not{separator}++{whatson}" x="1%" width="58%" layer="3"> + <drawimage condition="{timerfull}" imagetype="icon" path="ico_activetimer" x="{areawidth} - 0.9*{areaheight} - 10" width="0.9*{areaheight}" height="0.9*{areaheight}" valign="center" /> + <drawimage condition="{timerpartitial}" imagetype="icon" path="ico_activetimer" x="{areawidth} - 0.5*{areaheight} - 10" width="0.5*{areaheight}" height="0.5*{areaheight}" valign="center" /> + <drawrectangle condition="{running}" x="{areawidth}*0.85 - 10" y="{areaheight}/3" width="{areawidth}*0.15" height="{areaheight}/3" color="{clrWhite}" /> + <drawrectangle condition="{running}" x="{areawidth}*0.85 - 8" y="{areaheight}/3 + 2" width="{areawidth}*0.15 - 4" height="{areaheight}/3 - 4" color="{clrTransparent}" /> + <drawrectangle condition="{running}" x="{areawidth}*0.85 - 6" y="{areaheight}/3 + 4" width="{areawidth}*0.15 * {elapsed} / {duration} - 8" height="{areaheight}/3 - 8" color="{clrWhite}" /> + </area> + <!-- WHATSONNOW --> + <area condition="not{separator}++{whatsonnow}" x="1%" width="6%" layer="3"> + <drawimage name="logo" imagetype="channellogo" path="{channelid}" x="10" height="100%" valign="center" /> + </area> + <area condition="not{separator}++{whatsonnow}++{running}" x="8%" width="7%" layer="3"> + <drawrectangle condition="{current}" x="0" y="{areaheight}/3" width="{areawidth}" height="{areaheight}/3" color="{clrWhite}" /> + <drawrectangle condition="not{current}" x="0" y="{areaheight}/3" width="{areawidth}" height="{areaheight}/3" color="{clrTransBlueLight}" /> + <drawrectangle x="2" y="{areaheight}/3 + 2" width="{areawidth} - 4" height="{areaheight}/3 - 4" color="{clrTransparent}" /> + <drawrectangle x="4" y="{areaheight}/3 + 4" width="{areawidth} * {elapsed} / {duration} - 8" height="{areaheight}/3 - 8" color="{clrWhite}" /> + </area> + <area condition="not{separator}++{whatsonnow}++{timerfull}" x="53%" width="6%" layer="4"> + <drawimage imagetype="icon" path="ico_activetimer" x="{areawidth} - 0.9*{areaheight} - 10" width="0.9*{areaheight}" height="0.9*{areaheight}" valign="center" /> + </area> + <area condition="not{separator}++{whatsonnow}++{timerpartitial}" x="53%" width="6%" layer="5"> + <drawimage imagetype="icon" path="ico_activetimer" x="{areawidth} - 0.5*{areaheight} - 10" width="0.5*{areaheight}" height="0.5*{areaheight}" valign="center" /> + </area> + <areascroll condition="not{separator}++{whatsonnow}" scrollelement="menutext" mode="forthandback" orientation="horizontal" delay="1000" scrollspeed="medium" x="15%" width="44%" layer="4"> + <drawtext name="menutext" x="10" valign="center" font="{light}" fontsize="95%" color="{clrWhite}" text="{start} {title}" /> + </areascroll> + <!-- WHATSONNEXT --> + <area condition="not{separator}++{whatsonnext}" x="1%" width="6%" layer="3"> + <drawimage name="logo" imagetype="channellogo" path="{channelid}" x="10" height="100%" valign="center" /> + </area> + <area condition="not{separator}++{whatsonnext}++{timerfull}" x="53%" width="6%" layer="4"> + <drawimage imagetype="icon" path="ico_activetimer" x="{areawidth} - 0.9*{areaheight} - 10" width="0.9*{areaheight}" height="0.9*{areaheight}" valign="center" /> + </area> + <area condition="not{separator}++{whatsonnext}++{timerpartitial}" x="53%" width="6%" layer="5"> + <drawimage imagetype="icon" path="ico_activetimer" x="{areawidth} - 0.5*{areaheight} - 10" width="0.5*{areaheight}" height="0.5*{areaheight}" valign="center" /> + </area> + <areascroll condition="not{separator}++{whatsonnext}" scrollelement="menutext" mode="forthandback" orientation="horizontal" delay="1000" scrollspeed="medium" x="7%" width="52%" layer="4"> + <drawtext name="menutext" x="10" valign="center" font="{light}" fontsize="95%" color="{clrWhite}" text="{start} {title}" /> + </areascroll> + <!-- Separator --> + <area condition="{separator}" x="0" width="68%" layer="3"> + <drawtext x="20" valign="center" font="{light}" fontsize="95%" color="{clrBlueLight}" text="{title}" /> + </area> + </listelement> + <!-- additional element which is drawn for current element --> + <!-- Available Variables schedules menu currentelement: + {title} title of event + {shorttext} shorttext of event + {description} detailed description of event + {start} event start time in hh::mm + {stop} event stop time + {day} day of current event + {date} date of current event in dd.mm.yy + {running} true if event is currently running + {elapsed} elapsed time of event, if not running 0 + {duration} duration of event + {channelid} ChannelID as path to display channel logo + {hasposter} true if a scraped poster is available for this element + {posterwidth} width of scraped poster + {posterheight} height of scraped poster + {posterpath} absolute path of scraped poster + {timerpartitial} true if partitial timer is set for the event + {timerfull} true if full timer is set for the event + {whatson} true if menu "What's on" is displayed + {whatsonnow} true if menu "What's on now" is displayed + {whatsonnext} true if menu "What's on next" is displayed + {schedule[]} array with next 10 schedules, only for whatsonnow and whatsonnext + {schedule[title]} title of event + {schedule[shorttext]} shorttext of event + {schedule[start]} start time of event in hh:mm + {schedule[stop]} stop time of event in hh:mm + --> + <currentelement delay="500" fadetime="0"> + <area condition="{whatson}" x="63%" y="0" width="36%" height="100%" layer="2"> + <!-- title --> + <drawtext align="center" y="0" font="{semibold}" width="{areawidth}-20" fontsize="8%" color="{clrWhite}" text="{title}" /> + <!-- progress bar if event is running --> + <drawtext condition="{running}" name="start" x="{areawidth}/4 - {width(start)}" y="{areaheight}/16 + 20" font="{light}" fontsize="{areaheight}/18" color="{clrWhite}" text="{start}" /> + <drawtext condition="{running}" name="stop" x="{areawidth}*3/4" y="{areaheight}/16 + 20" font="{light}" fontsize="{areaheight}/18" color="{clrWhite}" text="{stop}" /> + <drawrectangle condition="{running}" x="{areawidth}/4+10" y="{areaheight}/16 + 20 + {areaheight}/36" width="{areawidth}/2 - 20" height="1" color="{clrWhite}" /> + <drawrectangle condition="{running}" x="{areawidth}/4+10" y="{areaheight}/16 + 20 + {areaheight}/36 -2" width="{areawidth}/2 * {elapsed} / {duration} - 20 * {elapsed} / {duration}" height="5" color="{clrWhite}" /> + <!-- start and stop if event is not running --> + <drawtext condition="not{running}" x="10" y="{areaheight}/18 + 20" font="{light}" fontsize="{areaheight}/20" color="{clrWhite}" text="{start} - {stop} ({duration} min)" /> + <!-- scraper poster --> + <drawimage condition="{hasposter}" name="poster" imagetype="image" path="{posterpath}" x="10" y="{posy(start)} + {height(start)} + 20" width="{areawidth}/3" height="{areawidth}/3 * {posterheight} / {posterwidth}"/> + <!-- description --> + <drawtextbox condition="{hasposter}" x="10" y="{posy(poster)}" width="99%" height="{areaheight} - {posy(poster)}" float="topleft" floatwidth="{width(poster)} + 10" floatheight="{height(poster)} + 20" font="{light}" fontsize="{areaheight}/20" color="{clrWhite}" text="{description}" /> + <drawtextbox condition="not{hasposter}" x="10" y="{posy(poster)}" width="99%" height="{areaheight} - {posy(poster)}" font="{light}" fontsize="{areaheight}/20" color="{clrWhite}" text="{description}" /> + </area> + <area condition="{whatsonnow}||{whatsonnext}" x="63%" y="0" width="36%" height="85%" layer="2"> + <!-- title --> + <drawtext align="center" y="0" font="{semibold}" width="{areawidth}-20" fontsize="10%" color="{clrWhite}" text="{title}" /> + <!-- progress bar if event is running --> + <drawtext condition="{running}" name="start" x="{areawidth}/4 - {width(start)}" y="{areaheight}/16 + 15" font="{light}" fontsize="{areaheight}/15" color="{clrWhite}" text="{start}" /> + <drawtext condition="{running}" name="stop" x="{areawidth}*3/4" y="{areaheight}/16 + 15" font="{light}" fontsize="{areaheight}/15" color="{clrWhite}" text="{stop}" /> + <drawrectangle condition="{running}" x="{areawidth}/4+10" y="{areaheight}/16 + 15 + {areaheight}/30" width="{areawidth}/2 - 20" height="1" color="{clrWhite}" /> + <drawrectangle condition="{running}" x="{areawidth}/4+10" y="{areaheight}/16 + 15 + {areaheight}/30 -2" width="{areawidth}/2 * {elapsed} / {duration} - 20 * {elapsed} / {duration}" height="5" color="{clrWhite}" /> + <!-- start and stop if event is not running --> + <drawtext condition="not{running}" x="10" y="{areaheight}/18 + 15" font="{light}" fontsize="{areaheight}/20" color="{clrWhite}" text="{start} - {stop} ({duration} min)" /> + <!-- scraper poster --> + <drawimage condition="{hasposter}" name="poster" imagetype="image" path="{posterpath}" x="10" y="{posy(start)} + {height(start)} + 10" width="{areawidth}/3" height="{areawidth}/3 * {posterheight} / {posterwidth}"/> + <!-- description --> + <drawtextbox condition="{hasposter}" x="10" y="{posy(poster)}" width="99%" height="{areaheight} - {posy(poster)}" float="topleft" floatwidth="{width(poster)} + 10" floatheight="{height(poster)} + 10" font="{light}" fontsize="{areaheight}/18" color="{clrWhite}" text="{description}" /> + <drawtextbox condition="not{hasposter}" x="10" y="{posy(poster)}" width="99%" height="{areaheight} - {posy(poster)}" font="{light}" fontsize="{areaheight}/18" color="{clrWhite}" text="{description}" /> + </area> + <areascroll condition="{whatsonnow}||{whatsonnext}" mode="forthandback" orientation="vertical" delay="1000" scrollspeed="medium" x="63%" y="85%" width="36%" height="15%" layer="2"> + <drawtext x="10" y="0" font="{semibold}" fontsize="30%" color="{clrWhite}" text="Next Schedules:" /> + <loop name="schedule" x="0" y="{areaheight}/4 + 5" orientation="vertical"> + <drawtext x="10" font="{light}" width="{areawidth}-20" fontsize="30%" color="{clrWhite}" text="{schedule[start]} {schedule[title]}" /> + </loop> + </areascroll> + </currentelement> + </menuitems> + <!-- Available Variables scrollbar: + {height} height in one-tenth of a percent of total height + {offset} offset from top in one-tenth of a percent of total height + --> + <scrollbar> + <area x="60%" y="10%" width="2%" height="82%" layer="3"> + <fill color="{clrWhite}" /> + <drawrectangle x="2" y="2" width="{areawidth} - 4" height="{areaheight} - 4" color="{clrTransparent}" /> + <drawrectangle x="4" y="4 + {areaheight} * {offset} / 1000" width="{areawidth} - 8" height="{areaheight} * {height} / 1000 - 8" color="{clrWhite}" /> + </area> + </scrollbar> +</menuschedules>
\ 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 @@ +<menusetup x="0" y="0" width="100%" height="100%" fadetime="0"> + <!-- + static content of main menu, is only drawn once at main menu startup + --> + <background> + <area x="0" y="0" width="100%" height="100%" layer="1"> + <fill color="{clrTransBlack}" /> + </area> + <area x="84%" y="0" width="16%" height="7%" layer="2"> + <drawrectangle x="0" y="0" width="52%" height="100%" color="{clrTransBlueLight}" /> + </area> + </background> + <!-- Available Variables header: + {title} title of current menu + {vdrversion} running VDR Version + --> + <header> + <area x="0" y="0" width="70%" height="7%" layer="2"> + <drawtext x="10" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{title}" /> + </area> + </header> + <!-- Available Variables datetime: + {time} time in hh:mm + {day} day in digits + {dayleadingzero} day in digits with leading 0 + {dayname} Full name of the day + {daynameshort} Short 3 char name of the day + {month} month in digits with leading 0 + {monthname} Full name of the month + {year} year in yyyy + --> + <datetime> + <area x="84%" y="0" width="8%" height="7%" layer="3"> + <drawtext align="right" y="0%" font="{light}" fontsize="55%" color="{clrWhite}" text="{dayname}" /> + <drawtext align="right" y="45%" font="{light}" fontsize="55%" color="{clrWhite}" text="{day}. {monthname}" /> + </area> + <area x="92%" y="0" width="8%" height="7%" layer="3"> + <drawtext align="center" valign="center" font="{light}" fontsize="100%" color="{clrWhite}" text="{time}" /> + </area> + </datetime> + + <!-- Available Variables colorbuttons: + {red} label of red button + {green} label of green button + {yellow} label of yellow button + {blue} label of blue button + --> + <colorbuttons> + <area x="0" y="93%" width="25%" height="7%" layer="2"> + <drawtext x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{red}" /> + <drawrectangle x="0" y="0" width="10" height="100%" color="{clrRed}" /> + </area> + <area x="25%" y="93%" width="25%" height="7%" layer="2"> + <drawtext x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{green}" /> + <drawrectangle x="0" y="0" width="10" height="100%" color="{clrGreen}" /> + </area> + <area x="50%" y="93%" width="25%" height="7%" layer="2"> + <drawtext x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{yellow}" /> + <drawrectangle x="0" y="0" width="10" height="100%" color="{clrYellow}" /> + </area> + <area x="75%" y="93%" width="25%" height="7%" layer="2"> + <drawtext x="20" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{blue}" /> + <drawrectangle x="0" y="0" width="10" height="100%" color="{clrBlue}" /> + </area> + </colorbuttons> + + <menuitems x="0" y="7%" orientation="vertical" width="98%" height="86%" align="center" numlistelements="10"> + <!-- Available Variables setup menu listelement: + {label} label of menu item + {number} number of menu item (or empty string if not set) + {icon} path of appropriate icon + {current} true if item is currently selected + {separator} true if item is a list separator + --> + <listelement> + <area x="0" width="60%" layer="2"> + <fill condition="not{current}" color="{clrTransparent}" /> + <fill condition="{current}" color="{clrTransBlueLight}" /> + </area> + <areascroll scrollelement="menutext" mode="forthandback" orientation="horizontal" delay="1000" scrollspeed="medium" x="0" width="60%" layer="3"> + <drawtext name="menutext" x="20" valign="center" font="{light}" fontsize="90%" color="{clrWhite}" text="{number} {label}" /> + </areascroll> + </listelement> + <!-- additional element which is drawn for current element --> + <!-- Available Variables main menu currentelement: + {label} label of menu item + {number} number of menu item (or empty string if not set) + {icon} path of appropriate icon + --> + <currentelement delay="50" fadetime="0"> + <area x="61%" y="30%" width="37%" height="36%" layer="2"> + <fill color="{clrTransBlueLight}" /> + </area> + <area x="61%" y="30%" width="37%" height="36%" layer="3"> + <drawimage imagetype="menuicon" path="{icon}" align="center" valign="center" width="{areaheight} - 10" height="{areaheight} - 10"/> + </area> + </currentelement> + </menuitems> + + <scrollbar> + <area x="98%" y="7%" width="2%" height="86%" layer="2"> + <fill color="{clrWhite}" /> + <drawrectangle x="2" y="2" width="{areawidth} - 4" height="{areaheight} - 4" color="{clrTransparent}" /> + <drawrectangle x="4" y="4 + {areaheight} * {offset} / 1000" width="{areawidth} - 8" height="{areaheight} * {height} / 1000 - 8" color="{clrWhite}" /> + </area> + </scrollbar> +</menusetup> 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 @@ +<menutimers x="0" y="0" width="100%" height="100%" fadetime="0"> + <menuitems x="0" y="10%" orientation="vertical" width="100%" height="82%" align="center" numlistelements="16"> + <!-- Available Variables channels menu listelement: + {title} Title of Timer + {timerstart} Start Time of Timer in hh::mm + {timerstop} End Time of Timer in hh::mm + {day} Day (numerical) + {dayname} Day, for repeating timers days where timer is active + {channelname} Name of channel which is set for the timer + {channelid} ID of channel which is set for the timer (for dispalying channel logo) + {channelnumber} Number of channel which is set for the timer + {eventtitle} Title of corresponding event + {eventstart} Start Time of corresponding event in hh::mm + {eventstop} Stop Time of corresponding event in hh::mm + {current} true if item is currently selected + {flagactive} true if timer is active + {flaginstant} true if timer is an instant timer + {flagvps} true if timer uses VPS + {flagrecording} true if is recording currently + {flagpending} true if timer is pending + --> + <listelement> + <!-- Background --> + <area x="1%" width="58%" layer="2"> + <fill condition="not{current}" color="{clrTransparent}" /> + <fill condition="{current}" color="{clrTransBlueLight}" /> + </area> + <area x="1%" width="58%" layer="2"> + <drawimage condition="{flagactive}" name="active" imagetype="icon" path="ico_timer_active" x="0" width="0.9*{areaheight}" height="0.9*{areaheight}" valign="center" /> + <drawimage condition="not{flagactive}" name="active" imagetype="icon" path="ico_timer_inactive" x="0" width="0.9*{areaheight}" height="0.9*{areaheight}" valign="center" /> + <drawimage condition="{flagrecording}" name="active" imagetype="icon" path="ico_timer_recording" x="0" width="0.9*{areaheight}" height="0.9*{areaheight}" valign="center" /> + </area> + <areascroll scrollelement="timertext" mode="forthandback" orientation="horizontal" delay="1000" scrollspeed="medium" x="5%" width="54%" layer="3"> + <drawtext name="timertext" x="10" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{dayname} {day}. {timerstart} - {timerstop}: {title}" /> + </areascroll> + </listelement> + <!-- additional element which is drawn for current element --> + <!-- Available Variables channels menu currentelement: + {title} Title of Timer + {timerstart} Start Time of Timer in hh::mm + {timerstop} End Time of Timer in hh::mm + {day} Day (numerical) + {dayname} Day, for repeating timers days where timer is active + {channelname} Name of channel which is set for the timer + {channelid} ID of channel which is set for the timer (for dispalying channel logo) + {channelnumber} Number of channel which is set for the timer + {eventtitle} Title of corresponding event + {eventstart} Start Time of corresponding event in hh::mm + {eventstop} Stop Time of corresponding event in hh::mm + {eventshorttext} Short Text corresponding event + {eventdescription} Description corresponding event + {hasposter} true if a scraped poster is available for event + {posterwidth} width of scraped poster + {posterheight} height of scraped poster + {posterpath} absolute path of scraped poster + {flagactive} true if timer is active + {flaginstant} true if timer is an instant timer + {flagvps} true if timer uses VPS + {flagrecording} true if is recording currently + {flagpending} true if timer is pending + --> + <currentelement delay="500" fadetime="0"> + <area x="63%" y="0" width="36%" height="15%" layer="2"> + <drawimage name="logo" imagetype="channellogo" path="{channelid}" x="10" y="0" height="100%" /> + <drawtext name="channum" x="{width(logo)} + 20" y="{areaheight}/6" width="{areawidth} - {width(logo)} - 30" font="{light}" fontsize="40%" color="{clrWhite}" text="Channel No. {channelnumber}" /> + <drawtext name="channame" x="{width(logo)} + 20" y="{areaheight}/3 + {areaheight}/6" width="{areawidth} - {width(logo)} - 30" font="{semibold}" fontsize="40%" color="{clrWhite}" text="{channelname}" /> + </area> + <area x="63%" y="15%" width="36%" height="70%" layer="2"> + <!-- title --> + <drawtext name="title" align="center" y="0" font="{semibold}" width="{areawidth}-20" fontsize="{areaheight}/10" color="{clrWhite}" text="{eventtitle}" /> + <!-- scraper poster --> + <drawimage condition="{hasposter}" name="poster" imagetype="image" path="{posterpath}" x="10" y="{posy(title)} + {height(title)} + 10" width="{areawidth}/3" height="{areawidth}/3 * {posterheight} / {posterwidth}"/> + <!-- description --> + <drawtextbox condition="{hasposter}" x="10" y="{posy(poster)}" width="99%" height="{areaheight} - {posy(poster)}" float="topleft" floatwidth="{width(poster)} + 10" floatheight="{height(poster)} + 20" font="{light}" fontsize="{areaheight}/14" color="{clrWhite}" text="{eventdescription}" /> + <drawtextbox condition="not{hasposter}" x="10" y="{posy(poster)}" width="99%" height="{areaheight} - {posy(poster)}" font="{light}" fontsize="{areaheight}/14" color="{clrWhite}" text="{eventdescription}" /> + </area> + </currentelement> + </menuitems> + <!-- Available Variables colorbuttons: + {height} height in one-tenth of a percent of total height + {offset} offset from top in one-tenth of a percent of total height + --> + <scrollbar> + <area x="60%" y="10%" width="2%" height="82%" layer="3"> + <fill color="{clrWhite}" /> + <drawrectangle x="2" y="2" width="{areawidth} - 4" height="{areaheight} - 4" color="{clrTransparent}" /> + <drawrectangle x="4" y="4 + {areaheight} * {offset} / 1000" width="{areawidth} - 8" height="{areaheight} * {height} / 1000 - 8" color="{clrWhite}" /> + </area> + </scrollbar> +</menutimers>
\ 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 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE displaymessage SYSTEM "../../dtd/displaymessage.dtd">
+
+<displaymessage x="5%" y="80%" width="90%" height="15%" fadetime="{fadeTime}">
+ <background>
+ <area x="0" y="0" width="100%" height="100%" layer="1">
+ <fill color="{clrTransBlack}" />
+ </area>
+ </background>
+
+ <!-- Available Variables message:
+ {text} message text
+ {status} true if message is a status message
+ {info} true if message is a info message
+ {warning} true if message is a warn message
+ {error} true if message is a error message
+ -->
+ <message>
+ <area x="0" y="0" width="100%" height="100%" layer="2">
+ <drawrectangle condition="{status}" x="20" y="0" width="20" height="100%" color="{clrGreen}" />
+ <drawrectangle condition="{info}" x="20" y="0" width="20" height="100%" color="{clrBlue}" />
+ <drawrectangle condition="{warning}" x="20" y="0" width="20" height="100%" color="{clrYellow}" />
+ <drawrectangle condition="{error}" x="20" y="0" width="20" height="100%" color="{clrRed}" />
+ <drawtext align="center" valign="center" width="{areawidth} - 80" font="{light}" fontsize="50%" color="{clrWhite}" text="{text}" />
+ </area>
+ </message>
+</displaymessage>
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 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE displayreplay SYSTEM "../../dtd/displayreplay.dtd"> + +<displayreplay x="0" y="0" width="100%" height="100%" fadetime="{fadeTime}"> + <background> + <!-- background infobar --> + <area x="0" y="80%" width="100%" height="20%" layer="1"> + <fill color="{clrTransBlack}" /> + </area> + <!-- background datetime --> + <area x="70%" y="0" width="30%" height="13%" layer="1"> + <fill color="{clrTransBlack}" /> + <drawrectangle x="0" y="0" width="45%" height="100%" color="{clrTransBlueLight}" /> + </area> + </background> + + <backgroundmodeonly> + <!-- background small infobar --> + <area x="25%" y="85%" width="50%" height="10%" layer="1"> + <fill color="{clrTransBlack}" /> + </area> + <!-- background datetime --> + <area x="70%" y="0" width="30%" height="13%" layer="1"> + <fill color="{clrTransBlack}" /> + <drawrectangle x="0" y="0" width="45%" height="100%" color="{clrTransBlueLight}" /> + </area> + </backgroundmodeonly> + + <!-- Available Variables datetime: + {time} time in hh:mm + {day} day in digits + {dayleadingzero} day in digits with leading 0 + {dayname} Full name of the day + {daynameshort} Short 3 char name of the day + {month} month in digits with leading 0 + {monthname} Full name of the month + {monthnameshort} 3 letter abbrivation of month name + {year} year in yyyy + --> + <datetime> + <area x="70%" y="0" width="13%" height="13%" layer="2"> + <drawtext align="right" y="0" font="{light}" fontsize="50%" color="{clrWhite}" text="{dayname}" /> + <drawtext align="right" y="48%" font="{light}" fontsize="50%" color="{clrWhite}" text="{day}. {monthnameshort}" /> + </area> + <area x="85%" y="0" width="13%" height="13%" layer="2"> + <drawtext align="center" valign="center" font="{light}" fontsize="100%" color="{clrWhite}" text="{time}" /> + </area> + </datetime> + + <!-- Available Variables scrapercontent: + {mediapath} Full Path of Poster or Banner to use in image path attribute + {mediawidth} width of image in pixel + {mediaheight} height of image in pixel + {isbanner} true if image is a banner, false if it is a poster + --> + <scrapercontent> + <area condition="{isbanner}" x="0" y="0" width="{areaheight}*0.13*{mediawidth}/{mediaheight}" height="13%" layer="2"> + <drawimage imagetype="image" path="{mediapath}" align="center" valign="center" width="{areawidth}" height="{areaheight}"/> + </area> + <area condition="not{isbanner}" x="0" y="0" width="{areaheight}*0.5*{mediawidth}/{mediaheight}" height="50%" layer="2"> + <drawimage imagetype="image" path="{mediapath}" x="5" y="5" width="{areawidth}-10" height="{areaheight}-10"/> + </area> + </scrapercontent> + + <!-- Available Variables rectitle: + {rectitle} Title of Recording + {recsubtitle} Subtitle of the Recording + {recdate} Date Recording in dd.mm.yy + {rectime} Time of Recording in hh:mm + --> + <rectitle> + <area x="1%" y="80%" width="69%" height="8%" layer="2"> + <drawtext x="0" name="title" valign="center" width="{areawidth}" font="{semibold}" fontsize="85%" color="{clrBlueLight}" text="{rectitle}" /> + <drawtext x="{width(title)}+10" valign="center" width="{areawidth}-{width(title)}-10" font="{light}" fontsize="85%" color="{clrWhite}" text="{recsubtitle}" /> + </area> + </rectitle> + + <!-- Available Variables recinfo: + {screenwidth} width of currently displayed recording in px + {screenheight} height of currently displayed recording in px + {resolution} resolution: hd1080i, hd720p, sd576i + {aspect} screen aspect, each 4:3, 16:9 or 21:9 + {isHD} true for hd1080i and hd720p + {isWideScreen} true if aspect is 16:9 or 21:9 + --> + <recinfo> + <area x="70%" y="80%" width="29%" height="8%" layer="2"> + <!-- widescreen icon --> + <drawimage name="widescreen" condition="{isWideScreen}" imagetype="icon" path="ico_widescreen_on" x="{areawidth} - {width(widescreen)}" valign="center" width="{areaheight}*0.8*1.87" height="{areaheight}*0.8"/> + <drawimage condition="not{isWideScreen}" imagetype="icon" path="ico_widescreen_off" x="{areawidth} - {width(widescreen)}" valign="center" width="{areaheight}*0.8*1.87" height="{areaheight}*0.8"/> + <!-- hd/sd icon --> + <drawimage name="hd" condition="{isHD}" imagetype="icon" path="ico_hd_on" x="{posx(widescreen)} - 15 - {width(hd)}" valign="center" width="{areaheight}*0.8*2.04" height="{areaheight}*0.8"/> + <drawimage condition="not{isHD}" imagetype="icon" path="ico_hd_off" x="{posx(widescreen)} - 15 - {width(hd)}" valign="center" width="{areaheight}*0.8*2.04" height="{areaheight}*0.8"/> + <!-- screenresolution text --> + <drawtext name="reslabel" x="{posx(hd)} - 30 - {width(reslabel)}" valign="center" font="{light}" fontsize="60%" color="{clrWhite}" text="{screenwidth}x{screenheight}" /> + </area> + </recinfo> + + <!-- Available Variables currenttime: + {reccurrent} Current Time in hh:mm:ss + --> + <currenttime> + <area x="1%" y="92%" width="30%" height="7%" layer="2"> + <drawtext x="0" valign="center" font="{light}" fontsize="100%" color="{clrTransBlueLight}" text="{reccurrent}" /> + </area> + </currenttime> + + <!-- Available Variables totaltime: + {rectotal} Total Time in hh:mm:ss + --> + <totaltime> + <area x="69%" y="92%" width="30%" height="7%" layer="2"> + <drawtext align="right" valign="center" font="{light}" fontsize="100%" color="{clrWhite}" text="{rectotal}" /> + </area> + </totaltime> + + <!-- Available Variables progressbar: + {current} current frame of recording + {total} total frames of recording + --> + <progressbar> + <area x="5%" y="89%" width="90%" height="3%" layer="2"> + <fill color="{clrDarkGray}" /> + <drawrectangle x="0" y="0" width="{current}/{total}*{areawidth}" height="100%" color="{clrTransBlueLight}" /> + </area> + </progressbar> + + <!-- Available Variables cutmarks: + {marks[]} array of available marks + {marks[position]} frame of current mark + {marks[endposition]} frame where startmark ends + {marks[total]} total number of frames + {marks[startmark]} true if mark is start mark + --> + <cutmarks> + <area x="5%" y="89%" width="90%" height="3%" layer="3"> + <loop name="marks" x="0" y="0" orientation="absolute"> + <drawrectangle x="{marks[position]}/{marks[total]}*{areawidth}" y="0" width="1" height="100%" color="{clrWhite}" /> + <drawrectangle condition="{marks[startmark]}" x="{marks[position]}/{marks[total]}*{areawidth}" y="0" width="5" height="1" color="{clrWhite}" /> + <drawrectangle condition="{marks[startmark]}" x="{marks[position]}/{marks[total]}*{areawidth}" y="{areaheight}-1" width="5" height="1" color="{clrWhite}" /> + <drawrectangle condition="not{marks[startmark]}" x="{marks[position]}/{marks[total]}*{areawidth} - 5" y="0" width="5" height="1" color="{clrWhite}" /> + <drawrectangle condition="not{marks[startmark]}" x="{marks[position]}/{marks[total]}*{areawidth} - 5" y="{areaheight}-1" width="5" height="1" color="{clrWhite}" /> + <drawrectangle condition="{marks[startmark]}" x="{marks[position]}/{marks[total]}*{areawidth}" y="30%" width="{marks[endposition]}/{marks[total]}*{areawidth} - {marks[position]}/{marks[total]}*{areawidth}" height="40%" color="{clrWhite}" /> + </loop> + </area> + </cutmarks> + + <!-- Available Variables controlicons and controliconsmodeonly: + {play} true if recording is played currently + {pause} true if recording is paused + {forward} true if fast forwarding + {forward1x} true if fast forwarding 1x (with 3 trickspeeds) + {forward2x} true if fast forwarding 2x (with 3 trickspeeds) + {forward3x} true if fast forwarding 3x (with 3 trickspeeds) + {rewind} true if rewinding + {rewind1x} true if rewinding 1x (with 3 trickspeeds) + {rewind2x} true if rewinding 2x (with 3 trickspeeds) + {rewind3x} true if rewinding 3x (with 3 trickspeeds) + --> + <controlicons> + <area x="30%" y="93%" width="40%" height="7%" layer="3"> + <drawimage condition="not{rewind} ++ not{rewind1x} ++ not{rewind2x} ++ not{rewind3x}" imagetype="icon" path="ico_rew_off" x="{areawidth}/2 - 2*{areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{rewind}" imagetype="icon" path="ico_rew" x="{areawidth}/2 - 2*{areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{rewind1x}" imagetype="icon" path="ico_rew_1x" x="{areawidth}/2 - 2*{areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{rewind2x}" imagetype="icon" path="ico_rew_2x" x="{areawidth}/2 - 2*{areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{rewind3x}" imagetype="icon" path="ico_rew_3x" x="{areawidth}/2 - 2*{areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + + <drawimage condition="not{pause}" imagetype="icon" path="ico_pause_off" x="{areawidth}/2 - {areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{pause}" imagetype="icon" path="ico_pause" x="{areawidth}/2 - {areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + + <drawimage condition="not{play}" imagetype="icon" path="ico_play_off" x="{areawidth}/2" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{play}" imagetype="icon" path="ico_play" x="{areawidth}/2" y="0" width="{areaheight}" height="{areaheight}"/> + + <drawimage condition="not{forward} ++ not{forward1x} ++ not{forward2x} ++ not{forward3x}" imagetype="icon" path="ico_ff_off" x="{areawidth}/2 + {areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{forward}" imagetype="icon" path="ico_ff" x="{areawidth}/2 + {areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{forward1x}" imagetype="icon" path="ico_ff_1x" x="{areawidth}/2 + {areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{forward2x}" imagetype="icon" path="ico_ff_2x" x="{areawidth}/2 + {areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{forward3x}" imagetype="icon" path="ico_ff_3x" x="{areawidth}/2 + {areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + </area> + </controlicons> + + <controliconsmodeonly> + <area x="25%" y="85%" width="50%" height="10%" layer="3"> + <drawimage condition="not{rewind} ++ not{rewind1x} ++ not{rewind2x} ++ not{rewind3x}" imagetype="icon" path="ico_rew_off" x="{areawidth}/2 - 2*{areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{rewind}" imagetype="icon" path="ico_rew" x="{areawidth}/2 - 2*{areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{rewind1x}" imagetype="icon" path="ico_rew_1x" x="{areawidth}/2 - 2*{areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{rewind2x}" imagetype="icon" path="ico_rew_2x" x="{areawidth}/2 - 2*{areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{rewind3x}" imagetype="icon" path="ico_rew_3x" x="{areawidth}/2 - 2*{areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + + <drawimage condition="not{pause}" imagetype="icon" path="ico_pause_off" x="{areawidth}/2 - {areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{pause}" imagetype="icon" path="ico_pause" x="{areawidth}/2 - {areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + + <drawimage condition="not{play}" imagetype="icon" path="ico_play_off" x="{areawidth}/2" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{play}" imagetype="icon" path="ico_play" x="{areawidth}/2" y="0" width="{areaheight}" height="{areaheight}"/> + + <drawimage condition="not{forward} ++ not{forward1x} ++ not{forward2x} ++ not{forward3x}" imagetype="icon" path="ico_ff_off" x="{areawidth}/2 + {areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{forward}" imagetype="icon" path="ico_ff" x="{areawidth}/2 + {areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{forward1x}" imagetype="icon" path="ico_ff_1x" x="{areawidth}/2 + {areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{forward2x}" imagetype="icon" path="ico_ff_2x" x="{areawidth}/2 + {areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{forward3x}" imagetype="icon" path="ico_ff_3x" x="{areawidth}/2 + {areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + </area> + </controliconsmodeonly> + + <!-- Available Variables jump: + {jump} time to jump to in hh:mm + --> + <jump> + <area x="35%" y="45%" width="30%" height="10%" layer="1"> + <fill color="{clrTransBlack}" /> + </area> + <area x="35%" y="45%" width="30%" height="10%" layer="2"> + <drawtext align="center" valign="center" font="{light}" fontsize="80%" color="{clrWhite}" text="{jump}" /> + </area> + </jump> + <!-- Available Variables message: + {text} message text + {status} true if message is a status message + {info} true if message is a info message + {warning} true if message is a warn message + {error} true if message is a error message + --> + <message> + <area x="10%" y="45%" width="80%" height="10%" layer="1"> + <drawrectangle condition="{status}" x="20" y="0" width="20" height="100%" color="{clrGreen}" /> + <drawrectangle condition="{info}" x="20" y="0" width="20" height="100%" color="{clrBlue}" /> + <drawrectangle condition="{warning}" x="20" y="0" width="20" height="100%" color="{clrYellow}" /> + <drawrectangle condition="{error}" x="20" y="0" width="20" height="100%" color="{clrRed}" /> + <drawtext align="center" valign="center" width="{areawidth} - 80" font="{light}" fontsize="40%" color="{clrWhite}" text="{text}" /> + </area> + </message> +</displayreplay> 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 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE displayvolume SYSTEM "../../dtd/displayvolume.dtd"> + +<displayvolume x="20%" y="75%" width="60%" height="20%" fadetime="{fadeTime}"> + <background> + <area x="0" y="0" width="100%" height="100%" layer="1"> + <fill color="{clrTransBlack}" /> + </area> + </background> + + <!-- Available Variables volume: + {volume} current volume, range from 0 to 255 + {volumepercent} current volume in % + {maxvolume} maximal volume + {mute} true if volume is muted + --> + <volume> + <area x="0" y="0" width="100%" height="50%" layer="2"> + <drawtext x="10" valign="center" font="{light}" fontsize="100%" color="{clrWhite}" text="{tr(volume)}: {volumepercent}%" /> + <drawimage condition="not{mute}" imagetype="icon" path="ico_volume" x="{areawidth} - {areaheight} - 5" y="5" width="{areaheight}-5" height="{areaheight}-5"/> + <drawimage condition="{mute}" imagetype="icon" path="ico_mute" x="{areawidth} - {areaheight} - 5" y="5" width="{areaheight}-5" height="{areaheight}-5"/> + </area> + <area x="5%" y="60%" width="90%" height="30%" layer="2"> + <fill color="{clrDarkGray}" /> + <drawrectangle x="0" y="0" width="{volume}/{maxvolume}*{areawidth}" height="100%" color="{clrTransBlueLight}" /> + </area> + </volume> + +</displayvolume> 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 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE globals SYSTEM "../../dtd/globals.dtd"> + +<globals> + <!-- + define all your needed colors here + --> + <colors> + <color name="clrRed">FFFF0000</color> + <color name="clrGreen">FF5FE200</color> + <color name="clrYellow">FFE2DA00</color> + <color name="clrBlue">FF007FE2</color> + <color name="clrTransBlack">C0000000</color> + <color name="clrSemiTransBlack">D0000000</color> + <color name="clrBlueLight">FF1E8BD7</color> + <color name="clrTransBlueLight">C01E8BD7</color> + <color name="clrTransWhite">C0FFFFFF</color> + <color name="clrWhite">FFFFFFFF</color> + <color name="clrDarkGray">FF14141E</color> + <color name="clrTransparent">00000000</color> + </colors> + <!-- + these variables can be used everywhere in the templates + variabls of type int can also be used as conditions, just + set such a variable to 1 for true and 0 for false + --> + <variables> + <var type="int" name="border">5</var> + <var type="int" name="fadeTime">0</var> + <var type="string" name="stringglobal">hützligrütz</var> + </variables> + <!-- + translations used in the skin + --> + <translations> + <token name="tr(activetimers)"> + <trans lang="en_EN">Active Timers</trans> + <trans lang="de_DE">Aktive Timer</trans> + </token> + <token name="tr(activetimer)"> + <trans lang="en_EN">Active Timer</trans> + <trans lang="de_DE">Aktiver Timer</trans> + </token> + <token name="tr(conflicts)"> + <trans lang="en_EN">Conflicts</trans> + <trans lang="de_DE">Konflikte</trans> + </token> + <token name="tr(disc)"> + <trans lang="en_EN">Disc</trans> + <trans lang="de_DE">Disk</trans> + </token> + <token name="tr(free)"> + <trans lang="en_EN">free</trans> + <trans lang="de_DE">frei</trans> + </token> + <token name="tr(hours)"> + <trans lang="en_EN">hours</trans> + <trans lang="de_DE">Stunden</trans> + </token> + <token name="tr(reruns)"> + <trans lang="en_EN">Reruns</trans> + <trans lang="de_DE">Wiederholungen</trans> + </token> + <token name="tr(rerunsof)"> + <trans lang="en_EN">Reruns of</trans> + <trans lang="de_DE">Wiederholungen von</trans> + </token> + <token name="tr(actors)"> + <trans lang="en_EN">Actors</trans> + <trans lang="de_DE">Schauspieler</trans> + </token> + <token name="tr(episode)"> + <trans lang="en_EN">Episode</trans> + <trans lang="de_DE">Folge</trans> + </token> + <token name="tr(season)"> + <trans lang="en_EN">Season</trans> + <trans lang="de_DE">Staffel</trans> + </token> + <token name="tr(gueststars)"> + <trans lang="en_EN">Guest Stars</trans> + <trans lang="de_DE">Gaststars</trans> + </token> + <token name="tr(seriesfirstaired)"> + <trans lang="en_EN">Series First Aired</trans> + <trans lang="de_DE">Erstausstrahlung der Serie</trans> + </token> + <token name="tr(episodefirstaired)"> + <trans lang="en_EN">Episode First Aired</trans> + <trans lang="de_DE">Erstausstrahlung der Episode</trans> + </token> + <token name="tr(network)"> + <trans lang="en_EN">Network</trans> + <trans lang="de_DE">TV Station</trans> + </token> + <token name="tr(genre)"> + <trans lang="en_EN">Genre</trans> + <trans lang="de_DE">Genre</trans> + </token> + <token name="tr(status)"> + <trans lang="en_EN">Status</trans> + <trans lang="de_DE">Status</trans> + </token> + <token name="tr(rating)"> + <trans lang="en_EN">Rating</trans> + <trans lang="de_DE">Bewertung</trans> + </token> + <token name="tr(episoderating)"> + <trans lang="en_EN">Episode Rating</trans> + <trans lang="de_DE">Bewertung der Folge</trans> + </token> + <token name="tr(recinfo)"> + <trans lang="en_EN">Recording Information</trans> + <trans lang="de_DE">Aufnahme Informationen</trans> + </token> + <token name="tr(seriesgalery)"> + <trans lang="en_EN">Series Galery</trans> + <trans lang="de_DE">Serien Galerie</trans> + </token> + <token name="tr(moviegalery)"> + <trans lang="en_EN">Movie Galery</trans> + <trans lang="de_DE">Spielfilm Galerie</trans> + </token> + <token name="tr(originaltitle)"> + <trans lang="en_EN">Original Title</trans> + <trans lang="de_DE">Originaltitel</trans> + </token> + <token name="tr(budget)"> + <trans lang="en_EN">Budget</trans> + <trans lang="de_DE">Budget</trans> + </token> + <token name="tr(revenue)"> + <trans lang="en_EN">Revenue</trans> + <trans lang="de_DE">Einnahmen</trans> + </token> + <token name="tr(adult)"> + <trans lang="en_EN">Adult</trans> + <trans lang="de_DE">Nur für Erwachsene</trans> + </token> + <token name="tr(releasedate)"> + <trans lang="en_EN">Release Date</trans> + <trans lang="de_DE">Erscheinungsdatum</trans> + </token> + <token name="tr(runtime)"> + <trans lang="en_EN">Runtime</trans> + <trans lang="de_DE">Laufzeit</trans> + </token> + <token name="tr(popularity)"> + <trans lang="en_EN">Popularity</trans> + <trans lang="de_DE">Popularität</trans> + </token> + <token name="tr(voteaverage)"> + <trans lang="en_EN">Vote Average</trans> + <trans lang="de_DE">Durchschnittliche Wertung</trans> + </token> + <token name="tr(homepage)"> + <trans lang="en_EN">Homepage</trans> + <trans lang="de_DE">Homepage</trans> + </token> + <token name="tr(recsize)"> + <trans lang="en_EN">Recording size</trans> + <trans lang="de_DE">Größe der Aufnahme</trans> + </token> + <token name="tr(recsizecutted)"> + <trans lang="en_EN">Cutted Recording Size</trans> + <trans lang="de_DE">Größe der geschnittenen Aufnahme</trans> + </token> + <token name="tr(reclength)"> + <trans lang="en_EN">Recording Length</trans> + <trans lang="de_DE">Länge der Aufnahme</trans> + </token> + <token name="tr(reclengthcutted)"> + <trans lang="en_EN">Cutted Recording Length</trans> + <trans lang="de_DE">Länge der geschnittenen Aufnahme</trans> + </token> + <token name="tr(bitrate)"> + <trans lang="en_EN">Bit Rate</trans> + <trans lang="de_DE">Bitrate</trans> + </token> + <token name="tr(format)"> + <trans lang="en_EN">Format</trans> + <trans lang="de_DE">Format</trans> + </token> + <token name="tr(searchtimer)"> + <trans lang="en_EN">Searchtimer</trans> + <trans lang="de_DE">Suchtimer</trans> + </token> + <token name="tr(volume)"> + <trans lang="en_EN">Volume</trans> + <trans lang="de_DE">Lautstärke</trans> + </token> + </translations> + <!-- + The three Fonts FontOSD, FontFix and FontSml configured in VDR + can be used in all template "font" attributes with this tokens: + {vdrOsd} + {vdrFix} + {vdrSml} + If you like to use further fonts, just define them below. + Syntax: + <font name="tokenname">fontname</font> + These fonts can then also be used in all templates in the "font" + attribute. + if an invalid font is used in a template, vdrOsd is used as default. + --> + <fonts> + <font name="light">VDROpen Sans Light:Light</font> + <font name="semibold">VDROpen Sans Semibold:Semibold</font> + </fonts> +</globals> 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 @@ +<?xml encoding="UTF-8"?>
+
+<!ENTITY % functions SYSTEM "functions.dtd">
+
+<!ELEMENT displayaudiotracks (background | header | menuitems)*>
+<!ATTLIST displayaudiotracks
+ x CDATA #REQUIRED
+ y CDATA #REQUIRED
+ width CDATA #REQUIRED
+ height CDATA #REQUIRED
+ fadetime CDATA #IMPLIED
+ scaletvx CDATA #IMPLIED
+ scaletvy CDATA #IMPLIED
+ scaletvwidth CDATA #IMPLIED
+ scaletvheight CDATA #IMPLIED
+>
+
+<!ELEMENT background (area|areascroll)*>
+<!ATTLIST background
+ debug CDATA #IMPLIED
+>
+
+<!ELEMENT header (area|areascroll)*>
+<!ATTLIST header
+ debug CDATA #IMPLIED
+>
+
+<!ELEMENT menuitems (listelement)>
+<!ATTLIST menuitems
+ x CDATA #REQUIRED
+ y CDATA #REQUIRED
+ width CDATA #REQUIRED
+ height CDATA #REQUIRED
+ align (left|top|center|bottom|right) #IMPLIED
+ menuitemwidth CDATA #IMPLIED
+ numlistelements CDATA #REQUIRED
+ orientation (horizontal|vertical) #REQUIRED
+>
+
+<!ELEMENT listelement (area|areascroll)*>
+
+%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 @@ +<?xml encoding="UTF-8"?>
+
+<!ENTITY % functions SYSTEM "functions.dtd">
+
+<!ELEMENT displaychannel (background | channelinfo | epginfo | progressbar | progressbarback |
+ statusinfo | screenresolution | channelgroup |
+ signalquality | signalqualityback | scrapercontent |
+ datetime | message)* >
+<!ATTLIST displaychannel
+ x CDATA #REQUIRED
+ y CDATA #REQUIRED
+ width CDATA #REQUIRED
+ height CDATA #REQUIRED
+ fadetime CDATA #IMPLIED
+ scaletvx CDATA #IMPLIED
+ scaletvy CDATA #IMPLIED
+ scaletvwidth CDATA #IMPLIED
+ scaletvheight CDATA #IMPLIED
+>
+
+<!ELEMENT background (area)*>
+<!ATTLIST background
+ debug CDATA #IMPLIED
+>
+
+<!ELEMENT channelinfo (area|areascroll)*>
+<!ATTLIST channelinfo
+ debug CDATA #IMPLIED
+>
+
+<!ELEMENT epginfo (area|areascroll)*>
+<!ATTLIST epginfo
+ debug CDATA #IMPLIED
+>
+
+<!ELEMENT progressbar (area|areascroll)*>
+<!ATTLIST progressbar
+ debug CDATA #IMPLIED
+>
+
+<!ELEMENT progressbarback (area)*>
+<!ATTLIST progressbarback
+ debug CDATA #IMPLIED
+>
+
+<!ELEMENT statusinfo (area|areascroll)*>
+<!ATTLIST statusinfo
+ debug CDATA #IMPLIED
+>
+
+<!ELEMENT screenresolution (area|areascroll)*>
+<!ATTLIST screenresolution
+ debug CDATA #IMPLIED
+>
+
+<!ELEMENT channelgroup (area|areascroll)*>
+<!ATTLIST channelgroup
+ debug CDATA #IMPLIED
+>
+
+<!ELEMENT signalquality (area|areascroll)*>
+<!ATTLIST signalquality
+ debug CDATA #IMPLIED
+>
+
+<!ELEMENT signalqualityback (area|areascroll)*>
+<!ATTLIST signalqualityback
+ debug CDATA #IMPLIED
+>
+
+<!ELEMENT scrapercontent (area|areascroll)*>
+<!ATTLIST scrapercontent
+ debug CDATA #IMPLIED
+>
+
+<!ELEMENT datetime (area|areascroll)*>
+<!ATTLIST datetime
+ debug CDATA #IMPLIED
+>
+
+<!ELEMENT message (area|areascroll)*>
+<!ATTLIST message
+ debug CDATA #IMPLIED
+>
+
+%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 @@ +<?xml encoding="UTF-8"?>
+
+<!ENTITY % functions SYSTEM "functions.dtd">
+
+<!ELEMENT displaymenu (background,header,datetime,message,colorbuttons,
+ menudefault,menumain,menusetup,menuschedules,
+ menutimers,menuchannels,menurecordings,
+ menudetailedepg,menudetailedrecording,
+ menudetailedtext)>
+<!ATTLIST displaymenu
+ x CDATA #REQUIRED
+ y CDATA #REQUIRED
+ width CDATA #REQUIRED
+ height CDATA #REQUIRED
+ fadetime CDATA #IMPLIED
+>
+
+<!ELEMENT background (area)*>
+<!ATTLIST background
+ debug CDATA #IMPLIED
+>
+
+<!ELEMENT header (area|areascroll)*>
+<!ATTLIST header
+ debug CDATA #IMPLIED
+>
+
+<!ELEMENT datetime (area|areascroll)*>
+<!ATTLIST datetime
+ debug CDATA #IMPLIED
+>
+
+<!ELEMENT message (area|areascroll)*>
+<!ATTLIST message
+ debug CDATA #IMPLIED
+>
+
+<!ELEMENT colorbuttons (area|areascroll)*>
+<!ATTLIST colorbuttons
+ debug CDATA #IMPLIED
+>
+
+<!ELEMENT timers (area|areascroll)*>
+<!ATTLIST timers
+ debug CDATA #IMPLIED
+>
+
+<!ELEMENT discusage (area|areascroll)*>
+<!ATTLIST discusage
+ debug CDATA #IMPLIED
+>
+
+<!ELEMENT devices (area|areascroll)*>
+<!ATTLIST devices
+ debug CDATA #IMPLIED
+>
+
+<!ELEMENT systemload (area|areascroll)*>
+<!ATTLIST systemload
+ debug CDATA #IMPLIED
+>
+
+<!ELEMENT scrollbar (area|areascroll)*>
+<!ATTLIST scrollbar
+ debug CDATA #IMPLIED
+>
+
+<!ELEMENT detailheader (area|areascroll)*>
+<!ATTLIST detailheader
+ debug CDATA #IMPLIED
+>
+
+<!ELEMENT tablabels (area|areascroll)*>
+<!ATTLIST tablabels
+ debug CDATA #IMPLIED
+>
+
+<!ELEMENT menudefault (background | header | datetime | colorbuttons | scrollbar | menuitems)*>
+<!ATTLIST menudefault
+ x CDATA #REQUIRED
+ y CDATA #REQUIRED
+ width CDATA #REQUIRED
+ height CDATA #REQUIRED
+ fadetime CDATA #IMPLIED
+ scaletvx CDATA #IMPLIED
+ scaletvy CDATA #IMPLIED
+ scaletvwidth CDATA #IMPLIED
+ scaletvheight CDATA #IMPLIED
+>
+
+<!ELEMENT menumain (background | header | datetime | colorbuttons | scrollbar | timers |
+ discusage | devices | systemload | menuitems)*>
+<!ATTLIST menumain
+ x CDATA #REQUIRED
+ y CDATA #REQUIRED
+ width CDATA #REQUIRED
+ height CDATA #REQUIRED
+ fadetime CDATA #IMPLIED
+ scaletvx CDATA #IMPLIED
+ scaletvy CDATA #IMPLIED
+ scaletvwidth CDATA #IMPLIED
+ scaletvheight CDATA #IMPLIED
+>
+
+<!ELEMENT menusetup (background | header | datetime | colorbuttons | scrollbar | menuitems)*>
+<!ATTLIST menusetup
+ x CDATA #REQUIRED
+ y CDATA #REQUIRED
+ width CDATA #REQUIRED
+ height CDATA #REQUIRED
+ fadetime CDATA #IMPLIED
+ scaletvx CDATA #IMPLIED
+ scaletvy CDATA #IMPLIED
+ scaletvwidth CDATA #IMPLIED
+ scaletvheight CDATA #IMPLIED
+>
+
+<!ELEMENT menuschedules (background | header | datetime | colorbuttons | scrollbar | menuitems)*>
+<!ATTLIST menuschedules
+ x CDATA #REQUIRED
+ y CDATA #REQUIRED
+ width CDATA #REQUIRED
+ height CDATA #REQUIRED
+ fadetime CDATA #IMPLIED
+ scaletvx CDATA #IMPLIED
+ scaletvy CDATA #IMPLIED
+ scaletvwidth CDATA #IMPLIED
+ scaletvheight CDATA #IMPLIED
+>
+
+<!ELEMENT menutimers (background | header | datetime | colorbuttons | scrollbar | menuitems)*>
+<!ATTLIST menutimers
+ x CDATA #REQUIRED
+ y CDATA #REQUIRED
+ width CDATA #REQUIRED
+ height CDATA #REQUIRED
+ fadetime CDATA #IMPLIED
+ scaletvx CDATA #IMPLIED
+ scaletvy CDATA #IMPLIED
+ scaletvwidth CDATA #IMPLIED
+ scaletvheight CDATA #IMPLIED
+>
+
+<!ELEMENT menuchannels (background | header | datetime | colorbuttons | scrollbar | menuitems)*>
+<!ATTLIST menuchannels
+ x CDATA #REQUIRED
+ y CDATA #REQUIRED
+ width CDATA #REQUIRED
+ height CDATA #REQUIRED
+ fadetime CDATA #IMPLIED
+ scaletvx CDATA #IMPLIED
+ scaletvy CDATA #IMPLIED
+ scaletvwidth CDATA #IMPLIED
+ scaletvheight CDATA #IMPLIED
+>
+
+<!ELEMENT menurecordings (background | header | datetime | colorbuttons | scrollbar | menuitems)*>
+<!ATTLIST menurecordings
+ x CDATA #REQUIRED
+ y CDATA #REQUIRED
+ width CDATA #REQUIRED
+ height CDATA #REQUIRED
+ fadetime CDATA #IMPLIED
+ scaletvx CDATA #IMPLIED
+ scaletvy CDATA #IMPLIED
+ scaletvwidth CDATA #IMPLIED
+ scaletvheight CDATA #IMPLIED
+>
+
+<!ELEMENT menudetailedepg (background | header | datetime | colorbuttons | scrollbar |
+ detailheader | tab | tablabels)*>
+<!ATTLIST menudetailedepg
+ x CDATA #REQUIRED
+ y CDATA #REQUIRED
+ width CDATA #REQUIRED
+ height CDATA #REQUIRED
+ fadetime CDATA #IMPLIED
+ scaletvx CDATA #IMPLIED
+ scaletvy CDATA #IMPLIED
+ scaletvwidth CDATA #IMPLIED
+ scaletvheight CDATA #IMPLIED
+>
+
+<!ELEMENT menudetailedrecording (background | header | datetime | colorbuttons | scrollbar |
+ detailheader | tab | tablabels)*>
+<!ATTLIST menudetailedrecording
+ x CDATA #REQUIRED
+ y CDATA #REQUIRED
+ width CDATA #REQUIRED
+ height CDATA #REQUIRED
+ fadetime CDATA #IMPLIED
+ scaletvx CDATA #IMPLIED
+ scaletvy CDATA #IMPLIED
+ scaletvwidth CDATA #IMPLIED
+ scaletvheight CDATA #IMPLIED
+>
+
+<!ELEMENT menudetailedtext (background | header | datetime | colorbuttons | scrollbar |
+ detailheader | tab )*>
+<!ATTLIST menudetailedtext
+ x CDATA #REQUIRED
+ y CDATA #REQUIRED
+ width CDATA #REQUIRED
+ height CDATA #REQUIRED
+ fadetime CDATA #IMPLIED
+ scaletvx CDATA #IMPLIED
+ scaletvy CDATA #IMPLIED
+ scaletvwidth CDATA #IMPLIED
+ scaletvheight CDATA #IMPLIED
+>
+
+<!ELEMENT menuitems (listelement,currentelement?)>
+<!ATTLIST menuitems
+ x CDATA #REQUIRED
+ y CDATA #REQUIRED
+ width CDATA #REQUIRED
+ height CDATA #REQUIRED
+ align (left|top|center|bottom|right) #IMPLIED
+ menuitemwidth CDATA #IMPLIED
+ determinatefont CDATA #IMPLIED
+ numlistelements CDATA #REQUIRED
+ orientation (horizontal|vertical) #REQUIRED
+>
+
+<!ELEMENT listelement (area|areascroll)*>
+<!ATTLIST listelement
+ debug CDATA #IMPLIED
+>
+
+<!ELEMENT currentelement (area|areascroll)*>
+<!ATTLIST currentelement
+ delay CDATA #REQUIRED
+ fadetime CDATA #IMPLIED
+ debug CDATA #IMPLIED
+>
+
+<!ELEMENT tab (loop|fill|drawtext|drawtextbox|drawimage|drawrectangle|drawellipse)*>
+<!ATTLIST tab
+ x CDATA #REQUIRED
+ y CDATA #REQUIRED
+ width CDATA #REQUIRED
+ height CDATA #REQUIRED
+ layer CDATA #REQUIRED
+ name CDATA #REQUIRED
+ scrollheight CDATA #REQUIRED
+ transparency CDATA #IMPLIED
+ condition CDATA #IMPLIED
+ debug (true|false) #IMPLIED
+>
+
+%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 @@ +<?xml encoding="UTF-8"?>
+
+<!ENTITY % functions SYSTEM "functions.dtd">
+
+<!ELEMENT displaymessage (background | message)*>
+<!ATTLIST displaymessage
+ x CDATA #REQUIRED
+ y CDATA #REQUIRED
+ width CDATA #REQUIRED
+ height CDATA #REQUIRED
+ fadetime CDATA #IMPLIED
+ scaletvx CDATA #IMPLIED
+ scaletvy CDATA #IMPLIED
+ scaletvwidth CDATA #IMPLIED
+ scaletvheight CDATA #IMPLIED
+>
+
+<!ELEMENT background (area)*>
+<!ATTLIST background
+ debug CDATA #IMPLIED
+>
+
+<!ELEMENT message (area|areascroll)*>
+<!ATTLIST message
+ debug CDATA #IMPLIED
+>
+
+%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 @@ +<?xml encoding="UTF-8"?>
+
+<!ENTITY % functions SYSTEM "functions.dtd">
+
+<!ELEMENT displayreplay (background | backgroundmodeonly |datetime |
+ scrapercontent | rectitle | recinfo | currenttime |
+ totaltime | progressbar | cutmarks | controlicons |
+ controliconsmodeonly | jump | message)*>
+<!ATTLIST displayreplay
+ x CDATA #REQUIRED
+ y CDATA #REQUIRED
+ width CDATA #REQUIRED
+ height CDATA #REQUIRED
+ fadetime CDATA #IMPLIED
+ scaletvx CDATA #IMPLIED
+ scaletvy CDATA #IMPLIED
+ scaletvwidth CDATA #IMPLIED
+ scaletvheight CDATA #IMPLIED
+>
+
+<!ELEMENT background (area)*>
+<!ATTLIST background
+ debug CDATA #IMPLIED
+>
+
+<!ELEMENT backgroundmodeonly (area)*>
+<!ATTLIST backgroundmodeonly
+ debug CDATA #IMPLIED
+>
+
+<!ELEMENT datetime (area|areascroll)*>
+<!ATTLIST datetime
+ debug CDATA #IMPLIED
+>
+
+<!ELEMENT scrapercontent (area|areascroll)*>
+<!ATTLIST scrapercontent
+ debug CDATA #IMPLIED
+>
+
+<!ELEMENT rectitle (area|areascroll)*>
+<!ATTLIST rectitle
+ debug CDATA #IMPLIED
+>
+
+<!ELEMENT recinfo (area|areascroll)*>
+<!ATTLIST recinfo
+ debug CDATA #IMPLIED
+>
+
+<!ELEMENT currenttime (area|areascroll)*>
+<!ATTLIST currenttime
+ debug CDATA #IMPLIED
+>
+
+<!ELEMENT totaltime (area|areascroll)*>
+<!ATTLIST totaltime
+ debug CDATA #IMPLIED
+>
+
+<!ELEMENT progressbar (area|areascroll)*>
+<!ATTLIST progressbar
+ debug CDATA #IMPLIED
+>
+
+<!ELEMENT cutmarks (area|areascroll)*>
+<!ATTLIST cutmarks
+ debug CDATA #IMPLIED
+>
+
+<!ELEMENT controlicons (area|areascroll)*>
+<!ATTLIST controlicons
+ debug CDATA #IMPLIED
+>
+
+<!ELEMENT controliconsmodeonly (area|areascroll)*>
+<!ATTLIST controliconsmodeonly
+ debug CDATA #IMPLIED
+>
+
+<!ELEMENT jump (area|areascroll)*>
+<!ATTLIST jump
+ debug CDATA #IMPLIED
+>
+
+<!ELEMENT message (area|areascroll)*>
+<!ATTLIST message
+ debug CDATA #IMPLIED
+>
+
+%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 @@ +<?xml encoding="UTF-8"?>
+
+<!ENTITY % functions SYSTEM "functions.dtd">
+
+<!ELEMENT displayvolume (background | volume)*>
+<!ATTLIST displayvolume
+ x CDATA #REQUIRED
+ y CDATA #REQUIRED
+ width CDATA #REQUIRED
+ height CDATA #REQUIRED
+ fadetime CDATA #IMPLIED
+ scaletvx CDATA #IMPLIED
+ scaletvy CDATA #IMPLIED
+ scaletvwidth CDATA #IMPLIED
+ scaletvheight CDATA #IMPLIED
+>
+
+<!ELEMENT background (area)*>
+<!ATTLIST background
+ debug CDATA #IMPLIED
+>
+
+<!ELEMENT volume (area|areascroll)*>
+<!ATTLIST volume
+ debug CDATA #IMPLIED
+>
+
+%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 @@ +<!ELEMENT area (loop|fill|drawtext|drawtextbox|drawimage|drawrectangle|drawellipse)*> +<!ATTLIST area + x CDATA #IMPLIED + y CDATA #IMPLIED + width CDATA #IMPLIED + height CDATA #IMPLIED + layer CDATA #REQUIRED + transparency CDATA #IMPLIED + condition CDATA #IMPLIED + debug (true|false) #IMPLIED +> + +<!ELEMENT areascroll (loop|fill|drawtext|drawtextbox|drawimage|drawrectangle|drawellipse)*> +<!ATTLIST areascroll + x CDATA #IMPLIED + y CDATA #IMPLIED + width CDATA #IMPLIED + height CDATA #IMPLIED + layer CDATA #REQUIRED + transparency CDATA #IMPLIED + mode (forthandback|carriagereturn) #REQUIRED + orientation (horizontal|vertical) #REQUIRED + scrollelement CDATA #IMPLIED + scrollspeed (slow|medium|fast) #REQUIRED + condition CDATA #IMPLIED + delay CDATA #REQUIRED + debug (true|false) #IMPLIED +> + +<!ELEMENT loop (drawtext|drawtextbox|drawimage|drawrectangle|drawellipse)+> +<!ATTLIST loop + x CDATA #REQUIRED + y CDATA #REQUIRED + width CDATA #IMPLIED + height CDATA #IMPLIED + columnwidth CDATA #IMPLIED + rowheight CDATA #IMPLIED + name CDATA #REQUIRED + orientation (horizontal|vertical|absolute) #REQUIRED + overflow (linewrap|cut) #IMPLIED + maxitems CDATA #IMPLIED + debug (true|false) #IMPLIED +> + +<!ELEMENT fill EMPTY> +<!ATTLIST fill + color CDATA #REQUIRED + condition CDATA #IMPLIED + debug (true|false) #IMPLIED +> + +<!ELEMENT drawtext EMPTY> +<!ATTLIST drawtext + x CDATA #IMPLIED + y CDATA #IMPLIED + width CDATA #IMPLIED + align (left|center|right) #IMPLIED + valign (top|center|bottom) #IMPLIED + color CDATA #REQUIRED + font CDATA #REQUIRED + fontsize CDATA #REQUIRED + name NMTOKEN #IMPLIED + text CDATA #REQUIRED + condition CDATA #IMPLIED + debug (true|false) #IMPLIED +> + +<!ELEMENT drawtextbox EMPTY> +<!ATTLIST drawtextbox + x CDATA #REQUIRED + y CDATA #REQUIRED + width CDATA #REQUIRED + height CDATA #IMPLIED + align (left|center|right) #IMPLIED + maxlines CDATA #IMPLIED + floatwidth CDATA #IMPLIED + floatheight CDATA #IMPLIED + float (topleft|topright) #IMPLIED + color CDATA #REQUIRED + font CDATA #REQUIRED + fontsize CDATA #REQUIRED + name NMTOKEN #IMPLIED + text CDATA #REQUIRED + condition CDATA #IMPLIED + debug NMTOKEN #IMPLIED +> + +<!ELEMENT drawrectangle EMPTY> +<!ATTLIST drawrectangle + x CDATA #REQUIRED + y CDATA #REQUIRED + width CDATA #IMPLIED + height CDATA #IMPLIED + align (left|center|right) #IMPLIED + valign (top|center|bottom) #IMPLIED + color CDATA #REQUIRED + name NMTOKEN #IMPLIED + condition CDATA #IMPLIED + debug NMTOKEN #IMPLIED + > + +<!ELEMENT drawellipse EMPTY> +<!ATTLIST drawellipse + x CDATA #REQUIRED + y CDATA #REQUIRED + width CDATA #IMPLIED + height CDATA #IMPLIED + align (left|center|right) #IMPLIED + valign (top|center|bottom) #IMPLIED + color CDATA #REQUIRED + quadrant CDATA #REQUIRED + name NMTOKEN #IMPLIED + condition CDATA #IMPLIED + debug NMTOKEN #IMPLIED + > + +<!ELEMENT drawimage EMPTY> +<!ATTLIST drawimage + x CDATA #IMPLIED + y CDATA #IMPLIED + width CDATA #IMPLIED + height CDATA #IMPLIED + align (left|center|right) #IMPLIED + valign (top|center|bottom) #IMPLIED + imagetype (channellogo|seplogo|skinpart|menuicon|icon|image) #REQUIRED + cache (true|false) #IMPLIED + path CDATA #REQUIRED + name CDATA #IMPLIED + condition CDATA #IMPLIED + debug NMTOKEN #IMPLIED +> 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 @@ +<?xml encoding="UTF-8"?>
+
+<!ELEMENT globals (colors,variables,translations,fonts)>
+<!ELEMENT colors (color)*>
+<!ELEMENT variables (var)*>
+<!ELEMENT translations (token)*>
+<!ELEMENT fonts (font)*>
+
+<!ELEMENT color (#PCDATA)>
+<!ATTLIST color
+ name NMTOKEN #REQUIRED>
+
+<!ELEMENT var (#PCDATA)>
+<!ATTLIST var
+ name NMTOKEN #REQUIRED
+ type (int|string) #REQUIRED>
+
+<!ELEMENT token (trans)+>
+<!ATTLIST token
+ name CDATA #REQUIRED>
+
+<!ELEMENT trans (#PCDATA)>
+<!ATTLIST trans
+ lang NMTOKEN #REQUIRED>
+
+<!ELEMENT font (#PCDATA)>
+<!ATTLIST font
+ name NMTOKEN #REQUIRED>
+
diff --git a/skins/nopacity/graphics/icons/ico_ac3.png b/skins/nopacity/graphics/icons/ico_ac3.png Binary files differnew file mode 100644 index 0000000..5b8614a --- /dev/null +++ b/skins/nopacity/graphics/icons/ico_ac3.png diff --git a/skins/nopacity/graphics/icons/ico_activetimer.png b/skins/nopacity/graphics/icons/ico_activetimer.png Binary files differnew file mode 100644 index 0000000..af4c33c --- /dev/null +++ b/skins/nopacity/graphics/icons/ico_activetimer.png diff --git a/skins/nopacity/graphics/icons/ico_arrow_left_channelsep.png b/skins/nopacity/graphics/icons/ico_arrow_left_channelsep.png Binary files differnew file mode 100644 index 0000000..642cd78 --- /dev/null +++ b/skins/nopacity/graphics/icons/ico_arrow_left_channelsep.png diff --git a/skins/nopacity/graphics/icons/ico_arrow_right_channelsep.png b/skins/nopacity/graphics/icons/ico_arrow_right_channelsep.png Binary files differnew file mode 100644 index 0000000..1418671 --- /dev/null +++ b/skins/nopacity/graphics/icons/ico_arrow_right_channelsep.png diff --git a/skins/nopacity/graphics/icons/ico_channelsep.png b/skins/nopacity/graphics/icons/ico_channelsep.png Binary files differnew file mode 100644 index 0000000..bf51238 --- /dev/null +++ b/skins/nopacity/graphics/icons/ico_channelsep.png diff --git a/skins/nopacity/graphics/icons/ico_cutted.png b/skins/nopacity/graphics/icons/ico_cutted.png Binary files differnew file mode 100644 index 0000000..b90c9c1 --- /dev/null +++ b/skins/nopacity/graphics/icons/ico_cutted.png diff --git a/skins/nopacity/graphics/icons/ico_daydelimiter.png b/skins/nopacity/graphics/icons/ico_daydelimiter.png Binary files differnew file mode 100644 index 0000000..7ae6053 --- /dev/null +++ b/skins/nopacity/graphics/icons/ico_daydelimiter.png diff --git a/skins/nopacity/graphics/icons/ico_discusage.png b/skins/nopacity/graphics/icons/ico_discusage.png Binary files differnew file mode 100644 index 0000000..f40fcd9 --- /dev/null +++ b/skins/nopacity/graphics/icons/ico_discusage.png diff --git a/skins/nopacity/graphics/icons/ico_dolbyoff.png b/skins/nopacity/graphics/icons/ico_dolbyoff.png Binary files differnew file mode 100644 index 0000000..ef4f17c --- /dev/null +++ b/skins/nopacity/graphics/icons/ico_dolbyoff.png diff --git a/skins/nopacity/graphics/icons/ico_dolbyon.png b/skins/nopacity/graphics/icons/ico_dolbyon.png Binary files differnew file mode 100644 index 0000000..1278abe --- /dev/null +++ b/skins/nopacity/graphics/icons/ico_dolbyon.png diff --git a/skins/nopacity/graphics/icons/ico_encrypted.png b/skins/nopacity/graphics/icons/ico_encrypted.png Binary files differnew file mode 100644 index 0000000..2b6345a --- /dev/null +++ b/skins/nopacity/graphics/icons/ico_encrypted.png diff --git a/skins/nopacity/graphics/icons/ico_ff.png b/skins/nopacity/graphics/icons/ico_ff.png Binary files differnew file mode 100644 index 0000000..3dea9d3 --- /dev/null +++ b/skins/nopacity/graphics/icons/ico_ff.png diff --git a/skins/nopacity/graphics/icons/ico_ff_1x.png b/skins/nopacity/graphics/icons/ico_ff_1x.png Binary files differnew file mode 100644 index 0000000..599256e --- /dev/null +++ b/skins/nopacity/graphics/icons/ico_ff_1x.png diff --git a/skins/nopacity/graphics/icons/ico_ff_2x.png b/skins/nopacity/graphics/icons/ico_ff_2x.png Binary files differnew file mode 100644 index 0000000..3eec356 --- /dev/null +++ b/skins/nopacity/graphics/icons/ico_ff_2x.png diff --git a/skins/nopacity/graphics/icons/ico_ff_3x.png b/skins/nopacity/graphics/icons/ico_ff_3x.png Binary files differnew file mode 100644 index 0000000..f686658 --- /dev/null +++ b/skins/nopacity/graphics/icons/ico_ff_3x.png diff --git a/skins/nopacity/graphics/icons/ico_ff_off.png b/skins/nopacity/graphics/icons/ico_ff_off.png Binary files differnew file mode 100644 index 0000000..cb551c2 --- /dev/null +++ b/skins/nopacity/graphics/icons/ico_ff_off.png diff --git a/skins/nopacity/graphics/icons/ico_fta.png b/skins/nopacity/graphics/icons/ico_fta.png Binary files differnew file mode 100644 index 0000000..55e3789 --- /dev/null +++ b/skins/nopacity/graphics/icons/ico_fta.png diff --git a/skins/nopacity/graphics/icons/ico_hd1080i.png b/skins/nopacity/graphics/icons/ico_hd1080i.png Binary files differnew file mode 100644 index 0000000..27b85ab --- /dev/null +++ b/skins/nopacity/graphics/icons/ico_hd1080i.png diff --git a/skins/nopacity/graphics/icons/ico_hd720p.png b/skins/nopacity/graphics/icons/ico_hd720p.png Binary files differnew file mode 100644 index 0000000..47317d8 --- /dev/null +++ b/skins/nopacity/graphics/icons/ico_hd720p.png diff --git a/skins/nopacity/graphics/icons/ico_mute.png b/skins/nopacity/graphics/icons/ico_mute.png Binary files differnew file mode 100644 index 0000000..4eefc75 --- /dev/null +++ b/skins/nopacity/graphics/icons/ico_mute.png diff --git a/skins/nopacity/graphics/icons/ico_pause.png b/skins/nopacity/graphics/icons/ico_pause.png Binary files differnew file mode 100644 index 0000000..cd8cad8 --- /dev/null +++ b/skins/nopacity/graphics/icons/ico_pause.png diff --git a/skins/nopacity/graphics/icons/ico_pause_off.png b/skins/nopacity/graphics/icons/ico_pause_off.png Binary files differnew file mode 100644 index 0000000..f9a9d94 --- /dev/null +++ b/skins/nopacity/graphics/icons/ico_pause_off.png diff --git a/skins/nopacity/graphics/icons/ico_play.png b/skins/nopacity/graphics/icons/ico_play.png Binary files differnew file mode 100644 index 0000000..4cc0541 --- /dev/null +++ b/skins/nopacity/graphics/icons/ico_play.png diff --git a/skins/nopacity/graphics/icons/ico_play_off.png b/skins/nopacity/graphics/icons/ico_play_off.png Binary files differnew file mode 100644 index 0000000..7fb820a --- /dev/null +++ b/skins/nopacity/graphics/icons/ico_play_off.png diff --git a/skins/nopacity/graphics/icons/ico_recfolder.png b/skins/nopacity/graphics/icons/ico_recfolder.png Binary files differnew file mode 100644 index 0000000..e3df65b --- /dev/null +++ b/skins/nopacity/graphics/icons/ico_recfolder.png diff --git a/skins/nopacity/graphics/icons/ico_recnew.png b/skins/nopacity/graphics/icons/ico_recnew.png Binary files differnew file mode 100644 index 0000000..b9166ba --- /dev/null +++ b/skins/nopacity/graphics/icons/ico_recnew.png diff --git a/skins/nopacity/graphics/icons/ico_recoff.png b/skins/nopacity/graphics/icons/ico_recoff.png Binary files differnew file mode 100644 index 0000000..4f59218 --- /dev/null +++ b/skins/nopacity/graphics/icons/ico_recoff.png diff --git a/skins/nopacity/graphics/icons/ico_recon.png b/skins/nopacity/graphics/icons/ico_recon.png Binary files differnew file mode 100644 index 0000000..14fe7be --- /dev/null +++ b/skins/nopacity/graphics/icons/ico_recon.png diff --git a/skins/nopacity/graphics/icons/ico_rew.png b/skins/nopacity/graphics/icons/ico_rew.png Binary files differnew file mode 100644 index 0000000..72408d0 --- /dev/null +++ b/skins/nopacity/graphics/icons/ico_rew.png diff --git a/skins/nopacity/graphics/icons/ico_rew_1x.png b/skins/nopacity/graphics/icons/ico_rew_1x.png Binary files differnew file mode 100644 index 0000000..333c30d --- /dev/null +++ b/skins/nopacity/graphics/icons/ico_rew_1x.png diff --git a/skins/nopacity/graphics/icons/ico_rew_2x.png b/skins/nopacity/graphics/icons/ico_rew_2x.png Binary files differnew file mode 100644 index 0000000..c5d1084 --- /dev/null +++ b/skins/nopacity/graphics/icons/ico_rew_2x.png diff --git a/skins/nopacity/graphics/icons/ico_rew_3x.png b/skins/nopacity/graphics/icons/ico_rew_3x.png Binary files differnew file mode 100644 index 0000000..6ab7a8d --- /dev/null +++ b/skins/nopacity/graphics/icons/ico_rew_3x.png diff --git a/skins/nopacity/graphics/icons/ico_rew_off.png b/skins/nopacity/graphics/icons/ico_rew_off.png Binary files differnew file mode 100644 index 0000000..ce18386 --- /dev/null +++ b/skins/nopacity/graphics/icons/ico_rew_off.png diff --git a/skins/nopacity/graphics/icons/ico_sd576i.png b/skins/nopacity/graphics/icons/ico_sd576i.png Binary files differnew file mode 100644 index 0000000..994a7a2 --- /dev/null +++ b/skins/nopacity/graphics/icons/ico_sd576i.png diff --git a/skins/nopacity/graphics/icons/ico_stereo.png b/skins/nopacity/graphics/icons/ico_stereo.png Binary files differnew file mode 100644 index 0000000..7f3610d --- /dev/null +++ b/skins/nopacity/graphics/icons/ico_stereo.png diff --git a/skins/nopacity/graphics/icons/ico_stereooff.png b/skins/nopacity/graphics/icons/ico_stereooff.png Binary files differnew file mode 100644 index 0000000..569a342 --- /dev/null +++ b/skins/nopacity/graphics/icons/ico_stereooff.png diff --git a/skins/nopacity/graphics/icons/ico_stereoon.png b/skins/nopacity/graphics/icons/ico_stereoon.png Binary files differnew file mode 100644 index 0000000..eb838b9 --- /dev/null +++ b/skins/nopacity/graphics/icons/ico_stereoon.png diff --git a/skins/nopacity/graphics/icons/ico_timer_active.png b/skins/nopacity/graphics/icons/ico_timer_active.png Binary files differnew file mode 100644 index 0000000..28c2f81 --- /dev/null +++ b/skins/nopacity/graphics/icons/ico_timer_active.png diff --git a/skins/nopacity/graphics/icons/ico_timer_inactive.png b/skins/nopacity/graphics/icons/ico_timer_inactive.png Binary files differnew file mode 100644 index 0000000..c4b1860 --- /dev/null +++ b/skins/nopacity/graphics/icons/ico_timer_inactive.png diff --git a/skins/nopacity/graphics/icons/ico_timer_recording.png b/skins/nopacity/graphics/icons/ico_timer_recording.png Binary files differnew file mode 100644 index 0000000..86dc66b --- /dev/null +++ b/skins/nopacity/graphics/icons/ico_timer_recording.png diff --git a/skins/nopacity/graphics/icons/ico_txtoff.png b/skins/nopacity/graphics/icons/ico_txtoff.png Binary files differnew file mode 100644 index 0000000..3b2eac3 --- /dev/null +++ b/skins/nopacity/graphics/icons/ico_txtoff.png diff --git a/skins/nopacity/graphics/icons/ico_txton.png b/skins/nopacity/graphics/icons/ico_txton.png Binary files differnew file mode 100644 index 0000000..148f9ef --- /dev/null +++ b/skins/nopacity/graphics/icons/ico_txton.png diff --git a/skins/nopacity/graphics/icons/ico_vdrlogo.png b/skins/nopacity/graphics/icons/ico_vdrlogo.png Binary files differnew file mode 100644 index 0000000..200cea7 --- /dev/null +++ b/skins/nopacity/graphics/icons/ico_vdrlogo.png diff --git a/skins/nopacity/graphics/icons/ico_volume.png b/skins/nopacity/graphics/icons/ico_volume.png Binary files differnew file mode 100644 index 0000000..3a72514 --- /dev/null +++ b/skins/nopacity/graphics/icons/ico_volume.png diff --git a/skins/nopacity/graphics/menuicons/customicons/Applikationen.png b/skins/nopacity/graphics/menuicons/customicons/Applikationen.png Binary files differnew file mode 100644 index 0000000..3c3b616 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/customicons/Applikationen.png diff --git a/skins/nopacity/graphics/menuicons/customicons/Audio.png b/skins/nopacity/graphics/menuicons/customicons/Audio.png Binary files differnew file mode 100644 index 0000000..ff387fe --- /dev/null +++ b/skins/nopacity/graphics/menuicons/customicons/Audio.png diff --git a/skins/nopacity/graphics/menuicons/customicons/Aufnahmen-Liste aktualisieren.png b/skins/nopacity/graphics/menuicons/customicons/Aufnahmen-Liste aktualisieren.png Binary files differnew file mode 100644 index 0000000..3cdddc9 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/customicons/Aufnahmen-Liste aktualisieren.png diff --git a/skins/nopacity/graphics/menuicons/customicons/Dienstprogramme.png b/skins/nopacity/graphics/menuicons/customicons/Dienstprogramme.png Binary files differnew file mode 100644 index 0000000..793aba6 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/customicons/Dienstprogramme.png diff --git a/skins/nopacity/graphics/menuicons/customicons/FireFox.png b/skins/nopacity/graphics/menuicons/customicons/FireFox.png Binary files differnew file mode 100644 index 0000000..192fadc --- /dev/null +++ b/skins/nopacity/graphics/menuicons/customicons/FireFox.png diff --git a/skins/nopacity/graphics/menuicons/customicons/Info.png b/skins/nopacity/graphics/menuicons/customicons/Info.png Binary files differnew file mode 100644 index 0000000..6737431 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/customicons/Info.png diff --git a/skins/nopacity/graphics/menuicons/customicons/Internet.png b/skins/nopacity/graphics/menuicons/customicons/Internet.png Binary files differnew file mode 100644 index 0000000..f3db150 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/customicons/Internet.png diff --git a/skins/nopacity/graphics/menuicons/customicons/Medien.png b/skins/nopacity/graphics/menuicons/customicons/Medien.png Binary files differnew file mode 100644 index 0000000..0ce2360 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/customicons/Medien.png diff --git a/skins/nopacity/graphics/menuicons/customicons/Rechner neu starten.png b/skins/nopacity/graphics/menuicons/customicons/Rechner neu starten.png Binary files differnew file mode 100644 index 0000000..5783ccf --- /dev/null +++ b/skins/nopacity/graphics/menuicons/customicons/Rechner neu starten.png diff --git a/skins/nopacity/graphics/menuicons/customicons/Remote wakeup.png b/skins/nopacity/graphics/menuicons/customicons/Remote wakeup.png Binary files differnew file mode 100644 index 0000000..1cd2f6e --- /dev/null +++ b/skins/nopacity/graphics/menuicons/customicons/Remote wakeup.png diff --git a/skins/nopacity/graphics/menuicons/customicons/Spiele.png b/skins/nopacity/graphics/menuicons/customicons/Spiele.png Binary files differnew file mode 100644 index 0000000..8e07161 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/customicons/Spiele.png diff --git a/skins/nopacity/graphics/menuicons/customicons/System herunterfahren.png b/skins/nopacity/graphics/menuicons/customicons/System herunterfahren.png Binary files differnew file mode 100644 index 0000000..e0234df --- /dev/null +++ b/skins/nopacity/graphics/menuicons/customicons/System herunterfahren.png diff --git a/skins/nopacity/graphics/menuicons/customicons/System.png b/skins/nopacity/graphics/menuicons/customicons/System.png Binary files differnew file mode 100644 index 0000000..81d100e --- /dev/null +++ b/skins/nopacity/graphics/menuicons/customicons/System.png diff --git a/skins/nopacity/graphics/menuicons/customicons/Tools.png b/skins/nopacity/graphics/menuicons/customicons/Tools.png Binary files differnew file mode 100644 index 0000000..cf328ef --- /dev/null +++ b/skins/nopacity/graphics/menuicons/customicons/Tools.png diff --git a/skins/nopacity/graphics/menuicons/customicons/Tunderbird.png b/skins/nopacity/graphics/menuicons/customicons/Tunderbird.png Binary files differnew file mode 100644 index 0000000..5ae27e0 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/customicons/Tunderbird.png diff --git a/skins/nopacity/graphics/menuicons/customicons/USB Massenspeicher sicher entfernen.png b/skins/nopacity/graphics/menuicons/customicons/USB Massenspeicher sicher entfernen.png Binary files differnew file mode 100644 index 0000000..cd7b81c --- /dev/null +++ b/skins/nopacity/graphics/menuicons/customicons/USB Massenspeicher sicher entfernen.png diff --git a/skins/nopacity/graphics/menuicons/customicons/VDR neu starten.png b/skins/nopacity/graphics/menuicons/customicons/VDR neu starten.png Binary files differnew file mode 100644 index 0000000..14904ca --- /dev/null +++ b/skins/nopacity/graphics/menuicons/customicons/VDR neu starten.png diff --git a/skins/nopacity/graphics/menuicons/customicons/Video.png b/skins/nopacity/graphics/menuicons/customicons/Video.png Binary files differnew file mode 100644 index 0000000..490ca4b --- /dev/null +++ b/skins/nopacity/graphics/menuicons/customicons/Video.png diff --git a/skins/nopacity/graphics/menuicons/customicons/Web.png b/skins/nopacity/graphics/menuicons/customicons/Web.png Binary files differnew file mode 100644 index 0000000..20260e3 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/customicons/Web.png diff --git a/skins/nopacity/graphics/menuicons/customicons/XBMC.png b/skins/nopacity/graphics/menuicons/customicons/XBMC.png Binary files differnew file mode 100644 index 0000000..c7c4c04 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/customicons/XBMC.png diff --git a/skins/nopacity/graphics/menuicons/customicons/Xterm.png b/skins/nopacity/graphics/menuicons/customicons/Xterm.png Binary files differnew file mode 100644 index 0000000..fa75282 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/customicons/Xterm.png diff --git a/skins/nopacity/graphics/menuicons/customicons/audiovideo.png b/skins/nopacity/graphics/menuicons/customicons/audiovideo.png Binary files differnew file mode 100644 index 0000000..726538d --- /dev/null +++ b/skins/nopacity/graphics/menuicons/customicons/audiovideo.png diff --git a/skins/nopacity/graphics/menuicons/customicons/markad_status.png b/skins/nopacity/graphics/menuicons/customicons/markad_status.png Binary files differnew file mode 100644 index 0000000..4fdc7a4 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/customicons/markad_status.png diff --git a/skins/nopacity/graphics/menuicons/customicons/schneiden_abbrechen.png b/skins/nopacity/graphics/menuicons/customicons/schneiden_abbrechen.png Binary files differnew file mode 100644 index 0000000..b2e0bd3 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/customicons/schneiden_abbrechen.png diff --git a/skins/nopacity/graphics/menuicons/customicons/tux.png b/skins/nopacity/graphics/menuicons/customicons/tux.png Binary files differnew file mode 100644 index 0000000..c5b4742 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/customicons/tux.png diff --git a/skins/nopacity/graphics/menuicons/customicons/usb.png b/skins/nopacity/graphics/menuicons/customicons/usb.png Binary files differnew file mode 100644 index 0000000..c4db1d4 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/customicons/usb.png diff --git a/skins/nopacity/graphics/menuicons/customicons/vdrlogo.png b/skins/nopacity/graphics/menuicons/customicons/vdrlogo.png Binary files differnew file mode 100644 index 0000000..037a191 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/customicons/vdrlogo.png diff --git a/skins/nopacity/graphics/menuicons/customicons/yaicon_blue.png b/skins/nopacity/graphics/menuicons/customicons/yaicon_blue.png Binary files differnew file mode 100644 index 0000000..2c49273 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/customicons/yaicon_blue.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/admin.png b/skins/nopacity/graphics/menuicons/pluginicons/admin.png Binary files differnew file mode 100644 index 0000000..cf328ef --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/admin.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/arghdirector.png b/skins/nopacity/graphics/menuicons/pluginicons/arghdirector.png Binary files differnew file mode 100644 index 0000000..bbd221a --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/arghdirector.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/autostart.png b/skins/nopacity/graphics/menuicons/pluginicons/autostart.png Binary files differnew file mode 100644 index 0000000..6fdb1bb --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/autostart.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/avahi4vdr.png b/skins/nopacity/graphics/menuicons/pluginicons/avahi4vdr.png Binary files differnew file mode 100644 index 0000000..044e71d --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/avahi4vdr.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/avards.png b/skins/nopacity/graphics/menuicons/pluginicons/avards.png Binary files differnew file mode 100644 index 0000000..cf8d037 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/avards.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/block.png b/skins/nopacity/graphics/menuicons/pluginicons/block.png Binary files differnew file mode 100644 index 0000000..86127c2 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/block.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/burn.png b/skins/nopacity/graphics/menuicons/pluginicons/burn.png Binary files differnew file mode 100644 index 0000000..305d7ff --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/burn.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/cdplayer.png b/skins/nopacity/graphics/menuicons/pluginicons/cdplayer.png Binary files differnew file mode 100644 index 0000000..89a6c19 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/cdplayer.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/chanman.png b/skins/nopacity/graphics/menuicons/pluginicons/chanman.png Binary files differnew file mode 100644 index 0000000..a73e83c --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/chanman.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/check.png b/skins/nopacity/graphics/menuicons/pluginicons/check.png Binary files differnew file mode 100644 index 0000000..d487a24 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/check.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/conflictcheckonly.png b/skins/nopacity/graphics/menuicons/pluginicons/conflictcheckonly.png Binary files differnew file mode 100644 index 0000000..7f832bd --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/conflictcheckonly.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/ddci.png b/skins/nopacity/graphics/menuicons/pluginicons/ddci.png Binary files differnew file mode 100644 index 0000000..4ad459c --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/ddci.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/devstatus.png b/skins/nopacity/graphics/menuicons/pluginicons/devstatus.png Binary files differnew file mode 100644 index 0000000..96c0ec1 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/devstatus.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/dummydevice.png b/skins/nopacity/graphics/menuicons/pluginicons/dummydevice.png Binary files differnew file mode 100644 index 0000000..11fd707 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/dummydevice.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/duplicates.png b/skins/nopacity/graphics/menuicons/pluginicons/duplicates.png Binary files differnew file mode 100644 index 0000000..dc1be57 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/duplicates.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/dvbapi.png b/skins/nopacity/graphics/menuicons/pluginicons/dvbapi.png Binary files differnew file mode 100644 index 0000000..b966461 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/dvbapi.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/dvbhddevice.png b/skins/nopacity/graphics/menuicons/pluginicons/dvbhddevice.png Binary files differnew file mode 100644 index 0000000..b874297 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/dvbhddevice.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/dvbsddevice.png b/skins/nopacity/graphics/menuicons/pluginicons/dvbsddevice.png Binary files differnew file mode 100644 index 0000000..106184e --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/dvbsddevice.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/dynamite.png b/skins/nopacity/graphics/menuicons/pluginicons/dynamite.png Binary files differnew file mode 100644 index 0000000..28ea35a --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/dynamite.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/eepg.png b/skins/nopacity/graphics/menuicons/pluginicons/eepg.png Binary files differnew file mode 100644 index 0000000..3938b96 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/eepg.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/epg2vdr.png b/skins/nopacity/graphics/menuicons/pluginicons/epg2vdr.png Binary files differnew file mode 100644 index 0000000..ac8757e --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/epg2vdr.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/epgsearch.png b/skins/nopacity/graphics/menuicons/pluginicons/epgsearch.png Binary files differnew file mode 100644 index 0000000..5eab415 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/epgsearch.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/epgsearchonly.png b/skins/nopacity/graphics/menuicons/pluginicons/epgsearchonly.png Binary files differnew file mode 100644 index 0000000..b5186e7 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/epgsearchonly.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/epgsync.png b/skins/nopacity/graphics/menuicons/pluginicons/epgsync.png Binary files differnew file mode 100644 index 0000000..5c14009 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/epgsync.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/externalplayer.png b/skins/nopacity/graphics/menuicons/pluginicons/externalplayer.png Binary files differnew file mode 100644 index 0000000..2bd67db --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/externalplayer.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/extrecmenu.png b/skins/nopacity/graphics/menuicons/pluginicons/extrecmenu.png Binary files differnew file mode 100644 index 0000000..6f613f1 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/extrecmenu.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/favorites.png b/skins/nopacity/graphics/menuicons/pluginicons/favorites.png Binary files differnew file mode 100644 index 0000000..409c852 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/favorites.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/femon.png b/skins/nopacity/graphics/menuicons/pluginicons/femon.png Binary files differnew file mode 100644 index 0000000..e87b711 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/femon.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/fepg.png b/skins/nopacity/graphics/menuicons/pluginicons/fepg.png Binary files differnew file mode 100644 index 0000000..65023ed --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/fepg.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/filebrowser.png b/skins/nopacity/graphics/menuicons/pluginicons/filebrowser.png Binary files differnew file mode 100644 index 0000000..d3f90e0 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/filebrowser.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/fritzbox.png b/skins/nopacity/graphics/menuicons/pluginicons/fritzbox.png Binary files differnew file mode 100644 index 0000000..7bfc229 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/fritzbox.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/graphlcd.png b/skins/nopacity/graphics/menuicons/pluginicons/graphlcd.png Binary files differnew file mode 100644 index 0000000..39ffd35 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/graphlcd.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/graphtft.png b/skins/nopacity/graphics/menuicons/pluginicons/graphtft.png Binary files differnew file mode 100644 index 0000000..39ffd35 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/graphtft.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/image.png b/skins/nopacity/graphics/menuicons/pluginicons/image.png Binary files differnew file mode 100644 index 0000000..33644e0 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/image.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/imonlcd.png b/skins/nopacity/graphics/menuicons/pluginicons/imonlcd.png Binary files differnew file mode 100644 index 0000000..3d34fc4 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/imonlcd.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/iptv.png b/skins/nopacity/graphics/menuicons/pluginicons/iptv.png Binary files differnew file mode 100644 index 0000000..4494ddc --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/iptv.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/lcdproc.png b/skins/nopacity/graphics/menuicons/pluginicons/lcdproc.png Binary files differnew file mode 100644 index 0000000..3d34fc4 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/lcdproc.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/mailbox.png b/skins/nopacity/graphics/menuicons/pluginicons/mailbox.png Binary files differnew file mode 100644 index 0000000..1bc76e8 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/mailbox.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/makemkv.png b/skins/nopacity/graphics/menuicons/pluginicons/makemkv.png Binary files differnew file mode 100644 index 0000000..41cddf1 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/makemkv.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/markad.png b/skins/nopacity/graphics/menuicons/pluginicons/markad.png Binary files differnew file mode 100644 index 0000000..b3defaf --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/markad.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/mlist.png b/skins/nopacity/graphics/menuicons/pluginicons/mlist.png Binary files differnew file mode 100644 index 0000000..19c367f --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/mlist.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/music.png b/skins/nopacity/graphics/menuicons/pluginicons/music.png Binary files differnew file mode 100644 index 0000000..abb012e --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/music.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/noepg.png b/skins/nopacity/graphics/menuicons/pluginicons/noepg.png Binary files differnew file mode 100644 index 0000000..eb9410d --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/noepg.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/nordlichtsepg.png b/skins/nopacity/graphics/menuicons/pluginicons/nordlichtsepg.png Binary files differnew file mode 100644 index 0000000..3ee3fa2 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/nordlichtsepg.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/osdteletext.png b/skins/nopacity/graphics/menuicons/pluginicons/osdteletext.png Binary files differnew file mode 100644 index 0000000..664e770 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/osdteletext.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/peer.png b/skins/nopacity/graphics/menuicons/pluginicons/peer.png Binary files differnew file mode 100644 index 0000000..998d568 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/peer.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/play.png b/skins/nopacity/graphics/menuicons/pluginicons/play.png Binary files differnew file mode 100644 index 0000000..2848fc6 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/play.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/pvrinput.png b/skins/nopacity/graphics/menuicons/pluginicons/pvrinput.png Binary files differnew file mode 100644 index 0000000..724f698 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/pvrinput.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/quickepgsearch.png b/skins/nopacity/graphics/menuicons/pluginicons/quickepgsearch.png Binary files differnew file mode 100644 index 0000000..76a31f4 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/quickepgsearch.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/radio.png b/skins/nopacity/graphics/menuicons/pluginicons/radio.png Binary files differnew file mode 100644 index 0000000..193b7d4 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/radio.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/remote.png b/skins/nopacity/graphics/menuicons/pluginicons/remote.png Binary files differnew file mode 100644 index 0000000..7f46b1b --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/remote.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/remotetimers.png b/skins/nopacity/graphics/menuicons/pluginicons/remotetimers.png Binary files differnew file mode 100644 index 0000000..fae3b79 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/remotetimers.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/rssreader.png b/skins/nopacity/graphics/menuicons/pluginicons/rssreader.png Binary files differnew file mode 100644 index 0000000..db538f0 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/rssreader.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/sc.png b/skins/nopacity/graphics/menuicons/pluginicons/sc.png Binary files differnew file mode 100644 index 0000000..2472d6c --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/sc.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/screenshot.png b/skins/nopacity/graphics/menuicons/pluginicons/screenshot.png Binary files differnew file mode 100644 index 0000000..be9b4d5 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/screenshot.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/seduatmo.png b/skins/nopacity/graphics/menuicons/pluginicons/seduatmo.png Binary files differnew file mode 100644 index 0000000..4b5292f --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/seduatmo.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/skyselectfeeds.png b/skins/nopacity/graphics/menuicons/pluginicons/skyselectfeeds.png Binary files differnew file mode 100644 index 0000000..d81a024 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/skyselectfeeds.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/sleeptimer.png b/skins/nopacity/graphics/menuicons/pluginicons/sleeptimer.png Binary files differnew file mode 100644 index 0000000..cd4956f --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/sleeptimer.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/softhddevice.png b/skins/nopacity/graphics/menuicons/pluginicons/softhddevice.png Binary files differnew file mode 100644 index 0000000..df13f2c --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/softhddevice.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/streamdev-server.png b/skins/nopacity/graphics/menuicons/pluginicons/streamdev-server.png Binary files differnew file mode 100644 index 0000000..e89ed8b --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/streamdev-server.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/systeminfo.png b/skins/nopacity/graphics/menuicons/pluginicons/systeminfo.png Binary files differnew file mode 100644 index 0000000..b14763f --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/systeminfo.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/targavfd.png b/skins/nopacity/graphics/menuicons/pluginicons/targavfd.png Binary files differnew file mode 100644 index 0000000..e91b111 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/targavfd.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/trayopenng.png b/skins/nopacity/graphics/menuicons/pluginicons/trayopenng.png Binary files differnew file mode 100644 index 0000000..6ebd17d --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/trayopenng.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/tvguide.png b/skins/nopacity/graphics/menuicons/pluginicons/tvguide.png Binary files differnew file mode 100644 index 0000000..968a37c --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/tvguide.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/tvm2vdr.png b/skins/nopacity/graphics/menuicons/pluginicons/tvm2vdr.png Binary files differnew file mode 100644 index 0000000..47f9a91 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/tvm2vdr.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/tvscraper.png b/skins/nopacity/graphics/menuicons/pluginicons/tvscraper.png Binary files differnew file mode 100644 index 0000000..a106cb5 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/tvscraper.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/undelete.png b/skins/nopacity/graphics/menuicons/pluginicons/undelete.png Binary files differnew file mode 100644 index 0000000..a53d50a --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/undelete.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/weatherng.png b/skins/nopacity/graphics/menuicons/pluginicons/weatherng.png Binary files differnew file mode 100644 index 0000000..a88f11d --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/weatherng.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/xmltv2vdr.png b/skins/nopacity/graphics/menuicons/pluginicons/xmltv2vdr.png Binary files differnew file mode 100644 index 0000000..ea73c74 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/xmltv2vdr.png diff --git a/skins/nopacity/graphics/menuicons/pluginicons/yaepghg.png b/skins/nopacity/graphics/menuicons/pluginicons/yaepghg.png Binary files differnew file mode 100644 index 0000000..53ce443 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/pluginicons/yaepghg.png diff --git a/skins/nopacity/graphics/menuicons/standardicons/CAM.png b/skins/nopacity/graphics/menuicons/standardicons/CAM.png Binary files differnew file mode 100644 index 0000000..a394877 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/standardicons/CAM.png diff --git a/skins/nopacity/graphics/menuicons/standardicons/Channels.png b/skins/nopacity/graphics/menuicons/standardicons/Channels.png Binary files differnew file mode 100644 index 0000000..ba2ba78 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/standardicons/Channels.png diff --git a/skins/nopacity/graphics/menuicons/standardicons/Commands.png b/skins/nopacity/graphics/menuicons/standardicons/Commands.png Binary files differnew file mode 100644 index 0000000..c6a83ef --- /dev/null +++ b/skins/nopacity/graphics/menuicons/standardicons/Commands.png diff --git a/skins/nopacity/graphics/menuicons/standardicons/DVB.png b/skins/nopacity/graphics/menuicons/standardicons/DVB.png Binary files differnew file mode 100644 index 0000000..3789145 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/standardicons/DVB.png diff --git a/skins/nopacity/graphics/menuicons/standardicons/EPG.png b/skins/nopacity/graphics/menuicons/standardicons/EPG.png Binary files differnew file mode 100644 index 0000000..e868b90 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/standardicons/EPG.png diff --git a/skins/nopacity/graphics/menuicons/standardicons/LNB.png b/skins/nopacity/graphics/menuicons/standardicons/LNB.png Binary files differnew file mode 100644 index 0000000..896dd99 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/standardicons/LNB.png diff --git a/skins/nopacity/graphics/menuicons/standardicons/Miscellaneous.png b/skins/nopacity/graphics/menuicons/standardicons/Miscellaneous.png Binary files differnew file mode 100644 index 0000000..2a41c4d --- /dev/null +++ b/skins/nopacity/graphics/menuicons/standardicons/Miscellaneous.png diff --git a/skins/nopacity/graphics/menuicons/standardicons/OSD.png b/skins/nopacity/graphics/menuicons/standardicons/OSD.png Binary files differnew file mode 100644 index 0000000..8f571c6 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/standardicons/OSD.png diff --git a/skins/nopacity/graphics/menuicons/standardicons/Plugins.png b/skins/nopacity/graphics/menuicons/standardicons/Plugins.png Binary files differnew file mode 100644 index 0000000..3fcba70 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/standardicons/Plugins.png diff --git a/skins/nopacity/graphics/menuicons/standardicons/Recording.png b/skins/nopacity/graphics/menuicons/standardicons/Recording.png Binary files differnew file mode 100644 index 0000000..741b1af --- /dev/null +++ b/skins/nopacity/graphics/menuicons/standardicons/Recording.png diff --git a/skins/nopacity/graphics/menuicons/standardicons/Recordings.png b/skins/nopacity/graphics/menuicons/standardicons/Recordings.png Binary files differnew file mode 100644 index 0000000..79aeeb7 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/standardicons/Recordings.png diff --git a/skins/nopacity/graphics/menuicons/standardicons/Replay.png b/skins/nopacity/graphics/menuicons/standardicons/Replay.png Binary files differnew file mode 100644 index 0000000..621596c --- /dev/null +++ b/skins/nopacity/graphics/menuicons/standardicons/Replay.png diff --git a/skins/nopacity/graphics/menuicons/standardicons/Restart.png b/skins/nopacity/graphics/menuicons/standardicons/Restart.png Binary files differnew file mode 100644 index 0000000..aa23cd4 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/standardicons/Restart.png diff --git a/skins/nopacity/graphics/menuicons/standardicons/Schedule.png b/skins/nopacity/graphics/menuicons/standardicons/Schedule.png Binary files differnew file mode 100644 index 0000000..3a98cac --- /dev/null +++ b/skins/nopacity/graphics/menuicons/standardicons/Schedule.png diff --git a/skins/nopacity/graphics/menuicons/standardicons/Setup.png b/skins/nopacity/graphics/menuicons/standardicons/Setup.png Binary files differnew file mode 100644 index 0000000..d121148 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/standardicons/Setup.png diff --git a/skins/nopacity/graphics/menuicons/standardicons/StopRecording.png b/skins/nopacity/graphics/menuicons/standardicons/StopRecording.png Binary files differnew file mode 100644 index 0000000..ed83fbb --- /dev/null +++ b/skins/nopacity/graphics/menuicons/standardicons/StopRecording.png diff --git a/skins/nopacity/graphics/menuicons/standardicons/StopReplay.png b/skins/nopacity/graphics/menuicons/standardicons/StopReplay.png Binary files differnew file mode 100644 index 0000000..9192760 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/standardicons/StopReplay.png diff --git a/skins/nopacity/graphics/menuicons/standardicons/Timers.png b/skins/nopacity/graphics/menuicons/standardicons/Timers.png Binary files differnew file mode 100644 index 0000000..b866c36 --- /dev/null +++ b/skins/nopacity/graphics/menuicons/standardicons/Timers.png diff --git a/skins/nopacity/graphics/skinparts/buttonblue.png b/skins/nopacity/graphics/skinparts/buttonblue.png Binary files differnew file mode 100644 index 0000000..d00e4d2 --- /dev/null +++ b/skins/nopacity/graphics/skinparts/buttonblue.png diff --git a/skins/nopacity/graphics/skinparts/buttongreen.png b/skins/nopacity/graphics/skinparts/buttongreen.png Binary files differnew file mode 100644 index 0000000..8c05c08 --- /dev/null +++ b/skins/nopacity/graphics/skinparts/buttongreen.png diff --git a/skins/nopacity/graphics/skinparts/buttonred.png b/skins/nopacity/graphics/skinparts/buttonred.png Binary files differnew file mode 100644 index 0000000..9367c9b --- /dev/null +++ b/skins/nopacity/graphics/skinparts/buttonred.png diff --git a/skins/nopacity/graphics/skinparts/buttonyellow.png b/skins/nopacity/graphics/skinparts/buttonyellow.png Binary files differnew file mode 100644 index 0000000..aff8758 --- /dev/null +++ b/skins/nopacity/graphics/skinparts/buttonyellow.png diff --git a/skins/nopacity/graphics/skinparts/channellogoback.png b/skins/nopacity/graphics/skinparts/channellogoback.png Binary files differnew file mode 100644 index 0000000..b0e83b1 --- /dev/null +++ b/skins/nopacity/graphics/skinparts/channellogoback.png diff --git a/skins/nopacity/graphics/skinparts/discpercent.png b/skins/nopacity/graphics/skinparts/discpercent.png Binary files differnew file mode 100644 index 0000000..cf32be2 --- /dev/null +++ b/skins/nopacity/graphics/skinparts/discpercent.png diff --git a/skins/nopacity/graphics/skinparts/displaychannelback.png b/skins/nopacity/graphics/skinparts/displaychannelback.png Binary files differnew file mode 100644 index 0000000..1437384 --- /dev/null +++ b/skins/nopacity/graphics/skinparts/displaychannelback.png diff --git a/skins/nopacity/graphics/skinparts/displaychanneltop.png b/skins/nopacity/graphics/skinparts/displaychanneltop.png Binary files differnew file mode 100644 index 0000000..5108435 --- /dev/null +++ b/skins/nopacity/graphics/skinparts/displaychanneltop.png diff --git a/skins/nopacity/graphics/skinparts/displayreplayback.png b/skins/nopacity/graphics/skinparts/displayreplayback.png Binary files differnew file mode 100644 index 0000000..d72931f --- /dev/null +++ b/skins/nopacity/graphics/skinparts/displayreplayback.png diff --git a/skins/nopacity/graphics/skinparts/displayreplaytop.png b/skins/nopacity/graphics/skinparts/displayreplaytop.png Binary files differnew file mode 100644 index 0000000..064347e --- /dev/null +++ b/skins/nopacity/graphics/skinparts/displayreplaytop.png diff --git a/skins/nopacity/graphics/skinparts/displayvolume.png b/skins/nopacity/graphics/skinparts/displayvolume.png Binary files differnew file mode 100644 index 0000000..a5c4c66 --- /dev/null +++ b/skins/nopacity/graphics/skinparts/displayvolume.png diff --git a/skins/nopacity/graphics/skinparts/headertop.png b/skins/nopacity/graphics/skinparts/headertop.png Binary files differnew file mode 100644 index 0000000..2bc19a6 --- /dev/null +++ b/skins/nopacity/graphics/skinparts/headertop.png diff --git a/skins/nopacity/graphics/skinparts/menubutton.png b/skins/nopacity/graphics/skinparts/menubutton.png Binary files differnew file mode 100644 index 0000000..0800a5e --- /dev/null +++ b/skins/nopacity/graphics/skinparts/menubutton.png diff --git a/skins/nopacity/graphics/skinparts/menubuttonactive.png b/skins/nopacity/graphics/skinparts/menubuttonactive.png Binary files differnew file mode 100644 index 0000000..caae104 --- /dev/null +++ b/skins/nopacity/graphics/skinparts/menubuttonactive.png diff --git a/skins/nopacity/graphics/skinparts/menubuttondefault.png b/skins/nopacity/graphics/skinparts/menubuttondefault.png Binary files differnew file mode 100644 index 0000000..76735de --- /dev/null +++ b/skins/nopacity/graphics/skinparts/menubuttondefault.png diff --git a/skins/nopacity/graphics/skinparts/menubuttondefaultactive.png b/skins/nopacity/graphics/skinparts/menubuttondefaultactive.png Binary files differnew file mode 100644 index 0000000..70c0b8a --- /dev/null +++ b/skins/nopacity/graphics/skinparts/menubuttondefaultactive.png diff --git a/skins/nopacity/graphics/skinparts/menubuttontop.png b/skins/nopacity/graphics/skinparts/menubuttontop.png Binary files differnew file mode 100644 index 0000000..1b49cfd --- /dev/null +++ b/skins/nopacity/graphics/skinparts/menubuttontop.png diff --git a/skins/nopacity/graphics/skinparts/messageError.png b/skins/nopacity/graphics/skinparts/messageError.png Binary files differnew file mode 100644 index 0000000..a894992 --- /dev/null +++ b/skins/nopacity/graphics/skinparts/messageError.png diff --git a/skins/nopacity/graphics/skinparts/messageInfo.png b/skins/nopacity/graphics/skinparts/messageInfo.png Binary files differnew file mode 100644 index 0000000..5f8e62a --- /dev/null +++ b/skins/nopacity/graphics/skinparts/messageInfo.png diff --git a/skins/nopacity/graphics/skinparts/messageStatus.png b/skins/nopacity/graphics/skinparts/messageStatus.png Binary files differnew file mode 100644 index 0000000..f4b83f4 --- /dev/null +++ b/skins/nopacity/graphics/skinparts/messageStatus.png diff --git a/skins/nopacity/graphics/skinparts/messageWarning.png b/skins/nopacity/graphics/skinparts/messageWarning.png Binary files differnew file mode 100644 index 0000000..f073ed5 --- /dev/null +++ b/skins/nopacity/graphics/skinparts/messageWarning.png diff --git a/skins/nopacity/graphics/skinparts/scrollbar.png b/skins/nopacity/graphics/skinparts/scrollbar.png Binary files differnew file mode 100644 index 0000000..f822555 --- /dev/null +++ b/skins/nopacity/graphics/skinparts/scrollbar.png diff --git a/skins/nopacity/graphics/skinparts/signal.png b/skins/nopacity/graphics/skinparts/signal.png Binary files differnew file mode 100644 index 0000000..4f03c7a --- /dev/null +++ b/skins/nopacity/graphics/skinparts/signal.png 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 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE displayaudiotracks SYSTEM "../../dtd/displayaudiotracks.dtd"> + +<displayaudiotracks x="25%" y="0" width="50%" height="100%" fadetime="{fadeTime}"> + <!-- Available Variables background: + {numtracks} number of displayed tracks + --> + <background> + <area x="0" y="{areaheight} - {numtracks} * {areaheight} / 10 - {areaheight} / 10" width="100%" height="{areaheight} / 10 + {areaheight} / 10 * {numtracks}" layer="1"> + <fill color="{clrTransBlack}" /> + </area> + </background> + + <!-- Available Variables header: + {numtracks} number of displayed tracks + {title} title of menu + --> + <header> + <area x="0" y="{areaheight} - {numtracks} * {areaheight} / 10 - {areaheight} / 10" width="100%" height="{areaheight} / 10" layer="2"> + <drawtext x="10" valign="center" font="{vdrOsd}" fontsize="80%" color="{clrWhite}" text="{title}" /> + <drawimage condition="{isstereo}" imagetype="icon" path="ico_stereo" x="{areawidth} - {areaheight}*0.9" valign="center" width="{areaheight}*0.9" height="{areaheight}*0.9"/> + <drawimage condition="{isac3}" imagetype="icon" path="ico_ac3" x="{areawidth} - {areaheight}*0.9" valign="center" width="{areaheight}*0.9" height="{areaheight}*0.9"/> + </area> + </header> + + <!-- Available Variables header: + {numelements} number of displayed tracks + --> + <menuitems x="0" y="{areaheight} - {numelements} * {areaheight} / 10" orientation="vertical" width="100%" height="{numelements} * {areaheight} / 10" align="top" numlistelements="{numelements}"> + <!-- Available Variables auidotrack listelement: + {current} true if item is currently selected + {title} title of auio track + --> + <listelement> + <!-- Background --> + <area x="1%" width="98%" layer="2"> + <drawimage condition="not{current}" imagetype="skinpart" path="menubutton" x="0" y="1%" width="{areawidth}" height="{areaheight}*0.98"/> + <drawimage condition="{current}" imagetype="skinpart" path="menubuttonactive" x="0" y="1%" width="{areawidth}" height="{areaheight}*0.98"/> + </area> + <area x="1%" width="98%" layer="3"> + <drawtext x="10" valign="center" font="{vdrOsd}" fontsize="60%" color="{clrWhite}" text="{title}" /> + </area> + </listelement> + </menuitems> + +</displayaudiotracks> 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 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE displaychannel SYSTEM "../../dtd/displaychannel.dtd"> + +<displaychannel x="0" y="0" width="100%" height="100%" fadetime="{fadeTime}"> + + <background> + <area x="1%" y="74%" width="98%" height="25%" layer="1" transparency="20"> + <drawimage imagetype="skinpart" path="displaychannelback" x="0" y="0" width="100%" height="100%"/> + </area> + <area x="1%" y="74%" width="98%" height="25%" layer="7"> + <drawimage imagetype="skinpart" path="displaychanneltop" x="0" y="0" width="100%" height="100%"/> + </area> + <area x="2%" y="80%" width="14%" height="18%" layer="2"> + <drawimage imagetype="skinpart" path="channellogoback" x="0" y="0" width="100%" height="100%"/> + </area> + </background> + <!-- Available Variables channelinfo: + {channelnumber} Number of Channel, with "-" in case of channel switching + {channelname} Name of current Channel + {channellogoexists} true if a channel logo exists + {channelid} ChannelID as path to display channel logo + {switching} true if a number is pressed on the remote to switch to a dedicated channel + --> + <channelinfo> + <area x="2%" y="80%" width="14%" height="18%" layer="2"> + <drawimage cache="true" imagetype="channellogo" path="{channelid}" height="98%" align="center" valign="center"/> + </area> + <area x="18%" y="74%" width="60%" height="6%" layer="2"> + <drawtext x="0" valign="center" font="{vdrOsd}" fontsize="95%" color="{clrWhite}" text="{channelnumber} {channelname}" /> + </area> + </channelinfo> + + <!-- Available Variables datetime: + {time} time in hh:mm + {day} day in digits + {dayleadingzero} day in digits with leading 0 + {dayname} Full name of the day + {daynameshort} Short 3 char name of the day + {month} month in digits with leading 0 + {monthname} Full name of the month + {year} year in yyyy + --> + <datetime> + <area x="78%" y="74%" width="20%" height="6%" layer="2"> + <drawtext align="right" valign="center" font="{vdrOsd}" fontsize="70%" color="{clrWhite}" text="{daynameshort} {day}.{month} {time}" /> + </area> + </datetime> + + <!-- Available Variables epginfo: + {currenttitle} Title of the current Schedule + {currentsubtitle} Subtitle of the current Schedule + {currentstart} Start of current Schedule in hh:mm + {currentstop} End of current Schedule in hh:mm + {currentduration} Duration of current Schedule in min + {currentelapsed} Elapsed time of current Schedule in min + {currentremaining} Remaining time of current Schedule in min + {currentrecording} true if current Schedule is recorded + {nexttitle} Title of next Schedule + {nextsubtitle} Subtitle of next Schedule + {nextstart} Start of next Schedule in hh:mm + {nextstop} Stop of next Schedule in hh:mm + {nextduration} Duration of next Schedule in min + {nextrecording} true if next Schedule will be recorded + --> + <epginfo> + <area x="18%" y="82%" width="68%" height="6%" layer="2"> + <drawtext name="starttime" x="0" y="0" font="{vdrOsd}" fontsize="60%" color="{clrWhite}" text="{currentstart}" /> + <drawtext x="{width(starttime)} + 15" y="0" width="{areawidth} - {width(starttime)} - 15" font="{vdrOsd}" fontsize="60%" color="{clrWhite}" text="{currenttitle}" /> + <drawtext x="{width(starttime)} + 16" y="55%" width="{areawidth} - {width(starttime)} - 16" font="{vdrOsd}" fontsize="45%" color="{clrWhite}" text="{currentsubtitle}" /> + </area> + <area x="86%" y="82%" width="11%" height="6%" layer="2"> + <drawtext align="right" y="0" font="{vdrOsd}" fontsize="60%" color="{clrWhite}" text="{currentelapsed}/{currentduration}min" /> + </area> + <area x="18%" y="88%" width="72%" height="6%" layer="2"> + <drawtext name="starttime" x="0" y="0" font="{vdrOsd}" fontsize="60%" color="{clrGray}" text="{nextstart}" /> + <drawtext x="{width(starttime)} + 15" y="0" width="{areawidth} - {width(starttime)} - 15" font="{vdrOsd}" fontsize="60%" color="{clrGray}" text="{nexttitle}" /> + <drawtext x="{width(starttime)} + 16" y="55%" width="{areawidth} - {width(starttime)} - 16" font="{vdrOsd}" fontsize="45%" color="{clrGray}" text="{nextsubtitle}" /> + </area> + <area x="90%" y="88%" width="7%" height="6%" layer="2"> + <drawtext align="right" y="0" font="{vdrOsd}" fontsize="60%" color="{clrGray}" text="{nextduration}min" /> + </area> + </epginfo> + + <!-- Available Variables progressbar: + {start} Start of current Schedule in hh:mm + {stop} End of current Schedule in hh:mm + {duration} Total Duration of current Schedule in seconds + {elapsed} Elapsed time of current Schedule in seconds + {remaining} Remaining time of current Schedule in seconds + --> + <progressbar> + <area x="17%" y="80%" width="81%" height="2%" layer="2"> + <drawellipse x="1" y="1" width="{areaheight}-2" height="{areaheight}-2" color="{clrBrightGreen}" quadrant="0" /> + <drawellipse x="1 + {elapsed}/{duration}*{areawidth} - {elapsed}/{duration}*{areaheight}" y="1" width="{areaheight}-2" height="{areaheight}-2" color="{clrBrightGreen}" quadrant="0" /> + <drawrectangle x="{areaheight}/2" y="1" width="{elapsed}/{duration}*{areawidth} - {elapsed}/{duration}*{areaheight}" height="{areaheight}-2" color="{clrBrightGreen}" /> + </area> + </progressbar> + + <progressbarback> + <area x="17%" y="80%" width="81%" height="2%" layer="2"> + <drawellipse x="0" y="0" width="{areaheight}" height="{areaheight}" color="{clrBlack}" quadrant="0" /> + <drawellipse x="{areawidth}-{areaheight}" y="0" width="{areaheight}" height="{areaheight}" color="{clrBlack}" quadrant="0" /> + <drawrectangle x="{areaheight}/2" y="0" width="{areawidth} - {areaheight}" height="{areaheight}" color="{clrBlack}" /> + </area> + </progressbarback> + <!-- Available Variables statusinfo: + {isRadio} true if channel is a radio channel + {hasVT} true if channel has video text + {isStereo} true if a stereo audio trac is available + {isDolby} true if a dolby audio track is available + {isEncrypted} true if channel is encrypted + {isRecording} true if currently a recording is running on this channel + --> + <statusinfo> + <area x="{areawidth}*0.98 - {areaheight}*0.40 - 25" y="93%" width="{areaheight}*0.25 + 20" height="5%" layer="2"> + <drawimage condition="{hasVT}" imagetype="icon" path="ico_txton" x="0" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="not{hasVT}" imagetype="icon" path="ico_txtoff" x="0" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{isStereo}" imagetype="icon" path="ico_stereoon" x="{areaheight}+5" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="not{isStereo}" imagetype="icon" path="ico_stereooff" x="{areaheight}+5" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{isDolby}" imagetype="icon" path="ico_dolbyon" x="2*{areaheight}+10" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="not{isDolby}" imagetype="icon" path="ico_dolbyoff" x="2*{areaheight}+10" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{isEncrypted}" imagetype="icon" path="ico_encrypted" x="3*{areaheight}+15" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="not{isEncrypted}" imagetype="icon" path="ico_fta" x="3*{areaheight}+15" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{isRecording}" imagetype="icon" path="ico_recon" x="4*{areaheight}+20" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="not{isRecording}" imagetype="icon" path="ico_recoff" x="4*{areaheight}+20" y="0" width="{areaheight}" height="{areaheight}"/> + </area> + </statusinfo> + + <!-- Available Variables screenresolution: + {screenwidth} width of currently displayed channel in px + {screenheight} height of currently displayed channel in px + {resolution} resolution: hd1080i, hd720p, sd576i + {aspect} screen aspect, each 4:3, 16:9 or 21:9 + {isHD} true for hd1080i and hd720p + {isWideScreen} true if aspect is 16:9 or 21:9 + --> + <screenresolution> + <area x="{areawidth}*0.98 - {areaheight}*0.15" y="93%" width="{areaheight}*0.15" height="5%" layer="2"> + <drawimage imagetype="icon" path="ico_{resolution}" x="0" y="0" width="{areaheight}*3" height="{areaheight}"/> + </area> + </screenresolution> + + <!-- Available Variables dvbdeviceinfo: + {prevAvailable} true if previous Channel Group is avaialble + {nextAvailable} true if next Channel Group is avaialble + {group} Name of current Channel Group + {nextgroup} Name of next Channel Group + {prevgroup} Name of prev Channel Group + {sepexists} true if a channel separator logo exists + {seppath} path for separator logo to use in imagetype "seplogo" + --> + <channelgroup> + <area x="2%" y="80%" width="14%" height="18%" layer="2"> + <drawimage condition="{sepexists}" imagetype="seplogo" path="{seppath}" height="98%" align="center" valign="center" /> + <drawimage condition="not{sepexists}" imagetype="icon" path="ico_channelsep" align="center" valign="center" width="{areaheight}*0.8" height="{areaheight}*0.8"/> + </area> + <area x="18%" y="82%" width="80%" height="10%" layer="2"> + <drawtext x="0" width="25%" valign="center" font="{vdrOsd}" fontsize="60%" color="{clrWhite}" text="{prevgroup}" /> + <drawtext x="30%" width="40%" valign="center" font="{vdrOsd}" fontsize="80%" color="{clrWhite}" text="{group}" /> + <drawtext align="right" width="25%" valign="center" font="{vdrOsd}" fontsize="60%" color="{clrWhite}" text="{nextgroup}" /> + <drawimage imagetype="icon" path="ico_arrow_left_channelsep" x="25%" valign="center" width="{areawidth}*4/100" height="{areawidth}*4/100"/> + <drawimage imagetype="icon" path="ico_arrow_right_channelsep" x="71%" valign="center" width="{areawidth}*4/100" height="{areawidth}*4/100"/> + </area> + </channelgroup> + <!-- Available Variables signalquality: + {signalstrength} STR value of currently displayed channel + {signalquality} SNR value of currently displayed channel + --> + <signalquality> + <area x="17%" y="95%" width="15%" height="4%" layer="3"> + <drawrectangle x="{areawidth}*{signalstrength}/100" y="0" width="{areawidth} - {areawidth}*{signalstrength}/100" height="45%" color="{clrTransBlack}" /> + <drawrectangle x="{areawidth}*{signalquality}/100" y="50%" width="{areawidth} - {areawidth}*{signalquality}/100" height="45%" color="{clrTransBlack}" /> + </area> + </signalquality> + + <!-- background of signalmeter, will only be drawn if signalquality was deleted --> + <signalqualityback> + <area x="17%" y="95%" width="15%" height="4%" layer="2"> + <drawimage imagetype="skinpart" path="signal" x="0" y="0" width="100%" height="45%"/> + <drawimage imagetype="skinpart" path="signal" x="0" y="50%" width="100%" height="45%"/> + </area> + </signalqualityback> + + <!-- Available Variables scrapercontent: + {mediapath} Full Path of Poster or Banner to use in image path attribute + {mediawidth} width of image in pixel + {mediaheight} height of image in pixel + {isbanner} true if image is a banner, false if it is a poster + --> + <scrapercontent> + <area condition="{isbanner}" x="1%" y="1%" width="{areaheight}*0.13*{mediawidth}/{mediaheight}" height="13%" layer="2"> + <drawimage imagetype="image" path="{mediapath}" align="center" valign="center" width="{areawidth}" height="{areaheight}"/> + </area> + <area condition="not{isbanner}" x="1%" y="1%" width="{areaheight}*0.5*{mediawidth}/{mediaheight}" height="50%" layer="2"> + <drawimage imagetype="image" path="{mediapath}" x="5" y="5" width="{areawidth}-10" height="{areaheight}-10"/> + </area> + </scrapercontent> + + <!-- Available Variables message: + {text} message text + {status} true if message is a status message + {info} true if message is a info message + {warning} true if message is a warn message + {error} true if message is a error message + --> + <message> + <area x="5%" y="58%" width="90%" height="15%" layer="6"> + <drawimage condition="{status}" imagetype="skinpart" path="messageStatus" x="0" y="0" width="100%" height="100%" /> + <drawimage condition="{info}" imagetype="skinpart" path="messageInfo" x="0" y="0" width="100%" height="100%" /> + <drawimage condition="{warning}" imagetype="skinpart" path="messageWarning" x="0" y="0" width="100%" height="100%" /> + <drawimage condition="{error}" imagetype="skinpart" path="messageError" x="0" y="0" width="100%" height="100%" /> + </area> + <area x="5%" y="58%" width="90%" height="15%" layer="7"> + <drawtext align="center" valign="center" font="{light}" fontsize="40%" color="{clrWhite}" text="{text}" /> + </area> + </message> + +</displaychannel> 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 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE displaymenu SYSTEM "../../dtd/displaymenu.dtd" [ +<!ENTITY displaymenudefault SYSTEM "displaymenudefault.xml"> +<!ENTITY displaymenumain SYSTEM "displaymenumain.xml"> +<!ENTITY displaymenusetup SYSTEM "displaymenusetup.xml"> +<!ENTITY displaymenuschedules SYSTEM "displaymenuschedules.xml"> +<!ENTITY displaymenutimers SYSTEM "displaymenutimers.xml"> +<!ENTITY displaymenuchannels SYSTEM "displaymenuchannels.xml"> +<!ENTITY displaymenurecordings SYSTEM "displaymenurecordings.xml"> +<!ENTITY displaymenudetailepg SYSTEM "displaymenudetailepg.xml"> +<!ENTITY displaymenudetailrecording SYSTEM "displaymenudetailrecording.xml"> +<!ENTITY displaymenudetailtext SYSTEM "displaymenudetailtext.xml"> +]> + +<displaymenu x="0" y="0" width="100%" height="100%" fadetime="0"> + <!-- + The following background, header, datetime and colorbuttons definitions are default + implementations. If one or more of these elements are not implemented in the subview, + the default implementations are used. + --> + <background> + <area x="0" y="0" width="100%" height="100%" layer="1"> + <!-- top bar --> + <drawrectangle x="0" y="0" width="{areawidth}" height="10%" color="{clrDarkBlue}" /> + <drawrectangle x="30%" y="{areaheight}*0.1 - 1" width="71%" height="1" color="{clrDarkGreen}" /> + <!-- menu bar --> + <drawrectangle x="0" y="10%" width="{areawidth}*29/100" height="81%" color="{clrDarkBlue}" /> + <drawrectangle x="{areawidth}*29/100 - 1" y="12%" width="1" height="76%" color="{clrDarkGreen}" /> + <!-- bottom bar --> + <drawrectangle x="0" y="90%" width="{areawidth}" height="10%" color="{clrDarkBlue}" /> + <drawrectangle x="30%" y="{areaheight}*0.9 - 1" width="71%" height="1" color="{clrDarkGreen}" /> + <!-- upper corner --> + <drawellipse x="{areawidth}*29/100" y="{areaheight}/10" width="{areawidth}*2/100" height="{areawidth}*2/100" quadrant="-2" color="{clrDarkGreen}" /> + <drawellipse x="{areawidth}*29/100 - 1" y="{areaheight}/10 - 1" width="{areawidth}*2/100" height="{areawidth}*2/100" quadrant="-2" color="{clrDarkBlue}" /> + <!-- lower corner --> + <drawellipse x="{areawidth}*29/100" y="{areaheight}*90/100 - {areawidth}*2/100" width="{areawidth}*2/100" height="{areawidth}*2/100" quadrant="-3" color="{clrDarkGreen}" /> + <drawellipse x="{areawidth}*29/100 - 1" y="{areaheight}*90/100 - {areawidth}*2/100 + 1" width="{areawidth}*2/100" height="{areawidth}*2/100" quadrant="-3" color="{clrDarkBlue}" /> + </area> + <area x="0" y="0" width="100%" height="10%" layer="2"> + <drawimage imagetype="skinpart" path="headertop" x="0" y="0" width="100%" height="100%"/> + </area> + </background> + <!-- Available Variables header: + {title} title of current menu + {vdrversion} running VDR Version + {hasicon} true if a menu icon is available + {icon} path of menu icon + --> + <header> + <area x="1%" y="0" width="64%" height="10%" layer="3"> + <drawtext x="0" valign="center" font="{vdrOsd}" fontsize="50%" color="{clrWhite}" text="{title}" /> + </area> + </header> + <!-- Available Variables datetime: + {time} time in hh:mm + {day} day in digits + {dayleadingzero} day in digits with leading 0 + {dayname} Full name of the day + {daynameshort} Short 3 char name of the day + {month} month in digits with leading 0 + {monthname} Full name of the month + {year} year in yyyy + --> + <datetime> + <area x="65%" y="0" width="34%" height="10%" layer="3"> + <drawtext align="right" valign="center" font="{vdrOsd}" fontsize="50%" color="{clrWhite}" text="{daynameshort} {day}.{month} {time}" /> + </area> + </datetime> + <!-- Available Variables message: + {text} message text + {status} true if message is an status message + {info} true if message is an info message + {warning} true if message is an warn message + {error} true if message is an error message + --> + <message> + <area x="5%" y="80%" width="90%" height="15%" layer="6"> + <drawimage condition="{status}" imagetype="skinpart" path="messageStatus" x="0" y="0" width="100%" height="100%" /> + <drawimage condition="{info}" imagetype="skinpart" path="messageInfo" x="0" y="0" width="100%" height="100%" /> + <drawimage condition="{warning}" imagetype="skinpart" path="messageWarning" x="0" y="0" width="100%" height="100%" /> + <drawimage condition="{error}" imagetype="skinpart" path="messageError" x="0" y="0" width="100%" height="100%" /> + </area> + <area x="5%" y="80%" width="90%" height="15%" layer="7"> + <drawtext align="center" valign="center" font="{light}" fontsize="40%" color="{clrWhite}" text="{text}" /> + </area> + </message> + <!-- Available Variables colorbuttons: + {red1} true if red button is button 1 + {red2} true if red button is button 2 + {red3} true if red button is button 3 + {red4} true if red button is button 4 + {green1} true if green button is button 1 + {green2} true if green button is button 2 + {green3} true if green button is button 3 + {green4} true if green button is button 4 + {yellow1} true if yellow button is button 1 + {yellow2} true if yellow button is button 2 + {yellow3} true if yellow button is button 3 + {yellow4} true if yellow button is button 4 + {blue1} true if blue button is button 1 + {blue2} true if blue button is button 2 + {blue3} true if blue button is button 3 + {blue4} true if blue button is button 4 + {red} label of red button + {green} label of green button + {yellow} label of yellow button + {blue} label of blue button + --> + <colorbuttons> + <area condition="{red1}" x="0" y="90%" width="25%" height="10%" layer="2"> + <drawimage imagetype="skinpart" path="buttonred" align="center" valign="center" width="90%" height="40%"/> + <drawtext align="center" valign="center" font="{vdrOsd}" fontsize="35%" color="{clrWhite}" text="{red}" /> + </area> + <area condition="{green1}" x="0" y="90%" width="25%" height="10%" layer="2"> + <drawimage imagetype="skinpart" path="buttongreen" align="center" valign="center" width="90%" height="40%"/> + <drawtext align="center" valign="center" font="{vdrOsd}" fontsize="35%" color="{clrWhite}" text="{green}" /> + </area> + <area condition="{yellow1}" x="0" y="90%" width="25%" height="10%" layer="2"> + <drawimage imagetype="skinpart" path="buttonyellow" align="center" valign="center" width="90%" height="40%"/> + <drawtext align="center" valign="center" font="{vdrOsd}" fontsize="35%" color="{clrWhite}" text="{yellow}" /> + </area> + <area condition="{blue1}" x="0" y="90%" width="25%" height="10%" layer="2"> + <drawimage imagetype="skinpart" path="buttonblue" align="center" valign="center" width="90%" height="40%"/> + <drawtext align="center" valign="center" font="{vdrOsd}" fontsize="35%" color="{clrWhite}" text="{blue}" /> + </area> + + <area condition="{red2}" x="25%" y="90%" width="25%" height="10%" layer="2"> + <drawimage imagetype="skinpart" path="buttonred" align="center" valign="center" width="90%" height="40%"/> + <drawtext align="center" valign="center" font="{vdrOsd}" fontsize="35%" color="{clrWhite}" text="{red}" /> + </area> + <area condition="{green2}" x="25%" y="90%" width="25%" height="10%" layer="2"> + <drawimage imagetype="skinpart" path="buttongreen" align="center" valign="center" width="90%" height="40%"/> + <drawtext align="center" valign="center" font="{vdrOsd}" fontsize="35%" color="{clrWhite}" text="{green}" /> + </area> + <area condition="{yellow2}" x="25%" y="90%" width="25%" height="10%" layer="2"> + <drawimage imagetype="skinpart" path="buttonyellow" align="center" valign="center" width="90%" height="40%"/> + <drawtext align="center" valign="center" font="{vdrOsd}" fontsize="35%" color="{clrWhite}" text="{yellow}" /> + </area> + <area condition="{blue2}" x="25%" y="90%" width="25%" height="10%" layer="2"> + <drawimage imagetype="skinpart" path="buttonblue" align="center" valign="center" width="90%" height="40%"/> + <drawtext align="center" valign="center" font="{vdrOsd}" fontsize="35%" color="{clrWhite}" text="{blue}" /> + </area> + + <area condition="{red3}" x="50%" y="90%" width="25%" height="10%" layer="2"> + <drawimage imagetype="skinpart" path="buttonred" align="center" valign="center" width="90%" height="40%"/> + <drawtext align="center" valign="center" font="{vdrOsd}" fontsize="35%" color="{clrWhite}" text="{red}" /> + </area> + <area condition="{green3}" x="50%" y="90%" width="25%" height="10%" layer="2"> + <drawimage imagetype="skinpart" path="buttongreen" align="center" valign="center" width="90%" height="40%"/> + <drawtext align="center" valign="center" font="{vdrOsd}" fontsize="35%" color="{clrWhite}" text="{green}" /> + </area> + <area condition="{yellow3}" x="50%" y="90%" width="25%" height="10%" layer="2"> + <drawimage imagetype="skinpart" path="buttonyellow" align="center" valign="center" width="90%" height="40%"/> + <drawtext align="center" valign="center" font="{vdrOsd}" fontsize="35%" color="{clrWhite}" text="{yellow}" /> + </area> + <area condition="{blue3}" x="50%" y="90%" width="25%" height="10%" layer="2"> + <drawimage imagetype="skinpart" path="buttonblue" align="center" valign="center" width="90%" height="40%"/> + <drawtext align="center" valign="center" font="{vdrOsd}" fontsize="35%" color="{clrWhite}" text="{blue}" /> + </area> + + <area condition="{red4}" x="75%" y="90%" width="25%" height="10%" layer="2"> + <drawimage imagetype="skinpart" path="buttonred" align="center" valign="center" width="90%" height="40%"/> + <drawtext align="center" valign="center" font="{vdrOsd}" fontsize="35%" color="{clrWhite}" text="{red}" /> + </area> + <area condition="{green4}" x="75%" y="90%" width="25%" height="10%" layer="2"> + <drawimage imagetype="skinpart" path="buttongreen" align="center" valign="center" width="90%" height="40%"/> + <drawtext align="center" valign="center" font="{vdrOsd}" fontsize="35%" color="{clrWhite}" text="{green}" /> + </area> + <area condition="{yellow4}" x="75%" y="90%" width="25%" height="10%" layer="2"> + <drawimage imagetype="skinpart" path="buttonyellow" align="center" valign="center" width="90%" height="40%"/> + <drawtext align="center" valign="center" font="{vdrOsd}" fontsize="35%" color="{clrWhite}" text="{yellow}" /> + </area> + <area condition="{blue4}" x="75%" y="90%" width="25%" height="10%" layer="2"> + <drawimage imagetype="skinpart" path="buttonblue" align="center" valign="center" width="90%" height="40%"/> + <drawtext align="center" valign="center" font="{vdrOsd}" fontsize="35%" color="{clrWhite}" text="{blue}" /> + </area> + </colorbuttons> + &displaymenudefault; + &displaymenumain; + &displaymenusetup; + &displaymenuschedules; + &displaymenutimers; + &displaymenuchannels; + &displaymenurecordings; + &displaymenudetailepg; + &displaymenudetailrecording; + &displaymenudetailtext; +</displaymenu> 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 @@ +<menuchannels x="0" y="0" width="100%" height="100%" fadetime="0" scaletvx="33%" scaletvy="10%" scaletvwidth="65%" scaletvheight="80%"> + <scrollbar> + <area x="30%" y="11%" width="2%" height="78%" layer="2"> + <fill color="{clrDarkBlue}" /> + <drawrectangle x="2" y="2" width="{areawidth} - 4" height="{areaheight} - 4" color="{clrTransparent}" /> + <drawrectangle x="4" y="4 + {areaheight} * {offset} / 1000" width="{areawidth} - 8" height="{areaheight} * {height} / 1000 - 8" color="{clrDarkGreen}" /> + </area> + </scrollbar> + + <menuitems x="{areawidth}*0.005" y="10%" orientation="vertical" width="99%" height="80%" align="center" numlistelements="10"> + <!-- Available Variables channels menu listelement: + {number} number of the displayed channel + {name} name of the displayed channel + {channelid} ChannelID as path to display channel logo + {transponder} Transponder of channel + {frequency} Frequency of channel + {source} Source of channel (S, C, T) + {sourcedescription} Descriptin of source from sources.conf + {position} orbital position of the satellite in case this is a DVB-S source + {isAtsc} true if channel is a ATSC channel + {isCable} true if channel is cable channel + {isSat} true if channel is a satellite channel + {isTerr} true if channel is terrestrical + {presenteventtitle} title of present event on this channel + {presenteventstart} present event start time in hh::mm + {presenteventstop} present event event stop time in hh::mm + {current} true if item is currently selected + {separator} true if item is a list separator + --> + <listelement> + <!-- background and foreground--> + <area x="0" width="28%" layer="2"> + <drawimage condition="not{current}" imagetype="skinpart" path="menubutton" x="0" y="1%" width="{areawidth}" height="{areaheight}*0.98"/> + <drawimage condition="{current}" imagetype="skinpart" path="menubuttonactive" x="0" y="1%" width="{areawidth}" height="{areaheight}*0.98"/> + </area> + <!-- channel logo --> + <area condition="not{separator}" x="5" width="6%" layer="3"> + <drawimage name="logo" imagetype="channellogo" path="{channelid}" x="0" height="100%" valign="center" /> + </area> + <!-- scrollable channel name --> + <areascroll condition="not{separator}++not{current}" scrollelement="channelname" mode="forthandback" orientation="horizontal" delay="1000" scrollspeed="medium" x="7%" width="20%" layer="3"> + <drawtext name="channelname" x="0" y="5" font="{vdrOsd}" fontsize="50%" color="{clrFontMenuItem}" text="{number} {name}" /> + </areascroll> + <areascroll condition="not{separator}++{current}" scrollelement="channelname" mode="forthandback" orientation="horizontal" delay="1000" scrollspeed="medium" x="7%" width="20%" layer="3"> + <drawtext name="channelname" x="0" y="5" font="{vdrOsd}" fontsize="50%" color="{clrFontMenuItemSelected}" text="{number} {name}" /> + </areascroll> + <!-- channel information --> + <area condition="not{separator}++not{current}" x="7%" width="20%" layer="3"> + <drawtext x="0" y="60%" font="{vdrOsd}" fontsize="30%" color="{clrFontMenuItem}" text="{sourcedescription}, {tr(transponder)} {transponder}" /> + </area> + <area condition="not{separator}++{current}" x="7%" width="20%" layer="3"> + <drawtext x="0" y="60%" font="{vdrOsd}" fontsize="30%" color="{clrFontMenuItemSelected}" text="{sourcedescription}, {tr(transponder)} {transponder}" /> + </area> + <!-- separator --> + <area condition="{separator}" x="0" width="28%" layer="3"> + <drawimage name="sep" imagetype="icon" path="ico_channelsep" x="10" valign="center" width="{areaheight}-10" height="{areaheight}-10"/> + <drawtext x="{width(sep)} + 20" valign="center" font="{vdrOsd}" fontsize="60%" color="{clrFontInactive}" text="{name}" /> + </area> + </listelement> + <!-- additional element which is drawn for current element --> + <!-- Available Variables channels menu currentelement: + {number} number of the displayed channel + {name} name of the displayed channel + {channelid} ChannelID as path to display channel logo + {transponder} Transponder of channel + {frequency} Frequency of channel + {source} Source of channel (S, C, T) + {sourcedescription} Descriptin of source from sources.conf + {position} orbital position of the satellite in case this is a DVB-S source + {isAtsc} true if channel is a ATSC channel + {isCable} true if channel is cable channel + {isSat} true if channel is a satellite channel + {isTerr} true if channel is terrestrical + {presenteventtitle} title of present event on this channel + {presenteventstart} present event start time in hh::mm + {presenteventstop} present event stop time in hh::mm + {presenteventshorttext} present event short text + {presenteventdescription} present event description + {presenteventday} present event name of day + {presenteventdate} present event date in dd:mm:yy + {presenteventelapsed} present event elapsed time + {presenteventduration} present event duration + {hasposter} true if a scraped poster is available for this elements present evemt + {posterwidth} width of scraped poster + {posterheight} height of scraped poster + {posterpath} absolute path of scraped poster + {nexteventtitle} title of next event on this channel + {nexteventstart} next event start time in hh::mm + {nexteventstop} next event event stop time in hh::mm + {nexteventshorttext} next event short text + {nexteventdescription} next event description + {nexteventday} next event name of day + {nexteventdate} next event date in dd:mm:yy + {nexteventdate} next event duration + {schedule[]} array with following 10 schedules + {schedule[title]} title of event + {schedule[shorttext]} shorttext of event + {schedule[start]} start time of event in hh:mm + {schedule[stop]} stop time of event in hh:mm + --> + <currentelement delay="500" fadetime="300"> + <area x="32%" y="2%" width="67%" height="96%" layer="2"> + <fill color="{clrTransBlack}" /> + </area> + <area x="32%" y="2%" width="67%" height="76%" layer="2"> + <!-- Logo and Header --> + <drawimage name="logo" imagetype="channellogo" path="{channelid}" x="1%" y="1%" width="20%" /> + <drawtext name="channelname" x="23%" y="{height(logo)} * 3 / 10" font="{vdrOsd}" fontsize="10%" color="{clrWhite}" text="{number} - {name}" /> + <drawtext x="23%" y="{posy(channelname)} + {height(channelname)}" font="{vdrOsd}" fontsize="7%" color="{clrWhite}" text="{sourcedescription}, {tr(transponder)} {transponder}" /> + <!-- NOW --> + <drawtext name="headernow" x="1%" y="{posy(logo)} + {height(logo)} + 10" font="{vdrOsd}" fontsize="6%" color="{clrWhite}" text="{tr(now)}: {presenteventstart} - {presenteventstop}" /> + <drawtext name="titlenow" x="1%" y="{posy(headernow)} + {height(headernow)}" width="48%" font="{vdrOsd}" fontsize="6%" color="{clrWhite}" text="{presenteventtitle}" /> + <drawtextbox x="1%" y="{posy(titlenow)} + {height(titlenow)} + 10" width="48%" height="{areaheight} - {posy(titlenow)} - {height(titlenow)} - 10" font="{vdrOsd}" fontsize="5%" color="{clrWhite}" text="{presenteventshorttext} {presenteventdescription}" /> + <!-- NEXT --> + <drawtext name="headernext" x="51%" y="{posy(logo)} + {height(logo)} + 10" font="{vdrOsd}" fontsize="6%" color="{clrWhite}" text="{tr(next)}: {nexteventstart} - {nexteventstop}" /> + <drawtext name="titlenext" x="51%" y="{posy(headernext)} + {height(headernext)}" width="48%" font="{vdrOsd}" fontsize="6%" color="{clrWhite}" text="{nexteventtitle}" /> + <drawtextbox x="51%" y="{posy(titlenext)} + {height(titlenext)} + 10" width="48%" height="{areaheight} - {posy(titlenext)} - {height(titlenext)} - 10" font="{vdrOsd}" fontsize="5%" color="{clrWhite}" text="{nexteventshorttext} {nexteventdescription}" /> + </area> + <areascroll mode="forthandback" orientation="vertical" delay="1000" scrollspeed="medium" x="32%" y="78%" width="67%" height="20%" layer="2"> + <drawtext x="10" y="0" font="{semibold}" fontsize="20%" color="{clrWhite}" text="{tr(nextschedules)}:" /> + <loop name="schedule" x="0" y="{areaheight}/4 + 5" orientation="vertical"> + <drawtext x="10" font="{vdrOsd}" width="{areawidth}-20" fontsize="19%" color="{clrWhite}" text="{schedule[start]} {schedule[title]}" /> + </loop> + </areascroll> + </currentelement> + </menuitems> +</menuchannels>
\ 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 @@ + <menudefault x="0" y="0" width="100%" height="100%" fadetime="0" scaletvx="0" scaletvy="0" scaletvwidth="0" scaletvheight="0"> + <background> + <area x="0" y="0" width="100%" height="100%" layer="1"> + <fill color="{clrDarkBlue}" /> + </area> + <area x="0" y="0" width="100%" height="10%" layer="2"> + <drawimage imagetype="skinpart" path="headertop" x="0" y="0" width="100%" height="100%"/> + </area> + </background> + + <!-- IMPORTANT: menuitemwidth and determinatefont have to be defined here. menuitemwidth defines the total width of the + default menu items, determinatefont the function which sets the actual font to use. With that it is possible to determinate + the correct column widths --> + <menuitems x="1%" y="10%" orientation="vertical" width="96%" height="80%" align="center" menuitemwidth="96%" determinatefont="column1" numlistelements="16"> + <!-- Available Variables default menu listelement: + {column1} text of column1 + {column2} text of column2 + {column3} text of column3 + {column4} text of column4 + {column5} text of column5 + {column6} text of column6 + {column2set} true if column2 is used + {column3set} true if column3 is used + {column4set} true if column4 is used + {column5set} true if column5 is used + {column6set} true if column6 is used + {column2x} proposed x value of column2 + {column3x} proposed x value of column3 + {column4x} proposed x value of column4 + {column5x} proposed x value of column5 + {column6x} proposed x value of column6 + {column1width} proposed width of column1 + {column2width} proposed width of column2 + {column3width} proposed width of column3 + {column4width} proposed width of column4 + {column5width} proposed width of column5 + {column6width} proposed width of column6 + {current} true if column is currently selected + {separator} true if column is a list separator + --> + <listelement> + <area x="0" width="100%" layer="2"> + <drawimage condition="not{current}" imagetype="skinpart" path="menubuttondefault" x="0" y="1%" width="{areawidth}" height="{areaheight}*0.98"/> + <drawimage condition="{current}" imagetype="skinpart" path="menubuttondefaultactive" x="0" y="1%" width="{areawidth}" height="{areaheight}*0.98"/> + </area> + <areascroll scrollelement="column1" mode="forthandback" orientation="horizontal" delay="1000" scrollspeed="medium" x="1%" width="{column1width}" layer="3"> + <drawtext condition="not{current}" name="column1" x="{column1x}" width="{column1width}" valign="center" font="{vdrOsd}" fontsize="90%" color="{clrFontMenuItem}" text="{column1}" /> + <drawtext condition="{current}" name="column1" x="{column1x}" width="{column1width}" valign="center" font="{vdrOsd}" fontsize="90%" color="{clrFontMenuItemSelected}" text="{column1}" /> + </areascroll> + <area x="1%" width="100%" layer="3"> + <drawtext condition="{column2set}++not{current}" x="{column2x}" valign="center" width="{column2width}" font="{vdrOsd}" fontsize="90%" color="{clrFontMenuItem}" text="{column2}" /> + <drawtext condition="{column2set}++{current}" x="{column2x}" valign="center" width="{column2width}" font="{vdrOsd}" fontsize="90%" color="{clrFontMenuItemSelected}" text="{column2}" /> + <drawtext condition="{column3set}++not{current}" x="{column3x}" valign="center" width="{column3width}" font="{vdrOsd}" fontsize="90%" color="{clrFontMenuItem}" text="{column3}" /> + <drawtext condition="{column3set}++{current}" x="{column3x}" valign="center" width="{column3width}" font="{vdrOsd}" fontsize="90%" color="{clrFontMenuItemSelected}" text="{column3}" /> + <drawtext condition="{column4set}++not{current}" x="{column4x}" valign="center" width="{column4width}" font="{vdrOsd}" fontsize="90%" color="{clrFontMenuItem}" text="{column4}" /> + <drawtext condition="{column4set}++{current}" x="{column4x}" valign="center" width="{column4width}" font="{vdrOsd}" fontsize="90%" color="{clrFontMenuItemSelected}" text="{column4}" /> + <drawtext condition="{column5set}++not{current}" x="{column5x}" valign="center" width="{column5width}" font="{vdrOsd}" fontsize="90%" color="{clrFontMenuItem}" text="{column5}" /> + <drawtext condition="{column5set}++{current}" x="{column5x}" valign="center" width="{column5width}" font="{vdrOsd}" fontsize="90%" color="{clrFontMenuItemSelected}" text="{column5}" /> + <drawtext condition="{column6set}++not{current}" x="{column6x}" valign="center" width="{column6width}" font="{vdrOsd}" fontsize="90%" color="{clrFontMenuItem}" text="{column6}" /> + <drawtext condition="{column6set}++{current}" x="{column6x}" valign="center" width="{column6width}" font="{vdrOsd}" fontsize="90%" color="{clrFontMenuItemSelected}" text="{column6}" /> + </area> + </listelement> + + </menuitems> +</menudefault> 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 @@ +<menudetailedepg x="0" y="0" width="100%" height="100%" fadetime="0"> + <background> + <area x="0" y="0" width="100%" height="100%" layer="1"> + <fill color="{clrTransBlack}" /> + <drawrectangle x="0" y="0" width="100%" height="10%" color="{clrDarkBlue}" /> + </area> + <area x="0" y="0" width="100%" height="10%" layer="2"> + <drawimage imagetype="skinpart" path="headertop" x="0" y="0" width="100%" height="100%"/> + </area> + </background> + <scrollbar> + <area x="97%" y="25%" width="2%" height="60%" layer="2"> + <fill color="{clrDarkBlue}" /> + <drawrectangle x="2" y="2" width="{areawidth} - 4" height="{areaheight} - 4" color="{clrTransparent}" /> + <drawrectangle x="4" y="4 + {areaheight} * {offset} / 1000" width="{areawidth} - 8" height="{areaheight} * {height} / 1000 - 8" color="{clrDarkGreen}" /> + </area> + </scrollbar> + <!-- Available Variables in detailheader elements: + {title} title of event + {shorttext} shorttext of event + {start} event start time in hh::mm + {stop} event stop time + {day} day of current event + {date} date of current event in dd.mm.yy + {running} true if event is currently running + {elapsed} elapsed time of event, if not running 0 + {duration} duration of event + {channelid} ChannelID as path to display channel logo + {ismovie} true if event is scraped as a movie + {isseries} true if event is scraped as a series + {posteravailable} true if a poster is available + {posterwidth} width of scraped poster + {posterheight} height of scraped poster + {posterpath} absolute path of scraped poster + {banneravailable} true if a banner is available + {bannerwidth} width of banner + {bannerheight} height of banner + {bannerpath} path of banner + {epgpicavailable} true if a epg picture is available + {epgpicpath} path of epg picture + --> + <detailheader> + <area x="1%" y="10%" width="98%" height="15%" layer="2"> + <fill color="{clrTransBlack}" /> + </area> + <area x="1%" y="10%" width="98%" height="15%" layer="3"> + <drawimage name="logo" imagetype="channellogo" path="{channelid}" x="0" height="80%" valign="center" /> + + <drawimage condition="{isseries}++{banneravailable}++not{epgpicavailable}" imagetype="image" path="{bannerpath}" x="{areawidth} - {areawidth}/3 - 10" valign="center" width="{areawidth}/3" height="{areawidth}/3 * {bannerheight} / {bannerwidth}"/> + <drawimage condition="{ismovie}++{posteravailable}++not{epgpicavailable}" imagetype="image" path="{posterpath}" x="{areawidth} - {areaheight}*8/10" valign="center" width="{areaheight}*8 / 10 * {posterheight} / {posterwidth}" height="{areaheight}*8 / 10"/> + <drawimage condition="{epgpicavailable}" imagetype="image" path="{epgpicpath}" x="{areawidth} - {areaheight}*8/10 * 174 / 130" valign="center" width="{areaheight}*8/10 * 174 / 130" height="{areaheight}*8 / 10"/> + + <drawtext name="title" x="{width(logo)} + 20" valign="center" font="{vdrOsd}" fontsize="35%" color="{clrWhite}" text="{title}" /> + <drawtext name="datetime" x="{width(logo)} + 20" y="{posy(title)} - {height(datetime)}" font="{vdrOsd}" fontsize="25%" color="{clrWhite}" text="{day} {date} {start} - {stop} ({duration} mins)" /> + <drawtext name="shorttext" x="{width(logo)} + 20" y="{posy(title)} + {height(title)}" font="{vdrOsd}" fontsize="25%" color="{clrWhite}" text="{shorttext}" /> + </area> + </detailheader> + + <!-- Available Variables in tab elements: + {title} title of event + {shorttext} shorttext of event + {description} description of event + {start} event start time in hh::mm + {stop} event stop time + {day} day of current event + {date} date of current event in dd.mm.yy + {running} true if event is currently running + {elapsed} elapsed time of event, if not running 0 + {duration} duration of event + {channelid} ChannelID as path to display channel logo + {hasreruns} true if reruns of this event are found + {reruns[]} array with reruns + {reruns[title]} title of rerun + {reruns[shorttext]} shorttext of rerun + {reruns[date]} date of rerun in dd:mm + {reruns[day]} short dayname of rerun + {reruns[start]} start time of rerun in hh:mm + {reruns[stop]} stop time of rerun in hh:mm + {reruns[channelname]} name of channel on which rerun occurs + {reruns[channelnumber]} number of channel on which rerun occurs + {reruns[channelid]} id of channel on which rerun occurs to display channel logo + {reruns[channellogoexists]} true if channel logo exists + {epgpic1avaialble} true if first epg picture is available + {epgpic2avaialble} true if first epg picture is available + {epgpic3avaialble} true if first epg picture is available + {epgpic1path} path of first epg picture + {epgpic2path} path of second epg picture + {epgpic3path} path of third epg picture + + {ismovie} true if event is scraped as a movie + Available variables for movies: + {movietitle} movie title from themoviedb + {movieoriginalTitle} movie original title from themoviedb + {movietagline} movie tagline from themoviedb + {movieoverview} movie overview from themoviedb + {movieadult} true if movie is rated as adult + {moviebudget} movie budget from themoviedb in $ + {movierevenue} movie revenue from themoviedb in $ + {moviegenres} movie genres from themoviedb + {moviehomepage} movie homepage from themoviedb + {moviereleasedate} movie release date from themoviedb + {movieruntime} movie runtime from themoviedb + {moviepopularity} movie popularity from themoviedb + {movievoteaverage} movie vote average from themoviedb + {posterwidth} width of scraped poster + {posterheight} height of scraped poster + {posterpath} absolute path of scraped poster + {fanartwidth} width of scraped fanart + {fanartheight} height of scraped fanart + {fanartpath} absolute path of scraped fanart + {movieiscollection} true if movie is part of a collection + {moviecollectionName} name of movie collection + {collectionposterwidth} width of scraped collection poster + {collectionposterheight} height of scraped collection poster + {collectionposterpath} absolute path of scraped collection poster + {collectionfanartwidth} width of scraped collection fanart + {collectionfanartheight} height of scraped collection fanart + {collectionfanartpath} absolute path of scraped collection fanart + {actors[]} array with movie actors + {actors[name]} real name of actor + {actors[role]} actor role + {actors[thumb]} absolute path of scraped actor thumb + {actors[thumbwidth]} width of scraped actor thumb + {actors[thumbheight]} height of scraped actor thumb + + {isseries} true if event is scraped as a series + Available variables for series: + {seriesname} name of series + {seriesoverview} series overview + {seriesfirstaired} first aired date + {seriesnetwork} network which produces series + {seriesgenre} series genre + {seriesrating} series thetvdb rating + {seriesstatus} status of series (running / finished) + {episodetitle} title of episode + {episodenumber} number of episode + {episodeseason} season of episode + {episodefirstaired} first aired date of episode + {episodegueststars} guest stars of episode + {episodeoverview} episode overview + {episoderating} user rating for episode + {episodeimagewidth} episode image width + {episodeimageheight} episode image height + {episodeimagepath} episode image path + {seasonposterwidth} episode season poster width + {seasonposterheight} episode season poster height + {seasonposterpath} episode season poster path + {seriesposter1width} width of 1st poster + {seriesposter1height} height of 1st poster + {seriesposter1path} path of 1st poster + {seriesposter2width} width of 2nd poster + {seriesposter2height} height of 2nd poster + {seriesposter2path} path of 2nd poster + {seriesposter3width} width of 3rd poster + {seriesposter3height} height of 3rd poster + {seriesposter3path} path of 3rd poster + {seriesfanart1width} width of 1st fanart + {seriesfanart1height} height of 1st fanart + {seriesfanart1path} path of 1st fanart + {seriesfanart2width} width of 2nd fanart + {seriesfanart2height} height of 2nd fanart + {seriesfanart2path} path of 2nd fanart + {seriesfanart3width} width of 3rd fanart + {seriesfanart3height} height of 3rd fanart + {seriesfanart3path} path of 3rd fanart + {seriesbanner1width} width of 1st banner + {seriesbanner1height} height of 1st banner + {seriesbanner1path} path of 1st banner + {seriesbanner2width} width of 2nd banner + {seriesbanner2height} height of 2nd banner + {seriesbanner2path} path of 2nd banner + {seriesbanner3width} width of 3rd banner + {seriesbanner3height} height of 3rd banner + {seriesbanner3path} path of 3rd fanart + {actors[]} array with movie actors + {actors[name]} real name of actor + {actors[role]} actor role + {actors[thumb]} absolute path of scraped actor thumb + {actors[thumbwidth]} width of scraped actor thumb + {actors[thumbheight]} height of scraped actor thumb + --> + + <!-- TAB EPGINFO --> + <tab name="EPG Info" x="2%" y="25%" width="94%" height="60%" layer="2" scrollheight="{areaheight}/4"> + <drawtextbox condition="not{isseries}++not{ismovie}" x="0" y="10" width="96%" font="{vdrOsd}" fontsize="6%" color="{clrWhite}" text="{description}" /> + <drawimage condition="{isseries}" name="seriesposter" imagetype="image" path="{seriesposter1path}" x="{areawidth}*0.75" y="10" width="{areawidth}*0.25" height="{areawidth} * 0.25 * {seriesposter1height} / {seriesposter1width}"/> + <drawimage condition="{ismovie}" name="movieposter" imagetype="image" path="{posterpath}" x="{areawidth}*0.75" y="10" width="{areawidth}*0.25" height="{areawidth} * 0.25 * {posterheight} / {posterwidth}" /> + <drawtextbox condition="{isseries}" x="0" y="10" width="96%" float="topright" floatwidth="{width(seriesposter)} + 10" floatheight="{height(seriesposter)} + 20" font="{vdrOsd}" fontsize="6%" color="{clrWhite}" text="{description}" /> + <drawtextbox condition="{ismovie}" x="0" y="10" width="96%" float="topright" floatwidth="{width(movieposter)} + 10" floatheight="{height(movieposter)} + 20" font="{vdrOsd}" fontsize="6%" color="{clrWhite}" text="{description}" /> + </tab> + <!-- TAB RERUNS --> + <tab condition="{hasreruns}" name="{tr(reruns)}" x="2%" y="25%" width="94%" height="60%" layer="2" scrollheight="{areaheight}/4"> + <drawtext align="center" y="0" name="title" font="{vdrOsd}" fontsize="10%" color="{clrWhite}" text="{tr(rerunsof)} '{title}'" /> + <loop name="reruns" x="0" y="{height(title)} + 10" width="{areawidth}" orientation="vertical"> + <drawimage name="logo" condition="{reruns[channellogoexists]}" imagetype="channellogo" path="{reruns[channelid]}" x="0" height="10%" /> + <drawtext name="channelname" condition="not{reruns[channellogoexists]}" x="-5" font="{vdrOsd}" fontsize="10%" color="{clrWhite}" text="{reruns[channelname]}" /> + <drawtext condition="{reruns[channellogoexists]}" x="{width(logo)}+20" y="-5" width="{areawidth} - {width(logo)} - 20" font="{vdrOsd}" fontsize="8%" color="{clrWhite}" text="{reruns[day]} {reruns[date]} {reruns[start]} - {reruns[stop]}: {reruns[title]} {reruns[shorttext]}" /> + <drawtext condition="not{reruns[channellogoexists]}" x="{width(channelname)}+20" y="-5" width="{areawidth} - {width(logo)} - 20" font="{vdrOsd}" fontsize="8%" color="{clrWhite}" text="{reruns[day]} {reruns[date]} {reruns[start]} - {reruns[stop]}: {reruns[title]} {reruns[shorttext]}" /> + </loop> + </tab> + <!-- TAB ACTORS --> + <tab condition="{isseries}||{ismovie}" name="{tr(actors)}" x="2%" y="25%" width="94%" height="60%" layer="2" scrollheight="{areaheight}/4"> + <drawtext align="center" name="title" y="0" font="{vdrOsd}" fontsize="15%" color="{clrWhite}" text="{tr(actors)}" /> + <loop name="actors" x="0" y="{height(title)} + 10" width="{areawidth}" orientation="horizontal" columnwidth="{areawidth}/5" rowheight="{areawidth}/5*1.8" overflow="linewrap"> + <drawimage name="thumb" imagetype="image" path="{actors[thumb]}" x="20" y="0" width="{columnwidth}-40" height="{columnwidth} * {actors[thumbheight]} / {actors[thumbwidth]} - 40 * {actors[thumbheight]} / {actors[thumbwidth]}"/> + <drawtext align="center" y="{height(thumb)} + 10" width="{columnwidth}" name="actorname" font="{vdrOsd}" fontsize="7%" color="{clrWhite}" text="{actors[name]}" /> + <drawtext align="center" y="{height(thumb)} + 10 + {height(actorname)}" width="{columnwidth}" font="{vdrOsd}" fontsize="7%" color="{clrWhite}" text="{actors[role]}" /> + </loop> + </tab> + <!-- TAB TVDBINFO --> + <tab condition="{isseries}" name="TvDBInfo" x="2%" y="25%" width="94%" height="60%" layer="2" scrollheight="{areaheight}/4"> + <drawimage name="banner" imagetype="image" path="{seriesbanner1path}" align="center" y="10" width="{areawidth}*0.9" height="{areawidth} * 0.9 * {seriesbanner1height} / {seriesbanner1width}"/> + <drawimage name="episodeimage" imagetype="image" path="{episodeimagepath}" x="{areawidth}*0.7" y="{height(banner)} + 20" width="{areawidth}*0.3" height="{areawidth} * 0.3 * {episodeimageheight} / {episodeimagewidth}"/> + <drawimage name="seasonposter" imagetype="image" path="{seasonposterpath}" x="{areawidth}*0.7" y="{height(banner)} + {height(episodeimage)} + 30" width="{areawidth}*0.3" height="{areawidth} * 0.3 * {seasonposterheight} / {seasonposterwidth}"/> + <drawtextbox x="0" y="{height(banner)} + 20" width="96%" float="topright" floatwidth="{width(seasonposter)} + 10" floatheight="{height(episodeimage)} + {height(seasonposter)} + 30" font="{vdrOsd}" fontsize="6%" color="{clrWhite}" text="{tr(episode)}: {episodetitle} ({tr(season)} {episodeseason}, {tr(episode)} {episodenumber}) {episodeoverview}| {tr(gueststars)}: {episodegueststars}|| {tr(seriesfirstaired)}: {seriesfirstaired}|| {tr(episodefirstaired)}: {episodefirstaired}|| {tr(network)}: {seriesnetwork}|| {tr(genre)}: {seriesgenre}|| {tr(status)}: {seriesstatus}|| {tr(rating)}: {seriesrating}|| {tr(episoderating)}: {episoderating} |{seriesoverview} " /> + </tab> + <!-- TAB SERIESGALERY --> + <tab condition="{isseries}" name="{tr(seriesgalery)}" x="2%" y="25%" width="94%" height="60%" layer="2" scrollheight="{areaheight}/4"> + <drawimage name="banner1" imagetype="image" path="{seriesbanner1path}" align="center" y="10" width="{areawidth}*0.9" height="{areawidth} * 0.9 * {seriesbanner1height} / {seriesbanner1width}"/> + <drawimage name="fanart1" imagetype="image" path="{seriesfanart1path}" align="center" y="{posy(banner1)} + {height(banner1)} + 20" width="{areawidth}*0.9" height="{areawidth} * 0.9 * {seriesfanart1height} / {seriesfanart1width}"/> + <drawimage name="banner2" imagetype="image" path="{seriesbanner2path}" align="center" y="{posy(fanart1)} + {height(fanart1)} + 20" width="{areawidth}*0.9" height="{areawidth} * 0.9 * {seriesbanner2height} / {seriesbanner2width}"/> + <drawimage name="fanart2" imagetype="image" path="{seriesfanart2path}" align="center" y="{posy(banner2)} + {height(banner2)} + 20" width="{areawidth}*0.9" height="{areawidth} * 0.9 * {seriesfanart2height} / {seriesfanart2width}"/> + <drawimage name="banner3" imagetype="image" path="{seriesbanner3path}" align="center" y="{posy(fanart2)} + {height(fanart2)} + 20" width="{areawidth}*0.9" height="{areawidth} * 0.9 * {seriesbanner3height} / {seriesbanner3width}"/> + <drawimage name="fanart3" imagetype="image" path="{seriesfanart3path}" align="center" y="{posy(banner3)} + {height(banner3)} + 20" width="{areawidth}*0.9" height="{areawidth} * 0.9 * {seriesfanart3height} / {seriesfanart3width}"/> + <drawimage name="poster1" imagetype="image" path="{seriesposter1path}" align="center" y="{posy(fanart3)} + {height(fanart3)} + 20" width="{areawidth}*0.5" height="{areawidth} * 0.5 * {seriesposter1height} / {seriesposter1width}"/> + <drawimage name="poster2" imagetype="image" path="{seriesposter2path}" align="center" y="{posy(poster1)} + {height(poster1)} + 20" width="{areawidth}*0.5" height="{areawidth} * 0.5 * {seriesposter2height} / {seriesposter2width}"/> + <drawimage name="poster3" imagetype="image" path="{seriesposter3path}" align="center" y="{posy(poster2)} + {height(poster2)} + 20" width="{areawidth}*0.5" height="{areawidth} * 0.5 * {seriesposter3height} / {seriesposter3width}"/> + </tab> + <!-- TAB MOVIEDBINFO --> + <tab condition="{ismovie}" name="MovieDBInfo" x="2%" y="25%" width="94%" height="60%" layer="2" scrollheight="{areaheight}/4"> + <drawimage name="poster" imagetype="image" path="{posterpath}" x="70%" y="10" width="{areawidth}*0.3" height="{areawidth} * 0.3 * {posterheight} / {posterwidth}"/> + <drawtextbox x="0" y="10" width="96%" float="topright" floatwidth="{width(poster)} + 10" floatheight="{height(poster)} + 20" font="{vdrOsd}" fontsize="8%" color="{clrWhite}" text="{tr(originaltitle)}: {movieoriginalTitle} |{tr(genre)}: {moviegenres} ||{movietagline} |{movieoverview} |{tr(budget)}: {moviebudget} ||{tr(revenue)}: {movierevenue} ||{tr(adult)}: {movieadult} ||{tr(releasedate)}: {moviereleasedate} ||{tr(runtime)}: {movieruntime} min || {tr(popularity)}: {moviepopularity} || {tr(voteaverage)}: {movievoteaverage} || {tr(homepage)}: {moviehomepage}| " /> + </tab> + <!-- TAB MOVIEGALERY --> + <tab condition="{ismovie}" name="{tr(moviegalery)}" x="2%" y="25%" width="94%" height="60%" layer="2" scrollheight="{areaheight}/4"> + <drawimage name="fanart" imagetype="image" path="{fanartpath}" align="center" y="10" width="{areawidth}*0.9" height="{areawidth} * 0.9 * {fanartheight} / {fanartwidth}"/> + <drawimage name="poster" imagetype="image" path="{posterpath}" align="center" y="{height(fanart)} + 30" width="{areawidth}*0.6" height="{areawidth} * 0.6 * {posterheight} / {posterwidth}"/> + <drawimage condition="{movieiscollection}" name="collectionfanart" imagetype="image" path="{collectionfanartpath}" align="center" y="{posy(poster)} + {height(poster)} + 20" width="{areawidth}*0.9" height="{areawidth} * 0.9 * {collectionfanartheight} / {collectionfanartwidth}"/> + <drawimage condition="{movieiscollection}" name="collectionposter" imagetype="image" path="{collectionposterpath}" align="center" y="{posy(collectionfanart)} + {height(collectionfanart)} + 20" width="{areawidth}*0.6" height="{areawidth} * 0.6 * {collectionposterheight} / {collectionposterwidth}"/> + </tab> + <!-- Available Variables tablabels: + {tabs[]} array with available tab labels + {tabs[title]} title of tab + {tabs[current]} true if tab is displayed currently + --> + <tablabels> + <area x="1%" y="85%" width="98%" height="5%" layer="3"> + <loop name="tabs" x="0" y="0" orientation="horizontal"> + <drawrectangle condition="{tabs[current]}" x="0" y="0" width="{width(label)}" height="100%" color="{clrDarkGreen}" /> + <drawrectangle condition="not{tabs[current]}" x="0" y="0" width="{width(label)}" height="100%" color="{clrDarkGreen}" /> + <drawrectangle condition="not{tabs[current]}" x="2" y="2" width="{width(label)} - 4" height="{areaheight}-4" color="{clrTransparent}" /> + <drawtext name="label" x="0" valign="center" font="{vdrOsd}" fontsize="95%" color="{clrWhite}" text=" {tabs[title]} " /> + </loop> + </area> + </tablabels> +</menudetailedepg>
\ 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 @@ +<menudetailedrecording x="0" y="0" width="100%" height="100%" fadetime="0"> + <background> + <area x="0" y="0" width="100%" height="100%" layer="1"> + <fill color="{clrTransBlack}" /> + <drawrectangle x="0" y="0" width="100%" height="10%" color="{clrDarkBlue}" /> + </area> + <area x="0" y="0" width="100%" height="10%" layer="2"> + <drawimage imagetype="skinpart" path="headertop" x="0" y="0" width="100%" height="100%"/> + </area> + </background> + <scrollbar> + <area x="97%" y="25%" width="2%" height="60%" layer="2"> + <fill color="{clrDarkBlue}" /> + <drawrectangle x="2" y="2" width="{areawidth} - 4" height="{areaheight} - 4" color="{clrTransparent}" /> + <drawrectangle x="4" y="4 + {areaheight} * {offset} / 1000" width="{areawidth} - 8" height="{areaheight} * {height} / 1000 - 8" color="{clrDarkGreen}" /> + </area> + </scrollbar> + <!-- Available Variables in detailheader elements: + {name} name of recording + {shorttext} shorttext of recording + {date} date of recording in dd.mm.yy + {time} time of current event in hh:mm + {duration} real duration of recording in minutes + {durationevent} duration of according event in minutes + {ismovie} true if event is scraped as a movie + {isseries} true if event is scraped as a series + {posteravailable} true if a poster is available + {posterwidth} width of scraped poster + {posterheight} height of scraped poster + {posterpath} absolute path of scraped poster + {banneravailable} true if a banner is available + {bannerwidth} width of banner + {bannerheight} height of banner + {bannerpath} path of banner + {recimgavailable} true if a recording image is available in the recording path + {recimgpath} path of rec image + --> + <detailheader> + <area x="1%" y="10%" width="98%" height="15%" layer="2"> + <fill color="{clrTransBlack}" /> + </area> + <area x="1%" y="10%" width="98%" height="15%" layer="3"> + <drawimage condition="{isseries}++{banneravailable}++not{recimgavailable}" imagetype="image" path="{bannerpath}" x="{areawidth} - {areawidth}/3 - 10" valign="center" width="{areawidth}/3" height="{areawidth}/3 * {bannerheight} / {bannerwidth}"/> + <drawimage condition="{ismovie}++{posteravailable}++not{recimgavailable}" imagetype="image" path="{posterpath}" x="{areawidth} - {areaheight}*8/10" valign="center" width="{areaheight}*8 / 10 * {posterheight} / {posterwidth}" height="{areaheight}*8 / 10"/> + <drawimage condition="{recimgavailable}" imagetype="image" path="{recimgpath}" x="{areawidth} - {areaheight}*8/10 * 174 / 130" valign="center" width="{areaheight}*8/10 * 174 / 130" height="{areaheight}*8 / 10"/> + <drawtext name="title" x="20" valign="center" font="{vdrOsd}" fontsize="35%" color="{clrWhite}" text="{name}" /> + <drawtext name="datetime" x="20" y="{posy(title)} - {height(datetime)}" font="{vdrOsd}" fontsize="25%" color="{clrWhite}" text="{date} {time} ({duration} mins)" /> + <drawtext name="shorttext" x="20" y="{posy(title)} + {height(title)}" font="{vdrOsd}" fontsize="25%" color="{clrWhite}" text="{shorttext}" /> + </area> + </detailheader> + <!-- Available Variables in tab elements: + {name} title of recording + {shorttext} shorttext of recording + {description} description of recording + {date} date of recording in dd.mm.yy + {time} time of recording in hh:mm + {duration} real duration of recording in minutes + {durationevent} duration of according event in minutes + + {recordingsize} size of recording (automatically in GB / MB) + {recordingsizecutted} size of cutted recording (automatically in GB / MB) + {recordinglength} length of recording (in hh::mm:ss) + {recordinglengthcutted} length of cutted recording (in hh::mm:ss) + {recordingbitrate} bitrate of recording (in MBit/s) + {recordingformat} format of recording (TS / PS) + {searchtimer} name of accordign searchtimer (if available) + + {recimg1avaialble} true if first recording image is available + {recimg2avaialble} true if first recording image is available + {recimg3avaialble} true if first recording image is available + {recimg1path} path of first recording image + {recimg2path} path of second recording image + {recimg3path} path of third recording image + + {ismovie} true if event is scraped as a movie + Available variables for movies: + {movietitle} movie title from themoviedb + {movieoriginalTitle} movie original title from themoviedb + {movietagline} movie tagline from themoviedb + {movieoverview} movie overview from themoviedb + {movieadult} true if movie is rated as adult + {moviebudget} movie budget from themoviedb in $ + {movierevenue} movie revenue from themoviedb in $ + {moviegenres} movie genres from themoviedb + {moviehomepage} movie homepage from themoviedb + {moviereleasedate} movie release date from themoviedb + {movieruntime} movie runtime from themoviedb + {moviepopularity} movie popularity from themoviedb + {movievoteaverage} movie vote average from themoviedb + {posterwidth} width of scraped poster + {posterheight} height of scraped poster + {posterpath} absolute path of scraped poster + {fanartwidth} width of scraped fanart + {fanartheight} height of scraped fanart + {fanartpath} absolute path of scraped fanart + {movieiscollection} true if movie is part of a collection + {moviecollectionName} name of movie collection + {collectionposterwidth} width of scraped collection poster + {collectionposterheight} height of scraped collection poster + {collectionposterpath} absolute path of scraped collection poster + {collectionfanartwidth} width of scraped collection fanart + {collectionfanartheight} height of scraped collection fanart + {collectionfanartpath} absolute path of scraped collection fanart + {actors[]} array with movie actors + {actors[name]} real name of actor + {actors[role]} actor role + {actors[thumb]} absolute path of scraped actor thumb + {actors[thumbwidth]} width of scraped actor thumb + {actors[thumbheight]} height of scraped actor thumb + + {isseries} true if event is scraped as a series + Available variables for series: + {seriesname} name of series + {seriesoverview} series overview + {seriesfirstaired} first aired date + {seriesnetwork} network which produces series + {seriesgenre} series genre + {seriesrating} series thetvdb rating + {seriesstatus} status of series (running / finished) + {episodetitle} title of episode + {episodenumber} number of episode + {episodeseason} season of episode + {episodefirstaired} first aired date of episode + {episodegueststars} guest stars of episode + {episodeoverview} episode overview + {episoderating} user rating for episode + {episodeimagewidth} episode image width + {episodeimageheight} episode image height + {episodeimagepath} episode image path + {seasonposterwidth} episode season poster width + {seasonposterheight} episode season poster height + {seasonposterpath} episode season poster path + {seriesposter1width} width of 1st poster + {seriesposter1height} height of 1st poster + {seriesposter1path} path of 1st poster + {seriesposter2width} width of 2nd poster + {seriesposter2height} height of 2nd poster + {seriesposter2path} path of 2nd poster + {seriesposter3width} width of 3rd poster + {seriesposter3height} height of 3rd poster + {seriesposter3path} path of 3rd poster + {seriesfanart1width} width of 1st fanart + {seriesfanart1height} height of 1st fanart + {seriesfanart1path} path of 1st fanart + {seriesfanart2width} width of 2nd fanart + {seriesfanart2height} height of 2nd fanart + {seriesfanart2path} path of 2nd fanart + {seriesfanart3width} width of 3rd fanart + {seriesfanart3height} height of 3rd fanart + {seriesfanart3path} path of 3rd fanart + {seriesbanner1width} width of 1st banner + {seriesbanner1height} height of 1st banner + {seriesbanner1path} path of 1st banner + {seriesbanner2width} width of 2nd banner + {seriesbanner2height} height of 2nd banner + {seriesbanner2path} path of 2nd banner + {seriesbanner3width} width of 3rd banner + {seriesbanner3height} height of 3rd banner + {seriesbanner3path} path of 3rd fanart + {actors[]} array with movie actors + {actors[name]} real name of actor + {actors[role]} actor role + {actors[thumb]} absolute path of scraped actor thumb + {actors[thumbwidth]} width of scraped actor thumb + {actors[thumbheight]} height of scraped actor thumb + --> + + <!-- a tab is one scrolling area, just position and draw as inside a normal area --> + <!-- just define as many tabs as needed --> + <tab name="Info" x="2%" y="25%" width="94%" height="60%" layer="2" scrollheight="{areaheight}/4"> + <drawtextbox condition="not{isseries}++not{ismovie}" x="0" y="0" width="96%" font="{vdrOsd}" fontsize="8%" color="{clrWhite}" text="{description}" /> + <drawimage condition="{isseries}" name="seriesposter" imagetype="image" path="{seriesposter1path}" x="{areawidth}*0.7" y="0" width="{areawidth}*0.3" height="{areawidth} * 0.3 * {seriesposter1height} / {seriesposter1width}"/> + <drawimage condition="{ismovie}" name="movieposter" imagetype="image" path="{posterpath}" x="{areawidth}*0.7" y="0" width="{areawidth}*0.3" height="{areawidth} * 0.3 * {posterheight} / {posterwidth}" /> + <drawtextbox condition="{isseries}" x="0" y="0" width="96%" float="topright" floatwidth="{width(seriesposter)} + 10" floatheight="{height(seriesposter)} + 20" font="{vdrOsd}" fontsize="6%" color="{clrWhite}" text="{description}" /> + <drawtextbox condition="{ismovie}" x="0" y="0" width="96%" float="topright" floatwidth="{width(movieposter)} + 10" floatheight="{height(movieposter)} + 20" font="{vdrOsd}" fontsize="6%" color="{clrWhite}" text="{description}" /> + </tab> + <tab name="{tr(recinfo)}" x="2%" y="25%" width="94%" height="60%" layer="2" scrollheight="{areaheight}/4"> + <drawtext align="center" y="0" name="title" font="{vdrOsd}" fontsize="10%" color="{clrWhite}" text="{tr(recinfo)}" /> + <drawtextbox x="0" y="{height(title)} + 20" width="96%" font="{vdrOsd}" fontsize="8%" color="{clrWhite}" text="{tr(recsize)}: {recordingsize} {tr(recsizecutted)}: {recordingsizecutted} {tr(reclength)}: {recordinglength} {tr(reclengthcutted)}: {recordinglengthcutted} {tr(bitrate)}: {recordingbitrate} {tr(format)}: {recordingformat} {tr(searchtimer)}: {searchtimer} " /> + </tab> + <tab condition="{isseries}||{ismovie}" name="{tr(actors)}" x="2%" y="25%" width="94%" height="60%" layer="2" scrollheight="{areaheight}/4"> + <drawtext align="center" name="title" y="0" font="{vdrOsd}" fontsize="10%" color="{clrWhite}" text="{tr(actors)}" /> + <loop name="actors" x="0" y="{height(title)} + 10" width="{areawidth}" orientation="horizontal" columnwidth="{areawidth}/5" rowheight="{areawidth}/5*1.8" overflow="linewrap"> + <drawimage name="thumb" imagetype="image" path="{actors[thumb]}" x="20" y="0" width="{columnwidth}-40" height="{columnwidth} * {actors[thumbheight]} / {actors[thumbwidth]} - 40 * {actors[thumbheight]} / {actors[thumbwidth]}"/> + <drawtext align="center" y="{height(thumb)} + 10" width="{columnwidth}" name="actorname" font="{vdrOsd}" fontsize="7%" color="{clrWhite}" text="{actors[name]}" /> + <drawtext align="center" y="{height(thumb)} + 10 + {height(actorname)}" width="{columnwidth}" font="{vdrOsd}" fontsize="7%" color="{clrWhite}" text="{actors[role]}" /> + </loop> + </tab> + <tab condition="{isseries}" name="TvDBInfo" x="2%" y="25%" width="94%" height="60%" layer="2" scrollheight="{areaheight}/4"> + <drawimage name="banner" imagetype="image" path="{seriesbanner1path}" align="center" y="10" width="{areawidth}*0.9" height="{areawidth} * 0.9 * {seriesbanner1height} / {seriesbanner1width}"/> + <drawimage name="episodeimage" imagetype="image" path="{episodeimagepath}" x="{areawidth}*0.7" y="{height(banner)} + 20" width="{areawidth}*0.3" height="{areawidth} * 0.3 * {episodeimageheight} / {episodeimagewidth}"/> + <drawimage name="seasonposter" imagetype="image" path="{seasonposterpath}" x="{areawidth}*0.7" y="{height(banner)} + {height(episodeimage)} + 30" width="{areawidth}*0.3" height="{areawidth} * 0.3 * {seasonposterheight} / {seasonposterwidth}"/> + <drawtextbox x="0" y="{height(banner)} + 20" width="96%" float="topright" floatwidth="{width(seasonposter)} + 10" floatheight="{height(episodeimage)} + {height(seasonposter)} + 30" font="{vdrOsd}" fontsize="6%" color="{clrWhite}" text="{tr(episode)}: {episodetitle} ({tr(season)} {episodeseason}, {tr(episode)} {episodenumber}) {episodeoverview}| {tr(gueststars)}: {episodegueststars}|| {tr(seriesfirstaired)}: {seriesfirstaired}|| {tr(episodefirstaired)}: {episodefirstaired}|| {tr(network)}: {seriesnetwork}|| {tr(genre)}: {seriesgenre}|| {tr(status)}: {seriesstatus}|| {tr(rating)}: {seriesrating}|| {tr(episoderating)}: {episoderating} |{seriesoverview} " /> + </tab> + <tab condition="{isseries}" name="{tr(seriesgalery)}" x="2%" y="25%" width="94%" height="60%" layer="2" scrollheight="{areaheight}/4"> + <drawimage name="banner1" imagetype="image" path="{seriesbanner1path}" align="center" y="10" width="{areawidth}*0.9" height="{areawidth} * 0.9 * {seriesbanner1height} / {seriesbanner1width}"/> + <drawimage name="fanart1" imagetype="image" path="{seriesfanart1path}" align="center" y="{posy(banner1)} + {height(banner1)} + 20" width="{areawidth}*0.9" height="{areawidth} * 0.9 * {seriesfanart1height} / {seriesfanart1width}"/> + <drawimage name="banner2" imagetype="image" path="{seriesbanner2path}" align="center" y="{posy(fanart1)} + {height(fanart1)} + 20" width="{areawidth}*0.9" height="{areawidth} * 0.9 * {seriesbanner2height} / {seriesbanner2width}"/> + <drawimage name="fanart2" imagetype="image" path="{seriesfanart2path}" align="center" y="{posy(banner2)} + {height(banner2)} + 20" width="{areawidth}*0.9" height="{areawidth} * 0.9 * {seriesfanart2height} / {seriesfanart2width}"/> + <drawimage name="banner3" imagetype="image" path="{seriesbanner3path}" align="center" y="{posy(fanart2)} + {height(fanart2)} + 20" width="{areawidth}*0.9" height="{areawidth} * 0.9 * {seriesbanner3height} / {seriesbanner3width}"/> + <drawimage name="fanart3" imagetype="image" path="{seriesfanart3path}" align="center" y="{posy(banner3)} + {height(banner3)} + 20" width="{areawidth}*0.9" height="{areawidth} * 0.9 * {seriesfanart3height} / {seriesfanart3width}"/> + <drawimage name="poster1" imagetype="image" path="{seriesposter1path}" align="center" y="{posy(fanart3)} + {height(fanart3)} + 20" width="{areawidth}*0.5" height="{areawidth} * 0.5 * {seriesposter1height} / {seriesposter1width}"/> + <drawimage name="poster2" imagetype="image" path="{seriesposter2path}" align="center" y="{posy(poster1)} + {height(poster1)} + 20" width="{areawidth}*0.5" height="{areawidth} * 0.5 * {seriesposter2height} / {seriesposter2width}"/> + <drawimage name="poster3" imagetype="image" path="{seriesposter3path}" align="center" y="{posy(poster2)} + {height(poster2)} + 20" width="{areawidth}*0.5" height="{areawidth} * 0.5 * {seriesposter3height} / {seriesposter3width}"/> + </tab> + <tab condition="{ismovie}" name="MovieDBInfo" x="2%" y="25%" width="94%" height="60%" layer="2" scrollheight="{areaheight}/4"> + <drawimage name="poster" imagetype="image" path="{posterpath}" x="70%" y="10" width="{areawidth}*0.3" height="{areawidth} * 0.3 * {posterheight} / {posterwidth}"/> + <drawtextbox x="0" y="10" width="96%" float="topright" floatwidth="{width(poster)} + 10" floatheight="{height(poster)} + 20" font="{vdrOsd}" fontsize="6%" color="{clrWhite}" text="{tr(originaltitle)}: {movieoriginalTitle} |{tr(genre)}: {moviegenres} ||{movietagline} |{movieoverview} |{tr(budget)}: {moviebudget}$ ||{tr(revenue)}: {movierevenue}$ ||{tr(adult)}: {movieadult} ||{tr(releasedate)}: {moviereleasedate} ||{tr(runtime)}: {movieruntime} min || {tr(popularity)}: {moviepopularity} || {tr(voteaverage)}: {movievoteaverage} || {tr(homepage)}: {moviehomepage}| " /> + </tab> + <tab condition="{ismovie}" name="{tr(moviegalery)}" x="2%" y="25%" width="94%" height="60%" layer="2" scrollheight="{areaheight}/4"> + <drawimage name="fanart" imagetype="image" path="{fanartpath}" align="center" y="10" width="{areawidth}*0.9" height="{areawidth} * 0.9 * {fanartheight} / {fanartwidth}"/> + <drawimage name="poster" imagetype="image" path="{posterpath}" align="center" y="{height(fanart)} + 30" width="{areawidth}*0.6" height="{areawidth} * 0.6 * {posterheight} / {posterwidth}"/> + <drawimage condition="{movieiscollection}" name="collectionfanart" imagetype="image" path="{collectionfanartpath}" align="center" y="{posy(poster)} + {height(poster)} + 20" width="{areawidth}*0.9" height="{areawidth} * 0.9 * {collectionfanartheight} / {collectionfanartwidth}"/> + <drawimage condition="{movieiscollection}" name="collectionposter" imagetype="image" path="{collectionposterpath}" align="center" y="{posy(collectionfanart)} + {height(collectionfanart)} + 20" width="{areawidth}*0.6" height="{areawidth} * 0.6 * {collectionposterheight} / {collectionposterwidth}"/> + </tab> + + <!-- Available Variables tablabels: + {tabs[]} array with available tab labels + {tabs[title]} title of tab + {tabs[current]} true if tab is displayed currently + --> + <tablabels> + <area x="1%" y="85%" width="98%" height="5%" layer="3"> + <loop name="tabs" x="0" y="0" orientation="horizontal"> + <drawrectangle condition="{tabs[current]}" x="0" y="0" width="{width(label)}" height="100%" color="{clrDarkGreen}" /> + <drawrectangle condition="not{tabs[current]}" x="0" y="0" width="{width(label)}" height="100%" color="{clrDarkGreen}" /> + <drawrectangle condition="not{tabs[current]}" x="2" y="2" width="{width(label)} - 4" height="{areaheight}-4" color="{clrTransparent}" /> + <drawtext name="label" x="0" valign="center" font="{vdrOsd}" fontsize="95%" color="{clrWhite}" text=" {tabs[title]} " /> + </loop> + </area> + </tablabels> + +</menudetailedrecording> 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 @@ +<menudetailedtext x="0" y="0" width="100%" height="100%" fadetime="0"> + <background> + <area x="0" y="0" width="100%" height="100%" layer="1"> + <fill color="{clrTransBlack}" /> + <drawrectangle x="0" y="0" width="100%" height="10%" color="{clrDarkBlue}" /> + </area> + <area x="0" y="0" width="100%" height="10%" layer="2"> + <drawimage imagetype="skinpart" path="headertop" x="0" y="0" width="100%" height="100%"/> + </area> + </background> + <scrollbar> + <area x="97%" y="11%" width="2%" height="79%" layer="2"> + <fill color="{clrDarkBlue}" /> + <drawrectangle x="2" y="2" width="{areawidth} - 4" height="{areaheight} - 4" color="{clrTransparent}" /> + <drawrectangle x="4" y="4 + {areaheight} * {offset} / 1000" width="{areawidth} - 8" height="{areaheight} * {height} / 1000 - 8" color="{clrDarkGreen}" /> + </area> + </scrollbar> + <!-- Available Variables in tab elements: + {text} detailed text + --> + <tab name="text" x="2%" y="11%" width="94%" height="79%" layer="2" scrollheight="{areaheight}/4"> + <drawtextbox x="0" y="0" width="100%" font="{light}" fontsize="5%" color="{clrWhite}" text="{text}" /> + </tab> + +</menudetailedtext>
\ 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 @@ +<menumain x="0" y="0" width="100%" height="100%" fadetime="0" scaletvx="33%" scaletvy="10%" scaletvwidth="65%" scaletvheight="80%" > + <!-- Available Variables header: + {title} title of current menu + {vdrversion} running VDR Version + {hasicon} true if a menu icon is available + {icon} path of menu icon + --> + <header> + <area x="1%" y="0" width="64%" height="10%" layer="3"> + <drawimage imagetype="icon" path="ico_vdrlogo" x="0" valign="center" width="{areaheight} * 0.9 * 160 / 70" height="{areaheight}*0.9"/> + <drawtext x="{areaheight} * 0.9 * 160 / 70 + 10" valign="center" font="{vdrOsd}" fontsize="50%" color="{clrWhite}" text="{vdrversion}" /> + </area> + </header> + + <!-- Available Variables timers: + {numtimers} number of active timers (max. 15 timers will be displayed) + {numtimerconflicts} number of current timer conflicts + {timer1exists} true if timer 1 available + {timer2exists} true if timer 2 available + ... + {timer15exists} true if timer 15 available + {timers[]} array with active timers (local and remote if remotetimers plugin is in use) + {timers[title]} title of timer + {timers[datetime]} date and time of timer + {timers[recording]} true if timer is recording currently + {timers[channelname]} name of channel for which timer is created + {timers[channelnumber]} number of channel + {timers[channelid]} ChannelID of channel + {timers[channellogoexists]} true if channel logo exists + --> + <timers> + <area x="85%" y="28%" width="14%" height="60%" layer="1"> + <drawrectangle condition="gt({numtimers}, 0)" x="0" y="0" width="{areawidth}" height="{areaheight} / 4 * 99 / 100" color="{clrTransBlack}" /> + <drawrectangle condition="gt({numtimers}, 1)" x="0" y="{areaheight} / 4" width="{areawidth}" height="{areaheight} / 4 * 99 / 100" color="{clrTransBlack}" /> + <drawrectangle condition="gt({numtimers}, 2)" x="0" y="{areaheight} / 2" width="{areawidth}" height="{areaheight} / 4 * 99 / 100" color="{clrTransBlack}" /> + <drawrectangle condition="gt({numtimers}, 3)" x="0" y="{areaheight} * 3 / 4" width="{areawidth}" height="{areaheight} / 4 * 99 / 100" color="{clrTransBlack}" /> + </area> + <area x="85%" y="28%" width="14%" height="60%" layer="2"> + <loop name="timers" x="0" y="0" orientation="vertical" columnwidth="100%" rowheight="{areaheight} / 4" overflow="cut"> + <drawrectangle condition="{timers[recording]}" x="0" y="0" width="{columnwidth}" height="{rowheight} * 99 / 100" color="{clrTransRed}" /> + <drawimage cache="true" name="logo" imagetype="channellogo" path="{timers[channelid]}" height="{rowheight} / 2" align="center" y="5" /> + <drawtextbox x="5" y="{height(logo)}+2" width="{columnwidth}-10" align="center" maxlines="2" font="{vdrOsd}" fontsize="4%" color="{clrWhite}" text="{timers[title]}" /> + <drawtext name="datetime" align="center" y="{rowheight}*84/100" font="{vdrOsd}" fontsize="4%" color="{clrWhite}" text="{timers[datetime]}" /> + </loop> + </area> + </timers> + + <scrollbar> + <area x="30%" y="11%" width="2%" height="78%" layer="2"> + <fill color="{clrDarkBlue}" /> + <drawrectangle x="2" y="2" width="{areawidth} - 4" height="{areaheight} - 4" color="{clrTransparent}" /> + <drawrectangle x="4" y="4 + {areaheight} * {offset} / 1000" width="{areawidth} - 8" height="{areaheight} * {height} / 1000 - 8" color="{clrDarkGreen}" /> + </area> + </scrollbar> + + <!-- Available Variables discusage: + {freetime} available disc capacity in hh:mm + {freepercent} available disc capacity in percent + {usedpercent} used disc capacity in percent + {freegb} available disc capacity in gigabytes + {discalert} true if disc usage is > 95% + {vdrusagestring} localized VDR internal usage string + --> + <discusage> + <area x="89%" y="11%" width="10%" height="16%" layer="1"> + <fill condition="lt({freepercent}, 6)" color="{clrTransRed}" /> + <fill condition="gt({freepercent}, 5)" color="{clrDarkBlue}" /> + <drawimage imagetype="skinpart" path="discpercent" x="0" y="82%" width="{areawidth}" height="18%"/> + </area> + <area x="89%" y="11%" width="10%" height="16%" layer="2"> + <drawimage imagetype="icon" path="ico_discusage" align="center" y="2" width="{areawidth}*65/100" height="{areawidth}*65/100"/> + <drawtext align="center" y="42%" font="{vdrOsd}" fontsize="18%" color="{clrWhite}" text="{freetime}h {tr(free)}" /> + <drawrectangle x="{areawidth}*{usedpercent}/100" y="82%" width="{areawidth} - {areawidth}*{usedpercent}/100" height="18%" color="{clrTransBlack}" /> + <drawtext align="center" y="82%" font="{vdrOsd}" fontsize="19%" color="{clrWhite}" text="{usedpercent}%" /> + </area> + </discusage> + + <!-- Available Variables devices: + {numdevices} number of available devices + {devices[]} array with available devices + {devices[num]} number of current device + {devices[type]} type of device (DVB-S, DVB-C, ...) + {devices[istuned]} true if device is currently tuned to a transponder + {devices[livetv]} true if device is currently playing livetv + {devices[recording]} true if device is currently recording + {devices[hascam]} true if device has a CAM + {devices[cam]} number of CAM + {devices[signalstrength]} signalstrength of devcie + {devices[signalquality]} signalstrength of devcie + {devices[channelnumber]} number of the currently tuned channel + {devices[channelname]} name of the currently tuned channel + {devices[channelid]} ID of the currently tuned channel + {devices[source]} source of the currently tuned channel + --> + <devices> + </devices> + + <!-- Available Variables systemload: + {load} current system load + --> + <systemload> + </systemload> + + <menuitems x="{areawidth}*0.005" y="10%" orientation="vertical" width="28%" height="80%" align="center" numlistelements="10"> + <!-- Available Variables main menu listelement: + {label} label of menu item + {number} number of menu item (or empty string if not set) + {icon} path of appropriate icon + {current} true if item is currently selected + {separator} true if item is a list separator + --> + <listelement> + <area x="0" width="100%" layer="2"> + <drawimage condition="not{current}" imagetype="skinpart" path="menubutton" x="0" y="1%" width="{areawidth}" height="{areaheight}*0.98"/> + <drawimage condition="{current}" imagetype="skinpart" path="menubuttonactive" x="0" y="1%" width="{areawidth}" height="{areaheight}*0.98"/> + </area> + <area x="0" width="100%" layer="7"> + <drawimage imagetype="skinpart" path="menubuttontop" x="0" y="1%" width="{areawidth}" height="{areaheight}*0.98"/> + </area> + <area x="0" width="100%" layer="3"> + <drawimage imagetype="menuicon" path="{icon}" x="10" valign="center" width="{areaheight}*0.8" height="{areaheight}*0.8"/> + </area> + <areascroll scrollelement="menutext" mode="forthandback" orientation="horizontal" delay="1000" scrollspeed="medium" x="23%" width="77%" layer="3"> + <drawtext condition="not{current}" name="menutext" x="0" valign="center" font="{vdrOsd}" fontsize="50%" color="{clrFontMenuItem}" text="{number} {label}" /> + <drawtext condition="{current}" name="menutext" x="0" valign="center" font="{vdrOsd}" fontsize="50%" color="{clrFontMenuItemSelected}" text="{number} {label}" /> + </areascroll> + </listelement> + <!-- additional element which is drawn for current element --> + <!-- Available Variables main menu currentelement: + {label} label of menu item + {number} number of menu item (or empty string if not set) + {icon} path of appropriate icon + --> + <currentelement delay="50" fadetime="0"> + </currentelement> + </menuitems> + +</menumain> 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 @@ +<menurecordings x="0" y="0" width="100%" height="100%" fadetime="0" scaletvx="33%" scaletvy="10%" scaletvwidth="65%" scaletvheight="80%"> + <scrollbar> + <area x="30%" y="11%" width="2%" height="78%" layer="2"> + <fill color="{clrDarkBlue}" /> + <drawrectangle x="2" y="2" width="{areawidth} - 4" height="{areaheight} - 4" color="{clrTransparent}" /> + <drawrectangle x="4" y="4 + {areaheight} * {offset} / 1000" width="{areawidth} - 8" height="{areaheight} * {height} / 1000 - 8" color="{clrDarkGreen}" /> + </area> + </scrollbar> + + <menuitems x="{areawidth}*0.005" y="10%" orientation="vertical" width="99%" height="80%" align="center" numlistelements="10"> + <!-- Available Variables recordings menu listelement: + {name} Name of recording + {date} Date of recording + {time} Time of recording + {duration} real duration of recording in minutes + {durationevent} duration of corresponding event in minutes + {current} true if item is currently selected + {new} true if recording is new + {cutted} true if recording is cutted + {folder} true if item is a folder + {numrecordingsfolder} if item is a folder, number of recordings in this folder + {newrecordingsfolder} if item is a folder, number of new recordings in this folder + {hasposterthumbnail} true if a scraped poster thumbnail is available for recording + {thumbnailbwidth} width of scraped poster thumbnail + {thumbnailheight} height of scraped poster thumbnail + {thumbnailpath} absolute path of scraped poster thumbnail + --> + <listelement> + <!-- background and foreground--> + <area x="0" width="28%" layer="2"> + <drawimage condition="not{current}" imagetype="skinpart" path="menubutton" x="0" y="1%" width="{areawidth}" height="{areaheight}*0.98"/> + <drawimage condition="{current}" imagetype="skinpart" path="menubuttonactive" x="0" y="1%" width="{areawidth}" height="{areaheight}*0.98"/> + </area> + <!-- Folders --> + <area condition="{folder}" x="1%" width="27%" layer="3"> + <drawimage name="foldericon" imagetype="icon" path="ico_recfolder" x="0" width="0.9*{areaheight} * 92 / 136" height="0.9*{areaheight}" valign="center" /> + </area> + <areascroll condition="{folder}" scrollelement="foldername" mode="forthandback" orientation="horizontal" delay="1000" scrollspeed="medium" x="5%" width="23%" layer="3"> + <drawtext condition="not{current}" name="foldername" x="0" valign="center" font="{vdrOsd}" fontsize="50%" color="{clrFontMenuItem}" text="{name} ({numrecordingsfolder}, {newrecordingsfolder} new)" /> + <drawtext condition="{current}" name="foldername" x="0" valign="center" font="{vdrOsd}" fontsize="50%" color="{clrFontMenuItemSelected}" text="{name} ({numrecordingsfolder}, {newrecordingsfolder} new)" /> + </areascroll> + <!-- Recording --> + <area condition="{hasposterthumbnail}++not{folder}" x="1%" width="4%" layer="3"> + <drawimage imagetype="image" path="{thumbnailpath}" x="0" width="0.9*{areaheight} * {thumbnailbwidth} / {thumbnailheight}" height="0.9*{areaheight}" valign="center" /> + </area> + <areascroll condition="not{folder}" scrollelement="recname" mode="forthandback" orientation="horizontal" delay="1000" scrollspeed="medium" x="5%" width="23%" layer="3"> + <drawtext condition="not{current}" name="recname" x="0" y="5" font="{vdrOsd}" fontsize="50%" color="{clrFontMenuItem}" text="{name}" /> + <drawtext condition="{current}" name="recname" x="0" y="5" font="{vdrOsd}" fontsize="50%" color="{clrFontMenuItemSelected}" text="{name}" /> + </areascroll> + <area condition="not{folder}" x="5%" width="23%" layer="3"> + <drawtext condition="not{current}" x="0" y="55%" font="{vdrOsd}" fontsize="40%" color="{clrFontMenuItem}" text="{date} {time}" /> + <drawtext condition="{current}" x="0" y="55%" font="{vdrOsd}" fontsize="40%" color="{clrFontMenuItemSelected}" text="{date} {time}" /> + <drawimage condition="{new}" name="new" imagetype="icon" path="ico_recnew" x="{areawidth} - {areaheight}/2 - 5" y="50%" width="{areaheight}*4/10" height="{areaheight}*4/10" /> + <drawimage condition="{new}++{cutted}" imagetype="icon" path="ico_cutted" x="{areawidth} - {areaheight} - 10" y="50%" width="{areaheight}*4/10" height="{areaheight}*4/10" /> + <drawimage condition="not{new}++{cutted}" imagetype="icon" path="ico_cutted" x="{areawidth} - {areaheight}/2 - 5" y="50%" width="{areaheight}*4/10" height="{areaheight}*4/10" /> + </area> + </listelement> + <!-- additional element which is drawn for current element --> + <!-- Available Variables channels menu currentelement: + {name} Name of recording + {shorttext} Short Text of recording + {description} Descrption of recording + {date} Date of recording + {time} Time of recording + {duration} real duration of recording in minutes + {durationevent} duration of corresponding event in minutes + {new} true if recording is new + {cutted} true if recording is cutted + {folder} true if item is a folder + {numrecordingsfolder} if item is a folder, number of recordings in this folder + {newrecordingsfolder} if item is a folder, number of new recordings in this folder + {hasposter} true if a scraped poster is available for recording + {posterwidth} width of scraped poster + {posterheight} height of scraped poster + {posterpath} absolute path of scraped poster + --> + <currentelement delay="500" fadetime="300"> + <area x="32%" y="2%" width="67%" height="96%" layer="2"> + <fill color="{clrTransBlack}" /> + <!-- header --> + <drawtext name="title" x="1%" y="0" width="98%" font="{vdrOsd}" fontsize="8%" color="{clrWhite}" text="{name}" /> + <drawtext name="shorttext" x="1%" y="{height(title)}" width="98%" font="{vdrOsd}" fontsize="6%" color="{clrWhite}" text="{shorttext}" /> + <drawtext name="datetime" x="1%" y="{posy(shorttext)} + {height(shorttext)}" font="{vdrOsd}" fontsize="5%" color="{clrWhite}" text="{date} {time}, {duration} min" /> + <!-- scraper poster --> + <drawimage condition="{hasposter}" name="poster" imagetype="image" path="{posterpath}" x="3*{areawidth}/4" y="{posy(datetime)} + {height(datetime)} + 20" width="{areawidth}/4" height="{areawidth}/4 * {posterheight} / {posterwidth}"/> + <!-- description --> + <drawtextbox condition="{hasposter}" x="1%" y="{posy(poster)}" width="98%" height="{areaheight} - {posy(poster)}" float="topright" floatwidth="{width(poster)} + 10" floatheight="{height(poster)} + 10" font="{vdrOsd}" fontsize="5%" color="{clrWhite}" text="{description}" /> + <drawtextbox condition="not{hasposter}" x="1%" y="{posy(poster)}" width="98%" height="{areaheight} - {posy(poster)}" font="{vdrOsd}" fontsize="5%" color="{clrWhite}" text="{description}" /> + </area> + </currentelement> + </menuitems> + +</menurecordings>
\ 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 @@ +<menuschedules x="0" y="0" width="100%" height="100%" fadetime="0" scaletvx="33%" scaletvy="10%" scaletvwidth="65%" scaletvheight="80%" > + <!-- Available Variables header: + {title} title of current menu + {vdrversion} running VDR Version + {channelnumber} Number of Channel of current event + {channelname} Name of current Channel of current event + {channellogoexists} true if a channel logo exists + {channelid} ChannelID as path to display channel logo + {whatson} true if menu "What's on" is displayed + {whatsonnow} true if menu "What's on now" is displayed + {whatsonnext} true if menu "What's on next" is displayed + --> + <header> + <area x="1%" y="0" width="64%" height="10%" layer="2"> + <drawtext condition="{whatsonnow}||{whatsonnext}" x="5" valign="center" font="{vdrOsd}" fontsize="80%" color="{clrWhite}" text="{title}" /> + <drawimage name="logo" condition="{whatson}" imagetype="channellogo" path="{channelid}" x="0" height="100%" align="left" valign="center" /> + <drawtext condition="{whatson}" x="{width(logo)}+20" valign="center" font="{vdrOsd}" fontsize="50%" color="{clrWhite}" text="{channelnumber} - {channelname}" /> + </area> + </header> + + + <scrollbar> + <area x="30%" y="11%" width="2%" height="78%" layer="2"> + <fill color="{clrDarkBlue}" /> + <drawrectangle x="2" y="2" width="{areawidth} - 4" height="{areaheight} - 4" color="{clrTransparent}" /> + <drawrectangle x="4" y="4 + {areaheight} * {offset} / 1000" width="{areawidth} - 8" height="{areaheight} * {height} / 1000 - 8" color="{clrDarkGreen}" /> + </area> + </scrollbar> + + <menuitems x="{areawidth}*0.005" y="10%" orientation="vertical" width="99%" height="80%" align="center" numlistelements="10"> + <!-- Available Variables schedules menu listelement: + {title} title of event + {shorttext} shorttext of event + {start} event start time in hh::mm + {stop} event stop time + {day} day of current event + {date} date of current event in dd.mm.yy + {running} true if event is currently running + {elapsed} elapsed time of event, if not running 0 + {duration} duration of event + {current} true if item is currently selected + {separator} true if item is a list separator + {channelid} ChannelID as path to display channel logo + {whatson} true if menu "What's on" is displayed + {whatsonnow} true if menu "What's on now" is displayed + {whatsonnext} true if menu "What's on next" is displayed + {timerpartitial} true if partitial timer is set for the event + {timerfull} true if full timer is set for the event + --> + <listelement> + <!-- background and foreground--> + <area x="0" width="28%" layer="2"> + <drawimage condition="not{current}" imagetype="skinpart" path="menubutton" x="0" y="1%" width="{areawidth}" height="{areaheight}*0.98"/> + <drawimage condition="{current}" imagetype="skinpart" path="menubuttonactive" x="0" y="1%" width="{areawidth}" height="{areaheight}*0.98"/> + </area> + <area x="0" width="28%" layer="7"> + <drawimage imagetype="skinpart" path="menubuttontop" x="0" y="1%" width="{areawidth}" height="{areaheight}*0.98"/> + </area> + <!-- element whatson --> + <area condition="not{separator}++{whatson}++not{current}" x="1%" width="27%" layer="3"> + <drawtext x="0" y="5%" font="{vdrOsd}" fontsize="40%" color="{clrFontMenuItem}" text="{start} - {stop}" /> + <drawimage condition="{timerfull}" imagetype="icon" path="ico_activetimer" x="{areawidth} - {areaheight}*5/10 - 10" y="10" width="{areaheight}*5/10" height="{areaheight}*5/10" /> + <drawimage condition="{timerpartitial}" imagetype="icon" path="ico_activetimer" x="{areawidth} - {areaheight}*3/10 - 10" y="10" width="{areaheight}*3/10" height="{areaheight}*3/10" /> + </area> + <areascroll scrollelement="menutext" mode="forthandback" orientation="horizontal" delay="1000" scrollspeed="medium" condition="not{separator}++{whatson}++not{current}" x="1%" width="27%" layer="3"> + <drawtext name="menutext" x="0" y="40%" font="{vdrOsd}" fontsize="55%" color="{clrFontMenuItem}" text="{title}" /> + </areascroll> + <!-- current element whatson --> + <area condition="not{separator}++{whatson}++{current}" x="1%" width="27%" layer="3"> + <drawtext x="0" y="5%" font="{vdrOsd}" fontsize="40%" color="{clrFontMenuItemSelected}" text="{start} - {stop}" /> + <drawimage condition="{timerfull}" imagetype="icon" path="ico_activetimer" x="{areawidth} - {areaheight}*5/10 - 10" y="10" width="{areaheight}*5/10" height="{areaheight}*5/10" /> + <drawimage condition="{timerpartitial}" imagetype="icon" path="ico_activetimer" x="{areawidth} - {areaheight}*3/10 - 10" y="10" width="{areaheight}*3/10" height="{areaheight}*3/10" /> + </area> + <areascroll scrollelement="menutext" mode="forthandback" orientation="horizontal" delay="1000" scrollspeed="medium" condition="not{separator}++{whatson}++{current}" x="1%" width="27%" layer="3"> + <drawtext name="menutext" x="0" y="40%" font="{vdrOsd}" fontsize="55%" color="{clrFontMenuItemSelected}" text="{title}" /> + </areascroll> + <!-- element whatsonnow --> + <area condition="not{separator}++{whatsonnow}" x="5" width="8%" layer="3"> + <drawimage name="logo" imagetype="channellogo" path="{channelid}" x="0" height="100%" valign="center" /> + </area> + <area condition="not{separator}++{whatsonnow}++not{current}" x="9%" width="18%" layer="3"> + <drawtext x="0" y="5%" font="{vdrOsd}" fontsize="40%" color="{clrFontMenuItem}" text="{start} - {stop}" /> + <drawimage condition="{timerfull}" imagetype="icon" path="ico_activetimer" x="{areawidth} - {areaheight}*5/10 - 10" y="10" width="{areaheight}*5/10" height="{areaheight}*5/10" /> + <drawimage condition="{timerpartitial}" imagetype="icon" path="ico_activetimer" x="{areawidth} - {areaheight}*3/10 - 10" y="10" width="{areaheight}*3/10" height="{areaheight}*3/10" /> + </area> + <areascroll scrollelement="menutext" mode="forthandback" orientation="horizontal" delay="1000" scrollspeed="medium" condition="not{separator}++{whatsonnow}++not{current}" x="9%" width="18%" layer="3"> + <drawtext name="menutext" x="0" y="40%" font="{vdrOsd}" fontsize="55%" color="{clrFontMenuItem}" text="{title}" /> + </areascroll> + <!-- current element whatsonnow --> + <area condition="not{separator}++{whatsonnow}++{current}" x="9%" width="18%" layer="3"> + <drawtext x="0" y="5%" font="{vdrOsd}" fontsize="40%" color="{clrFontMenuItemSelected}" text="{start} - {stop}" /> + <drawimage condition="{timerfull}" imagetype="icon" path="ico_activetimer" x="{areawidth} - {areaheight}*5/10 - 10" y="10" width="{areaheight}*5/10" height="{areaheight}*5/10" /> + <drawimage condition="{timerpartitial}" imagetype="icon" path="ico_activetimer" x="{areawidth} - {areaheight}*3/10 - 10" y="10" width="{areaheight}*3/10" height="{areaheight}*3/10" /> + </area> + <areascroll scrollelement="menutext" mode="forthandback" orientation="horizontal" delay="1000" scrollspeed="medium" condition="not{separator}++{whatsonnow}++{current}" x="9%" width="18%" layer="3"> + <drawtext name="menutext" x="0" y="40%" font="{vdrOsd}" fontsize="55%" color="{clrFontMenuItemSelected}" text="{title}" /> + </areascroll> + <!-- day or channel separator --> + <area condition="{separator}" x="0" width="28%" layer="3"> + <drawimage name="sep" imagetype="icon" path="ico_daydelimiter" x="10" valign="center" width="{areaheight}-10" height="{areaheight}-10"/> + <drawtext x="{width(sep)} + 20" valign="center" font="{vdrOsd}" fontsize="60%" color="{clrFontInactive}" text="{title}" /> + </area> + <!-- element whatsonnext --> + <area condition="not{separator}++{whatsonnext}" x="5" width="8%" layer="3"> + <drawimage name="logo" imagetype="channellogo" path="{channelid}" x="0" height="100%" valign="center" /> + </area> + <area condition="not{separator}++{whatsonnext}++not{current}" x="9%" width="18%" layer="3"> + <drawtext x="0" y="5%" font="{vdrOsd}" fontsize="40%" color="{clrFontMenuItem}" text="{start} - {stop}" /> + <drawimage condition="{timerfull}" imagetype="icon" path="ico_activetimer" x="{areawidth} - {areaheight}*5/10 - 10" y="10" width="{areaheight}*5/10" height="{areaheight}*5/10" /> + <drawimage condition="{timerpartitial}" imagetype="icon" path="ico_activetimer" x="{areawidth} - {areaheight}*3/10 - 10" y="10" width="{areaheight}*3/10" height="{areaheight}*3/10" /> + </area> + <areascroll scrollelement="menutext" mode="forthandback" orientation="horizontal" delay="1000" scrollspeed="medium" condition="not{separator}++{whatsonnext}++not{current}" x="9%" width="18%" layer="3"> + <drawtext name="menutext" x="0" y="40%" font="{vdrOsd}" fontsize="55%" color="{clrFontMenuItem}" text="{title}" /> + </areascroll> + <!-- current element whatsonnext --> + <area condition="not{separator}++{whatsonnext}++{current}" x="9%" width="18%" layer="3"> + <drawtext x="0" y="5%" font="{vdrOsd}" fontsize="40%" color="{clrFontMenuItemSelected}" text="{start} - {stop}" /> + <drawimage condition="{timerfull}" imagetype="icon" path="ico_activetimer" x="{areawidth} - {areaheight}*5/10 - 10" y="10" width="{areaheight}*5/10" height="{areaheight}*5/10" /> + <drawimage condition="{timerpartitial}" imagetype="icon" path="ico_activetimer" x="{areawidth} - {areaheight}*3/10 - 10" y="10" width="{areaheight}*3/10" height="{areaheight}*3/10" /> + </area> + <areascroll scrollelement="menutext" mode="forthandback" orientation="horizontal" delay="1000" scrollspeed="medium" condition="not{separator}++{whatsonnext}++{current}" x="9%" width="18%" layer="3"> + <drawtext name="menutext" x="0" y="40%" font="{vdrOsd}" fontsize="55%" color="{clrFontMenuItemSelected}" text="{title}" /> + </areascroll> + <!-- day or channel separator --> + <area condition="{separator}" x="0" width="28%" layer="3"> + <drawimage name="sep" imagetype="icon" path="ico_daydelimiter" x="10" valign="center" width="{areaheight}-10" height="{areaheight}-10"/> + <drawtext x="{width(sep)} + 20" valign="center" font="{vdrOsd}" fontsize="60%" color="{clrFontInactive}" text="{title}" /> + </area> + </listelement> + <!-- Available Variables schedules menu currentelement: + {title} title of event + {shorttext} shorttext of event + {description} detailed description of event + {start} event start time in hh::mm + {stop} event stop time + {day} day of current event + {date} date of current event in dd.mm.yy + {running} true if event is currently running + {elapsed} elapsed time of event, if not running 0 + {duration} duration of event + {channelid} ChannelID as path to display channel logo + {hasposter} true if a scraped poster is available for this element + {posterwidth} width of scraped poster + {posterheight} height of scraped poster + {posterpath} absolute path of scraped poster + {timerpartitial} true if partitial timer is set for the event + {timerfull} true if full timer is set for the event + {whatson} true if menu "What's on" is displayed + {whatsonnow} true if menu "What's on now" is displayed + {whatsonnext} true if menu "What's on next" is displayed + {schedule[]} array with next 10 schedules, only for whatsonnow and whatsonnext + {schedule[title]} title of event + {schedule[shorttext]} shorttext of event + {schedule[start]} start time of event in hh:mm + {schedule[stop]} stop time of event in hh:mm + --> + <currentelement delay="500" fadetime="300"> + <area x="32%" y="2%" width="67%" height="96%" layer="2"> + <fill color="{clrTransBlack}" /> + </area> + <area condition="{whatson}" x="32%" y="2%" width="67%" height="96%" layer="2"> + <!-- title --> + <drawtext name="title" align="center" y="0" font="{vdrOsd}" width="{areawidth}-20" fontsize="8%" color="{clrWhite}" text="{title}" /> + <!-- progress bar if event is running --> + <drawtext condition="{running}" name="start" x="{areawidth}/4 - {width(start)}" y="9%" font="vdrOsd}" fontsize="6%" color="{clrWhite}" text="{start}" /> + <drawtext condition="{running}" name="stop" x="{areawidth}*3/4" y="9%" font="{vdrOsd}" fontsize="6%" color="{clrWhite}" text="{stop}" /> + <drawellipse condition="{running}" x="{areawidth} / 4 + 5" y="{posy(start)} + {height(start)} / 2 - 6" width="11" height="11" quadrant="0" color="{clrDarkBlue}" /> + <drawrectangle condition="{running}" x="{areawidth} / 4 + 10" y="{posy(start)} + {height(start)} / 2 - 6" width="{areawidth}/2 - 20" height="11" color="{clrDarkBlue}" /> + <drawellipse condition="{running}" x="3 * {areawidth} / 4 - 16" y="{posy(start)} + {height(start)} / 2 - 6" width="11" height="11" quadrant="0" color="{clrDarkBlue}" /> + <drawellipse condition="{running}" x="{areawidth} / 4 + 6" y="{posy(start)} + {height(start)} / 2 - 5" width="9" height="9" quadrant="0" color="{clrBrightGreen}" /> + <drawrectangle condition="{running}" x="{areawidth} / 4 + 10" y="{posy(start)} + {height(start)} / 2 - 5" width="{areawidth}/2 * {elapsed} / {duration} - 20 * {elapsed} / {duration}" height="9" color="{clrBrightGreen}" /> + <drawellipse condition="{running}" x="{areawidth} / 4 + 10 + {areawidth}/2 * {elapsed} / {duration} - 20 * {elapsed} / {duration} - 4" y="{posy(start)} + {height(start)} / 2 - 5" width="9" height="9" quadrant="0" color="{clrBrightGreen}" /> + <!-- start and stop if event is not running --> + <drawtext condition="not{running}" x="10" y="9%" font="{vdrOsd}" fontsize="{areaheight}/20" color="{clrWhite}" text="{start} - {stop} ({duration} min)" /> + <!-- scraper poster --> + <drawimage condition="{hasposter}" name="poster" imagetype="image" path="{posterpath}" x="{areawidth} - {areawidth}/3" y="{posy(start)} + {height(start)} + 10" width="{areawidth}/3" height="{areawidth}/3 * {posterheight} / {posterwidth}"/> + <!-- description --> + <drawtextbox condition="{hasposter}" x="10" y="{posy(poster)}" width="99%" height="{areaheight} - {posy(poster)}" float="topright" floatwidth="{width(poster)} + 10" floatheight="{height(poster)} + 20" font="{vdrOsd}" fontsize="{areaheight}/20" color="{clrWhite}" text="{description}" /> + <drawtextbox condition="not{hasposter}" x="10" y="{posy(poster)}" width="99%" height="{areaheight} - {posy(poster)}" font="{vdrOsd}" fontsize="{areaheight}/20" color="{clrWhite}" text="{description}" /> + </area> + <!-- whatsonnow and whotsonnext --> + <area condition="{whatsonnow}||{whatsonnext}" x="32%" y="2%" width="67%" height="76%" layer="2"> + <!-- title --> + <drawtext align="center" y="0" font="{vdrOsd}" width="{areawidth}-20" fontsize="10%" color="{clrWhite}" text="{title}" /> + <!-- progress bar if event is running --> + <drawtext condition="{running}" name="start" x="{areawidth}/4 - {width(start)}" y="11%" font="vdrOsd}" fontsize="8%" color="{clrWhite}" text="{start}" /> + <drawtext condition="{running}" name="stop" x="{areawidth}*3/4" y="11%" font="{vdrOsd}" fontsize="8%" color="{clrWhite}" text="{stop}" /> + <drawellipse condition="{running}" x="{areawidth} / 4 + 5" y="{posy(start)} + {height(start)} / 2 - 6" width="11" height="11" quadrant="0" color="{clrDarkBlue}" /> + <drawrectangle condition="{running}" x="{areawidth} / 4 + 10" y="{posy(start)} + {height(start)} / 2 - 6" width="{areawidth}/2 - 20" height="11" color="{clrDarkBlue}" /> + <drawellipse condition="{running}" x="3 * {areawidth} / 4 - 16" y="{posy(start)} + {height(start)} / 2 - 6" width="11" height="11" quadrant="0" color="{clrDarkBlue}" /> + <drawellipse condition="{running}" x="{areawidth} / 4 + 6" y="{posy(start)} + {height(start)} / 2 - 5" width="9" height="9" quadrant="0" color="{clrBrightGreen}" /> + <drawrectangle condition="{running}" x="{areawidth} / 4 + 10" y="{posy(start)} + {height(start)} / 2 - 5" width="{areawidth}/2 * {elapsed} / {duration} - 20 * {elapsed} / {duration}" height="9" color="{clrBrightGreen}" /> + <drawellipse condition="{running}" x="{areawidth} / 4 + 10 + {areawidth}/2 * {elapsed} / {duration} - 20 * {elapsed} / {duration} - 4" y="{posy(start)} + {height(start)} / 2 - 5" width="9" height="9" quadrant="0" color="{clrBrightGreen}" /> + <!-- start and stop if event is not running --> + <drawtext condition="not{running}" x="10" y="9%" font="{vdrOsd}" fontsize="{areaheight}/20" color="{clrWhite}" text="{start} - {stop} ({duration} min)" /> + <!-- scraper poster --> + <drawimage condition="{hasposter}" name="poster" imagetype="image" path="{posterpath}" x="{areawidth}* 2 / 3" y="{posy(start)} + {height(start)} + 10" width="{areawidth}/3" height="{areawidth}/3 * {posterheight} / {posterwidth}"/> + <!-- description --> + <drawtextbox condition="{hasposter}" x="10" y="{posy(poster)}" width="99%" height="{areaheight} - {posy(poster)}" float="topright" floatwidth="{width(poster)} + 10" floatheight="{height(poster)} + 10" font="{vdrOsd}" fontsize="{areaheight}/18" color="{clrWhite}" text="{description}" /> + <drawtextbox condition="not{hasposter}" x="10" y="{posy(poster)}" width="99%" height="{areaheight} - {posy(poster)}" font="{vdrOsd}" fontsize="{areaheight}/18" color="{clrWhite}" text="{description}" /> + </area> + <areascroll condition="{whatsonnow}||{whatsonnext}" mode="forthandback" orientation="vertical" delay="1000" scrollspeed="medium" x="32%" y="78%" width="67%" height="20%" layer="2"> + <drawtext x="10" y="0" font="{semibold}" fontsize="20%" color="{clrWhite}" text="{tr(nextschedules)}:" /> + <loop name="schedule" x="0" y="{areaheight}/4 + 5" orientation="vertical"> + <drawtext x="10" font="{vdrOsd}" width="{areawidth}-20" fontsize="20%" color="{clrWhite}" text="{schedule[start]} {schedule[title]}" /> + </loop> + </areascroll> + </currentelement> + </menuitems> + +</menuschedules>
\ 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 @@ +<menusetup x="0" y="0" width="100%" height="100%" fadetime="0" scaletvx="33%" scaletvy="10%" scaletvwidth="65%" scaletvheight="80%" > + + <scrollbar> + <area x="30%" y="11%" width="2%" height="78%" layer="2"> + <fill color="{clrDarkBlue}" /> + <drawrectangle x="2" y="2" width="{areawidth} - 4" height="{areaheight} - 4" color="{clrTransparent}" /> + <drawrectangle x="4" y="4 + {areaheight} * {offset} / 1000" width="{areawidth} - 8" height="{areaheight} * {height} / 1000 - 8" color="{clrDarkGreen}" /> + </area> + </scrollbar> + + <menuitems x="{areawidth}*0.005" y="10%" orientation="vertical" width="28%" height="80%" align="center" numlistelements="10"> + <!-- Available Variables setup menu listelement: + {label} label of menu item + {number} number of menu item (or empty string if not set) + {icon} path of appropriate icon + {current} true if item is currently selected + {separator} true if item is a list separator + --> + <listelement> + <area x="0" width="100%" layer="2"> + <drawimage condition="not{current}" imagetype="skinpart" path="menubutton" x="0" y="1%" width="{areawidth}" height="{areaheight}*0.98"/> + <drawimage condition="{current}" imagetype="skinpart" path="menubuttonactive" x="0" y="1%" width="{areawidth}" height="{areaheight}*0.98"/> + </area> + <area x="0" width="100%" layer="7"> + <drawimage imagetype="skinpart" path="menubuttontop" x="0" y="1%" width="{areawidth}" height="{areaheight}*0.98"/> + </area> + <area x="0" width="100%" layer="3"> + <drawimage imagetype="menuicon" path="{icon}" x="10" valign="center" width="{areaheight}*0.9" height="{areaheight}*0.9"/> + </area> + <areascroll scrollelement="menutext" mode="forthandback" orientation="horizontal" delay="1000" scrollspeed="medium" x="25%" width="75%" layer="3"> + <drawtext condition="not{current}" name="menutext" x="0" valign="center" font="{vdrOsd}" fontsize="50%" color="{clrFontMenuItem}" text="{number} {label}" /> + <drawtext condition="{current}" name="menutext" x="0" valign="center" font="{vdrOsd}" fontsize="50%" color="{clrFontMenuItemSelected}" text="{number} {label}" /> + </areascroll> + </listelement> + <!-- additional element which is drawn for current element --> + <!-- Available Variables main menu currentelement: + {label} label of menu item + {number} number of menu item (or empty string if not set) + {icon} path of appropriate icon + --> + <currentelement delay="50" fadetime="0"> + </currentelement> + </menuitems> + +</menusetup> 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 @@ +<menutimers x="0" y="0" width="100%" height="100%" fadetime="0" scaletvx="33%" scaletvy="10%" scaletvwidth="65%" scaletvheight="80%"> + <scrollbar> + <area x="30%" y="11%" width="2%" height="78%" layer="2"> + <fill color="{clrDarkBlue}" /> + <drawrectangle x="2" y="2" width="{areawidth} - 4" height="{areaheight} - 4" color="{clrTransparent}" /> + <drawrectangle x="4" y="4 + {areaheight} * {offset} / 1000" width="{areawidth} - 8" height="{areaheight} * {height} / 1000 - 8" color="{clrDarkGreen}" /> + </area> + </scrollbar> + + <menuitems x="{areawidth}*0.005" y="10%" orientation="vertical" width="99%" height="80%" align="center" numlistelements="10"> + <!-- Available Variables channels menu listelement: + {title} Title of Timer + {timerstart} Start Time of Timer in hh::mm + {timerstop} End Time of Timer in hh::mm + {day} Day (numerical) + {dayname} Day, for repeating timers days where timer is active + {channelname} Name of channel which is set for the timer + {channelid} ID of channel which is set for the timer (for dispalying channel logo) + {channelnumber} Number of channel which is set for the timer + {eventtitle} Title of corresponding event + {eventstart} Start Time of corresponding event in hh::mm + {eventstop} Stop Time of corresponding event in hh::mm + {current} true if item is currently selected + {flagactive} true if timer is active + {flaginstant} true if timer is an instant timer + {flagvps} true if timer uses VPS + {flagrecording} true if is recording currently + {flagpending} true if timer is pending + --> + <listelement> + <!-- background and foreground--> + <area x="0" width="28%" layer="2"> + <drawimage condition="not{current}" imagetype="skinpart" path="menubutton" x="0" y="1%" width="{areawidth}" height="{areaheight}*0.98"/> + <drawimage condition="{current}" imagetype="skinpart" path="menubuttonactive" x="0" y="1%" width="{areawidth}" height="{areaheight}*0.98"/> + </area> + <!-- channel logo --> + <area x="5" width="6%" layer="3"> + <drawimage imagetype="channellogo" path="{channelid}" x="0" height="100%" valign="center" /> + </area> + <!-- datetime and icons --> + <area x="1%" width="28%" layer="3"> + <drawtext condition="not{current}" x="22%" y="5" font="{vdrOsd}" fontsize="40%" color="{clrFontMenuItem}" text="{dayname} {day}. {timerstart} - {timerstop}" /> + <drawtext condition="{current}" x="22%" y="5" font="{vdrOsd}" fontsize="40%" color="{clrFontMenuItemSelected}" text="{dayname} {day}. {timerstart} - {timerstop}" /> + <drawimage condition="{flagactive}" imagetype="icon" path="ico_timer_active" x="{areawidth} - 0.5*{areaheight} - 20" y="0" width="0.5*{areaheight}" height="0.5*{areaheight}" /> + <drawimage condition="not{flagactive}" imagetype="icon" path="ico_timer_inactive" x="{areawidth} - 0.5*{areaheight} - 20" y="0" width="0.5*{areaheight}" height="0.5*{areaheight}" /> + <drawimage condition="{flagrecording}" name="active" imagetype="icon" path="ico_timer_recording" x="{areawidth} - {areaheight} - 20" y="0" width="0.5*{areaheight}" height="0.5*{areaheight}" /> + </area> + <!-- Timer Name --> + <areascroll scrollelement="timername" mode="forthandback" orientation="horizontal" delay="1000" scrollspeed="medium" x="7%" width="20%" layer="3"> + <drawtext condition="not{current}" name="timername" x="0" y="50%" font="{vdrOsd}" fontsize="50%" color="{clrFontMenuItem}" text="{title}" /> + <drawtext condition="{current}" name="timername" x="0" y="50%" font="{vdrOsd}" fontsize="50%" color="{clrFontMenuItemSelected}" text="{title}" /> + </areascroll> + </listelement> + <!-- additional element which is drawn for current element --> + <!-- Available Variables channels menu currentelement: + {title} Title of Timer + {timerstart} Start Time of Timer in hh::mm + {timerstop} End Time of Timer in hh::mm + {day} Day (numerical) + {dayname} Day, for repeating timers days where timer is active + {channelname} Name of channel which is set for the timer + {channelid} ID of channel which is set for the timer (for dispalying channel logo) + {channelnumber} Number of channel which is set for the timer + {eventtitle} Title of corresponding event + {eventstart} Start Time of corresponding event in hh::mm + {eventstop} Stop Time of corresponding event in hh::mm + {eventshorttext} Short Text corresponding event + {eventdescription} Description corresponding event + {hasposter} true if a scraped poster is available for event + {posterwidth} width of scraped poster + {posterheight} height of scraped poster + {posterpath} absolute path of scraped poster + {flagactive} true if timer is active + {flaginstant} true if timer is an instant timer + {flagvps} true if timer uses VPS + {flagrecording} true if is recording currently + {flagpending} true if timer is pending + --> + <currentelement delay="500" fadetime="300"> + <area x="32%" y="2%" width="67%" height="96%" layer="2"> + <fill color="{clrTransBlack}" /> + </area> + <area x="32%" y="2%" width="67%" height="96%" layer="2"> + <!-- title --> + <drawtext name="title" align="center" y="0" font="{vdrOsd}" width="{areawidth}-20" fontsize="8%" color="{clrWhite}" text="{eventtitle} - {eventshorttext}" /> + <!-- start and stop if event is not running --> + <drawtext x="10" y="9%" font="{vdrOsd}" fontsize="6%" color="{clrWhite}" text="{dayname} {eventstart} - {eventstop}, {channelname}" /> + <!-- scraper poster --> + <drawimage condition="{hasposter}" name="poster" imagetype="image" path="{posterpath}" x="{areawidth} - {areawidth}/4" y="17%" width="{areawidth}/4" height="{areawidth}/4 * {posterheight} / {posterwidth}"/> + <!-- description --> + <drawtextbox condition="{hasposter}" x="10" y="{posy(poster)}" width="99%" height="{areaheight} - {posy(poster)}" float="topright" floatwidth="{width(poster)} + 10" floatheight="{height(poster)} + 20" font="{vdrOsd}" fontsize="5%" color="{clrWhite}" text="{eventdescription}" /> + <drawtextbox condition="not{hasposter}" x="10" y="{posy(poster)}" width="99%" height="{areaheight} - {posy(poster)}" font="{vdrOsd}" fontsize="5%" color="{clrWhite}" text="{eventdescription}" /> + </area> + </currentelement> + + </menuitems> + +</menutimers>
\ 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 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE displaymessage SYSTEM "../../dtd/displaymessage.dtd">
+
+<displaymessage x="0" y="0" width="100%" height="100%" fadetime="300">
+
+ <background>
+ </background>
+
+ <!-- Available Variables message:
+ {text} message text
+ {status} true if message is a status message
+ {info} true if message is a info message
+ {warning} true if message is a warn message
+ {error} true if message is a error message
+ -->
+ <message>
+ <area x="5%" y="80%" width="90%" height="15%" layer="6">
+ <drawimage condition="{status}" imagetype="skinpart" path="messageStatus" x="0" y="0" width="100%" height="100%" />
+ <drawimage condition="{info}" imagetype="skinpart" path="messageInfo" x="0" y="0" width="100%" height="100%" />
+ <drawimage condition="{warning}" imagetype="skinpart" path="messageWarning" x="0" y="0" width="100%" height="100%" />
+ <drawimage condition="{error}" imagetype="skinpart" path="messageError" x="0" y="0" width="100%" height="100%" />
+ </area>
+ <area x="5%" y="80%" width="90%" height="15%" layer="7">
+ <drawtext align="center" valign="center" font="{light}" fontsize="40%" color="{clrWhite}" text="{text}" />
+ </area>
+ </message>
+
+</displaymessage>
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 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE displayreplay SYSTEM "../../dtd/displayreplay.dtd"> + +<displayreplay x="0" y="0" width="100%" height="100%" fadetime="{fadeTime}"> + + <background> + <area x="1%" y="74%" width="98%" height="25%" layer="1" transparency="20"> + <drawimage imagetype="skinpart" path="displayreplayback" x="0" y="0" width="100%" height="100%"/> + </area> + <area x="1%" y="74%" width="98%" height="25%" layer="7"> + <drawimage imagetype="skinpart" path="displayreplaytop" x="0" y="0" width="100%" height="100%"/> + </area> + <!-- background progress bar --> + <area x="3%" y="83%" width="94%" height="2%" layer="2"> + <drawellipse x="0" y="0" width="{areaheight}" height="{areaheight}" color="{clrBlack}" quadrant="0" /> + <drawellipse x="{areawidth}-{areaheight}" y="0" width="{areaheight}" height="{areaheight}" color="{clrBlack}" quadrant="0" /> + <drawrectangle x="{areaheight}/2" y="0" width="{areawidth} - {areaheight}" height="{areaheight}" color="{clrBlack}" /> + </area> + </background> + + <backgroundmodeonly> + <area x="40%" y="86%" width="20%" height="11%" layer="3"> + <fill color="{clrBrightGreen}" /> + <drawrectangle x="1" y="1" width="{areawidth} -2" height="{areaheight} -2" color="{clrTransBlack}" /> + </area> + </backgroundmodeonly> + + <!-- Available Variables datetime: + {time} time in hh:mm + {day} day in digits + {dayleadingzero} day in digits with leading 0 + {dayname} Full name of the day + {daynameshort} Short 3 char name of the day + {month} month in digits with leading 0 + {monthname} Full name of the month + {year} year in yyyy + --> + <datetime> + <area x="63%" y="74%" width="35%" height="6%" layer="2"> + <drawtext align="right" valign="center" font="{vdrOsd}" fontsize="95%" color="{clrWhite}" width="100%" text="{daynameshort} {day}.{month} {time}" /> + </area> + </datetime> + + <!-- Available Variables scrapercontent: + {mediapath} Full Path of Poster or Banner to use in image path attribute + {mediawidth} width of image in pixel + {mediaheight} height of image in pixel + {isbanner} true if image is a banner, false if it is a poster + --> + <scrapercontent> + <area condition="{isbanner}" x="0" y="0" width="{areaheight}*0.13*{mediawidth}/{mediaheight}" height="13%" layer="2"> + <drawimage imagetype="image" path="{mediapath}" align="center" valign="center" width="{areawidth}" height="{areaheight}"/> + </area> + <area condition="not{isbanner}" x="0" y="0" width="{areaheight}*0.5*{mediawidth}/{mediaheight}" height="50%" layer="2"> + <drawimage imagetype="image" path="{mediapath}" x="5" y="5" width="{areawidth}-10" height="{areaheight}-10"/> + </area> + </scrapercontent> + + <!-- Available Variables rectitle: + {rectitle} Title of Recording + {recsubtitle} Subtitle of the Recording + {recdate} Date Recording in dd.mm.yy + {rectime} Time of Recording in hh:mm + --> + <rectitle> + <area x="3%" y="74%" width="60%" height="6%" layer="2"> + <drawtext name="title" x="0" valign="center" font="{vdrOsd}" fontsize="95%" color="{clrWhite}" width="100%" text="{rectitle}" /> + <drawtext condition="isset{recsubtitle}" x="{width(title)}" valign="center" font="{vdrOsd}" fontsize="95%" color="{clrWhite}" width="100%" text=" - {recsubtitle}" /> + </area> + </rectitle> + + <!-- Available Variables recinfo: + {screenwidth} width of currently displayed recording in px + {screenheight} height of currently displayed recording in px + {resolution} resolution: hd1080i, hd720p, sd576i + {aspect} screen aspect, each 4:3, 16:9 or 21:9 + {isHD} true for hd1080i and hd720p + {isWideScreen} true if aspect is 16:9 or 21:9 + --> + <recinfo> + <area x="{areawidth}*0.98 - {areaheight}*0.15" y="93%" width="{areaheight}*0.15" height="5%" layer="2"> + <drawimage imagetype="icon" path="ico_{resolution}" x="0" y="0" width="{areaheight}*3" height="{areaheight}"/> + </area> + </recinfo> + + <!-- Available Variables currenttime: + {reccurrent} Current Time in hh:mm:ss + --> + <currenttime> + <area x="3%" y="86%" width="30%" height="4%" layer="2"> + <drawtext x="0" valign="center" font="{vdrOsd}" fontsize="100%" color="{clrWhite}" text="{reccurrent}" /> + </area> + </currenttime> + + <!-- Available Variables totaltime: + {rectotal} Total Time in hh:mm:ss + --> + <totaltime> + <area x="67%" y="86%" width="30%" height="4%" layer="2"> + <drawtext align="right" valign="center" font="{vdrOsd}" fontsize="100%" color="{clrWhite}" text="{rectotal}" /> + </area> + </totaltime> + + <!-- Available Variables progressbar: + {current} current frame of recording + {total} total frames of recording + --> + <progressbar> + <area x="3%" y="83%" width="94%" height="2%" layer="2"> + <drawellipse x="1" y="1" width="{areaheight}-2" height="{areaheight}-2" color="{clrBrightGreen}" quadrant="0" /> + <drawrectangle x="{areaheight}/2" y="1" width="{current}/{total}*{areawidth} - {current}/{total}*{areaheight}" height="{areaheight}-2" color="{clrBrightGreen}" /> + </area> + </progressbar> + + <!-- Available Variables cutmarks: + {marks[]} array of available marks + {marks[position]} frame of current mark + {marks[endposition]} frame where startmark ends + {marks[total]} total number of frames + {marks[startmark]} true if mark is start mark + --> + <cutmarks> + <area x="3%" y="82%" width="94%" height="4%" layer="3"> + <loop name="marks" x="0" y="0" orientation="absolute"> + <drawrectangle x="{marks[position]}/{marks[total]}*{areawidth}" y="0" width="1" height="100%" color="{clrTransWhite}" /> + <drawrectangle condition="{marks[startmark]}" x="{marks[position]}/{marks[total]}*{areawidth}" y="0" width="5" height="1" color="{clrTransWhite}" /> + <drawrectangle condition="{marks[startmark]}" x="{marks[position]}/{marks[total]}*{areawidth}" y="{areaheight}-1" width="5" height="1" color="{clrTransWhite}" /> + <drawrectangle condition="not{marks[startmark]}" x="{marks[position]}/{marks[total]}*{areawidth} - 5" y="0" width="5" height="1" color="{clrTransWhite}" /> + <drawrectangle condition="not{marks[startmark]}" x="{marks[position]}/{marks[total]}*{areawidth} - 5" y="{areaheight}-1" width="5" height="1" color="{clrTransWhite}" /> + <drawrectangle condition="{marks[startmark]}" x="{marks[position]}/{marks[total]}*{areawidth}" y="30%" width="{marks[endposition]}/{marks[total]}*{areawidth} - {marks[position]}/{marks[total]}*{areawidth}" height="40%" color="{clrTransWhite}" /> + </loop> + </area> + </cutmarks> + + <!-- Available Variables controlicons and controliconsmodeonly: + {play} true if recording is played currently + {pause} true if recording is paused + {forward} true if fast forwarding + {forward1x} true if fast forwarding 1x (with 3 trickspeeds) + {forward2x} true if fast forwarding 2x (with 3 trickspeeds) + {forward3x} true if fast forwarding 3x (with 3 trickspeeds) + {rewind} true if rewinding + {rewind1x} true if rewinding 1x (with 3 trickspeeds) + {rewind2x} true if rewinding 2x (with 3 trickspeeds) + {rewind3x} true if rewinding 3x (with 3 trickspeeds) + --> + <controlicons> + <area x="30%" y="88%" width="40%" height="7%" layer="3"> + <drawimage condition="not{rewind} ++ not{rewind1x} ++ not{rewind2x} ++ not{rewind3x}" imagetype="icon" path="ico_rew_off" x="{areawidth}/2 - 2*{areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{rewind}" imagetype="icon" path="ico_rew" x="{areawidth}/2 - 2*{areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{rewind1x}" imagetype="icon" path="ico_rew_1x" x="{areawidth}/2 - 2*{areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{rewind2x}" imagetype="icon" path="ico_rew_2x" x="{areawidth}/2 - 2*{areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{rewind3x}" imagetype="icon" path="ico_rew_3x" x="{areawidth}/2 - 2*{areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + + <drawimage condition="not{pause}" imagetype="icon" path="ico_pause_off" x="{areawidth}/2 - {areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{pause}" imagetype="icon" path="ico_pause" x="{areawidth}/2 - {areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + + <drawimage condition="not{play}" imagetype="icon" path="ico_play_off" x="{areawidth}/2" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{play}" imagetype="icon" path="ico_play" x="{areawidth}/2" y="0" width="{areaheight}" height="{areaheight}"/> + + <drawimage condition="not{forward} ++ not{forward1x} ++ not{forward2x} ++ not{forward3x}" imagetype="icon" path="ico_ff_off" x="{areawidth}/2 + {areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{forward}" imagetype="icon" path="ico_ff" x="{areawidth}/2 + {areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{forward1x}" imagetype="icon" path="ico_ff_1x" x="{areawidth}/2 + {areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{forward2x}" imagetype="icon" path="ico_ff_2x" x="{areawidth}/2 + {areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{forward3x}" imagetype="icon" path="ico_ff_3x" x="{areawidth}/2 + {areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + </area> + </controlicons> + + <controliconsmodeonly> + <area x="30%" y="88%" width="40%" height="7%" layer="3"> + <drawimage condition="not{rewind} ++ not{rewind1x} ++ not{rewind2x} ++ not{rewind3x}" imagetype="icon" path="ico_rew_off" x="{areawidth}/2 - 2*{areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{rewind}" imagetype="icon" path="ico_rew" x="{areawidth}/2 - 2*{areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{rewind1x}" imagetype="icon" path="ico_rew_1x" x="{areawidth}/2 - 2*{areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{rewind2x}" imagetype="icon" path="ico_rew_2x" x="{areawidth}/2 - 2*{areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{rewind3x}" imagetype="icon" path="ico_rew_3x" x="{areawidth}/2 - 2*{areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + + <drawimage condition="not{pause}" imagetype="icon" path="ico_pause_off" x="{areawidth}/2 - {areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{pause}" imagetype="icon" path="ico_pause" x="{areawidth}/2 - {areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + + <drawimage condition="not{play}" imagetype="icon" path="ico_play_off" x="{areawidth}/2" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{play}" imagetype="icon" path="ico_play" x="{areawidth}/2" y="0" width="{areaheight}" height="{areaheight}"/> + + <drawimage condition="not{forward} ++ not{forward1x} ++ not{forward2x} ++ not{forward3x}" imagetype="icon" path="ico_ff_off" x="{areawidth}/2 + {areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{forward}" imagetype="icon" path="ico_ff" x="{areawidth}/2 + {areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{forward1x}" imagetype="icon" path="ico_ff_1x" x="{areawidth}/2 + {areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{forward2x}" imagetype="icon" path="ico_ff_2x" x="{areawidth}/2 + {areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{forward3x}" imagetype="icon" path="ico_ff_3x" x="{areawidth}/2 + {areaheight}" y="0" width="{areaheight}" height="{areaheight}"/> + </area> + </controliconsmodeonly> + + <!-- Available Variables jump: + {jump} time to jump to in hh:mm + --> + <jump> + <area x="5%" y="90%" width="30%" height="7%" layer="2"> + <drawtext align="center" valign="center" font="{vdrOsd}" fontsize="80%" color="{clrWhite}" text="{jump}" /> + </area> + </jump> + <!-- Available Variables message: + {text} message text + {status} true if message is a status message + {info} true if message is a info message + {warning} true if message is a warn message + {error} true if message is a error message + --> + <message> + <area x="5%" y="58%" width="90%" height="15%" layer="6"> + <drawimage condition="{status}" imagetype="skinpart" path="messageStatus" x="0" y="0" width="100%" height="100%" /> + <drawimage condition="{info}" imagetype="skinpart" path="messageInfo" x="0" y="0" width="100%" height="100%" /> + <drawimage condition="{warning}" imagetype="skinpart" path="messageWarning" x="0" y="0" width="100%" height="100%" /> + <drawimage condition="{error}" imagetype="skinpart" path="messageError" x="0" y="0" width="100%" height="100%" /> + </area> + <area x="5%" y="58%" width="90%" height="15%" layer="7"> + <drawtext align="center" valign="center" font="{light}" fontsize="40%" color="{clrWhite}" text="{text}" /> + </area> + </message> + +</displayreplay> 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 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE displayvolume SYSTEM "../../dtd/displayvolume.dtd"> + +<displayvolume x="20%" y="75%" width="60%" height="10%" fadetime="{fadeTime}"> + + <background> + </background> + + <!-- Available Variables volume: + {volume} current volume, range from 0 to 255 + {volumepercent} current volume in % + {maxvolume} maximal volume + {mute} true if volume is muted + --> + <volume> + <!-- Background --> + <area x="0" y="0" width="100%" height="100%" layer="1" transparency="20"> + <drawimage imagetype="skinpart" path="displayvolume" x="0" y="0" width="100%" height="100%"/> + </area> + <!-- Header --> + <area x="0" y="3%" width="100%" height="40%" layer="2"> + <drawtext x="10" valign="center" font="{vdrOsd}" fontsize="100%" color="{clrWhite}" text="{tr(volume)}: {volumepercent}%" /> + <drawimage condition="not{mute}" imagetype="icon" path="ico_volume" x="{areawidth} - 2*{areaheight}" y="5" width="{areaheight}" height="{areaheight}"/> + <drawimage condition="{mute}" imagetype="icon" path="ico_mute" x="{areawidth} - 2*{areaheight}" y="5" width="{areaheight}" height="{areaheight}"/> + </area> + <!-- Volumebar Background --> + <area x="4%" y="60%" width="92%" height="30%" layer="2"> + <drawellipse x="0" y="0" width="{areaheight}" height="{areaheight}" color="{clrBlack}" quadrant="0" /> + <drawellipse x="1" y="1" width="{areaheight}-2" height="{areaheight}-2" color="{clrBrightGreen}" quadrant="0" /> + <drawellipse x="{areawidth}-{areaheight}" y="0" width="{areaheight}" height="{areaheight}" color="{clrBlack}" quadrant="0" /> + <drawrectangle x="{areaheight}/2" y="0" width="{areawidth} - {areaheight}" height="{areaheight}" color="{clrBlack}" /> + </area> + <!-- Volumebar --> + <area x="5%" y="60%" width="91%" height="30%" layer="3"> + <drawrectangle x="1" y="1" width="{volume}/{maxvolume}*{areawidth} - {volume}/{maxvolume}*{areaheight}/2" height="{areaheight}-2" color="{clrBrightGreen}" /> + <drawellipse x="{volume}/{maxvolume}*{areawidth} - {volume}/{maxvolume}*{areaheight}/2" y="1" width="{areaheight}/2 - 2" height="{areaheight}-2" color="{clrBrightGreen}" quadrant="5" /> + </area> + </volume> + +</displayvolume> 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 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE globals SYSTEM "../../dtd/globals.dtd"> + +<globals> + <!-- + define all your needed colors here + --> + <colors> + <color name="clrRed">FFFF0000</color> + <color name="clrGreen">FF5FE200</color> + <color name="clrYellow">FFE2DA00</color> + <color name="clrBlue">FF007FE2</color> + <color name="clrWhite">FFFFFFFF</color> + <color name="clrTransWhite">99FFFFFF</color> + <color name="clrBlack">FF000000</color> + <color name="clrBrightGreen">FF8EAB21</color> + <color name="clrDarkGreen">FF4C5C11</color> + <color name="clrGray">FF858585</color> + <color name="clrDarkBlue">B012273F</color> + <color name="clrTransBlack">99000000</color> + <color name="clrTransRed">99FF0000</color> + <color name="clrFontMenuItem">FFFFFFFF</color> + <color name="clrFontMenuItemSelected">FF363636</color> + <color name="clrFontInactive">FF858585</color> + <color name="clrTransparent">00000000</color> + </colors> + <!-- + these variables can be used everywhere in the templates + variabls of type int can also be used as conditions, just + set such a variable to 1 for true and 0 for false + --> + <variables> + <var type="int" name="fadeTime">300</var> + </variables> + <!-- + translations used in the skin + --> + <translations> + <token name="tr(free)"> + <trans lang="en_EN">free</trans> + <trans lang="de_DE">frei</trans> + </token> + <token name="tr(transponder)"> + <trans lang="en_EN">Transponder</trans> + <trans lang="de_DE">Transponder</trans> + </token> + <token name="tr(now)"> + <trans lang="en_EN">Now</trans> + <trans lang="de_DE">Jetzt</trans> + </token> + <token name="tr(next)"> + <trans lang="en_EN">Next</trans> + <trans lang="de_DE">Nachfolgend</trans> + </token> + <token name="tr(nextschedules)"> + <trans lang="en_EN">Next Schedules</trans> + <trans lang="de_DE">Nachfolgende Sendungen</trans> + </token> + <token name="tr(reruns)"> + <trans lang="en_EN">Reruns</trans> + <trans lang="de_DE">Wiederholungen</trans> + </token> + <token name="tr(rerunsof)"> + <trans lang="en_EN">Reruns of</trans> + <trans lang="de_DE">Wiederholungen von</trans> + </token> + <token name="tr(actors)"> + <trans lang="en_EN">Actors</trans> + <trans lang="de_DE">Schauspieler</trans> + </token> + <token name="tr(episode)"> + <trans lang="en_EN">Episode</trans> + <trans lang="de_DE">Folge</trans> + </token> + <token name="tr(season)"> + <trans lang="en_EN">Season</trans> + <trans lang="de_DE">Staffel</trans> + </token> + <token name="tr(gueststars)"> + <trans lang="en_EN">Guest Stars</trans> + <trans lang="de_DE">Gaststars</trans> + </token> + <token name="tr(seriesfirstaired)"> + <trans lang="en_EN">Series First Aired</trans> + <trans lang="de_DE">Erstausstrahlung der Serie</trans> + </token> + <token name="tr(episodefirstaired)"> + <trans lang="en_EN">Episode First Aired</trans> + <trans lang="de_DE">Erstausstrahlung der Episode</trans> + </token> + <token name="tr(network)"> + <trans lang="en_EN">Network</trans> + <trans lang="de_DE">TV Station</trans> + </token> + <token name="tr(genre)"> + <trans lang="en_EN">Genre</trans> + <trans lang="de_DE">Genre</trans> + </token> + <token name="tr(status)"> + <trans lang="en_EN">Status</trans> + <trans lang="de_DE">Status</trans> + </token> + <token name="tr(rating)"> + <trans lang="en_EN">Rating</trans> + <trans lang="de_DE">Bewertung</trans> + </token> + <token name="tr(episoderating)"> + <trans lang="en_EN">Episode Rating</trans> + <trans lang="de_DE">Bewertung der Folge</trans> + </token> + <token name="tr(recinfo)"> + <trans lang="en_EN">Recording Information</trans> + <trans lang="de_DE">Aufnahme Informationen</trans> + </token> + <token name="tr(seriesgalery)"> + <trans lang="en_EN">Series Galery</trans> + <trans lang="de_DE">Serien Galerie</trans> + </token> + <token name="tr(moviegalery)"> + <trans lang="en_EN">Movie Galery</trans> + <trans lang="de_DE">Spielfilm Galerie</trans> + </token> + <token name="tr(originaltitle)"> + <trans lang="en_EN">Original Title</trans> + <trans lang="de_DE">Originaltitel</trans> + </token> + <token name="tr(budget)"> + <trans lang="en_EN">Budget</trans> + <trans lang="de_DE">Budget</trans> + </token> + <token name="tr(revenue)"> + <trans lang="en_EN">Revenue</trans> + <trans lang="de_DE">Einnahmen</trans> + </token> + <token name="tr(adult)"> + <trans lang="en_EN">Adult</trans> + <trans lang="de_DE">Nur für Erwachsene</trans> + </token> + <token name="tr(releasedate)"> + <trans lang="en_EN">Release Date</trans> + <trans lang="de_DE">Erscheinungsdatum</trans> + </token> + <token name="tr(runtime)"> + <trans lang="en_EN">Runtime</trans> + <trans lang="de_DE">Laufzeit</trans> + </token> + <token name="tr(popularity)"> + <trans lang="en_EN">Popularity</trans> + <trans lang="de_DE">Popularität</trans> + </token> + <token name="tr(voteaverage)"> + <trans lang="en_EN">Vote Average</trans> + <trans lang="de_DE">Durchschnittliche Wertung</trans> + </token> + <token name="tr(homepage)"> + <trans lang="en_EN">Homepage</trans> + <trans lang="de_DE">Homepage</trans> + </token> + <token name="tr(recsize)"> + <trans lang="en_EN">Recording size</trans> + <trans lang="de_DE">Größe der Aufnahme</trans> + </token> + <token name="tr(recsizecutted)"> + <trans lang="en_EN">Cutted Recording Size</trans> + <trans lang="de_DE">Größe der geschnittenen Aufnahme</trans> + </token> + <token name="tr(reclength)"> + <trans lang="en_EN">Recording Length</trans> + <trans lang="de_DE">Länge der Aufnahme</trans> + </token> + <token name="tr(reclengthcutted)"> + <trans lang="en_EN">Cutted Recording Length</trans> + <trans lang="de_DE">Länge der geschnittenen Aufnahme</trans> + </token> + <token name="tr(bitrate)"> + <trans lang="en_EN">Bit Rate</trans> + <trans lang="de_DE">Bitrate</trans> + </token> + <token name="tr(format)"> + <trans lang="en_EN">Format</trans> + <trans lang="de_DE">Format</trans> + </token> + <token name="tr(searchtimer)"> + <trans lang="en_EN">Searchtimer</trans> + <trans lang="de_DE">Suchtimer</trans> + </token> + <token name="tr(volume)"> + <trans lang="en_EN">Volume</trans> + <trans lang="de_DE">Lautstärke</trans> + </token> + </translations> + <!-- + The three Fonts FontOSD, FontFix and FontSml configured in VDR + can be used in all template "font" attributes with this tokens: + {vdrOsd} + {vdrFix} + {vdrSml} + If you like to use further fonts, just define them below. + Syntax: + <font name="tokenname">fontname</font> + These fonts can then also be used in all templates in the "font" + attribute. + if an invalid font is used in a template, vdrOsd is used as default. + --> + <fonts> + </fonts> +</globals> 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 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE displayaudiotracks SYSTEM "../../dtd/displayaudiotracks.dtd"> + +<displayaudiotracks x="0" y="0" width="100%" height="100%" fadetime="0"> + <!-- Available Variables background: + {numtracks} number of displayed tracks + --> + <background> + </background> + + <!-- Available Variables header: + {numtracks} number of displayed tracks + {title} title of menu + --> + <header> + </header> + + <!-- Available Variables header: + {numelements} number of displayed tracks + --> + <menuitems x="0" y="{areaheight} - {numelements} * {areaheight} / 10" orientation="vertical" width="100%" height="{numelements} * {areaheight} / 10" align="top" numlistelements="{numelements}"> + <!-- Available Variables auidotrack listelement: + {current} true if item is currently selected + {title} title of auio track + --> + <listelement> + </listelement> + </menuitems> + +</displayaudiotracks> 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 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE displaychannel SYSTEM "../../dtd/displaychannel.dtd"> + +<displaychannel x="0" y="0" width="100%" height="100%" fadetime="0"> + + <background> + </background> + + <!-- Available Variables channelinfo: + {channelnumber} Number of Channel, with "-" in case of channel switching + {channelname} Name of current Channel + {channellogoexists} true if a channel logo exists + {channelid} ChannelID as path to display channel logo + {switching} true if a number is pressed on the remote to switch to a dedicated channel + --> + <channelinfo> + </channelinfo> + + <!-- Available Variables epginfo: + {currenttitle} Title of the current Schedule + {currentsubtitle} Subtitle of the current Schedule + {currentstart} Start of current Schedule in hh:mm + {currentstop} End of current Schedule in hh:mm + {currentduration} Duration of current Schedule in min + {currentelapsed} Elapsed time of current Schedule in min + {currentremaining} Remaining time of current Schedule in min + {currentrecording} true if current Schedule is recorded + {nexttitle} Title of next Schedule + {nextsubtitle} Subtitle of next Schedule + {nextstart} Start of next Schedule in hh:mm + {nextstop} Stop of next Schedule in hh:mm + {nextduration} Duration of next Schedule in min + {nextrecording} true if next Schedule will be recorded + --> + <epginfo> + </epginfo> + + <!-- Available Variables progressbar: + {start} Start of current Schedule in hh:mm + {stop} End of current Schedule in hh:mm + {duration} Total Duration of current Schedule in seconds + {elapsed} Elapsed time of current Schedule in seconds + {remaining} Remaining time of current Schedule in seconds + --> + <progressbar> + </progressbar> + + <!-- Available Variables statusinfo: + {isRadio} true if channel is a radio channel + {hasVT} true if channel has video text + {isStereo} true if a stereo audio trac is available + {isDolby} true if a dolby audio track is available + {isEncrypted} true if channel is encrypted + {isRecording} true if currently a recording is running on this channel + --> + <statusinfo> + </statusinfo> + + <!-- Available Variables screenresolution: + {screenwidth} width of currently displayed channel in px + {screenheight} height of currently displayed channel in px + {resolution} resolution: hd1080i, hd720p, sd576i + {aspect} screen aspect, each 4:3, 16:9 or 21:9 + {isHD} true for hd1080i and hd720p + {isWideScreen} true if aspect is 16:9 or 21:9 + --> + <screenresolution> + </screenresolution> + + <!-- Available Variables dvbdeviceinfo: + {prevAvailable} true if previous Channel Group is avaialble + {nextAvailable} true if next Channel Group is avaialble + {group} Name of current Channel Group + {nextgroup} Name of next Channel Group + {prevgroup} Name of prev Channel Group + {sepexists} true if a channel separator logo exists + {seppath} path for separator logo to use in imagetype "seplogo" + --> + <channelgroup> + </channelgroup> + + <!-- Available Variables signalquality: + {signalstrength} STR value of currently displayed channel + {signalquality} SNR value of currently displayed channel + --> + <signalquality> + </signalquality> + + <!-- background of signalmeter, will only be drawn if signalquality was deleted --> + <signalqualityback> + </signalqualityback> + + <!-- Available Variables scrapercontent: + {mediapath} Full Path of Poster or Banner to use in image path attribute + {mediawidth} width of image in pixel + {mediaheight} height of image in pixel + {isbanner} true if image is a banner, false if it is a poster + --> + <scrapercontent> + </scrapercontent> + + <!-- Available Variables datetime: + {time} time in hh:mm + {day} day in digits + {dayleadingzero} day in digits with leading 0 + {dayname} Full name of the day + {daynameshort} Short 3 char name of the day + {month} month in digits with leading 0 + {monthname} Full name of the month + {monthnameshort} 3 letter abbrivation of month name + {year} year in yyyy + --> + <datetime> + </datetime> + + <!-- Available Variables message: + {text} message text + {status} true if message is a status message + {info} true if message is a info message + {warning} true if message is a warn message + {error} true if message is a error message + --> + <message> + </message> + +</displaychannel> 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 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE displaymenu SYSTEM "../../dtd/displaymenu.dtd" [ +<!ENTITY displaymenudefault SYSTEM "displaymenudefault.xml"> +<!ENTITY displaymenumain SYSTEM "displaymenumain.xml"> +<!ENTITY displaymenusetup SYSTEM "displaymenusetup.xml"> +<!ENTITY displaymenuschedules SYSTEM "displaymenuschedules.xml"> +<!ENTITY displaymenutimers SYSTEM "displaymenutimers.xml"> +<!ENTITY displaymenuchannels SYSTEM "displaymenuchannels.xml"> +<!ENTITY displaymenurecordings SYSTEM "displaymenurecordings.xml"> +<!ENTITY displaymenudetailepg SYSTEM "displaymenudetailepg.xml"> +<!ENTITY displaymenudetailrecording SYSTEM "displaymenudetailrecording.xml"> +<!ENTITY displaymenudetailtext SYSTEM "displaymenudetailtext.xml"> +]> + +<displaymenu x="0" y="0" width="100%" height="100%" fadetime="0"> + <!-- + The following background, header, datetime and colorbuttons definitions are default + implementations. If one or more of these elements are not implemented in the subview, + the default implementations are used. + --> + <background> + </background> + <!-- Available Variables header: + {title} title of current menu + {vdrversion} running VDR Version + {hasicon} true if a menu icon is available + {icon} path of menu icon + --> + <header> + </header> + <!-- Available Variables datetime: + {time} time in hh:mm + {day} day in digits + {dayleadingzero} day in digits with leading 0 + {dayname} Full name of the day + {daynameshort} Short 3 char name of the day + {month} month in digits with leading 0 + {monthname} Full name of the month + {monthnameshort} 3 letter abbrivation of month name + {year} year in yyyy + --> + <datetime> + </datetime> + <!-- Available Variables message: + {text} message text + {status} true if message is an status message + {info} true if message is an info message + {warning} true if message is an warn message + {error} true if message is an error message + --> + <message> + </message> + <!-- Available Variables colorbuttons: + {red1} true if red button is button 1 + {red2} true if red button is button 2 + {red3} true if red button is button 3 + {red4} true if red button is button 4 + {green1} true if green button is button 1 + {green2} true if green button is button 2 + {green3} true if green button is button 3 + {green4} true if green button is button 4 + {yellow1} true if yellow button is button 1 + {yellow2} true if yellow button is button 2 + {yellow3} true if yellow button is button 3 + {yellow4} true if yellow button is button 4 + {blue1} true if blue button is button 1 + {blue2} true if blue button is button 2 + {blue3} true if blue button is button 3 + {blue4} true if blue button is button 4 + {red} label of red button + {green} label of green button + {yellow} label of yellow button + {blue} label of blue button + --> + <colorbuttons> + </colorbuttons> + &displaymenudefault; + &displaymenumain; + &displaymenusetup; + &displaymenuschedules; + &displaymenutimers; + &displaymenuchannels; + &displaymenurecordings; + &displaymenudetailepg; + &displaymenudetailrecording; + &displaymenudetailtext; +</displaymenu> 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 @@ +<menuchannels x="0" y="0" width="100%" height="100%" fadetime="0"> + <menuitems x="0" y="0" orientation="vertical" width="100%" height="100%" align="center" numlistelements="16"> + <!-- Available Variables channels menu listelement: + {number} number of the displayed channel + {name} name of the displayed channel + {channelid} ChannelID as path to display channel logo + {transponder} Transponder of channel + {frequency} Frequency of channel + {source} Source of channel (S, C, T) + {sourcedescription} Descriptin of source from sources.conf + {position} orbital position of the satellite in case this is a DVB-S source + {isAtsc} true if channel is a ATSC channel + {isCable} true if channel is cable channel + {isSat} true if channel is a satellite channel + {isTerr} true if channel is terrestrical + {presenteventtitle} title of present event on this channel + {presenteventstart} present event start time in hh::mm + {presenteventstop} present event event stop time in hh::mm + {current} true if item is currently selected + {separator} true if item is a list separator + --> + <listelement> + </listelement> + <!-- additional element which is drawn for current element --> + <!-- Available Variables channels menu currentelement: + {menuitemx} x position of according menu item + {menuitemy} y position of according menu item + {menuitemwidth} width of according menu item + {menuitemheight} height of according menu item + {number} number of the displayed channel + {name} name of the displayed channel + {channelid} ChannelID as path to display channel logo + {transponder} Transponder of channel + {frequency} Frequency of channel + {source} Source of channel (S, C, T) + {sourcedescription} Descriptin of source from sources.conf + {position} orbital position of the satellite in case this is a DVB-S source + {isAtsc} true if channel is a ATSC channel + {isCable} true if channel is cable channel + {isSat} true if channel is a satellite channel + {isTerr} true if channel is terrestrical + {presenteventtitle} title of present event on this channel + {presenteventstart} present event start time in hh::mm + {presenteventstop} present event stop time in hh::mm + {presenteventshorttext} present event short text + {presenteventdescription} present event description + {presenteventday} present event name of day + {presenteventdate} present event date in dd:mm:yy + {presenteventelapsed} present event elapsed time + {presenteventduration} present event duration + {hasposter} true if a scraped poster is available for this elements present evemt + {posterwidth} width of scraped poster + {posterheight} height of scraped poster + {posterpath} absolute path of scraped poster + {nexteventtitle} title of next event on this channel + {nexteventstart} next event start time in hh::mm + {nexteventstop} next event event stop time in hh::mm + {nexteventshorttext} next event short text + {nexteventdescription} next event description + {nexteventday} next event name of day + {nexteventdate} next event date in dd:mm:yy + {nexteventdate} next event duration + {schedule[]} array with following 10 schedules + {schedule[title]} title of event + {schedule[shorttext]} shorttext of event + {schedule[start]} start time of event in hh:mm + {schedule[stop]} stop time of event in hh:mm + --> + <currentelement delay="500" fadetime="0"> + </currentelement> + + </menuitems> + +</menuchannels>
\ 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 @@ + <menudefault x="0" y="0" width="100%" height="100%" fadetime="0"> + <!-- IMPORTANT: menuitemwidth and determinatefont have to be defined here. menuitemwidth defines the total width of the + default menu items, determinatefont the function which sets the actual font to use. With that it is possible to determinate + the correct column widths --> + <menuitems x="0" y="0" orientation="vertical" width="100%" height="100%" align="center" menuitemwidth="94%" determinatefont="column1" numlistelements="16"> + <!-- Available Variables default menu listelement: + {column1} text of column1 + {column2} text of column2 + {column3} text of column3 + {column4} text of column4 + {column5} text of column5 + {column6} text of column6 + {column2set} true if column2 is used + {column3set} true if column3 is used + {column4set} true if column4 is used + {column5set} true if column5 is used + {column6set} true if column6 is used + {column2x} proposed x value of column2 + {column3x} proposed x value of column3 + {column4x} proposed x value of column4 + {column5x} proposed x value of column5 + {column6x} proposed x value of column6 + {column1width} proposed width of column1 + {column2width} proposed width of column2 + {column3width} proposed width of column3 + {column4width} proposed width of column4 + {column5width} proposed width of column5 + {column6width} proposed width of column6 + {current} true if column is currently selected + {separator} true if column is a list separator + --> + <listelement> + </listelement> + + </menuitems> +</menudefault> 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 @@ +<menudetailedepg x="0" y="0" width="100%" height="100%" fadetime="0"> + <!-- Available Variables in detailheader elements: + {title} title of event + {shorttext} shorttext of event + {start} event start time in hh::mm + {stop} event stop time + {day} day of current event + {date} date of current event in dd.mm.yy + {running} true if event is currently running + {elapsed} elapsed time of event, if not running 0 + {duration} duration of event + {channelid} ChannelID as path to display channel logo + {ismovie} true if event is scraped as a movie + {isseries} true if event is scraped as a series + {posteravailable} true if a poster is available + {posterwidth} width of scraped poster + {posterheight} height of scraped poster + {posterpath} absolute path of scraped poster + {banneravailable} true if a banner is available + {bannerwidth} width of banner + {bannerheight} height of banner + {bannerpath} path of banner + {epgpicavailable} true if a epg picture is available + {epgpicpath} path of epg picture + --> + <detailheader> + </detailheader> + + <!-- Available Variables in tab elements: + {title} title of event + {shorttext} shorttext of event + {description} description of event + {start} event start time in hh::mm + {stop} event stop time + {day} day of current event + {date} date of current event in dd.mm.yy + {running} true if event is currently running + {elapsed} elapsed time of event, if not running 0 + {duration} duration of event + {channelid} ChannelID as path to display channel logo + {hasreruns} true if reruns of this event are found + {reruns[]} array with reruns + {reruns[title]} title of rerun + {reruns[shorttext]} shorttext of rerun + {reruns[date]} date of rerun in dd:mm + {reruns[day]} short dayname of rerun + {reruns[start]} start time of rerun in hh:mm + {reruns[stop]} stop time of rerun in hh:mm + {reruns[channelname]} name of channel on which rerun occurs + {reruns[channelnumber]} number of channel on which rerun occurs + {reruns[channelid]} id of channel on which rerun occurs to display channel logo + {reruns[channellogoexists]} true if channel logo exists + {epgpic1avaialble} true if first epg picture is available + {epgpic2avaialble} true if first epg picture is available + {epgpic3avaialble} true if first epg picture is available + {epgpic1path} path of first epg picture + {epgpic2path} path of second epg picture + {epgpic3path} path of third epg picture + + {ismovie} true if event is scraped as a movie + Available variables for movies: + {movietitle} movie title from themoviedb + {movieoriginalTitle} movie original title from themoviedb + {movietagline} movie tagline from themoviedb + {movieoverview} movie overview from themoviedb + {movieadult} true if movie is rated as adult + {moviebudget} movie budget from themoviedb in $ + {movierevenue} movie revenue from themoviedb in $ + {moviegenres} movie genres from themoviedb + {moviehomepage} movie homepage from themoviedb + {moviereleasedate} movie release date from themoviedb + {movieruntime} movie runtime from themoviedb + {moviepopularity} movie popularity from themoviedb + {movievoteaverage} movie vote average from themoviedb + {posterwidth} width of scraped poster + {posterheight} height of scraped poster + {posterpath} absolute path of scraped poster + {fanartwidth} width of scraped fanart + {fanartheight} height of scraped fanart + {fanartpath} absolute path of scraped fanart + {movieiscollection} true if movie is part of a collection + {moviecollectionName} name of movie collection + {collectionposterwidth} width of scraped collection poster + {collectionposterheight} height of scraped collection poster + {collectionposterpath} absolute path of scraped collection poster + {collectionfanartwidth} width of scraped collection fanart + {collectionfanartheight} height of scraped collection fanart + {collectionfanartpath} absolute path of scraped collection fanart + {actors[]} array with movie actors + {actors[name]} real name of actor + {actors[role]} actor role + {actors[thumb]} absolute path of scraped actor thumb + {actors[thumbwidth]} width of scraped actor thumb + {actors[thumbheight]} height of scraped actor thumb + + {isseries} true if event is scraped as a series + Available variables for series: + {seriesname} name of series + {seriesoverview} series overview + {seriesfirstaired} first aired date + {seriesnetwork} network which produces series + {seriesgenre} series genre + {seriesrating} series thetvdb rating + {seriesstatus} status of series (running / finished) + {episodetitle} title of episode + {episodenumber} number of episode + {episodeseason} season of episode + {episodefirstaired} first aired date of episode + {episodegueststars} guest stars of episode + {episodeoverview} episode overview + {episoderating} user rating for episode + {episodeimagewidth} episode image width + {episodeimageheight} episode image height + {episodeimagepath} episode image path + {seasonposterwidth} episode season poster width + {seasonposterheight} episode season poster height + {seasonposterpath} episode season poster path + {seriesposter1width} width of 1st poster + {seriesposter1height} height of 1st poster + {seriesposter1path} path of 1st poster + {seriesposter2width} width of 2nd poster + {seriesposter2height} height of 2nd poster + {seriesposter2path} path of 2nd poster + {seriesposter3width} width of 3rd poster + {seriesposter3height} height of 3rd poster + {seriesposter3path} path of 3rd poster + {seriesfanart1width} width of 1st fanart + {seriesfanart1height} height of 1st fanart + {seriesfanart1path} path of 1st fanart + {seriesfanart2width} width of 2nd fanart + {seriesfanart2height} height of 2nd fanart + {seriesfanart2path} path of 2nd fanart + {seriesfanart3width} width of 3rd fanart + {seriesfanart3height} height of 3rd fanart + {seriesfanart3path} path of 3rd fanart + {seriesbanner1width} width of 1st banner + {seriesbanner1height} height of 1st banner + {seriesbanner1path} path of 1st banner + {seriesbanner2width} width of 2nd banner + {seriesbanner2height} height of 2nd banner + {seriesbanner2path} path of 2nd banner + {seriesbanner3width} width of 3rd banner + {seriesbanner3height} height of 3rd banner + {seriesbanner3path} path of 3rd fanart + {actors[]} array with movie actors + {actors[name]} real name of actor + {actors[role]} actor role + {actors[thumb]} absolute path of scraped actor thumb + {actors[thumbwidth]} width of scraped actor thumb + {actors[thumbheight]} height of scraped actor thumb + --> + + <!-- a tab is one scrolling area, just position and draw as inside a normal area --> + <!-- just define as many tabs as needed --> + <tab name="Tab1" x="0" y="0" width="100%" height="100%" layer="2" scrollheight="{areaheight}/4"> + </tab> + + <!-- Available Variables tablabels: + {tabs[]} array with available tab labels + {tabs[title]} title of tab + {tabs[current]} true if tab is displayed currently + --> + <tablabels> + </tablabels> +</menudetailedepg>
\ 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 @@ +<menudetailedrecording x="0" y="0" width="100%" height="100%" fadetime="0"> + <!-- Available Variables in detailheader elements: + {name} name of recording + {shorttext} shorttext of recording + {date} date of recording in dd.mm.yy + {time} time of current event in hh:mm + {duration} real duration of recording in minutes + {durationevent} duration of according event in minutes + {ismovie} true if event is scraped as a movie + {isseries} true if event is scraped as a series + {posteravailable} true if a poster is available + {posterwidth} width of scraped poster + {posterheight} height of scraped poster + {posterpath} absolute path of scraped poster + {banneravailable} true if a banner is available + {bannerwidth} width of banner + {bannerheight} height of banner + {bannerpath} path of banner + {recimgavailable} true if a recording image is available in the recording path + {recimgpath} path of rec image + --> + <detailheader> + </detailheader> + <!-- Available Variables in tab elements: + {name} title of recording + {shorttext} shorttext of recording + {description} description of recording + {date} date of recording in dd.mm.yy + {time} time of recording in hh:mm + {duration} real duration of recording in minutes + {durationevent} duration of according event in minutes + + {recordingsize} size of recording (automatically in GB / MB) + {recordingsizecutted} size of cutted recording (automatically in GB / MB) + {recordinglength} length of recording (in hh::mm:ss) + {recordinglengthcutted} length of cutted recording (in hh::mm:ss) + {recordingbitrate} bitrate of recording (in MBit/s) + {recordingformat} format of recording (TS / PS) + {searchtimer} name of accordign searchtimer (if available) + + {recimg1avaialble} true if first recording image is available + {recimg2avaialble} true if first recording image is available + {recimg3avaialble} true if first recording image is available + {recimg1path} path of first recording image + {recimg2path} path of second recording image + {recimg3path} path of third recording image + + {ismovie} true if event is scraped as a movie + Available variables for movies: + {movietitle} movie title from themoviedb + {movieoriginalTitle} movie original title from themoviedb + {movietagline} movie tagline from themoviedb + {movieoverview} movie overview from themoviedb + {movieadult} true if movie is rated as adult + {moviebudget} movie budget from themoviedb in $ + {movierevenue} movie revenue from themoviedb in $ + {moviegenres} movie genres from themoviedb + {moviehomepage} movie homepage from themoviedb + {moviereleasedate} movie release date from themoviedb + {movieruntime} movie runtime from themoviedb + {moviepopularity} movie popularity from themoviedb + {movievoteaverage} movie vote average from themoviedb + {posterwidth} width of scraped poster + {posterheight} height of scraped poster + {posterpath} absolute path of scraped poster + {fanartwidth} width of scraped fanart + {fanartheight} height of scraped fanart + {fanartpath} absolute path of scraped fanart + {movieiscollection} true if movie is part of a collection + {moviecollectionName} name of movie collection + {collectionposterwidth} width of scraped collection poster + {collectionposterheight} height of scraped collection poster + {collectionposterpath} absolute path of scraped collection poster + {collectionfanartwidth} width of scraped collection fanart + {collectionfanartheight} height of scraped collection fanart + {collectionfanartpath} absolute path of scraped collection fanart + {actors[]} array with movie actors + {actors[name]} real name of actor + {actors[role]} actor role + {actors[thumb]} absolute path of scraped actor thumb + {actors[thumbwidth]} width of scraped actor thumb + {actors[thumbheight]} height of scraped actor thumb + + {isseries} true if event is scraped as a series + Available variables for series: + {seriesname} name of series + {seriesoverview} series overview + {seriesfirstaired} first aired date + {seriesnetwork} network which produces series + {seriesgenre} series genre + {seriesrating} series thetvdb rating + {seriesstatus} status of series (running / finished) + {episodetitle} title of episode + {episodenumber} number of episode + {episodeseason} season of episode + {episodefirstaired} first aired date of episode + {episodegueststars} guest stars of episode + {episodeoverview} episode overview + {episoderating} user rating for episode + {episodeimagewidth} episode image width + {episodeimageheight} episode image height + {episodeimagepath} episode image path + {seasonposterwidth} episode season poster width + {seasonposterheight} episode season poster height + {seasonposterpath} episode season poster path + {seriesposter1width} width of 1st poster + {seriesposter1height} height of 1st poster + {seriesposter1path} path of 1st poster + {seriesposter2width} width of 2nd poster + {seriesposter2height} height of 2nd poster + {seriesposter2path} path of 2nd poster + {seriesposter3width} width of 3rd poster + {seriesposter3height} height of 3rd poster + {seriesposter3path} path of 3rd poster + {seriesfanart1width} width of 1st fanart + {seriesfanart1height} height of 1st fanart + {seriesfanart1path} path of 1st fanart + {seriesfanart2width} width of 2nd fanart + {seriesfanart2height} height of 2nd fanart + {seriesfanart2path} path of 2nd fanart + {seriesfanart3width} width of 3rd fanart + {seriesfanart3height} height of 3rd fanart + {seriesfanart3path} path of 3rd fanart + {seriesbanner1width} width of 1st banner + {seriesbanner1height} height of 1st banner + {seriesbanner1path} path of 1st banner + {seriesbanner2width} width of 2nd banner + {seriesbanner2height} height of 2nd banner + {seriesbanner2path} path of 2nd banner + {seriesbanner3width} width of 3rd banner + {seriesbanner3height} height of 3rd banner + {seriesbanner3path} path of 3rd fanart + {actors[]} array with movie actors + {actors[name]} real name of actor + {actors[role]} actor role + {actors[thumb]} absolute path of scraped actor thumb + {actors[thumbwidth]} width of scraped actor thumb + {actors[thumbheight]} height of scraped actor thumb + --> + + <!-- a tab is one scrolling area, just position and draw as inside a normal area --> + <!-- just define as many tabs as needed --> + <tab name="Tab1" x="0" y="0" width="100%" height="100%" layer="2" scrollheight="{areaheight}/4"> + </tab> + + <!-- Available Variables tablabels: + {tabs[]} array with available tab labels + {tabs[title]} title of tab + {tabs[current]} true if tab is displayed currently + --> + <tablabels> + </tablabels> + +</menudetailedrecording> 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 @@ +<menudetailedtext x="0" y="0" width="100%" height="100%" fadetime="0"> + + <!-- Available Variables in tab elements: + {text} detailed text + --> + <tab name="text" x="0" y="0" width="100" height="100%" layer="1" scrollheight="{areaheight}/4"> + </tab> + +</menudetailedtext>
\ 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 @@ +<menumain x="0" y="0" width="100%" height="100%" fadetime="0"> + + <!-- Available Variables timers: + {numtimers} number of active timers (max. 15 timers will be displayed) + {numtimerconflicts} number of current timer conflicts + {timer1exists} true if timer 1 available + {timer2exists} true if timer 2 available + ... + {timer15exists} true if timer 15 available + {timers[]} array with active timers (local and remote if remotetimers plugin is in use) + {timers[title]} title of timer + {timers[datetime]} date and time of timer + {timers[recording]} true if timer is recording currently + {timers[channelname]} name of channel for which timer is created + {timers[channelnumber]} number of channel + {timers[channelid]} ChannelID of channel + {timers[channellogoexists]} true if channel logo exists + --> + <timers> + </timers> + + <!-- Available Variables discusage: + {freetime} available disc capacity in hh:mm + {freepercent} available disc capacity in percent + {usedpercent} used disc capacity in percent + {freegb} available disc capacity in gigabytes + {discalert} true if disc usage is > 95% + {vdrusagestring} localized VDR internal usage string + --> + <discusage> + </discusage> + + <!-- Available Variables devices: + {numdevices} number of available devices + {devices[]} array with available devices + {devices[num]} number of current device + {devices[type]} type of device (DVB-S, DVB-C, ...) + {devices[istuned]} true if device is currently tuned to a transponder + {devices[livetv]} true if device is currently playing livetv + {devices[recording]} true if device is currently recording + {devices[hascam]} true if device has a CAM + {devices[cam]} number of CAM + {devices[signalstrength]} signalstrength of devcie + {devices[signalquality]} signalstrength of devcie + {devices[channelnumber]} number of the currently tuned channel + {devices[channelname]} name of the currently tuned channel + {devices[channelid]} ID of the currently tuned channel + {devices[source]} source of the currently tuned channel + --> + <devices> + </devices> + + <!-- Available Variables systemload: + {load} current system load + --> + <systemload> + </systemload> + + <menuitems x="0" y="0" orientation="vertical" width="100%" height="100%" align="center" numlistelements="8"> + <!-- Available Variables main menu listelement: + {label} label of menu item + {number} number of menu item (or empty string if not set) + {icon} path of appropriate icon + {current} true if item is currently selected + {separator} true if item is a list separator + --> + <listelement> + </listelement> + <!-- additional element which is drawn for current element --> + <!-- Available Variables main menu currentelement: + {label} label of menu item + {number} number of menu item (or empty string if not set) + {icon} path of appropriate icon + --> + <currentelement delay="50" fadetime="0"> + </currentelement> + </menuitems> + +</menumain> 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 @@ +<menurecordings x="0" y="0" width="100%" height="100%" fadetime="0"> + <menuitems x="0" y="0" orientation="vertical" width="100%" height="100%" align="center" numlistelements="16"> + <!-- Available Variables recordings menu listelement: + {name} Name of recording + {date} Date of recording + {time} Time of recording + {duration} real duration of recording in minutes + {durationevent} duration of corresponding event in minutes + {current} true if item is currently selected + {new} true if recording is new + {cutted} true if recording is cutted + {folder} true if item is a folder + {numrecordingsfolder} if item is a folder, number of recordings in this folder + {newrecordingsfolder} if item is a folder, number of new recordings in this folder + {hasposterthumbnail} true if a scraped poster thumbnail is available for recording + {thumbnailbwidth} width of scraped poster thumbnail + {thumbnailheight} height of scraped poster thumbnail + {thumbnailpath} absolute path of scraped poster thumbnail + --> + <listelement> + </listelement> + <!-- additional element which is drawn for current element --> + <!-- Available Variables channels menu currentelement: + {menuitemx} x position of according menu item + {menuitemy} y position of according menu item + {menuitemwidth} width of according menu item + {menuitemheight} height of according menu item + {name} Name of recording + {shorttext} Short Text of recording + {description} Descrption of recording + {date} Date of recording + {time} Time of recording + {duration} real duration of recording in minutes + {durationevent} duration of corresponding event in minutes + {new} true if recording is new + {cutted} true if recording is cutted + {folder} true if item is a folder + {numrecordingsfolder} if item is a folder, number of recordings in this folder + {newrecordingsfolder} if item is a folder, number of new recordings in this folder + {hasposter} true if a scraped poster is available for recording + {posterwidth} width of scraped poster + {posterheight} height of scraped poster + {posterpath} absolute path of scraped poster + --> + <currentelement delay="500" fadetime="0"> + </currentelement> + </menuitems> + +</menurecordings>
\ 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 @@ +<menuschedules x="0" y="0" width="100%" height="100%" fadetime="0"> + <!-- Available Variables header: + {title} title of current menu + {vdrversion} running VDR Version + {channelnumber} Number of Channel of current event + {channelname} Name of current Channel of current event + {channellogoexists} true if a channel logo exists + {channelid} ChannelID as path to display channel logo + {whatson} true if menu "What's on" is displayed + {whatsonnow} true if menu "What's on now" is displayed + {whatsonnext} true if menu "What's on next" is displayed + --> + <header> + </header> + + <menuitems x="0" y="0" orientation="vertical" width="100%" height="100%" align="center" numlistelements="16"> + <!-- Available Variables schedules menu listelement: + {title} title of event + {shorttext} shorttext of event + {start} event start time in hh::mm + {stop} event stop time + {day} day of current event + {date} date of current event in dd.mm.yy + {running} true if event is currently running + {elapsed} elapsed time of event, if not running 0 + {duration} duration of event + {current} true if item is currently selected + {separator} true if item is a list separator + {channelid} ChannelID as path to display channel logo + {whatson} true if menu "What's on" is displayed + {whatsonnow} true if menu "What's on now" is displayed + {whatsonnext} true if menu "What's on next" is displayed + {timerpartitial} true if partitial timer is set for the event + {timerfull} true if full timer is set for the event + --> + <listelement> + </listelement> + <!-- Available Variables schedules menu currentelement: + {menuitemx} x position of according menu item + {menuitemy} y position of according menu item + {menuitemwidth} width of according menu item + {menuitemheight} height of according menu item + {title} title of event + {shorttext} shorttext of event + {description} detailed description of event + {start} event start time in hh::mm + {stop} event stop time + {day} day of current event + {date} date of current event in dd.mm.yy + {running} true if event is currently running + {elapsed} elapsed time of event, if not running 0 + {duration} duration of event + {channelid} ChannelID as path to display channel logo + {hasposter} true if a scraped poster is available for this element + {posterwidth} width of scraped poster + {posterheight} height of scraped poster + {posterpath} absolute path of scraped poster + {timerpartitial} true if partitial timer is set for the event + {timerfull} true if full timer is set for the event + {whatson} true if menu "What's on" is displayed + {whatsonnow} true if menu "What's on now" is displayed + {whatsonnext} true if menu "What's on next" is displayed + {schedule[]} array with next 10 schedules, only for whatsonnow and whatsonnext + {schedule[title]} title of event + {schedule[shorttext]} shorttext of event + {schedule[start]} start time of event in hh:mm + {schedule[stop]} stop time of event in hh:mm + --> + <currentelement delay="500" fadetime="0"> + </currentelement> + </menuitems> + +</menuschedules>
\ 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 @@ +<menusetup x="0" y="0" width="100%" height="100%" fadetime="0"> + + <menuitems x="0" y="0" orientation="vertical" width="100%" height="100%" align="center" numlistelements="16"> + <!-- Available Variables setup menu listelement: + {label} label of menu item + {number} number of menu item (or empty string if not set) + {icon} path of appropriate icon + {current} true if item is currently selected + {separator} true if item is a list separator + --> + <listelement> + </listelement> + <!-- additional element which is drawn for current element --> + <!-- Available Variables main menu currentelement: + {menuitemx} x position of according menu item + {menuitemy} y position of according menu item + {menuitemwidth} width of according menu item + {menuitemheight} height of according menu item + {label} label of menu item + {number} number of menu item (or empty string if not set) + {icon} path of appropriate icon + --> + <currentelement delay="50" fadetime="0"> + </currentelement> + </menuitems> + +</menusetup> 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 @@ +<menutimers x="0" y="0" width="100%" height="100%" fadetime="0"> + <menuitems x="0" y="0" orientation="vertical" width="100%" height="100%" align="center" numlistelements="16"> + <!-- Available Variables channels menu listelement: + {title} Title of Timer + {timerstart} Start Time of Timer in hh::mm + {timerstop} End Time of Timer in hh::mm + {day} Day (numerical) + {dayname} Day, for repeating timers days where timer is active + {channelname} Name of channel which is set for the timer + {channelid} ID of channel which is set for the timer (for dispalying channel logo) + {channelnumber} Number of channel which is set for the timer + {eventtitle} Title of corresponding event + {eventstart} Start Time of corresponding event in hh::mm + {eventstop} Stop Time of corresponding event in hh::mm + {current} true if item is currently selected + {flagactive} true if timer is active + {flaginstant} true if timer is an instant timer + {flagvps} true if timer uses VPS + {flagrecording} true if is recording currently + {flagpending} true if timer is pending + --> + <listelement> + </listelement> + <!-- additional element which is drawn for current element --> + <!-- Available Variables channels menu currentelement: + {menuitemx} x position of according menu item + {menuitemy} y position of according menu item + {menuitemwidth} width of according menu item + {menuitemheight} height of according menu item + {title} Title of Timer + {timerstart} Start Time of Timer in hh::mm + {timerstop} End Time of Timer in hh::mm + {day} Day (numerical) + {dayname} Day, for repeating timers days where timer is active + {channelname} Name of channel which is set for the timer + {channelid} ID of channel which is set for the timer (for dispalying channel logo) + {channelnumber} Number of channel which is set for the timer + {eventtitle} Title of corresponding event + {eventstart} Start Time of corresponding event in hh::mm + {eventstop} Stop Time of corresponding event in hh::mm + {eventshorttext} Short Text corresponding event + {eventdescription} Description corresponding event + {hasposter} true if a scraped poster is available for event + {posterwidth} width of scraped poster + {posterheight} height of scraped poster + {posterpath} absolute path of scraped poster + {flagactive} true if timer is active + {flaginstant} true if timer is an instant timer + {flagvps} true if timer uses VPS + {flagrecording} true if is recording currently + {flagpending} true if timer is pending + --> + <currentelement delay="500" fadetime="0"> + </currentelement> + + </menuitems> + +</menutimers>
\ 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 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE displaymessage SYSTEM "../../dtd/displaymessage.dtd">
+
+<displaymessage x="0" y="0" width="100%" height="100%" fadetime="0">
+
+ <background>
+ </background>
+
+ <!-- Available Variables message:
+ {text} message text
+ {status} true if message is a status message
+ {info} true if message is a info message
+ {warning} true if message is a warn message
+ {error} true if message is a error message
+ -->
+ <message>
+ </message>
+
+</displaymessage>
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 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE displayreplay SYSTEM "../../dtd/displayreplay.dtd"> + +<displayreplay x="0" y="0" width="100%" height="100%" fadetime="0"> + + <background> + </background> + + <backgroundmodeonly> + </backgroundmodeonly> + + <!-- Available Variables datetime: + {time} time in hh:mm + {day} day in digits + {dayleadingzero} day in digits with leading 0 + {dayname} Full name of the day + {daynameshort} Short 3 char name of the day + {month} month in digits with leading 0 + {monthname} Full name of the month + {monthnameshort} 3 letter abbrivation of month name + {year} year in yyyy + --> + <datetime> + </datetime> + + <!-- Available Variables scrapercontent: + {mediapath} Full Path of Poster or Banner to use in image path attribute + {mediawidth} width of image in pixel + {mediaheight} height of image in pixel + {isbanner} true if image is a banner, false if it is a poster + --> + <scrapercontent> + </scrapercontent> + + <!-- Available Variables rectitle: + {rectitle} Title of Recording + {recsubtitle} Subtitle of the Recording + {recdate} Date Recording in dd.mm.yy + {rectime} Time of Recording in hh:mm + --> + <rectitle> + </rectitle> + + <!-- Available Variables recinfo: + {screenwidth} width of currently displayed recording in px + {screenheight} height of currently displayed recording in px + {resolution} resolution: hd1080i, hd720p, sd576i + {aspect} screen aspect, each 4:3, 16:9 or 21:9 + {isHD} true for hd1080i and hd720p + {isWideScreen} true if aspect is 16:9 or 21:9 + --> + <recinfo> + </recinfo> + + <!-- Available Variables currenttime: + {reccurrent} Current Time in hh:mm:ss + --> + <currenttime> + </currenttime> + + <!-- Available Variables totaltime: + {rectotal} Total Time in hh:mm:ss + --> + <totaltime> + </totaltime> + + <!-- Available Variables progressbar: + {current} current frame of recording + {total} total frames of recording + --> + <progressbar> + </progressbar> + + <!-- Available Variables cutmarks: + {marks[]} array of available marks + {marks[position]} frame of current mark + {marks[endposition]} frame where startmark ends + {marks[total]} total number of frames + {marks[startmark]} true if mark is start mark + --> + <cutmarks> + </cutmarks> + + <!-- Available Variables controlicons and controliconsmodeonly: + {play} true if recording is played currently + {pause} true if recording is paused + {forward} true if fast forwarding + {forward1x} true if fast forwarding 1x (with 3 trickspeeds) + {forward2x} true if fast forwarding 2x (with 3 trickspeeds) + {forward3x} true if fast forwarding 3x (with 3 trickspeeds) + {rewind} true if rewinding + {rewind1x} true if rewinding 1x (with 3 trickspeeds) + {rewind2x} true if rewinding 2x (with 3 trickspeeds) + {rewind3x} true if rewinding 3x (with 3 trickspeeds) + --> + <controlicons> + </controlicons> + + <controliconsmodeonly> + </controliconsmodeonly> + + <!-- Available Variables jump: + {jump} time to jump to in hh:mm + --> + <jump> + </jump> + <!-- Available Variables message: + {text} message text + {status} true if message is a status message + {info} true if message is a info message + {warning} true if message is a warn message + {error} true if message is a error message + --> + <message> + </message> + +</displayreplay> 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 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE displayvolume SYSTEM "../../dtd/displayvolume.dtd"> + +<displayvolume x="0" y="0" width="100%" height="100%" fadetime="0"> + + <background> + </background> + + <!-- Available Variables volume: + {volume} current volume, range from 0 to 255 + {volumepercent} current volume in % + {maxvolume} maximal volume + {mute} true if volume is muted + --> + <volume> + </volume> + +</displayvolume> 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 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE globals SYSTEM "../../dtd/globals.dtd"> + +<globals> + <!-- + define all your needed colors here + --> + <colors> + </colors> + <!-- + these variables can be used everywhere in the templates + variabls of type int can also be used as conditions, just + set such a variable to 1 for true and 0 for false + --> + <variables> + </variables> + <!-- + translations used in the skin + --> + <translations> + </translations> + <!-- + The three Fonts FontOSD, FontFix and FontSml configured in VDR + can be used in all template "font" attributes with this tokens: + {vdrOsd} + {vdrFix} + {vdrSml} + If you like to use further fonts, just define them below. + Syntax: + <font name="tokenname">fontname</font> + These fonts can then also be used in all templates in the "font" + attribute. + if an invalid font is used in a template, vdrOsd is used as default. + --> + <fonts> + </fonts> +</globals> 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 <vdr/menu.h> +#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<string,int>("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<string,int>("numtracks", numTracks)); + if (audioChannel < 0) { + intTokens.insert(pair<string,int>("isac3", true)); + intTokens.insert(pair<string,int>("isstereo", false)); + } else { + intTokens.insert(pair<string,int>("isac3", false)); + intTokens.insert(pair<string,int>("isstereo", true)); + } + stringTokens.insert(pair<string,string>("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 <vdr/menu.h> +#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<string,string>("channelname", *name)); + stringTokens.insert(pair<string,string>("channelnumber", *number)); + stringTokens.insert(pair<string,string>("channelid", *id)); + + intTokens.insert(pair<string, int>("switching", switching)); + bool logoExisis = imgCache->LogoExists(*id); + intTokens.insert(pair<string, int>("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<string, int>("year", now->tm_year + 1900)); + intTokens.insert(pair<string, int>("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<string,string>("monthname", monthname)); + stringTokens.insert(pair<string,string>("monthnameshort", monthshort)); + stringTokens.insert(pair<string,string>("month", *cString::sprintf("%02d", now->tm_mon + 1))); + stringTokens.insert(pair<string,string>("dayleadingzero", *cString::sprintf("%02d", now->tm_mday))); + stringTokens.insert(pair<string,string>("dayname", *WeekDayNameFull(now->tm_wday))); + stringTokens.insert(pair<string,string>("daynameshort", *WeekDayName(now->tm_wday))); + stringTokens.insert(pair<string,string>("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<string, string>("start", *start)); + stringTokens.insert(pair<string, string>("stop", *stop)); + + intTokens.insert(pair<string, int>("duration", Total)); + intTokens.insert(pair<string, int>("elapsed", Current)); + intTokens.insert(pair<string, int>("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<string,string>("currenttitle", (present->Title())?present->Title():"")); + stringTokens.insert(pair<string,string>("currentsubtitle", (present->ShortText())?present->ShortText():"")); + stringTokens.insert(pair<string,string>("currentstart", *present->GetTimeString())); + stringTokens.insert(pair<string,string>("currentstop", *present->GetEndTimeString())); + + intTokens.insert(pair<string,int>("currentduration", present->Duration() / 60)); + intTokens.insert(pair<string,int>("currentelapsed", (int)round((time(NULL) - present->StartTime())/60))); + intTokens.insert(pair<string,int>("currentremaining", (int)round((present->EndTime() - time(NULL))/60))); + intTokens.insert(pair<string,int>("currentrecording", presentRecording ? 1 : 0)); + } else { + stringTokens.insert(pair<string,string>("currenttitle", "")); + stringTokens.insert(pair<string,string>("currentsubtitle", "")); + stringTokens.insert(pair<string,string>("currentstart", "")); + stringTokens.insert(pair<string,string>("currentstop", "")); + + intTokens.insert(pair<string,int>("currentduration", 0)); + intTokens.insert(pair<string,int>("currentelapsed", 0)); + intTokens.insert(pair<string,int>("currentremaining", 0)); + intTokens.insert(pair<string,int>("currentrecording", 0)); + } + + if (next) { + stringTokens.insert(pair<string,string>("nexttitle", (next->Title())?next->Title():"")); + stringTokens.insert(pair<string,string>("nextsubtitle", (next->ShortText())?next->ShortText():"")); + stringTokens.insert(pair<string,string>("nextstart", *next->GetTimeString())); + stringTokens.insert(pair<string,string>("nextstop", *next->GetEndTimeString())); + + intTokens.insert(pair<string,int>("nextduration", next->Duration() / 60)); + intTokens.insert(pair<string,int>("nextrecording", nextRecording ? 1 : 0)); + } else { + stringTokens.insert(pair<string,string>("nexttitle", "")); + stringTokens.insert(pair<string,string>("nextsubtitle", "")); + stringTokens.insert(pair<string,string>("nextstart", "")); + stringTokens.insert(pair<string,string>("nextstop", "")); + + intTokens.insert(pair<string,int>("nextduration", 0)); + intTokens.insert(pair<string,int>("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<string,int>("isRadio", isRadio)); + intTokens.insert(pair<string,int>("hasVT", hasVT)); + intTokens.insert(pair<string,int>("isStereo", isStereo)); + intTokens.insert(pair<string,int>("isDolby", isDolby)); + intTokens.insert(pair<string,int>("isEncrypted", isEncrypted)); + intTokens.insert(pair<string,int>("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<string,int>("screenwidth", screenWidth)); + intTokens.insert(pair<string,int>("screenheight", screenHeight)); + intTokens.insert(pair<string,int>("isHD", isHD)); + intTokens.insert(pair<string,int>("isWideScreen", isWideScreen)); + stringTokens.insert(pair<string,string>("resolution", resName)); + stringTokens.insert(pair<string,string>("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<string,int>("mediawidth", mediaWidth)); + intTokens.insert(pair<string,int>("mediaheight", mediaHeight)); + intTokens.insert(pair<string,int>("isbanner", isBanner)); + stringTokens.insert(pair<string,string>("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<string,int>("signalstrength", SignalStrength)); + intTokens.insert(pair<string,int>("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<string,int>("sepexists", separatorExists)); + intTokens.insert(pair<string,int>("prevAvailable", prevAvailable)); + intTokens.insert(pair<string,int>("nextAvailable", nextAvailable)); + stringTokens.insert(pair<string,string>("group", *ChannelName)); + stringTokens.insert(pair<string,string>("nextgroup", nextChannelSep)); + stringTokens.insert(pair<string,string>("prevgroup", prevChannelSep)); + stringTokens.insert(pair<string,string>("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<string,string>("text", Text)); + + intTokens.insert(pair<string,int>("status", (Type == mtStatus) ? true : false)); + intTokens.insert(pair<string,int>("info", (Type == mtInfo) ? true : false)); + intTokens.insert(pair<string,int>("warning", (Type == mtWarning) ? true : false)); + intTokens.insert(pair<string,int>("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<string,string>("title", event->Title() ? event->Title() : "")); + stringTokens.insert(pair<string,string>("shorttext", event->ShortText() ? event->ShortText() : "")); + stringTokens.insert(pair<string,string>("description", event->Description() ? event->Description() : "")); + stringTokens.insert(pair<string,string>("start", *(event->GetTimeString()))); + stringTokens.insert(pair<string,string>("stop", *(event->GetEndTimeString()))); + stringTokens.insert(pair<string,string>("day", *WeekDayName(event->StartTime()))); + stringTokens.insert(pair<string,string>("date", *ShortDateString(event->StartTime()))); + stringTokens.insert(pair<string,string>("channelid", *(event->ChannelID().ToString()))); + + bool isRunning = false; + time_t now = time(NULL); + if ((now >= event->StartTime()) && (now <= event->EndTime())) + isRunning = true; + intTokens.insert(pair<string,int>("running", isRunning)); + if (isRunning) { + intTokens.insert(pair<string,int>("elapsed", (now - event->StartTime())/60)); + } else { + intTokens.insert(pair<string,int>("elapsed", 0)); + } + intTokens.insert(pair<string,int>("duration", event->Duration() / 60)); + + vector< map< string, string > > reruns; + bool hasReruns = LoadReruns(&reruns); + loopTokens.insert(pair<string, vector< map< string, string > > >("reruns", reruns)); + + intTokens.insert(pair<string,int>("hasreruns", hasReruns)); + + SetScraperTokens(); + SetEpgPictures(event->EventID()); + + } else if (recording) { + string name = recording->Name() ? recording->Name() : ""; + stringTokens.insert(pair<string,string>("name", name)); + + const cRecordingInfo *info = recording->Info(); + if (info) { + stringTokens.insert(pair<string,string>("shorttext", info->ShortText() ? info->ShortText() : "")); + stringTokens.insert(pair<string,string>("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<string,string>("date", recDate.c_str())); + stringTokens.insert(pair<string,string>("time", recTime.c_str())); + intTokens.insert(pair<string,int>("duration", recDuration)); + intTokens.insert(pair<string,int>("durationevent", duration)); + } + } else { + stringTokens.insert(pair<string,string>("shorttext", "")); + stringTokens.insert(pair<string,string>("description", "")); + int recDuration = recording->LengthInSeconds(); + recDuration = (recDuration>0)?(recDuration / 60):0; + stringTokens.insert(pair<string,string>("date", "")); + stringTokens.insert(pair<string,string>("time", "")); + intTokens.insert(pair<string,int>("duration", recDuration)); + intTokens.insert(pair<string,int>("durationevent", 0)); + } + LoadRecordingInformation(); + SetScraperTokens(); + SetRecordingImages(recording->FileName()); + } else if (text) { + stringTokens.insert(pair<string,string>("text", text)); + } else { + intTokens.insert(pair<string,int>("running", false)); + intTokens.insert(pair<string,int>("hasreruns", false)); + } +} + +void cDisplayMenuDetailView::SetScraperTokens(void) { + static cPlugin *pScraper = GetScraperPlugin(); + if (!pScraper || (!event && !recording)) { + intTokens.insert(pair<string,int>("ismovie", false)); + intTokens.insert(pair<string,int>("isseries", false)); + return; + } + + ScraperGetEventType getType; + getType.event = event; + getType.recording = recording; + if (!pScraper->Service("GetEventType", &getType)) { + intTokens.insert(pair<string,int>("ismovie", false)); + intTokens.insert(pair<string,int>("isseries", false)); + return; + } + + if (getType.type == tMovie) { + cMovie movie; + movie.movieId = getType.movieId; + pScraper->Service("GetMovie", &movie); + intTokens.insert(pair<string,int>("ismovie", true)); + intTokens.insert(pair<string,int>("isseries", false)); + + stringTokens.insert(pair<string,string>("movietitle", movie.title)); + stringTokens.insert(pair<string,string>("movieoriginalTitle", movie.originalTitle)); + stringTokens.insert(pair<string,string>("movietagline", movie.tagline)); + stringTokens.insert(pair<string,string>("movieoverview", movie.overview)); + stringTokens.insert(pair<string,string>("moviegenres", movie.genres)); + stringTokens.insert(pair<string,string>("moviehomepage", movie.homepage)); + stringTokens.insert(pair<string,string>("moviereleasedate", movie.releaseDate)); + stringstream pop; + pop << movie.popularity; + stringTokens.insert(pair<string,string>("moviepopularity", pop.str())); + stringstream vote; + vote << movie.voteAverage; + stringTokens.insert(pair<string,string>("movievoteaverage", pop.str())); + stringTokens.insert(pair<string,string>("posterpath", movie.poster.path)); + stringTokens.insert(pair<string,string>("fanartpath", movie.fanart.path)); + stringTokens.insert(pair<string,string>("collectionposterpath", movie.collectionPoster.path)); + stringTokens.insert(pair<string,string>("collectionfanartpath", movie.collectionFanart.path)); + + intTokens.insert(pair<string,int>("movieadult", movie.adult)); + intTokens.insert(pair<string,int>("moviebudget", movie.budget)); + intTokens.insert(pair<string,int>("movierevenue", movie.revenue)); + intTokens.insert(pair<string,int>("movieruntime", movie.runtime)); + intTokens.insert(pair<string,int>("posterwidth", movie.poster.width)); + intTokens.insert(pair<string,int>("posterheight", movie.poster.height)); + intTokens.insert(pair<string,int>("fanartwidth", movie.fanart.width)); + intTokens.insert(pair<string,int>("fanartheight", movie.fanart.height)); + intTokens.insert(pair<string,int>("collectionposterwidth", movie.collectionPoster.width)); + intTokens.insert(pair<string,int>("collectionposterheight", movie.collectionPoster.height)); + intTokens.insert(pair<string,int>("collectionfanartwidth", movie.collectionFanart.width)); + intTokens.insert(pair<string,int>("collectionfanartheight", movie.collectionFanart.height)); + + vector< map< string, string > > actors; + for (vector<cActor>::iterator act = movie.actors.begin(); act != movie.actors.end(); act++) { + map< string, string > actor; + actor.insert(pair<string, string>("actors[name]", (*act).name)); + actor.insert(pair<string, string>("actors[role]", (*act).role)); + actor.insert(pair<string, string>("actors[thumb]", (*act).actorThumb.path)); + stringstream actWidth, actHeight; + actWidth << (*act).actorThumb.width; + actHeight << (*act).actorThumb.height; + actor.insert(pair<string, string>("actors[thumbwidth]", actWidth.str())); + actor.insert(pair<string, string>("actors[thumbheight]", actHeight.str())); + actors.push_back(actor); + } + loopTokens.insert(pair<string, vector< map< string, string > > >("actors", actors)); + + } else if (getType.type == tSeries) { + cSeries series; + series.seriesId = getType.seriesId; + series.episodeId = getType.episodeId; + pScraper->Service("GetSeries", &series); + intTokens.insert(pair<string,int>("ismovie", false)); + intTokens.insert(pair<string,int>("isseries", true)); + //Series Basics + stringTokens.insert(pair<string,string>("seriesname", series.name)); + stringTokens.insert(pair<string,string>("seriesoverview", series.overview)); + stringTokens.insert(pair<string,string>("seriesfirstaired", series.firstAired)); + stringTokens.insert(pair<string,string>("seriesnetwork", series.network)); + stringTokens.insert(pair<string,string>("seriesgenre", series.genre)); + stringstream rating; + rating << series.rating; + stringTokens.insert(pair<string,string>("seriesrating", rating.str())); + stringTokens.insert(pair<string,string>("seriesstatus", series.status)); + //Episode Information + intTokens.insert(pair<string,int>("episodenumber", series.episode.number)); + intTokens.insert(pair<string,int>("episodeseason", series.episode.season)); + stringTokens.insert(pair<string,string>("episodetitle", series.episode.name)); + stringTokens.insert(pair<string,string>("episodefirstaired", series.episode.firstAired)); + stringTokens.insert(pair<string,string>("episodegueststars", series.episode.guestStars)); + stringTokens.insert(pair<string,string>("episodeoverview", series.episode.overview)); + stringstream eprating; + eprating << series.episode.rating; + stringTokens.insert(pair<string,string>("episoderating", eprating.str())); + intTokens.insert(pair<string,int>("episodeimagewidth", series.episode.episodeImage.width)); + intTokens.insert(pair<string,int>("episodeimageheight", series.episode.episodeImage.height)); + stringTokens.insert(pair<string,string>("episodeimagepath", series.episode.episodeImage.path)); + //Seasonposter + intTokens.insert(pair<string,int>("seasonposterwidth", series.seasonPoster.width)); + intTokens.insert(pair<string,int>("seasonposterheight", series.seasonPoster.height)); + stringTokens.insert(pair<string,string>("seasonposterpath", series.seasonPoster.path)); + + //Posters + int current = 1; + for(vector<cTvMedia>::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<string,int>(labelWidth.str(), (*poster).width)); + intTokens.insert(pair<string,int>(labelHeight.str(), (*poster).height)); + stringTokens.insert(pair<string,string>(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<string,int>(labelWidth.str(), 0)); + intTokens.insert(pair<string,int>(labelHeight.str(), 0)); + stringTokens.insert(pair<string,string>(labelPath.str(), "")); + } + } + + //Banners + current = 1; + for(vector<cTvMedia>::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<string,int>(labelWidth.str(), (*banner).width)); + intTokens.insert(pair<string,int>(labelHeight.str(), (*banner).height)); + stringTokens.insert(pair<string,string>(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<string,int>(labelWidth.str(), 0)); + intTokens.insert(pair<string,int>(labelHeight.str(), 0)); + stringTokens.insert(pair<string,string>(labelPath.str(), "")); + } + } + + //Fanarts + current = 1; + for(vector<cTvMedia>::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<string,int>(labelWidth.str(), (*fanart).width)); + intTokens.insert(pair<string,int>(labelHeight.str(), (*fanart).height)); + stringTokens.insert(pair<string,string>(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<string,int>(labelWidth.str(), 0)); + intTokens.insert(pair<string,int>(labelHeight.str(), 0)); + stringTokens.insert(pair<string,string>(labelPath.str(), "")); + } + } + + //Actors + vector< map< string, string > > actors; + for (vector<cActor>::iterator act = series.actors.begin(); act != series.actors.end(); act++) { + map< string, string > actor; + actor.insert(pair<string, string>("actors[name]", (*act).name)); + actor.insert(pair<string, string>("actors[role]", (*act).role)); + actor.insert(pair<string, string>("actors[thumb]", (*act).actorThumb.path)); + stringstream actWidth, actHeight; + actWidth << (*act).actorThumb.width; + actHeight << (*act).actorThumb.height; + actor.insert(pair<string, string>("actors[thumbwidth]", actWidth.str())); + actor.insert(pair<string, string>("actors[thumbheight]", actHeight.str())); + actors.push_back(actor); + } + loopTokens.insert(pair<string, vector< map< string, string > > >("actors", actors)); + + } else { + intTokens.insert(pair<string,int>("ismovie", false)); + intTokens.insert(pair<string,int>("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<Epgsearch_searchresults_v1_0::cServiceSearchResult>* 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<string, string>("reruns[title]", r->event->Title() ? r->event->Title() : "")); + rerun.insert(pair<string, string>("reruns[shorttext]", r->event->ShortText() ? r->event->ShortText() : "")); + rerun.insert(pair<string, string>("reruns[start]", *(r->event->GetTimeString()))); + rerun.insert(pair<string, string>("reruns[start]", *(r->event->GetTimeString()))); + rerun.insert(pair<string, string>("reruns[stop]", *(r->event->GetEndTimeString()))); + rerun.insert(pair<string, string>("reruns[date]", *ShortDateString(r->event->StartTime()))); + rerun.insert(pair<string, string>("reruns[day]", *WeekDayName(r->event->StartTime()))); + string channelID = *(r->event->ChannelID().ToString()); + rerun.insert(pair<string, string>("reruns[channelid]", channelID)); + bool logoExists = imgCache->LogoExists(channelID); + rerun.insert(pair<string, string>("reruns[channellogoexists]", logoExists ? "1" : "0")); + + cChannel *channel = Channels.GetByChannelID(r->event->ChannelID(), true, true); + if (channel) { + stringstream channelNumber; + channelNumber << channel->Number(); + rerun.insert(pair<string, string>("reruns[channelname]", channel->ShortName(true))); + rerun.insert(pair<string, string>("reruns[channelnumber]", channelNumber.str())); + } else { + rerun.insert(pair<string, string>("reruns[channelname]", "")); + rerun.insert(pair<string, string>("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<string,string>("recordingsize", *strRecSize)); + stringTokens.insert(pair<string,string>("recordingsizecutted", *strRecSizeCut)); + } else { + stringTokens.insert(pair<string,string>("recordingsize", "")); + stringTokens.insert(pair<string,string>("recordingsizecutted", "")); + } + + cChannel *channel = Channels.GetByChannelID(Info->ChannelID()); + if (channel) { + stringTokens.insert(pair<string,string>("recchannelname", channel->Name())); + intTokens.insert(pair<string,int>("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<string,string>("recordinglength", strLength)); + stringTokens.insert(pair<string,string>("recordinglengthcutted", strLengthCutted)); + stringTokens.insert(pair<string,string>("recordingbitrate", strBitrate)); + } + delete index; + } + + string recFormat = recording->IsPesRecording() ? "PES" : "TS"; + stringTokens.insert(pair<string,string>("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<string,string>("searchtimer", searchTimer)); + searchTimerFound = true; + } + } + } + } + if (!searchTimerFound) + stringTokens.insert(pair<string,string>("searchtimer", "n.a.")); +} + +string cDisplayMenuDetailView::StripXmlTag(string &Line, const char *Tag) { + // set the search strings + stringstream strStart, strStop; + strStart << "<" << Tag << ">"; + strStop << "</" << Tag << ">"; + // 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<string,int>(available.str(), true)); + stringTokens.insert(pair<string,string>(path.str(), *cString::sprintf("%s%s.jpg", *config.epgImagePath, picName.str().c_str()))); + } else { + intTokens.insert(pair<string,int>(available.str(), false)); + stringTokens.insert(pair<string,string>(path.str(), "")); + } + } +} + +void cDisplayMenuDetailView::SetRecordingImages(const char *recPath) { + if (!recPath) { + intTokens.insert(pair<string,int>("recimg1avaialble", false)); + intTokens.insert(pair<string,int>("recimg2avaialble", false)); + intTokens.insert(pair<string,int>("recimg3avaialble", false)); + stringTokens.insert(pair<string,string>("recimg1path", "")); + stringTokens.insert(pair<string,string>("recimg2path", "")); + stringTokens.insert(pair<string,string>("recimg3path", "")); + return; + } + + string path = recPath; + DIR *dirHandle; + struct dirent *dirEntry; + dirHandle = opendir(recPath); + if (!dirHandle) { + intTokens.insert(pair<string,int>("recimg1avaialble", false)); + intTokens.insert(pair<string,int>("recimg2avaialble", false)); + intTokens.insert(pair<string,int>("recimg3avaialble", false)); + stringTokens.insert(pair<string,string>("recimg1path", "")); + stringTokens.insert(pair<string,string>("recimg2path", "")); + stringTokens.insert(pair<string,string>("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<string,int>(available.str(), true)); + stringTokens.insert(pair<string,string>(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<string,int>(available.str(), false)); + stringTokens.insert(pair<string,string>(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<string,int>("ismovie", false)); + headerIntTokens.insert(pair<string,int>("isseries", false)); + headerIntTokens.insert(pair<string,int>("posteravailable", false)); + headerIntTokens.insert(pair<string,int>("banneravailable", false)); + } else { + ScraperGetEventType getType; + getType.event = event; + getType.recording = recording; + if (!pScraper->Service("GetEventType", &getType)) { + headerIntTokens.insert(pair<string,int>("ismovie", false)); + headerIntTokens.insert(pair<string,int>("isseries", false)); + headerIntTokens.insert(pair<string,int>("posteravailable", false)); + headerIntTokens.insert(pair<string,int>("banneravailable", false)); + } else { + if (getType.type == tMovie) { + cMovie movie; + movie.movieId = getType.movieId; + pScraper->Service("GetMovie", &movie); + headerIntTokens.insert(pair<string,int>("ismovie", true)); + headerIntTokens.insert(pair<string,int>("isseries", false)); + headerIntTokens.insert(pair<string,int>("posteravailable", true)); + headerIntTokens.insert(pair<string,int>("banneravailable", false)); + headerStringTokens.insert(pair<string,string>("posterpath", movie.poster.path)); + headerIntTokens.insert(pair<string,int>("posterwidth", movie.poster.width)); + headerIntTokens.insert(pair<string,int>("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<string,int>("ismovie", false)); + headerIntTokens.insert(pair<string,int>("isseries", true)); + vector<cTvMedia>::iterator poster = series.posters.begin(); + if (poster != series.posters.end()) { + headerIntTokens.insert(pair<string,int>("posterwidth", (*poster).width)); + headerIntTokens.insert(pair<string,int>("posterheight", (*poster).height)); + headerStringTokens.insert(pair<string,string>("posterpath", (*poster).path)); + headerIntTokens.insert(pair<string,int>("posteravailable", true)); + } else { + headerIntTokens.insert(pair<string,int>("posterwidth", 0)); + headerIntTokens.insert(pair<string,int>("posterheight", 0)); + headerStringTokens.insert(pair<string,string>("posterpath", "")); + headerIntTokens.insert(pair<string,int>("posteravailable", false)); + } + vector<cTvMedia>::iterator banner = series.banners.begin(); + if (banner != series.banners.end()) { + headerIntTokens.insert(pair<string,int>("bannerwidth", (*banner).width)); + headerIntTokens.insert(pair<string,int>("bannerheight", (*banner).height)); + headerStringTokens.insert(pair<string,string>("bannerpath", (*banner).path)); + headerIntTokens.insert(pair<string,int>("banneravailable", true)); + } else { + headerIntTokens.insert(pair<string,int>("bannerwidth", 0)); + headerIntTokens.insert(pair<string,int>("bannerheight", 0)); + headerStringTokens.insert(pair<string,string>("bannerpath", "")); + headerIntTokens.insert(pair<string,int>("banneravailable", false)); + } + } else { + headerIntTokens.insert(pair<string,int>("ismovie", false)); + headerIntTokens.insert(pair<string,int>("isseries", false)); + headerIntTokens.insert(pair<string,int>("posteravailable", false)); + headerIntTokens.insert(pair<string,int>("banneravailable", false)); + } + } + } + } + + if (event) { + headerStringTokens.insert(pair<string,string>("title", event->Title() ? event->Title() : "")); + headerStringTokens.insert(pair<string,string>("shorttext", event->ShortText() ? event->ShortText() : "")); + headerStringTokens.insert(pair<string,string>("start", *(event->GetTimeString()))); + headerStringTokens.insert(pair<string,string>("stop", *(event->GetEndTimeString()))); + headerStringTokens.insert(pair<string,string>("day", *WeekDayName(event->StartTime()))); + headerStringTokens.insert(pair<string,string>("date", *ShortDateString(event->StartTime()))); + headerStringTokens.insert(pair<string,string>("channelid", *(event->ChannelID().ToString()))); + + bool isRunning = false; + time_t now = time(NULL); + if ((now >= event->StartTime()) && (now <= event->EndTime())) + isRunning = true; + headerIntTokens.insert(pair<string,int>("running", isRunning)); + if (isRunning) { + headerIntTokens.insert(pair<string,int>("elapsed", (now - event->StartTime())/60)); + } else { + headerIntTokens.insert(pair<string,int>("elapsed", 0)); + } + headerIntTokens.insert(pair<string,int>("duration", event->Duration() / 60)); + + stringstream epgImageName; + epgImageName << event->EventID(); + bool epgPicAvailable = FileExists(*config.epgImagePath, epgImageName.str(), "jpg"); + if (epgPicAvailable) { + headerIntTokens.insert(pair<string,int>("epgpicavailable", true)); + headerStringTokens.insert(pair<string,string>("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<string,int>("epgpicavailable", true)); + headerStringTokens.insert(pair<string,string>("epgpicpath", *cString::sprintf("%s%s.jpg", *config.epgImagePath, epgImageName.str().c_str()))); + } else { + headerIntTokens.insert(pair<string,int>("epgpicavailable", false)); + headerStringTokens.insert(pair<string,string>("epgpicpath", "")); + } + } + + DrawViewElement(veDetailHeader, &headerStringTokens, &headerIntTokens); + } else if (recording) { + string name = recording->Name() ? recording->Name() : ""; + headerStringTokens.insert(pair<string,string>("name", name)); + + const cRecordingInfo *info = recording->Info(); + if (info) { + headerStringTokens.insert(pair<string,string>("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<string,string>("date", recDate.c_str())); + headerStringTokens.insert(pair<string,string>("time", recTime.c_str())); + headerIntTokens.insert(pair<string,int>("duration", recDuration)); + headerIntTokens.insert(pair<string,int>("durationevent", duration)); + } + } else { + headerStringTokens.insert(pair<string,string>("shorttext", "")); + int recDuration = recording->LengthInSeconds(); + recDuration = (recDuration>0)?(recDuration / 60):0; + headerStringTokens.insert(pair<string,string>("date", "")); + headerStringTokens.insert(pair<string,string>("time", "")); + headerIntTokens.insert(pair<string,int>("duration", recDuration)); + headerIntTokens.insert(pair<string,int>("durationevent", 0)); + } + + string recImage = ""; + string path = recording->FileName() ? recording->FileName() : ""; + string extension = ".jpg"; + if (FirstFileInFolder(path, extension, recImage)) { + headerIntTokens.insert(pair<string,int>("recimgavailable", true)); + headerStringTokens.insert(pair<string,string>("recimgpath", *cString::sprintf("%s/%s", path.c_str(), recImage.c_str()))); + } else { + headerIntTokens.insert(pair<string,int>("recimgavailable", false)); + headerStringTokens.insert(pair<string,string>("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<string,int>("height", barHeight)); + scrollbarIntTokens.insert(pair<string,int>("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<cTemplateViewTab*>::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 <list> +#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<cTemplateViewTab*> activeTabs; + list<cTemplateViewTab*>::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<string,int>("menuitemx", posMenuItem.X())); + intTokens.insert(pair<string,int>("menuitemy", posMenuItem.Y())); + intTokens.insert(pair<string,int>("menuitemwidth", posMenuItem.Width())); + intTokens.insert(pair<string,int>("menuitemheight", posMenuItem.Height())); +} + +void cDisplayMenuItemCurrentView::SetScraperPoster(const cEvent *event, const cRecording *recording) { + static cPlugin *pScraper = GetScraperPlugin(); + if (!pScraper || (!event && !recording)) { + intTokens.insert(pair<string,int>("hasposter", false)); + intTokens.insert(pair<string,int>("posterwidth", -1)); + intTokens.insert(pair<string,int>("posterheight", -1)); + stringTokens.insert(pair<string,string>("posterpath", "")); + return; + } + + ScraperGetPoster call; + call.event = event; + call.recording = recording; + if (pScraper->Service("GetPoster", &call)) { + intTokens.insert(pair<string,int>("hasposter", true)); + intTokens.insert(pair<string,int>("posterwidth", call.poster.width)); + intTokens.insert(pair<string,int>("posterheight", call.poster.height)); + stringTokens.insert(pair<string,string>("posterpath", call.poster.path)); + } else { + intTokens.insert(pair<string,int>("hasposter", false)); + intTokens.insert(pair<string,int>("posterwidth", -1)); + intTokens.insert(pair<string,int>("posterheight", -1)); + stringTokens.insert(pair<string,string>("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<string,string>("number", number)); + stringTokens.insert(pair<string,string>("label", label)); + stringTokens.insert(pair<string,string>("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<string,int>("whatson", (cat == mcSchedule) ? true: false)); + intTokens.insert(pair<string,int>("whatsonnow", (cat == mcScheduleNow) ? true: false)); + intTokens.insert(pair<string,int>("whatsonnext", (cat == mcScheduleNext) ? true: false)); + if (timerMatch == tmFull) { + intTokens.insert(pair<string,int>("timerpartitial", false)); + intTokens.insert(pair<string,int>("timerfull", true)); + } else if (timerMatch == tmPartial) { + intTokens.insert(pair<string,int>("timerpartitial", true)); + intTokens.insert(pair<string,int>("timerfull", false)); + } else { + intTokens.insert(pair<string,int>("timerpartitial", false)); + intTokens.insert(pair<string,int>("timerfull", false)); + } + + if (event) { + stringTokens.insert(pair<string,string>("title", event->Title() ? event->Title() : "")); + stringTokens.insert(pair<string,string>("shorttext", event->ShortText() ? event->ShortText() : "")); + stringTokens.insert(pair<string,string>("description", event->Description() ? event->Description() : "")); + stringTokens.insert(pair<string,string>("start", *(event->GetTimeString()))); + stringTokens.insert(pair<string,string>("stop", *(event->GetEndTimeString()))); + stringTokens.insert(pair<string,string>("day", *WeekDayName(event->StartTime()))); + stringTokens.insert(pair<string,string>("date", *ShortDateString(event->StartTime()))); + bool isRunning = false; + time_t now = time(NULL); + if ((now >= event->StartTime()) && (now <= event->EndTime())) + isRunning = true; + intTokens.insert(pair<string,int>("running", isRunning)); + if (isRunning) { + intTokens.insert(pair<string,int>("elapsed", (now - event->StartTime())/60)); + } else { + intTokens.insert(pair<string,int>("elapsed", 0)); + } + intTokens.insert(pair<string,int>("duration", event->Duration() / 60)); + SetScraperPoster(event); + } + if (channel) { + stringTokens.insert(pair<string,string>("channelid", *(channel->GetChannelID().ToString()))); + } + + vector< map<string,string> > schedulesTokens; + if (cat == mcScheduleNow || cat == mcScheduleNext) { + ReadSchedules(&schedulesTokens); + } + map < string, vector< map< string, string > > > loopTokens; + loopTokens.insert(pair<string, vector< map< string, string > > >("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<string,string> > *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<string,string> element; + element.insert(pair<string,string>("schedule[start]", *(curEvent->GetTimeString()))); + element.insert(pair<string,string>("schedule[stop]", *(curEvent->GetEndTimeString()))); + element.insert(pair<string,string>("schedule[title]", curEvent->Title() ? curEvent->Title() : "")); + element.insert(pair<string,string>("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<string,int>("number", channel->Number())); + intTokens.insert(pair<string,int>("transponder", channel->Transponder())); + intTokens.insert(pair<string,int>("frequency", channel->Frequency())); + + stringTokens.insert(pair<string,string>("name", channel->Name() ? channel->Name() : "")); + stringTokens.insert(pair<string,string>("channelid", *(channel->GetChannelID().ToString()))); + + //Channel Source Information + const cSource *source = Sources.Get(channel->Source()); + if (source) { + stringTokens.insert(pair<string,string>("source", *cSource::ToString(source->Code()))); + stringTokens.insert(pair<string,string>("sourcedescription", source->Description() ? source->Description() : "")); + stringTokens.insert(pair<string,string>("source", *cSource::ToString(source->Code()))); + intTokens.insert(pair<string,int>("isAtsc", source->IsAtsc(source->Code()))); + intTokens.insert(pair<string,int>("isCable", source->IsCable(source->Code()))); + intTokens.insert(pair<string,int>("isSat", source->IsSat(source->Code()))); + intTokens.insert(pair<string,int>("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<string,string>("presenteventtitle", presentEvent->Title() ? presentEvent->Title() : "")); + stringTokens.insert(pair<string,string>("presenteventshorttext", presentEvent->ShortText() ? presentEvent->ShortText() : "")); + stringTokens.insert(pair<string,string>("presenteventdescription", presentEvent->Description() ? presentEvent->Description() : "")); + stringTokens.insert(pair<string,string>("presenteventstart", *presentEvent->GetTimeString())); + stringTokens.insert(pair<string,string>("presenteventstop", *presentEvent->GetEndTimeString())); + stringTokens.insert(pair<string,string>("presenteventday", *WeekDayName(presentEvent->StartTime()))); + stringTokens.insert(pair<string,string>("presenteventdate", *ShortDateString(presentEvent->StartTime()))); + intTokens.insert(pair<string,int>("presenteventelapsed", (time(0) - presentEvent->StartTime())/60)); + intTokens.insert(pair<string,int>("presenteventduration", presentEvent->Duration() / 60)); + SetScraperPoster(presentEvent); + } else { + stringTokens.insert(pair<string,string>("presenteventtitle", "")); + stringTokens.insert(pair<string,string>("presenteventshorttext", "")); + stringTokens.insert(pair<string,string>("presenteventdescription", "")); + stringTokens.insert(pair<string,string>("presenteventstart", "")); + stringTokens.insert(pair<string,string>("presenteventstop", "")); + stringTokens.insert(pair<string,string>("presenteventday", "")); + stringTokens.insert(pair<string,string>("presenteventdate", "")); + intTokens.insert(pair<string,int>("presenteventelapsed", 0)); + intTokens.insert(pair<string,int>("presenteventduration", 0)); + } + const cList<cEvent> *events = schedule->Events(); + bool inserted = false; + if (events && presentEvent) { + const cEvent *nextEvent = events->Next(presentEvent); + if (nextEvent) { + stringTokens.insert(pair<string,string>("nexteventtitle", nextEvent->Title() ? nextEvent->Title() : "")); + stringTokens.insert(pair<string,string>("nexteventshorttext", nextEvent->ShortText() ? nextEvent->ShortText() : "")); + stringTokens.insert(pair<string,string>("nexteventdescription", nextEvent->Description() ? nextEvent->Description() : "")); + stringTokens.insert(pair<string,string>("nexteventstart", *nextEvent->GetTimeString())); + stringTokens.insert(pair<string,string>("nexteventstop", *nextEvent->GetEndTimeString())); + stringTokens.insert(pair<string,string>("nexteventday", *WeekDayName(nextEvent->StartTime()))); + stringTokens.insert(pair<string,string>("nexteventdate", *ShortDateString(nextEvent->StartTime()))); + intTokens.insert(pair<string,int>("nexteventduration", nextEvent->Duration() / 60)); + inserted = true; + } + } + if (!inserted) { + stringTokens.insert(pair<string,string>("nexteventtitle", "")); + stringTokens.insert(pair<string,string>("nexteventshorttext", "")); + stringTokens.insert(pair<string,string>("nexteventdescription", "")); + stringTokens.insert(pair<string,string>("nexteventstart", "")); + stringTokens.insert(pair<string,string>("nexteventstop", "")); + stringTokens.insert(pair<string,string>("nexteventday", "")); + stringTokens.insert(pair<string,string>("nexteventdate", "")); + intTokens.insert(pair<string,int>("nexteventduration", 0)); + } + } + + vector< map<string,string> > schedulesTokens; + ReadSchedules(&schedulesTokens); + + map < string, vector< map< string, string > > > loopTokens; + loopTokens.insert(pair<string, vector< map< string, string > > >("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<string,string> > *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<string,string> element; + element.insert(pair<string,string>("schedule[start]", *(curEvent->GetTimeString()))); + element.insert(pair<string,string>("schedule[stop]", *(curEvent->GetEndTimeString()))); + element.insert(pair<string,string>("schedule[title]", curEvent->Title() ? curEvent->Title() : "")); + element.insert(pair<string,string>("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<string,int>("flagactive", timer->HasFlags(tfActive))); + intTokens.insert(pair<string,int>("flaginstant", timer->HasFlags(tfInstant))); + intTokens.insert(pair<string,int>("flagvps", timer->HasFlags(tfVps))); + intTokens.insert(pair<string,int>("flagrecording", timer->Recording())); + intTokens.insert(pair<string,int>("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<string,string>("title", file)); + stringTokens.insert(pair<string,string>("timerstart", *cString::sprintf("%02d:%02d", timer->Start() / 100, timer->Start() % 100))); + stringTokens.insert(pair<string,string>("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<string,string>("day", day)); + stringTokens.insert(pair<string,string>("dayname", dayName)); + + const cChannel *channel = timer->Channel(); + if (channel) { + stringTokens.insert(pair<string,string>("channelname", channel->Name() ? channel->Name() : "")); + stringTokens.insert(pair<string,string>("channelid", *(channel->GetChannelID().ToString()))); + intTokens.insert(pair<string,int>("channelnumber", channel->Number())); + } else { + stringTokens.insert(pair<string,string>("channelname", "")); + stringTokens.insert(pair<string,string>("channelid", "")); + intTokens.insert(pair<string,int>("channelnumber", 0)); + } + + const cEvent *event = timer->Event(); + if (event) { + stringTokens.insert(pair<string,string>("eventtitle", event->Title() ? event->Title() : "")); + stringTokens.insert(pair<string,string>("eventstart", *event->GetTimeString())); + stringTokens.insert(pair<string,string>("eventstop", *event->GetEndTimeString())); + stringTokens.insert(pair<string,string>("eventshorttext", event->ShortText() ? event->ShortText() : "")); + stringTokens.insert(pair<string,string>("eventdescription", event->Description() ? event->Description() : "")); + SetScraperPoster(event); + } else { + stringTokens.insert(pair<string,string>("eventtitle", "")); + stringTokens.insert(pair<string,string>("eventtitle", "")); + stringTokens.insert(pair<string,string>("eventstop", "")); + stringTokens.insert(pair<string,string>("eventshorttext", "")); + stringTokens.insert(pair<string,string>("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<string,int>("folder", isFolder)); + + string name = recording->Name() ? recording->Name() : ""; + string buffer = ""; + try { + vector<string> 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<string,string>("name", buffer.c_str())); + intTokens.insert(pair<string,int>("new", recording->IsNew())); + intTokens.insert(pair<string,int>("newrecordingsfolder", newRecs)); + intTokens.insert(pair<string,int>("numrecordingsfolder", total)); + intTokens.insert(pair<string,int>("cutted", recording->IsEdited())); + + SetScraperPoster(NULL, recording); + + const cRecordingInfo *info = recording->Info(); + if (!info) return; + + stringTokens.insert(pair<string,string>("shorttext", info->ShortText() ? info->ShortText() : "")); + stringTokens.insert(pair<string,string>("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<string,string>("date", recDate.c_str())); + stringTokens.insert(pair<string,string>("time", recTime.c_str())); + intTokens.insert(pair<string,int>("duration", recDuration)); + intTokens.insert(pair<string,int>("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<string,string> > *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<string,string> > *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 <sstream>
+#include <algorithm>
+
+/*************************************************************
+* 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<string,int>("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<maxTabs; i++) {
+ stringstream name;
+ name << "column" << (i+1);
+ stringstream nameUsed;
+ nameUsed << name.str() << "set";
+ stringstream nameX;
+ nameX << name.str() << "x";
+ stringstream nameWidth;
+ nameWidth << name.str() << "width";
+ stringTokens.insert(pair<string,string>(name.str(), tabTexts[i]));
+ if (i>0)
+ intTokens.insert(pair<string,int>(nameUsed.str(), (tabTexts[i].size() > 0) ? 1 : 0 ));
+ intTokens.insert(pair<string,int>(nameX.str(), tabs[i]));
+ intTokens.insert(pair<string,int>(nameWidth.str(), tabWidths[i]));
+ }
+ intTokens.insert(pair<string,int>("current", current));
+ intTokens.insert(pair<string,int>("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<maxTabs; i++) {
+ esyslog("skindesigner: tab %d: text: %s, x: %d", i, tabTexts[i].c_str(), tabs[i]);
+ }
+}
+
+/*************************************************************
+* Private Functions
+*************************************************************/
+
+
+/*************************************************************
+* cDisplayMenuItemMainView
+*************************************************************/
+
+cDisplayMenuItemMainView::cDisplayMenuItemMainView(cTemplateViewList *tmplList, string itemText, bool current, bool selectable)
+ : cDisplayMenuItemView(tmplList, current, selectable) {
+ text = itemText;
+ number = "";
+ label = "";
+ icon = "";
+}
+
+cDisplayMenuItemMainView::~cDisplayMenuItemMainView() {
+}
+
+void cDisplayMenuItemMainView::SetTokens(void) {
+ if (!itemInit)
+ return;
+ itemInit = false;
+ stringTokens.insert(pair<string,string>("number", number));
+ stringTokens.insert(pair<string,string>("label", label));
+ stringTokens.insert(pair<string,string>("icon", icon));
+
+ intTokens.insert(pair<string,int>("current", current));
+ intTokens.insert(pair<string,int>("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<string,int>("current", current));
+ intTokens.insert(pair<string,int>("separator", !selectable));
+ intTokens.insert(pair<string,int>("whatson", (cat == mcSchedule) ? true: false));
+ intTokens.insert(pair<string,int>("whatsonnow", (cat == mcScheduleNow) ? true: false));
+ intTokens.insert(pair<string,int>("whatsonnext", (cat == mcScheduleNext) ? true: false));
+ if (timerMatch == tmFull) {
+ intTokens.insert(pair<string,int>("timerpartitial", false));
+ intTokens.insert(pair<string,int>("timerfull", true));
+ } else if (timerMatch == tmPartial) {
+ intTokens.insert(pair<string,int>("timerpartitial", true));
+ intTokens.insert(pair<string,int>("timerfull", false));
+ } else {
+ intTokens.insert(pair<string,int>("timerpartitial", false));
+ intTokens.insert(pair<string,int>("timerfull", false));
+ }
+
+ if (event) {
+ if (selectable) {
+ stringTokens.insert(pair<string,string>("title", event->Title() ? event->Title() : ""));
+ stringTokens.insert(pair<string,string>("shorttext", event->ShortText() ? event->ShortText() : ""));
+ stringTokens.insert(pair<string,string>("start", *(event->GetTimeString())));
+ stringTokens.insert(pair<string,string>("stop", *(event->GetEndTimeString())));
+ stringTokens.insert(pair<string,string>("day", *WeekDayName(event->StartTime())));
+ stringTokens.insert(pair<string,string>("date", *ShortDateString(event->StartTime())));
+ bool isRunning = false;
+ time_t now = time(NULL);
+ if ((now >= event->StartTime()) && (now <= event->EndTime()))
+ isRunning = true;
+ intTokens.insert(pair<string,int>("running", isRunning));
+ if (isRunning) {
+ intTokens.insert(pair<string,int>("elapsed", (now - event->StartTime())/60));
+ } else {
+ intTokens.insert(pair<string,int>("elapsed", 0));
+ }
+ intTokens.insert(pair<string,int>("duration", event->Duration() / 60));
+ } else {
+ stringTokens.insert(pair<string,string>("title", event->Title() ? ParseSeparator(event->Title()) : ""));
+ }
+ }
+ if (channel) {
+ stringTokens.insert(pair<string,string>("channelid", *(channel->GetChannelID().ToString())));
+ if (!event && !selectable) {
+ stringTokens.insert(pair<string,string>("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<string,int>("current", current));
+ intTokens.insert(pair<string,int>("separator", !selectable));
+ intTokens.insert(pair<string,int>("number", channel->Number()));
+ intTokens.insert(pair<string,int>("transponder", channel->Transponder()));
+ intTokens.insert(pair<string,int>("frequency", channel->Frequency()));
+
+ stringTokens.insert(pair<string,string>("name", channel->Name() ? channel->Name() : ""));
+ stringTokens.insert(pair<string,string>("channelid", *(channel->GetChannelID().ToString())));
+
+ //Channel Source Information
+ const cSource *source = Sources.Get(channel->Source());
+ if (source) {
+ stringTokens.insert(pair<string,string>("source", *cSource::ToString(source->Code())));
+ stringTokens.insert(pair<string,string>("sourcedescription", source->Description() ? source->Description() : ""));
+ stringTokens.insert(pair<string,string>("source", *cSource::ToString(source->Code())));
+ intTokens.insert(pair<string,int>("isAtsc", source->IsAtsc(source->Code())));
+ intTokens.insert(pair<string,int>("isCable", source->IsCable(source->Code())));
+ intTokens.insert(pair<string,int>("isSat", source->IsSat(source->Code())));
+ intTokens.insert(pair<string,int>("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<string,string>("presenteventtitle", presentEvent->Title() ? presentEvent->Title() : ""));
+ stringTokens.insert(pair<string,string>("presenteventstart", *presentEvent->GetTimeString()));
+ stringTokens.insert(pair<string,string>("presenteventstop", *presentEvent->GetEndTimeString()));
+ inserted = true;
+ }
+ }
+ if (!inserted) {
+ stringTokens.insert(pair<string,string>("presenteventtitle", ""));
+ stringTokens.insert(pair<string,string>("presenteventstart", ""));
+ stringTokens.insert(pair<string,string>("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<string,int>("flagactive", timer->HasFlags(tfActive)));
+ return;
+ }
+ itemInit = false;
+
+ intTokens.insert(pair<string,int>("current", current));
+ intTokens.insert(pair<string,int>("flagactive", timer->HasFlags(tfActive)));
+ intTokens.insert(pair<string,int>("flaginstant", timer->HasFlags(tfInstant)));
+ intTokens.insert(pair<string,int>("flagvps", timer->HasFlags(tfVps)));
+ intTokens.insert(pair<string,int>("flagrecording", timer->Recording()));
+ intTokens.insert(pair<string,int>("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<string,string>("title", file));
+ stringTokens.insert(pair<string,string>("timerstart", *cString::sprintf("%02d:%02d", timer->Start() / 100, timer->Start() % 100)));
+ stringTokens.insert(pair<string,string>("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<string,string>("day", day));
+ stringTokens.insert(pair<string,string>("dayname", dayName));
+
+ const cChannel *channel = timer->Channel();
+ if (channel) {
+ stringTokens.insert(pair<string,string>("channelname", channel->Name() ? channel->Name() : ""));
+ stringTokens.insert(pair<string,string>("channelid", *(channel->GetChannelID().ToString())));
+ intTokens.insert(pair<string,int>("channelnumber", channel->Number()));
+ } else {
+ stringTokens.insert(pair<string,string>("channelname", ""));
+ stringTokens.insert(pair<string,string>("channelid", ""));
+ intTokens.insert(pair<string,int>("channelnumber", 0));
+ }
+
+ const cEvent *event = timer->Event();
+ if (event) {
+ stringTokens.insert(pair<string,string>("eventtitle", event->Title() ? event->Title() : ""));
+ stringTokens.insert(pair<string,string>("eventstart", *event->GetTimeString()));
+ stringTokens.insert(pair<string,string>("eventstop", *event->GetEndTimeString()));
+ } else {
+ stringTokens.insert(pair<string,string>("eventtitle", ""));
+ stringTokens.insert(pair<string,string>("eventtitle", ""));
+ stringTokens.insert(pair<string,string>("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<string,int>("current", current));
+ bool isFolder = (total > 0) ? true : false;
+ intTokens.insert(pair<string,int>("folder", isFolder));
+
+ string name = recording->Name() ? recording->Name() : "";
+ string buffer = "";
+ try {
+ vector<string> 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<string,string>("name", buffer.c_str()));
+ intTokens.insert(pair<string,int>("new", recording->IsNew()));
+ intTokens.insert(pair<string,int>("newrecordingsfolder", newRecs));
+ intTokens.insert(pair<string,int>("numrecordingsfolder", total));
+ intTokens.insert(pair<string,int>("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<string,string>("date", recDate.c_str()));
+ stringTokens.insert(pair<string,string>("time", recTime.c_str()));
+ intTokens.insert(pair<string,int>("duration", recDuration));
+ intTokens.insert(pair<string,int>("durationevent", duration));
+
+ static cPlugin *pScraper = GetScraperPlugin();
+ if (!pScraper || !recording) {
+ intTokens.insert(pair<string,int>("hasposterthumbnail", false));
+ intTokens.insert(pair<string,int>("thumbnailbwidth", -1));
+ intTokens.insert(pair<string,int>("thumbnailheight", -1));
+ stringTokens.insert(pair<string,string>("thumbnailpath", ""));
+ return;
+ }
+
+ ScraperGetPosterThumb call;
+ call.event = NULL;
+ call.recording = recording;
+ if (pScraper->Service("GetPosterThumb", &call)) {
+ intTokens.insert(pair<string,int>("hasposterthumbnail", true));
+ intTokens.insert(pair<string,int>("thumbnailbwidth", call.poster.width));
+ intTokens.insert(pair<string,int>("thumbnailheight", call.poster.height));
+ stringTokens.insert(pair<string,string>("thumbnailpath", call.poster.path));
+ } else {
+ intTokens.insert(pair<string,int>("hasposterthumbnail", false));
+ intTokens.insert(pair<string,int>("thumbnailbwidth", -1));
+ intTokens.insert(pair<string,int>("thumbnailheight", -1));
+ stringTokens.insert(pair<string,string>("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<string,string>("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 <vdr/menu.h>
+#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<string,int>("numelements", count));
+ tmplList->CalculateListParameters(&intTokens);
+ }
+ menuItems = new cDisplayMenuItemView*[itemCount];
+ for (int i=0; i<itemCount; i++)
+ menuItems[i] = NULL;
+ tabs = new int[cSkinDisplayMenu::MaxTabs];
+ for (int i=0; i<cSkinDisplayMenu::MaxTabs; i++)
+ tabs[i] = 0;
+ tabWidths = new int[cSkinDisplayMenu::MaxTabs];
+ for (int i=0; i<cSkinDisplayMenu::MaxTabs; i++)
+ tabWidths[i] = 0;
+}
+
+cDisplayMenuListView::~cDisplayMenuListView() {
+ Clear();
+ delete[] menuItems;
+ delete[] tabs;
+ delete[] tabWidths;
+}
+
+void cDisplayMenuListView::SetTabs(int tab1, int tab2, int tab3, int tab4, int tab5) {
+
+ int menuItemWidth = 1920;
+ int averageFontWidth = 20;
+ if (tmplList) {
+ menuItemWidth = tmplList->GetMenuItemWidth();
+ 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<itemCount; i++) {
+ if (menuItems[i]) {
+ delete menuItems[i];
+ menuItems[i] = NULL;
+ }
+ }
+ oneColumn = true;
+ for (int i=0; i<cSkinDisplayMenu::MaxTabs; i++) {
+ tabs[i] = 0;
+ tabWidths[i] = 0;
+ }
+}
+
+void cDisplayMenuListView::AddDefaultMenuItem(int index, string *tabTexts, bool current, bool selectable) {
+ if (menuItems[index]) {
+ cDisplayMenuItemDefaultView *menuItem = dynamic_cast<cDisplayMenuItemDefaultView*>(menuItems[index]);
+ if (!menuItem)
+ return;
+ menuItem->SetCurrent(current);
+ menuItem->SetTabTexts(tabTexts);
+ return;
+ }
+ for (int i=1; i<cSkinDisplayMenu::MaxTabs; i++) {
+ if (tabTexts[i].size() > 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; i<cSkinDisplayMenu::MaxTabs; i++) {
+ tabs[i] = 0;
+ tabWidths[i] = 0;
+ }
+ }
+ int current = -1;
+ for (int i=0; i<itemCount; i++) {
+ if (menuItems[i] && menuItems[i]->Dirty()) {
+ 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; i<itemCount; i++) {
+ esyslog("skindesigner: item %d", i);
+ if (menuItems[i]) {
+ menuItems[i]->Debug();
+ }
+ }
+}
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 <vdr/menu.h> +#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<string,string>("title", menuTitle)); + stringTokens.insert(pair<string,string>("vdrversion", VDRVERSION)); + + //check for standard menu entries + bool hasIcon = false; + string icon = imgCache->GetIconName(menuTitle); + if (icon.size() > 0) + hasIcon = true; + + stringTokens.insert(pair<string,string>("icon", icon)); + intTokens.insert(pair<string,int>("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<string, int>("year", now->tm_year + 1900)); + intTokens.insert(pair<string, int>("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<string,string>("monthname", monthname)); + stringTokens.insert(pair<string,string>("monthnameshort", monthshort)); + stringTokens.insert(pair<string,string>("month", *cString::sprintf("%02d", now->tm_mon + 1))); + stringTokens.insert(pair<string,string>("dayleadingzero", *cString::sprintf("%02d", now->tm_mday))); + stringTokens.insert(pair<string,string>("dayname", *WeekDayNameFull(now->tm_wday))); + stringTokens.insert(pair<string,string>("daynameshort", *WeekDayName(now->tm_wday))); + stringTokens.insert(pair<string,string>("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<string,string>("red", buttonTexts[0])); + stringTokens.insert(pair<string,string>("green", buttonTexts[1])); + stringTokens.insert(pair<string,string>("yellow", buttonTexts[2])); + stringTokens.insert(pair<string,string>("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<string, int>(red, isRed)); + intTokens.insert(pair<string, int>(green, isGreen)); + intTokens.insert(pair<string, int>(yellow, isYellow)); + intTokens.insert(pair<string, int>(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<string, int>("status", (type == mtStatus) ? true : false)); + intTokens.insert(pair<string, int>("info", (type == mtInfo) ? true : false)); + intTokens.insert(pair<string, int>("warning", (type == mtWarning) ? true : false)); + intTokens.insert(pair<string, int>("error", (type == mtError) ? true : false)); + stringTokens.insert(pair<string,string>("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 <vdr/menu.h> +#include <vdr/videodir.h> +#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<string,string>("title", menuTitle)); + stringTokens.insert(pair<string,string>("vdrversion", VDRVERSION)); + + //check for standard menu entries + bool hasIcon = false; + string icon = imgCache->GetIconName(menuTitle); + if (icon.size() > 0) + hasIcon = true; + stringTokens.insert(pair<string,string>("icon", icon)); + intTokens.insert(pair<string,int>("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<string, int>("year", now->tm_year + 1900)); + intTokens.insert(pair<string, int>("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<string,string>("monthname", monthname)); + stringTokens.insert(pair<string,string>("monthnameshort", monthshort)); + stringTokens.insert(pair<string,string>("month", *cString::sprintf("%02d", now->tm_mon + 1))); + stringTokens.insert(pair<string,string>("dayleadingzero", *cString::sprintf("%02d", now->tm_mday))); + stringTokens.insert(pair<string,string>("dayname", *WeekDayNameFull(now->tm_wday))); + stringTokens.insert(pair<string,string>("daynameshort", *WeekDayName(now->tm_wday))); + stringTokens.insert(pair<string,string>("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<string,string>("red", buttonTexts[0])); + stringTokens.insert(pair<string,string>("green", buttonTexts[1])); + stringTokens.insert(pair<string,string>("yellow", buttonTexts[2])); + stringTokens.insert(pair<string,string>("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<string, int>(red, isRed)); + intTokens.insert(pair<string, int>(green, isGreen)); + intTokens.insert(pair<string, int>(yellow, isYellow)); + intTokens.insert(pair<string, int>(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<string, int>("status", (type == mtStatus) ? true : false)); + intTokens.insert(pair<string, int>("info", (type == mtInfo) ? true : false)); + intTokens.insert(pair<string, int>("warning", (type == mtWarning) ? true : false)); + intTokens.insert(pair<string, int>("error", (type == mtError) ? true : false)); + stringTokens.insert(pair<string,string>("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<string, int>("height", barHeight)); + intTokens.insert(pair<string, int>("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<string, int>("numtimers", numTimers)); + + int numTimerConflicts = SortedTimers.NumTimerConfilicts(); + intTokens.insert(pair<string, int>("numtimerconflicts", numTimerConflicts)); + + for (int i=0; i<15; i++) { + stringstream name; + name << "timer" << i+1 << "exists"; + if (i < numTimers) { + intTokens.insert(pair<string, int>(name.str(), true)); + } else { + intTokens.insert(pair<string, int>(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<string, int>("usedpercent", discUsage)); + intTokens.insert(pair<string, int>("freepercent", 100-discUsage)); + intTokens.insert(pair<string, int>("discalert", discAlert)); + intTokens.insert(pair<string, int>("freegb", freeGB)); + stringTokens.insert(pair<string,string>("freetime", freeTime)); + stringTokens.insert(pair<string,string>("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<numDevices; i++) { + lastSignalStrength[i] = 0; + lastSignalQuality[i] = 0; + recDevices[i] = false; + } +} + +bool cDisplayMenuMainView::DrawLoad(void) { + if (!ViewElementImplemented(veSystemLoad)) { + return false; + } + + map < string, string > 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<string,string>("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<string, int>("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<string,int>("whatson", (cat == mcSchedule) ? true: false)); + intTokens.insert(pair<string,int>("whatsonnow", (cat == mcScheduleNow) ? true: false)); + intTokens.insert(pair<string,int>("whatsonnext", (cat == mcScheduleNext) ? true: false)); + + stringTokens.insert(pair<string,string>("title", menuTitle)); + stringTokens.insert(pair<string,string>("vdrversion", VDRVERSION)); + if (channel) { + stringTokens.insert(pair<string,string>("channelnumber", *cString::sprintf("%d", channel->Number()))); + stringTokens.insert(pair<string,string>("channelname", channel->Name())); + stringTokens.insert(pair<string,string>("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 <vdr/menu.h> +#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<string,string>("text", text)); + + intTokens.insert(pair<string,int>("status", (type == mtStatus) ? true : false)); + intTokens.insert(pair<string,int>("info", (type == mtInfo) ? true : false)); + intTokens.insert(pair<string,int>("warning", (type == mtWarning) ? true : false)); + intTokens.insert(pair<string,int>("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 <vdr/menu.h> +#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<string, int>("year", now->tm_year + 1900)); + intTokens.insert(pair<string, int>("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<string,string>("monthname", monthname)); + stringTokens.insert(pair<string,string>("monthnameshort", monthshort)); + stringTokens.insert(pair<string,string>("month", *cString::sprintf("%02d", now->tm_mon + 1))); + stringTokens.insert(pair<string,string>("dayleadingzero", *cString::sprintf("%02d", now->tm_mday))); + stringTokens.insert(pair<string,string>("dayname", *WeekDayNameFull(now->tm_wday))); + stringTokens.insert(pair<string,string>("daynameshort", *WeekDayName(now->tm_wday))); + stringTokens.insert(pair<string,string>("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<string,string>("rectitle", recName ? recName : "")); + stringTokens.insert(pair<string,string>("recsubtitle", recShortText)); + stringTokens.insert(pair<string,string>("recdate", recDate)); + stringTokens.insert(pair<string,string>("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<string,int>("screenwidth", screenWidth)); + intTokens.insert(pair<string,int>("screenheight", screenHeight)); + intTokens.insert(pair<string,int>("isHD", isHD)); + intTokens.insert(pair<string,int>("isWideScreen", isWideScreen)); + stringTokens.insert(pair<string,string>("resolution", resName)); + stringTokens.insert(pair<string,string>("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<string,int>("mediawidth", mediaWidth)); + intTokens.insert(pair<string,int>("mediaheight", mediaHeight)); + intTokens.insert(pair<string,int>("isbanner", isBanner)); + stringTokens.insert(pair<string,string>("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<string,string>("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<string,string>("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<string,int>("current", current)); + intTokens.insert(pair<string,int>("total", total)); + stringTokens.insert(pair<string,string>("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<string,int>("play", isPlay)); + intTokens.insert(pair<string,int>("pause", isPause)); + intTokens.insert(pair<string,int>("forward", isFF)); + intTokens.insert(pair<string,int>("forward1x", isFF1x)); + intTokens.insert(pair<string,int>("forward2x", isFF2x)); + intTokens.insert(pair<string,int>("forward3x", isFF3x)); + intTokens.insert(pair<string,int>("rewind", isRew)); + intTokens.insert(pair<string,int>("rewind1x", isRew1x)); + intTokens.insert(pair<string,int>("rewind2x", isRew2x)); + intTokens.insert(pair<string,int>("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<string,string>("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<string,string>("text", text)); + + intTokens.insert(pair<string,int>("status", (type == mtStatus) ? true : false)); + intTokens.insert(pair<string,int>("info", (type == mtInfo) ? true : false)); + intTokens.insert(pair<string,int>("warning", (type == mtWarning) ? true : false)); + intTokens.insert(pair<string,int>("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 <vdr/menu.h> +#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<string,int>("volume", current)); + intTokens.insert(pair<string,int>("maxvolume", total)); + intTokens.insert(pair<string,int>("volumepercent", (double)current *100 / (double)total)); + intTokens.insert(pair<string,int>("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 <string,string> *stringTokens, map <string,int> *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<cTemplateLoopFunction*>(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<string,string> > loopToken = hit->second;
+ int lineNumber=0;
+ for (vector< map<string,string> >::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<string,string> 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<string,string> *stringTokens, map<string,int> *intTokens, map < string, vector< map< string, string > > > *loopTokens) {
+ esyslog("skindesigner: ------------------------------ Tokens for %s:", viewElement.c_str());
+ if (stringTokens) {
+ for (map<string,string>::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<string,int>::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<string,string> > tokens = it1->second;
+ esyslog("skindesigner: loop token %s", tokenName.c_str());
+ for (vector< map<string,string> >::iterator it2 = tokens.begin(); it2 != tokens.end(); it2++) {
+ esyslog("skindesigner: loop tokens line %d:", line++);
+ map<string,string> element = *it2;
+ for (map<string,string>::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<std::string> flds = s.split('\n', 1);
+
+ if (flds.size() < 1)
+ return;
+
+ std::stringstream sstrTextTall;
+ std::stringstream sstrTextFull;
+
+ for (int i=0; i<flds.size(); i++) {
+ if (!flds[i].size()) {
+ //empty line
+ linesDrawn++;
+ curY += fontHeight;
+ if (drawNarrow)
+ sstrTextTall << "\n";
+ else
+ sstrTextFull << "\n";
+ } else {
+ cTextWrapper wrapper;
+ if (drawNarrow) {
+ wrapper.Set((flds[i].c_str()), font, widthNarrow);
+ int newLines = wrapper.Lines();
+ //check if wrapper fits completely into narrow area
+ if (linesDrawn + newLines < linesNarrow) {
+ for (int line = 0; line < wrapper.Lines(); line++) {
+ sstrTextTall << wrapper.GetLine(line) << " ";
+ }
+ sstrTextTall << "\n";
+ linesDrawn += newLines;
+ } else {
+ //this wrapper has to be splitted
+ for (int line = 0; line < wrapper.Lines(); line++) {
+ if (line + linesDrawn < linesNarrow) {
+ sstrTextTall << wrapper.GetLine(line) << " ";
+ } else {
+ sstrTextFull << wrapper.GetLine(line) << " ";
+ }
+ }
+ sstrTextFull << "\n";
+ drawNarrow = false;
+ }
+ } else {
+ wrapper.Set((flds[i].c_str()), font, width);
+ for (int line = 0; line < wrapper.Lines(); line++) {
+ sstrTextFull << wrapper.GetLine(line) << " ";
+ }
+ sstrTextFull << "\n";
+ }
+ }
+ }
+ //VDRs textwrapper swallows linebreaks at the end, so we have to fix that manually
+ string textTall = sstrTextTall.str();
+ size_t posLastCarriageReturn = textTall.find_last_not_of("\n");
+
+ int numLinesToAddAtTall = 0;
+ if (posLastCarriageReturn != string::npos && (posLastCarriageReturn < textTall.size() - 1)) {
+ numLinesToAddAtTall = textTall.size() - posLastCarriageReturn - 2;
+ }
+
+ wTextTall.Set(textTall.c_str(), font, widthNarrow);
+ wTextFull.Set(sstrTextFull.str().c_str(), font, width);
+
+ int textLinesTall = wTextTall.Lines();
+ int textLinesFull = wTextFull.Lines();
+
+ int textXTall = x;
+ if (floatType == flTopLeft)
+ textXTall = x + floatWidth;
+
+ int yLine = y;
+ for (int line=0; line < textLinesTall; line++) {
+ cPoint pos(textXTall, yLine);
+ DrawText(num, pos, wTextTall.GetLine(line), clr, clrBack, fontName, fontSize);
+ yLine += fontHeight;
+ }
+
+ if (numLinesToAddAtTall) {
+ yLine += numLinesToAddAtTall * fontHeight;
+ }
+
+ for (int line=0; line < textLinesFull; line++) {
+ cPoint pos(x, yLine);
+ if (height > 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 <string,string> *stringTokens, map <string,int> *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 <string,string> *stringTokens = NULL, map <string,int> *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<string,string> *stringTokens, map<string,int> *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 <string,string> *stringTokens, map <string,int> *intTokens);
+ void ClearListItem(void);
+};
+
+#endif //__VIEW_H
\ No newline at end of file |