Initial push tvguide 0.0.1

This commit is contained in:
louis 2013-01-17 13:16:44 +01:00
commit 47c3fea545
34 changed files with 3740 additions and 0 deletions

340
COPYING Normal file
View File

@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

6
HISTORY Normal file
View File

@ -0,0 +1,6 @@
VDR Plugin 'tvguide' Revision History
-------------------------------------
2012-08-12: Version 0.0.1
- Initial revision.

122
Makefile Normal file
View File

@ -0,0 +1,122 @@
#
# 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.
#
PLUGIN = tvguide
### 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 = $(DESTDIR)$(call PKGCFG,libdir)
LOCDIR = $(DESTDIR)$(call PKGCFG,locdir)
PLGCFG = $(call PKGCFG,plgcfg)
CONFDIR= $(DESTDIR)$(call PKGCFG,configdir)
TMPDIR ?= /tmp
### The compiler options:
export CFLAGS = $(call PKGCFG,cflags)
export CXXFLAGS = $(call PKGCFG,cxxflags)
### Allow user defined options to overwrite defaults:
-include $(PLGCFG)
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 (add further entries here):
INCLUDES +=
INCLUDES += -I/usr/include/ImageMagick
DEFINES += -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
### The object files (add further files here):
OBJS = $(PLUGIN).o
### The main target:
all: $(SOFILE) i18n
### Implicit rules:
%.o: %.c
$(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) $<
### Dependencies:
MAKEDEP = $(CXX) -MM -MG
DEPFILE = .dependencies
$(DEPFILE): Makefile
@$(MAKEDEP) $(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 $(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): $(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) -lMagick++ -o $@
install-lib: $(SOFILE)
install -D $^ $(LIBDIR)/$^.$(APIVERSION)
install-themes:
@mkdir -p $(CONFDIR)/themes
cp themes/* $(CONFDIR)/themes
install: install-lib install-i18n install-themes
dist: $(I18Npo) clean
@-rm -rf $(TMPDIR)/$(ARCHIVE)
@mkdir $(TMPDIR)/$(ARCHIVE)
@cp -a * $(TMPDIR)/$(ARCHIVE)
@tar czf $(PACKAGE).tgz -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* *~

115
Makefile-smaller-VDR1.7.34 Normal file
View File

@ -0,0 +1,115 @@
#
# 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 = tvguide
### 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 C++ compiler and options:
CXX ?= g++
CXXFLAGS ?= -g -O3 -Wall -Woverloaded-virtual -Wno-parentheses
### The directory environment:
VDRDIR ?= ../../..
LIBDIR ?= ../../lib
TMPDIR ?= /tmp
### Make sure that necessary options are included:
include $(VDRDIR)/Make.global
### Allow user defined options to overwrite defaults:
-include $(VDRDIR)/Make.config
### The version number of VDR's plugin API (taken from VDR's "config.h"):
APIVERSION = $(shell sed -ne '/define APIVERSION/s/^.*"\(.*\)".*$$/\1/p' $(VDRDIR)/config.h)
### The name of the distribution archive:
ARCHIVE = $(PLUGIN)-$(VERSION)
PACKAGE = vdr-$(ARCHIVE)
### Includes and Defines (add further entries here):
INCLUDES += -I$(VDRDIR)/include
INCLUDES += -I/usr/include/ImageMagick
DEFINES += -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
### The object files (add further files here):
OBJS = $(PLUGIN).o
### The main target:
all: libvdr-$(PLUGIN).so i18n
### Implicit rules:
%.o: %.c
$(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) $<
### Dependencies:
MAKEDEP = $(CXX) -MM -MG
DEPFILE = .dependencies
$(DEPFILE): Makefile
@$(MAKEDEP) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.c) > $@
-include $(DEPFILE)
### Internationalization (I18N):
PODIR = po
LOCALEDIR = $(VDRDIR)/locale
I18Npo = $(wildcard $(PODIR)/*.po)
I18Nmsgs = $(addprefix $(LOCALEDIR)/, $(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 $@ $^
%.po: $(I18Npot)
msgmerge -U --no-wrap --no-location --backup=none -q $@ $<
@touch $@
$(I18Nmsgs): $(LOCALEDIR)/%/LC_MESSAGES/vdr-$(PLUGIN).mo: $(PODIR)/%.mo
@mkdir -p $(dir $@)
cp $< $@
.PHONY: i18n
i18n: $(I18Nmsgs) $(I18Npot)
### Targets:
libvdr-$(PLUGIN).so: $(OBJS)
$(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(OBJS) -lMagick++ -o $@
@cp --remove-destination $@ $(LIBDIR)/$@.$(APIVERSION)
dist: $(I18Npo) clean
@-rm -rf $(TMPDIR)/$(ARCHIVE)
@mkdir $(TMPDIR)/$(ARCHIVE)
@cp -a * $(TMPDIR)/$(ARCHIVE)
@tar czf $(PACKAGE).tgz -C $(TMPDIR) $(ARCHIVE)
@-rm -rf $(TMPDIR)/$(ARCHIVE)
@echo Distribution package created as $(PACKAGE).tgz
clean:
@-rm -f $(OBJS) $(DEPFILE) *.so *.tgz core* *~ $(PODIR)/*.mo $(PODIR)/*.pot

132
README Normal file
View File

@ -0,0 +1,132 @@
This is a "plugin" for the Video Disk Recorder (VDR).
Written by: Louis Braun <louis DOT braun AT gmx DOT de>
Project's homepage: URL
Latest version available at: URL
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.17 (TrueColor OSD is mandatorily needed)
- Installed ImageMagick for showing png/jpg Channel Logos and EPG Images
Description
-----------
"TvGuide" is a highly customizable 2D EPG viewer plugin.
Installation
------------
After "normal" Plugin installation copy the themes from
/put/your/path/here/VDR/PLUGINS/src/tvguide/themes/
to
VDRCONF/themes/
Options
-------
-l path, --logodir=path
Path to the logos (Default: <vdrconfdir>/plugins/tvguide/channellogos/).
-i path, --epgimages=path
Path to the epgimages (Default: <vdrconfdir>/plugins/tvguide/epgimages/).
Usage
-----
Remote Control Keys:
Up/Down/Left/Right: Navigation in the EPG grid
Ok: Detailed EPG View of the selected grid
2nd Ok closes the detailed view
Red: Set recording timer for the currently selected grid
Green / Yellow: Jump (default) five channels back / forward
Blue: Switch to currently selected channel
1 / 3: Big jump (default 3h) back / forward in time
4 / 6: huge jump (default 24h) back / forward in time
7 / 9: jump to previous / next prime time (8pm)
Exit: closes plugin
Setup Options
-------------
* General:
- Number of Channels / Columns:
Number of columns per screen (max. 8)
Keep in mind that the True Color OSD displays 64 Pixmaps in maximum, and each EPG
entry is a dedicated Pixmap. So if this value is too large, maybe not all EPG
information is shown on the screen.
- Channel Jump (Keys Green / Yellow):
Number of channels to jump back / forward, counted from the currently selected
channel (channel to which the selected EPG entry belongs)
- Time to display vertically in minutes
With this value the number of minutes per screen is determinated. The value is
an approximately value, because rounded values are used during calculation.
int((OSD Height - Header Height - Footer Height) / value)
--> Number of Pixel for one minute
- Big Step (Keys 1 / 3) in hours
Hours to jump vertically with keys 1 / 3
- Huge Step (Keys 4 / 6) in hours
Hours to jump vertically with keys 4 / 6
- Time Format (12h/24h)
Switching between 12h and 24h time format
* Screen Layout:
- Theme
Used Theme, theme files have to be placed accordingly
- Width of left Time Column
Width of almost left column in Pixel
- Height of Header (Channel Logos)
Height of header row in Pixel
- Height of Footer (Buttons)
Height of footer with color buttons in Pixel
- Show Channel Logos
show / hide channel logos, if logos are shown:
- Logo Extension
jpg / png
- Logo width
in Pixel
- Logo height
in Pixel
- Show EPG Images
show / hide EPG images, if images are shown:
- EPG Image width
in Pixel
- EPG Image height
in Pixel
* Fonts and Fontsizes:
- Font:
Used Font, all Fonts installed on your system are shown
- various font sizes:
Size in Pixel used for described purpose

274
channelcolumn.c Normal file
View File

@ -0,0 +1,274 @@
#include "channelcolumn.h"
cChannelColumn::cChannelColumn(int num, cChannel *channel, cMyTime *myTime) {
this->channel = channel;
this->num = num;
this->myTime = myTime;
hasTimer = channel->HasTimer();
}
cChannelColumn::~cChannelColumn(void) {
grids.Clear();
}
void cChannelColumn::clearGrids() {
grids.Clear();
}
void cChannelColumn::createHeader() {
color = theme.Color(clrHeader);
colorBlending = theme.Color(clrHeaderBlending);
caller = cString::sprintf("channelcolumn %s", channel->Name());
pixmap = osdManager.requestPixmap(2, cRect(tvguideConfig.timeColWidth + num*tvguideConfig.colWidth, 0, tvguideConfig.colWidth, tvguideConfig.headerHeight),
cRect::Null, *caller);
if (!pixmap) {
return;
}
drawBackground();
cTextWrapper tw;
cString headerText = cString::sprintf("%d - %s", channel->Number(), channel->Name());
tw.Set(*headerText, tvguideConfig.FontHeader, tvguideConfig.colWidth - 8);
int lines = tw.Lines();
int lineHeight = tvguideConfig.FontHeader->Height();
int yStart = (tvguideConfig.headerHeight - lines*lineHeight)/2 + 8;
if (!tvguideConfig.hideChannelLogos) {
cImageLoader imgLoader;
if (imgLoader.LoadLogo(channel->Name())) {
cImage logo = imgLoader.GetImage();
int logoX = (tvguideConfig.colWidth - tvguideConfig.logoWidth)/2;
pixmap->DrawImage(cPoint(logoX, 5), logo);
}
yStart = tvguideConfig.logoHeight + 8;
}
for (int i=0; i<lines; i++) {
int textWidth = tvguideConfig.FontHeader->Width(tw.GetLine(i));
int xText = (tvguideConfig.colWidth - textWidth) / 2;
if (xText < 0)
xText = 0;
pixmap->DrawText(cPoint(xText, yStart + i*lineHeight), tw.GetLine(i), theme.Color(clrFontHeader), clrTransparent, tvguideConfig.FontHeader);
}
drawBorder();
}
void cChannelColumn::drawHeader() {
pixmap->SetViewPort(cRect(tvguideConfig.timeColWidth + num*tvguideConfig.colWidth, 0, tvguideConfig.colWidth, tvguideConfig.headerHeight));
}
bool cChannelColumn::readGrids() {
schedules = cSchedules::Schedules(schedulesLock);
const cSchedule *Schedule = NULL;
Schedule = schedules->GetSchedule(channel);
if (!Schedule) {
return false;
}
bool eventFound = false;
const cEvent *event = Schedule->GetEventAround(myTime->GetStart());
if (event != NULL) {
eventFound = true;
} else {
for (int i=1; i<6; i++) {
event = Schedule->GetEventAround(myTime->GetStart()+i*5*60);
if (event) {
eventFound = true;
break;
}
}
}
if (eventFound) {
bool col = true;
for (; event; event = Schedule->Events()->Next(event)) {
cEpgGrid *grid = new cEpgGrid(this, event);
grid->setText();
grid->SetColor(col);
col = !col;
grids.Add(grid);
if (event->EndTime() > myTime->GetStop()) {
break;
}
}
return true;
} else {
return false;
}
}
void cChannelColumn::drawGrids() {
for (cEpgGrid *grid = grids.First(); grid; grid = grids.Next(grid)) {
grid->SetViewportHeight();
grid->PositionPixmap();
grid->Draw();
}
}
int cChannelColumn::getX() {
return tvguideConfig.timeColWidth + num*tvguideConfig.colWidth;
}
cEpgGrid * cChannelColumn::getActive() {
cMyTime t;
t.Now();
for (cEpgGrid *grid = grids.First(); grid; grid = grids.Next(grid)) {
if (grid->isActiveInitial(t.Get()))
return grid;
}
return grids.First();
}
cEpgGrid * cChannelColumn::getNext(cEpgGrid *activeGrid) {
if (activeGrid == NULL)
return NULL;
cEpgGrid *next = grids.Next(activeGrid);
if (next)
return next;
return NULL;
}
cEpgGrid * cChannelColumn::getPrev(cEpgGrid *activeGrid) {
if (activeGrid == NULL)
return NULL;
cEpgGrid *prev = grids.Prev(activeGrid);
if (prev)
return prev;
return NULL;
}
cEpgGrid * cChannelColumn::getNeighbor(cEpgGrid *activeGrid) {
if (!activeGrid)
return NULL;
cEpgGrid *neighbor = NULL;
int overlap = 0;
int overlapNew = 0;
cEpgGrid *grid = NULL;
grid = grids.First();
if (grid) {
for (; grid; grid = grids.Next(grid)) {
if ( (grid->StartTime() == activeGrid->StartTime()) ) {
neighbor = grid;
break;
}
overlapNew = activeGrid->calcOverlap(grid);
if (overlapNew > overlap) {
neighbor = grid;
overlap = overlapNew;
}
}
}
if (!neighbor)
neighbor = grids.First();
return neighbor;
}
void cChannelColumn::AddNewGridsAtStart() {
cEpgGrid *firstGrid = NULL;
firstGrid = grids.First();
if (firstGrid == NULL) {
//no epg, completely new.
schedules = cSchedules::Schedules(schedulesLock);
const cSchedule *Schedule = NULL;
Schedule = schedules->GetSchedule(channel);
if (!Schedule)
return;
const cEvent *event = Schedule->GetEventAround(myTime->GetStart());
if (!event)
return;
cEpgGrid *grid = new cEpgGrid(this, event);
grid->setText();
grid->SetColor(true);
grids.Ins(grid, grids.First());
return;
} else {
//if first event is long enough, nothing to do.
if (firstGrid->StartTime() <= myTime->GetStart()) {
return;
}
//if not, i have to add new ones to the list
schedules = cSchedules::Schedules(schedulesLock);
const cSchedule *Schedule = NULL;
Schedule = schedules->GetSchedule(channel);
if (!Schedule)
return;
bool col = !(firstGrid->IsColor1());
for (const cEvent *event = Schedule->GetEventAround(firstGrid->StartTime()-60); event; event = Schedule->Events()->Prev(event)) {
if (!event)
return;
cEpgGrid *grid = new cEpgGrid(this, event);
grid->setText();
grid->SetColor(col);
col = !col;
grids.Ins(grid, firstGrid);
firstGrid = grid;
if (event->StartTime() <= myTime->GetStart()) {
break;
}
}
}
}
void cChannelColumn::AddNewGridsAtEnd() {
cEpgGrid *lastGrid = NULL;
lastGrid = grids.Last();
if (lastGrid == NULL)
return;
//if last event is long enough, nothing to do.
if (lastGrid->EndTime() > myTime->GetStop()) {
return;
}
//if not, i have to add new ones to the list
schedules = cSchedules::Schedules(schedulesLock);
const cSchedule *Schedule = NULL;
Schedule = schedules->GetSchedule(channel);
if (!Schedule)
return;
bool col = !(lastGrid->IsColor1());
for (const cEvent *event = Schedule->GetEventAround(lastGrid->EndTime()+60); event; event = Schedule->Events()->Next(event)) {
if (!event)
return;
cEpgGrid *grid = new cEpgGrid(this, event);
grid->setText();
grid->SetColor(col);
col = !col;
grids.Add(grid);
if (event->EndTime() > myTime->GetStop()) {
break;
}
}
}
void cChannelColumn::ClearOutdatedStart() {
bool goOn = true;
cEpgGrid *firstGrid = NULL;
while (goOn) {
firstGrid = grids.First();
if ((firstGrid != NULL)&&(firstGrid->EndTime() < myTime->GetStart())) {
grids.Del(firstGrid);
firstGrid = NULL;
} else {
goOn = false;
}
}
}
void cChannelColumn::ClearOutdatedEnd() {
bool goOn = true;
cEpgGrid *lastGrid = NULL;
while (goOn) {
lastGrid = grids.Last();
if ((lastGrid != NULL)&&(lastGrid->StartTime() > myTime->GetStop())) {
grids.Del(lastGrid);
lastGrid = NULL;
} else {
goOn = false;
}
}
}
void cChannelColumn::dumpGrids() {
esyslog("------Channel %s ---------", channel->Name());
for (cEpgGrid *grid = grids.First(); grid; grid = grids.Next(grid)) {
grid->debug();
}
}

41
channelcolumn.h Normal file
View File

@ -0,0 +1,41 @@
#ifndef __TVGUIDE_CHANNELCOLUMN_H
#define __TVGUIDE_CHANNELCOLUMN_H
class cEpgGrid;
// --- cChannelColumn -------------------------------------------------------------
class cChannelColumn : public cListObject, public cStyledPixmap {
friend class cEpgGrid;
private:
cMyTime *myTime;
int num;
cChannel *channel;
cList<cEpgGrid> grids;
cSchedulesLock schedulesLock;
const cSchedules *schedules;
bool hasTimer;
public:
cChannelColumn(int num, cChannel *channel, cMyTime *myTime);
virtual ~cChannelColumn(void);
void createHeader();
void drawHeader();
bool readGrids();
void drawGrids();
int getX();
cChannel * getChannel() {return channel;}
cEpgGrid * getActive();
cEpgGrid * getNext(cEpgGrid *activeGrid);
cEpgGrid * getPrev(cEpgGrid *activeGrid);
cEpgGrid * getNeighbor(cEpgGrid *activeGrid);
void AddNewGridsAtStart();
void AddNewGridsAtEnd();
void ClearOutdatedStart();
void ClearOutdatedEnd();
int GetNum() {return num;};
void SetNum(int num) {this->num = num;};
void setTimer() {hasTimer = true;};
void clearGrids();
void dumpGrids();
};
#endif //__TVGUIDE_CHANNELCOLUMN_H

176
config.c Normal file
View File

@ -0,0 +1,176 @@
#include "config.h"
enum {
e12Hours,
e24Hours
};
cTvguideConfig::cTvguideConfig() {
osdWidth = 0;
osdHeight = 0;
colWidth = 0;
channelCols = 5;
displayTime = 160;
minuteHeight = 0;
timeColWidth = 120;
headerHeight = 120;
footerHeight = 80;
stepMinutes = 30;
bigStepHours = 3;
hugeStepHours = 24;
jumpChannels = 5;
hideChannelLogos = 0;
logoWidth = 130;
logoHeight = 73;
logoExtension = 0;
hideEpgImages = 0;
epgImageWidth = 315;
epgImageHeight = 240;
fontIndex = 0;
fontNameDefault = "VDRSymbols Sans:Book";
fontHeaderSize = 33;
fontGridSize = 27;
fontGridSmallSize = 24;
fontTimeLineWeekdaySize = 40;
fontTimeLineDateSize = 33;
fontTimeLineTimeSize = 0;
fontTimeLineTimeSizeDef12 = 24;
fontTimeLineTimeSizeDef24 = 33;
fontButtonSize = 33;
fontDetailViewSize = 33;
fontDetailHeaderSize = 40;
fontMessageBoxSize = 33;
fontMessageBoxLargeSize = 40;
FontHeader = NULL;
FontGrid = NULL;
FontGridSmall = NULL;
FontTimeLineWeekday = NULL;
FontTimeLineDate = NULL;
FontTimeLineTime = NULL;
FontButton = NULL;
FontDetailView = NULL;
FontDetailHeader = NULL;
FontMessageBox = NULL;
FontMessageBoxLarge = NULL;
timeFormat = 1;
themeIndex = 0;
useBlending = 1;
roundedCorners = 0;
}
cTvguideConfig::~cTvguideConfig() {
delete FontHeader;
delete FontGrid;
delete FontGridSmall;
delete FontTimeLineWeekday;
delete FontTimeLineDate;
delete FontTimeLineTime;
delete FontButton;
delete FontDetailView;
delete FontDetailHeader;
delete FontMessageBox;
delete FontMessageBoxLarge;
}
void cTvguideConfig::setDynamicValues(int width, int height) {
osdWidth = width;
osdHeight = height;
colWidth = (osdWidth - timeColWidth) / channelCols;
minuteHeight = (osdHeight - headerHeight - footerHeight) / displayTime;
if (!fontTimeLineTimeSize) {
if (timeFormat == e12Hours) {
fontTimeLineTimeSize = fontTimeLineTimeSizeDef12;
} else if (timeFormat == e24Hours) {
fontTimeLineTimeSize = fontTimeLineTimeSizeDef24;
}
} else if ((fontTimeLineTimeSize == fontTimeLineTimeSizeDef12) && (timeFormat == e24Hours)) {
fontTimeLineTimeSize = fontTimeLineTimeSizeDef24;
} else if ((fontTimeLineTimeSize == fontTimeLineTimeSizeDef24) && (timeFormat == e12Hours)) {
fontTimeLineTimeSize = fontTimeLineTimeSizeDef12;
}
cString fontname;
if (fontIndex == 0) {
fontname = fontNameDefault;
} else {
cStringList availableFonts;
cFont::GetAvailableFontNames(&availableFonts);
if (availableFonts[fontIndex-1]) {
fontname = availableFonts[fontIndex-1];
} else
fontname = fontNameDefault;
}
cFont *test = NULL;
test = cFont::CreateFont(*fontname, fontHeaderSize);
if (!test) {
fontname = DefaultFontSml;
}
delete test;
FontHeader = cFont::CreateFont(*fontname, fontHeaderSize);
FontGrid = cFont::CreateFont(*fontname, fontGridSize);
FontGridSmall = cFont::CreateFont(*fontname, fontGridSmallSize);
FontTimeLineWeekday = cFont::CreateFont(*fontname, fontTimeLineWeekdaySize);
FontTimeLineDate = cFont::CreateFont(*fontname, fontTimeLineDateSize);
FontTimeLineTime = cFont::CreateFont(*fontname, fontTimeLineTimeSize);
FontButton = cFont::CreateFont(*fontname, fontButtonSize);
FontDetailView = cFont::CreateFont(*fontname, fontDetailViewSize);
FontDetailHeader = cFont::CreateFont(*fontname, fontDetailHeaderSize);
FontMessageBox = cFont::CreateFont(*fontname, fontMessageBoxSize);
FontMessageBoxLarge = cFont::CreateFont(*fontname, fontMessageBoxLargeSize);
}
void cTvguideConfig::SetLogoPath(cString path) {
logoPath = path;
}
void cTvguideConfig::SetImagesPath(cString path) {
epgImagePath = path;
}
void cTvguideConfig::loadTheme() {
cThemes themes;
themes.Load(*cString("tvguide"));
const char *FileName = themes.FileName(themeIndex);
if (access(FileName, F_OK) == 0) {
::theme.Load(FileName);
}
}
bool cTvguideConfig::SetupParse(const char *Name, const char *Value) {
if (strcmp(Name, "timeFormat") == 0) timeFormat = atoi(Value);
else if (strcmp(Name, "themeIndex") == 0) themeIndex = atoi(Value);
else if (strcmp(Name, "useBlending") == 0) useBlending = atoi(Value);
else if (strcmp(Name, "roundedCorners") == 0) roundedCorners = atoi(Value);
else if (strcmp(Name, "channelCols") == 0) channelCols = atoi(Value);
else if (strcmp(Name, "displayTime") == 0) displayTime = atoi(Value);
else if (strcmp(Name, "hideChannelLogos") == 0) hideChannelLogos = atoi(Value);
else if (strcmp(Name, "logoExtension") == 0) logoExtension = atoi(Value);
else if (strcmp(Name, "logoWidth") == 0) logoWidth = atoi(Value);
else if (strcmp(Name, "logoHeight") == 0) logoHeight = atoi(Value);
else if (strcmp(Name, "bigStepHours") == 0) bigStepHours = atoi(Value);
else if (strcmp(Name, "hugeStepHours") == 0) hugeStepHours = atoi(Value);
else if (strcmp(Name, "jumpChannels") == 0) jumpChannels = atoi(Value);
else if (strcmp(Name, "hideEpgImages") == 0) hideEpgImages = atoi(Value);
else if (strcmp(Name, "epgImageWidth") == 0) epgImageWidth = atoi(Value);
else if (strcmp(Name, "epgImageHeight") == 0) epgImageHeight = atoi(Value);
else if (strcmp(Name, "timeColWidth") == 0) timeColWidth = atoi(Value);
else if (strcmp(Name, "headerHeight") == 0) headerHeight = atoi(Value);
else if (strcmp(Name, "footerHeight") == 0) footerHeight = atoi(Value);
else if (strcmp(Name, "fontIndex") == 0) fontIndex = atoi(Value);
else if (strcmp(Name, "fontHeaderSize") == 0) fontHeaderSize = atoi(Value);
else if (strcmp(Name, "fontGridSize") == 0) fontGridSize = atoi(Value);
else if (strcmp(Name, "fontGridSmallSize") == 0) fontGridSmallSize = atoi(Value);
else if (strcmp(Name, "fontTimeLineWeekdaySize") == 0) fontTimeLineWeekdaySize = atoi(Value);
else if (strcmp(Name, "fontTimeLineDateSize") == 0) fontTimeLineDateSize = atoi(Value);
else if (strcmp(Name, "fontTimeLineTimeSize") == 0) fontTimeLineTimeSize = atoi(Value);
else if (strcmp(Name, "fontButtonSize") == 0) fontButtonSize = atoi(Value);
else if (strcmp(Name, "fontDetailViewSize") == 0) fontDetailViewSize = atoi(Value);
else if (strcmp(Name, "fontDetailHeaderSize") == 0) fontDetailHeaderSize = atoi(Value);
else if (strcmp(Name, "fontMessageBoxSize") == 0) fontMessageBoxSize = atoi(Value);
else if (strcmp(Name, "fontMessageBoxLargeSize") == 0) fontMessageBoxLargeSize = atoi(Value);
else return false;
return true;
}

67
config.h Normal file
View File

@ -0,0 +1,67 @@
#ifndef __TVGUIDE_CONFIG_H
#define __TVGUIDE_CONFIG_H
class cTvguideConfig {
public:
cTvguideConfig();
~cTvguideConfig();
void SetLogoPath(cString path);
void SetImagesPath(cString path);
int osdWidth;
int osdHeight;
int colWidth;
int channelCols;
int displayTime;
int minuteHeight;
int timeColWidth;
int headerHeight;
int footerHeight;
int stepMinutes;
int bigStepHours;
int hugeStepHours;
int jumpChannels;
int hideChannelLogos;
int logoWidth;
int logoHeight;
cString logoPath;
int logoExtension;
int hideEpgImages;
int epgImageWidth;
int epgImageHeight;
cString epgImagePath;
int fontIndex;
const char *fontNameDefault;
int fontHeaderSize;
int fontGridSize;
int fontGridSmallSize;
int fontTimeLineWeekdaySize;
int fontTimeLineDateSize;
int fontTimeLineTimeSize;
int fontTimeLineTimeSizeDef12;
int fontTimeLineTimeSizeDef24;
int fontButtonSize;
int fontDetailViewSize;
int fontDetailHeaderSize;
int fontMessageBoxSize;
int fontMessageBoxLargeSize;
const cFont *FontHeader;
const cFont *FontGrid;
const cFont *FontGridSmall;
const cFont *FontTimeLineWeekday;
const cFont *FontTimeLineDate;
const cFont *FontTimeLineTime;
const cFont *FontButton;
const cFont *FontDetailView;
const cFont *FontDetailHeader;
const cFont *FontMessageBox;
const cFont *FontMessageBoxLarge;
int timeFormat;
int themeIndex;
int useBlending;
int roundedCorners;
void setDynamicValues(int width, int height);
bool SetupParse(const char *Name, const char *Value);
void loadTheme();
};
#endif //__TVGUIDE_CONFIG_H

186
detailview.c Normal file
View File

@ -0,0 +1,186 @@
#include "detailview.h"
cDetailView::cDetailView(cEpgGrid *grid) {
this->grid = grid;
this->event = grid->GetEvent();
imgScrollBar = NULL;
FrameTime = 40; // ms
FadeTime = 500; // ms
borderWidth = 100; //px
headerHeight = max (80 + tvguideConfig.logoHeight + 3 * tvguideConfig.FontDetailHeader->Height(), // border + logo + 3 Lines
80 + tvguideConfig.epgImageHeight);
description.Set(event->Description(), tvguideConfig.FontDetailView, tvguideConfig.osdWidth-2*borderWidth - 50 - 40);
contentScrollable = setContentDrawportHeight();
createPixmaps();
}
cDetailView::~cDetailView(void){
delete header;
osdManager.releasePixmap(content);
osdManager.releasePixmap(scrollBar);
osdManager.releasePixmap(footer);
delete imgScrollBar;
}
bool cDetailView::setContentDrawportHeight() {
int linesContent = description.Lines() + 1;
heightContent = linesContent * tvguideConfig.FontDetailView->Height();
if (heightContent > (tvguideConfig.osdHeight - 2 * borderWidth - headerHeight))
return true;
else
return false;
}
void cDetailView::createPixmaps() {
int scrollBarWidth = 50;
header = new cStyledPixmap(osdManager.requestPixmap(5, cRect(borderWidth, borderWidth, tvguideConfig.osdWidth - 2*borderWidth, headerHeight), cRect::Null, "detailViewHeader"), "detailViewHeader");
header->SetAlpha(0);
header->setColor(theme.Color(clrHeader), theme.Color(clrHeaderBlending));
content = osdManager.requestPixmap(5, cRect(borderWidth, borderWidth + headerHeight, tvguideConfig.osdWidth - 2*borderWidth - scrollBarWidth, tvguideConfig.osdHeight-2*borderWidth-headerHeight),
cRect(0,0, tvguideConfig.osdWidth - 2*borderWidth - scrollBarWidth, max(heightContent, tvguideConfig.osdHeight-2*borderWidth-headerHeight)));
content->SetAlpha(0);
header->setColor(theme.Color(clrHeader), theme.Color(clrHeaderBlending));
scrollBar = osdManager.requestPixmap(5, cRect(tvguideConfig.osdWidth-borderWidth-scrollBarWidth, borderWidth + headerHeight, scrollBarWidth, tvguideConfig.osdHeight-2*borderWidth-headerHeight));
scrollBar->SetAlpha(0);
footer = osdManager.requestPixmap(5, cRect(borderWidth, borderWidth + headerHeight + content->ViewPort().Height(), tvguideConfig.osdWidth - 2*borderWidth, 3));
footer->SetAlpha(0);
footer->Fill(clrWhite);
}
void cDetailView::drawHeader() {
header->drawBackground();
header->drawBoldBorder();
int lineHeight = tvguideConfig.FontDetailHeader->Height();
int offset = 30;
cImageLoader imgLoader;
if (tvguideConfig.hideChannelLogos) {
header->DrawText(cPoint(20, offset + 10), grid->column->getChannel()->Name(), theme.Color(clrFont), clrTransparent, tvguideConfig.FontDetailHeader);
offset += lineHeight + 10;
} else {
if (imgLoader.LoadLogo(grid->column->getChannel()->Name())) {
cImage logo = imgLoader.GetImage();
header->DrawImage(cPoint(20, 20), logo);
}
offset += tvguideConfig.logoHeight;
}
if (!tvguideConfig.hideEpgImages) {
if (imgLoader.LoadEPGImage(event->EventID())) {
cImage epgImage = imgLoader.GetImage();
int epgImageX = header->Width() - 30 - tvguideConfig.epgImageWidth;
int epgImageY = (header->Height() - 10 - tvguideConfig.epgImageHeight) / 2;
header->DrawRectangle(cRect(epgImageX-2, epgImageY-2, tvguideConfig.epgImageWidth + 4, tvguideConfig.epgImageHeight + 4), theme.Color(clrBorder));
header->DrawImage(cPoint(epgImageX, epgImageY), epgImage);
}
}
header->DrawText(cPoint(20, offset), event->Title(), theme.Color(clrFont), clrTransparent, tvguideConfig.FontDetailHeader);
cString datetime = cString::sprintf("%s, %s - %s (%d min)", *event->GetDateString(), *event->GetTimeString(), *event->GetEndTimeString(), event->Duration()/60);
header->DrawText(cPoint(20, offset + lineHeight), *datetime, theme.Color(clrFont), clrTransparent, tvguideConfig.FontDetailView);
header->DrawText(cPoint(20, offset + 2 * lineHeight), event->ShortText(), theme.Color(clrFont), clrTransparent, tvguideConfig.FontDetailView);
}
void cDetailView::drawContent() {
content->Fill(theme.Color(clrBorder));
content->DrawRectangle(cRect(2, 0, content->ViewPort().Width() - 2, content->DrawPort().Height()), theme.Color(clrBackground));
int textHeight = tvguideConfig.FontDetailView->Height();
int textLines = description.Lines();
for (int i=0; i<textLines; i++) {
content->DrawText(cPoint(20, 20 + i*textHeight), description.GetLine(i), theme.Color(clrFont), clrTransparent, tvguideConfig.FontDetailView);
}
}
void cDetailView::drawScrollbar() {
scrollBar->Fill(theme.Color(clrBorder));
double scrollBarOffset = 0.0;
if (contentScrollable) {
heightScrollbar = ( (double)scrollBar->ViewPort().Height() ) / (double)heightContent * ( (double)scrollBar->ViewPort().Height() );
scrollBarOffset = (-1.0)*(double)content->DrawPort().Point().Y() / (double)(content->DrawPort().Height() - (tvguideConfig.osdHeight-2*borderWidth-headerHeight));
scrollBarOffset *= ( (double)scrollBar->ViewPort().Height()-7.0 - heightScrollbar);
scrollBarOffset++;
} else {
heightScrollbar = scrollBar->ViewPort().Height();
}
scrollBar->DrawRectangle(cRect(3,0,scrollBar->ViewPort().Width()-6, scrollBar->ViewPort().Height()), theme.Color(clrBackground));
if (imgScrollBar == NULL) {
imgScrollBar = createScrollbar(scrollBar->ViewPort().Width()-10, heightScrollbar, theme.Color(clrHighlight), theme.Color(clrHighlightBlending));
}
scrollBar->DrawImage(cPoint(5, 2 + scrollBarOffset), *imgScrollBar);
}
void cDetailView::scrollUp() {
if (contentScrollable) {
int newDrawportHeight = content->DrawPort().Point().Y() + tvguideConfig.FontDetailView->Height();
content->SetDrawPortPoint(cPoint(0, min(newDrawportHeight,0)));
drawScrollbar();
}
}
void cDetailView::scrollDown() {
if (contentScrollable) {
int newDrawportHeight = content->DrawPort().Point().Y() - tvguideConfig.FontDetailView->Height();
int maxDrawportHeight = (content->DrawPort().Height() - (tvguideConfig.osdHeight-2*borderWidth-headerHeight));
content->SetDrawPortPoint(cPoint(0, max(newDrawportHeight,(-1)*maxDrawportHeight)));
drawScrollbar();
}
}
cImage *cDetailView::createScrollbar(int width, int height, tColor clrBgr, tColor clrBlend) {
cImage *image = new cImage(cSize(width, height));
image->Fill(clrBgr);
if (tvguideConfig.useBlending) {
int numSteps = 64;
int alphaStep = 0x03;
if (height < 30)
return image;
else if (height < 100) {
numSteps = 32;
alphaStep = 0x06;
}
int stepY = 0.5*height / numSteps;
if (stepY == 0)
stepY = 1;
int alpha = 0x40;
tColor clr;
for (int i = 0; i<numSteps; i++) {
clr = AlphaBlend(clrBgr, clrBlend, alpha);
for (int y = i*stepY; y < (i+1)*stepY; y++) {
for (int x=0; x<width; x++) {
image->SetPixel(cPoint(x,y), clr);
}
}
alpha += alphaStep;
}
}
return image;
}
void cDetailView::Action(void) {
drawHeader();
drawContent();
drawScrollbar();
uint64_t Start = cTimeMs::Now();
while (true) {
uint64_t Now = cTimeMs::Now();
cPixmap::Lock();
double t = min(double(Now - Start) / FadeTime, 1.0);
int Alpha = t * ALPHA_OPAQUE;
header->SetAlpha(Alpha);
content->SetAlpha(Alpha);
scrollBar->SetAlpha(Alpha);
footer->SetAlpha(Alpha);
osdManager.flush();
cPixmap::Unlock();
int Delta = cTimeMs::Now() - Now;
if (Delta < FrameTime)
cCondWait::SleepMs(FrameTime - Delta);
if ((Now - Start) > FadeTime)
break;
}
}

39
detailview.h Normal file
View File

@ -0,0 +1,39 @@
#ifndef __TVGUIDE_DETAILVIEW_H
#define __TVGUIDE_DETAILVIEW_H
// --- cDetailView -------------------------------------------------------------
class cEpgGrid;
class cDetailView : public cThread {
private:
cEpgGrid *grid;
cStyledPixmap *header;
cPixmap *content;
cPixmap *scrollBar;
cPixmap *footer;
const cEvent *event;
cImage *imgScrollBar;
int FrameTime;
int FadeTime;
cTextWrapper description;
int borderWidth;
int headerHeight;
bool setContentDrawportHeight();
int heightContent;
int heightScrollbar;
bool contentScrollable;
virtual void Action(void);
void drawHeader();
void drawContent();
void drawScrollbar();
cImage *createScrollbar(int width, int height, tColor clrBgr, tColor clrBlend);
public:
cDetailView(cEpgGrid *grid);
virtual ~cDetailView(void);
void createPixmaps();
void scrollUp();
void scrollDown();
};
#endif //__TVGUIDE_DETAILVIEW_H

146
epggrid.c Normal file
View File

@ -0,0 +1,146 @@
#include "channelcolumn.h"
#include "epggrid.h"
cEpgGrid::cEpgGrid(cChannelColumn *c, const cEvent *event) {
this->event = event;
this->column = c;
text = new cTextWrapper();
extText = new cTextWrapper();
dirty = true;
active = false;
viewportHeight = 0;
borderWidth = 10;
hasTimer = false;
if (column->hasTimer)
hasTimer = event->HasTimer();
}
cEpgGrid::~cEpgGrid(void) {
delete text;
delete extText;
}
void cEpgGrid::SetViewportHeight() {
int viewportHeightOld = viewportHeight;
if ( column->myTime->GetStart() > event->StartTime() ) {
viewportHeight = (min(event->EndTime(), column->myTime->GetStop()) - column->myTime->GetStart()) /60;
} else if ( column->myTime->GetStop() < event->EndTime() ) {
viewportHeight = (column->myTime->GetStop() - event->StartTime()) /60;
} else {
viewportHeight = event->Duration() / 60;
}
if (viewportHeight != viewportHeightOld)
dirty = true;
}
void cEpgGrid::PositionPixmap() {
int x0 = column->getX();
int y0 = tvguideConfig.headerHeight;
if ( column->myTime->GetStart() < event->StartTime() ) {
y0 += (event->StartTime() - column->myTime->GetStart())/60*tvguideConfig.minuteHeight;
}
if (!pixmap) {
caller = cString::sprintf("epggrid %s %s", column->channel->Name(), event->Title());
pixmap = osdManager.requestPixmap(-1, cRect(x0, y0, tvguideConfig.colWidth, viewportHeight * tvguideConfig.minuteHeight),
cRect(0, 0, tvguideConfig.colWidth, event->Duration()/60*tvguideConfig.minuteHeight), *caller);
} else {
pixmap->SetViewPort(cRect(x0, y0, tvguideConfig.colWidth, viewportHeight * tvguideConfig.minuteHeight));
}
}
void cEpgGrid::setBackground() {
if (active) {
color = theme.Color(clrHighlight);
colorBlending = theme.Color(clrHighlightBlending);
} else {
if (isColor1) {
color = theme.Color(clrGrid1);
colorBlending = theme.Color(clrGrid1Blending);
} else {
color = theme.Color(clrGrid2);
colorBlending = theme.Color(clrGrid2Blending);
}
}
}
void cEpgGrid::Draw() {
if (!pixmap) {
return;
}
if (dirty) {
setBackground();
drawBackground();
drawText();
if (hasTimer)
DrawRecIcon();
drawBorder();
pixmap->SetLayer(1);
dirty = false;
}
}
void cEpgGrid::DrawRecIcon() {
cString recIconText("REC");
int width = tvguideConfig.FontGrid->Width(*recIconText)+2*borderWidth;
int height = tvguideConfig.FontGrid->Height()+10;
pixmap->DrawRectangle( cRect(pixmap->ViewPort().Width() - width - borderWidth, pixmap->ViewPort().Height() - height - borderWidth, width, height), theme.Color(clrButtonRed));
pixmap->DrawText(cPoint(pixmap->ViewPort().Width() - width, pixmap->ViewPort().Height() - height - borderWidth/2), *recIconText, theme.Color(clrFont), clrTransparent, tvguideConfig.FontGrid);
}
void cEpgGrid::setText() {
cString strText;
strText = cString::sprintf("%s - %s:\n%s", *(event->GetTimeString()), *(event->GetEndTimeString()), event->Title());
text->Set(*(strText), tvguideConfig.FontGrid, tvguideConfig.colWidth-2*borderWidth);
extText->Set(event->ShortText(), tvguideConfig.FontGridSmall, tvguideConfig.colWidth-2*borderWidth);
}
void cEpgGrid::drawText() {
int gridHeight = pixmap->ViewPort().Height();
if (gridHeight/tvguideConfig.minuteHeight < 6)
return;
int textHeight = tvguideConfig.FontGrid->Height();
int textLines = text->Lines();
for (int i=0; i<textLines; i++) {
pixmap->DrawText(cPoint(borderWidth, borderWidth + i*textHeight), text->GetLine(i), theme.Color(clrFont), clrTransparent, tvguideConfig.FontGrid);
}
int extTextLines = extText->Lines();
int offset = (textLines+1)*textHeight - 0.5*textHeight;
textHeight = tvguideConfig.FontGridSmall->Height();
if ((pixmap->ViewPort().Height()-textHeight-10) > offset) {
for (int i=0; i<extTextLines; i++) {
pixmap->DrawText(cPoint(borderWidth, borderWidth + offset + i*textHeight), extText->GetLine(i), theme.Color(clrFont), clrTransparent, tvguideConfig.FontGridSmall);
}
}
}
int cEpgGrid::calcOverlap(cEpgGrid *neighbor) {
int overlap = 0;
if (intersects(neighbor)) {
if ((event->StartTime() <= neighbor->StartTime()) && (event->EndTime() <= neighbor->EndTime())) {
overlap = event->EndTime() - neighbor->StartTime();
} else if ((event->StartTime() >= neighbor->StartTime()) && (event->EndTime() >= neighbor->EndTime())) {
overlap = neighbor->EndTime() - event->StartTime();
} else if ((event->StartTime() >= neighbor->StartTime()) && (event->EndTime() <= neighbor->EndTime())) {
overlap = event->Duration();
} else if ((event->StartTime() <= neighbor->StartTime()) && (event->EndTime() >= neighbor->EndTime())) {
overlap = neighbor->EndTime() - neighbor->StartTime();
}
}
return overlap;
}
bool cEpgGrid::intersects(cEpgGrid *neighbor) {
return ! ( (neighbor->EndTime() <= event->StartTime()) || (neighbor->StartTime() >= event->EndTime()) );
}
bool cEpgGrid::isActiveInitial(time_t t) {
if ((event->StartTime() < t) && (event->EndTime() > t))
return true;
else
return false;
}
void cEpgGrid::debug() {
esyslog("tvguide Grid: %s, %s, viewportHeight: %d, Duration: %d", *(event->GetTimeString()), event->Title(), viewportHeight, event->Duration()/60);
}

44
epggrid.h Normal file
View File

@ -0,0 +1,44 @@
#ifndef __TVGUIDE_EPGGRID_H
#define __TVGUIDE_EPGGRID_H
// --- cEpgGrid -------------------------------------------------------------
class cEpgGrid : public cListObject, public cStyledPixmap {
private:
const cEvent *event;
cTextWrapper *text;
cTextWrapper *extText;
int viewportHeight;
int borderWidth;
void drawText();
void setBackground();
bool isColor1;
bool active;
bool dirty;
bool intersects(cEpgGrid *neighbor);
bool hasTimer;
void DrawRecIcon();
public:
cEpgGrid(cChannelColumn *c, const cEvent *event);
virtual ~cEpgGrid(void);
cChannelColumn *column;
void SetViewportHeight();
void PositionPixmap();
void setText();
void Draw();
void SetDirty() {dirty = true;};
void SetActive() {dirty = true; active = true;};
void SetInActive() {dirty = true; active = false;};
void SetColor(bool color) {isColor1 = color;};
bool IsColor1() {return isColor1;};
int GetViewportHeight() {return viewportHeight;};
const cEvent *GetEvent() {return event;};
bool isActiveInitial(time_t t);
time_t StartTime() { return event->StartTime(); };
time_t EndTime() { return event->EndTime(); };
int calcOverlap(cEpgGrid *neighbor);
void setTimer() {hasTimer = true;};
void debug();
};
#endif //__TVGUIDE_EPGGRID_H

59
footer.c Normal file
View File

@ -0,0 +1,59 @@
#include "footer.h"
cFooter::cFooter() {
int buttonHeight= tvguideConfig.footerHeight - 20;
textY = (buttonHeight - tvguideConfig.FontButton->Height())/2;
int distanceX = 20;
buttonWidth = (tvguideConfig.osdWidth - tvguideConfig.timeColWidth-5*distanceX)/4;
int startX = tvguideConfig.timeColWidth + distanceX;
int Y = tvguideConfig.osdHeight - tvguideConfig.footerHeight + (tvguideConfig.footerHeight - buttonHeight)/2;
buttonRed = new cStyledPixmap(osdManager.requestPixmap(3, cRect(startX, Y, buttonWidth, buttonHeight), cRect::Null, "btnRed"), "btnRed");
buttonGreen = new cStyledPixmap(osdManager.requestPixmap(3, cRect(startX + buttonWidth + distanceX, Y, buttonWidth, buttonHeight), cRect::Null, "btnGreen"), "btnGreen");
buttonYellow = new cStyledPixmap(osdManager.requestPixmap(3, cRect(startX + 2*(buttonWidth + distanceX), Y, buttonWidth, buttonHeight), cRect::Null, "btnYellow"), "btnYellow");
buttonBlue = new cStyledPixmap(osdManager.requestPixmap(3, cRect(startX + 3*(buttonWidth + distanceX), Y, buttonWidth, buttonHeight), cRect::Null, "btnBlue"), "btnBlue");
}
cFooter::~cFooter(void) {
delete buttonRed;
delete buttonGreen;
delete buttonYellow;
delete buttonBlue;
}
void cFooter::drawRedButton() {
buttonRed->setColor(theme.Color(clrButtonRed), theme.Color(clrButtonRedBlending));
buttonRed->drawBackground();
buttonRed->drawBorder();
cString text(tr("Set Timer"));
int width = tvguideConfig.FontButton->Width(*(text));
buttonRed->DrawText(cPoint((buttonWidth-width)/2, textY), *(text), theme.Color(clrFontButtons), clrTransparent, tvguideConfig.FontButton);
}
void cFooter::drawGreenButton() {
buttonGreen->setColor(theme.Color(clrButtonGreen), theme.Color(clrButtonGreenBlending));
buttonGreen->drawBackground();
buttonGreen->drawBorder();
cString text = cString::sprintf("%d %s", tvguideConfig.jumpChannels, tr("Channels back"));
int width = tvguideConfig.FontButton->Width(*text);
buttonGreen->DrawText(cPoint((buttonWidth-width)/2, textY), *text, theme.Color(clrFontButtons), clrTransparent, tvguideConfig.FontButton);
}
void cFooter::drawYellowButton() {
buttonYellow->setColor(theme.Color(clrButtonYellow), theme.Color(clrButtonYellowBlending));
buttonYellow->drawBackground();
buttonYellow->drawBorder();
cString text = cString::sprintf("%d %s", tvguideConfig.jumpChannels, tr("Channels forward"));
int width = tvguideConfig.FontButton->Width(*text);
buttonYellow->DrawText(cPoint((buttonWidth-width)/2, textY), *text, theme.Color(clrFontButtons), clrTransparent, tvguideConfig.FontButton);
}
void cFooter::drawBlueButton() {
buttonBlue->setColor(theme.Color(clrButtonBlue), theme.Color(clrButtonBlueBlending));
buttonBlue->drawBackground();
buttonBlue->drawBorder();
cString text(tr("Switch to Channel"));
int width = tvguideConfig.FontButton->Width(*(text));
buttonBlue->DrawText(cPoint((buttonWidth-width)/2, textY), *(text), theme.Color(clrFontButtons), clrTransparent, tvguideConfig.FontButton);
}

23
footer.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef __TVGUIDE_FOOTER_H
#define __TVGUIDE_FOOTER_H
// --- cFooter -------------------------------------------------------------
class cFooter {
private:
cStyledPixmap *buttonRed;
cStyledPixmap *buttonGreen;
cStyledPixmap *buttonYellow;
cStyledPixmap *buttonBlue;
int textY;
int buttonWidth;
public:
cFooter();
virtual ~cFooter(void);
void drawRedButton();
void drawGreenButton();
void drawYellowButton();
void drawBlueButton();
};
#endif //__TVGUIDE_FOOTER_H

78
imageloader.c Normal file
View File

@ -0,0 +1,78 @@
#include "imageloader.h"
#include <math.h>
using namespace Magick;
cImageLoader::cImageLoader() {
}
cImageLoader::~cImageLoader() {
}
bool cImageLoader::LoadLogo(const char *logo)
{
try
{
int width = tvguideConfig.logoWidth;
int height = tvguideConfig.logoHeight;
cString extension;
if (tvguideConfig.logoExtension == 0) {
extension = "png";
} else if (tvguideConfig.logoExtension == 1) {
extension = "jpg";
}
cString Filename = cString::sprintf("%s%s.%s", *tvguideConfig.logoPath, logo, *extension);
osdImage.read(*Filename);
if (height != 0 || width != 0) {
osdImage.sample( Geometry(width, height));
}
return true;
}
catch (...)
{
return false;
}
}
bool cImageLoader::LoadEPGImage(int eventID)
{
try
{
int width = tvguideConfig.epgImageWidth;
int height = tvguideConfig.epgImageHeight;
cString Filename = cString::sprintf("%s%d.jpg", *tvguideConfig.epgImagePath, eventID);
osdImage.read(*Filename);
if (height != 0 || width != 0)
osdImage.sample( Geometry(width, height));
return true;
}
catch (...)
{
return false;
}
}
cImage cImageLoader::GetImage()
{
int w, h;
w = osdImage.columns();
h = osdImage.rows();
cImage image (cSize(w, h));
const PixelPacket *pixels = osdImage.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;
}

23
imageloader.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef _TVGUIDE_IMAGELOADER_H
#define _TVGUIDE_IMAGELOADER_H
#define X_DISPLAY_MISSING
#include <vdr/osd.h>
#include <vdr/skins.h>
#include <Magick++.h>
using namespace Magick;
class cImageLoader {
public:
cImageLoader();
~cImageLoader();
cImage GetImage();
bool LoadLogo(const char *logo);
bool LoadEPGImage(int eventID);
private:
Image osdImage;
};
#endif //_TVGUIDE_IMAGELOADER_H

114
messagebox.c Normal file
View File

@ -0,0 +1,114 @@
#include "messagebox.h"
cMessageBoxThread::cMessageBoxThread(cPixmap *content, int displayTime) {
this->content = content;
FrameTime = 30; // ms
FadeTime = 200; // ms
this->displayTime = displayTime;
}
cMessageBoxThread::~cMessageBoxThread(void) {
Cancel(0);
}
void cMessageBoxThread::Action(void) {
uint64_t Start = cTimeMs::Now();
while (Running()) {
uint64_t Now = cTimeMs::Now();
cPixmap::Lock();
double t = min(double(Now - Start) / FadeTime, 1.0);
int Alpha = t * ALPHA_OPAQUE;
if (content) {
content->SetAlpha(Alpha);
osdManager.flush();
}
cPixmap::Unlock();
int Delta = cTimeMs::Now() - Now;
if (Delta < FrameTime)
cCondWait::SleepMs(FrameTime - Delta);
if ((Now - Start) > FadeTime)
break;
}
cCondWait::SleepMs(displayTime - 2*FadeTime);
Start = cTimeMs::Now();
while (Running()) {
uint64_t Now = cTimeMs::Now();
cPixmap::Lock();
double t = min(double(Now - Start) / FadeTime, 1.0);
int Alpha = (1-t) * ALPHA_OPAQUE;
if (content) {
content->SetAlpha(Alpha);
osdManager.flush();
}
cPixmap::Unlock();
int Delta = cTimeMs::Now() - Now;
if (Delta < FrameTime)
cCondWait::SleepMs(FrameTime - Delta);
if ((Now - Start) > FadeTime)
break;
}
osdManager.flush();
}
//--cMessageBox-------------------------------------------------------------
cMutex cMessageBox::mutex;
cMessageBoxThread *cMessageBox::msgboxThread = NULL;
cPixmap *cMessageBox::content = NULL;
bool cMessageBox::Start(int displayTime, cString msg) {
cMutexLock MutexLock(&mutex);
int width = (tvguideConfig.osdWidth - 600)/2;
if (!content) {
int height = 400;
content = osdManager.requestPixmap(5, cRect((tvguideConfig.osdWidth - width)/2,
(tvguideConfig.osdHeight- height)/2,
width, height),
cRect::Null, "msgbox");
}
if (msgboxThread) {
delete msgboxThread;
msgboxThread = NULL;
}
if (!msgboxThread) {
msgboxThread = new cMessageBoxThread(content, displayTime);
cTextWrapper message;
message.Set(msg, tvguideConfig.FontMessageBox, width - 40);
int textHeight = tvguideConfig.FontMessageBox->Height();
int textLines = message.Lines();
int height = textLines * (textHeight+20);
cPixmap::Lock();
content->SetViewPort(cRect((tvguideConfig.osdWidth - width)/2,(tvguideConfig.osdHeight- height)/2, width, height));
content->SetAlpha(0);
content->Fill(theme.Color(clrBorder));
content->DrawRectangle(cRect(2,2,width-4, height-4), theme.Color(clrBackground));
int textWidth = 0;
for (int i=0; i<textLines; i++) {
textWidth = tvguideConfig.FontMessageBox->Width(message.GetLine(i));
content->DrawText(cPoint((width - textWidth)/2, 20 + i*textHeight), message.GetLine(i), theme.Color(clrFont), clrTransparent, tvguideConfig.FontMessageBox);
}
cPixmap::Unlock();
msgboxThread->Start();
return true;
}
return false;
}
void cMessageBox::Stop(void) {
cMutexLock MutexLock(&mutex);
if (msgboxThread) {
delete msgboxThread;
msgboxThread = NULL;
}
}
void cMessageBox::Destroy(void) {
cMutexLock MutexLock(&mutex);
if (msgboxThread) {
delete msgboxThread;
msgboxThread = NULL;
}
if (content) {
osdManager.releasePixmap(content, "msgboxDestroy");
content = NULL;
}
}

31
messagebox.h Normal file
View File

@ -0,0 +1,31 @@
#ifndef __TVGUIDE_MESSAGEBOX_H
#define __TVGUIDE_MESSAGEBOX_H
class cMessageBoxThreadPool;
// --- cMessageBox -------------------------------------------------------------
class cMessageBoxThread : public cThread {
private:
cPixmap *content;
int FadeTime;
int FrameTime;
int displayTime;
virtual void Action(void);
public:
cMessageBoxThread(cPixmap *content, int displayTime);
virtual ~cMessageBoxThread(void);
};
class cMessageBox {
private:
static cMutex mutex;
static cMessageBoxThread *msgboxThread;
static cPixmap *content;
public:
static bool Start(int displayTime, cString msg);
static void Stop(void);
static void Destroy(void);
};
#endif //__TVGUIDE_MESSAGEBOX_H

52
osdmanager.c Normal file
View File

@ -0,0 +1,52 @@
#ifndef __TVGUIDE_OSDMANAGER_H
#define __TVGUIDE_OSDMANAGER_H
class cOsdManager {
private:
cOsd *osd;
int activePixmaps;
public:
cOsdManager(void);
bool setOsd();
void setBackground();
void flush() {osd->Flush();};
cPixmap *requestPixmap(int Layer, const cRect &ViewPort, const cRect &DrawPort = cRect::Null, const char *caller = "anonymous");
void releasePixmap(cPixmap *pixmap, const char *caller = "anonymous");
void deleteOsd() {delete osd;};
int Width() { return osd->Width(); };
int Height() { return osd->Height(); };
};
#endif //__TVGUIDE_OSDMANAGER_H
cOsdManager::cOsdManager(void) {
activePixmaps = 0;
}
bool cOsdManager::setOsd() {
osd = cOsdProvider::NewOsd(cOsd::OsdLeft(), cOsd::OsdTop());
if (osd) {
tArea Area = { 0, 0, cOsd::OsdWidth(), cOsd::OsdHeight(), 32 };
if (osd->SetAreas(&Area, 1) == oeOk) {
return true;
}
}
return false;
}
void cOsdManager::setBackground() {
osd->DrawRectangle(0, 0, cOsd::OsdWidth(), cOsd::OsdHeight(), theme.Color(clrBackgroundOSD));
}
cPixmap *cOsdManager::requestPixmap(int Layer, const cRect &ViewPort, const cRect &DrawPort, const char *caller) {
if (activePixmaps >= 64)
return NULL;
activePixmaps++;
//esyslog("tvguide: Pixmap angefordert von %s, verwendet: %d", caller, activePixmaps);
return osd->CreatePixmap(Layer, ViewPort, DrawPort);
}
void cOsdManager::releasePixmap(cPixmap *pixmap, const char *caller) {
activePixmaps--;
//esyslog("tvguide: Pixmap geloescht von %s, verwendet: %d", caller, activePixmaps);
osd->DestroyPixmap(pixmap);
}

139
po/de_DE.po Executable file
View File

@ -0,0 +1,139 @@
# VDR plugin language source file.
msgid ""
msgstr ""
"Project-Id-Version: vdr-tvguide 0.0.1\n"
"Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2012-12-27 15:27+0100\n"
"PO-Revision-Date: 2012-08-25 17:49+0200\n"
"Last-Translator: Horst\n"
"Language-Team: \n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
msgid "Set Timer"
msgstr "Aufnehmen"
msgid "Channels back"
msgstr "Kanäle zurück"
msgid "Channels forward"
msgstr "Kanäle vor"
msgid "Switch to Channel"
msgstr "Umschalten"
msgid "General Settings"
msgstr "Allgemeine Einstellungen"
msgid "Screen Presentation"
msgstr "Anzeigeoptionen"
msgid "Fonts and Fontsizes"
msgstr "Schriften und Schriftgrößen"
msgid "Number of Channels / Columns"
msgstr "Anzahl der Kanäle bzw. Spalten"
msgid "Channels to Jump (Keys Green / Yellow)"
msgstr "Kanalsprung (Tasten Grün / Gelb)"
msgid "Time to display vertically in minutes"
msgstr "Vertikal angezeigte Zeit (in Minuten)"
msgid "Big Step (Keys 1 / 3) in hours"
msgstr "Großer Sprung (Tasten 1 / 3) in Stunden"
msgid "Huge Step (Keys 4 / 6) in hours"
msgstr "Sehr großer Sprung (Tasten 4 / 6) in Stunden"
msgid "Time Format (12h/24h)"
msgstr "Zeitformat (12h/24h)"
msgid "Theme"
msgstr "Theme"
msgid "Use color gradients"
msgstr "Farbverläufe verwenden"
msgid "Rounded Corners"
msgstr "Abgerundete Ecken"
msgid "Width of Timeline"
msgstr "Breite der Zeitleiste"
msgid "Height of Header"
msgstr "Höhe des Headers"
msgid "Height of Footer"
msgstr "Höhe des Footers"
msgid "Show Channel Logos"
msgstr "Kanallogos anzeigen"
msgid "Logo Path used"
msgstr "Benutzer Pfad für Kanallogos"
msgid "Logo Extension"
msgstr "Logo Extension"
msgid "Logo width"
msgstr "Breite der Logos"
msgid "Logo height"
msgstr "Höhe der Logos"
msgid "Show EPG Images"
msgstr "EPG Bilder anzeigen"
msgid "EPG Images Path used"
msgstr "benutzer EPG Bilder Pfad"
msgid "EPG Image width"
msgstr "Breite der EPG Bilder"
msgid "EPG Image height"
msgstr "Höhe der EPG Bilder"
msgid "Font"
msgstr "Schriftart"
msgid "Channel Header Font Size"
msgstr "Kanal Header Schriftgröße"
msgid "Grid Font Size"
msgstr "Grid Schriftgröße"
msgid "Grid Font Small Size"
msgstr "Grid kleine Schriftgröße"
msgid "Timeline Weekday Font Size"
msgstr "Zeitleiste Wochentag Schriftgröße"
msgid "Timeline Date Font Size"
msgstr "Zeitleiste Datum Schriftgröße"
msgid "Timeline Time Font Size"
msgstr "Zeitleiste Zeit Schriftgröße"
msgid "Button Font Size"
msgstr "Button Schriftgröße"
msgid "Detail EPG View Font Size"
msgstr "Detailierte EPG Ansicht Schriftgröße"
msgid "Detail EPG View Header Font Size"
msgstr "Detailierte EPG Ansicht Header Schriftgröße"
msgid "Message Font Size"
msgstr "Nachrichten Schriftgröße"
msgid "Message Large Font Size"
msgstr "Nachrichten große Schriftgröße"
msgid "Timer not set! There is already a timer for this item."
msgstr "Timer wurde nicht gesetzt! Es existiert bereits ein Timer für diese Sendung"
msgid "Timer set"
msgstr "Timer gesetzt"

209
setup.c Normal file
View File

@ -0,0 +1,209 @@
#include "setup.h"
cTvguideSetup::cTvguideSetup() {
tmpTvguideConfig = tvguideConfig;
Setup();
}
cTvguideSetup::~cTvguideSetup() {
}
void cTvguideSetup::Setup(void) {
int currentItem = Current();
Clear();
Add(new cOsdItem(tr("General Settings")));
Add(new cOsdItem(tr("Screen Presentation")));
Add(new cOsdItem(tr("Fonts and Fontsizes")));
SetCurrent(Get(currentItem));
Display();
}
eOSState cTvguideSetup::ProcessKey(eKeys Key) {
bool hadSubMenu = HasSubMenu();
eOSState state = cMenuSetupPage::ProcessKey(Key);
if (hadSubMenu && Key == kOk)
Store();
if (!hadSubMenu && (state == osUnknown || Key == kOk)) {
if ((Key == kOk && !hadSubMenu)) {
const char* ItemText = Get(Current())->Text();
if (strcmp(ItemText, tr("General Settings")) == 0)
state = AddSubMenu(new cMenuSetupGeneral(&tmpTvguideConfig));
if (strcmp(ItemText, tr("Screen Presentation")) == 0)
state = AddSubMenu(new cMenuSetupScreenLayout(&tmpTvguideConfig));
if (strcmp(ItemText, tr("Fonts and Fontsizes")) == 0)
state = AddSubMenu(new cMenuSetupFont(&tmpTvguideConfig));
}
}
return state;
}
void cTvguideSetup::Store(void) {
tvguideConfig = tmpTvguideConfig;
SetupStore("themeIndex", tvguideConfig.themeIndex);
SetupStore("useBlending", tvguideConfig.useBlending);
SetupStore("roundedCorners", tvguideConfig.roundedCorners);
SetupStore("timeFormat", tvguideConfig.timeFormat);
SetupStore("channelCols", tvguideConfig.channelCols);
SetupStore("displayTime", tvguideConfig.displayTime);
SetupStore("bigStepHours", tvguideConfig.bigStepHours);
SetupStore("hugeStepHours", tvguideConfig.hugeStepHours);
SetupStore("jumpChannels", tvguideConfig.jumpChannels);
SetupStore("hideChannelLogos", tvguideConfig.hideChannelLogos);
SetupStore("logoExtension", tvguideConfig.logoExtension);
SetupStore("logoWidth", tvguideConfig.logoWidth);
SetupStore("logoHeight", tvguideConfig.logoHeight);
SetupStore("hideEpgImages", tvguideConfig.hideEpgImages);
SetupStore("epgImageWidth", tvguideConfig.epgImageWidth);
SetupStore("epgImageHeight", tvguideConfig.epgImageHeight);
SetupStore("epgImageHeight", tvguideConfig.epgImageHeight);
SetupStore("timeColWidth", tvguideConfig.timeColWidth);
SetupStore("headerHeight", tvguideConfig.headerHeight);
SetupStore("footerHeight", tvguideConfig.footerHeight);
SetupStore("fontIndex", tvguideConfig.fontIndex);
SetupStore("fontHeaderSize", tvguideConfig.fontHeaderSize);
SetupStore("fontGridSize", tvguideConfig.fontGridSize);
SetupStore("fontGridSmallSize", tvguideConfig.fontGridSmallSize);
SetupStore("fontTimeLineWeekdaySize", tvguideConfig.fontTimeLineWeekdaySize);
SetupStore("fontTimeLineDateSize", tvguideConfig.fontTimeLineDateSize);
SetupStore("fontTimeLineTimeSize", tvguideConfig.fontTimeLineTimeSize);
SetupStore("fontButtonSize", tvguideConfig.fontButtonSize);
SetupStore("fontDetailViewSize", tvguideConfig.fontDetailViewSize);
SetupStore("fontDetailHeaderSize", tvguideConfig.fontDetailHeaderSize);
SetupStore("fontMessageBoxSize", tvguideConfig.fontMessageBoxSize);
SetupStore("fontMessageBoxLargeSize", tvguideConfig.fontMessageBoxLargeSize);
}
cMenuSetupSubMenu::cMenuSetupSubMenu(const char* Title, cTvguideConfig* data) : cOsdMenu(Title, 30) {
tmpTvguideConfig = data;
}
cOsdItem *cMenuSetupSubMenu::InfoItem(const char *label, const char *value) {
cOsdItem *item;
item = new cOsdItem(cString::sprintf("%s: %s", label, value));
item->SetSelectable(false);
return item;
}
eOSState cMenuSetupSubMenu::ProcessKey(eKeys Key) {
eOSState state = cOsdMenu::ProcessKey(Key);
if (state == osUnknown) {
switch (Key) {
case kOk:
return osBack;
default:
break;
}
}
return state;
}
//------------------------------------------------------------------------------------------------------------------
cMenuSetupGeneral::cMenuSetupGeneral(cTvguideConfig* data) : cMenuSetupSubMenu(tr("General Settings"), data) {
timeFormatItems[0] = "12h";
timeFormatItems[1] = "24h";
Set();
}
void cMenuSetupGeneral::Set(void) {
int currentItem = Current();
Clear();
Add(new cMenuEditIntItem(tr("Number of Channels / Columns"), &tmpTvguideConfig->channelCols, 3, 8));
Add(new cMenuEditIntItem(tr("Channels to Jump (Keys Green / Yellow)"), &tmpTvguideConfig->jumpChannels, 2, 30));
Add(new cMenuEditIntItem(tr("Time to display vertically in minutes"), &tmpTvguideConfig->displayTime, 120, 320));
Add(new cMenuEditIntItem(tr("Big Step (Keys 1 / 3) in hours"), &tmpTvguideConfig->bigStepHours, 1, 12));
Add(new cMenuEditIntItem(tr("Huge Step (Keys 4 / 6) in hours"), &tmpTvguideConfig->hugeStepHours, 13, 48));
Add(new cMenuEditStraItem(tr("Time Format (12h/24h)"), &tmpTvguideConfig->timeFormat, 2, timeFormatItems));
SetCurrent(Get(currentItem));
Display();
}
//------------------------------------------------------------------------------------------------------------------
cMenuSetupScreenLayout::cMenuSetupScreenLayout(cTvguideConfig* data) : cMenuSetupSubMenu(tr("Screen Presentation"), data) {
themes.Load(*cString("tvguide"));
hideChannelLogosItems[0] = trVDR("yes");
hideChannelLogosItems[1] = trVDR("no");
logoExtensionItems[0] = "png";
logoExtensionItems[1] = "jpg";
Set();
}
void cMenuSetupScreenLayout::Set(void) {
int currentItem = Current();
Clear();
if (themes.NumThemes())
Add(new cMenuEditStraItem(tr("Theme"), &tmpTvguideConfig->themeIndex, themes.NumThemes(), themes.Descriptions()));
Add(new cMenuEditBoolItem(tr("Use color gradients"), &tmpTvguideConfig->useBlending));
Add(new cMenuEditBoolItem(tr("Rounded Corners"), &tmpTvguideConfig->roundedCorners));
Add(new cMenuEditIntItem(tr("Width of Timeline"), &tmpTvguideConfig->timeColWidth, 50, 300));
Add(new cMenuEditIntItem(tr("Height of Header"), &tmpTvguideConfig->headerHeight, 50, 300));
Add(new cMenuEditIntItem(tr("Height of Footer"), &tmpTvguideConfig->footerHeight, 50, 300));
const char *indent = " ";
Add(new cMenuEditStraItem(tr("Show Channel Logos"), &tmpTvguideConfig->hideChannelLogos, 2, hideChannelLogosItems));
if (!tmpTvguideConfig->hideChannelLogos) {
Add(InfoItem(tr("Logo Path used"), *tvguideConfig.logoPath));
Add(new cMenuEditStraItem(*cString::sprintf("%s%s", indent, tr("Logo Extension")), &tmpTvguideConfig->logoExtension, 2, logoExtensionItems));
Add(new cMenuEditIntItem(*cString::sprintf("%s%s", indent, tr("Logo width")), &tmpTvguideConfig->logoWidth, 0, 350));
Add(new cMenuEditIntItem(*cString::sprintf("%s%s", indent, tr("Logo height")), &tmpTvguideConfig->logoHeight, 0, 250));
}
Add(new cMenuEditStraItem(tr("Show EPG Images"), &tmpTvguideConfig->hideEpgImages, 2, hideChannelLogosItems));
if (!tmpTvguideConfig->hideEpgImages) {
Add(InfoItem(tr("EPG Images Path used"), *tvguideConfig.epgImagePath));
Add(new cMenuEditIntItem(*cString::sprintf("%s%s", indent, tr("EPG Image width")), &tmpTvguideConfig->epgImageWidth, 0, 800));
Add(new cMenuEditIntItem(*cString::sprintf("%s%s", indent, tr("EPG Image height")), &tmpTvguideConfig->epgImageHeight, 0, 800));
}
SetCurrent(Get(currentItem));
Display();
}
eOSState cMenuSetupScreenLayout::ProcessKey(eKeys Key) {
eOSState state = cOsdMenu::ProcessKey(Key);
if (Key == kOk) {
state = osBack;
} else if (Key != kNone) {
Set();
}
return state;
}
//------------------------------------------------------------------------------------------------------------------
cMenuSetupFont::cMenuSetupFont(cTvguideConfig* data) : cMenuSetupSubMenu(tr("Fonts and Fontsizes"), data) {
cFont::GetAvailableFontNames(&fontNames);
fontNames.Insert(strdup(tvguideConfig.fontNameDefault));
Set();
}
void cMenuSetupFont::Set(void) {
int currentItem = Current();
Clear();
Add(new cMenuEditStraItem(tr("Font"), &tmpTvguideConfig->fontIndex, fontNames.Size(), &fontNames[0]));
Add(new cMenuEditIntItem(tr("Channel Header Font Size"), &tmpTvguideConfig->fontHeaderSize, 10, 70));
Add(new cMenuEditIntItem(tr("Grid Font Size"), &tmpTvguideConfig->fontGridSize, 10, 70));
Add(new cMenuEditIntItem(tr("Grid Font Small Size"), &tmpTvguideConfig->fontGridSmallSize, 10, 70));
Add(new cMenuEditIntItem(tr("Timeline Weekday Font Size"), &tmpTvguideConfig->fontTimeLineWeekdaySize, 10, 70));
Add(new cMenuEditIntItem(tr("Timeline Date Font Size"), &tmpTvguideConfig->fontTimeLineDateSize, 10, 70));
Add(new cMenuEditIntItem(tr("Timeline Time Font Size"), &tmpTvguideConfig->fontTimeLineTimeSize, 10, 70));
Add(new cMenuEditIntItem(tr("Button Font Size"), &tmpTvguideConfig->fontButtonSize, 10, 70));
Add(new cMenuEditIntItem(tr("Detail EPG View Font Size"), &tmpTvguideConfig->fontDetailViewSize, 10, 70));
Add(new cMenuEditIntItem(tr("Detail EPG View Header Font Size"), &tmpTvguideConfig->fontDetailHeaderSize, 10, 70));
Add(new cMenuEditIntItem(tr("Message Font Size"), &tmpTvguideConfig->fontMessageBoxSize, 10, 70));
Add(new cMenuEditIntItem(tr("Message Large Font Size"), &tmpTvguideConfig->fontMessageBoxLargeSize, 10, 70));
SetCurrent(Get(currentItem));
Display();
}

54
setup.h Normal file
View File

@ -0,0 +1,54 @@
#ifndef __TVGUIDE_SETUP_H
#define __TVGUIDE_SETUP_H
class cTvguideSetup : public cMenuSetupPage {
public:
cTvguideSetup(void);
virtual ~cTvguideSetup();
private:
cTvguideConfig tmpTvguideConfig;
void Setup(void);
protected:
virtual eOSState ProcessKey(eKeys Key);
virtual void Store(void);
};
class cMenuSetupSubMenu : public cOsdMenu {
protected:
cTvguideConfig *tmpTvguideConfig;
virtual eOSState ProcessKey(eKeys Key);
virtual void Set(void) = 0;
cOsdItem *InfoItem(const char *label, const char *value);
public:
cMenuSetupSubMenu(const char *Title, cTvguideConfig *data);
};
class cMenuSetupGeneral : public cMenuSetupSubMenu {
protected:
const char * timeFormatItems[2];
void Set(void);
public:
cMenuSetupGeneral(cTvguideConfig *data);
};
class cMenuSetupScreenLayout : public cMenuSetupSubMenu {
protected:
virtual eOSState ProcessKey(eKeys Key);
cThemes themes;
const char * hideChannelLogosItems[2];
const char * logoExtensionItems[2];
void Set(void);
public:
cMenuSetupScreenLayout(cTvguideConfig *data);
};
class cMenuSetupFont : public cMenuSetupSubMenu {
protected:
cStringList fontNames;
void Set(void);
public:
cMenuSetupFont(cTvguideConfig *data);
};
#endif //__TVGUIDE_SETUP_H

125
styledpixmap.c Normal file
View File

@ -0,0 +1,125 @@
#include "styledpixmap.h"
cStyledPixmap::cStyledPixmap(void) {
pixmap = NULL;
caller = NULL;
}
cStyledPixmap::cStyledPixmap(cPixmap *pixmap, cString caller) {
this->pixmap = pixmap;
this->caller = caller;
}
cStyledPixmap::~cStyledPixmap(void) {
if (pixmap)
osdManager.releasePixmap(pixmap, *caller);
}
void cStyledPixmap::setPixmap(cPixmap *pixmap) {
if (pixmap) {
this->pixmap = pixmap;
}
}
void cStyledPixmap::drawBackground() {
if (!tvguideConfig.useBlending) {
pixmap->Fill(color);
} else {
drawBlendedBackground();
}
}
void cStyledPixmap::drawBlendedBackground() {
int width = pixmap->ViewPort().Width();
int height = pixmap->ViewPort().Height();
pixmap->Fill(color);
int numSteps = 64;
int alphaStep = 0x04;
if (height < 30)
return;
else if (height < 100) {
numSteps = 32;
alphaStep = 0x08;
}
int stepY = 0.5*height / numSteps;
if (stepY == 0) stepY = 1;
int alpha = 0x00;
tColor clr;
for (int i = 0; i<numSteps; i++) {
clr = AlphaBlend(color, colorBlending, alpha);
pixmap->DrawRectangle(cRect(0,i*stepY,width,stepY), clr);
alpha += alphaStep;
}
}
void cStyledPixmap::drawBorder() {
int width = pixmap->ViewPort().Width();
int height = pixmap->ViewPort().Height();
drawDefaultBorder(width, height);
if (tvguideConfig.roundedCorners) {
int borderRadius = 12;
drawRoundedCorners(width, height, borderRadius);
}
}
void cStyledPixmap::drawDefaultBorder(int width, int height) {
pixmap->DrawRectangle(cRect(0,0,width,2), theme.Color(clrBackground)); //top
pixmap->DrawRectangle(cRect(0,0,2,height), theme.Color(clrBackground)); //left
pixmap->DrawRectangle(cRect(0,height-2,width,2), theme.Color(clrBackground)); //bottom
pixmap->DrawRectangle(cRect(width-2,0,2,height), theme.Color(clrBackground)); //right
pixmap->DrawRectangle(cRect(2,2,width-4,1), theme.Color(clrBorder)); //top
pixmap->DrawRectangle(cRect(2,2,1,height-4), theme.Color(clrBorder)); //left
pixmap->DrawRectangle(cRect(2,height-3,width-4,1), theme.Color(clrBorder)); //bottom
pixmap->DrawRectangle(cRect(width-3,2,1,height-4), theme.Color(clrBorder)); //right
}
void cStyledPixmap::drawBoldBorder() {
int width = pixmap->ViewPort().Width();
int height = pixmap->ViewPort().Height();
pixmap->DrawRectangle(cRect(0,0,width,2), theme.Color(clrBorder)); //top
pixmap->DrawRectangle(cRect(0,0,2,height), theme.Color(clrBorder)); //left
pixmap->DrawRectangle(cRect(0,height-2,width,2), theme.Color(clrBorder)); //bottom
pixmap->DrawRectangle(cRect(width-2,0,2,height), theme.Color(clrBorder)); //right
}
void cStyledPixmap::drawRoundedCorners(int width, int height, int radius) {
pixmap->DrawEllipse(cRect(2,2,radius,radius), theme.Color(clrBorder), -2);
pixmap->DrawEllipse(cRect(1,1,radius,radius), theme.Color(clrBackground), -2);
pixmap->DrawEllipse(cRect(width-radius - 2,2,radius,radius), theme.Color(clrBorder), -1);
pixmap->DrawEllipse(cRect(width-radius - 1,1,radius,radius), theme.Color(clrBackground), -1);
if( height > 2*radius) {
pixmap->DrawEllipse(cRect(2,height-radius - 2,radius,radius), theme.Color(clrBorder), -3);
pixmap->DrawEllipse(cRect(1,height-radius - 1,radius,radius), theme.Color(clrBackground), -3);
pixmap->DrawEllipse(cRect(width-radius - 2,height-radius - 2,radius,radius), theme.Color(clrBorder), -4);
pixmap->DrawEllipse(cRect(width-radius - 1,height-radius - 1,radius,radius), theme.Color(clrBackground), -4);
}
}
void cStyledPixmap::drawVerticalLine(int x, int yStart, int yStop, tColor col) {
for (int y = yStart; y <= yStop; y++) {
pixmap->DrawPixel(cPoint(x,y), col);
}
}
void cStyledPixmap::drawHorizontalLine(int y, int xStart, int xStop, tColor col) {
for (int x = xStart; x <= xStop; x++) {
pixmap->DrawPixel(cPoint(x,y), col);
}
}
void cStyledPixmap::DrawText(const cPoint &Point, const char *s, tColor ColorFg, tColor ColorBg, const cFont *Font) {
pixmap->DrawText(Point, s, ColorFg, ColorBg, Font);
}
void cStyledPixmap::DrawImage(const cPoint &Point, const cImage &Image) {
pixmap->DrawImage(Point, Image);
}
void cStyledPixmap::DrawRectangle(const cRect &Rect, tColor Color) {
pixmap->DrawRectangle(Rect,Color);
}

35
styledpixmap.h Normal file
View File

@ -0,0 +1,35 @@
#ifndef __TVGUIDE_STYLEDPIXMAP_H
#define __TVGUIDE_STYLEDPIXMAP_H
// --- cStyledPixmap -------------------------------------------------------------
class cStyledPixmap {
private:
void drawVerticalLine(int x, int yStart, int yStop, tColor col);
void drawHorizontalLine(int y, int xStart, int xStop, tColor col);
protected:
cPixmap *pixmap;
cString caller;
tColor color;
tColor colorBlending;
void setPixmap(cPixmap *pixmap);
public:
cStyledPixmap(void);
cStyledPixmap(cPixmap *pixmap, cString caller);
virtual ~cStyledPixmap(void);
void drawBackground();
void drawBlendedBackground();
void drawBorder();
void drawBoldBorder();
void drawDefaultBorder(int width, int height);
void drawRoundedCorners(int width, int height, int radius);
void setColor(tColor color, tColor colorBlending) {this->color = color; this->colorBlending = colorBlending;};
void SetAlpha(int alpha) {pixmap->SetAlpha(alpha);};
void DrawText(const cPoint &Point, const char *s, tColor ColorFg, tColor ColorBg, const cFont *Font);
void DrawImage(const cPoint &Point, const cImage &Image);
void DrawRectangle(const cRect &Rect, tColor Color);
int Width() {return pixmap->ViewPort().Width();};
int Height() {return pixmap->ViewPort().Height();};
};
#endif //__TVGUIDE_STYLEDPIXMAP_H

View File

@ -0,0 +1,28 @@
Description = DarkBlue
clrBackground = FF000000
clrBackgroundOSD = FF000000
clrGrid1 = FF0E53A7
clrGrid1Blending = FF000000
clrGrid2 = FF071871
clrGrid2Blending = FF000000
clrHighlight = FF7A6D6D
clrHighlightBlending = FF1C1919
clrFont = FFFFFFFF
clrFontHeader = FF000000
clrFontButtons = FFFFFFFF
clrHeader = FF8B9194
clrHeaderBlending = FF000000
clrBorder = FFFFFFFF
clrTimeline1 = FFFFFFFF
clrTimeline1Blending = FF828282
clrTimeline2 = FF000000
clrTimeline2Blending = FF3F3F3F
clrButtonRed = FFD42627
clrButtonRedBlending = FF000000
clrButtonGreen = FF004F00
clrButtonGreenBlending = FF000000
clrButtonYellow = FFFFA300
clrButtonYellowBlending = FF000000
clrButtonBlue = FF0000FE
clrButtonBlueBlending = FF000000

View File

@ -0,0 +1,27 @@
Description = Default
clrBackground = FF000000
clrBackgroundOSD = FF000000
clrGrid1 = FF404749
clrGrid1Blending = FF000000
clrGrid2 = FF20293F
clrGrid2Blending = FF000000
clrHighlight = FFFF4D00
clrHighlightBlending = FF000000
clrFont = FFFFFFFF
clrFontHeader = FFFFFFFF
clrFontButtons = FFFFFFFF
clrHeader = FF000000
clrHeaderBlending = FFE0E0E0
clrBorder = FFFFFFFF
clrTimeline1 = FFFFFFFF
clrTimeline1Blending = FF828282
clrTimeline2 = FF000000
clrTimeline2Blending = FF3F3F3F
clrButtonRed = FFD42627
clrButtonRedBlending = FFE0E0E0
clrButtonGreen = FF004F00
clrButtonGreenBlending = FFE0E0E0
clrButtonYellow = FFFFA300
clrButtonYellowBlending = FFE0E0E0
clrButtonBlue = FF0000FE
clrButtonBlueBlending = FFE0E0E0

115
timeline.c Normal file
View File

@ -0,0 +1,115 @@
#include "timeline.h"
cTimeLine::cTimeLine(cMyTime *myTime) {
this->myTime = myTime;
dateViewer = new cStyledPixmap(osdManager.requestPixmap(3, cRect(0, 0, tvguideConfig.timeColWidth, tvguideConfig.headerHeight), cRect::Null, "dateViewer"), "dateViewer");
timeline = osdManager.requestPixmap(2, cRect(0, tvguideConfig.headerHeight, tvguideConfig.timeColWidth, tvguideConfig.osdHeight - tvguideConfig.headerHeight - tvguideConfig.footerHeight),
cRect(0,0, tvguideConfig.timeColWidth, 1440*tvguideConfig.minuteHeight), "timeline");
clock = new cStyledPixmap(osdManager.requestPixmap(3, cRect(0, tvguideConfig.osdHeight-tvguideConfig.footerHeight, tvguideConfig.timeColWidth, tvguideConfig.footerHeight-9), cRect::Null, "timeViewer"), "timeViewer");
}
cTimeLine::~cTimeLine(void) {
delete dateViewer;
osdManager.releasePixmap(timeline);
delete clock;
}
void cTimeLine::drawDateViewer() {
cString weekDay = myTime->GetWeekday();
cString date = myTime->GetDate();
int textHeight = tvguideConfig.FontTimeLineWeekday->Height();
int weekdayWidth = tvguideConfig.FontTimeLineWeekday->Width(*weekDay);
int dateWidth = tvguideConfig.FontTimeLineDate->Width(*date);
dateViewer->setColor(theme.Color(clrHeader), theme.Color(clrHeaderBlending));
dateViewer->drawBackground();
dateViewer->drawBorder();
dateViewer->DrawText(cPoint((tvguideConfig.timeColWidth-weekdayWidth)/2, (tvguideConfig.headerHeight-2*textHeight)/2), *weekDay, theme.Color(clrFontHeader), clrTransparent, tvguideConfig.FontTimeLineWeekday);
dateViewer->DrawText(cPoint((tvguideConfig.timeColWidth-dateWidth)/2, (tvguideConfig.headerHeight-2*textHeight)/2 + textHeight + 5), *date, theme.Color(clrFontHeader), clrTransparent, tvguideConfig.FontTimeLineDate);
}
void cTimeLine::drawTimeline() {
timeline->SetTile(true);
timeline->Fill(theme.Color(clrBackground));
tColor colorFont;
const cImage *img1 = createBackgroundImage(tvguideConfig.timeColWidth-4, tvguideConfig.minuteHeight*30, theme.Color(clrTimeline1), theme.Color(clrTimeline1Blending));
const cImage *img2 = createBackgroundImage(tvguideConfig.timeColWidth-4, tvguideConfig.minuteHeight*30, theme.Color(clrTimeline2), theme.Color(clrTimeline2Blending));
const cImage *img = NULL;
int textWidth, posY;
char timetext[10];
for (int i=0; i<48; i++) {
if (i%2==0) {
img = img1;
colorFont = theme.Color(clrTimeline2);
if (tvguideConfig.timeFormat == e12Hours) {
if (i == 0)
sprintf(timetext, "12:00 PM");
else if (i/2 < 13)
sprintf(timetext, "%d:00 AM", i/2);
else
sprintf(timetext, "%d:00 PM", i/2-12);
} else {
sprintf(timetext, "%d:00", i/2);
}
} else {
img = img2;
colorFont = theme.Color(clrTimeline1);
if (tvguideConfig.timeFormat == e12Hours) {
if (i == 1)
sprintf(timetext, "12:30 PM");
else if (i/2 < 13)
sprintf(timetext, "%d:30 AM", i/2);
else
sprintf(timetext, "%d:30 PM", i/2-12);
} else {
sprintf(timetext, "%d:30", i/2);
}
}
posY = i*tvguideConfig.minuteHeight*30;
timeline->DrawImage(cPoint(2, posY), *img);
textWidth = tvguideConfig.FontTimeLineTime->Width(timetext);
timeline->DrawText(cPoint((tvguideConfig.timeColWidth-textWidth)/2, posY + 5), timetext, colorFont, clrTransparent, tvguideConfig.FontTimeLineTime);
}
setTimeline();
delete img1;
delete img2;
}
cImage *cTimeLine::createBackgroundImage(int width, int height, tColor clrBgr, tColor clrBlend) {
cImage *image = new cImage(cSize(width, height));
image->Fill(clrBgr);
if (tvguideConfig.useBlending) {
int stepY = 0.5*height / 64;
int alpha = 0x00;
tColor clr;
for (int i = 0; i<64; i++) {
clr = AlphaBlend(clrBgr, clrBlend, alpha);
for (int y = i*stepY; y < (i+1)*stepY; y++) {
for (int x=0; x<width; x++) {
image->SetPixel(cPoint(x,y), clr);
}
}
alpha += 0x04;
}
}
return image;
}
void cTimeLine::setTimeline() {
int offset = myTime->GetTimelineOffset();
timeline->SetDrawPortPoint(cPoint(0, -offset*tvguideConfig.minuteHeight));
}
void cTimeLine::drawClock() {
cString currentTime = myTime->GetCurrentTime();
int textHeight = tvguideConfig.FontTimeLineTime->Height();
int clockWidth = tvguideConfig.FontTimeLineTime->Width(*currentTime);
clock->setColor(theme.Color(clrHeader), theme.Color(clrHeaderBlending));
clock->drawBackground();
clock->drawBorder();
clock->DrawText(cPoint((tvguideConfig.timeColWidth-clockWidth)/2, (tvguideConfig.footerHeight-textHeight)/2), *currentTime, theme.Color(clrFontHeader), clrTransparent, tvguideConfig.FontTimeLineTime);
}

22
timeline.h Normal file
View File

@ -0,0 +1,22 @@
#ifndef __TVGUIDE_TIMELINE_H
#define __TVGUIDE_TIMELINE_H
// --- cTimeLine -------------------------------------------------------------
class cTimeLine {
private:
cMyTime *myTime;
cStyledPixmap *dateViewer;
cPixmap *timeline;
cStyledPixmap *clock;
cImage *createBackgroundImage(int width, int height, tColor clrBgr, tColor clrBlend);
public:
cTimeLine(cMyTime *myTime);
virtual ~cTimeLine(void);
void drawDateViewer();
void drawTimeline();
void setTimeline();
void drawClock();
};
#endif //__TVGUIDE_TIMELINE_H

106
timer.c Normal file
View File

@ -0,0 +1,106 @@
#include "timer.h"
cMyTime::~cMyTime(void) {
}
void cMyTime::Now() {
t = time(0);
tStart = t;
tStart = GetRounded();
tStop = tStart + (tvguideConfig.osdHeight - tvguideConfig.headerHeight - tvguideConfig.footerHeight)/tvguideConfig.minuteHeight*60;
}
void cMyTime::AddStep(int step) {
tStart += step*60;
tStop += step*60;
}
bool cMyTime::DelStep(int step) {
if ((tStart - step*60)+30*60 < t) {
return true;
}
tStart -= step*60;
tStop -= step*60;
return false;
}
void cMyTime::SetTime(time_t newTime) {
tStart = newTime;
tStop = tStart + (tvguideConfig.osdHeight - tvguideConfig.headerHeight - tvguideConfig.footerHeight)/tvguideConfig.minuteHeight*60;
}
time_t cMyTime::getPrevPrimetime(time_t current) {
tm *st = localtime(&current);
if (st->tm_hour < 21) {
current -= 24 * 60* 60;
st = localtime(&current);
}
st->tm_hour = 20;
st->tm_min = 0;
time_t primeTime = mktime(st);
return primeTime;
}
time_t cMyTime::getNextPrimetime(time_t current){
tm *st = localtime(&current);
if (st->tm_hour > 19) {
current += 24 * 60* 60;
st = localtime(&current);
}
st->tm_hour = 20;
st->tm_min = 0;
time_t primeTime = mktime(st);
return primeTime;
}
bool cMyTime::tooFarInPast(time_t current) {
if (current < t) {
return true;
}
return false;
}
cString cMyTime::GetCurrentTime() {
char buf[25];
t = time(0);
tm *st = localtime(&t);
//snprintf(text, sizeof(text), "%d:%02d", st->tm_hour, st->tm_min);
if (tvguideConfig.timeFormat == e12Hours) {
strftime(buf, sizeof(buf), "%I:%M %p", st);
} else if (tvguideConfig.timeFormat == e24Hours)
strftime(buf, sizeof(buf), "%H:%M", st);
return buf;
}
cString cMyTime::GetDate() {
char text[6];
tm *st = localtime(&tStart);
snprintf(text, sizeof(text), "%d.%d", st->tm_mday, st->tm_mon+1);
return text;
}
cString cMyTime::GetWeekday() {
return WeekDayName(tStart);
}
int cMyTime::GetTimelineOffset() {
tm *st = localtime(&tStart);
int offset = st->tm_hour*60;
offset += st->tm_min;
return offset;
}
time_t cMyTime::GetRounded() {
tm *rounded = localtime ( &tStart );
rounded->tm_sec = 0;
if (rounded->tm_min > 29)
rounded->tm_min = 30;
else
rounded->tm_min = 0;
return mktime(rounded);
}
void cMyTime::debug() {
esyslog("t: %s, tStart: %s, tStop: %s", *TimeString(t), *TimeString(tStart), *TimeString(tStop));
}

32
timer.h Normal file
View File

@ -0,0 +1,32 @@
#ifndef __TVGUIDE_TIMER_H
#define __TVGUIDE_TIMER_H
// --- cMyTime -------------------------------------------------------------
class cMyTime {
private:
time_t t;
time_t tStart;
time_t tStop;
public:
cMyTime(){};
virtual ~cMyTime(void);
void Now();
void AddStep(int step);
bool DelStep(int step);
void SetTime(time_t newTime);
time_t Get() {return t;};
time_t GetStart() {return tStart;};
time_t GetStop() {return tStop;};
cString GetCurrentTime();
cString GetDate();
cString GetWeekday();
time_t getPrevPrimetime(time_t current);
time_t getNextPrimetime(time_t current);
bool tooFarInPast(time_t current);
int GetTimelineOffset();
time_t GetRounded();
void debug();
};
#endif //__TVGUIDE_TIMER_H

194
tvguide.c Normal file
View File

@ -0,0 +1,194 @@
/*
* tvguide.c: A plugin for the Video Disk Recorder
*
* See the README file for copyright information and how to reach the author.
*
* $Id$
*/
#include <time.h>
#include <getopt.h>
#include <vdr/osd.h>
#include <vdr/plugin.h>
#include <vdr/device.h>
#include "tvguideosd.c"
#if defined(APIVERSNUM) && APIVERSNUM < 10717
#error "VDR-1.7.17 API version or greater is required!"
#endif
static const char *VERSION = "0.0.1";
static const char *DESCRIPTION = "A fancy 2d EPG Viewer";
static const char *MAINMENUENTRY = "Tvguide";
class cPluginTvguide : public cPlugin {
private:
bool logoPathSet;
bool imagesPathSet;
public:
cPluginTvguide(void);
virtual ~cPluginTvguide();
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 MAINMENUENTRY; }
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);
};
cPluginTvguide::cPluginTvguide(void)
{
// Initialize any member variables here.
// DON'T DO ANYTHING ELSE THAT MAY HAVE SIDE EFFECTS, REQUIRE GLOBAL
// VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT!
logoPathSet = false;
imagesPathSet = false;
}
cPluginTvguide::~cPluginTvguide()
{
// Clean up after yourself!
}
const char *cPluginTvguide::CommandLineHelp(void)
{
// Return a string that describes all known command line options.
return
" -i <IMAGESDIR>, --epgimages=<IMAGESDIR> Set directory where epgimages are stored\n"
" -l <LOGODIR>, --logodir=<LOGODIR> Set directory where logos are stored.\n";
}
bool cPluginTvguide::ProcessArgs(int argc, char *argv[])
{
// Implement command line argument processing here if applicable.
static const struct option long_options[] = {
{ "epgimages", required_argument, NULL, 'i' },
{ "logopath", required_argument, NULL, 'l' },
{ 0, 0, 0, 0 }
};
int c;
cString *path = NULL;
while ((c = getopt_long(argc, argv, "i:f:l:", long_options, NULL)) != -1) {
switch (c) {
case 'i':
path = new cString(optarg);
tvguideConfig.SetImagesPath(*path);
imagesPathSet = true;
break;
case 'l':
path = new cString(optarg);
tvguideConfig.SetLogoPath(*path);
logoPathSet = true;
break;
default:
return false;
}
if (path)
delete path;
}
return true;
}
bool cPluginTvguide::Initialize(void)
{
// Initialize any background activities the plugin shall perform.
return true;
}
bool cPluginTvguide::Start(void)
{
if (!logoPathSet) {
cString path = cString::sprintf("%s/channellogos/", cPlugin::ConfigDirectory(PLUGIN_NAME_I18N));
tvguideConfig.SetLogoPath(path);
logoPathSet = true;
}
if (!imagesPathSet) {
cString path = cString::sprintf("%s/epgimages/", cPlugin::ConfigDirectory(PLUGIN_NAME_I18N));
tvguideConfig.SetImagesPath(path);
logoPathSet = true;
}
return true;
}
void cPluginTvguide::Stop(void)
{
// Stop any background activities the plugin is performing.
}
void cPluginTvguide::Housekeeping(void)
{
// Perform any cleanup or other regular tasks.
}
void cPluginTvguide::MainThreadHook(void)
{
// Perform actions in the context of the main program thread.
// WARNING: Use with great care - see PLUGINS.html!
}
cString cPluginTvguide::Active(void)
{
// Return a message string if shutdown should be postponed
return NULL;
}
time_t cPluginTvguide::WakeupTime(void)
{
// Return custom wakeup time for shutdown script
return 0;
}
cOsdObject *cPluginTvguide::MainMenuAction(void)
{
// Perform the action when selected from the main VDR menu.
return new cTvGuideOsd;
}
cMenuSetupPage *cPluginTvguide::SetupMenu(void)
{
// Return a setup menu in case the plugin supports one.
return new cTvguideSetup();
}
bool cPluginTvguide::SetupParse(const char *Name, const char *Value)
{
// Parse your own setup parameters and store their values.
return tvguideConfig.SetupParse(Name, Value);
}
bool cPluginTvguide::Service(const char *Id, void *Data)
{
// Handle custom service requests from other plugins
return false;
}
const char **cPluginTvguide::SVDRPHelpPages(void)
{
// Return help text for SVDRP commands this plugin implements
return NULL;
}
cString cPluginTvguide::SVDRPCommand(const char *Command, const char *Option, int &ReplyCode)
{
// Process SVDRP commands this plugin implements
return NULL;
}
VDRPLUGINCREATOR(cPluginTvguide); // Don't touch this!

