[vdr-plugin-tvguide] 01/03: Imported Upstream version 1.2.2
Tobias Grimm
tiber-guest at moszumanska.debian.org
Tue Feb 10 18:11:47 UTC 2015
This is an automated email from the git hooks/post-receive script.
tiber-guest pushed a commit to branch master
in repository vdr-plugin-tvguide.
commit ca346bbbd3ef7d7cf25dc59fc707df5af273a8d5
Author: etobi <git at e-tobi.net>
Date: Tue Feb 10 19:08:40 2015 +0100
Imported Upstream version 1.2.2
---
HISTORY | 128 +
Makefile | 25 +-
Makefile-smaller-VDR1.7.34 | 115 -
README | 281 +-
channelcolumn.c | 558 ++--
channelcolumn.h | 82 +-
channelgroup.c | 98 +
channelgroup.h | 44 +
channelgroups.c | 143 +
channelgroups.h | 30 +
channeljump.c | 90 +
channeljump.h | 29 +
config.c | 472 ++--
config.h | 308 ++-
detailview.c | 315 +--
detailview.h | 49 +-
dummygrid.c | 111 +
dummygrid.h | 34 +
epggrid.c | 255 +-
epggrid.h | 56 +-
fontmanager.c | 96 +
fontmanager.h | 41 +
footer.c | 174 +-
footer.h | 32 +-
geometrymanager.c | 74 +
geometrymanager.h | 54 +
grid.c | 82 +
grid.h | 58 +
headergrid.c | 128 +
headergrid.h | 21 +
icons/darkredNG/osdElements/button_30percent.png | Bin 0 -> 39062 bytes
icons/darkredNG/osdElements/button_70percent.png | Bin 0 -> 103047 bytes
.../osdElements/button_active_30percent.png | Bin 0 -> 38329 bytes
.../osdElements/button_active_70percent.png | Bin 0 -> 99939 bytes
icons/darkredNG/osdElements/buttonblue.png | Bin 0 -> 12519 bytes
icons/darkredNG/osdElements/buttongreen.png | Bin 0 -> 12737 bytes
icons/darkredNG/osdElements/buttonred.png | Bin 0 -> 12362 bytes
icons/darkredNG/osdElements/buttonyellow.png | Bin 0 -> 13023 bytes
icons/darkredNG/osdElements/channel_jump.png | Bin 0 -> 76404 bytes
.../darkredNG/osdElements/channelgroup_bottom.png | Bin 0 -> 2292 bytes
icons/darkredNG/osdElements/channelgroup_head.png | Bin 0 -> 2288 bytes
.../osdElements/channelgroup_horizontal.png | Bin 0 -> 31050 bytes
icons/darkredNG/osdElements/channelgroup_left.png | Bin 0 -> 1998 bytes
icons/darkredNG/osdElements/channelgroup_right.png | Bin 0 -> 1861 bytes
.../osdElements/channelgroup_vertical.png | Bin 0 -> 14472 bytes
.../osdElements/channellogoback_horizontal.png | Bin 0 -> 16307 bytes
.../osdElements/channellogoback_vertical.png | Bin 0 -> 26057 bytes
icons/darkredNG/osdElements/clock.png | Bin 0 -> 5976 bytes
icons/darkredNG/osdElements/date_vertical.png | Bin 0 -> 19803 bytes
icons/darkredNG/osdElements/grid_active_bottom.png | Bin 0 -> 2642 bytes
icons/darkredNG/osdElements/grid_active_head.png | Bin 0 -> 2684 bytes
.../osdElements/grid_active_horizontal.png | Bin 0 -> 30601 bytes
icons/darkredNG/osdElements/grid_active_left.png | Bin 0 -> 2328 bytes
icons/darkredNG/osdElements/grid_active_right.png | Bin 0 -> 2208 bytes
.../darkredNG/osdElements/grid_active_vertical.png | Bin 0 -> 97490 bytes
icons/darkredNG/osdElements/grid_bottom.png | Bin 0 -> 4170 bytes
icons/darkredNG/osdElements/grid_head.png | Bin 0 -> 3852 bytes
icons/darkredNG/osdElements/grid_horizontal.png | Bin 0 -> 32326 bytes
icons/darkredNG/osdElements/grid_left.png | Bin 0 -> 2301 bytes
icons/darkredNG/osdElements/grid_right.png | Bin 0 -> 2182 bytes
icons/darkredNG/osdElements/grid_vertical.png | Bin 0 -> 98957 bytes
icons/darkredNG/osdElements/recmenu_background.png | Bin 0 -> 309224 bytes
.../osdElements/statusheader_content_full.png | Bin 0 -> 259761 bytes
.../osdElements/statusheader_content_windowed.png | Bin 0 -> 195867 bytes
.../darkredNG/osdElements/statusheader_tvframe.png | Bin 0 -> 57079 bytes
.../darkredNG/osdElements/timeline1_horizontal.png | Bin 0 -> 21401 bytes
icons/darkredNG/osdElements/timeline1_vertical.png | Bin 0 -> 17751 bytes
.../darkredNG/osdElements/timeline2_horizontal.png | Bin 0 -> 20310 bytes
icons/darkredNG/osdElements/timeline2_vertical.png | Bin 0 -> 17650 bytes
icons/darkredNG/recmenuicons/activetimer.png | Bin 0 -> 1731 bytes
icons/darkredNG/recmenuicons/arrow_left.png | Bin 0 -> 1136 bytes
icons/darkredNG/recmenuicons/arrow_right.png | Bin 0 -> 936 bytes
icons/darkredNG/recmenuicons/delete_active.png | Bin 0 -> 768 bytes
icons/darkredNG/recmenuicons/delete_inactive.png | Bin 0 -> 886 bytes
icons/darkredNG/recmenuicons/edit_active.png | Bin 0 -> 2599 bytes
icons/darkredNG/recmenuicons/edit_inactive.png | Bin 0 -> 2009 bytes
icons/darkredNG/recmenuicons/icon_backspace.png | Bin 0 -> 1873 bytes
icons/darkredNG/recmenuicons/icon_del_ins.png | Bin 0 -> 1532 bytes
icons/darkredNG/recmenuicons/icon_shift.png | Bin 0 -> 1274 bytes
icons/darkredNG/recmenuicons/info_active.png | Bin 0 -> 2421 bytes
icons/darkredNG/recmenuicons/info_inactive.png | Bin 0 -> 1859 bytes
icons/darkredNG/recmenuicons/no.png | Bin 0 -> 1627 bytes
icons/darkredNG/recmenuicons/record_active.png | Bin 0 -> 6736 bytes
icons/darkredNG/recmenuicons/record_inactive.png | Bin 0 -> 3859 bytes
icons/darkredNG/recmenuicons/search_active.png | Bin 0 -> 3426 bytes
icons/darkredNG/recmenuicons/search_inactive.png | Bin 0 -> 2977 bytes
icons/darkredNG/recmenuicons/yes.png | Bin 0 -> 2655 bytes
icons/default/osdElements/button_30percent.png | Bin 0 -> 38442 bytes
icons/default/osdElements/button_70percent.png | Bin 0 -> 105355 bytes
.../osdElements/button_active_30percent.png | Bin 0 -> 39767 bytes
.../osdElements/button_active_70percent.png | Bin 0 -> 105357 bytes
icons/default/osdElements/buttonblue.png | Bin 0 -> 12519 bytes
icons/default/osdElements/buttongreen.png | Bin 0 -> 12737 bytes
icons/default/osdElements/buttonred.png | Bin 0 -> 12362 bytes
icons/default/osdElements/buttonyellow.png | Bin 0 -> 13023 bytes
icons/default/osdElements/channel_jump.png | Bin 0 -> 87769 bytes
icons/default/osdElements/channelgroup_bottom.png | Bin 0 -> 1877 bytes
icons/default/osdElements/channelgroup_head.png | Bin 0 -> 1836 bytes
.../osdElements/channelgroup_horiziontal.png | Bin 0 -> 31893 bytes
.../osdElements/channelgroup_horizontal.png | Bin 0 -> 31893 bytes
icons/default/osdElements/channelgroup_left.png | Bin 0 -> 1942 bytes
icons/default/osdElements/channelgroup_right.png | Bin 0 -> 1789 bytes
.../default/osdElements/channelgroup_vertical.png | Bin 0 -> 16921 bytes
.../default/osdElements/channelgroups_vertical.png | Bin 0 -> 19041 bytes
.../osdElements/channellogoback_horizontal.png | Bin 0 -> 17836 bytes
.../osdElements/channellogoback_vertical.png | Bin 0 -> 28204 bytes
icons/default/osdElements/clock.png | Bin 0 -> 6001 bytes
icons/default/osdElements/date_vertical.png | Bin 0 -> 19803 bytes
icons/default/osdElements/grid_active_bottom.png | Bin 0 -> 3289 bytes
icons/default/osdElements/grid_active_head.png | Bin 0 -> 3424 bytes
.../default/osdElements/grid_active_horizontal.png | Bin 0 -> 33656 bytes
icons/default/osdElements/grid_active_left.png | Bin 0 -> 2524 bytes
icons/default/osdElements/grid_active_right.png | Bin 0 -> 2527 bytes
icons/default/osdElements/grid_active_vertical.png | Bin 0 -> 100607 bytes
icons/default/osdElements/grid_bottom.png | Bin 0 -> 2863 bytes
icons/default/osdElements/grid_head.png | Bin 0 -> 2800 bytes
icons/default/osdElements/grid_horizontal.png | Bin 0 -> 33304 bytes
icons/default/osdElements/grid_left.png | Bin 0 -> 2462 bytes
icons/default/osdElements/grid_right.png | Bin 0 -> 2389 bytes
icons/default/osdElements/grid_vertical.png | Bin 0 -> 100766 bytes
icons/default/osdElements/grids_vertical.png | Bin 0 -> 116790 bytes
icons/default/osdElements/recmenu_background.png | Bin 0 -> 305292 bytes
.../osdElements/statusheader_content_full.png | Bin 0 -> 262937 bytes
.../osdElements/statusheader_content_windowed.png | Bin 0 -> 212247 bytes
icons/default/osdElements/statusheader_tvframe.png | Bin 0 -> 57459 bytes
icons/default/osdElements/timeline1_horizontal.png | Bin 0 -> 21401 bytes
icons/default/osdElements/timeline1_vertical.png | Bin 0 -> 17751 bytes
icons/default/osdElements/timeline2_horizontal.png | Bin 0 -> 20310 bytes
icons/default/osdElements/timeline2_vertical.png | Bin 0 -> 17650 bytes
icons/default/recmenuicons/activetimer.png | Bin 0 -> 1731 bytes
icons/default/recmenuicons/arrow_left.png | Bin 0 -> 1136 bytes
icons/default/recmenuicons/arrow_right.png | Bin 0 -> 936 bytes
icons/default/recmenuicons/delete_active.png | Bin 0 -> 768 bytes
icons/default/recmenuicons/delete_inactive.png | Bin 0 -> 886 bytes
icons/default/recmenuicons/edit_active.png | Bin 0 -> 2599 bytes
icons/default/recmenuicons/edit_inactive.png | Bin 0 -> 2009 bytes
icons/default/recmenuicons/icon_backspace.png | Bin 0 -> 1873 bytes
icons/default/recmenuicons/icon_del_ins.png | Bin 0 -> 1532 bytes
icons/default/recmenuicons/icon_shift.png | Bin 0 -> 1274 bytes
icons/default/recmenuicons/info_active.png | Bin 0 -> 2421 bytes
icons/default/recmenuicons/info_inactive.png | Bin 0 -> 1859 bytes
icons/default/recmenuicons/no.png | Bin 0 -> 1627 bytes
icons/default/recmenuicons/record_active.png | Bin 0 -> 6736 bytes
icons/default/recmenuicons/record_inactive.png | Bin 0 -> 3859 bytes
icons/default/recmenuicons/search_active.png | Bin 0 -> 3426 bytes
icons/default/recmenuicons/search_inactive.png | Bin 0 -> 2977 bytes
icons/default/recmenuicons/yes.png | Bin 0 -> 2655 bytes
icons/recmenuicons/activetimer.png | Bin 0 -> 1731 bytes
icons/recmenuicons/arrow_left.png | Bin 0 -> 1136 bytes
icons/recmenuicons/arrow_right.png | Bin 0 -> 936 bytes
icons/recmenuicons/delete_active.png | Bin 0 -> 768 bytes
icons/recmenuicons/delete_inactive.png | Bin 0 -> 886 bytes
icons/recmenuicons/edit_active.png | Bin 0 -> 2599 bytes
icons/recmenuicons/edit_inactive.png | Bin 0 -> 2009 bytes
icons/recmenuicons/icon_backspace.png | Bin 0 -> 1873 bytes
icons/recmenuicons/icon_del_ins.png | Bin 0 -> 1532 bytes
icons/recmenuicons/icon_shift.png | Bin 0 -> 1274 bytes
icons/recmenuicons/info_active.png | Bin 0 -> 2421 bytes
icons/recmenuicons/info_inactive.png | Bin 0 -> 1859 bytes
icons/recmenuicons/no.png | Bin 0 -> 1627 bytes
icons/recmenuicons/record_active.png | Bin 0 -> 6736 bytes
icons/recmenuicons/record_inactive.png | Bin 0 -> 3859 bytes
icons/recmenuicons/search_active.png | Bin 0 -> 3426 bytes
icons/recmenuicons/search_inactive.png | Bin 0 -> 2977 bytes
icons/recmenuicons/yes.png | Bin 0 -> 2655 bytes
imagecache.c | 715 +++++
imagecache.h | 92 +
imageloader.c | 179 +-
imageloader.h | 16 +-
imagemagickwrapper.c | 162 ++
imagemagickwrapper.h | 27 +
imagescaler.c | 149 +
imagescaler.h | 97 +
messagebox.c | 114 -
messagebox.h | 31 -
osdmanager.c | 68 +-
osdmanager.h | 23 +
po/ca_ES.po | 958 +++++++
po/de_DE.po | 882 +++++-
po/ru_RU.po | 955 +++++++
po/sk_SK.po | 955 +++++++
recmanager.c | 714 +++++
recmanager.h | 63 +
recmenu.c | 695 +++++
recmenu.h | 66 +
recmenuitem.c | 2902 ++++++++++++++++++++
recmenuitem.h | 684 +++++
recmenumanager.c | 893 ++++++
recmenumanager.h | 42 +
recmenus.c | 1561 +++++++++++
recmenus.h | 485 ++++
searchtimer.c | 570 ++++
searchtimer.h | 136 +
services/epgsearch.h | 202 ++
services/remotetimers.h | 33 +
services/scraper2vdr.h | 194 ++
setup.c | 561 +++-
setup.h | 100 +-
statusheader.c | 142 +
statusheader.h | 25 +
styledpixmap.c | 233 +-
styledpixmap.h | 70 +-
switchtimer.c | 113 +
switchtimer.h | 31 +
themes/tvguide-blue.theme | 53 +
themes/tvguide-darkblue.theme | 28 +-
themes/tvguide-darkred.theme | 53 +
themes/tvguide-darkredNG.theme | 53 +
themes/tvguide-default.theme | 65 +-
themes/tvguide-green.theme | 53 +
themes/tvguide-iceblue.theme | 51 +
themes/tvguide-keepitsimple.theme | 49 +
themes/tvguide-nOpacity.theme | 28 -
themes/tvguide-nOpacitygreen.theme | 28 -
timeline.c | 334 ++-
timeline.h | 29 +-
timer.c | 200 +-
timer.h | 66 +-
timerconflict.c | 177 ++
timerconflict.h | 38 +
tools.c | 474 ++++
tools.h | 68 +
tvguide.c | 156 +-
tvguideosd.c | 1171 ++++----
tvguideosd.h | 48 +-
view.c | 1046 +++++++
view.h | 149 +
227 files changed, 21820 insertions(+), 2518 deletions(-)
diff --git a/HISTORY b/HISTORY
index 3e346c4..6611bea 100644
--- a/HISTORY
+++ b/HISTORY
@@ -10,3 +10,131 @@ VDR Plugin 'tvguide' Revision History
- Changed color buttons to nOpacity style
- Changed channelheader to display transparent logos properly
- Added "style nOpacity" for backgrounds and theme nOpacity
+
+2013-05-13: Version 0.0.3
+
+- Added dummy grids if no EPG information is available for a certain
+ time
+- Completely rewrote code for creation of epg grids for a channel column
+- Completely rewrote code for scrolling forward and backward in time
+- Added status header with epg information of currently selected
+ schedule and scaled video picture
+
+2013-05-24: Version 0.0.4
+
+- Introduced horizontal display
+
+2013-06-01: Version 0.0.5
+
+- Added Theme DarkRed
+- Fixed some Bugs (position of video, deadlock)
+- Added Theme IceBlue
+- setup of usage of blending now done with clrDoBlending theme color
+ variable and not by setup
+- font color of active grid themable
+- avoided nasty font pixelation effects with theme iceblue
+- Display of channel groups
+- Buttons green / yellow can be configured to jump to prev / next channel
+ group
+- Added setup option to hide last channel group
+- Display of Main Menu Entry configurable
+- Eliminated setup option "Number of channels to jump", directly jump
+ number of channel columns / rows with green / yellow
+- Added setup option to switch functionality of keys "Blue" and "OK"
+- Setup option to hide schedules time display in horizontal EPG grids
+
+2013-07-08: Version 0.0.6
+
+- added frame around scaled video picture
+- added theme "keep it simple" (thanks @saman)
+- display of additional EPG pictures in detailed epg view
+- Introduction of "Search & Recording" Menu
+- added possibility to replace original VDR schedules menu
+- changed channel jump logic
+- red button also available in detail view
+- page scrolling with keys left and right in detail view
+- added possibility to choose folder for instant recording, possible
+ folders are read from VDRs folders list
+- recording folder also choosable for series timers
+- blue button also available in detail view
+- color buttons displayed as configured in VDR
+- Added Setup Option to define if tvguide closes after channel switching
+- Added remotetimers support (thanks @Saman for providing a patch)
+- Pimped timeline
+
+2013-07-23: Version 1.0.0
+
+- added tvscraper support
+
+Version 1.1.0
+
+- changed build system
+- introduced image caching
+- introduced new "graphical" style
+- added new graphical default theme and theme darkred NG corresponding
+ to nOpacity themes
+- using automatically configured nOpacity theme if available
+- adapted startup options to nOpacity startup options:
+ -e epgimages directory
+ -i icons directory
+ -l logo directory
+- changed detailed epg view using full screen, some further optimisations
+- search for <event_id>_0.jpg beside <event_id>.jpg as epg image
+- implemented GraphicsMagick compatibility (thanks @Manuel Reimer
+ for providing the patch)
+- changed Makefile to support both ImageMagick and GraphicsMagick
+ (configurable in Makefile)
+- Added russian and catalan translation
+- Added slovakian translation
+- fixed channel switching with blue key if detailed epg view is opened and
+ if "close tvguide on channel switch" is configured
+- fixed wrong font for clock in horizontal view
+- Added feature to jump to a specific channel with number keys
+- Fixed Bug 1484
+- Added Event Short Text (if available) to RecName (Closes Ticket 1490)
+- Fixed OSD Background Color (Closes Ticket 1474)
+- Rounded Corners for color buttons (Closes Ticket 1475)
+- Fixed some issues with text backgrounds in flat themes (closes
+ Tickets 1480 and 1486)
+- Added possibility to search for reruns in case of a timer conflict
+- Added timer Timeline view in red button recording menu
+- Current channel positioned in middle of channellist when tvguide is
+ opened
+- Added possibility to manage EPG Search Timers in red button recording
+ menu
+- completely refactored recording menu
+- restructured detailöed EPG View that tv frame and status buttons
+ are displayed
+- Favorites menu with EPG Search favorite timers with blue key
+- Display baseline for current time
+- Added possibility to create timer from favorites results
+- left / right scroll page up / down in recmenu result lists
+- Improved favorites menu with whats on now / next and up to four user
+ defined times
+- also check default paths when images and icons are loaded
+- directory for timers can be edited in timer edit menu
+- series recording can be configured in searchtimer menus
+- directory for searchtimers can be set and edited in searchtimer menus
+- set blue key favorite mode as new default
+
+Version 1.2.0
+
+- changed video directory choosage behaviour: added possibility to use
+ a fixed recording dir which also supports epgsearch variables
+- fixed a bug when scrolling page up and the menu footer is active
+- order of search timers in search timer list in alphabetical order
+- changed order of actions on search timer menu items
+
+Version 1.2.1
+
+- changed event result lists that it is possible to scroll page up and
+ down directly with left / right. A recording is triggered now with the
+ red key.
+- Added possibility to create a recording from search timer result list
+- Set minimum time to display in Plugin Setup from 120 to 60 minutes
+- made order of search timer list case insensitive
+
+Version 1.2.2
+
+- added scraper2vdr support
+- introduced tabbed EPG detail view
diff --git a/Makefile b/Makefile
index df0ba33..27f6838 100644
--- a/Makefile
+++ b/Makefile
@@ -3,6 +3,9 @@
#
# $Id$
+# External image lib to use: imagemagick, graphicsmagick
+IMAGELIB = imagemagick
+
# 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.
@@ -21,6 +24,7 @@ LIBDIR = $(call PKGCFG,libdir)
LOCDIR = $(call PKGCFG,locdir)
PLGCFG = $(call PKGCFG,plgcfg)
VDRCONFDIR= $(call PKGCFG,configdir)
+PLGRESDIR = $(call PKGCFG,resdir)/plugins/$(PLUGIN)
TMPDIR ?= /tmp
### The compiler options:
@@ -43,17 +47,19 @@ SOFILE = libvdr-$(PLUGIN).so
### Includes and Defines (add further entries here):
-INCLUDES += $(shell pkg-config --cflags-only-I Magick++)
-
DEFINES += -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
-DEFINES += -DMAGICKCORE_HDRI_ENABLE=0
-DEFINES += -DMAGICKCORE_QUANTUM_DEPTH=16
-LIBS += $(shell pkg-config --libs Magick++)
+ifeq ($(IMAGELIB), imagemagick)
+ INCLUDES += $(shell pkg-config --cflags Magick++)
+ LIBS += $(shell pkg-config --libs Magick++)
+else ifeq ($(IMAGELIB), graphicsmagick)
+ INCLUDES += $(shell pkg-config --cflags GraphicsMagick++)
+ LIBS += $(shell pkg-config --libs GraphicsMagick++)
+endif
### The object files (add further files here):
-OBJS = $(PLUGIN).o
+OBJS = $(PLUGIN).o channelcolumn.o channelgroup.o channelgroups.o channeljump.o config.o detailview.o dummygrid.o epggrid.o fontmanager.o footer.o geometrymanager.o grid.o headergrid.o imagecache.o imageloader.o imagemagickwrapper.o imagescaler.o osdmanager.o recmanager.o recmenu.o recmenuitem.o recmenumanager.o recmenus.o searchtimer.o setup.o statusheader.o styledpixmap.o switchtimer.o timeline.o timer.o timerconflict.o tools.o tvguideosd.o view.o
### The main target:
@@ -100,6 +106,7 @@ i18n: $(I18Nmo) $(I18Npot)
install-i18n: $(I18Nmsgs)
### Targets:
+
$(SOFILE): $(OBJS)
$(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(OBJS) $(LIBS) -o $@
@@ -110,7 +117,11 @@ install-themes:
@mkdir -p $(DESTDIR)$(VDRCONFDIR)/themes
cp themes/* $(DESTDIR)$(VDRCONFDIR)/themes
-install: install-lib install-i18n install-themes
+install-icons:
+ mkdir -p $(DESTDIR)$(PLGRESDIR)/icons
+ cp -r icons/* $(DESTDIR)$(PLGRESDIR)/icons
+
+install: install-lib install-i18n install-themes install-icons
dist: $(I18Npo) clean
@-rm -rf $(TMPDIR)/$(ARCHIVE)
diff --git a/Makefile-smaller-VDR1.7.34 b/Makefile-smaller-VDR1.7.34
deleted file mode 100644
index 49b84cc..0000000
--- a/Makefile-smaller-VDR1.7.34
+++ /dev/null
@@ -1,115 +0,0 @@
-#
-# 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
diff --git a/README b/README
index 1003a21..3047018 100644
--- a/README
+++ b/README
@@ -2,9 +2,9 @@ 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
+Project's homepage: http://projects.vdr-developer.org/projects/plg-tvguide
-Latest version available at: URL
+Latest version available at: http://projects.vdr-developer.org/projects/plg-tvguide/files
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
@@ -15,36 +15,68 @@ 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
+- Clone Git Repository: git clone git://projects.vdr-developer.org/vdr-plugin-tvguide.git
+- VDR version >= 2.0.0
+- Installed ImageMagick or GraphiksMagick for showing png/jpg Channel Logos, EPG Images
+ and menu icons
+- for scaling the video picture to fit into the VDR menu window please use
+ softhddevice plugin revision 87c1c7be (2013-01-01) or newer.
+- Installed epgsearch Plugin for extended search & recording features.
+- Installed remotetimers Plugin for creating timers on a vdr server remotely from a
+ vdr client.
Description
-----------
-"TvGuide" is a highly customizable 2D EPG viewer plugin.
+"TvGuide" is a highly customizable 2D EPG viewer plugin. The "Search & Recordings"
+Menü provided by the red button allows to search in the EPG and manage timers,
+search timers, series timers and switch timers in an convenient way.
Installation
------------
-After "normal" Plugin installation copy the themes from
+After "normal" Plugin installation you have to care about the paths for the
+used Icons, the channel logos and epg images. The following paths can be set
+at startup:
-/put/your/path/here/VDR/PLUGINS/src/tvguide/themes/
+-l path, --logodir=path
+ Path to the logos (Default: <ResourceDirectory>/plugins/tvguide/channellogos/).
-to
+-e path, --epgimages=path
+ Path to the epgimages (Default: <CacheDirectory>/plugins/tvguide/epgimages/).
-VDRCONF/themes/
+-i path, --icons=path
+ Path to the icons directory (Default: <ResourceDirectory>/plugins/tvguide/epgimages/).
-Options
--------
+<ResourceDirectory> and <CacheDirectory> is taken from your VDR configuration
+(make.config or vdr.pc).
--l path, --logodir=path
- Path to the logos (Default: <vdrconfdir>/plugins/tvguide/channellogos/).
+During a "make install" the Icons are automatically copied from <PlgSourceDirectory>/icons/
+to the default path. Included Theme files are also copied from <PlgSourceDirectory>/themes/
+to <ConfigDirectory>/themes/
+
+If directories for channel logos or icons are set via startup
+parameters, images are searched first in these directories. If the image
+is not available, an additional search in the according default directory
+will be performed.
+
+I recommend to use channel logos from https://github.com/3PO/Senderlogos
+To download them just change in the directory you want to place the logos
+and do a:
--i path, --epgimages=path
- Path to the epgimages (Default: <vdrconfdir>/plugins/tvguide/epgimages/).
+git clone https://github.com/3PO/Senderlogos.git logos
+An update of the logos can then be done with a "git pull" just inside this
+directory.
+
+For S2-6400 Users: Disable High Level OSD, otherwise the plugin will not be
+loaded because lack of true color support
+
+For Xine-Plugin Users: Set "Blend scaled Auto" as OSD display mode to achieve
+an suitable true color OSD.
+
+For Xineliboutput Users: Start vdr-sxfe with the --hud option enabled
Usage
-----
@@ -54,79 +86,192 @@ 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
+Red: Search & Recording Menu
Green / Yellow: Jump (default) five channels back / forward
-Blue: Switch to currently selected channel
+Blue: Depends on configured Mode:
+ Default: Favorites Menu, Switch to channel in
+ detailed EPG View
+ Optional: Switch to currently selected channel
+ Optional: Open detailed EPG view (OK switches
+ then to channel)
+
+Numeric Keys: If Setup Option "Functionality of numeric Keys" is configured
+to "Jump to specific channel", the numeric keys are used for channel number
+input. If "Timely Jump" is configured, the keys are used as follows:
+
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
+In Search & Recording menu the following options are available:
+
+- Instant Record: create a timer for the currently selected program. An
+ check for timer conflicts will be performed, if a timer conflict occurs,
+ the involved timers can be adapted to solve the conflict. Alternatively
+ reruns can be searched and used to solve timer conflicts.
+- Delete / Edit Timer: if a timer already exists for the currently selected
+ broadcast, this timer can be deleted or edited.
+- Timer Timeline: displays active timers per day
+- Create Search Timer: create an search timer with epgsearch. The most
+ important options can be defined directly in the menu, expert options
+ are available via the "advanced options" button.
+- Manage Search Timers: edit, delete and check results of search timers
+- Create Series Timer: create a periodical timer for a dedicated time on
+ dedicated days.
+- Create Switch Timer: create a switch timer for the currently selected
+ program.
+- Search: search with epgsearch
+- Check for Timer Conflicts: check for timer conflicts with epgsearch.
+- Search in Recordings: check if a recording already exists for the currently
+ selected program.
+
+The search & recordings menu is intended to present a convenient interface
+to different VDR core recording features and additional epgsearch features.
+The main goal is to reach better usability for "non expert users".
+
+The navigation through the search & recording menu can be done easily with
+up/down, left/right and the ok key. In scrolling lists, with left/right
+(after the first/last option of the displayed list element is selected) you
+jump to the next page of the list. Pressing up on the first / down on the
+last list item jumpps to the end / start of the list.
+
+In the Plugin Setup Menu in Section "Recording Menus and Favorites" you can
+choose three alternatives for the option "Folder for instant Recordings":
+- "Always use root video folder": the recording will always be placed in the
+ video root folder
+- "Select from folder list": before creating a timer, you'll get asked in which
+ directory the recording should be placed. If the epgsearch plugin is not
+ available, the entries from VDRs <VDRCONFIG>/folders.conf will be used. If
+ the epgsearch plugin is available, the more sophisticated epgsearch mechanism
+ will be used to identify the possible folders (folders from
+ <VDRCONFIG>/folders.conf and epgsearchfolders.conf and all already existing
+ folders in the video directory).
+- "Use fixed folder": the configured folder will always be used. If this string
+ is a epgsearch variable ("%variable%"), epgsearch will be used to replace
+ the variable with a concrete folder. All values defined in the epgsearch config
+ file "epgsearchuservars.conf" can be used. These variables use the definitions
+ from "epgsearchcats.conf". For a detailed description see the epgsearch Manual.
+ With that and a with an EPG with detailed information about movies and series
+ it is possible to create sophisticated paths for timers automatically (for
+ instance with series season and episode in the filename).
+
+For a search timer also all folders and the defined dedicated folder can be used.
+
+Favorites Menu: if configured, the blue key provides a favorite menu. In this
+menu the current scheduling ("What's on now") and the next upcomming Shows
+("What's on next") can be listed. Via the Plugin Setup Menu up to four user
+defined times can be configured with a dedicated description (for instance
+"Primetime" for 8:15 pm). These user defined times are also shown as options in
+the favorites menu. Finally all search timers with the option "use as favorite"
+enabled are displayed in the favorites menu. By selecting this entry, all hits
+for this search timer are shown.
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
-
+* General Settings:
+
+- Show Main Menu Entry
+ Display "tvguide" in main menu
+- Replace VDR Schedules Menu
+ If set to "yes", the original VDR schedules menu will be replaced by tvguide
+- Use appropriate nOpacity Theme: if nOpacity is configured as VDR skin, you can
+ configure TVGuide to select the choosen nOpacity theme automatically also as
+ TVGuide theme. If the appropriate theme is not avaiable, the default theme
+ will be used. If set to "no", you can configure the theme independend of
+ nOpacity
+ - Theme: nOpacity independent theme to use
+- Time to display in minutes: period of time to display in main EPG view
+- Rounded Corners
+ Use rounded corners for displayed boxes
+- Channel Jump Mode (Keys Green / Yellow)
+ select between jumping x channels back/forward or to the previous / next
+ channel group
+- Keys Blue and OK
+ Blue: Favorites in normal view, channel switch in det. EPG View, Ok: det. EPG View
+ or
+ Blue: Channel Switch, Ok: Detailed EPG
+ or
+ Blue: Detailed EPG, Ok: Channel Switch
+- Close TVGuide after channel switch: If set to "no", tvguide will not be closed
+ after a channel switch.
+- Functionality of numeric Keys: see chapter Usage / Remote Control Keys
+- Hide last Channel Group
+ If set to yes, the channels of the last channel group will not be displayed
- Big Step (Keys 1 / 3) in hours
- Hours to jump vertically with keys 1 / 3
-
+ 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
+- Display Reruns in detailed EPG View
+
+* Screen Presentation:
+
+- Display Mode
+ Choose between horizontal or vertical display of the channels. All further
+ width / height settings are dependend of this setting
+- Width/Height of Channel Header (% of osd width/height)
+- Width/Height of Timeline (% of osd width/height)
+- Number of Channels to display
+- Height of Headers (Status Header and EPG View Header, % of osd height)
+- Height of Footer
+- Display status header
+ - Scale video to upper right corner
+ - Rounded corners around video frame
+- Display channel names in Header
+- Display channel groups
+ - Width/Height of channel groups (% of osd width/height)
+- Display current time baseline
+- Show Channel Logos
show / hide channel logos, if logos are shown:
- Logo Extension
jpg / png
- - Logo width
- in Pixel
- - Logo height
- in Pixel
-
+ - Logo width ratio
+ - Logo height ratio
+- Text Border in Detailed EPG View (in pixel)
- Show EPG Images
show / hide EPG images, if images are shown:
- - EPG Image width
- in Pixel
- - EPG Image height
- in Pixel
+ - EPG Image width ratio
+ - EPG Image height ratio
+ - Number of additional EPG Images: number of additional EPG
+ images displayed at the bottom of the detailed EPG view.
+ - Additional EPG Image width (in Pixel)
+ - Additional 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
-
+- adjust various font sizes:
+ the defined value is added to / subtracted from the default font size
+
+* Recording Menus and Favorites
+
+- Folder for instant Recordings: (see chapter "Usage" for detailed description)
+ - Always use root video folder
+ - Select from folder list
+ - Use fixed folder
+- Use Remotetimers: Timers are handled not locally but on a VDR Server defined
+ with the remotetimers plugin.
+- Use "What's on now" in favorites
+- Use "What's on next" in favorites
+- Use user defined time 1 (to 4) in favorites
+ - Description (1 - 4)
+ - Time (1 - 4)
+- Limit channels in favorites: if set to yes, only the configured channel range
+ is used to display favorite results (except for search timer favorites)
+ - start channel
+ - stop channel
+
+* Image Caching
+
+- Create Log Messages for image loading: enable debug messages for image loading
+- Limit Logo Cache: if set to "no", every channel logo is cached. if set to "yes",
+ only the amount configured for "Maximal number of logos to cache" is cached, all
+ other logos are always loaded "on the fly"
+ - Maximal number of logos to cache
+- Number of logos to cache at start: number of logos to pre cache at plugin startup
+ (a too large number causes a slower VDR start)
+- Information about image cache sizes
\ No newline at end of file
diff --git a/channelcolumn.c b/channelcolumn.c
index 5590ce3..c23fbe6 100644
--- a/channelcolumn.c
+++ b/channelcolumn.c
@@ -1,283 +1,367 @@
#include "channelcolumn.h"
+#include "dummygrid.h"
-cChannelColumn::cChannelColumn(int num, cChannel *channel, cMyTime *myTime) {
- this->channel = channel;
- this->num = num;
- this->myTime = myTime;
- hasTimer = channel->HasTimer();
+cChannelColumn::cChannelColumn(int num, const cChannel *channel, cMyTime *myTime) {
+ this->channel = channel;
+ this->num = num;
+ this->myTime = myTime;
+ hasTimer = channel->HasTimer();
+ hasSwitchTimer = SwitchTimers.ChannelInSwitchList(channel);
+ schedulesLock = new cSchedulesLock(false, 100);
+ header = NULL;
}
cChannelColumn::~cChannelColumn(void) {
- osdManager.releasePixmap(pixmapLogo, cString::sprintf("channelcolumn logo %s", channel->Name()));
- grids.Clear();
+ if (header)
+ delete header;
+ grids.Clear();
+ delete schedulesLock;
}
void cChannelColumn::clearGrids() {
- grids.Clear();
+ 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;
- }
- pixmapLogo = osdManager.requestPixmap(3, cRect(tvguideConfig.timeColWidth + num*tvguideConfig.colWidth, 0, tvguideConfig.colWidth, tvguideConfig.headerHeight),
- cRect::Null, *caller);
- if (!pixmapLogo) {
- return;
- }
- pixmapLogo->Fill(clrTransparent);
-
- 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;
- pixmapLogo->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();
+ header = new cHeaderGrid();
+ header->createBackground(num);
+ header->drawChannel(channel);
}
void cChannelColumn::drawHeader() {
- pixmap->SetViewPort(cRect(tvguideConfig.timeColWidth + num*tvguideConfig.colWidth, 0, tvguideConfig.colWidth, tvguideConfig.headerHeight));
- pixmapLogo->SetViewPort(cRect(tvguideConfig.timeColWidth + num*tvguideConfig.colWidth, 0, tvguideConfig.colWidth, tvguideConfig.headerHeight));
+ header->setPosition(num);
}
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;
- }
-
+ schedules = cSchedules::Schedules(*schedulesLock);
+ const cSchedule *Schedule = NULL;
+ Schedule = schedules->GetSchedule(channel);
+ if (!Schedule) {
+ addDummyGrid(myTime->GetStart(), myTime->GetEnd(), NULL, false);
+ return true;
+ }
+ bool eventFound = false;
+ bool dummyAtStart = false;
+ const cEvent *startEvent = Schedule->GetEventAround(myTime->GetStart());
+ if (startEvent != NULL) {
+ eventFound = true;
+ } else {
+ for (int i=1; i<6; i++) {
+ startEvent = Schedule->GetEventAround(myTime->GetStart()+i*5*60);
+ if (startEvent) {
+ eventFound = true;
+ dummyAtStart = true;
+ break;
+ }
+ }
+ }
+ if (eventFound) {
+ bool col = true;
+ if (dummyAtStart) {
+ addDummyGrid(myTime->GetStart(), startEvent->StartTime(), NULL, col);
+ col = !col;
+ }
+ bool dummyNeeded = true;
+ bool toFarInFuture = false;
+ time_t endLast = myTime->GetStart();
+ const cEvent *event = startEvent;
+ const cEvent *eventLast = NULL;
+ for (; event; event = Schedule->Events()->Next(event)) {
+ if (endLast < event->StartTime()) {
+ //gap, dummy needed
+ time_t endTime = event->StartTime();
+ if (endTime > myTime->GetEnd()) {
+ endTime = myTime->GetEnd();
+ toFarInFuture = true;
+ }
+ addDummyGrid(endLast, endTime, NULL, col);
+ col = !col;
+ }
+ if (toFarInFuture) {
+ break;
+ }
+ addEpgGrid(event, NULL, col);
+ col = !col;
+ endLast = event->EndTime();
+ if (event->EndTime() > myTime->GetEnd()) {
+ dummyNeeded = false;
+ break;
+ }
+ eventLast = event;
+ }
+ if (dummyNeeded) {
+ addDummyGrid(eventLast->EndTime(), myTime->GetEnd(), NULL, col);
+ }
+ return true;
+ } else {
+ addDummyGrid(myTime->GetStart(), myTime->GetEnd(), NULL, false);
+ return true;
+ }
+ return false;
}
void cChannelColumn::drawGrids() {
- for (cEpgGrid *grid = grids.First(); grid; grid = grids.Next(grid)) {
- grid->SetViewportHeight();
- grid->PositionPixmap();
- grid->Draw();
- }
+ for (cGrid *grid = grids.First(); grid; grid = grids.Next(grid)) {
+ grid->SetViewportHeight();
+ grid->PositionPixmap();
+ grid->Draw();
+ }
}
int cChannelColumn::getX() {
- return tvguideConfig.timeColWidth + num*tvguideConfig.colWidth;
+ return geoManager.timeLineWidth + num*geoManager.colWidth;
+}
+
+int cChannelColumn::getY() {
+ return geoManager.statusHeaderHeight + geoManager.timeLineHeight + num*geoManager.rowHeight;
}
-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();
+cGrid * cChannelColumn::getActive() {
+ cMyTime t;
+ t.Now();
+ for (cGrid *grid = grids.First(); grid; grid = grids.Next(grid)) {
+ if (grid->Match(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;
+cGrid * cChannelColumn::getNext(cGrid *activeGrid) {
+ if (activeGrid == NULL)
+ return NULL;
+ cGrid *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;
+cGrid * cChannelColumn::getPrev(cGrid *activeGrid) {
+ if (activeGrid == NULL)
+ return NULL;
+ cGrid *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;
+cGrid * cChannelColumn::getNeighbor(cGrid *activeGrid) {
+ if (!activeGrid)
+ return NULL;
+ cGrid *neighbor = NULL;
+ int overlap = 0;
+ int overlapNew = 0;
+ cGrid *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;
+}
+
+bool cChannelColumn::isFirst(cGrid *grid) {
+ if (grid == grids.First())
+ return true;
+ return false;
}
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;
- }
- }
- }
+ cGrid *firstGrid = NULL;
+ firstGrid = grids.First();
+ if (firstGrid == NULL)
+ return;
+ //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) {
+ if (firstGrid->isDummy()) {
+ firstGrid->SetStartTime(myTime->GetStart());
+ firstGrid->SetEndTime(myTime->GetEnd());
+ }
+ return;
+ }
+ bool col = !(firstGrid->IsColor1());
+ bool dummyNeeded = true;
+ for (const cEvent *event = Schedule->GetEventAround(firstGrid->StartTime()-60); event; event = Schedule->Events()->Prev(event)) {
+ if (!event)
+ break;
+ if (event->EndTime() < myTime->GetStart()) {
+ break;
+ }
+ cGrid *grid = addEpgGrid(event, firstGrid, col);
+ col = !col;
+ firstGrid = grid;
+ if (event->StartTime() <= myTime->GetStart()) {
+ dummyNeeded = false;
+ break;
+ }
+ }
+ if (dummyNeeded) {
+ firstGrid = grids.First();
+ if (firstGrid->isDummy()) {
+ firstGrid->SetStartTime(myTime->GetStart());
+ if (firstGrid->EndTime() >= myTime->GetEnd())
+ firstGrid->SetEndTime(myTime->GetEnd());
+ } else {
+ addDummyGrid(myTime->GetStart(), firstGrid->StartTime(), firstGrid, col);
+ }
+ }
}
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;
- }
- }
+ cGrid *lastGrid = NULL;
+ lastGrid = grids.Last();
+ if (lastGrid == NULL)
+ return;
+ //if last event is long enough, nothing to do.
+ if (lastGrid->EndTime() >= myTime->GetEnd()) {
+ 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) {
+ if (lastGrid->isDummy()) {
+ lastGrid->SetStartTime(myTime->GetStart());
+ lastGrid->SetEndTime(myTime->GetEnd());
+ }
+ return;
+ }
+ bool col = !(lastGrid->IsColor1());
+ bool dummyNeeded = true;
+ for (const cEvent *event = Schedule->GetEventAround(lastGrid->EndTime()+60); event; event = Schedule->Events()->Next(event)) {
+ if (!event)
+ break;
+ if (event->StartTime() > myTime->GetEnd()) {
+ break;
+ }
+ addEpgGrid(event, NULL, col);
+ col = !col;
+ if (event->EndTime() > myTime->GetEnd()) {
+ dummyNeeded = false;
+ break;
+ }
+ }
+ if (dummyNeeded) {
+ lastGrid = grids.Last();
+ if (lastGrid->isDummy()) {
+ lastGrid->SetEndTime(myTime->GetEnd());
+ if (lastGrid->StartTime() <= myTime->GetStart())
+ lastGrid->SetStartTime(myTime->GetStart());
+ } else {
+ addDummyGrid(lastGrid->EndTime(), myTime->GetEnd(), NULL, col);
+ }
+ }
}
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;
- }
- }
+ cGrid *firstGrid = NULL;
+ while (true) {
+ firstGrid = grids.First();
+ if (!firstGrid)
+ break;
+ if (firstGrid->EndTime() <= myTime->GetStart()) {
+ grids.Del(firstGrid);
+ firstGrid = NULL;
+ } else {
+ if (firstGrid->isDummy()) {
+ firstGrid->SetStartTime(myTime->GetStart());
+ cGrid *next = getNext(firstGrid);
+ if (next) {
+ firstGrid->SetEndTime(next->StartTime());
+ } else {
+ firstGrid->SetEndTime(myTime->GetEnd());
+ }
+ }
+ break;
+ }
+ }
}
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;
- }
- }
+ cGrid *lastGrid = NULL;
+ while (true) {
+ lastGrid = grids.Last();
+ if (!lastGrid)
+ break;
+ if (lastGrid->StartTime() >= myTime->GetEnd()) {
+ grids.Del(lastGrid);
+ lastGrid = NULL;
+ } else {
+ if (lastGrid->isDummy()) {
+ lastGrid->SetEndTime(myTime->GetEnd());
+ cGrid *prev = getPrev(lastGrid);
+ if (prev) {
+ lastGrid->SetStartTime(prev->EndTime());
+ } else {
+ lastGrid->SetStartTime(myTime->GetStart());
+ }
+ }
+ break;
+ }
+ }
}
-void cChannelColumn::dumpGrids() {
- esyslog("------Channel %s ---------", channel->Name());
-
- for (cEpgGrid *grid = grids.First(); grid; grid = grids.Next(grid)) {
- grid->debug();
- }
-
+cGrid *cChannelColumn::addEpgGrid(const cEvent *event, cGrid *firstGrid, bool color) {
+ cGrid *grid = new cEpgGrid(this, event);
+ grid->setText();
+ grid->SetColor(color);
+ if (!firstGrid)
+ grids.Add(grid);
+ else
+ grids.Ins(grid, firstGrid);
+ return grid;
}
+
+cGrid *cChannelColumn::addDummyGrid(time_t start, time_t end, cGrid *firstGrid, bool color) {
+ cGrid *dummy = new cDummyGrid(this, start, end);
+ dummy->setText();
+ dummy->SetColor(color);
+ if (!firstGrid)
+ grids.Add(dummy);
+ else
+ grids.Ins(dummy, firstGrid);
+ return dummy;
+}
+
+void cChannelColumn::SetTimers() {
+ hasTimer = channel->HasTimer();
+ hasSwitchTimer = SwitchTimers.ChannelInSwitchList(channel);
+ for (cGrid *grid = grids.First(); grid; grid = grids.Next(grid)) {
+ bool gridHadTimer = grid->HasTimer();
+ grid->SetTimer();
+ if (gridHadTimer != grid->HasTimer())
+ grid->SetDirty();
+ bool gridHadSwitchTimer = grid->HasSwitchTimer();
+ grid->SetSwitchTimer();
+ if (gridHadSwitchTimer != grid->HasSwitchTimer())
+ grid->SetDirty();
+ grid->Draw();
+ }
+}
+
+void cChannelColumn::dumpGrids() {
+ esyslog("tvguide: ------Channel %s %d: %d entires ---------", channel->Name(), num, grids.Count());
+ int i=1;
+ for (cGrid *grid = grids.First(); grid; grid = grids.Next(grid)) {
+ esyslog("tvguide: grid %d: start: %s, stop: %s", i, *cMyTime::printTime(grid->StartTime()), *cMyTime::printTime(grid->EndTime()));
+ i++;
+ }
+}
\ No newline at end of file
diff --git a/channelcolumn.h b/channelcolumn.h
index 2b1fdbd..0e1d138 100644
--- a/channelcolumn.h
+++ b/channelcolumn.h
@@ -1,42 +1,62 @@
#ifndef __TVGUIDE_CHANNELCOLUMN_H
#define __TVGUIDE_CHANNELCOLUMN_H
+#include <vdr/tools.h>
+#include "grid.h"
+#include "epggrid.h"
+#include "headergrid.h"
+#include "switchtimer.h"
+
+class cGrid;
class cEpgGrid;
+class cHeaderGrid;
+
// --- cChannelColumn -------------------------------------------------------------
class cChannelColumn : public cListObject, public cStyledPixmap {
-friend class cEpgGrid;
private:
- cPixmap *pixmapLogo;
- cMyTime *myTime;
- int num;
- cChannel *channel;
- cList<cEpgGrid> grids;
- cSchedulesLock schedulesLock;
- const cSchedules *schedules;
- bool hasTimer;
+ cMyTime *myTime;
+ int num;
+ const cChannel *channel;
+ cHeaderGrid *header;
+ cList<cGrid> grids;
+ cSchedulesLock *schedulesLock;
+ const cSchedules *schedules;
+ bool hasTimer;
+ bool hasSwitchTimer;
+ cGrid *addEpgGrid(const cEvent *event, cGrid *firstGrid, bool color);
+ cGrid *addDummyGrid(time_t start, time_t end, cGrid *firstGrid, bool color);
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();
+ cChannelColumn(int num, const cChannel *channel, cMyTime *myTime);
+ virtual ~cChannelColumn(void);
+ void createHeader();
+ void drawHeader();
+ bool readGrids();
+ void drawGrids();
+ int getX();
+ int getY();
+ int Start() { return myTime->GetStart(); };
+ int Stop() { return myTime->GetEnd(); };
+ const char* Name() { return channel->Name(); };
+ const cChannel * getChannel() {return channel;}
+ cGrid * getActive();
+ cGrid * getNext(cGrid *activeGrid);
+ cGrid * getPrev(cGrid *activeGrid);
+ cGrid * getNeighbor(cGrid *activeGrid);
+ bool isFirst(cGrid *grid);
+ void AddNewGridsAtStart();
+ void AddNewGridsAtEnd();
+ void ClearOutdatedStart();
+ void ClearOutdatedEnd();
+ int GetNum() {return num;};
+ void SetNum(int num) {this->num = num;};
+ void setTimer() {hasTimer = channel->HasTimer();};
+ bool HasTimer() { return hasTimer; };
+ void setSwitchTimer() {hasSwitchTimer = SwitchTimers.ChannelInSwitchList(channel);};
+ bool HasSwitchTimer() { return hasSwitchTimer; };
+ void SetTimers();
+ void clearGrids();
+ void dumpGrids();
};
-#endif //__TVGUIDE_CHANNELCOLUMN_H
\ No newline at end of file
+#endif //__TVGUIDE_CHANNELCOLUMN_H
diff --git a/channelgroup.c b/channelgroup.c
new file mode 100644
index 0000000..3278f8c
--- /dev/null
+++ b/channelgroup.c
@@ -0,0 +1,98 @@
+#include <algorithm>
+#include "channelgroup.h"
+#include "tools.h"
+
+cChannelGroup::cChannelGroup(const char *name) {
+ channelStart = 0;
+ channelStop = 0;
+ this->name = name;
+}
+
+cChannelGroup::~cChannelGroup(void) {
+}
+
+void cChannelGroup::Dump(void) {
+ esyslog("tvguide: Group %s, startChannel %d, stopChannel %d", name, channelStart, channelStop);
+}
+
+// --- cChannelGroupGrid -------------------------------------------------------------
+
+cChannelGroupGrid::cChannelGroupGrid(const char *name) {
+ this->name = name;
+}
+
+cChannelGroupGrid::~cChannelGroupGrid(void) {
+}
+
+void cChannelGroupGrid::SetBackground() {
+ if (isColor1) {
+ color = theme.Color(clrGrid1);
+ colorBlending = theme.Color(clrGrid1Blending);
+ } else {
+ color = theme.Color(clrGrid2);
+ colorBlending = theme.Color(clrGrid2Blending);
+ }
+}
+
+void cChannelGroupGrid::SetGeometry(int start, int end) {
+ int x, y, width, height;
+ if (tvguideConfig.displayMode == eVertical) {
+ x = geoManager.timeLineWidth + start*geoManager.colWidth;
+ y = geoManager.statusHeaderHeight;
+ width = (end - start + 1) * geoManager.colWidth;
+ height = geoManager.channelGroupsHeight;
+ } else if (tvguideConfig.displayMode == eHorizontal) {
+ x = 0;
+ y = geoManager.statusHeaderHeight + geoManager.timeLineHeight + start*geoManager.rowHeight;
+ width = geoManager.channelGroupsWidth;
+ height = (end - start + 1) * geoManager.rowHeight;
+ }
+ pixmap = osdManager.requestPixmap(1, cRect(x, y, width, height));
+}
+
+void cChannelGroupGrid::Draw(void) {
+ if (tvguideConfig.style == eStyleGraphical) {
+ drawBackgroundGraphical(bgChannelGroup);
+ } else {
+ drawBackground();
+ drawBorder();
+ }
+ tColor colorText = theme.Color(clrFont);
+ tColor colorTextBack = (tvguideConfig.style == eStyleFlat)?color:clrTransparent;
+ if (tvguideConfig.displayMode == eVertical) {
+ DrawVertical(colorText, colorTextBack);
+ } else if (tvguideConfig.displayMode == eHorizontal) {
+ DrawHorizontal(colorText, colorTextBack);
+ }
+}
+
+void cChannelGroupGrid::DrawVertical(tColor colorText, tColor colorTextBack) {
+ int textY = (Height() - fontManager.FontChannelGroups->Height()) / 2;
+ cString text = CutText(name, Width() - 4, fontManager.FontChannelGroups).c_str();
+ int textWidth = fontManager.FontChannelGroups->Width(*text);
+ int x = (Width() - textWidth) / 2;
+ pixmap->DrawText(cPoint(x, textY), *text, colorText, colorTextBack, fontManager.FontChannelGroups);
+}
+
+void cChannelGroupGrid::DrawHorizontal(tColor colorText, tColor colorTextBack) {
+ std::string nameUpper = name;
+ std::transform(nameUpper.begin(), nameUpper.end(),nameUpper.begin(), ::toupper);
+ int numChars = nameUpper.length();
+ int charHeight = fontManager.FontChannelGroupsHorizontal->Height();
+ int textHeight = numChars * charHeight;
+ int y = 5;
+ if ((textHeight +5) < Height()) {
+ y = (Height() - textHeight) / 2;
+ }
+ for (int i=0; i < numChars; i++) {
+ if (((y + 2*charHeight) > Height()) && ((i+1)<numChars)) {
+ int x = (Width() - fontManager.FontChannelGroupsHorizontal->Width("...")) / 2;
+ pixmap->DrawText(cPoint(x, y), "...", colorText, colorTextBack, fontManager.FontChannelGroupsHorizontal);
+ break;
+ }
+ cString currentChar = cString::sprintf("%c", nameUpper.at(i));
+ int x = (Width() - fontManager.FontChannelGroupsHorizontal->Width(*currentChar)) / 2;
+ pixmap->DrawText(cPoint(x, y), *currentChar, colorText, colorTextBack, fontManager.FontChannelGroupsHorizontal);
+ y += fontManager.FontChannelGroupsHorizontal->Height();
+ }
+}
diff --git a/channelgroup.h b/channelgroup.h
new file mode 100644
index 0000000..e09f6de
--- /dev/null
+++ b/channelgroup.h
@@ -0,0 +1,44 @@
+#ifndef __TVGUIDE_CHANNELGROUP_H
+#define __TVGUIDE_CHANNELGROUP_H
+
+#include <vdr/tools.h>
+#include "styledpixmap.h"
+
+
+// --- cChannelGroup -------------------------------------------------------------
+
+class cChannelGroup {
+private:
+ int channelStart;
+ int channelStop;
+ const char *name;
+public:
+ cChannelGroup(const char *name);
+ virtual ~cChannelGroup(void);
+ void SetChannelStart(int start) { channelStart = start; };
+ int StartChannel(void) { return channelStart; };
+ void SetChannelStop(int stop) { channelStop = stop; };
+ int StopChannel(void) { return channelStop; };
+ const char* GetName(void) { return name; };
+ void Dump(void);
+};
+
+// --- cChannelGroupGrid -------------------------------------------------------------
+
+class cChannelGroupGrid : public cListObject, public cStyledPixmap {
+private:
+ const char *name;
+ bool isColor1;
+ void DrawHorizontal(tColor colorText, tColor colorTextBack);
+ void DrawVertical(tColor colorText, tColor colorTextBack);
+public:
+ cChannelGroupGrid(const char *name);
+ virtual ~cChannelGroupGrid(void);
+ void SetColor(bool color) {isColor1 = color;};
+ void SetBackground(void);
+ void SetGeometry(int start, int end);
+ void Draw(void);
+};
+
+
+#endif //__TVGUIDE_CHANNELGROUP_H
\ No newline at end of file
diff --git a/channelgroups.c b/channelgroups.c
new file mode 100644
index 0000000..6767cee
--- /dev/null
+++ b/channelgroups.c
@@ -0,0 +1,143 @@
+#include <vector>
+#include "channelgroups.h"
+
+cChannelGroups::cChannelGroups(void) {
+}
+
+cChannelGroups::~cChannelGroups(void) {
+}
+
+void cChannelGroups::ReadChannelGroups(void) {
+ bool setStart = false;
+ int lastChannelNumber = 0;
+ const cChannel *first = Channels.First();
+ if (!first->GroupSep()) {
+ channelGroups.push_back(cChannelGroup(tr("Main Program")));
+ setStart = true;
+ }
+ for (const cChannel *channel = Channels.First(); channel; channel = Channels.Next(channel)) {
+ if (setStart && (channelGroups.size() > 0)) {
+ channelGroups[channelGroups.size()-1].SetChannelStart(channel->Number());
+ setStart = false;
+ }
+ if (channel->GroupSep()) {
+ if (channelGroups.size() > 0) {
+ channelGroups[channelGroups.size()-1].SetChannelStop(lastChannelNumber);
+ }
+ channelGroups.push_back(cChannelGroup(channel->Name()));
+ setStart = true;
+ } else {
+ lastChannelNumber = channel->Number();
+ }
+ }
+ if (channelGroups.size() > 0) {
+ channelGroups[channelGroups.size()-1].SetChannelStop(lastChannelNumber);
+ if ((tvguideConfig.hideLastGroup)&&(channelGroups.size() > 1)) {
+ channelGroups.pop_back();
+ }
+ }
+}
+
+int cChannelGroups::GetGroup(const cChannel *channel) {
+ int channelNumber = channel->Number();
+ int numGroups = channelGroups.size();
+ if (numGroups) {
+ for (int i=0; i<numGroups; i++) {
+ if ((channelGroups[i].StartChannel() <= channelNumber) && ((channelGroups[i].StopChannel() >= channelNumber))) {
+ return i;
+ }
+ }
+ }
+ return -1;
+}
+
+const char* cChannelGroups::GetPrev(int group) {
+ if (group > 0) {
+ return channelGroups[group-1].GetName();
+ }
+ return "";
+}
+
+const char* cChannelGroups::GetNext(int group) {
+ if (group > -1) {
+ if ((group+1) < channelGroups.size())
+ return channelGroups[group+1].GetName();
+ }
+ return "";
+}
+
+int cChannelGroups::GetPrevGroupChannelNumber(const cChannel *channel) {
+ int currentGroup = GetGroup(channel);
+ if (currentGroup == -1)
+ return 0;
+ if (currentGroup > 0) {
+ return channelGroups[currentGroup-1].StartChannel();
+ }
+ return 0;
+}
+
+int cChannelGroups::GetNextGroupChannelNumber(const cChannel *channel) {
+ int currentGroup = GetGroup(channel);
+ if (currentGroup == -1)
+ return 0;
+ if ((currentGroup+1) < channelGroups.size()) {
+ return channelGroups[currentGroup+1].StartChannel();
+ }
+ return 0;
+}
+
+bool cChannelGroups::IsInLastGroup(const cChannel *channel) {
+ if (!tvguideConfig.hideLastGroup)
+ return false;
+ if (channelGroups.size() > 0) {
+ if (channel->Number() > channelGroups[channelGroups.size()-1].StopChannel()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void cChannelGroups::DrawChannelGroups(const cChannel *start, const cChannel *stop) {
+ groupGrids.Clear();
+ int group = GetGroup(start);
+ int groupLast = group;
+ int line = 0;
+ int lineStart = 0;
+ for (const cChannel *channel = Channels.Next(start); channel; channel = Channels.Next(channel)) {
+ if (channel->GroupSep())
+ continue;
+ group = GetGroup(channel);
+ if (group != groupLast) {
+ CreateGroupGrid(channelGroups[groupLast].GetName(), group, lineStart, line);
+ lineStart = line + 1;
+ }
+ line++;
+ groupLast = group;
+ if (channel == stop) {
+ CreateGroupGrid(channelGroups[groupLast].GetName(), group+1, lineStart, line);
+ break;
+ }
+ }
+
+}
+
+void cChannelGroups::CreateGroupGrid(const char *name, int number, int start, int end) {
+ cChannelGroupGrid *groupGrid = new cChannelGroupGrid(name);
+ groupGrid->SetColor(number%2);
+ groupGrid->SetBackground();
+ groupGrid->SetGeometry(start, end);
+ groupGrid->Draw();
+ groupGrids.Add(groupGrid);
+}
+
+int cChannelGroups::GetLastValidChannel(void) {
+ if (channelGroups.size() > 0)
+ return channelGroups[channelGroups.size()-1].StopChannel();
+ return 0;
+}
+
+void cChannelGroups::DumpGroups(void) {
+ for (std::vector<cChannelGroup>::iterator group = channelGroups.begin(); group!=channelGroups.end(); ++group) {
+ group->Dump();
+ }
+}
diff --git a/channelgroups.h b/channelgroups.h
new file mode 100644
index 0000000..02b146d
--- /dev/null
+++ b/channelgroups.h
@@ -0,0 +1,30 @@
+#ifndef __TVGUIDE_CHANNELGROUPS_H
+#define __TVGUIDE_CHANNELGROUPS_H
+
+#include <vector>
+#include <vdr/channels.h>
+#include "channelgroup.h"
+
+// --- cChannelGroups -------------------------------------------------------------
+
+class cChannelGroups {
+private:
+ std::vector<cChannelGroup> channelGroups;
+ cList<cChannelGroupGrid> groupGrids;
+public:
+ cChannelGroups(void);
+ virtual ~cChannelGroups(void);
+ void ReadChannelGroups(void);
+ const char* GetPrev(int group);
+ const char* GetNext(int group);
+ int GetGroup(const cChannel *channel);
+ int GetPrevGroupChannelNumber(const cChannel *channel);
+ int GetNextGroupChannelNumber(const cChannel *channel);
+ bool IsInLastGroup(const cChannel *channel);
+ void DrawChannelGroups(const cChannel *start, const cChannel *stop);
+ void CreateGroupGrid(const char *name, int number, int start, int end);
+ int GetLastValidChannel(void);
+ void DumpGroups(void);
+};
+
+#endif //__TVGUIDE_CHANNELGROUPS_H
diff --git a/channeljump.c b/channeljump.c
new file mode 100644
index 0000000..58fa77f
--- /dev/null
+++ b/channeljump.c
@@ -0,0 +1,90 @@
+#include <vdr/channels.h>
+#include "config.h"
+#include "geometrymanager.h"
+#include "osdmanager.h"
+#include "fontmanager.h"
+#include "channelgroups.h"
+#include "channeljump.h"
+
+cChannelJump::cChannelJump(cChannelGroups *channelGroups) {
+ this->channelGroups = channelGroups;
+ pixmapText = NULL;
+ channel = 0;
+ if (!tvguideConfig.hideLastGroup) {
+ maxChannels = Channels.MaxNumber();
+ } else {
+ maxChannels = channelGroups->GetLastValidChannel();
+ }
+ timeout = Setup.ChannelEntryTimeout;
+ startTime = cTimeMs::Now();
+ SetPixmaps();
+ Draw();
+}
+
+cChannelJump::~cChannelJump(void) {
+ osdManager.releasePixmap(pixmapBack);
+ osdManager.releasePixmap(pixmapText);
+}
+
+void cChannelJump::SetPixmaps(void) {
+ int x = (geoManager.osdWidth - geoManager.channelJumpWidth)/2;
+ int y = (geoManager.osdHeight - geoManager.channelJumpHeight)/2;
+
+ pixmapBack = osdManager.requestPixmap(4, cRect(x, y, geoManager.channelJumpWidth, geoManager.channelJumpHeight));
+ pixmap = osdManager.requestPixmap(5, cRect(x, y, geoManager.channelJumpWidth, geoManager.channelJumpHeight));
+ pixmapText = osdManager.requestPixmap(6, cRect(x, y, geoManager.channelJumpWidth, geoManager.channelJumpHeight));
+}
+
+void cChannelJump::Draw(void) {
+ if (tvguideConfig.style == eStyleGraphical) {
+ drawBackgroundGraphical(bgChannelJump);
+ } else {
+ pixmap->Fill(theme.Color(clrBackground));
+ drawBorder();
+ }
+ pixmapBack->Fill(clrTransparent);
+ pixmapBack->DrawRectangle(cRect(5, Height()/2, Width()-10, Height()-3), theme.Color(clrBackground));
+}
+
+void cChannelJump::DrawText(void) {
+ pixmapText->Fill(clrTransparent);
+
+ cString header = cString::sprintf("%s:", tr("Channel"));
+
+ const cFont *font = fontManager.FontMessageBox;
+ const cFont *fontHeader = fontManager.FontMessageBoxLarge;
+
+ int xHeader = (Width() - fontHeader->Width(*header)) / 2;
+ int yHeader = (Height()/2 - fontHeader->Height()) / 2;
+ pixmapText->DrawText(cPoint(xHeader, yHeader), *header, theme.Color(clrFont), clrTransparent, fontHeader);
+
+ cString strChannel = BuildChannelString();
+ int xChannel = (Width() - font->Width(*strChannel)) / 2;
+ int yChannel = Height()/2 + (Height()/2 - font->Height()) / 2;
+ pixmapText->DrawText(cPoint(xChannel, yChannel), *strChannel, theme.Color(clrFont), clrTransparent, font);
+
+}
+
+void cChannelJump::Set(int num) {
+ startTime = cTimeMs::Now();
+ if (channel == 0) {
+ channel = num;
+ return;
+ }
+ int newChannel = channel * 10 + num;
+ if (newChannel <= maxChannels)
+ channel = newChannel;
+}
+
+cString cChannelJump::BuildChannelString(void) {
+ if (channel*10 <= maxChannels)
+ return cString::sprintf("%d-", channel);
+ else
+ return cString::sprintf("%d", channel);
+}
+
+ bool cChannelJump::TimeOut(void) {
+ if ((cTimeMs::Now() - startTime) > timeout)
+ return true;
+ return false;
+ }
\ No newline at end of file
diff --git a/channeljump.h b/channeljump.h
new file mode 100644
index 0000000..6bb988f
--- /dev/null
+++ b/channeljump.h
@@ -0,0 +1,29 @@
+#ifndef __TVGUIDE_CHANNELJUMP_H
+#define __TVGUIDE_CHANNELJUMP_H
+
+#include "styledpixmap.h"
+
+// --- cChannelJump -------------------------------------------------------------
+
+class cChannelJump : public cStyledPixmap {
+private:
+ int channel;
+ cChannelGroups *channelGroups;
+ int maxChannels;
+ int startTime;
+ int timeout;
+ cPixmap *pixmapBack;
+ cPixmap *pixmapText;
+ void SetPixmaps(void);
+ void Draw(void);
+ cString BuildChannelString(void);
+public:
+ cChannelJump(cChannelGroups *channelGroups);
+ virtual ~cChannelJump(void);
+ void Set(int num);
+ void DrawText(void);
+ bool TimeOut(void);
+ int GetChannel(void) { return channel; };
+};
+
+#endif //__TVGUIDE_CHANNELJUMP_H
\ No newline at end of file
diff --git a/config.c b/config.c
index c146d53..76d01c7 100644
--- a/config.c
+++ b/config.c
@@ -1,176 +1,334 @@
+#include <string>
#include "config.h"
-enum {
- e12Hours,
- e24Hours
-};
-
cTvguideConfig::cTvguideConfig() {
- osdWidth = 0;
- osdHeight = 0;
- colWidth = 0;
- channelCols = 5;
- displayTime = 160;
- minuteHeight = 0;
- timeColWidth = 120;
- headerHeight = 150;
- footerHeight = 80;
- stepMinutes = 30;
- bigStepHours = 3;
- hugeStepHours = 24;
- jumpChannels = 5;
- hideChannelLogos = 0;
- logoWidth = 130;
- logoHeight = 100;
- 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;
+ debugImageLoading = 0;
+ showMainMenuEntry = 1;
+ replaceOriginalSchedule = 0;
+ displayMode = eHorizontal;
+ showTimeInGrid = 1;
+ channelCols = 5;
+ channelRows = 10;
+ displayTime = 160;
+ displayStatusHeader = 1;
+ displayChannelGroups = 1;
+ displayTimeBase = 1;
+ headerHeightPercent = 20;
+ channelGroupsPercent = 5;
+ epgViewBorder = 50;
+ scaleVideo = 1;
+ decorateVideo = 1;
+ timeLineWidthPercent = 8;
+ timeLineHeightPercent = 4;
+ displayChannelName = 1;
+ channelHeaderWidthPercent = 20;
+ channelHeaderHeightPercent = 15;
+ footerHeightPercent = 7;
+ stepMinutes = 30;
+ bigStepHours = 3;
+ hugeStepHours = 24;
+ channelJumpMode = eNumJump;
+ jumpChannels = 0;
+ blueKeyMode = 2;
+ closeOnSwitch = 1;
+ numkeyMode = 0;
+ useRemoteTimers = 0;
+ hideLastGroup = 0;
+ hideChannelLogos = 0;
+ logoWidthRatio = 13;
+ logoHeightRatio = 10;
+ logoExtension = 0;
+ hideEpgImages = 0;
+ epgImageWidth = 315;
+ epgImageHeight = 240;
+ numAdditionalEPGPictures = 9;
+ epgImageWidthLarge = 525;
+ epgImageHeightLarge = 400;
+ detailedViewScrollStep = 5;
+ instRecFolderMode = eFolderRoot;
+ instRecFixedFolder = "";
+ favWhatsOnNow = 1;
+ favWhatsOnNext = 1;
+ favUseTime1 = 0;
+ favUseTime2 = 0;
+ favUseTime3 = 0;
+ favUseTime4 = 0;
+ favTime1 = 0;
+ favTime2 = 0;
+ favTime3 = 0;
+ favTime4 = 0;
+ descUser1 = "";
+ descUser2 = "";
+ descUser3 = "";
+ descUser4 = "";
+ favLimitChannels = 0;
+ favStartChannel = 0;
+ favStopChannel = 0;
+ fontIndex = 0;
+ fontNameDefault = "VDRSymbols Sans:Book";
+ FontButtonDelta = 0;
+ FontDetailViewDelta = 0;
+ FontDetailViewSmallDelta = 0;
+ FontDetailHeaderDelta = 0;
+ FontMessageBoxDelta = 0;
+ FontMessageBoxLargeDelta = 0;
+ FontStatusHeaderDelta = 0;
+ FontStatusHeaderLargeDelta = 0;
+ FontChannelHeaderDelta = 0;
+ FontChannelGroupsDelta = 0;
+ FontGridDelta = 0;
+ FontGridSmallDelta = 0;
+ FontTimeLineWeekdayDelta = 0;
+ FontTimeLineDateDelta = 0;
+ FontTimeLineTimeDelta = 0;
+ FontChannelHeaderHorizontalDelta = 0;
+ FontChannelGroupsHorizontalDelta = 0;
+ FontGridHorizontalDelta = 0;
+ FontGridHorizontalSmallDelta = 0;
+ FontTimeLineDateHorizontalDelta = 0;
+ FontTimeLineTimeHorizontalDelta = 0;
+ FontRecMenuItemDelta = 0;
+ FontRecMenuItemSmallDelta = 0;
+ FontRecMenuItemLargeDelta = 0;
+ timeFormat = 1;
+ useNopacityTheme = 1;
+ themeIndex = -1;
+ themeIndexCurrent = -1;
+ themeName = "";
+ nOpacityTheme = "";
+ style = eStyleBlendingDefault;
+ roundedCorners = 0;
+ displayRerunsDetailEPGView = 1;
+ numReruns = 5;
+ useSubtitleRerun = 1;
+ numLogosInitial = 30;
+ numLogosMax = 50;
+ limitLogoCache = 1;
+ logoPathSet = false;
+ imagesPathSet = false;
+ iconsPathSet = false;
}
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::setDynamicValues() {
+ numGrids = (displayMode == eVertical)?channelCols:channelRows;
+ jumpChannels = numGrids;
+}
+
+bool cTvguideConfig::LoadTheme() {
+ //is correct theme already loaded?
+ if (nOpacityTheme.size() == 0)
+ nOpacityTheme = Setup.OSDTheme;
+ if ((themeIndex > -1) && (themeIndex == themeIndexCurrent)) {
+ if (!nOpacityTheme.compare(Setup.OSDTheme)) {
+ return false;
+ } else {
+ nOpacityTheme = Setup.OSDTheme;
+ }
+ }
+ //Load available Themes
+ cThemes themes;
+ themes.Load(*cString("tvguide"));
+ int numThemesAvailable = themes.NumThemes();
+
+ //Check for nOpacity Theme
+ if (useNopacityTheme) {
+ std::string nOpacity = "nOpacity";
+ std::string currentSkin = Setup.OSDSkin;
+ std::string currentSkinTheme = Setup.OSDTheme;
+ if (!currentSkin.compare(nOpacity)) {
+ for (int curThemeIndex = 0; curThemeIndex < numThemesAvailable; curThemeIndex++) {
+ std::string curThemeName = themes.Name(curThemeIndex);
+ if (!curThemeName.compare(currentSkinTheme)) {
+ themeIndex = curThemeIndex;
+ break;
+ }
+ }
+ }
+ }
+
+ if (themeIndex == -1) {
+ for (int curThemeIndex = 0; curThemeIndex < numThemesAvailable; curThemeIndex++) {
+ std::string curThemeName = themes.Name(curThemeIndex);
+ if (!curThemeName.compare("default")) {
+ themeIndex = curThemeIndex;
+ break;
+ }
+ }
+
+ }
+
+ if (themeIndex == -1)
+ themeIndex = 0;
+
+ themeIndexCurrent = themeIndex;
+
+ const char *themePath = themes.FileName(themeIndex);
+ if (access(themePath, F_OK) == 0) {
+ ::theme.Load(themePath);
+ themeName = themes.Name(themeIndex);
+ }
+ esyslog("tvguide: set Theme to %s", *themeName);
+ return true;
+}
+
+
+void cTvguideConfig::SetStyle(void) {
+ if (theme.Color(clrStyle) == CLR_STYLE_FLAT) {
+ style = eStyleFlat;
+ esyslog("tvguide: set flat style");
+ } else if (theme.Color(clrStyle) == CLR_STYLE_BLENDING_DEFAULT) {
+ style = eStyleBlendingDefault;
+ esyslog("tvguide: set blending style");
+ } else if (theme.Color(clrStyle) == CLR_STYLE_GRAPHICAL) {
+ style = eStyleGraphical;
+ esyslog("tvguide: set graphical style");
+ } else {
+ style = eStyleBlendingMagick;
+ esyslog("tvguide: set magick blending style");
+ }
+
}
void cTvguideConfig::SetLogoPath(cString path) {
- logoPath = path;
+ logoPath = checkSlashAtEnd(*path);
+ logoPathSet = true;
+ esyslog("tvguide: Logo Path set to %s", *logoPath);
}
void cTvguideConfig::SetImagesPath(cString path) {
- epgImagePath = path;
+ epgImagePath = checkSlashAtEnd(*path);
+ imagesPathSet = true;
+ esyslog("tvguide: EPG Image Path set to %s", *epgImagePath);
}
-void cTvguideConfig::loadTheme() {
- cThemes themes;
- themes.Load(*cString("tvguide"));
- const char *FileName = themes.FileName(themeIndex);
- if (access(FileName, F_OK) == 0) {
- ::theme.Load(FileName);
- }
+void cTvguideConfig::SetIconsPath(cString path) {
+ iconPath = checkSlashAtEnd(*path);
+ iconsPathSet = true;
+ esyslog("tvguide: Icon Path set to %s", *iconPath);
}
-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;
+void cTvguideConfig::SetDefaultPathes(void) {
+ logoPathDefault = cString::sprintf("%s/logos/", cPlugin::ResourceDirectory(PLUGIN_NAME_I18N));
+ iconPathDefault = cString::sprintf("%s/icons/", cPlugin::ResourceDirectory(PLUGIN_NAME_I18N));
+ epgImagePathDefault = cString::sprintf("%s/epgimages/", cPlugin::CacheDirectory(PLUGIN_NAME_I18N));
+
+ if (!logoPathSet) {
+ logoPath = logoPathDefault;
+ }
+ if (!imagesPathSet) {
+ epgImagePath = epgImagePathDefault;
+ }
+ if (!iconsPathSet) {
+ iconPath = iconPathDefault;
+ }
}
+
+cString cTvguideConfig::checkSlashAtEnd(std::string path) {
+ try {
+ if (!(path.at(path.size()-1) == '/'))
+ return cString::sprintf("%s/", path.c_str());
+ } catch (...) {return path.c_str();}
+ return path.c_str();
+}
+
+bool cTvguideConfig::SetupParse(const char *Name, const char *Value) {
+ if (strcmp(Name, "timeFormat") == 0) timeFormat = atoi(Value);
+ else if (strcmp(Name, "debugImageLoading") == 0) debugImageLoading = atoi(Value);
+ else if (strcmp(Name, "showMainMenuEntry") == 0) showMainMenuEntry = atoi(Value);
+ else if (strcmp(Name, "replaceOriginalSchedule") == 0) replaceOriginalSchedule = atoi(Value);
+ else if (strcmp(Name, "useNopacityTheme") == 0) useNopacityTheme = atoi(Value);
+ else if (strcmp(Name, "themeIndex") == 0) themeIndex = atoi(Value);
+ else if (strcmp(Name, "displayMode") == 0) displayMode = atoi(Value);
+ else if (strcmp(Name, "showTimeInGrid") == 0) showTimeInGrid = atoi(Value);
+ else if (strcmp(Name, "displayStatusHeader") == 0) displayStatusHeader = atoi(Value);
+ else if (strcmp(Name, "displayChannelGroups") == 0) displayChannelGroups = atoi(Value);
+ else if (strcmp(Name, "displayTimeBase") == 0) displayTimeBase = atoi(Value);
+ else if (strcmp(Name, "headerHeightPercent") == 0) headerHeightPercent = atoi(Value);
+ else if (strcmp(Name, "channelGroupsPercent") == 0) channelGroupsPercent = atoi(Value);
+ else if (strcmp(Name, "epgViewBorder") == 0) epgViewBorder = atoi(Value);
+ else if (strcmp(Name, "scaleVideo") == 0) scaleVideo = atoi(Value);
+ else if (strcmp(Name, "decorateVideo") == 0) decorateVideo = atoi(Value);
+ else if (strcmp(Name, "roundedCorners") == 0) roundedCorners = atoi(Value);
+ else if (strcmp(Name, "channelCols") == 0) channelCols = atoi(Value);
+ else if (strcmp(Name, "channelRows") == 0) channelRows = 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, "logoWidthRatio") == 0) logoWidthRatio = atoi(Value);
+ else if (strcmp(Name, "logoHeightRatio") == 0) logoHeightRatio = atoi(Value);
+ else if (strcmp(Name, "bigStepHours") == 0) bigStepHours = atoi(Value);
+ else if (strcmp(Name, "hugeStepHours") == 0) hugeStepHours = atoi(Value);
+ else if (strcmp(Name, "channelJumpMode") == 0) channelJumpMode = atoi(Value);
+ else if (strcmp(Name, "blueKeyMode") == 0) blueKeyMode = atoi(Value);
+ else if (strcmp(Name, "numkeyMode") == 0) numkeyMode = atoi(Value);
+ else if (strcmp(Name, "closeOnSwitch") == 0) closeOnSwitch = atoi(Value);
+ else if (strcmp(Name, "useRemoteTimers") == 0) useRemoteTimers = atoi(Value);
+ else if (strcmp(Name, "hideLastGroup") == 0) hideLastGroup = 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, "numAdditionalEPGPictures") == 0) numAdditionalEPGPictures = atoi(Value);
+ else if (strcmp(Name, "epgImageWidthLarge") == 0) epgImageWidthLarge = atoi(Value);
+ else if (strcmp(Name, "epgImageHeightLarge") == 0) epgImageHeightLarge = atoi(Value);
+ else if (strcmp(Name, "detailedViewScrollStep") == 0) detailedViewScrollStep = atoi(Value);
+ else if (strcmp(Name, "timeLineWidthPercent") == 0) timeLineWidthPercent = atoi(Value);
+ else if (strcmp(Name, "timeLineHeightPercent") == 0) timeLineHeightPercent = atoi(Value);
+ else if (strcmp(Name, "displayChannelName") == 0) displayChannelName = atoi(Value);
+ else if (strcmp(Name, "channelHeaderWidthPercent") == 0) channelHeaderWidthPercent = atoi(Value);
+ else if (strcmp(Name, "channelHeaderHeightPercent") == 0) channelHeaderHeightPercent = atoi(Value);
+ else if (strcmp(Name, "footerHeightPercent") == 0) footerHeightPercent = atoi(Value);
+ else if (strcmp(Name, "instRecFolderMode") == 0) instRecFolderMode = atoi(Value);
+ else if (strcmp(Name, "instRecFixedFolder") == 0) instRecFixedFolder = Value;
+ else if (strcmp(Name, "favWhatsOnNow") == 0) favWhatsOnNow = atoi(Value);
+ else if (strcmp(Name, "favWhatsOnNext") == 0) favWhatsOnNext = atoi(Value);
+ else if (strcmp(Name, "favUseTime1") == 0) favUseTime1 = atoi(Value);
+ else if (strcmp(Name, "favUseTime2") == 0) favUseTime2 = atoi(Value);
+ else if (strcmp(Name, "favUseTime3") == 0) favUseTime3 = atoi(Value);
+ else if (strcmp(Name, "favUseTime4") == 0) favUseTime4 = atoi(Value);
+ else if (strcmp(Name, "favTime1") == 0) favTime1 = atoi(Value);
+ else if (strcmp(Name, "favTime2") == 0) favTime2 = atoi(Value);
+ else if (strcmp(Name, "favTime3") == 0) favTime3 = atoi(Value);
+ else if (strcmp(Name, "favTime4") == 0) favTime4 = atoi(Value);
+ else if (strcmp(Name, "descUser1") == 0) descUser1 = Value;
+ else if (strcmp(Name, "descUser2") == 0) descUser2 = Value;
+ else if (strcmp(Name, "descUser3") == 0) descUser3 = Value;
+ else if (strcmp(Name, "descUser4") == 0) descUser4 = Value;
+ else if (strcmp(Name, "favLimitChannels") == 0) favLimitChannels = atoi(Value);
+ else if (strcmp(Name, "favStartChannel") == 0) favStartChannel = atoi(Value);
+ else if (strcmp(Name, "favStopChannel") == 0) favStopChannel = atoi(Value);
+ else if (strcmp(Name, "fontIndex") == 0) fontIndex = atoi(Value);
+ else if (strcmp(Name, "FontButtonDelta") == 0) FontButtonDelta = atoi(Value);
+ else if (strcmp(Name, "FontDetailViewDelta") == 0) FontDetailViewDelta = atoi(Value);
+ else if (strcmp(Name, "FontDetailHeaderDelta") == 0) FontDetailHeaderDelta = atoi(Value);
+ else if (strcmp(Name, "FontMessageBoxDelta") == 0) FontMessageBoxDelta = atoi(Value);
+ else if (strcmp(Name, "FontMessageBoxLargeDelta") == 0) FontMessageBoxLargeDelta = atoi(Value);
+ else if (strcmp(Name, "FontStatusHeaderDelta") == 0) FontStatusHeaderDelta = atoi(Value);
+ else if (strcmp(Name, "FontStatusHeaderLargeDelta") == 0) FontStatusHeaderLargeDelta = atoi(Value);
+ else if (strcmp(Name, "FontChannelHeaderDelta") == 0) FontChannelHeaderDelta = atoi(Value);
+ else if (strcmp(Name, "FontChannelGroupsDelta") == 0) FontChannelGroupsDelta = atoi(Value);
+ else if (strcmp(Name, "FontGridDelta") == 0) FontGridDelta = atoi(Value);
+ else if (strcmp(Name, "FontGridSmallDelta") == 0) FontGridSmallDelta = atoi(Value);
+ else if (strcmp(Name, "FontTimeLineWeekdayDelta") == 0) FontTimeLineWeekdayDelta = atoi(Value);
+ else if (strcmp(Name, "FontTimeLineDateDelta") == 0) FontTimeLineDateDelta = atoi(Value);
+ else if (strcmp(Name, "FontTimeLineTimeDelta") == 0) FontTimeLineTimeDelta = atoi(Value);
+ else if (strcmp(Name, "FontChannelHeaderHorizontalDelta") == 0) FontChannelHeaderHorizontalDelta = atoi(Value);
+ else if (strcmp(Name, "FontChannelGroupsHorizontalDelta") == 0) FontChannelGroupsHorizontalDelta = atoi(Value);
+ else if (strcmp(Name, "FontGridHorizontalDelta") == 0) FontGridHorizontalDelta = atoi(Value);
+ else if (strcmp(Name, "FontGridHorizontalSmallDelta") == 0) FontGridHorizontalSmallDelta = atoi(Value);
+ else if (strcmp(Name, "FontTimeLineDateHorizontalDelta") == 0) FontTimeLineDateHorizontalDelta = atoi(Value);
+ else if (strcmp(Name, "FontTimeLineTimeHorizontalDelta") == 0) FontTimeLineTimeHorizontalDelta = atoi(Value);
+ else if (strcmp(Name, "FontRecMenuItemDelta") == 0) FontRecMenuItemDelta = atoi(Value);
+ else if (strcmp(Name, "FontRecMenuItemSmallDelta") == 0) FontRecMenuItemSmallDelta = atoi(Value);
+ else if (strcmp(Name, "FontRecMenuItemLargeDelta") == 0) FontRecMenuItemLargeDelta = atoi(Value);
+ else if (strcmp(Name, "displayRerunsDetailEPGView") == 0) displayRerunsDetailEPGView = atoi(Value);
+ else if (strcmp(Name, "numReruns") == 0) numReruns = atoi(Value);
+ else if (strcmp(Name, "useSubtitleRerun") == 0) useSubtitleRerun = atoi(Value);
+ else if (strcmp(Name, "numLogosInitial") == 0) numLogosInitial = atoi(Value);
+ else if (strcmp(Name, "numLogosMax") == 0) numLogosMax = atoi(Value);
+ else if (strcmp(Name, "limitLogoCache") == 0) limitLogoCache = atoi(Value);
+ else return false;
+ return true;
+}
\ No newline at end of file
diff --git a/config.h b/config.h
index 0e184c8..7ebb49f 100644
--- a/config.h
+++ b/config.h
@@ -1,67 +1,255 @@
#ifndef __TVGUIDE_CONFIG_H
#define __TVGUIDE_CONFIG_H
+#include <vdr/themes.h>
+#include <vdr/plugin.h>
+#include "osdmanager.h"
+#include "geometrymanager.h"
+#include "fontmanager.h"
+#include "imagecache.h"
+
+enum {
+ e12Hours,
+ e24Hours
+};
+
+enum {
+ eVertical,
+ eHorizontal
+};
+
+enum {
+ eNumJump,
+ eGroupJump
+};
+
+enum {
+ eStyleGraphical,
+ eStyleBlendingMagick,
+ eStyleBlendingDefault,
+ eStyleFlat
+};
+
+
+enum eBlueKeyMode {
+ eBlueKeySwitch = 0,
+ eBlueKeyEPG,
+ eBlueKeyFavorites
+};
+
+enum eInstRecFolderMode {
+ eFolderRoot = 0,
+ eFolderSelect,
+ eFolderFixed
+};
+
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();
+ private:
+ cString checkSlashAtEnd(std::string path);
+ public:
+ cTvguideConfig();
+ ~cTvguideConfig();
+ int debugImageLoading;
+ int showMainMenuEntry;
+ int replaceOriginalSchedule;
+ int displayMode;
+ int showTimeInGrid;
+ int channelCols;
+ int channelRows;
+ int numGrids;
+ int displayTime;
+ int displayStatusHeader;
+ int displayChannelGroups;
+ int displayTimeBase;
+ int headerHeightPercent;
+ int channelGroupsPercent;
+ int epgViewBorder;
+ int scaleVideo;
+ int decorateVideo;
+ int timeLineWidthPercent;
+ int timeLineHeightPercent;
+ int displayChannelName;
+ int channelHeaderWidthPercent;
+ int channelHeaderHeightPercent;
+ int footerHeightPercent;
+ int stepMinutes;
+ int bigStepHours;
+ int hugeStepHours;
+ int channelJumpMode;
+ int jumpChannels;
+ int blueKeyMode;
+ int closeOnSwitch;
+ int numkeyMode;
+ int useRemoteTimers;
+ int hideLastGroup;
+ int hideChannelLogos;
+ int logoWidthRatio;
+ int logoHeightRatio;
+ cString logoPath;
+ int logoExtension;
+ int hideEpgImages;
+ int epgImageWidth;
+ int epgImageHeight;
+ int numAdditionalEPGPictures;
+ int epgImageWidthLarge;
+ int epgImageHeightLarge;
+ int detailedViewScrollStep;
+ cString epgImagePath;
+ cString iconPath;
+ cString logoPathDefault;
+ cString iconPathDefault;
+ cString epgImagePathDefault;
+ int instRecFolderMode;
+ std::string instRecFixedFolder;
+ int favWhatsOnNow;
+ int favWhatsOnNext;
+ int favUseTime1;
+ int favUseTime2;
+ int favUseTime3;
+ int favUseTime4;
+ int favTime1;
+ int favTime2;
+ int favTime3;
+ int favTime4;
+ std::string descUser1;
+ std::string descUser2;
+ std::string descUser3;
+ std::string descUser4;
+ int favLimitChannels;
+ int favStartChannel;
+ int favStopChannel;
+ int fontIndex;
+ const char *fontNameDefault;
+ int FontButtonDelta;
+ int FontDetailViewDelta;
+ int FontDetailViewSmallDelta;
+ int FontDetailHeaderDelta;
+ int FontMessageBoxDelta;
+ int FontMessageBoxLargeDelta;
+ int FontStatusHeaderDelta;
+ int FontStatusHeaderLargeDelta;
+ int FontChannelHeaderDelta;
+ int FontChannelGroupsDelta;
+ int FontGridDelta;
+ int FontGridSmallDelta;
+ int FontTimeLineWeekdayDelta;
+ int FontTimeLineDateDelta;
+ int FontTimeLineTimeDelta;
+ int FontChannelHeaderHorizontalDelta;
+ int FontChannelGroupsHorizontalDelta;
+ int FontGridHorizontalDelta;
+ int FontGridHorizontalSmallDelta;
+ int FontTimeLineDateHorizontalDelta;
+ int FontTimeLineTimeHorizontalDelta;
+ int FontRecMenuItemDelta;
+ int FontRecMenuItemSmallDelta;
+ int FontRecMenuItemLargeDelta;
+ int timeFormat;
+ int useNopacityTheme;
+ int themeIndex;
+ int themeIndexCurrent;
+ cString themeName;
+ std::string nOpacityTheme;
+ int style;
+ int roundedCorners;
+ int displayRerunsDetailEPGView;
+ int numReruns;
+ int useSubtitleRerun;
+ int numLogosInitial;
+ int numLogosMax;
+ int limitLogoCache;
+ bool logoPathSet;
+ bool imagesPathSet;
+ bool iconsPathSet;
+ bool LoadTheme();
+ void SetStyle(void);
+ void setDynamicValues(void);
+ void SetLogoPath(cString path);
+ void SetImagesPath(cString path);
+ void SetIconsPath(cString path);
+ void SetDefaultPathes(void);
+ bool SetupParse(const char *Name, const char *Value);
};
+#ifdef DEFINE_CONFIG
+ cTvguideConfig tvguideConfig;
+ cOsdManager osdManager;
+ cGeometryManager geoManager;
+ cFontManager fontManager;
+ cImageCache imgCache;
+ cTheme theme;
+ cPlugin* pRemoteTimers = NULL;
+#else
+ extern cTvguideConfig tvguideConfig;
+ extern cOsdManager osdManager;
+ extern cGeometryManager geoManager;
+ extern cFontManager fontManager;
+ extern cImageCache imgCache;
+ extern cTheme theme;
+ extern cPlugin* pRemoteTimers;
+#endif
+
+
+// --- Theme -------------------------------------------------------------
+//Style SETUP
+#define CLR_STYLE_BLENDING_MAGICK 0xFFFFFFFF
+#define CLR_STYLE_BLENDING_DEFAULT 0xAAAAAAAA
+#define CLR_STYLE_GRAPHICAL 0x66666666
+#define CLR_STYLE_FLAT 0x00000000
+
+THEME_CLR(theme, clrStyle, CLR_STYLE_BLENDING_DEFAULT);
+THEME_CLR(theme, clrBackgroundOSD, 0xB012273f);
+THEME_CLR(theme, clrBackground, 0xFF12273f);
+THEME_CLR(theme, clrGrid1, 0x00000000);
+THEME_CLR(theme, clrGrid1Blending, 0x00000000);
+THEME_CLR(theme, clrGrid2, 0x00000000);
+THEME_CLR(theme, clrGrid2Blending, 0x00000000);
+THEME_CLR(theme, clrHighlight, 0xAA3A3A55);
+THEME_CLR(theme, clrHighlightBlending, 0xDD000000);
+THEME_CLR(theme, clrGridFontBack, clrTransparent);
+THEME_CLR(theme, clrGridActiveFontBack, 0xFFAFD533);
+THEME_CLR(theme, clrFont, clrWhite);
+THEME_CLR(theme, clrFontActive, 0xFF363636);
+THEME_CLR(theme, clrFontHeader, 0xFF363636);
+THEME_CLR(theme, clrFontButtons, clrWhite);
+THEME_CLR(theme, clrStatusHeader, 0x00000000);
+THEME_CLR(theme, clrStatusHeaderBlending, 0x00000000);
+THEME_CLR(theme, clrHeader, 0x00000000);
+THEME_CLR(theme, clrHeaderBlending, 0x00000000);
+THEME_CLR(theme, clrBorder, 0x00000000);
+THEME_CLR(theme, clrTimeline1, clrWhite);
+THEME_CLR(theme, clrTimeline1Blending, 0xFF828282);
+THEME_CLR(theme, clrTimeline2, clrBlack);
+THEME_CLR(theme, clrTimeline2Blending, 0xFF3F3F3F);
+THEME_CLR(theme, clrTimeBase, 0xA0FF0000);
+THEME_CLR(theme, clrTabInactive, 0xA01F3D7A);
+THEME_CLR(theme, clrButtonRed, 0xFFFF0000);
+THEME_CLR(theme, clrButtonRedBorder, 0x00000000);
+THEME_CLR(theme, clrButtonGreen, 0x00000000);
+THEME_CLR(theme, clrButtonGreenBorder, 0x00000000);
+THEME_CLR(theme, clrButtonYellow, 0x00000000);
+THEME_CLR(theme, clrButtonYellowBorder, 0x00000000);
+THEME_CLR(theme, clrButtonBlue, 0x00000000);
+THEME_CLR(theme, clrButtonBlueBorder, 0x00000000);
+THEME_CLR(theme, clrButtonBlend, 0xDD000000);
+THEME_CLR(theme, clrRecMenuBackground, 0xAA000000);
+THEME_CLR(theme, clrRecMenuTimerConflictBackground, 0xFFCCCCCC);
+THEME_CLR(theme, clrRecMenuTimerConflictBar, 0xFF222222);
+THEME_CLR(theme, clrRecMenuTimerConflictOverlap, 0xAAFF0000);
+THEME_CLR(theme, clrRecMenuDayActive, 0xFF00FF00);
+THEME_CLR(theme, clrRecMenuDayInactive, 0xFFFF0000);
+THEME_CLR(theme, clrRecMenuDayHighlight, 0x44FFFFFF);
+THEME_CLR(theme, clrRecMenuTextBack, 0xFF000000);
+THEME_CLR(theme, clrRecMenuTextActiveBack, 0xFF939376);
+THEME_CLR(theme, clrRecMenuKeyboardBack, 0xFF000000);
+THEME_CLR(theme, clrRecMenuKeyboardBorder, clrWhite);
+THEME_CLR(theme, clrRecMenuKeyboardHigh, 0x40BB0000);
+THEME_CLR(theme, clrButtonRedKeyboard, 0xFFBB0000);
+THEME_CLR(theme, clrButtonGreenKeyboard, 0xFF00BB00);
+THEME_CLR(theme, clrButtonYellowKeyboard, 0xFFBBBB00);
+THEME_CLR(theme, clrRecMenuTimelineTimer, 0xB012273f);
+THEME_CLR(theme, clrRecMenuTimelineBack, 0xFF828282);
+THEME_CLR(theme, clrRecMenuTimelineActive, 0xFF3F3F3F);
+THEME_CLR(theme, clrRecMenuTimelineConflict, 0x30FF0000);
+THEME_CLR(theme, clrRecMenuTimelineConflictOverlap, 0x90FF0000);
#endif //__TVGUIDE_CONFIG_H
\ No newline at end of file
diff --git a/detailview.c b/detailview.c
index e867315..ca351ab 100644
--- a/detailview.c
+++ b/detailview.c
@@ -1,196 +1,159 @@
#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(const cEvent *event, cFooter *footer) {
+ this->event = event;
+ this->footer = footer;
}
cDetailView::~cDetailView(void){
- delete header;
- osdManager.releasePixmap(headerLogo);
- osdManager.releasePixmap(headerBack);
- osdManager.releasePixmap(content);
- osdManager.releasePixmap(scrollBar);
- osdManager.releasePixmap(footer);
- delete imgScrollBar;
+ Cancel(-1);
+ while (Active())
+ cCondWait::SleepMs(10);
+ footer->LeaveDetailedViewMode(Channels.GetByChannelID(event->ChannelID()));
+ if (view)
+ delete view;
}
-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::InitiateView(void) {
+ static cPlugin *pScraper2Vdr = cPluginManager::GetPlugin("scraper2vdr");
+ ScraperGetEventType call;
+ if (!event)
+ return;
+ call.event = event;
+ if (!pScraper2Vdr) {
+ view = new cEPGView();
+ } else if (pScraper2Vdr->Service("GetEventType", &call)) {
+ if (call.type == tMovie) {
+ view = new cMovieView(call.movieId);
+ } else if (call.type == tSeries) {
+ view = new cSeriesView(call.seriesId, call.episodeId);
+ }
+ } else {
+ view = new cEPGView();
+ }
+ view->SetTitle(event->Title());
+ view->SetSubTitle(event->ShortText());
+ view->SetInfoText(event->Description());
+ cString dateTime;
+ time_t vps = event->Vps();
+ if (vps) {
+ dateTime = cString::sprintf("%s %s - %s (%d %s) VPS: %s", *event->GetDateString(), *event->GetTimeString(), *event->GetEndTimeString(), event->Duration()/60, tr("min"), *TimeString(vps));
+ } else {
+ dateTime = cString::sprintf("%s %s - %s (%d %s)", *event->GetDateString(), *event->GetTimeString(), *event->GetEndTimeString(), event->Duration()/60, tr("min"));
+ }
+ view->SetDateTime(*dateTime);
+ view->SetChannel(Channels.GetByChannelID(event->ChannelID(), true));
+ view->SetEventID(event->EventID());
+ view->SetEvent(event);
}
-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);
- headerLogo = osdManager.requestPixmap(6, cRect(borderWidth, borderWidth, tvguideConfig.osdWidth - 2*borderWidth, headerHeight), cRect::Null, "detailViewHeaderLogo");
- headerLogo->Fill(clrTransparent);
- headerLogo->SetAlpha(0);
- headerBack = osdManager.requestPixmap(4, cRect(borderWidth, borderWidth, tvguideConfig.osdWidth - 2*borderWidth, headerHeight), cRect::Null, "detailViewHeaderBack");
- headerBack->SetAlpha(0);
- headerBack->Fill(clrBlack);
- 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(theme.Color(clrBorder));
-}
+std::string cDetailView::LoadReruns(void) {
+ if (!event)
+ return "";
+
+ cPlugin *epgSearchPlugin = cPluginManager::GetPlugin("epgsearch");
+ if (!epgSearchPlugin)
+ return "";
-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();
- headerLogo->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);
-}
+ if (isempty(event->Title()))
+ return "";
+
+ std::stringstream sstrReruns;
+ sstrReruns << tr("Reruns of ") << "\"" << event->Title() << "\":" << std::endl << std::endl;
-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);
- }
-}
+ Epgsearch_searchresults_v1_0 data;
+ std::string strQuery = event->Title();
-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);
-}
+ if (tvguideConfig.displayRerunsDetailEPGView > 0) {
+ if (tvguideConfig.useSubtitleRerun == 2 && !isempty(event->ShortText())) {
+ strQuery += "~";
+ strQuery += event->ShortText();
+ }
+ data.useSubTitle = true;
+ } else {
+ data.useSubTitle = false;
+ }
+ data.query = (char *)strQuery.c_str();
+ data.mode = 0;
+ data.channelNr = 0;
+ data.useTitle = true;
+ data.useDescription = false;
-void cDetailView::scrollUp() {
- if (contentScrollable) {
- int newDrawportHeight = content->DrawPort().Point().Y() + tvguideConfig.FontDetailView->Height();
- content->SetDrawPortPoint(cPoint(0, min(newDrawportHeight,0)));
- drawScrollbar();
- }
-}
+ bool foundRerun = false;
+ if (epgSearchPlugin->Service("Epgsearch-searchresults-v1.0", &data)) {
+ cList<Epgsearch_searchresults_v1_0::cServiceSearchResult>* list = data.pResultList;
+ if (list && (list->Count() > 1)) {
+ foundRerun = true;
+ int i = 0;
+ for (Epgsearch_searchresults_v1_0::cServiceSearchResult *r = list->First(); r && i < tvguideConfig.numReruns; r = list->Next(r)) {
+ if ((event->ChannelID() == r->event->ChannelID()) && (event->StartTime() == r->event->StartTime()))
+ continue;
+ i++;
+ sstrReruns << *DayDateTime(r->event->StartTime());
+ cChannel *channel = Channels.GetByChannelID(r->event->ChannelID(), true, true);
+ if (channel) {
+ sstrReruns << ", " << trVDR("Channel") << " " << channel->Number() << ":";
+ sstrReruns << " " << channel->ShortName(true);
+ }
+ sstrReruns << "\n" << r->event->Title();
+ if (!isempty(r->event->ShortText()))
+ sstrReruns << "~" << r->event->ShortText();
+ sstrReruns << std::endl << std::endl;
+ }
+ delete list;
+ }
+ }
-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();
- }
+ if (!foundRerun) {
+ sstrReruns << std::endl << tr("No reruns found");
+ }
+ return sstrReruns.str();
}
-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);
- headerBack->SetAlpha(Alpha);
- headerLogo->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;
+ InitiateView();
+ if (!view)
+ return;
+ view->SetFonts();
+ view->SetGeometry();
+ view->LoadMedia();
+ view->Start();
+ if (event)
+ view->SetAdditionalInfoText(LoadReruns());
+}
+
+eOSState cDetailView::ProcessKey(eKeys Key) {
+ eOSState state = osContinue;
+ if (Running())
+ return state;
+ switch (Key & ~k_Repeat) {
+ case kUp: {
+ bool scrolled = view->KeyUp();
+ if (scrolled) {
+ view->DrawScrollbar();
+ osdManager.flush();
+ }
+ break; }
+ case kDown: {
+ bool scrolled = view->KeyDown();
+ if (scrolled) {
+ view->DrawScrollbar();
+ osdManager.flush();
+ }
+ break; }
+ case kLeft:
+ view->KeyLeft();
+ view->Start();
+ break;
+ case kRight:
+ view->KeyRight();
+ view->Start();
+ break;
+ case kOk:
+ case kBack:
+ state = osEnd;
+ break;
}
+ return state;
}
\ No newline at end of file
diff --git a/detailview.h b/detailview.h
index f8219d5..58f653e 100644
--- a/detailview.h
+++ b/detailview.h
@@ -1,41 +1,28 @@
#ifndef __TVGUIDE_DETAILVIEW_H
#define __TVGUIDE_DETAILVIEW_H
-// --- cDetailView -------------------------------------------------------------
+#include <vdr/plugin.h>
+#include <vdr/epg.h>
+#include "config.h"
+#include "tools.h"
+#include "styledpixmap.h"
+#include "footer.h"
+#include "view.h"
-class cEpgGrid;
+// --- cDetailView -------------------------------------------------------------
-class cDetailView : public cThread {
+class cDetailView : public cThread {
private:
- cEpgGrid *grid;
- cStyledPixmap *header;
- cPixmap *headerLogo;
- cPixmap *headerBack;
- 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);
+ const cEvent *event;
+ cFooter *footer;
+ cView *view;
+ void InitiateView(void);
+ std::string LoadReruns(void);
+ void Action(void);
public:
- cDetailView(cEpgGrid *grid);
- virtual ~cDetailView(void);
- void createPixmaps();
- void scrollUp();
- void scrollDown();
+ cDetailView(const cEvent *event, cFooter *footer);
+ virtual ~cDetailView(void);
+ eOSState ProcessKey(eKeys Key);
};
#endif //__TVGUIDE_DETAILVIEW_H
\ No newline at end of file
diff --git a/dummygrid.c b/dummygrid.c
new file mode 100644
index 0000000..2ab9056
--- /dev/null
+++ b/dummygrid.c
@@ -0,0 +1,111 @@
+#include "dummygrid.h"
+
+cDummyGrid::cDummyGrid(cChannelColumn *c, time_t start, time_t end) : cGrid(c) {
+ this->start = start;
+ this->end = end;
+ strText = tr("No EPG Information available");
+ dummy = true;
+ hasTimer = false;
+}
+
+cDummyGrid::~cDummyGrid(void) {
+}
+
+time_t cDummyGrid::Duration(void) {
+ //max Duration 5h
+ if (end - start > 18000)
+ return 18000;
+ return (end - start);
+};
+
+void cDummyGrid::SetViewportHeight() {
+ int viewportHeightOld = viewportHeight;
+ viewportHeight = Duration() / 60 * geoManager.minutePixel;
+ if (viewportHeight != viewportHeightOld)
+ dirty = true;
+}
+
+void cDummyGrid::PositionPixmap() {
+ int x0, y0;
+ if (tvguideConfig.displayMode == eVertical) {
+ x0 = column->getX();
+ y0 = geoManager.statusHeaderHeight + geoManager.channelHeaderHeight + geoManager.channelGroupsHeight;
+ if ( column->Start() < StartTime() ) {
+ y0 += (StartTime() - column->Start())/60*geoManager.minutePixel;
+ }
+ if (!pixmap) {
+ pixmap = osdManager.requestPixmap(-1, cRect(x0, y0, geoManager.colWidth, viewportHeight));
+ } else if (dirty) {
+ osdManager.releasePixmap(pixmap);
+ pixmap = osdManager.requestPixmap(-1, cRect(x0, y0, geoManager.colWidth, viewportHeight));
+ } else {
+ pixmap->SetViewPort(cRect(x0, y0, geoManager.colWidth, viewportHeight));
+ }
+ } else if (tvguideConfig.displayMode == eHorizontal) {
+ x0 = geoManager.channelHeaderWidth + geoManager.channelGroupsWidth;
+ y0 = column->getY();
+ if ( column->Start() < StartTime() ) {
+ x0 += (StartTime() - column->Start())/60*geoManager.minutePixel;
+ }
+ if (!pixmap) {
+ pixmap = osdManager.requestPixmap(-1, cRect(x0, y0, viewportHeight, geoManager.rowHeight));
+ } else if (dirty) {
+ osdManager.releasePixmap(pixmap);
+ pixmap = osdManager.requestPixmap(-1, cRect(x0, y0, viewportHeight, geoManager.rowHeight));
+ } else {
+ pixmap->SetViewPort(cRect(x0, y0, viewportHeight, geoManager.rowHeight));
+ }
+ }
+}
+
+void cDummyGrid::setText() {
+ if (tvguideConfig.displayMode == eVertical) {
+ text->Set(*strText, fontManager.FontGrid, geoManager.colWidth-2*borderWidth);
+ }
+}
+
+void cDummyGrid::drawText() {
+ tColor colorText = (active)?theme.Color(clrFontActive):theme.Color(clrFont);
+ tColor colorTextBack;
+ if (tvguideConfig.style == eStyleFlat)
+ colorTextBack = color;
+ else if (tvguideConfig.style == eStyleGraphical)
+ colorTextBack = (active)?theme.Color(clrGridActiveFontBack):theme.Color(clrGridFontBack);
+ else
+ colorTextBack = clrTransparent;
+ if (tvguideConfig.displayMode == eVertical) {
+ if (Height()/geoManager.minutePixel < 6)
+ return;
+ int textHeight = fontManager.FontGrid->Height();
+ int textLines = text->Lines();
+ for (int i=0; i<textLines; i++) {
+ pixmap->DrawText(cPoint(borderWidth, borderWidth + i*textHeight), text->GetLine(i), colorText, colorTextBack, fontManager.FontGrid);
+
+ }
+ } else if (tvguideConfig.displayMode == eHorizontal) {
+ if (Width()/geoManager.minutePixel < 10) {
+ int titleY = (geoManager.rowHeight - fontManager.FontGridHorizontal->Height())/2;
+ pixmap->DrawText(cPoint(borderWidth - 2, titleY), "...", colorText, colorTextBack, fontManager.FontGridHorizontal);
+ return;
+ }
+ int titleY = (geoManager.rowHeight - fontManager.FontGridHorizontal->Height())/2;
+ pixmap->DrawText(cPoint(borderWidth, titleY), *strText, colorText, colorTextBack, fontManager.FontGridHorizontal);
+ }
+}
+cString cDummyGrid::getText(void) {
+ return strText;
+}
+
+cString cDummyGrid::getTimeString(void) {
+ return cString::sprintf("%s - %s", *TimeString(start), *TimeString(end));
+}
+
+void cDummyGrid::debug() {
+ esyslog("tvguide dummygrid: %s: %s, %s, viewportHeight: %d px, Duration: %ld min, active: %d",
+ column->Name(),
+ *cMyTime::printTime(start),
+ *cMyTime::printTime(end),
+ viewportHeight,
+ Duration()/60,
+ active);
+}
\ No newline at end of file
diff --git a/dummygrid.h b/dummygrid.h
new file mode 100644
index 0000000..f0837f6
--- /dev/null
+++ b/dummygrid.h
@@ -0,0 +1,34 @@
+#ifndef __TVGUIDE_DUMMYGRID_H
+#define __TVGUIDE_DUMMYGRID_H
+
+#include "grid.h"
+#include "channelcolumn.h"
+
+// --- cDummyGrid -------------------------------------------------------------
+
+class cDummyGrid : public cGrid {
+private:
+ time_t start;
+ time_t end;
+ cString strText;
+ void drawText();
+ time_t Duration(void);
+public:
+ cDummyGrid(cChannelColumn *c, time_t start, time_t end);
+ virtual ~cDummyGrid(void);
+ void SetViewportHeight();
+ void PositionPixmap();
+ void setText(void);
+ const cEvent *GetEvent() {return NULL;};
+ time_t StartTime() { return start; };
+ time_t EndTime() { return end; };
+ void SetStartTime(time_t start) { this->start = start; };
+ void SetEndTime(time_t end) { this->end = end; };
+ int calcOverlap(cGrid *neighbor);
+ void setTimer() {};
+ cString getText(void);
+ cString getTimeString(void);
+ void debug();
+};
+
+#endif //__TVGUIDE_DUMMYGRID_H
\ No newline at end of file
diff --git a/epggrid.c b/epggrid.c
index 8c8109d..7a21834 100644
--- a/epggrid.c
+++ b/epggrid.c
@@ -1,146 +1,169 @@
+#include "services/remotetimers.h"
#include "channelcolumn.h"
+#include "tools.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(cChannelColumn *c, const cEvent *event) : cGrid(c) {
+ this->event = event;
+ extText = new cTextWrapper();
+ hasTimer = false;
+ SetTimer();
+ hasSwitchTimer = false;
+ SetSwitchTimer();
+ dummy = false;
}
cEpgGrid::~cEpgGrid(void) {
- delete text;
- delete extText;
+ 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;
+ int viewportHeightOld = viewportHeight;
+ if ( column->Start() > StartTime() ) {
+ viewportHeight = (min((int)EndTime(), column->Stop()) - column->Start()) /60;
+ } else if ( column->Stop() < EndTime() ) {
+ viewportHeight = (column->Stop() - StartTime()) /60;
+ if (viewportHeight < 0) viewportHeight = 0;
+ } else {
+ viewportHeight = Duration() / 60;
+ }
+ viewportHeight *= geoManager.minutePixel;
+ 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;
- }
+ int x0, y0;
+ if (tvguideConfig.displayMode == eVertical) {
+ int x0 = column->getX();
+ int y0 = geoManager.statusHeaderHeight + geoManager.channelHeaderHeight + geoManager.channelGroupsHeight;
+ if ( column->Start() < StartTime() ) {
+ y0 += (StartTime() - column->Start())/60*geoManager.minutePixel;
+ }
+ if (!pixmap) {
+ pixmap = osdManager.requestPixmap(-1, cRect(x0, y0, geoManager.colWidth, viewportHeight),
+ cRect(0, 0, geoManager.colWidth, Duration()/60*geoManager.minutePixel));
+ } else {
+ pixmap->SetViewPort(cRect(x0, y0, geoManager.colWidth, viewportHeight));
+ }
+ } else if (tvguideConfig.displayMode == eHorizontal) {
+ int x0 = geoManager.channelHeaderWidth + geoManager.channelGroupsWidth;
+ int y0 = column->getY();
+ if ( column->Start() < StartTime() ) {
+ x0 += (StartTime() - column->Start())/60*geoManager.minutePixel;
+ }
+ if (!pixmap) {
+ pixmap = osdManager.requestPixmap(-1, cRect(x0, y0, viewportHeight, geoManager.rowHeight),
+ cRect(0, 0, Duration()/60*geoManager.minutePixel, geoManager.rowHeight));
+ } else {
+ pixmap->SetViewPort(cRect(x0, y0, viewportHeight, geoManager.rowHeight ));
+ }
+ }
- 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::SetTimer() {
+ if (tvguideConfig.useRemoteTimers && pRemoteTimers) {
+ RemoteTimers_Event_v1_0 rt;
+ rt.event = event;
+ if (pRemoteTimers->Service("RemoteTimers::GetTimerByEvent-v1.0", &rt))
+ hasTimer = true;
+ else
+ hasTimer = false;
+ } else if (column->HasTimer()) {
+ hasTimer = event->HasTimer();
+ } else {
+ hasTimer = 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::SetSwitchTimer() {
+ if (column->HasSwitchTimer()) {
+ hasSwitchTimer = SwitchTimers.EventInSwitchList(event);
+ } else {
+ hasSwitchTimer = false;
+ }
}
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);
+ if (tvguideConfig.displayMode == eVertical) {
+ cString strText;
+ strText = cString::sprintf("%s - %s:\n%s", *(event->GetTimeString()), *(event->GetEndTimeString()), event->Title());
+ text->Set(*(strText), fontManager.FontGrid, geoManager.colWidth-2*borderWidth);
+ extText->Set(event->ShortText(), fontManager.FontGridSmall, geoManager.colWidth-2*borderWidth);
+ } else if (tvguideConfig.displayMode == eHorizontal) {
+ timeString = cString::sprintf("%s - %s", *(event->GetTimeString()), *(event->GetEndTimeString()));
+ }
}
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);
- }
- }
+ tColor colorText = (active)?theme.Color(clrFontActive):theme.Color(clrFont);
+ tColor colorTextBack;
+ if (tvguideConfig.style == eStyleFlat)
+ colorTextBack = color;
+ else if (tvguideConfig.style == eStyleGraphical)
+ colorTextBack = (active)?theme.Color(clrGridActiveFontBack):theme.Color(clrGridFontBack);
+ else
+ colorTextBack = clrTransparent;
+ if (tvguideConfig.displayMode == eVertical) {
+ if (Height()/geoManager.minutePixel < 6)
+ return;
+ int textHeight = fontManager.FontGrid->Height();
+ int textLines = text->Lines();
+ for (int i=0; i<textLines; i++) {
+ pixmap->DrawText(cPoint(borderWidth, borderWidth + i*textHeight), text->GetLine(i), colorText, colorTextBack, fontManager.FontGrid);
+ }
+ int extTextLines = extText->Lines();
+ int offset = (textLines+1)*textHeight - 0.5*textHeight;
+ textHeight = fontManager.FontGridSmall->Height();
+ if ((Height()-textHeight-10) > offset) {
+ for (int i=0; i<extTextLines; i++) {
+ pixmap->DrawText(cPoint(borderWidth, borderWidth + offset + i*textHeight), extText->GetLine(i), colorText, colorTextBack, fontManager.FontGridSmall);
+ }
+ }
+ } else if (tvguideConfig.displayMode == eHorizontal) {
+ if (Width()/geoManager.minutePixel < 10) {
+ int titleY = (geoManager.rowHeight - fontManager.FontGridHorizontal->Height())/2;
+ pixmap->DrawText(cPoint(borderWidth - 2, titleY), "...", colorText, colorTextBack, fontManager.FontGridHorizontal);
+ return;
+ }
+ cString strTitle = CutText(event->Title(), viewportHeight, fontManager.FontGridHorizontal).c_str();
+ int titleY = 0;
+ if (tvguideConfig.showTimeInGrid) {
+ pixmap->DrawText(cPoint(borderWidth, borderWidth), *timeString, colorText, colorTextBack, fontManager.FontGridHorizontalSmall);
+ titleY = fontManager.FontGridHorizontalSmall->Height() + (geoManager.rowHeight - fontManager.FontGridHorizontalSmall->Height() - fontManager.FontGridHorizontal->Height())/2;
+ } else {
+ titleY = (geoManager.rowHeight - fontManager.FontGridHorizontal->Height())/2;
+ }
+ pixmap->DrawText(cPoint(borderWidth, titleY), *strTitle, colorText, colorTextBack, fontManager.FontGridHorizontal);
+ }
+ if (hasSwitchTimer)
+ drawIcon("Switch", theme.Color(clrButtonYellow));
+ if (hasTimer)
+ drawIcon("REC", theme.Color(clrButtonRed));
}
-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;
+void cEpgGrid::drawIcon(cString iconText, tColor color) {
+
+ const cFont *font = (tvguideConfig.displayMode == eVertical)
+ ?fontManager.FontGrid
+ :fontManager.FontGridHorizontalSmall;
+ int textWidth = font->Width(*iconText)+2*borderWidth;
+ int textHeight = font->Height()+10;
+ pixmap->DrawRectangle( cRect(Width() - textWidth - borderWidth, Height() - textHeight - borderWidth, textWidth, textHeight), color);
+ pixmap->DrawText(cPoint(Width() - textWidth, Height() - textHeight - borderWidth/2), *iconText, theme.Color(clrFont), color, font);
}
-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;
+cString cEpgGrid::getTimeString(void) {
+ return cString::sprintf("%s - %s", *(event->GetTimeString()), *(event->GetEndTimeString()));
}
void cEpgGrid::debug() {
- esyslog("tvguide Grid: %s, %s, viewportHeight: %d, Duration: %d", *(event->GetTimeString()), event->Title(), viewportHeight, event->Duration()/60);
-}
\ No newline at end of file
+ esyslog("tvguide epggrid: %s: %s, %s, viewportHeight: %d px, Duration: %d min, active: %d",
+ column->Name(),
+ *(event->GetTimeString()),
+ event->Title(),
+ viewportHeight,
+ event->Duration()/60,
+ active);
+}
diff --git a/epggrid.h b/epggrid.h
index 00160dc..95f40ea 100644
--- a/epggrid.h
+++ b/epggrid.h
@@ -1,44 +1,32 @@
#ifndef __TVGUIDE_EPGGRID_H
#define __TVGUIDE_EPGGRID_H
+#include <vdr/epg.h>
+#include "grid.h"
+
// --- cEpgGrid -------------------------------------------------------------
-class cEpgGrid : public cListObject, public cStyledPixmap {
+class cEpgGrid : public cGrid {
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();
+ const cEvent *event;
+ cTextWrapper *extText;
+ cString timeString;
+ void drawText();
+ void drawIcon(cString iconText, tColor color);
+ time_t Duration(void) { return event->Duration(); };
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();
+ cEpgGrid(cChannelColumn *c, const cEvent *event);
+ virtual ~cEpgGrid(void);
+ void SetViewportHeight();
+ void PositionPixmap();
+ void setText(void);
+ const cEvent *GetEvent() {return event;};
+ time_t StartTime() { return event->StartTime(); };
+ time_t EndTime() { return event->EndTime(); };
+ void SetTimer();
+ void SetSwitchTimer();
+ cString getTimeString(void);
+ void debug();
};
#endif //__TVGUIDE_EPGGRID_H
\ No newline at end of file
diff --git a/fontmanager.c b/fontmanager.c
new file mode 100644
index 0000000..b55621a
--- /dev/null
+++ b/fontmanager.c
@@ -0,0 +1,96 @@
+#include "geometrymanager.h"
+#include "config.h"
+#include "fontmanager.h"
+
+cFontManager::cFontManager() {
+}
+
+cFontManager::~cFontManager() {
+ DeleteFonts();
+}
+
+void cFontManager::SetFonts() {
+ InitialiseFontType();
+ //Common Fonts
+ FontButton = CreateFont(geoManager.footerHeight/3 + 4 + tvguideConfig.FontButtonDelta);
+ FontDetailView = CreateFont(geoManager.osdHeight/30 + tvguideConfig.FontDetailViewDelta);
+ FontDetailViewSmall = CreateFont(geoManager.osdHeight/40 + tvguideConfig.FontDetailViewSmallDelta);
+ FontDetailHeader = CreateFont(geoManager.osdHeight/27 + tvguideConfig.FontDetailHeaderDelta);
+ FontDetailHeaderLarge = CreateFont(geoManager.osdHeight/20 + tvguideConfig.FontDetailHeaderDelta);
+ FontMessageBox = CreateFont(geoManager.osdHeight/33 + tvguideConfig.FontMessageBoxDelta);
+ FontMessageBoxLarge = CreateFont(geoManager.osdHeight/30 + tvguideConfig.FontMessageBoxLargeDelta);
+ FontStatusHeader = CreateFont(geoManager.statusHeaderHeight/6 - 4 + tvguideConfig.FontStatusHeaderDelta);
+ FontStatusHeaderLarge = CreateFont(geoManager.statusHeaderHeight/5 + tvguideConfig.FontStatusHeaderLargeDelta);
+ //Fonts for vertical Display
+ FontChannelHeader = CreateFont(geoManager.colWidth/10 + tvguideConfig.FontChannelHeaderDelta);
+ FontChannelGroups = CreateFont(geoManager.colWidth/8 + tvguideConfig.FontChannelGroupsDelta);
+ FontGrid = CreateFont(geoManager.colWidth/12 + tvguideConfig.FontGridDelta);
+ FontGridSmall = CreateFont(geoManager.colWidth/12 + tvguideConfig.FontGridSmallDelta);
+ FontTimeLineWeekday = CreateFont(geoManager.timeLineWidth/3 + tvguideConfig.FontTimeLineWeekdayDelta);
+ FontTimeLineDate = CreateFont(geoManager.timeLineWidth/4 + tvguideConfig.FontTimeLineDateDelta);
+ FontTimeLineTime = CreateFont(geoManager.timeLineWidth/4 + tvguideConfig.FontTimeLineTimeDelta);
+ //Fonts for horizontal Display
+ FontChannelHeaderHorizontal = CreateFont(geoManager.rowHeight/3 + tvguideConfig.FontChannelHeaderHorizontalDelta);
+ FontChannelGroupsHorizontal = CreateFont(geoManager.rowHeight/3 + 5 + tvguideConfig.FontChannelGroupsHorizontalDelta);
+ FontGridHorizontal = CreateFont(geoManager.rowHeight/3 + 5 + tvguideConfig.FontGridHorizontalDelta);
+ FontGridHorizontalSmall = CreateFont(geoManager.rowHeight/4 + tvguideConfig.FontGridHorizontalSmallDelta);
+ FontTimeLineDateHorizontal = CreateFont(geoManager.timeLineHeight/2 + 5 + tvguideConfig.FontTimeLineDateHorizontalDelta);
+ FontTimeLineTimeHorizontal = CreateFont(geoManager.timeLineHeight/2 + tvguideConfig.FontTimeLineTimeHorizontalDelta);
+ //Fonts for RecMenu
+ FontRecMenuItem = CreateFont(geoManager.osdHeight/30 + tvguideConfig.FontRecMenuItemDelta);
+ FontRecMenuItemSmall = CreateFont(geoManager.osdHeight/40 + tvguideConfig.FontRecMenuItemSmallDelta);
+ FontRecMenuItemLarge = CreateFont(geoManager.osdHeight/25 + tvguideConfig.FontRecMenuItemLargeDelta);
+}
+
+void cFontManager::DeleteFonts() {
+ delete FontButton;
+ delete FontDetailView;
+ delete FontDetailViewSmall;
+ delete FontDetailHeader;
+ delete FontDetailHeaderLarge;
+ delete FontMessageBox;
+ delete FontMessageBoxLarge;
+ delete FontStatusHeader;
+ delete FontStatusHeaderLarge;
+ delete FontChannelHeader;
+ delete FontChannelGroups;
+ delete FontGrid;
+ delete FontGridSmall;
+ delete FontTimeLineWeekday;
+ delete FontTimeLineDate;
+ delete FontTimeLineTime;
+ delete FontChannelHeaderHorizontal;
+ delete FontChannelGroupsHorizontal;
+ delete FontGridHorizontal;
+ delete FontGridHorizontalSmall;
+ delete FontTimeLineDateHorizontal;
+ delete FontTimeLineTimeHorizontal;
+ delete FontRecMenuItem;
+ delete FontRecMenuItemSmall;
+ delete FontRecMenuItemLarge;
+}
+
+void cFontManager::InitialiseFontType(void) {
+ if (tvguideConfig.fontIndex == 0) {
+ fontName = tvguideConfig.fontNameDefault;
+ } else {
+ cStringList availableFonts;
+ cFont::GetAvailableFontNames(&availableFonts);
+ if (availableFonts[tvguideConfig.fontIndex-1]) {
+ fontName = availableFonts[tvguideConfig.fontIndex-1];
+ } else
+ fontName = tvguideConfig.fontNameDefault;
+ }
+ cFont *test = NULL;
+ test = cFont::CreateFont(*fontName, 30);
+ if (!test) {
+ fontName = DefaultFontSml;
+ }
+ delete test;
+ esyslog("tvguide: Set Font to %s", *fontName);
+}
+
+cFont *cFontManager::CreateFont(int size) {
+ return cFont::CreateFont(*fontName, size);
+}
+
diff --git a/fontmanager.h b/fontmanager.h
new file mode 100644
index 0000000..7253043
--- /dev/null
+++ b/fontmanager.h
@@ -0,0 +1,41 @@
+#ifndef __TVGUIDE_FONTMANAGER_H
+#define __TVGUIDE_FONTMANAGER_H
+
+#include <vdr/skins.h>
+
+class cFontManager {
+ cString fontName;
+ void InitialiseFontType(void);
+ cFont *CreateFont(int size);
+ public:
+ cFontManager();
+ ~cFontManager();
+ void SetFonts(void);
+ void DeleteFonts(void);
+ cFont *FontChannelHeader;
+ cFont *FontChannelHeaderHorizontal;
+ cFont *FontChannelGroups;
+ cFont *FontChannelGroupsHorizontal;
+ cFont *FontStatusHeader;
+ cFont *FontStatusHeaderLarge;
+ cFont *FontGrid;
+ cFont *FontGridSmall;
+ cFont *FontGridHorizontal;
+ cFont *FontGridHorizontalSmall;
+ cFont *FontTimeLineWeekday;
+ cFont *FontTimeLineDate;
+ cFont *FontTimeLineDateHorizontal;
+ cFont *FontTimeLineTime;
+ cFont *FontTimeLineTimeHorizontal;
+ cFont *FontButton;
+ cFont *FontDetailView;
+ cFont *FontDetailViewSmall;
+ cFont *FontDetailHeader;
+ cFont *FontDetailHeaderLarge;
+ cFont *FontMessageBox;
+ cFont *FontMessageBoxLarge;
+ cFont *FontRecMenuItem;
+ cFont *FontRecMenuItemSmall;
+ cFont *FontRecMenuItemLarge;
+};
+#endif //__TVGUIDE_FONTMANAGER_H
\ No newline at end of file
diff --git a/footer.c b/footer.c
index 6b908e8..7a5b9e5 100644
--- a/footer.c
+++ b/footer.c
@@ -1,53 +1,167 @@
+#include <string>
+#include "imageloader.h"
+#include "tools.h"
#include "footer.h"
-cFooter::cFooter() {
- buttonBorder = 20;
- buttonWidth = (tvguideConfig.osdWidth - tvguideConfig.timeColWidth - 5*buttonBorder)/4;
- buttonHeight= tvguideConfig.footerHeight - 2*buttonBorder;
- buttonY = (tvguideConfig.footerHeight - buttonHeight)/2;
-
- footer = osdManager.requestPixmap(2, cRect( tvguideConfig.timeColWidth,
- tvguideConfig.osdHeight - tvguideConfig.footerHeight,
- tvguideConfig.osdWidth - tvguideConfig.timeColWidth,
- tvguideConfig.footerHeight),
- cRect::Null, "footer");
+cFooter::cFooter(cChannelGroups *channelGroups) {
+ this->channelGroups = channelGroups;
+ currentGroup = -1;
+ buttonY = (geoManager.footerHeight - geoManager.buttonHeight)/2;
+ SetButtonPositions();
+ footer = osdManager.requestPixmap(2, cRect( 0,
+ geoManager.footerY,
+ geoManager.osdWidth,
+ geoManager.footerHeight),
+ cRect::Null);
footer->Fill(clrTransparent);
}
cFooter::~cFooter(void) {
- osdManager.releasePixmap(footer, "footer");;
+ osdManager.releasePixmap(footer);
}
void cFooter::drawRedButton() {
- cString text(tr("Set Timer"));
- DrawButton(*text, theme.Color(clrButtonRed), theme.Color(clrButtonRedBorder), 0);
+ cString text(tr("Search & Rec"));
+ DrawButton(*text, theme.Color(clrButtonRed), theme.Color(clrButtonRedBorder), oeButtonRed, positionButtons[0]);
}
void cFooter::drawGreenButton() {
cString text = cString::sprintf("%d %s", tvguideConfig.jumpChannels, tr("Channels back"));
- DrawButton(*text, theme.Color(clrButtonGreen), theme.Color(clrButtonGreenBorder), 1);
+ DrawButton(*text, theme.Color(clrButtonGreen), theme.Color(clrButtonGreenBorder), oeButtonGreen, positionButtons[1]);
+}
+
+void cFooter::drawGreenButton(const char *text) {
+ std::string cuttedText = CutText(text, geoManager.buttonWidth-6, fontManager.FontButton);
+ DrawButton(cuttedText.c_str(), theme.Color(clrButtonGreen), theme.Color(clrButtonGreenBorder), oeButtonGreen, positionButtons[1]);
}
void cFooter::drawYellowButton() {
cString text = cString::sprintf("%d %s", tvguideConfig.jumpChannels, tr("Channels forward"));
- DrawButton(*text, theme.Color(clrButtonYellow), theme.Color(clrButtonYellowBorder), 2);
+ DrawButton(*text, theme.Color(clrButtonYellow), theme.Color(clrButtonYellowBorder), oeButtonYellow, positionButtons[2]);
}
-void cFooter::drawBlueButton() {
- cString text(tr("Switch to Channel"));
- DrawButton(*text, theme.Color(clrButtonBlue), theme.Color(clrButtonBlueBorder), 3);
+void cFooter::drawYellowButton(const char *text) {
+ std::string cuttedText = CutText(text, geoManager.buttonWidth-6, fontManager.FontButton);
+ DrawButton(cuttedText.c_str(), theme.Color(clrButtonYellow), theme.Color(clrButtonYellowBorder), oeButtonYellow, positionButtons[2]);
}
-void cFooter::DrawButton(const char *text, tColor color, tColor borderColor, int num) {
-
- int left = num * buttonWidth + (num + 1) * buttonBorder;
- footer->DrawRectangle(cRect(left, buttonY, buttonWidth, buttonHeight), borderColor);
-
- cImageLoader imgLoader;
- imgLoader.DrawBackground(theme.Color(clrButtonBlend), color, buttonWidth-4, buttonHeight-4);
- footer->DrawImage(cPoint(left+2, buttonY+2), imgLoader.GetImage());
+void cFooter::drawBlueButton(bool detailedEPG) {
+ cString text;
+ if (tvguideConfig.blueKeyMode == eBlueKeySwitch)
+ text = tr("Switch to Channel");
+ else if (tvguideConfig.blueKeyMode == eBlueKeyEPG) {
+ if (!detailedEPG)
+ text = tr("Detailed EPG");
+ else
+ text = tr("Close detailed EPG");
+ } else if (tvguideConfig.blueKeyMode == eBlueKeyFavorites) {
+ if (!detailedEPG)
+ text = tr("Favorites");
+ else
+ text = tr("Switch to Channel");
+ }
+ DrawButton(*text, theme.Color(clrButtonBlue), theme.Color(clrButtonBlueBorder), oeButtonBlue, positionButtons[3]);
+}
+
+void cFooter::UpdateGroupButtons(const cChannel *channel, bool force) {
+ if (!channel)
+ return;
+ int group = channelGroups->GetGroup(channel);
+ if ((group != currentGroup) || force) {
+ currentGroup = group;
+ drawGreenButton(channelGroups->GetPrev(group));
+ drawYellowButton(channelGroups->GetNext(group));
+ }
+}
+
+void cFooter::SetDetailedViewMode(bool fromRecMenu) {
+ ClearButton(positionButtons[1]);
+ ClearButton(positionButtons[2]);
+ if (fromRecMenu) {
+ ClearButton(positionButtons[0]);
+ ClearButton(positionButtons[3]);
+ } else if (tvguideConfig.blueKeyMode != eBlueKeySwitch) {
+ ClearButton(positionButtons[3]);
+ drawBlueButton(true);
+ }
+}
+
+void cFooter::LeaveDetailedViewMode(const cChannel *channel) {
+ drawRedButton();
+ drawBlueButton();
+ if (tvguideConfig.channelJumpMode == eNumJump) {
+ drawGreenButton();
+ drawYellowButton();
+ } else {
+ UpdateGroupButtons(channel, true);
+ }
+}
+
+void cFooter::SetButtonPositions(void) {
+ for (int i=0; i < 4; i++) {
+ positionButtons[i] = -1;
+ }
+ /*
+ red button = 0
+ green button = 1
+ yellow button = 2
+ blue button = 3
+ */
+ for (int button=0; button<4; button++) {
+ if (Setup.ColorKey0 == button) {
+ positionButtons[button] = 0;
+ continue;
+ }
+ if (Setup.ColorKey1 == button) {
+ positionButtons[button] = 1;
+ continue;
+ }
+ if (Setup.ColorKey2 == button) {
+ positionButtons[button] = 2;
+ continue;
+ }
+ if (Setup.ColorKey3 == button) {
+ positionButtons[button] = 3;
+ continue;
+ }
+ }
+}
+
+void cFooter::DrawButton(const char *text, tColor color, tColor borderColor, eOsdElementType buttonType, int num) {
+ tColor colorTextBack = (tvguideConfig.style == eStyleFlat)?color:clrTransparent;
+ int left = num * geoManager.buttonWidth + (2 * num + 1) * geoManager.buttonBorder;
+
+ if ((tvguideConfig.style == eStyleBlendingMagick) || (tvguideConfig.style == eStyleBlendingDefault)) {
+ cImageLoader imgLoader;
+ imgLoader.DrawBackground(theme.Color(clrButtonBlend), color, geoManager.buttonWidth-4, geoManager.buttonHeight-4);
+ footer->DrawRectangle(cRect(left, buttonY, geoManager.buttonWidth, geoManager.buttonHeight), borderColor);
+ footer->DrawImage(cPoint(left+2, buttonY+2), imgLoader.GetImage());
+ if (tvguideConfig.roundedCorners) {
+ int borderRadius = 12;
+ int borderWidth = 2;
+ DrawRoundedCorners(footer, left, buttonY, geoManager.buttonWidth, geoManager.buttonHeight, borderRadius, borderWidth, borderColor);
+ }
+ } else if (tvguideConfig.style == eStyleGraphical) {
+ cImage *button = imgCache.GetOsdElement(buttonType);
+ if (button) {
+ footer->DrawImage(cPoint(left, buttonY), *button);
+ }
+ } else {
+ footer->DrawRectangle(cRect(left, buttonY, geoManager.buttonWidth, geoManager.buttonHeight), borderColor);
+ footer->DrawRectangle(cRect(left+1, buttonY+1, geoManager.buttonWidth-2, geoManager.buttonHeight-2), color);
+ if (tvguideConfig.roundedCorners) {
+ int borderRadius = 12;
+ int borderWidth = 1;
+ DrawRoundedCorners(footer, left, buttonY, geoManager.buttonWidth, geoManager.buttonHeight, borderRadius, borderWidth, borderColor);
+ }
+ }
- int textWidth = tvguideConfig.FontButton->Width(text);
- int textHeight = tvguideConfig.FontButton->Height();
- footer->DrawText(cPoint(left + (buttonWidth-textWidth)/2, buttonY + (buttonHeight-textHeight)/2), text, theme.Color(clrFontButtons), clrTransparent, tvguideConfig.FontButton);
+ int textWidth = fontManager.FontButton->Width(text);
+ int textHeight = fontManager.FontButton->Height();
+ footer->DrawText(cPoint(left + (geoManager.buttonWidth-textWidth)/2, buttonY + (geoManager.buttonHeight-textHeight)/2), text, theme.Color(clrFontButtons), colorTextBack, fontManager.FontButton);
+}
+
+void cFooter::ClearButton(int num) {
+ int left = num * geoManager.buttonWidth + (2 * num + 1) * geoManager.buttonBorder;
+ footer->DrawRectangle(cRect(left, buttonY, geoManager.buttonWidth, geoManager.buttonHeight), clrTransparent);
}
\ No newline at end of file
diff --git a/footer.h b/footer.h
index 805ab0a..e923476 100644
--- a/footer.h
+++ b/footer.h
@@ -1,23 +1,33 @@
#ifndef __TVGUIDE_FOOTER_H
#define __TVGUIDE_FOOTER_H
+#include <vdr/osd.h>
+#include "channelgroups.h"
+
// --- cFooter -------------------------------------------------------------
class cFooter {
private:
- cPixmap *footer;
- int buttonWidth;
- int buttonHeight;
+ cPixmap *footer;
int buttonY;
- int buttonBorder;
- void DrawButton(const char *text, tColor color, tColor borderColor, int num);
+ int positionButtons[4];
+ cChannelGroups *channelGroups;
+ int currentGroup;
+ void SetButtonPositions(void);
+ void DrawButton(const char *text, tColor color, tColor borderColor, eOsdElementType buttonType, int num);
+ void ClearButton(int num);
public:
- cFooter();
- virtual ~cFooter(void);
- void drawRedButton();
- void drawGreenButton();
- void drawYellowButton();
- void drawBlueButton();
+ cFooter(cChannelGroups *channelGroups);
+ virtual ~cFooter(void);
+ void drawRedButton();
+ void drawGreenButton();
+ void drawGreenButton(const char *text);
+ void drawYellowButton();
+ void drawYellowButton(const char *text);
+ void drawBlueButton(bool detailedEPG = false);
+ void UpdateGroupButtons(const cChannel *channel, bool force = false);
+ void SetDetailedViewMode(bool fromRecMenu = false);
+ void LeaveDetailedViewMode(const cChannel *channel);
};
#endif //__TVGUIDE_FOOTER_H
\ No newline at end of file
diff --git a/geometrymanager.c b/geometrymanager.c
new file mode 100644
index 0000000..94d47b7
--- /dev/null
+++ b/geometrymanager.c
@@ -0,0 +1,74 @@
+#include <vdr/osd.h>
+
+#include "config.h"
+#include "geometrymanager.h"
+
+cGeometryManager::cGeometryManager() {
+ osdWidth = 0;
+ osdHeight = 0;
+}
+
+cGeometryManager::~cGeometryManager() {
+}
+
+bool cGeometryManager::SetGeometry(int osdWidth, int osdHeight, bool force) {
+ if (!force && (this->osdWidth == osdWidth) && (this->osdHeight == osdHeight)) {
+ esyslog("tvgudie: GeoManager SetGeometry nothing to change");
+ return false;
+ }
+ this->osdWidth = osdWidth;
+ this->osdHeight = osdHeight;
+ esyslog("tvguide: Set OSD to %d x %d px", osdWidth, osdHeight);
+
+ statusHeaderHeight = (tvguideConfig.displayStatusHeader)?(tvguideConfig.headerHeightPercent * osdHeight / 100):0;
+ tvFrameWidth = statusHeaderHeight * 16 / 9;
+ headerContentWidth = (tvguideConfig.scaleVideo)?(osdWidth - tvFrameWidth):osdWidth;
+ channelGroupsWidth = (tvguideConfig.displayChannelGroups)?(tvguideConfig.channelGroupsPercent * osdWidth / 100):0;
+ channelGroupsHeight = (tvguideConfig.displayChannelGroups)?(tvguideConfig.channelGroupsPercent * osdHeight / 100):0;
+ channelHeaderWidth = tvguideConfig.channelHeaderWidthPercent * osdWidth / 100;
+ channelHeaderHeight = tvguideConfig.channelHeaderHeightPercent * osdHeight / 100;
+ timeLineWidth = tvguideConfig.timeLineWidthPercent * osdWidth / 100;
+ timeLineHeight = tvguideConfig.timeLineHeightPercent * osdHeight / 100;
+ clockWidth = tvFrameWidth / 3;
+ clockHeight = timeLineHeight;
+ footerHeight = tvguideConfig.footerHeightPercent * osdHeight / 100;
+ footerY = osdHeight - footerHeight;
+
+ if (tvguideConfig.displayMode == eVertical) {
+ colWidth = (osdWidth - timeLineWidth) / tvguideConfig.channelCols;
+ rowHeight = 0;
+ minutePixel = (osdHeight - statusHeaderHeight - channelGroupsHeight - channelHeaderHeight - footerHeight) / tvguideConfig.displayTime;
+ channelLogoWidth = colWidth;
+ channelLogoHeight = channelHeaderHeight;
+ logoWidth = channelLogoWidth/2 - 15;
+ logoHeight = logoWidth * tvguideConfig.logoHeightRatio / tvguideConfig.logoWidthRatio;
+ timeLineGridWidth = timeLineWidth;
+ timeLineGridHeight = minutePixel*30;
+ dateVieverWidth = timeLineWidth;
+ dateVieverHeight = channelHeaderHeight + channelGroupsHeight;
+ } else if (tvguideConfig.displayMode == eHorizontal) {
+ colWidth = 0;
+ rowHeight = (osdHeight - statusHeaderHeight - timeLineHeight - footerHeight) / tvguideConfig.channelRows;
+ minutePixel = (osdWidth - channelHeaderWidth - channelGroupsWidth) / tvguideConfig.displayTime;
+ channelLogoWidth = channelHeaderWidth;
+ channelLogoHeight = rowHeight;
+ logoWidth = channelLogoHeight * tvguideConfig.logoWidthRatio / tvguideConfig.logoHeightRatio;
+ logoHeight = channelLogoHeight;
+ timeLineGridWidth = geoManager.minutePixel*30;
+ timeLineGridHeight = geoManager.timeLineHeight;
+ dateVieverWidth = channelHeaderWidth + channelGroupsWidth;
+ dateVieverHeight = timeLineHeight;
+ }
+ buttonBorder = footerHeight / 6;
+ buttonWidth = osdWidth / 4 - 2 * buttonBorder;
+ buttonHeight = footerHeight - 3 * buttonBorder;
+
+ epgViewHeaderHeight = tvguideConfig.headerHeightPercent * osdHeight / 100;
+
+ borderRecMenus = 10;
+
+ channelJumpWidth = osdWidth * 30 / 100;
+ channelJumpHeight = osdHeight * 20 / 100;
+
+ return true;
+}
\ No newline at end of file
diff --git a/geometrymanager.h b/geometrymanager.h
new file mode 100644
index 0000000..ecd31b9
--- /dev/null
+++ b/geometrymanager.h
@@ -0,0 +1,54 @@
+#ifndef __TVGUIDE_GEOMETRYMANAGER_H
+#define __TVGUIDE_GEOMETRYMANAGER_H
+
+class cGeometryManager {
+private:
+public:
+ cGeometryManager(void);
+ ~cGeometryManager();
+ bool SetGeometry(int osdWidth, int osdHeight, bool force = false);
+ //Common
+ int osdWidth;
+ int osdHeight;
+ int statusHeaderHeight;
+ int tvFrameWidth;
+ int headerContentWidth;
+ //ChannelGroups
+ int channelGroupsWidth;
+ int channelGroupsHeight;
+ //ContentHeader
+ int channelHeaderWidth;
+ int channelHeaderHeight;
+ int logoWidth;
+ int logoHeight;
+ //Content
+ int colWidth;
+ int rowHeight;
+ int minutePixel;
+ int channelLogoWidth;
+ int channelLogoHeight;
+ //Timeline
+ int timeLineWidth;
+ int timeLineHeight;
+ int timeLineGridWidth;
+ int timeLineGridHeight;
+ int dateVieverWidth;
+ int dateVieverHeight;
+ int clockWidth;
+ int clockHeight;
+ //Footer
+ int footerY;
+ int footerHeight;
+ int buttonWidth;
+ int buttonHeight;
+ int buttonBorder;
+ //Detailed EPG View
+ int epgViewHeaderHeight;
+ //Recording Menus
+ int borderRecMenus;
+ //Channel Jump
+ int channelJumpWidth;
+ int channelJumpHeight;
+};
+
+#endif //__TVGUIDE_GEOMETRYMANAGER_H
\ No newline at end of file
diff --git a/grid.c b/grid.c
new file mode 100644
index 0000000..9a878d4
--- /dev/null
+++ b/grid.c
@@ -0,0 +1,82 @@
+#include "channelcolumn.h"
+#include "grid.h"
+
+cGrid::cGrid(cChannelColumn *c) {
+ this->column = c;
+ text = new cTextWrapper();
+ dirty = true;
+ active = false;
+ viewportHeight = 0;
+ borderWidth = 10;
+}
+
+cGrid::~cGrid(void) {
+ delete text;
+}
+
+void cGrid::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 cGrid::Draw() {
+ if (!pixmap) {
+ return;
+ }
+ if (dirty) {
+ if (tvguideConfig.style == eStyleGraphical) {
+ drawBackgroundGraphical(bgGrid, active);
+ drawText();
+ } else {
+ setBackground();
+ drawBackground();
+ drawText();
+ drawBorder();
+ }
+ pixmap->SetLayer(1);
+ dirty = false;
+ }
+}
+
+bool cGrid::isFirst(void) {
+ if (column->isFirst(this))
+ return true;
+ return false;
+}
+
+bool cGrid::Match(time_t t) {
+ if ((StartTime() < t) && (EndTime() > t))
+ return true;
+ else
+ return false;
+}
+
+int cGrid::calcOverlap(cGrid *neighbor) {
+ int overlap = 0;
+ if (intersects(neighbor)) {
+ if ((StartTime() <= neighbor->StartTime()) && (EndTime() <= neighbor->EndTime())) {
+ overlap = EndTime() - neighbor->StartTime();
+ } else if ((StartTime() >= neighbor->StartTime()) && (EndTime() >= neighbor->EndTime())) {
+ overlap = neighbor->EndTime() - StartTime();
+ } else if ((StartTime() >= neighbor->StartTime()) && (EndTime() <= neighbor->EndTime())) {
+ overlap = Duration();
+ } else if ((StartTime() <= neighbor->StartTime()) && (EndTime() >= neighbor->EndTime())) {
+ overlap = neighbor->EndTime() - neighbor->StartTime();
+ }
+ }
+ return overlap;
+}
+
+bool cGrid::intersects(cGrid *neighbor) {
+ return ! ( (neighbor->EndTime() <= StartTime()) || (neighbor->StartTime() >= EndTime()) );
+}
diff --git a/grid.h b/grid.h
new file mode 100644
index 0000000..bd35af1
--- /dev/null
+++ b/grid.h
@@ -0,0 +1,58 @@
+#ifndef __TVGUIDE_GRID_H
+#define __TVGUIDE_GRID_H
+
+#include <vdr/tools.h>
+#include "styledpixmap.h"
+
+class cChannelColumn;
+
+// --- cEpgGrid -------------------------------------------------------------
+
+class cGrid : public cListObject, public cStyledPixmap {
+protected:
+ cTextWrapper *text;
+ int viewportHeight;
+ int borderWidth;
+ void setBackground();
+ bool isColor1;
+ bool active;
+ bool dirty;
+ bool hasTimer;
+ bool hasSwitchTimer;
+ bool intersects(cGrid *neighbor);
+ virtual time_t Duration(void) {};
+ virtual void drawText(void) {};
+ bool dummy;
+public:
+ cGrid(cChannelColumn *c);
+ virtual ~cGrid(void);
+ cChannelColumn *column;
+ virtual void SetViewportHeight() {};
+ virtual void PositionPixmap() {};
+ virtual void setText(void) {};
+ 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;};
+ bool isFirst(void);
+ virtual const cEvent *GetEvent() {};
+ bool Match(time_t t);
+ virtual time_t StartTime() {};
+ virtual time_t EndTime() {};
+ virtual void SetStartTime(time_t start) {};
+ virtual void SetEndTime(time_t end) {};
+ int calcOverlap(cGrid *neighbor);
+ virtual void SetTimer() {};
+ virtual void SetSwitchTimer() {};
+ virtual cString getText(void) { return cString("");};
+ virtual cString getTimeString(void) { return cString("");};
+ bool Active(void) { return active; };
+ bool HasTimer() {return hasTimer;};
+ bool HasSwitchTimer() {return hasSwitchTimer;};
+ bool isDummy() { return dummy; };
+ virtual void debug() {};
+};
+
+#endif //__TVGUIDE_GRID_H
\ No newline at end of file
diff --git a/headergrid.c b/headergrid.c
new file mode 100644
index 0000000..ec6a991
--- /dev/null
+++ b/headergrid.c
@@ -0,0 +1,128 @@
+#include "imageloader.h"
+#include "tools.h"
+#include "headergrid.h"
+
+cHeaderGrid::cHeaderGrid(void) : cGrid(NULL) {
+ pixmap = NULL;
+ pixmapLogo = NULL;
+}
+
+cHeaderGrid::~cHeaderGrid(void) {
+ osdManager.releasePixmap(pixmapLogo);
+}
+
+void cHeaderGrid::createBackground(int num) {
+ color = theme.Color(clrHeader);
+ colorBlending = theme.Color(clrHeaderBlending);
+ int x, y;
+ if (tvguideConfig.displayMode == eVertical) {
+ x = geoManager.timeLineWidth + num*geoManager.colWidth;
+ y = geoManager.statusHeaderHeight + geoManager.channelGroupsHeight;
+ } else if (tvguideConfig.displayMode == eHorizontal) {
+ x = geoManager.channelGroupsWidth;
+ y = geoManager.statusHeaderHeight + geoManager.timeLineHeight + num*geoManager.rowHeight;
+ }
+ pixmap = osdManager.requestPixmap(1, cRect(x, y, geoManager.channelLogoWidth, geoManager.channelLogoHeight));
+ pixmapLogo = osdManager.requestPixmap(2, cRect(x, y, geoManager.channelLogoWidth, geoManager.channelLogoHeight));
+ if ((!pixmap) || (!pixmapLogo)){
+ return;
+ }
+ pixmapLogo->Fill(clrTransparent);
+ if (tvguideConfig.style == eStyleGraphical) {
+ drawBackgroundGraphical(bgChannelHeader);
+ } else {
+ drawBackground();
+ drawBorder();
+ }
+}
+
+void cHeaderGrid::drawChannel(const cChannel *channel) {
+ if (tvguideConfig.displayMode == eVertical) {
+ drawChannelVertical(channel);
+ } else if (tvguideConfig.displayMode == eHorizontal) {
+ drawChannelHorizontal(channel);
+ }
+}
+
+void cHeaderGrid::drawChannelHorizontal(const cChannel *channel) {
+ int logoWidth = geoManager.logoWidth;
+ int logoX = tvguideConfig.displayChannelName?2:(Width()-logoWidth)/2;
+ int textX = 5;
+ int textY = (Height() - fontManager.FontChannelHeaderHorizontal->Height())/2;
+ bool logoFound = false;
+ if (!tvguideConfig.hideChannelLogos) {
+ cImage *logo = imgCache.GetLogo(channel);
+ if (logo) {
+ pixmapLogo->DrawImage(cPoint(logoX, 0), *logo);
+ logoFound = true;
+ }
+ }
+ bool drawText = false;
+ int textWidthMax = Width() - 10;
+ if (!logoFound) {
+ drawText = true;
+ } else if (tvguideConfig.displayChannelName) {
+ drawText = true;
+ textX += logoWidth;
+ textWidthMax -= logoWidth;
+ }
+ if (drawText) {
+ tColor colorTextBack = (tvguideConfig.style == eStyleFlat)?color:clrTransparent;
+ cString strChannel = cString::sprintf("%d %s", channel->Number(), channel->Name());
+ strChannel = CutText(*strChannel, textWidthMax, fontManager.FontChannelHeaderHorizontal).c_str();
+ pixmap->DrawText(cPoint(textX, textY), *strChannel, theme.Color(clrFontHeader), colorTextBack, fontManager.FontChannelHeaderHorizontal);
+ }
+}
+
+void cHeaderGrid::drawChannelVertical(const cChannel *channel) {
+ int logoWidth = geoManager.logoWidth;
+ int logoHeight = geoManager.logoHeight;
+ cTextWrapper tw;
+ cString headerText = cString::sprintf("%d - %s", channel->Number(), channel->Name());
+ tw.Set(*headerText, fontManager.FontChannelHeader, geoManager.colWidth - 8);
+ int lines = tw.Lines();
+ int lineHeight = fontManager.FontChannelHeader->Height();
+ int yStart = (geoManager.channelHeaderHeight - lines*lineHeight)/2 + 8;
+ bool logoFound = false;
+ if (!tvguideConfig.hideChannelLogos) {
+ cImage *logo = imgCache.GetLogo(channel);
+ if (logo) {
+ pixmapLogo->DrawImage(cPoint((Width() - logoWidth)/2, 4), *logo);
+ logoFound = true;
+ }
+ }
+ bool drawText = false;
+ if (!logoFound) {
+ drawText = true;
+ } else if (tvguideConfig.displayChannelName) {
+ drawText = true;
+ yStart = logoHeight;
+ }
+ if (!drawText)
+ return;
+ tColor colorTextBack = (tvguideConfig.style == eStyleFlat)?color:clrTransparent;
+ for (int i=0; i<lines; i++) {
+ int textWidth = fontManager.FontChannelHeader->Width(tw.GetLine(i));
+ int xText = (geoManager.colWidth - textWidth) / 2;
+ if (xText < 0)
+ xText = 0;
+ pixmap->DrawText(cPoint(xText, yStart + i*lineHeight), tw.GetLine(i), theme.Color(clrFontHeader), colorTextBack, fontManager.FontChannelHeader);
+ }
+}
+
+void cHeaderGrid::setPosition(int num) {
+ int x, y, width, height;
+ if (tvguideConfig.displayMode == eVertical) {
+ x = geoManager.timeLineWidth + num*geoManager.colWidth;
+ y = geoManager.statusHeaderHeight + geoManager.channelGroupsHeight;
+ width = geoManager.colWidth;
+ height = geoManager.channelHeaderHeight;
+ } else if (tvguideConfig.displayMode == eHorizontal) {
+ x = geoManager.channelGroupsWidth;
+ y = geoManager.statusHeaderHeight + geoManager.timeLineHeight + num*geoManager.rowHeight;
+ width = geoManager.channelHeaderWidth;
+ height = geoManager.rowHeight;
+ }
+ pixmap->SetViewPort(cRect(x, y, width, height));
+ pixmapLogo->SetViewPort(cRect(x, y, width, height));
+}
diff --git a/headergrid.h b/headergrid.h
new file mode 100644
index 0000000..a4f0962
--- /dev/null
+++ b/headergrid.h
@@ -0,0 +1,21 @@
+#ifndef __TVGUIDE_HEADERGRID_H
+#define __TVGUIDE_HEADERGRID_H
+
+#include "grid.h"
+
+// --- cHeaderGrid -------------------------------------------------------------
+
+class cHeaderGrid : public cGrid {
+private:
+ cPixmap *pixmapLogo;
+ void drawChannelHorizontal(const cChannel *channel);
+ void drawChannelVertical(const cChannel *channel);
+public:
+ cHeaderGrid(void);
+ virtual ~cHeaderGrid(void);
+ void createBackground(int num);
+ void drawChannel(const cChannel *channel);
+ void setPosition(int num);
+};
+
+#endif //__TVGUIDE_HEADERGRID_H
\ No newline at end of file
diff --git a/icons/darkredNG/osdElements/button_30percent.png b/icons/darkredNG/osdElements/button_30percent.png
new file mode 100644
index 0000000..58f0281
Binary files /dev/null and b/icons/darkredNG/osdElements/button_30percent.png differ
diff --git a/icons/darkredNG/osdElements/button_70percent.png b/icons/darkredNG/osdElements/button_70percent.png
new file mode 100644
index 0000000..7234f08
Binary files /dev/null and b/icons/darkredNG/osdElements/button_70percent.png differ
diff --git a/icons/darkredNG/osdElements/button_active_30percent.png b/icons/darkredNG/osdElements/button_active_30percent.png
new file mode 100644
index 0000000..1b5aab0
Binary files /dev/null and b/icons/darkredNG/osdElements/button_active_30percent.png differ
diff --git a/icons/darkredNG/osdElements/button_active_70percent.png b/icons/darkredNG/osdElements/button_active_70percent.png
new file mode 100644
index 0000000..ba09ea0
Binary files /dev/null and b/icons/darkredNG/osdElements/button_active_70percent.png differ
diff --git a/icons/darkredNG/osdElements/buttonblue.png b/icons/darkredNG/osdElements/buttonblue.png
new file mode 100644
index 0000000..ac3536c
Binary files /dev/null and b/icons/darkredNG/osdElements/buttonblue.png differ
diff --git a/icons/darkredNG/osdElements/buttongreen.png b/icons/darkredNG/osdElements/buttongreen.png
new file mode 100644
index 0000000..e598518
Binary files /dev/null and b/icons/darkredNG/osdElements/buttongreen.png differ
diff --git a/icons/darkredNG/osdElements/buttonred.png b/icons/darkredNG/osdElements/buttonred.png
new file mode 100644
index 0000000..152acad
Binary files /dev/null and b/icons/darkredNG/osdElements/buttonred.png differ
diff --git a/icons/darkredNG/osdElements/buttonyellow.png b/icons/darkredNG/osdElements/buttonyellow.png
new file mode 100644
index 0000000..1b448c9
Binary files /dev/null and b/icons/darkredNG/osdElements/buttonyellow.png differ
diff --git a/icons/darkredNG/osdElements/channel_jump.png b/icons/darkredNG/osdElements/channel_jump.png
new file mode 100644
index 0000000..7f45bd4
Binary files /dev/null and b/icons/darkredNG/osdElements/channel_jump.png differ
diff --git a/icons/darkredNG/osdElements/channelgroup_bottom.png b/icons/darkredNG/osdElements/channelgroup_bottom.png
new file mode 100644
index 0000000..7127ea7
Binary files /dev/null and b/icons/darkredNG/osdElements/channelgroup_bottom.png differ
diff --git a/icons/darkredNG/osdElements/channelgroup_head.png b/icons/darkredNG/osdElements/channelgroup_head.png
new file mode 100644
index 0000000..bce9d22
Binary files /dev/null and b/icons/darkredNG/osdElements/channelgroup_head.png differ
diff --git a/icons/darkredNG/osdElements/channelgroup_horizontal.png b/icons/darkredNG/osdElements/channelgroup_horizontal.png
new file mode 100644
index 0000000..13d733c
Binary files /dev/null and b/icons/darkredNG/osdElements/channelgroup_horizontal.png differ
diff --git a/icons/darkredNG/osdElements/channelgroup_left.png b/icons/darkredNG/osdElements/channelgroup_left.png
new file mode 100644
index 0000000..df495b1
Binary files /dev/null and b/icons/darkredNG/osdElements/channelgroup_left.png differ
diff --git a/icons/darkredNG/osdElements/channelgroup_right.png b/icons/darkredNG/osdElements/channelgroup_right.png
new file mode 100644
index 0000000..42dcf6d
Binary files /dev/null and b/icons/darkredNG/osdElements/channelgroup_right.png differ
diff --git a/icons/darkredNG/osdElements/channelgroup_vertical.png b/icons/darkredNG/osdElements/channelgroup_vertical.png
new file mode 100644
index 0000000..43778d0
Binary files /dev/null and b/icons/darkredNG/osdElements/channelgroup_vertical.png differ
diff --git a/icons/darkredNG/osdElements/channellogoback_horizontal.png b/icons/darkredNG/osdElements/channellogoback_horizontal.png
new file mode 100644
index 0000000..d9bb54a
Binary files /dev/null and b/icons/darkredNG/osdElements/channellogoback_horizontal.png differ
diff --git a/icons/darkredNG/osdElements/channellogoback_vertical.png b/icons/darkredNG/osdElements/channellogoback_vertical.png
new file mode 100644
index 0000000..06684cc
Binary files /dev/null and b/icons/darkredNG/osdElements/channellogoback_vertical.png differ
diff --git a/icons/darkredNG/osdElements/clock.png b/icons/darkredNG/osdElements/clock.png
new file mode 100644
index 0000000..2e8686e
Binary files /dev/null and b/icons/darkredNG/osdElements/clock.png differ
diff --git a/icons/darkredNG/osdElements/date_vertical.png b/icons/darkredNG/osdElements/date_vertical.png
new file mode 100644
index 0000000..58a72e4
Binary files /dev/null and b/icons/darkredNG/osdElements/date_vertical.png differ
diff --git a/icons/darkredNG/osdElements/grid_active_bottom.png b/icons/darkredNG/osdElements/grid_active_bottom.png
new file mode 100644
index 0000000..08de467
Binary files /dev/null and b/icons/darkredNG/osdElements/grid_active_bottom.png differ
diff --git a/icons/darkredNG/osdElements/grid_active_head.png b/icons/darkredNG/osdElements/grid_active_head.png
new file mode 100644
index 0000000..060a908
Binary files /dev/null and b/icons/darkredNG/osdElements/grid_active_head.png differ
diff --git a/icons/darkredNG/osdElements/grid_active_horizontal.png b/icons/darkredNG/osdElements/grid_active_horizontal.png
new file mode 100644
index 0000000..9319d6b
Binary files /dev/null and b/icons/darkredNG/osdElements/grid_active_horizontal.png differ
diff --git a/icons/darkredNG/osdElements/grid_active_left.png b/icons/darkredNG/osdElements/grid_active_left.png
new file mode 100644
index 0000000..7852d94
Binary files /dev/null and b/icons/darkredNG/osdElements/grid_active_left.png differ
diff --git a/icons/darkredNG/osdElements/grid_active_right.png b/icons/darkredNG/osdElements/grid_active_right.png
new file mode 100644
index 0000000..73dfbd0
Binary files /dev/null and b/icons/darkredNG/osdElements/grid_active_right.png differ
diff --git a/icons/darkredNG/osdElements/grid_active_vertical.png b/icons/darkredNG/osdElements/grid_active_vertical.png
new file mode 100644
index 0000000..6d96d34
Binary files /dev/null and b/icons/darkredNG/osdElements/grid_active_vertical.png differ
diff --git a/icons/darkredNG/osdElements/grid_bottom.png b/icons/darkredNG/osdElements/grid_bottom.png
new file mode 100644
index 0000000..82c20c4
Binary files /dev/null and b/icons/darkredNG/osdElements/grid_bottom.png differ
diff --git a/icons/darkredNG/osdElements/grid_head.png b/icons/darkredNG/osdElements/grid_head.png
new file mode 100644
index 0000000..f434c11
Binary files /dev/null and b/icons/darkredNG/osdElements/grid_head.png differ
diff --git a/icons/darkredNG/osdElements/grid_horizontal.png b/icons/darkredNG/osdElements/grid_horizontal.png
new file mode 100644
index 0000000..6f28550
Binary files /dev/null and b/icons/darkredNG/osdElements/grid_horizontal.png differ
diff --git a/icons/darkredNG/osdElements/grid_left.png b/icons/darkredNG/osdElements/grid_left.png
new file mode 100644
index 0000000..df80f91
Binary files /dev/null and b/icons/darkredNG/osdElements/grid_left.png differ
diff --git a/icons/darkredNG/osdElements/grid_right.png b/icons/darkredNG/osdElements/grid_right.png
new file mode 100644
index 0000000..d39470f
Binary files /dev/null and b/icons/darkredNG/osdElements/grid_right.png differ
diff --git a/icons/darkredNG/osdElements/grid_vertical.png b/icons/darkredNG/osdElements/grid_vertical.png
new file mode 100644
index 0000000..6ad219d
Binary files /dev/null and b/icons/darkredNG/osdElements/grid_vertical.png differ
diff --git a/icons/darkredNG/osdElements/recmenu_background.png b/icons/darkredNG/osdElements/recmenu_background.png
new file mode 100644
index 0000000..2ab2573
Binary files /dev/null and b/icons/darkredNG/osdElements/recmenu_background.png differ
diff --git a/icons/darkredNG/osdElements/statusheader_content_full.png b/icons/darkredNG/osdElements/statusheader_content_full.png
new file mode 100644
index 0000000..7fd6885
Binary files /dev/null and b/icons/darkredNG/osdElements/statusheader_content_full.png differ
diff --git a/icons/darkredNG/osdElements/statusheader_content_windowed.png b/icons/darkredNG/osdElements/statusheader_content_windowed.png
new file mode 100644
index 0000000..56a60a7
Binary files /dev/null and b/icons/darkredNG/osdElements/statusheader_content_windowed.png differ
diff --git a/icons/darkredNG/osdElements/statusheader_tvframe.png b/icons/darkredNG/osdElements/statusheader_tvframe.png
new file mode 100644
index 0000000..261fea3
Binary files /dev/null and b/icons/darkredNG/osdElements/statusheader_tvframe.png differ
diff --git a/icons/darkredNG/osdElements/timeline1_horizontal.png b/icons/darkredNG/osdElements/timeline1_horizontal.png
new file mode 100644
index 0000000..9240b37
Binary files /dev/null and b/icons/darkredNG/osdElements/timeline1_horizontal.png differ
diff --git a/icons/darkredNG/osdElements/timeline1_vertical.png b/icons/darkredNG/osdElements/timeline1_vertical.png
new file mode 100644
index 0000000..5466546
Binary files /dev/null and b/icons/darkredNG/osdElements/timeline1_vertical.png differ
diff --git a/icons/darkredNG/osdElements/timeline2_horizontal.png b/icons/darkredNG/osdElements/timeline2_horizontal.png
new file mode 100644
index 0000000..4364677
Binary files /dev/null and b/icons/darkredNG/osdElements/timeline2_horizontal.png differ
diff --git a/icons/darkredNG/osdElements/timeline2_vertical.png b/icons/darkredNG/osdElements/timeline2_vertical.png
new file mode 100644
index 0000000..dfa06c9
Binary files /dev/null and b/icons/darkredNG/osdElements/timeline2_vertical.png differ
diff --git a/icons/darkredNG/recmenuicons/activetimer.png b/icons/darkredNG/recmenuicons/activetimer.png
new file mode 100644
index 0000000..af4c33c
Binary files /dev/null and b/icons/darkredNG/recmenuicons/activetimer.png differ
diff --git a/icons/darkredNG/recmenuicons/arrow_left.png b/icons/darkredNG/recmenuicons/arrow_left.png
new file mode 100644
index 0000000..57800c7
Binary files /dev/null and b/icons/darkredNG/recmenuicons/arrow_left.png differ
diff --git a/icons/darkredNG/recmenuicons/arrow_right.png b/icons/darkredNG/recmenuicons/arrow_right.png
new file mode 100644
index 0000000..ea45f3a
Binary files /dev/null and b/icons/darkredNG/recmenuicons/arrow_right.png differ
diff --git a/icons/darkredNG/recmenuicons/delete_active.png b/icons/darkredNG/recmenuicons/delete_active.png
new file mode 100644
index 0000000..f473717
Binary files /dev/null and b/icons/darkredNG/recmenuicons/delete_active.png differ
diff --git a/icons/darkredNG/recmenuicons/delete_inactive.png b/icons/darkredNG/recmenuicons/delete_inactive.png
new file mode 100644
index 0000000..21b0a88
Binary files /dev/null and b/icons/darkredNG/recmenuicons/delete_inactive.png differ
diff --git a/icons/darkredNG/recmenuicons/edit_active.png b/icons/darkredNG/recmenuicons/edit_active.png
new file mode 100644
index 0000000..ec39699
Binary files /dev/null and b/icons/darkredNG/recmenuicons/edit_active.png differ
diff --git a/icons/darkredNG/recmenuicons/edit_inactive.png b/icons/darkredNG/recmenuicons/edit_inactive.png
new file mode 100644
index 0000000..71f016c
Binary files /dev/null and b/icons/darkredNG/recmenuicons/edit_inactive.png differ
diff --git a/icons/darkredNG/recmenuicons/icon_backspace.png b/icons/darkredNG/recmenuicons/icon_backspace.png
new file mode 100644
index 0000000..6065fa3
Binary files /dev/null and b/icons/darkredNG/recmenuicons/icon_backspace.png differ
diff --git a/icons/darkredNG/recmenuicons/icon_del_ins.png b/icons/darkredNG/recmenuicons/icon_del_ins.png
new file mode 100644
index 0000000..f05a96b
Binary files /dev/null and b/icons/darkredNG/recmenuicons/icon_del_ins.png differ
diff --git a/icons/darkredNG/recmenuicons/icon_shift.png b/icons/darkredNG/recmenuicons/icon_shift.png
new file mode 100644
index 0000000..15ae851
Binary files /dev/null and b/icons/darkredNG/recmenuicons/icon_shift.png differ
diff --git a/icons/darkredNG/recmenuicons/info_active.png b/icons/darkredNG/recmenuicons/info_active.png
new file mode 100644
index 0000000..c88f76d
Binary files /dev/null and b/icons/darkredNG/recmenuicons/info_active.png differ
diff --git a/icons/darkredNG/recmenuicons/info_inactive.png b/icons/darkredNG/recmenuicons/info_inactive.png
new file mode 100644
index 0000000..37eeed2
Binary files /dev/null and b/icons/darkredNG/recmenuicons/info_inactive.png differ
diff --git a/icons/darkredNG/recmenuicons/no.png b/icons/darkredNG/recmenuicons/no.png
new file mode 100644
index 0000000..47cdba0
Binary files /dev/null and b/icons/darkredNG/recmenuicons/no.png differ
diff --git a/icons/darkredNG/recmenuicons/record_active.png b/icons/darkredNG/recmenuicons/record_active.png
new file mode 100644
index 0000000..476da99
Binary files /dev/null and b/icons/darkredNG/recmenuicons/record_active.png differ
diff --git a/icons/darkredNG/recmenuicons/record_inactive.png b/icons/darkredNG/recmenuicons/record_inactive.png
new file mode 100644
index 0000000..2a91da3
Binary files /dev/null and b/icons/darkredNG/recmenuicons/record_inactive.png differ
diff --git a/icons/darkredNG/recmenuicons/search_active.png b/icons/darkredNG/recmenuicons/search_active.png
new file mode 100644
index 0000000..7bf7bc7
Binary files /dev/null and b/icons/darkredNG/recmenuicons/search_active.png differ
diff --git a/icons/darkredNG/recmenuicons/search_inactive.png b/icons/darkredNG/recmenuicons/search_inactive.png
new file mode 100644
index 0000000..4a210bb
Binary files /dev/null and b/icons/darkredNG/recmenuicons/search_inactive.png differ
diff --git a/icons/darkredNG/recmenuicons/yes.png b/icons/darkredNG/recmenuicons/yes.png
new file mode 100644
index 0000000..2f1af98
Binary files /dev/null and b/icons/darkredNG/recmenuicons/yes.png differ
diff --git a/icons/default/osdElements/button_30percent.png b/icons/default/osdElements/button_30percent.png
new file mode 100644
index 0000000..565d16e
Binary files /dev/null and b/icons/default/osdElements/button_30percent.png differ
diff --git a/icons/default/osdElements/button_70percent.png b/icons/default/osdElements/button_70percent.png
new file mode 100644
index 0000000..7a43e01
Binary files /dev/null and b/icons/default/osdElements/button_70percent.png differ
diff --git a/icons/default/osdElements/button_active_30percent.png b/icons/default/osdElements/button_active_30percent.png
new file mode 100644
index 0000000..97392fd
Binary files /dev/null and b/icons/default/osdElements/button_active_30percent.png differ
diff --git a/icons/default/osdElements/button_active_70percent.png b/icons/default/osdElements/button_active_70percent.png
new file mode 100644
index 0000000..22d167e
Binary files /dev/null and b/icons/default/osdElements/button_active_70percent.png differ
diff --git a/icons/default/osdElements/buttonblue.png b/icons/default/osdElements/buttonblue.png
new file mode 100644
index 0000000..ac3536c
Binary files /dev/null and b/icons/default/osdElements/buttonblue.png differ
diff --git a/icons/default/osdElements/buttongreen.png b/icons/default/osdElements/buttongreen.png
new file mode 100644
index 0000000..e598518
Binary files /dev/null and b/icons/default/osdElements/buttongreen.png differ
diff --git a/icons/default/osdElements/buttonred.png b/icons/default/osdElements/buttonred.png
new file mode 100644
index 0000000..152acad
Binary files /dev/null and b/icons/default/osdElements/buttonred.png differ
diff --git a/icons/default/osdElements/buttonyellow.png b/icons/default/osdElements/buttonyellow.png
new file mode 100644
index 0000000..1b448c9
Binary files /dev/null and b/icons/default/osdElements/buttonyellow.png differ
diff --git a/icons/default/osdElements/channel_jump.png b/icons/default/osdElements/channel_jump.png
new file mode 100644
index 0000000..9e417d4
Binary files /dev/null and b/icons/default/osdElements/channel_jump.png differ
diff --git a/icons/default/osdElements/channelgroup_bottom.png b/icons/default/osdElements/channelgroup_bottom.png
new file mode 100644
index 0000000..c37ba42
Binary files /dev/null and b/icons/default/osdElements/channelgroup_bottom.png differ
diff --git a/icons/default/osdElements/channelgroup_head.png b/icons/default/osdElements/channelgroup_head.png
new file mode 100644
index 0000000..75ee8a8
Binary files /dev/null and b/icons/default/osdElements/channelgroup_head.png differ
diff --git a/icons/default/osdElements/channelgroup_horiziontal.png b/icons/default/osdElements/channelgroup_horiziontal.png
new file mode 100644
index 0000000..ead7606
Binary files /dev/null and b/icons/default/osdElements/channelgroup_horiziontal.png differ
diff --git a/icons/default/osdElements/channelgroup_horizontal.png b/icons/default/osdElements/channelgroup_horizontal.png
new file mode 100644
index 0000000..ead7606
Binary files /dev/null and b/icons/default/osdElements/channelgroup_horizontal.png differ
diff --git a/icons/default/osdElements/channelgroup_left.png b/icons/default/osdElements/channelgroup_left.png
new file mode 100644
index 0000000..30e1b45
Binary files /dev/null and b/icons/default/osdElements/channelgroup_left.png differ
diff --git a/icons/default/osdElements/channelgroup_right.png b/icons/default/osdElements/channelgroup_right.png
new file mode 100644
index 0000000..d89657c
Binary files /dev/null and b/icons/default/osdElements/channelgroup_right.png differ
diff --git a/icons/default/osdElements/channelgroup_vertical.png b/icons/default/osdElements/channelgroup_vertical.png
new file mode 100644
index 0000000..64134c7
Binary files /dev/null and b/icons/default/osdElements/channelgroup_vertical.png differ
diff --git a/icons/default/osdElements/channelgroups_vertical.png b/icons/default/osdElements/channelgroups_vertical.png
new file mode 100644
index 0000000..474c558
Binary files /dev/null and b/icons/default/osdElements/channelgroups_vertical.png differ
diff --git a/icons/default/osdElements/channellogoback_horizontal.png b/icons/default/osdElements/channellogoback_horizontal.png
new file mode 100644
index 0000000..2df7f52
Binary files /dev/null and b/icons/default/osdElements/channellogoback_horizontal.png differ
diff --git a/icons/default/osdElements/channellogoback_vertical.png b/icons/default/osdElements/channellogoback_vertical.png
new file mode 100644
index 0000000..669beeb
Binary files /dev/null and b/icons/default/osdElements/channellogoback_vertical.png differ
diff --git a/icons/default/osdElements/clock.png b/icons/default/osdElements/clock.png
new file mode 100644
index 0000000..3df1dae
Binary files /dev/null and b/icons/default/osdElements/clock.png differ
diff --git a/icons/default/osdElements/date_vertical.png b/icons/default/osdElements/date_vertical.png
new file mode 100644
index 0000000..58a72e4
Binary files /dev/null and b/icons/default/osdElements/date_vertical.png differ
diff --git a/icons/default/osdElements/grid_active_bottom.png b/icons/default/osdElements/grid_active_bottom.png
new file mode 100644
index 0000000..28fb443
Binary files /dev/null and b/icons/default/osdElements/grid_active_bottom.png differ
diff --git a/icons/default/osdElements/grid_active_head.png b/icons/default/osdElements/grid_active_head.png
new file mode 100644
index 0000000..a494d95
Binary files /dev/null and b/icons/default/osdElements/grid_active_head.png differ
diff --git a/icons/default/osdElements/grid_active_horizontal.png b/icons/default/osdElements/grid_active_horizontal.png
new file mode 100644
index 0000000..368309f
Binary files /dev/null and b/icons/default/osdElements/grid_active_horizontal.png differ
diff --git a/icons/default/osdElements/grid_active_left.png b/icons/default/osdElements/grid_active_left.png
new file mode 100644
index 0000000..0548e21
Binary files /dev/null and b/icons/default/osdElements/grid_active_left.png differ
diff --git a/icons/default/osdElements/grid_active_right.png b/icons/default/osdElements/grid_active_right.png
new file mode 100644
index 0000000..2aee1d6
Binary files /dev/null and b/icons/default/osdElements/grid_active_right.png differ
diff --git a/icons/default/osdElements/grid_active_vertical.png b/icons/default/osdElements/grid_active_vertical.png
new file mode 100644
index 0000000..6aba9d1
Binary files /dev/null and b/icons/default/osdElements/grid_active_vertical.png differ
diff --git a/icons/default/osdElements/grid_bottom.png b/icons/default/osdElements/grid_bottom.png
new file mode 100644
index 0000000..e90e05e
Binary files /dev/null and b/icons/default/osdElements/grid_bottom.png differ
diff --git a/icons/default/osdElements/grid_head.png b/icons/default/osdElements/grid_head.png
new file mode 100644
index 0000000..4196cd8
Binary files /dev/null and b/icons/default/osdElements/grid_head.png differ
diff --git a/icons/default/osdElements/grid_horizontal.png b/icons/default/osdElements/grid_horizontal.png
new file mode 100644
index 0000000..6bccb3f
Binary files /dev/null and b/icons/default/osdElements/grid_horizontal.png differ
diff --git a/icons/default/osdElements/grid_left.png b/icons/default/osdElements/grid_left.png
new file mode 100644
index 0000000..7b17046
Binary files /dev/null and b/icons/default/osdElements/grid_left.png differ
diff --git a/icons/default/osdElements/grid_right.png b/icons/default/osdElements/grid_right.png
new file mode 100644
index 0000000..17fe003
Binary files /dev/null and b/icons/default/osdElements/grid_right.png differ
diff --git a/icons/default/osdElements/grid_vertical.png b/icons/default/osdElements/grid_vertical.png
new file mode 100644
index 0000000..e7192ac
Binary files /dev/null and b/icons/default/osdElements/grid_vertical.png differ
diff --git a/icons/default/osdElements/grids_vertical.png b/icons/default/osdElements/grids_vertical.png
new file mode 100644
index 0000000..a481f27
Binary files /dev/null and b/icons/default/osdElements/grids_vertical.png differ
diff --git a/icons/default/osdElements/recmenu_background.png b/icons/default/osdElements/recmenu_background.png
new file mode 100644
index 0000000..018260b
Binary files /dev/null and b/icons/default/osdElements/recmenu_background.png differ
diff --git a/icons/default/osdElements/statusheader_content_full.png b/icons/default/osdElements/statusheader_content_full.png
new file mode 100644
index 0000000..18c6552
Binary files /dev/null and b/icons/default/osdElements/statusheader_content_full.png differ
diff --git a/icons/default/osdElements/statusheader_content_windowed.png b/icons/default/osdElements/statusheader_content_windowed.png
new file mode 100644
index 0000000..24fd20c
Binary files /dev/null and b/icons/default/osdElements/statusheader_content_windowed.png differ
diff --git a/icons/default/osdElements/statusheader_tvframe.png b/icons/default/osdElements/statusheader_tvframe.png
new file mode 100644
index 0000000..cdb800c
Binary files /dev/null and b/icons/default/osdElements/statusheader_tvframe.png differ
diff --git a/icons/default/osdElements/timeline1_horizontal.png b/icons/default/osdElements/timeline1_horizontal.png
new file mode 100644
index 0000000..9240b37
Binary files /dev/null and b/icons/default/osdElements/timeline1_horizontal.png differ
diff --git a/icons/default/osdElements/timeline1_vertical.png b/icons/default/osdElements/timeline1_vertical.png
new file mode 100644
index 0000000..5466546
Binary files /dev/null and b/icons/default/osdElements/timeline1_vertical.png differ
diff --git a/icons/default/osdElements/timeline2_horizontal.png b/icons/default/osdElements/timeline2_horizontal.png
new file mode 100644
index 0000000..4364677
Binary files /dev/null and b/icons/default/osdElements/timeline2_horizontal.png differ
diff --git a/icons/default/osdElements/timeline2_vertical.png b/icons/default/osdElements/timeline2_vertical.png
new file mode 100644
index 0000000..dfa06c9
Binary files /dev/null and b/icons/default/osdElements/timeline2_vertical.png differ
diff --git a/icons/default/recmenuicons/activetimer.png b/icons/default/recmenuicons/activetimer.png
new file mode 100644
index 0000000..af4c33c
Binary files /dev/null and b/icons/default/recmenuicons/activetimer.png differ
diff --git a/icons/default/recmenuicons/arrow_left.png b/icons/default/recmenuicons/arrow_left.png
new file mode 100644
index 0000000..57800c7
Binary files /dev/null and b/icons/default/recmenuicons/arrow_left.png differ
diff --git a/icons/default/recmenuicons/arrow_right.png b/icons/default/recmenuicons/arrow_right.png
new file mode 100644
index 0000000..ea45f3a
Binary files /dev/null and b/icons/default/recmenuicons/arrow_right.png differ
diff --git a/icons/default/recmenuicons/delete_active.png b/icons/default/recmenuicons/delete_active.png
new file mode 100644
index 0000000..f473717
Binary files /dev/null and b/icons/default/recmenuicons/delete_active.png differ
diff --git a/icons/default/recmenuicons/delete_inactive.png b/icons/default/recmenuicons/delete_inactive.png
new file mode 100644
index 0000000..21b0a88
Binary files /dev/null and b/icons/default/recmenuicons/delete_inactive.png differ
diff --git a/icons/default/recmenuicons/edit_active.png b/icons/default/recmenuicons/edit_active.png
new file mode 100644
index 0000000..ec39699
Binary files /dev/null and b/icons/default/recmenuicons/edit_active.png differ
diff --git a/icons/default/recmenuicons/edit_inactive.png b/icons/default/recmenuicons/edit_inactive.png
new file mode 100644
index 0000000..71f016c
Binary files /dev/null and b/icons/default/recmenuicons/edit_inactive.png differ
diff --git a/icons/default/recmenuicons/icon_backspace.png b/icons/default/recmenuicons/icon_backspace.png
new file mode 100644
index 0000000..6065fa3
Binary files /dev/null and b/icons/default/recmenuicons/icon_backspace.png differ
diff --git a/icons/default/recmenuicons/icon_del_ins.png b/icons/default/recmenuicons/icon_del_ins.png
new file mode 100644
index 0000000..f05a96b
Binary files /dev/null and b/icons/default/recmenuicons/icon_del_ins.png differ
diff --git a/icons/default/recmenuicons/icon_shift.png b/icons/default/recmenuicons/icon_shift.png
new file mode 100644
index 0000000..15ae851
Binary files /dev/null and b/icons/default/recmenuicons/icon_shift.png differ
diff --git a/icons/default/recmenuicons/info_active.png b/icons/default/recmenuicons/info_active.png
new file mode 100644
index 0000000..c88f76d
Binary files /dev/null and b/icons/default/recmenuicons/info_active.png differ
diff --git a/icons/default/recmenuicons/info_inactive.png b/icons/default/recmenuicons/info_inactive.png
new file mode 100644
index 0000000..37eeed2
Binary files /dev/null and b/icons/default/recmenuicons/info_inactive.png differ
diff --git a/icons/default/recmenuicons/no.png b/icons/default/recmenuicons/no.png
new file mode 100644
index 0000000..47cdba0
Binary files /dev/null and b/icons/default/recmenuicons/no.png differ
diff --git a/icons/default/recmenuicons/record_active.png b/icons/default/recmenuicons/record_active.png
new file mode 100644
index 0000000..476da99
Binary files /dev/null and b/icons/default/recmenuicons/record_active.png differ
diff --git a/icons/default/recmenuicons/record_inactive.png b/icons/default/recmenuicons/record_inactive.png
new file mode 100644
index 0000000..2a91da3
Binary files /dev/null and b/icons/default/recmenuicons/record_inactive.png differ
diff --git a/icons/default/recmenuicons/search_active.png b/icons/default/recmenuicons/search_active.png
new file mode 100644
index 0000000..7bf7bc7
Binary files /dev/null and b/icons/default/recmenuicons/search_active.png differ
diff --git a/icons/default/recmenuicons/search_inactive.png b/icons/default/recmenuicons/search_inactive.png
new file mode 100644
index 0000000..4a210bb
Binary files /dev/null and b/icons/default/recmenuicons/search_inactive.png differ
diff --git a/icons/default/recmenuicons/yes.png b/icons/default/recmenuicons/yes.png
new file mode 100644
index 0000000..2f1af98
Binary files /dev/null and b/icons/default/recmenuicons/yes.png differ
diff --git a/icons/recmenuicons/activetimer.png b/icons/recmenuicons/activetimer.png
new file mode 100644
index 0000000..af4c33c
Binary files /dev/null and b/icons/recmenuicons/activetimer.png differ
diff --git a/icons/recmenuicons/arrow_left.png b/icons/recmenuicons/arrow_left.png
new file mode 100644
index 0000000..57800c7
Binary files /dev/null and b/icons/recmenuicons/arrow_left.png differ
diff --git a/icons/recmenuicons/arrow_right.png b/icons/recmenuicons/arrow_right.png
new file mode 100644
index 0000000..ea45f3a
Binary files /dev/null and b/icons/recmenuicons/arrow_right.png differ
diff --git a/icons/recmenuicons/delete_active.png b/icons/recmenuicons/delete_active.png
new file mode 100644
index 0000000..f473717
Binary files /dev/null and b/icons/recmenuicons/delete_active.png differ
diff --git a/icons/recmenuicons/delete_inactive.png b/icons/recmenuicons/delete_inactive.png
new file mode 100644
index 0000000..21b0a88
Binary files /dev/null and b/icons/recmenuicons/delete_inactive.png differ
diff --git a/icons/recmenuicons/edit_active.png b/icons/recmenuicons/edit_active.png
new file mode 100644
index 0000000..ec39699
Binary files /dev/null and b/icons/recmenuicons/edit_active.png differ
diff --git a/icons/recmenuicons/edit_inactive.png b/icons/recmenuicons/edit_inactive.png
new file mode 100644
index 0000000..71f016c
Binary files /dev/null and b/icons/recmenuicons/edit_inactive.png differ
diff --git a/icons/recmenuicons/icon_backspace.png b/icons/recmenuicons/icon_backspace.png
new file mode 100644
index 0000000..6065fa3
Binary files /dev/null and b/icons/recmenuicons/icon_backspace.png differ
diff --git a/icons/recmenuicons/icon_del_ins.png b/icons/recmenuicons/icon_del_ins.png
new file mode 100644
index 0000000..f05a96b
Binary files /dev/null and b/icons/recmenuicons/icon_del_ins.png differ
diff --git a/icons/recmenuicons/icon_shift.png b/icons/recmenuicons/icon_shift.png
new file mode 100644
index 0000000..15ae851
Binary files /dev/null and b/icons/recmenuicons/icon_shift.png differ
diff --git a/icons/recmenuicons/info_active.png b/icons/recmenuicons/info_active.png
new file mode 100644
index 0000000..c88f76d
Binary files /dev/null and b/icons/recmenuicons/info_active.png differ
diff --git a/icons/recmenuicons/info_inactive.png b/icons/recmenuicons/info_inactive.png
new file mode 100644
index 0000000..37eeed2
Binary files /dev/null and b/icons/recmenuicons/info_inactive.png differ
diff --git a/icons/recmenuicons/no.png b/icons/recmenuicons/no.png
new file mode 100644
index 0000000..47cdba0
Binary files /dev/null and b/icons/recmenuicons/no.png differ
diff --git a/icons/recmenuicons/record_active.png b/icons/recmenuicons/record_active.png
new file mode 100644
index 0000000..476da99
Binary files /dev/null and b/icons/recmenuicons/record_active.png differ
diff --git a/icons/recmenuicons/record_inactive.png b/icons/recmenuicons/record_inactive.png
new file mode 100644
index 0000000..2a91da3
Binary files /dev/null and b/icons/recmenuicons/record_inactive.png differ
diff --git a/icons/recmenuicons/search_active.png b/icons/recmenuicons/search_active.png
new file mode 100644
index 0000000..7bf7bc7
Binary files /dev/null and b/icons/recmenuicons/search_active.png differ
diff --git a/icons/recmenuicons/search_inactive.png b/icons/recmenuicons/search_inactive.png
new file mode 100644
index 0000000..4a210bb
Binary files /dev/null and b/icons/recmenuicons/search_inactive.png differ
diff --git a/icons/recmenuicons/yes.png b/icons/recmenuicons/yes.png
new file mode 100644
index 0000000..2f1af98
Binary files /dev/null and b/icons/recmenuicons/yes.png differ
diff --git a/imagecache.c b/imagecache.c
new file mode 100644
index 0000000..eb3117c
--- /dev/null
+++ b/imagecache.c
@@ -0,0 +1,715 @@
+#include <string>
+#include <sstream>
+#include <map>
+#include <vdr/channels.h>
+#include "config.h"
+#include "imagescaler.h"
+#include "tools.h"
+#include "imagecache.h"
+
+cImageCache::cImageCache() : cImageMagickWrapper() {
+ tempStaticLogo = NULL;
+ groupsHead = NULL;
+ groupsBottom = NULL;
+ groupsLeft = NULL;
+ groupsRight = NULL;
+ imgLeft = NULL;
+ imgLeftActive = NULL;
+ imgRight = NULL;
+ imgRightActive = NULL;
+ imgHead = NULL;
+ imgHeadActive = NULL;
+ imgBottom = NULL;
+ imgBottomActive = NULL;
+}
+
+cImageCache::~cImageCache() {
+ Clear();
+}
+
+void cImageCache::CreateCache(void) {
+ if (tvguideConfig.style != eStyleGraphical)
+ return;
+ esyslog("tvguide: Creating Image Cache");
+ int start = cTimeMs::Now();
+ int startNext = cTimeMs::Now();
+ CreateOsdIconCache();
+ esyslog("tvguide: Osd Icon Cash created in %d ms", int(cTimeMs::Now()-startNext));
+ startNext = cTimeMs::Now();
+ PrepareGridIconCache();
+ CreateGridIconCache();
+ esyslog("tvguide: Grid Icon Cash created in %d ms", int(cTimeMs::Now()-startNext));
+ startNext = cTimeMs::Now();
+ CreateChannelGroupCache();
+ esyslog("tvguide: Channelgroup Cash created in %d ms", int(cTimeMs::Now()-startNext));
+ startNext = cTimeMs::Now();
+ CreateLogoCache();
+ esyslog("tvguide: Logo Cash created in %d ms", int(cTimeMs::Now()-startNext));
+ startNext = cTimeMs::Now();
+ esyslog("tvguide: Complete Image Cash created in %d ms", int(cTimeMs::Now()-start));
+}
+
+void cImageCache::CreateOsdIconCache(void) {
+ bool success = false;
+ //Status Header
+ std::string imgStatusHeaderContentFull = "osdElements/statusheader_content_full";
+ std::string imgStatusHeaderContentWindowed = "osdElements/statusheader_content_windowed";
+ std::string imgStatusHeaderTVFrame = "osdElements/statusheader_tvframe";
+ success = LoadIcon(imgStatusHeaderContentFull);
+ if (success)
+ InsertIntoOsdElementCache(oeStatusHeaderContentFull, geoManager.headerContentWidth, geoManager.statusHeaderHeight);
+ success = LoadIcon(imgStatusHeaderContentWindowed);
+ if (success)
+ InsertIntoOsdElementCache(oeStatusHeaderContentWindowed, geoManager.headerContentWidth, geoManager.statusHeaderHeight);
+ success = LoadIcon(imgStatusHeaderTVFrame);
+ if (success)
+ InsertIntoOsdElementCache(oeStatusHeaderTVFrame, geoManager.tvFrameWidth, geoManager.statusHeaderHeight);
+
+
+ //Color Buttons
+ std::string imgButtonRed = "osdElements/buttonred";
+ std::string imgButtonGreen = "osdElements/buttongreen";
+ std::string imgButtonYellow = "osdElements/buttonyellow";
+ std::string imgButtonBlue = "osdElements/buttonblue";
+ success = LoadIcon(imgButtonRed);
+ if (success)
+ InsertIntoOsdElementCache(oeButtonRed, geoManager.buttonWidth, geoManager.buttonHeight);
+ success = LoadIcon(imgButtonGreen);
+ if (success)
+ InsertIntoOsdElementCache(oeButtonGreen, geoManager.buttonWidth, geoManager.buttonHeight);
+ success = LoadIcon(imgButtonYellow);
+ if (success)
+ InsertIntoOsdElementCache(oeButtonYellow, geoManager.buttonWidth, geoManager.buttonHeight);
+ success = LoadIcon(imgButtonBlue);
+ if (success)
+ InsertIntoOsdElementCache(oeButtonBlue, geoManager.buttonWidth, geoManager.buttonHeight);
+
+ //Channel Logo Background
+ if (tvguideConfig.displayMode == eHorizontal) {
+ success = LoadIcon("osdElements/channellogoback_horizontal");
+ } else {
+ success = LoadIcon("osdElements/channellogoback_vertical");
+ }
+ if (success)
+ InsertIntoOsdElementCache(oeLogoBack, geoManager.channelLogoWidth, geoManager.channelLogoHeight);
+
+ //Timeline Elements
+ std::string imgTimeline1, imgTimeline2, imgDateViewer;
+ if (tvguideConfig.displayMode == eHorizontal) {
+ imgTimeline1 = "osdElements/timeline1_horizontal";
+ imgTimeline2 = "osdElements/timeline2_horizontal";
+ imgDateViewer = "osdElements/timeline2_horizontal";
+ } else {
+ imgTimeline1 = "osdElements/timeline1_vertical";
+ imgTimeline2 = "osdElements/timeline2_vertical";
+ imgDateViewer = "osdElements/date_vertical";
+ }
+ std::string imgClock = "osdElements/clock";
+ success = LoadIcon(imgTimeline1);
+ if (success)
+ InsertIntoOsdElementCache(oeTimeline1, geoManager.timeLineGridWidth, geoManager.timeLineGridHeight);
+ success = LoadIcon(imgTimeline2);
+ if (success)
+ InsertIntoOsdElementCache(oeTimeline2, geoManager.timeLineGridWidth, geoManager.timeLineGridHeight);
+ success = LoadIcon(imgDateViewer);
+ if (success)
+ InsertIntoOsdElementCache(oeDateViewer, geoManager.dateVieverWidth, geoManager.dateVieverHeight);
+ success = LoadIcon(imgClock);
+ if (success)
+ InsertIntoOsdElementCache(oeClock, geoManager.clockWidth, geoManager.clockHeight);
+
+ //Channel Jump
+ success = LoadIcon("osdElements/channel_jump");
+ if (success)
+ InsertIntoOsdElementCache(oeChannelJump, geoManager.channelJumpWidth, geoManager.channelJumpHeight);
+}
+
+void cImageCache::PrepareGridIconCache(void) {
+ bool success = false;
+ //Create Buffers for Background
+ gridsAvailable = true;
+ std::string grid, grid_active;
+ if (tvguideConfig.displayMode == eHorizontal) {
+ grid = "osdElements/grid_horizontal";
+ grid_active = "osdElements/grid_active_horizontal";
+ } else {
+ grid = "osdElements/grid_vertical";
+ grid_active = "osdElements/grid_active_vertical";
+ }
+ success = LoadIcon(grid);
+ if (success) {
+ bufferGrid = buffer;
+ } else {
+ gridsAvailable = false;
+ }
+ success = LoadIcon(grid_active);
+ if (success) {
+ bufferGridActive = buffer;
+ } else {
+ gridsAvailable = false;
+ }
+ //Create Grid Background Templates
+ imgLeft = NULL;
+ imgLeftActive = NULL;
+ imgRight = NULL;
+ imgRightActive = NULL;
+ imgHead = NULL;
+ imgHeadActive = NULL;
+ imgBottom = NULL;
+ imgBottomActive = NULL;
+
+ if (tvguideConfig.displayMode == eHorizontal) {
+ std::string left = "osdElements/grid_left";
+ std::string right = "osdElements/grid_right";
+ std::string left_active = "osdElements/grid_active_left";
+ std::string right_active = "osdElements/grid_active_right";
+ cornerWidth = 0;
+ cornerHeight = geoManager.rowHeight;
+ //first image determinates width
+ success = LoadIcon(left);
+ if (!success)
+ return;
+ int widthOriginal = 0;
+ int heightOriginal = 0;
+ widthOriginal = buffer.columns();
+ heightOriginal = buffer.rows();
+ cornerWidth = widthOriginal * cornerHeight / heightOriginal;
+ imgLeft = CreateImage(cornerWidth, cornerHeight, false);
+ success = LoadIcon(right);
+ if (success)
+ imgRight = CreateImage(cornerWidth, cornerHeight, false);
+ success = LoadIcon(left_active);
+ if (success)
+ imgLeftActive = CreateImage(cornerWidth, cornerHeight, false);
+ success = LoadIcon(right_active);
+ if (success)
+ imgRightActive = CreateImage(cornerWidth, cornerHeight, false);
+ } else {
+ std::string head = "osdElements/grid_head";
+ std::string bottom = "osdElements/grid_bottom";
+ std::string head_active = "osdElements/grid_active_head";
+ std::string bottom_active = "osdElements/grid_active_bottom";
+ cornerWidth = geoManager.colWidth;
+ cornerHeight = 0;
+ //first image determinates height
+ success = LoadIcon(head);
+ if (!success)
+ return;
+ int widthOriginal = 0;
+ int heightOriginal = 0;
+ widthOriginal = buffer.columns();
+ heightOriginal = buffer.rows();
+ cornerHeight = heightOriginal * cornerWidth / widthOriginal;
+ imgHead = CreateImage(cornerWidth, cornerHeight, false);
+ success = LoadIcon(bottom);
+ if (success)
+ imgBottom = CreateImage(cornerWidth, cornerHeight, false);
+ success = LoadIcon(head_active);
+ if (success)
+ imgHeadActive = CreateImage(cornerWidth, cornerHeight, false);
+ success = LoadIcon(bottom_active);
+ if (success)
+ imgBottomActive = CreateImage(cornerWidth, cornerHeight, false);
+ }
+}
+
+void cImageCache::CreateGridIconCache(void) {
+ if (tvguideConfig.displayMode == eHorizontal) {
+ int gridHeight = geoManager.rowHeight;
+ for (int minutes = 5; minutes <= 120; minutes += 5) {
+ GetGrid(minutes * geoManager.minutePixel, gridHeight, false);
+ }
+ } else {
+ int gridWidth = geoManager.colWidth;
+ for (int minutes = 5; minutes <= 120; minutes += 5) {
+ GetGrid(gridWidth, minutes * geoManager.minutePixel, false);
+ }
+ }
+}
+
+void cImageCache::CreateChannelGroupCache(void) {
+ bool success = false;
+ groupsHead = NULL;
+ groupsBottom = NULL;
+ groupsLeft = NULL;
+ groupsRight = NULL;
+ if (tvguideConfig.displayMode == eHorizontal) {
+ std::string channelGroupHead = "osdElements/channelgroup_head";
+ std::string channelGroupBottom = "osdElements/channelgroup_bottom";
+ int width = geoManager.channelGroupsWidth;
+ int heightHeadBottom = 0;
+ success = LoadIcon(channelGroupHead);
+ if (success) {
+ int widthOriginal = buffer.columns();
+ int heightOriginal = buffer.rows();
+ heightHeadBottom = heightOriginal * width / widthOriginal;
+ groupsHead = CreateImage(width, heightHeadBottom, false);
+ }
+ success = LoadIcon(channelGroupBottom);
+ if (success && heightHeadBottom) {
+ groupsBottom = CreateImage(width, heightHeadBottom, false);
+ }
+ for (int size = 1; size <= tvguideConfig.numGrids; ++size) {
+ InsertIntoGroupsCacheHorizontal(size);
+ }
+ } else {
+ std::string channelGroupLeft = "osdElements/channelgroup_left";
+ std::string channelGroupRight = "osdElements/channelgroup_right";
+ int widthHeadBottom = 0;
+ int height = geoManager.channelGroupsHeight;
+ success = LoadIcon(channelGroupLeft);
+ if (success) {
+ int widthOriginal = buffer.columns();
+ int heightOriginal = buffer.rows();
+ widthHeadBottom = widthOriginal * height / heightOriginal;
+ groupsLeft = CreateImage(widthHeadBottom, height, false);
+ }
+ success = LoadIcon(channelGroupRight);
+ if (success && widthHeadBottom) {
+ groupsRight = CreateImage(widthHeadBottom, height, false);
+ }
+ for (int size = 1; size <= tvguideConfig.numGrids; ++size) {
+ InsertIntoGroupsCacheVertical(size);
+ }
+ }
+
+}
+
+void cImageCache::CreateLogoCache(void) {
+ if (tvguideConfig.hideChannelLogos)
+ return;
+ if (tvguideConfig.numLogosInitial > 0) {
+ int channelsCached = 0;
+ for (const cChannel *channel = Channels.First(); channel; channel = Channels.Next(channel)) {
+ if (channelsCached >= tvguideConfig.numLogosInitial)
+ break;
+ if (!channel->GroupSep()) {
+ bool success = LoadLogo(channel);
+ if (success) {
+ channelsCached++;
+ InsertIntoLogoCache(*channel->GetChannelID().ToString());
+ }
+ }
+
+ }
+ }
+}
+
+
+cImage *cImageCache::GetOsdElement(eOsdElementType type) {
+ std::map<eOsdElementType, cImage*>::iterator hit = osdElementCache.find(type);
+ if (hit != osdElementCache.end()) {
+ return (cImage*)hit->second;
+ }
+ return NULL;
+}
+
+cImage *cImageCache::GetGrid(int width, int height, bool active) {
+ if (!gridsAvailable)
+ return NULL;
+ std::stringstream gridImageName;
+ gridImageName << width << "x" << height;
+ if (active)
+ gridImageName << "active";
+ std::string gridImg = gridImageName.str();
+ std::map<std::string, cImage*>::iterator hit = gridCache.find(gridImg);
+ if (hit != gridCache.end()) {
+ return (cImage*)hit->second;
+ } else {
+ InsertIntoGridCache(gridImg, width, height, active);
+ hit = gridCache.find(gridImg);
+ if (hit != gridCache.end()) {
+ return (cImage*)hit->second;
+ }
+ }
+ return NULL;
+}
+
+cImage *cImageCache::GetChannelGroup(int width, int height) {
+ std::stringstream groupName;
+ groupName << width << "x" << height;
+ std::map<std::string, cImage*>::iterator hit = groupsCache.find(groupName.str());
+ if (hit != groupsCache.end()) {
+ return (cImage*)hit->second;
+ }
+ return NULL;
+}
+
+cImage *cImageCache::GetLogo(const cChannel *channel) {
+ if (!channel)
+ return NULL;
+
+ std::map<std::string, cImage*>::iterator hit = logoCache.find(*channel->GetChannelID().ToString());
+
+ if (hit != logoCache.end()) {
+ return (cImage*)hit->second;
+ } else {
+ bool success = LoadLogo(channel);
+ if (success) {
+ if ((tvguideConfig.limitLogoCache) && (logoCache.size() >= tvguideConfig.numLogosMax)) {
+ //logo cache is full, don't cache anymore
+ if (tempStaticLogo) {
+ delete tempStaticLogo;
+ tempStaticLogo = NULL;
+ }
+ tempStaticLogo = CreateImage(geoManager.logoWidth, geoManager.logoHeight);
+ return tempStaticLogo;
+ } else {
+ //add requested logo to cache
+ InsertIntoLogoCache(*channel->GetChannelID().ToString());
+ hit = logoCache.find(*channel->GetChannelID().ToString());
+ if (hit != logoCache.end()) {
+ return (cImage*)hit->second;
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+cImage *cImageCache::GetIcon(std::string name, int width, int height) {
+ std::stringstream iconName;
+ iconName << name << width << "x" << height;
+ std::map<std::string, cImage*>::iterator hit = iconCache.find(iconName.str());
+ if (hit != iconCache.end()) {
+ return (cImage*)hit->second;
+ } else {
+ std::stringstream iconPath;
+ iconPath << "recmenuicons/" << name;
+ bool success = LoadIcon(iconPath.str());
+ if (success) {
+ cImage *image = CreateImage(width, height);
+ iconCache.insert(std::pair<std::string, cImage*>(iconName.str(), image));
+ hit = iconCache.find(iconName.str());
+ if (hit != iconCache.end()) {
+ return (cImage*)hit->second;
+ }
+ }
+ }
+ return NULL;
+}
+
+void cImageCache::InsertIntoOsdElementCache(eOsdElementType type, int width, int height) {
+ cImage *image = CreateImage(width, height, false);
+ if (image)
+ osdElementCache.insert(std::pair<eOsdElementType, cImage*>(type, image));
+}
+
+void cImageCache::InsertIntoGridCache(std::string name, int width, int height, bool active) {
+ cImage *image = CreateGrid(width, height, active);
+ if (image) {
+ if (tvguideConfig.displayMode == eHorizontal) {
+ AddCornersHorizontal(image, active);
+ } else {
+ AddCornersVertical(image, active);
+ }
+ gridCache.insert(std::pair<std::string, cImage*>(name, image));
+ }
+}
+
+cImage *cImageCache::CreateGrid(int width, int height, bool active) {
+ if (width > geoManager.osdWidth || width < 6 || height > geoManager.osdHeight || height < 6)
+ return NULL;
+ Image *currentGridBuffer = NULL;
+ if (active)
+ currentGridBuffer = &bufferGridActive;
+ else
+ currentGridBuffer = &bufferGrid;
+ int w, h;
+ w = currentGridBuffer->columns();
+ h = currentGridBuffer->rows();
+ const PixelPacket *pixels = currentGridBuffer->getConstPixels(0, 0, w, h);
+ cImage *image = NULL;
+ image = new cImage(cSize(width, height));
+ if (!image)
+ return NULL;
+ tColor *imgData = (tColor *)image->Data();
+ if (w != width || h != height) {
+ ImageScaler scaler;
+ scaler.SetImageParameters(imgData, width, width, height, w, h);
+ for (const void *pixels_end = &pixels[w*h]; pixels < pixels_end; ++pixels)
+ scaler.PutSourcePixel(pixels->blue / ((MaxRGB + 1) / 256),
+ pixels->green / ((MaxRGB + 1) / 256),
+ pixels->red / ((MaxRGB + 1) / 256),
+ ~((unsigned char)(pixels->opacity / ((MaxRGB + 1) / 256))));
+ return image;
+ }
+ for (const void *pixels_end = &pixels[width*height]; pixels < pixels_end; ++pixels)
+ *imgData++ = ((~int(pixels->opacity / ((MaxRGB + 1) / 256)) << 24) |
+ (int(pixels->green / ((MaxRGB + 1) / 256)) << 8) |
+ (int(pixels->red / ((MaxRGB + 1) / 256)) << 16) |
+ (int(pixels->blue / ((MaxRGB + 1) / 256)) ));
+ return image;
+}
+
+void cImageCache::AddCornersHorizontal(cImage *img, bool active) {
+ int imgWidth = img->Width();
+ cImage *cornerLeft = NULL;
+ cImage *cornerRight = NULL;
+ if (active) {
+ cornerLeft = imgLeftActive;
+ cornerRight = imgRightActive;
+ } else {
+ cornerLeft = imgLeft;
+ cornerRight = imgRight;
+ }
+ if (!cornerLeft || !cornerRight)
+ return;
+ int maxX = min(cornerWidth, imgWidth);
+ for (int row = 0; row < cornerHeight; row++) {
+ for (int col = 0; col < maxX; ++col) {
+ img->SetPixel(cPoint(col, row), cornerLeft->GetPixel(cPoint(col, row)));
+ img->SetPixel(cPoint(imgWidth - maxX + col, row), cornerRight->GetPixel(cPoint(col, row)));
+ }
+ }
+}
+
+void cImageCache::AddCornersVertical(cImage *img, bool active) {
+ int imgHeight = img->Height();
+ cImage *cornerHead = NULL;
+ cImage *cornerBottom = NULL;
+ if (active) {
+ cornerHead = imgHeadActive;
+ cornerBottom = imgBottomActive;
+ } else {
+ cornerHead = imgHead;
+ cornerBottom = imgBottom;
+ }
+ if (!cornerHead || !cornerBottom)
+ return;
+ int maxY = min(cornerHeight, imgHeight);
+ for (int row = 0; row < maxY; row++) {
+ for (int col = 0; col < cornerWidth; ++col) {
+ img->SetPixel(cPoint(col, row), cornerHead->GetPixel(cPoint(col, row)));
+ img->SetPixel(cPoint(col, imgHeight - maxY + row), cornerBottom->GetPixel(cPoint(col, row)));
+ }
+ }
+}
+
+void cImageCache::InsertIntoGroupsCacheHorizontal(int size) {
+ int width = geoManager.channelGroupsWidth;
+ bool success = LoadIcon("osdElements/channelgroup_horizontal");
+ if (success) {
+ int height = size * geoManager.rowHeight;
+ std::stringstream name;
+ name << width << "x" << height;
+ cImage *image = CreateImage(width, height, false);
+ if (image) {
+ AddCornersGroupHorizontal(image);
+ groupsCache.insert(std::pair<std::string, cImage*>(name.str(), image));
+ }
+ }
+}
+
+void cImageCache::InsertIntoGroupsCacheVertical(int size) {
+ int height = geoManager.channelGroupsHeight;
+ bool success = LoadIcon("osdElements/channelgroup_vertical");
+ if (success) {
+ int width = size * geoManager.colWidth;
+ std::stringstream name;
+ name << width << "x" << height;
+ cImage *image = CreateImage(width, height, false);
+ if (image) {
+ AddCornersGroupVertical(image);
+ groupsCache.insert(std::pair<std::string, cImage*>(name.str(), image));
+ }
+ }
+}
+
+void cImageCache::AddCornersGroupHorizontal(cImage *img) {
+ if (!groupsHead || !groupsBottom || !img)
+ return;
+ int imgWidth = img->Width();
+ int imgHeight = img->Height();
+ int heightHeadBottom = groupsHead->Height();
+ int maxY = min(heightHeadBottom, imgHeight);
+ for (int row = 0; row < maxY; row++) {
+ for (int col = 0; col < imgWidth; ++col) {
+ img->SetPixel(cPoint(col, row), groupsHead->GetPixel(cPoint(col, row)));
+ img->SetPixel(cPoint(col, imgHeight - maxY + row), groupsBottom->GetPixel(cPoint(col, row)));
+ }
+ }
+}
+
+void cImageCache::AddCornersGroupVertical(cImage *img) {
+ if (!groupsLeft || !groupsRight || !img)
+ return;
+ int imgWidth = img->Width();
+ int imgHeight = img->Height();
+ int widthLeftRight = groupsLeft->Width();
+ int maxX = min(widthLeftRight, imgWidth);
+ for (int row = 0; row < imgHeight; row++) {
+ for (int col = 0; col < maxX; ++col) {
+ img->SetPixel(cPoint(col, row), groupsLeft->GetPixel(cPoint(col, row)));
+ img->SetPixel(cPoint(imgWidth - maxX + col, row), groupsRight->GetPixel(cPoint(col, row)));
+ }
+ }
+}
+
+bool cImageCache::LoadIcon(std::string name) {
+ bool success = false;
+ if (tvguideConfig.iconsPathSet) {
+ cString iconPathTheme = cString::sprintf("%s%s/", *tvguideConfig.iconPath, *tvguideConfig.themeName);
+ success = LoadImage(name, *iconPathTheme, "png");
+ if (success) {
+ return true;
+ } else {
+ success = LoadImage(name, *tvguideConfig.iconPath, "png");
+ if (success) {
+ return true;
+ }
+ }
+ }
+ if (!success) {
+ cString iconPathTheme = cString::sprintf("%s%s/", *tvguideConfig.iconPathDefault, *tvguideConfig.themeName);
+ success = LoadImage(name, *iconPathTheme, "png");
+ if (success) {
+ return true;
+ } else {
+ success = LoadImage(name, *tvguideConfig.iconPathDefault, "png");
+ if (success) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool cImageCache::LoadLogo(const cChannel *channel) {
+ if (!channel)
+ return false;
+ std::string channelID = StrToLowerCase(*(channel->GetChannelID().ToString()));
+ std::string logoLower = StrToLowerCase(channel->Name());
+ bool success = false;
+ cString extension;
+ if (tvguideConfig.logoExtension == 0) {
+ extension = "png";
+ } else if (tvguideConfig.logoExtension == 1) {
+ extension = "jpg";
+ }
+
+ if (tvguideConfig.logoPathSet) {
+ success = LoadImage(channelID.c_str(), *tvguideConfig.logoPath, *extension);
+ if (success)
+ return true;
+ success = LoadImage(logoLower.c_str(), *tvguideConfig.logoPath, *extension);
+ if (success)
+ return true;
+ }
+ success = LoadImage(channelID.c_str(), *tvguideConfig.logoPathDefault, *extension);
+ if (success)
+ return true;
+ success = LoadImage(logoLower.c_str(), *tvguideConfig.logoPathDefault, *extension);
+ return success;
+}
+
+void cImageCache::InsertIntoLogoCache(std::string channelID) {
+ cImage *image = CreateImage(geoManager.logoWidth, geoManager.logoHeight);
+ logoCache.insert(std::pair<std::string, cImage*>(channelID, image));
+}
+
+std::string cImageCache::GetCacheSize(eCacheType type) {
+ std::stringstream result;
+ int sizeByte = 0;
+ int numImages = 0;
+ if (type == ctOsdElement) {
+ for(std::map<eOsdElementType, cImage*>::const_iterator it = osdElementCache.begin(); it != osdElementCache.end(); it++) {
+ cImage *img = (cImage*)it->second;
+ if (img)
+ sizeByte += img->Width() * img->Height() * sizeof(tColor);
+ }
+ numImages = osdElementCache.size();
+ } else if ((type == ctGrid) || (type == ctLogo) || (type == ctChannelGroup) || (type == ctIcon)) {
+ std::map<std::string, cImage*> *cache;
+ if (type == ctGrid)
+ cache = &gridCache;
+ else if (type == ctLogo)
+ cache = &logoCache;
+ else if (type == ctChannelGroup)
+ cache = &groupsCache;
+ else if (type == ctIcon)
+ cache = &iconCache;
+
+ for(std::map<std::string, cImage*>::const_iterator it = cache->begin(); it != cache->end(); it++) {
+ cImage *img = (cImage*)it->second;
+ if (img)
+ sizeByte += img->Width() * img->Height() * sizeof(tColor);
+ }
+ numImages = cache->size();
+ }
+ result << numImages << " " << tr("images") << " / " << sizeByte/1024 << " KByte";
+ return result.str();
+}
+
+void cImageCache::Clear(void) {
+ for(std::map<eOsdElementType, cImage*>::const_iterator it = osdElementCache.begin(); it != osdElementCache.end(); it++) {
+ cImage *img = (cImage*)it->second;
+ delete img;
+ }
+ osdElementCache.clear();
+
+ for(std::map<std::string, cImage*>::const_iterator it = gridCache.begin(); it != gridCache.end(); it++) {
+ cImage *img = (cImage*)it->second;
+ delete img;
+ }
+ gridCache.clear();
+
+ for(std::map<std::string, cImage*>::const_iterator it = groupsCache.begin(); it != groupsCache.end(); it++) {
+ cImage *img = (cImage*)it->second;
+ delete img;
+ }
+ groupsCache.clear();
+
+ for(std::map<std::string, cImage*>::const_iterator it = logoCache.begin(); it != logoCache.end(); it++) {
+ cImage *img = (cImage*)it->second;
+ delete img;
+ }
+ logoCache.clear();
+
+ for(std::map<std::string, cImage*>::const_iterator it = iconCache.begin(); it != iconCache.end(); it++) {
+ cImage *img = (cImage*)it->second;
+ delete img;
+ }
+ iconCache.clear();
+
+ if (tempStaticLogo)
+ delete tempStaticLogo;
+ if (groupsHead)
+ delete groupsHead;
+ if (groupsBottom)
+ delete groupsBottom;
+ if (groupsLeft)
+ delete groupsLeft;
+ if (groupsRight)
+ delete groupsRight;
+ if (imgLeft)
+ delete imgLeft;
+ if (imgLeftActive)
+ delete imgLeftActive;
+ if (imgRight)
+ delete imgRight;
+ if (imgRightActive)
+ delete imgRightActive;
+ if (imgHead)
+ delete imgHead;
+ if (imgHeadActive)
+ delete imgHeadActive;
+ if (imgBottom)
+ delete imgBottom;
+ if (imgBottomActive)
+ delete imgBottomActive;
+
+ tempStaticLogo = NULL;
+ groupsHead = NULL;
+ groupsBottom = NULL;
+ groupsLeft = NULL;
+ groupsRight = NULL;
+ imgLeft = NULL;
+ imgLeftActive = NULL;
+ imgRight = NULL;
+ imgRightActive = NULL;
+ imgHead = NULL;
+ imgHeadActive = NULL;
+ imgBottom = NULL;
+ imgBottomActive = NULL;
+}
diff --git a/imagecache.h b/imagecache.h
new file mode 100644
index 0000000..365e910
--- /dev/null
+++ b/imagecache.h
@@ -0,0 +1,92 @@
+#ifndef __TVGUIDE_IMAGECACHE_H
+#define __TVGUIDE_IMAGECACHE_H
+
+#define X_DISPLAY_MISSING
+
+#include <map>
+#include <vector>
+#include "imagemagickwrapper.h"
+
+enum eCacheType {
+ ctOsdElement = 0,
+ ctGrid,
+ ctLogo,
+ ctChannelGroup,
+ ctIcon,
+};
+
+enum eOsdElementType {
+ oeNone = -1,
+ oeStatusHeaderContentFull,
+ oeStatusHeaderContentWindowed,
+ oeStatusHeaderTVFrame,
+ oeButtonRed,
+ oeButtonGreen,
+ oeButtonYellow,
+ oeButtonBlue,
+ oeLogoBack,
+ oeTimeline1,
+ oeTimeline2,
+ oeDateViewer,
+ oeClock,
+ oeChannelJump,
+};
+
+class cImageCache : public cImageMagickWrapper {
+public:
+ cImageCache();
+ ~cImageCache();
+ void CreateCache(void);
+ cImage *GetOsdElement(eOsdElementType type);
+ cImage *GetGrid(int width, int height, bool active);
+ cImage *GetChannelGroup(int width, int height);
+ cImage *GetLogo(const cChannel *channel);
+ cImage *GetIcon(std::string name, int width, int height);
+ std::string GetCacheSize(eCacheType type);
+ void Clear(void);
+private:
+ cImage *tempStaticLogo;
+ Image bufferGrid;
+ Image bufferGridActive;
+ bool gridsAvailable;
+ int cornerWidth;
+ int cornerHeight;
+ cImage *imgLeft;
+ cImage *imgLeftActive;
+ cImage *imgRight;
+ cImage *imgRightActive;
+ cImage *imgHead;
+ cImage *imgHeadActive;
+ cImage *imgBottom;
+ cImage *imgBottomActive;
+ cImage *imgChannelgroupHead;
+ cImage *imgChannelgroupBottom;
+ cImage *groupsHead;
+ cImage *groupsBottom;
+ cImage *groupsLeft;
+ cImage *groupsRight;
+ std::map<eOsdElementType, cImage*> osdElementCache;
+ std::map<std::string, cImage*> gridCache;
+ std::map<std::string, cImage*> groupsCache;
+ std::map<std::string, cImage*> logoCache;
+ std::map<std::string, cImage*> iconCache;
+ void CreateOsdIconCache(void);
+ void PrepareGridIconCache(void);
+ void CreateGridIconCache(void);
+ void CreateChannelGroupCache(void);
+ void CreateLogoCache(void);
+ bool LoadIcon(std::string name);
+ void InsertIntoOsdElementCache(eOsdElementType type, int width=0, int height=0);
+ void InsertIntoGridCache(std::string name, int width, int height, bool active);
+ cImage *CreateGrid(int width, int height, bool active);
+ void AddCornersHorizontal(cImage *img, bool active);
+ void AddCornersVertical(cImage *img, bool active);
+ void InsertIntoGroupsCacheHorizontal(int size);
+ void InsertIntoGroupsCacheVertical(int size);
+ void AddCornersGroupHorizontal(cImage *img);
+ void AddCornersGroupVertical(cImage *img);
+ bool LoadLogo(const cChannel *channel);
+ void InsertIntoLogoCache(std::string channelID);
+};
+
+#endif //__TVGUIDE_IMAGECACHE_H
\ No newline at end of file
diff --git a/imageloader.c b/imageloader.c
index 02586d6..6ca5d69 100644
--- a/imageloader.c
+++ b/imageloader.c
@@ -1,8 +1,12 @@
-#include "imageloader.h"
#include <math.h>
#include <string>
#include <dirent.h>
#include <iostream>
+#include <vdr/channels.h>
+
+#include "config.h"
+#include "imageloader.h"
+#include "tools.h"
using namespace Magick;
@@ -13,31 +17,54 @@ cImageLoader::cImageLoader() {
cImageLoader::~cImageLoader() {
}
-bool cImageLoader::LoadLogo(const char *logo, int width = tvguideConfig.logoWidth, int height = tvguideConfig.logoHeight) {
- if ((width == 0)||(height==0))
+bool cImageLoader::LoadLogo(const cChannel *channel, int width, int height) {
+ if (!channel || (width == 0)||(height==0))
return false;
- std::string logoLower = logo;
- toLowerCase(logoLower);
+ std::string channelID = StrToLowerCase(*(channel->GetChannelID().ToString()));
+ std::string logoLower = StrToLowerCase(channel->Name());
cString extension;
if (tvguideConfig.logoExtension == 0) {
- extension = "png";
- } else if (tvguideConfig.logoExtension == 1) {
- extension = "jpg";
- }
- if (!LoadImage(logoLower.c_str(), tvguideConfig.logoPath, extension))
- return false;
- if (height != 0 || width != 0) {
- buffer.sample( Geometry(width, height));
+ extension = "png";
+ } else if (tvguideConfig.logoExtension == 1) {
+ extension = "jpg";
+ }
+ bool success = false;
+ if (tvguideConfig.logoPathSet) {
+ success = LoadImage(channelID.c_str(), *tvguideConfig.logoPath, *extension);
+ if (!success) {
+ success = LoadImage(logoLower.c_str(), *tvguideConfig.logoPath, *extension);
+ }
}
+ if (!success)
+ success = LoadImage(channelID.c_str(), *tvguideConfig.logoPathDefault, *extension);
+ if (!success)
+ success = LoadImage(logoLower.c_str(), *tvguideConfig.logoPathDefault, *extension);
+ if (success)
+ buffer.sample(Geometry(width, height));
+ return success;
+}
+
+bool cImageLoader::LoadEPGImage(int eventID, int width, int height) {
+ if ((width == 0)||(height==0))
+ return false;
+ bool success = false;
+ success = LoadImage(*cString::sprintf("%d", eventID), *tvguideConfig.epgImagePath, "jpg");
+ if (!success)
+ success = LoadImage(*cString::sprintf("%d_0", eventID), *tvguideConfig.epgImagePath, "jpg");
+ if (!success)
+ return false;
+ buffer.sample( Geometry(width, height));
return true;
}
-bool cImageLoader::LoadEPGImage(int eventID) {
- int width = tvguideConfig.epgImageWidth;
- int height = tvguideConfig.epgImageHeight;
+bool cImageLoader::LoadAdditionalEPGImage(cString name) {
+ int width = tvguideConfig.epgImageWidthLarge;
+ int height = tvguideConfig.epgImageHeightLarge;
if ((width == 0)||(height==0))
return false;
- if (!LoadImage(cString::sprintf("%d", eventID), tvguideConfig.epgImagePath, "jpg"))
+ bool success = false;
+ success = LoadImage(*name, *tvguideConfig.epgImagePath, "jpg");
+ if (!success)
return false;
if (height != 0 || width != 0) {
buffer.sample( Geometry(width, height));
@@ -45,17 +72,72 @@ bool cImageLoader::LoadEPGImage(int eventID) {
return true;
}
+bool cImageLoader::LoadPoster(const char *poster, int width, int height) {
+ if (LoadImage(poster)) {
+ buffer.sample(Geometry(width, height));
+ return true;
+ }
+ return false;
+}
+
+bool cImageLoader::LoadIcon(const char *cIcon, int size) {
+ if (size==0)
+ return false;
+ bool success = false;
+ if (tvguideConfig.iconsPathSet) {
+ cString iconPathTheme = cString::sprintf("%s%s/recmenuicons/", *tvguideConfig.iconPath, *tvguideConfig.themeName);
+ success = LoadImage(cIcon, *iconPathTheme, "png");
+ if (!success) {
+ cString iconPath = cString::sprintf("%srecmenuicons/", *tvguideConfig.iconPath);
+ success = LoadImage(cIcon, *iconPath, "png");
+ }
+ }
+ if (!success) {
+ cString iconPathTheme = cString::sprintf("%s%s/recmenuicons/", *tvguideConfig.iconPathDefault, *tvguideConfig.themeName);
+ success = LoadImage(cIcon, *iconPathTheme, "png");
+ if (!success) {
+ cString iconPath = cString::sprintf("%srecmenuicons/", *tvguideConfig.iconPathDefault);
+ success = LoadImage(cIcon, *iconPath, "png");
+ }
+ }
+ if (!success)
+ return false;
+ buffer.sample(Geometry(size, size));
+ return true;
+}
+
+bool cImageLoader::LoadOsdElement(cString name, int width, int height) {
+ if ((width == 0)||(height==0))
+ return false;
+ bool success = false;
+ if (tvguideConfig.iconsPathSet) {
+ cString path = cString::sprintf("%s%s%s", *tvguideConfig.iconPath, *tvguideConfig.themeName, "/osdElements/");
+ success = LoadImage(*name, *path, "png");
+ if (!success) {
+ path = cString::sprintf("%s%s", *tvguideConfig.iconPath, "/osdElements/");
+ success = LoadImage(*name, *path, "png");
+ }
+ }
+ if (!success) {
+ cString path = cString::sprintf("%s%s%s", *tvguideConfig.iconPathDefault, *tvguideConfig.themeName, "/osdElements/");
+ success = LoadImage(*name, *path, "png");
+ }
+ if (!success) {
+ cString path = cString::sprintf("%s%s", *tvguideConfig.iconPathDefault, "/osdElements/");
+ success = LoadImage(*name, *path, "png");
+ }
+ if (!success)
+ return false;
+ Geometry size(width, height);
+ size.aspect(true);
+ buffer.sample(size);
+ return true;
+}
+
bool cImageLoader::DrawBackground(tColor back, tColor blend, int width, int height) {
- if ((width == 0) || (height == 0))
+ if ((width < 1) || (height < 1) || (width > 1920) || (height > 1080))
return false;
- Color Back = Argb2Color(back);
- Color Blend = Argb2Color(blend);
- Image tmp(Geometry(width, height), Blend);
- double arguments[9] = {0.0,(double)height,0.0,-1*(double)width,0.0,0.0,1.5*(double)width,0.0,1.0};
- tmp.sparseColor(MatteChannel, BarycentricColorInterpolate, 9, arguments);
- Image tmp2(Geometry(width, height), Back);
- tmp.composite(tmp2, 0, 0, OverlayCompositeOp);
- buffer = tmp;
+ CreateGradient(back, blend, width, height, 0.8, 0.8);
return true;
}
@@ -78,30 +160,27 @@ cImage cImageLoader::GetImage() {
return image;
}
-Color cImageLoader::Argb2Color(tColor col) {
- tIndex alpha = (col & 0xFF000000) >> 24;
- tIndex red = (col & 0x00FF0000) >> 16;
- tIndex green = (col & 0x0000FF00) >> 8;
- tIndex blue = (col & 0x000000FF);
- Color color(MaxRGB*red/255, MaxRGB*green/255, MaxRGB*blue/255, MaxRGB*(0xFF-alpha)/255);
- return color;
-}
+void cImageLoader::CreateGradient(tColor back, tColor blend, int width, int height, double wfactor, double hfactor) {
+ Color Back = Argb2Color(back);
+ Color Blend = Argb2Color(blend);
+ int maxw = MaxRGB * wfactor;
+ int maxh = MaxRGB * hfactor;
-void cImageLoader::toLowerCase(std::string &str) {
- const int length = str.length();
- for(int i=0; i < length; ++i) {
- str[i] = std::tolower(str[i]);
+ Image imgblend(Geometry(width, height), Blend);
+ imgblend.modifyImage();
+ imgblend.type(TrueColorMatteType);
+ PixelPacket *pixels = imgblend.getPixels(0, 0, width, height);
+ for (int x = 0; x < width; x++) {
+ for (int y = 0; y < height; y++) {
+ PixelPacket *pixel = pixels + y * width + x;
+ int opacity = (maxw / width * x + maxh - maxh / height * y) / 2;
+ pixel->opacity = (opacity <= MaxRGB) ? opacity : MaxRGB;
+ }
}
-}
+ imgblend.syncPixels();
-bool cImageLoader::LoadImage(cString FileName, cString Path, cString Extension) {
- try {
- cString File = cString::sprintf("%s%s.%s", *Path, *FileName, *Extension);
- dsyslog("tvguide: trying to load: %s", *File);
- buffer.read(*File);
- dsyslog("tvguide: %s sucessfully loaded", *File);
- } catch (...) {
- return false;
- }
- return true;
-}
+ Image imgback(Geometry(width, height), Back);
+ imgback.composite(imgblend, 0, 0, OverCompositeOp);
+
+ buffer = imgback;
+}
\ No newline at end of file
diff --git a/imageloader.h b/imageloader.h
index 23faf65..942986f 100644
--- a/imageloader.h
+++ b/imageloader.h
@@ -6,22 +6,24 @@
#include <vdr/osd.h>
#include <vdr/skins.h>
#include <Magick++.h>
+#include "imagemagickwrapper.h"
using namespace Magick;
-class cImageLoader {
+class cImageLoader : public cImageMagickWrapper {
public:
cImageLoader();
~cImageLoader();
cImage GetImage();
- bool LoadLogo(const char *logo, int width, int height);
- bool LoadEPGImage(int eventID);
+ bool LoadLogo(const cChannel *channel, int width, int height);
+ bool LoadEPGImage(int eventID, int width, int height);
+ bool LoadAdditionalEPGImage(cString name);
+ bool LoadPoster(const char *poster, int width, int height);
+ bool LoadIcon(const char *cIcon, int size);
+ bool LoadOsdElement(cString name, int width, int height);
bool DrawBackground(tColor back, tColor blend, int width, int height);
private:
- Image buffer;
- Color Argb2Color(tColor col);
- void toLowerCase(std::string &str);
- bool LoadImage(cString FileName, cString Path, cString Extension);
+ void CreateGradient(tColor back, tColor blend, int width, int height, double wfactor, double hfactor);
};
#endif //_TVGUIDE_IMAGELOADER_H
diff --git a/imagemagickwrapper.c b/imagemagickwrapper.c
new file mode 100644
index 0000000..753b678
--- /dev/null
+++ b/imagemagickwrapper.c
@@ -0,0 +1,162 @@
+#include <string>
+#include <sstream>
+#include "imagemagickwrapper.h"
+#include "config.h"
+#include "imagescaler.h"
+
+cImageMagickWrapper::cImageMagickWrapper() {
+ InitializeMagick(NULL);
+}
+
+cImageMagickWrapper::~cImageMagickWrapper() {
+}
+
+cImage *cImageMagickWrapper::CreateImage(int width, int height, bool preserveAspect) {
+ int w, h;
+ w = buffer.columns();
+ h = buffer.rows();
+ if ((w == 0)||(h==0))
+ return NULL;
+ if (width == 0)
+ width = w;
+ if (height == 0)
+ height = h;
+ if (preserveAspect) {
+ unsigned scale_w = 1000 * width / w;
+ unsigned scale_h = 1000 * height / h;
+ if (scale_w > scale_h)
+ width = w * height / h;
+ else
+ height = h * width / w;
+ }
+ const PixelPacket *pixels = buffer.getConstPixels(0, 0, w, h);
+ cImage *image = NULL;
+ image = new cImage(cSize(width, height));
+ if (!image)
+ return NULL;
+ tColor *imgData = (tColor *)image->Data();
+ if (w != width || h != height) {
+ ImageScaler scaler;
+ scaler.SetImageParameters(imgData, width, width, height, w, h);
+ for (const void *pixels_end = &pixels[w*h]; pixels < pixels_end; ++pixels)
+ scaler.PutSourcePixel(pixels->blue / ((MaxRGB + 1) / 256),
+ pixels->green / ((MaxRGB + 1) / 256),
+ pixels->red / ((MaxRGB + 1) / 256),
+ ~((unsigned char)(pixels->opacity / ((MaxRGB + 1) / 256))));
+ return image;
+ }
+ for (const void *pixels_end = &pixels[width*height]; pixels < pixels_end; ++pixels)
+ *imgData++ = ((~int(pixels->opacity / ((MaxRGB + 1) / 256)) << 24) |
+ (int(pixels->green / ((MaxRGB + 1) / 256)) << 8) |
+ (int(pixels->red / ((MaxRGB + 1) / 256)) << 16) |
+ (int(pixels->blue / ((MaxRGB + 1) / 256)) ));
+ return image;
+}
+
+cImage cImageMagickWrapper::CreateImageCopy() {
+ int w, h;
+ w = buffer.columns();
+ h = buffer.rows();
+ cImage image (cSize(w, h));
+ const PixelPacket *pixels = buffer.getConstPixels(0, 0, w, h);
+ for (int iy = 0; iy < h; ++iy) {
+ for (int ix = 0; ix < w; ++ix) {
+ tColor col = (~int(pixels->opacity * 255 / MaxRGB) << 24)
+ | (int(pixels->green * 255 / MaxRGB) << 8)
+ | (int(pixels->red * 255 / MaxRGB) << 16)
+ | (int(pixels->blue * 255 / MaxRGB) );
+ image.SetPixel(cPoint(ix, iy), col);
+ ++pixels;
+ }
+ }
+ return image;
+}
+
+bool cImageMagickWrapper::LoadImage(std::string FileName, std::string Path, std::string Extension) {
+ try {
+ std::stringstream sstrImgFile;
+ sstrImgFile << Path << FileName << "." << Extension;
+ std::string imgFile = sstrImgFile.str();
+ if (tvguideConfig.debugImageLoading)
+ esyslog("tvguide: trying to load: %s", imgFile.c_str());
+ buffer.read(imgFile.c_str());
+ if (tvguideConfig.debugImageLoading)
+ esyslog("tvguide: %s sucessfully loaded", imgFile.c_str());
+ } catch( Magick::Warning &warning ) {
+ if (tvguideConfig.debugImageLoading)
+ esyslog("tvguide: Magick Warning: %s", warning.what());
+ return true;
+ } catch( Magick::Error &error ) {
+ if (tvguideConfig.debugImageLoading)
+ esyslog("tvguide: Magick Error: %s", error.what());
+ return false;
+ } catch(...) {
+ if (tvguideConfig.debugImageLoading)
+ esyslog("tvguide: an unknown Magick error occured during image loading");
+ return false;
+ }
+ return true;
+}
+
+bool cImageMagickWrapper::LoadImage(const char *fullpath) {
+ if ((fullpath == NULL) || (strlen(fullpath) < 5))
+ return false;
+ try {
+ if (tvguideConfig.debugImageLoading)
+ esyslog("tvguide: trying to load: %s", fullpath);
+ buffer.read(fullpath);
+ if (tvguideConfig.debugImageLoading)
+ esyslog("tvguide: %s sucessfully loaded", fullpath);
+ } catch( Magick::Warning &warning ) {
+ if (tvguideConfig.debugImageLoading)
+ esyslog("tvguide: Magick Warning: %s", warning.what());
+ return true;
+ } catch( Magick::Error &error ) {
+ if (tvguideConfig.debugImageLoading)
+ esyslog("tvguide: Magick Error: %s", error.what());
+ return false;
+ } catch(...) {
+ if (tvguideConfig.debugImageLoading)
+ esyslog("tvguide: an unknown Magick error occured during image loading");
+ return false;
+ }
+ return true;
+}
+
+Color cImageMagickWrapper::Argb2Color(tColor col) {
+ tIndex alpha = (col & 0xFF000000) >> 24;
+ tIndex red = (col & 0x00FF0000) >> 16;
+ tIndex green = (col & 0x0000FF00) >> 8;
+ tIndex blue = (col & 0x000000FF);
+ Color color(MaxRGB*red/255, MaxRGB*green/255, MaxRGB*blue/255, MaxRGB*(0xFF-alpha)/255);
+ return color;
+}
+
+void cImageMagickWrapper::CreateGradient(tColor back, tColor blend, int width, int height, double wfactor, double hfactor) {
+ Color Back = Argb2Color(back);
+ Color Blend = Argb2Color(blend);
+ int maxw = MaxRGB * wfactor;
+ int maxh = MaxRGB * hfactor;
+
+ Image imgblend(Geometry(width, height), Blend);
+ imgblend.modifyImage();
+ imgblend.type(TrueColorMatteType);
+ PixelPacket *pixels = imgblend.getPixels(0, 0, width, height);
+ for (int x = 0; x < width; x++) {
+ for (int y = 0; y < height; y++) {
+ PixelPacket *pixel = pixels + y * width + x;
+ int opacity = (maxw / width * x + maxh - maxh / height * y) / 2;
+ pixel->opacity = (opacity <= MaxRGB) ? opacity : MaxRGB;
+ }
+ }
+ imgblend.syncPixels();
+
+ Image imgback(Geometry(width, height), Back);
+ imgback.composite(imgblend, 0, 0, OverCompositeOp);
+
+ buffer = imgback;
+}
+
+void cImageMagickWrapper::CreateBackground(tColor back, tColor blend, int width, int height) {
+ CreateGradient(back, blend, width, height, 0.8, 0.8);
+}
\ No newline at end of file
diff --git a/imagemagickwrapper.h b/imagemagickwrapper.h
new file mode 100644
index 0000000..eafb69a
--- /dev/null
+++ b/imagemagickwrapper.h
@@ -0,0 +1,27 @@
+#ifndef __TVGUIDE_IMAGEMAGICKWRAPPER_H
+#define __TVGUIDE_IMAGEMAGICKWRAPPER_H
+
+#define X_DISPLAY_MISSING
+
+#include <Magick++.h>
+#include <vdr/osd.h>
+
+using namespace Magick;
+
+class cImageMagickWrapper {
+private:
+ void CreateGradient(tColor back, tColor blend, int width, int height, double wfactor, double hfactor);
+public:
+ cImageMagickWrapper();
+ ~cImageMagickWrapper();
+protected:
+ Image buffer;
+ Color Argb2Color(tColor col);
+ cImage *CreateImage(int width, int height, bool preserveAspect = true);
+ cImage CreateImageCopy(void);
+ bool LoadImage(std::string FileName, std::string Path, std::string Extension);
+ bool LoadImage(const char *fullpath);
+ void CreateBackground(tColor back, tColor blend, int width, int height);
+};
+
+#endif //__TVGUIDE_IMAGEMAGICKWRAPPER_H
diff --git a/imagescaler.c b/imagescaler.c
new file mode 100644
index 0000000..cebe912
--- /dev/null
+++ b/imagescaler.c
@@ -0,0 +1,149 @@
+
+#include "imagescaler.h"
+
+#include <cstdlib>
+#include <cmath>
+
+ImageScaler::ImageScaler() :
+ m_memory(NULL),
+ m_hor_filters(NULL),
+ m_ver_filters(NULL),
+ m_buffer(NULL),
+ m_dst_image(NULL),
+ m_dst_stride(0),
+ m_dst_width(0),
+ m_dst_height(0),
+ m_src_width(0),
+ m_src_height(0),
+ m_src_x(0),
+ m_src_y(0),
+ m_dst_x(0),
+ m_dst_y(0) {
+}
+
+ImageScaler::~ImageScaler() {
+ if ( m_memory ) free( m_memory );
+}
+
+// sin(x)/(x)
+static float sincf( float x ) {
+ if ( fabsf(x) < 0.05f ) return 1.0f - (1.0f/6.0f)*x*x; // taylor series approximation to avoid 0/0
+ return sin(x)/x;
+}
+
+static void CalculateFilters( ImageScaler::Filter *filters, int dst_size, int src_size ) {
+ const float fc = dst_size >= src_size ? 1.0f : ((float) dst_size)/((float) src_size);
+
+ for (int i = 0; i < dst_size; i++) {
+ const int d = 2*dst_size; // sample position denominator
+ const int e = (2*i+1) * src_size - dst_size; // sample position enumerator
+ int offset = e / d; // truncated sample position
+ const float sub_offset = ((float) (e - offset*d)) / ((float) d); // exact sample position is (float) e/d = offset + sub_offset
+
+ // calculate filter coefficients
+ float h[4];
+ for (int j=0; j<4; j++) {
+ const float t = 3.14159265359f * (sub_offset+(1-j));
+ h[j] = sincf( fc * t ) * cosf( 0.25f * t ); // sinc-lowpass and cos-window
+ }
+
+ // ensure that filter does not reach out off image bounds:
+ while ( offset < 1 ) {
+ h[0] += h[1];
+ h[1] = h[2];
+ h[2] = h[3];
+ h[3] = 0.0f;
+ offset++;
+ }
+
+ while ( offset+3 > src_size ) {
+ h[3] += h[2];
+ h[2] = h[1];
+ h[1] = h[0];
+ h[0] = 0.0f;
+ offset--;
+ }
+
+ // coefficients are normalized to sum up to 2048
+ const float norm = 2048.0f / ( h[0] + h[1] + h[2] + h[3] );
+
+ offset--; // offset of fist used pixel
+
+ filters[i].m_offset = offset + 4; // store offset of first unused pixel
+
+ for (int j=0; j<4; j++) {
+ const float t = norm * h[j];
+ filters[i].m_coeff[(offset+j) & 3] = (int) ((t > 0.0f) ? (t+0.5f) : (t-0.5f)); // consider ring buffer index permutations
+ }
+ }
+
+ // set end marker
+ filters[dst_size].m_offset = (unsigned) -1;
+
+}
+
+void ImageScaler::SetImageParameters( unsigned *dst_image, unsigned dst_stride, unsigned dst_width, unsigned dst_height, unsigned src_width, unsigned src_height ) {
+ m_src_x = 0;
+ m_src_y = 0;
+ m_dst_x = 0;
+ m_dst_y = 0;
+
+ m_dst_image = dst_image;
+ m_dst_stride = dst_stride;
+
+ // if image dimensions do not change we can keep the old filter coefficients
+ if ( (src_width == m_src_width) && (src_height == m_src_height) && (dst_width == m_dst_width) && (dst_height == m_dst_height) ) return;
+
+ m_dst_width = dst_width;
+ m_dst_height = dst_height;
+ m_src_width = src_width;
+ m_src_height = src_height;
+
+ if ( m_memory ) free( m_memory );
+
+ const unsigned hor_filters_size = (m_dst_width + 1) * sizeof(Filter); // reserve one extra position for end marker
+ const unsigned ver_filters_size = (m_dst_height + 1) * sizeof(Filter);
+ const unsigned buffer_size = 4 * m_dst_width * sizeof(TmpPixel);
+
+ char *p = (char *) malloc( hor_filters_size + ver_filters_size + buffer_size );
+
+ m_memory = p;
+
+ m_hor_filters = (Filter *) p; p += hor_filters_size;
+ m_ver_filters = (Filter *) p; p += ver_filters_size;
+ m_buffer = (TmpPixel *) p;
+
+ CalculateFilters( m_hor_filters, m_dst_width , m_src_width );
+ CalculateFilters( m_ver_filters, m_dst_height, m_src_height );
+}
+
+// shift range to 0..255 and clamp overflows
+static unsigned shift_clamp( int x ) {
+ x = ( x + (1<<21) ) >> 22;
+ if ( x < 0 ) return 0;
+ if ( x > 255 ) return 255;
+ return x;
+}
+
+void ImageScaler::NextSourceLine() {
+ m_dst_x = 0;
+ m_src_x = 0;
+ m_src_y++;
+
+ while ( m_ver_filters[m_dst_y].m_offset == m_src_y ) {
+ const int h0 = m_ver_filters[m_dst_y].m_coeff[0];
+ const int h1 = m_ver_filters[m_dst_y].m_coeff[1];
+ const int h2 = m_ver_filters[m_dst_y].m_coeff[2];
+ const int h3 = m_ver_filters[m_dst_y].m_coeff[3];
+ const TmpPixel *src = m_buffer;
+ unsigned *dst = m_dst_image + m_dst_stride * m_dst_y;
+
+ for (unsigned i=0; i<m_dst_width; i++) {
+ const ImageScaler::TmpPixel t( src[0]*h0 + src[1]*h1 + src[2]*h2 + src[3]*h3 );
+ src += 4;
+ dst[i] = shift_clamp(t[0]) | (shift_clamp(t[1])<<8) | (shift_clamp(t[2])<<16) | (shift_clamp(t[3])<<24);
+ }
+
+ m_dst_y++;
+ }
+}
diff --git a/imagescaler.h b/imagescaler.h
new file mode 100644
index 0000000..f2de6ba
--- /dev/null
+++ b/imagescaler.h
@@ -0,0 +1,97 @@
+#ifndef _ImageScaler_h
+#define _ImageScaler_h
+
+/*!
+ * this class scales images consisting of 4 components (RGBA)
+ * to an arbitrary size using a 4-tap filter
+ */
+class ImageScaler {
+public:
+
+ struct Filter {
+ unsigned m_offset;
+ short m_coeff[4];
+ };
+
+ ImageScaler();
+ ~ImageScaler();
+
+ //! set destination image and source image size
+ void SetImageParameters( unsigned *dst_image, unsigned dst_stride, unsigned dst_width, unsigned dst_height, unsigned src_width, unsigned src_height );
+
+ /*! process one pixel of source image; destination image is written while input is processed
+ * SetImageParameters() must be called first
+ */
+ void PutSourcePixel( unsigned char c0, unsigned char c1, unsigned char c2, unsigned char c3 ) {
+ m_hbuf[ (m_src_x++) & 3 ].Set( c0, c1, c2, c3 );
+
+ TmpPixel *bp = m_buffer + 4 * m_dst_x + (m_src_y & 3);
+ const Filter *fh;
+
+ while ( (fh=m_hor_filters+m_dst_x)->m_offset == m_src_x ) {
+ *bp = m_hbuf[0]*fh->m_coeff[0] + m_hbuf[1]*fh->m_coeff[1] + m_hbuf[2]*fh->m_coeff[2] + m_hbuf[3]*fh->m_coeff[3];
+ m_dst_x++;
+ bp += 4;
+ }
+
+ if ( m_src_x == m_src_width ) NextSourceLine();
+ }
+
+private:
+
+ //! temporary image pixel class - a 4-element integer vector
+ class TmpPixel {
+ public:
+ TmpPixel() {
+ }
+
+ TmpPixel( int c0, int c1, int c2, int c3 ) {
+ Set(c0,c1,c2,c3);
+ }
+
+ void Set( int c0, int c1, int c2, int c3 ) {
+ m_comp[0] = c0;
+ m_comp[1] = c1;
+ m_comp[2] = c2;
+ m_comp[3] = c3;
+ }
+
+ TmpPixel operator*( int s ) const {
+ return TmpPixel( m_comp[0]*s, m_comp[1]*s, m_comp[2]*s, m_comp[3]*s );
+ }
+
+ TmpPixel operator+( const TmpPixel &x ) const {
+ return TmpPixel( m_comp[0] + x[0], m_comp[1] + x[1], m_comp[2] + x[2], m_comp[3] + x[3] );
+ }
+
+ // return component i=[0..3] - No range check!
+ int operator[](unsigned i) const {
+ return m_comp[i];
+ }
+
+ private:
+ int m_comp[4];
+ };
+
+ //! this is called whenever one input line is processed completely
+ void NextSourceLine();
+
+ TmpPixel m_hbuf[4]; //! ring buffer for 4 input pixels
+ char *m_memory; //! buffer container
+ Filter *m_hor_filters; //! buffer for horizontal filters (one for each output image column)
+ Filter *m_ver_filters; //! buffer for vertical filters (one for each output image row)
+ TmpPixel *m_buffer; //! buffer contains 4 horizontally filtered input lines, multiplexed
+ unsigned *m_dst_image; //! pointer to destination image
+ unsigned m_dst_stride; //! destination image stride
+ unsigned m_dst_width; //! destination image width
+ unsigned m_dst_height; //! destination image height
+ unsigned m_src_width; //! source image width
+ unsigned m_src_height; //! source image height
+ unsigned m_src_x; //! x position of next source image pixel
+ unsigned m_src_y; //! y position of source image line currently beeing processed
+ unsigned m_dst_x; //! x position of next destination image pixel
+ unsigned m_dst_y; //! x position of next destination image line
+};
+
+#endif // _ImageScaler_h
+
diff --git a/messagebox.c b/messagebox.c
deleted file mode 100644
index 3f727d4..0000000
--- a/messagebox.c
+++ /dev/null
@@ -1,114 +0,0 @@
-#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;
- }
-}
diff --git a/messagebox.h b/messagebox.h
deleted file mode 100644
index 8b9ab23..0000000
--- a/messagebox.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#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
\ No newline at end of file
diff --git a/osdmanager.c b/osdmanager.c
index fb0ec6e..eefedf4 100644
--- a/osdmanager.c
+++ b/osdmanager.c
@@ -1,52 +1,38 @@
-#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
+#include "config.h"
+#include "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;
+ 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));
+
+ if (tvguideConfig.displayStatusHeader && tvguideConfig.scaleVideo) {
+ int widthStatus = cOsd::OsdWidth() - geoManager.statusHeaderHeight * 16 / 9;
+ osd->DrawRectangle(0, 0, widthStatus, geoManager.statusHeaderHeight, theme.Color(clrBackgroundOSD));
+ osd->DrawRectangle(0, geoManager.statusHeaderHeight, Width(), Height(), theme.Color(clrBackgroundOSD));
+ }
+ else
+ osd->DrawRectangle(0, 0, Width(), Height(), theme.Color(clrBackgroundOSD));
+
+}
+
+cPixmap *cOsdManager::requestPixmap(int Layer, const cRect &ViewPort, const cRect &DrawPort) {
+ return osd->CreatePixmap(Layer, ViewPort, DrawPort);
}
-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);
+void cOsdManager::releasePixmap(cPixmap *pixmap) {
+ if (!pixmap)
+ return;
+ osd->DestroyPixmap(pixmap);
}
\ No newline at end of file
diff --git a/osdmanager.h b/osdmanager.h
new file mode 100644
index 0000000..a0c7936
--- /dev/null
+++ b/osdmanager.h
@@ -0,0 +1,23 @@
+#ifndef __TVGUIDE_OSDMANAGER_H
+#define __TVGUIDE_OSDMANAGER_H
+
+#include <vdr/osd.h>
+
+class cOsdManager {
+ private:
+ cOsd *osd;
+ public:
+ cOsdManager(void);
+ bool setOsd();
+ void setBackground();
+ void flush() {osd->Flush();};
+ cPixmap *requestPixmap(int Layer, const cRect &ViewPort, const cRect &DrawPort = cRect::Null);
+ void releasePixmap(cPixmap *pixmap);
+ void deleteOsd() {delete osd;};
+ int Width() { return osd->Width(); };
+ int Height() { return osd->Height(); };
+ int Top() { return osd->Top(); };
+ int Left() { return osd->Left(); };
+};
+
+#endif //__TVGUIDE_OSDMANAGER_H
diff --git a/po/ca_ES.po b/po/ca_ES.po
new file mode 100644
index 0000000..6f8c6fb
--- /dev/null
+++ b/po/ca_ES.po
@@ -0,0 +1,958 @@
+# 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: 2014-05-10 17:24+0200\n"
+"PO-Revision-Date: 2013-09-21 17:49+0200\n"
+"Last-Translator: My friend <Sampep> Thanks David <Gabychan> <gbonich at gmail.com>\n"
+"Language-Team: \n"
+"Language: ca\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Poedit-Language: Catala\n"
+"X-Poedit-Country: Catalunya\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+msgid "Main Program"
+msgstr "Programa principal"
+
+msgid "Channel"
+msgstr "Canal"
+
+msgid "min"
+msgstr "min"
+
+msgid "Reruns of "
+msgstr ""
+
+msgid "No reruns found"
+msgstr ""
+
+msgid "No EPG Information available"
+msgstr "No hi ha informació EPG"
+
+msgid "Search & Rec"
+msgstr "Cerca & Enregistra"
+
+msgid "Channels back"
+msgstr "Canals enrere"
+
+msgid "Channels forward"
+msgstr "Canals endavant"
+
+msgid "Switch to Channel"
+msgstr "Canvia al canal"
+
+msgid "Detailed EPG"
+msgstr "EPG Detallat"
+
+msgid "Close detailed EPG"
+msgstr ""
+
+msgid "Favorites"
+msgstr ""
+
+msgid "images"
+msgstr ""
+
+msgid "root video folder"
+msgstr "Directori principal per a vídeo"
+
+msgid "Transp."
+msgstr "Transp."
+
+msgid "Timer Conflict"
+msgstr "Temporitzador en conflicte"
+
+msgid "all Channels"
+msgstr "tots els canals"
+
+msgid "unknown channel"
+msgstr "canal desconegut"
+
+msgid "Duration"
+msgstr "Durada"
+
+msgid "recorded at"
+msgstr "enregistrat a"
+
+msgid "from"
+msgstr "des de"
+
+msgid "Timers for"
+msgstr ""
+
+msgid "Rec"
+msgstr ""
+
+msgid "No Timers active"
+msgstr ""
+
+msgid "inactive"
+msgstr ""
+
+msgid "active timers"
+msgstr ""
+
+msgid "recordings done"
+msgstr ""
+
+msgid "What's on now"
+msgstr ""
+
+msgid "What's on next"
+msgstr ""
+
+msgid "Instant Record"
+msgstr "Enregistra a l'instant"
+
+msgid "Delete Timer"
+msgstr "Esborra temporitzador"
+
+msgid "Edit Timer"
+msgstr "Edita temporitzador"
+
+msgid "Timer Timeline"
+msgstr ""
+
+msgid "Create Search Timer"
+msgstr "Cerca temporitzadors"
+
+msgid "Search Timers"
+msgstr ""
+
+msgid "Create Series Timer"
+msgstr "Programa enregistrament de Sèries"
+
+msgid "Create Switch Timer"
+msgstr "Canvia temporitzadors"
+
+msgid "Delete Switch Timer"
+msgstr "Esborra canvis de temporitzadors"
+
+msgid "Search"
+msgstr "Cerca"
+
+msgid "Check for Timer Conflicts"
+msgstr "Comprova conflictes de temporitzadors"
+
+msgid "Search in Recordings"
+msgstr "Cerca a les gravacions"
+
+msgid "Set Folder for"
+msgstr "Programa carpeta per"
+
+msgid "Timer created"
+msgstr "Temporitzador creat"
+
+msgid "Timer NOT created"
+msgstr "Temporitzador NO creat"
+
+msgid "OK"
+msgstr "OK"
+
+msgid "Timer deleted"
+msgstr "Temporitzador esborrat"
+
+msgid "Timer"
+msgstr "Temporitzador"
+
+msgid "still recording - really delete?"
+msgstr "gravació en curs - segur que vols esborrar-la?"
+
+msgid "Yes"
+msgstr "Sí"
+
+msgid "No"
+msgstr "No"
+
+msgid "One"
+msgstr "Un"
+
+msgid "detected"
+msgstr "detectat"
+
+msgid "Timer Conflicts"
+msgstr "Conflicte al temporitzador"
+
+msgid "Show conflict"
+msgstr "Mostra conflicte"
+
+msgid "timers involved"
+msgstr "temporitzadors involucrats"
+
+msgid "Ignore Conflicts"
+msgstr "Ignora conflictes"
+
+msgid "Ignore Conflict"
+msgstr "Ignora conflicte"
+
+msgid "No Timer Conflicts found"
+msgstr "No s'han trobat conflictes"
+
+msgid "Close"
+msgstr "Tanca"
+
+msgid "reruns for"
+msgstr ""
+
+msgid "rerun for"
+msgstr ""
+
+msgid "found"
+msgstr ""
+
+msgid "Ignore reruns"
+msgstr ""
+
+msgid "No reruns found for Event"
+msgstr ""
+
+msgid "Timer for"
+msgstr ""
+
+msgid "replaced by rerun"
+msgstr ""
+
+msgid "Timer Active"
+msgstr "Temporitzador actiu"
+
+msgid "Priority"
+msgstr "Prioritat"
+
+msgid "Lifetime"
+msgstr "Temps restant"
+
+msgid "Day"
+msgstr "dia"
+
+msgid "Timer start time"
+msgstr "Inici temporitzador"
+
+msgid "Timer stop time"
+msgstr "Final temporitzador"
+
+msgid "Timer File"
+msgstr ""
+
+msgid "New Folder"
+msgstr ""
+
+msgid "Save"
+msgstr "Desa"
+
+msgid "Cancel"
+msgstr "Cancel·la"
+
+msgid "Create Series Timer based on"
+msgstr "Programa enregistrament de Sèries segons"
+
+msgid "Series Timer start time"
+msgstr "Inici temporitzador Sèries"
+
+msgid "Series Timer stop time"
+msgstr "Final temporitzador Sèries"
+
+msgid "Days to record"
+msgstr "Dies a enregistrar"
+
+msgid "Day to start"
+msgstr "Dia d'inici"
+
+msgid "Create Timer"
+msgstr "Crea temporitzador"
+
+msgid "Series Timer created"
+msgstr "Sèrie programada"
+
+msgid "Start"
+msgstr "Inici"
+
+msgid "Stop"
+msgstr "Final"
+
+msgid "Configure Search Timer based on"
+msgstr "Configura cerca de temporitzadors segons"
+
+msgid "Search Expression:"
+msgstr "Cerca expressió:"
+
+msgid "Continue"
+msgstr "Continua"
+
+msgid "Configure Search Timer for Search String"
+msgstr "Configura cerca de temporitzadors amb text"
+
+msgid "Manually configure Options"
+msgstr "Opcions de configuració manual"
+
+msgid "Use Template"
+msgstr "Utilitza plantilla"
+
+msgid "EPGSearch Search Timers"
+msgstr ""
+
+msgid "No Search Timers Configured"
+msgstr ""
+
+msgid "Configure Search Timer Options"
+msgstr ""
+
+msgid "Save Search Timer"
+msgstr ""
+
+msgid "Search String"
+msgstr ""
+
+msgid "Active"
+msgstr ""
+
+msgid "Search Mode"
+msgstr "Mode de cerca"
+
+msgid "Use Title"
+msgstr "Utilitza títol"
+
+msgid "Use Subtitle"
+msgstr "Utilitza subtítol"
+
+msgid "Use Description"
+msgstr "Utilitza descripció"
+
+msgid "Limit Channels"
+msgstr "Canals restringits"
+
+msgid "Use Time"
+msgstr "Utilitza temps"
+
+msgid "Display advanced Options"
+msgstr ""
+
+msgid "Limit Days of the Week"
+msgstr ""
+
+msgid "Time margin for start in minutes"
+msgstr ""
+
+msgid "Time margin for stop in minutes"
+msgstr ""
+
+msgid "Series Recording"
+msgstr ""
+
+msgid "Folder"
+msgstr ""
+
+msgid "Use VPS"
+msgstr ""
+
+msgid "Avoid Repeats"
+msgstr ""
+
+msgid "Use in Favorites"
+msgstr ""
+
+msgid "Hide advanced Options"
+msgstr ""
+
+msgid "Display Results for Search Timer"
+msgstr "Mostra resultats de la cerca"
+
+msgid "Start Channel"
+msgstr "Inicia canal"
+
+msgid "Stop Channel"
+msgstr "Atura canal"
+
+msgid "Start after"
+msgstr "Comença després"
+
+msgid "Start before"
+msgstr "Comença abans"
+
+msgid "Select Days"
+msgstr ""
+
+msgid "Number of allowed repeats"
+msgstr ""
+
+msgid "Compare Title"
+msgstr ""
+
+msgid "Compare Subtitle"
+msgstr ""
+
+msgid "Compare Description"
+msgstr ""
+
+msgid "Really delete Search Timer"
+msgstr ""
+
+msgid "Delete only Search Timer"
+msgstr ""
+
+msgid "Delete Search Timer and created Timers"
+msgstr ""
+
+msgid "Search Timer sucessfully created."
+msgstr "S'ha creat cerca de temporitzador"
+
+msgid "Search Timer update initialised"
+msgstr "Actualització de temporitzador iniciada"
+
+msgid "Search Timer NOT sucessfully created"
+msgstr "No s'ha creat cerca de temporitzador"
+
+msgid "Creating Search Timer"
+msgstr "Creant cerca de temporitzador"
+
+msgid "Search Term"
+msgstr "Cercant terme"
+
+msgid "Using Template"
+msgstr "Utilitzant plantilla"
+
+msgid "Use other Template"
+msgstr "Utilitza una altra plantilla"
+
+msgid "search results for Favorite"
+msgstr ""
+
+msgid "search result for Favorite"
+msgstr ""
+
+msgid "search results for Search Timer"
+msgstr "cerca resultats per temporitzador"
+
+msgid "search result for Search Timer"
+msgstr "cerca resultat per temporitzador"
+
+msgid "Nothing found for Search String"
+msgstr "No s'ha trobat la cadena de text"
+
+msgid "Configure Options for Switchtimer"
+msgstr "Opcions de configuració de canvi de temporitzador"
+
+msgid "Minutes before switching"
+msgstr "Minuts abans del canvi"
+
+msgid "switch"
+msgstr "canvia"
+
+msgid "announce only"
+msgstr "només anunci"
+
+msgid "ask for switch"
+msgstr "pregunta pel canvi"
+
+msgid "Switch Mode"
+msgstr "Mode de canvi"
+
+msgid "Create"
+msgstr "Crea"
+
+msgid "Switch Timer sucessfully created"
+msgstr "Canvi de temporitzador creat"
+
+msgid "Switch Timer NOT sucessfully created"
+msgstr "No s'ha creat el canvi de temporitzador"
+
+msgid "Switch Timer deleted"
+msgstr "Canvi de temporitzador esborrat"
+
+msgid "Channel to Search"
+msgstr "Canal a cercar"
+
+msgid "Search in title"
+msgstr "Cerca al títol"
+
+msgid "Search in Subtitle"
+msgstr "Cerca al subtítol"
+
+msgid "Search in Description"
+msgstr "Cerca a la descripció"
+
+msgid "Show Search Options"
+msgstr "Mostra opcions de cerca"
+
+msgid "Perform Search"
+msgstr "Realitza la cerca"
+
+msgid "search results for"
+msgstr "resultats de cerca per"
+
+msgid "search result for"
+msgstr "resultat de cerca per"
+
+msgid "Adapt Search"
+msgstr "Cerca adaptada"
+
+msgid "Search String has to have at least three letters"
+msgstr ""
+
+msgid "Found"
+msgstr "Trobada"
+
+msgid "recording"
+msgstr "gravació"
+
+msgid "recordings"
+msgstr "gravacions"
+
+msgid "for"
+msgstr "per"
+
+msgid "No recordings found for"
+msgstr "No s'han trobat gravacions per"
+
+msgid "No Favorites available"
+msgstr ""
+
+msgid "whole term must appear"
+msgstr "expressió completa"
+
+msgid "all terms must exist"
+msgstr "totes les paraules"
+
+msgid "one term must exist"
+msgstr "alguna paraula"
+
+msgid "exact match"
+msgstr "coincidència exacta"
+
+msgid "regular expression"
+msgstr "expressió regular"
+
+msgid "General Settings"
+msgstr "Preferències"
+
+msgid "Screen Presentation"
+msgstr "Presentació de pantalla"
+
+msgid "Fonts and Fontsizes"
+msgstr "Tipus i mida de lletra"
+
+msgid "Recording Menus and Favorites"
+msgstr ""
+
+msgid "Image Loading and Caching"
+msgstr ""
+
+msgid "x channels back / forward"
+msgstr "x canals enrere / endavant"
+
+msgid "previous / next channel group"
+msgstr "anterior / següent grup de canals"
+
+msgid "Blue: Channel Switch, Ok: Detailed EPG"
+msgstr "Blau: Canvi de canal, OK: EPG detallat"
+
+msgid "Blue: Detailed EPG, Ok: Channel Switch"
+msgstr "Blau: EPG detallat, OK: Canvi de canal"
+
+msgid "Blue: Favorites / Switch, Ok: Detailed EPG"
+msgstr ""
+
+msgid "Timely Jump"
+msgstr ""
+
+msgid "Jump to specific channel"
+msgstr ""
+
+msgid "never"
+msgstr "mai"
+
+msgid "if exists"
+msgstr "si existeix"
+
+msgid "always"
+msgstr "sempre"
+
+msgid "Show Main Menu Entry"
+msgstr "Mostra entrada del menú principal"
+
+msgid "Replace VDR Schedules Menu"
+msgstr "Canvia el menú Programació VDR"
+
+msgid "Use appropriate nOpacity Theme"
+msgstr ""
+
+msgid "Theme"
+msgstr "Plantilla"
+
+msgid "Time to display in minutes"
+msgstr "Temps a mostrar en minuts"
+
+msgid "Rounded Corners"
+msgstr "Cantells rodons"
+
+msgid "Channel Jump Mode (Keys Green / Yellow)"
+msgstr "Mode de salt de canal (Botons Verd / Groc)"
+
+msgid "Keys Blue and OK"
+msgstr "Botons Blau i OK"
+
+msgid "Close TVGuide after channel switch"
+msgstr "Tanca GuiaTV després del canvi de canal"
+
+msgid "Functionality of numeric Keys"
+msgstr ""
+
+msgid "Hide last Channel Group"
+msgstr "Amaga el darrer grup de canals"
+
+msgid "Big Step (Keys 1 / 3) in hours"
+msgstr "Salt (Botons 1 / 3) en hores"
+
+msgid "Huge Step (Keys 4 / 6) in hours"
+msgstr "Salt (Botons 4 / 6) en hores"
+
+msgid "Time Format (12h/24h)"
+msgstr "Format de temps (12h/24h)"
+
+msgid "EPG Window Text Scrolling Speed"
+msgstr ""
+
+msgid "Display Reruns in detailed EPG View"
+msgstr "Mostre reemissions a l'EPG detallat"
+
+msgid "Number of reruns to display"
+msgstr "Nombre de reemissions a mostrar"
+
+msgid "Use Subtitle for reruns"
+msgstr "Utilitza subtítol per reemissions"
+
+msgid "Display Mode"
+msgstr "Mode de visualització"
+
+msgid "Height of Channel Header (Perc. of osd height)"
+msgstr "Alçada de la capçalera del Canal (% alçada OSD)"
+
+msgid "Width of Timeline (Perc. of osd width)"
+msgstr "Amplada cronologia (% amplada OSD)"
+
+msgid "Number of Channels to display"
+msgstr "Nombre de Canals a mostrar"
+
+msgid "Width of Channel Header (Perc. of osd width)"
+msgstr "Amplada de la capçalera del Canal (% amplada OSD)"
+
+msgid "Height of Timeline (Perc. of osd height)"
+msgstr "Alçada cronologia (% alçada OSD)"
+
+msgid "Display time in EPG Grids"
+msgstr "Mostra el temps a l'EPG"
+
+msgid "Height of Headers (Status Header and EPG View, Perc. of osd height)"
+msgstr ""
+
+msgid "Height of Footer (Perc. of osd height)"
+msgstr ""
+
+msgid "Display status header"
+msgstr "Mostra capçalera d'estat"
+
+msgid "Scale video to upper right corner"
+msgstr "Escala de vídeo a cantonada superior dreta"
+
+msgid "Rounded corners around video frame"
+msgstr "Cantells rodons als fotogrames de vídeo"
+
+msgid "Display Channel Names in Header"
+msgstr "Mostra nom del canal a la capçalera"
+
+msgid "Display channel groups"
+msgstr "Mostra grups de canals"
+
+msgid "Height of channel groups (Perc. of osd height)"
+msgstr "Alçada dels grups de canals (% alçada OSD)"
+
+msgid "Width of channel groups (Perc. of osd width)"
+msgstr "Amplada dels grups de canals (% amplada OSD)"
+
+msgid "Display current time baseline"
+msgstr ""
+
+msgid "Show Channel Logos"
+msgstr "Mosta Logotip del canal"
+
+msgid "Logo Path used"
+msgstr "Origen logotip utilitzat"
+
+msgid "Logo Extension"
+msgstr "Extensió del Logotip"
+
+msgid "Logo width ratio"
+msgstr "Proporció amplada logotip"
+
+msgid "Logo height ratio"
+msgstr "Proporció alçada logotip"
+
+msgid "Text Border in Detailed View (pixel)"
+msgstr ""
+
+msgid "Show EPG Images"
+msgstr "Mostra imatges EPG"
+
+msgid "EPG Images Path used"
+msgstr "Origen imatges EPG utilitzades"
+
+msgid "EPG Image width"
+msgstr "Amplada imatge EPG"
+
+msgid "EPG Image height"
+msgstr "Alçada imatge EPG"
+
+msgid "Number of additional EPG Images"
+msgstr "Nombre addicional d'imatges EPG"
+
+msgid "Additional EPG Image width"
+msgstr "Amplada imatge addicional EPG"
+
+msgid "Additional EPG Image height"
+msgstr "Alçada imatge addicional EPG"
+
+msgid "Font"
+msgstr "Font"
+
+msgid "Status Header Font Size"
+msgstr "Mida de la Font - capçalera d'estat"
+
+msgid "Status Header Large Font Size"
+msgstr "Mida de la Font gran - capçalera d'estat"
+
+msgid "Detail EPG View Font Size"
+msgstr "Mida de la Font - EPG detallat"
+
+msgid "Detail EPG View Header Font Size"
+msgstr "Mida de la Font - capçalera EPG detallat"
+
+msgid "Message Font Size"
+msgstr "Mida de la Font - missatges"
+
+msgid "Message Large Font Size"
+msgstr "Mida de la Font gran - missatges"
+
+msgid "Button Font Size"
+msgstr "Mida de la Font dels botons"
+
+msgid "Channel Header Font Size"
+msgstr "Mida de la Font - capçalera canal"
+
+msgid "Channel Groups Font Size"
+msgstr "Mida de la Font - grups de canals"
+
+msgid "Grid Font Size"
+msgstr "Mida de la Font - graelles"
+
+msgid "Grid Font Small Size"
+msgstr "Mida de la Font petita - graelles"
+
+msgid "Timeline Weekday Font Size"
+msgstr "Mida de la Font - dia setmana cronologia"
+
+msgid "Timeline Date Font Size"
+msgstr "Mida de la Font - data cronologia"
+
+msgid "Timeline Time Font Size"
+msgstr "Mida de la Font - temps cronologia"
+
+msgid "Search & Recording Menu Font Size"
+msgstr "Mida de la Font - Menú Cerca & Enregistra"
+
+msgid "Search & Recording Menu Small Font Size"
+msgstr "Mida de la Font petita - Menú Cerca & Enregistra"
+
+msgid "Search & Recording Menu Header Font Size"
+msgstr ""
+
+msgid "Always use root video folder"
+msgstr ""
+
+msgid "Select from folder list"
+msgstr ""
+
+msgid "Use fixed folder"
+msgstr ""
+
+msgid "Folder for instant Recordings"
+msgstr ""
+
+msgid "Use Remotetimers"
+msgstr "Utilitza temporitzadors remots"
+
+msgid "Use \"What's on now\" in favorites"
+msgstr ""
+
+msgid "Use \"What's on next\" in favorites"
+msgstr ""
+
+msgid "Use user defined time 1 in favorites"
+msgstr ""
+
+msgid "Description"
+msgstr ""
+
+msgid "Time"
+msgstr ""
+
+msgid "Use user defined time 2 in favorites"
+msgstr ""
+
+msgid "Use user defined time 3 in favorites"
+msgstr ""
+
+msgid "Use user defined time 4 in favorites"
+msgstr ""
+
+msgid "Limit channels in favorites"
+msgstr ""
+
+msgid "Create Log Messages for image loading"
+msgstr ""
+
+msgid "Limit Logo Cache"
+msgstr ""
+
+msgid "Maximal number of logos to cache"
+msgstr ""
+
+msgid "Number of logos to cache at start"
+msgstr ""
+
+msgid "Cache Sizes"
+msgstr ""
+
+msgid "OSD Element Cache"
+msgstr ""
+
+msgid "Logo cache"
+msgstr ""
+
+msgid "EPG Grid Cache"
+msgstr ""
+
+msgid "Channel Groups Cache"
+msgstr ""
+
+msgid "Recording Menus Icon Cache"
+msgstr ""
+
+msgid "No Cast available"
+msgstr ""
+
+msgid "Cast"
+msgstr ""
+
+msgid "EPG Info"
+msgstr ""
+
+msgid "Reruns"
+msgstr ""
+
+msgid "Recording Information"
+msgstr ""
+
+msgid "Image Galery"
+msgstr ""
+
+msgid "TheTVDB Info"
+msgstr ""
+
+msgid "TheTVDB Information"
+msgstr ""
+
+msgid "Episode"
+msgstr ""
+
+msgid "Season"
+msgstr ""
+
+msgid "Episode Overview"
+msgstr ""
+
+msgid "First aired"
+msgstr ""
+
+msgid "Guest Stars"
+msgstr ""
+
+msgid "TheMovieDB Rating"
+msgstr ""
+
+msgid "Series Overview"
+msgstr ""
+
+msgid "Genre"
+msgstr ""
+
+msgid "Network"
+msgstr ""
+
+msgid "Status"
+msgstr ""
+
+msgid "TheMovieDB Information"
+msgstr ""
+
+msgid "Original Title"
+msgstr ""
+
+msgid "Tagline"
+msgstr ""
+
+msgid "Overview"
+msgstr ""
+
+msgid "yes"
+msgstr ""
+
+msgid "no"
+msgstr ""
+
+msgid "Adult"
+msgstr ""
+
+msgid "Collection"
+msgstr ""
+
+msgid "Budget"
+msgstr ""
+
+msgid "Revenue"
+msgstr ""
+
+msgid "Homepage"
+msgstr ""
+
+msgid "Release Date"
+msgstr ""
+
+msgid "Runtime"
+msgstr ""
+
+msgid "minutes"
+msgstr ""
+
+msgid "TheMovieDB Popularity"
+msgstr ""
+
+msgid "TheMovieDB Vote Average"
+msgstr ""
+
+#~ msgid "RERUNS OF THIS SHOW"
+#~ msgstr "REEMISSIONS"
+
+#~ msgid "Actors"
+#~ msgstr "Actors"
+
+#~ msgid "Use folders for instant records"
+#~ msgstr "Utilitza carpetes per gravacions a l'instant"
+
+#~ msgid "Height of status header (Perc. of osd height)"
+#~ msgstr "Alçada capçalera d'estat (% alçada OSD)"
+
+#~ msgid "Configure Search Timer Options for Search String"
+#~ msgstr "Configura opcions de cerca de temporitzadors amb text"
diff --git a/po/de_DE.po b/po/de_DE.po
index 0a4c8ed..d2e7cdf 100755
--- a/po/de_DE.po
+++ b/po/de_DE.po
@@ -3,7 +3,7 @@ msgid ""
msgstr ""
"Project-Id-Version: vdr-tvguide 0.0.1\n"
"Report-Msgid-Bugs-To: <see README>\n"
-"POT-Creation-Date: 2013-01-17 14:01+0100\n"
+"POT-Creation-Date: 2014-05-10 17:24+0200\n"
"PO-Revision-Date: 2012-08-25 17:49+0200\n"
"Last-Translator: Horst\n"
"Language-Team: \n"
@@ -12,8 +12,26 @@ msgstr ""
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-msgid "Set Timer"
-msgstr "Aufnehmen"
+msgid "Main Program"
+msgstr "Hauptprogramm"
+
+msgid "Channel"
+msgstr "Kanal"
+
+msgid "min"
+msgstr "min"
+
+msgid "Reruns of "
+msgstr "Wiederholungen von "
+
+msgid "No reruns found"
+msgstr "Keine Wiederholungen gefunden"
+
+msgid "No EPG Information available"
+msgstr "Keine EPG Daten verfügbar"
+
+msgid "Search & Rec"
+msgstr "Suchen & Aufn."
msgid "Channels back"
msgstr "Kanäle zurück"
@@ -24,6 +42,486 @@ msgstr "Kanäle vor"
msgid "Switch to Channel"
msgstr "Umschalten"
+msgid "Detailed EPG"
+msgstr "Detailiertes EPG"
+
+msgid "Close detailed EPG"
+msgstr "Det. EPG schließen"
+
+msgid "Favorites"
+msgstr "Favoriten"
+
+msgid "images"
+msgstr "Bilder"
+
+msgid "root video folder"
+msgstr "Video Hauptverzeichnis"
+
+msgid "Transp."
+msgstr "Transp."
+
+msgid "Timer Conflict"
+msgstr "Timer Konflikt"
+
+msgid "all Channels"
+msgstr "alle Kanäle"
+
+msgid "unknown channel"
+msgstr "unbekannter Kanal"
+
+msgid "Duration"
+msgstr "Dauer"
+
+msgid "recorded at"
+msgstr "aufgenommen am"
+
+msgid "from"
+msgstr "von"
+
+msgid "Timers for"
+msgstr "Timer für"
+
+msgid "Rec"
+msgstr "Aufn"
+
+msgid "No Timers active"
+msgstr "Keine Timer aktiv"
+
+msgid "inactive"
+msgstr "inaktiv"
+
+msgid "active timers"
+msgstr "aktive Timer"
+
+msgid "recordings done"
+msgstr "erledigte Aufnahmen"
+
+msgid "What's on now"
+msgstr "Was läuft jetzt?"
+
+msgid "What's on next"
+msgstr "Was läuft als nächstes?"
+
+msgid "Instant Record"
+msgstr "Aufnahme"
+
+msgid "Delete Timer"
+msgstr "Timer löschen"
+
+msgid "Edit Timer"
+msgstr "Timer bearbeiten"
+
+msgid "Timer Timeline"
+msgstr "Timer Tagesübersicht"
+
+msgid "Create Search Timer"
+msgstr "Suchtimer anlegen"
+
+msgid "Search Timers"
+msgstr "Suchtimer"
+
+msgid "Create Series Timer"
+msgstr "Serientimer anlegen"
+
+msgid "Create Switch Timer"
+msgstr "Umschalttimer anlegen"
+
+msgid "Delete Switch Timer"
+msgstr "Umschalttimer löschen"
+
+msgid "Search"
+msgstr "Suchen"
+
+msgid "Check for Timer Conflicts"
+msgstr "Auf Timerkonflikte prüfen"
+
+msgid "Search in Recordings"
+msgstr "In Aufnahmen suchen"
+
+msgid "Set Folder for"
+msgstr "Verzeichnis festlegen für"
+
+msgid "Timer created"
+msgstr "Timer angelegt"
+
+msgid "Timer NOT created"
+msgstr "Timer NICHT angelegt"
+
+msgid "OK"
+msgstr "OK"
+
+msgid "Timer deleted"
+msgstr "Timer gelöscht"
+
+msgid "Timer"
+msgstr "Timer"
+
+msgid "still recording - really delete?"
+msgstr "Aufzeichnung läuft - wirklich löschen?"
+
+msgid "Yes"
+msgstr "Ja"
+
+msgid "No"
+msgstr "Nein"
+
+msgid "One"
+msgstr "Ein"
+
+msgid "detected"
+msgstr "gefunden"
+
+msgid "Timer Conflicts"
+msgstr "Timerkonflikte"
+
+msgid "Show conflict"
+msgstr "Konflikt zeigen"
+
+msgid "timers involved"
+msgstr "Timer beteiligt"
+
+msgid "Ignore Conflicts"
+msgstr "Konflikte ignorieren"
+
+msgid "Ignore Conflict"
+msgstr "Konflikt ignorieren"
+
+msgid "No Timer Conflicts found"
+msgstr "Keine Timerkonflikte gefunden"
+
+msgid "Close"
+msgstr "Schließen"
+
+msgid "reruns for"
+msgstr "Wiederholungen für"
+
+msgid "rerun for"
+msgstr "Wiederholung für"
+
+msgid "found"
+msgstr "gefunden"
+
+msgid "Ignore reruns"
+msgstr "Wiederholungen ignorieren"
+
+msgid "No reruns found for Event"
+msgstr "Keine Wiederholungen gefunden für"
+
+msgid "Timer for"
+msgstr "Timer für"
+
+msgid "replaced by rerun"
+msgstr "ersetzt durch Wiederholung"
+
+msgid "Timer Active"
+msgstr "Timer aktiv"
+
+msgid "Priority"
+msgstr "Priorität"
+
+msgid "Lifetime"
+msgstr "Lebensdauer"
+
+msgid "Day"
+msgstr "Tag"
+
+msgid "Timer start time"
+msgstr "Timer Start Zeit"
+
+msgid "Timer stop time"
+msgstr "Timer Stop Zeit"
+
+msgid "Timer File"
+msgstr "Timer Datei"
+
+msgid "New Folder"
+msgstr "Neues Verzeichnis"
+
+msgid "Save"
+msgstr "Speichern"
+
+msgid "Cancel"
+msgstr "Abbrechen"
+
+msgid "Create Series Timer based on"
+msgstr "Serientimer anlegen basierend auf"
+
+msgid "Series Timer start time"
+msgstr "Serientimer Start Zeit"
+
+msgid "Series Timer stop time"
+msgstr "Serientimer Stop Zeit"
+
+msgid "Days to record"
+msgstr "Tage"
+
+msgid "Day to start"
+msgstr "Beginnen am"
+
+msgid "Create Timer"
+msgstr "Timer anlegen"
+
+msgid "Series Timer created"
+msgstr "Serientimer angelegt"
+
+msgid "Start"
+msgstr "Start"
+
+msgid "Stop"
+msgstr "Stop"
+
+msgid "Configure Search Timer based on"
+msgstr "Suchtimer konfigurieren basierend auf"
+
+msgid "Search Expression:"
+msgstr "Suchausdruck:"
+
+msgid "Continue"
+msgstr "Weiter"
+
+msgid "Configure Search Timer for Search String"
+msgstr "Suchtimer konfigurieren für Suchbegriff"
+
+msgid "Manually configure Options"
+msgstr "Optionen manuell konfigurieren"
+
+msgid "Use Template"
+msgstr "Template benutzen"
+
+msgid "EPGSearch Search Timers"
+msgstr "EPGSearch Suchtimer"
+
+msgid "No Search Timers Configured"
+msgstr "Keine Suchtimer angelegt"
+
+msgid "Configure Search Timer Options"
+msgstr "Suchtimer konfigurieren"
+
+msgid "Save Search Timer"
+msgstr "Suchtimer speichern"
+
+msgid "Search String"
+msgstr "Suchbegriff"
+
+msgid "Active"
+msgstr "Aktiv"
+
+msgid "Search Mode"
+msgstr "Suchmodus"
+
+msgid "Use Title"
+msgstr "Titel benutzen"
+
+msgid "Use Subtitle"
+msgstr "Untertitel benutzen"
+
+msgid "Use Description"
+msgstr "Beschreibung benutzen"
+
+msgid "Limit Channels"
+msgstr "Kanäle einschränken"
+
+msgid "Use Time"
+msgstr "Zeit benutzen"
+
+msgid "Display advanced Options"
+msgstr "Erweiterte Optionen anzeigen"
+
+msgid "Limit Days of the Week"
+msgstr "Wochentage beschränken"
+
+msgid "Time margin for start in minutes"
+msgstr "Zeit vor Start in Minuten"
+
+msgid "Time margin for stop in minutes"
+msgstr "Zeit nach Ende in Minuten"
+
+msgid "Series Recording"
+msgstr "Serienaufnahme"
+
+msgid "Folder"
+msgstr "Verzeichnis"
+
+msgid "Use VPS"
+msgstr "VPS benutzen"
+
+msgid "Avoid Repeats"
+msgstr "Wiederholungen vermeiden"
+
+msgid "Use in Favorites"
+msgstr "Als Favorit benutzen"
+
+msgid "Hide advanced Options"
+msgstr "Erweiterte Optionen ausblenden"
+
+msgid "Display Results for Search Timer"
+msgstr "Ergebnisse für Suchtimer anzeigen"
+
+msgid "Start Channel"
+msgstr "Startkanal"
+
+msgid "Stop Channel"
+msgstr "Stopkanal"
+
+msgid "Start after"
+msgstr "Beginn nach"
+
+msgid "Start before"
+msgstr "Beginn vor"
+
+msgid "Select Days"
+msgstr "Tage bestimmen"
+
+msgid "Number of allowed repeats"
+msgstr "Anzahl erlaubter Wiederholungen"
+
+msgid "Compare Title"
+msgstr "Titel vergleichen"
+
+msgid "Compare Subtitle"
+msgstr "Untertitel vergleichen"
+
+msgid "Compare Description"
+msgstr "Beschreibung vergleichen"
+
+msgid "Really delete Search Timer"
+msgstr "Suchtimer wirklich löschen"
+
+msgid "Delete only Search Timer"
+msgstr "Nur Suchtimer löschen"
+
+msgid "Delete Search Timer and created Timers"
+msgstr "Suchtimer und erzeugte Timer löschen"
+
+msgid "Search Timer sucessfully created."
+msgstr "Suchtimer erfolgreich angelegt"
+
+msgid "Search Timer update initialised"
+msgstr "Suchtimer update initialisiert"
+
+msgid "Search Timer NOT sucessfully created"
+msgstr "Suchtimer NICHT erfolgreich angelegt"
+
+msgid "Creating Search Timer"
+msgstr "Suchtimer anlegen"
+
+msgid "Search Term"
+msgstr "Suchbegriff"
+
+msgid "Using Template"
+msgstr "Template"
+
+msgid "Use other Template"
+msgstr "Anderes Template benutzen"
+
+msgid "search results for Favorite"
+msgstr "Suchergebnisse für Favorit"
+
+msgid "search result for Favorite"
+msgstr "Suchergebnis für Favorit"
+
+msgid "search results for Search Timer"
+msgstr "Treffer für Suchtimer"
+
+msgid "search result for Search Timer"
+msgstr "Treffer für Suchtimer"
+
+msgid "Nothing found for Search String"
+msgstr "Keine Treffer für Suchbegriff"
+
+msgid "Configure Options for Switchtimer"
+msgstr "Optionen für Umschalttimer konfigurieren"
+
+msgid "Minutes before switching"
+msgstr "Minuten vor umschalten"
+
+msgid "switch"
+msgstr "umschalten"
+
+msgid "announce only"
+msgstr "nur ankündigen"
+
+msgid "ask for switch"
+msgstr "vor umschalten fragen"
+
+msgid "Switch Mode"
+msgstr "Umschaltmodus"
+
+msgid "Create"
+msgstr "Anlegen"
+
+msgid "Switch Timer sucessfully created"
+msgstr "Umschalttimer erfolgreich angelegt"
+
+msgid "Switch Timer NOT sucessfully created"
+msgstr "Umschalttimer NICHT erfolgreich angelegt"
+
+msgid "Switch Timer deleted"
+msgstr "Umschalttimer gelöscht"
+
+msgid "Channel to Search"
+msgstr "Suche auf Kanal"
+
+msgid "Search in title"
+msgstr "In Titel suchen"
+
+msgid "Search in Subtitle"
+msgstr "In Untertitel suchen"
+
+msgid "Search in Description"
+msgstr "In Beschreibung suchen"
+
+msgid "Show Search Options"
+msgstr "Suchoptionen anzeigen"
+
+msgid "Perform Search"
+msgstr "Suche ausführen"
+
+msgid "search results for"
+msgstr "Suchergebnisse für"
+
+msgid "search result for"
+msgstr "Suchergebnis für"
+
+msgid "Adapt Search"
+msgstr "Suche anpassen"
+
+msgid "Search String has to have at least three letters"
+msgstr "Suchausdruck muss mindestens drei Zeichen haben"
+
+msgid "Found"
+msgstr " "
+
+msgid "recording"
+msgstr "Aufnahme gefunden"
+
+msgid "recordings"
+msgstr "Aufnahmen gefunden"
+
+msgid "for"
+msgstr "für"
+
+msgid "No recordings found for"
+msgstr "Keine Aufnahmen gefunden für"
+
+msgid "No Favorites available"
+msgstr "Keine Favoriten verfügbar"
+
+msgid "whole term must appear"
+msgstr "vollständiger Ausdruck"
+
+msgid "all terms must exist"
+msgstr "alle Worte"
+
+msgid "one term must exist"
+msgstr "ein Wort"
+
+msgid "exact match"
+msgstr "exakt"
+
+msgid "regular expression"
+msgstr "Regulärer Ausdruck"
+
msgid "General Settings"
msgstr "Allgemeine Einstellungen"
@@ -33,14 +531,74 @@ msgstr "Anzeigeoptionen"
msgid "Fonts and Fontsizes"
msgstr "Schriften und Schriftgrößen"
-msgid "Number of Channels / Columns"
-msgstr "Anzahl der Kanäle bzw. Spalten"
+msgid "Recording Menus and Favorites"
+msgstr "Aufzeichnungsmenü und Favoriten"
+
+msgid "Image Loading and Caching"
+msgstr "Image Loading und Caching"
+
+msgid "x channels back / forward"
+msgstr "x Kanäle zurück / vor"
+
+msgid "previous / next channel group"
+msgstr "vorherige / nächste Kanalgruppe"
+
+msgid "Blue: Channel Switch, Ok: Detailed EPG"
+msgstr "Blau: Umschalten, OK: Detailiertes EPG"
+
+msgid "Blue: Detailed EPG, Ok: Channel Switch"
+msgstr "Blau: Detailiertes EPG, OK: Umschalten"
+
+msgid "Blue: Favorites / Switch, Ok: Detailed EPG"
+msgstr "Blau: Favoriten / Umschalten, OK: Det. EPG"
+
+msgid "Timely Jump"
+msgstr "Zeitsprung"
+
+msgid "Jump to specific channel"
+msgstr "Sprung zu deinem bestimmten Kanal"
+
+msgid "never"
+msgstr "nie"
+
+msgid "if exists"
+msgstr "falls vorhanden"
+
+msgid "always"
+msgstr "immer"
+
+msgid "Show Main Menu Entry"
+msgstr "Hauptmenüeintrag anzeigen"
+
+msgid "Replace VDR Schedules Menu"
+msgstr "VDR Programm Menü ersetzen"
+
+msgid "Use appropriate nOpacity Theme"
+msgstr "Entsprechendes nOpacity Theme benutzen"
+
+msgid "Theme"
+msgstr "Theme"
+
+msgid "Time to display in minutes"
+msgstr "Angezeigte Zeitspanne in Minuten"
+
+msgid "Rounded Corners"
+msgstr "Abgerundete Ecken"
+
+msgid "Channel Jump Mode (Keys Green / Yellow)"
+msgstr "Kanalsprung Modus (Tasten grün / gelb)"
+
+msgid "Keys Blue and OK"
+msgstr "Tasten Blau und OK"
-msgid "Channels to Jump (Keys Green / Yellow)"
-msgstr "Kanalsprung (Tasten Grün / Gelb)"
+msgid "Close TVGuide after channel switch"
+msgstr "TVGuide nach Umschalten schließen"
-msgid "Time to display vertically in minutes"
-msgstr "Vertikal angezeigte Zeit (in Minuten)"
+msgid "Functionality of numeric Keys"
+msgstr "Funktion der Nummerntasten"
+
+msgid "Hide last Channel Group"
+msgstr "Letzte Kanalgruppe verstecken"
msgid "Big Step (Keys 1 / 3) in hours"
msgstr "Großer Sprung (Tasten 1 / 3) in Stunden"
@@ -51,23 +609,68 @@ msgstr "Sehr großer Sprung (Tasten 4 / 6) in Stunden"
msgid "Time Format (12h/24h)"
msgstr "Zeitformat (12h/24h)"
-msgid "Theme"
-msgstr "Theme"
+msgid "EPG Window Text Scrolling Speed"
+msgstr "Text Scroll Geschwindigkeit des EPG Fensters"
-msgid "Use color gradients"
-msgstr "Farbverläufe verwenden"
+msgid "Display Reruns in detailed EPG View"
+msgstr "Wiederholungen in der detailierten EPG Ansicht anzeigen"
-msgid "Rounded Corners"
-msgstr "Abgerundete Ecken"
+msgid "Number of reruns to display"
+msgstr "Anzahl der dargestellten Wiederholungen"
+
+msgid "Use Subtitle for reruns"
+msgstr "Untertitel für Wiederholungssuche nutzen"
+
+msgid "Display Mode"
+msgstr "Anzeigemodus"
+
+msgid "Height of Channel Header (Perc. of osd height)"
+msgstr "Höhe des Kanalheaders (% der OSD Höhe)"
+
+msgid "Width of Timeline (Perc. of osd width)"
+msgstr "Breite der Zeitleiste (% der OSD Breite)"
+
+msgid "Number of Channels to display"
+msgstr "Anzahl der angezeigten Kanäle"
+
+msgid "Width of Channel Header (Perc. of osd width)"
+msgstr "Breite des Kanalheaders (% der OSD Breite)"
+
+msgid "Height of Timeline (Perc. of osd height)"
+msgstr "Höhe der Zeitleiste (% der OSD Höhe)"
+
+msgid "Display time in EPG Grids"
+msgstr "Zeit in EPG Grids anzeigen"
+
+msgid "Height of Headers (Status Header and EPG View, Perc. of osd height)"
+msgstr "Höhe der Header (Status Header und EPG View, % der OSD Höhe)"
+
+msgid "Height of Footer (Perc. of osd height)"
+msgstr "Höhe des Footers (% der OSD Höhe)"
+
+msgid "Display status header"
+msgstr "Status Header anzeigen"
-msgid "Width of Timeline"
-msgstr "Breite der Zeitleiste"
+msgid "Scale video to upper right corner"
+msgstr "Video in obere rechte Ecke skalieren"
-msgid "Height of Header"
-msgstr "Höhe des Headers"
+msgid "Rounded corners around video frame"
+msgstr "Abgerundete Ecken um Videofenster"
-msgid "Height of Footer"
-msgstr "Höhe des Footers"
+msgid "Display Channel Names in Header"
+msgstr "Kanalnamen im Header anzeigen"
+
+msgid "Display channel groups"
+msgstr "Kanalgruppen anzeigen"
+
+msgid "Height of channel groups (Perc. of osd height)"
+msgstr "Höhe der Kanalgruppen (% der OSD Höhe)"
+
+msgid "Width of channel groups (Perc. of osd width)"
+msgstr "Breite der Kanalgruppen (% der OSD Breite)"
+
+msgid "Display current time baseline"
+msgstr "Linie für aktuelle Uhrzeit anzeigen"
msgid "Show Channel Logos"
msgstr "Kanallogos anzeigen"
@@ -78,17 +681,20 @@ msgstr "Benutzer Pfad für Kanallogos"
msgid "Logo Extension"
msgstr "Logo Extension"
-msgid "Logo width"
-msgstr "Breite der Logos"
+msgid "Logo width ratio"
+msgstr "Logo Breitenverhältnis"
+
+msgid "Logo height ratio"
+msgstr "Logo Höhenverhältnis"
-msgid "Logo height"
-msgstr "Höhe der Logos"
+msgid "Text Border in Detailed View (pixel)"
+msgstr "Rand im detailierten EPG View"
msgid "Show EPG Images"
msgstr "EPG Bilder anzeigen"
msgid "EPG Images Path used"
-msgstr "benutzer EPG Bilder Pfad"
+msgstr "Benutzer EPG Bilder Pfad"
msgid "EPG Image width"
msgstr "Breite der EPG Bilder"
@@ -96,12 +702,45 @@ msgstr "Breite der EPG Bilder"
msgid "EPG Image height"
msgstr "Höhe der EPG Bilder"
+msgid "Number of additional EPG Images"
+msgstr "Anzahl zusätzlicher EPG Bilder"
+
+msgid "Additional EPG Image width"
+msgstr "Breite der zus. EPG Bilder"
+
+msgid "Additional EPG Image height"
+msgstr "Höhe der zus. EPG Bilder"
+
msgid "Font"
msgstr "Schriftart"
+msgid "Status Header Font Size"
+msgstr "Status Header Schriftgröße"
+
+msgid "Status Header Large Font Size"
+msgstr "Status Header große 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 "Button Font Size"
+msgstr "Button Schriftgröße"
+
msgid "Channel Header Font Size"
msgstr "Kanal Header Schriftgröße"
+msgid "Channel Groups Font Size"
+msgstr "Kanalgruppen Schriftgröße"
+
msgid "Grid Font Size"
msgstr "Grid Schriftgröße"
@@ -117,23 +756,186 @@ msgstr "Zeitleiste Datum Schriftgröße"
msgid "Timeline Time Font Size"
msgstr "Zeitleiste Zeit Schriftgröße"
-msgid "Button Font Size"
-msgstr "Button Schriftgröße"
+msgid "Search & Recording Menu Font Size"
+msgstr "Suchen & Aufnehmen Menu Schriftgröße"
-msgid "Detail EPG View Font Size"
-msgstr "Detailierte EPG Ansicht Schriftgröße"
+msgid "Search & Recording Menu Small Font Size"
+msgstr "Suchen & Aufnehmen Menu kleine Schriftgröße"
-msgid "Detail EPG View Header Font Size"
-msgstr "Detailierte EPG Ansicht Header Schriftgröße"
+msgid "Search & Recording Menu Header Font Size"
+msgstr "Suchen & Aufnehmen Menu Header Schriftgröße"
-msgid "Message Font Size"
-msgstr "Nachrichten Schriftgröße"
+msgid "Always use root video folder"
+msgstr "Immer root video Verzeichnis benutzen"
-msgid "Message Large Font Size"
-msgstr "Nachrichten große Schriftgröße"
+msgid "Select from folder list"
+msgstr "Verzeichnis aus Liste auswählen"
+
+msgid "Use fixed folder"
+msgstr "Festes Verzeichnis benutzen"
+
+msgid "Folder for instant Recordings"
+msgstr "Verzeichnis für Sofortaufnahmen"
+
+msgid "Use Remotetimers"
+msgstr "RemoteTimers benutzen"
+
+msgid "Use \"What's on now\" in favorites"
+msgstr "\"Was läuft jetzt\" in Favoriten benutzen"
+
+msgid "Use \"What's on next\" in favorites"
+msgstr "\"Was läuft als nächstes\" in Favoriten benutzen"
+
+msgid "Use user defined time 1 in favorites"
+msgstr "Benutzerdef. Zeit 1 in Favoriten benutzen"
+
+msgid "Description"
+msgstr "Beschreibung"
+
+msgid "Time"
+msgstr "Zeit"
+
+msgid "Use user defined time 2 in favorites"
+msgstr "Benutzerdef. Zeit 2 in Favoriten benutzen"
+
+msgid "Use user defined time 3 in favorites"
+msgstr "Benutzerdef. Zeit 3 in Favoriten benutzen"
+
+msgid "Use user defined time 4 in favorites"
+msgstr "Benutzerdef. Zeit 4 in Favoriten benutzen"
+
+msgid "Limit channels in favorites"
+msgstr "Kanäle in Favoriten beschränken"
+
+msgid "Create Log Messages for image loading"
+msgstr "Log Nachrichten für das Laden der Bilder erzeugen"
+
+msgid "Limit Logo Cache"
+msgstr "Logo Cash beschränken"
+
+msgid "Maximal number of logos to cache"
+msgstr "Maximale Anzahl Logos"
+
+msgid "Number of logos to cache at start"
+msgstr "Anzahl der zu cachenden Logos beim Start"
+
+msgid "Cache Sizes"
+msgstr "Cache Größe"
+
+msgid "OSD Element Cache"
+msgstr "OSD Element Cache"
+
+msgid "Logo cache"
+msgstr "Logo Cache"
+
+msgid "EPG Grid Cache"
+msgstr "EPG Grid Cache"
+
+msgid "Channel Groups Cache"
+msgstr "Kanalgruppen Cache"
+
+msgid "Recording Menus Icon Cache"
+msgstr "Recording Menüs Icon Cache"
+
+msgid "No Cast available"
+msgstr "Keine Besetzung vorhanden"
+
+msgid "Cast"
+msgstr "Besetzung"
+
+msgid "EPG Info"
+msgstr "EPG Info"
+
+msgid "Reruns"
+msgstr "Wiederholungen"
+
+msgid "Recording Information"
+msgstr ""
+
+msgid "Image Galery"
+msgstr "Bildergalerie"
+
+msgid "TheTVDB Info"
+msgstr "TheTVDB Info"
+
+msgid "TheTVDB Information"
+msgstr "TheTVDB Information"
+
+msgid "Episode"
+msgstr "Episode"
+
+msgid "Season"
+msgstr "Staffel"
+
+msgid "Episode Overview"
+msgstr "Episodenüberblick"
+
+msgid "First aired"
+msgstr "Erstausstrahlung"
+
+msgid "Guest Stars"
+msgstr "Gast Stars"
+
+msgid "TheMovieDB Rating"
+msgstr "TheMovieDB Wertung"
+
+msgid "Series Overview"
+msgstr "Serienüberblick"
+
+msgid "Genre"
+msgstr "Genre"
+
+msgid "Network"
+msgstr "Sendeanstalt"
+
+msgid "Status"
+msgstr "Status"
+
+msgid "TheMovieDB Information"
+msgstr "TheMovieDB Information"
+
+msgid "Original Title"
+msgstr "Original Titel"
+
+msgid "Tagline"
+msgstr "Zusammenfassung"
+
+msgid "Overview"
+msgstr "Überblick"
+
+msgid "yes"
+msgstr "Ja"
+
+msgid "no"
+msgstr "Nein"
+
+msgid "Adult"
+msgstr "Nur für Erwachsene"
+
+msgid "Collection"
+msgstr "Kollektion"
+
+msgid "Budget"
+msgstr "Budget"
+
+msgid "Revenue"
+msgstr "Einnahmen"
+
+msgid "Homepage"
+msgstr "Homepage"
+
+msgid "Release Date"
+msgstr "Veröffentlicht"
+
+msgid "Runtime"
+msgstr "Laufzeit"
+
+msgid "minutes"
+msgstr "Minuten"
+
+msgid "TheMovieDB Popularity"
+msgstr "TheMovieDB Popularität"
-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 "TheMovieDB Vote Average"
+msgstr "TheMovieDB durchschnittliche Bewertung"
-msgid "Timer set"
-msgstr "Timer gesetzt"
diff --git a/po/ru_RU.po b/po/ru_RU.po
new file mode 100644
index 0000000..57bfa4d
--- /dev/null
+++ b/po/ru_RU.po
@@ -0,0 +1,955 @@
+# VDR plugin language source file.
+msgid ""
+msgstr ""
+"Project-Id-Version: vdr-tvguide 1.0.0\n"
+"Report-Msgid-Bugs-To: <see README>\n"
+"POT-Creation-Date: 2014-05-10 17:24+0200\n"
+"PO-Revision-Date: 2013-09-25 17:49+0400\n"
+"Last-Translator: AmiD, ilya\n"
+"Language-Team: Russia-Cherepovets(wm.amid at gmail.com)\n"
+"Language: ru\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+msgid "Main Program"
+msgstr "Основная программа"
+
+msgid "Channel"
+msgstr "Канал"
+
+msgid "min"
+msgstr "мин"
+
+msgid "Reruns of "
+msgstr ""
+
+msgid "No reruns found"
+msgstr ""
+
+msgid "No EPG Information available"
+msgstr "Нет доступной EPG информации"
+
+msgid "Search & Rec"
+msgstr "Поиск & Запись"
+
+msgid "Channels back"
+msgstr "Предыдущих каналов"
+
+msgid "Channels forward"
+msgstr "Следующих каналов"
+
+msgid "Switch to Channel"
+msgstr "Переключиться"
+
+msgid "Detailed EPG"
+msgstr "Подробный EPG"
+
+msgid "Close detailed EPG"
+msgstr ""
+
+msgid "Favorites"
+msgstr ""
+
+msgid "images"
+msgstr ""
+
+msgid "root video folder"
+msgstr "Главная видео директория"
+
+msgid "Transp."
+msgstr "Трансп."
+
+msgid "Timer Conflict"
+msgstr "Таймер-конфликт"
+
+msgid "all Channels"
+msgstr "все каналы"
+
+msgid "unknown channel"
+msgstr "неизвестный канал"
+
+msgid "Duration"
+msgstr "Продолжительность"
+
+msgid "recorded at"
+msgstr "записано"
+
+msgid "from"
+msgstr "от"
+
+msgid "Timers for"
+msgstr ""
+
+msgid "Rec"
+msgstr ""
+
+msgid "No Timers active"
+msgstr ""
+
+msgid "inactive"
+msgstr ""
+
+msgid "active timers"
+msgstr ""
+
+msgid "recordings done"
+msgstr ""
+
+msgid "What's on now"
+msgstr ""
+
+msgid "What's on next"
+msgstr ""
+
+msgid "Instant Record"
+msgstr "Записать"
+
+msgid "Delete Timer"
+msgstr "Удалить таймер"
+
+msgid "Edit Timer"
+msgstr "Редактировать таймер"
+
+msgid "Timer Timeline"
+msgstr ""
+
+msgid "Create Search Timer"
+msgstr "Создать поисковый таймер"
+
+msgid "Search Timers"
+msgstr ""
+
+msgid "Create Series Timer"
+msgstr "Создать циклический таймер"
+
+msgid "Create Switch Timer"
+msgstr "Создать таймер переключения"
+
+msgid "Delete Switch Timer"
+msgstr "Удалить таймер переключения"
+
+msgid "Search"
+msgstr "Поиск"
+
+msgid "Check for Timer Conflicts"
+msgstr "Поиск таймер-конфликтов"
+
+msgid "Search in Recordings"
+msgstr "Искать в записях"
+
+msgid "Set Folder for"
+msgstr "Укажите каталог для"
+
+msgid "Timer created"
+msgstr "Таймер создан"
+
+msgid "Timer NOT created"
+msgstr "Таймер НЕ создан"
+
+msgid "OK"
+msgstr "OK"
+
+msgid "Timer deleted"
+msgstr "Таймер удален"
+
+msgid "Timer"
+msgstr "Таймер"
+
+msgid "still recording - really delete?"
+msgstr "Идет запись - уверены что хотите удалить?"
+
+msgid "Yes"
+msgstr "Да"
+
+msgid "No"
+msgstr "Нет"
+
+msgid "One"
+msgstr "Один"
+
+msgid "detected"
+msgstr "обнаружен"
+
+msgid "Timer Conflicts"
+msgstr "Таймер-конфликты"
+
+msgid "Show conflict"
+msgstr "Показать конфликты"
+
+msgid "timers involved"
+msgstr "Таймер"
+
+msgid "Ignore Conflicts"
+msgstr "Игнорировать конфликты"
+
+msgid "Ignore Conflict"
+msgstr "Игнорировать конфликт"
+
+msgid "No Timer Conflicts found"
+msgstr "Таймер-конфликты не найдены"
+
+msgid "Close"
+msgstr "Закрыть"
+
+msgid "reruns for"
+msgstr ""
+
+msgid "rerun for"
+msgstr ""
+
+msgid "found"
+msgstr ""
+
+msgid "Ignore reruns"
+msgstr ""
+
+msgid "No reruns found for Event"
+msgstr ""
+
+msgid "Timer for"
+msgstr ""
+
+msgid "replaced by rerun"
+msgstr ""
+
+msgid "Timer Active"
+msgstr "Таймер активен"
+
+msgid "Priority"
+msgstr "Приоритет"
+
+msgid "Lifetime"
+msgstr "Срок хранения (дней)"
+
+msgid "Day"
+msgstr "День"
+
+msgid "Timer start time"
+msgstr "Время c"
+
+msgid "Timer stop time"
+msgstr "Время до"
+
+msgid "Timer File"
+msgstr ""
+
+msgid "New Folder"
+msgstr ""
+
+msgid "Save"
+msgstr "Сохранить"
+
+msgid "Cancel"
+msgstr "Отменить"
+
+msgid "Create Series Timer based on"
+msgstr "Настроить циклический таймер"
+
+msgid "Series Timer start time"
+msgstr "Время с"
+
+msgid "Series Timer stop time"
+msgstr "Время до"
+
+msgid "Days to record"
+msgstr "Дни недели"
+
+msgid "Day to start"
+msgstr "Начиная с"
+
+msgid "Create Timer"
+msgstr "Создать"
+
+msgid "Series Timer created"
+msgstr "Циклический таймер создан"
+
+msgid "Start"
+msgstr "Старт"
+
+msgid "Stop"
+msgstr "Стоп"
+
+msgid "Configure Search Timer based on"
+msgstr "Настроить поисковый таймер"
+
+msgid "Search Expression:"
+msgstr "Искать выражение:"
+
+msgid "Continue"
+msgstr "Продолжить"
+
+msgid "Configure Search Timer for Search String"
+msgstr "Настройка таймера поиска по ключевым словам"
+
+msgid "Manually configure Options"
+msgstr "Ручная настройка параметров"
+
+msgid "Use Template"
+msgstr "Использовать шаблоны"
+
+msgid "EPGSearch Search Timers"
+msgstr ""
+
+msgid "No Search Timers Configured"
+msgstr ""
+
+msgid "Configure Search Timer Options"
+msgstr ""
+
+msgid "Save Search Timer"
+msgstr ""
+
+msgid "Search String"
+msgstr ""
+
+msgid "Active"
+msgstr ""
+
+msgid "Search Mode"
+msgstr "Режим поиска"
+
+msgid "Use Title"
+msgstr "Искать в названиях"
+
+msgid "Use Subtitle"
+msgstr "Искать в эпизодах"
+
+msgid "Use Description"
+msgstr "Искать в описаниях"
+
+msgid "Limit Channels"
+msgstr "Ограничить список каналов"
+
+msgid "Use Time"
+msgstr "Время"
+
+msgid "Display advanced Options"
+msgstr ""
+
+msgid "Limit Days of the Week"
+msgstr ""
+
+msgid "Time margin for start in minutes"
+msgstr ""
+
+msgid "Time margin for stop in minutes"
+msgstr ""
+
+msgid "Series Recording"
+msgstr ""
+
+msgid "Folder"
+msgstr ""
+
+msgid "Use VPS"
+msgstr ""
+
+msgid "Avoid Repeats"
+msgstr ""
+
+msgid "Use in Favorites"
+msgstr ""
+
+msgid "Hide advanced Options"
+msgstr ""
+
+msgid "Display Results for Search Timer"
+msgstr "Тест"
+
+msgid "Start Channel"
+msgstr "С канала"
+
+msgid "Stop Channel"
+msgstr "По канал"
+
+msgid "Start after"
+msgstr "С"
+
+msgid "Start before"
+msgstr "До"
+
+msgid "Select Days"
+msgstr ""
+
+msgid "Number of allowed repeats"
+msgstr ""
+
+msgid "Compare Title"
+msgstr ""
+
+msgid "Compare Subtitle"
+msgstr ""
+
+msgid "Compare Description"
+msgstr ""
+
+msgid "Really delete Search Timer"
+msgstr ""
+
+msgid "Delete only Search Timer"
+msgstr ""
+
+msgid "Delete Search Timer and created Timers"
+msgstr ""
+
+msgid "Search Timer sucessfully created."
+msgstr "Поисковый таймер создан"
+
+msgid "Search Timer update initialised"
+msgstr "Поисковый таймер обновляется"
+
+msgid "Search Timer NOT sucessfully created"
+msgstr "Поисковый таймер НЕ создан"
+
+msgid "Creating Search Timer"
+msgstr "Создается поисковый таймер"
+
+msgid "Search Term"
+msgstr "Ключевое слово"
+
+msgid "Using Template"
+msgstr "Использовать шаблон"
+
+msgid "Use other Template"
+msgstr "Использовать другие шаблоны"
+
+msgid "search results for Favorite"
+msgstr ""
+
+msgid "search result for Favorite"
+msgstr ""
+
+msgid "search results for Search Timer"
+msgstr "Совпадений найдено"
+
+msgid "search result for Search Timer"
+msgstr "Совпадение найдено"
+
+msgid "Nothing found for Search String"
+msgstr "Совпадений НЕ найдено"
+
+msgid "Configure Options for Switchtimer"
+msgstr "Настройка таймера переключения"
+
+msgid "Minutes before switching"
+msgstr "Минут до события"
+
+msgid "switch"
+msgstr "Переключить"
+
+msgid "announce only"
+msgstr "Только предупредить"
+
+msgid "ask for switch"
+msgstr "Спросить о переключении"
+
+msgid "Switch Mode"
+msgstr "Режим переключения"
+
+msgid "Create"
+msgstr "Создать"
+
+msgid "Switch Timer sucessfully created"
+msgstr "Таймер переключения создан"
+
+msgid "Switch Timer NOT sucessfully created"
+msgstr "Таймер переключения НЕ был создан!"
+
+msgid "Switch Timer deleted"
+msgstr "Таймер переключения удален"
+
+msgid "Channel to Search"
+msgstr "Канал для поиска"
+
+msgid "Search in title"
+msgstr "Искать в названиях"
+
+msgid "Search in Subtitle"
+msgstr "Искать в эпизодах"
+
+msgid "Search in Description"
+msgstr "Искать в описаниях"
+
+msgid "Show Search Options"
+msgstr "Показать параметры поиска"
+
+msgid "Perform Search"
+msgstr "Найти"
+
+msgid "search results for"
+msgstr "Найдено по запросу"
+
+msgid "search result for"
+msgstr "Найден по запросу"
+
+msgid "Adapt Search"
+msgstr "Изменить"
+
+msgid "Search String has to have at least three letters"
+msgstr ""
+
+msgid "Found"
+msgstr "Найдено"
+
+msgid "recording"
+msgstr "запись"
+
+msgid "recordings"
+msgstr "записей"
+
+msgid "for"
+msgstr "для"
+
+msgid "No recordings found for"
+msgstr "Не найдено записей:"
+
+msgid "No Favorites available"
+msgstr ""
+
+msgid "whole term must appear"
+msgstr "фраза"
+
+msgid "all terms must exist"
+msgstr "все слова"
+
+msgid "one term must exist"
+msgstr "хотя бы одно слово"
+
+msgid "exact match"
+msgstr "точное совпадение"
+
+msgid "regular expression"
+msgstr "регулярные выражения"
+
+msgid "General Settings"
+msgstr "Основные настройки"
+
+msgid "Screen Presentation"
+msgstr "Графические настройки"
+
+msgid "Fonts and Fontsizes"
+msgstr "Шрифты и размер шрифтов"
+
+msgid "Recording Menus and Favorites"
+msgstr ""
+
+msgid "Image Loading and Caching"
+msgstr ""
+
+msgid "x channels back / forward"
+msgstr "x Каналов Назад/Вперед"
+
+msgid "previous / next channel group"
+msgstr "Предыдущая/Следующая группа"
+
+msgid "Blue: Channel Switch, Ok: Detailed EPG"
+msgstr "Синяя: Переключить канал, OK: Подробный EPG"
+
+msgid "Blue: Detailed EPG, Ok: Channel Switch"
+msgstr "Синяя: Подробный EPG, OK: Переключить канал"
+
+msgid "Blue: Favorites / Switch, Ok: Detailed EPG"
+msgstr ""
+
+msgid "Timely Jump"
+msgstr ""
+
+msgid "Jump to specific channel"
+msgstr ""
+
+msgid "never"
+msgstr "никогда"
+
+msgid "if exists"
+msgstr "если существует"
+
+msgid "always"
+msgstr "всегда"
+
+msgid "Show Main Menu Entry"
+msgstr "Показывать пункт в главном меню"
+
+msgid "Replace VDR Schedules Menu"
+msgstr "Заменять телегид VDR"
+
+msgid "Use appropriate nOpacity Theme"
+msgstr ""
+
+msgid "Theme"
+msgstr "Тема"
+
+msgid "Time to display in minutes"
+msgstr "Время показа в минутах"
+
+msgid "Rounded Corners"
+msgstr "Закруглять углы"
+
+msgid "Channel Jump Mode (Keys Green / Yellow)"
+msgstr "Режим прокрутки каналов (Зеленая/Желтая кнопки)"
+
+msgid "Keys Blue and OK"
+msgstr "Синяя кнопка и OK"
+
+msgid "Close TVGuide after channel switch"
+msgstr "Закрывать TVGuide при переключении канала"
+
+msgid "Functionality of numeric Keys"
+msgstr ""
+
+msgid "Hide last Channel Group"
+msgstr "Скрывать последнюю группу каналов"
+
+msgid "Big Step (Keys 1 / 3) in hours"
+msgstr "Прыжок (Кнопки 1 / 3) в часах"
+
+msgid "Huge Step (Keys 4 / 6) in hours"
+msgstr "Большой прыжок (Кнопки 4 / 6) в часах"
+
+msgid "Time Format (12h/24h)"
+msgstr "Формат времени (12h/24h)"
+
+msgid "EPG Window Text Scrolling Speed"
+msgstr ""
+
+msgid "Display Reruns in detailed EPG View"
+msgstr "Показывать повторы в подробном EPG"
+
+msgid "Number of reruns to display"
+msgstr "Кол-во"
+
+msgid "Use Subtitle for reruns"
+msgstr "Показывать эпизод"
+
+msgid "Display Mode"
+msgstr "Режим отображения"
+
+msgid "Height of Channel Header (Perc. of osd height)"
+msgstr "Высота заголовка канала (% от высоты OSD)"
+
+msgid "Width of Timeline (Perc. of osd width)"
+msgstr "Ширина таймлинии (% от ширины OSD)"
+
+msgid "Number of Channels to display"
+msgstr "Кол-во отображаемых каналов"
+
+msgid "Width of Channel Header (Perc. of osd width)"
+msgstr "Ширина заголовка канала (% от ширины OSD)"
+
+msgid "Height of Timeline (Perc. of osd height)"
+msgstr "Высота таймлинии (% от высоты OSD)"
+
+msgid "Display time in EPG Grids"
+msgstr "Показывать время в сетке EPG"
+
+msgid "Height of Headers (Status Header and EPG View, Perc. of osd height)"
+msgstr ""
+
+msgid "Height of Footer (Perc. of osd height)"
+msgstr ""
+
+msgid "Display status header"
+msgstr "Показывать верхнюю панель"
+
+msgid "Scale video to upper right corner"
+msgstr "Показывать видео в правом верхнем углу"
+
+msgid "Rounded corners around video frame"
+msgstr "Скруглять углы видео рамки"
+
+msgid "Display Channel Names in Header"
+msgstr "Показывать наименования каналов в верхней панели"
+
+msgid "Display channel groups"
+msgstr "Показывать группы каналов"
+
+msgid "Height of channel groups (Perc. of osd height)"
+msgstr "Высота группы каналов (% от высоты OSD)"
+
+msgid "Width of channel groups (Perc. of osd width)"
+msgstr "Ширина группы каналов (% от ширины OSD)"
+
+msgid "Display current time baseline"
+msgstr ""
+
+msgid "Show Channel Logos"
+msgstr "Показывать логотипы каналов"
+
+msgid "Logo Path used"
+msgstr "Путь к папке с логотипами"
+
+msgid "Logo Extension"
+msgstr "Расширения файлов с логотипами"
+
+msgid "Logo width ratio"
+msgstr "Ширина логотипов"
+
+msgid "Logo height ratio"
+msgstr "Высота логотипов"
+
+msgid "Text Border in Detailed View (pixel)"
+msgstr ""
+
+msgid "Show EPG Images"
+msgstr "Показывать картинки EPG"
+
+msgid "EPG Images Path used"
+msgstr "Путь к папке с картинками EPG"
+
+msgid "EPG Image width"
+msgstr "Ширина картирок EPG (пикселей)"
+
+msgid "EPG Image height"
+msgstr "Высота картинок EPG (пикселей)"
+
+msgid "Number of additional EPG Images"
+msgstr "Кол-во дополнительных EPG картинок"
+
+msgid "Additional EPG Image width"
+msgstr "Ширина дополнительных EPG картинок"
+
+msgid "Additional EPG Image height"
+msgstr "Высота дополнительных EPG картинок"
+
+msgid "Font"
+msgstr "Шрифт"
+
+msgid "Status Header Font Size"
+msgstr "Размер шрифта в верхней панели"
+
+msgid "Status Header Large Font Size"
+msgstr "Размер крупного шрифта в верхней панели"
+
+msgid "Detail EPG View Font Size"
+msgstr "Размер шрифта подробный EPG"
+
+msgid "Detail EPG View Header Font Size"
+msgstr "Размер шрифта верхней панели меню подробный EPG"
+
+msgid "Message Font Size"
+msgstr "Размер шрифта сообщений"
+
+msgid "Message Large Font Size"
+msgstr "Размер крупного шрифта сообщений"
+
+msgid "Button Font Size"
+msgstr "Размер шрифта кнопок"
+
+msgid "Channel Header Font Size"
+msgstr "Размер шрифта названий каналов"
+
+msgid "Channel Groups Font Size"
+msgstr "Размер шрифта групп каналов"
+
+msgid "Grid Font Size"
+msgstr "Размер шрифта сетки"
+
+msgid "Grid Font Small Size"
+msgstr "Размер маленького шрифта сетки"
+
+msgid "Timeline Weekday Font Size"
+msgstr "Размер шрифта таймлинии"
+
+msgid "Timeline Date Font Size"
+msgstr "Размер шрифта даты таймлинии"
+
+msgid "Timeline Time Font Size"
+msgstr "Размер шрифта времени таймлинии"
+
+msgid "Search & Recording Menu Font Size"
+msgstr "Размер шрифта меню Поиск & Запись"
+
+msgid "Search & Recording Menu Small Font Size"
+msgstr "Размер маленького шрифта меню Поиск & Запись"
+
+msgid "Search & Recording Menu Header Font Size"
+msgstr ""
+
+msgid "Always use root video folder"
+msgstr ""
+
+msgid "Select from folder list"
+msgstr ""
+
+msgid "Use fixed folder"
+msgstr ""
+
+msgid "Folder for instant Recordings"
+msgstr ""
+
+msgid "Use Remotetimers"
+msgstr "RemoteTimers benutzen"
+
+msgid "Use \"What's on now\" in favorites"
+msgstr ""
+
+msgid "Use \"What's on next\" in favorites"
+msgstr ""
+
+msgid "Use user defined time 1 in favorites"
+msgstr ""
+
+msgid "Description"
+msgstr ""
+
+msgid "Time"
+msgstr ""
+
+msgid "Use user defined time 2 in favorites"
+msgstr ""
+
+msgid "Use user defined time 3 in favorites"
+msgstr ""
+
+msgid "Use user defined time 4 in favorites"
+msgstr ""
+
+msgid "Limit channels in favorites"
+msgstr ""
+
+msgid "Create Log Messages for image loading"
+msgstr ""
+
+msgid "Limit Logo Cache"
+msgstr ""
+
+msgid "Maximal number of logos to cache"
+msgstr ""
+
+msgid "Number of logos to cache at start"
+msgstr ""
+
+msgid "Cache Sizes"
+msgstr ""
+
+msgid "OSD Element Cache"
+msgstr ""
+
+msgid "Logo cache"
+msgstr ""
+
+msgid "EPG Grid Cache"
+msgstr ""
+
+msgid "Channel Groups Cache"
+msgstr ""
+
+msgid "Recording Menus Icon Cache"
+msgstr ""
+
+msgid "No Cast available"
+msgstr ""
+
+msgid "Cast"
+msgstr ""
+
+msgid "EPG Info"
+msgstr ""
+
+msgid "Reruns"
+msgstr ""
+
+msgid "Recording Information"
+msgstr ""
+
+msgid "Image Galery"
+msgstr ""
+
+msgid "TheTVDB Info"
+msgstr ""
+
+msgid "TheTVDB Information"
+msgstr ""
+
+msgid "Episode"
+msgstr ""
+
+msgid "Season"
+msgstr ""
+
+msgid "Episode Overview"
+msgstr ""
+
+msgid "First aired"
+msgstr ""
+
+msgid "Guest Stars"
+msgstr ""
+
+msgid "TheMovieDB Rating"
+msgstr ""
+
+msgid "Series Overview"
+msgstr ""
+
+msgid "Genre"
+msgstr ""
+
+msgid "Network"
+msgstr ""
+
+msgid "Status"
+msgstr ""
+
+msgid "TheMovieDB Information"
+msgstr ""
+
+msgid "Original Title"
+msgstr ""
+
+msgid "Tagline"
+msgstr ""
+
+msgid "Overview"
+msgstr ""
+
+msgid "yes"
+msgstr ""
+
+msgid "no"
+msgstr ""
+
+msgid "Adult"
+msgstr ""
+
+msgid "Collection"
+msgstr ""
+
+msgid "Budget"
+msgstr ""
+
+msgid "Revenue"
+msgstr ""
+
+msgid "Homepage"
+msgstr ""
+
+msgid "Release Date"
+msgstr ""
+
+msgid "Runtime"
+msgstr ""
+
+msgid "minutes"
+msgstr ""
+
+msgid "TheMovieDB Popularity"
+msgstr ""
+
+msgid "TheMovieDB Vote Average"
+msgstr ""
+
+#~ msgid "RERUNS OF THIS SHOW"
+#~ msgstr "ПОВТОРЫ ЭТОЙ ПЕРЕДАЧИ"
+
+#~ msgid "Actors"
+#~ msgstr "Актеры"
+
+#~ msgid "Use folders for instant records"
+#~ msgstr "Использовать директории для быстрой записи"
+
+#~ msgid "Height of status header (Perc. of osd height)"
+#~ msgstr "Высота верхней панели (% от высоты OSD)"
+
+#~ msgid "Configure Search Timer Options for Search String"
+#~ msgstr "Настроить параметры таймера"
diff --git a/po/sk_SK.po b/po/sk_SK.po
new file mode 100644
index 0000000..27cb5f8
--- /dev/null
+++ b/po/sk_SK.po
@@ -0,0 +1,955 @@
+# VDR plugin language source file.
+msgid ""
+msgstr ""
+"Project-Id-Version: vdr-tvguide 1.1.0\n"
+"Report-Msgid-Bugs-To: <see README>\n"
+"POT-Creation-Date: 2014-05-10 17:24+0200\n"
+"PO-Revision-Date: 2013-09-15 00:12+0100\n"
+"Last-Translator: Milan Hrala <hrala.milan at gmail.com>\n"
+"Language-Team: \n"
+"Language: sk\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=iso-8859-2\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+msgid "Main Program"
+msgstr "Hlavn� program"
+
+msgid "Channel"
+msgstr "Kan�l"
+
+msgid "min"
+msgstr "min"
+
+msgid "Reruns of "
+msgstr ""
+
+msgid "No reruns found"
+msgstr ""
+
+msgid "No EPG Information available"
+msgstr "�iadne EPG �daje nie s� k dispoz�cii"
+
+msgid "Search & Rec"
+msgstr "Hlada� & Nahra�"
+
+msgid "Channels back"
+msgstr "kan�lov sp�"
+
+msgid "Channels forward"
+msgstr "kan�lov dopredu"
+
+msgid "Switch to Channel"
+msgstr "Prepn�� na kan�l"
+
+msgid "Detailed EPG"
+msgstr "Podrobn� EPG"
+
+msgid "Close detailed EPG"
+msgstr ""
+
+msgid "Favorites"
+msgstr ""
+
+msgid "images"
+msgstr ""
+
+msgid "root video folder"
+msgstr "Hlavn� video adres�r"
+
+msgid "Transp."
+msgstr "Transp."
+
+msgid "Timer Conflict"
+msgstr "Konflikt pl�nu"
+
+msgid "all Channels"
+msgstr "v�etky kan�ly"
+
+msgid "unknown channel"
+msgstr "nezn�my Kanal"
+
+msgid "Duration"
+msgstr "D�ka"
+
+msgid "recorded at"
+msgstr "Zaznamenan�"
+
+msgid "from"
+msgstr "z"
+
+msgid "Timers for"
+msgstr ""
+
+msgid "Rec"
+msgstr ""
+
+msgid "No Timers active"
+msgstr ""
+
+msgid "inactive"
+msgstr ""
+
+msgid "active timers"
+msgstr ""
+
+msgid "recordings done"
+msgstr ""
+
+msgid "What's on now"
+msgstr ""
+
+msgid "What's on next"
+msgstr ""
+
+msgid "Instant Record"
+msgstr "Okam�ite nahra�"
+
+msgid "Delete Timer"
+msgstr "Vymaza� pl�n nahr�vania"
+
+msgid "Edit Timer"
+msgstr "Upravi� pl�n nahr�vania"
+
+msgid "Timer Timeline"
+msgstr ""
+
+msgid "Create Search Timer"
+msgstr "Vytvori� vyh�ad�va� pl�nov nahr�vania"
+
+msgid "Search Timers"
+msgstr ""
+
+msgid "Create Series Timer"
+msgstr "Vytvori� s�riov� pl�n nahr�vania"
+
+msgid "Create Switch Timer"
+msgstr "Vytvori� prep�nac� pl�n"
+
+msgid "Delete Switch Timer"
+msgstr "Vymaza� prep�nac� pl�n"
+
+msgid "Search"
+msgstr "H�ada�"
+
+msgid "Check for Timer Conflicts"
+msgstr "Skontrolova� konflikty pl�nu"
+
+msgid "Search in Recordings"
+msgstr "Vyh�ada� v nahr�vkach"
+
+msgid "Set Folder for"
+msgstr "Nastavi� adres�r pre"
+
+msgid "Timer created"
+msgstr "Pl�n vytvoren�"
+
+msgid "Timer NOT created"
+msgstr "Pl�n nie je vytvoren�"
+
+msgid "OK"
+msgstr "OK"
+
+msgid "Timer deleted"
+msgstr "Pl�n vymazan�"
+
+msgid "Timer"
+msgstr "Pl�n"
+
+msgid "still recording - really delete?"
+msgstr "Pr�ve nahr�va - naozaj zmaza�?"
+
+msgid "Yes"
+msgstr "�no"
+
+msgid "No"
+msgstr "Nie"
+
+msgid "One"
+msgstr "Jeden"
+
+msgid "detected"
+msgstr "n�jden�ch"
+
+msgid "Timer Conflicts"
+msgstr "Konflikty pl�nov"
+
+msgid "Show conflict"
+msgstr "Zobrazi� konflikt"
+
+msgid "timers involved"
+msgstr "pl�ny komplikovan�"
+
+msgid "Ignore Conflicts"
+msgstr "Ignorova� konflikty"
+
+msgid "Ignore Conflict"
+msgstr "Ignorova� konflikt"
+
+msgid "No Timer Conflicts found"
+msgstr "Nena�li sa �iadne konflikty pl�nu"
+
+msgid "Close"
+msgstr "Zavrie�"
+
+msgid "reruns for"
+msgstr ""
+
+msgid "rerun for"
+msgstr ""
+
+msgid "found"
+msgstr ""
+
+msgid "Ignore reruns"
+msgstr ""
+
+msgid "No reruns found for Event"
+msgstr ""
+
+msgid "Timer for"
+msgstr ""
+
+msgid "replaced by rerun"
+msgstr ""
+
+msgid "Timer Active"
+msgstr "Pl�n akt�vny"
+
+msgid "Priority"
+msgstr "Priorita"
+
+msgid "Lifetime"
+msgstr "�ivotnos�"
+
+msgid "Day"
+msgstr "De�"
+
+msgid "Timer start time"
+msgstr "Pl�n za��na"
+
+msgid "Timer stop time"
+msgstr "Pl�n kon��"
+
+msgid "Timer File"
+msgstr ""
+
+msgid "New Folder"
+msgstr ""
+
+msgid "Save"
+msgstr "Ulo�i�"
+
+msgid "Cancel"
+msgstr "Zru�i�"
+
+msgid "Create Series Timer based on"
+msgstr "Vytvorenie pl�nu na z�klade s�rie"
+
+msgid "Series Timer start time"
+msgstr "S�riov� pl�n za��na"
+
+msgid "Series Timer stop time"
+msgstr "S�riov� pl�n kon��"
+
+msgid "Days to record"
+msgstr "Dni"
+
+msgid "Day to start"
+msgstr "Za��na d�a"
+
+msgid "Create Timer"
+msgstr "Vytvori� pl�n"
+
+msgid "Series Timer created"
+msgstr "Vytvoren� s�riov� pl�n"
+
+msgid "Start"
+msgstr "�tart"
+
+msgid "Stop"
+msgstr "Stop"
+
+msgid "Configure Search Timer based on"
+msgstr "Vyh�ad�vanie pl�nu nastavi� na z�klade"
+
+msgid "Search Expression:"
+msgstr "H�adan� v�raz:"
+
+msgid "Continue"
+msgstr "�al�ie"
+
+msgid "Configure Search Timer for Search String"
+msgstr "Konfigur�cia vyh�ad�vania pl�nu pre h�adan� k���ov� slovo "
+
+msgid "Manually configure Options"
+msgstr "Ru�ne konfigurova� mo�nosti"
+
+msgid "Use Template"
+msgstr "pou�itie �abl�ny"
+
+msgid "EPGSearch Search Timers"
+msgstr ""
+
+msgid "No Search Timers Configured"
+msgstr ""
+
+msgid "Configure Search Timer Options"
+msgstr ""
+
+msgid "Save Search Timer"
+msgstr ""
+
+msgid "Search String"
+msgstr ""
+
+msgid "Active"
+msgstr ""
+
+msgid "Search Mode"
+msgstr "Re�im vyh�ad�vania"
+
+msgid "Use Title"
+msgstr "Pou�i� n�zov"
+
+msgid "Use Subtitle"
+msgstr "Pou�i� titulky"
+
+msgid "Use Description"
+msgstr "Pou�i� popis"
+
+msgid "Limit Channels"
+msgstr "Obmedzi� kan�ly"
+
+msgid "Use Time"
+msgstr "Pou�i� �as"
+
+msgid "Display advanced Options"
+msgstr ""
+
+msgid "Limit Days of the Week"
+msgstr ""
+
+msgid "Time margin for start in minutes"
+msgstr ""
+
+msgid "Time margin for stop in minutes"
+msgstr ""
+
+msgid "Series Recording"
+msgstr ""
+
+msgid "Folder"
+msgstr ""
+
+msgid "Use VPS"
+msgstr ""
+
+msgid "Avoid Repeats"
+msgstr ""
+
+msgid "Use in Favorites"
+msgstr ""
+
+msgid "Hide advanced Options"
+msgstr ""
+
+msgid "Display Results for Search Timer"
+msgstr "Pozrie� v�sledky pre vyh�ad�vanie pl�nov"
+
+msgid "Start Channel"
+msgstr "Od kan�lu"
+
+msgid "Stop Channel"
+msgstr "Po kan�l"
+
+msgid "Start after"
+msgstr "Za�iatok po"
+
+msgid "Start before"
+msgstr "Za�iatok pred"
+
+msgid "Select Days"
+msgstr ""
+
+msgid "Number of allowed repeats"
+msgstr ""
+
+msgid "Compare Title"
+msgstr ""
+
+msgid "Compare Subtitle"
+msgstr ""
+
+msgid "Compare Description"
+msgstr ""
+
+msgid "Really delete Search Timer"
+msgstr ""
+
+msgid "Delete only Search Timer"
+msgstr ""
+
+msgid "Delete Search Timer and created Timers"
+msgstr ""
+
+msgid "Search Timer sucessfully created."
+msgstr "Vyh�ad�va� pl�nu vytvoren�."
+
+msgid "Search Timer update initialised"
+msgstr "Vyhlad�va� pl�nu inicializovan�"
+
+msgid "Search Timer NOT sucessfully created"
+msgstr "Vyh�ad�va� pl�nu nie je kompletne vytvoren�"
+
+msgid "Creating Search Timer"
+msgstr "Vytvorenie vyh�ad�vacieho pl�nu"
+
+msgid "Search Term"
+msgstr "k���ov� slovo"
+
+msgid "Using Template"
+msgstr "�abl�na"
+
+msgid "Use other Template"
+msgstr "Pou�i� in� �abl�nu"
+
+msgid "search results for Favorite"
+msgstr ""
+
+msgid "search result for Favorite"
+msgstr ""
+
+msgid "search results for Search Timer"
+msgstr "n�jden� v�sledky vyh�ad�vania pl�nu"
+
+msgid "search result for Search Timer"
+msgstr "n�jden� v�sledok vyh�ad�vania pl�nu"
+
+msgid "Nothing found for Search String"
+msgstr "H�adan� v�raz sa nena�iel"
+
+msgid "Configure Options for Switchtimer"
+msgstr "Konfigurova� mo�nosti pre prep�nac� pl�n"
+
+msgid "Minutes before switching"
+msgstr "Min�ty pred prepnut�m"
+
+msgid "switch"
+msgstr "Prepn��"
+
+msgid "announce only"
+msgstr "iba ozn�mi�"
+
+msgid "ask for switch"
+msgstr "op�ta� sa na prepnutie"
+
+msgid "Switch Mode"
+msgstr "Prep�nac� re�im"
+
+msgid "Create"
+msgstr "Vytvori�"
+
+msgid "Switch Timer sucessfully created"
+msgstr "Prepnutie je napl�novan�"
+
+msgid "Switch Timer NOT sucessfully created"
+msgstr "Pl�n prepnutia nie je vytvoren�"
+
+msgid "Switch Timer deleted"
+msgstr "Pl�n prepnutia vymazan�"
+
+msgid "Channel to Search"
+msgstr "H�ada� na kan�le"
+
+msgid "Search in title"
+msgstr "H�ada� v n�zve"
+
+msgid "Search in Subtitle"
+msgstr "H�ada� v titulk�ch"
+
+msgid "Search in Description"
+msgstr "H�ada� v popise"
+
+msgid "Show Search Options"
+msgstr "Zobrazi� mo�nosti vyh�ad�vania"
+
+msgid "Perform Search"
+msgstr "Vykona� vyh�ad�vanie"
+
+msgid "search results for"
+msgstr "vyh�adan� v�sledky pre"
+
+msgid "search result for"
+msgstr "vyh�adan� v�sledok pre"
+
+msgid "Adapt Search"
+msgstr "Prisp�sobi� vyh�ad�vanie"
+
+msgid "Search String has to have at least three letters"
+msgstr ""
+
+msgid "Found"
+msgstr "N�jden�"
+
+msgid "recording"
+msgstr "nahr�vka"
+
+msgid "recordings"
+msgstr "nahr�vky"
+
+msgid "for"
+msgstr "pre"
+
+msgid "No recordings found for"
+msgstr "Nena�li sa nahr�vky s n�zvom "
+
+msgid "No Favorites available"
+msgstr ""
+
+msgid "whole term must appear"
+msgstr "kompletn� v�raz"
+
+msgid "all terms must exist"
+msgstr "v�etky slov�"
+
+msgid "one term must exist"
+msgstr "jeden pojem mus� existova�"
+
+msgid "exact match"
+msgstr "presn� zhoda"
+
+msgid "regular expression"
+msgstr "regul�rny v�raz"
+
+msgid "General Settings"
+msgstr "V�eobecn� nastavenia"
+
+msgid "Screen Presentation"
+msgstr "Mo�nosti zobrazenia"
+
+msgid "Fonts and Fontsizes"
+msgstr "P�sma a ve�kosti p�sma"
+
+msgid "Recording Menus and Favorites"
+msgstr ""
+
+msgid "Image Loading and Caching"
+msgstr ""
+
+msgid "x channels back / forward"
+msgstr "x kan�lov sp� / vpred"
+
+msgid "previous / next channel group"
+msgstr "Predch�dzaj�ce / �al�ie skupiny kan�lov"
+
+msgid "Blue: Channel Switch, Ok: Detailed EPG"
+msgstr "Modr�: Prepn�� kan�l, OK: Podrobn� EPG"
+
+msgid "Blue: Detailed EPG, Ok: Channel Switch"
+msgstr "Modr�: podrobn� EPG, OK: prepn�� kan�l"
+
+msgid "Blue: Favorites / Switch, Ok: Detailed EPG"
+msgstr ""
+
+msgid "Timely Jump"
+msgstr ""
+
+msgid "Jump to specific channel"
+msgstr ""
+
+msgid "never"
+msgstr "nikdy"
+
+msgid "if exists"
+msgstr "ak s� k dispoz�cii"
+
+msgid "always"
+msgstr "v�dy"
+
+msgid "Show Main Menu Entry"
+msgstr "Zobrazi� v hlavnom menu"
+
+msgid "Replace VDR Schedules Menu"
+msgstr "Zameni� VDR menu (tv program)"
+
+msgid "Use appropriate nOpacity Theme"
+msgstr ""
+
+msgid "Theme"
+msgstr "T�ma"
+
+msgid "Time to display in minutes"
+msgstr "Zobrazen� �as v min�tach"
+
+msgid "Rounded Corners"
+msgstr "Zaoblen� rohy"
+
+msgid "Channel Jump Mode (Keys Green / Yellow)"
+msgstr "Re��m skoku kan�la (kl�vesy zelen� / �lt�)"
+
+msgid "Keys Blue and OK"
+msgstr "Tla�idl� modr� a OK"
+
+msgid "Close TVGuide after channel switch"
+msgstr "Zavrie� TVGuide po prepnut� kan�lu"
+
+msgid "Functionality of numeric Keys"
+msgstr ""
+
+msgid "Hide last Channel Group"
+msgstr "Skry� posledn� skupinu kan�lov"
+
+msgid "Big Step (Keys 1 / 3) in hours"
+msgstr "Ve�k� skoky (tla�idl� 1 / 3) v hodin�ch"
+
+msgid "Huge Step (Keys 4 / 6) in hours"
+msgstr "Ve�mi ve�k� skoky (tla�idl� 4 / 6) v hodin�ch"
+
+msgid "Time Format (12h/24h)"
+msgstr "Form�t �asu (12h/24h)"
+
+msgid "EPG Window Text Scrolling Speed"
+msgstr ""
+
+msgid "Display Reruns in detailed EPG View"
+msgstr "Repr�zy v podrobnom zobrazen� rel�cie EPG"
+
+msgid "Number of reruns to display"
+msgstr "Po�et zobrazovan�ch repr�z"
+
+msgid "Use Subtitle for reruns"
+msgstr "Titulky pre vyh�adanie repr�z"
+
+msgid "Display Mode"
+msgstr "Re��m zobrazenia"
+
+msgid "Height of Channel Header (Perc. of osd height)"
+msgstr "V��ka hlavi�ky kan�lov (% z OSD v��ky)"
+
+msgid "Width of Timeline (Perc. of osd width)"
+msgstr "��rka �asovej osi (% z OSD v��ky)"
+
+msgid "Number of Channels to display"
+msgstr "Po�et zobrazen�ch kan�lov"
+
+msgid "Width of Channel Header (Perc. of osd width)"
+msgstr "��rka hlavi�ky kan�lov (% z OSD ��rky)"
+
+msgid "Height of Timeline (Perc. of osd height)"
+msgstr "V��ka �asovej osi (% z OSD v��ky)"
+
+msgid "Display time in EPG Grids"
+msgstr "Zobrazi� �as v EPG mrie�ke"
+
+msgid "Height of Headers (Status Header and EPG View, Perc. of osd height)"
+msgstr ""
+
+msgid "Height of Footer (Perc. of osd height)"
+msgstr ""
+
+msgid "Display status header"
+msgstr "Zobrazi� stavov� hlavi�ku"
+
+msgid "Scale video to upper right corner"
+msgstr "�k�lovateln� video v pravom hornom rohu"
+
+msgid "Rounded corners around video frame"
+msgstr "Zaoblen� rohy do okna videa"
+
+msgid "Display Channel Names in Header"
+msgstr "Zobrazi� men� kan�lu v hlavi�ke"
+
+msgid "Display channel groups"
+msgstr "Zobrazi� skupiny kan�lov"
+
+msgid "Height of channel groups (Perc. of osd height)"
+msgstr "V��ka skupiny kan�la (% z OSD v��ky)"
+
+msgid "Width of channel groups (Perc. of osd width)"
+msgstr "��rka skupiny kan�la (% z OSD ��rky)"
+
+msgid "Display current time baseline"
+msgstr ""
+
+msgid "Show Channel Logos"
+msgstr "Zobrazi� log� kan�lov"
+
+msgid "Logo Path used"
+msgstr "Umiestnenie pou�it�ho loga"
+
+msgid "Logo Extension"
+msgstr "Logo pr�pona"
+
+msgid "Logo width ratio"
+msgstr "��rka loga"
+
+msgid "Logo height ratio"
+msgstr "V��ka loga"
+
+msgid "Text Border in Detailed View (pixel)"
+msgstr ""
+
+msgid "Show EPG Images"
+msgstr "Zobrazi� EPG obr�zky"
+
+msgid "EPG Images Path used"
+msgstr "Umiestnenie EPG obr�zkov"
+
+msgid "EPG Image width"
+msgstr "��rka EPG obr�zku"
+
+msgid "EPG Image height"
+msgstr "V��ka EPG obr�zku"
+
+msgid "Number of additional EPG Images"
+msgstr "Po�et �al��ch EPG obr�zkov"
+
+msgid "Additional EPG Image width"
+msgstr "��rka �al��ch EPG obr�zkov"
+
+msgid "Additional EPG Image height"
+msgstr "V��ka �al��ch EPG obr�zkov"
+
+msgid "Font"
+msgstr "P�smo"
+
+msgid "Status Header Font Size"
+msgstr "Ve�kos� p�sma stavovej hlavi�ky"
+
+msgid "Status Header Large Font Size"
+msgstr "Ve�kos� ve�k�ho p�sma stavovej hlavi�ky"
+
+msgid "Detail EPG View Font Size"
+msgstr "Ve�kos� p�sma v detailnom EPG poh�ade"
+
+msgid "Detail EPG View Header Font Size"
+msgstr "Ve�kos� p�sma hlavi�ky v detailnom EPG poh�ade"
+
+msgid "Message Font Size"
+msgstr "Ve�kos� p�sma spr�vy"
+
+msgid "Message Large Font Size"
+msgstr "Ve�kos� ve�k�ho p�sma spr�vy"
+
+msgid "Button Font Size"
+msgstr "Ve�kos� p�sma tla�idla"
+
+msgid "Channel Header Font Size"
+msgstr "Ve�kos� p�sma hlavi�ky kan�la"
+
+msgid "Channel Groups Font Size"
+msgstr "Ve�kos� p�sma skup�n kan�lu"
+
+msgid "Grid Font Size"
+msgstr "Ve�kos� p�sma mrie�ky"
+
+msgid "Grid Font Small Size"
+msgstr "Ve�kos� mal�ho p�sma mrie�ky"
+
+msgid "Timeline Weekday Font Size"
+msgstr "Ve�kos� p�sma d�a �asovej osi"
+
+msgid "Timeline Date Font Size"
+msgstr "Ve�kos� p�sma d�tumu �asovej osi"
+
+msgid "Timeline Time Font Size"
+msgstr "Ve�kos� p�sma hod�n �asovej osi"
+
+msgid "Search & Recording Menu Font Size"
+msgstr "H�ada� & Nahra� menu p�smo"
+
+msgid "Search & Recording Menu Small Font Size"
+msgstr "H�ada� & Nahra� menu mal� p�smo"
+
+msgid "Search & Recording Menu Header Font Size"
+msgstr ""
+
+msgid "Always use root video folder"
+msgstr ""
+
+msgid "Select from folder list"
+msgstr ""
+
+msgid "Use fixed folder"
+msgstr ""
+
+msgid "Folder for instant Recordings"
+msgstr ""
+
+msgid "Use Remotetimers"
+msgstr "Pou�i� vzdialen� pl�nova�"
+
+msgid "Use \"What's on now\" in favorites"
+msgstr ""
+
+msgid "Use \"What's on next\" in favorites"
+msgstr ""
+
+msgid "Use user defined time 1 in favorites"
+msgstr ""
+
+msgid "Description"
+msgstr ""
+
+msgid "Time"
+msgstr ""
+
+msgid "Use user defined time 2 in favorites"
+msgstr ""
+
+msgid "Use user defined time 3 in favorites"
+msgstr ""
+
+msgid "Use user defined time 4 in favorites"
+msgstr ""
+
+msgid "Limit channels in favorites"
+msgstr ""
+
+msgid "Create Log Messages for image loading"
+msgstr ""
+
+msgid "Limit Logo Cache"
+msgstr ""
+
+msgid "Maximal number of logos to cache"
+msgstr ""
+
+msgid "Number of logos to cache at start"
+msgstr ""
+
+msgid "Cache Sizes"
+msgstr ""
+
+msgid "OSD Element Cache"
+msgstr ""
+
+msgid "Logo cache"
+msgstr ""
+
+msgid "EPG Grid Cache"
+msgstr ""
+
+msgid "Channel Groups Cache"
+msgstr ""
+
+msgid "Recording Menus Icon Cache"
+msgstr ""
+
+msgid "No Cast available"
+msgstr ""
+
+msgid "Cast"
+msgstr ""
+
+msgid "EPG Info"
+msgstr ""
+
+msgid "Reruns"
+msgstr ""
+
+msgid "Recording Information"
+msgstr ""
+
+msgid "Image Galery"
+msgstr ""
+
+msgid "TheTVDB Info"
+msgstr ""
+
+msgid "TheTVDB Information"
+msgstr ""
+
+msgid "Episode"
+msgstr ""
+
+msgid "Season"
+msgstr ""
+
+msgid "Episode Overview"
+msgstr ""
+
+msgid "First aired"
+msgstr ""
+
+msgid "Guest Stars"
+msgstr ""
+
+msgid "TheMovieDB Rating"
+msgstr ""
+
+msgid "Series Overview"
+msgstr ""
+
+msgid "Genre"
+msgstr ""
+
+msgid "Network"
+msgstr ""
+
+msgid "Status"
+msgstr ""
+
+msgid "TheMovieDB Information"
+msgstr ""
+
+msgid "Original Title"
+msgstr ""
+
+msgid "Tagline"
+msgstr ""
+
+msgid "Overview"
+msgstr ""
+
+msgid "yes"
+msgstr ""
+
+msgid "no"
+msgstr ""
+
+msgid "Adult"
+msgstr ""
+
+msgid "Collection"
+msgstr ""
+
+msgid "Budget"
+msgstr ""
+
+msgid "Revenue"
+msgstr ""
+
+msgid "Homepage"
+msgstr ""
+
+msgid "Release Date"
+msgstr ""
+
+msgid "Runtime"
+msgstr ""
+
+msgid "minutes"
+msgstr ""
+
+msgid "TheMovieDB Popularity"
+msgstr ""
+
+msgid "TheMovieDB Vote Average"
+msgstr ""
+
+#~ msgid "RERUNS OF THIS SHOW"
+#~ msgstr "Repr�za tohto programu"
+
+#~ msgid "Actors"
+#~ msgstr "Herci"
+
+#~ msgid "Use folders for instant records"
+#~ msgstr "Pou�i� adres�re pre okam�it� nahr�vky"
+
+#~ msgid "Height of status header (Perc. of osd height)"
+#~ msgstr "V��ka stavovej hlavi�ky (% z OSD v��ky)"
+
+#~ msgid "Configure Search Timer Options for Search String"
+#~ msgstr "Konfigurova� mo�nosti pl�nov pre vyh�ad�vanie k���ov�ch slov"
diff --git a/recmanager.c b/recmanager.c
new file mode 100644
index 0000000..7ad6f4c
--- /dev/null
+++ b/recmanager.c
@@ -0,0 +1,714 @@
+#define __STL_CONFIG_H
+
+#include <string>
+#include <sstream>
+#include <vector>
+#include <algorithm>
+
+#include <vdr/menu.h>
+#include "services/remotetimers.h"
+#include "tools.h"
+#include "switchtimer.h"
+#include "timerconflict.h"
+#include "recmanager.h"
+
+static int CompareRecording(const void *p1, const void *p2) {
+ return (int)((*(cRecording **)p1)->Start() - (*(cRecording **)p2)->Start());
+}
+
+cRecManager::cRecManager(void) {
+ epgSearchPlugin = NULL;
+ epgSearchAvailable = false;
+}
+
+cRecManager::~cRecManager(void) {
+}
+
+void cRecManager::SetEPGSearchPlugin(void) {
+ epgSearchPlugin = cPluginManager::GetPlugin("epgsearch");
+ if (epgSearchPlugin) {
+ epgSearchAvailable = true;
+ }
+}
+
+bool cRecManager::RefreshRemoteTimers(void) {
+ cString errorMsg;
+ if (!pRemoteTimers->Service("RemoteTimers::RefreshTimers-v1.0", &errorMsg)) {
+ esyslog("tvguide: %s", *errorMsg);
+ return false;
+ }
+ return true;
+}
+
+bool cRecManager::CheckEventForTimer(const cEvent *event) {
+ bool hasTimer = false;
+
+ if (tvguideConfig.useRemoteTimers && pRemoteTimers) {
+ RemoteTimers_GetMatch_v1_0 rtMatch;
+ rtMatch.event = event;
+ pRemoteTimers->Service("RemoteTimers::GetMatch-v1.0", &rtMatch);
+ if (rtMatch.timerMatch == tmFull)
+ hasTimer = true;
+ } else
+ hasTimer = event->HasTimer();
+
+ return hasTimer;
+}
+
+cTimer *cRecManager::GetTimerForEvent(const cEvent *event) {
+ cTimer *timer = NULL;
+ if (tvguideConfig.useRemoteTimers && pRemoteTimers) {
+ RemoteTimers_GetMatch_v1_0 rtMatch;
+ rtMatch.event = event;
+ pRemoteTimers->Service("RemoteTimers::GetMatch-v1.0", &rtMatch);
+ timer = rtMatch.timer;
+ } else
+ timer = Timers.GetMatch(event);
+ return timer;
+}
+
+cTimer *cRecManager::createTimer(const cEvent *event, std::string path) {
+ cTimer *timer = NULL;
+ if (tvguideConfig.useRemoteTimers && pRemoteTimers) {
+ timer = createRemoteTimer(event, path);
+ } else {
+ timer = createLocalTimer(event, path);
+ }
+ return timer;
+}
+
+cTimer *cRecManager::createLocalTimer(const cEvent *event, std::string path) {
+ cTimer *timer = new cTimer(event);
+ cTimer *t = Timers.GetTimer(timer);
+ if (t) {
+ t->OnOff();
+ t->SetEventFromSchedule();
+ delete timer;
+ timer = t;
+ isyslog("timer %s reactivated", *t->ToDescr());
+ } else {
+ Timers.Add(timer);
+ isyslog("timer %s added (active)", *timer->ToDescr());
+ }
+ SetTimerPath(timer, event, path);
+ Timers.SetModified();
+ return timer;
+}
+
+cTimer *cRecManager::createRemoteTimer(const cEvent *event, std::string path) {
+ cTimer *t = new cTimer(event);
+ SetTimerPath(t, event, path);
+ RemoteTimers_Timer_v1_0 rt;
+ rt.timer = t;
+ pRemoteTimers->Service("RemoteTimers::GetTimer-v1.0", &rt.timer);
+ if (rt.timer) {
+ rt.timer->OnOff();
+ if (!pRemoteTimers->Service("RemoteTimers::ModTimer-v1.0", &rt))
+ rt.timer = NULL;
+ } else {
+ rt.timer = t;
+ if (!pRemoteTimers->Service("RemoteTimers::NewTimer-v1.0", &rt))
+ isyslog("%s", *rt.errorMsg);
+ }
+ RefreshRemoteTimers();
+ return rt.timer;
+}
+
+void cRecManager::SetTimerPath(cTimer *timer, const cEvent *event, std::string path) {
+ if (tvguideConfig.instRecFolderMode == eFolderFixed) {
+ Epgsearch_services_v1_2 *epgSearch = new Epgsearch_services_v1_2;
+ std::string recDir = tvguideConfig.instRecFixedFolder;
+ std::replace(recDir.begin(), recDir.end(), '/', '~');
+ if (strchr(recDir.c_str(), '%') != NULL) {
+ if (epgSearchPlugin->Service("Epgsearch-services-v1.1", epgSearch)) {
+ std::string newFileName = epgSearch->handler->Evaluate(recDir, event);
+ if (strchr(newFileName.c_str(), '%') == NULL) // only set directory to new value if all categories could have been replaced
+ timer->SetFile(newFileName.c_str());
+ else
+ esyslog("tvguide: timer path not set because replacing variable was not successfull: %s", newFileName.c_str());
+ }
+ } else {
+ cString newFileName;
+ if (recDir.size() > 0) {
+ newFileName = cString::sprintf("%s~%s", recDir.c_str(), timer->File());
+ timer->SetFile(*newFileName);
+ }
+ }
+ return;
+ }
+ //Set choosen path
+ cString newFileName;
+ if (path.size() > 0) {
+ std::replace(path.begin(), path.end(), '/', '~');
+ newFileName = cString::sprintf("%s~%s", path.c_str(), timer->File());
+ } else {
+ newFileName = event->Title();
+ }
+ timer->SetFile(*newFileName);
+}
+
+void cRecManager::DeleteTimer(int timerID) {
+ cTimer *t = Timers.Get(timerID);
+ if (!t)
+ return;
+ DeleteTimer(t);
+}
+
+void cRecManager::DeleteTimer(const cEvent *event) {
+ if (!event)
+ return;
+ if (tvguideConfig.useRemoteTimers && pRemoteTimers) {
+ DeleteRemoteTimer(event);
+ } else {
+ DeleteLocalTimer(event);
+ }
+}
+
+void cRecManager::DeleteLocalTimer(const cEvent *event) {
+ cTimer *t = Timers.GetMatch(event);
+ if (!t)
+ return;
+ DeleteTimer(t);
+}
+
+
+void cRecManager::DeleteTimer(cTimer *timer) {
+ if (timer->Recording()) {
+ timer->Skip();
+ cRecordControls::Process(time(NULL));
+ }
+ isyslog("timer %s deleted", *timer->ToDescr());
+ Timers.Del(timer, true);
+ Timers.SetModified();
+}
+
+void cRecManager::DeleteRemoteTimer(const cEvent *event) {
+ RemoteTimers_GetMatch_v1_0 rtMatch;
+ rtMatch.event = event;
+ pRemoteTimers->Service("RemoteTimers::GetMatch-v1.0", &rtMatch);
+ if (rtMatch.timer) {
+ RemoteTimers_Timer_v1_0 rt;
+ rt.timer = rtMatch.timer;
+ isyslog("remotetimer %s deleted", *rt.timer->ToDescr());
+ if (!pRemoteTimers->Service("RemoteTimers::DelTimer-v1.0", &rt))
+ isyslog("remotetimer error");
+ RefreshRemoteTimers();
+ }
+}
+
+void cRecManager::SaveTimer(cTimer *timer, cTimer newTimerSettings) {
+ if (!timer)
+ return;
+
+ bool active = newTimerSettings.HasFlags(tfActive);
+ int prio = newTimerSettings.Priority();
+ int lifetime = newTimerSettings.Lifetime();
+ time_t day = newTimerSettings.Day();
+ int start = newTimerSettings.Start();
+ int stop = newTimerSettings.Stop();
+ std::string fileName = newTimerSettings.File();
+
+ timer->SetDay(day);
+ timer->SetStart(start);
+ timer->SetStop(stop);
+ timer->SetPriority(prio);
+ timer->SetLifetime(lifetime);
+ timer->SetFile(fileName.c_str());
+
+ if (timer->HasFlags(tfActive) && !active)
+ timer->ClrFlags(tfActive);
+ else if (!timer->HasFlags(tfActive) && active)
+ timer->SetFlags(tfActive);
+
+ timer->SetEventFromSchedule();
+ if (tvguideConfig.useRemoteTimers && pRemoteTimers) {
+ RemoteTimers_Timer_v1_0 rt;
+ rt.timer = timer;
+ if (!pRemoteTimers->Service("RemoteTimers::ModTimer-v1.0", &rt))
+ rt.timer = NULL;
+ RefreshRemoteTimers();
+ } else {
+ Timers.SetModified();
+ }
+}
+
+
+bool cRecManager::IsRecorded(const cEvent *event) {
+ cTimer *timer = Timers.GetMatch(event);
+ if (!timer)
+ return false;
+ return timer->Recording();
+}
+
+cTVGuideTimerConflicts *cRecManager::CheckTimerConflict(void) {
+ cTVGuideTimerConflicts *conflictList = new cTVGuideTimerConflicts();
+ if (!epgSearchAvailable)
+ return conflictList;
+ Epgsearch_services_v1_1 *epgSearch = new Epgsearch_services_v1_1;
+ if (epgSearchPlugin->Service("Epgsearch-services-v1.1", epgSearch)) {
+ std::list<std::string> conflicts = epgSearch->handler->TimerConflictList();
+ int numConflicts = conflicts.size();
+ if (numConflicts == 0)
+ return conflictList;
+ for (std::list<std::string>::iterator it=conflicts.begin(); it != conflicts.end(); ++it) {
+ conflictList->AddConflict(*it);
+ }
+ }
+ delete epgSearch;
+ conflictList->CalculateConflicts();
+ return conflictList;
+}
+
+void cRecManager::CreateSeriesTimer(cTimer *seriesTimer) {
+ seriesTimer->SetEventFromSchedule();
+ if (tvguideConfig.useRemoteTimers && pRemoteTimers) {
+ RemoteTimers_Timer_v1_0 rt;
+ rt.timer = seriesTimer;
+ if (!pRemoteTimers->Service("RemoteTimers::NewTimer-v1.0", &rt))
+ isyslog("%s", *rt.errorMsg);
+ RefreshRemoteTimers();
+ } else {
+ Timers.Add(seriesTimer);
+ Timers.SetModified();
+ }
+}
+
+
+void cRecManager::ReadEPGSearchTemplates(std::vector<TVGuideEPGSearchTemplate> *epgTemplates) {
+ cString ConfigDir = cPlugin::ConfigDirectory("epgsearch");
+ cString epgsearchConf = "epgsearchtemplates.conf";
+ cString fileName = AddDirectory(*ConfigDir, *epgsearchConf);
+ if (access(fileName, F_OK) == 0) {
+ FILE *f = fopen(fileName, "r");
+ if (f) {
+ char *s;
+ cReadLine ReadLine;
+ while ((s = ReadLine.Read(f)) != NULL) {
+ char *p = strchr(s, '#');
+ if (p)
+ *p = 0;
+ stripspace(s);
+ try {
+ if (!isempty(s)) {
+ std::string templ = s;
+ int posID = templ.find_first_of(":");
+ int posName = templ.find_first_of(":", posID+1);
+ std::string name = templ.substr(posID+1, posName - posID - 1);
+ std::string templValue = templ.substr(posName);
+ TVGuideEPGSearchTemplate tmp;
+ tmp.name = name;
+ tmp.templValue = templValue;
+ epgTemplates->push_back(tmp);
+ }
+ } catch (...){}
+ }
+ }
+ }
+}
+
+const cEvent **cRecManager::PerformSearchTimerSearch(std::string epgSearchString, int &numResults) {
+ if (!epgSearchAvailable)
+ return NULL;
+ const cEvent **searchResults = NULL;
+ Epgsearch_services_v1_1 *epgSearch = new Epgsearch_services_v1_1;
+ if (epgSearchPlugin->Service("Epgsearch-services-v1.1", epgSearch)) {
+ std::list<std::string> results = epgSearch->handler->QuerySearch(epgSearchString);
+ numResults = results.size();
+ if (numResults > 0) {
+ searchResults = new const cEvent *[numResults];
+ cSchedulesLock schedulesLock;
+ const cSchedules *schedules;
+ schedules = cSchedules::Schedules(schedulesLock);
+ const cEvent *event = NULL;
+ int index=0;
+ for (std::list<std::string>::iterator it=results.begin(); it != results.end(); ++it) {
+ try {
+ splitstring s(it->c_str());
+ std::vector<std::string> flds = s.split(':', 1);
+ int eventID = atoi(flds[1].c_str());
+ std::string channelID = flds[7];
+ tChannelID chanID = tChannelID::FromString(channelID.c_str());
+ cChannel *channel = Channels.GetByChannelID(chanID);
+ if (channel) {
+ const cSchedule *Schedule = NULL;
+ Schedule = schedules->GetSchedule(channel);
+ event = Schedule->GetEvent(eventID);
+ if (event) {
+ searchResults[index] = event;
+ } else
+ return NULL;
+ } else
+ return NULL;
+ index++;
+ } catch (...){}
+ }
+ }
+ }
+ return searchResults;
+}
+
+const cEvent **cRecManager::PerformSearch(Epgsearch_searchresults_v1_0 data, int &numResults) {
+ if (epgSearchAvailable) {
+ if (epgSearchPlugin->Service("Epgsearch-searchresults-v1.0", &data)) {
+ cList<Epgsearch_searchresults_v1_0::cServiceSearchResult> *list = data.pResultList;
+ if (!list)
+ return NULL;
+ int numElements = list->Count();
+ const cEvent **searchResults = NULL;
+ if (numElements > 0) {
+ searchResults = new const cEvent *[numElements];
+ numResults = numElements;
+ int index = 0;
+ for (Epgsearch_searchresults_v1_0::cServiceSearchResult *r = list->First(); r ; r = list->Next(r)) {
+ searchResults[index] = r->event;
+ index++;
+ }
+ }
+ delete list;
+ return searchResults;
+ }
+ }
+ return NULL;
+}
+
+void cRecManager::GetSearchTimers(std::vector<cTVGuideSearchTimer> *searchTimer) {
+ if (!epgSearchAvailable) {
+ return;
+ }
+ Epgsearch_services_v1_1 *epgSearch = new Epgsearch_services_v1_1;
+ if (epgSearchPlugin->Service("Epgsearch-services-v1.1", epgSearch)) {
+ std::list<std::string> searchTimerList;
+ searchTimerList = epgSearch->handler->SearchTimerList();
+ for(std::list<std::string>::iterator it = searchTimerList.begin(); it != searchTimerList.end(); it++) {
+ cTVGuideSearchTimer timer;
+ timer.SetEPGSearchString(it->c_str());
+ if (timer.Parse())
+ searchTimer->push_back(timer);
+ }
+ }
+ std::sort(searchTimer->begin(), searchTimer->end());
+}
+
+int cRecManager::CreateSearchTimer(std::string epgSearchString) {
+ int timerID = -1;
+ if (!epgSearchAvailable)
+ return timerID;
+ Epgsearch_services_v1_1 *epgSearch = new Epgsearch_services_v1_1;
+ if (epgSearchPlugin->Service("Epgsearch-services-v1.1", epgSearch)) {
+ timerID = epgSearch->handler->AddSearchTimer(epgSearchString);
+ }
+ return timerID;
+}
+
+bool cRecManager::SaveSearchTimer(cTVGuideSearchTimer *searchTimer) {
+ if (!epgSearchAvailable)
+ return false;
+ Epgsearch_services_v1_1 *epgSearch = new Epgsearch_services_v1_1;
+ if (searchTimer->GetID() > -1) {
+ if (epgSearchPlugin->Service("Epgsearch-services-v1.1", epgSearch)) {
+ bool success = epgSearch->handler->ModSearchTimer(searchTimer->BuildSearchString());
+ if (success) {
+ esyslog("tvguide: search timer with id %d sucessfully modified", searchTimer->GetID());
+ return true;
+ } else {
+ esyslog("tvguide: error modifying search timer with id %d, build string %s", searchTimer->GetID(), searchTimer->BuildSearchString().c_str());
+ return false;
+ }
+ }
+ } else {
+ if (epgSearchPlugin->Service("Epgsearch-services-v1.1", epgSearch)) {
+ int timerID = epgSearch->handler->AddSearchTimer(searchTimer->BuildSearchString());
+ if (timerID >=0) {
+ esyslog("tvguide: search timer with id %d sucessfully created", timerID);
+ return true;
+ } else {
+ esyslog("tvguide: error creating search timer, build string %s", searchTimer->BuildSearchString().c_str());
+ return false;
+ }
+ }
+ }
+ return false;
+}
+
+void cRecManager::DeleteSearchTimer(cTVGuideSearchTimer *searchTimer, bool delTimers) {
+ if (!epgSearchAvailable)
+ return;
+ int searchTimerID = searchTimer->GetID();
+ if (delTimers) {
+ cTimer *timer = Timers.First();
+ while(timer) {
+ if (!timer->Recording()) {
+ char* searchID = GetAuxValue(timer, "s-id");
+ if (searchID) {
+ if (searchTimerID == atoi(searchID)) {
+ cTimer* timerNext = Timers.Next(timer);
+ DeleteTimer(timer);
+ timer = timerNext;
+ } else {
+ timer = Timers.Next(timer);
+ }
+ free(searchID);
+ } else {
+ timer = Timers.Next(timer);
+ }
+ } else {
+ timer = Timers.Next(timer);
+ }
+ }
+ }
+ Epgsearch_services_v1_1 *epgSearch = new Epgsearch_services_v1_1;
+ if (epgSearchPlugin->Service("Epgsearch-services-v1.1", epgSearch)) {
+ bool success = epgSearch->handler->DelSearchTimer(searchTimerID);
+ if (success) {
+ esyslog("tvguide: search timer \"%s\" sucessfully deleted", searchTimer->SearchString().c_str());
+ } else {
+ esyslog("tvguide: error deleting search timer \"%s\"", searchTimer->SearchString().c_str());
+ }
+ }
+}
+
+void cRecManager::UpdateSearchTimers(void) {
+ if (epgSearchAvailable) {
+ Epgsearch_updatesearchtimers_v1_0 data;
+ data.showMessage = false;
+ epgSearchPlugin->Service("Epgsearch-updatesearchtimers-v1.0", &data);
+ }
+}
+
+// announceOnly: 0 = switch, 1 = announce only, 2 = ask for switch
+bool cRecManager::CreateSwitchTimer(const cEvent *event, cSwitchTimer switchTimer) {
+ if (epgSearchAvailable && event) {
+ Epgsearch_switchtimer_v1_0 data;
+ data.event = event;
+ data.mode = 1;
+ data.switchMinsBefore = switchTimer.switchMinsBefore;
+ data.announceOnly = switchTimer.announceOnly;
+ data.success = false;
+ epgSearchPlugin->Service("Epgsearch-switchtimer-v1.0", &data);
+ cSwitchTimer *t = new cSwitchTimer(event);
+ SwitchTimers.Add(t);
+ return data.success;
+ }
+ return false;
+}
+
+void cRecManager::DeleteSwitchTimer(const cEvent *event) {
+ SwitchTimers.DeleteSwitchTimer(event);
+ if (epgSearchAvailable) {
+ Epgsearch_switchtimer_v1_0 data;
+ data.event = event;
+ data.mode = 2;
+ data.switchMinsBefore = 0;
+ data.announceOnly = 0;
+ data.success = false;
+ epgSearchPlugin->Service("Epgsearch-switchtimer-v1.0", &data);
+ }
+}
+
+cRecording **cRecManager::SearchForRecordings(std::string searchString, int &numResults) {
+
+ cRecording **matchingRecordings = NULL;
+ int num = 0;
+ numResults = 0;
+
+ for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording)) {
+ std::string s1 = recording->Name();
+ std::string s2 = searchString;
+ if (s1.empty() || s2.empty()) continue;
+
+ // tolerance for fuzzy searching: 90% of the shorter text length, but at least 1
+ int tolerance = std::max(1, (int)std::min(s1.size(), s2.size()) / 10);
+
+ bool match = FindIgnoreCase(s1, s2) >= 0 || FindIgnoreCase(s2, s1) >= 0;
+
+ if (!match) {
+ AFUZZY af = { NULL, NULL, NULL, NULL, NULL, NULL, { 0 }, { 0 }, 0, 0, 0, 0, 0, 0 };
+ if (s1.size() > 32) s1 = s1.substr(0, 32);
+ afuzzy_init(s1.c_str(), tolerance, 0, &af);
+ /* Checking substring */
+ int res = afuzzy_checkSUB(s2.c_str(), &af);
+ afuzzy_free(&af);
+ match = (res > 0);
+ }
+
+ if (!match) {
+ AFUZZY af = { NULL, NULL, NULL, NULL, NULL, NULL, { 0 }, { 0 }, 0, 0, 0, 0, 0, 0 };
+ if (s2.size() > 32) s2 = s2.substr(0, 32);
+ afuzzy_init(s2.c_str(), tolerance, 0, &af);
+ /* Checking substring */
+ int res = afuzzy_checkSUB(s1.c_str(), &af);
+ afuzzy_free(&af);
+ match = (res > 0);
+ }
+
+ if (match) {
+ matchingRecordings = (cRecording **)realloc(matchingRecordings, (num + 1) * sizeof(cRecording *));
+ matchingRecordings[num++] = recording;
+ }
+ }
+ if (num > 0) {
+ qsort(matchingRecordings, num, sizeof(cRecording *), CompareRecording);
+ numResults = num;
+ return matchingRecordings;
+ }
+ return NULL;
+}
+
+const cEvent **cRecManager::LoadReruns(const cEvent *event, int &numResults) {
+ if (epgSearchAvailable && !isempty(event->Title())) {
+ Epgsearch_searchresults_v1_0 data;
+ std::string strQuery = event->Title();
+ if (tvguideConfig.useSubtitleRerun > 0) {
+ if (tvguideConfig.useSubtitleRerun == 2 || !isempty(event->ShortText()))
+ strQuery += "~";
+ if (!isempty(event->ShortText()))
+ strQuery += event->ShortText();
+ data.useSubTitle = true;
+ } else {
+ data.useSubTitle = false;
+ }
+ data.query = (char *)strQuery.c_str();
+ data.mode = 0;
+ data.channelNr = 0;
+ data.useTitle = true;
+ data.useDescription = false;
+
+ if (epgSearchPlugin->Service("Epgsearch-searchresults-v1.0", &data)) {
+ cList<Epgsearch_searchresults_v1_0::cServiceSearchResult>* list = data.pResultList;
+ if (!list)
+ return NULL;
+ const cEvent **searchResults = NULL;
+ int numElements = list->Count();
+ if (numElements > 0) {
+ searchResults = new const cEvent *[numElements];
+ int index = 0;
+ for (Epgsearch_searchresults_v1_0::cServiceSearchResult *r = list->First(); r; r = list->Next(r)) {
+ if ((event->ChannelID() == r->event->ChannelID()) && (event->StartTime() == r->event->StartTime()))
+ continue;
+ searchResults[index] = r->event;
+ index++;
+ }
+ delete list;
+ numResults = index;
+ return searchResults;
+ }
+ }
+ }
+ return NULL;
+}
+
+void cRecManager::GetFavorites(std::vector<cTVGuideSearchTimer> *favorites) {
+ if (!epgSearchAvailable) {
+ return;
+ }
+ Epgsearch_services_v1_1 *epgSearch = new Epgsearch_services_v1_1;
+ if (epgSearchPlugin->Service("Epgsearch-services-v1.1", epgSearch)) {
+ std::list<std::string> searchTimerList;
+ searchTimerList = epgSearch->handler->SearchTimerList();
+ for(std::list<std::string>::iterator it = searchTimerList.begin(); it != searchTimerList.end(); it++) {
+ cTVGuideSearchTimer timer;
+ timer.SetEPGSearchString(it->c_str());
+ if (timer.Parse()) {
+ if (timer.UseInFavorites())
+ favorites->push_back(timer);
+ }
+ }
+ }
+
+}
+
+const cEvent **cRecManager::WhatsOnNow(bool nowOrNext, int &numResults) {
+ std::vector<const cEvent*> tmpResults;
+ cSchedulesLock schedulesLock;
+ const cSchedules *schedules = cSchedules::Schedules(schedulesLock);
+ const cChannel *startChannel = NULL, *stopChannel = NULL;
+ if (tvguideConfig.favLimitChannels) {
+ startChannel = Channels.GetByNumber(tvguideConfig.favStartChannel);
+ stopChannel = Channels.GetByNumber(tvguideConfig.favStopChannel);
+ }
+ if (!startChannel)
+ startChannel = Channels.First();
+
+ for (const cChannel *channel = startChannel; channel; channel = Channels.Next(channel)) {
+ if (channel->GroupSep()) continue;
+ const cSchedule *Schedule = schedules->GetSchedule(channel);
+ if (!Schedule) continue;
+
+ const cEvent *event = NULL;
+ if (nowOrNext)
+ event = Schedule->GetPresentEvent();
+ else
+ event = Schedule->GetFollowingEvent();
+ if (event) {
+ tmpResults.push_back(event);
+ }
+ if (stopChannel && (stopChannel->Number() <= channel->Number()))
+ break;
+ }
+ numResults = tmpResults.size();
+ const cEvent **results = new const cEvent *[numResults];
+ for (int i=0; i<numResults; i++) {
+ results[i] = tmpResults[i];
+ }
+
+ return results;
+}
+
+const cEvent **cRecManager::UserDefinedTime(int userTime, int &numResults) {
+ std::vector<const cEvent*> tmpResults;
+ int favTime = 0;
+ if (userTime == 1) {
+ favTime = tvguideConfig.favTime1;
+ } else if (userTime == 2) {
+ favTime = tvguideConfig.favTime2;
+ } else if (userTime == 3) {
+ favTime = tvguideConfig.favTime3;
+ } else if (userTime == 4) {
+ favTime = tvguideConfig.favTime4;
+ }
+
+ time_t now = time(0);
+ tm *midn = localtime(&now);
+ midn->tm_sec = 0;
+ midn->tm_min = 0;
+ midn->tm_hour = 0;
+ time_t midnight = mktime(midn);
+ int hours = favTime/100;
+ int mins = favTime - hours * 100;
+ time_t searchTime = midnight + hours*60*60 + mins*60;
+ if (searchTime < now)
+ searchTime += 24*60*60;
+
+ cSchedulesLock schedulesLock;
+ const cSchedules *schedules = cSchedules::Schedules(schedulesLock);
+ const cChannel *startChannel = NULL, *stopChannel = NULL;
+ if (tvguideConfig.favLimitChannels) {
+ startChannel = Channels.GetByNumber(tvguideConfig.favStartChannel);
+ stopChannel = Channels.GetByNumber(tvguideConfig.favStopChannel);
+ }
+ if (!startChannel)
+ startChannel = Channels.First();
+
+ for (const cChannel *channel = startChannel; channel; channel = Channels.Next(channel)) {
+ if (channel->GroupSep()) continue;
+ const cSchedule *Schedule = schedules->GetSchedule(channel);
+ if (!Schedule) continue;
+ const cEvent *event = Schedule->GetEventAround(searchTime);
+ if (!event) continue;
+ //if event is more or less over (only 15mns left), take next
+ if ((event->EndTime() - searchTime) < 15*60) {
+ event = Schedule->Events()->Next(event);
+ }
+ if (event)
+ tmpResults.push_back(event);
+ if (stopChannel && (stopChannel->Number() <= channel->Number()))
+ break;
+ }
+
+ numResults = tmpResults.size();
+ const cEvent **results = new const cEvent *[numResults];
+ for (int i=0; i<numResults; i++) {
+ results[i] = tmpResults[i];
+ }
+ return results;
+}
diff --git a/recmanager.h b/recmanager.h
new file mode 100644
index 0000000..a144071
--- /dev/null
+++ b/recmanager.h
@@ -0,0 +1,63 @@
+#ifndef __TVGUIDE_RECMMANAGER_H
+#define __TVGUIDE_RECMMANAGER_H
+
+#include <string>
+#include <vector>
+#include <vdr/plugin.h>
+#include "services/epgsearch.h"
+#include "detailview.h"
+#include "recmenu.h"
+#include "searchtimer.h"
+#include "switchtimer.h"
+#include "timerconflict.h"
+
+struct TVGuideEPGSearchTemplate {
+public:
+ std::string name;
+ std::string templValue;
+};
+
+// --- cRecManager -------------------------------------------------------------
+class cRecManager {
+private:
+ cPlugin *epgSearchPlugin;
+ bool epgSearchAvailable;
+public:
+ cRecManager(void);
+ void SetEPGSearchPlugin(void);
+ bool EpgSearchAvailable(void) {return epgSearchAvailable;};
+ bool RefreshRemoteTimers(void);
+ bool CheckEventForTimer(const cEvent *event);
+ cTimer *GetTimerForEvent(const cEvent *event);
+ cTimer *createTimer(const cEvent *event, std::string path = "");
+ cTimer *createLocalTimer(const cEvent *event, std::string path);
+ cTimer *createRemoteTimer(const cEvent *event, std::string path);
+ void SetTimerPath(cTimer *timer, const cEvent *event, std::string path);
+ void DeleteTimer(cTimer *timer);
+ void DeleteTimer(int timerID);
+ void DeleteTimer(const cEvent *event);
+ void DeleteLocalTimer(const cEvent *event);
+ void DeleteRemoteTimer(const cEvent *event);
+ void SaveTimer(cTimer *timer, cTimer newTimerSettings);
+ bool IsRecorded(const cEvent *event);
+ cTVGuideTimerConflicts *CheckTimerConflict(void);
+ void CreateSeriesTimer(cTimer *seriesTimer);
+ const cEvent **PerformSearchTimerSearch(std::string epgSearchString, int &numResults);
+ const cEvent **PerformSearch(Epgsearch_searchresults_v1_0 data, int &numResults);
+ void ReadEPGSearchTemplates(std::vector<TVGuideEPGSearchTemplate> *epgTemplates);
+ void GetSearchTimers(std::vector<cTVGuideSearchTimer> *timers);
+ int CreateSearchTimer(std::string epgSearchString);
+ bool SaveSearchTimer(cTVGuideSearchTimer *searchTimer);
+ void DeleteSearchTimer(cTVGuideSearchTimer *searchTimer, bool delTimers);
+ void UpdateSearchTimers(void);
+ bool CreateSwitchTimer(const cEvent *event, cSwitchTimer switchTimer);
+ void DeleteSwitchTimer(const cEvent *event);
+ cRecording **SearchForRecordings(std::string searchString, int &numResults);
+ const cEvent **LoadReruns(const cEvent *event, int &numResults);
+ void GetFavorites(std::vector<cTVGuideSearchTimer> *favorites);
+ const cEvent **WhatsOnNow(bool nowOrNext, int &numResults);
+ const cEvent **UserDefinedTime(int userTime, int &numResults);
+ virtual ~cRecManager (void);
+};
+
+#endif //__TVGUIDE_RECMMANAGER_H
\ No newline at end of file
diff --git a/recmenu.c b/recmenu.c
new file mode 100644
index 0000000..1c8166c
--- /dev/null
+++ b/recmenu.c
@@ -0,0 +1,695 @@
+#include <list>
+#include "recmenu.h"
+
+// --- cRecMenu -------------------------------------------------------------
+
+cRecMenu::cRecMenu(void) {
+ border = geoManager.borderRecMenus;
+ height = 2*border;
+ headerHeight = 0;
+ footerHeight = 0;
+ currentHeight = 0;
+ deleteMenuItems = true;
+ scrollable = false;
+ scrollbarWidth = 3 * border;
+ pixmapScrollBar = NULL;
+ imgScrollBar = NULL;
+ startIndex = 0;
+ stopIndex = 0;
+ numItems = 0;
+ header = NULL;
+ footer = NULL;
+}
+
+cRecMenu::~cRecMenu(void) {
+ if (header)
+ delete header;
+ ClearMenuItems(true);
+ if (footer)
+ delete footer;
+ if (pixmapScrollBar)
+ osdManager.releasePixmap(pixmapScrollBar);
+ if (imgScrollBar)
+ delete imgScrollBar;
+}
+
+void cRecMenu::SetWidthPercent(int percentOSDWidth) {
+ width = geoManager.osdWidth * percentOSDWidth / 100;
+ x = (geoManager.osdWidth - width) / 2;
+}
+
+void cRecMenu::SetWidthPixel(int pixel) {
+ width = pixel;
+ x = (geoManager.osdWidth - width) / 2;
+}
+
+int cRecMenu::CalculateOptimalWidth(void) {
+ int optWidth = 0;
+ for (std::list<cRecMenuItem*>::iterator item = menuItems.begin(); item != menuItems.end(); item++) {
+ int itemWidth = (*item)->GetWidth();
+ if (itemWidth > optWidth)
+ optWidth = itemWidth;
+ }
+ return optWidth;
+}
+
+bool cRecMenu::CalculateHeight(bool reDraw) {
+ int newHeight = 2*border;
+ if (header)
+ newHeight += headerHeight;
+ for (std::list<cRecMenuItem*>::iterator item = menuItems.begin(); item != menuItems.end(); item++) {
+ newHeight += (*item)->GetHeight();
+ }
+ if (footer)
+ newHeight += footerHeight;
+
+ y = (geoManager.osdHeight - newHeight) / 2;
+
+ if (newHeight != height) {
+ height = newHeight;
+ if (scrollable && !reDraw) {
+ width += scrollbarWidth + border;
+ }
+ return true;
+ }
+ return false;
+}
+
+void cRecMenu::CreatePixmap(void) {
+ if (pixmap)
+ osdManager.releasePixmap(pixmap);
+ pixmap = osdManager.requestPixmap(3, cRect(x, y, width, height));
+ if (scrollable) {
+ int scrollBarX = x + width - scrollbarWidth - border;
+ int scrollBarY = y + border + headerHeight;
+ int scrollBarHeight = height - headerHeight - footerHeight - 2 * border;
+ if (pixmapScrollBar)
+ osdManager.releasePixmap(pixmapScrollBar);
+ pixmapScrollBar = osdManager.requestPixmap(4, cRect(scrollBarX, scrollBarY, scrollbarWidth, scrollBarHeight));
+ } else
+ pixmapScrollBar = NULL;
+}
+
+void cRecMenu::SetHeader(cRecMenuItem *header) {
+ this->header = header;
+ headerHeight = header->GetHeight();
+ height += headerHeight;
+}
+
+void cRecMenu::SetFooter(cRecMenuItem *footer) {
+ this->footer = footer;
+ footerHeight = footer->GetHeight();
+ height += footerHeight;
+}
+
+void cRecMenu::ClearMenuItems(bool destructor) {
+ for (std::list<cRecMenuItem*>::iterator it = menuItems.begin(); it != menuItems.end(); it++) {
+ if (deleteMenuItems)
+ delete *it;
+ else if (!destructor)
+ (*it)->Hide();
+ }
+ menuItems.clear();
+};
+
+void cRecMenu::InitMenu(bool complete) {
+ currentHeight = 0;
+ numItems = 0;
+ if (scrollable) {
+ width -= scrollbarWidth + border;
+ osdManager.releasePixmap(pixmapScrollBar);
+ pixmapScrollBar = NULL;
+ delete imgScrollBar;
+ imgScrollBar = NULL;
+ }
+ osdManager.releasePixmap(pixmap);
+ pixmap = NULL;
+ for (std::list<cRecMenuItem*>::iterator it = menuItems.begin(); it != menuItems.end(); it++) {
+ if (deleteMenuItems)
+ delete *it;
+ else
+ (*it)->Hide();
+ }
+ menuItems.clear();
+ if (complete) {
+ startIndex = 0;
+ stopIndex = 0;
+ scrollable = false;
+ } else {
+ stopIndex = startIndex;
+ }
+
+}
+
+
+void cRecMenu::AddMenuItem(cRecMenuItem *item, bool inFront) {
+ item->Show();
+ if (!inFront)
+ menuItems.push_back(item);
+ else
+ menuItems.push_front(item);
+}
+
+bool cRecMenu::AddMenuItemInitial(cRecMenuItem *item, bool inFront) {
+ currentHeight += item->GetHeight();
+ int totalHeight = headerHeight + footerHeight + currentHeight + 2*border;
+ if (totalHeight >= geoManager.osdHeight - 10) {
+ scrollable = true;
+ currentHeight -= item->GetHeight();
+ if (deleteMenuItems) {
+ delete item;
+ }
+ return false;
+ }
+ numItems++;
+ if (!inFront) {
+ stopIndex++;
+ menuItems.push_back(item);
+ } else {
+ startIndex--;
+ menuItems.push_front(item);
+ }
+ return true;
+}
+
+void cRecMenu::Activate(cRecMenuItem *itemOld, cRecMenuItem *item) {
+ itemOld->setInactive();
+ itemOld->setBackground();
+ itemOld->Draw();
+ item->setActive();
+ item->setBackground();
+ item->Draw();
+}
+
+bool cRecMenu::ActivatePrev(void) {
+ cRecMenuItem *activeItem = GetActiveMenuItem();
+ if (!scrollable && footer && footer->isActive()) {
+ if (menuItems.size() > 0) {
+ cRecMenuItem *itemLast = menuItems.back();
+ Activate(footer, itemLast);
+ return true;
+ }
+ } else if (activeItem) {
+ cRecMenuItem *prev = NULL;
+ bool foundActive = false;
+ for (std::list<cRecMenuItem*>::iterator item = menuItems.end(); item != menuItems.begin(); ) {
+ item--;
+ if (*item == activeItem) {
+ foundActive = true;
+ continue;
+ }
+ if (!foundActive)
+ continue;
+ if ((*item)->isSelectable()) {
+ prev = *item;
+ break;
+ }
+ }
+ if (prev) {
+ Activate(activeItem , prev);
+ return true;
+ }
+ }
+ return false;
+}
+
+bool cRecMenu::ScrollUp(void) {
+ if (footer && footer->isActive()) {
+ if (menuItems.size() > 0)
+ Activate(footer, menuItems.back());
+ } else {
+ //get perv x items
+ int numNewItems = numItems / 2;
+ int numAdded = 0;
+ cRecMenuItem *newItem = NULL;
+ while (newItem = GetMenuItem(startIndex-1)) {
+ AddMenuItem(newItem, true);
+ cRecMenuItem *last = menuItems.back();
+ if (deleteMenuItems) {
+ delete last;
+ } else {
+ last->setInactive();
+ last->Hide();
+ }
+ menuItems.pop_back();
+ stopIndex--;
+ startIndex--;
+ numAdded++;
+ if (numAdded >= numNewItems)
+ break;
+ }
+ if (numAdded != 0) {
+ scrollable = true;
+ if (CalculateHeight(true))
+ CreatePixmap();
+ Arrange(deleteMenuItems);
+ Display(deleteMenuItems);
+ ActivatePrev();
+ } else {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool cRecMenu::ActivateNext(void) {
+ cRecMenuItem *activeItem = GetActiveMenuItem();
+ if (activeItem) {
+ cRecMenuItem *next = NULL;
+ bool foundActive = false;
+ for (std::list<cRecMenuItem*>::iterator item = menuItems.begin(); item != menuItems.end(); item++) {
+ if (*item == activeItem) {
+ foundActive = true;
+ continue;
+ }
+ if (!foundActive)
+ continue;
+ if ((*item)->isSelectable()) {
+ next = *item;
+ break;
+ }
+ }
+ if (next) {
+ Activate(activeItem , next);
+ return true;
+ } else if (!scrollable && footer && footer->isSelectable() && !footer->isActive()) {
+ Activate(activeItem , footer);
+ return true;
+ }
+ }
+ return false;
+}
+
+bool cRecMenu::ScrollDown(void) {
+ //get next x items
+ int numNewItems = numItems / 2;
+ int numAdded = 0;
+ cRecMenuItem *newItem = NULL;
+ while (newItem = GetMenuItem(stopIndex)) {
+ menuItems.push_back(newItem);
+ cRecMenuItem *first = menuItems.front();
+ if (deleteMenuItems) {
+ delete first;
+ } else {
+ first->setInactive();
+ first->Hide();
+ }
+ menuItems.pop_front();
+ startIndex++;
+ stopIndex++;
+ numAdded++;
+ if (numAdded >= numNewItems)
+ break;
+ }
+ if (numAdded != 0) {
+ scrollable = true;
+ if (CalculateHeight(true))
+ CreatePixmap();
+ Arrange(deleteMenuItems);
+ Display(deleteMenuItems);
+ ActivateNext();
+ } else {
+ //last item reached, activate footer if not already active
+ if ((footer) && !(footer->isActive())) {
+ cRecMenuItem *activeItem = GetActiveMenuItem();
+ Activate(activeItem , footer);
+ } else {
+ return false;
+ }
+ }
+ return true;
+}
+
+void cRecMenu::PageUp(void) {
+ cRecMenuItem *activeItem = GetActiveMenuItem();
+ if (!activeItem)
+ return;
+ if (!scrollable) {
+ JumpBegin();
+ return;
+ }
+ if (footer && activeItem == footer) {
+ Activate(footer, menuItems.front());
+ return;
+ }
+ int newActive = GetActive() - numItems;
+ if (newActive < 0)
+ newActive = 0;
+ activeItem->setInactive();
+ activeItem->setBackground();
+ ClearMenuItems();
+ currentHeight = 0;
+ stopIndex = startIndex;
+ numItems = 0;
+ cRecMenuItem *newItem = NULL;
+ bool spaceLeft = true;
+ while (newItem = GetMenuItem(startIndex-1)) {
+ if (startIndex-1 == newActive)
+ newItem->setActive();
+ spaceLeft = AddMenuItemInitial(newItem, true);
+ if (!spaceLeft)
+ break;
+ }
+ if (spaceLeft) {
+ while (newItem = GetMenuItem(stopIndex)) {
+ spaceLeft = AddMenuItemInitial(newItem);
+ if (!spaceLeft)
+ break;
+ }
+ }
+ if (GetActive() == numItems)
+ menuItems.front()->setActive();
+ if (CalculateHeight(true))
+ CreatePixmap();
+ Arrange(deleteMenuItems);
+ Display(deleteMenuItems);
+}
+
+void cRecMenu::PageDown(void) {
+ cRecMenuItem *activeItem = GetActiveMenuItem();
+ if (!activeItem)
+ return;
+ if (footer && activeItem == footer) {
+ return;
+ }
+ if (!scrollable) {
+ JumpEnd();
+ return;
+ }
+ int newActive = GetActive() + numItems;
+ activeItem->setInactive();
+ activeItem->setBackground();
+ ClearMenuItems();
+ currentHeight = 0;
+ numItems = 0;
+ startIndex = stopIndex;
+ cRecMenuItem *newItem = NULL;
+ bool spaceLeft = true;
+ while (newItem = GetMenuItem(stopIndex)) {
+ if (stopIndex == newActive)
+ newItem->setActive();
+ spaceLeft = AddMenuItemInitial(newItem);
+ if (!spaceLeft)
+ break;
+ }
+ if (spaceLeft) {
+ while (newItem = GetMenuItem(startIndex-1)) {
+ spaceLeft = AddMenuItemInitial(newItem, true);
+ if (!spaceLeft)
+ break;
+ }
+ }
+ if (GetActive() == GetTotalNumMenuItems())
+ menuItems.back()->setActive();
+ if (CalculateHeight(true))
+ CreatePixmap();
+ Arrange(deleteMenuItems);
+ Display(deleteMenuItems);
+}
+
+void cRecMenu::JumpBegin(void) {
+ cRecMenuItem *activeItem = GetActiveMenuItem();
+ if (!scrollable) {
+ cRecMenuItem *firstSelectable= NULL;
+ for (std::list<cRecMenuItem*>::iterator item = menuItems.begin(); item != menuItems.end(); item++) {
+ if ((*item)->isSelectable()) {
+ firstSelectable = *item;
+ break;
+ }
+ }
+ if (activeItem && firstSelectable) {
+ Activate(activeItem , firstSelectable);
+ }
+ } else {
+ activeItem->setInactive();
+ activeItem->setBackground();
+ if (footer)
+ footer->Draw();
+ ClearMenuItems();
+ int currentItem = 0;
+ cRecMenuItem *newItem = NULL;
+ while (newItem = GetMenuItem(currentItem)) {
+ AddMenuItem(newItem);
+ currentItem++;
+ if (currentItem >= numItems)
+ break;
+ }
+ Arrange(true);
+ startIndex = 0;
+ stopIndex = numItems-1;
+ cRecMenuItem *first = menuItems.front();
+ first->setActive();
+ first->setBackground();
+ first->Draw();
+ Display(true);
+ }
+}
+
+void cRecMenu::JumpEnd(void) {
+ cRecMenuItem *activeItem = GetActiveMenuItem();
+ if (!activeItem)
+ return;
+ if (!scrollable) {
+ cRecMenuItem *lastSelectable= NULL;
+ if (footer && footer->isSelectable()) {
+ lastSelectable = footer;
+ } else {
+ for (std::list<cRecMenuItem*>::iterator item = menuItems.end(); item != menuItems.begin(); ) {
+ item--;
+ if ((*item)->isSelectable()) {
+ lastSelectable = *item;
+ break;
+ }
+ }
+ }
+ if (lastSelectable) {
+ Activate(activeItem , lastSelectable);
+ }
+ } else {
+ activeItem->setInactive();
+ activeItem->setBackground();
+ ClearMenuItems();
+ int totalNumItems = GetTotalNumMenuItems();
+ int currentItem = totalNumItems-1;
+ int itemsAdded = 0;
+ cRecMenuItem *newItem = NULL;
+ while (newItem = GetMenuItem(currentItem)) {
+ AddMenuItem(newItem, true);
+ currentItem--;
+ itemsAdded++;
+ if (itemsAdded >= numItems)
+ break;
+ }
+ Arrange(true);
+ stopIndex = totalNumItems;
+ startIndex = stopIndex - numItems;
+ if (footer) {
+ footer->setActive();
+ footer->setBackground();
+ footer->Draw();
+ } else {
+ cRecMenuItem *last = menuItems.back();
+ last->setActive();
+ last->setBackground();
+ last->Draw();
+ }
+ Display(true);
+ }
+}
+
+void cRecMenu::Arrange(bool scroll) {
+ int xElement = x + border;
+ int yElement = y + border;
+ int widthElement = width - 2 * border;
+ if (scrollable)
+ widthElement -= scrollbarWidth + border;
+
+ if (header) {
+ if (!scroll) {
+ header->SetGeometry(xElement, yElement, widthElement);
+ header->SetPixmaps();
+ header->setBackground();
+ }
+ yElement += header->GetHeight();
+ }
+ for (std::list<cRecMenuItem*>::iterator item = menuItems.begin(); item != menuItems.end(); item++) {
+ (*item)->SetGeometry(xElement, yElement, widthElement);
+ (*item)->SetPixmaps();
+ yElement += (*item)->GetHeight();
+ }
+ if (footer && !scroll) {
+ footer->SetGeometry(xElement, yElement, widthElement);
+ footer->SetPixmaps();
+ footer->setBackground();
+ }
+}
+
+void cRecMenu::Display(bool scroll) {
+ if (tvguideConfig.style == eStyleGraphical) {
+ drawBackgroundGraphical(bgRecMenuBack);
+ } else {
+ pixmap->Fill(theme.Color(clrBackground));
+ drawBorder();
+ }
+ if (header && !scroll) {
+ header->setBackground();
+ header->Draw();
+ }
+ for (std::list<cRecMenuItem*>::iterator item = menuItems.begin(); item != menuItems.end(); item++) {
+ (*item)->setBackground();
+ (*item)->Show();
+ (*item)->Draw();
+ }
+ if (footer && !scroll) {
+ footer->setBackground();
+ footer->Draw();
+ }
+ if (scrollable)
+ DrawScrollBar();
+}
+
+void cRecMenu::Hide(void) {
+ pixmap->SetLayer(-1);
+ if (pixmapScrollBar)
+ pixmapScrollBar->SetLayer(-1);
+ if (header)
+ header->Hide();
+ if (footer)
+ footer->Hide();
+ for (std::list<cRecMenuItem*>::iterator item = menuItems.begin(); item != menuItems.end(); item++) {
+ (*item)->Hide();
+ }
+}
+
+void cRecMenu::Show(void) {
+ pixmap->SetLayer(3);
+ if (pixmapScrollBar)
+ pixmapScrollBar->SetLayer(3);
+ if (header)
+ header->Show();
+ if (footer)
+ footer->Show();
+ for (std::list<cRecMenuItem*>::iterator item = menuItems.begin(); item != menuItems.end(); item++) {
+ (*item)->Show();
+ }
+}
+
+void cRecMenu::UpdateActiveMenuItem(void) {
+ cRecMenuItem *activeItem = GetActiveMenuItem();
+ if (activeItem)
+ activeItem->Draw();
+}
+
+
+void cRecMenu::DrawScrollBar(void) {
+ pixmapScrollBar->Fill(theme.Color(clrBorder));
+ pixmapScrollBar->DrawRectangle(cRect(2,2,pixmapScrollBar->ViewPort().Width()-4, pixmapScrollBar->ViewPort().Height() - 4), theme.Color(clrBackground));
+
+ int totalNumItems = GetTotalNumMenuItems();
+ if (imgScrollBar == NULL) {
+ int scrollBarImgHeight = (pixmapScrollBar->ViewPort().Height() - 8) * numItems / totalNumItems;
+ imgScrollBar = createScrollbar(pixmapScrollBar->ViewPort().Width()-8, scrollBarImgHeight, theme.Color(clrHighlight), theme.Color(clrHighlightBlending));
+ }
+ int offset = (pixmapScrollBar->ViewPort().Height() - 8) * startIndex / totalNumItems;
+ pixmapScrollBar->DrawImage(cPoint(4, 2 + offset), *imgScrollBar);
+}
+
+cRecMenuItem *cRecMenu::GetActiveMenuItem(void) {
+ for (std::list<cRecMenuItem*>::iterator item = menuItems.begin(); item != menuItems.end(); item++) {
+ if ((*item)->isActive())
+ return *item;
+ }
+ if (footer && footer->isActive())
+ return footer;
+ return NULL;
+}
+
+cRecMenuItem *cRecMenu::GetMenuItemAt(int num) {
+ int current = 0;
+ for (std::list<cRecMenuItem*>::iterator item = menuItems.begin(); item != menuItems.end(); item++) {
+ if (current == num)
+ return *item;
+ current++;
+ }
+ return NULL;
+}
+
+int cRecMenu::GetActive(void) {
+ int numActive = startIndex;
+ for (std::list<cRecMenuItem*>::iterator item = menuItems.begin(); item != menuItems.end(); item++) {
+ if ((*item)->isActive()) {
+ break;
+ }
+ numActive++;
+ }
+ return numActive;
+}
+
+eRecMenuState cRecMenu::ProcessKey(eKeys Key) {
+ cRecMenuItem *activeItem = GetActiveMenuItem();
+ eRecMenuState state = rmsContinue;
+ if (!activeItem)
+ return state;
+
+ state = activeItem->ProcessKey(Key);
+ if (state == rmsRefresh) {
+ CreateMenuItems();
+ Display();
+ } else if (state == rmsNotConsumed) {
+ switch (Key & ~k_Repeat) {
+ case kUp:
+ if (!ActivatePrev())
+ if (!ScrollUp())
+ JumpEnd();
+ state = rmsConsumed;
+ break;
+ case kDown:
+ if (!ActivateNext())
+ if (!ScrollDown())
+ JumpBegin();
+ state = rmsConsumed;
+ break;
+ case kLeft:
+ PageUp();
+ state = rmsConsumed;
+ break;
+ case kRight:
+ PageDown();
+ state = rmsConsumed;
+ break;
+ default:
+ break;
+ }
+ }
+ return state;
+}
+
+cImage *cRecMenu::createScrollbar(int width, int height, tColor clrBgr, tColor clrBlend) {
+ cImage *image = new cImage(cSize(width, height));
+ image->Fill(clrBgr);
+ if (tvguideConfig.style != eStyleFlat) {
+ 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;
+}
\ No newline at end of file
diff --git a/recmenu.h b/recmenu.h
new file mode 100644
index 0000000..eb819ee
--- /dev/null
+++ b/recmenu.h
@@ -0,0 +1,66 @@
+#ifndef __TVGUIDE_RECMENU_H
+#define __TVGUIDE_RECMENU_H
+
+#include "recmenuitem.h"
+
+// --- cRecMenu -------------------------------------------------------------
+
+class cRecMenu : public cStyledPixmap {
+private:
+ std::list<cRecMenuItem*> menuItems;
+ int scrollbarWidth;
+ int numItems;
+ int startIndex, stopIndex;
+ void Activate(cRecMenuItem *itemOld, cRecMenuItem *item);
+ bool ActivateNext(void);
+ bool ActivatePrev(void);
+ bool ScrollUp(void);
+ bool ScrollDown(void);
+ void PageUp(void);
+ void PageDown(void);
+ void JumpBegin(void);
+ void JumpEnd(void);
+protected:
+ int x, y;
+ int width, height;
+ int headerHeight, footerHeight;
+ int currentHeight;
+ bool deleteMenuItems;
+ cPixmap *pixmapScrollBar;
+ cImage *imgScrollBar;
+ int border;
+ bool scrollable;
+ cRecMenuItem *header;
+ cRecMenuItem *footer;
+ void SetWidthPercent(int percentOSDWidth);
+ void SetWidthPixel(int pixel);
+ int CalculateOptimalWidth(void);
+ bool CalculateHeight(bool reDraw = false);
+ void CreatePixmap(void);
+ void SetHeader(cRecMenuItem *header);
+ void SetFooter(cRecMenuItem *footer);
+ void ClearMenuItems(bool destructor = false);
+ void InitMenu(bool complete);
+ bool AddMenuItemInitial(cRecMenuItem *item, bool inFront = false);
+ void AddMenuItem(cRecMenuItem *item, bool inFront = false);
+ void DrawScrollBar(void);
+ cImage *createScrollbar(int width, int height, tColor clrBgr, tColor clrBlend);
+ void Arrange(bool scroll = false);
+ virtual cRecMenuItem *GetMenuItem(int number) { return NULL; };
+ cRecMenuItem *GetActiveMenuItem(void);
+ cRecMenuItem *GetMenuItemAt(int num);
+ int GetCurrentNumMenuItems(void) { return menuItems.size(); };
+ virtual int GetTotalNumMenuItems(void) { return 0; };
+ virtual void CreateMenuItems(void) {};
+ int GetStartIndex(void) { return startIndex; };
+ int GetActive(void);
+public:
+ cRecMenu(void);
+ virtual ~cRecMenu(void);
+ void Display(bool scroll = false);
+ void Hide(void);
+ void Show(void);
+ void UpdateActiveMenuItem(void);
+ virtual eRecMenuState ProcessKey(eKeys Key);
+};
+#endif //__TVGUIDE_RECMENU_H
\ No newline at end of file
diff --git a/recmenuitem.c b/recmenuitem.c
new file mode 100644
index 0000000..6e4d31f
--- /dev/null
+++ b/recmenuitem.c
@@ -0,0 +1,2902 @@
+#include <math.h>
+#include <vdr/remote.h>
+#include "imageloader.h"
+#include "imagecache.h"
+#include "tools.h"
+#include "recmenus.h"
+#include "recmenuitem.h"
+
+// --- cRecMenuItem -------------------------------------------------------------
+
+cRecMenuItem::cRecMenuItem(void) {
+ height = 0;
+ action = rmsNotConsumed;
+ defaultBackground = true;
+ drawn = false;
+ font = fontManager.FontRecMenuItem;
+ fontSmall = fontManager.FontRecMenuItemSmall;
+ fontLarge = fontManager.FontRecMenuItemLarge;
+}
+
+cRecMenuItem::~cRecMenuItem(void) {
+}
+
+void cRecMenuItem::SetGeometry(int x, int y, int width) {
+ this->x = x;
+ this->y = y;
+ this->width = width;
+
+}
+
+void cRecMenuItem::SetPixmaps(void) {
+ if (!pixmap)
+ pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height));
+ else
+ pixmap->SetViewPort(cRect(x, y, width, height));
+}
+
+void cRecMenuItem::setBackground(void) {
+ if (tvguideConfig.style == eStyleGraphical) {
+ if (defaultBackground) {
+ drawBackgroundGraphical(bgButton, active);
+ }
+ colorTextBack = clrTransparent;
+ colorText = (active)?theme.Color(clrFontActive):theme.Color(clrFont);
+ } else {
+ if (active) {
+ color = theme.Color(clrHighlight);
+ colorBlending = theme.Color(clrHighlightBlending);
+ colorText = theme.Color(clrFontActive);
+ } else {
+ color = theme.Color(clrGrid1);
+ colorBlending = theme.Color(clrGrid1Blending);
+ colorText = theme.Color(clrFont);
+ }
+ colorTextBack = (tvguideConfig.style == eStyleFlat)?color:clrTransparent;
+ if (defaultBackground) {
+ drawBackground();
+ drawBorder();
+ }
+ }
+}
+
+// --- cRecMenuItemButton -------------------------------------------------------
+
+cRecMenuItemButton::cRecMenuItemButton(const char *text, eRecMenuState action, bool active, bool halfWidth, bool alignLeft, bool largeFont) {
+ selectable = true;
+ this->text = text;
+ this->action = action;
+ this->active = active;
+ fontButtons = (largeFont)?fontLarge:font;
+ height = 3 * fontButtons->Height() / 2;
+ this->halfWidth = halfWidth;
+ this->alignLeft = alignLeft;
+ pixmapText = NULL;
+}
+
+cRecMenuItemButton::~cRecMenuItemButton(void) {
+ if (pixmapText)
+ osdManager.releasePixmap(pixmapText);
+}
+
+int cRecMenuItemButton::GetWidth(void) {
+ return fontButtons->Width(*text);
+}
+
+void cRecMenuItemButton::SetPixmaps(void) {
+ if (halfWidth) {
+ x += width / 4;
+ width = width / 2;
+ }
+ if (!pixmap) {
+ pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height));
+ pixmapText = osdManager.requestPixmap(5, cRect(x, y, width, height));
+ } else {
+ pixmap->SetViewPort(cRect(x, y, width, height));
+ pixmapText->SetViewPort(cRect(x, y, width, height));
+ }
+}
+
+void cRecMenuItemButton::Draw(void) {
+ pixmapText->Fill(clrTransparent);
+ int y = (height - fontButtons->Height()) / 2;
+ int x;
+ if (!alignLeft)
+ x = (width - fontButtons->Width(*text)) / 2;
+ else
+ x = 10;
+ pixmapText->DrawText(cPoint(x, y), *text, colorText, colorTextBack, fontButtons);
+}
+
+void cRecMenuItemButton::Hide(void) {
+ if (pixmap) pixmap->SetLayer(-1);
+ if (pixmapText) pixmapText->SetLayer(-1);
+}
+
+void cRecMenuItemButton::Show(void) {
+ if (pixmap) pixmap->SetLayer(4);
+ if (pixmapText) pixmapText->SetLayer(5);
+}
+
+eRecMenuState cRecMenuItemButton::ProcessKey(eKeys Key) {
+ switch (Key & ~k_Repeat) {
+ case kOk:
+ return action;
+ break;
+ default:
+ break;
+ }
+ return rmsNotConsumed;
+}
+
+
+// --- cRecMenuItemButtonYesNo -------------------------------------------------------
+cRecMenuItemButtonYesNo::cRecMenuItemButtonYesNo(cString textYes,
+ cString textNo,
+ eRecMenuState actionYes,
+ eRecMenuState actionNo,
+ bool active) {
+ selectable = true;
+ this->textYes = textYes;
+ this->textNo = textNo;
+ this->action = actionYes;
+ this->actionNo = actionNo;
+ this->active = active;
+ yesActive = true;
+ height = 3 * font->Height() / 2;
+ pixmapNo = NULL;
+}
+
+cRecMenuItemButtonYesNo::~cRecMenuItemButtonYesNo(void) {
+ if (pixmapNo)
+ delete pixmapNo;
+}
+
+void cRecMenuItemButtonYesNo::SetPixmaps(void) {
+ int buttonWidth = 44 * width / 100;
+ int yesX = x + width / 25;
+ int noX = x + 52 * width / 100;
+ int yPixmaps = y + geoManager.borderRecMenus / 2;
+ if (!pixmap) {
+ pixmap = osdManager.requestPixmap(4, cRect(yesX, yPixmaps, buttonWidth, height));
+ pixmapNo = new cStyledPixmap(osdManager.requestPixmap(4, cRect(noX, yPixmaps, buttonWidth, height)));
+ } else {
+ pixmap->SetViewPort(cRect(yesX, yPixmaps, buttonWidth, height));
+ pixmapNo->SetViewPort(cRect(noX, yPixmaps, buttonWidth, height));
+ }
+}
+
+void cRecMenuItemButtonYesNo::Hide(void) {
+ if (pixmap) pixmap->SetLayer(-1);
+ if (pixmapNo) pixmapNo->SetLayer(-1);
+}
+
+void cRecMenuItemButtonYesNo::Show(void) {
+ if (pixmap) pixmap->SetLayer(4);
+ if (pixmapNo) pixmapNo->SetLayer(4);
+}
+
+void cRecMenuItemButtonYesNo::setBackground() {
+ if (tvguideConfig.style == eStyleGraphical) {
+ drawBackgroundGraphical(bgButton, yesActive&&active);
+ colorTextBack = clrTransparent;
+ colorTextNoBack = clrTransparent;
+ colorText = (active&&yesActive)?theme.Color(clrFontActive):theme.Color(clrFont);
+ colorTextNo = (active&&!yesActive)?theme.Color(clrFontActive):theme.Color(clrFont);
+ pixmapNo->drawBackgroundGraphical(bgButton, active&&!yesActive);
+ } else {
+ tColor colorNoBack;
+ if (active) {
+ if (yesActive) {
+ color = theme.Color(clrHighlight);
+ colorBlending = theme.Color(clrHighlightBlending);
+ colorText = theme.Color(clrFontActive);
+ colorNoBack = theme.Color(clrGrid1);
+ pixmapNo->setColor( colorNoBack,
+ theme.Color(clrGrid1Blending));
+ colorTextNo = theme.Color(clrFont);
+ } else {
+ color = theme.Color(clrGrid1);
+ colorBlending = theme.Color(clrGrid1Blending);
+ colorText = theme.Color(clrFont);
+ colorNoBack = theme.Color(clrHighlight);
+ pixmapNo->setColor( colorNoBack,
+ theme.Color(clrHighlightBlending));
+ colorTextNo = theme.Color(clrFontActive);
+ }
+ } else {
+ color = theme.Color(clrGrid1);
+ colorBlending = theme.Color(clrGrid1Blending);
+ colorText = theme.Color(clrFont);
+ colorNoBack = theme.Color(clrGrid1);
+ pixmapNo->setColor( colorNoBack,
+ theme.Color(clrGrid1Blending));
+ colorTextNo = theme.Color(clrFont);
+ }
+ colorTextBack = (tvguideConfig.style == eStyleFlat)?color:clrTransparent;
+ colorTextNoBack = (tvguideConfig.style == eStyleFlat)?colorNoBack:clrTransparent;
+ drawBackground();
+ drawBorder();
+ pixmapNo->drawBackground();
+ pixmapNo->drawBorder();
+ }
+}
+
+void cRecMenuItemButtonYesNo::Draw(void) {
+ int textYesX = (pixmap->ViewPort().Width() - font->Width(*textYes)) / 2;
+ int textNoX = (pixmapNo->Width() - font->Width(*textNo)) / 2;
+ int textY = (height - font->Height()) / 2;
+ pixmap->DrawText(cPoint(textYesX, textY), *textYes, colorText, colorTextBack, font);
+ pixmapNo->DrawText(cPoint(textNoX, textY), *textNo, colorTextNo, colorTextNoBack, font);
+}
+
+eRecMenuState cRecMenuItemButtonYesNo::ProcessKey(eKeys Key) {
+ switch (Key & ~k_Repeat) {
+ case kLeft:
+ if (!yesActive) {
+ yesActive = true;
+ setBackground();
+ Draw();
+ return rmsConsumed;
+ } else
+ return rmsNotConsumed;
+ break;
+ case kRight:
+ if (yesActive) {
+ yesActive = false;
+ setBackground();
+ Draw();
+ return rmsConsumed;
+ } else
+ return rmsNotConsumed;
+ break;
+ case kOk:
+ if (yesActive)
+ return action;
+ return actionNo;
+ break;
+ default:
+ break;
+ }
+ return rmsNotConsumed;
+}
+
+// --- cRecMenuItemInfo -------------------------------------------------------
+cRecMenuItemInfo::cRecMenuItemInfo(const char *text, bool largeFont) {
+ selectable = false;
+ active = false;
+ this->text = text;
+ fontInfo = (largeFont) ? fontLarge : font;
+ border = 10;
+}
+
+cRecMenuItemInfo::~cRecMenuItemInfo(void) {
+}
+
+void cRecMenuItemInfo::CalculateHeight(int textWidth) {
+ wrapper.Set(*text, fontInfo, textWidth);
+ height = fontInfo->Height() * wrapper.Lines() + 2*border;
+}
+
+void cRecMenuItemInfo::setBackground(void) {
+ pixmap->Fill(clrTransparent);
+ cRecMenuItem::setBackground();
+}
+
+void cRecMenuItemInfo::Draw(void) {
+ int lines = wrapper.Lines();
+ int lineHeight = fontInfo->Height();
+ int x = 0;
+ int y = border;
+ for (int i = 0; i < lines; i++) {
+ x = (width - fontInfo->Width(wrapper.GetLine(i))) / 2;
+ pixmap->DrawText(cPoint(x,y), wrapper.GetLine(i), theme.Color(clrFont), clrTransparent, fontInfo);
+ y += lineHeight;
+ }
+}
+
+// --- cRecMenuItemInt -------------------------------------------------------
+cRecMenuItemInt::cRecMenuItemInt(cString text,
+ int initialVal,
+ int minVal,
+ int maxVal,
+ bool active,
+ int *callback,
+ eRecMenuState action) {
+ selectable = true;
+ this->text = text;
+ this->currentVal = initialVal;
+ this->minVal = minVal;
+ this->maxVal = maxVal;
+ this->active = active;
+ this->callback = callback;
+ this->action = action;
+ height = 3 * font->Height() / 2;
+ pixmapVal = NULL;
+ fresh = true;
+}
+
+cRecMenuItemInt::~cRecMenuItemInt(void) {
+ if (pixmapVal)
+ osdManager.releasePixmap(pixmapVal);
+}
+
+void cRecMenuItemInt::SetPixmaps(void) {
+ if (!pixmap) {
+ pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height));
+ pixmapVal = osdManager.requestPixmap(5, cRect(x, y, width, height));
+ } else {
+ pixmap->SetViewPort(cRect(x, y, width, height));
+ pixmapVal->SetViewPort(cRect(x, y, width, height));
+ }
+}
+
+void cRecMenuItemInt::Hide(void) {
+ if (pixmap) pixmap->SetLayer(-1);
+ if (pixmapVal) pixmapVal->SetLayer(-1);
+}
+
+void cRecMenuItemInt::Show(void) {
+ if (pixmap) pixmap->SetLayer(4);
+ if (pixmapVal) pixmapVal->SetLayer(5);
+}
+
+void cRecMenuItemInt::setBackground() {
+ cRecMenuItem::setBackground();
+ fresh = true;
+}
+
+void cRecMenuItemInt::Draw(void) {
+ int textY = (height - font->Height()) / 2;
+ pixmap->DrawText(cPoint(10, textY), *text, colorText, colorTextBack, font);
+ DrawValue();
+}
+
+void cRecMenuItemInt::DrawValue(void) {
+ pixmapVal->Fill(clrTransparent);
+ cString textVal = cString::sprintf("%d", currentVal);
+ int textX = width - font->Width(*textVal) - 10;
+ int textY = (height - font->Height()) / 2;
+ pixmapVal->DrawText(cPoint(textX, textY), *textVal, colorText, clrTransparent, font);
+}
+
+eRecMenuState cRecMenuItemInt::ProcessKey(eKeys Key) {
+ int oldValue = currentVal;
+ switch (Key & ~k_Repeat) {
+ case kLeft:
+ fresh = true;
+ if (currentVal > minVal) {
+ currentVal--;
+ if (callback)
+ *callback = currentVal;
+ DrawValue();
+ }
+ return rmsConsumed;
+ break;
+ case kRight:
+ fresh = true;
+ if (currentVal < maxVal) {
+ currentVal++;
+ if (callback)
+ *callback = currentVal;
+ DrawValue();
+ }
+ return rmsConsumed;
+ break;
+ case k0 ... k9:
+ if (fresh) {
+ currentVal = 0;
+ fresh = false;
+ }
+ currentVal = currentVal * 10 + (Key - k0);
+ if (!((currentVal >= minVal) && (currentVal <= maxVal)))
+ currentVal = oldValue;
+ if (callback)
+ *callback = currentVal;
+ DrawValue();
+ return rmsConsumed;
+ break;
+ case kOk:
+ return action;
+ default:
+ break;
+ }
+ return rmsNotConsumed;
+}
+
+// --- cRecMenuItemBool -------------------------------------------------------
+cRecMenuItemBool::cRecMenuItemBool(cString text,
+ bool initialVal,
+ bool refresh,
+ bool active,
+ bool *callback,
+ eRecMenuState action) {
+ selectable = true;
+ this->text = text;
+ this->yes = initialVal;
+ this->refresh = refresh;
+ this->active = active;
+ this->callback = callback;
+ this->action = action;
+ height = 3 * font->Height() / 2;
+ pixmapVal = NULL;
+}
+
+cRecMenuItemBool::~cRecMenuItemBool(void) {
+ if (pixmapVal)
+ osdManager.releasePixmap(pixmapVal);
+}
+
+void cRecMenuItemBool::SetPixmaps(void) {
+ if (!pixmap) {
+ pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height));
+ pixmapVal = osdManager.requestPixmap(5, cRect(x, y, width, height));
+ } else {
+ pixmap->SetViewPort(cRect(x, y, width, height));
+ pixmapVal->SetViewPort(cRect(x, y, width, height));
+ }
+}
+
+void cRecMenuItemBool::Hide(void) {
+ if (pixmap) pixmap->SetLayer(-1);
+ if (pixmapVal) pixmapVal->SetLayer(-1);
+}
+
+void cRecMenuItemBool::Show(void) {
+ if (pixmap) pixmap->SetLayer(4);
+ if (pixmapVal) pixmapVal->SetLayer(5);
+}
+
+void cRecMenuItemBool::Draw(void) {
+ int textY = (height - font->Height()) / 2;
+ pixmap->DrawText(cPoint(10, textY), *text, colorText, colorTextBack, font);
+ DrawValue();
+}
+
+void cRecMenuItemBool::DrawValue(void) {
+ pixmapVal->Fill(clrTransparent);
+ std::string strIcon = yes?"yes":"no";
+ int iconSize = height - 8;
+ int iconX = width - iconSize - 10;
+ int iconY = (height - iconSize) / 2;
+
+ cImage *imgYesNo = imgCache.GetIcon(strIcon, iconSize, iconSize);
+ if (imgYesNo) {
+ pixmapVal->DrawImage(cPoint(iconX, iconY), *imgYesNo);
+ }
+}
+
+eRecMenuState cRecMenuItemBool::ProcessKey(eKeys Key) {
+ switch (Key & ~k_Repeat) {
+ case kLeft:
+ case kRight:
+ yes = !yes;
+ if (callback)
+ *callback = yes;
+ DrawValue();
+ if (refresh)
+ return rmsRefresh;
+ else
+ return rmsConsumed;
+ break;
+ case kOk:
+ return action;
+ default:
+ break;
+ }
+ return rmsNotConsumed;
+}
+
+// --- cRecMenuItemSelect -------------------------------------------------------
+cRecMenuItemSelect::cRecMenuItemSelect(cString text,
+ std::vector<std::string> Strings,
+ int initialVal,
+ bool active,
+ int *callback,
+ eRecMenuState action) {
+ selectable = true;
+ this->text = text;
+ strings = Strings;
+ numValues = Strings.size();
+ if ((initialVal < 0) || (initialVal > numValues-1))
+ this->currentVal = 0;
+ else
+ this->currentVal = initialVal;
+ this->active = active;
+ this->callback = callback;
+ this->action = action;
+ height = 3 * font->Height() / 2;
+ pixmapVal = NULL;
+}
+
+cRecMenuItemSelect::~cRecMenuItemSelect(void) {
+ if (pixmapVal)
+ osdManager.releasePixmap(pixmapVal);
+}
+
+void cRecMenuItemSelect::SetPixmaps(void) {
+ if (!pixmap) {
+ pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height));
+ pixmapVal = osdManager.requestPixmap(5, cRect(x, y, width, height));
+ } else {
+ pixmap->SetViewPort(cRect(x, y, width, height));
+ pixmapVal->SetViewPort(cRect(x, y, width, height));
+ }
+}
+
+void cRecMenuItemSelect::Hide(void) {
+ if (pixmap) pixmap->SetLayer(-1);
+ if (pixmapVal) pixmapVal->SetLayer(-1);
+}
+
+void cRecMenuItemSelect::Show(void) {
+ if (pixmap) pixmap->SetLayer(4);
+ if (pixmapVal) pixmapVal->SetLayer(5);
+}
+
+void cRecMenuItemSelect::Draw(void) {
+ int textY = (height - font->Height()) / 2;
+ pixmap->DrawText(cPoint(10, textY), *text, colorText, colorTextBack, font);
+ DrawValue();
+}
+
+void cRecMenuItemSelect::DrawValue(void) {
+ pixmapVal->Fill(clrTransparent);
+ std::string textVal = strings[currentVal];
+ int iconSize = min(128, height);
+ int textX = width - font->Width(textVal.c_str()) - iconSize;
+ int textY = (height - font->Height()) / 2;
+ pixmapVal->DrawText(cPoint(textX, textY), textVal.c_str(), colorText, clrTransparent, font);
+ int iconLeftX = textX - iconSize;
+ int iconRightX = width - iconSize;
+ int iconY = (height - iconSize) / 2;
+
+ cImage *imgLeft = imgCache.GetIcon("arrow_left", iconSize, iconSize);
+ if (imgLeft) {
+ pixmapVal->DrawImage(cPoint(iconLeftX, iconY), *imgLeft);
+ }
+ cImage *imgRight = imgCache.GetIcon("arrow_right", iconSize, iconSize);
+ if (imgRight) {
+ pixmapVal->DrawImage(cPoint(iconRightX, iconY), *imgRight);
+ }
+}
+
+eRecMenuState cRecMenuItemSelect::ProcessKey(eKeys Key) {
+ int oldValue = currentVal;
+ switch (Key & ~k_Repeat) {
+ case kLeft:
+ currentVal--;
+ if (currentVal<0)
+ currentVal = numValues - 1;
+ if (callback)
+ *callback = currentVal;
+ DrawValue();
+ return rmsConsumed;
+ break;
+ case kRight:
+ currentVal = (currentVal+1)%numValues;
+ if (callback)
+ *callback = currentVal;
+ DrawValue();
+ return rmsConsumed;
+ break;
+ case kOk:
+ return action;
+ default:
+ break;
+ }
+ return rmsNotConsumed;
+}
+
+// --- cRecMenuItemSelectDirectory -------------------------------------------------------
+cRecMenuItemSelectDirectory::cRecMenuItemSelectDirectory(cString text,
+ std::string originalFolder,
+ bool active,
+ char *callback,
+ eRecMenuState action,
+ bool isSearchTimer) {
+ selectable = true;
+ this->text = text;
+ this->originalFolder = originalFolder;
+ this->active = active;
+ this->callback = callback;
+ this->action = action;
+ height = 3 * font->Height() / 2;
+ pixmapVal = NULL;
+ folders.push_back(tr("root video folder"));
+ if (isSearchTimer && tvguideConfig.instRecFixedFolder.size() > 0)
+ folders.push_back(tvguideConfig.instRecFixedFolder);
+ ReadRecordingDirectories(&folders, NULL, "");
+ numValues = folders.size();
+ this->currentVal = GetInitial();
+}
+
+cRecMenuItemSelectDirectory::~cRecMenuItemSelectDirectory(void) {
+ if (pixmapVal)
+ osdManager.releasePixmap(pixmapVal);
+}
+
+void cRecMenuItemSelectDirectory::SetPixmaps(void) {
+ if (!pixmap) {
+ pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height));
+ pixmapVal = osdManager.requestPixmap(5, cRect(x, y, width, height));
+ } else {
+ pixmap->SetViewPort(cRect(x, y, width, height));
+ pixmapVal->SetViewPort(cRect(x, y, width, height));
+ }
+}
+
+void cRecMenuItemSelectDirectory::Hide(void) {
+ if (pixmap) pixmap->SetLayer(-1);
+ if (pixmapVal) pixmapVal->SetLayer(-1);
+}
+
+void cRecMenuItemSelectDirectory::Show(void) {
+ if (pixmap) pixmap->SetLayer(4);
+ if (pixmapVal) pixmapVal->SetLayer(5);
+}
+
+void cRecMenuItemSelectDirectory::Draw(void) {
+ int textY = (height - font->Height()) / 2;
+ pixmap->DrawText(cPoint(10, textY), *text, colorText, colorTextBack, font);
+ DrawValue();
+}
+
+void cRecMenuItemSelectDirectory::DrawValue(void) {
+ pixmapVal->Fill(clrTransparent);
+ int iconSize = min(128, height);
+ int textX = width - font->Width(folders[currentVal].c_str()) - iconSize;
+ int textY = (height - font->Height()) / 2;
+ pixmapVal->DrawText(cPoint(textX, textY), folders[currentVal].c_str(), colorText, clrTransparent, font);
+ int iconLeftX = textX - iconSize;
+ int iconRightX = width - iconSize;
+ int iconY = (height - iconSize) / 2;
+
+ cImage *imgLeft = imgCache.GetIcon("arrow_left", iconSize, iconSize);
+ if (imgLeft) {
+ pixmapVal->DrawImage(cPoint(iconLeftX, iconY), *imgLeft);
+ }
+ cImage *imgRight = imgCache.GetIcon("arrow_right", iconSize, iconSize);
+ if (imgRight) {
+ pixmapVal->DrawImage(cPoint(iconRightX, iconY), *imgRight);
+ }
+
+}
+
+eRecMenuState cRecMenuItemSelectDirectory::ProcessKey(eKeys Key) {
+ int oldValue = currentVal;
+ switch (Key & ~k_Repeat) {
+ case kLeft:
+ currentVal--;
+ if (currentVal<0)
+ currentVal = numValues - 1;
+ if (callback) {
+ SetCallback();
+ }
+ DrawValue();
+ return rmsConsumed;
+ break;
+ case kRight: {
+ currentVal = (currentVal+1)%numValues;
+ if (callback) {
+ SetCallback();
+ }
+ DrawValue();
+ return rmsConsumed;
+ break; }
+ case kOk:
+ return action;
+ default:
+ break;
+ }
+ return rmsNotConsumed;
+}
+
+void cRecMenuItemSelectDirectory::SetCallback(void) {
+ std::string newFolder = folders[currentVal];
+ if (!newFolder.compare(tr("root video folder")))
+ newFolder = "";
+ strncpy(callback, newFolder.c_str(), TEXTINPUTLENGTH);
+}
+
+int cRecMenuItemSelectDirectory::GetInitial(void) {
+ if (originalFolder.size() == 0)
+ return 0;
+ for (int i=0; i < numValues; i++) {
+ if (!folders[i].compare(originalFolder)) {
+ return i;
+ }
+ }
+ return 0;
+}
+
+
+// --- cRecMenuItemText -------------------------------------------------------
+cRecMenuItemText::cRecMenuItemText(cString title,
+ char *initialVal,
+ int length,
+ bool active,
+ char *callback) {
+ selectable = true;
+ this->title = title;
+ value = initialVal;
+ this->active = active;
+ this->callback = callback;
+ height = 3 * font->Height();
+ pixmapVal = NULL;
+ pixmapKeyboard = NULL;
+ pixmapKeyboardHighlight = NULL;
+ pixmapKeyboardIcons = NULL;
+ keyboardWidth = 50;
+ gridHeight = 3 * fontSmall->Height();
+ keyboardHeight = 5 * gridHeight;
+
+ this->length = length;
+ allowed = trVDR(FileNameChars);
+ pos = -1;
+ offset = 0;
+ insert = uppercase = false;
+ newchar = true;
+ lengthUtf8 = 0;
+ valueUtf8 = NULL;
+ allowedUtf8 = NULL;
+ charMapUtf8 = NULL;
+ currentCharUtf8 = NULL;
+ lastKey = kNone;
+ keyboardDrawn = false;
+}
+
+cRecMenuItemText::~cRecMenuItemText(void) {
+ if (pixmapVal)
+ osdManager.releasePixmap(pixmapVal);
+ if (pixmapKeyboard)
+ delete pixmapKeyboard;
+ if (pixmapKeyboardHighlight)
+ osdManager.releasePixmap(pixmapKeyboardHighlight);
+ if (pixmapKeyboardIcons)
+ osdManager.releasePixmap(pixmapKeyboardIcons);
+ delete[] valueUtf8;
+ delete[] allowedUtf8;
+ delete[] charMapUtf8;
+}
+
+void cRecMenuItemText::SetPixmaps(void) {
+ int xPixmapVal = x + 20;
+ int yPixmapVal = y + height / 2 + 10;
+ int widthPixmapVal = width - 40;
+ int heightPixmapVal = height / 2 - 20;
+ int keyboardX = x + (100 - keyboardWidth)*width / 100;
+ int keyboardY = y + height;
+ if (!pixmap) {
+ pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height));
+ pixmapVal = osdManager.requestPixmap(5, cRect(xPixmapVal, yPixmapVal, widthPixmapVal, heightPixmapVal));
+ pixmapKeyboard = new cStyledPixmap(osdManager.requestPixmap(-1, cRect(keyboardX, keyboardY, keyboardWidth*width/100, keyboardHeight)));
+ pixmapKeyboardHighlight = osdManager.requestPixmap(-1, cRect(keyboardX, keyboardY, keyboardWidth*width/100, keyboardHeight));
+ pixmapKeyboardIcons = osdManager.requestPixmap(-1, cRect(keyboardX, keyboardY, keyboardWidth*width/100, keyboardHeight));
+ } else {
+ pixmap->SetViewPort(cRect(x, y, width, height));
+ pixmapVal->SetViewPort(cRect(xPixmapVal, yPixmapVal, widthPixmapVal, heightPixmapVal));
+ pixmapKeyboard->SetViewPort(cRect(keyboardX, keyboardY, keyboardWidth*width/100, keyboardHeight));
+ pixmapKeyboardHighlight->SetViewPort(cRect(keyboardX, keyboardY, keyboardWidth*width/100, keyboardHeight));
+ pixmapKeyboardIcons->SetViewPort(cRect(keyboardX, keyboardY, keyboardWidth*width/100, keyboardHeight));
+ }
+ pixmapKeyboardIcons->Fill(clrTransparent);
+}
+
+void cRecMenuItemText::Hide(void) {
+ if (pixmap) pixmap->SetLayer(-1);
+ if (pixmapVal) pixmapVal->SetLayer(-1);
+ if (pixmapKeyboard) pixmapKeyboard->SetLayer(-1);
+ if (pixmapKeyboardHighlight) pixmapKeyboardHighlight->SetLayer(-1);
+ if (pixmapKeyboardIcons) pixmapKeyboardIcons->SetLayer(-1);
+}
+
+void cRecMenuItemText::Show(void) {
+ if (pixmap) pixmap->SetLayer(4);
+ if (pixmapVal) pixmapVal->SetLayer(5);
+}
+
+void cRecMenuItemText::setBackground() {
+ if (!active) {
+ DeactivateKeyboard();
+ }
+ cRecMenuItem::setBackground();
+}
+
+void cRecMenuItemText::Draw(void) {
+ int textY = (height/2 - font->Height()) / 2;
+ pixmap->DrawText(cPoint(10, textY), *title, colorText, colorTextBack, font);
+ DrawValue(value);
+}
+
+void cRecMenuItemText::DrawValue(char *newValue) {
+ tColor clrBack = InEditMode()?theme.Color(clrRecMenuTextActiveBack):theme.Color(clrRecMenuTextBack);
+ pixmapVal->Fill(clrBack);
+ int textX = pixmapVal->DrawPort().Width() - font->Width(newValue) - 10;
+ int textY = (pixmapVal->DrawPort().Height() - font->Height()) / 2;
+ pixmapVal->DrawText(cPoint(textX, textY), newValue, colorText, clrBack, font);
+}
+
+void cRecMenuItemText::ActivateKeyboard(void) {
+ pixmapKeyboard->SetLayer(6);
+ pixmapKeyboardHighlight->SetLayer(6);
+ pixmapKeyboardIcons->SetLayer(6);
+ pixmapKeyboardHighlight->Fill(clrTransparent);
+
+ if (keyboardDrawn)
+ return;
+
+ pixmapKeyboard->setColor(theme.Color(clrRecMenuKeyboardBack), theme.Color(clrRecMenuKeyboardBack));
+ pixmapKeyboard->drawBackground();
+
+ int widthKeyBoard = pixmapKeyboard->Width();
+ gridWidth = widthKeyBoard / 3;
+
+ pixmapKeyboard->DrawRectangle(cRect(0, 0, widthKeyBoard, keyboardHeight), theme.Color(clrRecMenuKeyboardBorder));
+ int num = 1;
+ for (int row = 0; row < 5; row++) {
+ for (int col = 0; col < 3; col++) {
+ int X = col*gridWidth;
+ int Y = row*gridHeight;
+ tColor clrBack = theme.Color(clrRecMenuKeyboardBack);
+ if (num==13)
+ clrBack = theme.Color(clrButtonRedKeyboard);
+ else if (num==14)
+ clrBack = theme.Color(clrButtonGreenKeyboard);
+ else if (num==15)
+ clrBack = theme.Color(clrButtonYellowKeyboard);
+ pixmapKeyboard->DrawRectangle(cRect(X+2, Y+2, gridWidth-4, gridHeight-4), clrBack);
+ pixmapKeyboard->DrawEllipse(cRect(X, Y, 20, 20), theme.Color(clrRecMenuKeyboardBorder),-2);
+ pixmapKeyboard->DrawEllipse(cRect(X, Y+gridHeight-20, 20, 20), theme.Color(clrRecMenuKeyboardBorder),-3);
+ pixmapKeyboard->DrawEllipse(cRect(X+gridWidth-20, Y+gridHeight-20, 20, 20), theme.Color(clrRecMenuKeyboardBorder),-4);
+ pixmapKeyboard->DrawEllipse(cRect(X+gridWidth-20, Y, 20, 20), theme.Color(clrRecMenuKeyboardBorder),-1);
+ bool draw = false;
+ bool drawIcon = false;
+ cString strNum;
+ std::string strIcon;
+ if (num<10) {
+ strNum = *cString::sprintf("%d", num);
+ draw = true;
+ } else if (num == 11) {
+ strNum = *cString::sprintf("%d", 0);
+ draw = true;
+ } else if (num==13) {
+ strIcon = "icon_shift";
+ drawIcon = true;
+ } else if (num==14) {
+ strIcon = "icon_del_ins";
+ drawIcon = true;
+ } else if (num==15) {
+ strIcon = "icon_backspace";
+ drawIcon = true;
+ }
+ if (draw) {
+ int numX = X + (gridWidth - font->Width(*strNum))/2;
+ int numY = Y + font->Height() / 4;
+ pixmapKeyboard->DrawText(cPoint(numX, numY), *strNum, colorText, colorTextBack, font);
+ char *smsKeys = GetSMSKeys(num);
+ int smsKeysX = X + (gridWidth - fontSmall->Width(smsKeys))/2;
+ int smsKeysY = Y + gridHeight - fontSmall->Height() - 10;
+ pixmapKeyboard->DrawText(cPoint(smsKeysX, smsKeysY), smsKeys, theme.Color(clrRecMenuKeyboardBorder), theme.Color(clrRecMenuKeyboardBack), fontSmall);
+ delete[] smsKeys;
+ }
+ if (drawIcon) {
+ int iconSize = gridHeight - 10;
+ cImage *imgIcon = imgCache.GetIcon(strIcon, iconSize, iconSize);
+ if (imgIcon) {
+ int iconX = X + (gridWidth - iconSize) / 2;
+ pixmapKeyboardIcons->DrawImage(cPoint(iconX, Y + 5), *imgIcon);
+ }
+ }
+ num++;
+ }
+ }
+ keyboardDrawn = true;
+}
+
+void cRecMenuItemText::DeactivateKeyboard(void) {
+ pixmapKeyboard->SetLayer(-1);
+ pixmapKeyboardHighlight->SetLayer(-1);
+ pixmapKeyboardIcons->SetLayer(-1);
+}
+
+void cRecMenuItemText::HighlightSMSKey(int num) {
+ int x = 0;
+ int y = 0;
+ if (num == 0) {
+ x = gridWidth;
+ y = 3 * gridHeight;
+ } else {
+ x = (num-1)%3 * gridWidth;
+ y = (num-1)/3 * gridHeight;
+ }
+ pixmapKeyboardHighlight->DrawRectangle(cRect(x, y, gridWidth, gridHeight), theme.Color(clrRecMenuKeyboardHigh));
+}
+
+void cRecMenuItemText::ClearSMSKey(void) {
+ pixmapKeyboardHighlight->Fill(clrTransparent);
+}
+
+
+char *cRecMenuItemText::GetSMSKeys(int num) {
+ if (num == 11)
+ num = 0;
+ if (num > 9)
+ return NULL;
+
+ currentCharUtf8 = charMapUtf8;
+ int pos = num;
+ while (pos > 0 && *currentCharUtf8) {
+ if (*currentCharUtf8++ == '\t')
+ pos--;
+ }
+ while (*currentCharUtf8 && *currentCharUtf8 != '\t' && !IsAllowed(*currentCharUtf8)) {
+ currentCharUtf8++;
+ }
+ uint *startCharUtf8 = currentCharUtf8;
+ int numChars = 0;
+ bool specialChar = false;
+ while(*currentCharUtf8 && *currentCharUtf8 != '\t' && IsAllowed(*currentCharUtf8)) {
+ currentCharUtf8++;
+ if (Utf8CharSet(*currentCharUtf8) > 1)
+ specialChar = true;
+ numChars++;
+ }
+ char buf[100];
+ char *p = buf;
+ int addition = 0;
+ if (specialChar)
+ addition = 1;
+ Utf8FromArray(startCharUtf8, p, numChars+addition);
+ int maxChars = min(numChars+1+addition, 8);
+ char *smskey = new char[maxChars];
+ Utf8Strn0Cpy(smskey, p, maxChars);
+ return smskey;
+}
+
+void cRecMenuItemText::EnterEditMode(void) {
+ if (!valueUtf8) {
+ valueUtf8 = new uint[length];
+ lengthUtf8 = Utf8ToArray(value, valueUtf8, length);
+ int l = strlen(allowed) + 1;
+ allowedUtf8 = new uint[l];
+ Utf8ToArray(allowed, allowedUtf8, l);
+ const char *charMap = trVDR("CharMap$ 0\t-.,1#~\\^$[]|()*+?{}/:%@&\tabc2\tdef3\tghi4\tjkl5\tmno6\tpqrs7\ttuv8\twxyz9");
+ l = strlen(charMap) + 1;
+ charMapUtf8 = new uint[l];
+ Utf8ToArray(charMap, charMapUtf8, l);
+ currentCharUtf8 = charMapUtf8;
+ AdvancePos();
+ }
+}
+
+void cRecMenuItemText::LeaveEditMode(bool SaveValue) {
+ if (valueUtf8) {
+ if (SaveValue) {
+ Utf8FromArray(valueUtf8, value, length);
+ stripspace(value);
+ if (callback) {
+ strncpy(callback, value, TEXTINPUTLENGTH);
+ }
+ }
+ lengthUtf8 = 0;
+ delete[] valueUtf8;
+ valueUtf8 = NULL;
+ delete[] allowedUtf8;
+ allowedUtf8 = NULL;
+ delete[] charMapUtf8;
+ charMapUtf8 = NULL;
+ pos = -1;
+ offset = 0;
+ newchar = true;
+ }
+}
+
+void cRecMenuItemText::AdvancePos(void) {
+ if (pos < length - 2 && pos < lengthUtf8) {
+ if (++pos >= lengthUtf8) {
+ if (pos >= 2 && valueUtf8[pos - 1] == ' ' && valueUtf8[pos - 2] == ' ')
+ pos--; // allow only two blanks at the end
+ else {
+ valueUtf8[pos] = ' ';
+ valueUtf8[pos + 1] = 0;
+ lengthUtf8++;
+ }
+ }
+ }
+ newchar = true;
+ if (!insert && Utf8is(alpha, valueUtf8[pos]))
+ uppercase = Utf8is(upper, valueUtf8[pos]);
+}
+
+uint cRecMenuItemText::Inc(uint c, bool Up) {
+ uint *p = IsAllowed(c);
+ if (!p)
+ p = allowedUtf8;
+ if (Up) {
+ if (!*++p)
+ p = allowedUtf8;
+ } else if (--p < allowedUtf8) {
+ p = allowedUtf8;
+ while (*p && *(p + 1))
+ p++;
+ }
+ return *p;
+}
+
+void cRecMenuItemText::Type(uint c) {
+ if (insert && lengthUtf8 < length - 1)
+ Insert();
+ valueUtf8[pos] = c;
+ if (pos < length - 2)
+ pos++;
+ if (pos >= lengthUtf8) {
+ valueUtf8[pos] = ' ';
+ valueUtf8[pos + 1] = 0;
+ lengthUtf8 = pos + 1;
+ }
+}
+
+void cRecMenuItemText::Insert(void) {
+ memmove(valueUtf8 + pos + 1, valueUtf8 + pos, (lengthUtf8 - pos + 1) * sizeof(*valueUtf8));
+ lengthUtf8++;
+ valueUtf8[pos] = ' ';
+}
+
+void cRecMenuItemText::Delete(void) {
+ memmove(valueUtf8 + pos, valueUtf8 + pos + 1, (lengthUtf8 - pos) * sizeof(*valueUtf8));
+ lengthUtf8--;
+}
+
+uint *cRecMenuItemText::IsAllowed(uint c) {
+ if (allowedUtf8) {
+ for (uint *a = allowedUtf8; *a; a++) {
+ if (c == *a)
+ return a;
+ }
+ }
+ return NULL;
+}
+
+void cRecMenuItemText::SetText(void) {
+ if (InEditMode()) {
+ int textAreaWidth = width - 20;
+ textAreaWidth -= font->Width("[]");
+ textAreaWidth -= font->Width("<>"); // reserving this anyway make the whole thing simpler
+ if (pos < offset)
+ offset = pos;
+ int WidthFromOffset = 0;
+ int EndPos = lengthUtf8;
+ for (int i = offset; i < lengthUtf8; i++) {
+ WidthFromOffset += font->Width(valueUtf8[i]);
+ if (WidthFromOffset > textAreaWidth) {
+ if (pos >= i) {
+ do {
+ WidthFromOffset -= font->Width(valueUtf8[offset]);
+ offset++;
+ } while (WidthFromOffset > textAreaWidth && offset < pos);
+ EndPos = pos + 1;
+ } else {
+ EndPos = i;
+ break;
+ }
+ }
+ }
+ char buf[1000];
+ char *p = buf;
+ if (offset)
+ *p++ = '<';
+ p += Utf8FromArray(valueUtf8 + offset, p, sizeof(buf) - (p - buf), pos - offset);
+ *p++ = '[';
+ if (insert && newchar)
+ *p++ = ']';
+ p += Utf8FromArray(&valueUtf8[pos], p, sizeof(buf) - (p - buf), 1);
+ if (!(insert && newchar))
+ *p++ = ']';
+ p += Utf8FromArray(&valueUtf8[pos + 1], p, sizeof(buf) - (p - buf), EndPos - pos - 1);
+ if (EndPos != lengthUtf8)
+ *p++ = '>';
+ *p = 0;
+ DrawValue(buf);
+ } else {
+ DrawValue(value);
+ }
+}
+
+eRecMenuState cRecMenuItemText::ProcessKey(eKeys Key) {
+ bool consumed = false;
+ bool SameKey = NORMALKEY(Key) == lastKey;
+ ClearSMSKey();
+ if (Key != kNone) {
+ lastKey = NORMALKEY(Key);
+ } else if (!newchar && k0 <= lastKey && lastKey <= k9 && autoAdvanceTimeout.TimedOut()) {
+ AdvancePos();
+ newchar = true;
+ currentCharUtf8 = NULL;
+ SetText();
+ return rmsConsumed;
+ }
+
+ switch ((int)Key) {
+ case kRed: // Switch between upper- and lowercase characters
+ if (InEditMode()) {
+ if (!insert || !newchar) {
+ uppercase = !uppercase;
+ valueUtf8[pos] = uppercase ? Utf8to(upper, valueUtf8[pos]) : Utf8to(lower, valueUtf8[pos]);
+ }
+ consumed = true;
+ }
+ break;
+ case kGreen: // Toggle insert/overwrite modes
+ if (InEditMode()) {
+ insert = !insert;
+ newchar = true;
+ consumed = true;
+ }
+ break;
+ case kYellow|k_Repeat:
+ case kYellow: // Remove the character at the current position; in insert mode it is the character to the right of the cursor
+ if (InEditMode()) {
+ if (lengthUtf8 > 1) {
+ if (!insert || pos < lengthUtf8 - 1)
+ Delete();
+ else if (insert && pos == lengthUtf8 - 1)
+ valueUtf8[pos] = ' '; // in insert mode, deleting the last character replaces it with a blank to keep the cursor position
+ // reduce position, if we removed the last character
+ if (pos == lengthUtf8)
+ pos--;
+ } else if (lengthUtf8 == 1)
+ valueUtf8[0] = ' '; // This is the last character in the string, replace it with a blank
+ if (Utf8is(alpha, valueUtf8[pos]))
+ uppercase = Utf8is(upper, valueUtf8[pos]);
+ newchar = true;
+ consumed = true;
+ }
+ break;
+ case kLeft|k_Repeat:
+ case kLeft:
+
+ if (pos > 0) {
+ if (!insert || newchar)
+ pos--;
+ newchar = true;
+ if (!insert && Utf8is(alpha, valueUtf8[pos]))
+ uppercase = Utf8is(upper, valueUtf8[pos]);
+ }
+ consumed = true;
+ break;
+ case kRight|k_Repeat:
+ case kRight:
+ if (InEditMode()) {
+ AdvancePos();
+ } else {
+ EnterEditMode();
+ ActivateKeyboard();
+ }
+ consumed = true;
+ break;
+ case kUp|k_Repeat:
+ case kUp:
+ case kDown|k_Repeat:
+ case kDown:
+ if (InEditMode()) {
+ if (insert && newchar) {
+ // create a new character in insert mode
+ if (lengthUtf8 < length - 1)
+ Insert();
+ }
+ if (uppercase)
+ valueUtf8[pos] = Utf8to(upper, Inc(Utf8to(lower, valueUtf8[pos]), NORMALKEY(Key) == kUp));
+ else
+ valueUtf8[pos] = Inc( valueUtf8[pos], NORMALKEY(Key) == kUp);
+ newchar = false;
+ consumed = true;
+ }
+ break;
+ case k0|k_Repeat ... k9|k_Repeat:
+ case k0 ... k9: {
+ if (InEditMode()) {
+ if (Setup.NumberKeysForChars) {
+ HighlightSMSKey(NORMALKEY(Key) - k0);
+ if (!SameKey) {
+ if (!newchar)
+ AdvancePos();
+ currentCharUtf8 = NULL;
+ }
+ if (!currentCharUtf8 || !*currentCharUtf8 || *currentCharUtf8 == '\t') {
+ // find the beginning of the character map entry for Key
+ int n = NORMALKEY(Key) - k0;
+ currentCharUtf8 = charMapUtf8;
+ while (n > 0 && *currentCharUtf8) {
+ if (*currentCharUtf8++ == '\t')
+ n--;
+ }
+ // find first allowed character
+ while (*currentCharUtf8 && *currentCharUtf8 != '\t' && !IsAllowed(*currentCharUtf8))
+ currentCharUtf8++;
+ }
+ if (*currentCharUtf8 && *currentCharUtf8 != '\t') {
+ if (insert && newchar) {
+ // create a new character in insert mode
+ if (lengthUtf8 < length - 1)
+ Insert();
+ }
+ valueUtf8[pos] = *currentCharUtf8;
+ if (uppercase)
+ valueUtf8[pos] = Utf8to(upper, valueUtf8[pos]);
+ // find next allowed character
+ do {
+ currentCharUtf8++;
+ } while (*currentCharUtf8 && *currentCharUtf8 != '\t' && !IsAllowed(*currentCharUtf8));
+ newchar = false;
+ autoAdvanceTimeout.Set(AUTO_ADVANCE_TIMEOUT);
+ }
+ } else {
+ Type('0' + NORMALKEY(Key) - k0);
+ }
+ consumed = true;
+ }
+ break; }
+ case kBack:
+ case kOk:
+ if (InEditMode()) {
+ LeaveEditMode(Key == kOk);
+ DeactivateKeyboard();
+ } else {
+ EnterEditMode();
+ ActivateKeyboard();
+ }
+ consumed = true;
+ break;
+ default:
+ if (InEditMode() && BASICKEY(Key) == kKbd) {
+ int c = KEYKBD(Key);
+ if (c <= 0xFF) {
+ if (IsAllowed(Utf8to(lower, c)))
+ Type(c);
+ else {
+ switch (c) {
+ case 0x7F: // backspace
+ if (pos > 0) {
+ pos--;
+ ProcessKey(kYellow);
+ }
+ break;
+ default: ;
+ }
+ }
+ } else {
+ switch (c) {
+ case kfHome: pos = 0; break;
+ case kfEnd: pos = lengthUtf8 - 1; break;
+ case kfIns: ProcessKey(kGreen);
+ case kfDel: ProcessKey(kYellow);
+ default: ;
+ }
+ }
+ consumed = true;
+ }
+ break;
+ }
+ SetText();
+ if (consumed)
+ return rmsConsumed;
+ return rmsNotConsumed;
+}
+
+// --- cRecMenuItemTime -------------------------------------------------------
+cRecMenuItemTime::cRecMenuItemTime(cString text,
+ int initialVal,
+ bool active,
+ int *callback,
+ eRecMenuState action) {
+ selectable = true;
+ this->text = text;
+ this->value = initialVal;
+ hh = value / 100;
+ mm = value % 100;
+ pos = 0;
+ fresh = true;
+ this->active = active;
+ this->callback = callback;
+ this->action = action;
+ height = 3 * font->Height() / 2;
+ pixmapVal = NULL;
+}
+
+cRecMenuItemTime::~cRecMenuItemTime(void) {
+ if (pixmapVal)
+ osdManager.releasePixmap(pixmapVal);
+}
+
+void cRecMenuItemTime::SetPixmaps(void) {
+ if (!pixmap) {
+ pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height));
+ pixmapVal = osdManager.requestPixmap(5, cRect(x, y, width, height));
+ } else {
+ pixmap->SetViewPort(cRect(x, y, width, height));
+ pixmapVal->SetViewPort(cRect(x, y, width, height));
+ }
+}
+
+void cRecMenuItemTime::Hide(void) {
+ if (pixmap) pixmap->SetLayer(-1);
+ if (pixmapVal) pixmapVal->SetLayer(-1);
+}
+
+void cRecMenuItemTime::Show(void) {
+ if (pixmap) pixmap->SetLayer(4);
+ if (pixmapVal) pixmapVal->SetLayer(5);
+}
+
+void cRecMenuItemTime::Draw(void) {
+ int textY = (height - font->Height()) / 2;
+ pixmap->DrawText(cPoint(10, textY), *text, colorText, colorTextBack, font);
+ DrawValue();
+}
+
+void cRecMenuItemTime::DrawValue(void) {
+ pixmapVal->Fill(clrTransparent);
+ char buf[10];
+ switch (pos) {
+ case 1: snprintf(buf, sizeof(buf), "%01d-:--", hh / 10); break;
+ case 2: snprintf(buf, sizeof(buf), "%02d:--", hh); break;
+ case 3: snprintf(buf, sizeof(buf), "%02d:%01d-", hh, mm / 10); break;
+ default: snprintf(buf, sizeof(buf), "%02d:%02d", hh, mm);
+ }
+ int textX = width - font->Width(buf) - 10;
+ int textY = (height - font->Height()) / 2;
+ pixmapVal->DrawText(cPoint(textX, textY), buf, colorText, clrTransparent, font);
+}
+
+eRecMenuState cRecMenuItemTime::ProcessKey(eKeys Key) {
+ switch (Key & ~k_Repeat) {
+ case kLeft|k_Repeat:
+ case kLeft: {
+ if (--mm < 0) {
+ mm = 59;
+ if (--hh < 0)
+ hh = 23;
+ }
+ fresh = true;
+ value = hh * 100 + mm;
+ if (callback)
+ *callback = value;
+ DrawValue();
+ return rmsConsumed;
+ break; }
+ case kRight|k_Repeat:
+ case kRight: {
+ if (++mm > 59) {
+ mm = 0;
+ if (++hh > 23)
+ hh = 0;
+ }
+ fresh = true;
+ value = hh * 100 + mm;
+ DrawValue();
+ if (callback)
+ *callback = value;
+ return rmsConsumed;
+ break; }
+ case k0|k_Repeat ... k9|k_Repeat:
+ case k0 ... k9: {
+ if (fresh || pos > 3) {
+ pos = 0;
+ fresh = false;
+ }
+ int n = Key - k0;
+ switch (pos) {
+ case 0:
+ if (n <= 2) {
+ hh = n * 10;
+ mm = 0;
+ pos++;
+ }
+ break;
+ case 1:
+ if (hh + n <= 23) {
+ hh += n;
+ pos++;
+ }
+ break;
+ case 2:
+ if (n <= 5) {
+ mm += n * 10;
+ pos++;
+ }
+ break;
+ case 3:
+ if (mm + n <= 59) {
+ mm += n;
+ pos++;
+ }
+ break;
+ default: ;
+ }
+ value = hh * 100 + mm;
+ if (callback)
+ *callback = value;
+ DrawValue();
+ return rmsConsumed;
+ break; }
+ case kOk:
+ return action;
+ default:
+ break;
+ }
+ return rmsNotConsumed;
+}
+
+// --- cRecMenuItemDay -------------------------------------------------------
+cRecMenuItemDay::cRecMenuItemDay(cString text,
+ time_t initialVal,
+ bool active,
+ time_t *callback,
+ eRecMenuState action) {
+ selectable = true;
+ this->text = text;
+ this->currentVal = cTimer::SetTime(initialVal, 0);
+ this->active = active;
+ this->callback = callback;
+ this->action = action;
+ height = 3 * font->Height() / 2;
+ pixmapVal = NULL;
+}
+
+cRecMenuItemDay::~cRecMenuItemDay(void) {
+ if (pixmapVal)
+ osdManager.releasePixmap(pixmapVal);
+}
+
+void cRecMenuItemDay::SetPixmaps(void) {
+ if (!pixmap) {
+ pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height));
+ pixmapVal = osdManager.requestPixmap(5, cRect(x, y, width, height));
+ } else {
+ pixmap->SetViewPort(cRect(x, y, width, height));
+ pixmapVal->SetViewPort(cRect(x, y, width, height));
+ }
+}
+
+void cRecMenuItemDay::Hide(void) {
+ if (pixmap) pixmap->SetLayer(-1);
+ if (pixmapVal) pixmapVal->SetLayer(-1);
+}
+
+void cRecMenuItemDay::Show(void) {
+ if (pixmap) pixmap->SetLayer(4);
+ if (pixmapVal) pixmapVal->SetLayer(5);
+}
+
+void cRecMenuItemDay::Draw(void) {
+ int textY = (height - font->Height()) / 2;
+ pixmap->DrawText(cPoint(10, textY), *text, colorText, colorTextBack, font);
+ DrawValue();
+}
+
+void cRecMenuItemDay::DrawValue(void) {
+ pixmapVal->Fill(clrTransparent);
+ cString textVal = DateString(currentVal);
+ int textX = width - font->Width(*textVal) - 10;
+ int textY = (height - font->Height()) / 2;
+ pixmapVal->DrawText(cPoint(textX, textY), *textVal, colorText, clrTransparent, font);
+}
+
+eRecMenuState cRecMenuItemDay::ProcessKey(eKeys Key) {
+ switch (Key & ~k_Repeat) {
+ case kLeft:
+ currentVal -= 60*60*24;
+ if (callback)
+ *callback = currentVal;
+ DrawValue();
+ return rmsConsumed;
+ break;
+ case kRight:
+ currentVal += 60*60*24;
+ if (callback)
+ *callback = currentVal;
+ DrawValue();
+ return rmsConsumed;
+ break;
+ case kOk:
+ return action;
+ default:
+ break;
+ }
+ return rmsNotConsumed;
+}
+
+// --- cRecMenuItemTimer -------------------------------------------------------
+cRecMenuItemTimer::cRecMenuItemTimer(const cTimer *timer,
+ eRecMenuState action1,
+ eRecMenuState action2,
+ eRecMenuState action3,
+ eRecMenuState action4,
+ time_t conflictStart,
+ time_t conflictStop,
+ time_t overlapStart,
+ time_t overlapStop,
+ bool active) {
+ selectable = true;
+ this->timer = timer;
+ this->action = action1;
+ this->action2 = action2;
+ this->action3 = action3;
+ this->action4 = action4;
+ iconActive = 0;
+ this->conflictStart = conflictStart;
+ this->conflictStop = conflictStop;
+ this->overlapStart = overlapStart;
+ this->overlapStop = overlapStop;
+ this->active = active;
+ height = 3 * font->Height();
+ pixmapIcons = NULL;
+}
+
+cRecMenuItemTimer::~cRecMenuItemTimer(void) {
+ if (pixmapIcons)
+ osdManager.releasePixmap(pixmapIcons);
+ if (pixmapStatus)
+ osdManager.releasePixmap(pixmapStatus);
+}
+
+void cRecMenuItemTimer::SetPixmaps(void) {
+ if (!pixmap) {
+ pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height));
+ pixmapStatus = osdManager.requestPixmap(5, cRect(x, y, width, height));
+ pixmapIcons = osdManager.requestPixmap(6, cRect(x, y, width, height));
+ } else {
+ pixmap->SetViewPort(cRect(x, y, width, height));
+ pixmapStatus->SetViewPort(cRect(x, y, width, height));
+ pixmapIcons->SetViewPort(cRect(x, y, width, height));
+ }
+ pixmapStatus->Fill(clrTransparent);
+ pixmapIcons->Fill(clrTransparent);
+}
+
+void cRecMenuItemTimer::Hide(void) {
+ if (pixmap) pixmap->SetLayer(-1);
+ if (pixmapStatus) pixmapStatus->SetLayer(-1);
+ if (pixmapIcons) pixmapIcons->SetLayer(-1);
+}
+
+void cRecMenuItemTimer::Show(void) {
+ if (pixmap) pixmap->SetLayer(4);
+ if (pixmapStatus) pixmapStatus->SetLayer(5);
+ if (pixmapIcons) pixmapIcons->SetLayer(6);
+}
+
+void cRecMenuItemTimer::Draw(void) {
+ const cChannel *channel = timer->Channel();
+ int channelTransponder = 0;
+ cString channelName = "";
+ if (channel) {
+ channelTransponder = channel->Transponder();
+ channelName = channel->Name();
+ }
+ int logoX = DrawIcons();
+ int logoWidth = height * tvguideConfig.logoWidthRatio / tvguideConfig.logoHeightRatio;
+ cImageLoader imgLoader;
+ if (!tvguideConfig.hideChannelLogos) {
+ if (imgLoader.LoadLogo(channel, logoWidth, height)) {
+ cImage logo = imgLoader.GetImage();
+ pixmapIcons->DrawImage(cPoint(logoX, 0), logo);
+ logoX += logoWidth + 5;
+ }
+ }
+ int textX = logoX;
+ int textHeightLine1 = (height/2 - font->Height()) / 2;
+ int textHeightLine2 = height/2 - 5 + (height/4 - fontSmall->Height()) / 2;
+ int textHeightLine3 = 3*height/4 - 5 + (height/4 - fontSmall->Height()) / 2;
+ const cEvent *event = timer->Event();
+ std::string timerTitle = "";
+ if (event) {
+ timerTitle = event->Title();
+ timerTitle = CutText(timerTitle, (70 * width / 100) - textX, font);
+ }
+ cString timeStart = DayDateTime(timer->StartTime());
+ cString timeEnd = TimeString(timer->StopTime());
+ cString timerTime = cString::sprintf("%s - %s", *timeStart, *timeEnd);
+ cString channelInfo = cString::sprintf("%s, %s %d", *channelName, tr("Transp."), channelTransponder);
+ pixmapIcons->DrawText(cPoint(textX, textHeightLine1), timerTitle.c_str(), colorText, colorTextBack, font);
+ pixmapIcons->DrawText(cPoint(textX, textHeightLine2), *timerTime, colorText, colorTextBack, fontSmall);
+ pixmapIcons->DrawText(cPoint(textX, textHeightLine3), *channelInfo, colorText, colorTextBack, fontSmall);
+
+ DrawTimerConflict();
+}
+
+int cRecMenuItemTimer::DrawIcons(void) {
+ int iconsX = 10;
+ int iconSize = height/2;
+ int iconY = (height - iconSize) / 2;
+ std::string iconInfo, iconDelete, iconEdit, iconSearch;
+ if (active) {
+ iconInfo = (iconActive==0)?"info_active":"info_inactive";
+ iconDelete = (iconActive==1)?"delete_active":"delete_inactive";
+ iconEdit = (iconActive==2)?"edit_active":"edit_inactive";
+ iconSearch = (iconActive==3)?"search_active":"search_inactive";
+ } else {
+ iconInfo = "info_inactive";
+ iconDelete = "delete_inactive";
+ iconEdit = "edit_inactive";
+ iconSearch = "search_inactive";
+ }
+
+ cImage *imgInfo = imgCache.GetIcon(iconInfo, iconSize, iconSize);
+ if (imgInfo) {
+ pixmapIcons->DrawImage(cPoint(iconsX, iconY), *imgInfo);
+ iconsX += iconSize + 5;
+ }
+ cImage *imgDelete = imgCache.GetIcon(iconDelete, iconSize, iconSize);
+ if (imgDelete) {
+ pixmapIcons->DrawImage(cPoint(iconsX, iconY), *imgDelete);
+ iconsX += iconSize + 5;
+ }
+ cImage *imgEdit = imgCache.GetIcon(iconEdit, iconSize, iconSize);
+ if (imgEdit) {
+ pixmapIcons->DrawImage(cPoint(iconsX, iconY), *imgEdit);
+ iconsX += iconSize + 5;
+ }
+ cImage *imgSearch = imgCache.GetIcon(iconSearch, iconSize, iconSize);
+ if (imgSearch) {
+ pixmapIcons->DrawImage(cPoint(iconsX, iconY), *imgSearch);
+ iconsX += iconSize + 5;
+ }
+ return iconsX;
+}
+
+void cRecMenuItemTimer::DrawTimerConflict(void) {
+ int widthConfl = 30 * width / 100;
+ int xConfl = width - widthConfl;
+ int heightConflBar = height / 4;
+ int yConflBar = (height - heightConflBar) / 2;
+ pixmapStatus->DrawRectangle(cRect(xConfl, 0, widthConfl, height), theme.Color(clrRecMenuTimerConflictBackground));
+
+ int completeWidthSecs = conflictStop - conflictStart;
+ int xConfBar = xConfl + (timer->StartTime() - conflictStart) * widthConfl / completeWidthSecs;
+ int widthConfBar = (timer->StopTime() - timer->StartTime()) * widthConfl / completeWidthSecs;
+ pixmapStatus->DrawRectangle(cRect(xConfBar, yConflBar, widthConfBar, heightConflBar), theme.Color(clrRecMenuTimerConflictBar));
+
+ int xOverlap = xConfl + (overlapStart - conflictStart) * widthConfl / completeWidthSecs;
+ int widthOverlap = (overlapStop - overlapStart) * widthConfl / completeWidthSecs;
+
+ pixmapIcons->DrawRectangle(cRect(xOverlap, 0, widthOverlap, height), theme.Color(clrRecMenuTimerConflictOverlap));
+
+ pixmapStatus->DrawRectangle(cRect(xConfl-3,2,1,height-4), theme.Color(clrBorder));
+ pixmapStatus->DrawRectangle(cRect(xConfl-2,0,2,height), theme.Color(clrBackground));
+}
+
+eRecMenuState cRecMenuItemTimer::ProcessKey(eKeys Key) {
+ switch (Key & ~k_Repeat) {
+ case kLeft:
+ if (iconActive > 0) {
+ iconActive--;
+ DrawIcons();
+ return rmsConsumed;
+ } else
+ return rmsNotConsumed;
+ break;
+ case kRight:
+ if (iconActive < 3) {
+ iconActive++;
+ DrawIcons();
+ return rmsConsumed;
+ } else
+ return rmsNotConsumed;
+ break;
+ case kOk:
+ if (iconActive == 0)
+ return action;
+ else if (iconActive == 1)
+ return action2;
+ else if (iconActive == 2)
+ return action3;
+ else if (iconActive == 3)
+ return action4;
+ break;
+ default:
+ break;
+ }
+ return rmsNotConsumed;
+}
+
+// --- cRecMenuItemTimerConflictHeader -------------------------------------------------------
+
+cRecMenuItemTimerConflictHeader::cRecMenuItemTimerConflictHeader(time_t conflictStart,
+ time_t conflictStop,
+ time_t overlapStart,
+ time_t overlapStop) {
+ selectable = false;
+ active = false;
+ this->conflictStart = conflictStart;
+ this->conflictStop = conflictStop;
+ this->overlapStart = overlapStart;
+ this->overlapStop = overlapStop;
+ height = 3*font->Height()/2;
+ pixmapStatus = NULL;
+}
+
+cRecMenuItemTimerConflictHeader::~cRecMenuItemTimerConflictHeader(void) {
+ if (pixmapStatus)
+ osdManager.releasePixmap(pixmapStatus);
+}
+
+void cRecMenuItemTimerConflictHeader::SetPixmaps(void) {
+ pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height));
+ pixmapStatus = osdManager.requestPixmap(5, cRect(x, y, width, height));
+ pixmapStatus->Fill(clrTransparent);
+}
+
+void cRecMenuItemTimerConflictHeader::Hide(void) {
+ if (pixmap) pixmap->SetLayer(-1);
+ if (pixmapStatus) pixmapStatus->SetLayer(-1);
+}
+
+void cRecMenuItemTimerConflictHeader::Show(void) {
+ if (pixmap) pixmap->SetLayer(4);
+ if (pixmapStatus) pixmapStatus->SetLayer(5);
+}
+
+void cRecMenuItemTimerConflictHeader::setBackground(void) {
+ pixmap->Fill(clrTransparent);
+ cRecMenuItem::setBackground();
+}
+
+void cRecMenuItemTimerConflictHeader::Draw(void) {
+ int widthConfl = 30 * width / 100;
+ int xConfl = width - widthConfl;
+ cString headerText = tr("Timer Conflict");
+ int xHeader = (xConfl - font->Width(*headerText)) / 2;
+ int yHeader = (height - font->Height()) / 2;
+ pixmap->DrawText(cPoint(xHeader, yHeader), *headerText, theme.Color(clrFont), colorTextBack, font);
+
+ pixmap->DrawRectangle(cRect(xConfl, 0, widthConfl, height), theme.Color(clrRecMenuTimerConflictBackground));
+
+ int completeWidthSecs = conflictStop - conflictStart;
+ int xOverlap = xConfl + (overlapStart - conflictStart) * widthConfl / completeWidthSecs;
+ int yOverlap = height - fontSmall->Height();
+ int widthOverlap = (overlapStop - overlapStart) * widthConfl / completeWidthSecs;
+
+ pixmapStatus->DrawRectangle(cRect(xOverlap, yOverlap, widthOverlap, height), theme.Color(clrRecMenuTimerConflictOverlap));
+
+ cString strConflStart = TimeString(conflictStart);
+ cString strConflStop = TimeString(conflictStop);
+ cString strOverlapStart = TimeString(overlapStart);
+ cString strOverlapStop = TimeString(overlapStop);
+ int y1 = 5;
+ int y2 = yOverlap;
+ int xConflStart = xConfl + 2;
+ int xConflStop = width - fontSmall->Width(*strConflStop) - 2;
+ int xOverlapStart = xOverlap - fontSmall->Width(*strOverlapStart) - 2;
+ int xOverlapStop = xOverlap + widthOverlap + 2;
+ pixmap->DrawText(cPoint(xConflStart, y1), *strConflStart, theme.Color(clrRecMenuTimerConflictBar), theme.Color(clrRecMenuTimerConflictBackground), fontSmall);
+ pixmap->DrawText(cPoint(xConflStop, y1), *strConflStop, theme.Color(clrRecMenuTimerConflictBar), theme.Color(clrRecMenuTimerConflictBackground), fontSmall);
+ pixmap->DrawText(cPoint(xOverlapStart, y2), *strOverlapStart, theme.Color(clrRecMenuTimerConflictOverlap), theme.Color(clrRecMenuTimerConflictBackground), fontSmall);
+ pixmap->DrawText(cPoint(xOverlapStop, y2), *strOverlapStop, theme.Color(clrRecMenuTimerConflictOverlap), theme.Color(clrRecMenuTimerConflictBackground), fontSmall);
+}
+
+// --- cRecMenuItemEvent -------------------------------------------------------
+cRecMenuItemEvent::cRecMenuItemEvent(const cEvent *event,
+ eRecMenuState action1,
+ eRecMenuState action2,
+ bool active) {
+ selectable = true;
+ this->event = event;
+ this->action = action1;
+ this->action2 = action2;
+ iconActive = 0;
+ this->active = active;
+ height = font->Height() + 2*fontSmall->Height() + 10;
+ pixmapText = NULL;
+ pixmapIcons = NULL;
+}
+
+cRecMenuItemEvent::~cRecMenuItemEvent(void) {
+ if (pixmapIcons)
+ osdManager.releasePixmap(pixmapIcons);
+ if (pixmapText)
+ osdManager.releasePixmap(pixmapText);
+}
+
+void cRecMenuItemEvent::SetPixmaps(void) {
+ if (!pixmap) {
+ pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height));
+ pixmapText = osdManager.requestPixmap(5, cRect(x, y, width, height));
+ pixmapText->Fill(clrTransparent);
+ pixmapIcons = osdManager.requestPixmap(6, cRect(x, y, width, height));
+ pixmapIcons->Fill(clrTransparent);
+ } else {
+ pixmap->SetViewPort(cRect(x, y, width, height));
+ pixmapText->SetViewPort(cRect(x, y, width, height));
+ pixmapIcons->SetViewPort(cRect(x, y, width, height));
+ }
+}
+
+void cRecMenuItemEvent::Draw(void) {
+ if (!event)
+ return;
+ int logoX = DrawIcons();
+ const cChannel *channel = Channels.GetByChannelID(event->ChannelID());
+ cString channelName = "";
+ if (channel)
+ channelName = channel->Name();
+ int logoWidth = height * tvguideConfig.logoWidthRatio / tvguideConfig.logoHeightRatio;
+ cImageLoader imgLoader;
+ if (!tvguideConfig.hideChannelLogos) {
+ if (imgLoader.LoadLogo(channel, logoWidth, height)) {
+ cImage logo = imgLoader.GetImage();
+ pixmapText->DrawImage(cPoint(logoX, 0), logo);
+ logoX += logoWidth + 5;
+ }
+ }
+
+ int textX = logoX;
+ int textHeightLine1 = 5;
+ int textHeightLine2 = 5 + fontSmall->Height();
+ int textHeightLine3 = height - fontSmall->Height() - 5;
+
+ cString title = event->Title();
+ cString desc = event->ShortText();
+ cString start = DayDateTime(event->StartTime());
+ cString end = event->GetEndTimeString();
+
+ colorText = active?theme.Color(clrFontActive):theme.Color(clrFont);
+ cString info = cString::sprintf("%s - %s, %s", *start, *end, *channelName);
+ pixmapText->DrawText(cPoint(textX, textHeightLine1), *info, colorText, clrTransparent, fontSmall);
+ pixmapText->DrawText(cPoint(textX, textHeightLine2), *title, colorText, clrTransparent, font);
+ pixmapText->DrawText(cPoint(textX, textHeightLine3), *desc, colorText, clrTransparent, fontSmall);
+}
+
+int cRecMenuItemEvent::DrawIcons(void) {
+ pixmapIcons->Fill(clrTransparent);
+ int iconsX = 10;
+ int iconSize = height / 2;
+ int iconY = (height - iconSize) / 2;
+ std::string iconInfo;
+ if (active) {
+ iconInfo = (iconActive==0)?"info_active":"info_inactive";
+ } else {
+ iconInfo = "info_inactive";
+ }
+ cImage *imgInfo = imgCache.GetIcon(iconInfo, iconSize, iconSize);
+ if (imgInfo) {
+ pixmapIcons->DrawImage(cPoint(iconsX, iconY), *imgInfo);
+ iconsX += iconSize + 5;
+ }
+
+ iconY = height - iconSize - 10;
+ if (event->HasTimer()) {
+ cImage *imgHasTimer = imgCache.GetIcon("activetimer", iconSize, iconSize);
+ if (imgHasTimer) {
+ pixmapIcons->DrawImage(cPoint(width - iconSize - 10, iconY), *imgHasTimer);
+ }
+ } else if (action2 != rmsDisabled) {
+ std::string iconRec = active ? "record_active" : "record_inactive";
+ cImage *imgRec = imgCache.GetIcon(iconRec, iconSize, iconSize);
+ if (imgRec) {
+ pixmapIcons->DrawImage(cPoint(width - iconSize - 10, iconY), *imgRec);
+ }
+ }
+
+
+ return iconsX;
+}
+
+void cRecMenuItemEvent::Hide(void) {
+ if (pixmap) pixmap->SetLayer(-1);
+ if (pixmapText) pixmapText->SetLayer(-1);
+ if (pixmapIcons) pixmapIcons->SetLayer(-1);
+}
+
+void cRecMenuItemEvent::Show(void) {
+ if (pixmap) pixmap->SetLayer(4);
+ if (pixmapText) pixmapText->SetLayer(5);
+ if (pixmapIcons) pixmapIcons->SetLayer(6);
+}
+
+eRecMenuState cRecMenuItemEvent::ProcessKey(eKeys Key) {
+ bool consumed = false;
+ switch (Key & ~k_Repeat) {
+ case kOk:
+ return action;
+ break;
+ case kRed:
+ if (!event->HasTimer())
+ return action2;
+ break;
+ default:
+ break;
+ }
+ return rmsNotConsumed;
+}
+
+// --- cRecMenuItemChannelChooser -------------------------------------------------------
+cRecMenuItemChannelChooser::cRecMenuItemChannelChooser(cString text,
+ cChannel *initialChannel,
+ bool active,
+ int *callback,
+ eRecMenuState action) {
+ selectable = true;
+ this->text = text;
+ this->channel = initialChannel;
+ if (initialChannel)
+ initialChannelSet = true;
+ else
+ initialChannelSet = false;
+ channelNumber = 0;
+ fresh = true;
+ this->active = active;
+ this->callback = callback;
+ this->action = action;
+ height = 2 * font->Height();
+ pixmapChannel = NULL;
+}
+
+cRecMenuItemChannelChooser::~cRecMenuItemChannelChooser(void) {
+ if (pixmapChannel)
+ osdManager.releasePixmap(pixmapChannel);
+}
+
+void cRecMenuItemChannelChooser::SetPixmaps(void) {
+ if (!pixmap) {
+ pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height));
+ pixmapChannel = osdManager.requestPixmap(5, cRect(x, y, width, height));
+ } else {
+ pixmap->SetViewPort(cRect(x, y, width, height));
+ pixmapChannel->SetViewPort(cRect(x, y, width, height));
+ }
+}
+
+void cRecMenuItemChannelChooser::Hide(void) {
+ if (pixmap) pixmap->SetLayer(-1);
+ if (pixmapChannel) pixmapChannel->SetLayer(-1);
+}
+
+void cRecMenuItemChannelChooser::Show(void) {
+ if (pixmap) pixmap->SetLayer(4);
+ if (pixmapChannel) pixmapChannel->SetLayer(5);
+}
+
+void cRecMenuItemChannelChooser::Draw(void) {
+ int textY = (height - font->Height()) / 2;
+ pixmap->DrawText(cPoint(10, textY), *text, colorText, colorTextBack, font);
+ DrawValue();
+}
+
+void cRecMenuItemChannelChooser::DrawValue(void) {
+ pixmapChannel->Fill(clrTransparent);
+ int textY = (height - font->Height()) / 2;
+ if (channel) {
+ cString textVal = cString::sprintf("%d - %s", channel->Number(), channel->Name());
+ int textX = width - font->Width(*textVal) - 10;
+ pixmapChannel->DrawText(cPoint(textX, textY), *textVal, colorText, clrTransparent, font);
+ int logoWidth = height * tvguideConfig.logoWidthRatio / tvguideConfig.logoHeightRatio;
+ int logoX = textX - logoWidth - 10;
+ cImageLoader imgLoader;
+ if (imgLoader.LoadLogo(channel, logoWidth, height)) {
+ cImage logo = imgLoader.GetImage();
+ pixmapChannel->DrawImage(cPoint(logoX, 0), logo);
+ }
+ } else {
+ cString textVal = tr("all Channels");
+ int textX = width - font->Width(*textVal) - 10;
+ pixmapChannel->DrawText(cPoint(textX, textY), *textVal, colorText, clrTransparent, font);
+ }
+}
+
+int cRecMenuItemChannelChooser::GetIntValue(void) {
+ if (channel)
+ return channel->Number();
+ return 0;
+}
+
+
+eRecMenuState cRecMenuItemChannelChooser::ProcessKey(eKeys Key) {
+ switch (Key & ~k_Repeat) {
+ case kLeft: {
+ fresh = true;
+ if (!channel)
+ return rmsConsumed;
+ cChannel *prev = channel;
+ cChannel *firstChannel = Channels.First();
+ if(firstChannel->GroupSep())
+ firstChannel = Channels.Next(firstChannel);
+ if (prev == firstChannel) {
+ if (!initialChannelSet)
+ channel = NULL;
+ } else {
+ while (prev = Channels.Prev(prev)) {
+ if(!prev->GroupSep()) {
+ channel = prev;
+ break;
+ }
+ }
+ }
+ if (callback) {
+ if (channel)
+ *callback = channel->Number();
+ else
+ *callback = 0;
+ }
+ DrawValue();
+ return rmsConsumed;
+ break; }
+ case kRight: {
+ fresh = true;
+ if (!channel) {
+ channel = Channels.First();
+ if(channel->GroupSep())
+ channel = Channels.Next(channel);
+ } else {
+ cChannel *next = channel;
+ while (next = Channels.Next(next)) {
+ if(!next->GroupSep()) {
+ channel = next;
+ break;
+ }
+ }
+ }
+ if (callback) {
+ if (channel)
+ *callback = channel->Number();
+ else
+ *callback = 0;
+ }
+ DrawValue();
+ return rmsConsumed;
+ break; }
+ case k0 ... k9: {
+ if (fresh) {
+ channelNumber = 0;
+ fresh = false;
+ }
+ channelNumber = channelNumber * 10 + (Key - k0);
+ cChannel *chanNew = Channels.GetByNumber(channelNumber);
+ if (chanNew) {
+ channel = chanNew;
+ DrawValue();
+ if (callback)
+ *callback = channel->Number();
+ }
+ return rmsConsumed;
+ break; }
+ case kOk:
+ return action;
+ default:
+ break;
+ }
+ return rmsNotConsumed;
+}
+
+// --- cRecMenuItemDayChooser -------------------------------------------------------
+cRecMenuItemDayChooser::cRecMenuItemDayChooser(cString text,
+ int weekdays,
+ bool active,
+ int *callback) {
+ selectable = true;
+ this->text = text;
+ if (weekdays < 1)
+ weekdays *= -1;
+ this->weekdays = weekdays;
+ this->active = active;
+ this->callback = callback;
+ height = 2 * font->Height();
+ selectedDay = 0;
+ pixmapWeekdays = NULL;
+ pixmapWeekdaysSelect = NULL;
+}
+
+cRecMenuItemDayChooser::~cRecMenuItemDayChooser(void) {
+ if (pixmapWeekdays)
+ osdManager.releasePixmap(pixmapWeekdays);
+ if (pixmapWeekdaysSelect)
+ osdManager.releasePixmap(pixmapWeekdaysSelect);
+}
+
+void cRecMenuItemDayChooser::SetPixmaps(void) {
+ if (!pixmap) {
+ pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height));
+ pixmapWeekdays = osdManager.requestPixmap(5, cRect(x, y, width, height));
+ pixmapWeekdaysSelect = osdManager.requestPixmap(6, cRect(x, y, width, height));
+ } else {
+ pixmap->SetViewPort(cRect(x, y, width, height));
+ pixmapWeekdays->SetViewPort(cRect(x, y, width, height));
+ pixmapWeekdaysSelect->SetViewPort(cRect(x, y, width, height));
+ }
+ SetSizes();
+}
+
+void cRecMenuItemDayChooser::Hide(void) {
+ if (pixmap) pixmap->SetLayer(-1);
+ if (pixmapWeekdays) pixmapWeekdays->SetLayer(-1);
+ if (pixmapWeekdaysSelect) pixmapWeekdaysSelect->SetLayer(-1);
+}
+
+void cRecMenuItemDayChooser::Show(void) {
+ if (pixmap) pixmap->SetLayer(4);
+ if (pixmapWeekdays) pixmapWeekdays->SetLayer(5);
+ if (pixmapWeekdaysSelect) pixmapWeekdaysSelect->SetLayer(6);
+}
+
+void cRecMenuItemDayChooser::SetSizes(void) {
+ days = trVDR("MTWTFSS");
+ int maxWidth = 0;
+ for (unsigned i=0; i<days.length(); ++i) {
+ int charWidth = font->Width(days.at(i));
+ if (charWidth > maxWidth)
+ maxWidth = charWidth;
+ }
+ daysSize = min(maxWidth + 15, height-4);
+ daysX = width - 10 - 7*daysSize;
+ daysY = (height - daysSize) / 2;
+}
+
+void cRecMenuItemDayChooser::setBackground() {
+ cRecMenuItem::setBackground();
+ if (active) {
+ DrawHighlight(selectedDay);
+ } else {
+ DrawHighlight(-1);
+ }
+}
+
+void cRecMenuItemDayChooser::Draw(void) {
+ int textY = (height - font->Height()) / 2;
+ pixmap->DrawText(cPoint(10, textY), *text, colorText, colorTextBack, font);
+ DrawDays();
+}
+
+void cRecMenuItemDayChooser::DrawDays(void) {
+ pixmapWeekdays->Fill(clrTransparent);
+ int textY = (height - font->Height()) / 2;
+ pixmapWeekdays->DrawRectangle(cRect(daysX, daysY, 7*daysSize, daysSize), theme.Color(clrBorder));
+ int currentX = daysX;
+ for (unsigned day=0; day<days.length(); ++day) {
+ cString strDay = cString::sprintf("%c", days.at(day));
+ pixmapWeekdays->DrawRectangle(cRect(currentX+2, daysY+2, daysSize-4, daysSize-4), theme.Color(clrBackground));
+ tColor colorDay = WeekDaySet(day)?theme.Color(clrRecMenuDayActive)
+ :theme.Color(clrRecMenuDayInactive);
+ int textX = currentX + (daysSize - font->Width(*strDay)) / 2;
+ pixmapWeekdays->DrawText(cPoint(textX, textY), *strDay, colorDay, clrTransparent, font);
+ currentX += daysSize;
+ }
+}
+
+void cRecMenuItemDayChooser::DrawHighlight(int day) {
+ pixmapWeekdaysSelect->Fill(clrTransparent);
+ if (day > -1) {
+ int currentX = daysX + day*daysSize;
+ pixmapWeekdaysSelect->DrawRectangle(cRect(currentX, daysY, daysSize, daysSize), theme.Color(clrRecMenuDayHighlight));
+ }
+}
+
+bool cRecMenuItemDayChooser::WeekDaySet(unsigned day) {
+ return weekdays & (1 << day);
+}
+
+void cRecMenuItemDayChooser::ToggleDay(void) {
+ bool dayActive = WeekDaySet(selectedDay);
+ int dayBit = pow(2, selectedDay);
+ if (dayActive) {
+ weekdays -= dayBit;
+ } else {
+ weekdays += dayBit;
+ }
+ if (callback) {
+ *callback = weekdays;
+ }
+}
+
+eRecMenuState cRecMenuItemDayChooser::ProcessKey(eKeys Key) {
+ switch (Key & ~k_Repeat) {
+ case kLeft: {
+ selectedDay--;
+ if (selectedDay<0)
+ selectedDay += 7;
+ DrawHighlight(selectedDay);
+ return rmsConsumed;
+ break; }
+ case kRight: {
+ selectedDay = (selectedDay+1)%7;
+ DrawHighlight(selectedDay);
+ return rmsConsumed;
+ break; }
+ case kOk:
+ ToggleDay();
+ DrawDays();
+ return rmsConsumed;
+ break;
+ default:
+ break;
+ }
+ return rmsNotConsumed;
+}
+
+// --- cRecMenuItemRecording -------------------------------------------------------
+cRecMenuItemRecording::cRecMenuItemRecording(cRecording *recording, bool active) {
+ selectable = true;
+ this->recording = recording;
+ this->active = active;
+ height = font->Height() + 2*fontSmall->Height() + 10;
+ pixmapText = NULL;
+}
+
+cRecMenuItemRecording::~cRecMenuItemRecording(void) {
+ if (pixmapText)
+ osdManager.releasePixmap(pixmapText);
+}
+
+void cRecMenuItemRecording::SetPixmaps(void) {
+ if (!pixmap) {
+ pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height));
+ pixmapText = osdManager.requestPixmap(5, cRect(x, y, width, height));
+ pixmapText->Fill(clrTransparent);
+ } else {
+ pixmap->SetViewPort(cRect(x, y, width, height));
+ pixmapText->SetViewPort(cRect(x, y, width, height));
+ }
+}
+
+void cRecMenuItemRecording::Draw(void) {
+ if (!recording)
+ return;
+ const cRecordingInfo *recInfo = recording->Info();
+ cChannel *channel = Channels.GetByChannelID(recInfo->ChannelID());
+ cString channelName = tr("unknown channel");
+ if (channel)
+ channelName = channel->Name();
+ cString name = recording->Name();
+ cString dateTime = cString::sprintf("%s, %s", *DateString(recording->Start()), *TimeString(recording->Start()));
+
+ int recDuration = recording->LengthInSeconds() / 60;
+
+ cString recDetails = cString::sprintf("%s: %d %s, %s %s %s \"%s\"", tr("Duration"), recDuration, tr("min"), tr("recorded at"), *dateTime, tr("from"), *channelName);
+ recDetails = CutText(*recDetails, width - 40, fontSmall).c_str();
+ int text1Y = (height/2 - font->Height()) / 2 + 5;
+ int text2Y = height/2 + (height/2 - fontSmall->Height())/2 - 5;
+ colorText = active?theme.Color(clrFontActive):theme.Color(clrFont);
+ pixmapText->DrawText(cPoint(10, text1Y), *name, colorText, clrTransparent, font);
+ pixmapText->DrawText(cPoint(10, text2Y), *recDetails, colorText, clrTransparent, fontSmall);
+}
+
+void cRecMenuItemRecording::Hide(void) {
+ if (pixmap) pixmap->SetLayer(-1);
+ if (pixmapText) pixmapText->SetLayer(-1);
+}
+
+void cRecMenuItemRecording::Show(void) {
+ if (pixmap) pixmap->SetLayer(4);
+ if (pixmapText) pixmapText->SetLayer(5);
+}
+
+// --- cRecMenuItemTimelineHeader -------------------------------------------------------
+cRecMenuItemTimelineHeader::cRecMenuItemTimelineHeader(time_t day, std::vector<cTVGuideTimerConflict*> conflictsToday) {
+ conflicts = conflictsToday;
+ pixmapTimeline = NULL;
+ pixmapTimerInfo = NULL;
+ pixmapTimerConflicts = NULL;
+ timer = NULL;
+ this->day = day;
+ selectable = false;
+ active = false;
+ height = 5 * font->Height();
+ timelineDrawn = false;
+}
+
+cRecMenuItemTimelineHeader::~cRecMenuItemTimelineHeader(void) {
+ if (pixmapTimeline)
+ osdManager.releasePixmap(pixmapTimeline);
+ if (pixmapTimerInfo)
+ osdManager.releasePixmap(pixmapTimerInfo);
+ if (pixmapTimerConflicts)
+ osdManager.releasePixmap(pixmapTimerConflicts);
+}
+
+void cRecMenuItemTimelineHeader::SetPixmaps(void) {
+ if (!pixmap) {
+ pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height));
+ pixmapTimeline = osdManager.requestPixmap(5, cRect(x, y, width, height));
+ pixmapTimerInfo = osdManager.requestPixmap(6, cRect(x, y + 3 * font->Height() / 2, width, 2 * font->Height()));
+ if (conflicts.size() > 0) {
+ pixmapTimerConflicts = osdManager.requestPixmap(6, cRect(x, y, width, height));
+ }
+ } else {
+ pixmap->SetViewPort(cRect(x, y, width, height));
+ pixmapTimeline->SetViewPort(cRect(x, y, width, height));
+ pixmapTimerInfo->SetViewPort(cRect(x, y + 3 * font->Height() / 2, width, 2 * font->Height()));
+ if (pixmapTimerConflicts)
+ pixmapTimerConflicts->SetViewPort(cRect(x, y, width, height));
+ }
+}
+
+void cRecMenuItemTimelineHeader::RefreshTimerDisplay(void) {
+ if (!pixmapTimerInfo)
+ return;
+ if (timer)
+ DrawCurrentTimer();
+ else
+ pixmapTimerInfo->Fill(clrTransparent);
+}
+
+void cRecMenuItemTimelineHeader::Draw(void) {
+ if (!timelineDrawn) {
+ DrawTimeline();
+ timelineDrawn = true;
+ }
+ DrawTimerConflicts();
+ pixmap->Fill(clrTransparent);
+ cString headerText = tr("Timers for");
+ cString dateText = DateString(day);
+ cString header = cString::sprintf("%s: %s", *headerText, *dateText);
+ int xText = (width - fontLarge->Width(*header)) / 2;
+ int yText = (height/4 - fontLarge->Height())/2;
+ pixmap->DrawText(cPoint(xText, yText), *header, colorText, clrTransparent, fontLarge);
+
+ DrawCurrentTimer();
+}
+
+void cRecMenuItemTimelineHeader::DrawCurrentTimer(void) {
+ pixmapTimerInfo->Fill(clrTransparent);
+ if (!timer)
+ return;
+ int infoHeight = pixmapTimerInfo->ViewPort().Height();
+ const cEvent *event = timer->Event();
+ const cChannel *channel = timer->Channel();
+ int x = 0;
+ if (channel) {
+ int logoWidth = infoHeight * tvguideConfig.logoWidthRatio / tvguideConfig.logoHeightRatio;
+ bool logoDrawn = false;
+ cImageLoader imgLoader;
+ if (!tvguideConfig.hideChannelLogos) {
+ if (imgLoader.LoadLogo(channel, logoWidth, infoHeight)) {
+ cImage logo = imgLoader.GetImage();
+ pixmapTimerInfo->DrawImage(cPoint(0, 0), logo);
+ x += logoWidth + 10;
+ logoDrawn = true;
+ }
+ }
+ if (tvguideConfig.hideChannelLogos || !logoDrawn) {
+ int channelNameWidth = fontSmall->Width(channel->Name());
+ pixmapTimerInfo->DrawText(cPoint(10, (infoHeight - fontSmall->Height())/2), channel->Name(), colorText, clrTransparent, fontSmall);
+ x += channelNameWidth + 20;
+ }
+ }
+
+ cString timerStartTime = TimeString(timer->StartTime());
+ cString timerStopTime = TimeString(timer->StopTime());
+ cString channelInfo = cString::sprintf("%s %d", tr("Transp."), timer->Channel()->Transponder());
+
+ if (event) {
+ cString title;
+ if (event->ShortText()) {
+ title = cString::sprintf("%s - %s", event->Title(), event->ShortText());
+ } else {
+ title = event->Title();
+ }
+ std::string titleCut = CutText(*title, width - x, font);
+ cString infoString = cString::sprintf("%s: %s - %s (%s. %s - %s), %s", *event->GetDateString(), *event->GetTimeString(), *event->GetEndTimeString(), tr("Rec"), *timerStartTime, *timerStopTime, *channelInfo);
+ pixmapTimerInfo->DrawText(cPoint(x, 0), *infoString, colorText, clrTransparent, font);
+ pixmapTimerInfo->DrawText(cPoint(x, font->Height()), titleCut.c_str(), colorText, clrTransparent, font);
+ } else {
+ cString infoString = cString::sprintf("%s. %s - %s, %s", tr("Rec"), *timerStartTime, *timerStopTime, *channelInfo);
+ pixmapTimerInfo->DrawText(cPoint(x, 0), *infoString, colorText, clrTransparent, font);
+ }
+}
+
+void cRecMenuItemTimelineHeader::DrawTimeline(void) {
+ pixmapTimeline->Fill(clrTransparent);
+ width5Mins = (float)width * 5.0 / 24.0 / 60.0;
+ int widthHour = 12 * width5Mins;
+ x0 = (width - 24*widthHour)/2;
+ int barHeight = fontSmall->Height();
+ int y = height - barHeight;
+ tColor col1 = theme.Color(clrTimeline1);
+ tColor col2 = theme.Color(clrTimeline2);
+ tColor colCurText = col1;
+ tColor colCurBack = col2;
+ int x = x0;
+ for (int hour = 0; hour < 24; hour++) {
+ pixmapTimeline->DrawRectangle(cRect(x, y, widthHour, barHeight), colCurBack);
+ cString hourText = cString::sprintf("%d", hour);
+ int xDelta = (widthHour - fontSmall->Width(*hourText)) / 2;
+ pixmapTimeline->DrawText(cPoint(x + xDelta, y), *hourText, colCurText, colCurBack, fontSmall);
+ x += widthHour;
+ colCurText = (colCurText==col1)?col2:col1;
+ colCurBack = (colCurBack==col1)?col2:col1;
+ }
+ pixmapTimeline->DrawRectangle(cRect(x0, height-2, width - 2*x0, 2), col2);
+}
+
+void cRecMenuItemTimelineHeader::DrawTimerConflicts(void) {
+ if (!pixmapTimerConflicts)
+ return;
+ pixmapTimerConflicts->Fill(clrTransparent);
+ int numConflicts = conflicts.size();
+ int barHeight = fontSmall->Height();
+ int y = height - barHeight;
+ for (int conflict = 0; conflict < numConflicts; conflict++) {
+ int confStart = conflicts[conflict]->timeStart - day;
+ int confStop = conflicts[conflict]->timeStop - day;
+ int overlapStart = conflicts[conflict]->overlapStart - day;
+ int overlapStop = conflicts[conflict]->overlapStop - day;
+ if (confStart < 0)
+ confStart = 0;
+ if (confStop > 24*60*60)
+ confStop = 24 * 60 * 60;
+ if (overlapStart < 0)
+ overlapStart = 0;
+ if (overlapStop > 24*60*60)
+ overlapStop = 24 * 60 * 60;
+ confStart = confStart / 60;
+ confStop = confStop / 60;
+ overlapStart = overlapStart / 60;
+ overlapStop = overlapStop / 60;
+ int xStartConflict = x0 + confStart * width5Mins / 5;
+ int xStopConflict = x0 + confStop * width5Mins / 5;
+ int xStartOverlap = x0 + overlapStart * width5Mins / 5;
+ int xStopOverlap = x0 + overlapStop * width5Mins / 5;
+ pixmapTimerConflicts->DrawRectangle(cRect(xStartConflict, y, xStopConflict - xStartConflict, barHeight), theme.Color(clrRecMenuTimelineConflict));
+ pixmapTimerConflicts->DrawRectangle(cRect(xStartOverlap, y, xStopOverlap - xStartOverlap, barHeight), theme.Color(clrRecMenuTimelineConflictOverlap));
+ }
+}
+
+void cRecMenuItemTimelineHeader::Hide(void) {
+ if (pixmap) pixmap->SetLayer(-1);
+ if (pixmapTimeline) pixmapTimeline->SetLayer(-1);
+ if (pixmapTimerInfo) pixmapTimerInfo->SetLayer(-1);
+ if (pixmapTimerConflicts) pixmapTimerConflicts->SetLayer(-1);
+}
+
+void cRecMenuItemTimelineHeader::Show(void) {
+ if (pixmap) pixmap->SetLayer(4);
+ if (pixmapTimeline) pixmapTimeline->SetLayer(5);
+ if (pixmapTimerInfo) pixmapTimerInfo->SetLayer(6);
+ if (pixmapTimerConflicts) pixmapTimerConflicts->SetLayer(6);
+}
+
+
+// --- cRecMenuItemTimelineTimer -------------------------------------------------------
+cRecMenuItemTimelineTimer::cRecMenuItemTimelineTimer(cTimer *timer, time_t start, time_t stop, std::vector<cTVGuideTimerConflict*> conflictsToday, cRecMenuItemTimelineHeader *header, bool active) {
+ conflicts = conflictsToday;
+ defaultBackground = false;
+ pixmapBack = NULL;
+ pixmapTimerConflicts = NULL;
+ this->timer = timer;
+ this->start = start;
+ this->stop = stop;
+ this->header = header;
+ selectable = true;
+ this->active = active;
+ height = geoManager.osdHeight / 16;
+}
+
+cRecMenuItemTimelineTimer::~cRecMenuItemTimelineTimer(void) {
+ if (pixmapBack)
+ osdManager.releasePixmap(pixmapBack);
+ if (pixmapTimerConflicts)
+ osdManager.releasePixmap(pixmapTimerConflicts);
+}
+
+void cRecMenuItemTimelineTimer::SetPixmaps(void) {
+ if (!pixmap) {
+ pixmapBack = osdManager.requestPixmap(4, cRect(x, y, width, height));
+ pixmap = osdManager.requestPixmap(5, cRect(x, y, width, height));
+ if (conflicts.size() > 0) {
+ pixmapTimerConflicts = osdManager.requestPixmap(6, cRect(x, y, width, height));
+ }
+ } else {
+ pixmapBack->SetViewPort(cRect(x, y, width, height));
+ pixmap->SetViewPort(cRect(x, y, width, height));
+ if (pixmapTimerConflicts)
+ pixmapTimerConflicts->SetViewPort(cRect(x, y, width, height));
+
+ }
+ width5Mins = (float)width * 5.0 / 24.0 / 60.0;
+ x0 = (width - 24*12*width5Mins)/2;
+}
+
+void cRecMenuItemTimelineTimer::Draw(void) {
+ DrawBackground();
+ if (!timer) {
+ DrawNoTimerInfo();
+ return;
+ }
+ if (!drawn) {
+ pixmap->Fill(clrTransparent);
+ DrawTimeScale();
+ DrawTimerBar();
+ DrawTimerConflicts();
+ drawn = true;
+ }
+}
+
+void cRecMenuItemTimelineTimer::DrawBackground(void) {
+ tColor backgroundColor = (active)?theme.Color(clrRecMenuTimelineActive):theme.Color(clrRecMenuTimelineBack);
+ pixmapBack->Fill(clrTransparent);
+ pixmapBack->DrawRectangle(cRect(x0, 0, width - 2 * x0, height), backgroundColor);
+}
+
+void cRecMenuItemTimelineTimer::DrawTimeScale(void) {
+ int x = x0;
+ for (int hour = 0; hour < 25; hour++) {
+ int xModified = (hour%2) ? x - 1 : x ;
+ pixmap->DrawRectangle(cRect(xModified,0,1,height), theme.Color(clrTimeline2));
+ x += width5Mins*12;
+ }
+}
+
+void cRecMenuItemTimelineTimer::DrawTimerBar(void) {
+ time_t timerStart = timer->StartTime() - start;
+ time_t timerStop = timer->StopTime() - start;
+ if (timerStart < 0)
+ timerStart = 0;
+ if (timerStop > 24*60*60)
+ timerStop = 24 * 60 * 60;
+ timerStart = timerStart / 60;
+ timerStop = timerStop / 60;
+ int xStart = x0 + timerStart * width5Mins / 5;
+ int xStop = x0 + timerStop * width5Mins / 5;
+ pixmap->DrawRectangle(cRect(xStart, height / 4, xStop - xStart, height / 2), theme.Color(clrRecMenuTimelineTimer));
+}
+
+void cRecMenuItemTimelineTimer::DrawTimerConflicts(void) {
+ if (!pixmapTimerConflicts)
+ return;
+ pixmapTimerConflicts->Fill(clrTransparent);
+ int numConflicts = conflicts.size();
+ for (int conflict = 0; conflict < numConflicts; conflict++) {
+ int confStart = conflicts[conflict]->timeStart - start;
+ int confStop = conflicts[conflict]->timeStop - start;
+ int overlapStart = conflicts[conflict]->overlapStart - start;
+ int overlapStop = conflicts[conflict]->overlapStop - start;
+ if (confStart < 0)
+ confStart = 0;
+ if (confStop > 24*60*60)
+ confStop = 24 * 60 * 60;
+ if (overlapStart < 0)
+ overlapStart = 0;
+ if (overlapStop > 24*60*60)
+ overlapStop = 24 * 60 * 60;
+ confStart = confStart / 60;
+ confStop = confStop / 60;
+ overlapStart = overlapStart / 60;
+ overlapStop = overlapStop / 60;
+ int xStartConflict = x0 + confStart * width5Mins / 5;
+ int xStopConflict = x0 + confStop * width5Mins / 5;
+ int xStartOverlap = x0 + overlapStart * width5Mins / 5;
+ int xStopOverlap = x0 + overlapStop * width5Mins / 5;
+ pixmapTimerConflicts->DrawRectangle(cRect(xStartConflict, 0, xStopConflict - xStartConflict, height), theme.Color(clrRecMenuTimelineConflict));
+ pixmapTimerConflicts->DrawRectangle(cRect(xStartOverlap, 0, xStopOverlap - xStartOverlap, height), theme.Color(clrRecMenuTimelineConflictOverlap));
+ }
+}
+
+void cRecMenuItemTimelineTimer::DrawNoTimerInfo(void) {
+ pixmap->Fill(clrTransparent);
+ cString noTimersText = tr("No Timers active");
+ int widthText = font->Width(*noTimersText);
+ int x = (width - widthText) / 2;
+ int y = (height - font->Height()) / 2;
+ pixmap->DrawText(cPoint(x, y), *noTimersText, colorText, clrTransparent, font);
+}
+
+void cRecMenuItemTimelineTimer::setActive(void) {
+ active = true;
+ header->SetCurrentTimer(timer);
+ header->RefreshTimerDisplay();
+}
+
+void cRecMenuItemTimelineTimer::setInactive(void) {
+ active = false;
+ header->UnsetCurrentTimer();
+ header->RefreshTimerDisplay();
+}
+
+void cRecMenuItemTimelineTimer::Hide(void) {
+ if (pixmap) pixmap->SetLayer(-1);
+ if (pixmapBack) pixmapBack->SetLayer(-1);
+ if (pixmapTimerConflicts) pixmapTimerConflicts->SetLayer(-1);
+}
+
+void cRecMenuItemTimelineTimer::Show(void) {
+ if (pixmap) pixmap->SetLayer(5);
+ if (pixmapBack) pixmapBack->SetLayer(4);
+ if (pixmapTimerConflicts) pixmapTimerConflicts->SetLayer(6);
+}
+
+cTimer *cRecMenuItemTimelineTimer::GetTimerValue(void) {
+ return timer;
+}
+
+eRecMenuState cRecMenuItemTimelineTimer::ProcessKey(eKeys Key) {
+ switch (Key & ~k_Repeat) {
+ case kOk:
+ return rmsTimelineTimerEdit;
+ default:
+ break;
+ }
+ return rmsNotConsumed;
+}
+
+
+// --- cRecMenuItemSearchTimer -------------------------------------------------------
+cRecMenuItemSearchTimer::cRecMenuItemSearchTimer(cTVGuideSearchTimer timer,
+ eRecMenuState action1,
+ eRecMenuState action2,
+ eRecMenuState action3,
+ bool active) {
+ this->timer = timer;
+ this->action = action1;
+ this->action2 = action2;
+ this->action3 = action3;
+ pixmapText = NULL;
+ pixmapIcons = NULL;
+ selectable = true;
+ this->active = active;
+ iconActive = 0;
+ height = 2 * font->Height();;
+}
+
+cRecMenuItemSearchTimer::~cRecMenuItemSearchTimer(void) {
+ if (pixmapText)
+ osdManager.releasePixmap(pixmapText);
+ if (pixmapIcons)
+ osdManager.releasePixmap(pixmapIcons);
+}
+
+void cRecMenuItemSearchTimer::SetPixmaps(void) {
+ if (!pixmap) {
+ pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height));
+ pixmapText = osdManager.requestPixmap(5, cRect(x, y, width, height));
+ pixmapIcons = osdManager.requestPixmap(6, cRect(x, y, width, height));
+ } else {
+ pixmap->SetViewPort(cRect(x, y, width, height));
+ pixmapText->SetViewPort(cRect(x, y, width, height));
+ pixmapIcons->SetViewPort(cRect(x, y, width, height));
+ }
+}
+
+void cRecMenuItemSearchTimer::Draw(void) {
+ int textX = DrawIcons();
+ pixmapText->Fill(clrTransparent);
+ textX += 20;
+ cString label;
+ if (timer.Active()) {
+ label = cString::sprintf("\"%s\"", timer.SearchString().c_str());
+ } else {
+ label = cString::sprintf("\"%s\" (%s)", timer.SearchString().c_str(), tr("inactive"));
+ }
+ int numTimersActive = timer.GetNumTimers();
+ int numRecordings = timer.GetNumRecordings();
+ cString info = cString::sprintf("%s: %d, %s: %d", tr("active timers"), numTimersActive, tr("recordings done"), numRecordings);
+ pixmapText->DrawText(cPoint(textX, 5 + (height/2 - font->Height())/2), *label, colorText, clrTransparent, font);
+ pixmapText->DrawText(cPoint(textX, height/2 + (height/2 - fontSmall->Height())/2), *info, colorText, clrTransparent, fontSmall);
+}
+
+void cRecMenuItemSearchTimer::Hide(void) {
+ if (pixmap) pixmap->SetLayer(-1);
+ if (pixmapText) pixmapText->SetLayer(-1);
+ if (pixmapIcons) pixmapIcons->SetLayer(-1);
+}
+
+void cRecMenuItemSearchTimer::Show(void) {
+ if (pixmap) pixmap->SetLayer(4);
+ if (pixmapText) pixmapText->SetLayer(5);
+ if (pixmapIcons) pixmapIcons->SetLayer(6);
+}
+
+int cRecMenuItemSearchTimer::DrawIcons(void) {
+ pixmapIcons->Fill(clrTransparent);
+ int iconsX = 10;
+ int iconSize = height / 2;
+ int iconY = (height - iconSize) / 2;
+ std::string iconEdit, iconDelete, iconSearch;
+ if (active) {
+ iconSearch = (iconActive==0)?"search_active":"search_inactive";
+ iconEdit = (iconActive==1)?"edit_active":"edit_inactive";
+ iconDelete = (iconActive==2)?"delete_active":"delete_inactive";
+ } else {
+ iconSearch = "search_inactive";
+ iconEdit = "edit_inactive";
+ iconDelete = "delete_inactive";
+ }
+ cImage *imgSearch = imgCache.GetIcon(iconSearch, iconSize, iconSize);
+ if (imgSearch) {
+ pixmapIcons->DrawImage(cPoint(iconsX, iconY), *imgSearch);
+ iconsX += iconSize + 10;
+ }
+ cImage *imgEdit = imgCache.GetIcon(iconEdit, iconSize, iconSize);
+ if (imgEdit) {
+ pixmapIcons->DrawImage(cPoint(iconsX, iconY), *imgEdit);
+ iconsX += iconSize + 10;
+ }
+ cImage *imgDel = imgCache.GetIcon(iconDelete, iconSize, iconSize);
+ if (imgDel) {
+ pixmapIcons->DrawImage(cPoint(iconsX, iconY), *imgDel);
+ iconsX += iconSize + 10;
+ }
+ return iconsX;
+}
+
+eRecMenuState cRecMenuItemSearchTimer::ProcessKey(eKeys Key) {
+ switch (Key & ~k_Repeat) {
+ case kLeft:
+ if (iconActive > 0) {
+ iconActive--;
+ DrawIcons();
+ return rmsConsumed;
+ }
+ return rmsNotConsumed;
+ break;
+ case kRight: {
+ if (iconActive < 2) {
+ iconActive++;
+ DrawIcons();
+ return rmsConsumed;
+ }
+ return rmsNotConsumed;
+ break; }
+ case kOk:
+ if (iconActive == 0)
+ return action;
+ else if (iconActive == 1)
+ return action2;
+ else if (iconActive == 2)
+ return action3;
+ break;
+ default:
+ break;
+ }
+ return rmsNotConsumed;
+}
+
+// --- cRecMenuItemFavorite -------------------------------------------------------
+cRecMenuItemFavorite::cRecMenuItemFavorite(cTVGuideSearchTimer favorite,
+ eRecMenuState action1,
+ bool active) {
+ this->favorite = favorite;
+ this->action = action1;
+ pixmapText = NULL;
+ pixmapIcons = NULL;
+ selectable = true;
+ this->active = active;
+ height = 2 * font->Height();;
+}
+
+cRecMenuItemFavorite::~cRecMenuItemFavorite(void) {
+ if (pixmapText)
+ osdManager.releasePixmap(pixmapText);
+ if (pixmapIcons)
+ osdManager.releasePixmap(pixmapIcons);
+}
+
+void cRecMenuItemFavorite::SetPixmaps(void) {
+ if (!pixmap) {
+ pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height));
+ pixmapText = osdManager.requestPixmap(5, cRect(x, y, width, height));
+ pixmapIcons = osdManager.requestPixmap(6, cRect(x, y, width, height));
+ } else {
+ pixmap->SetViewPort(cRect(x, y, width, height));
+ pixmapText->SetViewPort(cRect(x, y, width, height));
+ pixmapIcons->SetViewPort(cRect(x, y, width, height));
+ }
+}
+
+void cRecMenuItemFavorite::Draw(void) {
+ int textX = DrawIcons();
+ pixmapText->Fill(clrTransparent);
+ textX += 20;
+ cString label = cString::sprintf("\"%s\"", favorite.SearchString().c_str());
+ pixmapText->DrawText(cPoint(textX, (height - fontLarge->Height())/2), *label, colorText, clrTransparent, fontLarge);
+}
+
+void cRecMenuItemFavorite::Hide(void) {
+ if (pixmap) pixmap->SetLayer(-1);
+ if (pixmapText) pixmapText->SetLayer(-1);
+ if (pixmapIcons) pixmapIcons->SetLayer(-1);
+}
+
+void cRecMenuItemFavorite::Show(void) {
+ if (pixmap) pixmap->SetLayer(4);
+ if (pixmapText) pixmapText->SetLayer(5);
+ if (pixmapIcons) pixmapIcons->SetLayer(6);
+}
+
+int cRecMenuItemFavorite::DrawIcons(void) {
+ pixmapIcons->Fill(clrTransparent);
+ int iconsX = 10;
+ int iconSize = height / 2;
+ int iconY = (height - iconSize) / 2;
+ std::string iconSearch;
+ iconSearch = active ? "search_active" : "search_inactive" ;
+ cImage *imgSearch = imgCache.GetIcon(iconSearch, iconSize, iconSize);
+ if (imgSearch) {
+ pixmapIcons->DrawImage(cPoint(iconsX, iconY), *imgSearch);
+ iconsX += iconSize + 10;
+ }
+ return iconsX;
+}
+
+eRecMenuState cRecMenuItemFavorite::ProcessKey(eKeys Key) {
+ switch (Key & ~k_Repeat) {
+ case kOk:
+ return action;
+ default:
+ break;
+ }
+ return rmsNotConsumed;
+}
+
+// --- cRecMenuItemFavoriteStatic -------------------------------------------------------
+cRecMenuItemFavoriteStatic::cRecMenuItemFavoriteStatic(std::string text, eRecMenuState action, bool active) {
+ this->text = text;
+ this->action = action;
+ pixmapText = NULL;
+ pixmapIcons = NULL;
+ selectable = true;
+ this->active = active;
+ height = 2 * font->Height();;
+}
+
+cRecMenuItemFavoriteStatic::~cRecMenuItemFavoriteStatic(void) {
+ if (pixmapText)
+ osdManager.releasePixmap(pixmapText);
+ if (pixmapIcons)
+ osdManager.releasePixmap(pixmapIcons);
+}
+
+void cRecMenuItemFavoriteStatic::SetPixmaps(void) {
+ if (!pixmap) {
+ pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height));
+ pixmapText = osdManager.requestPixmap(5, cRect(x, y, width, height));
+ pixmapIcons = osdManager.requestPixmap(6, cRect(x, y, width, height));
+ } else {
+ pixmap->SetViewPort(cRect(x, y, width, height));
+ pixmapText->SetViewPort(cRect(x, y, width, height));
+ pixmapIcons->SetViewPort(cRect(x, y, width, height));
+ }
+}
+
+void cRecMenuItemFavoriteStatic::Draw(void) {
+ int textX = DrawIcons();
+ pixmapText->Fill(clrTransparent);
+ textX += 20;
+ pixmapText->DrawText(cPoint(textX, (height - fontLarge->Height())/2), text.c_str(), colorText, clrTransparent, fontLarge);
+}
+
+void cRecMenuItemFavoriteStatic::Hide(void) {
+ if (pixmap) pixmap->SetLayer(-1);
+ if (pixmapText) pixmapText->SetLayer(-1);
+ if (pixmapIcons) pixmapIcons->SetLayer(-1);
+}
+
+void cRecMenuItemFavoriteStatic::Show(void) {
+ if (pixmap) pixmap->SetLayer(4);
+ if (pixmapText) pixmapText->SetLayer(5);
+ if (pixmapIcons) pixmapIcons->SetLayer(6);
+}
+
+int cRecMenuItemFavoriteStatic::DrawIcons(void) {
+ pixmapIcons->Fill(clrTransparent);
+ int iconsX = 10;
+ int iconSize = height / 2;
+ int iconY = (height - iconSize) / 2;
+ std::string iconSearch;
+ iconSearch = active ? "search_active" : "search_inactive" ;
+ cImage *imgSearch = imgCache.GetIcon(iconSearch, iconSize, iconSize);
+ if (imgSearch) {
+ pixmapIcons->DrawImage(cPoint(iconsX, iconY), *imgSearch);
+ iconsX += iconSize + 10;
+ }
+ return iconsX;
+}
+
+eRecMenuState cRecMenuItemFavoriteStatic::ProcessKey(eKeys Key) {
+ switch (Key & ~k_Repeat) {
+ case kOk:
+ return action;
+ default:
+ break;
+ }
+ return rmsNotConsumed;
+}
\ No newline at end of file
diff --git a/recmenuitem.h b/recmenuitem.h
new file mode 100644
index 0000000..9df37db
--- /dev/null
+++ b/recmenuitem.h
@@ -0,0 +1,684 @@
+#ifndef __TVGUIDE_RECMENUITEM_H
+#define __TVGUIDE_RECMENUITEM_H
+
+#define AUTO_ADVANCE_TIMEOUT 1500
+
+#include <string>
+#include <vdr/tools.h>
+#include "styledpixmap.h"
+#include "timerconflict.h"
+#include "searchtimer.h"
+
+enum eRecMenuState {
+ rmsConsumed,
+ rmsNotConsumed,
+ rmsRefresh,
+ rmsContinue,
+ rmsClose,
+ rmsDisabled,
+ //INSTANT TIMER
+ rmsInstantRecord,
+ rmsInstantRecordFolder,
+ rmsIgnoreTimerConflict,
+ rmsDeleteTimerConflictMenu,
+ rmsEditTimerConflictMenu,
+ rmsSearchRerunsTimerConflictMenu,
+ rmsSaveTimerConflictMenu,
+ rmsTimerConflictShowInfo,
+ rmsDeleteTimer,
+ rmsDeleteTimerConfirmation,
+ rmsEditTimer,
+ rmsSaveTimer,
+ //SEARCH
+ rmsSearch,
+ rmsSearchWithOptions,
+ rmsSearchPerform,
+ rmsSearchShowInfo,
+ rmsSearchRecord,
+ rmsSearchRecordConfirm,
+ rmsSearchNothingFoundConfirm,
+ //SERIES TIMER
+ rmsSeriesTimer,
+ rmsSeriesTimerFolder,
+ rmsSeriesTimerCreate,
+ //SEARCHTIMER
+ rmsSearchTimer,
+ rmsSearchTimerOptions,
+ rmsSearchTimers,
+ rmsSearchTimerEdit,
+ rmsSearchTimerEditAdvanced,
+ rmsSearchTimerTest,
+ rmsSearchTimerSave,
+ rmsSearchTimerCreateWithTemplate,
+ rmsSearchTimerDeleteConfirm,
+ rmsSearchTimerDelete,
+ rmsSearchTimerDeleteWithTimers,
+ rmsSearchTimerRecord,
+ //SWITCHTIMER
+ rmsSwitchTimer,
+ rmsSwitchTimerCreate,
+ rmsSwitchTimerDelete,
+ //RECORDINGS SEARCH
+ rmsRecordingSearch,
+ rmsRecordingSearchResult,
+ //TIMER CONFLICTS
+ rmsTimerConflict,
+ rmsTimerConflicts,
+ rmsTimerConflictIgnoreReruns,
+ rmsTimerConflictRecordRerun,
+ //TIMELINE
+ rmsTimeline,
+ rmsTimelineTimerEdit,
+ rmsTimelineTimerSave,
+ rmsTimelineTimerDelete,
+ //FAVORITES
+ rmsFavoritesRecord,
+ rmsFavoritesRecordConfirm,
+ rmsFavoritesNow,
+ rmsFavoritesNext,
+ rmsFavoritesUser1,
+ rmsFavoritesUser2,
+ rmsFavoritesUser3,
+ rmsFavoritesUser4,
+};
+
+enum eDependend {
+ eGreater,
+ eLower,
+};
+
+// --- cRecMenuItem -------------------------------------------------------------
+class cRecMenuItem : public cListObject, public cStyledPixmap {
+protected:
+ int x, y;
+ int width, height;
+ bool selectable;
+ bool active;
+ bool defaultBackground;
+ bool drawn;
+ eRecMenuState action;
+ tColor colorText;
+ tColor colorTextBack;
+ const cFont *font;
+ const cFont *fontSmall;
+ const cFont *fontLarge;
+public:
+ cRecMenuItem(void);
+ virtual ~cRecMenuItem(void);
+ void SetGeometry(int x, int y, int width);
+ virtual void SetPixmaps(void);
+ virtual int GetHeight(void) { return height; };
+ virtual int GetWidth(void) { return 0; };
+ virtual void CalculateHeight(int textWidth) {};
+ virtual void setActive(void) { this->active = true; }
+ virtual void setInactive(void) { this->active = false; }
+ bool isSelectable(void) { return selectable; }
+ bool isActive(void) { return active; }
+ virtual void setBackground(void);
+ virtual void Draw(void) {};
+ virtual void Hide(void) { if (pixmap) pixmap->SetLayer(-1);};
+ virtual void Show(void) { if (pixmap) pixmap->SetLayer(4);};
+ virtual int GetIntValue(void) { return -1; };
+ virtual time_t GetTimeValue(void) { return 0; };
+ virtual bool GetBoolValue(void) { return false; };
+ virtual cString GetStringValue(void) { return cString(""); };
+ virtual const cEvent *GetEventValue(void) { return NULL; };
+ virtual cTimer *GetTimerValue(void) { return NULL; };
+ virtual eRecMenuState ProcessKey(eKeys Key) { return rmsNotConsumed; };
+};
+
+// --- cRecMenuItemButton -------------------------------------------------------
+class cRecMenuItemButton : public cRecMenuItem {
+private:
+ cString text;
+ bool halfWidth;
+ bool alignLeft;
+ const cFont *fontButtons;
+ cPixmap *pixmapText;
+public:
+ cRecMenuItemButton(const char *text, eRecMenuState action, bool active, bool halfWidth = false, bool alignLeft = false, bool largeFont = false);
+ virtual ~cRecMenuItemButton(void);
+ int GetWidth(void);
+ void SetPixmaps(void);
+ void Draw(void);
+ void Hide(void);
+ void Show(void);
+ cString GetStringValue(void) { return text; };
+ eRecMenuState ProcessKey(eKeys Key);
+};
+
+// --- cRecMenuItemButtonYesNo -------------------------------------------------------
+class cRecMenuItemButtonYesNo : public cRecMenuItem {
+private:
+ cString textYes;
+ cString textNo;
+ eRecMenuState actionNo;
+ bool yesActive;
+ cStyledPixmap *pixmapNo;
+ tColor colorTextNo;
+ tColor colorTextNoBack;
+public:
+ cRecMenuItemButtonYesNo(cString textYes,
+ cString textNo,
+ eRecMenuState actionYes,
+ eRecMenuState actionNo,
+ bool active);
+ virtual ~cRecMenuItemButtonYesNo(void);
+ void SetPixmaps(void);
+ void setBackground(void);
+ void Hide(void);
+ void Show(void);
+ eRecMenuState ProcessKey(eKeys Key);
+ void Draw(void);
+};
+
+// --- cRecMenuItemInfo -------------------------------------------------------
+class cRecMenuItemInfo : public cRecMenuItem {
+private:
+ cString text;
+ cTextWrapper wrapper;
+ int border;
+ const cFont *fontInfo;
+public:
+ cRecMenuItemInfo(const char *text, bool largeFont = false);
+ virtual ~cRecMenuItemInfo(void);
+ void setBackground(void);
+ void CalculateHeight(int textWidth);
+ void Draw(void);
+};
+
+// --- cRecMenuItemInt -------------------------------------------------------
+class cRecMenuItemInt : public cRecMenuItem {
+private:
+ cString text;
+ int currentVal;
+ int *callback;
+ int minVal;
+ int maxVal;
+ cPixmap *pixmapVal;
+ bool fresh;
+ void DrawValue(void);
+public:
+ cRecMenuItemInt(cString text,
+ int initialVal,
+ int minVal,
+ int maxVal,
+ bool active = false,
+ int *callback = NULL,
+ eRecMenuState action = rmsNotConsumed);
+ virtual ~cRecMenuItemInt(void);
+ void SetPixmaps(void);
+ void Hide(void);
+ void Show(void);
+ void setBackground(void);
+ eRecMenuState ProcessKey(eKeys Key);
+ void Draw(void);
+ int GetIntValue(void) { return currentVal; };
+};
+
+// --- cRecMenuItemBool -------------------------------------------------------
+class cRecMenuItemBool : public cRecMenuItem {
+private:
+ cString text;
+ bool yes;
+ bool *callback;
+ cPixmap *pixmapVal;
+ bool refresh;
+ void DrawValue(void);
+public:
+ cRecMenuItemBool(cString text,
+ bool initialVal,
+ bool refresh = false,
+ bool active = false,
+ bool *callback = NULL,
+ eRecMenuState action = rmsNotConsumed);
+ virtual ~cRecMenuItemBool(void);
+ void SetPixmaps(void);
+ void Hide(void);
+ void Show(void);
+ eRecMenuState ProcessKey(eKeys Key);
+ void Draw(void);
+ bool GetBoolValue(void) { return yes; };
+};
+
+// --- cRecMenuItemSelect -------------------------------------------------------
+class cRecMenuItemSelect : public cRecMenuItem {
+private:
+ cString text;
+ int currentVal;
+ int *callback;
+ std::vector<std::string> strings;
+ int numValues;
+ cPixmap *pixmapVal;
+ void DrawValue(void);
+public:
+ cRecMenuItemSelect(cString text,
+ std::vector<std::string> Strings,
+ int initialVal,
+ bool active = false,
+ int *callback = NULL,
+ eRecMenuState action = rmsNotConsumed);
+ virtual ~cRecMenuItemSelect(void);
+ void SetPixmaps(void);
+ void Hide(void);
+ void Show(void);
+ eRecMenuState ProcessKey(eKeys Key);
+ void Draw(void);
+ int GetIntValue(void) { return currentVal; };
+ cString GetStringValue(void) { return strings[currentVal].c_str(); };
+};
+
+// --- cRecMenuItemSelectDirectory -------------------------------------------------------
+class cRecMenuItemSelectDirectory : public cRecMenuItem {
+private:
+ cString text;
+ std::string originalFolder;
+ std::vector<std::string> folders;
+ int currentVal;
+ char *callback;
+ int numValues;
+ cPixmap *pixmapVal;
+ void DrawValue(void);
+ int GetInitial(void);
+ void SetCallback(void);
+public:
+ cRecMenuItemSelectDirectory(cString text,
+ std::string originalFolder,
+ bool active = false,
+ char *callback = NULL,
+ eRecMenuState action = rmsNotConsumed,
+ bool isSearchTimer = false);
+ virtual ~cRecMenuItemSelectDirectory(void);
+ void SetPixmaps(void);
+ void Hide(void);
+ void Show(void);
+ eRecMenuState ProcessKey(eKeys Key);
+ void Draw(void);
+};
+
+// --- cRecMenuItemText -------------------------------------------------------
+class cRecMenuItemText : public cRecMenuItem {
+private:
+ cString title;
+ char *value;
+ char *callback;
+ int length;
+ const char *allowed;
+ int pos, offset;
+ bool insert, newchar, uppercase;
+ int lengthUtf8;
+ uint *valueUtf8;
+ uint *allowedUtf8;
+ uint *charMapUtf8;
+ uint *currentCharUtf8;
+ eKeys lastKey;
+ cTimeMs autoAdvanceTimeout;
+ cPixmap *pixmapVal;
+ cStyledPixmap *pixmapKeyboard;
+ cPixmap *pixmapKeyboardHighlight;
+ cPixmap *pixmapKeyboardIcons;
+ int keyboardWidth;
+ int gridWidth;
+ int gridHeight;
+ int keyboardHeight;
+ bool keyboardDrawn;
+ uint *IsAllowed(uint c);
+ void AdvancePos(void);
+ uint Inc(uint c, bool Up);
+ void Type(uint c);
+ void Insert(void);
+ void Delete(void);
+ void EnterEditMode(void);
+ void LeaveEditMode(bool SaveValue = false);
+ bool InEditMode(void) { return valueUtf8 != NULL; };
+ void SetText(void);
+ void ActivateKeyboard(void);
+ void DeactivateKeyboard(void);
+ void HighlightSMSKey(int num);
+ void ClearSMSKey(void);
+ char *GetSMSKeys(int num);
+ void DrawValue(char *newValue);
+public:
+ cRecMenuItemText(cString title,
+ char *initialVal,
+ int length,
+ bool active = false,
+ char *callback = NULL);
+ virtual ~cRecMenuItemText(void);
+ void SetPixmaps(void);
+ void Hide(void);
+ void Show(void);
+ void setBackground(void);
+ eRecMenuState ProcessKey(eKeys Key);
+ void Draw(void);
+ cString GetStringValue(void) { return value; };
+};
+
+
+// --- cRecMenuItemTime -------------------------------------------------------
+class cRecMenuItemTime : public cRecMenuItem {
+private:
+ cString text;
+ int value;
+ int *callback;
+ int mm;
+ int hh;
+ int pos;
+ bool fresh;
+ cPixmap *pixmapVal;
+ void DrawValue(void);
+public:
+ cRecMenuItemTime(cString text,
+ int initialVal,
+ bool active = false,
+ int *callback = NULL,
+ eRecMenuState action = rmsNotConsumed);
+ virtual ~cRecMenuItemTime(void);
+ void SetPixmaps(void);
+ void Hide(void);
+ void Show(void);
+ eRecMenuState ProcessKey(eKeys Key);
+ void Draw(void);
+ int GetIntValue(void) { return value; };
+};
+
+// --- cRecMenuItemDay -------------------------------------------------------
+class cRecMenuItemDay : public cRecMenuItem {
+private:
+ cString text;
+ time_t currentVal;
+ time_t *callback;
+ cPixmap *pixmapVal;
+ void DrawValue(void);
+public:
+ cRecMenuItemDay(cString text,
+ time_t initialVal,
+ bool active = false,
+ time_t *callback = NULL,
+ eRecMenuState action = rmsNotConsumed);
+ virtual ~cRecMenuItemDay(void);
+ void SetPixmaps(void);
+ void Hide(void);
+ void Show(void);
+ eRecMenuState ProcessKey(eKeys Key);
+ void Draw(void);
+ time_t GetTimeValue(void) { return currentVal; };
+};
+
+// --- cRecMenuItemTimer -------------------------------------------------------
+class cRecMenuItemTimer : public cRecMenuItem {
+private:
+ const cTimer *timer;
+ eRecMenuState action2;
+ eRecMenuState action3;
+ eRecMenuState action4;
+ int iconActive;
+ cPixmap *pixmapIcons;
+ cPixmap *pixmapStatus;
+ time_t conflictStart;
+ time_t conflictStop;
+ time_t overlapStart;
+ time_t overlapStop;
+ int DrawIcons(void);
+ void DrawTimerConflict(void);
+public:
+ cRecMenuItemTimer(const cTimer *timer,
+ eRecMenuState action1,
+ eRecMenuState action2,
+ eRecMenuState action3,
+ eRecMenuState action4,
+ time_t conflictStart,
+ time_t conflictStop,
+ time_t overlapStart,
+ time_t overlapStop,
+ bool active);
+ virtual ~cRecMenuItemTimer(void);
+ void SetPixmaps(void);
+ void Hide(void);
+ void Show(void);
+ eRecMenuState ProcessKey(eKeys Key);
+ void Draw(void);
+};
+
+// --- cRecMenuItemTimerConflictHeader -------------------------------------------------------
+
+class cRecMenuItemTimerConflictHeader: public cRecMenuItem {
+private:
+ cPixmap *pixmapStatus;
+ time_t conflictStart;
+ time_t conflictStop;
+ time_t overlapStart;
+ time_t overlapStop;
+public:
+ cRecMenuItemTimerConflictHeader(time_t conflictStart,
+ time_t conflictStop,
+ time_t overlapStart,
+ time_t overlapStop);
+ virtual ~cRecMenuItemTimerConflictHeader(void);
+ void SetPixmaps(void);
+ void Hide(void);
+ void Show(void);
+ void setBackground(void);
+ void Draw(void);
+};
+
+// --- cRecMenuItemEvent -------------------------------------------------------
+class cRecMenuItemEvent : public cRecMenuItem {
+private:
+ const cEvent *event;
+ eRecMenuState action2;
+ int iconActive;
+ cPixmap *pixmapText;
+ cPixmap *pixmapIcons;
+ int DrawIcons(void);
+public:
+ cRecMenuItemEvent(const cEvent *event,
+ eRecMenuState action1,
+ eRecMenuState action2,
+ bool active);
+ virtual ~cRecMenuItemEvent(void);
+ void SetPixmaps(void);
+ void Hide(void);
+ void Show(void);
+ const cEvent *GetEventValue(void) { return event; };
+ eRecMenuState ProcessKey(eKeys Key);
+ void Draw(void);
+};
+
+// --- cRecMenuItemChannelChooser -------------------------------------------------------
+class cRecMenuItemChannelChooser : public cRecMenuItem {
+private:
+ cString text;
+ cChannel *channel;
+ int channelNumber;
+ int *callback;
+ bool initialChannelSet;
+ bool fresh;
+ cPixmap *pixmapChannel;
+ void DrawValue(void);
+public:
+ cRecMenuItemChannelChooser (cString text,
+ cChannel *initialChannel,
+ bool active = false,
+ int *callback = NULL,
+ eRecMenuState action = rmsNotConsumed);
+ virtual ~cRecMenuItemChannelChooser(void);
+ void SetPixmaps(void);
+ void Hide(void);
+ void Show(void);
+ eRecMenuState ProcessKey(eKeys Key);
+ void Draw(void);
+ int GetIntValue(void);
+};
+
+// --- cRecMenuItemDayChooser -------------------------------------------------------
+class cRecMenuItemDayChooser : public cRecMenuItem {
+private:
+ cString text;
+ int weekdays;
+ int *callback;
+ bool epgsearchMode;
+ std::string days;
+ int daysX;
+ int daysY;
+ int daysSize;
+ int selectedDay;
+ cPixmap *pixmapWeekdays;
+ cPixmap *pixmapWeekdaysSelect;
+ void SetSizes(void);
+ void DrawDays(void);
+ void DrawHighlight(int day);
+ void ToggleDay(void);
+ bool WeekDaySet(unsigned day);
+public:
+ cRecMenuItemDayChooser (cString text,
+ int weekdays,
+ bool active = false,
+ int *callback = NULL);
+ virtual ~cRecMenuItemDayChooser(void);
+ void SetPixmaps(void);
+ void Hide(void);
+ void Show(void);
+ void setBackground(void);
+ eRecMenuState ProcessKey(eKeys Key);
+ void Draw(void);
+ int GetIntValue(void) { return weekdays;} ;
+};
+
+// --- cRecMenuItemRecording -------------------------------------------------------
+class cRecMenuItemRecording : public cRecMenuItem {
+private:
+ cRecording *recording;
+ cPixmap *pixmapText;
+public:
+ cRecMenuItemRecording(cRecording *recording, bool active);
+ virtual ~cRecMenuItemRecording(void);
+ void SetPixmaps(void);
+ void Hide(void);
+ void Show(void);
+ void Draw(void);
+};
+
+// --- cRecMenuItemTimelineHeader -------------------------------------------------------
+class cRecMenuItemTimelineHeader : public cRecMenuItem {
+private:
+ time_t day;
+ cTimer *timer;
+ std::vector<cTVGuideTimerConflict*> conflicts;
+ cPixmap *pixmapTimeline;
+ cPixmap *pixmapTimerInfo;
+ cPixmap *pixmapTimerConflicts;
+ int width5Mins;
+ int x0;
+ bool timelineDrawn;
+ void DrawTimeline(void);
+ void DrawTimerConflicts(void);
+ void DrawCurrentTimer(void);
+public:
+ cRecMenuItemTimelineHeader(time_t day, std::vector<cTVGuideTimerConflict*> conflictsToday);
+ virtual ~cRecMenuItemTimelineHeader(void);
+ void SetDay(time_t day) { this->day = day; };
+ void SetPixmaps(void);
+ void SetCurrentTimer(cTimer *timer) { this->timer = timer; };
+ void UnsetCurrentTimer(void) { timer = NULL; };
+ void RefreshTimerDisplay(void);
+ void Hide(void);
+ void Show(void);
+ void Draw(void);
+};
+
+// --- cRecMenuItemTimelineTimer -------------------------------------------------------
+class cRecMenuItemTimelineTimer : public cRecMenuItem {
+private:
+ cTimer *timer;
+ std::vector<cTVGuideTimerConflict*> conflicts;
+ cPixmap *pixmapBack;
+ cPixmap *pixmapTimerConflicts;
+ cRecMenuItemTimelineHeader *header;
+ int x0;
+ int width5Mins;
+ time_t start;
+ time_t stop;
+ void DrawBackground(void);
+ void DrawTimerBar(void);
+ void DrawTimeScale(void);
+ void DrawTimerConflicts(void);
+ void DrawNoTimerInfo(void);
+public:
+ cRecMenuItemTimelineTimer(cTimer *timer, time_t start, time_t stop, std::vector<cTVGuideTimerConflict*> conflictsToday, cRecMenuItemTimelineHeader *header, bool active);
+ virtual ~cRecMenuItemTimelineTimer(void);
+ void setActive(void);
+ void setInactive(void);
+ void SetPixmaps(void);
+ void Hide(void);
+ void Show(void);
+ void Draw(void);
+ cTimer *GetTimerValue(void);
+ eRecMenuState ProcessKey(eKeys Key);
+};
+
+// --- cRecMenuItemSearchTimer -------------------------------------------------------
+class cRecMenuItemSearchTimer : public cRecMenuItem {
+private:
+ cTVGuideSearchTimer timer;
+ eRecMenuState action1;
+ eRecMenuState action2;
+ eRecMenuState action3;
+ int iconActive;
+ cPixmap *pixmapText;
+ cPixmap *pixmapIcons;
+ int DrawIcons(void);
+public:
+ cRecMenuItemSearchTimer(cTVGuideSearchTimer timer,
+ eRecMenuState action1,
+ eRecMenuState action2,
+ eRecMenuState action3,
+ bool active);
+ virtual ~cRecMenuItemSearchTimer(void);
+ void SetPixmaps(void);
+ void Hide(void);
+ void Show(void);
+ void Draw(void);
+ cTVGuideSearchTimer GetTimer(void) { return timer; };
+ eRecMenuState ProcessKey(eKeys Key);
+};
+
+// --- cRecMenuItemFavorite -------------------------------------------------------
+class cRecMenuItemFavorite : public cRecMenuItem {
+private:
+ cTVGuideSearchTimer favorite;
+ eRecMenuState action1;
+ cPixmap *pixmapText;
+ cPixmap *pixmapIcons;
+ int DrawIcons(void);
+public:
+ cRecMenuItemFavorite(cTVGuideSearchTimer favorite,
+ eRecMenuState action1,
+ bool active);
+ virtual ~cRecMenuItemFavorite(void);
+ void SetPixmaps(void);
+ void Hide(void);
+ void Show(void);
+ void Draw(void);
+ cTVGuideSearchTimer GetFavorite(void) { return favorite; };
+ eRecMenuState ProcessKey(eKeys Key);
+};
+
+// --- cRecMenuItemFavoriteStatic -------------------------------------------------------
+class cRecMenuItemFavoriteStatic : public cRecMenuItem {
+private:
+ std::string text;
+ cPixmap *pixmapText;
+ cPixmap *pixmapIcons;
+ int DrawIcons(void);
+public:
+ cRecMenuItemFavoriteStatic(std::string text, eRecMenuState action, bool active);
+ virtual ~cRecMenuItemFavoriteStatic(void);
+ void SetPixmaps(void);
+ void Hide(void);
+ void Show(void);
+ void Draw(void);
+ eRecMenuState ProcessKey(eKeys Key);
+};
+
+#endif //__TVGUIDE_RECMENUITEM_H
\ No newline at end of file
diff --git a/recmenumanager.c b/recmenumanager.c
new file mode 100644
index 0000000..edabf4d
--- /dev/null
+++ b/recmenumanager.c
@@ -0,0 +1,893 @@
+#include "recmenu.h"
+#include "recmenus.h"
+#include "switchtimer.h"
+#include "timerconflict.h"
+#include "recmenumanager.h"
+
+cRecMenuManager::cRecMenuManager(void) {
+ footer = NULL;
+ active = false;
+ activeMenu = NULL;
+ activeMenuBuffer = NULL;
+ activeMenuBuffer2 = NULL;
+ recManager = new cRecManager();
+ recManager->SetEPGSearchPlugin();
+ timerConflicts = NULL;
+ detailViewActive = false;
+}
+
+cRecMenuManager::~cRecMenuManager(void) {
+ if (activeMenu) {
+ active = false;
+ delete activeMenu;
+ activeMenu = NULL;
+ }
+ if (timerConflicts) {
+ delete timerConflicts;
+ timerConflicts = NULL;
+ }
+ delete recManager;
+}
+
+void cRecMenuManager::Start(const cEvent *event) {
+ active = true;
+ activeMenuBuffer = NULL;
+ detailViewActive = false;
+ SetBackground();
+ this->event = event;
+ activeMenu = new cRecMenuMain(recManager->EpgSearchAvailable(), recManager->CheckEventForTimer(event), SwitchTimers.EventInSwitchList(event));
+ activeMenu->Display();
+ osdManager.flush();
+}
+
+void cRecMenuManager::StartFavorites(void) {
+ active = true;
+ activeMenuBuffer = NULL;
+ detailViewActive = false;
+ SetBackground();
+ std::vector<cTVGuideSearchTimer> favorites;
+ recManager->GetFavorites(&favorites);
+ activeMenu = new cRecMenuFavorites(favorites);
+ activeMenu->Display();
+ osdManager.flush();
+}
+
+
+void cRecMenuManager::Close(void) {
+ event = NULL;
+ active = false;
+ if (activeMenu) {
+ delete activeMenu;
+ activeMenu = NULL;
+ }
+ if (timerConflicts) {
+ delete timerConflicts;
+ timerConflicts = NULL;
+ }
+ DeleteBackground();
+}
+
+void cRecMenuManager::SetBackground(void) {
+ int backgroundWidth = geoManager.osdWidth;
+ int backgroundHeight = geoManager.osdHeight;
+ pixmapBackground = osdManager.requestPixmap(3, cRect(0, 0, backgroundWidth, backgroundHeight));
+ pixmapBackground->Fill(theme.Color(clrRecMenuBackground));
+ if (tvguideConfig.scaleVideo) {
+ int tvHeight = geoManager.statusHeaderHeight;
+ int tvWidth = tvHeight * 16 / 9;
+ int tvX = geoManager.osdWidth - tvWidth;
+ pixmapBackground->DrawRectangle(cRect(tvX, 0, tvWidth, tvHeight), clrTransparent);
+ }
+}
+
+void cRecMenuManager::DeleteBackground(void) {
+ osdManager.releasePixmap(pixmapBackground);
+}
+
+eOSState cRecMenuManager::StateMachine(eRecMenuState nextState) {
+ eOSState state = osContinue;
+ switch (nextState) {
+ /***************************************************************************************
+ * INSTANT RECORDING
+ ****************************************************************************************/
+ case rmsInstantRecord: {
+ //caller: main menu or folder chooser
+ //Creating timer for active Event, if no conflict, confirm and exit
+ std::string recFolder = "";
+ if (cRecMenuAskFolder *menu = dynamic_cast<cRecMenuAskFolder*>(activeMenu)) {
+ recFolder = menu->GetFolder();
+ }
+ delete activeMenu;
+ cTimer *timer = recManager->createTimer(event, recFolder);
+ if (!DisplayTimerConflict(timer)) {
+ activeMenu = new cRecMenuConfirmTimer(event);
+ activeMenu->Display();
+ }
+ break; }
+ case rmsInstantRecordFolder:
+ //caller: main menu
+ //Asking for Folder
+ delete activeMenu;
+ activeMenu = new cRecMenuAskFolder(event, rmsInstantRecord);
+ activeMenu->Display();
+ break;
+ case rmsIgnoreTimerConflict:
+ //caller: cRecMenuTimerConflict
+ //Confirming created Timer
+ delete activeMenu;
+ activeMenu = new cRecMenuConfirmTimer(event);
+ activeMenu->Display();
+ break;
+ case rmsTimerConflictShowInfo: {
+ //caller: cRecMenuTimerConflict
+ int timerIndex;
+ if (cRecMenuTimerConflict *menu = dynamic_cast<cRecMenuTimerConflict*>(activeMenu)) {
+ timerIndex = menu->GetTimerConflictIndex();
+ } else break;
+ int timerID = timerConflicts->GetCurrentConflictTimerID(timerIndex);
+ cTimer *t = Timers.Get(timerID);
+ if (t) {
+ const cEvent *ev = t->Event();
+ if (ev) {
+ DisplayDetailedView(ev);
+ }
+ }
+ break; }
+ case rmsDeleteTimerConflictMenu: {
+ //caller: cRecMenuTimerConflict
+ //delete timer out of current timer conflict
+ int timerIndex;
+ if (cRecMenuTimerConflict *menu = dynamic_cast<cRecMenuTimerConflict*>(activeMenu)) {
+ timerIndex = menu->GetTimerConflictIndex();
+ } else break;
+ int timerID = timerConflicts->GetCurrentConflictTimerID(timerIndex);
+ recManager->DeleteTimer(timerID);
+ delete activeMenu;
+ if (!DisplayTimerConflict(timerID)) {
+ activeMenu = new cRecMenuConfirmTimer(event);
+ activeMenu->Display();
+ }
+ break; }
+ case rmsEditTimerConflictMenu: {
+ //caller: cRecMenuTimerConflict
+ //edit timer out of current timer conflict
+ int timerIndex;
+ if (cRecMenuTimerConflict *menu = dynamic_cast<cRecMenuTimerConflict*>(activeMenu)) {
+ timerIndex = menu->GetTimerConflictIndex();
+ } else break;
+ int timerID = timerConflicts->GetCurrentConflictTimerID(timerIndex);
+ cTimer *timer = Timers.Get(timerID);
+ if (timer) {
+ delete activeMenu;
+ activeMenu = new cRecMenuEditTimer(timer, rmsSaveTimerConflictMenu);
+ activeMenu->Display();
+ }
+ break; }
+ case rmsSaveTimerConflictMenu: {
+ //caller: cRecMenuEditTimer
+ //save timer from current timer conflict
+ cTimer timerModified;
+ cTimer *originalTimer;
+ if (cRecMenuEditTimer *menu = dynamic_cast<cRecMenuEditTimer*>(activeMenu)) {
+ timerModified = menu->GetTimer();
+ originalTimer = menu->GetOriginalTimer();
+ } else break;
+ recManager->SaveTimer(originalTimer, timerModified);
+ delete activeMenu;
+ if (!DisplayTimerConflict(originalTimer)) {
+ activeMenu = new cRecMenuConfirmTimer(event);
+ activeMenu->Display();
+ }
+ break; }
+ case rmsDeleteTimer:
+ //caller: main menu
+ //delete timer for active event
+ delete activeMenu;
+ if (recManager->IsRecorded(event)) {
+ activeMenu = new cRecMenuAskDeleteTimer(event);
+ } else {
+ recManager->DeleteTimer(event);
+ activeMenu = new cRecMenuConfirmDeleteTimer(event);
+ }
+ activeMenu->Display();
+ break;
+ case rmsDeleteTimerConfirmation:
+ //delete running timer for active event
+ recManager->DeleteTimer(event);
+ delete activeMenu;
+ activeMenu = new cRecMenuConfirmDeleteTimer(event);
+ activeMenu->Display();
+ break;
+ case rmsEditTimer: {
+ //edit timer for active event
+ cTimer *timer = recManager->GetTimerForEvent(event);
+ if (timer) {
+ delete activeMenu;
+ activeMenu = new cRecMenuEditTimer(timer, rmsSaveTimer);
+ activeMenu->Display();
+ }
+ break; }
+ case rmsSaveTimer: {
+ //caller: cRecMenuEditTimer
+ //save timer for active event
+ cTimer timerModified;
+ cTimer *originalTimer;
+ if (cRecMenuEditTimer *menu = dynamic_cast<cRecMenuEditTimer*>(activeMenu)) {
+ timerModified = menu->GetTimer();
+ originalTimer = menu->GetOriginalTimer();
+ } else break;
+ recManager->SaveTimer(originalTimer, timerModified);
+ state = osEnd;
+ Close();
+ break; }
+ /***************************************************************************************
+ * SERIES TIMER
+ ****************************************************************************************/
+ case rmsSeriesTimer: {
+ //caller: main menu oder folder chooser
+ std::string recFolder = "";
+ if (cRecMenuAskFolder *menu = dynamic_cast<cRecMenuAskFolder*>(activeMenu)) {
+ recFolder = menu->GetFolder();
+ }
+ delete activeMenu;
+ cChannel *channel = Channels.GetByChannelID(event->ChannelID());
+ activeMenu = new cRecMenuSeriesTimer(channel, event, recFolder);
+ activeMenu->Display();
+ break; }
+ case rmsSeriesTimerFolder:
+ //caller: main menu
+ //Asking for Folder
+ delete activeMenu;
+ activeMenu = new cRecMenuAskFolder(event, rmsSeriesTimer);
+ activeMenu->Display();
+ break;
+ case rmsSeriesTimerCreate: {
+ //caller: cRecMenuSeriesTimer
+ cTimer *seriesTimer;
+ if (cRecMenuSeriesTimer *menu = dynamic_cast<cRecMenuSeriesTimer*>(activeMenu)) {
+ seriesTimer = menu->GetTimer();
+ } else break;
+ recManager->CreateSeriesTimer(seriesTimer);
+ delete activeMenu;
+ activeMenu = new cRecMenuConfirmSeriesTimer(seriesTimer);
+ activeMenu->Display();
+ break; }
+ /**********************************************************************************************
+ * SEARCH TIMER
+ ***********************************************************************************************/
+ case rmsSearchTimer:
+ //Caller: main menu
+ //set search String for search timer
+ delete activeMenu;
+ activeMenu = new cRecMenuSearchTimer(event);
+ activeMenu->Display();
+ break;
+ case rmsSearchTimerOptions: {
+ //Caller: cRecMenuSearchTimer, cRecMenuSearchTimerTemplates
+ //Choose to set options manually or by template
+ std::string searchString;
+ cTVGuideSearchTimer searchTimer;
+ bool reload = false;
+ if (cRecMenuSearchTimer *menu = dynamic_cast<cRecMenuSearchTimer*>(activeMenu)) {
+ searchString = menu->GetSearchString();
+ } else if (cRecMenuSearchTimerTemplatesCreate *menu = dynamic_cast<cRecMenuSearchTimerTemplatesCreate*>(activeMenu)) {
+ searchTimer = menu->GetSearchTimer();
+ reload = true;
+ } else break;
+ delete activeMenu;
+ if (searchString.size() < 4) {
+ activeMenu = new cRecMenuSearchTimer(event);
+ } else {
+ if (!reload) {
+ searchTimer.SetSearchString(searchString);
+ }
+ std::vector<TVGuideEPGSearchTemplate> epgSearchTemplates;
+ recManager->ReadEPGSearchTemplates(&epgSearchTemplates);
+ if (epgSearchTemplates.size() > 0) {
+ activeMenu = new cRecMenuSearchTimerTemplates(searchTimer, epgSearchTemplates);
+ } else {
+ activeMenu = new cRecMenuSearchTimerEdit(searchTimer, false);
+ }
+ }
+ activeMenu->Display();
+ break; }
+ case rmsSearchTimers: {
+ //caller: main menu
+ DisplaySearchTimerList();
+ break; }
+ case rmsSearchTimerEdit:
+ case rmsSearchTimerEditAdvanced: {
+ //caller: cRecMenuSearchTimers, cRecMenuSearchTimerEdit, cRecMenuSearchTimerTemplates
+ cTVGuideSearchTimer searchTimer;
+ bool advancedOptions = false;
+ if (cRecMenuSearchTimers *menu = dynamic_cast<cRecMenuSearchTimers*>(activeMenu)) {
+ searchTimer = menu->GetSearchTimer();
+ } else if (cRecMenuSearchTimerEdit *menu = dynamic_cast<cRecMenuSearchTimerEdit*>(activeMenu)) {
+ searchTimer = menu->GetSearchTimer();
+ advancedOptions = (nextState == rmsSearchTimerEditAdvanced)?true:false;
+ } else if (cRecMenuSearchTimerTemplates *menu = dynamic_cast<cRecMenuSearchTimerTemplates*>(activeMenu)) {
+ searchTimer = menu->GetSearchTimer();
+ } else break;
+ delete activeMenu;
+ activeMenu = new cRecMenuSearchTimerEdit(searchTimer, advancedOptions);
+ activeMenu->Display();
+ break; }
+ case rmsSearchTimerTest: {
+ //caller: cRecMenuSearchTimerEdit, cRecMenuSearchTimerTemplatesCreate, cRecMenuSearchTimers, cRecMenuFavorites
+ //show results of currently choosen search timer
+ cTVGuideSearchTimer searchTimer;
+ eRecMenuState recState = rmsDisabled;
+ if (cRecMenuSearchTimerEdit *menu = dynamic_cast<cRecMenuSearchTimerEdit*>(activeMenu)) {
+ searchTimer = menu->GetSearchTimer();
+ recState = rmsSearchTimerRecord;
+ } else if (cRecMenuSearchTimers *menu = dynamic_cast<cRecMenuSearchTimers*>(activeMenu)) {
+ searchTimer = menu->GetSearchTimer();
+ recState = rmsSearchTimerRecord;
+ } else if (cRecMenuSearchTimerTemplatesCreate *menu = dynamic_cast<cRecMenuSearchTimerTemplatesCreate*>(activeMenu)) {
+ searchTimer = menu->GetSearchTimer();
+ TVGuideEPGSearchTemplate tmpl = menu->GetTemplate();
+ searchTimer.SetTemplate(tmpl.templValue);
+ searchTimer.Parse(true);
+ } else if (cRecMenuFavorites *menu = dynamic_cast<cRecMenuFavorites*>(activeMenu)) {
+ searchTimer = menu->GetFavorite();
+ recState = rmsFavoritesRecord;
+ } else break;
+ int numSearchResults = 0;
+ std::string searchString = searchTimer.BuildSearchString();
+ const cEvent **searchResult = recManager->PerformSearchTimerSearch(searchString, numSearchResults);
+ if (numSearchResults) {
+ activeMenuBuffer = activeMenu;
+ activeMenuBuffer->Hide();
+ activeMenu = new cRecMenuSearchTimerResults(searchTimer.SearchString(), searchResult, numSearchResults, "", recState);
+ activeMenu->Display();
+ } else {
+ activeMenuBuffer = activeMenu;
+ activeMenuBuffer->Hide();
+ activeMenu = new cRecMenuSearchTimerNothingFound(searchTimer.SearchString());
+ activeMenu->Display();
+ }
+ break; }
+ case rmsSearchTimerSave: {
+ //caller: cRecMenuSearchTimerEdit, cRecMenuSearchTimerTemplatesCreate
+ //create new or modify existing search timer
+ cTVGuideSearchTimer searchTimer;
+ if (cRecMenuSearchTimerEdit *menu = dynamic_cast<cRecMenuSearchTimerEdit*>(activeMenu)) {
+ searchTimer = menu->GetSearchTimer();
+ } else if (cRecMenuSearchTimerTemplatesCreate *menu = dynamic_cast<cRecMenuSearchTimerTemplatesCreate*>(activeMenu)) {
+ searchTimer = menu->GetSearchTimer();
+ TVGuideEPGSearchTemplate tmpl = menu->GetTemplate();
+ searchTimer.SetTemplate(tmpl.templValue);
+ searchTimer.Parse(true);
+ } else break;
+ bool success = recManager->SaveSearchTimer(&searchTimer);
+ recManager->UpdateSearchTimers();
+ if (searchTimer.GetID() >= 0) {
+ //Timer modified, show list
+ DisplaySearchTimerList();
+ } else {
+ //new timer, confirm
+ delete activeMenu;
+ activeMenu = new cRecMenuSearchTimerCreateConfirm(success);
+ activeMenu->Display();
+ }
+ break; }
+ case rmsSearchTimerCreateWithTemplate: {
+ //caller: cRecMenuSearchTimerTemplates
+ //create new search timer from template
+ TVGuideEPGSearchTemplate templ;
+ cTVGuideSearchTimer searchTimer;
+ if (cRecMenuSearchTimerTemplates *menu = dynamic_cast<cRecMenuSearchTimerTemplates*>(activeMenu)) {
+ templ = menu->GetTemplate();
+ searchTimer = menu->GetSearchTimer();
+ } else break;
+ delete activeMenu;
+ activeMenu = new cRecMenuSearchTimerTemplatesCreate(templ, searchTimer);
+ activeMenu->Display();
+ break; }
+ case rmsSearchTimerDeleteConfirm: {
+ //caller: cRecMenuSearchTimers
+ //Ask for confirmation and if timers created by this search timer should alo be deleted
+ cTVGuideSearchTimer searchTimer;
+ if (cRecMenuSearchTimers *menu = dynamic_cast<cRecMenuSearchTimers*>(activeMenu)) {
+ searchTimer = menu->GetSearchTimer();
+ } else break;
+ activeMenuBuffer = activeMenu;
+ activeMenuBuffer->Hide();
+ activeMenu = new cRecMenuSearchTimerDeleteConfirm(searchTimer);
+ activeMenu->Display();
+ break; }
+ case rmsSearchTimerDelete:
+ case rmsSearchTimerDeleteWithTimers: {
+ //caller: cRecMenuSearchTimerDeleteConfirm
+ //actually delete searchtimer
+ cTVGuideSearchTimer searchTimer;
+ if (cRecMenuSearchTimerDeleteConfirm *menu = dynamic_cast<cRecMenuSearchTimerDeleteConfirm*>(activeMenu)) {
+ searchTimer = menu->GetSearchTimer();
+ } else break;
+ bool delTimers = (nextState==rmsSearchTimerDeleteWithTimers)?true:false;
+ recManager->DeleteSearchTimer(&searchTimer, delTimers);
+ delete activeMenuBuffer;
+ activeMenuBuffer = NULL;
+ DisplaySearchTimerList();
+ break; }
+ case rmsSearchTimerRecord: {
+ //caller: cRecMenuSearchTimerResults
+ const cEvent *ev = NULL;
+ if (cRecMenuSearchTimerResults *menu = dynamic_cast<cRecMenuSearchTimerResults*>(activeMenu)) {
+ ev = menu->GetEvent();
+ } else break;
+ if (!ev)
+ break;
+ recManager->createTimer(ev, "");
+ activeMenuBuffer2 = activeMenu;
+ activeMenuBuffer2->Hide();
+ activeMenu = new cRecMenuSearchConfirmTimer(ev, rmsFavoritesRecordConfirm);
+ activeMenu->Display();
+ break; }
+ /**********************************************************************************************
+ * SWITCH TIMER
+ ***********************************************************************************************/
+ case rmsSwitchTimer:
+ delete activeMenu;
+ activeMenu = new cRecMenuSwitchTimer();
+ activeMenu->Display();
+ break;
+ case rmsSwitchTimerCreate: {
+ cSwitchTimer switchTimer;
+ if (cRecMenuSwitchTimer *menu = dynamic_cast<cRecMenuSwitchTimer*>(activeMenu)) {
+ switchTimer = menu->GetSwitchTimer();
+ } else break;
+ bool success = recManager->CreateSwitchTimer(event, switchTimer);
+ delete activeMenu;
+ activeMenu = new cRecMenuSwitchTimerConfirm(success);
+ activeMenu->Display();
+ break; }
+ case rmsSwitchTimerDelete:
+ recManager->DeleteSwitchTimer(event);
+ delete activeMenu;
+ activeMenu = new cRecMenuSwitchTimerDelete();
+ activeMenu->Display();
+ break;
+ /**********************************************************************************************
+ * RECORDINGS SEARCH
+ ***********************************************************************************************/
+ case rmsRecordingSearch: {
+ //caller: main menu or rmsRecordingSearchResult
+ std::string searchString = event->Title();
+ if (cRecMenuRecordingSearchResults *menu = dynamic_cast<cRecMenuRecordingSearchResults*>(activeMenu)) {
+ searchString = menu->GetSearchString();
+ };
+ delete activeMenu;
+ activeMenu = new cRecMenuRecordingSearch(searchString);
+ activeMenu->Display();
+ break; }
+ case rmsRecordingSearchResult: {
+ //caller: cRecMenuRecordingSearch
+ std::string searchString;
+ if (cRecMenuRecordingSearch *menu = dynamic_cast<cRecMenuRecordingSearch*>(activeMenu)) {
+ searchString = menu->GetSearchString();
+ } else break;
+ delete activeMenu;
+ if (searchString.size() < 4) {
+ activeMenu = new cRecMenuRecordingSearch(searchString);
+ } else {
+ int numSearchResults = 0;
+ cRecording **searchResult = recManager->SearchForRecordings(searchString, numSearchResults);
+ if (numSearchResults == 0) {
+ activeMenu = new cRecMenuRecordingSearchNotFound(searchString);
+ } else {
+ activeMenu = new cRecMenuRecordingSearchResults(searchString, searchResult, numSearchResults);
+ }
+ }
+ activeMenu->Display();
+ break; }
+ /**********************************************************************************************
+ * SEARCH
+ ***********************************************************************************************/
+ case rmsSearch:
+ case rmsSearchWithOptions: {
+ //caller: main menu, cRecMenuSearch, cRecMenuSearchResults
+ bool withOptions = false;
+ std::string searchString = event->Title();
+ if (cRecMenuSearch *menu = dynamic_cast<cRecMenuSearch*>(activeMenu)) {
+ withOptions = true;
+ searchString = menu->GetSearchString();
+ } else if (cRecMenuSearchResults *menu = dynamic_cast<cRecMenuSearchResults*>(activeMenu)) {
+ searchString = menu->GetSearchString();
+ }
+ delete activeMenu;
+ activeMenu = new cRecMenuSearch(searchString, withOptions);
+ activeMenu->Display();
+ break; }
+ case rmsSearchPerform: {
+ //caller: cRecMenuSearch
+ Epgsearch_searchresults_v1_0 epgSearchData;
+ if (cRecMenuSearch *menu = dynamic_cast<cRecMenuSearch*>(activeMenu)) {
+ epgSearchData = menu->GetEPGSearchStruct();
+ } else break;
+ std::string searchString = epgSearchData.query;
+ if (searchString.size() < 3) {
+ activeMenuBuffer = activeMenu;
+ activeMenuBuffer->Hide();
+ activeMenu = new cRecMenuSearchNothingFound(searchString, true);
+ } else {
+ int numSearchResults = 0;
+ const cEvent **searchResult = recManager->PerformSearch(epgSearchData, numSearchResults);
+ if (searchResult) {
+ delete activeMenu;
+ activeMenu = new cRecMenuSearchResults(searchString, searchResult, numSearchResults);
+ } else {
+ activeMenuBuffer = activeMenu;
+ activeMenuBuffer->Hide();
+ activeMenu = new cRecMenuSearchNothingFound(searchString);
+ }
+ }
+ activeMenu->Display();
+ break; }
+ case rmsSearchNothingFoundConfirm:
+ delete activeMenu;
+ activeMenu = activeMenuBuffer;
+ activeMenuBuffer = NULL;
+ activeMenu->Show();
+ break;
+ case rmsSearchShowInfo: {
+ //caller: cRecMenuSearchResults, cRecMenuSearchTimerResults
+ const cEvent *ev = NULL;
+ if (cRecMenuSearchResults *menu = dynamic_cast<cRecMenuSearchResults*>(activeMenu)) {
+ ev = menu->GetEvent();
+ } else if (cRecMenuSearchTimerResults *menu = dynamic_cast<cRecMenuSearchTimerResults*>(activeMenu)) {
+ ev = menu->GetEvent();
+ } else break;
+ if (ev) {
+ DisplayDetailedView(ev);
+ }
+ break;}
+ case rmsSearchRecord: {
+ //caller: cRecMenuSearchResults
+ const cEvent *ev = NULL;
+ if (cRecMenuSearchResults *menu = dynamic_cast<cRecMenuSearchResults*>(activeMenu)) {
+ ev = menu->GetEvent();
+ } else break;
+ if (!ev)
+ break;
+ recManager->createTimer(ev, "");
+ activeMenuBuffer = activeMenu;
+ activeMenuBuffer->Hide();
+ activeMenu = new cRecMenuSearchConfirmTimer(ev, rmsSearchRecordConfirm);
+ activeMenu->Display();
+ break;}
+ case rmsSearchRecordConfirm:
+ delete activeMenu;
+ activeMenu = activeMenuBuffer;
+ activeMenuBuffer = NULL;
+ activeMenu->UpdateActiveMenuItem();
+ activeMenu->Show();
+ break;
+ /**********************************************************************************************
+ * CHECK FOR TIMER CONFLICTS
+ ***********************************************************************************************/
+ case rmsTimerConflicts: {
+ //caller: main menu
+ //Show timer conflict
+ if (timerConflicts) {
+ delete timerConflicts;
+ }
+ timerConflicts = recManager->CheckTimerConflict();
+ delete activeMenu;
+ int numConflicts = timerConflicts->NumConflicts();
+ if (numConflicts > 0) {
+ activeMenu = new cRecMenuTimerConflicts(timerConflicts);
+ } else {
+ activeMenu = new cRecMenuNoTimerConflict();
+ }
+ activeMenu->Display();
+ break; }
+ case rmsTimerConflict: {
+ //caller: cRecMenuTimerConflicts
+ //Show timer conflict
+ if (!timerConflicts)
+ break;
+ int timerConflict;
+ if (cRecMenuTimerConflicts *menu = dynamic_cast<cRecMenuTimerConflicts*>(activeMenu)) {
+ timerConflict = menu->GetTimerConflict();
+ } else break;
+ timerConflicts->SetCurrentConflict(timerConflict);
+ delete activeMenu;
+ activeMenu = new cRecMenuTimerConflict(timerConflicts->GetCurrentConflict());
+ activeMenu->Display();
+ break; }
+ case rmsSearchRerunsTimerConflictMenu: {
+ //caller: cRecMenuTimerConflict
+ //Show reruns for timer from timer conflict
+ if (!timerConflicts)
+ break;
+ int timerConflict;
+ if (cRecMenuTimerConflict *menu = dynamic_cast<cRecMenuTimerConflict*>(activeMenu)) {
+ timerConflict = menu->GetTimerConflictIndex();
+ } else break;
+ int timerID = timerConflicts->GetCurrentConflictTimerID(timerConflict);
+ cTimer *timer = Timers.Get(timerID);
+ if (timer) {
+ const cEvent *event = timer->Event();
+ if (event) {
+ int numReruns = 0;
+ const cEvent **reruns = recManager->LoadReruns(event, numReruns);
+ if (reruns && (numReruns > 0)) {
+ activeMenuBuffer = activeMenu;
+ activeMenuBuffer->Hide();
+ activeMenu = new cRecMenuRerunResults(event, reruns, numReruns);
+ activeMenu->Display();
+ } else {
+ activeMenuBuffer = activeMenu;
+ activeMenuBuffer->Hide();
+ activeMenu = new cRecMenuNoRerunsFound((event->Title())?event->Title():"");
+ activeMenu->Display();
+ }
+ }
+ }
+ break; }
+ case rmsTimerConflictIgnoreReruns: {
+ delete activeMenu;
+ activeMenu = activeMenuBuffer;
+ activeMenuBuffer = NULL;
+ activeMenu->Show();
+ break; }
+ case rmsTimerConflictRecordRerun: {
+ //caller: cRecMenuRerunResults
+ //buffer: cRecMenuTimerConflict
+ if (!activeMenuBuffer)
+ break;
+ if (!timerConflicts)
+ break;
+ const cEvent *replace;
+ int originalConflictIndex;
+ if (cRecMenuRerunResults *menu = dynamic_cast<cRecMenuRerunResults*>(activeMenu)) {
+ replace = menu->GetRerunEvent();
+ } else break;
+ if (cRecMenuTimerConflict *menu = dynamic_cast<cRecMenuTimerConflict*>(activeMenuBuffer)) {
+ originalConflictIndex = menu->GetTimerConflictIndex();
+ } else break;
+ int originalTimerID = timerConflicts->GetCurrentConflictTimerID(originalConflictIndex);
+ cTimer *timerOriginal = Timers.Get(originalTimerID);
+ if (replace && timerOriginal) {
+ recManager->DeleteTimer(timerOriginal->Event());
+ recManager->createTimer(replace);
+ delete activeMenu;
+ if (activeMenuBuffer) {
+ delete activeMenuBuffer;
+ activeMenuBuffer = NULL;
+ }
+ activeMenu = new cRecMenuConfirmRerunUsed(timerOriginal->Event(), replace);
+ activeMenu->Display();
+ }
+ break; }
+ /**********************************************************************************************
+ * TIMELINE
+ ***********************************************************************************************/
+ case rmsTimeline: {
+ if (timerConflicts) {
+ delete timerConflicts;
+ }
+ timerConflicts = recManager->CheckTimerConflict();
+ delete activeMenu;
+ activeMenu = new cRecMenuTimeline(timerConflicts);
+ activeMenu->Display();
+ break; }
+ case rmsTimelineTimerEdit: {
+ cTimer *timer;
+ if (cRecMenuTimeline *menu = dynamic_cast<cRecMenuTimeline*>(activeMenu)) {
+ timer = menu->GetTimer();
+ } else break;
+ if (timer) {
+ delete activeMenu;
+ activeMenu = new cRecMenuEditTimer(timer, rmsTimelineTimerSave);
+ activeMenu->Display();
+ }
+ break;}
+ case rmsTimelineTimerSave: {
+ cTimer timerModified;
+ cTimer *originalTimer;
+ if (cRecMenuEditTimer *menu = dynamic_cast<cRecMenuEditTimer*>(activeMenu)) {
+ timerModified = menu->GetTimer();
+ originalTimer = menu->GetOriginalTimer();
+ } else break;
+ recManager->SaveTimer(originalTimer, timerModified);
+ delete activeMenu;
+ if (timerConflicts) {
+ delete timerConflicts;
+ }
+ timerConflicts = recManager->CheckTimerConflict();
+ activeMenu = new cRecMenuTimeline(timerConflicts);
+ activeMenu->Display();
+ break; }
+ case rmsTimelineTimerDelete: {
+ cTimer *timer;
+ if (cRecMenuEditTimer *menu = dynamic_cast<cRecMenuEditTimer*>(activeMenu)) {
+ timer = menu->GetOriginalTimer();
+ } else break;
+ recManager->DeleteTimer(timer);
+ delete activeMenu;
+ if (timerConflicts) {
+ delete timerConflicts;
+ }
+ timerConflicts = recManager->CheckTimerConflict();
+ activeMenu = new cRecMenuTimeline(timerConflicts);
+ activeMenu->Display();
+ break; }
+ /**********************************************************************************************
+ * FAVORITES
+ *********************************************************************************************/
+ case rmsFavoritesRecord: {
+ //caller: cRecMenuSearchTimerResults
+ const cEvent *ev = NULL;
+ if (cRecMenuSearchTimerResults *menu = dynamic_cast<cRecMenuSearchTimerResults*>(activeMenu)) {
+ ev = menu->GetEvent();
+ } else break;
+ if (!ev)
+ break;
+ recManager->createTimer(ev, "");
+ activeMenuBuffer2 = activeMenu;
+ activeMenuBuffer2->Hide();
+ activeMenu = new cRecMenuSearchConfirmTimer(ev, rmsFavoritesRecordConfirm);
+ activeMenu->Display();
+ break;}
+ case rmsFavoritesRecordConfirm:
+ delete activeMenu;
+ activeMenu = activeMenuBuffer2;
+ activeMenuBuffer2 = NULL;
+ activeMenu->UpdateActiveMenuItem();
+ activeMenu->Show();
+ break;
+ case rmsFavoritesNow:
+ case rmsFavoritesNext: {
+ int numResults = 0;
+ bool nowOrNext;
+ std::string header;
+ if (nextState == rmsFavoritesNow) {
+ nowOrNext = true;
+ header = tr("What's on now");
+ } else {
+ nowOrNext = false;
+ header = tr("What's on next");
+ }
+ const cEvent **result = recManager->WhatsOnNow(nowOrNext, numResults);
+ DisplayFavoriteResults(header, result, numResults);
+ break; }
+ case rmsFavoritesUser1: {
+ int numResults = 0;
+ const cEvent **result = recManager->UserDefinedTime(1, numResults);
+ DisplayFavoriteResults(tvguideConfig.descUser1, result, numResults);
+ break; }
+ case rmsFavoritesUser2: {
+ int numResults = 0;
+ const cEvent **result = recManager->UserDefinedTime(2, numResults);
+ DisplayFavoriteResults(tvguideConfig.descUser2, result, numResults);
+ break; }
+ case rmsFavoritesUser3: {
+ int numResults = 0;
+ const cEvent **result = recManager->UserDefinedTime(3, numResults);
+ DisplayFavoriteResults(tvguideConfig.descUser3, result, numResults);
+ break; }
+ case rmsFavoritesUser4: {
+ int numResults = 0;
+ const cEvent **result = recManager->UserDefinedTime(4, numResults);
+ DisplayFavoriteResults(tvguideConfig.descUser4, result, numResults);
+ break; }
+
+ /**********************************************************************************************
+ * COMMON
+ *********************************************************************************************/
+ case rmsClose: {
+ if (activeMenuBuffer == NULL) {
+ state = osEnd;
+ Close();
+ } else {
+ delete activeMenu;
+ activeMenu = activeMenuBuffer;
+ activeMenuBuffer = NULL;
+ activeMenu->UpdateActiveMenuItem();
+ activeMenu->Show();
+ state = osContinue;
+ }
+ break; }
+ default:
+ break;
+ }
+ return state;
+}
+
+void cRecMenuManager::DisplayFavoriteResults(std::string header, const cEvent **result, int numResults) {
+ if (numResults) {
+ activeMenuBuffer = activeMenu;
+ activeMenuBuffer->Hide();
+ activeMenu = new cRecMenuSearchTimerResults(header, result, numResults, "", rmsFavoritesRecord);
+ activeMenu->Display();
+ } else {
+ activeMenuBuffer = activeMenu;
+ activeMenuBuffer->Hide();
+ activeMenu = new cRecMenuSearchTimerNothingFound(header);
+ activeMenu->Display();
+ }
+}
+
+void cRecMenuManager::DisplaySearchTimerList(void) {
+ delete activeMenu;
+ std::vector<cTVGuideSearchTimer> searchTimers;
+ recManager->GetSearchTimers(&searchTimers);
+ activeMenu = new cRecMenuSearchTimers(searchTimers);
+ activeMenu->Display();
+}
+
+bool cRecMenuManager::DisplayTimerConflict(cTimer *timer) {
+ int timerID = 0;
+ for (cTimer *t = Timers.First(); t; t = Timers.Next(t)) {
+ if (t == timer)
+ return DisplayTimerConflict(timerID);
+ timerID++;
+ }
+ return false;
+}
+
+bool cRecMenuManager::DisplayTimerConflict(int timerID) {
+ if (timerConflicts)
+ delete timerConflicts;
+ timerConflicts = recManager->CheckTimerConflict();
+ if (!timerConflicts)
+ return false;
+ int showTimerConflict = timerConflicts->GetCorrespondingConflict(timerID);
+ if (showTimerConflict > -1) {
+ timerConflicts->SetCurrentConflict(showTimerConflict);
+ cTVGuideTimerConflict *conflict = timerConflicts->GetCurrentConflict();
+ if (!conflict)
+ return false;
+ activeMenu = new cRecMenuTimerConflict(conflict);
+ activeMenu->Display();
+ return true;
+ }
+ return false;
+}
+
+void cRecMenuManager::DisplayDetailedView(const cEvent *ev) {
+ activeMenu->Hide();
+ detailView = new cDetailView(ev, footer);
+ footer->SetDetailedViewMode(true);
+ detailView->Start();
+ detailViewActive = true;
+}
+
+eOSState cRecMenuManager::ProcessKey(eKeys Key) {
+ eOSState state = osContinue;
+ eRecMenuState nextState = rmsContinue;
+ if (!activeMenu)
+ return state;
+ if (detailViewActive) {
+ state = detailView->ProcessKey(Key);
+ if (state == osEnd) {
+ delete detailView;
+ detailView = NULL;
+ detailViewActive = false;
+ activeMenu->Show();
+ state = osContinue;
+ }
+ } else {
+ nextState = activeMenu->ProcessKey(Key);
+ if ((nextState == rmsClose) || ((nextState == rmsNotConsumed)&&(Key == kBack))){
+ if (activeMenuBuffer == NULL) {
+ state = osEnd;
+ Close();
+ } else {
+ delete activeMenu;
+ activeMenu = activeMenuBuffer;
+ activeMenuBuffer = NULL;
+ activeMenu->UpdateActiveMenuItem();
+ activeMenu->Show();
+ state = osContinue;
+ osdManager.flush();
+ }
+ return state;
+ }
+ state = StateMachine(nextState);
+ }
+ osdManager.flush();
+ return state;
+}
\ No newline at end of file
diff --git a/recmenumanager.h b/recmenumanager.h
new file mode 100644
index 0000000..9448c12
--- /dev/null
+++ b/recmenumanager.h
@@ -0,0 +1,42 @@
+#ifndef __TVGUIDE_RECMENUMANAGER_H
+#define __TVGUIDE_RECMENUMANAGER_H
+
+#include "recmenu.h"
+#include "recmanager.h"
+#include "services/epgsearch.h"
+#include "footer.h"
+
+// --- cRecMenuManager -------------------------------------------------------------
+class cRecMenuManager {
+private:
+ cFooter *footer;
+ bool active;
+ cRecMenu *activeMenu;
+ cRecMenu *activeMenuBuffer;
+ cRecMenu *activeMenuBuffer2;
+ const cEvent *event;
+ cRecManager *recManager;
+ cTVGuideTimerConflicts *timerConflicts;
+ cDetailView *detailView;
+ cPixmap *pixmapBackground;
+ bool detailViewActive;
+ void SetBackground(void);
+ void DeleteBackground(void);
+ void DisplaySearchTimerList(void);
+ bool DisplayTimerConflict(cTimer *timer);
+ bool DisplayTimerConflict(int timerID);
+ void DisplayDetailedView(const cEvent *ev);
+ void DisplayFavoriteResults(std::string header, const cEvent **result, int numResults);
+public:
+ cRecMenuManager(void);
+ virtual ~cRecMenuManager(void);
+ void SetFooter(cFooter *footer) { this->footer = footer; };
+ bool isActive(void) { return active; };
+ void Start(const cEvent *event);
+ void StartFavorites(void);
+ void Close(void);
+ eOSState StateMachine(eRecMenuState nextState);
+ eOSState ProcessKey(eKeys Key);
+};
+
+#endif //__TVGUIDE_RECMENUMANAGER_H
\ No newline at end of file
diff --git a/recmenus.c b/recmenus.c
new file mode 100644
index 0000000..701ffd9
--- /dev/null
+++ b/recmenus.c
@@ -0,0 +1,1561 @@
+#include "services/remotetimers.h"
+#include "tools.h"
+#include "recmenumanager.h"
+#include "recmenus.h"
+
+// --- cRecMenuMain ---------------------------------------------------------
+cRecMenuMain::cRecMenuMain(bool epgSearchAvailable, bool timerActive, bool switchTimerActive) {
+ eRecMenuState action = rmsInstantRecord;
+ if (!timerActive) {
+ if (tvguideConfig.instRecFolderMode == eFolderSelect)
+ action = rmsInstantRecordFolder;
+ AddMenuItem(new cRecMenuItemButton(tr("Instant Record"), action, true, false, false, true));
+ } else {
+ AddMenuItem(new cRecMenuItemButton(tr("Delete Timer"), rmsDeleteTimer, true, false, false, true));
+ AddMenuItem(new cRecMenuItemButton(tr("Edit Timer"), rmsEditTimer, false, false, false, true));
+ }
+
+ AddMenuItem(new cRecMenuItemButton(tr("Timer Timeline"), rmsTimeline, false, false, false, true));
+
+ if (epgSearchAvailable) {
+ AddMenuItem(new cRecMenuItemButton(tr("Create Search Timer"), rmsSearchTimer, false, false, false, true));
+ AddMenuItem(new cRecMenuItemButton(tr("Search Timers"), rmsSearchTimers, false, false, false, true));
+ }
+
+ if (tvguideConfig.instRecFolderMode == eFolderSelect)
+ action = rmsSeriesTimerFolder;
+ else
+ action = rmsSeriesTimer;
+ AddMenuItem(new cRecMenuItemButton(tr("Create Series Timer"), action, false, false, false, true));
+
+ if (epgSearchAvailable) {
+ if (!switchTimerActive) {
+ AddMenuItem(new cRecMenuItemButton(tr("Create Switch Timer"), rmsSwitchTimer, false, false, false, true));
+ } else {
+ AddMenuItem(new cRecMenuItemButton(tr("Delete Switch Timer"), rmsSwitchTimerDelete, false, false, false, true));
+ }
+ AddMenuItem(new cRecMenuItemButton(tr("Search"), rmsSearch, false, false, false, true));
+ }
+
+ if (epgSearchAvailable) {
+ AddMenuItem(new cRecMenuItemButton(tr("Check for Timer Conflicts"), rmsTimerConflicts, false, false, false, true));
+ }
+
+ AddMenuItem(new cRecMenuItemButton(tr("Search in Recordings"), rmsRecordingSearch, false, false, false, true));
+
+ int menuWidth = CalculateOptimalWidth() + 4 * border;
+ SetWidthPixel(menuWidth);
+
+ CalculateHeight();
+ CreatePixmap();
+ Arrange();
+};
+
+/******************************************************************************************
+* Instant Timer Menus
+******************************************************************************************/
+
+// --- cRecMenuAskFolder ---------------------------------------------------------
+cRecMenuAskFolder::cRecMenuAskFolder(const cEvent *event, eRecMenuState nextAction) {
+ SetWidthPercent(80);
+ NextAction = nextAction;
+ cString message = tr("Set Folder for");
+ cString headerText = cString::sprintf("%s\n\"%s\"", *message, event->Title());
+ cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*headerText, true);
+ infoItem->CalculateHeight(width - 2 * border);
+ SetHeader(infoItem);
+
+ AddMenuItemInitial(new cRecMenuItemButton(tr("root video folder"), nextAction, true, false, true));
+
+ ReadRecordingDirectories(&folders, NULL, "");
+ int numFolders = folders.size();
+ for (int i=0; i < numFolders; i++) {
+ if (!AddMenuItemInitial(new cRecMenuItemButton(folders[i].c_str(), nextAction, false, false, true)))
+ break;
+ }
+
+ CalculateHeight();
+ CreatePixmap();
+ Arrange();
+}
+
+cRecMenuItem *cRecMenuAskFolder::GetMenuItem(int number) {
+ if (number == 0) {
+ cRecMenuItem *result = new cRecMenuItemButton(tr("root video folder"), rmsInstantRecord, false, false, true);
+ return result;
+ } else if ((number > 0) && (number < folders.size()+1)) {
+ cRecMenuItem *result = new cRecMenuItemButton(folders[number-1].c_str(), rmsInstantRecord, false, false, true);
+ return result;
+ }
+ return NULL;
+}
+
+int cRecMenuAskFolder::GetTotalNumMenuItems(void) {
+ return folders.size()+1;
+}
+
+std::string cRecMenuAskFolder::GetFolder(void) {
+ std::string folder = "";
+ int folderActive = GetActive();
+ if (folderActive > 0 && folderActive < folders.size() + 1)
+ folder = folders[folderActive - 1];
+ return folder;
+}
+
+// --- cRecMenuConfirmTimer ---------------------------------------------------------
+cRecMenuConfirmTimer::cRecMenuConfirmTimer(const cEvent *event) {
+ SetWidthPercent(50);
+ cString channelName = Channels.GetByChannelID(event->ChannelID())->Name();
+ cString message;
+ bool eventHasTimer = false;
+ if (tvguideConfig.useRemoteTimers && pRemoteTimers) {
+ RemoteTimers_GetMatch_v1_0 rtMatch;
+ rtMatch.event = event;
+ pRemoteTimers->Service("RemoteTimers::GetMatch-v1.0", &rtMatch);
+ if (rtMatch.timerMatch == tmFull) {
+ eventHasTimer = true;
+ }
+ } else {
+ eventHasTimer = event->HasTimer();
+ }
+ if (eventHasTimer) {
+ message = tr("Timer created");
+ } else {
+ message = tr("Timer NOT created");
+ }
+ cString text = cString::sprintf("%s\n%s\n%s %s - %s\n%s",
+ *message,
+ *channelName,
+ *event->GetDateString(),
+ *event->GetTimeString(),
+ *event->GetEndTimeString(),
+ event->Title()
+ );
+ cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*text);
+ infoItem->CalculateHeight(width - 2 * border);
+ AddMenuItem(infoItem);
+ AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsClose, true, true));
+ CalculateHeight();
+ CreatePixmap();
+ Arrange();
+}
+
+// --- cRecMenuConfirmDeleteTimer ---------------------------------------------------------
+cRecMenuConfirmDeleteTimer::cRecMenuConfirmDeleteTimer(const cEvent *event) {
+ SetWidthPercent(50);
+ cString channelName = Channels.GetByChannelID(event->ChannelID())->Name();
+ cString text = cString::sprintf("%s\n%s\n%s %s - %s\n%s",
+ tr("Timer deleted"),
+ *channelName,
+ *event->GetDateString(),
+ *event->GetTimeString(),
+ *event->GetEndTimeString(),
+ event->Title()
+ );
+ cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*text);
+ infoItem->CalculateHeight(width - 4 * border);
+ AddMenuItem(infoItem);
+ AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsClose, true, true));
+
+ CalculateHeight();
+ CreatePixmap();
+ Arrange();
+}
+
+// --- cRecMenuAskDeleteTimer ---------------------------------------------------------
+cRecMenuAskDeleteTimer::cRecMenuAskDeleteTimer(const cEvent *event) {
+ SetWidthPercent(50);
+ cString channelName = Channels.GetByChannelID(event->ChannelID())->Name();
+ cString text = cString::sprintf("%s \"%s, %s\" %s",
+ tr("Timer"),
+ *channelName,
+ event->Title(),
+ tr("still recording - really delete?"));
+ cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*text);
+ infoItem->CalculateHeight(width - 4 * border);
+ AddMenuItem(infoItem);
+ AddMenuItem(new cRecMenuItemButtonYesNo(tr("Yes"), tr("No"), rmsDeleteTimerConfirmation, rmsClose, true));
+ CalculateHeight();
+ CreatePixmap();
+ Arrange();
+}
+
+// --- cRecMenuTimerConflicts ---------------------------------------------------------
+cRecMenuTimerConflicts::cRecMenuTimerConflicts(cTVGuideTimerConflicts *conflicts) {
+ int numConflicts = conflicts->NumConflicts();
+
+ cString text;
+ if (numConflicts == 1) {
+ text = cString::sprintf("%s %s %s", tr("One"), tr("Timer Conflict"), tr("detected"));
+ } else {
+ text = cString::sprintf("%d %s %s", conflicts->NumConflicts(), tr("Timer Conflicts"), tr("detected"));
+ }
+ cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*text, true);
+
+ for (int i=0; i<numConflicts; i++) {
+ cTVGuideTimerConflict *conflict = conflicts->GetConflict(i);
+ if (!conflict)
+ continue;
+ cString dateTime = DayDateTime(conflict->time);
+ int numTimers = conflict->timerIDs.size();
+ cString textConflict = cString::sprintf("%s: %s (%d %s)", tr("Show conflict"), *dateTime, numTimers, tr("timers involved"));
+ bool isActive = (i==0)?true:false;
+ AddMenuItem(new cRecMenuItemButton(*textConflict, rmsTimerConflict, isActive));
+ }
+
+ SetWidthPixel(CalculateOptimalWidth() + 4*border);
+ infoItem->CalculateHeight(width - 2 * border);
+ SetHeader(infoItem);
+ AddMenuItem(new cRecMenuItemButton(tr("Ignore Conflicts"), rmsClose, false));
+
+ CalculateHeight();
+ CreatePixmap();
+ Arrange();
+}
+
+int cRecMenuTimerConflicts::GetTimerConflict(void) {
+ return GetActive();
+}
+
+// --- cRecMenuTimerConflict ---------------------------------------------------------
+cRecMenuTimerConflict::cRecMenuTimerConflict(cTVGuideTimerConflict *conflict) {
+ SetWidthPercent(95);
+ this->conflict = conflict;
+ SetHeader(new cRecMenuItemTimerConflictHeader(conflict->timeStart,
+ conflict->timeStop,
+ conflict->overlapStart,
+ conflict->overlapStop));
+ SetFooter(new cRecMenuItemButton(tr("Ignore Conflict"), rmsIgnoreTimerConflict, false, true));
+ int i=0;
+ for(std::vector<int>::iterator it = conflict->timerIDs.begin(); it != conflict->timerIDs.end(); it++) {
+ const cTimer *timer = Timers.Get(*it);
+ if (timer) {
+ if (!AddMenuItemInitial(new cRecMenuItemTimer( timer,
+ rmsTimerConflictShowInfo,
+ rmsDeleteTimerConflictMenu,
+ rmsEditTimerConflictMenu,
+ rmsSearchRerunsTimerConflictMenu,
+ conflict->timeStart,
+ conflict->timeStop,
+ conflict->overlapStart,
+ conflict->overlapStop,
+ (!i)?true:false)
+ ))
+ break;
+ i++;
+ }
+ }
+ CalculateHeight();
+ CreatePixmap();
+ Arrange();
+}
+
+cRecMenuItem *cRecMenuTimerConflict::GetMenuItem(int number) {
+ if ((number >= 0) && (number < conflict->timerIDs.size())) {
+ const cTimer *timer = Timers.Get(conflict->timerIDs[number]);
+ cRecMenuItem *result = new cRecMenuItemTimer( timer,
+ rmsTimerConflictShowInfo,
+ rmsDeleteTimerConflictMenu,
+ rmsEditTimerConflictMenu,
+ rmsSearchRerunsTimerConflictMenu,
+ conflict->timeStart,
+ conflict->timeStop,
+ conflict->overlapStart,
+ conflict->overlapStop,
+ false);
+ return result;
+ }
+ return NULL;
+}
+
+int cRecMenuTimerConflict::GetTotalNumMenuItems(void) {
+ return conflict->timerIDs.size();
+}
+
+int cRecMenuTimerConflict::GetTimerConflictIndex(void) {
+ return GetActive();
+}
+
+// --- cRecMenuNoTimerConflict ---------------------------------------------------------
+cRecMenuNoTimerConflict::cRecMenuNoTimerConflict(void) {
+ SetWidthPercent(50);
+ cString text = tr("No Timer Conflicts found");
+ cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*text);
+ infoItem->CalculateHeight(width - 4 * border);
+ AddMenuItem(infoItem);
+ AddMenuItem(new cRecMenuItemButton(tr("Close"), rmsClose, true));
+ CalculateHeight();
+ CreatePixmap();
+ Arrange();
+}
+
+// --- cRecMenuRerunResults ---------------------------------------------------------
+cRecMenuRerunResults::cRecMenuRerunResults(const cEvent *original, const cEvent **reruns, int numReruns) {
+ this->reruns = reruns;
+ this->numReruns = numReruns;
+ SetWidthPercent(70);
+ this->numReruns = numReruns;
+ cString message1 = tr("reruns for");
+ cString message2 = tr("rerun for");
+ cString message3 = tr("found");
+ cString infoText = cString::sprintf("%d %s:\n\"%s\" %s", numReruns, (numReruns>1)?(*message1):(*message2), original->Title(), *message3);
+ cRecMenuItem *infoItem = new cRecMenuItemInfo(*infoText, true);
+ infoItem->CalculateHeight(width - 2 * border);
+ SetHeader(infoItem);
+
+ cRecMenuItem *button = new cRecMenuItemButton(tr("Ignore reruns"), rmsTimerConflictIgnoreReruns, false);
+ SetFooter(button);
+
+ if (reruns && (numReruns > 0)) {
+ for (int i=0; i<numReruns; i++) {
+ if (!AddMenuItemInitial(new cRecMenuItemEvent(reruns[i], rmsSearchShowInfo, rmsTimerConflictRecordRerun, (i==0)?true:false)))
+ break;
+ }
+ }
+ CalculateHeight();
+ CreatePixmap();
+ Arrange();
+}
+
+cRecMenuItem *cRecMenuRerunResults::GetMenuItem(int number) {
+ if ((number >= 0) && (number < numReruns)) {
+ cRecMenuItem *result = new cRecMenuItemEvent(reruns[number], rmsSearchShowInfo, rmsTimerConflictRecordRerun, false);
+ return result;
+ }
+ return NULL;
+}
+
+int cRecMenuRerunResults::GetTotalNumMenuItems(void) {
+ return numReruns;
+}
+
+const cEvent *cRecMenuRerunResults::GetRerunEvent(void) {
+ cRecMenuItemEvent *activeItem = dynamic_cast<cRecMenuItemEvent*>(GetActiveMenuItem());
+ return activeItem->GetEventValue();
+}
+
+// --- cRecMenuNoRerunsFound ---------------------------------------------------------
+cRecMenuNoRerunsFound::cRecMenuNoRerunsFound(cString searchString) {
+ SetWidthPercent(50);
+ cString message = tr("No reruns found for Event");
+ cString text = cString::sprintf("%s\n\"%s\"",
+ *message,
+ *searchString);
+ cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*text);
+ infoItem->CalculateHeight(width - 2 * border);
+ AddMenuItem(infoItem);
+ AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsTimerConflictIgnoreReruns, true, true));
+ CalculateHeight();
+ CreatePixmap();
+ Arrange();
+}
+
+// --- cRecMenuConfirmRerunUsed ---------------------------------------------------------
+cRecMenuConfirmRerunUsed::cRecMenuConfirmRerunUsed(const cEvent *original, const cEvent *replace) {
+ SetWidthPercent(70);
+ cString channelOrig = Channels.GetByChannelID(original->ChannelID())->Name();
+ cString channelReplace = Channels.GetByChannelID(replace->ChannelID())->Name();
+ cString message1 = tr("Timer for");
+ cString message2 = tr("replaced by rerun");
+ cString text = cString::sprintf("%s\n\"%s\", %s %s, %s\n%s\n\"%s\", %s %s, %s",
+ *message1,
+ original->Title(),
+ *original->GetDateString(),
+ *original->GetTimeString(),
+ *channelOrig,
+ *message2,
+ replace->Title(),
+ *replace->GetDateString(),
+ *replace->GetTimeString(),
+ *channelReplace);
+ cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*text);
+ infoItem->CalculateHeight(width - 2 * border);
+ AddMenuItem(infoItem);
+ AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsTimerConflicts, true, true));
+ CalculateHeight();
+ CreatePixmap();
+ Arrange();
+}
+
+// --- cRecMenuEditTimer ---------------------------------------------------------
+cRecMenuEditTimer::cRecMenuEditTimer(cTimer *timer, eRecMenuState nextState) {
+ SetWidthPercent(70);
+ if (!timer)
+ return;
+ originalTimer = timer;
+ cString title("");
+ cString channelName("");
+ if (timer->Event())
+ title = timer->Event()->Title();
+ if (timer->Channel())
+ channelName = timer->Channel()->Name();
+ cString infoText = cString::sprintf("%s:\n %s, %s", tr("Edit Timer"), *title, *channelName);
+ cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*infoText, true);
+ infoItem->CalculateHeight(width - 2 * border);
+ AddMenuItemInitial(infoItem);
+
+ timerActive = false;
+ if (tvguideConfig.useRemoteTimers && pRemoteTimers) {
+ RemoteTimers_GetMatch_v1_0 rtMatch;
+ rtMatch.event = timer->Event();
+ pRemoteTimers->Service("RemoteTimers::GetMatch-v1.0", &rtMatch);
+ if (rtMatch.timer) {
+ if (rtMatch.timerMatch == tmFull)
+ timerActive = true;
+ }
+ } else
+ timerActive = timer->HasFlags(tfActive);
+
+ day = timer->Day();
+ start = timer->Start();
+ stop = timer->Stop();
+ prio = timer->Priority();
+ lifetime = timer->Lifetime();
+ strncpy(folder, GetDirectoryFromTimer(timer->File()).c_str(), TEXTINPUTLENGTH);
+
+ AddMenuItemInitial(new cRecMenuItemBool(tr("Timer Active"), timerActive, false, true, &timerActive));
+ AddMenuItemInitial(new cRecMenuItemInt(tr("Priority"), prio, 0, MAXPRIORITY, false, &prio));
+ AddMenuItemInitial(new cRecMenuItemInt(tr("Lifetime"), lifetime, 0, MAXLIFETIME, false, &lifetime));
+ AddMenuItemInitial(new cRecMenuItemDay(tr("Day"), day, false, &day));
+ AddMenuItemInitial(new cRecMenuItemTime(tr("Timer start time"), start, false, &start));
+ AddMenuItemInitial(new cRecMenuItemTime(tr("Timer stop time"), stop, false, &stop));
+ cString fileInfo = cString::sprintf("%s:\n%s", tr("Timer File"), timer->File());
+ cRecMenuItemInfo *fileInfoItem = new cRecMenuItemInfo(*fileInfo, false);
+ fileInfoItem->CalculateHeight(width - 2 * border);
+ AddMenuItemInitial(fileInfoItem);
+ AddMenuItemInitial(new cRecMenuItemSelectDirectory(tr("New Folder"), std::string(folder), false, folder));
+ if (nextState == rmsTimelineTimerSave) {
+ AddMenuItemInitial(new cRecMenuItemButton(tr("Delete Timer"), rmsTimelineTimerDelete, false, false));
+ AddMenuItemInitial(new cRecMenuItemButtonYesNo(tr("Save"), tr("Cancel"), nextState, rmsTimeline, false));
+ } else {
+ AddMenuItemInitial(new cRecMenuItemButtonYesNo(tr("Save"), tr("Cancel"), nextState, rmsClose, false));
+ }
+ CalculateHeight();
+ CreatePixmap();
+ Arrange();
+}
+
+cTimer *cRecMenuEditTimer::GetOriginalTimer(void) {
+ return originalTimer;
+}
+
+cTimer cRecMenuEditTimer::GetTimer(void) {
+ cTimer t;
+ if (timerActive)
+ t.SetFlags(tfActive);
+ else
+ t.SetFlags(tfNone);
+ t.SetDay(day);
+ t.SetStart(start);
+ t.SetStop(stop);
+ t.SetPriority(prio);
+ t.SetLifetime(lifetime);
+ std::string newFolder(folder);
+ std::string newFile = originalTimer->File();
+ size_t found = newFile.find_last_of('~');
+ if (found != std::string::npos) {
+ std::string fileName = newFile.substr(found+1);
+ if (newFolder.size() > 0)
+ newFile = *cString::sprintf("%s~%s", newFolder.c_str(), fileName.c_str());
+ else
+ newFile = fileName;
+ } else {
+ if (newFolder.size() > 0)
+ newFile = *cString::sprintf("%s~%s", newFolder.c_str(), newFile.c_str());
+ }
+ std::replace(newFile.begin(), newFile.end(), '/', '~');
+ t.SetFile(newFile.c_str());
+ return t;
+}
+
+/******************************************************************************************
+* Series Timer Menus
+******************************************************************************************/
+
+// --- cRecMenuSeriesTimer ---------------------------------------------------------
+cRecMenuSeriesTimer::cRecMenuSeriesTimer(cChannel *initialChannel, const cEvent *event, std::string folder) {
+ if (!initialChannel)
+ return;
+ timerActive = true;
+ channel = initialChannel->Number();
+ dayOfWeek = 127;
+ priority = MAXPRIORITY;
+ lifetime = MAXLIFETIME;
+ CalculateTimes(event);
+ this->folder = folder;
+
+ SetWidthPercent(70);
+ cString title = tr("Create Series Timer based on");
+ cString infoText = cString::sprintf("%s:\n%s", *title, event->Title());
+ cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*infoText, true);
+ infoItem->CalculateHeight(width - 2 * border);
+ SetHeader(infoItem);
+
+ AddMenuItem(new cRecMenuItemBool(tr("Timer Active"), timerActive, false, false, &timerActive));
+ AddMenuItem(new cRecMenuItemChannelChooser(tr("Channel"), initialChannel, false, &channel));
+ AddMenuItem(new cRecMenuItemTime(tr("Series Timer start time"), start, false, &start));
+ AddMenuItem(new cRecMenuItemTime(tr("Series Timer stop time"), stop, false, &stop));
+ AddMenuItem(new cRecMenuItemDayChooser(tr("Days to record"), dayOfWeek, false, &dayOfWeek));
+ AddMenuItem(new cRecMenuItemDay(tr("Day to start"), tstart, false, &tstart));
+ AddMenuItem(new cRecMenuItemInt(tr("Priority"), priority, 0, MAXPRIORITY, false, &priority));
+ AddMenuItem(new cRecMenuItemInt(tr("Lifetime"), lifetime, 0, MAXLIFETIME, false, &lifetime));
+
+ AddMenuItem(new cRecMenuItemButtonYesNo(tr("Create Timer"), tr("Cancel"), rmsSeriesTimerCreate, rmsClose, true));
+
+ CalculateHeight();
+ CreatePixmap();
+ Arrange();
+}
+
+cTimer *cRecMenuSeriesTimer::GetTimer(void) {
+ cChannel *chan = Channels.GetByNumber(channel);
+ cTimer *seriesTimer = new cTimer(NULL, NULL, chan);
+ cString fileName = "TITLE EPISODE";
+ if (folder.size() > 0) {
+ std::replace(folder.begin(), folder.end(), '/', '~');
+ fileName = cString::sprintf("%s~%s", folder.c_str(), *fileName);
+ }
+ seriesTimer->SetDay(tstart);
+ seriesTimer->SetStart(start);
+ seriesTimer->SetStop(stop);
+ seriesTimer->SetPriority(priority);
+ seriesTimer->SetLifetime(lifetime);
+ seriesTimer->SetWeekDays(dayOfWeek);
+ seriesTimer->SetFile(*fileName);
+ if (timerActive)
+ seriesTimer->SetFlags(tfActive);
+ else
+ seriesTimer->SetFlags(tfNone);
+ return seriesTimer;
+}
+
+void cRecMenuSeriesTimer::CalculateTimes(const cEvent *event) {
+ tstart = event->StartTime();
+ tstart -= Setup.MarginStart * 60;
+ time_t tstop = tstart + event->Duration();
+ tstop += Setup.MarginStop * 60;
+
+ struct tm tm_r;
+ struct tm *time = localtime_r(&tstart, &tm_r);
+ start = time->tm_hour * 100 + time->tm_min;
+ time = localtime_r(&tstop, &tm_r);
+ stop = time->tm_hour * 100 + time->tm_min;
+ if (stop >= 2400)
+ stop -= 2400;
+}
+
+// --- cRecMenuConfirmSeriesTimer ---------------------------------------------------------
+cRecMenuConfirmSeriesTimer::cRecMenuConfirmSeriesTimer(cTimer *seriesTimer) {
+ SetWidthPercent(50);
+ cString message = tr("Series Timer created");
+ cString infoText = message;
+ if (seriesTimer) {
+ cString days = cTimer::PrintDay(seriesTimer->Day(), seriesTimer->WeekDays(), true);
+ infoText = cString::sprintf("%s\n%s, %s: %s, %s: %s", *message, *days, tr("Start"), *TimeString(seriesTimer->StartTime()), tr("Stop"), *TimeString(seriesTimer->StopTime()));
+ }
+ cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*infoText);
+ infoItem->CalculateHeight(width - 2 * border);
+ AddMenuItem(infoItem);
+ AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsClose, true, true));
+ CalculateHeight();
+ CreatePixmap();
+ Arrange();
+}
+
+/******************************************************************************************
+* SearchTimer Menus
+******************************************************************************************/
+
+// --- cRecMenuSearchTimer ---------------------------------------------------------
+cRecMenuSearchTimer::cRecMenuSearchTimer(const cEvent *event) {
+ SetWidthPercent(70);
+ cString message = tr("Configure Search Timer based on");
+ cString infoText = cString::sprintf("%s:\n\"%s\"", *message, event->Title());
+ cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*infoText, true);
+ infoItem->CalculateHeight(width - 2 * border);
+ SetHeader(infoItem);
+ strncpy(searchString, event->Title(), TEXTINPUTLENGTH);
+ AddMenuItemInitial(new cRecMenuItemText(tr("Search Expression:"), searchString, TEXTINPUTLENGTH, false));
+ AddMenuItemInitial(new cRecMenuItemButtonYesNo(tr("Continue"), tr("Cancel"), rmsSearchTimerOptions, rmsClose, true));
+ CalculateHeight();
+ CreatePixmap();
+ Arrange();
+}
+
+// --- cRecMenuSearchTimerTemplates ---------------------------------------------------------
+cRecMenuSearchTimerTemplates::cRecMenuSearchTimerTemplates(cTVGuideSearchTimer searchTimer, std::vector<TVGuideEPGSearchTemplate> templates) {
+ this->searchTimer = searchTimer;
+ this->templates = templates;
+ SetWidthPercent(70);
+ cString message = tr("Configure Search Timer for Search String");
+ cString infoText = cString::sprintf("%s:\n%s", *message, searchTimer.SearchString().c_str());
+ cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*infoText, true);
+ infoItem->CalculateHeight(width - 2 * border);
+ SetHeader(infoItem);
+
+ AddMenuItemInitial(new cRecMenuItemButton(tr("Manually configure Options"), rmsSearchTimerEdit, true));
+
+ numTemplates = templates.size();
+ for (int i=0; i<numTemplates; i++) {
+ cString buttonText = cString::sprintf("%s \"%s\"", tr("Use Template"), templates[i].name.c_str());
+ if (!AddMenuItemInitial(new cRecMenuItemButton(*buttonText, rmsSearchTimerCreateWithTemplate, false)))
+ break;
+ }
+ CalculateHeight();
+ CreatePixmap();
+ Arrange();
+}
+
+cRecMenuItem *cRecMenuSearchTimerTemplates::GetMenuItem(int number) {
+ if (number == 0) {
+ return new cRecMenuItemButton(tr("Manually configure Options"), rmsSearchTimerEdit, false);
+ } else if ((number > 0) && (number < numTemplates + 1)) {
+ cString buttonText = cString::sprintf("%s \"%s\"", tr("Use Template"), templates[number-1].name.c_str());
+ cRecMenuItem *templ = new cRecMenuItemButton(*buttonText, rmsSearchTimerCreateWithTemplate, false);
+ return templ;
+ }
+ return NULL;
+}
+
+int cRecMenuSearchTimerTemplates::GetTotalNumMenuItems(void) {
+ return numTemplates + 1;
+}
+
+TVGuideEPGSearchTemplate cRecMenuSearchTimerTemplates::GetTemplate(void) {
+ TVGuideEPGSearchTemplate templ;
+ int tmplActive = GetActive() - 1;
+ if (tmplActive >= 0 && tmplActive < templates.size())
+ templ = templates[tmplActive];
+ return templ;
+}
+// --- cRecMenuSearchTimers ---------------------------------------------------------
+cRecMenuSearchTimers::cRecMenuSearchTimers(std::vector<cTVGuideSearchTimer> searchTimers) {
+ this->searchTimers = searchTimers;
+ numSearchTimers = searchTimers.size();
+ SetWidthPercent(70);
+ cString headline;
+ if (numSearchTimers > 0) {
+ headline = tr("EPGSearch Search Timers");
+ } else {
+ headline = tr("No Search Timers Configured");
+ }
+ cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*headline, true);
+ infoItem->CalculateHeight(width - 2 * border);
+ SetHeader(infoItem);
+ cRecMenuItem *button = new cRecMenuItemButton(tr("Close"), rmsClose, (!numSearchTimers)?true:false);
+ SetFooter(button);
+ if (numSearchTimers > 0)
+ SetMenuItems();
+ CalculateHeight();
+ CreatePixmap();
+ Arrange();
+}
+
+cRecMenuSearchTimers::~cRecMenuSearchTimers(void) {
+
+}
+
+void cRecMenuSearchTimers::SetMenuItems(void) {
+ for (int i = 0; i < numSearchTimers; i++) {
+ if (!AddMenuItemInitial(new cRecMenuItemSearchTimer(searchTimers[i], rmsSearchTimerTest, rmsSearchTimerEdit, rmsSearchTimerDeleteConfirm, (i==0)?true:false)))
+ break;
+ }
+}
+
+cTVGuideSearchTimer cRecMenuSearchTimers::GetSearchTimer(void) {
+ cRecMenuItemSearchTimer *activeItem = dynamic_cast<cRecMenuItemSearchTimer*>(GetActiveMenuItem());
+ return activeItem->GetTimer();
+}
+
+cRecMenuItem *cRecMenuSearchTimers::GetMenuItem(int number) {
+ if (number < 0 || number >= numSearchTimers)
+ return NULL;
+ return new cRecMenuItemSearchTimer(searchTimers[number], rmsSearchTimerTest, rmsSearchTimerEdit, rmsSearchTimerDeleteConfirm, false);
+}
+
+int cRecMenuSearchTimers::GetTotalNumMenuItems(void) {
+ return numSearchTimers;
+}
+
+// --- cRecMenuSearchTimerEdit ---------------------------------------------------------
+cRecMenuSearchTimerEdit::cRecMenuSearchTimerEdit(cTVGuideSearchTimer searchTimer, bool advancedOptions) {
+ deleteMenuItems = false;
+ this->advancedOptions = advancedOptions;
+ this->searchTimer = searchTimer;
+ strncpy(searchString, searchTimer.SearchString().c_str(), TEXTINPUTLENGTH);
+ timerActive = searchTimer.Active();
+ mode = searchTimer.SearchMode();
+ useTitle = searchTimer.UseTitle();
+ useSubtitle = searchTimer.UseSubtitle();
+ useDescription = searchTimer.UseDescription();
+ useChannel = searchTimer.UseChannel();
+ startChannel = searchTimer.StartChannel();
+ stopChannel = searchTimer.StopChannel();
+ useTime = searchTimer.UseTime();
+ startTime = searchTimer.StartTime();
+ stopTime = searchTimer.StopTime();
+ useDayOfWeek = searchTimer.UseDayOfWeek();
+ dayOfWeek = searchTimer.DayOfWeek();
+ priority = searchTimer.Priority();
+ lifetime = searchTimer.Lifetime();
+ useEpisode = searchTimer.UseEpisode();
+ std::string dir = searchTimer.Directory();
+ strncpy(directory, dir.c_str(), TEXTINPUTLENGTH);
+ marginStart = searchTimer.MarginStart();
+ marginStop = searchTimer.MarginStop();
+ useVPS = searchTimer.UseVPS();
+ avoidRepeats = searchTimer.AvoidRepeats();
+ allowedRepeats = searchTimer.AllowedRepeats();
+ compareTitle = searchTimer.CompareTitle();
+ compareSubtitle = searchTimer.CompareSubtitle();
+ compareSummary = searchTimer.CompareSummary();
+ useInFavorites = searchTimer.UseInFavorites();
+
+ SetWidthPercent(70);
+ cString infoText;
+ if (searchTimer.GetID() > -1) {
+ infoText = tr("Configure Search Timer Options");
+ } else {
+ infoText = tr("Create Search Timer");
+ }
+ cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*infoText, true);
+ infoItem->CalculateHeight(width - 2 * border);
+ SetHeader(infoItem);
+ cRecMenuItemButtonYesNo *footerButton = new cRecMenuItemButtonYesNo(tr("Save Search Timer"), tr("Cancel"), rmsSearchTimerSave, rmsSearchTimers, (advancedOptions)?false:true);
+ SetFooter(footerButton);
+ InitMenuItems();
+ CreateMenuItems();
+}
+
+cRecMenuSearchTimerEdit::~cRecMenuSearchTimerEdit(void) {
+ for (std::vector<cRecMenuItem*>::iterator it = mainMenuItems.begin(); it != mainMenuItems.end(); it++) {
+ delete *it;
+ }
+ mainMenuItems.clear();
+ for (std::vector<cRecMenuItem*>::iterator it = useChannelSubMenu.begin(); it != useChannelSubMenu.end(); it++) {
+ delete *it;
+ }
+ useChannelSubMenu.clear();
+ for (std::vector<cRecMenuItem*>::iterator it = useTimeSubMenu.begin(); it != useTimeSubMenu.end(); it++) {
+ delete *it;
+ }
+ useTimeSubMenu.clear();
+ for (std::vector<cRecMenuItem*>::iterator it = useDayOfWeekSubMenu.begin(); it != useDayOfWeekSubMenu.end(); it++) {
+ delete *it;
+ }
+ useDayOfWeekSubMenu.clear();
+ for (std::vector<cRecMenuItem*>::iterator it = avoidRepeatSubMenu.begin(); it != avoidRepeatSubMenu.end(); it++) {
+ delete *it;
+ }
+ avoidRepeatSubMenu.clear();
+ currentMenuItems.clear();
+}
+
+void cRecMenuSearchTimerEdit::InitMenuItems(void) {
+
+ useChannelPos = 6;
+ useTimePos = 7;
+ useDayOfWeekPos = 8;
+ avoidRepeatsPos = 14;
+
+ mainMenuItems.push_back(new cRecMenuItemText(tr("Search String"), searchString, TEXTINPUTLENGTH, false, searchString));
+ mainMenuItems.push_back(new cRecMenuItemBool(tr("Active"), timerActive, false, false, &timerActive, rmsSearchTimerSave));
+ std::vector<std::string> searchModes;
+ searchTimer.GetSearchModes(&searchModes);
+ mainMenuItems.push_back(new cRecMenuItemSelect(tr("Search Mode"), searchModes, mode, false, &mode, rmsSearchTimerSave));
+ mainMenuItems.push_back(new cRecMenuItemBool(tr("Use Title"), useTitle, false, false, &useTitle, rmsSearchTimerSave));
+ mainMenuItems.push_back(new cRecMenuItemBool(tr("Use Subtitle"), useSubtitle, false, false, &useSubtitle, rmsSearchTimerSave));
+ mainMenuItems.push_back(new cRecMenuItemBool(tr("Use Description"), useDescription, false, false, &useDescription, rmsSearchTimerSave));
+ mainMenuItems.push_back(new cRecMenuItemBool(tr("Limit Channels"), useChannel, true, false, &useChannel, rmsSearchTimerSave));
+ mainMenuItems.push_back(new cRecMenuItemBool(tr("Use Time"), useTime, true, false, &useTime, rmsSearchTimerSave));
+ if (!advancedOptions) {
+ mainMenuItems.push_back(new cRecMenuItemButton(tr("Display advanced Options"), rmsSearchTimerEditAdvanced, false));
+ } else {
+ mainMenuItems.push_back(new cRecMenuItemBool(tr("Limit Days of the Week"), useDayOfWeek, true, false, &useDayOfWeek, rmsSearchTimerSave));
+ mainMenuItems.push_back(new cRecMenuItemInt(tr("Priority"), priority, 0, 99, false, &priority, rmsSearchTimerSave));
+ mainMenuItems.push_back(new cRecMenuItemInt(tr("Lifetime"), lifetime, 0, 99, false, &lifetime, rmsSearchTimerSave));
+ mainMenuItems.push_back(new cRecMenuItemInt(tr("Time margin for start in minutes"), marginStart, 0, 30, false, &marginStart, rmsSearchTimerSave));
+ mainMenuItems.push_back(new cRecMenuItemInt(tr("Time margin for stop in minutes"), marginStop, 0, 30, false, &marginStop, rmsSearchTimerSave));
+ mainMenuItems.push_back(new cRecMenuItemBool(tr("Series Recording"), useEpisode, false, false, &useEpisode, rmsSearchTimerSave));
+ mainMenuItems.push_back(new cRecMenuItemSelectDirectory(tr("Folder"), std::string(directory), false, directory, rmsSearchTimerSave, true));
+ mainMenuItems.push_back(new cRecMenuItemBool(tr("Use VPS"), useVPS, false, false, &useVPS, rmsSearchTimerSave));
+ mainMenuItems.push_back(new cRecMenuItemBool(tr("Avoid Repeats"), avoidRepeats, true, false, &avoidRepeats, rmsSearchTimerSave));
+ mainMenuItems.push_back(new cRecMenuItemBool(tr("Use in Favorites"), useInFavorites, false, false, &useInFavorites, rmsSearchTimerSave));
+ mainMenuItems.push_back(new cRecMenuItemButton(tr("Hide advanced Options"), rmsSearchTimerEdit, false));
+ }
+ mainMenuItems.push_back(new cRecMenuItemButton(tr("Display Results for Search Timer"), rmsSearchTimerTest, false));
+
+ if (startChannel == 0)
+ startChannel = 1;
+ if (stopChannel == 0)
+ stopChannel = 1;
+ useChannelSubMenu.push_back(new cRecMenuItemChannelChooser(tr("Start Channel"), Channels.GetByNumber(startChannel), false, &startChannel, rmsSearchTimerSave));
+ useChannelSubMenu.push_back(new cRecMenuItemChannelChooser(tr("Stop Channel"), Channels.GetByNumber(stopChannel), false, &stopChannel, rmsSearchTimerSave));
+
+ useTimeSubMenu.push_back(new cRecMenuItemTime(tr("Start after"), startTime, false, &startTime, rmsSearchTimerSave));
+ useTimeSubMenu.push_back(new cRecMenuItemTime(tr("Start before"), stopTime, false, &stopTime, rmsSearchTimerSave));
+
+ if (advancedOptions) {
+ useDayOfWeekSubMenu.push_back(new cRecMenuItemDayChooser(tr("Select Days"), dayOfWeek, false, &dayOfWeek));
+ avoidRepeatSubMenu.push_back(new cRecMenuItemInt(tr("Number of allowed repeats"), allowedRepeats, 0, 30, false, &allowedRepeats, rmsSearchTimerSave));
+ avoidRepeatSubMenu.push_back(new cRecMenuItemBool(tr("Compare Title"), compareTitle, false, false, &compareTitle, rmsSearchTimerSave));
+ avoidRepeatSubMenu.push_back(new cRecMenuItemBool(tr("Compare Subtitle"), compareSubtitle, false, false, &compareSubtitle, rmsSearchTimerSave));
+ avoidRepeatSubMenu.push_back(new cRecMenuItemBool(tr("Compare Description"), compareSummary, false, false, &compareSummary, rmsSearchTimerSave));
+ }
+}
+
+
+void cRecMenuSearchTimerEdit::CreateMenuItems(void) {
+ bool reDraw = false;
+ if (GetCurrentNumMenuItems() > 0) {
+ InitMenu(false);
+ currentMenuItems.clear();
+ reDraw = true;
+ }
+
+ int numMainMenuItems = mainMenuItems.size();
+
+ for (int i = 0; i < numMainMenuItems; i++) {
+ currentMenuItems.push_back(mainMenuItems[i]);
+ if ((i == useChannelPos) && useChannel)
+ AddSubMenu(&useChannelSubMenu);
+ else if ((i == useTimePos) && useTime)
+ AddSubMenu(&useTimeSubMenu);
+ else if (advancedOptions && (i == useDayOfWeekPos) && useDayOfWeek)
+ AddSubMenu(&useDayOfWeekSubMenu);
+ else if (advancedOptions && (i == avoidRepeatsPos) && avoidRepeats)
+ AddSubMenu(&avoidRepeatSubMenu);
+ }
+
+ int numMenuItemsAll = currentMenuItems.size();
+ int start = GetStartIndex();
+ for (int i = start; i < numMenuItemsAll; i++) {
+ if ((i == start) && !reDraw && advancedOptions) {
+ currentMenuItems[i]->setActive();
+ }
+ if (!AddMenuItemInitial(currentMenuItems[i])) {
+ break;
+ }
+ }
+ numMenuItems = currentMenuItems.size();
+ CalculateHeight();
+ CreatePixmap();
+ Arrange();
+}
+
+void cRecMenuSearchTimerEdit::AddSubMenu(std::vector<cRecMenuItem*> *subMenu) {
+ for (std::vector<cRecMenuItem*>::iterator it = subMenu->begin(); it < subMenu->end(); it++) {
+ currentMenuItems.push_back(*it);
+ }
+}
+
+
+cTVGuideSearchTimer cRecMenuSearchTimerEdit::GetSearchTimer(void) {
+ searchTimer.SetSearchString(searchString);
+ searchTimer.SetActive(timerActive);
+ searchTimer.SetSearchMode(mode);
+ searchTimer.SetUseTitle(useTitle);
+ searchTimer.SetUseSubtitle(useSubtitle);
+ searchTimer.SetUseDesription(useDescription);
+ searchTimer.SetUseChannel(useChannel);
+ if (useChannel) {
+ searchTimer.SetStartChannel(startChannel);
+ searchTimer.SetStopChannel(stopChannel);
+ }
+ searchTimer.SetUseTime(useTime);
+ if (useTime) {
+ searchTimer.SetStartTime(startTime);
+ searchTimer.SetStopTime(stopTime);
+ }
+ searchTimer.SetUseDayOfWeek(useDayOfWeek);
+ if (useDayOfWeek) {
+ searchTimer.SetDayOfWeek(dayOfWeek);
+ }
+ searchTimer.SetPriority(priority);
+ searchTimer.SetLifetime(lifetime);
+ searchTimer.SetUseEpisode(useEpisode);
+ std::string dir(directory);
+ std::replace(dir.begin(), dir.end(), '/', '~');
+ searchTimer.SetDirectory(dir);
+ searchTimer.SetMarginStart(marginStart);
+ searchTimer.SetMarginStop(marginStop);
+ searchTimer.SetUseVPS(useVPS);
+ searchTimer.SetAvoidRepeats(avoidRepeats);
+ if (avoidRepeats) {
+ searchTimer.SetAllowedRepeats(allowedRepeats);
+ searchTimer.SetCompareTitle(compareTitle);
+ searchTimer.SetCompareSubtitle(compareSubtitle);
+ searchTimer.SetCompareSummary(compareSummary);
+ }
+ searchTimer.SetUseInFavorites(useInFavorites);
+ return searchTimer;
+}
+
+int cRecMenuSearchTimerEdit::GetTotalNumMenuItems(void) {
+ return numMenuItems;
+}
+
+cRecMenuItem *cRecMenuSearchTimerEdit::GetMenuItem(int number) {
+ if ((number > -1) && (number < numMenuItems)) {
+ return currentMenuItems[number];
+ }
+ return NULL;
+}
+
+// --- cRecMenuSearchTimerDeleteConfirm ---------------------------------------------
+cRecMenuSearchTimerDeleteConfirm::cRecMenuSearchTimerDeleteConfirm(cTVGuideSearchTimer searchTimer) {
+ this->searchTimer = searchTimer;
+ SetWidthPercent(70);
+ cString message = tr("Really delete Search Timer");
+ cString infoText = cString::sprintf("%s \"%s\"?", *message, searchTimer.SearchString().c_str());
+ cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*infoText, true);
+ infoItem->CalculateHeight(width - 2 * border);
+ SetHeader(infoItem);
+ AddMenuItem(new cRecMenuItemButton(tr("Delete only Search Timer"), rmsSearchTimerDelete, true));
+ AddMenuItem(new cRecMenuItemButton(tr("Delete Search Timer and created Timers"), rmsSearchTimerDeleteWithTimers, false));
+ SetFooter(new cRecMenuItemButton(tr("Cancel"), rmsClose, false));
+ CalculateHeight();
+ CreatePixmap();
+ Arrange();
+}
+
+cRecMenuSearchTimerDeleteConfirm::~cRecMenuSearchTimerDeleteConfirm(void) {
+
+}
+
+cTVGuideSearchTimer cRecMenuSearchTimerDeleteConfirm::GetSearchTimer(void) {
+ return searchTimer;
+}
+
+// --- cRecMenuSearchTimerCreateConfirm ---------------------------------------------------------
+cRecMenuSearchTimerCreateConfirm::cRecMenuSearchTimerCreateConfirm(bool success) {
+ SetWidthPercent(50);
+
+ cString message1a = tr("Search Timer sucessfully created.");
+ cString message1b = tr ("Search Timer update initialised");
+ cString message1 = cString::sprintf("%s\n%s", *message1a, *message1b);
+ cString message2 = tr("Search Timer NOT sucessfully created");
+ cString infoText = success?message1:message2;
+ cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*infoText);
+ infoItem->CalculateHeight(width - 2 * border);
+ AddMenuItem(infoItem);
+
+ AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsClose, true));
+
+ CalculateHeight();
+ CreatePixmap();
+ Arrange();
+}
+
+// --- cRecMenuSearchTimerTemplatesCreate ---------------------------------------------------------
+cRecMenuSearchTimerTemplatesCreate::cRecMenuSearchTimerTemplatesCreate(TVGuideEPGSearchTemplate templ, cTVGuideSearchTimer searchTimer) {
+ this->templ = templ;
+ this->searchTimer = searchTimer;
+ SetWidthPercent(70);
+
+ cString message1 = tr("Creating Search Timer");
+ cString message2 = tr("Search Term");
+ cString message3 = tr("Using Template");
+
+ cString infoText = cString::sprintf("%s\n%s: \"%s\"\n%s \"%s\"", *message1, *message2, searchTimer.SearchString().c_str(), *message3, templ.name.c_str());
+ cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*infoText);
+ infoItem->CalculateHeight(width - 2 * border);
+ AddMenuItem(infoItem);
+
+ AddMenuItem(new cRecMenuItemButton(tr("Display Results for Search Timer"), rmsSearchTimerTest, true));
+ AddMenuItem(new cRecMenuItemButtonYesNo(tr("Create Search Timer"), tr("Use other Template"), rmsSearchTimerSave, rmsSearchTimerOptions, false));
+
+ CalculateHeight();
+ CreatePixmap();
+ Arrange();
+}
+
+
+// --- cRecMenuSearchTimerResults ---------------------------------------------------------
+cRecMenuSearchTimerResults::cRecMenuSearchTimerResults(std::string searchString, const cEvent **searchResults, int numResults, std::string templateName, eRecMenuState action2) {
+ this->searchResults = searchResults;
+ this->action2 = action2;
+ this->numResults = numResults;
+ SetWidthPercent(70);
+ cString message1 = "", message2 = "", message3 = "", infoText = "";
+ if (action2 == rmsFavoritesRecord) {
+ message1 = tr("search results for Favorite");
+ message2 = tr("search result for Favorite");
+ } else {
+ message1 = tr("search results for Search Timer");
+ message2 = tr("search result for Search Timer");
+ message3 = tr("Using Template");
+ }
+ if (templateName.size() > 0) {
+ infoText = cString::sprintf("%d %s:\n\"%s\"\n%s \"%s\"", numResults, (numResults>1)?(*message1):(*message2), searchString.c_str(), *message3, templateName.c_str());
+ } else {
+ infoText = cString::sprintf("%d %s:\n\"%s\"", numResults, (numResults>1)?(*message1):(*message2), searchString.c_str());
+ }
+ cRecMenuItem *infoItem = new cRecMenuItemInfo(*infoText, true);
+ infoItem->CalculateHeight(width - 2 * border);
+ SetHeader(infoItem);
+
+ cRecMenuItem *buttons = new cRecMenuItemButton(tr("Close"), rmsClose, false);
+ SetFooter(buttons);
+ if (searchResults && (numResults > 0)) {
+ for (int i=0; i<numResults; i++) {
+ if (!AddMenuItemInitial(new cRecMenuItemEvent(searchResults[i], rmsSearchShowInfo, action2, (i==0)?true:false)))
+ break;
+ }
+ }
+ CalculateHeight();
+ CreatePixmap();
+ Arrange();
+}
+
+cRecMenuItem *cRecMenuSearchTimerResults::GetMenuItem(int number) {
+ if ((number >= 0) && (number < numResults)) {
+ cRecMenuItem *result = new cRecMenuItemEvent(searchResults[number], rmsSearchShowInfo, action2, false);
+ return result;
+ }
+ return NULL;
+}
+
+int cRecMenuSearchTimerResults::GetTotalNumMenuItems(void) {
+ return numResults;
+}
+
+const cEvent *cRecMenuSearchTimerResults::GetEvent(void) {
+ const cEvent *ev = NULL;
+ if (cRecMenuItemEvent *activeItem = dynamic_cast<cRecMenuItemEvent*>(GetActiveMenuItem()))
+ ev = activeItem->GetEventValue();
+ return ev;
+}
+
+// --- cRecMenuSearchTimerNothingFound ---------------------------------------------------------
+cRecMenuSearchTimerNothingFound::cRecMenuSearchTimerNothingFound(std::string searchString) {
+ SetWidthPercent(50);
+ cString message = tr("Nothing found for Search String");
+ cString text;
+ text = cString::sprintf("%s\n\"%s\"",
+ *message,
+ searchString.c_str());
+ cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*text);
+ infoItem->CalculateHeight(width - 2 * border);
+ AddMenuItem(infoItem);
+ AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsClose, true, true));
+ CalculateHeight();
+ CreatePixmap();
+ Arrange();
+}
+
+/******************************************************************************************
+* SwitchTimer Menus
+******************************************************************************************/
+
+// --- cRecMenuSwitchTimer ---------------------------------------------------------
+cRecMenuSwitchTimer::cRecMenuSwitchTimer(void) {
+ switchMinsBefore = 2;
+ announceOnly = 0;
+
+ SetWidthPercent(60);
+
+ cString infoText = tr("Configure Options for Switchtimer");
+ cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*infoText, true);
+ infoItem->CalculateHeight(width - 2 * border);
+ AddMenuItem(infoItem);
+
+ AddMenuItem(new cRecMenuItemInt(tr("Minutes before switching"), switchMinsBefore, 0, 10, false, &switchMinsBefore));
+ std::vector<std::string> switchModes;
+ switchModes.push_back(tr("switch"));
+ switchModes.push_back(tr("announce only"));
+ switchModes.push_back(tr("ask for switch"));
+ AddMenuItem(new cRecMenuItemSelect(tr("Switch Mode"), switchModes, announceOnly, false, &announceOnly));
+
+ AddMenuItem(new cRecMenuItemButtonYesNo(tr("Create"), tr("Cancel"), rmsSwitchTimerCreate, rmsClose, true));
+
+ CalculateHeight();
+ CreatePixmap();
+ Arrange();
+}
+
+cSwitchTimer cRecMenuSwitchTimer::GetSwitchTimer(void) {
+ cSwitchTimer st;
+ st.switchMinsBefore = switchMinsBefore;
+ st.announceOnly = announceOnly;
+ return st;
+}
+
+// --- cRecMenuSwitchTimerConfirm ---------------------------------------------------------
+cRecMenuSwitchTimerConfirm::cRecMenuSwitchTimerConfirm(bool success) {
+ SetWidthPercent(50);
+
+ cString message1 = tr("Switch Timer sucessfully created");
+ cString message2 = tr("Switch Timer NOT sucessfully created");
+ cString infoText = success?message1:message2;
+ cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*infoText);
+ infoItem->CalculateHeight(width - 2 * border);
+ AddMenuItem(infoItem);
+
+ AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsClose, true));
+
+ CalculateHeight();
+ CreatePixmap();
+ Arrange();
+}
+
+// --- cRecMenuSwitchTimerDelete ---------------------------------------------------------
+cRecMenuSwitchTimerDelete::cRecMenuSwitchTimerDelete(void) {
+ SetWidthPercent(50);
+
+ cString infoText = tr("Switch Timer deleted");
+ cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*infoText);
+ infoItem->CalculateHeight(width - 2 * border);
+ AddMenuItem(infoItem);
+
+ AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsClose, true));
+
+ CalculateHeight();
+ CreatePixmap();
+ Arrange();
+}
+
+/******************************************************************************************
+* Search Menus
+******************************************************************************************/
+
+
+// --- cRecMenuSearch ---------------------------------------------------------
+cRecMenuSearch::cRecMenuSearch(std::string searchString, bool withOptions) {
+ strncpy(this->searchString, searchString.c_str(), TEXTINPUTLENGTH);
+ mode = 0;
+ channelNr = 0;
+ useTitle = true;
+ useSubTitle = true;
+ useDescription = false;
+ SetWidthPercent(60);
+ cString infoText = tr("Search");
+ cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*infoText, true);
+ infoItem->CalculateHeight(width - 2 * border);
+ SetHeader(infoItem);
+ AddMenuItem(new cRecMenuItemText(tr("Search Expression:"), this->searchString, TEXTINPUTLENGTH, false, this->searchString));
+ if (withOptions) {
+ std::vector<std::string> searchModes;
+ cTVGuideSearchTimer searchTimer;
+ searchTimer.GetSearchModes(&searchModes);
+ AddMenuItemInitial(new cRecMenuItemSelect(tr("Search Mode"), searchModes, 0, false, &mode));
+ AddMenuItemInitial(new cRecMenuItemChannelChooser(tr("Channel to Search"), NULL, false, &channelNr));
+ AddMenuItemInitial(new cRecMenuItemBool(tr("Search in title"), true, false, false, &useTitle));
+ AddMenuItemInitial(new cRecMenuItemBool(tr("Search in Subtitle"), true, false, false, &useSubTitle));
+ AddMenuItemInitial(new cRecMenuItemBool(tr("Search in Description"), false, false, false, &useDescription));
+ } else {
+ AddMenuItemInitial(new cRecMenuItemButton(tr("Show Search Options"), rmsSearchWithOptions, false));
+ }
+ cRecMenuItemButtonYesNo *button = new cRecMenuItemButtonYesNo(tr("Perform Search"), tr("Cancel"), rmsSearchPerform, rmsClose, true);
+ SetFooter(button);
+ CalculateHeight();
+ CreatePixmap();
+ Arrange();
+}
+
+Epgsearch_searchresults_v1_0 cRecMenuSearch::GetEPGSearchStruct(void) {
+ Epgsearch_searchresults_v1_0 data;
+ data.query = searchString;
+ data.mode = mode;
+ data.channelNr = channelNr;
+ data.useTitle = useTitle;
+ data.useSubTitle = useSubTitle;
+ data.useDescription = useDescription;
+ return data;
+}
+
+
+// --- cRecMenuSearchResults ---------------------------------------------------------
+cRecMenuSearchResults::cRecMenuSearchResults(std::string searchString, const cEvent **searchResults, int numResults) {
+ this->searchResults = searchResults;
+ SetWidthPercent(70);
+ this->searchString = searchString;
+ this->numResults = numResults;
+ cString message1 = tr("search results for");
+ cString message2 = tr("search result for");
+ cString infoText = cString::sprintf("%d %s:\n\"%s\"", numResults, (numResults>1)?(*message1):(*message2), searchString.c_str());
+ cRecMenuItem *infoItem = new cRecMenuItemInfo(*infoText, true);
+ infoItem->CalculateHeight(width - 2 * border);
+ SetHeader(infoItem);
+
+ cRecMenuItem *buttons = new cRecMenuItemButtonYesNo(tr("Adapt Search"), tr("Close"), rmsSearch, rmsClose, false);
+ SetFooter(buttons);
+ if (searchResults && (numResults > 0)) {
+ for (int i=0; i<numResults; i++) {
+ if (!AddMenuItemInitial(new cRecMenuItemEvent(searchResults[i], rmsSearchShowInfo, rmsSearchRecord, (i==0)?true:false)))
+ break;
+ }
+ }
+ CalculateHeight();
+ CreatePixmap();
+ Arrange();
+}
+
+cRecMenuItem *cRecMenuSearchResults::GetMenuItem(int number) {
+ if ((number >= 0) && (number < numResults)) {
+ cRecMenuItem *result = new cRecMenuItemEvent(searchResults[number], rmsSearchShowInfo, rmsSearchRecord, false);
+ return result;
+ }
+ return NULL;
+}
+
+int cRecMenuSearchResults::GetTotalNumMenuItems(void) {
+ return numResults;
+}
+
+const cEvent *cRecMenuSearchResults::GetEvent(void) {
+ const cEvent *ev = NULL;
+ if (cRecMenuItemEvent *activeItem = dynamic_cast<cRecMenuItemEvent*>(GetActiveMenuItem()))
+ ev = activeItem->GetEventValue();
+ return ev;
+}
+
+
+// --- cRecMenuSearchConfirmTimer ---------------------------------------------------------
+cRecMenuSearchConfirmTimer::cRecMenuSearchConfirmTimer(const cEvent *event, eRecMenuState nextAction) {
+ SetWidthPercent(50);
+ cString channelName = Channels.GetByChannelID(event->ChannelID())->Name();
+ cString message = tr("Timer created");
+ cString text = cString::sprintf("%s\n%s\n%s %s - %s\n%s",
+ *message,
+ *channelName,
+ *event->GetDateString(),
+ *event->GetTimeString(),
+ *event->GetEndTimeString(),
+ event->Title()
+ );
+ cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*text);
+ infoItem->CalculateHeight(width - 2 * border);
+ AddMenuItem(infoItem);
+ AddMenuItem(new cRecMenuItemButton(tr("OK"), nextAction, true, true));
+ CalculateHeight();
+ CreatePixmap();
+ Arrange();
+}
+
+// --- cRecMenuSearchNothingFound ---------------------------------------------------------
+cRecMenuSearchNothingFound::cRecMenuSearchNothingFound(std::string searchString, bool tooShort) {
+ SetWidthPercent(50);
+ cString text;
+ if (!tooShort) {
+ cString message = tr("Nothing found for Search String");
+ text = cString::sprintf("%s\n\"%s\"",
+ *message,
+ searchString.c_str());
+ } else {
+ cString message = tr("Search String has to have at least three letters");
+ text = cString::sprintf("%s\n\"%s\"",
+ *message,
+ searchString.c_str());
+
+ }
+ cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*text);
+ infoItem->CalculateHeight(width - 2 * border);
+ AddMenuItem(infoItem);
+ AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsSearchNothingFoundConfirm, true, true));
+ CalculateHeight();
+ CreatePixmap();
+ Arrange();
+}
+
+/******************************************************************************************
+* Recording Search Menus
+******************************************************************************************/
+
+// --- cRecMenuRecordingSearch ---------------------------------------------------------
+cRecMenuRecordingSearch::cRecMenuRecordingSearch(std::string search) {
+ strncpy(searchString, search.c_str(), TEXTINPUTLENGTH);
+ SetWidthPercent(60);
+ cString infoText = tr("Search in Recordings");
+ cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*infoText, true);
+ infoItem->CalculateHeight(width - 2 * border);
+ SetHeader(infoItem);
+
+ AddMenuItem(new cRecMenuItemText(tr("Search Expression:"), searchString, TEXTINPUTLENGTH, false, searchString));
+ AddMenuItem(new cRecMenuItemButtonYesNo(tr("Perform Search"), tr("Cancel"), rmsRecordingSearchResult, rmsClose, true));
+ CalculateHeight();
+ CreatePixmap();
+ Arrange();
+}
+
+// --- cRecMenuRecordingSearchResults ---------------------------------------------------------
+cRecMenuRecordingSearchResults::cRecMenuRecordingSearchResults(std::string searchString, cRecording **searchResults, int numResults) {
+ this->searchString = searchString;
+ this->searchResults = searchResults;
+ SetWidthPercent(80);
+ cString message1 = tr("Found");
+ cString message2 = tr("recording");
+ cString message3 = tr("recordings");
+ cString message4 = tr("for");
+ this->numResults = numResults;
+ cString infoText = cString::sprintf("%s %d %s %s:\n\"%s\"", *message1, numResults, (numResults>1)?(*message3):(*message2), *message4, searchString.c_str());
+ cRecMenuItem *infoItem = new cRecMenuItemInfo(*infoText, true);
+ infoItem->CalculateHeight(width - 2 * border);
+ SetHeader(infoItem);
+
+ cRecMenuItem *buttons = new cRecMenuItemButtonYesNo(tr("Adapt Search"), tr("Close"), rmsRecordingSearch, rmsClose, false);
+ SetFooter(buttons);
+ if (searchResults && (numResults > 0)) {
+ for (int i=0; i<numResults; i++) {
+ if (!AddMenuItemInitial(new cRecMenuItemRecording(searchResults[i], (i==0)?true:false)))
+ break;
+ }
+ }
+ CalculateHeight();
+ CreatePixmap();
+ Arrange();
+}
+
+cRecMenuItem *cRecMenuRecordingSearchResults::GetMenuItem(int number) {
+ if ((number >= 0) && (number < numResults)) {
+ cRecMenuItem *result = new cRecMenuItemRecording(searchResults[number], false);
+ return result;
+ }
+ return NULL;
+}
+
+int cRecMenuRecordingSearchResults::GetTotalNumMenuItems(void) {
+ return numResults;
+}
+
+// --- cRecMenuRecordingSearchNotFound ---------------------------------------------------------
+cRecMenuRecordingSearchNotFound::cRecMenuRecordingSearchNotFound(std::string searchString) {
+ SetWidthPercent(50);
+ cString message = tr("No recordings found for");
+ cString text = cString::sprintf("%s\n\"%s\"",
+ *message,
+ searchString.c_str());
+ cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*text);
+ infoItem->CalculateHeight(width - 2 * border);
+ AddMenuItem(infoItem);
+ AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsClose, true, true));
+ CalculateHeight();
+ CreatePixmap();
+ Arrange();
+}
+
+/******************************************************************************************
+* Timeline
+******************************************************************************************/
+
+// --- cRecMenuTimeline ---------------------------------------------------------
+cRecMenuTimeline::cRecMenuTimeline(cTVGuideTimerConflicts *timerConflicts) {
+ this->timerConflicts = timerConflicts;
+ SetStartStop();
+ conflictsToday = timerConflicts->GetConflictsBetween(timeStart, timeStop);
+ GetTimersForDay();
+ SetWidthPercent(95);
+ header = new cRecMenuItemTimelineHeader(timeStart, conflictsToday);
+ SetHeader(header);
+ cRecMenuItem *footer = new cRecMenuItemButton(tr("Close"), rmsClose, false, true);
+ SetFooter(footer);
+ SetTimers();
+}
+
+void cRecMenuTimeline::SetStartStop(void) {
+ time_t now = time(0);
+ tm *timeStruct = localtime(&now);
+ timeStart = now - timeStruct->tm_hour * 3600 - timeStruct->tm_min * 60 - timeStruct->tm_sec;
+ today = timeStart;
+ timeStop = timeStart + 24*3600 - 1;
+}
+
+
+void cRecMenuTimeline::GetTimersForDay(void) {
+ timersToday.clear();
+ for (cTimer *t = Timers.First(); t; t = Timers.Next(t)) {
+ if (((t->StartTime() > timeStart) && (t->StartTime() <= timeStop)) || ((t->StopTime() > timeStart) && (t->StopTime() <= timeStop))) {
+ timersToday.push_back(t);
+ }
+ }
+ numTimersToday = timersToday.size();
+}
+
+void cRecMenuTimeline::SetTimers(void) {
+ ClearMenu();
+ if (numTimersToday == 0) {
+ AddMenuItem(new cRecMenuItemTimelineTimer(NULL, 0, 0, conflictsToday, header, false));
+ header->UnsetCurrentTimer();
+ footer->setActive();
+ } else {
+ for (int i=0; i<numTimersToday; i++) {
+ cRecMenuItemTimelineTimer *item = new cRecMenuItemTimelineTimer(timersToday[i], timeStart, timeStop, conflictsToday, header, false);
+ if (i==0)
+ item->setActive();
+ if (!AddMenuItemInitial(item))
+ break;
+ }
+ footer->setInactive();
+ }
+ CalculateHeight();
+ CreatePixmap();
+ Arrange();
+}
+
+void cRecMenuTimeline::PrevDay(void) {
+ if ((timeStart - 3600*24) < today)
+ return;
+ timeStart -= 3600*24;
+ timeStop -= 3600*24;
+ conflictsToday = timerConflicts->GetConflictsBetween(timeStart, timeStop);
+ SetWidthPercent(95);
+ header->SetDay(timeStart);
+ header->UnsetCurrentTimer();
+ header->RefreshTimerDisplay();
+ GetTimersForDay();
+ SetTimers();
+ Display();
+}
+
+void cRecMenuTimeline::NextDay(void) {
+ timeStart += 3600*24;
+ timeStop += 3600*24;
+ conflictsToday = timerConflicts->GetConflictsBetween(timeStart, timeStop);
+ SetWidthPercent(95);
+ header->SetDay(timeStart);
+ header->UnsetCurrentTimer();
+ header->RefreshTimerDisplay();
+ GetTimersForDay();
+ SetTimers();
+ Display();
+}
+
+cRecMenuItem *cRecMenuTimeline::GetMenuItem(int number) {
+ if (number < 0)
+ return NULL;
+ if (number >= numTimersToday)
+ return NULL;
+ return new cRecMenuItemTimelineTimer(timersToday[number], timeStart, timeStop, conflictsToday, header, false);
+}
+
+int cRecMenuTimeline::GetTotalNumMenuItems(void) {
+ return numTimersToday;
+}
+
+void cRecMenuTimeline::ClearMenu(void) {
+ InitMenu(true);
+ header->UnsetCurrentTimer();
+}
+
+cTimer *cRecMenuTimeline::GetTimer(void) {
+ if (cRecMenuItemTimelineTimer *activeItem = dynamic_cast<cRecMenuItemTimelineTimer*>(GetActiveMenuItem()))
+ return activeItem->GetTimerValue();
+ return NULL;
+}
+
+
+eRecMenuState cRecMenuTimeline::ProcessKey(eKeys Key) {
+ eRecMenuState state = rmsContinue;
+ switch (Key & ~k_Repeat) {
+ case kLeft:
+ PrevDay();
+ state = rmsConsumed;
+ break;
+ case kRight:
+ NextDay();
+ state = rmsConsumed;
+ break;
+ default:
+ break;
+ }
+ if (state != rmsConsumed) {
+ state = cRecMenu::ProcessKey(Key);
+ }
+ return state;
+}
+
+/******************************************************************************************
+* Favorites
+******************************************************************************************/
+
+// --- cRecMenuFavorites ---------------------------------------------------------
+
+cRecMenuFavorites::cRecMenuFavorites(std::vector<cTVGuideSearchTimer> favorites) {
+ deleteMenuItems = false;
+ this->favorites = favorites;
+ CreateFavoritesMenuItems();
+ numFavorites = myMenuItems.size();
+ SetWidthPercent(70);
+ cString header;
+ if (numFavorites > 0) {
+ header = tr("Favorites");
+ } else {
+ header = tr("No Favorites available");
+ }
+ cRecMenuItemInfo *headerItem = new cRecMenuItemInfo(*header, true);
+ headerItem->CalculateHeight(width - 2 * border);
+ SetHeader(headerItem);
+
+ cRecMenuItem *button = new cRecMenuItemButton(tr("Close"), rmsClose, (numFavorites==0)?true:false);
+ SetFooter(button);
+
+ for (int i=0; i<numFavorites; i++) {
+ if (i==0)
+ myMenuItems[i]->setActive();
+ if (!AddMenuItemInitial(myMenuItems[i]))
+ break;
+ }
+
+ CalculateHeight();
+ CreatePixmap();
+ Arrange();
+}
+
+cRecMenuFavorites::~cRecMenuFavorites(void) {
+ for (std::vector<cRecMenuItem*>::iterator it = myMenuItems.begin(); it != myMenuItems.end(); it++) {
+ delete *it;
+ }
+ myMenuItems.clear();
+}
+
+void cRecMenuFavorites::CreateFavoritesMenuItems(void) {
+ if (tvguideConfig.favWhatsOnNow) {
+ myMenuItems.push_back(new cRecMenuItemFavoriteStatic(tr("What's on now"), rmsFavoritesNow, false));
+ }
+ if (tvguideConfig.favWhatsOnNext) {
+ myMenuItems.push_back(new cRecMenuItemFavoriteStatic(tr("What's on next"), rmsFavoritesNext, false));
+ }
+ if (tvguideConfig.favUseTime1) {
+ std::string desc = *cString::sprintf("%s (%s)", tvguideConfig.descUser1.c_str(), NiceTime(tvguideConfig.favTime1).c_str());
+ myMenuItems.push_back(new cRecMenuItemFavoriteStatic(desc, rmsFavoritesUser1, false));
+ }
+ if (tvguideConfig.favUseTime2) {
+ std::string desc = *cString::sprintf("%s (%s)", tvguideConfig.descUser2.c_str(), NiceTime(tvguideConfig.favTime2).c_str());
+ myMenuItems.push_back(new cRecMenuItemFavoriteStatic(desc, rmsFavoritesUser2, false));
+ }
+ if (tvguideConfig.favUseTime3) {
+ std::string desc = *cString::sprintf("%s (%s)", tvguideConfig.descUser3.c_str(), NiceTime(tvguideConfig.favTime3).c_str());
+ myMenuItems.push_back(new cRecMenuItemFavoriteStatic(desc, rmsFavoritesUser3, false));
+ }
+ if (tvguideConfig.favUseTime4) {
+ std::string desc = *cString::sprintf("%s (%s)", tvguideConfig.descUser4.c_str(), NiceTime(tvguideConfig.favTime4).c_str());
+ myMenuItems.push_back(new cRecMenuItemFavoriteStatic(desc, rmsFavoritesUser4, false));
+ }
+
+ int numAdditionalFavs = favorites.size();
+ for (int i = 0; i < numAdditionalFavs; i++) {
+ myMenuItems.push_back(new cRecMenuItemFavorite(favorites[i], rmsSearchTimerTest, false));
+ }
+
+}
+
+std::string cRecMenuFavorites::NiceTime(int favTime) {
+ int hours = favTime/100;
+ int mins = favTime - hours * 100;
+ return *cString::sprintf("%02d:%02d", hours, mins);
+}
+
+cRecMenuItem *cRecMenuFavorites::GetMenuItem(int number) {
+ if (number > -1 && number < numFavorites)
+ return myMenuItems[number];
+ return NULL;
+}
+
+int cRecMenuFavorites::GetTotalNumMenuItems(void) {
+ return numFavorites;
+}
+
+cTVGuideSearchTimer cRecMenuFavorites::GetFavorite(void) {
+ cRecMenuItemFavorite *activeItem = dynamic_cast<cRecMenuItemFavorite*>(GetActiveMenuItem());
+ return activeItem->GetFavorite();
+}
\ No newline at end of file
diff --git a/recmenus.h b/recmenus.h
new file mode 100644
index 0000000..547eee3
--- /dev/null
+++ b/recmenus.h
@@ -0,0 +1,485 @@
+#ifndef __TVGUIDE_RECMENUS_H
+#define __TVGUIDE_RECMENUS_H
+
+#define TEXTINPUTLENGTH 256
+
+#include <vector>
+#include <functional>
+#include <vdr/epg.h>
+#include "services/epgsearch.h"
+#include "switchtimer.h"
+#include "recmanager.h"
+
+// --- cRecMenuMain ---------------------------------------------------------
+class cRecMenuMain : public cRecMenu {
+public:
+ cRecMenuMain(bool epgSearchAvailable, bool timerActive, bool switchTimerActive);
+ virtual ~cRecMenuMain(void) {};
+};
+
+/******************************************************************************************
+* Instant Timer Menus
+******************************************************************************************/
+
+
+// --- cRecMenuAskFolder ---------------------------------------------------------
+class cRecMenuAskFolder: public cRecMenu {
+private:
+ std::vector<std::string> folders;
+ eRecMenuState NextAction;
+public:
+ cRecMenuAskFolder(const cEvent *event, eRecMenuState nextAction);
+ cRecMenuItem *GetMenuItem(int number);
+ int GetTotalNumMenuItems(void);
+ virtual ~cRecMenuAskFolder(void) {};
+ std::string GetFolder(void);
+};
+
+// --- cRecMenuConfirmTimer ---------------------------------------------------------
+class cRecMenuConfirmTimer: public cRecMenu {
+public:
+ cRecMenuConfirmTimer(const cEvent *event);
+ virtual ~cRecMenuConfirmTimer(void) {};
+};
+
+// --- cRecMenuConfirmDeleteTimer ---------------------------------------------------------
+class cRecMenuConfirmDeleteTimer: public cRecMenu {
+public:
+ cRecMenuConfirmDeleteTimer(const cEvent *event);
+ virtual ~cRecMenuConfirmDeleteTimer(void) {};
+};
+
+// --- cRecMenuAskDeleteTimer ---------------------------------------------------------
+class cRecMenuAskDeleteTimer: public cRecMenu {
+public:
+ cRecMenuAskDeleteTimer(const cEvent *event);
+ virtual ~cRecMenuAskDeleteTimer(void) {};
+};
+
+// --- cRecMenuTimerConflicts ---------------------------------------------------------
+class cRecMenuTimerConflicts: public cRecMenu {
+public:
+ cRecMenuTimerConflicts(cTVGuideTimerConflicts *conflicts);
+ virtual ~cRecMenuTimerConflicts(void) {};
+ int GetTimerConflict(void);
+};
+
+// --- cRecMenuTimerConflict ---------------------------------------------------------
+class cRecMenuTimerConflict: public cRecMenu {
+private:
+ cTVGuideTimerConflict *conflict;
+public:
+ cRecMenuTimerConflict(cTVGuideTimerConflict *conflict);
+ cRecMenuItem *GetMenuItem(int number);
+ int GetTotalNumMenuItems(void);
+ virtual ~cRecMenuTimerConflict(void) {};
+ int GetTimerConflictIndex(void);
+};
+
+// --- cRecMenuNoTimerConflict ---------------------------------------------------------
+class cRecMenuNoTimerConflict: public cRecMenu {
+public:
+ cRecMenuNoTimerConflict(void);
+ virtual ~cRecMenuNoTimerConflict(void) {};
+};
+
+// --- cRecMenuRerunResults ---------------------------------------------------------
+class cRecMenuRerunResults: public cRecMenu {
+private:
+ const cEvent **reruns;
+ int numReruns;
+public:
+ cRecMenuRerunResults(const cEvent *original, const cEvent **reruns, int numReruns);
+ cRecMenuItem *GetMenuItem(int number);
+ int GetTotalNumMenuItems(void);
+ virtual ~cRecMenuRerunResults(void) {
+ delete[] reruns;
+ };
+ const cEvent *GetRerunEvent(void);
+};
+
+// --- cRecMenuNoRerunsFound ---------------------------------------------------------
+class cRecMenuNoRerunsFound: public cRecMenu {
+public:
+ cRecMenuNoRerunsFound(cString searchString);
+ virtual ~cRecMenuNoRerunsFound(void) {};
+};
+
+// --- cRecMenuConfirmRerunUsed ---------------------------------------------------------
+class cRecMenuConfirmRerunUsed: public cRecMenu {
+public:
+ cRecMenuConfirmRerunUsed(const cEvent *original, const cEvent *replace);
+ virtual ~cRecMenuConfirmRerunUsed(void) {};
+};
+
+// --- cRecMenuEditTimer ---------------------------------------------------------
+class cRecMenuEditTimer: public cRecMenu {
+private:
+ cTimer *originalTimer;
+ bool timerActive;
+ time_t day;
+ int start;
+ int stop;
+ int prio;
+ int lifetime;
+ char folder[TEXTINPUTLENGTH];
+public:
+ cRecMenuEditTimer(cTimer *timer, eRecMenuState nextState);
+ virtual ~cRecMenuEditTimer(void) {};
+ cTimer GetTimer(void);
+ cTimer *GetOriginalTimer(void);
+};
+
+/******************************************************************************************
+* Series Timer Menus
+******************************************************************************************/
+
+
+// --- cRecMenuSeriesTimer ---------------------------------------------------------
+class cRecMenuSeriesTimer: public cRecMenu {
+ std::string folder;
+ bool timerActive;
+ int channel;
+ time_t tstart;
+ int start;
+ int stop;
+ int dayOfWeek;
+ int priority;
+ int lifetime;
+ void CalculateTimes(const cEvent *event);
+public:
+ cRecMenuSeriesTimer(cChannel *initialChannel, const cEvent *event, std::string folder);
+ virtual ~cRecMenuSeriesTimer(void) {};
+ cTimer *GetTimer(void);
+};
+
+// --- cRecMenuConfirmSeriesTimer ---------------------------------------------------------
+class cRecMenuConfirmSeriesTimer: public cRecMenu {
+public:
+ cRecMenuConfirmSeriesTimer(cTimer *seriesTimer);
+ virtual ~cRecMenuConfirmSeriesTimer(void) {};
+};
+
+/******************************************************************************************
+* SearchTimer Menus
+******************************************************************************************/
+
+// --- cRecMenuSearchTimer ---------------------------------------------------------
+class cRecMenuSearchTimer: public cRecMenu {
+private:
+ char searchString[TEXTINPUTLENGTH];
+public:
+ cRecMenuSearchTimer(const cEvent *event);
+ virtual ~cRecMenuSearchTimer(void) {};
+ std::string GetSearchString(void) { return searchString; };
+};
+
+// --- cRecMenuSearchTimerTemplates ---------------------------------------------------------
+class cRecMenuSearchTimerTemplates: public cRecMenu {
+private:
+ int numTemplates;
+ cTVGuideSearchTimer searchTimer;
+ std::vector<TVGuideEPGSearchTemplate> templates;
+public:
+ cRecMenuSearchTimerTemplates(cTVGuideSearchTimer searchTimer, std::vector<TVGuideEPGSearchTemplate> templates);
+ cRecMenuItem *GetMenuItem(int number);
+ int GetTotalNumMenuItems(void);
+ virtual ~cRecMenuSearchTimerTemplates(void) {};
+ cTVGuideSearchTimer GetSearchTimer(void) { return searchTimer; };
+ TVGuideEPGSearchTemplate GetTemplate(void);
+};
+
+
+// --- cRecMenuSearchTimers ---------------------------------------------------------
+class cRecMenuSearchTimers: public cRecMenu {
+private:
+ int numSearchTimers;
+ std::vector<cTVGuideSearchTimer> searchTimers;
+ void SetMenuItems(void);
+public:
+ cRecMenuSearchTimers(std::vector<cTVGuideSearchTimer> searchTimers);
+ cRecMenuItem *GetMenuItem(int number);
+ int GetTotalNumMenuItems(void);
+ cTVGuideSearchTimer GetSearchTimer(void);
+ virtual ~cRecMenuSearchTimers(void);
+};
+
+// --- cRecMenuSearchTimerEdit ---------------------------------------------------------
+class cRecMenuSearchTimerEdit: public cRecMenu {
+private:
+ bool advancedOptions;
+ cTVGuideSearchTimer searchTimer;
+ std::vector<cRecMenuItem*> mainMenuItems;
+ std::vector<cRecMenuItem*> useChannelSubMenu;
+ std::vector<cRecMenuItem*> useTimeSubMenu;
+ std::vector<cRecMenuItem*> useDayOfWeekSubMenu;
+ std::vector<cRecMenuItem*> avoidRepeatSubMenu;
+ std::vector<cRecMenuItem*> currentMenuItems;
+ int numMenuItems;
+ int useChannelPos;
+ int useTimePos;
+ int useDayOfWeekPos;
+ int avoidRepeatsPos;
+ char searchString[TEXTINPUTLENGTH];
+ bool timerActive;
+ int mode;
+ bool useTitle;
+ bool useSubtitle;
+ bool useDescription;
+ bool useChannel;
+ int startChannel;
+ int stopChannel;
+ bool useTime;
+ int startTime;
+ int stopTime;
+ bool useDayOfWeek;
+ int dayOfWeek;
+ int priority;
+ int lifetime;
+ bool useEpisode;
+ char directory[TEXTINPUTLENGTH];
+ int marginStart;
+ int marginStop;
+ bool useVPS;
+ bool avoidRepeats;
+ int allowedRepeats;
+ bool compareTitle;
+ bool compareSubtitle;
+ bool compareSummary;
+ bool useInFavorites;
+ void InitMenuItems(void);
+ void AddSubMenu(std::vector<cRecMenuItem*> *subMenu);
+public:
+ cRecMenuSearchTimerEdit(cTVGuideSearchTimer searchTimer, bool advancedOptions);
+ void CreateMenuItems(void);
+ virtual ~cRecMenuSearchTimerEdit(void);
+ cTVGuideSearchTimer GetSearchTimer(void);
+ cRecMenuItem *GetMenuItem(int number);
+ int GetTotalNumMenuItems(void);
+};
+
+// --- cRecMenuSearchTimerDeleteConfirm ---------------------------------------------
+class cRecMenuSearchTimerDeleteConfirm: public cRecMenu {
+private:
+ cTVGuideSearchTimer searchTimer;
+public:
+ cRecMenuSearchTimerDeleteConfirm(cTVGuideSearchTimer searchTimer);
+ virtual ~cRecMenuSearchTimerDeleteConfirm(void);
+ cTVGuideSearchTimer GetSearchTimer(void);
+};
+
+// --- cRecMenuSearchTimerCreateConfirm ---------------------------------------------------------
+class cRecMenuSearchTimerCreateConfirm: public cRecMenu {
+private:
+public:
+ cRecMenuSearchTimerCreateConfirm(bool success);
+ virtual ~cRecMenuSearchTimerCreateConfirm(void) {};
+};
+
+// --- cRecMenuSearchTimerTemplatesCreate ---------------------------------------------------------
+class cRecMenuSearchTimerTemplatesCreate: public cRecMenu {
+private:
+ TVGuideEPGSearchTemplate templ;
+ cTVGuideSearchTimer searchTimer;
+public:
+ cRecMenuSearchTimerTemplatesCreate(TVGuideEPGSearchTemplate templ, cTVGuideSearchTimer searchTimer);
+ virtual ~cRecMenuSearchTimerTemplatesCreate(void) {};
+ cTVGuideSearchTimer GetSearchTimer(void) { return searchTimer; };
+ TVGuideEPGSearchTemplate GetTemplate(void) { return templ; };
+};
+
+// --- cRecMenuSearchTimerResults ---------------------------------------------------------
+class cRecMenuSearchTimerResults: public cRecMenu {
+private:
+ const cEvent **searchResults;
+ int numResults;
+ eRecMenuState action2;
+public:
+ cRecMenuSearchTimerResults(std::string searchString, const cEvent **searchResults, int numResults, std::string templateName = "", eRecMenuState action2 = rmsDisabled);
+ cRecMenuItem *GetMenuItem(int number);
+ int GetTotalNumMenuItems(void);
+ virtual ~cRecMenuSearchTimerResults(void) {
+ delete[] searchResults;
+ };
+ const cEvent *GetEvent(void);
+};
+
+// --- cRecMenuSearchTimerNothingFound ---------------------------------------------------------
+class cRecMenuSearchTimerNothingFound: public cRecMenu {
+public:
+ cRecMenuSearchTimerNothingFound(std::string searchString);
+ virtual ~cRecMenuSearchTimerNothingFound(void) {};
+};
+
+/******************************************************************************************
+* SwitchTimer Menus
+******************************************************************************************/
+
+// --- cRecMenuSwitchTimer ---------------------------------------------------------
+class cRecMenuSwitchTimer: public cRecMenu {
+private:
+ int switchMinsBefore;
+ int announceOnly;
+public:
+ cRecMenuSwitchTimer(void);
+ virtual ~cRecMenuSwitchTimer(void) {};
+ cSwitchTimer GetSwitchTimer(void);
+};
+
+// --- cRecMenuSwitchTimerConfirm ---------------------------------------------------------
+class cRecMenuSwitchTimerConfirm: public cRecMenu {
+private:
+public:
+ cRecMenuSwitchTimerConfirm(bool success);
+ virtual ~cRecMenuSwitchTimerConfirm(void) {};
+};
+
+// --- cRecMenuSwitchTimerDelete ---------------------------------------------------------
+class cRecMenuSwitchTimerDelete: public cRecMenu {
+private:
+public:
+ cRecMenuSwitchTimerDelete(void);
+ virtual ~cRecMenuSwitchTimerDelete(void) {};
+};
+
+/******************************************************************************************
+* Search Menus
+******************************************************************************************/
+
+// --- cRecMenuSearch ---------------------------------------------------------
+class cRecMenuSearch: public cRecMenu {
+private:
+ char searchString[TEXTINPUTLENGTH];
+ int mode;
+ int channelNr;
+ bool useTitle;
+ bool useSubTitle;
+ bool useDescription;
+public:
+ cRecMenuSearch(std::string searchString, bool withOptions);
+ virtual ~cRecMenuSearch(void) {};
+ Epgsearch_searchresults_v1_0 GetEPGSearchStruct(void);
+ std::string GetSearchString(void) { return searchString; };
+};
+
+// --- cRecMenuSearchResults ---------------------------------------------------------
+class cRecMenuSearchResults: public cRecMenu {
+private:
+ std::string searchString;
+ const cEvent **searchResults;
+ int numResults;
+public:
+ cRecMenuSearchResults(std::string searchString, const cEvent **searchResults, int numResults);
+ cRecMenuItem *GetMenuItem(int number);
+ int GetTotalNumMenuItems(void);
+ virtual ~cRecMenuSearchResults(void) {
+ delete[] searchResults;
+ };
+ const cEvent *GetEvent(void);
+ std::string GetSearchString(void) { return searchString; };
+};
+
+// --- cRecMenuSearchConfirmTimer ---------------------------------------------------------
+class cRecMenuSearchConfirmTimer: public cRecMenu {
+public:
+ cRecMenuSearchConfirmTimer(const cEvent *event, eRecMenuState nextAction);
+ virtual ~cRecMenuSearchConfirmTimer(void) {};
+};
+
+// --- cRecMenuSearchNothingFound ---------------------------------------------------------
+class cRecMenuSearchNothingFound: public cRecMenu {
+public:
+ cRecMenuSearchNothingFound(std::string searchString, bool tooShort = false);
+ virtual ~cRecMenuSearchNothingFound(void) {};
+};
+
+/******************************************************************************************
+* Recording Search Menus
+******************************************************************************************/
+
+
+// --- cRecMenuRecordingSearch ---------------------------------------------------------
+class cRecMenuRecordingSearch: public cRecMenu {
+private:
+ char searchString[TEXTINPUTLENGTH];
+public:
+ cRecMenuRecordingSearch(std::string search);
+ virtual ~cRecMenuRecordingSearch(void) {};
+ std::string GetSearchString(void) { return searchString; };
+};
+
+// --- cRecMenuRecordingSearchResults ---------------------------------------------------------
+class cRecMenuRecordingSearchResults: public cRecMenu {
+private:
+ std::string searchString;
+ cRecording **searchResults;
+ int numResults;
+public:
+ cRecMenuRecordingSearchResults(std::string searchString, cRecording **searchResults, int numResults);
+ cRecMenuItem *GetMenuItem(int number);
+ int GetTotalNumMenuItems(void);
+ virtual ~cRecMenuRecordingSearchResults(void) {
+ delete[] searchResults;
+ };
+ std::string GetSearchString(void) { return searchString; };
+};
+
+// --- cRecMenuRecordingSearchNotFound ---------------------------------------------------------
+class cRecMenuRecordingSearchNotFound: public cRecMenu {
+public:
+ cRecMenuRecordingSearchNotFound(std::string searchString);
+ virtual ~cRecMenuRecordingSearchNotFound(void) {};
+};
+
+/******************************************************************************************
+* Timeline
+******************************************************************************************/
+
+// --- cRecMenuTimeline ---------------------------------------------------------
+class cRecMenuTimeline: public cRecMenu {
+private:
+ std::vector<cTimer*> timersToday;
+ int numTimersToday;
+ time_t today;
+ time_t timeStart;
+ time_t timeStop;
+ cTVGuideTimerConflicts *timerConflicts;
+ std::vector<cTVGuideTimerConflict*> conflictsToday;
+ cRecMenuItemTimelineHeader *header;
+ void SetStartStop(void);
+ void GetTimersForDay(void);
+ void SetTimers(void);
+ void PrevDay(void);
+ void NextDay(void);
+ void ClearMenu(void);
+public:
+ cRecMenuTimeline(cTVGuideTimerConflicts *timerConflicts);
+ cRecMenuItem *GetMenuItem(int number);
+ int GetTotalNumMenuItems(void);
+ virtual ~cRecMenuTimeline(void) {
+ };
+ eRecMenuState ProcessKey(eKeys Key);
+ cTimer *GetTimer(void);
+};
+
+/******************************************************************************************
+* Favorites
+******************************************************************************************/
+
+// --- cRecMenuFavorites ---------------------------------------------------------
+class cRecMenuFavorites: public cRecMenu {
+private:
+ std::vector<cTVGuideSearchTimer> favorites;
+ std::vector<cRecMenuItem*> myMenuItems;
+ int numFavorites;
+ void CreateFavoritesMenuItems(void);
+ std::string NiceTime(int favTime);
+public:
+ cRecMenuFavorites(std::vector<cTVGuideSearchTimer> favorites);
+ cRecMenuItem *GetMenuItem(int number);
+ int GetTotalNumMenuItems(void);
+ cTVGuideSearchTimer GetFavorite(void);
+ virtual ~cRecMenuFavorites(void);
+};
+
+#endif //__TVGUIDE_RECMENUS_H
\ No newline at end of file
diff --git a/searchtimer.c b/searchtimer.c
new file mode 100644
index 0000000..7e9b4db
--- /dev/null
+++ b/searchtimer.c
@@ -0,0 +1,570 @@
+#include <string>
+#include <vector>
+#include <sstream>
+#include <algorithm>
+#include <vdr/channels.h>
+#include <vdr/device.h>
+#include "tools.h"
+#include "searchtimer.h"
+
+// -- cTVGuideSearchTimer -----------------------------------------------------------------
+cTVGuideSearchTimer::cTVGuideSearchTimer(void) {
+ strTimer = "";
+ ID = -1;
+ searchString = "";
+ useTime = false;
+ startTime = 0000;
+ stopTime = 2359;
+ useChannel = false;
+ channelMin = Channels.GetByNumber(cDevice::CurrentChannel());
+ channelMax = Channels.GetByNumber(cDevice::CurrentChannel());
+ channelGroup = "";
+ useCase = false;
+ mode = 0;
+ useTitle = true;
+ useSubtitle = true;
+ useDescription = true;
+ useDuration = false;
+ minDuration = 0;
+ maxDuration = 2359;
+ useAsSearchTimer = true;
+ useDayOfWeek = false;
+ dayOfWeek = 0;
+ directory = "";
+ useEpisode = 0;
+ priority = 99;
+ lifetime = 99;
+ marginStart = 5;
+ marginStop = 5;
+ useVPS = false;
+ action = 0;
+ useExtEPGInfo = 0;
+ extEPGInfoValues = "";
+ avoidRepeats = 1;
+ allowedRepeats = 1;
+ compareTitle = 1;
+ compareSubtitle = 2;
+ compareSummary = 1;
+ catvaluesAvoidRepeat = 0;
+ repeatsWithinDays = 0;
+ delAfterDays = 0;
+ recordingsKeep = 0;
+ switchMinsBefore = 0;
+ pauseOnNrRecordings = 0;
+ blacklistMode = 0;
+ blacklists = "";
+ fuzzyTolerance = 0;
+ useInFavorites = 0;
+ menuTemplate = 0;
+ delMode = 0;
+ delAfterCountRecs = 0;
+ delAfterDaysOfFirstRec = 0;
+ useAsSearchTimerFrom = 0;
+ useAsSearchTimerTil = 0;
+ ignoreMissingEPGCats = 0;
+ unmuteSoundOnSwitch = 0;
+ compareSummaryMatchInPercent = 0;
+ contentsFilter = "";
+ compareDate = 0;
+}
+
+cTVGuideSearchTimer::~cTVGuideSearchTimer(void) {
+}
+
+bool cTVGuideSearchTimer::operator < (const cTVGuideSearchTimer& other) const {
+ std::string searchStringOther = other.SearchString();
+ searchStringOther = StrToLowerCase(searchStringOther);
+ std::string thisSearchString = StrToLowerCase(searchString);
+ int comp = thisSearchString.compare(searchStringOther);
+ if (comp < 0)
+ return true;
+ return false;
+}
+
+
+void cTVGuideSearchTimer::SetTemplate(std::string tmpl) {
+ std::stringstream searchTimerString;
+ searchTimerString << "0:";
+ searchTimerString << tmpl;
+ strTimer = searchTimerString.str();
+}
+
+int cTVGuideSearchTimer::DayOfWeek(void) {
+ int vdrDayOfWeek = 0;
+ if (dayOfWeek >= 0) {
+ vdrDayOfWeek = pow(2, (dayOfWeek+6)%7);
+ } else if (dayOfWeek < 0) {
+ int absDayOfWeek = abs(dayOfWeek);
+ for (int i=0; i < 7; i++) {
+ if (absDayOfWeek & (1 << i)) {
+ vdrDayOfWeek += pow(2, (i+6)%7);
+ }
+ }
+ }
+ return vdrDayOfWeek;
+}
+
+void cTVGuideSearchTimer::SetDayOfWeek(int VDRDayOfWeek) {
+ int epgSearchDayOfWeek = 0;
+ for (int i=0; i < 7; i++) {
+ if (VDRDayOfWeek & (1 << i)) {
+ epgSearchDayOfWeek += pow(2, (i+1)%7);
+ }
+ }
+ this->dayOfWeek = epgSearchDayOfWeek * (-1);
+}
+
+/*
+ 0 - unique search timer id
+ 1 - the search term
+ 2 - use time? 0/1
+ 3 - start time in HHMM
+ 4 - stop time in HHMM
+ 5 - use channel? 0 = no, 1 = Interval, 2 = Channel group, 3 = FTA only
+ 6 - if 'use channel' = 1 then channel id[|channel id] in VDR format,
+ one entry or min/max entry separated with |, if 'use channel' = 2
+ then the channel group name
+ 7 - match case? 0/1
+ 8 - search mode:
+ 0 - the whole term must appear as substring
+ 1 - all single terms (delimiters are blank,',', ';', '|' or '~')
+ must exist as substrings.
+ 2 - at least one term (delimiters are blank, ',', ';', '|' or '~')
+ must exist as substring.
+ 3 - matches exactly
+ 4 - regular expression
+ 9 - use title? 0/1
+ 10 - use subtitle? 0/1
+ 11 - use description? 0/1
+ 12 - use duration? 0/1
+ 13 - min duration in hhmm
+ 14 - max duration in hhmm
+ 15 - use as search timer? 0/1
+ 16 - use day of week? 0/1
+ 17 - day of week (0 = Sunday, 1 = Monday...;
+ -1 Sunday, -2 Monday, -4 Tuesday, ...; -7 Sun, Mon, Tue)
+ 18 - use series recording? 0/1
+ 19 - directory for recording
+ 20 - priority of recording
+ 21 - lifetime of recording
+ 22 - time margin for start in minutes
+ 23 - time margin for stop in minutes
+ 24 - use VPS? 0/1
+ 25 - action:
+ 0 = create a timer
+ 1 = announce only via OSD (no timer)
+ 2 = switch only (no timer)
+ 3 = announce via OSD and switch (no timer)
+ 4 = announce via mail
+ 26 - use extended EPG info? 0/1
+ 27 - extended EPG info values. This entry has the following format
+ (delimiter is '|' for each category, '#' separates id and value):
+ 1 - the id of the extended EPG info category as specified in
+ epgsearchcats.conf
+ 2 - the value of the extended EPG info category
+ (a ':' will be translated to "!^colon^!", e.g. in "16:9")
+ 28 - avoid repeats? 0/1
+ 29 - allowed repeats
+ 30 - compare title when testing for a repeat? 0/1
+ 31 - compare subtitle when testing for a repeat? 0/1/2
+ 0 - no
+ 1 - yes
+ 2 - yes, if present
+ 32 - compare description when testing for a repeat? 0/1
+ 33 - compare extended EPG info when testing for a repeat?
+ This entry is a bit field of the category IDs.
+ 34 - accepts repeats only within x days
+ 35 - delete a recording automatically after x days
+ 36 - but keep this number of recordings anyway
+ 37 - minutes before switch (if action = 2)
+ 38 - pause if x recordings already exist
+ 39 - blacklist usage mode (0 none, 1 selection, 2 all)
+ 40 - selected blacklist IDs separated with '|'
+ 41 - fuzzy tolerance value for fuzzy searching
+ 42 - use this search in favorites menu (0 no, 1 yes)
+ 43 - id of a menu search template
+ 44 - auto deletion mode (0 don't delete search timer, 1 delete after given
+ count of recordings, 2 delete after given days after first recording)
+ 45 - count of recordings after which to delete the search timer
+ 46 - count of days after the first recording after which to delete the search
+ timer
+ 47 - first day where the search timer is active (see parameter 16)
+ 48 - last day where the search timer is active (see parameter 16)
+ 49 - ignore missing EPG categories? 0/1
+ 50 - unmute sound if off when used as switch timer
+ 51 - percentage of match when comparing the summary of two events (with 'avoid repeats')
+ 52 - HEX representation of the content descriptors, each descriptor ID is represented with 2 chars
+ 53 - compare date when testing for a repeat? (0=no, 1=same day, 2=same week, 3=same month)
+*/
+bool cTVGuideSearchTimer::Parse(bool readTemplate) {
+ splitstring s(strTimer.c_str());
+ std::vector<std::string> values = s.split(':', 1);
+ int numValues = values.size();
+ if (numValues < 12)
+ return false;
+ for (int value = 0; value < numValues; value++) {
+ switch (value) {
+ case 0:
+ if (!readTemplate)
+ ID = atoi(values[value].c_str());
+ break;
+ case 1:
+ if (!readTemplate) {
+ std::string searchStringMasked = values[value];
+ std::replace(searchStringMasked.begin(), searchStringMasked.end(), '|', ':');
+ searchString = searchStringMasked;
+ }
+ break;
+ case 2:
+ useTime = atoi(values[value].c_str());
+ break;
+ case 3:
+ if (useTime) {
+ startTime = atoi(values[value].c_str());
+ }
+ break;
+ case 4:
+ if (useTime) {
+ stopTime = atoi(values[value].c_str());
+ }
+ break;
+ case 5:
+ useChannel = atoi(values[value].c_str());
+ break;
+ case 6:
+ if (useChannel == 0) {
+ channelMin = NULL;
+ channelMax = NULL;
+ } else if (useChannel == 1) {
+ char *channelMinbuffer = NULL;
+ char *channelMaxbuffer = NULL;
+ int channels = sscanf(values[value].c_str(), "%a[^|]|%a[^|]", &channelMinbuffer, &channelMaxbuffer);
+ channelMin = Channels.GetByChannelID(tChannelID::FromString(channelMinbuffer), true, true);
+ if (!channelMin) {
+ channelMin = channelMax = NULL;
+ useChannel = 0;
+ }
+ if (channels == 1)
+ channelMax = channelMin;
+ else {
+ channelMax = Channels.GetByChannelID(tChannelID::FromString(channelMaxbuffer), true, true);
+ if (!channelMax) {
+ channelMin = channelMax = NULL;
+ useChannel = 0;
+ }
+ }
+ free(channelMinbuffer);
+ free(channelMaxbuffer);
+ } else if (useChannel == 2) {
+ channelGroup = values[value];
+ }
+ break;
+ case 7:
+ useCase = atoi(values[value].c_str());
+ break;
+ case 8:
+ mode = atoi(values[value].c_str());
+ break;
+ case 9:
+ useTitle = atoi(values[value].c_str());
+ break;
+ case 10:
+ useSubtitle = atoi(values[value].c_str());
+ break;
+ case 11:
+ useDescription = atoi(values[value].c_str());
+ break;
+ case 12:
+ useDuration = atoi(values[value].c_str());
+ break;
+ case 13:
+ minDuration = atoi(values[value].c_str());
+ break;
+ case 14:
+ maxDuration = atoi(values[value].c_str());
+ break;
+ case 15:
+ useAsSearchTimer = atoi(values[value].c_str());
+ break;
+ case 16:
+ useDayOfWeek = atoi(values[value].c_str());
+ break;
+ case 17:
+ dayOfWeek = atoi(values[value].c_str());
+ break;
+ case 18:
+ useEpisode = atoi(values[value].c_str());
+ break;
+ case 19:
+ directory = values[value];
+ break;
+ case 20:
+ priority = atoi(values[value].c_str());
+ break;
+ case 21:
+ lifetime = atoi(values[value].c_str());
+ break;
+ case 22:
+ marginStart = atoi(values[value].c_str());
+ break;
+ case 23:
+ marginStop = atoi(values[value].c_str());
+ break;
+ case 24:
+ useVPS = atoi(values[value].c_str());
+ break;
+ case 25:
+ action = atoi(values[value].c_str());
+ break;
+ case 26:
+ useExtEPGInfo = atoi(values[value].c_str());
+ break;
+ case 27:
+ extEPGInfoValues = values[value];
+ break;
+ case 28:
+ avoidRepeats = atoi(values[value].c_str());
+ break;
+ case 29:
+ allowedRepeats = atoi(values[value].c_str());
+ break;
+ case 30:
+ compareTitle = atoi(values[value].c_str());
+ break;
+ case 31:
+ compareSubtitle = atoi(values[value].c_str());
+ break;
+ case 32:
+ compareSummary = atoi(values[value].c_str());
+ break;
+ case 33:
+ catvaluesAvoidRepeat = atol(values[value].c_str());
+ break;
+ case 34:
+ repeatsWithinDays = atoi(values[value].c_str());
+ break;
+ case 35:
+ delAfterDays = atoi(values[value].c_str());
+ break;
+ case 36:
+ recordingsKeep = atoi(values[value].c_str());
+ break;
+ case 37:
+ switchMinsBefore = atoi(values[value].c_str());
+ break;
+ case 38:
+ pauseOnNrRecordings = atoi(values[value].c_str());
+ break;
+ case 39:
+ blacklistMode = atoi(values[value].c_str());
+ break;
+ case 40:
+ blacklists = values[value];
+ break;
+ case 41:
+ fuzzyTolerance = atoi(values[value].c_str());
+ break;
+ case 42:
+ useInFavorites = atoi(values[value].c_str());
+ break;
+ case 43:
+ menuTemplate = atoi(values[value].c_str());
+ break;
+ case 44:
+ delMode = atoi(values[value].c_str());
+ break;
+ case 45:
+ delAfterCountRecs = atoi(values[value].c_str());
+ break;
+ case 46:
+ delAfterDaysOfFirstRec = atoi(values[value].c_str());
+ break;
+ case 47:
+ useAsSearchTimerFrom = atol(values[value].c_str());
+ break;
+ case 48:
+ useAsSearchTimerTil = atol(values[value].c_str());
+ break;
+ case 49:
+ ignoreMissingEPGCats = atoi(values[value].c_str());
+ break;
+ case 50:
+ unmuteSoundOnSwitch = atoi(values[value].c_str());
+ break;
+ case 51:
+ compareSummaryMatchInPercent = atoi(values[value].c_str());
+ break;
+ case 52:
+ contentsFilter = values[value];
+ break;
+ case 53:
+ compareDate = atoi(values[value].c_str());
+ break;
+ default:
+ break;
+ }
+ }
+ return true;
+}
+
+std::string cTVGuideSearchTimer::BuildSearchString(void) {
+ std::stringstream search;
+ // 0 - 2
+ if (ID > -1)
+ search << ID << ":";
+ else
+ search << ":";
+ std::string searchStringMasked = searchString;
+ std::replace(searchStringMasked.begin(), searchStringMasked.end(), ':', '|');
+ search << searchStringMasked << ":";
+ search << useTime << ":";
+
+ // 3 - 6
+ if (useTime) {
+ search << *cString::sprintf("%04d", startTime) << ":";
+ search << *cString::sprintf("%04d", stopTime) << ":";
+ } else {
+ search << "::";
+ }
+
+ search << useChannel << ":";
+ if (useChannel == 1) {
+ if (channelMin && channelMax) {
+ if (channelMin->Number() < channelMax->Number())
+ search << std::string(channelMin->GetChannelID().ToString()) << "|" << std::string(channelMax->GetChannelID().ToString()) << ":";
+ else
+ search << std::string(channelMin->GetChannelID().ToString()) << ":";
+ } else {
+ search << "0:";
+ }
+ } else if (useChannel == 2) {
+ search << channelGroup << ":";
+ } else {
+ search << "0:";
+ }
+ // 7 - 14
+ search << useCase << ":";
+ search << mode << ":";
+ search << useTitle << ":";
+ search << useSubtitle << ":";
+ search << useDescription << ":";
+ search << useDuration << ":";
+ if (useDuration) {
+ search << *cString::sprintf("%04d", minDuration) << ":";
+ search << *cString::sprintf("%04d", maxDuration) << ":";
+ } else {
+ search << "::";
+ }
+ //15 - 53
+ search << useAsSearchTimer << ":";
+ search << useDayOfWeek << ":";
+ search << dayOfWeek << ":";
+ search << useEpisode << ":";
+ search << directory << ":";
+ search << priority << ":";
+ search << lifetime << ":";
+ search << marginStart << ":";
+ search << marginStop << ":";
+ search << useVPS << ":";
+ search << action << ":";
+ search << useExtEPGInfo << ":";
+ search << extEPGInfoValues << ":";
+ search << avoidRepeats << ":";
+ search << allowedRepeats << ":";
+ search << compareTitle << ":";
+ search << compareSubtitle << ":";
+ search << compareSummary << ":";
+ search << catvaluesAvoidRepeat << ":";
+ search << repeatsWithinDays << ":";
+ search << delAfterDays << ":";
+ search << recordingsKeep << ":";
+ search << switchMinsBefore << ":";
+ search << pauseOnNrRecordings << ":";
+ search << blacklistMode << ":";
+ search << blacklists << ":";
+ search << fuzzyTolerance << ":";
+ search << useInFavorites << ":";
+ search << menuTemplate << ":";
+ search << delMode << ":";
+ search << delAfterCountRecs << ":";
+ search << delAfterDaysOfFirstRec << ":";
+ search << useAsSearchTimerFrom << ":";
+ search << useAsSearchTimerTil << ":";
+ search << ignoreMissingEPGCats << ":";
+ search << unmuteSoundOnSwitch << ":";
+ search << compareSummaryMatchInPercent << ":";
+ search << contentsFilter << ":";
+ search << compareDate;
+
+ strTimer = search.str();
+ return strTimer;
+}
+
+bool cTVGuideSearchTimer::Active(void) {
+ if (useAsSearchTimer)
+ return true;
+ return false;
+}
+
+
+int cTVGuideSearchTimer::GetNumTimers(void) {
+ int numTimers = 0;
+ if (ID < 0)
+ return numTimers;
+ for (cTimer *timer = Timers.First(); timer; timer = Timers.Next(timer)) {
+ char* searchID = GetAuxValue(timer, "s-id");
+ if (!searchID) continue;
+ if (ID == atoi(searchID))
+ numTimers++;
+ free(searchID);
+ }
+ return numTimers;
+}
+
+int cTVGuideSearchTimer::GetNumRecordings(void) {
+ int numRecordings = 0;
+ if (ID < 0)
+ return numRecordings;
+ for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording)) {
+ if (recording->IsEdited())
+ continue;
+ if (!recording->Info())
+ continue;
+ char* searchID = GetAuxValue(recording, "s-id");
+ if (!searchID) continue;
+ if (ID == atoi(searchID))
+ numRecordings++;
+ free(searchID);
+ }
+ return numRecordings;
+}
+
+void cTVGuideSearchTimer::GetSearchModes(std::vector<std::string> *searchModes) {
+ searchModes->push_back(tr("whole term must appear"));
+ searchModes->push_back(tr("all terms must exist"));
+ searchModes->push_back(tr("one term must exist"));
+ searchModes->push_back(tr("exact match"));
+ searchModes->push_back(tr("regular expression"));
+}
+
+
+void cTVGuideSearchTimer::Dump(void) {
+ esyslog("tvguide searchtimer: strTimer: %s", strTimer.c_str());
+ esyslog("tvguide searchtimer: ID: %d", ID);
+ esyslog("tvguide searchtimer: searchString: %s", searchString.c_str());
+ esyslog("tvguide searchtimer: useTime: %d", useTime);
+ esyslog("tvguide searchtimer: startTime: %d", startTime);
+ esyslog("tvguide searchtimer: stopTime: %d", stopTime);
+ esyslog("tvguide searchtimer: useChannel: %d", useChannel);
+ if (channelMin)
+ esyslog("tvguide searchtimer: channelMin: %s", channelMin->Name());
+ if (channelMax)
+ esyslog("tvguide searchtimer: channelMax: %s", channelMax->Name());
+ esyslog("tvguide searchtimer: channelGroup: %s", channelGroup.c_str());
+ esyslog("tvguide searchtimer: useCase: %d", useCase);
+ esyslog("tvguide searchtimer: mode: %d", mode);
+ esyslog("tvguide searchtimer: useTitle: %d", useTitle);
+ esyslog("tvguide searchtimer: useSubtitle: %d", useSubtitle);
+ esyslog("tvguide searchtimer: useDescription: %d", useDescription);
+}
+
diff --git a/searchtimer.h b/searchtimer.h
new file mode 100644
index 0000000..f797ebd
--- /dev/null
+++ b/searchtimer.h
@@ -0,0 +1,136 @@
+#ifndef __TVGUIDE_SEARCHTIMER_H
+#define __TVGUIDE_SEARCHTIMER_H
+
+
+class cTVGuideSearchTimer {
+private:
+ std::string strTimer;
+ int ID;
+ std::string searchString;
+ int useTime;
+ int startTime;
+ int stopTime;
+ int useChannel;
+ cChannel *channelMin;
+ cChannel *channelMax;
+ std::string channelGroup;
+ int useCase;
+ int mode;
+ int useTitle;
+ int useSubtitle;
+ int useDescription;
+ int useDuration;
+ int minDuration;
+ int maxDuration;
+ int useAsSearchTimer;
+ int useDayOfWeek;
+ int dayOfWeek;
+ int useEpisode;
+ std::string directory;
+ int priority;
+ int lifetime;
+ int marginStart;
+ int marginStop;
+ int useVPS;
+ int action;
+ int useExtEPGInfo;
+ std::string extEPGInfoValues;
+ int avoidRepeats;
+ int allowedRepeats;
+ int compareTitle;
+ int compareSubtitle;
+ int compareSummary;
+ unsigned long catvaluesAvoidRepeat;
+ int repeatsWithinDays;
+ int delAfterDays;
+ int recordingsKeep;
+ int switchMinsBefore;
+ int pauseOnNrRecordings;
+ int blacklistMode;
+ std::string blacklists;
+ int fuzzyTolerance;
+ int useInFavorites;
+ int menuTemplate;
+ int delMode;
+ int delAfterCountRecs;
+ int delAfterDaysOfFirstRec;
+ int useAsSearchTimerFrom;
+ int useAsSearchTimerTil;
+ int ignoreMissingEPGCats;
+ int unmuteSoundOnSwitch;
+ int compareSummaryMatchInPercent;
+ std::string contentsFilter;
+ int compareDate;
+public:
+ cTVGuideSearchTimer(void);
+ virtual ~cTVGuideSearchTimer(void);
+ bool operator < (const cTVGuideSearchTimer& other) const;
+ void SetEPGSearchString(std::string strTimer) { this->strTimer = strTimer; };
+ void SetTemplate(std::string tmpl);
+ bool Parse(bool readTemplate = false);
+ std::string BuildSearchString(void);
+ int GetID(void) { return ID; };
+ //GETTER
+ std::string SearchString(void) const { return searchString; };
+ bool Active(void);
+ bool UseTitle(void) { return useTitle; };
+ bool UseSubtitle(void) { return useSubtitle; };
+ bool UseDescription(void) { return useDescription; };
+ int SearchMode(void) { return mode; };
+ bool UseChannel(void) { return useChannel; };
+ int StartChannel(void) { return (channelMin)?channelMin->Number():0; };
+ int StopChannel(void) { return (channelMax)?channelMax->Number():0; };
+ bool UseTime(void) { return useTime; };
+ int StartTime(void) { return startTime; };
+ int StopTime(void) { return stopTime; };
+ bool UseDayOfWeek(void) { return useDayOfWeek; };
+ int DayOfWeek(void);
+ int UseEpisode(void) { return useEpisode; };
+ std::string Directory(void) { return directory; };
+ int Priority(void) { return priority; };
+ int Lifetime(void) { return lifetime; };
+ int MarginStart(void) { return marginStart; };
+ int MarginStop(void) { return marginStop; };
+ bool UseVPS(void) { return useVPS; };
+ bool AvoidRepeats(void) { return avoidRepeats; };
+ int AllowedRepeats(void) { return allowedRepeats; };
+ bool CompareTitle(void) { return compareTitle; };
+ bool CompareSubtitle(void) { return compareSubtitle; };
+ bool CompareSummary(void) { return compareSummary; };
+ bool UseInFavorites(void) { return useInFavorites; };
+ //SETTER
+ void SetSearchString(std::string searchString) { this->searchString = searchString; };
+ void SetActive(bool active) { useAsSearchTimer = active; };
+ void SetSearchMode(int searchMode) { mode = searchMode; };
+ void SetUseTitle(bool useTitle) { this->useTitle = useTitle; };
+ void SetUseSubtitle(bool useSubtitle) { this->useSubtitle = useSubtitle; };
+ void SetUseDesription(bool useDescription) { this->useDescription = useDescription; };
+ void SetUseChannel(bool useChannel) { this->useChannel = useChannel; };
+ void SetStartChannel(int startChannel) { channelMin = Channels.GetByNumber(startChannel); };
+ void SetStopChannel(int stopChannel) { channelMax = Channels.GetByNumber(stopChannel); };
+ void SetUseTime(bool useTime) { this->useTime = useTime; };
+ void SetStartTime(int startTime) { this->startTime = startTime; };
+ void SetStopTime(int stopTime) { this->stopTime = stopTime; };
+ void SetUseDayOfWeek(bool useDayOfWeek) { this->useDayOfWeek = useDayOfWeek; };
+ void SetDayOfWeek(int VDRDayOfWeek);
+ void SetUseEpisode(int useEpisode) { this->useEpisode = useEpisode; };
+ void SetDirectory(std::string directory) { this-> directory = directory; };
+ void SetPriority(int priority) { this->priority = priority; };
+ void SetLifetime(int lifetime) { this->lifetime = lifetime; };
+ void SetMarginStart(int marginStart) { this->marginStart = marginStart; };
+ void SetMarginStop(int marginStop) { this->marginStop = marginStop; };
+ void SetUseVPS(bool useVPS) { this->useVPS = useVPS; };
+ void SetAvoidRepeats(bool avoidRepeats) { this->avoidRepeats = avoidRepeats; };
+ void SetAllowedRepeats(int allowedRepeats) { this->allowedRepeats = allowedRepeats; };
+ void SetCompareTitle(bool compareTitle) { this->compareTitle = compareTitle; };
+ void SetCompareSubtitle(bool compareSubtitle) { this->compareSubtitle = compareSubtitle; };
+ void SetCompareSummary(bool compareSummary) { this->compareSummary = compareSummary; };
+ void SetUseInFavorites(bool useInFavorites) { this->useInFavorites = useInFavorites; };
+ //COMMON
+ int GetNumTimers(void);
+ int GetNumRecordings(void);
+ void GetSearchModes(std::vector<std::string> *searchModes);
+ void Dump(void);
+};
+
+#endif //__TVGUIDE_SEARCHTIMER_H
diff --git a/services/epgsearch.h b/services/epgsearch.h
new file mode 100644
index 0000000..2669da4
--- /dev/null
+++ b/services/epgsearch.h
@@ -0,0 +1,202 @@
+/* -*- c++ -*-
+Copyright (C) 2004-2013 Christian Wieninger
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+
+The author can be reached at cwieninger at gmx.de
+
+The project's page is at http://winni.vdr-developer.org/epgsearch
+*/
+
+#ifndef EPGSEARCHSERVICES_INC
+#define EPGSEARCHSERVICES_INC
+
+#include <string>
+#include <list>
+#include <memory>
+#include <set>
+#include <vdr/osdbase.h>
+
+// Data structure for service "Epgsearch-search-v1.0"
+struct Epgsearch_search_v1_0
+{
+// in
+ char* query; // search term
+ int mode; // search mode (0=phrase, 1=and, 2=or, 3=regular expression)
+ int channelNr; // channel number to search in (0=any)
+ bool useTitle; // search in title
+ bool useSubTitle; // search in subtitle
+ bool useDescription; // search in description
+// out
+ cOsdMenu* pResultMenu; // pointer to the menu of results
+};
+
+// Data structure for service "Epgsearch-exttimeredit-v1.0"
+struct Epgsearch_exttimeredit_v1_0
+{
+// in
+ cTimer* timer; // pointer to the timer to edit
+ bool bNew; // flag that indicates, if this is a new timer or an existing one
+ const cEvent* event; // pointer to the event corresponding to this timer (may be NULL)
+// out
+ cOsdMenu* pTimerMenu; // pointer to the menu of results
+};
+
+// Data structure for service "Epgsearch-enablesearchtimers-v1.0"
+struct Epgsearch_enablesearchtimers_v1_0
+{
+// in
+ bool enable; // enable search timer thread?
+};
+
+// Data structure for service "Epgsearch-updatesearchtimers-v1.0"
+struct Epgsearch_updatesearchtimers_v1_0
+{
+// in
+ bool showMessage; // inform via osd when finished?
+};
+
+// Data structure for service "Epgsearch-osdmessage-v1.0"
+struct Epgsearch_osdmessage_v1_0
+{
+// in
+ char* message; // the message to display
+ eMessageType type;
+};
+
+// Data structure for service "EpgsearchMenu-v1.0"
+struct EpgSearchMenu_v1_0
+{
+// in
+// out
+ cOsdMenu* Menu; // pointer to the menu
+};
+
+// Data structure for service "Epgsearch-lastconflictinfo-v1.0"
+struct Epgsearch_lastconflictinfo_v1_0
+{
+// in
+// out
+ time_t nextConflict; // next conflict date, 0 if none
+ int relevantConflicts; // number of relevant conflicts
+ int totalConflicts; // total number of conflicts
+};
+
+// Data structure for service "Epgsearch-searchresults-v1.0"
+struct Epgsearch_searchresults_v1_0
+{
+// in
+ char* query; // search term
+ int mode; // search mode (0=phrase, 1=and, 2=or, 3=regular expression)
+ int channelNr; // channel number to search in (0=any)
+ bool useTitle; // search in title
+ bool useSubTitle; // search in subtitle
+ bool useDescription; // search in description
+// out
+
+ class cServiceSearchResult : public cListObject
+ {
+ public:
+ const cEvent* event;
+ cServiceSearchResult(const cEvent* Event) : event(Event) {}
+ };
+
+ cList<cServiceSearchResult>* pResultList; // pointer to the results
+};
+
+// Data structure for service "Epgsearch-switchtimer-v1.0"
+struct Epgsearch_switchtimer_v1_0
+{
+// in
+ const cEvent* event;
+ int mode; // mode (0=query existence, 1=add/modify, 2=delete)
+// in/out
+ int switchMinsBefore;
+ int announceOnly;
+// out
+ bool success; // result
+};
+
+// Data structures for service "Epgsearch-services-v1.0"
+class cServiceHandler
+{
+ public:
+ virtual std::list<std::string> SearchTimerList() = 0;
+ // returns a list of search timer entries in the same format as used in epgsearch.conf
+ virtual int AddSearchTimer(const std::string&) = 0;
+ // adds a new search timer and returns its ID (-1 on error)
+ virtual bool ModSearchTimer(const std::string&) = 0;
+ // edits an existing search timer and returns success
+ virtual bool DelSearchTimer(int) = 0;
+ // deletes search timer with given ID and returns success
+ virtual std::list<std::string> QuerySearchTimer(int) = 0;
+ // returns the search result of the searchtimer with given ID in the same format as used in SVDRP command 'QRYS' (->MANUAL)
+ virtual std::list<std::string> QuerySearch(std::string) = 0;
+ // returns the search result of the searchtimer with given settings in the same format as used in SVDRP command 'QRYS' (->MANUAL)
+ virtual std::list<std::string> ExtEPGInfoList() = 0;
+ // returns a list of extended EPG categories in the same format as used in epgsearchcats.conf
+ virtual std::list<std::string> ChanGrpList() = 0;
+ // returns a list of channel groups maintained by epgsearch
+ virtual std::list<std::string> BlackList() = 0;
+ // returns a list of blacklists in the same format as used in epgsearchblacklists.conf
+ virtual std::set<std::string> DirectoryList() = 0;
+ // List of all recording directories used in recordings, timers, search timers or in epgsearchdirs.conf
+ virtual ~cServiceHandler() {}
+ // Read a setup value
+ virtual std::string ReadSetupValue(const std::string& entry) = 0;
+ // Write a setup value
+ virtual bool WriteSetupValue(const std::string& entry, const std::string& value) = 0;
+};
+
+struct Epgsearch_services_v1_0
+{
+// in/out
+ std::auto_ptr<cServiceHandler> handler;
+};
+
+// Data structures for service "Epgsearch-services-v1.1"
+class cServiceHandler_v1_1 : public cServiceHandler
+{
+ public:
+ // Get timer conflicts
+ virtual std::list<std::string> TimerConflictList(bool relOnly=false) = 0;
+ // Check if a conflict check is advised
+ virtual bool IsConflictCheckAdvised() = 0;
+};
+
+struct Epgsearch_services_v1_1
+{
+// in/out
+ std::auto_ptr<cServiceHandler_v1_1> handler;
+};
+
+// Data structures for service "Epgsearch-services-v1.2"
+class cServiceHandler_v1_2 : public cServiceHandler_v1_1
+{
+ public:
+ // List of all recording directories used in recordings, timers (and optionally search timers or in epgsearchdirs.conf)
+ virtual std::set<std::string> ShortDirectoryList() = 0;
+ // Evaluate an expression against an event
+ virtual std::string Evaluate(const std::string& expr, const cEvent* event) = 0;
+};
+
+struct Epgsearch_services_v1_2
+{
+// in/out
+ std::auto_ptr<cServiceHandler_v1_2> handler;
+};
+
+#endif
diff --git a/services/remotetimers.h b/services/remotetimers.h
new file mode 100644
index 0000000..cd86b7a
--- /dev/null
+++ b/services/remotetimers.h
@@ -0,0 +1,33 @@
+#ifndef REMOTETIMERSERVICES_INC
+#define REMOTETIMERSERVICES_INC
+
+#include <vdr/epg.h>
+#include <vdr/timers.h>
+
+// RemoteTimers services
+struct RemoteTimers_Event_v1_0 {
+ //in
+ const cEvent *event;
+ //out
+ cTimer *timer;
+ cString errorMsg;
+};
+
+struct RemoteTimers_GetMatch_v1_0 {
+ //in
+ const cEvent *event;
+ //out
+ cTimer *timer;
+ int timerMatch;
+ int timerType;
+ bool isRemote;
+};
+
+struct RemoteTimers_Timer_v1_0 {
+ //in+out
+ cTimer *timer;
+ //out
+ cString errorMsg;
+};
+
+#endif //REMOTETIMERSERVICES_INC
\ No newline at end of file
diff --git a/services/scraper2vdr.h b/services/scraper2vdr.h
new file mode 100644
index 0000000..703d077
--- /dev/null
+++ b/services/scraper2vdr.h
@@ -0,0 +1,194 @@
+#ifndef __SCRAPER2VDRSERVICES_H
+#define __SCRAPER2VDRSERVICES_H
+
+#include <vdr/epg.h>
+#include <vdr/recording.h>
+
+enum tvType {
+ tSeries,
+ tMovie,
+ tNone,
+};
+
+/*********************************************************************
+* Helper Structures
+*********************************************************************/
+class cTvMedia {
+public:
+ cTvMedia(void) {
+ path = "";
+ width = height = 0;
+ };
+ std::string path;
+ int width;
+ int height;
+};
+
+class cEpisode {
+public:
+ cEpisode(void) {
+ number = 0;
+ season = 0;
+ name = "";
+ firstAired = "";
+ guestStars = "";
+ overview = "";
+ rating = 0.0;
+ };
+ int number;
+ int season;
+ std::string name;
+ std::string firstAired;
+ std::string guestStars;
+ std::string overview;
+ float rating;
+ cTvMedia episodeImage;
+};
+
+class cActor {
+public:
+ cActor(void) {
+ name = "";
+ role = "";
+ };
+ std::string name;
+ std::string role;
+ cTvMedia actorThumb;
+};
+
+/*********************************************************************
+* Data Structures for Service Calls
+*********************************************************************/
+
+// Data structure for service "GetEventType"
+class ScraperGetEventType {
+public:
+ ScraperGetEventType(void) {
+ event = NULL;
+ recording = NULL;
+ type = tNone;
+ movieId = 0;
+ seriesId = 0;
+ episodeId = 0;
+ };
+// in
+ const cEvent *event; // check type for this event
+ const cRecording *recording; // or for this recording
+//out
+ tvType type; //typeSeries or typeMovie
+ int movieId;
+ int seriesId;
+ int episodeId;
+};
+
+//Data structure for full series and episode information
+class cMovie {
+public:
+ cMovie(void) {
+ title = "";
+ originalTitle = "";
+ tagline = "";
+ overview = "";
+ adult = false;
+ collectionName = "";
+ budget = 0;
+ revenue = 0;
+ genres = "";
+ homepage = "";
+ releaseDate = "";
+ runtime = 0;
+ popularity = 0.0;
+ voteAverage = 0.0;
+ };
+//IN
+ int movieId; // movieId fetched from ScraperGetEventType
+//OUT
+ std::string title;
+ std::string originalTitle;
+ std::string tagline;
+ std::string overview;
+ bool adult;
+ std::string collectionName;
+ int budget;
+ int revenue;
+ std::string genres;
+ std::string homepage;
+ std::string releaseDate;
+ int runtime;
+ float popularity;
+ float voteAverage;
+ cTvMedia poster;
+ cTvMedia fanart;
+ cTvMedia collectionPoster;
+ cTvMedia collectionFanart;
+ std::vector<cActor> actors;
+};
+
+//Data structure for full series and episode information
+class cSeries {
+public:
+ cSeries(void) {
+ seriesId = 0;
+ episodeId = 0;
+ name = "";
+ overview = "";
+ firstAired = "";
+ network = "";
+ genre = "";
+ rating = 0.0;
+ status = "";
+ };
+//IN
+ int seriesId; // seriesId fetched from ScraperGetEventType
+ int episodeId; // episodeId fetched from ScraperGetEventType
+//OUT
+ std::string name;
+ std::string overview;
+ std::string firstAired;
+ std::string network;
+ std::string genre;
+ float rating;
+ std::string status;
+ cEpisode episode;
+ std::vector<cActor> actors;
+ std::vector<cTvMedia> posters;
+ std::vector<cTvMedia> banners;
+ std::vector<cTvMedia> fanarts;
+ cTvMedia seasonPoster;
+};
+
+// Data structure for service "GetPosterBanner"
+class ScraperGetPosterBanner {
+public:
+ ScraperGetPosterBanner(void) {
+ type = tNone;
+ };
+// in
+ const cEvent *event; // check type for this event
+//out
+ tvType type; //typeSeries or typeMovie
+ cTvMedia poster;
+ cTvMedia banner;
+};
+
+// Data structure for service "GetPoster"
+class ScraperGetPoster {
+public:
+// in
+ const cEvent *event; // check type for this event
+ const cRecording *recording; // or for this recording
+//out
+ cTvMedia poster;
+};
+
+// Data structure for service "GetPosterThumb"
+class ScraperGetPosterThumb {
+public:
+// in
+ const cEvent *event; // check type for this event
+ const cRecording *recording; // or for this recording
+//out
+ cTvMedia poster;
+};
+
+#endif //__SCRAPER2VDRSERVICES_H
\ No newline at end of file
diff --git a/setup.c b/setup.c
index a8e57d6..c58af4d 100644
--- a/setup.c
+++ b/setup.c
@@ -1,86 +1,161 @@
#include "setup.h"
cTvguideSetup::cTvguideSetup() {
- tmpTvguideConfig = tvguideConfig;
- Setup();
+ tmpTvguideConfig = tvguideConfig;
+ Setup();
}
cTvguideSetup::~cTvguideSetup() {
+ geoManager.SetGeometry(cOsd::OsdWidth(), cOsd::OsdHeight(), true);
+ fontManager.DeleteFonts();
+ fontManager.SetFonts();
+ tvguideConfig.LoadTheme();
+ tvguideConfig.setDynamicValues();
+ imgCache.Clear();
+ imgCache.CreateCache();
}
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();
+ int currentItem = Current();
+ Clear();
+
+ Add(new cOsdItem(tr("General Settings")));
+ Add(new cOsdItem(tr("Screen Presentation")));
+ Add(new cOsdItem(tr("Fonts and Fontsizes")));
+ Add(new cOsdItem(tr("Recording Menus and Favorites")));
+ Add(new cOsdItem(tr("Image Loading and Caching")));
+
+ 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;
+ 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));
+ if (strcmp(ItemText, tr("Recording Menus and Favorites")) == 0)
+ state = AddSubMenu(new cMenuSetupFavorites(&tmpTvguideConfig));
+ if (strcmp(ItemText, tr("Image Loading and Caching")) == 0)
+ state = AddSubMenu(new cMenuSetupImageCache(&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);
+ tvguideConfig = tmpTvguideConfig;
+ SetupStore("debugImageLoading", tvguideConfig.debugImageLoading);
+ SetupStore("useNopacityTheme", tvguideConfig.useNopacityTheme);
+ SetupStore("themeIndex", tvguideConfig.themeIndex);
+ SetupStore("showMainMenuEntry", tvguideConfig.showMainMenuEntry);
+ SetupStore("replaceOriginalSchedule", tvguideConfig.replaceOriginalSchedule);
+ SetupStore("displayMode", tvguideConfig.displayMode);
+ SetupStore("showTimeInGrid", tvguideConfig.showTimeInGrid);
+ SetupStore("displayStatusHeader", tvguideConfig.displayStatusHeader);
+ SetupStore("displayChannelGroups", tvguideConfig.displayChannelGroups);
+ SetupStore("displayTimeBase", tvguideConfig.displayTimeBase);
+ SetupStore("headerHeightPercent", tvguideConfig.headerHeightPercent);
+ SetupStore("channelGroupsPercent", tvguideConfig.channelGroupsPercent);
+ SetupStore("epgViewBorder", tvguideConfig.epgViewBorder);
+ SetupStore("scaleVideo", tvguideConfig.scaleVideo);
+ SetupStore("decorateVideo", tvguideConfig.decorateVideo);
+ SetupStore("roundedCorners", tvguideConfig.roundedCorners);
+ SetupStore("timeFormat", tvguideConfig.timeFormat);
+ SetupStore("channelCols", tvguideConfig.channelCols);
+ SetupStore("channelRows", tvguideConfig.channelRows);
+ SetupStore("displayTime", tvguideConfig.displayTime);
+ SetupStore("bigStepHours", tvguideConfig.bigStepHours);
+ SetupStore("hugeStepHours", tvguideConfig.hugeStepHours);
+ SetupStore("channelJumpMode", tvguideConfig.channelJumpMode);
+ SetupStore("blueKeyMode", tvguideConfig.blueKeyMode);
+ SetupStore("numkeyMode", tvguideConfig.numkeyMode);
+ SetupStore("useRemoteTimers", tvguideConfig.useRemoteTimers);
+ SetupStore("closeOnSwitch", tvguideConfig.closeOnSwitch);
+ SetupStore("hideLastGroup", tvguideConfig.hideLastGroup);
+ SetupStore("hideChannelLogos", tvguideConfig.hideChannelLogos);
+ SetupStore("logoExtension", tvguideConfig.logoExtension);
+ SetupStore("logoWidthRatio", tvguideConfig.logoWidthRatio);
+ SetupStore("logoHeightRatio", tvguideConfig.logoHeightRatio);
+ SetupStore("hideEpgImages", tvguideConfig.hideEpgImages);
+ SetupStore("epgImageWidth", tvguideConfig.epgImageWidth);
+ SetupStore("epgImageHeight", tvguideConfig.epgImageHeight);
+ SetupStore("numAdditionalEPGPictures", tvguideConfig.numAdditionalEPGPictures);
+ SetupStore("epgImageWidthLarge", tvguideConfig.epgImageWidthLarge);
+ SetupStore("epgImageHeightLarge", tvguideConfig.epgImageHeightLarge);
+ SetupStore("detailedViewScrollStep", tvguideConfig.detailedViewScrollStep);
+ SetupStore("timeLineWidthPercent", tvguideConfig.timeLineWidthPercent);
+ SetupStore("timeLineHeightPercent", tvguideConfig.timeLineHeightPercent);
+ SetupStore("displayChannelName", tvguideConfig.displayChannelName);
+ SetupStore("channelHeaderWidthPercent", tvguideConfig.channelHeaderWidthPercent);
+ SetupStore("channelHeaderHeightPercent", tvguideConfig.channelHeaderHeightPercent);
+ SetupStore("footerHeightPercent", tvguideConfig.footerHeightPercent);
+ SetupStore("instRecFolderMode", tvguideConfig.instRecFolderMode);
+ SetupStore("instRecFixedFolder", tvguideConfig.instRecFixedFolder.c_str());
+ SetupStore("favWhatsOnNow", tvguideConfig.favWhatsOnNow);
+ SetupStore("favWhatsOnNext", tvguideConfig.favWhatsOnNext);
+ SetupStore("favUseTime1", tvguideConfig.favUseTime1);
+ SetupStore("favUseTime2", tvguideConfig.favUseTime2);
+ SetupStore("favUseTime3", tvguideConfig.favUseTime3);
+ SetupStore("favUseTime4", tvguideConfig.favUseTime4);
+ SetupStore("favTime1", tvguideConfig.favTime1);
+ SetupStore("favTime2", tvguideConfig.favTime2);
+ SetupStore("favTime3", tvguideConfig.favTime3);
+ SetupStore("favTime4", tvguideConfig.favTime4);
+ SetupStore("descUser1", tvguideConfig.descUser1.c_str());
+ SetupStore("descUser2", tvguideConfig.descUser2.c_str());
+ SetupStore("descUser3", tvguideConfig.descUser3.c_str());
+ SetupStore("descUser4", tvguideConfig.descUser4.c_str());
+ SetupStore("favLimitChannels", tvguideConfig.favLimitChannels);
+ SetupStore("favStartChannel", tvguideConfig.favStartChannel);
+ SetupStore("favStopChannel", tvguideConfig.favStopChannel);
+ SetupStore("fontIndex", tvguideConfig.fontIndex);
+ SetupStore("FontButtonDelta", tvguideConfig.FontButtonDelta);
+ SetupStore("FontDetailViewDelta", tvguideConfig.FontDetailViewDelta);
+ SetupStore("FontDetailHeaderDelta", tvguideConfig.FontDetailHeaderDelta);
+ SetupStore("FontMessageBoxDelta", tvguideConfig.FontMessageBoxDelta);
+ SetupStore("FontMessageBoxLargeDelta", tvguideConfig.FontMessageBoxLargeDelta);
+ SetupStore("FontStatusHeaderDelta", tvguideConfig.FontStatusHeaderDelta);
+ SetupStore("FontStatusHeaderLargeDelta", tvguideConfig.FontStatusHeaderLargeDelta);
+ SetupStore("FontChannelHeaderDelta", tvguideConfig.FontChannelHeaderDelta);
+ SetupStore("FontChannelGroupsDelta", tvguideConfig.FontChannelGroupsDelta);
+ SetupStore("FontGridDelta", tvguideConfig.FontGridDelta);
+ SetupStore("FontGridSmallDelta", tvguideConfig.FontGridSmallDelta);
+ SetupStore("FontTimeLineWeekdayDelta", tvguideConfig.FontTimeLineWeekdayDelta);
+ SetupStore("FontTimeLineDateDelta", tvguideConfig.FontTimeLineDateDelta);
+ SetupStore("FontTimeLineTimeDelta", tvguideConfig.FontTimeLineTimeDelta);
+ SetupStore("FontChannelHeaderHorizontalDelta", tvguideConfig.FontChannelHeaderHorizontalDelta);
+ SetupStore("FontChannelGroupsHorizontalDelta", tvguideConfig.FontChannelGroupsHorizontalDelta);
+ SetupStore("FontGridHorizontalDelta", tvguideConfig.FontGridHorizontalDelta);
+ SetupStore("FontGridHorizontalSmallDelta", tvguideConfig.FontGridHorizontalSmallDelta);
+ SetupStore("FontTimeLineDateHorizontalDelta", tvguideConfig.FontTimeLineDateHorizontalDelta);
+ SetupStore("FontTimeLineTimeHorizontalDelta", tvguideConfig.FontTimeLineTimeHorizontalDelta);
+ SetupStore("FontRecMenuItemDelta", tvguideConfig.FontRecMenuItemDelta);
+ SetupStore("FontRecMenuItemSmallDelta", tvguideConfig.FontRecMenuItemSmallDelta);
+ SetupStore("FontRecMenuItemLargeDelta", tvguideConfig.FontRecMenuItemLargeDelta);
+ SetupStore("displayRerunsDetailEPGView", tvguideConfig.displayRerunsDetailEPGView);
+ SetupStore("numReruns", tvguideConfig.numReruns);
+ SetupStore("useSubtitleRerun", tvguideConfig.useSubtitleRerun);
+ SetupStore("numLogosInitial", tvguideConfig.numLogosInitial);
+ SetupStore("numLogosMax", tvguideConfig.numLogosMax);
+ SetupStore("limitLogoCache", tvguideConfig.limitLogoCache);
}
cMenuSetupSubMenu::cMenuSetupSubMenu(const char* Title, cTvguideConfig* data) : cOsdMenu(Title, 30) {
- tmpTvguideConfig = data;
+ tmpTvguideConfig = data;
+ indent = " ";
}
cOsdItem *cMenuSetupSubMenu::InfoItem(const char *label, const char *value) {
@@ -103,110 +178,302 @@ eOSState cMenuSetupSubMenu::ProcessKey(eKeys Key) {
return state;
}
-//------------------------------------------------------------------------------------------------------------------
+//----- General Settings -------------------------------------------------------------------------------------------------------------
cMenuSetupGeneral::cMenuSetupGeneral(cTvguideConfig* data) : cMenuSetupSubMenu(tr("General Settings"), data) {
- timeFormatItems[0] = "12h";
- timeFormatItems[1] = "24h";
-
- Set();
+ themes.Load(*cString("tvguide"));
+ timeFormatItems[0] = "12h";
+ timeFormatItems[1] = "24h";
+ jumpMode[0] = tr("x channels back / forward");
+ jumpMode[1] = tr("previous / next channel group");
+ blueMode[0] = tr("Blue: Channel Switch, Ok: Detailed EPG");
+ blueMode[1] = tr("Blue: Detailed EPG, Ok: Channel Switch");
+ blueMode[2] = tr("Blue: Favorites / Switch, Ok: Detailed EPG");
+ numMode[0] = tr("Timely Jump");
+ numMode[1] = tr("Jump to specific channel");
+ useSubtitleRerunTexts[0] = tr("never");
+ useSubtitleRerunTexts[1] = tr("if exists");
+ useSubtitleRerunTexts[2] = tr("always");
+ 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));
+ int currentItem = Current();
+ Clear();
+ Add(new cMenuEditBoolItem(tr("Show Main Menu Entry"), &tmpTvguideConfig->showMainMenuEntry));
+ Add(new cMenuEditBoolItem(tr("Replace VDR Schedules Menu"), &tmpTvguideConfig->replaceOriginalSchedule));
+ Add(new cMenuEditBoolItem(tr("Use appropriate nOpacity Theme"), &tmpTvguideConfig->useNopacityTheme));
+ if (!tmpTvguideConfig->useNopacityTheme) {
+ if (themes.NumThemes())
+ Add(new cMenuEditStraItem(cString::sprintf("%s%s", *indent, tr("Theme")), &tmpTvguideConfig->themeIndex, themes.NumThemes(), themes.Descriptions()));
+ }
+ Add(new cMenuEditIntItem(tr("Time to display in minutes"), &tmpTvguideConfig->displayTime, 60, 320));
+ Add(new cMenuEditBoolItem(tr("Rounded Corners"), &tmpTvguideConfig->roundedCorners));
+
+ Add(new cMenuEditStraItem(tr("Channel Jump Mode (Keys Green / Yellow)"), &tmpTvguideConfig->channelJumpMode, 2, jumpMode));
+ Add(new cMenuEditStraItem(tr("Keys Blue and OK"), &tmpTvguideConfig->blueKeyMode, 3, blueMode));
+ Add(new cMenuEditBoolItem(tr("Close TVGuide after channel switch"), &tmpTvguideConfig->closeOnSwitch));
+ Add(new cMenuEditStraItem(tr("Functionality of numeric Keys"), &tmpTvguideConfig->numkeyMode, 2, numMode));
+ Add(new cMenuEditBoolItem(tr("Hide last Channel Group"), &tmpTvguideConfig->hideLastGroup));
+ 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));
+ Add(new cMenuEditIntItem(tr("EPG Window Text Scrolling Speed"), &tmpTvguideConfig->detailedViewScrollStep, 1, 30));
+ Add(new cMenuEditBoolItem(tr("Display Reruns in detailed EPG View"), &tmpTvguideConfig->displayRerunsDetailEPGView));
+ if (tmpTvguideConfig->displayRerunsDetailEPGView) {
+ Add(new cMenuEditIntItem(cString::sprintf("%s%s", *indent, tr("Number of reruns to display")), &tmpTvguideConfig->numReruns, 1, 10));
+ Add(new cMenuEditStraItem(cString::sprintf("%s%s", *indent, tr("Use Subtitle for reruns")), &tmpTvguideConfig->useSubtitleRerun, 3, useSubtitleRerunTexts));
+ }
+ SetCurrent(Get(currentItem));
+ Display();
+}
- SetCurrent(Get(currentItem));
- Display();
+eOSState cMenuSetupGeneral::ProcessKey(eKeys Key) {
+ eOSState state = cOsdMenu::ProcessKey(Key);
+ if (Key == kOk) {
+ state = osBack;
+ } else if (Key != kNone) {
+ Set();
+ }
+ return state;
}
-//------------------------------------------------------------------------------------------------------------------
+//----- Screen Presentation -------------------------------------------------------------------------------------------------------------
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";
- blendingMethods[0] = "none";
- blendingMethods[1] = "classic";
- blendingMethods[2] = "nOpacity style";
- Set();
+ displayModeItems[0] = "vertical";
+ displayModeItems[1] = "horizontal";
+ 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 cMenuEditStraItem(tr("Use color gradients"), &tmpTvguideConfig->useBlending, 3, blendingMethods));
- 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();
+ int currentItem = Current();
+ Clear();
+
+ Add(new cMenuEditStraItem(tr("Display Mode"), &tmpTvguideConfig->displayMode, 2, displayModeItems));
+ if (tmpTvguideConfig->displayMode == eVertical) {
+ Add(new cMenuEditIntItem(*cString::sprintf("%s%s", *indent, tr("Height of Channel Header (Perc. of osd height)")), &tmpTvguideConfig->channelHeaderHeightPercent, 5, 30));
+ Add(new cMenuEditIntItem(*cString::sprintf("%s%s", *indent, tr("Width of Timeline (Perc. of osd width)")), &tmpTvguideConfig->timeLineWidthPercent, 5, 30));
+ Add(new cMenuEditIntItem(*cString::sprintf("%s%s", *indent, tr("Number of Channels to display")), &tmpTvguideConfig->channelCols, 3, 12));
+ } else if (tmpTvguideConfig->displayMode == eHorizontal) {
+ Add(new cMenuEditIntItem(*cString::sprintf("%s%s", *indent, tr("Width of Channel Header (Perc. of osd width)")), &tmpTvguideConfig->channelHeaderWidthPercent, 5, 30));
+ Add(new cMenuEditIntItem(*cString::sprintf("%s%s", *indent, tr("Height of Timeline (Perc. of osd height)")), &tmpTvguideConfig->timeLineHeightPercent, 5, 30));
+ Add(new cMenuEditIntItem(*cString::sprintf("%s%s", *indent, tr("Number of Channels to display")), &tmpTvguideConfig->channelRows, 3, 12));
+ Add(new cMenuEditBoolItem(*cString::sprintf("%s%s", *indent, tr("Display time in EPG Grids")), &tmpTvguideConfig->showTimeInGrid));
+ }
+ Add(new cMenuEditIntItem(tr("Height of Headers (Status Header and EPG View, Perc. of osd height)"), &tmpTvguideConfig->headerHeightPercent, 10, 50));
+ Add(new cMenuEditIntItem(tr("Height of Footer (Perc. of osd height)"), &tmpTvguideConfig->footerHeightPercent, 3, 20));
+
+ Add(new cMenuEditBoolItem(tr("Display status header"), &tmpTvguideConfig->displayStatusHeader));
+ if (tmpTvguideConfig->displayStatusHeader) {
+ Add(new cMenuEditBoolItem(*cString::sprintf("%s%s", *indent, tr("Scale video to upper right corner")), &tmpTvguideConfig->scaleVideo));
+ Add(new cMenuEditBoolItem(*cString::sprintf("%s%s", *indent, tr("Rounded corners around video frame")), &tmpTvguideConfig->decorateVideo));
+ }
+
+ Add(new cMenuEditBoolItem(tr("Display Channel Names in Header"), &tmpTvguideConfig->displayChannelName));
+ Add(new cMenuEditBoolItem(tr("Display channel groups"), &tmpTvguideConfig->displayChannelGroups));
+ if (tmpTvguideConfig->displayChannelGroups) {
+ if (tmpTvguideConfig->displayMode == eVertical) {
+ Add(new cMenuEditIntItem(*cString::sprintf("%s%s", *indent, tr("Height of channel groups (Perc. of osd height)")), &tmpTvguideConfig->channelGroupsPercent, 3, 30));
+ } else if (tmpTvguideConfig->displayMode == eHorizontal) {
+ Add(new cMenuEditIntItem(*cString::sprintf("%s%s", *indent, tr("Width of channel groups (Perc. of osd width)")), &tmpTvguideConfig->channelGroupsPercent, 3, 30));
+ }
+ }
+
+ Add(new cMenuEditBoolItem(tr("Display current time baseline"), &tmpTvguideConfig->displayTimeBase));
+ 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 ratio")), &tmpTvguideConfig->logoWidthRatio, 1, 1000));
+ Add(new cMenuEditIntItem(*cString::sprintf("%s%s", *indent, tr("Logo height ratio")), &tmpTvguideConfig->logoHeightRatio, 1, 1000));
+ }
+
+ Add(new cMenuEditIntItem(tr("Text Border in Detailed View (pixel)"), &tmpTvguideConfig->epgViewBorder, 0, 300));
+
+ 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));
+ Add(new cMenuEditIntItem(*cString::sprintf("%s%s", *indent, tr("Number of additional EPG Images")), &tmpTvguideConfig->numAdditionalEPGPictures, 0, 20));
+ Add(new cMenuEditIntItem(*cString::sprintf("%s%s", *indent, tr("Additional EPG Image width")), &tmpTvguideConfig->epgImageWidthLarge, 1, 800));
+ Add(new cMenuEditIntItem(*cString::sprintf("%s%s", *indent, tr("Additional EPG Image height")), &tmpTvguideConfig->epgImageHeightLarge, 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;
+ eOSState state = cOsdMenu::ProcessKey(Key);
+ if (Key == kOk) {
+ state = osBack;
+ } else if (Key != kNone) {
+ Set();
+ }
+ return state;
}
-//------------------------------------------------------------------------------------------------------------------
+//-----Fonts and Fontsizes -------------------------------------------------------------------------------------------------------
cMenuSetupFont::cMenuSetupFont(cTvguideConfig* data) : cMenuSetupSubMenu(tr("Fonts and Fontsizes"), data) {
- cFont::GetAvailableFontNames(&fontNames);
- fontNames.Insert(strdup(tvguideConfig.fontNameDefault));
- Set();
+ 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();
-}
\ No newline at end of file
+ int currentItem = Current();
+ Clear();
+
+ Add(new cMenuEditStraItem(tr("Font"), &tmpTvguideConfig->fontIndex, fontNames.Size(), &fontNames[0]));
+
+ Add(new cMenuEditIntItem(tr("Status Header Font Size"), &tmpTvguideConfig->FontStatusHeaderDelta, -30, 30));
+ Add(new cMenuEditIntItem(tr("Status Header Large Font Size"), &tmpTvguideConfig->FontStatusHeaderLargeDelta, -30, 30));
+ Add(new cMenuEditIntItem(tr("Detail EPG View Font Size"), &tmpTvguideConfig->FontDetailViewDelta, -30, 30));
+ Add(new cMenuEditIntItem(tr("Detail EPG View Header Font Size"), &tmpTvguideConfig->FontDetailHeaderDelta, -30, 30));
+ Add(new cMenuEditIntItem(tr("Message Font Size"), &tmpTvguideConfig->FontMessageBoxDelta, -30, 30));
+ Add(new cMenuEditIntItem(tr("Message Large Font Size"), &tmpTvguideConfig->FontMessageBoxLargeDelta, -30, 30));
+ Add(new cMenuEditIntItem(tr("Button Font Size"), &tmpTvguideConfig->FontButtonDelta, -30, 30));
+
+
+ if (tmpTvguideConfig->displayMode == eVertical) {
+ Add(new cMenuEditIntItem(tr("Channel Header Font Size"), &tmpTvguideConfig->FontChannelHeaderDelta, -30, 30));
+ Add(new cMenuEditIntItem(tr("Channel Groups Font Size"), &tmpTvguideConfig->FontChannelGroupsDelta, -30, 30));
+ Add(new cMenuEditIntItem(tr("Grid Font Size"), &tmpTvguideConfig->FontGridDelta, -30, 30));
+ Add(new cMenuEditIntItem(tr("Grid Font Small Size"), &tmpTvguideConfig->FontGridSmallDelta, -30, 30));
+ Add(new cMenuEditIntItem(tr("Timeline Weekday Font Size"), &tmpTvguideConfig->FontTimeLineWeekdayDelta, -30, 30));
+ Add(new cMenuEditIntItem(tr("Timeline Date Font Size"), &tmpTvguideConfig->FontTimeLineDateDelta, -30, 30));
+ Add(new cMenuEditIntItem(tr("Timeline Time Font Size"), &tmpTvguideConfig->FontTimeLineTimeDelta, -30, 30));
+ } else if (tmpTvguideConfig->displayMode == eHorizontal) {
+ Add(new cMenuEditIntItem(tr("Channel Header Font Size"), &tmpTvguideConfig->FontChannelHeaderHorizontalDelta, -30, 30));
+ Add(new cMenuEditIntItem(tr("Channel Groups Font Size"), &tmpTvguideConfig->FontChannelGroupsHorizontalDelta, -30, 30));
+ Add(new cMenuEditIntItem(tr("Grid Font Size"), &tmpTvguideConfig->FontGridHorizontalDelta, -30, 30));
+ Add(new cMenuEditIntItem(tr("Grid Font Small Size"), &tmpTvguideConfig->FontGridHorizontalSmallDelta, -30, 30));
+ Add(new cMenuEditIntItem(tr("Timeline Date Font Size"), &tmpTvguideConfig->FontTimeLineDateHorizontalDelta, -30, 30));
+ Add(new cMenuEditIntItem(tr("Timeline Time Font Size"), &tmpTvguideConfig->FontTimeLineTimeHorizontalDelta, -30, 30));
+ }
+
+ Add(new cMenuEditIntItem(tr("Search & Recording Menu Font Size"), &tmpTvguideConfig->FontRecMenuItemDelta, -30, 30));
+ Add(new cMenuEditIntItem(tr("Search & Recording Menu Small Font Size"), &tmpTvguideConfig->FontRecMenuItemSmallDelta, -30, 30));
+ Add(new cMenuEditIntItem(tr("Search & Recording Menu Header Font Size"), &tmpTvguideConfig->FontRecMenuItemLargeDelta, -30, 30));
+
+ SetCurrent(Get(currentItem));
+ Display();
+}
+
+//----- Recording Menus and Favorites -------------------------------------------------------------------------------------------------------
+
+cMenuSetupFavorites::cMenuSetupFavorites(cTvguideConfig* data) : cMenuSetupSubMenu(tr("Recording Menus and Favorites"), data) {
+ strn0cpy(description1, data->descUser1.c_str(), sizeof(description1));
+ strn0cpy(description2, data->descUser2.c_str(), sizeof(description2));
+ strn0cpy(description3, data->descUser3.c_str(), sizeof(description3));
+ strn0cpy(description4, data->descUser4.c_str(), sizeof(description4));
+ recFolderMode[0] = tr("Always use root video folder");
+ recFolderMode[1] = tr("Select from folder list");
+ recFolderMode[2] = tr("Use fixed folder");
+ strn0cpy(fixedFolder, data->instRecFixedFolder.c_str(), sizeof(fixedFolder));
+ Set();
+}
+
+void cMenuSetupFavorites::Set(void) {
+ int currentItem = Current();
+ Clear();
+
+ Add(new cMenuEditStraItem(tr("Folder for instant Recordings"), &tmpTvguideConfig->instRecFolderMode, 3, recFolderMode));
+ if (tmpTvguideConfig->instRecFolderMode == eFolderFixed) {
+ Add(new cMenuEditStrItem(cString::sprintf("%s%s", *indent, tr("Folder")), fixedFolder, sizeof(fixedFolder), trVDR(FileNameChars)));
+ }
+ if (pRemoteTimers)
+ Add(new cMenuEditBoolItem(tr("Use Remotetimers"), &tmpTvguideConfig->useRemoteTimers));
+
+ Add(new cMenuEditBoolItem(tr("Use \"What's on now\" in favorites"), &tmpTvguideConfig->favWhatsOnNow));
+ Add(new cMenuEditBoolItem(tr("Use \"What's on next\" in favorites"), &tmpTvguideConfig->favWhatsOnNext));
+ Add(new cMenuEditBoolItem(tr("Use user defined time 1 in favorites"), &tmpTvguideConfig->favUseTime1));
+ if (tmpTvguideConfig->favUseTime1) {
+ Add(new cMenuEditStrItem(cString::sprintf("%s%s", *indent, tr("Description")), description1, sizeof(description1), trVDR(FileNameChars)));
+ Add(new cMenuEditTimeItem(cString::sprintf("%s%s", *indent, tr("Time")), &tmpTvguideConfig->favTime1));
+ }
+ Add(new cMenuEditBoolItem(tr("Use user defined time 2 in favorites"), &tmpTvguideConfig->favUseTime2));
+ if (tmpTvguideConfig->favUseTime2) {
+ Add(new cMenuEditStrItem(cString::sprintf("%s%s", *indent, tr("Description")), description2, sizeof(description2), trVDR(FileNameChars)));
+ Add(new cMenuEditTimeItem(cString::sprintf("%s%s", *indent, tr("Time")), &tmpTvguideConfig->favTime2));
+ }
+ Add(new cMenuEditBoolItem(tr("Use user defined time 3 in favorites"), &tmpTvguideConfig->favUseTime3));
+ if (tmpTvguideConfig->favUseTime3) {
+ Add(new cMenuEditStrItem(cString::sprintf("%s%s", *indent, tr("Description")), description3, sizeof(description3), trVDR(FileNameChars)));
+ Add(new cMenuEditTimeItem(cString::sprintf("%s%s", *indent, tr("Time")), &tmpTvguideConfig->favTime3));
+ }
+ Add(new cMenuEditBoolItem(tr("Use user defined time 4 in favorites"), &tmpTvguideConfig->favUseTime4));
+ if (tmpTvguideConfig->favUseTime4) {
+ Add(new cMenuEditStrItem(cString::sprintf("%s%s", *indent, tr("Description")), description4, sizeof(description4), trVDR(FileNameChars)));
+ Add(new cMenuEditTimeItem(cString::sprintf("%s%s", *indent, tr("Time")), &tmpTvguideConfig->favTime4));
+ }
+ Add(new cMenuEditBoolItem(tr("Limit channels in favorites"), &tmpTvguideConfig->favLimitChannels));
+ if (tmpTvguideConfig->favLimitChannels) {
+ Add(new cMenuEditChanItem(tr("Start Channel"), &tmpTvguideConfig->favStartChannel));
+ Add(new cMenuEditChanItem(tr("Stop Channel"), &tmpTvguideConfig->favStopChannel));
+ }
+
+
+ SetCurrent(Get(currentItem));
+ Display();
+}
+
+eOSState cMenuSetupFavorites::ProcessKey(eKeys Key) {
+ int tmpFavUseTime1 = tmpTvguideConfig->favUseTime1;
+ int tmpFavUseTime2 = tmpTvguideConfig->favUseTime2;
+ int tmpFavUseTime3 = tmpTvguideConfig->favUseTime3;
+ int tmpFavUseTime4 = tmpTvguideConfig->favUseTime4;
+ int tmpFavLimitChannels = tmpTvguideConfig->favLimitChannels;
+ int tmpFolderMode = tmpTvguideConfig->instRecFolderMode;
+ eOSState state = cOsdMenu::ProcessKey(Key);
+ if (Key == kOk) {
+ tmpTvguideConfig->descUser1 = description1;
+ tmpTvguideConfig->descUser2 = description2;
+ tmpTvguideConfig->descUser3 = description3;
+ tmpTvguideConfig->descUser4 = description4;
+ tmpTvguideConfig->instRecFixedFolder = fixedFolder;
+ } else if ((Key == kLeft)||(Key == kRight)) {
+ if ((tmpFavUseTime1 != tmpTvguideConfig->favUseTime1) ||
+ (tmpFavUseTime2 != tmpTvguideConfig->favUseTime2) ||
+ (tmpFavUseTime3 != tmpTvguideConfig->favUseTime3) ||
+ (tmpFavUseTime4 != tmpTvguideConfig->favUseTime4) ||
+ (tmpFavLimitChannels != tmpTvguideConfig->favLimitChannels) ||
+ (tmpFolderMode != tmpTvguideConfig->instRecFolderMode) )
+ Set();
+ }
+ return state;
+}
+
+
+//-----Image Caching-------------------------------------------------------------------------------------------------------------
+cMenuSetupImageCache::cMenuSetupImageCache(cTvguideConfig* data) : cMenuSetupSubMenu(tr("Image Loading and Caching"), data) {
+ Set();
+}
+
+void cMenuSetupImageCache::Set(void) {
+ int currentItem = Current();
+ Clear();
+ Add(new cMenuEditBoolItem(tr("Create Log Messages for image loading"), &tmpTvguideConfig->debugImageLoading));
+ Add(new cMenuEditBoolItem(tr("Limit Logo Cache"), &tmpTvguideConfig->limitLogoCache));
+ if (&tmpTvguideConfig->limitLogoCache) {
+ Add(new cMenuEditIntItem(cString::sprintf("%s%s", *indent, tr("Maximal number of logos to cache")), &tmpTvguideConfig->numLogosMax, 1, 9999));
+ }
+ Add(new cMenuEditIntItem(tr("Number of logos to cache at start"), &tmpTvguideConfig->numLogosInitial, 0, 9999));
+
+ Add(InfoItem(tr("Cache Sizes"), ""));
+ Add(InfoItem(tr("OSD Element Cache"), (imgCache.GetCacheSize(ctOsdElement)).c_str()));
+ Add(InfoItem(tr("Logo cache"), (imgCache.GetCacheSize(ctLogo)).c_str()));
+ Add(InfoItem(tr("EPG Grid Cache"), (imgCache.GetCacheSize(ctGrid)).c_str()));
+ Add(InfoItem(tr("Channel Groups Cache"), (imgCache.GetCacheSize(ctChannelGroup)).c_str()));
+ Add(InfoItem(tr("Recording Menus Icon Cache"), (imgCache.GetCacheSize(ctIcon)).c_str()));
+
+ SetCurrent(Get(currentItem));
+ Display();
+}
diff --git a/setup.h b/setup.h
index ba81d8f..f7f8b2c 100644
--- a/setup.h
+++ b/setup.h
@@ -1,55 +1,85 @@
#ifndef __TVGUIDE_SETUP_H
#define __TVGUIDE_SETUP_H
+#include <vdr/menuitems.h>
+#include "config.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);
+ 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);
+ protected:
+ cTvguideConfig *tmpTvguideConfig;
+ virtual eOSState ProcessKey(eKeys Key);
+ virtual void Set(void) = 0;
+ cOsdItem *InfoItem(const char *label, const char *value);
+ cString indent;
+ public:
+ cMenuSetupSubMenu(const char *Title, cTvguideConfig *data);
};
class cMenuSetupGeneral : public cMenuSetupSubMenu {
- protected:
- const char * timeFormatItems[2];
- void Set(void);
- public:
- cMenuSetupGeneral(cTvguideConfig *data);
+ protected:
+ virtual eOSState ProcessKey(eKeys Key);
+ cThemes themes;
+ const char * timeFormatItems[2];
+ const char * jumpMode[2];
+ const char * blueMode[3];
+ const char * numMode[2];
+ const char *useSubtitleRerunTexts[3];
+ 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];
- const char * blendingMethods[3];
- void Set(void);
- public:
- cMenuSetupScreenLayout(cTvguideConfig *data);
+ protected:
+ virtual eOSState ProcessKey(eKeys Key);
+ const char * displayModeItems[2];
+ 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);
+ protected:
+ cStringList fontNames;
+ void Set(void);
+ public:
+ cMenuSetupFont(cTvguideConfig *data);
+};
+
+class cMenuSetupFavorites : public cMenuSetupSubMenu {
+ protected:
+ char description1[256];
+ char description2[256];
+ char description3[256];
+ char description4[256];
+ const char * recFolderMode[3];
+ char fixedFolder[256];
+ void Set(void);
+ virtual eOSState ProcessKey(eKeys Key);
+ public:
+ cMenuSetupFavorites(cTvguideConfig *data);
+};
+
+class cMenuSetupImageCache : public cMenuSetupSubMenu {
+ protected:
+ void Set(void);
+ public:
+ cMenuSetupImageCache(cTvguideConfig *data);
};
#endif //__TVGUIDE_SETUP_H
\ No newline at end of file
diff --git a/statusheader.c b/statusheader.c
new file mode 100644
index 0000000..cac916e
--- /dev/null
+++ b/statusheader.c
@@ -0,0 +1,142 @@
+#include "tools.h"
+#include "services/scraper2vdr.h"
+#include "imageloader.h"
+#include "statusheader.h"
+
+cStatusHeader::cStatusHeader(void) {
+ color = theme.Color(clrStatusHeader);
+ colorBlending = theme.Color(clrStatusHeaderBlending);
+ height = geoManager.statusHeaderHeight;
+ width = geoManager.headerContentWidth;
+ tvFrameWidth = geoManager.tvFrameWidth;
+ pixmap = osdManager.requestPixmap(1, cRect(0, 0, width, height));
+ pixmapText = osdManager.requestPixmap(2, cRect(0, 0, width, height));
+ pixmapTVFrame = osdManager.requestPixmap(1, cRect(width, 0, tvFrameWidth, height));
+}
+
+cStatusHeader::~cStatusHeader(void) {
+ osdManager.releasePixmap(pixmapText);
+ osdManager.releasePixmap(pixmapTVFrame);
+ if (tvguideConfig.scaleVideo) {
+ cRect vidWin = cDevice::PrimaryDevice()->CanScaleVideo(cRect::Null);
+ cDevice::PrimaryDevice()->ScaleVideo(vidWin);
+ }
+}
+
+void cStatusHeader::Draw(void) {
+ pixmapText->Fill(clrTransparent);
+ pixmapTVFrame->Fill(clrTransparent);
+ if (tvguideConfig.style == eStyleGraphical) {
+ if (tvguideConfig.scaleVideo) {
+ drawBackgroundGraphical(bgStatusHeaderWindowed);
+ cImage *tvFrameBack = imgCache.GetOsdElement(oeStatusHeaderTVFrame);
+ if (tvFrameBack)
+ pixmapTVFrame->DrawImage(cPoint(0,0), *tvFrameBack);
+ } else {
+ drawBackgroundGraphical(bgStatusHeaderFull);
+ }
+ } else {
+ if (tvguideConfig.decorateVideo) {
+ DecorateVideoFrame();
+ }
+ drawBackground();
+ drawBorder();
+ }
+}
+
+void cStatusHeader::ScaleVideo(void) {
+ if (tvguideConfig.scaleVideo) {
+ int width = height * 16 / 9;
+ int x = osdManager.Left() + geoManager.osdWidth - width;
+ int y = osdManager.Top();
+ cRect availableRect(x, y, width, height);
+ cRect vidWin = cDevice::PrimaryDevice()->CanScaleVideo(availableRect);
+ cDevice::PrimaryDevice()->ScaleVideo(vidWin);
+ }
+}
+
+void cStatusHeader::DrawInfoText(cGrid *grid) {
+ int border = 10;
+ int textWidth = width - 2 * border - geoManager.clockWidth - 2;
+ tColor colorTextBack = (tvguideConfig.style == eStyleFlat)?color:clrTransparent;
+ pixmapText->Fill(clrTransparent);
+ int x = border;
+ int y = border;
+ if (!grid->isDummy()) {
+ const cEvent *event = grid->GetEvent();
+ int newX = DrawPoster(event, x, y, height-2*border, border);
+ if (newX > 0) {
+ textWidth -= (newX - x);
+ x += newX;
+ }
+ cString time = grid->getTimeString();
+ cString title("");
+ title = cString::sprintf(": %s", event->Title());
+ cString header = cString::sprintf("%s%s", *time, *title);
+ header = CutText(*header, textWidth, fontManager.FontStatusHeaderLarge).c_str();
+ pixmapText->DrawText(cPoint(x,y), *header, theme.Color(clrFont), colorTextBack, fontManager.FontStatusHeaderLarge);
+ y += fontManager.FontStatusHeaderLarge->Height() + border;
+ int heightText = pixmapText->ViewPort().Height() - y;
+ cTextWrapper description;
+ description.Set(event->Description(), fontManager.FontStatusHeader, textWidth);
+ int lineHeight = fontManager.FontStatusHeader->Height();
+ int textLines = description.Lines();
+ int maxLines = heightText / lineHeight;
+ int lines = min(textLines, maxLines);
+ for (int i = 0; i < lines-1; i++) {
+ pixmapText->DrawText(cPoint(x,y), description.GetLine(i), theme.Color(clrFont), colorTextBack, fontManager.FontStatusHeader);
+ y += lineHeight;
+ }
+ cString lastLine = description.GetLine(lines-1);
+ if (textLines > maxLines) {
+ lastLine = cString::sprintf("%s...", *lastLine);
+ }
+ pixmapText->DrawText(cPoint(x,y), *lastLine, theme.Color(clrFont), colorTextBack, fontManager.FontStatusHeader);
+ } else {
+ int heightText = pixmapText->ViewPort().Height() - y;
+ y += (heightText - fontManager.FontStatusHeaderLarge->Height() - 2*border)/2;
+ pixmapText->DrawText(cPoint(x,y), *grid->getText(), theme.Color(clrFont), colorTextBack, fontManager.FontStatusHeaderLarge);
+ }
+}
+
+int cStatusHeader::DrawPoster(const cEvent *event, int x, int y, int height, int border) {
+ bool hasPoster = false;
+ ScraperGetPoster posterScraper2Vdr;
+ int posterWidth = 0;
+ int posterHeight = 0;
+ static cPlugin *pScraper2Vdr = cPluginManager::GetPlugin("scraper2vdr");
+ if (pScraper2Vdr) {
+ posterScraper2Vdr.event = event;
+ posterScraper2Vdr.recording = NULL;
+ if (pScraper2Vdr->Service("GetPoster", &posterScraper2Vdr)) {
+ hasPoster = true;
+ int posterWidthOrig = posterScraper2Vdr.poster.width;
+ int posterHeightOrig = posterScraper2Vdr.poster.height;
+ posterHeight = height;
+ posterWidth = posterWidthOrig * ((double)posterHeight / (double)posterHeightOrig);
+ } else {
+ hasPoster = false;
+ }
+ }
+ if (hasPoster) {
+ cImageLoader imgLoader;
+ if (imgLoader.LoadPoster(posterScraper2Vdr.poster.path.c_str(), posterWidth, posterHeight)) {
+ pixmapText->DrawImage(cPoint(x, y), imgLoader.GetImage());
+ return posterWidth + border;
+ }
+ }
+ return 0;
+}
+
+void cStatusHeader::DecorateVideoFrame(void) {
+ int radius = 16;
+ int frame = 2;
+ pixmapTVFrame->DrawRectangle(cRect(0, 0, tvFrameWidth, frame), theme.Color(clrBackgroundOSD));
+ pixmapTVFrame->DrawEllipse(cRect(frame,frame,radius,radius), theme.Color(clrBackgroundOSD), -2);
+ pixmapTVFrame->DrawRectangle(cRect(tvFrameWidth - frame, frame, frame, height - 2*frame), theme.Color(clrBackgroundOSD));
+ pixmapTVFrame->DrawEllipse(cRect(tvFrameWidth - radius - frame, frame, radius, radius), theme.Color(clrBackgroundOSD), -1);
+ pixmapTVFrame->DrawRectangle(cRect(0, frame, frame, height - 2*frame), theme.Color(clrBackgroundOSD));
+ pixmapTVFrame->DrawEllipse(cRect(frame, height - radius - frame, radius, radius), theme.Color(clrBackgroundOSD), -3);
+ pixmapTVFrame->DrawRectangle(cRect(0, height - frame, tvFrameWidth, frame), theme.Color(clrBackgroundOSD));
+ pixmapTVFrame->DrawEllipse(cRect(tvFrameWidth - radius - frame, height - radius - frame, radius, radius), theme.Color(clrBackgroundOSD), -4);
+}
\ No newline at end of file
diff --git a/statusheader.h b/statusheader.h
new file mode 100644
index 0000000..3096803
--- /dev/null
+++ b/statusheader.h
@@ -0,0 +1,25 @@
+#ifndef __TVGUIDE_STATUSHEADER_H
+#define __TVGUIDE_STATUSHEADER_H
+
+#include "styledpixmap.h"
+#include "grid.h"
+
+// --- cStatusHeader -------------------------------------------------------------
+
+class cStatusHeader : public cStyledPixmap {
+private:
+ int width, height;
+ int tvFrameWidth;
+ cPixmap *pixmapText;
+ cPixmap *pixmapTVFrame;
+ int DrawPoster(const cEvent *event, int x, int y, int height, int border);
+ void DecorateVideoFrame(void);
+public:
+ cStatusHeader(void);
+ virtual ~cStatusHeader(void);
+ void Draw(void);
+ void ScaleVideo(void);
+ void DrawInfoText(cGrid *grid);
+};
+
+#endif //__TVGUIDE_STATUSHEADER_H
\ No newline at end of file
diff --git a/styledpixmap.c b/styledpixmap.c
index 1669501..73c9256 100644
--- a/styledpixmap.c
+++ b/styledpixmap.c
@@ -1,62 +1,123 @@
+#include "imageloader.h"
+#include "geometrymanager.h"
#include "styledpixmap.h"
cStyledPixmap::cStyledPixmap(void) {
- pixmap = NULL;
- caller = NULL;
+ pixmap = NULL;
}
-cStyledPixmap::cStyledPixmap(cPixmap *pixmap, cString caller) {
- this->pixmap = pixmap;
- this->caller = caller;
+cStyledPixmap::cStyledPixmap(cPixmap *pixmap) {
+ this->pixmap = pixmap;
}
cStyledPixmap::~cStyledPixmap(void) {
- if (pixmap)
- osdManager.releasePixmap(pixmap, *caller);
+ if (pixmap)
+ osdManager.releasePixmap(pixmap);
}
void cStyledPixmap::setPixmap(cPixmap *pixmap) {
- if (pixmap) {
- this->pixmap = pixmap;
- }
+ if (pixmap) {
+ this->pixmap = pixmap;
+ }
}
void cStyledPixmap::drawBackground() {
- if (tvguideConfig.useBlending == 1){
- drawBlendedBackground();
- } else if (tvguideConfig.useBlending == 2){
- drawSparsedBackground();
- } else {
+ if (tvguideConfig.style == eStyleBlendingDefault){
+ drawBlendedBackground();
+ } else if (tvguideConfig.style == eStyleBlendingMagick){
+ drawSparsedBackground();
+ } else {
pixmap->Fill(color);
}
}
+void cStyledPixmap::drawBackgroundGraphical(eBackgroundType type, bool active) {
+ cImage *back = NULL;
+ if (type == bgGrid) {
+ back = imgCache.GetGrid(pixmap->ViewPort().Width(), pixmap->ViewPort().Height(), active);
+ } else if (type == bgChannelHeader) {
+ back = imgCache.GetOsdElement(oeLogoBack);
+ } else if (type == bgChannelGroup) {
+ back = imgCache.GetChannelGroup(pixmap->ViewPort().Width(), pixmap->ViewPort().Height());
+ } else if (type == bgStatusHeaderWindowed) {
+ back = imgCache.GetOsdElement(oeStatusHeaderContentWindowed);
+ } else if (type == bgStatusHeaderFull) {
+ back = imgCache.GetOsdElement(oeStatusHeaderContentFull);
+ } else if (type == bgClock) {
+ back = imgCache.GetOsdElement(oeClock);
+ } else if (type == bgButton) {
+ drawBackgroundButton(active);
+ return;
+ } else if (type == bgRecMenuBack) {
+ cImageLoader imgLoader;
+ if (imgLoader.LoadOsdElement("recmenu_background", pixmap->ViewPort().Width(), pixmap->ViewPort().Height())) {
+ cImage background = imgLoader.GetImage();
+ pixmap->DrawImage(cPoint(0, 0), background);
+ } else {
+ pixmap->Fill(clrTransparent);
+ }
+ return;
+ } else if (type == bgChannelJump) {
+ back = imgCache.GetOsdElement(oeChannelJump);
+ }
+ if (back) {
+ pixmap->DrawImage(cPoint(0,0), *back);
+ } else {
+ pixmap->Fill(clrTransparent);
+ }
+}
+
+void cStyledPixmap::drawBackgroundButton(bool active) {
+ std::string buttonName = "";
+ int buttonWidth = pixmap->ViewPort().Width();
+ int buttonHeight = pixmap->ViewPort().Height();
+ if (buttonWidth > geoManager.osdWidth * 50 / 100) {
+ if (active)
+ buttonName = "button_active_70percent";
+ else
+ buttonName = "button_70percent";
+ } else {
+ if (active)
+ buttonName = "button_active_30percent";
+ else
+ buttonName = "button_30percent";
+ }
+ cImageLoader imgLoader;
+ if (imgLoader.LoadOsdElement(buttonName.c_str(), buttonWidth, buttonHeight)) {
+ cImage button = imgLoader.GetImage();
+ pixmap->DrawImage(cPoint(0, 0), button);
+ } else {
+ pixmap->Fill(clrTransparent);
+ }
+}
+
+
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;
- }
+ 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::drawSparsedBackground() {
- int width = pixmap->ViewPort().Width();
- int height = pixmap->ViewPort().Height();
+ int width = pixmap->ViewPort().Width();
+ int height = pixmap->ViewPort().Height();
cImageLoader imgLoader;
if (imgLoader.DrawBackground(colorBlending, color, width, height))
pixmap->DrawImage(cPoint(0,0), imgLoader.GetImage());
@@ -64,73 +125,81 @@ void cStyledPixmap::drawSparsedBackground() {
}
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);
- }
+ 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
+ pixmap->DrawRectangle(cRect(0,0,width,2), clrTransparent); //top
+ pixmap->DrawRectangle(cRect(0,0,2,height), clrTransparent); //left
+ pixmap->DrawRectangle(cRect(0,height-2,width,2), clrTransparent); //bottom
+ pixmap->DrawRectangle(cRect(width-2,0,2,height), clrTransparent); //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
+ 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);
- }
+ pixmap->DrawEllipse(cRect(2,2,radius,radius), theme.Color(clrBorder), -2);
+ pixmap->DrawEllipse(cRect(1,1,radius,radius), clrTransparent, -2);
+
+ pixmap->DrawEllipse(cRect(width-radius - 2,2,radius,radius), theme.Color(clrBorder), -1);
+ pixmap->DrawEllipse(cRect(width-radius - 1,1,radius,radius), clrTransparent, -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), clrTransparent, -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), clrTransparent, -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);
- }
+ 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);
- }
+ 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);
+ pixmap->DrawText(Point, s, ColorFg, ColorBg, Font);
}
void cStyledPixmap::DrawImage(const cPoint &Point, const cImage &Image) {
- pixmap->DrawImage(Point, Image);
+ pixmap->DrawImage(Point, Image);
}
void cStyledPixmap::DrawRectangle(const cRect &Rect, tColor Color) {
- pixmap->DrawRectangle(Rect,Color);
+ pixmap->DrawRectangle(Rect,Color);
}
+
+void cStyledPixmap::DrawEllipse(const cRect &Rect, tColor Color, int Quadrant) {
+ pixmap->DrawEllipse(Rect,Color,Quadrant);
+}
+
+void cStyledPixmap::SetViewPort(const cRect &Rect) {
+ pixmap->SetViewPort(Rect);
+}
\ No newline at end of file
diff --git a/styledpixmap.h b/styledpixmap.h
index 147d6a0..82af25c 100644
--- a/styledpixmap.h
+++ b/styledpixmap.h
@@ -1,36 +1,58 @@
#ifndef __TVGUIDE_STYLEDPIXMAP_H
#define __TVGUIDE_STYLEDPIXMAP_H
+#include <vdr/osd.h>
+#include <vdr/epg.h>
+#include "timer.h"
+#include "config.h"
+
+enum eBackgroundType {
+ bgGrid,
+ bgStatusHeaderFull,
+ bgStatusHeaderWindowed,
+ bgChannelHeader,
+ bgChannelGroup,
+ bgClock,
+ bgButton,
+ bgRecMenuBack,
+ bgChannelJump,
+};
+
// --- cStyledPixmap -------------------------------------------------------------
class cStyledPixmap {
private:
- void drawVerticalLine(int x, int yStart, int yStop, tColor col);
- void drawHorizontalLine(int y, int xStart, int xStop, tColor col);
+ void drawVerticalLine(int x, int yStart, int yStop, tColor col);
+ void drawHorizontalLine(int y, int xStart, int xStop, tColor col);
+ void drawBackgroundButton(bool active);
protected:
- cPixmap *pixmap;
- cString caller;
- tColor color;
- tColor colorBlending;
- void setPixmap(cPixmap *pixmap);
+ cPixmap *pixmap;
+ tColor color;
+ tColor colorBlending;
+ void setPixmap(cPixmap *pixmap);
public:
- cStyledPixmap(void);
- cStyledPixmap(cPixmap *pixmap, cString caller);
- virtual ~cStyledPixmap(void);
- void drawBackground();
- void drawBlendedBackground();
- void drawSparsedBackground();
- 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();};
+ cStyledPixmap(void);
+ cStyledPixmap(cPixmap *pixmap);
+ virtual ~cStyledPixmap(void);
+ void drawBackground();
+ void drawBackgroundGraphical(eBackgroundType type, bool active = false);
+ void drawBlendedBackground();
+ void drawSparsedBackground();
+ 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 SetLayer(int layer) {pixmap->SetLayer(layer);};
+ void Fill(tColor clr) {pixmap->Fill(clr);};
+ 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);
+ void DrawEllipse(const cRect &Rect, tColor Color, int Quadrant);
+ void SetViewPort(const cRect &Rect);
+ int Width() {return pixmap->ViewPort().Width();};
+ int Height() {return pixmap->ViewPort().Height();};
};
#endif //__TVGUIDE_STYLEDPIXMAP_H
\ No newline at end of file
diff --git a/switchtimer.c b/switchtimer.c
new file mode 100644
index 0000000..f56c469
--- /dev/null
+++ b/switchtimer.c
@@ -0,0 +1,113 @@
+#include "switchtimer.h"
+
+cSwitchTimers SwitchTimers;
+
+// -- cSwitchTimer -----------------------------------------------------------------
+cSwitchTimer::cSwitchTimer(void) {
+ eventID = 0;
+ startTime = 0;
+ switchMinsBefore = 2;
+ announceOnly = 0;
+}
+
+cSwitchTimer::cSwitchTimer(const cEvent* Event) {
+ eventID = 0;
+ startTime = 0;
+ if (Event) {
+ eventID = Event->EventID();
+ channelID = Event->ChannelID();
+ startTime = Event->StartTime();
+ }
+}
+
+bool cSwitchTimer::Parse(const char *s) {
+ char *line;
+ char *pos;
+ char *pos_next;
+ int parameter = 1;
+ int valuelen;
+#define MAXVALUELEN (10 * MaxFileName)
+
+ char value[MAXVALUELEN];
+ startTime=0;
+
+ pos = line = strdup(s);
+ pos_next = pos + strlen(pos);
+ if (*pos_next == '\n') *pos_next = 0;
+ while (*pos) {
+ while (*pos == ' ')
+ pos++;
+ if (*pos) {
+ if (*pos != ':') {
+ pos_next = strchr(pos, ':');
+ if (!pos_next)
+ pos_next = pos + strlen(pos);
+ valuelen = pos_next - pos + 1;
+ if (valuelen > MAXVALUELEN)
+ valuelen = MAXVALUELEN;
+ strn0cpy(value, pos, valuelen);
+ pos = pos_next;
+ switch (parameter) {
+ case 1:
+ channelID = tChannelID::FromString(value);
+ break;
+ case 2:
+ eventID = atoi(value);
+ break;
+ case 3:
+ startTime = atol(value);
+ break;
+ default:
+ break;
+ }
+ }
+ parameter++;
+ }
+ if (*pos)
+ pos++;
+ }
+ free(line);
+ return (parameter >= 3) ? true : false;
+}
+
+bool cSwitchTimers::EventInSwitchList(const cEvent* event) {
+ if (!event) return false;
+ cMutexLock SwitchTimersLock(this);
+ cSwitchTimer* switchTimer = SwitchTimers.First();
+ while (switchTimer) {
+ if (switchTimer->eventID == event->EventID())
+ return true;
+ switchTimer = SwitchTimers.Next(switchTimer);
+ }
+ return false;
+}
+
+bool cSwitchTimers::ChannelInSwitchList(const cChannel* channel) {
+ if (!channel) return false;
+ cMutexLock SwitchTimersLock(this);
+ cSwitchTimer* switchTimer = SwitchTimers.First();
+ while (switchTimer) {
+ if (switchTimer->channelID == channel->GetChannelID())
+ return true;
+ switchTimer = SwitchTimers.Next(switchTimer);
+ }
+ return false;
+}
+
+void cSwitchTimers::DeleteSwitchTimer(const cEvent *event) {
+ if (!event) return;
+ cMutexLock SwitchTimersLock(this);
+ cSwitchTimer* switchTimer = SwitchTimers.First();
+ cSwitchTimer* delTimer = NULL;
+
+ while (switchTimer) {
+ if (switchTimer->eventID == event->EventID()) {
+ delTimer = switchTimer;
+ break;
+ }
+ switchTimer = SwitchTimers.Next(switchTimer);
+ }
+ if (delTimer) {
+ SwitchTimers.Del(delTimer, true);
+ }
+}
diff --git a/switchtimer.h b/switchtimer.h
new file mode 100644
index 0000000..09ebe88
--- /dev/null
+++ b/switchtimer.h
@@ -0,0 +1,31 @@
+#ifndef __TVGUIDE_SWITCHTIMER_H
+#define __TVGUIDE_SWITCHTIMER_H
+
+#include <vdr/plugin.h>
+
+class cSwitchTimer : public cListObject {
+public:
+ tEventID eventID;
+ time_t startTime;
+ tChannelID channelID;
+ int switchMinsBefore;
+ int announceOnly;
+ cSwitchTimer(void);
+ cSwitchTimer(const cEvent* Event);
+ bool Parse(const char *s);
+ void SetEventID(tEventID eventID) { this->eventID = eventID; };
+ void SetStartTime(time_t startTime) { this->startTime = startTime; };
+};
+
+class cSwitchTimers : public cConfig<cSwitchTimer>, public cMutex {
+public:
+ cSwitchTimers(void) {}
+ ~cSwitchTimers(void) {}
+ bool EventInSwitchList(const cEvent* event);
+ bool ChannelInSwitchList(const cChannel* channel);
+ void DeleteSwitchTimer(const cEvent *event);
+};
+
+extern cSwitchTimers SwitchTimers;
+
+#endif //__TVGUIDE_SWITCHTIMER_H
diff --git a/themes/tvguide-blue.theme b/themes/tvguide-blue.theme
new file mode 100644
index 0000000..2aeda4c
--- /dev/null
+++ b/themes/tvguide-blue.theme
@@ -0,0 +1,53 @@
+Description = Blue
+clrStyle = FFFFFFFF
+clrBackground = FF000000
+clrBackgroundOSD = FF000000
+clrGrid1 = EE555555
+clrGrid1Blending = 90000000
+clrGrid2 = EE888888
+clrGrid2Blending = 90000000
+clrHighlight = EE0033FF
+clrHighlightBlending = DD000000
+clrGridFontBack = 00000000
+clrGridActiveFontBack = 00000000
+clrFont = FFFFFFFF
+clrFontActive = FFFFFFFF
+clrFontHeader = FFFFFFFF
+clrFontButtons = FFFFFFFF
+clrHeader = EE888888
+clrHeaderBlending = 90000000
+clrBorder = DD003DF5
+clrStatusHeader = 00000000
+clrStatusHeaderBlending = 00000000
+clrTimeline1 = BBFFFFFF
+clrTimeline1Blending = 90828282
+clrTimeline2 = BB000000
+clrTimeline2Blending = 903F3F3F
+clrTimeBase = A0FF0000
+clrTabInactive = 44003DF5
+clrButtonRed = 99BB0000
+clrButtonRedBorder = FFBB0000
+clrButtonGreen = 9900BB00
+clrButtonGreenBorder = FF00BB00
+clrButtonYellow = 99BBBB00
+clrButtonYellowBorder = FFBBBB00
+clrButtonBlue = 990000BB
+clrButtonBlueBorder = FF0000BB
+clrButtonBlend = DD000000
+clrRecMenuBackground = AA000000
+clrRecMenuTimerConflictBackground = FFCCCCCC
+clrRecMenuTimerConflictBar = FF222222
+clrRecMenuTimerConflictOverlap = AAFF0000
+clrRecMenuDayActive = FF00FF00
+clrRecMenuDayInactive = FFFF0000
+clrRecMenuDayHighlight = 44FFFFFF
+clrRecMenuTextBack = FF000000
+clrRecMenuTextActiveBack = FF404749
+clrRecMenuKeyboardBack = FF000000
+clrRecMenuKeyboardBorder = FF003DF5
+clrRecMenuKeyboardHigh = 40BB0000
+clrRecMenuTimelineTimer = B012273f
+clrRecMenuTimelineBack = FF828282
+clrRecMenuTimelineActive = FF3F3F3F
+clrRecMenuTimelineConflict = 30FF0000
+clrRecMenuTimelineConflictOverlap = 90FF0000
\ No newline at end of file
diff --git a/themes/tvguide-darkblue.theme b/themes/tvguide-darkblue.theme
index 59db3ad..008aa80 100644
--- a/themes/tvguide-darkblue.theme
+++ b/themes/tvguide-darkblue.theme
@@ -1,5 +1,5 @@
-Description = DarkBlue
-
+Description = Dark Blue
+clrStyle = AAAAAAAA
clrBackground = FF000000
clrBackgroundOSD = FF000000
clrGrid1 = FF0E53A7
@@ -8,16 +8,23 @@ clrGrid2 = FF071871
clrGrid2Blending = FF000000
clrHighlight = FF7A6D6D
clrHighlightBlending = FF1C1919
+clrGridFontBack = 00000000
+clrGridActiveFontBack = 00000000
clrFont = FFFFFFFF
+clrFontActive = FFFFFFFF
clrFontHeader = FF000000
clrFontButtons = FFFFFFFF
clrHeader = FF8B9194
clrHeaderBlending = FF000000
clrBorder = FFFFFFFF
+clrStatusHeader = 00000000
+clrStatusHeaderBlending = 00000000
clrTimeline1 = FFFFFFFF
clrTimeline1Blending = FF828282
clrTimeline2 = FF000000
clrTimeline2Blending = FF3F3F3F
+clrTimeBase = A0FF0000
+clrTabInactive = 99242A38
clrButtonRed = 99BB0000
clrButtonRedBorder = FFBB0000
clrButtonGreen = 9900BB00
@@ -27,3 +34,20 @@ clrButtonYellowBorder = FFBBBB00
clrButtonBlue = 990000BB
clrButtonBlueBorder = FF0000BB
clrButtonBlend = DD000000
+clrRecMenuBackground = AA000000
+clrRecMenuTimerConflictBackground = FFCCCCCC
+clrRecMenuTimerConflictBar = FF222222
+clrRecMenuTimerConflictOverlap = AAFF0000
+clrRecMenuDayActive = FF00FF00
+clrRecMenuDayInactive = FFFF0000
+clrRecMenuDayHighlight = 44FFFFFF
+clrRecMenuTextBack = FF000000
+clrRecMenuTextActiveBack = FF404749
+clrRecMenuKeyboardBack = FF000000
+clrRecMenuKeyboardBorder = FFFFFFFF
+clrRecMenuKeyboardHigh = 40BB0000
+clrRecMenuTimelineTimer = B012273f
+clrRecMenuTimelineBack = FF828282
+clrRecMenuTimelineActive = FF3F3F3F
+clrRecMenuTimelineConflict = 30FF0000
+clrRecMenuTimelineConflictOverlap = 90FF0000
\ No newline at end of file
diff --git a/themes/tvguide-darkred.theme b/themes/tvguide-darkred.theme
new file mode 100644
index 0000000..06f7c71
--- /dev/null
+++ b/themes/tvguide-darkred.theme
@@ -0,0 +1,53 @@
+Description = Dark Red
+clrStyle = FFFFFFFF
+clrBackground = FF000000
+clrBackgroundOSD = FF000000
+clrGrid1 = EE555555
+clrGrid1Blending = 90000000
+clrGrid2 = DD333333
+clrGrid2Blending = 90000000
+clrHighlight = DDBB0000
+clrHighlightBlending = DD000000
+clrGridFontBack = 00000000
+clrGridActiveFontBack = 00000000
+clrFont = FFFFFFFF
+clrFontActive = FFFFFFFF
+clrFontHeader = FFFFFFFF
+clrFontButtons = FFFFFFFF
+clrHeader = EE888888
+clrHeaderBlending = 90000000
+clrBorder = AABB0000
+clrStatusHeader = 00000000
+clrStatusHeaderBlending = 00000000
+clrTimeline1 = BBFFFFFF
+clrTimeline1Blending = 90828282
+clrTimeline2 = BB000000
+clrTimeline2Blending = 903F3F3F
+clrTimeBase = A0FF0000
+clrTabInactive = 66550000
+clrButtonRed = 99BB0000
+clrButtonRedBorder = FFBB0000
+clrButtonGreen = 9900BB00
+clrButtonGreenBorder = FF00BB00
+clrButtonYellow = 99BBBB00
+clrButtonYellowBorder = FFBBBB00
+clrButtonBlue = 990000BB
+clrButtonBlueBorder = FF0000BB
+clrButtonBlend = DD000000
+clrRecMenuBackground = AA000000
+clrRecMenuTimerConflictBackground = FFCCCCCC
+clrRecMenuTimerConflictBar = FF222222
+clrRecMenuTimerConflictOverlap = AAFF0000
+clrRecMenuDayActive = FF00FF00
+clrRecMenuDayInactive = FFFF0000
+clrRecMenuDayHighlight = 44FFFFFF
+clrRecMenuTextBack = FF000000
+clrRecMenuTextActiveBack = FF404749
+clrRecMenuKeyboardBack = FF000000
+clrRecMenuKeyboardBorder = FF660000
+clrRecMenuKeyboardHigh = 40BB0000
+clrRecMenuTimelineTimer = B0660000
+clrRecMenuTimelineBack = FF828282
+clrRecMenuTimelineActive = FF3F3F3F
+clrRecMenuTimelineConflict = 30FF0000
+clrRecMenuTimelineConflictOverlap = 90FF0000
\ No newline at end of file
diff --git a/themes/tvguide-darkredNG.theme b/themes/tvguide-darkredNG.theme
new file mode 100644
index 0000000..93ddc41
--- /dev/null
+++ b/themes/tvguide-darkredNG.theme
@@ -0,0 +1,53 @@
+Description = Dark Red NG
+clrStyle = 66666666
+clrBackground = FF000000
+clrBackgroundOSD = FF000000
+clrGrid1 = EE555555
+clrGrid1Blending = 90000000
+clrGrid2 = DD333333
+clrGrid2Blending = 90000000
+clrHighlight = DDBB0000
+clrHighlightBlending = DD000000
+clrGridFontBack = 00000000
+clrGridActiveFontBack = 00000000
+clrFont = FFFFFFFF
+clrFontActive = FFFFFFFF
+clrFontHeader = FFFFFFFF
+clrFontButtons = FFFFFFFF
+clrHeader = EE888888
+clrHeaderBlending = 90000000
+clrBorder = 00000000
+clrStatusHeader = 00000000
+clrStatusHeaderBlending = 00000000
+clrTimeline1 = FFFFFFFF
+clrTimeline1Blending = 90828282
+clrTimeline2 = FF000000
+clrTimeline2Blending = 903F3F3F
+clrTimeBase = A0FF0000
+clrTabInactive = 66660000
+clrButtonRed = 99BB0000
+clrButtonRedBorder = FFBB0000
+clrButtonGreen = 9900BB00
+clrButtonGreenBorder = FF00BB00
+clrButtonYellow = 99BBBB00
+clrButtonYellowBorder = FFBBBB00
+clrButtonBlue = 990000BB
+clrButtonBlueBorder = FF0000BB
+clrButtonBlend = DD000000
+clrRecMenuBackground = AA000000
+clrRecMenuTimerConflictBackground = FFCCCCCC
+clrRecMenuTimerConflictBar = FF222222
+clrRecMenuTimerConflictOverlap = 90FF0000
+clrRecMenuDayActive = FF00FF00
+clrRecMenuDayInactive = FFFF0000
+clrRecMenuDayHighlight = 44FFFFFF
+clrRecMenuTextBack = FF000000
+clrRecMenuTextActiveBack = FF404749
+clrRecMenuKeyboardBack = FF000000
+clrRecMenuKeyboardBorder = FF660000
+clrRecMenuKeyboardHigh = 40BB0000
+clrRecMenuTimelineTimer = B0660000
+clrRecMenuTimelineBack = FF828282
+clrRecMenuTimelineActive = FF3F3F3F
+clrRecMenuTimelineConflict = 30FF0000
+clrRecMenuTimelineConflictOverlap = 90FF0000
\ No newline at end of file
diff --git a/themes/tvguide-default.theme b/themes/tvguide-default.theme
index b9817b5..c8fc9b0 100644
--- a/themes/tvguide-default.theme
+++ b/themes/tvguide-default.theme
@@ -1,28 +1,53 @@
Description = Default
-clrBackground = FF000000
-clrBackgroundOSD = FF000000
-clrGrid1 = FF404749
-clrGrid1Blending = FF000000
-clrGrid2 = FF20293F
-clrGrid2Blending = FF000000
-clrHighlight = FFFF4D00
-clrHighlightBlending = FF000000
+clrStyle = 66666666
+clrBackground = FF12273f
+clrBackgroundOSD = B012273f
+clrGrid1 = 00000000
+clrGrid1Blending = 00000000
+clrGrid2 = 00000000
+clrGrid2Blending = 00000000
+clrHighlight = DD313548
+clrHighlightBlending = DD000000
+clrGridFontBack = 00000000
+clrGridActiveFontBack = FFAFD533
clrFont = FFFFFFFF
-clrFontHeader = FFFFFFFF
+clrFontActive = FF363636
+clrFontHeader = FF363636
clrFontButtons = FFFFFFFF
-clrHeader = FF000000
-clrHeaderBlending = FFE0E0E0
-clrBorder = FFFFFFFF
+clrHeader = 00000000
+clrHeaderBlending = 00000000
+clrBorder = 00000000
+clrStatusHeader = 00000000
+clrStatusHeaderBlending = 00000000
clrTimeline1 = FFFFFFFF
clrTimeline1Blending = FF828282
clrTimeline2 = FF000000
clrTimeline2Blending = FF3F3F3F
-clrButtonRed = 99BB0000
-clrButtonRedBorder = FFBB0000
-clrButtonGreen = 9900BB00
-clrButtonGreenBorder = FF00BB00
-clrButtonYellow = 99BBBB00
-clrButtonYellowBorder = FFBBBB00
-clrButtonBlue = 990000BB
-clrButtonBlueBorder = FF0000BB
+clrTimeBase = A0FF0000
+clrTabInactive = A01F3D7A
+clrButtonRed = FFFF0000
+clrButtonRedBorder = 00000000
+clrButtonGreen = 00000000
+clrButtonGreenBorder = 00000000
+clrButtonYellow = 00000000
+clrButtonYellowBorder = 00000000
+clrButtonBlue = 00000000
+clrButtonBlueBorder = 00000000
clrButtonBlend = DD000000
+clrRecMenuBackground = AA000000
+clrRecMenuTimerConflictBackground = FFCCCCCC
+clrRecMenuTimerConflictBar = FF222222
+clrRecMenuTimerConflictOverlap = A0FF0000
+clrRecMenuDayActive = FF00FF00
+clrRecMenuDayInactive = FFFF0000
+clrRecMenuDayHighlight = 44FFFFFF
+clrRecMenuTextBack = FF000000
+clrRecMenuTextActiveBack = FF939376
+clrRecMenuKeyboardBack = FF000000
+clrRecMenuKeyboardBorder = FFFFFFFF
+clrRecMenuKeyboardHigh = 40BB0000
+clrRecMenuTimelineTimer = B012273f
+clrRecMenuTimelineBack = FF828282
+clrRecMenuTimelineActive = FF3F3F3F
+clrRecMenuTimelineConflict = 30FF0000
+clrRecMenuTimelineConflictOverlap = 90FF0000
diff --git a/themes/tvguide-green.theme b/themes/tvguide-green.theme
new file mode 100644
index 0000000..7fca3b0
--- /dev/null
+++ b/themes/tvguide-green.theme
@@ -0,0 +1,53 @@
+Description = Green
+clrStyle = FFFFFFFF
+clrBackground = FF000000
+clrBackgroundOSD = FF000000
+clrGrid1 = EE555555
+clrGrid1Blending = 90000000
+clrGrid2 = EE888888
+clrGrid2Blending = 90000000
+clrHighlight = EE006600
+clrHighlightBlending = 22000000
+clrGridFontBack = 00000000
+clrGridActiveFontBack = 00000000
+clrFont = FFFFFFFF
+clrFontActive = FFFFFFFF
+clrFontHeader = FFFFFFFF
+clrFontButtons = FFFFFFFF
+clrHeader = EE888888
+clrHeaderBlending = 90000000
+clrBorder = EE006600
+clrStatusHeader = 00000000
+clrStatusHeaderBlending = 00000000
+clrTimeline1 = BBFFFFFF
+clrTimeline1Blending = 90828282
+clrTimeline2 = BB000000
+clrTimeline2Blending = 903F3F3F
+clrTimeBase = A0FF0000
+clrTabInactive = 33006600
+clrButtonRed = 99BB0000
+clrButtonRedBorder = FFBB0000
+clrButtonGreen = 9900BB00
+clrButtonGreenBorder = FF00BB00
+clrButtonYellow = 99BBBB00
+clrButtonYellowBorder = FFBBBB00
+clrButtonBlue = 990000BB
+clrButtonBlueBorder = FF0000BB
+clrButtonBlend = DD000000
+clrRecMenuBackground = AA000000
+clrRecMenuTimerConflictBackground = FFCCCCCC
+clrRecMenuTimerConflictBar = FF222222
+clrRecMenuTimerConflictOverlap = AAFF0000
+clrRecMenuDayActive = FF00FF00
+clrRecMenuDayInactive = FFFF0000
+clrRecMenuDayHighlight = 44FFFFFF
+clrRecMenuTextBack = FF000000
+clrRecMenuTextActiveBack = FF404749
+clrRecMenuKeyboardBack = FF000000
+clrRecMenuKeyboardBorder = EE006600
+clrRecMenuKeyboardHigh = 40BB0000
+clrRecMenuTimelineTimer = B0003D00
+clrRecMenuTimelineBack = FF828282
+clrRecMenuTimelineActive = FF3F3F3F
+clrRecMenuTimelineConflict = 30FF0000
+clrRecMenuTimelineConflictOverlap = 90FF0000
\ No newline at end of file
diff --git a/themes/tvguide-iceblue.theme b/themes/tvguide-iceblue.theme
new file mode 100644
index 0000000..310872a
--- /dev/null
+++ b/themes/tvguide-iceblue.theme
@@ -0,0 +1,51 @@
+Description = IceBlue
+clrStyle = 00000000
+clrBackground = DDFFFFFF
+clrBackgroundOSD = FFFFFFFF
+clrGrid1 = BB555555
+clrGrid2 = BB888888
+clrGridFontBack = 00000000
+clrGridActiveFontBack = 00000000
+clrHighlight = FF000044
+clrFont = FF000000
+clrFontActive = FFFFFFFF
+clrFontButtons = FFFFFFFF
+clrFontHeader = FF000000
+clrHeader = FFFFFFFF
+clrBorder = FF000000
+clrStatusHeader = FFFFFFFF
+clrStatusHeaderBlending = FFFFFFFF
+clrTimeline1 = FFDDDDDD
+clrTimeline1Blending = 00000000
+clrTimeline2 = FF000000
+clrTimeline2Blending = 00000000
+clrTimeBase = A0FF0000
+clrTabInactive = 88B8B8E6
+clrButtonRed = FFBB0000
+clrButtonRedBorder = FF000000
+clrButtonGreen = FF00BB00
+clrButtonGreenBorder = FF000000
+clrButtonYellow = FFBBBB00
+clrButtonYellowBorder = FF000000
+clrButtonBlue = FF0000BB
+clrButtonBlueBorder = FF000000
+clrRecMenuBackground = AA000000
+clrRecMenuTimerConflictBackground = FFCCCCCC
+clrRecMenuTimerConflictBar = FF222222
+clrRecMenuTimerConflictOverlap = AAFF0000
+clrRecMenuDayActive = FF00FF00
+clrRecMenuDayInactive = FFFF0000
+clrRecMenuDayHighlight = 77000000
+clrRecMenuTextBack = FF3C3C3C
+clrRecMenuTextActiveBack = FF404749
+clrRecMenuKeyboardBack = FF000044
+clrRecMenuKeyboardBorder = FF3C3C3C
+clrRecMenuKeyboardHigh = 55FFFFFF
+clrButtonRedKeyboard = FFBB0000
+clrButtonGreenKeyboard = FF00BB00
+clrButtonYellowKeyboard = FFBBBB00
+clrRecMenuTimelineTimer = B012273f
+clrRecMenuTimelineBack = FF828282
+clrRecMenuTimelineActive = FF3F3F3F
+clrRecMenuTimelineConflict = 30FF0000
+clrRecMenuTimelineConflictOverlap = 90FF0000
\ No newline at end of file
diff --git a/themes/tvguide-keepitsimple.theme b/themes/tvguide-keepitsimple.theme
new file mode 100644
index 0000000..1f325c9
--- /dev/null
+++ b/themes/tvguide-keepitsimple.theme
@@ -0,0 +1,49 @@
+Description = Keep it simple
+clrStyle = 00000000
+clrBackground = FF111111
+clrBackgroundOSD = FF111111
+clrGrid1 = BB555555
+clrGrid2 = BB888888
+clrGridFontBack = 00000000
+clrGridActiveFontBack = 00000000
+clrHighlight = FF336699
+clrFont = FFFFFFFF
+clrFontActive = FFFFFFFF
+clrFontButtons = FFFFFFFF
+clrFontHeader = FFDCDCDC
+clrHeader = FF2B3856
+clrBorder = FF000000
+clrStatusHeader = FF111111
+clrStatusHeaderBlending = 00000000
+clrTimeline1 = FF737CA1
+clrTimeline1Blending = 00000000
+clrTimeline2 = FF2B3856
+clrTimeline2Blending = 00000000
+clrTimeBase = A0FF0000
+clrTabInactive = 886fac10
+clrButtonRed = 99BB0000
+clrButtonRedBorder = FFBB0000
+clrButtonGreen = 9900BB00
+clrButtonGreenBorder = FF00BB00
+clrButtonYellow = 99BBBB00
+clrButtonYellowBorder = FFBBBB00
+clrButtonBlue = 990000BB
+clrButtonBlueBorder = FF0000BB
+clrButtonBlend = DD000000
+clrRecMenuBackground = AA000000
+clrRecMenuTimerConflictBackground = FFCCCCCC
+clrRecMenuTimerConflictBar = FF222222
+clrRecMenuTimerConflictOverlap = AAFF0000
+clrRecMenuDayActive = FF00FF00
+clrRecMenuDayInactive = FFFF0000
+clrRecMenuDayHighlight = 44FFFFFF
+clrRecMenuTextBack = FF000000
+clrRecMenuTextActiveBack = FF404749
+clrRecMenuKeyboardBack = FF000000
+clrRecMenuKeyboardBorder = BB555555
+clrRecMenuKeyboardHigh = 40BB0000
+clrRecMenuTimelineTimer = B012273f
+clrRecMenuTimelineBack = FF828282
+clrRecMenuTimelineActive = FF3F3F3F
+clrRecMenuTimelineConflict = 30FF0000
+clrRecMenuTimelineConflictOverlap = 90FF0000
\ No newline at end of file
diff --git a/themes/tvguide-nOpacity.theme b/themes/tvguide-nOpacity.theme
deleted file mode 100644
index f00d54b..0000000
--- a/themes/tvguide-nOpacity.theme
+++ /dev/null
@@ -1,28 +0,0 @@
-Description = nOpacity
-clrBackground = FF000000
-clrBackgroundOSD = FF000000
-clrGrid1 = EE555555
-clrGrid1Blending = 90000000
-clrGrid2 = EE888888
-clrGrid2Blending = 90000000
-clrHighlight = EE0033FF
-clrHighlightBlending = DD000000
-clrFont = FFFFFFFF
-clrFontHeader = FFFFFFFF
-clrFontButtons = FFFFFFFF
-clrHeader = EE888888
-clrHeaderBlending = 90000000
-clrBorder = DD003DF5
-clrTimeline1 = BBFFFFFF
-clrTimeline1Blending = 90828282
-clrTimeline2 = BB000000
-clrTimeline2Blending = 903F3F3F
-clrButtonRed = 99BB0000
-clrButtonRedBorder = FFBB0000
-clrButtonGreen = 9900BB00
-clrButtonGreenBorder = FF00BB00
-clrButtonYellow = 99BBBB00
-clrButtonYellowBorder = FFBBBB00
-clrButtonBlue = 990000BB
-clrButtonBlueBorder = FF0000BB
-clrButtonBlend = DD000000
diff --git a/themes/tvguide-nOpacitygreen.theme b/themes/tvguide-nOpacitygreen.theme
deleted file mode 100644
index 46ca336..0000000
--- a/themes/tvguide-nOpacitygreen.theme
+++ /dev/null
@@ -1,28 +0,0 @@
-Description = nOpacity Green
-clrBackground = FF000000
-clrBackgroundOSD = FF000000
-clrGrid1 = EE555555
-clrGrid1Blending = 90000000
-clrGrid2 = EE888888
-clrGrid2Blending = 90000000
-clrHighlight = EE006600
-clrHighlightBlending = 22000000
-clrFont = FFFFFFFF
-clrFontHeader = FFFFFFFF
-clrFontButtons = FFFFFFFF
-clrHeader = EE888888
-clrHeaderBlending = 90000000
-clrBorder = EE006600
-clrTimeline1 = BBFFFFFF
-clrTimeline1Blending = 90828282
-clrTimeline2 = BB000000
-clrTimeline2Blending = 903F3F3F
-clrButtonRed = 99BB0000
-clrButtonRedBorder = FFBB0000
-clrButtonGreen = 9900BB00
-clrButtonGreenBorder = FF00BB00
-clrButtonYellow = 99BBBB00
-clrButtonYellowBorder = FFBBBB00
-clrButtonBlue = 990000BB
-clrButtonBlueBorder = FF0000BB
-clrButtonBlend = DD000000
diff --git a/timeline.c b/timeline.c
index be3199a..168861c 100644
--- a/timeline.c
+++ b/timeline.c
@@ -1,102 +1,237 @@
+#include "imageloader.h"
#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");
+ this->myTime = myTime;
+ if (tvguideConfig.displayMode == eVertical) {
+ dateViewer = new cStyledPixmap(osdManager.requestPixmap(1, cRect(0,
+ geoManager.statusHeaderHeight,
+ geoManager.dateVieverWidth,
+ geoManager.dateVieverHeight)));
+ timeline = osdManager.requestPixmap(2, cRect(0,
+ geoManager.statusHeaderHeight + geoManager.channelHeaderHeight + geoManager.channelGroupsHeight,
+ geoManager.timeLineWidth,
+ geoManager.osdHeight - geoManager.statusHeaderHeight - geoManager.channelHeaderHeight - geoManager.channelGroupsHeight - geoManager.footerHeight)
+ , cRect(0,
+ 0,
+ geoManager.timeLineWidth,
+ 1440*geoManager.minutePixel));
+ timeBase = osdManager.requestPixmap(3, cRect(0,
+ geoManager.statusHeaderHeight + geoManager.channelGroupsHeight + geoManager.channelHeaderHeight,
+ geoManager.osdWidth,
+ geoManager.timeLineGridHeight));
+ } else if (tvguideConfig.displayMode == eHorizontal) {
+ dateViewer = new cStyledPixmap(osdManager.requestPixmap(1, cRect(0,
+ geoManager.statusHeaderHeight,
+ geoManager.dateVieverWidth,
+ geoManager.dateVieverHeight)));
+ timeline = osdManager.requestPixmap(2, cRect(geoManager.channelHeaderWidth + geoManager.channelGroupsWidth,
+ geoManager.statusHeaderHeight,
+ geoManager.osdWidth - geoManager.channelHeaderWidth - geoManager.channelGroupsWidth,
+ geoManager.timeLineHeight)
+ , cRect(0,
+ 0,
+ 1440*geoManager.minutePixel,
+ geoManager.timeLineHeight));
+ timeBase = osdManager.requestPixmap(3, cRect(geoManager.channelGroupsWidth + geoManager.channelHeaderWidth,
+ geoManager.statusHeaderHeight,
+ geoManager.timeLineGridWidth,
+ geoManager.timeLineHeight + tvguideConfig.channelRows * geoManager.rowHeight));
+ }
+ timeBase->Fill(clrTransparent);
+ int clockY = 10;
+ int clockX;
+ if (tvguideConfig.scaleVideo) {
+ clockX = geoManager.osdWidth - geoManager.tvFrameWidth - geoManager.clockWidth - 4;
+ } else {
+ clockX = geoManager.osdWidth - geoManager.clockWidth - 10;
+ }
+ clock = new cStyledPixmap(osdManager.requestPixmap(3, cRect(clockX,
+ clockY,
+ geoManager.clockWidth,
+ geoManager.clockHeight)));
}
cTimeLine::~cTimeLine(void) {
- delete dateViewer;
- osdManager.releasePixmap(timeline);
- delete clock;
+ delete dateViewer;
+ osdManager.releasePixmap(timeline);
+ if (clock)
+ 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);
+ cString weekDay = myTime->GetWeekday();
+ cString date = myTime->GetDate();
+ if (tvguideConfig.style != eStyleGraphical) {
+ dateViewer->setColor(theme.Color(clrHeader), theme.Color(clrHeaderBlending));
+ dateViewer->drawBackground();
+ dateViewer->drawBorder();
+
+ } else {
+ cImage *imgBack = imgCache.GetOsdElement(oeDateViewer);
+ if (imgBack)
+ dateViewer->DrawImage(cPoint(0,0), *imgBack);
+ else
+ dateViewer->Fill(clrTransparent);
+ }
+ tColor colorFont = theme.Color(clrFont);
+ tColor colorFontBack = (tvguideConfig.style == eStyleFlat)?theme.Color(clrHeader):clrTransparent;
- 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);
+ if (tvguideConfig.displayMode == eVertical) {
+ int textHeight = fontManager.FontTimeLineWeekday->Height();
+ int weekdayWidth = fontManager.FontTimeLineWeekday->Width(*weekDay);
+ int dateWidth = fontManager.FontTimeLineDate->Width(*date);
+ dateViewer->DrawText(cPoint((geoManager.timeLineWidth-weekdayWidth)/2, (geoManager.channelHeaderHeight + geoManager.channelGroupsHeight -2*textHeight)/2), *weekDay, colorFont, colorFontBack, fontManager.FontTimeLineWeekday);
+ dateViewer->DrawText(cPoint((geoManager.timeLineWidth-dateWidth)/2, (geoManager.channelHeaderHeight + geoManager.channelGroupsHeight -2*textHeight)/2 + textHeight + 5), *date, colorFont, colorFontBack, fontManager.FontTimeLineDate);
+ } else if (tvguideConfig.displayMode == eHorizontal) {
+ cString strDate = cString::sprintf("%s %s", *weekDay, *date);
+ int x = (dateViewer->Width() - fontManager.FontTimeLineDateHorizontal->Width(*strDate))/2;
+ int y = (dateViewer->Height() - fontManager.FontTimeLineDateHorizontal->Height())/2;
+ dateViewer->DrawText(cPoint(x, y), *strDate, colorFont, colorFontBack, fontManager.FontTimeLineDateHorizontal);
+ }
}
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;
+ timeline->SetTile(true);
+ timeline->Fill(clrTransparent);
+ tColor colorFont, colorBackground;
+
+ int imgWidth = geoManager.timeLineGridWidth;
+ int imgHeight = geoManager.timeLineGridHeight;
+ const cImage *img1 = NULL;
+ const cImage *img2 = NULL;
+ if (tvguideConfig.style == eStyleGraphical) {
+ img1 = imgCache.GetOsdElement(oeTimeline1);
+ img2 = imgCache.GetOsdElement(oeTimeline2);
+ } else {
+ img1 = createBackgroundImage(imgWidth, imgHeight, theme.Color(clrTimeline1), theme.Color(clrTimeline1Blending));
+ img2 = createBackgroundImage(imgWidth, imgHeight, theme.Color(clrTimeline2), theme.Color(clrTimeline2Blending));
+ }
+ const cImage *img = NULL;
+ if (!img1 || !img2)
+ return;
+ int textWidth, posX, posY;
+ char timetext[10];
+
+ for (int i=0; i<48; i++) {
+ if (i%2==0) {
+ img = img1;
+ colorFont = theme.Color(clrTimeline2);
+ colorBackground = (tvguideConfig.style == eStyleFlat)?theme.Color(clrTimeline1):clrTransparent;
+ 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);
+ colorBackground = (tvguideConfig.style == eStyleFlat)?theme.Color(clrTimeline2):clrTransparent;
+ 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);
+ }
+ }
+ if (tvguideConfig.displayMode == eVertical) {
+ posY = i*geoManager.minutePixel*30;
+ timeline->DrawImage(cPoint(0, posY), *img);
+ if (tvguideConfig.style != eStyleGraphical) {
+ decorateTile(0, posY, imgWidth+2, imgHeight);
+ }
+ textWidth = fontManager.FontTimeLineTime->Width(timetext);
+ timeline->DrawText(cPoint((geoManager.timeLineWidth-textWidth)/2, posY + 5), timetext, colorFont, colorBackground, fontManager.FontTimeLineTime);
+ } else if (tvguideConfig.displayMode == eHorizontal) {
+ posX = i*geoManager.minutePixel*30;
+ timeline->DrawImage(cPoint(posX, 0), *img);
+ if (tvguideConfig.style != eStyleGraphical) {
+ decorateTile(posX, 0, imgWidth, imgHeight+2);
+ }
+ timeline->DrawText(cPoint(posX + 15, (dateViewer->Height() - fontManager.FontTimeLineTimeHorizontal->Height())/2), timetext, colorFont, colorBackground, fontManager.FontTimeLineTimeHorizontal);
+ }
+ }
+ setTimeline();
+ if (tvguideConfig.style != eStyleGraphical) {
+ delete img1;
+ delete img2;
+ }
}
+void cTimeLine::decorateTile(int posX, int posY, int tileWidth, int tileHeight) {
+ timeline->DrawRectangle(cRect(posX,posY,tileWidth,2), clrTransparent); //top
+ timeline->DrawRectangle(cRect(posX,posY,2,tileHeight), clrTransparent); //left
+ timeline->DrawRectangle(cRect(posX,posY + tileHeight-2,tileWidth,2), clrTransparent); //bottom
+ timeline->DrawRectangle(cRect(posX + tileWidth-2,posY,2,tileHeight), clrTransparent); //right
+
+ timeline->DrawRectangle(cRect(2+posX,posY+2,tileWidth-4,1), theme.Color(clrBorder)); //top
+ timeline->DrawRectangle(cRect(2+posX,posY+2,1,tileHeight-4), theme.Color(clrBorder)); //left
+ timeline->DrawRectangle(cRect(2+posX,posY+tileHeight-3,tileWidth-4,1), theme.Color(clrBorder)); //bottom
+ timeline->DrawRectangle(cRect(posX+tileWidth-3,posY+2,1,tileHeight-4), theme.Color(clrBorder)); //right
+
+ if (tvguideConfig.roundedCorners) {
+ int borderRadius = 12;
+ drawRoundedCorners(posX, posY, tileWidth, tileHeight, borderRadius);
+ }
+}
+
+void cTimeLine::drawRoundedCorners(int posX, int posY, int width, int height, int radius) {
+ timeline->DrawEllipse(cRect(posX+2,posY+2,radius,radius), theme.Color(clrBorder), -2);
+ timeline->DrawEllipse(cRect(posX+1,posY+1,radius,radius), clrTransparent, -2);
+
+ timeline->DrawEllipse(cRect(posX+width-radius - 2,posY+2,radius,radius), theme.Color(clrBorder), -1);
+ timeline->DrawEllipse(cRect(posX+width-radius - 1,posY+1,radius,radius), clrTransparent, -1);
+
+ if( height > 2*radius) {
+ timeline->DrawEllipse(cRect(posX+2,posY+height-radius - 2,radius,radius), theme.Color(clrBorder), -3);
+ timeline->DrawEllipse(cRect(posX+1,posY+height-radius - 1,radius,radius), clrTransparent, -3);
+
+ timeline->DrawEllipse(cRect(posX+width-radius - 2,posY+height-radius - 2,radius,radius), theme.Color(clrBorder), -4);
+ timeline->DrawEllipse(cRect(posX+width-radius - 1,posY+height-radius - 1,radius,radius), clrTransparent, -4);
+ }
+}
+
+void cTimeLine::drawCurrentTimeBase(void) {
+ timeBase->Fill(clrTransparent);
+ bool nowVisible = myTime->NowVisible();
+ if (!nowVisible)
+ return;
+ int deltaTime = (myTime->GetNow() - myTime->GetStart()) / 60 * geoManager.minutePixel;
+ if (tvguideConfig.displayMode == eVertical) {
+ timeBase->DrawRectangle(cRect(0, deltaTime - 2, timeBase->ViewPort().Width(), 4), theme.Color(clrTimeBase));
+ } else {
+ timeBase->DrawRectangle(cRect(deltaTime-2, 0, 4, timeBase->ViewPort().Height()), theme.Color(clrTimeBase));
+ }
+}
+
+
cImage *cTimeLine::createBackgroundImage(int width, int height, tColor clrBgr, tColor clrBlend) {
- cImage *image = NULL;
- if (tvguideConfig.useBlending == 1) {
+ cImage *image = NULL;
+ if (tvguideConfig.style == eStyleBlendingDefault) {
image = new cImage(cSize(width, height));
image->Fill(clrBgr);
- 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;
- }
- } else if (tvguideConfig.useBlending == 2) {
+ 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;
+ }
+ } else if (tvguideConfig.style == eStyleBlendingMagick) {
cImageLoader imgLoader;
if (imgLoader.DrawBackground(clrBgr, clrBlend, width, height)) {
image = new cImage(imgLoader.GetImage());
@@ -105,20 +240,37 @@ cImage *cTimeLine::createBackgroundImage(int width, int height, tColor clrBgr, t
image = new cImage(cSize(width, height));
image->Fill(clrBgr);
}
- return image;
+ return image;
}
void cTimeLine::setTimeline() {
- int offset = myTime->GetTimelineOffset();
- timeline->SetDrawPortPoint(cPoint(0, -offset*tvguideConfig.minuteHeight));
+ int offset = myTime->GetTimelineOffset();
+ int xNew, yNew;
+ if (tvguideConfig.displayMode == eVertical) {
+ xNew = 0;
+ yNew = -offset*geoManager.minutePixel;
+ } else if (tvguideConfig.displayMode == eHorizontal) {
+ xNew = -offset*geoManager.minutePixel;
+ yNew = 0;
+ }
+ timeline->SetDrawPortPoint(cPoint(xNew, yNew));
+ if (tvguideConfig.displayTimeBase)
+ drawCurrentTimeBase();
}
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);
+ clock->Fill(clrTransparent);
+ cString currentTime = myTime->GetCurrentTime();
+ const cFont *font = (tvguideConfig.displayMode == eVertical)?fontManager.FontTimeLineTime:fontManager.FontTimeLineTimeHorizontal;
+ int textHeight = font->Height();
+ int clockTextWidth = font->Width(*currentTime);
+ tColor colorFontBack = (tvguideConfig.style == eStyleFlat)?theme.Color(clrHeader):clrTransparent;
+ if (tvguideConfig.style == eStyleGraphical) {
+ clock->drawBackgroundGraphical(bgClock);
+ } else {
+ clock->setColor(theme.Color(clrHeader), theme.Color(clrHeaderBlending));
+ clock->drawBackground();
+ clock->drawBorder();
+ }
+ clock->DrawText(cPoint((geoManager.clockWidth-clockTextWidth)/2, (geoManager.clockHeight-textHeight)/2), *currentTime, theme.Color(clrFont), colorFontBack, font);
}
\ No newline at end of file
diff --git a/timeline.h b/timeline.h
index e534fa5..127b7be 100644
--- a/timeline.h
+++ b/timeline.h
@@ -1,22 +1,29 @@
#ifndef __TVGUIDE_TIMELINE_H
#define __TVGUIDE_TIMELINE_H
+#include "timer.h"
+#include "styledpixmap.h"
+
// --- cTimeLine -------------------------------------------------------------
class cTimeLine {
private:
- cMyTime *myTime;
- cStyledPixmap *dateViewer;
- cPixmap *timeline;
- cStyledPixmap *clock;
- cImage *createBackgroundImage(int width, int height, tColor clrBgr, tColor clrBlend);
+ cMyTime *myTime;
+ cStyledPixmap *dateViewer;
+ cPixmap *timeline;
+ cStyledPixmap *clock;
+ cPixmap *timeBase;
+ void decorateTile(int posX, int posY, int tileWidth, int tileHeight);
+ void drawRoundedCorners(int posX, int posY, int width, int height, int radius);
+ cImage *createBackgroundImage(int width, int height, tColor clrBgr, tColor clrBlend);
+ void drawCurrentTimeBase(void);
public:
- cTimeLine(cMyTime *myTime);
- virtual ~cTimeLine(void);
- void drawDateViewer();
- void drawTimeline();
- void setTimeline();
- void drawClock();
+ cTimeLine(cMyTime *myTime);
+ virtual ~cTimeLine(void);
+ void setTimeline();
+ void drawDateViewer();
+ void drawTimeline();
+ void drawClock();
};
#endif //__TVGUIDE_TIMELINE_H
\ No newline at end of file
diff --git a/timer.c b/timer.c
index 9ec6681..59c21ec 100644
--- a/timer.c
+++ b/timer.c
@@ -1,106 +1,178 @@
+#include <time.h>
+#include <vdr/tools.h>
+#include "config.h"
#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;
+cString cMyTime::printTime(time_t displayTime) {
+ struct tm *ts;
+ ts = localtime(&displayTime);
+ cString strTime = cString::sprintf("%d.%d-%d:%d.%d", ts->tm_mday, ts->tm_mon+1, ts->tm_hour, ts->tm_min, ts->tm_sec);
+ return strTime;
+}
+
+
+void cMyTime::Now() {
+ t = time(0);
+ tStart = t;
+ tStart = GetRounded();
+ if (tvguideConfig.displayMode == eVertical) {
+ tEnd = tStart + (geoManager.osdHeight - geoManager.statusHeaderHeight - geoManager.channelHeaderHeight - geoManager.channelGroupsHeight - geoManager.footerHeight)/geoManager.minutePixel*60;
+ } else if (tvguideConfig.displayMode == eHorizontal) {
+ tEnd = tStart + (geoManager.osdWidth - geoManager.channelHeaderWidth - geoManager.channelGroupsWidth)/geoManager.minutePixel*60;
+ }
}
void cMyTime::AddStep(int step) {
- tStart += step*60;
- tStop += step*60;
+ tStart += step*60;
+ tEnd += step*60;
}
bool cMyTime::DelStep(int step) {
- if ((tStart - step*60)+30*60 < t) {
- return true;
- }
- tStart -= step*60;
- tStop -= step*60;
- return false;
+ if ((tStart - step*60)+30*60 < t) {
+ return true;
+ }
+ tStart -= step*60;
+ tEnd -= step*60;
+ return false;
}
void cMyTime::SetTime(time_t newTime) {
- tStart = newTime;
- tStop = tStart + (tvguideConfig.osdHeight - tvguideConfig.headerHeight - tvguideConfig.footerHeight)/tvguideConfig.minuteHeight*60;
+ tStart = newTime;
+ if (tvguideConfig.displayMode == eVertical) {
+ tEnd = tStart + (geoManager.osdHeight - geoManager.statusHeaderHeight - geoManager.channelHeaderHeight - geoManager.channelGroupsHeight - geoManager.footerHeight)/geoManager.minutePixel*60;
+ } else if (tvguideConfig.displayMode == eHorizontal) {
+ tEnd = tStart + (geoManager.osdWidth - geoManager.channelHeaderWidth - geoManager.channelGroupsWidth)/geoManager.minutePixel*60;
+ }
}
time_t cMyTime::getPrevPrimetime(time_t current) {
- tm *st = localtime(¤t);
- if (st->tm_hour < 21) {
- current -= 24 * 60* 60;
- st = localtime(¤t);
- }
- st->tm_hour = 20;
- st->tm_min = 0;
- time_t primeTime = mktime(st);
- return primeTime;
+ tm *st = localtime(¤t);
+ if (st->tm_hour < 21) {
+ current -= 24 * 60* 60;
+ st = localtime(¤t);
+ }
+ 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(¤t);
- if (st->tm_hour > 19) {
- current += 24 * 60* 60;
- st = localtime(¤t);
- }
- st->tm_hour = 20;
- st->tm_min = 0;
- time_t primeTime = mktime(st);
- return primeTime;
+ tm *st = localtime(¤t);
+ if (st->tm_hour > 19) {
+ current += 24 * 60* 60;
+ st = localtime(¤t);
+ }
+ 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;
+ 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;
-
+ 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;
+ 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);
+ return WeekDayName(tStart);
}
int cMyTime::GetTimelineOffset() {
- tm *st = localtime(&tStart);
- int offset = st->tm_hour*60;
- offset += st->tm_min;
- return offset;
+ 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);
+ 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);
}
+bool cMyTime::NowVisible(void) {
+ if (t > tStart)
+ return true;
+ return false;
+}
+
+
void cMyTime::debug() {
- esyslog("t: %s, tStart: %s, tStop: %s", *TimeString(t), *TimeString(tStart), *TimeString(tStop));
+ esyslog("t: %s, tStart: %s, tEnd: %s", *TimeString(t), *TimeString(tStart), *TimeString(tEnd));
+}
+
+// --- cTimeInterval -------------------------------------------------------------
+
+cTimeInterval::cTimeInterval(time_t start, time_t stop) {
+ this->start = start;
+ this->stop = stop;
+}
+
+cTimeInterval::~cTimeInterval(void) {
}
+
+cTimeInterval *cTimeInterval::Intersect(cTimeInterval *interval) {
+ time_t startIntersect, stopIntersect;
+
+ if ((stop <= interval->Start()) || (interval->Stop() <= start)) {
+ return NULL;
+ }
+
+ if (start <= interval->Start()) {
+ startIntersect = interval->Start();
+ } else {
+ startIntersect = start;
+ }
+ if (stop <= interval->Stop()) {
+ stopIntersect = stop;
+ } else {
+ stopIntersect = interval->Stop();
+ }
+ return new cTimeInterval(startIntersect, stopIntersect);
+}
+
+cTimeInterval *cTimeInterval::Union(cTimeInterval *interval) {
+ time_t startUnion, stopUnion;
+
+ if (start <= interval->Start()) {
+ startUnion = start;
+ } else {
+ startUnion = interval->Start();
+ }
+ if (stop <= interval->Stop()) {
+ stopUnion = interval->Stop();
+ } else {
+ stopUnion = stop;
+ }
+ return new cTimeInterval(startUnion, stopUnion);
+}
\ No newline at end of file
diff --git a/timer.h b/timer.h
index b2d9aa5..6491458 100644
--- a/timer.h
+++ b/timer.h
@@ -1,32 +1,52 @@
#ifndef __TVGUIDE_TIMER_H
#define __TVGUIDE_TIMER_H
+#include <vdr/tools.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();
+ private:
+ time_t t;
+ time_t tStart;
+ time_t tEnd;
+ public:
+ cMyTime(){};
+ virtual ~cMyTime(void);
+ static cString printTime(time_t displayTime);
+ void Now();
+ time_t GetNow() { return t; };
+ 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 GetEnd() {return tEnd;};
+ 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();
+ bool NowVisible(void);
+ void debug();
+};
+
+// --- cTimeInterval -------------------------------------------------------------
+
+class cTimeInterval {
+ private:
+ time_t start;
+ time_t stop;
+ public:
+ cTimeInterval(time_t start, time_t stop);
+ virtual ~cTimeInterval(void);
+ time_t Start(void) { return start; };
+ time_t Stop(void) { return stop; };
+ cTimeInterval *Intersect(cTimeInterval *interval);
+ cTimeInterval *Union(cTimeInterval *interval);
};
#endif //__TVGUIDE_TIMER_H
\ No newline at end of file
diff --git a/timerconflict.c b/timerconflict.c
new file mode 100644
index 0000000..e2a1fee
--- /dev/null
+++ b/timerconflict.c
@@ -0,0 +1,177 @@
+#include <string>
+#include <vector>
+#include <vdr/timers.h>
+#include "tools.h"
+#include "timer.h"
+#include "timerconflict.h"
+
+cTVGuideTimerConflict::cTVGuideTimerConflict(void) {
+ time = 0;
+ timeStart = 0;
+ timeStop = 0;
+ overlapStart = 0;
+ overlapStop = 0;
+ percentPossible = 0;
+ timerID = 0;
+}
+
+cTVGuideTimerConflict::~cTVGuideTimerConflict(void) {
+
+}
+
+bool cTVGuideTimerConflict::timerInvolved(int involvedID) {
+ int numConflicts = timerIDs.size();
+ for (int i=0; i<numConflicts; i++) {
+ if (timerIDs[i] == involvedID)
+ return true;
+ }
+ return false;
+}
+
+// --- cTVGuideTimerConflicts------------------------------------
+
+cTVGuideTimerConflicts::cTVGuideTimerConflicts(void) {
+ numConflicts = 0;
+ currentConflict = -1;
+}
+
+cTVGuideTimerConflicts::~cTVGuideTimerConflicts(void) {
+ for(std::vector<cTVGuideTimerConflict*>::const_iterator it = conflicts.begin(); it != conflicts.end(); it++) {
+ cTVGuideTimerConflict *conf = *it;
+ delete conf;
+ }
+ conflicts.clear();
+}
+
+void cTVGuideTimerConflicts::AddConflict(std::string epgSearchConflictLine) {
+ /* TIMERCONFLICT FORMAT:
+ The result list looks like this for example when we have 2 timer conflicts at one time:
+ 1190232780:152|30|50#152#45:45|10|50#152#45
+ '1190232780' is the time of the conflict in seconds since 1970-01-01.
+ It's followed by list of timers that have a conflict at this time:
+ '152|30|50#1 int editTimer(cTimer *timer, bool active, int prio, int start, int stop);
+ 52#45' is the description of the first conflicting timer. Here:
+ '152' is VDR's timer id of this timer as returned from VDR's LSTT command
+ '30' is the percentage of recording that would be done (0...100)
+ '50#152#45' is the list of concurrent timers at this conflict
+ '45|10|50#152#45' describes the next conflict
+ */
+ cTVGuideTimerConflict *conflict = new cTVGuideTimerConflict();
+ splitstring s(epgSearchConflictLine.c_str());
+ std::vector<std::string> flds = s.split(':');
+ if (flds.size() < 2)
+ return;
+ conflict->time = atoi(flds[0].c_str());
+ splitstring s2(flds[1].c_str());
+ std::vector<std::string> flds2 = s2.split('|');
+ if (flds2.size() < 3)
+ return;
+ conflict->timerID = atoi(flds2[0].c_str());
+ conflict->percentPossible = atoi(flds2[1].c_str());
+ splitstring s3(flds2[2].c_str());
+ std::vector<std::string> flds3 = s3.split('#');
+ std::vector<int> timerIDs;
+ for (int k = 0; k < flds3.size(); k++) {
+ timerIDs.push_back(atoi(flds3[k].c_str()) - 1);
+ }
+ conflict->timerIDs = timerIDs;
+ conflicts.push_back(conflict);
+}
+
+void cTVGuideTimerConflicts::CalculateConflicts(void) {
+ numConflicts = conflicts.size();
+ time_t startTime = 0;
+ time_t endTime = 0;
+ for (int i=0; i < numConflicts; i++) {
+ cTimeInterval *unionSet = NULL;
+ int numTimers = conflicts[i]->timerIDs.size();
+ for (int j=0; j < numTimers; j++) {
+ const cTimer *timer = Timers.Get(conflicts[i]->timerIDs[j]);
+ if (timer) {
+ if (!unionSet) {
+ unionSet = new cTimeInterval(timer->StartTime(), timer->StopTime());
+ } else {
+ cTimeInterval *timerInterval = new cTimeInterval(timer->StartTime(), timer->StopTime());
+ cTimeInterval *newUnion = unionSet->Union(timerInterval);
+ delete unionSet;
+ delete timerInterval;
+ unionSet = newUnion;
+ }
+ }
+ }
+ conflicts[i]->timeStart = unionSet->Start();
+ conflicts[i]->timeStop = unionSet->Stop();
+ delete unionSet;
+
+ cTimeInterval *intersect = NULL;
+ for (int j=0; j < numTimers; j++) {
+ const cTimer *timer = Timers.Get(conflicts[i]->timerIDs[j]);
+ if (timer) {
+ if (!intersect) {
+ intersect = new cTimeInterval(timer->StartTime(), timer->StopTime());
+ } else {
+ cTimeInterval *timerInterval = new cTimeInterval(timer->StartTime(), timer->StopTime());
+ cTimeInterval *newIntersect = intersect->Intersect(timerInterval);
+ if (newIntersect) {
+ delete intersect;
+ intersect = newIntersect;
+ }
+ delete timerInterval;
+ }
+ }
+ }
+ conflicts[i]->overlapStart = intersect->Start();
+ conflicts[i]->overlapStop = intersect->Stop();
+ delete intersect;
+ }
+}
+
+cTVGuideTimerConflict *cTVGuideTimerConflicts::GetCurrentConflict(void) {
+ if (currentConflict < 0)
+ return NULL;
+ if (currentConflict > (numConflicts-1))
+ return NULL;
+ return conflicts[currentConflict];
+}
+
+int cTVGuideTimerConflicts::GetCurrentConflictTimerID(int timerIndex) {
+ if (currentConflict < 0)
+ return -1;
+ if (currentConflict > (numConflicts-1))
+ return -1;
+ int numTimersInConflict = conflicts[currentConflict]->timerIDs.size();
+ if (timerIndex > (numTimersInConflict - 1))
+ return -1;
+ return conflicts[currentConflict]->timerIDs[timerIndex];
+}
+
+int cTVGuideTimerConflicts::GetCorrespondingConflict(int timerID) {
+ int conflictIndex = -1;
+ if (numConflicts > 0) {
+ for (int i=0; i<numConflicts; i++) {
+ if (conflicts[i]->timerInvolved(timerID)) {
+ conflictIndex = i;
+ break;
+ }
+ }
+ }
+ return conflictIndex;
+}
+
+cTVGuideTimerConflict *cTVGuideTimerConflicts::GetConflict(int conflictIndex) {
+ if (conflictIndex < 0)
+ return NULL;
+ if (conflictIndex > (numConflicts-1))
+ return NULL;
+ return conflicts[conflictIndex];
+}
+
+std::vector<cTVGuideTimerConflict*> cTVGuideTimerConflicts::GetConflictsBetween(time_t start, time_t stop) {
+ std::vector<cTVGuideTimerConflict*> conflictsFound;
+ for (int i=0; i < numConflicts; i++) {
+ if ((conflicts[i]->timeStart > start) && (conflicts[i]->timeStart < stop)||
+ (conflicts[i]->timeStop > start) && (conflicts[i]->timeStop < stop))
+ conflictsFound.push_back(conflicts[i]);
+ }
+ return conflictsFound;
+}
\ No newline at end of file
diff --git a/timerconflict.h b/timerconflict.h
new file mode 100644
index 0000000..d3def89
--- /dev/null
+++ b/timerconflict.h
@@ -0,0 +1,38 @@
+#ifndef __TVGUIDE_TIMERCONFLICT_H
+#define __TVGUIDE_TIMERCONFLICT_H
+
+class cTVGuideTimerConflict {
+public:
+ cTVGuideTimerConflict(void);
+ virtual ~cTVGuideTimerConflict(void);
+ time_t time;
+ time_t timeStart;
+ time_t timeStop;
+ time_t overlapStart;
+ time_t overlapStop;
+ int percentPossible;
+ int timerID;
+ std::vector<int> timerIDs;
+ bool timerInvolved(int involvedID);
+};
+
+class cTVGuideTimerConflicts {
+private:
+ std::vector<cTVGuideTimerConflict*> conflicts;
+ int numConflicts;
+ int currentConflict;
+public:
+ cTVGuideTimerConflicts(void);
+ virtual ~cTVGuideTimerConflicts(void);
+ void AddConflict(std::string epgSearchConflictLine);
+ void CalculateConflicts(void);
+ int NumConflicts(void) {return numConflicts; };
+ void SetCurrentConflict(int current) { currentConflict = current; };
+ cTVGuideTimerConflict *GetCurrentConflict(void);
+ int GetCurrentConflictTimerID(int timerIndex);
+ int GetCorrespondingConflict(int timerID);
+ cTVGuideTimerConflict *GetConflict(int conflictIndex);
+ std::vector<cTVGuideTimerConflict*> GetConflictsBetween(time_t start, time_t stop);
+};
+
+#endif //__TVGUIDE_RECMMANAGER_H
\ No newline at end of file
diff --git a/tools.c b/tools.c
new file mode 100644
index 0000000..2607332
--- /dev/null
+++ b/tools.c
@@ -0,0 +1,474 @@
+#include <string>
+#include <vector>
+#include <sstream>
+#include <algorithm>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <vdr/osd.h>
+#include <vdr/plugin.h>
+#include "services/epgsearch.h"
+
+#include "tools.h"
+
+/****************************************************************************************
+* CUTTEXT
+****************************************************************************************/
+std::string CutText(std::string text, int width, const cFont *font) {
+ if (width <= font->Size())
+ return text.c_str();
+ if (font->Width(text.c_str()) < width)
+ return text.c_str();
+ cTextWrapper twText;
+ twText.Set(text.c_str(), font, width);
+ std::string cuttedTextNative = twText.GetLine(0);
+ std::stringstream sstrText;
+ sstrText << cuttedTextNative << "...";
+ std::string cuttedText = sstrText.str();
+ int actWidth = font->Width(cuttedText.c_str());
+ if (actWidth > width) {
+ int overlap = actWidth - width;
+ int charWidth = font->Width(".");
+ if (charWidth == 0)
+ charWidth = 1;
+ int cutChars = overlap / charWidth;
+ if (cutChars > 0) {
+ cuttedTextNative = cuttedTextNative.substr(0, cuttedTextNative.length() - cutChars);
+ std::stringstream sstrText2;
+ sstrText2 << cuttedTextNative << "...";
+ cuttedText = sstrText2.str();
+ }
+ }
+ return cuttedText;
+}
+
+/****************************************************************************************
+* StrToLowerCase
+****************************************************************************************/
+std::string StrToLowerCase(std::string str) {
+ std::string lowerCase = str;
+ const int length = lowerCase.length();
+ for(int i=0; i < length; ++i) {
+ lowerCase[i] = std::tolower(lowerCase[i]);
+ }
+ return lowerCase;
+}
+
+/****************************************************************************************
+* GetDirectoryFromTimer
+****************************************************************************************/
+std::string GetDirectoryFromTimer(std::string file) {
+ std::string dir = "";
+ size_t found = file.find_last_of('~');
+ if (found != std::string::npos) {
+ dir = file.substr(0, found);
+ }
+ return dir;
+}
+
+/****************************************************************************************
+* GetDirectoryFromTimer
+****************************************************************************************/
+void ReadRecordingDirectories(std::vector<std::string> *folders, cList<cNestedItem> *rootFolders, cString path) {
+ cPlugin *epgSearchPlugin = NULL;
+ epgSearchPlugin = cPluginManager::GetPlugin("epgsearch");
+ if (epgSearchPlugin) {
+ Epgsearch_services_v1_0 *epgSearch = new Epgsearch_services_v1_0;
+ if (epgSearchPlugin->Service("Epgsearch-services-v1.0", epgSearch)) {
+ std::set<std::string> epgSearchDirs = epgSearch->handler->DirectoryList();
+ std::set<std::string>::iterator it;
+ for (it = epgSearchDirs.begin(); it != epgSearchDirs.end(); it++) {
+ std::string newFolder = *it;
+ std::replace(newFolder.begin(), newFolder.end(), '/', '~');
+ folders->push_back(newFolder);
+ }
+ }
+ } else {
+ cList<cNestedItem> *foldersLevel = NULL;
+ if (rootFolders) {
+ foldersLevel = rootFolders;
+ } else {
+ foldersLevel = &Folders;
+ }
+ for (cNestedItem *folder = foldersLevel->First(); folder; folder = foldersLevel->Next(folder)) {
+ std::string strFolder = *cString::sprintf("%s%s", *path, folder->Text());
+ std::replace(strFolder.begin(), strFolder.end(), '/', '~');
+ folders->push_back(strFolder);
+ cList<cNestedItem> *subItems = folder->SubItems();
+ if (subItems) {
+ std::string strFolder2 = *cString::sprintf("%s%s", *path, folder->Text());
+ std::replace(strFolder2.begin(), strFolder2.end(), '/', '~');
+ ReadRecordingDirectories(folders, subItems, strFolder2.c_str());
+ }
+ }
+ }
+}
+
+
+/****************************************************************************************
+* DrawRoundedCorners
+****************************************************************************************/
+void DrawRoundedCorners(cPixmap *p, int posX, int posY, int width, int height, int radius, int borderWidth, tColor borderColor) {
+ if( height > 2*radius) {
+ p->DrawEllipse(cRect(posX, posY, radius, radius), borderColor, -2);
+ p->DrawEllipse(cRect(posX - borderWidth, posY - borderWidth, radius, radius), clrTransparent, -2);
+
+ p->DrawEllipse(cRect(posX+width - radius, posY, radius, radius), borderColor, -1);
+ p->DrawEllipse(cRect(posX+width - radius + borderWidth, posY - borderWidth, radius, radius), clrTransparent, -1);
+
+ p->DrawEllipse(cRect(posX, posY + height - radius, radius, radius), borderColor, -3);
+ p->DrawEllipse(cRect(posX - borderWidth, posY + height - radius + borderWidth, radius, radius), clrTransparent, -3);
+
+ p->DrawEllipse(cRect(posX + width - radius, posY + height - radius, radius, radius), borderColor, -4);
+ p->DrawEllipse(cRect(posX + width - radius + borderWidth, posY + height - radius + borderWidth, radius, radius), clrTransparent, -4);
+ }
+}
+
+
+/****************************************************************************************
+* SPLTSTRING
+****************************************************************************************/
+// split: receives a char delimiter; returns a vector of strings
+// By default ignores repeated delimiters, unless argument rep == 1.
+std::vector<std::string>& splitstring::split(char delim, int rep) {
+ if (!flds.empty()) flds.clear(); // empty vector if necessary
+ std::string work = data();
+ std::string buf = "";
+ int i = 0;
+ while (i < work.length()) {
+ if (work[i] != delim)
+ buf += work[i];
+ else if (rep == 1) {
+ flds.push_back(buf);
+ buf = "";
+ } else if (buf.length() > 0) {
+ flds.push_back(buf);
+ buf = "";
+ }
+ i++;
+ }
+ if (!buf.empty())
+ flds.push_back(buf);
+ return flds;
+}
+
+/****************************************************************************************
+* FINDIGNORECASE
+****************************************************************************************/
+int FindIgnoreCase(const std::string& expr, const std::string& query)
+{
+ const char *p = expr.c_str();
+ const char *r = strcasestr(p, query.c_str());
+
+ if (!r)
+ return -1;
+ return r - p;
+}
+
+
+/****************************************************************************************
+* GetAuxValue
+****************************************************************************************/
+char* GetAuxValue(const char* aux, const char* name) {
+ if (isempty(aux))
+ return NULL;
+
+ char* descr = strdup(aux);
+ char* beginaux = strstr(descr, "<epgsearch>");
+ char* endaux = strstr(descr, "</epgsearch>");
+ if (!beginaux || !endaux) {
+ free(descr);
+ return NULL;
+ }
+
+ beginaux += 11; // strlen("<epgsearch>");
+ endaux[0] = 0;
+ memmove(descr, beginaux, endaux - beginaux + 1);
+
+ if (strcmp(name, "epgsearch") == 0)
+ return descr; // full aux
+
+ int namelen = strlen(name);
+ char catname[100] = "";
+ catname[0] = '<';
+ memcpy(catname + 1, name, namelen);
+ catname[1 + namelen] = '>';
+ catname[2 + namelen] = 0;
+
+ char* cat = strcasestr(descr, catname);
+ if (!cat) {
+ free(descr);
+ return NULL;
+ }
+
+ cat += namelen + 2;
+ char* end = strstr(cat, "</");
+ if (!end) {
+ free(descr);
+ return NULL;
+ }
+ end[0] = 0;
+
+ int catlen = end - cat + 1;
+ char* value = (char *) malloc(catlen);
+ memcpy(value, cat, catlen);
+
+ free(descr);
+ return value;
+}
+
+char* GetAuxValue(const cRecording *recording, const char* name) {
+ if (!recording || !recording->Info())
+ return NULL;
+ return GetAuxValue(recording->Info()->Aux(), name);
+}
+
+char* GetAuxValue(const cTimer *timer, const char* name) {
+ if (!timer || !timer->Aux())
+ return NULL;
+ return GetAuxValue(timer->Aux(), name);
+}
+
+/****************************************************************************************
+* FUZZYSEARCH
+****************************************************************************************/
+
+/******************************************************************************
+FUNCTION afuzzy_init()
+ Initialization of the fuzzy search routine. This applies to the consequent
+ calls of the afuzzy_CheckRTR (whole string matching) and afuzzy_CheckSUB
+ (substring match) routines. afuzzy_init() should be called for each
+ new pattern or error length. The search is case sensitive
+
+ARGUMENTS:
+ p Pattern
+ kerr Number of possible errors. Shouldn't exceed pattern length
+ UseFilter Use agrep filter algorithm that speeds up search.
+ fuzzy pointer to the structure that will be later passes to Check*
+ (the first 6 elements should be NULLs for the first call)
+
+RETURN VALUE:
+ none
+
+ALGORITHM
+ see. the article on agrep algorithms.
+ The only change is accounting transpositions as one edit operation .
+******************************************************************************/
+void afuzzy_init(const char *p, int kerr, int UseFilter, AFUZZY *fuzzy)
+{
+ int cnt, p_len, i, j, l, d, m, dd;
+ char PatFilter[sizeof(Uint)*8 + 1];
+
+ fuzzy->k = kerr;
+ m = strlen(p);
+ fuzzy->FilterSet = 0;
+ memset(fuzzy->Map, 0 , sizeof(fuzzy->Map) );
+
+ if (fuzzy->S)
+ free(fuzzy->S);
+ if (fuzzy->R)
+ free(fuzzy->R);
+ if (fuzzy->R1)
+ free(fuzzy->R1);
+ if (fuzzy->RP)
+ free(fuzzy->RP);
+ if (fuzzy->RI)
+ free(fuzzy->RI);
+ if (fuzzy->FilterS)
+ free(fuzzy->FilterS);
+
+ fuzzy->FilterS = NULL;
+ fuzzy->S = (Uint *)calloc(m + 1, sizeof(Uint));
+ fuzzy->R = (Uint *)calloc(fuzzy->k + 1, sizeof(Uint));
+ fuzzy->R1 = (Uint *)calloc(fuzzy->k + 1, sizeof(Uint));
+ fuzzy->RI = (Uint *)calloc(fuzzy->k + 1, sizeof(Uint));
+ fuzzy->RP = (Uint *)calloc(fuzzy->k + 1, sizeof(Uint));
+
+ for (i = 0, cnt = 0; i < m; i++)
+ {
+ l = fuzzy->Map[(unsigned char)p[i]];
+ if (!l)
+ {
+ l = fuzzy->Map[(unsigned char)p[i]] = ++cnt;
+ fuzzy->S[l] = 0;
+ }
+ fuzzy->S[l] |= 1 << i;
+ }
+
+
+ for (d = 0; d <= fuzzy->k; d++)
+ fuzzy->RI[d] = (1 << d) - 1;
+
+ fuzzy->mask_ok = (1 << (m - 1));
+ fuzzy->r_size = sizeof(Uint) * (fuzzy->k + 1);
+ p_len = m;
+
+ if (p_len > (int) sizeof(Uint)*8)
+ p_len = (int) sizeof(Uint)*8;
+
+ /* If k is zero then no filter is needed! */
+ if (fuzzy->k && (p_len >= 2*(fuzzy->k + 1)) )
+ {
+ if (UseFilter)
+ {
+ fuzzy->FilterSet = 1;
+ memset(fuzzy->FilterMap, 0 , sizeof(fuzzy->FilterMap) );
+ fuzzy->FilterS = (Uint *)calloc(m + 1, sizeof(Uint));
+
+ /* Not let's fill the interleaved pattern */
+ dd = p_len / (fuzzy->k + 1);
+ p_len = dd * (fuzzy->k + 1);
+
+ for (i = 0, cnt = 0; i < dd; i++)
+ for (j = 0; j < fuzzy->k + 1; j++, cnt++)
+ PatFilter[cnt] = (unsigned char)p[j*dd + i];
+ PatFilter[p_len] = 0;
+
+ for (i = 0, cnt = 0; i < p_len; i++)
+ {
+ l = fuzzy->FilterMap[(unsigned char)PatFilter[i]];
+ if (!l)
+ {
+ l = fuzzy->FilterMap[(unsigned char)PatFilter[i]] = ++cnt;
+ fuzzy->FilterS[l] = 0;
+ }
+ fuzzy->FilterS[l] |= 1 << i;
+ }
+ fuzzy->filter_ok = 0;
+ for (i = p_len - fuzzy->k - 1; i <= p_len - 1; i++) /* k+1 times */
+ fuzzy->filter_ok |= 1 << i;
+
+ /* k+1 first bits set to 1 */
+ fuzzy->filter_shift = (1 << (fuzzy->k + 2)) - 1;
+ }
+ }
+}
+
+/******************************************************************************
+FUNCTION afuzzy_free()
+ Cleaning up after previous afuzzy_init() call.
+
+ARGUMENTS:
+ fuzzy pointer to the afuzzy parameters structure
+
+RETURN VALUE:
+ none
+******************************************************************************/
+void afuzzy_free(AFUZZY *fuzzy)
+{
+ if (fuzzy->S)
+ {
+ free(fuzzy->S);
+ fuzzy->S = NULL;
+ }
+ if (fuzzy->R)
+ {
+ free(fuzzy->R);
+ fuzzy->R = NULL;
+ }
+ if (fuzzy->R1)
+ {
+ free(fuzzy->R1);
+ fuzzy->R1 = NULL;
+ }
+ if (fuzzy->RP)
+ {
+ free(fuzzy->RP);
+ fuzzy->RP = NULL;
+ }
+ if (fuzzy->RI)
+ {
+ free(fuzzy->RI);
+ fuzzy->RI = NULL;
+ }
+ if (fuzzy->FilterS)
+ {
+ free(fuzzy->FilterS);
+ fuzzy->FilterS = NULL;
+ }
+}
+
+
+/******************************************************************************
+FUNCTION afuzzy_CheckSUB()
+ Perform a fuzzy pattern substring matching. afuzzy_init() should be
+ called previously to initialize the pattern and error length.
+ Positive result means that some part of the string given matches the
+ pattern with no more than afuzzy->k errors (1 error = 1 letter
+ replacement or transposition)
+
+ARGUMENTS:
+ t the string to test
+ fuzzy pointer to the afuzzy parameters structure
+
+RETURN VALUE:
+ 0 - no match
+ > 0 - strings match
+
+ALGORITHM
+ ????????????????
+******************************************************************************/
+int afuzzy_checkSUB(const char *t, AFUZZY *fuzzy)
+{
+ register char c;
+ register int j, d;
+
+ /* For eficciency this case should be little bit optimized */
+ if (!fuzzy->k)
+ {
+ Uint R = 0, R1;
+
+ for (j = 0; (c = t[j]) != '\0'; j++)
+ {
+ R1 = ( ((R<<1) | 1) & fuzzy->S[fuzzy->Map[(unsigned char)c]]);
+ R = R1;
+
+ if (R1 & fuzzy->mask_ok)
+ return 1;
+ } /* end for (register int j = 0 ... */
+ return 0;
+ }
+
+ if (fuzzy->FilterSet && !afuzzy_checkFLT(t, fuzzy))
+ return 0;
+
+ memcpy(fuzzy->R, fuzzy->RI, fuzzy->r_size); /* R = RI */
+
+ for (j = 0; (c = t[j]); j++)
+ {
+ for (d = 0; d <= fuzzy->k; d++)
+ {
+ fuzzy->R1[d] = (((fuzzy->R[d]<<1) | 1) &
+ fuzzy->S[fuzzy->Map[(unsigned char)c]]);
+ if (d > 0)
+ fuzzy->R1[d] |= ((fuzzy->R[d-1] | fuzzy->R1[d-1])<<1) | 1 |
+ fuzzy->R[d-1];
+ }
+ if (fuzzy->R1[fuzzy->k] & fuzzy->mask_ok)
+ return j;
+
+ memcpy(fuzzy->R, fuzzy->R1, fuzzy->r_size);
+
+ } /* end for (register int j = 0 ... */
+
+ return 0;
+}
+
+static int afuzzy_checkFLT(const char *t, AFUZZY *fuzzy)
+{
+ register Uint FilterR = 0;
+ register Uint FilterR1;
+ register int j;
+
+ for (j = 0; t[j] != '\0'; j++)
+ {
+ FilterR1 = ( ((FilterR<<(fuzzy->k+1)) | fuzzy->filter_shift) &
+ fuzzy->FilterS[fuzzy->FilterMap[(unsigned char)t[j]]]);
+ if (FilterR1 & fuzzy->filter_ok)
+ return 1;
+ FilterR = FilterR1;
+ } /* end for (register int j = 0 ... */
+
+ return 0;
+}
diff --git a/tools.h b/tools.h
new file mode 100644
index 0000000..f401ea4
--- /dev/null
+++ b/tools.h
@@ -0,0 +1,68 @@
+#ifndef __TVGUIDETOOLS_H
+#define __TVGUIDETOOLS_H
+
+#include <string>
+#include <vector>
+#include <vdr/font.h>
+#include <vdr/recording.h>
+
+std::string CutText(std::string text, int width, const cFont *font);
+std::string StrToLowerCase(std::string str);
+std::string GetDirectoryFromTimer(std::string file);
+void ReadRecordingDirectories(std::vector<std::string> *folders, cList<cNestedItem> *rootFolders, cString path);
+void DrawRoundedCorners(cPixmap *p, int posX, int posY, int width, int height, int radius, int borderWidth, tColor borderColor);
+
+class splitstring : public std::string {
+ std::vector<std::string> flds;
+public:
+ splitstring(const char *s) : std::string(s) { };
+ std::vector<std::string>& split(char delim, int rep=0);
+};
+
+int FindIgnoreCase(const std::string& expr, const std::string& query);
+
+char* GetAuxValue(const char* aux, const char* name);
+char* GetAuxValue(const cRecording *recording, const char* name);
+char* GetAuxValue(const cTimer* timer, const char* name);
+
+#ifndef _AFUZZY_H
+#define _AFUZZY_H
+
+// source from:
+/*
+ Leonid Boitsov 2002. (itman at narod.ru)
+ C version of Stas Namin.
+ This code is a GPL software and is distributed under GNU
+ public licence without any warranty.
+*/
+
+typedef unsigned int Uint;
+
+#define MaxPatSize (sizeof(Uint) * 8)
+
+typedef struct
+{
+ Uint *R,
+ *R1,
+ *RP,
+ *S,
+ *RI;
+ Uint *FilterS;
+
+ int Map[256];
+ int FilterMap[256];
+ int k;
+ Uint mask_ok;
+ Uint filter_ok;
+ Uint filter_shift;
+ int r_size;
+ int FilterSet;
+} AFUZZY;
+
+void afuzzy_init(const char *p, int kerr, int UseFilter, AFUZZY *fuzzy);
+void afuzzy_free(AFUZZY *fuzzy);
+int afuzzy_checkSUB(const char *t, AFUZZY *fuzzy);
+static int afuzzy_checkFLT(const char *t, AFUZZY *fuzzy);
+#endif
+
+#endif // __TVGUIDETOOLS_H
\ No newline at end of file
diff --git a/tvguide.c b/tvguide.c
index 3a27d41..029166d 100644
--- a/tvguide.c
+++ b/tvguide.c
@@ -11,23 +11,26 @@
#include <vdr/osd.h>
#include <vdr/plugin.h>
#include <vdr/device.h>
+#include <vdr/menu.h>
-#include "tvguideosd.c"
-
-#if defined(APIVERSNUM) && APIVERSNUM < 10717
-#error "VDR-1.7.17 API version or greater is required!"
-#endif
+#define DEFINE_CONFIG 1
+#include "geometrymanager.h"
+#include "fontmanager.h"
+#include "imagecache.h"
+#include "config.h"
+#include "setup.h"
+#include "tvguideosd.h"
+#if defined(APIVERSNUM) && APIVERSNUM < 20000
+#error "VDR-2.0.0 API version or greater is required!"
+#endif
-static const char *VERSION = "0.0.2";
+static const char *VERSION = "1.2.2";
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();
@@ -42,7 +45,7 @@ public:
virtual void MainThreadHook(void);
virtual cString Active(void);
virtual time_t WakeupTime(void);
- virtual const char *MainMenuEntry(void) { return MAINMENUENTRY; }
+ virtual const char *MainMenuEntry(void) { return (tvguideConfig.showMainMenuEntry)?MAINMENUENTRY:NULL; }
virtual cOsdObject *MainMenuAction(void);
virtual cMenuSetupPage *SetupMenu(void);
virtual bool SetupParse(const char *Name, const char *Value);
@@ -51,144 +54,107 @@ public:
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(void) {
}
-cPluginTvguide::~cPluginTvguide()
-{
- // Clean up after yourself!
+cPluginTvguide::~cPluginTvguide() {
}
-const char *cPluginTvguide::CommandLineHelp(void)
-{
- // Return a string that describes all known command line options.
+const char *cPluginTvguide::CommandLineHelp(void) {
return
- " -i <IMAGESDIR>, --epgimages=<IMAGESDIR> Set directory where epgimages are stored\n"
+ " -e <IMAGESDIR>, --epgimages=<IMAGESDIR> Set directory where epgimages are stored.\n"
+ " -i <ICONDIR>, --icons=<ICONDIR> Set directory where icons 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.
+bool cPluginTvguide::ProcessArgs(int argc, char *argv[]) {
static const struct option long_options[] = {
- { "epgimages", required_argument, NULL, 'i' },
+ { "epgimages", required_argument, NULL, 'e' },
+ { "iconpath", 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;
+ while ((c = getopt_long(argc, argv, "e:i:l:", long_options, NULL)) != -1) {
+ switch (c) {
+ case 'e':
+ tvguideConfig.SetImagesPath(cString(optarg));
break;
+ case 'i':
+ tvguideConfig.SetIconsPath(cString(optarg));
+ break;
case 'l':
- path = new cString(optarg);
- tvguideConfig.SetLogoPath(*path);
- logoPathSet = true;
+ tvguideConfig.SetLogoPath(cString(optarg));
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::Initialize(void) {
+ tvguideConfig.SetDefaultPathes();
+ tvguideConfig.LoadTheme();
+ tvguideConfig.SetStyle();
+ tvguideConfig.setDynamicValues();
+ geoManager.SetGeometry(cOsd::OsdWidth(), cOsd::OsdHeight());
+ fontManager.SetFonts();
+ imgCache.CreateCache();
+ 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;
+bool cPluginTvguide::Start(void) {
+ return true;
}
-void cPluginTvguide::Stop(void)
-{
- // Stop any background activities the plugin is performing.
+void cPluginTvguide::Stop(void) {
}
-void cPluginTvguide::Housekeeping(void)
-{
- // Perform any cleanup or other regular tasks.
+void cPluginTvguide::Housekeeping(void) {
}
-void cPluginTvguide::MainThreadHook(void)
-{
- // Perform actions in the context of the main program thread.
- // WARNING: Use with great care - see PLUGINS.html!
+void cPluginTvguide::MainThreadHook(void) {
}
-cString cPluginTvguide::Active(void)
-{
- // Return a message string if shutdown should be postponed
+cString cPluginTvguide::Active(void) {
return NULL;
}
-time_t cPluginTvguide::WakeupTime(void)
-{
- // Return custom wakeup time for shutdown script
+time_t cPluginTvguide::WakeupTime(void) {
return 0;
}
-cOsdObject *cPluginTvguide::MainMenuAction(void)
-{
- // Perform the action when selected from the main VDR menu.
- return new cTvGuideOsd;
+cOsdObject *cPluginTvguide::MainMenuAction(void) {
+ return new cTvGuideOsd;
}
-cMenuSetupPage *cPluginTvguide::SetupMenu(void)
-{
- // Return a setup menu in case the plugin supports one.
+cMenuSetupPage *cPluginTvguide::SetupMenu(void) {
return new cTvguideSetup();
}
-bool cPluginTvguide::SetupParse(const char *Name, const char *Value)
-{
- // Parse your own setup parameters and store their values.
+bool cPluginTvguide::SetupParse(const char *Name, const char *Value) {
return tvguideConfig.SetupParse(Name, Value);
}
-bool cPluginTvguide::Service(const char *Id, void *Data)
-{
- // Handle custom service requests from other plugins
+bool cPluginTvguide::Service(const char *Id, void *Data) {
+ if (strcmp(Id, "MainMenuHooksPatch-v1.0::osSchedule") == 0 && tvguideConfig.replaceOriginalSchedule != 0) {
+ if (Data == NULL)
+ return true;
+ cOsdObject **guide = (cOsdObject**) Data;
+ if (guide)
+ *guide = MainMenuAction();
+ return true;
+ }
return false;
}
-const char **cPluginTvguide::SVDRPHelpPages(void)
-{
- // Return help text for SVDRP commands this plugin implements
+const char **cPluginTvguide::SVDRPHelpPages(void) {
return NULL;
}
-cString cPluginTvguide::SVDRPCommand(const char *Command, const char *Option, int &ReplyCode)
-{
- // Process SVDRP commands this plugin implements
+cString cPluginTvguide::SVDRPCommand(const char *Command, const char *Option, int &ReplyCode) {
return NULL;
}
-VDRPLUGINCREATOR(cPluginTvguide); // Don't touch this!
+VDRPLUGINCREATOR(cPluginTvguide);
diff --git a/tvguideosd.c b/tvguideosd.c
index b127fdd..9770d82 100644
--- a/tvguideosd.c
+++ b/tvguideosd.c
@@ -1,542 +1,717 @@
-// --- 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, 0x99BB0000);
-THEME_CLR(theme, clrButtonRedBorder, 0xFFBB0000);
-THEME_CLR(theme, clrButtonGreen, 0x9900BB00);
-THEME_CLR(theme, clrButtonGreenBorder, 0xFF00BB00);
-THEME_CLR(theme, clrButtonYellow, 0x99BBBB00);
-THEME_CLR(theme, clrButtonYellowBorder, 0xFFBBBB00);
-THEME_CLR(theme, clrButtonBlue, 0x990000BB);
-THEME_CLR(theme, clrButtonBlueBorder, 0xFF0000BB);
-THEME_CLR(theme, clrButtonBlend, 0xDD000000);
-
-#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 <stdlib.h>
+#include <vector>
+
+#include "config.h"
+#include "services/epgsearch.h"
+#include "services/remotetimers.h"
+
+#include "tools.h"
+#include "setup.h"
#include "tvguideosd.h"
-#include <stdlib.h>
cTvGuideOsd::cTvGuideOsd(void) {
- detailView = NULL;
- detailViewActive = false;
- timeLine = NULL;
+ detailView = NULL;
+ detailViewActive = false;
+ activeGrid = NULL;
+ timeLine = NULL;
+ recMenuManager = NULL;
+ channelJumper = NULL;
}
cTvGuideOsd::~cTvGuideOsd() {
- delete myTime;
- columns.Clear();
- if (detailView)
- delete detailView;
- delete timeLine;
- delete footer;
- cMessageBox::Destroy();
- osdManager.deleteOsd();
+ delete myTime;
+ columns.Clear();
+ if (tvguideConfig.displayStatusHeader) {
+ delete statusHeader;
+ }
+ if (detailView)
+ delete detailView;
+ delete timeLine;
+ delete channelGroups;
+ delete footer;
+ delete recMenuManager;
+ if (channelJumper)
+ delete channelJumper;
+ 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));
+ int start = cTimeMs::Now();
+ bool ok = false;
+ ok = osdManager.setOsd();
+ if (ok) {
+ bool themeChanged = tvguideConfig.LoadTheme();
+ tvguideConfig.SetStyle();
+ tvguideConfig.setDynamicValues();
+ bool geoChanged = geoManager.SetGeometry(cOsd::OsdWidth(), cOsd::OsdHeight());
+ if (themeChanged || geoChanged) {
+ fontManager.DeleteFonts();
+ fontManager.SetFonts();
+ imgCache.Clear();
+ imgCache.CreateCache();
+ }
+ osdManager.setBackground();
+ myTime = new cMyTime();
+ myTime->Now();
+ SwitchTimers.Load(AddDirectory(cPlugin::ConfigDirectory("epgsearch"), "epgsearchswitchtimers.conf"));
+ recMenuManager = new cRecMenuManager();
+ pRemoteTimers = cPluginManager::CallFirstService("RemoteTimers::RefreshTimers-v1.0", NULL);
+ if (pRemoteTimers) {
+ isyslog("tvguide: remotetimers-plugin is available");
+ }
+ if (tvguideConfig.useRemoteTimers && pRemoteTimers) {
+ cString errorMsg;
+ if (!pRemoteTimers->Service("RemoteTimers::RefreshTimers-v1.0", &errorMsg)) {
+ esyslog("tvguide: %s", *errorMsg);
+ }
+ }
+ 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();
- }
+ cPixmap::Lock();
+ cChannel *startChannel = Channels.GetByNumber(cDevice::CurrentChannel());
+ int numBack = tvguideConfig.numGrids / 2;
+ int offset = 0;
+ const cChannel *newStartChannel = startChannel;
+ for (; newStartChannel ; newStartChannel = Channels.Prev(newStartChannel)) {
+ if (newStartChannel && !newStartChannel->GroupSep()) {
+ offset++;
+ }
+ if (offset == numBack)
+ break;
+ }
+ if (!newStartChannel)
+ newStartChannel = Channels.First();
+ offset--;
+ if (offset < 0)
+ offset = 0;
+
+ if (tvguideConfig.displayStatusHeader) {
+ statusHeader = new cStatusHeader();
+ statusHeader->Draw();
+ statusHeader->ScaleVideo();
+ }
+ timeLine = new cTimeLine(myTime);
+ timeLine->drawDateViewer();
+ timeLine->drawTimeline();
+ timeLine->drawClock();
+ channelGroups = new cChannelGroups();
+ channelGroups->ReadChannelGroups();
+ footer = new cFooter(channelGroups);
+ recMenuManager->SetFooter(footer);
+ footer->drawRedButton();
+ if (tvguideConfig.channelJumpMode == eNumJump) {
+ footer->drawGreenButton();
+ footer->drawYellowButton();
+ }
+ footer->drawBlueButton(false);
+ osdManager.flush();
+ readChannels(newStartChannel);
+ drawGridsChannelJump(offset);
+ osdManager.flush();
+ cPixmap::Unlock();
+}
+
+void cTvGuideOsd::readChannels(const cChannel *channelStart) {
+ int i=0;
+ bool foundEnough = false;
+ columns.Clear();
+ if (!channelStart)
+ return;
+ for (const cChannel *channel = channelStart; channel; channel = Channels.Next(channel)) {
+ if (!channel->GroupSep()) {
+ if (channelGroups->IsInLastGroup(channel)) {
+ break;
+ }
+ cChannelColumn *column = new cChannelColumn(i, channel, myTime);
+ if (column->readGrids()) {
+ columns.Add(column);
+ i++;
+ } else {
+ delete column;
+ }
+ }
+ if (i == tvguideConfig.numGrids) {
+ foundEnough = true;
+ break;
+ }
+ }
+ if (!foundEnough) {
+ int numCurrent = columns.Count();
+ int numBack = tvguideConfig.numGrids - numCurrent;
+ int newChannelNumber = columns.First()->getChannel()->Number() - numBack;
+ const cChannel *newStart = Channels.GetByNumber(newChannelNumber);
+ readChannels(newStart);
+ }
+}
+
+void cTvGuideOsd::drawGridsChannelJump(int offset) {
+ if (columns.Count() == 0)
+ return;
+ activeGrid = columns.Get(offset)->getActive();
+ if (activeGrid)
+ activeGrid->SetActive();
+ if (tvguideConfig.displayStatusHeader) {
+ statusHeader->DrawInfoText(activeGrid);
+ }
+ if (activeGrid && (tvguideConfig.channelJumpMode == eGroupJump)) {
+ footer->UpdateGroupButtons(activeGrid->column->getChannel());
+ }
+ if (tvguideConfig.displayChannelGroups) {
+ channelGroups->DrawChannelGroups(columns.First()->getChannel(), columns.Last()->getChannel());
+ }
+ 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();
+ 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();
+ if (tvguideConfig.displayStatusHeader) {
+ statusHeader->DrawInfoText(activeGrid);
+ }
+ }
}
-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::setNextActiveGrid(cGrid *next) {
+ if (!next || !activeGrid) {
+ return;
+ }
+ activeGrid->SetInActive();
+ activeGrid->Draw();
+ activeGrid = next;
+ activeGrid->SetActive();
+ activeGrid->Draw();
+ if (tvguideConfig.displayStatusHeader) {
+ statusHeader->DrawInfoText(activeGrid);
+ }
}
-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::channelForward() {
+ cChannelColumn *colRight = columns.Next(activeGrid->column);
+ bool colAdded = false;
+ if (!colRight) {
+ const cChannel *channelRight = activeGrid->column->getChannel();
+ while (channelRight = Channels.Next(channelRight)) {
+ if (!channelRight->GroupSep()) {
+ if (channelGroups->IsInLastGroup(channelRight)) {
+ break;
+ }
+ colRight = new cChannelColumn(tvguideConfig.numGrids - 1, channelRight, myTime);
+ if (colRight->readGrids()) {
+ break;
+ } else {
+ delete colRight;
+ colRight = NULL;
+ }
+ }
+ }
+ if (colRight) {
+ colAdded = true;
+ if (columns.Count() == tvguideConfig.numGrids) {
+ 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) {
+ cGrid *right = colRight->getNeighbor(activeGrid);
+ if (right) {
+ setNextActiveGrid(right);
+ }
+ }
+ if (tvguideConfig.displayChannelGroups && colAdded) {
+ channelGroups->DrawChannelGroups(columns.First()->getChannel(), columns.Last()->getChannel());
+ }
+ if (activeGrid && (tvguideConfig.channelJumpMode == eGroupJump)) {
+ footer->UpdateGroupButtons(activeGrid->column->getChannel());
+ }
+ osdManager.flush();
+}
+
+void cTvGuideOsd::channelBack() {
+ cChannelColumn *colLeft = columns.Prev(activeGrid->column);
+ bool colAdded = false;
+ if (!colLeft) {
+ const 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) {
+ colAdded = true;
+ if (columns.Count() == tvguideConfig.numGrids) {
+ 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) {
+ cGrid *left = colLeft->getNeighbor(activeGrid);
+ if (left) {
+ setNextActiveGrid(left);
+ }
+ }
+ if (tvguideConfig.displayChannelGroups && colAdded) {
+ channelGroups->DrawChannelGroups(columns.First()->getChannel(), columns.Last()->getChannel());
+ }
+
+ if (activeGrid && (tvguideConfig.channelJumpMode == eGroupJump)) {
+ footer->UpdateGroupButtons(activeGrid->column->getChannel());
+ }
+ osdManager.flush();
+}
+
+void cTvGuideOsd::timeForward() {
+ bool actionDone = false;
+ if ( (myTime->GetEnd() - activeGrid->EndTime())/60 < 30 ) {
+ ScrollForward();
+ actionDone = true;
+ }
+ cGrid *next = activeGrid->column->getNext(activeGrid);
+ if (next) {
+ if ( (next->EndTime() < myTime->GetEnd())
+ || ( (myTime->GetEnd() - next->StartTime())/60 > 30 ) ) {
+ setNextActiveGrid(next);
+ actionDone = true;
+ }
+ }
+ if (!actionDone) {
+ ScrollForward();
+ }
+ 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();
- }
+ 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::timeBack() {
+ bool actionDone = false;
+ if ( (activeGrid->StartTime() - myTime->GetStart())/60 < 30 ) {
+ ScrollBack();
+ actionDone = true;
+ }
+ cGrid *prev = activeGrid->column->getPrev(activeGrid);
+ if (prev) {
+ if ( (prev->StartTime() > myTime->GetStart())
+ || ( (prev->EndTime() - myTime->GetStart())/60 > 30 )
+ || ( prev->isFirst()) ) {
+ setNextActiveGrid(prev);
+ actionDone = true;
+ }
+ }
+ if (!actionDone) {
+ ScrollBack();
+ }
+ osdManager.flush();
}
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();
- }
+ 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::processKeyUp() {
+ if (!activeGrid) {
+ return;
+ }
+ if (tvguideConfig.displayMode == eVertical) {
+ timeBack();
+ } else if (tvguideConfig.displayMode == eHorizontal) {
+ channelBack();
+ }
+}
+
+void cTvGuideOsd::processKeyDown() {
+ if (!activeGrid) {
+ return;
+ }
+ if (tvguideConfig.displayMode == eVertical) {
+ timeForward();
+ } else if (tvguideConfig.displayMode == eHorizontal) {
+ channelForward();
+ }
}
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();
+ if (activeGrid == NULL)
+ return;
+ if (tvguideConfig.displayMode == eVertical) {
+ channelBack();
+ } else if (tvguideConfig.displayMode == eHorizontal) {
+ timeBack();
+ }
}
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();
- }
+ if (activeGrid == NULL)
+ return;
+ if (tvguideConfig.displayMode == eVertical) {
+ channelForward();
+ } else if (tvguideConfig.displayMode == eHorizontal) {
+ timeForward();
+ }
}
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);
+ if ((activeGrid == NULL) || activeGrid->isDummy())
+ return;
+ recMenuManager->Start(activeGrid->GetEvent());
}
void cTvGuideOsd::processKeyGreen() {
- if (activeGrid == NULL)
- return;
- cChannel *currentChannel = activeGrid->column->getChannel();
- bool doUpdate = readChannelsReverse(currentChannel);
- if (doUpdate && (columns.Count() > 0)) {
- drawGridsChannelJump();
- }
- osdManager.flush();
+ if (activeGrid == NULL)
+ return;
+
+ const cChannel *currentChannel = activeGrid->column->getChannel();
+ const cChannel *firstChannel = columns.First()->getChannel();
+ int currentCol = activeGrid->column->GetNum();
+ const cChannel *prev = NULL;
+
+ if (tvguideConfig.channelJumpMode == eGroupJump) {
+ int prevNum = channelGroups->GetPrevGroupChannelNumber(currentChannel);
+ if (prevNum) {
+ prev = Channels.GetByNumber(prevNum);
+ }
+ } else if (tvguideConfig.channelJumpMode == eNumJump) {
+ int i = tvguideConfig.jumpChannels + 1;
+ for (const cChannel *channel = firstChannel; channel; channel = Channels.Prev(channel)) {
+ if (!channel->GroupSep()) {
+ prev = channel;
+ i--;
+ }
+ if (i == 0)
+ break;
+ }
+ }
+ if (prev) {
+ readChannels(prev);
+ if (columns.Count() > 0) {
+ if (tvguideConfig.channelJumpMode == eGroupJump)
+ drawGridsChannelJump();
+ else
+ drawGridsChannelJump(currentCol);
+ }
+ 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();
+ if (activeGrid == NULL)
+ return;
+ const cChannel *currentChannel = activeGrid->column->getChannel();
+ int currentCol = activeGrid->column->GetNum();
+ const cChannel *firstChannel = columns.First()->getChannel();
+ const cChannel *next = NULL;
+
+ if (tvguideConfig.channelJumpMode == eGroupJump) {
+ int nextNum = channelGroups->GetNextGroupChannelNumber(currentChannel);
+ if (nextNum) {
+ next = Channels.GetByNumber(nextNum);
+ }
+ } else if (tvguideConfig.channelJumpMode == eNumJump) {
+ int i=0;
+ for (const cChannel *channel = firstChannel; channel; channel = Channels.Next(channel)) {
+ if (channelGroups->IsInLastGroup(channel)) {
+ break;
+ }
+ if (!channel->GroupSep()) {
+ next = channel;
+ i++;
+ }
+ if (i == (tvguideConfig.jumpChannels+1)) {
+ break;
+ }
+ }
+ }
+ if (next) {
+ readChannels(next);
+ if (columns.Count() > 0) {
+ if (tvguideConfig.channelJumpMode == eGroupJump)
+ drawGridsChannelJump();
+ else
+ drawGridsChannelJump(currentCol);
+ }
+ osdManager.flush();
+ }
+}
+
+eOSState cTvGuideOsd::processKeyBlue(bool *alreadyUnlocked) {
+ if (tvguideConfig.blueKeyMode == eBlueKeySwitch) {
+ return ChannelSwitch(alreadyUnlocked);
+ } else if (tvguideConfig.blueKeyMode == eBlueKeyEPG) {
+ DetailedEPG();
+ } else if (tvguideConfig.blueKeyMode == eBlueKeyFavorites) {
+ recMenuManager->StartFavorites();
+ }
+ return osContinue;
+}
+
+eOSState cTvGuideOsd::processKeyOk(bool *alreadyUnlocked) {
+ if (tvguideConfig.blueKeyMode == eBlueKeySwitch) {
+ DetailedEPG();
+ } else if (tvguideConfig.blueKeyMode == eBlueKeyEPG) {
+ return ChannelSwitch(alreadyUnlocked);
+ } else if (tvguideConfig.blueKeyMode == eBlueKeyFavorites) {
+ DetailedEPG();
+ }
+ return osContinue;
+}
+
+eOSState cTvGuideOsd::ChannelSwitch(bool *alreadyUnlocked) {
+ if (activeGrid == NULL)
+ return osContinue;
+ const cChannel *currentChannel = activeGrid->column->getChannel();
+ if (currentChannel) {
+ cPixmap::Unlock();
+ *alreadyUnlocked = true;
+ cDevice::PrimaryDevice()->SwitchChannel(currentChannel, true);
+ if (tvguideConfig.closeOnSwitch) {
+ if (detailView) {
+ delete detailView;
+ detailView = NULL;
+ detailViewActive = false;
+ }
+ return osEnd;
+ }
+ }
+ return osContinue;
+}
+
+void cTvGuideOsd::DetailedEPG() {
+ if (!activeGrid->isDummy()) {
+ detailViewActive = true;
+ detailView = new cDetailView(activeGrid->GetEvent(), footer);
+ footer->SetDetailedViewMode();
+ osdManager.flush();
+ detailView->Start();
+ osdManager.flush();
+ }
+}
+
+void cTvGuideOsd::processNumKey(int numKey) {
+ if (tvguideConfig.numkeyMode == 0) {
+ //timely jumps with 1,3,4,6,7,9
+ TimeJump(numKey);
+ } else {
+ //jump to specific channel
+ ChannelJump(numKey);
+ }
+}
+
+void cTvGuideOsd::TimeJump(int mode) {
+ switch (mode) {
+ case 1: {
+ bool tooFarInPast = myTime->DelStep(tvguideConfig.bigStepHours*60);
+ if (tooFarInPast)
+ return;
+ }
+ break;
+ case 3: {
+ myTime->AddStep(tvguideConfig.bigStepHours*60);
+ }
+ break;
+ case 4: {
+ bool tooFarInPast = myTime->DelStep(tvguideConfig.hugeStepHours*60);
+ if (tooFarInPast)
+ return;
+ }
+ break;
+ case 6: {
+ myTime->AddStep(tvguideConfig.hugeStepHours*60);
+ }
+ break;
+ case 7: {
+ cMyTime primeChecker;
+ primeChecker.Now();
+ time_t prevPrime = primeChecker.getPrevPrimetime(myTime->GetStart());
+ if (primeChecker.tooFarInPast(prevPrime))
+ return;
+ myTime->SetTime(prevPrime);
+ }
+ break;
+ case 9: {
+ cMyTime primeChecker;
+ time_t nextPrime = primeChecker.getNextPrimetime(myTime->GetStart());
+ myTime->SetTime(nextPrime);
+ }
+ break;
+ default:
+ return;
+ }
+ drawGridsTimeJump();
+ timeLine->drawDateViewer();
+ timeLine->drawClock();
+ timeLine->setTimeline();
+ osdManager.flush();
+}
+
+void cTvGuideOsd::ChannelJump(int num) {
+ if (!channelJumper) {
+ channelJumper = new cChannelJump(channelGroups);
+ }
+ channelJumper->Set(num);
+ channelJumper->DrawText();
+ osdManager.flush();
+}
+
+void cTvGuideOsd::CheckTimeout(void) {
+ if (!channelJumper)
+ return;
+ if (channelJumper->TimeOut()) {
+ int newChannelNum = channelJumper->GetChannel();
+ delete channelJumper;
+ channelJumper = NULL;
+ const cChannel *newChannel = Channels.GetByNumber(newChannelNum);
+ if (newChannel) {
+ readChannels(newChannel);
+ if (columns.Count() > 0) {
+ drawGridsChannelJump();
+ }
+ }
+ osdManager.flush();
+ }
+}
+
+void cTvGuideOsd::SetTimers() {
+ for (cChannelColumn *column = columns.First(); column; column = columns.Next(column)) {
+ column->SetTimers();
+ }
}
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;
-}
\ No newline at end of file
+ eOSState state = osContinue;
+ cPixmap::Lock();
+ bool alreadyUnlocked = false;
+ if (recMenuManager->isActive()) {
+ state = recMenuManager->ProcessKey(Key);
+ if (state == osEnd) {
+ SetTimers();
+ osdManager.flush();
+ }
+ state = osContinue;
+ } else if (detailViewActive) {
+ if ((Key & ~k_Repeat) == kRed) {
+ delete detailView;
+ detailView = NULL;
+ detailViewActive = false;
+ processKeyRed();
+ } else if ((Key & ~k_Repeat) == kBlue) {
+ delete detailView;
+ detailView = NULL;
+ detailViewActive = false;
+ if ((tvguideConfig.blueKeyMode == eBlueKeySwitch) || (tvguideConfig.blueKeyMode == eBlueKeyFavorites)) {
+ state = ChannelSwitch(&alreadyUnlocked);
+ } else {
+ osdManager.flush();
+ state = osContinue;
+ }
+ } else if ((Key & ~k_Repeat) == kOk && (tvguideConfig.blueKeyMode == eBlueKeyEPG)) {
+ delete detailView;
+ detailView = NULL;
+ detailViewActive = false;
+ state = ChannelSwitch(&alreadyUnlocked);
+ } else {
+ state = detailView->ProcessKey(Key);
+ if (state == osEnd) {
+ delete detailView;
+ detailView = NULL;
+ detailViewActive = false;
+ osdManager.flush();
+ state = osContinue;
+ }
+ }
+ } else {
+ 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(&alreadyUnlocked); break;
+ case kOk: state = processKeyOk(&alreadyUnlocked); break;
+ case kBack: state=osEnd; break;
+ case k0 ... k9: processNumKey(Key - k0); break;
+ case kNone: if (channelJumper) CheckTimeout(); break;
+ default: break;
+ }
+ }
+ if (!alreadyUnlocked) {
+ cPixmap::Unlock();
+ }
+ return state;
+}
+
+void cTvGuideOsd::dump() {
+ esyslog("tvguide: ------Dumping Content---------");
+ activeGrid->debug();
+ int i=1;
+ for (cChannelColumn *col = columns.First(); col; col = columns.Next(col)) {
+ col->dumpGrids();
+ }
+}
diff --git a/tvguideosd.h b/tvguideosd.h
index c619ec4..1e6a990 100644
--- a/tvguideosd.h
+++ b/tvguideosd.h
@@ -1,21 +1,35 @@
#ifndef __TVGUIDE_TVGUIDEOSD_H
#define __TVGUIDE_TVGUIDEOSD_H
+#include "timer.h"
+#include "grid.h"
+#include "channelcolumn.h"
+#include "statusheader.h"
+#include "detailview.h"
+#include "timeline.h"
+#include "channelgroups.h"
+#include "footer.h"
+#include "recmenumanager.h"
+#include "channeljump.h"
+
// --- cTvGuideOsd -------------------------------------------------------------
class cTvGuideOsd : public cOsdObject {
private:
cMyTime *myTime;
cList<cChannelColumn> columns;
- cEpgGrid *activeGrid;
+ cGrid *activeGrid;
+ cStatusHeader *statusHeader;
cDetailView *detailView;
cTimeLine *timeLine;
+ cChannelGroups *channelGroups;
cFooter *footer;
+ cRecMenuManager *recMenuManager;
+ cChannelJump *channelJumper;
bool detailViewActive;
void drawOsd();
- void readChannels(cChannel *channelStart);
- bool readChannelsReverse(cChannel *channelStart);
- void drawGridsChannelJump();
+ void readChannels(const cChannel *channelStart);
+ void drawGridsChannelJump(int offset = 0);
void drawGridsTimeJump();
void processKeyUp();
void processKeyDown();
@@ -24,17 +38,23 @@ private:
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);
+ eOSState processKeyBlue(bool *alreadyUnlocked);
+ eOSState processKeyOk(bool *alreadyUnlocked);
+ void processNumKey(int numKey);
+ void TimeJump(int mode);
+ void ChannelJump(int num);
+ void CheckTimeout(void);
+ void setNextActiveGrid(cGrid *next);
+ void channelForward();
+ void channelBack();
+ void timeForward();
+ void timeBack();
void ScrollForward();
void ScrollBack();
+ eOSState ChannelSwitch(bool *alreadyUnlocked);
+ void DetailedEPG();
+ void SetTimers();
+ void dump();
public:
cTvGuideOsd(void);
virtual ~cTvGuideOsd(void);
@@ -42,4 +62,4 @@ public:
virtual eOSState ProcessKey(eKeys Key);
};
-#endif //__TVGUIDE_TVGUIDEOSD_H
\ No newline at end of file
+#endif //__TVGUIDE_TVGUIDEOSD_H
diff --git a/view.c b/view.c
new file mode 100644
index 0000000..7608c03
--- /dev/null
+++ b/view.c
@@ -0,0 +1,1046 @@
+#include "detailview.h"
+
+/********************************************************************************************
+* cView
+********************************************************************************************/
+
+cView::cView(void) {
+ activeView = 0;
+ scrollable = false;
+ tabbed = false;
+ font = NULL;
+ fontSmall = NULL;
+ fontHeader = NULL;
+ fontHeaderLarge = NULL;
+ pixmapBackground = NULL;
+ pixmapHeader = NULL;
+ pixmapHeaderLogo = NULL;
+ pixmapContent = NULL;
+ pixmapTabs = NULL;
+ pixmapScrollbar = NULL;
+ pixmapScrollbarBack = NULL;
+ imgScrollBar = NULL;
+ title = "";
+ subTitle = "";
+ dateTime = "";
+ infoText = "";
+ channel = NULL;
+ eventID = 0;
+ event = NULL;
+ x = 0;
+ y = 0;
+ width = 0;
+ height = 0;
+ border = 0;
+ headerHeight = 0;
+ contentHeight = 0;
+ tabHeight = 0;
+ headerDrawn = false;
+}
+
+cView::~cView(void) {
+ if (pixmapBackground)
+ osdManager.releasePixmap(pixmapBackground);
+ if (pixmapHeader)
+ delete pixmapHeader;
+ if (pixmapHeaderLogo)
+ osdManager.releasePixmap(pixmapHeaderLogo);
+ if (pixmapContent)
+ osdManager.releasePixmap(pixmapContent);
+ if (pixmapTabs)
+ osdManager.releasePixmap(pixmapTabs);
+ if (pixmapScrollbar)
+ osdManager.releasePixmap(pixmapScrollbar);
+ if (pixmapScrollbarBack)
+ osdManager.releasePixmap(pixmapScrollbarBack);
+ if (imgScrollBar)
+ delete imgScrollBar;
+}
+
+void cView::SetFonts(void) {
+ font = fontManager.FontDetailView;
+ fontSmall = fontManager.FontDetailViewSmall;
+ fontHeaderLarge = fontManager.FontDetailHeaderLarge;
+ fontHeader = fontManager.FontDetailHeader;
+}
+
+void cView::SetGeometry(void) {
+ x = 0;
+ y = 0;
+ scrollbarWidth = 40;
+ width = geoManager.osdWidth - scrollbarWidth;
+ height = geoManager.osdHeight;
+ border = tvguideConfig.epgViewBorder;
+ headerWidth = geoManager.headerContentWidth;
+ headerHeight = geoManager.epgViewHeaderHeight;
+ if (tabbed)
+ tabHeight = font->Height() * 3 / 2;
+ contentHeight = height - headerHeight - tabHeight - geoManager.footerHeight;
+}
+
+void cView::DrawHeader(void) {
+ if (!pixmapHeader) {
+ pixmapHeader = new cStyledPixmap(osdManager.requestPixmap(5, cRect(0, 0, headerWidth, headerHeight)));
+ pixmapHeader->setColor(theme.Color(clrHeader), theme.Color(clrHeaderBlending));
+ }
+ if (!pixmapHeaderLogo) {
+ pixmapHeaderLogo = osdManager.requestPixmap(6, cRect(0, 0, width, headerHeight));
+ }
+ pixmapHeader->Fill(clrTransparent);
+ pixmapHeaderLogo->Fill(clrTransparent);
+ if (tvguideConfig.style == eStyleGraphical) {
+ if (tvguideConfig.scaleVideo) {
+ pixmapHeader->drawBackgroundGraphical(bgStatusHeaderWindowed);
+ } else {
+ pixmapHeader->drawBackgroundGraphical(bgStatusHeaderFull);
+ }
+ } else {
+ pixmapHeader->drawBackground();
+ pixmapHeader->drawBoldBorder();
+ }
+ //Channel Logo
+ int logoHeight = 2 * headerHeight / 3;
+ int logoWidth = logoHeight * tvguideConfig.logoWidthRatio / tvguideConfig.logoHeightRatio;
+ int xText = border / 2;
+ if (channel && !tvguideConfig.hideChannelLogos) {
+ cImageLoader imgLoader;
+ if (imgLoader.LoadLogo(channel, logoWidth, logoHeight)) {
+ cImage logo = imgLoader.GetImage();
+ pixmapHeaderLogo->DrawImage(cPoint(border/2, (headerHeight - logoHeight)/2), logo);
+ xText += logoWidth + border / 2;
+ }
+ }
+ //Date and Time, Title, Subtitle
+ int yDateTime = border / 2;
+ int yTitle = (headerHeight - fontHeaderLarge->Height()) / 2;
+ int ySubtitle = headerHeight - fontHeader->Height() - border / 3;
+ int textWidthMax = headerWidth - xText;
+ pixmapHeader->DrawText(cPoint(xText, yDateTime), CutText(dateTime, textWidthMax, fontHeader).c_str(), theme.Color(clrFont), theme.Color(clrStatusHeader), fontHeader);
+ pixmapHeader->DrawText(cPoint(xText, yTitle), CutText(title, textWidthMax, fontHeaderLarge).c_str(), theme.Color(clrFont), theme.Color(clrStatusHeader), fontHeaderLarge);
+ pixmapHeader->DrawText(cPoint(xText, ySubtitle), CutText(subTitle, textWidthMax, fontHeader).c_str(), theme.Color(clrFont), theme.Color(clrStatusHeader), fontHeader);
+ //REC Icon
+ eTimerMatch timerMatch=tmNone;
+ cTimer *ti;
+ if (!event)
+ return;
+ if (tvguideConfig.useRemoteTimers && pRemoteTimers) {
+ RemoteTimers_GetMatch_v1_0 rtMatch;
+ rtMatch.event = event;
+ pRemoteTimers->Service("RemoteTimers::GetMatch-v1.0", &rtMatch);
+ timerMatch = (eTimerMatch)rtMatch.timerMatch;
+ ti = rtMatch.timer;
+ } else {
+ ti=Timers.GetMatch(event, &timerMatch);
+ }
+ if (timerMatch == tmFull) {
+ cString recIconText(" REC ");
+ int widthIcon = fontManager.FontDetailHeader->Width(*recIconText);
+ int height = fontManager.FontDetailHeader->Height()+10;
+ int posX = headerWidth - widthIcon - 20;
+ int posY = 20;
+ pixmapHeader->DrawRectangle( cRect(posX, posY, widthIcon, height), theme.Color(clrButtonRed));
+ pixmapHeader->DrawText(cPoint(posX, posY+5), *recIconText, theme.Color(clrFont), theme.Color(clrButtonRed), fontManager.FontDetailHeader);
+ }
+}
+
+void cView::DrawTabs(void) {
+ if (!pixmapTabs) {
+ pixmapTabs = osdManager.requestPixmap(4, cRect(0, y + headerHeight + contentHeight, width + scrollbarWidth, tabHeight));
+ }
+ tColor bgColor = theme.Color(clrTabInactive);
+ pixmapTabs->Fill(clrTransparent);
+ pixmapTabs->DrawRectangle(cRect(0, 0, width, 2), bgColor);
+ int numTabs = tabs.size();
+ int xCurrent = 0;
+ for (int tab = 0; tab < numTabs; tab++) {
+ std::string tabText = tabs[tab];
+ int textWidth = font->Width(tabText.c_str());
+ int tabWidth = textWidth + border;
+ pixmapTabs->DrawRectangle(cRect(xCurrent, (tab == activeView) ? 0 : 2, tabWidth - 2, tabHeight), bgColor);
+ pixmapTabs->DrawEllipse(cRect(xCurrent, tabHeight - border/2, border/2, border/2), clrTransparent, -3);
+ pixmapTabs->DrawEllipse(cRect(xCurrent + tabWidth - border / 2 - 2, tabHeight - border/2, border/2, border/2), clrTransparent, -4);
+ if (tab == activeView) {
+ pixmapTabs->DrawRectangle(cRect(xCurrent + 2, 0, tabWidth - 6, tabHeight - border/2 - 1), clrTransparent);
+ pixmapTabs->DrawRectangle(cRect(xCurrent + border / 2, tabHeight - border/2 - 1, tabWidth - border, border/2 - 1), clrTransparent);
+ pixmapTabs->DrawEllipse(cRect(xCurrent + 2, tabHeight - border/2 - 2, border/2, border/2), clrTransparent, 3);
+ pixmapTabs->DrawEllipse(cRect(xCurrent + tabWidth - border / 2 - 4, tabHeight - border/2 - 2, border/2, border/2), clrTransparent, 4);
+ }
+ pixmapTabs->DrawText(cPoint(xCurrent + (tabWidth - textWidth) / 2, 2 + (tabHeight - font->Height())/2), tabText.c_str(), theme.Color(clrFont), (tab == activeView) ? clrTransparent : bgColor, font);
+ xCurrent += tabWidth;
+ }
+}
+
+void cView::ClearContent(void) {
+ if (pixmapContent && Running()) {
+ osdManager.releasePixmap(pixmapContent);
+ pixmapContent = NULL;
+ }
+ if (pixmapBackground && Running()) {
+ osdManager.releasePixmap(pixmapBackground);
+ pixmapBackground = NULL;
+ }
+}
+
+void cView::CreateContent(int fullHeight) {
+ scrollable = false;
+ pixmapBackground = osdManager.requestPixmap(3, cRect(x, y + headerHeight, width + scrollbarWidth, contentHeight + tabHeight));
+ pixmapBackground->Fill(theme.Color(clrBackground));
+
+ int drawPortHeight = contentHeight;
+ if (fullHeight > contentHeight) {
+ drawPortHeight = fullHeight;
+ scrollable = true;
+ }
+ pixmapContent = osdManager.requestPixmap(4, cRect(x, y + headerHeight, width, contentHeight), cRect(0, 0, width, drawPortHeight));
+ pixmapContent->Fill(clrTransparent);
+}
+
+void cView::DrawContent(std::string *text) {
+ cTextWrapper wText;
+ wText.Set(text->c_str(), font, width - 2 * border);
+ int lineHeight = font->Height();
+ int textLines = wText.Lines();
+ int textHeight = lineHeight * textLines + 2*border;
+ int yText = border;
+ CreateContent(textHeight);
+ for (int i=0; i < textLines; i++) {
+ pixmapContent->DrawText(cPoint(border, yText), wText.GetLine(i), theme.Color(clrFont), clrTransparent, font);
+ yText += lineHeight;
+ }
+}
+
+void cView::DrawFloatingContent(std::string *infoText, cTvMedia *img, cTvMedia *img2) {
+ cTextWrapper wTextTall;
+ cTextWrapper wTextFull;
+ int imgWidth = img->width;
+ int imgHeight = img->height;
+ int imgWidth2 = 0;
+ int imgHeight2 = 0;
+ if (imgHeight > (contentHeight - 2 * border)) {
+ imgHeight = contentHeight - 2 * border;
+ imgWidth = imgWidth * ((double)imgHeight / (double)img->height);
+ }
+ int imgHeightTotal = imgHeight;
+ if (img2) {
+ imgWidth2 = imgWidth;
+ imgHeight2 = img2->height * ((double)img2->width / (double)imgWidth2);
+ imgHeightTotal += img2->height + border;
+ }
+ CreateFloatingTextWrapper(&wTextTall, &wTextFull, infoText, imgWidth, imgHeightTotal);
+ int lineHeight = font->Height();
+ int textLinesTall = wTextTall.Lines();
+ int textLinesFull = wTextFull.Lines();
+ int textHeight = lineHeight * (textLinesTall + textLinesFull) + 2*border;
+ int yText = border;
+ CreateContent(max(textHeight, imgHeight + 2*border));
+ for (int i=0; i < textLinesTall; i++) {
+ pixmapContent->DrawText(cPoint(border, yText), wTextTall.GetLine(i), theme.Color(clrFont), clrTransparent, font);
+ yText += lineHeight;
+ }
+ for (int i=0; i < textLinesFull; i++) {
+ pixmapContent->DrawText(cPoint(border, yText), wTextFull.GetLine(i), theme.Color(clrFont), clrTransparent, font);
+ yText += lineHeight;
+ }
+ osdManager.flush();
+ cImageLoader imgLoader;
+ if (imgLoader.LoadPoster(img->path.c_str(), imgWidth, imgHeight)) {
+ if (Running() && pixmapContent)
+ pixmapContent->DrawImage(cPoint(width - imgWidth - border, border), imgLoader.GetImage());
+ }
+ if (!img2)
+ return;
+ osdManager.flush();
+ if (imgLoader.LoadPoster(img2->path.c_str(), imgWidth2, imgHeight2)) {
+ if (Running() && pixmapContent)
+ pixmapContent->DrawImage(cPoint(width - imgWidth2 - border, imgHeight + 2*border), imgLoader.GetImage());
+ }
+}
+
+void cView::CreateFloatingTextWrapper(cTextWrapper *twNarrow, cTextWrapper *twFull, std::string *text, int widthImg, int heightImg) {
+ int lineHeight = font->Height();
+ int linesNarrow = (heightImg + 2*border)/ lineHeight;
+ int linesDrawn = 0;
+ int y = 0;
+ int widthNarrow = width - 3 * border - widthImg;
+ bool drawNarrow = true;
+
+ splitstring s(text->c_str());
+ std::vector<std::string> flds = s.split('\n', 1);
+
+ if (flds.size() < 1)
+ return;
+
+ std::stringstream sstrTextTall;
+ std::stringstream sstrTextFull;
+
+ for (int i=0; i<flds.size(); i++) {
+ if (!flds[i].size()) {
+ //empty line
+ linesDrawn++;
+ y += lineHeight;
+ if (drawNarrow)
+ sstrTextTall << "\n";
+ else
+ sstrTextFull << "\n";
+ } else {
+ cTextWrapper wrapper;
+ if (drawNarrow) {
+ wrapper.Set((flds[i].c_str()), font, widthNarrow);
+ int newLines = wrapper.Lines();
+ //check if wrapper fits completely into narrow area
+ if (linesDrawn + newLines < linesNarrow) {
+ for (int line = 0; line < wrapper.Lines(); line++) {
+ sstrTextTall << wrapper.GetLine(line) << " ";
+ }
+ sstrTextTall << "\n";
+ linesDrawn += newLines;
+ } else {
+ //this wrapper has to be splitted
+ for (int line = 0; line < wrapper.Lines(); line++) {
+ if (line + linesDrawn < linesNarrow) {
+ sstrTextTall << wrapper.GetLine(line) << " ";
+ } else {
+ sstrTextFull << wrapper.GetLine(line) << " ";
+ }
+ }
+ sstrTextFull << "\n";
+ drawNarrow = false;
+ }
+ } else {
+ wrapper.Set((flds[i].c_str()), font, width - 2*border);
+ for (int line = 0; line < wrapper.Lines(); line++) {
+ sstrTextFull << wrapper.GetLine(line) << " ";
+ }
+ sstrTextFull << "\n";
+ }
+ }
+ }
+ twNarrow->Set(sstrTextTall.str().c_str(), font, widthNarrow);
+ twFull->Set(sstrTextFull.str().c_str(), font, width - 2 * border);
+}
+
+void cView::DrawActors(std::vector<cActor> *actors) {
+ int numActors = actors->size();
+ if (numActors < 1) {
+ CreateContent(100);
+ pixmapContent->DrawText(cPoint(border, border), tr("No Cast available"), theme.Color(clrFont), clrTransparent, fontHeaderLarge);
+ return;
+ }
+ int thumbWidth = actors->at(0).actorThumb.width;
+ int thumbHeight = actors->at(0).actorThumb.height;
+
+ int picsPerLine = width / (thumbWidth + 2 * border);
+ if (picsPerLine < 1)
+ return;
+
+ int picLines = numActors / picsPerLine;
+ if (numActors%picsPerLine != 0)
+ picLines++;
+
+ int totalHeight = picLines * (thumbHeight + 2*fontSmall->Height() + border + border/2) + 2*border + fontHeaderLarge->Height();
+
+ CreateContent(totalHeight);
+ cString header = cString::sprintf("%s:", tr("Cast"));
+ pixmapContent->DrawText(cPoint(border, border), *header, theme.Color(clrFont), clrTransparent, fontHeaderLarge);
+
+ int x = 0;
+ int y = 2 * border + fontHeaderLarge->Height();
+ if (!Running())
+ return;
+ cImageLoader imgLoader;
+ int actor = 0;
+ for (int row = 0; row < picLines; row++) {
+ for (int col = 0; col < picsPerLine; col++) {
+ if (!Running())
+ return;
+ if (actor == numActors)
+ break;
+ std::string path = actors->at(actor).actorThumb.path;
+ std::string name = actors->at(actor).name;
+ std::stringstream sstrRole;
+ sstrRole << "\"" << actors->at(actor).role << "\"";
+ std::string role = sstrRole.str();
+ if (imgLoader.LoadPoster(path.c_str(), thumbWidth, thumbHeight)) {
+ if (Running() && pixmapContent)
+ pixmapContent->DrawImage(cPoint(x + border, y), imgLoader.GetImage());
+ }
+
+ if (fontSmall->Width(name.c_str()) > thumbWidth + 2*border)
+ name = CutText(name, thumbWidth + 2*border, fontSmall);
+ if (fontSmall->Width(role.c_str()) > thumbWidth + 2*border)
+ role = CutText(role, thumbWidth + 2*border, fontSmall);
+ int xName = x + ((thumbWidth+2*border) - fontSmall->Width(name.c_str()))/2;
+ int xRole = x + ((thumbWidth+2*border) - fontSmall->Width(role.c_str()))/2;
+ if (Running() && pixmapContent) {
+ pixmapContent->DrawText(cPoint(xName, y + thumbHeight + border/2), name.c_str(), theme.Color(clrFont), clrTransparent, fontSmall);
+ pixmapContent->DrawText(cPoint(xRole, y + thumbHeight + border/2 + fontSmall->Height()), role.c_str(), theme.Color(clrFont), clrTransparent, fontSmall);
+ x += thumbWidth + 2*border;
+ }
+ actor++;
+ }
+ osdManager.flush();
+ x = 0;
+ y += thumbHeight + 2 * fontSmall->Height() + border + border/2;
+ }
+}
+
+void cView::ClearScrollbar(void) {
+ if (pixmapScrollbar)
+ pixmapScrollbar->Fill(clrTransparent);
+ if (pixmapScrollbarBack)
+ pixmapScrollbarBack->Fill(clrTransparent);
+}
+
+void cView::ClearScrollbarImage(void) {
+ if (imgScrollBar) {
+ delete imgScrollBar;
+ imgScrollBar = NULL;
+ }
+}
+
+void cView::DrawScrollbar(void) {
+ ClearScrollbar();
+ if (!scrollable || !pixmapContent)
+ return;
+
+ if (!pixmapScrollbar) {
+ pixmapScrollbar = osdManager.requestPixmap(6, cRect(width, y + headerHeight, scrollbarWidth, contentHeight));
+ pixmapScrollbar->Fill(clrTransparent);
+ }
+ if (!pixmapScrollbarBack) {
+ pixmapScrollbarBack = osdManager.requestPixmap(5, cRect(width, y + headerHeight, scrollbarWidth, contentHeight));
+ pixmapScrollbarBack->Fill(clrTransparent);
+ }
+
+ int totalBarHeight = pixmapScrollbar->ViewPort().Height() - 6;
+
+ int aktHeight = (-1)*pixmapContent->DrawPort().Point().Y();
+ int totalHeight = pixmapContent->DrawPort().Height();
+ int screenHeight = pixmapContent->ViewPort().Height();
+
+ int barHeight = (double)(screenHeight * totalBarHeight) / (double)totalHeight ;
+ int barTop = (double)(aktHeight * totalBarHeight) / (double)totalHeight ;
+
+ if (!imgScrollBar) {
+ imgScrollBar = CreateScrollbarImage(pixmapScrollbar->ViewPort().Width()-10, barHeight, theme.Color(clrHighlight), theme.Color(clrHighlightBlending));
+ }
+
+ pixmapScrollbarBack->Fill(theme.Color(clrHighlightBlending));
+ pixmapScrollbarBack->DrawRectangle(cRect(2, 2, pixmapScrollbar->ViewPort().Width() - 4, pixmapScrollbar->ViewPort().Height() - 4), theme.Color(clrHighlightBlending));
+
+ pixmapScrollbar->DrawImage(cPoint(3, 3 + barTop), *imgScrollBar);
+}
+
+cImage *cView::CreateScrollbarImage(int width, int height, tColor clrBgr, tColor clrBlend) {
+ cImage *image = new cImage(cSize(width, height));
+ image->Fill(clrBgr);
+ if (tvguideConfig.style != eStyleFlat) {
+ 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;
+}
+
+bool cView::KeyUp(void) {
+ if (!scrollable)
+ return false;
+ int aktHeight = pixmapContent->DrawPort().Point().Y();
+ int lineHeight = font->Height();
+ if (aktHeight >= 0) {
+ return false;
+ }
+ int step = tvguideConfig.detailedViewScrollStep * font->Height();
+ int newY = aktHeight + step;
+ if (newY > 0)
+ newY = 0;
+ pixmapContent->SetDrawPortPoint(cPoint(0, newY));
+ return true;
+}
+
+bool cView::KeyDown(void) {
+ if (!scrollable)
+ return false;
+ int aktHeight = pixmapContent->DrawPort().Point().Y();
+ int totalHeight = pixmapContent->DrawPort().Height();
+ int screenHeight = pixmapContent->ViewPort().Height();
+
+ if (totalHeight - ((-1)*aktHeight) == screenHeight) {
+ return false;
+ }
+ int step = tvguideConfig.detailedViewScrollStep * font->Height();
+ int newY = aktHeight - step;
+ if ((-1)*newY > totalHeight - screenHeight)
+ newY = (-1)*(totalHeight - screenHeight);
+ pixmapContent->SetDrawPortPoint(cPoint(0, newY));
+ return true;
+}
+
+/********************************************************************************************
+* cEPGView : cView
+********************************************************************************************/
+
+cEPGView::cEPGView(void) : cView() {
+ tabbed = true;
+ numEPGPics = -1;
+ numTabs = 0;
+}
+
+cEPGView::~cEPGView(void) {
+ Cancel(-1);
+ while (Active())
+ cCondWait::SleepMs(10);
+}
+
+void cEPGView::SetTabs(void) {
+ tabs.push_back(tr("EPG Info"));
+ if (eventID > 0)
+ tabs.push_back(tr("Reruns"));
+ else
+ tabs.push_back(tr("Recording Information"));
+ if (numEPGPics > 0)
+ tabs.push_back(tr("Image Galery"));
+ numTabs = tabs.size();
+}
+
+void cEPGView::CheckEPGImages(void) {
+ if (eventID > 0) {
+ for (int i=1; i <= tvguideConfig.numAdditionalEPGPictures; i++) {
+ cString epgimage;
+ epgimage = cString::sprintf("%s%d_%d.jpg", *tvguideConfig.epgImagePath, eventID, i);
+ FILE *fp = fopen(*epgimage, "r");
+ if (fp) {
+ std::stringstream ss;
+ ss << i;
+ epgPics.push_back(ss.str());
+ fclose(fp);
+ } else {
+ break;
+ }
+ }
+ } else {
+ return;
+ }
+ numEPGPics = epgPics.size();
+}
+
+void cEPGView::DrawImages(void) {
+ int imgWidth = tvguideConfig.epgImageWidthLarge;
+ int imgHeight = tvguideConfig.epgImageHeightLarge;
+
+ int totalHeight = numEPGPics * (imgHeight + border);
+
+ CreateContent(totalHeight);
+
+ cImageLoader imgLoader;
+ int yPic = border;
+ for (int pic = 0; pic < numEPGPics; pic++) {
+ bool drawPic = false;
+ if (eventID > 0) {
+ cString epgimage = cString::sprintf("%d_%d", eventID, atoi(epgPics[pic].c_str()));
+ if (imgLoader.LoadAdditionalEPGImage(epgimage)) {
+ drawPic = true;
+ }
+
+ }
+ if (drawPic) {
+ pixmapContent->DrawImage(cPoint((width - imgWidth) / 2, yPic), imgLoader.GetImage());
+ yPic += imgHeight + border;
+ osdManager.flush();
+ }
+ }
+}
+
+void cEPGView::KeyLeft(void) {
+ if (Running())
+ return;
+ ClearScrollbarImage();
+ activeView--;
+ if (activeView < 0)
+ activeView = numTabs - 1;
+}
+
+void cEPGView::KeyRight(void) {
+ if (Running())
+ return;
+ ClearScrollbarImage();
+ activeView = (activeView + 1) % numTabs;
+}
+
+void cEPGView::Action(void) {
+ ClearContent();
+ if (!headerDrawn) {
+ DrawHeader();
+ osdManager.flush();
+ headerDrawn = true;
+ }
+ if (tabs.size() == 0) {
+ CheckEPGImages();
+ SetTabs();
+ }
+ DrawTabs();
+ switch (activeView) {
+ case evtInfo:
+ DrawContent(&infoText);
+ break;
+ case evtAddInfo:
+ DrawContent(&addInfoText);
+ break;
+ case evtImages:
+ DrawImages();
+ break;
+ }
+ DrawScrollbar();
+ osdManager.flush();
+}
+
+/********************************************************************************************
+* cSeriesView : cView
+********************************************************************************************/
+
+cSeriesView::cSeriesView(int seriesId, int episodeId) : cView() {
+ this->seriesId = seriesId;
+ this->episodeId = episodeId;
+ tvdbInfo = "";
+ tabbed = true;
+}
+
+cSeriesView::~cSeriesView(void) {
+ Cancel(-1);
+ while (Active())
+ cCondWait::SleepMs(10);
+}
+
+void cSeriesView::LoadMedia(void) {
+ static cPlugin *pScraper2Vdr = cPluginManager::GetPlugin("scraper2vdr");
+ if (!pScraper2Vdr || seriesId < 1)
+ return;
+ series.seriesId = seriesId;
+ series.episodeId = episodeId;
+ pScraper2Vdr->Service("GetSeries", &series);
+}
+
+void cSeriesView::SetTabs(void) {
+ tabs.push_back(tr("EPG Info"));
+ if (eventID > 0)
+ tabs.push_back(tr("Reruns"));
+ else
+ tabs.push_back(tr("Recording Information"));
+ tabs.push_back(tr("Cast"));
+ tabs.push_back(tr("TheTVDB Info"));
+ tabs.push_back(tr("Image Galery"));
+}
+
+void cSeriesView::CreateTVDBInfo(void) {
+ if (tvdbInfo.size() > 0)
+ return;
+ std::stringstream info;
+ info << tr("TheTVDB Information") << ":\n\n";
+
+ if (series.episode.name.size() > 0) {
+ info << tr("Episode") << ": " << series.episode.name << " (" << tr("Season") << " " << series.episode.season << ", " << tr("Episode") << " " << series.episode.number << ")\n\n";
+ }
+ if (series.episode.overview.size() > 0) {
+ info << tr("Episode Overview") << ": " << series.episode.overview << "\n\n";
+ }
+ if (series.episode.firstAired.size() > 0) {
+ info << tr("First aired") << ": " << series.episode.firstAired << "\n\n";
+ }
+ if (series.episode.guestStars.size() > 0) {
+ info << tr("Guest Stars") << ": " << series.episode.guestStars << "\n\n";
+ }
+ if (series.episode.rating > 0) {
+ info << tr("TheMovieDB Rating") << ": " << series.episode.rating << "\n\n";
+ }
+ if (series.overview.size() > 0) {
+ info << tr("Series Overview") << ": " << series.overview << "\n\n";
+ }
+ if (series.firstAired.size() > 0) {
+ info << tr("First aired") << ": " << series.firstAired << "\n\n";
+ }
+ if (series.genre.size() > 0) {
+ info << tr("Genre") << ": " << series.genre << "\n\n";
+ }
+ if (series.network.size() > 0) {
+ info << tr("Network") << ": " << series.network << "\n\n";
+ }
+ if (series.rating > 0) {
+ info << tr("TheMovieDB Rating") << ": " << series.rating << "\n\n";
+ }
+ if (series.status.size() > 0) {
+ info << tr("Status") << ": " << series.status << "\n\n";
+ }
+ tvdbInfo = info.str();
+}
+
+void cSeriesView::DrawImages(void) {
+ int numPosters = series.posters.size();
+ int numFanarts = series.fanarts.size();
+ int numBanners = series.banners.size();
+
+ int totalHeight = border;
+ //Fanart Height
+ int fanartWidth = width - 2 * border;
+ int fanartHeight = 0;
+ if (numFanarts > 0 && series.fanarts[0].width > 0) {
+ fanartHeight = series.fanarts[0].height * ((double)fanartWidth / (double)series.fanarts[0].width);
+ if (fanartHeight > contentHeight - 2 * border) {
+ int fanartHeightOrig = fanartHeight;
+ fanartHeight = contentHeight - 2 * border;
+ fanartWidth = fanartWidth * ((double)fanartHeight / (double)fanartHeightOrig);
+ }
+ totalHeight += series.fanarts.size() * (fanartHeight + border);
+ }
+ //Poster Height
+ int posterWidth = (width - 4 * border) / 2;
+ int posterHeight = 0;
+ if (numPosters > 0 && series.posters[0].width > 0) {
+ posterHeight = series.posters[0].height * ((double)posterWidth / (double)series.posters[0].width);
+ }
+ if (numPosters > 0)
+ totalHeight += posterHeight + border;
+ if (numPosters == 3)
+ totalHeight += posterHeight + border;
+ //Banners Height
+ if (numBanners > 0)
+ totalHeight += (series.banners[0].height + border) * numBanners;
+
+ CreateContent(totalHeight);
+
+ cImageLoader imgLoader;
+ int yPic = border;
+ for (int i=0; i < numFanarts; i++) {
+ if (numBanners > i) {
+ if (imgLoader.LoadPoster(series.banners[i].path.c_str(), series.banners[i].width, series.banners[i].height) && Running()) {
+ pixmapContent->DrawImage(cPoint((width - series.banners[i].width) / 2, yPic), imgLoader.GetImage());
+ yPic += series.banners[i].height + border;
+ osdManager.flush();
+ }
+ }
+ if (imgLoader.LoadPoster(series.fanarts[i].path.c_str(), fanartWidth, fanartHeight) && Running()) {
+ pixmapContent->DrawImage(cPoint((width - fanartWidth)/2, yPic), imgLoader.GetImage());
+ yPic += fanartHeight + border;
+ osdManager.flush();
+ }
+ }
+ if (numPosters >= 1) {
+ if (imgLoader.LoadPoster(series.posters[0].path.c_str(), posterWidth, posterHeight) && Running()) {
+ pixmapContent->DrawImage(cPoint(border, yPic), imgLoader.GetImage());
+ osdManager.flush();
+ yPic += posterHeight + border;
+ }
+ }
+ if (numPosters >= 2) {
+ if (imgLoader.LoadPoster(series.posters[1].path.c_str(), posterWidth, posterHeight) && Running()) {
+ pixmapContent->DrawImage(cPoint(2 * border + posterWidth, yPic - posterHeight - border), imgLoader.GetImage());
+ osdManager.flush();
+ }
+ }
+ if (numPosters == 3) {
+ if (imgLoader.LoadPoster(series.posters[2].path.c_str(), posterWidth, posterHeight) && Running()) {
+ pixmapContent->DrawImage(cPoint((width - posterWidth) / 2, yPic), imgLoader.GetImage());
+ osdManager.flush();
+ }
+ }
+}
+
+int cSeriesView::GetRandomPoster(void) {
+ int numPosters = series.posters.size();
+ if (numPosters == 0)
+ return -1;
+ srand((unsigned)time(NULL));
+ int randPoster = rand()%numPosters;
+ return randPoster;
+}
+
+void cSeriesView::KeyLeft(void) {
+ if (Running())
+ return;
+ ClearScrollbarImage();
+ activeView--;
+ if (activeView < 0)
+ activeView = mvtCount - 1;
+}
+
+void cSeriesView::KeyRight(void) {
+ if (Running())
+ return;
+ ClearScrollbarImage();
+ activeView = (activeView + 1) % mvtCount;
+}
+
+void cSeriesView::Action(void) {
+ ClearContent();
+ if (!headerDrawn) {
+ DrawHeader();
+ osdManager.flush();
+ headerDrawn = true;
+ }
+ if (tabs.size() == 0) {
+ SetTabs();
+ }
+ DrawTabs();
+ int randomPoster = GetRandomPoster();
+ switch (activeView) {
+ case mvtInfo:
+ if (randomPoster >= 0) {
+ DrawFloatingContent(&infoText, &series.posters[randomPoster]);
+ } else
+ DrawContent(&infoText);
+ break;
+ case mvtAddInfo:
+ if (randomPoster >= 0)
+ DrawFloatingContent(&addInfoText, &series.posters[randomPoster]);
+ else
+ DrawContent(&addInfoText);
+ break;
+ case mvtCast:
+ DrawActors(&series.actors);
+ break;
+ case mvtOnlineInfo:
+ CreateTVDBInfo();
+ if ((series.seasonPoster.path.size() > 0) && series.episode.episodeImage.path.size() > 0)
+ DrawFloatingContent(&tvdbInfo, &series.episode.episodeImage, &series.seasonPoster);
+ else if (series.seasonPoster.path.size() > 0)
+ DrawFloatingContent(&tvdbInfo, &series.seasonPoster);
+ else if (series.episode.episodeImage.path.size() > 0)
+ DrawFloatingContent(&tvdbInfo, &series.episode.episodeImage);
+ else if (randomPoster >= 0)
+ DrawFloatingContent(&tvdbInfo, &series.posters[randomPoster]);
+ else
+ DrawContent(&tvdbInfo);
+ break;
+ case mvtImages:
+ DrawImages();
+ break;
+ }
+ DrawScrollbar();
+ osdManager.flush();
+}
+
+/********************************************************************************************
+* cMovieView : cView
+********************************************************************************************/
+
+cMovieView::cMovieView(int movieId) : cView() {
+ this->movieId = movieId;
+ tabbed = true;
+}
+
+cMovieView::~cMovieView(void) {
+ Cancel(-1);
+ while (Active())
+ cCondWait::SleepMs(10);
+}
+
+void cMovieView::LoadMedia(void) {
+ static cPlugin *pScraper2Vdr = cPluginManager::GetPlugin("scraper2vdr");
+ if (!pScraper2Vdr || movieId < 1)
+ return;
+ movie.movieId = movieId;
+ pScraper2Vdr->Service("GetMovie", &movie);
+}
+
+void cMovieView::SetTabs(void) {
+ tabs.push_back(tr("EPG Info"));
+ if (eventID > 0)
+ tabs.push_back(tr("Reruns"));
+ else
+ tabs.push_back(tr("Recording Information"));
+ tabs.push_back(tr("Cast"));
+ tabs.push_back(tr("TheTVDB Info"));
+ tabs.push_back(tr("Image Galery"));
+}
+
+void cMovieView::CreateMovieDBInfo(void) {
+ if (movieDBInfo.size() > 0)
+ return;
+ std::stringstream info;
+ info << tr("TheMovieDB Information") << ":\n\n";
+ if (movie.originalTitle.size() > 0) {
+ info << tr("Original Title") << ": " << movie.originalTitle << "\n\n";
+ }
+ if (movie.tagline.size() > 0) {
+ info << tr("Tagline") << ": " << movie.tagline << "\n\n";
+ }
+ if (movie.overview.size() > 0) {
+ info << tr("Overview") << ": " << movie.overview << "\n\n";
+ }
+ std::string strAdult = (movie.adult)?(tr("yes")):(tr("no"));
+ info << tr("Adult") << ": " << strAdult << "\n\n";
+ if (movie.collectionName.size() > 0) {
+ info << tr("Collection") << ": " << movie.collectionName << "\n\n";
+ }
+ if (movie.budget > 0) {
+ info << tr("Budget") << ": " << movie.budget << "$\n\n";
+ }
+ if (movie.revenue > 0) {
+ info << tr("Revenue") << ": " << movie.revenue << "$\n\n";
+ }
+ if (movie.genres.size() > 0) {
+ info << tr("Genre") << ": " << movie.genres << "\n\n";
+ }
+ if (movie.homepage.size() > 0) {
+ info << tr("Homepage") << ": " << movie.homepage << "\n\n";
+ }
+ if (movie.releaseDate.size() > 0) {
+ info << tr("Release Date") << ": " << movie.releaseDate << "\n\n";
+ }
+ if (movie.runtime > 0) {
+ info << tr("Runtime") << ": " << movie.runtime << " " << tr("minutes") << "\n\n";
+ }
+ if (movie.popularity > 0) {
+ info << tr("TheMovieDB Popularity") << ": " << movie.popularity << "\n\n";
+ }
+ if (movie.voteAverage > 0) {
+ info << tr("TheMovieDB Vote Average") << ": " << movie.voteAverage << "\n\n";
+ }
+ movieDBInfo = info.str();
+}
+
+void cMovieView::DrawImages(void) {
+ int totalHeight = border;
+ //Fanart Height
+ int fanartWidth = width - 2 * border;
+ int fanartHeight = 0;
+ if (movie.fanart.width > 0 && movie.fanart.height > 0 && movie.fanart.path.size() > 0) {
+ fanartHeight = movie.fanart.height * ((double)fanartWidth / (double)movie.fanart.width);
+ if (fanartHeight > contentHeight - 2 * border) {
+ int fanartHeightOrig = fanartHeight;
+ fanartHeight = contentHeight - 2 * border;
+ fanartWidth = fanartWidth * ((double)fanartHeight / (double)fanartHeightOrig);
+ }
+ totalHeight += fanartHeight + border;
+ }
+ //Collection Fanart Height
+ int collectionFanartWidth = width - 2 * border;
+ int collectionFanartHeight = 0;
+ if (movie.collectionFanart.width > 0 && movie.collectionFanart.height > 0 && movie.collectionFanart.path.size() > 0) {
+ collectionFanartHeight = movie.collectionFanart.height * ((double)collectionFanartWidth / (double)movie.collectionFanart.width);
+ if (collectionFanartHeight > contentHeight - 2 * border) {
+ int fanartHeightOrig = collectionFanartHeight;
+ collectionFanartHeight = contentHeight - 2 * border;
+ collectionFanartWidth = collectionFanartWidth * ((double)collectionFanartHeight / (double)fanartHeightOrig);
+ }
+ totalHeight += collectionFanartHeight + border;
+ }
+ //Poster Height
+ if (movie.poster.width > 0 && movie.poster.height > 0 && movie.poster.path.size() > 0) {
+ totalHeight += movie.poster.height + border;
+ }
+ //Collection Popster Height
+ if (movie.collectionPoster.width > 0 && movie.collectionPoster.height > 0 && movie.collectionPoster.path.size() > 0) {
+ totalHeight += movie.collectionPoster.height + border;
+ }
+
+ CreateContent(totalHeight);
+
+ cImageLoader imgLoader;
+ int yPic = border;
+ if (movie.fanart.width > 0 && movie.fanart.height > 0 && movie.fanart.path.size() > 0) {
+ if (imgLoader.LoadPoster(movie.fanart.path.c_str(), fanartWidth, fanartHeight) && Running()) {
+ pixmapContent->DrawImage(cPoint((width - fanartWidth)/2, yPic), imgLoader.GetImage());
+ yPic += fanartHeight + border;
+ osdManager.flush();
+ }
+ }
+ if (movie.collectionFanart.width > 0 && movie.collectionFanart.height > 0 && movie.collectionFanart.path.size() > 0) {
+ if (imgLoader.LoadPoster(movie.collectionFanart.path.c_str(), collectionFanartWidth, collectionFanartHeight) && Running()) {
+ pixmapContent->DrawImage(cPoint((width - collectionFanartWidth)/2, yPic), imgLoader.GetImage());
+ yPic += collectionFanartHeight + border;
+ osdManager.flush();
+ }
+ }
+ if (movie.poster.width > 0 && movie.poster.height > 0 && movie.poster.path.size() > 0) {
+ if (imgLoader.LoadPoster(movie.poster.path.c_str(), movie.poster.width, movie.poster.height) && Running()) {
+ pixmapContent->DrawImage(cPoint((width - movie.poster.width) / 2, yPic), imgLoader.GetImage());
+ yPic += movie.poster.height + border;
+ osdManager.flush();
+ }
+ }
+ if (movie.collectionPoster.width > 0 && movie.collectionPoster.height > 0 && movie.collectionPoster.path.size() > 0) {
+ if (imgLoader.LoadPoster(movie.collectionPoster.path.c_str(), movie.collectionPoster.width, movie.collectionPoster.height) && Running()) {
+ pixmapContent->DrawImage(cPoint((width - movie.collectionPoster.width) / 2, yPic), imgLoader.GetImage());
+ yPic += movie.collectionPoster.height + border;
+ osdManager.flush();
+ }
+ }
+}
+
+void cMovieView::KeyLeft(void) {
+ if (Running())
+ return;
+ ClearScrollbarImage();
+ activeView--;
+ if (activeView < 0)
+ activeView = mvtCount - 1;
+}
+
+void cMovieView::KeyRight(void) {
+ if (Running())
+ return;
+ ClearScrollbarImage();
+ activeView = (activeView + 1) % mvtCount;
+}
+
+void cMovieView::Action(void) {
+ ClearContent();
+ if (!headerDrawn) {
+ DrawHeader();
+ osdManager.flush();
+ headerDrawn = true;
+ }
+ if (tabs.size() == 0) {
+ SetTabs();
+ }
+ DrawTabs();
+ bool posterAvailable = (movie.poster.path.size() > 0 && movie.poster.width > 0 && movie.poster.height > 0) ? true : false;
+ switch (activeView) {
+ case mvtInfo:
+ if (posterAvailable)
+ DrawFloatingContent(&infoText, &movie.poster);
+ else
+ DrawContent(&infoText);
+ break;
+ case mvtAddInfo:
+ if (posterAvailable)
+ DrawFloatingContent(&addInfoText, &movie.poster);
+ else
+ DrawContent(&addInfoText);
+ break;
+ case mvtCast:
+ DrawActors(&movie.actors);
+ break;
+ case mvtOnlineInfo:
+ CreateMovieDBInfo();
+ if (posterAvailable)
+ DrawFloatingContent(&movieDBInfo, &movie.poster);
+ else
+ DrawContent(&movieDBInfo);
+ break;
+ case mvtImages:
+ DrawImages();
+ break;
+ }
+ DrawScrollbar();
+ osdManager.flush();
+}
\ No newline at end of file
diff --git a/view.h b/view.h
new file mode 100644
index 0000000..5581390
--- /dev/null
+++ b/view.h
@@ -0,0 +1,149 @@
+#ifndef __TVGUIDE_VIEW_H
+#define __TVGUIDE_VIEW_H
+
+#include <vector>
+#include <string>
+#include <sstream>
+#include <vdr/skins.h>
+#include "services/scraper2vdr.h"
+#include "services/epgsearch.h"
+#include "services/remotetimers.h"
+#include "config.h"
+#include "imagecache.h"
+#include "imageloader.h"
+#include "tools.h"
+
+enum eEPGViewTabs {
+ evtInfo = 0,
+ evtAddInfo,
+ evtImages,
+ evtCount
+};
+
+enum eMediaViewTabs {
+ mvtInfo = 0,
+ mvtAddInfo,
+ mvtCast,
+ mvtOnlineInfo,
+ mvtImages,
+ mvtCount
+};
+
+class cView : public cThread {
+protected:
+ const cEvent *event;
+ cPixmap *pixmapBackground;
+ cStyledPixmap *pixmapHeader;
+ cPixmap *pixmapHeaderLogo;
+ cPixmap *pixmapContent;
+ cPixmap *pixmapScrollbar;
+ cPixmap *pixmapScrollbarBack;
+ cPixmap *pixmapTabs;
+ cFont *font, *fontSmall, *fontHeader, *fontHeaderLarge;
+ cImage *imgScrollBar;
+ int activeView;
+ bool scrollable;
+ bool tabbed;
+ int x, y;
+ int width, height;
+ int border;
+ int headerWidth, headerHeight;
+ int contentHeight;
+ int tabHeight;
+ int scrollbarWidth;
+ std::vector<std::string> tabs;
+ std::string title;
+ std::string subTitle;
+ std::string dateTime;
+ std::string infoText;
+ std::string addInfoText;
+ const cChannel *channel;
+ int eventID;
+ bool headerDrawn;
+ void DrawHeader(void);
+ void ClearContent(void);
+ void CreateContent(int fullHeight);
+ void DrawContent(std::string *text);
+ void DrawFloatingContent(std::string *infoText, cTvMedia *img, cTvMedia *img2 = NULL);
+ void CreateFloatingTextWrapper(cTextWrapper *twNarrow, cTextWrapper *twFull, std::string *text, int widthImg, int heightImg);
+ void DrawActors(std::vector<cActor> *actors);
+ void ClearScrollbar(void);
+ void ClearScrollbarImage(void);
+ cImage *CreateScrollbarImage(int width, int height, tColor clrBgr, tColor clrBlend);
+ virtual void SetTabs(void) {};
+ void DrawTabs(void);
+public:
+ cView(void);
+ virtual ~cView(void);
+ void SetTitle(const char *t) { title = t ? t : ""; };
+ void SetSubTitle(const char *s) { subTitle = s ? s : ""; };
+ void SetDateTime(const char *dt) { dateTime = dt; };
+ void SetInfoText(const char *i) { infoText = i ? i : ""; };
+ void SetAdditionalInfoText(std::string addInfo) { addInfoText = addInfo; };
+ void SetChannel(const cChannel *c) { channel = c; };
+ void SetEventID(int id) { eventID = id; };
+ void SetEvent(const cEvent *event) { this->event = event; };
+ virtual void LoadMedia(void) {};
+ void SetGeometry(void);
+ void SetFonts(void);
+ virtual bool KeyUp(void);
+ virtual bool KeyDown(void);
+ virtual void KeyLeft(void) {};
+ virtual void KeyRight(void) {};
+ void DrawScrollbar(void);
+ virtual void Action(void) {};
+};
+
+class cEPGView : public cView {
+protected:
+ std::vector<std::string> epgPics;
+ int numEPGPics;
+ int numTabs;
+ void SetTabs(void);
+ void CheckEPGImages(void);
+ void DrawImages(void);
+public:
+ cEPGView(void);
+ virtual ~cEPGView(void);
+ void KeyLeft(void);
+ void KeyRight(void);
+ void Action(void);
+};
+
+class cSeriesView : public cView {
+protected:
+ int seriesId;
+ int episodeId;
+ cSeries series;
+ std::string tvdbInfo;
+ void SetTabs(void);
+ void CreateTVDBInfo(void);
+ void DrawImages(void);
+ int GetRandomPoster(void);
+public:
+ cSeriesView(int seriesId, int episodeId);
+ virtual ~cSeriesView(void);
+ void LoadMedia(void);
+ void KeyLeft(void);
+ void KeyRight(void);
+ void Action(void);
+};
+
+class cMovieView : public cView {
+protected:
+ int movieId;
+ cMovie movie;
+ std::string movieDBInfo;
+ void SetTabs(void);
+ void CreateMovieDBInfo(void);
+ void DrawImages(void);
+public:
+ cMovieView(int movieId);
+ virtual ~cMovieView(void);
+ void LoadMedia(void);
+ void KeyLeft(void);
+ void KeyRight(void);
+ void Action(void);
+};
+
+#endif //__TVGUIDE_VIEW_H
\ No newline at end of file
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-vdr-dvb/vdr-plugin-tvguide.git
More information about the pkg-vdr-dvb-changes
mailing list