initial commit version 0.0.1

This commit is contained in:
louis 2014-09-27 09:25:14 +02:00
commit b0509b5182
503 changed files with 24368 additions and 0 deletions

340
COPYING Normal file
View File

@ -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.

7
HISTORY Normal file
View File

@ -0,0 +1,7 @@
VDR Plugin 'skindesigner' Revision History
---------------------------------------
2014-09-27: Version 0.0.1
- Initial revision.

176
Makefile Normal file
View File

@ -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* *~

102
README Normal file
View File

@ -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.

76
config.c Normal file
View File

@ -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;
}

53
config.h Normal file
View File

@ -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

309
designer.c Normal file
View File

@ -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;
}

49
designer.h Normal file
View File

@ -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

193
displaychannel.c Normal file
View File

@ -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();
}

32
displaychannel.h Normal file
View File

@ -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

233
displaymenu.c Normal file
View File

@ -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;
}

48
displaymenu.h Normal file
View File

@ -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

43
displaymessage.c Normal file
View File

@ -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();
}
}

22
displaymessage.h Normal file
View File

@ -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

131
displayreplay.c Normal file
View File

@ -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++;
}
}

34
displayreplay.h Normal file
View File

@ -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

58
displaytracks.c Normal file
View File

@ -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();
}

27
displaytracks.h Normal file
View File

@ -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

43
displayvolume.c Normal file
View File

@ -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();
}
}

21
displayvolume.h Normal file
View File

@ -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

View File

@ -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.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

174
libcore/fontmanager.c Normal file
View File

@ -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;
}

35
libcore/fontmanager.h Normal file
View File

@ -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

155
libcore/helpers.c Normal file
View File

@ -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));
}

35
libcore/helpers.h Normal file
View File

@ -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

389
libcore/imagecache.c Normal file
View File

@ -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);
}
}

53
libcore/imagecache.h Normal file
View File

@ -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

56
libcore/imageloader.c Normal file
View File

@ -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( ... ) { }
}
}
}

23
libcore/imageloader.h Normal file
View File

@ -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

View File

@ -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);
}

View File

@ -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

149
libcore/imagescaler.c Normal file
View File

@ -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++;
}
}

97
libcore/imagescaler.h Normal file
View File

@ -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

477
libcore/pixmapcontainer.c Normal file
View File

@ -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);
}

73
libcore/pixmapcontainer.h Normal file
View File

@ -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

84
libcore/timers.c Normal file
View File

@ -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();
}
}
}

20
libcore/timers.h Normal file
View File

@ -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

98
libtemplate/globals.c Normal file
View File

@ -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());
}
}
}

38
libtemplate/globals.h Normal file
View File

@ -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

394
libtemplate/parameter.c Normal file
View File

@ -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);
}
}

138
libtemplate/parameter.h Normal file
View File

@ -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

273
libtemplate/template.c Normal file
View File

@ -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;
}
}

57
libtemplate/template.h Normal file
View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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> > &params) {
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();
}
}

View File

@ -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> > &params);
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

View File

@ -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> > &params) {
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> > &params) {
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();
}
}

View File

@ -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> > &params);
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> > &params);
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

1567
libtemplate/templateview.c Normal file

File diff suppressed because it is too large Load Diff

198
libtemplate/templateview.h Normal file
View File

@ -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> > &params);
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

View File

@ -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> > &params) {
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();
}
}

View File

@ -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> > &params);
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

View File

@ -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();
}

View File

@ -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

View File

@ -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: -------------------------------------------------------");
}

View File

@ -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

728
libtemplate/xmlparser.c Normal file
View File

@ -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;
}

56
libtemplate/xmlparser.h Normal file
View File

@ -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

167
services/epgsearch.h Normal file
View File

@ -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

141
services/remotetimers.h Normal file
View File

@ -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

214
services/scraper2vdr.h Normal file
View File

@ -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

73
setup.c Normal file
View 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);
}

16
setup.h Normal file
View 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

165
skindesigner.c Normal file
View File

@ -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!

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 958 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 386 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 369 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 458 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 413 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 958 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 788 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Some files were not shown because too many files have changed in this diff Show More