initial commit version 0.0.1
340
COPYING
Normal 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
@ -0,0 +1,7 @@
|
|||||||
|
VDR Plugin 'skindesigner' Revision History
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
2014-09-27: Version 0.0.1
|
||||||
|
|
||||||
|
- Initial revision.
|
||||||
|
|
176
Makefile
Normal 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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
|
201
fonts/VDROpenSans/Apache License.txt
Normal 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.
|
BIN
fonts/VDROpenSans/VDROpenSans-Bold.ttf
Normal file
BIN
fonts/VDROpenSans/VDROpenSans-BoldItalic.ttf
Normal file
BIN
fonts/VDROpenSans/VDROpenSans-ExtraBold.ttf
Normal file
BIN
fonts/VDROpenSans/VDROpenSans-ExtraBoldItalic.ttf
Normal file
BIN
fonts/VDROpenSans/VDROpenSans-Italic.ttf
Normal file
BIN
fonts/VDROpenSans/VDROpenSans-Light.ttf
Normal file
BIN
fonts/VDROpenSans/VDROpenSans-LightItalic.ttf
Normal file
BIN
fonts/VDROpenSans/VDROpenSans-Regular.ttf
Normal file
BIN
fonts/VDROpenSans/VDROpenSans-Semibold.ttf
Normal file
BIN
fonts/VDROpenSans/VDROpenSans-SemiboldItalic.ttf
Normal file
174
libcore/fontmanager.c
Normal 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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
|
162
libcore/imagemagickwrapper.c
Normal 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);
|
||||||
|
}
|
28
libcore/imagemagickwrapper.h
Normal 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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
|
1474
libtemplate/templatefunction.c
Normal file
211
libtemplate/templatefunction.h
Normal 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
|
208
libtemplate/templateloopfunction.c
Normal 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> > ¶ms) {
|
||||||
|
eFuncType type = ftNone;
|
||||||
|
|
||||||
|
if (!name.compare("drawtext")) {
|
||||||
|
type = ftDrawText;
|
||||||
|
} else if (!name.compare("drawtextbox")) {
|
||||||
|
type = ftDrawTextBox;
|
||||||
|
} else if (!name.compare("drawimage")) {
|
||||||
|
type = ftDrawImage;
|
||||||
|
} else if (!name.compare("drawrectangle")) {
|
||||||
|
type = ftDrawRectangle;
|
||||||
|
} else if (!name.compare("drawellipse")) {
|
||||||
|
type = ftDrawEllipse;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == ftNone) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cTemplateFunction *f = new cTemplateFunction(type);
|
||||||
|
f->SetParameters(params);
|
||||||
|
functions.push_back(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cTemplateLoopFunction::CalculateLoopFuncParameters(void) {
|
||||||
|
int columnWidth = GetNumericParameter(ptColumnWidth);
|
||||||
|
int rowHeight = GetNumericParameter(ptRowHeight);
|
||||||
|
for (vector<cTemplateFunction*>::iterator func = functions.begin(); func != functions.end(); func++) {
|
||||||
|
(*func)->SetGlobals(globals);
|
||||||
|
(*func)->SetContainer(0, 0, containerWidth, containerHeight);
|
||||||
|
(*func)->SetLoopContainer(columnWidth, rowHeight);
|
||||||
|
(*func)->CalculateParameters();
|
||||||
|
(*func)->CompleteParameters();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cTemplateFunction *cTemplateLoopFunction::GetNextFunction(void) {
|
||||||
|
if (funcIt == functions.end())
|
||||||
|
return NULL;
|
||||||
|
cTemplateFunction *func = *funcIt;
|
||||||
|
funcIt++;
|
||||||
|
return func;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cTemplateLoopFunction::ClearDynamicParameters(void) {
|
||||||
|
InitIterator();
|
||||||
|
cTemplateFunction *func = NULL;
|
||||||
|
while(func = GetNextFunction()) {
|
||||||
|
func->ClearDynamicParameters();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cTemplateLoopFunction::ParseDynamicParameters(map <string,string> *tokens) {
|
||||||
|
if (!tokens)
|
||||||
|
return;
|
||||||
|
InitIterator();
|
||||||
|
cTemplateFunction *func = NULL;
|
||||||
|
|
||||||
|
map <string,int> intTokens;
|
||||||
|
for (map <string,string>::iterator it = tokens->begin(); it != tokens->end(); it++) {
|
||||||
|
if (isNumber(it->second))
|
||||||
|
intTokens.insert(pair<string, int>(it->first, atoi((it->second).c_str())));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool completelyParsed = true;
|
||||||
|
while(func = GetNextFunction()) {
|
||||||
|
func->SetStringTokens(tokens);
|
||||||
|
func->SetIntTokens(&intTokens);
|
||||||
|
bool funcCompletelyParsed = func->ParseParameters();
|
||||||
|
if (!funcCompletelyParsed)
|
||||||
|
completelyParsed = false;
|
||||||
|
if (func->Updated())
|
||||||
|
func->CompleteParameters();
|
||||||
|
func->UnsetStringTokens();
|
||||||
|
func->UnsetIntTokens();
|
||||||
|
}
|
||||||
|
if (completelyParsed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReplaceWidthFunctions();
|
||||||
|
ReplaceHeightFunctions();
|
||||||
|
}
|
||||||
|
|
||||||
|
int cTemplateLoopFunction::GetLoopElementsWidth(void) {
|
||||||
|
int cW = GetNumericParameter(ptColumnWidth);
|
||||||
|
if (cW > 0) {
|
||||||
|
return cW;
|
||||||
|
}
|
||||||
|
InitIterator();
|
||||||
|
cTemplateFunction *func = NULL;
|
||||||
|
int maxWidth = 1;
|
||||||
|
while(func = GetNextFunction()) {
|
||||||
|
int funcWidth = func->GetWidth(true);
|
||||||
|
if (funcWidth > maxWidth)
|
||||||
|
maxWidth = funcWidth;
|
||||||
|
}
|
||||||
|
return maxWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cTemplateLoopFunction::GetLoopElementsHeight(void) {
|
||||||
|
int rH = GetNumericParameter(ptRowHeight);
|
||||||
|
if (rH > 0)
|
||||||
|
return rH;
|
||||||
|
InitIterator();
|
||||||
|
cTemplateFunction *func = NULL;
|
||||||
|
int maxHeight = 1;
|
||||||
|
while(func = GetNextFunction()) {
|
||||||
|
int funcY = func->GetNumericParameter(ptY);
|
||||||
|
int funcHeight = func->GetHeight();
|
||||||
|
int totalHeight = funcY + funcHeight;
|
||||||
|
if (totalHeight > maxHeight)
|
||||||
|
maxHeight = totalHeight;
|
||||||
|
}
|
||||||
|
return maxHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cTemplateLoopFunction::ReplaceWidthFunctions(void) {
|
||||||
|
InitIterator();
|
||||||
|
cTemplateFunction *func = NULL;
|
||||||
|
while(func = GetNextFunction()) {
|
||||||
|
if (func->ParsedCompletely()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
multimap<eParamType,string> widths;
|
||||||
|
func->GetNeededWidths(&widths);
|
||||||
|
for (map<eParamType, string>::iterator names = widths.begin(); names !=widths.end(); names++) {
|
||||||
|
eParamType type = names->first;
|
||||||
|
string label = names->second;
|
||||||
|
int funcWidth = 0;
|
||||||
|
for (vector<cTemplateFunction*>::iterator it = functions.begin(); it != functions.end(); it++) {
|
||||||
|
cTemplateFunction *myFunc = *it;
|
||||||
|
string myFuncName = myFunc->GetParameter(ptName);
|
||||||
|
if (!myFuncName.compare(label)) {
|
||||||
|
funcWidth = myFunc->GetWidth();
|
||||||
|
func->SetWidth(type, label, funcWidth);
|
||||||
|
if (func->Updated()) {
|
||||||
|
func->CompleteParameters();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cTemplateLoopFunction::ReplaceHeightFunctions(void) {
|
||||||
|
InitIterator();
|
||||||
|
cTemplateFunction *func = NULL;
|
||||||
|
while(func = GetNextFunction()) {
|
||||||
|
if (func->ParsedCompletely()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
multimap<eParamType,string> heights;
|
||||||
|
func->GetNeededHeights(&heights);
|
||||||
|
for (map<eParamType, string>::iterator names = heights.begin(); names !=heights.end(); names++) {
|
||||||
|
eParamType type = names->first;
|
||||||
|
string label = names->second;
|
||||||
|
int funcHeight = 0;
|
||||||
|
for (vector<cTemplateFunction*>::iterator it = functions.begin(); it != functions.end(); it++) {
|
||||||
|
cTemplateFunction *myFunc = *it;
|
||||||
|
string myFuncName = myFunc->GetParameter(ptName);
|
||||||
|
if (!myFuncName.compare(label)) {
|
||||||
|
funcHeight = myFunc->GetHeight();
|
||||||
|
func->SetHeight(type, label, funcHeight);
|
||||||
|
if (func->Updated()) {
|
||||||
|
func->CompleteParameters();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cTemplateLoopFunction::Ready(void) {
|
||||||
|
bool isReady = true;
|
||||||
|
map< eParamType, string >::iterator hit = numericDynamicParameters.find(ptColumnWidth);
|
||||||
|
if (hit != numericDynamicParameters.end())
|
||||||
|
isReady = false;
|
||||||
|
hit = numericDynamicParameters.find(ptRowHeight);
|
||||||
|
if (hit != numericDynamicParameters.end())
|
||||||
|
isReady = false;
|
||||||
|
return isReady;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cTemplateLoopFunction::Debug(void) {
|
||||||
|
cTemplateFunction::Debug();
|
||||||
|
esyslog("skindesigner: functions to be looped:");
|
||||||
|
for (vector<cTemplateFunction*>::iterator func = functions.begin(); func != functions.end(); func++) {
|
||||||
|
(*func)->Debug();
|
||||||
|
}
|
||||||
|
}
|
33
libtemplate/templateloopfunction.h
Normal 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> > ¶ms);
|
||||||
|
void CalculateLoopFuncParameters(void);
|
||||||
|
void InitIterator(void);
|
||||||
|
cTemplateFunction *GetNextFunction(void);
|
||||||
|
void ClearDynamicParameters(void);
|
||||||
|
void ParseDynamicParameters(map <string,string> *tokens);
|
||||||
|
int GetLoopElementsWidth(void);
|
||||||
|
int GetLoopElementsHeight(void);
|
||||||
|
int GetContainerWidth(void) { return containerWidth; };
|
||||||
|
int GetContainerHeight(void) { return containerHeight; };
|
||||||
|
bool Ready(void);
|
||||||
|
void Debug(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //__TEMPLATELOOPFUNCTION_H
|
473
libtemplate/templatepixmap.c
Normal 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> > ¶ms) {
|
||||||
|
parameters = new cTemplateFunction(ftPixmap);
|
||||||
|
parameters->SetGlobals(globals);
|
||||||
|
parameters->SetParameters(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cTemplatePixmap::SetContainer(int x, int y, int w, int h) {
|
||||||
|
containerX = x;
|
||||||
|
containerY = y;
|
||||||
|
containerWidth = w;
|
||||||
|
containerHeight = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cTemplatePixmap::SetWidth(int width) {
|
||||||
|
cString pWidth = cString::sprintf("%d", width);
|
||||||
|
parameters->SetWidthManually(*pWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cTemplatePixmap::SetHeight(int height) {
|
||||||
|
cString pHeight = cString::sprintf("%d", height);
|
||||||
|
parameters->SetHeightManually(*pHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cTemplatePixmap::SetX(int x) {
|
||||||
|
parameters->SetXManually(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cTemplatePixmap::SetY(int y) {
|
||||||
|
parameters->SetYManually(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cTemplatePixmap::ClearDynamicParameters(void) {
|
||||||
|
parameters->ClearDynamicParameters();
|
||||||
|
}
|
||||||
|
|
||||||
|
void cTemplatePixmap::ParseDynamicParameters(map <string,int> *intTokens, bool initFuncs) {
|
||||||
|
parameters->ClearDynamicParameters();
|
||||||
|
parameters->SetIntTokens(intTokens);
|
||||||
|
parameters->ParseParameters();
|
||||||
|
parameters->UnsetIntTokens();
|
||||||
|
|
||||||
|
if (!DoExecute()) {
|
||||||
|
parameters->ClearDynamicParameters();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!initFuncs || !Ready())
|
||||||
|
return;
|
||||||
|
|
||||||
|
int x = parameters->GetNumericParameter(ptX);
|
||||||
|
int y = parameters->GetNumericParameter(ptY);
|
||||||
|
int width = parameters->GetNumericParameter(ptWidth);
|
||||||
|
int height = parameters->GetNumericParameter(ptHeight);
|
||||||
|
|
||||||
|
for (vector<cTemplateFunction*>::iterator func = functions.begin(); func != functions.end(); func++) {
|
||||||
|
(*func)->SetContainer(x, y, width, height);
|
||||||
|
(*func)->CalculateParameters();
|
||||||
|
(*func)->CompleteParameters();
|
||||||
|
if ((*func)->GetType() == ftLoop) {
|
||||||
|
cTemplateLoopFunction *loopFunc = dynamic_cast<cTemplateLoopFunction*>(*func);
|
||||||
|
if (!loopFunc->Ready()) {
|
||||||
|
loopFunc->SetIntTokens(intTokens);
|
||||||
|
loopFunc->ParseParameters();
|
||||||
|
loopFunc->UnsetIntTokens();
|
||||||
|
}
|
||||||
|
loopFunc->CalculateLoopFuncParameters();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cTemplatePixmap::AddFunction(string name, vector<pair<string, string> > ¶ms) {
|
||||||
|
eFuncType type = ftNone;
|
||||||
|
|
||||||
|
if (!name.compare("fill")) {
|
||||||
|
type = ftFill;
|
||||||
|
} else if (!name.compare("drawtext")) {
|
||||||
|
type = ftDrawText;
|
||||||
|
} else if (!name.compare("drawtextbox")) {
|
||||||
|
type = ftDrawTextBox;
|
||||||
|
} else if (!name.compare("drawimage")) {
|
||||||
|
type = ftDrawImage;
|
||||||
|
} else if (!name.compare("drawrectangle")) {
|
||||||
|
type = ftDrawRectangle;
|
||||||
|
} else if (!name.compare("drawellipse")) {
|
||||||
|
type = ftDrawEllipse;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == ftNone) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cTemplateFunction *f = new cTemplateFunction(type);
|
||||||
|
f->SetParameters(params);
|
||||||
|
functions.push_back(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cTemplatePixmap::AddLoopFunction(cTemplateLoopFunction *lf) {
|
||||||
|
functions.push_back(lf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool cTemplatePixmap::CalculateParameters(void) {
|
||||||
|
bool paramsValid = true;
|
||||||
|
//Calculate Pixmap Size
|
||||||
|
parameters->SetContainer(containerX, containerY, containerWidth, containerHeight);
|
||||||
|
parameters->SetGlobals(globals);
|
||||||
|
paramsValid = parameters->CalculateParameters();
|
||||||
|
|
||||||
|
int pixWidth = parameters->GetNumericParameter(ptWidth);
|
||||||
|
int pixHeight = parameters->GetNumericParameter(ptHeight);
|
||||||
|
|
||||||
|
for (vector<cTemplateFunction*>::iterator func = functions.begin(); func != functions.end(); func++) {
|
||||||
|
(*func)->SetGlobals(globals);
|
||||||
|
if (!Ready())
|
||||||
|
continue;
|
||||||
|
(*func)->SetContainer(0, 0, pixWidth, pixHeight);
|
||||||
|
paramsValid = (*func)->CalculateParameters();
|
||||||
|
(*func)->CompleteParameters();
|
||||||
|
if ((*func)->GetType() == ftLoop) {
|
||||||
|
cTemplateLoopFunction *loopFunc = dynamic_cast<cTemplateLoopFunction*>(*func);
|
||||||
|
loopFunc->CalculateLoopFuncParameters();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return paramsValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cTemplatePixmap::ClearDynamicFunctionParameters(void) {
|
||||||
|
InitIterator();
|
||||||
|
cTemplateFunction *func = NULL;
|
||||||
|
while(func = GetNextFunction()) {
|
||||||
|
func->ClearDynamicParameters();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cTemplatePixmap::ParseDynamicFunctionParameters(map <string,string> *stringTokens, map <string,int> *intTokens) {
|
||||||
|
InitIterator();
|
||||||
|
cTemplateFunction *func = NULL;
|
||||||
|
bool completelyParsed = true;
|
||||||
|
bool updated = false;
|
||||||
|
while(func = GetNextFunction()) {
|
||||||
|
func->SetStringTokens(stringTokens);
|
||||||
|
func->SetIntTokens(intTokens);
|
||||||
|
bool funcCompletelyParsed = func->ParseParameters();
|
||||||
|
if (!funcCompletelyParsed)
|
||||||
|
completelyParsed = false;
|
||||||
|
if (func->Updated())
|
||||||
|
func->CompleteParameters();
|
||||||
|
func->UnsetIntTokens();
|
||||||
|
func->UnsetStringTokens();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (completelyParsed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReplaceWidthFunctions();
|
||||||
|
ReplaceHeightFunctions();
|
||||||
|
ReplacePosXFunctions();
|
||||||
|
ReplacePosYFunctions();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cTemplatePixmap::CalculateDrawPortSize(cSize &size, map < string, vector< map< string, string > > > *loopTokens) {
|
||||||
|
int pixWidth = parameters->GetNumericParameter(ptWidth);
|
||||||
|
int pixHeight = parameters->GetNumericParameter(ptHeight);
|
||||||
|
int orientation = parameters->GetNumericParameter(ptOrientation);
|
||||||
|
if (orientation < 0)
|
||||||
|
orientation = orVertical;
|
||||||
|
if (orientation == orHorizontal) {
|
||||||
|
//get function which determinates drawport width
|
||||||
|
cTemplateFunction *scrollFunc = GetScrollFunction();
|
||||||
|
if (!scrollFunc)
|
||||||
|
return false;
|
||||||
|
int drawportWidth = scrollFunc->GetWidth(false) + scrollFunc->GetNumericParameter(ptX) + 10;
|
||||||
|
if (drawportWidth > pixWidth) {
|
||||||
|
size.SetWidth(drawportWidth);
|
||||||
|
size.SetHeight(pixHeight);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else if (orientation == orVertical) {
|
||||||
|
//check "last" element height
|
||||||
|
InitIterator();
|
||||||
|
cTemplateFunction *f = NULL;
|
||||||
|
int drawportHeight = 1;
|
||||||
|
while (f = GetNextFunction()) {
|
||||||
|
if (f->GetType() == ftLoop) {
|
||||||
|
cTemplateLoopFunction *loopFunc = dynamic_cast<cTemplateLoopFunction*>(f);
|
||||||
|
//get number of loop tokens
|
||||||
|
string loopTokenName = loopFunc->GetParameter(ptName);
|
||||||
|
int numLoopTokens = 0;
|
||||||
|
map < string, vector< map< string, string > > >::iterator hit = loopTokens->find(loopTokenName);
|
||||||
|
if (hit != loopTokens->end()) {
|
||||||
|
vector< map<string,string> > loopToken = hit->second;
|
||||||
|
numLoopTokens = loopToken.size();
|
||||||
|
//parse first loop token element to get correct height
|
||||||
|
vector< map<string,string> >::iterator firstLoopToken = loopToken.begin();
|
||||||
|
loopFunc->ClearDynamicParameters();
|
||||||
|
loopFunc->ParseDynamicParameters(&(*firstLoopToken));
|
||||||
|
}
|
||||||
|
int orientation = loopFunc->GetNumericParameter(ptOrientation);
|
||||||
|
int yFunc = loopFunc->GetNumericParameter(ptY);
|
||||||
|
int heightFunc = loopFunc->GetLoopElementsHeight();
|
||||||
|
if (loopTokens && orientation == orVertical) {
|
||||||
|
//height is height of loop elements times num loop elements
|
||||||
|
heightFunc = heightFunc * numLoopTokens;
|
||||||
|
} else if (loopTokens && orientation == orHorizontal) {
|
||||||
|
int overflow = loopFunc->GetNumericParameter(ptOverflow);
|
||||||
|
if (overflow == otCut) {
|
||||||
|
//do nothing, height is only height of one line
|
||||||
|
} else if (overflow == otWrap) {
|
||||||
|
int widthFunc = loopFunc->GetLoopElementsWidth();
|
||||||
|
if (widthFunc <= 0)
|
||||||
|
continue;
|
||||||
|
int loopWidth = loopFunc->GetNumericParameter(ptWidth);
|
||||||
|
if (loopWidth <= 0)
|
||||||
|
loopWidth = loopFunc->GetContainerWidth();
|
||||||
|
int elementsPerRow = loopWidth / widthFunc;
|
||||||
|
int rest = loopWidth % widthFunc;
|
||||||
|
if (rest > 0)
|
||||||
|
elementsPerRow++;
|
||||||
|
if (elementsPerRow <= 0)
|
||||||
|
continue;
|
||||||
|
int lines = numLoopTokens / elementsPerRow;
|
||||||
|
rest = numLoopTokens % elementsPerRow;
|
||||||
|
if (rest > 0)
|
||||||
|
lines++;
|
||||||
|
heightFunc = heightFunc * lines;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int neededHeight = heightFunc + yFunc;
|
||||||
|
if (neededHeight > drawportHeight)
|
||||||
|
drawportHeight = neededHeight;
|
||||||
|
} else {
|
||||||
|
int yFunc = f->GetNumericParameter(ptY);
|
||||||
|
int heightFunc = f->GetHeight();
|
||||||
|
int neededHeight = heightFunc + yFunc;
|
||||||
|
if (neededHeight > drawportHeight)
|
||||||
|
drawportHeight = neededHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (drawportHeight > pixHeight) {
|
||||||
|
size.SetWidth(pixWidth);
|
||||||
|
size.SetHeight(drawportHeight);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
size.SetWidth(0);
|
||||||
|
size.SetHeight(0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cTemplatePixmap::SetScrollingTextWidth(void) {
|
||||||
|
int orientation = parameters->GetNumericParameter(ptOrientation);
|
||||||
|
if (orientation != orHorizontal)
|
||||||
|
return;
|
||||||
|
int pixWidth = parameters->GetNumericParameter(ptWidth);
|
||||||
|
InitIterator();
|
||||||
|
cTemplateFunction *func = NULL;
|
||||||
|
while(func = GetNextFunction()) {
|
||||||
|
if (func->GetType() == ftDrawText) {
|
||||||
|
int offset = func->GetNumericParameter(ptX);
|
||||||
|
func->SetMaxTextWidth(pixWidth - offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
cTemplateFunction *cTemplatePixmap::GetScrollFunction(void) {
|
||||||
|
string scrollElement = parameters->GetParameter(ptScrollElement);
|
||||||
|
if (scrollElement.size() == 0)
|
||||||
|
return NULL;
|
||||||
|
InitIterator();
|
||||||
|
cTemplateFunction *f = NULL;
|
||||||
|
bool foundElement = false;
|
||||||
|
while (f = GetNextFunction()) {
|
||||||
|
string funcName = f->GetParameter(ptName);
|
||||||
|
if (!funcName.compare(scrollElement)) {
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
cRect cTemplatePixmap::GetPixmapSize(void) {
|
||||||
|
cRect size;
|
||||||
|
size.SetX(GetNumericParameter(ptX));
|
||||||
|
size.SetY(GetNumericParameter(ptY));
|
||||||
|
size.SetWidth(GetNumericParameter(ptWidth));
|
||||||
|
size.SetHeight(GetNumericParameter(ptHeight));
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cTemplatePixmap::GetNumericParameter(eParamType type) {
|
||||||
|
if (!parameters)
|
||||||
|
return -1;
|
||||||
|
return parameters->GetNumericParameter(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cTemplatePixmap::InitIterator(void) {
|
||||||
|
funcIt = functions.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
cTemplateFunction *cTemplatePixmap::GetNextFunction(void) {
|
||||||
|
if (funcIt == functions.end())
|
||||||
|
return NULL;
|
||||||
|
cTemplateFunction *func = *funcIt;
|
||||||
|
funcIt++;
|
||||||
|
return func;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cTemplatePixmap::Ready(void) {
|
||||||
|
int myX = parameters->GetNumericParameter(ptX);
|
||||||
|
if (myX < 0)
|
||||||
|
return false;
|
||||||
|
int myY = parameters->GetNumericParameter(ptY);
|
||||||
|
if (myY < 0)
|
||||||
|
return false;
|
||||||
|
int myWidth = parameters->GetNumericParameter(ptWidth);
|
||||||
|
if (myWidth < 1)
|
||||||
|
return false;
|
||||||
|
int myHeight = parameters->GetNumericParameter(ptHeight);
|
||||||
|
if (myHeight < 1)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cTemplatePixmap::ReplaceWidthFunctions(void) {
|
||||||
|
InitIterator();
|
||||||
|
cTemplateFunction *func = NULL;
|
||||||
|
while(func = GetNextFunction()) {
|
||||||
|
if (func->ParsedCompletely()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
multimap<eParamType,string> widths;
|
||||||
|
func->GetNeededWidths(&widths);
|
||||||
|
for (map<eParamType, string>::iterator names = widths.begin(); names !=widths.end(); names++) {
|
||||||
|
eParamType type = names->first;
|
||||||
|
string label = names->second;
|
||||||
|
int funcWidth = 0;
|
||||||
|
for (vector<cTemplateFunction*>::iterator it = functions.begin(); it != functions.end(); it++) {
|
||||||
|
cTemplateFunction *myFunc = *it;
|
||||||
|
string myFuncName = myFunc->GetParameter(ptName);
|
||||||
|
if (!myFuncName.compare(label)) {
|
||||||
|
funcWidth = myFunc->GetWidth();
|
||||||
|
func->SetWidth(type, label, funcWidth);
|
||||||
|
if (func->Updated()) {
|
||||||
|
func->CompleteParameters();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cTemplatePixmap::ReplaceHeightFunctions(void) {
|
||||||
|
InitIterator();
|
||||||
|
cTemplateFunction *func = NULL;
|
||||||
|
while(func = GetNextFunction()) {
|
||||||
|
if (func->ParsedCompletely()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
multimap<eParamType,string> heights;
|
||||||
|
func->GetNeededHeights(&heights);
|
||||||
|
for (map<eParamType, string>::iterator names = heights.begin(); names !=heights.end(); names++) {
|
||||||
|
eParamType type = names->first;
|
||||||
|
string label = names->second;
|
||||||
|
int funcHeight = 0;
|
||||||
|
for (vector<cTemplateFunction*>::iterator it = functions.begin(); it != functions.end(); it++) {
|
||||||
|
cTemplateFunction *myFunc = *it;
|
||||||
|
string myFuncName = myFunc->GetParameter(ptName);
|
||||||
|
if (!myFuncName.compare(label)) {
|
||||||
|
funcHeight = myFunc->GetHeight();
|
||||||
|
func->SetHeight(type, label, funcHeight);
|
||||||
|
if (func->Updated()) {
|
||||||
|
func->CompleteParameters();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cTemplatePixmap::ReplacePosXFunctions(void) {
|
||||||
|
InitIterator();
|
||||||
|
cTemplateFunction *func = NULL;
|
||||||
|
while(func = GetNextFunction()) {
|
||||||
|
if (func->ParsedCompletely()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
multimap<eParamType,string> posXs;
|
||||||
|
func->GetNeededPosX(&posXs);
|
||||||
|
for (map<eParamType, string>::iterator names = posXs.begin(); names !=posXs.end(); names++) {
|
||||||
|
eParamType type = names->first;
|
||||||
|
string label = names->second;
|
||||||
|
int funcX = 0;
|
||||||
|
for (vector<cTemplateFunction*>::iterator it = functions.begin(); it != functions.end(); it++) {
|
||||||
|
cTemplateFunction *myFunc = *it;
|
||||||
|
string myFuncName = myFunc->GetParameter(ptName);
|
||||||
|
if (!myFuncName.compare(label)) {
|
||||||
|
funcX = myFunc->GetNumericParameter(ptX);
|
||||||
|
if (funcX > -1) {
|
||||||
|
func->SetX(type, label, funcX);
|
||||||
|
if (func->Updated()) {
|
||||||
|
func->CompleteParameters();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cTemplatePixmap::ReplacePosYFunctions(void) {
|
||||||
|
InitIterator();
|
||||||
|
cTemplateFunction *func = NULL;
|
||||||
|
while(func = GetNextFunction()) {
|
||||||
|
if (func->ParsedCompletely()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
multimap<eParamType,string> posYs;
|
||||||
|
func->GetNeededPosY(&posYs);
|
||||||
|
for (map<eParamType, string>::iterator names = posYs.begin(); names !=posYs.end(); names++) {
|
||||||
|
eParamType type = names->first;
|
||||||
|
string label = names->second;
|
||||||
|
int funcY = 0;
|
||||||
|
for (vector<cTemplateFunction*>::iterator it = functions.begin(); it != functions.end(); it++) {
|
||||||
|
cTemplateFunction *myFunc = *it;
|
||||||
|
string myFuncName = myFunc->GetParameter(ptName);
|
||||||
|
if (!myFuncName.compare(label)) {
|
||||||
|
funcY = myFunc->GetNumericParameter(ptY);
|
||||||
|
if (funcY > -1) {
|
||||||
|
func->SetY(type, label, funcY);
|
||||||
|
if (func->Updated()) {
|
||||||
|
func->CompleteParameters();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cTemplatePixmap::Debug(void) {
|
||||||
|
esyslog("skindesigner: pixmap container size x: %d, y: %d, width: %d, height %d", containerX, containerY, containerWidth, containerHeight);
|
||||||
|
parameters->Debug();
|
||||||
|
for (vector<cTemplateFunction*>::iterator it = functions.begin(); it != functions.end(); it++) {
|
||||||
|
(*it)->Debug();
|
||||||
|
}
|
||||||
|
}
|
82
libtemplate/templatepixmap.h
Normal 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> > ¶ms);
|
||||||
|
void SetWidth(int width);
|
||||||
|
void SetHeight(int height);
|
||||||
|
void SetX(int x);
|
||||||
|
void SetY(int y);
|
||||||
|
void SetContainer(int x, int y, int w, int h);
|
||||||
|
void SetGlobals(cGlobals *globals) { this->globals = globals; };
|
||||||
|
void AddFunction(string name, vector<pair<string, string> > ¶ms);
|
||||||
|
void AddLoopFunction(cTemplateLoopFunction *lf);
|
||||||
|
//PreCache Parameters
|
||||||
|
bool CalculateParameters(void);
|
||||||
|
//clear dynamically set function parameters
|
||||||
|
void ClearDynamicFunctionParameters(void);
|
||||||
|
//Clear dynamically set pixmap parameters
|
||||||
|
void ClearDynamicParameters(void);
|
||||||
|
//Parse pixmap parameters with dynamically set Tokens
|
||||||
|
void ParseDynamicParameters(map <string,int> *intTokens, bool initFuncs);
|
||||||
|
//Parse all function parameters with dynamically set Tokens
|
||||||
|
void ParseDynamicFunctionParameters(map <string,string> *stringTokens, map <string,int> *intTokens);
|
||||||
|
//Calculate size of drawport in case area scrolls
|
||||||
|
bool CalculateDrawPortSize(cSize &size, map < string, vector< map< string, string > > > *loopTokens = NULL);
|
||||||
|
//Set max width for text in scrollarea
|
||||||
|
void SetScrollingTextWidth(void);
|
||||||
|
//Getter Functions
|
||||||
|
cRect GetPixmapSize(void);
|
||||||
|
int GetNumericParameter(eParamType type);
|
||||||
|
bool Scrolling(void) { return scrolling; };
|
||||||
|
bool DoExecute(void) { return parameters->DoExecute(); };
|
||||||
|
bool DoDebug(void) { return parameters->DoDebug(); };
|
||||||
|
bool Ready(void);
|
||||||
|
//Traverse Functions
|
||||||
|
void InitIterator(void);
|
||||||
|
cTemplateFunction *GetNextFunction(void);
|
||||||
|
//Debug
|
||||||
|
void Debug(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //__TEMPLATEPIXMAP_H
|
1567
libtemplate/templateview.c
Normal file
198
libtemplate/templateview.h
Normal 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> > ¶ms);
|
||||||
|
void SetContainer(int x, int y, int width, int height);
|
||||||
|
//access view elements
|
||||||
|
cTemplateViewElement *GetViewElement(eViewElement ve);
|
||||||
|
void InitViewElementIterator(void);
|
||||||
|
cTemplateViewElement *GetNextViewElement(void);
|
||||||
|
//access list elements
|
||||||
|
cTemplateViewList *GetViewList(eViewList vl);
|
||||||
|
void InitViewListIterator(void);
|
||||||
|
cTemplateViewList *GetNextViewList(void);
|
||||||
|
//access tabs
|
||||||
|
void InitViewTabIterator(void);
|
||||||
|
cTemplateViewTab *GetNextViewTab(void);
|
||||||
|
//access sub views
|
||||||
|
cTemplateView *GetSubView(eSubView sv);
|
||||||
|
void InitSubViewIterator(void);
|
||||||
|
cTemplateView *GetNextSubView(void);
|
||||||
|
//Getter Functions
|
||||||
|
const char *GetViewName(void) { return viewName.c_str(); };
|
||||||
|
int GetNumericParameter(eParamType type);
|
||||||
|
cRect GetOsdSize(void);
|
||||||
|
int GetNumPixmaps(void);
|
||||||
|
int GetNumPixmapsViewElement(eViewElement ve);
|
||||||
|
int GetNumListViewMenuItems(void);
|
||||||
|
bool GetScalingWindow(cRect &scalingWindow);
|
||||||
|
//Checks for parsing template XML files
|
||||||
|
bool ValidSubView(const char *subView);
|
||||||
|
bool ValidViewElement(const char *viewElement);
|
||||||
|
bool ValidViewList(const char *viewList);
|
||||||
|
bool ValidFunction(const char *func);
|
||||||
|
bool ValidAttribute(const char *func, const char *att);
|
||||||
|
//Caching
|
||||||
|
void Translate(void);
|
||||||
|
void PreCache(bool isSubview);
|
||||||
|
//Debug
|
||||||
|
void Debug(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
// --- cTemplateViewChannel -------------------------------------------------------------
|
||||||
|
|
||||||
|
class cTemplateViewChannel : public cTemplateView {
|
||||||
|
private:
|
||||||
|
void SetViewElements(void);
|
||||||
|
void SetViewLists(void);
|
||||||
|
public:
|
||||||
|
cTemplateViewChannel(void);
|
||||||
|
virtual ~cTemplateViewChannel(void);
|
||||||
|
string GetViewElementName(eViewElement ve);
|
||||||
|
void AddPixmap(string viewElement, cTemplatePixmap *pix, bool debugViewElement);
|
||||||
|
};
|
||||||
|
|
||||||
|
// --- cTemplateViewMenu -------------------------------------------------------------
|
||||||
|
|
||||||
|
class cTemplateViewMenu : public cTemplateView {
|
||||||
|
private:
|
||||||
|
void SetSubViews(void);
|
||||||
|
void SetViewElements(void);
|
||||||
|
void SetViewLists(void);
|
||||||
|
public:
|
||||||
|
cTemplateViewMenu(void);
|
||||||
|
virtual ~cTemplateViewMenu(void);
|
||||||
|
string GetSubViewName(eSubView sv);
|
||||||
|
string GetViewElementName(eViewElement ve);
|
||||||
|
string GetViewListName(eViewList vl);
|
||||||
|
void AddSubView(string sSubView, cTemplateView *subView);
|
||||||
|
void AddPixmap(string viewElement, cTemplatePixmap *pix, bool debugViewElement);
|
||||||
|
void AddViewList(string sViewList, cTemplateViewList *viewList);
|
||||||
|
void AddViewTab(cTemplateViewTab *viewTab);
|
||||||
|
};
|
||||||
|
|
||||||
|
// --- cTemplateViewMessage -------------------------------------------------------------
|
||||||
|
|
||||||
|
class cTemplateViewMessage : public cTemplateView {
|
||||||
|
private:
|
||||||
|
void SetViewElements(void);
|
||||||
|
public:
|
||||||
|
cTemplateViewMessage(void);
|
||||||
|
virtual ~cTemplateViewMessage(void);
|
||||||
|
string GetViewElementName(eViewElement ve);
|
||||||
|
void AddPixmap(string viewElement, cTemplatePixmap *pix, bool debugViewElement);
|
||||||
|
};
|
||||||
|
|
||||||
|
// --- cTemplateViewReplay -------------------------------------------------------------
|
||||||
|
|
||||||
|
class cTemplateViewReplay : public cTemplateView {
|
||||||
|
private:
|
||||||
|
void SetViewElements(void);
|
||||||
|
public:
|
||||||
|
cTemplateViewReplay(void);
|
||||||
|
virtual ~cTemplateViewReplay(void);
|
||||||
|
string GetViewElementName(eViewElement ve);
|
||||||
|
void AddPixmap(string viewElement, cTemplatePixmap *pix, bool debugViewElement);
|
||||||
|
};
|
||||||
|
|
||||||
|
// --- cTemplateViewVolume -------------------------------------------------------------
|
||||||
|
|
||||||
|
class cTemplateViewVolume : public cTemplateView {
|
||||||
|
private:
|
||||||
|
void SetViewElements(void);
|
||||||
|
public:
|
||||||
|
cTemplateViewVolume(void);
|
||||||
|
virtual ~cTemplateViewVolume(void);
|
||||||
|
string GetViewElementName(eViewElement ve);
|
||||||
|
void AddPixmap(string viewElement, cTemplatePixmap *pix, bool debugViewElement);
|
||||||
|
};
|
||||||
|
|
||||||
|
// --- cTemplateViewAudioTracks -------------------------------------------------------------
|
||||||
|
|
||||||
|
class cTemplateViewAudioTracks : public cTemplateView {
|
||||||
|
private:
|
||||||
|
void SetViewElements(void);
|
||||||
|
void SetViewLists(void);
|
||||||
|
public:
|
||||||
|
cTemplateViewAudioTracks(void);
|
||||||
|
virtual ~cTemplateViewAudioTracks(void);
|
||||||
|
string GetViewElementName(eViewElement ve);
|
||||||
|
string GetViewListName(eViewList vl);
|
||||||
|
void AddPixmap(string viewElement, cTemplatePixmap *pix, bool debugViewElement);
|
||||||
|
void AddViewList(string sViewList, cTemplateViewList *viewList);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //__TEMPLATEVIEW_H
|
128
libtemplate/templateviewelement.c
Normal 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> > ¶ms) {
|
||||||
|
parameters = new cTemplateFunction(ftViewElement);
|
||||||
|
parameters->SetGlobals(globals);
|
||||||
|
parameters->SetParameters(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cTemplateViewElement::CalculateParameters(void) {
|
||||||
|
if (!parameters)
|
||||||
|
return true;
|
||||||
|
bool paramsValid = true;
|
||||||
|
parameters->SetContainer(containerX, containerY, containerWidth, containerHeight);
|
||||||
|
parameters->SetGlobals(globals);
|
||||||
|
paramsValid = parameters->CalculateParameters();
|
||||||
|
|
||||||
|
return paramsValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cTemplateViewElement::CalculatePixmapParameters(void) {
|
||||||
|
bool paramsValid = true;
|
||||||
|
for (vector<cTemplatePixmap*>::iterator pix = viewPixmaps.begin(); pix != viewPixmaps.end(); pix++) {
|
||||||
|
(*pix)->SetContainer(containerX, containerY, containerWidth, containerHeight);
|
||||||
|
(*pix)->SetGlobals(globals);
|
||||||
|
paramsValid = paramsValid && (*pix)->CalculateParameters();
|
||||||
|
}
|
||||||
|
return paramsValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cTemplateViewElement::CalculatePixmapParametersList(int orientation, int numElements) {
|
||||||
|
bool paramsValid = true;
|
||||||
|
for (vector<cTemplatePixmap*>::iterator pix = viewPixmaps.begin(); pix != viewPixmaps.end(); pix++) {
|
||||||
|
(*pix)->SetContainer(containerX, containerY, containerWidth, containerHeight);
|
||||||
|
(*pix)->SetGlobals(globals);
|
||||||
|
if (orientation == orHorizontal) {
|
||||||
|
if (numElements > 0) {
|
||||||
|
int width = containerWidth / numElements;
|
||||||
|
(*pix)->SetWidth(width);
|
||||||
|
}
|
||||||
|
} else if (orientation == orVertical) {
|
||||||
|
if (numElements > 0) {
|
||||||
|
int height = containerHeight / numElements;
|
||||||
|
(*pix)->SetHeight(height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
paramsValid = paramsValid && (*pix)->CalculateParameters();
|
||||||
|
}
|
||||||
|
return paramsValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cTemplateViewElement::GetNumericParameter(eParamType type) {
|
||||||
|
if (!parameters)
|
||||||
|
return -1;
|
||||||
|
return parameters->GetNumericParameter(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cTemplateViewElement::InitIterator(void) {
|
||||||
|
pixIterator = viewPixmaps.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
cTemplatePixmap *cTemplateViewElement::GetNextPixmap(void) {
|
||||||
|
if (pixIterator == viewPixmaps.end())
|
||||||
|
return NULL;
|
||||||
|
cTemplatePixmap *pix = *pixIterator;
|
||||||
|
pixIterator++;
|
||||||
|
return pix;
|
||||||
|
}
|
||||||
|
|
||||||
|
cTemplateFunction *cTemplateViewElement::GetFunction(string name) {
|
||||||
|
InitIterator();
|
||||||
|
cTemplatePixmap *pix = NULL;
|
||||||
|
while (pix = GetNextPixmap()) {
|
||||||
|
pix->InitIterator();
|
||||||
|
cTemplateFunction *func = NULL;
|
||||||
|
while(func = pix->GetNextFunction()) {
|
||||||
|
if (func->GetType() == ftDrawText) {
|
||||||
|
string funcName = func->GetParameter(ptName);
|
||||||
|
if (!funcName.compare(name))
|
||||||
|
return func;
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cTemplateViewElement::Debug(void) {
|
||||||
|
esyslog("skindesigner: viewelement container size x: %d, y: %d, width: %d, height %d", containerX, containerY, containerWidth, containerHeight);
|
||||||
|
if (parameters)
|
||||||
|
parameters->Debug();
|
||||||
|
for (vector<cTemplatePixmap*>::iterator it = viewPixmaps.begin(); it != viewPixmaps.end(); it++) {
|
||||||
|
(*it)->Debug();
|
||||||
|
}
|
||||||
|
}
|
99
libtemplate/templateviewelement.h
Normal 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> > ¶ms);
|
||||||
|
bool CalculateParameters(void);
|
||||||
|
bool CalculatePixmapParameters(void);
|
||||||
|
bool CalculatePixmapParametersList(int orientation, int numElements);
|
||||||
|
int GetNumericParameter(eParamType type);
|
||||||
|
void AddPixmap(cTemplatePixmap *pix) { viewPixmaps.push_back(pix); };
|
||||||
|
virtual void SetGlobals(cGlobals *globals);
|
||||||
|
void SetContainer(int x, int y, int width, int height);
|
||||||
|
void SetPixOffset(int offset) { pixOffset = offset; };
|
||||||
|
int GetPixOffset(void) { return pixOffset; };
|
||||||
|
virtual int GetNumPixmaps(void) { return viewPixmaps.size(); };
|
||||||
|
void InitIterator(void);
|
||||||
|
cTemplatePixmap *GetNextPixmap(void);
|
||||||
|
cTemplateFunction *GetFunction(string name);
|
||||||
|
void ActivateDebugTokens(void) {debugTokens = true; };
|
||||||
|
bool DebugTokens(void) { return debugTokens; };
|
||||||
|
virtual void Debug(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //__TEMPLATEVIEWELEMENT_H
|
138
libtemplate/templateviewlist.c
Normal 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();
|
||||||
|
}
|
49
libtemplate/templateviewlist.h
Normal 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
|
38
libtemplate/templateviewtab.c
Normal 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: -------------------------------------------------------");
|
||||||
|
}
|
31
libtemplate/templateviewtab.h
Normal 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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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!
|
BIN
skins/default/graphics/icons/ico_ac3.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
skins/default/graphics/icons/ico_activetimer.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
skins/default/graphics/icons/ico_channelsep.png
Normal file
After Width: | Height: | Size: 958 B |
BIN
skins/default/graphics/icons/ico_crypt_off.png
Normal file
After Width: | Height: | Size: 386 B |
BIN
skins/default/graphics/icons/ico_crypt_on.png
Normal file
After Width: | Height: | Size: 369 B |
BIN
skins/default/graphics/icons/ico_cutted.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
skins/default/graphics/icons/ico_discusage.png
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
skins/default/graphics/icons/ico_dolby_off.png
Normal file
After Width: | Height: | Size: 458 B |
BIN
skins/default/graphics/icons/ico_dolby_on.png
Normal file
After Width: | Height: | Size: 413 B |
BIN
skins/default/graphics/icons/ico_ff.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
skins/default/graphics/icons/ico_ff_1x.png
Normal file
After Width: | Height: | Size: 5.1 KiB |
BIN
skins/default/graphics/icons/ico_ff_2x.png
Normal file
After Width: | Height: | Size: 5.4 KiB |
BIN
skins/default/graphics/icons/ico_ff_3x.png
Normal file
After Width: | Height: | Size: 5.5 KiB |
BIN
skins/default/graphics/icons/ico_ff_off.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
skins/default/graphics/icons/ico_hd_off.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
skins/default/graphics/icons/ico_hd_on.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
skins/default/graphics/icons/ico_line_off.png
Normal file
After Width: | Height: | Size: 147 B |
BIN
skins/default/graphics/icons/ico_line_on.png
Normal file
After Width: | Height: | Size: 958 B |
BIN
skins/default/graphics/icons/ico_mute.png
Normal file
After Width: | Height: | Size: 3.0 KiB |
BIN
skins/default/graphics/icons/ico_pause.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
skins/default/graphics/icons/ico_pause_off.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
skins/default/graphics/icons/ico_play.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
skins/default/graphics/icons/ico_play_off.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
skins/default/graphics/icons/ico_rec_off.png
Normal file
After Width: | Height: | Size: 788 B |
BIN
skins/default/graphics/icons/ico_rec_on.png
Normal file
After Width: | Height: | Size: 1.1 KiB |