summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Schirrmacher <vdr.skinflat@schirrmacher.eu>2013-07-29 13:18:57 (GMT)
committerMartin Schirrmacher <vdr.skinflat@schirrmacher.eu>2013-07-29 13:18:57 (GMT)
commit7472f2b15cc861d71bc645fe96862139c529a387 (patch)
treea9aff30d93d8314e433220f8ec83156b2860cffc
downloadskin-flat-7472f2b15cc861d71bc645fe96862139c529a387.tar.gz
skin-flat-7472f2b15cc861d71bc645fe96862139c529a387.tar.bz2
initial commit
-rw-r--r--COPYING340
-rw-r--r--HISTORY5
-rw-r--r--Makefile136
-rw-r--r--README47
-rw-r--r--baserender.c276
-rw-r--r--baserender.h79
-rw-r--r--displaychannel.c192
-rw-r--r--displaychannel.h25
-rw-r--r--displaymenu.c191
-rw-r--r--displaymenu.h37
-rw-r--r--displaymessage.c22
-rw-r--r--displaymessage.h12
-rw-r--r--displayreplay.c141
-rw-r--r--displayreplay.h28
-rw-r--r--displaytracks.c58
-rw-r--r--displaytracks.h20
-rw-r--r--displayvolume.c56
-rw-r--r--displayvolume.h21
-rw-r--r--flat.c50
-rw-r--r--flat.h101
-rwxr-xr-xgenerate_theme.sh141
-rw-r--r--icons/COPYRIGHT11
-rw-r--r--icons/default/forward.pngbin0 -> 3360 bytes
-rw-r--r--icons/default/forward_sel.pngbin0 -> 2501 bytes
-rw-r--r--icons/default/mute.pngbin0 -> 2665 bytes
-rw-r--r--icons/default/pause.pngbin0 -> 3391 bytes
-rw-r--r--icons/default/pause_sel.pngbin0 -> 2023 bytes
-rw-r--r--icons/default/play.pngbin0 -> 4123 bytes
-rw-r--r--icons/default/play_sel.pngbin0 -> 2811 bytes
-rw-r--r--icons/default/prev.pngbin0 -> 5373 bytes
-rw-r--r--icons/default/prev_sel.pngbin0 -> 3386 bytes
-rw-r--r--icons/default/rewind.pngbin0 -> 3543 bytes
-rw-r--r--icons/default/rewind_sel.pngbin0 -> 2531 bytes
-rw-r--r--icons/default/skip.pngbin0 -> 5208 bytes
-rw-r--r--icons/default/skip_sel.pngbin0 -> 3446 bytes
-rw-r--r--icons/white/forward.pngbin0 -> 3095 bytes
-rw-r--r--icons/white/forward_sel.pngbin0 -> 2501 bytes
-rw-r--r--icons/white/mute.pngbin0 -> 8345 bytes
-rw-r--r--icons/white/pause.pngbin0 -> 3016 bytes
-rw-r--r--icons/white/pause_sel.pngbin0 -> 2023 bytes
-rw-r--r--icons/white/play.pngbin0 -> 3772 bytes
-rw-r--r--icons/white/play_sel.pngbin0 -> 2811 bytes
-rw-r--r--icons/white/prev.pngbin0 -> 5011 bytes
-rw-r--r--icons/white/prev_sel.pngbin0 -> 3386 bytes
-rw-r--r--icons/white/rewind.pngbin0 -> 3267 bytes
-rw-r--r--icons/white/rewind_sel.pngbin0 -> 2531 bytes
-rw-r--r--icons/white/skip.pngbin0 -> 4761 bytes
-rw-r--r--icons/white/skip_sel.pngbin0 -> 3446 bytes
-rw-r--r--imageloader.c281
-rw-r--r--imageloader.h46
-rw-r--r--po/de_DE.po19
-rw-r--r--skinflat.c117
-rw-r--r--symbols/arrowdown.xpm17
-rw-r--r--symbols/arrowup.xpm17
-rw-r--r--symbols/audio.xpm23
-rw-r--r--symbols/audioleft.xpm23
-rw-r--r--symbols/audioright.xpm23
-rw-r--r--symbols/audiostereo.xpm23
-rw-r--r--symbols/dolbydigital.xpm23
-rw-r--r--symbols/encrypted.xpm23
-rw-r--r--symbols/ffwd.xpm31
-rw-r--r--symbols/ffwd1.xpm31
-rw-r--r--symbols/ffwd2.xpm31
-rw-r--r--symbols/ffwd3.xpm31
-rw-r--r--symbols/frew.xpm31
-rw-r--r--symbols/frew1.xpm31
-rw-r--r--symbols/frew2.xpm31
-rw-r--r--symbols/frew3.xpm31
-rw-r--r--symbols/mute.xpm25
-rw-r--r--symbols/pause.xpm31
-rw-r--r--symbols/play.xpm31
-rw-r--r--symbols/radio.xpm23
-rw-r--r--symbols/recording.xpm23
-rw-r--r--symbols/sfwd.xpm31
-rw-r--r--symbols/sfwd1.xpm31
-rw-r--r--symbols/sfwd2.xpm31
-rw-r--r--symbols/sfwd3.xpm31
-rw-r--r--symbols/srew.xpm31
-rw-r--r--symbols/srew1.xpm31
-rw-r--r--symbols/srew2.xpm31
-rw-r--r--symbols/srew3.xpm31
-rw-r--r--symbols/teletext.xpm23
-rw-r--r--symbols/volume.xpm19
-rw-r--r--themes/flat-white.theme49
84 files changed, 3344 insertions, 0 deletions
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..f90922e
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <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.
diff --git a/HISTORY b/HISTORY
new file mode 100644
index 0000000..2b365c2
--- /dev/null
+++ b/HISTORY
@@ -0,0 +1,5 @@
+VDR Plugin 'skinflat' Revision History
+---------------------------------------
+
+2013-XX-XX: Version 0.0.1
+- Erste Version \ No newline at end of file
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..2fc80b5
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,136 @@
+#
+# Makefile for a Video Disk Recorder plugin
+#
+# $Id$
+
+# The official name of this plugin.
+# This name will be used in the '-P...' option of VDR to load the plugin.
+# By default the main source file also carries this name.
+# IMPORTANT: the presence of this macro is important for the Make.config
+# file. So it must be defined, even if it is not used here!
+#
+PLUGIN = skinflat
+
+### 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 (add further entries here):
+
+INCLUDES += $(shell pkg-config --cflags-only-I Magick++)
+
+DEFINES += -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
+DEFINES += -DMAGICKCORE_HDRI_ENABLE=0
+DEFINES += -DMAGICKCORE_QUANTUM_DEPTH=16
+
+LIBS += $(shell pkg-config --libs Magick++)
+
+### The object files (add further files here):
+
+OBJS = imageloader.o baserender.o displaychannel.o displaymenu.o displaymessage.o \
+ displayreplay.o displaytracks.o displayvolume.o flat.o $(PLUGIN).o
+
+### The main target:
+
+all: $(SOFILE) i18n
+
+### Implicit rules:
+
+%.o: %.c
+ $(CXX) -Wall $(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-icons:
+ mkdir -p $(DESTDIR)$(VDRCONFDIR)/plugins/$(PLUGIN)/icons
+ cp -r icons/* $(DESTDIR)$(VDRCONFDIR)/plugins/$(PLUGIN)/icons
+
+install: install-lib install-i18n install-themes install-icons
+
+dist: $(I18Npo) clean
+ @-rm -rf $(TMPDIR)/$(ARCHIVE)
+ @mkdir $(TMPDIR)/$(ARCHIVE)
+ @cp -a * $(TMPDIR)/$(ARCHIVE)
+ @tar czf $(PACKAGE).tgz --exclude .git* --exclude *.o --exclude *.rej --exclude *.orig -C $(TMPDIR) $(ARCHIVE)
+ @-rm -rf $(TMPDIR)/$(ARCHIVE)
+ @echo Distribution package created as $(PACKAGE).tgz
+
+clean:
+ @-rm -f $(PODIR)/*.mo $(PODIR)/*.pot
+ @-rm -f $(OBJS) $(DEPFILE) *.so *.tgz core* *~
diff --git a/README b/README
new file mode 100644
index 0000000..4c1ffcf
--- /dev/null
+++ b/README
@@ -0,0 +1,47 @@
+This is a "plugin" for the Video Disk Recorder (VDR).
+
+Written by: Martin Schirrmacher <vdr.skinflat@schirrmacher.eu>
+Based on: skin-nOpacity from Louis Braun
+ http://projects.vdr-developer.org/projects/skin-nopacity/
+
+Project's homepage: http://projects.vdr-developer.org/projects/plg-skinflat/
+
+
+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.
+
+Requirements
+------------
+
+- VDR version >= 1.7.34
+
+- Installed ImageMagick for displaying png/jpg Icons, Channel Logos and EPG Images
+
+Description
+-----------
+skinflat ist ein einfacher und schlanker Skin für VDR.
+
+Installation
+------------
+Installation wie bei allen VDR Plugins.
+ make
+ make install
+
+Für die Kanallogos empfehle ich die Logos von 3PO Repo (https://github.com/3PO/Senderlogos).
+Diese können mit folgendem Befehl heruntergeladen werden:
+ git clone https://github.com/3PO/Senderlogos.git logos
+Die Logos müssen im folgenden Ordner zur Verfügung gestellt werden:
+ <vdrconfigdir>/plugins/skinflat/logos/
+
+Der Skin muss im Menü unter Einstellungen -> OSD ausgewählt werden.
+
+
+Themes and theme specific Icons
+-------------------------------
+Der Skin ist weitestgehend über Themes anpassbar.
+Für die einfache Erstellung eines Themes existiert im Quellcode-Verzeichnis folgendes script:
+ generate_theme.sh
+Damit kann einfach ein neues Theme erstellt werden.
diff --git a/baserender.c b/baserender.c
new file mode 100644
index 0000000..121ee07
--- /dev/null
+++ b/baserender.c
@@ -0,0 +1,276 @@
+#include "baserender.h"
+#include "flat.h"
+
+cFlatBaseRender::cFlatBaseRender(void) {
+ font = cFont::CreateFont(Setup.FontOsd, Setup.FontOsdSize );
+ fontSml = cFont::CreateFont(Setup.FontSml, Setup.FontSmlSize);
+ fontFixed = cFont::CreateFont(Setup.FontFix, Setup.FontFixSize);
+
+ fontHeight = font->Height();
+ fontSmlHeight = fontSml->Height();
+
+ topBarTitle = "";
+ topBarLastDate = "";
+ topBarUpdateTitle = false;
+ topBarHeight = 0;
+
+ marginOsd = 5;
+ marginItem = 10;
+
+ buttonsHeight = 0;
+
+ topBarPixmap = NULL;
+ buttonsPixmap = NULL;
+ messagePixmap = NULL;
+ contentPixmap = NULL;
+}
+
+cFlatBaseRender::~cFlatBaseRender(void) {
+ delete font;
+ delete fontSml;
+ delete fontFixed;
+
+ if( osd )
+ {
+ if( topBarPixmap )
+ osd->DestroyPixmap(topBarPixmap);
+ if( buttonsPixmap )
+ osd->DestroyPixmap(buttonsPixmap);
+ if( messagePixmap )
+ osd->DestroyPixmap(messagePixmap);
+ if( contentPixmap )
+ osd->DestroyPixmap(contentPixmap);
+
+ delete osd;
+ }
+}
+
+void cFlatBaseRender::CreateFullOsd(void) {
+ CreateOsd(cOsd::OsdLeft() + marginOsd, cOsd::OsdTop() + marginOsd, cOsd::OsdWidth() - marginOsd*2, cOsd::OsdHeight() - marginOsd*2);
+}
+
+void cFlatBaseRender::CreateOsd(int left, int top, int width, int height) {
+ osdWidth = width;
+ osdHeight = height;
+
+ osd = cOsdProvider::NewOsd(left, top);
+ if (osd) {
+ tArea Area = { 0, 0, width, height, 32 };
+ if (osd->SetAreas(&Area, 1) == oeOk) {
+ return;
+ }
+ }
+ return;
+}
+
+void cFlatBaseRender::TopBarCreate(void) {
+ topBarHeight = fontHeight;
+
+ topBarPixmap = osd->CreatePixmap(1, cRect(0, 0, osdWidth, topBarHeight));
+ topBarPixmap->Fill(clrTransparent);
+}
+
+void cFlatBaseRender::TopBarSetTitle(cString title) {
+ topBarTitle = title;
+ topBarUpdateTitle = true;
+}
+
+// sollte bei jedum "Flush" aufgerufen werden!
+void cFlatBaseRender::TopBarUpdate(void) {
+ cString curDate = DayDateTime();
+ if ( strcmp(curDate, topBarLastDate) || topBarUpdateTitle ) {
+ topBarUpdateTitle = false;
+ topBarLastDate = curDate;
+
+ topBarPixmap->Fill(Theme.Color(clrTopBarBg));
+ topBarPixmap->DrawText(cPoint(50, 0), topBarTitle, Theme.Color(clrTopBarFont), clrTransparent, font);
+ int width = font->Width(*curDate);
+ topBarPixmap->DrawText(cPoint(osdWidth - width, 0), curDate, Theme.Color(clrTopBarDateTimeFont), clrTransparent, font);
+ }
+}
+
+void cFlatBaseRender::ButtonsCreate(void) {
+ buttonsHeight = fontHeight + 30;
+ buttonsWidth = osdWidth;
+
+ buttonsPixmap = osd->CreatePixmap(1, cRect(0, osdHeight - buttonsHeight, buttonsWidth, buttonsHeight));
+ buttonsPixmap->Fill(clrTransparent);
+}
+
+void cFlatBaseRender::ButtonsSet(const char *Red, const char *Green, const char *Yellow, const char *Blue) {
+ int buttonWidth = (buttonsWidth / 4) - marginItem;
+
+ buttonsPixmap->Fill(clrTransparent);
+
+ int x = 0;
+ buttonsPixmap->DrawText(cPoint(x, 0), Red, Theme.Color(clrButtonFont), Theme.Color(clrButtonBg), font, buttonWidth, 0, taCenter);
+ buttonsPixmap->DrawRectangle(cRect(x, fontHeight + 12, buttonWidth, 4), Theme.Color(clrButtonRed));
+
+ x += buttonWidth + marginItem;
+ buttonsPixmap->DrawText(cPoint(x, 0), Green, Theme.Color(clrButtonFont), Theme.Color(clrButtonBg), font, buttonWidth, 0, taCenter);
+ buttonsPixmap->DrawRectangle(cRect(x, fontHeight + 12, buttonWidth, 4), Theme.Color(clrButtonGreen));
+
+ x += buttonWidth + marginItem;
+ buttonsPixmap->DrawText(cPoint(x, 0), Yellow, Theme.Color(clrButtonFont), Theme.Color(clrButtonBg), font, buttonWidth, 0, taCenter);
+ buttonsPixmap->DrawRectangle(cRect(x, fontHeight + 12, buttonWidth, 4), Theme.Color(clrButtonYellow));
+
+ x += buttonWidth + marginItem;
+ buttonsPixmap->DrawText(cPoint(x, 0), Blue, Theme.Color(clrButtonFont), Theme.Color(clrButtonBg), font, buttonWidth, 0, taCenter);
+ buttonsPixmap->DrawRectangle(cRect(x, fontHeight + 12, buttonWidth, 4), Theme.Color(clrButtonBlue));
+}
+
+void cFlatBaseRender::MessageCreate(void) {
+ messageHeight = fontHeight;
+ messagePixmap = osd->CreatePixmap(2, cRect(0, osdHeight - messageHeight - 50, osdWidth, messageHeight));
+ messagePixmap->Fill(clrTransparent);
+}
+
+void cFlatBaseRender::MessageSet(eMessageType Type, const char *Text) {
+ tColor col = Theme.Color(clrMessageStatus);
+ switch (Type) {
+ case mtStatus:
+ col = Theme.Color(clrMessageStatus);
+ break;
+ case mtInfo:
+ col = Theme.Color(clrMessageInfo);
+ break;
+ case mtWarning:
+ col = Theme.Color(clrMessageWarning);
+ break;
+ case mtError:
+ col = Theme.Color(clrMessageError);
+ break;
+ }
+ messagePixmap->Fill(Theme.Color(clrMessageBg));
+
+ messagePixmap->DrawRectangle(cRect( 0, 0, 50, messageHeight), col);
+ messagePixmap->DrawRectangle(cRect( osdWidth - 50, 0, 50, messageHeight), col);
+
+ int textWidth = font->Width(Text);
+ messagePixmap->DrawText(cPoint((osdWidth - textWidth) / 2, 0), Text, Theme.Color(clrMessageFont), Theme.Color(clrMessageBg), font);
+}
+
+void cFlatBaseRender::MessageClear(void) {
+ messagePixmap->Fill(clrTransparent);
+}
+
+void cFlatBaseRender::ContentCreate(int Left, int Top, int Width, int Height) {
+ contentHasScrollbar = false;
+ contentShown = false;
+
+ contentLeft = Left;
+ contentTop = Top;
+ contentWidth = Width;
+ contentHeight = Height;
+ int lines = ContentVisibleLines();
+ contentHeight = lines * fontHeight;
+}
+
+void cFlatBaseRender::ContentSet(const char *Text, tColor ColorFg, tColor ColorBg) {
+ contentWrapper.Set(Text, font, contentWidth);
+ contentColorFg = ColorFg;
+ contentColorBg = ColorBg;
+
+ int contentWrapperHeight = (contentWrapper.Lines()+1) * fontHeight;
+
+ if( contentWrapperHeight > contentHeight ) {
+ contentDrawPortHeight = contentWrapperHeight;
+ contentHasScrollbar = true;
+ } else {
+ contentDrawPortHeight = contentHeight;
+ contentHasScrollbar = false;
+ }
+
+ contentPixmap = osd->CreatePixmap(2, cRect(contentLeft, contentTop, contentWidth, contentHeight),
+ cRect(0, 0, contentWidth, contentDrawPortHeight));
+
+ contentPixmap->Fill(contentColorBg);
+
+ contentDraw();
+ contentShown = true;
+}
+
+bool cFlatBaseRender::ContentScrollable(void) {
+ return contentHasScrollbar;
+}
+
+double cFlatBaseRender::ScrollbarSize(void) {
+ return (double)contentHeight / (double)contentDrawPortHeight;
+}
+
+int cFlatBaseRender::ContentScrollTotal(void) {
+ return contentWrapper.Lines();
+}
+
+int cFlatBaseRender::ContentGetHeight(void) {
+ return contentHeight;
+}
+
+int cFlatBaseRender::ContentScrollOffset(void) {
+ double offset;
+ if ( ((-1)*contentPixmap->DrawPort().Point().Y() + contentHeight + fontHeight) > contentDrawPortHeight)
+ offset = (double)1 - ScrollbarSize();
+ else
+ offset = (double)((-1)*contentPixmap->DrawPort().Point().Y())/(double)((-1)*contentPixmap->DrawPort().Point().Y() + contentHeight);
+ return ContentScrollTotal() * offset;
+}
+
+int cFlatBaseRender::ContentVisibleLines(void) {
+ return (contentHeight / fontHeight);
+}
+
+bool cFlatBaseRender::ContentScroll(bool Up, bool Page) {
+ int aktHeight = contentPixmap->DrawPort().Point().Y();
+ int totalHeight = contentPixmap->DrawPort().Height();
+ int screenHeight = contentPixmap->ViewPort().Height();
+ int lineHeight = fontHeight;
+ bool scrolled = false;
+ if (Up) {
+ if (Page) {
+ int newY = aktHeight + screenHeight;
+ if (newY > 0)
+ newY = 0;
+ contentPixmap->SetDrawPortPoint(cPoint(0, newY));
+ scrolled = true;
+ } else {
+ if (aktHeight < 0) {
+ contentPixmap->SetDrawPortPoint(cPoint(0, aktHeight + lineHeight));
+ scrolled = true;
+ }
+ }
+ } else {
+ if (Page) {
+ int newY = aktHeight - screenHeight;
+ if ((-1)*newY > totalHeight - screenHeight)
+ newY = (-1)*(totalHeight - screenHeight);
+ contentPixmap->SetDrawPortPoint(cPoint(0, newY));
+ scrolled = true;
+ } else {
+ if (totalHeight - ((-1)*aktHeight + lineHeight) > screenHeight) {
+ contentPixmap->SetDrawPortPoint(cPoint(0, aktHeight - lineHeight));
+ scrolled = true;
+ }
+ }
+ }
+ return scrolled;
+}
+
+bool cFlatBaseRender::ContentIsShown(void) {
+ return contentShown;
+}
+
+void cFlatBaseRender::ContentClear(void) {
+ if( contentPixmap )
+ contentPixmap->Fill(clrTransparent);
+ contentShown = false;
+}
+
+void cFlatBaseRender::contentDraw(void) {
+ int linesText = contentWrapper.Lines();
+ int currentHeight = 0;
+ for (int i=0; i < linesText; i++) {
+ //printf("drawLine: %d %s\n", i, contentWrapper.GetLine(i));
+ currentHeight = (i)*fontHeight;
+ contentPixmap->DrawText(cPoint(0, currentHeight), contentWrapper.GetLine(i), contentColorFg, contentColorBg, font, contentWidth);
+ }
+}
diff --git a/baserender.h b/baserender.h
new file mode 100644
index 0000000..9f0f823
--- /dev/null
+++ b/baserender.h
@@ -0,0 +1,79 @@
+#pragma once
+
+#include "flat.h"
+#include "imageloader.h"
+
+class cFlatBaseRender
+{
+ protected:
+ cOsd *osd;
+
+ int osdWidth, osdHeight;
+ int marginOsd;
+ int marginItem;
+
+ // Standard fonts
+ cFont *font;
+ cFont *fontSml;
+ cFont *fontFixed;
+ int fontHeight;
+ int fontSmlHeight;
+
+ // TopBar
+ cPixmap *topBarPixmap;
+ cString topBarTitle;
+ bool topBarUpdateTitle;
+ cString topBarLastDate;
+ int topBarHeight;
+
+ // Buttons rot, grün, gelb, blau
+ cPixmap *buttonsPixmap;
+ int buttonsWidth, buttonsHeight;
+
+ // Nachricht
+ cPixmap *messagePixmap;
+ int messageWidth, messageHeight;
+
+ // Mehrzeiliger Content mit Scrollbalken
+ cPixmap *contentPixmap;
+ int contentLeft, contentTop, contentHeight, contentWidth;
+ int contentDrawPortHeight; // gesamthöhe des Textes
+ bool contentHasScrollbar;
+ bool contentShown;
+ tColor contentColorFg, contentColorBg;
+ cTextWrapper contentWrapper;
+
+ void contentDraw(void);
+ double ScrollbarSize(void);
+
+ public:
+ cImageLoader imgLoader;
+
+ cFlatBaseRender(void);
+ ~cFlatBaseRender(void);
+
+ void CreateFullOsd(void);
+ void CreateOsd(int Left, int Top, int Width, int Height);
+
+ void TopBarCreate(void);
+ void TopBarSetTitle(cString title);
+ void TopBarUpdate(void);
+
+ void ButtonsCreate(void);
+ void ButtonsSet(const char *Red, const char *Green = NULL, const char *Yellow = NULL, const char *Blue = NULL);
+
+ void MessageCreate(void);
+ void MessageSet(eMessageType Type, const char *Text);
+ void MessageClear(void);
+
+ void ContentCreate(int Left, int Top, int Width, int Height);
+ void ContentSet(const char *Text, tColor ColorFg, tColor ColorBg);
+ bool ContentIsShown(void);
+ bool ContentScrollable(void);
+ int ContentScrollTotal(void);
+ int ContentScrollOffset(void);
+ int ContentVisibleLines(void);
+ int ContentGetHeight(void);
+ bool ContentScroll(bool Up, bool Page);
+ void ContentClear(void);
+};
diff --git a/displaychannel.c b/displaychannel.c
new file mode 100644
index 0000000..8607f54
--- /dev/null
+++ b/displaychannel.c
@@ -0,0 +1,192 @@
+#include "symbols/audio.xpm"
+#include "symbols/dolbydigital.xpm"
+
+#include "displaychannel.h"
+
+cFlatDisplayChannel::cFlatDisplayChannel(bool WithInfo) {
+ present = NULL;
+ channelName = "";
+
+ CreateFullOsd();
+ if ( !osd )
+ return;
+ TopBarCreate();
+ MessageCreate();
+
+ // von unten noch oben
+ // 2 * EPG + 2 * EPGsml
+ int heightProgress = 8;
+ heightBottom = (fontHeight * 2) + (fontSmlHeight * 2) + heightProgress; // Top, Buttom, Between
+ int heightTop = fontHeight;
+
+ int height = heightBottom;
+ chanInfoBottomPixmap = osd->CreatePixmap(1, cRect(0, osdHeight - height, osdWidth, heightBottom));
+
+ height += heightProgress;
+ chanInfoProgressPixmap = osd->CreatePixmap(2, cRect(0, osdHeight - height, osdWidth, heightProgress));
+ chanInfoProgressPixmap->Fill( clrTransparent );
+
+ height += heightTop + 2;
+ chanInfoTopPixmap = osd->CreatePixmap(1, cRect(0, osdHeight - height, osdWidth, heightTop));
+}
+
+cFlatDisplayChannel::~cFlatDisplayChannel() {
+ if (osd) {
+ osd->DestroyPixmap(chanInfoTopPixmap);
+ osd->DestroyPixmap(chanInfoProgressPixmap);
+ osd->DestroyPixmap(chanInfoBottomPixmap);
+ }
+}
+
+void cFlatDisplayChannel::SetChannel(const cChannel *Channel, int Number) {
+ cString channelNumber("");
+ if (Channel) {
+ channelName = Channel->Name();
+ if (!Channel->GroupSep())
+ channelNumber = cString::sprintf("%d%s", Channel->Number(), Number ? "-" : "");
+ else if (Number)
+ channelNumber = cString::sprintf("%d-", Number);
+ } else
+ channelName = ChannelString(NULL, 0);
+
+ cString channelString = cString::sprintf("%s %s", *channelNumber, *channelName);
+
+ chanInfoTopPixmap->Fill(Theme.Color(clrChannelBg));
+ chanInfoTopPixmap->DrawText(cPoint(50, 0), channelString, Theme.Color(clrChannelFontTitle), Theme.Color(clrChannelBg), font);
+}
+
+void cFlatDisplayChannel::SetEvents(const cEvent *Present, const cEvent *Following) {
+ present = Present;
+ cString epgShort("");
+ cString epg("");
+
+ chanInfoBottomPixmap->Fill(Theme.Color(clrChannelBg));
+
+ int imageHeight = heightBottom - marginItem*2;
+ if( imgLoader.LoadLogo(*channelName, imageHeight, imageHeight) ) {
+ int imageLeft = marginItem;
+ int imageTop = (heightBottom - imgLoader.Height() ) / 2;
+
+ chanInfoBottomPixmap->DrawImage( cPoint(imageLeft, imageTop), imgLoader.GetImage() );
+ }
+
+ int left = heightBottom + marginItem;
+
+ if( Present ) {
+ cString startTime = Present->GetTimeString();
+ cString endTime = Present->GetEndTimeString();
+
+ cString timeString = cString::sprintf("%s - %s", *startTime, *endTime);
+ int timeStringWidth = fontSml->Width(*timeString);
+
+ int epgWidth = font->Width(Present->Title());
+ int epgShortWidth = fontSml->Width(Present->ShortText());
+
+ int s = (int)(time(NULL) - Present->StartTime()) / 60;
+ int sleft = (Present->Duration() / 60) - s;
+
+ cString seen = cString::sprintf("%d-/%d+ (%d) min", s, sleft, Present->Duration() / 60);
+ int seenWidth = fontSml->Width(*seen);
+
+ if( epgWidth > osdWidth - left - timeStringWidth ) {
+ int dotsWidth = font->Width("... ");
+ cTextWrapper epgInfoWrapper(Present->Title(), font, osdWidth - left - timeStringWidth - dotsWidth);
+ epg = epgInfoWrapper.GetLine(0);
+ epg = cString::sprintf("%s...", *epg);
+ } else {
+ epg = Present->Title();
+ }
+
+ if( epgShortWidth > osdWidth - left - timeStringWidth ) {
+ int dotsWidth = fontSml->Width("... ");
+ cTextWrapper epgInfoWrapper(Present->ShortText(), fontSml, osdWidth - left - timeStringWidth - dotsWidth);
+ epgShort = epgInfoWrapper.GetLine(0);
+ epgShort = cString::sprintf("%s...", *epgShort);
+ } else {
+ epgShort = Present->ShortText();
+ }
+
+ chanInfoBottomPixmap->DrawText(cPoint(osdWidth - timeStringWidth, 0), *timeString,
+ Theme.Color(clrChannelFontEpg), Theme.Color(clrChannelBg), fontSml);
+ chanInfoBottomPixmap->DrawText(cPoint(osdWidth - seenWidth, fontSmlHeight), *seen,
+ Theme.Color(clrChannelFontEpg), Theme.Color(clrChannelBg), fontSml);
+
+ chanInfoBottomPixmap->DrawText(cPoint(left, 0), *epg, Theme.Color(clrChannelFontEpg), Theme.Color(clrChannelBg), font);
+ chanInfoBottomPixmap->DrawText(cPoint(left, fontHeight), *epgShort, Theme.Color(clrChannelFontEpg), Theme.Color(clrChannelBg), fontSml);
+
+ }
+ if( Following ) {
+ cString startTime = Following->GetTimeString();
+ cString endTime = Following->GetEndTimeString();
+
+ cString timeString = cString::sprintf("%s - %s", *startTime, *endTime);
+ int timeStringWidth = fontSml->Width(*timeString);
+
+ int epgWidth = fontSml->Width(Following->Title());
+ int epgShortWidth = fontSml->Width(Following->ShortText());
+
+ cString dur = cString::sprintf("%d min", Following->Duration() / 60);
+ int durWidth = fontSml->Width(*dur);
+
+ if( epgWidth > osdWidth - left - timeStringWidth ) {
+ int dotsWidth = font->Width("... ");
+ cTextWrapper epgInfoWrapper(Following->Title(), font, osdWidth - left - timeStringWidth - dotsWidth);
+ epg = epgInfoWrapper.GetLine(0);
+ epg = cString::sprintf("%s...", *epg);
+ } else {
+ epg = Following->Title();
+ }
+ if (epgShortWidth > osdWidth - left - timeStringWidth ) {
+ int dotsWidth = fontSml->Width("... ");
+ cTextWrapper epgInfoWrapper(Following->ShortText(), fontSml, osdWidth - left - timeStringWidth - dotsWidth);
+ epgShort = epgInfoWrapper.GetLine(0);
+ epgShort = cString::sprintf("%s...", *epgShort);
+ } else {
+ epgShort = Following->ShortText();
+ }
+
+ chanInfoBottomPixmap->DrawText(cPoint(osdWidth - timeStringWidth, fontHeight + fontSmlHeight), *timeString,
+ Theme.Color(clrChannelFontEpg), Theme.Color(clrChannelBg), fontSml);
+ chanInfoBottomPixmap->DrawText(cPoint(osdWidth - durWidth, fontHeight + fontSmlHeight*2), *dur,
+ Theme.Color(clrChannelFontEpg), Theme.Color(clrChannelBg), fontSml);
+
+ chanInfoBottomPixmap->DrawText(cPoint(left, fontHeight + fontSmlHeight), *epg,
+ Theme.Color(clrChannelFontEpg), Theme.Color(clrChannelBg), font);
+ chanInfoBottomPixmap->DrawText(cPoint(left, fontHeight*2 + fontSmlHeight), *epgShort,
+ Theme.Color(clrChannelFontEpg), Theme.Color(clrChannelBg), fontSml);
+ }
+}
+
+void cFlatDisplayChannel::DrawProgressBar(int Current, int Total) {
+ int barFullWidth = chanInfoProgressPixmap->ViewPort().Width();
+ double percentLeft = ((double)Current) / (double)Total;
+
+ chanInfoProgressPixmap->Fill( clrTransparent );
+
+ if (Current > 0) {
+ chanInfoProgressPixmap->DrawRectangle(cRect( 0, 2, barFullWidth, 2), Theme.Color(clrChannelProgressBg));
+ chanInfoProgressPixmap->DrawRectangle(cRect( 0, 0, (barFullWidth * percentLeft), 6), Theme.Color(clrChannelProgressFg));
+ }
+}
+
+void cFlatDisplayChannel::SetMessage(eMessageType Type, const char *Text) {
+ // Wenn es einen Text gibt, diesen Anzeigen ansonsten Message ausblenden
+ if( Text )
+ MessageSet(Type, Text);
+ else
+ MessageClear();
+}
+
+void cFlatDisplayChannel::Flush(void) {
+ int Current = 0;
+ int Total = 0;
+ if( present ) {
+ time_t t = time(NULL);
+ if (t > present->StartTime())
+ Current = t - present->StartTime();
+ Total = present->Duration();
+ DrawProgressBar(Current, Total);
+ }
+ TopBarUpdate();
+ osd->Flush();
+}
diff --git a/displaychannel.h b/displaychannel.h
new file mode 100644
index 0000000..033ae64
--- /dev/null
+++ b/displaychannel.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include "baserender.h"
+
+class cFlatDisplayChannel : public cFlatBaseRender, public cSkinDisplayChannel {
+ private:
+ const cEvent *present;
+
+ cString channelName;
+
+ cPixmap *chanInfoTopPixmap;
+ cPixmap *chanInfoProgressPixmap;
+ cPixmap *chanInfoBottomPixmap;
+
+ int heightBottom;
+
+ void DrawProgressBar(int Current, int Total);
+ public:
+ cFlatDisplayChannel(bool WithInfo);
+ virtual ~cFlatDisplayChannel();
+ 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);
+};
diff --git a/displaymenu.c b/displaymenu.c
new file mode 100644
index 0000000..f71fa33
--- /dev/null
+++ b/displaymenu.c
@@ -0,0 +1,191 @@
+#include "displaymenu.h"
+
+#include "symbols/arrowdown.xpm"
+#include "symbols/arrowup.xpm"
+
+cFlatDisplayMenu::cFlatDisplayMenu(void) {
+ CreateFullOsd();
+ TopBarCreate();
+ ButtonsCreate();
+ MessageCreate();
+
+ itemHeight = fontHeight + 2;
+
+ scrollBarWidth = 10;
+ scrollBarHeight = osdHeight - (topBarHeight + buttonsHeight + marginItem*2 );
+ scrollBarTop = topBarHeight + marginItem;
+
+ menuWidth = osdWidth - scrollBarWidth - marginItem;
+
+ menuPixmap = osd->CreatePixmap(1, cRect(0, topBarHeight + marginItem, menuWidth, scrollBarHeight ));
+
+ contentTop = topBarHeight + marginItem + fontHeight + (fontSmlHeight*2) + marginItem;
+ ContentCreate(0, contentTop, menuWidth, scrollBarHeight - fontHeight*2 -3);
+
+ scrollbarPixmap = osd->CreatePixmap(2, cRect(osdWidth - scrollBarWidth, scrollBarTop, scrollBarWidth, scrollBarHeight));
+
+ menuPixmap->Fill(clrTransparent);
+ scrollbarPixmap->Fill(clrTransparent);
+}
+
+cFlatDisplayMenu::~cFlatDisplayMenu() {
+ osd->DestroyPixmap(menuPixmap);
+ osd->DestroyPixmap(scrollbarPixmap);
+}
+
+void cFlatDisplayMenu::DrawScrollbar(int Total, int Offset, int Shown, int Top, int Height, bool CanScrollUp, bool CanScrollDown) {
+ if (Total > 0 && Total > Shown) {
+ int scrollHeight = max(int((Height) * double(Shown) / Total + 0.5), 5);
+ int scrollTop = min(int(Top + (Height) * double(Offset) / Total + 0.5), Top + Height - scrollHeight);
+
+ scrollbarPixmap->Fill(clrTransparent);
+
+ scrollbarPixmap->DrawRectangle(cRect(0, Top, 2, Height), Theme.Color(clrScrollbarBg));
+ scrollbarPixmap->DrawRectangle(cRect(0, scrollTop, 5, scrollHeight), Theme.Color(clrScrollbarFg));
+ }
+}
+
+void cFlatDisplayMenu::SetScrollbar(int Total, int Offset) {
+ DrawScrollbar(Total, Offset, MaxItems(), 0, ItemsHeight(), Offset > 0, Offset + MaxItems() < Total);
+}
+
+void cFlatDisplayMenu::Scroll(bool Up, bool Page) {
+ // Wird das Menü gescrollt oder Content?
+ if( ContentIsShown() )
+ {
+ bool scrolled = ContentScroll(Up, Page);
+ if( scrolled )
+ {
+ DrawScrollbar(ContentScrollTotal(), ContentScrollOffset(), ContentVisibleLines(), contentTop - scrollBarTop, ContentGetHeight(), ContentScrollOffset() > 0, ContentScrollOffset() + ContentVisibleLines() < ContentScrollTotal());
+ }
+ } else {
+ cSkinDisplayMenu::Scroll(Up, Page);
+ }
+}
+
+int cFlatDisplayMenu::MaxItems(void) {
+ return scrollBarHeight / itemHeight;
+}
+
+int cFlatDisplayMenu::ItemsHeight(void) {
+ return MaxItems() * itemHeight;
+}
+void cFlatDisplayMenu::Clear(void) {
+ textScroller.Reset();
+ menuPixmap->Fill(clrTransparent);
+ scrollbarPixmap->Fill(clrTransparent);
+ ContentClear();
+}
+
+void cFlatDisplayMenu::SetTitle(const char *Title) {
+ TopBarSetTitle(Title);
+}
+
+void cFlatDisplayMenu::SetButtons(const char *Red, const char *Green, const char *Yellow, const char *Blue) {
+ ButtonsSet(Red, Green, Yellow, Blue);
+}
+
+void cFlatDisplayMenu::SetMessage(eMessageType Type, const char *Text) {
+ if (Text)
+ MessageSet(Type, Text);
+ else
+ MessageClear();
+}
+
+void cFlatDisplayMenu::SetItem(const char *Text, int Index, bool Current, bool Selectable) {
+ int y = Index * itemHeight;
+ tColor ColorFg, ColorBg;
+ if (Current) {
+ ColorFg = Theme.Color(clrItemCurrentFont);
+ ColorBg = Theme.Color(clrItemCurrentBg);
+ }
+ else {
+ if( Selectable ) {
+ ColorFg = Theme.Color(clrItemSelableFont);
+ ColorBg = Theme.Color(clrItemSelableBg);
+ } else {
+ ColorFg = Theme.Color(clrItemFont);
+ ColorBg = Theme.Color(clrItemBg);
+ }
+ }
+
+ for (int i = 0; i < MaxTabs; i++)
+ {
+ const char *s = GetTabbedText(Text, i);
+ if (s) {
+ int xt = Tab(i);
+ menuPixmap->DrawText(cPoint(xt, y), s, ColorFg, ColorBg, font, menuWidth);
+ }
+ if (!Tab(i + 1))
+ break;
+ }
+}
+
+void cFlatDisplayMenu::SetEvent(const cEvent *Event) {
+ if( !Event )
+ return;
+
+ menuPixmap->Fill(clrTransparent);
+ cString date = Event->GetDateString();
+ cString startTime = Event->GetTimeString();
+ cString endTime = Event->GetEndTimeString();
+
+ cString timeString = cString::sprintf("%s %s - %s", *date, *startTime, *endTime);
+
+ cString title = Event->Title();
+ cString shortText = Event->ShortText();
+
+ menuPixmap->DrawText(cPoint(0, 0), timeString, Theme.Color(clrMenuEventFontInfo), Theme.Color(clrMenuEventBg), fontSml, menuWidth);
+ menuPixmap->DrawText(cPoint(0, fontSmlHeight), title, Theme.Color(clrMenuEventFontTitle), Theme.Color(clrMenuEventBg), font, menuWidth);
+ menuPixmap->DrawText(cPoint(0, fontSmlHeight + fontHeight), shortText, Theme.Color(clrMenuEventFontInfo), Theme.Color(clrMenuEventBg), fontSml, menuWidth);
+
+ ContentSet( Event->Description(), Theme.Color(clrMenuEventFontInfo), Theme.Color(clrMenuEventBg) );
+ if( ContentScrollable() )
+ DrawScrollbar(ContentScrollTotal(), ContentScrollOffset(), ContentVisibleLines(), contentTop - scrollBarTop, ContentGetHeight(), ContentScrollOffset() > 0, ContentScrollOffset() + ContentVisibleLines() < ContentScrollTotal());
+}
+
+void cFlatDisplayMenu::SetRecording(const cRecording *Recording) {
+ if( !Recording )
+ return;
+ menuPixmap->Fill(clrTransparent);
+
+ const cRecordingInfo *recInfo = Recording->Info();
+ cString timeString = cString::sprintf("%s %s %s", *DateString(Recording->Start()), *TimeString(Recording->Start()), recInfo->ChannelName() ? recInfo->ChannelName() : "");
+
+ cString title = recInfo->Title();
+ if( isempty(title) )
+ title = Recording->Name();
+ cString shortText = recInfo->ShortText();
+
+ menuPixmap->DrawText(cPoint(0, 0), timeString, Theme.Color(clrMenuRecFontInfo), Theme.Color(clrMenuRecBg), fontSml, menuWidth);
+ menuPixmap->DrawText(cPoint(0, fontSmlHeight), title, Theme.Color(clrMenuRecFontTitle), Theme.Color(clrMenuRecBg), font, menuWidth);
+ menuPixmap->DrawText(cPoint(0, fontSmlHeight + fontHeight), shortText, Theme.Color(clrMenuRecFontTitle), Theme.Color(clrMenuRecBg), fontSml, menuWidth);
+
+ ContentSet( recInfo->Description(), Theme.Color(clrMenuRecFontInfo), Theme.Color(clrMenuRecBg) );
+ if( ContentScrollable() )
+ DrawScrollbar(ContentScrollTotal(), ContentScrollOffset(), ContentVisibleLines(), contentTop - scrollBarTop, ContentGetHeight(), ContentScrollOffset() > 0, ContentScrollOffset() + ContentVisibleLines() < ContentScrollTotal());
+}
+
+void cFlatDisplayMenu::SetText(const char *Text, bool FixedFont) {
+ if( !Text )
+ return;
+ menuPixmap->Fill(clrTransparent);
+
+ ContentSet( Text, Theme.Color(clrMenuTextFont), Theme.Color(clrMenuTextBg) );
+ if( ContentScrollable() )
+ SetScrollbar( ContentScrollTotal(), 0 );
+}
+
+int cFlatDisplayMenu::GetTextAreaWidth(void) const {
+ return menuWidth - (marginItem*2);
+}
+
+const cFont *cFlatDisplayMenu::GetTextAreaFont(bool FixedFont) const {
+ const cFont *rfont = FixedFont ? fontFixed : font;
+ return rfont;
+}
+
+void cFlatDisplayMenu::Flush(void) {
+ TopBarUpdate();
+ osd->Flush();
+}
diff --git a/displaymenu.h b/displaymenu.h
new file mode 100644
index 0000000..fa97d8f
--- /dev/null
+++ b/displaymenu.h
@@ -0,0 +1,37 @@
+#pragma once
+
+#include "baserender.h"
+
+class cFlatDisplayMenu : public cFlatBaseRender, public cSkinDisplayMenu {
+ private:
+
+ cPixmap *menuPixmap;
+ int menuWidth;
+
+ int contentTop;
+
+ cPixmap *scrollbarPixmap;
+ int scrollBarTop, scrollBarWidth, scrollBarHeight;
+
+ int itemHeight;
+
+ void DrawScrollbar(int Total, int Offset, int Shown, int Top, int Height, bool CanScrollUp, bool CanScrollDown);
+ int ItemsHeight(void);
+ public:
+ cFlatDisplayMenu(void);
+ virtual ~cFlatDisplayMenu();
+ virtual void Scroll(bool Up, bool Page);
+ virtual int MaxItems(void);
+ virtual void Clear(void);
+ virtual void SetTitle(const char *Title);
+ virtual void SetButtons(const char *Red, const char *Green = NULL, const char *Yellow = NULL, const char *Blue = NULL);
+ virtual void SetMessage(eMessageType Type, const char *Text);
+ virtual void SetItem(const char *Text, int Index, bool Current, bool Selectable);
+ virtual void 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 int GetTextAreaWidth(void) const;
+ virtual const cFont *GetTextAreaFont(bool FixedFont) const;
+ virtual void Flush(void);
+};
diff --git a/displaymessage.c b/displaymessage.c
new file mode 100644
index 0000000..ec23f23
--- /dev/null
+++ b/displaymessage.c
@@ -0,0 +1,22 @@
+#include "displaymessage.h"
+
+cFlatDisplayMessage::cFlatDisplayMessage(void) {
+ CreateFullOsd();
+ TopBarCreate();
+ MessageCreate();
+}
+
+cFlatDisplayMessage::~cFlatDisplayMessage() {
+}
+
+void cFlatDisplayMessage::SetMessage(eMessageType Type, const char *Text) {
+ if (Text)
+ MessageSet(Type, Text);
+ else
+ MessageClear();
+}
+
+void cFlatDisplayMessage::Flush(void) {
+ TopBarUpdate();
+ osd->Flush();
+}
diff --git a/displaymessage.h b/displaymessage.h
new file mode 100644
index 0000000..2b1145a
--- /dev/null
+++ b/displaymessage.h
@@ -0,0 +1,12 @@
+#pragma once
+
+#include "baserender.h"
+
+class cFlatDisplayMessage : public cFlatBaseRender, public cSkinDisplayMessage {
+ private:
+ public:
+ cFlatDisplayMessage(void);
+ virtual ~cFlatDisplayMessage();
+ virtual void SetMessage(eMessageType Type, const char *Text);
+ virtual void Flush(void);
+};
diff --git a/displayreplay.c b/displayreplay.c
new file mode 100644
index 0000000..17a2655
--- /dev/null
+++ b/displayreplay.c
@@ -0,0 +1,141 @@
+#include "displayreplay.h"
+
+cFlatDisplayReplay::cFlatDisplayReplay(bool ModeOnly) {
+ progressBarHeight = 10;
+ labelHeight = fontHeight;
+ current = "";
+ total = "";
+ CreateFullOsd();
+ TopBarCreate();
+ MessageCreate();
+
+ labelPixmap = osd->CreatePixmap(1, cRect(0, osdHeight - 50 - labelHeight, osdWidth, labelHeight));
+ progressBarPixmap = osd->CreatePixmap(1, cRect(0, osdHeight - 50 - labelHeight - progressBarHeight, osdWidth, progressBarHeight));
+
+ labelPixmap->Fill(Theme.Color(clrReplayBg));
+ progressBarPixmap->Fill(clrTransparent);
+}
+
+cFlatDisplayReplay::~cFlatDisplayReplay() {
+ osd->DestroyPixmap(labelPixmap);
+ osd->DestroyPixmap(progressBarPixmap);
+}
+
+void cFlatDisplayReplay::SetRecording(const cRecording *Recording) {
+ const cRecordingInfo *recInfo = Recording->Info();
+ SetTitle( recInfo->Title() );
+ cString info = "";
+ if (recInfo->ShortText())
+ info = cString::sprintf("%s - %s %s", recInfo->ShortText(), *ShortDateString(Recording->Start()), *TimeString(Recording->Start()));
+ else
+ info = cString::sprintf("%s %s", *ShortDateString(Recording->Start()), *TimeString(Recording->Start()));
+
+ labelPixmap->DrawText(cPoint(0, 0), info, Theme.Color(clrReplayFont), Theme.Color(clrReplayBg), font, osdWidth);
+}
+
+void cFlatDisplayReplay::SetTitle(const char *Title) {
+ TopBarSetTitle(Title);
+}
+
+void cFlatDisplayReplay::SetMode(bool Play, bool Forward, int Speed) {
+ if( Setup.ShowReplayMode ) {
+ int left = osdWidth - (labelHeight * 4 + marginItem * 3);
+ left /= 2;
+
+ labelPixmap->DrawRectangle(cRect( left - font->Width("33") - marginItem, 0, labelHeight*4 + marginItem*6 + font->Width("33")*2, labelHeight), Theme.Color(clrReplayBg) );
+ labelPixmap->DrawRectangle(cRect( left - marginItem, 0, labelHeight*4 + marginItem*4, labelHeight), clrTransparent );
+
+ cString rewind, pause, play, forward;
+ cString speed;
+
+ if( Speed == -1 ) {
+ if( Play ) {
+ rewind = "rewind";
+ pause = "pause";
+ play = "play_sel";
+ forward = "forward";
+ } else {
+ rewind = "rewind";
+ pause = "pause_sel";
+ play = "play";
+ forward = "forward";
+ }
+ } else {
+ speed = cString::sprintf("%d", Speed);
+ if( Forward ) {
+ rewind = "rewind";
+ pause = "pause";
+ play = "play";
+ forward = "forward_sel";
+ labelPixmap->DrawText(cPoint(left + labelHeight*4 + marginItem*4, 0), speed, Theme.Color(clrReplayFont), Theme.Color(clrReplayBg), font);
+ } else {
+ rewind = "rewind_sel";
+ pause = "pause";
+ play = "play";
+ forward = "forward";
+ labelPixmap->DrawText(cPoint(left - font->Width(speed) - marginItem, 0), speed, Theme.Color(clrReplayFont), Theme.Color(clrReplayBg), font);
+ }
+ }
+
+ if( imgLoader.LoadIcon(*rewind, labelHeight, labelHeight) )
+ labelPixmap->DrawImage( cPoint(left, 0), imgLoader.GetImage() );
+ if( imgLoader.LoadIcon(*pause, labelHeight, labelHeight) )
+ labelPixmap->DrawImage( cPoint(left + labelHeight + marginItem, 0), imgLoader.GetImage() );
+ if( imgLoader.LoadIcon(*play, labelHeight, labelHeight) )
+ labelPixmap->DrawImage( cPoint(left + labelHeight*2 + marginItem*2, 0), imgLoader.GetImage() );
+ if( imgLoader.LoadIcon(*forward, labelHeight, labelHeight) )
+ labelPixmap->DrawImage( cPoint(left + labelHeight*3 + marginItem*3, 0), imgLoader.GetImage() );
+
+ }
+}
+
+void cFlatDisplayReplay::DrawProgressBar(int Current, int Total) {
+ int barFullWidth = progressBarPixmap->ViewPort().Width();
+ double percentLeft = ((double)Current) / (double)Total;
+
+ progressBarPixmap->Fill( clrTransparent );
+
+ if (Current > 0) {
+ progressBarPixmap->DrawRectangle(cRect( 0, 2, barFullWidth, 2), Theme.Color(clrReplayProgressBg));
+ progressBarPixmap->DrawRectangle(cRect( 0, 0, (barFullWidth * percentLeft), 6), Theme.Color(clrReplayProgressFg));
+ }
+}
+
+void cFlatDisplayReplay::SetProgress(int Current, int Total) {
+ DrawProgressBar(Current, Total);
+}
+
+void cFlatDisplayReplay::SetCurrent(const char *Current) {
+ current = Current;
+ UpdateInfo();
+}
+
+void cFlatDisplayReplay::SetTotal(const char *Total) {
+ total = Total;
+ UpdateInfo();
+}
+
+void cFlatDisplayReplay::UpdateInfo(void) {
+ cString Info = cString::sprintf("%s - %s", *current, *total);
+ int right = osdWidth - font->Width(Info);
+ labelPixmap->DrawText(cPoint(right, 0), Info, Theme.Color(clrReplayFont), Theme.Color(clrReplayBg), font, font->Width(Info), fontHeight);
+}
+
+void cFlatDisplayReplay::SetJump(const char *Jump) {
+ int left = osdWidth - font->Width(Jump);
+ left /= 2;
+
+ labelPixmap->DrawText(cPoint(left, 0), Jump, Theme.Color(clrReplayFont), Theme.Color(clrReplayBg), font, font->Width(Jump), fontHeight, taCenter);
+}
+
+void cFlatDisplayReplay::SetMessage(eMessageType Type, const char *Text) {
+ if (Text)
+ MessageSet(Type, Text);
+ else
+ MessageClear();
+}
+
+void cFlatDisplayReplay::Flush(void) {
+ TopBarUpdate();
+ osd->Flush();
+}
diff --git a/displayreplay.h b/displayreplay.h
new file mode 100644
index 0000000..026005c
--- /dev/null
+++ b/displayreplay.h
@@ -0,0 +1,28 @@
+#pragma once
+
+#include "baserender.h"
+
+class cFlatDisplayReplay : public cFlatBaseRender, public cSkinDisplayReplay {
+ private:
+ cString current, total;
+
+ int labelHeight;
+ int progressBarHeight;
+ cPixmap *progressBarPixmap;
+ cPixmap *labelPixmap;
+
+ void DrawProgressBar(int Current, int Total);
+ void UpdateInfo(void);
+ public:
+ cFlatDisplayReplay(bool ModeOnly);
+ virtual ~cFlatDisplayReplay();
+ 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);
+};
diff --git a/displaytracks.c b/displaytracks.c
new file mode 100644
index 0000000..326b9b3
--- /dev/null
+++ b/displaytracks.c
@@ -0,0 +1,58 @@
+#include "displaytracks.h"
+
+cFlatDisplayTracks::cFlatDisplayTracks(const char *Title, int NumTracks, const char * const *Tracks) {
+
+ CreateFullOsd();
+ TopBarCreate();
+
+ itemHeight = fontHeight + 2;
+ currentIndex = -1;
+ maxItemWidth = font->Width(Title);
+ for (int i = 0; i < NumTracks; i++)
+ maxItemWidth = max(maxItemWidth, font->Width(Tracks[i]));
+
+ int itemsHeight = NumTracks * itemHeight;
+ int left = osdWidth - maxItemWidth;
+ left /= 2;
+ TopBarSetTitle(Title);
+
+ tracksPixmap = osd->CreatePixmap(1, cRect(left, osdHeight - itemsHeight - marginItem, maxItemWidth, itemsHeight));
+ tracksPixmap->Fill(clrTransparent);
+
+ for (int i = 0; i < NumTracks; i++)
+ SetItem(Tracks[i], i, false);
+}
+
+cFlatDisplayTracks::~cFlatDisplayTracks() {
+ osd->DestroyPixmap(tracksPixmap);
+}
+
+void cFlatDisplayTracks::SetItem(const char *Text, int Index, bool Current) {
+ int y = Index * itemHeight;
+ tColor ColorFg, ColorBg;
+ if (Current) {
+ ColorFg = Theme.Color(clrTrackItemCurrentFont);
+ ColorBg = Theme.Color(clrTrackItemCurrentBg);
+ currentIndex = Index;
+ }
+ else {
+ ColorFg = Theme.Color(clrTrackItemFont);
+ ColorBg = Theme.Color(clrTrackItemBg);
+ }
+ tracksPixmap->DrawText(cPoint(0, y), Text, ColorFg, ColorBg, font, maxItemWidth, itemHeight - 2, taCenter);
+}
+
+void cFlatDisplayTracks::SetTrack(int Index, const char * const *Tracks) {
+ if (currentIndex >= 0)
+ SetItem(Tracks[currentIndex], currentIndex, false);
+ SetItem(Tracks[Index], Index, true);
+}
+
+void cFlatDisplayTracks::SetAudioChannel(int AudioChannel) {
+ return;
+}
+
+void cFlatDisplayTracks::Flush(void) {
+ TopBarUpdate();
+ osd->Flush();
+}
diff --git a/displaytracks.h b/displaytracks.h
new file mode 100644
index 0000000..da8d9bf
--- /dev/null
+++ b/displaytracks.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#include "baserender.h"
+
+class cFlatDisplayTracks : public cFlatBaseRender, public cSkinDisplayTracks {
+ private:
+ cPixmap *tracksPixmap;
+
+ int itemHeight;
+ int maxItemWidth;
+ int currentIndex;
+
+ void SetItem(const char *Text, int Index, bool Current);
+ public:
+ cFlatDisplayTracks(const char *Title, int NumTracks, const char * const *Tracks);
+ virtual ~cFlatDisplayTracks();
+ virtual void SetTrack(int Index, const char * const *Tracks);
+ virtual void SetAudioChannel(int AudioChannel);
+ virtual void Flush(void);
+};
diff --git a/displayvolume.c b/displayvolume.c
new file mode 100644
index 0000000..4575fc6
--- /dev/null
+++ b/displayvolume.c
@@ -0,0 +1,56 @@
+#include "symbols/mute.xpm"
+#include "displayvolume.h"
+
+cFlatDisplayVolume::cFlatDisplayVolume(void) {
+ muted = false;
+
+ progressBarHeight = 20;
+ labelHeight = fontHeight;
+
+ CreateFullOsd();
+ TopBarCreate();
+
+ progressBarPixmap = osd->CreatePixmap(1, cRect(0, osdHeight - 50 - progressBarHeight, osdWidth, progressBarHeight));
+ labelPixmap = osd->CreatePixmap(1, cRect(0, osdHeight - 50 - progressBarHeight - labelHeight - marginItem, osdWidth, labelHeight));
+}
+
+cFlatDisplayVolume::~cFlatDisplayVolume() {
+ osd->DestroyPixmap(labelPixmap);
+ osd->DestroyPixmap(progressBarPixmap);
+}
+
+void cFlatDisplayVolume::SetVolume(int Current, int Total, bool Mute) {
+ labelPixmap->Fill(clrTransparent);
+ cString label = cString::sprintf("%s: %d", tr("Volume"), Current);
+ cString maxLabel = cString::sprintf("%s: %d", tr("Volume"), 555);
+ int maxlabelWidth = font->Width(maxLabel);
+ int left = osdWidth / 2 - maxlabelWidth / 2;
+
+ labelPixmap->DrawText(cPoint(left, 0), *label, Theme.Color(clrVolumeFont), Theme.Color(clrVolumeBg),
+ font, maxlabelWidth, fontHeight, taCenter);
+ if (Mute) {
+ if( imgLoader.LoadIcon("mute", labelHeight, labelHeight) ) {
+ labelPixmap->DrawImage( cPoint(left + maxlabelWidth + marginItem, 0), imgLoader.GetImage() );
+ }
+ }
+ DrawProgressBar(Current, Total);
+}
+
+void cFlatDisplayVolume::DrawProgressBar(int Current, int Total) {
+ int barFullWidth = osdWidth * 3 / 4;
+ int left = osdWidth - barFullWidth;
+ left /= 2;
+ double percentLeft = ((double)Current) / (double)Total;
+
+ progressBarPixmap->Fill(clrTransparent);
+
+ if (Current > 0) {
+ progressBarPixmap->DrawRectangle(cRect( left, 2, barFullWidth, 2), Theme.Color(clrVolumeProgressBg));
+ progressBarPixmap->DrawRectangle(cRect( left, 0, (barFullWidth * percentLeft), 6), Theme.Color(clrVolumeProgressFg));
+ }
+}
+
+void cFlatDisplayVolume::Flush(void) {
+ TopBarUpdate();
+ osd->Flush();
+}
diff --git a/displayvolume.h b/displayvolume.h
new file mode 100644
index 0000000..cba37a8
--- /dev/null
+++ b/displayvolume.h
@@ -0,0 +1,21 @@
+#pragma once
+
+#include "baserender.h"
+
+class cFlatDisplayVolume : public cFlatBaseRender, public cSkinDisplayVolume {
+ private:
+ bool muted;
+
+ cPixmap *progressBarPixmap;
+ int progressBarHeight;
+
+ cPixmap *labelPixmap;
+ int labelHeight;
+
+ void DrawProgressBar(int Current, int Total);
+ public:
+ cFlatDisplayVolume(void);
+ virtual ~cFlatDisplayVolume();
+ virtual void SetVolume(int Current, int Total, bool Mute);
+ virtual void Flush(void);
+};
diff --git a/flat.c b/flat.c
new file mode 100644
index 0000000..bbcf49c
--- /dev/null
+++ b/flat.c
@@ -0,0 +1,50 @@
+#include <vdr/osd.h>
+#include <vdr/menu.h>
+
+#include "flat.h"
+
+#include "displaychannel.h"
+#include "displaymenu.h"
+#include "displaymessage.h"
+#include "displayreplay.h"
+#include "displaytracks.h"
+#include "displayvolume.h"
+
+
+cTheme Theme;
+static bool menuActive = false;
+
+cFlat::cFlat(void) : cSkin("flat", &::Theme) {
+ displayMenu = NULL;
+}
+
+const char *cFlat::Description(void) {
+ return "flat";
+}
+
+cSkinDisplayChannel *cFlat::DisplayChannel(bool WithInfo) {
+ return new cFlatDisplayChannel(WithInfo);
+}
+
+cSkinDisplayMenu *cFlat::DisplayMenu(void) {
+ cFlatDisplayMenu *menu = new cFlatDisplayMenu;
+ displayMenu = menu;
+ menuActive = true;
+ return menu;
+}
+
+cSkinDisplayReplay *cFlat::DisplayReplay(bool ModeOnly) {
+ return new cFlatDisplayReplay(ModeOnly);
+}
+
+cSkinDisplayVolume *cFlat::DisplayVolume(void) {
+ return new cFlatDisplayVolume;
+}
+
+cSkinDisplayTracks *cFlat::DisplayTracks(const char *Title, int NumTracks, const char * const *Tracks) {
+ return new cFlatDisplayTracks(Title, NumTracks, Tracks);
+}
+
+cSkinDisplayMessage *cFlat::DisplayMessage(void) {
+ return new cFlatDisplayMessage;
+}
diff --git a/flat.h b/flat.h
new file mode 100644
index 0000000..fbbe81f
--- /dev/null
+++ b/flat.h
@@ -0,0 +1,101 @@
+#pragma once
+
+#include <vdr/skins.h>
+#include <vdr/videodir.h>
+
+class cFlatDisplayMenu;
+extern cTheme Theme;
+
+// BUTTONS
+#define CLR_BUTTONRED 0x99BB0000
+#define CLR_BUTTONGREEN 0x9900BB00
+#define CLR_BUTTONYELLOW 0x99BBBB00
+#define CLR_BUTTONBLUE 0x990000BB
+
+// MESSAGES
+#define CLR_MESSAGESTATUS 0x900000FF
+#define CLR_MESSAGEINFO 0x90009900
+#define CLR_MESSAGEWARNING 0x90BBBB00
+#define CLR_MESSAGEERROR 0x90BB0000
+
+// TopBar
+THEME_CLR(Theme, clrTopBarBg, 0x90222222);
+THEME_CLR(Theme, clrTopBarFont, 0xFFEEEEEE);
+THEME_CLR(Theme, clrTopBarDateTimeFont, 0xFFEEEEEE);
+
+// Buttons
+THEME_CLR(Theme, clrButtonBg, 0x90222222);
+THEME_CLR(Theme, clrButtonFont, 0xFFEEEEEE);
+THEME_CLR(Theme, clrButtonRed, CLR_BUTTONRED);
+THEME_CLR(Theme, clrButtonGreen, CLR_BUTTONGREEN);
+THEME_CLR(Theme, clrButtonYellow, CLR_BUTTONYELLOW);
+THEME_CLR(Theme, clrButtonBlue, CLR_BUTTONBLUE);
+
+// Messages
+THEME_CLR(Theme, clrMessageBg, 0x90222222);
+THEME_CLR(Theme, clrMessageFont, 0xFFEEEEEE);
+
+THEME_CLR(Theme, clrMessageStatus, CLR_MESSAGESTATUS);
+THEME_CLR(Theme, clrMessageInfo, CLR_MESSAGEINFO);
+THEME_CLR(Theme, clrMessageWarning, CLR_MESSAGEWARNING);
+THEME_CLR(Theme, clrMessageError, CLR_MESSAGEERROR);
+
+// Channel
+THEME_CLR(Theme, clrChannelBg, 0x90222222);
+THEME_CLR(Theme, clrChannelFontTitle, 0xFFEEEEEE);
+THEME_CLR(Theme, clrChannelFontEpg, 0xFFEEEEEE);
+THEME_CLR(Theme, clrChannelProgressFg, 0xFFEEEEEE);
+THEME_CLR(Theme, clrChannelProgressBg, 0xFFEEEEEE);
+
+// Menu
+THEME_CLR(Theme, clrItemBg, 0x90909090);
+THEME_CLR(Theme, clrItemFont, 0xFFEEEEEE);
+THEME_CLR(Theme, clrItemCurrentBg, 0x903090B0);
+THEME_CLR(Theme, clrItemCurrentFont, 0xFFEEEEEE);
+THEME_CLR(Theme, clrItemSelableBg, 0x90222222);
+THEME_CLR(Theme, clrItemSelableFont, 0xFFEEEEEE);
+THEME_CLR(Theme, clrScrollbarFg, 0xFFEEEEEE);
+THEME_CLR(Theme, clrScrollbarBg, 0xFFEEEEEE);
+// Menu Event
+THEME_CLR(Theme, clrMenuEventBg, 0x90222222);
+THEME_CLR(Theme, clrMenuEventFontTitle, 0xFFEEEEEE);
+THEME_CLR(Theme, clrMenuEventFontInfo, 0xFFEEEEEE);
+// Menu Recording
+THEME_CLR(Theme, clrMenuRecBg, 0x90222222);
+THEME_CLR(Theme, clrMenuRecFontTitle, 0xFFEEEEEE);
+THEME_CLR(Theme, clrMenuRecFontInfo, 0xFFEEEEEE);
+// Menu Text (Multiline)
+THEME_CLR(Theme, clrMenuTextBg, 0x90222222);
+THEME_CLR(Theme, clrMenuTextFont, 0xFFEEEEEE);
+
+// Replay
+THEME_CLR(Theme, clrReplayBg, 0x90222222);
+THEME_CLR(Theme, clrReplayFont, 0xFFEEEEEE);
+THEME_CLR(Theme, clrReplayProgressFg, 0xFFEEEEEE);
+THEME_CLR(Theme, clrReplayProgressBg, 0xFFEEEEEE);
+
+// Tracks
+THEME_CLR(Theme, clrTrackItemBg, 0x90909090);
+THEME_CLR(Theme, clrTrackItemFont, 0xFFEEEEEE);
+THEME_CLR(Theme, clrTrackItemCurrentBg, 0x903090B0);
+THEME_CLR(Theme, clrTrackItemCurrentFont, 0xFFEEEEEE);
+
+// Volume
+THEME_CLR(Theme, clrVolumeBg, 0x90222222);
+THEME_CLR(Theme, clrVolumeFont, 0xFFEEEEEE);
+THEME_CLR(Theme, clrVolumeProgressFg, 0xFFEEEEEE);
+THEME_CLR(Theme, clrVolumeProgressBg, 0xFFEEEEEE);
+
+class cFlat : public cSkin {
+ private:
+ cFlatDisplayMenu *displayMenu;
+ public:
+ cFlat(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);
+};
diff --git a/generate_theme.sh b/generate_theme.sh
new file mode 100755
index 0000000..aea6338
--- /dev/null
+++ b/generate_theme.sh
@@ -0,0 +1,141 @@
+#!/bin/bash
+
+echo "*********************************"
+echo "* theme generator version 0.1 *"
+echo "* for skinflat version <= 0.0.1 *"
+echo "*********************************"
+
+echo ""
+echo "all colors must be of the form AARRGGBB"
+echo ""
+
+echo "simple mode: "
+echo " you only need 4 colors"
+echo " + Backround "
+echo " + Foreground (Font, Scrollbar, Progressbar) "
+echo " + Current (current menu item background) "
+echo " + Selable (selable menu item background) "
+echo ""
+echo "normale mode: "
+echo " you need 10 colors"
+
+while [ 1 ]
+do
+ echo ""
+ echo -n "which mode you want s (simple) / n (normal): "
+ read Mode
+
+ if [ "$Mode" != "s" ] && [ "$Mode" != "n" ]
+ then
+ echo "wrong answer, just type \"s\" or \"n\"!"
+ else
+ break
+ fi
+done
+
+if [ "$Mode" == "s" ]
+then
+ echo -n "Name: "
+ read ThemeName
+ echo -n "Background color: "
+ read Background
+ echo -n "Foreground color: "
+ read Foreground
+ echo -n "Menu item current background color: "
+ read ItemCurBG
+ echo -n "Menu item selectable background color: "
+ read ItemSelableBG
+
+ Font=$Foreground
+ TitleFont=$Foreground
+ ProgressBG=$Foreground
+ ProgressFG=$Foreground
+ ScrollbarBG=$Foreground
+ ScrollbarFG=$Foreground
+ ItemBG=$Background
+
+else
+ echo -n "Name: "
+ read ThemeName
+ echo -n "Background color: "
+ read Background
+ echo -n "Font color: "
+ read Font
+ echo -n "Title font color: "
+ read TitleFont
+ echo -n "Menu item (not selectable) background color: "
+ read ItemBG
+ echo -n "Menu item current/selected background color: "
+ read ItemCurBG
+ echo -n "Menu item selectable background color: "
+ read ItemSelableBG
+ echo -n "Progressbar background color: "
+ read ProgressBG
+ echo -n "Progressbar foreground color: "
+ read ProgressFG
+ echo -n "Scrollbar background color: "
+ read ScrollbarBG
+ echo -n "Scrollbar foreground color: "
+ read ScrollbarFG
+fi
+
+FILE=flat-${ThemeName}.theme
+
+echo "Description = $ThemeName" > $FILE
+echo "clrTopBarBg = $Background" >> $FILE
+echo "clrTopBarFont = $Font" >> $FILE
+echo "clrTopBarDateTimeFont = $Font" >> $FILE
+echo "clrButtonBg = $Background" >> $FILE
+echo "clrButtonFont = $Font" >> $FILE
+echo "clrButtonRed = 99BB0000" >> $FILE
+echo "clrButtonGreen = 9900BB00" >> $FILE
+echo "clrButtonYellow = 99BBBB00" >> $FILE
+echo "clrButtonBlue = 990000BB" >> $FILE
+echo "clrMessageBg = $Background" >> $FILE
+echo "clrMessageFont = $Font" >> $FILE
+echo "clrMessageStatus = 900000FF" >> $FILE
+echo "clrMessageInfo = 90009900" >> $FILE
+echo "clrMessageWarning = 90BBBB00" >> $FILE
+echo "clrMessageError = 90BB0000" >> $FILE
+echo "clrChannelBg = $Background" >> $FILE
+echo "clrChannelFontTitle = $TitleFont" >> $FILE
+echo "clrChannelFontEpg = $Font" >> $FILE
+echo "clrChannelProgressFg = $ProgressFG" >> $FILE
+echo "clrChannelProgressBg = $ProgressBG" >> $FILE
+echo "clrItemBg = $ItemBG" >> $FILE
+echo "clrItemFont = $Font" >> $FILE
+echo "clrItemCurrentBg = $ItemCurBG" >> $FILE
+echo "clrItemCurrentFont = $Font" >> $FILE
+echo "clrItemSelableBg = $ItemSelableBG" >> $FILE
+echo "clrItemSelableFont = $Font" >> $FILE
+echo "clrScrollbarFg = $ScrollbarFG" >> $FILE
+echo "clrScrollbarBg = $ScrollbarBG" >> $FILE
+echo "clrMenuEventBg = $Background" >> $FILE
+echo "clrMenuEventFontTitle = $TitleFont" >> $FILE
+echo "clrMenuEventFontInfo = $Font" >> $FILE
+echo "clrMenuRecBg = $Background" >> $FILE
+echo "clrMenuRecFontTitle = $TitleFont" >> $FILE
+echo "clrMenuRecFontInfo = $Font" >> $FILE
+echo "clrMenuTextBg = $Background" >> $FILE
+echo "clrMenuTextFont = $Font" >> $FILE
+echo "clrReplayBg = $Background" >> $FILE
+echo "clrReplayFont = $Font" >> $FILE
+echo "clrReplayProgressFg = $ProgressFG" >> $FILE
+echo "clrReplayProgressBg = $ProgressBG" >> $FILE
+echo "clrTrackItemBg = $ItemBG" >> $FILE
+echo "clrTrackItemFont = $Font" >> $FILE
+echo "clrTrackItemCurrentBg = $ItemCurBG" >> $FILE
+echo "clrTrackItemCurrentFont = $Font" >> $FILE
+echo "clrVolumeBg = $Background" >> $FILE
+echo "clrVolumeFont = $Font" >> $FILE
+echo "clrVolumeProgressFg = $ProgressFG" >> $FILE
+echo "clrVolumeProgressBg = $ProgressBG" >> $FILE
+
+echo ""
+echo "Theme <${FILE}> saved"
+echo "Feel free to adjust single colors in the file"
+echo "you must manually move it to your vdr config to test it"
+echo "for example: mv ${FILE} /etc/vdr/themes/"
+echo ""
+echo "Remember, You must provide icons for your theme"
+echo "look at <vdrconfig>/plugins/skinflat/icons/default/"
diff --git a/icons/COPYRIGHT b/icons/COPYRIGHT
new file mode 100644
index 0000000..67c1833
--- /dev/null
+++ b/icons/COPYRIGHT
@@ -0,0 +1,11 @@
+Symbols from
+Alexander Moore
+paket Snowish
+under GNU/GPL
+http://findicons.com/pack/2152/snowish
+
+mute & unmute from
+brsev
+paket vrsev
+Creative Commons Attribution
+http://findicons.com/pack/949/token \ No newline at end of file
diff --git a/icons/default/forward.png b/icons/default/forward.png
new file mode 100644
index 0000000..b7464a8
--- /dev/null
+++ b/icons/default/forward.png
Binary files differ
diff --git a/icons/default/forward_sel.png b/icons/default/forward_sel.png
new file mode 100644
index 0000000..a7eb25a
--- /dev/null
+++ b/icons/default/forward_sel.png
Binary files differ
diff --git a/icons/default/mute.png b/icons/default/mute.png
new file mode 100644
index 0000000..91fc4f8
--- /dev/null
+++ b/icons/default/mute.png
Binary files differ
diff --git a/icons/default/pause.png b/icons/default/pause.png
new file mode 100644
index 0000000..1755f16
--- /dev/null
+++ b/icons/default/pause.png
Binary files differ
diff --git a/icons/default/pause_sel.png b/icons/default/pause_sel.png
new file mode 100644
index 0000000..be8b4b4
--- /dev/null
+++ b/icons/default/pause_sel.png
Binary files differ
diff --git a/icons/default/play.png b/icons/default/play.png
new file mode 100644
index 0000000..84e8a6e
--- /dev/null
+++ b/icons/default/play.png
Binary files differ
diff --git a/icons/default/play_sel.png b/icons/default/play_sel.png
new file mode 100644
index 0000000..a4769c3
--- /dev/null
+++ b/icons/default/play_sel.png
Binary files differ
diff --git a/icons/default/prev.png b/icons/default/prev.png
new file mode 100644
index 0000000..4a7f813
--- /dev/null
+++ b/icons/default/prev.png
Binary files differ
diff --git a/icons/default/prev_sel.png b/icons/default/prev_sel.png
new file mode 100644
index 0000000..fed33f3
--- /dev/null
+++ b/icons/default/prev_sel.png
Binary files differ
diff --git a/icons/default/rewind.png b/icons/default/rewind.png
new file mode 100644
index 0000000..393e1bc
--- /dev/null
+++ b/icons/default/rewind.png
Binary files differ
diff --git a/icons/default/rewind_sel.png b/icons/default/rewind_sel.png
new file mode 100644
index 0000000..64ff951
--- /dev/null
+++ b/icons/default/rewind_sel.png
Binary files differ
diff --git a/icons/default/skip.png b/icons/default/skip.png
new file mode 100644
index 0000000..1ef72ba
--- /dev/null
+++ b/icons/default/skip.png
Binary files differ
diff --git a/icons/default/skip_sel.png b/icons/default/skip_sel.png
new file mode 100644
index 0000000..6058681
--- /dev/null
+++ b/icons/default/skip_sel.png
Binary files differ
diff --git a/icons/white/forward.png b/icons/white/forward.png
new file mode 100644
index 0000000..e02bb2a
--- /dev/null
+++ b/icons/white/forward.png
Binary files differ
diff --git a/icons/white/forward_sel.png b/icons/white/forward_sel.png
new file mode 100644
index 0000000..a7eb25a
--- /dev/null
+++ b/icons/white/forward_sel.png
Binary files differ
diff --git a/icons/white/mute.png b/icons/white/mute.png
new file mode 100644
index 0000000..ff14bd7
--- /dev/null
+++ b/icons/white/mute.png
Binary files differ
diff --git a/icons/white/pause.png b/icons/white/pause.png
new file mode 100644
index 0000000..7ba4c5a
--- /dev/null
+++ b/icons/white/pause.png
Binary files differ
diff --git a/icons/white/pause_sel.png b/icons/white/pause_sel.png
new file mode 100644
index 0000000..be8b4b4
--- /dev/null
+++ b/icons/white/pause_sel.png
Binary files differ
diff --git a/icons/white/play.png b/icons/white/play.png
new file mode 100644
index 0000000..4464192
--- /dev/null
+++ b/icons/white/play.png
Binary files differ
diff --git a/icons/white/play_sel.png b/icons/white/play_sel.png
new file mode 100644
index 0000000..a4769c3
--- /dev/null
+++ b/icons/white/play_sel.png
Binary files differ
diff --git a/icons/white/prev.png b/icons/white/prev.png
new file mode 100644
index 0000000..ae23a36
--- /dev/null
+++ b/icons/white/prev.png
Binary files differ
diff --git a/icons/white/prev_sel.png b/icons/white/prev_sel.png
new file mode 100644
index 0000000..fed33f3
--- /dev/null
+++ b/icons/white/prev_sel.png
Binary files differ
diff --git a/icons/white/rewind.png b/icons/white/rewind.png
new file mode 100644
index 0000000..8b455ee
--- /dev/null
+++ b/icons/white/rewind.png
Binary files differ
diff --git a/icons/white/rewind_sel.png b/icons/white/rewind_sel.png
new file mode 100644
index 0000000..64ff951
--- /dev/null
+++ b/icons/white/rewind_sel.png
Binary files differ
diff --git a/icons/white/skip.png b/icons/white/skip.png
new file mode 100644
index 0000000..98390e2
--- /dev/null
+++ b/icons/white/skip.png
Binary files differ
diff --git a/icons/white/skip_sel.png b/icons/white/skip_sel.png
new file mode 100644
index 0000000..6058681
--- /dev/null
+++ b/icons/white/skip_sel.png
Binary files differ
diff --git a/imageloader.c b/imageloader.c
new file mode 100644
index 0000000..e1b625b
--- /dev/null
+++ b/imageloader.c
@@ -0,0 +1,281 @@
+#include "imageloader.h"
+#include <math.h>
+#include <string>
+#include <dirent.h>
+#include <iostream>
+
+using namespace Magick;
+
+cImageLoader::cImageLoader() {
+ InitializeMagick(NULL);
+ logoPathDefault = cString::sprintf("%s/logos/", PLUGINPATH);
+ iconPathDefault = cString::sprintf("%s/icons/", PLUGINPATH);
+ epgImagePathDefault = cString::sprintf("%s/epgImages/", PLUGINPATH);
+
+ logoExtension = "png";
+}
+
+cImageLoader::~cImageLoader() {
+}
+
+bool cImageLoader::LoadLogo(const char *logo, int width=-1, int height=-1) {
+ if( width == -1 )
+ width = logoWidth;
+ if( height == -1 )
+ height = logoHeight;
+
+ if( (width == 0) || (height==0) )
+ return false;
+ std::string logoLower = logo;
+ toLowerCase(logoLower);
+ bool success = false;
+ if( logoPathSet ) {
+ success = LoadImage(logoLower.c_str(), logoPath, logoExtension);
+ }
+ if( !success ) {
+ success = LoadImage(logoLower.c_str(), logoPathDefault, logoExtension);
+ }
+ if( !success )
+ return false;
+
+ if( height != 0 || width != 0 ) {
+ buffer.sample( Geometry(width, height) );
+ }
+ return true;
+}
+
+int cImageLoader::Height(void) {
+ Geometry geo = buffer.size();
+ return geo.height();
+}
+
+int cImageLoader::Width(void) {
+ Geometry geo = buffer.size();
+ return geo.width();
+}
+
+bool cImageLoader::LoadIcon(const char *cIcon, int size) {
+ if (size==0)
+ return false;
+ bool success = false;
+ if (iconPathSet) {
+ cString iconThemePath = cString::sprintf("%s%s/", *iconPath, Setup.OSDTheme);
+ success = LoadImage(cString(cIcon), iconThemePath, "png");
+ if (!success) {
+ success = LoadImage(cString(cIcon), iconPath, "png");
+ }
+ }
+ if (!success) {
+ cString iconThemePath = cString::sprintf("%s%s/", *iconPathDefault, Setup.OSDTheme);
+ printf("%s\n", *iconThemePath);
+ success = LoadImage(cString(cIcon), iconThemePath, "png");
+ if (!success) {
+ success = LoadImage(cString(cIcon), iconPathDefault, "png");
+ }
+ }
+ if (!success)
+ return false;
+ buffer.sample(Geometry(size, size));
+ return true;
+}
+
+bool cImageLoader::LoadIcon(const char *cIcon, int width, int height, bool preserveAspect) {
+ try {
+ if ((width == 0)||(height==0))
+ return false;
+ bool success = false;
+ if (iconPathSet) {
+ cString iconThemePath = cString::sprintf("%s%s/", *iconPath, Setup.OSDTheme);
+ success = LoadImage(cString(cIcon), iconThemePath, "png");
+ if (!success) {
+ success = LoadImage(cString(cIcon), iconPath, "png");
+ }
+ }
+ if (!success) {
+ cString iconThemePath = cString::sprintf("%s%s/", *iconPathDefault, Setup.OSDTheme);
+ success = LoadImage(cString(cIcon), iconThemePath, "png");
+ if (!success) {
+ success = LoadImage(cString(cIcon), iconPathDefault, "png");
+ }
+ }
+ if (!success)
+ return false;
+ if (preserveAspect) {
+ buffer.sample(Geometry(width, height));
+ } else {
+ cString geometry = cString::sprintf("%dx%d!", width, height);
+ buffer.scale(Geometry(*geometry));
+ }
+ return true;
+ }
+ catch (...) {
+ return false;
+ }
+}
+
+bool cImageLoader::LoadEPGImage(int eventID) {
+ int width = epgImageWidth;
+ int height = epgImageHeight;
+ if ((width == 0)||(height==0))
+ return false;
+ bool success = false;
+ if (epgImagePathSet) {
+ success = LoadImage(cString::sprintf("%d", eventID), epgImagePath, "jpg");
+ }
+ if (!success) {
+ success = LoadImage(cString::sprintf("%d", eventID), epgImagePathDefault, "jpg");
+ }
+ if (!success)
+ return false;
+ if (height != 0 || width != 0) {
+ buffer.sample( Geometry(width, height));
+ }
+ return true;
+}
+
+bool cImageLoader::LoadAdditionalEPGImage(cString name) {
+ int width = epgImageWidthLarge;
+ int height = epgImageHeightLarge;
+ if ((width == 0)||(height==0))
+ return false;
+ bool success = false;
+ if (epgImagePathSet) {
+ success = LoadImage(name, epgImagePath, "jpg");
+ }
+ if (!success) {
+ success = LoadImage(name, epgImagePathDefault, "jpg");
+ }
+ if (!success)
+ return false;
+ if (height != 0 || width != 0) {
+ buffer.sample( Geometry(width, height));
+ }
+ return true;
+}
+
+bool cImageLoader::LoadRecordingImage(cString Path) {
+ int width = epgImageWidth;
+ int height = epgImageHeight;
+ if ((width == 0)||(height==0))
+ return false;
+ cString recImage("");
+ if (FirstImageInFolder(Path, "jpg", &recImage)) {
+ recImage = cString::sprintf("/%s", *recImage);
+ if (!LoadImage(*recImage, Path, "jpg"))
+ return false;
+ buffer.sample( Geometry(width, height));
+ return true;
+ }
+ return false;
+}
+
+bool cImageLoader::LoadAdditionalRecordingImage(cString path, cString name) {
+ int width = epgImageWidthLarge;
+ int height = epgImageHeightLarge;
+ if ((width == 0)||(height==0))
+ return false;
+ if (LoadImage(name, path, "jpg")) {
+ buffer.sample( Geometry(width, height));
+ return true;
+ }
+ return false;
+}
+
+void cImageLoader::DrawBackground(tColor back, tColor blend, int width, int height, bool mirror) {
+ Color Back = Argb2Color(back);
+ Color Blend = Argb2Color(blend);
+ Image tmp(Geometry(width, height), Blend);
+ double arguments[9] = {0.0,(double)height,0.0,-1*(double)width,0.0,0.0,1.5*(double)width,0.0,1.0};
+ tmp.sparseColor(MatteChannel, BarycentricColorInterpolate, 9, arguments);
+ Image tmp2(Geometry(width, height), Back);
+ tmp.composite(tmp2, 0, 0, OverlayCompositeOp);
+ if (mirror)
+ tmp.flop();
+ buffer = tmp;
+}
+
+void cImageLoader::DrawBackground2(tColor back, tColor blend, int width, int height) {
+ Color Back = Argb2Color(back);
+ Color Blend = Argb2Color(blend);
+ Image tmp(Geometry(width, height), Blend);
+ double arguments[9] = {0.0,(double)height,0.0,-0.5*(double)width,0.0,0.0,0.75*(double)width,0.0,1.0};
+ tmp.sparseColor(MatteChannel, BarycentricColorInterpolate, 9, arguments);
+ Image tmp2(Geometry(width, height), Back);
+ tmp.composite(tmp2, 0, 0, OverlayCompositeOp);
+ buffer = tmp;
+}
+
+void cImageLoader::Colorize(tColor col)
+{
+ // opacity
+ // 0 = opaque
+ // QuantumRange = trans
+ buffer.colorize(QuantumRange / 2, Argb2Color(col) );
+}
+
+cImage cImageLoader::GetImage() {
+ 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;
+}
+
+Color cImageLoader::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 cImageLoader::toLowerCase(std::string &str) {
+ const int length = str.length();
+ for(int i=0; i < length; ++i) {
+ str[i] = std::tolower(str[i]);
+ }
+}
+
+bool cImageLoader::LoadImage(cString FileName, cString Path, cString Extension) {
+ try {
+ cString File = cString::sprintf("%s%s.%s", *Path, *FileName, *Extension);
+ dsyslog("imageloader: trying to load: %s", *File);
+ //printf("imageloader: trying to load: %s\n", *File);
+ buffer.read(*File);
+ dsyslog("imageloader: %s sucessfully loaded", *File);
+ //printf("imageloader: %s sucessfully loaded\n", *File);
+ } catch (...) {
+ return false;
+ }
+ return true;
+}
+
+bool cImageLoader::FirstImageInFolder(cString Path, cString Extension, cString *recImage) {
+ DIR *folder;
+ struct dirent *file;
+ folder = opendir(Path);
+ while ( (file = readdir(folder)) ) {
+ if (endswith(file->d_name, *Extension)) {
+ std::string fileName = file->d_name;
+ if (fileName.length() > 4)
+ fileName = fileName.substr(0, fileName.length() - 4);
+ else
+ return false;
+ *recImage = fileName.c_str();
+ return true;
+ }
+ }
+ return false;
+}
diff --git a/imageloader.h b/imageloader.h
new file mode 100644
index 0000000..83d4b27
--- /dev/null
+++ b/imageloader.h
@@ -0,0 +1,46 @@
+#pragma once
+
+#define X_DISPLAY_MISSING
+
+#include <vdr/osd.h>
+#include <vdr/skins.h>
+#include <vdr/plugin.h>
+
+#include <Magick++.h>
+
+#define PLUGINPATH (cPlugin::ConfigDirectory(PLUGIN_NAME_I18N))
+
+using namespace Magick;
+
+class cImageLoader {
+public:
+ cImageLoader();
+ ~cImageLoader();
+ cImage GetImage();
+ bool LoadLogo(const char *logo, int width, int height);
+ bool LoadIcon(const char *cIcon, int size);
+ bool LoadIcon(const char *cIcon, int width, int height, bool preserveAspect = true);
+ bool LoadEPGImage(int eventID);
+ bool LoadAdditionalEPGImage(cString name);
+ bool LoadRecordingImage(cString Path);
+ bool LoadAdditionalRecordingImage(cString path, cString name);
+ void DrawBackground(tColor back, tColor blend, int width, int height, bool mirror = false);
+ void DrawBackground2(tColor back, tColor blend, int width, int height);
+ void Colorize(tColor col);
+ int Height(void);
+ int Width(void);
+
+private:
+ int epgImageWidthLarge, epgImageHeightLarge;
+ int epgImageWidth, epgImageHeight;
+ int logoWidth, logoHeight;
+ cString logoExtension;
+ cString logoPath, logoPathDefault, iconPath, iconPathDefault, epgImagePath, epgImagePathDefault;
+ bool logoPathSet, iconPathSet, epgImagePathSet;
+
+ Image buffer;
+ Color Argb2Color(tColor col);
+ void toLowerCase(std::string &str);
+ bool LoadImage(cString FileName, cString Path, cString Extension);
+ bool FirstImageInFolder(cString Path, cString Extension, cString *recImage);
+};
diff --git a/po/de_DE.po b/po/de_DE.po
new file mode 100644
index 0000000..f4c6f2d
--- /dev/null
+++ b/po/de_DE.po
@@ -0,0 +1,19 @@
+# VDR plugin language source file.
+# Copyright (C) 2008 Martin Schirrmacher <vdr.skinflat@schirrmacher.eu>
+# This file is distributed under the same license as the skinflat package.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: vdr-skinflat 0.0.1\n"
+"Report-Msgid-Bugs-To: <see README>\n"
+"POT-Creation-Date: 2013-07-29 07:40+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-15\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+msgid "Volume"
+msgstr "Lautstärke"
diff --git a/skinflat.c b/skinflat.c
new file mode 100644
index 0000000..a336815
--- /dev/null
+++ b/skinflat.c
@@ -0,0 +1,117 @@
+/*
+ * skinflat.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>
+
+#if defined(APIVERSNUM) && APIVERSNUM < 10734
+#error "VDR-1.7.34 API version or greater is required!"
+#endif
+
+#include "flat.h"
+
+static const char *VERSION = "0.0.1";
+static const char *DESCRIPTION = "skin flat";
+
+class cPluginFlat : public cPlugin {
+ private:
+ cFlat *flat;
+ public:
+ cPluginFlat(void);
+ virtual ~cPluginFlat();
+ 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);
+};
+
+cPluginFlat::cPluginFlat(void) {
+ flat = NULL;
+}
+
+cPluginFlat::~cPluginFlat() {
+}
+
+const char *cPluginFlat::CommandLineHelp(void) {
+ return "";
+}
+
+bool cPluginFlat::ProcessArgs(int argc, char *argv[]) {
+ // Implement command line argument processing here if applicable.
+ return true;
+}
+
+bool cPluginFlat::Initialize(void) {
+ return true;
+}
+
+bool cPluginFlat::Start(void) {
+ if (!cOsdProvider::SupportsTrueColor()) {
+ esyslog("skinflat: No TrueColor OSD found! Aborting!");
+ return false;
+ } else
+ dsyslog("skinflat: TrueColor OSD found");
+ flat = new cFlat;
+ return flat;
+}
+
+void cPluginFlat::Stop(void) {
+}
+
+void cPluginFlat::Housekeeping(void) {
+}
+
+void cPluginFlat::MainThreadHook(void) {
+}
+
+cString cPluginFlat::Active(void) {
+ return NULL;
+}
+
+time_t cPluginFlat::WakeupTime(void) {
+ return 0;
+}
+
+cOsdObject *cPluginFlat::MainMenuAction(void) {
+ return NULL;
+}
+
+cMenuSetupPage *cPluginFlat::SetupMenu(void) {
+ return NULL;
+}
+
+bool cPluginFlat::SetupParse(const char *Name, const char *Value) {
+ return true;
+}
+
+bool cPluginFlat::Service(const char *Id, void *Data) {
+ return false;
+}
+
+const char **cPluginFlat::SVDRPHelpPages(void) {
+ return NULL;
+}
+
+cString cPluginFlat::SVDRPCommand(const char *Command, const char *Option, int &ReplyCode) {
+ return NULL;
+}
+
+VDRPLUGINCREATOR(cPluginFlat); // Don't touch this!
diff --git a/symbols/arrowdown.xpm b/symbols/arrowdown.xpm
new file mode 100644
index 0000000..8ef6b0a
--- /dev/null
+++ b/symbols/arrowdown.xpm
@@ -0,0 +1,17 @@
+/* XPM */
+static const char *const arrowdown_xpm[] = {
+"12 12 2 1",
+". c #FFFFFF",
+"+ c #000000",
+"++++++++++++",
+"++++++++++++",
+".++++++++++.",
+".++++++++++.",
+"..++++++++..",
+"..++++++++..",
+"...++++++...",
+"...++++++...",
+"....++++....",
+"....++++....",
+".....++.....",
+".....++....."};
diff --git a/symbols/arrowup.xpm b/symbols/arrowup.xpm
new file mode 100644
index 0000000..9ee2e6c
--- /dev/null
+++ b/symbols/arrowup.xpm
@@ -0,0 +1,17 @@
+/* XPM */
+static const char *const arrowup_xpm[] = {
+"12 12 2 1",
+". c #FFFFFF",
+"+ c #000000",
+".....++.....",
+".....++.....",
+"....++++....",
+"....++++....",
+"...++++++...",
+"...++++++...",
+"..++++++++..",
+"..++++++++..",
+".++++++++++.",
+".++++++++++.",
+"++++++++++++",
+"++++++++++++"};
diff --git a/symbols/audio.xpm b/symbols/audio.xpm
new file mode 100644
index 0000000..44021ad
--- /dev/null
+++ b/symbols/audio.xpm
@@ -0,0 +1,23 @@
+/* XPM */
+static const char *const audio_xpm[] = {
+"27 18 2 1",
+". c #FFFFFF",
+"+ c #000000",
+"...........................",
+"...........................",
+"..+++++++++++++++++++++++..",
+"..+++++++++++++++++++++++..",
+"..++...................++..",
+"..++...................++..",
+"..++...++++.....++++...++..",
+"..++..++..++...++..++..++..",
+"..++.++....++.++....++.++..",
+"..++..++..++...++..++..++..",
+"..++...++++.....++++...++..",
+"..++...................++..",
+"..++...................++..",
+"..++...................++..",
+"..+++++++++++++++++++++++..",
+"..+++++++++++++++++++++++..",
+"...........................",
+"..........................."};
diff --git a/symbols/audioleft.xpm b/symbols/audioleft.xpm
new file mode 100644
index 0000000..8f68360
--- /dev/null
+++ b/symbols/audioleft.xpm
@@ -0,0 +1,23 @@
+/* XPM */
+static const char *const audioleft_xpm[] = {
+"27 18 2 1",
+". c #FFFFFF",
+"+ c #000000",
+"...........................",
+"...........................",
+"...........................",
+"...........................",
+".....++++.........++++.....",
+"...++++++++.....++++++++...",
+"...++++++++.....++....++...",
+"..++++++++++...++......++..",
+"..++++++++++...++......++..",
+"..++++++++++...++......++..",
+"..++++++++++...++......++..",
+"...++++++++.....++....++...",
+"...++++++++.....++++++++...",
+".....++++.........++++.....",
+"...........................",
+"...........................",
+"...........................",
+"..........................."};
diff --git a/symbols/audioright.xpm b/symbols/audioright.xpm
new file mode 100644
index 0000000..b349792
--- /dev/null
+++ b/symbols/audioright.xpm
@@ -0,0 +1,23 @@
+/* XPM */
+static const char *const audioright_xpm[] = {
+"27 18 2 1",
+". c #FFFFFF",
+"+ c #000000",
+"...........................",
+"...........................",
+"...........................",
+"...........................",
+".....++++.........++++.....",
+"...++++++++.....++++++++...",
+"...++....++.....++++++++...",
+"..++......++...++++++++++..",
+"..++......++...++++++++++..",
+"..++......++...++++++++++..",
+"..++......++...++++++++++..",
+"...++....++.....++++++++...",
+"...++++++++.....++++++++...",
+".....++++.........++++.....",
+"...........................",
+"...........................",
+"...........................",
+"..........................."};
diff --git a/symbols/audiostereo.xpm b/symbols/audiostereo.xpm
new file mode 100644
index 0000000..4c59a5e
--- /dev/null
+++ b/symbols/audiostereo.xpm
@@ -0,0 +1,23 @@
+/* XPM */
+static const char *const audiostereo_xpm[] = {
+"27 18 2 1",
+". c #FFFFFF",
+"+ c #000000",
+"...........................",
+"...........................",
+"...........................",
+"...........................",
+".....++++.........++++.....",
+"...++++++++.....++++++++...",
+"...++++++++.....++++++++...",
+"..++++++++++...++++++++++..",
+"..++++++++++...++++++++++..",
+"..++++++++++...++++++++++..",
+"..++++++++++...++++++++++..",
+"...++++++++.....++++++++...",
+"...++++++++.....++++++++...",
+".....++++.........++++.....",
+"...........................",
+"...........................",
+"...........................",
+"..........................."};
diff --git a/symbols/dolbydigital.xpm b/symbols/dolbydigital.xpm
new file mode 100644
index 0000000..432b476
--- /dev/null
+++ b/symbols/dolbydigital.xpm
@@ -0,0 +1,23 @@
+/* XPM */
+static const char *const dolbydigital_xpm[] = {
+"27 18 2 1",
+". c #FFFFFF",
+"+ c #000000",
+"...........................",
+"...........................",
+"..+++++++++++.+++++++++++..",
+"..++.++++++++.++++++++.++..",
+"..++...++++++.++++++...++..",
+"..++.....++++.++++.....++..",
+"..++......+++.+++......++..",
+"..++.......++.++.......++..",
+"..++.......++.++.......++..",
+"..++.......++.++.......++..",
+"..++.......++.++.......++..",
+"..++......+++.+++......++..",
+"..++.....++++.++++.....++..",
+"..++...++++++.++++++...++..",
+"..++.++++++++.++++++++.++..",
+"..+++++++++++.+++++++++++..",
+"...........................",
+"..........................."};
diff --git a/symbols/encrypted.xpm b/symbols/encrypted.xpm
new file mode 100644
index 0000000..fc3178b
--- /dev/null
+++ b/symbols/encrypted.xpm
@@ -0,0 +1,23 @@
+/* XPM */
+static const char *const encrypted_xpm[] = {
+"27 18 2 1",
+". c #FFFFFF",
+"+ c #000000",
+"...........................",
+"...........................",
+"..+++++++++++++++++++++++..",
+"..+++++++++++++++++++++++..",
+"..++...................++..",
+"..++...................++..",
+"..++............++++...++..",
+"..++...........++..++..++..",
+"..++.+++++++++++....++.++..",
+"..++.+++++++++++....++.++..",
+"..++..+++......++..++..++..",
+"..++..+++.......++++...++..",
+"..++...................++..",
+"..++...................++..",
+"..+++++++++++++++++++++++..",
+"..+++++++++++++++++++++++..",
+"...........................",
+"..........................."};
diff --git a/symbols/ffwd.xpm b/symbols/ffwd.xpm
new file mode 100644
index 0000000..fb39329
--- /dev/null
+++ b/symbols/ffwd.xpm
@@ -0,0 +1,31 @@
+/* XPM */
+static const char *const ffwd_xpm[] = {
+"28 26 2 1",
+". c #FFFFFF",
+"+ c #000000",
+"............................",
+"............................",
+"..++......++................",
+"..+++.....+++...............",
+"..+++++...+++++.............",
+"..++++++....++++............",
+"..++++++++...+++++..........",
+"..+++++++++....++++.........",
+"..+++++++++++...+++++.......",
+"..++++++++++++....++++......",
+"..++++++++++++++...+++++....",
+"..+++++++++++++++....++++...",
+"..++++++++++++++++....++++..",
+"..++++++++++++++++....++++..",
+"..+++++++++++++++....++++...",
+"..++++++++++++++...+++++....",
+"..++++++++++++....++++......",
+"..+++++++++++...+++++.......",
+"..+++++++++....++++.........",
+"..++++++++...+++++..........",
+"..++++++....++++............",
+"..+++++...+++++.............",
+"..+++.....+++...............",
+"..++......++................",
+"............................",
+"............................"};
diff --git a/symbols/ffwd1.xpm b/symbols/ffwd1.xpm
new file mode 100644
index 0000000..4b81436
--- /dev/null
+++ b/symbols/ffwd1.xpm
@@ -0,0 +1,31 @@
+/* XPM */
+static const char *const ffwd1_xpm[] = {
+"28 26 2 1",
+". c #FFFFFF",
+"+ c #000000",
+"............................",
+"............................",
+"..++......++................",
+"..+++.....+++...............",
+"..+++++...+++++.............",
+"..++++++....++++............",
+"..++++++++...+++++..........",
+"..+++++++++....++++.........",
+"..+++++++++++...+++++.......",
+"..++++++++++++....++++......",
+"..++++++++++++++...+++++....",
+"..++++++++++++++.....++++...",
+"..++++++++++++++...+++++....",
+"..++++++++++++....++++......",
+"..+++++++++++...+++++.......",
+"..+++++++++....++++.........",
+"..++++++++...+++++..........",
+"..++++++....++++............",
+"..+++++...+++++.............",
+"..+++.....+++...............",
+"..++......++................",
+"............................",
+"..++++++....................",
+"..++++++....................",
+"............................",
+"............................"};
diff --git a/symbols/ffwd2.xpm b/symbols/ffwd2.xpm
new file mode 100644
index 0000000..19e62d1
--- /dev/null
+++ b/symbols/ffwd2.xpm
@@ -0,0 +1,31 @@
+/* XPM */
+static const char *const ffwd2_xpm[] = {
+"28 26 2 1",
+". c #FFFFFF",
+"+ c #000000",
+"............................",
+"............................",
+"..++......++................",
+"..+++.....+++...............",
+"..+++++...+++++.............",
+"..++++++....++++............",
+"..++++++++...+++++..........",
+"..+++++++++....++++.........",
+"..+++++++++++...+++++.......",
+"..++++++++++++....++++......",
+"..++++++++++++++...+++++....",
+"..++++++++++++++.....++++...",
+"..++++++++++++++...+++++....",
+"..++++++++++++....++++......",
+"..+++++++++++...+++++.......",
+"..+++++++++....++++.........",
+"..++++++++...+++++..........",
+"..++++++....++++............",
+"..+++++...+++++.............",
+"..+++.....+++...............",
+"..++......++................",
+"............................",
+"..++++++...++++++...........",
+"..++++++...++++++...........",
+"............................",
+"............................"};
diff --git a/symbols/ffwd3.xpm b/symbols/ffwd3.xpm
new file mode 100644
index 0000000..2bc65bd
--- /dev/null
+++ b/symbols/ffwd3.xpm
@@ -0,0 +1,31 @@
+/* XPM */
+static const char *const ffwd3_xpm[] = {
+"28 26 2 1",
+". c #FFFFFF",
+"+ c #000000",
+"............................",
+"............................",
+"..++......++................",
+"..+++.....+++...............",
+"..+++++...+++++.............",
+"..++++++....++++............",
+"..++++++++...+++++..........",
+"..+++++++++....++++.........",
+"..+++++++++++...+++++.......",
+"..++++++++++++....++++......",
+"..++++++++++++++...+++++....",
+"..++++++++++++++.....++++...",
+"..++++++++++++++...+++++....",
+"..++++++++++++....++++......",
+"..+++++++++++...+++++.......",
+"..+++++++++....++++.........",
+"..++++++++...+++++..........",
+"..++++++....++++............",
+"..+++++...+++++.............",
+"..+++.....+++...............",
+"..++......++................",
+"............................",
+"..++++++...++++++...++++++..",
+"..++++++...++++++...++++++..",
+"............................",
+"............................"};
diff --git a/symbols/frew.xpm b/symbols/frew.xpm
new file mode 100644
index 0000000..3583735
--- /dev/null
+++ b/symbols/frew.xpm
@@ -0,0 +1,31 @@
+/* XPM */
+static const char *const frew_xpm[] = {
+"28 26 2 1",
+". c #FFFFFF",
+"+ c #000000",
+"............................",
+"............................",
+"................++......++..",
+"...............+++.....+++..",
+".............+++++...+++++..",
+"............++++....++++++..",
+"..........+++++...++++++++..",
+".........++++....+++++++++..",
+".......+++++...+++++++++++..",
+"......++++....++++++++++++..",
+"....+++++...++++++++++++++..",
+"...++++....+++++++++++++++..",
+"..++++....++++++++++++++++..",
+"..++++....++++++++++++++++..",
+"...++++....+++++++++++++++..",
+"....+++++...++++++++++++++..",
+"......++++....++++++++++++..",
+".......+++++...+++++++++++..",
+".........++++....+++++++++..",
+"..........+++++...++++++++..",
+"............++++....++++++..",
+".............+++++...+++++..",
+"...............+++.....+++..",
+"................++......++..",
+"............................",
+"............................"};
diff --git a/symbols/frew1.xpm b/symbols/frew1.xpm
new file mode 100644
index 0000000..4aab792
--- /dev/null
+++ b/symbols/frew1.xpm
@@ -0,0 +1,31 @@
+/* XPM */
+static const char *const frew1_xpm[] = {
+"28 26 2 1",
+". c #FFFFFF",
+"+ c #000000",
+"............................",
+"............................",
+"................++......++..",
+"...............+++.....+++..",
+".............+++++...+++++..",
+"............++++....++++++..",
+"..........+++++...++++++++..",
+".........++++....+++++++++..",
+".......+++++...+++++++++++..",
+"......++++....++++++++++++..",
+"....+++++...++++++++++++++..",
+"...++++.....++++++++++++++..",
+"....+++++...++++++++++++++..",
+"......++++....++++++++++++..",
+".......+++++...+++++++++++..",
+".........++++....+++++++++..",
+"..........+++++...++++++++..",
+"............++++....++++++..",
+".............+++++...+++++..",
+"...............+++.....+++..",
+"................++......++..",
+"............................",
+"....................++++++..",
+"....................++++++..",
+"............................",
+"............................"};
diff --git a/symbols/frew2.xpm b/symbols/frew2.xpm
new file mode 100644
index 0000000..707edfc
--- /dev/null
+++ b/symbols/frew2.xpm
@@ -0,0 +1,31 @@
+/* XPM */
+static const char *const frew2_xpm[] = {
+"28 26 2 1",
+". c #FFFFFF",
+"+ c #000000",
+"............................",
+"............................",
+"................++......++..",
+"...............+++.....+++..",
+".............+++++...+++++..",
+"............++++....++++++..",
+"..........+++++...++++++++..",
+".........++++....+++++++++..",
+".......+++++...+++++++++++..",
+"......++++....++++++++++++..",
+"....+++++...++++++++++++++..",
+"...++++.....++++++++++++++..",
+"....+++++...++++++++++++++..",
+"......++++....++++++++++++..",
+".......+++++...+++++++++++..",
+".........++++....+++++++++..",
+"..........+++++...++++++++..",
+"............++++....++++++..",
+".............+++++...+++++..",
+"...............+++.....+++..",
+"................++......++..",
+"............................",
+"...........++++++...++++++..",
+"...........++++++...++++++..",
+"............................",
+"............................"};
diff --git a/symbols/frew3.xpm b/symbols/frew3.xpm
new file mode 100644
index 0000000..95a3d15
--- /dev/null
+++ b/symbols/frew3.xpm
@@ -0,0 +1,31 @@
+/* XPM */
+static const char *const frew3_xpm[] = {
+"28 26 2 1",
+". c #FFFFFF",
+"+ c #000000",
+"............................",
+"............................",
+"................++......++..",
+"...............+++.....+++..",
+".............+++++...+++++..",
+"............++++....++++++..",
+"..........+++++...++++++++..",
+".........++++....+++++++++..",
+".......+++++...+++++++++++..",
+"......++++....++++++++++++..",
+"....+++++...++++++++++++++..",
+"...++++.....++++++++++++++..",
+"....+++++...++++++++++++++..",
+"......++++....++++++++++++..",
+".......+++++...+++++++++++..",
+".........++++....+++++++++..",
+"..........+++++...++++++++..",
+"............++++....++++++..",
+".............+++++...+++++..",
+"...............+++.....+++..",
+"................++......++..",
+"............................",
+"..++++++...++++++...++++++..",
+"..++++++...++++++...++++++..",
+"............................",
+"............................"};
diff --git a/symbols/mute.xpm b/symbols/mute.xpm
new file mode 100644
index 0000000..90fb79c
--- /dev/null
+++ b/symbols/mute.xpm
@@ -0,0 +1,25 @@
+/* XPM */
+static const char *const mute_xpm[] = {
+"26 20 2 1",
+". c #FFFFFF",
+"+ c #000000",
+"......++.......++.......++",
+"......+++....++++......+++",
+".......+++..+++++.....+++.",
+"........+++..+.++....+++..",
+".......+.+++...++...+++...",
+".....++++.+++..++..+++....",
+"++++++++...+++....+++.....",
+"+++++++.....+++..+++......",
+"++...++......++++++.......",
+"++...++.......++++........",
+"++...++.......++++........",
+"++...++......++++++.......",
+"+++++++.....+++..+++......",
+"++++++++...+++....+++.....",
+".....++++.+++..++..+++....",
+".......+.+++...++...+++...",
+"........+++..+.++....+++..",
+".......+++..+++++.....+++.",
+"......+++....++++......+++",
+"......++.......++.......++"};
diff --git a/symbols/pause.xpm b/symbols/pause.xpm
new file mode 100644
index 0000000..945b794
--- /dev/null
+++ b/symbols/pause.xpm
@@ -0,0 +1,31 @@
+/* XPM */
+static const char *const pause_xpm[] = {
+"28 26 2 1",
+". c #FFFFFF",
+"+ c #000000",
+"............................",
+"............................",
+"......+++++......+++++......",
+"......+++++......+++++......",
+"......+++++......+++++......",
+"......+++++......+++++......",
+"......+++++......+++++......",
+"......+++++......+++++......",
+"......+++++......+++++......",
+"......+++++......+++++......",
+"......+++++......+++++......",
+"......+++++......+++++......",
+"......+++++......+++++......",
+"......+++++......+++++......",
+"......+++++......+++++......",
+"......+++++......+++++......",
+"......+++++......+++++......",
+"......+++++......+++++......",
+"......+++++......+++++......",
+"......+++++......+++++......",
+"......+++++......+++++......",
+"......+++++......+++++......",
+"......+++++......+++++......",
+"......+++++......+++++......",
+"............................",
+"............................"};
diff --git a/symbols/play.xpm b/symbols/play.xpm
new file mode 100644
index 0000000..ca27fa3
--- /dev/null
+++ b/symbols/play.xpm
@@ -0,0 +1,31 @@
+/* XPM */
+static const char *const play_xpm[] = {
+"28 26 2 1",
+". c #FFFFFF",
+"+ c #000000",
+"............................",
+"............................",
+"......++....................",
+"......+++...................",
+"......+++++.................",
+"......++++++................",
+"......++++++++..............",
+"......+++++++++.............",
+"......+++++++++++...........",
+"......++++++++++++..........",
+"......++++++++++++++........",
+"......+++++++++++++++.......",
+"......++++++++++++++++......",
+"......++++++++++++++++......",
+"......+++++++++++++++.......",
+"......++++++++++++++........",
+"......++++++++++++..........",
+"......+++++++++++...........",
+"......+++++++++.............",
+"......++++++++..............",
+"......++++++................",
+"......+++++.................",
+"......+++...................",
+"......++....................",
+"............................",
+"............................"};
diff --git a/symbols/radio.xpm b/symbols/radio.xpm
new file mode 100644
index 0000000..a14b0a9
--- /dev/null
+++ b/symbols/radio.xpm
@@ -0,0 +1,23 @@
+/* XPM */
+static const char *const radio_xpm[] = {
+"27 18 2 1",
+". c #FFFFFF",
+"+ c #000000",
+"...........................",
+"............+++++..........",
+"............+++++++++......",
+"............+++++++++++....",
+"............+++...++++++...",
+"............+++.....++++...",
+"............+++.....+++....",
+"............+++.....++.....",
+"............+++............",
+"............+++............",
+"............+++............",
+"......+++++++++............",
+"...+++++++++++++...........",
+"..+++++++++++++++..........",
+"..+++++++++++++++..........",
+"...+++++++++++++...........",
+".....++++++++++............",
+"..........................."};
diff --git a/symbols/recording.xpm b/symbols/recording.xpm
new file mode 100644
index 0000000..155df61
--- /dev/null
+++ b/symbols/recording.xpm
@@ -0,0 +1,23 @@
+/* XPM */
+static const char *const recording_xpm[] = {
+"27 18 2 1",
+". c #FFFFFF",
+"+ c #000000",
+"...........................",
+"...........................",
+"..++++++...++++++..++++++..",
+"..+++++++.+++++++.+++++++..",
+"..++...++.++......++.......",
+"..++...++.++......++.......",
+"..++...++.++......++.......",
+"..++...++.++......++.......",
+"..++++++..+++++...++.......",
+"..++++....+++++...++.......",
+"..++.++...++......++.......",
+"..++..++..++......++.......",
+"..++...++.++......++.......",
+"..++...++.++......++.......",
+"..++...++.+++++++.+++++++..",
+"..++...++..++++++..++++++..",
+"...........................",
+"..........................."};
diff --git a/symbols/sfwd.xpm b/symbols/sfwd.xpm
new file mode 100644
index 0000000..e79c69b
--- /dev/null
+++ b/symbols/sfwd.xpm
@@ -0,0 +1,31 @@
+/* XPM */
+static const char *const sfwd_xpm[] = {
+"28 26 2 1",
+". c #FFFFFF",
+"+ c #000000",
+"............................",
+"............................",
+"..+++++...++................",
+"..+++++...+++...............",
+"..+++++...+++++.............",
+"..+++++...++++++............",
+"..+++++...++++++++..........",
+"..+++++...+++++++++.........",
+"..+++++...+++++++++++.......",
+"..+++++...++++++++++++......",
+"..+++++...++++++++++++++....",
+"..+++++...+++++++++++++++...",
+"..+++++...++++++++++++++++..",
+"..+++++...++++++++++++++++..",
+"..+++++...+++++++++++++++...",
+"..+++++...++++++++++++++....",
+"..+++++...++++++++++++......",
+"..+++++...+++++++++++.......",
+"..+++++...+++++++++.........",
+"..+++++...++++++++..........",
+"..+++++...++++++............",
+"..+++++...+++++.............",
+"..+++++...+++...............",
+"..+++++...++................",
+"............................",
+"............................"};
diff --git a/symbols/sfwd1.xpm b/symbols/sfwd1.xpm
new file mode 100644
index 0000000..67cf6ce
--- /dev/null
+++ b/symbols/sfwd1.xpm
@@ -0,0 +1,31 @@
+/* XPM */
+static const char *const sfwd1_xpm[] = {
+"28 26 2 1",
+". c #FFFFFF",
+"+ c #000000",
+"............................",
+"............................",
+"..+++++...++................",
+"..+++++...+++...............",
+"..+++++...+++++.............",
+"..+++++...++++++............",
+"..+++++...++++++++..........",
+"..+++++...+++++++++.........",
+"..+++++...+++++++++++.......",
+"..+++++...++++++++++++......",
+"..+++++...++++++++++++++....",
+"..+++++...+++++++++++++++...",
+"..+++++...++++++++++++++....",
+"..+++++...++++++++++++......",
+"..+++++...+++++++++++.......",
+"..+++++...+++++++++.........",
+"..+++++...++++++++..........",
+"..+++++...++++++............",
+"..+++++...+++++.............",
+"..+++++...+++...............",
+"..+++++...++................",
+"............................",
+"..++++++....................",
+"..++++++....................",
+"............................",
+"............................"};
diff --git a/symbols/sfwd2.xpm b/symbols/sfwd2.xpm
new file mode 100644
index 0000000..a90bb92
--- /dev/null
+++ b/symbols/sfwd2.xpm
@@ -0,0 +1,31 @@
+/* XPM */
+static const char *const sfwd2_xpm[] = {
+"28 26 2 1",
+". c #FFFFFF",
+"+ c #000000",
+"............................",
+"............................",
+"..+++++...++................",
+"..+++++...+++...............",
+"..+++++...+++++.............",
+"..+++++...++++++............",
+"..+++++...++++++++..........",
+"..+++++...+++++++++.........",
+"..+++++...+++++++++++.......",
+"..+++++...++++++++++++......",
+"..+++++...++++++++++++++....",
+"..+++++...+++++++++++++++...",
+"..+++++...++++++++++++++....",
+"..+++++...++++++++++++......",
+"..+++++...+++++++++++.......",
+"..+++++...+++++++++.........",
+"..+++++...++++++++..........",
+"..+++++...++++++............",
+"..+++++...+++++.............",
+"..+++++...+++...............",
+"..+++++...++................",
+"............................",
+"..++++++...++++++...........",
+"..++++++...++++++...........",
+"............................",
+"............................"};
diff --git a/symbols/sfwd3.xpm b/symbols/sfwd3.xpm
new file mode 100644
index 0000000..e03965c
--- /dev/null
+++ b/symbols/sfwd3.xpm
@@ -0,0 +1,31 @@
+/* XPM */
+static const char *const sfwd3_xpm[] = {
+"28 26 2 1",
+". c #FFFFFF",
+"+ c #000000",
+"............................",
+"............................",
+"..+++++...++................",
+"..+++++...+++...............",
+"..+++++...+++++.............",
+"..+++++...++++++............",
+"..+++++...++++++++..........",
+"..+++++...+++++++++.........",
+"..+++++...+++++++++++.......",
+"..+++++...++++++++++++......",
+"..+++++...++++++++++++++....",
+"..+++++...+++++++++++++++...",
+"..+++++...++++++++++++++....",
+"..+++++...++++++++++++......",
+"..+++++...+++++++++++.......",
+"..+++++...+++++++++.........",
+"..+++++...++++++++..........",
+"..+++++...++++++............",
+"..+++++...+++++.............",
+"..+++++...+++...............",
+"..+++++...++................",
+"............................",
+"..++++++...++++++...++++++..",
+"..++++++...++++++...++++++..",
+"............................",
+"............................"};
diff --git a/symbols/srew.xpm b/symbols/srew.xpm
new file mode 100644
index 0000000..05b9dc1
--- /dev/null
+++ b/symbols/srew.xpm
@@ -0,0 +1,31 @@
+/* XPM */
+static const char *const srew_xpm[] = {
+"28 26 2 1",
+". c #FFFFFF",
+"+ c #000000",
+"............................",
+"............................",
+"................++...+++++..",
+"...............+++...+++++..",
+".............+++++...+++++..",
+"............++++++...+++++..",
+"..........++++++++...+++++..",
+".........+++++++++...+++++..",
+".......+++++++++++...+++++..",
+"......++++++++++++...+++++..",
+"....++++++++++++++...+++++..",
+"...+++++++++++++++...+++++..",
+"..++++++++++++++++...+++++..",
+"..++++++++++++++++...+++++..",
+"...+++++++++++++++...+++++..",
+"....++++++++++++++...+++++..",
+"......++++++++++++...+++++..",
+".......+++++++++++...+++++..",
+".........+++++++++...+++++..",
+"..........++++++++...+++++..",
+"............++++++...+++++..",
+".............+++++...+++++..",
+"...............+++...+++++..",
+"................++...+++++..",
+"............................",
+"............................"};
diff --git a/symbols/srew1.xpm b/symbols/srew1.xpm
new file mode 100644
index 0000000..43de690
--- /dev/null
+++ b/symbols/srew1.xpm
@@ -0,0 +1,31 @@
+/* XPM */
+static const char *const srew1_xpm[] = {
+"28 26 2 1",
+". c #FFFFFF",
+"+ c #000000",
+"............................",
+"............................",
+"................++...+++++..",
+"...............+++...+++++..",
+".............+++++...+++++..",
+"............++++++...+++++..",
+"..........++++++++...+++++..",
+".........+++++++++...+++++..",
+".......+++++++++++...+++++..",
+"......++++++++++++...+++++..",
+"....++++++++++++++...+++++..",
+"...+++++++++++++++...+++++..",
+"....++++++++++++++...+++++..",
+"......++++++++++++...+++++..",
+".......+++++++++++...+++++..",
+".........+++++++++...+++++..",
+"..........++++++++...+++++..",
+"............++++++...+++++..",
+".............+++++...+++++..",
+"...............+++...+++++..",
+"................++...+++++..",
+"............................",
+"....................++++++..",
+"....................++++++..",
+"............................",
+"............................"};
diff --git a/symbols/srew2.xpm b/symbols/srew2.xpm
new file mode 100644
index 0000000..f06a1e3
--- /dev/null
+++ b/symbols/srew2.xpm
@@ -0,0 +1,31 @@
+/* XPM */
+static const char *const srew2_xpm[] = {
+"28 26 2 1",
+". c #FFFFFF",
+"+ c #000000",
+"............................",
+"............................",
+"................++...+++++..",
+"...............+++...+++++..",
+".............+++++...+++++..",
+"............++++++...+++++..",
+"..........++++++++...+++++..",
+".........+++++++++...+++++..",
+".......+++++++++++...+++++..",
+"......++++++++++++...+++++..",
+"....++++++++++++++...+++++..",
+"...+++++++++++++++...+++++..",
+"....++++++++++++++...+++++..",
+"......++++++++++++...+++++..",
+".......+++++++++++...+++++..",
+".........+++++++++...+++++..",
+"..........++++++++...+++++..",
+"............++++++...+++++..",
+".............+++++...+++++..",
+"...............+++...+++++..",
+"................++...+++++..",
+"............................",
+"...........++++++...++++++..",
+"...........++++++...++++++..",
+"............................",
+"............................"};
diff --git a/symbols/srew3.xpm b/symbols/srew3.xpm
new file mode 100644
index 0000000..b881980
--- /dev/null
+++ b/symbols/srew3.xpm
@@ -0,0 +1,31 @@
+/* XPM */
+static const char *const srew3_xpm[] = {
+"28 26 2 1",
+". c #FFFFFF",
+"+ c #000000",
+"............................",
+"............................",
+"................++...+++++..",
+"...............+++...+++++..",
+".............+++++...+++++..",
+"............++++++...+++++..",
+"..........++++++++...+++++..",
+".........+++++++++...+++++..",
+".......+++++++++++...+++++..",
+"......++++++++++++...+++++..",
+"....++++++++++++++...+++++..",
+"...+++++++++++++++...+++++..",
+"....++++++++++++++...+++++..",
+"......++++++++++++...+++++..",
+".......+++++++++++...+++++..",
+".........+++++++++...+++++..",
+"..........++++++++...+++++..",
+"............++++++...+++++..",
+".............+++++...+++++..",
+"...............+++...+++++..",
+"................++...+++++..",
+"............................",
+"..++++++...++++++...++++++..",
+"..++++++...++++++...++++++..",
+"............................",
+"............................"};
diff --git a/symbols/teletext.xpm b/symbols/teletext.xpm
new file mode 100644
index 0000000..345ab9e
--- /dev/null
+++ b/symbols/teletext.xpm
@@ -0,0 +1,23 @@
+/* XPM */
+static const char *const teletext_xpm[] = {
+"27 18 2 1",
+". c #FFFFFF",
+"+ c #000000",
+"...........................",
+"...........................",
+"..+++++++++++++++++++++++..",
+"..+++++++++++++++++++++++..",
+"..++...................++..",
+"..++..+++++++++++++++..++..",
+"..++..+++++++++++++++..++..",
+"..++...................++..",
+"..++..+++++++++++++++..++..",
+"..++..+++++++++++++++..++..",
+"..++...................++..",
+"..++..+++++++++++++++..++..",
+"..++..+++++++++++++++..++..",
+"..++...................++..",
+"..+++++++++++++++++++++++..",
+"..+++++++++++++++++++++++..",
+"...........................",
+"..........................."};
diff --git a/symbols/volume.xpm b/symbols/volume.xpm
new file mode 100644
index 0000000..c6186fe
--- /dev/null
+++ b/symbols/volume.xpm
@@ -0,0 +1,19 @@
+/* XPM */
+static const char *const volume_xpm[] = {
+"28 14 2 1",
+". c #FFFFFF",
+"+ c #000000",
+"..........................++",
+"........................++++",
+"......................++++++",
+"....................++++++++",
+"..................++++++++++",
+"................++++++++++++",
+"..............++++++++++++++",
+"............++++++++++++++++",
+"..........++++++++++++++++++",
+"........++++++++++++++++++++",
+"......++++++++++++++++++++++",
+"....++++++++++++++++++++++++",
+"..++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++"};
diff --git a/themes/flat-white.theme b/themes/flat-white.theme
new file mode 100644
index 0000000..bfcea97
--- /dev/null
+++ b/themes/flat-white.theme
@@ -0,0 +1,49 @@
+Description = Default
+clrTopBarBg = 90CCCCCC
+clrTopBarFont = FF222222
+clrTopBarDateTimeFont = FF222222
+clrButtonBg = 90CCCCCC
+clrButtonFont = FF222222
+clrButtonRed = 99BB0000
+clrButtonGreen = 9900BB00
+clrButtonYellow = 99BBBB00
+clrButtonBlue = 990000BB
+clrMessageBg = 90CCCCCC
+clrMessageFont = FF222222
+clrMessageStatus = 900000FF
+clrMessageInfo = 90009900
+clrMessageWarning = 90BBBB00
+clrMessageError = 90BB0000
+clrChannelBg = 90CCCCCC
+clrChannelFontTitle = FF222222
+clrChannelFontEpg = FF222222
+clrChannelProgressFg = FFFFFFFF
+clrChannelProgressBg = FFFFFFFF
+clrItemBg = 90808080
+clrItemFont = FF222222
+clrItemCurrentBg = 903090B0
+clrItemCurrentFont = FF222222
+clrItemSelableBg = 90CCCCCC
+clrItemSelableFont = FF222222
+clrScrollbarFg = FFFFFFFF
+clrScrollbarBg = FFFFFFFF
+clrMenuEventBg = 90CCCCCC
+clrMenuEventFontTitle = FF222222
+clrMenuEventFontInfo = FF222222
+clrMenuRecBg = 90CCCCCC
+clrMenuRecFontTitle = FF222222
+clrMenuRecFontInfo = FF222222
+clrMenuTextBg = 90CCCCCC
+clrMenuTextFont = FF222222
+clrReplayBg = 90CCCCCC
+clrReplayFont = FF222222
+clrReplayProgressFg = FFFFFFFF
+clrReplayProgressBg = FFFFFFFF
+clrTrackItemBg = 90CCCCCC
+clrTrackItemFont = FF222222
+clrTrackItemCurrentBg = 906AB0C0
+clrTrackItemCurrentFont = FF222222
+clrVolumeBg = 90CCCCCC
+clrVolumeFont = FF222222
+clrVolumeProgressFg = FFFFFFFF
+clrVolumeProgressBg = FFFFFFFF