541
tvguideosd.c Normal file
View File

@ -0,0 +1,541 @@
// --- Theme -------------------------------------------------------------
static cTheme theme;
THEME_CLR(theme, clrBackgroundOSD, clrBlack);
THEME_CLR(theme, clrBackground, clrBlack);
THEME_CLR(theme, clrGrid1, 0xFF404749);
THEME_CLR(theme, clrGrid1Blending, 0xFF000000);
THEME_CLR(theme, clrGrid2, 0xFF20293F);
THEME_CLR(theme, clrGrid2Blending, 0xFF000000);
THEME_CLR(theme, clrHighlight, 0xFFFF4D00);
THEME_CLR(theme, clrHighlightBlending, 0xFF000000);
THEME_CLR(theme, clrFont, clrWhite);
THEME_CLR(theme, clrFontHeader, clrWhite);
THEME_CLR(theme, clrFontButtons, clrWhite);
THEME_CLR(theme, clrHeader, clrBlack);
THEME_CLR(theme, clrHeaderBlending, 0xFFE0E0E0);
THEME_CLR(theme, clrBorder, clrWhite);
THEME_CLR(theme, clrTimeline1, clrWhite);
THEME_CLR(theme, clrTimeline1Blending, 0xFF828282);
THEME_CLR(theme, clrTimeline2, clrBlack);
THEME_CLR(theme, clrTimeline2Blending, 0xFF3F3F3F);
THEME_CLR(theme, clrButtonRed, 0xFFD42627);
THEME_CLR(theme, clrButtonRedBlending, 0xFFE0E0E0);
THEME_CLR(theme, clrButtonGreen, 0xFF004F00);
THEME_CLR(theme, clrButtonGreenBlending, 0xFFE0E0E0);
THEME_CLR(theme, clrButtonYellow, 0xFFffa300);
THEME_CLR(theme, clrButtonYellowBlending, 0xFFE0E0E0);
THEME_CLR(theme, clrButtonBlue, 0xFF0000fe);
THEME_CLR(theme, clrButtonBlueBlending, 0xFFE0E0E0);
#include "config.c"
cTvguideConfig tvguideConfig;
#include "osdmanager.c"
cOsdManager osdManager;
#include "setup.c"
#include "imageloader.c"
#include "styledpixmap.c"
#include "timer.c"
#include "messagebox.c"
#include "timeline.c"
#include "epggrid.c"
#include "detailview.c"
#include "channelcolumn.c"
#include "footer.c"
#include "tvguideosd.h"
#include <stdlib.h>
cTvGuideOsd::cTvGuideOsd(void) {
detailView = NULL;
detailViewActive = false;
timeLine = NULL;
}
cTvGuideOsd::~cTvGuideOsd() {
delete myTime;
columns.Clear();
if (detailView)
delete detailView;
delete timeLine;
delete footer;
cMessageBox::Destroy();
osdManager.deleteOsd();
}
void cTvGuideOsd::Show(void) {
int start = cTimeMs::Now();
bool ok = false;
ok = osdManager.setOsd();
if (ok) {
tvguideConfig.setDynamicValues(osdManager.Width(), osdManager.Height());
tvguideConfig.loadTheme();
osdManager.setBackground();
myTime = new cMyTime();
myTime->Now();
drawOsd();
}
esyslog("tvguide: Rendering took %d ms", int(cTimeMs::Now()-start));
}
void cTvGuideOsd::drawOsd() {
cPixmap::Lock();
cChannel *startChannel = Channels.GetByNumber(cDevice::CurrentChannel());
timeLine = new cTimeLine(myTime);
timeLine->drawDateViewer();
timeLine->drawTimeline();
timeLine->drawClock();
footer = new cFooter();
footer->drawRedButton();
footer->drawGreenButton();
footer->drawYellowButton();
footer->drawBlueButton();
osdManager.flush();
readChannels(startChannel);
drawGridsChannelJump();
osdManager.flush();
cPixmap::Unlock();
}
void cTvGuideOsd::readChannels(cChannel *channelStart) {
int i=0;
columns.Clear();
if (!channelStart)
return;
for (cChannel *channel = channelStart; channel; channel = Channels.Next(channel)) {
if (!channel->GroupSep()) {
cChannelColumn *column = new cChannelColumn(i, channel, myTime);
if (column->readGrids()) {
columns.Add(column);
i++;
} else {
delete column;
}
}
if (i == tvguideConfig.channelCols)
break;
}
}
bool cTvGuideOsd::readChannelsReverse(cChannel *channelStart) {
bool doUpdate = false;
int i = tvguideConfig.channelCols;
if (!channelStart)
return false;
for (cChannel *channel = Channels.Prev(channelStart); channel; channel = Channels.Prev(channel)) {
if (!channel->GroupSep()) {
cChannelColumn *column = new cChannelColumn(i-1, channel, myTime);
if (column->readGrids()) {
if (i == tvguideConfig.channelCols) {
columns.Clear();
doUpdate = true;
}
columns.Ins(column, columns.First());
i--;
} else {
delete column;
}
}
if (i == 0)
break;
}
return doUpdate;
}
void cTvGuideOsd::drawGridsChannelJump() {
if (columns.Count() == 0)
return;
activeGrid = columns.First()->getActive();
if (activeGrid)
activeGrid->SetActive();
for (cChannelColumn *column = columns.First(); column; column = columns.Next(column)) {
column->createHeader();
column->drawGrids();
}
}
void cTvGuideOsd::drawGridsTimeJump() {
if (columns.Count() == 0)
return;
cChannelColumn *colActive = NULL;
if (activeGrid) {
colActive = activeGrid->column;
} else {
colActive = columns.First();
}
for (cChannelColumn *column = columns.First(); column; column = columns.Next(column)) {
column->clearGrids();
column->readGrids();
column->drawGrids();
}
activeGrid = colActive->getActive();
if (activeGrid) {
activeGrid->SetActive();
activeGrid->Draw();
}
}
void cTvGuideOsd::setNextActiveGrid(cEpgGrid *next) {
if (!next || !activeGrid) {
return;
}
activeGrid->SetInActive();
activeGrid->Draw();
activeGrid = next;
activeGrid->SetActive();
activeGrid->Draw();
}
void cTvGuideOsd::processKeyUp() {
if (detailViewActive) {
detailView->scrollUp();
} else {
if (activeGrid == NULL) {
ScrollBack();
//Search for new active Grid
cEpgGrid *actGrid = NULL;
for (cChannelColumn *column = columns.First(); column; column = columns.Next(column)) {
actGrid = column->getActive();
if (actGrid) {
activeGrid = actGrid;
activeGrid->SetActive();
activeGrid->Draw();
break;
}
}
} else if (activeGrid->StartTime() <= myTime->GetStart()) {
activeGrid->debug();
ScrollBack();
} else {
cEpgGrid *prev = NULL;
prev = activeGrid->column->getPrev(activeGrid);
if (prev) {
setNextActiveGrid(prev);
} else {
ScrollBack();
prev = activeGrid->column->getPrev(activeGrid);
if (prev) {
setNextActiveGrid(prev);
}
}
}
}
osdManager.flush();
}
void cTvGuideOsd::processKeyDown() {
if (detailViewActive) {
detailView->scrollDown();
} else {
if (activeGrid == NULL) {
ScrollForward();
} else if (activeGrid->EndTime() > myTime->GetStop()) {
ScrollForward();
} else {
cEpgGrid *next = NULL;
next = activeGrid->column->getNext(activeGrid);
if (next) {
setNextActiveGrid(next);
} else {
ScrollForward();
next = activeGrid->column->getNext(activeGrid);
if (next) {
setNextActiveGrid(next);
}
}
}
}
osdManager.flush();
}
void cTvGuideOsd::ScrollForward() {
myTime->AddStep(tvguideConfig.stepMinutes);
timeLine->drawDateViewer();
timeLine->drawClock();
timeLine->setTimeline();
for (cChannelColumn *column = columns.First(); column; column = columns.Next(column)) {
column->AddNewGridsAtEnd();
column->ClearOutdatedStart();
column->drawGrids();
}
}
void cTvGuideOsd::ScrollBack() {
bool tooFarInPast = myTime->DelStep(tvguideConfig.stepMinutes);
if (tooFarInPast)
return;
timeLine->drawDateViewer();
timeLine->drawClock();
timeLine->setTimeline();
for (cChannelColumn *column = columns.First(); column; column = columns.Next(column)) {
column->AddNewGridsAtStart();
column->ClearOutdatedEnd();
column->drawGrids();
}
}
void cTvGuideOsd::processKeyLeft() {
if (detailViewActive)
return;
if (activeGrid == NULL)
return;
cChannelColumn *colLeft = columns.Prev(activeGrid->column);
if (!colLeft) {
cChannel *channelLeft = activeGrid->column->getChannel();
while (channelLeft = Channels.Prev(channelLeft)) {
if (!channelLeft->GroupSep()) {
colLeft = new cChannelColumn(0, channelLeft, myTime);
if (colLeft->readGrids()) {
break;
} else {
delete colLeft;
colLeft = NULL;
}
}
}
if (colLeft) {
if (columns.Count() == tvguideConfig.channelCols) {
cChannelColumn *cLast = columns.Last();
columns.Del(cLast);
}
for (cChannelColumn *column = columns.First(); column; column = columns.Next(column)) {
column->SetNum(column->GetNum() + 1);
column->drawHeader();
column->drawGrids();
}
columns.Ins(colLeft, columns.First());
colLeft->createHeader();
colLeft->drawGrids();
}
}
if (colLeft) {
cEpgGrid *left = colLeft->getNeighbor(activeGrid);
if (left) {
setNextActiveGrid(left);
}
}
osdManager.flush();
}
void cTvGuideOsd::processKeyRight() {
if (detailViewActive)
return;
if (activeGrid == NULL)
return;
cChannelColumn *colRight = columns.Next(activeGrid->column);
if (!colRight) {
cChannel *channelRight = activeGrid->column->getChannel();
while (channelRight = Channels.Next(channelRight)) {
if (!channelRight->GroupSep()) {
colRight = new cChannelColumn(tvguideConfig.channelCols - 1, channelRight, myTime);
if (colRight->readGrids()) {
break;
} else {
delete colRight;
colRight = NULL;
}
}
}
if (colRight) {
if (columns.Count() == tvguideConfig.channelCols) {
cChannelColumn *cFirst = columns.First();
columns.Del(cFirst);
}
for (cChannelColumn *column = columns.First(); column; column = columns.Next(column)) {
column->SetNum(column->GetNum() - 1);
column->drawHeader();
column->drawGrids();
}
columns.Add(colRight);
colRight->createHeader();
colRight->drawGrids();
}
}
if (colRight) {
cEpgGrid *right = colRight->getNeighbor(activeGrid);
if (right) {
setNextActiveGrid(right);
}
}
osdManager.flush();
}
void cTvGuideOsd::processKeyOk() {
if (detailViewActive) {
delete detailView;
detailView = NULL;
detailViewActive = false;
osdManager.flush();
} else {
detailViewActive = true;
detailView = new cDetailView(activeGrid);
detailView->Start();
}
}
void cTvGuideOsd::processKeyRed() {
if (activeGrid == NULL)
return;
cTimer *timer = new cTimer(activeGrid->GetEvent());
cTimer *t = Timers.GetTimer(timer);
cString msg;
if (t) {
isyslog("timer %s already exists", *timer->ToDescr());
delete timer;
msg = cString::sprintf(tr("Timer not set! There is already a timer for this item."));
} else {
Timers.Add(timer);
Timers.SetModified();
msg = cString::sprintf("%s:\n%s (%s) %s - %s", tr("Timer set"), activeGrid->GetEvent()->Title(), timer->Channel()->Name(), *DayDateTime(timer->StartTime()), *TimeString(timer->StopTime()));
timer->SetEvent(activeGrid->GetEvent());
activeGrid->setTimer();
activeGrid->column->setTimer();
activeGrid->SetDirty();
activeGrid->Draw();
osdManager.flush();
isyslog("timer %s added (active)", *timer->ToDescr());
}
cMessageBox::Start(4000, msg);
}
void cTvGuideOsd::processKeyGreen() {
if (activeGrid == NULL)
return;
cChannel *currentChannel = activeGrid->column->getChannel();
bool doUpdate = readChannelsReverse(currentChannel);
if (doUpdate && (columns.Count() > 0)) {
drawGridsChannelJump();
}
osdManager.flush();
}
void cTvGuideOsd::processKeyYellow() {
if (activeGrid == NULL)
return;
cChannel *currentChannel = activeGrid->column->getChannel();
cChannel *next = NULL;
int i=0;
for (cChannel *channel = currentChannel; channel; channel = Channels.Next(channel)) {
if (!channel->GroupSep()) {
next = channel;
i++;
}
if (i == (tvguideConfig.jumpChannels+1))
break;
}
if (next) {
readChannels(next);
if (columns.Count() > 0) {
drawGridsChannelJump();
}
osdManager.flush();
}
}
eOSState cTvGuideOsd::processKeyBlue() {
if (activeGrid == NULL)
return osContinue;
cChannel *currentChannel = activeGrid->column->getChannel();
if (currentChannel) {
cDevice::PrimaryDevice()->SwitchChannel(currentChannel, true);
return osEnd;
}
return osContinue;
}
void cTvGuideOsd::processKey1() {
bool tooFarInPast = myTime->DelStep(tvguideConfig.bigStepHours*60);
if (tooFarInPast)
return;
drawGridsTimeJump();
timeLine->drawDateViewer();
timeLine->drawClock();
timeLine->setTimeline();
osdManager.flush();
}
void cTvGuideOsd::processKey3() {
myTime->AddStep(tvguideConfig.bigStepHours*60);
drawGridsTimeJump();
timeLine->drawDateViewer();
timeLine->drawClock();
timeLine->setTimeline();
osdManager.flush();
}
void cTvGuideOsd::processKey4() {
bool tooFarInPast = myTime->DelStep(tvguideConfig.hugeStepHours*60);
if (tooFarInPast)
return;
drawGridsTimeJump();
timeLine->drawDateViewer();
timeLine->drawClock();
timeLine->setTimeline();
osdManager.flush();
}
void cTvGuideOsd::processKey6() {
myTime->AddStep(tvguideConfig.hugeStepHours*60);
drawGridsTimeJump();
timeLine->drawDateViewer();
timeLine->drawClock();
timeLine->setTimeline();
osdManager.flush();
}
void cTvGuideOsd::processKey7() {
cMyTime *primeChecker = new cMyTime();
primeChecker->Now();
time_t prevPrime = primeChecker->getPrevPrimetime(myTime->GetStart());
if (primeChecker->tooFarInPast(prevPrime))
return;
myTime->SetTime(prevPrime);
drawGridsTimeJump();
timeLine->drawDateViewer();
timeLine->drawClock();
timeLine->setTimeline();
osdManager.flush();
}
void cTvGuideOsd::processKey9() {
cMyTime *primeChecker = new cMyTime();
time_t nextPrime = primeChecker->getNextPrimetime(myTime->GetStart());
myTime->SetTime(nextPrime);
drawGridsTimeJump();
timeLine->drawDateViewer();
timeLine->drawClock();
timeLine->setTimeline();
osdManager.flush();
}
eOSState cTvGuideOsd::ProcessKey(eKeys Key) {
eOSState state = cOsdObject::ProcessKey(Key);
if (state == osUnknown) {
cPixmap::Lock();
state = osContinue;
switch (Key & ~k_Repeat) {
case kUp: processKeyUp(); break;
case kDown: processKeyDown(); break;
case kLeft: processKeyLeft(); break;
case kRight: processKeyRight(); break;
case kRed: processKeyRed(); break;
case kGreen: processKeyGreen(); break;
case kYellow: processKeyYellow(); break;
case kBlue: state = processKeyBlue(); break;
case kOk: processKeyOk(); break;
case kBack: state=osEnd; break;
case k1: processKey1(); break;
case k3: processKey3(); break;
case k4: processKey4(); break;
case k6: processKey6(); break;
case k7: processKey7(); break;
case k9: processKey9(); break;
default: break;
}
cPixmap::Unlock();
}
return state;
}

45
tvguideosd.h Normal file
View File

@ -0,0 +1,45 @@
#ifndef __TVGUIDE_TVGUIDEOSD_H
#define __TVGUIDE_TVGUIDEOSD_H
// --- cTvGuideOsd -------------------------------------------------------------
class cTvGuideOsd : public cOsdObject {
private:
cMyTime *myTime;
cList<cChannelColumn> columns;
cEpgGrid *activeGrid;
cDetailView *detailView;
cTimeLine *timeLine;
cFooter *footer;
bool detailViewActive;
void drawOsd();
void readChannels(cChannel *channelStart);
bool readChannelsReverse(cChannel *channelStart);
void drawGridsChannelJump();
void drawGridsTimeJump();
void processKeyUp();
void processKeyDown();
void processKeyLeft();
void processKeyRight();
void processKeyRed();
void processKeyGreen();
void processKeyYellow();
eOSState processKeyBlue();
void processKeyOk();
void processKey1();
void processKey3();
void processKey4();
void processKey6();
void processKey7();
void processKey9();
void setNextActiveGrid(cEpgGrid *next);
void ScrollForward();
void ScrollBack();
public:
cTvGuideOsd(void);
virtual ~cTvGuideOsd(void);
virtual void Show(void);
virtual eOSState ProcessKey(eKeys Key);
};
#endif //__TVGUIDE_TVGUIDEOSD_H